summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-04 11:33:00 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-04 15:28:21 +0100
commitaf5333e0a02b2295304d4e029b15ee15a4fe2b3a (patch)
treec5c43680d374f58b487eeeaf18fb7ec6b84ba074
parentBUS_SPACE(9): Use simple memory model for ARM (diff)
downloadrtems-libbsd-af5333e0a02b2295304d4e029b15ee15a4fe2b3a.tar.bz2
Update to FreeBSD 8.4
-rw-r--r--Makefile5
m---------freebsd-org0
-rwxr-xr-xfreebsd-to-rtems.py41
-rw-r--r--freebsd/include/rpc/xdr.h20
-rw-r--r--freebsd/lib/libc/include/libc_private.h16
-rw-r--r--freebsd/lib/libc/net/getaddrinfo.c5
-rw-r--r--freebsd/lib/libc/net/ip6opt.c2
-rw-r--r--freebsd/lib/libc/net/name6.c12
-rw-r--r--freebsd/lib/libipsec/pfkey.c14
-rw-r--r--freebsd/lib/libkvm/kvm.h1
-rw-r--r--freebsd/lib/libmemstat/memstat_uma.c3
-rw-r--r--freebsd/lib/libutil/humanize_number.c89
-rw-r--r--freebsd/lib/libutil/libutil.h44
-rw-r--r--freebsd/sbin/dhclient/clparse.c2
-rw-r--r--freebsd/sbin/dhclient/dhclient.c50
-rw-r--r--freebsd/sbin/dhclient/dhcp.h1
-rw-r--r--freebsd/sbin/dhclient/dhcpd.h6
-rw-r--r--freebsd/sbin/dhclient/errwarn.c2
-rw-r--r--freebsd/sbin/dhclient/options.c174
-rw-r--r--freebsd/sbin/dhclient/tables.c5
-rw-r--r--freebsd/sbin/ifconfig/ifcarp.c24
-rw-r--r--freebsd/sbin/ifconfig/ifconfig.c4
-rw-r--r--freebsd/sbin/ifconfig/iflagg.c53
-rw-r--r--freebsd/sbin/ifconfig/ifmedia.c16
-rw-r--r--freebsd/sbin/ifconfig/ifvlan.c2
-rw-r--r--freebsd/sbin/route/route.c455
-rw-r--r--freebsd/sys/arm/arm/legacy.c34
-rw-r--r--freebsd/sys/arm/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/arm/pci/pci_bus.c30
-rw-r--r--freebsd/sys/avr/avr/legacy.c34
-rw-r--r--freebsd/sys/avr/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/avr/pci/pci_bus.c30
-rw-r--r--freebsd/sys/bfin/bfin/legacy.c34
-rw-r--r--freebsd/sys/bfin/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/bfin/pci/pci_bus.c30
-rw-r--r--freebsd/sys/cam/ata/ata_all.h2
-rw-r--r--freebsd/sys/cam/cam.h1
-rw-r--r--freebsd/sys/cam/cam_ccb.h33
-rw-r--r--freebsd/sys/cam/cam_debug.h60
-rw-r--r--freebsd/sys/cam/cam_periph.h2
-rw-r--r--freebsd/sys/cam/cam_sim.h4
-rw-r--r--freebsd/sys/cam/cam_xpt.h27
-rw-r--r--freebsd/sys/cam/cam_xpt_sim.h2
-rw-r--r--freebsd/sys/cam/scsi/scsi_all.c177
-rw-r--r--freebsd/sys/cam/scsi/scsi_all.h25
-rw-r--r--freebsd/sys/contrib/pf/net/pf.c29
-rw-r--r--freebsd/sys/contrib/pf/net/pf_ioctl.c4
-rw-r--r--freebsd/sys/crypto/sha2/sha2.c16
-rw-r--r--freebsd/sys/dev/bce/if_bce.c2210
-rw-r--r--freebsd/sys/dev/bce/if_bcefw.h21970
-rw-r--r--freebsd/sys/dev/bce/if_bcereg.h388
-rw-r--r--freebsd/sys/dev/bfe/if_bfe.c15
-rw-r--r--freebsd/sys/dev/bge/if_bge.c1576
-rw-r--r--freebsd/sys/dev/bge/if_bgereg.h280
-rw-r--r--freebsd/sys/dev/dc/dcphy.c26
-rw-r--r--freebsd/sys/dev/dc/if_dc.c1695
-rw-r--r--freebsd/sys/dev/dc/if_dcreg.h1325
-rw-r--r--freebsd/sys/dev/dc/pnphy.c33
-rw-r--r--freebsd/sys/dev/e1000/e1000_80003es2lan.c241
-rw-r--r--freebsd/sys/dev/e1000/e1000_80003es2lan.h67
-rw-r--r--freebsd/sys/dev/e1000/e1000_82540.c109
-rw-r--r--freebsd/sys/dev/e1000/e1000_82541.c6
-rw-r--r--freebsd/sys/dev/e1000/e1000_82542.c5
-rw-r--r--freebsd/sys/dev/e1000/e1000_82543.c11
-rw-r--r--freebsd/sys/dev/e1000/e1000_82571.c633
-rw-r--r--freebsd/sys/dev/e1000/e1000_82575.c1725
-rw-r--r--freebsd/sys/dev/e1000/e1000_82575.h599
-rw-r--r--freebsd/sys/dev/e1000/e1000_api.c110
-rw-r--r--freebsd/sys/dev/e1000/e1000_api.h161
-rw-r--r--freebsd/sys/dev/e1000/e1000_defines.h2590
-rw-r--r--freebsd/sys/dev/e1000/e1000_hw.h426
-rw-r--r--freebsd/sys/dev/e1000/e1000_i210.h92
-rw-r--r--freebsd/sys/dev/e1000/e1000_ich8lan.c2504
-rw-r--r--freebsd/sys/dev/e1000/e1000_ich8lan.h369
-rw-r--r--freebsd/sys/dev/e1000/e1000_mac.c1006
-rw-r--r--freebsd/sys/dev/e1000/e1000_mac.h18
-rw-r--r--freebsd/sys/dev/e1000/e1000_manage.c384
-rw-r--r--freebsd/sys/dev/e1000/e1000_manage.h62
-rw-r--r--freebsd/sys/dev/e1000/e1000_mbx.c8
-rw-r--r--freebsd/sys/dev/e1000/e1000_nvm.c398
-rw-r--r--freebsd/sys/dev/e1000/e1000_nvm.h32
-rw-r--r--freebsd/sys/dev/e1000/e1000_osdep.c6
-rw-r--r--freebsd/sys/dev/e1000/e1000_osdep.h14
-rw-r--r--freebsd/sys/dev/e1000/e1000_phy.c2137
-rw-r--r--freebsd/sys/dev/e1000/e1000_phy.h290
-rw-r--r--freebsd/sys/dev/e1000/e1000_regs.h1092
-rw-r--r--freebsd/sys/dev/e1000/e1000_vf.c64
-rw-r--r--freebsd/sys/dev/e1000/e1000_vf.h15
-rw-r--r--freebsd/sys/dev/e1000/if_em.c1054
-rw-r--r--freebsd/sys/dev/e1000/if_em.h27
-rw-r--r--freebsd/sys/dev/e1000/if_igb.c1466
-rw-r--r--freebsd/sys/dev/e1000/if_igb.h48
-rw-r--r--freebsd/sys/dev/e1000/if_lem.c362
-rw-r--r--freebsd/sys/dev/e1000/if_lem.h6
-rw-r--r--freebsd/sys/dev/fxp/if_fxp.c180
-rw-r--r--freebsd/sys/dev/fxp/if_fxpreg.h18
-rw-r--r--freebsd/sys/dev/fxp/if_fxpvar.h2
-rw-r--r--freebsd/sys/dev/led/led.c160
-rw-r--r--freebsd/sys/dev/led/led.h2
-rw-r--r--freebsd/sys/dev/mii/brgphy.c93
-rw-r--r--freebsd/sys/dev/mii/brgphyreg.h2
-rw-r--r--freebsd/sys/dev/mii/icsphy.c7
-rw-r--r--freebsd/sys/dev/mii/mii.c174
-rw-r--r--freebsd/sys/dev/mii/mii.h6
-rw-r--r--freebsd/sys/dev/mii/mii_bitbang.h54
-rw-r--r--freebsd/sys/dev/mii/mii_physubr.c29
-rw-r--r--freebsd/sys/dev/mii/miivar.h53
-rw-r--r--freebsd/sys/dev/pci/pci.c536
-rw-r--r--freebsd/sys/dev/pci/pci_pci.c659
-rw-r--r--freebsd/sys/dev/pci/pci_private.h7
-rw-r--r--freebsd/sys/dev/pci/pci_user.c53
-rw-r--r--freebsd/sys/dev/pci/pcib_private.h31
-rw-r--r--freebsd/sys/dev/pci/pcireg.h331
-rw-r--r--freebsd/sys/dev/pci/pcivar.h28
-rw-r--r--freebsd/sys/dev/re/if_re.c1181
-rw-r--r--freebsd/sys/dev/smc/if_smc.c150
-rw-r--r--freebsd/sys/dev/usb/controller/ehci.c375
-rw-r--r--freebsd/sys/dev/usb/controller/ehci.h12
-rw-r--r--freebsd/sys/dev/usb/controller/ohci.c117
-rw-r--r--freebsd/sys/dev/usb/controller/ohci.h11
-rw-r--r--freebsd/sys/dev/usb/controller/ohcireg.h7
-rw-r--r--freebsd/sys/dev/usb/controller/usb_controller.c331
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.c84
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.h12
-rw-r--r--freebsd/sys/dev/usb/storage/umass.c91
-rw-r--r--freebsd/sys/dev/usb/usb.h50
-rw-r--r--freebsd/sys/dev/usb/usb_bus.h18
-rw-r--r--freebsd/sys/dev/usb/usb_busdma.c19
-rw-r--r--freebsd/sys/dev/usb/usb_cdc.h7
-rw-r--r--freebsd/sys/dev/usb/usb_controller.h64
-rw-r--r--freebsd/sys/dev/usb/usb_core.c1
-rw-r--r--freebsd/sys/dev/usb/usb_debug.c137
-rw-r--r--freebsd/sys/dev/usb/usb_debug.h24
-rw-r--r--freebsd/sys/dev/usb/usb_dev.c88
-rw-r--r--freebsd/sys/dev/usb/usb_dev.h1
-rw-r--r--freebsd/sys/dev/usb/usb_device.c396
-rw-r--r--freebsd/sys/dev/usb/usb_device.h86
-rw-r--r--freebsd/sys/dev/usb/usb_dynamic.c1
-rw-r--r--freebsd/sys/dev/usb/usb_error.c1
-rw-r--r--freebsd/sys/dev/usb/usb_freebsd.h5
-rw-r--r--freebsd/sys/dev/usb/usb_generic.c76
-rw-r--r--freebsd/sys/dev/usb/usb_handle_request.c36
-rw-r--r--freebsd/sys/dev/usb/usb_hid.c51
-rw-r--r--freebsd/sys/dev/usb/usb_hub.c363
-rw-r--r--freebsd/sys/dev/usb/usb_hub.h14
-rw-r--r--freebsd/sys/dev/usb/usb_ioctl.h44
-rw-r--r--freebsd/sys/dev/usb/usb_lookup.c115
-rw-r--r--freebsd/sys/dev/usb/usb_mbuf.c1
-rw-r--r--freebsd/sys/dev/usb/usb_msctest.c186
-rw-r--r--freebsd/sys/dev/usb/usb_msctest.h2
-rw-r--r--freebsd/sys/dev/usb/usb_parse.c1
-rw-r--r--freebsd/sys/dev/usb/usb_pf.h120
-rw-r--r--freebsd/sys/dev/usb/usb_process.c24
-rw-r--r--freebsd/sys/dev/usb/usb_process.h6
-rw-r--r--freebsd/sys/dev/usb/usb_request.c365
-rw-r--r--freebsd/sys/dev/usb/usb_request.h6
-rw-r--r--freebsd/sys/dev/usb/usb_transfer.c260
-rw-r--r--freebsd/sys/dev/usb/usb_util.c23
-rw-r--r--freebsd/sys/dev/usb/usbdi.h54
-rw-r--r--freebsd/sys/dev/usb/usbhid.h6
-rw-r--r--freebsd/sys/h8300/h8300/legacy.c34
-rw-r--r--freebsd/sys/h8300/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/h8300/pci/pci_bus.c30
-rw-r--r--freebsd/sys/i386/i386/legacy.c34
-rw-r--r--freebsd/sys/i386/include/machine/cpufunc.h7
-rw-r--r--freebsd/sys/i386/include/machine/intr_machdep.h6
-rw-r--r--freebsd/sys/i386/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/i386/include/machine/specialreg.h33
-rw-r--r--freebsd/sys/i386/pci/pci_bus.c30
-rw-r--r--freebsd/sys/kern/init_main.c4
-rw-r--r--freebsd/sys/kern/kern_event.c18
-rw-r--r--freebsd/sys/kern/kern_hhook.c456
-rw-r--r--freebsd/sys/kern/kern_intr.c32
-rw-r--r--freebsd/sys/kern/kern_khelp.c475
-rw-r--r--freebsd/sys/kern/kern_linker.c110
-rw-r--r--freebsd/sys/kern/kern_mib.c3
-rw-r--r--freebsd/sys/kern/kern_osd.c405
-rw-r--r--freebsd/sys/kern/kern_subr.c144
-rw-r--r--freebsd/sys/kern/kern_sysctl.c294
-rw-r--r--freebsd/sys/kern/kern_timeout.c524
-rw-r--r--freebsd/sys/kern/subr_bus.c251
-rw-r--r--freebsd/sys/kern/subr_kobj.c75
-rw-r--r--freebsd/sys/kern/subr_rman.c163
-rw-r--r--freebsd/sys/kern/subr_sbuf.c256
-rw-r--r--freebsd/sys/kern/subr_taskqueue.c10
-rw-r--r--freebsd/sys/kern/subr_unit.c187
-rw-r--r--freebsd/sys/kern/sys_generic.c89
-rw-r--r--freebsd/sys/kern/sys_socket.c13
-rw-r--r--freebsd/sys/kern/uipc_domain.c2
-rw-r--r--freebsd/sys/kern/uipc_mbuf.c7
-rw-r--r--freebsd/sys/kern/uipc_sockbuf.c3
-rw-r--r--freebsd/sys/kern/uipc_socket.c154
-rw-r--r--freebsd/sys/kern/uipc_syscalls.c54
-rw-r--r--freebsd/sys/lm32/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/lm32/lm32/legacy.c34
-rw-r--r--freebsd/sys/lm32/pci/pci_bus.c30
-rw-r--r--freebsd/sys/m32c/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/m32c/m32c/legacy.c34
-rw-r--r--freebsd/sys/m32c/pci/pci_bus.c30
-rw-r--r--freebsd/sys/m32r/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/m32r/m32r/legacy.c34
-rw-r--r--freebsd/sys/m32r/pci/pci_bus.c30
-rw-r--r--freebsd/sys/m68k/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/m68k/m68k/legacy.c34
-rw-r--r--freebsd/sys/m68k/pci/pci_bus.c30
-rw-r--r--freebsd/sys/mips/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/mips/mips/legacy.c34
-rw-r--r--freebsd/sys/mips/pci/pci_bus.c30
-rw-r--r--freebsd/sys/net/bpf.c633
-rw-r--r--freebsd/sys/net/bpf.h9
-rw-r--r--freebsd/sys/net/bpf_buffer.c51
-rw-r--r--freebsd/sys/net/bpf_buffer.h3
-rw-r--r--freebsd/sys/net/bpf_zerocopy.h2
-rw-r--r--freebsd/sys/net/bpfdesc.h23
-rw-r--r--freebsd/sys/net/bridgestp.c174
-rw-r--r--freebsd/sys/net/bridgestp.h8
-rw-r--r--freebsd/sys/net/ieee8023ad_lacp.c4
-rw-r--r--freebsd/sys/net/if.c256
-rw-r--r--freebsd/sys/net/if.h61
-rw-r--r--freebsd/sys/net/if_arcsubr.c1
-rw-r--r--freebsd/sys/net/if_atmsubr.c1
-rw-r--r--freebsd/sys/net/if_bridge.c113
-rw-r--r--freebsd/sys/net/if_epair.c92
-rw-r--r--freebsd/sys/net/if_ethersubr.c7
-rw-r--r--freebsd/sys/net/if_faith.c2
-rw-r--r--freebsd/sys/net/if_fddisubr.c1
-rw-r--r--freebsd/sys/net/if_fwsubr.c1
-rw-r--r--freebsd/sys/net/if_gif.c12
-rw-r--r--freebsd/sys/net/if_gre.c102
-rw-r--r--freebsd/sys/net/if_gre.h2
-rw-r--r--freebsd/sys/net/if_iso88025subr.c1
-rw-r--r--freebsd/sys/net/if_lagg.c142
-rw-r--r--freebsd/sys/net/if_lagg.h21
-rw-r--r--freebsd/sys/net/if_llatbl.c29
-rw-r--r--freebsd/sys/net/if_llatbl.h22
-rw-r--r--freebsd/sys/net/if_media.c2
-rw-r--r--freebsd/sys/net/if_media.h106
-rw-r--r--freebsd/sys/net/if_spppfr.c2
-rw-r--r--freebsd/sys/net/if_spppsubr.c1
-rw-r--r--freebsd/sys/net/if_stf.c1
-rw-r--r--freebsd/sys/net/if_tap.c14
-rw-r--r--freebsd/sys/net/if_tun.c37
-rw-r--r--freebsd/sys/net/if_var.h19
-rw-r--r--freebsd/sys/net/if_vlan.c201
-rw-r--r--freebsd/sys/net/netisr.c402
-rw-r--r--freebsd/sys/net/netisr.h88
-rw-r--r--freebsd/sys/net/netisr_internal.h127
-rw-r--r--freebsd/sys/net/radix_mpath.c5
-rw-r--r--freebsd/sys/net/raw_cb.h5
-rw-r--r--freebsd/sys/net/raw_usrreq.c10
-rw-r--r--freebsd/sys/net/route.c252
-rw-r--r--freebsd/sys/net/route.h45
-rw-r--r--freebsd/sys/net/rtsock.c342
-rw-r--r--freebsd/sys/net/vnet.h56
-rw-r--r--freebsd/sys/net80211/ieee80211.h45
-rw-r--r--freebsd/sys/net80211/ieee80211_ageq.c2
-rw-r--r--freebsd/sys/net80211/ieee80211_amrr.c4
-rw-r--r--freebsd/sys/net80211/ieee80211_freebsd.c14
-rw-r--r--freebsd/sys/net80211/ieee80211_mesh.c2
-rw-r--r--freebsd/sys/net80211/ieee80211_output.c2
-rw-r--r--freebsd/sys/netatalk/aarp.c6
-rw-r--r--freebsd/sys/netatalk/at_control.c8
-rw-r--r--freebsd/sys/netinet/cc.h167
-rw-r--r--freebsd/sys/netinet/cc/cc.c332
-rw-r--r--freebsd/sys/netinet/cc/cc_module.h70
-rw-r--r--freebsd/sys/netinet/cc/cc_newreno.c239
-rw-r--r--freebsd/sys/netinet/icmp6.h21
-rw-r--r--freebsd/sys/netinet/icmp_var.h3
-rw-r--r--freebsd/sys/netinet/if_atm.c6
-rw-r--r--freebsd/sys/netinet/if_ether.c100
-rw-r--r--freebsd/sys/netinet/igmp.c59
-rw-r--r--freebsd/sys/netinet/in.c189
-rw-r--r--freebsd/sys/netinet/in.h1
-rw-r--r--freebsd/sys/netinet/in_mcast.c16
-rw-r--r--freebsd/sys/netinet/in_pcb.c227
-rw-r--r--freebsd/sys/netinet/in_pcb.h5
-rw-r--r--freebsd/sys/netinet/in_proto.c16
-rw-r--r--freebsd/sys/netinet/in_rmx.c24
-rw-r--r--freebsd/sys/netinet/in_var.h8
-rw-r--r--freebsd/sys/netinet/ip.h25
-rw-r--r--freebsd/sys/netinet/ip_carp.c85
-rw-r--r--freebsd/sys/netinet/ip_divert.c4
-rw-r--r--freebsd/sys/netinet/ip_fw.h56
-rw-r--r--freebsd/sys/netinet/ip_icmp.c60
-rw-r--r--freebsd/sys/netinet/ip_input.c20
-rw-r--r--freebsd/sys/netinet/ip_ipsec.c2
-rw-r--r--freebsd/sys/netinet/ip_mroute.c4
-rw-r--r--freebsd/sys/netinet/ip_output.c12
-rw-r--r--freebsd/sys/netinet/ip_var.h3
-rw-r--r--freebsd/sys/netinet/ipfw/ip_dn_glue.c6
-rw-r--r--freebsd/sys/netinet/ipfw/ip_dn_io.c101
-rw-r--r--freebsd/sys/netinet/ipfw/ip_dn_private.h4
-rw-r--r--freebsd/sys/netinet/ipfw/ip_dummynet.c79
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw2.c310
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_log.c19
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_nat.c209
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_pfil.c14
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_private.h25
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_sockopt.c129
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_table.c595
-rw-r--r--freebsd/sys/netinet/libalias/alias.h6
-rw-r--r--freebsd/sys/netinet/libalias/alias_db.c33
-rw-r--r--freebsd/sys/netinet/libalias/alias_ftp.c124
-rw-r--r--freebsd/sys/netinet/libalias/alias_local.h7
-rw-r--r--freebsd/sys/netinet/libalias/alias_mod.h3
-rw-r--r--freebsd/sys/netinet/libalias/alias_proxy.c2
-rw-r--r--freebsd/sys/netinet/libalias/alias_sctp.c2
-rw-r--r--freebsd/sys/netinet/raw_ip.c14
-rw-r--r--freebsd/sys/netinet/sctp.h167
-rw-r--r--freebsd/sys/netinet/sctp_asconf.c1198
-rw-r--r--freebsd/sys/netinet/sctp_asconf.h12
-rw-r--r--freebsd/sys/netinet/sctp_auth.c51
-rw-r--r--freebsd/sys/netinet/sctp_auth.h18
-rw-r--r--freebsd/sys/netinet/sctp_bsd_addr.c146
-rw-r--r--freebsd/sys/netinet/sctp_bsd_addr.h13
-rw-r--r--freebsd/sys/netinet/sctp_cc_functions.c1829
-rw-r--r--freebsd/sys/netinet/sctp_constants.h171
-rw-r--r--freebsd/sys/netinet/sctp_crc32.c9
-rw-r--r--freebsd/sys/netinet/sctp_crc32.h12
-rw-r--r--freebsd/sys/netinet/sctp_dtrace_declare.h80
-rw-r--r--freebsd/sys/netinet/sctp_dtrace_define.h233
-rw-r--r--freebsd/sys/netinet/sctp_header.h53
-rw-r--r--freebsd/sys/netinet/sctp_indata.c1645
-rw-r--r--freebsd/sys/netinet/sctp_indata.h36
-rw-r--r--freebsd/sys/netinet/sctp_input.c2241
-rw-r--r--freebsd/sys/netinet/sctp_input.h26
-rw-r--r--freebsd/sys/netinet/sctp_lock_bsd.h55
-rw-r--r--freebsd/sys/netinet/sctp_os.h12
-rw-r--r--freebsd/sys/netinet/sctp_os_bsd.h48
-rw-r--r--freebsd/sys/netinet/sctp_output.c5195
-rw-r--r--freebsd/sys/netinet/sctp_output.h96
-rw-r--r--freebsd/sys/netinet/sctp_pcb.c2229
-rw-r--r--freebsd/sys/netinet/sctp_pcb.h52
-rw-r--r--freebsd/sys/netinet/sctp_peeloff.c127
-rw-r--r--freebsd/sys/netinet/sctp_peeloff.h23
-rw-r--r--freebsd/sys/netinet/sctp_structs.h279
-rw-r--r--freebsd/sys/netinet/sctp_sysctl.c364
-rw-r--r--freebsd/sys/netinet/sctp_sysctl.h184
-rw-r--r--freebsd/sys/netinet/sctp_timer.c584
-rw-r--r--freebsd/sys/netinet/sctp_timer.h17
-rw-r--r--freebsd/sys/netinet/sctp_uio.h378
-rw-r--r--freebsd/sys/netinet/sctp_usrreq.c3405
-rw-r--r--freebsd/sys/netinet/sctp_var.h59
-rw-r--r--freebsd/sys/netinet/sctputil.c2214
-rw-r--r--freebsd/sys/netinet/sctputil.h70
-rw-r--r--freebsd/sys/netinet/tcp.h26
-rw-r--r--freebsd/sys/netinet/tcp_hostcache.c27
-rw-r--r--freebsd/sys/netinet/tcp_input.c701
-rw-r--r--freebsd/sys/netinet/tcp_lro.c62
-rw-r--r--freebsd/sys/netinet/tcp_lro.h63
-rw-r--r--freebsd/sys/netinet/tcp_offload.h2
-rw-r--r--freebsd/sys/netinet/tcp_output.c123
-rw-r--r--freebsd/sys/netinet/tcp_reass.c51
-rw-r--r--freebsd/sys/netinet/tcp_sack.c3
-rw-r--r--freebsd/sys/netinet/tcp_seq.h31
-rw-r--r--freebsd/sys/netinet/tcp_subr.c217
-rw-r--r--freebsd/sys/netinet/tcp_syncache.c29
-rw-r--r--freebsd/sys/netinet/tcp_timer.c110
-rw-r--r--freebsd/sys/netinet/tcp_timewait.c9
-rw-r--r--freebsd/sys/netinet/tcp_usrreq.c73
-rw-r--r--freebsd/sys/netinet/tcp_var.h77
-rw-r--r--freebsd/sys/netinet/udp.h4
-rw-r--r--freebsd/sys/netinet/udp_usrreq.c41
-rw-r--r--freebsd/sys/netinet/udp_var.h2
-rw-r--r--freebsd/sys/netinet6/frag6.c13
-rw-r--r--freebsd/sys/netinet6/icmp6.c48
-rw-r--r--freebsd/sys/netinet6/in6.c726
-rw-r--r--freebsd/sys/netinet6/in6.h2
-rw-r--r--freebsd/sys/netinet6/in6_gif.c7
-rw-r--r--freebsd/sys/netinet6/in6_ifattach.c72
-rw-r--r--freebsd/sys/netinet6/in6_mcast.c27
-rw-r--r--freebsd/sys/netinet6/in6_pcb.c5
-rw-r--r--freebsd/sys/netinet6/in6_proto.c52
-rw-r--r--freebsd/sys/netinet6/in6_rmx.c249
-rw-r--r--freebsd/sys/netinet6/in6_src.c154
-rw-r--r--freebsd/sys/netinet6/in6_var.h18
-rw-r--r--freebsd/sys/netinet6/ip6_forward.c2
-rw-r--r--freebsd/sys/netinet6/ip6_input.c100
-rw-r--r--freebsd/sys/netinet6/ip6_ipsec.c14
-rw-r--r--freebsd/sys/netinet6/ip6_mroute.c1
-rw-r--r--freebsd/sys/netinet6/ip6_output.c50
-rw-r--r--freebsd/sys/netinet6/ip6_var.h3
-rw-r--r--freebsd/sys/netinet6/mld6.c102
-rw-r--r--freebsd/sys/netinet6/nd6.c331
-rw-r--r--freebsd/sys/netinet6/nd6.h7
-rw-r--r--freebsd/sys/netinet6/nd6_nbr.c70
-rw-r--r--freebsd/sys/netinet6/nd6_rtr.c274
-rw-r--r--freebsd/sys/netinet6/raw_ip6.c14
-rw-r--r--freebsd/sys/netinet6/scope6.c53
-rw-r--r--freebsd/sys/netinet6/scope6_var.h2
-rw-r--r--freebsd/sys/netinet6/sctp6_usrreq.c559
-rw-r--r--freebsd/sys/netinet6/sctp6_var.h15
-rw-r--r--freebsd/sys/netinet6/udp6_usrreq.c58
-rw-r--r--freebsd/sys/netipsec/ipsec.h16
-rw-r--r--freebsd/sys/netipsec/ipsec_output.c3
-rw-r--r--freebsd/sys/netipsec/key.c73
-rw-r--r--freebsd/sys/netipsec/key.h3
-rw-r--r--freebsd/sys/netipsec/xform.h2
-rw-r--r--freebsd/sys/netipsec/xform_ah.c44
-rw-r--r--freebsd/sys/netipsec/xform_esp.c87
-rw-r--r--freebsd/sys/netipsec/xform_ipcomp.c43
-rw-r--r--freebsd/sys/nios2/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/nios2/nios2/legacy.c34
-rw-r--r--freebsd/sys/nios2/pci/pci_bus.c30
-rw-r--r--freebsd/sys/opencrypto/deflate.c8
-rw-r--r--freebsd/sys/opencrypto/xform.h3
-rw-r--r--freebsd/sys/pci/if_rlreg.h126
-rw-r--r--freebsd/sys/powerpc/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/powerpc/pci/pci_bus.c30
-rw-r--r--freebsd/sys/powerpc/powerpc/legacy.c34
-rw-r--r--freebsd/sys/sh/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/sh/pci/pci_bus.c30
-rw-r--r--freebsd/sys/sh/sh/legacy.c34
-rw-r--r--freebsd/sys/sparc/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/sparc/pci/pci_bus.c30
-rw-r--r--freebsd/sys/sparc/sparc/legacy.c34
-rw-r--r--freebsd/sys/sparc64/include/machine/cpufunc.h28
-rw-r--r--freebsd/sys/sparc64/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/sparc64/pci/pci_bus.c30
-rw-r--r--freebsd/sys/sparc64/sparc64/legacy.c34
-rw-r--r--freebsd/sys/sys/ata.h15
-rw-r--r--freebsd/sys/sys/buf.h6
-rw-r--r--freebsd/sys/sys/bus.h30
-rw-r--r--freebsd/sys/sys/callout.h1
-rw-r--r--freebsd/sys/sys/eventhandler.h7
-rw-r--r--freebsd/sys/sys/file.h17
-rw-r--r--freebsd/sys/sys/filedesc.h2
-rw-r--r--freebsd/sys/sys/hhook.h156
-rw-r--r--freebsd/sys/sys/kernel.h2
-rw-r--r--freebsd/sys/sys/khelp.h76
-rw-r--r--freebsd/sys/sys/kobj.h1
-rw-r--r--freebsd/sys/sys/libkern.h1
-rw-r--r--freebsd/sys/sys/limits.h2
-rw-r--r--freebsd/sys/sys/mman.h15
-rw-r--r--freebsd/sys/sys/module_khelp.h110
-rw-r--r--freebsd/sys/sys/mount.h10
-rw-r--r--freebsd/sys/sys/mutex.h3
-rw-r--r--freebsd/sys/sys/osd.h3
-rw-r--r--freebsd/sys/sys/priority.h13
-rw-r--r--freebsd/sys/sys/priv.h3
-rw-r--r--freebsd/sys/sys/proc.h72
-rw-r--r--freebsd/sys/sys/queue.h13
-rw-r--r--freebsd/sys/sys/refcount.h6
-rw-r--r--freebsd/sys/sys/rman.h3
-rw-r--r--freebsd/sys/sys/sbuf.h9
-rw-r--r--freebsd/sys/sys/sdt.h96
-rw-r--r--freebsd/sys/sys/selinfo.h1
-rw-r--r--freebsd/sys/sys/socket.h16
-rw-r--r--freebsd/sys/sys/sockio.h3
-rw-r--r--freebsd/sys/sys/sysctl.h14
-rw-r--r--freebsd/sys/sys/sysproto.h17
-rw-r--r--freebsd/sys/sys/systm.h95
-rw-r--r--freebsd/sys/sys/taskqueue.h10
-rw-r--r--freebsd/sys/sys/un.h9
-rw-r--r--freebsd/sys/sys/user.h3
-rw-r--r--freebsd/sys/v850/include/machine/legacyvar.h8
-rw-r--r--freebsd/sys/v850/pci/pci_bus.c30
-rw-r--r--freebsd/sys/v850/v850/legacy.c34
-rw-r--r--freebsd/sys/vm/uma.h6
-rw-r--r--freebsd/sys/vm/uma_core.c40
-rw-r--r--freebsd/sys/vm/uma_int.h4
-rw-r--r--freebsd/sys/vm/vm_extern.h3
-rw-r--r--freebsd/usr.bin/netstat/if.c28
-rw-r--r--freebsd/usr.bin/netstat/inet.c78
-rw-r--r--freebsd/usr.bin/netstat/main.c35
-rw-r--r--freebsd/usr.bin/netstat/netstat.h7
-rw-r--r--freebsd/usr.bin/netstat/route.c64
-rw-r--r--freebsd/usr.bin/netstat/sctp.c326
-rw-r--r--rtemsbsd/include/rtems/bsd/local/bus_if.h33
-rw-r--r--rtemsbsd/include/rtems/bsd/local/device_if.h2
-rw-r--r--rtemsbsd/include/rtems/bsd/local/miidevs.h19
-rw-r--r--rtemsbsd/include/rtems/bsd/local/pci_if.h2
-rw-r--r--rtemsbsd/include/rtems/bsd/local/pcib_if.h2
-rw-r--r--rtemsbsd/include/rtems/bsd/local/usb_if.h14
-rw-r--r--rtemsbsd/include/rtems/bsd/local/usbdevs.h919
-rw-r--r--rtemsbsd/include/rtems/bsd/local/usbdevs_data.h4715
-rw-r--r--rtemsbsd/include/rtems/bsd/local/vnode_if.h1546
-rw-r--r--rtemsbsd/include/rtems/bsd/local/vnode_if_newproto.h66
-rw-r--r--rtemsbsd/include/rtems/bsd/local/vnode_if_typedef.h170
-rw-r--r--rtemsbsd/local/bus_if.c10
-rw-r--r--rtemsbsd/local/device_if.c2
-rw-r--r--rtemsbsd/local/pci_if.c2
-rw-r--r--rtemsbsd/local/pcib_if.c2
-rw-r--r--rtemsbsd/local/usb_if.c10
-rw-r--r--rtemsbsd/rtems/rtems-bsd-pci_bus.c1
-rw-r--r--rtemsbsd/rtems/rtems-bsd-pci_cfgreg.c1
486 files changed, 65561 insertions, 40296 deletions
diff --git a/Makefile b/Makefile
index e6b1e312..8da90c58 100644
--- a/Makefile
+++ b/Makefile
@@ -120,12 +120,15 @@ freebsd/lib/libipsec/policy_parse.c: freebsd/lib/libipsec/policy_parse.y
mv __libipsecyy.tab.h freebsd/lib/libipsec/y.tab.h
LIB_C_FILES += freebsd/sys/kern/init_main.c
LIB_C_FILES += freebsd/sys/kern/kern_event.c
+LIB_C_FILES += freebsd/sys/kern/kern_hhook.c
LIB_C_FILES += freebsd/sys/kern/kern_intr.c
+LIB_C_FILES += freebsd/sys/kern/kern_khelp.c
LIB_C_FILES += freebsd/sys/kern/kern_linker.c
LIB_C_FILES += freebsd/sys/kern/kern_mbuf.c
LIB_C_FILES += freebsd/sys/kern/kern_mib.c
LIB_C_FILES += freebsd/sys/kern/kern_module.c
LIB_C_FILES += freebsd/sys/kern/kern_mtxpool.c
+LIB_C_FILES += freebsd/sys/kern/kern_osd.c
LIB_C_FILES += freebsd/sys/kern/kern_subr.c
LIB_C_FILES += freebsd/sys/kern/kern_sysctl.c
LIB_C_FILES += freebsd/sys/kern/kern_time.c
@@ -200,6 +203,8 @@ LIB_C_FILES += freebsd/sys/net/netisr.c
LIB_C_FILES += freebsd/sys/netinet/accf_data.c
LIB_C_FILES += freebsd/sys/netinet/accf_dns.c
LIB_C_FILES += freebsd/sys/netinet/accf_http.c
+LIB_C_FILES += freebsd/sys/netinet/cc/cc.c
+LIB_C_FILES += freebsd/sys/netinet/cc/cc_newreno.c
LIB_C_FILES += freebsd/sys/netinet/if_atm.c
LIB_C_FILES += freebsd/sys/netinet/if_ether.c
LIB_C_FILES += freebsd/sys/netinet/igmp.c
diff --git a/freebsd-org b/freebsd-org
-Subproject acc6ddf18bd9aac26c2f719b5b0868985ac5390
+Subproject 9001b0780a86959b6c84bf1d794ce4542218865
diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py
index 53a05cea..981045fa 100755
--- a/freebsd-to-rtems.py
+++ b/freebsd-to-rtems.py
@@ -690,9 +690,11 @@ base.addHeaderFiles(
'sys/sys/filio.h',
'sys/sys/fnv_hash.h',
'sys/sys/hash.h',
+ 'sys/sys/hhook.h',
'sys/sys/interrupt.h',
'sys/sys/jail.h',
'sys/sys/kernel.h',
+ 'sys/sys/khelp.h',
'sys/sys/kobj.h',
'sys/sys/kthread.h',
'sys/sys/ktr.h',
@@ -709,6 +711,7 @@ base.addHeaderFiles(
'sys/sys/malloc.h',
'sys/sys/mbuf.h',
'sys/sys/module.h',
+ 'sys/sys/module_khelp.h',
'sys/sys/mount.h',
'sys/sys/_mutex.h',
'sys/sys/mutex.h',
@@ -778,12 +781,15 @@ base.addSourceFiles(
[
'sys/kern/init_main.c',
'sys/kern/kern_event.c',
+ 'sys/kern/kern_hhook.c',
'sys/kern/kern_intr.c',
+ 'sys/kern/kern_khelp.c',
'sys/kern/kern_linker.c',
'sys/kern/kern_mbuf.c',
'sys/kern/kern_mib.c',
'sys/kern/kern_module.c',
'sys/kern/kern_mtxpool.c',
+ 'sys/kern/kern_osd.c',
'sys/kern/kern_subr.c',
'sys/kern/kern_sysctl.c',
'sys/kern/kern_time.c',
@@ -837,6 +843,7 @@ devUsb.addHeaderFiles(
'sys/dev/usb/usb_ioctl.h',
'sys/dev/usb/usb_mbuf.h',
'sys/dev/usb/usb_msctest.h',
+ 'sys/dev/usb/usb_pf.h',
'sys/dev/usb/usb_process.h',
'sys/dev/usb/usb_request.h',
'sys/dev/usb/usb_transfer.h',
@@ -1141,6 +1148,7 @@ devNet = Module('dev_net')
devNet.addHeaderFiles(
[
'sys/dev/mii/mii.h',
+ 'sys/dev/mii/mii_bitbang.h',
'sys/dev/mii/miivar.h',
'sys/dev/mii/brgphyreg.h',
'sys/dev/mii/icsphyreg.h',
@@ -1258,25 +1266,26 @@ devNic_e1000 = Module('dev_nic_e1000')
devNic_e1000.addHeaderFiles(
[
'sys/dev/e1000/e1000_80003es2lan.h',
- 'sys/dev/e1000/e1000_82571.h',
- 'sys/dev/e1000/e1000_defines.h',
- 'sys/dev/e1000/e1000_mac.h',
- 'sys/dev/e1000/e1000_nvm.h',
- 'sys/dev/e1000/e1000_regs.h',
- 'sys/dev/e1000/if_igb.h',
'sys/dev/e1000/e1000_82541.h',
- 'sys/dev/e1000/e1000_82575.h',
- 'sys/dev/e1000/e1000_hw.h',
- 'sys/dev/e1000/e1000_manage.h',
- 'sys/dev/e1000/e1000_osdep.h',
- 'sys/dev/e1000/e1000_vf.h',
- 'sys/dev/e1000/if_lem.h',
'sys/dev/e1000/e1000_82543.h',
+ 'sys/dev/e1000/e1000_82571.h',
+ 'sys/dev/e1000/e1000_82575.h',
'sys/dev/e1000/e1000_api.h',
+ 'sys/dev/e1000/e1000_defines.h',
+ 'sys/dev/e1000/e1000_hw.h',
+ 'sys/dev/e1000/e1000_i210.h',
'sys/dev/e1000/e1000_ich8lan.h',
+ 'sys/dev/e1000/e1000_mac.h',
+ 'sys/dev/e1000/e1000_manage.h',
'sys/dev/e1000/e1000_mbx.h',
+ 'sys/dev/e1000/e1000_nvm.h',
+ 'sys/dev/e1000/e1000_osdep.h',
'sys/dev/e1000/e1000_phy.h',
+ 'sys/dev/e1000/e1000_regs.h',
+ 'sys/dev/e1000/e1000_vf.h',
'sys/dev/e1000/if_em.h',
+ 'sys/dev/e1000/if_igb.h',
+ 'sys/dev/e1000/if_lem.h',
]
)
devNic_e1000.addSourceFiles(
@@ -1405,6 +1414,7 @@ net.addHeaderFiles(
'sys/net/if_vlan_var.h',
'sys/net/iso88025.h',
'sys/net/netisr.h',
+ 'sys/net/netisr_internal.h',
'sys/net/pfil.h',
'sys/net/pfkeyv2.h',
'sys/net/ppp_defs.h',
@@ -1469,6 +1479,8 @@ net.addSourceFiles(
netinet = Module('netinet')
netinet.addHeaderFiles(
[
+ 'sys/netinet/cc.h',
+ 'sys/netinet/cc/cc_module.h',
'sys/netinet/icmp6.h',
'sys/netinet/icmp_var.h',
'sys/netinet/if_atm.h',
@@ -1503,9 +1515,10 @@ netinet.addHeaderFiles(
'sys/netinet/sctp_asconf.h',
'sys/netinet/sctp_auth.h',
'sys/netinet/sctp_bsd_addr.h',
- 'sys/netinet/sctp_cc_functions.h',
'sys/netinet/sctp_constants.h',
'sys/netinet/sctp_crc32.h',
+ 'sys/netinet/sctp_dtrace_declare.h',
+ 'sys/netinet/sctp_dtrace_define.h',
'sys/netinet/sctp.h',
'sys/netinet/sctp_header.h',
'sys/netinet/sctp_indata.h',
@@ -1548,6 +1561,8 @@ netinet.addSourceFiles(
'sys/netinet/accf_data.c',
'sys/netinet/accf_dns.c',
'sys/netinet/accf_http.c',
+ 'sys/netinet/cc/cc.c',
+ 'sys/netinet/cc/cc_newreno.c',
'sys/netinet/if_atm.c',
'sys/netinet/if_ether.c',
'sys/netinet/igmp.c',
diff --git a/freebsd/include/rpc/xdr.h b/freebsd/include/rpc/xdr.h
index a02291bc..76968afc 100644
--- a/freebsd/include/rpc/xdr.h
+++ b/freebsd/include/rpc/xdr.h
@@ -97,26 +97,26 @@ enum xdr_op {
* an operations vector for the particular implementation (e.g. see xdr_mem.c),
* and two private fields for the use of the particular implementation.
*/
-typedef struct __rpc_xdr {
+typedef struct XDR {
enum xdr_op x_op; /* operation; fast additional param */
const struct xdr_ops {
/* get a long from underlying stream */
- bool_t (*x_getlong)(struct __rpc_xdr *, long *);
+ bool_t (*x_getlong)(struct XDR *, long *);
/* put a long to " */
- bool_t (*x_putlong)(struct __rpc_xdr *, const long *);
+ bool_t (*x_putlong)(struct XDR *, const long *);
/* get some bytes from " */
- bool_t (*x_getbytes)(struct __rpc_xdr *, char *, u_int);
+ bool_t (*x_getbytes)(struct XDR *, char *, u_int);
/* put some bytes to " */
- bool_t (*x_putbytes)(struct __rpc_xdr *, const char *, u_int);
+ bool_t (*x_putbytes)(struct XDR *, const char *, u_int);
/* returns bytes off from beginning */
- u_int (*x_getpostn)(struct __rpc_xdr *);
+ u_int (*x_getpostn)(struct XDR *);
/* lets you reposition the stream */
- bool_t (*x_setpostn)(struct __rpc_xdr *, u_int);
+ bool_t (*x_setpostn)(struct XDR *, u_int);
/* buf quick ptr to buffered data */
- int32_t *(*x_inline)(struct __rpc_xdr *, u_int);
+ int32_t *(*x_inline)(struct XDR *, u_int);
/* free privates of this xdr_stream */
- void (*x_destroy)(struct __rpc_xdr *);
- bool_t (*x_control)(struct __rpc_xdr *, int, void *);
+ void (*x_destroy)(struct XDR *);
+ bool_t (*x_control)(struct XDR *, int, void *);
} *x_ops;
char * x_public; /* users' data */
void * x_private; /* pointer to private data */
diff --git a/freebsd/lib/libc/include/libc_private.h b/freebsd/lib/libc/include/libc_private.h
index c72b41ee..4e1430ca 100644
--- a/freebsd/lib/libc/include/libc_private.h
+++ b/freebsd/lib/libc/include/libc_private.h
@@ -76,6 +76,19 @@ void _rtld_error(const char *fmt, ...);
#define FLOCKFILE(fp) if (__isthreaded) _FLOCKFILE(fp)
#define FUNLOCKFILE(fp) if (__isthreaded) _funlockfile(fp)
+struct _spinlock;
+extern struct _spinlock __stdio_thread_lock;
+#define STDIO_THREAD_LOCK() \
+do { \
+ if (__isthreaded) \
+ _SPINLOCK(&__stdio_thread_lock); \
+} while (0)
+#define STDIO_THREAD_UNLOCK() \
+do { \
+ if (__isthreaded) \
+ _SPINUNLOCK(&__stdio_thread_lock); \
+} while (0)
+
/*
* Indexes into the pthread jump table.
*
@@ -226,4 +239,7 @@ extern int __sys_fcntl(int, int, ...);
/* execve() with PATH processing to implement posix_spawnp() */
int _execvpe(const char *, char * const *, char * const *);
+struct dl_phdr_info;
+int __elf_phdr_match_addr(struct dl_phdr_info *, void *);
+
#endif /* _LIBC_PRIVATE_H_ */
diff --git a/freebsd/lib/libc/net/getaddrinfo.c b/freebsd/lib/libc/net/getaddrinfo.c
index 760652d6..5fe2b01e 100644
--- a/freebsd/lib/libc/net/getaddrinfo.c
+++ b/freebsd/lib/libc/net/getaddrinfo.c
@@ -847,8 +847,6 @@ set_source(struct ai_order *aio, struct policyhead *ph)
struct in6_ifreq ifr6;
u_int32_t flags6;
- /* XXX: interface name should not be hardcoded */
- strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
memset(&ifr6, 0, sizeof(ifr6));
memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen);
if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
@@ -1576,7 +1574,8 @@ ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
if (*scope == '\0')
return -1;
- if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
+ if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
+ IN6_IS_ADDR_MC_NODELOCAL(a6)) {
/*
* We currently assume a one-to-one mapping between links
* and interfaces, so we simply use interface indices for
diff --git a/freebsd/lib/libc/net/ip6opt.c b/freebsd/lib/libc/net/ip6opt.c
index b3fe4a08..fcd76a3e 100644
--- a/freebsd/lib/libc/net/ip6opt.c
+++ b/freebsd/lib/libc/net/ip6opt.c
@@ -461,7 +461,7 @@ inet6_opt_append(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
int
inet6_opt_finish(void *extbuf, socklen_t extlen, int offset)
{
- int updatelen = offset > 0 ? (1 + ((offset - 1) | 7)) : 0;;
+ int updatelen = offset > 0 ? (1 + ((offset - 1) | 7)) : 0;
if (extbuf) {
u_int8_t *padp;
diff --git a/freebsd/lib/libc/net/name6.c b/freebsd/lib/libc/net/name6.c
index c60a3efd..564721ae 100644
--- a/freebsd/lib/libc/net/name6.c
+++ b/freebsd/lib/libc/net/name6.c
@@ -200,6 +200,7 @@ static struct hostent *_hpmapv6(struct hostent *, int *);
#endif
static struct hostent *_hpsort(struct hostent *, res_state);
+#ifdef INET6
static struct hostent *_hpreorder(struct hostent *);
static int get_addrselectpolicy(struct policyhead *);
static void free_addrselectpolicy(struct policyhead *);
@@ -209,6 +210,7 @@ static void set_source(struct hp_order *, struct policyhead *);
static int matchlen(struct sockaddr *, struct sockaddr *);
static int comp_dst(const void *, const void *);
static int gai_addr2scopetype(struct sockaddr *);
+#endif
/*
* Functions defined in RFC2553
@@ -285,8 +287,10 @@ getipnodebyname(const char *name, int af, int flags, int *errp)
hp = gethostbyname2(name, af);
hp = _hpcopy(hp, errp);
-
#ifdef INET6
+ if (af == AF_INET6)
+ hp = _hpreorder(hp);
+
if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) &&
MAPADDRENABLED(flags)) {
struct hostent *hp2 = gethostbyname2(name, AF_INET);
@@ -309,7 +313,7 @@ getipnodebyname(const char *name, int af, int flags, int *errp)
*errp = statp->res_h_errno;
statp->options = options;
- return _hpreorder(_hpsort(hp, statp));
+ return _hpsort(hp, statp);
}
struct hostent *
@@ -632,6 +636,7 @@ _hpsort(struct hostent *hp, res_state statp)
return hp;
}
+#ifdef INET6
/*
* _hpreorder: sort address by default address selection
*/
@@ -884,8 +889,6 @@ set_source(struct hp_order *aio, struct policyhead *ph)
struct in6_ifreq ifr6;
u_int32_t flags6;
- /* XXX: interface name should not be hardcoded */
- strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
memset(&ifr6, 0, sizeof(ifr6));
memcpy(&ifr6.ifr_addr, &ss, ss.ss_len);
if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
@@ -1111,3 +1114,4 @@ gai_addr2scopetype(struct sockaddr *sa)
return(-1);
}
}
+#endif
diff --git a/freebsd/lib/libipsec/pfkey.c b/freebsd/lib/libipsec/pfkey.c
index 0c914962..aa0f1404 100644
--- a/freebsd/lib/libipsec/pfkey.c
+++ b/freebsd/lib/libipsec/pfkey.c
@@ -662,7 +662,7 @@ pfkey_send_register(so, satype)
{
int len, algno;
- if (satype == PF_UNSPEC) {
+ if (satype == SADB_SATYPE_UNSPEC) {
for (algno = 0;
algno < sizeof(supported_map)/sizeof(supported_map[0]);
algno++) {
@@ -1778,6 +1778,18 @@ pfkey_align(msg, mhp)
case SADB_X_EXT_SA2:
mhp[ext->sadb_ext_type] = (caddr_t)ext;
break;
+ case SADB_X_EXT_NAT_T_TYPE:
+ case SADB_X_EXT_NAT_T_SPORT:
+ case SADB_X_EXT_NAT_T_DPORT:
+ /* case SADB_X_EXT_NAT_T_OA: is OAI */
+ case SADB_X_EXT_NAT_T_OAI:
+ case SADB_X_EXT_NAT_T_OAR:
+ case SADB_X_EXT_NAT_T_FRAG:
+ if (feature_present("ipsec_natt")) {
+ mhp[ext->sadb_ext_type] = (caddr_t)ext;
+ break;
+ }
+ /* FALLTHROUGH */
default:
__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
return -1;
diff --git a/freebsd/lib/libkvm/kvm.h b/freebsd/lib/libkvm/kvm.h
index 9ff0bf82..4c2b4b8a 100644
--- a/freebsd/lib/libkvm/kvm.h
+++ b/freebsd/lib/libkvm/kvm.h
@@ -69,6 +69,7 @@ struct kvm_swap {
__BEGIN_DECLS
int kvm_close(kvm_t *);
+int kvm_dpcpu_setcpu(kvm_t *, unsigned int);
char **kvm_getargv(kvm_t *, const struct kinfo_proc *, int);
int kvm_getcptime(kvm_t *, long *);
char **kvm_getenvv(kvm_t *, const struct kinfo_proc *, int);
diff --git a/freebsd/lib/libmemstat/memstat_uma.c b/freebsd/lib/libmemstat/memstat_uma.c
index 38571f1b..7480b18d 100644
--- a/freebsd/lib/libmemstat/memstat_uma.c
+++ b/freebsd/lib/libmemstat/memstat_uma.c
@@ -29,7 +29,6 @@
#include <rtems/bsd/sys/param.h>
#include <sys/sysctl.h>
-#define LIBMEMSTAT /* Cause vm_page.h not to include opt_vmpage.h */
#include <vm/vm.h>
#include <vm/vm_page.h>
@@ -264,7 +263,7 @@ kread(kvm_t *kvm, void *kvm_pointer, void *address, size_t size,
}
static int
-kread_string(kvm_t *kvm, void *kvm_pointer, char *buffer, int buflen)
+kread_string(kvm_t *kvm, const void *kvm_pointer, char *buffer, int buflen)
{
ssize_t ret;
int i;
diff --git a/freebsd/lib/libutil/humanize_number.c b/freebsd/lib/libutil/humanize_number.c
index e58668b7..876c2bce 100644
--- a/freebsd/lib/libutil/humanize_number.c
+++ b/freebsd/lib/libutil/humanize_number.c
@@ -42,43 +42,58 @@ __FBSDID("$FreeBSD$");
#include <locale.h>
#include <libutil.h>
+static const int maxscale = 7;
+
int
-humanize_number(char *buf, size_t len, int64_t bytes,
+humanize_number(char *buf, size_t len, int64_t quotient,
const char *suffix, int scale, int flags)
{
const char *prefixes, *sep;
- int b, i, r, maxscale, s1, s2, sign;
+ int i, r, remainder, s1, s2, sign;
int64_t divisor, max;
size_t baselen;
assert(buf != NULL);
assert(suffix != NULL);
assert(scale >= 0);
+ assert(scale < maxscale || (((scale & (HN_AUTOSCALE | HN_GETSCALE)) != 0)));
+ assert(!((flags & HN_DIVISOR_1000) && (flags & HN_IEC_PREFIXES)));
- if (flags & HN_DIVISOR_1000) {
- /* SI for decimal multiplies */
- divisor = 1000;
- if (flags & HN_B)
- prefixes = "B\0k\0M\0G\0T\0P\0E";
- else
- prefixes = "\0\0k\0M\0G\0T\0P\0E";
- } else {
+ remainder = 0;
+
+ if (flags & HN_IEC_PREFIXES) {
+ baselen = 2;
/*
- * binary multiplies
- * XXX IEC 60027-2 recommends Ki, Mi, Gi...
+ * Use the prefixes for power of two recommended by
+ * the International Electrotechnical Commission
+ * (IEC) in IEC 80000-3 (i.e. Ki, Mi, Gi...).
+ *
+ * HN_IEC_PREFIXES implies a divisor of 1024 here
+ * (use of HN_DIVISOR_1000 would have triggered
+ * an assertion earlier).
*/
divisor = 1024;
if (flags & HN_B)
- prefixes = "B\0K\0M\0G\0T\0P\0E";
+ prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+ else
+ prefixes = "\0\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+ } else {
+ baselen = 1;
+ if (flags & HN_DIVISOR_1000)
+ divisor = 1000;
+ else
+ divisor = 1024;
+
+ if (flags & HN_B)
+ prefixes = "B\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
else
- prefixes = "\0\0K\0M\0G\0T\0P\0E";
+ prefixes = "\0\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
}
-#define SCALE2PREFIX(scale) (&prefixes[(scale) << 1])
- maxscale = 7;
+#define SCALE2PREFIX(scale) (&prefixes[(scale) * 3])
- if (scale >= maxscale &&
- (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
+ if (scale < 0 || (scale >= maxscale &&
+ (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0))
return (-1);
if (buf == NULL || suffix == NULL)
@@ -86,14 +101,13 @@ humanize_number(char *buf, size_t len, int64_t bytes,
if (len > 0)
buf[0] = '\0';
- if (bytes < 0) {
+ if (quotient < 0) {
sign = -1;
- bytes *= -100;
- baselen = 3; /* sign, digit, prefix */
+ quotient = -quotient;
+ baselen += 2; /* sign, digit */
} else {
sign = 1;
- bytes *= 100;
- baselen = 2; /* digit, prefix */
+ baselen += 1; /* digit */
}
if (flags & HN_NOSPACE)
sep = "";
@@ -109,7 +123,7 @@ humanize_number(char *buf, size_t len, int64_t bytes,
if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
/* See if there is additional columns can be used. */
- for (max = 100, i = len - baselen; i-- > 0;)
+ for (max = 1, i = len - baselen; i-- > 0;)
max *= 10;
/*
@@ -117,30 +131,37 @@ humanize_number(char *buf, size_t len, int64_t bytes,
* If there will be an overflow by the rounding below,
* divide once more.
*/
- for (i = 0; bytes >= max - 50 && i < maxscale; i++)
- bytes /= divisor;
+ for (i = 0;
+ (quotient >= max || (quotient == max - 1 && remainder >= 950)) &&
+ i < maxscale; i++) {
+ remainder = quotient % divisor;
+ quotient /= divisor;
+ }
if (scale & HN_GETSCALE)
return (i);
- } else
- for (i = 0; i < scale && i < maxscale; i++)
- bytes /= divisor;
+ } else {
+ for (i = 0; i < scale && i < maxscale; i++) {
+ remainder = quotient % divisor;
+ quotient /= divisor;
+ }
+ }
/* If a value <= 9.9 after rounding and ... */
- if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
+ if (quotient <= 9 && remainder < 950 && i > 0 && flags & HN_DECIMAL) {
/* baselen + \0 + .N */
if (len < baselen + 1 + 2)
return (-1);
- b = ((int)bytes + 5) / 10;
- s1 = b / 10;
- s2 = b % 10;
+ s1 = (int)quotient + ((remainder + 50) / 1000);
+ s2 = ((remainder + 50) / 100) % 10;
r = snprintf(buf, len, "%d%s%d%s%s%s",
sign * s1, localeconv()->decimal_point, s2,
sep, SCALE2PREFIX(i), suffix);
} else
r = snprintf(buf, len, "%" PRId64 "%s%s%s",
- sign * ((bytes + 50) / 100),
+ sign * (quotient + (remainder + 50) / 1000),
sep, SCALE2PREFIX(i), suffix);
return (r);
}
+
diff --git a/freebsd/lib/libutil/libutil.h b/freebsd/lib/libutil/libutil.h
index 3187fb37..4b3c31c6 100644
--- a/freebsd/lib/libutil/libutil.h
+++ b/freebsd/lib/libutil/libutil.h
@@ -39,6 +39,39 @@
#ifndef _LIBUTIL_H_
#define _LIBUTIL_H_
+#include <sys/cdefs.h>
+#include <rtems/bsd/sys/_types.h>
+
+#ifndef _GID_T_DECLARED
+typedef __gid_t gid_t;
+#define _GID_T_DECLARED
+#endif
+
+#ifndef _INT64_T_DECLARED
+typedef __int64_t int64_t;
+#define _INT64_T_DECLARED
+#endif
+
+#ifndef _UINT64_T_DECLARED
+typedef __uint64_t uint64_t;
+#define _UINT64_T_DECLARED
+#endif
+
+#ifndef _PID_T_DECLARED
+typedef __pid_t pid_t;
+#define _PID_T_DECLARED
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+
+#ifndef _UID_T_DECLARED
+typedef __uid_t uid_t;
+#define _UID_T_DECLARED
+#endif
+
#define PROPERTY_MAX_NAME 64
#define PROPERTY_MAX_VALUE 512
@@ -119,6 +152,7 @@ int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2);
void pw_fini(void);
int pw_init(const char *_dir, const char *_master);
char *pw_make(const struct passwd *_pw);
+char *pw_make_v7(const struct passwd *_pw);
int pw_mkdb(const char *_user);
int pw_lock(void);
struct passwd *pw_scan(const char *_line, int _flags);
@@ -127,9 +161,15 @@ int pw_tmp(int _mfd);
#endif
#ifdef _GRP_H_
+int gr_copy(int __ffd, int _tfd, const struct group *_gr, struct group *_old_gr);
+struct group *gr_dup(const struct group *gr);
int gr_equal(const struct group *gr1, const struct group *gr2);
+void gr_fini(void);
+int gr_init(const char *_dir, const char *_master);
+int gr_lock(void);
char *gr_make(const struct group *gr);
-struct group *gr_dup(const struct group *gr);
+int gr_mkdb(void);
+int gr_tmp(int _mdf);
struct group *gr_scan(const char *line);
#endif
@@ -174,7 +214,9 @@ __END_DECLS
#define HN_NOSPACE 0x02
#define HN_B 0x04
#define HN_DIVISOR_1000 0x08
+#define HN_IEC_PREFIXES 0x10
+/* maxscale = 0x07 */
#define HN_GETSCALE 0x10
#define HN_AUTOSCALE 0x20
diff --git a/freebsd/sbin/dhclient/clparse.c b/freebsd/sbin/dhclient/clparse.c
index 5d7084e7..7c1e74fc 100644
--- a/freebsd/sbin/dhclient/clparse.c
+++ b/freebsd/sbin/dhclient/clparse.c
@@ -100,6 +100,8 @@ read_client_conf(void)
DHO_DOMAIN_NAME_SERVERS;
top_level_config.requested_options
[top_level_config.requested_option_count++] = DHO_HOST_NAME;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_DOMAIN_SEARCH;
if ((cfile = fopen(path_dhclient_conf, "r")) != NULL) {
do {
diff --git a/freebsd/sbin/dhclient/dhclient.c b/freebsd/sbin/dhclient/dhclient.c
index b72d5bff..8ee70084 100644
--- a/freebsd/sbin/dhclient/dhclient.c
+++ b/freebsd/sbin/dhclient/dhclient.c
@@ -95,6 +95,9 @@ struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
struct in_addr inaddr_any;
struct sockaddr_in sockaddr_broadcast;
+char *path_dhclient_pidfile;
+struct pidfh *pidfile;
+
/*
* ASSERT_STATE() does nothing now; it used to be
* assert (state_is == state_shouldbe).
@@ -215,6 +218,7 @@ routehandler(struct protocol *p)
struct sockaddr *sa;
struct iaddr a;
ssize_t n;
+ int linkstat;
n = read(routefd, &msg, sizeof(msg));
rtm = (struct rt_msghdr *)msg;
@@ -275,6 +279,15 @@ routehandler(struct protocol *p)
ifi->name);
goto die;
}
+ linkstat = interface_link_status(ifi->name);
+ if (linkstat != ifi->linkstat) {
+ debug("%s link state %s -> %s", ifi->name,
+ ifi->linkstat ? "up" : "down",
+ linkstat ? "up" : "down");
+ ifi->linkstat = linkstat;
+ if (linkstat)
+ state_reboot(ifi);
+ }
break;
case RTM_IFANNOUNCE:
ifan = (struct if_announcemsghdr *)rtm;
@@ -316,6 +329,8 @@ die:
if (ifi->client->alias)
script_write_params("alias_", ifi->client->alias);
script_go();
+ if (pidfile != NULL)
+ pidfile_remove(pidfile);
exit(1);
}
@@ -327,12 +342,13 @@ main(int argc, char *argv[])
int pipe_fd[2];
int immediate_daemon = 0;
struct passwd *pw;
+ pid_t otherpid;
/* Initially, log errors to stderr as well as to syslogd. */
openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
setlogmask(LOG_UPTO(LOG_DEBUG));
- while ((ch = getopt(argc, argv, "bc:dl:qu")) != -1)
+ while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
switch (ch) {
case 'b':
immediate_daemon = 1;
@@ -346,6 +362,9 @@ main(int argc, char *argv[])
case 'l':
path_dhclient_db = optarg;
break;
+ case 'p':
+ path_dhclient_pidfile = optarg;
+ break;
case 'q':
quiet = 1;
break;
@@ -362,6 +381,24 @@ main(int argc, char *argv[])
if (argc != 1)
usage();
+ if (path_dhclient_pidfile == NULL) {
+#ifdef __rtems__
+#define _PATH_VARRUN "/var/run"
+#endif /* __rtems__ */
+ asprintf(&path_dhclient_pidfile,
+ "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
+ if (path_dhclient_pidfile == NULL)
+ error("asprintf");
+ }
+ pidfile = pidfile_open(path_dhclient_pidfile, 0600, &otherpid);
+ if (pidfile == NULL) {
+ if (errno == EEXIST)
+ error("dhclient already running, pid: %d.", otherpid);
+ if (errno == EAGAIN)
+ error("dhclient already running.");
+ warning("Cannot open or create pidfile: %m");
+ }
+
if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
error("calloc");
if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
@@ -385,6 +422,12 @@ main(int argc, char *argv[])
read_client_conf();
+ /* The next bit is potentially very time-consuming, so write out
+ the pidfile right away. We will write it out again with the
+ correct pid after daemonizing. */
+ if (pidfile != NULL)
+ pidfile_write(pidfile);
+
if (!interface_link_status(ifi->name)) {
fprintf(stderr, "%s: no link ...", ifi->name);
fflush(stderr);
@@ -400,6 +443,7 @@ main(int argc, char *argv[])
}
fprintf(stderr, " got link\n");
}
+ ifi->linkstat = 1;
if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
error("cannot open %s: %m", _PATH_DEVNULL);
@@ -2302,6 +2346,9 @@ go_daemon(void)
if (daemon(1, 0) == -1)
error("daemon");
+ if (pidfile != NULL)
+ pidfile_write(pidfile);
+
/* we are chrooted, daemon(3) fails to open /dev/null */
if (nullfd != -1) {
dup2(nullfd, STDIN_FILENO);
@@ -2372,6 +2419,7 @@ check_option(struct client_lease *l, int option)
}
return (1);
case DHO_DOMAIN_NAME:
+ case DHO_DOMAIN_SEARCH:
if (!res_hnok(sbuf)) {
if (!check_search(sbuf)) {
warning("Bogus domain search list %d: %s (%s)",
diff --git a/freebsd/sbin/dhclient/dhcp.h b/freebsd/sbin/dhclient/dhcp.h
index e4fa9d17..6e7d1a74 100644
--- a/freebsd/sbin/dhclient/dhcp.h
+++ b/freebsd/sbin/dhclient/dhcp.h
@@ -169,6 +169,7 @@ struct dhcp_packet {
#define DHO_STREETTALK_SERVER 75
#define DHO_STREETTALK_DA_SERVER 76
#define DHO_DHCP_USER_CLASS_ID 77
+#define DHO_DOMAIN_SEARCH 119
#define DHO_CLASSLESS_ROUTES 121
#define DHO_END 255
diff --git a/freebsd/sbin/dhclient/dhcpd.h b/freebsd/sbin/dhclient/dhcpd.h
index 0c47a9f8..d7844bc6 100644
--- a/freebsd/sbin/dhclient/dhcpd.h
+++ b/freebsd/sbin/dhclient/dhcpd.h
@@ -41,7 +41,7 @@
* $FreeBSD$
*/
-#include <rtems/bsd/sys/types.h>
+#include <rtems/bsd/sys/param.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@@ -60,6 +60,7 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <libutil.h>
#include <limits.h>
#include <netdb.h>
#include <paths.h>
@@ -207,6 +208,7 @@ struct interface_info {
int errors;
int dead;
u_int16_t index;
+ int linkstat;
};
struct timeout {
@@ -353,6 +355,8 @@ extern int log_perror;
extern struct client_config top_level_config;
+extern struct pidfh *pidfile;
+
void dhcpoffer(struct packet *);
void dhcpack(struct packet *);
void dhcpnak(struct packet *);
diff --git a/freebsd/sbin/dhclient/errwarn.c b/freebsd/sbin/dhclient/errwarn.c
index de345832..57207807 100644
--- a/freebsd/sbin/dhclient/errwarn.c
+++ b/freebsd/sbin/dhclient/errwarn.c
@@ -83,6 +83,8 @@ error(char *fmt, ...)
fprintf(stderr, "exiting.\n");
fflush(stderr);
}
+ if (pidfile != NULL)
+ pidfile_remove(pidfile);
exit(1);
}
diff --git a/freebsd/sbin/dhclient/options.c b/freebsd/sbin/dhclient/options.c
index 09aa4d8f..17643e76 100644
--- a/freebsd/sbin/dhclient/options.c
+++ b/freebsd/sbin/dhclient/options.c
@@ -55,6 +55,10 @@ void parse_options(struct packet *);
void parse_option_buffer(struct packet *, unsigned char *, int);
int store_options(unsigned char *, int, struct tree_cache **,
unsigned char *, int, int, int, int);
+void expand_domain_search(struct packet *packet);
+int find_search_domain_name_len(struct option_data *option, int *offset);
+void expand_search_domain_name(struct option_data *option, int *offset,
+ unsigned char **domain_search);
/*
@@ -94,6 +98,11 @@ parse_options(struct packet *packet)
(unsigned char *)packet->raw->sname,
sizeof(packet->raw->sname));
}
+
+ /* Expand DHCP Domain Search option. */
+ if (packet->options_valid) {
+ expand_domain_search(packet);
+ }
}
/*
@@ -194,6 +203,171 @@ parse_option_buffer(struct packet *packet,
}
/*
+ * Expand DHCP Domain Search option. The value of this option is
+ * encoded like DNS' list of labels. See:
+ * RFC 3397
+ * RFC 1035
+ */
+void
+expand_domain_search(struct packet *packet)
+{
+ int offset, expanded_len, next_domain_len;
+ struct option_data *option;
+ unsigned char *domain_search, *cursor;
+
+ if (packet->options[DHO_DOMAIN_SEARCH].data == NULL)
+ return;
+
+ option = &packet->options[DHO_DOMAIN_SEARCH];
+
+ /* Compute final expanded length. */
+ expanded_len = 0;
+ offset = 0;
+ while (offset < option->len) {
+ next_domain_len = find_search_domain_name_len(option, &offset);
+ if (next_domain_len < 0)
+ /* The Domain Search option value is invalid. */
+ return;
+
+ /* We add 1 for the space between domain names. */
+ expanded_len += next_domain_len + 1;
+ }
+ if (expanded_len > 0)
+ /* Remove 1 for the superfluous trailing space. */
+ --expanded_len;
+
+ domain_search = malloc(expanded_len + 1);
+ if (domain_search == NULL)
+ error("Can't allocate storage for expanded domain-search\n");
+
+ offset = 0;
+ cursor = domain_search;
+ while (offset < option->len) {
+ expand_search_domain_name(option, &offset, &cursor);
+ cursor[0] = ' ';
+ cursor++;
+ }
+ domain_search[expanded_len] = '\0';
+
+ free(option->data);
+ option->len = expanded_len;
+ option->data = domain_search;
+}
+
+int
+find_search_domain_name_len(struct option_data *option, int *offset)
+{
+ int domain_name_len, i, label_len, pointer, pointed_len;
+
+ domain_name_len = 0;
+
+ i = *offset;
+ while (i < option->len) {
+ label_len = option->data[i];
+ if (label_len == 0) {
+ /*
+ * A zero-length label marks the end of this
+ * domain name.
+ */
+ *offset = i + 1;
+ return (domain_name_len);
+ } else if (label_len & 0xC0) {
+ /* This is a pointer to another list of labels. */
+ if (i + 1 >= option->len) {
+ /* The pointer is truncated. */
+ warning("Truncated pointer in DHCP Domain "
+ "Search option.");
+ return (-1);
+ }
+
+ pointer = ((label_len & ~(0xC0)) << 8) +
+ option->data[i + 1];
+ if (pointer >= *offset) {
+ /*
+ * The pointer must indicates a prior
+ * occurance.
+ */
+ warning("Invalid forward pointer in DHCP "
+ "Domain Search option compression.");
+ return (-1);
+ }
+
+ pointed_len = find_search_domain_name_len(option,
+ &pointer);
+ domain_name_len += pointed_len;
+
+ *offset = i + 2;
+ return (domain_name_len);
+ }
+
+ if (i + label_len >= option->len) {
+ warning("Truncated label in DHCP Domain Search "
+ "option.");
+ return (-1);
+ }
+
+ /*
+ * Update the domain name length with the length of the
+ * current label, plus a trailing dot ('.').
+ */
+ domain_name_len += label_len + 1;
+
+ /* Move cursor. */
+ i += label_len + 1;
+ }
+
+ warning("Truncated DHCP Domain Search option.");
+
+ return (-1);
+}
+
+void
+expand_search_domain_name(struct option_data *option, int *offset,
+ unsigned char **domain_search)
+{
+ int i, label_len, pointer;
+ unsigned char *cursor;
+
+ /*
+ * This is the same loop than the function above
+ * (find_search_domain_name_len). Therefore, we remove checks,
+ * they're already done. Here, we just make the copy.
+ */
+ i = *offset;
+ cursor = *domain_search;
+ while (i < option->len) {
+ label_len = option->data[i];
+ if (label_len == 0) {
+ /*
+ * A zero-length label marks the end of this
+ * domain name.
+ */
+ *offset = i + 1;
+ *domain_search = cursor;
+ return;
+ } else if (label_len & 0xC0) {
+ /* This is a pointer to another list of labels. */
+ pointer = ((label_len & ~(0xC0)) << 8) +
+ option->data[i + 1];
+
+ expand_search_domain_name(option, &pointer, &cursor);
+
+ *offset = i + 2;
+ *domain_search = cursor;
+ return;
+ }
+
+ /* Copy the label found. */
+ memcpy(cursor, option->data + i + 1, label_len);
+ cursor[label_len] = '.';
+
+ /* Move cursor. */
+ i += label_len + 1;
+ cursor += label_len + 1;
+ }
+}
+
+/*
* cons options into a big buffer, and then split them out into the
* three separate buffers if needed. This allows us to cons up a set of
* vendor options using the same routine.
diff --git a/freebsd/sbin/dhclient/tables.c b/freebsd/sbin/dhclient/tables.c
index 81a9acc8..c7bac57e 100644
--- a/freebsd/sbin/dhclient/tables.c
+++ b/freebsd/sbin/dhclient/tables.c
@@ -184,7 +184,7 @@ struct option dhcp_options[256] = {
{ "option-116", "X", &dhcp_universe, 116 },
{ "option-117", "X", &dhcp_universe, 117 },
{ "option-118", "X", &dhcp_universe, 118 },
- { "option-119", "X", &dhcp_universe, 119 },
+ { "domain-search", "t", &dhcp_universe, 119 },
{ "option-120", "X", &dhcp_universe, 120 },
{ "classless-routes", "BA", &dhcp_universe, 121 },
{ "option-122", "X", &dhcp_universe, 122 },
@@ -400,12 +400,13 @@ unsigned char dhcp_option_default_priority_list[] = {
DHO_IRC_SERVER,
DHO_STREETTALK_SERVER,
DHO_STREETTALK_DA_SERVER,
+ DHO_DOMAIN_SEARCH,
/* Presently-undefined options... */
62, 63, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
- 118, 119, 120, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+ 118, 120, 122, 123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
diff --git a/freebsd/sbin/ifconfig/ifcarp.c b/freebsd/sbin/ifconfig/ifcarp.c
index 96a6dcb9..2537d6be 100644
--- a/freebsd/sbin/ifconfig/ifcarp.c
+++ b/freebsd/sbin/ifconfig/ifcarp.c
@@ -57,6 +57,7 @@ void setcarp_advbase(const char *,int, int, const struct afswtch *rafp);
void setcarp_advskew(const char *, int, int, const struct afswtch *rafp);
void setcarp_passwd(const char *, int, int, const struct afswtch *rafp);
void setcarp_vhid(const char *, int, int, const struct afswtch *rafp);
+void setcarp_state(const char *, int, int, const struct afswtch *rafp);
void
carp_status(int s)
@@ -175,11 +176,34 @@ setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
return;
}
+void setcarp_state(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct carpreq carpr;
+ int i;
+
+ bzero((char *)&carpr, sizeof(struct carpreq));
+ ifr.ifr_data = (caddr_t)&carpr;
+
+ if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGVH");
+
+ for (i = 0; i <= CARP_MAXSTATE; i++) {
+ if (!strcasecmp(val, carp_states[i])) {
+ carpr.carpr_state = i;
+ break;
+ }
+ }
+
+ if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSVH");
+}
+
static struct cmd carp_cmds[] = {
DEF_CMD_ARG("advbase", setcarp_advbase),
DEF_CMD_ARG("advskew", setcarp_advskew),
DEF_CMD_ARG("pass", setcarp_passwd),
DEF_CMD_ARG("vhid", setcarp_vhid),
+ DEF_CMD_ARG("state", setcarp_state),
};
static struct afswtch af_carp = {
.af_name = "af_carp",
diff --git a/freebsd/sbin/ifconfig/ifconfig.c b/freebsd/sbin/ifconfig/ifconfig.c
index b80d880f..0d658856 100644
--- a/freebsd/sbin/ifconfig/ifconfig.c
+++ b/freebsd/sbin/ifconfig/ifconfig.c
@@ -363,6 +363,8 @@ main(int argc, char *argv[])
}
cp = ifa->ifa_name;
+ if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0)
+ continue;
if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
continue;
if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
@@ -925,7 +927,7 @@ unsetifdescr(const char *val, int value, int s, const struct afswtch *afp)
#define IFCAPBITS \
"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \
-"\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE"
+"\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP"
/*
* Print the status of the interface. If an address family was
diff --git a/freebsd/sbin/ifconfig/iflagg.c b/freebsd/sbin/ifconfig/iflagg.c
index 16862e85..8a98f8a9 100644
--- a/freebsd/sbin/ifconfig/iflagg.c
+++ b/freebsd/sbin/ifconfig/iflagg.c
@@ -81,6 +81,36 @@ setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
err(1, "SIOCSLAGG");
}
+static void
+setlagghash(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct lagg_reqflags rf;
+ char *str, *tmp, *tok;
+
+
+ rf.rf_flags = 0;
+ str = tmp = strdup(val);
+ while ((tok = strsep(&tmp, ",")) != NULL) {
+ if (strcmp(tok, "l2") == 0)
+ rf.rf_flags |= LAGG_F_HASHL2;
+ else if (strcmp(tok, "l3") == 0)
+ rf.rf_flags |= LAGG_F_HASHL3;
+ else if (strcmp(tok, "l4") == 0)
+ rf.rf_flags |= LAGG_F_HASHL4;
+ else {
+ free(str);
+ errx(1, "Invalid lagghash option: %s", tok);
+ }
+ }
+ free(str);
+ if (rf.rf_flags == 0)
+ errx(1, "No lagghash options supplied");
+
+ strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname));
+ if (ioctl(s, SIOCSLAGGHASH, &rf))
+ err(1, "SIOCSLAGGHASH");
+}
+
static char *
lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen)
{
@@ -115,6 +145,7 @@ lagg_status(int s)
struct lagg_protos lpr[] = LAGG_PROTOS;
struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS];
struct lagg_reqall ra;
+ struct lagg_reqflags rf;
struct lacp_opreq *lp;
const char *proto = "<unknown>";
int i, isport = 0;
@@ -132,6 +163,10 @@ lagg_status(int s)
ra.ra_size = sizeof(rpbuf);
ra.ra_port = rpbuf;
+ strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname));
+ if (ioctl(s, SIOCGLAGGFLAGS, &rf) != 0)
+ rf.rf_flags = 0;
+
if (ioctl(s, SIOCGLAGG, &ra) == 0) {
lp = (struct lacp_opreq *)&ra.ra_lacpreq;
@@ -143,6 +178,23 @@ lagg_status(int s)
}
printf("\tlaggproto %s", proto);
+ if (rf.rf_flags & LAGG_F_HASHMASK) {
+ const char *sep = "";
+
+ printf(" lagghash ");
+ if (rf.rf_flags & LAGG_F_HASHL2) {
+ printf("%sl2", sep);
+ sep = ",";
+ }
+ if (rf.rf_flags & LAGG_F_HASHL3) {
+ printf("%sl3", sep);
+ sep = ",";
+ }
+ if (rf.rf_flags & LAGG_F_HASHL4) {
+ printf("%sl4", sep);
+ sep = ",";
+ }
+ }
if (isport)
printf(" laggdev %s", rp.rp_ifname);
putchar('\n');
@@ -174,6 +226,7 @@ static struct cmd lagg_cmds[] = {
DEF_CMD_ARG("laggport", setlaggport),
DEF_CMD_ARG("-laggport", unsetlaggport),
DEF_CMD_ARG("laggproto", setlaggproto),
+ DEF_CMD_ARG("lagghash", setlagghash),
};
static struct afswtch af_lagg = {
.af_name = "af_lagg",
diff --git a/freebsd/sbin/ifconfig/ifmedia.c b/freebsd/sbin/ifconfig/ifmedia.c
index aa262568..f827c357 100644
--- a/freebsd/sbin/ifconfig/ifmedia.c
+++ b/freebsd/sbin/ifconfig/ifmedia.c
@@ -284,13 +284,9 @@ setmedia(const char *val, int d, int s, const struct afswtch *afp)
subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
+ ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
- if ((ifr.ifr_media & IFM_TMASK) == 0) {
- ifr.ifr_media &= ~(IFM_GMASK | IFM_OMASK);
- }
-
ifmr->ifm_current = ifr.ifr_media;
callback_register(setifmediacallback, (void *)ifmr);
}
@@ -437,6 +433,9 @@ static const struct ifmedia_description ifm_subtype_shared_aliases[] =
static const struct ifmedia_description ifm_shared_option_descriptions[] =
IFM_SHARED_OPTION_DESCRIPTIONS;
+static struct ifmedia_description ifm_shared_option_aliases[] =
+ IFM_SHARED_OPTION_ALIASES;
+
struct ifmedia_type_to_subtype {
struct {
const struct ifmedia_description *desc;
@@ -445,7 +444,7 @@ struct ifmedia_type_to_subtype {
struct {
const struct ifmedia_description *desc;
int alias;
- } options[3];
+ } options[4];
struct {
const struct ifmedia_description *desc;
int alias;
@@ -464,6 +463,7 @@ static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
},
{
{ &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
{ &ifm_subtype_ethernet_option_descriptions[0], 0 },
{ NULL, 0 },
},
@@ -481,6 +481,7 @@ static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
},
{
{ &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
{ &ifm_subtype_tokenring_option_descriptions[0], 0 },
{ NULL, 0 },
},
@@ -498,6 +499,7 @@ static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
},
{
{ &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
{ &ifm_subtype_fddi_option_descriptions[0], 0 },
{ NULL, 0 },
},
@@ -515,6 +517,7 @@ static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
},
{
{ &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
{ &ifm_subtype_ieee80211_option_descriptions[0], 0 },
{ NULL, 0 },
},
@@ -534,6 +537,7 @@ static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
},
{
{ &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
{ &ifm_subtype_atm_option_descriptions[0], 0 },
{ NULL, 0 },
},
diff --git a/freebsd/sbin/ifconfig/ifvlan.c b/freebsd/sbin/ifconfig/ifvlan.c
index e745df82..b1c808c7 100644
--- a/freebsd/sbin/ifconfig/ifvlan.c
+++ b/freebsd/sbin/ifconfig/ifvlan.c
@@ -183,6 +183,8 @@ static struct cmd vlan_cmds[] = {
DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap),
DEF_CMD("-vlanhwtso", -IFCAP_VLAN_HWTSO, setifcap),
DEF_CMD("vlanhwtso", IFCAP_VLAN_HWTSO, setifcap),
+ DEF_CMD("vlanhwcsum", IFCAP_VLAN_HWCSUM, setifcap),
+ DEF_CMD("-vlanhwcsum", -IFCAP_VLAN_HWCSUM, setifcap),
};
static struct afswtch af_vlan = {
.af_name = "af_vlan",
diff --git a/freebsd/sbin/route/route.c b/freebsd/sbin/route/route.c
index 3a56959f..ba07349a 100644
--- a/freebsd/sbin/route/route.c
+++ b/freebsd/sbin/route/route.c
@@ -37,8 +37,6 @@ static const char copyright[] =
#if 0
static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95";
#endif
-static const char rcsid[] =
- "$FreeBSD$";
#endif /* not lint */
#ifdef __rtems__
@@ -47,6 +45,9 @@ static const char rcsid[] =
#include <machine/rtems-bsd-program.h>
#include <machine/rtems-bsd-commands.h>
#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <rtems/bsd/sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
@@ -75,7 +76,7 @@ static const char rcsid[] =
#include <ifaddrs.h>
static const struct keytab {
- char *kt_cp;
+ const char *kt_cp;
int kt_i;
} keywords[] = {
#include "keywords.h"
@@ -121,29 +122,39 @@ struct rt_ctx rt_ctx;
typedef union sockunion *sup;
-static int keyword();
static int atalk_aton(const char *, struct at_addr *);
static char *atalk_ntoa(struct at_addr, char [20]);
-static const char *routename(), *netname();
-static void interfaces(struct rt_ctx *c);
-static void set_metric();
-static void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
-static void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
-static void inet_makenetandmask();
+static void bprintf(FILE *, int, const char *);
+static void flushroutes(struct rt_ctx *, int argc, char *argv[]);
+static int getaddr(struct rt_ctx *, int, char *, struct hostent **);
+static int keyword(const char *);
+static void inet_makenetandmask(struct rt_ctx *, u_long, struct sockaddr_in *, u_long);
#ifdef INET6
-static int inet6_makenetandmask(struct rt_ctx *, struct sockaddr_in6 *, char *);
+static int inet6_makenetandmask(struct rt_ctx *, struct sockaddr_in6 *, const char *);
#endif
-static int getaddr(), rtmsg();
-static int prefixlen();
-extern char *iso_ntoa();
+static void interfaces(struct rt_ctx *);
+static void mask_addr(struct rt_ctx *);
+static void monitor(struct rt_ctx *);
+static const char *netname(struct rt_ctx *, struct sockaddr *);
+static void newroute(struct rt_ctx *, int, char **);
+static void pmsg_addrs(struct rt_ctx *, char *, int, size_t);
+static void pmsg_common(struct rt_ctx *, struct rt_msghdr *, size_t);
+static int prefixlen(struct rt_ctx *, const char *);
+static void print_getmsg(struct rt_ctx *, struct rt_msghdr *, int);
+static void print_rtmsg(struct rt_ctx *, struct rt_msghdr *, size_t);
+static const char *routename(struct rt_ctx *, struct sockaddr *);
+static int rtmsg(struct rt_ctx *, int, int);
+static void set_metric(struct rt_ctx *, char *, int);
+static void sockaddr(char *, struct sockaddr *);
+static void sodump(sup, const char *);
+extern char *iso_ntoa(void);
static void usage(const char *) __dead2;
void
-usage(cp)
- const char *cp;
+usage(const char *cp)
{
- if (cp)
+ if (cp != NULL)
warnx("bad keyword: %s", cp);
(void) fprintf(stderr,
"usage: route [-dnqtv] command [[modifiers] args]\n");
@@ -199,9 +210,7 @@ main(int argc, char **argv, struct rt_ctx *c)
{
#else /* __rtems__ */
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char **argv)
{
struct rt_ctx *c;
#endif /* __rtems__ */
@@ -222,7 +231,7 @@ main(argc, argv)
#endif /* __rtems__ */
if (argc < 2)
- usage((char *)NULL);
+ usage(NULL);
while ((ch = getopt(argc, argv, "nqdtv")) != -1)
switch(ch) {
@@ -243,7 +252,7 @@ main(argc, argv)
break;
case '?':
default:
- usage((char *)NULL);
+ usage(NULL);
}
argc -= optind;
argv += optind;
@@ -256,7 +265,7 @@ main(argc, argv)
c->s = socket(PF_ROUTE, SOCK_RAW, 0);
if (c->s < 0)
err(EX_OSERR, "socket");
- if (*argv)
+ if (*argv != NULL)
switch (keyword(*argv)) {
case K_GET:
case K_SHOW:
@@ -287,18 +296,15 @@ main(argc, argv)
* Purge all entries in the routing tables not
* associated with network interfaces.
*/
-void
-flushroutes(c, argc, argv)
- struct rt_ctx *c;
- int argc;
- char *argv[];
+static void
+flushroutes(struct rt_ctx *c, int argc, char *argv[])
{
size_t needed;
int mib[6], rlen, seqno, count = 0;
char *buf, *next, *lim;
struct rt_msghdr *rtm;
- if (c->uid && !c->debugonly) {
+ if (c->uid != 0 && !c->debugonly) {
errx(EX_NOPERM, "must be root to alter routing table");
}
shutdown(c->s, SHUT_RD); /* Don't want to read back our messages */
@@ -338,7 +344,7 @@ retry:
errx(EX_OSERR, "malloc failed");
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
if (errno == ENOMEM && count++ < 10) {
- warnx("Routing table grew, retrying");
+ warnx("Routing table grew, retrying");
sleep(1);
free(buf);
goto retry;
@@ -355,7 +361,7 @@ retry:
print_rtmsg(c, rtm, rtm->rtm_msglen);
if ((rtm->rtm_flags & RTF_GATEWAY) == 0)
continue;
- if (c->af) {
+ if (c->af != 0) {
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
if (sa->sa_family != c->af)
@@ -383,21 +389,19 @@ retry:
else {
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
(void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ?
- routename(sa) : netname(c, sa));
+ routename(c, sa) : netname(c, sa));
sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
- (void) printf("%-20.20s ", routename(sa));
+ (void) printf("%-20.20s ", routename(c, sa));
(void) printf("done\n");
}
}
free(buf);
}
-const char *
-routename(c, sa)
- struct rt_ctx *c;
- struct sockaddr *sa;
+static const char *
+routename(struct rt_ctx *c, struct sockaddr *sa)
{
- char *cp;
+ const char *cp;
char atalk_buf[20];
struct hostent *hp;
int n;
@@ -420,20 +424,22 @@ routename(c, sa)
{ struct in_addr in;
in = ((struct sockaddr_in *)sa)->sin_addr;
- cp = 0;
+ cp = NULL;
if (in.s_addr == INADDR_ANY || sa->sa_len < 4)
cp = "default";
- if (cp == 0 && !c->nflag) {
+ if (cp == NULL && !c->nflag) {
hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
AF_INET);
- if (hp) {
- if ((cp = strchr(hp->h_name, '.')) &&
- !strcmp(cp + 1, c->domain))
- *cp = 0;
+ if (hp != NULL) {
+ char *cptr;
+ cptr = strchr(hp->h_name, '.');
+ if (cptr != NULL &&
+ strcmp(cptr + 1, c->domain) == 0)
+ *cptr = '\0';
cp = hp->h_name;
}
}
- if (cp) {
+ if (cp != NULL) {
strncpy(c->rt_line, cp, sizeof(c->rt_line) - 1);
c->rt_line[sizeof(c->rt_line) - 1] = '\0';
} else
@@ -454,7 +460,8 @@ routename(c, sa)
#ifdef __KAME__
if (sa->sa_len == sizeof(struct sockaddr_in6) &&
(IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
- IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr)) &&
sin6.sin6_scope_id == 0) {
sin6.sin6_scope_id =
ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
@@ -481,16 +488,17 @@ routename(c, sa)
return (link_ntoa((struct sockaddr_dl *)sa));
default:
- { u_short *s = (u_short *)sa;
- u_short *slim = s + ((sa->sa_len + 1) >> 1);
- char *cp = c->rt_line + sprintf(c->rt_line, "(%d)", sa->sa_family);
+ {
+ u_short *sp = (u_short *)sa;
+ u_short *splim = sp + ((sa->sa_len + 1) >> 1);
+ char *cps = c->rt_line + sprintf(c->rt_line, "(%d)", sa->sa_family);
char *cpe = c->rt_line + sizeof(c->rt_line);
- while (++s < slim && cp < cpe) /* start with sa->sa_data */
- if ((n = snprintf(cp, cpe - cp, " %x", *s)) > 0)
- cp += n;
+ while (++sp < splim && cps < cpe) /* start with sa->sa_data */
+ if ((n = snprintf(cps, cpe - cps, " %x", *sp)) > 0)
+ cps += n;
else
- *cp = '\0';
+ *cps = '\0';
break;
}
}
@@ -502,13 +510,11 @@ routename(c, sa)
* The address is assumed to be that of a net or subnet, not a host.
*/
const char *
-netname(c, sa)
- struct rt_ctx *c;
- struct sockaddr *sa;
+netname(struct rt_ctx *c, struct sockaddr *sa)
{
- char *cp = 0;
+ const char *cp = NULL;
char atalk_buf[20];
- struct netent *np = 0;
+ struct netent *np = NULL;
u_long net, mask;
u_long i;
int n, subnetshift;
@@ -539,17 +545,17 @@ netname(c, sa)
* Guess at the subnet mask, assuming reasonable
* width subnet fields.
*/
- while (in.s_addr &~ mask)
- mask = (long)mask >> subnetshift;
+ while (in.s_addr & ~mask)
+ mask |= mask >> subnetshift;
net = in.s_addr & mask;
while ((mask & 1) == 0)
mask >>= 1, net >>= 1;
np = getnetbyaddr(net, AF_INET);
- if (np)
+ if (np != NULL)
cp = np->n_name;
}
#define C(x) (unsigned)((x) & 0xff)
- if (cp)
+ if (cp != NULL)
strncpy(c->net_line, cp, sizeof(c->net_line));
else if ((in.s_addr & 0xffffff) == 0)
(void) sprintf(c->net_line, "%u", C(in.s_addr >> 24));
@@ -580,7 +586,8 @@ netname(c, sa)
#ifdef __KAME__
if (sa->sa_len == sizeof(struct sockaddr_in6) &&
(IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
- IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr)) &&
sin6.sin6_scope_id == 0) {
sin6.sin6_scope_id =
ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
@@ -608,27 +615,25 @@ netname(c, sa)
default:
- { u_short *s = (u_short *)sa->sa_data;
- u_short *slim = s + ((sa->sa_len + 1)>>1);
- char *cp = c->net_line + sprintf(c->net_line, "af %d:", sa->sa_family);
+ {
+ u_short *sp = (u_short *)sa->sa_data;
+ u_short *splim = sp + ((sa->sa_len + 1)>>1);
+ char *cps = c->net_line + sprintf(c->net_line, "af %d:", sa->sa_family);
char *cpe = c->net_line + sizeof(c->net_line);
- while (s < slim && cp < cpe)
- if ((n = snprintf(cp, cpe - cp, " %x", *s++)) > 0)
- cp += n;
+ while (sp < splim && cps < cpe)
+ if ((n = snprintf(cps, cpe - cps, " %x", *sp++)) > 0)
+ cps += n;
else
- *cp = '\0';
+ *cps = '\0';
break;
}
}
return (c->net_line);
}
-void
-set_metric(c, value, key)
- struct rt_ctx *c;
- char *value;
- int key;
+static void
+set_metric(struct rt_ctx *c, char *value, int key)
{
int flag = 0;
u_long noval, *valp = &noval;
@@ -653,18 +658,16 @@ set_metric(c, value, key)
*valp = atoi(value);
}
-void
-newroute(c, argc, argv)
- struct rt_ctx *c;
- int argc;
- char **argv;
+static void
+newroute(struct rt_ctx *c, int argc, char **argv)
{
- char *cmd, *dest = "", *gateway = "", *err;
+ char *cmd;
+ const char *dest = "", *gateway = "", *errmsg;
int ishost = 0, proxy = 0, ret, attempts, oerrno, flags = RTF_STATIC;
int key;
struct hostent *hp = 0;
- if (c->uid) {
+ if (c->uid != 0) {
errx(EX_NOPERM, "must be root to alter routing table");
}
cmd = argv[0];
@@ -741,33 +744,33 @@ newroute(c, argc, argv)
break;
case K_IFA:
if (!--argc)
- usage((char *)NULL);
+ usage(NULL);
(void) getaddr(c, RTA_IFA, *++argv, 0);
break;
case K_IFP:
if (!--argc)
- usage((char *)NULL);
+ usage(NULL);
(void) getaddr(c, RTA_IFP, *++argv, 0);
break;
case K_GENMASK:
if (!--argc)
- usage((char *)NULL);
+ usage(NULL);
(void) getaddr(c, RTA_GENMASK, *++argv, 0);
break;
case K_GATEWAY:
if (!--argc)
- usage((char *)NULL);
+ usage(NULL);
(void) getaddr(c, RTA_GATEWAY, *++argv, 0);
break;
case K_DST:
if (!--argc)
- usage((char *)NULL);
+ usage(NULL);
ishost = getaddr(c, RTA_DST, *++argv, &hp);
dest = *argv;
break;
case K_NETMASK:
if (!--argc)
- usage((char *)NULL);
+ usage(NULL);
(void) getaddr(c, RTA_NETMASK, *++argv, 0);
/* FALLTHROUGH */
case K_NET:
@@ -775,7 +778,7 @@ newroute(c, argc, argv)
break;
case K_PREFIXLEN:
if (!--argc)
- usage((char *)NULL);
+ usage(NULL);
if (prefixlen(c, *++argv) == -1) {
c->forcenet = 0;
ishost = 1;
@@ -794,7 +797,7 @@ newroute(c, argc, argv)
case K_RTTVAR:
case K_WEIGHT:
if (!--argc)
- usage((char *)NULL);
+ usage(NULL);
set_metric(c, *++argv, key);
break;
default:
@@ -818,9 +821,9 @@ newroute(c, argc, argv)
#ifdef INET6
if (c->af == AF_INET6) {
c->rtm_addrs &= ~RTA_NETMASK;
- memset((void *)&c->so_mask, 0, sizeof(c->so_mask));
+ memset((void *)&c->so_mask, 0, sizeof(c->so_mask));
}
-#endif
+#endif
}
if (c->forcenet)
ishost = 0;
@@ -839,10 +842,12 @@ newroute(c, argc, argv)
break;
if (errno != ENETUNREACH && errno != ESRCH)
break;
- if (c->af == AF_INET && *gateway && hp && hp->h_addr_list[1]) {
+ if (c->af == AF_INET && *gateway != '\0' &&
+ hp != NULL && hp->h_addr_list[1] != NULL) {
hp->h_addr_list++;
memmove(&c->so_gate.sin.sin_addr, hp->h_addr_list[0],
- MIN(hp->h_length, sizeof(c->so_gate.sin.sin_addr)));
+ MIN((size_t)hp->h_length,
+ sizeof(c->so_gate.sin.sin_addr)));
} else
break;
}
@@ -862,42 +867,39 @@ newroute(c, argc, argv)
} else {
switch (oerrno) {
case ESRCH:
- err = "not in table";
+ errmsg = "not in table";
break;
case EBUSY:
- err = "entry in use";
+ errmsg = "entry in use";
break;
case ENOBUFS:
- err = "not enough memory";
+ errmsg = "not enough memory";
break;
case EADDRINUSE:
/* handle recursion avoidance in rt_setgate() */
- err = "gateway uses the same route";
+ errmsg = "gateway uses the same route";
break;
case EEXIST:
- err = "route already in table";
+ errmsg = "route already in table";
break;
default:
- err = strerror(oerrno);
+ errmsg = strerror(oerrno);
break;
}
- (void) printf(": %s\n", err);
+ (void) printf(": %s\n", errmsg);
}
}
exit(ret != 0);
}
-void
-inet_makenetandmask(c, net, sin, bits)
- struct rt_ctx *c;
- u_long net, bits;
- struct sockaddr_in *sin;
+static void
+inet_makenetandmask(struct rt_ctx *c, u_long net, struct sockaddr_in *sin, u_long bits)
{
u_long addr, mask = 0;
char *cp;
c->rtm_addrs |= RTA_NETMASK;
- /*
+ /*
* XXX: This approach unable to handle 0.0.0.1/32 correctly
* as inet_network() converts 0.0.0.1 and 1 equally.
*/
@@ -910,7 +912,7 @@ inet_makenetandmask(c, net, sin, bits)
else
addr = net;
/*
- * If no /xx was specified we must cacluate the
+ * If no /xx was specified we must calculate the
* CIDR address.
*/
if ((bits == 0) && (addr != 0)) {
@@ -943,14 +945,11 @@ inet_makenetandmask(c, net, sin, bits)
* XXX the function may need more improvement...
*/
static int
-inet6_makenetandmask(c, sin6, plen)
- struct rt_ctx *c;
- struct sockaddr_in6 *sin6;
- char *plen;
+inet6_makenetandmask(struct rt_ctx *c, struct sockaddr_in6 *sin6, const char *plen)
{
struct in6_addr in6;
- if (!plen) {
+ if (plen == NULL) {
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
sin6->sin6_scope_id == 0) {
plen = "0";
@@ -963,11 +962,11 @@ inet6_makenetandmask(c, sin6, plen)
}
}
- if (!plen || strcmp(plen, "128") == 0)
- return 1;
+ if (plen == NULL || strcmp(plen, "128") == 0)
+ return (1);
c->rtm_addrs |= RTA_NETMASK;
- (void)prefixlen(c, plen);
- return 0;
+ prefixlen(c, plen);
+ return (0);
}
#endif
@@ -975,12 +974,8 @@ inet6_makenetandmask(c, sin6, plen)
* Interpret an argument as a network address of some kind,
* returning 1 if a host address, 0 if a network address.
*/
-int
-getaddr(c, which, s, hpp)
- struct rt_ctx *c;
- int which;
- char *s;
- struct hostent **hpp;
+static int
+getaddr(struct rt_ctx *c, int which, char *str, struct hostent **hpp)
{
sup su;
struct hostent *hp;
@@ -1008,17 +1003,17 @@ getaddr(c, which, s, hpp)
if (getifaddrs(&ifap))
err(1, "getifaddrs");
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr->sa_family != AF_LINK)
continue;
- if (strcmp(s, ifa->ifa_name))
+ if (strcmp(str, ifa->ifa_name) != 0)
continue;
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
}
/* If we found it, then use it */
- if (sdl) {
+ if (sdl != NULL) {
/*
* Copy is safe since we have a
* sockaddr_storage member in sockunion{}.
@@ -1028,7 +1023,7 @@ getaddr(c, which, s, hpp)
memcpy(&su->sdl, sdl, sdl->sdl_len);
}
freeifaddrs(ifap);
- if (sdl)
+ if (sdl != NULL)
return(1);
}
break;
@@ -1051,9 +1046,9 @@ getaddr(c, which, s, hpp)
}
su->sa.sa_len = c->aflen;
su->sa.sa_family = afamily; /* cases that don't want it have left already */
- if (strcmp(s, "default") == 0) {
+ if (strcmp(str, "default") == 0) {
/*
- * Default is net 0.0.0.0/0
+ * Default is net 0.0.0.0/0
*/
switch (which) {
case RTA_DST:
@@ -1061,7 +1056,7 @@ getaddr(c, which, s, hpp)
#if 0
bzero(su, sizeof(*su)); /* for readability */
#endif
- (void) getaddr(c, RTA_NETMASK, s, 0);
+ getaddr(c, RTA_NETMASK, str, 0);
break;
#if 0
case RTA_NETMASK:
@@ -1079,22 +1074,23 @@ getaddr(c, which, s, hpp)
int ecode;
q = NULL;
- if (which == RTA_DST && (q = strchr(s, '/')) != NULL)
+ if (which == RTA_DST && (q = strchr(str, '/')) != NULL)
*q = '\0';
memset(&hints, 0, sizeof(hints));
hints.ai_family = afamily; /*AF_INET6*/
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- ecode = getaddrinfo(s, NULL, &hints, &res);
+ ecode = getaddrinfo(str, NULL, &hints, &res);
if (ecode != 0 || res->ai_family != AF_INET6 ||
res->ai_addrlen != sizeof(su->sin6)) {
- (void) fprintf(stderr, "%s: %s\n", s,
+ (void) fprintf(stderr, "%s: %s\n", str,
gai_strerror(ecode));
exit(1);
}
memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
#ifdef __KAME__
if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) ||
- IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr)) &&
+ IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&su->sin6.sin6_addr)) &&
su->sin6.sin6_scope_id) {
*(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] =
htons(su->sin6.sin6_scope_id);
@@ -1111,19 +1107,19 @@ getaddr(c, which, s, hpp)
#endif /* INET6 */
case AF_APPLETALK:
- if (!atalk_aton(s, &su->sat.sat_addr))
- errx(EX_NOHOST, "bad address: %s", s);
+ if (!atalk_aton(str, &su->sat.sat_addr))
+ errx(EX_NOHOST, "bad address: %s", str);
c->rtm_addrs |= RTA_NETMASK;
return(c->forcehost || su->sat.sat_addr.s_node != 0);
case AF_LINK:
- link_addr(s, &su->sdl);
+ link_addr(str, &su->sdl);
return (1);
case PF_ROUTE:
su->sa.sa_len = sizeof(*su);
- sockaddr(s, &su->sa);
+ sockaddr(str, &su->sa);
return (1);
case AF_INET:
@@ -1135,10 +1131,10 @@ getaddr(c, which, s, hpp)
hpp = &hp;
*hpp = NULL;
- q = strchr(s,'/');
- if (q && which == RTA_DST) {
+ q = strchr(str,'/');
+ if (q != NULL && which == RTA_DST) {
*q = '\0';
- if ((val = inet_network(s)) != INADDR_NONE) {
+ if ((val = inet_network(str)) != INADDR_NONE) {
inet_makenetandmask(
c, val, &su->sin, strtoul(q+1, 0, 0));
return (0);
@@ -1146,7 +1142,7 @@ getaddr(c, which, s, hpp)
*q = '/';
}
if ((which != RTA_DST || c->forcenet == 0) &&
- inet_aton(s, &su->sin.sin_addr)) {
+ inet_aton(str, &su->sin.sin_addr)) {
val = su->sin.sin_addr.s_addr;
if (which != RTA_DST || c->forcehost ||
inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
@@ -1157,29 +1153,27 @@ getaddr(c, which, s, hpp)
}
}
if (which == RTA_DST && c->forcehost == 0 &&
- ((val = inet_network(s)) != INADDR_NONE ||
- ((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0))) {
+ ((val = inet_network(str)) != INADDR_NONE ||
+ ((np = getnetbyname(str)) != NULL && (val = np->n_net) != 0))) {
netdone:
inet_makenetandmask(c, val, &su->sin, 0);
return (0);
}
- hp = gethostbyname(s);
- if (hp) {
+ hp = gethostbyname(str);
+ if (hp != NULL) {
*hpp = hp;
su->sin.sin_family = hp->h_addrtype;
memmove((char *)&su->sin.sin_addr, hp->h_addr,
- MIN(hp->h_length, sizeof(su->sin.sin_addr)));
+ MIN((size_t)hp->h_length, sizeof(su->sin.sin_addr)));
return (1);
}
- errx(EX_NOHOST, "bad address: %s", s);
+ errx(EX_NOHOST, "bad address: %s", str);
}
-int
-prefixlen(c, s)
- struct rt_ctx *c;
- char *s;
+static int
+prefixlen(struct rt_ctx *c, const char *str)
{
- int len = atoi(s), q, r;
+ int len = atoi(str), q, r;
int max;
char *p;
@@ -1196,13 +1190,12 @@ prefixlen(c, s)
p = (char *)&c->so_mask.sin.sin_addr;
break;
default:
- (void) fprintf(stderr, "prefixlen not supported in this af\n");
+ fprintf(stderr, "prefixlen not supported in this af\n");
exit(1);
- /*NOTREACHED*/
}
if (len < 0 || max < len) {
- (void) fprintf(stderr, "%s: bad value\n", s);
+ fprintf(stderr, "%s: bad value\n", str);
exit(1);
}
@@ -1216,12 +1209,12 @@ prefixlen(c, s)
if (r > 0)
*((u_char *)p + q) = (0xff00 >> r) & 0xff;
if (len == max)
- return -1;
+ return (-1);
else
- return len;
+ return (len);
}
-void
+static void
interfaces(struct rt_ctx *c)
{
size_t needed;
@@ -1257,7 +1250,7 @@ retry2:
free(buf);
}
-void
+static void
monitor(struct rt_ctx *c)
{
int n;
@@ -1268,7 +1261,7 @@ monitor(struct rt_ctx *c)
interfaces(c);
exit(0);
}
- for(;;) {
+ for (;;) {
time_t now;
n = read(c->s, msg, 2048);
now = time(NULL);
@@ -1277,10 +1270,8 @@ monitor(struct rt_ctx *c)
}
}
-int
-rtmsg(c, cmd, flags)
- struct rt_ctx *c;
- int cmd, flags;
+static int
+rtmsg(struct rt_ctx *c, int cmd, int flags)
{
int rlen;
char *cp = c->m_rtmsg.m_space;
@@ -1348,9 +1339,8 @@ rtmsg(c, cmd, flags)
return (0);
}
-void
-mask_addr(c)
- struct rt_ctx *c;
+static void
+mask_addr(struct rt_ctx *c)
{
int olen = c->so_mask.sa.sa_len;
char *cp1 = olen + (char *)&c->so_mask, *cp2;
@@ -1399,7 +1389,7 @@ static const char *const msgtypes[] = {
"RTM_NEWMADDR: new multicast group membership on iface",
"RTM_DELMADDR: multicast group membership removed from iface",
"RTM_IFANNOUNCE: interface arrival/departure",
- 0,
+ "RTM_IEEE80211: IEEE 802.11 wireless event",
};
static const char metricnames[] =
@@ -1417,11 +1407,11 @@ static const char ifnetflags[] =
static const char addrnames[] =
"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";
-void
-print_rtmsg(c, rtm, msglen)
- struct rt_ctx *c;
- struct rt_msghdr *rtm;
- int msglen;
+static const char errfmt[] =
+"\n%s: truncated route message, only %zu bytes left\n";
+
+static void
+print_rtmsg(struct rt_ctx *c, struct rt_msghdr *rtm, size_t msglen)
{
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
@@ -1429,7 +1419,7 @@ print_rtmsg(c, rtm, msglen)
struct ifma_msghdr *ifmam;
#endif
struct if_announcemsghdr *ifan;
- char *state;
+ const char *state;
if (c->verbose == 0)
return;
@@ -1438,13 +1428,22 @@ print_rtmsg(c, rtm, msglen)
rtm->rtm_version);
return;
}
- if (msgtypes[rtm->rtm_type] != NULL)
+ if (rtm->rtm_type < sizeof(msgtypes) / sizeof(msgtypes[0]))
(void)printf("%s: ", msgtypes[rtm->rtm_type]);
else
- (void)printf("#%d: ", rtm->rtm_type);
+ (void)printf("unknown type %d: ", rtm->rtm_type);
(void)printf("len %d, ", rtm->rtm_msglen);
+
+#define REQUIRE(x) do { \
+ if (msglen < sizeof(x)) \
+ goto badlen; \
+ else \
+ msglen -= sizeof(x); \
+ } while (0)
+
switch (rtm->rtm_type) {
case RTM_IFINFO:
+ REQUIRE(struct if_msghdr);
ifm = (struct if_msghdr *)rtm;
(void) printf("if# %d, ", ifm->ifm_index);
switch (ifm->ifm_data.ifi_link_state) {
@@ -1460,23 +1459,26 @@ print_rtmsg(c, rtm, msglen)
}
(void) printf("link: %s, flags:", state);
bprintf(stdout, ifm->ifm_flags, ifnetflags);
- pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs);
+ pmsg_addrs(c, (char *)(ifm + 1), ifm->ifm_addrs, msglen);
break;
case RTM_NEWADDR:
case RTM_DELADDR:
+ REQUIRE(struct ifa_msghdr);
ifam = (struct ifa_msghdr *)rtm;
(void) printf("metric %d, flags:", ifam->ifam_metric);
bprintf(stdout, ifam->ifam_flags, routeflags);
- pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs);
+ pmsg_addrs(c, (char *)(ifam + 1), ifam->ifam_addrs, msglen);
break;
#ifdef RTM_NEWMADDR
case RTM_NEWMADDR:
case RTM_DELMADDR:
+ REQUIRE(struct ifma_msghdr);
ifmam = (struct ifma_msghdr *)rtm;
- pmsg_addrs((char *)(ifmam + 1), ifmam->ifmam_addrs);
+ pmsg_addrs(c, (char *)(ifmam + 1), ifmam->ifmam_addrs, msglen);
break;
#endif
case RTM_IFANNOUNCE:
+ REQUIRE(struct if_announcemsghdr);
ifan = (struct if_announcemsghdr *)rtm;
(void) printf("if# %d, what: ", ifan->ifan_index);
switch (ifan->ifan_what) {
@@ -1497,15 +1499,18 @@ print_rtmsg(c, rtm, msglen)
(void) printf("pid: %ld, seq %d, errno %d, flags:",
(long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
bprintf(stdout, rtm->rtm_flags, routeflags);
- pmsg_common(rtm);
+ pmsg_common(c, rtm, msglen);
}
+
+ return;
+
+badlen:
+ (void)printf(errfmt, __func__, msglen);
+#undef REQUIRE
}
-void
-print_getmsg(c, rtm, msglen)
- struct rt_ctx *c;
- struct rt_msghdr *rtm;
- int msglen;
+static void
+print_getmsg(struct rt_ctx *c, struct rt_msghdr *rtm, int msglen)
{
struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL;
struct sockaddr_dl *ifp = NULL;
@@ -1513,7 +1518,8 @@ print_getmsg(c, rtm, msglen)
char *cp;
int i;
- (void) printf(" route to: %s\n", routename(&c->so_dst));
+ (void) printf(" route to: %s\n",
+ routename(c, (struct sockaddr *)&c->so_dst));
if (rtm->rtm_version != RTM_VERSION) {
warnx("routing message version %d not understood",
rtm->rtm_version);
@@ -1554,16 +1560,16 @@ print_getmsg(c, rtm, msglen)
if (dst && mask)
mask->sa_family = dst->sa_family; /* XXX */
if (dst)
- (void)printf("destination: %s\n", routename(dst));
+ (void)printf("destination: %s\n", routename(c, dst));
if (mask) {
int savenflag = c->nflag;
c->nflag = 1;
- (void)printf(" mask: %s\n", routename(mask));
+ (void)printf(" mask: %s\n", routename(c, mask));
c->nflag = savenflag;
}
if (gate && rtm->rtm_flags & RTF_GATEWAY)
- (void)printf(" gateway: %s\n", routename(gate));
+ (void)printf(" gateway: %s\n", routename(c, gate));
if (ifp)
(void)printf(" interface: %.*s\n",
ifp->sdl_nlen, ifp->sdl_data);
@@ -1588,7 +1594,7 @@ print_getmsg(c, rtm, msglen)
#undef msec
#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
if (c->verbose)
- pmsg_common(rtm);
+ pmsg_common(c, rtm, msglen);
else if (rtm->rtm_addrs &~ RTA_IGN) {
(void) printf("sockaddrs: ");
bprintf(stdout, rtm->rtm_addrs, addrnames);
@@ -1597,21 +1603,22 @@ print_getmsg(c, rtm, msglen)
#undef RTA_IGN
}
-void
-pmsg_common(rtm)
- struct rt_msghdr *rtm;
+static void
+pmsg_common(struct rt_ctx *c, struct rt_msghdr *rtm, size_t msglen)
{
(void) printf("\nlocks: ");
bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
(void) printf(" inits: ");
bprintf(stdout, rtm->rtm_inits, metricnames);
- pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs);
+ if (msglen > sizeof(struct rt_msghdr))
+ pmsg_addrs(c, ((char *)(rtm + 1)), rtm->rtm_addrs,
+ msglen - sizeof(struct rt_msghdr));
+ else
+ (void) fflush(stdout);
}
-void
-pmsg_addrs(cp, addrs)
- char *cp;
- int addrs;
+static void
+pmsg_addrs(struct rt_ctx *c, char *cp, int addrs, size_t len)
{
struct sockaddr *sa;
int i;
@@ -1623,28 +1630,31 @@ pmsg_addrs(cp, addrs)
(void) printf("\nsockaddrs: ");
bprintf(stdout, addrs, addrnames);
(void) putchar('\n');
- for (i = 1; i; i <<= 1)
+ for (i = 1; i != 0; i <<= 1)
if (i & addrs) {
sa = (struct sockaddr *)cp;
- (void) printf(" %s", routename(sa));
+ if (len == 0 || len < SA_SIZE(sa)) {
+ (void) printf(errfmt, __func__, len);
+ break;
+ }
+ (void) printf(" %s", routename(c, sa));
+ len -= SA_SIZE(sa);
cp += SA_SIZE(sa);
}
(void) putchar('\n');
(void) fflush(stdout);
}
-void
-bprintf(fp, b, s)
- FILE *fp;
- int b;
- u_char *s;
+static void
+bprintf(FILE *fp, int b, const char *sstr)
{
+ const u_char *str = (const u_char *) sstr;
int i;
int gotsome = 0;
if (b == 0)
return;
- while ((i = *s++) != 0) {
+ while ((i = *str++) != 0) {
if (b & (1 << (i-1))) {
if (gotsome == 0)
i = '<';
@@ -1652,31 +1662,28 @@ bprintf(fp, b, s)
i = ',';
(void) putc(i, fp);
gotsome = 1;
- for (; (i = *s) > 32; s++)
+ for (; (i = *str) > 32; str++)
(void) putc(i, fp);
} else
- while (*s > 32)
- s++;
+ while (*str > 32)
+ str++;
}
if (gotsome)
(void) putc('>', fp);
}
int
-keyword(cp)
- char *cp;
+keyword(const char *cp)
{
const struct keytab *kt = keywords;
- while (kt->kt_cp && strcmp(kt->kt_cp, cp))
+ while (kt->kt_cp != NULL && strcmp(kt->kt_cp, cp) != 0)
kt++;
- return kt->kt_i;
+ return (kt->kt_i);
}
-void
-sodump(su, which)
- sup su;
- char *which;
+static void
+sodump(sup su, const char *which)
{
char atalk_buf[20];
@@ -1706,10 +1713,8 @@ sodump(su, which)
#define END (4*1)
#define DELIM (4*2)
-void
-sockaddr(addr, sa)
- char *addr;
- struct sockaddr *sa;
+static void
+sockaddr(char *addr, struct sockaddr *sa)
{
char *cp = (char *)sa;
int size = sa->sa_len;
@@ -1725,7 +1730,7 @@ sockaddr(addr, sa)
new = *addr - 'a' + 10;
} else if ((*addr >= 'A') && (*addr <= 'F')) {
new = *addr - 'A' + 10;
- } else if (*addr == 0)
+ } else if (*addr == '\0')
state |= END;
else
state |= DELIM;
@@ -1750,7 +1755,7 @@ sockaddr(addr, sa)
sa->sa_len = cp - (char *)sa;
}
-int
+static int
atalk_aton(const char *text, struct at_addr *addr)
{
u_int net, node;
@@ -1763,7 +1768,7 @@ atalk_aton(const char *text, struct at_addr *addr)
return(1);
}
-char *
+static char *
atalk_ntoa(struct at_addr at, char buf[20])
{
(void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node);
diff --git a/freebsd/sys/arm/arm/legacy.c b/freebsd/sys/arm/arm/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/arm/arm/legacy.c
+++ b/freebsd/sys/arm/arm/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/arm/include/machine/legacyvar.h b/freebsd/sys/arm/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/arm/include/machine/legacyvar.h
+++ b/freebsd/sys/arm/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/arm/pci/pci_bus.c b/freebsd/sys/arm/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/arm/pci/pci_bus.c
+++ b/freebsd/sys/arm/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/avr/avr/legacy.c b/freebsd/sys/avr/avr/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/avr/avr/legacy.c
+++ b/freebsd/sys/avr/avr/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/avr/include/machine/legacyvar.h b/freebsd/sys/avr/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/avr/include/machine/legacyvar.h
+++ b/freebsd/sys/avr/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/avr/pci/pci_bus.c b/freebsd/sys/avr/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/avr/pci/pci_bus.c
+++ b/freebsd/sys/avr/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/bfin/bfin/legacy.c b/freebsd/sys/bfin/bfin/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/bfin/bfin/legacy.c
+++ b/freebsd/sys/bfin/bfin/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/bfin/include/machine/legacyvar.h b/freebsd/sys/bfin/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/bfin/include/machine/legacyvar.h
+++ b/freebsd/sys/bfin/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/bfin/pci/pci_bus.c b/freebsd/sys/bfin/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/bfin/pci/pci_bus.c
+++ b/freebsd/sys/bfin/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/cam/ata/ata_all.h b/freebsd/sys/cam/ata/ata_all.h
index 2e838fdc..526fc194 100644
--- a/freebsd/sys/cam/ata/ata_all.h
+++ b/freebsd/sys/cam/ata/ata_all.h
@@ -35,6 +35,8 @@ struct ccb_ataio;
struct cam_periph;
union ccb;
+#define SID_DMA 0x10 /* Abuse inq_flags bit to track enabled DMA. */
+
struct ata_cmd {
u_int8_t flags; /* ATA command flags */
#define CAM_ATAIO_48BIT 0x01 /* Command has 48-bit format */
diff --git a/freebsd/sys/cam/cam.h b/freebsd/sys/cam/cam.h
index 5a58db6c..8ea1d04c 100644
--- a/freebsd/sys/cam/cam.h
+++ b/freebsd/sys/cam/cam.h
@@ -87,6 +87,7 @@ typedef struct {
#define CAM_PRIORITY_NORMAL ((CAM_RL_NORMAL << 8) + 0x80)
#define CAM_PRIORITY_NONE (u_int32_t)-1
#define CAM_PRIORITY_TO_RL(x) ((x) >> 8)
+#define CAM_RL_TO_PRIORITY(x) ((x) << 8)
u_int32_t generation;
int index;
#define CAM_UNQUEUED_INDEX -1
diff --git a/freebsd/sys/cam/cam_ccb.h b/freebsd/sys/cam/cam_ccb.h
index 89042942..3e85eacb 100644
--- a/freebsd/sys/cam/cam_ccb.h
+++ b/freebsd/sys/cam/cam_ccb.h
@@ -187,6 +187,11 @@ typedef enum {
/*
* Set SIM specific knob values.
*/
+
+ XPT_SCAN_TGT = 0x1E | XPT_FC_QUEUED | XPT_FC_USER_CCB
+ | XPT_FC_XPT_ONLY,
+ /* Scan Target */
+
/* HBA engine commands 0x20->0x2F */
XPT_ENG_INQ = 0x20 | XPT_FC_XPT_ONLY,
/* HBA engine feature inquiry */
@@ -251,6 +256,14 @@ typedef enum {
XPORT_ISCSI, /* iSCSI */
} cam_xport;
+#define XPORT_IS_ATA(t) ((t) == XPORT_ATA || (t) == XPORT_SATA)
+#define XPORT_IS_SCSI(t) ((t) != XPORT_UNKNOWN && \
+ (t) != XPORT_UNSPECIFIED && \
+ !XPORT_IS_ATA(t))
+#define XPORT_DEVSTAT_TYPE(t) (XPORT_IS_ATA(t) ? DEVSTAT_TYPE_IF_IDE : \
+ XPORT_IS_SCSI(t) ? DEVSTAT_TYPE_IF_SCSI : \
+ DEVSTAT_TYPE_IF_OTHER)
+
#define PROTO_VERSION_UNKNOWN (UINT_MAX - 1)
#define PROTO_VERSION_UNSPECIFIED UINT_MAX
#define XPORT_VERSION_UNKNOWN (UINT_MAX - 1)
@@ -808,6 +821,14 @@ struct ccb_trans_settings_scsi
#define CTS_SCSI_FLAGS_TAG_ENB 0x01
};
+struct ccb_trans_settings_ata
+{
+ u_int valid; /* Which fields to honor */
+#define CTS_ATA_VALID_TQ 0x01
+ u_int flags;
+#define CTS_ATA_FLAGS_TAG_ENB 0x01
+};
+
struct ccb_trans_settings_spi
{
u_int valid; /* Which fields to honor */
@@ -842,7 +863,7 @@ struct ccb_trans_settings_sas {
u_int32_t bitrate; /* Mbps */
};
-struct ccb_trans_settings_ata {
+struct ccb_trans_settings_pata {
u_int valid; /* Which fields to honor */
#define CTS_ATA_VALID_MODE 0x01
#define CTS_ATA_VALID_BYTECOUNT 0x02
@@ -869,9 +890,10 @@ struct ccb_trans_settings_sata {
u_int atapi; /* Length of ATAPI CDB */
u_int caps; /* Device and host SATA caps. */
#define CTS_SATA_CAPS_H 0x0000ffff
-#define CTS_SATA_CAPS_HH_PMREQ 0x00000001
-#define CTS_SATA_CAPS_HH_APST 0x00000002
-#define CTS_SATA_CAPS_HH_DMAAA 0x00000010 /* Auto-activation */
+#define CTS_SATA_CAPS_H_PMREQ 0x00000001
+#define CTS_SATA_CAPS_H_APST 0x00000002
+#define CTS_SATA_CAPS_H_DMAAA 0x00000010 /* Auto-activation */
+#define CTS_SATA_CAPS_H_AN 0x00000020 /* Async. notification */
#define CTS_SATA_CAPS_D 0xffff0000
#define CTS_SATA_CAPS_D_PMREQ 0x00010000
#define CTS_SATA_CAPS_D_APST 0x00020000
@@ -887,6 +909,7 @@ struct ccb_trans_settings {
u_int transport_version;
union {
u_int valid; /* Which fields to honor */
+ struct ccb_trans_settings_ata ata;
struct ccb_trans_settings_scsi scsi;
} proto_specific;
union {
@@ -894,7 +917,7 @@ struct ccb_trans_settings {
struct ccb_trans_settings_spi spi;
struct ccb_trans_settings_fc fc;
struct ccb_trans_settings_sas sas;
- struct ccb_trans_settings_ata ata;
+ struct ccb_trans_settings_pata ata;
struct ccb_trans_settings_sata sata;
} xport_specific;
};
diff --git a/freebsd/sys/cam/cam_debug.h b/freebsd/sys/cam/cam_debug.h
index 4b0fd245..37acd7dc 100644
--- a/freebsd/sys/cam/cam_debug.h
+++ b/freebsd/sys/cam/cam_debug.h
@@ -40,10 +40,39 @@ typedef enum {
CAM_DEBUG_SUBTRACE = 0x04, /* internal to routine flows */
CAM_DEBUG_CDB = 0x08, /* print out SCSI CDBs only */
CAM_DEBUG_XPT = 0x10, /* print out xpt scheduling */
- CAM_DEBUG_PERIPH = 0x20 /* print out peripheral calls */
+ CAM_DEBUG_PERIPH = 0x20, /* print out peripheral calls */
+ CAM_DEBUG_PROBE = 0x40 /* print out probe actions */
} cam_debug_flags;
-#if defined(CAMDEBUG) && defined(_KERNEL)
+#if defined(_KERNEL) && !defined(__rtems__)
+
+#ifndef CAM_DEBUG_FLAGS
+#define CAM_DEBUG_FLAGS CAM_DEBUG_NONE
+#endif
+
+#ifndef CAM_DEBUG_COMPILE
+#ifdef CAMDEBUG
+#define CAM_DEBUG_COMPILE (-1)
+#else
+#define CAM_DEBUG_COMPILE (CAM_DEBUG_INFO | CAM_DEBUG_CDB | \
+ CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | \
+ CAM_DEBUG_FLAGS)
+#endif
+#endif
+
+#ifndef CAM_DEBUG_BUS
+#define CAM_DEBUG_BUS (-1)
+#endif
+#ifndef CAM_DEBUG_TARGET
+#define CAM_DEBUG_TARGET (-1)
+#endif
+#ifndef CAM_DEBUG_LUN
+#define CAM_DEBUG_LUN (-1)
+#endif
+
+#ifndef CAM_DEBUG_DELAY
+#define CAM_DEBUG_DELAY 0
+#endif
/* Path we want to debug */
extern struct cam_path *cam_dpath;
@@ -51,37 +80,48 @@ extern struct cam_path *cam_dpath;
extern u_int32_t cam_dflags;
/* Printf delay value (to prevent scrolling) */
extern u_int32_t cam_debug_delay;
-
+
/* Debugging macros. */
#define CAM_DEBUGGED(path, flag) \
- ((cam_dflags & (flag)) \
+ (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \
&& (cam_dpath != NULL) \
&& (xpt_path_comp(cam_dpath, path) >= 0) \
&& (xpt_path_comp(cam_dpath, path) < 2))
+
#define CAM_DEBUG(path, flag, printfargs) \
- if ((cam_dflags & (flag)) \
+ if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \
&& (cam_dpath != NULL) \
&& (xpt_path_comp(cam_dpath, path) >= 0) \
&& (xpt_path_comp(cam_dpath, path) < 2)) { \
xpt_print_path(path); \
- printf printfargs; \
+ printf printfargs; \
if (cam_debug_delay != 0) \
DELAY(cam_debug_delay); \
}
+
#define CAM_DEBUG_PRINT(flag, printfargs) \
- if (cam_dflags & (flag)) { \
+ if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \
printf("cam_debug: "); \
- printf printfargs; \
+ printf printfargs; \
+ if (cam_debug_delay != 0) \
+ DELAY(cam_debug_delay); \
+ }
+
+#define CAM_DEBUG_PATH_PRINT(flag, path, printfargs) \
+ if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \
+ xpt_print(path, "cam_debug: "); \
+ printf printfargs; \
if (cam_debug_delay != 0) \
DELAY(cam_debug_delay); \
}
-#else /* !CAMDEBUG || !_KERNEL */
+#else /* !_KERNEL */
#define CAM_DEBUGGED(A, B) 0
#define CAM_DEBUG(A, B, C)
#define CAM_DEBUG_PRINT(A, B)
+#define CAM_DEBUG_PATH_PRINT(A, B, C)
-#endif /* CAMDEBUG && _KERNEL */
+#endif /* _KERNEL */
#endif /* _CAM_CAM_DEBUG_H */
diff --git a/freebsd/sys/cam/cam_periph.h b/freebsd/sys/cam/cam_periph.h
index 33e9f758..c68fc9ba 100644
--- a/freebsd/sys/cam/cam_periph.h
+++ b/freebsd/sys/cam/cam_periph.h
@@ -119,6 +119,7 @@ struct cam_periph {
#define CAM_PERIPH_NEW_DEV_FOUND 0x10
#define CAM_PERIPH_RECOVERY_INPROG 0x20
#define CAM_PERIPH_SENSE_INPROG 0x40
+#define CAM_PERIPH_FREE 0x80
u_int32_t immediate_priority;
u_int32_t refcount;
SLIST_HEAD(, ccb_hdr) ccb_list; /* For "immediate" requests */
@@ -145,6 +146,7 @@ struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
cam_status cam_periph_acquire(struct cam_periph *periph);
void cam_periph_release(struct cam_periph *periph);
void cam_periph_release_locked(struct cam_periph *periph);
+void cam_periph_release_locked_buses(struct cam_periph *periph);
int cam_periph_hold(struct cam_periph *periph, int priority);
void cam_periph_unhold(struct cam_periph *periph);
void cam_periph_invalidate(struct cam_periph *periph);
diff --git a/freebsd/sys/cam/cam_sim.h b/freebsd/sys/cam/cam_sim.h
index 6b5a496f..ce6b38fc 100644
--- a/freebsd/sys/cam/cam_sim.h
+++ b/freebsd/sys/cam/cam_sim.h
@@ -140,7 +140,9 @@ struct cam_sim {
u_int32_t flags;
#define CAM_SIM_REL_TIMEOUT_PENDING 0x01
#define CAM_SIM_MPSAFE 0x02
-#define CAM_SIM_ON_DONEQ 0x04
+#define CAM_SIM_ON_DONEQ 0x04
+#define CAM_SIM_POLLED 0x08
+#define CAM_SIM_BATCH 0x10
struct callout callout;
struct cam_devq *devq; /* Device Queue to use for this SIM */
int refcount; /* References to the SIM. */
diff --git a/freebsd/sys/cam/cam_xpt.h b/freebsd/sys/cam/cam_xpt.h
index 61a7f3f0..c716a6ec 100644
--- a/freebsd/sys/cam/cam_xpt.h
+++ b/freebsd/sys/cam/cam_xpt.h
@@ -63,28 +63,6 @@ struct async_node {
SLIST_HEAD(async_list, async_node);
SLIST_HEAD(periph_list, cam_periph);
-#if defined(CAM_DEBUG_FLAGS) && !defined(CAMDEBUG)
-#error "You must have options CAMDEBUG to use options CAM_DEBUG_FLAGS"
-#endif
-
-/*
- * In order to enable the CAM_DEBUG_* options, the user must have CAMDEBUG
- * enabled. Also, the user must have either none, or all of CAM_DEBUG_BUS,
- * CAM_DEBUG_TARGET, and CAM_DEBUG_LUN specified.
- */
-#if defined(CAM_DEBUG_BUS) || defined(CAM_DEBUG_TARGET) \
- || defined(CAM_DEBUG_LUN)
-#ifdef CAMDEBUG
-#if !defined(CAM_DEBUG_BUS) || !defined(CAM_DEBUG_TARGET) \
- || !defined(CAM_DEBUG_LUN)
-#error "You must define all or none of CAM_DEBUG_BUS, CAM_DEBUG_TARGET \
- and CAM_DEBUG_LUN"
-#endif /* !CAM_DEBUG_BUS || !CAM_DEBUG_TARGET || !CAM_DEBUG_LUN */
-#else /* !CAMDEBUG */
-#error "You must use options CAMDEBUG if you use the CAM_DEBUG_* options"
-#endif /* CAMDEBUG */
-#endif /* CAM_DEBUG_BUS || CAM_DEBUG_TARGET || CAM_DEBUG_LUN */
-
void xpt_action(union ccb *new_ccb);
void xpt_action_default(union ccb *new_ccb);
union ccb *xpt_alloc_ccb(void);
@@ -104,6 +82,9 @@ cam_status xpt_create_path_unlocked(struct cam_path **new_path_ptr,
path_id_t path_id,
target_id_t target_id, lun_id_t lun_id);
void xpt_free_path(struct cam_path *path);
+void xpt_path_counts(struct cam_path *path, uint32_t *bus_ref,
+ uint32_t *periph_ref, uint32_t *target_ref,
+ uint32_t *device_ref);
int xpt_path_comp(struct cam_path *path1,
struct cam_path *path2);
void xpt_print_path(struct cam_path *path);
@@ -113,6 +94,7 @@ int xpt_path_string(struct cam_path *path, char *str,
path_id_t xpt_path_path_id(struct cam_path *path);
target_id_t xpt_path_target_id(struct cam_path *path);
lun_id_t xpt_path_lun_id(struct cam_path *path);
+int xpt_path_legacy_ata_id(struct cam_path *path);
struct cam_sim *xpt_path_sim(struct cam_path *path);
struct cam_periph *xpt_path_periph(struct cam_path *path);
void xpt_async(u_int32_t async_code, struct cam_path *path,
@@ -135,4 +117,3 @@ void xpt_release_path(struct cam_path *path);
#endif /* _KERNEL */
#endif /* _CAM_CAM_XPT_H */
-
diff --git a/freebsd/sys/cam/cam_xpt_sim.h b/freebsd/sys/cam/cam_xpt_sim.h
index 323f786c..67b895f2 100644
--- a/freebsd/sys/cam/cam_xpt_sim.h
+++ b/freebsd/sys/cam/cam_xpt_sim.h
@@ -51,6 +51,8 @@ void xpt_release_devq_rl(struct cam_path *path, cam_rl rl,
u_int count, int run_queue);
int xpt_sim_opened(struct cam_sim *sim);
void xpt_done(union ccb *done_ccb);
+void xpt_batch_start(struct cam_sim *sim);
+void xpt_batch_done(struct cam_sim *sim);
#endif
#endif /* _CAM_CAM_XPT_SIM_H */
diff --git a/freebsd/sys/cam/scsi/scsi_all.c b/freebsd/sys/cam/scsi/scsi_all.c
index 324a8e3a..bf002dbe 100644
--- a/freebsd/sys/cam/scsi/scsi_all.c
+++ b/freebsd/sys/cam/scsi/scsi_all.c
@@ -760,7 +760,7 @@ static struct asc_table_entry asc_table[] = {
*
* SCSI ASC/ASCQ Assignments
* Numeric Sorted Listing
- * as of 7/29/08
+ * as of 5/20/12
*
* D - DIRECT ACCESS DEVICE (SBC-2) device column key
* .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
@@ -846,6 +846,12 @@ static struct asc_table_entry asc_table[] = {
/* DT R MAEBKV */
{ SST(0x00, 0x1E, SS_RDEF, /* XXX TBD */
"Conflicting SA creation request") },
+ /* DT B */
+ { SST(0x00, 0x1F, SS_RDEF, /* XXX TBD */
+ "Logical unit transitioning to another power condition") },
+ /* DT P B */
+ { SST(0x00, 0x20, SS_RDEF, /* XXX TBD */
+ "Extended copy information available") },
/* D W O BK */
{ SST(0x01, 0x00, SS_RDEF,
"No index/sector signal") },
@@ -915,6 +921,33 @@ static struct asc_table_entry asc_table[] = {
/* DT R MAEBKV */
{ SST(0x04, 0x13, SS_RDEF, /* XXX TBD */
"Logical unit not ready, SA creation in progress") },
+ /* D B */
+ { SST(0x04, 0x14, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, space allocation in progress") },
+ /* M */
+ { SST(0x04, 0x15, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, robotics disabled") },
+ /* M */
+ { SST(0x04, 0x16, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, configuration required") },
+ /* M */
+ { SST(0x04, 0x17, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, calibration required") },
+ /* M */
+ { SST(0x04, 0x18, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, a door is open") },
+ /* M */
+ { SST(0x04, 0x19, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, operating in sequential mode") },
+ /* DT B */
+ { SST(0x04, 0x1A, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, START/STOP UNIT command in progress") },
+ /* D B */
+ { SST(0x04, 0x1B, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, sanitize in progress") },
+ /* DT MAEB */
+ { SST(0x04, 0x1C, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, additional power use not yet granted") },
/* DTL WROMAEBKVF */
{ SST(0x05, 0x00, SS_RDEF,
"Logical unit does not respond to selection") },
@@ -981,6 +1014,12 @@ static struct asc_table_entry asc_table[] = {
/* DTLPWROMAEBKVF */
{ SST(0x0B, 0x07, SS_RDEF, /* XXX TBD */
"Warning - degraded power to non-volatile cache") },
+ /* DTLPWROMAEBKVF */
+ { SST(0x0B, 0x08, SS_RDEF, /* XXX TBD */
+ "Warning - power loss expected") },
+ /* D */
+ { SST(0x0B, 0x09, SS_RDEF, /* XXX TBD */
+ "Warning - device statistics notification available") },
/* T R */
{ SST(0x0C, 0x00, SS_RDEF,
"Write error") },
@@ -1023,6 +1062,9 @@ static struct asc_table_entry asc_table[] = {
/* DTLPWRO AEBKVF */
{ SST(0x0C, 0x0D, SS_RDEF, /* XXX TBD */
"Write error - not enough unsolicited data") },
+ /* DT W O BK */
+ { SST(0x0C, 0x0E, SS_RDEF, /* XXX TBD */
+ "Multiple write errors") },
/* R */
{ SST(0x0C, 0x0F, SS_RDEF, /* XXX TBD */
"Defects in error window") },
@@ -1068,6 +1110,12 @@ static struct asc_table_entry asc_table[] = {
/* DT W O */
{ SST(0x10, 0x03, SS_RDEF, /* XXX TBD */
"Logical block reference tag check failed") },
+ /* T */
+ { SST(0x10, 0x04, SS_RDEF, /* XXX TBD */
+ "Logical block protection error on recovered buffer data") },
+ /* T */
+ { SST(0x10, 0x05, SS_RDEF, /* XXX TBD */
+ "Logical block protection method error") },
/* DT WRO BK */
{ SST(0x11, 0x00, SS_RDEF,
"Unrecovered read error") },
@@ -1272,6 +1320,9 @@ static struct asc_table_entry asc_table[] = {
/* DT WRO BK */
{ SST(0x1D, 0x00, SS_FATAL,
"Miscompare during verify operation") },
+ /* D B */
+ { SST(0x1D, 0x01, SS_RDEF, /* XXX TBD */
+ "Miscomparable verify of unmapped LBA") },
/* D W O BK */
{ SST(0x1E, 0x00, SS_NOP | SSQ_PRINT_SENSE,
"Recovered ID with ECC correction") },
@@ -1314,6 +1365,9 @@ static struct asc_table_entry asc_table[] = {
/* DT PWROMAEBK */
{ SST(0x20, 0x0B, SS_RDEF, /* XXX TBD */
"Access denied - ACL LUN conflict") },
+ /* T */
+ { SST(0x20, 0x0C, SS_FATAL | EINVAL,
+ "Illegal command when not in append-only mode") },
/* DT WRO BK */
{ SST(0x21, 0x00, SS_FATAL | EINVAL,
"Logical block address out of range") },
@@ -1329,6 +1383,39 @@ static struct asc_table_entry asc_table[] = {
/* D */
{ SST(0x22, 0x00, SS_FATAL | EINVAL,
"Illegal function (use 20 00, 24 00, or 26 00)") },
+ /* DT P B */
+ { SST(0x23, 0x00, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, cause not reportable") },
+ /* DT P B */
+ { SST(0x23, 0x01, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, unsupported token type") },
+ /* DT P B */
+ { SST(0x23, 0x02, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, remote token usage not supported") },
+ /* DT P B */
+ { SST(0x23, 0x03, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, remote ROD token creation not supported") },
+ /* DT P B */
+ { SST(0x23, 0x04, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token unknown") },
+ /* DT P B */
+ { SST(0x23, 0x05, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token corrupt") },
+ /* DT P B */
+ { SST(0x23, 0x06, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token revoked") },
+ /* DT P B */
+ { SST(0x23, 0x07, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token expired") },
+ /* DT P B */
+ { SST(0x23, 0x08, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token cancelled") },
+ /* DT P B */
+ { SST(0x23, 0x09, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token deleted") },
+ /* DT P B */
+ { SST(0x23, 0x0A, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, invalid token length") },
/* DTLPWROMAEBKVF */
{ SST(0x24, 0x00, SS_FATAL | EINVAL,
"Invalid field in CDB") },
@@ -1437,6 +1524,9 @@ static struct asc_table_entry asc_table[] = {
/* R F */
{ SST(0x27, 0x06, SS_RDEF, /* XXX TBD */
"Conditional write protect") },
+ /* D B */
+ { SST(0x27, 0x07, SS_RDEF, /* XXX TBD */
+ "Space allocation failed write protect") },
/* DTLPWROMAEBKVF */
{ SST(0x28, 0x00, SS_FATAL | ENXIO,
"Not ready to ready change, medium may have changed") },
@@ -1535,6 +1625,9 @@ static struct asc_table_entry asc_table[] = {
/* DT R MAEBKV */
{ SST(0x2A, 0x14, SS_RDEF, /* XXX TBD */
"SA creation capabilities data has changed") },
+ /* T M V */
+ { SST(0x2A, 0x15, SS_RDEF, /* XXX TBD */
+ "Medium removal prevention preempted") },
/* DTLPWRO K */
{ SST(0x2B, 0x00, SS_RDEF,
"Copy cannot execute since host cannot disconnect") },
@@ -1574,6 +1667,9 @@ static struct asc_table_entry asc_table[] = {
/* T */
{ SST(0x2C, 0x0B, SS_RDEF, /* XXX TBD */
"Not reserved") },
+ /* D */
+ { SST(0x2C, 0x0C, SS_RDEF, /* XXX TBD */
+ "ORWRITE generation does not match") },
/* T */
{ SST(0x2D, 0x00, SS_RDEF,
"Overwrite error on update in place") },
@@ -1637,6 +1733,9 @@ static struct asc_table_entry asc_table[] = {
/* M */
{ SST(0x30, 0x12, SS_RDEF, /* XXX TBD */
"Incompatible volume qualifier") },
+ /* M */
+ { SST(0x30, 0x13, SS_RDEF, /* XXX TBD */
+ "Cleaning volume expired") },
/* DT WRO BK */
{ SST(0x31, 0x00, SS_RDEF,
"Medium format corrupted") },
@@ -1646,6 +1745,9 @@ static struct asc_table_entry asc_table[] = {
/* R */
{ SST(0x31, 0x02, SS_RDEF, /* XXX TBD */
"Zoned formatting failed due to spare linking") },
+ /* D B */
+ { SST(0x31, 0x03, SS_RDEF, /* XXX TBD */
+ "SANITIZE command failed") },
/* D W O BK */
{ SST(0x32, 0x00, SS_RDEF,
"No defect spare location available") },
@@ -1694,6 +1796,9 @@ static struct asc_table_entry asc_table[] = {
/* B */
{ SST(0x38, 0x06, SS_RDEF, /* XXX TBD */
"ESN - device busy class event") },
+ /* D */
+ { SST(0x38, 0x07, SS_RDEF, /* XXX TBD */
+ "Thin provisioning soft threshold reached") },
/* DTL WROMAE K */
{ SST(0x39, 0x00, SS_RDEF,
"Saving parameters not supported") },
@@ -1793,6 +1898,9 @@ static struct asc_table_entry asc_table[] = {
/* M */
{ SST(0x3B, 0x1B, SS_RDEF, /* XXX TBD */
"Data transfer device inserted") },
+ /* T */
+ { SST(0x3B, 0x1C, SS_RDEF, /* XXX TBD */
+ "Too many logical objects on partition to support operation") },
/* DTLPWROMAE K */
{ SST(0x3D, 0x00, SS_RDEF,
"Invalid bits in IDENTIFY message") },
@@ -1896,6 +2004,9 @@ static struct asc_table_entry asc_table[] = {
/* DTLPWROMAEBKVF */
{ SST(0x44, 0x00, SS_RDEF,
"Internal target failure") },
+ /* DT P MAEBKVF */
+ { SST(0x44, 0x01, SS_RDEF, /* XXX TBD */
+ "Persistent reservation information lost") },
/* DT B */
{ SST(0x44, 0x71, SS_RDEF, /* XXX TBD */
"ATA device failed set features") },
@@ -1959,6 +2070,27 @@ static struct asc_table_entry asc_table[] = {
/* DT PWROMAEBK */
{ SST(0x4B, 0x06, SS_RDEF, /* XXX TBD */
"Initiator response timeout") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x07, SS_RDEF, /* XXX TBD */
+ "Connection lost") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x08, SS_RDEF, /* XXX TBD */
+ "Data-in buffer overflow - data buffer size") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x09, SS_RDEF, /* XXX TBD */
+ "Data-in buffer overflow - data buffer descriptor area") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x0A, SS_RDEF, /* XXX TBD */
+ "Data-in buffer error") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x0B, SS_RDEF, /* XXX TBD */
+ "Data-out buffer overflow - data buffer size") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x0C, SS_RDEF, /* XXX TBD */
+ "Data-out buffer overflow - data buffer descriptor area") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x0D, SS_RDEF, /* XXX TBD */
+ "Data-out buffer error") },
/* DTLPWROMAEBKVF */
{ SST(0x4C, 0x00, SS_RDEF,
"Logical unit failed self-configuration") },
@@ -2004,6 +2136,18 @@ static struct asc_table_entry asc_table[] = {
/* T */
{ SST(0x53, 0x04, SS_RDEF, /* XXX TBD */
"Medium thread or unthread failure") },
+ /* M */
+ { SST(0x53, 0x05, SS_RDEF, /* XXX TBD */
+ "Volume identifier invalid") },
+ /* T */
+ { SST(0x53, 0x06, SS_RDEF, /* XXX TBD */
+ "Volume identifier missing") },
+ /* M */
+ { SST(0x53, 0x07, SS_RDEF, /* XXX TBD */
+ "Duplicate volume identifier") },
+ /* M */
+ { SST(0x53, 0x08, SS_RDEF, /* XXX TBD */
+ "Element status unknown") },
/* P */
{ SST(0x54, 0x00, SS_RDEF,
"SCSI to host system interface failure") },
@@ -2040,6 +2184,15 @@ static struct asc_table_entry asc_table[] = {
/* M */
{ SST(0x55, 0x0A, SS_RDEF, /* XXX TBD */
"Data currently unavailable") },
+ /* DTLPWROMAEBKVF */
+ { SST(0x55, 0x0B, SS_RDEF, /* XXX TBD */
+ "Insufficient power for operation") },
+ /* DT P B */
+ { SST(0x55, 0x0C, SS_RDEF, /* XXX TBD */
+ "Insufficient resources to create ROD") },
+ /* DT P B */
+ { SST(0x55, 0x0D, SS_RDEF, /* XXX TBD */
+ "Insufficient resources to create ROD token") },
/* R */
{ SST(0x57, 0x00, SS_RDEF,
"Unable to recover table-of-contents") },
@@ -2346,6 +2499,24 @@ static struct asc_table_entry asc_table[] = {
/* DTLPWRO A K */
{ SST(0x5E, 0x04, SS_RDEF,
"Standby condition activated by command") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x05, SS_RDEF,
+ "Idle-B condition activated by timer") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x06, SS_RDEF,
+ "Idle-B condition activated by command") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x07, SS_RDEF,
+ "Idle-C condition activated by timer") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x08, SS_RDEF,
+ "Idle-C condition activated by command") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x09, SS_RDEF,
+ "Standby-Y condition activated by timer") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x0A, SS_RDEF,
+ "Standby-Y condition activated by command") },
/* B */
{ SST(0x5E, 0x41, SS_RDEF, /* XXX TBD */
"Power state change to active") },
@@ -3044,6 +3215,10 @@ scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio,
sizeof(cdb_str)));
}
+#ifdef _KERNEL
+ xpt_free_ccb((union ccb *)cgd);
+#endif
+
return(0);
}
diff --git a/freebsd/sys/cam/scsi/scsi_all.h b/freebsd/sys/cam/scsi/scsi_all.h
index cddf4f9f..f6608056 100644
--- a/freebsd/sys/cam/scsi/scsi_all.h
+++ b/freebsd/sys/cam/scsi/scsi_all.h
@@ -611,6 +611,7 @@ struct ata_pass_16 {
#define READ_12 0xA8
#define WRITE_12 0xAA
#define READ_ELEMENT_STATUS 0xB8
+#define READ_CD 0xBE
/* Maintenance In Service Action Codes */
#define REPORT_IDENTIFYING_INFRMATION 0x05
@@ -846,6 +847,17 @@ struct scsi_read_capacity_data_long
{
uint8_t addr[8];
uint8_t length[4];
+#define SRC16_PROT_EN 0x01
+#define SRC16_P_TYPE 0x0e
+ uint8_t prot;
+#define SRC16_LBPPBE 0x0f
+#define SRC16_PI_EXPONENT 0xf0
+#define SRC16_PI_EXPONENT_SHIFT 4
+ uint8_t prot_lbppbe;
+#define SRC16_LALBA 0x3fff
+#define SRC16_LBPRZ 0x4000
+#define SRC16_LBPME 0x8000
+ uint8_t lalba_lbp[2];
};
struct scsi_report_luns
@@ -1123,12 +1135,6 @@ int scsi_sense_sbuf(struct ccb_scsiio *csio, struct sbuf *sb,
char * scsi_sense_string(struct ccb_scsiio *csio,
char *str, int str_len);
void scsi_sense_print(struct ccb_scsiio *csio);
-int scsi_interpret_sense(union ccb *ccb,
- u_int32_t sense_flags,
- u_int32_t *relsim_flags,
- u_int32_t *reduction,
- u_int32_t *timeout,
- scsi_sense_action error_action);
#else /* _KERNEL */
int scsi_command_string(struct cam_device *device,
struct ccb_scsiio *csio, struct sbuf *sb);
@@ -1140,13 +1146,6 @@ char * scsi_sense_string(struct cam_device *device,
char *str, int str_len);
void scsi_sense_print(struct cam_device *device,
struct ccb_scsiio *csio, FILE *ofile);
-int scsi_interpret_sense(struct cam_device *device,
- union ccb *ccb,
- u_int32_t sense_flags,
- u_int32_t *relsim_flags,
- u_int32_t *reduction,
- u_int32_t *timeout,
- scsi_sense_action error_action);
#endif /* _KERNEL */
#define SF_RETRY_UA 0x01
diff --git a/freebsd/sys/contrib/pf/net/pf.c b/freebsd/sys/contrib/pf/net/pf.c
index 8070caa4..0f80c4d7 100644
--- a/freebsd/sys/contrib/pf/net/pf.c
+++ b/freebsd/sys/contrib/pf/net/pf.c
@@ -3209,11 +3209,7 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
dst->sin_len = sizeof(*dst);
dst->sin_addr = addr->v4;
#ifdef __FreeBSD__
-#ifdef RTF_PRCLONING
- rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING));
-#else /* !RTF_PRCLONING */
- in_rtalloc_ign(&ro, 0, 0);
-#endif
+ in_rtalloc_ign(&ro, 0, RT_DEFAULT_FIB);
#else /* ! __FreeBSD__ */
rtalloc_noclone(&ro, NO_CLONING);
#endif
@@ -3229,12 +3225,7 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
dst6->sin6_len = sizeof(*dst6);
dst6->sin6_addr = addr->v6;
#ifdef __FreeBSD__
-#ifdef RTF_PRCLONING
- rtalloc_ign((struct route *)&ro6,
- (RTF_CLONING | RTF_PRCLONING));
-#else /* !RTF_PRCLONING */
- rtalloc_ign((struct route *)&ro6, 0);
-#endif
+ in6_rtalloc_ign(&ro6, 0, RT_DEFAULT_FIB);
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro6, NO_CLONING);
#endif
@@ -6146,9 +6137,11 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
#ifdef __FreeBSD__
/* XXX MRT not always INET */ /* stick with table 0 though */
if (af == AF_INET)
- in_rtalloc_ign((struct route *)&ro, 0, 0);
+ in_rtalloc_ign((struct route *)&ro, 0, RT_DEFAULT_FIB);
+#ifdef INET6
else
- rtalloc_ign((struct route *)&ro, 0);
+ in6_rtalloc_ign(&ro, 0, RT_DEFAULT_FIB);
+#endif
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro, NO_CLONING);
#endif
@@ -6224,14 +6217,12 @@ pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
}
#ifdef __FreeBSD__
-# ifdef RTF_PRCLONING
- rtalloc_ign((struct route *)&ro, (RTF_CLONING|RTF_PRCLONING));
-# else /* !RTF_PRCLONING */
if (af == AF_INET)
- in_rtalloc_ign((struct route *)&ro, 0, 0);
+ in_rtalloc_ign((struct route *)&ro, 0, RT_DEFAULT_FIB);
+#ifdef INET6
else
- rtalloc_ign((struct route *)&ro, 0);
-# endif
+ in6_rtalloc_ign(&ro, 0, RT_DEFAULT_FIB);
+#endif
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro, NO_CLONING);
#endif
diff --git a/freebsd/sys/contrib/pf/net/pf_ioctl.c b/freebsd/sys/contrib/pf/net/pf_ioctl.c
index 24f41d36..95578f68 100644
--- a/freebsd/sys/contrib/pf/net/pf_ioctl.c
+++ b/freebsd/sys/contrib/pf/net/pf_ioctl.c
@@ -1538,7 +1538,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
#ifdef __FreeBSD__ /* ROUTING */
- if (rule->rtableid > 0 && rule->rtableid > rt_numfibs)
+ if (rule->rtableid > 0 && rule->rtableid >= rt_numfibs)
#else
if (rule->rtableid > 0 && !rtable_exists(rule->rtableid))
#endif
@@ -1806,7 +1806,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (newrule->rtableid > 0 &&
#ifdef __FreeBSD__ /* ROUTING */
- newrule->rtableid > rt_numfibs)
+ newrule->rtableid >= rt_numfibs)
#else
!rtable_exists(newrule->rtableid))
#endif
diff --git a/freebsd/sys/crypto/sha2/sha2.c b/freebsd/sys/crypto/sha2/sha2.c
index c5330f31..32f4bca6 100644
--- a/freebsd/sys/crypto/sha2/sha2.c
+++ b/freebsd/sys/crypto/sha2/sha2.c
@@ -208,9 +208,9 @@ typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
* library -- they are intended for private internal visibility/use
* only.
*/
-void SHA512_Last(SHA512_CTX*);
-void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
-void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
+static void SHA512_Last(SHA512_CTX*);
+static void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
+static void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
@@ -368,7 +368,7 @@ void SHA256_Init(SHA256_CTX* context) {
(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
j++
-void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+static void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
sha2_word32 T1, *W256;
int j;
@@ -426,7 +426,7 @@ void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
#else /* SHA2_UNROLL_TRANSFORM */
-void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+static void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
sha2_word32 T1, T2, *W256;
int j;
@@ -695,7 +695,7 @@ void SHA512_Init(SHA512_CTX* context) {
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
j++
-void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+static void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
sha2_word64 T1, *W512 = (sha2_word64*)context->buffer;
int j;
@@ -750,7 +750,7 @@ void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
#else /* SHA2_UNROLL_TRANSFORM */
-void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+static void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
sha2_word64 T1 = 0, T2 = 0, *W512 = (sha2_word64*)context->buffer;
int j;
@@ -876,7 +876,7 @@ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
usedspace = freespace = 0;
}
-void SHA512_Last(SHA512_CTX* context) {
+static void SHA512_Last(SHA512_CTX* context) {
unsigned int usedspace;
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
diff --git a/freebsd/sys/dev/bce/if_bce.c b/freebsd/sys/dev/bce/if_bce.c
index ab8c938e..313a1bc8 100644
--- a/freebsd/sys/dev/bce/if_bce.c
+++ b/freebsd/sys/dev/bce/if_bce.c
@@ -91,19 +91,13 @@ __FBSDID("$FreeBSD$");
#endif
/****************************************************************************/
-/* BCE Build Time Options */
-/****************************************************************************/
-/* #define BCE_NVRAM_WRITE_SUPPORT 1 */
-
-
-/****************************************************************************/
/* PCI Device ID Table */
/* */
/* Used by bce_probe() to identify the devices supported by this driver. */
/****************************************************************************/
#define BCE_DEVDESC_MAX 64
-static struct bce_type bce_devs[] = {
+static const struct bce_type bce_devs[] = {
/* BCM5706C Controllers and OEM boards. */
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3101,
"HP NC370T Multifunction Gigabit Server Adapter" },
@@ -169,7 +163,7 @@ static struct bce_type bce_devs[] = {
/****************************************************************************/
/* Supported Flash NVRAM device data. */
/****************************************************************************/
-static struct flash_spec flash_table[] =
+static const struct flash_spec flash_table[] =
{
#define BUFFERED_FLAGS (BCE_NV_BUFFERED | BCE_NV_TRANSLATE)
#define NONBUFFERED_FLAGS (BCE_NV_WREN)
@@ -266,7 +260,7 @@ static struct flash_spec flash_table[] =
* logical-to-physical mapping is required in the
* driver.
*/
-static struct flash_spec flash_5709 = {
+static const struct flash_spec flash_5709 = {
.flags = BCE_NV_BUFFERED,
.page_bits = BCM5709_FLASH_PAGE_BITS,
.page_size = BCM5709_FLASH_PAGE_SIZE,
@@ -289,48 +283,43 @@ static int bce_shutdown (device_t);
/* BCE Debug Data Structure Dump Routines */
/****************************************************************************/
#ifdef BCE_DEBUG
-static u32 bce_reg_rd (struct bce_softc *, u32);
-static void bce_reg_wr (struct bce_softc *, u32, u32);
-static void bce_reg_wr16 (struct bce_softc *, u32, u16);
-static u32 bce_ctx_rd (struct bce_softc *, u32, u32);
-static void bce_dump_enet (struct bce_softc *, struct mbuf *);
-static void bce_dump_mbuf (struct bce_softc *, struct mbuf *);
+static u32 bce_reg_rd (struct bce_softc *, u32);
+static void bce_reg_wr (struct bce_softc *, u32, u32);
+static void bce_reg_wr16 (struct bce_softc *, u32, u16);
+static u32 bce_ctx_rd (struct bce_softc *, u32, u32);
+static void bce_dump_enet (struct bce_softc *, struct mbuf *);
+static void bce_dump_mbuf (struct bce_softc *, struct mbuf *);
static void bce_dump_tx_mbuf_chain (struct bce_softc *, u16, int);
static void bce_dump_rx_mbuf_chain (struct bce_softc *, u16, int);
-#ifdef BCE_JUMBO_HDRSPLIT
static void bce_dump_pg_mbuf_chain (struct bce_softc *, u16, int);
-#endif
-static void bce_dump_txbd (struct bce_softc *,
+static void bce_dump_txbd (struct bce_softc *,
int, struct tx_bd *);
-static void bce_dump_rxbd (struct bce_softc *,
+static void bce_dump_rxbd (struct bce_softc *,
int, struct rx_bd *);
-#ifdef BCE_JUMBO_HDRSPLIT
-static void bce_dump_pgbd (struct bce_softc *,
+static void bce_dump_pgbd (struct bce_softc *,
int, struct rx_bd *);
-#endif
static void bce_dump_l2fhdr (struct bce_softc *,
int, struct l2_fhdr *);
-static void bce_dump_ctx (struct bce_softc *, u16);
-static void bce_dump_ftqs (struct bce_softc *);
+static void bce_dump_ctx (struct bce_softc *, u16);
+static void bce_dump_ftqs (struct bce_softc *);
static void bce_dump_tx_chain (struct bce_softc *, u16, int);
static void bce_dump_rx_bd_chain (struct bce_softc *, u16, int);
-#ifdef BCE_JUMBO_HDRSPLIT
static void bce_dump_pg_chain (struct bce_softc *, u16, int);
-#endif
static void bce_dump_status_block (struct bce_softc *);
static void bce_dump_stats_block (struct bce_softc *);
static void bce_dump_driver_state (struct bce_softc *);
static void bce_dump_hw_state (struct bce_softc *);
+static void bce_dump_shmem_state (struct bce_softc *);
static void bce_dump_mq_regs (struct bce_softc *);
static void bce_dump_bc_state (struct bce_softc *);
static void bce_dump_txp_state (struct bce_softc *, int);
static void bce_dump_rxp_state (struct bce_softc *, int);
-static void bce_dump_tpat_state (struct bce_softc *, int);
+static void bce_dump_tpat_state (struct bce_softc *, int);
static void bce_dump_cp_state (struct bce_softc *, int);
static void bce_dump_com_state (struct bce_softc *, int);
-static void bce_dump_rv2p_state (struct bce_softc *);
-static void bce_breakpoint (struct bce_softc *);
-#endif
+static void bce_dump_rv2p_state (struct bce_softc *);
+static void bce_breakpoint (struct bce_softc *);
+#endif /*BCE_DEBUG */
/****************************************************************************/
@@ -345,21 +334,27 @@ static int bce_miibus_read_reg (device_t, int, int);
static int bce_miibus_write_reg (device_t, int, int, int);
static void bce_miibus_statchg (device_t);
+#ifdef BCE_DEBUG
+static int bce_sysctl_nvram_dump(SYSCTL_HANDLER_ARGS);
+#ifdef BCE_NVRAM_WRITE_SUPPORT
+static int bce_sysctl_nvram_write(SYSCTL_HANDLER_ARGS);
+#endif
+#endif
/****************************************************************************/
/* BCE NVRAM Access Routines */
/****************************************************************************/
static int bce_acquire_nvram_lock (struct bce_softc *);
static int bce_release_nvram_lock (struct bce_softc *);
-static void bce_enable_nvram_access (struct bce_softc *);
-static void bce_disable_nvram_access (struct bce_softc *);
+static void bce_enable_nvram_access(struct bce_softc *);
+static void bce_disable_nvram_access(struct bce_softc *);
static int bce_nvram_read_dword (struct bce_softc *, u32, u8 *, u32);
-static int bce_init_nvram (struct bce_softc *);
-static int bce_nvram_read (struct bce_softc *, u32, u8 *, int);
-static int bce_nvram_test (struct bce_softc *);
+static int bce_init_nvram (struct bce_softc *);
+static int bce_nvram_read (struct bce_softc *, u32, u8 *, int);
+static int bce_nvram_test (struct bce_softc *);
#ifdef BCE_NVRAM_WRITE_SUPPORT
static int bce_enable_nvram_write (struct bce_softc *);
-static void bce_disable_nvram_write (struct bce_softc *);
+static void bce_disable_nvram_write(struct bce_softc *);
static int bce_nvram_erase_page (struct bce_softc *, u32);
static int bce_nvram_write_dword (struct bce_softc *, u32, u8 *, u32);
static int bce_nvram_write (struct bce_softc *, u32, u8 *, int);
@@ -368,84 +363,85 @@ static int bce_nvram_write (struct bce_softc *, u32, u8 *, int);
/****************************************************************************/
/* */
/****************************************************************************/
-static void bce_get_media (struct bce_softc *);
-static void bce_init_media (struct bce_softc *);
-static void bce_dma_map_addr (void *,
- bus_dma_segment_t *, int, int);
-static int bce_dma_alloc (device_t);
-static void bce_dma_free (struct bce_softc *);
+static void bce_get_rx_buffer_sizes(struct bce_softc *, int);
+static void bce_get_media (struct bce_softc *);
+static void bce_init_media (struct bce_softc *);
+static u32 bce_get_rphy_link (struct bce_softc *);
+static void bce_dma_map_addr (void *, bus_dma_segment_t *, int, int);
+static int bce_dma_alloc (device_t);
+static void bce_dma_free (struct bce_softc *);
static void bce_release_resources (struct bce_softc *);
/****************************************************************************/
/* BCE Firmware Synchronization and Load */
/****************************************************************************/
+static void bce_fw_cap_init (struct bce_softc *);
static int bce_fw_sync (struct bce_softc *, u32);
static void bce_load_rv2p_fw (struct bce_softc *, u32 *, u32, u32);
static void bce_load_cpu_fw (struct bce_softc *,
struct cpu_reg *, struct fw_info *);
-static void bce_start_cpu (struct bce_softc *, struct cpu_reg *);
-static void bce_halt_cpu (struct bce_softc *, struct cpu_reg *);
+static void bce_start_cpu (struct bce_softc *, struct cpu_reg *);
+static void bce_halt_cpu (struct bce_softc *, struct cpu_reg *);
static void bce_start_rxp_cpu (struct bce_softc *);
static void bce_init_rxp_cpu (struct bce_softc *);
static void bce_init_txp_cpu (struct bce_softc *);
static void bce_init_tpat_cpu (struct bce_softc *);
static void bce_init_cp_cpu (struct bce_softc *);
static void bce_init_com_cpu (struct bce_softc *);
-static void bce_init_cpus (struct bce_softc *);
+static void bce_init_cpus (struct bce_softc *);
-static void bce_print_adapter_info (struct bce_softc *);
+static void bce_print_adapter_info (struct bce_softc *);
static void bce_probe_pci_caps (device_t, struct bce_softc *);
-static void bce_stop (struct bce_softc *);
-static int bce_reset (struct bce_softc *, u32);
-static int bce_chipinit (struct bce_softc *);
-static int bce_blockinit (struct bce_softc *);
+static void bce_stop (struct bce_softc *);
+static int bce_reset (struct bce_softc *, u32);
+static int bce_chipinit (struct bce_softc *);
+static int bce_blockinit (struct bce_softc *);
static int bce_init_tx_chain (struct bce_softc *);
static void bce_free_tx_chain (struct bce_softc *);
-static int bce_get_rx_buf (struct bce_softc *,
+static int bce_get_rx_buf (struct bce_softc *,
struct mbuf *, u16 *, u16 *, u32 *);
static int bce_init_rx_chain (struct bce_softc *);
static void bce_fill_rx_chain (struct bce_softc *);
static void bce_free_rx_chain (struct bce_softc *);
-#ifdef BCE_JUMBO_HDRSPLIT
-static int bce_get_pg_buf (struct bce_softc *,
+static int bce_get_pg_buf (struct bce_softc *,
struct mbuf *, u16 *, u16 *);
static int bce_init_pg_chain (struct bce_softc *);
static void bce_fill_pg_chain (struct bce_softc *);
static void bce_free_pg_chain (struct bce_softc *);
-#endif
static struct mbuf *bce_tso_setup (struct bce_softc *,
struct mbuf **, u16 *);
-static int bce_tx_encap (struct bce_softc *, struct mbuf **);
+static int bce_tx_encap (struct bce_softc *, struct mbuf **);
static void bce_start_locked (struct ifnet *);
-static void bce_start (struct ifnet *);
-static int bce_ioctl (struct ifnet *, u_long, caddr_t);
-static void bce_watchdog (struct bce_softc *);
+static void bce_start (struct ifnet *);
+static int bce_ioctl (struct ifnet *, u_long, caddr_t);
+static void bce_watchdog (struct bce_softc *);
static int bce_ifmedia_upd (struct ifnet *);
static int bce_ifmedia_upd_locked (struct ifnet *);
static void bce_ifmedia_sts (struct ifnet *, struct ifmediareq *);
+static void bce_ifmedia_sts_rphy (struct bce_softc *, struct ifmediareq *);
static void bce_init_locked (struct bce_softc *);
-static void bce_init (void *);
+static void bce_init (void *);
static void bce_mgmt_init_locked (struct bce_softc *sc);
-static int bce_init_ctx (struct bce_softc *);
+static int bce_init_ctx (struct bce_softc *);
static void bce_get_mac_addr (struct bce_softc *);
static void bce_set_mac_addr (struct bce_softc *);
-static void bce_phy_intr (struct bce_softc *);
+static void bce_phy_intr (struct bce_softc *);
static inline u16 bce_get_hw_rx_cons (struct bce_softc *);
static void bce_rx_intr (struct bce_softc *);
static void bce_tx_intr (struct bce_softc *);
static void bce_disable_intr (struct bce_softc *);
static void bce_enable_intr (struct bce_softc *, int);
-static void bce_intr (void *);
+static void bce_intr (void *);
static void bce_set_rx_mode (struct bce_softc *);
static void bce_stats_update (struct bce_softc *);
-static void bce_tick (void *);
-static void bce_pulse (void *);
+static void bce_tick (void *);
+static void bce_pulse (void *);
static void bce_add_sysctls (struct bce_softc *);
@@ -464,10 +460,6 @@ static device_method_t bce_methods[] = {
/* DEVMETHOD(device_resume, bce_resume), */
/* DEVMETHOD(device_quiesce, bce_quiesce), */
- /* Bus interface (bus_if.h) */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
-
/* MII interface (miibus_if.h) */
DEVMETHOD(miibus_readreg, bce_miibus_read_reg),
DEVMETHOD(miibus_writereg, bce_miibus_write_reg),
@@ -476,7 +468,7 @@ static device_method_t bce_methods[] = {
/* DEVMETHOD(miibus_linkchg, bce_miibus_linkchg), */
/* DEVMETHOD(miibus_mediainit, bce_miibus_mediainit), */
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t bce_driver = {
@@ -491,8 +483,8 @@ MODULE_DEPEND(bce, pci, 1, 1, 1);
MODULE_DEPEND(bce, ether, 1, 1, 1);
MODULE_DEPEND(bce, miibus, 1, 1, 1);
-DRIVER_MODULE(bce, pci, bce_driver, bce_devclass, 0, 0);
-DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, 0, 0);
+DRIVER_MODULE(bce, pci, bce_driver, bce_devclass, NULL, NULL);
+DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, NULL, NULL);
/****************************************************************************/
@@ -501,23 +493,148 @@ DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, 0, 0);
SYSCTL_NODE(_hw, OID_AUTO, bce, CTLFLAG_RD, 0, "bce driver parameters");
/* Allowable values are TRUE or FALSE */
+static int bce_verbose = TRUE;
+TUNABLE_INT("hw.bce.verbose", &bce_verbose);
+SYSCTL_INT(_hw_bce, OID_AUTO, verbose, CTLFLAG_RDTUN, &bce_verbose, 0,
+ "Verbose output enable/disable");
+
+/* Allowable values are TRUE or FALSE */
static int bce_tso_enable = TRUE;
TUNABLE_INT("hw.bce.tso_enable", &bce_tso_enable);
SYSCTL_UINT(_hw_bce, OID_AUTO, tso_enable, CTLFLAG_RDTUN, &bce_tso_enable, 0,
-"TSO Enable/Disable");
+ "TSO Enable/Disable");
/* Allowable values are 0 (IRQ), 1 (MSI/IRQ), and 2 (MSI-X/MSI/IRQ) */
/* ToDo: Add MSI-X support. */
static int bce_msi_enable = 1;
TUNABLE_INT("hw.bce.msi_enable", &bce_msi_enable);
SYSCTL_UINT(_hw_bce, OID_AUTO, msi_enable, CTLFLAG_RDTUN, &bce_msi_enable, 0,
-"MSI-X|MSI|INTx selector");
+ "MSI-X|MSI|INTx selector");
+
+/* Allowable values are 1, 2, 4, 8. */
+static int bce_rx_pages = DEFAULT_RX_PAGES;
+TUNABLE_INT("hw.bce.rx_pages", &bce_rx_pages);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_pages, CTLFLAG_RDTUN, &bce_rx_pages, 0,
+ "Receive buffer descriptor pages (1 page = 255 buffer descriptors)");
+
+/* Allowable values are 1, 2, 4, 8. */
+static int bce_tx_pages = DEFAULT_TX_PAGES;
+TUNABLE_INT("hw.bce.tx_pages", &bce_tx_pages);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_pages, CTLFLAG_RDTUN, &bce_tx_pages, 0,
+ "Transmit buffer descriptor pages (1 page = 255 buffer descriptors)");
+
+/* Allowable values are TRUE or FALSE. */
+static int bce_hdr_split = TRUE;
+TUNABLE_INT("hw.bce.hdr_split", &bce_hdr_split);
+SYSCTL_UINT(_hw_bce, OID_AUTO, hdr_split, CTLFLAG_RDTUN, &bce_hdr_split, 0,
+ "Frame header/payload splitting Enable/Disable");
+
+/* Allowable values are TRUE or FALSE. */
+static int bce_strict_rx_mtu = FALSE;
+TUNABLE_INT("hw.bce.strict_rx_mtu", &bce_strict_rx_mtu);
+SYSCTL_UINT(_hw_bce, OID_AUTO, loose_rx_mtu, CTLFLAG_RDTUN,
+ &bce_strict_rx_mtu, 0,
+ "Enable/Disable strict RX frame size checking");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate 1 interrupt for every transmit completion. */
+static int bce_tx_quick_cons_trip_int = 1;
+#else
+/* Generate 1 interrupt for every 20 transmit completions. */
+static int bce_tx_quick_cons_trip_int = DEFAULT_TX_QUICK_CONS_TRIP_INT;
+#endif
+TUNABLE_INT("hw.bce.tx_quick_cons_trip_int", &bce_tx_quick_cons_trip_int);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_quick_cons_trip_int, CTLFLAG_RDTUN,
+ &bce_tx_quick_cons_trip_int, 0,
+ "Transmit BD trip point during interrupts");
+
+/* Allowable values are 0 ... 100 */
+/* Generate 1 interrupt for every transmit completion. */
+#ifdef BCE_DEBUG
+static int bce_tx_quick_cons_trip = 1;
+#else
+/* Generate 1 interrupt for every 20 transmit completions. */
+static int bce_tx_quick_cons_trip = DEFAULT_TX_QUICK_CONS_TRIP;
+#endif
+TUNABLE_INT("hw.bce.tx_quick_cons_trip", &bce_tx_quick_cons_trip);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_quick_cons_trip, CTLFLAG_RDTUN,
+ &bce_tx_quick_cons_trip, 0,
+ "Transmit BD trip point");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate an interrupt if 0us have elapsed since the last TX completion. */
+static int bce_tx_ticks_int = 0;
+#else
+/* Generate an interrupt if 80us have elapsed since the last TX completion. */
+static int bce_tx_ticks_int = DEFAULT_TX_TICKS_INT;
+#endif
+TUNABLE_INT("hw.bce.tx_ticks_int", &bce_tx_ticks_int);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_ticks_int, CTLFLAG_RDTUN,
+ &bce_tx_ticks_int, 0, "Transmit ticks count during interrupt");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate an interrupt if 0us have elapsed since the last TX completion. */
+static int bce_tx_ticks = 0;
+#else
+/* Generate an interrupt if 80us have elapsed since the last TX completion. */
+static int bce_tx_ticks = DEFAULT_TX_TICKS;
+#endif
+TUNABLE_INT("hw.bce.tx_ticks", &bce_tx_ticks);
+SYSCTL_UINT(_hw_bce, OID_AUTO, tx_ticks, CTLFLAG_RDTUN,
+ &bce_tx_ticks, 0, "Transmit ticks count");
+
+/* Allowable values are 1 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate 1 interrupt for every received frame. */
+static int bce_rx_quick_cons_trip_int = 1;
+#else
+/* Generate 1 interrupt for every 6 received frames. */
+static int bce_rx_quick_cons_trip_int = DEFAULT_RX_QUICK_CONS_TRIP_INT;
+#endif
+TUNABLE_INT("hw.bce.rx_quick_cons_trip_int", &bce_rx_quick_cons_trip_int);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_quick_cons_trip_int, CTLFLAG_RDTUN,
+ &bce_rx_quick_cons_trip_int, 0,
+ "Receive BD trip point duirng interrupts");
+
+/* Allowable values are 1 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate 1 interrupt for every received frame. */
+static int bce_rx_quick_cons_trip = 1;
+#else
+/* Generate 1 interrupt for every 6 received frames. */
+static int bce_rx_quick_cons_trip = DEFAULT_RX_QUICK_CONS_TRIP;
+#endif
+TUNABLE_INT("hw.bce.rx_quick_cons_trip", &bce_rx_quick_cons_trip);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_quick_cons_trip, CTLFLAG_RDTUN,
+ &bce_rx_quick_cons_trip, 0,
+ "Receive BD trip point");
+
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate an int. if 0us have elapsed since the last received frame. */
+static int bce_rx_ticks_int = 0;
+#else
+/* Generate an int. if 18us have elapsed since the last received frame. */
+static int bce_rx_ticks_int = DEFAULT_RX_TICKS_INT;
+#endif
+TUNABLE_INT("hw.bce.rx_ticks_int", &bce_rx_ticks_int);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_ticks_int, CTLFLAG_RDTUN,
+ &bce_rx_ticks_int, 0, "Receive ticks count during interrupt");
-/* ToDo: Add tunable to enable/disable strict MTU handling. */
-/* Currently allows "loose" RX MTU checking (i.e. sets the */
-/* H/W RX MTU to the size of the largest receive buffer, or */
-/* 2048 bytes). This will cause a UNH failure but is more */
-/* desireable from a functional perspective. */
+/* Allowable values are 0 ... 100 */
+#ifdef BCE_DEBUG
+/* Generate an int. if 0us have elapsed since the last received frame. */
+static int bce_rx_ticks = 0;
+#else
+/* Generate an int. if 18us have elapsed since the last received frame. */
+static int bce_rx_ticks = DEFAULT_RX_TICKS;
+#endif
+TUNABLE_INT("hw.bce.rx_ticks", &bce_rx_ticks);
+SYSCTL_UINT(_hw_bce, OID_AUTO, rx_ticks, CTLFLAG_RDTUN,
+ &bce_rx_ticks, 0, "Receive ticks count");
/****************************************************************************/
@@ -532,7 +649,7 @@ SYSCTL_UINT(_hw_bce, OID_AUTO, msi_enable, CTLFLAG_RDTUN, &bce_msi_enable, 0,
static int
bce_probe(device_t dev)
{
- struct bce_type *t;
+ const struct bce_type *t;
struct bce_softc *sc;
char *descbuf;
u16 vid = 0, did = 0, svid = 0, sdid = 0;
@@ -540,7 +657,6 @@ bce_probe(device_t dev)
t = bce_devs;
sc = device_get_softc(dev);
- bzero(sc, sizeof(struct bce_softc));
sc->bce_unit = device_get_unit(dev);
sc->bce_dev = dev;
@@ -599,7 +715,7 @@ bce_print_adapter_info(struct bce_softc *sc)
DBENTER(BCE_VERBOSE_LOAD);
- if (bootverbose) {
+ if (bce_verbose || bootverbose) {
BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid);
printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >>
12) + 'A', ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4));
@@ -621,12 +737,14 @@ bce_print_adapter_info(struct bce_softc *sc)
}
/* Firmware version and device features. */
- printf("B/C (%s); Flags (", sc->bce_bc_ver);
+ printf("B/C (%s); Bufs (RX:%d;TX:%d;PG:%d); Flags (",
+ sc->bce_bc_ver, sc->rx_pages, sc->tx_pages,
+ (bce_hdr_split == TRUE ? sc->pg_pages: 0));
- #ifdef BCE_JUMBO_HDRSPLIT
- printf("SPLT");
- i++;
- #endif
+ if (bce_hdr_split == TRUE) {
+ printf("SPLT");
+ i++;
+ }
if (sc->bce_flags & BCE_USING_MSI_FLAG) {
if (i > 0) printf("|");
@@ -643,12 +761,30 @@ bce_print_adapter_info(struct bce_softc *sc)
printf("2.5G"); i++;
}
+ if (sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) {
+ if (i > 0) printf("|");
+ printf("Remote PHY(%s)",
+ sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG ?
+ "FIBER" : "TP"); i++;
+ }
+
if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
if (i > 0) printf("|");
printf("MFW); MFW (%s)\n", sc->bce_mfw_ver);
} else {
printf(")\n");
}
+
+ printf("Coal (RX:%d,%d,%d,%d; TX:%d,%d,%d,%d)\n",
+ sc->bce_rx_quick_cons_trip_int,
+ sc->bce_rx_quick_cons_trip,
+ sc->bce_rx_ticks_int,
+ sc->bce_rx_ticks,
+ sc->bce_tx_quick_cons_trip_int,
+ sc->bce_tx_quick_cons_trip,
+ sc->bce_tx_ticks_int,
+ sc->bce_tx_ticks);
+
}
DBEXIT(BCE_VERBOSE_LOAD);
@@ -707,6 +843,189 @@ bce_probe_pci_caps(device_t dev, struct bce_softc *sc)
/****************************************************************************/
+/* Load and validate user tunable settings. */
+/* */
+/* Returns: */
+/* Nothing. */
+/****************************************************************************/
+static void
+bce_set_tunables(struct bce_softc *sc)
+{
+ /* Set sysctl values for RX page count. */
+ switch (bce_rx_pages) {
+ case 1:
+ /* fall-through */
+ case 2:
+ /* fall-through */
+ case 4:
+ /* fall-through */
+ case 8:
+ sc->rx_pages = bce_rx_pages;
+ break;
+ default:
+ sc->rx_pages = DEFAULT_RX_PAGES;
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.rx_pages! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_rx_pages, DEFAULT_RX_PAGES);
+ }
+
+ /* ToDo: Consider allowing user setting for pg_pages. */
+ sc->pg_pages = min((sc->rx_pages * 4), MAX_PG_PAGES);
+
+ /* Set sysctl values for TX page count. */
+ switch (bce_tx_pages) {
+ case 1:
+ /* fall-through */
+ case 2:
+ /* fall-through */
+ case 4:
+ /* fall-through */
+ case 8:
+ sc->tx_pages = bce_tx_pages;
+ break;
+ default:
+ sc->tx_pages = DEFAULT_TX_PAGES;
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.tx_pages! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_tx_pages, DEFAULT_TX_PAGES);
+ }
+
+ /*
+ * Validate the TX trip point (i.e. the number of
+ * TX completions before a status block update is
+ * generated and an interrupt is asserted.
+ */
+ if (bce_tx_quick_cons_trip_int <= 100) {
+ sc->bce_tx_quick_cons_trip_int =
+ bce_tx_quick_cons_trip_int;
+ } else {
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.tx_quick_cons_trip_int! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_tx_quick_cons_trip_int,
+ DEFAULT_TX_QUICK_CONS_TRIP_INT);
+ sc->bce_tx_quick_cons_trip_int =
+ DEFAULT_TX_QUICK_CONS_TRIP_INT;
+ }
+
+ if (bce_tx_quick_cons_trip <= 100) {
+ sc->bce_tx_quick_cons_trip =
+ bce_tx_quick_cons_trip;
+ } else {
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.tx_quick_cons_trip! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_tx_quick_cons_trip,
+ DEFAULT_TX_QUICK_CONS_TRIP);
+ sc->bce_tx_quick_cons_trip =
+ DEFAULT_TX_QUICK_CONS_TRIP;
+ }
+
+ /*
+ * Validate the TX ticks count (i.e. the maximum amount
+ * of time to wait after the last TX completion has
+ * occurred before a status block update is generated
+ * and an interrupt is asserted.
+ */
+ if (bce_tx_ticks_int <= 100) {
+ sc->bce_tx_ticks_int =
+ bce_tx_ticks_int;
+ } else {
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.tx_ticks_int! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_tx_ticks_int,
+ DEFAULT_TX_TICKS_INT);
+ sc->bce_tx_ticks_int =
+ DEFAULT_TX_TICKS_INT;
+ }
+
+ if (bce_tx_ticks <= 100) {
+ sc->bce_tx_ticks =
+ bce_tx_ticks;
+ } else {
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.tx_ticks! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_tx_ticks,
+ DEFAULT_TX_TICKS);
+ sc->bce_tx_ticks =
+ DEFAULT_TX_TICKS;
+ }
+
+ /*
+ * Validate the RX trip point (i.e. the number of
+ * RX frames received before a status block update is
+ * generated and an interrupt is asserted.
+ */
+ if (bce_rx_quick_cons_trip_int <= 100) {
+ sc->bce_rx_quick_cons_trip_int =
+ bce_rx_quick_cons_trip_int;
+ } else {
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.rx_quick_cons_trip_int! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_rx_quick_cons_trip_int,
+ DEFAULT_RX_QUICK_CONS_TRIP_INT);
+ sc->bce_rx_quick_cons_trip_int =
+ DEFAULT_RX_QUICK_CONS_TRIP_INT;
+ }
+
+ if (bce_rx_quick_cons_trip <= 100) {
+ sc->bce_rx_quick_cons_trip =
+ bce_rx_quick_cons_trip;
+ } else {
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.rx_quick_cons_trip! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_rx_quick_cons_trip,
+ DEFAULT_RX_QUICK_CONS_TRIP);
+ sc->bce_rx_quick_cons_trip =
+ DEFAULT_RX_QUICK_CONS_TRIP;
+ }
+
+ /*
+ * Validate the RX ticks count (i.e. the maximum amount
+ * of time to wait after the last RX frame has been
+ * received before a status block update is generated
+ * and an interrupt is asserted.
+ */
+ if (bce_rx_ticks_int <= 100) {
+ sc->bce_rx_ticks_int = bce_rx_ticks_int;
+ } else {
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.rx_ticks_int! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_rx_ticks_int,
+ DEFAULT_RX_TICKS_INT);
+ sc->bce_rx_ticks_int = DEFAULT_RX_TICKS_INT;
+ }
+
+ if (bce_rx_ticks <= 100) {
+ sc->bce_rx_ticks = bce_rx_ticks;
+ } else {
+ BCE_PRINTF("%s(%d): Illegal value (%d) specified for "
+ "hw.bce.rx_ticks! Setting default of %d.\n",
+ __FILE__, __LINE__, bce_rx_ticks,
+ DEFAULT_RX_TICKS);
+ sc->bce_rx_ticks = DEFAULT_RX_TICKS;
+ }
+
+ /* Disabling both RX ticks and RX trips will prevent interrupts. */
+ if ((bce_rx_quick_cons_trip == 0) && (bce_rx_ticks == 0)) {
+ BCE_PRINTF("%s(%d): Cannot set both hw.bce.rx_ticks and "
+ "hw.bce.rx_quick_cons_trip to 0. Setting default values.\n",
+ __FILE__, __LINE__);
+ sc->bce_rx_ticks = DEFAULT_RX_TICKS;
+ sc->bce_rx_quick_cons_trip = DEFAULT_RX_QUICK_CONS_TRIP;
+ }
+
+ /* Disabling both TX ticks and TX trips will prevent interrupts. */
+ if ((bce_tx_quick_cons_trip == 0) && (bce_tx_ticks == 0)) {
+ BCE_PRINTF("%s(%d): Cannot set both hw.bce.tx_ticks and "
+ "hw.bce.tx_quick_cons_trip to 0. Setting default values.\n",
+ __FILE__, __LINE__);
+ sc->bce_tx_ticks = DEFAULT_TX_TICKS;
+ sc->bce_tx_quick_cons_trip = DEFAULT_TX_QUICK_CONS_TRIP;
+ }
+
+}
+
+
+/****************************************************************************/
/* Device attach function. */
/* */
/* Allocates device resources, performs secondary chip identification, */
@@ -722,7 +1041,7 @@ bce_attach(device_t dev)
struct bce_softc *sc;
struct ifnet *ifp;
u32 val;
- int error, rid, rc = 0;
+ int count, error, rc = 0, rid;
sc = device_get_softc(dev);
sc->bce_dev = dev;
@@ -735,6 +1054,8 @@ bce_attach(device_t dev)
sc->bce_flags = 0;
sc->bce_phy_flags = 0;
+ bce_set_tunables(sc);
+
pci_enable_busmaster(dev);
/* Allocate PCI memory resources. */
@@ -757,6 +1078,7 @@ bce_attach(device_t dev)
bce_probe_pci_caps(dev, sc);
rid = 1;
+ count = 0;
#if 0
/* Try allocating MSI-X interrupts. */
if ((sc->bce_cap_flags & BCE_MSIX_CAPABLE_FLAG) &&
@@ -764,14 +1086,14 @@ bce_attach(device_t dev)
((sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&rid, RF_ACTIVE)) != NULL)) {
- msi_needed = sc->bce_msi_count = 1;
+ msi_needed = count = 1;
- if (((error = pci_alloc_msix(dev, &sc->bce_msi_count)) != 0) ||
- (sc->bce_msi_count != msi_needed)) {
+ if (((error = pci_alloc_msix(dev, &count)) != 0) ||
+ (count != msi_needed)) {
BCE_PRINTF("%s(%d): MSI-X allocation failed! Requested = %d,"
"Received = %d, error = %d\n", __FILE__, __LINE__,
- msi_needed, sc->bce_msi_count, error);
- sc->bce_msi_count = 0;
+ msi_needed, count, error);
+ count = 0;
pci_release_msi(dev);
bus_release_resource(dev, SYS_RES_MEMORY, rid,
sc->bce_res_irq);
@@ -780,44 +1102,38 @@ bce_attach(device_t dev)
DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI-X interrupt.\n",
__FUNCTION__);
sc->bce_flags |= BCE_USING_MSIX_FLAG;
- sc->bce_intr = bce_intr;
}
}
#endif
/* Try allocating a MSI interrupt. */
if ((sc->bce_cap_flags & BCE_MSI_CAPABLE_FLAG) &&
- (bce_msi_enable >= 1) && (sc->bce_msi_count == 0)) {
- sc->bce_msi_count = 1;
- if ((error = pci_alloc_msi(dev, &sc->bce_msi_count)) != 0) {
+ (bce_msi_enable >= 1) && (count == 0)) {
+ count = 1;
+ if ((error = pci_alloc_msi(dev, &count)) != 0) {
BCE_PRINTF("%s(%d): MSI allocation failed! "
"error = %d\n", __FILE__, __LINE__, error);
- sc->bce_msi_count = 0;
+ count = 0;
pci_release_msi(dev);
} else {
DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI "
"interrupt.\n", __FUNCTION__);
sc->bce_flags |= BCE_USING_MSI_FLAG;
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716))
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709)
sc->bce_flags |= BCE_ONE_SHOT_MSI_FLAG;
- sc->bce_irq_rid = 1;
- sc->bce_intr = bce_intr;
+ rid = 1;
}
}
/* Try allocating a legacy interrupt. */
- if (sc->bce_msi_count == 0) {
+ if (count == 0) {
DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using INTx interrupt.\n",
__FUNCTION__);
rid = 0;
- sc->bce_intr = bce_intr;
}
sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &rid, RF_SHAREABLE | RF_ACTIVE);
-
- sc->bce_irq_rid = rid;
+ &rid, RF_ACTIVE | (count != 0 ? 0 : RF_SHAREABLE));
/* Report any IRQ allocation errors. */
if (sc->bce_res_irq == NULL) {
@@ -988,6 +1304,9 @@ bce_attach(device_t dev)
if (val & BCE_PCICFG_MISC_STATUS_32BIT_DET)
sc->bce_flags |= BCE_PCI_32BIT_FLAG;
+ /* Find the media type for the adapter. */
+ bce_get_media(sc);
+
/* Reset controller and announce to bootcode that driver is present. */
if (bce_reset(sc, BCE_DRV_MSG_CODE_RESET)) {
BCE_PRINTF("%s(%d): Controller reset failed!\n",
@@ -1024,44 +1343,17 @@ bce_attach(device_t dev)
* values for the RX and TX chains.
*/
-#ifdef BCE_DEBUG
- /* Force more frequent interrupts. */
- sc->bce_tx_quick_cons_trip_int = 1;
- sc->bce_tx_quick_cons_trip = 1;
- sc->bce_tx_ticks_int = 0;
- sc->bce_tx_ticks = 0;
-
- sc->bce_rx_quick_cons_trip_int = 1;
- sc->bce_rx_quick_cons_trip = 1;
- sc->bce_rx_ticks_int = 0;
- sc->bce_rx_ticks = 0;
-#else
- /* Improve throughput at the expense of increased latency. */
- sc->bce_tx_quick_cons_trip_int = 20;
- sc->bce_tx_quick_cons_trip = 20;
- sc->bce_tx_ticks_int = 80;
- sc->bce_tx_ticks = 80;
-
- sc->bce_rx_quick_cons_trip_int = 6;
- sc->bce_rx_quick_cons_trip = 6;
- sc->bce_rx_ticks_int = 18;
- sc->bce_rx_ticks = 18;
-#endif
-
/* Not used for L2. */
- sc->bce_comp_prod_trip_int = 0;
- sc->bce_comp_prod_trip = 0;
- sc->bce_com_ticks_int = 0;
- sc->bce_com_ticks = 0;
- sc->bce_cmd_ticks_int = 0;
- sc->bce_cmd_ticks = 0;
+ sc->bce_comp_prod_trip_int = 0;
+ sc->bce_comp_prod_trip = 0;
+ sc->bce_com_ticks_int = 0;
+ sc->bce_com_ticks = 0;
+ sc->bce_cmd_ticks_int = 0;
+ sc->bce_cmd_ticks = 0;
/* Update statistics once every second. */
sc->bce_stats_ticks = 1000000 & 0xffff00;
- /* Find the media type for the adapter. */
- bce_get_media(sc);
-
/* Store data needed by PHY driver for backplane applications */
sc->bce_shared_hw_cfg = bce_shmem_rd(sc, BCE_SHARED_HW_CFG_CONFIG);
sc->bce_port_hw_cfg = bce_shmem_rd(sc, BCE_PORT_HW_CFG_CONFIG);
@@ -1101,6 +1393,15 @@ bce_attach(device_t dev)
ifp->if_capabilities = BCE_IF_CAPABILITIES;
}
+#if __FreeBSD_version >= 800505
+ /*
+ * Introducing IFCAP_LINKSTATE didn't bump __FreeBSD_version
+ * so it's approximate value.
+ */
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0)
+ ifp->if_capabilities |= IFCAP_LINKSTATE;
+#endif
+
ifp->if_capenable = ifp->if_capabilities;
/*
@@ -1108,23 +1409,11 @@ bce_attach(device_t dev)
* This may change later if the MTU size is set to
* something other than 1500.
*/
-#ifdef BCE_JUMBO_HDRSPLIT
- sc->rx_bd_mbuf_alloc_size = MHLEN;
- /* Make sure offset is 16 byte aligned for hardware. */
- sc->rx_bd_mbuf_align_pad =
- roundup2((MSIZE - MHLEN), 16) - (MSIZE - MHLEN);
- sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
- sc->rx_bd_mbuf_align_pad;
- sc->pg_bd_mbuf_alloc_size = MCLBYTES;
-#else
- sc->rx_bd_mbuf_alloc_size = MCLBYTES;
- sc->rx_bd_mbuf_align_pad =
- roundup2(MCLBYTES, 16) - MCLBYTES;
- sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
- sc->rx_bd_mbuf_align_pad;
-#endif
+ bce_get_rx_buffer_sizes(sc,
+ (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN));
- ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD;
+ /* Recalculate our buffer allocation sizes. */
+ ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD_ALLOC;
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
IFQ_SET_READY(&ifp->if_snd);
@@ -1136,14 +1425,52 @@ bce_attach(device_t dev)
/* Handle any special PHY initialization for SerDes PHYs. */
bce_init_media(sc);
- /* MII child bus by attaching the PHY. */
- rc = mii_attach(dev, &sc->bce_miibus, ifp, bce_ifmedia_upd,
- bce_ifmedia_sts, BMSR_DEFCAPMASK, sc->bce_phy_addr,
- MII_OFFSET_ANY, MIIF_DOPAUSE | MIIF_FORCEPAUSE);
- if (rc != 0) {
- BCE_PRINTF("%s(%d): attaching PHYs failed\n", __FILE__,
- __LINE__);
- goto bce_attach_fail;
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0) {
+ ifmedia_init(&sc->bce_ifmedia, IFM_IMASK, bce_ifmedia_upd,
+ bce_ifmedia_sts);
+ /*
+ * We can't manually override remote PHY's link and assume
+ * PHY port configuration(Fiber or TP) is not changed after
+ * device attach. This may not be correct though.
+ */
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG) != 0) {
+ if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) {
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_2500_SX, 0, NULL);
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_2500_SX | IFM_FDX, 0, NULL);
+ }
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_1000_SX, 0, NULL);
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_1000_SX | IFM_FDX, 0, NULL);
+ } else {
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_10_T, 0, NULL);
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL);
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_100_TX, 0, NULL);
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL);
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_1000_T, 0, NULL);
+ ifmedia_add(&sc->bce_ifmedia,
+ IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
+ }
+ ifmedia_add(&sc->bce_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&sc->bce_ifmedia, IFM_ETHER | IFM_AUTO);
+ sc->bce_ifmedia.ifm_media = sc->bce_ifmedia.ifm_cur->ifm_media;
+ } else {
+ /* MII child bus by attaching the PHY. */
+ rc = mii_attach(dev, &sc->bce_miibus, ifp, bce_ifmedia_upd,
+ bce_ifmedia_sts, BMSR_DEFCAPMASK, sc->bce_phy_addr,
+ MII_OFFSET_ANY, MIIF_DOPAUSE | MIIF_FORCEPAUSE);
+ if (rc != 0) {
+ BCE_PRINTF("%s(%d): attaching PHYs failed\n", __FILE__,
+ __LINE__);
+ goto bce_attach_fail;
+ }
}
/* Attach to the Ethernet interface list. */
@@ -1248,8 +1575,12 @@ bce_detach(device_t dev)
ether_ifdetach(ifp);
/* If we have a child device on the MII bus remove it too. */
- bus_generic_detach(dev);
- device_delete_child(dev, sc->bce_miibus);
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0)
+ ifmedia_removeall(&sc->bce_ifmedia);
+ else {
+ bus_generic_detach(dev);
+ device_delete_child(dev, sc->bce_miibus);
+ }
/* Release all remaining resources. */
bce_release_resources(sc);
@@ -1301,7 +1632,7 @@ bce_shutdown(device_t dev)
static u32
bce_reg_rd(struct bce_softc *sc, u32 offset)
{
- u32 val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, offset);
+ u32 val = REG_RD(sc, offset);
DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
__FUNCTION__, offset, val);
return val;
@@ -1319,7 +1650,7 @@ bce_reg_wr16(struct bce_softc *sc, u32 offset, u16 val)
{
DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%04X\n",
__FUNCTION__, offset, val);
- bus_space_write_2(sc->bce_btag, sc->bce_bhandle, offset, val);
+ REG_WR16(sc, offset, val);
}
@@ -1334,7 +1665,7 @@ bce_reg_wr(struct bce_softc *sc, u32 offset, u32 val)
{
DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
__FUNCTION__, offset, val);
- bus_space_write_4(sc->bce_btag, sc->bce_bhandle, offset, val);
+ REG_WR(sc, offset, val);
}
#endif
@@ -1452,8 +1783,7 @@ bce_ctx_rd(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset)
offset = ctx_offset + cid_addr;
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
REG_WR(sc, BCE_CTX_CTX_CTRL, (offset | BCE_CTX_CTX_CTRL_READ_REQ));
@@ -1505,8 +1835,7 @@ bce_ctx_wr(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset, u32 ctx_val)
BCE_PRINTF("%s(): Invalid CID address: 0x%08X.\n",
__FUNCTION__, cid_addr));
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
REG_WR(sc, BCE_CTX_CTX_DATA, ctx_val);
REG_WR(sc, BCE_CTX_CTX_CTRL, (offset | BCE_CTX_CTX_CTRL_WRITE_REQ));
@@ -1547,13 +1876,6 @@ bce_miibus_read_reg(device_t dev, int phy, int reg)
sc = device_get_softc(dev);
- /* Make sure we are accessing the correct PHY address. */
- if (phy != sc->bce_phy_addr) {
- DBPRINT(sc, BCE_INSANE_PHY, "Invalid PHY address %d "
- "for PHY read!\n", phy);
- return(0);
- }
-
/*
* The 5709S PHY is an IEEE Clause 45 PHY
* with special mappings to work with IEEE
@@ -1636,13 +1958,6 @@ bce_miibus_write_reg(device_t dev, int phy, int reg, int val)
sc = device_get_softc(dev);
- /* Make sure we are accessing the correct PHY address. */
- if (phy != sc->bce_phy_addr) {
- DBPRINT(sc, BCE_INSANE_PHY, "Invalid PHY address %d "
- "for PHY write!\n", phy);
- return(0);
- }
-
DB_PRINT_PHY_REG(reg, val);
/*
@@ -1712,13 +2027,28 @@ bce_miibus_statchg(device_t dev)
{
struct bce_softc *sc;
struct mii_data *mii;
- int val;
+ struct ifmediareq ifmr;
+ int media_active, media_status, val;
sc = device_get_softc(dev);
DBENTER(BCE_VERBOSE_PHY);
- mii = device_get_softc(sc->bce_miibus);
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0) {
+ bzero(&ifmr, sizeof(ifmr));
+ bce_ifmedia_sts_rphy(sc, &ifmr);
+ media_active = ifmr.ifm_active;
+ media_status = ifmr.ifm_status;
+ } else {
+ mii = device_get_softc(sc->bce_miibus);
+ media_active = mii->mii_media_active;
+ media_status = mii->mii_media_status;
+ }
+
+ /* Ignore invalid media status. */
+ if ((media_status & (IFM_ACTIVE | IFM_AVALID)) !=
+ (IFM_ACTIVE | IFM_AVALID))
+ goto bce_miibus_statchg_exit;
val = REG_RD(sc, BCE_EMAC_MODE);
val &= ~(BCE_EMAC_MODE_PORT | BCE_EMAC_MODE_HALF_DUPLEX |
@@ -1726,7 +2056,7 @@ bce_miibus_statchg(device_t dev)
BCE_EMAC_MODE_25G);
/* Set MII or GMII interface based on the PHY speed. */
- switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ switch (IFM_SUBTYPE(media_active)) {
case IFM_10_T:
if (BCE_CHIP_NUM(sc) != BCE_CHIP_NUM_5706) {
DBPRINT(sc, BCE_INFO_PHY,
@@ -1755,7 +2085,7 @@ bce_miibus_statchg(device_t dev)
}
/* Set half or full duplex based on PHY settings. */
- if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) {
+ if ((IFM_OPTIONS(media_active) & IFM_FDX) == 0) {
DBPRINT(sc, BCE_INFO_PHY,
"Setting Half-Duplex interface.\n");
val |= BCE_EMAC_MODE_HALF_DUPLEX;
@@ -1765,7 +2095,7 @@ bce_miibus_statchg(device_t dev)
REG_WR(sc, BCE_EMAC_MODE, val);
- if ((mii->mii_media_active & IFM_ETH_RXPAUSE) != 0) {
+ if ((IFM_OPTIONS(media_active) & IFM_ETH_RXPAUSE) != 0) {
DBPRINT(sc, BCE_INFO_PHY,
"%s(): Enabling RX flow control.\n", __FUNCTION__);
BCE_SETBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN);
@@ -1775,7 +2105,7 @@ bce_miibus_statchg(device_t dev)
BCE_CLRBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN);
}
- if ((mii->mii_media_active & IFM_ETH_TXPAUSE) != 0) {
+ if ((IFM_OPTIONS(media_active) & IFM_ETH_TXPAUSE) != 0) {
DBPRINT(sc, BCE_INFO_PHY,
"%s(): Enabling TX flow control.\n", __FUNCTION__);
BCE_SETBIT(sc, BCE_EMAC_TX_MODE, BCE_EMAC_TX_MODE_FLOW_EN);
@@ -1789,6 +2119,7 @@ bce_miibus_statchg(device_t dev)
/* ToDo: Update watermarks in bce_init_rx_context(). */
+bce_miibus_statchg_exit:
DBEXIT(BCE_VERBOSE_PHY);
}
@@ -2187,12 +2518,11 @@ bce_init_nvram(struct bce_softc *sc)
{
u32 val;
int j, entry_count, rc = 0;
- struct flash_spec *flash;
+ const struct flash_spec *flash;
DBENTER(BCE_VERBOSE_NVRAM);
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
sc->bce_flash_info = &flash_5709;
goto bce_init_nvram_get_flash_size;
}
@@ -2600,9 +2930,9 @@ bce_nvram_write(struct bce_softc *sc, u32 offset, u8 *data_buf,
goto bce_nvram_write_exit;
bce_nvram_write_locked_exit:
- bce_disable_nvram_write(sc);
- bce_disable_nvram_access(sc);
- bce_release_nvram_lock(sc);
+ bce_disable_nvram_write(sc);
+ bce_disable_nvram_access(sc);
+ bce_release_nvram_lock(sc);
bce_nvram_write_exit:
if (align_start || align_end)
@@ -2647,7 +2977,7 @@ bce_nvram_test(struct bce_softc *sc)
* Verify that offset 0 of the NVRAM contains
* a valid magic number.
*/
- magic = bce_be32toh(buf[0]);
+ magic = bce_be32toh(buf[0]);
if (magic != BCE_NVRAM_MAGIC) {
rc = ENODEV;
BCE_PRINTF("%s(%d): Invalid NVRAM magic value! "
@@ -2691,6 +3021,58 @@ bce_nvram_test_exit:
/****************************************************************************/
+/* Calculates the size of the buffers to allocate based on the MTU. */
+/* */
+/* Returns: */
+/* Nothing. */
+/****************************************************************************/
+static void
+bce_get_rx_buffer_sizes(struct bce_softc *sc, int mtu)
+{
+ DBENTER(BCE_VERBOSE_LOAD);
+
+ /* Use a single allocation type when header splitting enabled. */
+ if (bce_hdr_split == TRUE) {
+ sc->rx_bd_mbuf_alloc_size = MHLEN;
+ /* Make sure offset is 16 byte aligned for hardware. */
+ sc->rx_bd_mbuf_align_pad =
+ roundup2((MSIZE - MHLEN), 16) - (MSIZE - MHLEN);
+ sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
+ sc->rx_bd_mbuf_align_pad;
+ sc->pg_bd_mbuf_alloc_size = MCLBYTES;
+ } else {
+ if ((mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN +
+ ETHER_CRC_LEN) > MCLBYTES) {
+ /* Setup for jumbo RX buffer allocations. */
+ sc->rx_bd_mbuf_alloc_size = MJUM9BYTES;
+ sc->rx_bd_mbuf_align_pad =
+ roundup2(MJUM9BYTES, 16) - MJUM9BYTES;
+ sc->rx_bd_mbuf_data_len =
+ sc->rx_bd_mbuf_alloc_size -
+ sc->rx_bd_mbuf_align_pad;
+ } else {
+ /* Setup for standard RX buffer allocations. */
+ sc->rx_bd_mbuf_alloc_size = MCLBYTES;
+ sc->rx_bd_mbuf_align_pad =
+ roundup2(MCLBYTES, 16) - MCLBYTES;
+ sc->rx_bd_mbuf_data_len =
+ sc->rx_bd_mbuf_alloc_size -
+ sc->rx_bd_mbuf_align_pad;
+ }
+ }
+
+// DBPRINT(sc, BCE_INFO_LOAD,
+ DBPRINT(sc, BCE_WARN,
+ "%s(): rx_bd_mbuf_alloc_size = %d, rx_bd_mbuf_data_len = %d, "
+ "rx_bd_mbuf_align_pad = %d\n", __FUNCTION__,
+ sc->rx_bd_mbuf_alloc_size, sc->rx_bd_mbuf_data_len,
+ sc->rx_bd_mbuf_align_pad);
+
+ DBEXIT(BCE_VERBOSE_LOAD);
+
+}
+
+/****************************************************************************/
/* Identifies the current media type of the controller and sets the PHY */
/* address. */
/* */
@@ -2808,7 +3190,8 @@ bce_get_media_exit:
static void
bce_init_media(struct bce_softc *sc)
{
- if ((sc->bce_phy_flags & BCE_PHY_IEEE_CLAUSE_45_FLAG) != 0) {
+ if ((sc->bce_phy_flags & (BCE_PHY_IEEE_CLAUSE_45_FLAG |
+ BCE_PHY_REMOTE_CAP_FLAG)) == BCE_PHY_IEEE_CLAUSE_45_FLAG) {
/*
* Configure 5709S/5716S PHYs to use traditional IEEE
* Clause 22 method. Otherwise we have no way to attach
@@ -2894,8 +3277,7 @@ bce_dma_free(struct bce_softc *sc)
/* Free, unmap and destroy all context memory pages. */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
for (i = 0; i < sc->ctx_pages; i++ ) {
if (sc->ctx_block[i] != NULL) {
bus_dmamem_free(
@@ -2925,7 +3307,7 @@ bce_dma_free(struct bce_softc *sc)
/* Free, unmap and destroy all TX buffer descriptor chain pages. */
- for (i = 0; i < TX_PAGES; i++ ) {
+ for (i = 0; i < sc->tx_pages; i++ ) {
if (sc->tx_bd_chain[i] != NULL) {
bus_dmamem_free(
sc->tx_bd_chain_tag,
@@ -2953,7 +3335,7 @@ bce_dma_free(struct bce_softc *sc)
/* Free, unmap and destroy all RX buffer descriptor chain pages. */
- for (i = 0; i < RX_PAGES; i++ ) {
+ for (i = 0; i < sc->rx_pages; i++ ) {
if (sc->rx_bd_chain[i] != NULL) {
bus_dmamem_free(
sc->rx_bd_chain_tag,
@@ -2980,38 +3362,38 @@ bce_dma_free(struct bce_softc *sc)
}
-#ifdef BCE_JUMBO_HDRSPLIT
/* Free, unmap and destroy all page buffer descriptor chain pages. */
- for (i = 0; i < PG_PAGES; i++ ) {
- if (sc->pg_bd_chain[i] != NULL) {
- bus_dmamem_free(
- sc->pg_bd_chain_tag,
- sc->pg_bd_chain[i],
- sc->pg_bd_chain_map[i]);
- sc->pg_bd_chain[i] = NULL;
- }
+ if (bce_hdr_split == TRUE) {
+ for (i = 0; i < sc->pg_pages; i++ ) {
+ if (sc->pg_bd_chain[i] != NULL) {
+ bus_dmamem_free(
+ sc->pg_bd_chain_tag,
+ sc->pg_bd_chain[i],
+ sc->pg_bd_chain_map[i]);
+ sc->pg_bd_chain[i] = NULL;
+ }
- if (sc->pg_bd_chain_map[i] != NULL) {
- bus_dmamap_unload(
- sc->pg_bd_chain_tag,
- sc->pg_bd_chain_map[i]);
- bus_dmamap_destroy(
- sc->pg_bd_chain_tag,
- sc->pg_bd_chain_map[i]);
- sc->pg_bd_chain_map[i] = NULL;
+ if (sc->pg_bd_chain_map[i] != NULL) {
+ bus_dmamap_unload(
+ sc->pg_bd_chain_tag,
+ sc->pg_bd_chain_map[i]);
+ bus_dmamap_destroy(
+ sc->pg_bd_chain_tag,
+ sc->pg_bd_chain_map[i]);
+ sc->pg_bd_chain_map[i] = NULL;
+ }
}
- }
- /* Destroy the page buffer descriptor tag. */
- if (sc->pg_bd_chain_tag != NULL) {
- bus_dma_tag_destroy(sc->pg_bd_chain_tag);
- sc->pg_bd_chain_tag = NULL;
+ /* Destroy the page buffer descriptor tag. */
+ if (sc->pg_bd_chain_tag != NULL) {
+ bus_dma_tag_destroy(sc->pg_bd_chain_tag);
+ sc->pg_bd_chain_tag = NULL;
+ }
}
-#endif
/* Unload and destroy the TX mbuf maps. */
- for (i = 0; i < TOTAL_TX_BD; i++) {
+ for (i = 0; i < MAX_TX_BD_AVAIL; i++) {
if (sc->tx_mbuf_map[i] != NULL) {
bus_dmamap_unload(sc->tx_mbuf_tag,
sc->tx_mbuf_map[i]);
@@ -3028,7 +3410,7 @@ bce_dma_free(struct bce_softc *sc)
}
/* Unload and destroy the RX mbuf maps. */
- for (i = 0; i < TOTAL_RX_BD; i++) {
+ for (i = 0; i < MAX_RX_BD_AVAIL; i++) {
if (sc->rx_mbuf_map[i] != NULL) {
bus_dmamap_unload(sc->rx_mbuf_tag,
sc->rx_mbuf_map[i]);
@@ -3044,24 +3426,24 @@ bce_dma_free(struct bce_softc *sc)
sc->rx_mbuf_tag = NULL;
}
-#ifdef BCE_JUMBO_HDRSPLIT
/* Unload and destroy the page mbuf maps. */
- for (i = 0; i < TOTAL_PG_BD; i++) {
- if (sc->pg_mbuf_map[i] != NULL) {
- bus_dmamap_unload(sc->pg_mbuf_tag,
- sc->pg_mbuf_map[i]);
- bus_dmamap_destroy(sc->pg_mbuf_tag,
- sc->pg_mbuf_map[i]);
- sc->pg_mbuf_map[i] = NULL;
+ if (bce_hdr_split == TRUE) {
+ for (i = 0; i < MAX_PG_BD_AVAIL; i++) {
+ if (sc->pg_mbuf_map[i] != NULL) {
+ bus_dmamap_unload(sc->pg_mbuf_tag,
+ sc->pg_mbuf_map[i]);
+ bus_dmamap_destroy(sc->pg_mbuf_tag,
+ sc->pg_mbuf_map[i]);
+ sc->pg_mbuf_map[i] = NULL;
+ }
}
- }
- /* Destroy the page mbuf tag. */
- if (sc->pg_mbuf_tag != NULL) {
- bus_dma_tag_destroy(sc->pg_mbuf_tag);
- sc->pg_mbuf_tag = NULL;
+ /* Destroy the page mbuf tag. */
+ if (sc->pg_mbuf_tag != NULL) {
+ bus_dma_tag_destroy(sc->pg_mbuf_tag);
+ sc->pg_mbuf_tag = NULL;
+ }
}
-#endif
/* Destroy the parent tag */
if (sc->parent_tag != NULL) {
@@ -3234,8 +3616,7 @@ bce_dma_alloc(device_t dev)
__FUNCTION__, (uintmax_t) sc->stats_block_paddr);
/* BCM5709 uses host memory as cache for context memory. */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
sc->ctx_pages = 0x2000 / BCM_PAGE_SIZE;
if (sc->ctx_pages == 0)
sc->ctx_pages = 1;
@@ -3304,7 +3685,7 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- for (i = 0; i < TX_PAGES; i++) {
+ for (i = 0; i < sc->tx_pages; i++) {
if(bus_dmamem_alloc(sc->tx_bd_chain_tag,
(void **)&sc->tx_bd_chain[i],
@@ -3355,7 +3736,7 @@ bce_dma_alloc(device_t dev)
}
/* Create DMA maps for the TX mbufs clusters. */
- for (i = 0; i < TOTAL_TX_BD; i++) {
+ for (i = 0; i < TOTAL_TX_BD_ALLOC; i++) {
if (bus_dmamap_create(sc->tx_mbuf_tag, BUS_DMA_NOWAIT,
&sc->tx_mbuf_map[i])) {
BCE_PRINTF("%s(%d): Unable to create TX mbuf DMA "
@@ -3381,7 +3762,7 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- for (i = 0; i < RX_PAGES; i++) {
+ for (i = 0; i < sc->rx_pages; i++) {
if (bus_dmamem_alloc(sc->rx_bd_chain_tag,
(void **)&sc->rx_bd_chain[i],
@@ -3413,12 +3794,11 @@ bce_dma_alloc(device_t dev)
/*
* Create a DMA tag for RX mbufs.
*/
-#ifdef BCE_JUMBO_HDRSPLIT
- max_size = max_seg_size = ((sc->rx_bd_mbuf_alloc_size < MCLBYTES) ?
- MCLBYTES : sc->rx_bd_mbuf_alloc_size);
-#else
- max_size = max_seg_size = MJUM9BYTES;
-#endif
+ if (bce_hdr_split == TRUE)
+ max_size = max_seg_size = ((sc->rx_bd_mbuf_alloc_size < MCLBYTES) ?
+ MCLBYTES : sc->rx_bd_mbuf_alloc_size);
+ else
+ max_size = max_seg_size = MJUM9BYTES;
max_segments = 1;
DBPRINT(sc, BCE_INFO_LOAD, "%s(): Creating rx_mbuf_tag "
@@ -3437,7 +3817,7 @@ bce_dma_alloc(device_t dev)
}
/* Create DMA maps for the RX mbuf clusters. */
- for (i = 0; i < TOTAL_RX_BD; i++) {
+ for (i = 0; i < TOTAL_RX_BD_ALLOC; i++) {
if (bus_dmamap_create(sc->rx_mbuf_tag, BUS_DMA_NOWAIT,
&sc->rx_mbuf_map[i])) {
BCE_PRINTF("%s(%d): Unable to create RX mbuf "
@@ -3447,78 +3827,77 @@ bce_dma_alloc(device_t dev)
}
}
-#ifdef BCE_JUMBO_HDRSPLIT
- /*
- * Create a DMA tag for the page buffer descriptor chain,
- * allocate and clear the memory, and fetch the physical
- * address of the blocks.
- */
- if (bus_dma_tag_create(sc->parent_tag, BCM_PAGE_SIZE,
- BCE_DMA_BOUNDARY, BUS_SPACE_MAXADDR, sc->max_bus_addr,
- NULL, NULL, BCE_PG_CHAIN_PAGE_SZ, 1, BCE_PG_CHAIN_PAGE_SZ,
- 0, NULL, NULL, &sc->pg_bd_chain_tag)) {
- BCE_PRINTF("%s(%d): Could not allocate page descriptor "
- "chain DMA tag!\n", __FILE__, __LINE__);
- rc = ENOMEM;
- goto bce_dma_alloc_exit;
- }
-
- for (i = 0; i < PG_PAGES; i++) {
-
- if (bus_dmamem_alloc(sc->pg_bd_chain_tag,
- (void **)&sc->pg_bd_chain[i],
- BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
- &sc->pg_bd_chain_map[i])) {
- BCE_PRINTF("%s(%d): Could not allocate page "
- "descriptor chain DMA memory!\n",
- __FILE__, __LINE__);
+ if (bce_hdr_split == TRUE) {
+ /*
+ * Create a DMA tag for the page buffer descriptor chain,
+ * allocate and clear the memory, and fetch the physical
+ * address of the blocks.
+ */
+ if (bus_dma_tag_create(sc->parent_tag, BCM_PAGE_SIZE,
+ BCE_DMA_BOUNDARY, BUS_SPACE_MAXADDR, sc->max_bus_addr,
+ NULL, NULL, BCE_PG_CHAIN_PAGE_SZ, 1, BCE_PG_CHAIN_PAGE_SZ,
+ 0, NULL, NULL, &sc->pg_bd_chain_tag)) {
+ BCE_PRINTF("%s(%d): Could not allocate page descriptor "
+ "chain DMA tag!\n", __FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
}
- error = bus_dmamap_load(sc->pg_bd_chain_tag,
- sc->pg_bd_chain_map[i], sc->pg_bd_chain[i],
- BCE_PG_CHAIN_PAGE_SZ, bce_dma_map_addr,
- &sc->pg_bd_chain_paddr[i], BUS_DMA_NOWAIT);
-
- if (error) {
- BCE_PRINTF("%s(%d): Could not map page descriptor "
- "chain DMA memory!\n", __FILE__, __LINE__);
- rc = ENOMEM;
- goto bce_dma_alloc_exit;
- }
+ for (i = 0; i < sc->pg_pages; i++) {
+ if (bus_dmamem_alloc(sc->pg_bd_chain_tag,
+ (void **)&sc->pg_bd_chain[i],
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
+ &sc->pg_bd_chain_map[i])) {
+ BCE_PRINTF("%s(%d): Could not allocate page "
+ "descriptor chain DMA memory!\n",
+ __FILE__, __LINE__);
+ rc = ENOMEM;
+ goto bce_dma_alloc_exit;
+ }
- DBPRINT(sc, BCE_INFO_LOAD, "%s(): pg_bd_chain_paddr[%d] = "
- "0x%jX\n", __FUNCTION__, i,
- (uintmax_t) sc->pg_bd_chain_paddr[i]);
- }
+ error = bus_dmamap_load(sc->pg_bd_chain_tag,
+ sc->pg_bd_chain_map[i], sc->pg_bd_chain[i],
+ BCE_PG_CHAIN_PAGE_SZ, bce_dma_map_addr,
+ &sc->pg_bd_chain_paddr[i], BUS_DMA_NOWAIT);
- /*
- * Create a DMA tag for page mbufs.
- */
- max_size = max_seg_size = ((sc->pg_bd_mbuf_alloc_size < MCLBYTES) ?
- MCLBYTES : sc->pg_bd_mbuf_alloc_size);
+ if (error) {
+ BCE_PRINTF("%s(%d): Could not map page descriptor "
+ "chain DMA memory!\n", __FILE__, __LINE__);
+ rc = ENOMEM;
+ goto bce_dma_alloc_exit;
+ }
- if (bus_dma_tag_create(sc->parent_tag, 1, BCE_DMA_BOUNDARY,
- sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL,
- max_size, 1, max_seg_size, 0, NULL, NULL, &sc->pg_mbuf_tag)) {
- BCE_PRINTF("%s(%d): Could not allocate page mbuf "
- "DMA tag!\n", __FILE__, __LINE__);
- rc = ENOMEM;
- goto bce_dma_alloc_exit;
- }
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): pg_bd_chain_paddr[%d] = "
+ "0x%jX\n", __FUNCTION__, i,
+ (uintmax_t) sc->pg_bd_chain_paddr[i]);
+ }
- /* Create DMA maps for the page mbuf clusters. */
- for (i = 0; i < TOTAL_PG_BD; i++) {
- if (bus_dmamap_create(sc->pg_mbuf_tag, BUS_DMA_NOWAIT,
- &sc->pg_mbuf_map[i])) {
- BCE_PRINTF("%s(%d): Unable to create page mbuf "
- "DMA map!\n", __FILE__, __LINE__);
+ /*
+ * Create a DMA tag for page mbufs.
+ */
+ max_size = max_seg_size = ((sc->pg_bd_mbuf_alloc_size < MCLBYTES) ?
+ MCLBYTES : sc->pg_bd_mbuf_alloc_size);
+
+ if (bus_dma_tag_create(sc->parent_tag, 1, BCE_DMA_BOUNDARY,
+ sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL,
+ max_size, 1, max_seg_size, 0, NULL, NULL, &sc->pg_mbuf_tag)) {
+ BCE_PRINTF("%s(%d): Could not allocate page mbuf "
+ "DMA tag!\n", __FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
}
+
+ /* Create DMA maps for the page mbuf clusters. */
+ for (i = 0; i < TOTAL_PG_BD_ALLOC; i++) {
+ if (bus_dmamap_create(sc->pg_mbuf_tag, BUS_DMA_NOWAIT,
+ &sc->pg_mbuf_map[i])) {
+ BCE_PRINTF("%s(%d): Unable to create page mbuf "
+ "DMA map!\n", __FILE__, __LINE__);
+ rc = ENOMEM;
+ goto bce_dma_alloc_exit;
+ }
+ }
}
-#endif
bce_dma_alloc_exit:
DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_CTX);
@@ -3553,8 +3932,8 @@ bce_release_resources(struct bce_softc *sc)
if (sc->bce_res_irq != NULL) {
DBPRINT(sc, BCE_INFO_RESET, "Releasing IRQ.\n");
- bus_release_resource(dev, SYS_RES_IRQ, sc->bce_irq_rid,
- sc->bce_res_irq);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ rman_get_rid(sc->bce_res_irq), sc->bce_res_irq);
}
if (sc->bce_flags & (BCE_USING_MSI_FLAG | BCE_USING_MSIX_FLAG)) {
@@ -3878,8 +4257,7 @@ bce_init_rxp_cpu(struct bce_softc *sc)
cpu_reg.spad_base = BCE_RXP_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
fw.ver_major = bce_RXP_b09FwReleaseMajor;
fw.ver_minor = bce_RXP_b09FwReleaseMinor;
fw.ver_fix = bce_RXP_b09FwReleaseFix;
@@ -3977,8 +4355,7 @@ bce_init_txp_cpu(struct bce_softc *sc)
cpu_reg.spad_base = BCE_TXP_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
fw.ver_major = bce_TXP_b09FwReleaseMajor;
fw.ver_minor = bce_TXP_b09FwReleaseMinor;
fw.ver_fix = bce_TXP_b09FwReleaseFix;
@@ -4075,8 +4452,7 @@ bce_init_tpat_cpu(struct bce_softc *sc)
cpu_reg.spad_base = BCE_TPAT_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
fw.ver_major = bce_TPAT_b09FwReleaseMajor;
fw.ver_minor = bce_TPAT_b09FwReleaseMinor;
fw.ver_fix = bce_TPAT_b09FwReleaseFix;
@@ -4173,8 +4549,7 @@ bce_init_cp_cpu(struct bce_softc *sc)
cpu_reg.spad_base = BCE_CP_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
fw.ver_major = bce_CP_b09FwReleaseMajor;
fw.ver_minor = bce_CP_b09FwReleaseMinor;
fw.ver_fix = bce_CP_b09FwReleaseFix;
@@ -4271,8 +4646,7 @@ bce_init_com_cpu(struct bce_softc *sc)
cpu_reg.spad_base = BCE_COM_SCRATCH;
cpu_reg.mips_view_base = 0x8000000;
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
fw.ver_major = bce_COM_b09FwReleaseMajor;
fw.ver_minor = bce_COM_b09FwReleaseMinor;
fw.ver_fix = bce_COM_b09FwReleaseFix;
@@ -4355,8 +4729,7 @@ bce_init_cpus(struct bce_softc *sc)
{
DBENTER(BCE_VERBOSE_RESET);
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
if ((BCE_CHIP_REV(sc) == BCE_CHIP_REV_Ax)) {
bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc1,
@@ -4404,8 +4777,7 @@ bce_init_ctx(struct bce_softc *sc)
rc = 0;
DBENTER(BCE_VERBOSE_RESET | BCE_VERBOSE_CTX);
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
retry_cnt = CTX_INIT_RETRY_COUNT;
DBPRINT(sc, BCE_INFO_CTX, "Initializing 5709 context.\n");
@@ -4593,9 +4965,9 @@ bce_stop(struct bce_softc *sc)
bce_disable_intr(sc);
/* Free RX buffers. */
-#ifdef BCE_JUMBO_HDRSPLIT
- bce_free_pg_chain(sc);
-#endif
+ if (bce_hdr_split == TRUE) {
+ bce_free_pg_chain(sc);
+ }
bce_free_rx_chain(sc);
/* Free TX buffers. */
@@ -4614,14 +4986,25 @@ bce_stop(struct bce_softc *sc)
static int
bce_reset(struct bce_softc *sc, u32 reset_code)
{
- u32 val;
+ u32 emac_mode_save, val;
int i, rc = 0;
+ static const u32 emac_mode_mask = BCE_EMAC_MODE_PORT |
+ BCE_EMAC_MODE_HALF_DUPLEX | BCE_EMAC_MODE_25G;
DBENTER(BCE_VERBOSE_RESET);
DBPRINT(sc, BCE_VERBOSE_RESET, "%s(): reset_code = 0x%08X\n",
__FUNCTION__, reset_code);
+ /*
+ * If ASF/IPMI is operational, then the EMAC Mode register already
+ * contains appropriate values for the link settings that have
+ * been auto-negotiated. Resetting the chip will clobber those
+ * values. Save the important bits so we can restore them after
+ * the reset.
+ */
+ emac_mode_save = REG_RD(sc, BCE_EMAC_MODE) & emac_mode_mask;
+
/* Wait for pending PCI transactions to complete. */
REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS,
BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
@@ -4632,8 +5015,7 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
DELAY(5);
/* Disable DMA */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
val = REG_RD(sc, BCE_MISC_NEW_CORE_CTL);
val &= ~BCE_MISC_NEW_CORE_CTL_DMA_ENABLE;
REG_WR(sc, BCE_MISC_NEW_CORE_CTL, val);
@@ -4655,8 +5037,7 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
val = REG_RD(sc, BCE_MISC_ID);
/* Chip reset. */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
REG_WR(sc, BCE_MISC_COMMAND, BCE_MISC_COMMAND_SW_RESET);
REG_RD(sc, BCE_MISC_COMMAND);
DELAY(5);
@@ -4709,8 +5090,15 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
if (rc)
BCE_PRINTF("%s(%d): Firmware did not complete "
"initialization!\n", __FILE__, __LINE__);
+ /* Get firmware capabilities. */
+ bce_fw_cap_init(sc);
bce_reset_exit:
+ /* Restore EMAC Mode bits needed to keep ASF/IPMI running. */
+ val = REG_RD(sc, BCE_EMAC_MODE);
+ val = (val & ~emac_mode_mask) | emac_mode_save;
+ REG_WR(sc, BCE_EMAC_MODE, val);
+
DBEXIT(BCE_VERBOSE_RESET);
return (rc);
}
@@ -4785,8 +5173,7 @@ bce_chipinit(struct bce_softc *sc)
val |= BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
/* Enable bins used on the 5709. */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
val |= BCE_MQ_CONFIG_BIN_MQ_MODE;
if (BCE_CHIP_ID(sc) == BCE_CHIP_ID_5709_A1)
val |= BCE_MQ_CONFIG_HALT_DIS;
@@ -4940,8 +5327,7 @@ bce_blockinit(struct bce_softc *sc)
}
/* Enable DMA */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
val = REG_RD(sc, BCE_MISC_NEW_CORE_CTL);
val |= BCE_MISC_NEW_CORE_CTL_DMA_ENABLE;
REG_WR(sc, BCE_MISC_NEW_CORE_CTL, val);
@@ -4965,8 +5351,7 @@ bce_blockinit(struct bce_softc *sc)
}
/* Enable all remaining blocks in the MAC. */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716))
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709)
REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
BCE_MISC_ENABLE_DEFAULT_XI);
else
@@ -5008,10 +5393,10 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
DBENTER(BCE_EXTREME_RESET | BCE_EXTREME_RECV | BCE_EXTREME_LOAD);
/* Make sure the inputs are valid. */
- DBRUNIF((*chain_prod > MAX_RX_BD),
+ DBRUNIF((*chain_prod > MAX_RX_BD_ALLOC),
BCE_PRINTF("%s(%d): RX producer out of range: "
"0x%04X > 0x%04X\n", __FILE__, __LINE__,
- *chain_prod, (u16) MAX_RX_BD));
+ *chain_prod, (u16) MAX_RX_BD_ALLOC));
DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): prod = 0x%04X, "
"chain_prod = 0x%04X, prod_bseq = 0x%08X\n", __FUNCTION__,
@@ -5034,15 +5419,11 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
goto bce_get_rx_buf_exit);
/* This is a new mbuf allocation. */
-#ifdef BCE_JUMBO_HDRSPLIT
- MGETHDR(m_new, M_DONTWAIT, MT_DATA);
-#else
- if (sc->rx_bd_mbuf_alloc_size <= MCLBYTES)
- m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (bce_hdr_split == TRUE)
+ MGETHDR(m_new, M_DONTWAIT, MT_DATA);
else
m_new = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR,
sc->rx_bd_mbuf_alloc_size);
-#endif
if (m_new == NULL) {
sc->mbuf_alloc_failed_count++;
@@ -5115,7 +5496,6 @@ bce_get_rx_buf_exit:
}
-#ifdef BCE_JUMBO_HDRSPLIT
/****************************************************************************/
/* Encapsulate an mbuf cluster into the page chain. */
/* */
@@ -5138,10 +5518,10 @@ bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
DBENTER(BCE_EXTREME_RESET | BCE_EXTREME_RECV | BCE_EXTREME_LOAD);
/* Make sure the inputs are valid. */
- DBRUNIF((*prod_idx > MAX_PG_BD),
+ DBRUNIF((*prod_idx > MAX_PG_BD_ALLOC),
BCE_PRINTF("%s(%d): page producer out of range: "
"0x%04X > 0x%04X\n", __FILE__, __LINE__,
- *prod_idx, (u16) MAX_PG_BD));
+ *prod_idx, (u16) MAX_PG_BD_ALLOC));
DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): prod = 0x%04X, "
"chain_prod = 0x%04X\n", __FUNCTION__, *prod, *prod_idx);
@@ -5226,7 +5606,6 @@ bce_get_pg_buf_exit:
return(rc);
}
-#endif /* BCE_JUMBO_HDRSPLIT */
/****************************************************************************/
@@ -5243,8 +5622,7 @@ bce_init_tx_context(struct bce_softc *sc)
DBENTER(BCE_VERBOSE_RESET | BCE_VERBOSE_SEND | BCE_VERBOSE_CTX);
/* Initialize the context ID for an L2 TX chain. */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
/* Set the CID type to support an L2 connection. */
val = BCE_L2CTX_TX_TYPE_TYPE_L2_XI |
BCE_L2CTX_TX_TYPE_SIZE_L2_XI;
@@ -5299,7 +5677,7 @@ bce_init_tx_chain(struct bce_softc *sc)
sc->tx_cons = 0;
sc->tx_prod_bseq = 0;
sc->used_tx_bd = 0;
- sc->max_tx_bd = USABLE_TX_BD;
+ sc->max_tx_bd = USABLE_TX_BD_ALLOC;
DBRUN(sc->tx_hi_watermark = 0);
DBRUN(sc->tx_full_count = 0);
@@ -5314,24 +5692,26 @@ bce_init_tx_chain(struct bce_softc *sc)
*/
/* Set the TX next pointer chain entries. */
- for (i = 0; i < TX_PAGES; i++) {
+ for (i = 0; i < sc->tx_pages; i++) {
int j;
txbd = &sc->tx_bd_chain[i][USABLE_TX_BD_PER_PAGE];
/* Check if we've reached the last page. */
- if (i == (TX_PAGES - 1))
+ if (i == (sc->tx_pages - 1))
j = 0;
else
j = i + 1;
- txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(sc->tx_bd_chain_paddr[j]));
- txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(sc->tx_bd_chain_paddr[j]));
+ txbd->tx_bd_haddr_hi =
+ htole32(BCE_ADDR_HI(sc->tx_bd_chain_paddr[j]));
+ txbd->tx_bd_haddr_lo =
+ htole32(BCE_ADDR_LO(sc->tx_bd_chain_paddr[j]));
}
bce_init_tx_context(sc);
- DBRUNMSG(BCE_INSANE_SEND, bce_dump_tx_chain(sc, 0, TOTAL_TX_BD));
+ DBRUNMSG(BCE_INSANE_SEND, bce_dump_tx_chain(sc, 0, TOTAL_TX_BD_ALLOC));
DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_SEND | BCE_VERBOSE_LOAD);
return(rc);
@@ -5352,7 +5732,7 @@ bce_free_tx_chain(struct bce_softc *sc)
DBENTER(BCE_VERBOSE_RESET | BCE_VERBOSE_SEND | BCE_VERBOSE_UNLOAD);
/* Unmap, unload, and free any mbufs still in the TX mbuf chain. */
- for (i = 0; i < TOTAL_TX_BD; i++) {
+ for (i = 0; i < MAX_TX_BD_AVAIL; i++) {
if (sc->tx_mbuf_ptr[i] != NULL) {
if (sc->tx_mbuf_map[i] != NULL)
bus_dmamap_sync(sc->tx_mbuf_tag,
@@ -5365,7 +5745,7 @@ bce_free_tx_chain(struct bce_softc *sc)
}
/* Clear each TX chain page. */
- for (i = 0; i < TX_PAGES; i++)
+ for (i = 0; i < sc->tx_pages; i++)
bzero((char *)sc->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ);
sc->used_tx_bd = 0;
@@ -5405,21 +5785,20 @@ bce_init_rx_context(struct bce_softc *sc)
* when pause frames can be stopped (the high
* watermark).
*/
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
u32 lo_water, hi_water;
- if (sc->bce_flags && BCE_USING_TX_FLOW_CONTROL) {
+ if (sc->bce_flags & BCE_USING_TX_FLOW_CONTROL) {
lo_water = BCE_L2CTX_RX_LO_WATER_MARK_DEFAULT;
} else {
lo_water = 0;
}
- if (lo_water >= USABLE_RX_BD) {
+ if (lo_water >= USABLE_RX_BD_ALLOC) {
lo_water = 0;
}
- hi_water = USABLE_RX_BD / 4;
+ hi_water = USABLE_RX_BD_ALLOC / 4;
if (hi_water <= lo_water) {
lo_water = 0;
@@ -5440,8 +5819,7 @@ bce_init_rx_context(struct bce_softc *sc)
CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_CTX_TYPE, val);
/* Setup the MQ BIN mapping for l2_ctx_host_bseq. */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
val = REG_RD(sc, BCE_MQ_MAP_L2_5);
REG_WR(sc, BCE_MQ_MAP_L2_5, val | BCE_MQ_MAP_L2_5_ARM);
}
@@ -5475,17 +5853,17 @@ bce_init_rx_chain(struct bce_softc *sc)
sc->rx_prod = 0;
sc->rx_cons = 0;
sc->rx_prod_bseq = 0;
- sc->free_rx_bd = USABLE_RX_BD;
- sc->max_rx_bd = USABLE_RX_BD;
+ sc->free_rx_bd = USABLE_RX_BD_ALLOC;
+ sc->max_rx_bd = USABLE_RX_BD_ALLOC;
/* Initialize the RX next pointer chain entries. */
- for (i = 0; i < RX_PAGES; i++) {
+ for (i = 0; i < sc->rx_pages; i++) {
int j;
rxbd = &sc->rx_bd_chain[i][USABLE_RX_BD_PER_PAGE];
/* Check if we've reached the last page. */
- if (i == (RX_PAGES - 1))
+ if (i == (sc->rx_pages - 1))
j = 0;
else
j = i + 1;
@@ -5500,16 +5878,17 @@ bce_init_rx_chain(struct bce_softc *sc)
/* Fill up the RX chain. */
bce_fill_rx_chain(sc);
- DBRUN(sc->rx_low_watermark = USABLE_RX_BD);
+ DBRUN(sc->rx_low_watermark = USABLE_RX_BD_ALLOC);
DBRUN(sc->rx_empty_count = 0);
- for (i = 0; i < RX_PAGES; i++) {
+ for (i = 0; i < sc->rx_pages; i++) {
bus_dmamap_sync(sc->rx_bd_chain_tag, sc->rx_bd_chain_map[i],
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
bce_init_rx_context(sc);
- DBRUNMSG(BCE_EXTREME_RECV, bce_dump_rx_bd_chain(sc, 0, TOTAL_RX_BD));
+ DBRUNMSG(BCE_EXTREME_RECV,
+ bce_dump_rx_bd_chain(sc, 0, TOTAL_RX_BD_ALLOC));
DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_RECV | BCE_VERBOSE_LOAD |
BCE_VERBOSE_CTX);
@@ -5583,7 +5962,7 @@ bce_free_rx_chain(struct bce_softc *sc)
DBENTER(BCE_VERBOSE_RESET | BCE_VERBOSE_RECV | BCE_VERBOSE_UNLOAD);
/* Free any mbufs still in the RX mbuf chain. */
- for (i = 0; i < TOTAL_RX_BD; i++) {
+ for (i = 0; i < MAX_RX_BD_AVAIL; i++) {
if (sc->rx_mbuf_ptr[i] != NULL) {
if (sc->rx_mbuf_map[i] != NULL)
bus_dmamap_sync(sc->rx_mbuf_tag,
@@ -5596,7 +5975,7 @@ bce_free_rx_chain(struct bce_softc *sc)
}
/* Clear each RX chain page. */
- for (i = 0; i < RX_PAGES; i++)
+ for (i = 0; i < sc->rx_pages; i++)
if (sc->rx_bd_chain[i] != NULL) {
bzero((char *)sc->rx_bd_chain[i],
BCE_RX_CHAIN_PAGE_SZ);
@@ -5613,7 +5992,6 @@ bce_free_rx_chain(struct bce_softc *sc)
}
-#ifdef BCE_JUMBO_HDRSPLIT
/****************************************************************************/
/* Allocate memory and initialize the page data structures. */
/* Assumes that bce_init_rx_chain() has not already been called. */
@@ -5634,31 +6012,32 @@ bce_init_pg_chain(struct bce_softc *sc)
/* Initialize the page producer and consumer indices. */
sc->pg_prod = 0;
sc->pg_cons = 0;
- sc->free_pg_bd = USABLE_PG_BD;
- sc->max_pg_bd = USABLE_PG_BD;
+ sc->free_pg_bd = USABLE_PG_BD_ALLOC;
+ sc->max_pg_bd = USABLE_PG_BD_ALLOC;
DBRUN(sc->pg_low_watermark = sc->max_pg_bd);
DBRUN(sc->pg_empty_count = 0);
/* Initialize the page next pointer chain entries. */
- for (i = 0; i < PG_PAGES; i++) {
+ for (i = 0; i < sc->pg_pages; i++) {
int j;
pgbd = &sc->pg_bd_chain[i][USABLE_PG_BD_PER_PAGE];
/* Check if we've reached the last page. */
- if (i == (PG_PAGES - 1))
+ if (i == (sc->pg_pages - 1))
j = 0;
else
j = i + 1;
/* Setup the chain page pointers. */
- pgbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(sc->pg_bd_chain_paddr[j]));
- pgbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(sc->pg_bd_chain_paddr[j]));
+ pgbd->rx_bd_haddr_hi =
+ htole32(BCE_ADDR_HI(sc->pg_bd_chain_paddr[j]));
+ pgbd->rx_bd_haddr_lo =
+ htole32(BCE_ADDR_LO(sc->pg_bd_chain_paddr[j]));
}
/* Setup the MQ BIN mapping for host_pg_bidx. */
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716))
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709)
REG_WR(sc, BCE_MQ_MAP_L2_3, BCE_MQ_MAP_L2_3_DEFAULT);
CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_PG_BUF_SIZE, 0);
@@ -5680,12 +6059,13 @@ bce_init_pg_chain(struct bce_softc *sc)
/* Fill up the page chain. */
bce_fill_pg_chain(sc);
- for (i = 0; i < PG_PAGES; i++) {
+ for (i = 0; i < sc->pg_pages; i++) {
bus_dmamap_sync(sc->pg_bd_chain_tag, sc->pg_bd_chain_map[i],
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
- DBRUNMSG(BCE_EXTREME_RECV, bce_dump_pg_chain(sc, 0, TOTAL_PG_BD));
+ DBRUNMSG(BCE_EXTREME_RECV,
+ bce_dump_pg_chain(sc, 0, TOTAL_PG_BD_ALLOC));
DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_RECV | BCE_VERBOSE_LOAD |
BCE_VERBOSE_CTX);
return(rc);
@@ -5753,7 +6133,7 @@ bce_free_pg_chain(struct bce_softc *sc)
DBENTER(BCE_VERBOSE_RESET | BCE_VERBOSE_RECV | BCE_VERBOSE_UNLOAD);
/* Free any mbufs still in the mbuf page chain. */
- for (i = 0; i < TOTAL_PG_BD; i++) {
+ for (i = 0; i < MAX_PG_BD_AVAIL; i++) {
if (sc->pg_mbuf_ptr[i] != NULL) {
if (sc->pg_mbuf_map[i] != NULL)
bus_dmamap_sync(sc->pg_mbuf_tag,
@@ -5766,7 +6146,7 @@ bce_free_pg_chain(struct bce_softc *sc)
}
/* Clear each page chain pages. */
- for (i = 0; i < PG_PAGES; i++)
+ for (i = 0; i < sc->pg_pages; i++)
bzero((char *)sc->pg_bd_chain[i], BCE_PG_CHAIN_PAGE_SZ);
sc->free_pg_bd = sc->max_pg_bd;
@@ -5778,7 +6158,55 @@ bce_free_pg_chain(struct bce_softc *sc)
DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_RECV | BCE_VERBOSE_UNLOAD);
}
-#endif /* BCE_JUMBO_HDRSPLIT */
+
+
+static u32
+bce_get_rphy_link(struct bce_softc *sc)
+{
+ u32 advertise, link;
+ int fdpx;
+
+ advertise = 0;
+ fdpx = 0;
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG) != 0)
+ link = bce_shmem_rd(sc, BCE_RPHY_SERDES_LINK);
+ else
+ link = bce_shmem_rd(sc, BCE_RPHY_COPPER_LINK);
+ if (link & BCE_NETLINK_ANEG_ENB)
+ advertise |= BCE_NETLINK_ANEG_ENB;
+ if (link & BCE_NETLINK_SPEED_10HALF)
+ advertise |= BCE_NETLINK_SPEED_10HALF;
+ if (link & BCE_NETLINK_SPEED_10FULL) {
+ advertise |= BCE_NETLINK_SPEED_10FULL;
+ fdpx++;
+ }
+ if (link & BCE_NETLINK_SPEED_100HALF)
+ advertise |= BCE_NETLINK_SPEED_100HALF;
+ if (link & BCE_NETLINK_SPEED_100FULL) {
+ advertise |= BCE_NETLINK_SPEED_100FULL;
+ fdpx++;
+ }
+ if (link & BCE_NETLINK_SPEED_1000HALF)
+ advertise |= BCE_NETLINK_SPEED_1000HALF;
+ if (link & BCE_NETLINK_SPEED_1000FULL) {
+ advertise |= BCE_NETLINK_SPEED_1000FULL;
+ fdpx++;
+ }
+ if (link & BCE_NETLINK_SPEED_2500HALF)
+ advertise |= BCE_NETLINK_SPEED_2500HALF;
+ if (link & BCE_NETLINK_SPEED_2500FULL) {
+ advertise |= BCE_NETLINK_SPEED_2500FULL;
+ fdpx++;
+ }
+ if (fdpx)
+ advertise |= BCE_NETLINK_FC_PAUSE_SYM |
+ BCE_NETLINK_FC_PAUSE_ASYM;
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG) == 0)
+ advertise |= BCE_NETLINK_PHY_APP_REMOTE |
+ BCE_NETLINK_ETH_AT_WIRESPEED;
+
+ return (advertise);
+}
/****************************************************************************/
@@ -5815,25 +6243,111 @@ bce_ifmedia_upd_locked(struct ifnet *ifp)
{
struct bce_softc *sc = ifp->if_softc;
struct mii_data *mii;
- int error;
+ struct mii_softc *miisc;
+ struct ifmedia *ifm;
+ u32 link;
+ int error, fdx;
DBENTER(BCE_VERBOSE_PHY);
error = 0;
BCE_LOCK_ASSERT(sc);
- mii = device_get_softc(sc->bce_miibus);
+ sc->bce_link_up = FALSE;
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0) {
+ ifm = &sc->bce_ifmedia;
+ if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
+ return (EINVAL);
+ link = 0;
+ fdx = IFM_OPTIONS(ifm->ifm_media) & IFM_FDX;
+ switch(IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ /*
+ * Check advertised link of remote PHY by reading
+ * BCE_RPHY_SERDES_LINK or BCE_RPHY_COPPER_LINK.
+ * Always use the same link type of remote PHY.
+ */
+ link = bce_get_rphy_link(sc);
+ break;
+ case IFM_2500_SX:
+ if ((sc->bce_phy_flags &
+ (BCE_PHY_REMOTE_PORT_FIBER_FLAG |
+ BCE_PHY_2_5G_CAPABLE_FLAG)) == 0)
+ return (EINVAL);
+ /*
+ * XXX
+ * Have to enable forced 2.5Gbps configuration.
+ */
+ if (fdx != 0)
+ link |= BCE_NETLINK_SPEED_2500FULL;
+ else
+ link |= BCE_NETLINK_SPEED_2500HALF;
+ break;
+ case IFM_1000_SX:
+ if ((sc->bce_phy_flags &
+ BCE_PHY_REMOTE_PORT_FIBER_FLAG) == 0)
+ return (EINVAL);
+ /*
+ * XXX
+ * Have to disable 2.5Gbps configuration.
+ */
+ if (fdx != 0)
+ link = BCE_NETLINK_SPEED_1000FULL;
+ else
+ link = BCE_NETLINK_SPEED_1000HALF;
+ break;
+ case IFM_1000_T:
+ if (sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG)
+ return (EINVAL);
+ if (fdx != 0)
+ link = BCE_NETLINK_SPEED_1000FULL;
+ else
+ link = BCE_NETLINK_SPEED_1000HALF;
+ break;
+ case IFM_100_TX:
+ if (sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG)
+ return (EINVAL);
+ if (fdx != 0)
+ link = BCE_NETLINK_SPEED_100FULL;
+ else
+ link = BCE_NETLINK_SPEED_100HALF;
+ break;
+ case IFM_10_T:
+ if (sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG)
+ return (EINVAL);
+ if (fdx != 0)
+ link = BCE_NETLINK_SPEED_10FULL;
+ else
+ link = BCE_NETLINK_SPEED_10HALF;
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (IFM_SUBTYPE(ifm->ifm_media) != IFM_AUTO) {
+ /*
+ * XXX
+ * Advertise pause capability for full-duplex media.
+ */
+ if (fdx != 0)
+ link |= BCE_NETLINK_FC_PAUSE_SYM |
+ BCE_NETLINK_FC_PAUSE_ASYM;
+ if ((sc->bce_phy_flags &
+ BCE_PHY_REMOTE_PORT_FIBER_FLAG) == 0)
+ link |= BCE_NETLINK_PHY_APP_REMOTE |
+ BCE_NETLINK_ETH_AT_WIRESPEED;
+ }
- /* Make sure the MII bus has been enumerated. */
- if (mii) {
- sc->bce_link_up = FALSE;
- if (mii->mii_instance) {
- struct mii_softc *miisc;
+ bce_shmem_wr(sc, BCE_MB_ARGS_0, link);
+ error = bce_fw_sync(sc, BCE_DRV_MSG_CODE_CMD_SET_LINK);
+ } else {
+ mii = device_get_softc(sc->bce_miibus);
+ /* Make sure the MII bus has been enumerated. */
+ if (mii) {
LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
- mii_phy_reset(miisc);
+ mii_phy_reset(miisc);
+ error = mii_mediachg(mii);
}
- error = mii_mediachg(mii);
}
DBEXIT(BCE_VERBOSE_PHY);
@@ -5841,6 +6355,85 @@ bce_ifmedia_upd_locked(struct ifnet *ifp)
}
+static void
+bce_ifmedia_sts_rphy(struct bce_softc *sc, struct ifmediareq *ifmr)
+{
+ struct ifnet *ifp;
+ u32 link;
+
+ ifp = sc->bce_ifp;
+ BCE_LOCK_ASSERT(sc);
+
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_active = IFM_ETHER;
+ link = bce_shmem_rd(sc, BCE_LINK_STATUS);
+ /* XXX Handle heart beat status? */
+ if ((link & BCE_LINK_STATUS_LINK_UP) != 0)
+ ifmr->ifm_status |= IFM_ACTIVE;
+ else {
+ ifmr->ifm_active |= IFM_NONE;
+ ifp->if_baudrate = 0;
+ return;
+ }
+ switch (link & BCE_LINK_STATUS_SPEED_MASK) {
+ case BCE_LINK_STATUS_10HALF:
+ ifmr->ifm_active |= IFM_10_T | IFM_HDX;
+ ifp->if_baudrate = IF_Mbps(10UL);
+ break;
+ case BCE_LINK_STATUS_10FULL:
+ ifmr->ifm_active |= IFM_10_T | IFM_FDX;
+ ifp->if_baudrate = IF_Mbps(10UL);
+ break;
+ case BCE_LINK_STATUS_100HALF:
+ ifmr->ifm_active |= IFM_100_TX | IFM_HDX;
+ ifp->if_baudrate = IF_Mbps(100UL);
+ break;
+ case BCE_LINK_STATUS_100FULL:
+ ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
+ ifp->if_baudrate = IF_Mbps(100UL);
+ break;
+ case BCE_LINK_STATUS_1000HALF:
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG) == 0)
+ ifmr->ifm_active |= IFM_1000_T | IFM_HDX;
+ else
+ ifmr->ifm_active |= IFM_1000_SX | IFM_HDX;
+ ifp->if_baudrate = IF_Mbps(1000UL);
+ break;
+ case BCE_LINK_STATUS_1000FULL:
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG) == 0)
+ ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
+ else
+ ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
+ ifp->if_baudrate = IF_Mbps(1000UL);
+ break;
+ case BCE_LINK_STATUS_2500HALF:
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG) == 0) {
+ ifmr->ifm_active |= IFM_NONE;
+ return;
+ } else
+ ifmr->ifm_active |= IFM_2500_SX | IFM_HDX;
+ ifp->if_baudrate = IF_Mbps(2500UL);
+ break;
+ case BCE_LINK_STATUS_2500FULL:
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_PORT_FIBER_FLAG) == 0) {
+ ifmr->ifm_active |= IFM_NONE;
+ return;
+ } else
+ ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
+ ifp->if_baudrate = IF_Mbps(2500UL);
+ break;
+ default:
+ ifmr->ifm_active |= IFM_NONE;
+ return;
+ }
+
+ if ((link & BCE_LINK_STATUS_RX_FC_ENABLED) != 0)
+ ifmr->ifm_active |= IFM_ETH_RXPAUSE;
+ if ((link & BCE_LINK_STATUS_TX_FC_ENABLED) != 0)
+ ifmr->ifm_active |= IFM_ETH_TXPAUSE;
+}
+
+
/****************************************************************************/
/* Reports current media status. */
/* */
@@ -5861,11 +6454,15 @@ bce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
BCE_UNLOCK(sc);
return;
}
- mii = device_get_softc(sc->bce_miibus);
- mii_pollstat(mii);
- ifmr->ifm_active = mii->mii_media_active;
- ifmr->ifm_status = mii->mii_media_status;
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0)
+ bce_ifmedia_sts_rphy(sc, ifmr);
+ else {
+ mii = device_get_softc(sc->bce_miibus);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ }
BCE_UNLOCK(sc);
@@ -5902,14 +6499,26 @@ bce_phy_intr(struct bce_softc *sc)
STATUS_ATTN_BITS_LINK_STATE);
DBPRINT(sc, BCE_INFO_PHY, "%s(): Link is now UP.\n",
__FUNCTION__);
- }
- else {
+ } else {
REG_WR(sc, BCE_PCICFG_STATUS_BIT_CLEAR_CMD,
STATUS_ATTN_BITS_LINK_STATE);
DBPRINT(sc, BCE_INFO_PHY, "%s(): Link is now DOWN.\n",
__FUNCTION__);
}
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0) {
+ if (new_link_state) {
+ if (bootverbose)
+ if_printf(sc->bce_ifp, "link UP\n");
+ if_link_state_change(sc->bce_ifp,
+ LINK_STATE_UP);
+ } else {
+ if (bootverbose)
+ if_printf(sc->bce_ifp, "link DOWN\n");
+ if_link_state_change(sc->bce_ifp,
+ LINK_STATE_DOWN);
+ }
+ }
/*
* Assume link is down and allow
* tick routine to update the state
@@ -5962,10 +6571,8 @@ bce_rx_intr(struct bce_softc *sc)
unsigned int pkt_len;
u16 sw_rx_cons, sw_rx_cons_idx, hw_rx_cons;
u32 status;
-#ifdef BCE_JUMBO_HDRSPLIT
unsigned int rem_len;
u16 sw_pg_cons, sw_pg_cons_idx;
-#endif
DBENTER(BCE_VERBOSE_RECV | BCE_VERBOSE_INTR);
DBRUN(sc->interrupts_rx++);
@@ -5974,26 +6581,23 @@ bce_rx_intr(struct bce_softc *sc)
__FUNCTION__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq);
/* Prepare the RX chain pages to be accessed by the host CPU. */
- for (int i = 0; i < RX_PAGES; i++)
+ for (int i = 0; i < sc->rx_pages; i++)
bus_dmamap_sync(sc->rx_bd_chain_tag,
sc->rx_bd_chain_map[i], BUS_DMASYNC_POSTREAD);
-#ifdef BCE_JUMBO_HDRSPLIT
/* Prepare the page chain pages to be accessed by the host CPU. */
- for (int i = 0; i < PG_PAGES; i++)
- bus_dmamap_sync(sc->pg_bd_chain_tag,
- sc->pg_bd_chain_map[i], BUS_DMASYNC_POSTREAD);
-#endif
+ if (bce_hdr_split == TRUE) {
+ for (int i = 0; i < sc->pg_pages; i++)
+ bus_dmamap_sync(sc->pg_bd_chain_tag,
+ sc->pg_bd_chain_map[i], BUS_DMASYNC_POSTREAD);
+ }
/* Get the hardware's view of the RX consumer index. */
hw_rx_cons = sc->hw_rx_cons = bce_get_hw_rx_cons(sc);
/* Get working copies of the driver's view of the consumer indices. */
sw_rx_cons = sc->rx_cons;
-
-#ifdef BCE_JUMBO_HDRSPLIT
sw_pg_cons = sc->pg_cons;
-#endif
/* Update some debug statistics counters */
DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
@@ -6036,7 +6640,7 @@ bce_rx_intr(struct bce_softc *sc)
* with an l2_fhdr structure which provides status
* information about the received frame (including
* VLAN tags and checksum info). The frames are
- * also automatically adjusted to align the IP
+ * also automatically adjusted to word align the IP
* header (i.e. two null bytes are inserted before
* the Ethernet header). As a result the data
* DMA'd by the controller into the mbuf looks
@@ -6065,96 +6669,104 @@ bce_rx_intr(struct bce_softc *sc)
*/
m_adj(m0, sizeof(struct l2_fhdr) + ETHER_ALIGN);
-#ifdef BCE_JUMBO_HDRSPLIT
/*
- * Check whether the received frame fits in a single
- * mbuf or not (i.e. packet data + FCS <=
- * sc->rx_bd_mbuf_data_len bytes).
+ * When split header mode is used, an ethernet frame
+ * may be split across the receive chain and the
+ * page chain. If that occurs an mbuf cluster must be
+ * reassembled from the individual mbuf pieces.
*/
- if (pkt_len > m0->m_len) {
- /*
- * The received frame is larger than a single mbuf.
- * If the frame was a TCP frame then only the TCP
- * header is placed in the mbuf, the remaining
- * payload (including FCS) is placed in the page
- * chain, the SPLIT flag is set, and the header
- * length is placed in the IP checksum field.
- * If the frame is not a TCP frame then the mbuf
- * is filled and the remaining bytes are placed
- * in the page chain.
- */
-
- DBPRINT(sc, BCE_INFO_RECV, "%s(): Found a large "
- "packet.\n", __FUNCTION__);
-
+ if (bce_hdr_split == TRUE) {
/*
- * When the page chain is enabled and the TCP
- * header has been split from the TCP payload,
- * the ip_xsum structure will reflect the length
- * of the TCP header, not the IP checksum. Set
- * the packet length of the mbuf accordingly.
+ * Check whether the received frame fits in a single
+ * mbuf or not (i.e. packet data + FCS <=
+ * sc->rx_bd_mbuf_data_len bytes).
*/
- if (status & L2_FHDR_STATUS_SPLIT)
- m0->m_len = l2fhdr->l2_fhdr_ip_xsum;
-
- rem_len = pkt_len - m0->m_len;
-
- /* Pull mbufs off the page chain for the remaining data. */
- while (rem_len > 0) {
- struct mbuf *m_pg;
-
- sw_pg_cons_idx = PG_CHAIN_IDX(sw_pg_cons);
+ if (pkt_len > m0->m_len) {
+ /*
+ * The received frame is larger than a single mbuf.
+ * If the frame was a TCP frame then only the TCP
+ * header is placed in the mbuf, the remaining
+ * payload (including FCS) is placed in the page
+ * chain, the SPLIT flag is set, and the header
+ * length is placed in the IP checksum field.
+ * If the frame is not a TCP frame then the mbuf
+ * is filled and the remaining bytes are placed
+ * in the page chain.
+ */
- /* Remove the mbuf from the page chain. */
- m_pg = sc->pg_mbuf_ptr[sw_pg_cons_idx];
- sc->pg_mbuf_ptr[sw_pg_cons_idx] = NULL;
- DBRUN(sc->debug_pg_mbuf_alloc--);
- sc->free_pg_bd++;
+ DBPRINT(sc, BCE_INFO_RECV, "%s(): Found a large "
+ "packet.\n", __FUNCTION__);
+ DBRUN(sc->split_header_frames_rcvd++);
- /* Unmap the page chain mbuf from DMA space. */
- bus_dmamap_sync(sc->pg_mbuf_tag,
- sc->pg_mbuf_map[sw_pg_cons_idx],
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->pg_mbuf_tag,
- sc->pg_mbuf_map[sw_pg_cons_idx]);
-
- /* Adjust the mbuf length. */
- if (rem_len < m_pg->m_len) {
- /* The mbuf chain is complete. */
- m_pg->m_len = rem_len;
- rem_len = 0;
- } else {
- /* More packet data is waiting. */
- rem_len -= m_pg->m_len;
+ /*
+ * When the page chain is enabled and the TCP
+ * header has been split from the TCP payload,
+ * the ip_xsum structure will reflect the length
+ * of the TCP header, not the IP checksum. Set
+ * the packet length of the mbuf accordingly.
+ */
+ if (status & L2_FHDR_STATUS_SPLIT) {
+ m0->m_len = l2fhdr->l2_fhdr_ip_xsum;
+ DBRUN(sc->split_header_tcp_frames_rcvd++);
}
- /* Concatenate the mbuf cluster to the mbuf. */
- m_cat(m0, m_pg);
+ rem_len = pkt_len - m0->m_len;
+
+ /* Pull mbufs off the page chain for any remaining data. */
+ while (rem_len > 0) {
+ struct mbuf *m_pg;
+
+ sw_pg_cons_idx = PG_CHAIN_IDX(sw_pg_cons);
+
+ /* Remove the mbuf from the page chain. */
+ m_pg = sc->pg_mbuf_ptr[sw_pg_cons_idx];
+ sc->pg_mbuf_ptr[sw_pg_cons_idx] = NULL;
+ DBRUN(sc->debug_pg_mbuf_alloc--);
+ sc->free_pg_bd++;
+
+ /* Unmap the page chain mbuf from DMA space. */
+ bus_dmamap_sync(sc->pg_mbuf_tag,
+ sc->pg_mbuf_map[sw_pg_cons_idx],
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->pg_mbuf_tag,
+ sc->pg_mbuf_map[sw_pg_cons_idx]);
+
+ /* Adjust the mbuf length. */
+ if (rem_len < m_pg->m_len) {
+ /* The mbuf chain is complete. */
+ m_pg->m_len = rem_len;
+ rem_len = 0;
+ } else {
+ /* More packet data is waiting. */
+ rem_len -= m_pg->m_len;
+ }
+
+ /* Concatenate the mbuf cluster to the mbuf. */
+ m_cat(m0, m_pg);
+
+ sw_pg_cons = NEXT_PG_BD(sw_pg_cons);
+ }
- sw_pg_cons = NEXT_PG_BD(sw_pg_cons);
- }
+ /* Set the total packet length. */
+ m0->m_pkthdr.len = pkt_len;
- /* Set the total packet length. */
- m0->m_pkthdr.len = pkt_len;
-
- } else {
- /*
- * The received packet is small and fits in a
- * single mbuf (i.e. the l2_fhdr + pad + packet +
- * FCS <= MHLEN). In other words, the packet is
- * 154 bytes or less in size.
- */
+ } else {
+ /*
+ * The received packet is small and fits in a
+ * single mbuf (i.e. the l2_fhdr + pad + packet +
+ * FCS <= MHLEN). In other words, the packet is
+ * 154 bytes or less in size.
+ */
- DBPRINT(sc, BCE_INFO_RECV, "%s(): Found a small "
- "packet.\n", __FUNCTION__);
+ DBPRINT(sc, BCE_INFO_RECV, "%s(): Found a small "
+ "packet.\n", __FUNCTION__);
+ /* Set the total packet length. */
+ m0->m_pkthdr.len = m0->m_len = pkt_len;
+ }
+ } else
/* Set the total packet length. */
m0->m_pkthdr.len = m0->m_len = pkt_len;
- }
-#else
- /* Set the total packet length. */
- m0->m_pkthdr.len = m0->m_len = pkt_len;
-#endif
/* Remove the trailing Ethernet FCS. */
m_adj(m0, -ETHER_CRC_LEN);
@@ -6163,8 +6775,8 @@ bce_rx_intr(struct bce_softc *sc)
DBRUN(m_sanity(m0, FALSE));
DBRUNIF(((m0->m_len < ETHER_HDR_LEN) |
(m0->m_pkthdr.len > BCE_MAX_JUMBO_ETHER_MTU_VLAN)),
- BCE_PRINTF("Invalid Ethernet frame size!\n");
- m_print(m0, 128));
+ BCE_PRINTF("Invalid Ethernet frame size!\n");
+ m_print(m0, 128));
DBRUNIF(DB_RANDOMTRUE(l2fhdr_error_sim_control),
sc->l2fhdr_error_sim_count++;
@@ -6223,7 +6835,9 @@ bce_rx_intr(struct bce_softc *sc)
/* Attach the VLAN tag. */
if (status & L2_FHDR_STATUS_L2_VLAN_TAG) {
+ DBRUN(sc->vlan_tagged_frames_rcvd++);
if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
+ DBRUN(sc->vlan_tagged_frames_stripped++);
#if __FreeBSD_version < 700000
VLAN_INPUT_TAG(ifp, m0,
l2fhdr->l2_fhdr_vlan_tag, continue);
@@ -6266,9 +6880,7 @@ bce_rx_int_next_rx:
if (m0) {
/* Make sure we don't lose our place when we release the lock. */
sc->rx_cons = sw_rx_cons;
-#ifdef BCE_JUMBO_HDRSPLIT
sc->pg_cons = sw_pg_cons;
-#endif
BCE_UNLOCK(sc);
(*ifp->if_input)(ifp, m0);
@@ -6276,9 +6888,7 @@ bce_rx_int_next_rx:
/* Recover our place. */
sw_rx_cons = sc->rx_cons;
-#ifdef BCE_JUMBO_HDRSPLIT
sw_pg_cons = sc->pg_cons;
-#endif
}
/* Refresh hw_cons to see if there's new work */
@@ -6286,26 +6896,26 @@ bce_rx_int_next_rx:
hw_rx_cons = sc->hw_rx_cons = bce_get_hw_rx_cons(sc);
}
-#ifdef BCE_JUMBO_HDRSPLIT
/* No new packets. Refill the page chain. */
- sc->pg_cons = sw_pg_cons;
- bce_fill_pg_chain(sc);
-#endif
+ if (bce_hdr_split == TRUE) {
+ sc->pg_cons = sw_pg_cons;
+ bce_fill_pg_chain(sc);
+ }
/* No new packets. Refill the RX chain. */
sc->rx_cons = sw_rx_cons;
bce_fill_rx_chain(sc);
/* Prepare the page chain pages to be accessed by the NIC. */
- for (int i = 0; i < RX_PAGES; i++)
+ for (int i = 0; i < sc->rx_pages; i++)
bus_dmamap_sync(sc->rx_bd_chain_tag,
sc->rx_bd_chain_map[i], BUS_DMASYNC_PREWRITE);
-#ifdef BCE_JUMBO_HDRSPLIT
- for (int i = 0; i < PG_PAGES; i++)
- bus_dmamap_sync(sc->pg_bd_chain_tag,
- sc->pg_bd_chain_map[i], BUS_DMASYNC_PREWRITE);
-#endif
+ if (bce_hdr_split == TRUE) {
+ for (int i = 0; i < sc->pg_pages; i++)
+ bus_dmamap_sync(sc->pg_bd_chain_tag,
+ sc->pg_bd_chain_map[i], BUS_DMASYNC_PREWRITE);
+ }
DBPRINT(sc, BCE_EXTREME_RECV, "%s(exit): rx_prod = 0x%04X, "
"rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n",
@@ -6375,10 +6985,10 @@ bce_tx_intr(struct bce_softc *sc)
"sw_tx_chain_cons = 0x%04X\n",
__FUNCTION__, hw_tx_cons, sw_tx_cons, sw_tx_chain_cons);
- DBRUNIF((sw_tx_chain_cons > MAX_TX_BD),
+ DBRUNIF((sw_tx_chain_cons > MAX_TX_BD_ALLOC),
BCE_PRINTF("%s(%d): TX chain consumer out of range! "
" 0x%04X > 0x%04X\n", __FILE__, __LINE__, sw_tx_chain_cons,
- (int) MAX_TX_BD);
+ (int) MAX_TX_BD_ALLOC);
bce_breakpoint(sc));
DBRUN(txbd = &sc->tx_bd_chain[TX_PAGE(sw_tx_chain_cons)]
@@ -6544,21 +7154,30 @@ bce_init_locked(struct bce_softc *sc)
bcopy(IF_LLADDR(sc->bce_ifp), sc->eaddr, ETHER_ADDR_LEN);
bce_set_mac_addr(sc);
+ if (bce_hdr_split == FALSE)
+ bce_get_rx_buffer_sizes(sc, ifp->if_mtu);
/*
* Calculate and program the hardware Ethernet MTU
- * size. Be generous on the receive if we have room.
+ * size. Be generous on the receive if we have room
+ * and allowed by the user.
*/
-#ifdef BCE_JUMBO_HDRSPLIT
- if (ifp->if_mtu <= (sc->rx_bd_mbuf_data_len +
- sc->pg_bd_mbuf_alloc_size))
- ether_mtu = sc->rx_bd_mbuf_data_len +
- sc->pg_bd_mbuf_alloc_size;
-#else
- if (ifp->if_mtu <= sc->rx_bd_mbuf_data_len)
- ether_mtu = sc->rx_bd_mbuf_data_len;
-#endif
- else
+ if (bce_strict_rx_mtu == TRUE)
ether_mtu = ifp->if_mtu;
+ else {
+ if (bce_hdr_split == TRUE) {
+ if (ifp->if_mtu <= (sc->rx_bd_mbuf_data_len +
+ sc->pg_bd_mbuf_alloc_size))
+ ether_mtu = sc->rx_bd_mbuf_data_len +
+ sc->pg_bd_mbuf_alloc_size;
+ else
+ ether_mtu = ifp->if_mtu;
+ } else {
+ if (ifp->if_mtu <= sc->rx_bd_mbuf_data_len)
+ ether_mtu = sc->rx_bd_mbuf_data_len;
+ else
+ ether_mtu = ifp->if_mtu;
+ }
+ }
ether_mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN;
@@ -6573,22 +7192,16 @@ bce_init_locked(struct bce_softc *sc)
else
REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu);
- DBPRINT(sc, BCE_INFO_LOAD,
- "%s(): rx_bd_mbuf_alloc_size = %d, rx_bce_mbuf_data_len = %d, "
- "rx_bd_mbuf_align_pad = %d\n", __FUNCTION__,
- sc->rx_bd_mbuf_alloc_size, sc->rx_bd_mbuf_data_len,
- sc->rx_bd_mbuf_align_pad);
-
/* Program appropriate promiscuous/multicast filtering. */
bce_set_rx_mode(sc);
-#ifdef BCE_JUMBO_HDRSPLIT
- DBPRINT(sc, BCE_INFO_LOAD, "%s(): pg_bd_mbuf_alloc_size = %d\n",
- __FUNCTION__, sc->pg_bd_mbuf_alloc_size);
+ if (bce_hdr_split == TRUE) {
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): pg_bd_mbuf_alloc_size = %d\n",
+ __FUNCTION__, sc->pg_bd_mbuf_alloc_size);
- /* Init page buffer descriptor chain. */
- bce_init_pg_chain(sc);
-#endif
+ /* Init page buffer descriptor chain. */
+ bce_init_pg_chain(sc);
+ }
/* Init RX buffer descriptor chain. */
bce_init_rx_chain(sc);
@@ -6747,7 +7360,7 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags)
return (NULL);
}
- /* IP header length and checksum will be calc'd by hardware */
+ /* Clear IP header length and checksum, will be calc'd by h/w. */
ip = (struct ip *)(m->m_data + sizeof(struct ether_header));
ip_len = ip->ip_len;
ip->ip_len = 0;
@@ -7116,7 +7729,7 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct bce_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
struct mii_data *mii;
- int mask, error = 0, reinit;
+ int mask, error = 0;
DBENTER(BCE_VERBOSE_MISC);
@@ -7137,40 +7750,10 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
BCE_LOCK(sc);
ifp->if_mtu = ifr->ifr_mtu;
- reinit = 0;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- /*
- * Because allocation size is used in RX
- * buffer allocation, stop controller if
- * it is already running.
- */
- bce_stop(sc);
- reinit = 1;
- }
-#ifdef BCE_JUMBO_HDRSPLIT
- /* No buffer allocation size changes are necessary. */
-#else
- /* Recalculate our buffer allocation sizes. */
- if ((ifp->if_mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN +
- ETHER_CRC_LEN) > MCLBYTES) {
- sc->rx_bd_mbuf_alloc_size = MJUM9BYTES;
- sc->rx_bd_mbuf_align_pad =
- roundup2(MJUM9BYTES, 16) - MJUM9BYTES;
- sc->rx_bd_mbuf_data_len =
- sc->rx_bd_mbuf_alloc_size -
- sc->rx_bd_mbuf_align_pad;
- } else {
- sc->rx_bd_mbuf_alloc_size = MCLBYTES;
- sc->rx_bd_mbuf_align_pad =
- roundup2(MCLBYTES, 16) - MCLBYTES;
- sc->rx_bd_mbuf_data_len =
- sc->rx_bd_mbuf_alloc_size -
- sc->rx_bd_mbuf_align_pad;
- }
-#endif
-
- if (reinit != 0)
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
bce_init_locked(sc);
+ }
BCE_UNLOCK(sc);
break;
@@ -7224,10 +7807,14 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
case SIOCGIFMEDIA:
DBPRINT(sc, BCE_VERBOSE_MISC,
"Received SIOCSIFMEDIA/SIOCGIFMEDIA\n");
-
- mii = device_get_softc(sc->bce_miibus);
- error = ifmedia_ioctl(ifp, ifr,
- &mii->mii_media, command);
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0)
+ error = ifmedia_ioctl(ifp, ifr, &sc->bce_ifmedia,
+ command);
+ else {
+ mii = device_get_softc(sc->bce_miibus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media,
+ command);
+ }
break;
/* Set interface capability */
@@ -7847,7 +8434,7 @@ bce_pulse(void *xsc)
sc->bc_state = bce_shmem_rd(sc, BCE_BC_STATE_CONDITION);
/* Report whether the bootcode still knows the driver is running. */
- if (bootverbose) {
+ if (bce_verbose || bootverbose) {
if (sc->bce_drv_cardiac_arrest == FALSE) {
if (!(sc->bc_state & BCE_CONDITION_DRV_PRESENT)) {
sc->bce_drv_cardiac_arrest = TRUE;
@@ -7892,6 +8479,7 @@ bce_tick(void *xsc)
struct bce_softc *sc = xsc;
struct mii_data *mii;
struct ifnet *ifp;
+ struct ifmediareq ifmr;
ifp = sc->bce_ifp;
@@ -7905,10 +8493,13 @@ bce_tick(void *xsc)
/* Update the statistics from the hardware statistics block. */
bce_stats_update(sc);
+ /*
+ * ToDo: This is a safety measure. Need to re-evaluate
+ * high level processing logic and eliminate this code.
+ */
/* Top off the receive and page chains. */
-#ifdef BCE_JUMBO_HDRSPLIT
- bce_fill_pg_chain(sc);
-#endif
+ if (bce_hdr_split == TRUE)
+ bce_fill_pg_chain(sc);
bce_fill_rx_chain(sc);
/* Check that chip hasn't hung. */
@@ -7919,21 +8510,32 @@ bce_tick(void *xsc)
goto bce_tick_exit;
/* Link is down. Check what the PHY's doing. */
- mii = device_get_softc(sc->bce_miibus);
- mii_tick(mii);
-
- /* Check if the link has come up. */
- if ((mii->mii_media_status & IFM_ACTIVE) &&
- (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)) {
- DBPRINT(sc, BCE_VERBOSE_MISC,
- "%s(): Link up!\n", __FUNCTION__);
- sc->bce_link_up = TRUE;
- if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
- IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX ||
- IFM_SUBTYPE(mii->mii_media_active) == IFM_2500_SX) &&
- bootverbose)
- BCE_PRINTF("Gigabit link up!\n");
+ if ((sc->bce_phy_flags & BCE_PHY_REMOTE_CAP_FLAG) != 0) {
+ bzero(&ifmr, sizeof(ifmr));
+ bce_ifmedia_sts_rphy(sc, &ifmr);
+ if ((ifmr.ifm_status & (IFM_ACTIVE | IFM_AVALID)) ==
+ (IFM_ACTIVE | IFM_AVALID)) {
+ sc->bce_link_up = TRUE;
+ bce_miibus_statchg(sc->bce_dev);
+ }
+ } else {
+ mii = device_get_softc(sc->bce_miibus);
+ mii_tick(mii);
+ /* Check if the link has come up. */
+ if ((mii->mii_media_status & IFM_ACTIVE) &&
+ (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)) {
+ DBPRINT(sc, BCE_VERBOSE_MISC, "%s(): Link up!\n",
+ __FUNCTION__);
+ sc->bce_link_up = TRUE;
+ if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
+ IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX ||
+ IFM_SUBTYPE(mii->mii_media_active) == IFM_2500_SX) &&
+ (bce_verbose || bootverbose))
+ BCE_PRINTF("Gigabit link up!\n");
+ }
+ }
+ if (sc->bce_link_up == TRUE) {
/* Now that link is up, handle any outstanding TX traffic. */
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
DBPRINT(sc, BCE_VERBOSE_MISC, "%s(): Found "
@@ -7947,6 +8549,35 @@ bce_tick_exit:
return;
}
+static void
+bce_fw_cap_init(struct bce_softc *sc)
+{
+ u32 ack, cap, link;
+
+ ack = 0;
+ cap = bce_shmem_rd(sc, BCE_FW_CAP_MB);
+ if ((cap & BCE_FW_CAP_SIGNATURE_MAGIC_MASK) !=
+ BCE_FW_CAP_SIGNATURE_MAGIC)
+ return;
+ if ((cap & (BCE_FW_CAP_MFW_KEEP_VLAN | BCE_FW_CAP_BC_KEEP_VLAN)) ==
+ (BCE_FW_CAP_MFW_KEEP_VLAN | BCE_FW_CAP_BC_KEEP_VLAN))
+ ack |= BCE_DRV_ACK_CAP_SIGNATURE_MAGIC |
+ BCE_FW_CAP_MFW_KEEP_VLAN | BCE_FW_CAP_BC_KEEP_VLAN;
+ if ((sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) != 0 &&
+ (cap & BCE_FW_CAP_REMOTE_PHY_CAP) != 0) {
+ sc->bce_phy_flags &= ~BCE_PHY_REMOTE_PORT_FIBER_FLAG;
+ sc->bce_phy_flags |= BCE_PHY_REMOTE_CAP_FLAG;
+ link = bce_shmem_rd(sc, BCE_LINK_STATUS);
+ if ((link & BCE_LINK_STATUS_SERDES_LINK) != 0)
+ sc->bce_phy_flags |= BCE_PHY_REMOTE_PORT_FIBER_FLAG;
+ ack |= BCE_DRV_ACK_CAP_SIGNATURE_MAGIC |
+ BCE_FW_CAP_REMOTE_PHY_CAP;
+ }
+
+ if (ack != 0)
+ bce_shmem_wr(sc, BCE_DRV_ACK_CAP_MB, ack);
+}
+
#ifdef BCE_DEBUG
/****************************************************************************/
@@ -8083,6 +8714,10 @@ bce_sysctl_stats_clear(SYSCTL_HANDLER_ARGS)
if (result == 1) {
sc = (struct bce_softc *)arg1;
+ struct statistics_block *stats;
+
+ stats = (struct statistics_block *) sc->stats_block;
+ bzero(stats, sizeof(struct statistics_block));
/* Clear the internal H/W statistics counters. */
REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW);
@@ -8095,7 +8730,7 @@ bce_sysctl_stats_clear(SYSCTL_HANDLER_ARGS)
sc->tso_frames_failed = 0;
sc->rx_empty_count =
sc->tx_full_count = 0;
- sc->rx_low_watermark = USABLE_RX_BD;
+ sc->rx_low_watermark = USABLE_RX_BD_ALLOC;
sc->tx_hi_watermark = 0;
sc->l2fhdr_error_count =
sc->l2fhdr_error_sim_count = 0;
@@ -8105,9 +8740,11 @@ bce_sysctl_stats_clear(SYSCTL_HANDLER_ARGS)
sc->dma_map_addr_tx_failed_count = 0;
sc->mbuf_frag_count = 0;
sc->csum_offload_tcp_udp =
- sc->csum_offload_ip = 0;
+ sc->csum_offload_ip = 0;
sc->vlan_tagged_frames_rcvd =
- sc->vlan_tagged_frames_stripped = 0;
+ sc->vlan_tagged_frames_stripped = 0;
+ sc->split_header_frames_rcvd =
+ sc->split_header_tcp_frames_rcvd = 0;
/* Clear firmware maintained statistics. */
REG_WR_IND(sc, 0x120084, 0);
@@ -8118,6 +8755,35 @@ bce_sysctl_stats_clear(SYSCTL_HANDLER_ARGS)
/****************************************************************************/
+/* Allows the shared memory contents to be dumped through the sysctl . */
+/* interface. */
+/* */
+/* Returns: */
+/* 0 for success, positive value for failure. */
+/****************************************************************************/
+static int
+bce_sysctl_shmem_state(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ int result;
+ struct bce_softc *sc;
+
+ result = -1;
+ error = sysctl_handle_int(oidp, &result, 0, req);
+
+ if (error || !req->newptr)
+ return (error);
+
+ if (result == 1) {
+ sc = (struct bce_softc *)arg1;
+ bce_dump_shmem_state(sc);
+ }
+
+ return error;
+}
+
+
+/****************************************************************************/
/* Allows the bootcode state to be dumped through the sysctl interface. */
/* */
/* Returns: */
@@ -8166,7 +8832,7 @@ bce_sysctl_dump_rx_bd_chain(SYSCTL_HANDLER_ARGS)
if (result == 1) {
sc = (struct bce_softc *)arg1;
- bce_dump_rx_bd_chain(sc, 0, TOTAL_RX_BD);
+ bce_dump_rx_bd_chain(sc, 0, TOTAL_RX_BD_ALLOC);
}
return error;
@@ -8194,7 +8860,7 @@ bce_sysctl_dump_rx_mbuf_chain(SYSCTL_HANDLER_ARGS)
if (result == 1) {
sc = (struct bce_softc *)arg1;
- bce_dump_rx_mbuf_chain(sc, 0, USABLE_RX_BD);
+ bce_dump_rx_mbuf_chain(sc, 0, USABLE_RX_BD_ALLOC);
}
return error;
@@ -8222,14 +8888,13 @@ bce_sysctl_dump_tx_chain(SYSCTL_HANDLER_ARGS)
if (result == 1) {
sc = (struct bce_softc *)arg1;
- bce_dump_tx_chain(sc, 0, TOTAL_TX_BD);
+ bce_dump_tx_chain(sc, 0, TOTAL_TX_BD_ALLOC);
}
return error;
}
-#ifdef BCE_JUMBO_HDRSPLIT
/****************************************************************************/
/* Provides a sysctl interface to allow dumping the page chain. */
/* */
@@ -8251,12 +8916,11 @@ bce_sysctl_dump_pg_chain(SYSCTL_HANDLER_ARGS)
if (result == 1) {
sc = (struct bce_softc *)arg1;
- bce_dump_pg_chain(sc, 0, TOTAL_PG_BD);
+ bce_dump_pg_chain(sc, 0, TOTAL_PG_BD_ALLOC);
}
return error;
}
-#endif
/****************************************************************************/
/* Provides a sysctl interface to allow reading arbitrary NVRAM offsets in */
@@ -8279,7 +8943,8 @@ bce_sysctl_nvram_read(SYSCTL_HANDLER_ARGS)
if (error || (req->newptr == NULL))
return (error);
- bce_nvram_read(sc, result, data, 4);
+ error = bce_nvram_read(sc, result, data, 4);
+
BCE_PRINTF("offset 0x%08X = 0x%08X\n", result, bce_be32toh(val[0]));
return (error);
@@ -8350,6 +9015,69 @@ bce_sysctl_phy_read(SYSCTL_HANDLER_ARGS)
/****************************************************************************/
+/* Provides a sysctl interface for dumping the nvram contents. */
+/* DO NOT ENABLE ON PRODUCTION SYSTEMS! */
+/* */
+/* Returns: */
+/* 0 for success, positive errno for failure. */
+/****************************************************************************/
+static int
+bce_sysctl_nvram_dump(SYSCTL_HANDLER_ARGS)
+{
+ struct bce_softc *sc = (struct bce_softc *)arg1;
+ int error, i;
+
+ if (sc->nvram_buf == NULL)
+ sc->nvram_buf = malloc(sc->bce_flash_size,
+ M_TEMP, M_ZERO | M_WAITOK);
+
+ error = 0;
+ if (req->oldlen == sc->bce_flash_size) {
+ for (i = 0; i < sc->bce_flash_size && error == 0; i++)
+ error = bce_nvram_read(sc, i, &sc->nvram_buf[i], 1);
+ }
+
+ if (error == 0)
+ error = SYSCTL_OUT(req, sc->nvram_buf, sc->bce_flash_size);
+
+ return error;
+}
+
+#ifdef BCE_NVRAM_WRITE_SUPPORT
+/****************************************************************************/
+/* Provides a sysctl interface for writing to nvram. */
+/* DO NOT ENABLE ON PRODUCTION SYSTEMS! */
+/* */
+/* Returns: */
+/* 0 for success, positive errno for failure. */
+/****************************************************************************/
+static int
+bce_sysctl_nvram_write(SYSCTL_HANDLER_ARGS)
+{
+ struct bce_softc *sc = (struct bce_softc *)arg1;
+ int error;
+
+ if (sc->nvram_buf == NULL)
+ sc->nvram_buf = malloc(sc->bce_flash_size,
+ M_TEMP, M_ZERO | M_WAITOK);
+ else
+ bzero(sc->nvram_buf, sc->bce_flash_size);
+
+ error = SYSCTL_IN(req, sc->nvram_buf, sc->bce_flash_size);
+ if (error == 0)
+ return (error);
+
+ if (req->newlen == sc->bce_flash_size)
+ error = bce_nvram_write(sc, 0, sc->nvram_buf,
+ sc->bce_flash_size);
+
+
+ return error;
+}
+#endif
+
+
+/****************************************************************************/
/* Provides a sysctl interface to allow reading a CID. */
/* */
/* Returns: */
@@ -8376,7 +9104,7 @@ bce_sysctl_dump_ctx(SYSCTL_HANDLER_ARGS)
}
- /****************************************************************************/
+/****************************************************************************/
/* Provides a sysctl interface to forcing the driver to dump state and */
/* enter the debugger. DO NOT ENABLE ON PRODUCTION SYSTEMS! */
/* */
@@ -8405,7 +9133,6 @@ bce_sysctl_breakpoint(SYSCTL_HANDLER_ARGS)
}
#endif
-
/****************************************************************************/
/* Adds any sysctl parameters for tuning or debugging purposes. */
/* */
@@ -8514,113 +9241,137 @@ bce_add_sysctls(struct bce_softc *sc)
CTLFLAG_RD, &sc->rx_low_watermark,
0, "Lowest level of free rx_bd's");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"rx_empty_count",
CTLFLAG_RD, &sc->rx_empty_count,
- 0, "Number of times the RX chain was empty");
+ "Number of times the RX chain was empty");
SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_hi_watermark",
CTLFLAG_RD, &sc->tx_hi_watermark,
0, "Highest level of used tx_bd's");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"tx_full_count",
CTLFLAG_RD, &sc->tx_full_count,
- 0, "Number of times the TX chain was full");
+ "Number of times the TX chain was full");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"tso_frames_requested",
CTLFLAG_RD, &sc->tso_frames_requested,
- 0, "Number of TSO frames requested");
+ "Number of TSO frames requested");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"tso_frames_completed",
CTLFLAG_RD, &sc->tso_frames_completed,
- 0, "Number of TSO frames completed");
+ "Number of TSO frames completed");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"tso_frames_failed",
CTLFLAG_RD, &sc->tso_frames_failed,
- 0, "Number of TSO frames failed");
+ "Number of TSO frames failed");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"csum_offload_ip",
CTLFLAG_RD, &sc->csum_offload_ip,
- 0, "Number of IP checksum offload frames");
+ "Number of IP checksum offload frames");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"csum_offload_tcp_udp",
CTLFLAG_RD, &sc->csum_offload_tcp_udp,
- 0, "Number of TCP/UDP checksum offload frames");
+ "Number of TCP/UDP checksum offload frames");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"vlan_tagged_frames_rcvd",
CTLFLAG_RD, &sc->vlan_tagged_frames_rcvd,
- 0, "Number of VLAN tagged frames received");
+ "Number of VLAN tagged frames received");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"vlan_tagged_frames_stripped",
CTLFLAG_RD, &sc->vlan_tagged_frames_stripped,
- 0, "Number of VLAN tagged frames stripped");
+ "Number of VLAN tagged frames stripped");
- SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"interrupts_rx",
CTLFLAG_RD, &sc->interrupts_rx,
- 0, "Number of RX interrupts");
+ "Number of RX interrupts");
- SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"interrupts_tx",
CTLFLAG_RD, &sc->interrupts_tx,
- 0, "Number of TX interrupts");
+ "Number of TX interrupts");
+
+ if (bce_hdr_split == TRUE) {
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
+ "split_header_frames_rcvd",
+ CTLFLAG_RD, &sc->split_header_frames_rcvd,
+ "Number of split header frames received");
+
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
+ "split_header_tcp_frames_rcvd",
+ CTLFLAG_RD, &sc->split_header_tcp_frames_rcvd,
+ "Number of split header TCP frames received");
+ }
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "nvram_dump", CTLTYPE_OPAQUE | CTLFLAG_RD,
+ (void *)sc, 0,
+ bce_sysctl_nvram_dump, "S", "");
+
+#ifdef BCE_NVRAM_WRITE_SUPPORT
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "nvram_write", CTLTYPE_OPAQUE | CTLFLAG_WR,
+ (void *)sc, 0,
+ bce_sysctl_nvram_write, "S", "");
#endif
+#endif /* BCE_DEBUG */
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHcInOctets",
CTLFLAG_RD, &sc->stat_IfHCInOctets,
"Bytes received");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCInBadOctets",
CTLFLAG_RD, &sc->stat_IfHCInBadOctets,
"Bad bytes received");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCOutOctets",
CTLFLAG_RD, &sc->stat_IfHCOutOctets,
"Bytes sent");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCOutBadOctets",
CTLFLAG_RD, &sc->stat_IfHCOutBadOctets,
"Bad bytes sent");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCInUcastPkts",
CTLFLAG_RD, &sc->stat_IfHCInUcastPkts,
"Unicast packets received");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCInMulticastPkts",
CTLFLAG_RD, &sc->stat_IfHCInMulticastPkts,
"Multicast packets received");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCInBroadcastPkts",
CTLFLAG_RD, &sc->stat_IfHCInBroadcastPkts,
"Broadcast packets received");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCOutUcastPkts",
CTLFLAG_RD, &sc->stat_IfHCOutUcastPkts,
"Unicast packets sent");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCOutMulticastPkts",
CTLFLAG_RD, &sc->stat_IfHCOutMulticastPkts,
"Multicast packets sent");
- SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
+ SYSCTL_ADD_QUAD(ctx, children, OID_AUTO,
"stat_IfHCOutBroadcastPkts",
CTLFLAG_RD, &sc->stat_IfHCOutBroadcastPkts,
"Broadcast packets sent");
@@ -8879,6 +9630,11 @@ bce_add_sysctls(struct bce_softc *sc)
bce_sysctl_stats_clear, "I", "Clear statistics block");
SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "shmem_state", CTLTYPE_INT | CTLFLAG_RW,
+ (void *)sc, 0,
+ bce_sysctl_shmem_state, "I", "Shared memory state information");
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"bc_state", CTLTYPE_INT | CTLFLAG_RW,
(void *)sc, 0,
bce_sysctl_bc_state, "I", "Bootcode state information");
@@ -8898,12 +9654,13 @@ bce_add_sysctls(struct bce_softc *sc)
(void *)sc, 0,
bce_sysctl_dump_tx_chain, "I", "Dump tx_bd chain");
-#ifdef BCE_JUMBO_HDRSPLIT
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
- "dump_pg_chain", CTLTYPE_INT | CTLFLAG_RW,
- (void *)sc, 0,
- bce_sysctl_dump_pg_chain, "I", "Dump page chain");
-#endif
+ if (bce_hdr_split == TRUE) {
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dump_pg_chain", CTLTYPE_INT | CTLFLAG_RW,
+ (void *)sc, 0,
+ bce_sysctl_dump_pg_chain, "I", "Dump page chain");
+ }
+
SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dump_ctx", CTLTYPE_INT | CTLFLAG_RW,
(void *)sc, 0,
@@ -9207,7 +9964,6 @@ bce_dump_rx_mbuf_chain(struct bce_softc *sc, u16 chain_prod, int count)
}
-#ifdef BCE_JUMBO_HDRSPLIT
/****************************************************************************/
/* Prints out the mbufs in the mbuf page chain. */
/* */
@@ -9237,7 +9993,6 @@ bce_dump_pg_mbuf_chain(struct bce_softc *sc, u16 chain_prod, int count)
"----------------"
"----------------------------\n");
}
-#endif
/****************************************************************************/
@@ -9251,7 +10006,7 @@ bce_dump_txbd(struct bce_softc *sc, int idx, struct tx_bd *txbd)
{
int i = 0;
- if (idx > MAX_TX_BD)
+ if (idx > MAX_TX_BD_ALLOC)
/* Index out of range. */
BCE_PRINTF("tx_bd[0x%04X]: Invalid tx_bd index!\n", idx);
else if ((idx & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
@@ -9364,7 +10119,7 @@ bce_dump_txbd(struct bce_softc *sc, int idx, struct tx_bd *txbd)
static __attribute__ ((noinline)) void
bce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd)
{
- if (idx > MAX_RX_BD)
+ if (idx > MAX_RX_BD_ALLOC)
/* Index out of range. */
BCE_PRINTF("rx_bd[0x%04X]: Invalid rx_bd index!\n", idx);
else if ((idx & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
@@ -9381,7 +10136,6 @@ bce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd)
}
-#ifdef BCE_JUMBO_HDRSPLIT
/****************************************************************************/
/* Prints out a rx_bd structure in the page chain. */
/* */
@@ -9391,7 +10145,7 @@ bce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd)
static __attribute__ ((noinline)) void
bce_dump_pgbd(struct bce_softc *sc, int idx, struct rx_bd *pgbd)
{
- if (idx > MAX_PG_BD)
+ if (idx > MAX_PG_BD_ALLOC)
/* Index out of range. */
BCE_PRINTF("pg_bd[0x%04X]: Invalid pg_bd index!\n", idx);
else if ((idx & USABLE_PG_BD_PER_PAGE) == USABLE_PG_BD_PER_PAGE)
@@ -9405,7 +10159,6 @@ bce_dump_pgbd(struct bce_softc *sc, int idx, struct rx_bd *pgbd)
pgbd->rx_bd_haddr_hi, pgbd->rx_bd_haddr_lo,
pgbd->rx_bd_len, pgbd->rx_bd_flags);
}
-#endif
/****************************************************************************/
@@ -9481,8 +10234,7 @@ bce_dump_ctx(struct bce_softc *sc, u16 cid)
"consumer index\n", CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_RX_NX_PG_BDIDX));
} else if (cid == TX_CID) {
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
BCE_PRINTF(" 0x%08X - (L2CTX_TX_TYPE_XI) ctx type\n",
CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_TYPE_XI));
@@ -9744,8 +10496,7 @@ bce_dump_ftqs(struct bce_softc *sc)
(BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_CPQ_VALID_CNT << 8) |
(BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_MGMQ_VALID_CNT);
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716))
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709)
val = val |
(BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI <<
24);
@@ -9778,8 +10529,7 @@ bce_dump_ftqs(struct bce_softc *sc)
BCE_PRINTF(" CS 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n",
cmd, ctl, cur_depth, max_depth, valid_cnt);
- if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) {
/* Input queue to the RV2P Command Scheduler */
cmd = REG_RD(sc, BCE_RV2PCSR_FTQ_CMD);
ctl = REG_RD(sc, BCE_RV2PCSR_FTQ_CTL);
@@ -9815,10 +10565,10 @@ bce_dump_tx_chain(struct bce_softc *sc, u16 tx_prod, int count)
"----------------------------\n");
BCE_PRINTF("page size = 0x%08X, tx chain pages = 0x%08X\n",
- (u32) BCM_PAGE_SIZE, (u32) TX_PAGES);
+ (u32) BCM_PAGE_SIZE, (u32) sc->tx_pages);
BCE_PRINTF("tx_bd per page = 0x%08X, usable tx_bd per page = 0x%08X\n",
(u32) TOTAL_TX_BD_PER_PAGE, (u32) USABLE_TX_BD_PER_PAGE);
- BCE_PRINTF("total tx_bd = 0x%08X\n", (u32) TOTAL_TX_BD);
+ BCE_PRINTF("total tx_bd = 0x%08X\n", (u32) TOTAL_TX_BD_ALLOC);
BCE_PRINTF(
"----------------------------"
@@ -9857,12 +10607,12 @@ bce_dump_rx_bd_chain(struct bce_softc *sc, u16 rx_prod, int count)
"----------------------------\n");
BCE_PRINTF("page size = 0x%08X, rx chain pages = 0x%08X\n",
- (u32) BCM_PAGE_SIZE, (u32) RX_PAGES);
+ (u32) BCM_PAGE_SIZE, (u32) sc->rx_pages);
BCE_PRINTF("rx_bd per page = 0x%08X, usable rx_bd per page = 0x%08X\n",
(u32) TOTAL_RX_BD_PER_PAGE, (u32) USABLE_RX_BD_PER_PAGE);
- BCE_PRINTF("total rx_bd = 0x%08X\n", (u32) TOTAL_RX_BD);
+ BCE_PRINTF("total rx_bd = 0x%08X\n", (u32) TOTAL_RX_BD_ALLOC);
BCE_PRINTF(
"----------------------------"
@@ -9883,7 +10633,6 @@ bce_dump_rx_bd_chain(struct bce_softc *sc, u16 rx_prod, int count)
}
-#ifdef BCE_JUMBO_HDRSPLIT
/****************************************************************************/
/* Prints out the page chain. */
/* */
@@ -9902,13 +10651,12 @@ bce_dump_pg_chain(struct bce_softc *sc, u16 pg_prod, int count)
"----------------------------\n");
BCE_PRINTF("page size = 0x%08X, pg chain pages = 0x%08X\n",
- (u32) BCM_PAGE_SIZE, (u32) PG_PAGES);
+ (u32) BCM_PAGE_SIZE, (u32) sc->pg_pages);
BCE_PRINTF("rx_bd per page = 0x%08X, usable rx_bd per page = 0x%08X\n",
(u32) TOTAL_PG_BD_PER_PAGE, (u32) USABLE_PG_BD_PER_PAGE);
- BCE_PRINTF("total rx_bd = 0x%08X, max_pg_bd = 0x%08X\n",
- (u32) TOTAL_PG_BD, (u32) MAX_PG_BD);
+ BCE_PRINTF("total pg_bd = 0x%08X\n", (u32) TOTAL_PG_BD_ALLOC);
BCE_PRINTF(
"----------------------------"
@@ -9927,7 +10675,6 @@ bce_dump_pg_chain(struct bce_softc *sc, u16 pg_prod, int count)
"----------------"
"----------------------------\n");
}
-#endif
#define BCE_PRINT_RX_CONS(arg) \
@@ -10134,12 +10881,12 @@ bce_dump_driver_state(struct bce_softc *sc)
BCE_PRINTF("0x%08X:%08X - (sc->rx_bd_chain) rx_bd chain "
"virtual address\n", val_hi, val_lo);
-#ifdef BCE_JUMBO_HDRSPLIT
- val_hi = BCE_ADDR_HI(sc->pg_bd_chain);
- val_lo = BCE_ADDR_LO(sc->pg_bd_chain);
- BCE_PRINTF("0x%08X:%08X - (sc->pg_bd_chain) page chain "
- "virtual address\n", val_hi, val_lo);
-#endif
+ if (bce_hdr_split == TRUE) {
+ val_hi = BCE_ADDR_HI(sc->pg_bd_chain);
+ val_lo = BCE_ADDR_LO(sc->pg_bd_chain);
+ BCE_PRINTF("0x%08X:%08X - (sc->pg_bd_chain) page chain "
+ "virtual address\n", val_hi, val_lo);
+ }
val_hi = BCE_ADDR_HI(sc->tx_mbuf_ptr);
val_lo = BCE_ADDR_LO(sc->tx_mbuf_ptr);
@@ -10151,24 +10898,28 @@ bce_dump_driver_state(struct bce_softc *sc)
BCE_PRINTF("0x%08X:%08X - (sc->rx_mbuf_ptr) rx mbuf chain "
"virtual address\n", val_hi, val_lo);
-#ifdef BCE_JUMBO_HDRSPLIT
- val_hi = BCE_ADDR_HI(sc->pg_mbuf_ptr);
- val_lo = BCE_ADDR_LO(sc->pg_mbuf_ptr);
- BCE_PRINTF("0x%08X:%08X - (sc->pg_mbuf_ptr) page mbuf chain "
- "virtual address\n", val_hi, val_lo);
-#endif
+ if (bce_hdr_split == TRUE) {
+ val_hi = BCE_ADDR_HI(sc->pg_mbuf_ptr);
+ val_lo = BCE_ADDR_LO(sc->pg_mbuf_ptr);
+ BCE_PRINTF("0x%08X:%08X - (sc->pg_mbuf_ptr) page mbuf chain "
+ "virtual address\n", val_hi, val_lo);
+ }
- BCE_PRINTF(" 0x%08X - (sc->interrupts_generated) "
- "h/w intrs\n", sc->interrupts_generated);
+ BCE_PRINTF(" 0x%016llX - (sc->interrupts_generated) "
+ "h/w intrs\n",
+ (long long unsigned int) sc->interrupts_generated);
- BCE_PRINTF(" 0x%08X - (sc->interrupts_rx) "
- "rx interrupts handled\n", sc->interrupts_rx);
+ BCE_PRINTF(" 0x%016llX - (sc->interrupts_rx) "
+ "rx interrupts handled\n",
+ (long long unsigned int) sc->interrupts_rx);
- BCE_PRINTF(" 0x%08X - (sc->interrupts_tx) "
- "tx interrupts handled\n", sc->interrupts_tx);
+ BCE_PRINTF(" 0x%016llX - (sc->interrupts_tx) "
+ "tx interrupts handled\n",
+ (long long unsigned int) sc->interrupts_tx);
- BCE_PRINTF(" 0x%08X - (sc->phy_interrupts) "
- "phy interrupts handled\n", sc->phy_interrupts);
+ BCE_PRINTF(" 0x%016llX - (sc->phy_interrupts) "
+ "phy interrupts handled\n",
+ (long long unsigned int) sc->phy_interrupts);
BCE_PRINTF(" 0x%08X - (sc->last_status_idx) "
"status block index\n", sc->last_status_idx);
@@ -10188,8 +10939,8 @@ bce_dump_driver_state(struct bce_softc *sc)
BCE_PRINTF(" 0x%08X - (sc->used_tx_bd) used "
"tx_bd's\n", sc->used_tx_bd);
- BCE_PRINTF("0x%08X/%08X - (sc->tx_hi_watermark) tx hi "
- "watermark\n", sc->tx_hi_watermark, sc->max_tx_bd);
+ BCE_PRINTF(" 0x%04X/0x%04X - (sc->tx_hi_watermark)/"
+ "(sc->max_tx_bd)\n", sc->tx_hi_watermark, sc->max_tx_bd);
BCE_PRINTF(" 0x%04X(0x%04X) - (sc->rx_prod) rx producer "
"index\n", sc->rx_prod, (u16) RX_CHAIN_IDX(sc->rx_prod));
@@ -10200,28 +10951,31 @@ bce_dump_driver_state(struct bce_softc *sc)
BCE_PRINTF(" 0x%08X - (sc->rx_prod_bseq) rx producer "
"byte seq index\n", sc->rx_prod_bseq);
+ BCE_PRINTF(" 0x%04X/0x%04X - (sc->rx_low_watermark)/"
+ "(sc->max_rx_bd)\n", sc->rx_low_watermark, sc->max_rx_bd);
+
BCE_PRINTF(" 0x%08X - (sc->debug_rx_mbuf_alloc) rx "
"mbufs allocated\n", sc->debug_rx_mbuf_alloc);
BCE_PRINTF(" 0x%08X - (sc->free_rx_bd) free "
"rx_bd's\n", sc->free_rx_bd);
-#ifdef BCE_JUMBO_HDRSPLIT
- BCE_PRINTF(" 0x%04X(0x%04X) - (sc->pg_prod) page producer "
- "index\n", sc->pg_prod, (u16) PG_CHAIN_IDX(sc->pg_prod));
+ if (bce_hdr_split == TRUE) {
+ BCE_PRINTF(" 0x%04X(0x%04X) - (sc->pg_prod) page producer "
+ "index\n", sc->pg_prod, (u16) PG_CHAIN_IDX(sc->pg_prod));
- BCE_PRINTF(" 0x%04X(0x%04X) - (sc->pg_cons) page consumer "
- "index\n", sc->pg_cons, (u16) PG_CHAIN_IDX(sc->pg_cons));
+ BCE_PRINTF(" 0x%04X(0x%04X) - (sc->pg_cons) page consumer "
+ "index\n", sc->pg_cons, (u16) PG_CHAIN_IDX(sc->pg_cons));
- BCE_PRINTF(" 0x%08X - (sc->debug_pg_mbuf_alloc) page "
- "mbufs allocated\n", sc->debug_pg_mbuf_alloc);
+ BCE_PRINTF(" 0x%08X - (sc->debug_pg_mbuf_alloc) page "
+ "mbufs allocated\n", sc->debug_pg_mbuf_alloc);
+ }
BCE_PRINTF(" 0x%08X - (sc->free_pg_bd) free page "
"rx_bd's\n", sc->free_pg_bd);
- BCE_PRINTF("0x%08X/%08X - (sc->pg_low_watermark) page low "
- "watermark\n", sc->pg_low_watermark, sc->max_pg_bd);
-#endif
+ BCE_PRINTF(" 0x%04X/0x%04X - (sc->pg_low_watermark)/"
+ "(sc->max_pg_bd)\n", sc->pg_low_watermark, sc->max_pg_bd);
BCE_PRINTF(" 0x%08X - (sc->mbuf_alloc_failed_count) "
"mbuf alloc failures\n", sc->mbuf_alloc_failed_count);
@@ -10352,6 +11106,44 @@ bce_dump_hw_state(struct bce_softc *sc)
/****************************************************************************/
+/* Prints out the contentst of shared memory which is used for host driver */
+/* to bootcode firmware communication. */
+/* */
+/* Returns: */
+/* Nothing. */
+/****************************************************************************/
+static __attribute__ ((noinline)) void
+bce_dump_shmem_state(struct bce_softc *sc)
+{
+ BCE_PRINTF(
+ "----------------------------"
+ " Hardware State "
+ "----------------------------\n");
+
+ BCE_PRINTF("0x%08X - Shared memory base address\n",
+ sc->bce_shmem_base);
+ BCE_PRINTF("%s - bootcode version\n",
+ sc->bce_bc_ver);
+
+ BCE_PRINTF(
+ "----------------------------"
+ " Shared Mem "
+ "----------------------------\n");
+
+ for (int i = 0x0; i < 0x200; i += 0x10) {
+ BCE_PRINTF("0x%04X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
+ i, bce_shmem_rd(sc, i), bce_shmem_rd(sc, i + 0x4),
+ bce_shmem_rd(sc, i + 0x8), bce_shmem_rd(sc, i + 0xC));
+ }
+
+ BCE_PRINTF(
+ "----------------------------"
+ "----------------"
+ "----------------------------\n");
+}
+
+
+/****************************************************************************/
/* Prints out the mailbox queue registers. */
/* */
/* Returns: */
@@ -10809,13 +11601,15 @@ bce_breakpoint(struct bce_softc *sc)
bce_dump_enet(sc, NULL);
bce_dump_txbd(sc, 0, NULL);
bce_dump_rxbd(sc, 0, NULL);
- bce_dump_tx_mbuf_chain(sc, 0, USABLE_TX_BD);
- bce_dump_rx_mbuf_chain(sc, 0, USABLE_RX_BD);
+ bce_dump_tx_mbuf_chain(sc, 0, USABLE_TX_BD_ALLOC);
+ bce_dump_rx_mbuf_chain(sc, 0, USABLE_RX_BD_ALLOC);
+ bce_dump_pg_mbuf_chain(sc, 0, USABLE_PG_BD_ALLOC);
bce_dump_l2fhdr(sc, 0, NULL);
bce_dump_ctx(sc, RX_CID);
bce_dump_ftqs(sc);
- bce_dump_tx_chain(sc, 0, USABLE_TX_BD);
- bce_dump_rx_bd_chain(sc, 0, USABLE_RX_BD);
+ bce_dump_tx_chain(sc, 0, USABLE_TX_BD_ALLOC);
+ bce_dump_rx_bd_chain(sc, 0, USABLE_RX_BD_ALLOC);
+ bce_dump_pg_chain(sc, 0, USABLE_PG_BD_ALLOC);
bce_dump_status_block(sc);
bce_dump_stats_block(sc);
bce_dump_driver_state(sc);
@@ -10827,12 +11621,7 @@ bce_breakpoint(struct bce_softc *sc)
bce_dump_cp_state(sc, 0);
bce_dump_com_state(sc, 0);
bce_dump_rv2p_state(sc);
-
-#ifdef BCE_JUMBO_HDRSPLIT
bce_dump_pgbd(sc, 0, NULL);
- bce_dump_pg_mbuf_chain(sc, 0, USABLE_PG_BD);
- bce_dump_pg_chain(sc, 0, USABLE_PG_BD);
-#endif
}
bce_dump_status_block(sc);
@@ -10844,4 +11633,3 @@ bce_breakpoint(struct bce_softc *sc)
return;
}
#endif
-
diff --git a/freebsd/sys/dev/bce/if_bcefw.h b/freebsd/sys/dev/bce/if_bcefw.h
index c41ff10a..0b30bb83 100644
--- a/freebsd/sys/dev/bce/if_bcefw.h
+++ b/freebsd/sys/dev/bce/if_bcefw.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2011 Broadcom Corporation
* David Christensen <davidch@broadcom.com>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,1310 +31,1254 @@
/*
* This file contains firmware data derived from proprietary unpublished
- * source code, Copyright (c) 2004, 2005, 2007, 2008 Broadcom Corporation.
+ * source code, Copyright (c) 2004-2011 Broadcom Corporation.
*
* Permission is hereby granted for the distribution of this firmware data
- * in hexadecimal or equivalent format, provided this copyright notice is
- * accompanying it.
+ * in hexadecimal or equivalent format, provided this copyright notice also
+ * accompanies it.
*/
-/* Firmware release 4.6.17 for BCM5706 and BCM5708 (b06). */
-/* Firmware release 4.6.16 for BCM5709 and BCM5716 (b09). */
-int bce_COM_b06FwReleaseMajor = 0x1;
-int bce_COM_b06FwReleaseMinor = 0x0;
-int bce_COM_b06FwReleaseFix = 0x0;
-u32 bce_COM_b06FwStartAddr = 0x080000f8;
-u32 bce_COM_b06FwTextAddr = 0x08000000;
-int bce_COM_b06FwTextLen = 0x4df0;
-u32 bce_COM_b06FwDataAddr = 0x00000000;
-int bce_COM_b06FwDataLen = 0x0;
-u32 bce_COM_b06FwRodataAddr = 0x08004df0;
-int bce_COM_b06FwRodataLen = 0x14;
-u32 bce_COM_b06FwBssAddr = 0x08004e58;
-int bce_COM_b06FwBssLen = 0xbc;
-u32 bce_COM_b06FwSbssAddr = 0x08004e20;
-int bce_COM_b06FwSbssLen = 0x38;
-u32 bce_COM_b06FwSDataAddr = 0x00000000;
-int bce_COM_b06FwSDataLen = 0x0;
-u32 bce_COM_b06FwText[(0x4df0/4) + 1] = {
-0xa00003e, 0x0, 0x0,
-0xd, 0x636f6d34, 0x2e362e31, 0x37000000,
-0x4061102, 0x0, 0x3, 0x14,
-0x32, 0x3, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x10,
-0x136, 0xea60, 0x1, 0x0,
-0x0, 0x0, 0x8, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x2,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x10, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x10000003, 0x0, 0xd, 0xd,
-0x3c020800, 0x24424e20, 0x3c030800, 0x24634f14,
-0xac400000, 0x43202b, 0x1480fffd, 0x24420004,
-0x3c1d0800, 0x37bd7ffc, 0x3a0f021, 0x3c100800,
-0x261000f8, 0x3c1c0800, 0x279c4e20, 0xe0002bd,
-0x0, 0xd, 0x3c036010, 0x8c645000,
-0x2402ff7f, 0x3c1a8000, 0x822024, 0x3484380c,
-0x24020037, 0xac645000, 0xaf420008, 0x24020c80,
-0xaf420024, 0x3c1b8008, 0x3c060800, 0x24c607e8,
-0x3c020800, 0x24424e58, 0x2404001b, 0x2484ffff,
-0xac460000, 0x481fffd, 0x24420004, 0x3c020800,
-0x24420380, 0x3c010800, 0xac224e60, 0x3c020800,
-0x24420680, 0x3c010800, 0xac224e64, 0x3c020800,
-0x24420dcc, 0x3c010800, 0xac224ea0, 0x3c020800,
-0x24420a5c, 0x3c030800, 0x24630954, 0x3c040800,
-0x24840990, 0x3c050800, 0x24a53c70, 0x3c010800,
-0xac224ea8, 0x3c020800, 0x24420570, 0x3c010800,
-0xac264ea4, 0x3c010800, 0xac254eb4, 0x3c010800,
-0xac234ebc, 0x3c010800, 0xac224ec0, 0x3c010800,
-0xac244ec4, 0x3c010800, 0xac234e5c, 0x3c010800,
-0xac204e68, 0x3c010800, 0xac204e6c, 0x3c010800,
-0xac204e70, 0x3c010800, 0xac204e74, 0x3c010800,
-0xac204e78, 0x3c010800, 0xac204e7c, 0x3c010800,
-0xac204e80, 0x3c010800, 0xac244e84, 0x3c010800,
-0xac204e88, 0x3c010800, 0xac204e8c, 0x3c010800,
-0xac204e90, 0x3c010800, 0xac204e94, 0x3c010800,
-0xac204e98, 0x3c010800, 0xac264e9c, 0x3c010800,
-0xac204eac, 0x3c010800, 0xac254eb0, 0x3c010800,
-0xac234eb8, 0xa000707, 0x0, 0x3c030800,
-0x8c630020, 0x8f820008, 0x10430003, 0x0,
-0xa00053f, 0xaf830008, 0x3e00008, 0x0,
-0x27bdffe8, 0xafb00010, 0xafbf0014, 0x27500100,
-0x92020009, 0x1040001a, 0x24030001, 0x3c020800,
-0x8c420020, 0x10400016, 0x1821, 0xe000577,
-0x0, 0x96030008, 0x3c060800, 0x94c64ed6,
-0x8e040018, 0x8f820020, 0x9605000c, 0x31c00,
-0x661825, 0xac440000, 0xac450004, 0x24040001,
-0xac400008, 0xac40000c, 0xac400010, 0xac400014,
-0xac400018, 0xe00059c, 0xac43001c, 0x1821,
-0x8fbf0014, 0x8fb00010, 0x601021, 0x3e00008,
-0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x97420108,
-0x30437000, 0x24022000, 0x1062000a, 0x28642001,
-0x54800012, 0x8fbf0010, 0x24024000, 0x10620008,
-0x24026000, 0x1062000a, 0x8fbf0010, 0xa0000fb,
-0x1021, 0x8fbf0010, 0xa0000bb, 0x27bd0018,
-0xe000409, 0x0, 0xa0000fa, 0x8fbf0010,
-0xe000fc9, 0x0, 0x8fbf0010, 0x1021,
-0x3e00008, 0x27bd0018, 0x3c020800, 0x8c420020,
-0x27bdffe8, 0x10400027, 0xafbf0010, 0xe000577,
-0x0, 0x97420108, 0x9743010c, 0x8f850020,
-0x3042003e, 0x3063ffff, 0x21400, 0x431025,
-0xaca20000, 0x8f420100, 0x3c060800, 0x94c64ed6,
-0x8fbf0010, 0xaca20004, 0x97430116, 0x9744010e,
-0x3c022000, 0x31c00, 0x3084ffff, 0x641825,
-0xaca30008, 0xc23025, 0x97420110, 0x97430112,
-0x24040001, 0x21400, 0x3063ffff, 0x431025,
-0xaca2000c, 0x97420114, 0x27bd0018, 0x3042ffff,
-0xaca20010, 0xaca00014, 0xaca00018, 0xa00059c,
-0xaca6001c, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x3c020800, 0x8c420020, 0x27bdffe8, 0x1040002a,
-0xafbf0010, 0xe000577, 0x0, 0x97420108,
-0x9743010c, 0x8f850020, 0x3042003e, 0x3063ffff,
-0x21400, 0x431025, 0xaca20000, 0x8f420100,
-0x3c060800, 0x94c64ed6, 0x8fbf0010, 0xaca20004,
-0x97430116, 0x9744010e, 0x3c022000, 0x31c00,
-0x3084ffff, 0x641825, 0xaca30008, 0xc23025,
-0x97420110, 0x97430112, 0x24040001, 0x21400,
-0x3063ffff, 0x431025, 0xaca2000c, 0x97420114,
-0x27bd0018, 0x3042ffff, 0xaca20010, 0x8f420118,
-0xaca20014, 0x9342010b, 0x304200ff, 0xaca20018,
-0xa00059c, 0xaca6001c, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x27bdffe0, 0xafb00010, 0xafbf0018,
-0xafb10014, 0x27500100, 0x9203000b, 0x2402001a,
-0x96110008, 0x14620035, 0x2021, 0x32220001,
-0x10400009, 0x0, 0x8e020000, 0x96030014,
-0x211c2, 0x21040, 0x5a1021, 0xa4430080,
-0xa000179, 0x32220002, 0xe00012b, 0x0,
-0x3c020800, 0x8c420040, 0x24420001, 0x3c010800,
-0xac220040, 0x32220002, 0x2202b, 0x3c020800,
-0x8c420044, 0x32230004, 0x24420001, 0x3c010800,
-0xac220044, 0x1060001a, 0x8fbf0018, 0x8f4202b8,
-0x4410008, 0x24040001, 0x3c020800, 0x8c420060,
-0x24420001, 0x3c010800, 0xac220060, 0xa00019c,
-0x8fb10014, 0x8e020020, 0x96030016, 0x2021,
-0xaf420280, 0x8e020004, 0xa7430284, 0xaf420288,
-0x3c021000, 0xaf4202b8, 0x3c020800, 0x8c42005c,
-0x24420001, 0x3c010800, 0xac22005c, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x801021, 0x3e00008,
-0x27bd0020, 0x27bdffe0, 0xafb00010, 0xafbf0018,
-0xafb10014, 0x27500100, 0x9203000b, 0x24020003,
-0x96110008, 0x14620048, 0x2021, 0x32220001,
-0x10400008, 0x0, 0x8e020000, 0x96030014,
-0x211c2, 0x21040, 0x5a1021, 0xa0001bb,
-0xa4430080, 0xe0000fd, 0x0, 0x3c020800,
-0x8c420040, 0x24420001, 0x3c010800, 0xac220040,
-0x3c020800, 0x8c420044, 0x32230004, 0x24420001,
-0x3c010800, 0xac220044, 0x1060001a, 0x32220002,
-0x8f4202b8, 0x4430008, 0x8e020020, 0x3c020800,
-0x8c420060, 0x24420001, 0x3c010800, 0xac220060,
-0xa0001f1, 0x24040001, 0x96030016, 0x2021,
-0xaf420280, 0x8e020004, 0xa7430284, 0xaf420288,
-0x3c021000, 0xaf4202b8, 0x3c020800, 0x8c42005c,
-0x24420001, 0x3c010800, 0xac22005c, 0xa0001f2,
-0x8fbf0018, 0x10400014, 0x2021, 0x8f430104,
-0x3c026020, 0xac430014, 0x8c420004, 0x240301fe,
-0x304203ff, 0x1443000c, 0x2021, 0x8f420100,
-0x219c2, 0x2462fffc, 0x2c420008, 0x10400003,
-0x24040002, 0x2462fffd, 0x442004, 0x3c026000,
-0xac446914, 0x2021, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x801021, 0x3e00008, 0x27bd0020,
-0x93620000, 0x3e00008, 0xaf800004, 0x3e00008,
-0x1021, 0x27bdffe8, 0xafbf0014, 0xafb00010,
-0x8f420100, 0xaf420020, 0x8f420104, 0xaf4200a8,
-0x9350010b, 0xe0001f7, 0x321000ff, 0x3c020800,
-0x24424e58, 0x101880, 0x2e10001c, 0x16000004,
-0x621021, 0xe0001fa, 0xa000212, 0x0,
-0x8c420000, 0x40f809, 0x0, 0x10400005,
-0x3c024000, 0x8f430104, 0x3c026020, 0xac430014,
-0x3c024000, 0xaf420138, 0x3c020800, 0x8c420034,
-0x8fbf0014, 0x8fb00010, 0x24420001, 0x3c010800,
-0xac220034, 0x3e00008, 0x27bd0018, 0x27bdffe8,
-0xafbf0010, 0x8f420140, 0xe0001f7, 0xaf420020,
-0xe000393, 0x0, 0x3c024000, 0xaf420178,
-0x3c030800, 0x24630038, 0x8c620000, 0x8fbf0010,
-0x27bd0018, 0x24420001, 0x3e00008, 0xac620000,
-0x27bdffe8, 0xafbf0010, 0x8f420180, 0xe0001f7,
-0xaf420020, 0x8f430180, 0x24020f00, 0x14620005,
-0x0, 0x8f420188, 0xa742009c, 0xa00024c,
-0x3c024000, 0x93620000, 0x24030050, 0x304200ff,
-0x14430008, 0x3c024000, 0xe000377, 0x0,
-0x14400004, 0x3c024000, 0xe000e55, 0x0,
-0x3c024000, 0xaf4201b8, 0x3c020800, 0x8c42003c,
-0x8fbf0010, 0x24420001, 0x3c010800, 0xac22003c,
-0x3e00008, 0x27bd0018, 0x3e00008, 0x1021,
-0x8f430104, 0x8f820010, 0x10430008, 0x0,
-0x3c020800, 0x8c420084, 0x24420001, 0x3c010800,
-0xac220084, 0x8f420104, 0xaf820010, 0x3e00008,
-0x0, 0x27bdffe8, 0xafbf0010, 0x27440100,
-0x94820008, 0x30430002, 0x30420004, 0x1040001b,
-0x0, 0x8f4202b8, 0x4410008, 0x24050001,
-0x3c020800, 0x8c420060, 0x24420001, 0x3c010800,
-0xac220060, 0xa000294, 0x8fbf0010, 0x8c820020,
-0x94830016, 0x2821, 0xaf420280, 0x8c820004,
-0xa7430284, 0xaf420288, 0x3c021000, 0xaf4202b8,
-0x3c020800, 0x8c42005c, 0x24420001, 0x3c010800,
-0xac22005c, 0xa000294, 0x8fbf0010, 0x10600008,
-0x24050001, 0x3c020800, 0x8c420084, 0x24420001,
-0x3c010800, 0xac220084, 0xa000294, 0x8fbf0010,
-0x8f440100, 0xe000257, 0x0, 0x2821,
-0x8fbf0010, 0xa01021, 0x3e00008, 0x27bd0018,
-0x3c020800, 0x8c420088, 0x27430100, 0x9465000c,
-0x24420001, 0x3c010800, 0xac220088, 0x8c640018,
-0x3451021, 0x90454000, 0xaf440038, 0x8c62001c,
-0x2403fff8, 0x52e00, 0x431024, 0x34420004,
-0xaf42003c, 0x3c020005, 0xaf420030, 0x0,
-0x0, 0x0, 0xaf450404, 0x0,
-0x0, 0x0, 0x3c020006, 0x34420001,
-0xaf420030, 0x0, 0x0, 0x0,
-0x8f420000, 0x30420010, 0x1040fffd, 0x1021,
-0x3e00008, 0x0, 0x27bdffe0, 0xafbf0018,
-0xafb10014, 0xe000055, 0xafb00010, 0x3c028000,
-0x34420070, 0x8c420000, 0xaf820014, 0xe0000b2,
-0x0, 0x3c028000, 0x34460070, 0x3c030800,
-0x8c6300a0, 0x3c020800, 0x8c4200a4, 0x10430004,
-0x8f840014, 0x3c010800, 0xac2300a4, 0xa743009e,
-0x8cca0000, 0x3c030800, 0x8c6300bc, 0x3c020800,
-0x8c4200b8, 0x1442023, 0x641821, 0x4021,
-0x64202b, 0x481021, 0x441021, 0x3c010800,
-0xac2300bc, 0x3c010800, 0xac2200b8, 0x8f510000,
-0x32220007, 0x1040ffe1, 0xaf8a0014, 0x8cc60000,
-0x3c050800, 0x8ca500bc, 0x3c040800, 0x8c8400b8,
-0xca3023, 0xa62821, 0x1021, 0xa6302b,
-0x822021, 0x862021, 0x32270001, 0x3c010800,
-0xac2500bc, 0x3c010800, 0xac2400b8, 0x10e00021,
-0x32220002, 0x8f420100, 0xaf420020, 0x8f420104,
-0xaf4200a8, 0x9342010b, 0xe0001f7, 0x305000ff,
-0x2e02001c, 0x54400004, 0x101080, 0xe0001fa,
-0xa00030b, 0x0, 0x3c030800, 0x24634e58,
-0x431021, 0x8c420000, 0x40f809, 0x0,
-0x10400005, 0x3c024000, 0x8f430104, 0x3c026020,
-0xac430014, 0x3c024000, 0xaf420138, 0x3c020800,
-0x8c420034, 0x24420001, 0x3c010800, 0xac220034,
-0x32220002, 0x1040000e, 0x32220004, 0x8f420140,
-0xe0001f7, 0xaf420020, 0xe000393, 0x0,
-0x3c024000, 0xaf420178, 0x3c020800, 0x8c420038,
-0x24420001, 0x3c010800, 0xac220038, 0x32220004,
-0x1040ff9b, 0x3c028000, 0x8f420180, 0xe0001f7,
-0xaf420020, 0x8f430180, 0x24020f00, 0x14620005,
-0x0, 0x8f420188, 0xa742009c, 0xa000340,
-0x3c024000, 0x93620000, 0x24030050, 0x304200ff,
-0x14430008, 0x3c024000, 0xe000377, 0x0,
-0x54400004, 0x3c024000, 0xe000e55, 0x0,
-0x3c024000, 0xaf4201b8, 0x3c020800, 0x8c42003c,
-0x24420001, 0x3c010800, 0xac22003c, 0xa0002c3,
-0x3c028000, 0x3c029000, 0x34420001, 0x822025,
-0xaf440020, 0x8f420020, 0x440fffe, 0x0,
-0x3e00008, 0x0, 0x3c028000, 0x34420001,
-0x822025, 0x3e00008, 0xaf440020, 0x27bdffe0,
-0xafb10014, 0xafb00010, 0x808821, 0xafbf0018,
-0xe000348, 0x30b000ff, 0x9362007d, 0x2202021,
-0x2028025, 0xa370007d, 0x8f700074, 0x3c028000,
-0xe000351, 0x2028024, 0x16000009, 0x8fbf0018,
-0x8f4201f8, 0x440fffe, 0x24020002, 0xaf5101c0,
-0xa34201c4, 0x3c021000, 0xaf4201f8, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
-0x27bdffd0, 0x1021, 0x3e00008, 0x27bd0030,
-0x27bdffe8, 0xafbf0010, 0x97420184, 0x30420200,
-0x10400005, 0x2021, 0xe00108c, 0x0,
-0xa00038b, 0x24040001, 0x8f420188, 0x4400009,
-0x8fbf0010, 0x8f420188, 0x3c03ff00, 0x431024,
-0x3c030400, 0x14430003, 0x24040001, 0x9362003e,
-0x8fbf0010, 0x801021, 0x3e00008, 0x27bd0018,
-0xa3600022, 0x8f440140, 0xa000356, 0x24050001,
-0x27bdffe8, 0xafbf0014, 0xafb00010, 0x93620000,
-0x24030020, 0x304200ff, 0x1043000b, 0x0,
-0x93620000, 0x24030030, 0x304200ff, 0x10430006,
-0x0, 0x93620000, 0x24030050, 0x304200ff,
-0x14430062, 0x8fbf0014, 0x93420148, 0x304200ff,
-0x2443ffff, 0x2c620005, 0x1040005c, 0x8fbf0014,
-0x31080, 0x3c030800, 0x24634df0, 0x431021,
-0x8c420000, 0x400008, 0x0, 0xe000348,
-0x8f440140, 0x8f70000c, 0x8f420144, 0x16020002,
-0x24020001, 0xaf62000c, 0xe000351, 0x8f440140,
-0x8f420144, 0x14500004, 0x8fbf0014, 0x8fb00010,
-0xa001000, 0x27bd0018, 0x8f62000c, 0xa0003ff,
-0x0, 0x97620010, 0x8f430144, 0x3042ffff,
-0x14620009, 0x0, 0x24020001, 0xa7620010,
-0x8f420140, 0xaf420200, 0x3c021000, 0xaf420238,
-0xa000406, 0x8fbf0014, 0x97620010, 0xa0003ff,
-0x0, 0xe000348, 0x8f440140, 0x97620012,
-0x8f430144, 0x3050ffff, 0x16030002, 0x24020001,
-0xa7620012, 0xe000351, 0x8f440140, 0x8f420144,
-0x16020004, 0x8fbf0014, 0x8fb00010, 0xa00038f,
-0x27bd0018, 0x97620012, 0xa0003ff, 0x0,
-0x97620014, 0x8f430144, 0x3042ffff, 0x14620006,
-0x8fbf0014, 0x24020001, 0x8fb00010, 0xa7620014,
-0xa00132c, 0x27bd0018, 0x97620014, 0xa0003ff,
-0x0, 0x97620016, 0x8f430144, 0x3042ffff,
-0x14620006, 0x24020001, 0x8fbf0014, 0x8fb00010,
-0xa7620016, 0xa000bf3, 0x27bd0018, 0x97620016,
-0x14400006, 0x8fbf0014, 0x3c020800, 0x8c420070,
-0x24420001, 0x3c010800, 0xac220070, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0x93430109, 0x2402001f, 0x8f500100,
-0x106200a5, 0x28620020, 0x10400018, 0x24020038,
-0x2862000a, 0x1040000c, 0x2402000b, 0x28620008,
-0x1040002c, 0x0, 0x46000e7, 0x28620002,
-0x14400028, 0x24020006, 0x10620026, 0x8fbf0014,
-0xa000503, 0x8fb00010, 0x1062005e, 0x2862000b,
-0x144000de, 0x8fbf0014, 0x2402000e, 0x10620073,
-0x8fb00010, 0xa000503, 0x0, 0x106200c2,
-0x28620039, 0x1040000a, 0x24020080, 0x24020036,
-0x106200cc, 0x28620037, 0x104000b6, 0x24020035,
-0x106200c3, 0x8fbf0014, 0xa000503, 0x8fb00010,
-0x1062002b, 0x28620081, 0x10400006, 0x240200c8,
-0x24020039, 0x106200b6, 0x8fbf0014, 0xa000503,
-0x8fb00010, 0x10620099, 0x8fbf0014, 0xa000503,
-0x8fb00010, 0x3c020800, 0x8c420020, 0x104000bb,
-0x8fbf0014, 0xe000577, 0x0, 0x8f420100,
-0x8f830020, 0x9745010c, 0x97460108, 0xac620000,
-0x8f420104, 0x3c040800, 0x94844ed6, 0x52c00,
-0xac620004, 0x8f420118, 0x63400, 0xc43025,
-0xac620008, 0x8f42011c, 0x24040001, 0xac62000c,
-0x9342010a, 0xa22825, 0xac650010, 0xac600014,
-0xac600018, 0xac66001c, 0xa0004d7, 0x8fbf0014,
-0x3c020800, 0x8c420020, 0x1040009c, 0x8fbf0014,
-0xe000577, 0x0, 0x97440108, 0x3c030800,
-0x94634ed6, 0x9745010c, 0x42202, 0x9746010e,
-0x8f820020, 0x42600, 0x832025, 0x52c00,
-0x3c030080, 0xa62825, 0x832025, 0xac400000,
-0xac400004, 0xac400008, 0xac40000c, 0xac450010,
-0xac400014, 0xac400018, 0xac44001c, 0xa0004d6,
-0x24040001, 0x9742010c, 0x14400015, 0x0,
-0x93620005, 0x30420010, 0x14400011, 0x0,
-0xe000348, 0x2002021, 0x93620005, 0x2002021,
-0x34420010, 0xe000351, 0xa3620005, 0x93620000,
-0x24030020, 0x304200ff, 0x1043006f, 0x2002021,
-0x8fbf0014, 0x8fb00010, 0xa0010a2, 0x27bd0018,
-0xd, 0xa000502, 0x8fbf0014, 0x3c020800,
-0x8c420020, 0x10400065, 0x8fbf0014, 0xe000577,
-0x0, 0x8f420104, 0x8f830020, 0x9744010c,
-0x3c050800, 0x94a54ed6, 0xac620000, 0x9762002c,
-0x42400, 0x3042ffff, 0x822025, 0x3c02400e,
-0xa22825, 0xac640004, 0xac600008, 0xac60000c,
-0xac600010, 0xac600014, 0xac600018, 0xac65001c,
-0xa0004d6, 0x24040001, 0xe000348, 0x2002021,
-0xa7600008, 0xe000351, 0x2002021, 0x2002021,
-0xe000356, 0x24050001, 0x3c020800, 0x8c420020,
-0x10400042, 0x8fbf0014, 0xe000577, 0x0,
-0x9742010c, 0x8f830020, 0x3c050800, 0x94a54ed6,
-0x21400, 0xac700000, 0xac620004, 0xac600008,
-0x8f64004c, 0x3c02401f, 0xa22825, 0xac64000c,
-0x8f620050, 0x24040001, 0xac620010, 0x8f620054,
-0xac620014, 0xac600018, 0xac65001c, 0x8fbf0014,
-0x8fb00010, 0xa00059c, 0x27bd0018, 0x93620000,
-0x24030020, 0x304200ff, 0x10430024, 0x8fbf0014,
-0xe000fea, 0x2002021, 0x10400020, 0x8fbf0014,
-0x2002021, 0x8fb00010, 0x2821, 0xa000356,
-0x27bd0018, 0x2002021, 0x8fbf0014, 0x8fb00010,
-0xa000664, 0x27bd0018, 0x9745010c, 0x2002021,
-0x8fbf0014, 0x8fb00010, 0xa000684, 0x27bd0018,
-0x2002021, 0x8fb00010, 0xa0006a9, 0x27bd0018,
-0x9345010d, 0x2002021, 0x8fb00010, 0xa0006f3,
-0x27bd0018, 0x2002021, 0x8fbf0014, 0x8fb00010,
-0xa0006cf, 0x27bd0018, 0x8fbf0014, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0x8f420278, 0x440fffe,
-0x34820080, 0xaf420240, 0x24020002, 0xa3420244,
-0x3c021000, 0x3e00008, 0xaf420278, 0x3c040800,
-0x94844ee2, 0x3c020800, 0x8c424eec, 0x3083ffff,
-0x318c0, 0x431021, 0xaf42003c, 0x3c020800,
-0x8c424ee8, 0xaf420038, 0x3c020050, 0x34420008,
-0xaf420030, 0x0, 0x0, 0x0,
-0x8f420000, 0x30420020, 0x1040fffd, 0x0,
-0x8f420400, 0x3c010800, 0xac224ed8, 0x8f420404,
-0x3c010800, 0xac224edc, 0x3c020020, 0xaf420030,
-0x0, 0x3c020800, 0x94424ee0, 0x3c030800,
-0x94634ee4, 0x3c050800, 0x94a54ee6, 0x24840001,
-0x431021, 0x3083ffff, 0x3c010800, 0xa4224ee0,
-0x3c010800, 0xa4244ee2, 0x14650003, 0x0,
-0x3c010800, 0xa4204ee2, 0x3e00008, 0x0,
-0x3c05000a, 0x27bdffe8, 0x3452821, 0x3c040800,
-0x24844ec8, 0xafbf0010, 0xe000601, 0x2406000a,
-0x3c020800, 0x94424eca, 0x3c030800, 0x94634ee6,
-0x3042000f, 0x24420003, 0x431804, 0x24027fff,
-0x43102b, 0x10400002, 0xaf83001c, 0xd,
-0xe00050e, 0x0, 0x3c020800, 0x94424ed2,
-0x8fbf0010, 0x27bd0018, 0x3e00008, 0xa74200a2,
-0x3c02000a, 0x3421021, 0x94430006, 0x3c020800,
-0x94424ed2, 0x3c010800, 0xa4234ece, 0x431023,
-0x8f83001c, 0x21400, 0x21403, 0x43102b,
-0x3e00008, 0x38420001, 0x27bdffe8, 0xafbf0010,
-0x3c02000a, 0x3421021, 0x94420006, 0x3c010800,
-0xa4224ece, 0xe00055b, 0x0, 0x5440fff9,
-0x3c02000a, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe8, 0xafbf0010, 0xe00055b, 0x0,
-0x10400003, 0x0, 0xe000569, 0x0,
-0x3c020800, 0x8c424ed8, 0x8fbf0010, 0x27430400,
-0xaf420038, 0x3c020800, 0x8c424edc, 0x27bd0018,
-0xaf830020, 0xaf42003c, 0x3c020005, 0xaf420030,
-0x3e00008, 0xaf800018, 0x8f820018, 0x3c030006,
-0x21140, 0x431025, 0xaf420030, 0x0,
-0x0, 0x0, 0x8f420000, 0x30420010,
-0x1040fffd, 0x27420400, 0xaf820020, 0x3e00008,
-0xaf800018, 0x3c060800, 0x8cc64edc, 0x8f850018,
-0x8f830020, 0x3c020800, 0x94424ed2, 0x27bdffe0,
-0x24a50001, 0x24630020, 0x24420001, 0x24c70020,
-0xafb10014, 0xafb00010, 0xafbf0018, 0xaf850018,
-0xaf830020, 0x3c010800, 0xa4224ed2, 0x309000ff,
-0x3c010800, 0xac274edc, 0x4c10008, 0x8821,
-0x4e00006, 0x0, 0x3c020800, 0x8c424ed8,
-0x24420001, 0x3c010800, 0xac224ed8, 0x3c020800,
-0x94424ed2, 0x3c030800, 0x94634ee0, 0x10202b,
-0x431026, 0x2c420001, 0x441025, 0x14400004,
-0x8f830018, 0x24020010, 0x1462000f, 0x0,
-0xe00058d, 0x24110001, 0x3c030800, 0x94634ed2,
-0x3c020800, 0x94424ee0, 0x14620003, 0x0,
-0xe00050e, 0x0, 0x16000003, 0x0,
-0xe000577, 0x0, 0x3c030800, 0x94634ed6,
-0x3c020800, 0x94424ed4, 0x24630001, 0x3064ffff,
-0x3c010800, 0xa4234ed6, 0x14820003, 0x0,
-0x3c010800, 0xa4204ed6, 0x12000006, 0x0,
-0x3c020800, 0x94424ed2, 0xa74200a2, 0xa0005ef,
-0x2201021, 0xe00055b, 0x0, 0x10400004,
-0x2201021, 0xe000569, 0x0, 0x2201021,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0020, 0x3084ffff, 0x30a5ffff, 0x1821,
-0x10800007, 0x0, 0x30820001, 0x10400002,
-0x42042, 0x651821, 0xa0005f7, 0x52840,
-0x3e00008, 0x601021, 0x10c00006, 0x24c6ffff,
-0x8ca20000, 0x24a50004, 0xac820000, 0xa000601,
-0x24840004, 0x3e00008, 0x0, 0x10a00008,
-0x24a3ffff, 0xac860000, 0x0, 0x0,
-0x2402ffff, 0x2463ffff, 0x1462fffa, 0x24840004,
-0x3e00008, 0x0, 0x24020001, 0xaf62000c,
-0xa7620010, 0xa7620012, 0xa7620014, 0x3e00008,
-0xa7620016, 0x3082007f, 0x3421021, 0x3c08000e,
-0x481821, 0x3c020800, 0x8c420020, 0x27bdffd8,
-0x2407ff80, 0xafb3001c, 0xafb20018, 0xafb10014,
-0xafb00010, 0xafbf0020, 0x808021, 0x30b100ff,
-0x872024, 0x30d200ff, 0x1040002f, 0x9821,
-0xaf44002c, 0x90620000, 0x24030050, 0x304200ff,
-0x1443000e, 0x0, 0x3c020800, 0x8c4200e0,
-0x2021021, 0x471024, 0xaf42002c, 0x3c020800,
-0x8c4200e0, 0x2021021, 0x3042007f, 0x3421021,
-0x481021, 0x944200d4, 0x3053ffff, 0xe000577,
-0x0, 0x3c020800, 0x94424ed6, 0x8f830020,
-0x113400, 0xc23025, 0x122c00, 0x3c024000,
-0xc23025, 0x34a50001, 0xac700000, 0x8fbf0020,
-0xac600004, 0x8fb20018, 0xac730008, 0x8fb10014,
-0xac60000c, 0x8fb3001c, 0xac650010, 0x8fb00010,
-0xac600014, 0x24040001, 0xac600018, 0x27bd0028,
-0xa00059c, 0xac66001c, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0028, 0x9343010f, 0x24020010, 0x1062000e,
-0x28650011, 0x10a00007, 0x24020012, 0x24020008,
-0x2405003a, 0x10620006, 0x3021, 0x3e00008,
-0x0, 0x24050035, 0x1462fffc, 0x3021,
-0xa00061c, 0x0, 0x8f420074, 0x24420fa0,
-0x3e00008, 0xaf62000c, 0x27bdffe8, 0xafbf0010,
-0xe000356, 0x24050001, 0x8fbf0010, 0x24020001,
-0xa7620012, 0x27bd0018, 0x24020001, 0x3e00008,
-0xa3600022, 0x27bdffe0, 0xafb10014, 0xafb00010,
-0xafbf0018, 0x30b1ffff, 0xe000348, 0x808021,
-0x9362003f, 0x24030004, 0x304200ff, 0x1443000c,
-0x2002021, 0x12200008, 0x2402000a, 0xe000615,
-0x0, 0x93620005, 0x2403fffe, 0x431024,
-0xa3620005, 0x24020012, 0xa362003f, 0x2002021,
-0xe000351, 0xa3600081, 0x16200003, 0x2002021,
-0xe000679, 0x0, 0x2002021, 0x322600ff,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x24050038,
-0xa00061c, 0x27bd0020, 0x27bdffe0, 0xafbf001c,
-0xafb20018, 0xafb10014, 0xafb00010, 0xe000348,
-0x808021, 0xe000615, 0x0, 0x9362003f,
-0x24120018, 0x305100ff, 0x12320003, 0x2002021,
-0x24020012, 0xa362003f, 0x93620005, 0x2403fffe,
-0x431024, 0xe000351, 0xa3620005, 0x2002021,
-0x24050020, 0x16320007, 0x3021, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa000356,
-0x27bd0020, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x24050039, 0xa00061c, 0x27bd0020,
-0x27bdffe8, 0xafb00010, 0xafbf0014, 0x9742010c,
-0x24050036, 0x808021, 0x14400010, 0x304600ff,
-0xe000348, 0x0, 0x24020012, 0xa362003f,
-0x93620005, 0x34420010, 0xe000615, 0xa3620005,
-0xe000351, 0x2002021, 0x2002021, 0xe000356,
-0x24050020, 0xa0006e8, 0x0, 0xe00061c,
-0x0, 0xe000348, 0x2002021, 0x93620023,
-0x2403ff9f, 0x2002021, 0x431024, 0x8fbf0014,
-0x8fb00010, 0xa3620023, 0xa000351, 0x27bd0018,
-0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
-0x30b100ff, 0xe000348, 0x808021, 0x24020012,
-0xe000615, 0xa362003f, 0xe000351, 0x2002021,
-0x2002021, 0x2203021, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x24050035, 0xa00061c, 0x27bd0020,
-0xa380002c, 0x3e00008, 0xa380002d, 0x8f420278,
-0x440fffe, 0x8f820034, 0xaf420240, 0x24020002,
-0xa3420244, 0x3c021000, 0x3e00008, 0xaf420278,
-0x3c036000, 0x8c625400, 0x30420008, 0x1440fffd,
-0x0, 0x8c625408, 0xaf820000, 0x24020052,
-0xac605408, 0xac645430, 0xac625434, 0x24020008,
-0x3e00008, 0xac625400, 0x3c026000, 0x8c425400,
-0x30420008, 0x10400005, 0x3c036000, 0x8c625400,
-0x30420008, 0x1440fffd, 0x0, 0x8f830000,
-0x3c026000, 0x3e00008, 0xac435408, 0x90a30000,
-0x24020005, 0x804021, 0x3063003f, 0x4821,
-0x14620005, 0x5021, 0x90a2001c, 0x94a3001e,
-0x304900ff, 0x306affff, 0xad00000c, 0xad000010,
-0xad000024, 0x95020014, 0x8d05001c, 0x8d040018,
-0x3042ffff, 0x491023, 0x21100, 0x237c3,
-0x403821, 0x862023, 0xa2102b, 0x822023,
-0xa72823, 0xad05001c, 0xad040018, 0xa5090014,
-0xa5090020, 0xa50a0016, 0x3e00008, 0xa50a0022,
-0x8f4201f8, 0x440fffe, 0x24020002, 0xaf4401c0,
-0xa34201c4, 0x3c021000, 0x3e00008, 0xaf4201f8,
-0x3c020800, 0x8c4200b4, 0x27bdffe8, 0xafbf0014,
-0x24420001, 0xafb00010, 0x3c010800, 0xac2200b4,
-0x8f430024, 0x3c02001f, 0x30aa00ff, 0x3442ff80,
-0x30d800ff, 0x628024, 0x80f821, 0x30ef00ff,
-0x1158003b, 0x1405821, 0x240cff80, 0x3c19000a,
-0x3163007f, 0x310c0, 0x31940, 0x621821,
-0x3c020800, 0x8c4200dc, 0x25680001, 0x310d007f,
-0x3e21021, 0x431021, 0x3043007f, 0x3431821,
-0x4c1024, 0x794821, 0xaf420024, 0x8d220024,
-0x16c1824, 0x6c7026, 0xad22000c, 0x8d220024,
-0x310800ff, 0xad220010, 0x95220014, 0x95230020,
-0x8d27001c, 0x3042ffff, 0x3063ffff, 0x8d260018,
-0x431023, 0x21100, 0x227c3, 0x402821,
-0xc43023, 0xe2102b, 0xc23023, 0xe53823,
-0xad27001c, 0xad260018, 0x95220020, 0xa5220014,
-0x95220022, 0x154b000a, 0xa5220016, 0x8d230024,
-0x8d220008, 0x25460001, 0x31450080, 0x14620004,
-0x30c4007f, 0x108f0002, 0x38aa0080, 0xc05021,
-0x51af0001, 0x31c800ff, 0x1518ffc9, 0x1005821,
-0x8f840034, 0x3082007f, 0x3421821, 0x3c02000a,
-0x621821, 0x2402ff80, 0x822024, 0xaf440024,
-0xa06a0079, 0xa06a0083, 0x8c620050, 0x8f840034,
-0xac620070, 0x8c650074, 0x3c027fff, 0x3442ffff,
-0xa22824, 0xe00074f, 0xac650074, 0xaf500024,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x27bdffc0, 0xafbe0038, 0xafb70034, 0xafb5002c,
-0xafb20020, 0xafb1001c, 0xafb00018, 0xafbf003c,
-0xafb60030, 0xafb40028, 0xafb30024, 0x8f450024,
-0x8f460028, 0x8f43002c, 0x3c02001f, 0x3442ff80,
-0x621824, 0xc23024, 0x80a821, 0xafa30014,
-0xa2f024, 0xe000713, 0xafa60010, 0x3c020800,
-0x8c4200e0, 0x2410ff80, 0x3608821, 0x2a21021,
-0x501024, 0xaf420024, 0x3c020800, 0x8c4200e0,
-0x2a21021, 0x3042007f, 0x3421821, 0x3c02000a,
-0x629021, 0x924200d2, 0x93630084, 0x305700ff,
-0x306300ff, 0x24020001, 0x10620034, 0x3602021,
-0x24020002, 0x14620036, 0x0, 0xe0012f8,
-0x2402821, 0x92230083, 0x92220083, 0x3063007f,
-0x3042007f, 0x210c0, 0x31940, 0x621821,
-0x3c020800, 0x8c4200dc, 0x2a21021, 0x433821,
-0xf01024, 0xaf420028, 0x92250078, 0x92240083,
-0x30e2007f, 0x3421821, 0x3c02000c, 0x14850007,
-0x628021, 0x2402ffff, 0xa24200f1, 0x2402ffff,
-0xa64200f2, 0xa00080b, 0x2402ffff, 0x96020020,
-0xa24200f1, 0x96020022, 0xa64200f2, 0x8e020024,
-0xae4200f4, 0x92220083, 0xa24200f0, 0x8e4200c8,
-0xae4200fc, 0x8e4200c4, 0xae4200f8, 0x8e220050,
-0xae420100, 0x8e4200cc, 0xae420104, 0x92220085,
-0x3042003f, 0xa000866, 0x34420040, 0xe00131b,
-0x2402821, 0x92220085, 0xa000866, 0x3042003f,
-0x93620085, 0x2403ffdf, 0x3042003f, 0xa3620085,
-0x93620085, 0x431024, 0xa3620085, 0x93630083,
-0x93620078, 0x307400ff, 0x304200ff, 0x10540036,
-0x240aff80, 0x3c0c000c, 0x3283007f, 0x310c0,
-0x31940, 0x621821, 0x3c020800, 0x8c4200dc,
-0x26880001, 0x3109007f, 0x2a21021, 0x433821,
-0x30e2007f, 0x3421821, 0xea1024, 0xaf420028,
-0x6c8021, 0x8e020024, 0x28a1824, 0x6a5826,
-0xae02000c, 0x8e020024, 0x310800ff, 0xae020010,
-0x96020014, 0x96030020, 0x8e07001c, 0x3042ffff,
-0x3063ffff, 0x8e060018, 0x431023, 0x21100,
-0x227c3, 0x402821, 0xc43023, 0xe2102b,
-0xc23023, 0xe53823, 0xae07001c, 0xae060018,
-0x96020020, 0xa6020014, 0x96020022, 0xa6020016,
-0x92220079, 0x304200ff, 0x10540007, 0x0,
-0x51370001, 0x316800ff, 0x92220078, 0x304200ff,
-0x1448ffcd, 0x100a021, 0x92220083, 0xa2220079,
-0x8e220050, 0xa0008c6, 0xae220070, 0xa2220085,
-0x8e22004c, 0x2405ff80, 0xae42010c, 0x92220085,
-0x34420020, 0xa2220085, 0x924200d1, 0x3c030800,
-0x8c6300dc, 0x305400ff, 0x3c020800, 0x8c4200e4,
-0x143140, 0x1420c0, 0x2a31821, 0xc42021,
-0x2a21021, 0x643821, 0x461021, 0x451824,
-0xe52824, 0xaf450028, 0xaf43002c, 0x3042007f,
-0x924400d0, 0x30e3007f, 0x3422821, 0x3431821,
-0x3c02000c, 0x628021, 0x3c02000e, 0x309600ff,
-0xa29821, 0x1296002a, 0x0, 0x8e02000c,
-0x2002021, 0x2602821, 0x10400025, 0x26100028,
-0xe00072e, 0x0, 0x9262000d, 0x26830001,
-0x307400ff, 0x3042007f, 0xa262000d, 0x2404ff80,
-0x1697fff0, 0x26730020, 0x3c020800, 0x8c4200dc,
-0xa021, 0x2a21021, 0x441024, 0xaf420028,
-0x3c020800, 0x8c4200e4, 0x3c030800, 0x8c6300dc,
-0x2a21021, 0x441024, 0xaf42002c, 0x3c020800,
-0x8c4200e4, 0x2a31821, 0x3063007f, 0x2a21021,
-0x3042007f, 0x3422021, 0x3431821, 0x3c02000c,
-0x628021, 0x3c02000e, 0xa000888, 0x829821,
-0x8e4200d8, 0xae220050, 0x8e4200d8, 0xae220070,
-0x92250083, 0x924600d1, 0x92230083, 0x924400d1,
-0x2402ff80, 0xa22824, 0x3063007f, 0x308400ff,
-0xa62825, 0x64182a, 0x10600002, 0x30a500ff,
-0x38a50080, 0xa2250083, 0xa2250079, 0xe000721,
-0x0, 0x9222007e, 0x2a02021, 0xa222007a,
-0x8e230074, 0x3c027fff, 0x3442ffff, 0x621824,
-0xe00074f, 0xae230074, 0x8fa20010, 0xaf5e0024,
-0x8fbf003c, 0xaf420028, 0x8fbe0038, 0x8fa20014,
-0x8fb70034, 0x8fb60030, 0x8fb5002c, 0x8fb40028,
-0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
-0x27bd0040, 0x3e00008, 0xaf42002c, 0x90a20000,
-0x24420001, 0xa0a20000, 0x3c030800, 0x8c6300f4,
-0x304200ff, 0x1443000f, 0x803021, 0xa0a00000,
-0x3c020800, 0x8c4200e4, 0x8f840034, 0x822021,
-0x3082007f, 0x3421821, 0x3c02000c, 0x621821,
-0x2402ff80, 0x822024, 0xacc30000, 0x3e00008,
-0xaf440028, 0x8c820000, 0x24420020, 0x3e00008,
-0xac820000, 0x94c20000, 0x3c080800, 0x950800ca,
-0x30e7ffff, 0x804821, 0x1021021, 0xa4c20000,
-0x94c20000, 0x3042ffff, 0xe2102b, 0x54400001,
-0xa4c70000, 0x94a20000, 0x3c030800, 0x8c6300cc,
-0x24420001, 0xa4a20000, 0x94a20000, 0x3042ffff,
-0x54430007, 0x8f860028, 0x107102b, 0xa4a00000,
-0x54400001, 0x1003821, 0xa4c70000, 0x8f860028,
-0x8cc4001c, 0xaf44003c, 0x94a20000, 0x8f43003c,
-0x3042ffff, 0x210c0, 0x621821, 0xaf43003c,
-0x8f42003c, 0x822023, 0x18800004, 0x0,
-0x8cc20018, 0xa000927, 0x24420001, 0x8cc20018,
-0xaf420038, 0x3c020050, 0x34420010, 0xaf420030,
-0x0, 0x0, 0x0, 0x8f420000,
-0x30420020, 0x1040fffd, 0x0, 0x8f420404,
-0xad220004, 0x8f420400, 0xad220000, 0x3c020020,
-0xaf420030, 0x3e00008, 0x0, 0x27bdffe0,
-0xafb20018, 0xafb10014, 0xafb00010, 0xafbf001c,
-0x94c20000, 0xc08021, 0x3c120800, 0x965200c6,
-0x24420001, 0xa6020000, 0x96030000, 0x94e20000,
-0xe03021, 0x14430005, 0x8fb10030, 0xe0008fc,
-0x2403821, 0xa000959, 0x0, 0x8c830004,
-0x8c820004, 0x24420040, 0x4610007, 0xac820004,
-0x8c820004, 0x4400004, 0x0, 0x8c820000,
-0x24420001, 0xac820000, 0x96020000, 0x3042ffff,
-0x50520001, 0xa6000000, 0x96220000, 0x24420001,
-0xa6220000, 0x8f820028, 0x96230000, 0x94420016,
-0x14430004, 0x8fbf001c, 0x24020001, 0xa6220000,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x8f890028, 0x27bdffe0,
-0xafbf0018, 0x8d220028, 0x27480400, 0x30e700ff,
-0xaf420038, 0x8d22002c, 0xaf880030, 0xaf42003c,
-0x3c020005, 0xaf420030, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x8c82000c, 0x8c82000c, 0xad020000, 0x8c820010,
-0xad020004, 0x8c820018, 0xad020008, 0x8c82001c,
-0xad02000c, 0x8ca20014, 0xad020010, 0x8c820020,
-0xad020014, 0x90820005, 0x304200ff, 0x21200,
-0xad020018, 0x8ca20018, 0xad02001c, 0x8ca2000c,
-0xad020020, 0x8ca20010, 0xad020024, 0x8ca2001c,
-0xad020028, 0x8ca20020, 0xad02002c, 0xad060030,
-0xad000034, 0x97830026, 0x3402ffff, 0x14620002,
-0x602021, 0x3404ffff, 0x10e00011, 0xad040038,
-0x95230036, 0x95240036, 0x24020001, 0x3063ffff,
-0x318c2, 0x691821, 0x90650040, 0x30840007,
-0x821004, 0x451025, 0xa0620040, 0x8f820028,
-0x94420056, 0x3042ffff, 0xa0009c0, 0xad02003c,
-0x95230036, 0x95240036, 0x24020001, 0x3063ffff,
-0x318c2, 0x691821, 0x90650040, 0x30840007,
-0x821004, 0x21027, 0x451024, 0xa0620040,
-0xad00003c, 0x0, 0x0, 0x0,
-0x3c020006, 0x34420040, 0xaf420030, 0x0,
-0x0, 0x0, 0x8f420000, 0x30420010,
-0x1040fffd, 0x8f860028, 0xaf880030, 0x24c20056,
-0x24c7003c, 0x24c40028, 0x24c50032, 0x24c60036,
-0xe00093a, 0xafa20010, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x8f830024, 0x3c050800, 0x8ca500e8,
-0x8f820034, 0x30633fff, 0x31980, 0x451021,
-0x431021, 0x2403ff80, 0x3045007f, 0x431024,
-0xaf420028, 0x3451821, 0x3c02000c, 0x623021,
-0x90c2000d, 0x3821, 0x34420010, 0xa0c2000d,
-0x8f890028, 0x8f8a0024, 0x95230036, 0xa1382,
-0x30480003, 0x24020001, 0xa4c3000e, 0x1102000b,
-0x29020002, 0x10400005, 0x24020002, 0x1100000c,
-0x24030001, 0xa000a03, 0x1821, 0x11020006,
-0x0, 0xa000a03, 0x1821, 0x8cc2002c,
-0xa000a03, 0x24430001, 0x8cc20014, 0x24430001,
-0x8cc20018, 0x43102b, 0x14400003, 0x0,
-0xa000a0c, 0x24070001, 0x9522003e, 0x24420001,
-0xa522003e, 0xa1382, 0x30430003, 0x2c620002,
-0x10400009, 0x802821, 0x14600004, 0x0,
-0x94c20036, 0xa000a1c, 0x3046ffff, 0x8cc60038,
-0xa000a1c, 0x802821, 0x3021, 0x3c040800,
-0x24844ef0, 0xa00096d, 0x0, 0x27490100,
-0x8d22000c, 0x95230006, 0x1202021, 0x21602,
-0x3045003f, 0x3063ffff, 0x24020027, 0x28a60028,
-0x10a2000e, 0xaf830024, 0x10c00008, 0x24020031,
-0x24020021, 0x10a20009, 0x24020025, 0x10a20007,
-0x9382002d, 0xa000a3a, 0x0, 0x10a20005,
-0x9382002d, 0xa000a3a, 0x0, 0xa0009d8,
-0x0, 0xa00070a, 0x0, 0x95230006,
-0x91240005, 0x8d25000c, 0x8d260010, 0x8d270018,
-0x8d28001c, 0x8d290020, 0x24420001, 0x3c010800,
-0xa4234ef6, 0x3c010800, 0xa0244ef5, 0x3c010800,
-0xac254efc, 0x3c010800, 0xac264f00, 0x3c010800,
-0xac274f08, 0x3c010800, 0xac284f0c, 0x3c010800,
-0xac294f10, 0x3e00008, 0xa382002d, 0x8f870028,
-0x27bdffc0, 0xafb30034, 0xafb20030, 0xafb1002c,
-0xafb00028, 0xafbf0038, 0x3c020800, 0x8c4200d0,
-0x94e30030, 0x30b0ffff, 0x501007, 0x3045ffff,
-0x3063ffff, 0xc09821, 0xa7a20010, 0x3c110800,
-0x963100c6, 0x14a30006, 0x3092ffff, 0x8ce20024,
-0x24420030, 0xaf42003c, 0xa000a73, 0x8ce20020,
-0x94e20032, 0x3042ffff, 0x54a20008, 0x27a40018,
-0x8ce2002c, 0x24420030, 0xaf42003c, 0x8ce20028,
-0xaf420038, 0xa000a81, 0x8f840028, 0x27a50010,
-0x27a60020, 0x2203821, 0xe0008fc, 0xa7a00020,
-0x8fa20018, 0x24420030, 0xaf420038, 0x8fa2001c,
-0xaf42003c, 0x8f840028, 0x3c020005, 0xaf420030,
-0x94820034, 0x27430400, 0x3042ffff, 0x202102b,
-0x14400007, 0xaf830030, 0x94820054, 0x94830034,
-0x2021021, 0x431023, 0xa000a95, 0x3043ffff,
-0x94830054, 0x94820034, 0x2231821, 0x501023,
-0x621823, 0x3063ffff, 0x94820016, 0x3042ffff,
-0x14430003, 0x0, 0xa000aa3, 0x24030001,
-0x94820016, 0x3042ffff, 0x43102b, 0x10400005,
-0x8f820030, 0x94820016, 0x621023, 0x3043ffff,
-0x8f820030, 0xac530000, 0xac400004, 0xac520008,
-0xac43000c, 0x3c020006, 0x34420010, 0xaf420030,
-0x0, 0x0, 0x0, 0x8f420000,
-0x30420010, 0x1040fffd, 0x1018c2, 0x641821,
-0x90650040, 0x32040007, 0x24020001, 0x8fbf0038,
-0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
-0x821004, 0x451025, 0x27bd0040, 0x3e00008,
-0xa0620040, 0x27bdffa8, 0xafb60050, 0xafb5004c,
-0xafb40048, 0xafb30044, 0xafb1003c, 0xafbf0054,
-0xafb20040, 0xafb00038, 0x8c900000, 0x3c020800,
-0x8c4200e8, 0x8f860034, 0x96030002, 0x2413ff80,
-0xc23021, 0x30633fff, 0x31980, 0xc33821,
-0xf31024, 0x90b20000, 0xaf42002c, 0x92030002,
-0x30e2007f, 0x3423021, 0x3c02000e, 0xc28821,
-0x306300c0, 0x24020040, 0x80a821, 0xa0b021,
-0x14620026, 0xa021, 0x8e340038, 0x8e220018,
-0x14400002, 0x24020001, 0xae220018, 0x9202000d,
-0x30420020, 0x14400015, 0x8f820034, 0x3c030800,
-0x8c6300dc, 0x1238c0, 0x123140, 0x431021,
-0xc73021, 0x463821, 0x30e30007, 0x3c020080,
-0x30e60078, 0xc23025, 0x3431821, 0xf31024,
-0xaf420800, 0x24630900, 0xaf460810, 0x8e220018,
-0x8c630008, 0x431021, 0xae220018, 0x8e22002c,
-0x8e230018, 0x24420001, 0x62182b, 0x1060003d,
-0x0, 0xa000b57, 0x0, 0x92030002,
-0x2402ffc0, 0x431024, 0x304200ff, 0x14400005,
-0x24020001, 0xae220018, 0x96220036, 0xa000b40,
-0x3054ffff, 0x8e220014, 0x24420001, 0xae220018,
-0x92020000, 0x21600, 0x21603, 0x4410029,
-0x0, 0x96020002, 0x27a40010, 0x802821,
-0xa7a20016, 0x96020002, 0x24070001, 0x3021,
-0x3042ffff, 0xaf820024, 0xe00096d, 0xafa0001c,
-0x96030002, 0x3c040800, 0x8c8400e8, 0x8f820034,
-0x30633fff, 0x31980, 0x441021, 0x431021,
-0x3043007f, 0x3c05000c, 0x531024, 0x3431821,
-0xaf420028, 0x651821, 0x9062000d, 0x122140,
-0x3042007f, 0xa062000d, 0x3c030800, 0x8c6300e4,
-0x8f820034, 0x431021, 0x443821, 0x30e2007f,
-0x3421021, 0x451021, 0xf31824, 0xaf430028,
-0xaea20000, 0x9222000d, 0x30420010, 0x10400013,
-0x2a02021, 0x8f830028, 0x8ea40000, 0x2803021,
-0x9462003e, 0x2442ffff, 0xa462003e, 0x94840002,
-0x9625000e, 0x3084ffff, 0xe000a52, 0x30a5ffff,
-0x8f820028, 0x94430034, 0x9622000e, 0x14430003,
-0x2a02021, 0x24020001, 0xa382002c, 0x2c02821,
-0xe0008e2, 0x0, 0x8fbf0054, 0x8fb60050,
-0x8fb5004c, 0x8fb40048, 0x8fb30044, 0x8fb20040,
-0x8fb1003c, 0x8fb00038, 0x3e00008, 0x27bd0058,
-0x8f850028, 0x27bdffd0, 0xafb40028, 0xafb20020,
-0xafbf002c, 0xafb30024, 0xafb1001c, 0xafb00018,
-0x90a800d0, 0x90a600d1, 0x3c020800, 0x8c4200e4,
-0x8f830034, 0x30c700ff, 0xa3a60010, 0x621821,
-0x71140, 0x621821, 0x3062007f, 0x3422021,
-0x3c02000c, 0x822021, 0x2402ff80, 0x621824,
-0x311200ff, 0x8cb100d8, 0xafa40014, 0x8cb300dc,
-0xa021, 0xaf430028, 0x10f2001f, 0x24020001,
-0x8fa60014, 0x27a40014, 0x27a50010, 0x8cc20004,
-0x2228021, 0x2701023, 0x4400017, 0x24020001,
-0x90c3000d, 0x2402ff80, 0x431024, 0x304200ff,
-0x14400007, 0x2008821, 0x90c2000d, 0x34420040,
-0xe0008e2, 0xa0c2000d, 0xa000b9e, 0x93a20010,
-0xe000ac0, 0x24140001, 0x8f830028, 0xac7000d8,
-0x93a20010, 0xa06200d1, 0x93a20010, 0x1452ffe5,
-0x8fa60014, 0x24020001, 0x16820004, 0x8fbf002c,
-0xe00070a, 0x0, 0x8fbf002c, 0x8fb40028,
-0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0030, 0x27bdffd8, 0xafb3001c,
-0xafb20018, 0xafb10014, 0xafb00010, 0xafbf0020,
-0x809821, 0xe08021, 0x30b1ffff, 0xe000577,
-0x30d200ff, 0x0, 0x0, 0x0,
-0x8f820020, 0xac510000, 0xac520004, 0xac530008,
-0xac40000c, 0xac400010, 0xac400014, 0xac400018,
-0x3c030800, 0x94634ed6, 0x2038025, 0xac50001c,
-0x0, 0x0, 0x0, 0x24040001,
-0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0xa00059c, 0x27bd0028, 0x27bdffe8,
-0xafb00010, 0xafbf0014, 0x30a5ffff, 0x30c600ff,
-0x808021, 0x24020c80, 0xaf420024, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0xe000bad, 0x0, 0x3c040800, 0x248400e0,
-0x8c820000, 0x2403ff80, 0x8fbf0014, 0x2021021,
-0x431024, 0xaf420024, 0x8c820000, 0x3c03000a,
-0x2028021, 0x3210007f, 0x3501021, 0x8fb00010,
-0x431021, 0x27bd0018, 0x3e00008, 0xaf820028,
-0x27bdffe8, 0xafbf0010, 0x8f440140, 0x3c030800,
-0x8c6300e0, 0x2402ff80, 0xaf840034, 0x831821,
-0x621024, 0xaf420024, 0x3c020008, 0x3424021,
-0x95050002, 0x3063007f, 0x3c02000a, 0x3431821,
-0x621821, 0x30a5ffff, 0x3402ffff, 0x3021,
-0x3c076020, 0x10a20006, 0xaf830028, 0x2402ffff,
-0xa5020002, 0x946500d4, 0xe000bd2, 0x30a5ffff,
-0x8fbf0010, 0x24020c80, 0x27bd0018, 0x3e00008,
-0xaf420024, 0x3c020008, 0x3424021, 0x95020002,
-0x3c0a0800, 0x954a00c6, 0x3046ffff, 0x14c00007,
-0x3402ffff, 0x8f820028, 0x8f840034, 0x3c076020,
-0x944500d4, 0xa000c3b, 0x30a5ffff, 0x10c20024,
-0x8f870028, 0x94e20054, 0x94e40016, 0x3045ffff,
-0xa61023, 0xa6182b, 0x3089ffff, 0x10600004,
-0x3044ffff, 0xc51023, 0x1221023, 0x3044ffff,
-0x8a102b, 0x1040000c, 0x12a1023, 0x24020001,
-0xa5020016, 0x2402ffff, 0xa5020002, 0x94e500d4,
-0x8f840034, 0x3021, 0x30a5ffff, 0x3c076020,
-0xa000bd2, 0x0, 0x44102a, 0x10400008,
-0x0, 0x95020016, 0x30420001, 0x10400004,
-0x0, 0x9742007e, 0x24420014, 0xa5020016,
-0x3e00008, 0x0, 0x8f840028, 0x27bdffe0,
-0xafbf0018, 0x94820034, 0x9483003e, 0x1060001a,
-0x3048ffff, 0x9383002c, 0x24020001, 0x14620027,
-0x8fbf0018, 0x8f820028, 0x818c2, 0x31080007,
-0x621821, 0x2447003a, 0x24490054, 0x24440020,
-0x24450030, 0x24460034, 0x90620040, 0x304200ff,
-0x1021007, 0x30420001, 0x10400016, 0x8fbf0018,
-0xe00093a, 0xafa90010, 0x8f820028, 0x94420034,
-0xa000c54, 0x3048ffff, 0x94830036, 0x94820034,
-0x1043000e, 0x8fbf0018, 0x94820036, 0xa4820034,
-0x94820056, 0xa4820054, 0x8c82002c, 0xac820024,
-0x94820032, 0xa4820030, 0x9482003c, 0xa482003a,
-0x8fbf0018, 0xa000c14, 0x27bd0020, 0x3e00008,
-0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x8f4a0100,
-0x3c050800, 0x8ca500e0, 0x3c020800, 0x90424efc,
-0x3c0c0800, 0x958c4ef6, 0x1452821, 0x304b003f,
-0x30a2007f, 0x3424021, 0x39690032, 0x3c02000a,
-0x3963003f, 0x2c630001, 0x1024021, 0x2d290001,
-0x2402ff80, 0xa22824, 0x1234825, 0xaf8a0034,
-0x801821, 0xaf450024, 0x3021, 0x802821,
-0x24070001, 0xaf880028, 0x3c040800, 0x24844ef0,
-0xaf8c0024, 0x15200006, 0xa380002d, 0x24020020,
-0x1562000e, 0x3402ffff, 0x1582000c, 0x0,
-0x24020020, 0x15620005, 0x0, 0x8c630014,
-0x2402ffff, 0x10620007, 0x0, 0xe00096d,
-0x0, 0xa000cb0, 0x0, 0xe0009d8,
-0x602021, 0xe000c49, 0x0, 0x8fbf0010,
-0x24020c80, 0x27bd0018, 0x3e00008, 0xaf420024,
-0x3c020800, 0x8c4200e0, 0x27bdffa0, 0xafb1003c,
-0x821021, 0x2411ff80, 0xafbe0058, 0xafb70054,
-0xafb20040, 0xafb00038, 0xafbf005c, 0xafb60050,
-0xafb5004c, 0xafb40048, 0xafb30044, 0x511024,
-0x8f480024, 0x8f490028, 0x8f470028, 0xaf420024,
-0x3c020800, 0x8c4200e0, 0x809021, 0x24060006,
-0x821021, 0x3042007f, 0x3421821, 0x3c02000a,
-0x628021, 0x3c02001f, 0x3442ff80, 0xe23824,
-0x27a40010, 0x260500f0, 0x122f024, 0x102b824,
-0xe000601, 0xafa70030, 0x8fa20018, 0xae0200c4,
-0x8fa2001c, 0xae0200c8, 0x8fa20024, 0xae0200cc,
-0x93a40010, 0x920300d1, 0x2402ff80, 0x821024,
-0x431025, 0x304900ff, 0x3083007f, 0x3122007f,
-0x62102a, 0x10400004, 0x310c0, 0x1311026,
-0x304900ff, 0x310c0, 0x31940, 0x621821,
-0x3c020800, 0x8c4200dc, 0x920400d2, 0x2421021,
-0x431021, 0x511024, 0xaf420028, 0x93a30010,
-0x3063007f, 0x310c0, 0x31940, 0x621821,
-0x3c020800, 0x8c4200dc, 0x2421021, 0x431021,
-0x3042007f, 0x3421821, 0x3c02000c, 0x624021,
-0x8fa30014, 0x2402ffff, 0x10620030, 0x309500ff,
-0x93a20011, 0x95030014, 0x304400ff, 0x3063ffff,
-0x64182b, 0x1060000d, 0x0, 0x95040014,
-0x8d07001c, 0x8d060018, 0x3084ffff, 0x442023,
-0x42100, 0x1021, 0xe43821, 0xe4202b,
-0xc23021, 0xa000d2a, 0xc43021, 0x95040014,
-0x8d07001c, 0x8d060018, 0x3084ffff, 0x822023,
-0x42100, 0x1021, 0x801821, 0xc23023,
-0xe4202b, 0xc43023, 0xe33823, 0xad07001c,
-0xad060018, 0x93a20011, 0xa5020014, 0x97a20012,
-0xa5020016, 0x8fa20014, 0xad020010, 0x8fa20014,
-0xad02000c, 0x93a20011, 0xa5020020, 0x97a20012,
-0xa5020022, 0x8fa20014, 0xad020024, 0x2406ff80,
-0x2461024, 0x3256007f, 0xaf420024, 0x3561821,
-0x3c02000a, 0x628021, 0x8e02004c, 0x8fa20020,
-0x3124007f, 0x428c0, 0xae020050, 0x8fa20020,
-0x42140, 0x852821, 0xae020070, 0x93a20010,
-0x1208821, 0xa2020083, 0x93a20010, 0xa2020079,
-0x92020085, 0x3042003f, 0xa2020085, 0x3c020800,
-0x8c4200dc, 0x2421021, 0x451021, 0x461024,
-0xaf42002c, 0x3c020800, 0x8c4200e4, 0x3c030800,
-0x8c6300dc, 0x2421021, 0x441021, 0x461024,
-0xaf420028, 0x3c020800, 0x8c4200e4, 0x2431821,
-0x651821, 0x2421021, 0x441021, 0x3042007f,
-0x3063007f, 0x93a50010, 0x3422021, 0x3431821,
-0x3c02000e, 0x624021, 0x3c02000c, 0x10b1008c,
-0x824821, 0x3233007f, 0x16600019, 0x2404ff80,
-0x3c020800, 0x8c4200dc, 0x2421021, 0x441024,
-0xaf42002c, 0x3c020800, 0x8c4200e4, 0x3c030800,
-0x8c6300dc, 0x2421021, 0x441024, 0xaf420028,
-0x3c020800, 0x8c4200e4, 0x2431821, 0x3063007f,
-0x2421021, 0x3042007f, 0x3422021, 0x3431821,
-0x3c02000e, 0x624021, 0x3c02000c, 0x824821,
-0x9124000d, 0x2414ff80, 0x1021, 0x942025,
-0xa124000d, 0x95040002, 0x95050014, 0x8d07001c,
-0x3084ffff, 0x30a5ffff, 0x8d060018, 0x852023,
-0x42100, 0xe43821, 0xc23021, 0xe4202b,
-0xc43021, 0xad07001c, 0xad060018, 0x95020002,
-0xa5020014, 0xa5000016, 0x8d020008, 0xad020010,
-0x8d020008, 0xad02000c, 0x95020002, 0xa5020020,
-0xa5000022, 0x8d020008, 0xad020024, 0x9122000d,
-0x30420040, 0x10400042, 0x26220001, 0x3c020800,
-0x8c4200e0, 0xa3b30028, 0x3c10000a, 0x2421021,
-0x541024, 0xaf420024, 0x3c020800, 0x8c4200e0,
-0xa380002c, 0x27a4002c, 0x2421021, 0x3042007f,
-0x3421821, 0x701821, 0x8c6200d8, 0x8d260004,
-0x27a50028, 0xafa9002c, 0x461021, 0xac6200d8,
-0xe000ac0, 0xaf830028, 0x93a30028, 0x8f820028,
-0xe00070a, 0xa04300d1, 0xe000c49, 0x0,
-0x2541024, 0xaf420024, 0x3c020800, 0x8c4200dc,
-0x132940, 0x1320c0, 0xa42021, 0x2421021,
-0x441021, 0x541024, 0xaf42002c, 0x3c020800,
-0x8c4200e4, 0x3c030800, 0x8c6300dc, 0x3563021,
-0x2421021, 0x451021, 0x541024, 0xaf420028,
-0x3c020800, 0x8c4200e4, 0x2431821, 0x641821,
-0x2421021, 0x451021, 0x3042007f, 0x3063007f,
-0x3422021, 0x3431821, 0x3c02000e, 0x624021,
-0x3c02000c, 0xd08021, 0x824821, 0x26220001,
-0x3043007f, 0x14750005, 0x304400ff, 0x2403ff80,
-0x2231024, 0x431026, 0x304400ff, 0x93a20010,
-0x808821, 0x25080028, 0x1444ff76, 0x25290020,
-0x93a40010, 0x8fa30014, 0x2402ffff, 0x1062000a,
-0x308900ff, 0x24820001, 0x24830001, 0x3042007f,
-0x14550005, 0x306900ff, 0x2403ff80, 0x831024,
-0x431026, 0x304900ff, 0x92020078, 0x305300ff,
-0x11330032, 0x1208821, 0x3c020800, 0x8c4200dc,
-0x3225007f, 0x520c0, 0x52940, 0xa42021,
-0x2421021, 0x2406ff80, 0x441021, 0x461024,
-0xaf42002c, 0x3c030800, 0x8c6300dc, 0x3c020800,
-0x8c4200e4, 0x2431821, 0x2421021, 0x451021,
-0x641821, 0x461024, 0x3063007f, 0xaf420028,
-0x3431821, 0x3c02000e, 0x624021, 0x3c020800,
-0x8c4200e4, 0x8d06000c, 0x1002021, 0x2421021,
-0x451021, 0x3042007f, 0x3421821, 0x3c02000c,
-0x624821, 0x10c0000d, 0x1202821, 0xe00072e,
-0x0, 0x2402ff80, 0x2221824, 0x26240001,
-0x622826, 0x3082007f, 0x14550002, 0x308300ff,
-0x30a300ff, 0x1473ffd0, 0x608821, 0x8e030074,
-0x3c027fff, 0x3442ffff, 0x621824, 0xae030074,
-0xe00074f, 0x2402021, 0xaf570024, 0x8fa20030,
-0xaf5e0028, 0x8fbf005c, 0x8fbe0058, 0x8fb70054,
-0x8fb60050, 0x8fb5004c, 0x8fb40048, 0x8fb30044,
-0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x27bd0060,
-0x3e00008, 0xaf42002c, 0x27bdffd8, 0xafb1001c,
-0xafbf0020, 0xafb00018, 0x27510188, 0x92220003,
-0x2408ff80, 0x3c03000a, 0x3047007f, 0xa3a70010,
-0x8f460180, 0x3c020800, 0x8c4200e0, 0xaf860034,
-0xc22821, 0xa81024, 0xaf420024, 0x92240000,
-0x30a2007f, 0x3421021, 0x431021, 0xaf820028,
-0x3084007f, 0x24020002, 0x14820025, 0x71940,
-0x3c020800, 0x8c4200e4, 0xc21021, 0x432821,
-0x30a2007f, 0x3421821, 0xa81024, 0xaf420028,
-0x3c02000c, 0x621821, 0x9062000d, 0xafa30014,
-0x481025, 0xa062000d, 0x8fa30014, 0x9062000d,
-0x30420040, 0x5040006a, 0x8fbf0020, 0x8f860028,
-0xa380002c, 0x27a40014, 0x8cc200d8, 0x8c630004,
-0x27a50010, 0x431021, 0xe000ac0, 0xacc200d8,
-0x93a30010, 0x8f820028, 0xe00070a, 0xa04300d1,
-0xe000c49, 0x0, 0xa000eeb, 0x8fbf0020,
-0xe000713, 0xc02021, 0xe000721, 0x0,
-0x3c020008, 0x3428021, 0x92230001, 0x9202007b,
-0x1443004f, 0x8fbf0020, 0x92220000, 0x3044007f,
-0x24020004, 0x10820017, 0x28820005, 0x10400006,
-0x24020005, 0x24020003, 0x10820007, 0x8fb1001c,
-0xa000eec, 0x0, 0x10820012, 0x8fbf0020,
-0xa000eec, 0x8fb1001c, 0x92050083, 0x92060078,
-0x8e070074, 0x8f840034, 0x30a500ff, 0x73e02,
-0x30c600ff, 0xe000757, 0x30e7007f, 0xa000eeb,
-0x8fbf0020, 0xe000cb7, 0x8f840034, 0xa000eeb,
-0x8fbf0020, 0x24020c80, 0xaf420024, 0x9202003e,
-0x30420040, 0x10400020, 0x0, 0x9202003e,
-0x21600, 0x21603, 0x4410006, 0x0,
-0x8f840034, 0xe000684, 0x24050093, 0xa000eeb,
-0x8fbf0020, 0x9202003f, 0x24030018, 0x304200ff,
-0x1443000c, 0x8f840034, 0x24050039, 0xe00061c,
-0x3021, 0xe000348, 0x8f840034, 0x24020012,
-0xa202003f, 0xe000351, 0x8f840034, 0xa000eeb,
-0x8fbf0020, 0x24050036, 0xe00061c, 0x3021,
-0xa000eeb, 0x8fbf0020, 0xe000348, 0x8f840034,
-0x92020005, 0x34420020, 0xa2020005, 0xe000351,
-0x8f840034, 0xe0010a2, 0x8f840034, 0x8fbf0020,
-0x8fb1001c, 0x8fb00018, 0x24020c80, 0x27bd0028,
-0x3e00008, 0xaf420024, 0x27bdffe8, 0xafb00010,
-0xafbf0014, 0x27430100, 0x94620008, 0x21400,
-0x21403, 0x4410002, 0x8021, 0x24100001,
-0x94620008, 0x30420080, 0x1040001a, 0x2001021,
-0x94620008, 0x30422000, 0x10400016, 0x2001021,
-0x8c630018, 0x3c021c2d, 0x344219ed, 0x24060006,
-0x1062000f, 0x3c076021, 0x3c020800, 0x8c4200d4,
-0x10400007, 0x8f820028, 0x8f830028, 0x90620062,
-0x3042000f, 0x34420040, 0xa0620062, 0x8f820028,
-0x8f840034, 0x944500d4, 0xe000bd2, 0x30a5ffff,
-0x2001021, 0x8fbf0014, 0x8fb00010, 0x3e00008,
-0x27bd0018, 0x27bdffe0, 0xafb10014, 0xafb00010,
-0xa380002c, 0xafbf0018, 0x8f450100, 0x3c030800,
-0x8c6300e0, 0x2402ff80, 0xaf850034, 0xa31821,
-0x3064007f, 0x3442021, 0x621824, 0x3c02000a,
-0x822021, 0xaf430024, 0x27500100, 0x8e020014,
-0x8c8300dc, 0xaf840028, 0x431023, 0x18400004,
-0x8821, 0x8e020014, 0xe000b63, 0xac8200dc,
-0x9202000b, 0x24030002, 0x304200ff, 0x1443002f,
-0x0, 0x96020008, 0x304300ff, 0x24020082,
-0x14620005, 0x24020084, 0xe000a1e, 0x0,
-0xa000f77, 0x0, 0x14620009, 0x24020081,
-0x8f820028, 0x8f840034, 0x3c076021, 0x944500d4,
-0x92060005, 0x30a5ffff, 0xa000f66, 0x30c600ff,
-0x14620027, 0x0, 0x9202000a, 0x304300ff,
-0x30620020, 0x10400004, 0x30620040, 0x8f840034,
-0xa000f62, 0x24060040, 0x10400004, 0x31600,
-0x8f840034, 0xa000f62, 0x24060041, 0x21603,
-0x4410017, 0x8f840034, 0x24060042, 0x8f820028,
-0x3c076019, 0x944500d4, 0x30a5ffff, 0xe000bd2,
-0x0, 0xa000f77, 0x0, 0x9202000b,
-0x24030016, 0x304200ff, 0x10430006, 0x0,
-0x9202000b, 0x24030017, 0x304200ff, 0x14430004,
-0x0, 0xe000ef1, 0x0, 0x408821,
-0xe000c49, 0x0, 0x9202000a, 0x30420008,
-0x10400006, 0x24020c80, 0x8f850028, 0x3c040008,
-0xe0012d0, 0x3442021, 0x24020c80, 0xaf420024,
-0x8fbf0018, 0x2201021, 0x8fb00010, 0x8fb10014,
-0x3e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0x8f500024, 0x3c030800, 0x8c6300e0,
-0x8f450100, 0x2402ff80, 0xa31821, 0x3064007f,
-0x3442021, 0x621824, 0x3c02000a, 0x822021,
-0xaf850034, 0xaf430024, 0x90820062, 0xaf840028,
-0x3042000f, 0x34420050, 0xa0820062, 0x3c02001f,
-0x3442ff80, 0xe00070a, 0x2028024, 0xaf500024,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x3c020800, 0x8c420020, 0x1040001d, 0x27450100,
-0x90a30009, 0x3c020008, 0x3422021, 0x24020018,
-0x54620003, 0x3c020008, 0xa000fb8, 0x24020008,
-0x3422021, 0x24020016, 0x14620005, 0x24020017,
-0x24020012, 0xa082003f, 0xa000fc2, 0x94a70008,
-0x54620006, 0x94a70008, 0x93620005, 0x2403fffe,
-0x431024, 0xa3620005, 0x94a70008, 0x90a6001b,
-0x8ca40000, 0x94a50006, 0xa000bad, 0x73c00,
-0x3e00008, 0x0, 0x27440100, 0x94820008,
-0x304500ff, 0x38a30082, 0x38a20084, 0x2c630001,
-0x2c420001, 0x621825, 0x10600006, 0x24020083,
-0x9382002d, 0x1040000d, 0x0, 0xa000c7c,
-0x0, 0x14a20005, 0x24a2ff80, 0x8f430104,
-0x3c026020, 0x3e00008, 0xac430014, 0x304200ff,
-0x2c420002, 0x10400003, 0x24020022, 0xa000f1c,
-0x0, 0x14a20003, 0x0, 0xa000f89,
-0x0, 0xa000fa7, 0x0, 0x9363007e,
-0x9362007a, 0x14430009, 0x2021, 0x93620000,
-0x24030050, 0x304200ff, 0x14430004, 0x24040001,
-0x9362007e, 0x24420001, 0xa362007e, 0x3e00008,
-0x801021, 0x8f4201f8, 0x440fffe, 0x24020002,
-0xaf4401c0, 0xa34201c4, 0x3c021000, 0x3e00008,
-0xaf4201f8, 0x27bdffe8, 0xafbf0010, 0x9362003f,
-0x2403000a, 0x304200ff, 0x14430046, 0x0,
-0x8f630054, 0x8f62004c, 0x1062007f, 0x3603021,
-0x93620000, 0x24030050, 0x304200ff, 0x1443002f,
-0x0, 0x8f440140, 0x3c020800, 0x8c4200e0,
-0x2403ff80, 0x821021, 0x431024, 0xaf420024,
-0x3c020800, 0x8c4200e0, 0x8f650054, 0x3c03000a,
-0x822021, 0x3084007f, 0x3441021, 0x431021,
-0xac450108, 0x9762003c, 0x8f63004c, 0x3042ffff,
-0x21040, 0x621821, 0xaf63005c, 0x8f630054,
-0x8f64004c, 0x9762003c, 0x641823, 0x3042ffff,
-0x31843, 0x21040, 0x43102a, 0x10400006,
-0x0, 0x8f620054, 0x8f63004c, 0x431023,
-0xa001038, 0x21043, 0x9762003c, 0x3042ffff,
-0x21040, 0xacc20064, 0x24020001, 0xa0c0007c,
-0xa0c20084, 0x24020c80, 0xaf420024, 0xe000fea,
-0x8f440140, 0x10400049, 0x8fbf0010, 0x8f430140,
-0x8f4201f8, 0x440fffe, 0x24020002, 0xaf4301c0,
-0xa34201c4, 0x3c021000, 0xaf4201f8, 0xa00108a,
-0x8fbf0010, 0x9362003f, 0x24030010, 0x304200ff,
-0x14430004, 0x0, 0x8f440140, 0xa001076,
-0x2821, 0x9362003f, 0x24030016, 0x304200ff,
-0x14430004, 0x24020014, 0xa362003f, 0xa001084,
-0x0, 0x8f62004c, 0x8f630050, 0x431023,
-0x441002a, 0x8fbf0010, 0x93620081, 0x24420001,
-0xa3620081, 0x93620081, 0x3c030800, 0x8c6300c0,
-0x304200ff, 0x14430010, 0x0, 0x9362003f,
-0x24030004, 0x304200ff, 0x14430006, 0x0,
-0x8f440140, 0x8fbf0010, 0x24050093, 0xa000684,
-0x27bd0018, 0x8f440140, 0x24050093, 0x8fbf0010,
-0xa0006f3, 0x27bd0018, 0x8f440140, 0xe000348,
-0x0, 0x8f620054, 0x2442ffff, 0xaf620054,
-0x8f620050, 0x2442ffff, 0xaf620050, 0xe000351,
-0x8f440140, 0x8f440140, 0x8fbf0010, 0x24050004,
-0xa000356, 0x27bd0018, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x8f420188, 0x9363007e, 0x21402,
-0x304400ff, 0x306300ff, 0x1464000d, 0x0,
-0x93620080, 0x304200ff, 0x10440009, 0x0,
-0xa3640080, 0x93620000, 0x24030050, 0x304200ff,
-0x14430004, 0x0, 0xa0007bb, 0x8f440180,
-0xa3640080, 0x3e00008, 0x0, 0x27bdffe8,
-0xafb00010, 0xafbf0014, 0x93620005, 0x24030030,
-0x30420030, 0x14430089, 0x808021, 0x3c020800,
-0x8c420020, 0x10400080, 0x2002021, 0xe000577,
-0x0, 0x8f850020, 0xacb00000, 0x9362003e,
-0x9363003f, 0x304200ff, 0x21200, 0x306300ff,
-0x431025, 0xaca20004, 0x93620082, 0x21600,
-0x21603, 0x4410005, 0x0, 0x3c030800,
-0x8c630048, 0xa0010c8, 0x0, 0x9362003e,
-0x30420040, 0x14400003, 0x1821, 0x93620081,
-0x304300ff, 0x93620082, 0x31e00, 0x304200ff,
-0x21400, 0x621825, 0xaca30008, 0x8f620040,
-0xaca2000c, 0x8f620048, 0xaca20010, 0x8f62004c,
-0xaca20014, 0x8f620050, 0x8f63004c, 0x431023,
-0x4410003, 0x0, 0xa0010dc, 0x8f62004c,
-0x8f620050, 0xaca20018, 0x3c020800, 0x94424ed6,
-0x3c03c00b, 0x2021, 0x431025, 0xe00059c,
-0xaca2001c, 0x8f620054, 0x8f840020, 0xac820000,
-0x8f620058, 0xac820004, 0x8f62005c, 0xac820008,
-0x8f620060, 0x8f430074, 0x431021, 0xac82000c,
-0x8f620064, 0xac820010, 0x97630068, 0x9762006a,
-0x31c00, 0x3042ffff, 0x621825, 0xac830014,
-0x93620082, 0x24030080, 0x304200ff, 0x14430003,
-0x0, 0xa001110, 0xac800018, 0x8f63000c,
-0x24020001, 0x1062000e, 0x2402ffff, 0x9362003e,
-0x30420040, 0x1440000a, 0x2402ffff, 0x8f63000c,
-0x8f420074, 0x621823, 0x3c020800, 0x621024,
-0x14400002, 0x2821, 0x602821, 0x51043,
-0xac820018, 0x3c020800, 0x94424ed6, 0x3c03c00c,
-0x2021, 0x431025, 0x8f830020, 0xe00059c,
-0xac62001c, 0x8f620018, 0x8f830020, 0x3c050800,
-0x94a54ed6, 0x24040001, 0xac620000, 0xac600004,
-0x8f66006c, 0x3c02400d, 0xa22825, 0xac660008,
-0x8f6200dc, 0xac62000c, 0xac600010, 0x93620005,
-0x21600, 0xac620014, 0xac600018, 0xe00059c,
-0xac65001c, 0x2002021, 0x8fbf0014, 0x8fb00010,
-0xa3600005, 0xa000505, 0x27bd0018, 0x8fbf0014,
-0x8fb00010, 0x3e00008, 0x27bd0018, 0x9742007c,
-0x30c600ff, 0xa0860084, 0x3047ffff, 0x24020005,
-0x14c2000b, 0x24e34650, 0x90a20112, 0x2c420007,
-0x10400007, 0x24e30a00, 0x90a30112, 0x24020014,
-0x621004, 0xe21021, 0xa001148, 0x3047ffff,
-0x3067ffff, 0x3e00008, 0xa4870014, 0xac87004c,
-0x8ca20108, 0x804021, 0xa04821, 0xe21023,
-0x30c600ff, 0x18400003, 0x93aa0013, 0x24e2fffc,
-0xaca20108, 0x30c20001, 0x10400008, 0x0,
-0x8d020050, 0xe21023, 0x4410013, 0x24060005,
-0x8d020054, 0x10e20010, 0x0, 0x8d020054,
-0x14e2001a, 0x0, 0x3c020800, 0x8c4200d8,
-0x30420020, 0x1040000a, 0x24020001, 0x91030078,
-0x91020083, 0x14430006, 0x24020001, 0x1002021,
-0x1202821, 0x24060004, 0xa001136, 0x0,
-0xa1000084, 0x11400009, 0xa5020014, 0x8f430100,
-0x8f4201f8, 0x440fffe, 0x24020002, 0xaf4301c0,
-0xa34201c4, 0x3c021000, 0xaf4201f8, 0x3e00008,
-0x0, 0x27bdffe8, 0x8fa90028, 0xafbf0010,
-0x804021, 0xe91823, 0x18600073, 0x30c600ff,
-0xa080007c, 0xa0800081, 0x8ca20108, 0xe21023,
-0x440004d, 0x0, 0x8c820050, 0x9483003c,
-0x8c840064, 0x474823, 0x3063ffff, 0x1231821,
-0x83202b, 0x10800004, 0x0, 0x8d020064,
-0xa001199, 0xe21021, 0x9502003c, 0x3042ffff,
-0x1221021, 0xe21021, 0xad02005c, 0x9502003c,
-0x8d03005c, 0x3042ffff, 0x21040, 0xe21021,
-0x43102b, 0x10400003, 0x0, 0xa0011a8,
-0x8d02005c, 0x9502003c, 0x3042ffff, 0x21040,
-0xe21021, 0xad02005c, 0xa1000084, 0xad07004c,
-0x8ca20108, 0xe21023, 0x18400002, 0x24e2fffc,
-0xaca20108, 0x30c20001, 0x1040000a, 0x0,
-0x8d020050, 0xe21023, 0x4410004, 0x1002021,
-0x8d020054, 0x14e20003, 0x0, 0xa0011ca,
-0x24060005, 0x8d020054, 0x14e20047, 0x8fbf0010,
-0x3c020800, 0x8c4200d8, 0x30420020, 0x1040000a,
-0x24020001, 0x91030078, 0x91020083, 0x14430006,
-0x24020001, 0x1002021, 0x24060004, 0x8fbf0010,
-0xa001136, 0x27bd0018, 0xa1000084, 0xa5020014,
-0x8f430100, 0x8f4201f8, 0x440fffe, 0x24020002,
-0xa0011ef, 0x0, 0x8c82005c, 0x491023,
-0x43102b, 0x54400001, 0xac87005c, 0x9502003c,
-0x3042ffff, 0x62102b, 0x14400007, 0x24020002,
-0x9502003c, 0x8d03005c, 0x3042ffff, 0x621821,
-0xad03005c, 0x24020002, 0xad07004c, 0xa1020084,
-0xe000fea, 0x8f440100, 0x1040001b, 0x8fbf0010,
-0x8f430100, 0x8f4201f8, 0x440fffe, 0x24020002,
-0xaf4301c0, 0xa34201c4, 0x3c021000, 0xaf4201f8,
-0xa001205, 0x8fbf0010, 0x30c20010, 0x1040000e,
-0x8fbf0010, 0x8c83005c, 0x9482003c, 0x691823,
-0x3042ffff, 0x621821, 0x3c023fff, 0x3444ffff,
-0x83102b, 0x54400001, 0x801821, 0x1231021,
-0xad02005c, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe8, 0x8faa0028, 0xafbf0010, 0x804021,
-0xea4823, 0x19200021, 0x30c600ff, 0x8c83005c,
-0x8c820064, 0x6a1823, 0x43102b, 0x50400010,
-0x691821, 0x94a20110, 0x1221021, 0xa4a20110,
-0x94a20110, 0x3042ffff, 0x43102b, 0x1440000a,
-0x3c023fff, 0x94a20110, 0x431023, 0xa4a20110,
-0x9482003c, 0x3042ffff, 0xa001224, 0x621821,
-0xa4a00110, 0x3c023fff, 0x3444ffff, 0x83102b,
-0x54400001, 0x801821, 0x671021, 0xad02005c,
-0xa100007c, 0xa00126c, 0xa1000081, 0x30c20010,
-0x1040003c, 0x0, 0x8c820050, 0x4a1023,
-0x18400038, 0x0, 0x9082007c, 0x24420001,
-0xa082007c, 0x9082007c, 0x3c030800, 0x8c630024,
-0x304200ff, 0x43102b, 0x1440005c, 0x8fbf0010,
-0x8ca20108, 0xe21023, 0x18400058, 0x0,
-0x8c830054, 0x9482003c, 0x6a1823, 0x3042ffff,
-0x31843, 0x21040, 0x43102a, 0x10400005,
-0x0, 0x8c820054, 0x4a1023, 0xa001253,
-0x21043, 0x9482003c, 0x3042ffff, 0x21040,
-0xad020064, 0x9502003c, 0x8d040064, 0x9503003c,
-0x3042ffff, 0x21040, 0x822021, 0x3063ffff,
-0x831821, 0x1431021, 0xad02005c, 0x8d020054,
-0xaca20108, 0x24020002, 0xa1020084, 0xe000fea,
-0x8f440100, 0x10400035, 0x8fbf0010, 0x8f430100,
-0x8f4201f8, 0x440fffe, 0x24020002, 0xa001295,
-0x0, 0xad07004c, 0x8ca20108, 0xe21023,
-0x18400002, 0x24e2fffc, 0xaca20108, 0x30c20001,
-0x1040000a, 0x0, 0x8d020050, 0xe21023,
-0x4410004, 0x1002021, 0x8d020054, 0x14e20003,
-0x0, 0xa00128c, 0x24060005, 0x8d020054,
-0x14e2001a, 0x8fbf0010, 0x3c020800, 0x8c4200d8,
-0x30420020, 0x1040000a, 0x24020001, 0x91030078,
-0x91020083, 0x14430006, 0x24020001, 0x1002021,
-0x24060004, 0x8fbf0010, 0xa001136, 0x27bd0018,
-0xa1000084, 0xa5020014, 0x8f430100, 0x8f4201f8,
-0x440fffe, 0x24020002, 0xaf4301c0, 0xa34201c4,
-0x3c021000, 0xaf4201f8, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x8faa0010, 0x8c820050, 0x804021,
-0x30c600ff, 0x4a1023, 0xa04821, 0x18400007,
-0xe01821, 0x24020001, 0xa0800084, 0xa0a00112,
-0xa4820014, 0xa001207, 0xafaa0010, 0xa0800081,
-0xad07004c, 0x8ca20108, 0xe21023, 0x18400002,
-0x24e2fffc, 0xaca20108, 0x30c20001, 0x10400008,
-0x0, 0x8d020050, 0x621023, 0x4410013,
-0x24060005, 0x8d020054, 0x10620010, 0x0,
-0x8d020054, 0x14620011, 0x0, 0x3c020800,
-0x8c4200d8, 0x30420020, 0x1040000a, 0x24020001,
-0x91030078, 0x91020083, 0x14430006, 0x24020001,
-0x1002021, 0x1202821, 0x24060004, 0xa001136,
-0x0, 0xa1000084, 0xa5020014, 0x3e00008,
-0x0, 0x27bdffe0, 0xafbf0018, 0x27420100,
-0x9046000a, 0x8c480014, 0x8c8b004c, 0x90820084,
-0x30c900ff, 0x1681823, 0x304a00ff, 0x1c60001a,
-0x2d460006, 0x24020001, 0x1421004, 0x10c00016,
-0x30430003, 0x1203021, 0x1003821, 0x14600007,
-0x304c000c, 0x15800009, 0x30420030, 0x1440000b,
-0x8fbf0018, 0xa0012f6, 0x0, 0xe001207,
-0xafab0010, 0xa0012f6, 0x8fbf0018, 0xe00117c,
-0xafab0010, 0xa0012f6, 0x8fbf0018, 0xafab0010,
-0xe00129c, 0xafaa0014, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x24020003, 0xa0820084, 0x8c820054,
-0x3e00008, 0xaca20108, 0x3c020008, 0x3421821,
-0x90620081, 0x24060043, 0x3c076019, 0x24420001,
-0xa0620081, 0x90630081, 0x3c020800, 0x8c4200c0,
-0x306300ff, 0x14620010, 0x2403ff80, 0x3c020800,
-0x8c4200e0, 0x821021, 0x431024, 0xaf420024,
-0x3c020800, 0x8c4200e0, 0x3c03000a, 0x821021,
-0x3042007f, 0x3421021, 0x431021, 0x944500d4,
-0xa000bd2, 0x30a5ffff, 0x3e00008, 0x0,
-0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
-0x8f420180, 0x808021, 0xa08821, 0xe0012fd,
-0x402021, 0xa2000084, 0x8e020054, 0x8fbf0018,
-0x8fb00010, 0xae220108, 0x8fb10014, 0x3e00008,
-0x27bd0020, 0x27bdffe0, 0x3c020008, 0xafb00010,
-0xafbf0018, 0xafb10014, 0x3428021, 0x8f510140,
-0x92030084, 0x8e040050, 0x8e02004c, 0x14820040,
-0x306600ff, 0x3c020800, 0x8c4200e0, 0x2403ff80,
-0x2221021, 0x431024, 0xaf420024, 0x3c020800,
-0x8c4200e0, 0x9744007c, 0x92050081, 0x2221021,
-0x3042007f, 0x3421821, 0x3c02000a, 0x621821,
-0x14a0000b, 0x3084ffff, 0x24020005, 0x54c20014,
-0x248205dc, 0x90620112, 0x24420001, 0xa0620112,
-0x24020c80, 0xaf420024, 0xa001355, 0x24020005,
-0xa0600112, 0x24020005, 0x14c20009, 0x248205dc,
-0x92020081, 0x2c420007, 0x50400005, 0x24820a00,
-0x92030081, 0x24020014, 0x621004, 0x821021,
-0x3044ffff, 0xa6040014, 0xe0012fd, 0x2202021,
-0x9602003c, 0x8e03004c, 0x2202021, 0x3042ffff,
-0x21040, 0x621821, 0xe000348, 0xae03005c,
-0x9202007d, 0x2202021, 0x34420040, 0xe000351,
-0xa202007d, 0x8f4201f8, 0x440fffe, 0x24020002,
-0xaf5101c0, 0xa34201c4, 0x3c021000, 0xaf4201f8,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0020, 0x0 };
-u32 bce_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
-u32 bce_COM_b06FwRodata[(0x14/4) + 1] = {
-0x8000ec8,
-0x8000f10, 0x8000f50, 0x8000f9c, 0x8000fd0,
+/* Firmware release 6.0.15 for BCM5706 and BCM5708 (b06). */
+/* Firmware release 6.0.17 for BCM5709 and BCM5716 (b09). */
+
+int bce_COM_b06FwReleaseMajor = 0x6;
+int bce_COM_b06FwReleaseMinor = 0x0;
+int bce_COM_b06FwReleaseFix = 0xf;
+u32 bce_COM_b06FwStartAddr = 0x08000118;
+u32 bce_COM_b06FwTextAddr = 0x08000000;
+int bce_COM_b06FwTextLen = 0x4a68;
+u32 bce_COM_b06FwDataAddr = 0x00000000;
+int bce_COM_b06FwDataLen = 0x0;
+u32 bce_COM_b06FwRodataAddr = 0x08004a68;
+int bce_COM_b06FwRodataLen = 0x14;
+u32 bce_COM_b06FwBssAddr = 0x08004ad8;
+int bce_COM_b06FwBssLen = 0xc4;
+u32 bce_COM_b06FwSbssAddr = 0x08004aa0;
+int bce_COM_b06FwSbssLen = 0x38;
+u32 bce_COM_b06FwSDataAddr = 0x00000000;
+int bce_COM_b06FwSDataLen = 0x0;
+u32 bce_COM_b06FwText[(0x4a68/4) + 1] = {
+0xa000046, 0x0, 0x0,
+0xd, 0x636f6d36, 0x2e302e31, 0x35000000,
+0x6000f02, 0x0, 0x3, 0xc8,
+0x32, 0x3, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x10,
+0x136, 0xea60, 0x5, 0x0,
+0x0, 0x0, 0x8, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x2,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x10, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x10000003, 0x0, 0xd, 0xd,
+0x3c020800, 0x24424aa0, 0x3c030800, 0x24634b9c,
+0xac400000, 0x43202b, 0x1480fffd, 0x24420004,
+0x3c1d0800, 0x37bd7ffc, 0x3a0f021, 0x3c100800,
+0x26100118, 0x3c1c0800, 0x279c4aa0, 0xe000168,
+0x0, 0xd, 0x27470100, 0x90e3000b,
+0x2402001a, 0x94e50008, 0x14620028, 0x2021,
+0x8ce20000, 0x3c030800, 0x8c630044, 0x94e60014,
+0x211c2, 0x21040, 0x30a40002, 0x5a1021,
+0x24630001, 0x30a50004, 0xa4460080, 0x3c010800,
+0xac230044, 0x10a00019, 0x4202b, 0x8f4202b8,
+0x4410008, 0x24040001, 0x3c020800, 0x8c420060,
+0x24420001, 0x3c010800, 0xac220060, 0x3e00008,
+0x801021, 0x8ce20020, 0x94e30016, 0x2021,
+0xaf420280, 0x8ce20004, 0xa7430284, 0xaf420288,
+0x3c021000, 0xaf4202b8, 0x3c020800, 0x8c42005c,
+0x24420001, 0x3c010800, 0xac22005c, 0x3e00008,
+0x801021, 0x27470100, 0x90e3000b, 0x24020003,
+0x94e50008, 0x14620028, 0x2021, 0x8ce20000,
+0x3c030800, 0x8c630044, 0x94e60014, 0x211c2,
+0x21040, 0x30a40002, 0x5a1021, 0x24630001,
+0x30a50004, 0xa4460080, 0x3c010800, 0xac230044,
+0x10a00019, 0x4202b, 0x8f4202b8, 0x4410008,
+0x24040001, 0x3c020800, 0x8c420060, 0x24420001,
+0x3c010800, 0xac220060, 0x3e00008, 0x801021,
+0x8ce20020, 0x94e30016, 0x2021, 0xaf420280,
+0x8ce20004, 0xa7430284, 0xaf420288, 0x3c021000,
+0xaf4202b8, 0x3c020800, 0x8c42005c, 0x24420001,
+0x3c010800, 0xac22005c, 0x3e00008, 0x801021,
+0x8f430100, 0x24020100, 0x50620003, 0x311c2,
+0xd, 0x311c2, 0x21040, 0x5a1021,
+0xa4400080, 0x3e00008, 0x1021, 0x93620000,
+0x3e00008, 0xaf800000, 0x3e00008, 0x1021,
+0x3e00008, 0x1021, 0x24020100, 0x14820008,
+0x0, 0x3c020800, 0x8c4200fc, 0x24420001,
+0x3c010800, 0xac2200fc, 0xa0000dd, 0x30a20020,
+0x3c020800, 0x8c420084, 0x24420001, 0x3c010800,
+0xac220084, 0x30a20020, 0x10400008, 0x30a30010,
+0x3c020800, 0x8c420108, 0x24420001, 0x3c010800,
+0xac220108, 0x3e00008, 0x0, 0x10600008,
+0x0, 0x3c020800, 0x8c420104, 0x24420001,
+0x3c010800, 0xac220104, 0x3e00008, 0x0,
+0x3c020800, 0x8c420100, 0x24420001, 0x3c010800,
+0xac220100, 0x3e00008, 0x0, 0x27bdffe8,
+0xafbf0010, 0x27440100, 0x94830008, 0x30620004,
+0x1040001b, 0x30660002, 0x8f4202b8, 0x4410008,
+0x24050001, 0x3c020800, 0x8c420060, 0x24420001,
+0x3c010800, 0xac220060, 0xa000129, 0x8fbf0010,
+0x8c820020, 0x94830016, 0x2821, 0xaf420280,
+0x8c820004, 0xa7430284, 0xaf420288, 0x3c021000,
+0xaf4202b8, 0x3c020800, 0x8c42005c, 0x24420001,
+0x3c010800, 0xac22005c, 0xa000129, 0x8fbf0010,
+0x10c00006, 0x602821, 0x8f440100, 0xe0000cd,
+0x0, 0xa000128, 0x24050001, 0x8f820008,
+0x8f430104, 0x50430007, 0x2821, 0x8f440100,
+0xe0000cd, 0x0, 0x8f420104, 0xaf820008,
+0x2821, 0x8fbf0010, 0xa01021, 0x3e00008,
+0x27bd0018, 0x27bdffe8, 0xafbf0014, 0xafb00010,
+0x97420108, 0x30437000, 0x24022000, 0x1062000b,
+0x28622001, 0x1440002f, 0x1021, 0x24024000,
+0x10620025, 0x0, 0x24026000, 0x10620026,
+0x1021, 0xa000165, 0x8fbf0014, 0x27500100,
+0x92020009, 0x1040001a, 0x24030001, 0x3c020800,
+0x8c420020, 0x10400016, 0x1821, 0xe000493,
+0x0, 0x96030008, 0x3c060800, 0x94c64b5e,
+0x8e040018, 0x8f820020, 0x9605000c, 0x31c00,
+0x661825, 0xac440000, 0xac450004, 0x24040001,
+0xac400008, 0xac40000c, 0xac400010, 0xac400014,
+0xac400018, 0xe0004b8, 0xac43001c, 0x1821,
+0xa000164, 0x601021, 0xe000325, 0x0,
+0xa000164, 0x1021, 0xe000ee9, 0x0,
+0x1021, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x27bdffe0, 0xafb20018, 0x3c036010,
+0xafbf001c, 0xafb10014, 0xafb00010, 0x8c645000,
+0x2402ff7f, 0x3c1a8000, 0x822024, 0x3484380c,
+0x24020037, 0xac645000, 0x3c120800, 0x26524ad8,
+0xaf420008, 0x24020c80, 0xaf420024, 0x3c1b8008,
+0x3c060800, 0x24c60324, 0x2401021, 0x2404001d,
+0x2484ffff, 0xac460000, 0x481fffd, 0x24420004,
+0x3c020800, 0x244204b0, 0x3c010800, 0xac224ae0,
+0x3c020800, 0x24420230, 0x3c010800, 0xac224ae4,
+0x3c020800, 0x24420174, 0x3c030800, 0x2463032c,
+0x3c040800, 0x248403d8, 0x3c050800, 0x24a538f0,
+0x3c010800, 0xac224b40, 0x3c020800, 0x244202ec,
+0x3c010800, 0xac264b24, 0x3c010800, 0xac254b34,
+0x3c010800, 0xac234b3c, 0x3c010800, 0xac244b44,
+0x3c010800, 0xac224b48, 0x3c010800, 0xac234adc,
+0x3c010800, 0xac204ae8, 0x3c010800, 0xac204aec,
+0x3c010800, 0xac204af0, 0x3c010800, 0xac204af4,
+0x3c010800, 0xac204af8, 0x3c010800, 0xac204afc,
+0x3c010800, 0xac204b00, 0x3c010800, 0xac244b04,
+0x3c010800, 0xac204b08, 0x3c010800, 0xac204b0c,
+0x3c010800, 0xac204b10, 0x3c010800, 0xac204b14,
+0x3c010800, 0xac204b18, 0x3c010800, 0xac264b1c,
+0x3c010800, 0xac264b20, 0x3c010800, 0xac254b30,
+0x3c010800, 0xac234b38, 0xe000623, 0x0,
+0x3c028000, 0x34420070, 0x8c420000, 0xaf820014,
+0x3c030800, 0x8c630020, 0x8f820004, 0x10430004,
+0x3c028000, 0xe00045b, 0xaf830004, 0x3c028000,
+0x34460070, 0x3c030800, 0x8c6300a0, 0x3c020800,
+0x8c4200a4, 0x10430004, 0x8f840014, 0x3c010800,
+0xac2300a4, 0xa743009e, 0x8cca0000, 0x3c030800,
+0x8c6300bc, 0x3c020800, 0x8c4200b8, 0x1442023,
+0x641821, 0x4021, 0x64202b, 0x481021,
+0x441021, 0x3c010800, 0xac2300bc, 0x3c010800,
+0xac2200b8, 0x8f510000, 0x32220007, 0x1040ffdc,
+0xaf8a0014, 0x8cc60000, 0x3c050800, 0x8ca500bc,
+0x3c040800, 0x8c8400b8, 0xca3023, 0xa62821,
+0x1021, 0xa6302b, 0x822021, 0x862021,
+0x32270001, 0x3c010800, 0xac2500bc, 0x3c010800,
+0xac2400b8, 0x10e0001f, 0x32220002, 0x8f420100,
+0xaf420020, 0x8f420104, 0xaf4200a8, 0x9342010b,
+0xe0000c6, 0x305000ff, 0x2e02001e, 0x54400004,
+0x101080, 0xe0000c9, 0xa000213, 0x0,
+0x521021, 0x8c420000, 0x40f809, 0x0,
+0x10400005, 0x3c024000, 0x8f430104, 0x3c026020,
+0xac430014, 0x3c024000, 0xaf420138, 0x3c020800,
+0x8c420034, 0x24420001, 0x3c010800, 0xac220034,
+0x32220002, 0x1040000e, 0x32220004, 0x8f420140,
+0xe0000c6, 0xaf420020, 0xe000295, 0x0,
+0x3c024000, 0xaf420178, 0x3c020800, 0x8c420038,
+0x24420001, 0x3c010800, 0xac220038, 0x32220004,
+0x1040ff98, 0x3c028000, 0x8f420180, 0xe0000c6,
+0xaf420020, 0x8f430180, 0x24020f00, 0x14620005,
+0x0, 0x8f420188, 0xa742009c, 0xa000248,
+0x3c024000, 0x93620000, 0x24030050, 0x304200ff,
+0x14430008, 0x3c024000, 0xe00027b, 0x0,
+0x54400004, 0x3c024000, 0xe000d75, 0x0,
+0x3c024000, 0xaf4201b8, 0x3c020800, 0x8c42003c,
+0x24420001, 0x3c010800, 0xac22003c, 0xa0001c8,
+0x3c028000, 0x3c029000, 0x34420001, 0x822025,
+0xaf440020, 0x8f420020, 0x440fffe, 0x0,
+0x3e00008, 0x0, 0x3c028000, 0x34420001,
+0x822025, 0x3e00008, 0xaf440020, 0x27bdffe0,
+0xafb10014, 0xafb00010, 0x808821, 0xafbf0018,
+0xe000250, 0x30b000ff, 0x9362007d, 0x2202021,
+0x2028025, 0xa370007d, 0x8f700074, 0x3c028000,
+0xe000259, 0x2028024, 0x16000009, 0x8fbf0018,
+0x8f4201f8, 0x440fffe, 0x24020002, 0xaf5101c0,
+0xa34201c4, 0x3c021000, 0xaf4201f8, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
+0x27bdffe8, 0xafbf0010, 0x97420184, 0x8f440188,
+0x30420200, 0x10400005, 0x2821, 0xe000faa,
+0x0, 0xa00028d, 0x24050001, 0x3c02ff00,
+0x4800005, 0x821824, 0x3c020400, 0x50620001,
+0x9362003e, 0x24050001, 0x8fbf0010, 0xa01021,
+0x3e00008, 0x27bd0018, 0xa3600022, 0x8f440140,
+0xa00025e, 0x24050001, 0x27bdffe8, 0xafbf0014,
+0xafb00010, 0x93620000, 0x304400ff, 0x38830020,
+0x38820030, 0x3182b, 0x2102b, 0x621824,
+0x10600003, 0x24020050, 0x14820080, 0x8fbf0014,
+0x93620005, 0x30420001, 0x1040007c, 0x8fbf0014,
+0x93420148, 0x2443ffff, 0x2c620005, 0x10400078,
+0x8fb00010, 0x31080, 0x3c030800, 0x24634a68,
+0x431021, 0x8c420000, 0x400008, 0x0,
+0xe000250, 0x8f440140, 0x8f70000c, 0x8f420144,
+0x16020002, 0x24020001, 0xaf62000c, 0xe000259,
+0x8f440140, 0x8f420144, 0x14500004, 0x8fbf0014,
+0x8fb00010, 0xa000f20, 0x27bd0018, 0x8f62000c,
+0xa000304, 0x0, 0x97620010, 0x8f430144,
+0x3042ffff, 0x1462001a, 0x0, 0x24020001,
+0xa7620010, 0x8f420238, 0x4430010, 0x8f420140,
+0x3c02003f, 0x3446f000, 0x3c056000, 0x3c04ffc0,
+0x8ca22bbc, 0x441824, 0x461024, 0x21302,
+0x31d82, 0x10620039, 0x0, 0x8f420238,
+0x440fff7, 0x0, 0x8f420140, 0xaf420200,
+0x3c021000, 0xaf420238, 0xa000322, 0x8fbf0014,
+0x97620010, 0xa000304, 0x0, 0xe000250,
+0x8f440140, 0x97620012, 0x8f430144, 0x3050ffff,
+0x16030002, 0x24020001, 0xa7620012, 0xe000259,
+0x8f440140, 0x8f420144, 0x16020004, 0x8fbf0014,
+0x8fb00010, 0xa000291, 0x27bd0018, 0x97620012,
+0xa000304, 0x0, 0x97620014, 0x8f430144,
+0x3042ffff, 0x14620006, 0x24020001, 0x8fbf0014,
+0x8fb00010, 0xa7620014, 0xa00124a, 0x27bd0018,
+0x97620014, 0x1440001d, 0x8fbf0014, 0xa00031c,
+0x0, 0x97620016, 0x8f430144, 0x3042ffff,
+0x1462000b, 0x24020001, 0x8fbf0014, 0x8fb00010,
+0xa7620016, 0xa000b12, 0x27bd0018, 0x97420078,
+0x24420004, 0xa7620010, 0xa000322, 0x8fbf0014,
+0x97620016, 0x24030001, 0x3042ffff, 0x14430007,
+0x8fbf0014, 0x3c020800, 0x8c420070, 0x24420001,
+0x3c010800, 0xac220070, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0014,
+0xafb00010, 0x8f500100, 0x93620000, 0x93430109,
+0x304400ff, 0x2402001f, 0x106200a5, 0x28620020,
+0x10400018, 0x24020038, 0x2862000a, 0x1040000c,
+0x2402000b, 0x28620008, 0x1040002c, 0x0,
+0x46000e5, 0x28620002, 0x14400028, 0x24020006,
+0x10620026, 0x8fbf0014, 0xa00041f, 0x8fb00010,
+0x1062005e, 0x2862000b, 0x144000dc, 0x8fbf0014,
+0x2402000e, 0x10620073, 0x8fb00010, 0xa00041f,
+0x0, 0x106200c0, 0x28620039, 0x1040000a,
+0x24020080, 0x24020036, 0x106200ca, 0x28620037,
+0x104000b4, 0x24020035, 0x106200c1, 0x8fbf0014,
+0xa00041f, 0x8fb00010, 0x1062002b, 0x28620081,
+0x10400006, 0x240200c8, 0x24020039, 0x106200b4,
+0x8fbf0014, 0xa00041f, 0x8fb00010, 0x10620099,
+0x8fbf0014, 0xa00041f, 0x8fb00010, 0x3c020800,
+0x8c420020, 0x104000b9, 0x8fbf0014, 0xe000493,
+0x0, 0x8f420100, 0x8f830020, 0x9745010c,
+0x97460108, 0xac620000, 0x8f420104, 0x3c040800,
+0x94844b5e, 0x52c00, 0xac620004, 0x8f420118,
+0x63400, 0xc43025, 0xac620008, 0x8f42011c,
+0x24040001, 0xac62000c, 0x9342010a, 0xa22825,
+0xac650010, 0xac600014, 0xac600018, 0xac66001c,
+0xa0003f5, 0x8fbf0014, 0x3c020800, 0x8c420020,
+0x1040009a, 0x8fbf0014, 0xe000493, 0x0,
+0x97440108, 0x3c030800, 0x94634b5e, 0x9745010c,
+0x42202, 0x9746010e, 0x8f820020, 0x42600,
+0x832025, 0x52c00, 0x3c030080, 0xa62825,
+0x832025, 0xac400000, 0xac400004, 0xac400008,
+0xac40000c, 0xac450010, 0xac400014, 0xac400018,
+0xac44001c, 0xa0003f4, 0x24040001, 0x9742010c,
+0x14400015, 0x0, 0x93620005, 0x30420010,
+0x14400011, 0x0, 0xe000250, 0x2002021,
+0x93620005, 0x2002021, 0x34420010, 0xe000259,
+0xa3620005, 0x93620000, 0x24030020, 0x304200ff,
+0x1043006d, 0x2002021, 0x8fbf0014, 0x8fb00010,
+0xa000fc0, 0x27bd0018, 0xd, 0xa00041e,
+0x8fbf0014, 0x3c020800, 0x8c420020, 0x10400063,
+0x8fbf0014, 0xe000493, 0x0, 0x8f420104,
+0x8f830020, 0x9744010c, 0x3c050800, 0x94a54b5e,
+0xac620000, 0x9762002c, 0x42400, 0x3042ffff,
+0x822025, 0x3c02400e, 0xa22825, 0xac640004,
+0xac600008, 0xac60000c, 0xac600010, 0xac600014,
+0xac600018, 0xac65001c, 0xa0003f4, 0x24040001,
+0xe000250, 0x2002021, 0xa7600008, 0xe000259,
+0x2002021, 0x2002021, 0xe00025e, 0x24050001,
+0x3c020800, 0x8c420020, 0x10400040, 0x8fbf0014,
+0xe000493, 0x0, 0x9742010c, 0x8f830020,
+0x3c050800, 0x94a54b5e, 0x21400, 0xac700000,
+0xac620004, 0xac600008, 0x8f64004c, 0x3c02401f,
+0xa22825, 0xac64000c, 0x8f620050, 0x24040001,
+0xac620010, 0x8f620054, 0xac620014, 0xac600018,
+0xac65001c, 0x8fbf0014, 0x8fb00010, 0xa0004b8,
+0x27bd0018, 0x24020020, 0x50820025, 0x8fb00010,
+0xe000f0a, 0x2002021, 0x10400020, 0x8fbf0014,
+0x2002021, 0x8fb00010, 0x2821, 0xa00025e,
+0x27bd0018, 0x2002021, 0x8fbf0014, 0x8fb00010,
+0xa000580, 0x27bd0018, 0x9745010c, 0x2002021,
+0x8fbf0014, 0x8fb00010, 0xa0005a0, 0x27bd0018,
+0x2002021, 0x8fb00010, 0xa0005c5, 0x27bd0018,
+0x9345010d, 0x2002021, 0x8fb00010, 0xa00060f,
+0x27bd0018, 0x2002021, 0x8fbf0014, 0x8fb00010,
+0xa0005eb, 0x27bd0018, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x8f420278, 0x440fffe,
+0x24020002, 0x34840080, 0xaf440240, 0xa3420244,
+0x3c021000, 0x3e00008, 0xaf420278, 0x3c040800,
+0x94844b6a, 0x3c020800, 0x8c424b74, 0x3083ffff,
+0x318c0, 0x431021, 0xaf42003c, 0x3c020800,
+0x8c424b70, 0xaf420038, 0x3c020050, 0x34420008,
+0xaf420030, 0x0, 0x0, 0x0,
+0x8f420000, 0x30420020, 0x1040fffd, 0x0,
+0x8f420400, 0x3c010800, 0xac224b60, 0x8f420404,
+0x3c010800, 0xac224b64, 0x3c020020, 0xaf420030,
+0x0, 0x3c020800, 0x94424b68, 0x3c030800,
+0x94634b6c, 0x3c050800, 0x94a54b6e, 0x24840001,
+0x431021, 0x3083ffff, 0x3c010800, 0xa4224b68,
+0x3c010800, 0xa4244b6a, 0x14650003, 0x0,
+0x3c010800, 0xa4204b6a, 0x3e00008, 0x0,
+0x3c05000a, 0x27bdffe8, 0x3452821, 0x3c040800,
+0x24844b50, 0xafbf0010, 0xe00051d, 0x2406000a,
+0x3c020800, 0x94424b52, 0x3c030800, 0x94634b6e,
+0x3042000f, 0x24420003, 0x431804, 0x24027fff,
+0x43102b, 0x10400002, 0xaf83001c, 0xd,
+0xe00042a, 0x0, 0x3c020800, 0x94424b5a,
+0x8fbf0010, 0x27bd0018, 0x3e00008, 0xa74200a2,
+0x3c02000a, 0x3421021, 0x94430006, 0x3c020800,
+0x94424b5a, 0x3c010800, 0xa4234b56, 0x431023,
+0x8f83001c, 0x21400, 0x21403, 0x43102b,
+0x3e00008, 0x38420001, 0x27bdffe8, 0xafbf0010,
+0x3c02000a, 0x3421021, 0x94420006, 0x3c010800,
+0xa4224b56, 0xe000477, 0x0, 0x5440fff9,
+0x3c02000a, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x27bdffe8, 0xafbf0010, 0xe000477, 0x0,
+0x10400003, 0x0, 0xe000485, 0x0,
+0x3c020800, 0x8c424b60, 0x8fbf0010, 0x27430400,
+0xaf420038, 0x3c020800, 0x8c424b64, 0x27bd0018,
+0xaf830020, 0xaf42003c, 0x3c020005, 0xaf420030,
+0x3e00008, 0xaf800018, 0x8f820018, 0x3c030006,
+0x21140, 0x431025, 0xaf420030, 0x0,
+0x0, 0x0, 0x8f420000, 0x30420010,
+0x1040fffd, 0x27420400, 0xaf820020, 0x3e00008,
+0xaf800018, 0x3c060800, 0x8cc64b64, 0x8f850018,
+0x8f830020, 0x3c020800, 0x94424b5a, 0x27bdffe0,
+0x24a50001, 0x24630020, 0x24420001, 0x24c70020,
+0xafb10014, 0xafb00010, 0xafbf0018, 0xaf850018,
+0xaf830020, 0x3c010800, 0xa4224b5a, 0x309000ff,
+0x3c010800, 0xac274b64, 0x4c10008, 0x8821,
+0x4e00006, 0x0, 0x3c020800, 0x8c424b60,
+0x24420001, 0x3c010800, 0xac224b60, 0x3c020800,
+0x94424b5a, 0x3c030800, 0x94634b68, 0x10202b,
+0x431026, 0x2c420001, 0x441025, 0x14400004,
+0x8f830018, 0x24020010, 0x1462000f, 0x0,
+0xe0004a9, 0x24110001, 0x3c030800, 0x94634b5a,
+0x3c020800, 0x94424b68, 0x14620003, 0x0,
+0xe00042a, 0x0, 0x16000003, 0x0,
+0xe000493, 0x0, 0x3c030800, 0x94634b5e,
+0x3c020800, 0x94424b5c, 0x24630001, 0x3064ffff,
+0x3c010800, 0xa4234b5e, 0x14820003, 0x0,
+0x3c010800, 0xa4204b5e, 0x12000006, 0x0,
+0x3c020800, 0x94424b5a, 0xa74200a2, 0xa00050b,
+0x2201021, 0xe000477, 0x0, 0x10400004,
+0x2201021, 0xe000485, 0x0, 0x2201021,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x3084ffff, 0x30a5ffff, 0x1821,
+0x10800007, 0x0, 0x30820001, 0x10400002,
+0x42042, 0x651821, 0xa000513, 0x52840,
+0x3e00008, 0x601021, 0x10c00006, 0x24c6ffff,
+0x8ca20000, 0x24a50004, 0xac820000, 0xa00051d,
+0x24840004, 0x3e00008, 0x0, 0x10a00008,
+0x24a3ffff, 0xac860000, 0x0, 0x0,
+0x2402ffff, 0x2463ffff, 0x1462fffa, 0x24840004,
+0x3e00008, 0x0, 0x24020001, 0xaf62000c,
+0xa7620010, 0xa7620012, 0xa7620014, 0x3e00008,
+0xa7620016, 0x3082007f, 0x3421021, 0x3c08000e,
+0x481821, 0x3c020800, 0x8c420020, 0x27bdffd8,
+0x2407ff80, 0xafb3001c, 0xafb20018, 0xafb10014,
+0xafb00010, 0xafbf0020, 0x808021, 0x30b100ff,
+0x872024, 0x30d200ff, 0x1040002f, 0x9821,
+0xaf44002c, 0x90620000, 0x24030050, 0x304200ff,
+0x1443000e, 0x0, 0x3c020800, 0x8c4200e0,
+0x2021021, 0x471024, 0xaf42002c, 0x3c020800,
+0x8c4200e0, 0x2021021, 0x3042007f, 0x3421021,
+0x481021, 0x944200d4, 0x3053ffff, 0xe000493,
+0x0, 0x3c020800, 0x94424b5e, 0x8f830020,
+0x113400, 0xc23025, 0x122c00, 0x3c024000,
+0xc23025, 0x34a50001, 0xac700000, 0x8fbf0020,
+0xac600004, 0x8fb20018, 0xac730008, 0x8fb10014,
+0xac60000c, 0x8fb3001c, 0xac650010, 0x8fb00010,
+0xac600014, 0x24040001, 0xac600018, 0x27bd0028,
+0xa0004b8, 0xac66001c, 0x8fbf0020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0028, 0x9343010f, 0x24020010, 0x1062000e,
+0x28650011, 0x10a00007, 0x24020012, 0x24020008,
+0x2405003a, 0x10620006, 0x3021, 0x3e00008,
+0x0, 0x24050035, 0x1462fffc, 0x3021,
+0xa000538, 0x0, 0x8f420074, 0x24420fa0,
+0x3e00008, 0xaf62000c, 0x27bdffe8, 0xafbf0010,
+0xe00025e, 0x24050001, 0x8fbf0010, 0x24020001,
+0xa7620012, 0x27bd0018, 0x24020001, 0x3e00008,
+0xa3600022, 0x27bdffe0, 0xafb10014, 0xafb00010,
+0xafbf0018, 0x30b1ffff, 0xe000250, 0x808021,
+0x9362003f, 0x24030004, 0x304200ff, 0x1443000c,
+0x2002021, 0x12200008, 0x2402000a, 0xe000531,
+0x0, 0x93620005, 0x2403fffe, 0x431024,
+0xa3620005, 0x24020012, 0xa362003f, 0x2002021,
+0xe000259, 0xa3600081, 0x16200003, 0x2002021,
+0xe000595, 0x0, 0x2002021, 0x322600ff,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x24050038,
+0xa000538, 0x27bd0020, 0x27bdffe0, 0xafbf001c,
+0xafb20018, 0xafb10014, 0xafb00010, 0xe000250,
+0x808021, 0xe000531, 0x0, 0x9362003f,
+0x24120018, 0x305100ff, 0x12320003, 0x2002021,
+0x24020012, 0xa362003f, 0x93620005, 0x2403fffe,
+0x431024, 0xe000259, 0xa3620005, 0x2002021,
+0x24050020, 0x16320007, 0x3021, 0x8fbf001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa00025e,
+0x27bd0020, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x24050039, 0xa000538, 0x27bd0020,
+0x27bdffe8, 0xafb00010, 0xafbf0014, 0x9742010c,
+0x24050036, 0x808021, 0x14400010, 0x304600ff,
+0xe000250, 0x0, 0x24020012, 0xa362003f,
+0x93620005, 0x34420010, 0xe000531, 0xa3620005,
+0xe000259, 0x2002021, 0x2002021, 0xe00025e,
+0x24050020, 0xa000604, 0x0, 0xe000538,
+0x0, 0xe000250, 0x2002021, 0x93620023,
+0x2403ff9f, 0x2002021, 0x431024, 0x8fbf0014,
+0x8fb00010, 0xa3620023, 0xa000259, 0x27bd0018,
+0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
+0x30b100ff, 0xe000250, 0x808021, 0x24020012,
+0xe000531, 0xa362003f, 0xe000259, 0x2002021,
+0x2002021, 0x2203021, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x24050035, 0xa000538, 0x27bd0020,
+0xa380002c, 0x3e00008, 0xa380002d, 0x8f420278,
+0x440fffe, 0x8f820034, 0xaf420240, 0x24020002,
+0xa3420244, 0x3c021000, 0x3e00008, 0xaf420278,
+0x3c036000, 0x8c625400, 0x30420008, 0x1440fffd,
+0x0, 0x8c625408, 0xaf82000c, 0x24020052,
+0xac605408, 0xac645430, 0xac625434, 0x24020008,
+0x3e00008, 0xac625400, 0x3c026000, 0x8c425400,
+0x30420008, 0x10400005, 0x3c036000, 0x8c625400,
+0x30420008, 0x1440fffd, 0x0, 0x8f83000c,
+0x3c026000, 0x3e00008, 0xac435408, 0x90a30000,
+0x24020005, 0x804021, 0x3063003f, 0x4821,
+0x14620005, 0x5021, 0x90a2001c, 0x94a3001e,
+0x304900ff, 0x306affff, 0xad00000c, 0xad000010,
+0xad000024, 0x95020014, 0x8d05001c, 0x8d040018,
+0x3042ffff, 0x491023, 0x21100, 0x237c3,
+0x403821, 0x862023, 0xa2102b, 0x822023,
+0xa72823, 0xad05001c, 0xad040018, 0xa5090014,
+0xa5090020, 0xa50a0016, 0x3e00008, 0xa50a0022,
+0x8f4201f8, 0x440fffe, 0x24020002, 0xaf4401c0,
+0xa34201c4, 0x3c021000, 0x3e00008, 0xaf4201f8,
+0x3c020800, 0x8c4200b4, 0x27bdffe8, 0xafbf0014,
+0x24420001, 0xafb00010, 0x3c010800, 0xac2200b4,
+0x8f430024, 0x3c02001f, 0x30aa00ff, 0x3442ff80,
+0x30d800ff, 0x628024, 0x80f821, 0x30ef00ff,
+0x1158003b, 0x1405821, 0x240cff80, 0x3c19000a,
+0x3163007f, 0x310c0, 0x31940, 0x621821,
+0x3c020800, 0x8c4200dc, 0x25680001, 0x310d007f,
+0x3e21021, 0x431021, 0x3043007f, 0x3431821,
+0x4c1024, 0x794821, 0xaf420024, 0x8d220024,
+0x16c1824, 0x6c7026, 0xad22000c, 0x8d220024,
+0x310800ff, 0xad220010, 0x95220014, 0x95230020,
+0x8d27001c, 0x3042ffff, 0x3063ffff, 0x8d260018,
+0x431023, 0x21100, 0x227c3, 0x402821,
+0xc43023, 0xe2102b, 0xc23023, 0xe53823,
+0xad27001c, 0xad260018, 0x95220020, 0xa5220014,
+0x95220022, 0x154b000a, 0xa5220016, 0x8d230024,
+0x8d220008, 0x25460001, 0x31450080, 0x14620004,
+0x30c4007f, 0x108f0002, 0x38aa0080, 0xc05021,
+0x51af0001, 0x31c800ff, 0x1518ffc9, 0x1005821,
+0x8f840034, 0x3082007f, 0x3421821, 0x3c02000a,
+0x621821, 0x2402ff80, 0x822024, 0xaf440024,
+0xa06a0079, 0xa06a0083, 0x8c620050, 0x8f840034,
+0xac620070, 0x8c650074, 0x3c027fff, 0x3442ffff,
+0xa22824, 0xe00066b, 0xac650074, 0xaf500024,
+0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
+0x27bdffc0, 0xafbe0038, 0xafb70034, 0xafb5002c,
+0xafb20020, 0xafb1001c, 0xafb00018, 0xafbf003c,
+0xafb60030, 0xafb40028, 0xafb30024, 0x8f450024,
+0x8f460028, 0x8f43002c, 0x3c02001f, 0x3442ff80,
+0x621824, 0xc23024, 0x80a821, 0xafa30014,
+0xa2f024, 0xe00062f, 0xafa60010, 0x3c020800,
+0x8c4200e0, 0x2410ff80, 0x3608821, 0x2a21021,
+0x501024, 0xaf420024, 0x3c020800, 0x8c4200e0,
+0x2a21021, 0x3042007f, 0x3421821, 0x3c02000a,
+0x629021, 0x924200d2, 0x93630084, 0x305700ff,
+0x306300ff, 0x24020001, 0x10620034, 0x3602021,
+0x24020002, 0x14620036, 0x0, 0xe001216,
+0x2402821, 0x92230083, 0x92220083, 0x3063007f,
+0x3042007f, 0x210c0, 0x31940, 0x621821,
+0x3c020800, 0x8c4200dc, 0x2a21021, 0x433821,
+0xf01024, 0xaf420028, 0x92250078, 0x92240083,
+0x30e2007f, 0x3421821, 0x3c02000c, 0x14850007,
+0x628021, 0x2402ffff, 0xa24200f1, 0x2402ffff,
+0xa64200f2, 0xa000727, 0x2402ffff, 0x96020020,
+0xa24200f1, 0x96020022, 0xa64200f2, 0x8e020024,
+0xae4200f4, 0x92220083, 0xa24200f0, 0x8e4200c8,
+0xae4200fc, 0x8e4200c4, 0xae4200f8, 0x8e220050,
+0xae420100, 0x8e4200cc, 0xae420104, 0x92220085,
+0x3042003f, 0xa000782, 0x34420040, 0xe001239,
+0x2402821, 0x92220085, 0xa000782, 0x3042003f,
+0x93620085, 0x2403ffdf, 0x3042003f, 0xa3620085,
+0x93620085, 0x431024, 0xa3620085, 0x93630083,
+0x93620078, 0x307400ff, 0x304200ff, 0x10540036,
+0x240aff80, 0x3c0c000c, 0x3283007f, 0x310c0,
+0x31940, 0x621821, 0x3c020800, 0x8c4200dc,
+0x26880001, 0x3109007f, 0x2a21021, 0x433821,
+0x30e2007f, 0x3421821, 0xea1024, 0xaf420028,
+0x6c8021, 0x8e020024, 0x28a1824, 0x6a5826,
+0xae02000c, 0x8e020024, 0x310800ff, 0xae020010,
+0x96020014, 0x96030020, 0x8e07001c, 0x3042ffff,
+0x3063ffff, 0x8e060018, 0x431023, 0x21100,
+0x227c3, 0x402821, 0xc43023, 0xe2102b,
+0xc23023, 0xe53823, 0xae07001c, 0xae060018,
+0x96020020, 0xa6020014, 0x96020022, 0xa6020016,
+0x92220079, 0x304200ff, 0x10540007, 0x0,
+0x51370001, 0x316800ff, 0x92220078, 0x304200ff,
+0x1448ffcd, 0x100a021, 0x92220083, 0xa2220079,
+0x8e220050, 0xa0007e2, 0xae220070, 0xa2220085,
+0x8e22004c, 0x2405ff80, 0xae42010c, 0x92220085,
+0x34420020, 0xa2220085, 0x924200d1, 0x3c030800,
+0x8c6300dc, 0x305400ff, 0x3c020800, 0x8c4200e4,
+0x143140, 0x1420c0, 0x2a31821, 0xc42021,
+0x2a21021, 0x643821, 0x461021, 0x451824,
+0xe52824, 0xaf450028, 0xaf43002c, 0x3042007f,
+0x924400d0, 0x30e3007f, 0x3422821, 0x3431821,
+0x3c02000c, 0x628021, 0x3c02000e, 0x309600ff,
+0xa29821, 0x1296002a, 0x0, 0x8e02000c,
+0x2002021, 0x2602821, 0x10400025, 0x26100028,
+0xe00064a, 0x0, 0x9262000d, 0x26830001,
+0x307400ff, 0x3042007f, 0xa262000d, 0x2404ff80,
+0x1697fff0, 0x26730020, 0x3c020800, 0x8c4200dc,
+0xa021, 0x2a21021, 0x441024, 0xaf420028,
+0x3c020800, 0x8c4200e4, 0x3c030800, 0x8c6300dc,
+0x2a21021, 0x441024, 0xaf42002c, 0x3c020800,
+0x8c4200e4, 0x2a31821, 0x3063007f, 0x2a21021,
+0x3042007f, 0x3422021, 0x3431821, 0x3c02000c,
+0x628021, 0x3c02000e, 0xa0007a4, 0x829821,
+0x8e4200d8, 0xae220050, 0x8e4200d8, 0xae220070,
+0x92250083, 0x924600d1, 0x92230083, 0x924400d1,
+0x2402ff80, 0xa22824, 0x3063007f, 0x308400ff,
+0xa62825, 0x64182a, 0x10600002, 0x30a500ff,
+0x38a50080, 0xa2250083, 0xa2250079, 0xe00063d,
+0x0, 0x9222007e, 0x2a02021, 0xa222007a,
+0x8e230074, 0x3c027fff, 0x3442ffff, 0x621824,
+0xe00066b, 0xae230074, 0x8fa20010, 0xaf5e0024,
+0x8fbf003c, 0xaf420028, 0x8fbe0038, 0x8fa20014,
+0x8fb70034, 0x8fb60030, 0x8fb5002c, 0x8fb40028,
+0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
+0x27bd0040, 0x3e00008, 0xaf42002c, 0x90a20000,
+0x24420001, 0xa0a20000, 0x3c030800, 0x8c6300f4,
+0x304200ff, 0x1443000f, 0x803021, 0xa0a00000,
+0x3c020800, 0x8c4200e4, 0x8f840034, 0x822021,
+0x3082007f, 0x3421821, 0x3c02000c, 0x621821,
+0x2402ff80, 0x822024, 0xacc30000, 0x3e00008,
+0xaf440028, 0x8c820000, 0x24420020, 0x3e00008,
+0xac820000, 0x94c20000, 0x3c080800, 0x950800ca,
+0x30e7ffff, 0x804821, 0x1021021, 0xa4c20000,
+0x94c20000, 0x3042ffff, 0xe2102b, 0x54400001,
+0xa4c70000, 0x94a20000, 0x3c030800, 0x8c6300cc,
+0x24420001, 0xa4a20000, 0x94a20000, 0x3042ffff,
+0x54430007, 0x8f860028, 0x107102b, 0xa4a00000,
+0x54400001, 0x1003821, 0xa4c70000, 0x8f860028,
+0x8cc4001c, 0xaf44003c, 0x94a20000, 0x8f43003c,
+0x3042ffff, 0x210c0, 0x621821, 0xaf43003c,
+0x8f42003c, 0x822023, 0x18800004, 0x0,
+0x8cc20018, 0xa000843, 0x24420001, 0x8cc20018,
+0xaf420038, 0x3c020050, 0x34420010, 0xaf420030,
+0x0, 0x0, 0x0, 0x8f420000,
+0x30420020, 0x1040fffd, 0x0, 0x8f420404,
+0xad220004, 0x8f420400, 0xad220000, 0x3c020020,
+0xaf420030, 0x3e00008, 0x0, 0x27bdffe0,
+0xafb20018, 0xafb10014, 0xafb00010, 0xafbf001c,
+0x94c20000, 0xc08021, 0x3c120800, 0x965200c6,
+0x24420001, 0xa6020000, 0x96030000, 0x94e20000,
+0xe03021, 0x14430005, 0x8fb10030, 0xe000818,
+0x2403821, 0xa000875, 0x0, 0x8c830004,
+0x8c820004, 0x24420040, 0x4610007, 0xac820004,
+0x8c820004, 0x4400004, 0x0, 0x8c820000,
+0x24420001, 0xac820000, 0x96020000, 0x3042ffff,
+0x50520001, 0xa6000000, 0x96220000, 0x24420001,
+0xa6220000, 0x8f820028, 0x96230000, 0x94420016,
+0x14430004, 0x8fbf001c, 0x24020001, 0xa6220000,
+0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0020, 0x8f890028, 0x27bdffe0,
+0xafbf0018, 0x8d220028, 0x27480400, 0x30e700ff,
+0xaf420038, 0x8d22002c, 0xaf880030, 0xaf42003c,
+0x3c020005, 0xaf420030, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x8c82000c, 0x8c82000c, 0xad020000, 0x8c820010,
+0xad020004, 0x8c820018, 0xad020008, 0x8c82001c,
+0xad02000c, 0x8ca20014, 0xad020010, 0x8c820020,
+0xad020014, 0x90820005, 0x304200ff, 0x21200,
+0xad020018, 0x8ca20018, 0xad02001c, 0x8ca2000c,
+0xad020020, 0x8ca20010, 0xad020024, 0x8ca2001c,
+0xad020028, 0x8ca20020, 0xad02002c, 0xad060030,
+0xad000034, 0x97830026, 0x3402ffff, 0x14620002,
+0x602021, 0x3404ffff, 0x10e00011, 0xad040038,
+0x95230036, 0x95240036, 0x24020001, 0x3063ffff,
+0x318c2, 0x691821, 0x90650040, 0x30840007,
+0x821004, 0x451025, 0xa0620040, 0x8f820028,
+0x94420056, 0x3042ffff, 0xa0008dc, 0xad02003c,
+0x95230036, 0x95240036, 0x24020001, 0x3063ffff,
+0x318c2, 0x691821, 0x90650040, 0x30840007,
+0x821004, 0x21027, 0x451024, 0xa0620040,
+0xad00003c, 0x0, 0x0, 0x0,
+0x3c020006, 0x34420040, 0xaf420030, 0x0,
+0x0, 0x0, 0x8f420000, 0x30420010,
+0x1040fffd, 0x8f860028, 0xaf880030, 0x24c20056,
+0x24c7003c, 0x24c40028, 0x24c50032, 0x24c60036,
+0xe000856, 0xafa20010, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x8f830024, 0x3c060800, 0x8cc600e8,
+0x8f820034, 0x30633fff, 0x31980, 0x461021,
+0x431021, 0x2403ff80, 0x3046007f, 0x431024,
+0xaf420028, 0x3461821, 0x3c02000c, 0x623021,
+0x90c2000d, 0x30a500ff, 0x3821, 0x34420010,
+0xa0c2000d, 0x8f890028, 0x8f8a0024, 0x95230036,
+0xa1382, 0x30480003, 0x24020001, 0xa4c3000e,
+0x1102000b, 0x29020002, 0x10400005, 0x24020002,
+0x1100000c, 0x24030001, 0xa000920, 0x1821,
+0x11020006, 0x0, 0xa000920, 0x1821,
+0x8cc2002c, 0xa000920, 0x24430001, 0x8cc20014,
+0x24430001, 0x8cc20018, 0x43102b, 0x50400009,
+0x24070001, 0x24020027, 0x14a20003, 0x0,
+0xa00092c, 0x24070001, 0x9522003e, 0x24420001,
+0xa522003e, 0xa1382, 0x30430003, 0x2c620002,
+0x10400009, 0x802821, 0x14600004, 0x0,
+0x94c20036, 0xa00093c, 0x3046ffff, 0x8cc60038,
+0xa00093c, 0x802821, 0x3021, 0x3c040800,
+0x24844b78, 0xa000889, 0x0, 0x27490100,
+0x8d22000c, 0x95230006, 0x1202021, 0x21602,
+0x3046003f, 0x3063ffff, 0x24020027, 0xc02821,
+0x28c70028, 0x10c2000e, 0xaf830024, 0x10e00008,
+0x24020031, 0x24020021, 0x10c20009, 0x24020025,
+0x10c20007, 0x9382002d, 0xa00095b, 0x0,
+0x10c20005, 0x9382002d, 0xa00095b, 0x0,
+0xa0008f4, 0x0, 0xa000626, 0x0,
+0x95230006, 0x91240005, 0x8d25000c, 0x8d260010,
+0x8d270018, 0x8d28001c, 0x8d290020, 0x24420001,
+0x3c010800, 0xa4234b7e, 0x3c010800, 0xa0244b7d,
+0x3c010800, 0xac254b84, 0x3c010800, 0xac264b88,
+0x3c010800, 0xac274b90, 0x3c010800, 0xac284b94,
+0x3c010800, 0xac294b98, 0x3e00008, 0xa382002d,
+0x8f870028, 0x27bdffc0, 0xafb30034, 0xafb20030,
+0xafb1002c, 0xafb00028, 0xafbf0038, 0x3c020800,
+0x8c4200d0, 0x94e30030, 0x30b0ffff, 0x501007,
+0x3045ffff, 0x3063ffff, 0xc09821, 0xa7a20010,
+0x3c110800, 0x963100c6, 0x14a30006, 0x3092ffff,
+0x8ce20024, 0x24420030, 0xaf42003c, 0xa000994,
+0x8ce20020, 0x94e20032, 0x3042ffff, 0x54a20008,
+0x27a40018, 0x8ce2002c, 0x24420030, 0xaf42003c,
+0x8ce20028, 0xaf420038, 0xa0009a2, 0x8f840028,
+0x27a50010, 0x27a60020, 0x2203821, 0xe000818,
+0xa7a00020, 0x8fa20018, 0x24420030, 0xaf420038,
+0x8fa2001c, 0xaf42003c, 0x8f840028, 0x3c020005,
+0xaf420030, 0x94820034, 0x27430400, 0x3042ffff,
+0x202102b, 0x14400007, 0xaf830030, 0x94820054,
+0x94830034, 0x2021021, 0x431023, 0xa0009b6,
+0x3043ffff, 0x94830054, 0x94820034, 0x2231821,
+0x501023, 0x621823, 0x3063ffff, 0x94820016,
+0x3042ffff, 0x14430003, 0x0, 0xa0009c4,
+0x24030001, 0x94820016, 0x3042ffff, 0x43102b,
+0x10400005, 0x8f820030, 0x94820016, 0x621023,
+0x3043ffff, 0x8f820030, 0xac530000, 0xac400004,
+0xac520008, 0xac43000c, 0x3c020006, 0x34420010,
+0xaf420030, 0x0, 0x0, 0x0,
+0x8f420000, 0x30420010, 0x1040fffd, 0x1018c2,
+0x641821, 0x90650040, 0x32040007, 0x24020001,
+0x8fbf0038, 0x8fb30034, 0x8fb20030, 0x8fb1002c,
+0x8fb00028, 0x821004, 0x451025, 0x27bd0040,
+0x3e00008, 0xa0620040, 0x27bdffa8, 0xafb60050,
+0xafb5004c, 0xafb40048, 0xafb30044, 0xafb1003c,
+0xafbf0054, 0xafb20040, 0xafb00038, 0x8c900000,
+0x3c020800, 0x8c4200e8, 0x8f860034, 0x96030002,
+0x2413ff80, 0xc23021, 0x30633fff, 0x31980,
+0xc33821, 0xf31024, 0x90b20000, 0xaf42002c,
+0x92030002, 0x30e2007f, 0x3423021, 0x3c02000e,
+0xc28821, 0x306300c0, 0x24020040, 0x80a821,
+0xa0b021, 0x14620026, 0xa021, 0x8e340038,
+0x8e220018, 0x14400002, 0x24020001, 0xae220018,
+0x9202000d, 0x30420020, 0x14400015, 0x8f820034,
+0x3c030800, 0x8c6300dc, 0x1238c0, 0x123140,
+0x431021, 0xc73021, 0x463821, 0x30e30007,
+0x3c020080, 0x30e60078, 0xc23025, 0x3431821,
+0xf31024, 0xaf420800, 0x24630900, 0xaf460810,
+0x8e220018, 0x8c630008, 0x431021, 0xae220018,
+0x8e22002c, 0x8e230018, 0x24420001, 0x62182b,
+0x1060003d, 0x0, 0xa000a78, 0x0,
+0x92030002, 0x2402ffc0, 0x431024, 0x304200ff,
+0x14400005, 0x24020001, 0xae220018, 0x96220036,
+0xa000a61, 0x3054ffff, 0x8e220014, 0x24420001,
+0xae220018, 0x92020000, 0x21600, 0x21603,
+0x4410029, 0x0, 0x96020002, 0x27a40010,
+0x802821, 0xa7a20016, 0x96020002, 0x24070001,
+0x3021, 0x3042ffff, 0xaf820024, 0xe000889,
+0xafa0001c, 0x96030002, 0x3c040800, 0x8c8400e8,
+0x8f820034, 0x30633fff, 0x31980, 0x441021,
+0x431021, 0x3043007f, 0x3c05000c, 0x531024,
+0x3431821, 0xaf420028, 0x651821, 0x9062000d,
+0x122140, 0x3042007f, 0xa062000d, 0x3c030800,
+0x8c6300e4, 0x8f820034, 0x431021, 0x443821,
+0x30e2007f, 0x3421021, 0x451021, 0xf31824,
+0xaf430028, 0xaea20000, 0x9222000d, 0x30420010,
+0x10400013, 0x2a02021, 0x8f830028, 0x8ea40000,
+0x2803021, 0x9462003e, 0x2442ffff, 0xa462003e,
+0x94840002, 0x9625000e, 0x3084ffff, 0xe000973,
+0x30a5ffff, 0x8f820028, 0x94430034, 0x9622000e,
+0x14430003, 0x2a02021, 0x24020001, 0xa382002c,
+0x2c02821, 0xe0007fe, 0x0, 0x8fbf0054,
+0x8fb60050, 0x8fb5004c, 0x8fb40048, 0x8fb30044,
+0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008,
+0x27bd0058, 0x8f820028, 0x27bdffd0, 0xafb40028,
+0xafb20020, 0xafbf002c, 0xafb30024, 0xafb1001c,
+0xafb00018, 0x904400d0, 0x904300d1, 0xa021,
+0x309200ff, 0xa3a30010, 0x306300ff, 0x8c5100d8,
+0x8c5300dc, 0x1072002b, 0x24020001, 0x3c030800,
+0x8c6300e4, 0x93a40010, 0x8f820034, 0x2406ff80,
+0x42140, 0x431021, 0x441021, 0x3043007f,
+0x461024, 0xaf420028, 0x3431821, 0x3c02000c,
+0x621821, 0x8c620004, 0x27a40014, 0x27a50010,
+0x2228021, 0x2701023, 0x4400015, 0xafa30014,
+0x9062000d, 0xc21024, 0x304200ff, 0x14400007,
+0x2008821, 0x9062000d, 0x34420040, 0xe0007fe,
+0xa062000d, 0xa000abd, 0x93a20010, 0xe0009e1,
+0x24140001, 0x8f830028, 0xac7000d8, 0x93a20010,
+0xa06200d1, 0x93a20010, 0x1452ffd8, 0x0,
+0x24020001, 0x16820004, 0x8fbf002c, 0xe000626,
+0x0, 0x8fbf002c, 0x8fb40028, 0x8fb30024,
+0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
+0x27bd0030, 0x27bdffd8, 0xafb3001c, 0xafb20018,
+0xafb10014, 0xafb00010, 0xafbf0020, 0x809821,
+0xe08021, 0x30b1ffff, 0xe000493, 0x30d200ff,
+0x0, 0x0, 0x0, 0x8f820020,
+0xac510000, 0xac520004, 0xac530008, 0xac40000c,
+0xac400010, 0xac400014, 0xac400018, 0x3c030800,
+0x94634b5e, 0x2038025, 0xac50001c, 0x0,
+0x0, 0x0, 0x24040001, 0x8fbf0020,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0xa0004b8, 0x27bd0028, 0x27bdffe8, 0xafb00010,
+0xafbf0014, 0x30a5ffff, 0x30c600ff, 0x808021,
+0x24020c80, 0xaf420024, 0x0, 0x0,
+0x0, 0x0, 0x0, 0xe000acc,
+0x0, 0x3c040800, 0x248400e0, 0x8c820000,
+0x2403ff80, 0x8fbf0014, 0x2021021, 0x431024,
+0xaf420024, 0x8c820000, 0x3c03000a, 0x2028021,
+0x3210007f, 0x3501021, 0x8fb00010, 0x431021,
+0x27bd0018, 0x3e00008, 0xaf820028, 0x27bdffe8,
+0xafbf0010, 0x8f440140, 0x3c030800, 0x8c6300e0,
+0x2402ff80, 0xaf840034, 0x831821, 0x621024,
+0xaf420024, 0x3c020008, 0x3424021, 0x95050002,
+0x3063007f, 0x3c02000a, 0x3431821, 0x621821,
+0x30a5ffff, 0x3402ffff, 0x3021, 0x3c076020,
+0x10a20006, 0xaf830028, 0x2402ffff, 0xa5020002,
+0x946500d4, 0xe000af1, 0x30a5ffff, 0x8fbf0010,
+0x24020c80, 0x27bd0018, 0x3e00008, 0xaf420024,
+0x3c020008, 0x3424021, 0x95020002, 0x3c0a0800,
+0x954a00c6, 0x3046ffff, 0x14c00007, 0x3402ffff,
+0x8f820028, 0x8f840034, 0x3c076020, 0x944500d4,
+0xa000b5a, 0x30a5ffff, 0x10c20024, 0x8f870028,
+0x94e20054, 0x94e40016, 0x3045ffff, 0xa61023,
+0xa6182b, 0x3089ffff, 0x10600004, 0x3044ffff,
+0xc51023, 0x1221023, 0x3044ffff, 0x8a102b,
+0x1040000c, 0x12a1023, 0x24020001, 0xa5020016,
+0x2402ffff, 0xa5020002, 0x94e500d4, 0x8f840034,
+0x3021, 0x30a5ffff, 0x3c076020, 0xa000af1,
+0x0, 0x44102a, 0x10400008, 0x0,
+0x95020016, 0x30420001, 0x10400004, 0x0,
+0x9742007e, 0x24420014, 0xa5020016, 0x3e00008,
+0x0, 0x8f840028, 0x27bdffe0, 0xafbf0018,
+0x94820034, 0x9483003e, 0x1060001a, 0x3048ffff,
+0x9383002c, 0x24020001, 0x14620027, 0x8fbf0018,
+0x8f820028, 0x818c2, 0x31080007, 0x621821,
+0x2447003a, 0x24490054, 0x24440020, 0x24450030,
+0x24460034, 0x90620040, 0x304200ff, 0x1021007,
+0x30420001, 0x10400016, 0x8fbf0018, 0xe000856,
+0xafa90010, 0x8f820028, 0x94420034, 0xa000b73,
+0x3048ffff, 0x94830036, 0x94820034, 0x1043000e,
+0x8fbf0018, 0x94820036, 0xa4820034, 0x94820056,
+0xa4820054, 0x8c82002c, 0xac820024, 0x94820032,
+0xa4820030, 0x9482003c, 0xa482003a, 0x8fbf0018,
+0xa000b33, 0x27bd0020, 0x3e00008, 0x27bd0020,
+0x27bdffe8, 0xafbf0010, 0x8f4a0100, 0x3c050800,
+0x8ca500e0, 0x3c020800, 0x90424b84, 0x3c0c0800,
+0x958c4b7e, 0x1452821, 0x304b003f, 0x30a2007f,
+0x3424021, 0x39690032, 0x3c02000a, 0x3963003f,
+0x2c630001, 0x1024021, 0x2d290001, 0x2402ff80,
+0xa22824, 0x1234825, 0xaf8a0034, 0x801821,
+0xaf450024, 0x3021, 0x802821, 0x24070001,
+0xaf880028, 0x3c040800, 0x24844b78, 0xaf8c0024,
+0x15200007, 0xa380002d, 0x24020020, 0x5562000f,
+0x602021, 0x3402ffff, 0x5582000c, 0x602021,
+0x24020020, 0x15620005, 0x0, 0x8c630014,
+0x2402ffff, 0x10620007, 0x0, 0xe000889,
+0x0, 0xa000bd0, 0x0, 0xe0008f4,
+0x1602821, 0xe000b68, 0x0, 0x8fbf0010,
+0x24020c80, 0x27bd0018, 0x3e00008, 0xaf420024,
+0x3c020800, 0x8c4200e0, 0x27bdffa0, 0xafb1003c,
+0x821021, 0x2411ff80, 0xafbe0058, 0xafb70054,
+0xafb20040, 0xafb00038, 0xafbf005c, 0xafb60050,
+0xafb5004c, 0xafb40048, 0xafb30044, 0x511024,
+0x8f480024, 0x8f490028, 0x8f470028, 0xaf420024,
+0x3c020800, 0x8c4200e0, 0x809021, 0x24060006,
+0x821021, 0x3042007f, 0x3421821, 0x3c02000a,
+0x628021, 0x3c02001f, 0x3442ff80, 0xe23824,
+0x27a40010, 0x260500f0, 0x122f024, 0x102b824,
+0xe00051d, 0xafa70030, 0x8fa20018, 0xae0200c4,
+0x8fa2001c, 0xae0200c8, 0x8fa20024, 0xae0200cc,
+0x93a40010, 0x920300d1, 0x2402ff80, 0x821024,
+0x431025, 0x304900ff, 0x3083007f, 0x3122007f,
+0x62102a, 0x10400004, 0x310c0, 0x1311026,
+0x304900ff, 0x310c0, 0x31940, 0x621821,
+0x3c020800, 0x8c4200dc, 0x920400d2, 0x2421021,
+0x431021, 0x511024, 0xaf420028, 0x93a30010,
+0x3063007f, 0x310c0, 0x31940, 0x621821,
+0x3c020800, 0x8c4200dc, 0x2421021, 0x431021,
+0x3042007f, 0x3421821, 0x3c02000c, 0x624021,
+0x8fa30014, 0x2402ffff, 0x10620030, 0x309500ff,
+0x93a20011, 0x95030014, 0x304400ff, 0x3063ffff,
+0x64182b, 0x1060000d, 0x0, 0x95040014,
+0x8d07001c, 0x8d060018, 0x3084ffff, 0x442023,
+0x42100, 0x1021, 0xe43821, 0xe4202b,
+0xc23021, 0xa000c4a, 0xc43021, 0x95040014,
+0x8d07001c, 0x8d060018, 0x3084ffff, 0x822023,
+0x42100, 0x1021, 0x801821, 0xc23023,
+0xe4202b, 0xc43023, 0xe33823, 0xad07001c,
+0xad060018, 0x93a20011, 0xa5020014, 0x97a20012,
+0xa5020016, 0x8fa20014, 0xad020010, 0x8fa20014,
+0xad02000c, 0x93a20011, 0xa5020020, 0x97a20012,
+0xa5020022, 0x8fa20014, 0xad020024, 0x2406ff80,
+0x2461024, 0x3256007f, 0xaf420024, 0x3561821,
+0x3c02000a, 0x628021, 0x8e02004c, 0x8fa20020,
+0x3124007f, 0x428c0, 0xae020050, 0x8fa20020,
+0x42140, 0x852821, 0xae020070, 0x93a20010,
+0x1208821, 0xa2020083, 0x93a20010, 0xa2020079,
+0x92020085, 0x3042003f, 0xa2020085, 0x3c020800,
+0x8c4200dc, 0x2421021, 0x451021, 0x461024,
+0xaf42002c, 0x3c020800, 0x8c4200e4, 0x3c030800,
+0x8c6300dc, 0x2421021, 0x441021, 0x461024,
+0xaf420028, 0x3c020800, 0x8c4200e4, 0x2431821,
+0x651821, 0x2421021, 0x441021, 0x3042007f,
+0x3063007f, 0x93a50010, 0x3422021, 0x3431821,
+0x3c02000e, 0x624021, 0x3c02000c, 0x10b1008c,
+0x824821, 0x3233007f, 0x16600019, 0x2404ff80,
+0x3c020800, 0x8c4200dc, 0x2421021, 0x441024,
+0xaf42002c, 0x3c020800, 0x8c4200e4, 0x3c030800,
+0x8c6300dc, 0x2421021, 0x441024, 0xaf420028,
+0x3c020800, 0x8c4200e4, 0x2431821, 0x3063007f,
+0x2421021, 0x3042007f, 0x3422021, 0x3431821,
+0x3c02000e, 0x624021, 0x3c02000c, 0x824821,
+0x9124000d, 0x2414ff80, 0x1021, 0x942025,
+0xa124000d, 0x95040002, 0x95050014, 0x8d07001c,
+0x3084ffff, 0x30a5ffff, 0x8d060018, 0x852023,
+0x42100, 0xe43821, 0xc23021, 0xe4202b,
+0xc43021, 0xad07001c, 0xad060018, 0x95020002,
+0xa5020014, 0xa5000016, 0x8d020008, 0xad020010,
+0x8d020008, 0xad02000c, 0x95020002, 0xa5020020,
+0xa5000022, 0x8d020008, 0xad020024, 0x9122000d,
+0x30420040, 0x10400042, 0x26220001, 0x3c020800,
+0x8c4200e0, 0xa3b30028, 0x3c10000a, 0x2421021,
+0x541024, 0xaf420024, 0x3c020800, 0x8c4200e0,
+0xa380002c, 0x27a4002c, 0x2421021, 0x3042007f,
+0x3421821, 0x701821, 0x8c6200d8, 0x8d260004,
+0x27a50028, 0xafa9002c, 0x461021, 0xac6200d8,
+0xe0009e1, 0xaf830028, 0x93a30028, 0x8f820028,
+0xe000626, 0xa04300d1, 0xe000b68, 0x0,
+0x2541024, 0xaf420024, 0x3c020800, 0x8c4200dc,
+0x132940, 0x1320c0, 0xa42021, 0x2421021,
+0x441021, 0x541024, 0xaf42002c, 0x3c020800,
+0x8c4200e4, 0x3c030800, 0x8c6300dc, 0x3563021,
+0x2421021, 0x451021, 0x541024, 0xaf420028,
+0x3c020800, 0x8c4200e4, 0x2431821, 0x641821,
+0x2421021, 0x451021, 0x3042007f, 0x3063007f,
+0x3422021, 0x3431821, 0x3c02000e, 0x624021,
+0x3c02000c, 0xd08021, 0x824821, 0x26220001,
+0x3043007f, 0x14750005, 0x304400ff, 0x2403ff80,
+0x2231024, 0x431026, 0x304400ff, 0x93a20010,
+0x808821, 0x25080028, 0x1444ff76, 0x25290020,
+0x93a40010, 0x8fa30014, 0x2402ffff, 0x1062000a,
+0x308900ff, 0x24820001, 0x24830001, 0x3042007f,
+0x14550005, 0x306900ff, 0x2403ff80, 0x831024,
+0x431026, 0x304900ff, 0x92020078, 0x305300ff,
+0x11330032, 0x1208821, 0x3c020800, 0x8c4200dc,
+0x3225007f, 0x520c0, 0x52940, 0xa42021,
+0x2421021, 0x2406ff80, 0x441021, 0x461024,
+0xaf42002c, 0x3c030800, 0x8c6300dc, 0x3c020800,
+0x8c4200e4, 0x2431821, 0x2421021, 0x451021,
+0x641821, 0x461024, 0x3063007f, 0xaf420028,
+0x3431821, 0x3c02000e, 0x624021, 0x3c020800,
+0x8c4200e4, 0x8d06000c, 0x1002021, 0x2421021,
+0x451021, 0x3042007f, 0x3421821, 0x3c02000c,
+0x624821, 0x10c0000d, 0x1202821, 0xe00064a,
+0x0, 0x2402ff80, 0x2221824, 0x26240001,
+0x622826, 0x3082007f, 0x14550002, 0x308300ff,
+0x30a300ff, 0x1473ffd0, 0x608821, 0x8e030074,
+0x3c027fff, 0x3442ffff, 0x621824, 0xae030074,
+0xe00066b, 0x2402021, 0xaf570024, 0x8fa20030,
+0xaf5e0028, 0x8fbf005c, 0x8fbe0058, 0x8fb70054,
+0x8fb60050, 0x8fb5004c, 0x8fb40048, 0x8fb30044,
+0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x27bd0060,
+0x3e00008, 0xaf42002c, 0x27bdffd8, 0xafb1001c,
+0xafbf0020, 0xafb00018, 0x27510188, 0x92220003,
+0x2408ff80, 0x3c03000a, 0x3047007f, 0xa3a70010,
+0x8f460180, 0x3c020800, 0x8c4200e0, 0xaf860034,
+0xc22821, 0xa81024, 0xaf420024, 0x92240000,
+0x30a2007f, 0x3421021, 0x431021, 0xaf820028,
+0x3084007f, 0x24020002, 0x14820025, 0x71940,
+0x3c020800, 0x8c4200e4, 0xc21021, 0x432821,
+0x30a2007f, 0x3421821, 0xa81024, 0xaf420028,
+0x3c02000c, 0x621821, 0x9062000d, 0xafa30014,
+0x481025, 0xa062000d, 0x8fa30014, 0x9062000d,
+0x30420040, 0x5040006a, 0x8fbf0020, 0x8f860028,
+0xa380002c, 0x27a40014, 0x8cc200d8, 0x8c630004,
+0x27a50010, 0x431021, 0xe0009e1, 0xacc200d8,
+0x93a30010, 0x8f820028, 0xe000626, 0xa04300d1,
+0xe000b68, 0x0, 0xa000e0b, 0x8fbf0020,
+0xe00062f, 0xc02021, 0xe00063d, 0x0,
+0x3c020008, 0x3428021, 0x92230001, 0x9202007b,
+0x1443004f, 0x8fbf0020, 0x92220000, 0x3044007f,
+0x24020004, 0x10820017, 0x28820005, 0x10400006,
+0x24020005, 0x24020003, 0x10820007, 0x8fb1001c,
+0xa000e0c, 0x0, 0x10820012, 0x8fbf0020,
+0xa000e0c, 0x8fb1001c, 0x92050083, 0x92060078,
+0x8e070074, 0x8f840034, 0x30a500ff, 0x73e02,
+0x30c600ff, 0xe000673, 0x30e7007f, 0xa000e0b,
+0x8fbf0020, 0xe000bd7, 0x8f840034, 0xa000e0b,
+0x8fbf0020, 0x24020c80, 0xaf420024, 0x9202003e,
+0x30420040, 0x10400020, 0x0, 0x9202003e,
+0x21600, 0x21603, 0x4410006, 0x0,
+0x8f840034, 0xe0005a0, 0x24050093, 0xa000e0b,
+0x8fbf0020, 0x9202003f, 0x24030018, 0x304200ff,
+0x1443000c, 0x8f840034, 0x24050039, 0xe000538,
+0x3021, 0xe000250, 0x8f840034, 0x24020012,
+0xa202003f, 0xe000259, 0x8f840034, 0xa000e0b,
+0x8fbf0020, 0x24050036, 0xe000538, 0x3021,
+0xa000e0b, 0x8fbf0020, 0xe000250, 0x8f840034,
+0x92020005, 0x34420020, 0xa2020005, 0xe000259,
+0x8f840034, 0xe000fc0, 0x8f840034, 0x8fbf0020,
+0x8fb1001c, 0x8fb00018, 0x24020c80, 0x27bd0028,
+0x3e00008, 0xaf420024, 0x27bdffe8, 0xafb00010,
+0xafbf0014, 0x27430100, 0x94620008, 0x21400,
+0x21403, 0x4410002, 0x8021, 0x24100001,
+0x94620008, 0x30420080, 0x1040001a, 0x2001021,
+0x94620008, 0x30422000, 0x10400016, 0x2001021,
+0x8c630018, 0x3c021c2d, 0x344219ed, 0x24060006,
+0x1062000f, 0x3c076021, 0x3c020800, 0x8c4200d4,
+0x10400007, 0x8f820028, 0x8f830028, 0x90620062,
+0x3042000f, 0x34420040, 0xa0620062, 0x8f820028,
+0x8f840034, 0x944500d4, 0xe000af1, 0x30a5ffff,
+0x2001021, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x27bdffe0, 0xafb10014, 0xafb00010,
+0xa380002c, 0xafbf0018, 0x8f450100, 0x3c030800,
+0x8c6300e0, 0x2402ff80, 0xaf850034, 0xa31821,
+0x3064007f, 0x3442021, 0x621824, 0x3c02000a,
+0x822021, 0xaf430024, 0x27500100, 0x8e020014,
+0x8c8300dc, 0xaf840028, 0x431023, 0x18400004,
+0x8821, 0x8e020014, 0xe000a84, 0xac8200dc,
+0x9202000b, 0x24030002, 0x304200ff, 0x1443002f,
+0x0, 0x96020008, 0x304300ff, 0x24020082,
+0x14620005, 0x24020084, 0xe00093e, 0x0,
+0xa000e97, 0x0, 0x14620009, 0x24020081,
+0x8f820028, 0x8f840034, 0x3c076021, 0x944500d4,
+0x92060005, 0x30a5ffff, 0xa000e86, 0x30c600ff,
+0x14620027, 0x0, 0x9202000a, 0x304300ff,
+0x30620020, 0x10400004, 0x30620040, 0x8f840034,
+0xa000e82, 0x24060040, 0x10400004, 0x31600,
+0x8f840034, 0xa000e82, 0x24060041, 0x21603,
+0x4410017, 0x8f840034, 0x24060042, 0x8f820028,
+0x3c076019, 0x944500d4, 0x30a5ffff, 0xe000af1,
+0x0, 0xa000e97, 0x0, 0x9202000b,
+0x24030016, 0x304200ff, 0x10430006, 0x0,
+0x9202000b, 0x24030017, 0x304200ff, 0x14430004,
+0x0, 0xe000e11, 0x0, 0x408821,
+0xe000b68, 0x0, 0x9202000a, 0x30420008,
+0x10400006, 0x24020c80, 0x8f850028, 0x3c040008,
+0xe0011ee, 0x3442021, 0x24020c80, 0xaf420024,
+0x8fbf0018, 0x2201021, 0x8fb00010, 0x8fb10014,
+0x3e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014,
+0xafb00010, 0x8f500024, 0x3c030800, 0x8c6300e0,
+0x8f450100, 0x2402ff80, 0xa31821, 0x3064007f,
+0x3442021, 0x621824, 0x3c02000a, 0x822021,
+0xaf850034, 0xaf430024, 0x90820062, 0xaf840028,
+0x3042000f, 0x34420050, 0xa0820062, 0x3c02001f,
+0x3442ff80, 0xe000626, 0x2028024, 0xaf500024,
+0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
+0x3c020800, 0x8c420020, 0x1040001d, 0x27450100,
+0x90a30009, 0x3c020008, 0x3422021, 0x24020018,
+0x54620003, 0x3c020008, 0xa000ed8, 0x24020008,
+0x3422021, 0x24020016, 0x14620005, 0x24020017,
+0x24020012, 0xa082003f, 0xa000ee2, 0x94a70008,
+0x54620006, 0x94a70008, 0x93620005, 0x2403fffe,
+0x431024, 0xa3620005, 0x94a70008, 0x90a6001b,
+0x8ca40000, 0x94a50006, 0xa000acc, 0x73c00,
+0x3e00008, 0x0, 0x27440100, 0x94820008,
+0x304500ff, 0x38a30082, 0x38a20084, 0x2c630001,
+0x2c420001, 0x621825, 0x10600006, 0x24020083,
+0x9382002d, 0x1040000d, 0x0, 0xa000b9b,
+0x0, 0x14a20005, 0x24a2ff80, 0x8f430104,
+0x3c026020, 0x3e00008, 0xac430014, 0x304200ff,
+0x2c420002, 0x10400003, 0x24020022, 0xa000e3c,
+0x0, 0x14a20003, 0x0, 0xa000ea9,
+0x0, 0xa000ec7, 0x0, 0x9363007e,
+0x9362007a, 0x14430009, 0x2021, 0x93620000,
+0x24030050, 0x304200ff, 0x14430004, 0x24040001,
+0x9362007e, 0x24420001, 0xa362007e, 0x3e00008,
+0x801021, 0x8f4201f8, 0x440fffe, 0x24020002,
+0xaf4401c0, 0xa34201c4, 0x3c021000, 0x3e00008,
+0xaf4201f8, 0x27bdffe8, 0xafbf0010, 0x9362003f,
+0x2403000a, 0x304200ff, 0x14430046, 0x0,
+0x8f630054, 0x8f62004c, 0x1062007d, 0x3603021,
+0x93620000, 0x24030050, 0x304200ff, 0x1443002f,
+0x0, 0x8f440140, 0x3c020800, 0x8c4200e0,
+0x2403ff80, 0x821021, 0x431024, 0xaf420024,
+0x3c020800, 0x8c4200e0, 0x8f650054, 0x3c03000a,
+0x822021, 0x3084007f, 0x3441021, 0x431021,
+0xac450108, 0x9762003c, 0x8f63004c, 0x3042ffff,
+0x21040, 0x621821, 0xaf63005c, 0x8f630054,
+0x8f64004c, 0x9762003c, 0x641823, 0x3042ffff,
+0x31843, 0x21040, 0x43102a, 0x10400006,
+0x0, 0x8f620054, 0x8f63004c, 0x431023,
+0xa000f58, 0x21043, 0x9762003c, 0x3042ffff,
+0x21040, 0xacc20064, 0x24020001, 0xa0c0007c,
+0xa0c20084, 0x24020c80, 0xaf420024, 0xe000f0a,
+0x8f440140, 0x10400047, 0x8fbf0010, 0x8f430140,
+0x8f4201f8, 0x440fffe, 0x24020002, 0xaf4301c0,
+0xa34201c4, 0x3c021000, 0xaf4201f8, 0xa000fa8,
+0x8fbf0010, 0x9362003f, 0x24030010, 0x304200ff,
+0x14430004, 0x0, 0x8f440140, 0xa000f94,
+0x2821, 0x9362003f, 0x24030016, 0x304200ff,
+0x14430004, 0x24020014, 0xa362003f, 0xa000fa2,
+0x0, 0x8f62004c, 0x8f630050, 0x431023,
+0x4410028, 0x8fbf0010, 0x93620081, 0x24420001,
+0xa3620081, 0x93620081, 0x2c420004, 0x14400010,
+0x0, 0x9362003f, 0x24030004, 0x304200ff,
+0x14430006, 0x0, 0x8f440140, 0x8fbf0010,
+0x24050093, 0xa0005a0, 0x27bd0018, 0x8f440140,
+0x24050093, 0x8fbf0010, 0xa00060f, 0x27bd0018,
+0x8f440140, 0xe000250, 0x0, 0x8f620054,
+0x2442ffff, 0xaf620054, 0x8f620050, 0x2442ffff,
+0xaf620050, 0xe000259, 0x8f440140, 0x8f440140,
+0x8fbf0010, 0x24050004, 0xa00025e, 0x27bd0018,
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8f420188,
+0x9363007e, 0x21402, 0x304400ff, 0x306300ff,
+0x1464000d, 0x0, 0x93620080, 0x304200ff,
+0x10440009, 0x0, 0xa3640080, 0x93620000,
+0x24030050, 0x304200ff, 0x14430004, 0x0,
+0xa0006d7, 0x8f440180, 0xa3640080, 0x3e00008,
+0x0, 0x27bdffe8, 0xafb00010, 0xafbf0014,
+0x93620005, 0x24030030, 0x30420030, 0x14430089,
+0x808021, 0x3c020800, 0x8c420020, 0x10400080,
+0x2002021, 0xe000493, 0x0, 0x8f850020,
+0xacb00000, 0x9362003e, 0x9363003f, 0x304200ff,
+0x21200, 0x306300ff, 0x431025, 0xaca20004,
+0x93620082, 0x21600, 0x21603, 0x4410005,
+0x0, 0x3c030800, 0x8c630048, 0xa000fe6,
+0x0, 0x9362003e, 0x30420040, 0x14400003,
+0x1821, 0x93620081, 0x304300ff, 0x93620082,
+0x31e00, 0x304200ff, 0x21400, 0x621825,
+0xaca30008, 0x8f620040, 0xaca2000c, 0x8f620048,
+0xaca20010, 0x8f62004c, 0xaca20014, 0x8f620050,
+0x8f63004c, 0x431023, 0x4410003, 0x0,
+0xa000ffa, 0x8f62004c, 0x8f620050, 0xaca20018,
+0x3c020800, 0x94424b5e, 0x3c03c00b, 0x2021,
+0x431025, 0xe0004b8, 0xaca2001c, 0x8f620054,
+0x8f840020, 0xac820000, 0x8f620058, 0xac820004,
+0x8f62005c, 0xac820008, 0x8f620060, 0x8f430074,
+0x431021, 0xac82000c, 0x8f620064, 0xac820010,
+0x97630068, 0x9762006a, 0x31c00, 0x3042ffff,
+0x621825, 0xac830014, 0x93620082, 0x24030080,
+0x304200ff, 0x14430003, 0x0, 0xa00102e,
+0xac800018, 0x8f63000c, 0x24020001, 0x1062000e,
+0x2402ffff, 0x9362003e, 0x30420040, 0x1440000a,
+0x2402ffff, 0x8f63000c, 0x8f420074, 0x621823,
+0x3c020800, 0x621024, 0x14400002, 0x2821,
+0x602821, 0x51043, 0xac820018, 0x3c020800,
+0x94424b5e, 0x3c03c00c, 0x2021, 0x431025,
+0x8f830020, 0xe0004b8, 0xac62001c, 0x8f620018,
+0x8f830020, 0x3c050800, 0x94a54b5e, 0x24040001,
+0xac620000, 0xac600004, 0x8f66006c, 0x3c02400d,
+0xa22825, 0xac660008, 0x8f6200dc, 0xac62000c,
+0xac600010, 0x93620005, 0x21600, 0xac620014,
+0xac600018, 0xe0004b8, 0xac65001c, 0x2002021,
+0x8fbf0014, 0x8fb00010, 0xa3600005, 0xa000421,
+0x27bd0018, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x9742007c, 0x30c600ff, 0xa0860084,
+0x3047ffff, 0x24020005, 0x14c2000b, 0x24e34650,
+0x90a20112, 0x2c420007, 0x10400007, 0x24e30a00,
+0x90a30112, 0x24020014, 0x621004, 0xe21021,
+0xa001066, 0x3047ffff, 0x3067ffff, 0x3e00008,
+0xa4870014, 0xac87004c, 0x8ca20108, 0x804021,
+0xa04821, 0xe21023, 0x30c600ff, 0x18400003,
+0x93aa0013, 0x24e2fffc, 0xaca20108, 0x30c20001,
+0x10400008, 0x0, 0x8d020050, 0xe21023,
+0x4410013, 0x24060005, 0x8d020054, 0x10e20010,
+0x0, 0x8d020054, 0x14e2001a, 0x0,
+0x3c020800, 0x8c4200d8, 0x30420020, 0x1040000a,
+0x24020001, 0x91030078, 0x91020083, 0x14430006,
+0x24020001, 0x1002021, 0x1202821, 0x24060004,
+0xa001054, 0x0, 0xa1000084, 0x11400009,
+0xa5020014, 0x8f430100, 0x8f4201f8, 0x440fffe,
+0x24020002, 0xaf4301c0, 0xa34201c4, 0x3c021000,
+0xaf4201f8, 0x3e00008, 0x0, 0x27bdffe8,
+0x8fa90028, 0xafbf0010, 0x804021, 0xe91823,
+0x18600073, 0x30c600ff, 0xa080007c, 0xa0800081,
+0x8ca20108, 0xe21023, 0x440004d, 0x0,
+0x8c820050, 0x9483003c, 0x8c840064, 0x474823,
+0x3063ffff, 0x1231821, 0x83202b, 0x10800004,
+0x0, 0x8d020064, 0xa0010b7, 0xe21021,
+0x9502003c, 0x3042ffff, 0x1221021, 0xe21021,
+0xad02005c, 0x9502003c, 0x8d03005c, 0x3042ffff,
+0x21040, 0xe21021, 0x43102b, 0x10400003,
+0x0, 0xa0010c6, 0x8d02005c, 0x9502003c,
+0x3042ffff, 0x21040, 0xe21021, 0xad02005c,
+0xa1000084, 0xad07004c, 0x8ca20108, 0xe21023,
+0x18400002, 0x24e2fffc, 0xaca20108, 0x30c20001,
+0x1040000a, 0x0, 0x8d020050, 0xe21023,
+0x4410004, 0x1002021, 0x8d020054, 0x14e20003,
+0x0, 0xa0010e8, 0x24060005, 0x8d020054,
+0x14e20047, 0x8fbf0010, 0x3c020800, 0x8c4200d8,
+0x30420020, 0x1040000a, 0x24020001, 0x91030078,
+0x91020083, 0x14430006, 0x24020001, 0x1002021,
+0x24060004, 0x8fbf0010, 0xa001054, 0x27bd0018,
+0xa1000084, 0xa5020014, 0x8f430100, 0x8f4201f8,
+0x440fffe, 0x24020002, 0xa00110d, 0x0,
+0x8c82005c, 0x491023, 0x43102b, 0x54400001,
+0xac87005c, 0x9502003c, 0x3042ffff, 0x62102b,
+0x14400007, 0x24020002, 0x9502003c, 0x8d03005c,
+0x3042ffff, 0x621821, 0xad03005c, 0x24020002,
+0xad07004c, 0xa1020084, 0xe000f0a, 0x8f440100,
+0x1040001b, 0x8fbf0010, 0x8f430100, 0x8f4201f8,
+0x440fffe, 0x24020002, 0xaf4301c0, 0xa34201c4,
+0x3c021000, 0xaf4201f8, 0xa001123, 0x8fbf0010,
+0x30c20010, 0x1040000e, 0x8fbf0010, 0x8c83005c,
+0x9482003c, 0x691823, 0x3042ffff, 0x621821,
+0x3c023fff, 0x3444ffff, 0x83102b, 0x54400001,
+0x801821, 0x1231021, 0xad02005c, 0x8fbf0010,
+0x3e00008, 0x27bd0018, 0x27bdffe8, 0x8faa0028,
+0xafbf0010, 0x804021, 0xea4823, 0x19200021,
+0x30c600ff, 0x8c83005c, 0x8c820064, 0x6a1823,
+0x43102b, 0x50400010, 0x691821, 0x94a20110,
+0x1221021, 0xa4a20110, 0x94a20110, 0x3042ffff,
+0x43102b, 0x1440000a, 0x3c023fff, 0x94a20110,
+0x431023, 0xa4a20110, 0x9482003c, 0x3042ffff,
+0xa001142, 0x621821, 0xa4a00110, 0x3c023fff,
+0x3444ffff, 0x83102b, 0x54400001, 0x801821,
+0x671021, 0xad02005c, 0xa100007c, 0xa00118a,
+0xa1000081, 0x30c20010, 0x1040003c, 0x0,
+0x8c820050, 0x4a1023, 0x18400038, 0x0,
+0x9082007c, 0x24420001, 0xa082007c, 0x9082007c,
+0x3c030800, 0x8c630024, 0x304200ff, 0x43102b,
+0x1440005c, 0x8fbf0010, 0x8ca20108, 0xe21023,
+0x18400058, 0x0, 0x8c830054, 0x9482003c,
+0x6a1823, 0x3042ffff, 0x31843, 0x21040,
+0x43102a, 0x10400005, 0x0, 0x8c820054,
+0x4a1023, 0xa001171, 0x21043, 0x9482003c,
+0x3042ffff, 0x21040, 0xad020064, 0x9502003c,
+0x8d040064, 0x9503003c, 0x3042ffff, 0x21040,
+0x822021, 0x3063ffff, 0x831821, 0x1431021,
+0xad02005c, 0x8d020054, 0xaca20108, 0x24020002,
+0xa1020084, 0xe000f0a, 0x8f440100, 0x10400035,
+0x8fbf0010, 0x8f430100, 0x8f4201f8, 0x440fffe,
+0x24020002, 0xa0011b3, 0x0, 0xad07004c,
+0x8ca20108, 0xe21023, 0x18400002, 0x24e2fffc,
+0xaca20108, 0x30c20001, 0x1040000a, 0x0,
+0x8d020050, 0xe21023, 0x4410004, 0x1002021,
+0x8d020054, 0x14e20003, 0x0, 0xa0011aa,
+0x24060005, 0x8d020054, 0x14e2001a, 0x8fbf0010,
+0x3c020800, 0x8c4200d8, 0x30420020, 0x1040000a,
+0x24020001, 0x91030078, 0x91020083, 0x14430006,
+0x24020001, 0x1002021, 0x24060004, 0x8fbf0010,
+0xa001054, 0x27bd0018, 0xa1000084, 0xa5020014,
+0x8f430100, 0x8f4201f8, 0x440fffe, 0x24020002,
+0xaf4301c0, 0xa34201c4, 0x3c021000, 0xaf4201f8,
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8faa0010,
+0x8c820050, 0x804021, 0x30c600ff, 0x4a1023,
+0xa04821, 0x18400007, 0xe01821, 0x24020001,
+0xa0800084, 0xa0a00112, 0xa4820014, 0xa001125,
+0xafaa0010, 0xa0800081, 0xad07004c, 0x8ca20108,
+0xe21023, 0x18400002, 0x24e2fffc, 0xaca20108,
+0x30c20001, 0x10400008, 0x0, 0x8d020050,
+0x621023, 0x4410013, 0x24060005, 0x8d020054,
+0x10620010, 0x0, 0x8d020054, 0x14620011,
+0x0, 0x3c020800, 0x8c4200d8, 0x30420020,
+0x1040000a, 0x24020001, 0x91030078, 0x91020083,
+0x14430006, 0x24020001, 0x1002021, 0x1202821,
+0x24060004, 0xa001054, 0x0, 0xa1000084,
+0xa5020014, 0x3e00008, 0x0, 0x27bdffe0,
+0xafbf0018, 0x27420100, 0x9046000a, 0x8c480014,
+0x8c8b004c, 0x90820084, 0x30c900ff, 0x1681823,
+0x304a00ff, 0x1c60001a, 0x2d460006, 0x24020001,
+0x1421004, 0x10c00016, 0x30430003, 0x1203021,
+0x1003821, 0x14600007, 0x304c000c, 0x15800009,
+0x30420030, 0x1440000b, 0x8fbf0018, 0xa001214,
+0x0, 0xe001125, 0xafab0010, 0xa001214,
+0x8fbf0018, 0xe00109a, 0xafab0010, 0xa001214,
+0x8fbf0018, 0xafab0010, 0xe0011ba, 0xafaa0014,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x24020003,
+0xa0820084, 0x8c820054, 0x3e00008, 0xaca20108,
+0x3c020008, 0x3421821, 0x90620081, 0x24060043,
+0x3c076019, 0x24420001, 0xa0620081, 0x90630081,
+0x3c020800, 0x8c4200c0, 0x306300ff, 0x14620010,
+0x2403ff80, 0x3c020800, 0x8c4200e0, 0x821021,
+0x431024, 0xaf420024, 0x3c020800, 0x8c4200e0,
+0x3c03000a, 0x821021, 0x3042007f, 0x3421021,
+0x431021, 0x944500d4, 0xa000af1, 0x30a5ffff,
+0x3e00008, 0x0, 0x27bdffe0, 0xafbf0018,
+0xafb10014, 0xafb00010, 0x8f420180, 0x808021,
+0xa08821, 0xe00121b, 0x402021, 0xa2000084,
+0x8e020054, 0x8fbf0018, 0x8fb00010, 0xae220108,
+0x8fb10014, 0x3e00008, 0x27bd0020, 0x27bdffe0,
+0x3c020008, 0xafb00010, 0xafbf0018, 0xafb10014,
+0x3428021, 0x8f510140, 0x92030084, 0x8e040050,
+0x8e02004c, 0x14820040, 0x306600ff, 0x3c020800,
+0x8c4200e0, 0x2403ff80, 0x2221021, 0x431024,
+0xaf420024, 0x3c020800, 0x8c4200e0, 0x9744007c,
+0x92050081, 0x2221021, 0x3042007f, 0x3421821,
+0x3c02000a, 0x621821, 0x14a0000b, 0x3084ffff,
+0x24020005, 0x54c20014, 0x248205dc, 0x90620112,
+0x24420001, 0xa0620112, 0x24020c80, 0xaf420024,
+0xa001273, 0x24020005, 0xa0600112, 0x24020005,
+0x14c20009, 0x248205dc, 0x92020081, 0x2c420007,
+0x50400005, 0x24820a00, 0x92030081, 0x24020014,
+0x621004, 0x821021, 0x3044ffff, 0xa6040014,
+0xe00121b, 0x2202021, 0x9602003c, 0x8e03004c,
+0x2202021, 0x3042ffff, 0x21040, 0x621821,
+0xe000250, 0xae03005c, 0x9202007d, 0x2202021,
+0x34420040, 0xe000259, 0xa202007d, 0x8f4201f8,
+0x440fffe, 0x24020002, 0xaf5101c0, 0xa34201c4,
+0x3c021000, 0xaf4201f8, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x0 };
+u32 bce_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
+u32 bce_COM_b06FwRodata[(0x14/4) + 1] = {
+0x8000acc,
+0x8000b14, 0x8000b98, 0x8000be4, 0x8000c20,
0x0 };
-u32 bce_COM_b06FwBss[(0xbc/4) + 1] = { 0x0 };
-u32 bce_COM_b06FwSbss[(0x38/4) + 1] = { 0x0 };
-u32 bce_COM_b06FwSdata[(0x0/4) + 1] = { 0x0 };
+u32 bce_COM_b06FwBss[(0xc4/4) + 1] = { 0x0 };
+u32 bce_COM_b06FwSbss[(0x38/4) + 1] = { 0x0 };
+u32 bce_COM_b06FwSdata[(0x0/4) + 1] = { 0x0 };
-int bce_RXP_b06FwReleaseMajor = 0x1;
-int bce_RXP_b06FwReleaseMinor = 0x0;
-int bce_RXP_b06FwReleaseFix = 0x0;
-u32 bce_RXP_b06FwStartAddr = 0x080031d8;
-u32 bce_RXP_b06FwTextAddr = 0x08000000;
-int bce_RXP_b06FwTextLen = 0x70dc;
-u32 bce_RXP_b06FwDataAddr = 0x00000000;
-int bce_RXP_b06FwDataLen = 0x0;
-u32 bce_RXP_b06FwRodataAddr = 0x080070dc;
-int bce_RXP_b06FwRodataLen = 0x24;
-u32 bce_RXP_b06FwBssAddr = 0x08007178;
-int bce_RXP_b06FwBssLen = 0x450;
-u32 bce_RXP_b06FwSbssAddr = 0x08007120;
-int bce_RXP_b06FwSbssLen = 0x54;
-u32 bce_RXP_b06FwSDataAddr = 0x00000000;
-int bce_RXP_b06FwSDataLen = 0x0;
-u32 bce_RXP_b06FwText[(0x70dc/4) + 1] = {
-0xa000c76, 0x0, 0x0,
-0xd, 0x72787034, 0x2e362e31, 0x37000000,
-0x4061103, 0x0, 0x1, 0x0,
+int bce_RXP_b06FwReleaseMajor = 0x6;
+int bce_RXP_b06FwReleaseMinor = 0x0;
+int bce_RXP_b06FwReleaseFix = 0xf;
+u32 bce_RXP_b06FwStartAddr = 0x08003210;
+u32 bce_RXP_b06FwTextAddr = 0x08000000;
+int bce_RXP_b06FwTextLen = 0x72d0;
+u32 bce_RXP_b06FwDataAddr = 0x00000000;
+int bce_RXP_b06FwDataLen = 0x0;
+u32 bce_RXP_b06FwRodataAddr = 0x080072d0;
+int bce_RXP_b06FwRodataLen = 0x24;
+u32 bce_RXP_b06FwBssAddr = 0x0800736c;
+int bce_RXP_b06FwBssLen = 0x440;
+u32 bce_RXP_b06FwSbssAddr = 0x08007320;
+int bce_RXP_b06FwSbssLen = 0x4c;
+u32 bce_RXP_b06FwSDataAddr = 0x00000000;
+int bce_RXP_b06FwSDataLen = 0x0;
+u32 bce_RXP_b06FwText[(0x72d0/4) + 1] = {
+0xa000c84, 0x0, 0x0,
+0xd, 0x72787036, 0x2e302e31, 0x35000000,
+0x6000f03, 0x0, 0x1, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
@@ -2130,525 +2074,565 @@ u32 bce_RXP_b06FwText[(0x70dc/4) + 1] = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
-0x10000003, 0x0, 0xd, 0xd,
-0x3c020800, 0x24427120, 0x3c030800, 0x246375c8,
-0xac400000, 0x43202b, 0x1480fffd, 0x24420004,
-0x3c1d0800, 0x37bd7ffc, 0x3a0f021, 0x3c100800,
-0x261031d8, 0x3c1c0800, 0x279c7120, 0xe001164,
-0x0, 0xd, 0x30a5ffff, 0x30c600ff,
-0x27430180, 0x8f4201b8, 0x440fffe, 0x24020002,
-0xac640000, 0xa4650008, 0xa066000a, 0xa062000b,
-0x3c021000, 0xac670018, 0x3e00008, 0xaf4201b8,
-0x3c036000, 0x8c624ff8, 0x440fffe, 0x3c020200,
-0xac644fc0, 0xac624fc4, 0x3c021000, 0x3e00008,
-0xac624ff8, 0x27bdffe8, 0xafbf0014, 0xafb00010,
-0xe0011b3, 0x808021, 0x93620005, 0x2403fffe,
-0x2002021, 0x431024, 0x8fbf0014, 0x8fb00010,
-0xa3620005, 0xa0011bc, 0x27bd0018, 0x27bdffe8,
-0xafb00010, 0xafbf0014, 0xe000ea4, 0x808021,
-0x93620000, 0x24030050, 0x304200ff, 0x14430004,
-0x24020100, 0xaf420180, 0xa000cc1, 0x2002021,
-0xaf400180, 0x2002021, 0x8fbf0014, 0x8fb00010,
-0xa000f7d, 0x27bd0018, 0x27bdff98, 0xafbe0060,
-0xafb7005c, 0xafb20048, 0xafbf0064, 0xafb60058,
-0xafb50054, 0xafb40050, 0xafb3004c, 0xafb10044,
-0xafb00040, 0x8f500128, 0x9363003f, 0x93620005,
-0xf021, 0x307200ff, 0x21027, 0x30420001,
-0xb821, 0x14400066, 0xafa00038, 0x93420116,
-0x93430112, 0x304200ff, 0x306300ff, 0x3422021,
-0x3431021, 0x24454000, 0x8f820000, 0x10400018,
-0x24884000, 0x8f420104, 0x3c030001, 0x431024,
-0x10400013, 0x0, 0x8ca3000c, 0x8f620030,
-0x146201a2, 0x24020001, 0x8ca30010, 0x8f62002c,
-0x1462019e, 0x24020001, 0x9762003a, 0x94834000,
-0x3042ffff, 0x14620199, 0x24020001, 0x97620038,
-0x95030002, 0x3042ffff, 0x14620194, 0x24020001,
-0x93620000, 0x304300ff, 0x24020020, 0x10620005,
-0x24020050, 0x10620006, 0x0, 0xa000d0b,
-0x0, 0xd, 0xa000d14, 0xafa00030,
-0x3c1e0800, 0x27de7188, 0xa000d14, 0xafa00030,
-0x3c020800, 0x8c4200dc, 0x24420001, 0x3c010800,
-0xac2200dc, 0xe00127d, 0x0, 0xa000e8f,
-0x8fbf0064, 0x8f420104, 0x3c030020, 0x9113000d,
-0x431024, 0x2202b, 0x42140, 0xafa40030,
-0x8f430104, 0x3c020040, 0x621824, 0x14600002,
-0x34870040, 0x803821, 0x32620020, 0xafa70030,
-0x14400002, 0x34e60080, 0xe03021, 0x10c0000b,
-0xafa60030, 0x93c50008, 0x8f67004c, 0x2002021,
-0x52b00, 0x34a50081, 0x30a5f081, 0xe000c8d,
-0x30c600ff, 0xa000e8c, 0x0, 0x9362003e,
-0x30420040, 0x1040000e, 0x24020004, 0x56420006,
-0x24020012, 0x2002021, 0xe0013da, 0x1003021,
-0xa000e8f, 0x8fbf0064, 0x16420005, 0x0,
-0xe000cb2, 0x2021, 0xa000e8f, 0x8fbf0064,
-0x9742011a, 0x9504000e, 0x93630035, 0x32650004,
-0x3055ffff, 0x642004, 0xafa4003c, 0x8d110004,
-0x10a00015, 0x8d140008, 0x9362003e, 0x30420040,
-0x10400007, 0x0, 0xe00133b, 0x2202021,
-0x1040000d, 0x0, 0xa000e8c, 0x0,
-0x8f620044, 0x2221023, 0x4400132, 0x0,
-0x8f620048, 0x2221023, 0x441012e, 0x24040016,
-0xa000da2, 0x8fc20004, 0x8f620048, 0x2221023,
-0x4400008, 0x0, 0x3c020800, 0x8c423100,
-0x24420001, 0x3c010800, 0xac223100, 0xa000e81,
-0x0, 0x8f620040, 0x2221023, 0x18400009,
-0x2402000c, 0x3c020800, 0x8c423100, 0x327300fc,
-0xa821, 0x24420001, 0x3c010800, 0xac223100,
-0x2402000c, 0xafa20030, 0x8f620040, 0x511823,
-0x1860000d, 0x2a3102a, 0x14400103, 0x0,
-0x14750006, 0x2a31023, 0x3a620001, 0x30420001,
-0x144000fd, 0x0, 0x2a31023, 0x2238821,
-0xa000d8a, 0x3055ffff, 0x1821, 0x32620002,
-0x1040001a, 0x32620010, 0x9362003e, 0x30420040,
-0x50400011, 0x8fc20004, 0xe0011b3, 0x2002021,
-0x24020018, 0xa362003f, 0x93620005, 0x2403fffe,
-0x2002021, 0x431024, 0xe0011bc, 0xa3620005,
-0x24040039, 0x2821, 0xe001324, 0x24060018,
-0xa000e8e, 0x24020001, 0x24040017, 0x40f809,
-0x0, 0xa000e8e, 0x24020001, 0x104000e5,
-0x0, 0x8f64004c, 0x8f620054, 0x2821023,
-0x1c4000e0, 0x2841023, 0x4420001, 0x80a021,
-0xafa30018, 0xafb10010, 0xafb50014, 0x93420120,
-0x8f660040, 0x9764003c, 0x304200ff, 0x3422821,
-0x8fa2003c, 0xa32821, 0x8fa30030, 0x3084ffff,
-0x44202b, 0x8fc20000, 0x641825, 0x24a54000,
-0xafa50020, 0xafa60028, 0xafa30030, 0xafa60024,
-0xafa0002c, 0xafb40034, 0x40f809, 0x27a40010,
-0x8fa20030, 0x30420002, 0x54400001, 0x327300fe,
-0x9362003e, 0x30420040, 0x10400037, 0x8fa30014,
-0x8f620054, 0x1682001a, 0x32620001, 0x24020014,
-0x12420010, 0x2a420015, 0x10400006, 0x24020016,
-0x2402000c, 0x12420007, 0x32620001, 0xa000deb,
-0x0, 0x12420005, 0x32620001, 0xa000deb,
-0x0, 0xa000de6, 0x2417000e, 0xa000de6,
-0x24170010, 0xa000dea, 0x24170012, 0x93620023,
-0x2403ffbd, 0x431024, 0xa3620023, 0x32620001,
-0x10400019, 0x8fa30014, 0x2402000c, 0x1242000e,
-0x2a42000d, 0x10400006, 0x2402000e, 0x2402000a,
-0x12420007, 0x8fa20024, 0xa000e03, 0x24420001,
-0x12420008, 0x8fa20024, 0xa000e03, 0x24420001,
-0xa000e01, 0x24170008, 0x2402000e, 0x16e20002,
-0x24170016, 0x24170010, 0x8fa20024, 0x24420001,
-0xafa20024, 0x8fa30014, 0x8fa20024, 0x8f760040,
-0x431021, 0xaf620040, 0x8fa2003c, 0x93640036,
-0x8f630040, 0x2829021, 0x3402ffff, 0x821004,
-0x621821, 0xaf630048, 0x8fa60030, 0x30c20008,
-0x1040000e, 0x0, 0x8f620058, 0x16420004,
-0x30c600ff, 0x9742011a, 0x50400001, 0x34c60010,
-0x93c50008, 0x8fa70034, 0x2002021, 0x52b00,
-0x34a50080, 0xe000c8d, 0x30a5f080, 0x8f620040,
-0x561023, 0x18400017, 0x8fa20018, 0x3c020800,
-0x8c423198, 0x30420010, 0x10400009, 0x24020001,
-0x97620068, 0x14400006, 0x24020001, 0xa7620068,
-0x9742007a, 0x2442000a, 0xa000e47, 0xa7620012,
-0xa7620012, 0xe0011b3, 0x2002021, 0x9362007d,
-0x24030001, 0x2002021, 0x34420001, 0xa000e45,
-0xafa30038, 0x1840000a, 0x0, 0xe0011b3,
+0x0, 0x80, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0xa, 0x0,
+0x0, 0x0, 0x10000003, 0x0,
+0xd, 0xd, 0x3c020800, 0x24427320,
+0x3c030800, 0x246377ac, 0xac400000, 0x43202b,
+0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc,
+0x3a0f021, 0x3c100800, 0x26103210, 0x3c1c0800,
+0x279c7320, 0xe0010fe, 0x0, 0xd,
+0x30a5ffff, 0x30c600ff, 0x27430180, 0x8f4201b8,
+0x440fffe, 0x24020002, 0xac640000, 0xa4650008,
+0xa066000a, 0xa062000b, 0x3c021000, 0xac670018,
+0x3e00008, 0xaf4201b8, 0x3c036000, 0x8c624ff8,
+0x440fffe, 0x3c020200, 0xac644fc0, 0xac624fc4,
+0x3c021000, 0x3e00008, 0xac624ff8, 0x9482000c,
+0x24860014, 0xa03821, 0x21302, 0x21080,
+0x824021, 0xc8102b, 0x10400057, 0x0,
+0x90c30000, 0x2c620009, 0x50400051, 0x90c20001,
+0x31080, 0x3c030800, 0x246372d0, 0x431021,
+0x8c420000, 0x400008, 0x0, 0x90c30001,
+0x2402000a, 0x1462003a, 0x0, 0x1061023,
+0x2c42000a, 0x14400036, 0x24c60002, 0x8ce20000,
+0x34420100, 0xace20000, 0x90c20000, 0x90c30001,
+0x90c40002, 0x90c50003, 0x31c00, 0x21600,
+0x431025, 0x42200, 0x441025, 0x451025,
+0x24c60004, 0xace20004, 0x90c20000, 0x90c30001,
+0x90c40002, 0x90c50003, 0x21600, 0x31c00,
+0x431025, 0x42200, 0x441025, 0x451025,
+0x24c60004, 0xa000cb8, 0xace20008, 0x90c30001,
+0x24020004, 0x14620016, 0x24c60002, 0x90c20000,
+0x90c40001, 0x8ce30000, 0x21200, 0x441025,
+0x34630004, 0x24c60002, 0xace2000c, 0xa000cb8,
+0xace30000, 0x90c30001, 0x24020003, 0x14620008,
+0x24c60002, 0x8ce20000, 0x90c30000, 0x24c60001,
+0x34420008, 0xa0e30010, 0xa000cb8, 0xace20000,
+0x3e00008, 0x24020001, 0x90c30001, 0x24020002,
+0x10620002, 0x24c40002, 0x1002021, 0xa000cb8,
+0x803021, 0xa000cb8, 0x24c60001, 0x90c20001,
+0xa000cb8, 0xc23021, 0x3e00008, 0x1021,
+0x27bdffe8, 0xafbf0014, 0xafb00010, 0xe001302,
+0x808021, 0x93620005, 0x2403fffe, 0x2002021,
+0x431024, 0x8fbf0014, 0x8fb00010, 0xa3620005,
+0xa00130b, 0x27bd0018, 0x27bdffe8, 0xafb00010,
+0xafbf0014, 0xe000f3c, 0x808021, 0x93620000,
+0x24030050, 0x304200ff, 0x14430004, 0x24020100,
+0xaf420180, 0xa000d30, 0x2002021, 0xaf400180,
+0x2002021, 0x8fbf0014, 0x8fb00010, 0xa000fe7,
+0x27bd0018, 0x27bdff80, 0xafbe0078, 0xafb70074,
+0xafb20060, 0xafbf007c, 0xafb60070, 0xafb5006c,
+0xafb40068, 0xafb30064, 0xafb1005c, 0xafb00058,
+0x8f500128, 0x3c020800, 0x8c4231a0, 0x2403ff80,
+0x9365003f, 0x2021021, 0x431024, 0xaf420024,
+0x3c020800, 0x8c4231a0, 0x93640005, 0x30b200ff,
+0x2021021, 0x3042007f, 0x3421821, 0x42027,
+0x3c02000a, 0x621821, 0x30840001, 0xaf830014,
+0xf021, 0xb821, 0x14800053, 0xafa00050,
+0x93430116, 0x93440112, 0x8f450104, 0x306300ff,
+0x3c020001, 0x308400ff, 0xa22824, 0x3431021,
+0x3441821, 0x24564000, 0x24674000, 0x14a001cd,
+0x24020001, 0x93620000, 0x304300ff, 0x24020020,
+0x10620005, 0x24020050, 0x10620006, 0x0,
+0xa000d74, 0x0, 0xd, 0xa000d7d,
+0xafa00030, 0x3c1e0800, 0x27de736c, 0xa000d7d,
+0xafa00030, 0x3c020800, 0x8c4200dc, 0x24420001,
+0x3c010800, 0xac2200dc, 0xe00139f, 0x0,
+0xa000f31, 0x8fbf007c, 0x8f420104, 0x3c030020,
+0x92d3000d, 0x431024, 0x2202b, 0x42140,
+0xafa40030, 0x8f430104, 0x3c020040, 0x621824,
+0x14600002, 0x34850040, 0x802821, 0x32620020,
+0xafa50030, 0x14400002, 0x34a60080, 0xa03021,
+0x10c0000b, 0xafa60030, 0x93c50008, 0x8f67004c,
+0x2002021, 0x52b00, 0x34a50081, 0x30a5f081,
+0xe000c9b, 0x30c600ff, 0xa000f2e, 0x0,
+0x9362003e, 0x30420040, 0x1040000f, 0x24020004,
+0x56420007, 0x24020012, 0x2002021, 0xe02821,
+0xe0013f7, 0x2c03021, 0xa000f31, 0x8fbf007c,
+0x16420005, 0x0, 0xe000d21, 0x2021,
+0xa000f31, 0x8fbf007c, 0x9743011a, 0x96c4000e,
+0x93620035, 0x32650004, 0x3075ffff, 0x442004,
+0xafa40054, 0x8ed10004, 0x10a00015, 0x8ed40008,
+0x9362003e, 0x30420040, 0x10400007, 0x0,
+0xe0013e0, 0x2202021, 0x1040000d, 0x0,
+0xa000f2e, 0x0, 0x8f620044, 0x2221023,
+0x440016a, 0x0, 0x8f620048, 0x2221023,
+0x4410166, 0x24040016, 0xa000e21, 0x8fc20004,
+0x8f620048, 0x2221023, 0x4400008, 0x0,
+0x3c020800, 0x8c423100, 0x24420001, 0x3c010800,
+0xac223100, 0xa000f23, 0x0, 0x8f620040,
+0x2221023, 0x18400012, 0x8f840014, 0x3c020800,
+0x8c423100, 0x327300fc, 0xa821, 0x24420001,
+0x3c010800, 0xac223100, 0x8f630040, 0x9482011c,
+0x2231823, 0x3042ffff, 0x43102a, 0x50400010,
+0x2402000c, 0x8f620040, 0xa000df2, 0x2221023,
+0x9483011c, 0x9762003c, 0x43102b, 0x10400006,
+0x0, 0x9482011c, 0x551023, 0xa482011c,
+0xa000df7, 0x2402000c, 0xa480011c, 0x2402000c,
+0xafa20030, 0x8f620040, 0x512023, 0x1880000d,
+0x2a4102a, 0x14400126, 0x0, 0x14950006,
+0x2a41023, 0x3a620001, 0x30420001, 0x14400120,
+0x0, 0x2a41023, 0x2248821, 0xa000e09,
+0x3055ffff, 0x2021, 0x32620002, 0x1040001a,
+0x32620010, 0x9362003e, 0x30420040, 0x50400011,
+0x8fc20004, 0xe001302, 0x2002021, 0x24020018,
+0xa362003f, 0x93620005, 0x2403fffe, 0x2002021,
+0x431024, 0xe00130b, 0xa3620005, 0x24040039,
+0x2821, 0xe0013c9, 0x24060018, 0xa000f30,
+0x24020001, 0x24040017, 0x40f809, 0x0,
+0xa000f30, 0x24020001, 0x10400108, 0x0,
+0x8f63004c, 0x8f620054, 0x2821023, 0x1c400103,
+0x2831023, 0x4420001, 0x60a021, 0xafa40018,
+0xafb10010, 0xafb50014, 0x93420120, 0x8f650040,
+0x9763003c, 0x304200ff, 0x3421021, 0x441021,
+0x8fa40054, 0x3063ffff, 0x24424000, 0x83182b,
+0x8fa40030, 0xafa20020, 0xafa50028, 0x832025,
+0xafa40030, 0xafa50024, 0xafa0002c, 0xafb40034,
+0x9362003e, 0x30420008, 0x50400011, 0x8fc20000,
+0x2c02021, 0x27a50038, 0xe000cb2, 0xafa00038,
+0x5440000b, 0x8fc20000, 0x8fa20038, 0x30420100,
+0x50400007, 0x8fc20000, 0x8fa3003c, 0x8f620060,
+0x621023, 0x4430001, 0xaf630060, 0x8fc20000,
+0x40f809, 0x27a40010, 0x8fa20030, 0x30420002,
+0x54400001, 0x327300fe, 0x9362003e, 0x30420040,
+0x10400037, 0x8fa20024, 0x8f620054, 0x1682001a,
+0x32620001, 0x24020014, 0x12420010, 0x2a420015,
+0x10400006, 0x24020016, 0x2402000c, 0x12420007,
+0x32620001, 0xa000e7d, 0x0, 0x12420005,
+0x32620001, 0xa000e7d, 0x0, 0xa000e78,
+0x2417000e, 0xa000e78, 0x24170010, 0xa000e7c,
+0x24170012, 0x93620023, 0x2403ffbd, 0x431024,
+0xa3620023, 0x32620001, 0x10400019, 0x8fa20024,
+0x2402000c, 0x1242000e, 0x2a42000d, 0x10400006,
+0x2402000e, 0x2402000a, 0x12420007, 0x8fa20024,
+0xa000e95, 0x24420001, 0x12420008, 0x8fa20024,
+0xa000e95, 0x24420001, 0xa000e93, 0x24170008,
+0x2402000e, 0x16e20002, 0x24170016, 0x24170010,
+0x8fa20024, 0x24420001, 0xafa20024, 0x8fa20024,
+0x8fa30014, 0x8f760040, 0x431021, 0xaf620040,
+0x8f820014, 0x9442011c, 0x10400009, 0x0,
+0x8f620048, 0x8f640040, 0x9763003c, 0x441023,
+0x3063ffff, 0x43102a, 0x10400008, 0x8fa20054,
+0x93640036, 0x8f630040, 0x3402fffc, 0x821004,
+0x621821, 0xaf630048, 0x8fa20054, 0x8fa60030,
+0x2829021, 0x30c20008, 0x1040000e, 0x0,
+0x8f620058, 0x16420004, 0x30c600ff, 0x9742011a,
+0x50400001, 0x34c60010, 0x93c50008, 0x8fa70034,
+0x2002021, 0x52b00, 0x34a50080, 0xe000c9b,
+0x30a5f080, 0x8f620040, 0x561023, 0x1840001b,
+0x8fa20018, 0x3c020800, 0x8c423198, 0x30420010,
+0x1040000d, 0x24020001, 0x97620068, 0x1440000a,
+0x24020001, 0x8f820014, 0x9442011c, 0x14400006,
+0x24020001, 0xa7620068, 0x9742007a, 0x24420064,
+0xa000ee9, 0xa7620012, 0xa7620012, 0xe001302,
0x2002021, 0x9362007d, 0x24030001, 0x2002021,
-0xafa30038, 0x34420004, 0xe0011bc, 0xa362007d,
-0x9362003e, 0x30420040, 0x1440000c, 0x32620001,
-0x1040000a, 0x0, 0x8f630040, 0x8fc20004,
-0x24040018, 0x24630001, 0x40f809, 0xaf630040,
-0x8fa20030, 0xa000e8e, 0x30420004, 0x8f620058,
-0x10520010, 0x0, 0x8f620018, 0x2221023,
-0x1c400008, 0x24020001, 0x8f620018, 0x16220009,
-0x0, 0x8f62001c, 0x2821023, 0x4400005,
-0x24020001, 0xaf720058, 0xafa20038, 0xaf710018,
-0xaf74001c, 0x12e0000b, 0x8fa30038, 0xe0011b3,
-0x2002021, 0xa377003f, 0xe0011bc, 0x2002021,
-0x2e03021, 0x24040037, 0xe001324, 0x2821,
-0x8fa30038, 0x10600003, 0x0, 0xe000c9b,
-0x2002021, 0x12a00005, 0x1821, 0x8fa20030,
-0x30420004, 0x50400011, 0x601021, 0x24030001,
-0xa000e8e, 0x601021, 0xe0011b3, 0x2002021,
-0x9362007d, 0x2002021, 0x34420004, 0xe0011bc,
-0xa362007d, 0xe000c9b, 0x2002021, 0xa000e8e,
-0x24020001, 0xaf400044, 0x24020001, 0x8fbf0064,
-0x8fbe0060, 0x8fb7005c, 0x8fb60058, 0x8fb50054,
-0x8fb40050, 0x8fb3004c, 0x8fb20048, 0x8fb10044,
-0x8fb00040, 0x3e00008, 0x27bd0068, 0x8c870004,
-0x8c860000, 0x1021, 0xe53821, 0xe5282b,
-0xc23021, 0xc53021, 0xac870004, 0x3e00008,
-0xac860000, 0x8f4201b8, 0x440fffe, 0x24020800,
+0x34420001, 0xa000ee7, 0xafa30050, 0x1840000a,
+0x0, 0xe001302, 0x2002021, 0x9362007d,
+0x24030001, 0x2002021, 0xafa30050, 0x34420004,
+0xe00130b, 0xa362007d, 0x9362003e, 0x30420040,
+0x1440000c, 0x32620001, 0x1040000a, 0x0,
+0x8f630040, 0x8fc20004, 0x24040018, 0x24630001,
+0x40f809, 0xaf630040, 0x8fa20030, 0xa000f30,
+0x30420004, 0x8f620058, 0x10520010, 0x0,
+0x8f620018, 0x2221023, 0x1c400008, 0x24040001,
+0x8f620018, 0x16220009, 0x0, 0x8f62001c,
+0x2821023, 0x4400005, 0x0, 0xaf720058,
+0xafa40050, 0xaf710018, 0xaf74001c, 0x12e0000b,
+0x8fa20050, 0xe001302, 0x2002021, 0xa377003f,
+0xe00130b, 0x2002021, 0x2e03021, 0x24040037,
+0xe0013c9, 0x2821, 0x8fa20050, 0x10400003,
+0x0, 0xe000ca9, 0x2002021, 0x12a00005,
+0x1821, 0x8fa20030, 0x30420004, 0x50400011,
+0x601021, 0x24030001, 0xa000f30, 0x601021,
+0xe001302, 0x2002021, 0x9362007d, 0x2002021,
+0x34420004, 0xe00130b, 0xa362007d, 0xe000ca9,
+0x2002021, 0xa000f30, 0x24020001, 0xaf400044,
+0x24020001, 0x8fbf007c, 0x8fbe0078, 0x8fb70074,
+0x8fb60070, 0x8fb5006c, 0x8fb40068, 0x8fb30064,
+0x8fb20060, 0x8fb1005c, 0x8fb00058, 0x3e00008,
+0x27bd0080, 0x8f4201b8, 0x440fffe, 0x24020800,
0xaf4201b8, 0x3e00008, 0x0, 0x3c020008,
-0x3422821, 0x94a20048, 0x3084ffff, 0x1040001b,
-0x24840012, 0x94a20048, 0x3042ffff, 0x44102a,
-0x10400017, 0x24020003, 0x2402001a, 0x93430120,
-0xa342018b, 0x8f820008, 0x306300ff, 0x30424000,
-0x10400009, 0x2463fffe, 0x94a20048, 0x3042ffff,
-0x43102b, 0x14400005, 0x8f820014, 0xa7430194,
-0xa000ec8, 0x34420001, 0x8f820014, 0x2403fffe,
-0x431024, 0x3e00008, 0xaf820014, 0x24020003,
-0x3e00008, 0xa342018b, 0x27bdffe0, 0xafb20018,
-0xafb10014, 0xafb00010, 0xafbf001c, 0x30b1ffff,
-0x30d0ffff, 0x30f2ffff, 0x8f4201b8, 0x440fffe,
-0x0, 0xaf440180, 0xaf440020, 0xe000eaa,
-0x2002021, 0x8f830008, 0x8f840014, 0xa751018c,
-0xa750018e, 0xa7430190, 0x8f830004, 0x30828000,
-0xaf4301a8, 0xa7520188, 0x1040000e, 0x8f820014,
+0x3421021, 0x94420048, 0x3084ffff, 0x24840012,
+0x3045ffff, 0x10a00017, 0xa4102b, 0x10400016,
+0x24020003, 0x93420120, 0x2403001a, 0xa343018b,
+0x304200ff, 0x2446fffe, 0x8f820000, 0xa6182b,
+0x38630001, 0x21382, 0x431024, 0x10400005,
+0x8f840004, 0x34820001, 0xa7460194, 0x3e00008,
+0xaf820004, 0x2402fffe, 0x821024, 0x3e00008,
+0xaf820004, 0x24020003, 0x3e00008, 0xa342018b,
+0x27bdffe0, 0xafb10014, 0xafb00010, 0xafbf0018,
+0x30b0ffff, 0x30d1ffff, 0x8f4201b8, 0x440fffe,
+0x0, 0xaf440180, 0xaf440020, 0xe000f42,
+0x2002021, 0x8f830000, 0x8f840004, 0xa750019a,
+0xa750018e, 0xa7430190, 0x8f830008, 0x30828000,
+0xaf4301a8, 0xa7510188, 0x1040000e, 0x8f820004,
0x93420116, 0x304200fc, 0x24420004, 0x5a1021,
-0x8c424000, 0x3042ffff, 0x14400006, 0x8f820014,
-0x3c02ffff, 0x34427fff, 0x821024, 0xaf820014,
-0x8f820014, 0x2403bfff, 0x431024, 0xa74201a6,
+0x8c424000, 0x3042ffff, 0x14400006, 0x8f820004,
+0x3c02ffff, 0x34427fff, 0x821024, 0xaf820004,
+0x8f820004, 0x2403bfff, 0x431024, 0xa74201a6,
0x9743010c, 0x8f420104, 0x31c00, 0x3042ffff,
0x621825, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018,
-0x30d2ffff, 0xaf440180, 0xaf440020, 0x2402021,
-0xafb10014, 0xafb00010, 0x30f1ffff, 0xafbf001c,
-0xe000eaa, 0x30b0ffff, 0x8f830014, 0x2402bfff,
-0xa750018c, 0x621824, 0x8f820008, 0xa752018e,
-0xa7510188, 0xa74301a6, 0xa7420190, 0x3c021000,
-0xaf4201b8, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0020, 0x27430180,
-0x8f4201b8, 0x440fffe, 0x24022000, 0xa4620008,
-0x24020002, 0xa062000b, 0xa4600010, 0x3c021000,
-0xaf4201b8, 0x3e00008, 0x0, 0x8f470070,
-0x93420112, 0x8f830008, 0x27bdfff0, 0x304200ff,
-0x22882, 0x30620100, 0x3021, 0x10400043,
-0x24a40003, 0x30624000, 0x10400010, 0x30622000,
-0x41080, 0x5a1021, 0x8c434000, 0x24a40004,
-0x41080, 0xafa30000, 0x5a1021, 0x8c424000,
-0xafa20004, 0x93420116, 0x304200fc, 0x5a1021,
-0x8c424000, 0xa000f56, 0xafa20008, 0x1040002f,
-0x3021, 0x41080, 0x5a1021, 0x8c434000,
-0x24a40004, 0x41080, 0xafa30000, 0x5a1021,
-0x8c424000, 0xafa00008, 0xafa20004, 0x8fa80008,
-0x3021, 0x2021, 0x240a0008, 0x3c090800,
-0x25290100, 0x3a41021, 0x148a0003, 0x42a00,
-0x1100000a, 0x0, 0x90420000, 0x24840001,
-0x2c83000c, 0xa21021, 0x21080, 0x491021,
-0x8c420000, 0x1460fff3, 0xc23026, 0x3c040800,
-0x8c843104, 0x8f420070, 0x2c830020, 0x10600009,
-0x473823, 0x3c030800, 0x24633108, 0x41080,
-0x431021, 0x24830001, 0xac470000, 0x3c010800,
-0xac233104, 0xaf860004, 0x24060001, 0xc01021,
-0x3e00008, 0x27bd0010, 0x3c020800, 0x8c420038,
-0x27bdffd0, 0xafb50024, 0xafb3001c, 0xafbf0028,
-0xafb40020, 0xafb20018, 0xafb10014, 0xafb00010,
-0x3c150800, 0x26b50038, 0x14400002, 0x2453ffff,
-0x9821, 0x8f840008, 0x30824000, 0x1040000a,
-0x30828000, 0x3c020020, 0x821024, 0x50400006,
-0x30828000, 0x8f820014, 0x2403bfff, 0x831824,
-0xa000fa2, 0x34421000, 0x1040000a, 0x3c020020,
-0x821024, 0x10400007, 0x8f820014, 0x3c03ffff,
-0x34637fff, 0x831824, 0x34428000, 0xaf820014,
-0xaf830008, 0xe000f2e, 0x0, 0x14400008,
-0x8f840008, 0x9743011e, 0x9742011c, 0x3063ffff,
-0x21400, 0x621825, 0xaf830004, 0x8f840008,
-0x9742010c, 0x30831000, 0x10600011, 0x3046ffff,
-0x30820020, 0x1440000f, 0x24120005, 0x3c021000,
-0x821024, 0x1040000b, 0x24120001, 0x3c030e00,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x8f470070, 0x93420112, 0x8f830000,
+0x27bdfff0, 0x304200ff, 0x22882, 0x30620100,
+0x3021, 0x10400043, 0x24a40003, 0x30624000,
+0x10400010, 0x30622000, 0x41080, 0x5a1021,
+0x8c434000, 0x24a40004, 0x41080, 0xafa30000,
+0x5a1021, 0x8c424000, 0xafa20004, 0x93420116,
+0x304200fc, 0x5a1021, 0x8c424000, 0xa000fc0,
+0xafa20008, 0x1040002f, 0x3021, 0x41080,
+0x5a1021, 0x8c434000, 0x24a40004, 0x41080,
+0xafa30000, 0x5a1021, 0x8c424000, 0xafa00008,
+0xafa20004, 0x8fa80008, 0x3021, 0x2021,
+0x240a0008, 0x3c090800, 0x25290100, 0x3a41021,
+0x148a0003, 0x42a00, 0x1100000a, 0x0,
+0x90420000, 0x24840001, 0x2c83000c, 0xa21021,
+0x21080, 0x491021, 0x8c420000, 0x1460fff3,
+0xc23026, 0x3c040800, 0x8c843104, 0x8f420070,
+0x2c830020, 0x10600009, 0x473823, 0x3c030800,
+0x24633108, 0x41080, 0x431021, 0x24830001,
+0xac470000, 0x3c010800, 0xac233104, 0xaf860008,
+0x24060001, 0xc01021, 0x3e00008, 0x27bd0010,
+0x3c020800, 0x8c420038, 0x27bdffd0, 0xafb50024,
+0xafb40020, 0xafb10014, 0xafbf0028, 0xafb3001c,
+0xafb20018, 0xafb00010, 0x8821, 0x3c150800,
+0x26b50038, 0x14400002, 0x2454ffff, 0xa021,
+0x9742010e, 0x8f840000, 0x3042ffff, 0x30834000,
+0x1060000a, 0x24520004, 0x3c020020, 0x821024,
+0x50400007, 0x30828000, 0x8f820004, 0x2403bfff,
+0x831824, 0xa001010, 0x34421000, 0x30828000,
+0x1040000a, 0x3c020020, 0x821024, 0x10400007,
+0x8f820004, 0x3c03ffff, 0x34637fff, 0x831824,
+0x34428000, 0xaf820004, 0xaf830000, 0xe000f98,
+0x0, 0x14400007, 0x0, 0x9743011e,
+0x9742011c, 0x3063ffff, 0x21400, 0x621825,
+0xaf830008, 0x9742010c, 0x8f434000, 0x3045ffff,
+0x3402ffff, 0x14620003, 0x0, 0xa001028,
+0x24110020, 0x8f424000, 0x30420100, 0x54400001,
+0x24110010, 0x8f840000, 0x30821000, 0x50400014,
+0x36310001, 0x30820020, 0x1440000b, 0x3c021000,
+0x821024, 0x5040000e, 0x36310001, 0x3c030e00,
0x3c020dff, 0x831824, 0x3442ffff, 0x43102b,
-0x10400004, 0x0, 0xa000fc4, 0x24120005,
-0x24120001, 0x3c050800, 0x8ca50034, 0x54a00019,
-0x8f840008, 0x8f82001c, 0x54400016, 0x8f840008,
-0x8f820014, 0x30424000, 0x54400012, 0x8f840008,
-0x3c021f01, 0x821024, 0x3c031000, 0x1443000d,
-0x8f840008, 0x30c20200, 0x1440000b, 0x3c020001,
-0x9746010e, 0x36470002, 0x2021, 0x24c60004,
-0x30c6ffff, 0xe000f05, 0x24050002, 0xa00108d,
-0x8fbf0028, 0x3c020001, 0x821024, 0x1040000c,
-0x8f830014, 0x3c020800, 0x8c4200d8, 0x9746010e,
-0x24040080, 0x24420001, 0x30c6ffff, 0x24050002,
-0x3c010800, 0xac2200d8, 0xa00108a, 0x24070003,
-0x30624000, 0x10400006, 0x3c021000, 0x3c020f00,
-0x821024, 0x50400001, 0x93420116, 0x3c021000,
-0x821024, 0x10400044, 0x0, 0x3c020800,
-0x8c420030, 0x1040000c, 0x30624000, 0x1040000a,
-0x3c030f00, 0x831824, 0x3c020100, 0x43102b,
-0x14400005, 0x0, 0x9746010e, 0x36470002,
-0xa001087, 0x24040080, 0x10a0000d, 0x30820100,
-0x1040000b, 0x3c020f00, 0x821024, 0x3c030200,
-0x10430007, 0x8f820004, 0x531024, 0x551021,
-0x90420004, 0x24420004, 0xa00103a, 0x221c0,
-0x0, 0x8f860008, 0x3c050800, 0x8ca500d0,
-0x61602, 0x3050000f, 0x38a20001, 0x2c420001,
-0x2e03000c, 0x431024, 0x14400018, 0x1021c0,
-0x2602fffc, 0x2c420004, 0x54400014, 0x2021,
-0x38a20002, 0x2c420001, 0x431024, 0x10400003,
-0x61242, 0xa00103a, 0x2021, 0x10182b,
-0x431024, 0x50400009, 0x1021c0, 0x9746010e,
-0x2021, 0x24050002, 0x24c60004, 0x30c6ffff,
-0xe000ecd, 0x3247fffb, 0x1021c0, 0x9746010e,
-0xa001087, 0x36470002, 0x8f424000, 0x3c110800,
-0x8e310024, 0x30420100, 0x10400040, 0x32220001,
-0x2208021, 0x10a00017, 0x32540004, 0x30820100,
-0x10400015, 0x24020001, 0x3c020f00, 0x821024,
-0x3c030200, 0x1043000f, 0x8f820004, 0x9746010e,
-0x2403821, 0x531024, 0x551021, 0x90440004,
-0x24c60004, 0x30c6ffff, 0x24840004, 0x421c0,
-0xe000ecd, 0x24050002, 0x2402fffe, 0x2228024,
-0x3252fffb, 0x24020001, 0x16020007, 0x32020001,
-0x32420004, 0x50400001, 0x36520002, 0x9746010e,
-0xa001086, 0x2403821, 0x1040000a, 0x32020004,
-0x9746010e, 0x2403821, 0x2021, 0x24c60004,
-0x30c6ffff, 0xe000ecd, 0x24050002, 0x3252fffb,
-0x32020004, 0x1040000b, 0x8f820008, 0x30420800,
-0x10400008, 0x0, 0x9746010e, 0x2403821,
-0x24040100, 0x24c60004, 0x30c6ffff, 0xe000ecd,
-0x24050002, 0x56800010, 0x8fbf0028, 0xe000f22,
-0x0, 0xa00108d, 0x8fbf0028, 0x1040000a,
-0x8fbf0028, 0x9746010e, 0x36470002, 0x2021,
-0x24c60004, 0x30c6ffff, 0x24050002, 0xe000ecd,
-0x0, 0x8fbf0028, 0x8fb50024, 0x8fb40020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x1021, 0x3e00008, 0x27bd0030, 0x27430180,
-0x8f4201b8, 0x440fffe, 0x0, 0x8f420148,
-0x21402, 0xa4620008, 0x24020002, 0xa062000b,
-0x8f420148, 0xa4620010, 0x8f420144, 0xac620024,
-0x3c021000, 0x3e00008, 0xaf4201b8, 0x27bdffe8,
-0xafb00010, 0x3c04600c, 0xafbf0014, 0x8c825000,
-0x2403ff7f, 0x3c1a8000, 0x431024, 0x3442380c,
-0xac825000, 0x24020003, 0x3c106000, 0xaf420008,
-0x8e020808, 0x3c1b8008, 0x3c010800, 0xac200020,
-0x3042fff0, 0x38420010, 0x2c420001, 0xe001b39,
-0xaf820000, 0x3c04ffff, 0x3c020400, 0x34830806,
-0x3442000c, 0xae021948, 0xae03194c, 0x3c056016,
-0x8e021980, 0x8ca30000, 0x34420200, 0x641824,
-0xae021980, 0x3c025353, 0x14620003, 0x34a47c00,
-0x8ca20004, 0x502021, 0x8c82007c, 0x8c830078,
-0x8fbf0014, 0x8fb00010, 0x27bd0018, 0xaf820018,
-0x3e00008, 0xaf830010, 0x27bdffe8, 0xafbf0010,
-0x8f434000, 0x3402ffff, 0x3c040800, 0x248400f0,
-0x10620007, 0x0, 0x8f424000, 0x3c040800,
-0x248400e8, 0x30420100, 0x10400009, 0x0,
-0x9745010e, 0xe000e9a, 0x30a5ffff, 0x9745010e,
-0x3c040800, 0x248431c8, 0xa0010fc, 0x8fbf0010,
-0x8f434000, 0x8f820010, 0x3c040800, 0x248400e0,
-0x1462000a, 0x0, 0x8f434004, 0x8f820018,
-0x14620006, 0x0, 0x9745010e, 0x3c040800,
-0x248431b8, 0xa0010fc, 0x8fbf0010, 0x9745010e,
-0x8fbf0010, 0x30a5ffff, 0xa000e9a, 0x27bd0018,
-0x27bdffe8, 0xafbf0010, 0x8f420128, 0xaf420020,
-0x8f420104, 0x8f430100, 0xaf820008, 0xe000ea4,
-0xaf830014, 0xe0010d5, 0x0, 0x3c020800,
-0x8c4200c0, 0x10400008, 0x8f840008, 0x3c020800,
-0x8c4200c4, 0x24420001, 0x3c010800, 0xac2200c4,
-0xa001135, 0x0, 0x3c020010, 0x821024,
-0x1440000a, 0x8f830014, 0x3c020800, 0x8c420020,
-0x24420001, 0x3c010800, 0xac220020, 0xe000f7d,
-0x2021, 0xa001133, 0x0, 0x2402bfff,
+0x50400007, 0x36310001, 0x3c020800, 0x8c42002c,
+0x24420001, 0x3c010800, 0xac22002c, 0x36310005,
+0x3c060800, 0x8cc60034, 0x54c00023, 0x8f850000,
+0x8f820004, 0x30424000, 0x5440001f, 0x8f850000,
+0x3c021f01, 0x821024, 0x3c031000, 0x5443001a,
+0x8f850000, 0x30a20200, 0x14400017, 0x8f850000,
+0x3250ffff, 0x36310002, 0x8f4201b8, 0x440fffe,
+0x0, 0xaf400180, 0x2002021, 0xe000f42,
+0xaf400020, 0x8f830004, 0x2402bfff, 0xa750019a,
+0x621824, 0x8f820000, 0xa750018e, 0xa7510188,
+0xa74301a6, 0xa7420190, 0x3c021000, 0xaf4201b8,
+0xa0010f5, 0x1021, 0x3c021000, 0xa21024,
+0x1040003a, 0x0, 0x10c0000f, 0x0,
+0x30a20100, 0x1040000c, 0x3c030200, 0x3c020f00,
+0xa21024, 0x10430008, 0x0, 0x8f820008,
+0x541024, 0x551021, 0x90420004, 0x24420004,
+0xa00109f, 0x221c0, 0x0, 0x51602,
+0x3050000f, 0x3a030002, 0x2e4203ef, 0x38420001,
+0x2c630001, 0x621824, 0x14600073, 0x24020001,
+0x3c030800, 0x8c6300d0, 0x2e06000c, 0x38620001,
+0x2c420001, 0x461024, 0x14400015, 0x1021c0,
+0x2602fffc, 0x2c420004, 0x54400011, 0x2021,
+0x38620002, 0x2c420001, 0x461024, 0x10400003,
+0x51242, 0xa00109f, 0x2021, 0x10182b,
+0x431024, 0x50400006, 0x1021c0, 0x2021,
+0x3245ffff, 0xe000f63, 0x3226fffb, 0x1021c0,
+0x3245ffff, 0xa0010f2, 0x36260002, 0x8f424000,
+0x3c030800, 0x8c630024, 0x30420100, 0x10400046,
+0x30620001, 0x32220004, 0x3070000d, 0x14400002,
+0x24130004, 0x24130002, 0x512c2, 0x38420001,
+0x2e4303ef, 0x30420001, 0x38630001, 0x431025,
+0x10400003, 0x3231fffb, 0x2402fffb, 0x2028024,
+0x10c00018, 0x32020001, 0x30a20100, 0x10400015,
+0x32020001, 0x3c020f00, 0xa21024, 0x3c030200,
+0x1043000f, 0x8f820008, 0x2403fffe, 0x2038024,
+0x541024, 0x551021, 0x90420004, 0x2333025,
+0x24420004, 0x12000002, 0x221c0, 0x3226ffff,
+0xe000f63, 0x3245ffff, 0x12000027, 0x1021,
+0x32020001, 0x1040000d, 0x32020004, 0x24020001,
+0x12020002, 0x2333025, 0x3226ffff, 0x2021,
+0xe000f63, 0x3245ffff, 0x2402fffe, 0x2028024,
+0x12000019, 0x1021, 0x32020004, 0x10400016,
+0x24020001, 0x24020004, 0x12020002, 0x2333025,
+0x3226ffff, 0x3245ffff, 0xe000f63, 0x24040100,
+0x2402fffb, 0x2028024, 0x1200000b, 0x1021,
+0xa0010f5, 0x24020001, 0x10400007, 0x1021,
+0x3245ffff, 0x36260002, 0x2021, 0xe000f63,
+0x0, 0x1021, 0x8fbf0028, 0x8fb50024,
+0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0030, 0x27bdffd0,
+0xafb00010, 0x3c04600c, 0xafbf002c, 0xafb60028,
+0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018,
+0xafb10014, 0x8c825000, 0x2403ff7f, 0x3c1a8000,
+0x431024, 0x3442380c, 0xac825000, 0x24020003,
+0x3c106000, 0xaf420008, 0x8e020808, 0x3c1b8008,
+0x3c010800, 0xac200020, 0x3042fff0, 0x38420010,
+0x2c420001, 0xe001b85, 0xaf820018, 0x3c04ffff,
+0x3c020400, 0x34830806, 0x3442000c, 0xae021948,
+0xae03194c, 0x3c056016, 0x8e021980, 0x8ca30000,
+0x34420200, 0x641824, 0xae021980, 0x3c025353,
+0x14620003, 0x34a47c00, 0x8ca20004, 0x502021,
+0x8c82007c, 0x8c830078, 0xaf820010, 0xaf83000c,
+0x8f550000, 0x32a20003, 0x1040fffd, 0x32a20001,
+0x1040013d, 0x32a20002, 0x8f420128, 0xaf420020,
+0x8f420104, 0x8f430100, 0xaf820000, 0xe000f3c,
+0xaf830004, 0x3c020800, 0x8c4200c0, 0x10400008,
+0x8f840000, 0x3c020800, 0x8c4200c4, 0x24420001,
+0x3c010800, 0xac2200c4, 0xa001269, 0x0,
+0x3c020010, 0x821024, 0x1440010c, 0x8f830004,
+0x3c020800, 0x8c420020, 0x3c030800, 0x8c630038,
+0x8821, 0x24420001, 0x3c010800, 0xac220020,
+0x3c160800, 0x26d60038, 0x14600002, 0x2474ffff,
+0xa021, 0x9742010e, 0x30834000, 0x3042ffff,
+0x1060000a, 0x24520004, 0x3c020020, 0x821024,
+0x50400007, 0x30828000, 0x8f820004, 0x2403bfff,
+0x831824, 0xa001170, 0x34421000, 0x30828000,
+0x1040000a, 0x3c020020, 0x821024, 0x10400007,
+0x8f820004, 0x3c03ffff, 0x34637fff, 0x831824,
+0x34428000, 0xaf820004, 0xaf830000, 0xe000f98,
+0x0, 0x14400007, 0x0, 0x9743011e,
+0x9742011c, 0x3063ffff, 0x21400, 0x621825,
+0xaf830008, 0x9742010c, 0x8f434000, 0x3045ffff,
+0x3402ffff, 0x14620003, 0x0, 0xa001188,
+0x24110020, 0x8f424000, 0x30420100, 0x54400001,
+0x24110010, 0x8f840000, 0x30821000, 0x50400014,
+0x36310001, 0x30820020, 0x1440000b, 0x3c021000,
+0x821024, 0x5040000e, 0x36310001, 0x3c030e00,
+0x3c020dff, 0x831824, 0x3442ffff, 0x43102b,
+0x50400007, 0x36310001, 0x3c020800, 0x8c42002c,
+0x24420001, 0x3c010800, 0xac22002c, 0x36310005,
+0x3c060800, 0x8cc60034, 0x54c00023, 0x8f850000,
+0x8f820004, 0x30424000, 0x5440001f, 0x8f850000,
+0x3c021f01, 0x821024, 0x3c031000, 0x5443001a,
+0x8f850000, 0x30a20200, 0x14400017, 0x8f850000,
+0x3250ffff, 0x36310002, 0x8f4201b8, 0x440fffe,
+0x0, 0xaf400180, 0x2002021, 0xe000f42,
+0xaf400020, 0x8f830004, 0x2402bfff, 0xa750019a,
+0x621824, 0x8f820000, 0xa750018e, 0xa7510188,
+0xa74301a6, 0xa7420190, 0x3c021000, 0xaf4201b8,
+0xa001267, 0x1021, 0x3c021000, 0xa21024,
+0x1040003a, 0x0, 0x10c0000f, 0x0,
+0x30a20100, 0x1040000c, 0x3c030200, 0x3c020f00,
+0xa21024, 0x10430008, 0x0, 0x8f820008,
+0x541024, 0x561021, 0x90420004, 0x24420004,
+0xa0011ff, 0x221c0, 0x0, 0x51602,
+0x3050000f, 0x3a030002, 0x2e4203ef, 0x38420001,
+0x2c630001, 0x621824, 0x14600085, 0x24020001,
+0x3c030800, 0x8c6300d0, 0x2e06000c, 0x38620001,
+0x2c420001, 0x461024, 0x14400015, 0x1021c0,
+0x2602fffc, 0x2c420004, 0x54400011, 0x2021,
+0x38620002, 0x2c420001, 0x461024, 0x50400003,
+0x51242, 0xa0011ff, 0x2021, 0x10182b,
+0x431024, 0x50400006, 0x1021c0, 0x2021,
+0x3245ffff, 0xe000f63, 0x3226fffb, 0x1021c0,
+0x3245ffff, 0xa001252, 0x36260002, 0x8f424000,
+0x3c030800, 0x8c630024, 0x30420100, 0x10400046,
+0x30620001, 0x32220004, 0x3070000d, 0x14400002,
+0x24130004, 0x24130002, 0x512c2, 0x38420001,
+0x2e4303ef, 0x30420001, 0x38630001, 0x431025,
+0x10400003, 0x3231fffb, 0x2402fffb, 0x2028024,
+0x10c00018, 0x32020001, 0x30a20100, 0x10400015,
+0x32020001, 0x3c020f00, 0xa21024, 0x3c030200,
+0x1043000f, 0x8f820008, 0x2403fffe, 0x2038024,
+0x541024, 0x561021, 0x90420004, 0x2333025,
+0x24420004, 0x12000002, 0x221c0, 0x3226ffff,
+0xe000f63, 0x3245ffff, 0x12000039, 0x1021,
+0x32020001, 0x1040000d, 0x32020004, 0x24020001,
+0x12020002, 0x2333025, 0x3226ffff, 0x2021,
+0xe000f63, 0x3245ffff, 0x2402fffe, 0x2028024,
+0x1200002b, 0x1021, 0x32020004, 0x10400028,
+0x24020001, 0x24020004, 0x12020002, 0x2333025,
+0x3226ffff, 0x3245ffff, 0xe000f63, 0x24040100,
+0x2402fffb, 0x2028024, 0x1200001d, 0x1021,
+0xa001267, 0x24020001, 0x50400019, 0x1021,
+0x3245ffff, 0x36260002, 0x2021, 0xe000f63,
+0x0, 0xa001267, 0x1021, 0x2402bfff,
0x621024, 0x10400008, 0x0, 0x240287ff,
0x621024, 0x14400008, 0x3c020060, 0x821024,
-0x10400005, 0x0, 0xe000cc5, 0x0,
-0xa001133, 0x0, 0xe00119d, 0x0,
+0x10400005, 0x0, 0xe000d34, 0x0,
+0xa001267, 0x0, 0xe0012c7, 0x0,
0x10400006, 0x3c024000, 0x8f430124, 0x3c026020,
0xac430014, 0x0, 0x3c024000, 0xaf420138,
-0x0, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe8, 0xafbf0010, 0x8f420140, 0x3c044000,
-0xaf420020, 0x8f430148, 0x3c027000, 0x621824,
-0x10640010, 0x83102b, 0x14400006, 0x3c026000,
-0x3c022000, 0x10620007, 0x0, 0xa00115f,
-0x3c024000, 0x1062000b, 0x3c024000, 0xa00115f,
-0x0, 0xe001096, 0x0, 0xa00115f,
-0x3c024000, 0xe0011c1, 0x0, 0xa00115f,
-0x3c024000, 0xe001b46, 0x0, 0x3c024000,
-0xaf420178, 0x0, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x27bdffe8, 0xafbf0014, 0xe0010a6,
-0xafb00010, 0x3c028000, 0x34420070, 0x8c430000,
-0x403821, 0xaf830020, 0x603021, 0x8ce80000,
-0x3c050800, 0x8ca500fc, 0x3c040800, 0x8c8400f8,
-0x1063023, 0x1021, 0xa62821, 0xa6302b,
-0x822021, 0x862021, 0x3c010800, 0xac2500fc,
-0x3c010800, 0xac2400f8, 0x8f500000, 0x32020003,
-0x1040ffee, 0x1003021, 0x8ce60000, 0x3c050800,
-0x8ca500fc, 0x3c040800, 0x8c8400f8, 0xc83023,
-0xa62821, 0x1021, 0xa6302b, 0x822021,
-0x862021, 0x32070001, 0x3c010800, 0xac2500fc,
-0xaf880020, 0x3c010800, 0xac2400f8, 0x10e00004,
-0x32020002, 0xe0010ff, 0x0, 0x32020002,
-0x5040ffd1, 0x3c028000, 0xe00113f, 0x0,
-0xa001169, 0x3c028000, 0x8f420100, 0x3042003e,
-0x14400011, 0x24020001, 0xaf400048, 0x8f420100,
-0x304207c0, 0x10400005, 0x0, 0xaf40004c,
-0xaf400050, 0x3e00008, 0x24020001, 0xaf400054,
-0xaf400040, 0x8f420100, 0x30423800, 0x54400001,
-0xaf400044, 0x24020001, 0x3e00008, 0x0,
-0x3c029000, 0x34420001, 0x822025, 0xaf440020,
-0x8f420020, 0x440fffe, 0x0, 0x3e00008,
-0x0, 0x3c028000, 0x34420001, 0x822025,
-0x3e00008, 0xaf440020, 0x27bdffe0, 0xafb20018,
-0xafbf001c, 0xafb10014, 0xafb00010, 0x8f500140,
-0x8f510148, 0x3c028000, 0x119402, 0x2222024,
-0x324300ff, 0x2402000e, 0x1062008a, 0x2862000f,
-0x10400012, 0x28620037, 0x24020006, 0x1062003b,
-0x28620007, 0x10400007, 0x24020009, 0x1060001a,
-0x24020001, 0x10620025, 0x0, 0xa001276,
-0x0, 0x1062007b, 0x2402000b, 0x1062005b,
-0x3222ffff, 0xa001276, 0x0, 0x10400008,
-0x24020038, 0x28620035, 0x10400080, 0x2402001f,
-0x1062007e, 0x0, 0xa001276, 0x0,
-0x1062007a, 0x24020080, 0x10620042, 0x0,
-0xa001276, 0x0, 0x8f4201b8, 0x440fffe,
-0x24020001, 0xaf500180, 0xaf400184, 0xa7520188,
-0xa342018a, 0x24020002, 0xa342018b, 0xa7510190,
-0x8f420144, 0xa001271, 0xaf4201a4, 0x1080000a,
-0x24020002, 0x3c010800, 0xa0227178, 0x3c010800,
-0xac307180, 0x8f420144, 0x3c010800, 0xac22717c,
-0xa001278, 0x8fbf001c, 0x8f4201b8, 0x440fffe,
-0x24020002, 0xa00125b, 0x0, 0x8f4201b8,
-0x440fffe, 0x0, 0xaf500180, 0x3c020800,
-0x90427178, 0x10400003, 0x1821, 0x3c030800,
-0x8c637180, 0xaf430184, 0xa7520188, 0x3c020800,
-0x90427178, 0x1821, 0x34420001, 0xa342018a,
-0x24020002, 0xa342018b, 0xa7510190, 0x8f420144,
-0xaf4201a4, 0x3c020800, 0x90427178, 0x10400003,
-0x3c021000, 0x3c030800, 0x8c63717c, 0xaf4301a8,
-0xaf4201b8, 0x3c010800, 0xa0207178, 0xa001278,
-0x8fbf001c, 0x8f4201b8, 0x440fffe, 0x24020002,
-0xa342018b, 0xa7520188, 0xa7510190, 0x8f420144,
-0xa7420192, 0xa001273, 0x3c021000, 0x1440001d,
-0x0, 0x93620005, 0x30420004, 0x14400037,
-0x0, 0xe0011b3, 0x2002021, 0x93620005,
-0x2002021, 0x34420004, 0xe0011bc, 0xa3620005,
-0x93620005, 0x30420004, 0x14400002, 0x0,
-0xd, 0x93620000, 0x24030020, 0x304200ff,
-0x14430008, 0x0, 0x8f4201b8, 0x440fffe,
-0x24020005, 0xaf500180, 0xa342018b, 0x3c021000,
-0xaf4201b8, 0x8f4201b8, 0x440fffe, 0x24020002,
-0xaf400180, 0xaf500184, 0xa7520188, 0xa342018a,
-0xa342018b, 0xa7510190, 0xaf4001a4, 0x8f420144,
-0xaf4201a8, 0xa001273, 0x3c021000, 0x8f4201b8,
-0x440fffe, 0x24020001, 0xaf500180, 0xaf400184,
-0xa7520188, 0xa342018a, 0x24020002, 0xa342018b,
-0xa7510190, 0xaf4001a4, 0xaf4001a8, 0x3c021000,
-0xaf4201b8, 0xa001278, 0x8fbf001c, 0xd,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010,
-0xe000ea4, 0x0, 0xaf400180, 0x8fbf0010,
-0x2021, 0xa000f7d, 0x27bd0018, 0x3084ffff,
-0x30a5ffff, 0x1821, 0x10800007, 0x0,
-0x30820001, 0x10400002, 0x42042, 0x651821,
-0xa001289, 0x52840, 0x3e00008, 0x601021,
-0x10c00006, 0x24c6ffff, 0x8ca20000, 0x24a50004,
-0xac820000, 0xa001293, 0x24840004, 0x3e00008,
-0x0, 0x10a00008, 0x24a3ffff, 0xac860000,
-0x0, 0x0, 0x2402ffff, 0x2463ffff,
-0x1462fffa, 0x24840004, 0x3e00008, 0x0,
-0x27bdffe0, 0xafb20018, 0xafb10014, 0xafb00010,
-0xafbf001c, 0x9482000c, 0xa08821, 0x24900014,
-0x21302, 0x21080, 0x829021, 0x3021,
-0xa02021, 0xe00129c, 0x24050005, 0x212102b,
-0x10400057, 0x1021, 0x92030000, 0x2c620009,
-0x50400051, 0x92020001, 0x31080, 0x3c030800,
-0x246370dc, 0x431021, 0x8c420000, 0x400008,
-0x0, 0x92030001, 0x2402000c, 0x14620048,
-0x24020001, 0x2501023, 0x2c42000a, 0x14400036,
-0x26100002, 0x8e220000, 0x34420100, 0xae220000,
-0x92020000, 0x92030001, 0x92040002, 0x92050003,
-0x31c00, 0x21600, 0x431025, 0x42200,
-0x441025, 0x451025, 0x26100004, 0xae220004,
-0x92020000, 0x92030001, 0x92040002, 0x92050003,
-0x21600, 0x31c00, 0x431025, 0x42200,
-0x441025, 0x451025, 0x26100004, 0xa0012b6,
-0xae220008, 0x92030001, 0x24020004, 0x14620016,
-0x26100002, 0x92020000, 0x92040001, 0x8e230000,
-0x21200, 0x441025, 0x34630004, 0x26100002,
-0xae22000c, 0xa0012b6, 0xae230000, 0x92030001,
-0x24020003, 0x14620008, 0x26100002, 0x8e220000,
-0x92030000, 0x26100001, 0x34420008, 0xa2230010,
-0xa0012b6, 0xae220000, 0xa00130f, 0x24020001,
-0x92030001, 0x24020002, 0x10620002, 0x26040002,
-0x2402021, 0xa0012b6, 0x808021, 0xa0012b6,
-0x26100001, 0x92020001, 0xa0012b6, 0x2028021,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0xe0011b3, 0x808021, 0x9362007d,
-0x2002021, 0x34420020, 0xe0011bc, 0xa362007d,
-0x2002021, 0x8fbf0014, 0x8fb00010, 0xa000c9b,
-0x27bd0018, 0x308300ff, 0x30a500ff, 0x30c600ff,
-0x27470180, 0x8f4201b8, 0x440fffe, 0x0,
-0x8f420128, 0x34634000, 0xace20000, 0x24020001,
-0xace00004, 0xa4e30008, 0xa0e2000a, 0x24020002,
-0xa0e2000b, 0x3c021000, 0xa4e50010, 0xace00024,
-0xace00028, 0xa4e60012, 0x3e00008, 0xaf4201b8,
-0x27bdffe8, 0xafbf0010, 0x9362003f, 0x24030012,
-0x304200ff, 0x1043000d, 0x803021, 0x8f620044,
-0x821023, 0x440000a, 0x8fbf0010, 0x8f620048,
-0x24040039, 0x2821, 0xc21023, 0x4410004,
-0x24060012, 0xe001324, 0x0, 0x8fbf0010,
-0x24020001, 0x3e00008, 0x27bd0018, 0x27bdffc8,
-0xafb1002c, 0xa08821, 0xafb20030, 0x27a50010,
-0x809021, 0x2202021, 0xafbf0034, 0xe0012a7,
-0xafb00028, 0x10400009, 0x2402021, 0x8e220008,
-0xaf620084, 0xe001315, 0xaf600040, 0x24040038,
-0x2405008d, 0xa0013d1, 0x24060012, 0x93620034,
+0x0, 0x32a20002, 0x1040febd, 0x0,
+0x8f420140, 0x3c044000, 0xaf420020, 0x8f430148,
+0x3c027000, 0x621824, 0x10640042, 0x0,
+0x83102b, 0x14400006, 0x3c026000, 0x3c022000,
+0x10620007, 0x3c024000, 0xa0012c3, 0x0,
+0x1062003c, 0x3c024000, 0xa0012c3, 0x0,
+0x8f450140, 0x8f460144, 0x8f420148, 0x21402,
+0x304300ff, 0x24020004, 0x1462000a, 0x27440180,
+0x8f4201b8, 0x440fffe, 0x2402001c, 0xac850000,
+0xa082000b, 0x3c021000, 0xaf4201b8, 0xa0012c3,
+0x3c024000, 0x24020009, 0x14620012, 0x61602,
+0x229c0, 0xaf450020, 0x8f4201b8, 0x440fffe,
+0x24020001, 0x24030003, 0xaf450180, 0xa343018b,
+0xa740018e, 0xa740019a, 0xa7400190, 0xaf4001a8,
+0xa7420188, 0xa74201a6, 0xaf4001ac, 0x3c021000,
+0xaf4201b8, 0x8f4201b8, 0x440fffe, 0x0,
+0xac850000, 0x8f420148, 0x21402, 0xa4820008,
+0x24020002, 0xa082000b, 0x8f420148, 0xa4820010,
+0x3c021000, 0xac860024, 0xaf4201b8, 0xa0012c3,
+0x3c024000, 0xe001310, 0x0, 0xa0012c3,
+0x3c024000, 0xe001bba, 0x0, 0x3c024000,
+0xaf420178, 0x0, 0xa00112f, 0x0,
+0x8f420100, 0x3042003e, 0x14400011, 0x24020001,
+0xaf400048, 0x8f420100, 0x304207c0, 0x10400005,
+0x0, 0xaf40004c, 0xaf400050, 0x3e00008,
+0x24020001, 0xaf400054, 0xaf400040, 0x8f420100,
+0x30423800, 0x54400001, 0xaf400044, 0x24020001,
+0x3e00008, 0x0, 0x8f4201b8, 0x440fffe,
+0x24020001, 0xaf440180, 0xaf400184, 0xa7450188,
+0xa342018a, 0x24020002, 0xa342018b, 0x9742014a,
+0x14c00004, 0xa7420190, 0xaf4001a4, 0xa0012ef,
+0x3c021000, 0x8f420144, 0xaf4201a4, 0x3c021000,
+0xaf4001a8, 0x3e00008, 0xaf4201b8, 0x8f4201b8,
+0x440fffe, 0x24020002, 0xaf440180, 0xaf440184,
+0xa7450188, 0xa342018a, 0xa342018b, 0x9742014a,
+0xa7420190, 0xaf4001a4, 0x8f420144, 0xaf4201a8,
+0x3c021000, 0x3e00008, 0xaf4201b8, 0x3c029000,
+0x34420001, 0x822025, 0xaf440020, 0x8f420020,
+0x440fffe, 0x0, 0x3e00008, 0x0,
+0x3c028000, 0x34420001, 0x822025, 0x3e00008,
+0xaf440020, 0x27bdffe8, 0xafbf0014, 0xafb00010,
+0x8f500140, 0x93430149, 0x93420148, 0x93440148,
+0x306300ff, 0x304200ff, 0x21200, 0x622825,
+0x24020019, 0x10620076, 0x30840080, 0x2862001a,
+0x1040001c, 0x24020020, 0x24020008, 0x10620077,
+0x28620009, 0x1040000e, 0x2402000b, 0x24020001,
+0x10620034, 0x28620002, 0x50400005, 0x24020006,
+0x50600034, 0x2002021, 0xa00139a, 0x0,
+0x10620030, 0x2002021, 0xa00139a, 0x0,
+0x1062003b, 0x2862000c, 0x50400002, 0x2402000e,
+0x24020009, 0x10620056, 0x2002021, 0xa00139a,
+0x0, 0x10620056, 0x28620021, 0x1040000f,
+0x24020038, 0x2402001c, 0x10620058, 0x2862001d,
+0x10400006, 0x2402001f, 0x2402001b, 0x1062004c,
+0x0, 0xa00139a, 0x0, 0x1062004a,
+0x2002021, 0xa00139a, 0x0, 0x10620045,
+0x28620039, 0x10400007, 0x24020080, 0x2462ffcb,
+0x2c420002, 0x10400045, 0x2002021, 0xa001396,
+0x3021, 0x10620009, 0x0, 0xa00139a,
+0x0, 0x1480003d, 0x2002021, 0xa001390,
+0x8fbf0014, 0xa001396, 0x24060001, 0x8f4201b8,
+0x440fffe, 0x24020002, 0xa342018b, 0xa7450188,
+0x9742014a, 0xa7420190, 0x8f420144, 0xa7420192,
+0x3c021000, 0xaf4201b8, 0xa00139c, 0x8fbf0014,
+0x9742014a, 0x14400029, 0x0, 0x93620005,
+0x30420004, 0x14400025, 0x0, 0xe001302,
+0x2002021, 0x93620005, 0x2002021, 0x34420004,
+0xe00130b, 0xa3620005, 0x93620005, 0x30420004,
+0x14400002, 0x0, 0xd, 0x93620000,
+0x24030020, 0x304200ff, 0x14430014, 0x0,
+0x8f4201b8, 0x440fffe, 0x24020005, 0xaf500180,
+0xa342018b, 0x3c021000, 0xa00139a, 0xaf4201b8,
+0x8fbf0014, 0x8fb00010, 0xa0012f2, 0x27bd0018,
+0xd, 0x2002021, 0x3021, 0x8fbf0014,
+0x8fb00010, 0xa0012dd, 0x27bd0018, 0xd,
+0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
+0x27bdffe8, 0xafbf0010, 0xe000f3c, 0x0,
+0xaf400180, 0x8fbf0010, 0x2021, 0xa000fe7,
+0x27bd0018, 0x3084ffff, 0x30a5ffff, 0x1821,
+0x10800007, 0x0, 0x30820001, 0x10400002,
+0x42042, 0x651821, 0xa0013ab, 0x52840,
+0x3e00008, 0x601021, 0x10c00006, 0x24c6ffff,
+0x8ca20000, 0x24a50004, 0xac820000, 0xa0013b5,
+0x24840004, 0x3e00008, 0x0, 0x10a00008,
+0x24a3ffff, 0xac860000, 0x0, 0x0,
+0x2402ffff, 0x2463ffff, 0x1462fffa, 0x24840004,
+0x3e00008, 0x0, 0x308300ff, 0x30a500ff,
+0x30c600ff, 0x27470180, 0x8f4201b8, 0x440fffe,
+0x0, 0x8f420128, 0x34634000, 0xace20000,
+0x24020001, 0xace00004, 0xa4e30008, 0xa0e2000a,
+0x24020002, 0xa0e2000b, 0x3c021000, 0xa4e50010,
+0xace00024, 0xace00028, 0xa4e60012, 0x3e00008,
+0xaf4201b8, 0x27bdffe8, 0xafbf0010, 0x9362003f,
+0x24030012, 0x304200ff, 0x1043000d, 0x803021,
+0x8f620044, 0x821023, 0x440000a, 0x8fbf0010,
+0x8f620048, 0x24040039, 0x2821, 0xc21023,
+0x4410004, 0x24060012, 0xe0013c9, 0x0,
+0x8fbf0010, 0x24020001, 0x3e00008, 0x27bd0018,
+0x27bdffc8, 0xafb20030, 0xafb1002c, 0xafbf0034,
+0xafb00028, 0x90c5000d, 0x809021, 0x30a40010,
+0x1080000b, 0xc08821, 0x8cc30008, 0x8f620054,
+0x10620007, 0x30a20005, 0x144000b5, 0x24040001,
+0xe000d21, 0x2021, 0xa0014bb, 0x402021,
+0x30a20005, 0x10400009, 0x30a30012, 0x108000ac,
+0x24040001, 0x8e230008, 0x8f620054, 0x146200a9,
+0x8fbf0034, 0xa00142c, 0x24040038, 0x24020012,
+0x146200a3, 0x24040001, 0x2202021, 0x27a50010,
+0xe000cb2, 0xafa00010, 0x10400011, 0x2402021,
+0x8e220008, 0xaf620084, 0xaf600040, 0xe001302,
+0x0, 0x9362007d, 0x2402021, 0x34420020,
+0xe00130b, 0xa362007d, 0xe000ca9, 0x2402021,
+0x24040038, 0x2405008d, 0xa0014b8, 0x24060012,
+0x9362003e, 0x30420008, 0x1040000f, 0x8fa20010,
+0x30420100, 0x10400007, 0x8fa30014, 0x8f620060,
+0x621023, 0x4430008, 0xaf630060, 0xa001441,
+0x0, 0xaf600060, 0x9362003e, 0x2403fff7,
+0x431024, 0xa362003e, 0x9362003e, 0x30420008,
+0x14400002, 0x24060003, 0x3021, 0x93620034,
0x93630037, 0x8f640084, 0x304200ff, 0x306300ff,
-0x432821, 0xa4202b, 0x1080000b, 0x0,
-0x9763003c, 0x8f620084, 0x3063ffff, 0x451023,
-0x62182b, 0x14600004, 0x0, 0x8f620084,
-0xa00137b, 0x458023, 0x9762003c, 0x3050ffff,
-0x8fa30010, 0x30620004, 0x50400003, 0x2e020218,
-0x8fa2001c, 0x202102b, 0x14400005, 0x2002021,
-0x30620004, 0x10400002, 0x24040218, 0x8fa4001c,
-0x2c820080, 0x10400002, 0x808021, 0x24100080,
-0xe0011b3, 0x2402021, 0x24020001, 0xaf62000c,
-0x9362003e, 0x102040, 0x3042007f, 0xa362003e,
-0x8e220004, 0x24420001, 0xaf620040, 0xa770003c,
-0x8f620050, 0x9623000e, 0x431021, 0xaf620058,
-0x8f620050, 0x441021, 0xaf62005c, 0x8e220004,
-0xaf620018, 0x8e220008, 0xaf62001c, 0x8fa20010,
-0x30420008, 0x5440000a, 0x93a20020, 0xa3600036,
-0x93620036, 0x2403ffdf, 0xa3620035, 0x9362003e,
-0x431024, 0xa362003e, 0xa0013b1, 0x8e220008,
-0xa3620035, 0x8e220008, 0xaf62004c, 0x8f620024,
-0x8f630040, 0x431021, 0xaf620048, 0x93620000,
-0x24030050, 0x304200ff, 0x14430012, 0x2403ff80,
-0x3c020800, 0x8c4231a0, 0x2421021, 0x431024,
-0xaf420028, 0x3c020800, 0x8c4231a0, 0x8e240008,
-0x3c03000c, 0x2421021, 0x3042007f, 0x3421021,
-0x431021, 0xac4400d8, 0x8e230008, 0xaf820028,
-0xac4300dc, 0xe0011bc, 0x2402021, 0x24040038,
-0x2821, 0x2406000a, 0xe001324, 0x0,
+0x661821, 0x31880, 0x432821, 0xa4202b,
+0x1080000b, 0x0, 0x9763003c, 0x8f620084,
+0x3063ffff, 0x451023, 0x62182b, 0x14600004,
+0x0, 0x8f620084, 0xa00145d, 0x458023,
+0x9762003c, 0x3050ffff, 0x8fa30010, 0x30620004,
+0x10400004, 0x62880, 0x8fa2001c, 0xa001465,
+0x202102b, 0x2e020218, 0x50400003, 0x24020218,
+0xa00146e, 0x2051023, 0x30630004, 0x10600003,
+0x451023, 0x8fa2001c, 0x451023, 0x408021,
+0x2c420080, 0x54400001, 0x24100080, 0xe001302,
+0x2402021, 0x24020001, 0xaf62000c, 0x9362003e,
+0x102040, 0x3042007f, 0xa362003e, 0x8e220004,
+0x24420001, 0xaf620040, 0xa770003c, 0x8f620050,
+0x9623000e, 0x431021, 0xaf620058, 0x8f620050,
+0x441021, 0xaf62005c, 0x8e220004, 0xaf620018,
+0x8e220008, 0xaf62001c, 0x8fa20010, 0x30420008,
+0x5440000a, 0x93a20020, 0xa3600036, 0x93620036,
+0x2403ffdf, 0xa3620035, 0x9362003e, 0x431024,
+0xa362003e, 0xa001498, 0x8e220008, 0xa3620035,
+0x8e220008, 0xaf62004c, 0x8f620024, 0x8f630040,
+0x431021, 0xaf620048, 0x93620000, 0x24030050,
+0x304200ff, 0x14430012, 0x2403ff80, 0x3c020800,
+0x8c4231a0, 0x2421021, 0x431024, 0xaf420028,
+0x3c020800, 0x8c4231a0, 0x8e240008, 0x3c03000c,
+0x2421021, 0x3042007f, 0x3421021, 0x431021,
+0xac4400d8, 0x8e230008, 0xaf820014, 0xac4300dc,
+0xe00130b, 0x2402021, 0x24040038, 0x2821,
+0x2406000a, 0xe0013c9, 0x0, 0x24040001,
0x8fbf0034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
-0x24020001, 0x3e00008, 0x27bd0038, 0x27bdffe8,
-0xafbf0010, 0x90c7000d, 0xc02821, 0x30e60010,
-0x10c0000a, 0x30e20004, 0x8ca30008, 0x8f620054,
-0x10620006, 0x30e20004, 0x14400017, 0x8fbf0010,
-0x2021, 0xa000cb2, 0x27bd0018, 0x1040000d,
-0x30e30012, 0x10c00010, 0x8fbf0010, 0x8ca30008,
-0x8f620054, 0x1462000d, 0x24020001, 0x24040038,
-0x2405008d, 0xe001324, 0x24060012, 0xa0013fd,
-0x8fbf0010, 0x24020012, 0x14620003, 0x8fbf0010,
-0xa001352, 0x27bd0018, 0x24020001, 0x3e00008,
-0x27bd0018, 0x27bdfff8, 0x27420180, 0xafa20000,
-0x308a00ff, 0x8f4201b8, 0x440fffe, 0x0,
-0x8f460128, 0x3c020800, 0x8c4231a0, 0x2403ff80,
-0xaf860050, 0xc21021, 0x431024, 0xaf420024,
-0x3c020800, 0x8c4231a0, 0x8fa90000, 0x8fa80000,
-0xc21021, 0x3042007f, 0x3421821, 0x3c02000a,
-0x621821, 0x946400d4, 0x8fa70000, 0x8fa50000,
-0x24020002, 0xaf830028, 0xa0a2000b, 0x8fa30000,
-0x35426000, 0x3084ffff, 0xa4e20008, 0x3c021000,
-0xad260000, 0xad040004, 0xac600024, 0x27bd0008,
-0xaf4201b8, 0x3e00008, 0x24020001, 0x8c820004,
-0x8f830028, 0x451023, 0xac820004, 0x90620063,
-0x3042007f, 0xa0620063, 0x8c820020, 0x93830030,
-0x8f850028, 0x34420002, 0xaf830044, 0xa7800042,
-0xac820020, 0xa4a000e4, 0x90a20063, 0x2403ffbf,
-0x431024, 0x3e00008, 0xa0a20063, 0x27430180,
-0x8f4201b8, 0x440fffe, 0x8f820050, 0xac620000,
-0x8f420124, 0xac620004, 0x24026083, 0xa4620008,
-0x24020002, 0xa062000b, 0x3c021000, 0x3e00008,
-0xaf4201b8, 0x8f880044, 0x93820030, 0x8f830028,
-0x3c070800, 0x24e77594, 0x481023, 0x304200ff,
-0x304900fc, 0x24650088, 0x8f860048, 0x304a0003,
+0x801021, 0x3e00008, 0x27bd0038, 0x27bdfff8,
+0x27420180, 0xafa20000, 0x308a00ff, 0x8f4201b8,
+0x440fffe, 0x0, 0x8f460128, 0x3c020800,
+0x8c4231a0, 0x2403ff80, 0xaf860048, 0xc21021,
+0x431024, 0xaf420024, 0x3c020800, 0x8c4231a0,
+0x8fa90000, 0x8fa80000, 0xc21021, 0x3042007f,
+0x3421821, 0x3c02000a, 0x621821, 0x946400d4,
+0x8fa70000, 0x8fa50000, 0x24020002, 0xaf830014,
+0xa0a2000b, 0x8fa30000, 0x35426000, 0x3084ffff,
+0xa4e20008, 0x3c021000, 0xad260000, 0xad040004,
+0xac600024, 0x27bd0008, 0xaf4201b8, 0x3e00008,
+0x24020001, 0x8f88003c, 0x93820028, 0x8f830014,
+0x3c070800, 0x24e77778, 0x481023, 0x304200ff,
+0x304900fc, 0x24650088, 0x8f860040, 0x304a0003,
0x11200009, 0x2021, 0x24820004, 0x8ca30000,
0x304400ff, 0x89102a, 0xace30000, 0x24a50004,
0x1440fff9, 0x24e70004, 0x11400009, 0x2021,
0x24820001, 0x90a30000, 0x304400ff, 0x8a102b,
0xa0e30000, 0x24a50001, 0x1440fff9, 0x24e70001,
-0x30c20003, 0x14400004, 0x8f850044, 0x31020003,
+0x30c20003, 0x14400004, 0x8f85003c, 0x31020003,
0x1040000d, 0x0, 0x10a00009, 0x2021,
0x24820001, 0x90c30000, 0x304400ff, 0x85102b,
0xa0e30000, 0x24c60001, 0x1440fff9, 0x24e70001,
0x3e00008, 0x0, 0x1100fffd, 0x2021,
0x24820004, 0x8cc30000, 0x304400ff, 0x88102b,
0xace30000, 0x24c60004, 0x1440fff9, 0x24e70004,
-0x3e00008, 0x0, 0x8f830044, 0x93820030,
+0x3e00008, 0x0, 0x8f83003c, 0x93820028,
0x30c600ff, 0x30a500ff, 0x431023, 0x304300ff,
-0x8f820028, 0x803821, 0x431021, 0x14c00002,
+0x8f820014, 0x803821, 0x431021, 0x14c00002,
0x24480088, 0x833821, 0x30e20003, 0x14400005,
0x30a20003, 0x14400003, 0x30620003, 0x1040000d,
0x0, 0x10a00009, 0x2021, 0x24820001,
@@ -2657,427 +2641,416 @@ u32 bce_RXP_b06FwText[(0x70dc/4) + 1] = {
0x0, 0x10a0fffd, 0x2021, 0x24820004,
0x8ce30000, 0x304400ff, 0x85102b, 0xad030000,
0x24e70004, 0x1440fff9, 0x25080004, 0x3e00008,
-0x0, 0x27bdfff8, 0x2402ffff, 0xafa20000,
-0x803821, 0x2405002f, 0x3c090800, 0x25297194,
-0x240800ff, 0x2406ffff, 0x90e20000, 0x24a3ffff,
-0x62202, 0xc21026, 0x304200ff, 0x21080,
-0x491021, 0x8c420000, 0x306500ff, 0x24e70001,
-0x14a8fff5, 0x823026, 0x61027, 0xafa20004,
-0xafa20000, 0x2821, 0x27a60004, 0xc51023,
-0x90440003, 0x24a20001, 0xbd1821, 0x304500ff,
-0x2ca20004, 0x1440fff9, 0xa0640000, 0x8fa20000,
-0x3e00008, 0x27bd0008, 0x804821, 0x30aaffff,
-0x30c600ff, 0x30e7ffff, 0x27480180, 0x8f4201b8,
-0x440fffe, 0x8f820050, 0xad020000, 0x8f420124,
-0xad020004, 0x8d220020, 0xa5070008, 0xa102000a,
-0x24020016, 0xa102000b, 0x93430120, 0x8d220008,
-0x8d240004, 0x306300ff, 0x431021, 0x97830042,
-0x441021, 0x8d250024, 0x431023, 0x3c030800,
-0x8c6331a0, 0x8f840028, 0xa502000c, 0x246300e8,
-0x2402ffff, 0xa50a000e, 0xa5030010, 0xa5060012,
-0xad050018, 0xad020024, 0x94820114, 0x2403fff7,
-0x3042ffff, 0xad020028, 0x8c820118, 0xad02002c,
-0x3c021000, 0xad000030, 0xaf4201b8, 0x8d220020,
-0x431024, 0x3e00008, 0xad220020, 0x8f820028,
-0x30e7ffff, 0x804821, 0x904200d3, 0x30a5ffff,
-0x30c600ff, 0x21100, 0x30420f00, 0xe23825,
-0x27480180, 0x8f4201b8, 0x440fffe, 0x8f820050,
-0xad020000, 0x8f420124, 0xad020004, 0x8d220020,
-0xa5070008, 0xa102000a, 0x24020017, 0xa102000b,
-0x93430120, 0x8d220008, 0x8d240004, 0x306300ff,
-0x431021, 0x97830042, 0x441021, 0x8f840028,
-0x431023, 0x3c030800, 0x8c6331a0, 0xa502000c,
-0xa505000e, 0x246300e8, 0xa5030010, 0xa5060012,
-0xad000014, 0x8d220024, 0xad020018, 0x8c82005c,
-0xad02001c, 0x8c820058, 0xad020020, 0x2402ffff,
-0xad020024, 0x948200e6, 0x3042ffff, 0xad020028,
-0x94820060, 0x948300be, 0x30427fff, 0x3063ffff,
-0x21200, 0x431021, 0xad02002c, 0x3c021000,
-0xad000030, 0xaf4201b8, 0x948200be, 0x2403fff7,
-0xa21021, 0xa48200be, 0x8d220020, 0x431024,
-0x3e00008, 0xad220020, 0x27430180, 0x8f4201b8,
-0x440fffe, 0x24020018, 0xac640000, 0xa062000b,
-0x8f820028, 0x944200e6, 0xa4620010, 0x3c021000,
-0xac600030, 0x3e00008, 0xaf4201b8, 0x27430180,
-0x8f4201b8, 0x440fffe, 0x8f82002c, 0x9442001c,
-0x3042ffff, 0x211c0, 0xac620000, 0x24020019,
-0xa062000b, 0x3c021000, 0xac600030, 0x3e00008,
-0xaf4201b8, 0x8f870034, 0x30c300ff, 0x8f4201b8,
-0x440fffe, 0x8f820050, 0x34636000, 0xaca20000,
-0x9382004c, 0xa0a20005, 0x8ce20010, 0xa4a20006,
-0xa4a30008, 0x8c820020, 0x2403fff7, 0xa0a2000a,
-0x24020002, 0xa0a2000b, 0x8ce20000, 0xaca20010,
-0x8ce20004, 0xaca20014, 0x8ce2001c, 0xaca20024,
-0x8ce20020, 0xaca20028, 0x8ce2002c, 0xaca2002c,
-0x8c820024, 0xaca20018, 0x3c021000, 0xaf4201b8,
-0x8c820020, 0x431024, 0x3e00008, 0xac820020,
-0x9382004c, 0x24030001, 0x27bdffe8, 0x433004,
-0x2c420020, 0xafb00010, 0xafbf0014, 0x2410fffe,
-0x10400005, 0x27450180, 0x3c020800, 0x8c423190,
-0xa00159c, 0x461024, 0x3c020800, 0x8c423194,
-0x461024, 0x14400007, 0x24060084, 0x8f830028,
-0x2410ffff, 0x90620062, 0x3042000f, 0x34420040,
-0xa0620062, 0xe001568, 0x0, 0x2001021,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x8f83002c, 0x27bdffe0, 0xafb20018, 0xafb10014,
-0xafb00010, 0xafbf001c, 0x9062000d, 0xa09021,
-0x30d100ff, 0x3042007f, 0xa062000d, 0x8f850028,
-0x8e430018, 0x808021, 0x8ca2007c, 0x14620005,
-0x2402000e, 0x90a20063, 0x34420020, 0xa0015c5,
-0xa0a20063, 0xe00158b, 0xa382004c, 0x2403ffff,
-0x10430047, 0x2404ffff, 0x52200045, 0x2021,
-0x8e430000, 0x3c020010, 0x621024, 0x50400004,
-0x3c020008, 0x2002021, 0xa0015d4, 0x24020015,
-0x621024, 0x50400009, 0x8e450000, 0x2002021,
-0x24020014, 0xe00158b, 0xa382004c, 0x2403ffff,
-0x10430033, 0x2404ffff, 0x8e450000, 0x3c020002,
-0xa21024, 0x10400016, 0x3c020004, 0x8f86002c,
-0x8cc20014, 0x8cc30010, 0x8cc40014, 0x431023,
-0x44102b, 0x50400005, 0x2002021, 0x8e43002c,
-0x8cc20010, 0x10620003, 0x2002021, 0xa001605,
-0x24020012, 0x3c020004, 0xa21024, 0x5040001c,
-0x2021, 0x2002021, 0xa001605, 0x24020013,
-0xa21024, 0x10400006, 0x8f83002c, 0x8c620010,
-0x50400013, 0x2021, 0xa0015ff, 0x2002021,
-0x8c620010, 0x50400004, 0x8e42002c, 0x2002021,
-0xa001605, 0x24020011, 0x50400009, 0x2021,
-0x2002021, 0x24020017, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x10430002, 0x2404ffff, 0x2021,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x801021, 0x3e00008, 0x27bd0020, 0x93830030,
-0x27bdffe0, 0x24020034, 0xafb20018, 0xafb10014,
-0xafbf001c, 0xafb00010, 0x808821, 0x1462000c,
-0xa09021, 0x8f840034, 0xe0014b4, 0x8c900030,
-0x12020007, 0x24020005, 0x2202021, 0xe00158b,
-0xa382004c, 0x2403ffff, 0x1043005f, 0x2404ffff,
-0x92420004, 0x10400009, 0x8f820028, 0x2202021,
-0x2402000c, 0xe00158b, 0xa382004c, 0x2403ffff,
-0x10430055, 0x2404ffff, 0x8f820028, 0xa3800024,
-0x8e430004, 0x8c440080, 0x3c0200ff, 0x3442ffff,
-0x621824, 0x83202b, 0x10800008, 0xaf83003c,
-0x2202021, 0x24020019, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x10430044, 0x2404ffff, 0x97820042,
-0x8f870044, 0x8f88003c, 0x471023, 0x11000039,
-0xa7820042, 0x8f860028, 0x3045ffff, 0x8f840050,
-0x90c300bc, 0x3c020800, 0x8c4231a0, 0x31882,
-0x30700001, 0x822021, 0x101080, 0x1021021,
-0xa2282b, 0x10a00010, 0x24820088, 0x8f840034,
-0x1082000d, 0x3c033f01, 0x8e420000, 0x431024,
-0x3c032500, 0x14430006, 0x30e500ff, 0x8c820000,
-0xacc20088, 0x8c820010, 0xa001665, 0xacc20098,
-0xe001489, 0x3021, 0x8f85003c, 0x93830024,
-0x8f860028, 0x30a20003, 0x21023, 0x30420003,
-0x433821, 0xa3870024, 0x94c400e4, 0xa22821,
-0x8f830044, 0x8f820048, 0x34841000, 0xa4c400e4,
-0x431021, 0xaf820048, 0x1200000e, 0xaf850044,
-0x24e20004, 0xa3820024, 0x94c200e4, 0x24a30004,
-0xaf830044, 0x34422000, 0xa4c200e4, 0xa001685,
-0x2021, 0x8f820048, 0xaf800044, 0x471021,
-0xaf820048, 0x2021, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x801021, 0x3e00008,
-0x27bd0020, 0x8f860028, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0x90c20063, 0x30420020, 0x10400008,
-0x30a500ff, 0x8cc2007c, 0x2403ffdf, 0x24420001,
-0xacc2007c, 0x90c20063, 0x431024, 0xa0c20063,
-0x10a00023, 0x8f830028, 0x27500180, 0x2002821,
-0xe001568, 0x24060082, 0x8f820028, 0x90420063,
-0x30420040, 0x50400019, 0xa380004c, 0x8f830034,
-0x8f4201b8, 0x440fffe, 0x8f820050, 0xae020000,
-0x24026082, 0xa6020008, 0x24020002, 0xa202000b,
-0x8c620008, 0xae020010, 0x8c62000c, 0xae020014,
-0x8c620014, 0xae020018, 0x8c620018, 0xae020024,
-0x8c620024, 0xae020028, 0x8c620028, 0xae02002c,
-0x3c021000, 0xaf4201b8, 0xa380004c, 0x8f830028,
-0x8fbf0014, 0x8fb00010, 0x90620063, 0x27bd0018,
-0x3042007f, 0xa0620063, 0x97820042, 0x8f860044,
-0x8f850028, 0x93830030, 0x461023, 0xa7820042,
-0xa4a000e4, 0x90a40063, 0x8f820048, 0xaf830044,
-0x2403ffbf, 0x461021, 0x832024, 0xaf820048,
-0xa0a40063, 0x8f820028, 0xa04000bd, 0x8f820028,
-0x3e00008, 0xa44000be, 0x8f8a0028, 0x27bdffe0,
-0xafb10014, 0xafb00010, 0x8f880044, 0xafbf0018,
-0x93890024, 0x954200e4, 0x30d100ff, 0x109182b,
-0x808021, 0x30ac00ff, 0x3047ffff, 0x5821,
-0x14600003, 0x310600ff, 0x1203021, 0x1095823,
-0x97830042, 0x68102b, 0x14400032, 0x0,
-0x14680007, 0x24020001, 0x8e020020, 0x2403fffb,
-0x34e78000, 0x431024, 0xae020020, 0x24020001,
-0x34e70880, 0x15820005, 0x3165ffff, 0xe0014d9,
-0x2002021, 0xa00171a, 0x2002021, 0xe00150a,
-0x2002021, 0xe00154d, 0x8f840050, 0x8f840028,
-0x94820060, 0x24420001, 0xa4820060, 0x94820060,
-0x3c030800, 0x8c633188, 0x30427fff, 0x5443000f,
-0x2002021, 0x94820060, 0x24038000, 0x431024,
-0xa4820060, 0x90820060, 0x90830060, 0x304200ff,
-0x211c2, 0x21027, 0x211c0, 0x3063007f,
-0x621825, 0xa0830060, 0x2002021, 0x2202821,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0xa00168c,
-0x27bd0020, 0x91420063, 0x2403ff80, 0x431025,
-0xa1420063, 0x97820042, 0x3048ffff, 0x11000020,
-0x93830024, 0x8f840028, 0x4b1023, 0x304600ff,
-0x948300e4, 0x2402efff, 0x168282b, 0x621824,
-0xa48300e4, 0x14a00003, 0x8e020020, 0x1005821,
-0x3021, 0x2403fffb, 0x34e78000, 0x431024,
-0xae020020, 0x24020001, 0x15820005, 0x3165ffff,
-0xe0014d9, 0x2002021, 0xa001742, 0x97830042,
-0xe00150a, 0x2002021, 0x97830042, 0x8f820044,
-0xa7800042, 0x431023, 0xaf820044, 0x93830024,
-0x8f820028, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0x27bd0020, 0x3e00008, 0xa04300bd, 0x8f820028,
-0x90430088, 0x904500bd, 0x24490088, 0x3063003f,
-0x2463ffe0, 0x24020001, 0x623804, 0x2c630020,
-0x30e80019, 0xa3850024, 0x10600010, 0xaf890034,
-0x3c028000, 0x34420002, 0x24050001, 0x24060001,
-0x15000008, 0xe21824, 0x2821, 0x14600005,
-0x30e20020, 0x10400005, 0x24050001, 0x91260001,
-0x30c60001, 0xa0016d9, 0x0, 0x3e00008,
-0x0, 0x27bdffd8, 0xafb00010, 0x8f900034,
-0xafb40020, 0xafb10014, 0xafbf0024, 0xafb3001c,
-0xafb20018, 0x8e050010, 0x3c020800, 0x8c4231b0,
-0x8f860038, 0x30a33fff, 0x62182b, 0x8cd30014,
-0x808821, 0x8cd20020, 0x10600078, 0xa021,
-0x90c3000d, 0x2402ff80, 0x431024, 0x304200ff,
-0x50400073, 0x2202021, 0x51382, 0x30420003,
-0x5440006f, 0x2202021, 0x94c3001c, 0x8f820028,
-0x8e050028, 0xa4430114, 0x8cc20010, 0x2621823,
-0x14650007, 0x2402001f, 0x8f82003c, 0x621021,
-0x262102b, 0x10400008, 0x8f83002c, 0x24020018,
-0xe00158b, 0xa382004c, 0x2403ffff, 0x1043006f,
-0x2404ffff, 0x8f83002c, 0x8f84003c, 0x8c620010,
-0x2449021, 0x441023, 0xac620010, 0x8f820028,
-0xac720020, 0x8c420068, 0x52102b, 0x10400009,
-0x8f830038, 0x2202021, 0x2402001d, 0xe00158b,
-0xa382004c, 0x2403ffff, 0x1043005c, 0x2404ffff,
-0x8f830038, 0x8e020024, 0x8c630024, 0x10430007,
-0x2202021, 0x2402001c, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x10430051, 0x2404ffff, 0x8f84002c,
-0x8c820024, 0x24420001, 0xac820024, 0x12530004,
-0x8f820028, 0x8c420068, 0x5642000e, 0x8e020000,
-0x8e020000, 0x3c030080, 0x431024, 0x1440000d,
-0x2402001a, 0x2202021, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x1043003d, 0x2404ffff, 0xa0017d6,
-0x8e020014, 0x3c030080, 0x431024, 0x50400003,
-0x8e020014, 0xac800020, 0x8e020014, 0x2412ffff,
-0x10520006, 0x2402001b, 0x2202021, 0xe00158b,
-0xa382004c, 0x1052002d, 0x2404ffff, 0x8e030000,
-0x3c020001, 0x621024, 0x1040001f, 0x3c020080,
-0x621024, 0x14400008, 0x2202021, 0x2402001a,
-0xe00158b, 0xa382004c, 0x2403ffff, 0x1043001f,
-0x2404ffff, 0x2202021, 0x2002821, 0xe0015ab,
-0x24060001, 0x2403ffff, 0x2404ffff, 0x1443000e,
-0x24140001, 0xa00180b, 0x8fbf0024, 0x2202021,
-0x2402000d, 0x8fbf0024, 0x8fb40020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x27bd0028,
-0xa00158b, 0xa382004c, 0x8f83002c, 0x2202021,
-0x2803021, 0x94620036, 0x24050001, 0x24420001,
-0xe0016d9, 0xa4620036, 0x2021, 0x8fbf0024,
-0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x801021, 0x3e00008, 0x27bd0028,
-0x8f830028, 0x27bdffd8, 0xafb40020, 0xafb3001c,
-0xafb20018, 0xafb10014, 0xafb00010, 0xafbf0024,
-0x90620063, 0x8f910034, 0x2412ffff, 0x34420040,
-0x92250000, 0xa0620063, 0x8e220010, 0x809821,
-0x30b0003f, 0x10520006, 0x360a021, 0x2402000d,
-0xe00158b, 0xa382004c, 0x10520052, 0x2404ffff,
-0x8f830028, 0x8e220018, 0x8c63007c, 0x10430007,
-0x2602021, 0x2402000e, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x10430047, 0x2404ffff, 0x24040020,
-0x12040004, 0x8f830028, 0x90620063, 0x34420020,
-0xa0620063, 0x8f85003c, 0x10a0001e, 0x0,
-0x56040004, 0x8f820028, 0x2602021, 0xa001855,
-0x2402000a, 0x9683000a, 0x2404fffd, 0x94420060,
-0x3042ffff, 0x10430034, 0x8fbf0024, 0x3c020800,
-0x8c42318c, 0x45102b, 0x14400006, 0x2602021,
-0x2821, 0xe0016d9, 0x24060001, 0xa00187c,
-0x2021, 0x2402002d, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x10430023, 0x2404ffff, 0xa00187c,
-0x2021, 0x16040005, 0x8f840028, 0x8e230014,
-0x2402ffff, 0x50620018, 0x2602021, 0x94820060,
+0x0, 0x804821, 0x30aaffff, 0x30c600ff,
+0x30e7ffff, 0x27480180, 0x8f4201b8, 0x440fffe,
+0x8f820048, 0xad020000, 0x8f420124, 0xad020004,
+0x8d220020, 0xa5070008, 0xa102000a, 0x24020016,
+0xa102000b, 0x93430120, 0x8d220008, 0x8d240004,
+0x306300ff, 0x431021, 0x9783003a, 0x441021,
+0x8d250024, 0x431023, 0x3c030800, 0x8c6331a0,
+0x8f840014, 0xa502000c, 0x246300e8, 0x2402ffff,
+0xa50a000e, 0xa5030010, 0xa5060012, 0xad050018,
+0xad020024, 0x94820114, 0x2403fff7, 0x3042ffff,
+0xad020028, 0x8c820118, 0xad02002c, 0x3c021000,
+0xad000030, 0xaf4201b8, 0x8d220020, 0x431024,
+0x3e00008, 0xad220020, 0x8f820014, 0x30e7ffff,
+0x804821, 0x904200d3, 0x30a5ffff, 0x30c600ff,
+0x21100, 0x30420f00, 0xe23825, 0x27480180,
+0x8f4201b8, 0x440fffe, 0x8f820048, 0xad020000,
+0x8f420124, 0xad020004, 0x8d220020, 0xa5070008,
+0xa102000a, 0x24020017, 0xa102000b, 0x93430120,
+0x8d220008, 0x8d240004, 0x306300ff, 0x431021,
+0x9783003a, 0x441021, 0x8f840014, 0x431023,
+0x3c030800, 0x8c6331a0, 0xa502000c, 0xa505000e,
+0x246300e8, 0xa5030010, 0xa5060012, 0xad000014,
+0x8d220024, 0xad020018, 0x8c82005c, 0xad02001c,
+0x8c820058, 0xad020020, 0x2402ffff, 0xad020024,
+0x948200e6, 0x3042ffff, 0xad020028, 0x94820060,
+0x948300be, 0x30427fff, 0x3063ffff, 0x21200,
+0x431021, 0xad02002c, 0x3c021000, 0xad000030,
+0xaf4201b8, 0x948200be, 0x2403fff7, 0xa21021,
+0xa48200be, 0x8d220020, 0x431024, 0x3e00008,
+0xad220020, 0x27430180, 0x8f4201b8, 0x440fffe,
+0x8f820024, 0x9442001c, 0x3042ffff, 0x211c0,
+0xac620000, 0x24020019, 0xa062000b, 0x3c021000,
+0xac600030, 0x3e00008, 0xaf4201b8, 0x8f87002c,
+0x30c300ff, 0x8f4201b8, 0x440fffe, 0x8f820048,
+0x34636000, 0xaca20000, 0x93820044, 0xa0a20005,
+0x8ce20010, 0xa4a20006, 0xa4a30008, 0x8c820020,
+0x2403fff7, 0xa0a2000a, 0x24020002, 0xa0a2000b,
+0x8ce20000, 0xaca20010, 0x8ce20004, 0xaca20014,
+0x8ce2001c, 0xaca20024, 0x8ce20020, 0xaca20028,
+0x8ce2002c, 0xaca2002c, 0x8c820024, 0xaca20018,
+0x3c021000, 0xaf4201b8, 0x8c820020, 0x431024,
+0x3e00008, 0xac820020, 0x8f860014, 0x27bdffe8,
+0xafbf0014, 0xafb00010, 0x90c20063, 0x30420020,
+0x10400008, 0x30a500ff, 0x8cc2007c, 0x2403ffdf,
+0x24420001, 0xacc2007c, 0x90c20063, 0x431024,
+0xa0c20063, 0x10a00023, 0x8f830014, 0x27500180,
+0x2002821, 0xe0015d6, 0x24060082, 0x8f820014,
+0x90420063, 0x30420040, 0x50400019, 0xa3800044,
+0x8f83002c, 0x8f4201b8, 0x440fffe, 0x8f820048,
+0xae020000, 0x24026082, 0xa6020008, 0x24020002,
+0xa202000b, 0x8c620008, 0xae020010, 0x8c62000c,
+0xae020014, 0x8c620014, 0xae020018, 0x8c620018,
+0xae020024, 0x8c620024, 0xae020028, 0x8c620028,
+0xae02002c, 0x3c021000, 0xaf4201b8, 0xa3800044,
+0x8f830014, 0x8fbf0014, 0x8fb00010, 0x90620063,
+0x27bd0018, 0x3042007f, 0xa0620063, 0x9782003a,
+0x8f86003c, 0x8f850014, 0x93830028, 0x461023,
+0xa782003a, 0xa4a000e4, 0x90a40063, 0x8f820040,
+0xaf83003c, 0x2403ffbf, 0x461021, 0x832024,
+0xaf820040, 0xa0a40063, 0x8f820014, 0xa04000bd,
+0x8f820014, 0x3e00008, 0xa44000be, 0x8f8a0014,
+0x27bdffe0, 0xafb10014, 0xafb00010, 0x8f88003c,
+0xafbf0018, 0x9389001c, 0x954200e4, 0x30d100ff,
+0x109182b, 0x808021, 0x30ac00ff, 0x3047ffff,
+0x5821, 0x14600003, 0x310600ff, 0x1203021,
+0x1095823, 0x9783003a, 0x68102b, 0x1440003c,
+0x0, 0x14680007, 0x24020001, 0x8e020020,
+0x2403fffb, 0x34e78000, 0x431024, 0xae020020,
+0x24020001, 0x34e70880, 0x15820005, 0x3165ffff,
+0xe001554, 0x2002021, 0xa001691, 0x2002021,
+0xe001585, 0x2002021, 0x8f840048, 0x27430180,
+0x8f4201b8, 0x440fffe, 0x24020018, 0xac640000,
+0xa062000b, 0x8f840014, 0x948200e6, 0xa4620010,
+0x3c021000, 0xac600030, 0xaf4201b8, 0x94820060,
0x24420001, 0xa4820060, 0x94820060, 0x3c030800,
-0x8c633188, 0x30427fff, 0x5443000f, 0x2602021,
+0x8c633188, 0x30427fff, 0x5443000f, 0x2002021,
0x94820060, 0x24038000, 0x431024, 0xa4820060,
0x90820060, 0x90830060, 0x304200ff, 0x211c2,
0x21027, 0x211c0, 0x3063007f, 0x621825,
-0xa0830060, 0x2602021, 0xe00168c, 0x24050001,
-0x2021, 0x8fbf0024, 0x8fb40020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x801021,
-0x3e00008, 0x27bd0028, 0x8f830028, 0x27bdffe8,
-0xafb00010, 0xafbf0014, 0x90620063, 0x8f870034,
-0x808021, 0x34420040, 0x8ce60010, 0xa0620063,
-0x3c030800, 0x8c6331b0, 0x30c23fff, 0x43102b,
-0x1040004e, 0x8f850038, 0x2402ff80, 0x90a3000d,
-0x431024, 0x304200ff, 0x50400049, 0x2002021,
-0x61382, 0x30480003, 0x24020002, 0x55020044,
-0x2002021, 0x94a2001c, 0x8f850028, 0x24030023,
-0xa4a20114, 0x8ce60000, 0x61602, 0x3042003f,
-0x10430010, 0x3c030083, 0x8ce30018, 0x8ca2007c,
-0x10620006, 0x2402000e, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x10430038, 0x2404ffff, 0x8f830028,
-0x90620063, 0x34420020, 0xa0620063, 0xa0018c1,
-0x8f83002c, 0xc31024, 0x14430007, 0x8f83002c,
-0x90a20062, 0x3042000f, 0x34420020, 0xa0a20062,
-0xa3880040, 0x8f83002c, 0x9062000d, 0x3042007f,
-0xa062000d, 0x8f83003c, 0x10600018, 0x2002021,
-0x8f840038, 0x8c820010, 0x43102b, 0x10400009,
-0x24020018, 0x2002021, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x10430018, 0x2404ffff, 0xa0018e9,
-0x2021, 0x8c820010, 0x24050001, 0x2002021,
-0x431023, 0x8f83002c, 0x24060001, 0xe0016d9,
-0xac620010, 0xa0018e9, 0x2021, 0xe00168c,
-0x24050001, 0xa0018e9, 0x2021, 0x2002021,
-0x2402000d, 0x8fbf0014, 0x8fb00010, 0x27bd0018,
-0xa00158b, 0xa382004c, 0x8fbf0014, 0x8fb00010,
-0x801021, 0x3e00008, 0x27bd0018, 0x27bdffd8,
-0xafb00010, 0x8f900034, 0xafb3001c, 0xafbf0020,
-0xafb20018, 0xafb10014, 0x8e120010, 0x3c030800,
-0x8c6331b0, 0x32423fff, 0x43102b, 0x1040007c,
-0x809821, 0x8f850038, 0x2402ff80, 0x90a3000d,
-0x431024, 0x304200ff, 0x50400076, 0x2602021,
-0x121382, 0x30420003, 0x24030001, 0x54430071,
-0x2602021, 0x90a2000d, 0x30420008, 0x54400003,
-0x8f82003c, 0xa001919, 0x24020024, 0x50400003,
-0x8e03000c, 0xa001919, 0x24020027, 0x8ca20020,
-0x14620005, 0x24020020, 0x8e030008, 0x8ca20024,
-0x10620008, 0x24020020, 0xe00158b, 0xa382004c,
-0x2403ffff, 0x1043006a, 0x2404ffff, 0xa001944,
-0x8f84002c, 0x8e020014, 0x2411ffff, 0x14510003,
-0x8f870028, 0xa00193f, 0x24020025, 0x8e030018,
-0x8ce2007c, 0x14620016, 0x2402000e, 0x8e030024,
-0x8ca20028, 0x14620012, 0x24020021, 0x8e060028,
-0x8ca2002c, 0x14c2000e, 0x2402001f, 0x8e03002c,
-0x1060000b, 0x24020023, 0x8ce20068, 0x43102b,
-0x14400007, 0x24020026, 0x8ca20014, 0x661821,
-0x43102b, 0x50400007, 0x8f84002c, 0x24020022,
-0xe00158b, 0xa382004c, 0x10510045, 0x2404ffff,
-0x8f84002c, 0x2403fff7, 0x9082000d, 0x431024,
-0xa082000d, 0x8f860028, 0x3c030800, 0x8c6331ac,
-0x8f820050, 0x94c400e0, 0x8f85002c, 0x431021,
-0x30847fff, 0x42040, 0x441021, 0x3043007f,
-0x3432021, 0x3c03000e, 0x832021, 0x2403ff80,
-0x431024, 0xaf42002c, 0xa4920000, 0x8ca20028,
-0x24420001, 0xaca20028, 0x8ca2002c, 0x8e03002c,
-0x431021, 0xaca2002c, 0x8e02002c, 0xaca20030,
-0x8e020014, 0xaca20034, 0x94a2003a, 0x24420001,
-0xa4a2003a, 0x94c600e0, 0x3c020800, 0x8c4231b0,
-0x24c40001, 0x30837fff, 0x14620013, 0x803021,
-0x24028000, 0x823024, 0x30c2ffff, 0x213c2,
-0x304200ff, 0x21027, 0xa001981, 0x233c0,
-0x2602021, 0x2402000d, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x27bd0028,
-0xa00158b, 0xa382004c, 0x8f820028, 0x2602021,
-0x24050001, 0xe00168c, 0xa44600e0, 0x2021,
-0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x801021, 0x3e00008, 0x27bd0028,
-0x27bdffe0, 0xafb10014, 0x8f910034, 0xafb00010,
-0xafbf0018, 0x8e260010, 0x3c030800, 0x8c6331b0,
-0x30c23fff, 0x43102b, 0x1040005e, 0x808021,
-0x8f850038, 0x2402ff80, 0x90a3000d, 0x431024,
-0x304200ff, 0x50400058, 0x2002021, 0x8f82003c,
-0x10400008, 0x61382, 0x8f820028, 0x9763000a,
-0x2404fffd, 0x94420060, 0x3042ffff, 0x10430055,
-0x61382, 0x30420003, 0x1440000e, 0x0,
-0x92220002, 0x10400005, 0x8e230024, 0x50600015,
-0x92230003, 0xa0019ba, 0x2002021, 0x8ca20024,
-0x50620010, 0x92230003, 0x2002021, 0xa0019c2,
-0x2402000f, 0x90a2000d, 0x30420008, 0x54400009,
-0x92230003, 0x2002021, 0x24020010, 0xe00158b,
-0xa382004c, 0x2403ffff, 0x1043003a, 0x2404ffff,
-0x92230003, 0x24020002, 0x5462000c, 0x92220003,
-0x8f82003c, 0x54400009, 0x92220003, 0x2002021,
-0x2402002c, 0xe00158b, 0xa382004c, 0x2403ffff,
-0x1043002c, 0x2404ffff, 0x92220003, 0x2202821,
-0x2002021, 0x38460010, 0x2cc60001, 0x2c420001,
-0xe0015ab, 0x463025, 0x2411ffff, 0x10510021,
-0x2404ffff, 0x8f83003c, 0x10600012, 0x2002021,
-0x3c020800, 0x8c42318c, 0x43102b, 0x14400006,
-0x0, 0x2821, 0xe0016d9, 0x24060001,
-0xa001a00, 0x2021, 0x2402002d, 0xe00158b,
-0xa382004c, 0x1051000f, 0x2404ffff, 0xa001a00,
-0x2021, 0xe00168c, 0x24050001, 0xa001a00,
-0x2021, 0x2002021, 0x2402000d, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x27bd0020, 0xa00158b,
-0xa382004c, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0x801021, 0x3e00008, 0x27bd0020, 0x93830040,
-0x27bdffe0, 0x24020002, 0xafb10014, 0xafb00010,
-0x808821, 0xafbf0018, 0x8021, 0x1062008c,
-0x2404fffd, 0x97850042, 0x8f830044, 0x30a2ffff,
-0x43102b, 0x5440007d, 0x8f840048, 0xe00144c,
-0x0, 0x3c020800, 0x24427594, 0x2202021,
-0x402821, 0xe001612, 0xaf820034, 0x2409ffff,
-0x1049007b, 0x2404ffff, 0x3c080800, 0x8d0875a4,
-0x3c020800, 0x8c4231b0, 0x3c030800, 0x90637594,
+0xa0830060, 0x2002021, 0x2202821, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0xa0015f9, 0x27bd0020,
+0x91420063, 0x2403ff80, 0x431025, 0xa1420063,
+0x9782003a, 0x3048ffff, 0x11000020, 0x9383001c,
+0x8f840014, 0x4b1023, 0x304600ff, 0x948300e4,
+0x2402efff, 0x168282b, 0x621824, 0xa48300e4,
+0x14a00003, 0x8e020020, 0x1005821, 0x3021,
+0x2403fffb, 0x34e78000, 0x431024, 0xae020020,
+0x24020001, 0x15820005, 0x3165ffff, 0xe001554,
+0x2002021, 0xa0016b9, 0x9783003a, 0xe001585,
+0x2002021, 0x9783003a, 0x8f82003c, 0xa780003a,
+0x431023, 0xaf82003c, 0x9383001c, 0x8f820014,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x27bd0020,
+0x3e00008, 0xa04300bd, 0x93820044, 0x24030001,
+0x27bdffe8, 0x433004, 0x2c420020, 0xafb00010,
+0xafbf0014, 0x2410fffe, 0x10400005, 0x27450180,
+0x3c020800, 0x8c423190, 0xa0016d6, 0x461024,
+0x3c020800, 0x8c423194, 0x461024, 0x14400007,
+0x24060084, 0x8f830014, 0x2410ffff, 0x90620062,
+0x3042000f, 0x34420040, 0xa0620062, 0xe0015d6,
+0x0, 0x2001021, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x8f830024, 0x27bdffe0,
+0xafb20018, 0xafb10014, 0xafb00010, 0xafbf001c,
+0x9062000d, 0xa09021, 0x30d100ff, 0x3042007f,
+0xa062000d, 0x8f850014, 0x8e430018, 0x808021,
+0x8ca2007c, 0x14620005, 0x2402000e, 0x90a20063,
+0x34420020, 0xa0016ff, 0xa0a20063, 0xe0016c5,
+0xa3820044, 0x2403ffff, 0x10430047, 0x2404ffff,
+0x52200045, 0x2021, 0x8e430000, 0x3c020010,
+0x621024, 0x50400004, 0x3c020008, 0x2002021,
+0xa00170e, 0x24020015, 0x621024, 0x50400009,
+0x8e450000, 0x2002021, 0x24020014, 0xe0016c5,
+0xa3820044, 0x2403ffff, 0x10430033, 0x2404ffff,
+0x8e450000, 0x3c020002, 0xa21024, 0x10400016,
+0x3c020004, 0x8f860024, 0x8cc20014, 0x8cc30010,
+0x8cc40014, 0x431023, 0x44102b, 0x50400005,
+0x2002021, 0x8e43002c, 0x8cc20010, 0x10620003,
+0x2002021, 0xa00173f, 0x24020012, 0x3c020004,
+0xa21024, 0x5040001c, 0x2021, 0x2002021,
+0xa00173f, 0x24020013, 0xa21024, 0x10400006,
+0x8f830024, 0x8c620010, 0x50400013, 0x2021,
+0xa001739, 0x2002021, 0x8c620010, 0x50400004,
+0x8e42002c, 0x2002021, 0xa00173f, 0x24020011,
+0x50400009, 0x2021, 0x2002021, 0x24020017,
+0xe0016c5, 0xa3820044, 0x2403ffff, 0x10430002,
+0x2404ffff, 0x2021, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x801021, 0x3e00008,
+0x27bd0020, 0x8f830014, 0x27bdffd8, 0xafb40020,
+0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010,
+0xafbf0024, 0x90620063, 0x8f91002c, 0x2412ffff,
+0x34420040, 0x92250000, 0xa0620063, 0x8e220010,
+0x809821, 0x30b0003f, 0x10520006, 0x360a021,
+0x2402000d, 0xe0016c5, 0xa3820044, 0x10520054,
+0x2404ffff, 0x8f830014, 0x8e220018, 0x8c63007c,
+0x10430007, 0x2602021, 0x2402000e, 0xe0016c5,
+0xa3820044, 0x2403ffff, 0x10430049, 0x2404ffff,
+0x24040020, 0x12040004, 0x8f830014, 0x90620063,
+0x34420020, 0xa0620063, 0x8f850034, 0x10a00020,
+0x0, 0x56040004, 0x8f820014, 0x2602021,
+0xa001790, 0x2402000a, 0x9683000a, 0x94420060,
+0x3042ffff, 0x14430004, 0x8f820020, 0x2404fffd,
+0xa0017b7, 0xaf82003c, 0x3c020800, 0x8c42318c,
+0x45102b, 0x14400006, 0x2602021, 0x2821,
+0xe001646, 0x24060001, 0xa0017b7, 0x2021,
+0x2402002d, 0xe0016c5, 0xa3820044, 0x2403ffff,
+0x10430023, 0x2404ffff, 0xa0017b7, 0x2021,
+0x16040005, 0x8f840014, 0x8e230014, 0x2402ffff,
+0x50620018, 0x2602021, 0x94820060, 0x24420001,
+0xa4820060, 0x94820060, 0x3c030800, 0x8c633188,
+0x30427fff, 0x5443000f, 0x2602021, 0x94820060,
+0x24038000, 0x431024, 0xa4820060, 0x90820060,
+0x90830060, 0x304200ff, 0x211c2, 0x21027,
+0x211c0, 0x3063007f, 0x621825, 0xa0830060,
+0x2602021, 0xe0015f9, 0x24050001, 0x2021,
+0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x801021, 0x3e00008,
+0x27bd0028, 0x8f830014, 0x27bdffe8, 0xafb00010,
+0xafbf0014, 0x90620063, 0x8f87002c, 0x808021,
+0x34420040, 0x8ce60010, 0xa0620063, 0x3c030800,
+0x8c6331b0, 0x30c23fff, 0x43102b, 0x1040004e,
+0x8f850030, 0x2402ff80, 0x90a3000d, 0x431024,
+0x304200ff, 0x50400049, 0x2002021, 0x61382,
+0x30480003, 0x24020002, 0x55020044, 0x2002021,
+0x94a2001c, 0x8f850014, 0x24030023, 0xa4a20114,
+0x8ce60000, 0x61602, 0x3042003f, 0x10430010,
+0x3c030083, 0x8ce30018, 0x8ca2007c, 0x10620006,
+0x2402000e, 0xe0016c5, 0xa3820044, 0x2403ffff,
+0x10430038, 0x2404ffff, 0x8f830014, 0x90620063,
+0x34420020, 0xa0620063, 0xa0017fc, 0x8f830024,
+0xc31024, 0x14430007, 0x8f830024, 0x90a20062,
+0x3042000f, 0x34420020, 0xa0a20062, 0xa3880038,
+0x8f830024, 0x9062000d, 0x3042007f, 0xa062000d,
+0x8f830034, 0x10600018, 0x2002021, 0x8f840030,
+0x8c820010, 0x43102b, 0x10400009, 0x24020018,
+0x2002021, 0xe0016c5, 0xa3820044, 0x2403ffff,
+0x10430018, 0x2404ffff, 0xa001824, 0x2021,
+0x8c820010, 0x24050001, 0x2002021, 0x431023,
+0x8f830024, 0x24060001, 0xe001646, 0xac620010,
+0xa001824, 0x2021, 0xe0015f9, 0x24050001,
+0xa001824, 0x2021, 0x2002021, 0x2402000d,
+0x8fbf0014, 0x8fb00010, 0x27bd0018, 0xa0016c5,
+0xa3820044, 0x8fbf0014, 0x8fb00010, 0x801021,
+0x3e00008, 0x27bd0018, 0x27bdffc8, 0xafb20020,
+0xafbf0034, 0xafb60030, 0xafb5002c, 0xafb40028,
+0xafb30024, 0xafb1001c, 0xafb00018, 0x8f460128,
+0x3c030800, 0x8c6331a0, 0x2402ff80, 0xaf860048,
+0xc31821, 0x3065007f, 0x3452821, 0x621824,
+0x3c02000a, 0xaf430024, 0xa22821, 0x90a20062,
+0x809021, 0xaf850014, 0x304200ff, 0x21102,
+0xa3820038, 0x90a200bc, 0x30420002, 0x14400002,
+0x24030034, 0x24030030, 0x8f820014, 0xa3830028,
+0x93830038, 0x8c4200c0, 0xa3800044, 0xaf82003c,
+0x24020004, 0x10620314, 0x8f84003c, 0x8e440004,
+0x50800311, 0x8f84003c, 0x8e420010, 0x3083ffff,
+0xa784003a, 0x106002f7, 0xaf820040, 0x8f840014,
+0x2403ff80, 0x90820063, 0x621024, 0x304200ff,
+0x144002c7, 0x9785003a, 0x93830038, 0x24020002,
+0x30b6ffff, 0x14620005, 0x8821, 0x93820028,
+0x2403fffd, 0xa001b11, 0xaf82003c, 0x8f82003c,
+0x2c2102b, 0x14400299, 0x8f840040, 0xe0014ec,
+0x0, 0x93830028, 0x3c040800, 0x24847778,
+0x24020034, 0x1462002e, 0xaf84002c, 0x3c0a0800,
+0x8d4a77a8, 0x2402ffff, 0xafa20010, 0x803821,
+0x2405002f, 0x3c090800, 0x25297378, 0x240800ff,
+0x2406ffff, 0x90e20000, 0x24a3ffff, 0x62202,
+0xc21026, 0x304200ff, 0x21080, 0x491021,
+0x8c420000, 0x306500ff, 0x24e70001, 0x14a8fff5,
+0x823026, 0x61027, 0xafa20014, 0xafa20010,
+0x2821, 0x27a70010, 0x27a60014, 0xc51023,
+0x90440003, 0x24a20001, 0xa71821, 0x304500ff,
+0x2ca20004, 0x1440fff9, 0xa0640000, 0x8fa20010,
+0x11420007, 0x24020005, 0x2402021, 0xe0016c5,
+0xa3820044, 0x2403ffff, 0x10430064, 0x2404ffff,
+0x3c020800, 0x9042777c, 0x10400009, 0x8f820014,
+0x2402021, 0x2402000c, 0xe0016c5, 0xa3820044,
+0x2403ffff, 0x10430059, 0x2404ffff, 0x8f820014,
+0xa380001c, 0x3c030800, 0x8c63777c, 0x8c440080,
+0x3c0200ff, 0x3442ffff, 0x621824, 0x83202b,
+0x10800008, 0xaf830034, 0x2402021, 0x24020019,
+0xe0016c5, 0xa3820044, 0x2403ffff, 0x10430047,
+0x2404ffff, 0x8f87003c, 0x9782003a, 0x8f850034,
+0xaf870020, 0x472023, 0x10a0003b, 0xa784003a,
+0x8f860014, 0x30a20003, 0x21023, 0x90c300bc,
+0x30500003, 0xb02821, 0x31882, 0x30730001,
+0x131080, 0xa22821, 0x3c030800, 0x8c6331a0,
+0x8f820048, 0x3084ffff, 0x85202b, 0x431021,
+0x10800011, 0x24420088, 0x8f84002c, 0x1082000e,
+0x3c033f01, 0x3c020800, 0x8c427778, 0x431024,
+0x3c032500, 0x14430006, 0x30e500ff, 0x8c820000,
+0xacc20088, 0x8c820010, 0xa0018e9, 0xacc20098,
+0xe001529, 0x3021, 0x9382001c, 0x8f850014,
+0x8f830040, 0x2023821, 0x8f82003c, 0xa387001c,
+0x94a400e4, 0x621821, 0x8f820034, 0x34841000,
+0xaf830040, 0x503021, 0xa4a400e4, 0x1260000e,
+0xaf86003c, 0x24e20004, 0xa382001c, 0x94a200e4,
+0x24c30004, 0xaf83003c, 0x34422000, 0xa4a200e4,
+0xa001906, 0x2021, 0x8f820040, 0xaf80003c,
+0x471021, 0xaf820040, 0x2021, 0x2414ffff,
+0x10940209, 0x2403ffff, 0x3c080800, 0x8d087788,
+0x3c020800, 0x8c4231b0, 0x3c030800, 0x90637778,
0x31043fff, 0x82102b, 0x1040001b, 0x3067003f,
-0x3c020800, 0x8c4231a8, 0x8f830050, 0x42180,
+0x3c020800, 0x8c4231a8, 0x8f830048, 0x42180,
0x621821, 0x641821, 0x3062007f, 0x3422821,
0x3c02000c, 0xa22821, 0x3c020080, 0x34420001,
0x30660078, 0xc23025, 0x2402ff80, 0x621024,
-0xaf420028, 0x30640007, 0xaf420804, 0x8f820028,
-0x3442021, 0x24840940, 0xaf460814, 0xaf85002c,
-0xaf840038, 0xac430118, 0x93830040, 0x24020003,
-0x1462003b, 0x24020001, 0x24020026, 0x10e2003d,
+0xaf420028, 0x30640007, 0xaf420804, 0x8f820014,
+0x3442021, 0x24840940, 0xaf460814, 0xaf850024,
+0xaf840030, 0xac430118, 0x93830038, 0x24020003,
+0x146201c7, 0x24020001, 0x24020026, 0x10e201c9,
0x28e20027, 0x10400013, 0x24020032, 0x24020022,
-0x10e20038, 0x28e20023, 0x10400008, 0x24020024,
-0x24020020, 0x10e20024, 0x24020021, 0x10e2001e,
-0x2202021, 0xa001a7f, 0x2402000b, 0x10e2002d,
-0x24020025, 0x10e20010, 0x2202021, 0xa001a7f,
-0x2402000b, 0x10e2001a, 0x28e20033, 0x10400006,
-0x2402003f, 0x24020031, 0x10e2000b, 0x2202021,
-0xa001a7f, 0x2402000b, 0x10e20011, 0x2202021,
-0xa001a7f, 0x2402000b, 0xe00176c, 0x2202021,
-0xa001a9a, 0x408021, 0xe0018ee, 0x2202021,
-0xa001a9a, 0x408021, 0xe00198f, 0x2202021,
-0xa001a9a, 0x408021, 0x1509000e, 0x0,
-0xe001813, 0x2202021, 0xa001a9a, 0x408021,
-0xe00158b, 0xa382004c, 0xa001a9a, 0x408021,
-0x14620017, 0x2002021, 0x24020023, 0x14e20005,
-0x2402000b, 0xe001885, 0x2202021, 0xa001a9a,
-0x408021, 0x2202021, 0xa382004c, 0xe00158b,
-0x2410ffff, 0xa001a9b, 0x2002021, 0x30a500ff,
-0xe001489, 0x24060001, 0x97830042, 0x8f820044,
-0xa7800042, 0x431023, 0xaf820044, 0x2002021,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x801021,
-0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafb10014,
-0xafbf0018, 0xafb00010, 0x8f460128, 0x3c030800,
-0x8c6331a0, 0x2402ff80, 0xaf860050, 0xc31821,
-0x3065007f, 0x3452821, 0x621824, 0x3c02000a,
-0xaf430024, 0xa22821, 0x90a20062, 0x808821,
-0xaf850028, 0x304200ff, 0x21102, 0xa3820040,
-0x90a200bc, 0x30420002, 0x14400002, 0x24030034,
-0x24030030, 0x8f820028, 0xa3830030, 0x93830040,
-0x8c4200c0, 0xa380004c, 0xaf820044, 0x24020004,
-0x10620030, 0x8f840044, 0x8e240004, 0x5080002d,
-0x8f840044, 0x8e220010, 0x3083ffff, 0xa7840042,
-0x1060001f, 0xaf820048, 0x8f830028, 0x2405ff80,
-0x2202021, 0x90620063, 0xa21024, 0x304200ff,
-0x1440000d, 0x0, 0xe001a06, 0x97900042,
-0x10400010, 0x401821, 0x2402fffd, 0x54620011,
-0x8e230020, 0x2002821, 0xe00142a, 0x2202021,
-0xa001aec, 0x8e230020, 0x90620063, 0xa21024,
-0x304200ff, 0x10400003, 0x2202021, 0xe00174e,
-0x0, 0x97820042, 0x1440ffe4, 0x8f830028,
-0x8e230020, 0x30620004, 0x10400006, 0x8f840044,
-0x2402fffb, 0x621024, 0xe00143e, 0xae220020,
-0x8f840044, 0x8f830028, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x24020001, 0x27bd0020, 0x3e00008,
-0xac6400c0, 0x30a500ff, 0x24030001, 0x24a90001,
-0x69102b, 0x1040000c, 0x4021, 0x240a0001,
-0xa31023, 0x4a3804, 0x24630001, 0x30820001,
-0x69302b, 0x10400002, 0x42042, 0x1074025,
-0x54c0fff8, 0xa31023, 0x3e00008, 0x1001021,
-0x27bdffe0, 0x3c021edc, 0xafb20018, 0xafb10014,
-0xafbf001c, 0xafb00010, 0x34526f41, 0x8821,
-0x24050008, 0xe001afc, 0x2202021, 0x118080,
-0x3c070800, 0x24e77194, 0x21600, 0x2071821,
-0xac620000, 0x2821, 0x24a20001, 0x3045ffff,
-0x8c620000, 0x2ca60008, 0x4410002, 0x22040,
-0x922026, 0x14c0fff8, 0xac640000, 0x2078021,
-0x8e040000, 0xe001afc, 0x24050020, 0x26230001,
-0x3071ffff, 0x2e230100, 0x1460ffe5, 0xae020000,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x3c020800, 0x24426a84,
-0x3c010800, 0xac227188, 0x3c020800, 0x24425000,
-0x3c010800, 0xac22718c, 0x24020006, 0x3c010800,
-0xa0227190, 0xa001b0f, 0x0, 0x27bdffd8,
+0x10e201c4, 0x28e20023, 0x10400008, 0x24020024,
+0x24020020, 0x10e201b0, 0x24020021, 0x10e2013f,
+0x2402021, 0xa001af3, 0x2402000b, 0x10e201b9,
+0x24020025, 0x10e20010, 0x2402021, 0xa001af3,
+0x2402000b, 0x10e201a6, 0x28e20033, 0x10400006,
+0x2402003f, 0x24020031, 0x10e20092, 0x2402021,
+0xa001af3, 0x2402000b, 0x10e2019d, 0x2402021,
+0xa001af3, 0x2402000b, 0x8f90002c, 0x3c030800,
+0x8c6331b0, 0x8f850030, 0x8e040010, 0xa821,
+0x8cb30014, 0x30823fff, 0x43102b, 0x8cb10020,
+0x50400187, 0x2402021, 0x90a3000d, 0x2402ff80,
+0x431024, 0x304200ff, 0x50400181, 0x2402021,
+0x41382, 0x30420003, 0x1440017d, 0x2402021,
+0x94a3001c, 0x8f820014, 0x8e040028, 0xa4430114,
+0x8ca20010, 0x2621823, 0x10640003, 0x2402021,
+0xa00197c, 0x2402001f, 0x8f820034, 0x621021,
+0x262102b, 0x10400008, 0x8f830024, 0x2402021,
+0x24020018, 0xe0016c5, 0xa3820044, 0x1054016c,
+0x2404ffff, 0x8f830024, 0x8f840034, 0x8c620010,
+0x2248821, 0x441023, 0xac620010, 0x8f820014,
+0xac710020, 0x8c420068, 0x51102b, 0x10400009,
+0x8f830030, 0x2402021, 0x2402001d, 0xe0016c5,
+0xa3820044, 0x2403ffff, 0x10430159, 0x2404ffff,
+0x8f830030, 0x8e020024, 0x8c630024, 0x10430007,
+0x2402021, 0x2402001c, 0xe0016c5, 0xa3820044,
+0x2403ffff, 0x1043014e, 0x2404ffff, 0x8f840024,
+0x8c820024, 0x24420001, 0xac820024, 0x12330004,
+0x8f820014, 0x8c420068, 0x5622000e, 0x8e020000,
+0x8e020000, 0x3c030080, 0x431024, 0x1440000d,
+0x2402001a, 0x2402021, 0xe0016c5, 0xa3820044,
+0x2403ffff, 0x1043013a, 0x2404ffff, 0xa0019ba,
+0x8e020014, 0x3c030080, 0x431024, 0x50400003,
+0x8e020014, 0xac800020, 0x8e020014, 0x2411ffff,
+0x10510006, 0x2402001b, 0x2402021, 0xe0016c5,
+0xa3820044, 0x1051012a, 0x2404ffff, 0x8e030000,
+0x3c020001, 0x621024, 0x10400012, 0x3c020080,
+0x621024, 0x14400008, 0x2402021, 0x2402001a,
+0xe0016c5, 0xa3820044, 0x2403ffff, 0x1043011c,
+0x2404ffff, 0x2402021, 0x2002821, 0xe0016e5,
+0x24060001, 0x2403ffff, 0x10430115, 0x2404ffff,
+0x24150001, 0x8f830024, 0x2a03021, 0x2402021,
+0x94620036, 0x24050001, 0x24420001, 0xa001ad7,
+0xa4620036, 0x8f90002c, 0x3c030800, 0x8c6331b0,
+0x8e130010, 0x32623fff, 0x43102b, 0x10400089,
+0x8f840030, 0x2402ff80, 0x9083000d, 0x431024,
+0x304200ff, 0x10400084, 0x2402000d, 0x131382,
+0x30420003, 0x24030001, 0x1443007f, 0x2402000d,
+0x9082000d, 0x30420008, 0x54400004, 0x8f820034,
+0x2402021, 0xa001a08, 0x24020024, 0x50400004,
+0x8e03000c, 0x2402021, 0xa001a08, 0x24020027,
+0x8c820020, 0x54620006, 0x2402021, 0x8e030008,
+0x8c820024, 0x50620009, 0x8e020014, 0x2402021,
+0x24020020, 0xe0016c5, 0xa3820044, 0x10540071,
+0x2403ffff, 0xa001a3d, 0x8f840024, 0x2411ffff,
+0x14510004, 0x8f860014, 0x2402021, 0xa001a38,
+0x24020025, 0x8e030018, 0x8cc2007c, 0x10620003,
+0x2402000e, 0xa001a38, 0x2402021, 0x8e030024,
+0x8c820028, 0x10620003, 0x24020021, 0xa001a38,
+0x2402021, 0x8e050028, 0x8c82002c, 0x10a20003,
+0x2402001f, 0xa001a38, 0x2402021, 0x8e03002c,
+0x14600003, 0x24020023, 0xa001a38, 0x2402021,
+0x8cc20068, 0x43102b, 0x10400003, 0x24020026,
+0xa001a38, 0x2402021, 0x8c820014, 0x651821,
+0x43102b, 0x10400008, 0x8f840024, 0x2402021,
+0x24020022, 0xe0016c5, 0xa3820044, 0x10510041,
+0x2403ffff, 0x8f840024, 0x2403fff7, 0x9082000d,
+0x431024, 0xa082000d, 0x8f860014, 0x3c030800,
+0x8c6331ac, 0x8f820048, 0x94c400e0, 0x8f850024,
+0x431021, 0x30847fff, 0x42040, 0x441021,
+0x3043007f, 0x3432021, 0x3c03000e, 0x832021,
+0x2403ff80, 0x431024, 0xaf42002c, 0xa4930000,
+0x8ca20028, 0x24420001, 0xaca20028, 0x8ca2002c,
+0x8e03002c, 0x431021, 0xaca2002c, 0x8e02002c,
+0xaca20030, 0x8e020014, 0xaca20034, 0x94a2003a,
+0x24420001, 0xa4a2003a, 0x94c600e0, 0x3c020800,
+0x8c4231b0, 0x24c40001, 0x30837fff, 0x1462000f,
+0x803021, 0x24028000, 0x823024, 0x30c2ffff,
+0x213c2, 0x304200ff, 0x21027, 0xa001a76,
+0x233c0, 0x2402000d, 0x2402021, 0xe0016c5,
+0xa3820044, 0xa001a7c, 0x401821, 0x8f820014,
+0x2402021, 0x24050001, 0xe0015f9, 0xa44600e0,
+0x1821, 0xa001b0e, 0x608821, 0x8f90002c,
+0x3c030800, 0x8c6331b0, 0x8e050010, 0x30a23fff,
+0x43102b, 0x10400061, 0x2402ff80, 0x8f840030,
+0x9083000d, 0x431024, 0x304200ff, 0x5040005c,
+0x2402021, 0x8f820034, 0x1040000b, 0x51382,
+0x8f820014, 0x9763000a, 0x94420060, 0x3042ffff,
+0x14430005, 0x51382, 0x8f820020, 0x2404fffd,
+0xa001aeb, 0xaf82003c, 0x30420003, 0x1440000e,
+0x0, 0x92020002, 0x10400005, 0x8e030024,
+0x50600015, 0x92030003, 0xa001aa7, 0x2402021,
+0x8c820024, 0x50620010, 0x92030003, 0x2402021,
+0xa001aaf, 0x2402000f, 0x9082000d, 0x30420008,
+0x54400009, 0x92030003, 0x2402021, 0x24020010,
+0xe0016c5, 0xa3820044, 0x2403ffff, 0x10430038,
+0x2404ffff, 0x92030003, 0x24020002, 0x5462000c,
+0x92020003, 0x8f820034, 0x54400009, 0x92020003,
+0x2402021, 0x2402002c, 0xe0016c5, 0xa3820044,
+0x2403ffff, 0x1043002a, 0x2404ffff, 0x92020003,
+0x2002821, 0x2402021, 0x38460010, 0x2cc60001,
+0x2c420001, 0xe0016e5, 0x463025, 0x2410ffff,
+0x1050001f, 0x2404ffff, 0x8f830034, 0x10600013,
+0x2402021, 0x3c020800, 0x8c42318c, 0x43102b,
+0x14400007, 0x0, 0x2821, 0x24060001,
+0xe001646, 0x0, 0xa001aeb, 0x2021,
+0x2402002d, 0xe0016c5, 0xa3820044, 0x1050000c,
+0x2404ffff, 0xa001aeb, 0x2021, 0xe0015f9,
+0x24050001, 0xa001aeb, 0x2021, 0x2402021,
+0x2402000d, 0xe0016c5, 0xa3820044, 0x402021,
+0xa001b0e, 0x808821, 0x1514000e, 0x0,
+0xe00174c, 0x2402021, 0xa001b0e, 0x408821,
+0xe0016c5, 0xa3820044, 0xa001b0e, 0x408821,
+0x14620017, 0x2201821, 0x24020023, 0x14e20005,
+0x2402000b, 0xe0017c0, 0x2402021, 0xa001b0e,
+0x408821, 0x2402021, 0xa3820044, 0xe0016c5,
+0x2411ffff, 0xa001b0f, 0x2201821, 0x30a500ff,
+0xe001529, 0x24060001, 0x9783003a, 0x8f82003c,
+0xa780003a, 0x431023, 0xaf82003c, 0x2201821,
+0x1220003e, 0x9782003a, 0x2402fffd, 0x5462003e,
+0x8e430020, 0x8e420004, 0x8f830014, 0x561023,
+0xae420004, 0x90620063, 0x3042007f, 0xa0620063,
+0x8e420020, 0x8f840014, 0xa780003a, 0x34420002,
+0xae420020, 0xa48000e4, 0x90820063, 0x2403ffbf,
+0x431024, 0xa0820063, 0xa001b51, 0x8e430020,
+0x90820063, 0x621024, 0x304200ff, 0x10400023,
+0x9782003a, 0x90820088, 0x908300bd, 0x24850088,
+0x3042003f, 0x2444ffe0, 0x2c820020, 0xa383001c,
+0x10400019, 0xaf85002c, 0x24020001, 0x821804,
+0x30620019, 0x1440000c, 0x3c028000, 0x34420002,
+0x621024, 0x1440000b, 0x30620020, 0x1040000f,
+0x9782003a, 0x90a60001, 0x2402021, 0x24050001,
+0xa001b4b, 0x30c60001, 0x2402021, 0xa001b4a,
+0x24050001, 0x2402021, 0x2821, 0x24060001,
+0xe001646, 0x0, 0x9782003a, 0x1440fd0c,
+0x8f840014, 0x8e430020, 0x30620004, 0x10400012,
+0x8f84003c, 0x2402fffb, 0x621024, 0xae420020,
+0x27430180, 0x8f4201b8, 0x440fffe, 0x8f820048,
+0xac620000, 0x8f420124, 0xac620004, 0x24026083,
+0xa4620008, 0x24020002, 0xa062000b, 0x3c021000,
+0xaf4201b8, 0x8f84003c, 0x8f830014, 0x8fbf0034,
+0x8fb60030, 0x8fb5002c, 0x8fb40028, 0x8fb30024,
+0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x24020001,
+0x27bd0038, 0x3e00008, 0xac6400c0, 0x30a500ff,
+0x24030001, 0x24a90001, 0x69102b, 0x1040000c,
+0x4021, 0x240a0001, 0xa31023, 0x4a3804,
+0x24630001, 0x30820001, 0x69302b, 0x10400002,
+0x42042, 0x1074025, 0x54c0fff8, 0xa31023,
+0x3e00008, 0x1001021, 0x3c020800, 0x244260a4,
+0x3c010800, 0xac22736c, 0x3c020800, 0x24425308,
+0x3c010800, 0xac227370, 0x24020006, 0x27bdffe0,
+0x3c010800, 0xa0227374, 0x3c021edc, 0xafb20018,
+0xafb10014, 0xafbf001c, 0xafb00010, 0x34526f41,
+0x8821, 0x24050008, 0xe001b72, 0x2202021,
+0x118080, 0x3c070800, 0x24e77378, 0x21600,
+0x2071821, 0xac620000, 0x2821, 0x24a20001,
+0x3045ffff, 0x8c620000, 0x2ca60008, 0x4410002,
+0x22040, 0x922026, 0x14c0fff8, 0xac640000,
+0x2078021, 0x8e040000, 0xe001b72, 0x24050020,
+0x26230001, 0x3071ffff, 0x2e230100, 0x1460ffe5,
+0xae020000, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffd8,
0xafb3001c, 0xafb20018, 0xafbf0020, 0xafb10014,
0xafb00010, 0x8f510140, 0x8f480148, 0x89402,
0x324300ff, 0x311300ff, 0x8f4201b8, 0x440fffe,
@@ -3085,502 +3058,512 @@ u32 bce_RXP_b06FwText[(0x70dc/4) + 1] = {
0x24020002, 0xa6120008, 0xa202000b, 0x24020014,
0xae130024, 0x10620025, 0x28620015, 0x10400008,
0x24020015, 0x24020010, 0x10620030, 0x24020012,
-0x10620009, 0x8fbf0020, 0xa001c30, 0x8fb3001c,
-0x10620067, 0x24020022, 0x10620037, 0x8fbf0020,
-0xa001c30, 0x8fb3001c, 0x3c020800, 0x8c4231a0,
+0x10620009, 0x8fbf0020, 0xa001cad, 0x8fb3001c,
+0x10620070, 0x24020022, 0x10620037, 0x8fbf0020,
+0xa001cad, 0x8fb3001c, 0x3c020800, 0x8c4231a0,
0x2403ff80, 0x2221021, 0x431024, 0xaf420024,
0x3c020800, 0x8c4231a0, 0x2221021, 0x3042007f,
-0x3421821, 0x3c02000a, 0x621821, 0x166000b3,
-0xaf830028, 0x90620062, 0x3042000f, 0x34420030,
-0xa0620062, 0xa001c2f, 0x8fbf0020, 0x3c046000,
+0x3421821, 0x3c02000a, 0x621821, 0x166000bc,
+0xaf830014, 0x90620062, 0x3042000f, 0x34420030,
+0xa0620062, 0xa001cac, 0x8fbf0020, 0x3c046000,
0x8c832c08, 0x3c02f003, 0x3442ffff, 0x621824,
0xac832c08, 0x3c020800, 0x8c4231a0, 0x8c832c08,
0x24420074, 0x21082, 0x21480, 0x621825,
-0xac832c08, 0xa001c2f, 0x8fbf0020, 0x3c020800,
+0xac832c08, 0xa001cac, 0x8fbf0020, 0x3c020800,
0x8c4231a0, 0x2403ff80, 0x2221021, 0x431024,
0xaf420024, 0x3c020800, 0x8c4231a0, 0x3c03000a,
0x2221021, 0x3042007f, 0x3421021, 0x431021,
-0xa001c2e, 0xaf820028, 0x3c020800, 0x8c4231a0,
-0x2404ff80, 0x2221021, 0x441024, 0xaf420024,
+0xa001cab, 0xaf820014, 0x3c020800, 0x8c4231a0,
+0x2405ff80, 0x2221021, 0x451024, 0xaf420024,
0x3c020800, 0x8c4231a0, 0x2221021, 0x3042007f,
0x3421821, 0x3c02000a, 0x621821, 0x90620063,
-0x821024, 0x304200ff, 0x1040007c, 0xaf830028,
+0xa21024, 0x304200ff, 0x10400085, 0xaf830014,
0x24620088, 0x94430012, 0x3c020800, 0x8c4231a8,
0x30633fff, 0x31980, 0x2221021, 0x431021,
-0x3043007f, 0x3431821, 0x441024, 0x3c04000c,
-0x641821, 0xaf420028, 0xe00155a, 0xaf83002c,
-0x8f4201b8, 0x440fffe, 0x0, 0xae110000,
-0x8f420144, 0xae020004, 0x24020002, 0xa6120008,
-0xa202000b, 0xae130024, 0xa001c2f, 0x8fbf0020,
-0x2406ff80, 0x2261024, 0xaf420020, 0x3c020800,
-0x8c4231a0, 0x31043fff, 0x42180, 0x2221021,
-0x461024, 0xaf420024, 0x3c030800, 0x8c6331a8,
-0x3c020800, 0x8c4231a0, 0x3227007f, 0x2231821,
-0x2221021, 0x641821, 0x3042007f, 0x3064007f,
-0x3422821, 0x3c02000a, 0x661824, 0xa22821,
-0x3442021, 0x3c02000c, 0x822021, 0xaf430028,
-0x3c020008, 0x3471821, 0x629021, 0xaf850028,
-0xaf84002c, 0xe00155a, 0x1008021, 0x8f4201b8,
-0x440fffe, 0x8f82002c, 0x8f840028, 0x27450180,
-0x9042000d, 0xacb10000, 0xa4b00006, 0x21600,
-0x21603, 0x21027, 0x237c2, 0x14c00016,
-0x24820088, 0x94420012, 0x32033fff, 0x30423fff,
-0x14430012, 0x24026082, 0x90830063, 0x2402ff80,
-0x431024, 0x304200ff, 0x5040000c, 0x24026082,
-0x90820062, 0x3042000f, 0x34420040, 0xa0820062,
-0x24026084, 0xa4a20008, 0x2402000d, 0xa0a20005,
-0xa001c19, 0x3c022700, 0x24026082, 0xa4a20008,
-0xa0a00005, 0x3c022700, 0x61c00, 0x621825,
-0x24020002, 0xa0a2000b, 0xaca30010, 0xaca00014,
-0xaca00024, 0xaca00028, 0xaca0002c, 0x8e42004c,
-0x8f84002c, 0xaca20018, 0x9083000d, 0x2402ff80,
-0x431024, 0x304200ff, 0x10400005, 0x8fbf0020,
-0x9082000d, 0x3042007f, 0xa082000d, 0x8fbf0020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3c021000, 0x27bd0028, 0x3e00008, 0xaf4201b8,
-0x0 };
-u32 bce_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
-u32 bce_RXP_b06FwRodata[(0x24/4) + 1] = {
-0x8004c28,
-0x8004c28, 0x8004ba0, 0x8004bd8, 0x8004c0c,
-0x8004c30, 0x8004c30, 0x8004c30, 0x8004b10,
+0x3043007f, 0x3432021, 0x451024, 0x3c03000c,
+0x832021, 0xaf420028, 0x9082000d, 0xa21024,
+0x304200ff, 0x10400072, 0xaf840024, 0x9082000d,
+0x30420010, 0x1440006f, 0x8fbf0020, 0xe0015c8,
+0x0, 0x8f4201b8, 0x440fffe, 0x0,
+0xae110000, 0x8f420144, 0xae020004, 0x24020002,
+0xa6120008, 0xa202000b, 0xae130024, 0xa001cac,
+0x8fbf0020, 0x2406ff80, 0x2261024, 0xaf420020,
+0x3c020800, 0x8c4231a0, 0x31043fff, 0x42180,
+0x2221021, 0x461024, 0xaf420024, 0x3c030800,
+0x8c6331a8, 0x3c020800, 0x8c4231a0, 0x3227007f,
+0x2231821, 0x2221021, 0x641821, 0x3042007f,
+0x3064007f, 0x3422821, 0x3c02000a, 0x661824,
+0xa22821, 0x3442021, 0x3c02000c, 0x822021,
+0xaf430028, 0x3c020008, 0x3471821, 0x629021,
+0xaf850014, 0xaf840024, 0xe0015c8, 0x1008021,
+0x8f4201b8, 0x440fffe, 0x8f820024, 0x8f840014,
+0x27450180, 0x9042000d, 0xacb10000, 0xa4b00006,
+0x21600, 0x21603, 0x21027, 0x237c2,
+0x14c00016, 0x24820088, 0x94420012, 0x32033fff,
+0x30423fff, 0x14430012, 0x24026082, 0x90830063,
+0x2402ff80, 0x431024, 0x304200ff, 0x5040000c,
+0x24026082, 0x90820062, 0x3042000f, 0x34420040,
+0xa0820062, 0x24026084, 0xa4a20008, 0x2402000d,
+0xa0a20005, 0xa001c96, 0x3c022700, 0x24026082,
+0xa4a20008, 0xa0a00005, 0x3c022700, 0x61c00,
+0x621825, 0x24020002, 0xa0a2000b, 0xaca30010,
+0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c,
+0x8e42004c, 0x8f840024, 0xaca20018, 0x9083000d,
+0x2402ff80, 0x431024, 0x304200ff, 0x10400005,
+0x8fbf0020, 0x9082000d, 0x3042007f, 0xa082000d,
+0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3c021000, 0x27bd0028, 0x3e00008,
+0xaf4201b8, 0x0 };
+u32 bce_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
+u32 bce_RXP_b06FwRodata[(0x24/4) + 1] = {
+0x8003430,
+0x8003430, 0x80033a8, 0x80033e0, 0x8003414,
+0x8003438, 0x8003438, 0x8003438, 0x8003318,
0x0 };
-u32 bce_RXP_b06FwBss[(0x450/4) + 1] = { 0x0 };
-u32 bce_RXP_b06FwSbss[(0x54/4) + 1] = { 0x0 };
-u32 bce_RXP_b06FwSdata[(0x0/4) + 1] = { 0x0 };
+u32 bce_RXP_b06FwBss[(0x440/4) + 1] = { 0x0 };
+u32 bce_RXP_b06FwSbss[(0x4c/4) + 1] = { 0x0 };
+u32 bce_RXP_b06FwSdata[(0x0/4) + 1] = { 0x0 };
-int bce_TPAT_b06FwReleaseMajor = 0x1;
-int bce_TPAT_b06FwReleaseMinor = 0x0;
-int bce_TPAT_b06FwReleaseFix = 0x0;
-u32 bce_TPAT_b06FwStartAddr = 0x08000488;
-u32 bce_TPAT_b06FwTextAddr = 0x08000400;
-int bce_TPAT_b06FwTextLen = 0x175c;
-u32 bce_TPAT_b06FwDataAddr = 0x00000000;
-int bce_TPAT_b06FwDataLen = 0x0;
-u32 bce_TPAT_b06FwRodataAddr = 0x00000000;
-int bce_TPAT_b06FwRodataLen = 0x0;
-u32 bce_TPAT_b06FwBssAddr = 0x08001bc4;
-int bce_TPAT_b06FwBssLen = 0x450;
-u32 bce_TPAT_b06FwSbssAddr = 0x08001b80;
-int bce_TPAT_b06FwSbssLen = 0x44;
-u32 bce_TPAT_b06FwSDataAddr = 0x00000000;
-int bce_TPAT_b06FwSDataLen = 0x0;
-u32 bce_TPAT_b06FwText[(0x175c/4) + 1] = {
-0xa000122, 0x0, 0x0,
-0xd, 0x74706134, 0x2e362e31, 0x37000000,
-0x4061101, 0x0, 0x0, 0x0,
+int bce_TPAT_b06FwReleaseMajor = 0x6;
+int bce_TPAT_b06FwReleaseMinor = 0x0;
+int bce_TPAT_b06FwReleaseFix = 0xf;
+u32 bce_TPAT_b06FwStartAddr = 0x08000490;
+u32 bce_TPAT_b06FwTextAddr = 0x08000400;
+int bce_TPAT_b06FwTextLen = 0x17d4;
+u32 bce_TPAT_b06FwDataAddr = 0x00000000;
+int bce_TPAT_b06FwDataLen = 0x0;
+u32 bce_TPAT_b06FwRodataAddr = 0x00000000;
+int bce_TPAT_b06FwRodataLen = 0x0;
+u32 bce_TPAT_b06FwBssAddr = 0x08001c44;
+int bce_TPAT_b06FwBssLen = 0x450;
+u32 bce_TPAT_b06FwSbssAddr = 0x08001c00;
+int bce_TPAT_b06FwSbssLen = 0x44;
+u32 bce_TPAT_b06FwSDataAddr = 0x00000000;
+int bce_TPAT_b06FwSDataLen = 0x0;
+u32 bce_TPAT_b06FwText[(0x17d4/4) + 1] = {
+0xa000124, 0x0, 0x0,
+0xd, 0x74706136, 0x2e302e31, 0x35000000,
+0x6000f01, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
-0x10000003, 0x0, 0xd, 0xd,
-0x3c020800, 0x24421b80, 0x3c030800, 0x24632014,
-0xac400000, 0x43202b, 0x1480fffd, 0x24420004,
-0x3c1d0800, 0x37bd2ffc, 0x3a0f021, 0x3c100800,
-0x26100488, 0x3c1c0800, 0x279c1b80, 0xe00015a,
-0x0, 0xd, 0x3084ffff, 0x30820007,
-0x8f850018, 0x10400002, 0x24830007, 0x3064fff8,
-0x853021, 0x30c41fff, 0x3441821, 0x247b4000,
-0xaf85001c, 0xaf840018, 0x3e00008, 0xaf440084,
-0x3084ffff, 0x30820007, 0x8f850020, 0x8f860028,
-0x10400002, 0x24830007, 0x3064fff8, 0x852021,
-0x86182b, 0x14600002, 0xaf850024, 0x862023,
-0x3442821, 0x34068000, 0xaf840020, 0xaf440080,
-0xa62021, 0x3e00008, 0xaf840038, 0x27bdffd8,
-0xafb3001c, 0xafb20018, 0xafb00010, 0xafbf0024,
-0xafb40020, 0xafb10014, 0x3c086008, 0x8d145000,
-0x2418ff7f, 0x3c1a8000, 0x2989824, 0x3672380c,
-0xad125000, 0x8f510008, 0x3c07601c, 0x3c086000,
-0x36300001, 0xaf500008, 0xaf800018, 0xaf400080,
-0xaf400084, 0x8ce60008, 0x8d0f0808, 0x3c076016,
-0x8cec0000, 0x31eefff0, 0x39ca0010, 0x3c0dffff,
-0x340b8000, 0x3c030080, 0x34b4821, 0x2d440001,
-0x18d2824, 0x3c025353, 0x3c010800, 0xac230420,
-0xaf890038, 0xaf860028, 0xaf840010, 0x275b4000,
-0x14a20003, 0x34e37c00, 0x8cf90004, 0x3281821,
-0x8c7f007c, 0x8c650078, 0x3c028000, 0x34520070,
-0xaf85003c, 0xaf9f0040, 0x3c130800, 0x26731bc4,
-0x240a021, 0x8e480000, 0x8f460000, 0x38c30001,
-0x30640001, 0x10800017, 0xaf880034, 0x2804821,
-0x8d2d0000, 0x3c190800, 0x8f39045c, 0x3c110800,
-0x8e310458, 0x1a8f823, 0x33f7821, 0x4021,
-0x2283821, 0x1ff802b, 0xf07021, 0x3c010800,
-0xac2f045c, 0x3c010800, 0xac2e0458, 0x8f4c0000,
-0x398b0001, 0x316a0001, 0x1540ffed, 0x1a04021,
-0xaf8d0034, 0x8e4e0000, 0x3c0c0800, 0x8d8c045c,
-0x3c0a0800, 0x8d4a0458, 0x1c86823, 0x18d2821,
-0x5821, 0xad302b, 0x14b2021, 0x861021,
-0x3c010800, 0xac25045c, 0x3c010800, 0xac220458,
-0x8f450108, 0x8f440100, 0x30a92000, 0xaf850000,
-0xaf84000c, 0x1120000a, 0xa03021, 0x3c070800,
-0x8ce7042c, 0x24ef0001, 0x3c010800, 0xac2f042c,
-0x3c104000, 0xaf500138, 0xa000190, 0x0,
-0x30b00200, 0x16000014, 0x24110f00, 0x10910012,
-0x24070d00, 0x10870233, 0x30b00006, 0x5200fff5,
-0x3c104000, 0x936d0000, 0x240c0010, 0x31a600f0,
-0x10cc0269, 0x240e0070, 0x10ce02dd, 0x8f8b0014,
-0x25670001, 0xaf870014, 0x3c104000, 0xaf500138,
-0xa000190, 0x0, 0x97480104, 0x1100ffe5,
-0x3c104000, 0x30b84000, 0x170000a2, 0x0,
-0x8f590178, 0x720fffe, 0x8f870038, 0x24090008,
-0x24050800, 0x8ce30008, 0xaf450178, 0xa7490140,
-0xa7400142, 0x97420104, 0x8f860000, 0x3049ffff,
-0x30df0001, 0x13e002d5, 0x1204021, 0x2524fffe,
-0x240a0002, 0xa74a0146, 0x3088ffff, 0xa7440148,
-0x3c0b0800, 0x8d6b043c, 0x156002c4, 0x8f8f000c,
-0x30c30020, 0x14600002, 0x24040009, 0x24040001,
-0x30cd0c00, 0x240c0400, 0x51ac0001, 0x34840004,
-0xa744014a, 0x3c050800, 0x8ca50420, 0x3c020048,
-0x3c190001, 0xa2f825, 0x30d80002, 0x3f92825,
-0x13000004, 0x1821, 0x3c040100, 0xa42825,
-0x24030001, 0x30ca0004, 0x51400005, 0xaf830008,
-0x3c060010, 0xa62825, 0x24030001, 0xaf830008,
-0xaf451000, 0x0, 0x0, 0x0,
-0x0, 0x8f830008, 0x10600023, 0x0,
-0x8f4b1000, 0x561fffe, 0x0, 0x1060001e,
-0x0, 0x8f4d1000, 0x3c030020, 0x1a36024,
-0x11800019, 0x8f8f0000, 0x31ee0002, 0x11c00016,
-0x0, 0x97501014, 0x16000013, 0x0,
-0x97451008, 0x30bfffff, 0x27f80006, 0x18c882,
-0x193080, 0xc72821, 0x33110001, 0x33030003,
-0x12200320, 0x8ca20000, 0xd, 0xc7f821,
-0xafe20000, 0x3c190800, 0x8f390430, 0x27260001,
-0x3c010800, 0xac260430, 0x8f6a0000, 0x3405ffff,
-0xaf8a0004, 0x8ce20000, 0x1045029a, 0x2021,
-0x8ce50000, 0x30bf0100, 0x13e0027e, 0x1002021,
-0x3c070800, 0x8ce70474, 0x3c100800, 0x8e10044c,
-0xe85821, 0x3c180800, 0x8f180470, 0x168882b,
-0x3c080800, 0x8d080448, 0x7821, 0x2046021,
-0x30f1821, 0x184702b, 0x10f6821, 0x715021,
-0x1ae1021, 0x3c010800, 0xac2c044c, 0x3c010800,
-0xac220448, 0x3c010800, 0xac2b0474, 0x3c010800,
-0xac2a0470, 0x8f8d0018, 0x1203021, 0x31290007,
-0x25ae0008, 0x31c21fff, 0x3426021, 0xaf8d001c,
-0xaf820018, 0x259b4000, 0xaf420084, 0x11200003,
-0x8f900020, 0x24c80007, 0x3106fff8, 0x8f840028,
-0xd02821, 0xa4782b, 0x15e00002, 0xaf900024,
-0xa42823, 0x3452021, 0x34038000, 0x831021,
-0x3c061000, 0xaf850020, 0xaf820038, 0xaf450080,
-0xaf460178, 0x8f8b0014, 0x25670001, 0xa0001dd,
-0xaf870014, 0x8f620008, 0x8f670000, 0x24110030,
-0x7c602, 0x330300f0, 0x107100a2, 0x24190040,
-0x1479ff4b, 0x8f8b0014, 0x8f4a0178, 0x540fffe,
-0x30a70200, 0x14e00003, 0x51282, 0xd,
-0x51282, 0x30500003, 0x104900, 0x1307021,
-0xe6880, 0x1b06021, 0xc5880, 0x1738021,
-0x8e080000, 0x15000002, 0x0, 0xd,
-0x8f6f0004, 0x5e202b1, 0x92030006, 0x92070005,
-0x920f0004, 0x3c020001, 0x72880, 0xb06021,
-0x8d890018, 0x27710008, 0x25ee0005, 0x1226821,
-0xe3082, 0xad8d0018, 0x2202021, 0xe000580,
-0x26050014, 0x920b0006, 0x8f7f0004, 0x3c087fff,
-0xb2080, 0x913021, 0x8cc30004, 0x350affff,
-0x3eac824, 0x79c021, 0xacd80004, 0x92070005,
-0x92090004, 0x960d0008, 0x72880, 0xb1f821,
-0x8fef0000, 0x97420104, 0x3c07ffff, 0x1e75024,
-0x304effff, 0x1c96021, 0x18d5823, 0x3168ffff,
-0x1482025, 0xafe40000, 0x92030007, 0x24190001,
-0x10790269, 0x24060003, 0x10660279, 0x0,
-0x8e190010, 0x241f000a, 0xa75f0140, 0xa7590142,
-0x92030004, 0x8f860000, 0x24070001, 0xa7430144,
-0xa7400146, 0x97580104, 0x30d10002, 0x3c050041,
-0xa7580148, 0x1821, 0xa747014a, 0x12200003,
-0x30ca0004, 0x3c050141, 0x24030001, 0x51400005,
-0xaf830008, 0x3c080010, 0xa82825, 0x24030001,
-0xaf830008, 0xaf451000, 0x0, 0x0,
-0x0, 0x0, 0x8f8b0008, 0x11600004,
-0x0, 0x8f441000, 0x481fffe, 0x0,
-0x8f6a0000, 0x92070004, 0x3c050800, 0x8ca50444,
-0xaf8a0004, 0x975f0104, 0x3c0f0800, 0x8def0440,
-0x30e300ff, 0x33f9ffff, 0x79c021, 0xb86821,
-0x1021, 0x24e6000a, 0x30c8ffff, 0x1b8482b,
-0x1e27021, 0x1c96021, 0x31100007, 0x3c010800,
-0xac2d0444, 0x3c010800, 0xac2c0440, 0x12000003,
-0x8f8d0018, 0x250b0007, 0x3168fff8, 0x10d7021,
-0x31cc1fff, 0xaf8d001c, 0xaf8c0018, 0xaf4c0084,
-0x97440104, 0x34c8021, 0x3084ffff, 0x30880007,
-0x11000003, 0x261b4000, 0x24890007, 0x3124fff8,
-0x8f820020, 0x8f850028, 0x822021, 0x85782b,
-0x15e00002, 0xaf820024, 0x852023, 0x3448821,
-0x34058000, 0x2251021, 0x3c061000, 0xaf840020,
-0xaf820038, 0xaf440080, 0xaf460178, 0xa000285,
-0x8f8b0014, 0x8f5f0178, 0x7e0fffe, 0x30aa0200,
-0x15400003, 0x54282, 0xd, 0x54282,
-0x31020003, 0x27100, 0x1c26821, 0xd6080,
-0x1824821, 0x92880, 0xb38021, 0x8e0b0000,
-0x11600002, 0x0, 0xd, 0x8f6f000c,
-0x5e001f3, 0x8f870038, 0x24190001, 0xae190000,
-0x8ce30008, 0xa2000007, 0x8f780004, 0x181c02,
-0x306600ff, 0x24d10005, 0x113083, 0x2cc40041,
-0x14800002, 0xa2030004, 0xd, 0x8f6b0004,
-0x3c0effff, 0xe02821, 0x3164ffff, 0x248f000b,
-0xf4082, 0x81080, 0x474821, 0x8d2d0000,
-0x26040014, 0xa60b0008, 0x1ae6024, 0xe000580,
-0xad2c0000, 0x8f5f0108, 0x3c0a1000, 0x3ea3824,
-0x10e001a3, 0x0, 0x97460104, 0x92030007,
-0x24d1ffec, 0x34650002, 0x3224ffff, 0xa2050007,
-0x96060008, 0x2cc70013, 0x54e00005, 0x92030007,
-0x920a0007, 0x355f0001, 0xa21f0007, 0x92030007,
-0x240b0001, 0x106b01ba, 0x24090003, 0x106901cd,
-0x8f880038, 0x30cfffff, 0x25e40002, 0x4c883,
-0x333f00ff, 0x1f2880, 0xa2190005, 0xa85821,
-0x8d780000, 0x97510104, 0x3c03ffff, 0x3036024,
-0x3222ffff, 0x4f7023, 0x25cdfffe, 0x18d4825,
-0xad690000, 0x92060005, 0x3c02fff6, 0x344effff,
-0x30ca00ff, 0xa3880, 0xf02021, 0x90990014,
-0x3c1fff7f, 0x37e7ffff, 0x3323000f, 0x667821,
-0x31f800ff, 0x182880, 0xb08821, 0x8e2d0020,
-0xa86021, 0xa20f0006, 0x1ae4824, 0xae0d000c,
-0xad89000c, 0x920b0006, 0x8e04000c, 0x127f824,
-0xb5080, 0x150c821, 0x97260026, 0x148c021,
-0x874024, 0xaf260024, 0xae08000c, 0xaf3f0020,
-0xaf060010, 0x8f860000, 0x240c0010, 0x24090002,
-0xa74c0140, 0xa7400142, 0xa7400144, 0xa7490146,
-0x974b0104, 0x24070001, 0x30c80002, 0x256afffe,
-0xa74a0148, 0x3c050009, 0xa747014a, 0x11000003,
-0x1821, 0x3c050109, 0x24030001, 0x30cd0004,
-0x51a00005, 0xaf830008, 0x3c060010, 0xa62825,
+0x0, 0x0, 0x10000003, 0x0,
+0xd, 0xd, 0x3c020800, 0x24421c00,
+0x3c030800, 0x24632094, 0xac400000, 0x43202b,
+0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd2ffc,
+0x3a0f021, 0x3c100800, 0x26100490, 0x3c1c0800,
+0x279c1c00, 0xe00015c, 0x0, 0xd,
+0x3084ffff, 0x30820007, 0x8f850018, 0x10400002,
+0x24830007, 0x3064fff8, 0x853021, 0x30c41fff,
+0x3441821, 0x247b4000, 0xaf85001c, 0xaf840018,
+0x3e00008, 0xaf440084, 0x3084ffff, 0x30820007,
+0x8f850020, 0x8f860028, 0x10400002, 0x24830007,
+0x3064fff8, 0x852021, 0x86182b, 0x14600002,
+0xaf850024, 0x862023, 0x3442821, 0x34068000,
+0xaf840020, 0xaf440080, 0xa62021, 0x3e00008,
+0xaf840038, 0x27bdffd8, 0xafb3001c, 0xafb20018,
+0xafb00010, 0xafbf0024, 0xafb40020, 0xafb10014,
+0x3c086008, 0x8d145000, 0x2418ff7f, 0x3c1a8000,
+0x2989824, 0x3672380c, 0xad125000, 0x8f510008,
+0x3c07601c, 0x3c086000, 0x36300001, 0xaf500008,
+0xaf800018, 0xaf400080, 0xaf400084, 0x8ce60008,
+0x8d0f0808, 0x3c076016, 0x8cec0000, 0x31eefff0,
+0x39ca0010, 0x3c0dffff, 0x340b8000, 0x3c030080,
+0x34b4821, 0x2d440001, 0x18d2824, 0x3c025353,
+0x3c010800, 0xac230420, 0xaf890038, 0xaf860028,
+0xaf840010, 0x275b4000, 0x14a20003, 0x34e37c00,
+0x8cf90004, 0x3281821, 0x8c7f007c, 0x8c650078,
+0x3c028000, 0x3c0b0800, 0x8d6b048c, 0x3c0a0800,
+0x8d4a0488, 0x34520070, 0xaf85003c, 0xaf9f0040,
+0x3c130800, 0x26731c44, 0x240a021, 0x8e480000,
+0x8f460000, 0x38c30001, 0x30640001, 0x10800017,
+0xaf880034, 0x2804821, 0x8d2f0000, 0x3c050800,
+0x8ca5045c, 0x3c180800, 0x8f180458, 0x1e81023,
+0xa28021, 0xc821, 0x202402b, 0x3198821,
+0x2283821, 0x3c010800, 0xac30045c, 0x3c010800,
+0xac270458, 0x8f4e0000, 0x39cd0001, 0x31ac0001,
+0x1580ffed, 0x1e04021, 0xaf8f0034, 0x8e510000,
+0x3c070800, 0x8ce7045c, 0x3c0d0800, 0x8dad0458,
+0x2288023, 0xf06021, 0x7021, 0x190302b,
+0x1ae1821, 0x662021, 0x3c010800, 0xac2c045c,
+0x3c010800, 0xac240458, 0x8f460108, 0x8f470100,
+0x30c92000, 0xaf860000, 0xaf87000c, 0x1120000a,
+0xc04021, 0x3c180800, 0x8f18042c, 0x27080001,
+0x3c010800, 0xac28042c, 0x3c184000, 0xaf580138,
+0xa000196, 0x0, 0x97490104, 0x2821,
+0x1455021, 0x3122ffff, 0x1625821, 0x162f82b,
+0x15f5021, 0x30d90200, 0x3c010800, 0xac2b048c,
+0x3c010800, 0xac2a0488, 0x17200015, 0x24040f00,
+0x10e40013, 0x0, 0x24080d00, 0x10e8023b,
+0x30cd0006, 0x11a0ffe9, 0x3c184000, 0x936e0000,
+0x24090010, 0x31c400f0, 0x10890271, 0x24020070,
+0x108202e5, 0x8f880014, 0x250f0001, 0xaf8f0014,
+0x3c184000, 0xaf580138, 0xa000196, 0x0,
+0x974c0104, 0x1180ffd9, 0x3c184000, 0x30c34000,
+0x146000a1, 0x0, 0x8f460178, 0x4c0fffe,
+0x8f870038, 0x24100800, 0x240f0008, 0x8ce30008,
+0xaf500178, 0xa74f0140, 0xa7400142, 0x974e0104,
+0x8f860000, 0x31c9ffff, 0x30cd0001, 0x11a002e1,
+0x1204021, 0x2531fffe, 0x24180002, 0xa7580146,
+0x3228ffff, 0xa7510148, 0x3c190800, 0x8f39043c,
+0x172002d0, 0x8f8c000c, 0x30df0020, 0x17e00002,
+0x24040009, 0x24040001, 0x30c20c00, 0x24050400,
+0x50450001, 0x34840004, 0xa744014a, 0x3c110800,
+0x8e310420, 0x3c180048, 0x3c100001, 0x2381825,
+0x30cf0002, 0x702825, 0x11e00004, 0x1821,
+0x3c190100, 0xb92825, 0x24030001, 0x30df0004,
+0x53e00005, 0xaf830008, 0x3c060010, 0xa62825,
0x24030001, 0xaf830008, 0xaf451000, 0x0,
-0x0, 0x0, 0x0, 0x92180004,
-0x27110002, 0x322f0007, 0xf1023, 0x304e0007,
-0xae0e0010, 0x8f900008, 0x12000004, 0x0,
-0x8f431000, 0x461fffe, 0x0, 0x8f780000,
-0x8f8f0018, 0x3c100800, 0x8e100444, 0xaf980004,
-0x97510104, 0x25e60010, 0x30ca1fff, 0x3222ffff,
-0xaf8f001c, 0xaf8a0018, 0xaf4a0084, 0x2449fffe,
-0x3c0b0800, 0x8d6b0440, 0x974e0104, 0x1206821,
-0x967c3, 0x20d2821, 0x31c9ffff, 0xad402b,
-0x16c3821, 0xe82021, 0x34af821, 0x31390007,
-0x3c010800, 0xac250444, 0x3c010800, 0xac240440,
-0x13200003, 0x27fb4000, 0x25230007, 0x3069fff8,
-0x8f9f0020, 0x8f840028, 0x13f3821, 0xe4c82b,
-0x17200002, 0xaf9f0024, 0xe43823, 0x3472021,
-0x34058000, 0x851021, 0x3c061000, 0xaf870020,
-0xaf820038, 0xaf470080, 0xaf460178, 0xa000285,
-0x8f8b0014, 0x97580104, 0x1300fdc2, 0x3c104000,
-0x8f430178, 0x460fffe, 0x30b94000, 0x13200003,
-0x3c040008, 0xd, 0x3c040008, 0xaf440140,
-0x24080800, 0xaf480178, 0x8f8b0000, 0x974a0104,
-0x317f0001, 0x13e000e9, 0x3146ffff, 0x24d0fffe,
-0x240c0002, 0xa74c0146, 0xa7500148, 0x8f8f0018,
-0x2405000d, 0xa745014a, 0x8f710000, 0x25e20008,
-0x30491fff, 0x3497021, 0x30cd0007, 0xaf910004,
-0xaf8f001c, 0xaf890018, 0xc03821, 0xaf490084,
-0x11a00003, 0x25db4000, 0x24c60007, 0x30c7fff8,
-0x8f980020, 0x8f840028, 0xf83021, 0xc4382b,
-0x14e00002, 0xaf980024, 0xc43023, 0x8f8a0014,
-0x3465821, 0x34088000, 0x168f821, 0x25590001,
-0x3c031000, 0x3c104000, 0xaf860020, 0xaf9f0038,
-0xaf460080, 0xaf430178, 0xaf990014, 0xaf500138,
-0xa000190, 0x0, 0x8f690000, 0x97440104,
-0x3127ffff, 0x3088ffff, 0x8f4f0178, 0x5e0fffe,
-0x30ff0007, 0x1f1823, 0x30780007, 0x24e6fffe,
-0x2419000a, 0xa7590140, 0xa7580142, 0xa7460144,
-0xa7400146, 0xa7480148, 0x8f420108, 0x30510020,
-0x16200002, 0x24030009, 0x24030001, 0x30aa0002,
-0xa743014a, 0x3c040041, 0x11400003, 0x1821,
-0x3c040141, 0x24030001, 0x30ab0004, 0x51600005,
-0xaf830008, 0x3c050010, 0x852025, 0x24030001,
-0xaf830008, 0xaf441000, 0x0, 0x0,
-0x0, 0x0, 0x8f900008, 0x12000004,
-0x0, 0x8f4c1000, 0x581fffe, 0x0,
-0x8f780000, 0x27620008, 0x8f8d003c, 0xaf980004,
-0x94460008, 0x9451000a, 0x944f000c, 0x30ceffff,
-0x112400, 0x31e9ffff, 0x11cd00a2, 0x892025,
-0x3c030800, 0x8c630444, 0x3c180800, 0x8f180440,
-0xe85021, 0x255ffffe, 0x7f7821, 0x1021,
-0x1ff302b, 0x3028821, 0x2264821, 0x3c010800,
-0xac2f0444, 0x3c010800, 0xac290440, 0x24eb0008,
-0x3162ffff, 0x30470007, 0x10e00003, 0x8f850018,
-0x24500007, 0x3202fff8, 0x3106ffff, 0x30c80007,
-0x457021, 0x31cd1fff, 0x34d6021, 0xaf85001c,
-0xaf8d0018, 0x259b4000, 0xaf4d0084, 0x11000003,
-0x8f8f0020, 0x24c40007, 0x3086fff8, 0x8f840028,
-0xcf2821, 0xa4482b, 0x15200002, 0xaf8f0024,
-0xa42823, 0xaf850020, 0xaf450080, 0x3c110800,
-0x8e310434, 0x345c021, 0x34028000, 0x3023021,
-0x12200005, 0xaf860038, 0x93830017, 0x2419000e,
-0x1079000d, 0x241f043f, 0x3c0a1000, 0xaf4a0178,
-0x8f8b0014, 0x25670001, 0xa0001dd, 0xaf870014,
-0xe0005a6, 0x3c104000, 0x8f8b0014, 0x25670001,
-0xa0001de, 0xaf870014, 0x3c0a1000, 0xa75f0148,
-0xaf4a0178, 0xa0004b4, 0x8f8b0014, 0x240e0f00,
-0x11ee003d, 0x30d10020, 0x16200002, 0x24030009,
-0x24030001, 0xa000208, 0xa743014a, 0xa0001fb,
-0xa7400146, 0x94e50008, 0x94e2000a, 0x94eb000c,
-0x8f86003c, 0x2fc00, 0x316affff, 0x30b9ffff,
-0x13260037, 0x3ea2025, 0x3c050800, 0x8ca50444,
-0x3c1f0800, 0x8fff0440, 0x5021, 0xa83821,
-0xe8302b, 0x3eac821, 0x326c021, 0x3c010800,
-0xac270444, 0x3c010800, 0xac380440, 0xa000269,
-0x8f8d0018, 0x3c190800, 0x8f39047c, 0x3c030800,
-0x8c630454, 0x3c060800, 0x8cc60478, 0x3c0f0800,
-0x8def0450, 0x3283821, 0x686821, 0xe8c02b,
-0xc48821, 0x1a8402b, 0x1e47021, 0x2385821,
-0x1c86021, 0x3c010800, 0xac2d0454, 0x3c010800,
-0xac2c0450, 0x3c010800, 0xac27047c, 0x3c010800,
-0xac2b0478, 0xa000269, 0x8f8d0018, 0xa7400146,
-0xa00041b, 0x8f8f0018, 0x30d00020, 0x1600ffc5,
-0x2403000d, 0x24030005, 0xa000208, 0xa743014a,
-0x97590104, 0x2738fff0, 0xa00036b, 0x3304ffff,
-0x8f8c0040, 0x148cffc8, 0x8021, 0x3c110800,
-0x8e31046c, 0x3c040800, 0x8c840468, 0x2287021,
-0x1c8782b, 0x904021, 0x10f6821, 0x3c010800,
-0xac2e046c, 0x3c010800, 0xac2d0468, 0xa000269,
-0x8f8d0018, 0x8f990040, 0x1499ff5d, 0x6021,
-0x3c050800, 0x8ca5046c, 0x3c100800, 0x8e100468,
-0xe82021, 0x248efffe, 0xaef821, 0x3ee582b,
-0x20c5021, 0x14b1821, 0x3c010800, 0xac3f046c,
-0x3c010800, 0xac230468, 0xa00048b, 0x24eb0008,
-0x8f880038, 0x3c02ffff, 0x8d0e000c, 0x1c26824,
-0x1a46025, 0xad0c000c, 0xa000379, 0x30cfffff,
-0xa0003a9, 0xae000000, 0x974b0104, 0x92040004,
-0x8e2a000c, 0x1644021, 0x251ffff2, 0x1471824,
-0x33f9ffff, 0x79c025, 0xae38000c, 0xa0002d4,
-0x8e190010, 0x3c03ffff, 0x8d110010, 0x2232824,
-0xa47825, 0xad0f0010, 0xa000379, 0x30cfffff,
-0x97450104, 0x92060004, 0x8e2f0010, 0xa61021,
-0x2449ffee, 0x1e76824, 0x312effff, 0x1ae6025,
-0xae2c0010, 0xa0002d4, 0x8e190010, 0x8e06000c,
-0xae000000, 0x3c080, 0x3108821, 0xa0002a6,
-0xae260020, 0x1460000d, 0x3050ffff, 0x3c04ffff,
-0x446024, 0x1846826, 0xd582b, 0xc502b,
-0x14b1024, 0x10400002, 0x0, 0xd,
-0x8ca30000, 0xa00023e, 0x641025, 0x3a11ffff,
-0x11782b, 0x10702b, 0x1cf2024, 0x10800002,
-0x0, 0xd, 0x8cb80000, 0xa00023e,
-0x3702ffff, 0x3084ffff, 0x30a5ffff, 0x10800007,
-0x1821, 0x30820001, 0x10400002, 0x42042,
-0x651821, 0x1480fffb, 0x52840, 0x3e00008,
-0x601021, 0x10c00007, 0x0, 0x8ca20000,
-0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb,
-0x24840004, 0x3e00008, 0x0, 0x10a00008,
-0x24a3ffff, 0xac860000, 0x0, 0x0,
-0x2402ffff, 0x2463ffff, 0x1462fffa, 0x24840004,
-0x3e00008, 0x0, 0x308effff, 0x30d8ffff,
-0x57c00, 0x1f86025, 0x39cdffff, 0x1ac5021,
-0x14c582b, 0x14b4821, 0x94402, 0x3127ffff,
-0xe83021, 0x62402, 0x30c5ffff, 0xa41821,
-0x3862ffff, 0x3e00008, 0x3042ffff, 0x3c0c0800,
-0x8d8c0484, 0x240bff80, 0x27bdffd0, 0x1845021,
-0x14b4824, 0xaf490020, 0x3c080800, 0x8d080484,
-0xafb20020, 0xafb00018, 0xafbf0028, 0xafb30024,
-0xafb1001c, 0x93660004, 0x1043821, 0x30e4007f,
-0x9a1021, 0x3c030008, 0x439021, 0x30c50020,
-0x3608021, 0x3c080111, 0x277b0008, 0x14a00002,
-0x26460070, 0x2646006c, 0x92130004, 0x97510104,
-0x920f0004, 0x3267000f, 0x322effff, 0x31ed0040,
-0x1c72823, 0x11a00005, 0x4821, 0x925900bc,
-0x33380004, 0x17000090, 0x0, 0x924300bc,
-0x307f0004, 0x13e0000f, 0x0, 0x10a0000d,
-0x0, 0x960e0002, 0x240aff80, 0xa76021,
-0x25cdfffe, 0xa74d1016, 0x920b0004, 0x14b2024,
-0x308200ff, 0x10400085, 0x10c4025, 0x3c0f0400,
-0x10f4025, 0x8f530178, 0x660fffe, 0x2404000a,
-0xa7440140, 0x960d0002, 0x24040009, 0x31ac0007,
-0xc5823, 0x316a0007, 0xa74a0142, 0x96020002,
-0x2443fffe, 0xa7430144, 0xa7400146, 0x975f0104,
-0xa75f0148, 0x8f590108, 0x33380020, 0x53000001,
-0x24040001, 0x920f0004, 0x31ee0010, 0x15c00002,
-0x34830010, 0x801821, 0xa743014a, 0x0,
-0x0, 0x0, 0x0, 0xaf481000,
-0x0, 0x0, 0x0, 0x0,
-0x8f511000, 0x621fffe, 0x3113ffff, 0x12600003,
-0x0, 0x8f481018, 0xacc80000, 0x96030006,
-0x307fffff, 0x27f90002, 0x199882, 0x138880,
-0x23b3021, 0x8cd80000, 0x15200057, 0x183402,
-0x92030004, 0x2405ff80, 0xa3f824, 0x33f100ff,
-0x1220002c, 0x0, 0x924700bc, 0x30f20002,
-0x12400028, 0x0, 0x974b100c, 0x2562fffe,
-0xa7421016, 0x0, 0x3c0a0400, 0x35490030,
-0xaf491000, 0x0, 0x0, 0x0,
-0x0, 0x8f4c1000, 0x581fffe, 0x0,
-0x9749100c, 0x8f51101c, 0xc02021, 0x3127ffff,
-0x24f20030, 0x121882, 0x32880, 0xbbf821,
-0x3226ffff, 0xaff10000, 0xe000595, 0x112c02,
-0x13c880, 0x33b9821, 0x8e780000, 0x27400,
-0xafb80010, 0x8fa80010, 0x310fffff, 0xafaf0010,
-0x8fa40010, 0x1c46825, 0xafad0010, 0x8fa60010,
-0xae660000, 0x97730008, 0x976d000a, 0x9766000c,
-0x8f8a003c, 0xd5c00, 0x30ccffff, 0x3262ffff,
-0x104a0036, 0x16c2025, 0x96060002, 0x3c101000,
-0x24d30008, 0xe000139, 0x3264ffff, 0x974c0104,
-0xe000147, 0x3184ffff, 0xaf500178, 0x8fbf0028,
-0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0030, 0x10a0ff70, 0x0,
-0x24a5fffc, 0xa0005ce, 0x24090004, 0x8cd10000,
-0xaf511018, 0x8f530178, 0x660ff7a, 0x2404000a,
-0xa0005e3, 0x0, 0xa7c821, 0x8f880038,
-0x8f4e101c, 0x19c082, 0x187880, 0x1e82021,
-0xac8e0000, 0xe2c02, 0xc02021, 0xe000595,
-0x31c6ffff, 0x23b2821, 0x8cad0000, 0x25400,
-0x403021, 0xafad0010, 0x8fac0010, 0x318bffff,
-0xafab0010, 0x8fa20010, 0x1424825, 0xafa90010,
-0x8fa70010, 0xa000613, 0xaca70000, 0x8f8f0040,
-0x148fffc9, 0x0, 0x97420104, 0x960b0002,
-0x3c050800, 0x8ca5046c, 0x3049ffff, 0x316affff,
-0x3c110800, 0x8e310468, 0x12a3821, 0x24f2fffe,
-0xb24021, 0x12ffc3, 0x112c82b, 0x23fc021,
-0x3192021, 0x3c010800, 0xac28046c, 0x3c010800,
-0xac240468, 0xa00064d, 0x0, 0xa4102b,
-0x10400009, 0x24030001, 0x52840, 0xa4102b,
-0x4a00003, 0x31840, 0x5440fffc, 0x52840,
-0x10600007, 0x0, 0x85302b, 0x14c00002,
-0x31842, 0x852023, 0x1460fffb, 0x52842,
-0x3e00008, 0x801021, 0x8f85002c, 0x27bdffe8,
-0x53027, 0x2cc30001, 0x2ca40002, 0x831025,
-0x10400003, 0xafbf0010, 0x2405007f, 0xaf85002c,
-0x52827, 0x30a5ffff, 0xe000574, 0x240426f5,
-0x8f830030, 0x240402bd, 0x403021, 0x83382b,
-0x10e00009, 0x24050001, 0x42040, 0x83102b,
-0x4800003, 0x52840, 0x5440fffc, 0x42040,
-0x10a00008, 0xc35021, 0x64402b, 0x15000002,
-0x52842, 0x641823, 0x14a0fffb, 0x42042,
-0xc35021, 0x8fbf0010, 0xa4c02, 0x312200ff,
-0x27bd0018, 0xaf8a002c, 0x3e00008, 0xaf890030,
-0x0 };
-u32 bce_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 };
-u32 bce_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 };
-u32 bce_TPAT_b06FwBss[(0x450/4) + 1] = { 0x0 };
-u32 bce_TPAT_b06FwSbss[(0x44/4) + 1] = { 0x0 };
-u32 bce_TPAT_b06FwSdata[(0x0/4) + 1] = { 0x0 };
+0x0, 0x0, 0x0, 0x8f830008,
+0x10600023, 0x0, 0x8f451000, 0x4a1fffe,
+0x0, 0x1060001e, 0x0, 0x8f441000,
+0x3c0c0020, 0x8c1024, 0x10400019, 0x8f8e0000,
+0x31cd0002, 0x11a00016, 0x0, 0x974f1014,
+0x15e00013, 0x0, 0x97591008, 0x3338ffff,
+0x27110006, 0x111882, 0x33080, 0xc72821,
+0x32300001, 0x32230003, 0x1200032c, 0x8ca20000,
+0xd, 0xc7f821, 0xafe20000, 0x3c050800,
+0x8ca50430, 0x24a60001, 0x3c010800, 0xac260430,
+0x8f6d0000, 0x3402ffff, 0xaf8d0004, 0x8cec0000,
+0x118202a6, 0x2021, 0x8ced0000, 0x31ac0100,
+0x1180028a, 0x0, 0x3c020800, 0x8c420474,
+0x3c030800, 0x8c63044c, 0x3c1f0800, 0x8fff0470,
+0x3c180800, 0x8f180448, 0x483821, 0x688021,
+0xe8282b, 0x3e43021, 0x208402b, 0x3048821,
+0xc57021, 0x2287821, 0x3c010800, 0xac30044c,
+0x3c010800, 0xac2f0448, 0x3c010800, 0xac270474,
+0x3c010800, 0xac2e0470, 0x8f840018, 0x1203021,
+0x31290007, 0x249f0008, 0x33f91fff, 0x3594021,
+0xaf84001c, 0xaf990018, 0x251b4000, 0xaf590084,
+0x11200003, 0x8f830020, 0x24c20007, 0x3046fff8,
+0x8f840028, 0xc32821, 0xa4302b, 0x14c00002,
+0xaf830024, 0xa42823, 0x3456021, 0x340d8000,
+0x18d1021, 0x3c0f1000, 0xaf850020, 0xaf820038,
+0xaf450080, 0xaf4f0178, 0x8f880014, 0x250f0001,
+0xa0001ef, 0xaf8f0014, 0x8f620008, 0x8f670000,
+0x24050030, 0x77602, 0x31c300f0, 0x106500a7,
+0x240f0040, 0x546fff4c, 0x8f880014, 0x8f4b0178,
+0x560fffe, 0x0, 0x30ca0200, 0x15400003,
+0x61282, 0xd, 0x61282, 0x304d0003,
+0xd4900, 0x12d1821, 0x38080, 0x20d4021,
+0x86080, 0x1938021, 0x8e1f0000, 0x17e00002,
+0x0, 0xd, 0x8f6e0004, 0x5c202bd,
+0x92070006, 0x920e0005, 0x92020004, 0x3c090001,
+0xe1880, 0x70f821, 0x8fed0018, 0x27710008,
+0x24480005, 0x1a96021, 0x83082, 0xafec0018,
+0x2202021, 0xe00059e, 0x26050014, 0x920a0006,
+0x8f790004, 0x3c0b7fff, 0xa2080, 0x917821,
+0x8df80004, 0x3566ffff, 0x3262824, 0x3053821,
+0xade70004, 0x920e0005, 0x920d0004, 0x960c0008,
+0xe1080, 0x51c821, 0x8f230000, 0x97490104,
+0x3c07ffff, 0x675824, 0x3128ffff, 0x10df821,
+0x3ec5023, 0x3144ffff, 0x1643025, 0xaf260000,
+0x92030007, 0x24180001, 0x10780275, 0x240f0003,
+0x106f0285, 0x0, 0x8e050010, 0x2419000a,
+0xa7590140, 0xa7450142, 0x92180004, 0x8f860000,
+0x240f0001, 0xa7580144, 0xa7400146, 0x97470104,
+0x30d10002, 0x3c050041, 0xa7470148, 0x1821,
+0xa74f014a, 0x12200003, 0x30cb0004, 0x3c050141,
+0x24030001, 0x51600005, 0xaf830008, 0x3c060010,
+0xa62825, 0x24030001, 0xaf830008, 0xaf451000,
+0x0, 0x0, 0x0, 0x0,
+0x8f8a0008, 0x11400004, 0x0, 0x8f441000,
+0x481fffe, 0x0, 0x8f6b0000, 0x92080004,
+0x3c110800, 0x8e310444, 0xaf8b0004, 0x97590104,
+0x311800ff, 0x3c0e0800, 0x8dce0440, 0x3325ffff,
+0x3053821, 0x2276021, 0x1021, 0x250f000a,
+0x31e8ffff, 0x187482b, 0x1c26821, 0x1a9f821,
+0x31100007, 0x3c010800, 0xac2c0444, 0x3c010800,
+0xac3f0440, 0x12000003, 0x8f8c0018, 0x25060007,
+0x30c8fff8, 0x10c6821, 0x31bf1fff, 0xaf8c001c,
+0xaf9f0018, 0xaf5f0084, 0x97440104, 0x35f8021,
+0x3084ffff, 0x308a0007, 0x11400003, 0x261b4000,
+0x24890007, 0x3124fff8, 0x8f820020, 0x8f850028,
+0x822021, 0x85702b, 0x15c00002, 0xaf820024,
+0x852023, 0x3c0b0800, 0x8d6b048c, 0x3c0a0800,
+0x8d4a0488, 0x3448821, 0x34038000, 0x2231021,
+0x3c0f1000, 0xaf840020, 0xaf820038, 0xaf440080,
+0xaf4f0178, 0xa000296, 0x8f880014, 0x8f500178,
+0x600fffe, 0x30d10200, 0x16200003, 0x61282,
+0xd, 0x61282, 0x305f0003, 0x1f1900,
+0x7f3021, 0x62080, 0x9fc821, 0x194880,
+0x1338021, 0x8e180000, 0x13000002, 0x0,
+0xd, 0x8f6c000c, 0x58001fb, 0x8f870038,
+0x240e0001, 0xae0e0000, 0x8ce30008, 0xa2000007,
+0x8f650004, 0x55402, 0x314d00ff, 0x25a80005,
+0x83082, 0x2ccb0041, 0x15600002, 0xa20a0004,
+0xd, 0x8f780004, 0x3c03ffff, 0xe02821,
+0x330bffff, 0x256c000b, 0xc1082, 0x22080,
+0x874821, 0x8d3f0000, 0x26040014, 0xa6180008,
+0x3e3c824, 0xe00059e, 0xad390000, 0x8f4f0108,
+0x3c111000, 0x1f13824, 0x10e001ab, 0x0,
+0x974d0104, 0x92080007, 0x25aaffec, 0x35060002,
+0x3144ffff, 0xa2060007, 0x96060008, 0x2cc70013,
+0x54e00005, 0x92030007, 0x92110007, 0x362f0001,
+0xa20f0007, 0x92030007, 0x24180001, 0x107801c2,
+0x24090003, 0x106901d5, 0x8f880038, 0x30cbffff,
+0x25710002, 0x117883, 0x31e400ff, 0x42880,
+0xa20f0005, 0xa84821, 0x8d2d0000, 0x974a0104,
+0x3c0effff, 0x1aef824, 0x3143ffff, 0x6b1023,
+0x244cfffe, 0x3ecc825, 0xad390000, 0x92060005,
+0x3c03fff6, 0x3462ffff, 0x30d800ff, 0x183880,
+0xf08821, 0x922f0014, 0x3c04ff7f, 0x3487ffff,
+0x31ee000f, 0x1c65821, 0x316500ff, 0x55080,
+0x1506821, 0x8dac0020, 0x148f821, 0xa20b0006,
+0x182c824, 0xae0c000c, 0xaff9000c, 0x92090006,
+0x8e11000c, 0x3277824, 0x9c080, 0x3107021,
+0x95c60026, 0x3082821, 0x2272024, 0xae04000c,
+0xadcf0020, 0xadc60024, 0xaca60010, 0x8f880000,
+0x3c0b0800, 0x8d6b048c, 0x3c0a0800, 0x8d4a0488,
+0x241f0010, 0x24190002, 0xa75f0140, 0xa7400142,
+0xa7400144, 0xa7590146, 0x97490104, 0x24070001,
+0x31060002, 0x2538fffe, 0xa7580148, 0x3c050009,
+0xa747014a, 0x10c00003, 0x1821, 0x3c050109,
+0x24030001, 0x310c0004, 0x51800005, 0xaf830008,
+0x3c080010, 0xa82825, 0x24030001, 0xaf830008,
+0xaf451000, 0x0, 0x0, 0x0,
+0x0, 0x92050004, 0x24ae0002, 0x31cd0007,
+0xd1823, 0x30620007, 0xae020010, 0x8f900008,
+0x12000004, 0x0, 0x8f4f1000, 0x5e1fffe,
+0x0, 0x8f710000, 0x8f8e0018, 0x3c030800,
+0x8c630444, 0xaf910004, 0x97450104, 0x25cf0010,
+0x31e61fff, 0x30a2ffff, 0xaf8e001c, 0xaf860018,
+0xaf460084, 0x2449fffe, 0x3c0c0800, 0x8d8c0440,
+0x974d0104, 0x1208021, 0x947c3, 0x70c021,
+0x31a9ffff, 0x310f82b, 0x188c821, 0x33f2021,
+0x3463821, 0x31310007, 0x3c010800, 0xac380444,
+0x3c010800, 0xac240440, 0x12200003, 0x24fb4000,
+0x25270007, 0x30e9fff8, 0x8f860020, 0x8f840028,
+0x1263821, 0xe4c02b, 0x17000002, 0xaf860024,
+0xe43823, 0x3472021, 0x34198000, 0x991021,
+0x3c0f1000, 0xaf870020, 0xaf820038, 0xaf470080,
+0xaf4f0178, 0xa000296, 0x8f880014, 0x97470104,
+0x10e0fdae, 0x3c184000, 0x8f580178, 0x700fffe,
+0x30c54000, 0x10a00003, 0x3c1f0008, 0xd,
+0x3c1f0008, 0xaf5f0140, 0x24100800, 0x8f860000,
+0xaf500178, 0x97440104, 0x30d90001, 0x132000ed,
+0x3086ffff, 0x24ccfffe, 0x240d0002, 0xa74d0146,
+0xa74c0148, 0x8f910018, 0x2408000d, 0xa748014a,
+0x8f630000, 0x262f0008, 0x31e21fff, 0x3427021,
+0x30c90007, 0xaf830004, 0xaf91001c, 0xaf820018,
+0xc03821, 0xaf420084, 0x11200003, 0x25db4000,
+0x24d80007, 0x3307fff8, 0x8f850020, 0x8f840028,
+0xe53021, 0xc4382b, 0x14e00002, 0xaf850024,
+0xc43023, 0x8f840014, 0x346f821, 0x340c8000,
+0xaf860020, 0x3ec8021, 0xaf460080, 0x24990001,
+0x3c061000, 0x3c184000, 0xaf460178, 0xaf900038,
+0xaf990014, 0xaf580138, 0xa000196, 0x0,
+0x8f630000, 0x97510104, 0x3067ffff, 0x3228ffff,
+0x8f4f0178, 0x5e0fffe, 0x30ec0007, 0xcf823,
+0x33f00007, 0x24f9fffe, 0x2404000a, 0xa7440140,
+0xa7500142, 0xa7590144, 0xa7400146, 0xa7480148,
+0x8f450108, 0x30b80020, 0x17000002, 0x24030009,
+0x24030001, 0x30cd0002, 0xa743014a, 0x3c040041,
+0x11a00003, 0x1821, 0x3c040141, 0x24030001,
+0x30c90004, 0x51200005, 0xaf830008, 0x3c060010,
+0x862025, 0x24030001, 0xaf830008, 0xaf441000,
+0x0, 0x0, 0x0, 0x0,
+0x8f8e0008, 0x11c00004, 0x0, 0x8f421000,
+0x441fffe, 0x0, 0x8f7f0000, 0x27640008,
+0x8f91003c, 0xaf9f0004, 0x94850008, 0x9490000a,
+0x9499000c, 0x30afffff, 0x10c400, 0x3323ffff,
+0x11f100a6, 0x3032025, 0x3c0e0800, 0x8dce0444,
+0x3c0c0800, 0x8d8c0440, 0xe88821, 0x2626fffe,
+0x1c62821, 0x6821, 0xa6f82b, 0x18d2021,
+0x9f8021, 0x3c010800, 0xac250444, 0x3c010800,
+0xac300440, 0x24e20008, 0x3042ffff, 0x30470007,
+0x10e00003, 0x8f830018, 0x244f0007, 0x31e2fff8,
+0x3106ffff, 0x30c80007, 0x438021, 0x32191fff,
+0x359c021, 0xaf83001c, 0xaf990018, 0x271b4000,
+0xaf590084, 0x11000003, 0x8f8c0020, 0x24c50007,
+0x30a6fff8, 0x8f840028, 0xcc2821, 0xa4f82b,
+0x17e00002, 0xaf8c0024, 0xa42823, 0xaf850020,
+0xaf450080, 0x3c040800, 0x8c840434, 0x3454821,
+0x340e8000, 0x12e6821, 0x10800005, 0xaf8d0038,
+0x93910017, 0x2406000e, 0x12260011, 0x2407043f,
+0x3c021000, 0xaf420178, 0x8f880014, 0x250f0001,
+0xa0001ef, 0xaf8f0014, 0xe0005c4, 0xe02021,
+0x8f880014, 0x3c0b0800, 0x8d6b048c, 0x3c0a0800,
+0x8d4a0488, 0x250f0001, 0xa0001ef, 0xaf8f0014,
+0x3c021000, 0xa7470148, 0xaf420178, 0xa0004ce,
+0x8f880014, 0x24040f00, 0x1184003d, 0x30ce0020,
+0x15c00002, 0x24030009, 0x24030001, 0xa00021a,
+0xa743014a, 0xa00020d, 0xa7400146, 0x94ef0008,
+0x94f1000a, 0x94f0000c, 0x8f8c003c, 0x117400,
+0x3207ffff, 0x31edffff, 0x11ac0037, 0x1c72025,
+0x3c180800, 0x8f180444, 0x3c0f0800, 0x8def0440,
+0x8021, 0x3086821, 0x1a8382b, 0x1f07021,
+0x1c76021, 0x3c010800, 0xac2d0444, 0x3c010800,
+0xac2c0440, 0xa00027a, 0x8f840018, 0x3c020800,
+0x8c42047c, 0x3c030800, 0x8c630454, 0x3c1f0800,
+0x8fff0478, 0x3c180800, 0x8f180450, 0x483821,
+0x688021, 0xe8282b, 0x3e43021, 0x208402b,
+0x3048821, 0xc57021, 0x2287821, 0x3c010800,
+0xac300454, 0x3c010800, 0xac2f0450, 0x3c010800,
+0xac27047c, 0x3c010800, 0xac2e0478, 0xa00027a,
+0x8f840018, 0xa7400146, 0xa000435, 0x8f910018,
+0x30cd0020, 0x15a0ffc5, 0x2403000d, 0x24030005,
+0xa00021a, 0xa743014a, 0x974e0104, 0x25c5fff0,
+0xa000381, 0x30a4ffff, 0x8f980040, 0x1498ffc8,
+0x1021, 0x3c050800, 0x8ca5046c, 0x3c1f0800,
+0x8fff0468, 0xa8c821, 0x328302b, 0x3e22021,
+0x864021, 0x3c010800, 0xac39046c, 0x3c010800,
+0xac280468, 0xa00027a, 0x8f840018, 0x8f8c0040,
+0x148cff59, 0xe8c821, 0x3c180800, 0x8f18046c,
+0x3c110800, 0x8e310468, 0x2723fffe, 0x3034821,
+0x1021, 0x123302b, 0x2227021, 0x1c66821,
+0x3c010800, 0xac29046c, 0x3c010800, 0xac2d0468,
+0xa0004a5, 0x24e20008, 0x8f880038, 0x3c03ffff,
+0x8d02000c, 0x43f824, 0x3e4c825, 0xad19000c,
+0xa00038f, 0x30cbffff, 0xa0003c3, 0xae000000,
+0x974a0104, 0x92040004, 0x8e26000c, 0x1445821,
+0x2579fff2, 0xc7c024, 0x3325ffff, 0x3053825,
+0xae27000c, 0xa0002e6, 0x8e050010, 0x3c0dffff,
+0x8d0a0010, 0x14d5824, 0x1646025, 0xad0c0010,
+0xa00038f, 0x30cbffff, 0x97430104, 0x920e0004,
+0x8e290010, 0x6e1021, 0x244dffee, 0x1276024,
+0x31a8ffff, 0x188f825, 0xae3f0010, 0xa0002e6,
+0x8e050010, 0x8e0f000c, 0xae000000, 0x78880,
+0x2302821, 0xa0002b8, 0xacaf0020, 0x1460000d,
+0x3058ffff, 0x3c04ffff, 0x446824, 0x1a47026,
+0xe602b, 0xd102b, 0x4cf824, 0x13e00002,
+0x0, 0xd, 0x8caf0000, 0xa000250,
+0x1e41025, 0x3b03ffff, 0x3882b, 0x18802b,
+0x2112024, 0x10800002, 0x0, 0xd,
+0x8cb90000, 0xa000250, 0x3722ffff, 0x3084ffff,
+0x30a5ffff, 0x10800007, 0x1821, 0x30820001,
+0x10400002, 0x42042, 0x651821, 0x1480fffb,
+0x52840, 0x3e00008, 0x601021, 0x10c00007,
+0x0, 0x8ca20000, 0x24c6ffff, 0x24a50004,
+0xac820000, 0x14c0fffb, 0x24840004, 0x3e00008,
+0x0, 0x10a00008, 0x24a3ffff, 0xac860000,
+0x0, 0x0, 0x2402ffff, 0x2463ffff,
+0x1462fffa, 0x24840004, 0x3e00008, 0x0,
+0x308effff, 0x30d8ffff, 0x57c00, 0x1f86025,
+0x39cdffff, 0x1ac5021, 0x14c582b, 0x14b4821,
+0x94402, 0x3127ffff, 0xe83021, 0x62402,
+0x30c5ffff, 0xa41821, 0x3862ffff, 0x3e00008,
+0x3042ffff, 0x3c0c0800, 0x8d8c0484, 0x240bff80,
+0x27bdffd0, 0x1845021, 0x14b4824, 0xaf490020,
+0x3c080800, 0x8d080484, 0xafb20020, 0xafb00018,
+0xafbf0028, 0xafb30024, 0xafb1001c, 0x93660004,
+0x1043821, 0x30e4007f, 0x9a1021, 0x3c030008,
+0x439021, 0x30c50020, 0x3608021, 0x3c080111,
+0x277b0008, 0x14a00002, 0x26460070, 0x2646006c,
+0x92130004, 0x97510104, 0x920f0004, 0x3267000f,
+0x322effff, 0x31ed0040, 0x1c72823, 0x11a00005,
+0x4821, 0x925900bc, 0x33380004, 0x17000090,
+0x0, 0x924300bc, 0x307f0004, 0x13e0000f,
+0x0, 0x10a0000d, 0x0, 0x960e0002,
+0x240aff80, 0xa76021, 0x25cdfffe, 0xa74d1016,
+0x920b0004, 0x14b2024, 0x308200ff, 0x10400085,
+0x10c4025, 0x3c0f0400, 0x10f4025, 0x8f530178,
+0x660fffe, 0x2404000a, 0xa7440140, 0x960d0002,
+0x24040009, 0x31ac0007, 0xc5823, 0x316a0007,
+0xa74a0142, 0x96020002, 0x2443fffe, 0xa7430144,
+0xa7400146, 0x975f0104, 0xa75f0148, 0x8f590108,
+0x33380020, 0x53000001, 0x24040001, 0x920f0004,
+0x31ee0010, 0x15c00002, 0x34830010, 0x801821,
+0xa743014a, 0x0, 0x0, 0x0,
+0x0, 0xaf481000, 0x0, 0x0,
+0x0, 0x0, 0x8f511000, 0x621fffe,
+0x3113ffff, 0x12600003, 0x0, 0x8f481018,
+0xacc80000, 0x96030006, 0x307fffff, 0x27f90002,
+0x199882, 0x138880, 0x23b3021, 0x8cd80000,
+0x15200057, 0x183402, 0x92030004, 0x2405ff80,
+0xa3f824, 0x33f100ff, 0x1220002c, 0x0,
+0x924700bc, 0x30f20002, 0x12400028, 0x0,
+0x974b100c, 0x2562fffe, 0xa7421016, 0x0,
+0x3c0a0400, 0x35490030, 0xaf491000, 0x0,
+0x0, 0x0, 0x0, 0x8f4c1000,
+0x581fffe, 0x0, 0x9749100c, 0x8f51101c,
+0xc02021, 0x3127ffff, 0x24f20030, 0x121882,
+0x32880, 0xbbf821, 0x3226ffff, 0xaff10000,
+0xe0005b3, 0x112c02, 0x13c880, 0x33b9821,
+0x8e780000, 0x27400, 0xafb80010, 0x8fa80010,
+0x310fffff, 0xafaf0010, 0x8fa40010, 0x1c46825,
+0xafad0010, 0x8fa60010, 0xae660000, 0x97730008,
+0x976d000a, 0x9766000c, 0x8f8a003c, 0xd5c00,
+0x30ccffff, 0x3262ffff, 0x104a0036, 0x16c2025,
+0x96060002, 0x3c101000, 0x24d30008, 0xe00013b,
+0x3264ffff, 0x974c0104, 0xe000149, 0x3184ffff,
+0xaf500178, 0x8fbf0028, 0x8fb30024, 0x8fb20020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030,
+0x10a0ff70, 0x0, 0x24a5fffc, 0xa0005ec,
+0x24090004, 0x8cd10000, 0xaf511018, 0x8f530178,
+0x660ff7a, 0x2404000a, 0xa000601, 0x0,
+0xa7c821, 0x8f880038, 0x8f4e101c, 0x19c082,
+0x187880, 0x1e82021, 0xac8e0000, 0xe2c02,
+0xc02021, 0xe0005b3, 0x31c6ffff, 0x23b2821,
+0x8cad0000, 0x25400, 0x403021, 0xafad0010,
+0x8fac0010, 0x318bffff, 0xafab0010, 0x8fa20010,
+0x1424825, 0xafa90010, 0x8fa70010, 0xa000631,
+0xaca70000, 0x8f8f0040, 0x148fffc9, 0x0,
+0x97420104, 0x960b0002, 0x3c050800, 0x8ca5046c,
+0x3049ffff, 0x316affff, 0x3c110800, 0x8e310468,
+0x12a3821, 0x24f2fffe, 0xb24021, 0x12ffc3,
+0x112c82b, 0x23fc021, 0x3192021, 0x3c010800,
+0xac28046c, 0x3c010800, 0xac240468, 0xa00066b,
+0x0, 0xa4102b, 0x10400009, 0x24030001,
+0x52840, 0xa4102b, 0x4a00003, 0x31840,
+0x5440fffc, 0x52840, 0x10600007, 0x0,
+0x85302b, 0x14c00002, 0x31842, 0x852023,
+0x1460fffb, 0x52842, 0x3e00008, 0x801021,
+0x8f85002c, 0x27bdffe8, 0x53027, 0x2cc30001,
+0x2ca40002, 0x831025, 0x10400003, 0xafbf0010,
+0x2405007f, 0xaf85002c, 0x52827, 0x30a5ffff,
+0xe000592, 0x240426f5, 0x8f830030, 0x240402bd,
+0x403021, 0x83382b, 0x10e00009, 0x24050001,
+0x42040, 0x83102b, 0x4800003, 0x52840,
+0x5440fffc, 0x42040, 0x10a00008, 0xc35021,
+0x64402b, 0x15000002, 0x52842, 0x641823,
+0x14a0fffb, 0x42042, 0xc35021, 0x8fbf0010,
+0xa4c02, 0x312200ff, 0x27bd0018, 0xaf8a002c,
+0x3e00008, 0xaf890030, 0x0 };
+u32 bce_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 };
+u32 bce_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 };
+u32 bce_TPAT_b06FwBss[(0x450/4) + 1] = { 0x0 };
+u32 bce_TPAT_b06FwSbss[(0x44/4) + 1] = { 0x0 };
+u32 bce_TPAT_b06FwSdata[(0x0/4) + 1] = { 0x0 };
-int bce_TXP_b06FwReleaseMajor = 0x1;
-int bce_TXP_b06FwReleaseMinor = 0x0;
-int bce_TXP_b06FwReleaseFix = 0x0;
-u32 bce_TXP_b06FwStartAddr = 0x08000098;
-u32 bce_TXP_b06FwTextAddr = 0x08000000;
-int bce_TXP_b06FwTextLen = 0x3a74;
-u32 bce_TXP_b06FwDataAddr = 0x00000000;
-int bce_TXP_b06FwDataLen = 0x0;
-u32 bce_TXP_b06FwRodataAddr = 0x00000000;
-int bce_TXP_b06FwRodataLen = 0x0;
-u32 bce_TXP_b06FwBssAddr = 0x08003b08;
-int bce_TXP_b06FwBssLen = 0x14c;
-u32 bce_TXP_b06FwSbssAddr = 0x08003aa0;
-int bce_TXP_b06FwSbssLen = 0x68;
-u32 bce_TXP_b06FwSDataAddr = 0x00000000;
-int bce_TXP_b06FwSDataLen = 0x0;
-u32 bce_TXP_b06FwText[(0x3a74/4) + 1] = {
-0xa000026, 0x0, 0x0,
-0xd, 0x74787034, 0x2e362e31, 0x37000000,
-0x4061100, 0xa, 0x136, 0xea60,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x1d, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
+int bce_TXP_b06FwReleaseMajor = 0x6;
+int bce_TXP_b06FwReleaseMinor = 0x0;
+int bce_TXP_b06FwReleaseFix = 0xf;
+u32 bce_TXP_b06FwStartAddr = 0x080000a8;
+u32 bce_TXP_b06FwTextAddr = 0x08000000;
+int bce_TXP_b06FwTextLen = 0x3bfc;
+u32 bce_TXP_b06FwDataAddr = 0x00000000;
+int bce_TXP_b06FwDataLen = 0x0;
+u32 bce_TXP_b06FwRodataAddr = 0x00000000;
+int bce_TXP_b06FwRodataLen = 0x0;
+u32 bce_TXP_b06FwBssAddr = 0x08003c88;
+int bce_TXP_b06FwBssLen = 0x14c;
+u32 bce_TXP_b06FwSbssAddr = 0x08003c20;
+int bce_TXP_b06FwSbssLen = 0x68;
+u32 bce_TXP_b06FwSDataAddr = 0x00000000;
+int bce_TXP_b06FwSDataLen = 0x0;
+u32 bce_TXP_b06FwText[(0x3bfc/4) + 1] = {
+0xa00002a, 0x0, 0x0,
+0xd, 0x74787036, 0x2e302e31, 0x35000000,
+0x6000f00, 0x0, 0x136, 0xea60,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x16, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x1388,
+0x0, 0x5dc, 0x0, 0x0,
0x10000003, 0x0, 0xd, 0xd,
-0x3c020800, 0x24423aa0, 0x3c030800, 0x24633c54,
+0x3c020800, 0x24423c20, 0x3c030800, 0x24633dd4,
0xac400000, 0x43202b, 0x1480fffd, 0x24420004,
0x3c1d0800, 0x37bd7ffc, 0x3a0f021, 0x3c100800,
-0x26100098, 0x3c1c0800, 0x279c3aa0, 0xe000305,
+0x261000a8, 0x3c1c0800, 0x279c3c20, 0xe0002ba,
0x0, 0xd, 0x8f830038, 0x3c088000,
0x35070070, 0x8ce50000, 0x833025, 0x3c029000,
0xc22025, 0xaf850030, 0xaf440020, 0x8f490020,
@@ -3589,7 +3572,7 @@ u32 bce_TXP_b06FwText[(0x3a74/4) + 1] = {
0x8dce0078, 0xa62023, 0x3245821, 0x7821,
0x164682b, 0x1cf6021, 0x18d5021, 0x3c010800,
0xac2b007c, 0x3c010800, 0xac2a0078, 0x3e00008,
-0x0, 0xa00003d, 0x24040001, 0x8f840038,
+0x0, 0xa000041, 0x24040001, 0x8f840038,
0x3c058000, 0x34a20001, 0x821825, 0x3e00008,
0xaf430020, 0x3e00008, 0x1021, 0x3084ffff,
0x30a5ffff, 0x10800007, 0x1821, 0x30820001,
@@ -3605,7 +3588,7 @@ u32 bce_TXP_b06FwText[(0x3a74/4) + 1] = {
0xa3460152, 0xa748015a, 0xaf470160, 0x8fa40018,
0x8fa30014, 0xa7440158, 0xaf430154, 0x3e00008,
0xaf420178, 0x3e00008, 0x0, 0x3c038000,
-0x34620070, 0x8c490000, 0x8f88003c, 0x24840007,
+0x34620070, 0x8c490000, 0x8f880000, 0x24840007,
0x27bdfff8, 0x3084fff8, 0xaf890030, 0x974d008a,
0x31acffff, 0xafac0000, 0x8fab0000, 0x1685023,
0x2547ffff, 0x30e61fff, 0xc4282b, 0x14a0fff7,
@@ -3615,469 +3598,481 @@ u32 bce_TXP_b06FwText[(0x3a74/4) + 1] = {
0x1c3c82b, 0xc4c021, 0x1fa4021, 0x3194821,
0x25024000, 0x27bd0008, 0x3c010800, 0xac2e0084,
0x3c010800, 0xac290080, 0x3e00008, 0x0,
-0x8f82003c, 0x24860007, 0x30c5fff8, 0xa21821,
-0x30641fff, 0x3e00008, 0xaf84003c, 0x3c0e20ff,
-0x27bdffe0, 0x3c1a8000, 0x3c0f8008, 0x35cdfffd,
-0xafbf0018, 0xafb10014, 0xafb00010, 0xaf8f0044,
-0xaf4d0e00, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x3c0c00ff, 0x358bfffd,
-0xaf4b0e00, 0x3c066004, 0x8cc95000, 0x240aff7f,
-0x3c116000, 0x12a4024, 0x3507380c, 0xacc75000,
-0x8e240438, 0x24050009, 0xaf450008, 0x3083ffff,
-0x38622f71, 0x2450c0b3, 0xaf80004c, 0xe000064,
-0xaf80003c, 0x52000001, 0xae20442c, 0xe000460,
-0x0, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0xa000e77, 0x27bd0020, 0x27bdffd0, 0xafb20028,
-0xafb10024, 0xafbf002c, 0xafb00020, 0x93620008,
-0x809021, 0xa08821, 0x1440002d, 0x24040010,
-0xe00009a, 0x0, 0x8f8e004c, 0x3c103200,
-0x31c600ff, 0x67c00, 0x1f06025, 0x25cd0001,
-0xaf8d004c, 0xac4c0000, 0x936b0009, 0x9369000a,
-0x316a00ff, 0xa3c00, 0x312800ff, 0xe82025,
-0xac440004, 0x8f83004c, 0x6400043, 0xac430008,
-0xac40000c, 0x97980040, 0x33050008, 0x14a00002,
-0x26280006, 0x26280002, 0x97420e14, 0x8f450e1c,
-0x8f670004, 0x937f0002, 0x3044ffff, 0x33f900ff,
-0xafb90010, 0x8f710014, 0xafa80018, 0xe000087,
-0xafb10014, 0x8fbf002c, 0x8fb20028, 0x8fb10024,
-0x8fb00020, 0x24040010, 0xa0000c3, 0x27bd0030,
-0x93690009, 0x9368000b, 0x312300ff, 0x310200ff,
-0x628021, 0x261f000a, 0x33f0ffff, 0xe00009a,
-0x2002021, 0x8f86004c, 0x3c0d4100, 0x24d90001,
-0xaf99004c, 0x93780009, 0x30c600ff, 0x67400,
-0x330500ff, 0x24af0002, 0x1cf6025, 0x18d5825,
-0xac4b0000, 0x8f6a000c, 0x97440e14, 0x1523825,
-0xac470004, 0x8f450e1c, 0x8f670004, 0x93690002,
-0x3084ffff, 0x312800ff, 0xafa80010, 0x8f630014,
-0xafb10018, 0xe000087, 0xafa30014, 0x2002021,
-0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-0xa0000c3, 0x27bd0030, 0x3c128000, 0xa000114,
-0xac52000c, 0x27bdffd8, 0xafb3001c, 0xafbf0020,
-0xafb20018, 0xafb10014, 0xafb00010, 0x93620008,
-0x14400081, 0x809821, 0xaf60000c, 0x97850040,
-0x30a44000, 0x1080008b, 0x24030016, 0x24104007,
-0xa363000a, 0xaf700014, 0x938f0042, 0x8f6c0014,
-0x31ee0007, 0xe6a40, 0x18d5825, 0xaf6b0014,
-0x978a0040, 0x8f680014, 0x31490010, 0x1093825,
-0xaf670014, 0x97860040, 0x30c30008, 0x5060008d,
-0x2821, 0x8f660014, 0x3c031000, 0x3c028100,
-0xc32825, 0xaf650014, 0x97440e0a, 0x2418000e,
-0x3405fffc, 0x309fffff, 0x3e2c825, 0xaf790004,
-0xa3780002, 0x9372000a, 0x26510004, 0xa371000a,
-0x97830040, 0x9364000a, 0x30661f00, 0x61183,
-0x44f821, 0x27f90028, 0xa3790009, 0x97580e0c,
-0xa7780010, 0x93720009, 0x26510002, 0x32300007,
-0x107823, 0x31ee0007, 0xa36e000b, 0x936d0009,
-0x976c0010, 0x8f900034, 0x97890040, 0x31ab00ff,
-0x16c5021, 0x1454021, 0x31270040, 0x10e00005,
-0x3105ffff, 0xb0382b, 0x3c068000, 0x10e00014,
-0x8821, 0x205402b, 0x15000033, 0x2021,
-0x8f4a0e14, 0xaf4a0e10, 0x8f490e1c, 0xaf490e18,
-0xaf450e00, 0x8f4c0000, 0x318b0008, 0x1160fffd,
-0x0, 0x974d0e08, 0xa08021, 0x3021,
-0xa78d0040, 0x8f450e04, 0x24110001, 0xaf850034,
-0x976e0010, 0x31d2ffff, 0x8e640000, 0x901023,
-0x14400009, 0xae620000, 0x8f6a0014, 0x8f870048,
-0x35490040, 0xaf690014, 0x8f480e10, 0xace80020,
-0x8f430e18, 0xace30024, 0xc02021, 0xe0000f5,
-0x2002821, 0x8e660000, 0x14c00005, 0x0,
-0x8f6b0014, 0x240cffbf, 0x16c9824, 0xaf730014,
-0x8f6d000c, 0x1b22821, 0xaf65000c, 0x93720008,
-0x16400003, 0x0, 0x16200031, 0x0,
-0xa3710008, 0x2002021, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x801021,
-0x3e00008, 0x27bd0028, 0x8f900034, 0x97910040,
-0x3c068000, 0x2009021, 0x322f0040, 0x15e0ffd2,
-0x8821, 0x977f0010, 0x8f980034, 0x33f9ffff,
-0x1738ffed, 0x2021, 0x3021, 0xa0001b9,
-0x24110001, 0x2403000e, 0x24104007, 0xa363000a,
-0xaf700014, 0x938f0042, 0x8f6c0014, 0x31ee0007,
-0xe6a40, 0x18d5825, 0xaf6b0014, 0x978a0040,
-0x8f680014, 0x31490010, 0x1093825, 0xaf670014,
-0x97860040, 0x30c30008, 0x1460ff76, 0x0,
-0x2821, 0xaf600004, 0xa000187, 0xa3600002,
-0x8f6f0014, 0x3c19efff, 0x3738fffe, 0x1f87024,
-0xa0001d7, 0xaf6e0014, 0x8f870038, 0x8f8a0044,
-0x27bdffe0, 0x8f860048, 0xafb00018, 0xafbf001c,
-0x8f450104, 0x8d4900ac, 0xaf470080, 0x8cc80020,
-0xa93823, 0x8021, 0xaf480e10, 0x8f440e10,
-0x4821, 0xaf440e14, 0x8cc20024, 0xaf420e18,
-0x8f430e18, 0xaf430e1c, 0x10e00036, 0x2d390001,
-0x936b0008, 0x1160004f, 0x0, 0x976e0010,
-0x31cdffff, 0xed602b, 0x1580004a, 0x0,
-0x97780010, 0x330fffff, 0xaf4f0e00, 0x8f5f0000,
-0x33f90008, 0x1320fffd, 0x0, 0x97420e08,
-0x8f460e04, 0x3045ffff, 0x30a30001, 0x1060008a,
-0x0, 0xd, 0x30a8a040, 0x24040040,
-0x1104003b, 0x30a9a000, 0x11200085, 0x0,
-0x936c0008, 0x51800009, 0x27a40010, 0x976f0010,
-0x31eeffff, 0xce682b, 0x11a00004, 0x27a40010,
-0x30b80040, 0x1300007a, 0x0, 0xafa70010,
-0xa7850040, 0xaf860034, 0xe000158, 0x0,
-0x404821, 0x1440ffd0, 0x8fa70010, 0x8f420e14,
-0x8f840048, 0xac820020, 0x8f470e1c, 0xac870024,
-0x2d390001, 0x3303025, 0x10c00017, 0x8fbf001c,
-0x8f840038, 0x24100f00, 0x10900085, 0x0,
-0x8f4f0178, 0x5e0fffe, 0x24180f00, 0x1098006f,
-0x0, 0x8f470e14, 0x24020240, 0x3c101000,
-0xaf470144, 0x8f490e1c, 0xaf490148, 0xa3400152,
-0xa740015a, 0xaf400160, 0xa7400158, 0xaf420154,
-0xaf500178, 0x8fbf001c, 0x8fb00018, 0x3e00008,
-0x27bd0020, 0xaf470e00, 0xa00022e, 0x0,
-0x8f490178, 0x520fffe, 0x240a0800, 0x8f84003c,
-0xaf4a0178, 0x9758008a, 0x330fffff, 0x1e47023,
-0x25cdffff, 0x31ac1fff, 0x2d8b0008, 0x1560fff9,
-0x0, 0x8f83004c, 0x8f9f0038, 0xc04821,
-0x3442021, 0x24660001, 0x24190f00, 0xaf86004c,
-0x306a00ff, 0xe93823, 0x24864000, 0x13f90005,
-0x24080001, 0x938b0042, 0x31680007, 0x81240,
-0x34480001, 0xa7c00, 0x3c180100, 0x1f87025,
-0xac8e4000, 0x8f8d004c, 0x30ac0036, 0x30a40008,
-0xaccd0004, 0x1080002e, 0x10c3025, 0x974d0e0a,
-0x8f8c003c, 0x3c028100, 0x31a4ffff, 0x258b0008,
-0x824025, 0x3c031000, 0x31651fff, 0x25390006,
+0x8f820000, 0x24860007, 0x30c5fff8, 0xa21821,
+0x30641fff, 0x3e00008, 0xaf840000, 0x8f870038,
+0x8f8a0040, 0x27bdffb8, 0x8f860044, 0xafb60040,
+0xafbf0044, 0xafb5003c, 0xafb40038, 0xafb30034,
+0xafb20030, 0xafb1002c, 0xafb00028, 0x8f450104,
+0x8d4900ac, 0xaf470080, 0x8cc80020, 0xa93823,
+0xb021, 0xaf480e10, 0x8f440e10, 0x4821,
+0xaf440e14, 0x8cc20024, 0xaf420e18, 0x8f430e18,
+0xaf430e1c, 0x10e00125, 0x2d230001, 0x936b0008,
+0x116000d4, 0x0, 0x976e0010, 0x31cdffff,
+0xed602b, 0x158000cf, 0x0, 0x97700010,
+0x320fffff, 0xaf4f0e00, 0x8f520000, 0x32510008,
+0x1220fffd, 0x0, 0x97540e08, 0x8f460e04,
+0x3285ffff, 0x30b30001, 0x12600132, 0x0,
+0xd, 0x30b8a040, 0x24150040, 0x131500c0,
+0x30a9a000, 0x1120012d, 0x0, 0x937f0008,
+0x13e00008, 0x0, 0x97630010, 0x306bffff,
+0xcb402b, 0x11000003, 0x30ac0040, 0x11800123,
+0x0, 0xa785003c, 0xaf860034, 0x93660008,
+0xe02821, 0xafa70020, 0x14c00124, 0x27b30020,
+0xaf60000c, 0x9782003c, 0x30474000, 0x14e00002,
+0x24030016, 0x2403000e, 0x24194007, 0xa363000a,
+0xaf790014, 0x938a003e, 0x8f740014, 0x31580007,
+0x18aa40, 0x2959025, 0xaf720014, 0x9784003c,
+0x8f700014, 0x30910010, 0x2117825, 0xaf6f0014,
+0x978e003c, 0x31cd0008, 0x11a00147, 0x2821,
+0x8f670014, 0x3c021000, 0x3c0c8100, 0xe22825,
+0xaf650014, 0x97460e0a, 0x2408000e, 0x3405fffc,
+0x30c3ffff, 0x6c5825, 0xaf6b0004, 0xa3680002,
+0x937f000a, 0x27e90004, 0xa369000a, 0x9786003c,
+0x9363000a, 0x30cc1f00, 0xc5983, 0x1634021,
+0x251f0028, 0xa37f0009, 0x97490e0c, 0xa7690010,
+0x93790009, 0x272a0002, 0x31580007, 0x18a823,
+0x32b10007, 0xa371000b, 0x93740009, 0x97640010,
+0x8f910034, 0x978f003c, 0x329200ff, 0x2448021,
+0x2057021, 0x31ed0040, 0x11a00005, 0x31c4ffff,
+0x91282b, 0x3c128000, 0x10a00014, 0xa021,
+0x224382b, 0x14e0011b, 0x8fa50020, 0x8f4d0e14,
+0xaf4d0e10, 0x8f420e1c, 0xaf420e18, 0xaf440e00,
+0x8f4f0000, 0x31ee0008, 0x11c0fffd, 0x0,
+0x97540e08, 0x808821, 0x9021, 0xa794003c,
+0x8f500e04, 0x24140001, 0xaf900034, 0x97640010,
+0x3095ffff, 0x8e680000, 0x111f823, 0x17e00009,
+0xae7f0000, 0x8f650014, 0x8f8b0044, 0x34a60040,
+0xaf660014, 0x8f4c0e10, 0xad6c0020, 0x8f430e18,
+0xad630024, 0x93670008, 0x14e000d2, 0x0,
+0xe00009e, 0x24040010, 0x8f890048, 0x3c083200,
+0x402821, 0x312600ff, 0x6fc00, 0x3e85025,
+0x25390001, 0xaf990048, 0xac4a0000, 0x93780009,
+0x9370000a, 0x330400ff, 0x47400, 0x320f00ff,
+0x1cf6825, 0xac4d0004, 0x8f820048, 0x64000ea,
+0xaca20008, 0xaca0000c, 0x9783003c, 0x306b0008,
+0x15600002, 0x26280006, 0x26280002, 0x974e0e14,
+0x8f450e1c, 0x8f670004, 0x936d0002, 0x31c4ffff,
+0x31a200ff, 0xafa20010, 0x8f6c0014, 0xafa80018,
+0xe00008b, 0xafac0014, 0x24040010, 0xe0000c7,
+0x0, 0x8e720000, 0x16400005, 0x0,
+0x8f640014, 0x2405ffbf, 0x859824, 0xaf730014,
+0x8f79000c, 0x3353821, 0xaf67000c, 0x93750008,
+0x16a00008, 0x0, 0x12800006, 0x0,
+0x8f7f0014, 0x3c0befff, 0x3568fffe, 0x3e84824,
+0xaf690014, 0xa3740008, 0x8fa50020, 0xa000246,
+0x2202021, 0xaf470e00, 0xa0000f5, 0x0,
+0x8f590178, 0x720fffe, 0x241f0800, 0x8f840000,
+0xaf5f0178, 0x974b008a, 0x316affff, 0x1444823,
+0x2528ffff, 0x31021fff, 0x2c430008, 0x1460fff9,
+0x0, 0x8f8e0048, 0x8f8d0038, 0xc04821,
+0x3442021, 0x25c60001, 0x240c0f00, 0xaf860048,
+0xe93823, 0x24864000, 0x31ca00ff, 0x11ac0005,
+0x24080001, 0x9391003e, 0x32300007, 0x107a40,
+0x35e80001, 0xaac00, 0x3c180100, 0x2b8a025,
+0xac944000, 0x8f930048, 0x30b20036, 0x30a40008,
+0xacd30004, 0x10800097, 0x1123025, 0x974e0e0a,
+0x8f8d0000, 0x3c028100, 0x31ccffff, 0x25ab0008,
+0x1824025, 0x3c031000, 0x31651fff, 0x25390006,
0x241f000e, 0xaf480160, 0xc33025, 0xa75f015a,
-0xaf85003c, 0xa7590158, 0x14e0000a, 0x8f9f0038,
-0x24050f00, 0x53e50002, 0x24100001, 0x34c60040,
-0x8f430e10, 0x8f880048, 0xad030020, 0x8f4b0e18,
-0xad0b0024, 0x8f420e14, 0xaf420144, 0x8f440e1c,
-0xaf440148, 0xa34a0152, 0x3c0a1000, 0xaf460154,
-0xa000221, 0xaf4a0178, 0x14c0ff78, 0x30a8a040,
-0x8f420e14, 0x8f840048, 0x4821, 0xac820020,
-0x8f470e1c, 0xac870024, 0xa000258, 0x2d390001,
-0x8f98003c, 0x25390002, 0xa7590158, 0x270f0008,
-0x31ee1fff, 0xa0002ad, 0xaf8e003c, 0xaf40014c,
-0x1120002c, 0x0, 0x8f460e10, 0xaf460144,
-0x8f430e18, 0x24020040, 0x3c101000, 0xaf430148,
-0xa3400152, 0xa740015a, 0xaf400160, 0xa7400158,
-0xaf420154, 0xaf500178, 0xa000271, 0x8fbf001c,
-0x11200006, 0x0, 0x975f0e08, 0x33e50040,
-0x14a00002, 0x0, 0xd, 0x8f480178,
-0x500fffe, 0x0, 0x974e0e10, 0x3c0d0500,
-0x24032000, 0x31ccffff, 0x18d1025, 0xaf42014c,
-0x8f440e14, 0x3c0b1000, 0xaf440144, 0x8f4a0e1c,
-0xaf4a0148, 0xa3400152, 0x8f840038, 0xa740015a,
-0xaf400160, 0xa7400158, 0xaf430154, 0xa00025f,
-0xaf4b0178, 0x8f590e14, 0xaf590144, 0x8f430e1c,
-0xa0002d9, 0x24020040, 0x27bdffe0, 0xafb20018,
-0xafb10014, 0xafb00010, 0xafbf001c, 0xe0000ca,
-0x0, 0x3c028000, 0x8f8a0044, 0x34500070,
-0x3c120800, 0x26523b70, 0x2008821, 0x8e080000,
-0x8f450000, 0x38a40001, 0x30830001, 0x10600017,
-0xaf880030, 0x2204821, 0x8d2c0000, 0x3c020800,
-0x8c42006c, 0x3c180800, 0x8f180068, 0x1881823,
-0x436821, 0xc821, 0x1a3782b, 0x3197021,
-0x1cf4021, 0x3c010800, 0xac2d006c, 0x3c010800,
-0xac280068, 0x8f4b0000, 0x39670001, 0x30e60001,
-0x14c0ffed, 0x1804021, 0xaf8c0030, 0x8e180000,
-0x3c0e0800, 0x8dce006c, 0x3c0c0800, 0x8d8c0068,
-0x3087823, 0x1cf2821, 0x4021, 0xaf302b,
-0x1885821, 0x1662021, 0x3c010800, 0xac25006c,
-0x3c010800, 0xac240068, 0x8f490100, 0x25470088,
-0xaf870048, 0xaf890038, 0xaf490020, 0x8e070000,
-0xaf870030, 0x8f590178, 0x720fffe, 0x0,
-0x8e0f0000, 0x3c0d0800, 0x8dad0074, 0x3c0c0800,
-0x8d8c0070, 0x1e77023, 0x1ae2821, 0x3021,
-0xae582b, 0x1862021, 0x8b3821, 0x24090800,
-0x3c010800, 0xac250074, 0x3c010800, 0xac270070,
-0xaf490178, 0x93430108, 0xa3830042, 0x93820042,
-0x305f0001, 0x17e00015, 0x8f830038, 0x241f0d00,
-0x107f0019, 0x24020f00, 0x1062001d, 0x0,
-0x91470000, 0x24030050, 0x30e900ff, 0x11230004,
-0x3c054000, 0xaf450138, 0xa000312, 0x0,
-0xe0008da, 0x0, 0x8f8a0044, 0x3c054000,
-0xaf450138, 0xa000312, 0x0, 0x93990042,
-0x33380006, 0x185100, 0xe00020d, 0x152d821,
-0xa00036e, 0x8f8a0044, 0x3c1b0800, 0x277b3bf0,
-0xe00020d, 0x0, 0xa00036e, 0x8f8a0044,
-0x3c1b0800, 0x277b3c10, 0xe00020d, 0x0,
-0xa00036e, 0x8f8a0044, 0x90aa0001, 0x8fab0010,
-0x8cac0010, 0x3c0300ff, 0x8d680004, 0xad6c0020,
-0x8cad0014, 0xe06021, 0x3462ffff, 0xad6d0024,
-0x8ca70018, 0x3c09ff00, 0x109c024, 0xad670028,
-0x8cae001c, 0x182c824, 0x3197825, 0xad6f0004,
-0xad6e002c, 0x8cad0008, 0x314a00ff, 0xad6d001c,
-0x94a90002, 0x3128ffff, 0xad680010, 0x90a70000,
-0xa5600002, 0xa1600004, 0xa1670000, 0x90a30002,
-0x306200ff, 0x21982, 0x10600005, 0x24050001,
-0x1065000e, 0x0, 0x3e00008, 0xa16a0001,
-0x8cd80028, 0x354a0080, 0xad780018, 0x8ccf0014,
-0xad6f0014, 0x8cce0030, 0xad6e0008, 0x8cc4002c,
-0xa16a0001, 0x3e00008, 0xad64000c, 0x8ccd001c,
-0xad6d0018, 0x8cc90014, 0xad690014, 0x8cc80024,
-0xad680008, 0x8cc70020, 0xad67000c, 0x8cc20014,
-0x8c830064, 0x43c82b, 0x13200007, 0x0,
-0x8cc20014, 0x144cffe4, 0x0, 0x354a0080,
-0x3e00008, 0xa16a0001, 0x8c820064, 0xa0003c4,
-0x0, 0x90aa0000, 0x27bdfff8, 0x8fa9001c,
-0xa3aa0000, 0x8fae0000, 0x3c0fff80, 0x8fa80018,
-0x35e2ffff, 0x8ccd002c, 0x1c26024, 0xafac0000,
-0xa1200004, 0xe06021, 0xa7a00002, 0x8fb80000,
-0x8d270004, 0x1881821, 0xa05821, 0xc05021,
-0x6d2826, 0x3c06ff7f, 0x3c0f00ff, 0x2cad0001,
-0x35eeffff, 0x34d9ffff, 0x3c02ff00, 0x3193024,
-0xd1dc0, 0x10ec824, 0xe2c024, 0xc37025,
-0x3197825, 0xad2e0000, 0xad2f0004, 0x8d450024,
-0xafae0000, 0xad250008, 0x8d4d0020, 0x2405ffff,
-0xad2d000c, 0x95680002, 0x3107ffff, 0xad270010,
-0x91660018, 0x30c200ff, 0x219c2, 0x50600001,
-0x8d450034, 0xad250014, 0x8d670008, 0x27bd0008,
-0xad27001c, 0x8c8b00cc, 0xad2c0028, 0xad20002c,
-0xad2b0024, 0xad200018, 0x3e00008, 0xad200020,
-0x27bdffe0, 0xafb20018, 0xafb10014, 0xafb00010,
-0xafbf001c, 0x90980000, 0xc08821, 0x3c0d00ff,
-0x330f007f, 0xa0cf0000, 0x908e0001, 0x35acffff,
-0x3c0aff00, 0xa0ce0001, 0x94a6001e, 0xa2200004,
-0x8cab0014, 0x8e290004, 0xa08021, 0x16c2824,
-0x12a4024, 0x809021, 0x1052025, 0xa6260002,
-0xae240004, 0x26050020, 0x26240008, 0xe000072,
-0x24060002, 0x92470000, 0x26050028, 0x26240014,
-0x71e00, 0x31603, 0x24060004, 0x4400003,
-0x2403ffff, 0x96590002, 0x3323ffff, 0xe000072,
-0xae230010, 0x26240024, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x24050003, 0x3021,
-0xa00007c, 0x27bd0020, 0x27bdffd8, 0xafb1001c,
-0xafb00018, 0xafbf0020, 0x90a80000, 0x24020001,
-0x8fb0003c, 0x3103003f, 0x808821, 0x10620014,
-0x8faa0038, 0x240b0005, 0x506b0016, 0xafaa0010,
-0xa02021, 0xc02821, 0xe000407, 0x2003021,
-0x922400bc, 0x30830002, 0x10600003, 0x26060030,
-0xacc00000, 0x24c60004, 0x8fbf0020, 0x8fb1001c,
-0x8fb00018, 0xc01021, 0x3e00008, 0x27bd0028,
-0x1403821, 0xe000385, 0xafb00010, 0xa00044b,
-0x0, 0xe0003cc, 0xafb00014, 0xa00044b,
-0x0, 0x3c02000a, 0x3421821, 0x3c040800,
-0x24843b08, 0x2405001a, 0x3021, 0xa00007c,
-0xaf83002c, 0x3c038000, 0x34620070, 0x8c480000,
-0xa05821, 0xc04821, 0x308a00ff, 0xaf880030,
-0x8f440178, 0x480fffe, 0x3c0c8000, 0x35860070,
-0x8cc50000, 0x3c030800, 0x8c630074, 0x3c180800,
-0x8f180070, 0xa82023, 0x646821, 0xc821,
-0x1a4782b, 0x3197021, 0x1cf6021, 0x3c010800,
-0xac2d0074, 0x3c010800, 0xac2c0070, 0x8f480e14,
-0xaf480144, 0xaf47014c, 0xa34a0152, 0xa74b0158,
-0x93460108, 0x30c50008, 0x54a00001, 0x35291000,
-0x934b0900, 0x24070050, 0x316a00ff, 0x11470007,
-0x0, 0x8f450e1c, 0xaf450148, 0xaf490154,
-0x3c091000, 0x3e00008, 0xaf490178, 0x934d0108,
-0x31a80008, 0x11000010, 0x0, 0x934f0108,
-0x31ee0010, 0x51c00001, 0x35290008, 0x3c040800,
-0x90843b6c, 0xa3440150, 0x8f4309a4, 0xaf430148,
-0x8f4209a0, 0xaf420144, 0xaf490154, 0x3c091000,
-0x3e00008, 0xaf490178, 0x3c190800, 0x8f393b28,
-0x33380008, 0x5700fff1, 0x35290008, 0xa00049e,
-0x0, 0x24070040, 0xaf470814, 0xaf400810,
-0x8f420944, 0x8f430950, 0x8f440954, 0x8f45095c,
-0x8f46094c, 0xaf820064, 0xaf830054, 0xaf840050,
-0xaf85005c, 0x3e00008, 0xaf860060, 0x93460109,
-0x30c5007f, 0x518c0, 0x52140, 0x831021,
-0x3e00008, 0x24420088, 0x3c0a0800, 0x914a3b2d,
-0x3c090800, 0x95293b26, 0x3c051100, 0xa3c00,
-0x25280002, 0xe83025, 0xc51825, 0x24820008,
-0xac830000, 0x3e00008, 0xac800004, 0x8f4a002c,
-0x974d0908, 0x3c0e000e, 0x34e3821, 0x31acffff,
-0xc41c0, 0xaf48002c, 0x97430908, 0x94eb001a,
-0x804021, 0x24020001, 0x3169ffff, 0xac890000,
-0x8ce6001c, 0xa05821, 0xac860004, 0x8ce40020,
-0xad040008, 0x90e30019, 0x30630003, 0x1062003e,
-0x0, 0x28650002, 0x14a00071, 0x240f0002,
-0x106f004c, 0x0, 0x24180003, 0x10780055,
-0x0, 0x3c090800, 0x95293b1c, 0x93430934,
-0x934f0921, 0x3c050800, 0x94a53b22, 0x306400ff,
-0x94ee002a, 0x46882, 0x31ec00ff, 0x978f0058,
-0xdc600, 0xccc00, 0x3127ffff, 0x3191025,
-0xa73021, 0x462025, 0x1cf6821, 0x3c034000,
-0x836025, 0xd4c00, 0xad090004, 0xad0c0000,
-0x93590920, 0x3c180006, 0x25090014, 0x193e00,
-0xf82825, 0xad050008, 0x8f4e092c, 0x25e60001,
-0x30c27fff, 0xad0e000c, 0x8f440930, 0xa7820058,
-0x25020028, 0xad040010, 0x8f4d0938, 0xad0d0014,
-0xad2b0004, 0x8f4c0940, 0xad2c0008, 0x93430937,
-0x3c190800, 0x93393b2c, 0xad200010, 0x34700,
-0x19c400, 0x1185825, 0x3567ffff, 0xad27000c,
-0x3e00008, 0xaf4a002c, 0x3c090800, 0x95293b1c,
-0x3c0d0800, 0x95ad3b26, 0x3c0c0800, 0x958c3b18,
-0x94e40024, 0x312effff, 0x1ae3021, 0xcc1823,
-0x4cc00, 0x2462fff2, 0x322c025, 0x240f0800,
-0xad18000c, 0xad0f0014, 0xad000010, 0xa0004f2,
-0x25080018, 0x94e50024, 0x94ee0028, 0x3c090800,
-0x95293b1c, 0x56c00, 0xe6400, 0x35a68100,
-0x35840800, 0xad06000c, 0xad040010, 0xa0004f2,
-0x25080014, 0x3c090800, 0x95293b1c, 0x3c0f0800,
-0x95ef3b26, 0x3c060800, 0x94c63b18, 0x94e40024,
-0x3125ffff, 0x94ed0028, 0x1e57021, 0x1c66023,
-0x4cc00, 0xd1c00, 0x2582ffee, 0x627825,
-0x37388100, 0x24050800, 0xad18000c, 0xad0f0010,
-0xad050018, 0xad000014, 0xa0004f2, 0x2508001c,
-0x1460ff94, 0x0, 0x94e30024, 0x3c090800,
-0x95293b1c, 0x31400, 0x34590800, 0xad19000c,
-0xa0004f2, 0x25080010, 0x3e00008, 0x240201f4,
-0x27bdffe8, 0xafb00010, 0xafbf0014, 0xe00005c,
-0x808021, 0x24050040, 0xaf450814, 0x8f830054,
-0x8f840050, 0x8f85005c, 0x701821, 0x641023,
-0x18400004, 0xaf830054, 0xaf630054, 0x8f660054,
-0xaf860050, 0x1200000c, 0x0, 0x8f440074,
-0x93680081, 0x3409fa00, 0x2d070007, 0x10e00005,
-0x891021, 0x936c0081, 0x240b01f4, 0x18b5004,
-0x1441021, 0xaf62000c, 0x8f4e095c, 0x1c56823,
-0x19a00004, 0x8fbf0014, 0x8f4f095c, 0xaf8f005c,
-0x8fbf0014, 0x8fb00010, 0xa00005e, 0x27bd0018,
-0x8f840064, 0x8f830054, 0x8f820050, 0xaf640044,
-0xaf630050, 0x3e00008, 0xaf620054, 0x3c038000,
-0x34620070, 0x8c430000, 0x27bdfff8, 0x308700ff,
-0x30a900ff, 0x30c800ff, 0xaf830030, 0x8f440178,
-0x480fffe, 0x3c028000, 0x34590070, 0x8f380000,
-0xa3a70003, 0x3c070800, 0x8ce70074, 0x8fac0000,
-0x3c060800, 0x8cc60070, 0x3037823, 0x3c0e7fff,
-0xefc821, 0x35cdffff, 0x5021, 0x18d2824,
-0xca1821, 0x847c0, 0x32f202b, 0xa81025,
-0x64c021, 0xafa20000, 0x3c010800, 0xac390074,
-0x3c010800, 0xac380070, 0x934f010a, 0xa3a00002,
-0x3c0e80ff, 0xa3af0001, 0x8fac0000, 0x312b007f,
-0x35cdffff, 0x18d4824, 0xb5600, 0x12a4025,
-0x24073000, 0x2406ff80, 0x3c051000, 0x27bd0008,
-0xaf48014c, 0xaf470154, 0xa7400158, 0xa3460152,
-0x3e00008, 0xaf450178, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0x8f650074, 0x3c068000, 0x309000ff,
-0xa62025, 0xe00005c, 0xaf640074, 0x93630005,
-0x34620008, 0xe00005e, 0xa3620005, 0x2002021,
-0x8fbf0014, 0x8fb00010, 0x24050005, 0x24060001,
-0xa000596, 0x27bd0018, 0x27bdffe0, 0x3c038000,
-0xafb00010, 0xafbf0018, 0xafb10014, 0x34620070,
-0x8c470000, 0x309000ff, 0x30a800ff, 0xaf870030,
-0x8f440178, 0x480fffe, 0x3c188000, 0x37110070,
-0x8e2f0000, 0x3c0d0800, 0x8dad0074, 0x3c0a0800,
-0x8d4a0070, 0x1e77023, 0x1ae2821, 0x5821,
-0xae302b, 0x14b4821, 0x1263821, 0x3c010800,
-0xac250074, 0x8821, 0x3c010800, 0xac270070,
-0x1100000f, 0x0, 0x8f620074, 0x2619ffff,
-0x3208007f, 0x2fe02, 0x33e5007f, 0x15000006,
-0x332200ff, 0x2407ff80, 0x2072026, 0x24a3ffff,
-0x838025, 0x320200ff, 0x408021, 0x24111008,
-0xe00005c, 0x0, 0x8f490818, 0x31250004,
-0x14a0fffd, 0x3218007f, 0x1878c0, 0x187140,
-0x1cf6821, 0x25ac0088, 0xaf4c0818, 0x274a0980,
-0x8d4b0020, 0xaf4b0144, 0x8d460024, 0xaf460148,
-0xa3500150, 0xe00005e, 0xa7400158, 0x2201021,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0020, 0x27bdffe8, 0x308400ff, 0xafbf0010,
-0xe0005e1, 0x30a500ff, 0x8f830054, 0x8fbf0010,
-0x34450040, 0x2404ff90, 0x3c021000, 0x27bd0018,
-0xaf43014c, 0xa3440152, 0xaf450154, 0x3e00008,
-0xaf420178, 0x27bdffe8, 0xafbf0014, 0xafb00010,
-0x9345093f, 0x24020006, 0x3c080800, 0x95083b22,
-0x30a300ff, 0x2487ffd8, 0x24050004, 0x10620036,
-0x24060002, 0x974e093c, 0x3c0d0204, 0x63400,
-0x31ccffff, 0x18d5825, 0xac8b0000, 0x934a093e,
-0x31490020, 0x11200008, 0x0, 0x935f0936,
-0x3c190103, 0x37380300, 0x33f000ff, 0x2187825,
-0x24050008, 0xac8f0004, 0x93580934, 0x934d0921,
-0x3c104000, 0x330e00ff, 0xe6082, 0x31ab00ff,
-0xc5600, 0xb1400, 0x1421825, 0x68f825,
-0x3f0c825, 0xac99ffd8, 0x93580937, 0x8f4c0948,
-0x8f4d0940, 0x57882, 0x330e00ff, 0x1cf5821,
-0x18d2823, 0xb5700, 0x1461025, 0x30a3ffff,
-0x434025, 0xf4880, 0x1273021, 0xace80020,
-0xe00005c, 0x24d00028, 0x24040004, 0xe00005e,
-0xa364003f, 0x2001021, 0x8fbf0014, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0xa000644, 0x24060012,
-0x27bdffd0, 0x24090010, 0xafb50024, 0xafb40020,
-0xafb3001c, 0xafb10014, 0xafb00010, 0x3c010800,
-0xa0293b2c, 0xafbf0028, 0xafb20018, 0x97480908,
-0x309400ff, 0x3c02000e, 0x3107ffff, 0x731c0,
-0xaf46002c, 0x97440908, 0x9344010b, 0x30b300ff,
-0x3428021, 0x30830030, 0xa821, 0x106000e4,
-0x8821, 0x240c0004, 0x3c010800, 0xa02c3b2c,
-0x934b093e, 0xb5600, 0xa2e03, 0x4a00131,
-0x0, 0xaf400048, 0x9352010b, 0x324f0020,
-0x11e00006, 0x0, 0x935f093e, 0x1fce00,
-0x19c603, 0x7000148, 0x0, 0x9346010b,
-0x30c20040, 0x10400003, 0x8f920054, 0x8f870054,
-0x24f2ffff, 0x960a002c, 0x93450934, 0x93490937,
-0xa78a0058, 0x30a600ff, 0x312700ff, 0x71080,
-0x462021, 0x91f821, 0x3c010800, 0xa43f3b22,
-0x92030018, 0x3c010800, 0xa4203b1c, 0x3c010800,
-0xa4203b18, 0x307000ff, 0x3f04021, 0x250b000a,
-0x3170ffff, 0x3c010800, 0xa4283b24, 0x3c010800,
-0xa4283b26, 0xe00009a, 0x2002021, 0xe0004c5,
-0x402021, 0x8f4b002c, 0x97580908, 0x3c19000e,
-0x3594021, 0x330fffff, 0xf71c0, 0xaf4e002c,
-0x97430908, 0x950d001a, 0x24110001, 0x403821,
-0x31acffff, 0xac4c0000, 0x8d0a001c, 0xac4a0004,
-0x8d050020, 0xac450008, 0x91090019, 0x31230003,
-0x107100bd, 0x28710002, 0x16200103, 0x240c0002,
-0x106c00f5, 0x240d0003, 0x106d00ca, 0x0,
-0x3c090800, 0x95293b1c, 0x93430934, 0x93580921,
-0x3c0a0800, 0x954a3b22, 0x306400ff, 0x950c002a,
-0x4f882, 0x331900ff, 0x97980058, 0x1f7600,
-0x197c00, 0x3126ffff, 0x1cf4025, 0x1466821,
-0x10d8825, 0x1982821, 0x3c084000, 0x2281025,
-0x54c00, 0xace90004, 0xace20000, 0x93430920,
-0x3c040006, 0x24e90014, 0x3fe00, 0x3e4c825,
-0xacf90008, 0x8f4e092c, 0x270f0001, 0x31e67fff,
-0xacee000c, 0x8f4d0930, 0xa7860058, 0x24e60028,
-0xaced0010, 0x8f4c0938, 0xacec0014, 0xad320004,
-0x8f510940, 0xad310008, 0x93420937, 0x3c050800,
-0x90a53b2c, 0xad200010, 0x22700, 0x51c00,
-0x83f825, 0x37f2ffff, 0xad32000c, 0xaf4b002c,
-0x12a00033, 0x0, 0x9352093f, 0x24150006,
-0x24050004, 0x324b00ff, 0x117500cd, 0x24090002,
-0x974f093c, 0x3c0e0204, 0x31edffff, 0x1ae6025,
-0xacec0028, 0x9351093e, 0x32220020, 0x10400008,
-0x0, 0x93440936, 0x3c180103, 0x371f0300,
-0x309900ff, 0x33f2825, 0xacc50004, 0x24050008,
-0x93520934, 0x93430921, 0x56082, 0x324b00ff,
-0xba882, 0x306400ff, 0x15fe00, 0x4c400,
-0x3f8c825, 0x32a7825, 0x1e87025, 0xacceffd8,
-0x934d0937, 0x8f520948, 0x8f420940, 0x31b100ff,
-0x22c5821, 0x2423023, 0xb1f00, 0x9ac00,
-0x754825, 0x30c8ffff, 0x1285025, 0xe00005c,
-0xacea0020, 0x24070004, 0xe00005e, 0xa367003f,
-0xe0000c3, 0x2002021, 0x3c050800, 0x90a53b2c,
-0x30b00003, 0x1200000f, 0x2802021, 0x8f880054,
-0x25090001, 0xaf890054, 0xaf690050, 0x8f6a0054,
-0x1493823, 0x18e00002, 0x1202021, 0x8f640054,
-0xaf640054, 0x8f420074, 0x244601f4, 0xaf66000c,
-0x2802021, 0x2602821, 0xa7600068, 0xe0005e1,
-0x3c131000, 0x8f8e0054, 0x34540006, 0xaf4e014c,
-0x8f8d004c, 0x8fbf0028, 0x8fb50024, 0x31b100ff,
-0x25ac0001, 0xaf8c004c, 0x8fb20018, 0xa3510152,
-0x8fb00010, 0xaf540154, 0x8fb10014, 0xaf530178,
-0x8fb40020, 0x8fb3001c, 0x3e00008, 0x27bd0030,
-0x9359093e, 0x19c600, 0x189603, 0x6420048,
-0x24110002, 0x93420923, 0x30440002, 0x1080ff1e,
-0x8f870060, 0x8f860054, 0x14e6ff1b, 0x0,
-0xe00005c, 0x0, 0x9365003f, 0x24080016,
-0x30a900ff, 0x1128000c, 0x240a0008, 0x3c0d0800,
-0x91ad3b2c, 0x35ac0001, 0x3c010800, 0xa02c3b2c,
-0x936b003f, 0x316300ff, 0x106a0065, 0x240e000a,
-0x106e005e, 0x2402000c, 0xe00005e, 0x0,
-0xa00069d, 0x0, 0x3c090800, 0x95293b1c,
-0x3c190800, 0x97393b26, 0x3c180800, 0x97183b18,
-0x950e0024, 0x313fffff, 0x33f7821, 0x1f86823,
-0xe8c00, 0x25acfff2, 0x22c5025, 0x24050800,
-0x24470018, 0xac4a000c, 0xac450014, 0xa0006e5,
-0xac400010, 0x3c090800, 0x95293b1c, 0x3c180800,
-0x97183b26, 0x3c0f0800, 0x95ef3b18, 0x950d0024,
-0x3139ffff, 0x950c0028, 0x3197021, 0x1cf8823,
-0xd2c00, 0xc5400, 0x2622ffee, 0x1423025,
-0x34a48100, 0x24030800, 0xace4000c, 0xace60010,
-0xace30018, 0xace00014, 0xa0006e5, 0x24e7001c,
-0x3c010800, 0xa0313b2c, 0x9343093e, 0x24150001,
-0x307f0020, 0x17e0fed4, 0x24110008, 0xa00069d,
-0x24110004, 0x8f6e0084, 0x8f4d0940, 0x11a0fecd,
-0xaf8e0054, 0x240f0014, 0x3c010800, 0xa02f3b2c,
-0xa00069c, 0x0, 0x95020024, 0x95060028,
-0x3c090800, 0x95293b1c, 0x22400, 0x61c00,
-0x349f8100, 0x34790800, 0xacff000c, 0xacf90010,
-0xa0006e5, 0x24e70014, 0x1460ff01, 0x0,
-0x95180024, 0x3c090800, 0x95293b1c, 0x24470010,
-0x187c00, 0x35ee0800, 0xa0006e5, 0xac4e000c,
-0xa00071f, 0x24090012, 0x8f64004c, 0xaf640054,
-0x8f630054, 0xa0006a6, 0xaf630050, 0xa362003f,
-0xe00005e, 0x0, 0xa00069d, 0x0,
-0x24020014, 0xa0007f3, 0xa362003f, 0x27bdffe8,
-0x308400ff, 0xafbf0010, 0xe0005e1, 0x30a500ff,
+0xaf850000, 0xa7590158, 0x14e0000a, 0x8f930038,
+0x24120f00, 0x52720002, 0x24160001, 0x34c60040,
+0x8f580e10, 0x8f940044, 0xae980020, 0x8f550e18,
+0xae950024, 0x8f450e14, 0xaf450144, 0x8f590e1c,
+0xaf590148, 0xa34a0152, 0x3c0a1000, 0xaf460154,
+0xaf4a0178, 0x14e0fedd, 0x2d230001, 0x76a025,
+0x12800017, 0x8fbf0044, 0x8f840038, 0x24160f00,
+0x10960084, 0x0, 0x8f450178, 0x4a0fffe,
+0x24150f00, 0x1095006e, 0x0, 0x8f470e14,
+0x24020240, 0x3c1f1000, 0xaf470144, 0x8f440e1c,
+0xaf440148, 0xa3400152, 0xa740015a, 0xaf400160,
+0xa7400158, 0xaf420154, 0xaf5f0178, 0x8fbf0044,
+0x8fb60040, 0x8fb5003c, 0x8fb40038, 0x8fb30034,
+0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x3e00008,
+0x27bd0048, 0x14c0fed0, 0x30b8a040, 0x8f420e14,
+0x8f840044, 0x4821, 0xac820020, 0x8f510e1c,
+0xac910024, 0xa00020e, 0x2d230001, 0x8f910034,
+0x978a003c, 0x3c128000, 0x220a821, 0x31580040,
+0x1700ff30, 0xa021, 0x97690010, 0x8f920034,
+0x3139ffff, 0x13320035, 0x2021, 0x804821,
+0x1480fea0, 0xa03821, 0x8f420e14, 0x8f840044,
+0xac820020, 0x8f510e1c, 0xac910024, 0xa00020e,
+0x2d230001, 0x936a0009, 0x9378000b, 0x315000ff,
+0x330f00ff, 0x20f7021, 0x25c2000a, 0x3050ffff,
+0xe00009e, 0x2002021, 0x8f860048, 0x3c1f4100,
+0x24cd0001, 0xaf8d0048, 0x936c0009, 0x30c600ff,
+0x64400, 0x318300ff, 0x246b0002, 0x10b4825,
+0x13fc825, 0xac590000, 0x8f67000c, 0x97440e14,
+0xf22825, 0xac450004, 0x8f450e1c, 0x8f670004,
+0x936a0002, 0x3084ffff, 0x315800ff, 0xafb80010,
+0x8f6f0014, 0xafb10018, 0xe00008b, 0xafaf0014,
+0xa0001a6, 0x2002021, 0xaf600004, 0xa00013e,
+0xa3600002, 0xa000246, 0x2021, 0x9021,
+0xa000170, 0x24140001, 0x3c128000, 0xa000195,
+0xacb2000c, 0x8f910000, 0x25240002, 0xa7440158,
+0x26300008, 0x320f1fff, 0xa0001f9, 0xaf8f0000,
+0xaf40014c, 0x1120002c, 0x0, 0x8f590e10,
+0xaf590144, 0x8f430e18, 0x24020040, 0x3c1f1000,
+0xaf430148, 0xa3400152, 0xa740015a, 0xaf400160,
+0xa7400158, 0xaf420154, 0xaf5f0178, 0xa000227,
+0x8fbf0044, 0x11200006, 0x0, 0x97460e08,
+0x30cc0040, 0x15800002, 0x0, 0xd,
+0x8f4d0178, 0x5a0fffe, 0x0, 0x97530e10,
+0x3c120500, 0x240e2000, 0x326affff, 0x152c025,
+0xaf58014c, 0x8f4f0e14, 0x3c021000, 0xaf4f0144,
+0x8f500e1c, 0xaf500148, 0xa3400152, 0x8f840038,
+0xa740015a, 0xaf400160, 0xa7400158, 0xaf4e0154,
+0xa000215, 0xaf420178, 0x8f490e14, 0xaf490144,
+0x8f430e1c, 0xa00028e, 0x24020040, 0x3c0e20ff,
+0x27bdffe0, 0x3c1a8000, 0x3c0f8008, 0x35cdfffd,
+0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010,
+0xaf8f0040, 0xaf4d0e00, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x3c0c00ff,
+0x358bfffd, 0xaf4b0e00, 0x3c066004, 0x8cc95000,
+0x240aff7f, 0x3c116000, 0x12a4024, 0x3507380c,
+0xacc75000, 0x8e240438, 0x24050009, 0xaf450008,
+0x3083ffff, 0x38622f71, 0x2450c0b3, 0xaf800048,
+0xe000068, 0xaf800000, 0x52000001, 0xae20442c,
+0xe000435, 0x3c118000, 0xe000ed9, 0x36300070,
+0x8f8a0040, 0x3c120800, 0x26523c88, 0x2008821,
+0x8e080000, 0x8f5f0000, 0x3bf90001, 0x33380001,
+0x13000017, 0xaf880030, 0x2204821, 0x8d270000,
+0x3c0f0800, 0x8def006c, 0x3c0c0800, 0x8d8c0068,
+0xe8c023, 0x1f82821, 0x6821, 0xb8302b,
+0x18d5821, 0x1664021, 0x3c010800, 0xac25006c,
+0x3c010800, 0xac280068, 0x8f440000, 0x38830001,
+0x30620001, 0x1440ffed, 0xe04021, 0xaf870030,
+0x8e0c0000, 0x3c050800, 0x8ca5006c, 0x3c040800,
+0x8c840068, 0x1883023, 0xa63821, 0x1021,
+0xe6402b, 0x821821, 0x68f821, 0x3c010800,
+0xac27006c, 0x3c010800, 0xac3f0068, 0x8f490100,
+0x25590088, 0xaf990044, 0xaf890038, 0xaf490020,
+0x8e070000, 0xaf870030, 0x8f4d0178, 0x5a0fffe,
+0x0, 0x8e060000, 0x3c0b0800, 0x8d6b0074,
+0x3c040800, 0x8c840070, 0xc72823, 0x165f821,
+0x1021, 0x3e5402b, 0x823821, 0xe8c821,
+0x24090800, 0x3c010800, 0xac3f0074, 0x3c010800,
+0xac390070, 0xaf490178, 0x93580108, 0xa398003e,
+0x938f003e, 0x31ee0001, 0x15c00015, 0x8f830038,
+0x240e0d00, 0x106e0019, 0x240f0f00, 0x106f001d,
+0x0, 0x91590000, 0x24180050, 0x332900ff,
+0x11380004, 0x3c1f4000, 0xaf5f0138, 0xa0002e7,
+0x0, 0xe00090e, 0x0, 0x8f8a0040,
+0x3c1f4000, 0xaf5f0138, 0xa0002e7, 0x0,
+0x938d003e, 0x31ac0006, 0xc5100, 0xe0000ce,
+0x152d821, 0xa000343, 0x8f8a0040, 0x3c1b0800,
+0x277b3d08, 0xe0000ce, 0x0, 0xa000343,
+0x8f8a0040, 0x3c1b0800, 0x277b3d28, 0xe0000ce,
+0x0, 0xa000343, 0x8f8a0040, 0x90aa0001,
+0x8fab0010, 0x8cac0010, 0x3c0300ff, 0x8d680004,
+0xad6c0020, 0x8cad0014, 0xe06021, 0x3462ffff,
+0xad6d0024, 0x8ca70018, 0x3c09ff00, 0x109c024,
+0xad670028, 0x8cae001c, 0x182c824, 0x3197825,
+0xad6f0004, 0xad6e002c, 0x8cad0008, 0x314a00ff,
+0xad6d001c, 0x94a90002, 0x3128ffff, 0xad680010,
+0x90a70000, 0xa5600002, 0xa1600004, 0xa1670000,
+0x90a30002, 0x306200ff, 0x21982, 0x10600005,
+0x24050001, 0x1065000e, 0x0, 0x3e00008,
+0xa16a0001, 0x8cd80028, 0x354a0080, 0xad780018,
+0x8ccf0014, 0xad6f0014, 0x8cce0030, 0xad6e0008,
+0x8cc4002c, 0xa16a0001, 0x3e00008, 0xad64000c,
+0x8ccd001c, 0xad6d0018, 0x8cc90014, 0xad690014,
+0x8cc80024, 0xad680008, 0x8cc70020, 0xad67000c,
+0x8cc20014, 0x8c830064, 0x43c82b, 0x13200007,
+0x0, 0x8cc20014, 0x144cffe4, 0x0,
+0x354a0080, 0x3e00008, 0xa16a0001, 0x8c820064,
+0xa000399, 0x0, 0x90aa0000, 0x27bdfff8,
+0x8fa9001c, 0xa3aa0000, 0x8fae0000, 0x3c0fff80,
+0x8fa80018, 0x35e2ffff, 0x8ccd002c, 0x1c26024,
+0xafac0000, 0xa1200004, 0xe06021, 0xa7a00002,
+0x8fb80000, 0x8d270004, 0x1881821, 0xa05821,
+0xc05021, 0x6d2826, 0x3c06ff7f, 0x3c0f00ff,
+0x2cad0001, 0x35eeffff, 0x34d9ffff, 0x3c02ff00,
+0x3193024, 0xd1dc0, 0x10ec824, 0xe2c024,
+0xc37025, 0x3197825, 0xad2e0000, 0xad2f0004,
+0x8d450024, 0xafae0000, 0xad250008, 0x8d4d0020,
+0x2405ffff, 0xad2d000c, 0x95680002, 0x3107ffff,
+0xad270010, 0x91660018, 0x30c200ff, 0x219c2,
+0x50600001, 0x8d450034, 0xad250014, 0x8d670008,
+0x27bd0008, 0xad27001c, 0x8c8b00cc, 0xad2c0028,
+0xad20002c, 0xad2b0024, 0xad200018, 0x3e00008,
+0xad200020, 0x27bdffe0, 0xafb20018, 0xafb10014,
+0xafb00010, 0xafbf001c, 0x90980000, 0xc08821,
+0x3c0d00ff, 0x330f007f, 0xa0cf0000, 0x908e0001,
+0x35acffff, 0x3c0aff00, 0xa0ce0001, 0x94a6001e,
+0xa2200004, 0x8cab0014, 0x8e290004, 0xa08021,
+0x16c2824, 0x12a4024, 0x809021, 0x1052025,
+0xa6260002, 0xae240004, 0x26050020, 0x26240008,
+0xe000076, 0x24060002, 0x92470000, 0x26050028,
+0x26240014, 0x71e00, 0x31603, 0x24060004,
+0x4400003, 0x2403ffff, 0x96590002, 0x3323ffff,
+0xe000076, 0xae230010, 0x26240024, 0x8fbf001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x24050003,
+0x3021, 0xa000080, 0x27bd0020, 0x27bdffd8,
+0xafb1001c, 0xafb00018, 0xafbf0020, 0x90a80000,
+0x24020001, 0x8fb0003c, 0x3103003f, 0x808821,
+0x10620014, 0x8faa0038, 0x240b0005, 0x506b0016,
+0xafaa0010, 0xa02021, 0xc02821, 0xe0003dc,
+0x2003021, 0x922400bc, 0x30830002, 0x10600003,
+0x26060030, 0xacc00000, 0x24c60004, 0x8fbf0020,
+0x8fb1001c, 0x8fb00018, 0xc01021, 0x3e00008,
+0x27bd0028, 0x1403821, 0xe00035a, 0xafb00010,
+0xa000420, 0x0, 0xe0003a1, 0xafb00014,
+0xa000420, 0x0, 0x3c02000a, 0x3421821,
+0x3c040800, 0x24843d6c, 0x2405001a, 0x3021,
+0xa000080, 0xaf830054, 0x3c038000, 0x34620070,
+0x8c480000, 0xa05821, 0xc04821, 0x308a00ff,
+0xaf880030, 0x8f440178, 0x480fffe, 0x3c0c8000,
+0x35860070, 0x8cc50000, 0x3c030800, 0x8c630074,
+0x3c180800, 0x8f180070, 0xa82023, 0x646821,
+0xc821, 0x1a4782b, 0x3197021, 0x1cf6021,
+0x3c010800, 0xac2d0074, 0x3c010800, 0xac2c0070,
+0x8f480e14, 0xaf480144, 0xaf47014c, 0xa34a0152,
+0xa74b0158, 0x93460108, 0x30c50008, 0x54a00001,
+0x35291000, 0x934b0900, 0x24070050, 0x316a00ff,
+0x11470007, 0x0, 0x8f450e1c, 0xaf450148,
+0xaf490154, 0x3c091000, 0x3e00008, 0xaf490178,
+0x934d0108, 0x31a80008, 0x11000010, 0x0,
+0x934f0108, 0x31ee0010, 0x51c00001, 0x35290008,
+0x3c040800, 0x90843dd0, 0xa3440150, 0x8f4309a4,
+0xaf430148, 0x8f4209a0, 0xaf420144, 0xaf490154,
+0x3c091000, 0x3e00008, 0xaf490178, 0x3c190800,
+0x8f393d8c, 0x33380008, 0x5700fff1, 0x35290008,
+0xa000473, 0x0, 0x24070040, 0xaf470814,
+0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954,
+0x8f45095c, 0x8f46094c, 0xaf820064, 0xaf830050,
+0xaf84004c, 0xaf85005c, 0x3e00008, 0xaf860060,
+0x93460109, 0x30c5007f, 0x518c0, 0x52140,
+0x831021, 0x3e00008, 0x24420088, 0x3c090800,
+0x91293d91, 0x24a80002, 0x3c051100, 0x93c00,
+0xe83025, 0xc51825, 0x24820008, 0xac830000,
+0x3e00008, 0xac800004, 0x9347010b, 0x8f4a002c,
+0x974f0908, 0x3c18000e, 0x3584821, 0x31eeffff,
+0xe41c0, 0xaf48002c, 0x97430908, 0x952c001a,
+0x804021, 0x24030001, 0x318bffff, 0xac8b0000,
+0x8d2d001c, 0xa05821, 0xc06021, 0xac8d0004,
+0x8d240020, 0x30e70040, 0xad040008, 0x91220019,
+0x30440003, 0x10830048, 0x28850002, 0x14a00062,
+0x24060002, 0x10860056, 0x24190003, 0x10990066,
+0x0, 0x10e0003a, 0x0, 0x3c070800,
+0x94e73d86, 0x24e20001, 0x934f0934, 0x93470921,
+0x9525002a, 0x31ee00ff, 0xe4882, 0x30ed00ff,
+0x97870058, 0x93600, 0xd1c00, 0x3044ffff,
+0xc31025, 0x44c025, 0xa77821, 0x3c194000,
+0x3197025, 0xf4c00, 0xad090004, 0xad0e0000,
+0x934d0920, 0x3c030006, 0x25090014, 0xd3600,
+0xc32025, 0xad040008, 0x8f59092c, 0x24e50001,
+0x30a27fff, 0xad19000c, 0x8f580930, 0xa7820058,
+0x25020028, 0xad180010, 0x8f4f0938, 0xad0f0014,
+0xad2b0004, 0x8f4e0940, 0xad2e0008, 0x934d0937,
+0x3c050800, 0x90a53d90, 0x8f440948, 0x8f460940,
+0x31a700ff, 0xec1821, 0x867823, 0x3c700,
+0x5cc00, 0x3196025, 0x31e8fffc, 0x1885825,
+0xad2b000c, 0xad200010, 0x3e00008, 0xaf4a002c,
+0x3c0d0800, 0x95ad3d86, 0x3c0e0800, 0x95ce3d80,
+0xa0004c9, 0x1ae1021, 0x3c050800, 0x94a53d8a,
+0x3c060800, 0x94c63d80, 0x3c180800, 0x97183d7c,
+0x952e0024, 0xa67821, 0x1f86823, 0xe2400,
+0x25a2fff2, 0x821825, 0x24190800, 0xad03000c,
+0xad190014, 0xad000010, 0xa0004c4, 0x25080018,
+0x95260024, 0x95250028, 0x6c400, 0x57c00,
+0x370e8100, 0x35ed0800, 0xad0e000c, 0xad0d0010,
+0xa0004c4, 0x25080014, 0x1480ffa2, 0x0,
+0x95240024, 0x41400, 0x34430800, 0xad03000c,
+0xa0004c4, 0x25080010, 0x3c030800, 0x94633d8a,
+0x3c050800, 0x94a53d80, 0x3c060800, 0x94c63d7c,
+0x95390024, 0x95380028, 0x652021, 0x867823,
+0x196c00, 0x187400, 0x25e2ffee, 0x1c22025,
+0x35a38100, 0x24190800, 0xad03000c, 0xad040010,
+0xad190018, 0xad000014, 0xa0004c4, 0x2508001c,
+0x3e00008, 0x240201f4, 0x27bdffe8, 0xafb00010,
+0xafbf0014, 0xe000060, 0x808021, 0x24050040,
+0xaf450814, 0x8f830050, 0x8f84004c, 0x8f85005c,
+0x701821, 0x641023, 0x18400004, 0xaf830050,
+0xaf630054, 0x8f660054, 0xaf86004c, 0x1200000c,
+0x0, 0x8f440074, 0x93680081, 0x3409fa00,
+0x2d070007, 0x10e00005, 0x891021, 0x936c0081,
+0x240b01f4, 0x18b5004, 0x1441021, 0xaf62000c,
+0x8f4e095c, 0x1c56823, 0x19a00004, 0x8fbf0014,
+0x8f4f095c, 0xaf8f005c, 0x8fbf0014, 0x8fb00010,
+0xa000062, 0x27bd0018, 0x8f840064, 0x8f830050,
+0x8f82004c, 0xaf640044, 0xaf630050, 0x3e00008,
+0xaf620054, 0x3c038000, 0x34620070, 0x8c430000,
+0x27bdfff8, 0x308700ff, 0x30a900ff, 0x30c800ff,
+0xaf830030, 0x8f440178, 0x480fffe, 0x3c028000,
+0x34590070, 0x8f380000, 0xa3a70003, 0x3c070800,
+0x8ce70074, 0x8fac0000, 0x3c060800, 0x8cc60070,
+0x3037823, 0x3c0e7fff, 0xefc821, 0x35cdffff,
+0x5021, 0x18d2824, 0xca1821, 0x847c0,
+0x32f202b, 0xa81025, 0x64c021, 0xafa20000,
+0x3c010800, 0xac390074, 0x3c010800, 0xac380070,
+0x934f010a, 0xa3a00002, 0x3c0e80ff, 0xa3af0001,
+0x8fac0000, 0x312b007f, 0x35cdffff, 0x18d4824,
+0xb5600, 0x12a4025, 0x24073000, 0x2406ff80,
+0x3c051000, 0x27bd0008, 0xaf48014c, 0xaf470154,
+0xa7400158, 0xa3460152, 0x3e00008, 0xaf450178,
+0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f650074,
+0x3c068000, 0x309000ff, 0xa62025, 0xe000060,
+0xaf640074, 0x93630005, 0x34620008, 0xe000062,
+0xa3620005, 0x2002021, 0x8fbf0014, 0x8fb00010,
+0x24050005, 0x24060001, 0xa000570, 0x27bd0018,
+0x27bdffe0, 0x3c038000, 0xafb00010, 0xafbf0018,
+0xafb10014, 0x34620070, 0x8c470000, 0x309000ff,
+0x30a800ff, 0xaf870030, 0x8f440178, 0x480fffe,
+0x3c188000, 0x37110070, 0x8e2f0000, 0x3c0d0800,
+0x8dad0074, 0x3c0a0800, 0x8d4a0070, 0x1e77023,
+0x1ae2821, 0x5821, 0xae302b, 0x14b4821,
+0x1263821, 0x3c010800, 0xac250074, 0x8821,
+0x3c010800, 0xac270070, 0x1100000f, 0x0,
+0x8f620074, 0x2619ffff, 0x3208007f, 0x2fe02,
+0x33e5007f, 0x15000006, 0x332200ff, 0x2407ff80,
+0x2072026, 0x24a3ffff, 0x838025, 0x320200ff,
+0x408021, 0x24111008, 0xe000060, 0x0,
+0x8f490818, 0x31250004, 0x14a0fffd, 0x3218007f,
+0x1878c0, 0x187140, 0x1cf6821, 0x25ac0088,
+0xaf4c0818, 0x274a0980, 0x8d4b0020, 0xaf4b0144,
+0x8d460024, 0xaf460148, 0xa3500150, 0xe000062,
+0xa7400158, 0x2201021, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffe8,
+0x308400ff, 0xafbf0010, 0xe0005bb, 0x30a500ff,
+0x8f830050, 0x8fbf0010, 0x34450040, 0x2404ff90,
+0x3c021000, 0x27bd0018, 0xaf43014c, 0xa3440152,
+0xaf450154, 0x3e00008, 0xaf420178, 0x9343093e,
+0x30620008, 0x1040000d, 0x3c090101, 0x3528080a,
+0xac880000, 0x8f470074, 0xac870004, 0x3c060800,
+0x90c63d90, 0x30c50010, 0x50a00006, 0xac800008,
+0x8f6a0060, 0xac8a0008, 0x2484000c, 0x3e00008,
+0x801021, 0xa000622, 0x2484000c, 0x27bdffe8,
+0xafbf0014, 0xafb00010, 0x9346093f, 0xa05021,
+0x52880, 0x853823, 0x30c200ff, 0x24030006,
+0x3c090800, 0x95293d86, 0x24e8ffd8, 0x24050004,
+0x10430037, 0x24060002, 0x9750093c, 0x3c0f0204,
+0x63400, 0x320effff, 0x1cf6825, 0xac8d0000,
+0x934c093e, 0x318b0020, 0x11600008, 0x0,
+0x93430936, 0x3c020103, 0x345f0300, 0x307900ff,
+0x33fc025, 0x24050008, 0xac980004, 0x93430934,
+0x93590921, 0x5f882, 0x306200ff, 0x2c082,
+0x332f00ff, 0x186e00, 0xf7400, 0x1ae6025,
+0x1892025, 0x3c094000, 0x898025, 0xacf0ffd8,
+0x93430937, 0x8f4f0948, 0x8f580940, 0x306200ff,
+0x4ac821, 0x33f7021, 0x1f86023, 0xe6f00,
+0x1a65025, 0x3185fffc, 0x1f5880, 0x1454825,
+0x1683821, 0xad090020, 0xe000060, 0x24f00028,
+0x24040004, 0xe000062, 0xa364003f, 0x2001021,
+0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
+0xa000635, 0x24060012, 0x27bdffd0, 0x24090010,
+0xafb60028, 0xafb50024, 0xafb40020, 0xafb10014,
+0xafb00010, 0x3c010800, 0xa0293d90, 0xafbf002c,
+0xafb3001c, 0xafb20018, 0x97480908, 0x309400ff,
+0x3c02000e, 0x3107ffff, 0x731c0, 0xaf46002c,
+0x97440908, 0x9344010b, 0x30b500ff, 0x3428021,
+0x30830030, 0xb021, 0x10600125, 0x8821,
+0x240c0004, 0x3c010800, 0xa02c3d90, 0x934b093e,
+0xb5600, 0xa2e03, 0x4a00160, 0x0,
+0xaf400048, 0x934f010b, 0x31ee0020, 0x11c00006,
+0x0, 0x9358093e, 0x189e00, 0x139603,
+0x6400189, 0x0, 0x9344010b, 0x30830040,
+0x10600003, 0x8f930050, 0x8f820050, 0x2453ffff,
+0x9347093e, 0x30e60008, 0x14c00002, 0x24120003,
+0x9021, 0x9619002c, 0x93580934, 0x934f0937,
+0xa7990058, 0x330c00ff, 0x31ee00ff, 0x24e6821,
+0xd5880, 0x16c5021, 0x1514021, 0x3c010800,
+0xa4283d86, 0x92050018, 0x30a900ff, 0x1091821,
+0x3c010800, 0xa4233d88, 0x92110018, 0x16200002,
+0x0, 0xd, 0x3c010800, 0xa4233d8a,
+0x3c010800, 0xa4203d80, 0x3c010800, 0xa4203d7c,
+0x935f010b, 0x3063ffff, 0x33f00040, 0x12000002,
+0x2464000a, 0x2464000b, 0x3091ffff, 0xe00009e,
+0x2202021, 0x9358010b, 0x3c080800, 0x95083d8a,
+0x402021, 0x185982, 0x31670001, 0xe00049a,
+0x1072821, 0x934c010b, 0x8f4b002c, 0x974e0908,
+0x3c0f000e, 0x34f4021, 0x31cdffff, 0xd51c0,
+0xaf4a002c, 0x97430908, 0x9505001a, 0x403821,
+0x24040001, 0x30a9ffff, 0xac490000, 0x8d06001c,
+0x404821, 0x318a0040, 0xac460004, 0x8d020020,
+0xace20008, 0x91030019, 0x30630003, 0x106400ec,
+0x28790002, 0x17200118, 0x24100002, 0x1070010c,
+0x241f0003, 0x107f011e, 0x0, 0x114000de,
+0x0, 0x3c090800, 0x95293d86, 0x25220001,
+0x935f0934, 0x934e0921, 0x9504002a, 0x33f900ff,
+0x19c082, 0x31cf00ff, 0x978e0058, 0x184600,
+0xf6c00, 0x10d8025, 0x3045ffff, 0x2051025,
+0x8e5021, 0x3c034000, 0x433025, 0xa6400,
+0xacec0004, 0xace60000, 0x935f0920, 0x3c190006,
+0x24ec0014, 0x1fc600, 0x3197825, 0xacef0008,
+0x8f48092c, 0x25cd0001, 0x31a57fff, 0xace8000c,
+0x8f500930, 0xa7850058, 0x24e80028, 0xacf00010,
+0x8f440938, 0x1008021, 0xace40014, 0xad930004,
+0x8f530940, 0xad930008, 0x934a0937, 0x3c190800,
+0x93393d90, 0x8f430948, 0x8f460940, 0x314200ff,
+0x52f821, 0x667023, 0x1f7f00, 0x19c400,
+0x1f82825, 0x31cdfffc, 0xad2025, 0xad84000c,
+0xad800010, 0xaf4b002c, 0x934b093e, 0x31730008,
+0x1260000d, 0x3c060101, 0x34cc080a, 0xacec0028,
+0x8f530074, 0xad130004, 0x3c0b0800, 0x916b3d90,
+0x31670010, 0x50e00003, 0xad000008, 0x8f6a0060,
+0xad0a0008, 0x2510000c, 0x12c0003d, 0x0,
+0x9343093f, 0x24160006, 0x24060004, 0x306200ff,
+0x105600c9, 0x24070002, 0x9758093c, 0x3c0f0204,
+0x330dffff, 0x1af4025, 0xae080000, 0x9345093e,
+0x30a40020, 0x10800008, 0x0, 0x93530936,
+0x3c0b0103, 0x357f0300, 0x327900ff, 0x33f7025,
+0xae0e0004, 0x24060008, 0x934f0934, 0x93480921,
+0x312affff, 0x31ed00ff, 0xd1082, 0x310300ff,
+0x2b600, 0x32c00, 0x2c56025, 0x18a9825,
+0x122080, 0x3c094000, 0x2045023, 0x2695825,
+0xad4bffd8, 0x935f0937, 0x8f4f0948, 0x8f580940,
+0x33f900ff, 0x3327021, 0x6b082, 0x1d66821,
+0x74400, 0x1f82823, 0xd1f00, 0x683025,
+0x30a2fffc, 0x2547ffd8, 0xc26025, 0x168080,
+0x2074821, 0xacec0020, 0x25300028, 0xe000060,
+0x24120004, 0xa372003f, 0xe000062, 0x0,
+0x9347010b, 0x30f20040, 0x12400005, 0x3c1900ff,
+0x8e180000, 0x372effff, 0x30e3024, 0xae060000,
+0xe0000c7, 0x2202021, 0x3c100800, 0x92103d90,
+0x32110003, 0x1220000f, 0x2a02821, 0x8f890050,
+0x25330001, 0xaf930050, 0xaf730050, 0x8f6b0054,
+0x173f823, 0x1be00002, 0x2602021, 0x8f640054,
+0xaf640054, 0x8f4c0074, 0x258401f4, 0xaf64000c,
+0x2a02821, 0x2802021, 0xa7600068, 0xe0005bb,
+0x3c141000, 0x8f850050, 0x34550006, 0xaf45014c,
+0x8f8a0048, 0x8fbf002c, 0x8fb3001c, 0x25560001,
+0xaf960048, 0x8fb20018, 0xa34a0152, 0x8fb60028,
+0xaf550154, 0x8fb10014, 0xaf540178, 0x8fb50024,
+0x8fb40020, 0x8fb00010, 0x3e00008, 0x27bd0030,
+0x9358093e, 0x189e00, 0x139603, 0x6420036,
+0x24110002, 0x93440923, 0x30830002, 0x1060fedd,
+0x8f860060, 0x8f820050, 0x14c2feda, 0x0,
+0xe000060, 0x0, 0x9369003f, 0x24070016,
+0x312800ff, 0x1107000c, 0x24050008, 0x3c0c0800,
+0x918c3d90, 0x358b0001, 0x3c010800, 0xa02b3d90,
+0x936a003f, 0x314300ff, 0x10650065, 0x240d000a,
+0x106d005e, 0x2402000c, 0xe000062, 0x0,
+0xa000690, 0x0, 0x3c090800, 0x95293d86,
+0x3c0a0800, 0x954a3d80, 0xa0006f3, 0x12a1021,
+0x3c090800, 0x95293d8a, 0x3c040800, 0x94843d80,
+0x3c060800, 0x94c63d7c, 0x95030024, 0x1241021,
+0x46f823, 0x3cc00, 0x27f0fff2, 0x330c025,
+0x240f0800, 0xacf8000c, 0xacef0014, 0xace00010,
+0xa0006ee, 0x24e70018, 0x3c010800, 0xa0313d90,
+0x935f093e, 0x24160001, 0x33f90020, 0x1720fea5,
+0x24110008, 0xa000690, 0x24110004, 0x8f6e0084,
+0x8f4d0940, 0x11a0fe9e, 0xaf8e0050, 0x240f0014,
+0x3c010800, 0xa02f3d90, 0xa00068f, 0x0,
+0x950e0024, 0x950d0028, 0xe6400, 0xd2c00,
+0x35898100, 0x34a60800, 0xace9000c, 0xace60010,
+0xa0006ee, 0x24e70014, 0x1460feec, 0x0,
+0x95020024, 0x21c00, 0x34640800, 0xace4000c,
+0xa0006ee, 0x24e70010, 0xa000741, 0x24070012,
+0x3c020800, 0x94423d8a, 0x3c060800, 0x94c63d80,
+0x3c030800, 0x94633d7c, 0x95100024, 0x95190028,
+0x46f821, 0x3e3c023, 0x106c00, 0x197400,
+0x270fffee, 0x1cf2825, 0x35ac8100, 0xacec000c,
+0xace50010, 0x24070800, 0xad270018, 0x2527001c,
+0xa0006ee, 0xad200014, 0x8f7f004c, 0xaf7f0054,
+0x8f790054, 0xa000699, 0xaf790050, 0xa362003f,
+0xe000062, 0x0, 0xa000690, 0x0,
+0x24020014, 0xa000827, 0xa362003f, 0x27bdffe8,
+0x308400ff, 0xafbf0010, 0xe0005bb, 0x30a500ff,
0x9378007e, 0x9379007f, 0x936e0080, 0x9368007a,
0x332f00ff, 0x186600, 0xf6c00, 0x31cb00ff,
0x18d4825, 0xb5200, 0x8fbf0010, 0x12a3825,
@@ -4088,7 +4083,7 @@ u32 bce_TXP_b06FwText[(0x3a74/4) + 1] = {
0xafb3001c, 0x93420109, 0x308600ff, 0x30b000ff,
0x618c2, 0x32040002, 0x30710001, 0x14800005,
0x305200ff, 0x93670005, 0x30e50008, 0x10a0000d,
-0x30c80010, 0x2402021, 0xe0005cd, 0x2202821,
+0x30c80010, 0x2402021, 0xe0005a7, 0x2202821,
0x24040001, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
0x8fb10014, 0x8fb00010, 0x801021, 0x3e00008,
0x27bd0028, 0x15000032, 0x0, 0x93430109,
@@ -4101,472 +4096,488 @@ u32 bce_TXP_b06FwText[(0x3a74/4) + 1] = {
0x14a00053, 0x2402021, 0x16200006, 0x32040001,
0x8e7f0024, 0x8f590104, 0x17f9ffd6, 0x2021,
0x32040001, 0x1080000a, 0x2402021, 0x8f420940,
-0x8f930064, 0x10530006, 0x0, 0xe00067b,
+0x8f930064, 0x10530006, 0x0, 0xe00066d,
0x2202821, 0x8f430940, 0xaf630044, 0x2402021,
-0xe000628, 0x2202821, 0xa00082c, 0x24040001,
+0xe000602, 0x2202821, 0xa000860, 0x24040001,
0x3c090800, 0x8d290064, 0x25260001, 0x3c010800,
0xac260064, 0x16000012, 0x0, 0x8f6d0084,
0x3c0e00c0, 0x1ae6024, 0x15800005, 0x2402021,
-0xe0007fa, 0x2202821, 0xa00082c, 0x24040001,
-0x24050004, 0xe000596, 0x24060001, 0x2402021,
-0xe0007fa, 0x2202821, 0xa00082c, 0x24040001,
-0xe00003d, 0x24040001, 0x936b007d, 0x20b5025,
-0xe00005e, 0xa36a007d, 0xa00086f, 0x8f6d0084,
+0xe00082e, 0x2202821, 0xa000860, 0x24040001,
+0x24050004, 0xe000570, 0x24060001, 0x2402021,
+0xe00082e, 0x2202821, 0xa000860, 0x24040001,
+0xe000041, 0x24040001, 0x936b007d, 0x20b5025,
+0xe000062, 0xa36a007d, 0xa0008a3, 0x8f6d0084,
0x8f660074, 0x8f480104, 0x8e670024, 0x64e02,
0x1507ffb6, 0x3126007f, 0x936b0083, 0x26440001,
0x308a007f, 0x11460043, 0x316300ff, 0x5464ffb0,
0x8f640084, 0x26450001, 0x30b1007f, 0x30a200ff,
-0x12260004, 0x24050001, 0x409021, 0xa000842,
+0x12260004, 0x24050001, 0x409021, 0xa000876,
0x24110001, 0x240fff80, 0x24f7024, 0x1cf9026,
-0x324200ff, 0x409021, 0xa000842, 0x24110001,
-0xe00067b, 0x2202821, 0x32180030, 0x1300ffaa,
-0x32100082, 0x2402021, 0xe0005cd, 0x2202821,
-0xa00082c, 0x24040001, 0x8f6e0074, 0x3c0f8000,
+0x324200ff, 0x409021, 0xa000876, 0x24110001,
+0xe00066d, 0x2202821, 0x32180030, 0x1300ffaa,
+0x32100082, 0x2402021, 0xe0005a7, 0x2202821,
+0xa000860, 0x24040001, 0x8f6e0074, 0x3c0f8000,
0x24050003, 0x1cf9025, 0xaf720074, 0x93710083,
-0x24060001, 0xe000596, 0x322400ff, 0xe00003d,
-0x24040001, 0x936d007d, 0x20d6025, 0xe00005e,
+0x24060001, 0xe000570, 0x322400ff, 0xe000041,
+0x24040001, 0x936d007d, 0x20d6025, 0xe000062,
0xa36c007d, 0x3c0b0800, 0x8d6b0054, 0x25700001,
-0x3c010800, 0xac300054, 0xa00082c, 0x24040001,
+0x3c010800, 0xac300054, 0xa000860, 0x24040001,
0x8f680074, 0x3c098000, 0x24050004, 0x1093825,
-0xaf670074, 0x93630083, 0x24060001, 0xe000596,
-0x306400ff, 0xe00003d, 0x24040001, 0x9362007d,
-0x2029825, 0xe00005e, 0xa373007d, 0xa00082c,
+0xaf670074, 0x93630083, 0x24060001, 0xe000570,
+0x306400ff, 0xe000041, 0x24040001, 0x9362007d,
+0x2029825, 0xe000062, 0xa373007d, 0xa000860,
0x24040001, 0x324d0080, 0x39ac0080, 0x546cff6c,
-0x8f640084, 0xa000895, 0x26450001, 0x27bdffd0,
-0x3c0a0008, 0xafbf002c, 0xafb40028, 0xafb30024,
-0xafb20020, 0xafb1001c, 0xafb00018, 0x34ad821,
-0x24090040, 0xaf490814, 0xaf400810, 0x8f420944,
-0x8f430950, 0x8f460954, 0x8f47095c, 0x8f48094c,
-0x93440108, 0x9345010b, 0xaf820064, 0x308400ff,
-0x30a500ff, 0xaf830054, 0xaf860050, 0xaf87005c,
-0xe000816, 0xaf880060, 0x1440015a, 0x8fbf002c,
-0xa7600068, 0x934d0900, 0x240b0050, 0x3c140800,
-0x26943c30, 0x31ac00ff, 0x3c120800, 0x26523c40,
-0x118b0003, 0x0, 0xa021, 0x9021,
-0x934f0109, 0x8f880054, 0x24020010, 0x31f1007f,
-0x1170c0, 0x116940, 0x1ae2821, 0x24b80088,
-0xaf580818, 0x8f4a0104, 0x8f4b09a4, 0x3c0c000e,
-0x34cc821, 0x14b4823, 0x3c010800, 0xac293b08,
-0x8f440958, 0x3c010800, 0xa0223b2c, 0x97460908,
-0x881823, 0x3c010800, 0xac233b0c, 0x30c7ffff,
-0x7f9c0, 0x3c010800, 0xac283b30, 0xaf5f002c,
-0x97420908, 0x9730002c, 0x8e910000, 0x932f0018,
-0x3789821, 0xa7900058, 0xaf930048, 0x220f809,
-0x31f000ff, 0x304e0002, 0x15c0018e, 0x30530001,
-0x12600142, 0x0, 0x8f4f09a4, 0x24130001,
-0x3c010800, 0xac2f3b34, 0x93510934, 0x934e0937,
-0x322500ff, 0x31cd00ff, 0xd6080, 0x1855021,
-0x1505821, 0x3c010800, 0xa42b3b24, 0x3c010800,
-0xa42a3b22, 0x93490934, 0x312200ff, 0x2022021,
-0x24900010, 0x3c010800, 0xa4303b20, 0x24080006,
-0x8f990054, 0x3c010800, 0xac283b28, 0x8f9f005c,
-0x8f580958, 0x8021, 0x3f92823, 0x4a0013c,
-0x3192023, 0x480013a, 0xa4382b, 0x10e0013c,
-0x0, 0x3c010800, 0xac253b0c, 0x8e420000,
-0x40f809, 0x0, 0x30460002, 0x14c000dd,
-0x408821, 0x30430001, 0x54600010, 0x8e420004,
-0x3c040800, 0x8c843b10, 0x3c09c000, 0x898025,
-0xaf500e00, 0x8f4b0000, 0x316a0008, 0x1140fffd,
-0x0, 0x97450e08, 0x24100001, 0xa7850040,
-0x8f4c0e04, 0xaf8c0034, 0x8e420004, 0x40f809,
-0x0, 0x2228825, 0x322d0002, 0x15a00159,
-0x0, 0x3c090800, 0x95293b18, 0x3c060800,
-0x94c63b24, 0x3c040800, 0x94843b1a, 0x3c190800,
-0x8f393b10, 0x1265821, 0x3c180800, 0x8f183b34,
-0x3c1f0800, 0x97ff3b2e, 0x1641821, 0x8f4e0940,
-0x3292821, 0x246f0002, 0x3196821, 0xbf6021,
-0x3c010800, 0xa42b3b26, 0xaf8e0064, 0x3c010800,
-0xac2d3b34, 0x3c010800, 0xa42c3b1c, 0xe00009a,
-0x31e4ffff, 0x8f87004c, 0x402021, 0x3c010800,
-0xa0273b2d, 0x8e420008, 0x24e80001, 0xaf88004c,
-0x40f809, 0x0, 0x8f4b002c, 0x97490908,
-0x3c0a000e, 0x34a3821, 0x3124ffff, 0x419c0,
-0x8f8a0054, 0xaf43002c, 0x97430908, 0x94e6001a,
-0x404021, 0x30dfffff, 0xac5f0000, 0x8cf9001c,
-0xac590004, 0x8cf80020, 0xac580008, 0x90ef0019,
-0x31e30003, 0x107300e6, 0x0, 0x28620002,
-0x14400102, 0x240c0002, 0x106c00f4, 0x240d0003,
-0x106d00a7, 0x0, 0x3c090800, 0x95293b1c,
-0x93450934, 0x934c0921, 0x3c0f0800, 0x95ef3b22,
-0x30bf00ff, 0x94ee002a, 0x1f6882, 0x319900ff,
-0x978c0058, 0xd1600, 0x19c400, 0x3124ffff,
-0x1e43021, 0x584825, 0x1263825, 0x1cc2821,
-0x3c034000, 0xe3f825, 0x56c00, 0xad0d0004,
-0xad1f0000, 0x93590920, 0x3c180006, 0x250d0014,
-0x197e00, 0x1f87025, 0xad0e0008, 0x8f42092c,
-0x25860001, 0x8e4c000c, 0xad02000c, 0x8f440930,
-0x30c97fff, 0xa7890058, 0xad040010, 0x8f470938,
-0x25040028, 0xad070014, 0xadaa0004, 0x8f450940,
-0xada50008, 0x93430937, 0x3c1f0800, 0x93ff3b2c,
-0xada00010, 0x3c700, 0x1fcc00, 0x3197825,
-0x35eeffff, 0xadae000c, 0xaf4b002c, 0x180f809,
-0x0, 0x3c060800, 0x94c63b26, 0x3c020800,
-0x94423b1a, 0xc24821, 0x252b0002, 0xe0000c3,
-0x3164ffff, 0x3c080800, 0x8d083b08, 0x3c070800,
-0x8ce73b10, 0x1075023, 0x3c010800, 0xac2a3b08,
-0x15400006, 0x0, 0x3c080800, 0x8d083b28,
-0x350a0040, 0x3c010800, 0xac2a3b28, 0x12000084,
-0x8f830048, 0x8f470e10, 0x8f900048, 0xae070020,
-0x8f4b0e18, 0xae0b0024, 0x3c100800, 0x96103b1c,
-0xe00005c, 0x0, 0x240f0040, 0xaf4f0814,
-0x8f860054, 0x8f890050, 0xd01821, 0x697023,
-0x19c00004, 0xaf830054, 0xaf630054, 0x8f640054,
-0xaf840050, 0x1200000c, 0x0, 0x8f440074,
-0x93780081, 0x3419fa00, 0x2f020007, 0x10400005,
-0x991821, 0x937f0081, 0x240c01f4, 0x3ec6804,
-0x1a41821, 0xaf63000c, 0x8f4a095c, 0x8f88005c,
-0x1482823, 0x18a00003, 0x0, 0x8f50095c,
-0xaf90005c, 0xe00005e, 0x0, 0x8f830054,
-0x8e470010, 0x3c010800, 0xac233b30, 0xe0f809,
-0x0, 0x3c0b0800, 0x8d6b3b08, 0x1560ff10,
-0x24080006, 0x8f590024, 0x975f0908, 0x8f890064,
-0x8f8e0054, 0x3c0c001f, 0x97840058, 0x8f8f002c,
-0x8f930050, 0x33f8ffff, 0x358dff80, 0x32d3024,
-0x1811c0, 0x32320010, 0xaf420024, 0xa5e4002c,
-0xaf460024, 0xaf690044, 0xaf6e0050, 0xaf730054,
-0x5640007c, 0x8e850004, 0x322a0040, 0x55400031,
-0x8e910008, 0x8e88000c, 0x100f809, 0x0,
-0x8fbf002c, 0x8fb40028, 0x8fb30024, 0x8fb20020,
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030,
-0x3c090800, 0x95293b1c, 0x3c030800, 0x94633b26,
-0x3c040800, 0x94843b18, 0x94f90024, 0x3125ffff,
-0x94f80028, 0x65f821, 0x3e47823, 0x196400,
-0x186c00, 0x25eeffee, 0x1ae3025, 0x35828100,
-0x24030800, 0xad02000c, 0xad060010, 0xad030018,
-0xad000014, 0xa0009b3, 0x2508001c, 0x93430109,
-0x8f860038, 0x33e00, 0xe64025, 0xaf480080,
-0x8f5f09a0, 0x8f5809a4, 0xafbf0010, 0xaf5f0e14,
-0x8fb90010, 0xaf590e10, 0xaf580e1c, 0xa00092d,
-0xaf580e18, 0x220f809, 0x0, 0x8e88000c,
-0x100f809, 0x0, 0xa000a50, 0x8fbf002c,
-0xa4600020, 0xa4730022, 0xa000a05, 0xac730024,
-0x3c010800, 0xac203b0c, 0xa000953, 0x8e420000,
-0x3c010800, 0xac243b0c, 0xa000953, 0x8e420000,
-0x3c090800, 0x95293b1c, 0x3c1f0800, 0x97ff3b26,
-0x3c050800, 0x94a53b18, 0x94f80024, 0x3124ffff,
-0x3e4c821, 0x3257823, 0x186c00, 0x25eefff2,
-0x1ae6025, 0xac4c000c, 0x24020800, 0xad020014,
-0xad000010, 0xa0009b3, 0x25080018, 0x94e60024,
-0x94e30028, 0x3c090800, 0x95293b1c, 0x62400,
-0x3fc00, 0x34858100, 0x37f90800, 0xad05000c,
-0xad190010, 0xa0009b3, 0x25080014, 0x1460ff02,
-0x0, 0x94f80024, 0x3c090800, 0x95293b1c,
-0x187c00, 0x35ee0800, 0xad0e000c, 0xa0009b3,
-0x25080010, 0x93520109, 0x2821, 0xe000628,
-0x324400ff, 0x8fbf002c, 0x8fb40028, 0x8fb30024,
+0x8f640084, 0xa0008c9, 0x26450001, 0x27bdffc8,
+0x3c0a0008, 0xafbf0030, 0xafb5002c, 0xafb40028,
+0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018,
+0x34ad821, 0x24090040, 0xaf490814, 0xaf400810,
+0x8f420944, 0x8f430950, 0x8f460954, 0x8f47095c,
+0x8f48094c, 0x93440108, 0x9345010b, 0xaf820064,
+0x308400ff, 0x30a500ff, 0xaf830050, 0xaf86004c,
+0xaf87005c, 0xe00084a, 0xaf880060, 0x1440017d,
+0x8fbf0030, 0xa7600068, 0x934d0900, 0x240b0050,
+0x3c150800, 0x26b53d48, 0x31ac00ff, 0x3c120800,
+0x26523d58, 0x118b0003, 0x0, 0xa821,
+0x9021, 0x93510109, 0x8f9f0050, 0x24040010,
+0x322e007f, 0xe68c0, 0xe6140, 0x18d2821,
+0x24b40088, 0xaf540818, 0x8f490104, 0x8f4a09a4,
+0x3c0b000e, 0x34bc021, 0x12a1023, 0x3c010800,
+0xac223d6c, 0x8f430958, 0x3c010800, 0xa0243d90,
+0x97470908, 0x7f3023, 0x3c010800, 0xac263d70,
+0x30e8ffff, 0x8c9c0, 0x3c010800, 0xac3f3d94,
+0xaf59002c, 0x97420908, 0x9710002c, 0x8eb10000,
+0x930f0018, 0x3749821, 0xa7900058, 0xaf930044,
+0x220f809, 0x31f000ff, 0x304e0002, 0x15c001b2,
+0x304f0001, 0x11e0014f, 0x0, 0x9343093e,
+0x30660008, 0x14c00002, 0x24140003, 0xa021,
+0x8f5809a4, 0x24130001, 0x3c010800, 0xac383d98,
+0x934f0934, 0x93510937, 0x31ec00ff, 0x322e00ff,
+0x28e6821, 0xd2880, 0xac5021, 0x1505821,
+0x3c010800, 0xa42b3d88, 0x3c010800, 0xa42a3d86,
+0x93490934, 0x312200ff, 0x2022021, 0x24900010,
+0x3c010800, 0xa4303d84, 0x24070006, 0x8f9f0050,
+0x3c010800, 0xac273d8c, 0x8f88005c, 0x8f590958,
+0x8021, 0x11f2823, 0x4a00149, 0x33f2023,
+0x4800147, 0xa4302b, 0x10c00149, 0x0,
+0x3c010800, 0xac253d70, 0x8e420000, 0x40f809,
+0x0, 0x30430002, 0x146000f8, 0x408821,
+0x30440001, 0x54800010, 0x8e420004, 0x3c090800,
+0x8d293d74, 0x3c0ac000, 0x12a8025, 0xaf500e00,
+0x8f450000, 0x30ab0008, 0x1160fffd, 0x0,
+0x974d0e08, 0x24100001, 0xa78d003c, 0x8f4c0e04,
+0xaf8c0034, 0x8e420004, 0x40f809, 0x0,
+0x2228825, 0x322e0002, 0x15c00180, 0x0,
+0x3c090800, 0x95293d7c, 0x3c060800, 0x94c63d88,
+0x3c0a0800, 0x954a3d7e, 0x3c190800, 0x8f393d74,
+0x1266021, 0x3c180800, 0x8f183d98, 0x3c030800,
+0x94633d92, 0x18a2021, 0x8f4e0940, 0x329f821,
+0x248f0002, 0x3e32821, 0x3196821, 0x3c010800,
+0xa42c3d8a, 0xaf8e0064, 0x3c010800, 0xac2d3d98,
+0x3c010800, 0xa4253d80, 0xe00009e, 0x31e4ffff,
+0x8f870048, 0x402021, 0x3c010800, 0xa0273d91,
+0x8e420008, 0x24e80001, 0xaf880048, 0x40f809,
+0x0, 0x9344010b, 0x8f4c002c, 0x974a0908,
+0x3c0b000e, 0x34b4021, 0x3149ffff, 0x919c0,
+0x8f8b0050, 0xaf43002c, 0x97430908, 0x9506001a,
+0x403821, 0x308a0040, 0x30dfffff, 0xac5f0000,
+0x8d19001c, 0x404821, 0xac590004, 0x8d180020,
+0xac580008, 0x910f0019, 0x31e30003, 0x107300f0,
+0x0, 0x28620002, 0x14400109, 0x24050002,
+0x106500fd, 0x240d0003, 0x106d010d, 0x0,
+0x114000d9, 0x0, 0x3c0a0800, 0x954a3d86,
+0x25420001, 0x934d0934, 0x93580921, 0x950e002a,
+0x31a300ff, 0x32082, 0x331f00ff, 0x97980058,
+0x47e00, 0x1fcc00, 0x1f94025, 0x3049ffff,
+0x1091025, 0x1d83021, 0x3c054000, 0x455025,
+0x66c00, 0xaced0004, 0xacea0000, 0x93430920,
+0x3c040006, 0x24ed0014, 0x3fe00, 0x3e4c825,
+0xacf90008, 0x8f49092c, 0x270f0001, 0x31ee7fff,
+0xace9000c, 0x8f480930, 0xa78e0058, 0x24e90028,
+0xace80010, 0x8f450938, 0x1204021, 0xace50014,
+0xadab0004, 0x8f420940, 0xada20008, 0x934b0937,
+0x3c1f0800, 0x93ff3d90, 0x8f430948, 0x8f4a0940,
+0x316600ff, 0xd42021, 0x6a7823, 0x4c700,
+0x1fcc00, 0x3192825, 0x31eefffc, 0xae1025,
+0xada2000c, 0xada00010, 0xaf4c002c, 0x934c093e,
+0x318b0008, 0x5160000f, 0x8e58000c, 0x3c060101,
+0x34ca080a, 0xacea0028, 0x8f4b0074, 0xad2b0004,
+0x3c0c0800, 0x918c3d90, 0x31870010, 0x50e00003,
+0xad200008, 0x8f620060, 0xad220008, 0x2528000c,
+0x8e58000c, 0x300f809, 0x1002021, 0x3c190800,
+0x97393d8a, 0x3c1f0800, 0x97ff3d7e, 0x33f7821,
+0x25e90002, 0xe0000c7, 0x3124ffff, 0x3c0e0800,
+0x8dce3d6c, 0x3c080800, 0x8d083d74, 0x1c82823,
+0x3c010800, 0xac253d6c, 0x14a00006, 0x0,
+0x3c030800, 0x8c633d8c, 0x34640040, 0x3c010800,
+0xac243d8c, 0x12000070, 0x8f8c0044, 0x8f470e10,
+0x8f900044, 0xae070020, 0x8f4d0e18, 0xae0d0024,
+0x3c100800, 0x96103d80, 0xe000060, 0x0,
+0x24020040, 0xaf420814, 0x8f860050, 0x8f8a004c,
+0xd01821, 0x6a5823, 0x19600004, 0xaf830050,
+0xaf630054, 0x8f650054, 0xaf85004c, 0x1200000c,
+0x0, 0x8f440074, 0x93680081, 0x3409fa00,
+0x2d0e0007, 0x11c00005, 0x891821, 0x937f0081,
+0x241901f4, 0x3f97804, 0x1e41821, 0xaf63000c,
+0x8f44095c, 0x8f83005c, 0x83c023, 0x1b000003,
+0x0, 0x8f50095c, 0xaf90005c, 0xe000062,
+0x0, 0x8f8c0050, 0x8e470010, 0x3c010800,
+0xac2c3d94, 0xe0f809, 0x0, 0x3c0d0800,
+0x8dad3d6c, 0x55a0fef5, 0x24070006, 0x8f450024,
+0x97590908, 0x8f8b0064, 0x8f940050, 0x3c0f001f,
+0x97820058, 0x8f860054, 0x8f93004c, 0x3328ffff,
+0x35e9ff80, 0xa95024, 0x871c0, 0x32320100,
+0xaf4e0024, 0xa4c2002c, 0xaf4a0024, 0xaf6b0044,
+0xaf740050, 0xaf730054, 0x16400080, 0x32380010,
+0x57000086, 0x8ea40004, 0x32230040, 0x5460001b,
+0x8eb10008, 0x8eb0000c, 0x200f809, 0x0,
+0x8fbf0030, 0x8fb5002c, 0x8fb40028, 0x8fb30024,
0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0030, 0xa0f809, 0x0, 0xa000a4a,
-0x322a0040, 0x1200ff6b, 0x0, 0x8f4e0e14,
-0x8f920048, 0xae4e0020, 0x8f530e1c, 0xa000a34,
-0xae530024, 0x8f820018, 0x804021, 0x3c040100,
-0x90470085, 0x30e30020, 0x10600009, 0x0,
-0x3c070800, 0x8ce73b30, 0x8f830014, 0xe32023,
-0x4800008, 0x93890000, 0x14e30003, 0x1002021,
-0x3e00008, 0x801021, 0x3c040100, 0x3e00008,
-0x801021, 0x1120000b, 0x673823, 0x8f8c001c,
-0x24090034, 0x918b00bc, 0x316a0002, 0x51400001,
-0x24090030, 0xe9682b, 0x15a0fff1, 0x1002021,
-0xe93823, 0x2419fffc, 0xb9c024, 0xf97824,
-0xf8702b, 0x15c0ffea, 0x1e82021, 0x30c20003,
-0x21823, 0x14c00012, 0x30690003, 0x3021,
-0xa97021, 0x1c66821, 0xed602b, 0x1180ffe0,
-0x3c040100, 0x2d2f0001, 0x6482b, 0x1053821,
-0x1e93024, 0x14c0ffda, 0x24e4fffc, 0x2419fffc,
-0xb9c024, 0x3082021, 0x3e00008, 0x801021,
-0x8f8b001c, 0x24060004, 0x916a00bc, 0x31440004,
-0x1480ffec, 0xa97021, 0xa000afc, 0x3021,
-0x27bdffe8, 0xafbf0010, 0x8f460100, 0x934a0109,
-0x3c1f0800, 0x8fff0090, 0x2407ff80, 0x314f00ff,
-0x31e8007f, 0x86140, 0x3e6c821, 0x32cc021,
-0x27090120, 0x1277024, 0x3c010800, 0xa02f3b6c,
-0xaf4e080c, 0x3c0d0800, 0x8dad0090, 0x3c040080,
-0x34820003, 0x1a65821, 0x16c1821, 0x24650120,
-0x30aa0078, 0x1424025, 0xaf48081c, 0x3c1f0800,
-0x8fff0090, 0x8f880044, 0x3e6c021, 0x33190007,
-0x3074824, 0x33a7821, 0xaf490028, 0x25e909c0,
-0x952e0002, 0x3c0d0800, 0x8dad008c, 0x3c0a0800,
-0x8d4a0090, 0x31cc3fff, 0x1a61821, 0xc5980,
-0x6b2821, 0xa72024, 0xaf44002c, 0x95220002,
-0x3c1f0800, 0x8fff008c, 0x91070085, 0x30593fff,
-0x3e67821, 0x19c180, 0x1467021, 0x1f86821,
-0x31cc007f, 0x31ab007f, 0x19a2821, 0x17a5021,
-0x3c03000c, 0x3c04000e, 0xa32821, 0x1441021,
-0x30e60020, 0x27470980, 0xaf820028, 0xaf880018,
-0xaf890020, 0xaf85001c, 0x10c00006, 0xaf870024,
-0x8d020050, 0x8ca4010c, 0x443023, 0x18c00077,
-0x0, 0x910c0085, 0x240dffdf, 0x18d3824,
-0xa1070085, 0x8f8b0018, 0x8f890020, 0x8f870024,
-0x8d65004c, 0xaf850014, 0x912f000d, 0x31ee0020,
-0x11c00017, 0x0, 0x24090001, 0xa3890000,
-0xaf800008, 0x8ce40024, 0x8f850008, 0x240a0008,
-0xaf800004, 0xaf80000c, 0x3c010800, 0xa42a3b1a,
-0x3c010800, 0xa4203b2e, 0xe000ad0, 0x3021,
-0x8f850020, 0x8fbf0010, 0xaf820010, 0x90a8000d,
+0x27bd0038, 0x93470109, 0x8f880038, 0x7fe00,
+0x3e8c825, 0xaf590080, 0x8f5809a0, 0x8f5309a4,
+0xafb80010, 0xaf580e14, 0x8fb40010, 0xaf540e10,
+0xaf530e1c, 0xa000962, 0xaf530e18, 0x220f809,
+0x0, 0x8eb0000c, 0x200f809, 0x0,
+0xa000aa8, 0x8fbf0030, 0xa5800020, 0xa5930022,
+0xa000a5b, 0xad930024, 0x3c090800, 0x95293d86,
+0x3c060800, 0x94c63d80, 0xa0009f4, 0x1261021,
+0x3c010800, 0xac203d70, 0xa00098e, 0x8e420000,
+0x3c010800, 0xac243d70, 0xa00098e, 0x8e420000,
+0x3c030800, 0x94633d8a, 0x3c040800, 0x94843d80,
+0x3c1f0800, 0x97ff3d7c, 0x95180024, 0x64c821,
+0x33f7823, 0x186c00, 0x25eefff2, 0x1ae2825,
+0xac45000c, 0x24020800, 0xace20014, 0xace00010,
+0xa0009ef, 0x24e70018, 0x95060024, 0x95090028,
+0x62400, 0x91c00, 0x349f8100, 0x34790800,
+0xacff000c, 0xacf90010, 0xa0009ef, 0x24e70014,
+0x1460fefb, 0x0, 0x95180024, 0x187c00,
+0x35ee0800, 0xacee000c, 0xa0009ef, 0x24e70010,
+0x3c070800, 0x94e73d80, 0x3c040800, 0x94843d8a,
+0x3c030800, 0x94633d7c, 0x95190024, 0x95180028,
+0x87f821, 0x3e37823, 0x24070800, 0x192c00,
+0x186c00, 0x25eeffee, 0x1ae3025, 0x34a28100,
+0xad270018, 0x2527001c, 0xad22000c, 0xad260010,
+0xa0009ef, 0xad200014, 0x93520109, 0x2821,
+0xe000602, 0x324400ff, 0x8fbf0030, 0x8fb5002c,
+0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
+0x8fb00018, 0x3e00008, 0x27bd0038, 0x935f0109,
+0x33e400ff, 0xe00066d, 0x2821, 0x32380010,
+0x5300ff7e, 0x32230040, 0x8ea40004, 0x80f809,
+0x0, 0xa000aa2, 0x32230040, 0x1200ff5f,
+0x0, 0x8f540e14, 0x8f920044, 0xae540020,
+0x8f530e1c, 0xa000a8a, 0xae530024, 0x8f82001c,
+0x804021, 0x3c040100, 0x90470085, 0x30e30020,
+0x10600009, 0x0, 0x3c070800, 0x8ce73d94,
+0x8f830018, 0xe32023, 0x4800008, 0x93890004,
+0x14e30003, 0x1002021, 0x3e00008, 0x801021,
+0x3c040100, 0x3e00008, 0x801021, 0x1120000b,
+0x673823, 0x8f8c0020, 0x24090034, 0x918b00bc,
+0x316a0002, 0x51400001, 0x24090030, 0xe9682b,
+0x15a0fff1, 0x1002021, 0xe93823, 0x2419fffc,
+0xb9c024, 0xf97824, 0xf8702b, 0x15c0ffea,
+0x1e82021, 0x30c20003, 0x21823, 0x14c00012,
+0x30690003, 0x3021, 0xa97021, 0x1c66821,
+0xed602b, 0x1180ffe0, 0x3c040100, 0x2d2f0001,
+0x6482b, 0x1053821, 0x1e93024, 0x14c0ffda,
+0x24e4fffc, 0x2419fffc, 0xb9c024, 0x3082021,
+0x3e00008, 0x801021, 0x8f8b0020, 0x24060004,
+0x916a00bc, 0x31440004, 0x1480ffec, 0xa97021,
+0xa000b5e, 0x3021, 0x27bdffe8, 0xafbf0010,
+0x8f460100, 0x934a0109, 0x3c1f0800, 0x8fff0090,
+0x2407ff80, 0x314f00ff, 0x31e8007f, 0x86140,
+0x3e6c821, 0x32cc021, 0x27090120, 0x1277024,
+0x3c010800, 0xa02f3dd0, 0xaf4e080c, 0x3c0d0800,
+0x8dad0090, 0x3c040080, 0x34820003, 0x1a65821,
+0x16c1821, 0x24650120, 0x30aa0078, 0x1424025,
+0xaf48081c, 0x3c1f0800, 0x8fff0090, 0x8f880040,
+0x3e6c021, 0x33190007, 0x3074824, 0x33a7821,
+0xaf490028, 0x25e909c0, 0x952e0002, 0x3c0d0800,
+0x8dad008c, 0x3c0a0800, 0x8d4a0090, 0x31cc3fff,
+0x1a61821, 0xc5980, 0x6b2821, 0xa72024,
+0xaf44002c, 0x95220002, 0x3c1f0800, 0x8fff008c,
+0x91070085, 0x30593fff, 0x3e67821, 0x19c180,
+0x1467021, 0x1f86821, 0x31cc007f, 0x31ab007f,
+0x19a2821, 0x17a5021, 0x3c03000c, 0x3c04000e,
+0xa32821, 0x1441021, 0x30e60020, 0x27470980,
+0xaf82002c, 0xaf88001c, 0xaf890024, 0xaf850020,
+0x10c00006, 0xaf870028, 0x8d020050, 0x8ca4010c,
+0x443023, 0x18c00077, 0x0, 0x910c0085,
+0x240dffdf, 0x18d3824, 0xa1070085, 0x8f8b001c,
+0x8f890024, 0x8f870028, 0x8d65004c, 0xaf850018,
+0x912f000d, 0x31ee0020, 0x11c00017, 0x0,
+0x24090001, 0xa3890004, 0xaf80000c, 0x8ce40024,
+0x8f85000c, 0x240a0008, 0xaf800008, 0xaf800010,
+0x3c010800, 0xa42a3d7e, 0x3c010800, 0xa4203d92,
+0xe000b32, 0x3021, 0x8f850024, 0x8fbf0010,
+0xaf820014, 0x90a8000d, 0x27bd0018, 0x83942,
+0x3e00008, 0x30e20001, 0x913f0002, 0x24180001,
+0x33f900ff, 0x192182, 0x10980039, 0x24080002,
+0x1088005b, 0x8f86002c, 0x8ce50024, 0x14a0001b,
+0x8f9f0020, 0x91220000, 0x240a0005, 0x3046003f,
+0x10ca0047, 0x24040001, 0x8f860008, 0xa3840004,
+0xaf860010, 0xaf86000c, 0x8ce40024, 0x8f85000c,
+0x240a0008, 0x3c010800, 0xa42a3d7e, 0x3c010800,
+0xa4203d92, 0xe000b32, 0x0, 0x8f850024,
+0x8fbf0010, 0xaf820014, 0x90a8000d, 0x27bd0018,
+0x83942, 0x3e00008, 0x30e20001, 0x8cf80008,
+0x8cf90024, 0x8fee00c4, 0xa3800004, 0x8ce40024,
+0xaf8e000c, 0x8f85000c, 0x8f860008, 0x3197823,
+0x240a0008, 0xaf8f0010, 0x3c010800, 0xa42a3d7e,
+0x3c010800, 0xa4203d92, 0xe000b32, 0x0,
+0x8f850024, 0x8fbf0010, 0xaf820014, 0x90a8000d,
0x27bd0018, 0x83942, 0x3e00008, 0x30e20001,
-0x913f0002, 0x24180001, 0x33f900ff, 0x192182,
-0x10980039, 0x24080002, 0x1088005b, 0x8f860028,
-0x8ce50024, 0x14a0001b, 0x8f9f001c, 0x91220000,
-0x240a0005, 0x3046003f, 0x10ca0047, 0x24040001,
-0x8f860004, 0xa3840000, 0xaf86000c, 0xaf860008,
-0x8ce40024, 0x8f850008, 0x240a0008, 0x3c010800,
-0xa42a3b1a, 0x3c010800, 0xa4203b2e, 0xe000ad0,
-0x0, 0x8f850020, 0x8fbf0010, 0xaf820010,
-0x90a8000d, 0x27bd0018, 0x83942, 0x3e00008,
-0x30e20001, 0x8cf80008, 0x8cf90024, 0x8fee00c4,
-0xa3800000, 0x8ce40024, 0xaf8e0008, 0x8f850008,
-0x8f860004, 0x3197823, 0x240a0008, 0xaf8f000c,
-0x3c010800, 0xa42a3b1a, 0x3c010800, 0xa4203b2e,
-0xe000ad0, 0x0, 0x8f850020, 0x8fbf0010,
-0xaf820010, 0x90a8000d, 0x27bd0018, 0x83942,
-0x3e00008, 0x30e20001, 0x91230000, 0x3062003f,
-0x10440027, 0x8f85001c, 0x8ce40024, 0x14800021,
-0x0, 0x8d2e0018, 0x3c187fff, 0x8f85001c,
-0x370fffff, 0x1cf1824, 0xaf830004, 0x8f9f0004,
-0x8ca80084, 0x3e8c82b, 0x17200002, 0x3e02021,
-0x8ca40084, 0xa000b8b, 0xaf840004, 0x8ca3010c,
-0xa000b69, 0xaf830014, 0x8d2c0018, 0x8f860004,
-0x3c0d7fff, 0x8f89001c, 0x35a3ffff, 0x1835824,
-0x24040001, 0xaf8b000c, 0xad2000cc, 0xa3840000,
-0xa000b97, 0xaf860008, 0x8cca0014, 0xa000b8b,
-0xaf8a0004, 0x8ca300c8, 0xa000bce, 0xaf830004,
-0x8f840028, 0x8cac0064, 0x8c8d0014, 0x18d582b,
-0x11600004, 0x0, 0x8ca20064, 0xa000bce,
-0xaf820004, 0x8c820014, 0xa000bce, 0xaf820004,
-0x8f850008, 0x27bdffe0, 0xafbf0018, 0xafb10014,
-0x14a00007, 0xafb00010, 0x8f860020, 0x24020005,
-0x90c40000, 0x3083003f, 0x106200b6, 0x8f84001c,
-0x8f910004, 0xa08021, 0x8f8c0024, 0x3c050800,
-0x8ca53b0c, 0x8d8b0004, 0x31663fff, 0xc5502b,
-0x55400001, 0xc02821, 0x938d0000, 0x11a00073,
-0xb0f82b, 0x8f98001c, 0x24040034, 0x930f00bc,
-0x31ee0002, 0x51c00001, 0x24040030, 0xa4c82b,
-0x172000d1, 0x0, 0xa42823, 0xb0f82b,
-0x3c010800, 0xa4243b18, 0x17e00068, 0x2002021,
-0x3c030800, 0x8c633b08, 0x83102b, 0x54400001,
-0x801821, 0x8f880020, 0x3c010800, 0xac233b10,
-0x4821, 0x9104000d, 0x30830020, 0x50600001,
-0x8f490e18, 0x8f830010, 0x123382b, 0x10e00059,
-0x0, 0x3c040800, 0x8c843b10, 0x895821,
-0x6b502b, 0x11400056, 0x90602b, 0x693023,
-0xc02021, 0x3c010800, 0xac263b10, 0x12000003,
-0x241ffffc, 0x1090008a, 0x32270003, 0x9fc824,
-0x3c010800, 0xac393b10, 0x3c010800, 0xa4203b2e,
-0x8f840008, 0x12040007, 0x8f83001c, 0xaf910004,
-0x2002021, 0x8c7100cc, 0xaf900008, 0x26300001,
-0xac7000cc, 0x3c020800, 0x8c423b10, 0x8f8a000c,
-0x24070018, 0x822023, 0x1422823, 0xaf840008,
-0x10800002, 0xaf85000c, 0x24070010, 0x8f860018,
-0x3c010800, 0xa0273b2c, 0x24070040, 0x90cc0085,
-0x318b00c0, 0x11670040, 0x8f8d0010, 0x14a00015,
-0x2021, 0x934a0109, 0x8f420974, 0x314500ff,
-0x22602, 0x24a30001, 0x3090007f, 0x3071007f,
-0x1230007a, 0x2407ff80, 0xa0c30083, 0x3c090800,
-0x8d293b28, 0x8f880020, 0x240d0002, 0x352c0008,
-0x3c010800, 0xa02d3b6d, 0x3c010800, 0xac2c3b28,
-0x24040010, 0x910e000d, 0x31c60020, 0x10c00005,
-0x801821, 0x24080001, 0x3c010800, 0xac283b10,
-0x34830001, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0x601021, 0x3e00008, 0x27bd0020, 0x3c010800,
-0xa4203b18, 0x13e0ff9a, 0x2002021, 0xa000c1f,
-0xa02021, 0x3c040800, 0x8c843b10, 0x90602b,
-0x1180ffae, 0x0, 0x3c0f0800, 0x95ef3b18,
-0x1e47021, 0x1c6682b, 0x11a00007, 0x2c820004,
-0x3c1f6000, 0x8ff95404, 0x3338003f, 0x1700ffe5,
-0x24030042, 0x2c820004, 0x1040ffa0, 0x24030042,
-0xa000c7d, 0x8fbf0018, 0x152dffc0, 0x0,
-0x8cdf0074, 0x3c038000, 0x2405ff80, 0x3e3c825,
-0xacd90074, 0x90d80085, 0x240e0004, 0x24040010,
-0x330f003f, 0x1e54025, 0xa0c80085, 0x8f880020,
-0x3c010800, 0xa02e3b6d, 0x24030001, 0x9106000d,
-0x30c90020, 0x15200003, 0x0, 0x3c030800,
-0x8c633b10, 0x3c010800, 0xac233b08, 0xa000c74,
-0x0, 0x8f87000c, 0x8c880084, 0xe8282b,
-0x14a00002, 0xe08821, 0x8c910084, 0x24090001,
-0xa3890000, 0x8f440e18, 0x2202821, 0xe000ad0,
-0x2203021, 0x2208021, 0xa000c05, 0xaf820010,
-0x71823, 0x30660003, 0x3c010800, 0xa4263b2e,
-0x12200005, 0x8f8c001c, 0x918b00bc, 0x316a0004,
-0x15400015, 0x24cd0004, 0x3c0f0800, 0x95ef3b2e,
-0x1e47021, 0xae302b, 0x50c0ff6e, 0x8f840008,
-0x2c850005, 0x14a0ffa3, 0x24030042, 0x30980003,
-0x17000002, 0x981823, 0x2483fffc, 0x3c010800,
-0xac233b10, 0xa000c41, 0x0, 0xa75824,
-0xa000c69, 0x1671826, 0x3c010800, 0xa42d3b2e,
-0xa000cd1, 0x0, 0x3c010800, 0xac203b10,
-0xa000c7c, 0x24030042, 0x8f83000c, 0x14600007,
-0x1021, 0x8f880020, 0x24050005, 0x91060000,
-0x30c400ff, 0x10850003, 0x0, 0x3e00008,
-0x0, 0x910a0018, 0x314900ff, 0x939c2,
-0x14e0fffa, 0x8f850018, 0x3c040800, 0x94843b18,
-0x3c030800, 0x8c633b30, 0x3c190800, 0x8f393b10,
-0x3c0f0800, 0x95ef3b2e, 0x64c021, 0x8cad0054,
-0x3197021, 0x1cf6021, 0x18d5823, 0x1960001d,
-0x0, 0x910e001c, 0x8f8c0028, 0x974b0e10,
-0x31cd00ff, 0x8d850004, 0x16d3023, 0x8d880000,
-0x30ceffff, 0xe5100, 0xaac821, 0x3821,
-0x1072021, 0x32a182b, 0x83c021, 0xad990004,
-0xad980000, 0x918f000a, 0x1cf6821, 0xa18d000a,
-0x8f880028, 0x974b0e12, 0xa50b0008, 0x950a0038,
-0x25490001, 0xa5090038, 0x9107000d, 0x34e60008,
-0xa106000d, 0x3e00008, 0x0, 0x27bdffe0,
-0x93870000, 0x8f8f0020, 0x8fad0014, 0x3c0e7fff,
-0x8f890008, 0x35c8ffff, 0xafbf001c, 0xafb00018,
-0x1a81824, 0x91ea000d, 0x717c0, 0x3c1fbfff,
-0x625825, 0x2d2e0001, 0x8f900014, 0x37f9ffff,
-0x3c180800, 0x8f183b30, 0x3c0f0800, 0x95ef3b26,
-0x1796824, 0xe4780, 0x3c07efff, 0x3c05f0ff,
-0x1a81825, 0x31490020, 0x34e2ffff, 0x34acffff,
-0x3105823, 0x27a50010, 0x24060002, 0x25ea0002,
-0x621824, 0x808021, 0x15200002, 0x4021,
-0x8f480e1c, 0xa7aa0012, 0x5600037, 0x24070000,
-0x30ff00ff, 0x1fcf00, 0x8f8b0018, 0x793825,
-0xafa70014, 0x916f0085, 0x3c080800, 0x91083b2d,
-0x3c18dfff, 0x31ee00c0, 0x370affff, 0xe182b,
-0x3c1f0800, 0x97ff3b20, 0xea6824, 0xa3a80011,
-0x31740, 0x1a24825, 0x8fb90010, 0xafa90014,
-0x3c0a0800, 0x914a3b2f, 0xa7bf0016, 0x8fa80014,
-0x32cc024, 0x3c0b0100, 0x3c0f0fff, 0x30b1825,
-0x31470003, 0x35eeffff, 0x10c6824, 0x71600,
-0x6ef824, 0x3c097000, 0x1a2c825, 0x3e95825,
-0xafb90014, 0xafab0010, 0xe000072, 0xa3a00015,
-0x8f8c0020, 0x26020008, 0x9186000d, 0x30c40020,
-0x10800006, 0x8fbf001c, 0x3c050800, 0x94a53b1c,
-0x24b0ffff, 0x3c010800, 0xa4303b1c, 0x8fb00018,
-0x3e00008, 0x27bd0020, 0x8f980010, 0x118502b,
-0x5540ffc7, 0x24070001, 0xa000d54, 0x30ff00ff,
-0x93820000, 0x27bdffe0, 0xafbf0018, 0x1040000f,
-0x805021, 0x8f880020, 0x240b0005, 0x8f890004,
-0x91070000, 0x8f84001c, 0x1002821, 0x30e3003f,
-0x8f860028, 0x106b0008, 0x3821, 0xafa90010,
-0xe000439, 0xafaa0014, 0xa3800000, 0x8fbf0018,
-0x3e00008, 0x27bd0020, 0x8d190018, 0x3c0f0800,
-0x8def3b10, 0x8f98000c, 0x3c027fff, 0x8d080014,
-0x345fffff, 0x33f6824, 0x1f87021, 0x1ae6023,
-0x1883821, 0xafa90010, 0xe000439, 0xafaa0014,
-0xa000da2, 0xa3800000, 0x8f870020, 0x3c050800,
-0x94a53b2e, 0x3c020800, 0x8c423b28, 0x90e6000d,
-0x52400, 0x30c30020, 0x1060002c, 0x444025,
-0x8f850018, 0x6021, 0x240b0001, 0x90a30085,
-0x4821, 0x240a0001, 0x3c0f8000, 0x35ee0070,
-0x8dc70000, 0xaf870030, 0x8f580178, 0x700fffe,
-0x3c038000, 0x34790070, 0x8f380000, 0x3c050800,
-0x8ca50074, 0x3c0d0800, 0x8dad0070, 0x3077823,
-0xaf3821, 0x1021, 0xef302b, 0x1a22021,
-0x861821, 0x3c010800, 0xac270074, 0x3c010800,
-0xac230070, 0xaf4b0148, 0x3c190800, 0x8f393b30,
-0xa7490144, 0xa74a0146, 0xaf59014c, 0x3c0b0800,
-0x916b3b2d, 0xa34b0152, 0xaf480154, 0x3c081000,
-0xa74c0158, 0x3e00008, 0xaf480178, 0x8f4b0e1c,
-0x3c0a0800, 0x8d4a3b10, 0x97490e16, 0x974d0e14,
-0x1456021, 0x312affff, 0xa000dc5, 0x31a9ffff,
-0x8f830020, 0x9064000d, 0x30820020, 0x10400029,
-0x0, 0x4821, 0x5021, 0x4021,
-0x3c078000, 0x34eb0070, 0x8d670000, 0xaf870030,
-0x8f4c0178, 0x580fffe, 0x3c0d8000, 0x35ac0070,
-0x8d8b0000, 0x3c050800, 0x8ca50074, 0x3c040800,
-0x8c840070, 0x1673023, 0xa67821, 0x1021,
-0x1e6c82b, 0x82c021, 0x3197021, 0x3c010800,
-0xac2f0074, 0x3c010800, 0xac2e0070, 0xaf490148,
-0x3c0d0800, 0x8dad3b30, 0xa7480144, 0x24090040,
-0xa74a0146, 0x3c081000, 0x240aff91, 0xaf4d014c,
-0xa34a0152, 0xaf490154, 0xa7400158, 0x3e00008,
-0xaf480178, 0x8f490e18, 0x97460e12, 0x97450e10,
-0x30caffff, 0xa000dfb, 0x30a8ffff, 0x8f830020,
-0x27bdfff8, 0x9064000d, 0x30820020, 0x1040003a,
-0x0, 0x240b0001, 0x4821, 0x240a0001,
-0x3c088000, 0x35070070, 0x8ce30000, 0xaf830030,
-0x8f4c0178, 0x580fffe, 0x3c0e8000, 0x3c040800,
-0x90843b6c, 0x35c70070, 0x8cec0000, 0x3c050800,
-0x8ca50074, 0xa3a40003, 0x3c190800, 0x8f390070,
-0x8fad0000, 0x1833023, 0xa63821, 0x1021,
-0x3227821, 0xe6c02b, 0x1f86021, 0x1ae4025,
-0xafa80000, 0x3c010800, 0xac270074, 0x3c010800,
-0xac2c0070, 0x9346010a, 0x3c040800, 0x90843b6d,
-0xa3a00002, 0xa3a60001, 0x8fa30000, 0x3c0580ff,
-0x3099007f, 0x34a2ffff, 0x627824, 0x19c600,
-0x1f87025, 0x240d3000, 0xaf4e014c, 0x27bd0008,
-0xaf4d0154, 0xa7400158, 0xaf4b0148, 0xa7490144,
-0xa74a0146, 0x3c091000, 0x240aff80, 0xa34a0152,
-0x3e00008, 0xaf490178, 0x8f4b0e18, 0x97460e12,
-0x97450e10, 0x30caffff, 0xa000e2f, 0x30a9ffff,
-0x8f850018, 0x24020080, 0x90a40085, 0x308300c0,
-0x10620005, 0x8f86001c, 0x8f880004, 0x8f870008,
-0xacc800c8, 0xacc700c4, 0x3e00008, 0x0,
-0x3c0a0800, 0x254a37cc, 0x3c090800, 0x25293898,
-0x3c080800, 0x25082c4c, 0x3c070800, 0x24e739ac,
-0x3c060800, 0x24c6363c, 0x3c050800, 0x24a533b4,
-0x3c040800, 0x24842fdc, 0x3c030800, 0x246336d4,
-0x3c020800, 0x244234a8, 0x3c010800, 0xac2a3c38,
-0x3c010800, 0xac293c34, 0x3c010800, 0xac283c30,
-0x3c010800, 0xac273c3c, 0x3c010800, 0xac263c4c,
-0x3c010800, 0xac253c44, 0x3c010800, 0xac243c40,
-0x3c010800, 0xac233c50, 0x3c010800, 0xac223c48,
-0x3e00008, 0x0, 0x0 };
-u32 bce_TXP_b06FwData[(0x0/4) + 1] = { 0x0 };
-u32 bce_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
-u32 bce_TXP_b06FwBss[(0x14c/4) + 1] = { 0x0 };
-u32 bce_TXP_b06FwSbss[(0x68/4) + 1] = { 0x0 };
-u32 bce_TXP_b06FwSdata[(0x0/4) + 1] = { 0x0 };
+0x91230000, 0x3062003f, 0x10440027, 0x8f850020,
+0x8ce40024, 0x14800021, 0x0, 0x8d2e0018,
+0x3c187fff, 0x8f850020, 0x370fffff, 0x1cf1824,
+0xaf830008, 0x8f9f0008, 0x8ca80084, 0x3e8c82b,
+0x17200002, 0x3e02021, 0x8ca40084, 0xa000bed,
+0xaf840008, 0x8ca3010c, 0xa000bcb, 0xaf830018,
+0x8d2c0018, 0x8f860008, 0x3c0d7fff, 0x8f890020,
+0x35a3ffff, 0x1835824, 0x24040001, 0xaf8b0010,
+0xad2000cc, 0xa3840004, 0xa000bf9, 0xaf86000c,
+0x8cca0014, 0xa000bed, 0xaf8a0008, 0x8ca300c8,
+0xa000c30, 0xaf830008, 0x8f84002c, 0x8cac0064,
+0x8c8d0014, 0x18d582b, 0x11600004, 0x0,
+0x8ca20064, 0xa000c30, 0xaf820008, 0x8c820014,
+0xa000c30, 0xaf820008, 0x8f85000c, 0x27bdffe0,
+0xafbf0018, 0xafb10014, 0x14a00007, 0xafb00010,
+0x8f860024, 0x24020005, 0x90c40000, 0x3083003f,
+0x106200b6, 0x8f840020, 0x8f910008, 0xa08021,
+0x8f8c0028, 0x3c050800, 0x8ca53d70, 0x8d8b0004,
+0x31663fff, 0xc5502b, 0x55400001, 0xc02821,
+0x938d0004, 0x11a00073, 0xb0f82b, 0x8f980020,
+0x24040034, 0x930f00bc, 0x31ee0002, 0x51c00001,
+0x24040030, 0xa4c82b, 0x172000d1, 0x0,
+0xa42823, 0xb0f82b, 0x3c010800, 0xa4243d7c,
+0x17e00068, 0x2002021, 0x3c030800, 0x8c633d6c,
+0x83102b, 0x54400001, 0x801821, 0x8f880024,
+0x3c010800, 0xac233d74, 0x4821, 0x9104000d,
+0x30830020, 0x50600001, 0x8f490e18, 0x8f830014,
+0x123382b, 0x10e00059, 0x0, 0x3c040800,
+0x8c843d74, 0x895821, 0x6b502b, 0x11400056,
+0x90602b, 0x693023, 0xc02021, 0x3c010800,
+0xac263d74, 0x12000003, 0x241ffffc, 0x1090008a,
+0x32270003, 0x9fc824, 0x3c010800, 0xac393d74,
+0x3c010800, 0xa4203d92, 0x8f84000c, 0x12040007,
+0x8f830020, 0xaf910008, 0x2002021, 0x8c7100cc,
+0xaf90000c, 0x26300001, 0xac7000cc, 0x3c020800,
+0x8c423d74, 0x8f8a0010, 0x24070018, 0x822023,
+0x1422823, 0xaf84000c, 0x10800002, 0xaf850010,
+0x24070010, 0x8f86001c, 0x3c010800, 0xa0273d90,
+0x24070040, 0x90cc0085, 0x318b00c0, 0x11670040,
+0x8f8d0014, 0x14a00015, 0x2021, 0x934a0109,
+0x8f420974, 0x314500ff, 0x22602, 0x24a30001,
+0x3090007f, 0x3071007f, 0x1230007a, 0x2407ff80,
+0xa0c30083, 0x3c090800, 0x8d293d8c, 0x8f880024,
+0x240d0002, 0x352c0008, 0x3c010800, 0xa02d3dd1,
+0x3c010800, 0xac2c3d8c, 0x24040010, 0x910e000d,
+0x31c60020, 0x10c00005, 0x801821, 0x24080001,
+0x3c010800, 0xac283d74, 0x34830001, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x601021, 0x3e00008,
+0x27bd0020, 0x3c010800, 0xa4203d7c, 0x13e0ff9a,
+0x2002021, 0xa000c81, 0xa02021, 0x3c040800,
+0x8c843d74, 0x90602b, 0x1180ffae, 0x0,
+0x3c0f0800, 0x95ef3d7c, 0x1e47021, 0x1c6682b,
+0x11a00007, 0x2c820004, 0x3c1f6000, 0x8ff95404,
+0x3338003f, 0x1700ffe5, 0x24030042, 0x2c820004,
+0x1040ffa0, 0x24030042, 0xa000cdf, 0x8fbf0018,
+0x152dffc0, 0x0, 0x8cdf0074, 0x3c038000,
+0x2405ff80, 0x3e3c825, 0xacd90074, 0x90d80085,
+0x240e0004, 0x24040010, 0x330f003f, 0x1e54025,
+0xa0c80085, 0x8f880024, 0x3c010800, 0xa02e3dd1,
+0x24030001, 0x9106000d, 0x30c90020, 0x15200003,
+0x0, 0x3c030800, 0x8c633d74, 0x3c010800,
+0xac233d6c, 0xa000cd6, 0x0, 0x8f870010,
+0x8c880084, 0xe8282b, 0x14a00002, 0xe08821,
+0x8c910084, 0x24090001, 0xa3890004, 0x8f440e18,
+0x2202821, 0xe000b32, 0x2203021, 0x2208021,
+0xa000c67, 0xaf820014, 0x71823, 0x30660003,
+0x3c010800, 0xa4263d92, 0x12200005, 0x8f8c0020,
+0x918b00bc, 0x316a0004, 0x15400015, 0x24cd0004,
+0x3c0f0800, 0x95ef3d92, 0x1e47021, 0xae302b,
+0x50c0ff6e, 0x8f84000c, 0x2c850005, 0x14a0ffa3,
+0x24030042, 0x30980003, 0x17000002, 0x981823,
+0x2483fffc, 0x3c010800, 0xac233d74, 0xa000ca3,
+0x0, 0xa75824, 0xa000ccb, 0x1671826,
+0x3c010800, 0xa42d3d92, 0xa000d33, 0x0,
+0x3c010800, 0xac203d74, 0xa000cde, 0x24030042,
+0x8f830010, 0x14600007, 0x1021, 0x8f880024,
+0x24050005, 0x91060000, 0x30c400ff, 0x10850003,
+0x0, 0x3e00008, 0x0, 0x910a0018,
+0x314900ff, 0x939c2, 0x14e0fffa, 0x8f85001c,
+0x3c040800, 0x94843d7c, 0x3c030800, 0x8c633d94,
+0x3c190800, 0x8f393d74, 0x3c0f0800, 0x95ef3d92,
+0x64c021, 0x8cad0054, 0x3197021, 0x1cf6021,
+0x18d5823, 0x1960001d, 0x0, 0x910e001c,
+0x8f8c002c, 0x974b0e10, 0x31cd00ff, 0x8d850004,
+0x16d3023, 0x8d880000, 0x30ceffff, 0xe5100,
+0xaac821, 0x3821, 0x1072021, 0x32a182b,
+0x83c021, 0xad990004, 0xad980000, 0x918f000a,
+0x1cf6821, 0xa18d000a, 0x8f88002c, 0x974b0e12,
+0xa50b0008, 0x950a0038, 0x25490001, 0xa5090038,
+0x9107000d, 0x34e60008, 0xa106000d, 0x3e00008,
+0x0, 0x27bdffe0, 0x93870004, 0x8f8f0024,
+0x8fad0014, 0x3c0e7fff, 0x8f89000c, 0x35c8ffff,
+0xafbf001c, 0xafb00018, 0x1a81824, 0x91ea000d,
+0x717c0, 0x3c1fbfff, 0x625825, 0x2d2e0001,
+0x8f900018, 0x37f9ffff, 0x3c180800, 0x8f183d94,
+0x3c0f0800, 0x95ef3d8a, 0x1796824, 0xe4780,
+0x3c07efff, 0x3c05f0ff, 0x1a81825, 0x31490020,
+0x34e2ffff, 0x34acffff, 0x3105823, 0x27a50010,
+0x24060002, 0x25ea0002, 0x621824, 0x808021,
+0x15200002, 0x4021, 0x8f480e1c, 0xa7aa0012,
+0x5600037, 0x24070000, 0x30ff00ff, 0x1fcf00,
+0x8f8b001c, 0x793825, 0xafa70014, 0x916f0085,
+0x3c080800, 0x91083d91, 0x3c18dfff, 0x31ee00c0,
+0x370affff, 0xe182b, 0x3c1f0800, 0x97ff3d84,
+0xea6824, 0xa3a80011, 0x31740, 0x1a24825,
+0x8fb90010, 0xafa90014, 0x3c0a0800, 0x914a3d93,
+0xa7bf0016, 0x8fa80014, 0x32cc024, 0x3c0b0100,
+0x3c0f0fff, 0x30b1825, 0x31470003, 0x35eeffff,
+0x10c6824, 0x71600, 0x6ef824, 0x3c097000,
+0x1a2c825, 0x3e95825, 0xafb90014, 0xafab0010,
+0xe000076, 0xa3a00015, 0x8f8c0024, 0x26020008,
+0x9186000d, 0x30c40020, 0x10800006, 0x8fbf001c,
+0x3c050800, 0x94a53d80, 0x24b0ffff, 0x3c010800,
+0xa4303d80, 0x8fb00018, 0x3e00008, 0x27bd0020,
+0x8f980014, 0x118502b, 0x5540ffc7, 0x24070001,
+0xa000db6, 0x30ff00ff, 0x93820004, 0x27bdffe0,
+0xafbf0018, 0x1040000f, 0x805021, 0x8f880024,
+0x240b0005, 0x8f890008, 0x91070000, 0x8f840020,
+0x1002821, 0x30e3003f, 0x8f86002c, 0x106b0008,
+0x3821, 0xafa90010, 0xe00040e, 0xafaa0014,
+0xa3800004, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x8d190018, 0x3c0f0800, 0x8def3d74, 0x8f980010,
+0x3c027fff, 0x8d080014, 0x345fffff, 0x33f6824,
+0x1f87021, 0x1ae6023, 0x1883821, 0xafa90010,
+0xe00040e, 0xafaa0014, 0xa000e04, 0xa3800004,
+0x8f870024, 0x3c050800, 0x94a53d92, 0x3c020800,
+0x8c423d8c, 0x90e6000d, 0x52400, 0x30c30020,
+0x1060002c, 0x444025, 0x8f85001c, 0x6021,
+0x240b0001, 0x90a30085, 0x4821, 0x240a0001,
+0x3c0f8000, 0x35ee0070, 0x8dc70000, 0xaf870030,
+0x8f580178, 0x700fffe, 0x3c038000, 0x34790070,
+0x8f380000, 0x3c050800, 0x8ca50074, 0x3c0d0800,
+0x8dad0070, 0x3077823, 0xaf3821, 0x1021,
+0xef302b, 0x1a22021, 0x861821, 0x3c010800,
+0xac270074, 0x3c010800, 0xac230070, 0xaf4b0148,
+0x3c190800, 0x8f393d94, 0xa7490144, 0xa74a0146,
+0xaf59014c, 0x3c0b0800, 0x916b3d91, 0xa34b0152,
+0xaf480154, 0x3c081000, 0xa74c0158, 0x3e00008,
+0xaf480178, 0x8f4b0e1c, 0x3c0a0800, 0x8d4a3d74,
+0x97490e16, 0x974d0e14, 0x1456021, 0x312affff,
+0xa000e27, 0x31a9ffff, 0x8f830024, 0x9064000d,
+0x30820020, 0x10400029, 0x0, 0x4821,
+0x5021, 0x4021, 0x3c078000, 0x34eb0070,
+0x8d670000, 0xaf870030, 0x8f4c0178, 0x580fffe,
+0x3c0d8000, 0x35ac0070, 0x8d8b0000, 0x3c050800,
+0x8ca50074, 0x3c040800, 0x8c840070, 0x1673023,
+0xa67821, 0x1021, 0x1e6c82b, 0x82c021,
+0x3197021, 0x3c010800, 0xac2f0074, 0x3c010800,
+0xac2e0070, 0xaf490148, 0x3c0d0800, 0x8dad3d94,
+0xa7480144, 0x24090040, 0xa74a0146, 0x3c081000,
+0x240aff91, 0xaf4d014c, 0xa34a0152, 0xaf490154,
+0xa7400158, 0x3e00008, 0xaf480178, 0x8f490e18,
+0x97460e12, 0x97450e10, 0x30caffff, 0xa000e5d,
+0x30a8ffff, 0x8f830024, 0x27bdfff8, 0x9064000d,
+0x30820020, 0x1040003a, 0x0, 0x240b0001,
+0x4821, 0x240a0001, 0x3c088000, 0x35070070,
+0x8ce30000, 0xaf830030, 0x8f4c0178, 0x580fffe,
+0x3c0e8000, 0x3c040800, 0x90843dd0, 0x35c70070,
+0x8cec0000, 0x3c050800, 0x8ca50074, 0xa3a40003,
+0x3c190800, 0x8f390070, 0x8fad0000, 0x1833023,
+0xa63821, 0x1021, 0x3227821, 0xe6c02b,
+0x1f86021, 0x1ae4025, 0xafa80000, 0x3c010800,
+0xac270074, 0x3c010800, 0xac2c0070, 0x9346010a,
+0x3c040800, 0x90843dd1, 0xa3a00002, 0xa3a60001,
+0x8fa30000, 0x3c0580ff, 0x3099007f, 0x34a2ffff,
+0x627824, 0x19c600, 0x1f87025, 0x240d3000,
+0xaf4e014c, 0x27bd0008, 0xaf4d0154, 0xa7400158,
+0xaf4b0148, 0xa7490144, 0xa74a0146, 0x3c091000,
+0x240aff80, 0xa34a0152, 0x3e00008, 0xaf490178,
+0x8f4b0e18, 0x97460e12, 0x97450e10, 0x30caffff,
+0xa000e91, 0x30a9ffff, 0x8f85001c, 0x24020080,
+0x90a40085, 0x308300c0, 0x10620005, 0x8f860020,
+0x8f880008, 0x8f87000c, 0xacc800c8, 0xacc700c4,
+0x3e00008, 0x0, 0x3c0a0800, 0x254a3954,
+0x3c090800, 0x25293a20, 0x3c080800, 0x25082dd4,
+0x3c070800, 0x24e73b34, 0x3c060800, 0x24c637c4,
+0x3c050800, 0x24a5353c, 0x3c040800, 0x24843164,
+0x3c030800, 0x2463385c, 0x3c020800, 0x24423630,
+0x3c010800, 0xac2a3d50, 0x3c010800, 0xac293d4c,
+0x3c010800, 0xac283d48, 0x3c010800, 0xac273d54,
+0x3c010800, 0xac263d64, 0x3c010800, 0xac253d5c,
+0x3c010800, 0xac243d58, 0x3c010800, 0xac233d68,
+0x3c010800, 0xac223d60, 0x3e00008, 0x0,
+0x0 };
+u32 bce_TXP_b06FwData[(0x0/4) + 1] = { 0x0 };
+u32 bce_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
+u32 bce_TXP_b06FwBss[(0x14c/4) + 1] = { 0x0 };
+u32 bce_TXP_b06FwSbss[(0x68/4) + 1] = { 0x0 };
+u32 bce_TXP_b06FwSdata[(0x0/4) + 1] = { 0x0 };
-int bce_CP_b06FwReleaseMajor = 0x1;
-int bce_CP_b06FwReleaseMinor = 0x0;
-int bce_CP_b06FwReleaseFix = 0x0;
-u32 bce_CP_b06FwStartAddr = 0x08000080;
-u32 bce_CP_b06FwTextAddr = 0x08000000;
-int bce_CP_b06FwTextLen = 0x56cc;
-u32 bce_CP_b06FwDataAddr = 0x08005820;
-int bce_CP_b06FwDataLen = 0x84;
-u32 bce_CP_b06FwRodataAddr = 0x080056cc;
-int bce_CP_b06FwRodataLen = 0x134;
-u32 bce_CP_b06FwBssAddr = 0x08005998;
-int bce_CP_b06FwBssLen = 0x5d8;
-u32 bce_CP_b06FwSbssAddr = 0x080058a4;
-int bce_CP_b06FwSbssLen = 0xf1;
-u32 bce_CP_b06FwSDataAddr = 0x00000000;
-int bce_CP_b06FwSDataLen = 0x0;
-u32 bce_CP_b06FwText[(0x56cc/4) + 1] = {
-0xa000020, 0x0, 0x0,
-0xd, 0x6370342e, 0x362e3137, 0x0,
-0x4061104, 0x0, 0x0, 0x0,
+int bce_CP_b06FwReleaseMajor = 0x6;
+int bce_CP_b06FwReleaseMinor = 0x0;
+int bce_CP_b06FwReleaseFix = 0xf;
+u32 bce_CP_b06FwStartAddr = 0x080000a0;
+u32 bce_CP_b06FwTextAddr = 0x08000000;
+int bce_CP_b06FwTextLen = 0x5688;
+u32 bce_CP_b06FwDataAddr = 0x08005800;
+int bce_CP_b06FwDataLen = 0x84;
+u32 bce_CP_b06FwRodataAddr = 0x08005688;
+int bce_CP_b06FwRodataLen = 0x158;
+u32 bce_CP_b06FwBssAddr = 0x08005978;
+int bce_CP_b06FwBssLen = 0x5d8;
+u32 bce_CP_b06FwSbssAddr = 0x08005884;
+int bce_CP_b06FwSbssLen = 0xf1;
+u32 bce_CP_b06FwSDataAddr = 0x00000000;
+int bce_CP_b06FwSDataLen = 0x0;
+u32 bce_CP_b06FwText[(0x5688/4) + 1] = {
+0xa000028, 0x0, 0x0,
+0xd, 0x6370362e, 0x302e3135, 0x0,
+0x6000f04, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x20,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x1,
-0x2b, 0x0, 0x10000003, 0x0,
-0xd, 0xd, 0x3c020800, 0x244258a4,
-0x3c030800, 0x24635f70, 0xac400000, 0x43202b,
+0x2b, 0x0, 0x4, 0x30d40,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x10000003, 0x0,
+0xd, 0xd, 0x3c020800, 0x24425884,
+0x3c030800, 0x24635f50, 0xac400000, 0x43202b,
0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc,
-0x3a0f021, 0x3c100800, 0x26100080, 0x3c1c0800,
-0x279c58a4, 0xe00019c, 0x0, 0xd,
+0x3a0f021, 0x3c100800, 0x261000a0, 0x3c1c0800,
+0x279c5884, 0xe0001ac, 0x0, 0xd,
0x27bdffe8, 0x3c096018, 0xafbf0010, 0x8d2c5000,
0x240dff7f, 0x24080031, 0x18d5824, 0x356a380c,
0x24070c00, 0x3c1a8000, 0xad2a5000, 0x3c04800a,
-0xaf480008, 0x3c1b8008, 0xaf470024, 0xe000924,
-0xaf840010, 0xe0008e7, 0x0, 0xe000834,
-0x0, 0xe00125e, 0x0, 0x3c046016,
+0xaf480008, 0x3c1b8008, 0xaf470024, 0xe000915,
+0xaf840010, 0xe0008d8, 0x0, 0xe000825,
+0x0, 0xe001252, 0x0, 0x3c046016,
0x8c850000, 0x3c06ffff, 0x3c025353, 0xa61824,
-0x1062003f, 0x34867c00, 0x94c201f2, 0xa780002c,
+0x10620047, 0x34867c00, 0x94c201f2, 0xa780002c,
0x10400003, 0xa78000cc, 0x38581e1e, 0xa798002c,
0x94c201f8, 0x10400004, 0x978300cc, 0x38591e1e,
0xa79900cc, 0x978300cc, 0x2c7f0067, 0x53e00001,
0x24030066, 0x9784002c, 0x2c820401, 0x14400002,
0x602821, 0x24040400, 0x3c076000, 0x8ce90438,
-0x2403103c, 0x3128ffff, 0x11030017, 0x30b9ffff,
-0x5720000c, 0xa38000ce, 0x24020050, 0xa38200ce,
-0x939f00ce, 0x13e0000a, 0x8fbf0010, 0x27bd0018,
-0xa78000cc, 0xa780002c, 0xa7800034, 0x3e00008,
-0xa78000e6, 0x939f00ce, 0x17e0fff8, 0x8fbf0010,
-0x27bd0018, 0xa78500cc, 0xa784002c, 0xa7800034,
-0x3e00008, 0xa78000e6, 0xa38000ce, 0x8ccb003c,
+0x2403103c, 0x3128ffff, 0x1103001f, 0x30b9ffff,
+0x57200010, 0xa38000ce, 0x24020050, 0xa38200ce,
+0x939f00ce, 0x53e0000f, 0xa78500cc, 0xa78000cc,
+0x978500cc, 0x8fbf0010, 0xa780002c, 0xa7800034,
+0xa78000e6, 0x3c010800, 0xac250080, 0x3e00008,
+0x27bd0018, 0x939f00ce, 0x57e0fff5, 0xa78000cc,
+0xa78500cc, 0x978500cc, 0x8fbf0010, 0xa784002c,
+0xa7800034, 0xa78000e6, 0x3c010800, 0xac250080,
+0x3e00008, 0x27bd0018, 0xa38000ce, 0x8ccb003c,
0x316a0001, 0x1140000e, 0x0, 0x30a7ffff,
-0x10e0ffe6, 0x24020050, 0x8ccc00c8, 0x31860001,
-0x14c0ffe4, 0x939f00ce, 0xa000072, 0x24020051,
-0x8c8f0004, 0x3c0e6000, 0xa000055, 0x1ee3021,
+0x10e0ffde, 0x24020050, 0x8ccc00c8, 0x31860001,
+0x14c0ffdc, 0x939f00ce, 0xa00007a, 0x24020051,
+0x8c8f0004, 0x3c0e6000, 0xa00005d, 0x1ee3021,
0x8cef0808, 0x240d5708, 0xf7402, 0x11cd0004,
-0x30b8ffff, 0x24050066, 0xa000073, 0x24040400,
-0x1700ffd4, 0x939f00ce, 0xa000072, 0x24020050,
+0x30b8ffff, 0x24050066, 0xa00007b, 0x24040400,
+0x1700ffcc, 0x939f00ce, 0xa00007a, 0x24020050,
0x8f860010, 0x3089ffff, 0x93940, 0x8cc30010,
0x3c080050, 0xe82025, 0xaf430038, 0x8cc50014,
0x27420400, 0xaf82001c, 0xaf45003c, 0xaf440030,
@@ -4586,10 +4597,10 @@ u32 bce_CP_b06FwText[(0x56cc/4) + 1] = {
0x9487001c, 0xc71821, 0xa4830018, 0x9485001a,
0x24a20001, 0xa482001a, 0x9498001a, 0x9499001e,
0x13380003, 0x0, 0x3e00008, 0x0,
-0x3e00008, 0xa480001a, 0x8c820020, 0xa0000cc,
-0x3c0d0050, 0xa0000bd, 0x0, 0x3c030800,
+0x3e00008, 0xa480001a, 0x8c820020, 0xa0000dc,
+0x3c0d0050, 0xa0000cd, 0x0, 0x3c030800,
0x8c630020, 0x8f820018, 0x27bdffe8, 0x10620008,
-0xafbf0010, 0xe0000f4, 0xaf830018, 0x3c030800,
+0xafbf0010, 0xe000104, 0xaf830018, 0x3c030800,
0x8c630020, 0x24040001, 0x10640004, 0x8f890010,
0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8fbf0010,
0x3c076012, 0xa520000a, 0x9528000a, 0x34e50010,
@@ -4602,7 +4613,7 @@ u32 bce_CP_b06FwText[(0x56cc/4) + 1] = {
0x8fbf0034, 0x94890018, 0x948a000a, 0x12a4023,
0x3102ffff, 0x2c2382b, 0x14e00002, 0x2c02021,
0x402021, 0x2c8c0005, 0x15800002, 0x80a021,
-0x24140004, 0xe0000a3, 0x2802021, 0x8f870010,
+0x24140004, 0xe0000b3, 0x2802021, 0x8f870010,
0x2809821, 0xaf800014, 0x94ed000a, 0x2808821,
0x1280004e, 0x31b2ffff, 0x3c177000, 0x3c154000,
0x3c1e6000, 0x8f8f001c, 0x8dee0000, 0x1d71824,
@@ -4621,25 +4632,25 @@ u32 bce_CP_b06FwText[(0x56cc/4) + 1] = {
0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c,
0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
0x27bd0038, 0x107e001b, 0x0, 0x1477ffcc,
-0x24100001, 0xe0015a9, 0x0, 0x8f830014,
+0x24100001, 0xe001598, 0x0, 0x8f830014,
0x1060ffcb, 0x230f823, 0x2915823, 0x8f870010,
-0x1702021, 0xa000187, 0x3093ffff, 0x8f830014,
-0x1460ffcb, 0x3c110020, 0xaf510030, 0xa000153,
-0x0, 0xe00079b, 0x2402821, 0xa000147,
-0x408021, 0xe000341, 0x2402821, 0xa000147,
-0x408021, 0xe001471, 0x2202021, 0xa000147,
-0x408021, 0xe0000bd, 0x0, 0xa000169,
+0x1702021, 0xa000197, 0x3093ffff, 0x8f830014,
+0x1460ffcb, 0x3c110020, 0xaf510030, 0xa000163,
+0x0, 0xe00077d, 0x2402821, 0xa000157,
+0x408021, 0xe00033a, 0x2402821, 0xa000157,
+0x408021, 0xe001460, 0x2202021, 0xa000157,
+0x408021, 0xe0000cd, 0x0, 0xa000179,
0x2d33823, 0x27bdffe8, 0xafb00010, 0xafbf0014,
-0xe000037, 0x0, 0x3c028000, 0x34500070,
-0xa0001aa, 0x8e060000, 0x8f4f0000, 0x39ee0001,
+0xe00003f, 0x0, 0x3c028000, 0x34500070,
+0xa0001ba, 0x8e060000, 0x8f4f0000, 0x39ee0001,
0x31c20001, 0x10400024, 0x8f8600a8, 0x8e070000,
0x3c0c0800, 0x8d8c003c, 0x3c090800, 0x8d290038,
0xe66823, 0x18d2821, 0x5021, 0xad302b,
0x12a4021, 0x1062021, 0x3c010800, 0xac25003c,
-0xaf8700a8, 0x3c010800, 0xac240038, 0xe0000f6,
+0xaf8700a8, 0x3c010800, 0xac240038, 0xe000106,
0x0, 0x3c030800, 0x8c630070, 0x1060ffe6,
0x602021, 0x3c050800, 0x8ca50068, 0x3c060800,
-0x8cc6006c, 0xe001538, 0x0, 0x3c010800,
+0x8cc6006c, 0xe001527, 0x0, 0x3c010800,
0xac200070, 0x8f4f0000, 0x39ee0001, 0x31c20001,
0x1440ffde, 0x8f8600a8, 0x8e0a0000, 0x8f8b00a8,
0x3c050800, 0x8ca5003c, 0x3c040800, 0x8c840038,
@@ -4649,1001 +4660,994 @@ u32 bce_CP_b06FwText[(0x56cc/4) + 1] = {
0x3f92024, 0x10980012, 0xaf840000, 0xaf440020,
0x936d0000, 0x240c0020, 0x31a600ff, 0x10cc0012,
0x240e0050, 0x10ce0004, 0x3c194000, 0xaf590138,
-0xa0001a3, 0x0, 0xe0011d4, 0x0,
-0x3c194000, 0xaf590138, 0xa0001a3, 0x0,
-0xe00010f, 0x0, 0x3c194000, 0xaf590138,
-0xa0001a3, 0x0, 0x8f580100, 0x802821,
-0x330f00ff, 0x1e02021, 0xe0002ee, 0xaf8f0004,
-0x3c194000, 0xaf590138, 0xa0001a3, 0x0,
+0xa0001b3, 0x0, 0xe0011c8, 0x0,
+0x3c194000, 0xaf590138, 0xa0001b3, 0x0,
+0xe00011f, 0x0, 0x3c194000, 0xaf590138,
+0xa0001b3, 0x0, 0x8f580100, 0x802821,
+0x330f00ff, 0x1e02021, 0xe0002f1, 0xaf8f0004,
+0x3c194000, 0xaf590138, 0xa0001b3, 0x0,
0xa4102b, 0x24030001, 0x10400009, 0x3021,
0x52840, 0xa4102b, 0x4a00003, 0x31840,
0x5440fffc, 0x52840, 0x5060000a, 0x4182b,
0x85382b, 0x54e00004, 0x31842, 0xc33025,
0x852023, 0x31842, 0x1460fff9, 0x52842,
-0x4182b, 0x3e00008, 0xc31021, 0x3084ffff,
-0x30a5ffff, 0x8f4201b8, 0x440fffe, 0x3c074080,
-0x873025, 0x3c031000, 0xaf400180, 0xaf450184,
-0xaf460188, 0x3e00008, 0xaf4301b8, 0x3084ffff,
-0x8f4201b8, 0x440fffe, 0x3c074038, 0x8ca60000,
-0x872825, 0x3c031000, 0xaf460180, 0xaf450188,
-0x3e00008, 0xaf4301b8, 0x8f830038, 0x8f860030,
-0x1066000b, 0x804021, 0x3c070800, 0x24e75a18,
+0x4182b, 0x3e00008, 0xc31021, 0x8f4201b8,
+0x440fffe, 0x0, 0xaf440180, 0x3c031000,
+0x24040040, 0xaf450184, 0xa3440188, 0xa3460189,
+0xa747018a, 0x3e00008, 0xaf4301b8, 0x3084ffff,
+0x803821, 0x30a5ffff, 0x2021, 0xa00022a,
+0x24060080, 0x3087ffff, 0x8ca40000, 0x24060038,
+0xa00022a, 0x2821, 0x8f830038, 0x8f860030,
+0x1066000b, 0x804021, 0x3c070800, 0x24e759f8,
0x328c0, 0xa71021, 0x8c440000, 0x24630001,
0x10880005, 0x3063000f, 0x5466fffa, 0x328c0,
-0x3e00008, 0x1021, 0x3c070800, 0x24e75a1c,
+0x3e00008, 0x1021, 0x3c070800, 0x24e759fc,
0xa73021, 0x3e00008, 0x8cc20000, 0x3c039000,
0x34620001, 0x822025, 0xaf440020, 0x8f450020,
0x4a0fffe, 0x0, 0x3e00008, 0x0,
0x3c038000, 0x34620001, 0x822025, 0x3e00008,
0xaf440020, 0x27bdffe0, 0xafb10014, 0x3091ffff,
-0xafb00010, 0xafbf0018, 0x12200015, 0xa08021,
-0x8ca50000, 0x10a00013, 0x24040002, 0xe000c6b,
-0x24060140, 0xae000000, 0x8f4201b8, 0x440000d,
-0x2821, 0x3c064000, 0x2262025, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x3c031000, 0x27bd0020,
-0xaf450180, 0xaf440188, 0x3e00008, 0xaf4301b8,
-0x8ca50000, 0x8f4201b8, 0x440fffe, 0x3c064000,
-0x2262025, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0x3c031000, 0x27bd0020, 0xaf450180, 0xaf440188,
-0x3e00008, 0xaf4301b8, 0x3086ffff, 0x8f4201b8,
-0x440fffe, 0x3c094006, 0x8ca80000, 0xc93825,
-0xaf480180, 0x8ca40004, 0x3c031000, 0xaf440184,
-0xaf470188, 0x3e00008, 0xaf4301b8, 0x27bdffe0,
-0xafb00010, 0xafbf0018, 0xafb10014, 0x9363003e,
-0x808021, 0x802821, 0x30620040, 0x2021,
-0x1040000f, 0x8e110000, 0xe000860, 0x2202021,
-0x93670000, 0x24040050, 0x30e500ff, 0x50a40012,
-0x8e0f0000, 0x2202021, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0xa762013c, 0xa000920, 0x27bd0020,
-0xe00027d, 0x0, 0xe000860, 0x2202021,
-0x93670000, 0x24040050, 0x30e500ff, 0x14a4fff2,
-0x2202021, 0x8e0f0000, 0x3c100800, 0x8e100050,
-0x3c0d000c, 0x240bff80, 0x1f05021, 0x314e007f,
-0x1da6021, 0x18d4021, 0x14b4824, 0xaf490028,
+0xafb00010, 0xafbf0018, 0x12200013, 0xa08021,
+0x8ca20000, 0x24040002, 0x24060140, 0x1040000f,
+0x402821, 0xe000c5c, 0x0, 0x1021,
+0xae000000, 0x2203821, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x402021, 0x2821, 0x3021,
+0xa00022a, 0x27bd0020, 0x8ca20000, 0x2203821,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x402021,
+0x2821, 0x3021, 0xa00022a, 0x27bd0020,
+0xa01021, 0x3087ffff, 0x8ca50004, 0x8c440000,
+0xa00022a, 0x24060006, 0x27bdffe0, 0xafb00010,
+0xafbf0018, 0xafb10014, 0x9363003e, 0x808021,
+0x802821, 0x30620040, 0x2021, 0x1040000f,
+0x8e110000, 0xe000851, 0x2202021, 0x93670000,
+0x24040050, 0x30e500ff, 0x50a40012, 0x8e0f0000,
0x2202021, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0xa50200d6, 0x27bd0020, 0xa000920, 0xaf8800d0,
-0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
-0x93660001, 0x808021, 0xe000246, 0x30d10004,
-0x93640005, 0x1029c2, 0xa7650000, 0x34830040,
-0xa3630005, 0xe00024f, 0x2002021, 0xe000922,
-0x2002021, 0x24020001, 0xaf62000c, 0x2002821,
-0xa7620010, 0x24040002, 0xa7620012, 0x24060140,
-0xa7620014, 0xe000c6b, 0xa7620016, 0x1620000f,
-0x8fbf0018, 0x978c0034, 0x3c0b0800, 0x8d6b0078,
-0x2588ffff, 0x3109ffff, 0x256a0001, 0x12a382b,
-0x10e00006, 0xa7880034, 0x3c0f6006, 0x240e0016,
-0x35ed0010, 0xadae0050, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffe0,
-0xafb10014, 0xafbf0018, 0xafb00010, 0xa08821,
-0x1080000a, 0x3c036000, 0x24020080, 0x10820012,
-0x0, 0xd, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0020, 0x8c682bf8,
-0x500fffe, 0x0, 0xac712bc0, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x3c091000, 0x27bd0020,
-0x3e00008, 0xac692bf8, 0xe000246, 0xa02021,
-0x93650005, 0x2202021, 0xe00024f, 0x30b000ff,
-0x2403003e, 0x1603ffe7, 0x0, 0x8f440178,
-0x480fffe, 0x24070007, 0x3c061000, 0xaf510140,
-0x2202021, 0xa3470144, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0xaf460178, 0xa0002bf, 0x27bd0020,
-0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f500020,
-0x0, 0xe000922, 0xaf440020, 0xaf500020,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x3084ffff, 0x8f4201b8, 0x440fffe, 0x3c074035,
-0x873025, 0x3c031000, 0xaf450180, 0xaf400184,
-0xaf460188, 0x3e00008, 0xaf4301b8, 0x3084ffff,
-0x8f4201b8, 0x440fffe, 0x3c074036, 0x873025,
-0x3c031000, 0xaf450180, 0xaf400184, 0xaf460188,
-0x3e00008, 0xaf4301b8, 0x27bdffd0, 0xafb3001c,
-0x3093ffff, 0xafb50024, 0xafb20018, 0xafbf0028,
-0xafb40020, 0xafb10014, 0xafb00010, 0x30b5ffff,
-0x12600027, 0x9021, 0x8f90001c, 0x8e030000,
-0x3c068000, 0x24020040, 0x33e02, 0x32c02,
-0x30e4007f, 0x668824, 0x1482001d, 0x30a500ff,
-0x8f830028, 0x2c68000a, 0x51000010, 0x8f910014,
-0x35880, 0x3c0c0800, 0x258c56cc, 0x16c5021,
-0x8d490000, 0x1200008, 0x0, 0x2b21821,
-0x3065ffff, 0xe00021a, 0x24040084, 0x16200002,
-0x8f90001c, 0xaf800028, 0x8f910014, 0x260c0020,
-0x264b0001, 0x1808021, 0x3172ffff, 0x16200004,
-0xaf8c001c, 0x253402b, 0x1500ffdc, 0x0,
-0x2401021, 0x8fbf0028, 0x8fb50024, 0x8fb40020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0030, 0x240d0034, 0x14ad00f6,
-0x0, 0x920b000e, 0x240a1680, 0x3c07000c,
-0xa36b0021, 0x9203000d, 0x347f821, 0x3c066000,
-0xa3630020, 0x96110012, 0x3c087fff, 0x350cffff,
-0xa771003c, 0x96020010, 0x240b0005, 0x3054ffff,
-0xaf740084, 0x8e19001c, 0xaf4a0028, 0x8ff80000,
-0x8ccf4448, 0x3197026, 0x1ee3021, 0xaf66004c,
-0x8f69004c, 0x24cd0001, 0x3c197f00, 0xaf690050,
-0x8f640050, 0xaf640054, 0xaf660070, 0xaf6d0058,
-0x8f650058, 0x24040050, 0xaf65005c, 0xa3600023,
-0xaf6c0064, 0xa36b0037, 0x8e030014, 0xaf630048,
-0x8f710048, 0xaf710024, 0x8e020018, 0xaf62006c,
-0x9214000c, 0xa3740036, 0x936a003e, 0x355f0020,
-0xa37f003e, 0x8f780074, 0x3197824, 0x35ee4000,
-0xaf6e0074, 0x93700000, 0x320900ff, 0x11240233,
-0x2418ff80, 0x3c040800, 0x24845a98, 0xe00028a,
-0x0, 0x24060004, 0x24070001, 0x3c040800,
-0x8c845a98, 0xa366007d, 0xa3670005, 0x8f4a0178,
-0x540fffe, 0x24020002, 0xaf440140, 0xa3420144,
-0x8f90001c, 0x3c141000, 0xaf540178, 0xa000369,
-0xaf800028, 0x2cad0037, 0x51a0ff9c, 0x8f910014,
-0x5a080, 0x3c180800, 0x271856f4, 0x2987821,
-0x8dee0000, 0x1c00008, 0x0, 0x24060006,
-0x14a60011, 0x0, 0x3c1f0800, 0x8fff5a98,
-0x24040005, 0xaf5f0020, 0x8e190018, 0xaf790018,
-0x8f78004c, 0xaf78001c, 0x8f6f0050, 0x122000c2,
-0xaf6f0070, 0xa000369, 0xaf840028, 0x240a0007,
-0x10aa0084, 0x24030006, 0x3c050800, 0x24a55a98,
-0xe000254, 0x24040081, 0x8f90001c, 0x11102b,
-0xa000369, 0xaf820028, 0x240a0004, 0x14aafff6,
-0x24030050, 0x3c0e0800, 0x8dce5a98, 0xaf4e0020,
-0x8e090008, 0xaf690040, 0x8e060008, 0xaf660044,
-0x8e07000c, 0xaf670048, 0x8e040010, 0xaf64004c,
-0x8e0d0010, 0xaf6d0084, 0x8e080014, 0xaf680050,
-0x8e050018, 0xaf650054, 0x8e0c001c, 0xaf6c0058,
-0x936b0000, 0x317400ff, 0x128301f5, 0x0,
-0x8f640048, 0x8f660040, 0x863823, 0x4e00004,
-0x2404008c, 0x1620ffde, 0x24020003, 0x24040082,
-0x3c050800, 0x24a55a98, 0xe00027d, 0x0,
-0x8f90001c, 0x1021, 0xa000369, 0xaf820028,
-0x24090005, 0x14a9ffcc, 0x24052000, 0x3c0a0800,
-0x8d4a5a98, 0xaf4a0020, 0x8e1f0004, 0xaf7f005c,
-0x92190008, 0x24100008, 0xa3790021, 0x8f98001c,
-0x930f0009, 0xa36f0020, 0x8f86001c, 0x90ce000a,
-0x31c400ff, 0x10900010, 0x28830009, 0x1460006c,
-0x24020002, 0x24080020, 0x1088000b, 0x34058000,
-0x28850021, 0x14a00008, 0x24054000, 0x240d0040,
-0x108d0005, 0x3c050001, 0x24070080, 0x10870002,
-0x3c050002, 0x24054000, 0x8f6e0074, 0x3c0fff00,
-0x1cf8024, 0x2054825, 0xaf690074, 0x90c4000b,
-0xa3640081, 0x8f84001c, 0x9486000c, 0x10c0019b,
-0x0, 0x948e000c, 0x241fffbf, 0x24060004,
-0xa76e003c, 0x9090000e, 0xa370003e, 0x8f89001c,
-0x9124000f, 0xa364003f, 0x8f94001c, 0x8e8d0010,
-0x8f470074, 0x1a72823, 0xaf650060, 0x8e880014,
-0xaf680064, 0x968c0018, 0xa76c0068, 0x968b001a,
-0xa76b006a, 0x8e82001c, 0xaf62006c, 0x96830002,
-0xa763013e, 0x928a000e, 0xa36a003e, 0x9379003e,
-0x33fc024, 0x1220016a, 0xa378003e, 0x8f90001c,
-0xa000369, 0xaf860028, 0x24140022, 0x14b4ff7e,
-0x24030007, 0x3c020800, 0x8c425a98, 0x1220000c,
-0xaf420020, 0xa000369, 0xaf830028, 0x240c0033,
-0x10ac0014, 0x24080028, 0x3c050800, 0x24a55a98,
-0xe000226, 0x24040081, 0xa0003ee, 0x8f90001c,
-0x3c040800, 0x24845a98, 0xe00028a, 0x0,
-0x936b0000, 0x24110050, 0x316300ff, 0x10710154,
-0x0, 0x8f90001c, 0x1821, 0xa000369,
-0xaf830028, 0x3c050800, 0x8ca55a98, 0x24040081,
-0xaf450020, 0xa3680034, 0x3c050800, 0x24a55a98,
-0xe000226, 0x0, 0x8f90001c, 0x24020009,
-0xa000369, 0xaf820028, 0x2b28821, 0x3225ffff,
-0xe00021a, 0x24040084, 0xa000369, 0x8f90001c,
-0x1082ffa1, 0x24050400, 0x28940003, 0x12800176,
-0x240c0004, 0x240b0001, 0x548bff9b, 0x24054000,
-0xa00043d, 0x24050100, 0x3c040800, 0x24845a98,
-0x8f62004c, 0xe00028a, 0x8f630050, 0x8f90001c,
-0x2021, 0xa000369, 0xaf840028, 0x8e100004,
-0x2404008a, 0xaf500020, 0x936e0005, 0x31c90002,
-0x15200165, 0x2002821, 0x93780023, 0x2002821,
-0x330f0020, 0x15e00160, 0x2404008d, 0x9362003f,
-0x24190012, 0x305f00ff, 0x13f9015b, 0x24040081,
-0xe000246, 0x2002021, 0x93740023, 0x240a0004,
-0x2002021, 0x36830042, 0xa3630023, 0xe00024f,
-0xa36a007d, 0x8f4b0178, 0x560fffe, 0x24050002,
-0xaf500140, 0xa3450144, 0x8f90001c, 0x3c0c1000,
-0xaf4c0178, 0xa0003ef, 0x11102b, 0x8e100004,
-0x2404008a, 0xaf500020, 0x936d0005, 0x31a80002,
-0x15000019, 0x2002821, 0x9367003f, 0x24140012,
-0x30e400ff, 0x10940101, 0x0, 0x936e003f,
-0x24060004, 0x31c900ff, 0x112600fc, 0x0,
-0xe000246, 0x2002021, 0x93620023, 0x2419fffe,
-0x2002021, 0x345f0020, 0xa37f0023, 0xa374003f,
-0x93780005, 0x3197824, 0xe00024f, 0xa36f0005,
-0x2002821, 0x2021, 0xe000336, 0x0,
-0xa0003ee, 0x8f90001c, 0x8e050004, 0x3c0f0008,
-0x34f4021, 0xaf450020, 0x910e0000, 0x24060050,
-0x31c900ff, 0x1126017a, 0x24040088, 0x8f5901b8,
-0x720fffe, 0x3c0c400e, 0x8c5825, 0x3c031000,
-0xaf450180, 0xaf400184, 0xaf4b0188, 0xaf4301b8,
-0x91020000, 0x240aff80, 0x24040004, 0x4af825,
-0xa11f0000, 0xe000c6b, 0x24060030, 0xa0003ee,
-0x8f90001c, 0x8e04001c, 0xe000231, 0x0,
-0x1040014c, 0x404821, 0x8f90001c, 0x24050089,
-0x8f4d01b8, 0x5a0fffe, 0x0, 0xaf490180,
-0x8e0f001c, 0x3c144001, 0x11702b, 0xb44825,
-0x3c111000, 0xaf4f0184, 0xaf8e0028, 0xaf490188,
-0xaf5101b8, 0xa00036a, 0x8f910014, 0x96190002,
-0x3c140800, 0x26945a98, 0x33380004, 0x130000f2,
-0x3c026000, 0x8e1f001c, 0x3c010800, 0xac3f5a98,
-0xaf5f0020, 0x920c0010, 0x240b0014, 0x318400ff,
-0x148b011c, 0x0, 0x96090002, 0x312d0001,
-0x15a001b2, 0x0, 0x8e020004, 0xae820008,
-0x3c0e0800, 0x8dce5aa0, 0x11c001a8, 0x0,
-0x8f690074, 0x3c0e8000, 0x24040001, 0x12e6825,
-0xaf6d0074, 0xa3600005, 0xaf64000c, 0x3c0c0800,
-0x8d8c5aa0, 0x8f88001c, 0xa7640010, 0xc59c2,
-0xa7640012, 0xa7640014, 0xa7640016, 0xa76b0008,
-0x8d030008, 0x24040002, 0xaf63002c, 0x8d0a000c,
-0xaf6a0030, 0x91070010, 0xa3670034, 0x8f82001c,
-0x90450011, 0xa3650035, 0x8f86001c, 0x90d00012,
-0xa3700036, 0x8f9f001c, 0x93f90013, 0xa3790037,
-0x8f90001c, 0x96180014, 0xa7780038, 0x96140016,
-0xa774003a, 0x8e0f0018, 0xaf6f0024, 0x5620fe02,
-0xaf840028, 0x3c050800, 0x24a55a98, 0xe000254,
-0x2021, 0x8f90001c, 0xa0004ac, 0x2021,
-0x8e0f0004, 0x3c140800, 0x26945a98, 0x3c010800,
-0xac2f5a98, 0xaf4f0020, 0x920e0003, 0x31c90004,
-0x11200002, 0x24020012, 0x24020006, 0xa362003f,
-0x9203001b, 0x240affc0, 0x3062003f, 0x4af825,
-0xa37f003e, 0x92190003, 0x33380001, 0x170000c1,
-0x0, 0x8e020008, 0xae820008, 0x3c020800,
-0x8c425aa0, 0x104000c0, 0x0, 0x221c2,
-0xa7640008, 0x8e0d000c, 0x240b0001, 0x24140014,
-0xaf6d002c, 0x8e080010, 0xaf680030, 0x96050016,
-0xa7650038, 0x960c0014, 0xa76c003a, 0xaf6b000c,
-0xa76b0010, 0xa76b0012, 0xa76b0014, 0xa76b0016,
-0x122000eb, 0xa3740034, 0x92060003, 0x30c70002,
-0x2cf00001, 0x26020008, 0x8f90001c, 0xa000369,
-0xaf820028, 0x8e140004, 0x24030081, 0xaf540020,
-0x93680023, 0x31050010, 0x10a000ac, 0x0,
-0x8f4401b8, 0x480fffe, 0x3c06401f, 0x11382b,
-0x661025, 0x3c111000, 0xaf540180, 0xaf870028,
-0xaf400184, 0xaf420188, 0xaf5101b8, 0xa00036a,
-0x8f910014, 0x8e060004, 0x3c190008, 0x3592021,
-0xaf460020, 0x8e070008, 0x90980000, 0x240f0050,
-0x331400ff, 0x128f00a7, 0x24050088, 0x8f4401b8,
-0x480fffe, 0x3c0d4009, 0x11602b, 0xad1025,
-0x3c111000, 0xaf460180, 0xaf8c0028, 0xaf470184,
-0xaf420188, 0xaf5101b8, 0xa00036a, 0x8f910014,
-0x3c050800, 0x24a55a98, 0xe00027d, 0x24040082,
-0x8f90001c, 0x3021, 0xa000369, 0xaf860028,
-0x3c040800, 0x8c845a98, 0xe0014f6, 0x0,
-0x8f90001c, 0xa000486, 0x1821, 0xe000336,
-0x24040081, 0xa0003ee, 0x8f90001c, 0x3c050800,
-0x24a55a98, 0xe00027d, 0x2404008b, 0x8f90001c,
-0x11302b, 0xa000369, 0xaf860028, 0x3c190800,
-0x8f395a98, 0x3c1f0800, 0x8fff0050, 0x24ccfffe,
-0x33f7821, 0x1f87024, 0xaf4e0028, 0x3c040800,
-0x8c845a98, 0x3c090800, 0x8d290050, 0x896821,
-0x31a5007f, 0xba4021, 0x1078021, 0xae0600d8,
-0xaf9000d0, 0xae0000dc, 0xa0003b8, 0xae0c0108,
-0xaf600084, 0x3c080800, 0x8d085a98, 0x3c0d0800,
-0x8dad0050, 0x2405ff80, 0x3c02000c, 0x10d5821,
-0x1656024, 0xaf4c0028, 0x8e0a0014, 0x3174007f,
-0x29a1821, 0x627821, 0xadea00d8, 0x8e1f0014,
-0xaf8f00d0, 0xadff00dc, 0x8e190010, 0x2738fffe,
-0xa00040b, 0xadf80108, 0x548cfe27, 0x24054000,
-0xa00043d, 0x24051000, 0xe00032b, 0x0,
-0xa0003ee, 0x8f90001c, 0x8c46442c, 0x3c056c62,
-0x34b07970, 0x3c010800, 0xac205a98, 0x14d00008,
-0x24040002, 0x97880034, 0x978a002c, 0x2802821,
-0x10a382b, 0x10e00011, 0x24040092, 0x24040002,
-0xe000c89, 0x24050140, 0x3c010800, 0xac225a98,
-0xaf420020, 0x3c030800, 0x8c635a98, 0x10600005,
-0x24040083, 0xe000854, 0x0, 0x10400009,
-0x24040083, 0x3c050800, 0x24a55a98, 0xe000254,
-0x0, 0x8f90001c, 0x11202b, 0xa000369,
-0xaf840028, 0xe000858, 0x0, 0xa000530,
-0x8f90001c, 0x8e040008, 0xe000231, 0x0,
-0xa000586, 0xae820008, 0x3c050800, 0x24a55a98,
-0xe000226, 0x24040087, 0x8f90001c, 0xa0005a2,
-0x11102b, 0xe00085c, 0x0, 0x3c050800,
-0x24a55a98, 0xa00063a, 0x2404008b, 0xe000246,
-0x2802021, 0x93700023, 0x2802021, 0x360d0010,
-0xe00024f, 0xa36d0023, 0x8f90001c, 0xa0005ab,
-0x1821, 0x24040004, 0xe000c89, 0x24050030,
-0x1440002a, 0x404821, 0x8f90001c, 0xa000517,
-0x24050083, 0x9205000c, 0x30bf0001, 0x13e00003,
-0x0, 0x9602000e, 0xa482002c, 0x920a000c,
-0x31480002, 0x1100ff51, 0x2821, 0x960b0012,
-0x8e030014, 0xa48b001a, 0xa0005c2, 0xac83001c,
-0x8f830038, 0x8f870030, 0x1067fe84, 0x2021,
-0x3c090800, 0x25295a1c, 0x320c0, 0x893021,
-0x8cd40000, 0x1285005e, 0x24780001, 0x3303000f,
-0x5467fffa, 0x320c0, 0xa0004fe, 0x2021,
-0x3c050800, 0x24a55a98, 0xe00027d, 0x24040082,
-0x8f90001c, 0xa0005a2, 0x1021, 0x3c0b0008,
-0x34b2021, 0x24030050, 0x240a0001, 0xaf420020,
-0xa0830000, 0xa08a0001, 0x8f88001c, 0x91070004,
-0xa0870018, 0x8f82001c, 0x90450005, 0xa0850019,
-0x8f86001c, 0x90df0006, 0xa09f001a, 0x8f99001c,
-0x93380007, 0xa098001b, 0x8f94001c, 0x928f0008,
-0xa08f001c, 0x8f90001c, 0x920e0009, 0xa08e001d,
-0x8f8d001c, 0x91ac000a, 0xa08c001e, 0x8f8b001c,
-0x3c0c0800, 0x258c5a1c, 0x9163000b, 0x3c0b0800,
-0x256b5a18, 0xa083001f, 0x8f8a001c, 0x9148000c,
-0xa0880020, 0x8f87001c, 0x90e5000d, 0xa0850021,
-0x8f82001c, 0x24054646, 0x9046000e, 0xa0860022,
-0x8f9f001c, 0x93f9000f, 0xa0990023, 0x8f98001c,
-0x93140010, 0xa0940024, 0x8f8f001c, 0x91f00011,
-0xa0900025, 0x8f90001c, 0x8f8e0030, 0x8f990038,
-0x960d0014, 0xe18c0, 0x25c80001, 0xa48d0028,
-0x960a0016, 0x6c3021, 0x6bf821, 0xa48a002a,
-0x96070018, 0x3108000f, 0xa487002c, 0xa485002e,
-0x8e02001c, 0xacc90000, 0xaf880030, 0x11190003,
-0xafe20000, 0xa000517, 0x2821, 0x250c0001,
-0x3184000f, 0x2821, 0xa000517, 0xaf840038,
-0x3c070800, 0x24e75a18, 0x878021, 0x2021,
-0xacc00000, 0xa0004fe, 0xae000000, 0x3c050800,
-0x24a55a98, 0xa00063a, 0x24040087, 0x8e040004,
-0xe000231, 0x0, 0xa00053b, 0xae820008,
-0x3084ffff, 0x30c600ff, 0x8f4201b8, 0x440fffe,
-0x64400, 0x1043025, 0x3c072000, 0xc72025,
-0x3c031000, 0xaf400180, 0xaf450184, 0xaf440188,
-0x3e00008, 0xaf4301b8, 0x27bdffe8, 0xafb00010,
-0xafbf0014, 0x3c076000, 0x24060002, 0x10800006,
-0xa08021, 0x10102b, 0x8fbf0014, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0x3c09600e, 0xad200034,
-0x8ce5201c, 0x8f82001c, 0x2408fffc, 0xa81824,
-0xace3201c, 0xe0006ef, 0x8c45000c, 0x10102b,
+0xa762013c, 0xa000911, 0x27bd0020, 0xe000287,
+0x0, 0xe000851, 0x2202021, 0x93670000,
+0x24040050, 0x30e500ff, 0x14a4fff2, 0x2202021,
+0x8e0f0000, 0x3c100800, 0x8e100050, 0x3c0d000c,
+0x240bff80, 0x1f05021, 0x314e007f, 0x1da6021,
+0x18d4021, 0x14b4824, 0xaf490028, 0x2202021,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0xa50200d6,
+0x27bd0020, 0xa000911, 0xaf8800d0, 0x27bdffe0,
+0xafbf0018, 0xafb10014, 0xafb00010, 0x93660001,
+0x808021, 0xe000256, 0x30d10004, 0x93640005,
+0x1029c2, 0xa7650000, 0x34830040, 0xa3630005,
+0xe00025f, 0x2002021, 0xe000913, 0x2002021,
+0x24020001, 0xaf62000c, 0x2002821, 0xa7620010,
+0x24040002, 0xa7620012, 0x24060140, 0xa7620014,
+0xe000c5c, 0xa7620016, 0x1620000f, 0x8fbf0018,
+0x978c0034, 0x3c0b0800, 0x8d6b0078, 0x2588ffff,
+0x3109ffff, 0x256a0001, 0x12a382b, 0x10e00006,
+0xa7880034, 0x3c0f6006, 0x240e0016, 0x35ed0010,
+0xadae0050, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafb10014,
+0xafbf0018, 0xafb00010, 0xa08821, 0x1080000a,
+0x3c036000, 0x24020080, 0x10820012, 0x0,
+0xd, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0020, 0x8c682bf8, 0x500fffe,
+0x0, 0xac712bc0, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x3c091000, 0x27bd0020, 0x3e00008,
+0xac692bf8, 0xe000256, 0xa02021, 0x93650005,
+0x2202021, 0xe00025f, 0x30b000ff, 0x2403003e,
+0x1603ffe7, 0x0, 0x8f440178, 0x480fffe,
+0x24070007, 0x3c061000, 0xaf510140, 0x2202021,
+0xa3470144, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0xaf460178, 0xa0002c2, 0x27bd0020, 0x27bdffe8,
+0xafbf0014, 0xafb00010, 0x8f500020, 0x0,
+0xe000913, 0xaf440020, 0xaf500020, 0x8fbf0014,
+0x8fb00010, 0x3e00008, 0x27bd0018, 0x3084ffff,
+0x803821, 0x24060035, 0xa02021, 0xa00022a,
+0x2821, 0x3084ffff, 0x803821, 0x24060036,
+0xa02021, 0xa00022a, 0x2821, 0x27bdffd0,
+0xafb3001c, 0x3093ffff, 0xafb50024, 0xafb20018,
+0xafbf0028, 0xafb40020, 0xafb10014, 0xafb00010,
+0x30b5ffff, 0x12600027, 0x9021, 0x8f90001c,
+0x8e030000, 0x3c068000, 0x24020040, 0x33e02,
+0x32c02, 0x30e4007f, 0x668824, 0x1482001d,
+0x30a500ff, 0x8f830028, 0x2c68000a, 0x51000010,
+0x8f910014, 0x35880, 0x3c0c0800, 0x258c5688,
+0x16c5021, 0x8d490000, 0x1200008, 0x0,
+0x2b21021, 0x3045ffff, 0xe000236, 0x24040084,
+0x16200002, 0x8f90001c, 0xaf800028, 0x8f910014,
+0x260c0020, 0x26430001, 0x1808021, 0x3072ffff,
+0x16200004, 0xaf8c001c, 0x253502b, 0x1540ffdc,
+0x0, 0x2401021, 0x8fbf0028, 0x8fb50024,
+0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0030, 0x240e0034,
+0x14ae00f9, 0x0, 0x9203000e, 0x241f1680,
+0x3c07000c, 0xa3630021, 0x9202000d, 0x347c821,
+0x3c066000, 0xa3620020, 0x96110012, 0x3c0a7fff,
+0x354cffff, 0xa771003c, 0x960b0010, 0x24030005,
+0x3168ffff, 0xaf680084, 0x8e05001c, 0xaf5f0028,
+0x8f380000, 0x8cc44448, 0x3057826, 0x8f3021,
+0xaf66004c, 0x8f69004c, 0x24ce0001, 0x3c057f00,
+0xaf690050, 0x8f740050, 0xaf740054, 0xaf660070,
+0xaf6e0058, 0x8f6d0058, 0x24140050, 0xaf6d005c,
+0xa3600023, 0xaf6c0064, 0xa3630037, 0x8e020014,
+0xaf620048, 0x8f710048, 0xaf710024, 0x8e0b0018,
+0xaf6b006c, 0x9208000c, 0xa3680036, 0x937f003e,
+0x37f90020, 0xa379003e, 0x8f780074, 0x3058024,
+0x360f4000, 0xaf6f0074, 0x93640000, 0x308900ff,
+0x51340245, 0x2404ff80, 0x3c040800, 0x24845a78,
+0xe00028d, 0x0, 0x3c100800, 0x8e105a78,
+0xe000256, 0x2002021, 0x24060004, 0x24070001,
+0xa366007d, 0x2002021, 0xe00025f, 0xa3670005,
+0x8f5f0178, 0x7e0fffe, 0x240b0002, 0xaf500140,
+0xa34b0144, 0x8f90001c, 0x3c081000, 0xaf480178,
+0xa000362, 0xaf800028, 0x2cad0037, 0x51a0ff98,
+0x8f910014, 0x5a080, 0x3c180800, 0x271856b0,
+0x2987821, 0x8dee0000, 0x1c00008, 0x0,
+0x24180006, 0x14b80011, 0x0, 0x3c080800,
+0x8d085a78, 0x24040005, 0xaf480020, 0x8e1f0018,
+0xaf7f0018, 0x8f79004c, 0xaf79001c, 0x8f650050,
+0x122000c0, 0xaf650070, 0xa000362, 0xaf840028,
+0x24060007, 0x10a60083, 0x24030006, 0x3c050800,
+0x24a55a78, 0xe000264, 0x24040081, 0x8f90001c,
+0x11102b, 0xa000362, 0xaf820028, 0x24070004,
+0x14a7fff6, 0x24050050, 0x3c180800, 0x8f185a78,
+0xaf580020, 0x8e0f0008, 0xaf6f0040, 0x8e090008,
+0xaf690044, 0x8e14000c, 0xaf740048, 0x8e0e0010,
+0xaf6e004c, 0x8e0d0010, 0xaf6d0084, 0x8e0a0014,
+0xaf6a0050, 0x8e0c0018, 0xaf6c0054, 0x8e04001c,
+0xaf640058, 0x93630000, 0x306b00ff, 0x116501d8,
+0x0, 0x8f740048, 0x8f690040, 0x2897023,
+0x5c00004, 0x2404008c, 0x1620ffde, 0x24020003,
+0x24040082, 0x3c050800, 0x24a55a78, 0xe000287,
+0x0, 0x8f90001c, 0x1021, 0xa000362,
+0xaf820028, 0x240f0005, 0x14afffcc, 0x24052000,
+0x3c070800, 0x8ce75a78, 0xaf470020, 0x8e060004,
+0xaf66005c, 0x92080008, 0x24100008, 0xa3680021,
+0x8f9f001c, 0x93f90009, 0xa3790020, 0x8f86001c,
+0x90d8000a, 0x330400ff, 0x10900011, 0x0,
+0x28850009, 0x14a00069, 0x24020002, 0x240a0020,
+0x108a000b, 0x34058000, 0x288d0021, 0x15a00008,
+0x24054000, 0x240e0040, 0x108e0005, 0x3c050001,
+0x24140080, 0x10940002, 0x3c050002, 0x24054000,
+0x8f780074, 0x3c19ff00, 0x3198024, 0x2057825,
+0xaf6f0074, 0x90c4000b, 0xa3640081, 0x8f84001c,
+0x9489000c, 0x11200192, 0x0, 0x9490000c,
+0x2406ffbf, 0x24050004, 0xa770003c, 0x908f000e,
+0xa36f003e, 0x8f84001c, 0x9089000f, 0xa369003f,
+0x8f8b001c, 0x8d6e0010, 0x8f540074, 0x1d46823,
+0xaf6d0060, 0x8d6a0014, 0xaf6a0064, 0x956c0018,
+0xa76c0068, 0x9563001a, 0xa763006a, 0x8d62001c,
+0xaf62006c, 0x9167000e, 0xa367003e, 0x9368003e,
+0x106f824, 0x1220014b, 0xa37f003e, 0x8f90001c,
+0xa000362, 0xaf850028, 0x24070022, 0x14a7ff7f,
+0x24030007, 0x3c0b0800, 0x8d6b5a78, 0x1220000c,
+0xaf4b0020, 0xa000362, 0xaf830028, 0x240c0033,
+0x10ac0014, 0x240a0028, 0x3c050800, 0x24a55a78,
+0xe00023c, 0x24040081, 0xa0003eb, 0x8f90001c,
+0x3c040800, 0x24845a78, 0xe00028d, 0x0,
+0x93630000, 0x24110050, 0x306200ff, 0x10510135,
+0x0, 0x8f90001c, 0x1821, 0xa000362,
+0xaf830028, 0x3c0d0800, 0x8dad5a78, 0x24040081,
+0xaf4d0020, 0x3c050800, 0x24a55a78, 0xe00023c,
+0xa36a0034, 0x8f90001c, 0x24020009, 0xa000362,
+0xaf820028, 0x2b28821, 0x3225ffff, 0xe000236,
+0x24040084, 0xa000362, 0x8f90001c, 0x1082ffa4,
+0x24050400, 0x288b0003, 0x11600170, 0x240c0004,
+0x24030001, 0x5483ff9e, 0x24054000, 0xa00043b,
+0x24050100, 0x3c040800, 0x24845a78, 0x8f62004c,
+0xe00028d, 0x8f630050, 0x8f90001c, 0x2021,
+0xa000362, 0xaf840028, 0x8e100004, 0x2404008a,
+0xaf500020, 0x93790005, 0x33380002, 0x1700015f,
+0x2002821, 0x93680023, 0x2002821, 0x311f0020,
+0x17e0015a, 0x2404008d, 0x9367003f, 0x24060012,
+0x30e200ff, 0x10460155, 0x24040081, 0xe000256,
+0x2002021, 0x93630023, 0x24050004, 0x2002021,
+0x346b0042, 0xa36b0023, 0xe00025f, 0xa365007d,
+0x8f440178, 0x480fffe, 0x240a0002, 0xaf500140,
+0xa34a0144, 0x8f90001c, 0x3c0c1000, 0xaf4c0178,
+0xa0003ec, 0x11102b, 0x8e100004, 0x2404008a,
+0xaf500020, 0x936e0005, 0x31cd0002, 0x15a00016,
+0x2002821, 0x936f003f, 0x24140004, 0x2002821,
+0x31e900ff, 0x11340010, 0x24040081, 0xe000256,
+0x2002021, 0x93620023, 0x24080012, 0x241ffffe,
+0x34460020, 0xa3660023, 0xa368003f, 0x93790005,
+0x2002021, 0x33fc024, 0xe00025f, 0xa3780005,
+0x2002821, 0x2021, 0xe000334, 0x0,
+0xa0003eb, 0x8f90001c, 0x8e100004, 0x3c030008,
+0x343a021, 0xaf500020, 0x928b0000, 0x24050050,
+0x316400ff, 0x10850161, 0x24070088, 0x2002021,
+0x2821, 0xe00022a, 0x2406000e, 0x928d0000,
+0x240eff80, 0x2002821, 0x1ae8025, 0xa2900000,
+0x24040004, 0xe000c5c, 0x24060030, 0xa0003eb,
+0x8f90001c, 0x8e080004, 0x3c140800, 0x26945a78,
+0x3c010800, 0xac285a78, 0xaf480020, 0x921f0003,
+0x33f90004, 0x13200002, 0x24020012, 0x24020006,
+0xa362003f, 0x920b001b, 0x2404ffc0, 0x3165003f,
+0xa43825, 0xa367003e, 0x92060003, 0x30c20001,
+0x14400132, 0x0, 0x8e020008, 0xae820008,
+0x3c020800, 0x8c425a80, 0x10400131, 0x249c2,
+0xa7690008, 0x8e14000c, 0x240c0001, 0x24030014,
+0xaf74002c, 0x8e0e0010, 0xaf6e0030, 0x960d0016,
+0xa76d0038, 0x960a0014, 0xa76a003a, 0xaf6c000c,
+0xa76c0010, 0xa76c0012, 0xa76c0014, 0xa76c0016,
+0x12200136, 0xa3630034, 0x920f0003, 0x31f00002,
+0x2e110001, 0x8f90001c, 0x26220008, 0xa000362,
+0xaf820028, 0x8e040004, 0x3c0e0008, 0x34e3021,
+0xaf440020, 0x8e050008, 0x90cd0000, 0x240c0050,
+0x31aa00ff, 0x114c0086, 0x24070088, 0x24060009,
+0xe00022a, 0x0, 0xa0003eb, 0x8f90001c,
+0x8e04001c, 0xe000241, 0x0, 0x104000f4,
+0x405021, 0x8f89001c, 0x24070089, 0x1402021,
+0x8d25001c, 0x24060001, 0xe00022a, 0x0,
+0xa0003eb, 0x8f90001c, 0x960d0002, 0x3c140800,
+0x26945a78, 0x31aa0004, 0x514000b8, 0x3c106000,
+0x8e0e001c, 0x3c010800, 0xac2e5a78, 0xaf4e0020,
+0x92070010, 0x24080014, 0x30e200ff, 0x144800d6,
+0x0, 0x960b0002, 0x31630001, 0x14600165,
+0x0, 0x8e020004, 0xae820008, 0x3c140800,
+0x8e945a80, 0x1280015b, 0x0, 0x8f740074,
+0x3c038000, 0x24040001, 0x2835825, 0xaf6b0074,
+0xa3600005, 0xaf64000c, 0x3c070800, 0x8ce75a80,
+0x8f86001c, 0xa7640010, 0x711c2, 0xa7640012,
+0xa7640014, 0xa7640016, 0xa7620008, 0x8cc80008,
+0x24040002, 0xaf68002c, 0x8cc5000c, 0xaf650030,
+0x90df0010, 0xa37f0034, 0x8f99001c, 0x93300011,
+0xa3700035, 0x8f98001c, 0x930f0012, 0xa36f0036,
+0x8f89001c, 0x912e0013, 0xa36e0037, 0x8f90001c,
+0x960d0014, 0xa76d0038, 0x960a0016, 0xa76a003a,
+0x8e0c0018, 0xaf6c0024, 0x5620fdcc, 0xaf840028,
+0x3c050800, 0x24a55a78, 0xe000264, 0x2021,
+0x8f90001c, 0xa0004a7, 0x2021, 0x8e100004,
+0x24070081, 0xaf500020, 0x93690023, 0x31340010,
+0x12800017, 0x0, 0x2002021, 0x2821,
+0x2406001f, 0xe00022a, 0x0, 0xa0003eb,
+0x8f90001c, 0x3c050800, 0x24a55a78, 0xe000287,
+0x24040082, 0x8f90001c, 0x2821, 0xa000362,
+0xaf850028, 0x3c040800, 0x8c845a78, 0xe0014e5,
+0x0, 0x8f90001c, 0xa000482, 0x1821,
+0xe000256, 0x2002021, 0x93780023, 0x2002021,
+0x370f0010, 0xe00025f, 0xa36f0023, 0x3821,
+0x2002021, 0x2821, 0xa0005a8, 0x2406001f,
+0x920f000c, 0x31e90001, 0x11200003, 0x0,
+0x9618000e, 0xa4d8002c, 0x921f000c, 0x33f90002,
+0x13200005, 0x3821, 0x8e020014, 0x96080012,
+0xacc2001c, 0xa4c8001a, 0xa000543, 0x24060009,
+0x3c050800, 0x24a55a78, 0xe000287, 0x2404008b,
+0x8f90001c, 0x11282b, 0xa000362, 0xaf850028,
+0xaf600084, 0x3c0a0800, 0x8d4a5a78, 0x3c0d0800,
+0x8dad0050, 0x240cff80, 0x3c02000c, 0x14d1821,
+0x6c2024, 0xaf440028, 0x8e070014, 0x306b007f,
+0x17a2821, 0xa2c821, 0xaf2700d8, 0x8e060014,
+0xaf9900d0, 0xaf2600dc, 0x8e080010, 0x251ffffe,
+0xa000408, 0xaf3f0108, 0x3c050800, 0x8ca55a78,
+0x3c190800, 0x8f390050, 0x24ccfffe, 0xb9c021,
+0x3047824, 0xaf4f0028, 0x3c140800, 0x8e945a78,
+0x3c090800, 0x8d290050, 0x2897021, 0x31cd007f,
+0x1ba5021, 0x1478021, 0xae0600d8, 0xaf9000d0,
+0xae0000dc, 0xa0003b1, 0xae0c0108, 0x548cfe30,
+0x24054000, 0xa00043b, 0x24051000, 0xe00032e,
+0x0, 0xa0003eb, 0x8f90001c, 0x8e0f442c,
+0x3c186c62, 0x37097970, 0x3c010800, 0xac205a78,
+0x15e90008, 0x24050140, 0x979f0034, 0x9786002c,
+0x2802821, 0x3e6c82b, 0x13200011, 0x24040092,
+0x24050140, 0xe000c7a, 0x24040002, 0x3c010800,
+0xac225a78, 0xaf420020, 0x3c050800, 0x8ca55a78,
+0x10a00005, 0x24040083, 0xe000845, 0x0,
+0x10400009, 0x24040083, 0x3c050800, 0x24a55a78,
+0xe000264, 0x0, 0x8f90001c, 0x11202b,
+0xa000362, 0xaf840028, 0xe000849, 0x0,
+0xa00055f, 0x8f90001c, 0xe00084d, 0x0,
+0x3c050800, 0x24a55a78, 0xa00062f, 0x2404008b,
+0x24040004, 0xe000c7a, 0x24050030, 0x1440002a,
+0x405021, 0x8f89001c, 0x24070083, 0x1402021,
+0x8d25001c, 0xa000551, 0x24060001, 0x8e040008,
+0xe000241, 0x0, 0xa00051b, 0xae820008,
+0x3c050800, 0x24a55a78, 0xe00023c, 0x24040087,
+0x8f90001c, 0xa000536, 0x11102b, 0x8f830038,
+0x8f860030, 0x1066fe9d, 0x3821, 0x3c070800,
+0x24e759fc, 0x320c0, 0x872821, 0x8cac0000,
+0x11900061, 0x246a0001, 0x3143000f, 0x5466fffa,
+0x320c0, 0xa0004f6, 0x3821, 0x3c050800,
+0x24a55a78, 0xe000287, 0x24040082, 0x8f90001c,
+0xa000536, 0x1021, 0x3c0b0008, 0x34b2021,
+0x24030050, 0x24070001, 0xaf420020, 0xa0830000,
+0xa0870001, 0x8f82001c, 0x90480004, 0xa0880018,
+0x8f85001c, 0x90a60005, 0xa0860019, 0x8f9f001c,
+0x93f90006, 0xa099001a, 0x8f90001c, 0x92180007,
+0xa098001b, 0x8f94001c, 0x928f0008, 0xa08f001c,
+0x8f89001c, 0x912e0009, 0xa08e001d, 0x8f8d001c,
+0x91ac000a, 0xa08c001e, 0x8f8b001c, 0x3c0c0800,
+0x258c59fc, 0x9163000b, 0x3c0b0800, 0x256b59f8,
+0xa083001f, 0x8f87001c, 0x90e8000c, 0xa0880020,
+0x8f82001c, 0x9045000d, 0x24024646, 0xa0850021,
+0x8f86001c, 0x90df000e, 0xa09f0022, 0x8f99001c,
+0x9330000f, 0xa0900023, 0x8f98001c, 0x93140010,
+0xa0940024, 0x8f8f001c, 0x91e90011, 0xa0890025,
+0x8f89001c, 0x8f8e0030, 0x8f900038, 0x952d0014,
+0xe18c0, 0x25c80001, 0xa48d0028, 0x95270016,
+0x6c3021, 0x6bc821, 0xa487002a, 0x95250018,
+0x3108000f, 0xa485002c, 0xa482002e, 0x8d3f001c,
+0xacca0000, 0xaf880030, 0x11100006, 0xaf3f0000,
+0x3821, 0x8d25001c, 0x1402021, 0xa000551,
+0x24060001, 0x250c0001, 0x3184000f, 0x3821,
+0xa0006b8, 0xaf840038, 0x3c070800, 0x24e759f8,
+0x873021, 0x3821, 0xaca00000, 0xa0004f6,
+0xacc00000, 0x3c050800, 0x24a55a78, 0xa00062f,
+0x24040087, 0x8e040004, 0xe000241, 0x0,
+0xa00056a, 0xae820008, 0x3084ffff, 0x30c600ff,
+0x8f4201b8, 0x440fffe, 0x64400, 0x1043025,
+0x3c072000, 0xc72025, 0x3c031000, 0xaf400180,
+0xaf450184, 0xaf440188, 0x3e00008, 0xaf4301b8,
+0x27bdffe8, 0xafb00010, 0xafbf0014, 0x3c076000,
+0x24060002, 0x10800006, 0xa08021, 0x10102b,
0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x3c02600e, 0x34470100, 0x24090018, 0x274a0400,
-0x0, 0x0, 0x0, 0x3c060050,
-0x34c30200, 0xaf440038, 0xaf45003c, 0xaf430030,
-0x1401821, 0x8f4b0000, 0x31680020, 0x1100fffd,
-0x2406007f, 0x2408ffff, 0x8c6c0000, 0x24c6ffff,
-0x24630004, 0xacec0000, 0x14c8fffb, 0x24e70004,
-0x0, 0x0, 0x0, 0x3c0f0020,
-0xaf4f0030, 0x0, 0x24ad0200, 0x1a5702b,
-0x2529ffff, 0x8e2021, 0x1520ffe1, 0x1a02821,
-0x3e00008, 0x0, 0x27bdffe0, 0xafb10014,
-0xafbf0018, 0xafb00010, 0x3c05600e, 0x8ca20034,
-0x808821, 0x14400006, 0x3c046000, 0x8c87201c,
-0x2408fffc, 0xe83024, 0x34c30001, 0xac83201c,
-0x8f8b001c, 0x24090001, 0xaca90034, 0x95690002,
-0x8d650014, 0x8d70000c, 0x2d240081, 0x8d670004,
-0x8d660008, 0x10800007, 0x8d6a0010, 0x2d2c0004,
-0x1580000e, 0x30ce0007, 0x312d0003, 0x11a0000b,
-0x0, 0x2404008b, 0x2002821, 0xe0006ef,
-0x24060003, 0x11102b, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0020, 0x15c0fff6,
-0x2404008b, 0x3c030020, 0xaf430030, 0x0,
-0x24020001, 0xaf820014, 0x0, 0x0,
-0x0, 0x3c1f0150, 0x13fc825, 0x25380003,
-0x3c0f600e, 0xaf470038, 0x181882, 0xaf46003c,
-0x35e8003c, 0xaf590030, 0x27470400, 0x8f440000,
-0x30860020, 0x10c0fffd, 0x0, 0x10600008,
-0x2466ffff, 0x2403ffff, 0x8ceb0000, 0x24c6ffff,
-0x24e70004, 0xad0b0000, 0x14c3fffb, 0x25080004,
-0x3c08600e, 0xad090038, 0x0, 0x0,
-0x0, 0x3c070020, 0xaf470030, 0x0,
-0xe000717, 0x1402021, 0x2002821, 0x2021,
-0xe0006ef, 0x24060003, 0x11102b, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
-0x27bdffd8, 0xafb20018, 0x3092ffff, 0xafb10014,
-0xafbf0020, 0xafb3001c, 0xafb00010, 0x1240002c,
-0x8821, 0xa0007af, 0x24130001, 0x50b3003c,
-0x8ce5000c, 0xd, 0x262d0001, 0x31b1ffff,
-0x24ec0020, 0x232382b, 0x10e00021, 0xaf8c001c,
-0x8f820014, 0x1440001e, 0x8f87001c, 0x3c067000,
-0x3c032000, 0x8ce40000, 0x862824, 0x14a30018,
-0x8f85003c, 0x44402, 0x3c098000, 0x898024,
-0x14a0ffea, 0x310600ff, 0x24040002, 0x10c4001f,
-0x28ca0003, 0x11400016, 0x240b0003, 0x14d3ffe7,
-0x262d0001, 0x2002821, 0xe0006fd, 0x24040001,
-0x8f87001c, 0xaf82003c, 0x262d0001, 0x31b1ffff,
-0x24ec0020, 0x232382b, 0x14e0ffe1, 0xaf8c001c,
-0x2201021, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028,
-0x14cbffd2, 0x262d0001, 0xe00073d, 0x2002021,
-0x8f87001c, 0xa0007c9, 0xaf82003c, 0x2002821,
-0xe0006fd, 0x2021, 0xa0007c8, 0x8f87001c,
-0xe0006ef, 0x24040084, 0x1600ffc3, 0x8f87001c,
-0xa0007a9, 0xaf80003c, 0x3082ffff, 0x14400003,
-0x1821, 0x42402, 0x24030010, 0x308500ff,
-0x14a00005, 0x3087000f, 0x24660008, 0x42202,
-0x30c300ff, 0x3087000f, 0x14e00005, 0x30890003,
-0x24680004, 0x42102, 0x310300ff, 0x30890003,
-0x15200005, 0x388b0001, 0x246a0002, 0x42082,
-0x314300ff, 0x388b0001, 0x31640001, 0x10800002,
-0x246c0001, 0x318300ff, 0x3e00008, 0x601021,
-0x308bffff, 0xb3942, 0x30e600ff, 0x3c090800,
-0x25295998, 0x64080, 0x1096021, 0x8d870000,
-0x3164001f, 0x240a0001, 0x8a1804, 0x30a500ff,
-0xe32025, 0x14a00002, 0x31027, 0xe22024,
-0x240f0001, 0xcf7004, 0x1096821, 0xe2827,
-0x14800005, 0xada40000, 0x8f86000c, 0xa61024,
-0x3e00008, 0xaf82000c, 0x8f88000c, 0x1c81025,
-0x3e00008, 0xaf82000c, 0x3c06001f, 0x3c036000,
-0x3084ffff, 0x34c5ff80, 0x24020020, 0xac602008,
-0xac60200c, 0xac602010, 0xac652014, 0xac642018,
-0xac622000, 0x0, 0x0, 0x3e00008,
-0x0, 0x27bdffe8, 0x2402ffff, 0xafbf0010,
-0xaf82000c, 0x2021, 0x3c060800, 0x24c65998,
-0x2405ffff, 0x24890001, 0x44080, 0x3124ffff,
-0x1061821, 0x2c870020, 0x14e0fffa, 0xac650000,
-0xe000825, 0x2021, 0x24020001, 0x3c046000,
-0x24050020, 0xac822018, 0xac852000, 0x0,
-0x0, 0x0, 0x244a0001, 0x3142ffff,
-0x2c460400, 0x14c0fff7, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x8f830008, 0x2c620400, 0x3e00008,
-0x38420001, 0x8f830008, 0x24620001, 0x3e00008,
-0xaf820008, 0x8f830008, 0x2462ffff, 0x3e00008,
-0xaf820008, 0x27bdffe0, 0xafb10014, 0xafbf0018,
-0xafb00010, 0x8f6b0030, 0x3c066000, 0x808821,
-0xaccb2008, 0x8f6a002c, 0x3c028000, 0x24030008,
-0xacca200c, 0x9769003a, 0x97680038, 0x92c00,
-0x3107ffff, 0xa72025, 0xacc42010, 0xacc22014,
-0xacc32000, 0x0, 0x0, 0x0,
-0x3c036000, 0x8c6d2000, 0x31ac0008, 0x1580fff9,
-0x0, 0x8c6e2014, 0x5c00020, 0x0,
-0xe0007e9, 0x8f84000c, 0x24080, 0x3c090800,
-0x25295998, 0x1093821, 0x8ce40000, 0xe0007e9,
-0x28140, 0x2022021, 0x3090ffff, 0x2002021,
-0xe000807, 0x2821, 0x3c0c8000, 0x22c5825,
-0x3210ffff, 0x3c116000, 0x240a0020, 0xae2b2014,
-0xae302018, 0xae2a2000, 0x0, 0x0,
-0x0, 0x2001021, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0020, 0x8c662014,
-0x3c02001f, 0x3443ff80, 0x3c1fffe8, 0xc3c024,
-0x37f90800, 0x3198021, 0x1079c2, 0x3c0c8000,
-0x22c5825, 0x31f0ffff, 0x3c116000, 0x240a0020,
+0x3c09600e, 0xad200034, 0x8ce5201c, 0x8f82001c,
+0x2408fffc, 0xa81824, 0xace3201c, 0xe0006d1,
+0x8c45000c, 0x10102b, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x3c02600e, 0x34470100,
+0x24090018, 0x274a0400, 0x0, 0x0,
+0x0, 0x3c060050, 0x34c30200, 0xaf440038,
+0xaf45003c, 0xaf430030, 0x1401821, 0x8f4b0000,
+0x31680020, 0x1100fffd, 0x2406007f, 0x2408ffff,
+0x8c6c0000, 0x24c6ffff, 0x24630004, 0xacec0000,
+0x14c8fffb, 0x24e70004, 0x0, 0x0,
+0x0, 0x3c0f0020, 0xaf4f0030, 0x0,
+0x24ad0200, 0x1a5702b, 0x2529ffff, 0x8e2021,
+0x1520ffe1, 0x1a02821, 0x3e00008, 0x0,
+0x27bdffe0, 0xafb10014, 0xafbf0018, 0xafb00010,
+0x3c05600e, 0x8ca20034, 0x808821, 0x14400006,
+0x3c046000, 0x8c87201c, 0x2408fffc, 0xe83024,
+0x34c30001, 0xac83201c, 0x8f8b001c, 0x24090001,
+0xaca90034, 0x95690002, 0x8d650014, 0x8d70000c,
+0x2d240081, 0x8d670004, 0x8d660008, 0x10800007,
+0x8d6a0010, 0x2d2c0004, 0x1580000e, 0x30ce0007,
+0x312d0003, 0x11a0000b, 0x0, 0x2404008b,
+0x2002821, 0xe0006d1, 0x24060003, 0x11102b,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x15c0fff6, 0x2404008b, 0x3c030020,
+0xaf430030, 0x0, 0x24020001, 0xaf820014,
+0x0, 0x0, 0x0, 0x3c1f0150,
+0x13fc825, 0x25380003, 0x3c0f600e, 0xaf470038,
+0x181882, 0xaf46003c, 0x35e8003c, 0xaf590030,
+0x27470400, 0x8f440000, 0x30860020, 0x10c0fffd,
+0x0, 0x10600008, 0x2466ffff, 0x2403ffff,
+0x8ceb0000, 0x24c6ffff, 0x24e70004, 0xad0b0000,
+0x14c3fffb, 0x25080004, 0x3c08600e, 0xad090038,
+0x0, 0x0, 0x0, 0x3c070020,
+0xaf470030, 0x0, 0xe0006f9, 0x1402021,
+0x2002821, 0x2021, 0xe0006d1, 0x24060003,
+0x11102b, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018,
+0x3092ffff, 0xafb10014, 0xafbf001c, 0xafb00010,
+0x1640000d, 0x8821, 0xa0007aa, 0x2201021,
+0x24050001, 0x50850027, 0x8ce5000c, 0xd,
+0x26230001, 0x3071ffff, 0x24e20020, 0x232382b,
+0x10e00019, 0xaf82001c, 0x8f820014, 0x14400016,
+0x8f87001c, 0x3c067000, 0x3c032000, 0x8ce50000,
+0xa62024, 0x14830010, 0x8f84003c, 0x54402,
+0x3c098000, 0xa98024, 0x1480ffe9, 0x310600ff,
+0x2cca0009, 0x5140ffeb, 0x26230001, 0x66880,
+0x3c0e0800, 0x25ce578c, 0x1ae6021, 0x8d8b0000,
+0x1600008, 0x0, 0x2201021, 0x8fbf001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0xe0006d1, 0x24040084, 0x1600ffd8,
+0x8f87001c, 0xa00078b, 0xaf80003c, 0x90ef0002,
+0x2021, 0x24060009, 0xe0006d1, 0xf2e00,
+0x8f87001c, 0x10102b, 0xa00078b, 0xaf82003c,
+0x2002821, 0xe0006df, 0x24040001, 0x8f87001c,
+0xa00078b, 0xaf82003c, 0x2002821, 0xe0006df,
+0x2021, 0xa0007c3, 0x8f87001c, 0xe00071f,
+0x2002021, 0xa0007c3, 0x8f87001c, 0x30b0ffff,
+0x1019c0, 0x8f5801b8, 0x700fffe, 0x3c1f2004,
+0x3c191000, 0xaf430180, 0xaf400184, 0xaf5f0188,
+0xaf5901b8, 0xa00078c, 0x26230001, 0x3082ffff,
+0x14400003, 0x1821, 0x42402, 0x24030010,
+0x308500ff, 0x14a00005, 0x3087000f, 0x24660008,
+0x42202, 0x30c300ff, 0x3087000f, 0x14e00005,
+0x30890003, 0x24680004, 0x42102, 0x310300ff,
+0x30890003, 0x15200005, 0x388b0001, 0x246a0002,
+0x42082, 0x314300ff, 0x388b0001, 0x31640001,
+0x10800002, 0x246c0001, 0x318300ff, 0x3e00008,
+0x601021, 0x308bffff, 0xb3942, 0x30e600ff,
+0x3c090800, 0x25295978, 0x64080, 0x1096021,
+0x8d870000, 0x3164001f, 0x240a0001, 0x8a1804,
+0x30a500ff, 0xe32025, 0x14a00002, 0x31027,
+0xe22024, 0x240f0001, 0xcf7004, 0x1096821,
+0xe2827, 0x14800005, 0xada40000, 0x8f86000c,
+0xa61024, 0x3e00008, 0xaf82000c, 0x8f88000c,
+0x1c81025, 0x3e00008, 0xaf82000c, 0x3c06001f,
+0x3c036000, 0x3084ffff, 0x34c5ff80, 0x24020020,
+0xac602008, 0xac60200c, 0xac602010, 0xac652014,
+0xac642018, 0xac622000, 0x0, 0x0,
+0x3e00008, 0x0, 0x27bdffe8, 0x2402ffff,
+0xafbf0010, 0xaf82000c, 0x2021, 0x3c060800,
+0x24c65978, 0x2405ffff, 0x24890001, 0x44080,
+0x3124ffff, 0x1061821, 0x2c870020, 0x14e0fffa,
+0xac650000, 0xe000816, 0x2021, 0x24020001,
+0x3c046000, 0x24050020, 0xac822018, 0xac852000,
+0x0, 0x0, 0x0, 0x244a0001,
+0x3142ffff, 0x2c460400, 0x14c0fff7, 0x8fbf0010,
+0x3e00008, 0x27bd0018, 0x8f830008, 0x2c620400,
+0x3e00008, 0x38420001, 0x8f830008, 0x24620001,
+0x3e00008, 0xaf820008, 0x8f830008, 0x2462ffff,
+0x3e00008, 0xaf820008, 0x27bdffe0, 0xafb10014,
+0xafbf0018, 0xafb00010, 0x8f6b0030, 0x3c066000,
+0x808821, 0xaccb2008, 0x8f6a002c, 0x3c028000,
+0x24030008, 0xacca200c, 0x9769003a, 0x97680038,
+0x92c00, 0x3107ffff, 0xa72025, 0xacc42010,
+0xacc22014, 0xacc32000, 0x0, 0x0,
+0x0, 0x3c036000, 0x8c6d2000, 0x31ac0008,
+0x1580fff9, 0x0, 0x8c6e2014, 0x5c00020,
+0x0, 0xe0007da, 0x8f84000c, 0x24080,
+0x3c090800, 0x25295978, 0x1093821, 0x8ce40000,
+0xe0007da, 0x28140, 0x2022021, 0x3090ffff,
+0x2002021, 0xe0007f8, 0x2821, 0x3c0c8000,
+0x22c5825, 0x3210ffff, 0x3c116000, 0x240a0020,
0xae2b2014, 0xae302018, 0xae2a2000, 0x0,
0x0, 0x0, 0x2001021, 0x8fbf0018,
0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
-0x27bdffe8, 0xafb00010, 0x3402ffff, 0x3090ffff,
-0xafbf0014, 0x12020006, 0x2002021, 0xe000825,
-0x0, 0x2002021, 0xe000807, 0x24050001,
-0x8f840008, 0x8fbf0014, 0x8fb00010, 0x2483ffff,
-0x27bd0018, 0x3e00008, 0xaf830008, 0x439c2,
-0x30e6003f, 0x43b42, 0x71840, 0x24021000,
-0x2cc40020, 0x24c8ffe0, 0xaf42002c, 0x24630001,
-0x14800003, 0x30a900ff, 0x71840, 0x310600ff,
-0x36080, 0x24080001, 0x19a5821, 0x3c0a000e,
-0xc82804, 0x16a3821, 0x11200005, 0x53027,
-0x8ce90000, 0x1253025, 0x3e00008, 0xace60000,
-0x8cee0000, 0x1c66824, 0x3e00008, 0xaced0000,
-0x27bdffe8, 0xafbf0014, 0xafb00010, 0x3c046000,
-0x8c850808, 0x3403f000, 0x30a2f000, 0x50430006,
-0x24020001, 0x8c870808, 0x3404e000, 0x30e6f000,
-0x10c4001e, 0x24020002, 0xaf820040, 0x3c106000,
-0x3c0a0200, 0xae0a0814, 0x24091000, 0x3c08000e,
-0x8e034400, 0x3482021, 0xaf49002c, 0x24050120,
-0xe000ccf, 0x3021, 0x8f830040, 0x10600004,
-0x3c021691, 0x240b0001, 0x106b000e, 0x3c023d6c,
-0x344f0090, 0xae0f4408, 0x8fbf0014, 0x8fb00010,
-0x3c0c6000, 0x240e1000, 0x3c0d0200, 0x27bd0018,
-0xad8e4420, 0x3e00008, 0xad8d0810, 0xa0008f6,
-0xaf800040, 0x3c0218da, 0x344f0090, 0xae0f4408,
-0x8fbf0014, 0x8fb00010, 0x3c0c6000, 0x240e1000,
-0x3c0d0200, 0x27bd0018, 0xad8e4420, 0x3e00008,
-0xad8d0810, 0xa0008ca, 0x24050001, 0xa0008ca,
-0x2821, 0x3c080800, 0x25085da4, 0x2404ffff,
-0x1001821, 0x2402001e, 0x2442ffff, 0xac640000,
-0x441fffd, 0x24630004, 0x3c070800, 0x24e75e20,
-0x8ce5fffc, 0x2404001c, 0x24060001, 0x308a001f,
-0x1464804, 0x24840001, 0x91027, 0x2c830020,
-0x1460fffa, 0xa22824, 0xace5fffc, 0x3c056666,
-0x34a4616e, 0x3c060800, 0x24c65ee0, 0xaf840058,
-0xaf88009c, 0x2404ffff, 0xc01821, 0x2402001f,
+0x8c662014, 0x3c02001f, 0x3443ff80, 0x3c1fffe8,
+0xc3c024, 0x37f90800, 0x3198021, 0x1079c2,
+0x3c0c8000, 0x22c5825, 0x31f0ffff, 0x3c116000,
+0x240a0020, 0xae2b2014, 0xae302018, 0xae2a2000,
+0x0, 0x0, 0x0, 0x2001021,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x27bdffe8, 0xafb00010, 0x3402ffff,
+0x3090ffff, 0xafbf0014, 0x12020006, 0x2002021,
+0xe000816, 0x0, 0x2002021, 0xe0007f8,
+0x24050001, 0x8f840008, 0x8fbf0014, 0x8fb00010,
+0x2483ffff, 0x27bd0018, 0x3e00008, 0xaf830008,
+0x439c2, 0x30e6003f, 0x43b42, 0x71840,
+0x24021000, 0x2cc40020, 0x24c8ffe0, 0xaf42002c,
+0x24630001, 0x14800003, 0x30a900ff, 0x71840,
+0x310600ff, 0x36080, 0x24080001, 0x19a5821,
+0x3c0a000e, 0xc82804, 0x16a3821, 0x11200005,
+0x53027, 0x8ce90000, 0x1253025, 0x3e00008,
+0xace60000, 0x8cee0000, 0x1c66824, 0x3e00008,
+0xaced0000, 0x27bdffe8, 0xafbf0014, 0xafb00010,
+0x3c046000, 0x8c850808, 0x3403f000, 0x30a2f000,
+0x50430006, 0x24020001, 0x8c870808, 0x3404e000,
+0x30e6f000, 0x10c4001e, 0x24020002, 0xaf820040,
+0x3c106000, 0x3c0a0200, 0xae0a0814, 0x24091000,
+0x3c08000e, 0x8e034400, 0x3482021, 0xaf49002c,
+0x24050120, 0xe000cc0, 0x3021, 0x8f830040,
+0x10600004, 0x3c021691, 0x240b0001, 0x106b000e,
+0x3c023d2c, 0x344f0090, 0xae0f4408, 0x8fbf0014,
+0x8fb00010, 0x3c0c6000, 0x240e1000, 0x3c0d0200,
+0x27bd0018, 0xad8e4420, 0x3e00008, 0xad8d0810,
+0xa0008e7, 0xaf800040, 0x3c0218da, 0x344f0090,
+0xae0f4408, 0x8fbf0014, 0x8fb00010, 0x3c0c6000,
+0x240e1000, 0x3c0d0200, 0x27bd0018, 0xad8e4420,
+0x3e00008, 0xad8d0810, 0xa0008bb, 0x24050001,
+0xa0008bb, 0x2821, 0x3c080800, 0x25085d84,
+0x2404ffff, 0x1001821, 0x2402001e, 0x2442ffff,
+0xac640000, 0x441fffd, 0x24630004, 0x3c070800,
+0x24e75e00, 0x8ce5fffc, 0x2404001c, 0x24060001,
+0x308a001f, 0x1464804, 0x24840001, 0x91027,
+0x2c830020, 0x1460fffa, 0xa22824, 0xace5fffc,
+0x3c056666, 0x34a4616e, 0x3c060800, 0x24c65ec0,
+0xaf840058, 0xaf88009c, 0x2404ffff, 0xc01821,
+0x2402001f, 0x2442ffff, 0xac640000, 0x441fffd,
+0x24630004, 0x3c076666, 0x3c050800, 0x24a55e80,
+0xaf860048, 0x34e6616e, 0xaf860098, 0x2404ffff,
+0xa01821, 0x2402000f, 0x2442ffff, 0xac640000,
+0x441fffd, 0x24630004, 0x3c0b6666, 0x3c060800,
+0x24c65e00, 0x3568616e, 0xaf8500a4, 0xaf880070,
+0x2404ffff, 0xc01821, 0x2402001f, 0x2442ffff,
+0xac640000, 0x441fffd, 0x24630004, 0x3c0d6666,
+0x3c0a0800, 0x254a5f40, 0x35ac616e, 0xaf860090,
+0xaf8c005c, 0x2404ffff, 0x1401821, 0x24020003,
0x2442ffff, 0xac640000, 0x441fffd, 0x24630004,
-0x3c076666, 0x3c050800, 0x24a55ea0, 0xaf860048,
-0x34e6616e, 0xaf860098, 0x2404ffff, 0xa01821,
-0x2402000f, 0x2442ffff, 0xac640000, 0x441fffd,
-0x24630004, 0x3c0b6666, 0x3c060800, 0x24c65e20,
-0x3568616e, 0xaf8500a4, 0xaf880070, 0x2404ffff,
-0xc01821, 0x2402001f, 0x2442ffff, 0xac640000,
-0x441fffd, 0x24630004, 0x3c0d6666, 0x3c0a0800,
-0x254a5f60, 0x35ac616e, 0xaf860090, 0xaf8c005c,
-0x2404ffff, 0x1401821, 0x24020003, 0x2442ffff,
-0xac640000, 0x441fffd, 0x24630004, 0x3c090800,
-0x25295f70, 0x8d27fffc, 0x24040006, 0x24050001,
-0x3099001f, 0x325c004, 0x24840001, 0x187827,
-0x2c8e0020, 0x15c0fffa, 0xef3824, 0xad27fffc,
-0x3c096666, 0x24030400, 0x240403dc, 0x24050200,
-0x24060066, 0x3522616e, 0x3c080800, 0x25085aa4,
-0xaf820074, 0xaf830044, 0xaf83006c, 0xaf830050,
-0xaf830084, 0xaf8a008c, 0xaf840064, 0xaf85004c,
-0xaf860054, 0xaf840078, 0xaf850060, 0xaf860080,
-0x1001821, 0x24020002, 0x2442ffff, 0xac600000,
-0x441fffd, 0x24630004, 0x24040003, 0x2403000c,
-0x3c0a0800, 0x254a5ab0, 0xaf8a0068, 0xa00099d,
-0x2405ffff, 0x41880, 0x24840001, 0x685821,
-0x2c8700c0, 0x14e0fffb, 0xad650000, 0x3c0e6666,
-0x35cd616e, 0x240c17a0, 0x24081800, 0xaf8d0088,
-0xaf8c0094, 0x3e00008, 0xaf88007c, 0x2484007f,
-0x421c2, 0x4021, 0x3021, 0x3821,
-0x2821, 0xa0009b4, 0xaf8400a0, 0x10600006,
-0x24e70001, 0xc43021, 0x24a50001, 0x2cc20bf5,
-0x1440fffa, 0x2ca30066, 0x3c090800, 0x25295f60,
-0x1201821, 0x24020003, 0x2442ffff, 0xac600000,
-0x441fffd, 0x24630004, 0x10e0001a, 0x24e3ffff,
-0x32942, 0x10a0000a, 0x2021, 0x2406ffff,
-0x3c030800, 0x24635f60, 0x24840001, 0x85502b,
-0xac660000, 0x25080001, 0x1540fffb, 0x24630004,
-0x30e2001f, 0x10400008, 0x86880, 0x240c0001,
-0x4c3804, 0x85880, 0x1692821, 0x24e6ffff,
-0x3e00008, 0xaca60000, 0x1a94021, 0x2409ffff,
-0xad090000, 0x3e00008, 0x0, 0xaf440028,
-0x3c04000c, 0x3442021, 0x52882, 0xa000ccf,
-0x3021, 0x42180, 0x3c036000, 0xac641008,
-0x0, 0x52980, 0xac65100c, 0x0,
-0x3e00008, 0x8c62100c, 0x27bdffe8, 0x802821,
-0x24040038, 0xafbf0014, 0xe0009e4, 0xafb00010,
-0x24040e00, 0xaf440028, 0x3c10000c, 0x3502021,
-0x24050010, 0xe000ccf, 0x3021, 0x3501021,
-0xac400000, 0xac400004, 0x24040038, 0x8fbf0014,
-0x8fb00010, 0x24053fff, 0x27bd0018, 0xa0009e4,
-0x8c430000, 0x42180, 0x3c036000, 0xac641008,
-0x0, 0x8c62100c, 0x3e00008, 0x21182,
-0x27bdffc8, 0xafb40020, 0x8f940068, 0xafbe0030,
-0xafb7002c, 0xafb60028, 0xb821, 0x80b021,
-0x241e00c0, 0xafbf0034, 0xafb50024, 0xafb3001c,
-0xafb20018, 0xafb10014, 0xafb00010, 0xa000a21,
-0xafa5003c, 0x50400001, 0x8f940068, 0x27deffff,
-0x13c00028, 0x26940004, 0x8e920000, 0x3c030800,
-0x24635da0, 0x1240fff7, 0x283102b, 0x3c040800,
-0x24845aa4, 0x2841023, 0x2a8c0, 0x9821,
-0xa000a30, 0x24110001, 0x118840, 0x12200026,
-0x0, 0x2b38021, 0x2512824, 0x2002021,
-0x10a0fff9, 0x26730001, 0xe0009ed, 0x0,
-0x166840, 0x32ec0001, 0x1ac2021, 0xe0009e4,
-0x2002821, 0x8f890094, 0x26f70001, 0x8fa6003c,
-0x3aeb0001, 0x316a0001, 0x2528ffff, 0x113827,
-0x2cab021, 0xaf880094, 0x16e6ffe7, 0x2479024,
-0xae920000, 0x2e01021, 0x8fbf0034, 0x8fbe0030,
-0x8fb7002c, 0x8fb60028, 0x8fb50024, 0x8fb40020,
+0x3c090800, 0x25295f50, 0x8d27fffc, 0x24040006,
+0x24050001, 0x3099001f, 0x325c004, 0x24840001,
+0x187827, 0x2c8e0020, 0x15c0fffa, 0xef3824,
+0xad27fffc, 0x3c096666, 0x24030400, 0x240403dc,
+0x24050200, 0x24060066, 0x3522616e, 0x3c080800,
+0x25085a84, 0xaf820074, 0xaf830044, 0xaf83006c,
+0xaf830050, 0xaf830084, 0xaf8a008c, 0xaf840064,
+0xaf85004c, 0xaf860054, 0xaf840078, 0xaf850060,
+0xaf860080, 0x1001821, 0x24020002, 0x2442ffff,
+0xac600000, 0x441fffd, 0x24630004, 0x24040003,
+0x2403000c, 0x3c0a0800, 0x254a5a90, 0xaf8a0068,
+0xa00098e, 0x2405ffff, 0x41880, 0x24840001,
+0x685821, 0x2c8700c0, 0x14e0fffb, 0xad650000,
+0x3c0e6666, 0x35cd616e, 0x240c17a0, 0x24081800,
+0xaf8d0088, 0xaf8c0094, 0x3e00008, 0xaf88007c,
+0x2484007f, 0x421c2, 0x4021, 0x3021,
+0x3821, 0x2821, 0xa0009a5, 0xaf8400a0,
+0x10600006, 0x24e70001, 0xc43021, 0x24a50001,
+0x2cc20bf5, 0x1440fffa, 0x2ca30066, 0x3c090800,
+0x25295f40, 0x1201821, 0x24020003, 0x2442ffff,
+0xac600000, 0x441fffd, 0x24630004, 0x10e0001a,
+0x24e3ffff, 0x32942, 0x10a0000a, 0x2021,
+0x2406ffff, 0x3c030800, 0x24635f40, 0x24840001,
+0x85502b, 0xac660000, 0x25080001, 0x1540fffb,
+0x24630004, 0x30e2001f, 0x10400008, 0x86880,
+0x240c0001, 0x4c3804, 0x85880, 0x1692821,
+0x24e6ffff, 0x3e00008, 0xaca60000, 0x1a94021,
+0x2409ffff, 0xad090000, 0x3e00008, 0x0,
+0xaf440028, 0x3c04000c, 0x3442021, 0x52882,
+0xa000cc0, 0x3021, 0x42180, 0x3c036000,
+0xac641008, 0x0, 0x52980, 0xac65100c,
+0x0, 0x3e00008, 0x8c62100c, 0x27bdffe8,
+0x802821, 0x24040038, 0xafbf0014, 0xe0009d5,
+0xafb00010, 0x24040e00, 0xaf440028, 0x3c10000c,
+0x3502021, 0x24050010, 0xe000cc0, 0x3021,
+0x3501021, 0xac400000, 0xac400004, 0x24040038,
+0x8fbf0014, 0x8fb00010, 0x24053fff, 0x27bd0018,
+0xa0009d5, 0x8c430000, 0x42180, 0x3c036000,
+0xac641008, 0x0, 0x8c62100c, 0x3e00008,
+0x21182, 0x27bdffc8, 0xafb40020, 0x8f940068,
+0xafbe0030, 0xafb7002c, 0xafb60028, 0xb821,
+0x80b021, 0x241e00c0, 0xafbf0034, 0xafb50024,
+0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010,
+0xa000a12, 0xafa5003c, 0x50400001, 0x8f940068,
+0x27deffff, 0x13c00028, 0x26940004, 0x8e920000,
+0x3c030800, 0x24635d80, 0x1240fff7, 0x283102b,
+0x3c040800, 0x24845a84, 0x2841023, 0x2a8c0,
+0x9821, 0xa000a21, 0x24110001, 0x118840,
+0x12200026, 0x0, 0x2b38021, 0x2512824,
+0x2002021, 0x10a0fff9, 0x26730001, 0xe0009de,
+0x0, 0x166840, 0x32ec0001, 0x1ac2021,
+0xe0009d5, 0x2002821, 0x8f890094, 0x26f70001,
+0x8fa6003c, 0x3aeb0001, 0x316a0001, 0x2528ffff,
+0x113827, 0x2cab021, 0xaf880094, 0x16e6ffe7,
+0x2479024, 0xae920000, 0x2e01021, 0x8fbf0034,
+0x8fbe0030, 0x8fb7002c, 0x8fb60028, 0x8fb50024,
+0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0038, 0x3c0e0800,
+0x25ce5d80, 0x28e102b, 0xa000a0d, 0xae920000,
+0x27bdffd8, 0xafb10014, 0xafb00010, 0xafbf0020,
+0xafb3001c, 0xafb20018, 0xa08821, 0x10a0001f,
+0x48040, 0x3c130800, 0x26735a84, 0xa000a5a,
+0x24120001, 0x12200019, 0x26100001, 0xe0009f5,
+0x2002021, 0x23142, 0x2444ffa0, 0x61880,
+0x3045001f, 0x2c8217a1, 0x731821, 0x2631ffff,
+0x1040fff4, 0xb23004, 0x8c690000, 0x2002021,
+0x24053fff, 0x1264024, 0x1500ffee, 0x1263825,
+0xe0009d5, 0xac670000, 0x8f8a0094, 0x26100001,
+0x25470001, 0x1620ffe9, 0xaf870094, 0x8fbf0020,
0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0038, 0x3c0e0800, 0x25ce5da0,
-0x28e102b, 0xa000a1c, 0xae920000, 0x27bdffd8,
-0xafb10014, 0xafb00010, 0xafbf0020, 0xafb3001c,
-0xafb20018, 0xa08821, 0x10a0001f, 0x48040,
-0x3c130800, 0x26735aa4, 0xa000a69, 0x24120001,
-0x12200019, 0x26100001, 0xe000a04, 0x2002021,
-0x23142, 0x2444ffa0, 0x61880, 0x3045001f,
-0x2c8217a1, 0x731821, 0x2631ffff, 0x1040fff4,
-0xb23004, 0x8c690000, 0x2002021, 0x24053fff,
-0x1264024, 0x1500ffee, 0x1263825, 0xe0009e4,
-0xac670000, 0x8f8a0094, 0x26100001, 0x25470001,
-0x1620ffe9, 0xaf870094, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0028, 0x8f85009c, 0x805821, 0x4021,
-0x4821, 0x240a001f, 0x3c0c0800, 0x258c5e1c,
-0x3c0d0800, 0x25ad5da4, 0x8ca60000, 0x50c00014,
-0x4021, 0xad1023, 0x238c0, 0x24030001,
-0xa000aa2, 0x2021, 0x15000003, 0xe41021,
-0x24482024, 0x4821, 0x25290001, 0x512b0013,
-0x2506dfdc, 0x10600006, 0x24840001, 0xc37024,
-0x15c0fff5, 0x31840, 0xa000aa0, 0x4021,
-0x10ac0026, 0x24a30004, 0x602821, 0x254affff,
-0x1540ffe5, 0xaf85009c, 0x512b0004, 0x2506dfdc,
-0x4021, 0x3e00008, 0x1001021, 0x66142,
-0x30c5001f, 0xc5080, 0x3c070800, 0x24e75da4,
-0x24040001, 0x1473021, 0x1120000f, 0xa42004,
-0x3c050800, 0x24a55e20, 0x14800005, 0x2529ffff,
-0x24c60004, 0x10c50011, 0x0, 0x24040001,
-0x8ccf0000, 0x4c027, 0x42040, 0x1f86824,
-0x1520fff5, 0xaccd0000, 0x8f990078, 0x1001021,
-0x32b4823, 0x3e00008, 0xaf890078, 0x3c050800,
-0x24a55da4, 0xa000aaa, 0x4021, 0x3c060800,
-0x24c65da4, 0xa000ac3, 0x24040001, 0x308800ff,
-0x24020002, 0x1102000a, 0x24030003, 0x1103005c,
-0x8f8900a4, 0x24040004, 0x1104005f, 0x24050005,
-0x11050067, 0x1821, 0x3e00008, 0x601021,
-0x8f890048, 0x3c0c0800, 0x258c5ee0, 0x3c040800,
-0x24845f60, 0x24030020, 0x1060000f, 0x5821,
-0x240d0002, 0x240e0003, 0x3c0f0800, 0x25ef5ee0,
-0x8d270000, 0x14e0000b, 0x30f9ffff, 0x25290004,
-0x124c02b, 0x53000001, 0x1804821, 0x2463ffff,
-0x5460fff8, 0x8d270000, 0x1601821, 0x3e00008,
-0x601021, 0x13200032, 0x3c0500ff, 0x30e200ff,
-0x403021, 0x10400042, 0x5021, 0x24050001,
-0x2021, 0x5c840, 0xa6c024, 0x17000003,
-0x332500ff, 0x14a0fffb, 0x24840001, 0x12cc023,
-0x1828c0, 0xaa6021, 0x8c5021, 0x3144001f,
-0x240c0001, 0x8c1804, 0x31027, 0xe23024,
-0x110d0041, 0xad260000, 0x110e004c, 0xa1840,
-0x110d0036, 0x8f87006c, 0x510e0056, 0x8f8c0060,
-0x240d0004, 0x110d005a, 0x8f8e0084, 0x240e0005,
-0x150effda, 0x1601821, 0x240b1430, 0x11400006,
-0x1821, 0x8f8400a0, 0x24630001, 0x6a402b,
-0x1500fffd, 0x1645821, 0x8f8a0080, 0xaf89008c,
-0x1601821, 0x2549ffff, 0xa000afa, 0xaf890080,
-0xe52024, 0x73602, 0x1080ffd0, 0x240a0018,
-0x75402, 0x314600ff, 0xa000b02, 0x240a0010,
-0x3c0c0800, 0x258c5ea0, 0x3c040800, 0x24845ee0,
-0xa000ae9, 0x24030010, 0x3c0c0800, 0x258c5e20,
-0x3c040800, 0x24845ea0, 0xa000ae8, 0x8f890090,
-0x71a02, 0x306600ff, 0xa000b02, 0x240a0008,
-0x8f89008c, 0x3c0c0800, 0x258c5f60, 0x3c040800,
-0x24845f70, 0xa000ae9, 0x24030004, 0xa4080,
-0x250b0030, 0x24e6ffff, 0x1601821, 0xaf890048,
-0xa000afa, 0xaf86006c, 0xac982, 0x197880,
-0x3c070800, 0x24e75ea0, 0x1e72021, 0xa1842,
-0x8c8f0000, 0x3079001f, 0x32c3804, 0x7c027,
-0x1f86024, 0xa000b17, 0xac8c0000, 0x33142,
-0x62880, 0xaf2821, 0x3062001f, 0x8cb80000,
-0x24630001, 0x4cc804, 0x32142, 0x193827,
-0x41080, 0x3073024, 0x4f2021, 0xa000b5b,
-0xaca60000, 0xa68c0, 0x25ab0032, 0x258affff,
-0x1601821, 0xaf8900a4, 0xa000afa, 0xaf8a0060,
-0x254b1030, 0xaf890090, 0x1601821, 0x25c9ffff,
-0xa000afa, 0xaf890084, 0x30860007, 0x2cc20006,
-0x10400014, 0x0, 0x64080, 0x3c030800,
-0x246357d0, 0x1033821, 0x8ce40000, 0x800008,
-0x0, 0x24090003, 0x10a9000e, 0x0,
-0x240a0005, 0x10aa000b, 0x0, 0x240b0001,
-0x10ab0008, 0x0, 0x8f8c00a0, 0x10ac0005,
-0x0, 0x3e00008, 0x1021, 0xa000a88,
-0xa02021, 0xa000ad6, 0xc02021, 0x27bdffe8,
-0x308400ff, 0x24030002, 0x1083000b, 0xafbf0010,
-0x24060003, 0x1086003a, 0x24080004, 0x10880068,
-0x240e0005, 0x108e007f, 0x2caf1430, 0x8fbf0010,
-0x3e00008, 0x27bd0018, 0x2ca20030, 0x1440fffc,
-0x8fbf0010, 0x24a5ffd0, 0x531c2, 0x66880,
-0x3c070800, 0x24e75ee0, 0x1a73021, 0x8cc90000,
-0x52882, 0x30ac001f, 0x240b0001, 0x18b5004,
-0x8f840048, 0x12a4025, 0xacc80000, 0x8c830000,
-0x50600001, 0xaf860048, 0x8f98006c, 0x30ae0001,
-0x24a6ffff, 0x270f0001, 0x15c00002, 0xaf8f006c,
-0x24a60001, 0x64142, 0x82080, 0x871821,
-0x8c790000, 0x30c2001f, 0x24060001, 0x46f804,
-0x33f3824, 0x10e0ffda, 0x8fbf0010, 0x5c182,
-0x187080, 0x3c0f0800, 0x25ef5ea0, 0x1cf4821,
-0x8d2b0000, 0x56842, 0x31a5001f, 0xa66004,
-0x16c5025, 0x27bd0018, 0x3e00008, 0xad2a0000,
-0x2ca70030, 0x14e0ffca, 0x8fbf0010, 0x30b90007,
-0x1723ffc7, 0x24a8ffce, 0x86a02, 0xd6080,
-0x3c0b0800, 0x256b5ea0, 0x18b3021, 0x8cc40000,
-0x828c2, 0x30aa001f, 0x24080001, 0x1484804,
-0x8f8200a4, 0x891825, 0xacc30000, 0x8c5f0000,
-0x53e00001, 0xaf8600a4, 0x57040, 0xe7942,
-0xf2880, 0x3c040800, 0x24845ee0, 0xa41821,
-0x8c6b0000, 0x25df0001, 0x31cd001f, 0x1f5142,
-0x1a86004, 0x16c4825, 0xa1080, 0xac690000,
-0x442821, 0x8ca60000, 0x8f980060, 0x33f9001f,
-0x8fbf0010, 0x3283804, 0xc77825, 0x270e0001,
-0x27bd0018, 0xacaf0000, 0x3e00008, 0xaf8e0060,
-0x24a5efd0, 0x2cb80400, 0x1300ff99, 0x8fbf0010,
-0x53142, 0x65880, 0x3c0a0800, 0x254a5e20,
-0x16a3021, 0x8cc40000, 0x30a3001f, 0x24090001,
-0x691004, 0x8f990090, 0x82f825, 0xacdf0000,
-0x8f270000, 0x50e00001, 0xaf860090, 0x8f8d0084,
-0x8fbf0010, 0x27bd0018, 0x25ac0001, 0x3e00008,
-0xaf8c0084, 0x15e0ff82, 0x8fbf0010, 0x8f8600a0,
-0x61040, 0x46f821, 0x1f2100, 0x3e4c821,
-0x193840, 0x24f81430, 0xb8402b, 0x1100ff78,
-0x8fbf0010, 0x24a4ebd0, 0xe000203, 0xc02821,
-0x27942, 0xf7080, 0x3c0d0800, 0x25ad5f60,
-0x1cd2021, 0x8c8b0000, 0x304c001f, 0x24060001,
-0x1861804, 0x8f89008c, 0x1635025, 0xac8a0000,
-0x8d250000, 0x50a00001, 0xaf84008c, 0x8f980080,
-0x8fbf0010, 0x27bd0018, 0x27080001, 0x3e00008,
-0xaf880080, 0x30a50007, 0x24030003, 0x10a30010,
-0x28a20004, 0x14400008, 0x24070002, 0x24030004,
-0x10a30015, 0x24080005, 0x10a8000f, 0x8f8500a0,
-0x3e00008, 0x0, 0x14a7fffd, 0x802821,
-0x14c3fffb, 0x24040002, 0xa000b9a, 0x0,
-0x24090005, 0x802821, 0x10c9fffb, 0x24040003,
-0x3e00008, 0x0, 0x14c5fff1, 0x802821,
-0xa000b9a, 0x24040005, 0x240a0001, 0x802821,
-0x10cafff1, 0x24040004, 0x3e00008, 0x0,
-0x27bdffe0, 0xafb00010, 0x581c2, 0x2603ffd0,
-0x24c5003f, 0x2c6223d0, 0x24c6007f, 0xafb20018,
-0xafb10014, 0xafbf001c, 0x309100ff, 0x691c2,
-0x52982, 0x2002021, 0x10400008, 0x2403ffff,
-0xe000a5a, 0x0, 0x2002021, 0x2202821,
-0xe000c48, 0x2403021, 0x1821, 0x8fbf001c,
+0x3e00008, 0x27bd0028, 0x8f85009c, 0x805821,
+0x4021, 0x4821, 0x240a001f, 0x3c0c0800,
+0x258c5dfc, 0x3c0d0800, 0x25ad5d84, 0x8ca60000,
+0x50c00014, 0x4021, 0xad1023, 0x238c0,
+0x24030001, 0xa000a93, 0x2021, 0x15000003,
+0xe41021, 0x24482024, 0x4821, 0x25290001,
+0x512b0013, 0x2506dfdc, 0x10600006, 0x24840001,
+0xc37024, 0x15c0fff5, 0x31840, 0xa000a91,
+0x4021, 0x10ac0026, 0x24a30004, 0x602821,
+0x254affff, 0x1540ffe5, 0xaf85009c, 0x512b0004,
+0x2506dfdc, 0x4021, 0x3e00008, 0x1001021,
+0x66142, 0x30c5001f, 0xc5080, 0x3c070800,
+0x24e75d84, 0x24040001, 0x1473021, 0x1120000f,
+0xa42004, 0x3c050800, 0x24a55e00, 0x14800005,
+0x2529ffff, 0x24c60004, 0x10c50011, 0x0,
+0x24040001, 0x8ccf0000, 0x4c027, 0x42040,
+0x1f86824, 0x1520fff5, 0xaccd0000, 0x8f990078,
+0x1001021, 0x32b4823, 0x3e00008, 0xaf890078,
+0x3c050800, 0x24a55d84, 0xa000a9b, 0x4021,
+0x3c060800, 0x24c65d84, 0xa000ab4, 0x24040001,
+0x308800ff, 0x24020002, 0x1102000a, 0x24030003,
+0x1103005c, 0x8f8900a4, 0x24040004, 0x1104005f,
+0x24050005, 0x11050067, 0x1821, 0x3e00008,
+0x601021, 0x8f890048, 0x3c0c0800, 0x258c5ec0,
+0x3c040800, 0x24845f40, 0x24030020, 0x1060000f,
+0x5821, 0x240d0002, 0x240e0003, 0x3c0f0800,
+0x25ef5ec0, 0x8d270000, 0x14e0000b, 0x30f9ffff,
+0x25290004, 0x124c02b, 0x53000001, 0x1804821,
+0x2463ffff, 0x5460fff8, 0x8d270000, 0x1601821,
+0x3e00008, 0x601021, 0x13200032, 0x3c0500ff,
+0x30e200ff, 0x403021, 0x10400042, 0x5021,
+0x24050001, 0x2021, 0x5c840, 0xa6c024,
+0x17000003, 0x332500ff, 0x14a0fffb, 0x24840001,
+0x12cc023, 0x1828c0, 0xaa6021, 0x8c5021,
+0x3144001f, 0x240c0001, 0x8c1804, 0x31027,
+0xe23024, 0x110d0041, 0xad260000, 0x110e004c,
+0xa1840, 0x110d0036, 0x8f87006c, 0x510e0056,
+0x8f8c0060, 0x240d0004, 0x110d005a, 0x8f8e0084,
+0x240e0005, 0x150effda, 0x1601821, 0x240b1430,
+0x11400006, 0x1821, 0x8f8400a0, 0x24630001,
+0x6a402b, 0x1500fffd, 0x1645821, 0x8f8a0080,
+0xaf89008c, 0x1601821, 0x2549ffff, 0xa000aeb,
+0xaf890080, 0xe52024, 0x73602, 0x1080ffd0,
+0x240a0018, 0x75402, 0x314600ff, 0xa000af3,
+0x240a0010, 0x3c0c0800, 0x258c5e80, 0x3c040800,
+0x24845ec0, 0xa000ada, 0x24030010, 0x3c0c0800,
+0x258c5e00, 0x3c040800, 0x24845e80, 0xa000ad9,
+0x8f890090, 0x71a02, 0x306600ff, 0xa000af3,
+0x240a0008, 0x8f89008c, 0x3c0c0800, 0x258c5f40,
+0x3c040800, 0x24845f50, 0xa000ada, 0x24030004,
+0xa4080, 0x250b0030, 0x24e6ffff, 0x1601821,
+0xaf890048, 0xa000aeb, 0xaf86006c, 0xac982,
+0x197880, 0x3c070800, 0x24e75e80, 0x1e72021,
+0xa1842, 0x8c8f0000, 0x3079001f, 0x32c3804,
+0x7c027, 0x1f86024, 0xa000b08, 0xac8c0000,
+0x33142, 0x62880, 0xaf2821, 0x3062001f,
+0x8cb80000, 0x24630001, 0x4cc804, 0x32142,
+0x193827, 0x41080, 0x3073024, 0x4f2021,
+0xa000b4c, 0xaca60000, 0xa68c0, 0x25ab0032,
+0x258affff, 0x1601821, 0xaf8900a4, 0xa000aeb,
+0xaf8a0060, 0x254b1030, 0xaf890090, 0x1601821,
+0x25c9ffff, 0xa000aeb, 0xaf890084, 0x30860007,
+0x2cc20006, 0x10400014, 0x0, 0x64080,
+0x3c030800, 0x246357b0, 0x1033821, 0x8ce40000,
+0x800008, 0x0, 0x24090003, 0x10a9000e,
+0x0, 0x240a0005, 0x10aa000b, 0x0,
+0x240b0001, 0x10ab0008, 0x0, 0x8f8c00a0,
+0x10ac0005, 0x0, 0x3e00008, 0x1021,
+0xa000a79, 0xa02021, 0xa000ac7, 0xc02021,
+0x27bdffe8, 0x308400ff, 0x24030002, 0x1083000b,
+0xafbf0010, 0x24060003, 0x1086003a, 0x24080004,
+0x10880068, 0x240e0005, 0x108e007f, 0x2caf1430,
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x2ca20030,
+0x1440fffc, 0x8fbf0010, 0x24a5ffd0, 0x531c2,
+0x66880, 0x3c070800, 0x24e75ec0, 0x1a73021,
+0x8cc90000, 0x52882, 0x30ac001f, 0x240b0001,
+0x18b5004, 0x8f840048, 0x12a4025, 0xacc80000,
+0x8c830000, 0x50600001, 0xaf860048, 0x8f98006c,
+0x30ae0001, 0x24a6ffff, 0x270f0001, 0x15c00002,
+0xaf8f006c, 0x24a60001, 0x64142, 0x82080,
+0x871821, 0x8c790000, 0x30c2001f, 0x24060001,
+0x46f804, 0x33f3824, 0x10e0ffda, 0x8fbf0010,
+0x5c182, 0x187080, 0x3c0f0800, 0x25ef5e80,
+0x1cf4821, 0x8d2b0000, 0x56842, 0x31a5001f,
+0xa66004, 0x16c5025, 0x27bd0018, 0x3e00008,
+0xad2a0000, 0x2ca70030, 0x14e0ffca, 0x8fbf0010,
+0x30b90007, 0x1723ffc7, 0x24a8ffce, 0x86a02,
+0xd6080, 0x3c0b0800, 0x256b5e80, 0x18b3021,
+0x8cc40000, 0x828c2, 0x30aa001f, 0x24080001,
+0x1484804, 0x8f8200a4, 0x891825, 0xacc30000,
+0x8c5f0000, 0x53e00001, 0xaf8600a4, 0x57040,
+0xe7942, 0xf2880, 0x3c040800, 0x24845ec0,
+0xa41821, 0x8c6b0000, 0x25df0001, 0x31cd001f,
+0x1f5142, 0x1a86004, 0x16c4825, 0xa1080,
+0xac690000, 0x442821, 0x8ca60000, 0x8f980060,
+0x33f9001f, 0x8fbf0010, 0x3283804, 0xc77825,
+0x270e0001, 0x27bd0018, 0xacaf0000, 0x3e00008,
+0xaf8e0060, 0x24a5efd0, 0x2cb80400, 0x1300ff99,
+0x8fbf0010, 0x53142, 0x65880, 0x3c0a0800,
+0x254a5e00, 0x16a3021, 0x8cc40000, 0x30a3001f,
+0x24090001, 0x691004, 0x8f990090, 0x82f825,
+0xacdf0000, 0x8f270000, 0x50e00001, 0xaf860090,
+0x8f8d0084, 0x8fbf0010, 0x27bd0018, 0x25ac0001,
+0x3e00008, 0xaf8c0084, 0x15e0ff82, 0x8fbf0010,
+0x8f8600a0, 0x61040, 0x46f821, 0x1f2100,
+0x3e4c821, 0x193840, 0x24f81430, 0xb8402b,
+0x1100ff78, 0x8fbf0010, 0x24a4ebd0, 0xe000213,
+0xc02821, 0x27942, 0xf7080, 0x3c0d0800,
+0x25ad5f40, 0x1cd2021, 0x8c8b0000, 0x304c001f,
+0x24060001, 0x1861804, 0x8f89008c, 0x1635025,
+0xac8a0000, 0x8d250000, 0x50a00001, 0xaf84008c,
+0x8f980080, 0x8fbf0010, 0x27bd0018, 0x27080001,
+0x3e00008, 0xaf880080, 0x30a50007, 0x24030003,
+0x10a30010, 0x28a20004, 0x14400008, 0x24070002,
+0x24030004, 0x10a30015, 0x24080005, 0x10a8000f,
+0x8f8500a0, 0x3e00008, 0x0, 0x14a7fffd,
+0x802821, 0x14c3fffb, 0x24040002, 0xa000b8b,
+0x0, 0x24090005, 0x802821, 0x10c9fffb,
+0x24040003, 0x3e00008, 0x0, 0x14c5fff1,
+0x802821, 0xa000b8b, 0x24040005, 0x240a0001,
+0x802821, 0x10cafff1, 0x24040004, 0x3e00008,
+0x0, 0x27bdffe0, 0xafb00010, 0x581c2,
+0x2603ffd0, 0x24c5003f, 0x2c6223d0, 0x24c6007f,
+0xafb20018, 0xafb10014, 0xafbf001c, 0x309100ff,
+0x691c2, 0x52982, 0x2002021, 0x10400008,
+0x2403ffff, 0xe000a4b, 0x0, 0x2002021,
+0x2202821, 0xe000c39, 0x2403021, 0x1821,
+0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0x601021, 0x3e00008, 0x27bd0020, 0x27bdffd8,
+0x24a2007f, 0xafb3001c, 0xafb20018, 0x299c2,
+0x309200ff, 0x24a3003f, 0x2402021, 0x2602821,
+0xafb10014, 0xafb00010, 0xafbf0020, 0xe000b6e,
+0x38982, 0x408021, 0x402021, 0x2202821,
+0x14400009, 0x1821, 0x8fbf0020, 0x8fb3001c,
0x8fb20018, 0x8fb10014, 0x8fb00010, 0x601021,
-0x3e00008, 0x27bd0020, 0x27bdffd8, 0x24a2007f,
-0xafb3001c, 0xafb20018, 0x299c2, 0x309200ff,
-0x24a3003f, 0x2402021, 0x2602821, 0xafb10014,
-0xafb00010, 0xafbf0020, 0xe000b7d, 0x38982,
-0x408021, 0x402021, 0x2202821, 0x14400009,
-0x1821, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x601021, 0x3e00008,
-0x27bd0028, 0xe000a0b, 0x0, 0x402821,
-0x2002021, 0x1051fff3, 0x1019c0, 0xe000a5a,
-0x0, 0x2002021, 0x2402821, 0xe000c48,
-0x2603021, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x1821, 0x601021,
-0x3e00008, 0x27bd0028, 0x3084ffff, 0x30a5ffff,
-0x10800007, 0x1821, 0x30820001, 0x10400002,
-0x42042, 0x651821, 0x1480fffb, 0x52840,
-0x3e00008, 0x601021, 0x10c00007, 0x0,
-0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
-0x14c0fffb, 0x24840004, 0x3e00008, 0x0,
-0x10a00008, 0x24a3ffff, 0xac860000, 0x0,
-0x0, 0x2402ffff, 0x2463ffff, 0x1462fffa,
-0x24840004, 0x3e00008, 0x0, 0x30a5ffff,
-0x8f4201b8, 0x440fffe, 0x3c076015, 0xa73025,
-0x3c031000, 0xaf440180, 0xaf400184, 0xaf460188,
-0x3e00008, 0xaf4301b8, 0x8f8500d0, 0x2c864000,
-0x801821, 0x8ca70084, 0x87102b, 0x14400010,
-0x0, 0x8ca80084, 0x2d064000, 0x50c0000f,
-0x24034000, 0x8caa0084, 0x8a482b, 0x51200001,
-0x8ca30084, 0x35a42, 0xb2080, 0x3c050800,
-0x24a55820, 0x851821, 0x3e00008, 0x8c620000,
-0x14c0fff4, 0x0, 0x24034000, 0x35a42,
-0xb2080, 0x3c050800, 0x24a55820, 0x851821,
-0x3e00008, 0x8c620000, 0x8f8300d0, 0x906600d0,
-0x24c50001, 0xa06500d0, 0x8f8500d0, 0x906400d0,
-0x90a200d2, 0x10440017, 0x0, 0x936c0078,
-0x8f8b00bc, 0x318a00ff, 0xa16a000c, 0x25490001,
-0x938700c4, 0x312200ff, 0x3048007f, 0x1107000b,
-0x26827, 0xa3620078, 0x8f4e0178, 0x5c0fffe,
-0x8f9900b0, 0x24180002, 0x3c0f1000, 0xaf590140,
-0xa3580144, 0x3e00008, 0xaf4f0178, 0xa000d18,
-0x31a20080, 0xa0a000d0, 0xa000d0e, 0x0,
-0x8f8700d0, 0x27bdffc8, 0xafbf0030, 0xafb7002c,
-0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c,
-0xafb20018, 0xafb10014, 0xafb00010, 0x94e300e0,
-0x94e200e2, 0x104300d7, 0x2405ffff, 0x3c047fff,
-0x3497ffff, 0x2415ff80, 0xa000dff, 0x3c16000e,
-0x108a00d1, 0x8fbf0030, 0x8f9100b0, 0x3c180800,
-0x8f18005c, 0x1230c0, 0x129140, 0x3117021,
-0x1d57824, 0xaf4f002c, 0x94ec00e2, 0x31cd007f,
-0x1ba5821, 0x318a7fff, 0x1764821, 0xa8040,
-0x2091021, 0x94530000, 0x3c080800, 0x8d080058,
-0x246c021, 0x32733fff, 0x131980, 0x1032021,
-0x2242821, 0x30bf007f, 0x3fac821, 0xb5a024,
-0xaf54002c, 0x336a021, 0x8e870010, 0x8e8f0030,
-0x3785821, 0x256d0088, 0xef7023, 0x240c0002,
-0xae8e0010, 0xaf8d00ac, 0xa16c0088, 0x976a003c,
-0x8e840030, 0x8f9100ac, 0xe000ce5, 0x3150ffff,
-0x24b80, 0x2094025, 0x3c024200, 0x1022025,
-0xae240004, 0x8e830004, 0x8f8d00ac, 0x8e860000,
-0x240e0008, 0xada3001c, 0xada60018, 0xada0000c,
-0xada00010, 0x929f000a, 0x33f900ff, 0xa5b90014,
-0x96850008, 0x3c1f000c, 0xa5a50016, 0x9298000a,
-0x331100ff, 0xa5b10020, 0x96900008, 0x24180005,
-0xa5b00022, 0xada00024, 0x928f000b, 0x2410c000,
-0x31e700ff, 0xa5a70002, 0xa1ae0001, 0x8e8c0030,
-0x8f8b00ac, 0x8f8400b0, 0xad6c0008, 0x3c0a0800,
-0x8d4a0054, 0x1444821, 0x1354024, 0xaf480028,
-0x3c020800, 0x8c420054, 0x443021, 0x30c3007f,
-0x7ac821, 0x33f2821, 0x2458821, 0xaf9100bc,
-0xaf8500c0, 0xa2380000, 0x8f8a00bc, 0x2403ffbf,
-0x2418ffdf, 0x954f0002, 0x1f03824, 0xf37025,
-0xa54e0002, 0x914d0002, 0x31ac003f, 0x358b0040,
-0xa14b0002, 0x8f8600bc, 0x8f8900d0, 0xacc00004,
-0x8d28007c, 0x3c098000, 0xacc80008, 0x90c4000d,
-0x3082007f, 0xa0c2000d, 0x8f8500bc, 0x90bf000d,
-0x3e3c824, 0xa0b9000d, 0x8f9100bc, 0x9233000d,
-0x2789024, 0xa232000d, 0x8e900034, 0x8f8b00bc,
-0xad700010, 0x8e87002c, 0x8e8f0030, 0xef7023,
-0xad6e0014, 0x916d0018, 0x31ac007f, 0xa16c0018,
-0x8f9f00bc, 0x8e8a0030, 0x8fe80018, 0x1572024,
-0x1093024, 0xc41025, 0xafe20018, 0x9283000a,
-0xa3e3001c, 0x96990008, 0x8f8500bc, 0x8f9800d0,
-0xa4b9001e, 0x8e900030, 0x8e840030, 0xe000203,
-0x8f050084, 0x8f8500d0, 0x29140, 0x29900,
-0x90af00bc, 0x2538821, 0x403021, 0x31e70002,
-0x10e00003, 0x2118021, 0x29080, 0x2128021,
-0x90b900bc, 0x33270004, 0x10e00002, 0x6f880,
-0x21f8021, 0x8e980030, 0x8f8b00bc, 0x24068000,
-0x330f0003, 0xf7023, 0x31cd0003, 0x20d6021,
-0xad6c0004, 0x94a400e2, 0x94aa00e2, 0x94b000e2,
-0x31497fff, 0x25220001, 0x30537fff, 0x2061824,
-0x734025, 0xa4a800e2, 0x94a400e2, 0x3c140800,
-0x8e940060, 0x30917fff, 0x12340022, 0x0,
-0xe000d05, 0x0, 0x8f8700d0, 0x2821,
-0x94f300e0, 0x94f000e2, 0x1213000f, 0x8fbf0030,
-0x90e900d0, 0x90e800d1, 0x313200ff, 0x310400ff,
-0x244302b, 0x14c0ff36, 0x264a0001, 0x90ee00d2,
-0x264b0001, 0x31cd00ff, 0x8d6021, 0x158bff33,
-0x8f9100b0, 0x8fbf0030, 0x8fb7002c, 0x8fb60028,
-0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0xa01021, 0x3e00008,
-0x27bd0038, 0x94a300e2, 0x664024, 0xa4a800e2,
-0x90a400e2, 0x90b900e2, 0x309100ff, 0x11a1c2,
-0x14f827, 0x1f39c0, 0x3332007f, 0x2473025,
-0xa000df7, 0xa0a600e2, 0x3084ffff, 0x30a5ffff,
-0xaf440018, 0xaf45001c, 0x3e00008, 0x8f420014,
-0x27bdffb8, 0xafb00020, 0x8f9000d0, 0x3084ffff,
-0xafa40010, 0xafbf0044, 0xafbe0040, 0xafb7003c,
-0xafb60038, 0xafb50034, 0xafb40030, 0xafb3002c,
-0xafb20028, 0xafb10024, 0xa7a00018, 0x920600d1,
-0x920500d0, 0x30c400ff, 0x30a300ff, 0x64102b,
-0x10400122, 0xafa00014, 0x920900d0, 0x8fb50010,
-0x312800ff, 0x883823, 0x24f4ffff, 0x14882b,
-0x15982b, 0x2339024, 0x52400126, 0x8fb40014,
-0x961e0012, 0x961f0010, 0x8fb70010, 0x3dfc823,
-0x171400, 0x19c400, 0x22403, 0x181403,
-0x2e2b02a, 0x52c00001, 0x402021, 0x284282b,
-0x10a00002, 0x801821, 0x2801821, 0x33c00,
-0x71c03, 0x3064ffff, 0x2c860009, 0x14c00002,
-0x60b821, 0x24170008, 0x8e0a0008, 0x176980,
-0x8e09000c, 0x31abffff, 0x3c0c0010, 0x16c4025,
-0x27520400, 0xaf4a0038, 0xaf9200b8, 0xaf49003c,
-0xaf480030, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x8f4f0000, 0x31ee0020, 0x11c0fffd,
-0x17982a, 0x2711024, 0xa000e92, 0xb021,
-0x55e00101, 0x92580001, 0x31130080, 0x126001cf,
-0x1202021, 0x96550012, 0x32a5ffff, 0xe000cda,
-0xa7b50018, 0x8f9000d0, 0x291a023, 0x26c80001,
-0x8f9100b8, 0x8b400, 0x16b403, 0x262c0040,
-0x2d7782a, 0x14882b, 0x240b0001, 0x1809021,
-0x1f11024, 0xaf8c00b8, 0xafab0014, 0x104001bc,
-0x8f8900b0, 0x3c0c0800, 0x8d8c0054, 0x240bff80,
-0x921e00d0, 0x1895021, 0x14b2824, 0x921900d0,
-0xaf450028, 0x8e470010, 0x3c080800, 0x8d080058,
-0x3c180800, 0x8f180054, 0x30e33fff, 0x32180,
-0x1043021, 0x1265821, 0x2402ff80, 0x162f824,
-0x920c00d0, 0xaf5f002c, 0x92480000, 0x33d100ff,
-0x333500ff, 0x3099821, 0x117140, 0x1578c0,
-0x326d007f, 0x1cf3821, 0x1ba2821, 0x318300ff,
-0x3164007f, 0x3c0a000c, 0xaa8821, 0x367f021,
-0x33140, 0x9a1021, 0x3108003f, 0x3c1f000e,
-0xd1c021, 0x5f9821, 0x27d90088, 0x2d150008,
-0xaf9100c0, 0xaf9900ac, 0xaf9800bc, 0xaf9300b4,
-0x12a0018a, 0x8821, 0x240e0001, 0x10e4004,
-0x310d005d, 0x11a0ffb2, 0x310f0002, 0x8e4a0028,
-0x3c030080, 0x3c04ffef, 0xae6a0000, 0x8e450024,
-0xa260000a, 0x3488ffff, 0xae650004, 0x9247002c,
-0x3c1fff9f, 0x37feffff, 0xa267000c, 0x8e62000c,
-0x3c180040, 0xa267000b, 0x433025, 0xc8c824,
-0x33e8824, 0x238a825, 0xae75000c, 0x8e490004,
-0xae600018, 0x3c0f00ff, 0xae690014, 0x8e4d002c,
-0x35eeffff, 0x8f8b00b0, 0x1ae6024, 0xae6c0010,
-0x8e470008, 0xa6600008, 0x96450012, 0xae670020,
-0x8e42000c, 0x30b03fff, 0x105180, 0xae620024,
-0x8e5e0014, 0x14b1821, 0x30a40001, 0xae7e0028,
-0x8e590018, 0x331c2, 0x44380, 0xae79002c,
-0x8e51001c, 0xc8f821, 0xa67f001c, 0xae710030,
-0x96580002, 0x8e550020, 0xa678001e, 0xae750034,
-0x92490033, 0x31300004, 0x56000005, 0x92500000,
-0x8f8c00d0, 0x8d8b007c, 0xae6b0030, 0x92500000,
-0x8f8f00bc, 0xa1f00000, 0x924e0033, 0x31cd0002,
-0x51a00007, 0x925e0001, 0x8f8900bc, 0x2418ff80,
-0x91310000, 0x311a825, 0xa1350000, 0x925e0001,
-0x8f9900bc, 0x2409ffbf, 0x240bffdf, 0xa33e0001,
-0x8f9500bc, 0x92b8000d, 0x3311007f, 0xa2b1000d,
-0x8f8e00bc, 0x91d0000d, 0x2097824, 0xa1cf000d,
-0x8f8800bc, 0x8e6d0014, 0x910a000d, 0x2dac0001,
-0xc2940, 0x14b3824, 0xe51825, 0xa103000d,
-0x96420012, 0x8f8800bc, 0x8f8700d0, 0xa5020002,
-0x8e450004, 0x90ff00bc, 0x30a40003, 0x43023,
-0x30de0003, 0xbe1021, 0x33f90002, 0x17200002,
-0x24440034, 0x24440030, 0x90e200bc, 0xa23024,
-0x30df0004, 0x17e00002, 0x24830004, 0x801821,
-0x8f8f00ac, 0x24090002, 0xad030004, 0xa1e90000,
-0x924e003f, 0x8f8d00ac, 0xa1ae0001, 0x8f9500ac,
-0x924c003f, 0x8e440004, 0xa6ac0002, 0x976b003c,
-0xe000ce5, 0x3170ffff, 0x25380, 0x20a3825,
-0x3c054200, 0xe51825, 0xaea30004, 0x8f8600ac,
-0x8e480038, 0xacc80018, 0x8e440034, 0xacc4001c,
-0xacc0000c, 0xacc00010, 0xa4c00014, 0xa4c00016,
-0xa4c00020, 0xa4c00022, 0xacc00024, 0x8e640014,
-0x50800001, 0x24040001, 0xacc40008, 0xe000d05,
-0x24110001, 0xa000e85, 0x8f9000d0, 0x920f00d2,
-0x920e00d0, 0x8fb50010, 0x31eb00ff, 0x31cd00ff,
-0x8d6023, 0x16c5021, 0x2554ffff, 0x14882b,
-0x15982b, 0x2339024, 0x1640fedd, 0x0,
-0x8fb40014, 0x8fbf0044, 0x8fbe0040, 0x3a820001,
-0x8fb7003c, 0x8fb60038, 0x8fb50034, 0x8fb40030,
-0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-0x3e00008, 0x27bd0048, 0x33110020, 0x122000ee,
-0x24150001, 0x921e00bc, 0x241f0001, 0xa821,
-0x33d90001, 0x1320000d, 0xafbf001c, 0x8e440014,
-0x8e080084, 0x88102b, 0x14400002, 0x803021,
-0x8e060084, 0x8e030064, 0xc3a82b, 0x16a00002,
-0xc02021, 0x8e040064, 0x80a821, 0x8e470014,
-0x8e050064, 0xe5302b, 0x14c00002, 0xe02021,
-0x8e040064, 0x95f023, 0x13c00004, 0x8fac001c,
-0x240a0002, 0xafaa001c, 0x8fac001c, 0x28c582b,
-0x156000a8, 0x1821, 0x8e4f0038, 0x8e6d000c,
-0x3c0e0080, 0xae6f0000, 0x8e4a0034, 0x3c10ff9f,
-0x1ae5825, 0xae6a0004, 0x9246003f, 0x360cffff,
-0x16c3824, 0x3c050020, 0x3c03ffef, 0xa266000b,
-0xe51025, 0x3468ffff, 0x8f8700b8, 0x48f824,
-0x3c040008, 0x3e4c825, 0xae79000c, 0x8cf80014,
-0xae600018, 0x2be7821, 0xae780014, 0x8cf10018,
-0xae71001c, 0x8ce90008, 0xae690024, 0x8cee000c,
-0xae6f002c, 0xae600028, 0xae6e0020, 0xa6600038,
-0xa660003a, 0x8ced0014, 0x1b58023, 0x21e9023,
-0x12400011, 0xae720010, 0x90ea003d, 0x8e650004,
-0x8e640000, 0xa3100, 0xa6c821, 0x1021,
-0x326402b, 0x82f821, 0x3e8c021, 0xae790004,
-0xae780000, 0x90f1003d, 0xa271000a, 0x8f8900b8,
-0x95320006, 0xa6720008, 0x8f9800ac, 0x24190002,
-0x2a02021, 0xa3190000, 0x9769003c, 0x8f9200ac,
-0xe000ce5, 0x3131ffff, 0x27b80, 0x8f8500b8,
-0x22f6825, 0x3c0e4200, 0x1ae8025, 0xae500004,
-0x8f8400ac, 0x8cac0038, 0xac8c0018, 0x8cab0034,
-0xac8b001c, 0xac80000c, 0xac800010, 0xa4800014,
-0xa4800016, 0xa4800020, 0xa4800022, 0xac800024,
-0x90a7003f, 0xa4870002, 0x12a00134, 0x24030001,
-0x53c00002, 0x90a2003d, 0x90a2003e, 0x24480001,
-0xa0880001, 0x8f9f00ac, 0xaff50008, 0x8f8300d0,
-0x24070034, 0x906600bc, 0x30c50002, 0x50a00001,
-0x24070030, 0x8f9200b8, 0x8f8a00bc, 0x906d00bc,
-0x924b0000, 0x2412c000, 0x32a50003, 0xa14b0000,
-0x8f8600b8, 0x8f8800bc, 0x24020004, 0x90c40001,
-0x451823, 0x30790003, 0xa1040001, 0x8f8a00bc,
-0x8f9f00b8, 0xf53821, 0x95580002, 0x97e90012,
-0xf93821, 0x3128824, 0x312f3fff, 0x22f7025,
-0xa54e0002, 0x91500002, 0x31a80004, 0x320c003f,
-0x358b0040, 0xa14b0002, 0x12a00002, 0x8f8500bc,
-0xe83821, 0x8f8e00d0, 0xaca70004, 0x240bffbf,
-0x8dcd007c, 0x2ea40001, 0x2403ffdf, 0xacad0008,
-0x90b0000d, 0x44140, 0x320c007f, 0xa0ac000d,
-0x8f8600bc, 0x90ca000d, 0x14b1024, 0xa0c2000d,
-0x8f8700bc, 0x90e5000d, 0xa3f824, 0x3e8c825,
-0xa0f9000d, 0x8f9100b8, 0x8f8d00bc, 0x8e380020,
-0xadb80010, 0x8e290024, 0xada90014, 0x8e2f0028,
-0xadaf0018, 0x8e2e002c, 0xe000d05, 0xadae001c,
-0x8fb0001c, 0x240c0002, 0x120c00ed, 0x8f9000d0,
-0x8fa3001c, 0x608821, 0x14600002, 0x60a821,
-0xa021, 0x56a0fe39, 0x291a023, 0x14882b,
-0x8fae0010, 0x96070010, 0x3c0a0020, 0x1d6f023,
-0x2c7c021, 0x33d2ffff, 0xa6180010, 0xafb20010,
-0xaf4a0030, 0x0, 0x96170010, 0x96130012,
-0x1277008e, 0x164180, 0x8e16000c, 0x8e0f0008,
-0x817c3, 0x2c82821, 0xa8582b, 0x1e2a821,
-0x2ab1821, 0xae05000c, 0xae030008, 0x8fb30010,
-0x13b82b, 0x2378024, 0x1200ff05, 0x8f9000d0,
-0xa000e4b, 0x0, 0x8e480038, 0xa6600008,
-0x240f0003, 0xae680000, 0x8e4c0034, 0xa260000a,
-0x8f9000b8, 0xae6c0004, 0x3c050080, 0x920b003f,
-0xa26f000c, 0x8e62000c, 0x3c11ff9f, 0xa26b000b,
-0x456825, 0x3623ffff, 0x3c04ffef, 0x8f8c00b8,
-0x1a33024, 0x349fffff, 0xdfc824, 0xae79000c,
-0x8d890014, 0x959e0012, 0x8f9800b0, 0xae690010,
-0x8d8e0014, 0xae600018, 0xae600020, 0xae6e0014,
-0xae600024, 0x8d870018, 0x33ce3fff, 0xe5180,
-0xae670028, 0x8d880008, 0x1589021, 0x33d00001,
-0xae680030, 0x8d91000c, 0x8f8d00ac, 0x1259c2,
-0x107b80, 0x16f2821, 0x24020002, 0xa665001c,
-0xa6600036, 0xae71002c, 0xa1a20000, 0x9763003c,
-0x8f9800ac, 0x3c044200, 0x307fffff, 0x3e43025,
-0xaf060004, 0x8f9900b8, 0x24070001, 0x240bc000,
-0x8f330038, 0x24060034, 0xaf130018, 0x8f290034,
-0xaf09001c, 0xaf00000c, 0xaf000010, 0xa7000014,
-0xa7000016, 0xa7000020, 0xa7000022, 0xaf000024,
-0xa7150002, 0xa3070001, 0x8f8a00ac, 0x8f9e00b8,
-0x8f8c00bc, 0xad550008, 0x93c80000, 0xa1880000,
-0x8f9200b8, 0x8f8f00bc, 0x92500001, 0xa1f00001,
-0x8f8400bc, 0x94910002, 0x22b2824, 0xae1025,
-0xa4820002, 0x908d0002, 0x31a3003f, 0xa0830002,
-0x8f8300d0, 0x8f8400bc, 0x907f00bc, 0x33f30002,
-0x52600001, 0x24060030, 0xac860004, 0x8c65007c,
-0x240dffbf, 0x2a08821, 0xac850008, 0x9082000d,
-0x3043007f, 0xa083000d, 0x8f8600bc, 0x90c4000d,
-0x8df824, 0xa0df000d, 0x8f8e00bc, 0x91d9000d,
-0x37290020, 0xa1c9000d, 0x8f9e00b8, 0x8f9300bc,
-0x8fc70020, 0xae670010, 0x8fd80024, 0xae780014,
-0x8fca0028, 0xae6a0018, 0x8fd2002c, 0xe000d05,
-0xae72001c, 0xa00104c, 0x8f9000d0, 0x96020014,
-0x8e040004, 0x3043ffff, 0x368c0, 0x8df821,
-0xaf5f003c, 0x8e190004, 0x8f46003c, 0x3264823,
-0x1920003c, 0x0, 0x8e050000, 0x24a20001,
-0x3c0b0010, 0x35750008, 0xaf420038, 0xaf550030,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x8f4c0000, 0x318f0020, 0x11e0fffd, 0x0,
-0x8f530400, 0x3c080020, 0xae130008, 0x8f570404,
-0xae17000c, 0xaf480030, 0x0, 0x3c060800,
-0x8cc60044, 0x24160001, 0x10d600bb, 0x0,
-0x96190012, 0x3c050800, 0x8ca50040, 0xb94821,
-0xa6090012, 0x960e0014, 0x25c70001, 0xa6070014,
-0x96180014, 0x3304ffff, 0x5486ff49, 0x8fb30010,
-0xa6000014, 0xe000e25, 0x30a5ffff, 0x3c040800,
-0x8c840024, 0x961f0012, 0x446823, 0x3ed3023,
-0xa6060012, 0xa001067, 0x8fb30010, 0xa0830001,
-0x8f8200ac, 0x24040001, 0xac440008, 0xa000fff,
-0x8f8300d0, 0x8e020000, 0xa0010f8, 0x3c0b0010,
-0x8f9f00c0, 0x8fb8001c, 0x920f00d0, 0x920b00d0,
-0x920d00d0, 0x31f100ff, 0x316e00ff, 0xe28c0,
-0x111140, 0x451821, 0x31a600ff, 0x3635021,
-0x6c940, 0x33f3821, 0x25490088, 0xaf8900ac,
-0xaf8700bc, 0xa1580088, 0x9768003c, 0x3c02021,
-0x8f9100ac, 0xe000ce5, 0x3110ffff, 0x26380,
-0x20c7825, 0x3c044200, 0x8f8c00b8, 0x1e45825,
-0xae2b0004, 0x8d910038, 0x8f8b00ac, 0x6821,
-0xd1100, 0xad710018, 0x8d8e0034, 0x3c087fff,
-0x3504ffff, 0xad6e001c, 0x9183003e, 0x8d65001c,
-0x8d790018, 0x33100, 0x38702, 0xa6c021,
-0x50f825, 0x306482b, 0x33f3821, 0xe95021,
-0xad78001c, 0xad6a0018, 0xad60000c, 0xad600010,
-0x918f003e, 0x24050005, 0x3c45024, 0xa56f0014,
-0x95910004, 0x3c02021, 0xa5710016, 0x918e003e,
-0xa56e0020, 0x958d0004, 0xa56d0022, 0xad600024,
-0x9190003f, 0xa5700002, 0x9182003d, 0x24430001,
+0x3e00008, 0x27bd0028, 0xe0009fc, 0x0,
+0x402821, 0x2002021, 0x1051fff3, 0x1019c0,
+0xe000a4b, 0x0, 0x2002021, 0x2402821,
+0xe000c39, 0x2603021, 0x8fbf0020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x1821,
+0x601021, 0x3e00008, 0x27bd0028, 0x3084ffff,
+0x30a5ffff, 0x10800007, 0x1821, 0x30820001,
+0x10400002, 0x42042, 0x651821, 0x1480fffb,
+0x52840, 0x3e00008, 0x601021, 0x10c00007,
+0x0, 0x8ca20000, 0x24c6ffff, 0x24a50004,
+0xac820000, 0x14c0fffb, 0x24840004, 0x3e00008,
+0x0, 0x10a00008, 0x24a3ffff, 0xac860000,
+0x0, 0x0, 0x2402ffff, 0x2463ffff,
+0x1462fffa, 0x24840004, 0x3e00008, 0x0,
+0x30a5ffff, 0x8f4201b8, 0x440fffe, 0x3c076015,
+0xa73025, 0x3c031000, 0xaf440180, 0xaf400184,
+0xaf460188, 0x3e00008, 0xaf4301b8, 0x8f8500d0,
+0x2c864000, 0x801821, 0x8ca70084, 0x87102b,
+0x14400010, 0x0, 0x8ca80084, 0x2d064000,
+0x50c0000f, 0x24034000, 0x8caa0084, 0x8a482b,
+0x51200001, 0x8ca30084, 0x35a42, 0xb2080,
+0x3c050800, 0x24a55800, 0x851821, 0x3e00008,
+0x8c620000, 0x14c0fff4, 0x0, 0x24034000,
+0x35a42, 0xb2080, 0x3c050800, 0x24a55800,
+0x851821, 0x3e00008, 0x8c620000, 0x8f8300d0,
+0x906600d0, 0x24c50001, 0xa06500d0, 0x8f8500d0,
+0x906400d0, 0x90a200d2, 0x10440017, 0x0,
+0x936c0078, 0x8f8b00bc, 0x318a00ff, 0xa16a000c,
+0x25490001, 0x938700c4, 0x312200ff, 0x3048007f,
+0x1107000b, 0x26827, 0xa3620078, 0x8f4e0178,
+0x5c0fffe, 0x8f9900b0, 0x24180002, 0x3c0f1000,
+0xaf590140, 0xa3580144, 0x3e00008, 0xaf4f0178,
+0xa000d09, 0x31a20080, 0xa0a000d0, 0xa000cff,
+0x0, 0x8f8700d0, 0x27bdffc8, 0xafbf0030,
+0xafb7002c, 0xafb60028, 0xafb50024, 0xafb40020,
+0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010,
+0x94e300e0, 0x94e200e2, 0x104300d7, 0x2405ffff,
+0x3c047fff, 0x3497ffff, 0x2415ff80, 0xa000df0,
+0x3c16000e, 0x108a00d1, 0x8fbf0030, 0x8f9100b0,
+0x3c180800, 0x8f18005c, 0x1230c0, 0x129140,
+0x3117021, 0x1d57824, 0xaf4f002c, 0x94ec00e2,
+0x31cd007f, 0x1ba5821, 0x318a7fff, 0x1764821,
+0xa8040, 0x2091021, 0x94530000, 0x3c080800,
+0x8d080058, 0x246c021, 0x32733fff, 0x131980,
+0x1032021, 0x2242821, 0x30bf007f, 0x3fac821,
+0xb5a024, 0xaf54002c, 0x336a021, 0x8e870010,
+0x8e8f0030, 0x3785821, 0x256d0088, 0xef7023,
+0x240c0002, 0xae8e0010, 0xaf8d00ac, 0xa16c0088,
+0x976a003c, 0x8e840030, 0x8f9100ac, 0xe000cd6,
+0x3150ffff, 0x24b80, 0x2094025, 0x3c024200,
+0x1022025, 0xae240004, 0x8e830004, 0x8f8d00ac,
+0x8e860000, 0x240e0008, 0xada3001c, 0xada60018,
+0xada0000c, 0xada00010, 0x929f000a, 0x33f900ff,
+0xa5b90014, 0x96850008, 0x3c1f000c, 0xa5a50016,
+0x9298000a, 0x331100ff, 0xa5b10020, 0x96900008,
+0x24180005, 0xa5b00022, 0xada00024, 0x928f000b,
+0x2410c000, 0x31e700ff, 0xa5a70002, 0xa1ae0001,
+0x8e8c0030, 0x8f8b00ac, 0x8f8400b0, 0xad6c0008,
+0x3c0a0800, 0x8d4a0054, 0x1444821, 0x1354024,
+0xaf480028, 0x3c020800, 0x8c420054, 0x443021,
+0x30c3007f, 0x7ac821, 0x33f2821, 0x2458821,
+0xaf9100bc, 0xaf8500c0, 0xa2380000, 0x8f8a00bc,
+0x2403ffbf, 0x2418ffdf, 0x954f0002, 0x1f03824,
+0xf37025, 0xa54e0002, 0x914d0002, 0x31ac003f,
+0x358b0040, 0xa14b0002, 0x8f8600bc, 0x8f8900d0,
+0xacc00004, 0x8d28007c, 0x3c098000, 0xacc80008,
+0x90c4000d, 0x3082007f, 0xa0c2000d, 0x8f8500bc,
+0x90bf000d, 0x3e3c824, 0xa0b9000d, 0x8f9100bc,
+0x9233000d, 0x2789024, 0xa232000d, 0x8e900034,
+0x8f8b00bc, 0xad700010, 0x8e87002c, 0x8e8f0030,
+0xef7023, 0xad6e0014, 0x916d0018, 0x31ac007f,
+0xa16c0018, 0x8f9f00bc, 0x8e8a0030, 0x8fe80018,
+0x1572024, 0x1093024, 0xc41025, 0xafe20018,
+0x9283000a, 0xa3e3001c, 0x96990008, 0x8f8500bc,
+0x8f9800d0, 0xa4b9001e, 0x8e900030, 0x8e840030,
+0xe000213, 0x8f050084, 0x8f8500d0, 0x29140,
+0x29900, 0x90af00bc, 0x2538821, 0x403021,
+0x31e70002, 0x10e00003, 0x2118021, 0x29080,
+0x2128021, 0x90b900bc, 0x33270004, 0x10e00002,
+0x6f880, 0x21f8021, 0x8e980030, 0x8f8b00bc,
+0x24068000, 0x330f0003, 0xf7023, 0x31cd0003,
+0x20d6021, 0xad6c0004, 0x94a400e2, 0x94aa00e2,
+0x94b000e2, 0x31497fff, 0x25220001, 0x30537fff,
+0x2061824, 0x734025, 0xa4a800e2, 0x94a400e2,
+0x3c140800, 0x8e940060, 0x30917fff, 0x12340022,
+0x0, 0xe000cf6, 0x0, 0x8f8700d0,
+0x2821, 0x94f300e0, 0x94f000e2, 0x1213000f,
+0x8fbf0030, 0x90e900d0, 0x90e800d1, 0x313200ff,
+0x310400ff, 0x244302b, 0x14c0ff36, 0x264a0001,
+0x90ee00d2, 0x264b0001, 0x31cd00ff, 0x8d6021,
+0x158bff33, 0x8f9100b0, 0x8fbf0030, 0x8fb7002c,
+0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa01021,
+0x3e00008, 0x27bd0038, 0x94a300e2, 0x664024,
+0xa4a800e2, 0x90a400e2, 0x90b900e2, 0x309100ff,
+0x11a1c2, 0x14f827, 0x1f39c0, 0x3332007f,
+0x2473025, 0xa000de8, 0xa0a600e2, 0x3084ffff,
+0x30a5ffff, 0xaf440018, 0xaf45001c, 0x3e00008,
+0x8f420014, 0x27bdffb8, 0xafb00020, 0x8f9000d0,
+0x3084ffff, 0xafa40010, 0xafbf0044, 0xafbe0040,
+0xafb7003c, 0xafb60038, 0xafb50034, 0xafb40030,
+0xafb3002c, 0xafb20028, 0xafb10024, 0xa7a00018,
+0x920600d1, 0x920500d0, 0x30c400ff, 0x30a300ff,
+0x64102b, 0x10400122, 0xafa00014, 0x920900d0,
+0x8fb50010, 0x312800ff, 0x883823, 0x24f4ffff,
+0x14882b, 0x15982b, 0x2339024, 0x52400126,
+0x8fb40014, 0x961e0012, 0x961f0010, 0x8fb70010,
+0x3dfc823, 0x171400, 0x19c400, 0x22403,
+0x181403, 0x2e2b02a, 0x52c00001, 0x402021,
+0x284282b, 0x10a00002, 0x801821, 0x2801821,
+0x33c00, 0x71c03, 0x3064ffff, 0x2c860009,
+0x14c00002, 0x60b821, 0x24170008, 0x8e0a0008,
+0x176980, 0x8e09000c, 0x31abffff, 0x3c0c0010,
+0x16c4025, 0x27520400, 0xaf4a0038, 0xaf9200b8,
+0xaf49003c, 0xaf480030, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x8f4f0000, 0x31ee0020,
+0x11c0fffd, 0x17982a, 0x2711024, 0xa000e83,
+0xb021, 0x55e00101, 0x92580001, 0x31130080,
+0x126001cf, 0x1202021, 0x96550012, 0x32a5ffff,
+0xe000ccb, 0xa7b50018, 0x8f9000d0, 0x291a023,
+0x26cd0001, 0x8f9100b8, 0xdb400, 0x16b403,
+0x26380040, 0x2d7582a, 0x14882b, 0x24050001,
+0x3009021, 0x1711024, 0xaf9800b8, 0xafa50014,
+0x104001bc, 0x8f8900b0, 0x3c0c0800, 0x8d8c0054,
+0x240bff80, 0x921e00d0, 0x1895021, 0x14b2824,
+0x921900d0, 0xaf450028, 0x8e470010, 0x3c080800,
+0x8d080058, 0x3c180800, 0x8f180054, 0x30e33fff,
+0x32180, 0x1043021, 0x1265821, 0x2402ff80,
+0x162f824, 0x920c00d0, 0xaf5f002c, 0x92480000,
+0x33d100ff, 0x333500ff, 0x3099821, 0x117140,
+0x1578c0, 0x326d007f, 0x1cf3821, 0x1ba2821,
+0x318300ff, 0x3164007f, 0x3c0a000c, 0xaa8821,
+0x367f021, 0x33140, 0x9a1021, 0x3108003f,
+0x3c1f000e, 0xd1c021, 0x5f9821, 0x27d90088,
+0x2d150008, 0xaf9100c0, 0xaf9900ac, 0xaf9800bc,
+0xaf9300b4, 0x12a0018a, 0x8821, 0x240e0001,
+0x10e4004, 0x310d005d, 0x11a0ffb2, 0x310f0002,
+0x8e4a0028, 0x3c030080, 0x3c04ffef, 0xae6a0000,
+0x8e450024, 0xa260000a, 0x3488ffff, 0xae650004,
+0x9247002c, 0x3c1fff9f, 0x37feffff, 0xa267000c,
+0x8e62000c, 0x3c180040, 0xa267000b, 0x433025,
+0xc8c824, 0x33e8824, 0x238a825, 0xae75000c,
+0x8e490004, 0xae600018, 0x3c0f00ff, 0xae690014,
+0x8e4d002c, 0x35eeffff, 0x8f8b00b0, 0x1ae6024,
+0xae6c0010, 0x8e470008, 0xa6600008, 0x96450012,
+0xae670020, 0x8e42000c, 0x30b03fff, 0x105180,
+0xae620024, 0x8e5e0014, 0x14b1821, 0x30a40001,
+0xae7e0028, 0x8e590018, 0x331c2, 0x44380,
+0xae79002c, 0x8e51001c, 0xc8f821, 0xa67f001c,
+0xae710030, 0x96580002, 0x8e550020, 0xa678001e,
+0xae750034, 0x92490033, 0x31300004, 0x56000005,
+0x92500000, 0x8f8c00d0, 0x8d8b007c, 0xae6b0030,
+0x92500000, 0x8f8f00bc, 0xa1f00000, 0x924e0033,
+0x31cd0002, 0x51a00007, 0x925e0001, 0x8f8900bc,
+0x2418ff80, 0x91310000, 0x311a825, 0xa1350000,
+0x925e0001, 0x8f9900bc, 0x2409ffbf, 0x240bffdf,
+0xa33e0001, 0x8f9500bc, 0x92b8000d, 0x3311007f,
+0xa2b1000d, 0x8f8e00bc, 0x91d0000d, 0x2097824,
+0xa1cf000d, 0x8f8800bc, 0x8e6d0014, 0x910a000d,
+0x2dac0001, 0xc2940, 0x14b3824, 0xe51825,
+0xa103000d, 0x96420012, 0x8f8800bc, 0x8f8700d0,
+0xa5020002, 0x8e450004, 0x90ff00bc, 0x30a40003,
+0x43023, 0x30de0003, 0xbe1021, 0x33f90002,
+0x17200002, 0x24440034, 0x24440030, 0x90e200bc,
+0xa23024, 0x30df0004, 0x17e00002, 0x24830004,
+0x801821, 0x8f8f00ac, 0x24090002, 0xad030004,
+0xa1e90000, 0x924e003f, 0x8f8d00ac, 0xa1ae0001,
+0x8f9500ac, 0x924c003f, 0x8e440004, 0xa6ac0002,
+0x976b003c, 0xe000cd6, 0x3170ffff, 0x25380,
+0x20a3825, 0x3c054200, 0xe51825, 0xaea30004,
+0x8f8600ac, 0x8e480038, 0xacc80018, 0x8e440034,
+0xacc4001c, 0xacc0000c, 0xacc00010, 0xa4c00014,
+0xa4c00016, 0xa4c00020, 0xa4c00022, 0xacc00024,
+0x8e640014, 0x50800001, 0x24040001, 0xacc40008,
+0xe000cf6, 0x24110001, 0xa000e76, 0x8f9000d0,
+0x920f00d2, 0x920e00d0, 0x8fb50010, 0x31eb00ff,
+0x31cd00ff, 0x8d6023, 0x16c5021, 0x2554ffff,
+0x14882b, 0x15982b, 0x2339024, 0x1640fedd,
+0x0, 0x8fb40014, 0x8fbf0044, 0x8fbe0040,
+0x3a820001, 0x8fb7003c, 0x8fb60038, 0x8fb50034,
+0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024,
+0x8fb00020, 0x3e00008, 0x27bd0048, 0x33110020,
+0x122000ef, 0x24150001, 0x921e00bc, 0x241f0001,
+0xa821, 0x33d90001, 0x1320000d, 0xafbf001c,
+0x8e440014, 0x8e080084, 0x88102b, 0x14400002,
+0x803021, 0x8e060084, 0x8e030064, 0xc3a82b,
+0x16a00002, 0xc02021, 0x8e040064, 0x80a821,
+0x8e470014, 0x8e050064, 0xe5302b, 0x14c00002,
+0xe02021, 0x8e040064, 0x95f023, 0x13c00004,
+0x8fac001c, 0x240a0002, 0xafaa001c, 0x8fac001c,
+0x28c582b, 0x156000a8, 0x1821, 0x8e4f0038,
+0x8e6d000c, 0x3c0e0080, 0xae6f0000, 0x8e4a0034,
+0x3c10ff9f, 0x1ae5825, 0xae6a0004, 0x9246003f,
+0x360cffff, 0x16c3824, 0x3c050020, 0x3c03ffef,
+0xa266000b, 0xe51025, 0x3468ffff, 0x8f8700b8,
+0x48f824, 0x3c040008, 0x3e4c825, 0xae79000c,
+0x8cf80014, 0xae600018, 0x2be7821, 0xae780014,
+0x8cf10018, 0xae71001c, 0x8ce90008, 0xae690024,
+0x8cee000c, 0xae6f002c, 0xae600028, 0xae6e0020,
+0xa6600038, 0xa660003a, 0x8ced0014, 0x1b58023,
+0x21e9023, 0x12400011, 0xae720010, 0x90ea003d,
+0x8e650004, 0x8e640000, 0xa3100, 0xa6c821,
+0x1021, 0x326402b, 0x82f821, 0x3e8c021,
+0xae790004, 0xae780000, 0x90f1003d, 0xa271000a,
+0x8f8900b8, 0x95320006, 0xa6720008, 0x8f9800ac,
+0x24190002, 0x2a02021, 0xa3190000, 0x9769003c,
+0x8f9200ac, 0xe000cd6, 0x3131ffff, 0x27b80,
+0x8f8500b8, 0x22f6825, 0x3c0e4200, 0x1ae8025,
+0xae500004, 0x8f8400ac, 0x8cac0038, 0xac8c0018,
+0x8cab0034, 0xac8b001c, 0xac80000c, 0xac800010,
+0xa4800014, 0xa4800016, 0xa4800020, 0xa4800022,
+0xac800024, 0x90a7003f, 0xa4870002, 0x12a00135,
+0x24030001, 0x53c00002, 0x90a2003d, 0x90a2003e,
+0x24480001, 0xa0880001, 0x8f9f00ac, 0xaff50008,
+0x8f8300d0, 0x24070034, 0x906600bc, 0x30c50002,
+0x50a00001, 0x24070030, 0x8f9200b8, 0x8f8a00bc,
+0x906d00bc, 0x924b0000, 0x2412c000, 0x32a50003,
+0xa14b0000, 0x8f8600b8, 0x8f8800bc, 0x24020004,
+0x90c40001, 0x451823, 0x30790003, 0xa1040001,
+0x8f8a00bc, 0x8f9f00b8, 0xf53821, 0x95580002,
+0x97e90012, 0xf93821, 0x3128824, 0x312f3fff,
+0x22f7025, 0xa54e0002, 0x91500002, 0x31a80004,
+0x320c003f, 0x358b0040, 0xa14b0002, 0x12a00002,
+0x8f8500bc, 0xe83821, 0x8f8e00d0, 0xaca70004,
+0x240bffbf, 0x8dcd007c, 0x2ea40001, 0x2403ffdf,
+0xacad0008, 0x90b0000d, 0x44140, 0x320c007f,
+0xa0ac000d, 0x8f8600bc, 0x90ca000d, 0x14b1024,
+0xa0c2000d, 0x8f8700bc, 0x90e5000d, 0xa3f824,
+0x3e8c825, 0xa0f9000d, 0x8f9100b8, 0x8f8d00bc,
+0x8e380020, 0xadb80010, 0x8e290024, 0xada90014,
+0x8e2f0028, 0xadaf0018, 0x8e2e002c, 0xe000cf6,
+0xadae001c, 0x8fb0001c, 0x240c0002, 0x120c00ee,
+0x8f9000d0, 0x8fa3001c, 0x608821, 0x14600002,
+0x60a821, 0xa021, 0x56a0fe39, 0x291a023,
+0x14882b, 0x8fa90010, 0x96070010, 0x3c1e0020,
+0x1364023, 0x2c75021, 0x3112ffff, 0xa60a0010,
+0xafb20010, 0xaf5e0030, 0x0, 0x96170010,
+0x96130012, 0x1277008f, 0x0, 0x8e05000c,
+0x8e0b0008, 0x166980, 0xad7021, 0xdc7c3,
+0x1cda82b, 0x1787821, 0x1f56021, 0xae0e000c,
+0xae0c0008, 0x8fb30010, 0x13b82b, 0x2378024,
+0x1200ff04, 0x8f9000d0, 0xa000e3c, 0x0,
+0x8e4d0038, 0xa6600008, 0x240b0003, 0xae6d0000,
+0x8e500034, 0xa260000a, 0x8f9800b8, 0xae700004,
+0x3c050080, 0x9311003f, 0xa26b000c, 0x8e6f000c,
+0x3c0eff9f, 0xa271000b, 0x1e51025, 0x35ccffff,
+0x3c03ffef, 0x8f9200b8, 0x4c3024, 0x3464ffff,
+0xc4f824, 0xae7f000c, 0x8e590014, 0x96480012,
+0x8f8a00b0, 0xae790010, 0x8e490014, 0xae600018,
+0xae600020, 0xae690014, 0xae600024, 0x8e470018,
+0x31093fff, 0x9f180, 0xae670028, 0x8e4d0008,
+0x3ca8021, 0x31180001, 0xae6d0030, 0x8e4f000c,
+0x8f8c00ac, 0x1089c2, 0x185b80, 0x22b2821,
+0x240e0002, 0xa665001c, 0xa6600036, 0xae6f002c,
+0xa18e0000, 0x9763003c, 0x8f8a00ac, 0x3c044200,
+0x3062ffff, 0x443025, 0xad460004, 0x8f9f00b8,
+0x24070001, 0x2411c000, 0x8ff30038, 0x24060034,
+0xad530018, 0x8ff90034, 0xad59001c, 0xad40000c,
+0xad400010, 0xa5400014, 0xa5400016, 0xa5400020,
+0xa5400022, 0xad400024, 0xa5550002, 0xa1470001,
+0x8f9e00ac, 0x8f8800b8, 0x8f9200bc, 0xafd50008,
+0x910d0000, 0xa24d0000, 0x8f9000b8, 0x8f8b00bc,
+0x92180001, 0xa1780001, 0x8f8400bc, 0x94850002,
+0xb17824, 0x1e97025, 0xa48e0002, 0x908c0002,
+0x3183003f, 0xa0830002, 0x8f8300d0, 0x8f8400bc,
+0x906200bc, 0x30530002, 0x52600001, 0x24060030,
+0xac860004, 0x8c6f007c, 0x2403ffbf, 0x2a08821,
+0xac8f0008, 0x908e000d, 0x31cc007f, 0xa08c000d,
+0x8f8600bc, 0x90c2000d, 0x432024, 0xa0c4000d,
+0x8f8900bc, 0x913f000d, 0x37f90020, 0xa139000d,
+0x8f8800b8, 0x8f9300bc, 0x8d070020, 0xae670010,
+0x8d0a0024, 0xae6a0014, 0x8d1e0028, 0xae7e0018,
+0x8d12002c, 0xe000cf6, 0xae72001c, 0xa00103d,
+0x8f9000d0, 0x960e0014, 0x8e030004, 0x31ccffff,
+0xc10c0, 0x622021, 0xaf44003c, 0x8e1f0004,
+0x8f46003c, 0x3e6c823, 0x1b20003c, 0x0,
+0x8e0f0000, 0x25e20001, 0x3c050010, 0x34b50008,
+0xaf420038, 0xaf550030, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x8f580000, 0x330b0020,
+0x1160fffd, 0x0, 0x8f530400, 0x3c0d0020,
+0xae130008, 0x8f570404, 0xae17000c, 0xaf4d0030,
+0x0, 0x3c060800, 0x8cc60044, 0x24160001,
+0x10d600bd, 0x0, 0x961f0012, 0x3c050800,
+0x8ca50040, 0xbfc821, 0xa6190012, 0x96090014,
+0x25270001, 0xa6070014, 0x960a0014, 0x3144ffff,
+0x5486ff49, 0x8fb30010, 0xa6000014, 0xe000e16,
+0x30a5ffff, 0x3c040800, 0x8c840024, 0x96030012,
+0x441023, 0x623023, 0xa6060012, 0xa001059,
+0x8fb30010, 0xa0830001, 0x8f8200ac, 0x24040001,
+0xac440008, 0xa000ff0, 0x8f8300d0, 0x8e020000,
+0xa0010ea, 0x3c050010, 0x8f8200c0, 0x8fa7001c,
+0x921800d0, 0x920b00d0, 0x920e00d0, 0x331100ff,
+0x316900ff, 0x117940, 0x928c0, 0x1e56021,
+0x31c300ff, 0x36c5021, 0x33140, 0xc2c821,
+0x255f0088, 0xaf9f00ac, 0xaf9900bc, 0xa1470088,
+0x9768003c, 0x3c02021, 0x8f9100ac, 0xe000cd6,
+0x3110ffff, 0x26b80, 0x20dc025, 0x3c044200,
+0x8f8d00b8, 0x3045825, 0xae2b0004, 0x8da90038,
+0x8f8b00ac, 0x8821, 0x118100, 0xad690018,
+0x8daf0034, 0x3c087fff, 0x3504ffff, 0xad6f001c,
+0x91ac003e, 0x8d65001c, 0x8d660018, 0xc1900,
+0xc7702, 0xa33821, 0x20e1025, 0xe3f82b,
+0xc2c821, 0x33f5021, 0xad67001c, 0xad6a0018,
+0xad60000c, 0xad600010, 0x91b8003e, 0x24050005,
+0x3c45024, 0xa5780014, 0x95a90004, 0x3c02021,
+0xa5690016, 0x91af003e, 0xa56f0020, 0x95b10004,
+0xa5710022, 0xad600024, 0x91ae003f, 0xa56e0002,
+0x91b0003e, 0x91ac003d, 0x1901023, 0x24430001,
0xa1630001, 0x8f8600ac, 0x8f9f00bc, 0xacde0008,
0xa3e50000, 0x8f9000bc, 0x8f9900b8, 0x2405ffbf,
0x96070002, 0x97380012, 0x2477824, 0x33093fff,
@@ -5658,15 +5662,15 @@ u32 bce_CP_b06FwText[(0x56cc/4) + 1] = {
0x8f8500bc, 0x8f8300b8, 0x8cab0018, 0x16c1024,
0x4a3025, 0xaca60018, 0x9068003e, 0xa0a8001c,
0x8f9f00b8, 0x8f8700bc, 0x8f9800d0, 0x97f90004,
-0xa4f9001e, 0xe000203, 0x8f050084, 0x8f8600d0,
+0xa4f9001e, 0xe000213, 0x8f050084, 0x8f8600d0,
0x27940, 0x24900, 0x90d200bc, 0x1e98821,
0x402821, 0x32550002, 0x12a00003, 0x3d12021,
-0x2a880, 0x952021, 0x90cc00bc, 0x31920004,
-0x12400003, 0x33c90003, 0x54080, 0x882021,
-0x24190004, 0x8f9e00bc, 0x3293823, 0x30f80003,
-0x985021, 0xafca0004, 0xe000d05, 0xa6650038,
-0xa001047, 0x8f9000d0, 0x960a0012, 0x3c1e0800,
-0x8fde0024, 0x3ca9021, 0xa6120012, 0xa001067,
+0x2a880, 0x952021, 0x90cd00bc, 0x31b20004,
+0x12400003, 0x33df0003, 0x54080, 0x882021,
+0x24060004, 0x8f9e00bc, 0xdfc823, 0x33270003,
+0x875021, 0xafca0004, 0xe000cf6, 0xa6650038,
+0xa001038, 0x8f9000d0, 0x961e0012, 0x3c080800,
+0x8d080024, 0x11e9021, 0xa6120012, 0xa001059,
0x8fb30010, 0x27bdffe0, 0x3c180800, 0x8f180050,
0xafb00010, 0xafbf0018, 0xafb10014, 0xaf8400b0,
0x93710074, 0x3047821, 0x2410ff80, 0x31ee007f,
@@ -5678,30 +5682,30 @@ u32 bce_CP_b06FwText[(0x56cc/4) + 1] = {
0x1ae6024, 0x318b00ff, 0x116a002f, 0x0,
0x16000007, 0x241f0c00, 0xaf5f0024, 0x8fb10014,
0x8fbf0018, 0x8fb00010, 0x3e00008, 0x27bd0020,
-0xe000e2b, 0x2002021, 0x241f0c00, 0xaf5f0024,
+0xe000e1c, 0x2002021, 0x241f0c00, 0xaf5f0024,
0x8fb10014, 0x8fbf0018, 0x8fb00010, 0x3e00008,
0x27bd0020, 0x94a200e0, 0x94a400e2, 0x90bf0113,
0x821826, 0x3079ffff, 0x33e700c0, 0x14e00009,
0x2f310001, 0x16000038, 0x0, 0x5620ffe6,
-0x241f0c00, 0xe000d27, 0x0, 0xa0011f9,
-0x241f0c00, 0x1620ffde, 0x0, 0xe000d27,
+0x241f0c00, 0xe000d18, 0x0, 0xa0011ed,
+0x241f0c00, 0x1620ffde, 0x0, 0xe000d18,
0x0, 0x1440ffdc, 0x241f0c00, 0x16000022,
0x8f8300d0, 0x90690113, 0x3122003f, 0xa0620113,
-0xa0011f9, 0x241f0c00, 0x94af00d4, 0x8f8600d4,
-0xe02821, 0x24040005, 0xe000c6b, 0x31f0ffff,
+0xa0011ed, 0x241f0c00, 0x94af00d4, 0x8f8600d4,
+0xe02821, 0x24040005, 0xe000c5c, 0x31f0ffff,
0x14400005, 0x24030003, 0x979100e6, 0x1821,
0x2625ffff, 0xa78500e6, 0x8f5801b8, 0x700fffe,
0x3c196013, 0xaf400180, 0x241f0c00, 0xaf500184,
0x793825, 0x3c101000, 0xaf470188, 0x8fb10014,
0xaf5001b8, 0xaf5f0024, 0x8fb00010, 0x8fbf0018,
-0x3e00008, 0x27bd0020, 0xe000e2b, 0x2002021,
+0x3e00008, 0x27bd0020, 0xe000e1c, 0x2002021,
0x5040ffb5, 0x241f0c00, 0x8f8300d0, 0x90690113,
-0xa001222, 0x3122003f, 0xe000e2b, 0x2002021,
+0xa001216, 0x3122003f, 0xe000e1c, 0x2002021,
0x1440ffad, 0x241f0c00, 0x12200007, 0x8f8300d0,
0x90680113, 0x3106003f, 0x34c20040, 0xa0620113,
-0xa0011f9, 0x241f0c00, 0xe000d27, 0x0,
+0xa0011ed, 0x241f0c00, 0xe000d18, 0x0,
0x5040ffa1, 0x241f0c00, 0x8f8300d0, 0x90680113,
-0x3106003f, 0xa001252, 0x34c20040, 0xaf9b00c8,
+0x3106003f, 0xa001246, 0x34c20040, 0xaf9b00c8,
0x3e00008, 0xaf8000ec, 0x3089ffff, 0x94042,
0x2d020041, 0x92980, 0x14400002, 0x95040,
0x24080040, 0x87940, 0x8c0c0, 0x1f85821,
@@ -5742,285 +5746,258 @@ u32 bce_CP_b06FwText[(0x56cc/4) + 1] = {
0x3c0c0800, 0x8d8c0050, 0x240bff80, 0x8ccd0008,
0x3c03000c, 0xd51c0, 0x18a4021, 0x10b4824,
0xaf8a00e8, 0xaf490028, 0x90c70007, 0x3105007f,
-0xba1021, 0x432821, 0x30e40004, 0x1080002f,
-0xaf8500d0, 0x90cf0007, 0x31ee0008, 0x11c0003c,
+0xba1021, 0x432821, 0x30e40004, 0x10800039,
+0xaf8500d0, 0x90cf0007, 0x31ee0008, 0x11c00038,
0x0, 0x8cd9000c, 0x8cc40014, 0x324c02b,
-0x13000026, 0x0, 0x8cc2000c, 0xaca20064,
+0x13000030, 0x0, 0x8cc2000c, 0xaca20064,
0x8ccd0018, 0x2402fff8, 0xacad0068, 0x8ccc0010,
0xacac0080, 0x8ccb000c, 0xacab0084, 0x8cca001c,
0xacaa007c, 0x90a900bc, 0x1224024, 0xa0a800bc,
0x90c30007, 0x30670008, 0x10e00004, 0x8f8500d0,
0x90af00bc, 0x35ee0001, 0xa0ae00bc, 0x90d90007,
-0x33380001, 0x1300000f, 0x8f8400d0, 0x24070020,
-0x908200bc, 0x34490002, 0xa08900bc, 0x8f8400d0,
-0x90880062, 0x310300f0, 0x14670006, 0x240a0034,
-0xac8a00c0, 0xa001334, 0x0, 0xa00130e,
-0x8cc20014, 0x90cb0007, 0x31660002, 0x10c00005,
-0x0, 0x908d00bc, 0x35ac0004, 0xa08c00bc,
-0x8f8400d0, 0x90980113, 0x330f003f, 0xa08f0113,
-0x8f8e00d0, 0x95c500d4, 0x3e00008, 0x30a2ffff,
-0xaca00064, 0xa00130f, 0x0, 0x27bdffd8,
-0xafb00010, 0x8f90001c, 0xafbf0024, 0xafb40020,
-0xafb20018, 0xafb10014, 0xafb3001c, 0x9613000e,
-0x3c07600a, 0x3c146006, 0x3264ffff, 0x36930010,
-0xe001261, 0x34f40410, 0x8f8400d4, 0x3c11600e,
-0xe0009aa, 0x36310010, 0x920e0015, 0x3c070800,
-0x8ce70060, 0x3c126012, 0x31cd000f, 0xa38d00f0,
-0x8e0e0004, 0x8e0d0008, 0x96080012, 0x961f0010,
-0x9619001a, 0x9618001e, 0x960f001c, 0x310cffff,
-0x33ebffff, 0x332affff, 0x3309ffff, 0x31e6ffff,
-0x3c010800, 0xac2b0040, 0x3c010800, 0xac2c0024,
-0x3c010800, 0xac2a0044, 0xae293178, 0xae26317c,
-0x92020015, 0x96030016, 0x36520010, 0x304400ff,
-0x3065ffff, 0x3c060800, 0x8cc60064, 0xae243188,
-0xae4500b4, 0x92080014, 0x96190018, 0x241f0001,
-0x11fc004, 0x332fffff, 0x3c050800, 0x8ca50058,
-0xae5800b8, 0xae4f00bc, 0x920c0014, 0xaf8e00d8,
-0xaf8d00dc, 0x318b00ff, 0xae4b00c0, 0x920a0015,
-0xae670048, 0xae66004c, 0x314900ff, 0xae4900c8,
-0xae65007c, 0x3c030800, 0x8c630050, 0x3c040800,
-0x8c84004c, 0x3c080800, 0x8d080054, 0x3c020800,
-0x8c42005c, 0x8fbf0024, 0xae630080, 0x8fb00010,
-0xae830074, 0x8fb3001c, 0xae22319c, 0xae4200dc,
-0xae2731a0, 0xae2631a4, 0xae24318c, 0xae233190,
-0xae283194, 0xae253198, 0xae870050, 0xae860054,
-0xae850070, 0x8fb10014, 0xae4700e0, 0xae4600e4,
-0xae4400cc, 0xae4300d0, 0xae4800d4, 0xae4500d8,
-0x8fb40020, 0x8fb20018, 0x3e00008, 0x27bd0028,
-0x27bdffe0, 0xafb10014, 0xafbf0018, 0x24110001,
-0xe000854, 0xafb00010, 0x10510005, 0x978400e6,
-0x978300cc, 0x83102b, 0x14400008, 0x8f8500d4,
-0x24070002, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0xe01021, 0x3e00008, 0x27bd0020, 0xe000c89,
-0x24040005, 0xaf8200e8, 0x1040fff6, 0x24070002,
-0xe000858, 0x8f90001c, 0x979f00e6, 0x8f9900e8,
-0x8f8d00c8, 0x27ef0001, 0x240e0050, 0xaf590020,
-0xa78f00e6, 0xa1ae0000, 0x3c0c0800, 0x8d8c0064,
-0x8f8600c8, 0x240a8000, 0xc5e00, 0xaccb0074,
-0xa4c00006, 0x94c9000a, 0x241fff80, 0x3c0d000c,
-0x12ac024, 0xa4d8000a, 0x90c8000a, 0x24182000,
-0x11f1825, 0xa0c3000a, 0x8f8700c8, 0xa0e00078,
-0x8f8500c8, 0x3821, 0xa0a00083, 0x3c020800,
-0x8c420050, 0x8f8400e8, 0x447821, 0x1ffc824,
-0xaf590028, 0x960b0002, 0x31ee007f, 0x1da6021,
-0x18d3021, 0xa4cb00d4, 0x960a0002, 0xaf8600d0,
-0x3c0e0004, 0x25492401, 0xa4c900e6, 0x8e080004,
-0xacc80004, 0x8e030008, 0xacc30000, 0xa4c00010,
-0xa4c00014, 0xa0c000d0, 0x8f8500d0, 0x2403ffbf,
-0xa0a000d1, 0x3c040800, 0x8c840064, 0x8f8200d0,
-0xa04400d2, 0x8e1f000c, 0x8f8a00d0, 0x978f00e4,
-0xad5f001c, 0x8e190010, 0x24100030, 0xad590018,
-0xa5400030, 0xa5510054, 0xa5510056, 0xa54f0016,
-0xad4e0068, 0xad580080, 0xad580084, 0x914d0062,
-0x31ac000f, 0x358b0010, 0xa14b0062, 0x8f8600d0,
-0x90c90063, 0x3128007f, 0xa0c80063, 0x8f8400d0,
-0x2406ffff, 0x90850063, 0xa31024, 0xa0820063,
-0x8f9100d0, 0xe01021, 0x923f00bc, 0x37f90001,
-0xa23900bc, 0x8f8a00d0, 0x938f00f0, 0xad580064,
-0xad5000c0, 0x914e00d3, 0xf6900, 0x31cc000f,
-0x18d5825, 0xa14b00d3, 0x8f8500d0, 0x8f8900dc,
-0xaca900e8, 0x8f8800d8, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x27bd0020, 0xaca800ec, 0xa4a600d6,
-0xa4a000e0, 0xa4a000e2, 0x3e00008, 0x0,
-0x27bdffe0, 0xafb00010, 0x8f90001c, 0xafb10014,
-0xafbf0018, 0x8e190004, 0x3c180800, 0x8f180050,
-0x240fff80, 0x1989c0, 0x2387021, 0x31cd007f,
-0x1cf6024, 0x1ba5021, 0x3c0b000c, 0xaf4c0028,
-0x14b4021, 0x950900d4, 0x950400d6, 0x8e070004,
-0x3131ffff, 0xaf8800d0, 0xe000922, 0x721c0,
-0x8e060004, 0x8f8300c8, 0x629c0, 0xaf450020,
-0x9064003e, 0x30820040, 0x14400006, 0x8f8400d0,
-0x341fffff, 0x948300d6, 0x3062ffff, 0x145f0004,
-0x0, 0x948400d6, 0xe0008b7, 0x3084ffff,
-0x8e050004, 0x2203021, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x24040022, 0x3821, 0x529c0,
-0xa001285, 0x27bd0020, 0x27bdffe0, 0xafb10014,
-0x3091ffff, 0xafb00010, 0xafbf0018, 0x1220001d,
-0x8021, 0x8f86001c, 0x8cc50000, 0x24030006,
-0x53f02, 0x51402, 0x30e40007, 0x14830015,
-0x304500ff, 0x2ca80006, 0x1100004d, 0x55880,
-0x3c0c0800, 0x258c57e8, 0x16c5021, 0x8d490000,
-0x1200008, 0x0, 0x8f8e00ec, 0x240d0001,
-0x11cd0059, 0x0, 0x260b0001, 0x3170ffff,
-0x24ca0020, 0x211202b, 0x1403021, 0x1480ffe6,
-0xaf8a001c, 0x2001021, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0020, 0x938700ce,
-0x14e00038, 0x24040014, 0xe001346, 0x0,
-0x8f86001c, 0x24020001, 0xa00148d, 0xaf8200ec,
-0x8f8900ec, 0x24080002, 0x1128003b, 0x24040013,
-0x2821, 0x3021, 0x24070001, 0xe001285,
-0x0, 0xa00148d, 0x8f86001c, 0x8f8700ec,
-0x24050002, 0x14e5fff6, 0x24040012, 0xe0012f2,
-0x0, 0x8f8500e8, 0x403021, 0x24040012,
-0xe001285, 0x3821, 0xa00148d, 0x8f86001c,
-0x8f8300ec, 0x241f0003, 0x147fffd0, 0x260b0001,
-0xe0012a4, 0x0, 0x8f8500e8, 0x403021,
-0x24020002, 0x24040010, 0x3821, 0xaf8200ec,
-0xe001285, 0x0, 0xa00148d, 0x8f86001c,
-0x8f8f00ec, 0x24060002, 0x11e6000b, 0x0,
-0x24040010, 0x2821, 0x3021, 0xa0014aa,
-0x24070001, 0x2821, 0xe001285, 0x3021,
-0xa00148d, 0x8f86001c, 0xe0013b3, 0x0,
-0x14400012, 0x8f99001c, 0x8f86001c, 0x24020003,
-0xa00148d, 0xaf8200ec, 0xe00143f, 0x0,
-0xa00148d, 0x8f86001c, 0xe001294, 0x0,
-0x24020002, 0x24040014, 0x2821, 0x3021,
-0x3821, 0xa0014c7, 0xaf8200ec, 0x403821,
-0x24040010, 0x97380002, 0x2821, 0xe001285,
-0x3306ffff, 0xa00148d, 0x8f86001c, 0x8f8400c8,
-0x3c077fff, 0x34e6ffff, 0x8c850074, 0x24020001,
-0xa61824, 0xac830074, 0x3e00008, 0xa0820005,
-0x10a00036, 0x2ca20080, 0x274a0400, 0x3c0b0005,
-0x24090080, 0x10400007, 0x24080080, 0x30a6000f,
-0xc54021, 0x2d030081, 0x14600002, 0xa04821,
-0x24080080, 0xaf4b0030, 0x0, 0x0,
-0x0, 0x11000009, 0x3821, 0x1403021,
-0x8c8d0000, 0x24e70004, 0xe8602b, 0xaccd0000,
-0x24840004, 0x1580fffa, 0x24c60004, 0x0,
-0x0, 0x0, 0x3c0e0006, 0x10e3825,
-0xaf470030, 0x0, 0x0, 0x0,
-0x8f4f0000, 0x31e80010, 0x1100fffd, 0x0,
-0x8f42003c, 0x8f43003c, 0x49c821, 0x323c02b,
-0x13000004, 0x0, 0x8f4c0038, 0x25860001,
-0xaf460038, 0x8f47003c, 0xa92823, 0xe96821,
-0xaf4d003c, 0x14a0ffce, 0x2ca20080, 0x3e00008,
-0x0, 0x27bdffd0, 0x3c020002, 0xafb10014,
-0x3c11000c, 0xaf450038, 0xafb3001c, 0xaf46003c,
-0x809821, 0xaf420030, 0x24050088, 0xaf440028,
-0x3512021, 0xafbf0028, 0xafb50024, 0xafb40020,
-0xafb20018, 0xe0014ff, 0xafb00010, 0x3c1f0800,
-0x8fff004c, 0x3c180800, 0x8f180064, 0x2410ff80,
-0x3f3a821, 0x32b9007f, 0x2b07824, 0x18a0c0,
-0x33a7021, 0x189140, 0x1d12021, 0xaf4f0028,
-0xe0014ff, 0x2542821, 0x3c0d0800, 0x8dad0050,
-0x24050120, 0x1b35821, 0x316c007f, 0x1705024,
-0x19a4821, 0x1312021, 0xe0014ff, 0xaf4a0028,
-0x3c080800, 0x8d080054, 0x3c050800, 0x8ca50064,
-0x1133821, 0x30e6007f, 0xf01824, 0xda2021,
-0x912021, 0xaf430028, 0xe0014ff, 0x52940,
-0x3c020800, 0x8c420058, 0x3c100800, 0x8e100060,
-0x1200001c, 0x538821, 0x2415ff80, 0xa001582,
-0x3c14000c, 0x3226007f, 0x2351824, 0xda2021,
-0x2402821, 0xaf430028, 0x942021, 0xe0014ff,
-0x2610ffc0, 0x1200000f, 0x2328821, 0x2e050041,
-0x10a0fff4, 0x24121000, 0x3226007f, 0x109180,
-0x2351824, 0xda2021, 0x2402821, 0xaf430028,
-0x942021, 0xe0014ff, 0x8021, 0x1600fff3,
-0x2328821, 0x3c0b0800, 0x8d6b005c, 0x240aff80,
-0x24050002, 0x1734021, 0x10a4824, 0xaf490028,
-0x3c040800, 0x94840062, 0x3110007f, 0x21a8821,
-0x3c07000c, 0xe000cb9, 0x2279821, 0x402821,
-0x2602021, 0x8fbf0028, 0x8fb50024, 0x8fb40020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0xa0014ff, 0x27bd0030, 0x8f83001c, 0x8c620004,
-0x10400003, 0x0, 0x3e00008, 0x0,
-0x8c640010, 0x8c650008, 0xa001538, 0x8c66000c,
-0x0 };
-u32 bce_CP_b06FwData[(0x84/4) + 1] = {
-0x0,
-0x1b, 0xf, 0xa, 0x8,
-0x6, 0x5, 0x5, 0x4,
-0x4, 0x3, 0x3, 0x3,
-0x3, 0x3, 0x2, 0x2,
+0x33380001, 0x13000008, 0x8f8300d0, 0x8f8700d0,
+0x24040034, 0x90e800bc, 0x35030002, 0xa0e300bc,
+0x8f8300d0, 0xac6400c0, 0x90c90007, 0x31260002,
+0x10c00005, 0x0, 0x906a00bc, 0x35420004,
+0xa06200bc, 0x8f8300d0, 0x90650113, 0x30ad003f,
+0xa06d0113, 0x8f8c00d0, 0x958b00d4, 0x3e00008,
+0x3162ffff, 0x8cc20014, 0xa001302, 0x0,
+0xa001303, 0xaca00064, 0x27bdffd8, 0xafb00010,
+0x8f90001c, 0xafbf0024, 0xafb40020, 0xafb20018,
+0xafb10014, 0xafb3001c, 0x9613000e, 0x3c07600a,
+0x3c146006, 0x3264ffff, 0x36930010, 0xe001255,
+0x34f40410, 0x8f8400d4, 0x3c11600e, 0xe00099b,
+0x36310010, 0x920e0015, 0x3c070800, 0x8ce70060,
+0x3c126012, 0x31cd000f, 0xa38d00f0, 0x8e0e0004,
+0x8e0d0008, 0x96080012, 0x961f0010, 0x9619001a,
+0x9618001e, 0x960f001c, 0x310cffff, 0x33ebffff,
+0x332affff, 0x3309ffff, 0x31e6ffff, 0x3c010800,
+0xac2b0040, 0x3c010800, 0xac2c0024, 0x3c010800,
+0xac2a0044, 0xae293178, 0xae26317c, 0x92020015,
+0x96030016, 0x36520010, 0x304400ff, 0x3065ffff,
+0x3c060800, 0x8cc60064, 0xae243188, 0xae4500b4,
+0x92080014, 0x96190018, 0x241f0001, 0x11fc004,
+0x332fffff, 0x3c050800, 0x8ca50058, 0xae5800b8,
+0xae4f00bc, 0x920c0014, 0xaf8e00d8, 0xaf8d00dc,
+0x318b00ff, 0xae4b00c0, 0x920a0015, 0xae670048,
+0xae66004c, 0x314900ff, 0xae4900c8, 0xae65007c,
+0x3c030800, 0x8c630050, 0x3c040800, 0x8c84004c,
+0x3c080800, 0x8d080054, 0x3c020800, 0x8c42005c,
+0x8fbf0024, 0xae630080, 0x8fb00010, 0xae830074,
+0x8fb3001c, 0xae22319c, 0xae4200dc, 0xae2731a0,
+0xae2631a4, 0xae24318c, 0xae233190, 0xae283194,
+0xae253198, 0xae870050, 0xae860054, 0xae850070,
+0x8fb10014, 0xae4700e0, 0xae4600e4, 0xae4400cc,
+0xae4300d0, 0xae4800d4, 0xae4500d8, 0x8fb40020,
+0x8fb20018, 0x3e00008, 0x27bd0028, 0x27bdffe0,
+0xafb10014, 0xafbf0018, 0x24110001, 0xe000845,
+0xafb00010, 0x10510005, 0x978400e6, 0x978300cc,
+0x83102b, 0x14400008, 0x8f8500d4, 0x24070002,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0xe01021,
+0x3e00008, 0x27bd0020, 0xe000c7a, 0x24040005,
+0xaf8200e8, 0x1040fff6, 0x24070002, 0xe000849,
+0x8f90001c, 0x979f00e6, 0x8f9900e8, 0x8f8d00c8,
+0x27ef0001, 0x240e0050, 0xaf590020, 0xa78f00e6,
+0xa1ae0000, 0x3c0c0800, 0x8d8c0064, 0x8f8600c8,
+0x240a8000, 0xc5e00, 0xaccb0074, 0xa4c00006,
+0x94c9000a, 0x241fff80, 0x3c0d000c, 0x12ac024,
+0xa4d8000a, 0x90c8000a, 0x24182000, 0x11f1825,
+0xa0c3000a, 0x8f8700c8, 0xa0e00078, 0x8f8500c8,
+0x3821, 0xa0a00083, 0x3c020800, 0x8c420050,
+0x8f8400e8, 0x447821, 0x1ffc824, 0xaf590028,
+0x960b0002, 0x31ee007f, 0x1da6021, 0x18d3021,
+0xa4cb00d4, 0x960a0002, 0xaf8600d0, 0x3c0e0004,
+0x25492401, 0xa4c900e6, 0x8e080004, 0xacc80004,
+0x8e030008, 0xacc30000, 0xa4c00010, 0xa4c00014,
+0xa0c000d0, 0x8f8500d0, 0x2403ffbf, 0xa0a000d1,
+0x3c040800, 0x8c840064, 0x8f8200d0, 0xa04400d2,
+0x8e1f000c, 0x8f8a00d0, 0x978f00e4, 0xad5f001c,
+0x8e190010, 0x24100030, 0xad590018, 0xa5400030,
+0xa5510054, 0xa5510056, 0xa54f0016, 0xad4e0068,
+0xad580080, 0xad580084, 0x914d0062, 0x31ac000f,
+0x358b0010, 0xa14b0062, 0x8f8600d0, 0x90c90063,
+0x3128007f, 0xa0c80063, 0x8f8400d0, 0x2406ffff,
+0x90850063, 0xa31024, 0xa0820063, 0x8f9100d0,
+0xe01021, 0x923f00bc, 0x37f90001, 0xa23900bc,
+0x8f8a00d0, 0x938f00f0, 0xad580064, 0xad5000c0,
+0x914e00d3, 0xf6900, 0x31cc000f, 0x18d5825,
+0xa14b00d3, 0x8f8500d0, 0x8f8900dc, 0xaca900e8,
+0x8f8800d8, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x27bd0020, 0xaca800ec, 0xa4a600d6, 0xa4a000e0,
+0xa4a000e2, 0x3e00008, 0x0, 0x27bdffe0,
+0xafb00010, 0x8f90001c, 0xafb10014, 0xafbf0018,
+0x8e190004, 0x3c180800, 0x8f180050, 0x240fff80,
+0x1989c0, 0x2387021, 0x31cd007f, 0x1cf6024,
+0x1ba5021, 0x3c0b000c, 0xaf4c0028, 0x14b4021,
+0x950900d4, 0x950400d6, 0x8e070004, 0x3131ffff,
+0xaf8800d0, 0xe000913, 0x721c0, 0x8e060004,
+0x8f8300c8, 0x629c0, 0xaf450020, 0x9064003e,
+0x30820040, 0x14400006, 0x8f8400d0, 0x341fffff,
+0x948300d6, 0x3062ffff, 0x145f0004, 0x0,
+0x948400d6, 0xe0008a8, 0x3084ffff, 0x8e050004,
+0x2203021, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x24040022, 0x3821, 0x529c0, 0xa001279,
+0x27bd0020, 0x27bdffe0, 0xafb10014, 0x3091ffff,
+0xafb00010, 0xafbf0018, 0x1220001d, 0x8021,
+0x8f86001c, 0x8cc50000, 0x24030006, 0x53f02,
+0x51402, 0x30e40007, 0x14830015, 0x304500ff,
+0x2ca80006, 0x1100004d, 0x55880, 0x3c0c0800,
+0x258c57c8, 0x16c5021, 0x8d490000, 0x1200008,
+0x0, 0x8f8e00ec, 0x240d0001, 0x11cd0059,
+0x0, 0x260b0001, 0x3170ffff, 0x24ca0020,
+0x211202b, 0x1403021, 0x1480ffe6, 0xaf8a001c,
+0x2001021, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0020, 0x938700ce, 0x14e00038,
+0x24040014, 0xe001335, 0x0, 0x8f86001c,
+0x24020001, 0xa00147c, 0xaf8200ec, 0x8f8900ec,
+0x24080002, 0x1128003b, 0x24040013, 0x2821,
+0x3021, 0x24070001, 0xe001279, 0x0,
+0xa00147c, 0x8f86001c, 0x8f8700ec, 0x24050002,
+0x14e5fff6, 0x24040012, 0xe0012e6, 0x0,
+0x8f8500e8, 0x403021, 0x24040012, 0xe001279,
+0x3821, 0xa00147c, 0x8f86001c, 0x8f8300ec,
+0x241f0003, 0x147fffd0, 0x260b0001, 0xe001298,
+0x0, 0x8f8500e8, 0x403021, 0x24020002,
+0x24040010, 0x3821, 0xaf8200ec, 0xe001279,
+0x0, 0xa00147c, 0x8f86001c, 0x8f8f00ec,
+0x24060002, 0x11e6000b, 0x0, 0x24040010,
+0x2821, 0x3021, 0xa001499, 0x24070001,
+0x2821, 0xe001279, 0x3021, 0xa00147c,
+0x8f86001c, 0xe0013a2, 0x0, 0x14400012,
+0x8f99001c, 0x8f86001c, 0x24020003, 0xa00147c,
+0xaf8200ec, 0xe00142e, 0x0, 0xa00147c,
+0x8f86001c, 0xe001288, 0x0, 0x24020002,
+0x24040014, 0x2821, 0x3021, 0x3821,
+0xa0014b6, 0xaf8200ec, 0x403821, 0x24040010,
+0x97380002, 0x2821, 0xe001279, 0x3306ffff,
+0xa00147c, 0x8f86001c, 0x8f8400c8, 0x3c077fff,
+0x34e6ffff, 0x8c850074, 0x24020001, 0xa61824,
+0xac830074, 0x3e00008, 0xa0820005, 0x10a00036,
+0x2ca20080, 0x274a0400, 0x3c0b0005, 0x24090080,
+0x10400007, 0x24080080, 0x30a6000f, 0xc54021,
+0x2d030081, 0x14600002, 0xa04821, 0x24080080,
+0xaf4b0030, 0x0, 0x0, 0x0,
+0x11000009, 0x3821, 0x1403021, 0x8c8d0000,
+0x24e70004, 0xe8602b, 0xaccd0000, 0x24840004,
+0x1580fffa, 0x24c60004, 0x0, 0x0,
+0x0, 0x3c0e0006, 0x10e3825, 0xaf470030,
+0x0, 0x0, 0x0, 0x8f4f0000,
+0x31e80010, 0x1100fffd, 0x0, 0x8f42003c,
+0x8f43003c, 0x49c821, 0x323c02b, 0x13000004,
+0x0, 0x8f4c0038, 0x25860001, 0xaf460038,
+0x8f47003c, 0xa92823, 0xe96821, 0xaf4d003c,
+0x14a0ffce, 0x2ca20080, 0x3e00008, 0x0,
+0x27bdffd0, 0x3c020002, 0xafb10014, 0x3c11000c,
+0xaf450038, 0xafb3001c, 0xaf46003c, 0x809821,
+0xaf420030, 0x24050088, 0xaf440028, 0x3512021,
+0xafbf0028, 0xafb50024, 0xafb40020, 0xafb20018,
+0xe0014ee, 0xafb00010, 0x3c1f0800, 0x8fff004c,
+0x3c180800, 0x8f180064, 0x2410ff80, 0x3f3a821,
+0x32b9007f, 0x2b07824, 0x18a0c0, 0x33a7021,
+0x189140, 0x1d12021, 0xaf4f0028, 0xe0014ee,
+0x2542821, 0x3c0d0800, 0x8dad0050, 0x24050120,
+0x1b35821, 0x316c007f, 0x1705024, 0x19a4821,
+0x1312021, 0xe0014ee, 0xaf4a0028, 0x3c080800,
+0x8d080054, 0x3c050800, 0x8ca50064, 0x1133821,
+0x30e6007f, 0xf01824, 0xda2021, 0x912021,
+0xaf430028, 0xe0014ee, 0x52940, 0x3c020800,
+0x8c420058, 0x3c100800, 0x8e100060, 0x1200001c,
+0x538821, 0x2415ff80, 0xa001571, 0x3c14000c,
+0x3226007f, 0x2351824, 0xda2021, 0x2402821,
+0xaf430028, 0x942021, 0xe0014ee, 0x2610ffc0,
+0x1200000f, 0x2328821, 0x2e050041, 0x10a0fff4,
+0x24121000, 0x3226007f, 0x109180, 0x2351824,
+0xda2021, 0x2402821, 0xaf430028, 0x942021,
+0xe0014ee, 0x8021, 0x1600fff3, 0x2328821,
+0x3c0b0800, 0x8d6b005c, 0x240aff80, 0x24050002,
+0x1734021, 0x10a4824, 0xaf490028, 0x3c040800,
+0x94840062, 0x3110007f, 0x21a8821, 0x3c07000c,
+0xe000caa, 0x2279821, 0x402821, 0x2602021,
+0x8fbf0028, 0x8fb50024, 0x8fb40020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa0014ee,
+0x27bd0030, 0x8f83001c, 0x8c620004, 0x10400003,
+0x0, 0x3e00008, 0x0, 0x8c640010,
+0x8c650008, 0xa001527, 0x8c66000c, 0x0 };
+u32 bce_CP_b06FwData[(0x84/4) + 1] = {
+0x0, 0x1b, 0xf,
+0xa, 0x8, 0x6, 0x5,
+0x5, 0x4, 0x4, 0x3,
+0x3, 0x3, 0x3, 0x3,
0x2, 0x2, 0x2, 0x2,
0x2, 0x2, 0x2, 0x2,
0x2, 0x2, 0x2, 0x2,
-0x2, 0x1, 0x1, 0x1,
-0x0 };
-u32 bce_CP_b06FwRodata[(0x134/4) + 1] = {
-0x8000f30, 0x8000d88, 0x8000fc4,
-0x800106c, 0x8000f58, 0x8000f98, 0x80011a4,
-0x8000da4, 0x80011c8, 0x8000df4, 0x8001498,
-0x8001440, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8001254, 0x8001254, 0x8000da4, 0x8000da4,
-0x80016e0, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8000da4, 0x80013d4, 0x8000da4, 0x8000da4,
-0x8000da4, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8000da4, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8000da4, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8000fb8, 0x8000da4, 0x8000da4, 0x8001690,
-0x8000da4, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8000da4, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8000da4, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8000da4, 0x8000da4, 0x8000da4, 0x8000da4,
-0x8000da4, 0x80015bc, 0x8000da4, 0x8000da4,
-0x8001348, 0x80012b8, 0x8002e50, 0x8002e58,
-0x8002e20, 0x8002e2c, 0x8002e38, 0x8002e44,
-0x800532c, 0x80052ec, 0x80052b8, 0x800528c,
-0x8005268, 0x8005224, 0x0 };
-u32 bce_CP_b06FwBss[(0x5d8/4) + 1] = { 0x0 };
-u32 bce_CP_b06FwSbss[(0xf1/4) + 1] = { 0x0 };
-u32 bce_CP_b06FwSdata[(0x0/4) + 1] = { 0x0 };
+0x2, 0x2, 0x2, 0x1,
+0x1, 0x1, 0x0 };
+u32 bce_CP_b06FwRodata[(0x158/4) + 1] = {
+0x8000f24, 0x8000d6c, 0x8000fb8,
+0x8001060, 0x8000f4c, 0x8000f8c, 0x8001194,
+0x8000d88, 0x80011b8, 0x8000dd8, 0x8001554,
+0x800151c, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8001240, 0x8001240, 0x8000d88, 0x8000d88,
+0x80014e0, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8000d88, 0x80013b4, 0x8000d88, 0x8000d88,
+0x8000d88, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8000d88, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8000d88, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8000fac, 0x8000d88, 0x8000d88, 0x8001678,
+0x8000d88, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8000d88, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8000d88, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8000d88, 0x8000d88, 0x8000d88, 0x8000d88,
+0x8000d88, 0x8001410, 0x8000d88, 0x8000d88,
+0x8001334, 0x80012a4, 0x8001e2c, 0x8001efc,
+0x8001f14, 0x8001f28, 0x8001f38, 0x8001e2c,
+0x8001e2c, 0x8001e2c, 0x8001ed8, 0x8002e14,
+0x8002e1c, 0x8002de4, 0x8002df0, 0x8002dfc,
+0x8002e08, 0x80052e8, 0x80052a8, 0x8005274,
+0x8005248, 0x8005224, 0x80051e0, 0x0 };
+u32 bce_CP_b06FwBss[(0x5d8/4) + 1] = { 0x0 };
+u32 bce_CP_b06FwSbss[(0xf1/4) + 1] = { 0x0 };
+u32 bce_CP_b06FwSdata[(0x0/4) + 1] = { 0x0 };
u32 bce_rv2p_proc1[] = {
- 0x00000010, 0xb1800002,
- 0x0000001f, 0x01030100,
+ 0x00000010, 0xb1800006,
+ 0x0000001f, 0x0106000f,
+ 0x00000008, 0x0500ffff,
+ 0x00000018, 0x00020000,
+ 0x00000008, 0x050000ff,
+ 0x00000018, 0x00020000,
0x00000008, 0xac000001,
- 0x00000000, 0x05000000,
+ 0x00000008, 0x07800000,
0x0000000c, 0x2f800001,
0x00000000, 0x2b000000,
0x00000000, 0x2b800000,
- 0x00000010, 0x203f0063,
+ 0x00000010, 0x91e10002,
+ 0x00000008, 0xac000001,
+ 0x00000010, 0x203f003b,
0x00000010, 0x213f0003,
- 0x00000010, 0x20bf0032,
+ 0x00000010, 0x20bf0015,
0x00000018, 0x8000fffd,
- 0x00000010, 0xb1b8b00d,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c380000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x80000075,
- 0x00000018, 0x8000010b,
- 0x00000008, 0x02000002,
- 0x0000000f, 0x42e0001c,
- 0x00000010, 0x91840a11,
- 0x00000010, 0x2c62000b,
- 0x00000018, 0x8000001e,
- 0x00000008, 0x02000002,
- 0x0000000f, 0x42e0001c,
- 0x00000010, 0x91840a18,
- 0x00000008, 0x2c8000b1,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x00000018, 0x8000006f,
- 0x00000018, 0x80000015,
+ 0x0000000c, 0x1f800002,
+ 0x00000018, 0x8000fff9,
0x00000008, 0xb1000001,
0x00000008, 0x2c8000b0,
0x00000008, 0x2d000008,
0x00000008, 0x2d800001,
- 0x00000018, 0x80000069,
+ 0x00000018, 0x8000003c,
0x0000000b, 0x2fdf0002,
0x0000000c, 0x1f800002,
0x00000000, 0x2c070000,
0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffdc,
+ 0x00000018, 0x8000ffef,
0x0000000b, 0x2fdf0002,
0x0000000c, 0x1f800000,
0x00000000, 0x2c070000,
0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffd6,
- 0x0000000c, 0x1f800002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffd3,
- 0x0000000c, 0x29800002,
+ 0x00000018, 0x8000ffea,
0x0000000c, 0x1f800002,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a000005,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ffcd,
- 0x00000008, 0x0224003c,
+ 0x00000018, 0x8000ffe8,
+ 0x00000008, 0x02240025,
0x00000018, 0x00040000,
- 0x00000018, 0x8000001c,
- 0x00000018, 0x8000001e,
- 0x00000018, 0x80000052,
- 0x00000018, 0x8000009e,
- 0x00000018, 0x8000009d,
0x00000018, 0x80000000,
+ 0x00000018, 0x8000001b,
+ 0x00000018, 0x80000042,
0x00000018, 0x80000000,
0x00000018, 0x80000000,
0x00000018, 0x80000000,
@@ -6028,88 +6005,75 @@ u32 bce_rv2p_proc1[] = {
0x00000018, 0x80000000,
0x00000018, 0x80000000,
0x00000018, 0x80000000,
- 0x00000018, 0x800000df,
0x00000018, 0x80000000,
0x00000018, 0x80000000,
- 0x00000018, 0x80000015,
- 0x00000018, 0x8000001b,
0x00000018, 0x80000000,
- 0x00000018, 0x800000b4,
- 0x00000018, 0x8000002e,
- 0x00000018, 0x800000df,
- 0x00000018, 0x8000010a,
- 0x00000018, 0x800000d5,
- 0x00000018, 0x8000012e,
- 0x00000018, 0x8000003b,
+ 0x00000018, 0x8000008e,
0x00000018, 0x80000000,
- 0x00000018, 0x80000071,
- 0x0000000c, 0x1f800001,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffac,
- 0x00000010, 0x91d40000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000008, 0x2a000002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffa6,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000008d,
+ 0x00000018, 0x800000b7,
+ 0x00000018, 0x80000084,
+ 0x00000018, 0x800000da,
+ 0x00000018, 0x8000002b,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000006b,
0x00000010, 0x91d40000,
0x0000000c, 0x29800001,
0x0000000c, 0x1f800001,
- 0x00000000, 0x29420000,
0x00000008, 0x2a000002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff9f,
- 0x00000018, 0x8000ff9e,
- 0x00000010, 0xb1bcb00a,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c3c0000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x80000016,
- 0x00000018, 0x800000ac,
- 0x00000010, 0x2c6201ba,
- 0x00000018, 0x80000005,
- 0x00000008, 0x2c8000b1,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x0000000c, 0x29800000,
- 0x0000000c, 0x1f800000,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a000006,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ff89,
- 0x00000010, 0x91d40000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000008, 0x2a00000b,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff83,
+ 0x00000008, 0x07800000,
+ 0x00000018, 0x8000ffc4,
+ 0x00000008, 0x03800100,
+ 0x00000010, 0xb73c0e00,
+ 0x00000018, 0x80000000,
0x00000018, 0x00020000,
0x00000000, 0x06820000,
- 0x00000010, 0xb18a0006,
- 0x00000000, 0x860c1400,
- 0x00000010, 0xb18c0004,
- 0x00000000, 0x05000000,
+ 0x00000010, 0xb18f0004,
+ 0x00000010, 0xb18f1403,
0x00000008, 0x2a000001,
0x00000010, 0x91d40000,
+ 0x00000000, 0x07801400,
0x00000018, 0x000d0000,
0x00000000, 0x05020000,
0x00000010, 0x91de0000,
0x00000018, 0x000a0000,
+ 0x00000000, 0x06820000,
+ 0x00000010, 0x91de0000,
+ 0x00000009, 0x0561ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x30e1ffff,
+ 0x00000018, 0x8000ffa9,
+ 0x00000001, 0x05611400,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0xb0e10001,
+ 0x00000018, 0x000d0000,
+ 0x00000000, 0x06820000,
+ 0x00000010, 0x91de0000,
+ 0x00000009, 0x0562ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x3162ffff,
+ 0x00000018, 0x8000ff9f,
+ 0x00000001, 0x05621400,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0xb1620001,
+ 0x00000018, 0x000d0000,
0x00000010, 0xb1a0b013,
0x0000000b, 0x2fdf0002,
0x00000000, 0x2c200000,
0x00000008, 0x2c800000,
0x00000008, 0x2d000000,
0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ffee,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ffdb,
0x00000008, 0x2d80011c,
0x00000010, 0x001f0000,
- 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000ffe2,
0x0000000f, 0x47600008,
0x0000000f, 0x060e0001,
0x00000000, 0x0f580000,
@@ -6117,7 +6081,7 @@ u32 bce_rv2p_proc1[] = {
0x00000000, 0x0ae50000,
0x00000009, 0x0b66ffff,
0x00000000, 0x0d610000,
- 0x00000018, 0x80000013,
+ 0x00000018, 0x80000015,
0x0000000f, 0x47600008,
0x0000000b, 0x2fdf0002,
0x00000008, 0x2c800000,
@@ -6127,43 +6091,53 @@ u32 bce_rv2p_proc1[] = {
0x0000000f, 0x060e0001,
0x00000010, 0x001f0000,
0x00000000, 0x0f580000,
- 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000ffd0,
0x00000000, 0x0a640000,
0x00000000, 0x0ae50000,
0x00000009, 0x0b66ffff,
0x00000000, 0x0d610000,
0x00000000, 0x02620000,
+ 0x00000000, 0x02e00000,
0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x30050000,
0x00000000, 0x31040000,
0x00000000, 0x309a0000,
+ 0x00000010, 0x0060000a,
+ 0x00000008, 0x05160001,
+ 0x00000010, 0xba9a1403,
+ 0x00000000, 0x03000000,
+ 0x00000018, 0x80000006,
+ 0x00000018, 0x8000ff6c,
+ 0x00000010, 0xb6061404,
+ 0x00000008, 0x03060001,
+ 0x00000008, 0x2a000001,
+ 0x00000018, 0x8000ff71,
0x00000000, 0x0c961800,
0x00000009, 0x0c99ffff,
0x00000004, 0xcc993400,
- 0x00000010, 0xb1963202,
+ 0x00000010, 0xba992c02,
0x00000008, 0x0f800000,
0x0000000c, 0x29800001,
- 0x00000010, 0x00220002,
0x0000000c, 0x29520001,
0x0000000c, 0x29520000,
+ 0x00000008, 0x22800002,
0x00000008, 0x0200000e,
0x00000008, 0x0280001a,
0x00000010, 0xb1c40a02,
0x00000008, 0x02000003,
- 0x00000008, 0x22000001,
0x0000000c, 0x1f800001,
0x00000000, 0x2adf0000,
0x00000000, 0x2a000800,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ff3f,
+ 0x00000018, 0x8000ff60,
0x0000000b, 0x2fdf0002,
0x00000010, 0x91d40000,
0x00000008, 0x2a000001,
0x00000000, 0x2c200000,
+ 0x00000010, 0x91d40000,
0x00000008, 0x2c800000,
0x00000008, 0x2d000000,
0x00000008, 0x2d80011c,
- 0x00000010, 0x91d40000,
- 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000ff9f,
0x00000008, 0x2c800006,
0x00000008, 0x2d000006,
0x00000000, 0x30800000,
@@ -6174,95 +6148,19 @@ u32 bce_rv2p_proc1[] = {
0x00000010, 0x91de0000,
0x00000000, 0x2adf0000,
0x00000008, 0x2a000010,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff2a,
- 0x00000010, 0x91a0b009,
- 0x00000008, 0x2c8000b1,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x00000018, 0x8000ffab,
- 0x00000018, 0x80000010,
- 0x00000008, 0xac000001,
- 0x00000018, 0x8000000b,
- 0x00000000, 0x0380b000,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c004000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ff9a,
- 0x00000018, 0x80000030,
- 0x00000018, 0x80000006,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c000e00,
- 0x00000008, 0x2a000007,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ff14,
- 0x00000000, 0x06820000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x0ce70007,
- 0x00000009, 0x0562ffff,
- 0x00000010, 0xba6c1405,
- 0x00000000, 0x2adf0000,
- 0x00000000, 0x21000000,
- 0x00000008, 0x2a000005,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2c8000b0,
- 0x00000008, 0x2d000008,
- 0x0000000c, 0x31620018,
- 0x00000008, 0x2d800001,
- 0x00000018, 0x8000ff8c,
- 0x00000018, 0x000d0000,
- 0x00000010, 0xb1a0b00e,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c200000,
- 0x00000010, 0x91d40000,
- 0x00000018, 0x80000014,
- 0x00000010, 0x2c620002,
- 0x00000018, 0x8000000b,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c070000,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000fef6,
- 0x00000008, 0x2c8000b1,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a00000a,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000feeb,
- 0x00000000, 0x05020000,
- 0x00000008, 0x2c8000b0,
- 0x00000008, 0x2d000008,
- 0x00000008, 0x2d800150,
- 0x00000000, 0x00000000,
- 0x00000010, 0x205f0000,
- 0x00000008, 0x2c800000,
- 0x00000008, 0x2d000000,
- 0x00000008, 0x2d800108,
- 0x00000000, 0x00000000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x000a0000,
+ 0x00000008, 0x07800000,
+ 0x00000018, 0x8000ff4b,
0x00000010, 0x91d40000,
- 0x00000008, 0x0600aaaa,
- 0x00000018, 0x8000ff5b,
+ 0x00000008, 0x050000aa,
+ 0x00000018, 0x8000ff89,
0x0000000c, 0x29800001,
0x0000000c, 0x1f800001,
0x00000008, 0x2a000009,
- 0x00000008, 0x0500aaaa,
- 0x00000018, 0x8000fed7,
+ 0x00000018, 0x8000ff44,
0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ff53,
- 0x00000010, 0x91a03c02,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ff82,
+ 0x00000010, 0x91a0b002,
0x00000010, 0xb1e66207,
0x0000000b, 0x2fdf0002,
0x00000000, 0x2c310000,
@@ -6276,7 +6174,7 @@ u32 bce_rv2p_proc1[] = {
0x00000000, 0x2ca70000,
0x00000008, 0x2d000010,
0x00000008, 0x2d800108,
- 0x00000018, 0x8000ff4c,
+ 0x00000018, 0x8000ff7a,
0x00000010, 0xb1a60010,
0x00000010, 0x001f0000,
0x0000000f, 0x0f300007,
@@ -6299,13 +6197,12 @@ u32 bce_rv2p_proc1[] = {
0x00000000, 0x2adf0000,
0x00000008, 0x2a00000c,
0x00000010, 0x009f0000,
- 0x00000000, 0x0f200000,
+ 0x00000000, 0x2c200000,
0x0000000c, 0x1f800001,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000feab,
+ 0x00000018, 0x8000ff19,
0x00000010, 0x91d40000,
- 0x00000008, 0x0600aaaa,
- 0x00000018, 0x8000ff27,
+ 0x00000008, 0x050000aa,
+ 0x00000018, 0x8000ff57,
0x0000000f, 0x47220008,
0x00000009, 0x070e000f,
0x00000008, 0x070e0008,
@@ -6324,7 +6221,7 @@ u32 bce_rv2p_proc1[] = {
0x00000000, 0x0c960a00,
0x00000009, 0x0c99ffff,
0x00000008, 0x0d00ffff,
- 0x00000010, 0xb1963202,
+ 0x00000010, 0xba992c02,
0x00000008, 0x0f800005,
0x00000010, 0xb1a80008,
0x00000010, 0x205f0000,
@@ -6333,71 +6230,64 @@ u32 bce_rv2p_proc1[] = {
0x00000000, 0x2ca70000,
0x00000008, 0x2d000010,
0x00000008, 0x2d800108,
- 0x00000018, 0x8000ff13,
+ 0x00000018, 0x8000ff42,
0x0000000c, 0x29800001,
0x00000010, 0x001f0000,
0x0000000c, 0x1f800001,
0x00000000, 0x2adf0000,
0x00000008, 0x2a00000d,
- 0x00000008, 0x0500aaaa,
- 0x00000018, 0x8000fe85,
+ 0x00000018, 0x8000fef4,
0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ff01,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ff32,
0x0000000c, 0x29800001,
0x0000000c, 0x1f800001,
0x00000008, 0x2a000007,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000fe7d,
- 0x00000008, 0x03050004,
- 0x00000006, 0x83040c00,
- 0x00000008, 0x02850200,
- 0x00000000, 0x86050c00,
- 0x00000001, 0x860c0e00,
- 0x00000008, 0x02040004,
- 0x00000000, 0x02041800,
- 0x00000000, 0x83871800,
- 0x00000018, 0x00020000,
+ 0x00000018, 0x8000feed,
};
u32 bce_rv2p_proc2[] = {
0x00000010, 0xb1800004,
- 0x0000001f, 0x01030100,
+ 0x0000001f, 0x0106000f,
0x00000008, 0x050000ff,
0x00000018, 0x00020000,
0x00000000, 0x2a000000,
0x00000010, 0xb1d40000,
+ 0x00000010, 0x91de0000,
+ 0x00000010, 0x20530000,
+ 0x00000010, 0x001f0000,
+ 0x00000000, 0x2f80aa00,
0x0000000c, 0x29800001,
- 0x00000008, 0x02540008,
+ 0x00000008, 0x0254000e,
+ 0x00000000, 0x2c400000,
+ 0x00000000, 0x0f400000,
0x00000018, 0x00040000,
- 0x00000018, 0x80000010,
0x00000018, 0x80000011,
- 0x00000018, 0x8000003a,
- 0x00000018, 0x80000104,
- 0x00000018, 0x80000103,
- 0x00000018, 0x80000102,
- 0x00000018, 0x80000102,
+ 0x00000018, 0x80000012,
+ 0x00000018, 0x80000038,
+ 0x00000018, 0x800000df,
+ 0x00000018, 0x800000de,
+ 0x00000018, 0x800000dd,
+ 0x00000018, 0x800000dd,
0x00000018, 0x80000000,
- 0x00000018, 0x80000114,
- 0x00000018, 0x800000fe,
- 0x00000018, 0x8000000c,
- 0x00000018, 0x80000118,
- 0x00000018, 0x8000016a,
- 0x00000018, 0x80000067,
- 0x00000018, 0x800000da,
- 0x00000018, 0x800000e7,
+ 0x00000018, 0x800000f6,
+ 0x00000018, 0x800000d9,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x800000fa,
+ 0x00000018, 0x80000148,
+ 0x00000018, 0x8000005a,
+ 0x00000018, 0x800000c4,
+ 0x00000018, 0x800000c5,
+ 0x00000018, 0x800000d2,
0x00000000, 0x2a000000,
- 0x00000018, 0x8000ffeb,
+ 0x00000018, 0x8000ffe4,
0x00000000, 0x2a000000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ffe7,
- 0x00000000, 0x2a000000,
- 0x00000018, 0x8000ffe5,
+ 0x00000018, 0x8000ffe1,
0x00000018, 0x00020000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963421,
+ 0x00000010, 0xb99a2c21,
0x00000010, 0x205f0000,
0x00000000, 0x2c1e0000,
0x00000008, 0x2c800006,
@@ -6408,7 +6298,7 @@ u32 bce_rv2p_proc2[] = {
0x00000000, 0x0d610000,
0x00000018, 0x000a0000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963416,
+ 0x00000010, 0xb99a2c16,
0x00000010, 0x205f0000,
0x00000000, 0x09d80000,
0x00000000, 0x2c1e0000,
@@ -6421,7 +6311,7 @@ u32 bce_rv2p_proc2[] = {
0x00000000, 0x2c130000,
0x00000018, 0x000a0000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963409,
+ 0x00000010, 0xb99a2c09,
0x00000010, 0x205f0000,
0x00000000, 0x2c1e0000,
0x00000008, 0x2c800006,
@@ -6431,31 +6321,25 @@ u32 bce_rv2p_proc2[] = {
0x00000010, 0x91de0000,
0x00000000, 0x0d7a0000,
0x00000018, 0x000a0000,
- 0x00000010, 0x91de0000,
- 0x00000010, 0x001f0000,
- 0x00000000, 0x2f80aa00,
0x00000000, 0x2a000000,
+ 0x00000008, 0x22000001,
0x00000000, 0x0d610000,
- 0x00000000, 0x03620000,
- 0x00000000, 0x2c400000,
- 0x00000000, 0x02638c00,
- 0x00000000, 0x26460000,
- 0x00000008, 0x02040012,
- 0x00000010, 0xb9060827,
- 0x00000000, 0x0f580000,
+ 0x00000010, 0x21c20024,
+ 0x00000010, 0xb1c60002,
+ 0x00000010, 0x234200a2,
+ 0x00000009, 0x0b66ffff,
+ 0x00000010, 0xba9a2c20,
0x00000000, 0x0a640000,
0x00000000, 0x0ae50000,
- 0x00000009, 0x0b66ffff,
0x00000000, 0x0c000000,
0x00000000, 0x0b800000,
0x00000008, 0x0cc60012,
- 0x00000018, 0x8000ffcb,
+ 0x00000018, 0x8000ffd0,
0x00000008, 0x0f800003,
0x00000000, 0x00000000,
0x00000010, 0x009f0000,
0x00000008, 0x27110012,
0x00000000, 0x66900000,
- 0x00000008, 0xa31b0012,
0x00000010, 0xb1980003,
0x00000010, 0x001f0000,
0x00000008, 0x0f800004,
@@ -6463,39 +6347,30 @@ u32 bce_rv2p_proc2[] = {
0x00000008, 0x2c80000c,
0x00000008, 0x2d00000c,
0x00000010, 0x009f0000,
+ 0x00000010, 0x91c60005,
+ 0x00000010, 0x001f0000,
+ 0x00000010, 0xba9a2c03,
+ 0x00000008, 0x0f800004,
+ 0x00000018, 0x8000fffd,
0x00000000, 0x25960000,
0x0000000c, 0x29800000,
- 0x00000000, 0x06660000,
- 0x00000000, 0x86611800,
- 0x00000009, 0x0260000f,
- 0x0000000f, 0x02040002,
- 0x00000010, 0xb60c0803,
- 0x0000000c, 0x1fbf0000,
- 0x0000000c, 0x33660010,
0x00000000, 0x32140000,
0x00000000, 0x32950000,
0x00000005, 0x73662c00,
0x00000000, 0x31e32e00,
0x00000008, 0x2d800010,
- 0x00000010, 0x20530000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000ff90,
+ 0x00000018, 0x8000ff96,
0x00000000, 0x23000000,
0x00000009, 0x25e6ffff,
0x00000008, 0x2200000b,
0x0000000c, 0x69520000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ff89,
- 0x00000010, 0x91de0000,
- 0x00000010, 0x001f0000,
- 0x00000000, 0x2f80aa00,
+ 0x00000018, 0x8000ff90,
0x00000000, 0x2a000000,
- 0x00000000, 0x2c400000,
0x00000008, 0x2c800040,
0x00000008, 0x2d000020,
0x00000008, 0x2d80011c,
- 0x00000000, 0x00000000,
+ 0x00000008, 0x22000001,
0x00000010, 0x91de0000,
0x0000000f, 0x42ea0010,
0x00000010, 0x004f0004,
@@ -6503,21 +6378,22 @@ u32 bce_rv2p_proc2[] = {
0x00000008, 0x02490012,
0x00000010, 0xb5840a00,
0x00000000, 0x0d610000,
- 0x00000010, 0xba66345a,
- 0x00000000, 0x03620000,
- 0x00000010, 0xb8630c58,
+ 0x00000010, 0xba663457,
0x00000008, 0x83050012,
0x00000010, 0x004f0002,
0x00000000, 0x03490000,
0x00000001, 0x83068c00,
0x00000000, 0x83c60c00,
- 0x00000010, 0xb1870010,
+ 0x00000010, 0xb1870013,
0x00000000, 0x0b6e0000,
- 0x00000018, 0x8000ff6b,
- 0x00000001, 0x06691400,
- 0x00000010, 0x918c0002,
+ 0x00000009, 0x0569ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x34e9ffff,
+ 0x00000018, 0x8000ff75,
+ 0x00000001, 0x05691400,
+ 0x00000010, 0x918a0002,
0x00000008, 0xb4e90001,
- 0x00000010, 0xb1e92c4c,
+ 0x00000010, 0xbae92c48,
0x00000000, 0x86692c00,
0x00000000, 0x02000000,
0x00000009, 0x02eaffff,
@@ -6526,9 +6402,7 @@ u32 bce_rv2p_proc2[] = {
0x0000000f, 0x460c0001,
0x0000000f, 0x02850001,
0x00000010, 0x918c01fc,
- 0x00000010, 0xb7040e43,
- 0x00000000, 0x2c400000,
- 0x00000000, 0x0f400000,
+ 0x00000010, 0xb7040e3f,
0x00000000, 0x0d610000,
0x00000000, 0x0a640000,
0x00000000, 0x0ae50000,
@@ -6541,7 +6415,6 @@ u32 bce_rv2p_proc2[] = {
0x00000010, 0x009f0000,
0x00000008, 0x27110012,
0x00000000, 0x66900000,
- 0x00000000, 0x26460000,
0x00000000, 0x23060000,
0x00000010, 0xb1980005,
0x00000010, 0x001f0000,
@@ -6591,9 +6464,7 @@ u32 bce_rv2p_proc2[] = {
0x00000008, 0x2c800050,
0x00000008, 0x2d000030,
0x00000008, 0x2d80000c,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ff1f,
- 0x00000000, 0x26460000,
+ 0x00000018, 0x8000ff2d,
0x00000000, 0x23000000,
0x00000009, 0x25e6ffff,
0x00000000, 0x0b6e0000,
@@ -6601,70 +6472,58 @@ u32 bce_rv2p_proc2[] = {
0x00000008, 0x2200001b,
0x0000000c, 0x69520000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ff15,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000ff25,
0x00000000, 0x2a000000,
- 0x00000010, 0x003f000b,
- 0x00000000, 0x06660000,
- 0x00000000, 0x86611800,
- 0x00000009, 0x026000f0,
- 0x00000010, 0xb70c0807,
- 0x0000000c, 0x73660010,
- 0x00000008, 0x2c800018,
- 0x00000008, 0x2d000018,
- 0x00000008, 0x2d800002,
- 0x0000000c, 0x5fbf0000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000ff07,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000ff23,
0x00000000, 0x2a000000,
- 0x00000000, 0x2c400000,
0x0000000c, 0x29800000,
0x00000010, 0x91de0000,
0x00000008, 0x2c80001a,
0x00000008, 0x2d00001a,
- 0x00000000, 0x33000000,
+ 0x00000005, 0x73660000,
0x00000008, 0x2d800002,
0x00000000, 0x31800000,
0x00000010, 0x91de0000,
0x00000008, 0x2c80000c,
0x00000008, 0x2d00000c,
0x00000008, 0x2d800004,
- 0x00000010, 0x20530000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000fef6,
- 0x00000018, 0x8000fef5,
+ 0x00000018, 0x8000ff16,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000ff14,
0x00000000, 0x2a000000,
0x00000010, 0x001f0000,
0x00000000, 0x0f008000,
0x00000008, 0x0f800007,
- 0x00000018, 0x80000014,
+ 0x00000018, 0x8000001b,
+ 0x00000000, 0x280a0000,
0x00000000, 0x05020000,
0x00000008, 0x22000009,
- 0x00000000, 0x286d0000,
0x00000000, 0x29000000,
0x0000000f, 0x65680010,
+ 0x00000000, 0x248a0000,
0x00000003, 0xf66c9400,
0x00000010, 0xb972a004,
0x0000000c, 0x73e70019,
0x0000000c, 0x21420004,
- 0x00000000, 0x3bf60000,
+ 0x00000000, 0x3cf80000,
0x0000000c, 0x29800000,
0x00000010, 0x20530000,
0x00000008, 0x22000008,
0x0000000c, 0x61420004,
0x00000018, 0x000a0000,
+ 0x00000000, 0x05020000,
+ 0x0000000c, 0x61420000,
+ 0x00000010, 0x01420003,
+ 0x0000000c, 0x33e7001d,
+ 0x0000000c, 0x61420002,
+ 0x00000018, 0x000a0000,
0x00000000, 0x2a000000,
0x00000010, 0x001f0000,
0x0000000f, 0x0f470007,
0x00000008, 0x0f800008,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000feda,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2fd50000,
- 0x00000010, 0x001f0000,
+ 0x00000010, 0x009f0000,
+ 0x00000018, 0x8000fef2,
0x00000000, 0x33510000,
0x00000000, 0x2a000000,
0x00000010, 0xb1c60023,
@@ -6739,13 +6598,11 @@ u32 bce_rv2p_proc2[] = {
0x00000008, 0x2d80000c,
0x00000000, 0x00000000,
0x00000010, 0x91de0000,
- 0x00000010, 0x05c20003,
- 0x00000000, 0x33000000,
+ 0x00000010, 0x05c20004,
0x00000008, 0x0f800007,
- 0x00000010, 0x20530000,
+ 0x00000000, 0x33000000,
0x00000010, 0x009f0000,
- 0x00000018, 0x8000fe87,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000fea3,
0x00000000, 0x2a000000,
0x0000000f, 0x0f500007,
0x00000010, 0xb1c6002d,
@@ -6804,1004 +6661,1037 @@ u32 bce_rv2p_proc2[] = {
0x00000008, 0x22000017,
0x0000000c, 0x29800000,
0x00000010, 0x001f0000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000fe4a,
+ 0x00000018, 0x8000fe68,
};
-int bce_TXP_b09FwReleaseMajor = 0x1;
-int bce_TXP_b09FwReleaseMinor = 0x0;
-int bce_TXP_b09FwReleaseFix = 0x0;
-u32 bce_TXP_b09FwStartAddr = 0x08000098;
-u32 bce_TXP_b09FwTextAddr = 0x08000000;
-int bce_TXP_b09FwTextLen = 0x3afc;
-u32 bce_TXP_b09FwDataAddr = 0x00000000;
-int bce_TXP_b09FwDataLen = 0x0;
-u32 bce_TXP_b09FwRodataAddr = 0x08003afc;
-int bce_TXP_b09FwRodataLen = 0x30;
-u32 bce_TXP_b09FwBssAddr = 0x08003bcc;
-int bce_TXP_b09FwBssLen = 0x24c;
-u32 bce_TXP_b09FwSbssAddr = 0x08003b60;
-int bce_TXP_b09FwSbssLen = 0x6c;
-u32 bce_TXP_b09FwSDataAddr = 0x00000000;
-int bce_TXP_b09FwSDataLen = 0x0;
-u32 bce_TXP_b09FwText[(0x3afc/4) + 1] = {
-0xa000026,
-0x0, 0x0, 0xd, 0x74787034,
-0x2e362e31, 0x36000000, 0x4061000, 0xa,
-0x136, 0xea60, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x1d,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x10000003, 0x0,
-0xd, 0xd, 0x3c020800, 0x24423b60,
-0x3c030800, 0x24633e18, 0xac400000, 0x43202b,
-0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc,
-0x3a0f021, 0x3c100800, 0x26100098, 0x3c1c0800,
-0x279c3b60, 0xe0004ae, 0x0, 0xd,
-0x3c058000, 0x8f830030, 0x34a80070, 0x8d070000,
-0x833025, 0x3c029000, 0xc22025, 0xaca40020,
-0xaf870024, 0x3c048000, 0x8c890020, 0x520fffe,
-0x0, 0x34840070, 0x8c850000, 0x3c180800,
-0x8f18007c, 0x3c0d0800, 0x8dad0078, 0xa7c823,
-0x3195021, 0x7021, 0x159602b, 0x1ae5821,
-0x16c3821, 0x3c010800, 0xac2a007c, 0x3c010800,
-0xac270078, 0x3e00008, 0x0, 0xa00003d,
-0x24040001, 0x8f850030, 0x3c048000, 0x34830001,
-0xa31025, 0x3e00008, 0xac820020, 0x3e00008,
-0x1021, 0x3084ffff, 0x30a5ffff, 0x10800007,
-0x1821, 0x30820001, 0x10400002, 0x42042,
-0x651821, 0x1480fffb, 0x52840, 0x3e00008,
-0x601021, 0x10c00007, 0x0, 0x8ca20000,
-0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb,
-0x24840004, 0x3e00008, 0x0, 0x10a00008,
-0x24a3ffff, 0xac860000, 0x0, 0x0,
-0x2402ffff, 0x2463ffff, 0x1462fffa, 0x24840004,
-0x3e00008, 0x0, 0x90aa0031, 0x8fab0010,
-0x8cac0040, 0x3c0300ff, 0x8d680004, 0xad6c0020,
-0x8cad0044, 0xe06021, 0x3462ffff, 0xad6d0024,
-0x8ca70048, 0x3c09ff00, 0x109c024, 0xad670028,
-0x8cae004c, 0x182c824, 0x3197825, 0xad6f0004,
-0xad6e002c, 0x8cad0038, 0x314a00ff, 0xad6d001c,
-0x94a90032, 0x3128ffff, 0xad680010, 0x90a70030,
-0xa5600002, 0xa1600004, 0xa1670000, 0x90a30032,
-0x306200ff, 0x21982, 0x10600005, 0x24050001,
-0x1065000e, 0x0, 0x3e00008, 0xa16a0001,
-0x8cd80028, 0x354a0080, 0xad780018, 0x8ccf0014,
-0xad6f0014, 0x8cce0030, 0xad6e0008, 0x8cc4002c,
-0xa16a0001, 0x3e00008, 0xad64000c, 0x8ccd001c,
-0xad6d0018, 0x8cc90014, 0xad690014, 0x8cc80024,
-0xad680008, 0x8cc70020, 0xad67000c, 0x8cc20014,
-0x8c830070, 0x43c82b, 0x13200007, 0x0,
-0x8cc20014, 0x144cffe4, 0x0, 0x354a0080,
-0x3e00008, 0xa16a0001, 0x8c820070, 0xa0000c6,
-0x0, 0x90890030, 0x27bdfff8, 0x8fa8001c,
-0xa3a90000, 0x8fa30000, 0x3c0dff80, 0x35a2ffff,
-0x8cac002c, 0x625824, 0xafab0000, 0xa1000004,
-0xc05821, 0xa7a00002, 0x8d060004, 0xa04821,
-0x167c821, 0x8fa50000, 0x805021, 0x3c18ff7f,
-0x32c2026, 0x3c0e00ff, 0x2c8c0001, 0x370fffff,
-0x35cdffff, 0x3c02ff00, 0xafc824, 0xedc024,
-0xc27824, 0xc1dc0, 0x3236825, 0x1f87025,
-0xad0d0000, 0xad0e0004, 0x8d240024, 0xafad0000,
-0xad040008, 0x8d2c0020, 0x2404ffff, 0xad0c000c,
-0x95470032, 0x30e6ffff, 0xad060010, 0x91450048,
-0x30a200ff, 0x219c2, 0x50600001, 0x8d240034,
-0xad040014, 0x8d470038, 0x8faa0018, 0x27bd0008,
-0xad0b0028, 0xad0a0024, 0xad07001c, 0xad00002c,
-0xad000018, 0x3e00008, 0xad000020, 0x27bdffe0,
-0xafb20018, 0xafb10014, 0xafb00010, 0xafbf001c,
-0x90980030, 0xc08821, 0x3c0d00ff, 0x330f007f,
-0xa0cf0000, 0x908e0031, 0x35acffff, 0x3c0aff00,
-0xa0ce0001, 0x94a6001e, 0xa2200004, 0x8cab0014,
-0x8e290004, 0xa08021, 0x16c2824, 0x12a4024,
-0x809021, 0x1052025, 0xa6260002, 0xae240004,
-0x26050020, 0x26240008, 0xe000072, 0x24060002,
-0x92470030, 0x26050028, 0x26240014, 0x71e00,
-0x31603, 0x24060004, 0x4400003, 0x2403ffff,
-0x96590032, 0x3323ffff, 0xe000072, 0xae230010,
-0x26240024, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x24050003, 0x3021, 0xa00007c,
-0x27bd0020, 0x27bdffd8, 0xafb1001c, 0xafb00018,
-0xafbf0020, 0x90a90030, 0x24020001, 0xe05021,
-0x3123003f, 0xa04021, 0x8fb00040, 0x808821,
-0xc04821, 0x10620014, 0x8fa70038, 0x240b0005,
-0xa02021, 0xc02821, 0x106b0013, 0x2003021,
-0xe000108, 0x0, 0x9225007c, 0x30a40002,
-0x10800003, 0x26030030, 0xae000030, 0x26030034,
-0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x601021,
-0x3e00008, 0x27bd0028, 0xe000087, 0xafb00010,
-0xa00014f, 0x0, 0x8fa3003c, 0x1002021,
-0x1202821, 0x1403021, 0xafa30010, 0xe0000ce,
-0xafb00014, 0xa00014f, 0x0, 0x8f820050,
-0x24430001, 0x304200ff, 0xaf830050, 0x3e00008,
-0x0, 0x3c058000, 0x8ca30e10, 0x8f840044,
-0xac830020, 0x8ca20e18, 0x3e00008, 0xac820024,
-0x3c058000, 0x8ca30e14, 0x8f840044, 0xac830020,
-0x8ca20e1c, 0x3e00008, 0xac820024, 0x93820038,
-0x1040001b, 0x2483000f, 0x2404fff0, 0x643824,
-0x10e00019, 0x978b002c, 0x9784004c, 0x9389002e,
-0x3c0a601c, 0xa000190, 0x1644023, 0x1037021,
-0x642823, 0x11260002, 0x31c2ffff, 0x30a2ffff,
-0x47302b, 0x50c0000e, 0xe44821, 0x8d4d000c,
-0x31a3ffff, 0x36400, 0xc2c03, 0x4a1fff3,
-0x3021, 0x30637fff, 0xa000188, 0x24060001,
-0x3e00008, 0x0, 0x9784004c, 0xe44821,
-0x3123ffff, 0x3168ffff, 0x68382b, 0x54e0fff8,
-0xa783004c, 0x938a002e, 0x11400005, 0x240f0001,
-0x6bc023, 0xa380002e, 0x3e00008, 0xa798004c,
-0x6bc023, 0xa38f002e, 0x3e00008, 0xa798004c,
-0x3e00008, 0x0, 0x27bdffe8, 0xafb00010,
-0x3084ffff, 0x3c108000, 0x93a8002b, 0xafbf0014,
-0xa6040144, 0x960a0e16, 0x30c600ff, 0x8fa90030,
-0xa60a0146, 0xae050148, 0xa2060152, 0xa608015a,
-0xae070160, 0x8fa3002c, 0xa6090158, 0x1202021,
-0xe00017c, 0xae030154, 0x3c021000, 0xae020178,
+int bce_TXP_b09FwReleaseMajor = 0x6;
+int bce_TXP_b09FwReleaseMinor = 0x0;
+int bce_TXP_b09FwReleaseFix = 0x11;
+u32 bce_TXP_b09FwStartAddr = 0x080000a8;
+u32 bce_TXP_b09FwTextAddr = 0x08000000;
+int bce_TXP_b09FwTextLen = 0x3d28;
+u32 bce_TXP_b09FwDataAddr = 0x00000000;
+int bce_TXP_b09FwDataLen = 0x0;
+u32 bce_TXP_b09FwRodataAddr = 0x08003d28;
+int bce_TXP_b09FwRodataLen = 0x30;
+u32 bce_TXP_b09FwBssAddr = 0x08003df0;
+int bce_TXP_b09FwBssLen = 0x24c;
+u32 bce_TXP_b09FwSbssAddr = 0x08003d88;
+int bce_TXP_b09FwSbssLen = 0x64;
+u32 bce_TXP_b09FwSDataAddr = 0x00000000;
+int bce_TXP_b09FwSDataLen = 0x0;
+u32 bce_TXP_b09FwText[(0x3d28/4) + 1] = {
+0xa00002a, 0x0, 0x0,
+0xd, 0x74787036, 0x2e302e31, 0x37000000,
+0x6001100, 0x0, 0x136, 0xea60,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x16, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x1388,
+0x0, 0x5dc, 0x0, 0x0,
+0x10000003, 0x0, 0xd, 0xd,
+0x3c020800, 0x24423d88, 0x3c030800, 0x2463403c,
+0xac400000, 0x43202b, 0x1480fffd, 0x24420004,
+0x3c1d0800, 0x37bd7ffc, 0x3a0f021, 0x3c100800,
+0x261000a8, 0x3c1c0800, 0x279c3d88, 0xe00044e,
+0x0, 0xd, 0x27bdffb4, 0xafa10000,
+0xafa20004, 0xafa30008, 0xafa4000c, 0xafa50010,
+0xafa60014, 0xafa70018, 0xafa8001c, 0xafa90020,
+0xafaa0024, 0xafab0028, 0xafac002c, 0xafad0030,
+0xafae0034, 0xafaf0038, 0xafb8003c, 0xafb90040,
+0xafbc0044, 0xafbf0048, 0xe000591, 0x0,
+0x8fbf0048, 0x8fbc0044, 0x8fb90040, 0x8fb8003c,
+0x8faf0038, 0x8fae0034, 0x8fad0030, 0x8fac002c,
+0x8fab0028, 0x8faa0024, 0x8fa90020, 0x8fa8001c,
+0x8fa70018, 0x8fa60014, 0x8fa50010, 0x8fa4000c,
+0x8fa30008, 0x8fa20004, 0x8fa10000, 0x27bd004c,
+0x3c1b6004, 0x8f7a5030, 0x377b5028, 0x3400008,
+0xaf7a0000, 0x8f86003c, 0x3c039000, 0x3c028000,
+0x862825, 0xa32025, 0xac440020, 0x3c038000,
+0x8c670020, 0x4e0fffe, 0x0, 0x3e00008,
+0x0, 0xa000070, 0x24040001, 0x8f85003c,
+0x3c048000, 0x34830001, 0xa31025, 0x3e00008,
+0xac820020, 0x3e00008, 0x1021, 0x3084ffff,
+0x30a5ffff, 0x10800007, 0x1821, 0x30820001,
+0x10400002, 0x42042, 0x651821, 0x1480fffb,
+0x52840, 0x3e00008, 0x601021, 0x10c00007,
+0x0, 0x8ca20000, 0x24c6ffff, 0x24a50004,
+0xac820000, 0x14c0fffb, 0x24840004, 0x3e00008,
+0x0, 0x10a00008, 0x24a3ffff, 0xac860000,
+0x0, 0x0, 0x2402ffff, 0x2463ffff,
+0x1462fffa, 0x24840004, 0x3e00008, 0x0,
+0x90aa0031, 0x8fab0010, 0x8cac0040, 0x3c0300ff,
+0x8d680004, 0xad6c0020, 0x8cad0044, 0xe06021,
+0x3462ffff, 0xad6d0024, 0x8ca70048, 0x3c09ff00,
+0x109c024, 0xad670028, 0x8cae004c, 0x182c824,
+0x3197825, 0xad6f0004, 0xad6e002c, 0x8cad0038,
+0x314a00ff, 0xad6d001c, 0x94a90032, 0x3128ffff,
+0xad680010, 0x90a70030, 0xa5600002, 0xa1600004,
+0xa1670000, 0x90a30032, 0x306200ff, 0x21982,
+0x10600005, 0x24050001, 0x1065000e, 0x0,
+0x3e00008, 0xa16a0001, 0x8cd80028, 0x354a0080,
+0xad780018, 0x8ccf0014, 0xad6f0014, 0x8cce0030,
+0xad6e0008, 0x8cc4002c, 0xa16a0001, 0x3e00008,
+0xad64000c, 0x8ccd001c, 0xad6d0018, 0x8cc90014,
+0xad690014, 0x8cc80024, 0xad680008, 0x8cc70020,
+0xad67000c, 0x8cc20014, 0x8c830070, 0x43c82b,
+0x13200007, 0x0, 0x8cc20014, 0x144cffe4,
+0x0, 0x354a0080, 0x3e00008, 0xa16a0001,
+0x8c820070, 0xa0000e6, 0x0, 0x90890030,
+0x27bdfff8, 0x8fa8001c, 0xa3a90000, 0x8fa30000,
+0x3c0dff80, 0x35a2ffff, 0x8cac002c, 0x625824,
+0xafab0000, 0xa1000004, 0xc05821, 0xa7a00002,
+0x8d060004, 0xa04821, 0x167c821, 0x8fa50000,
+0x805021, 0x3c18ff7f, 0x32c2026, 0x3c0e00ff,
+0x2c8c0001, 0x370fffff, 0x35cdffff, 0x3c02ff00,
+0xafc824, 0xedc024, 0xc27824, 0xc1dc0,
+0x3236825, 0x1f87025, 0xad0d0000, 0xad0e0004,
+0x8d240024, 0xafad0000, 0xad040008, 0x8d2c0020,
+0x2404ffff, 0xad0c000c, 0x95470032, 0x30e6ffff,
+0xad060010, 0x91450048, 0x30a200ff, 0x219c2,
+0x50600001, 0x8d240034, 0xad040014, 0x8d470038,
+0x8faa0018, 0x27bd0008, 0xad0b0028, 0xad0a0024,
+0xad07001c, 0xad00002c, 0xad000018, 0x3e00008,
+0xad000020, 0x27bdffe0, 0xafb20018, 0xafb10014,
+0xafb00010, 0xafbf001c, 0x90980030, 0xc08821,
+0x3c0d00ff, 0x330f007f, 0xa0cf0000, 0x908e0031,
+0x35acffff, 0x3c0aff00, 0xa0ce0001, 0x94a6001e,
+0xa2200004, 0x8cab0014, 0x8e290004, 0xa08021,
+0x16c2824, 0x12a4024, 0x809021, 0x1052025,
+0xa6260002, 0xae240004, 0x26050020, 0x26240008,
+0xe000092, 0x24060002, 0x92470030, 0x26050028,
+0x26240014, 0x71e00, 0x31603, 0x24060004,
+0x4400003, 0x2403ffff, 0x96590032, 0x3323ffff,
+0xe000092, 0xae230010, 0x26240024, 0x8fbf001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x24050003,
+0x3021, 0xa00009c, 0x27bd0020, 0x27bdffd8,
+0xafb1001c, 0xafb00018, 0xafbf0020, 0x90a90030,
+0x24020001, 0xe05021, 0x3123003f, 0xa04021,
+0x8fb00040, 0x808821, 0xc04821, 0x10620014,
+0x8fa70038, 0x240b0005, 0xa02021, 0xc02821,
+0x106b0013, 0x2003021, 0xe000128, 0x0,
+0x9225007c, 0x30a40002, 0x10800003, 0x26030030,
+0xae000030, 0x26030034, 0x8fbf0020, 0x8fb1001c,
+0x8fb00018, 0x601021, 0x3e00008, 0x27bd0028,
+0xe0000a7, 0xafb00010, 0xa00016f, 0x0,
+0x8fa3003c, 0x1002021, 0x1202821, 0x1403021,
+0xafa30010, 0xe0000ee, 0xafb00014, 0xa00016f,
+0x0, 0x3c068000, 0x34c20e00, 0x8c440010,
+0x8f850044, 0xaca40020, 0x8c430018, 0x3e00008,
+0xaca30024, 0x3c068000, 0x34c20e00, 0x8c440014,
+0x8f850044, 0xaca40020, 0x8c43001c, 0x3e00008,
+0xaca30024, 0x9382000c, 0x1040001b, 0x2483000f,
+0x2404fff0, 0x643824, 0x10e00019, 0x978b0010,
+0x9784000e, 0x9389000d, 0x3c0a601c, 0xa0001ac,
+0x1644023, 0x1037021, 0x642823, 0x11260002,
+0x31c2ffff, 0x30a2ffff, 0x47302b, 0x50c0000e,
+0xe44821, 0x8d4d000c, 0x31a3ffff, 0x36400,
+0xc2c03, 0x4a1fff3, 0x3021, 0x30637fff,
+0xa0001a4, 0x24060001, 0x3e00008, 0x0,
+0x9784000e, 0xe44821, 0x3123ffff, 0x3168ffff,
+0x68382b, 0x54e0fff8, 0xa783000e, 0x938a000d,
+0x11400005, 0x240f0001, 0x6bc023, 0xa380000d,
+0x3e00008, 0xa798000e, 0x6bc023, 0xa38f000d,
+0x3e00008, 0xa798000e, 0x3e00008, 0x0,
+0x27bdffe8, 0xafb00010, 0x3c108000, 0x36030140,
+0x308bffff, 0x93aa002b, 0xafbf0014, 0xa46b0004,
+0x36040e00, 0x94880016, 0x30c600ff, 0x8fa90030,
+0xa4680006, 0xac650008, 0xa0660012, 0xa46a001a,
+0xac670020, 0x8fa5002c, 0xa4690018, 0x1202021,
+0xe000198, 0xac650014, 0x3c021000, 0xae020178,
0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x3c038000, 0x34620070, 0x8c490000, 0x8f87003c,
-0x24840007, 0x27bdfff8, 0x3084fff8, 0xaf890024,
-0x3c088000, 0x950e008a, 0x31cdffff, 0xafad0000,
-0x8fac0000, 0x1875823, 0x256affff, 0x31461fff,
-0xc4282b, 0x14a0fff7, 0x350d0070, 0x8dac0000,
-0x3c050800, 0x8ca50084, 0x3c0a0800, 0x8d4a0080,
-0x1895823, 0x1021, 0xabc021, 0x7c882,
-0x1422021, 0x30b302b, 0x193880, 0x35094000,
-0x867821, 0xe91021, 0x27bd0008, 0x3c010800,
-0xac380084, 0x3c010800, 0xac2f0080, 0x3e00008,
-0x0, 0x8f82003c, 0x24860007, 0x30c5fff8,
-0xa21821, 0x30641fff, 0x3e00008, 0xaf84003c,
-0x3c0320ff, 0x27bdffe8, 0x3c076000, 0x3c088000,
-0x24050010, 0x3464fffd, 0xace53008, 0xafbf0010,
-0xad040e00, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x3c0200ff, 0x345ffffd,
-0xad1f0e00, 0x3c0b6004, 0x8d785000, 0x2419ff7f,
-0x3c0e0002, 0x3197824, 0x35ec380c, 0x35cd0109,
-0xaced4c18, 0x24060009, 0xad6c5000, 0x8cea0438,
-0xad060008, 0xad000014, 0x8ce94c1c, 0x3145ffff,
-0x3c065709, 0x91e02, 0x38a42f71, 0x3062000f,
-0x34c80010, 0xaf820048, 0x10400007, 0x2485c0b3,
-0x8ceb4c1c, 0x3c0d001f, 0x35acfc00, 0x16c5024,
-0xa49c2, 0xaf890034, 0x8cf90808, 0x241ff000,
-0x33fc024, 0x3087026, 0x3067826, 0x2de80001,
-0x2dc60001, 0x1063825, 0x50e00009, 0xa3800038,
-0x3c09601c, 0x8d240008, 0x24030001, 0xa3830038,
-0x30827c00, 0xa780004c, 0xa380002e, 0xa782002c,
-0xaf800050, 0x14a00003, 0xaf80003c, 0x3c056000,
-0xaca0442c, 0xe000559, 0x0, 0x8fbf0010,
-0xa000e99, 0x27bd0018, 0x27bdffc8, 0xafb3002c,
-0xafb20028, 0xafbf0030, 0xafb10024, 0xafb00020,
-0x93620008, 0x809821, 0xa09021, 0x14400035,
-0x24040010, 0xe0001c9, 0x0, 0xe000168,
-0x408021, 0x2c400, 0x3c193200, 0x3198825,
-0xae110000, 0x936f0009, 0x976e0012, 0x936a000a,
-0x31ec00ff, 0x31cdffff, 0x18d5821, 0xb4400,
-0x314900ff, 0x1093825, 0xae070004, 0x8f850050,
-0x97840040, 0x403021, 0x30832000, 0x1460004d,
-0xae050008, 0xae00000c, 0x3c058000, 0x97840040,
-0x662004f, 0x8e03000c, 0x30900008, 0x16000002,
-0x26480006, 0x26480002, 0x94a40e14, 0x8ca50e1c,
-0x8f670004, 0x936a0002, 0x3084ffff, 0x314900ff,
-0xafa90010, 0x8f720014, 0xafa80018, 0xe0001af,
-0xafb20014, 0x8fbf0030, 0x8fb3002c, 0x8fb20028,
-0x8fb10024, 0x8fb00020, 0x24040010, 0xa0001f2,
-0x27bd0038, 0x93650009, 0x97710012, 0x936c000b,
-0x30ad00ff, 0x1b13021, 0x318b00ff, 0xcb8021,
-0x2602000a, 0x3050ffff, 0xe0001c9, 0x2002021,
-0xe000168, 0x408821, 0x93680009, 0x97640012,
-0x2fc00, 0x310900ff, 0x308affff, 0x12a3821,
-0x24e30002, 0x3e3c025, 0x3c194100, 0x3197825,
-0xae2f0000, 0x8f6e000c, 0x3c0d8000, 0x95ac0e14,
-0x1d32825, 0xae250004, 0x8da50e1c, 0x8f670004,
-0x936b0002, 0x3184ffff, 0x316600ff, 0xafa60010,
-0x8f680014, 0x403021, 0xafb20018, 0xe0001af,
-0xafa80014, 0x2002021, 0x8fbf0030, 0x8fb3002c,
-0x8fb20028, 0x8fb10024, 0x8fb00020, 0xa0001f2,
-0x27bd0038, 0x97620012, 0x3c058000, 0x97840040,
-0x305fffff, 0x661ffb4, 0xae1f000c, 0x8e03000c,
-0x3c078000, 0x679825, 0xa00026b, 0xae13000c,
-0x27bdffd8, 0xafb40020, 0xafbf0024, 0xafb3001c,
-0xafb20018, 0xafb10014, 0xafb00010, 0x93620008,
-0x14400094, 0x80a021, 0xaf60000c, 0x97850040,
-0x30a44000, 0x1080009e, 0x24030016, 0x24104007,
-0xa363000a, 0xaf700014, 0x938f0042, 0x8f6c0014,
-0x31ee0001, 0xe6a40, 0x18d5825, 0xaf6b0014,
-0x978a0040, 0x8f680014, 0x31490010, 0x1093825,
-0xaf670014, 0x97860040, 0x30c30008, 0x1060009f,
-0x0, 0x8f660014, 0x3c031000, 0x3c048000,
-0xc32825, 0xaf650014, 0x94820e0a, 0x3c1f8100,
-0x2413000e, 0x3059ffff, 0x33fc025, 0xaf780004,
-0xa3730002, 0x9372000a, 0x3406fffc, 0x26510004,
-0xa371000a, 0x97880040, 0x31072000, 0x10e00091,
-0x0, 0x3c0b8000, 0x97890040, 0x95680e0c,
-0x97840040, 0x91842, 0x3107c000, 0x30650003,
-0x71303, 0x309f1000, 0xa2c025, 0x1fca03,
-0x3199825, 0x1390c0, 0xa7720012, 0x97910040,
-0x936f000a, 0x118182, 0x320e003c, 0x1cf6821,
-0x25ac003c, 0xa36c0009, 0x956a0e0c, 0x31493fff,
-0xa7690010, 0x976d0012, 0x936c0009, 0x18d5821,
-0x256a0002, 0x31490007, 0x94023, 0x31030007,
-0xa363000b, 0x93670009, 0x97640012, 0x97650010,
-0x30e200ff, 0x8f900028, 0x97980040, 0x44f821,
-0x3e5c821, 0x3269821, 0x33120040, 0x12400005,
-0x3266ffff, 0xd0702b, 0x3c118000, 0x11c00016,
-0x9021, 0x206782b, 0x15e0002d, 0x2021,
-0x3c108000, 0x8e120e14, 0x3c058000, 0xae120e10,
-0x8e110e1c, 0xae110e18, 0xae060e00, 0x8cb80000,
-0x33130008, 0x1260fffd, 0x0, 0x94b90e08,
-0xc08021, 0x8821, 0xa7990040, 0x8ca60e04,
-0x24120001, 0xaf860028, 0x977f0010, 0x33f3ffff,
-0x8e890000, 0x1302023, 0x10800058, 0xae840000,
-0x2202021, 0xe000243, 0x2002821, 0x8e8c0000,
-0x15800005, 0x0, 0x8f6d0014, 0x240effbf,
-0x1aea024, 0xaf740014, 0x8f78000c, 0x3138821,
-0xaf71000c, 0x936f0008, 0x15e00003, 0x0,
-0x16400040, 0x0, 0xa3720008, 0x2002021,
-0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x801021, 0x3e00008,
-0x27bd0028, 0x8f900028, 0x97820040, 0x3c118000,
-0x2009821, 0x30450040, 0x14a0ffd9, 0x9021,
-0x97680010, 0x8f870028, 0x3103ffff, 0x1467ffec,
-0x2021, 0x8821, 0xa000339, 0x24120001,
-0x2403000e, 0x24104007, 0xa363000a, 0xaf700014,
-0x938f0042, 0x8f6c0014, 0x31ee0001, 0xe6a40,
-0x18d5825, 0xaf6b0014, 0x978a0040, 0x8f680014,
-0x31490010, 0x1093825, 0xaf670014, 0x97860040,
-0x30c30008, 0x1460ff63, 0x0, 0xaf600004,
-0xa3600002, 0x97880040, 0x31072000, 0x14e0ff71,
-0x3021, 0xa7600012, 0x97910040, 0x936f000a,
-0x3c0b8000, 0x32301f00, 0x107183, 0x1cf6821,
-0x25ac0028, 0xa36c0009, 0x956a0e0c, 0xa00030a,
-0xa76a0010, 0x8f660014, 0x3c1fefff, 0x37f9fffe,
-0xd99824, 0xa00034f, 0xaf730014, 0x8f6b0014,
-0x356a0040, 0xe00016e, 0xaf6a0014, 0xa00033e,
-0x2202021, 0x8f850044, 0x8f8a0030, 0x27bdffc0,
-0x3c048000, 0xafb70034, 0xafb40028, 0xafb1001c,
-0xafbf0038, 0xafb60030, 0xafb5002c, 0xafb30024,
-0xafb20020, 0xafb00018, 0x8c870104, 0x8ca90024,
-0xac8a0080, 0x8ca80020, 0xe98823, 0xb821,
-0xac880e10, 0x8ca60024, 0xa021, 0xac860e18,
-0x8c820e10, 0xac820e14, 0x8c830e18, 0xac830e1c,
-0x12200033, 0x3c168000, 0x936b0008, 0x11600054,
-0x0, 0x976e0010, 0x31cdffff, 0x22d602b,
-0x1580004f, 0x0, 0x97700010, 0x320fffff,
-0xaecf0e00, 0x3c058000, 0x8cb30000, 0x32720008,
-0x1240fffd, 0x0, 0x94b50e08, 0x8ca50e04,
-0x32b0ffff, 0x32140001, 0x12800044, 0x0,
-0xd, 0x3219a040, 0x24180040, 0x13380045,
-0x3214a000, 0x1280003f, 0x0, 0x93730008,
-0x12600009, 0x27a40010, 0x97620010, 0x305fffff,
-0xbfc82b, 0x53200005, 0xafb10010, 0x32080040,
-0x11000034, 0x0, 0xafb10010, 0xa7900040,
-0xaf850028, 0xe0002bd, 0x0, 0x40a021,
-0x104000be, 0x8fb10010, 0x1620ffcf, 0x0,
-0x2e960001, 0x2d78825, 0x12200017, 0x8fbf0038,
-0x8f850030, 0x24170f00, 0x10b70071, 0x3c048000,
-0x8c8f0178, 0x5e0fffe, 0x24180f00, 0x50b8008f,
-0x3c048000, 0x8c990e14, 0x24140240, 0x3c051000,
-0xac990144, 0x8c930e1c, 0xac930148, 0xa0800152,
-0xa480015a, 0xac800160, 0xa4800158, 0xac940154,
-0xac850178, 0x8fbf0038, 0x8fb70034, 0x8fb60030,
-0x8fb5002c, 0x8fb40028, 0x8fb30024, 0x8fb20020,
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0040,
-0xaed10e00, 0xa0003c3, 0x3c058000, 0x14a0ffbe,
-0x3219a040, 0xe000175, 0xa021, 0xa0003ea,
-0x2e960001, 0x3c038000, 0x8c7f0178, 0x7e0fffe,
-0x24020800, 0x8f84003c, 0xac620178, 0x3c038000,
-0x946b008a, 0x316affff, 0x1443823, 0x24e9ffff,
-0x31281fff, 0x2d060008, 0x14c0fff9, 0x346c4000,
-0xa0a021, 0xe000168, 0x8c9021, 0x8f830030,
-0x24040f00, 0x40a821, 0x2348823, 0x3c068000,
-0x10640005, 0x24050001, 0x938e0042, 0x31c50001,
-0x56a40, 0x35a50001, 0x15fc00, 0x3c020100,
-0x3e2c825, 0xae590000, 0x8f930050, 0x32180036,
-0x320f0008, 0xae530004, 0x11e00041, 0xb89825,
-0x94c30e0a, 0x8f84003c, 0x3c0b8100, 0x306affff,
-0x24920008, 0x32481fff, 0x14b4825, 0x3c071000,
-0x26920006, 0x2410000e, 0xacc90160, 0x2679825,
-0xa4d0015a, 0xaf88003c, 0xa4d20158, 0x16200008,
-0x3c108000, 0x8f8e0030, 0x24050f00, 0x51c50002,
-0x24170001, 0x36730040, 0xe00016e, 0x3c108000,
-0x8e180e14, 0x2402021, 0xae180144, 0x8e0f0e1c,
-0xae0f0148, 0xa2150152, 0xae130154, 0xe00017c,
-0x3c151000, 0xae150178, 0xa0003e7, 0x0,
-0x12800005, 0x3c078000, 0x94f20e08, 0x32490040,
-0x11200042, 0x0, 0x8c8a0178, 0x540fffe,
-0x0, 0x94950e10, 0x3c100500, 0x24032000,
-0x32aeffff, 0x1d06825, 0xac8d014c, 0x8c8c0e14,
-0x3c0b1000, 0xac8c0144, 0x8c860e1c, 0xac860148,
-0xa0800152, 0xa480015a, 0xac800160, 0xa4800158,
-0xac830154, 0xac8b0178, 0xa0003f1, 0x3c048000,
-0x8f8d003c, 0x26920002, 0xa4d20158, 0x25ac0008,
-0x31861fff, 0xa00044c, 0xaf86003c, 0xac80014c,
-0x12800019, 0x0, 0x8c9f0e10, 0xac9f0144,
-0x8c830e18, 0x3c088000, 0x24110040, 0xac830148,
-0x8fbf0038, 0xa1000152, 0x8fb70034, 0xa500015a,
-0x8fb60030, 0xad000160, 0x8fb5002c, 0xa5000158,
-0x8fb40028, 0xad110154, 0x8fb30024, 0x8fb20020,
-0x8fb1001c, 0x8fb00018, 0x3c041000, 0x27bd0040,
-0x3e00008, 0xad040178, 0x8c820e14, 0xac820144,
-0x8c830e1c, 0xa00048b, 0x3c088000, 0xe000175,
-0x2e960001, 0xa0003eb, 0x2d78825, 0x0,
-0xd, 0x0, 0x2400033a, 0xa000467,
-0x3c048000, 0x27bdffd8, 0xafb10014, 0x3c118000,
-0xafb00010, 0xafb40020, 0xafb3001c, 0xafb20018,
-0xafbf0024, 0x3c130800, 0x26733c34, 0xe0001f9,
-0x36300070, 0x3c140800, 0x26943cb4, 0x2009021,
-0x8e080000, 0x8e240000, 0x38830001, 0x30620001,
-0x10400016, 0x3c0a8000, 0x2404821, 0x8d270000,
-0x3c1f0800, 0x8fff006c, 0x3c0f0800, 0x8def0068,
-0xe81023, 0x3e26021, 0xc021, 0x182702b,
-0x1f86821, 0x1ae4021, 0x3c010800, 0xac2c006c,
-0x3c010800, 0xac280068, 0x8d4b0000, 0x39660001,
-0x30c50001, 0x14a0ffed, 0xe04021, 0x8e1f0000,
-0x3c180800, 0x8f18006c, 0x3c0d0800, 0x8dad0068,
-0x3e8c823, 0x3193821, 0x7021, 0xf9602b,
-0x1ae4021, 0x10c5821, 0x3c010800, 0xac27006c,
-0x3c010800, 0xac2b0068, 0x8e280100, 0x2406ff80,
-0x3c04800a, 0x25050240, 0xa64824, 0xae280020,
-0xae290024, 0x8e090000, 0x30a3007f, 0x645021,
-0x3c078000, 0xaf8a0044, 0xaf880030, 0xaf890024,
-0x8ce20178, 0x440fffe, 0x0, 0x8e1f0000,
-0x3c180800, 0x8f180074, 0x3c0d0800, 0x8dad0070,
-0x3e9c823, 0x3195821, 0x7021, 0x179302b,
-0x1ae6021, 0x1864821, 0x24050800, 0x3c010800,
-0xac2b0074, 0x3c010800, 0xac290070, 0xace50178,
-0x90e40108, 0xa3840042, 0x93830042, 0x306a0001,
-0x1140000f, 0x240e0d00, 0x2502f800, 0x2c470301,
-0x10e0001c, 0x819c2, 0x2464fff0, 0x45042,
-0xa4140, 0xe00039a, 0x113d821, 0x3c0a4000,
-0x3c088000, 0xad0a0138, 0xa0004bd, 0x0,
-0x110e0026, 0x240f0f00, 0x110f002a, 0x3c028008,
-0x34470080, 0x90ff0000, 0x24180050, 0x33f900ff,
-0x1738fff3, 0x3c0a4000, 0xe0009a3, 0x0,
-0x3c0a4000, 0x3c088000, 0xad0a0138, 0xa0004bd,
-0x0, 0x8f840034, 0x64282b, 0x14a0000b,
-0x8f860048, 0x866021, 0x258bffff, 0x163482b,
-0x15200006, 0x646823, 0xd1940, 0xe00039a,
-0x74d821, 0xa000519, 0x3c0a4000, 0x0,
-0xd, 0x0, 0x240003ad, 0xe00039a,
-0x0, 0xa000519, 0x3c0a4000, 0x3c1b0800,
-0x277b3db4, 0xe00039a, 0x0, 0xa000519,
-0x3c0a4000, 0x3c1b0800, 0x277b3dd4, 0xe00039a,
-0x0, 0xa000519, 0x3c0a4000, 0x8f820050,
-0x24430001, 0x304200ff, 0xaf830050, 0x3e00008,
-0x0, 0x411c0, 0x3e00008, 0x24420240,
-0x3c040800, 0x24843bcc, 0x2405001a, 0xa00007c,
-0x3021, 0x27bdffe0, 0xafbf001c, 0xafb20018,
-0xafb10014, 0xafb00010, 0x3c108000, 0x920b0109,
-0x2412ff80, 0xe000556, 0x3164007f, 0x8f910030,
-0x515021, 0x1524024, 0xae080024, 0x92030109,
-0xe000556, 0x3064007f, 0x24060080, 0x240700c0,
-0x24040040, 0xae000810, 0xae040814, 0xae060818,
-0xae07081c, 0x920c0109, 0x51f821, 0x33f8007f,
-0x3c19800a, 0x3191021, 0x3184007f, 0xe000556,
-0xaf820044, 0x8e110100, 0x3c0c0080, 0x35850001,
-0x2227821, 0x1f24824, 0xae090804, 0x8e0e0100,
-0x35980002, 0x36090900, 0x1c26821, 0x31ab0078,
-0x1655025, 0xae0a0820, 0x8e050100, 0x8e080100,
-0x36050980, 0x1021821, 0x24640040, 0x923024,
-0xae060808, 0x8e070100, 0xe2f821, 0x27f90040,
-0x33320078, 0x2588825, 0xae110824, 0x8e040100,
-0x952f000c, 0x8fbf001c, 0x8fb20018, 0x31eeffff,
-0xe69c0, 0xae0d0800, 0xae0c0828, 0x952b000c,
-0x8fb10014, 0x316affff, 0xa41c0, 0xae08002c,
-0x8ca30050, 0x8fb00010, 0x8ca2003c, 0x8d240004,
-0x8ca6001c, 0x8ca70038, 0x27bd0020, 0xaf830068,
-0xaf820058, 0xaf840054, 0xaf860060, 0x3e00008,
-0xaf870064, 0x3c0a0800, 0x914a3bf1, 0x3c090800,
-0x95293bea, 0x3c051100, 0xa3c00, 0x25280002,
-0xe83025, 0xc51825, 0x24820008, 0xac830000,
-0x3e00008, 0xac800004, 0x3c088000, 0x35070900,
-0x90e60011, 0x24020028, 0x805021, 0x30c300ff,
-0xa06021, 0x10620002, 0x340b86dd, 0x240b0800,
-0x3c078000, 0x34e20a9a, 0x94590000, 0x34ef0a9c,
-0x34ed0aa0, 0x3338ffff, 0xad580000, 0x8dee0000,
-0x34e80a80, 0x24040001, 0xad4e0004, 0x8da90000,
-0xad490008, 0x91050019, 0x30a30003, 0x10640043,
-0x28660002, 0x14c000b0, 0x24040002, 0x1064008b,
-0x24050003, 0x10650096, 0x34e60aa4, 0x3c090800,
-0x95293be0, 0x24020800, 0x5162004d, 0x3c0e8000,
-0x3c0e8000, 0x35c50900, 0x90a60012, 0x90b90019,
-0x35cb0980, 0x8d680028, 0x30c700ff, 0x77880,
-0x3138ffff, 0x332300ff, 0x1f81021, 0x32500,
-0x887025, 0x25c00, 0x3c0d6000, 0x1cd3025,
-0x356906ff, 0xad490004, 0xad460000, 0x8ca7002c,
-0x25490028, 0xad470008, 0x8cb90030, 0xad59000c,
-0x8cb80034, 0xad580010, 0x8caf0038, 0xad4f0014,
-0x8ca3001c, 0xad430018, 0x8ca80020, 0x3c038000,
-0x3462093c, 0xad48001c, 0x8ca40024, 0x346f0900,
-0xad440020, 0x8cad0028, 0xad4d0024, 0x8c590000,
-0xad2c0004, 0x25220014, 0xad390000, 0x8c78010c,
-0xad380008, 0x91e80012, 0x3c040800, 0x90843bf0,
-0xad200010, 0x82f00, 0x46c00, 0xad6025,
-0x358affff, 0x3e00008, 0xad2a000c, 0x3c090800,
-0x95293be0, 0x3c0f0800, 0x95ef3bea, 0x34f90aa4,
-0x3c0e0800, 0x95ce3bdc, 0x97280000, 0x3138ffff,
-0x1f86821, 0x1ae3823, 0x82c00, 0x24e3fff2,
-0xa32025, 0x24020800, 0xad44000c, 0xad400010,
-0xad4b0014, 0x1562ffb6, 0x254a0018, 0x3c0e8000,
-0x35cd0900, 0x91a20011, 0x91a70019, 0x3c050800,
-0x94a53be6, 0x304600ff, 0x35cb0a80, 0x956e002a,
-0x6c882, 0x30f800ff, 0x9787005c, 0x191e00,
-0x187c00, 0x3128ffff, 0xa82021, 0x6f4825,
-0x1241025, 0x1c73021, 0x3c0b4000, 0x4bc825,
-0x6c400, 0xad590000, 0xad580004, 0x91af0018,
-0x3c030006, 0x24e90001, 0xf4600, 0x1037025,
-0xad4e0008, 0x8da5002c, 0x3c038000, 0x3462093c,
-0xad45000c, 0x8dab001c, 0x31247fff, 0x25490014,
-0xad4b0010, 0x8c590000, 0xad2c0004, 0x346f0900,
-0xad390000, 0x8c78010c, 0xa784005c, 0x25220014,
-0xad380008, 0x91e80012, 0x3c040800, 0x90843bf0,
-0xad200010, 0x82f00, 0x46c00, 0xad6025,
-0x358affff, 0x3e00008, 0xad2a000c, 0x34e20aa4,
-0x94460000, 0x95190028, 0x3c090800, 0x95293be0,
-0x6c400, 0x197c00, 0x370e8100, 0x1eb6825,
-0xad4e000c, 0xad4d0010, 0xa0005e2, 0x254a0014,
-0x3c090800, 0x95293be0, 0x3c180800, 0x97183bea,
-0x3c0f0800, 0x95ef3bdc, 0x94ce0000, 0x3139ffff,
-0x950d0028, 0x3194021, 0x10f3823, 0xe2400,
-0xd2c00, 0x24e3ffee, 0xa33025, 0x34828100,
-0xad42000c, 0xad460010, 0xad400014, 0xad4b0018,
-0xa0005e2, 0x254a001c, 0x1460ff54, 0x34e90aa4,
-0x95280000, 0x3c090800, 0x95293be0, 0x83c00,
-0xeb1825, 0xad43000c, 0xa0005e2, 0x254a0010,
-0x3e00008, 0x240207d0, 0x27bdffe0, 0xafb20018,
-0xafb10014, 0xafb00010, 0xafbf001c, 0xe00005c,
-0x808821, 0x8f880058, 0x8f870054, 0x3c058008,
-0x34b20080, 0x1112821, 0x3c108000, 0x24020080,
-0x240300c0, 0xa72023, 0xae020818, 0x3c068008,
-0xae03081c, 0x18800004, 0xaf850058, 0xacc50004,
-0x8cc90004, 0xaf890054, 0x12200009, 0x36040980,
-0xe000695, 0x0, 0x924c0027, 0x8e0b0074,
-0x1825004, 0x14b3021, 0xae46000c, 0x36040980,
-0x8c8e001c, 0x8f8f0060, 0x1cf6823, 0x19a00004,
-0x8fbf001c, 0x8c90001c, 0xaf900060, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa00005e,
-0x27bd0020, 0x8f860068, 0x8f830058, 0x8f820054,
-0x3c058008, 0x34a40080, 0xac860050, 0xac83003c,
-0x3e00008, 0xaca20004, 0x3c038000, 0x34670070,
-0x8ce30000, 0x308700ff, 0x3c040800, 0x8c840054,
-0x27bdfff8, 0x30aa00ff, 0x24820001, 0x3c010800,
-0xac220054, 0x30c800ff, 0xaf830024, 0x3c098000,
-0x8d250178, 0x4a0fffe, 0x352b0070, 0x8d650000,
-0xa3a70003, 0x3c180800, 0x8f180074, 0x8fb90000,
-0x3c0d0800, 0x8dad0070, 0xa33823, 0x3c047fff,
-0xe07821, 0x3482ffff, 0x3073821, 0x7021,
-0x3225824, 0x1ae3021, 0xef602b, 0x847c0,
-0xcc1821, 0x1682825, 0xafa50000, 0x3c010800,
-0xac270074, 0x3c010800, 0xac230070, 0x9124010a,
-0xa3a00002, 0x3c0280ff, 0xa3a40001, 0x8fb80000,
-0x314f007f, 0x3459ffff, 0x3196824, 0xf7600,
-0x3c0b0020, 0x1ae6025, 0x356a2000, 0x2408ff80,
-0x3c061000, 0x27bd0008, 0xad2c014c, 0xad2a0154,
-0xa5200158, 0xa1280152, 0x3e00008, 0xad260178,
-0x3c038000, 0x34620070, 0x8c480000, 0x308a00ff,
-0x30a900ff, 0xaf880024, 0x3c048000, 0x8c850178,
-0x4a0fffe, 0x34870070, 0x8ceb0000, 0x3c050800,
-0x8ca50074, 0x3c190800, 0x8f390070, 0x1682023,
-0xa47021, 0x1021, 0x1c4c02b, 0x3227821,
-0x3c078000, 0x1f86821, 0x3c010800, 0xac2e0074,
-0x34e60a00, 0x3c010800, 0xac2d0070, 0x8ccc0020,
-0x9582b, 0x34e80980, 0xacec0144, 0x8cc90024,
-0xb1540, 0xace90148, 0xa0ea0150, 0x9104004c,
-0xa0e4016d, 0x3e00008, 0xa4e00158, 0x27bdffe8,
-0x308400ff, 0xafbf0010, 0xe00070d, 0x30a500ff,
-0x8f830058, 0x8fbf0010, 0x3c058000, 0x34460040,
-0x2404ff90, 0x3c021000, 0x27bd0018, 0xaca3014c,
-0xa0a40152, 0xaca60154, 0x3e00008, 0xaca20178,
-0x27bdffe0, 0x3c088008, 0xafbf001c, 0xafb20018,
-0xafb10014, 0xafb00010, 0x35100080, 0x8e060018,
-0x3c078000, 0x309200ff, 0xc72025, 0xae040018,
-0xe00005c, 0x30b100ff, 0x92030005, 0x34620008,
-0xe00005e, 0xa2020005, 0x2402021, 0xe000734,
-0x2202821, 0x2402021, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x24050005, 0x24060001,
-0xa0006cf, 0x27bd0020, 0x3c088000, 0x27bdffe8,
-0xafb00010, 0x35050980, 0xafbf0014, 0x90a70009,
-0x24020006, 0x35060900, 0x30e300ff, 0x24100004,
-0x10620072, 0x24080002, 0x94ae005c, 0x3c0d0204,
-0x31ccffff, 0x18d5825, 0xac8b0000, 0x90aa0008,
-0x31490020, 0x11200008, 0x0, 0x90bf004e,
-0x3c190103, 0x37380300, 0x33ef00ff, 0x1f82825,
-0x24100008, 0xac850004, 0x90cc0011, 0x90c90011,
-0x318a00ff, 0xa5882, 0x312700ff, 0x256a0005,
-0xa1080, 0x38e30028, 0x14600029, 0x824823,
-0x90cf0012, 0x3c198000, 0x37220900, 0x31e500ff,
-0x57080, 0x1d06821, 0xd3400, 0x34c406ff,
-0xad240004, 0x904c0011, 0x90580012, 0x373f0980,
-0x8fe40034, 0x8f2f010c, 0x105882, 0x330500ff,
-0xab7021, 0x83400, 0x8f1823, 0xe6f00,
-0x1a61025, 0x319f00fc, 0x3067ffff, 0x3e9c021,
-0x47c825, 0x14b7821, 0xf2880, 0xaf19000c,
-0xe00005c, 0x1258021, 0x3c0a8008, 0x24090004,
-0x35480080, 0xe00005e, 0xa1090009, 0x2001021,
+0x8f850000, 0x24840007, 0x27bdfff8, 0x3084fff8,
+0x3c068000, 0x94cb008a, 0x316affff, 0xafaa0000,
+0x8fa90000, 0x1254023, 0x2507ffff, 0x30e31fff,
+0x64102b, 0x1440fff7, 0x56882, 0xd2880,
+0x34cc4000, 0xac1021, 0x3e00008, 0x27bd0008,
+0x8f820000, 0x24860007, 0x30c5fff8, 0xa21821,
+0x30641fff, 0x3e00008, 0xaf840000, 0x8f87003c,
+0x8f840044, 0x27bdffb0, 0xafb70044, 0xafb40038,
+0xafb1002c, 0xafbf0048, 0xafb60040, 0xafb5003c,
+0xafb30034, 0xafb20030, 0xafb00028, 0x3c0b8000,
+0x8c860024, 0xad670080, 0x8c8a0020, 0x35670e00,
+0x35690100, 0xacea0010, 0x8c880024, 0x8d250004,
+0xb821, 0xace80018, 0x8ce30010, 0xa68823,
+0xa021, 0xace30014, 0x8ce20018, 0xace2001c,
+0x122000fe, 0xe0b021, 0x936c0008, 0x118000f4,
+0x0, 0x976f0010, 0x31eeffff, 0x22e682b,
+0x15a000ef, 0x0, 0x97720010, 0x3250ffff,
+0xaed00000, 0x3c038000, 0x8c740000, 0x32930008,
+0x1260fffd, 0x0, 0x96d80008, 0x8ec70004,
+0x3305ffff, 0x30b50001, 0x12a000e4, 0x0,
+0xd, 0x30bfa040, 0x24190040, 0x13f9011b,
+0x30b4a000, 0x128000df, 0x0, 0x93730008,
+0x12600008, 0x0, 0x976d0010, 0x31acffff,
+0xec202b, 0x10800003, 0x30ae0040, 0x11c000d5,
+0x0, 0xa7850040, 0xaf870038, 0x93630008,
+0x2202821, 0xafb10020, 0x146000f5, 0x27b40020,
+0xaf60000c, 0x978f0040, 0x31f14000, 0x16200002,
+0x24030016, 0x2403000e, 0x24054007, 0xa363000a,
+0xaf650014, 0x938a0042, 0x8f700014, 0x31550001,
+0x151240, 0x2024825, 0xaf690014, 0x979f0040,
+0x8f780014, 0x33f90010, 0x3194025, 0xaf680014,
+0x97920040, 0x32470008, 0x10e0016e, 0x0,
+0x8f670014, 0x3c121000, 0x3c118000, 0xf27825,
+0xaf6f0014, 0x36230e00, 0x946e000a, 0x3c0d8100,
+0x2406000e, 0x31ccffff, 0x18d2025, 0xaf640004,
+0xa3660002, 0x9373000a, 0x3406fffc, 0x266b0004,
+0xa36b000a, 0x97980040, 0x33082000, 0x1100015f,
+0x0, 0x3c058000, 0x34a90e00, 0x97990040,
+0x9538000c, 0x97870040, 0x194042, 0x3312c000,
+0x31030003, 0x127b03, 0x30f11000, 0x6f6825,
+0x117203, 0x1ae6025, 0xc20c0, 0xa7640012,
+0x97930040, 0x936a000a, 0x135982, 0x3175003c,
+0x2aa1021, 0x2450003c, 0xa3700009, 0x953f000c,
+0x33f93fff, 0xa7790010, 0x97700012, 0x93690009,
+0x130f821, 0x27e50002, 0x30b90007, 0x19c023,
+0x33080007, 0xa368000b, 0x93710009, 0x97720012,
+0x976f0010, 0x322700ff, 0x8f910038, 0x978d0040,
+0xf21821, 0x6f7021, 0x1c66021, 0x31a60040,
+0x10c00005, 0x3185ffff, 0xb1102b, 0x3c128000,
+0x10400017, 0x9821, 0x225a82b, 0x56a0013e,
+0x8fa50020, 0x3c048000, 0x348a0e00, 0x8d530014,
+0x3c068000, 0xad530010, 0x8d4b001c, 0xad4b0018,
+0xad450000, 0x8ccd0000, 0x31ac0008, 0x1180fffd,
+0x34ce0e00, 0x95c30008, 0xa08821, 0x9021,
+0xa7830040, 0x8dc60004, 0x24130001, 0xaf860038,
+0x976f0010, 0x31f5ffff, 0x8e9f0000, 0x3f12823,
+0x10a0011f, 0xae850000, 0x93620008, 0x144000dd,
+0x0, 0xe0001e7, 0x24040010, 0x8f900048,
+0x402821, 0x3c023200, 0x320600ff, 0x65400,
+0x142f825, 0x26090001, 0xaf890048, 0xacbf0000,
+0x93790009, 0x97780012, 0x936f000a, 0x332800ff,
+0x3303ffff, 0x1033821, 0x76c00, 0x31ee00ff,
+0x1ae6025, 0xacac0004, 0x8f840048, 0x978b0040,
+0x316a2000, 0x1140010a, 0xaca40008, 0x97640012,
+0x308bffff, 0x6400108, 0xacab000c, 0x978e0040,
+0x31c50008, 0x14a00002, 0x26280006, 0x26280002,
+0x3c1f8000, 0x37e70e00, 0x94f90014, 0x8ce5001c,
+0x8f670004, 0x93780002, 0x3324ffff, 0x330300ff,
+0xafa30010, 0x8f6f0014, 0xafa80018, 0xe0001cb,
+0xafaf0014, 0x24040010, 0xe0001fb, 0x0,
+0x8e920000, 0x16400005, 0x0, 0x8f780014,
+0x2403ffbf, 0x303a024, 0xaf740014, 0x8f67000c,
+0xf5c821, 0xaf79000c, 0x93750008, 0x16a00008,
+0x0, 0x12600006, 0x0, 0x8f680014,
+0x3c0aefff, 0x3549fffe, 0x109f824, 0xaf7f0014,
+0xa3730008, 0x8fa50020, 0xa00034f, 0x2202021,
+0xaed10000, 0xa00022d, 0x3c038000, 0x14e0ff1e,
+0x30bfa040, 0xe000190, 0xa021, 0x2e910001,
+0x237b025, 0x12c00018, 0x8fbf0048, 0x8f87003c,
+0x24170f00, 0x10f700d4, 0x3c068000, 0x8cd90178,
+0x720fffe, 0x241f0f00, 0x10ff00f6, 0x34ca0e00,
+0x8d560014, 0x34c70140, 0x24080240, 0xacf60004,
+0x8d49001c, 0x3c141000, 0xace90008, 0xa0e00012,
+0xa4e0001a, 0xace00020, 0xa4e00018, 0xace80014,
+0xacd40178, 0x8fbf0048, 0x8fb70044, 0x8fb60040,
+0x8fb5003c, 0x8fb40038, 0x8fb30034, 0x8fb20030,
+0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0050,
+0x8f910038, 0x97880040, 0x3c128000, 0x220a821,
+0x31070040, 0x14e0ff7c, 0x9821, 0x97790010,
+0x8f920038, 0x3338ffff, 0x131200a8, 0x2021,
+0x80a021, 0x108000f3, 0xa08821, 0x1620fece,
+0x0, 0xa00031f, 0x2e910001, 0x3c038000,
+0x8c620178, 0x440fffe, 0x24080800, 0x8f860000,
+0xac680178, 0x3c038000, 0x946d008a, 0x31acffff,
+0x1865823, 0x256affff, 0x31441fff, 0x2c890008,
+0x1520fff9, 0x0, 0x8f8f0048, 0x34704000,
+0x8f83003c, 0xe0a021, 0x240e0f00, 0x25e70001,
+0xaf870048, 0xd03021, 0x2348823, 0x3c088000,
+0x31f500ff, 0x106e0005, 0x24070001, 0x93980042,
+0x33130001, 0x139240, 0x36470001, 0x152400,
+0x3c0a0100, 0x8a4825, 0xacc90000, 0x8f820048,
+0x30bf0036, 0x30b90008, 0xacc20004, 0x13200099,
+0xff9825, 0x35120e00, 0x9650000a, 0x8f870000,
+0x3c0f8100, 0x3203ffff, 0x24ed0008, 0x35060140,
+0x6f6025, 0x3c0e1000, 0x31ab1fff, 0x26920006,
+0x2405000e, 0xaccc0020, 0x26e9825, 0xa4c5001a,
+0xaf8b0000, 0xa4d20018, 0x16200008, 0x3c108000,
+0x8f89003c, 0x24020f00, 0x51220002, 0x24170001,
+0x36730040, 0xe000188, 0x3c108000, 0x36060e00,
+0x8ccb0014, 0x360a0140, 0x2402021, 0xad4b0004,
+0x8cc5001c, 0xad450008, 0xa1550012, 0xad530014,
+0xe000198, 0x3c151000, 0xae150178, 0xa000352,
+0x0, 0x936f0009, 0x976e0012, 0x936d000b,
+0x31e500ff, 0xae2021, 0x31ac00ff, 0x8c8021,
+0x2602000a, 0x3050ffff, 0xe0001e7, 0x2002021,
+0x8f860048, 0x3c034100, 0x3c058000, 0x24cb0001,
+0xaf8b0048, 0x936a0009, 0x97690012, 0x30c600ff,
+0x315f00ff, 0x3128ffff, 0x3e83821, 0x24f90002,
+0x6c400, 0x3197825, 0x1e37025, 0xac4e0000,
+0x8f6d000c, 0x34a40e00, 0x948b0014, 0x1b26025,
+0xac4c0004, 0x8c85001c, 0x8f670004, 0x936a0002,
+0x3164ffff, 0x314900ff, 0xafa90010, 0x8f680014,
+0xafb10018, 0xe0001cb, 0xafa80014, 0xa0002fd,
+0x2002021, 0xaf600004, 0xa3600002, 0x97980040,
+0x33082000, 0x1500fea3, 0x3021, 0xa7600012,
+0x97840040, 0x936b000a, 0x3c108000, 0x30931f00,
+0x135183, 0x14ba821, 0x26a20028, 0xa3620009,
+0x36090e00, 0x953f000c, 0xa000295, 0xa77f0010,
+0x8f700014, 0x36090040, 0xe000188, 0xaf690014,
+0xa0002c9, 0x0, 0xa00034f, 0x2021,
+0x641fefa, 0xaca0000c, 0x8cac000c, 0x3c0d8000,
+0x18d9025, 0xa0002ea, 0xacb2000c, 0x9021,
+0xa0002c5, 0x24130001, 0x12800007, 0x3c028000,
+0x344b0e00, 0x95660008, 0x30d30040, 0x12600049,
+0x0, 0x3c068000, 0x8cd00178, 0x600fffe,
+0x34c50e00, 0x94b50010, 0x3c030500, 0x34cc0140,
+0x32b8ffff, 0x3039025, 0xad92000c, 0x8caf0014,
+0x240d2000, 0x3c041000, 0xad8f0004, 0x8cae001c,
+0xad8e0008, 0xa1800012, 0xa580001a, 0xad800020,
+0xa5800018, 0xad8d0014, 0xacc40178, 0xa000326,
+0x3c068000, 0x8f9f0000, 0x35180140, 0x26920002,
+0x27f90008, 0x33281fff, 0xa7120018, 0xa000391,
+0xaf880000, 0x3c028000, 0x34450140, 0xaca0000c,
+0x1280001b, 0x34530e00, 0x34510e00, 0x8e370010,
+0xacb70004, 0x8e240018, 0x3c0b8000, 0xaca40008,
+0x35700140, 0x24040040, 0xa2000012, 0x8fbf0048,
+0xa600001a, 0x8fb70044, 0xae000020, 0x8fb60040,
+0xa6000018, 0x8fb5003c, 0xae040014, 0x8fb40038,
+0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
+0x3c021000, 0x27bd0050, 0x3e00008, 0xad620178,
+0x8e660014, 0xaca60004, 0x8e64001c, 0xa00042a,
+0x3c0b8000, 0xe000190, 0x2e910001, 0xa000320,
+0x237b025, 0x0, 0xd, 0x0,
+0x24000369, 0xa000401, 0x3c068000, 0x27bdffd8,
+0xafbf0020, 0x3c098000, 0x3c1f20ff, 0xafb20018,
+0x3c076000, 0x35320e00, 0x24020010, 0x37f9fffd,
+0xace23008, 0xafb3001c, 0xafb10014, 0xafb00010,
+0xae590000, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x3c1800ff, 0x3713fffd,
+0xae530000, 0x3c0b6004, 0x8d705000, 0x2411ff7f,
+0x3c0e0002, 0x2117824, 0x35ec380c, 0x35cd0109,
+0xaced4c18, 0x240a0009, 0xad6c5000, 0x8ce80438,
+0xad2a0008, 0xad200014, 0x8ce54c1c, 0x3106ffff,
+0x38c42f71, 0x51e02, 0x3062000f, 0x2486c0b3,
+0x10400007, 0xaf820008, 0x8ce54c1c, 0x3c09001f,
+0x3528fc00, 0xa81824, 0x321c2, 0xaf840004,
+0x8cf10808, 0x3c0f5709, 0x2412f000, 0x2327024,
+0x35f00010, 0x1d06026, 0x1cf6826, 0x2daa0001,
+0x2d8b0001, 0x14b3825, 0x50e00009, 0xa380000c,
+0x3c1f601c, 0x8ff80008, 0x24190001, 0xa399000c,
+0x33137c00, 0xa7930010, 0xa780000e, 0xa380000d,
+0xaf800048, 0x14c00003, 0xaf800000, 0x3c066000,
+0xacc0442c, 0xe0005b9, 0x3c108000, 0xe000f24,
+0x36110100, 0x3c120800, 0x26523df0, 0x3c130800,
+0x26733e70, 0x8e030000, 0x38640001, 0x30820001,
+0x1440fffc, 0x3c0b800a, 0x8e260000, 0x2407ff80,
+0x24c90240, 0x312a007f, 0x14b4021, 0x1272824,
+0xae060020, 0xaf880044, 0xae050024, 0x3c048000,
+0xaf86003c, 0x8c8c0178, 0x580fffe, 0x24180800,
+0x922f0008, 0xac980178, 0xa38f0042, 0x938e0042,
+0x31cd0001, 0x11a0000f, 0x24050d00, 0x24dff800,
+0x2ff90301, 0x1320001c, 0x629c2, 0x24a4fff0,
+0x41042, 0x23140, 0xe000202, 0xd2d821,
+0x3c024000, 0x3c068000, 0xacc20138, 0xa0004a0,
+0x0, 0x10c50023, 0x240d0f00, 0x10cd0027,
+0x3c1f8008, 0x37f90080, 0x93380000, 0x240e0050,
+0x330f00ff, 0x15eefff3, 0x3c024000, 0xe000a40,
+0x0, 0x3c024000, 0x3c068000, 0xacc20138,
+0xa0004a0, 0x0, 0x8f830004, 0xa3402b,
+0x1500000b, 0x8f8b0008, 0x6b5021, 0x2547ffff,
+0xe5482b, 0x15200006, 0xa36023, 0xc1940,
+0xe000202, 0x73d821, 0xa0004c4, 0x3c024000,
+0xd, 0xe000202, 0x0, 0xa0004c4,
+0x3c024000, 0x3c1b0800, 0x277b3f70, 0xe000202,
+0x0, 0xa0004c4, 0x3c024000, 0x3c1b0800,
+0x277b3f90, 0xe000202, 0x0, 0xa0004c4,
+0x3c024000, 0x3c066004, 0x3c090800, 0x25290104,
+0xacc9502c, 0x8cc85000, 0x3c058000, 0x3c020002,
+0x35070080, 0xacc75000, 0x3c040800, 0x248415a4,
+0x3c030800, 0x2463155c, 0xaca50008, 0xaca2000c,
+0x3c010800, 0xac243d80, 0x3c010800, 0xac233d84,
+0x3e00008, 0x24020001, 0xa03021, 0x3c1c0800,
+0x279c3d88, 0x3c0c0400, 0x3c0b0002, 0x8b3826,
+0x8c4026, 0x2ce20001, 0x7502b, 0x2d050001,
+0xa4880, 0x3c030800, 0x24633d80, 0x452025,
+0x1231821, 0x10800003, 0x1021, 0xac660000,
+0x24020001, 0x3e00008, 0x0, 0x3c1c0800,
+0x279c3d88, 0x3c0b0400, 0x3c0a0002, 0x8a3026,
+0x8b3826, 0x2cc20001, 0x6482b, 0x2ce50001,
+0x94080, 0x3c030800, 0x24633d80, 0x452025,
+0x1031821, 0x10800005, 0x1021, 0x3c0c0800,
+0x258c155c, 0xac6c0000, 0x24020001, 0x3e00008,
+0x0, 0x3c090002, 0x3c080400, 0x883026,
+0x893826, 0x2cc30001, 0x802821, 0x2ce40001,
+0x831025, 0x1040000b, 0x3021, 0x3c1c0800,
+0x279c3d88, 0x3c0a8000, 0x8d4e0008, 0x24060001,
+0x1ca6825, 0xad4d0008, 0x8d4c000c, 0x1855825,
+0xad4b000c, 0x3e00008, 0xc01021, 0x3c1c0800,
+0x279c3d88, 0x3c058000, 0x8ca6000c, 0x42027,
+0x24020001, 0xc41824, 0x3e00008, 0xaca3000c,
+0x3c020002, 0x1082000b, 0x3c056000, 0x3c070400,
+0x10870003, 0x0, 0x3e00008, 0x0,
+0x8ca908d0, 0x240afffd, 0x12a4024, 0x3e00008,
+0xaca808d0, 0x8ca408d0, 0x2406fffe, 0x861824,
+0x3e00008, 0xaca308d0, 0x3c05601a, 0x34a60010,
+0x8cc30080, 0x27bdfff8, 0x8cc50084, 0xafa30000,
+0x93a40000, 0x24020001, 0x10820003, 0xafa50004,
+0x3e00008, 0x27bd0008, 0x93a70001, 0x14e00014,
+0x97ac0002, 0x97b80002, 0x3c0f8000, 0x330efffc,
+0x1cf6821, 0xada50000, 0xa3a00000, 0x3c066000,
+0x8cc708d0, 0x2408fffe, 0x3c04601a, 0xe82824,
+0xacc508d0, 0x8fa30004, 0x8fa20000, 0x34990010,
+0x27bd0008, 0xaf220080, 0x3e00008, 0xaf230084,
+0x3c0b8000, 0x318afffc, 0x14b4821, 0x8d280000,
+0xa00057d, 0xafa80004, 0x27bdffe8, 0xafbf0010,
+0x3c1c0800, 0x279c3d88, 0x3c058000, 0x8ca4000c,
+0x8ca20004, 0x3c030002, 0x442824, 0x10a0000a,
+0xa31824, 0x3c060400, 0x3c040002, 0x14600009,
+0xa61024, 0x1440000f, 0x3c040400, 0xd,
+0x3c1c0800, 0x279c3d88, 0x8fbf0010, 0x3e00008,
+0x27bd0018, 0x3c020800, 0x8c423d80, 0x40f809,
+0x0, 0x3c1c0800, 0x279c3d88, 0xa0005a6,
+0x8fbf0010, 0x3c020800, 0x8c423d84, 0x40f809,
+0x0, 0xa0005ac, 0x0, 0x411c0,
+0x3e00008, 0x24420240, 0x3c040800, 0x24843fd4,
+0x2405001a, 0xa00009c, 0x3021, 0x27bdffe0,
+0xafb00010, 0x3c108000, 0xafbf0018, 0xafb10014,
+0x36110100, 0x92220009, 0xe0005b6, 0x3044007f,
+0x8e3f0000, 0x8f89003c, 0x3c0f0080, 0x3e26021,
+0x25880040, 0x49f821, 0x240dff80, 0x310e0078,
+0x31980078, 0x35f90001, 0x35f10002, 0x3193825,
+0x1d14825, 0x10d3024, 0x3ed5824, 0x18d2824,
+0x240a0040, 0x24040080, 0x240300c0, 0xae0b0024,
+0xae000810, 0xae0a0814, 0xae040818, 0xae03081c,
+0xae050804, 0xae070820, 0xae060808, 0xae090824,
+0x36090900, 0x9539000c, 0x36050980, 0x33ed007f,
+0x3338ffff, 0x1889c0, 0xae110800, 0xae0f0828,
+0x952c000c, 0x8fbf0018, 0x8fb10014, 0x318bffff,
+0xb51c0, 0xae0a002c, 0x8ca40050, 0x8fb00010,
+0x8ca3003c, 0x8d270004, 0x8ca8001c, 0x8ca60038,
+0x3c0e800a, 0x1ae1021, 0x27bd0020, 0xaf820044,
+0xaf840050, 0xaf830054, 0xaf87004c, 0xaf88005c,
+0x3e00008, 0xaf860060, 0x3c090800, 0x91293ff9,
+0x24a80002, 0x3c051100, 0x93c00, 0xe83025,
+0xc51825, 0x24820008, 0xac830000, 0x3e00008,
+0xac800004, 0x3c098000, 0x35230900, 0x9128010b,
+0x906a0011, 0x24020028, 0x804821, 0x314700ff,
+0xa07021, 0xc06821, 0x31080040, 0x10e20002,
+0x340c86dd, 0x240c0800, 0x3c0a8000, 0x35420a9a,
+0x94470000, 0x354b0a9c, 0x35460aa0, 0x30f9ffff,
+0xad390000, 0x8d780000, 0x354b0a80, 0x24040001,
+0xad380004, 0x8ccf0000, 0xad2f0008, 0x91650019,
+0x30a30003, 0x1064009a, 0x28640002, 0x148000b9,
+0x24050002, 0x106500a8, 0x240f0003, 0x106f00be,
+0x35450aa4, 0x240a0800, 0x118a004d, 0x0,
+0x51000042, 0x3c0b8000, 0x3c048000, 0x34830900,
+0x90670012, 0x30e200ff, 0x4d7821, 0xfc880,
+0x27240001, 0x3c0a8000, 0x354f0900, 0x91e50019,
+0x354c0980, 0x8d870028, 0x30a300ff, 0x31500,
+0x475825, 0x4c400, 0x3c196000, 0x1793025,
+0x370806ff, 0xad260000, 0xad280004, 0x8dea002c,
+0x25280028, 0xad2a0008, 0x8dec0030, 0xad2c000c,
+0x8de50034, 0xad250010, 0x8de40038, 0xad240014,
+0x8de3001c, 0xad230018, 0x8de70020, 0xad27001c,
+0x8de20024, 0xad220020, 0x8df90028, 0xad390024,
+0x3c098000, 0x3526093c, 0x8ccf0000, 0x352a0100,
+0xad0e0004, 0xad0f0000, 0x8d4e000c, 0x35230900,
+0x35250980, 0xad0e0008, 0x906c0012, 0x8d47000c,
+0x8cb90034, 0x3c180800, 0x93183ff8, 0x318200ff,
+0x4d5821, 0x3277823, 0xb3700, 0x182400,
+0xc47025, 0x31e9fffc, 0x1c96825, 0x25020014,
+0xad0d000c, 0x3e00008, 0xad000010, 0x35780900,
+0x93060012, 0x3c050800, 0x94a53fe8, 0x30c800ff,
+0x10d5021, 0xa6080, 0xa00063c, 0x1852021,
+0x15000060, 0x0, 0x3c080800, 0x95083fee,
+0x3c060800, 0x94c63fe8, 0x1061021, 0x3c0b8000,
+0x35790900, 0x93380011, 0x932a0019, 0x35660a80,
+0x330800ff, 0x94cf002a, 0x86082, 0x314500ff,
+0x978a0058, 0xc1e00, 0x52400, 0x3047ffff,
+0x641025, 0x47c025, 0x1ea3021, 0x3c0b4000,
+0x30b4025, 0x66400, 0xad280000, 0xad2c0004,
+0x93250018, 0x3c030006, 0x25280014, 0x53e00,
+0xe31025, 0xad220008, 0x8f24002c, 0x254f0001,
+0x31eb7fff, 0xad24000c, 0x8f38001c, 0xa78b0058,
+0xad380010, 0x3c098000, 0x3526093c, 0x8ccf0000,
+0x352a0100, 0xad0e0004, 0xad0f0000, 0x8d4e000c,
+0x35230900, 0x35250980, 0xad0e0008, 0x906c0012,
+0x8d47000c, 0x8cb90034, 0x3c180800, 0x93183ff8,
+0x318200ff, 0x4d5821, 0x3277823, 0xb3700,
+0x182400, 0xc47025, 0x31e9fffc, 0x1c96825,
+0x25020014, 0xad0d000c, 0x3e00008, 0xad000010,
+0x3c020800, 0x94423ff2, 0x3c050800, 0x94a53fe8,
+0x35440aa4, 0x3c070800, 0x94e73fe4, 0x948b0000,
+0x45c821, 0x327c023, 0xb1c00, 0x2706fff2,
+0x665025, 0xad2a000c, 0xad200010, 0xad2c0014,
+0xa000630, 0x25290018, 0x354f0aa4, 0x95e50000,
+0x95640028, 0x51400, 0x43c00, 0x34598100,
+0xec5825, 0xad39000c, 0xad2b0010, 0xa000630,
+0x25290014, 0x3c0c0800, 0x958c3fee, 0xa000686,
+0x25820001, 0x5460ff4c, 0x240a0800, 0x35580aa4,
+0x97060000, 0x61c00, 0x6c5025, 0xad2a000c,
+0xa000630, 0x25290010, 0x3c030800, 0x94633ff2,
+0x3c070800, 0x94e73fe8, 0x3c0f0800, 0x95ef3fe4,
+0x94a40000, 0x95790028, 0x671021, 0x4f5823,
+0x41c00, 0x193400, 0x2578ffee, 0xd87825,
+0x346a8100, 0xad2a000c, 0xad2f0010, 0xad200014,
+0xad2c0018, 0xa000630, 0x2529001c, 0x3e00008,
+0x240207d0, 0x27bdffe0, 0xafb20018, 0xafb10014,
+0xafb00010, 0xafbf001c, 0xe00007c, 0x808821,
+0x8f880054, 0x8f87004c, 0x3c058008, 0x34b20080,
+0x1112821, 0x3c108000, 0x24020080, 0x240300c0,
+0xa72023, 0xae020818, 0x3c068008, 0xae03081c,
+0x18800004, 0xaf850054, 0xacc50004, 0x8cc90004,
+0xaf89004c, 0x12200009, 0x36040980, 0xe000702,
+0x0, 0x924c0027, 0x8e0b0074, 0x1825004,
+0x14b3021, 0xae46000c, 0x36040980, 0x8c8e001c,
+0x8f8f005c, 0x1cf6823, 0x19a00004, 0x8fbf001c,
+0x8c90001c, 0xaf90005c, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0xa00007e, 0x27bd0020,
+0x8f860050, 0x8f830054, 0x8f82004c, 0x3c058008,
+0x34a40080, 0xac860050, 0xac83003c, 0x3e00008,
+0xaca20004, 0x3c030800, 0x8c630054, 0x27bdfff8,
+0x308400ff, 0x24620001, 0x30a500ff, 0x3c010800,
+0xac220054, 0x30c600ff, 0x3c078000, 0x8ce80178,
+0x500fffe, 0x3c0c7fff, 0xa3a40003, 0x8faa0000,
+0x358bffff, 0x14b4824, 0x627c0, 0x1244025,
+0xafa80000, 0x34e20100, 0x9043000a, 0xa3a00002,
+0x3c1980ff, 0xa3a30001, 0x8faf0000, 0x30ae007f,
+0x3738ffff, 0x1f86024, 0xe6e00, 0x3c0a0020,
+0x34e50140, 0x18d5825, 0x35492000, 0x2406ff80,
+0x3c041000, 0x27bd0008, 0xacab000c, 0xaca90014,
+0xa4a00018, 0xa0a60012, 0x3e00008, 0xace40178,
+0x308800ff, 0x30a700ff, 0x3c038000, 0x8c620178,
+0x440fffe, 0x3c0c8000, 0x358a0a00, 0x8d4b0020,
+0x35840140, 0x35850980, 0xac8b0004, 0x8d490024,
+0x7302b, 0x61540, 0xac890008, 0xa0880010,
+0x90a3004c, 0xa083002d, 0x3e00008, 0xa4800018,
+0x27bdffe8, 0x308400ff, 0xafbf0010, 0xe000767,
+0x30a500ff, 0x8f830054, 0x8fbf0010, 0x3c068000,
+0x34c50140, 0x34470040, 0x2404ff90, 0x3c021000,
+0x27bd0018, 0xaca3000c, 0xa0a40012, 0xaca70014,
+0x3e00008, 0xacc20178, 0x27bdffe0, 0x3c088008,
+0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010,
+0x35100080, 0x8e060018, 0x3c078000, 0x309200ff,
+0xc72025, 0xae040018, 0xe00007c, 0x30b100ff,
+0x92030005, 0x34620008, 0xe00007e, 0xa2020005,
+0x2402021, 0xe00077b, 0x2202821, 0x2402021,
+0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0x24050005, 0x24060001, 0xa00073c, 0x27bd0020,
+0x3c058000, 0x34a30980, 0x90660008, 0x30c20008,
+0x1040000f, 0x3c0a0101, 0x3549080a, 0xac890000,
+0x8ca80074, 0xac880004, 0x3c070800, 0x90e73ff8,
+0x30e50010, 0x50a00008, 0xac800008, 0x3c0d8008,
+0x35ac0080, 0x8d8b0058, 0xac8b0008, 0x2484000c,
+0x3e00008, 0x801021, 0xa0007bf, 0x2484000c,
+0x27bdffe8, 0x3c098000, 0xafb00010, 0xafbf0014,
+0x35260980, 0x90c80009, 0x24020006, 0xa05821,
+0x310300ff, 0x35270900, 0x808021, 0x24050004,
+0x1062007b, 0x24080002, 0x94cf005c, 0x3c0e0204,
+0x31edffff, 0x1ae6025, 0xae0c0000, 0x90ca0008,
+0x31440020, 0x10800008, 0x0, 0x90c2004e,
+0x3c1f0103, 0x37f90300, 0x305800ff, 0x3193025,
+0x24050008, 0xae060004, 0x90f90011, 0x90e60012,
+0x90e40011, 0x333800ff, 0x187082, 0x30cf00ff,
+0x1cf5021, 0x14b6821, 0x308900ff, 0x31aaffff,
+0x39230028, 0xa6080, 0x1460002c, 0x20c4823,
+0x90e40012, 0x3c198000, 0x372f0100, 0x308c00ff,
+0x18b1821, 0x31080, 0x45f821, 0x1f8400,
+0x360706ff, 0xad270004, 0x373f0900, 0x93ec0011,
+0x93ee0012, 0x37260980, 0x5c082, 0x8de4000c,
+0x8cc50034, 0x31cd00ff, 0x1ab1021, 0x581821,
+0xa4f823, 0x88400, 0x33f00, 0xf03025,
+0x33f9ffff, 0x318f00fc, 0xd97025, 0x1582021,
+0x1e96821, 0x45080, 0xadae000c, 0xe00007c,
+0x12a8021, 0x3c088008, 0x240b0004, 0x35050080,
+0xe00007e, 0xa0ab0009, 0x2001021, 0x8fbf0014,
+0x8fb00010, 0x3e00008, 0x27bd0018, 0x90ec0011,
+0x90e30019, 0x3c180800, 0x97183fee, 0x318200ff,
+0x2f882, 0x307000ff, 0x1fce00, 0x103c00,
+0x3273025, 0xd87025, 0x3c0f4000, 0x1cf6825,
+0x3c198000, 0xad2d0000, 0x373f0900, 0x93ec0011,
+0x93ee0012, 0x372f0100, 0x37260980, 0x5c082,
+0x8de4000c, 0x8cc50034, 0x31cd00ff, 0x1ab1021,
+0x581821, 0xa4f823, 0x88400, 0x33f00,
+0xf03025, 0x33f9ffff, 0x318f00fc, 0xd97025,
+0x1582021, 0x1e96821, 0x45080, 0xadae000c,
+0xe00007c, 0x12a8021, 0x3c088008, 0x240b0004,
+0x35050080, 0xe00007e, 0xa0ab0009, 0x2001021,
0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x90ce0011, 0x90cd0019, 0x3c070800, 0x94e73be6,
-0x31c600ff, 0x62082, 0x31ac00ff, 0x45e00,
-0xc1c00, 0x1631025, 0x47c825, 0x3c1f4000,
-0x33fc025, 0x3c198000, 0xad380000, 0x37220900,
-0x904c0011, 0x90580012, 0x373f0980, 0x8fe40034,
-0x8f2f010c, 0x105882, 0x330500ff, 0xab7021,
-0x83400, 0x8f1823, 0xe6f00, 0x1a61025,
-0x319f00fc, 0x3067ffff, 0x3e9c021, 0x47c825,
-0x14b7821, 0xf2880, 0xaf19000c, 0xe00005c,
-0x1258021, 0x3c0a8008, 0x24090004, 0x35480080,
-0xe00005e, 0xa1090009, 0x2001021, 0x8fbf0014,
-0x8fb00010, 0x3e00008, 0x27bd0018, 0xa00076f,
-0x24080012, 0x27bdffd8, 0xafb40020, 0xafb3001c,
-0xafb20018, 0xafb10014, 0xafbf0024, 0xafb00010,
-0x3c068000, 0x90c3010b, 0x309200ff, 0x30b300ff,
-0x30620030, 0xa021, 0x10400070, 0x8821,
-0x34c40980, 0x90880008, 0x83e00, 0x72e03,
-0x4a00097, 0x24040004, 0x8f880058, 0x3c010800,
-0xa0243bf0, 0x3c0c8000, 0xad800048, 0x3c038000,
-0x906e010b, 0x31c50020, 0x10a00007, 0x3c028000,
-0x34790980, 0x93380008, 0x188600, 0x107e03,
-0x5e2009c, 0x3c028008, 0x34500900, 0x34470a80,
-0x904d010b, 0x94eb002c, 0x92030011, 0x921f0012,
-0x90e50018, 0x307800ff, 0x33f900ff, 0x197880,
-0x1f87021, 0x1d15021, 0x30b100ff, 0x1514821,
-0x2524000a, 0x31ac0040, 0x3091ffff, 0xc302b,
-0x2202021, 0xa78b005c, 0x3c010800, 0xa42a3be6,
-0x3c010800, 0xa4293be8, 0x3c010800, 0xa4293bea,
-0x3c010800, 0xa4203be0, 0x3c010800, 0xa4203bdc,
-0xe0001c9, 0x1068023, 0xe0005b2, 0x402021,
-0x402021, 0xe0005bf, 0x2002821, 0x1680005c,
-0x0, 0xe0001f2, 0x2202021, 0x3c080800,
-0x91083bf0, 0x31140003, 0x12800016, 0x3c1f8008,
-0x8f840058, 0x3c0c8008, 0x35860080, 0x248b0001,
-0xaccb003c, 0x3c058008, 0x8caa0004, 0x1602021,
-0x14b4823, 0x19200002, 0xaf8b0058, 0x8ca40004,
-0xe000695, 0xaca40004, 0x3c0f8000, 0x8dee0074,
-0x3c058008, 0x34ad0080, 0x4e8821, 0xadb1000c,
-0x3c1f8008, 0x37f90080, 0x2402021, 0x2602821,
-0xa320006b, 0xe00070d, 0x3c128000, 0x8f980058,
-0x34500006, 0xae58014c, 0xe000550, 0x3c131000,
-0xa2420152, 0x8fbf0024, 0xae500154, 0x8fb40020,
-0xae530178, 0x8fb10014, 0x8fb3001c, 0x8fb20018,
-0x8fb00010, 0x3e00008, 0x27bd0028, 0x34c30980,
-0x906f0008, 0xf7600, 0xe6e03, 0x5a00033,
-0x34c20900, 0x9059001b, 0x241f0010, 0x3c010800,
-0xa03f3bf0, 0x33380002, 0x1300ff90, 0x8f880058,
-0x8f830064, 0x1468ff8e, 0x3c038000, 0xe00005c,
-0x0, 0x3c098008, 0x35250080, 0x90a40009,
-0x24070016, 0x308800ff, 0x1107000d, 0x0,
-0x90a60009, 0x3c0c0800, 0x918c3bf0, 0x240a0008,
-0x30c400ff, 0x358b0001, 0x3c010800, 0xa02b3bf0,
-0x108a002f, 0x240d000a, 0x108d0028, 0x2402000c,
-0xe00005e, 0x0, 0xa0007fc, 0x8f880058,
-0xe000763, 0x402021, 0xa00082e, 0x0,
-0x3c0b8008, 0x356a0080, 0x8d480054, 0x8cc9010c,
-0x1120ff66, 0xaf880058, 0x24060014, 0x3c010800,
-0xa0263bf0, 0xa0007fb, 0x3c0c8000, 0x90710008,
-0x24140002, 0x3c010800, 0xa0343bf0, 0x32300020,
-0x1200000b, 0x24140001, 0x8f880058, 0xa0007fc,
-0x24110008, 0x345f0080, 0x8fe70038, 0xac470004,
-0x8c430004, 0xafe3003c, 0xa000807, 0x3c028000,
-0x8f880058, 0xa0007fc, 0x24110004, 0xa0a20009,
-0xe00005e, 0x0, 0xa0007fc, 0x8f880058,
-0x24020014, 0xa0008ad, 0xa0a20009, 0x27bdffe8,
-0xafbf0014, 0xafb00010, 0x3c108000, 0x92020109,
-0x24050001, 0xe00070d, 0x304400ff, 0x3c1f8008,
-0x93f8000e, 0x37e30080, 0x93f9000f, 0x906e0026,
-0x93e9000a, 0x332f00ff, 0x186600, 0xf6c00,
-0x31cb00ff, 0x18d5025, 0xb3200, 0x1463825,
-0x312800ff, 0x34456000, 0xe82025, 0x2402ff81,
-0x3c031000, 0xae04014c, 0x8fbf0014, 0xae050154,
-0xa2020152, 0xae030178, 0x8fb00010, 0x3e00008,
-0x27bd0018, 0x27bdffe8, 0x308400ff, 0xafbf0010,
-0xe00070d, 0x30a500ff, 0x34460040, 0x3c048000,
-0x2405ff92, 0xac860154, 0xa0850152, 0x8f830058,
-0x8fbf0010, 0x3c021000, 0x27bd0018, 0xac83014c,
-0x3e00008, 0xac820178, 0x27bdffd8, 0xafb20018,
-0xafb10014, 0xafb00010, 0xafbf0020, 0xafb3001c,
-0x3c078000, 0x90e20109, 0x308600ff, 0x30b000ff,
-0x618c2, 0x32040002, 0x30710001, 0x14800007,
-0x305200ff, 0x3c098008, 0x35330080, 0x92680005,
-0x31050008, 0x10a0000c, 0x30ca0010, 0x2402021,
-0xe000745, 0x2202821, 0x24020001, 0x8fbf0020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x15400030, 0x34e50a00,
-0x8cb90024, 0x8cb80008, 0x13380047, 0x4021,
-0x3c0e8008, 0x35d30080, 0x926d0068, 0x240b0002,
-0x31ac00ff, 0x118b0080, 0x3c068000, 0x927f004c,
-0x90c40109, 0x509f0004, 0x3213007c, 0x11000067,
-0x0, 0x3213007c, 0x1660005a, 0x2402021,
-0x16200008, 0x320c0001, 0x3c078000, 0x34eb0a00,
-0x8d650024, 0x8ce80104, 0x14a8ffdc, 0x1021,
-0x320c0001, 0x1180000d, 0x2402021, 0x3c108000,
-0x8e0e010c, 0x8f8d0068, 0x11cd0008, 0x0,
-0xe0007e2, 0x2202821, 0x8e0f010c, 0x3c188008,
-0x37100080, 0xae0f0050, 0x2402021, 0xe000734,
-0x2202821, 0xa000900, 0x24020001, 0x3c070800,
-0x8ce70064, 0x24e60001, 0x3c010800, 0xac260064,
-0x1600000d, 0x0, 0x2202821, 0xe000734,
-0x2402021, 0x926f0068, 0x240d0002, 0x31ee00ff,
-0x11cd0022, 0x2402021, 0xe0008b4, 0x0,
-0xa000900, 0x24020001, 0xe00003d, 0x24040001,
-0x926c0025, 0x20c5825, 0xe00005e, 0xa26b0025,
-0xa000940, 0x2202821, 0x8e630018, 0x8ce40104,
-0x8cbf0024, 0x31602, 0x149fffb5, 0x3045007f,
-0x9269004c, 0x26440001, 0x3093007f, 0x12650040,
-0x312300ff, 0x1464ffaf, 0x3c0e8008, 0x26480001,
-0x3111007f, 0x310200ff, 0x1225000b, 0x24080001,
-0x409021, 0xa00090d, 0x24110001, 0x24050004,
-0xe0006cf, 0x24060001, 0xe0008b4, 0x0,
-0xa000900, 0x24020001, 0x2407ff80, 0x2472824,
-0xa79026, 0x324200ff, 0x409021, 0xa00090d,
-0x24110001, 0xe0007e2, 0x2202821, 0x32060030,
-0x10c0ffa3, 0x32100082, 0x2402021, 0xe000745,
-0x2202821, 0xa000900, 0x24020001, 0x8e630018,
-0x2402021, 0x2202821, 0x661025, 0xe0008d6,
-0xae620018, 0x9264004c, 0x24050003, 0x24060001,
-0xe0006cf, 0x308400ff, 0xe00003d, 0x24040001,
-0x926a0025, 0x20a4825, 0xe00005e, 0xa2690025,
-0xa000900, 0x24020001, 0x8e780018, 0x3c198000,
-0x2402021, 0x3197825, 0x2202821, 0xe000734,
-0xae6f0018, 0x9264004c, 0xa000988, 0x24050004,
-0x32460080, 0x38ca0080, 0x146aff6e, 0x3c0e8008,
-0xa000961, 0x26480001, 0x27bdffc0, 0xafb00018,
-0x3c108000, 0xafbf0038, 0xafb70034, 0xafb60030,
-0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020,
-0xe00055e, 0xafb1001c, 0x92040108, 0x9205010b,
-0x308400ff, 0xe0008e7, 0x30a500ff, 0x144000d6,
-0x8fbf0038, 0x3c098008, 0x35280080, 0xa100006b,
-0x36070980, 0x90e60000, 0x24020050, 0x3c170800,
-0x26f73df4, 0x30c300ff, 0x3c140800, 0x26943e04,
-0x10620003, 0x3c108000, 0xb821, 0xa021,
-0x241f0010, 0x36110a00, 0x36130980, 0x8e160104,
-0x8f8d0058, 0x8e380024, 0x36190a80, 0x8e720020,
-0x3c010800, 0xa03f3bf0, 0x972c002c, 0x8ef50000,
-0x932b0018, 0x24d7023, 0x2d87823, 0x3c010800,
-0xac2f3bcc, 0x3c010800, 0xac2e3bd0, 0x3c010800,
-0xac2d3bf4, 0xa78c005c, 0x2a0f809, 0x317200ff,
-0x304a0002, 0x154000da, 0x30450001, 0x10a000b4,
-0x0, 0x36050900, 0x8e2b0024, 0x90bf0011,
-0x90b90012, 0x90b60011, 0x33ef00ff, 0x333800ff,
-0x32cd00ff, 0x187080, 0x1cf8021, 0x24d6021,
-0x212a821, 0x258a0010, 0x3c010800, 0xa4353be8,
-0x3c010800, 0xac2b3bf8, 0x3c010800, 0xa42a3be4,
-0x3c010800, 0xa4303be6, 0x260b021, 0x3c158000,
-0x8f920058, 0x8f840060, 0x8ed30020, 0x24110006,
-0x923023, 0x2722823, 0x3c010800, 0xac313bec,
-0x4c000af, 0x9821, 0x4a000ad, 0xc5102b,
-0x104000af, 0x0, 0x3c010800, 0xac263bd0,
-0x8e900000, 0x200f809, 0x0, 0x30430002,
-0x1460006f, 0x408821, 0x30460001, 0x54c00011,
-0x8e920004, 0x3c080800, 0x8d083bd4, 0x3c09c000,
-0x3c048000, 0x1093825, 0xaea70e00, 0x8c8b0000,
-0x316a0008, 0x1140fffd, 0x0, 0x948d0e08,
-0x24130001, 0xa78d0040, 0x8c8c0e04, 0xaf8c0028,
-0x8e920004, 0x240f809, 0x0, 0x2228825,
-0x322e0002, 0x15c000a5, 0x0, 0x3c180800,
-0x97183bdc, 0x3c120800, 0x96523be8, 0x3c190800,
-0x97393bde, 0x3c070800, 0x8ce73bd4, 0x3124021,
-0x3c0b0800, 0x8d6b3bf8, 0x3c0e0800, 0x95ce3bf2,
-0x3c128000, 0x1197821, 0x8e46010c, 0xf86821,
-0x25ec0002, 0x1ae4821, 0x1675021, 0xaf860068,
-0x3c010800, 0xac2a3bf8, 0x3c010800, 0xa4293be0,
-0x3c010800, 0xa4283bea, 0xe0001c9, 0x3184ffff,
-0xe000550, 0x408021, 0x3c010800, 0xa0223bf1,
-0x8e820008, 0x40f809, 0x2002021, 0x8f850058,
-0xe0005bf, 0x402021, 0x8e90000c, 0x200f809,
-0x402021, 0x3c030800, 0x94633bea, 0x3c020800,
-0x94423bde, 0x622021, 0x24850002, 0xe0001f2,
-0x30a4ffff, 0x3c190800, 0x8f393bcc, 0x3c1f0800,
-0x8fff3bd4, 0x33fc023, 0x3c010800, 0xac383bcc,
-0x17000006, 0x0, 0x3c050800, 0x8ca53bec,
-0x34bf0040, 0x3c010800, 0xac3f3bec, 0x12600042,
-0x8f820044, 0x8e430e10, 0x8f930044, 0xae630020,
-0x8e440e18, 0xae640024, 0x3c040800, 0x94843be0,
-0xe000697, 0x0, 0x8f860058, 0x8e8a0010,
-0x3c010800, 0xac263bf4, 0x140f809, 0x0,
-0x3c090800, 0x8d293bcc, 0x1520ff7e, 0x8f920058,
-0x9796005c, 0x3c14800e, 0x32350010, 0xe0006c6,
-0xa696002c, 0x56a00045, 0x8eeb0004, 0x32270040,
-0x54e0001e, 0x8ef10008, 0x8eec000c, 0x180f809,
-0x0, 0x8fbf0038, 0x8fb70034, 0x8fb60030,
-0x8fb5002c, 0x8fb40028, 0x8fb30024, 0x8fb20020,
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0040,
-0x92090109, 0x8f880030, 0x93e00, 0xe83025,
-0xae060080, 0x8e230020, 0x8e240024, 0xafa30010,
-0xae030e14, 0x8fa20010, 0xae020e10, 0xae040e1c,
-0xae040e18, 0xa0009e3, 0x36050900, 0x220f809,
-0x0, 0x8eec000c, 0x180f809, 0x0,
-0xa000a8b, 0x8fbf0038, 0x24080001, 0x24100001,
-0xa4400020, 0xa4480022, 0xa000a6f, 0xac500024,
-0x3c010800, 0xac203bd0, 0xa000a0a, 0x8e900000,
-0x3c010800, 0xac253bd0, 0xa000a0a, 0x8e900000,
-0x92110109, 0x2821, 0xe000734, 0x322400ff,
+0xa0007d1, 0x24080012, 0x27bdffd0, 0x3c038000,
+0xafb60028, 0xafb50024, 0xafb40020, 0xafb10014,
+0xafbf002c, 0xafb3001c, 0xafb20018, 0xafb00010,
+0x34670100, 0x90e6000b, 0x309400ff, 0x30b500ff,
+0x30c20030, 0xb021, 0x10400099, 0x8821,
+0x34640980, 0x90880008, 0x82e00, 0x51e03,
+0x46000c0, 0x24040004, 0x8f860054, 0x3c010800,
+0xa0243ff8, 0x3c0c8000, 0xad800048, 0x3c048000,
+0x348e0100, 0x91cd000b, 0x31a50020, 0x10a00007,
+0x3c078000, 0x34930980, 0x92720008, 0x128600,
+0x107e03, 0x5e000c4, 0x3c1f8008, 0x34ec0100,
+0x918a000b, 0x34eb0980, 0x91690008, 0x31440040,
+0x4402b, 0x31230008, 0xc89823, 0x14600002,
+0x24120003, 0x9021, 0x3c108000, 0x36180a80,
+0x36040900, 0x970e002c, 0x90830011, 0x90890012,
+0x93050018, 0x307f00ff, 0x312800ff, 0x2481021,
+0x2c880, 0x930d0018, 0x33f7821, 0x1f13021,
+0x30b100ff, 0xd11821, 0xa78e0058, 0x3c010800,
+0xa4263fee, 0x3c010800, 0xa4233ff0, 0x15a00002,
+0x0, 0xd, 0x920b010b, 0x3065ffff,
+0x3c010800, 0xa4233ff2, 0x316a0040, 0x3c010800,
+0xa4203fe8, 0x3c010800, 0xa4203fe4, 0x11400002,
+0x24a4000a, 0x24a4000b, 0x3091ffff, 0xe0001e7,
+0x2202021, 0x9206010b, 0x3c0c0800, 0x958c3ff2,
+0x402021, 0x66982, 0x31a70001, 0xe000601,
+0x1872821, 0x402021, 0x2602821, 0xe00060c,
+0x2403021, 0xe0007ab, 0x402021, 0x16c00069,
+0x402021, 0x9212010b, 0x32560040, 0x12c00005,
+0x3c0500ff, 0x8c930000, 0x34aeffff, 0x26e8024,
+0xac900000, 0xe0001fb, 0x2202021, 0x3c0f0800,
+0x91ef3ff8, 0x31f10003, 0x12200016, 0x3c138008,
+0x8f820054, 0x3c098008, 0x35280080, 0x245f0001,
+0xad1f003c, 0x3c058008, 0x8cb90004, 0x3e02021,
+0x33fc023, 0x1b000002, 0xaf9f0054, 0x8ca40004,
+0xe000702, 0xaca40004, 0x3c078000, 0x8ceb0074,
+0x3c048008, 0x34830080, 0x4b5021, 0xac6a000c,
+0x3c138008, 0x36700080, 0x2802021, 0x2a02821,
+0xa200006b, 0xe000767, 0x3c148000, 0x8f920054,
+0x368c0140, 0xad92000c, 0x8f860048, 0x3c151000,
+0x344d0006, 0x24d60001, 0xaf960048, 0x8fbf002c,
+0xa1860012, 0x8fb60028, 0xad8d0014, 0x8fb3001c,
+0xae950178, 0x8fb20018, 0x8fb50024, 0x8fb40020,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030,
+0x34640980, 0x908f0008, 0xf7600, 0xe6e03,
+0x5a00033, 0x347f0900, 0x93f8001b, 0x24190010,
+0x3c010800, 0xa0393ff8, 0x33130002, 0x1260ff67,
+0x8f860054, 0x8f820060, 0x1446ff65, 0x3c048000,
+0xe00007c, 0x0, 0x3c048008, 0x34850080,
+0x90a80009, 0x24060016, 0x310300ff, 0x1066000d,
+0x0, 0x90ab0009, 0x3c070800, 0x90e73ff8,
+0x24090008, 0x316400ff, 0x34ea0001, 0x3c010800,
+0xa02a3ff8, 0x1089002f, 0x240c000a, 0x108c0028,
+0x2402000c, 0xe00007e, 0x0, 0xa00086a,
+0x8f860054, 0xe0007c3, 0x2402821, 0xa0008b8,
+0x402021, 0x3c0b8008, 0x356a0080, 0x8d460054,
+0x8ce9000c, 0x1120ff3d, 0xaf860054, 0x24070014,
+0x3c010800, 0xa0273ff8, 0xa000869, 0x3c0c8000,
+0x90910008, 0x24120002, 0x3c010800, 0xa0323ff8,
+0x32300020, 0x1200000b, 0x24160001, 0x8f860054,
+0xa00086a, 0x24110008, 0x37f80080, 0x8f020038,
+0xafe20004, 0x8ff90004, 0xaf19003c, 0xa000876,
+0x3c078000, 0x8f860054, 0xa00086a, 0x24110004,
+0xa0a20009, 0xe00007e, 0x0, 0xa00086a,
+0x8f860054, 0x24020014, 0xa000944, 0xa0a20009,
+0x27bdffe8, 0xafb00010, 0x3c108000, 0xafbf0014,
+0x36020100, 0x90440009, 0xe000767, 0x24050001,
+0x3c048008, 0x9099000e, 0x34830080, 0x909f000f,
+0x906f0026, 0x9089000a, 0x33f800ff, 0x196e00,
+0x187400, 0x31ec00ff, 0x1ae5025, 0xc5a00,
+0x14b3825, 0x312800ff, 0x36030140, 0x34456000,
+0xe83025, 0x2402ff81, 0x3c041000, 0xac66000c,
+0x8fbf0014, 0xac650014, 0xa0620012, 0xae040178,
+0x8fb00010, 0x3e00008, 0x27bd0018, 0x27bdffe8,
+0x308400ff, 0xafbf0010, 0xe000767, 0x30a500ff,
+0x3c058000, 0x34a40140, 0x34470040, 0x2406ff92,
+0xac870014, 0xa0860012, 0x8f830054, 0x8fbf0010,
+0x3c021000, 0x27bd0018, 0xac83000c, 0x3e00008,
+0xaca20178, 0x27bdffd8, 0xafb00010, 0x308400ff,
+0x30b000ff, 0x3c058000, 0xafb10014, 0xafbf0020,
+0xafb3001c, 0xafb20018, 0x410c2, 0x34a60100,
+0x32030002, 0x30510001, 0x14600007, 0x90d20009,
+0x3c098008, 0x35330080, 0x92680005, 0x31070008,
+0x10e0000c, 0x308a0010, 0x2402021, 0xe00078d,
+0x2202821, 0x24020001, 0x8fbf0020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0028, 0x15400034, 0x34a50a00, 0x8cb80024,
+0x8caf0008, 0x130f004b, 0x3821, 0x3c0d8008,
+0x35b30080, 0x926c0068, 0x24060002, 0x318b00ff,
+0x11660084, 0x3c068000, 0x34c20100, 0x9263004c,
+0x90590009, 0x307f00ff, 0x53f90004, 0x3213007c,
+0x10e00069, 0x0, 0x3213007c, 0x5660005c,
+0x2402021, 0x16200009, 0x320d0001, 0x3c0c8000,
+0x35840100, 0x358b0a00, 0x8d650024, 0x8c860004,
+0x14a6ffd9, 0x1021, 0x320d0001, 0x11a0000e,
+0x2402021, 0x3c188000, 0x37100100, 0x8e0f000c,
+0x8f8e0050, 0x11ee0008, 0x0, 0xe00084d,
+0x2202821, 0x8e19000c, 0x3c1f8008, 0x37f00080,
+0xae190050, 0x2402021, 0xe00077b, 0x2202821,
+0xa000999, 0x24020001, 0x3c050800, 0x8ca50064,
+0x24a40001, 0x3c010800, 0xac240064, 0x1600000d,
+0x0, 0x2202821, 0xe00077b, 0x2402021,
+0x926e0068, 0x240c0002, 0x31cd00ff, 0x11ac0022,
+0x2402021, 0xe00094b, 0x0, 0xa000999,
+0x24020001, 0xe000070, 0x24040001, 0x926b0025,
+0x20b3025, 0xe00007e, 0xa2660025, 0xa0009dd,
+0x2202821, 0x8e620018, 0x8cdf0004, 0x8cb90024,
+0x21e02, 0x17f9ffb1, 0x3065007f, 0x9268004c,
+0x26440001, 0x3093007f, 0x12650040, 0x310300ff,
+0x1464ffab, 0x3c0d8008, 0x26470001, 0x30f1007f,
+0x30e200ff, 0x1225000b, 0x24070001, 0x409021,
+0xa0009a6, 0x24110001, 0x24050004, 0xe00073c,
+0x24060001, 0xe00094b, 0x0, 0xa000999,
+0x24020001, 0x2405ff80, 0x2452024, 0x859026,
+0x324200ff, 0x409021, 0xa0009a6, 0x24110001,
+0xe00084d, 0x2202821, 0x32070030, 0x10e0ffa1,
+0x32100082, 0x2402021, 0xe00078d, 0x2202821,
+0xa000999, 0x24020001, 0x8e690018, 0x2402021,
+0x2202821, 0x1264025, 0xe00096e, 0xae680018,
+0x9264004c, 0x24050003, 0x24060001, 0xe00073c,
+0x308400ff, 0xe000070, 0x24040001, 0x92710025,
+0x2115025, 0xe00007e, 0xa26a0025, 0xa000999,
+0x24020001, 0x8e6f0018, 0x3c188000, 0x2402021,
+0x1f87025, 0x2202821, 0xe00077b, 0xae6e0018,
+0x9264004c, 0xa000a25, 0x24050004, 0x324a0080,
+0x39490080, 0x1469ff6a, 0x3c0d8008, 0xa0009fe,
+0x26470001, 0x27bdffc0, 0xafb00018, 0x3c108000,
+0xafbf0038, 0xafb70034, 0xafb60030, 0xafb5002c,
+0xafb40028, 0xafb30024, 0xafb20020, 0xe0005be,
+0xafb1001c, 0x36020100, 0x9045000b, 0xe000980,
+0x90440008, 0x144000e7, 0x8fbf0038, 0x3c088008,
+0x35070080, 0xa0e0006b, 0x36060980, 0x90c50000,
+0x24030050, 0x3c170800, 0x26f73fb0, 0x30a400ff,
+0x3c130800, 0x26733fc0, 0x10830003, 0x3c108000,
+0xb821, 0x9821, 0x241f0010, 0x36110100,
+0x36120a00, 0x36150980, 0x8e580024, 0x8e340004,
+0x8eaf0020, 0x8f8c0054, 0x3c010800, 0xa03f3ff8,
+0x36190a80, 0x972b002c, 0x8ef60000, 0x932a0018,
+0x2987023, 0x1ec6823, 0x3c010800, 0xac2e3fd4,
+0x3c010800, 0xac2d3fd8, 0x3c010800, 0xac2c3ffc,
+0xa78b0058, 0x2c0f809, 0x315400ff, 0x30490002,
+0x152000e9, 0x30420001, 0x504000c4, 0x92270009,
+0x92a90008, 0x31280008, 0x15000002, 0x24150003,
+0xa821, 0x3c0a8000, 0x35430900, 0x35440a00,
+0x8c8d0024, 0x90720011, 0x90700012, 0x907f0011,
+0x325900ff, 0x321100ff, 0x2b11021, 0x2c080,
+0x33ef00ff, 0x319b021, 0x28f7021, 0x2d46021,
+0x25cb0010, 0x3c010800, 0xa4363fee, 0x3c010800,
+0xac2d4000, 0x3c010800, 0xa42c3ff0, 0x3c010800,
+0xa42b3fec, 0x35560100, 0x35540980, 0x35510e00,
+0x8f870054, 0x8f89005c, 0x8e850020, 0x24080006,
+0x1273023, 0x3c010800, 0xac283ff4, 0xa72823,
+0x4c000b5, 0x9021, 0x4a000b3, 0xc5502b,
+0x114000b5, 0x0, 0x3c010800, 0xac263fd8,
+0x8e620000, 0x40f809, 0x0, 0x30460002,
+0x14c00074, 0x408021, 0x304b0001, 0x55600011,
+0x8e620004, 0x3c0d0800, 0x8dad3fdc, 0x3c0ec000,
+0x3c048000, 0x1ae6025, 0xae2c0000, 0x8c980000,
+0x330f0008, 0x11e0fffd, 0x0, 0x963f0008,
+0x24120001, 0xa79f0040, 0x8e390004, 0xaf990038,
+0x8e620004, 0x40f809, 0x0, 0x2028025,
+0x32030002, 0x146000b3, 0x0, 0x3c090800,
+0x95293fe4, 0x3c060800, 0x94c63ff0, 0x3c0a0800,
+0x954a3fe6, 0x3c070800, 0x8ce73fdc, 0x1267021,
+0x3c030800, 0x8c634000, 0x3c080800, 0x95083ffa,
+0x1ca2021, 0x8ed9000c, 0xe92821, 0x249f0002,
+0xa87821, 0x67c021, 0x33e4ffff, 0xaf990050,
+0x3c010800, 0xac384000, 0x3c010800, 0xa42f3fe8,
+0x3c010800, 0xa42e3ff2, 0xe0001e7, 0x0,
+0x8f8d0048, 0x402021, 0x3c010800, 0xa02d3ff9,
+0x8e620008, 0x25ac0001, 0xaf8c0048, 0x40f809,
+0x0, 0x8f850054, 0x2a03021, 0xe00060c,
+0x402021, 0xe0007ab, 0x402021, 0x8e6b000c,
+0x160f809, 0x402021, 0x3c0a0800, 0x954a3ff2,
+0x3c060800, 0x94c63fe6, 0x1464821, 0x25280002,
+0xe0001fb, 0x3104ffff, 0x3c050800, 0x8ca53fd4,
+0x3c070800, 0x8ce73fdc, 0xa72023, 0x3c010800,
+0xac243fd4, 0x14800006, 0x0, 0x3c020800,
+0x8c423ff4, 0x344b0040, 0x3c010800, 0xac2b3ff4,
+0x12400043, 0x8f8e0044, 0x8e2d0010, 0x8f920044,
+0xae4d0020, 0x8e2c0018, 0xae4c0024, 0x3c040800,
+0x94843fe8, 0xe000704, 0x0, 0x8f9f0054,
+0x8e670010, 0x3c010800, 0xac3f3ffc, 0xe0f809,
+0x0, 0x3c190800, 0x8f393fd4, 0x1720ff79,
+0x8f870054, 0x97930058, 0x3c11800e, 0x32160100,
+0xe000733, 0xa633002c, 0x16c00045, 0x32030010,
+0x5460004c, 0x8ee50004, 0x32080040, 0x5500001d,
+0x8ef00008, 0x8ee4000c, 0x80f809, 0x0,
0x8fbf0038, 0x8fb70034, 0x8fb60030, 0x8fb5002c,
0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0040, 0x160f809,
-0x0, 0xa000a85, 0x32270040, 0x5260ffb1,
-0x9796005c, 0x8eb60e14, 0x8f940044, 0xae960020,
-0x8eaf0e1c, 0xae8f0024, 0xa000a7e, 0x9796005c,
-0x8f820000, 0x42180, 0x3e00008, 0x821021,
-0x3c078008, 0x34e20080, 0x90430069, 0x804021,
-0x10600009, 0x3c040100, 0x3c070800, 0x8ce73bf4,
-0x8f83001c, 0xe32023, 0x4800008, 0x93890008,
-0x14e30003, 0x1002021, 0x3e00008, 0x801021,
-0x3c040100, 0x3e00008, 0x801021, 0x1120000b,
-0x673823, 0x3c0d8000, 0x35ac0980, 0x918b007c,
-0x316a0002, 0x11400020, 0x24090034, 0xe9702b,
-0x15c0fff1, 0x1002021, 0xe93823, 0x2403fffc,
-0xa3c824, 0xe3c024, 0xf9782b, 0x15e0ffea,
-0x3082021, 0x30c40003, 0x41023, 0x14c00014,
-0x30490003, 0x3021, 0xa97821, 0x1e67021,
-0xee682b, 0x11a0ffe0, 0x3c040100, 0x2d380001,
-0x6c82b, 0x1054821, 0x3193824, 0x14e0ffda,
-0x2524fffc, 0x2402fffc, 0xa21824, 0x682021,
-0x3e00008, 0x801021, 0xa000af4, 0x24090030,
-0x3c0c8000, 0x35860980, 0x90cb007c, 0x316a0004,
-0x1540ffe9, 0x24060004, 0xa000b03, 0x3021,
-0x3c030800, 0x8c63005c, 0x8f820004, 0x27bdffe8,
-0xafbf0014, 0x10620005, 0xafb00010, 0x329c0,
-0x24a40280, 0xaf840000, 0xaf830004, 0x3c108000,
-0x36030a00, 0x94650032, 0xe000ad5, 0x30a43fff,
-0x8e040100, 0x3c180080, 0x370f0003, 0x82c821,
-0x2402ff80, 0x3226024, 0x3329007f, 0xcf940,
-0x3e94025, 0x332e0078, 0x3c0d1000, 0x10d5025,
+0x8fb00018, 0x3e00008, 0x27bd0040, 0x8f86003c,
+0x36110e00, 0x72e00, 0xa62025, 0xae040080,
+0x8e430020, 0x8e500024, 0xafa30010, 0xae230014,
+0x8fb20010, 0xae320010, 0xae30001c, 0xa000a7f,
+0xae300018, 0x200f809, 0x0, 0x8ee4000c,
+0x80f809, 0x0, 0xa000b38, 0x8fbf0038,
+0x24180001, 0x240f0001, 0xa5c00020, 0xa5d80022,
+0xa000b1a, 0xadcf0024, 0x3c010800, 0xac203fd8,
+0xa000ab0, 0x8e620000, 0x3c010800, 0xac253fd8,
+0xa000ab0, 0x8e620000, 0x92240009, 0xe00077b,
+0x2821, 0x8fbf0038, 0x8fb70034, 0x8fb60030,
+0x8fb5002c, 0x8fb40028, 0x8fb30024, 0x8fb20020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0040,
+0x3c148000, 0x92950109, 0x2821, 0xe00084d,
+0x32a400ff, 0x32030010, 0x5060ffb8, 0x32080040,
+0x8ee50004, 0xa0f809, 0x0, 0xa000b32,
+0x32080040, 0x5240ffa8, 0x97930058, 0x8e340014,
+0x8f930044, 0xae740020, 0x8e35001c, 0xae750024,
+0xa000b29, 0x97930058, 0x8f820014, 0x42180,
+0x3e00008, 0x821021, 0x3c078008, 0x34e20080,
+0x90430069, 0x804021, 0x10600009, 0x3c040100,
+0x3c070800, 0x8ce73ffc, 0x8f830030, 0xe32023,
+0x4800008, 0x9389001c, 0x14e30003, 0x1002021,
+0x3e00008, 0x801021, 0x3c040100, 0x3e00008,
+0x801021, 0x1120000b, 0x673823, 0x3c0d8000,
+0x35ac0980, 0x918b007c, 0x316a0002, 0x11400020,
+0x24090034, 0xe9702b, 0x15c0fff1, 0x1002021,
+0xe93823, 0x2403fffc, 0xa3c824, 0xe3c024,
+0xf9782b, 0x15e0ffea, 0x3082021, 0x30c40003,
+0x41023, 0x14c00014, 0x30490003, 0x3021,
+0xa97821, 0x1e67021, 0xee682b, 0x11a0ffe0,
+0x3c040100, 0x2d380001, 0x6c82b, 0x1054821,
+0x3193824, 0x14e0ffda, 0x2524fffc, 0x2402fffc,
+0xa21824, 0x682021, 0x3e00008, 0x801021,
+0xa000ba8, 0x24090030, 0x3c0c8000, 0x35860980,
+0x90cb007c, 0x316a0004, 0x1540ffe9, 0x24060004,
+0xa000bb7, 0x3021, 0x3c030800, 0x8c63005c,
+0x8f820018, 0x27bdffe0, 0xafbf0018, 0xafb10014,
+0x10620005, 0xafb00010, 0x329c0, 0x24a40280,
+0xaf840014, 0xaf830018, 0x3c108000, 0x36020a00,
+0x94450032, 0x36110100, 0xe000b89, 0x30a43fff,
+0x8e240000, 0x241fff80, 0x3c110080, 0x82c021,
+0x31f6024, 0x3309007f, 0xcc940, 0x3294025,
+0x330e0078, 0x362f0003, 0x3c0d1000, 0x10d5025,
0x1cf5825, 0xae0c0028, 0x36080980, 0xae0c080c,
0xae0b082c, 0xae0a0830, 0x91030069, 0x3c06800c,
-0x1263821, 0x10600006, 0xaf870020, 0x8d09003c,
-0x8d06006c, 0x1263823, 0x18e0007f, 0x0,
-0x3c0c8008, 0x358b0080, 0x3c0a8000, 0xa1600069,
-0x35500980, 0x8e020038, 0x3c068000, 0x34c50a00,
-0x90ad003c, 0x31a80020, 0x11000019, 0xaf82001c,
-0x240e0001, 0x3c198000, 0x37300a00, 0xa38e0008,
-0xaf800010, 0x8e040024, 0x8f850010, 0x24180008,
-0xaf80000c, 0xaf800014, 0x3c010800, 0xa4383bde,
-0x3c010800, 0xa4203bf2, 0xe000ad9, 0x3021,
-0x920f003c, 0x8fbf0014, 0x8fb00010, 0xf7142,
-0xaf820018, 0x27bd0018, 0x3e00008, 0x31c20001,
-0x90b90032, 0x240f0001, 0x333800ff, 0x182182,
-0x108f003f, 0x241f0002, 0x109f0062, 0x34c20ac0,
-0x3c038000, 0x34640a00, 0x8c990024, 0x1720001d,
-0x34660900, 0x90830030, 0x241f0005, 0x3062003f,
-0x105f004c, 0x24050001, 0x8f86000c, 0xa3850008,
-0xaf860014, 0xaf860010, 0x3c198000, 0x37300a00,
-0x8e040024, 0x8f850010, 0x24180008, 0x3c010800,
-0xa4383bde, 0x3c010800, 0xa4203bf2, 0xe000ad9,
-0x0, 0x920f003c, 0x8fbf0014, 0x8fb00010,
-0xf7142, 0xaf820018, 0x27bd0018, 0x3e00008,
-0x31c20001, 0x8c880008, 0x8c8d0024, 0x8ccb0064,
-0x3c198000, 0x37300a00, 0xaf8b0010, 0xa3800008,
-0x8e040024, 0x8f86000c, 0x8f850010, 0x10d6023,
-0x24180008, 0xaf8c0014, 0x3c010800, 0xa4383bde,
-0x3c010800, 0xa4203bf2, 0xe000ad9, 0x0,
-0x920f003c, 0x8fbf0014, 0x8fb00010, 0xf7142,
-0xaf820018, 0x27bd0018, 0x3e00008, 0x31c20001,
-0x90a70030, 0x30e3003f, 0x50640028, 0x34c50ac0,
-0x8caa0024, 0x15400022, 0x34c80900, 0x8cab0048,
-0x3c0c7fff, 0x3585ffff, 0x1651024, 0x3c188000,
-0xaf82000c, 0x37050900, 0x8f8e000c, 0x8caf0060,
-0x1cf682b, 0x15a00002, 0x1c02021, 0x8ca40060,
-0xa000b75, 0xaf84000c, 0x8d02006c, 0xa000b50,
-0x3c068000, 0x8c890048, 0x8f86000c, 0x3c0a7fff,
-0x3550ffff, 0x1303824, 0x3c048008, 0x24050001,
-0xaf870014, 0xac80006c, 0xa3850008, 0xa000b83,
-0xaf860010, 0x8c440014, 0xa000b75, 0xaf84000c,
-0x8d020068, 0xa000bbd, 0x3c188000, 0x34c40980,
-0x8c860070, 0x8cb00014, 0xd0482b, 0x11200004,
-0x0, 0x8c820070, 0xa000bbd, 0x3c188000,
-0x8ca20014, 0xa000bbd, 0x3c188000, 0x8f850010,
-0x27bdffe0, 0xafbf0018, 0xafb10014, 0x14a00008,
-0xafb00010, 0x3c048000, 0x34870a00, 0x90e60030,
-0x24020005, 0x30c3003f, 0x106200b7, 0x34840900,
-0x8f91000c, 0xa08021, 0x3c048000, 0x348e0a00,
-0x8dcd0004, 0x3c060800, 0x8cc63bd0, 0x31a73fff,
-0xe6602b, 0x55800001, 0xe03021, 0x938f0008,
-0x11e00076, 0xd0102b, 0x34990980, 0x9338007c,
-0x33040002, 0x10800077, 0x24030034, 0xc3f82b,
-0x17e000d6, 0xc33023, 0xd0102b, 0x3c010800,
-0xa4233bdc, 0x1440006d, 0x2001821, 0x3c040800,
-0x8c843bcc, 0x64282b, 0x54a00001, 0x602021,
-0x3c058000, 0x34a90a00, 0x9128003c, 0x3c010800,
-0xac243bd4, 0x31030020, 0x14600002, 0x4821,
-0x8ca90e18, 0x8f880018, 0x128502b, 0x1140005f,
-0x0, 0x3c050800, 0x8ca53bd4, 0xa96021,
-0x10c582b, 0x1160005c, 0xb0682b, 0x1093823,
-0xe02821, 0x3c010800, 0xac273bd4, 0x12000003,
-0x2402fffc, 0x10b0008c, 0x322a0003, 0xa2f824,
-0x3c010800, 0xa4203bf2, 0x3c010800, 0xac3f3bd4,
-0x3e02821, 0x8f840010, 0x12040006, 0x3c038008,
-0x8c6a006c, 0x2002021, 0xaf91000c, 0x25500001,
-0xac70006c, 0x8f8b0014, 0x858823, 0xaf910010,
-0x1652023, 0xaf840014, 0x12200002, 0x24070018,
-0x24070010, 0x3c0e8008, 0x35c60080, 0x90cd0068,
-0x240c0001, 0x3c010800, 0xa0273bf0, 0x31a700ff,
-0x10ec0047, 0x0, 0x14800018, 0x2821,
-0x3c0b8000, 0x91650109, 0x35710980, 0x8e230018,
-0x30a500ff, 0x35602, 0x24a30001, 0x3146007f,
-0x3070007f, 0x1206007e, 0x240cff80, 0x3c0f8008,
-0x35e90080, 0xa123004c, 0x3c080800, 0x8d083bec,
-0x240e0002, 0x3c010800, 0xa02e3c31, 0x350d0008,
-0x3c010800, 0xac2d3bec, 0x24050010, 0x3c1f8000,
-0x37e40a00, 0x9099003c, 0x33380020, 0x13000005,
-0xa02021, 0x24020001, 0x3c010800, 0xac223bd4,
-0x34a40001, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0x801021, 0x3e00008, 0x27bd0020, 0x3c010800,
-0xa4203bdc, 0x1040ff95, 0x2001821, 0xa000c10,
-0xc01821, 0xa000c08, 0x24030030, 0x3c050800,
-0x8ca53bd4, 0xb0682b, 0x11a0ffa8, 0x0,
-0x3c040800, 0x94843bdc, 0x857821, 0x1e7702b,
-0x11c00007, 0x2ca20004, 0x3c1f6000, 0x8ff95404,
-0x3338003f, 0x1700ffe3, 0x24040042, 0x2ca20004,
-0x1040ff9a, 0x24040042, 0xa000c73, 0x8fbf0018,
-0x1528ffb9, 0x0, 0x8cc20018, 0x3c188000,
-0x24190002, 0x58f825, 0xacdf0018, 0x37040a00,
-0xa0d90068, 0x9089003c, 0x240f0004, 0xa01021,
-0x31280020, 0x3c010800, 0xa02f3c31, 0x11000002,
-0x24050010, 0x24020001, 0x3c010800, 0xac223bcc,
-0xa000c69, 0x3c1f8000, 0x8f880014, 0x8c890060,
-0x109282b, 0x14a00002, 0x1008821, 0x8c910060,
-0x3c0b8000, 0x8d640e18, 0x240a0001, 0x2202821,
-0x2203021, 0xa38a0008, 0xe000ad9, 0x2208021,
-0xa000bf7, 0xaf820018, 0xa1823, 0x12200007,
-0x30640003, 0x3c0d8000, 0x35a70980, 0x90ec007c,
-0x318b0004, 0x15600019, 0x248e0004, 0x3c010800,
-0xa4243bf2, 0x3c180800, 0x97183bf2, 0x3052021,
-0xc4782b, 0x11e0ff6c, 0x8f840010, 0x2ca60005,
-0x14c0ffa4, 0x24040042, 0x30b90003, 0x17200002,
-0xb91823, 0x24a3fffc, 0x3c010800, 0xac233bd4,
-0x3c010800, 0xa4203bf2, 0xa000c36, 0x602821,
-0xac3824, 0xa000c5c, 0xec1826, 0x3c010800,
-0xa42e3bf2, 0xa000cc6, 0x0, 0x3c010800,
-0xac203bd4, 0xa000c72, 0x24040042, 0x8f830014,
-0x3c0b8000, 0x356a0a00, 0x14600006, 0x1021,
-0x91460030, 0x24050005, 0x30c400ff, 0x10850003,
-0x0, 0x3e00008, 0x0, 0x91490048,
-0x312800ff, 0x839c2, 0x14e0fffa, 0x3c048008,
-0x3c060800, 0x94c63bdc, 0x3c030800, 0x8c633bf4,
-0x3c050800, 0x8ca53bd4, 0x3c180800, 0x97183bf2,
-0x66c821, 0x8c8e0004, 0x3257821, 0x1f86821,
-0x1ae6023, 0x1980001d, 0x0, 0x9158004c,
-0x8f8d0020, 0x956e0e10, 0x330f00ff, 0x8da90004,
-0x1cf3023, 0x8daa0000, 0x30cfffff, 0xf6100,
-0x12c2821, 0x3821, 0x1472021, 0xac182b,
-0x83c821, 0xada50004, 0xadb90000, 0x91b8000a,
-0x1f87021, 0xa1ae000a, 0x956c0e12, 0x8f8a0020,
-0xa54c0008, 0x95490038, 0x25280001, 0xa5480038,
-0x9147000d, 0x34eb0008, 0xa14b000d, 0x3e00008,
-0x0, 0x27bdffd8, 0xafb00018, 0x938f0008,
-0x8fb00014, 0x3c087fff, 0x8f870010, 0x3c0c8000,
-0x3518ffff, 0xafbf0020, 0xafb1001c, 0x35990a00,
-0x2181824, 0x932a003c, 0xf5fc0, 0x3c02bfff,
-0x2cf00001, 0x3449ffff, 0x6bf825, 0x3c080800,
-0x8d083bf4, 0x8f99001c, 0x3c180800, 0x97183bea,
-0x3e95824, 0x107f80, 0x3c07efff, 0x3c05f0ff,
-0x16f1825, 0x3c118000, 0x31490020, 0x34e2ffff,
-0x34adffff, 0x362e0980, 0x27a50010, 0x24060002,
-0x1194023, 0x270a0002, 0x621824, 0x808021,
-0x15200002, 0x5821, 0x8d8b0e1c, 0xa7aa0012,
-0x500003a, 0x24070000, 0x30ef00ff, 0xf3f00,
-0x674025, 0x3c028008, 0xafa80014, 0x344b0080,
-0x916a0068, 0x3c0f0800, 0x91ef3bf1, 0x3c09dfff,
-0x353fffff, 0xa602b, 0x3c020800, 0x94423be4,
-0xa3af0011, 0x11fc024, 0xccf40, 0x3191825,
-0x8fa70010, 0xafa30014, 0x3c1f0800, 0x93ff3bf3,
-0xa7a20016, 0x8fa80014, 0xed4824, 0x3c0b0100,
-0x3c0a0fff, 0x12bc825, 0x33f80003, 0x354cffff,
-0x10d7824, 0x3c027000, 0x32c3824, 0x181e00,
-0xe24825, 0x1e35825, 0xafab0014, 0xafa90010,
-0x91df007c, 0xa3bf0015, 0xe000072, 0x0,
-0x362d0a00, 0x91a6003c, 0x30c40020, 0x10800006,
-0x26020008, 0x3c110800, 0x96313be0, 0x262effff,
-0x3c010800, 0xa42e3be0, 0x8fbf0020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f8a0018,
-0x16a602b, 0x5580ffc4, 0x24070001, 0xa000d50,
-0x30ef00ff, 0x93830008, 0x3c028000, 0x27bdffd8,
-0x34480a00, 0x805021, 0xafbf0020, 0x34460ac0,
-0x1002821, 0x1060000e, 0x34440980, 0x91070030,
-0x240b0005, 0x8f89000c, 0x30ec003f, 0x118b000b,
-0x3821, 0xafa90010, 0x3c0b8008, 0x8d69006c,
-0xafaa0018, 0xe00013a, 0xafa90014, 0xa3800008,
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x8d1f0048,
-0x3c180800, 0x8f183bd4, 0x8f990014, 0x3c027fff,
-0x8d080044, 0x3443ffff, 0xafa90010, 0x3c0b8008,
-0x8d69006c, 0x3e37024, 0x3197821, 0x1cf6823,
-0x1a83821, 0xafaa0018, 0xe00013a, 0xafa90014,
-0xa000da5, 0xa3800008, 0x3c058000, 0x34a60a00,
-0x90c7003c, 0x3c060800, 0x94c63bf2, 0x3c020800,
-0x8c423bec, 0x30e30020, 0x62400, 0x10600031,
-0x444825, 0x3c088008, 0x35050080, 0x90a30068,
-0x6821, 0x240c0001, 0x5021, 0x240b0001,
-0x3c188000, 0x370f0070, 0x8de80000, 0x3c078000,
-0xaf880024, 0x8cf90178, 0x720fffe, 0x34e50070,
-0x8ca20000, 0x3c030800, 0x8c630074, 0x3c0f0800,
-0x8def0070, 0x482023, 0x642821, 0xc021,
-0xa4302b, 0x1f87021, 0x1c64021, 0x3c010800,
-0xac250074, 0x3c010800, 0xac280070, 0xacec0148,
-0x3c020800, 0x8c423bf4, 0xa4ea0144, 0xa4eb0146,
-0xace2014c, 0x3c040800, 0x90843bf1, 0x3c038008,
-0xa0e40152, 0xace90154, 0xa4ed0158, 0x346d0080,
-0x91ac004c, 0x3c091000, 0xa0ec016d, 0x3e00008,
-0xace90178, 0x8cac0e1c, 0x3c0b0800, 0x8d6b3bd4,
-0x94aa0e16, 0x94ae0e14, 0x1666821, 0x314bffff,
-0xa000dcd, 0x31caffff, 0x3c048000, 0x34830a00,
-0x9065003c, 0x30a20020, 0x1040002b, 0x0,
-0x5821, 0x5021, 0x4821, 0x3c088000,
-0x35040070, 0x8c880000, 0x3c078000, 0xaf880024,
-0x8cec0178, 0x580fffe, 0x34ee0070, 0x8dcd0000,
-0x3c050800, 0x8ca50074, 0x3c040800, 0x8c840070,
-0x1a86023, 0xacc021, 0x1021, 0x30c302b,
-0x82c821, 0x3267821, 0x3c010800, 0xac380074,
-0x3c010800, 0xac2f0070, 0xaceb0148, 0x3c0e0800,
-0x8dce3bf4, 0x240dff91, 0x240b0040, 0xa4e90144,
-0xa4ea0146, 0xacee014c, 0xa0ed0152, 0xaceb0154,
-0xa4e00158, 0x90ea0109, 0x3c091000, 0xa0ea016d,
-0x3e00008, 0xace90178, 0x8c8b0e18, 0x94870e12,
-0x94860e10, 0x30eaffff, 0xa000e08, 0x30c9ffff,
-0x3c048000, 0x34830a00, 0x9065003c, 0x30a20020,
-0x10400039, 0x27bdfff8, 0x240c0001, 0x5021,
-0x240b0001, 0x3c088000, 0x35040070, 0x8c890000,
-0x3c088000, 0xaf890024, 0x8d0d0178, 0x5a0fffe,
-0x350e0070, 0x8dc70000, 0x3c050800, 0x8ca50074,
-0x3c040800, 0x8c840070, 0xe96823, 0xadc021,
-0x1021, 0x30d302b, 0x82c821, 0x3267821,
-0x3c010800, 0xac380074, 0x3c010800, 0xac2f0070,
-0x91090109, 0x3c0e0800, 0x91ce3c31, 0x3c0380ff,
-0xa3a90003, 0x8fad0000, 0x31c7007f, 0x3462ffff,
-0x1a82025, 0xafa40000, 0x9106010a, 0xa3a00002,
-0x7ce00, 0xa3a60001, 0x8fa50000, 0x240e3000,
-0x3c091000, 0xa2c024, 0x3197825, 0xad0f014c,
-0x27bd0008, 0xad0e0154, 0xa5000158, 0xad0c0148,
-0xa50a0144, 0x240aff80, 0xa50b0146, 0xa10a0152,
-0x3e00008, 0xad090178, 0x8c8c0e18, 0x94870e12,
-0x94860e10, 0x30ebffff, 0xa000e3e, 0x30caffff,
-0x27bdffe8, 0xafb00010, 0x3c108000, 0xafbf0014,
-0x36180a00, 0x970f0032, 0xe000ad5, 0x31e43fff,
-0x8e0e0100, 0x240dff80, 0x3c042000, 0x1c25821,
+0x1263821, 0x10600006, 0xaf870034, 0x8d09003c,
+0x8d03006c, 0x1233823, 0x18e00082, 0x0,
+0x3c0b8008, 0x356a0080, 0x3c108000, 0xa1400069,
+0x36060980, 0x8cc20038, 0x3c068000, 0x34c50a00,
+0x90a8003c, 0x310c0020, 0x1180001a, 0xaf820030,
+0x240d0001, 0x3c0e8000, 0x35d10a00, 0xa38d001c,
+0xaf800024, 0x8e240024, 0x8f850024, 0x240d0008,
+0xaf800020, 0xaf800028, 0x3c010800, 0xa42d3fe6,
+0x3c010800, 0xa4203ffa, 0xe000b8d, 0x3021,
+0x9228003c, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x86142, 0xaf82002c, 0x27bd0020, 0x3e00008,
+0x31820001, 0x90b80032, 0x240e0001, 0x330f00ff,
+0xf2182, 0x108e0041, 0x24190002, 0x10990064,
+0x34c40ac0, 0x3c038000, 0x34640a00, 0x8c8f0024,
+0x15e0001e, 0x34660900, 0x909f0030, 0x24180005,
+0x33f9003f, 0x1338004e, 0x24030001, 0x8f860020,
+0xa383001c, 0xaf860028, 0xaf860024, 0x3c0e8000,
+0x35d10a00, 0x8e240024, 0x8f850024, 0x240d0008,
+0x3c010800, 0xa42d3fe6, 0x3c010800, 0xa4203ffa,
+0xe000b8d, 0x0, 0x9228003c, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x86142, 0xaf82002c,
+0x27bd0020, 0x3e00008, 0x31820001, 0x8c8a0008,
+0x8c8b0024, 0x8cd00064, 0x3c0e8000, 0x35d10a00,
+0x14b2823, 0xaf900024, 0xa380001c, 0xaf850028,
+0x8e240024, 0x8f860020, 0x8f850024, 0x240d0008,
+0x3c010800, 0xa42d3fe6, 0x3c010800, 0xa4203ffa,
+0xe000b8d, 0x0, 0x9228003c, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x86142, 0xaf82002c,
+0x27bd0020, 0x3e00008, 0x31820001, 0x90a20030,
+0x3051003f, 0x52240028, 0x34c50ac0, 0x8cb00024,
+0x16000022, 0x34cb0900, 0x8ca60048, 0x3c0a7fff,
+0x3545ffff, 0xc51024, 0x3c0e8000, 0xaf820020,
+0x35c50900, 0x8f880020, 0x8cad0060, 0x10d602b,
+0x15800002, 0x1002021, 0x8ca40060, 0xa000c2c,
+0xaf840020, 0x8d02006c, 0xa000c06, 0x3c068000,
+0x8c820048, 0x8f860020, 0x3c097fff, 0x3527ffff,
+0x478824, 0x3c048008, 0x24030001, 0xaf910028,
+0xac80006c, 0xa383001c, 0xa000c3a, 0xaf860024,
+0x8c9f0014, 0xa000c2c, 0xaf9f0020, 0x8d620068,
+0xa000c76, 0x3c0e8000, 0x34c40980, 0x8c890070,
+0x8ca30014, 0x123382b, 0x10e00004, 0x0,
+0x8c820070, 0xa000c76, 0x3c0e8000, 0x8ca20014,
+0xa000c76, 0x3c0e8000, 0x8f850024, 0x27bdffe0,
+0xafbf0018, 0xafb10014, 0x14a00008, 0xafb00010,
+0x3c048000, 0x34870a00, 0x90e60030, 0x24020005,
+0x30c3003f, 0x106200b9, 0x34840900, 0x8f910020,
+0xa08021, 0x3c048000, 0x348e0a00, 0x8dcd0004,
+0x3c060800, 0x8cc63fd8, 0x31a73fff, 0xe6602b,
+0x55800001, 0xe03021, 0x938f001c, 0x11e00078,
+0xd0282b, 0x349f0980, 0x93f9007c, 0x33380002,
+0x13000079, 0x24030034, 0xc3102b, 0x144000d9,
+0x0, 0xc33023, 0xd0282b, 0x3c010800,
+0xa4233fe4, 0x14a0006e, 0x2001821, 0x3c040800,
+0x8c843fd4, 0x64402b, 0x55000001, 0x602021,
+0x3c058000, 0x34a90a00, 0x912a003c, 0x3c010800,
+0xac243fdc, 0x31430020, 0x14600003, 0x4821,
+0x34ab0e00, 0x8d690018, 0x8f88002c, 0x128202b,
+0x1080005f, 0x0, 0x3c050800, 0x8ca53fdc,
+0xa96821, 0x10d602b, 0x1180005c, 0xb0702b,
+0x1093823, 0xe02821, 0x3c010800, 0xac273fdc,
+0x12000003, 0x240afffc, 0x10b0008d, 0x32240003,
+0xaa1824, 0x3c010800, 0xa4203ffa, 0x3c010800,
+0xac233fdc, 0x602821, 0x8f840024, 0x12040006,
+0x3c0b8008, 0x8d6c006c, 0x2002021, 0xaf910020,
+0x25900001, 0xad70006c, 0x8f8d0028, 0x858823,
+0xaf910024, 0x1a52023, 0xaf840028, 0x12200002,
+0x24070018, 0x24070010, 0x3c188008, 0x37060080,
+0x90cf0068, 0x3c010800, 0xa0273ff8, 0x24070001,
+0x31ee00ff, 0x11c70047, 0x0, 0x14800018,
+0x2821, 0x3c068000, 0x34d10980, 0x34cd0100,
+0x91a60009, 0x8e2c0018, 0x24c40001, 0xc8602,
+0x3205007f, 0x308b007f, 0x1165007f, 0x2407ff80,
+0x3c198008, 0x37290080, 0xa124004c, 0x3c080800,
+0x8d083ff4, 0x24180002, 0x3c010800, 0xa0384039,
+0x350f0008, 0x3c010800, 0xac2f3ff4, 0x24050010,
+0x3c028000, 0x34440a00, 0x9083003c, 0x307f0020,
+0x13e00005, 0xa02021, 0x240a0001, 0x3c010800,
+0xac2a3fdc, 0x34a40001, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x801021, 0x3e00008, 0x27bd0020,
+0x3c010800, 0xa4203fe4, 0x10a0ff94, 0x2001821,
+0xa000cca, 0xc01821, 0xa000cc1, 0x24030030,
+0x3c050800, 0x8ca53fdc, 0xb0702b, 0x11c0ffa8,
+0x0, 0x3c190800, 0x97393fe4, 0x325c021,
+0x307782b, 0x11e00007, 0x2caa0004, 0x3c036000,
+0x8c625404, 0x305f003f, 0x17e0ffe3, 0x24040042,
+0x2caa0004, 0x1140ff9a, 0x24040042, 0xa000d2e,
+0x8fbf0018, 0x1528ffb9, 0x0, 0x8cca0018,
+0x3c1f8000, 0x24020002, 0x15f1825, 0xacc30018,
+0x37f90a00, 0xa0c20068, 0x9329003c, 0x24040004,
+0xa01021, 0x31280020, 0x3c010800, 0xa0244039,
+0x11000002, 0x24050010, 0x24020001, 0x3c010800,
+0xac223fd4, 0xa000d24, 0x3c028000, 0x8f880028,
+0x8c890060, 0x109282b, 0x14a00002, 0x1008821,
+0x8c910060, 0x3c048000, 0x348b0e00, 0x8d640018,
+0x240a0001, 0x2202821, 0x2203021, 0xa38a001c,
+0xe000b8d, 0x2208021, 0xa000cb0, 0xaf82002c,
+0x45823, 0x12200007, 0x31640003, 0x3c0e8000,
+0x35c70980, 0x90ed007c, 0x31ac0004, 0x15800019,
+0x248f0004, 0x3c010800, 0xa4243ffa, 0x3c1f0800,
+0x97ff3ffa, 0x3e5c821, 0xd9c02b, 0x1300ff6b,
+0x8f840024, 0x2ca60005, 0x14c0ffa3, 0x24040042,
+0x30a20003, 0x14400002, 0xa21823, 0x24a3fffc,
+0x3c010800, 0xac233fdc, 0x3c010800, 0xa4203ffa,
+0xa000cf1, 0x602821, 0xc77024, 0xa000d17,
+0x1c72026, 0x3c010800, 0xa42f3ffa, 0xa000d82,
+0x0, 0x3c010800, 0xac203fdc, 0xa000d2d,
+0x24040042, 0x8f830028, 0x3c058000, 0x34aa0a00,
+0x14600006, 0x1021, 0x91470030, 0x24060005,
+0x30e400ff, 0x10860003, 0x0, 0x3e00008,
+0x0, 0x914b0048, 0x316900ff, 0x941c2,
+0x1500fffa, 0x3c068008, 0x3c040800, 0x94843fe4,
+0x3c030800, 0x8c633ffc, 0x3c190800, 0x8f393fdc,
+0x3c0f0800, 0x95ef3ffa, 0x64c021, 0x8ccd0004,
+0x3197021, 0x1cf6021, 0x34ab0e00, 0x18d2823,
+0x18a0001d, 0x0, 0x914f004c, 0x8f8c0034,
+0x956d0010, 0x31ee00ff, 0x8d890004, 0x1ae3023,
+0x8d8a0000, 0x30ceffff, 0xe2900, 0x125c821,
+0x3821, 0x1472021, 0x325182b, 0x83c021,
+0xad990004, 0xad980000, 0x918f000a, 0x1cf6821,
+0xa18d000a, 0x95650012, 0x8f8a0034, 0xa5450008,
+0x954b0038, 0x25690001, 0xa5490038, 0x9148000d,
+0x35070008, 0xa147000d, 0x3e00008, 0x0,
+0x27bdffd8, 0xafb00018, 0x9388001c, 0x8fb00014,
+0x3c0a8000, 0x3c197fff, 0x8f870024, 0x3738ffff,
+0xafbf0020, 0xafb1001c, 0x355f0a00, 0x2181824,
+0x93eb003c, 0x87fc0, 0x3c02bfff, 0x6f6025,
+0x2cf00001, 0x3449ffff, 0x3c1f0800, 0x8fff3ffc,
+0x8f990030, 0x3c180800, 0x97183ff2, 0x1897824,
+0x104780, 0x3c07efff, 0x3c05f0ff, 0x1e81825,
+0x3c118000, 0x31690020, 0x34e2ffff, 0x34adffff,
+0x362e0980, 0x27a50010, 0x24060002, 0x3f96023,
+0x270b0002, 0x354a0e00, 0x621824, 0x808021,
+0x15200002, 0x4021, 0x8d48001c, 0xa7ab0012,
+0x5800039, 0x24070000, 0x30e800ff, 0x83f00,
+0x675825, 0x3c028008, 0xafab0014, 0x344f0080,
+0x91ea0068, 0x3c080800, 0x91083ff9, 0x3c09dfff,
+0x352cffff, 0xaf82b, 0x3c020800, 0x94423fec,
+0xa3a80011, 0x16cc024, 0x1fcf40, 0x3191825,
+0x8fa70010, 0xafa30014, 0x3c0c0800, 0x918c3ffb,
+0xa7a20016, 0x8fab0014, 0xed4824, 0x3c0f0100,
+0x3c0a0fff, 0x12fc825, 0x31980003, 0x355fffff,
+0x16d4024, 0x3c027000, 0x33f3824, 0x181e00,
+0xe24825, 0x1037825, 0xafaf0014, 0xafa90010,
+0x91cc007c, 0xe000092, 0xa3ac0015, 0x362d0a00,
+0x91a6003c, 0x30c40020, 0x10800006, 0x26020008,
+0x3c110800, 0x96313fe8, 0x262effff, 0x3c010800,
+0xa42e3fe8, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
+0x3e00008, 0x27bd0028, 0x8f8b002c, 0x10b502b,
+0x5540ffc5, 0x24070001, 0xa000e0e, 0x30e800ff,
+0x9383001c, 0x3c028000, 0x27bdffd8, 0x34480a00,
+0x805021, 0xafbf0020, 0x34460ac0, 0x1002821,
+0x1060000e, 0x34440980, 0x91070030, 0x240b0005,
+0x8f890020, 0x30ec003f, 0x118b000b, 0x3821,
+0xafa90010, 0x3c0b8008, 0x8d69006c, 0xafaa0018,
+0xe00015a, 0xafa90014, 0xa380001c, 0x8fbf0020,
+0x3e00008, 0x27bd0028, 0x8d1f0048, 0x3c180800,
+0x8f183fdc, 0x8f990028, 0x3c027fff, 0x8d080044,
+0x3443ffff, 0xafa90010, 0x3c0b8008, 0x8d69006c,
+0x3e37024, 0x3197821, 0x1cf6823, 0x1a83821,
+0xafaa0018, 0xe00015a, 0xafa90014, 0xa000e62,
+0xa380001c, 0x3c058000, 0x34a60a00, 0x90c7003c,
+0x3c060800, 0x94c63ffa, 0x3c020800, 0x8c423ff4,
+0x30e30020, 0x62400, 0x1060001e, 0x443825,
+0x3c088008, 0x35050080, 0x90a30068, 0x4821,
+0x24080001, 0x2821, 0x24040001, 0x3c068000,
+0x8ccd0178, 0x5a0fffe, 0x34cf0140, 0xade80008,
+0x3c020800, 0x8c423ffc, 0xa5e50004, 0xa5e40006,
+0xade2000c, 0x3c040800, 0x90843ff9, 0x3c038008,
+0x34790080, 0xa1e40012, 0xade70014, 0xa5e90018,
+0x9338004c, 0x3c0e1000, 0xa1f8002d, 0x3e00008,
+0xacce0178, 0x34a90e00, 0x8d28001c, 0x3c0c0800,
+0x8d8c3fdc, 0x952b0016, 0x952a0014, 0x1864821,
+0x3164ffff, 0xa000e8a, 0x3145ffff, 0x3c048000,
+0x34830a00, 0x9065003c, 0x30a20020, 0x10400019,
+0x34870e00, 0x4021, 0x3821, 0x2021,
+0x3c068000, 0x8cc90178, 0x520fffe, 0x34ca0140,
+0x34cf0100, 0x91eb0009, 0xad480008, 0x3c0e0800,
+0x8dce3ffc, 0x240dff91, 0x240c0040, 0x3c081000,
+0xa5440004, 0xa5470006, 0xad4e000c, 0xa14d0012,
+0xad4c0014, 0xa5400018, 0xa14b002d, 0x3e00008,
+0xacc80178, 0x8ce80018, 0x94e60012, 0x94e40010,
+0x30c7ffff, 0xa000eb3, 0x3084ffff, 0x3c048000,
+0x34830a00, 0x9065003c, 0x30a20020, 0x10400027,
+0x27bdfff8, 0x24090001, 0x3821, 0x24080001,
+0x3c068000, 0x8cca0178, 0x540fffe, 0x3c0280ff,
+0x34c40100, 0x908d0009, 0x3c0c0800, 0x918c4039,
+0xa3ad0003, 0x8fab0000, 0x3185007f, 0x3459ffff,
+0x1665025, 0xafaa0000, 0x9083000a, 0xa3a00002,
+0x57e00, 0xa3a30001, 0x8fb80000, 0x34cb0140,
+0x240c3000, 0x3197024, 0x1cf6825, 0xad6d000c,
+0x27bd0008, 0xad6c0014, 0xa5600018, 0xad690008,
+0xa5670004, 0x2409ff80, 0xa5680006, 0x3c081000,
+0xa1690012, 0x3e00008, 0xacc80178, 0x34870e00,
+0x8ce90018, 0x94e60012, 0x94e40010, 0x30c8ffff,
+0xa000ed7, 0x3087ffff, 0x27bdffe0, 0xafb10014,
+0x3c118000, 0xafb00010, 0xafbf0018, 0x36380a00,
+0x970f0032, 0x36300100, 0xe000b89, 0x31e43fff,
+0x8e0e0000, 0x240dff80, 0x3c042000, 0x1c25821,
0x16d6024, 0xc4940, 0x316a007f, 0x12a4025,
-0x1043825, 0x3c048008, 0xae070830, 0x34860080,
+0x1043825, 0x3c048008, 0xae270830, 0x34860080,
0x90c50068, 0x24030002, 0x30a200ff, 0x10430004,
-0x8f9f000c, 0x8f990010, 0xac9f0068, 0xac990064,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x3c0a0800, 0x254a37fc, 0x3c090800, 0x252938d4,
-0x3c080800, 0x25082c74, 0x3c070800, 0x24e739e4,
-0x3c060800, 0x24c63638, 0x3c050800, 0x24a53390,
-0x3c040800, 0x24842fa0, 0x3c030800, 0x246336ec,
-0x3c020800, 0x24423488, 0x3c010800, 0xac2a3dfc,
-0x3c010800, 0xac293df8, 0x3c010800, 0xac283df4,
-0x3c010800, 0xac273e00, 0x3c010800, 0xac263e10,
-0x3c010800, 0xac253e08, 0x3c010800, 0xac243e04,
-0x3c010800, 0xac233e14, 0x3c010800, 0xac223e0c,
-0x3e00008, 0x0, 0x0 };
-u32 bce_TXP_b09FwData[(0x0/4) + 1] = { 0x0 };
-u32 bce_TXP_b09FwRodata[(0x30/4) + 1] = {
+0x8f9f0020, 0x8f990024, 0xac9f0068, 0xac990064,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x3c0a0800, 0x254a3aa8, 0x3c090800,
+0x25293b38, 0x3c080800, 0x25082f44, 0x3c070800,
+0x24e73c04, 0x3c060800, 0x24c6392c, 0x3c050800,
+0x24a53680, 0x3c040800, 0x24843284, 0x3c030800,
+0x246339e0, 0x3c020800, 0x2442377c, 0x3c010800,
+0xac2a3fb8, 0x3c010800, 0xac293fb4, 0x3c010800,
+0xac283fb0, 0x3c010800, 0xac273fbc, 0x3c010800,
+0xac263fcc, 0x3c010800, 0xac253fc4, 0x3c010800,
+0xac243fc0, 0x3c010800, 0xac233fd0, 0x3c010800,
+0xac223fc8, 0x3e00008, 0x0, 0x0 };
+u32 bce_TXP_b09FwData[(0x0/4) + 1] = { 0x0 };
+u32 bce_TXP_b09FwRodata[(0x30/4) + 1] = {
0x80000940, 0x80000900, 0x80080100,
0x80080080, 0x80080000, 0x800e0000, 0x80080080,
0x80080000, 0x80000a80, 0x80000a00, 0x80000980,
0x80000900, 0x0 };
-u32 bce_TXP_b09FwBss[(0x24c/4) + 1] = { 0x0 };
-u32 bce_TXP_b09FwSbss[(0x6c/4) + 1] = { 0x0 };
-u32 bce_TXP_b09FwSdata[(0x0/4) + 1] = { 0x0 };
+u32 bce_TXP_b09FwBss[(0x24c/4) + 1] = { 0x0 };
+u32 bce_TXP_b09FwSbss[(0x64/4) + 1] = { 0x0 };
+u32 bce_TXP_b09FwSdata[(0x0/4) + 1] = { 0x0 };
-
-int bce_TPAT_b09FwReleaseMajor = 0x1;
-int bce_TPAT_b09FwReleaseMinor = 0x0;
-int bce_TPAT_b09FwReleaseFix = 0x0;
-u32 bce_TPAT_b09FwStartAddr = 0x08000488;
-u32 bce_TPAT_b09FwTextAddr = 0x08000400;
-int bce_TPAT_b09FwTextLen = 0x13a4;
-u32 bce_TPAT_b09FwDataAddr = 0x00000000;
-int bce_TPAT_b09FwDataLen = 0x0;
-u32 bce_TPAT_b09FwRodataAddr = 0x080017a4;
-int bce_TPAT_b09FwRodataLen = 0x4;
-u32 bce_TPAT_b09FwBssAddr = 0x08001800;
-int bce_TPAT_b09FwBssLen = 0x12b4;
-u32 bce_TPAT_b09FwSbssAddr = 0x080017c0;
-int bce_TPAT_b09FwSbssLen = 0x40;
-u32 bce_TPAT_b09FwSDataAddr = 0x00000000;
-int bce_TPAT_b09FwSDataLen = 0x0;
-u32 bce_TPAT_b09FwText[(0x13a4/4) + 1] = {
-0xa000122,
-0x0, 0x0, 0xd, 0x74706134,
-0x2e362e31, 0x36000000, 0x4061001, 0x0,
+
+int bce_TPAT_b09FwReleaseMajor = 0x6;
+int bce_TPAT_b09FwReleaseMinor = 0x0;
+int bce_TPAT_b09FwReleaseFix = 0x11;
+u32 bce_TPAT_b09FwStartAddr = 0x08000490;
+u32 bce_TPAT_b09FwTextAddr = 0x08000400;
+int bce_TPAT_b09FwTextLen = 0x12fc;
+u32 bce_TPAT_b09FwDataAddr = 0x00000000;
+int bce_TPAT_b09FwDataLen = 0x0;
+u32 bce_TPAT_b09FwRodataAddr = 0x080016fc;
+int bce_TPAT_b09FwRodataLen = 0x4;
+u32 bce_TPAT_b09FwBssAddr = 0x0800175c;
+int bce_TPAT_b09FwBssLen = 0x12b4;
+u32 bce_TPAT_b09FwSbssAddr = 0x08001720;
+int bce_TPAT_b09FwSbssLen = 0x3c;
+u32 bce_TPAT_b09FwSDataAddr = 0x00000000;
+int bce_TPAT_b09FwSDataLen = 0x0;
+u32 bce_TPAT_b09FwText[(0x12fc/4) + 1] = {
+0xa000124, 0x0, 0x0,
+0xd, 0x74706136, 0x2e302e31, 0x37000000,
+0x6001101, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
@@ -7809,11 +7699,11 @@ u32 bce_TPAT_b09FwText[(0x13a4/4) + 1] = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x10000003, 0x0,
-0xd, 0xd, 0x3c020800, 0x244217c0,
-0x3c030800, 0x24632ab4, 0xac400000, 0x43202b,
+0xd, 0xd, 0x3c020800, 0x24421720,
+0x3c030800, 0x24632a10, 0xac400000, 0x43202b,
0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd2ffc,
-0x3a0f021, 0x3c100800, 0x26100488, 0x3c1c0800,
-0x279c17c0, 0xe00025e, 0x0, 0xd,
+0x3a0f021, 0x3c100800, 0x26100490, 0x3c1c0800,
+0x279c1720, 0xe000262, 0x0, 0xd,
0x2402ff80, 0x27bdffe0, 0x821024, 0xafb00010,
0xaf420020, 0xafbf0018, 0xafb10014, 0x93650004,
0x3084007f, 0x3441821, 0x3c020008, 0x621821,
@@ -7827,7 +7717,7 @@ u32 bce_TPAT_b09FwText[(0x13a4/4) + 1] = {
0x10a00010, 0x0, 0x96020002, 0xa72021,
0x1044025, 0x2442fffe, 0xa7421016, 0x92030004,
0x2402ff80, 0x431024, 0x304200ff, 0x10400003,
-0x3c020400, 0xa000172, 0x1024025, 0x8cc20000,
+0x3c020400, 0xa000174, 0x1024025, 0x8cc20000,
0xaf421018, 0x8f420178, 0x440fffe, 0x2402000a,
0xa7420140, 0x96020002, 0x24040009, 0x30420007,
0x21023, 0x30420007, 0xa7420142, 0x96020002,
@@ -7842,9 +7732,9 @@ u32 bce_TPAT_b09FwText[(0x13a4/4) + 1] = {
0x0, 0x8f421018, 0xacc20000, 0x96020006,
0x3042ffff, 0x24420002, 0x21043, 0x21040,
0x3628821, 0x96220000, 0x1120000d, 0x3044ffff,
-0xa71021, 0x8f83003c, 0x8f45101c, 0x21082,
+0xa71021, 0x8f830038, 0x8f45101c, 0x21082,
0x21080, 0x431021, 0xac450000, 0x30a6ffff,
-0xe0005b7, 0x52c02, 0x402021, 0xa6220000,
+0xe00058d, 0x52c02, 0x402021, 0xa6220000,
0x92030004, 0x2402ff80, 0x431024, 0x304200ff,
0x1040001f, 0x0, 0x92020005, 0x30420002,
0x1040001b, 0x0, 0x9742100c, 0x2442fffe,
@@ -7853,9 +7743,9 @@ u32 bce_TPAT_b09FwText[(0x13a4/4) + 1] = {
0x0, 0x8f421000, 0x441fffe, 0x0,
0x9742100c, 0x8f45101c, 0x3042ffff, 0x24420030,
0x21082, 0x21080, 0x5b1021, 0xac450000,
-0x30a6ffff, 0xe0005b7, 0x52c02, 0xa6220000,
-0x96040002, 0x24840008, 0xe0001e7, 0x3084ffff,
-0x97440104, 0xe0001f5, 0x3084ffff, 0x8fbf0018,
+0x30a6ffff, 0xe00058d, 0x52c02, 0xa6220000,
+0x96040002, 0x24840008, 0xe0001e9, 0x3084ffff,
+0x97440104, 0xe0001f7, 0x3084ffff, 0x8fbf0018,
0x8fb10014, 0x8fb00010, 0x3c021000, 0x27bd0020,
0x3e00008, 0xaf420178, 0x3084ffff, 0x30820007,
0x8f850024, 0x10400002, 0x24830007, 0x3064fff8,
@@ -7865,867 +7755,857 @@ u32 bce_TPAT_b09FwText[(0x13a4/4) + 1] = {
0x10400002, 0x2483000f, 0x3064fff0, 0xa41021,
0x46182b, 0xaf850030, 0x462023, 0x14600002,
0xaf82002c, 0xaf84002c, 0x8f82002c, 0x34048000,
-0x3421821, 0x641821, 0xaf83003c, 0x3e00008,
+0x3421821, 0x641821, 0xaf830038, 0x3e00008,
0xaf420080, 0x8f820014, 0x10400008, 0x8f820004,
-0x8f82ffe4, 0x14400005, 0x8f820004, 0x3c02ffbf,
+0x8f82ffdc, 0x14400005, 0x8f820004, 0x3c02ffbf,
0x3442ffff, 0x822024, 0x8f820004, 0x30430006,
0x24020002, 0x1062000f, 0x3c020101, 0x2c620003,
0x50400005, 0x24020004, 0x1060000f, 0x3c020001,
-0xa00022e, 0x0, 0x10620005, 0x24020006,
-0x1462000c, 0x3c020111, 0xa000227, 0x821025,
+0xa000230, 0x0, 0x10620005, 0x24020006,
+0x1462000c, 0x3c020111, 0xa000229, 0x821025,
0x3c020011, 0x821025, 0xaf421000, 0x24020001,
-0xa00022e, 0xaf82000c, 0x821025, 0xaf421000,
+0xa000230, 0xaf82000c, 0x821025, 0xaf421000,
0xaf80000c, 0x0, 0x0, 0x0,
0x3e00008, 0x0, 0x8f82000c, 0x10400004,
0x0, 0x8f421000, 0x441fffe, 0x0,
-0x3e00008, 0x0, 0x8f820010, 0x229c2,
-0x24a3fff0, 0x31842, 0x2444f800, 0x31140,
-0x431021, 0x21080, 0x431021, 0x21080,
-0x3c030800, 0x24631800, 0x2c840301, 0x14800013,
-0x433021, 0x8f840018, 0xa4102b, 0x1440000f,
-0x3021, 0xa41023, 0x21940, 0x621821,
-0x31880, 0x621821, 0x8f82001c, 0x821021,
-0x2442ffff, 0x45102b, 0x14400004, 0x31880,
-0x3c020800, 0x24421a14, 0x623021, 0x3e00008,
-0xc01021, 0x27bdffe0, 0xafbf0018, 0xafb10014,
-0xafb00010, 0x3c046008, 0x8c825000, 0x2403ff7f,
-0x3c066000, 0x431024, 0x3442380c, 0xac825000,
-0x8cc24c1c, 0x3c1a8000, 0x21602, 0x3042000f,
-0x10400007, 0xaf82001c, 0x8cc34c1c, 0x3c02001f,
-0x3442fc00, 0x621824, 0x319c2, 0xaf830018,
-0x8f420008, 0x275b4000, 0x34420001, 0xaf420008,
-0xaf800024, 0x3c02601c, 0xaf400080, 0xaf400084,
-0x8c450008, 0x8cc30808, 0x34028000, 0x3422021,
-0x2402fff0, 0x621824, 0x3c020080, 0x3c010800,
-0xac220420, 0x3c025709, 0xaf84003c, 0x14620004,
-0xaf850034, 0x24020001, 0xa00028e, 0xaf820014,
-0xaf800014, 0x3c028000, 0x34440070, 0x8c830000,
-0x8f420000, 0x38420001, 0x30420001, 0x10400018,
-0xaf830038, 0x804021, 0x603021, 0x8d070000,
-0x3c050800, 0x8ca5045c, 0x3c040800, 0x8c840458,
-0xe63023, 0x1021, 0xa62821, 0xa6302b,
-0x822021, 0x862021, 0x3c010800, 0xac25045c,
-0x3c010800, 0xac240458, 0x8f420000, 0x38420001,
-0x30420001, 0x1440ffed, 0xe03021, 0xaf870038,
-0x3c028000, 0x34420070, 0x8c470000, 0x8f860038,
-0x3c050800, 0x8ca5045c, 0x3c040800, 0x8c840458,
-0xe63823, 0x1021, 0xa72821, 0x822021,
-0x8f820014, 0xa7302b, 0x862021, 0x3c010800,
-0xac25045c, 0x3c010800, 0xac240458, 0x10400016,
-0x0, 0x97420104, 0x10400005, 0x8f830000,
-0x14600007, 0x2462ffff, 0xa0002d0, 0x2c62000a,
-0x2c620010, 0x50400004, 0x8f830000, 0x24620001,
-0xaf820000, 0x8f830000, 0x2c62000a, 0x14400003,
-0x2c620007, 0xa0002d7, 0xaf80ffe4, 0x10400002,
-0x24020001, 0xaf82ffe4, 0x8f430108, 0x8f440100,
-0x30622000, 0xaf830004, 0x10400008, 0xaf840010,
-0x3c020800, 0x8c42042c, 0x24420001, 0x3c010800,
-0xac22042c, 0xa0005b3, 0x3c024000, 0x30650200,
-0x14a00003, 0x24020f00, 0x14820260, 0x24020d00,
-0x97420104, 0x104002c8, 0x3c024000, 0x30624000,
-0x144000ad, 0x8f82003c, 0x8c440008, 0x8f420178,
-0x440fffe, 0x24020800, 0xaf420178, 0x24020008,
-0xa7420140, 0xa7400142, 0x97420104, 0x8f840004,
-0x3051ffff, 0x30820001, 0x10400007, 0x2208021,
-0x2623fffe, 0x24020002, 0x3070ffff, 0xa7420146,
-0xa000304, 0xa7430148, 0xa7400146, 0x3c020800,
-0x8c42043c, 0x1440000d, 0x8f830010, 0x30820020,
-0x14400002, 0x24030009, 0x24030001, 0x602021,
-0x8f830010, 0x24020900, 0x50620001, 0x34840004,
-0xa744014a, 0xa00031f, 0x0, 0x24020f00,
-0x14620005, 0x30820020, 0x14400006, 0x2403000d,
-0xa00031e, 0x24030005, 0x14400002, 0x24030009,
-0x24030001, 0xa743014a, 0x3c020800, 0x8c420420,
-0x3c040048, 0xe00020a, 0x442025, 0xe000233,
-0x0, 0x8f82000c, 0x1040003e, 0x0,
-0x8f421000, 0x3c030020, 0x431024, 0x10400039,
-0x8f820004, 0x30420002, 0x10400036, 0x0,
-0x97421014, 0x14400033, 0x0, 0x97421008,
-0x8f88003c, 0x3042ffff, 0x24420006, 0x21882,
-0x33880, 0xe83021, 0x30430001, 0x8cc40000,
-0x10600004, 0x30420003, 0xd, 0xa000360,
-0xe81021, 0x54400010, 0x3084ffff, 0x3c05ffff,
-0x852024, 0x851826, 0x3182b, 0x4102b,
-0x431024, 0x10400005, 0x0, 0x0,
-0xd, 0x0, 0x240001cb, 0x8cc20000,
-0xa00035f, 0x452025, 0x3883ffff, 0x3182b,
+0x3e00008, 0x0, 0x8f820010, 0x2443f800,
+0x231c2, 0x24c2fff0, 0x2c630301, 0x10600003,
+0x21042, 0xa000257, 0xac820000, 0x8f850018,
+0xc5102b, 0x1440000b, 0x1821, 0xc51023,
+0x24470001, 0x8f82001c, 0xa21021, 0x2442ffff,
+0x46102b, 0x54400004, 0x2402ffff, 0xa000257,
+0xac870000, 0x2402ffff, 0xa000260, 0xac820000,
+0x8c820000, 0x21940, 0x621821, 0x31880,
+0x621821, 0x31880, 0x3c020800, 0x2442175c,
+0x621821, 0x3e00008, 0x601021, 0x27bdffd8,
+0xafbf0020, 0xafb1001c, 0xafb00018, 0x3c046008,
+0x8c825000, 0x2403ff7f, 0x3c066000, 0x431024,
+0x3442380c, 0xac825000, 0x8cc24c1c, 0x3c1a8000,
+0x21602, 0x3042000f, 0x10400007, 0xaf82001c,
+0x8cc34c1c, 0x3c02001f, 0x3442fc00, 0x621824,
+0x319c2, 0xaf830018, 0x8f420008, 0x275b4000,
+0x34420001, 0xaf420008, 0xaf800024, 0x3c02601c,
+0xaf400080, 0xaf400084, 0x8c450008, 0x8cc30808,
+0x34028000, 0x3422021, 0x2402fff0, 0x621824,
+0x3c020080, 0x3c010800, 0xac220420, 0x3c025709,
+0xaf840038, 0x14620004, 0xaf850034, 0x24020001,
+0xa000292, 0xaf820014, 0xaf800014, 0x8f420000,
+0x38420001, 0x30420001, 0x1440fffc, 0x8f820014,
+0x10400016, 0x0, 0x97420104, 0x10400005,
+0x8f830000, 0x14600007, 0x2462ffff, 0xa0002a7,
+0x2c62000a, 0x2c620010, 0x50400004, 0x8f830000,
+0x24620001, 0xaf820000, 0x8f830000, 0x2c62000a,
+0x14400003, 0x2c620007, 0xa0002ae, 0xaf80ffdc,
+0x10400002, 0x24020001, 0xaf82ffdc, 0x8f430108,
+0x8f440100, 0x30622000, 0xaf830004, 0x10400008,
+0xaf840010, 0x3c020800, 0x8c42042c, 0x24420001,
+0x3c010800, 0xac22042c, 0xa00058a, 0x3c024000,
+0x30650200, 0x14a00003, 0x24020f00, 0x14820260,
+0x24020d00, 0x97420104, 0x104002c8, 0x3c024000,
+0x30624000, 0x144000ad, 0x8f820038, 0x8c440008,
+0x8f420178, 0x440fffe, 0x24020800, 0xaf420178,
+0x24020008, 0xa7420140, 0xa7400142, 0x97420104,
+0x8f840004, 0x3051ffff, 0x30820001, 0x10400007,
+0x2208021, 0x2623fffe, 0x24020002, 0x3070ffff,
+0xa7420146, 0xa0002db, 0xa7430148, 0xa7400146,
+0x3c020800, 0x8c42043c, 0x1440000d, 0x8f830010,
+0x30820020, 0x14400002, 0x24030009, 0x24030001,
+0x602021, 0x8f830010, 0x24020900, 0x50620001,
+0x34840004, 0xa744014a, 0xa0002f6, 0x0,
+0x24020f00, 0x14620005, 0x30820020, 0x14400006,
+0x2403000d, 0xa0002f5, 0x24030005, 0x14400002,
+0x24030009, 0x24030001, 0xa743014a, 0x3c020800,
+0x8c420420, 0x3c040048, 0xe00020c, 0x442025,
+0xe000235, 0x0, 0x8f82000c, 0x1040003e,
+0x0, 0x8f421000, 0x3c030020, 0x431024,
+0x10400039, 0x8f820004, 0x30420002, 0x10400036,
+0x0, 0x97421014, 0x14400033, 0x0,
+0x97421008, 0x8f880038, 0x3042ffff, 0x24420006,
+0x21882, 0x33880, 0xe83021, 0x30430001,
+0x8cc40000, 0x10600004, 0x30420003, 0xd,
+0xa000337, 0xe81021, 0x54400010, 0x3084ffff,
+0x3c05ffff, 0x852024, 0x851826, 0x3182b,
0x4102b, 0x431024, 0x10400005, 0x0,
-0x0, 0xd, 0x0, 0x240001d4,
-0x8cc20000, 0x3444ffff, 0xe81021, 0xac440000,
-0x3c020800, 0x8c420430, 0x24420001, 0x3c010800,
-0xac220430, 0x8f620000, 0x8f84003c, 0xaf820008,
-0x8c830000, 0x3402ffff, 0x1462000f, 0x1021,
-0x3c050800, 0x8ca50454, 0x3c040800, 0x8c840450,
-0xb02821, 0xb0302b, 0x822021, 0x862021,
-0x3c010800, 0xac250454, 0x3c010800, 0xac240450,
-0xa0005a9, 0x24040008, 0x8c820000, 0x30420100,
-0x1040000f, 0x1021, 0x3c050800, 0x8ca5044c,
-0x3c040800, 0x8c840448, 0xb02821, 0xb0302b,
-0x822021, 0x862021, 0x3c010800, 0xac25044c,
-0x3c010800, 0xac240448, 0xa0005a9, 0x24040008,
-0x3c050800, 0x8ca50444, 0x3c040800, 0x8c840440,
-0xb02821, 0xb0302b, 0x822021, 0x862021,
-0x3c010800, 0xac250444, 0x3c010800, 0xac240440,
-0xa0005a9, 0x24040008, 0x8f620008, 0x8f620000,
-0x21602, 0x304300f0, 0x24020030, 0x10620005,
-0x24020040, 0x106200e0, 0x8f820020, 0xa0005b1,
-0x24420001, 0x14a00005, 0x0, 0x0,
-0xd, 0x0, 0x240001fe, 0x8f420178,
-0x440fffe, 0x0, 0xe00023b, 0x0,
-0x14400005, 0x408021, 0x0, 0xd,
-0x0, 0x24000205, 0x8e020000, 0x10400005,
+0x0, 0xd, 0x0, 0x24000222,
+0x8cc20000, 0xa000336, 0x452025, 0x3883ffff,
+0x3182b, 0x4102b, 0x431024, 0x10400005,
+0x0, 0x0, 0xd, 0x0,
+0x2400022b, 0x8cc20000, 0x3444ffff, 0xe81021,
+0xac440000, 0x3c020800, 0x8c420430, 0x24420001,
+0x3c010800, 0xac220430, 0x8f620000, 0x8f840038,
+0xaf820008, 0x8c830000, 0x3402ffff, 0x1462000f,
+0x1021, 0x3c050800, 0x8ca50454, 0x3c040800,
+0x8c840450, 0xb02821, 0xb0302b, 0x822021,
+0x862021, 0x3c010800, 0xac250454, 0x3c010800,
+0xac240450, 0xa000580, 0x24040008, 0x8c820000,
+0x30420100, 0x1040000f, 0x1021, 0x3c050800,
+0x8ca5044c, 0x3c040800, 0x8c840448, 0xb02821,
+0xb0302b, 0x822021, 0x862021, 0x3c010800,
+0xac25044c, 0x3c010800, 0xac240448, 0xa000580,
+0x24040008, 0x3c050800, 0x8ca50444, 0x3c040800,
+0x8c840440, 0xb02821, 0xb0302b, 0x822021,
+0x862021, 0x3c010800, 0xac250444, 0x3c010800,
+0xac240440, 0xa000580, 0x24040008, 0x8f620008,
+0x8f620000, 0x21602, 0x304300f0, 0x24020030,
+0x10620005, 0x24020040, 0x106200e0, 0x8f820020,
+0xa000588, 0x24420001, 0x14a00005, 0x0,
+0x0, 0xd, 0x0, 0x24000256,
+0x8f420178, 0x440fffe, 0x0, 0xe00023d,
+0x27a40010, 0x14400005, 0x408021, 0x0,
+0xd, 0x0, 0x2400025d, 0x8e020000,
+0x10400005, 0x0, 0x0, 0xd,
+0x0, 0x24000260, 0x8f62000c, 0x4430003,
+0x24020001, 0xa00042e, 0xae000000, 0xae020000,
+0x8f820038, 0x8c480008, 0xa2000007, 0x8f65000c,
+0x8f640004, 0x30a3ffff, 0x42402, 0x852023,
+0x308200ff, 0x431021, 0x24420005, 0x23083,
+0x2cc20081, 0xa605000a, 0x14400005, 0xa2040004,
+0x0, 0xd, 0x0, 0x24000278,
+0x8f850038, 0xe0005ab, 0x26040014, 0x8f620004,
+0x8f430108, 0xa6020008, 0x3c021000, 0x621824,
+0x10600008, 0x0, 0x97420104, 0x92030007,
+0x2442ffec, 0x34630002, 0x3045ffff, 0xa0003c3,
+0xa2030007, 0x97420104, 0x2442fff0, 0x3045ffff,
+0x96060008, 0x2cc20013, 0x54400005, 0x92030007,
+0x92020007, 0x34420001, 0xa2020007, 0x92030007,
+0x24020001, 0x10620005, 0x24020003, 0x1062000b,
+0x8f820038, 0xa0003e0, 0x30c6ffff, 0x8f820038,
+0x3c04ffff, 0x8c43000c, 0x641824, 0x651825,
+0xac43000c, 0xa0003e0, 0x30c6ffff, 0x3c04ffff,
+0x8c430010, 0x641824, 0x651825, 0xac430010,
+0x30c6ffff, 0x24c20002, 0x21083, 0xa2020005,
+0x8f830038, 0x304200ff, 0x21080, 0x432821,
+0x8ca80000, 0x8ca20000, 0x24030004, 0x21702,
+0x14430012, 0x0, 0x97420104, 0x3c03ffff,
+0x1031824, 0x3042ffff, 0x461023, 0x2442fffe,
+0x624025, 0xaca80000, 0x92030005, 0x306200ff,
+0x21080, 0x501021, 0x90420014, 0x3042000f,
+0x431021, 0xa000415, 0xa2020006, 0x8ca40004,
+0x97420104, 0x9603000a, 0x3088ffff, 0x3042ffff,
+0x461023, 0x2442ffd6, 0x21400, 0x1024025,
+0xaca80004, 0x92020007, 0x92040005, 0x24630028,
+0x31883, 0x641821, 0x34420004, 0xa2030006,
+0xa2020007, 0x8f820004, 0x2403fffb, 0x34420002,
+0x431024, 0xaf820004, 0x92030006, 0x8f870038,
+0x31880, 0x701021, 0x8c440020, 0x3c02fff6,
+0x3442ffff, 0x824024, 0x671821, 0xae04000c,
+0xac68000c, 0x92050006, 0x3c03ff7f, 0x8e02000c,
+0x52880, 0xb02021, 0x3463ffff, 0x1033024,
+0x94880026, 0xa72821, 0x431024, 0xae02000c,
+0xac860020, 0xac880024, 0xaca80010, 0x24020010,
+0xa7420140, 0x24020002, 0xa7400142, 0xa7400144,
+0xa7420146, 0x97420104, 0x3c040008, 0x2442fffe,
+0xa7420148, 0x24020001, 0xe00020c, 0xa742014a,
+0x9603000a, 0x92020004, 0x431021, 0x24420002,
+0x30420007, 0x21023, 0x30420007, 0xe000235,
+0xae020010, 0x8f620000, 0x3c030800, 0x8c630444,
+0x24040010, 0xaf820008, 0x97420104, 0x3042ffff,
+0x2442fffe, 0x403821, 0x237c3, 0x3c020800,
+0x8c420440, 0x671821, 0x67282b, 0x461021,
+0x451021, 0x3c010800, 0xac230444, 0x3c010800,
+0xac220440, 0xa000515, 0x0, 0x14a00005,
0x0, 0x0, 0xd, 0x0,
-0x24000208, 0x8f62000c, 0x4430003, 0x24020001,
-0xa000457, 0xae000000, 0xae020000, 0x8f82003c,
-0x8c480008, 0xa2000007, 0x8f65000c, 0x8f640004,
-0x30a3ffff, 0x42402, 0x852023, 0x308200ff,
-0x431021, 0x24420005, 0x23083, 0x2cc20081,
-0xa605000a, 0x14400005, 0xa2040004, 0x0,
-0xd, 0x0, 0x24000220, 0x8f85003c,
-0xe0005d5, 0x26040014, 0x8f620004, 0x8f430108,
-0xa6020008, 0x3c021000, 0x621824, 0x10600008,
-0x0, 0x97420104, 0x92030007, 0x2442ffec,
-0x34630002, 0x3045ffff, 0xa0003ec, 0xa2030007,
-0x97420104, 0x2442fff0, 0x3045ffff, 0x96060008,
-0x2cc20013, 0x54400005, 0x92030007, 0x92020007,
-0x34420001, 0xa2020007, 0x92030007, 0x24020001,
-0x10620005, 0x24020003, 0x1062000b, 0x8f82003c,
-0xa000409, 0x30c6ffff, 0x8f82003c, 0x3c04ffff,
-0x8c43000c, 0x641824, 0x651825, 0xac43000c,
-0xa000409, 0x30c6ffff, 0x3c04ffff, 0x8c430010,
-0x641824, 0x651825, 0xac430010, 0x30c6ffff,
-0x24c20002, 0x21083, 0xa2020005, 0x8f83003c,
-0x304200ff, 0x21080, 0x432821, 0x8ca80000,
-0x8ca20000, 0x24030004, 0x21702, 0x14430012,
-0x0, 0x97420104, 0x3c03ffff, 0x1031824,
-0x3042ffff, 0x461023, 0x2442fffe, 0x624025,
-0xaca80000, 0x92030005, 0x306200ff, 0x21080,
-0x501021, 0x90420014, 0x3042000f, 0x431021,
-0xa00043e, 0xa2020006, 0x8ca40004, 0x97420104,
-0x9603000a, 0x3088ffff, 0x3042ffff, 0x461023,
-0x2442ffd6, 0x21400, 0x1024025, 0xaca80004,
-0x92020007, 0x92040005, 0x24630028, 0x31883,
-0x641821, 0x34420004, 0xa2030006, 0xa2020007,
-0x8f820004, 0x2403fffb, 0x34420002, 0x431024,
-0xaf820004, 0x92030006, 0x8f87003c, 0x31880,
-0x701021, 0x8c440020, 0x3c02fff6, 0x3442ffff,
-0x824024, 0x671821, 0xae04000c, 0xac68000c,
-0x92050006, 0x3c03ff7f, 0x8e02000c, 0x52880,
-0xb02021, 0x3463ffff, 0x1033024, 0x94880026,
-0xa72821, 0x431024, 0xae02000c, 0xac860020,
-0xac880024, 0xaca80010, 0x24020010, 0xa7420140,
-0x24020002, 0xa7400142, 0xa7400144, 0xa7420146,
-0x97420104, 0x3c040008, 0x2442fffe, 0xa7420148,
-0x24020001, 0xe00020a, 0xa742014a, 0x9603000a,
-0x92020004, 0x431021, 0x24420002, 0x30420007,
-0x21023, 0x30420007, 0xe000233, 0xae020010,
-0x8f620000, 0x3c030800, 0x8c630444, 0x24040010,
-0xaf820008, 0x97420104, 0x3042ffff, 0x2442fffe,
-0x403821, 0x237c3, 0x3c020800, 0x8c420440,
-0x671821, 0x67282b, 0x461021, 0x451021,
-0x3c010800, 0xac230444, 0x3c010800, 0xac220440,
-0xa00053e, 0x0, 0x14a00005, 0x0,
-0x0, 0xd, 0x0, 0x2400029e,
-0x8f420178, 0x440fffe, 0x0, 0xe00023b,
-0x0, 0x14400005, 0x408021, 0x0,
-0xd, 0x0, 0x240002a5, 0x8e020000,
-0x54400006, 0x92020007, 0x0, 0xd,
-0x0, 0x240002a8, 0x92020007, 0x30420004,
-0x10400005, 0x8f820004, 0x2403fffb, 0x34420002,
-0x431024, 0xaf820004, 0x8f620004, 0x4430008,
-0x92020007, 0x92020006, 0x8e03000c, 0xae000000,
-0x21080, 0x501021, 0xac430020, 0x92020007,
-0x30420004, 0x54400009, 0x9602000a, 0x92020005,
-0x3c030001, 0x21080, 0x501021, 0x8c460018,
-0xc33021, 0xac460018, 0x9602000a, 0x92060004,
-0x27710008, 0x2202021, 0xc23021, 0x24c60005,
-0x26050014, 0xe0005d5, 0x63082, 0x92040006,
-0x8f650004, 0x3c027fff, 0x42080, 0x912021,
-0x8c830004, 0x3442ffff, 0xa22824, 0x651821,
-0xac830004, 0x92020007, 0x92040005, 0x92030004,
-0x30420004, 0x10400014, 0x96070008, 0x308400ff,
-0x42080, 0x912021, 0x8c860004, 0x97420104,
-0x9605000a, 0x306300ff, 0x3042ffff, 0x431021,
-0x451021, 0x30e3ffff, 0x431023, 0x2442ffd8,
-0x30c6ffff, 0x21400, 0xc23025, 0xac860004,
-0xa0004f2, 0x92030007, 0x308500ff, 0x52880,
-0xb12821, 0x8ca40000, 0x97420104, 0x306300ff,
-0x3042ffff, 0x431021, 0x471023, 0x3c03ffff,
-0x832024, 0x3042ffff, 0x822025, 0xaca40000,
-0x92030007, 0x24020001, 0x10620006, 0x0,
-0x24020003, 0x10620011, 0x0, 0xa000515,
-0x8e030010, 0x97420104, 0x92030004, 0x9605000a,
-0x8e24000c, 0x431021, 0x451021, 0x2442fff2,
+0x2400030a, 0x8f420178, 0x440fffe, 0x0,
+0xe00023d, 0x27a40014, 0x14400005, 0x408021,
+0x0, 0xd, 0x0, 0x24000311,
+0x8e020000, 0x54400006, 0x92020007, 0x0,
+0xd, 0x0, 0x2400031c, 0x92020007,
+0x30420004, 0x10400005, 0x8f820004, 0x2403fffb,
+0x34420002, 0x431024, 0xaf820004, 0x8f620004,
+0x4430008, 0x92020007, 0x92020006, 0x8e03000c,
+0xae000000, 0x21080, 0x501021, 0xac430020,
+0x92020007, 0x30420004, 0x54400009, 0x9602000a,
+0x92020005, 0x3c030001, 0x21080, 0x501021,
+0x8c460018, 0xc33021, 0xac460018, 0x9602000a,
+0x92060004, 0x27710008, 0x2202021, 0xc23021,
+0x24c60005, 0x26050014, 0xe0005ab, 0x63082,
+0x92040006, 0x8f650004, 0x3c027fff, 0x42080,
+0x912021, 0x8c830004, 0x3442ffff, 0xa22824,
+0x651821, 0xac830004, 0x92020007, 0x92040005,
+0x92030004, 0x30420004, 0x10400014, 0x96070008,
+0x308400ff, 0x42080, 0x912021, 0x8c860004,
+0x97420104, 0x9605000a, 0x306300ff, 0x3042ffff,
+0x431021, 0x451021, 0x30e3ffff, 0x431023,
+0x2442ffd8, 0x30c6ffff, 0x21400, 0xc23025,
+0xac860004, 0xa0004c9, 0x92030007, 0x308500ff,
+0x52880, 0xb12821, 0x8ca40000, 0x97420104,
+0x306300ff, 0x3042ffff, 0x431021, 0x471023,
0x3c03ffff, 0x832024, 0x3042ffff, 0x822025,
-0xae24000c, 0xa000515, 0x8e030010, 0x97420104,
-0x92030004, 0x9605000a, 0x8e240010, 0x431021,
-0x451021, 0x2442ffee, 0x3c03ffff, 0x832024,
-0x3042ffff, 0x822025, 0xae240010, 0x8e030010,
-0x2402000a, 0xa7420140, 0xa7430142, 0x9603000a,
-0x92020004, 0x3c040040, 0x431021, 0xa7420144,
-0xa7400146, 0x97420104, 0xa7420148, 0x24020001,
-0xe00020a, 0xa742014a, 0xe000233, 0x0,
-0x8f620000, 0x92030004, 0x2021, 0xaf820008,
-0x97420104, 0x9606000a, 0x3042ffff, 0x621821,
-0x602821, 0x3c030800, 0x8c630444, 0x3c020800,
-0x8c420440, 0x651821, 0x441021, 0x65382b,
-0x471021, 0x3c010800, 0xac230444, 0x3c010800,
-0xac220440, 0x92040004, 0x862021, 0x2484000a,
-0x3084ffff, 0xe0001e7, 0x0, 0x97440104,
-0x3084ffff, 0xe0001f5, 0x0, 0x3c021000,
-0xaf420178, 0xa0005b0, 0x8f820020, 0x14820027,
-0x30620006, 0x97420104, 0x10400067, 0x3c024000,
-0x30624000, 0x10400005, 0x0, 0x0,
-0xd, 0x0, 0x24000396, 0x8f420178,
-0x440fffe, 0x24020800, 0xaf420178, 0x24020008,
-0xa7420140, 0xa7400142, 0x8f820004, 0x97430104,
-0x30420001, 0x10400007, 0x3070ffff, 0x2603fffe,
-0x24020002, 0xa7420146, 0xa7430148, 0xa000568,
-0x2402000d, 0xa7400146, 0x2402000d, 0xa742014a,
-0x8f620000, 0x24040008, 0xaf820008, 0xe0001e7,
-0x0, 0xa000542, 0x2002021, 0x10400042,
-0x3c024000, 0x93620000, 0x304300f0, 0x24020010,
-0x10620005, 0x24020070, 0x10620035, 0x0,
-0xa0005b0, 0x8f820020, 0x8f620000, 0x97430104,
-0x3050ffff, 0x3071ffff, 0x8f420178, 0x440fffe,
-0x32020007, 0x21023, 0x30420007, 0x2403000a,
-0x2604fffe, 0xa7430140, 0xa7420142, 0xa7440144,
-0xa7400146, 0xa7510148, 0x8f420108, 0x30420020,
-0x14400002, 0x24030009, 0x24030001, 0xa743014a,
-0xe00020a, 0x3c040040, 0xe000233, 0x0,
-0x3c070800, 0x8ce70444, 0x2111021, 0x2442fffe,
-0x3c060800, 0x8cc60440, 0x401821, 0xe33821,
-0x1021, 0x8f650000, 0xe3402b, 0xc23021,
-0x26040008, 0xc83021, 0x3084ffff, 0xaf850008,
-0x3c010800, 0xac270444, 0x3c010800, 0xac260440,
-0xe0001e7, 0x0, 0xa000542, 0x2202021,
-0xe000139, 0x0, 0x8f820020, 0x24420001,
-0xaf820020, 0x3c024000, 0xaf420138, 0x0,
-0xa00028f, 0x3c028000, 0x3084ffff, 0x30c6ffff,
+0xaca40000, 0x92030007, 0x24020001, 0x10620006,
+0x0, 0x24020003, 0x10620011, 0x0,
+0xa0004ec, 0x8e030010, 0x97420104, 0x92030004,
+0x9605000a, 0x8e24000c, 0x431021, 0x451021,
+0x2442fff2, 0x3c03ffff, 0x832024, 0x3042ffff,
+0x822025, 0xae24000c, 0xa0004ec, 0x8e030010,
+0x97420104, 0x92030004, 0x9605000a, 0x8e240010,
+0x431021, 0x451021, 0x2442ffee, 0x3c03ffff,
+0x832024, 0x3042ffff, 0x822025, 0xae240010,
+0x8e030010, 0x2402000a, 0xa7420140, 0xa7430142,
+0x9603000a, 0x92020004, 0x3c040040, 0x431021,
+0xa7420144, 0xa7400146, 0x97420104, 0xa7420148,
+0x24020001, 0xe00020c, 0xa742014a, 0xe000235,
+0x0, 0x8f620000, 0x92030004, 0x2021,
+0xaf820008, 0x97420104, 0x9606000a, 0x3042ffff,
+0x621821, 0x602821, 0x3c030800, 0x8c630444,
+0x3c020800, 0x8c420440, 0x651821, 0x441021,
+0x65382b, 0x471021, 0x3c010800, 0xac230444,
+0x3c010800, 0xac220440, 0x92040004, 0x862021,
+0x2484000a, 0x3084ffff, 0xe0001e9, 0x0,
+0x97440104, 0x3084ffff, 0xe0001f7, 0x0,
+0x3c021000, 0xaf420178, 0xa000587, 0x8f820020,
+0x14820027, 0x30620006, 0x97420104, 0x10400067,
+0x3c024000, 0x30624000, 0x10400005, 0x0,
+0x0, 0xd, 0x0, 0x24000420,
+0x8f420178, 0x440fffe, 0x24020800, 0xaf420178,
+0x24020008, 0xa7420140, 0xa7400142, 0x8f820004,
+0x97430104, 0x30420001, 0x10400007, 0x3070ffff,
+0x2603fffe, 0x24020002, 0xa7420146, 0xa7430148,
+0xa00053f, 0x2402000d, 0xa7400146, 0x2402000d,
+0xa742014a, 0x8f620000, 0x24040008, 0xaf820008,
+0xe0001e9, 0x0, 0xa000519, 0x2002021,
+0x10400042, 0x3c024000, 0x93620000, 0x304300f0,
+0x24020010, 0x10620005, 0x24020070, 0x10620035,
+0x8f820020, 0xa000588, 0x24420001, 0x8f620000,
+0x97430104, 0x3050ffff, 0x3071ffff, 0x8f420178,
+0x440fffe, 0x32020007, 0x21023, 0x30420007,
+0x2403000a, 0x2604fffe, 0xa7430140, 0xa7420142,
+0xa7440144, 0xa7400146, 0xa7510148, 0x8f420108,
+0x30420020, 0x14400002, 0x24030009, 0x24030001,
+0xa743014a, 0xe00020c, 0x3c040040, 0xe000235,
+0x0, 0x3c070800, 0x8ce70444, 0x2111021,
+0x2442fffe, 0x3c060800, 0x8cc60440, 0x401821,
+0xe33821, 0x1021, 0x8f650000, 0xe3402b,
+0xc23021, 0x26040008, 0xc83021, 0x3084ffff,
+0xaf850008, 0x3c010800, 0xac270444, 0x3c010800,
+0xac260440, 0xe0001e9, 0x0, 0xa000519,
+0x2202021, 0xe00013b, 0x0, 0x8f820020,
+0x24420001, 0xaf820020, 0x3c024000, 0xaf420138,
+0xa000292, 0x0, 0x3084ffff, 0x30c6ffff,
0x52c00, 0xa62825, 0x3882ffff, 0x451021,
0x45282b, 0x451021, 0x21c02, 0x3042ffff,
0x431021, 0x21c02, 0x3042ffff, 0x431021,
0x3842ffff, 0x3e00008, 0x3042ffff, 0x3084ffff,
0x30a5ffff, 0x1821, 0x10800007, 0x0,
0x30820001, 0x10400002, 0x42042, 0x651821,
-0xa0005cb, 0x52840, 0x3e00008, 0x601021,
+0xa0005a1, 0x52840, 0x3e00008, 0x601021,
0x10c00006, 0x24c6ffff, 0x8ca20000, 0x24a50004,
-0xac820000, 0xa0005d5, 0x24840004, 0x3e00008,
+0xac820000, 0xa0005ab, 0x24840004, 0x3e00008,
0x0, 0x10a00008, 0x24a3ffff, 0xac860000,
0x0, 0x0, 0x2402ffff, 0x2463ffff,
0x1462fffa, 0x24840004, 0x3e00008, 0x0,
0x0 };
-u32 bce_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 };
-u32 bce_TPAT_b09FwRodata[(0x4/4) + 1] = {
-0x1,
-0x0 };
-u32 bce_TPAT_b09FwBss[(0x12b4/4) + 1] = { 0x0 };
-u32 bce_TPAT_b09FwSbss[(0x40/4) + 1] = { 0x0 };
-u32 bce_TPAT_b09FwSdata[(0x0/4) + 1] = { 0x0 };
+u32 bce_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 };
+u32 bce_TPAT_b09FwRodata[(0x4/4) + 1] = {
+0x1, 0x0 };
+u32 bce_TPAT_b09FwBss[(0x12b4/4) + 1] = { 0x0 };
+u32 bce_TPAT_b09FwSbss[(0x3c/4) + 1] = { 0x0 };
+u32 bce_TPAT_b09FwSdata[(0x0/4) + 1] = { 0x0 };
-int bce_COM_b09FwReleaseMajor = 0x1;
-int bce_COM_b09FwReleaseMinor = 0x0;
-int bce_COM_b09FwReleaseFix = 0x0;
-u32 bce_COM_b09FwStartAddr = 0x080000f8;
-u32 bce_COM_b09FwTextAddr = 0x08000000;
-int bce_COM_b09FwTextLen = 0x4ac8;
-u32 bce_COM_b09FwDataAddr = 0x00000000;
-int bce_COM_b09FwDataLen = 0x0;
-u32 bce_COM_b09FwRodataAddr = 0x08004ac8;
-int bce_COM_b09FwRodataLen = 0x30;
-u32 bce_COM_b09FwBssAddr = 0x08004b58;
-int bce_COM_b09FwBssLen = 0xc0;
-u32 bce_COM_b09FwSbssAddr = 0x08004b20;
-int bce_COM_b09FwSbssLen = 0x38;
-u32 bce_COM_b09FwSDataAddr = 0x00000000;
-int bce_COM_b09FwSDataLen = 0x0;
-u32 bce_COM_b09FwText[(0x4ac8/4) + 1] = {
-0xa00003e,
-0x0, 0x0, 0xd, 0x636f6d34,
-0x2e362e31, 0x36000000, 0x4061002, 0x0,
-0x3, 0x14, 0x32, 0x3,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x10, 0x136, 0xea60,
-0x1, 0x0, 0x0, 0x0,
-0x8, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x2, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
+int bce_COM_b09FwReleaseMajor = 0x6;
+int bce_COM_b09FwReleaseMinor = 0x0;
+int bce_COM_b09FwReleaseFix = 0x11;
+u32 bce_COM_b09FwStartAddr = 0x08000118;
+u32 bce_COM_b09FwTextAddr = 0x08000000;
+int bce_COM_b09FwTextLen = 0x5594;
+u32 bce_COM_b09FwDataAddr = 0x00000000;
+int bce_COM_b09FwDataLen = 0x0;
+u32 bce_COM_b09FwRodataAddr = 0x08005594;
+int bce_COM_b09FwRodataLen = 0x38;
+u32 bce_COM_b09FwBssAddr = 0x08005638;
+int bce_COM_b09FwBssLen = 0x11c;
+u32 bce_COM_b09FwSbssAddr = 0x08005608;
+int bce_COM_b09FwSbssLen = 0x30;
+u32 bce_COM_b09FwSDataAddr = 0x00000000;
+int bce_COM_b09FwSDataLen = 0x0;
+u32 bce_COM_b09FwText[(0x5594/4) + 1] = {
+0xa000046, 0x0, 0x0,
+0xd, 0x636f6d36, 0x2e302e31, 0x37000000,
+0x6001102, 0x0, 0x3, 0xc8,
+0x32, 0x3, 0x0, 0x0,
0x0, 0x0, 0x0, 0x10,
+0x136, 0xea60, 0x5, 0x0,
+0x0, 0x0, 0x8, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x2,
0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x10000003, 0x0,
-0xd, 0xd, 0x3c020800, 0x24424b20,
-0x3c030800, 0x24634c18, 0xac400000, 0x43202b,
-0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd9ffc,
-0x3a0f021, 0x3c100800, 0x261000f8, 0x3c1c0800,
-0x279c4b20, 0xe000273, 0x0, 0xd,
-0x27bdffe8, 0x3c028000, 0xafb00010, 0xafbf0014,
-0x34500100, 0x92020009, 0x1040001a, 0x24030001,
-0x3c020800, 0x8c420020, 0x10400016, 0x1821,
-0xe000d71, 0x0, 0x96030008, 0x3c060800,
-0x94c64bfe, 0x8e040018, 0x8f82002c, 0x9605000c,
-0x31c00, 0x661825, 0xac440000, 0xac450004,
-0x24040001, 0xac400008, 0xac40000c, 0xac400010,
-0xac400014, 0xac400018, 0xe000d98, 0xac43001c,
-0x1821, 0x8fbf0014, 0x8fb00010, 0x601021,
-0x3e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010,
-0x3c028000, 0x94420108, 0x30437000, 0x24022000,
-0x1062000a, 0x28642001, 0x54800012, 0x8fbf0010,
-0x24024000, 0x10620008, 0x24026000, 0x1062000a,
-0x8fbf0010, 0xa000097, 0x1021, 0x8fbf0010,
-0xa000055, 0x27bd0018, 0xe000433, 0x0,
-0xa000096, 0x8fbf0010, 0xe000c81, 0x0,
-0x8fbf0010, 0x1021, 0x3e00008, 0x27bd0018,
-0x3c020800, 0x8c420020, 0x27bdffe8, 0x10400028,
-0xafbf0010, 0xe000d71, 0x0, 0x3c058000,
-0x94a20108, 0x94a3010c, 0x8f86002c, 0x3042003e,
-0x3063ffff, 0x21400, 0x431025, 0xacc20000,
-0x8ca20100, 0x3c070800, 0x94e74bfe, 0x8fbf0010,
-0xacc20004, 0x94a30116, 0x94a4010e, 0x3c022000,
-0x31c00, 0x3084ffff, 0x641825, 0xacc30008,
-0xe23825, 0x94a20110, 0x94a30112, 0x24040001,
-0x21400, 0x3063ffff, 0x431025, 0xacc2000c,
-0x94a20114, 0x27bd0018, 0x3042ffff, 0xacc20010,
-0xacc00014, 0xacc00018, 0xa000d98, 0xacc7001c,
-0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c068000,
-0x8cc202b8, 0x24030001, 0x4410008, 0x802821,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x10, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x10000003, 0x0, 0xd, 0xd,
+0x3c020800, 0x24425608, 0x3c030800, 0x24635754,
+0xac400000, 0x43202b, 0x1480fffd, 0x24420004,
+0x3c1d0800, 0x37bd9ffc, 0x3a0f021, 0x3c100800,
+0x26100118, 0x3c1c0800, 0x279c5608, 0xe000256,
+0x0, 0xd, 0x27bdffb4, 0xafa10000,
+0xafa20004, 0xafa30008, 0xafa4000c, 0xafa50010,
+0xafa60014, 0xafa70018, 0xafa8001c, 0xafa90020,
+0xafaa0024, 0xafab0028, 0xafac002c, 0xafad0030,
+0xafae0034, 0xafaf0038, 0xafb8003c, 0xafb90040,
+0xafbc0044, 0xafbf0048, 0xe001544, 0x0,
+0x8fbf0048, 0x8fbc0044, 0x8fb90040, 0x8fb8003c,
+0x8faf0038, 0x8fae0034, 0x8fad0030, 0x8fac002c,
+0x8fab0028, 0x8faa0024, 0x8fa90020, 0x8fa8001c,
+0x8fa70018, 0x8fa60014, 0x8fa50010, 0x8fa4000c,
+0x8fa30008, 0x8fa20004, 0x8fa10000, 0x27bd004c,
+0x3c1b6010, 0x8f7a5030, 0x377b5028, 0x3400008,
+0xaf7a0000, 0x8f820024, 0x27bdffe0, 0xafb00010,
+0xafbf0018, 0xafb10014, 0x8c42000c, 0x3c108000,
+0x8e110100, 0x10400034, 0x8fbf0018, 0xe000d84,
+0x0, 0x8f850020, 0x24047fff, 0x91202b,
+0xacb10000, 0x8e030104, 0x96020108, 0x31c00,
+0x3042ffff, 0x621825, 0xaca30004, 0x9202010a,
+0x96030114, 0x304200ff, 0x3063ffff, 0x21400,
+0x431025, 0xaca20008, 0x9603010c, 0x9602010e,
+0x31c00, 0x3042ffff, 0x621825, 0xaca3000c,
+0x96030110, 0x96020112, 0x31c00, 0x3042ffff,
+0x621825, 0xaca30010, 0x8e020118, 0xaca20014,
+0x8e02011c, 0xaca20018, 0x14800008, 0x8f820024,
+0x97820000, 0x3c042005, 0x441825, 0x24420001,
+0xaca3001c, 0xa0000c6, 0xa7820000, 0x3c034018,
+0x9442001e, 0x431025, 0xaca2001c, 0xe000db8,
+0x24040001, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x1021, 0x3e00008, 0x27bd0020, 0x3c078000,
+0x8ce202b8, 0x34e50100, 0x4410008, 0x24030001,
0x3c020800, 0x8c420060, 0x24420001, 0x3c010800,
-0xac220060, 0x3e00008, 0x601021, 0x8c830020,
-0x94820016, 0xacc30280, 0x2442fffc, 0xa4c20284,
-0x3c020800, 0x8c42005c, 0x8c840004, 0x94a3000e,
-0x24420001, 0x3c010800, 0xac22005c, 0x3c021000,
-0xa4c30286, 0xacc40288, 0x1821, 0xacc202b8,
-0x3e00008, 0x601021, 0x3c020800, 0x8c420020,
-0x27bdffe8, 0x1040002b, 0xafbf0010, 0xe000d71,
-0x0, 0x3c058000, 0x94a20108, 0x94a3010c,
-0x8f86002c, 0x3042003e, 0x3063ffff, 0x21400,
-0x431025, 0xacc20000, 0x8ca20100, 0x3c070800,
-0x94e74bfe, 0x8fbf0010, 0xacc20004, 0x94a30116,
-0x94a4010e, 0x3c022000, 0x31c00, 0x3084ffff,
-0x641825, 0xacc30008, 0xe23825, 0x94a20110,
-0x94a30112, 0x24040001, 0x21400, 0x3063ffff,
-0x431025, 0xacc2000c, 0x94a20114, 0x27bd0018,
-0x3042ffff, 0xacc20010, 0x8ca20118, 0xacc20014,
-0x90a2010b, 0x304200ff, 0xacc20018, 0xa000d98,
-0xacc7001c, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe0, 0xafb00010, 0x3c108000, 0xafb20018,
-0xafbf001c, 0xafb10014, 0x36120100, 0x9243000b,
-0x2402001a, 0x96510008, 0x1462005b, 0x2821,
-0x32220001, 0x10400018, 0x0, 0x8e420000,
-0x22340, 0x3c02003f, 0x3442ffff, 0x44102b,
-0x10400004, 0x3c030040, 0x96420014, 0xa00013b,
-0x832021, 0x8e030100, 0x24020100, 0x54620006,
-0x96420014, 0x3c028008, 0x94420004, 0x3042000f,
-0x22500, 0x96420014, 0x821025, 0xae020080,
-0xa00016f, 0x0, 0x3c020800, 0x8c420020,
-0x10400028, 0x0, 0xe000d71, 0x0,
-0x96020108, 0x9603010c, 0x8f85002c, 0x3042003e,
-0x3063ffff, 0x21400, 0x431025, 0xaca20000,
-0x8e020100, 0x3c060800, 0x94c64bfe, 0xaca20004,
-0x96030116, 0x9604010e, 0x3c022000, 0x31c00,
-0x3084ffff, 0x641825, 0xaca30008, 0xc23025,
-0x96020110, 0x96030112, 0x24040001, 0x21400,
-0x3063ffff, 0x431025, 0xaca2000c, 0x96020114,
-0x3042ffff, 0xaca20010, 0x8e020118, 0xaca20014,
-0x9202010b, 0x304200ff, 0xaca20018, 0xe000d98,
-0xaca6001c, 0x3c020800, 0x8c420040, 0x24420001,
-0x3c010800, 0xac220040, 0x3c030800, 0x8c630044,
-0x32220002, 0x32240004, 0x24630001, 0x3c010800,
-0xac230044, 0x10800008, 0x2282b, 0x2402021,
+0xac220060, 0x3e00008, 0x601021, 0x3c020800,
+0x8c42005c, 0x8ca40020, 0x94a30016, 0x8ca60004,
+0x94a5000e, 0x24420001, 0xace40280, 0x2463fffc,
+0x3c010800, 0xac22005c, 0x3c021000, 0xa4e30284,
+0xa4e50286, 0x1821, 0xace60288, 0xace202b8,
+0x3e00008, 0x601021, 0x27bdffe0, 0x3c028000,
+0xafb00010, 0x34420100, 0xafbf001c, 0xafb20018,
+0xafb10014, 0x8c430000, 0x94450008, 0x2462fe00,
+0x2c420381, 0x10400003, 0x381c2, 0xa000102,
+0x26100004, 0x24020100, 0x14620005, 0x3c118000,
+0x3c028008, 0x90420004, 0x305000ff, 0x3c118000,
+0x36320100, 0x96430014, 0x3202000f, 0x21500,
+0x431025, 0x3c030800, 0x8c630044, 0x30a40004,
+0xae220080, 0x24630001, 0x3c010800, 0xac230044,
+0x10800007, 0x30a20002, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0xa0000ce, 0x27bd0020,
+0x1040002d, 0x1821, 0x30a20080, 0x10400005,
+0x36220070, 0x8e44001c, 0xe000c67, 0x240500a0,
+0x36220070, 0x8c440000, 0x8f82000c, 0x821023,
+0x2c43012c, 0x10600004, 0xaf820010, 0x24030001,
+0xa000145, 0xaf84000c, 0x8e420004, 0x3c036020,
+0xaf84000c, 0xac620014, 0x3c020800, 0x8c420058,
+0x50400015, 0x1821, 0x8c620004, 0x240301fe,
+0x304203ff, 0x14430010, 0x1821, 0x2e020004,
+0x10400003, 0x2e020008, 0xa000140, 0x8021,
+0x14400003, 0x0, 0xa000140, 0x2610fff9,
+0xd, 0x24020002, 0x2021004, 0x3c036000,
+0xac626914, 0x1821, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x601021, 0x3e00008,
+0x27bd0020, 0x3c048000, 0x8c830100, 0x24020100,
+0x50620003, 0x3c028008, 0xd, 0x3c028008,
+0x90430004, 0x1021, 0x3063000f, 0x31d00,
+0x3e00008, 0xac830080, 0x41880, 0x2782ff9c,
+0x621821, 0x410c0, 0x441023, 0x8c640000,
+0x210c0, 0x3c030800, 0x246356e4, 0x431021,
+0x3c038000, 0xac640090, 0x3e00008, 0xaf820024,
+0x3c020800, 0x8c420114, 0x10400019, 0x30844000,
+0x30a2007f, 0x231c0, 0x3c020200, 0x10800014,
+0xa21825, 0x3c026020, 0xac430014, 0x3c040800,
+0x8c8456b8, 0x3c030800, 0x8c630110, 0x3c028000,
+0x24050900, 0xac450020, 0x862021, 0x24630001,
+0x3c028008, 0xac440064, 0x3c010800, 0xac230110,
+0x3c010800, 0xac2456b8, 0x3e00008, 0x0,
+0x3c026020, 0x3e00008, 0xac450014, 0x3e00008,
+0x1021, 0x3e00008, 0x1021, 0x30a20008,
+0x10400008, 0x24020100, 0x3c020800, 0x8c42010c,
+0x24420001, 0x3c010800, 0xac22010c, 0x3e00008,
+0x0, 0x14820008, 0x0, 0x3c020800,
+0x8c4200fc, 0x24420001, 0x3c010800, 0xac2200fc,
+0xa0001a3, 0x30a20020, 0x3c020800, 0x8c420084,
+0x24420001, 0x3c010800, 0xac220084, 0x30a20020,
+0x10400008, 0x30a20010, 0x3c020800, 0x8c420108,
+0x24420001, 0x3c010800, 0xac220108, 0x3e00008,
+0x0, 0x10400008, 0x0, 0x3c020800,
+0x8c420104, 0x24420001, 0x3c010800, 0xac220104,
+0x3e00008, 0x0, 0x3c020800, 0x8c420100,
+0x24420001, 0x3c010800, 0xac220100, 0x3e00008,
+0x0, 0x27bdffe0, 0xafb10014, 0x3c118000,
+0xafb20018, 0xafbf001c, 0xafb00010, 0x36320100,
+0x96500008, 0x32020004, 0x10400007, 0x32030002,
+0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0xa0000ce, 0x27bd0020, 0x1060000b, 0x2002821,
+0x8e240100, 0xe00018a, 0x0, 0x32020080,
+0x10400003, 0x240500a1, 0xe000c67, 0x8e44001c,
+0xa0001e3, 0x24020001, 0x8e230104, 0x8f820008,
+0x10430006, 0x2002821, 0x8e240100, 0xe00018a,
+0x0, 0x8e220104, 0xaf820008, 0x1021,
0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0xa0000c8, 0x27bd0020, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0xa01021, 0x3e00008,
-0x27bd0020, 0x27bdffe0, 0x3c058000, 0xafb10014,
-0xafbf0018, 0xafb00010, 0x34b10100, 0x9223000b,
-0x24020003, 0x14620043, 0x96300008, 0x32020001,
-0x10400016, 0x3c02003f, 0x8e230000, 0x3442ffff,
-0x32340, 0x44102b, 0x50400005, 0x24020100,
-0x96220014, 0x3c030040, 0xa0001a4, 0x832021,
-0x54620006, 0x96220014, 0x3c028008, 0x94420004,
-0x3042000f, 0x22500, 0x96220014, 0x821025,
-0xaca20080, 0xa0001af, 0x0, 0xe000099,
-0x0, 0x3c020800, 0x8c420040, 0x24420001,
-0x3c010800, 0xac220040, 0x3c020800, 0x8c420044,
-0x32030004, 0x24420001, 0x3c010800, 0xac220044,
-0x10600007, 0x32020002, 0x2202021, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0xa0000c8, 0x27bd0020,
-0x10400015, 0x8fbf0018, 0x3c048000, 0x8c830104,
-0x3c026020, 0xac430014, 0x8c420004, 0x240301fe,
-0x304203ff, 0x1443000c, 0x8fbf0018, 0x8c820100,
-0x219c2, 0x2462fffc, 0x2c420008, 0x10400003,
-0x24040002, 0x2462fffd, 0x442004, 0x3c026000,
-0xac446914, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-0x1021, 0x3e00008, 0x27bd0020, 0x3c048000,
-0x8c830100, 0x24020100, 0x50620003, 0x3c028008,
-0xd, 0x3c028008, 0x94430004, 0x1021,
-0x3063000f, 0x31d00, 0x3e00008, 0xac830080,
-0x3c028008, 0x34420080, 0x90420000, 0x3e00008,
-0xaf800000, 0x3e00008, 0x1021, 0x27bdffe8,
-0x3c028000, 0xafbf0014, 0xafb00010, 0x8c430100,
-0xac430020, 0x8c430104, 0xac4300a8, 0x9050010b,
-0xe0001e5, 0x321000ff, 0x3c020800, 0x24424b58,
-0x101880, 0x2e10001d, 0x16000005, 0x621021,
-0xe0001ea, 0x401821, 0xa000205, 0x0,
-0x8c420000, 0x40f809, 0x0, 0x401821,
-0x3c020800, 0x8c420034, 0x10600005, 0x24440001,
-0x3c028000, 0x8c430104, 0x3c026020, 0xac430014,
-0x8fbf0014, 0x8fb00010, 0x3c034000, 0x3c028000,
-0x27bd0018, 0xac430138, 0x3c010800, 0xac240034,
-0x3e00008, 0x0, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0x3c108000, 0x8e020140, 0xe0001e5,
-0xae020020, 0xe000399, 0x0, 0x3c040800,
-0x24840038, 0x8c820000, 0x3c034000, 0xae030178,
-0x8fbf0014, 0x8fb00010, 0x24420001, 0x27bd0018,
-0x3e00008, 0xac820000, 0x27bdffe8, 0xafb00010,
-0xafbf0014, 0x3c108000, 0x8e020180, 0xe0001e5,
-0xae020020, 0x8e030180, 0x24020f00, 0x54620008,
-0x3c028008, 0x8e020188, 0x3c0300e0, 0x3042ffff,
-0x431025, 0xae020080, 0xa00024a, 0x3c028000,
-0x34420080, 0x90420000, 0x24030050, 0x304200ff,
-0x14430008, 0x3c028000, 0xe000379, 0x0,
-0x14400004, 0x3c028000, 0xe000967, 0x0,
-0x3c028000, 0x3c034000, 0xac4301b8, 0x3c020800,
-0x8c42003c, 0x8fbf0014, 0x8fb00010, 0x24420001,
-0x3c010800, 0xac22003c, 0x3e00008, 0x27bd0018,
-0x3e00008, 0x1021, 0x3c058000, 0x34a40100,
-0x94820008, 0x30430002, 0x30420004, 0x10400003,
-0x0, 0xa0000c8, 0x0, 0x10600005,
-0x24040001, 0x3c020800, 0x8c420084, 0xa00026f,
-0x24420001, 0x8ca30104, 0x8f82000c, 0x10430008,
-0x2021, 0x8ca30104, 0x3c020800, 0x8c420084,
-0xaf83000c, 0x24420001, 0x3c010800, 0xac220084,
-0x3e00008, 0x801021, 0x27bdffe8, 0x3c036010,
-0xafbf0014, 0xafb00010, 0x8c655000, 0x2402ff7f,
-0x3c048000, 0xa22824, 0x34a5380c, 0x24020037,
-0xac655000, 0xac820008, 0x24020c80, 0xac820024,
-0x3c060800, 0x24c607a8, 0x3c020800, 0x24424b58,
-0x2405001c, 0x24a5ffff, 0xac460000, 0x4a1fffd,
-0x24420004, 0x3c020800, 0x244201ec, 0x3c010800,
-0xac224b60, 0x3c020800, 0x24420618, 0x3c010800,
-0xac224b64, 0x3c020800, 0x24420d10, 0x3c010800,
-0xac224ba0, 0x3c020800, 0x24420464, 0x3c030800,
-0x24630954, 0x3c040800, 0x2484095c, 0x3c050800,
-0x24a52c94, 0x3c010800, 0xac224bc0, 0x3c020800,
-0x24420760, 0x3c010800, 0xac264ba8, 0x3c010800,
-0xac254bb4, 0x3c010800, 0xac234bbc, 0x3c010800,
-0xac244bc4, 0x3c010800, 0xac224bc8, 0x3c010800,
-0xac234b5c, 0x3c010800, 0xac204b68, 0x3c010800,
-0xac204b6c, 0x3c010800, 0xac204b70, 0x3c010800,
-0xac204b74, 0x3c010800, 0xac204b78, 0x3c010800,
-0xac204b7c, 0x3c010800, 0xac204b80, 0x3c010800,
-0xac244b84, 0x3c010800, 0xac204b88, 0x3c010800,
-0xac204b8c, 0x3c010800, 0xac204b90, 0x3c010800,
-0xac204b94, 0x3c010800, 0xac204b98, 0x3c010800,
-0xac264b9c, 0x3c010800, 0xac264ba4, 0x3c010800,
-0xac204bac, 0x3c010800, 0xac254bb0, 0x3c010800,
-0xac234bb8, 0xe00055a, 0x0, 0x3c028000,
-0x34420070, 0x8c420000, 0xaf820010, 0x3c030800,
-0x8c630020, 0x8f820004, 0x10430004, 0x3c058000,
-0xe000d37, 0xaf830004, 0x3c058000, 0x34a90070,
-0x8d280000, 0x8f840010, 0x3c070800, 0x8ce700bc,
-0x3c060800, 0x8cc600b8, 0x1042023, 0x1021,
-0xe43821, 0xc23021, 0xe4202b, 0xc43021,
-0x3c010800, 0xac2700bc, 0x3c010800, 0xac2600b8,
-0x8cb00000, 0x32020007, 0x1040ffe4, 0xaf880010,
-0x8d260000, 0x3c050800, 0x8ca500bc, 0x3c040800,
-0x8c8400b8, 0xc83023, 0xa62821, 0x1021,
-0xa6302b, 0x822021, 0x862021, 0x32070001,
-0x3c010800, 0xac2500bc, 0x3c010800, 0xac2400b8,
-0x10e00004, 0x32020002, 0xe0001ec, 0x0,
-0x32020002, 0x10400004, 0x32020004, 0xe000217,
-0x0, 0x32020004, 0x5040ffc5, 0x3c028000,
-0xe00022b, 0x0, 0xa0002d5, 0x3c028000,
-0x3c029000, 0x34420001, 0x822025, 0x3c028000,
-0xac440020, 0x3c038000, 0x8c620020, 0x440fffe,
-0x0, 0x3e00008, 0x0, 0x3c028000,
-0x34430001, 0x832025, 0x3e00008, 0xac440020,
-0x27bdffe0, 0xafb10014, 0xafb00010, 0x808821,
-0xafbf0018, 0xe000315, 0x30b000ff, 0x8f83ffac,
-0x2202021, 0x90620025, 0x2028025, 0xa0700025,
-0x8c700018, 0x3c028000, 0xe000320, 0x2028024,
-0x1600000a, 0x8fbf0018, 0x3c038000, 0x8c6201f8,
-0x440fffe, 0x24020002, 0xac7101c0, 0xa06201c4,
-0x3c021000, 0xac6201f8, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffb8,
-0xafbf0044, 0xafb00040, 0x3c078000, 0x8ce60104,
-0x8f82ffa8, 0xafa60028, 0x8c450020, 0xafa5002c,
-0x8c44003c, 0xafa40030, 0x8c430040, 0xafa30034,
-0x8c42004c, 0xafa60010, 0xafa50014, 0xafa20020,
-0xafa20038, 0x3c020800, 0x8c420020, 0xafa40018,
-0xafa3001c, 0x8cf00100, 0x10400019, 0x8fbf0044,
-0xe000d71, 0x0, 0x8f83002c, 0x3c050800,
-0x94a54bfe, 0x3c024018, 0xac700000, 0xa22825,
-0x8fa20010, 0x24040001, 0xac620004, 0x8fa20014,
-0xac620008, 0x8fa20018, 0xac62000c, 0x8fa2001c,
-0xac620010, 0x8fa20020, 0xac620014, 0x8fa20024,
-0xac620018, 0xe000d98, 0xac65001c, 0x8fbf0044,
-0x8fb00040, 0x1021, 0x3e00008, 0x27bd0048,
-0x27bdffe8, 0xafbf0010, 0x3c038000, 0x94620184,
-0x30420200, 0x10400005, 0x2021, 0xe000fe3,
-0x0, 0xa00038f, 0x24040001, 0x8c620188,
-0x440000a, 0x8fbf0010, 0x8c620188, 0x3c03ff00,
-0x431024, 0x3c030400, 0x14430004, 0x24040001,
-0x8f82ffac, 0x90420008, 0x8fbf0010, 0x801021,
-0x3e00008, 0x27bd0018, 0x8f82ffb0, 0x24050001,
-0xa040001a, 0x3c028000, 0xa000325, 0x8c440140,
-0x27bdffe0, 0xafb10014, 0x8f91ffac, 0xafbf001c,
-0xafb20018, 0xafb00010, 0x92220000, 0x24030020,
-0x304200ff, 0x1043000c, 0x3c028000, 0x92220000,
-0x24030030, 0x304200ff, 0x10430007, 0x3c028000,
-0x92220000, 0x24030050, 0x304200ff, 0x14430081,
-0x8fbf001c, 0x3c028000, 0x90420148, 0x304200ff,
-0x2443ffff, 0x2c620005, 0x1040007a, 0x8fbf001c,
-0x31080, 0x3c030800, 0x24634ad8, 0x431021,
-0x8c420000, 0x400008, 0x0, 0x3c118000,
-0x8e240140, 0xe000315, 0x8f92ffac, 0x8e50000c,
-0x8e220144, 0x16020002, 0x24020001, 0xae42000c,
-0xe000320, 0x8e240140, 0x8e220144, 0x14500006,
+0x3e00008, 0x27bd0020, 0x2c820004, 0x14400002,
+0x1821, 0x2483fffd, 0x24020002, 0x621004,
+0x3c036000, 0x3e00008, 0xac626914, 0x27bdffe0,
+0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010,
+0x3c048000, 0x94820108, 0x30437000, 0x24022000,
+0x1062000a, 0x28622001, 0x54400052, 0x8fbf001c,
+0x24024000, 0x10620048, 0x24026000, 0x1062004a,
+0x8fbf001c, 0xa000251, 0x8fb20018, 0x34820100,
+0x90430009, 0x8c500018, 0x9451000c, 0x24020009,
+0x1062001c, 0x9021, 0x28620009, 0x14400021,
+0x8f820024, 0x2402000a, 0x50620012, 0x323100ff,
+0x2402000b, 0x1062000f, 0x0, 0x2402000c,
+0x14620018, 0x8f820024, 0x3c020800, 0x8c4256b8,
+0x24030900, 0xac830020, 0x501021, 0x3c038008,
+0xac620064, 0x3c010800, 0xac2256b8, 0xa000250,
+0x8fbf001c, 0xe0001e9, 0x102602, 0xa000230,
+0x8f820024, 0xe0001e9, 0x102602, 0x3c038008,
+0x9462001a, 0x8c72000c, 0x3042ffff, 0x2028025,
+0x8f820024, 0x8c42000c, 0x5040001e, 0x8fbf001c,
+0xe000d84, 0x0, 0x3c028000, 0x34420100,
+0x94430008, 0x8f820024, 0x31c00, 0x9444001e,
+0x8f820020, 0x641825, 0xac500000, 0x24040001,
+0xac510004, 0xac520008, 0xac40000c, 0xac400010,
+0xac400014, 0xac400018, 0xe000db8, 0xac43001c,
+0xa000250, 0x8fbf001c, 0xe000440, 0x0,
+0xa000250, 0x8fbf001c, 0xe000c9f, 0x0,
0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0xa000f51, 0x27bd0020, 0x8e42000c, 0xa000427,
-0x0, 0x96220010, 0x3c048000, 0x8c830144,
-0x3042ffff, 0x14620009, 0x0, 0x24020001,
-0xa6220010, 0x8c820140, 0xac820200, 0x3c021000,
-0xac820238, 0xa00042e, 0x8fbf001c, 0x96220010,
-0xa000427, 0x0, 0x92220000, 0x24030020,
-0x304200ff, 0x1443000b, 0x3c128000, 0x96220012,
-0x3c038000, 0x8c630144, 0x3042ffff, 0x14620018,
-0x0, 0x24020001, 0xa6220012, 0xa000400,
-0x8fbf001c, 0x8e440140, 0xe000315, 0x0,
-0x96220012, 0x8e430144, 0x3050ffff, 0x16030002,
-0x24020001, 0xa6220012, 0xe000320, 0x8e440140,
-0x8e420144, 0x16020006, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0xa000393, 0x27bd0020,
-0x96220012, 0xa000427, 0x0, 0x96220014,
-0x3c038000, 0x8c630144, 0x3042ffff, 0x14620009,
-0x0, 0x24020001, 0xa6220014, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa001268,
-0x27bd0020, 0x96220014, 0xa000427, 0x0,
-0x96220016, 0x3c038000, 0x8c630144, 0x3042ffff,
-0x14620008, 0x24020001, 0xa6220016, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa000b0b,
-0x27bd0020, 0x96220016, 0x14400006, 0x8fbf001c,
-0x3c020800, 0x8c420070, 0x24420001, 0x3c010800,
-0xac220070, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x27bdffe0, 0x3c028000,
-0xafb10014, 0xafbf001c, 0xafb20018, 0xafb00010,
-0x34510100, 0x92230009, 0x8c500100, 0x2402001f,
-0x106200aa, 0x28620020, 0x10400018, 0x24020038,
-0x2862000a, 0x1040000c, 0x2402000b, 0x28620008,
-0x1040002c, 0x0, 0x4600100, 0x28620002,
-0x14400028, 0x24020006, 0x10620026, 0x8fbf001c,
-0xa00054a, 0x8fb20018, 0x10620060, 0x2862000b,
-0x144000f7, 0x8fbf001c, 0x2402000e, 0x10620077,
-0x8fb20018, 0xa00054a, 0x0, 0x106200d3,
+0x1021, 0x3e00008, 0x27bd0020, 0x27bdffd8,
+0xafb40020, 0x3c036010, 0xafbf0024, 0xafb3001c,
+0xafb20018, 0xafb10014, 0xafb00010, 0x8c645000,
+0x2402ff7f, 0x3c140800, 0x26945638, 0x822024,
+0x3484380c, 0xac645000, 0x3c028000, 0x24030037,
+0xe0014b0, 0xac430008, 0x3c070800, 0x24e70618,
+0x2801021, 0x2404001d, 0x2484ffff, 0xac470000,
+0x481fffd, 0x24420004, 0x3c020800, 0x244207c8,
+0x3c010800, 0xac225640, 0x3c020800, 0x24420230,
+0x3c030800, 0x24630620, 0x3c040800, 0x248403b4,
+0x3c050800, 0x24a506f0, 0x3c060800, 0x24c62c9c,
+0x3c010800, 0xac225680, 0x3c020800, 0x24420530,
+0x3c010800, 0xac275684, 0x3c010800, 0xac265694,
+0x3c010800, 0xac23569c, 0x3c010800, 0xac2456a0,
+0x3c010800, 0xac2556a4, 0x3c010800, 0xac2256a8,
+0x3c010800, 0xac23563c, 0x3c010800, 0xac245644,
+0x3c010800, 0xac205660, 0x3c010800, 0xac255664,
+0x3c010800, 0xac205670, 0x3c010800, 0xac27567c,
+0x3c010800, 0xac265690, 0x3c010800, 0xac235698,
+0xe00056e, 0x0, 0xaf80000c, 0x3c028000,
+0x8c530000, 0x8f830004, 0x3c020800, 0x8c420020,
+0x10620021, 0x32620007, 0x8821, 0x2792ff9c,
+0x3c100800, 0x261056e4, 0x3c020800, 0x8c420020,
+0x24050001, 0x2251804, 0x432024, 0x8f820004,
+0x431024, 0x5044000c, 0x26310001, 0x10800008,
+0xaf900024, 0x8e430000, 0x3c028000, 0xac430090,
+0xe000d4b, 0xae05000c, 0xa0002c1, 0x26310001,
+0xae00000c, 0x26310001, 0x2e220002, 0x26100038,
+0x1440ffe9, 0x26520004, 0x3c020800, 0x8c420020,
+0xaf820004, 0x32620007, 0x1040ffd9, 0x3c028000,
+0x32620001, 0x1040002d, 0x32620002, 0x3c058000,
+0x8ca20100, 0x2021, 0xaca20020, 0x8ca30104,
+0x2c420781, 0x10400008, 0xaca300a8, 0x94a20108,
+0x24032000, 0x30427000, 0x14430003, 0x3c028008,
+0x90420005, 0x304400ff, 0xe000159, 0x0,
+0x3c028000, 0x9042010b, 0x304300ff, 0x2c62001e,
+0x54400004, 0x31080, 0xe000186, 0xa0002ec,
+0x0, 0x541021, 0x8c420000, 0x40f809,
+0x0, 0x10400004, 0x3c028000, 0x8c430104,
+0x3c026020, 0xac430014, 0x3c020800, 0x8c420034,
+0x3c044000, 0x3c038000, 0x24420001, 0xac640138,
+0x3c010800, 0xac220034, 0x32620002, 0x10400010,
+0x32620004, 0x3c108000, 0x8e020140, 0x2021,
+0xe000159, 0xae020020, 0xe000383, 0x0,
+0x3c024000, 0xae020178, 0x3c020800, 0x8c420038,
+0x24420001, 0x3c010800, 0xac220038, 0x32620004,
+0x1040ff97, 0x3c028000, 0x3c108000, 0x8e020180,
+0x2021, 0xe000159, 0xae020020, 0x8e030180,
+0x24020f00, 0x54620007, 0x3c028008, 0x8e020188,
+0x3c0300e0, 0x3042ffff, 0x431025, 0xa000328,
+0xae020080, 0x34420080, 0x90420000, 0x24030050,
+0x304200ff, 0x14430007, 0x0, 0xe000362,
+0x0, 0x14400003, 0x0, 0xe000971,
+0x0, 0x3c020800, 0x8c42003c, 0x3c044000,
+0x3c038000, 0x24420001, 0xac6401b8, 0x3c010800,
+0xac22003c, 0xa0002a3, 0x3c028000, 0x3c029000,
+0x34420001, 0x822025, 0x3c028000, 0xac440020,
+0x3c038000, 0x8c620020, 0x440fffe, 0x0,
+0x3e00008, 0x0, 0x3c028000, 0x34430001,
+0x832025, 0x3e00008, 0xac440020, 0x27bdffe0,
+0xafb10014, 0xafb00010, 0x808821, 0xafbf0018,
+0xe000332, 0x30b000ff, 0x8f83ff94, 0x2202021,
+0x90620025, 0x2028025, 0xa0700025, 0x8c700018,
+0x3c028000, 0xe00033d, 0x2028024, 0x1600000b,
+0x8fbf0018, 0x3c048000, 0x8c8201f8, 0x440fffe,
+0x348201c0, 0x24030002, 0xac510000, 0xa0430004,
+0x3c021000, 0xac8201f8, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffe8,
+0x3c028000, 0xafbf0010, 0x34420180, 0x94430004,
+0x8c440008, 0x30630200, 0x10600005, 0x2821,
+0xe00100c, 0x0, 0xa000378, 0x24050001,
+0x3c02ff00, 0x4800007, 0x821824, 0x3c020400,
+0x14620004, 0x24050001, 0x8f82ff94, 0x90420008,
+0x24050001, 0x8fbf0010, 0xa01021, 0x3e00008,
+0x27bd0018, 0x8f82ff98, 0x24050001, 0xa040001a,
+0x3c028000, 0x34420140, 0xa000342, 0x8c440000,
+0x8f85ff94, 0x27bdffe0, 0xafbf001c, 0xafb20018,
+0xafb10014, 0xafb00010, 0x90a20000, 0x304400ff,
+0x38830020, 0x38820030, 0x3182b, 0x2102b,
+0x621824, 0x10600003, 0x24020050, 0x148200a8,
+0x8fbf001c, 0x90a20005, 0x30420001, 0x104000a4,
+0x8fbf001c, 0x3c028000, 0x34420140, 0x90420008,
+0x2443ffff, 0x2c620005, 0x1040009e, 0x8fb20018,
+0x31080, 0x3c030800, 0x246355ac, 0x431021,
+0x8c420000, 0x400008, 0x0, 0x3c028000,
+0x34510140, 0xe000332, 0x8e240000, 0x8f92ff94,
+0x8e220004, 0x8e50000c, 0x16020002, 0x24020001,
+0xae42000c, 0xe00033d, 0x8e240000, 0x8e220004,
+0x14500006, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0xa000f78, 0x27bd0020, 0x8e42000c,
+0xa000419, 0x0, 0x3c048000, 0x34820140,
+0x94a30010, 0x8c420004, 0x3063ffff, 0x1443001c,
+0x0, 0x24020001, 0xa4a20010, 0x8c820238,
+0x441000f, 0x3c038000, 0x3c02003f, 0x3448f000,
+0x3c076000, 0x3c06ffc0, 0x8ce22bbc, 0x461824,
+0x481024, 0x21302, 0x31d82, 0x10620058,
+0x3c028000, 0x8c820238, 0x440fff7, 0x3c038000,
+0x34620140, 0x8c440000, 0x34620200, 0xac440000,
+0x3c021000, 0xac620238, 0xa00043b, 0x8fbf001c,
+0x94a20010, 0xa000419, 0x0, 0x24020020,
+0x1482000f, 0x3c028000, 0x3c038000, 0x94a20012,
+0x34630140, 0x8c630004, 0x3042ffff, 0x14620005,
+0x0, 0x24020001, 0xa4a20012, 0xa000402,
+0x8fbf001c, 0x94a20012, 0xa000419, 0x0,
+0x34510140, 0xe000332, 0x8e240000, 0x8f92ff94,
+0x8e230004, 0x96420012, 0x3050ffff, 0x16030002,
+0x24020001, 0xa6420012, 0xe00033d, 0x8e240000,
+0x8e220004, 0x16020006, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0xa00037c, 0x27bd0020,
+0x96420012, 0xa000419, 0x0, 0x3c038000,
+0x94a20014, 0x34630140, 0x8c630004, 0x3042ffff,
+0x14620008, 0x24020001, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0xa4a20014, 0xa001463,
+0x27bd0020, 0x94a20014, 0x14400021, 0x8fbf001c,
+0xa000435, 0x0, 0x3c038000, 0x94a20016,
+0x34630140, 0x8c630004, 0x3042ffff, 0x1462000d,
+0x24020001, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0xa4a20016, 0xa000b14, 0x27bd0020,
+0x94420078, 0x24420004, 0xa4a20010, 0xa00043b,
+0x8fbf001c, 0x94a20016, 0x24030001, 0x3042ffff,
+0x14430007, 0x8fbf001c, 0x3c020800, 0x8c420070,
+0x24420001, 0x3c010800, 0xac220070, 0x8fbf001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x27bdffd8, 0xafb20018, 0x8f92ff94,
+0xafb10014, 0xafbf0020, 0xafb3001c, 0xafb00010,
+0x3c028000, 0x34510100, 0x8c500100, 0x92420000,
+0x92230009, 0x304400ff, 0x2402001f, 0x106200ab,
+0x28620020, 0x10400019, 0x24020038, 0x2862000a,
+0x1040000d, 0x2402000b, 0x28620008, 0x1040002e,
+0x8f820024, 0x4600104, 0x28620002, 0x1440002a,
+0x8f820024, 0x24020006, 0x10620026, 0x8fbf0020,
+0xa00055f, 0x8fb3001c, 0x10620060, 0x2862000b,
+0x144000fa, 0x8fbf0020, 0x2402000e, 0x10620078,
+0x8f820024, 0xa00055f, 0x8fb3001c, 0x106200d2,
0x28620039, 0x1040000a, 0x24020080, 0x24020036,
-0x106200e3, 0x28620037, 0x104000c5, 0x24020035,
-0x106200d8, 0x8fbf001c, 0xa00054a, 0x8fb20018,
+0x106200e5, 0x28620037, 0x104000c3, 0x24020035,
+0x106200d9, 0x8fbf0020, 0xa00055f, 0x8fb3001c,
0x1062002d, 0x28620081, 0x10400006, 0x240200c8,
-0x24020039, 0x106200c9, 0x8fbf001c, 0xa00054a,
-0x8fb20018, 0x106200a2, 0x8fbf001c, 0xa00054a,
-0x8fb20018, 0x3c020800, 0x8c420020, 0x104000d4,
-0x8fbf001c, 0xe000d71, 0x0, 0x3c028000,
-0x34420100, 0x8c440000, 0x8f83002c, 0x94470008,
-0x3c050800, 0x94a54bfe, 0xac640000, 0x8c440004,
-0x73c00, 0xe53825, 0xac640004, 0x8c440018,
-0x9446000c, 0xac640008, 0x8c45001c, 0x63400,
-0x24040001, 0xac65000c, 0x9042000a, 0xc23025,
-0xac660010, 0xac600014, 0xac600018, 0xac67001c,
-0xa00050c, 0x8fbf001c, 0x3c020800, 0x8c420020,
-0x104000b3, 0x8fbf001c, 0xe000d71, 0x0,
-0x96240008, 0x3c030800, 0x94634bfe, 0x9625000c,
-0x42202, 0x9626000e, 0x8f82002c, 0x42600,
+0x24020039, 0x106200c9, 0x8fbf0020, 0xa00055f,
+0x8fb3001c, 0x106200a2, 0x8fbf0020, 0xa00055f,
+0x8fb3001c, 0x8f820024, 0x8c42000c, 0x104000d7,
+0x8fbf0020, 0xe000d84, 0x0, 0x3c038000,
+0x34630100, 0x8c620000, 0x8f850020, 0x94670008,
+0x9466000c, 0xaca20000, 0x8c640004, 0x8f820024,
+0x63400, 0xaca40004, 0x9448001e, 0x8c620018,
+0x73c00, 0xe83825, 0xaca20008, 0x8c62001c,
+0x24040001, 0xaca2000c, 0x9062000a, 0xc23025,
+0xaca60010, 0xaca00014, 0xaca00018, 0xaca7001c,
+0xa00051d, 0x8fbf0020, 0x8f820024, 0x8c42000c,
+0x104000b6, 0x8fbf0020, 0xe000d84, 0x0,
+0x8f820024, 0x96240008, 0x9625000c, 0x9443001e,
+0x42202, 0x9626000e, 0x8f820020, 0x42600,
0x832025, 0x52c00, 0x3c030080, 0xa62825,
0x832025, 0xac400000, 0xac400004, 0xac400008,
0xac40000c, 0xac450010, 0xac400014, 0xac400018,
-0xac44001c, 0xa00050b, 0x24040001, 0x9622000c,
-0x14400017, 0x8f91ffac, 0x92220005, 0x30420010,
-0x14400013, 0x0, 0xe000315, 0x2002021,
-0x92220005, 0x2002021, 0x34420010, 0xe000320,
-0xa2220005, 0x92220000, 0x24030020, 0x304200ff,
-0x10430086, 0x2002021, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0xa00104c, 0x27bd0020,
-0xd, 0xa000549, 0x8fbf001c, 0x3c020800,
-0x8c420020, 0x1040007a, 0x8fbf001c, 0xe000d71,
-0x0, 0x8e220004, 0x8f83002c, 0x9624000c,
-0x3c050800, 0x94a54bfe, 0xac620000, 0x3c028008,
-0x9442002c, 0x42400, 0x3042ffff, 0x822025,
-0x3c02400e, 0xa22825, 0xac640004, 0xac600008,
-0xac60000c, 0xac600010, 0xac600014, 0xac600018,
-0xac65001c, 0xa00050b, 0x24040001, 0xe000315,
-0x2002021, 0x8f92ffb0, 0x2002021, 0xe000320,
-0xa640000c, 0x2002021, 0xe000325, 0x24050001,
-0x3c020800, 0x8c420020, 0x10400055, 0x8fbf001c,
-0xe000d71, 0x0, 0x9622000c, 0x8f83002c,
-0x8f84ffac, 0x21400, 0xac700000, 0xac620004,
-0xac600008, 0x8c820038, 0x3c050800, 0x94a54bfe,
-0xac62000c, 0x8c86003c, 0x3c02401f, 0xa22825,
-0xac660010, 0x8e420004, 0x24040001, 0xac620014,
-0xac600018, 0xac65001c, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0xa000d98, 0x27bd0020,
-0x8f82ffac, 0x24030020, 0x90420000, 0x304200ff,
-0x10430033, 0x8fbf001c, 0xe000f37, 0x0,
-0x1040002f, 0x8fbf001c, 0x3c038000, 0x8c6201f8,
-0x440fffe, 0x24020002, 0xac7001c0, 0xa06201c4,
-0x3c021000, 0xac6201f8, 0xa000549, 0x8fbf001c,
-0x2002021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0xa000e80, 0x27bd0020, 0x9625000c,
-0x2002021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0xa000ea5, 0x27bd0020, 0x2002021,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa000ed0,
-0x27bd0020, 0x9225000d, 0x2002021, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0xa000f21, 0x27bd0020,
-0x2002021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0xa000ef8, 0x27bd0020, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0020, 0x3c038000, 0x8c620278, 0x440fffe,
-0x24020002, 0xac640240, 0xa0620244, 0x3c021000,
-0x3e00008, 0xac620278, 0x411c0, 0x3e00008,
-0x24420240, 0xa3800018, 0x3e00008, 0xa3800019,
-0x3c038000, 0x8c620278, 0x440fffe, 0x8f82001c,
-0xac620240, 0x24020002, 0xa0620244, 0x3c021000,
-0x3e00008, 0xac620278, 0x3e00008, 0x0,
-0x90830030, 0x24020005, 0x804021, 0x3063003f,
-0x4821, 0x14620005, 0x5021, 0x9082004c,
-0x9483004e, 0x304900ff, 0x306affff, 0xad00000c,
-0xad000010, 0xad000024, 0x95020014, 0x8d05001c,
-0x8d040018, 0x3042ffff, 0x491023, 0x21100,
-0x237c3, 0x403821, 0x862023, 0xa2102b,
-0x822023, 0xa72823, 0xad05001c, 0xad040018,
-0xa5090014, 0xa5090020, 0xa50a0016, 0x3e00008,
-0xa50a0022, 0x3e00008, 0x0, 0x27bdffd8,
-0xafb20018, 0x3c128008, 0xafb40020, 0xafb3001c,
-0xafb10014, 0xafbf0024, 0xafb00010, 0x36510100,
-0x9222000c, 0x3c140800, 0x929400f7, 0x304300ff,
-0x24020001, 0x10620031, 0x809821, 0x24020002,
-0x14620034, 0x36500080, 0xe001242, 0x0,
-0x9204004c, 0xe000557, 0x3084007f, 0x2621021,
-0x2403ff80, 0x431824, 0x3c048000, 0xac830094,
-0x92450008, 0x9204004c, 0x3042007f, 0x3c038006,
-0x14850007, 0x438021, 0x2402ffff, 0xa2220011,
-0x2402ffff, 0xa6220012, 0xa0005ba, 0x2402ffff,
-0x96020020, 0xa2220011, 0x96020022, 0xa6220012,
-0x8e020024, 0x3c048008, 0xae220014, 0x34850080,
-0x90a2004c, 0x34830100, 0xa0620010, 0x8ca2003c,
-0xac620018, 0x8c820068, 0xac6200e4, 0x8c820064,
-0xac6200e0, 0x8c82006c, 0xac6200e8, 0x24020001,
-0xa0a20068, 0xa0005d6, 0x3c048008, 0xe00125b,
-0x0, 0x36420080, 0xa0400068, 0xa0005d6,
-0x3c048008, 0xa2000068, 0xa2000069, 0xa000612,
-0x3c028008, 0x34830080, 0x8c620038, 0x34850100,
-0xac62006c, 0x24020001, 0xa0620069, 0x90a200c5,
-0x90830008, 0x305100ff, 0x3072007f, 0x1232001b,
-0x3c088008, 0xe000557, 0x2202021, 0x2621021,
-0x2403ff80, 0x431824, 0x3c048000, 0xac830094,
-0x3042007f, 0x3c038006, 0x438021, 0x8e02000c,
-0x1040000d, 0x2002021, 0xe000569, 0x0,
-0x26220001, 0x305100ff, 0x9203003c, 0x2341026,
-0x2102b, 0x21023, 0x3063007f, 0x2228824,
-0xa0005e0, 0xa203003c, 0x3c088008, 0x35040100,
-0x8c8200d0, 0x35070080, 0xace2003c, 0x8c8200d0,
-0xad020000, 0x90e5004c, 0x908600c5, 0x90e3004c,
-0x908400c5, 0x2402ff80, 0xa22824, 0x3063007f,
-0x308400ff, 0xa62825, 0x64182a, 0x10600002,
-0x30a500ff, 0x38a50080, 0xa0e5004c, 0xa1050009,
-0x3c028008, 0x9043000e, 0x34440080, 0x3c058000,
-0xa043000a, 0x8c830018, 0x3c027fff, 0x3442ffff,
-0x621824, 0xac830018, 0x8ca201f8, 0x440fffe,
-0x0, 0xacb301c0, 0x8fbf0024, 0x8fb40020,
+0xac44001c, 0xa00051c, 0x24040001, 0x9622000c,
+0x14400018, 0x0, 0x92420005, 0x30420010,
+0x14400014, 0x0, 0xe000332, 0x2002021,
+0x92420005, 0x2002021, 0x34420010, 0xe00033d,
+0xa2420005, 0x92420000, 0x24030020, 0x304200ff,
+0x10430089, 0x2002021, 0x8fbf0020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa001075,
+0x27bd0028, 0xd, 0xa00055e, 0x8fbf0020,
+0x8c42000c, 0x1040007d, 0x8fbf0020, 0xe000d84,
+0x0, 0x8e220004, 0x8f840020, 0x9623000c,
+0xac820000, 0x3c028008, 0x9445002c, 0x8f820024,
+0x31c00, 0x30a5ffff, 0x9446001e, 0x3c02400e,
+0x651825, 0xc23025, 0xac830004, 0xac800008,
+0xac80000c, 0xac800010, 0xac800014, 0xac800018,
+0xac86001c, 0xa00051c, 0x24040001, 0xe000332,
+0x2002021, 0x8f93ff98, 0x2002021, 0xe00033d,
+0xa660000c, 0x2002021, 0xe000342, 0x24050001,
+0x8f820024, 0x8c42000c, 0x10400058, 0x8fbf0020,
+0xe000d84, 0x0, 0x9622000c, 0x8f830020,
+0x21400, 0xac700000, 0xac620004, 0xac600008,
+0x8e440038, 0x8f820024, 0xac64000c, 0x8e46003c,
+0x9445001e, 0x3c02401f, 0xac660010, 0xa22825,
+0x8e620004, 0x24040001, 0xac620014, 0xac600018,
+0xac65001c, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0xa000db8, 0x27bd0028,
+0x24020020, 0x1082003a, 0x8fb3001c, 0xe000f5e,
+0x0, 0x10400035, 0x8fbf0020, 0x3c048000,
+0x8c8201f8, 0x440fffe, 0x348201c0, 0x24030002,
+0xac500000, 0xa0430004, 0x3c021000, 0xac8201f8,
+0xa00055e, 0x8fbf0020, 0x2002021, 0x8fbf0020,
0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x24020002, 0xa0a201c4, 0x27bd0028, 0x3c021000,
-0x3e00008, 0xaca201f8, 0x90a20000, 0x27bdffe0,
-0xafb20018, 0x24420001, 0xa0a20000, 0x3c030800,
-0x8c6300f4, 0x304200ff, 0xafb10014, 0xafbf001c,
-0xafb00010, 0xa08821, 0x14430002, 0x809021,
-0xa0a00000, 0xe000557, 0x92240000, 0x8f90001c,
-0x2403ff80, 0x2021021, 0x431024, 0x3c038000,
-0xac620024, 0xe000557, 0x92240000, 0x2028021,
-0x3210007f, 0x3c02800a, 0x2028021, 0xae500000,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x94820006, 0x90830005,
-0x8c85000c, 0x8c860010, 0x8c870018, 0x8c88001c,
-0x8c840020, 0x3c010800, 0xa4224bd2, 0x3c010800,
-0xa0234bd1, 0x3c010800, 0xac254bd8, 0x3c010800,
-0xac264bdc, 0x3c010800, 0xac274be4, 0x3c010800,
-0xac284be8, 0x3c010800, 0xac244bec, 0x3e00008,
-0x0, 0x3c028008, 0x34420100, 0x8c440034,
-0x3c038000, 0x34650400, 0xac640038, 0x8c420038,
-0xaf850030, 0xac62003c, 0x3c020005, 0xac620030,
-0x0, 0x0, 0x3e00008, 0x0,
-0x3c020006, 0x308400ff, 0x822025, 0x3c028000,
-0xac440030, 0x0, 0x0, 0x0,
-0x3c038000, 0x8c620000, 0x30420010, 0x1040fffd,
-0x34620400, 0x3e00008, 0xaf820030, 0x94c20000,
-0x3c080800, 0x950800ca, 0x30e7ffff, 0x804821,
-0x1021021, 0xa4c20000, 0x94c20000, 0x3042ffff,
-0xe2102b, 0x54400001, 0xa4c70000, 0x94a20000,
-0x3c030800, 0x8c6300cc, 0x24420001, 0xa4a20000,
-0x94a20000, 0x3042ffff, 0x14430007, 0x3c028008,
-0x107102b, 0xa4a00000, 0x54400001, 0x1003821,
-0xa4c70000, 0x3c028008, 0x34460100, 0x8cc30028,
-0x94a20000, 0x3c048000, 0x3042fffe, 0x210c0,
-0x621021, 0xac82003c, 0x8c82003c, 0x621823,
-0x18600004, 0x0, 0x8cc20024, 0xa0006af,
-0x24420001, 0x8cc20024, 0xac820038, 0x3c020050,
-0x34420010, 0x3c038000, 0xac620030, 0x0,
-0x0, 0x0, 0x8c620000, 0x30420020,
-0x1040fffd, 0x0, 0x94a20000, 0x3c048000,
-0x30420001, 0x210c0, 0x441021, 0x8c430400,
-0xad230000, 0x8c420404, 0xad220004, 0x3c020020,
-0x3e00008, 0xac820030, 0x27bdffe0, 0xafb20018,
-0xafb10014, 0xafb00010, 0xafbf001c, 0x94c20000,
-0xc08021, 0x3c120800, 0x965200c6, 0x24420001,
-0xa6020000, 0x96030000, 0x94e20000, 0xe03021,
-0x14430005, 0x8fb10030, 0xe000684, 0x2403821,
-0xa0006e6, 0x0, 0x8c830004, 0x8c820004,
-0x24420040, 0x4610007, 0xac820004, 0x8c820004,
-0x4400004, 0x0, 0x8c820000, 0x24420001,
-0xac820000, 0x96020000, 0x3042ffff, 0x50520001,
-0xa6000000, 0x96220000, 0x24420001, 0xa6220000,
-0x3c028008, 0x34420100, 0x96230000, 0x9442003c,
-0x14430004, 0x8fbf001c, 0x24020001, 0xa6220000,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x27bdffe0, 0x3c028008,
-0xafbf0018, 0x34420100, 0x8c480034, 0x3c038000,
-0x34690400, 0xac680038, 0x8c420038, 0x30e700ff,
-0xaf890030, 0xac62003c, 0x3c020005, 0xac620030,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x8c82000c, 0x8c82000c,
-0x97830016, 0xad220000, 0x8c820010, 0x604021,
-0xad220004, 0x8c820018, 0xad220008, 0x8c82001c,
-0xad22000c, 0x8ca20014, 0xad220010, 0x8c820020,
-0xad220014, 0x90820005, 0x304200ff, 0x21200,
-0xad220018, 0x8ca20018, 0xad22001c, 0x8ca2000c,
-0xad220020, 0x8ca20010, 0xad220024, 0x8ca2001c,
-0xad220028, 0x8ca20020, 0xad22002c, 0x3402ffff,
-0xad260030, 0xad200034, 0x50620001, 0x3408ffff,
-0xad280038, 0x50e00011, 0x3c028008, 0x3c048008,
-0x34840100, 0x94820050, 0x3042ffff, 0xad22003c,
-0x94830044, 0x94850044, 0x24020001, 0x3063ffff,
-0x318c2, 0x641821, 0x90640054, 0x30a50007,
-0xa21004, 0xa000751, 0x441025, 0x34420100,
-0xad20003c, 0x94430044, 0x94440044, 0x3063ffff,
-0x318c2, 0x621821, 0x30840007, 0x90650054,
-0x24020001, 0x821004, 0x21027, 0x451024,
-0xa0620054, 0x0, 0x0, 0x0,
-0x3c020006, 0x34420040, 0x3c038000, 0xac620030,
+0xa000ea7, 0x27bd0028, 0x9625000c, 0x2002021,
+0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0xa000ecc, 0x27bd0028, 0x2002021,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0xa000ef7, 0x27bd0028, 0x9225000d, 0x2002021,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0xa000f48, 0x27bd0028, 0x2002021, 0x8fbf0020,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0xa000f1f, 0x27bd0028, 0x8fbf0020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0028, 0x3c058000, 0x8ca20278, 0x440fffe,
+0x34a20240, 0x24030002, 0xac440000, 0xa0430004,
+0x3c021000, 0x3e00008, 0xaca20278, 0xa3800018,
+0x3e00008, 0xa3800019, 0x3c038000, 0x8c620278,
+0x440fffe, 0x8f82001c, 0xac620240, 0x24020002,
+0xa0620244, 0x3c021000, 0x3e00008, 0xac620278,
+0x3c026000, 0x3e00008, 0x8c425404, 0x90830030,
+0x24020005, 0x804021, 0x3063003f, 0x4821,
+0x14620005, 0x5021, 0x9082004c, 0x9483004e,
+0x304900ff, 0x306affff, 0xad00000c, 0xad000010,
+0xad000024, 0x95020014, 0x8d05001c, 0x8d040018,
+0x3042ffff, 0x491023, 0x21100, 0x237c3,
+0x403821, 0x862023, 0xa2102b, 0x822023,
+0xa72823, 0xad05001c, 0xad040018, 0xa5090014,
+0xa5090020, 0xa50a0016, 0x3e00008, 0xa50a0022,
+0x3e00008, 0x0, 0x27bdffd8, 0xafb20018,
+0x3c128008, 0xafb40020, 0xafb3001c, 0xafb10014,
+0xafbf0024, 0xafb00010, 0x36510100, 0x3c026000,
+0x8c425404, 0x9222000c, 0x3c140800, 0x929400f7,
+0x304300ff, 0x24020001, 0x10620032, 0x809821,
+0x24020002, 0x14620035, 0x36500080, 0xe00143d,
+0x0, 0x9202004c, 0x2403ff80, 0x3c048000,
+0x3042007f, 0x211c0, 0x24420240, 0x2621021,
+0x431824, 0xac830094, 0x92450008, 0x9204004c,
+0x3042007f, 0x3c038006, 0x14850007, 0x438021,
+0x2402ffff, 0xa2220011, 0x2402ffff, 0xa6220012,
+0xa0005d2, 0x2402ffff, 0x96020020, 0xa2220011,
+0x96020022, 0xa6220012, 0x8e020024, 0x3c048008,
+0xae220014, 0x34850080, 0x90a2004c, 0x34830100,
+0xa0620010, 0x8ca2003c, 0xac620018, 0x8c820068,
+0xac6200f4, 0x8c820064, 0xac6200f0, 0x8c82006c,
+0xac6200f8, 0x24020001, 0xa0a20068, 0xa0005ee,
+0x3c048008, 0xe001456, 0x0, 0x36420080,
+0xa0400068, 0xa0005ee, 0x3c048008, 0xa2000068,
+0xa2000069, 0xa000629, 0x3c028008, 0x34830080,
+0x8c620038, 0x34850100, 0xac62006c, 0x24020001,
+0xa0620069, 0x90a200d5, 0x90830008, 0x305100ff,
+0x3072007f, 0x12320019, 0x1111c0, 0x24420240,
+0x2621021, 0x2403ff80, 0x431824, 0x3c048000,
+0xac830094, 0x3042007f, 0x3c038006, 0x438021,
+0x8e02000c, 0x1040000d, 0x2002021, 0xe00057e,
+0x0, 0x26220001, 0x305100ff, 0x9203003c,
+0x2341026, 0x2102b, 0x21023, 0x3063007f,
+0x2228824, 0xa0005f8, 0xa203003c, 0x3c088008,
+0x35040100, 0x8c8200e0, 0x35070080, 0xace2003c,
+0x8c8200e0, 0xad020000, 0x90e5004c, 0x908600d5,
+0x90e3004c, 0x908400d5, 0x2402ff80, 0xa22824,
+0x3063007f, 0x308400ff, 0xa62825, 0x64182a,
+0x10600002, 0x30a500ff, 0x38a50080, 0xa0e5004c,
+0xa1050009, 0x3c028008, 0x9043000e, 0x34440080,
+0x3c058000, 0xa043000a, 0x8c830018, 0x3c027fff,
+0x3442ffff, 0x621824, 0xac830018, 0x8ca201f8,
+0x440fffe, 0x0, 0xacb301c0, 0x8fbf0024,
+0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x24020002, 0xa0a201c4, 0x27bd0028,
+0x3c021000, 0x3e00008, 0xaca201f8, 0x90a20000,
+0x24420001, 0xa0a20000, 0x3c030800, 0x8c6300f4,
+0x304200ff, 0x14430002, 0x803021, 0xa0a00000,
+0x90a20000, 0x8f84001c, 0x211c0, 0x24420240,
+0x24830040, 0x822021, 0x2402ff80, 0x822024,
+0x3063007f, 0x3c02800a, 0x621821, 0x3c028000,
+0xac440024, 0x3e00008, 0xacc30000, 0x94820006,
+0x90830005, 0x8c85000c, 0x8c860010, 0x8c870018,
+0x8c88001c, 0x8c840020, 0x3c010800, 0xa42256c6,
+0x3c010800, 0xa02356c5, 0x3c010800, 0xac2556cc,
+0x3c010800, 0xac2656d0, 0x3c010800, 0xac2756d8,
+0x3c010800, 0xac2856dc, 0x3c010800, 0xac2456e0,
+0x3e00008, 0x0, 0x3c028008, 0x34420100,
+0x8c440034, 0x3c038000, 0x34650400, 0xac640038,
+0x8c420038, 0xaf850028, 0xac62003c, 0x3c020005,
+0xac620030, 0x0, 0x0, 0x3e00008,
+0x0, 0x3c020006, 0x308400ff, 0x822025,
+0x3c028000, 0xac440030, 0x0, 0x0,
+0x0, 0x3c038000, 0x8c620000, 0x30420010,
+0x1040fffd, 0x34620400, 0x3e00008, 0xaf820028,
+0x94c20000, 0x3c080800, 0x950800ca, 0x30e7ffff,
+0x804821, 0x1021021, 0xa4c20000, 0x94c20000,
+0x3042ffff, 0xe2102b, 0x54400001, 0xa4c70000,
+0x94a20000, 0x3c030800, 0x8c6300cc, 0x24420001,
+0xa4a20000, 0x94a20000, 0x3042ffff, 0x14430007,
+0x3c028008, 0x107102b, 0xa4a00000, 0x54400001,
+0x1003821, 0xa4c70000, 0x3c028008, 0x34460100,
+0x8cc30028, 0x94a20000, 0x3c048000, 0x3042fffe,
+0x210c0, 0x621021, 0xac82003c, 0x8c82003c,
+0x621823, 0x18600004, 0x0, 0x8cc20024,
+0xa0006ba, 0x24420001, 0x8cc20024, 0xac820038,
+0x3c020050, 0x34420010, 0x3c038000, 0xac620030,
0x0, 0x0, 0x0, 0x8c620000,
-0x30420010, 0x1040fffd, 0x3c068008, 0x34c20150,
-0x34630400, 0x34c7014a, 0x34c40134, 0x34c50140,
-0x34c60144, 0xafa20010, 0xe0006c7, 0xaf830030,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f830014,
-0x3c050800, 0x8ca500e8, 0x8f82001c, 0x30633fff,
-0x31980, 0x451021, 0x431021, 0x2403ff80,
-0x431824, 0x3c058000, 0xaca30028, 0x3042007f,
-0x3c03800c, 0x433021, 0x90c2000d, 0x3821,
-0x34420010, 0xa0c2000d, 0x8f890014, 0x3c028008,
-0x34420100, 0x94430044, 0x91382, 0x30480003,
-0x24020001, 0xa4c3000e, 0x1102000b, 0x29020002,
-0x10400005, 0x24020002, 0x1100000c, 0x24030001,
-0xa000798, 0x1821, 0x11020006, 0x0,
-0xa000798, 0x1821, 0x8cc2002c, 0xa000798,
-0x24430001, 0x8cc20014, 0x24430001, 0x8cc20018,
-0x43102b, 0x14400003, 0x3c038008, 0xa0007a2,
-0x24070001, 0x34630100, 0x9462004c, 0x24420001,
-0xa462004c, 0x91382, 0x30430003, 0x2c620002,
-0x10400009, 0x802821, 0x14600004, 0x0,
-0x94c20034, 0xa0007b2, 0x3046ffff, 0x8cc60038,
-0xa0007b2, 0x802821, 0x3021, 0x3c040800,
-0x24844bcc, 0xa0006fb, 0x0, 0x27bdff90,
-0xafb60068, 0xafb50064, 0xafb40060, 0xafb3005c,
-0xafb20058, 0xafb10054, 0xafbf006c, 0xafb00050,
-0x8c900000, 0x80b021, 0x3c020800, 0x8c4200e8,
-0x96040032, 0x8f83001c, 0x2414ff80, 0x30843fff,
-0x621821, 0x42180, 0x641821, 0x741024,
-0x3c138000, 0xa09021, 0x90a50000, 0xae620028,
-0x92040032, 0x3c02800c, 0x3063007f, 0x628821,
-0x308400c0, 0x24020040, 0x1482002d, 0xa821,
-0x8e350038, 0x8e220018, 0x14400002, 0x24020001,
-0xae220018, 0x9202003c, 0x30420020, 0x1440000f,
-0x0, 0xe000557, 0xa02021, 0x8f83001c,
+0x30420020, 0x1040fffd, 0x0, 0x94a20000,
+0x3c048000, 0x30420001, 0x210c0, 0x441021,
+0x8c430400, 0xad230000, 0x8c420404, 0xad220004,
+0x3c020020, 0x3e00008, 0xac820030, 0x27bdffe0,
+0xafb20018, 0xafb10014, 0xafb00010, 0xafbf001c,
+0x94c20000, 0xc08021, 0x3c120800, 0x965200c6,
+0x24420001, 0xa6020000, 0x96030000, 0x94e20000,
+0xe03021, 0x14430005, 0x8fb10030, 0xe00068f,
+0x2403821, 0xa0006f1, 0x0, 0x8c830004,
+0x8c820004, 0x24420040, 0x4610007, 0xac820004,
+0x8c820004, 0x4400004, 0x0, 0x8c820000,
+0x24420001, 0xac820000, 0x96020000, 0x3042ffff,
+0x50520001, 0xa6000000, 0x96220000, 0x24420001,
+0xa6220000, 0x3c028008, 0x34420100, 0x96230000,
+0x9442003c, 0x14430004, 0x8fbf001c, 0x24020001,
+0xa6220000, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x27bdffe0,
+0x3c028008, 0xafbf0018, 0x34420100, 0x8c480034,
+0x3c038000, 0x34690400, 0xac680038, 0x8c420038,
+0x30e700ff, 0xaf890028, 0xac62003c, 0x3c020005,
+0xac620030, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x8c82000c,
+0x8c82000c, 0x97830016, 0xad220000, 0x8c820010,
+0x604021, 0xad220004, 0x8c820018, 0xad220008,
+0x8c82001c, 0xad22000c, 0x8ca20014, 0xad220010,
+0x8c820020, 0xad220014, 0x90820005, 0x304200ff,
+0x21200, 0xad220018, 0x8ca20018, 0xad22001c,
+0x8ca2000c, 0xad220020, 0x8ca20010, 0xad220024,
+0x8ca2001c, 0xad220028, 0x8ca20020, 0xad22002c,
+0x3402ffff, 0xad260030, 0xad200034, 0x50620001,
+0x3408ffff, 0xad280038, 0x50e00011, 0x3c028008,
+0x3c048008, 0x34840100, 0x94820050, 0x3042ffff,
+0xad22003c, 0x94830044, 0x94850044, 0x24020001,
+0x3063ffff, 0x318c2, 0x641821, 0x90640064,
+0x30a50007, 0xa21004, 0xa00075c, 0x441025,
+0x34420100, 0xad20003c, 0x94430044, 0x94440044,
+0x3063ffff, 0x318c2, 0x621821, 0x30840007,
+0x90650064, 0x24020001, 0x821004, 0x21027,
+0x451024, 0xa0620064, 0x0, 0x0,
+0x0, 0x3c020006, 0x34420040, 0x3c038000,
+0xac620030, 0x0, 0x0, 0x0,
+0x8c620000, 0x30420010, 0x1040fffd, 0x3c068008,
+0x34c20150, 0x34630400, 0x34c7014a, 0x34c40134,
+0x34c50140, 0x34c60144, 0xafa20010, 0xe0006d2,
+0xaf830028, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x8f830014, 0x3c060800, 0x8cc600e8, 0x8f82001c,
+0x30633fff, 0x31980, 0x461021, 0x431021,
+0x2403ff80, 0x431824, 0x3c068000, 0xacc30028,
+0x3042007f, 0x3c03800c, 0x433021, 0x90c2000d,
+0x30a500ff, 0x3821, 0x34420010, 0xa0c2000d,
+0x8f890014, 0x3c028008, 0x34420100, 0x94430044,
+0x91382, 0x30480003, 0x24020001, 0xa4c3000e,
+0x1102000b, 0x29020002, 0x10400005, 0x24020002,
+0x1100000c, 0x24030001, 0xa0007a4, 0x1821,
+0x11020006, 0x0, 0xa0007a4, 0x1821,
+0x8cc2002c, 0xa0007a4, 0x24430001, 0x8cc20014,
+0x24430001, 0x8cc20018, 0x43102b, 0x5040000a,
+0x24070001, 0x24020027, 0x14a20003, 0x3c038008,
+0xa0007b1, 0x24070001, 0x34630100, 0x9462004c,
+0x24420001, 0xa462004c, 0x91382, 0x30430003,
+0x2c620002, 0x10400009, 0x802821, 0x14600004,
+0x0, 0x94c20034, 0xa0007c1, 0x3046ffff,
+0x8cc60038, 0xa0007c1, 0x802821, 0x3021,
+0x3c040800, 0x248456c0, 0xa000706, 0x0,
+0x27bdff90, 0xafb60068, 0xafb50064, 0xafb40060,
+0xafb3005c, 0xafb20058, 0xafb10054, 0xafbf006c,
+0xafb00050, 0x8c900000, 0x80b021, 0x3c020800,
+0x8c4200e8, 0x96040032, 0x8f83001c, 0x2414ff80,
+0x30843fff, 0x621821, 0x42180, 0x641821,
+0x741024, 0x3c138000, 0xa09021, 0x90a50000,
+0xae620028, 0x92040032, 0x3c02800c, 0x3063007f,
+0x628821, 0x308400c0, 0x24020040, 0x14820032,
+0xa821, 0x8e350038, 0x8e220018, 0x14400002,
+0x24020001, 0xae220018, 0x9202003c, 0x30420020,
+0x1440000e, 0x8f83001c, 0x511c0, 0x24420240,
0x621821, 0x30640078, 0x3c020080, 0x822025,
0x741824, 0xae630800, 0xae640810, 0x8e220018,
0x8e030008, 0x431021, 0xae220018, 0x8e22002c,
-0x8e230018, 0x24420001, 0x62182b, 0x1060003d,
+0x8e230018, 0x24420001, 0x62182b, 0x10600043,
0x0, 0x92420000, 0x24420001, 0xa2420000,
0x3c030800, 0x8c6300f4, 0x304200ff, 0x50430001,
-0xa2400000, 0xe000557, 0x92440000, 0x8f90001c,
-0x2021021, 0x541024, 0xa0008b8, 0xae620024,
-0x92030032, 0x2402ffc0, 0x431024, 0x304200ff,
-0x14400005, 0x24020001, 0xae220018, 0x96220034,
-0xa00082e, 0x3055ffff, 0x8e220014, 0x24420001,
-0xae220018, 0x92020030, 0x21600, 0x21603,
-0x441001c, 0x0, 0x96020032, 0x27a40010,
-0x802821, 0xa7a20016, 0x96020032, 0x3021,
-0x24070001, 0x3042ffff, 0xaf820014, 0xe0006fb,
-0xafa0001c, 0x96020032, 0x8f83001c, 0x3c040800,
-0x8c8400e8, 0x30423fff, 0x21180, 0x641821,
-0x621821, 0x741024, 0xae62002c, 0x3063007f,
-0x3c02800e, 0x621821, 0x9062000d, 0x3042007f,
-0xa062000d, 0x9222000d, 0x30420010, 0x50400078,
-0x92420000, 0x3c028008, 0x34440100, 0x9482004c,
-0x8ec30000, 0x3c130800, 0x967300c6, 0x2442ffff,
-0xa482004c, 0x94620032, 0x9623000e, 0x3054ffff,
-0x3070ffff, 0x3c030800, 0x8c6300d0, 0x701807,
-0xa7a30038, 0x9482003e, 0x3063ffff, 0x3042ffff,
-0x14620007, 0x0, 0x8c820030, 0x3c038000,
-0x24420030, 0xac62003c, 0xa000856, 0x8c82002c,
-0x94820040, 0x3042ffff, 0x54620009, 0x27a40040,
-0x8c820038, 0x3c038000, 0x24420030, 0xac62003c,
-0x8c820034, 0xac620038, 0xa000865, 0x3c038000,
-0x27a50038, 0x27a60048, 0x2603821, 0xe000684,
-0xa7a00048, 0x8fa30040, 0x3c028000, 0x24630030,
-0xac430038, 0x8fa30044, 0xac43003c, 0x3c038000,
-0x3c020005, 0xac620030, 0x3c028008, 0x34440100,
-0x94820042, 0x34630400, 0x3042ffff, 0x202102b,
-0x14400007, 0xaf830030, 0x9482004e, 0x94830042,
-0x2021021, 0x431023, 0xa00087b, 0x3043ffff,
-0x9483004e, 0x94820042, 0x2631821, 0x501023,
-0x621823, 0x3063ffff, 0x3c028008, 0x34440100,
-0x9482003c, 0x3042ffff, 0x14430003, 0x0,
-0xa00088b, 0x24030001, 0x9482003c, 0x3042ffff,
-0x62102b, 0x14400005, 0x8f820030, 0x9482003c,
-0x621023, 0x3043ffff, 0x8f820030, 0xac550000,
-0xac400004, 0xac540008, 0xac43000c, 0x3c020006,
-0x34420010, 0x3c038000, 0xac620030, 0x0,
-0x0, 0x0, 0x8c620000, 0x30420010,
-0x1040fffd, 0x3c048008, 0x34840100, 0x1018c2,
-0x641821, 0x90650054, 0x32020007, 0x24060001,
-0x461004, 0x451025, 0xa0620054, 0x94830042,
-0x9622000e, 0x50430001, 0xa3860018, 0x92420000,
-0x24420001, 0xa2420000, 0x3c030800, 0x8c6300f4,
-0x304200ff, 0x50430001, 0xa2400000, 0xe000557,
-0x92440000, 0x8f90001c, 0x2403ff80, 0x2021021,
-0x431024, 0x3c038000, 0xac620024, 0xe000557,
-0x92440000, 0x2028021, 0x3210007f, 0x3c02800a,
-0x2028021, 0xaed00000, 0x8fbf006c, 0x8fb60068,
-0x8fb50064, 0x8fb40060, 0x8fb3005c, 0x8fb20058,
-0x8fb10054, 0x8fb00050, 0x3e00008, 0x27bd0070,
-0x27bdffd8, 0xafb3001c, 0xafb20018, 0xafb10014,
-0xafb00010, 0xafbf0020, 0x809821, 0xe08021,
-0x30b1ffff, 0xe000d71, 0x30d200ff, 0x0,
-0x0, 0x0, 0x8f82002c, 0xac510000,
-0xac520004, 0xac530008, 0xac40000c, 0xac400010,
-0xac400014, 0xac400018, 0x3c030800, 0x94634bfe,
-0x2038025, 0xac50001c, 0x0, 0x0,
-0x0, 0x24040001, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa000d98,
-0x27bd0028, 0x30a5ffff, 0x30c600ff, 0x24030c80,
-0x3c028000, 0xac430024, 0x0, 0x0,
-0x0, 0x0, 0x0, 0xa0008c9,
-0x0, 0x3c028008, 0x34430100, 0x9462000e,
+0xa2400000, 0x92420000, 0x8f84001c, 0x211c0,
+0x24420240, 0x24830040, 0x3063007f, 0x822021,
+0x3c02800a, 0x942024, 0x621821, 0xae640024,
+0xa0008d2, 0xaec30000, 0x92030032, 0x2402ffc0,
+0x431024, 0x304200ff, 0x14400005, 0x24020001,
+0xae220018, 0x96220034, 0xa000842, 0x3055ffff,
+0x8e220014, 0x24420001, 0xae220018, 0x92020030,
+0x21600, 0x21603, 0x441001c, 0x0,
+0x96020032, 0x27a40010, 0x802821, 0xa7a20016,
+0x96020032, 0x3021, 0x24070001, 0x3042ffff,
+0xaf820014, 0xe000706, 0xafa0001c, 0x96020032,
+0x8f83001c, 0x3c040800, 0x8c8400e8, 0x30423fff,
+0x21180, 0x641821, 0x621821, 0x741024,
+0xae62002c, 0x3063007f, 0x3c02800e, 0x621821,
+0x9062000d, 0x3042007f, 0xa062000d, 0x9222000d,
+0x30420010, 0x50400078, 0x92420000, 0x3c028008,
+0x34440100, 0x9482004c, 0x8ec30000, 0x3c130800,
+0x967300c6, 0x2442ffff, 0xa482004c, 0x94620032,
+0x9623000e, 0x3054ffff, 0x3070ffff, 0x3c030800,
+0x8c6300d0, 0x701807, 0xa7a30038, 0x9482003e,
+0x3063ffff, 0x3042ffff, 0x14620007, 0x0,
+0x8c820030, 0x3c038000, 0x24420030, 0xac62003c,
+0xa00086a, 0x8c82002c, 0x94820040, 0x3042ffff,
+0x54620009, 0x27a40040, 0x8c820038, 0x3c038000,
+0x24420030, 0xac62003c, 0x8c820034, 0xac620038,
+0xa000879, 0x3c038000, 0x27a50038, 0x27a60048,
+0x2603821, 0xe00068f, 0xa7a00048, 0x8fa30040,
+0x3c028000, 0x24630030, 0xac430038, 0x8fa30044,
+0xac43003c, 0x3c038000, 0x3c020005, 0xac620030,
+0x3c028008, 0x34440100, 0x94820042, 0x34630400,
+0x3042ffff, 0x202102b, 0x14400007, 0xaf830028,
+0x9482004e, 0x94830042, 0x2021021, 0x431023,
+0xa00088f, 0x3043ffff, 0x9483004e, 0x94820042,
+0x2631821, 0x501023, 0x621823, 0x3063ffff,
+0x3c028008, 0x34440100, 0x9482003c, 0x3042ffff,
+0x14430003, 0x0, 0xa00089f, 0x24030001,
+0x9482003c, 0x3042ffff, 0x62102b, 0x14400005,
+0x8f820028, 0x9482003c, 0x621023, 0x3043ffff,
+0x8f820028, 0xac550000, 0xac400004, 0xac540008,
+0xac43000c, 0x3c020006, 0x34420010, 0x3c038000,
+0xac620030, 0x0, 0x0, 0x0,
+0x8c620000, 0x30420010, 0x1040fffd, 0x3c048008,
+0x34840100, 0x1018c2, 0x641821, 0x90650064,
+0x32020007, 0x24060001, 0x461004, 0x451025,
+0xa0620064, 0x94830042, 0x9622000e, 0x50430001,
+0xa3860018, 0x92420000, 0x24420001, 0xa2420000,
+0x3c030800, 0x8c6300f4, 0x304200ff, 0x50430001,
+0xa2400000, 0x92420000, 0x8f84001c, 0x211c0,
+0x24420240, 0x24830040, 0x822021, 0x2402ff80,
+0x822024, 0x3063007f, 0x3c02800a, 0x621821,
+0x3c028000, 0xac440024, 0xaec30000, 0x8fbf006c,
+0x8fb60068, 0x8fb50064, 0x8fb40060, 0x8fb3005c,
+0x8fb20058, 0x8fb10054, 0x8fb00050, 0x3e00008,
+0x27bd0070, 0x27bdffd8, 0xafb3001c, 0xafb20018,
+0xafb10014, 0xafb00010, 0xafbf0020, 0x809821,
+0xe08021, 0x30b1ffff, 0xe000d84, 0x30d200ff,
+0x0, 0x0, 0x0, 0x8f820020,
+0x8f830024, 0xac510000, 0xac520004, 0xac530008,
+0xac40000c, 0xac400010, 0xac400014, 0xac400018,
+0x9463001e, 0x2038025, 0xac50001c, 0x0,
+0x0, 0x0, 0x24040001, 0x8fbf0020,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0xa000db8, 0x27bd0028, 0x30a5ffff, 0xa0008dc,
+0x30c600ff, 0x3c028008, 0x34430100, 0x9462000e,
0x3c080800, 0x950800c6, 0x3046ffff, 0x14c00004,
-0x3402ffff, 0x946500da, 0xa00091f, 0x8f84001c,
+0x3402ffff, 0x946500ea, 0xa000929, 0x8f84001c,
0x10c20027, 0x0, 0x9462004e, 0x9464003c,
0x3045ffff, 0xa61023, 0xa6182b, 0x3087ffff,
0x10600004, 0x3044ffff, 0xc51023, 0xe21023,
0x3044ffff, 0x88102b, 0x1040000e, 0xe81023,
0x3c028008, 0x34440100, 0x24030001, 0x34420080,
-0xa4430016, 0x2402ffff, 0xa482000e, 0x948500da,
-0x8f84001c, 0x3021, 0x30a5ffff, 0xa0008ee,
+0xa4430016, 0x2402ffff, 0xa482000e, 0x948500ea,
+0x8f84001c, 0x3021, 0x30a5ffff, 0xa000901,
0x3c076020, 0x44102a, 0x10400009, 0x3c028008,
0x34430080, 0x94620016, 0x30420001, 0x10400004,
0x3c028000, 0x9442007e, 0x24420014, 0xa4620016,
@@ -8733,534 +8613,556 @@ u32 bce_COM_b09FwText[(0x4ac8/4) + 1] = {
0xafbf001c, 0xafb00018, 0x34420100, 0x94430042,
0x9442004c, 0x10400019, 0x3068ffff, 0x93830018,
0x24020001, 0x14620029, 0x8fbf001c, 0x3c068008,
-0x34d00100, 0x810c2, 0x501021, 0x90420054,
+0x34d00100, 0x810c2, 0x501021, 0x90420064,
0x31030007, 0x34c70148, 0x304200ff, 0x621007,
0x30420001, 0x34c9014e, 0x34c4012c, 0x34c5013e,
-0x10400016, 0x34c60142, 0xe0006c7, 0xafa90010,
-0x96020042, 0xa00093c, 0x3048ffff, 0x3c028008,
+0x10400016, 0x34c60142, 0xe0006d2, 0xafa90010,
+0x96020042, 0xa000946, 0x3048ffff, 0x3c028008,
0x34440100, 0x94830044, 0x94820042, 0x1043000f,
0x8fbf001c, 0x94820044, 0xa4820042, 0x94820050,
0xa482004e, 0x8c820038, 0xac820030, 0x94820040,
0xa482003e, 0x9482004a, 0xa4820048, 0x8fbf001c,
-0x8fb00018, 0xa0008fa, 0x27bd0020, 0x8fb00018,
+0x8fb00018, 0xa000904, 0x27bd0020, 0x8fb00018,
0x3e00008, 0x27bd0020, 0x27bdffa0, 0xafb1004c,
0x3c118000, 0xafbf0058, 0xafb30054, 0xafb20050,
0xafb00048, 0x36260188, 0x90c20003, 0x3044007f,
0xa3a40010, 0x8e320180, 0x90c20000, 0x3043007f,
0x24020003, 0x1062003b, 0xaf92001c, 0x28620004,
0x10400006, 0x24020004, 0x24020002, 0x10620009,
-0x8fbf0058, 0xa000b03, 0x8fb30054, 0x1062004b,
-0x24020005, 0x1062014c, 0x8fbf0058, 0xa000b03,
+0x8fbf0058, 0xa000b0f, 0x8fb30054, 0x1062004d,
+0x24020005, 0x1062014e, 0x8fbf0058, 0xa000b0f,
0x8fb30054, 0x411c0, 0x2421021, 0x2404ff80,
0x24420240, 0x441024, 0x26430040, 0xae220024,
0x3063007f, 0x3c02800a, 0x621821, 0x9062003c,
0xafa3003c, 0x441025, 0xa062003c, 0x8fa3003c,
-0x9062003c, 0x30420040, 0x1040016a, 0x8fbf0058,
-0x3c108008, 0xa3800018, 0x36100100, 0x8e0200d0,
+0x9062003c, 0x30420040, 0x1040016c, 0x8fbf0058,
+0x3c108008, 0xa3800018, 0x36100100, 0x8e0200e0,
0x8c630034, 0x27a4003c, 0x27a50010, 0x431021,
-0xe0007b4, 0xae0200d0, 0x93a20010, 0x3c038000,
-0xa20200c5, 0x8c620278, 0x440fffe, 0x8f82001c,
+0xe0007c3, 0xae0200e0, 0x93a20010, 0x3c038000,
+0xa20200d5, 0x8c620278, 0x440fffe, 0x8f82001c,
0xac620240, 0x24020002, 0xa0620244, 0x3c021000,
-0xac620278, 0xe00092f, 0x0, 0xa000b02,
+0xac620278, 0xe000939, 0x0, 0xa000b0e,
0x8fbf0058, 0x3c058008, 0x90c30001, 0x90a2000b,
-0x1443014c, 0x8fbf0058, 0x34a40080, 0x8c820018,
-0x9082004c, 0x90a20008, 0x8c830018, 0x3c027fff,
-0x3442ffff, 0x621824, 0x3c020800, 0x8c4200b4,
-0xac830018, 0x3c038000, 0x24420001, 0x3c010800,
-0xac2200b4, 0x8c6201f8, 0x440fffe, 0x8f82001c,
-0xac6201c0, 0xa000aca, 0x24020002, 0x3c108008,
-0x90c30001, 0x9202000b, 0x14430132, 0x8fbf0058,
-0x36050110, 0x27a40018, 0xe000e20, 0x24060003,
-0x27a40028, 0x360501e0, 0xe000e20, 0x24060003,
-0x8fa20028, 0x36030100, 0xae020064, 0x8fa2002c,
-0xae020068, 0x8fa20030, 0xae02006c, 0x93a40018,
-0x906300c5, 0x2402ff80, 0x821024, 0x431025,
-0x305000ff, 0x3084007f, 0x3202007f, 0x82102a,
-0x54400001, 0x3a100080, 0xe000557, 0x0,
-0x2421021, 0x2403ff80, 0x431024, 0xae220094,
-0x93a40018, 0x3c130800, 0x927300f7, 0xe000557,
-0x3084007f, 0x2421021, 0x3042007f, 0x3c038006,
-0x434021, 0x8fa3001c, 0x2402ffff, 0x10620034,
-0xafa80040, 0x93a20019, 0x95030014, 0x304400ff,
-0x3063ffff, 0x64182b, 0x10600010, 0x0,
-0x95040014, 0x8d07001c, 0x8d060018, 0x3084ffff,
-0x442023, 0x42100, 0xe43821, 0x1021,
-0xe4202b, 0xc23021, 0xc43021, 0xad07001c,
-0xad060018, 0xa000a23, 0x93a20019, 0x95040014,
-0x8d07001c, 0x8d060018, 0x3084ffff, 0x822023,
-0x42100, 0x1021, 0x801821, 0xc23023,
-0xe4202b, 0xc43023, 0xe33823, 0xad07001c,
-0xad060018, 0x93a20019, 0x8fa30040, 0xa4620014,
-0x97a2001a, 0xa4620016, 0x8fa2001c, 0xac620010,
-0x8fa2001c, 0xac62000c, 0x93a20019, 0xa4620020,
-0x97a2001a, 0xa4620022, 0x8fa2001c, 0xac620024,
-0x3c048008, 0x34830080, 0x8c620038, 0x8fa20020,
-0x2008821, 0xac62003c, 0x8fa20020, 0xac820000,
-0x93a20018, 0xa062004c, 0x93a20018, 0xa0820009,
-0xa0600068, 0x93a20018, 0x10510052, 0x93a40018,
-0x3230007f, 0xe000557, 0x2002021, 0x2421021,
-0x2407ff80, 0x3046007f, 0x3c038000, 0x471024,
-0xac620094, 0x3c028006, 0xc23021, 0x90c2003c,
-0xafa60040, 0x2021, 0x471025, 0xa0c2003c,
-0x8fa80040, 0x95020002, 0x95030014, 0x8d07001c,
-0x3042ffff, 0x3063ffff, 0x8d060018, 0x431023,
-0x21100, 0xe23821, 0xe2102b, 0xc43021,
-0xc23021, 0xad07001c, 0xad060018, 0x95020002,
-0xa5020014, 0xa5000016, 0x8d020008, 0xad020010,
-0x8d020008, 0xad02000c, 0x95020002, 0xa5020020,
-0xa5000022, 0x8d020008, 0xad020024, 0x9102003c,
-0x30420040, 0x1040001a, 0x26220001, 0xa3b00038,
-0x3c108008, 0xa3800018, 0x36100100, 0x8e0200d0,
-0x8d030034, 0x27a40040, 0x27a50038, 0x431021,
-0xe0007b4, 0xae0200d0, 0x93a20038, 0x3c038000,
-0xa20200c5, 0x8c620278, 0x440fffe, 0x8f82001c,
-0xac620240, 0x24020002, 0xa0620244, 0x3c021000,
-0xac620278, 0xe00092f, 0x0, 0x26220001,
-0x3043007f, 0x14730004, 0x402021, 0x2403ff80,
-0x2231024, 0x432026, 0x93a20018, 0xa000a3f,
-0x309100ff, 0x8fa3001c, 0x2402ffff, 0x1062000a,
-0x309000ff, 0x24820001, 0x24830001, 0x3042007f,
-0x14530005, 0x307000ff, 0x2403ff80, 0x831024,
-0x431026, 0x305000ff, 0x3c028008, 0x90420008,
-0x2008821, 0x305000ff, 0x12300019, 0x3222007f,
-0x211c0, 0x2421021, 0x24420240, 0x2403ff80,
-0x431824, 0x3c048000, 0xac830094, 0x3042007f,
-0x3c038006, 0x431021, 0x8c43000c, 0x402021,
-0x1060000b, 0xafa20040, 0xe000569, 0x0,
-0x26230001, 0x2405ff80, 0x3062007f, 0x14530002,
-0x2252024, 0x851826, 0xa000aa3, 0x307100ff,
-0x3c048008, 0x34840080, 0x8c830018, 0x3c027fff,
-0x3442ffff, 0x621824, 0xac830018, 0x3c038000,
-0x8c6201f8, 0x440fffe, 0x0, 0xac7201c0,
-0x24020002, 0xa06201c4, 0x3c021000, 0xac6201f8,
-0xa000b02, 0x8fbf0058, 0x3c048008, 0x90c30001,
-0x9082000b, 0x1443002f, 0x8fbf0058, 0x34900080,
-0x92020008, 0x30420040, 0x10400020, 0x0,
-0x92020008, 0x21600, 0x21603, 0x4410005,
-0x2402021, 0xe000ea5, 0x24050093, 0xa000b02,
-0x8fbf0058, 0x92020009, 0x24030018, 0x304200ff,
-0x1443000d, 0x2402021, 0x24050039, 0xe000e3d,
-0x3021, 0xe000315, 0x8f84001c, 0x8f82ffac,
-0x24030012, 0xa0430009, 0xe000320, 0x8f84001c,
-0xa000b02, 0x8fbf0058, 0x24050036, 0xe000e3d,
-0x3021, 0xa000b02, 0x8fbf0058, 0xe000315,
-0x2402021, 0x92020005, 0x8f84001c, 0x34420020,
-0xe000320, 0xa2020005, 0xe00104c, 0x8f84001c,
-0x8fbf0058, 0x8fb30054, 0x8fb20050, 0x8fb1004c,
-0x8fb00048, 0x24030c80, 0x3c028000, 0x27bd0060,
-0x3e00008, 0xac430024, 0x27bdffe8, 0x3c028008,
-0xafb00010, 0xafbf0014, 0x34450100, 0x3c108000,
-0x8e020140, 0x94a3000e, 0x3021, 0x402021,
-0xaf82001c, 0x3063ffff, 0x3402ffff, 0x10620006,
-0x3c076020, 0x2402ffff, 0xa4a2000e, 0x94a500da,
-0xe0008ee, 0x30a5ffff, 0x24020c80, 0xae020024,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x27bdffc0, 0x3c098000, 0x3c058008, 0xafb70034,
-0xafb20020, 0xafbf0038, 0xafb60030, 0xafb5002c,
-0xafb40028, 0xafb30024, 0xafb1001c, 0xafb00018,
-0x35320100, 0x34a80100, 0x8d270100, 0x8e420014,
-0x8d0300d4, 0xb821, 0xa3800018, 0x431023,
-0x18400055, 0xaf87001c, 0x8e420014, 0x2403ff80,
-0x24e40040, 0xad0200d4, 0x90a60008, 0x910500c5,
-0x3084007f, 0x30d3007f, 0x30a200ff, 0x211c0,
-0xe21021, 0x24420240, 0xa3a50010, 0x431024,
-0x8d1400d0, 0x8d1500d4, 0xad220024, 0x93a30010,
-0x3c02800a, 0x822021, 0xafa40014, 0x10730033,
-0xb021, 0x8fa30014, 0x27a40014, 0x27a50010,
-0x8c620034, 0x2828021, 0x2b01023, 0x440002b,
-0x2411ff80, 0x9062003c, 0x2221024, 0x304200ff,
-0x1440001b, 0x200a021, 0x9062003c, 0x34420040,
-0xa062003c, 0x93a20010, 0x24420001, 0x304300ff,
-0xa3a20010, 0x3c020800, 0x8c4200f4, 0x50620001,
-0xa3a00010, 0xe000557, 0x93a40010, 0x8f90001c,
-0x3c038000, 0x2021021, 0x511024, 0xac620024,
-0xe000557, 0x93a40010, 0x2028021, 0x3210007f,
-0x3c02800a, 0x2028021, 0xa000b81, 0xafb00014,
-0xe0007b4, 0x0, 0x3c028008, 0x34420100,
-0xac5000d0, 0x93a30010, 0x24160001, 0xa04300c5,
-0x93a20010, 0x1453ffd0, 0x8fa30014, 0x24020001,
-0x16c20009, 0x3c038000, 0x8c620278, 0x440fffe,
+0x1443014e, 0x8fbf0058, 0x34a40080, 0x8c820018,
+0x9082004c, 0x90a20008, 0x3c026000, 0x8c425404,
+0x8c830018, 0x3c027fff, 0x3442ffff, 0x621824,
+0x3c020800, 0x8c4200b4, 0xac830018, 0x3c038000,
+0x24420001, 0x3c010800, 0xac2200b4, 0x8c6201f8,
+0x440fffe, 0x8f82001c, 0xac6201c0, 0xa000ad6,
+0x24020002, 0x3c108008, 0x90c30001, 0x9202000b,
+0x14430132, 0x8fbf0058, 0x27a40018, 0x36050110,
+0x24060003, 0x3c026000, 0x8c425404, 0xe000e47,
+0x0, 0x27a40028, 0x360501f0, 0xe000e47,
+0x24060003, 0x8fa20028, 0x36030100, 0xae020064,
+0x8fa2002c, 0xae020068, 0x8fa20030, 0xae02006c,
+0x93a40018, 0x906300d5, 0x2402ff80, 0x821024,
+0x431025, 0x304900ff, 0x3084007f, 0x3122007f,
+0x82102a, 0x54400001, 0x39290080, 0x411c0,
+0x24420240, 0x2403ff80, 0x2421021, 0x431024,
+0xae220094, 0x26420040, 0x3042007f, 0x3c038006,
+0x434021, 0x8fa3001c, 0x2402ffff, 0xafa80040,
+0x3c130800, 0x927300f7, 0x10620033, 0x93a20019,
+0x95030014, 0x304400ff, 0x3063ffff, 0x64182b,
+0x10600010, 0x0, 0x95040014, 0x8d07001c,
+0x8d060018, 0x3084ffff, 0x442023, 0x42100,
+0xe43821, 0x1021, 0xe4202b, 0xc23021,
+0xc43021, 0xad07001c, 0xad060018, 0xa000a2f,
+0x93a20019, 0x95040014, 0x8d07001c, 0x8d060018,
+0x3084ffff, 0x822023, 0x42100, 0x1021,
+0x801821, 0xc23023, 0xe4202b, 0xc43023,
+0xe33823, 0xad07001c, 0xad060018, 0x93a20019,
+0x8fa30040, 0xa4620014, 0x97a2001a, 0xa4620016,
+0x8fa2001c, 0xac620010, 0x8fa2001c, 0xac62000c,
+0x93a20019, 0xa4620020, 0x97a2001a, 0xa4620022,
+0x8fa2001c, 0xac620024, 0x3c048008, 0x34830080,
+0x8c620038, 0x8fa20020, 0x1208821, 0xac62003c,
+0x8fa20020, 0xac820000, 0x93a20018, 0xa062004c,
+0x93a20018, 0xa0820009, 0xa0600068, 0x93a20018,
+0x10510051, 0x2407ff80, 0x3229007f, 0x911c0,
+0x24420240, 0x2421021, 0x3046007f, 0x3c038000,
+0x471024, 0xac620094, 0x3c028006, 0xc23021,
+0x90c2003c, 0xafa60040, 0x2021, 0x471025,
+0xa0c2003c, 0x8fa80040, 0x95020002, 0x95030014,
+0x8d07001c, 0x3042ffff, 0x3063ffff, 0x8d060018,
+0x431023, 0x21100, 0xe23821, 0xe2102b,
+0xc43021, 0xc23021, 0xad07001c, 0xad060018,
+0x95020002, 0xa5020014, 0xa5000016, 0x8d020008,
+0xad020010, 0x8d020008, 0xad02000c, 0x95020002,
+0xa5020020, 0xa5000022, 0x8d020008, 0xad020024,
+0x9102003c, 0x30420040, 0x1040001a, 0x26220001,
+0x3c108008, 0xa3a90038, 0xa3800018, 0x36100100,
+0x8e0200e0, 0x8d030034, 0x27a40040, 0x27a50038,
+0x431021, 0xe0007c3, 0xae0200e0, 0x93a20038,
+0x3c038000, 0xa20200d5, 0x8c620278, 0x440fffe,
0x8f82001c, 0xac620240, 0x24020002, 0xa0620244,
-0x3c021000, 0xac620278, 0x9242000b, 0x24030002,
-0x304200ff, 0x14430072, 0x0, 0x96420008,
-0x304300ff, 0x24020082, 0x14620040, 0x24020084,
-0x3c028000, 0x34490100, 0x8d22000c, 0x95230006,
-0x21602, 0x3063ffff, 0x3044003f, 0x24020027,
-0x1082000f, 0xaf830014, 0x28820028, 0x10400008,
-0x24020031, 0x24020021, 0x10820009, 0x24020025,
-0x10820007, 0x93820019, 0xa000bc0, 0x0,
-0x10820007, 0x93820019, 0xa000bc0, 0x0,
-0xe00076c, 0x1202021, 0xa000c40, 0x0,
+0x3c021000, 0xac620278, 0xe000939, 0x0,
+0x26220001, 0x3043007f, 0x14730004, 0x402021,
+0x2403ff80, 0x2231024, 0x432026, 0x93a20018,
+0xa000a4b, 0x309100ff, 0x93a40018, 0x8fa3001c,
+0x2402ffff, 0x1062000a, 0x308900ff, 0x24820001,
+0x24830001, 0x3042007f, 0x14530005, 0x306900ff,
+0x2403ff80, 0x831024, 0x431026, 0x304900ff,
+0x3c028008, 0x90420008, 0x1208821, 0x305000ff,
+0x12300019, 0x3222007f, 0x211c0, 0x2421021,
+0x24420240, 0x2403ff80, 0x431824, 0x3c048000,
+0xac830094, 0x3042007f, 0x3c038006, 0x431021,
+0x8c43000c, 0x402021, 0x1060000b, 0xafa20040,
+0xe00057e, 0x0, 0x26230001, 0x2405ff80,
+0x3062007f, 0x14530002, 0x2252024, 0x851826,
+0xa000aaf, 0x307100ff, 0x3c048008, 0x34840080,
+0x8c830018, 0x3c027fff, 0x3442ffff, 0x621824,
+0xac830018, 0x3c038000, 0x8c6201f8, 0x440fffe,
+0x0, 0xac7201c0, 0x24020002, 0xa06201c4,
+0x3c021000, 0xac6201f8, 0xa000b0e, 0x8fbf0058,
+0x3c048008, 0x90c30001, 0x9082000b, 0x1443002f,
+0x8fbf0058, 0x34900080, 0x92020008, 0x30420040,
+0x10400020, 0x0, 0x92020008, 0x21600,
+0x21603, 0x4410005, 0x2402021, 0xe000ecc,
+0x24050093, 0xa000b0e, 0x8fbf0058, 0x92020009,
+0x24030018, 0x304200ff, 0x1443000d, 0x2402021,
+0x24050039, 0xe000e64, 0x3021, 0xe000332,
+0x8f84001c, 0x8f82ff94, 0x24030012, 0xa0430009,
+0xe00033d, 0x8f84001c, 0xa000b0e, 0x8fbf0058,
+0x24050036, 0xe000e64, 0x3021, 0xa000b0e,
+0x8fbf0058, 0xe000332, 0x2402021, 0x92020005,
+0x8f84001c, 0x34420020, 0xe00033d, 0xa2020005,
+0xe001075, 0x8f84001c, 0x8fbf0058, 0x8fb30054,
+0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x3e00008,
+0x27bd0060, 0x3c028008, 0x34450100, 0x3c028000,
+0x8c420140, 0x94a3000e, 0x3021, 0x402021,
+0xaf82001c, 0x3063ffff, 0x3402ffff, 0x10620006,
+0x3c076020, 0x2402ffff, 0xa4a2000e, 0x94a500ea,
+0xa000901, 0x30a5ffff, 0x3e00008, 0x0,
+0x27bdffc8, 0x3c028000, 0x3c068008, 0xafb5002c,
+0xafb1001c, 0xafbf0030, 0xafb40028, 0xafb30024,
+0xafb20020, 0xafb00018, 0x34510100, 0x34c50100,
+0x8c430100, 0x8e220014, 0x8ca400e4, 0xa821,
+0xaf83001c, 0x441023, 0x18400052, 0xa3800018,
+0x8e220014, 0x5021, 0xaca200e4, 0x90c30008,
+0x90a200d5, 0x3073007f, 0xa3a20010, 0x8cb200e0,
+0x8cb400e4, 0x304200ff, 0x1053003b, 0x93a20010,
+0x8f83001c, 0x2407ff80, 0x211c0, 0x621021,
+0x24420240, 0x24630040, 0x471024, 0x3063007f,
+0x3c098000, 0x3c08800a, 0x681821, 0xad220024,
+0x8c620034, 0x27a40014, 0x27a50010, 0x2428021,
+0x2901023, 0x4400028, 0xafa30014, 0x9062003c,
+0xe21024, 0x304200ff, 0x14400019, 0x2009021,
+0x9062003c, 0x34420040, 0xa062003c, 0x8f86001c,
+0x93a30010, 0x24c20040, 0x3042007f, 0x482821,
+0x3c020800, 0x8c4200f4, 0x24630001, 0x306400ff,
+0x14820002, 0xa3a30010, 0xa3a00010, 0x93a20010,
+0xafa50014, 0x211c0, 0x24420240, 0xc21021,
+0x471024, 0xad220024, 0xa000b45, 0x93a20010,
+0xe0007c3, 0x0, 0x3c028008, 0x34420100,
+0xac5000e0, 0x93a30010, 0x240a0001, 0xa04300d5,
+0xa000b45, 0x93a20010, 0x24020001, 0x15420009,
0x3c038000, 0x8c620278, 0x440fffe, 0x8f82001c,
0xac620240, 0x24020002, 0xa0620244, 0x3c021000,
-0xac620278, 0xa000c40, 0x0, 0x95230006,
-0x91240005, 0x8d25000c, 0x8d260010, 0x8d270018,
-0x8d28001c, 0x8d290020, 0x24420001, 0x3c010800,
-0xa4234bd2, 0x3c010800, 0xa0244bd1, 0x3c010800,
-0xac254bd8, 0x3c010800, 0xac264bdc, 0x3c010800,
-0xac274be4, 0x3c010800, 0xac284be8, 0x3c010800,
-0xac294bec, 0xa000c40, 0xa3820019, 0x1462000a,
-0x24020081, 0x3c028008, 0x34420100, 0x944500da,
-0x92460005, 0x8f84001c, 0x30a5ffff, 0x30c600ff,
-0xa000c01, 0x3c076021, 0x1462005c, 0x0,
-0x9242000a, 0x304300ff, 0x30620020, 0x10400007,
-0x30620040, 0x3c028008, 0x34420100, 0x944500da,
-0x8f84001c, 0xa000bff, 0x24060040, 0x10400007,
-0x31600, 0x3c028008, 0x34420100, 0x944500da,
-0x8f84001c, 0xa000bff, 0x24060041, 0x21603,
-0x4410046, 0x3c028008, 0x34420100, 0x944500da,
-0x8f84001c, 0x24060042, 0x30a5ffff, 0x3c076019,
-0xe0008ee, 0x0, 0xa000c40, 0x0,
-0x9242000b, 0x24040016, 0x304200ff, 0x10440006,
-0x3c068000, 0x9242000b, 0x24030017, 0x304200ff,
-0x14430032, 0x0, 0x34c50100, 0x90a2000b,
-0x304200ff, 0x1444000b, 0x8021, 0x8ca20020,
-0x8ca40020, 0x2403ff80, 0x431024, 0x21140,
-0x3084007f, 0x441025, 0x3c032000, 0x431025,
-0xacc20830, 0x94a20008, 0x21400, 0x21403,
-0x4420001, 0x24100001, 0x94a20008, 0x30420080,
-0x5040001a, 0x200b821, 0x94a20008, 0x30422000,
-0x50400016, 0x200b821, 0x8ca30018, 0x3c021c2d,
-0x344219ed, 0x10620011, 0x200b821, 0x3c020800,
-0x8c4200d4, 0x10400005, 0x3c028008, 0x24030004,
-0x34420100, 0xa04300ec, 0x3c028008, 0x34420100,
-0x944500da, 0x8f84001c, 0x24060006, 0x30a5ffff,
-0xe0008ee, 0x3c076021, 0x200b821, 0xe00092f,
-0x0, 0x9242000a, 0x30420008, 0x10400004,
-0x3c028000, 0xe00121f, 0x0, 0x3c028000,
-0x24030c80, 0xac430024, 0x8fbf0038, 0x2e01021,
-0x8fb60030, 0x8fb70034, 0x8fb5002c, 0x8fb40028,
-0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0040, 0x2402ff80, 0x822024,
-0x3c029000, 0x34420007, 0x822025, 0x3c028000,
-0xac440020, 0x3c038000, 0x8c620020, 0x440fffe,
-0x0, 0x3e00008, 0x0, 0x3c038000,
-0x2402ff80, 0x822024, 0x34620007, 0x822025,
-0xac640020, 0x8c620020, 0x440fffe, 0x0,
-0x3e00008, 0x0, 0x3c028008, 0x24030005,
-0x34420100, 0xa04300ec, 0x3c028000, 0x8c420100,
-0x3c038000, 0xaf82001c, 0x8c620278, 0x440fffe,
-0x8f82001c, 0xac620240, 0x24020002, 0xa0620244,
+0xac620278, 0x9222000b, 0x24030002, 0x304200ff,
+0x14430072, 0x0, 0x96220008, 0x304300ff,
+0x24020082, 0x14620040, 0x24020084, 0x3c028000,
+0x34490100, 0x8d22000c, 0x95230006, 0x21602,
+0x3063ffff, 0x3045003f, 0x24020027, 0x10a2000f,
+0xaf830014, 0x28a20028, 0x10400008, 0x24020031,
+0x24020021, 0x10a20009, 0x24020025, 0x10a20007,
+0x93820019, 0xa000bbd, 0x0, 0x10a20007,
+0x93820019, 0xa000bbd, 0x0, 0xe000777,
+0x1202021, 0xa000c3d, 0x0, 0x3c038000,
+0x8c620278, 0x440fffe, 0x8f82001c, 0xac620240,
+0x24020002, 0xa0620244, 0x3c021000, 0xac620278,
+0xa000c3d, 0x0, 0x95230006, 0x91240005,
+0x8d25000c, 0x8d260010, 0x8d270018, 0x8d28001c,
+0x8d290020, 0x24420001, 0x3c010800, 0xa42356c6,
+0x3c010800, 0xa02456c5, 0x3c010800, 0xac2556cc,
+0x3c010800, 0xac2656d0, 0x3c010800, 0xac2756d8,
+0x3c010800, 0xac2856dc, 0x3c010800, 0xac2956e0,
+0xa000c3d, 0xa3820019, 0x1462000a, 0x24020081,
+0x3c028008, 0x34420100, 0x944500ea, 0x92260005,
+0x8f84001c, 0x30a5ffff, 0x30c600ff, 0xa000bfe,
+0x3c076021, 0x1462005c, 0x0, 0x9222000a,
+0x304300ff, 0x30620020, 0x10400007, 0x30620040,
+0x3c028008, 0x34420100, 0x944500ea, 0x8f84001c,
+0xa000bfc, 0x24060040, 0x10400007, 0x31600,
+0x3c028008, 0x34420100, 0x944500ea, 0x8f84001c,
+0xa000bfc, 0x24060041, 0x21603, 0x4410046,
+0x3c028008, 0x34420100, 0x944500ea, 0x8f84001c,
+0x24060042, 0x30a5ffff, 0x3c076019, 0xe000901,
+0x0, 0xa000c3d, 0x0, 0x9222000b,
+0x24040016, 0x304200ff, 0x10440006, 0x3c068000,
+0x9222000b, 0x24030017, 0x304200ff, 0x14430032,
+0x0, 0x34c50100, 0x90a2000b, 0x304200ff,
+0x1444000b, 0x8021, 0x8ca20020, 0x8ca40020,
+0x2403ff80, 0x431024, 0x21140, 0x3084007f,
+0x441025, 0x3c032000, 0x431025, 0xacc20830,
+0x94a20008, 0x21400, 0x21403, 0x4420001,
+0x24100001, 0x94a20008, 0x30420080, 0x5040001a,
+0x200a821, 0x94a20008, 0x30422000, 0x50400016,
+0x200a821, 0x8ca30018, 0x3c021c2d, 0x344219ed,
+0x10620011, 0x200a821, 0x3c020800, 0x8c4200d4,
+0x10400005, 0x3c028008, 0x24030004, 0x34420100,
+0xa04300fc, 0x3c028008, 0x34420100, 0x944500ea,
+0x8f84001c, 0x24060006, 0x30a5ffff, 0xe000901,
+0x3c076021, 0x200a821, 0xe000939, 0x0,
+0x9222000a, 0x30420008, 0x10400004, 0x2a01021,
+0xe001379, 0x0, 0x2a01021, 0x8fbf0030,
+0x8fb5002c, 0x8fb40028, 0x8fb30024, 0x8fb20020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038,
+0x2402ff80, 0x822024, 0x3c029000, 0x34420007,
+0x822025, 0x3c028000, 0xac440020, 0x3c038000,
+0x8c620020, 0x440fffe, 0x0, 0x3e00008,
+0x0, 0x3c038000, 0x2402ff80, 0x822024,
+0x34620007, 0x822025, 0xac640020, 0x8c620020,
+0x440fffe, 0x0, 0x3e00008, 0x0,
+0x27bdffd8, 0xafb3001c, 0xafb10014, 0xafb00010,
+0xafbf0020, 0xafb20018, 0x3c118000, 0x3c028008,
+0x8e320020, 0x34530100, 0xae240020, 0x966300ea,
+0x51400, 0x3c074000, 0x473825, 0xa08021,
+0x3021, 0xe000901, 0x3065ffff, 0x240200a1,
+0x16020002, 0x2402ffff, 0xa2620009, 0xae320020,
+0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0028, 0x3c028008,
+0x24030005, 0x27bdffe8, 0x34420100, 0xa04300fc,
+0xafbf0010, 0x3c028000, 0x8c420100, 0x240500a1,
+0x402021, 0xe000c67, 0xaf82001c, 0x3c038000,
+0x8c620278, 0x440fffe, 0x8f82001c, 0x8fbf0010,
+0x27bd0018, 0xac620240, 0x24020002, 0xa0620244,
0x3c021000, 0xac620278, 0x3e00008, 0x0,
-0x27bdffe8, 0x3c068000, 0xafbf0010, 0x34c50100,
-0x94a20008, 0x304400ff, 0x38830082, 0x38820084,
-0x2c630001, 0x2c420001, 0x621825, 0x10600030,
-0x24020083, 0x93820019, 0x50400039, 0x8fbf0010,
-0x3c020800, 0x90424bd8, 0x8cc40100, 0x3c070800,
-0x94e74bd2, 0x3046003f, 0x38c30032, 0x38c2003f,
+0x27bdffe8, 0x3c068000, 0xafbf0010, 0x34c70100,
+0x94e20008, 0x304400ff, 0x38830082, 0x38820084,
+0x2c630001, 0x2c420001, 0x621825, 0x1060002d,
+0x24020083, 0x93820019, 0x5040003b, 0x8fbf0010,
+0x3c020800, 0x904256cc, 0x8cc40100, 0x3c060800,
+0x94c656c6, 0x3045003f, 0x38a30032, 0x38a2003f,
0x2c630001, 0x2c420001, 0x621825, 0xaf84001c,
-0xaf870014, 0xa3800019, 0x14600006, 0xa02021,
-0x24020020, 0x14c20011, 0x3402ffff, 0x14e2000f,
-0x0, 0x24020020, 0x14c20005, 0x0,
-0x8ca30014, 0x2402ffff, 0x1062000a, 0x0,
-0x3c040800, 0x24844bcc, 0x3021, 0xe0006fb,
-0x24070001, 0xa000cb6, 0x0, 0xe00076c,
-0x0, 0xe00092f, 0x0, 0x24030c80,
-0x3c028000, 0xac430024, 0xa000cef, 0x8fbf0010,
-0x14820006, 0x2482ff80, 0x8cc30104, 0x3c026020,
-0xac430014, 0xa000cef, 0x8fbf0010, 0x304200ff,
-0x2c420002, 0x10400004, 0x24020022, 0x8fbf0010,
-0xa000b25, 0x27bd0018, 0x14820003, 0x8fbf0010,
-0xa000c6f, 0x27bd0018, 0x3c020800, 0x8c420020,
-0x1040001d, 0x24020018, 0x90a30009, 0x14620003,
-0x24020016, 0xa000cdb, 0x24030008, 0x14620007,
-0x24020017, 0x24030012, 0x3c028008, 0x34420080,
-0xa0430009, 0xa000ce8, 0x94a70008, 0x54620007,
-0x94a70008, 0x8f82ffac, 0x2404fffe, 0x90430005,
-0x641824, 0xa0430005, 0x94a70008, 0x90a6001b,
-0x8ca40000, 0x94a50006, 0x8fbf0010, 0x73c00,
-0xa0008c9, 0x27bd0018, 0x3e00008, 0x27bd0018,
-0x3c050800, 0x94a54c0a, 0x3c030800, 0x8c634c14,
-0x3c048000, 0x30a2ffff, 0x230c0, 0x2402fff0,
-0xc21024, 0x621821, 0xac83003c, 0x3c020800,
-0x8c424c10, 0x3c038000, 0xac820038, 0x3c020050,
-0x34420010, 0xac620030, 0x0, 0x0,
-0x0, 0x8c620000, 0x30420020, 0x1040fffd,
-0x30c20008, 0x10400009, 0x3c028000, 0x8c620408,
-0x8c63040c, 0x3c010800, 0xac224c00, 0x3c010800,
-0xac234c04, 0xa000d1b, 0x3c030020, 0x8c430400,
-0x8c420404, 0x3c010800, 0xac234c00, 0x3c010800,
-0xac224c04, 0x3c030020, 0x3c028000, 0xac430030,
-0x3c078000, 0x8ce20030, 0x431024, 0x1440fffd,
-0x0, 0x3c030800, 0x94634c08, 0x3c020800,
-0x94424c0c, 0x3c060800, 0x94c64c0e, 0x24a50001,
-0x621821, 0x30a4ffff, 0x3c020040, 0xace20030,
-0x3c010800, 0xa4234c08, 0x3c010800, 0xa4254c0a,
-0x14860003, 0x0, 0x3c010800, 0xa4204c0a,
-0x3e00008, 0x0, 0x27bdffe8, 0x3c040800,
-0x24844bf0, 0x3c05800a, 0xafbf0010, 0xe000e20,
-0x2406000a, 0x3c020800, 0x94424bf2, 0x3c030800,
-0x94634c0e, 0x3042000f, 0x24420003, 0x431804,
-0x24027fff, 0x43102b, 0x10400002, 0xaf830028,
-0xd, 0xe000cf1, 0x0, 0x3c020800,
-0x94424bf4, 0x3c030800, 0x94634bfa, 0x8fbf0010,
-0x3042000f, 0x21500, 0x621825, 0x27bd0018,
-0x3c028000, 0x3e00008, 0xac4300a0, 0x3c02800a,
-0x94430006, 0x3c020800, 0x94424bfa, 0x3c010800,
-0xa4234bf6, 0x431023, 0x8f830028, 0x3042ffff,
-0x43102b, 0x3e00008, 0x38420001, 0x27bdffe8,
-0xafbf0010, 0x3c02800a, 0x94420006, 0x3c010800,
-0xa4224bf6, 0xe000d58, 0x0, 0x5440fffa,
-0x3c02800a, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe8, 0xafbf0010, 0xe000d58, 0x0,
-0x10400003, 0x0, 0xe000d64, 0x0,
-0x3c020800, 0x8c424c00, 0x3c038000, 0x8fbf0010,
-0xac620038, 0x3c020800, 0x8c424c04, 0x34640400,
-0x27bd0018, 0xac62003c, 0x3c020005, 0xac620030,
-0xaf84002c, 0x3e00008, 0xaf800024, 0x8f820024,
+0xaf860014, 0xa3800019, 0x14600007, 0xe02021,
+0x24020020, 0x14a20012, 0x0, 0x3402ffff,
+0x14c2000f, 0x0, 0x24020020, 0x14a20005,
+0xe02821, 0x8ce30014, 0x2402ffff, 0x5062000b,
+0x8fbf0010, 0x3c040800, 0x248456c0, 0x3021,
+0xe000706, 0x24070001, 0xa000cd6, 0x8fbf0010,
+0xe000777, 0x0, 0x8fbf0010, 0xa000939,
+0x27bd0018, 0x14820004, 0x24020085, 0x8cc50104,
+0xa000ce1, 0x2021, 0x14820006, 0x2482ff80,
+0x8cc50104, 0x24044000, 0x8fbf0010, 0xa000167,
+0x27bd0018, 0x304200ff, 0x2c420002, 0x10400004,
+0x24020022, 0x8fbf0010, 0xa000b27, 0x27bd0018,
+0x14820004, 0x8f820024, 0x8fbf0010, 0xa000c86,
+0x27bd0018, 0x8c42000c, 0x1040001e, 0xe02821,
+0x90e30009, 0x24020018, 0x14620003, 0x24020016,
+0xa000cfc, 0x24030008, 0x14620007, 0x24020017,
+0x24030012, 0x3c028008, 0x34420080, 0xa0430009,
+0xa000d09, 0x94a70008, 0x54620007, 0x94a70008,
+0x8f82ff94, 0x2404fffe, 0x90430005, 0x641824,
+0xa0430005, 0x94a70008, 0x90a6001b, 0x8ca40000,
+0x94a50006, 0x8fbf0010, 0x73c00, 0xa0008dc,
+0x27bd0018, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x8f850024, 0x3c048000, 0x94a2002a, 0x8ca30034,
+0x230c0, 0x2402fff0, 0xc21024, 0x621821,
+0xac83003c, 0x8ca20030, 0x3c038000, 0xac820038,
+0x3c020050, 0x34420010, 0xac620030, 0x0,
+0x0, 0x0, 0x8c620000, 0x30420020,
+0x1040fffd, 0x30c20008, 0x10400006, 0x3c028000,
+0x8c620408, 0xaca20020, 0x8c62040c, 0xa000d34,
+0xaca20024, 0x8c430400, 0xaca30020, 0x8c420404,
+0xaca20024, 0x3c030020, 0x3c028000, 0xac430030,
+0x3c048000, 0x8c820030, 0x431024, 0x1440fffd,
+0x8f860024, 0x3c020040, 0xac820030, 0x94c3002a,
+0x94c20028, 0x94c4002c, 0x94c5002e, 0x24630001,
+0x441021, 0x3064ffff, 0xa4c20028, 0x14850002,
+0xa4c3002a, 0xa4c0002a, 0x3e00008, 0x0,
+0x8f840024, 0x27bdffe8, 0x3c058004, 0x24840010,
+0xafbf0010, 0xe000e47, 0x2406000a, 0x8f840024,
+0x94820012, 0x9483002e, 0x3042000f, 0x24420003,
+0x431804, 0x24027fff, 0x43102b, 0x10400002,
+0xac830000, 0xd, 0xe000d13, 0x0,
+0x8f830024, 0x8fbf0010, 0x27bd0018, 0x94620014,
+0x9463001a, 0x3042000f, 0x21500, 0x621825,
+0x3c028000, 0x3e00008, 0xac4300a0, 0x8f830024,
+0x3c028004, 0x94440006, 0x9462001a, 0x8c650000,
+0xa4640016, 0x441023, 0x3042ffff, 0x45102b,
+0x3e00008, 0x38420001, 0x8f840024, 0x3c078004,
+0x9486001a, 0x8c850000, 0x94e20006, 0xa4820016,
+0x94e30006, 0xc31023, 0x3042ffff, 0x45102b,
+0x38420001, 0x1440fff8, 0xa4830016, 0x3e00008,
+0x0, 0x8f840024, 0x3c028004, 0x94420006,
+0x9483001a, 0x8c850000, 0xa4820016, 0x621023,
+0x3042ffff, 0x45102b, 0x38420001, 0x5040000d,
+0x8f850024, 0x603021, 0x3c078004, 0x94e20006,
+0xa4820016, 0x94e30006, 0xc31023, 0x3042ffff,
+0x45102b, 0x38420001, 0x1440fff8, 0xa4830016,
+0x8f850024, 0x3c038000, 0x34620400, 0x8ca40020,
+0xaf820020, 0xac640038, 0x8ca20024, 0xac62003c,
+0x3c020005, 0xac620030, 0x3e00008, 0xaca00004,
+0x8f840024, 0x3c030006, 0x8c820004, 0x21140,
+0x431025, 0x3c038000, 0xac620030, 0x0,
+0x0, 0x0, 0x8c620000, 0x30420010,
+0x1040fffd, 0x34620400, 0xac800004, 0x3e00008,
+0xaf820020, 0x8f860024, 0x27bdffe0, 0xafb10014,
+0xafb00010, 0xafbf0018, 0x8cc30004, 0x8cc50024,
+0x8f820020, 0x309000ff, 0x94c4001a, 0x24630001,
+0x24420020, 0x24840001, 0x24a70020, 0xacc30004,
+0xaf820020, 0xa4c4001a, 0xacc70024, 0x4a10006,
+0x8821, 0x4e20005, 0x94c2001a, 0x8cc20020,
+0x24420001, 0xacc20020, 0x94c2001a, 0x94c30028,
+0x2e040001, 0x431026, 0x2c420001, 0x441024,
+0x50400005, 0x94c2001a, 0x24020001, 0xacc20008,
+0x94c2001a, 0x94c30028, 0x10202b, 0x431026,
+0x2c420001, 0x441025, 0x14400007, 0x0,
+0x8cc20008, 0x14400004, 0x24020010, 0x8cc30004,
+0x1462000f, 0x8f850024, 0xe000da7, 0x24110001,
+0x8f820024, 0x94430028, 0x9442001a, 0x14430003,
+0x0, 0xe000d13, 0x0, 0x16000004,
+0x8f850024, 0xe000d84, 0x0, 0x8f850024,
+0x94a2001e, 0x94a4001c, 0x24420001, 0x3043ffff,
+0x14640002, 0xa4a2001e, 0xa4a0001e, 0x1200000a,
+0x3c028004, 0x94a20014, 0x94a3001a, 0x3042000f,
+0x21500, 0x621825, 0x3c028000, 0xac4300a0,
+0xa000e1e, 0xaca00008, 0x94420006, 0x94a3001a,
+0x8ca40000, 0xa4a20016, 0x621023, 0x3042ffff,
+0x44102b, 0x38420001, 0x1040000d, 0x2201021,
+0x603021, 0x3c078004, 0x94e20006, 0xa4a20016,
+0x94e30006, 0xc31023, 0x3042ffff, 0x44102b,
+0x38420001, 0x1440fff8, 0xa4a30016, 0x2201021,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x3e00008, 0x0, 0x8f82002c,
0x3c030006, 0x21140, 0x431025, 0x3c038000,
0xac620030, 0x0, 0x0, 0x0,
0x8c620000, 0x30420010, 0x1040fffd, 0x34620400,
-0xaf82002c, 0x3e00008, 0xaf800024, 0x3c060800,
-0x8cc64c04, 0x8f850024, 0x8f83002c, 0x3c020800,
-0x94424bfa, 0x27bdffe0, 0x24a50001, 0x24630020,
-0x24420001, 0x24c70020, 0xafb10014, 0xafb00010,
-0xafbf0018, 0xaf850024, 0xaf83002c, 0x3c010800,
-0xa4224bfa, 0x309000ff, 0x3c010800, 0xac274c04,
-0x4c10008, 0x8821, 0x4e00006, 0x0,
-0x3c020800, 0x8c424c00, 0x24420001, 0x3c010800,
-0xac224c00, 0x3c040800, 0x94844c08, 0x3c020800,
-0x94424bfa, 0x2e030001, 0x441026, 0x2c440001,
-0x831824, 0x10600004, 0x10102b, 0x24020001,
-0xaf820020, 0x10102b, 0x821025, 0x14400006,
-0x8f820020, 0x14400004, 0x8f830024, 0x24020010,
-0x1462000f, 0x0, 0xe000d88, 0x24110001,
-0x3c030800, 0x94634bfa, 0x3c020800, 0x94424c08,
-0x14620003, 0x0, 0xe000cf1, 0x0,
-0x16000003, 0x0, 0xe000d71, 0x0,
-0x3c030800, 0x94634bfe, 0x3c020800, 0x94424bfc,
-0x24630001, 0x3064ffff, 0x3c010800, 0xa4234bfe,
-0x14820003, 0x0, 0x3c010800, 0xa4204bfe,
-0x1200000b, 0x0, 0x3c020800, 0x94424bf4,
-0x3c030800, 0x94634bfa, 0x21500, 0x621825,
-0x3c028000, 0xac4300a0, 0xa000df7, 0xaf800020,
-0xe000d58, 0x0, 0x10400004, 0x2201021,
-0xe000d64, 0x0, 0x2201021, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
-0x3e00008, 0x0, 0x8f820034, 0x3c030006,
-0x21140, 0x431025, 0x3c038000, 0xac620030,
-0x0, 0x0, 0x0, 0x8c620000,
-0x30420010, 0x1040fffd, 0x34620400, 0xaf820030,
-0x3e00008, 0xaf800034, 0x3e00008, 0x1021,
-0x3e00008, 0x0, 0x3084ffff, 0x30a5ffff,
-0x1821, 0x10800007, 0x0, 0x30820001,
-0x10400002, 0x42042, 0x651821, 0xa000e16,
-0x52840, 0x3e00008, 0x601021, 0x10c00006,
-0x24c6ffff, 0x8ca20000, 0x24a50004, 0xac820000,
-0xa000e20, 0x24840004, 0x3e00008, 0x0,
-0x10a00008, 0x24a3ffff, 0xac860000, 0x0,
-0x0, 0x2402ffff, 0x2463ffff, 0x1462fffa,
-0x24840004, 0x3e00008, 0x0, 0x3c028008,
-0x34420080, 0x24030001, 0xac43000c, 0xa4430010,
-0xa4430012, 0xa4430014, 0x3e00008, 0xa4430016,
-0x27bdffd8, 0x24820080, 0x2407ff80, 0x3043007f,
-0xafb00010, 0x808021, 0x472024, 0x3c020800,
-0x8c420020, 0x3c08800e, 0xafb3001c, 0xafb20018,
-0xafb10014, 0xafbf0020, 0x3c098000, 0x681821,
-0x30b100ff, 0x30d200ff, 0x10400029, 0x9821,
-0x26020100, 0xad24002c, 0x472824, 0x3042007f,
-0x482021, 0x90620000, 0x24030050, 0x304200ff,
-0x14430004, 0x0, 0xad25002c, 0x948200da,
-0x3053ffff, 0xe000d71, 0x0, 0x3c030800,
-0x94634bfe, 0x8f82002c, 0x112c00, 0xa32825,
-0x122400, 0x3c034000, 0x34840001, 0xa32825,
-0xac500000, 0x8fbf0020, 0xac400004, 0x8fb20018,
-0xac530008, 0x8fb10014, 0xac40000c, 0x8fb3001c,
-0xac440010, 0x8fb00010, 0xac400014, 0x24040001,
-0xac400018, 0x27bd0028, 0xa000d98, 0xac45001c,
-0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0028, 0x3c068000,
-0x34c20100, 0x9043000f, 0x24020010, 0x1062000e,
-0x28650011, 0x10a00007, 0x24020012, 0x24020008,
-0x2405003a, 0x10620006, 0x3021, 0x3e00008,
-0x0, 0x24050035, 0x1462fffc, 0x3021,
-0xa000e3d, 0x0, 0x8cc20074, 0x8f83ffac,
-0x24420fa0, 0x3e00008, 0xac62000c, 0x27bdffe8,
-0xafbf0010, 0xe000325, 0x24050001, 0x3c048008,
-0x8fbf0010, 0x24020001, 0x34830080, 0xa4620012,
-0x27bd0018, 0x24020001, 0x3e00008, 0xa080001a,
-0x27bdffe0, 0xafb20018, 0xafb10014, 0xafb00010,
-0xafbf001c, 0x30b2ffff, 0xe000315, 0x808821,
-0x3c028008, 0x34500080, 0x92020009, 0x24030004,
-0x304200ff, 0x1443000c, 0x3c028008, 0x12400008,
-0x2402000a, 0xe000e34, 0x0, 0x92020005,
-0x2403fffe, 0x431024, 0xa2020005, 0x24020012,
-0xa2020009, 0x3c028008, 0x34420080, 0x2202021,
-0xe000320, 0xa0400027, 0x16400003, 0x2202021,
-0xe000e98, 0x0, 0x2202021, 0x324600ff,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x24050038, 0xa000e3d, 0x27bd0020, 0x27bdffe0,
-0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010,
-0xe000315, 0x808021, 0xe000e34, 0x0,
-0x3c028008, 0x34450080, 0x90a20009, 0x24120018,
-0x305100ff, 0x12320003, 0x2002021, 0x24020012,
-0xa0a20009, 0x90a20005, 0x2403fffe, 0x431024,
-0xe000320, 0xa0a20005, 0x2002021, 0x24050020,
-0x16320007, 0x3021, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0xa000325, 0x27bd0020,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x24050039, 0xa000e3d, 0x27bd0020, 0x27bdffe8,
-0x3c028000, 0xafb00010, 0xafbf0014, 0x34420100,
-0x9442000c, 0x24050036, 0x808021, 0x14400012,
-0x304600ff, 0xe000315, 0x0, 0x3c028008,
-0x34420080, 0x24030012, 0xa0430009, 0x90430005,
-0x34630010, 0xe000e34, 0xa0430005, 0xe000320,
-0x2002021, 0x2002021, 0xe000325, 0x24050020,
-0xa000f15, 0x0, 0xe000e3d, 0x0,
-0xe000315, 0x2002021, 0x3c028008, 0x9043001b,
-0x2405ff9f, 0x2002021, 0x651824, 0x8fbf0014,
-0x8fb00010, 0xa043001b, 0xa000320, 0x27bd0018,
-0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
-0x30b100ff, 0xe000315, 0x808021, 0x3c028008,
-0x24030012, 0x34420080, 0xe000e34, 0xa0430009,
-0xe000320, 0x2002021, 0x2002021, 0x2203021,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x24050035,
-0xa000e3d, 0x27bd0020, 0x3c048008, 0x9083000e,
-0x9082000a, 0x1443000b, 0x2821, 0x8f82ffac,
-0x24030050, 0x24050001, 0x90420000, 0x304200ff,
-0x14430004, 0x0, 0x9082000e, 0x24420001,
-0xa082000e, 0x3e00008, 0xa01021, 0x3c038000,
-0x8c6201f8, 0x440fffe, 0x24020002, 0xac6401c0,
-0xa06201c4, 0x3c021000, 0x3e00008, 0xac6201f8,
-0x27bdffe0, 0xafb20018, 0x3c128008, 0xafb10014,
-0xafbf001c, 0xafb00010, 0x36510080, 0x92220009,
-0x2403000a, 0x304200ff, 0x1443003a, 0x0,
-0x8e430004, 0x8e220038, 0x5062007e, 0x8fbf001c,
-0x92220000, 0x24030050, 0x304200ff, 0x14430025,
-0x3c028000, 0x8c420140, 0x8e430004, 0x36420100,
-0x2202821, 0xac43001c, 0x9622005c, 0x8e230038,
-0x3042ffff, 0x21040, 0x621821, 0xae23001c,
-0x8e430004, 0x8e240038, 0x9622005c, 0x641823,
-0x3042ffff, 0x31843, 0x21040, 0x43102a,
-0x10400006, 0x0, 0x8e420004, 0x8e230038,
-0x431023, 0xa000f83, 0x22043, 0x9622005c,
-0x3042ffff, 0x22040, 0x3c028008, 0x34430100,
-0x34420080, 0xaca4002c, 0xa0400024, 0x24020001,
-0xa062000c, 0xe000f37, 0x0, 0x10400051,
-0x8fbf001c, 0x3c028000, 0x8c440140, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa000f48,
-0x27bd0020, 0x92220009, 0x24030010, 0x304200ff,
-0x14430004, 0x3c028000, 0x8c440140, 0xa000fc5,
-0x2821, 0x92220009, 0x24030016, 0x304200ff,
-0x14430006, 0x24020014, 0xa2220009, 0x3c028000,
-0x8c440140, 0xa000fd8, 0x8fbf001c, 0x8e220038,
-0x8e23003c, 0x431023, 0x4410032, 0x8fbf001c,
-0x92220027, 0x24420001, 0xa2220027, 0x92220027,
-0x3c030800, 0x8c630048, 0x304200ff, 0x14430016,
-0x3c108000, 0x92220009, 0x24030004, 0x304200ff,
-0x14430009, 0x3c028000, 0x8c440140, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x24050093,
-0xa000ea5, 0x27bd0020, 0x8c440140, 0x24050093,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0xa000f21, 0x27bd0020, 0x8e040140, 0xe000315,
-0x0, 0x8e420004, 0x2442ffff, 0xae420004,
-0x8e22003c, 0x2442ffff, 0xae22003c, 0xe000320,
-0x8e040140, 0x8e040140, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x24050004, 0xa000325,
-0x27bd0020, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x3c068000, 0x8cc20188,
-0x3c038008, 0x34650080, 0x9063000e, 0x21402,
-0x304400ff, 0x306300ff, 0x1464000e, 0x3c028008,
-0x90a20026, 0x304200ff, 0x10440009, 0x8f82ffac,
-0xa0a40026, 0x24030050, 0x90420000, 0x304200ff,
-0x14430006, 0x0, 0xa00058c, 0x8cc40180,
-0x3c028008, 0x34420080, 0xa0440026, 0x3e00008,
-0x0, 0x27bdffe0, 0x30e700ff, 0xafb20018,
-0xafbf001c, 0xafb10014, 0xafb00010, 0x809021,
-0x14e00006, 0x30c600ff, 0x0, 0xd,
-0x0, 0xa001037, 0x24000117, 0x3c038008,
-0x9062000e, 0x304200ff, 0x14460023, 0x34620080,
-0x90420026, 0x304200ff, 0x1446001f, 0x0,
-0x9062000f, 0x304200ff, 0x1446001b, 0x0,
-0x9062000a, 0x304200ff, 0x14460003, 0x8f90ffac,
-0xd, 0x8f90ffac, 0x8f82ffb0, 0x3c118000,
-0xae05003c, 0xac450000, 0xa066000a, 0xe000315,
-0x8e240100, 0xa2000024, 0xe000320, 0x8e240100,
+0xaf820028, 0x3e00008, 0xaf80002c, 0x3e00008,
+0x1021, 0x3e00008, 0x0, 0x3084ffff,
+0x30a5ffff, 0x1821, 0x10800007, 0x0,
+0x30820001, 0x10400002, 0x42042, 0x651821,
+0xa000e3d, 0x52840, 0x3e00008, 0x601021,
+0x10c00006, 0x24c6ffff, 0x8ca20000, 0x24a50004,
+0xac820000, 0xa000e47, 0x24840004, 0x3e00008,
+0x0, 0x10a00008, 0x24a3ffff, 0xac860000,
+0x0, 0x0, 0x2402ffff, 0x2463ffff,
+0x1462fffa, 0x24840004, 0x3e00008, 0x0,
+0x3c028008, 0x34420080, 0x24030001, 0xac43000c,
+0xa4430010, 0xa4430012, 0xa4430014, 0x3e00008,
+0xa4430016, 0x8f820024, 0x27bdffd8, 0xafb3001c,
+0xafb20018, 0xafb10014, 0xafb00010, 0xafbf0020,
+0x8c47000c, 0x24820080, 0x2409ff80, 0x3c08800e,
+0x3043007f, 0x808021, 0x3c0a8000, 0x492024,
+0x681821, 0x30b100ff, 0x30d200ff, 0x10e00029,
+0x9821, 0x26020100, 0xad44002c, 0x492824,
+0x3042007f, 0x482021, 0x90620000, 0x24030050,
+0x304200ff, 0x14430004, 0x0, 0xad45002c,
+0x948200ea, 0x3053ffff, 0xe000d84, 0x0,
+0x8f820024, 0x8f830020, 0x112c00, 0x9442001e,
+0x122400, 0x34840001, 0xa22825, 0x3c024000,
+0xa22825, 0xac700000, 0x8fbf0020, 0xac600004,
+0x8fb20018, 0xac730008, 0x8fb10014, 0xac60000c,
+0x8fb3001c, 0xac640010, 0x8fb00010, 0xac600014,
+0x24040001, 0xac600018, 0x27bd0028, 0xa000db8,
+0xac65001c, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028,
+0x3c068000, 0x34c20100, 0x9043000f, 0x24020010,
+0x1062000e, 0x28650011, 0x10a00007, 0x24020012,
+0x24020008, 0x2405003a, 0x10620006, 0x3021,
+0x3e00008, 0x0, 0x24050035, 0x1462fffc,
+0x3021, 0xa000e64, 0x0, 0x8cc20074,
+0x8f83ff94, 0x24420fa0, 0x3e00008, 0xac62000c,
+0x27bdffe8, 0xafbf0010, 0xe000342, 0x24050001,
+0x3c048008, 0x8fbf0010, 0x24020001, 0x34830080,
+0xa4620012, 0x27bd0018, 0x24020001, 0x3e00008,
+0xa080001a, 0x27bdffe0, 0xafb20018, 0xafb10014,
+0xafb00010, 0xafbf001c, 0x30b2ffff, 0xe000332,
+0x808821, 0x3c028008, 0x34500080, 0x92020009,
+0x24030004, 0x304200ff, 0x1443000c, 0x3c028008,
+0x12400008, 0x2402000a, 0xe000e5b, 0x0,
+0x92020005, 0x2403fffe, 0x431024, 0xa2020005,
+0x24020012, 0xa2020009, 0x3c028008, 0x34420080,
+0x2202021, 0xe00033d, 0xa0400027, 0x16400003,
+0x2202021, 0xe000ebf, 0x0, 0x2202021,
+0x324600ff, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x24050038, 0xa000e64, 0x27bd0020,
+0x27bdffe0, 0xafbf001c, 0xafb20018, 0xafb10014,
+0xafb00010, 0xe000332, 0x808021, 0xe000e5b,
+0x0, 0x3c028008, 0x34450080, 0x90a20009,
+0x24120018, 0x305100ff, 0x12320003, 0x2002021,
+0x24020012, 0xa0a20009, 0x90a20005, 0x2403fffe,
+0x431024, 0xe00033d, 0xa0a20005, 0x2002021,
+0x24050020, 0x16320007, 0x3021, 0x8fbf001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa000342,
+0x27bd0020, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x24050039, 0xa000e64, 0x27bd0020,
+0x27bdffe8, 0x3c028000, 0xafb00010, 0xafbf0014,
+0x34420100, 0x9442000c, 0x24050036, 0x808021,
+0x14400012, 0x304600ff, 0xe000332, 0x0,
+0x3c028008, 0x34420080, 0x24030012, 0xa0430009,
+0x90430005, 0x34630010, 0xe000e5b, 0xa0430005,
+0xe00033d, 0x2002021, 0x2002021, 0xe000342,
+0x24050020, 0xa000f3c, 0x0, 0xe000e64,
+0x0, 0xe000332, 0x2002021, 0x3c028008,
+0x9043001b, 0x2405ff9f, 0x2002021, 0x651824,
+0x8fbf0014, 0x8fb00010, 0xa043001b, 0xa00033d,
+0x27bd0018, 0x27bdffe0, 0xafbf0018, 0xafb10014,
+0xafb00010, 0x30b100ff, 0xe000332, 0x808021,
+0x3c028008, 0x24030012, 0x34420080, 0xe000e5b,
+0xa0430009, 0xe00033d, 0x2002021, 0x2002021,
+0x2203021, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x24050035, 0xa000e64, 0x27bd0020, 0x3c048008,
+0x9083000e, 0x9082000a, 0x1443000b, 0x2821,
+0x8f82ff94, 0x24030050, 0x24050001, 0x90420000,
+0x304200ff, 0x14430004, 0x0, 0x9082000e,
+0x24420001, 0xa082000e, 0x3e00008, 0xa01021,
0x3c038000, 0x8c6201f8, 0x440fffe, 0x24020002,
-0xac7201c0, 0xa06201c4, 0x3c021000, 0xac6201f8,
-0xa001038, 0x8fbf001c, 0x0, 0xd,
-0x0, 0x24000140, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
-0x8f83ffac, 0x3c028000, 0x8c440100, 0x34420100,
-0x8c65003c, 0x9046001b, 0xa000ffe, 0x24070001,
-0x3c028008, 0x9043000e, 0x9042000a, 0x431026,
-0x304200ff, 0x3e00008, 0x2102b, 0x27bdffe0,
-0x3c028008, 0xafb10014, 0xafb00010, 0xafbf0018,
-0x34500080, 0x92020005, 0x24030030, 0x30420030,
-0x14430084, 0x808821, 0x3c020800, 0x8c420020,
-0x10400081, 0x8fbf0018, 0xe000d71, 0x0,
-0x8f86002c, 0xacd10000, 0x92020008, 0x92030009,
-0x304200ff, 0x21200, 0x306300ff, 0x431025,
-0xacc20004, 0x9202004d, 0x21600, 0x21603,
-0x4410005, 0x0, 0x3c030800, 0x8c630048,
-0xa001076, 0x3c108008, 0x92020008, 0x30420040,
-0x14400003, 0x1821, 0x92020027, 0x304300ff,
-0x3c108008, 0x36110080, 0x9222004d, 0x31e00,
-0x3c050800, 0x94a54bfe, 0x304200ff, 0x21400,
-0x621825, 0xacc30008, 0x8e230030, 0x3c02c00b,
-0xa22825, 0xacc3000c, 0x8e220034, 0x2021,
-0xacc20010, 0x8e220038, 0xacc20014, 0x8e22003c,
-0xacc20018, 0xe000d98, 0xacc5001c, 0x8e020004,
-0x8f84002c, 0x3c058000, 0xac820000, 0x8e220020,
-0xac820004, 0x8e22001c, 0xac820008, 0x8e220058,
-0x8ca30074, 0x431021, 0xac82000c, 0x8e22002c,
-0xac820010, 0x8e220040, 0x8e230044, 0x21400,
-0x431025, 0xac820014, 0x9222004d, 0x24030080,
-0x304200ff, 0x14430003, 0x0, 0xa0010b8,
-0xac800018, 0x8e23000c, 0x24020001, 0x1062000e,
+0xac6401c0, 0xa06201c4, 0x3c021000, 0x3e00008,
+0xac6201f8, 0x27bdffe0, 0xafb20018, 0x3c128008,
+0xafb10014, 0xafbf001c, 0xafb00010, 0x36510080,
+0x92220009, 0x2403000a, 0x304200ff, 0x1443003e,
+0x0, 0x8e430004, 0x8e220038, 0x50620080,
+0x8fbf001c, 0x92220000, 0x24030050, 0x304200ff,
+0x14430025, 0x3c028000, 0x8c420140, 0x8e430004,
+0x36420100, 0x2202821, 0xac43001c, 0x9622005c,
+0x8e230038, 0x3042ffff, 0x21040, 0x621821,
+0xae23001c, 0x8e430004, 0x8e240038, 0x9622005c,
+0x641823, 0x3042ffff, 0x31843, 0x21040,
+0x43102a, 0x10400006, 0x0, 0x8e420004,
+0x8e230038, 0x431023, 0xa000faa, 0x22043,
+0x9622005c, 0x3042ffff, 0x22040, 0x3c028008,
+0x34430100, 0x34420080, 0xaca4002c, 0xa0400024,
+0x24020001, 0xa062000c, 0xe000f5e, 0x0,
+0x10400053, 0x8fbf001c, 0x3c028000, 0x8c440140,
+0x3c038000, 0x8c6201f8, 0x440fffe, 0x24020002,
+0xac6401c0, 0xa06201c4, 0x3c021000, 0xac6201f8,
+0xa001007, 0x8fbf001c, 0x92220009, 0x24030010,
+0x304200ff, 0x14430004, 0x3c028000, 0x8c440140,
+0xa000fee, 0x2821, 0x92220009, 0x24030016,
+0x304200ff, 0x14430006, 0x24020014, 0xa2220009,
+0x3c028000, 0x8c440140, 0xa001001, 0x8fbf001c,
+0x8e220038, 0x8e23003c, 0x431023, 0x4410030,
+0x8fbf001c, 0x92220027, 0x24420001, 0xa2220027,
+0x92220027, 0x2c420004, 0x14400016, 0x3c108000,
+0x92220009, 0x24030004, 0x304200ff, 0x14430009,
+0x3c028000, 0x8c440140, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x24050093, 0xa000ecc,
+0x27bd0020, 0x8c440140, 0x24050093, 0x8fbf001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0xa000f48,
+0x27bd0020, 0x8e040140, 0xe000332, 0x0,
+0x8e420004, 0x2442ffff, 0xae420004, 0x8e22003c,
+0x2442ffff, 0xae22003c, 0xe00033d, 0x8e040140,
+0x8e040140, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x24050004, 0xa000342, 0x27bd0020,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x3c068000, 0x8cc20188, 0x3c038008,
+0x34650080, 0x9063000e, 0x21402, 0x304400ff,
+0x306300ff, 0x1464000e, 0x3c028008, 0x90a20026,
+0x304200ff, 0x10440009, 0x8f82ff94, 0xa0a40026,
+0x24030050, 0x90420000, 0x304200ff, 0x14430006,
+0x0, 0xa0005a1, 0x8cc40180, 0x3c028008,
+0x34420080, 0xa0440026, 0x3e00008, 0x0,
+0x27bdffe0, 0x30e700ff, 0xafb20018, 0xafbf001c,
+0xafb10014, 0xafb00010, 0x809021, 0x14e00006,
+0x30c600ff, 0x0, 0xd, 0x0,
+0xa001060, 0x24000116, 0x3c038008, 0x9062000e,
+0x304200ff, 0x14460023, 0x34620080, 0x90420026,
+0x304200ff, 0x1446001f, 0x0, 0x9062000f,
+0x304200ff, 0x1446001b, 0x0, 0x9062000a,
+0x304200ff, 0x14460003, 0x8f90ff94, 0xd,
+0x8f90ff94, 0x8f82ff98, 0x3c118000, 0xae05003c,
+0xac450000, 0xa066000a, 0xe000332, 0x8e240100,
+0xa2000024, 0xe00033d, 0x8e240100, 0x3c038000,
+0x8c6201f8, 0x440fffe, 0x24020002, 0xac7201c0,
+0xa06201c4, 0x3c021000, 0xac6201f8, 0xa001061,
+0x8fbf001c, 0x0, 0xd, 0x0,
+0x2400013f, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x8f83ff94,
+0x3c028000, 0x8c440100, 0x34420100, 0x8c65003c,
+0x9046001b, 0xa001027, 0x24070001, 0x3c028008,
+0x9043000e, 0x9042000a, 0x431026, 0x304200ff,
+0x3e00008, 0x2102b, 0x27bdffe0, 0x3c028008,
+0xafb10014, 0xafb00010, 0xafbf0018, 0x34500080,
+0x92020005, 0x24030030, 0x30420030, 0x14430085,
+0x808821, 0x8f820024, 0x8c42000c, 0x10400082,
+0x8fbf0018, 0xe000d84, 0x0, 0x8f860020,
+0xacd10000, 0x92020008, 0x92030009, 0x304200ff,
+0x21200, 0x306300ff, 0x431025, 0xacc20004,
+0x9202004d, 0x21600, 0x21603, 0x4410005,
+0x0, 0x3c030800, 0x8c630048, 0xa00109f,
+0x3c108008, 0x92020008, 0x30420040, 0x14400003,
+0x1821, 0x92020027, 0x304300ff, 0x3c108008,
+0x36110080, 0x9222004d, 0x31e00, 0x304200ff,
+0x21400, 0x621825, 0xacc30008, 0x8e240030,
+0x8f820024, 0xacc4000c, 0x8e250034, 0x9443001e,
+0x3c02c00b, 0xacc50010, 0x621825, 0x8e220038,
+0x2021, 0xacc20014, 0x8e22003c, 0xacc20018,
+0xe000db8, 0xacc3001c, 0x8e020004, 0x8f840020,
+0x3c058000, 0xac820000, 0x8e220020, 0xac820004,
+0x8e22001c, 0xac820008, 0x8e220058, 0x8ca30074,
+0x431021, 0xac82000c, 0x8e22002c, 0xac820010,
+0x8e220040, 0x8e230044, 0x21400, 0x431025,
+0xac820014, 0x9222004d, 0x24030080, 0x304200ff,
+0x14430004, 0x0, 0xac800018, 0xa0010e3,
+0x8f820024, 0x8e23000c, 0x24020001, 0x1062000e,
0x2402ffff, 0x92220008, 0x30420040, 0x1440000a,
0x2402ffff, 0x8e23000c, 0x8ca20074, 0x621823,
0x3c020800, 0x621024, 0x14400002, 0x2821,
-0x602821, 0x51043, 0xac820018, 0x3c020800,
-0x94424bfe, 0x3c03c00c, 0x2021, 0x431025,
-0x8f83002c, 0xe000d98, 0xac62001c, 0x3c048008,
-0x34820100, 0x8c420000, 0x8f83002c, 0x34840080,
-0x3c060800, 0x94c64bfe, 0xac620000, 0xac600004,
-0x8c850048, 0x3c02400d, 0xc23025, 0xac650008,
-0xac60000c, 0xac600010, 0x90820005, 0x8fbf0018,
-0x8fb10014, 0x21600, 0xac620014, 0x8fb00010,
-0xac600018, 0x24040001, 0xac66001c, 0xa000d98,
+0x602821, 0x51043, 0xac820018, 0x8f820024,
+0x2021, 0x9443001e, 0x3c02c00c, 0x621825,
+0x8f820020, 0xe000db8, 0xac43001c, 0x3c038008,
+0x34620100, 0x8c420000, 0x8f850020, 0x34630080,
+0x8fbf0018, 0xaca20000, 0xaca00004, 0x8c640048,
+0x8f820024, 0x8fb10014, 0xaca40008, 0xaca0000c,
+0xaca00010, 0x90630005, 0x9446001e, 0x3c02400d,
+0x31e00, 0xc23025, 0xaca30014, 0x8fb00010,
+0xaca00018, 0x24040001, 0xaca6001c, 0xa000db8,
0x27bd0020, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
0x3e00008, 0x27bd0020, 0x3c028000, 0x9443007c,
0x3c028008, 0x34460100, 0x308400ff, 0x3065ffff,
0x24020005, 0x24a34650, 0xa0c4000c, 0x5482000c,
0x3065ffff, 0x90c2000d, 0x2c420007, 0x10400007,
0x24a30a00, 0x90c3000d, 0x24020014, 0x621004,
-0xa21021, 0xa0010f5, 0x3045ffff, 0x3065ffff,
+0xa21021, 0xa00111f, 0x3045ffff, 0x3065ffff,
0x3c028008, 0x34420080, 0x3e00008, 0xa4450014,
0x3c038008, 0x34680080, 0xad050038, 0x34670100,
0x8ce2001c, 0x308400ff, 0xa21023, 0x18400003,
0x30c600ff, 0x24a2fffc, 0xace2001c, 0x30820001,
0x50400008, 0x3c038008, 0x8d02003c, 0xa21023,
0x4410012, 0x24040005, 0x8c620004, 0x10a2000f,
-0x3c038008, 0x8c620004, 0x14a20018, 0x0,
+0x3c038008, 0x8c620004, 0x14a2001e, 0x0,
0x3c020800, 0x8c4200d8, 0x30420020, 0x10400009,
0x3c028008, 0x34620080, 0x90630008, 0x9042004c,
-0x14430004, 0x3c028008, 0x24040004, 0xa0010df,
+0x14430004, 0x3c028008, 0x24040004, 0xa001109,
0x0, 0x34430080, 0x34420100, 0xa040000c,
-0x24020001, 0xa4620014, 0x10c00004, 0x3c028000,
-0x8c440100, 0xa000f48, 0x0, 0x3e00008,
-0x0, 0x27bdffe8, 0xa61823, 0xafbf0010,
-0x1860004e, 0x308800ff, 0x3c028008, 0x34470080,
-0xa0e00024, 0x34440100, 0xa0e00027, 0x8c82001c,
-0xa21023, 0x440002b, 0x0, 0x8ce2003c,
-0x94e3005c, 0x8ce4002c, 0x453023, 0x3063ffff,
-0xc31821, 0x83202b, 0x10800004, 0xe01821,
-0x8ce2002c, 0xa001148, 0xa21021, 0x94e2005c,
-0x3042ffff, 0xc21021, 0xa21021, 0xac62001c,
-0x3c028008, 0x34470080, 0x94e2005c, 0x8ce3001c,
-0x3042ffff, 0x21040, 0xa21021, 0x43102b,
-0x10400003, 0x0, 0xa001159, 0x8ce2001c,
-0x94e2005c, 0x3042ffff, 0x21040, 0xa21021,
-0xace2001c, 0x3c028008, 0x34420100, 0x8fbf0010,
-0x1002021, 0x24060001, 0xa040000c, 0xa0010f9,
-0x27bd0018, 0x8ce2001c, 0x461023, 0x43102b,
-0x54400001, 0xace5001c, 0x94e2005c, 0x3042ffff,
-0x62102b, 0x14400007, 0x24020002, 0x94e2005c,
-0x8ce3001c, 0x3042ffff, 0x621821, 0xace3001c,
-0x24020002, 0xace50038, 0xe000f37, 0xa082000c,
-0x10400018, 0x8fbf0010, 0x3c028000, 0x8c440100,
-0x8fbf0010, 0xa000f48, 0x27bd0018, 0x31020010,
+0x24020001, 0xa4620014, 0x10c0000a, 0x3c028000,
+0x8c440100, 0x3c038000, 0x8c6201f8, 0x440fffe,
+0x24020002, 0xac6401c0, 0xa06201c4, 0x3c021000,
+0xac6201f8, 0x3e00008, 0x0, 0x27bdffe8,
+0xa61823, 0xafbf0010, 0x18600080, 0x308800ff,
+0x3c028008, 0x34470080, 0xa0e00024, 0x34440100,
+0xa0e00027, 0x8c82001c, 0xa21023, 0x4400056,
+0x0, 0x8ce2003c, 0x94e3005c, 0x8ce4002c,
+0x453023, 0x3063ffff, 0xc31821, 0x83202b,
+0x10800004, 0xe01821, 0x8ce2002c, 0xa001178,
+0xa21021, 0x94e2005c, 0x3042ffff, 0xc21021,
+0xa21021, 0xac62001c, 0x3c028008, 0x34440080,
+0x9482005c, 0x8c83001c, 0x3042ffff, 0x21040,
+0xa21021, 0x43102b, 0x10400004, 0x0,
+0x8c82001c, 0xa00118b, 0x3c068008, 0x9482005c,
+0x3042ffff, 0x21040, 0xa21021, 0x3c068008,
+0x34c30100, 0x34c70080, 0xac82001c, 0xa060000c,
+0xace50038, 0x8c62001c, 0xa21023, 0x18400002,
+0x24a2fffc, 0xac62001c, 0x31020001, 0x10400008,
+0x3c038008, 0x8ce2003c, 0xa21023, 0x4410012,
+0x24040005, 0x8cc20004, 0x10a20010, 0x8fbf0010,
+0x8c620004, 0x14a2004f, 0x8fbf0010, 0x3c020800,
+0x8c4200d8, 0x30420020, 0x1040000a, 0x3c028008,
+0x34620080, 0x90630008, 0x9042004c, 0x14430005,
+0x3c028008, 0x24040004, 0x8fbf0010, 0xa001109,
+0x27bd0018, 0x34430080, 0x34420100, 0xa040000c,
+0x24020001, 0xa4620014, 0x3c028000, 0x8c440100,
+0x3c038000, 0x8c6201f8, 0x440fffe, 0x24020002,
+0xa0011d8, 0x0, 0x8ce2001c, 0x461023,
+0x43102b, 0x54400001, 0xace5001c, 0x94e2005c,
+0x3042ffff, 0x62102b, 0x14400007, 0x24020002,
+0x94e2005c, 0x8ce3001c, 0x3042ffff, 0x621821,
+0xace3001c, 0x24020002, 0xace50038, 0xe000f5e,
+0xa082000c, 0x1040001f, 0x8fbf0010, 0x3c028000,
+0x8c440100, 0x3c038000, 0x8c6201f8, 0x440fffe,
+0x24020002, 0xac6401c0, 0xa06201c4, 0x3c021000,
+0xac6201f8, 0xa0011f0, 0x8fbf0010, 0x31020010,
0x10400010, 0x8fbf0010, 0x3c028008, 0x34450080,
0x8ca3001c, 0x94a2005c, 0x661823, 0x3042ffff,
0x621821, 0x3c023fff, 0x3444ffff, 0x83102b,
@@ -9272,105 +9174,253 @@ u32 bce_COM_b09FwText[(0x4ac8/4) + 1] = {
0x34470100, 0x8ce20020, 0x461021, 0xace20020,
0x8ce20020, 0x44102b, 0x1440000b, 0x3c023fff,
0x8ce20020, 0x441023, 0xace20020, 0x9522005c,
-0x3042ffff, 0xa0011ae, 0x822021, 0xace00020,
+0x3042ffff, 0xa001210, 0x822021, 0xace00020,
0x862021, 0x3c023fff, 0x3443ffff, 0x64102b,
0x54400001, 0x602021, 0x3c028008, 0x34420080,
0x851821, 0xac43001c, 0xa0400024, 0xa0400027,
-0xa0011fd, 0x8fbf0010, 0x31420010, 0x10400040,
-0x8fbf0010, 0x3c068008, 0x34c40080, 0x8c82003c,
-0x481023, 0x5840003b, 0x1402021, 0x90820024,
+0xa001262, 0x3c038008, 0x31420010, 0x10400043,
+0x3c038008, 0x3c068008, 0x34c40080, 0x8c82003c,
+0x481023, 0x5840003e, 0x34660080, 0x90820024,
0x24420001, 0xa0820024, 0x90820024, 0x3c030800,
-0x8c630024, 0x304200ff, 0x43102b, 0x54400034,
+0x8c630024, 0x304200ff, 0x43102b, 0x14400068,
0x8fbf0010, 0x34c20100, 0x8c42001c, 0xa21023,
-0x1840002f, 0x8fbf0010, 0x8cc30004, 0x9482005c,
+0x18400063, 0x0, 0x8cc30004, 0x9482005c,
0x681823, 0x3042ffff, 0x31843, 0x21040,
0x43102a, 0x10400005, 0x0, 0x8cc20004,
-0x481023, 0xa0011e3, 0x21043, 0x9482005c,
+0x481023, 0xa001245, 0x21043, 0x9482005c,
0x3042ffff, 0x21040, 0x3c068008, 0xac82002c,
0x34c50080, 0x94a2005c, 0x8ca4002c, 0x94a3005c,
0x3042ffff, 0x21040, 0x822021, 0x3063ffff,
0x832021, 0x1041021, 0xaca2001c, 0x8cc20004,
-0x34c60100, 0xacc2001c, 0x24020002, 0xe000f37,
-0xa0c2000c, 0x1040000a, 0x8fbf0010, 0x3c028000,
-0x8c440100, 0x8fbf0010, 0xa000f48, 0x27bd0018,
-0x1402021, 0x24060001, 0xa0010f9, 0x27bd0018,
-0x3e00008, 0x27bd0018, 0x3c098008, 0x352a0080,
-0x8d42003c, 0x308300ff, 0x352b0100, 0x461023,
-0x30e700ff, 0x18400006, 0x602021, 0x24020001,
-0xa160000c, 0xa160000d, 0xa001190, 0xa5420014,
-0x24020005, 0x35290100, 0x3021, 0x14e20008,
-0xa1400027, 0x9122000d, 0x2c420006, 0x10400004,
-0x0, 0x9122000d, 0x24420001, 0xa122000d,
-0xa0010f9, 0x0, 0x3c038008, 0x3c028000,
-0x34420100, 0x34640080, 0x34630100, 0x9045000a,
-0x8c480014, 0x8c890038, 0x9062000c, 0x30aa00ff,
-0x1281823, 0x304700ff, 0x1c60000e, 0x2ce40006,
-0x24020001, 0xe21004, 0x1080000a, 0x30430003,
-0x1402021, 0x1002821, 0x1203021, 0x14600007,
-0x304b000c, 0x15600007, 0x30420030, 0x14400007,
-0x0, 0x3e00008, 0x0, 0xa001190,
-0x0, 0xa00112a, 0x0, 0xa001203,
-0x0, 0x3c038008, 0x34640100, 0x24020003,
-0xa082000c, 0x8c620004, 0x3e00008, 0xac82001c,
-0x3c058008, 0x34a30080, 0x90620027, 0x34a50100,
-0x24060043, 0x24420001, 0xa0620027, 0x90630027,
-0x3c020800, 0x8c420048, 0x306300ff, 0x14620004,
-0x3c076021, 0x94a500da, 0xa0008ee, 0x30a5ffff,
-0x3e00008, 0x0, 0x27bdffe8, 0xafbf0010,
-0x3c028000, 0xe001249, 0x8c440180, 0x3c028008,
-0x34430100, 0xa060000c, 0x8c420004, 0x8fbf0010,
-0x27bd0018, 0x3e00008, 0xac62001c, 0x27bdffe0,
-0x3c028008, 0xafbf0018, 0xafb10014, 0xafb00010,
-0x34450080, 0x34460100, 0x3c088000, 0x8d090140,
-0x90c3000c, 0x8ca4003c, 0x8ca20038, 0x14820038,
-0x306700ff, 0x9502007c, 0x90a30027, 0x14600009,
-0x3045ffff, 0x24020005, 0x54e20008, 0x3c048008,
-0x90c2000d, 0x24420001, 0xa0c2000d, 0xa001284,
-0x3c048008, 0xa0c0000d, 0x3c048008, 0x34820100,
-0x9042000c, 0x24030005, 0x304200ff, 0x1443000a,
-0x24a205dc, 0x34830080, 0x90620027, 0x2c420007,
-0x50400005, 0x24a20a00, 0x90630027, 0x24020014,
-0x621004, 0xa21021, 0x3c108008, 0x36100080,
-0x3045ffff, 0x1202021, 0xe001249, 0xa6050014,
-0x9602005c, 0x8e030038, 0x3c118000, 0x3042ffff,
-0x21040, 0x621821, 0xae03001c, 0xe000315,
-0x8e240140, 0x92020025, 0x34420040, 0xa2020025,
-0xe000320, 0x8e240140, 0x8e240140, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0xa000f48, 0x27bd0020,
+0x34c60100, 0xacc2001c, 0x24020002, 0xe000f5e,
+0xa0c2000c, 0x1040003e, 0x8fbf0010, 0x3c028000,
+0x8c440100, 0x3c038000, 0x8c6201f8, 0x440fffe,
+0x24020002, 0xa001292, 0x0, 0x34660080,
+0xacc50038, 0x34640100, 0x8c82001c, 0xa21023,
+0x18400002, 0x24a2fffc, 0xac82001c, 0x31420001,
+0x5040000a, 0x3c038008, 0x8cc2003c, 0xa21023,
+0x4430014, 0x24040005, 0x8c620004, 0x14a20003,
+0x3c038008, 0xa001284, 0x24040005, 0x8c620004,
+0x14a2001f, 0x8fbf0010, 0x3c020800, 0x8c4200d8,
+0x30420020, 0x1040000a, 0x3c028008, 0x34620080,
+0x90630008, 0x9042004c, 0x14430005, 0x3c028008,
+0x24040004, 0x8fbf0010, 0xa001109, 0x27bd0018,
+0x34430080, 0x34420100, 0xa040000c, 0x24020001,
+0xa4620014, 0x3c028000, 0x8c440100, 0x3c038000,
+0x8c6201f8, 0x440fffe, 0x24020002, 0xac6401c0,
+0xa06201c4, 0x3c021000, 0xac6201f8, 0x8fbf0010,
+0x3e00008, 0x27bd0018, 0x27bdffe8, 0x3c0a8008,
+0xafbf0010, 0x35490080, 0x8d22003c, 0xc04021,
+0x308400ff, 0x461023, 0x1840009d, 0x30e700ff,
+0x35470100, 0x24020001, 0xa63023, 0xa0e0000c,
+0xa0e0000d, 0xa5220014, 0x18c00024, 0x30820010,
+0x8d23001c, 0x8d22002c, 0x681823, 0x43102b,
+0x1040000f, 0x0, 0x8ce20020, 0x461021,
+0xace20020, 0x8ce20020, 0x43102b, 0x1440000b,
+0x3c023fff, 0x8ce20020, 0x431023, 0xace20020,
+0x9522005c, 0x3042ffff, 0xa0012c1, 0x621821,
+0xace00020, 0x661821, 0x3c023fff, 0x3446ffff,
+0xc3102b, 0x54400001, 0xc01821, 0x3c028008,
+0x34420080, 0x651821, 0xac43001c, 0xa0400024,
+0xa0400027, 0xa00130f, 0x3c038008, 0x10400040,
+0x3c038008, 0x8d22003c, 0x481023, 0x5840003d,
+0x34670080, 0x91220024, 0x24420001, 0xa1220024,
+0x91220024, 0x3c030800, 0x8c630024, 0x304200ff,
+0x43102b, 0x1440009a, 0x8fbf0010, 0x8ce2001c,
+0xa21023, 0x18400096, 0x0, 0x8d430004,
+0x9522005c, 0x681823, 0x3042ffff, 0x31843,
+0x21040, 0x43102a, 0x10400005, 0x1202021,
+0x8d420004, 0x481023, 0xa0012f2, 0x21043,
+0x9522005c, 0x3042ffff, 0x21040, 0x3c068008,
+0xac82002c, 0x34c50080, 0x94a2005c, 0x8ca4002c,
+0x94a3005c, 0x3042ffff, 0x21040, 0x822021,
+0x3063ffff, 0x831821, 0x1031021, 0xaca2001c,
+0x8cc20004, 0x34c60100, 0xacc2001c, 0x24020002,
+0xe000f5e, 0xa0c2000c, 0x10400071, 0x8fbf0010,
+0x3c028000, 0x8c440100, 0x3c038000, 0x8c6201f8,
+0x440fffe, 0x24020002, 0xa001339, 0x0,
+0x34670080, 0xace50038, 0x34660100, 0x8cc2001c,
+0xa21023, 0x18400002, 0x24a2fffc, 0xacc2001c,
+0x30820001, 0x50400008, 0x3c038008, 0x8ce2003c,
+0xa21023, 0x4430051, 0x24040005, 0x8c620004,
+0x10a2003e, 0x3c038008, 0x8c620004, 0x54a20054,
+0x8fbf0010, 0x3c020800, 0x8c4200d8, 0x30420020,
+0x10400006, 0x3c028008, 0x34620080, 0x90630008,
+0x9042004c, 0x10430040, 0x3c028008, 0x34430080,
+0x34420100, 0xa040000c, 0x24020001, 0xa4620014,
+0x3c028000, 0x8c440100, 0x3c038000, 0x8c6201f8,
+0x440fffe, 0x24020002, 0xac6401c0, 0xa06201c4,
+0x3c021000, 0xac6201f8, 0xa001377, 0x8fbf0010,
+0x24020005, 0xa1200027, 0x14e2000a, 0x3c038008,
+0x35430100, 0x9062000d, 0x2c420006, 0x50400005,
+0x3c038008, 0x9062000d, 0x24420001, 0xa062000d,
+0x3c038008, 0x34670080, 0xace50038, 0x34660100,
+0x8cc2001c, 0xa21023, 0x18400002, 0x24a2fffc,
+0xacc2001c, 0x30820001, 0x5040000a, 0x3c038008,
+0x8ce2003c, 0xa21023, 0x4410014, 0x24040005,
+0x8c620004, 0x14a20003, 0x3c038008, 0xa00136e,
+0x24040005, 0x8c620004, 0x14a20015, 0x8fbf0010,
+0x3c020800, 0x8c4200d8, 0x30420020, 0x1040000a,
+0x3c028008, 0x34620080, 0x90630008, 0x9042004c,
+0x14430005, 0x3c028008, 0x24040004, 0x8fbf0010,
+0xa001109, 0x27bd0018, 0x34430080, 0x34420100,
+0xa040000c, 0x24020001, 0xa4620014, 0x8fbf0010,
+0x3e00008, 0x27bd0018, 0x3c0b8008, 0x27bdffe8,
+0x3c028000, 0xafbf0010, 0x34420100, 0x356a0080,
+0x9044000a, 0x35690100, 0x8c450014, 0x8d480038,
+0x9123000c, 0x308400ff, 0x1051023, 0x1c4000b3,
+0x306700ff, 0x2ce20006, 0x504000b1, 0x8fbf0010,
+0x24020001, 0xe23004, 0x30c20003, 0x54400008,
+0xa83023, 0x30c2000c, 0x144000a1, 0x30c20030,
+0x144000a3, 0x8fbf0010, 0xa00143b, 0x0,
+0x18c00024, 0x30820010, 0x8d43001c, 0x8d42002c,
+0x681823, 0x43102b, 0x1040000f, 0x0,
+0x8d220020, 0x461021, 0xad220020, 0x8d220020,
+0x43102b, 0x1440000b, 0x3c023fff, 0x8d220020,
+0x431023, 0xad220020, 0x9542005c, 0x3042ffff,
+0xa0013af, 0x621821, 0xad200020, 0x661821,
+0x3c023fff, 0x3446ffff, 0xc3102b, 0x54400001,
+0xc01821, 0x3c028008, 0x34420080, 0x651821,
+0xac43001c, 0xa0400024, 0xa0400027, 0xa0013fd,
+0x3c038008, 0x10400040, 0x3c038008, 0x8d42003c,
+0x481023, 0x1840003d, 0x34670080, 0x91420024,
+0x24420001, 0xa1420024, 0x91420024, 0x3c030800,
+0x8c630024, 0x304200ff, 0x43102b, 0x14400070,
+0x8fbf0010, 0x8d22001c, 0xa21023, 0x1840006c,
+0x0, 0x8d630004, 0x9542005c, 0x681823,
+0x3042ffff, 0x31843, 0x21040, 0x43102a,
+0x10400005, 0x1402021, 0x8d620004, 0x481023,
+0xa0013e0, 0x21043, 0x9542005c, 0x3042ffff,
+0x21040, 0x3c068008, 0xac82002c, 0x34c50080,
+0x94a2005c, 0x8ca4002c, 0x94a3005c, 0x3042ffff,
+0x21040, 0x822021, 0x3063ffff, 0x831821,
+0x1031021, 0xaca2001c, 0x8cc20004, 0x34c60100,
+0xacc2001c, 0x24020002, 0xe000f5e, 0xa0c2000c,
+0x10400047, 0x8fbf0010, 0x3c028000, 0x8c440100,
+0x3c038000, 0x8c6201f8, 0x440fffe, 0x24020002,
+0xa00142d, 0x0, 0x34670080, 0xace50038,
+0x34660100, 0x8cc2001c, 0xa21023, 0x18400002,
+0x24a2fffc, 0xacc2001c, 0x30820001, 0x5040000a,
+0x3c038008, 0x8ce2003c, 0xa21023, 0x4430014,
+0x24040005, 0x8c620004, 0x14a20003, 0x3c038008,
+0xa00141f, 0x24040005, 0x8c620004, 0x14a20028,
+0x8fbf0010, 0x3c020800, 0x8c4200d8, 0x30420020,
+0x1040000a, 0x3c028008, 0x34620080, 0x90630008,
+0x9042004c, 0x14430005, 0x3c028008, 0x24040004,
+0x8fbf0010, 0xa001109, 0x27bd0018, 0x34430080,
+0x34420100, 0xa040000c, 0x24020001, 0xa4620014,
+0x3c028000, 0x8c440100, 0x3c038000, 0x8c6201f8,
+0x440fffe, 0x24020002, 0xac6401c0, 0xa06201c4,
+0x3c021000, 0xac6201f8, 0xa00143b, 0x8fbf0010,
+0x8fbf0010, 0x1003021, 0xa00115a, 0x27bd0018,
+0x1003021, 0xa001299, 0x27bd0018, 0x8fbf0010,
+0x3e00008, 0x27bd0018, 0x3c038008, 0x34640100,
+0x24020003, 0xa082000c, 0x8c620004, 0x3e00008,
+0xac82001c, 0x3c058008, 0x34a30080, 0x90620027,
+0x34a50100, 0x24060043, 0x24420001, 0xa0620027,
+0x90630027, 0x3c020800, 0x8c420048, 0x306300ff,
+0x14620004, 0x3c076021, 0x94a500ea, 0xa000901,
+0x30a5ffff, 0x3e00008, 0x0, 0x27bdffe8,
+0xafbf0010, 0x3c028000, 0xe001444, 0x8c440180,
+0x3c028008, 0x34430100, 0xa060000c, 0x8c420004,
+0x8fbf0010, 0x27bd0018, 0x3e00008, 0xac62001c,
+0x27bdffe0, 0x3c028008, 0xafbf0018, 0xafb10014,
+0xafb00010, 0x34450080, 0x34460100, 0x3c088000,
+0x8d090140, 0x90c3000c, 0x8ca4003c, 0x8ca20038,
+0x1482003b, 0x306700ff, 0x9502007c, 0x90a30027,
+0x14600009, 0x3045ffff, 0x24020005, 0x54e20008,
+0x3c048008, 0x90c2000d, 0x24420001, 0xa0c2000d,
+0xa00147f, 0x3c048008, 0xa0c0000d, 0x3c048008,
+0x34820100, 0x9042000c, 0x24030005, 0x304200ff,
+0x1443000a, 0x24a205dc, 0x34830080, 0x90620027,
+0x2c420007, 0x50400005, 0x24a20a00, 0x90630027,
+0x24020014, 0x621004, 0xa21021, 0x3c108008,
+0x36100080, 0x3045ffff, 0x1202021, 0xe001444,
+0xa6050014, 0x9602005c, 0x8e030038, 0x3c118000,
+0x3042ffff, 0x21040, 0x621821, 0xae03001c,
+0xe000332, 0x8e240140, 0x92020025, 0x34420040,
+0xa2020025, 0xe00033d, 0x8e240140, 0x8e240140,
+0x3c038000, 0x8c6201f8, 0x440fffe, 0x24020002,
+0xac6401c0, 0xa06201c4, 0x3c021000, 0xac6201f8,
0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0020, 0x0 };
-u32 bce_COM_b09FwData[(0x0/4) + 1] = { 0x0 };
-u32 bce_COM_b09FwRodata[(0x30/4) + 1] = {
-0x80080100, 0x80080080, 0x80080000,
-0x80080240, 0x8000ef0, 0x8000f48, 0x8000f8c,
-0x8001020, 0x8001064, 0x80080100, 0x80080080,
-0x80080000, 0x0 };
-u32 bce_COM_b09FwBss[(0xc0/4) + 1] = { 0x0 };
-u32 bce_COM_b09FwSbss[(0x38/4) + 1] = { 0x0 };
-u32 bce_COM_b09FwSdata[(0x0/4) + 1] = { 0x0 };
+0x27bd0020, 0x3c036010, 0x3c020800, 0x24420174,
+0xac62502c, 0x8c625000, 0x3c048000, 0x34420080,
+0xac625000, 0x3c020800, 0x2442547c, 0x3c010800,
+0xac225600, 0x3c020800, 0x24425438, 0x3c010800,
+0xac225604, 0x3c020002, 0xac840008, 0xac82000c,
+0x3e00008, 0x24020001, 0xa03021, 0x3c1c0800,
+0x279c5608, 0x3c020002, 0x3c050400, 0x852826,
+0x822026, 0x4102b, 0x2ca50001, 0x2c840001,
+0x21080, 0x3c030800, 0x24635600, 0x852025,
+0x431821, 0x10800003, 0x1021, 0xac660000,
+0x24020001, 0x3e00008, 0x0, 0x3c1c0800,
+0x279c5608, 0x3c020002, 0x3c050400, 0x852826,
+0x822026, 0x4102b, 0x2ca50001, 0x2c840001,
+0x21080, 0x3c030800, 0x24635600, 0x852025,
+0x431821, 0x10800005, 0x1021, 0x3c020800,
+0x24425438, 0xac620000, 0x24020001, 0x3e00008,
+0x0, 0x3c020002, 0x3c030400, 0x821026,
+0x831826, 0x2c420001, 0x2c630001, 0x431025,
+0x1040000b, 0x2821, 0x3c1c0800, 0x279c5608,
+0x3c038000, 0x8c620008, 0x24050001, 0x431025,
+0xac620008, 0x8c62000c, 0x441025, 0xac62000c,
+0x3e00008, 0xa01021, 0x3c1c0800, 0x279c5608,
+0x3c058000, 0x8ca3000c, 0x42027, 0x24020001,
+0x641824, 0x3e00008, 0xaca3000c, 0x3c020002,
+0x14820006, 0x3c056000, 0x8ca208d0, 0x2403fffe,
+0x431024, 0x3e00008, 0xaca208d0, 0x3c020400,
+0x14820005, 0x0, 0x8ca208d0, 0x2403fffd,
+0x431024, 0xaca208d0, 0x3e00008, 0x0,
+0x3c02601a, 0x34420010, 0x8c430080, 0x27bdfff8,
+0x8c440084, 0xafa30000, 0x93a30000, 0x24020004,
+0x1462001a, 0xafa40004, 0x93a20001, 0x10400007,
+0x97a30002, 0x3062fffc, 0x3c038000, 0x431021,
+0x8c420000, 0xa001536, 0xafa20004, 0x3062fffc,
+0x3c038000, 0x431021, 0xac440000, 0xa3a00000,
+0x3c056000, 0x8ca208d0, 0x2403fffe, 0x3c04601a,
+0x431024, 0xaca208d0, 0x8fa30004, 0x8fa20000,
+0x34840010, 0xac830084, 0xac820080, 0x3e00008,
+0x27bd0008, 0x27bdffe8, 0xafbf0010, 0x3c1c0800,
+0x279c5608, 0x3c028000, 0x8c43000c, 0x8c420004,
+0x431824, 0x3c020002, 0x10600014, 0x622824,
+0x3c020400, 0x3c040002, 0x10a00005, 0x621024,
+0x3c020800, 0x8c425600, 0xa00155b, 0x0,
+0x10400007, 0x3c040400, 0x3c020800, 0x8c425604,
+0x40f809, 0x0, 0xa001560, 0x0,
+0xd, 0x3c1c0800, 0x279c5608, 0x8fbf0010,
+0x3e00008, 0x27bd0018, 0x0 };
+u32 bce_COM_b09FwData[(0x0/4) + 1] = { 0x0 };
+u32 bce_COM_b09FwRodata[(0x38/4) + 1] = {
+0x80080240, 0x80080100, 0x80080080,
+0x80080000, 0xc80, 0x3200, 0x8000e98,
+0x8000ef4, 0x8000f88, 0x8001028, 0x8001074,
+0x80080100, 0x80080080, 0x80080000, 0x0 };
+u32 bce_COM_b09FwBss[(0x11c/4) + 1] = { 0x0 };
+u32 bce_COM_b09FwSbss[(0x30/4) + 1] = { 0x0 };
+u32 bce_COM_b09FwSdata[(0x0/4) + 1] = { 0x0 };
-int bce_RXP_b09FwReleaseMajor = 0x1;
-int bce_RXP_b09FwReleaseMinor = 0x0;
-int bce_RXP_b09FwReleaseFix = 0x0;
-u32 bce_RXP_b09FwStartAddr = 0x080031d8;
-u32 bce_RXP_b09FwTextAddr = 0x08000000;
-int bce_RXP_b09FwTextLen = 0x7908;
-u32 bce_RXP_b09FwDataAddr = 0x00000000;
-int bce_RXP_b09FwDataLen = 0x0;
-u32 bce_RXP_b09FwRodataAddr = 0x08007908;
-int bce_RXP_b09FwRodataLen = 0x124;
-u32 bce_RXP_b09FwBssAddr = 0x08007ab8;
-int bce_RXP_b09FwBssLen = 0x20;
-u32 bce_RXP_b09FwSbssAddr = 0x08007a60;
-int bce_RXP_b09FwSbssLen = 0x58;
-u32 bce_RXP_b09FwSDataAddr = 0x00000000;
-int bce_RXP_b09FwSDataLen = 0x0;
-u32 bce_RXP_b09FwText[(0x7908/4) + 1] = {
-0xa000c76,
-0x0, 0x0, 0xd, 0x72787034,
-0x2e362e31, 0x36000000, 0x4061003, 0x0,
-0x1, 0x0, 0x0, 0x0,
+int bce_RXP_b09FwReleaseMajor = 0x6;
+int bce_RXP_b09FwReleaseMinor = 0x0;
+int bce_RXP_b09FwReleaseFix = 0x11;
+u32 bce_RXP_b09FwStartAddr = 0x08003210;
+u32 bce_RXP_b09FwTextAddr = 0x08000000;
+int bce_RXP_b09FwTextLen = 0x9090;
+u32 bce_RXP_b09FwDataAddr = 0x00000000;
+int bce_RXP_b09FwDataLen = 0x0;
+u32 bce_RXP_b09FwRodataAddr = 0x08009090;
+int bce_RXP_b09FwRodataLen = 0x33c;
+u32 bce_RXP_b09FwBssAddr = 0x08009478;
+int bce_RXP_b09FwBssLen = 0x1bc;
+u32 bce_RXP_b09FwSbssAddr = 0x08009400;
+int bce_RXP_b09FwSbssLen = 0x78;
+u32 bce_RXP_b09FwSDataAddr = 0x00000000;
+int bce_RXP_b09FwSDataLen = 0x0;
+u32 bce_RXP_b09FwText[(0x9090/4) + 1] = {
+0xa000c84, 0x0, 0x0,
+0xd, 0x72787036, 0x2e302e31, 0x37000000,
+0x6001103, 0x0, 0x1, 0x0,
+0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
@@ -10165,507 +10215,651 @@ u32 bce_RXP_b09FwText[(0x7908/4) + 1] = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
+0x0, 0x80, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0xa, 0x0,
0x0, 0x0, 0x10000003, 0x0,
-0xd, 0xd, 0x3c020800, 0x24427a60,
-0x3c030800, 0x24637ad8, 0xac400000, 0x43202b,
+0xd, 0xd, 0x3c020801, 0x24429400,
+0x3c030801, 0x24639634, 0xac400000, 0x43202b,
0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd9ffc,
-0x3a0f021, 0x3c100800, 0x261031d8, 0x3c1c0800,
-0x279c7a60, 0xe001253, 0x0, 0xd,
+0x3a0f021, 0x3c100800, 0x26103210, 0x3c1c0801,
+0x279c9400, 0xe001274, 0x0, 0xd,
0x3c028000, 0x30a5ffff, 0x30c600ff, 0x34430180,
0x3c088000, 0x8d0901b8, 0x520fffe, 0x0,
0xac640000, 0x24040002, 0xa4650008, 0xa066000a,
0xa064000b, 0xac670018, 0x3c031000, 0x3e00008,
0xad0301b8, 0x3c056000, 0x8ca24ff8, 0x440fffe,
0x0, 0xaca44fc0, 0x3c031000, 0x3c040200,
-0xaca44fc4, 0x3e00008, 0xaca34ff8, 0x27bdffe8,
-0xafbf0014, 0xafb00010, 0xe0012a5, 0x808021,
-0x3c048008, 0x34850080, 0x90a60005, 0x2403fffe,
-0x2002021, 0xc31024, 0x8fbf0014, 0x8fb00010,
-0xa0a20005, 0xa0012af, 0x27bd0018, 0x27bdffe8,
-0xafb00010, 0xafbf0014, 0xe000ed6, 0x808021,
-0x3c068008, 0x34c50080, 0x90a40000, 0x24020050,
-0x308300ff, 0x10620007, 0x3c098000, 0x2002021,
-0x8fbf0014, 0x8fb00010, 0xad200180, 0xa000fc5,
-0x27bd0018, 0x24080100, 0x3c078000, 0x2002021,
-0x8fbf0014, 0x8fb00010, 0xace80180, 0xa000fc5,
-0x27bd0018, 0x27bdff88, 0x3c088008, 0xafbe0070,
-0xafb60068, 0xafb40060, 0xafb00050, 0xafbf0074,
-0xafb7006c, 0xafb50064, 0xafb3005c, 0xafb20058,
-0xafb10054, 0x35050080, 0x3c078000, 0x8cf10128,
-0x90a40009, 0xace00084, 0x90a60005, 0x309000ff,
-0xa021, 0x61827, 0x30620001, 0xb021,
-0x14400067, 0xf021, 0x90a90000, 0x24050020,
-0x312400ff, 0x10850016, 0x240a0050, 0x108a008d,
-0x0, 0x3c0c0800, 0x8d8c00dc, 0x258b0001,
-0x3c010800, 0xac2b00dc, 0xe00139b, 0x0,
-0x8fbf0074, 0x8fbe0070, 0x8fb7006c, 0x8fb60068,
-0x8fb50064, 0x8fb40060, 0x8fb3005c, 0x8fb20058,
-0x8fb10054, 0x8fb00050, 0x3e00008, 0x27bd0078,
-0xd, 0x3c158000, 0xafa00030, 0x96a20116,
-0x8eb90104, 0x3c1f0020, 0x36b20c00, 0x33fc024,
-0x18b82b, 0x173140, 0xafa60030, 0x8eae0104,
-0x3053ffff, 0x3c0f0040, 0x2723821, 0x1cf6824,
-0x90f2000d, 0x11a00048, 0x34c40040, 0x32430020,
-0x14600002, 0x34860080, 0x803021, 0x14c00094,
-0xafa60030, 0x3c098008, 0x35250080, 0x90a80008,
-0x31060040, 0x50c00006, 0x3c088008, 0x240a0004,
-0x120a00a3, 0x240b0012, 0x120b0029, 0x3c088008,
-0x35150100, 0x3c178000, 0x96f3011a, 0x94ee000e,
-0x92af0008, 0x324c0004, 0x3275ffff, 0x1ee6804,
-0xafad003c, 0x8cf30004, 0x11800031, 0x8cf70008,
-0x35030080, 0x90780008, 0x33070040, 0x14e00028,
-0x0, 0x8c720050, 0x2728823, 0x6200006,
-0x3c068000, 0x8c7f0034, 0x27fc823, 0x7220084,
-0x8e820008, 0x3c068000, 0xacc00044, 0x24020001,
-0x8fbf0074, 0x8fbe0070, 0x8fb7006c, 0x8fb60068,
-0x8fb50064, 0x8fb40060, 0x8fb3005c, 0x8fb20058,
-0x8fb10054, 0x8fb00050, 0x3e00008, 0x27bd0078,
-0xe000cb8, 0x2021, 0x8fbf0074, 0x8fbe0070,
-0x8fb7006c, 0x8fb60068, 0x8fb50064, 0x8fb40060,
-0x8fb3005c, 0x8fb20058, 0x8fb10054, 0x8fb00050,
-0x3e00008, 0x27bd0078, 0xa000d18, 0xc02021,
-0xe00146c, 0x2602021, 0x1440ffdf, 0x3c068000,
-0x3c038008, 0x34630080, 0x8c640034, 0x2641023,
-0x4400018, 0x0, 0x3c140800, 0x8e943100,
-0x26900001, 0x3c010800, 0xac303100, 0xe0012a5,
-0x2202021, 0x3c048008, 0x349f0080, 0x93fe0025,
-0x2202021, 0x37c90004, 0xa3e90025, 0xe0012af,
-0x0, 0xe000c9e, 0x2202021, 0xa000d45,
-0x24020001, 0x3c140800, 0x26947ac8, 0xa000d07,
-0x3c158000, 0x8c680030, 0x2683023, 0x18c00008,
-0x240b000c, 0x3c090800, 0x8d293100, 0x325200fc,
-0xa821, 0x25250001, 0x3c010800, 0xac253100,
-0xafab0030, 0x8c6a0030, 0x1534023, 0x190000e0,
-0x2a8602a, 0x1580ffdd, 0x0, 0x12a8002a,
-0x2a87823, 0x2689821, 0x31f5ffff, 0x32470002,
-0x10e00034, 0x32590010, 0x3c138008, 0x36700080,
-0x921e0008, 0x33d60040, 0x52c000d3, 0x8e820008,
-0x2202021, 0xe0012a5, 0x24120018, 0xa2120009,
-0x92170005, 0x2418fffe, 0x2202021, 0x2f8a824,
-0xe0012af, 0xa2150005, 0x24040039, 0x2821,
-0xe001447, 0x24060018, 0xa000d45, 0x24020001,
-0x9296000c, 0x3c048008, 0x349e0080, 0x8fc70038,
-0x16a300, 0x36900081, 0x30c600ff, 0x2202021,
-0xe000c8d, 0x3205f081, 0x3c068000, 0xacc00044,
-0xa000d45, 0x24020001, 0x3a4e0001, 0x31cd0001,
-0x15a0ffae, 0x2689821, 0xa000d97, 0x0,
-0x40f809, 0x24040016, 0xa000d45, 0x24020001,
-0x2202021, 0xe001529, 0xe02821, 0xa000cfa,
-0x8fbf0074, 0x1320ff73, 0x3c048008, 0x34890080,
-0x8d230038, 0x8c820004, 0x2e2f823, 0x1fe0ff6e,
-0x3c068000, 0x2e33023, 0x4c20001, 0x60b821,
-0xafa80018, 0x3c198000, 0xafb30010, 0xafb50014,
-0x97260120, 0x8d2a0030, 0x9524005c, 0x8fb8003c,
-0x8fad0030, 0x3087ffff, 0x30dfffff, 0x3e87021,
-0x372f4000, 0x307282b, 0x8e820004, 0x1cf6021,
-0x1a55825, 0xafa90048, 0xafac0020, 0xafaa0028,
-0xafab0030, 0xafaa0024, 0xafa0002c, 0xafb70034,
-0x40f809, 0x27a40010, 0x8fa80030, 0x31030002,
-0x10600002, 0x8fa90048, 0x325200fe, 0x91230008,
-0x30690040, 0x51200013, 0x8fa40024, 0x3c028008,
-0x8c480004, 0x111700a4, 0x240a0014, 0x32580001,
-0x5300000c, 0x8fa40024, 0x2419000c, 0x121900c0,
-0x2a1f000d, 0x13e000ba, 0x2406000e, 0x2404000a,
-0x52040001, 0x24160008, 0x8fa90024, 0x25240001,
-0xafa40024, 0x3c188008, 0x37050080, 0x8fa70014,
-0x8caf0030, 0x340cffff, 0x877021, 0xacae0030,
-0xafaf0038, 0x90ad004e, 0x8cab0030, 0x8fa8003c,
-0x1ac1004, 0x1625021, 0xacaa0034, 0x8fa60030,
-0x2e82021, 0x30c30008, 0x1060000b, 0xafa40040,
-0x8cb90020, 0x1324008f, 0x30c600ff, 0x9289000c,
-0x8fa70034, 0x98300, 0x36040080, 0x3085f080,
-0xe000c8d, 0x2202021, 0x3c0a8008, 0x35500080,
-0x8e030030, 0x8fa80038, 0x683023, 0x18c00065,
-0x262f0080, 0x3c0e0800, 0x8dce3198, 0x2407ff80,
-0x1e76824, 0x31ec007f, 0x3c068000, 0x3c028004,
-0x31cb0010, 0xaccd0090, 0x1160003b, 0x1822821,
-0x90b8006b, 0x57000039, 0x3c048008, 0x241f0001,
-0xa0bf006b, 0x94c5007a, 0x24b9000a, 0xa6190012,
-0x3c0a8008, 0x35450080, 0x90a80008, 0x31100040,
-0x16000004, 0x3c038008, 0x324b0001, 0x1560006b,
-0x0, 0x34640080, 0x8c8c0020, 0x8fb20040,
-0x11920009, 0x34630100, 0x8c6d0000, 0x26d1023,
-0x18400012, 0x8fb80040, 0x241e0001, 0xac980020,
-0xac730000, 0xac770004, 0x16c0002d, 0x0,
-0x17c00027, 0x0, 0x12a00005, 0x1821,
-0x8fa50030, 0x30b50004, 0x52a0fe95, 0x601021,
-0x24030001, 0xa000cf9, 0x601021, 0x8c6e0000,
-0x15d3fff1, 0x0, 0x8c670004, 0x2e77823,
-0x5e1ffe9, 0x8fb80040, 0xa000e5b, 0x0,
-0xa000d98, 0x4021, 0x40f809, 0x24040017,
-0xa000d45, 0x24020001, 0x3c048008, 0x34900080,
-0x241e0001, 0x2202021, 0xe0012a5, 0xa61e0012,
-0x92090025, 0x2202021, 0x241e0001, 0x35220001,
-0xe0012af, 0xa2020025, 0xa000e46, 0x3c0a8008,
-0xe000c9e, 0x2202021, 0xa000e5f, 0x0,
-0xe0012a5, 0x2202021, 0x3c198008, 0x37370080,
-0x2202021, 0xe0012af, 0xa2f60009, 0x2c03021,
-0x24040037, 0xe001447, 0x2821, 0xa000e5d,
-0x0, 0x8fa60018, 0x58c0ffae, 0x3c0a8008,
-0xe0012a5, 0x2202021, 0x92030025, 0x2202021,
-0x241e0001, 0x34620004, 0xe0012af, 0xa2020025,
-0xa000e46, 0x3c0a8008, 0x120a0030, 0x2a0b0015,
-0x11600024, 0x240d0016, 0x240c000c, 0x560cff58,
-0x32580001, 0x3c058008, 0x90af001b, 0x2407ffbd,
-0x2416000e, 0x1e77024, 0xa0ae001b, 0xa000e01,
-0x32580001, 0x3c1f8000, 0x97e5011a, 0x50a0ff6f,
-0x34c60010, 0xa000e25, 0x9289000c, 0x8cb30030,
-0x8e960008, 0x24040018, 0x26740001, 0x2c0f809,
-0xacb40030, 0x8fb10030, 0xa000cf9, 0x32220004,
-0x1606ff4a, 0x8fa90024, 0xa000e0c, 0x24160010,
-0x2410000e, 0x52d0ff44, 0x24160010, 0xa000e0b,
-0x24160016, 0x560dff36, 0x32580001, 0x3c058008,
-0x90af001b, 0x2407ffbd, 0x24160010, 0x1e77024,
-0xa0ae001b, 0xa000e01, 0x32580001, 0xa000e00,
-0x24160012, 0x3c038000, 0x8c6201b8, 0x440fffe,
+0xaca44fc4, 0x3e00008, 0xaca34ff8, 0x9486000c,
+0xa05021, 0x24880014, 0x62b02, 0x51080,
+0x444821, 0x109182b, 0x10600011, 0x0,
+0x91030000, 0x2c640009, 0x50800009, 0x91190001,
+0x36080, 0x3c0d0801, 0x25ad9090, 0x18d5821,
+0x8d670000, 0xe00008, 0x0, 0x91190001,
+0x1194021, 0x109302b, 0x54c0fff2, 0x91030000,
+0x3e00008, 0x1021, 0xa000ccc, 0x25080001,
+0x910f0001, 0x240e000a, 0x15ee0040, 0x128c823,
+0x2f38000a, 0x1700003d, 0x250d0002, 0x8d580000,
+0x250f0006, 0x370e0100, 0xad4e0000, 0x910c0002,
+0x91ab0001, 0x91a40002, 0x91a60003, 0xc2e00,
+0xb3c00, 0xa71025, 0x41a00, 0x43c825,
+0x326c025, 0xad580004, 0x910e0006, 0x91ed0001,
+0x91e70002, 0x91e50003, 0xe5e00, 0xd6400,
+0x16c3025, 0x72200, 0xc41025, 0x451825,
+0x2508000a, 0xa000ccc, 0xad430008, 0x910f0001,
+0x25040002, 0x24080002, 0x55e80001, 0x1202021,
+0xa000ccc, 0x804021, 0x910c0001, 0x240b0003,
+0x158b0016, 0x0, 0x8d580000, 0x910e0002,
+0x25080003, 0x370d0008, 0xa14e0010, 0xa000ccc,
+0xad4d0000, 0x91190001, 0x240f0004, 0x172f000b,
+0x0, 0x91070002, 0x91040003, 0x8d430000,
+0x72a00, 0xa41025, 0x34660004, 0x25080004,
+0xad42000c, 0xa000ccc, 0xad460000, 0x3e00008,
+0x24020001, 0x27bdffe8, 0xafbf0014, 0xafb00010,
+0xe0015e5, 0x808021, 0x3c048008, 0x34850080,
+0x90a60005, 0x2403fffe, 0x2002021, 0xc31024,
+0x8fbf0014, 0x8fb00010, 0xa0a20005, 0xa0015ef,
+0x27bd0018, 0x27bdffe8, 0xafb00010, 0xafbf0014,
+0xe000fd4, 0x808021, 0x3c068008, 0x34c50080,
+0x90a40000, 0x24020050, 0x308300ff, 0x10620007,
+0x3c098000, 0x2002021, 0x8fbf0014, 0x8fb00010,
+0xad200180, 0xa0010a6, 0x27bd0018, 0x24080100,
+0x3c078000, 0x2002021, 0x8fbf0014, 0x8fb00010,
+0xace80180, 0xa0010a6, 0x27bd0018, 0x27bdff78,
+0x3c058008, 0xafbe0080, 0xafb7007c, 0xafb3006c,
+0xafb10064, 0xafbf0084, 0xafb60078, 0xafb50074,
+0xafb40070, 0xafb20068, 0xafb00060, 0x34a60080,
+0x3c058000, 0x8cb20128, 0x90c40009, 0x8ca70104,
+0x3c020001, 0x309100ff, 0xe21824, 0xb821,
+0xf021, 0x10600007, 0x9821, 0x3c090800,
+0x8d2931f0, 0x24130001, 0x25280001, 0x3c010800,
+0xac2831f0, 0xaca00084, 0x90cc0005, 0xc5827,
+0x316a0001, 0x15400072, 0xafa00050, 0x90cd0000,
+0x24060020, 0x31a400ff, 0x10860018, 0x240e0050,
+0x108e0093, 0x0, 0x3c100800, 0x8e1000dc,
+0x260f0001, 0x3c010800, 0xac2f00dc, 0xe00165e,
+0x0, 0x401821, 0x8fbf0084, 0x8fbe0080,
+0x8fb7007c, 0x8fb60078, 0x8fb50074, 0x8fb40070,
+0x8fb3006c, 0x8fb20068, 0x8fb10064, 0x8fb00060,
+0x601021, 0x3e00008, 0x27bd0088, 0xd,
+0x3c1f8000, 0xafa00030, 0x97e50116, 0x8fe20104,
+0x3c040020, 0x30b9ffff, 0x443824, 0x7182b,
+0x33140, 0xafa60030, 0x8ff50104, 0x37f80c00,
+0x3c160040, 0x3388021, 0x2b6a024, 0x34c40040,
+0x12800047, 0x9215000d, 0x32a80020, 0x15000002,
+0x34860080, 0x803021, 0x14c0009f, 0xafa60030,
+0x3c0d8008, 0x35a60080, 0x90cc0008, 0x318b0040,
+0x51600006, 0x3c068008, 0x240e0004, 0x122e00a8,
+0x240f0012, 0x122f0032, 0x3c068008, 0x34c40100,
+0x3c028000, 0x9447011a, 0x9619000e, 0x909f0008,
+0x8e180008, 0x30e3ffff, 0x3f9b004, 0x32b40004,
+0xafb6005c, 0xafa30058, 0x8e160004, 0x1280002e,
+0xafb80054, 0x34c30080, 0x90680008, 0x31050040,
+0x14a00025, 0x0, 0x8c700050, 0x2d09023,
+0x6400005, 0x0, 0x8c710034, 0x2d1a823,
+0x6a20167, 0x8ee20008, 0x12600006, 0x3c128000,
+0x3c150800, 0x8eb531f4, 0x26b60001, 0x3c010800,
+0xac3631f4, 0xae400044, 0x24030001, 0x8fbf0084,
+0x8fbe0080, 0x8fb7007c, 0x8fb60078, 0x8fb50074,
+0x8fb40070, 0x8fb3006c, 0x8fb20068, 0x8fb10064,
+0x8fb00060, 0x601021, 0x3e00008, 0x27bd0088,
+0xe000d28, 0x2021, 0xa000d75, 0x401821,
+0xa000d95, 0xc02021, 0xe0016ae, 0x2c02021,
+0x1440ffe1, 0x0, 0x3c0b8008, 0x35640080,
+0x8c8a0034, 0x2ca4823, 0x520001d, 0x0,
+0x3c1e0800, 0x8fde3100, 0x27d70001, 0x3c010800,
+0xac373100, 0x12600006, 0x2402021, 0x3c140800,
+0x8e9431f4, 0x26900001, 0x3c010800, 0xac3031f4,
+0xe0015e5, 0x3c1e8008, 0x37cd0080, 0x91b70025,
+0x2402021, 0x36ee0004, 0xe0015ef, 0xa1ae0025,
+0xe000cac, 0x2402021, 0xa000dca, 0x24030001,
+0x3c170801, 0x26f794f8, 0xa000d84, 0x3c1f8000,
+0x8c860030, 0x2c66023, 0x1980000c, 0x2419000c,
+0x908f004f, 0x3c140800, 0x8e943100, 0x32b500fc,
+0x35ed0001, 0x268e0001, 0x3c010800, 0xac2e3100,
+0xa08d004f, 0xafa00058, 0x2419000c, 0xafb90030,
+0x8c980030, 0x316a023, 0x1a80010b, 0x8fa30058,
+0x74f82a, 0x17e0ffd3, 0x0, 0x1074002a,
+0x8fa50058, 0x2d4b021, 0xb41023, 0x3044ffff,
+0xafa40058, 0x32a80002, 0x1100002e, 0x32ab0010,
+0x3c158008, 0x36b00080, 0x92160008, 0x32d30040,
+0x526000fb, 0x8ee20008, 0xe0015e5, 0x2402021,
+0x240a0018, 0xa20a0009, 0x92110005, 0x2409fffe,
+0x2402021, 0x2299024, 0xe0015ef, 0xa2120005,
+0x24040039, 0x2821, 0xe001689, 0x24060018,
+0xa000dca, 0x24030001, 0x92fe000c, 0x3c0a8008,
+0x35490080, 0x1ebb00, 0x8d270038, 0x36f10081,
+0x2402021, 0x3225f081, 0xe000c9b, 0x30c600ff,
+0xa000dc1, 0x0, 0x3aa70001, 0x30e30001,
+0x1460ffa4, 0x2d4b021, 0xa000e1d, 0x0,
+0x2402021, 0xe0016cb, 0x2002821, 0xa000d75,
+0x401821, 0x1160ff70, 0x3c0f8008, 0x3c0d8008,
+0x35ee0080, 0x8dc40038, 0x8fa30054, 0x8da60004,
+0x666023, 0x1d80ff68, 0x0, 0x64c023,
+0x7020001, 0xafa40054, 0x3c1f0800, 0x8fff31e4,
+0x33f90001, 0x13200015, 0x8fac0058, 0x3c078000,
+0x94e3011a, 0x10600012, 0x3c068008, 0xe0020f8,
+0x2402021, 0x3c030801, 0x90639529, 0x30640002,
+0x14800145, 0x0, 0x306c0004, 0x11800007,
+0x8fac0058, 0x306600fb, 0x3c010801, 0xa0269529,
+0x32b500fc, 0xafa00058, 0x8fac0058, 0x3c068008,
+0x34d30080, 0xafb40018, 0xafb60010, 0xafac0014,
+0x3c088000, 0x950b0120, 0x8e6f0030, 0x966a005c,
+0x8fa3005c, 0x8fbf0030, 0x3169ffff, 0x3144ffff,
+0x8fae0054, 0x1341021, 0x35054000, 0x64382b,
+0x45c821, 0x3e7c025, 0xafb90020, 0xafaf0028,
+0xafb80030, 0xafaf0024, 0xafa0002c, 0xafae0034,
+0x926d0008, 0x31b40008, 0x168000bb, 0x2002021,
+0x8ee20004, 0x40f809, 0x27a40010, 0x8faf0030,
+0x31f30002, 0x56600001, 0x32b500fe, 0x3c048008,
+0x349f0080, 0x93f90008, 0x33380040, 0x53000013,
+0x8fa40024, 0x8c850004, 0x8fa70054, 0x10a700d5,
+0x24040014, 0x32b00001, 0x1200000c, 0x8fa40024,
+0x2414000c, 0x1234011a, 0x2a2d000d, 0x11a00102,
+0x2413000e, 0x240e000a, 0x522e0001, 0x241e0008,
+0x8faf0024, 0x25e40001, 0xafa40024, 0x8faa0014,
+0x3c0b8008, 0x35650080, 0x8a4821, 0x8cb10030,
+0xaca90030, 0x90a4004e, 0x8ca70030, 0x3408fffc,
+0x881804, 0xe3f821, 0xacbf0034, 0x8fa60030,
+0x8fb90054, 0x8fb8005c, 0x30c20008, 0x1040000b,
+0x3389821, 0x8cac0020, 0x119300d3, 0x30c600ff,
+0x92ee000c, 0x8fa70034, 0x2402021, 0xe6b00,
+0x35b40080, 0xe000c9b, 0x3285f080, 0x3c028008,
+0x34500080, 0x8e0f0030, 0x1f13023, 0x18c00097,
+0x26480080, 0x3c070800, 0x8ce731e4, 0x2404ff80,
+0x1041824, 0x3118007f, 0x3c1f8000, 0x3c198004,
+0x30f10001, 0xafe30090, 0x12200006, 0x3192821,
+0x3c030801, 0x90639529, 0x30690008, 0x152000c6,
+0x306a00f7, 0x3c108008, 0x36040080, 0x908c004f,
+0x318b0001, 0x15600042, 0x0, 0x3c060800,
+0x8cc63198, 0x30ce0010, 0x51c00042, 0x30f90001,
+0x90af006b, 0x55e0003f, 0x30f90001, 0x24180001,
+0xa0b8006b, 0x3c118000, 0x9622007a, 0x24470064,
+0xa4870012, 0x3c0d8008, 0x35a50080, 0x90b40008,
+0x32900040, 0x16000004, 0x3c038008, 0x32ae0001,
+0x15c0008b, 0x0, 0x34640080, 0x8c860020,
+0x10d3000a, 0x34630100, 0x8c670000, 0x2c77823,
+0x19e00097, 0x8fbf0054, 0xac930020, 0x24130001,
+0xac760000, 0xafb30050, 0xac7f0004, 0x17c0004e,
+0x0, 0x8fa90050, 0x1520000b, 0x0,
+0x3c030801, 0x90639529, 0x306a0001, 0x1140002e,
+0x8fab0058, 0x306400fe, 0x3c010801, 0xa0249529,
+0xa000d75, 0x1821, 0xe000cac, 0x2402021,
+0xa000f13, 0x0, 0xa000e20, 0xa021,
+0x40f809, 0x24040017, 0xa000dca, 0x24030001,
+0x40f809, 0x24040016, 0xa000dca, 0x24030001,
+0x9094004f, 0x240dfffe, 0x28d2824, 0xa085004f,
+0x30f90001, 0x13200006, 0x3c048008, 0x3c030801,
+0x90639529, 0x307f0010, 0x17e00051, 0x306800ef,
+0x34900080, 0x240a0001, 0x2402021, 0xe0015e5,
+0xa60a0012, 0x92030025, 0x24090001, 0xafa90050,
+0x34620001, 0x2402021, 0xe0015ef, 0xa2020025,
+0xa000ef9, 0x3c0d8008, 0x1160fe83, 0x1821,
+0x8fa50030, 0x30ac0004, 0x1180fe2c, 0x8fbf0084,
+0xa000dcb, 0x24030001, 0x27a50038, 0xe000cb6,
+0xafa00038, 0x5440ff43, 0x8ee20004, 0x8fb40038,
+0x32900100, 0x5200ff3f, 0x8ee20004, 0x8fa3003c,
+0x8e6e0058, 0x6e6823, 0x5a3ff39, 0xae630058,
+0xa000e94, 0x8ee20004, 0xe0015e5, 0x2402021,
+0x3c038008, 0x34680080, 0x2402021, 0xe0015ef,
+0xa11e0009, 0x3c03021, 0x24040037, 0xe001689,
+0x2821, 0xa000f11, 0x8fa90050, 0x8fab0018,
+0x5960ff8d, 0x3c0d8008, 0xe0015e5, 0x2402021,
+0x920c0025, 0x24050001, 0xafa50050, 0x35820004,
+0x2402021, 0xe0015ef, 0xa2020025, 0xa000ef9,
+0x3c0d8008, 0x12240059, 0x2a230015, 0x1060004d,
+0x24090016, 0x2408000c, 0x5628ff27, 0x32b00001,
+0x3c0a8008, 0x914c001b, 0x2406ffbd, 0x241e000e,
+0x1865824, 0xa14b001b, 0xa000ea5, 0x32b00001,
+0x3c010801, 0xa0289529, 0xa000ef9, 0x3c0d8008,
+0x8cb50030, 0x8efe0008, 0x24040018, 0x26b60001,
+0x3c0f809, 0xacb60030, 0x3c030801, 0x90639529,
+0x30770001, 0x16e0ff81, 0x306a0001, 0x8fb20030,
+0xa000d75, 0x32430004, 0x3c108000, 0x9605011a,
+0x50a0ff2b, 0x34c60010, 0xa000ec8, 0x92ee000c,
+0x8c620000, 0x1456ff6d, 0x0, 0x8c780004,
+0x8fb90054, 0x3388823, 0x621ff63, 0x8fbf0054,
+0xa000f0e, 0x0, 0x3c010801, 0xa02a9529,
+0xa000f30, 0x30f90001, 0x1633ff02, 0x8faf0024,
+0xa000eb0, 0x241e0010, 0xe0015e5, 0x2402021,
+0x3c0b8008, 0x35680080, 0x91090025, 0x240a0001,
+0xafaa0050, 0x35330004, 0x2402021, 0xe0015ef,
+0xa1130025, 0x3c050801, 0x90a59529, 0x30a200fd,
+0x3c010801, 0xa0229529, 0xa000e6d, 0x401821,
+0x2411000e, 0x53d1feea, 0x241e0010, 0xa000eaf,
+0x241e0016, 0x5629fedc, 0x32b00001, 0x3c0a8008,
+0x914c001b, 0x2406ffbd, 0x241e0010, 0x1865824,
+0xa14b001b, 0xa000ea5, 0x32b00001, 0xa000ea4,
+0x241e0012, 0x3c038000, 0x8c6201b8, 0x440fffe,
0x24040800, 0xac6401b8, 0x3e00008, 0x0,
-0x3c058008, 0x94a20048, 0x3084ffff, 0x10400019,
-0x24840012, 0x94a90048, 0x3c038000, 0x3128ffff,
-0x104382a, 0x10e00013, 0x34660180, 0x946d0120,
-0x8f8c0004, 0x240b001a, 0x31aaffff, 0x31834000,
-0xa0cb000b, 0x10600010, 0x2544fffe, 0x94af0048,
-0x31eeffff, 0x1c4282b, 0x14a0000c, 0x8f98000c,
-0xa4c40014, 0x8f86000c, 0x34c20001, 0x3e00008,
-0xaf82000c, 0x3c078000, 0x24040003, 0x34e20180,
-0x3e00008, 0xa044000b, 0x8f98000c, 0x2419fffe,
-0x3191024, 0x3e00008, 0xaf82000c, 0x27bdffd8,
-0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014,
-0xafbf0024, 0xafb00010, 0x801821, 0x30b3ffff,
-0x30d2ffff, 0x30f4ffff, 0x3c118000, 0x8e2201b8,
-0x440fffe, 0x36300180, 0xae030000, 0x2402021,
-0xe000edd, 0xae230020, 0x8f86000c, 0x8f850004,
-0x8f830000, 0x30c48000, 0xa613000c, 0xa612000e,
-0xa6050010, 0xae030028, 0xa6140008, 0x1080000e,
-0x3c0f8000, 0x962c0116, 0x318bfffc, 0x256a0004,
-0x1514821, 0x8d284000, 0x3107ffff, 0x14e00007,
-0x2414bfff, 0x3c0effff, 0x35cd7fff, 0xcd3024,
-0xaf86000c, 0x3c0f8000, 0x2414bfff, 0x35f10180,
-0xd49824, 0xa6330026, 0x8df20104, 0xae32002c,
-0x3c061000, 0xade601b8, 0x8fbf0024, 0x8fb40020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014,
-0x3c118000, 0x804021, 0xafb40020, 0xafb00010,
-0x30d4ffff, 0x36300180, 0x2802021, 0xae080000,
-0xae280020, 0xafb3001c, 0xafb20018, 0x30f3ffff,
-0xafbf0024, 0xe000edd, 0x30b2ffff, 0x8f85000c,
-0x8f830004, 0x2406bfff, 0xa62024, 0xa612000c,
-0xa614000e, 0xa6130008, 0xa6040026, 0xa6030010,
-0x3c021000, 0xae2201b8, 0x8fbf0024, 0x8fb40020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x3c028000, 0x34450180,
-0x3c048000, 0x8c8301b8, 0x460fffe, 0x24072000,
-0x24060002, 0xa4a70008, 0xa0a6000b, 0xa4a00010,
-0x3c051000, 0xac8501b8, 0x3e00008, 0x0,
-0x3c058000, 0x34a40070, 0x8c8a0000, 0x90a60112,
-0x8f840004, 0x27bdfff0, 0x30c300ff, 0x31882,
-0x30820100, 0x3821, 0x10400039, 0x24660003,
-0x30874000, 0x50e00039, 0x30882000, 0x61080,
-0x45c821, 0x8f2f4000, 0x24780004, 0x187080,
-0xafaf0000, 0x1c56821, 0x8dac4000, 0xafac0004,
-0x94ab0116, 0x3169fffc, 0x1254021, 0x8d054000,
-0xafa50008, 0x8fa90008, 0x3021, 0x2821,
-0x3c070800, 0x24e70100, 0xa000f9e, 0x24080008,
-0x90420000, 0x24a50001, 0x2cad000c, 0x62c821,
-0x19c080, 0x3077821, 0x8dee0000, 0x11a00006,
-0xce3026, 0x3a51021, 0x14a8fff5, 0x51a00,
-0x5520fff4, 0x90420000, 0x3c048000, 0x34870070,
-0x3c050800, 0x8ca53104, 0x8ce30000, 0x2ca80020,
-0x11000009, 0x6a3823, 0x55880, 0x3c0c0800,
-0x258c3108, 0x16c4821, 0x24aa0001, 0xad270000,
-0x3c010800, 0xac2a3104, 0xaf860000, 0x24070001,
-0xe01021, 0x3e00008, 0x27bd0010, 0x1100fffc,
-0x3821, 0x66080, 0x1855821, 0x8d644000,
-0x24690004, 0x93880, 0xafa40000, 0xe51821,
-0x8c664000, 0xafa00008, 0xa000f8e, 0xafa60004,
-0x3c020800, 0x8c420038, 0x27bdffd8, 0xafb40020,
-0xafb20018, 0xafbf0024, 0xafb3001c, 0xafb10014,
-0xafb00010, 0x3c140800, 0x26940038, 0x14400002,
-0x2452ffff, 0x9021, 0x8f850004, 0x30a34000,
-0x1060000f, 0x30a98000, 0x3c060020, 0xa62024,
-0x1080000b, 0x8f87000c, 0x2408bfff, 0xa82824,
-0x34e31000, 0xaf850004, 0x30af2000, 0x15e0000a,
-0x3c110004, 0x2413ffbf, 0xa000fef, 0x731024,
-0x15200062, 0x3c0b0020, 0x30af2000, 0x11e0fff9,
-0x8f83000c, 0x3c110004, 0xb18024, 0x1200fff6,
-0x2413ffbf, 0x34620040, 0x30b80100, 0x1300000f,
-0xaf82000c, 0x3c1f0020, 0xbfc824, 0x13200005,
-0x3c0a8000, 0x3c030004, 0xa31024, 0x104000c8,
-0x0, 0x9549011e, 0x9548011c, 0x3126ffff,
-0x83c00, 0xc72025, 0xaf840000, 0x3c0d8000,
-0x95ac010c, 0x30ab1000, 0x11600008, 0x3186ffff,
-0x30ae0020, 0x15c00006, 0x24110005, 0x3c101000,
-0xb07824, 0x15e00073, 0x3c1f0c00, 0x24110001,
-0x30a20100, 0x54400009, 0x3c0c0001, 0x8f830014,
-0x54600006, 0x3c0c0001, 0x8f87000c, 0x30e44000,
-0x1080009a, 0x3c0a1f01, 0x3c0c0001, 0xac3024,
-0x14c0006c, 0x3c108000, 0x8f84000c, 0x30934000,
-0x12600006, 0x3c031000, 0x3c190f00, 0xb9c024,
-0x1300008b, 0x3c1f8000, 0x3c031000, 0xa31024,
-0x1040002c, 0x3c068000, 0x3c070800, 0x8ce70030,
-0x14e00073, 0x30884000, 0x30a60100, 0x10c00098,
-0x3c0e0f00, 0xae6824, 0x3c0c0200, 0x11ac0094,
-0x8f930000, 0x2728024, 0x2147821, 0x91f40004,
-0x26920004, 0x1221c0, 0x3c0e8000, 0x95c6010e,
-0x36270002, 0x24d40004, 0x3286ffff, 0x24050002,
-0xe000f04, 0x0, 0x8fbf0024, 0x8fb40020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x1021, 0x3e00008, 0x27bd0028, 0xab5024,
-0x1140ff9e, 0x30af2000, 0x8f8c000c, 0x3c0effff,
-0x35cd7fff, 0xad2824, 0x35838000, 0xa000fdf,
-0xaf850004, 0x8cd04000, 0x320f0100, 0x11e0003c,
-0x30b80100, 0x3c100800, 0x8e100024, 0x13000014,
-0x32330004, 0x3c020f00, 0xa2f824, 0x3c190200,
-0x13f9000f, 0x8f830000, 0x94c9010e, 0x2203821,
-0x725824, 0x1745021, 0x91480004, 0x25240004,
-0x3086ffff, 0x25140004, 0x1421c0, 0x24050002,
-0xe000f04, 0x2412fffe, 0x2128024, 0x3231fffb,
-0x24070001, 0x1207006f, 0x32060001, 0x14c00090,
-0x3c0e8000, 0x320f0004, 0x11e00004, 0x8f980004,
-0x33100800, 0x16000078, 0x3c1f8000, 0x5660ffc7,
-0x8fbf0024, 0xe000f63, 0x0, 0xa001040,
-0x8fbf0024, 0x3c190bff, 0xbfc024, 0x3733ffff,
-0x278882b, 0x5220ff8a, 0x24110001, 0xa00100d,
-0x24110005, 0x3c0e0800, 0x8dce00d8, 0x960f010e,
-0x24040080, 0x25cd0001, 0x31e6ffff, 0x24050002,
-0x3c010800, 0xac2d00d8, 0xa00103d, 0x24070003,
-0x3c120800, 0x8e520024, 0x32420001, 0x1040ffab,
-0x8fbf0024, 0x94c6010e, 0x36270002, 0x2021,
-0x24d40004, 0x3286ffff, 0xa00103d, 0x24050002,
-0x1100ff8e, 0x30a60100, 0x3c0b0f00, 0xab5024,
-0x3c090100, 0x12a202b, 0x1480ff88, 0x0,
-0x3c058000, 0x94a6010e, 0x36270002, 0x24040080,
-0x24d40004, 0x3286ffff, 0xa00103d, 0x24050002,
-0x97e30116, 0xa001024, 0x3c031000, 0xaa4824,
-0x3c081000, 0x1528ff65, 0x3c0c0001, 0x30cb0200,
-0x1560ff63, 0xac3024, 0x3c148000, 0x9692010e,
-0x36270002, 0x2021, 0x26450004, 0x30a6ffff,
-0xe000f3f, 0x24050002, 0xa001040, 0x8fbf0024,
-0xe000f71, 0x0, 0xa001000, 0x8f850004,
-0x0, 0x3c060800, 0x8cc600d0, 0x51602,
-0x3050000f, 0x38df0001, 0x2ff90001, 0x2e03000c,
-0x323c024, 0x1700ff68, 0x1021c0, 0x2608fffc,
-0x2d070004, 0x14e00007, 0x3c0e8000, 0x38ca0002,
-0x2d490001, 0x1232024, 0x5080000e, 0x53242,
-0x3c0e8000, 0x95c6010e, 0x2021, 0xa00103a,
-0x36270002, 0x32330004, 0x52600001, 0x36310002,
-0x3c0c8000, 0x9586010e, 0x2203821, 0xa001099,
-0x2021, 0x10182b, 0xc35824, 0x1560000f,
-0x3c058000, 0x1021c0, 0x3c0e8000, 0x95c6010e,
-0xa00103a, 0x36270002, 0x97f9010e, 0x2203821,
-0x24040100, 0x27310004, 0x3226ffff, 0xe000f04,
-0x24050002, 0xa001078, 0x0, 0x94ad010e,
-0x2021, 0x24050002, 0x25ac0004, 0x3186ffff,
-0xe000f04, 0x3227fffb, 0xa0010eb, 0x1021c0,
-0x95c5010e, 0x2203821, 0x2021, 0x24ad0004,
-0x31a6ffff, 0xe000f04, 0x24050002, 0xa001072,
-0x3231fffb, 0x3c058000, 0x8ca70148, 0x24030004,
-0x34a60180, 0x72402, 0x308200ff, 0x10430010,
-0x3c048000, 0x8c8901b8, 0x520fffe, 0x0,
-0x8c8f0148, 0x240d0002, 0x3c0a1000, 0xf7402,
-0xa4ce0008, 0xa0cd000b, 0x8c8c0148, 0xa4cc0010,
-0x8c8b0144, 0xaccb0024, 0x3e00008, 0xac8a01b8,
-0x8ca40140, 0x3c038000, 0xc02821, 0x8c6601b8,
-0x4c0fffe, 0x2408001c, 0xaca40000, 0xa0a8000b,
-0x3c051000, 0xac6501b8, 0x3e00008, 0x0,
-0x27bdffe8, 0xafb00010, 0xafbf0014, 0x3c10600c,
-0x8e0d5000, 0x240eff7f, 0x24060003, 0x1ae6024,
-0x3588380c, 0x3c058000, 0xae085000, 0xaca60008,
-0x3c010800, 0xac200020, 0xe001555, 0x0,
-0x3c086016, 0x8d0a0000, 0x3c0bffff, 0x3c090010,
-0x35238051, 0x3c046000, 0x14b3824, 0x3c025353,
-0xae03537c, 0x34842020, 0x3c050800, 0x24a57908,
-0x2406000a, 0x10e20009, 0x35037c00, 0x8c7f007c,
-0x8c790078, 0x8fb00010, 0xaf9f0010, 0x8fbf0014,
-0x27bd0018, 0xa0013b1, 0xaf990008, 0x8d0f0004,
-0x3c186000, 0x8fb00010, 0x1f81821, 0x8c7f007c,
-0x8c790078, 0xaf9f0010, 0x8fbf0014, 0x27bd0018,
-0xa0013b1, 0xaf990008, 0x3c048000, 0x8c834000,
-0x3402ffff, 0x1062003a, 0x0, 0x8c874000,
-0x30e50100, 0x10a00021, 0x0, 0x9487010e,
-0x3c020800, 0x8c4200ec, 0x9485010e, 0x3c0d0800,
-0x8dad31cc, 0x30e3ffff, 0x3c180800, 0x8f1800e8,
-0x3c090800, 0x8d2931c8, 0x436021, 0x30abffff,
-0x183782b, 0xc821, 0x1ab1821, 0x5021,
-0x3197021, 0x6b302b, 0x12a4021, 0x1cf2021,
-0x1061021, 0x3c010800, 0xac2c00ec, 0x3c010800,
-0xac2400e8, 0x3c010800, 0xac2331cc, 0x3c010800,
-0xac2231c8, 0x3e00008, 0x0, 0x8c884000,
-0x8f8c0008, 0x110c0032, 0x3c0d8000, 0x95ab010e,
-0x3c0a0800, 0x8d4a00e4, 0x3c080800, 0x8d0800e0,
-0x3169ffff, 0x1492821, 0x3021, 0xa9602b,
-0x1063821, 0xec1021, 0x3c010800, 0xac2500e4,
-0x3c010800, 0xac2200e0, 0x3e00008, 0x0,
-0x9483010e, 0x9482010e, 0x3c190800, 0x8f3900f4,
-0x3c090800, 0x8d2931cc, 0x3c0e0800, 0x8dce00f0,
-0x3c080800, 0x8d0831c8, 0x3078ffff, 0x304bffff,
-0x3382821, 0x12b1821, 0x7821, 0x5021,
-0xb8682b, 0x1cf6021, 0x6b302b, 0x10a3821,
-0x18d2021, 0xe61021, 0x3c010800, 0xac2500f4,
-0x3c010800, 0xac2400f0, 0x3c010800, 0xac2331cc,
-0x3c010800, 0xac2231c8, 0x3e00008, 0x0,
-0x8c894004, 0x8f860010, 0x1526ffcc, 0x3c0d8000,
-0x9483010e, 0x3c190800, 0x8f3931bc, 0x3c0e0800,
-0x8dce31b8, 0x3078ffff, 0x3385821, 0x7821,
-0x178202b, 0x1cf6821, 0x1a45021, 0x3c010800,
-0xac2b31bc, 0x3c010800, 0xac2a31b8, 0x3e00008,
-0x0, 0x27bdffe8, 0x3c058000, 0xafbf0014,
-0xafb00010, 0x8cb00128, 0xacb00020, 0x8ca30104,
-0x8ca40100, 0xaf830004, 0xe000ed6, 0xaf84000c,
-0xe00115f, 0x0, 0x3c020800, 0x8c4200c0,
-0x10400026, 0x8f840004, 0x3c070800, 0x8ce700c4,
-0x24e60001, 0x3c010800, 0xac2600c4, 0x3c028000,
-0x8c440124, 0x3c1f6020, 0xafe40014, 0x0,
-0x3c068000, 0x3c034000, 0xacc30138, 0x0,
-0x12000013, 0x8fbf0014, 0x260f0140, 0x26190080,
-0x2404ff80, 0x1e4c024, 0x324f824, 0x1f6940,
-0x332e007f, 0x185940, 0x31ec007f, 0x3c0a2000,
-0x35480002, 0x1ae3825, 0x16c4825, 0x1288025,
-0xe82825, 0xacc50830, 0xacd00830, 0x8fbf0014,
-0x8fb00010, 0x3e00008, 0x27bd0018, 0x3c090010,
-0x894024, 0x1100000f, 0x8f83000c, 0x240dbfff,
-0x6d6024, 0x11800007, 0x240f87ff, 0x6f7024,
-0x15c00013, 0x3c190060, 0x99c024, 0x13000010,
-0x0, 0xe000cd2, 0x0, 0xa001221,
-0x0, 0x3c0b0800, 0x8d6b0020, 0x256a0001,
-0x3c010800, 0xac2a0020, 0xe000fc5, 0x2021,
-0x1040ffcc, 0x3c068000, 0xa0011e9, 0x3c028000,
-0xe00128e, 0x0, 0xa001221, 0x0,
-0x27bdffe8, 0x3c028000, 0xafbf0010, 0x8c460140,
-0x3c037000, 0x3c054000, 0xac460020, 0x8c440148,
-0x832024, 0x10850013, 0xa4102b, 0x1040000b,
-0x3c072000, 0x3c086000, 0x10880017, 0x0,
-0x3c0a4000, 0x3c098000, 0xad2a0178, 0x0,
-0x8fbf0010, 0x3e00008, 0x27bd0018, 0x5487fff9,
-0x3c0a4000, 0xe00110a, 0x0, 0xa00123a,
-0x3c0a4000, 0xe0012b4, 0x0, 0x3c0a4000,
-0x3c098000, 0xad2a0178, 0x0, 0x8fbf0010,
-0x3e00008, 0x27bd0018, 0xe001d6f, 0x0,
-0xa00123a, 0x3c0a4000, 0x27bdffe0, 0xafb20018,
-0x3c128000, 0xafb10014, 0xafbf001c, 0xafb00010,
-0xe00112d, 0x36510070, 0x8e260000, 0xaf860018,
-0x8e280000, 0x3c0b0800, 0x8d6b00fc, 0x3c070800,
-0x8ce700f8, 0x1066023, 0x16c2821, 0x4821,
-0xac302b, 0xe91821, 0x662021, 0x3c010800,
-0xac2500fc, 0x3c010800, 0xac2400f8, 0x8e500000,
-0x32020003, 0x1040ffee, 0x1003021, 0x8e260000,
-0x3c050800, 0x8ca500fc, 0x3c1f0800, 0x8fff00f8,
-0xc81823, 0xa37821, 0x1021, 0x1e3c82b,
-0x3e2c021, 0x3197021, 0x320d0001, 0x3c010800,
-0xac2f00fc, 0xaf880018, 0x3c010800, 0xac2e00f8,
-0x15a00008, 0x0, 0x32080002, 0x1100ffd6,
-0x0, 0xe001229, 0x0, 0xa00125b,
-0x0, 0xe0011d2, 0x0, 0xa001284,
-0x32080002, 0x3c038000, 0x8c640100, 0x3082003e,
-0x14400008, 0x0, 0xac600048, 0x8c660100,
-0x30c507c0, 0x10a00005, 0x0, 0xac60004c,
-0xac600050, 0x3e00008, 0x24020001, 0xac600054,
-0xac600040, 0x8c680100, 0x31073800, 0x10e0fff9,
-0x0, 0x24020001, 0x3e00008, 0xac600044,
-0x3c039000, 0x34620001, 0x822025, 0x3c038000,
-0xac640020, 0x8c650020, 0x4a0fffe, 0x0,
-0x3e00008, 0x0, 0x3c028000, 0x34430001,
-0x832025, 0x3e00008, 0xac440020, 0x27bdffd8,
-0xafb10014, 0x3c048000, 0xafbf0020, 0xafb3001c,
-0xafb20018, 0xafb00010, 0x8c920140, 0x8c900148,
-0x2402000e, 0x108c02, 0x322300ff, 0x10620059,
-0x2042824, 0x2866000f, 0x10c00013, 0x286a0037,
-0x24070006, 0x1067008e, 0x28680007, 0x5100002d,
-0x24040009, 0x10600078, 0x3c068000, 0x24090001,
-0x106900b0, 0x0, 0xd, 0x8fbf0020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x11400059, 0x240d0038,
-0x286b0035, 0x11600005, 0x3c058000, 0x240c001f,
-0x146cfff1, 0x0, 0x3c058000, 0x8cb801b8,
-0x700fffe, 0x34b90180, 0xaf320000, 0x241f0001,
-0x24120002, 0x3c021000, 0xaf200004, 0xa7310008,
-0xa33f000a, 0xa332000b, 0xa7300010, 0xaf200024,
-0xaf200028, 0xaca201b8, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0028, 0x10640023, 0x2405000b, 0x1465ffd6,
-0x3218ffff, 0x17000020, 0x3c058000, 0x8f93fed4,
-0x927f0005, 0x33f90004, 0x1720ffcf, 0x0,
-0xe0012a5, 0x2402021, 0x92690005, 0x2402021,
-0x35280004, 0xe0012af, 0xa2680005, 0x92670005,
-0x30e20004, 0x14400002, 0x0, 0xd,
-0x926b0000, 0x24060020, 0x316a00ff, 0x1546000a,
-0x3c058000, 0x8ca401b8, 0x480fffe, 0x34ad0180,
-0x240e0005, 0x3c0c1000, 0xadb20000, 0xa1ae000b,
-0xacac01b8, 0x3c058000, 0x8ca301b8, 0x460fffe,
-0x34af0180, 0x24130002, 0xade00000, 0xadf20004,
-0xa5f10008, 0xa1f3000a, 0xa1f3000b, 0xa5f00010,
-0xade00024, 0x8cb10144, 0x3c101000, 0xadf10028,
-0xacb001b8, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028,
-0x106dffad, 0x240e0080, 0x146eff9b, 0x0,
-0x3c058000, 0x8ca301b8, 0x460fffe, 0x34af0180,
-0x24120002, 0xa1f2000b, 0xa5f10008, 0xa5f00010,
-0x8cb30144, 0x3c021000, 0xa5f30012, 0xaca201b8,
-0xa0012f0, 0x8fbf0020, 0x8cc301b8, 0x460fffe,
-0x34d30180, 0xae720000, 0xae600004, 0x24120001,
-0xa6710008, 0x24110002, 0xa272000a, 0xa271000b,
-0xa6700010, 0x8cd00144, 0x3c0f1000, 0xae700024,
-0xae600028, 0xaccf01b8, 0xa00132b, 0x8fbf0020,
-0x3c038000, 0x8c6601b8, 0x4c0fffe, 0x34620180,
-0x3c060800, 0x90c67ab8, 0xac520000, 0x10c00003,
-0x3821, 0x3c070800, 0x8ce77ac0, 0x3c058000,
-0x34aa0180, 0x24040002, 0x34cc0001, 0xac470004,
-0xa5510008, 0xa14c000a, 0xa144000b, 0xa5500010,
-0x8cab0144, 0x2021, 0x1402821, 0xad4b0024,
-0x10c00003, 0x8fbf0020, 0x3c040800, 0x8c847abc,
+0x805021, 0x30a5ffff, 0x30c6ffff, 0x3c048000,
+0x8c8201b8, 0x440fffe, 0x34880180, 0xad0a0000,
+0x3c078008, 0xac8a0020, 0x94e30048, 0x3067ffff,
+0x10e00042, 0x3c0d8000, 0x24ab0012, 0xeb482b,
+0x5120003f, 0x24040003, 0x34820100, 0x94590020,
+0x8f890000, 0x2404001a, 0x3338ffff, 0x270bfffe,
+0xeb782b, 0x39ee0001, 0x96b82, 0x1ae6024,
+0xa104000b, 0x51800049, 0x8f8b0004, 0x8f830004,
+0xa50b0014, 0x34680001, 0xaf880004, 0x30ce0040,
+0x15c00033, 0x3c048000, 0x3c028000, 0x34420180,
+0xa445000e, 0x3c078000, 0x34ec0180, 0xa585001a,
+0x8f85000c, 0x310b8000, 0xa5890010, 0xad850028,
+0xa5860008, 0x1160000f, 0x8f850014, 0x34ea0100,
+0x954e0016, 0x31cdfffc, 0x25a40004, 0x871821,
+0x8c674000, 0x30e6ffff, 0x14c00007, 0x3c048000,
+0x3c18ffff, 0x370f7fff, 0x10f4024, 0xaf880004,
+0x8f850014, 0x3c048000, 0x2402bfff, 0x34830180,
+0x102c824, 0xa4790026, 0x10a00004, 0xac69002c,
+0x54402, 0xa4650010, 0xa4680026, 0x3c091000,
+0xac8901b8, 0x3e00008, 0x0, 0x24040003,
+0x35ac0180, 0x30ce0040, 0x8f890000, 0x8f880004,
+0xa184000b, 0x51c0ffd1, 0x3c028000, 0x3c048000,
+0xac8a0020, 0x3c0f8008, 0x95ea0040, 0x3143ffff,
+0x50600008, 0x34820180, 0xa3c02b, 0x57000001,
+0xa01821, 0x34990180, 0xa723000e, 0xa001005,
+0x3c078000, 0xa001003, 0x30c6ffbf, 0x2407fffe,
+0x1674024, 0xa000ffe, 0xaf880004, 0x27bdffe8,
+0x8fa20028, 0x30a5ffff, 0x30c6ffff, 0xafbf0010,
+0xaf87000c, 0xaf820014, 0xaf800004, 0xe000fdb,
+0xaf800000, 0x8fbf0010, 0x27bd0018, 0x3e00008,
+0xaf800014, 0x3c068000, 0x34c40070, 0x34c70100,
+0x8c8a0000, 0x90e50012, 0x8f840000, 0x27bdfff0,
+0x30a300ff, 0x31882, 0x30824000, 0x10400037,
+0x24650003, 0x5c880, 0x326c021, 0x8f0e4000,
+0x246f0004, 0xf6880, 0xafae0000, 0x1a66021,
+0x8d8b4000, 0xafab0004, 0x94e90016, 0x3128fffc,
+0x1063821, 0x8ce64000, 0xafa60008, 0x8fa90008,
+0x3021, 0x2821, 0x3c070800, 0x24e70100,
+0xa00107e, 0x24080008, 0x90590000, 0x24a50001,
+0x2cac000c, 0x79c021, 0x187880, 0x1e77021,
+0x8dcd0000, 0x11800006, 0xcd3026, 0x3a51021,
+0x14a8fff5, 0x51a00, 0x5520fff4, 0x90590000,
+0x3c048000, 0x34870070, 0x3c050800, 0x8ca53104,
+0x8ce30000, 0x2ca20020, 0x10400009, 0x6a3823,
+0x54880, 0x3c0b0800, 0x256b3108, 0x12b4021,
+0x24aa0001, 0xad070000, 0x3c010800, 0xac2a3104,
+0xc01021, 0x3e00008, 0x27bd0010, 0x30822000,
+0x1040000b, 0x55880, 0x1664821, 0x8d244000,
+0x24680004, 0x83880, 0xafa40000, 0xe61821,
+0x8c654000, 0xafa00008, 0xa00106e, 0xafa50004,
+0xd, 0xa00106f, 0x8fa90008, 0x27bdffd8,
+0x3c058000, 0xafb10014, 0xafb00010, 0xafbf0024,
+0xafb40020, 0xafb3001c, 0xafb20018, 0x8f870000,
+0x34a40100, 0x9483000e, 0x30e24000, 0x8021,
+0x10400010, 0x3071ffff, 0x3c080020, 0xe83024,
+0x10c0000d, 0x30eb8000, 0x8f890004, 0x240abfff,
+0xea3824, 0x35231000, 0xaf870000, 0x30f32000,
+0x1660000b, 0x3c180004, 0x2419ffbf, 0xa0010cf,
+0x791024, 0x30eb8000, 0x1560004d, 0x3c0d0020,
+0x30f32000, 0x1260fff8, 0x8f830004, 0x3c180004,
+0xf8a024, 0x1280fff5, 0x2419ffbf, 0x34620040,
+0x30ff0100, 0x13e00010, 0xaf820004, 0x8f820028,
+0x10400006, 0x3c0e8000, 0x3c040020, 0xe41824,
+0x146000ce, 0x3c060004, 0x3c0e8000, 0x35cd0100,
+0x95ac001e, 0x95ab001c, 0x3189ffff, 0xb5400,
+0x12a4025, 0xaf88000c, 0x3c138000, 0x36740100,
+0x9692000c, 0x8e634000, 0x340fffff, 0x106f0084,
+0x3244ffff, 0x30780100, 0x57000001, 0x24100010,
+0x30f91000, 0x53200008, 0x36120001, 0x30ff0020,
+0x17e00073, 0x3c031000, 0xe31024, 0x1440006a,
+0x3c0a0c00, 0x36120001, 0x30ec0100, 0x1580000b,
+0x3c060001, 0x8f880004, 0x310d4000, 0x15a00008,
+0xe62824, 0x3c131f01, 0xf37824, 0x3c0e1000,
+0x11ee00ae, 0x30940200, 0x3c060001, 0xe62824,
+0x10a00019, 0x3c191000, 0x3c040800, 0x8c840024,
+0x30940002, 0x168000d9, 0x24030001, 0x8fbf0024,
+0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x601021, 0x3e00008, 0x27bd0028,
+0xed6024, 0x1180ffb3, 0x30f32000, 0x8f8e0004,
+0x3c12ffff, 0x364f7fff, 0xef3824, 0x35c38000,
+0xa0010be, 0xaf870000, 0xf9c024, 0x1700004e,
+0x2021, 0xaf800010, 0x3c038000, 0x34650100,
+0x94ae000e, 0x8f910010, 0x31caffff, 0x108000c6,
+0x25530004, 0x30ef0100, 0x15e00070, 0x3c180f00,
+0x3a280002, 0x2e7003ef, 0x2d190001, 0x3a1f0001,
+0x33f2824, 0x14a00022, 0x24040001, 0x3c030800,
+0x8c6300d0, 0x2e25000c, 0x1121c0, 0x386c0001,
+0x2d8b0001, 0x1651024, 0x14400014, 0x3270ffff,
+0x262dfffc, 0x2da40004, 0x14800103, 0x2021,
+0x386a0002, 0x2d460001, 0xc51824, 0x546000ff,
+0x2002821, 0x262ffff8, 0x2dee0004, 0x15c00007,
+0x0, 0x7a242, 0x11c02b, 0x2984824,
+0x15200109, 0x2002821, 0x1121c0, 0x2002821,
+0x36460002, 0xe000fdb, 0x0, 0x2021,
+0x801821, 0x8fbf0024, 0x8fb40020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x601021,
+0x3e00008, 0x27bd0028, 0x3c090bff, 0xea4024,
+0x3526ffff, 0xc8282b, 0x50a0ff93, 0x36120001,
+0x3c0b0800, 0x8d6b002c, 0x36120005, 0x25700001,
+0x3c010800, 0xac30002c, 0xa0010f6, 0x30ec0100,
+0xa0010eb, 0x24100020, 0x71602, 0x305f000f,
+0x1f80c0, 0x3c030801, 0x24639478, 0x2032021,
+0x1080ffad, 0xaf9f0010, 0x90880000, 0x5100ffab,
+0x3c038000, 0x3c0d8000, 0x35a90100, 0x952c000e,
+0x240b0003, 0x2403021, 0x318affff, 0x25450004,
+0x110b00d9, 0x5021, 0x90880001, 0x24140002,
+0x311100ff, 0x123400bf, 0x30f80040, 0x310300ff,
+0x24080001, 0x106800c8, 0x30e20040, 0x8c8a0004,
+0x8f8b0024, 0x55600006, 0x34c60002, 0x254dfe00,
+0x2dac0381, 0x55800001, 0x36460040, 0x34c60002,
+0x1402021, 0x30a5ffff, 0xe000fdb, 0x30c6ffff,
+0x4021, 0xa00110a, 0x1001821, 0xf8a024,
+0x3c090200, 0x1289ff8f, 0x3a280002, 0x90b10013,
+0x3270ffff, 0x2002821, 0x322700ff, 0x24f30004,
+0x1321c0, 0xa001150, 0x36460002, 0xe62824,
+0x14a0ff32, 0x3c0e8000, 0xe001054, 0x3c138000,
+0x8f870000, 0xa0010e2, 0xaf82000c, 0x1680ff53,
+0x3c060001, 0x26240004, 0x3085ffff, 0x36460002,
+0x3c038000, 0x8c7101b8, 0x620fffe, 0x8f890008,
+0x346a0180, 0xad400000, 0x112000b2, 0x3c0d8000,
+0x24b80012, 0x138902b, 0x124000af, 0x240c0003,
+0x34700100, 0x96030020, 0x2402001a, 0x30f94000,
+0x307fffff, 0xa142000b, 0x132000ab, 0x27e3fffe,
+0x123582b, 0x156000a9, 0x2409fffe, 0x35080001,
+0xa5430014, 0xaf880004, 0x3c0e8000, 0x2413bfff,
+0x1137824, 0x35c80180, 0xa505000e, 0xa505001a,
+0xa5060008, 0xa50f0026, 0xa5070010, 0x3c071000,
+0xadc701b8, 0x1821, 0x8fbf0024, 0x8fb40020,
0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3c0e1000, 0x3c0d8000, 0x27bd0028, 0xaca40028,
-0xadae01b8, 0x3c010800, 0xa0207ab8, 0x3e00008,
-0x0, 0x10a0000b, 0x3c068000, 0x8c980144,
-0x24190002, 0x3c010800, 0xa0397ab8, 0x3c010800,
-0xac327ac0, 0x3c010800, 0xac387abc, 0xa00132b,
-0x8fbf0020, 0x8cdf01b8, 0x7e0fffe, 0x34c70180,
-0x24090002, 0xace00000, 0xacf20004, 0xa4f10008,
-0xa0e9000a, 0xa0e9000b, 0xa4f00010, 0xace00024,
-0x8cc80144, 0x3c021000, 0xace80028, 0xacc201b8,
-0xa00132b, 0x8fbf0020, 0x27bdffe8, 0xafbf0010,
-0xe000ed6, 0x0, 0x3c028000, 0x8fbf0010,
-0x2021, 0xac400180, 0xa000fc5, 0x27bd0018,
-0x3084ffff, 0x30a5ffff, 0x10800007, 0x1821,
-0x30820001, 0x10400002, 0x42042, 0x651821,
-0x1480fffb, 0x52840, 0x3e00008, 0x601021,
-0x10c00007, 0x0, 0x8ca20000, 0x24c6ffff,
-0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004,
-0x3e00008, 0x0, 0x10a00008, 0x24a3ffff,
-0xac860000, 0x0, 0x0, 0x2402ffff,
-0x2463ffff, 0x1462fffa, 0x24840004, 0x3e00008,
-0x0, 0x27bdffe0, 0xafb20018, 0xafb10014,
-0xafb00010, 0xafbf001c, 0x9486000c, 0xa09021,
-0x24900014, 0x61b02, 0x31080, 0x448821,
-0x3021, 0xa02021, 0xe0013bb, 0x24050005,
-0x211202b, 0x10800012, 0x1021, 0x92030000,
-0x2c650009, 0x50a00009, 0x92020001, 0x34880,
-0x3c0a0800, 0x254a793c, 0x12a4021, 0x8d070000,
-0xe00008, 0x0, 0x92020001, 0x2028021,
-0x211202b, 0x5480fff2, 0x92030000, 0x1021,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0xa0013d5, 0x26100001,
-0x920c0001, 0x240b000c, 0x158b0040, 0x2307023,
-0x2dcd000a, 0x15a0003d, 0x26080006, 0x8e430000,
-0x26020002, 0x34640100, 0xae440000, 0x921f0002,
-0x90590001, 0x904e0002, 0x904b0003, 0x1f7e00,
-0x19c400, 0x1f86025, 0xe6a00, 0x18d5025,
-0x14b4825, 0xae490004, 0x92070006, 0x91050001,
-0x91040002, 0x91190003, 0x71e00, 0x53400,
-0x66f825, 0x41200, 0x3e2c025, 0x3197825,
-0x2610000a, 0xa0013d5, 0xae4f0008, 0x921f0001,
-0x26040002, 0x24100002, 0x57f00001, 0x2202021,
-0xa0013d5, 0x808021, 0x920e0001, 0x240d0003,
-0x15cdffcb, 0x24020001, 0x8e590000, 0x92180002,
-0x26100003, 0x372f0008, 0xa2580010, 0xa0013d5,
-0xae4f0000, 0x92050001, 0x24060004, 0x14a6ffc0,
-0x24020001, 0x920c0002, 0x920b0003, 0x8e490000,
-0xc5200, 0x14b4025, 0x35270004, 0x26100004,
-0xae48000c, 0xa0013d5, 0xae470000, 0xa0013e9,
-0x24020001, 0x27bdffe8, 0xafbf0014, 0xafb00010,
-0xe0012a5, 0x808021, 0x3c048008, 0x34830080,
-0x90650025, 0x2002021, 0x34a20020, 0xe0012af,
-0xa0620025, 0x2002021, 0x8fbf0014, 0x8fb00010,
-0xa000c9e, 0x27bd0018, 0x3c038000, 0x27bdfff8,
+0x601021, 0x3e00008, 0x27bd0028, 0x3c120800,
+0x8e5200d8, 0x2202821, 0x24040080, 0x26510001,
+0x3c010800, 0xac3100d8, 0xe000fdb, 0x24060003,
+0xa0011d9, 0x1821, 0x8c654000, 0x30b10100,
+0x12200046, 0x32590004, 0x3c1f0800, 0x8fff0024,
+0x24140004, 0x17200002, 0x33f0000d, 0x24140002,
+0x76ac2, 0x39a40001, 0x2e6c03ef, 0x30820001,
+0x398b0001, 0x4b4025, 0x11000003, 0x3251fffb,
+0x2412fffb, 0x2128024, 0x30e30100, 0x50600015,
+0x321f0001, 0x3c0a0f00, 0xea3024, 0x3c070200,
+0x10c7000f, 0x3c198000, 0x37250100, 0x90a90013,
+0x2418fffe, 0x2188024, 0x312f00ff, 0x25ee0004,
+0xe21c0, 0x12000002, 0x2343025, 0x3226ffff,
+0xe000fdb, 0x3265ffff, 0x1200ff3d, 0x2021,
+0x321f0001, 0x13e0000d, 0x320b0004, 0x24080001,
+0x12080002, 0x2343025, 0x3226ffff, 0x2021,
+0xe000fdb, 0x3265ffff, 0x2402fffe, 0x2028024,
+0x1200ff2f, 0x2021, 0x320b0004, 0x5160000d,
+0x24040001, 0x2343025, 0x24140004, 0x56140001,
+0x3226ffff, 0x2411fffb, 0x3265ffff, 0x24040100,
+0xe000fdb, 0x2119824, 0x1260ff21, 0x2021,
+0x24040001, 0xa001154, 0x801821, 0x3c0c0800,
+0x8d8c0024, 0x31900001, 0x5200ff19, 0x2021,
+0x3265ffff, 0x36460002, 0xe000fdb, 0x2021,
+0xa001153, 0x2021, 0x2002821, 0xa001150,
+0x36460002, 0x13000006, 0x0, 0x95300010,
+0x949f0002, 0x32190fff, 0x13f9ff3d, 0x310300ff,
+0x3c040801, 0x90849479, 0x1080ff3d, 0x24080001,
+0xa00110a, 0x1001821, 0x5040ff39, 0x8c8a0004,
+0xa00124b, 0x0, 0xe000fdb, 0x3246fffb,
+0xa00114e, 0x1121c0, 0x90830001, 0x240e0001,
+0x106eff3c, 0x24080001, 0x240f0002, 0x106f0004,
+0x30f30040, 0x24080001, 0xa00110a, 0x1001821,
+0x5260fffd, 0x24080001, 0x95250010, 0x94870002,
+0x30a9ffff, 0x50e9fea1, 0x1001821, 0xa001261,
+0x24080001, 0x240c0003, 0x35aa0180, 0xa14c000b,
+0xa0011ce, 0x3c0e8000, 0x2409fffe, 0xa0011cc,
+0x1094024, 0x27bdffc0, 0xafb00018, 0xafbf003c,
+0x3c10600c, 0xafbe0038, 0xafb70034, 0xafb60030,
+0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020,
+0xafb1001c, 0x8e0e5000, 0x240fff7f, 0x3c068000,
+0x1cf6824, 0x35ac380c, 0x240b0003, 0xae0c5000,
+0xaccb0008, 0x3c010800, 0xac200020, 0xe0017b0,
+0x0, 0x3c0a0010, 0x35498051, 0x3c066016,
+0xae09537c, 0x8cc70000, 0x3c086014, 0x8d0500a0,
+0x3c03ffff, 0xe32024, 0x3c025353, 0x51fc2,
+0x1082029b, 0x34c57c00, 0x8cbf007c, 0x8ca20078,
+0x3c1e6000, 0x37c42020, 0x3c050801, 0x24a590c0,
+0xaf820018, 0xaf9f001c, 0xe001674, 0x2406000a,
+0x3c190001, 0x27399478, 0x3c010800, 0xac3931dc,
+0xe00206b, 0xaf800014, 0x8fd70808, 0x2418fff0,
+0x3c155709, 0x2f8b024, 0x12d5028b, 0x24040001,
+0xaf800028, 0x3c148000, 0x36970100, 0x2e0f021,
+0x8e900000, 0x32050003, 0x10a0fffd, 0x32070001,
+0x14e0005d, 0x32060002, 0x10c0fff9, 0x3c078000,
+0x34e50140, 0x8cb90000, 0x24100040, 0xacf90020,
+0x90b80008, 0x33030070, 0x1070010b, 0x28690041,
+0x11200008, 0x24080060, 0x241f0020, 0x107f000e,
+0x3c0b4000, 0x3c068000, 0xaccb0178, 0xa0012b3,
+0x0, 0x1468fffb, 0x3c0b4000, 0xe001f88,
+0x0, 0x3c0b4000, 0x3c068000, 0xaccb0178,
+0xa0012b3, 0x0, 0x90ab0009, 0x24110004,
+0x8ca70000, 0x316800ff, 0x1111015d, 0x2512fffa,
+0x2e530006, 0x12600016, 0x3c068000, 0x8caa0004,
+0x8f860024, 0x94a3000a, 0xa3e02, 0x310500ff,
+0x10c00005, 0x3064ffff, 0x2cec0008, 0x15800002,
+0x24e70004, 0x24070003, 0x240e0009, 0x10ae01a1,
+0x28af000a, 0x11e00184, 0x2410000a, 0x24040008,
+0x10a4001a, 0x749c0, 0x1203821, 0x3c068000,
+0x8cd001b8, 0x600fffe, 0x34c40180, 0xac870000,
+0x34c50140, 0x90b60008, 0x24190002, 0x3c0b4000,
+0x32c200ff, 0x28a00, 0x228f825, 0xa49f0008,
+0xa099000b, 0x94a7000a, 0x3c081000, 0xa4870010,
+0x8cb80004, 0xac980024, 0xacc801b8, 0x3c068000,
+0xaccb0178, 0xa0012b3, 0x0, 0xac202,
+0x330300ff, 0x24050001, 0x5465ffe4, 0x1203821,
+0x8f990020, 0xaf830024, 0x27270001, 0xaf870020,
+0xa0012f2, 0x1203821, 0x8fd10028, 0x3c0b8008,
+0xae910020, 0x8fc60004, 0x8fca0000, 0x95690048,
+0xaf860000, 0xaf8a0004, 0x3128ffff, 0xe000fd4,
+0xaf880008, 0x3c030800, 0x8c6300c0, 0x10600025,
+0x8f870000, 0x3c0e0800, 0x8dce00c4, 0x25cd0001,
+0x3c010800, 0xac2d00c4, 0x3c1f8000, 0x37e90100,
+0x8d390024, 0x3c076020, 0xacf90014, 0x0,
+0x3c068000, 0x3c084000, 0xacc80138, 0x0,
+0x5220ff85, 0x32060002, 0x262d0140, 0x262e0080,
+0x2404ff80, 0x1a42824, 0x1c47824, 0xf1940,
+0x31cc007f, 0x59940, 0x31b2007f, 0x3c152000,
+0x36a20002, 0x6c5025, 0x272b025, 0x2c28825,
+0x1425825, 0xaccb0830, 0xacd10830, 0xa0012b9,
+0x32060002, 0x3c120010, 0xf27824, 0x15e00070,
+0x8f830004, 0x3c180800, 0x8f180020, 0x97d6000e,
+0x30f54000, 0x27130001, 0x3c010800, 0xac330020,
+0x9021, 0x12a00081, 0x32d3ffff, 0x3c1f0020,
+0xffc824, 0x1320007e, 0x30e58000, 0x8f820004,
+0x2404bfff, 0xe43824, 0x34431000, 0xaf870000,
+0x30eb2000, 0x11600073, 0x240effbf, 0x3c0d0004,
+0xed6024, 0x11800002, 0x6e1024, 0x34620040,
+0x30ef0100, 0x11e00010, 0xaf820004, 0x8f950028,
+0x12a00007, 0x3c180020, 0xf8b024, 0x12c00004,
+0x3c1f0004, 0xffc824, 0x1320016d, 0x0,
+0x96e3001e, 0x96e8001c, 0x3065ffff, 0x81400,
+0xa22025, 0xaf84000c, 0x96ea000c, 0x8e844000,
+0x3409ffff, 0x10890085, 0x3145ffff, 0x30860100,
+0x54c00001, 0x24120010, 0x30eb1000, 0x11600013,
+0x36560001, 0x30ec0020, 0x1580000a, 0x3c0e1000,
+0xee6824, 0x11a0000d, 0x3c190c00, 0x3c180bff,
+0xf9b024, 0x3715ffff, 0x2b6782b, 0x11e00007,
+0x36560001, 0x3c1f0800, 0x8fff002c, 0x36560005,
+0x27f20001, 0x3c010800, 0xac32002c, 0x30e40100,
+0x1480000b, 0x3c060001, 0x8f880004, 0x31024000,
+0x54400008, 0xe62824, 0x3c0a1f01, 0xea4824,
+0x3c031000, 0x11230109, 0x30a60200, 0x3c060001,
+0xe62824, 0x10a0003e, 0x3c181000, 0x3c0d0800,
+0x8dad0024, 0x31ac0002, 0x15800006, 0x24030001,
+0x601021, 0x1040ff83, 0x3c068000, 0xa00132a,
+0x3c1f8000, 0x3c0f0800, 0x8def00d8, 0x2602821,
+0x24040080, 0x25ee0001, 0x3c010800, 0xac2e00d8,
+0xe000fdb, 0x24060003, 0xa0013ab, 0x1821,
+0x2405bfff, 0x656824, 0x11a00007, 0x240f87ff,
+0x6f7024, 0x15c00008, 0x3c180060, 0xf82024,
+0x10800005, 0x0, 0xe000d42, 0x0,
+0xa0013ac, 0x0, 0xe00159c, 0x0,
+0xa0013ac, 0x0, 0xe0015f4, 0x0,
+0x3c0b4000, 0x3c068000, 0xaccb0178, 0xa0012b3,
+0x0, 0xa001367, 0x6e1024, 0x30e58000,
+0x10a0ff87, 0x8f830004, 0x3c080020, 0xe81824,
+0x5060ff83, 0x8f830004, 0x8f890004, 0x3c06ffff,
+0x34ca7fff, 0xea3824, 0xa00135e, 0x35238000,
+0xf8a824, 0x16a0001f, 0x4021, 0xaf800010,
+0x3c038000, 0x34640100, 0x9486000e, 0x8f930010,
+0x30c5ffff, 0x1100014e, 0x24b50004, 0x30ea0100,
+0x11400055, 0x3a7f0002, 0x3c0e0f00, 0xee6824,
+0x3c0c0200, 0x11ac0051, 0x2eb203ef, 0x908f0013,
+0x32b2ffff, 0x31e400ff, 0x24870004, 0x721c0,
+0x2402821, 0x36c60002, 0xe000fdb, 0x0,
+0x2021, 0xa0013ab, 0x801821, 0xa001381,
+0x24120020, 0x72602, 0x3099000f, 0x19f8c0,
+0x3c120801, 0x26529478, 0x3f24021, 0x1100ffdc,
+0xaf990010, 0x91090000, 0x1120ffda, 0x3c038000,
+0x3c138000, 0x366a0100, 0x954b000e, 0x24030003,
+0x2c03021, 0x3162ffff, 0x24450004, 0x112300ec,
+0x2021, 0x91090001, 0x240d0002, 0x312e00ff,
+0x11cd00fa, 0x313200ff, 0x24090001, 0x12490010,
+0x30ff0040, 0x8d040004, 0x8f830024, 0x14600006,
+0x34d30002, 0x248bfe00, 0x2d620381, 0x54400001,
+0x36c60040, 0x34d30002, 0x30a5ffff, 0xe000fdb,
+0x3266ffff, 0x4821, 0xa0013ab, 0x1201821,
+0x53e0fff1, 0x8d040004, 0x3c080801, 0x91089479,
+0x1100ffed, 0x24090001, 0xa0013ab, 0x1201821,
+0x3c048000, 0x8c8a01b8, 0x540fffe, 0x34960180,
+0x2415001c, 0xaec70000, 0xa2d5000b, 0x3c021000,
+0xac8201b8, 0x3c0b4000, 0x3c068000, 0xaccb0178,
+0xa0012b3, 0x0, 0x2eb203ef, 0x2ff90001,
+0x3a490001, 0x329c024, 0x1700ffb6, 0x24040001,
+0x3c030800, 0x8c6300d0, 0x2e65000c, 0x1321c0,
+0x386b0001, 0x2d620001, 0x454024, 0x1500ffa8,
+0x32b2ffff, 0x266afffc, 0x2d460004, 0x14c00013,
+0x2021, 0x386d0002, 0x2dac0001, 0x1851824,
+0x1460000f, 0x2402821, 0x266efff8, 0x2dc50004,
+0x14a0ff9b, 0x0, 0x77a42, 0x13382b,
+0x1e7a824, 0x56a00008, 0x2402821, 0x1321c0,
+0x2402821, 0xa0013fd, 0x36c60002, 0x2402821,
+0xa0013fd, 0x36c60002, 0xe000fdb, 0x32c6fffb,
+0xa001467, 0x1321c0, 0x10b00072, 0x45a02,
+0x2406000b, 0x14a6fe7c, 0x749c0, 0x314600ff,
+0x65600, 0xa5e03, 0x56200b0, 0x30c6007f,
+0x670c0, 0x3c0f0801, 0x25ef9478, 0x1cfa821,
+0xa2a00001, 0xa2a00000, 0x3c136000, 0x8e631820,
+0x240d0001, 0xcd4804, 0x96027, 0x749c0,
+0x6c9024, 0x1203821, 0xae721820, 0xa0012f2,
+0xa6a00002, 0x14c0004b, 0x8f8c0020, 0x749c0,
+0x3c0b8000, 0xad690020, 0x3c118008, 0x963f0040,
+0x13e00002, 0x24050001, 0x24050041, 0x3c048000,
+0x8c8a01b8, 0x540fffe, 0x34960180, 0x24120003,
+0xaec90000, 0xa2d2000b, 0xa6c0000e, 0xa6c0001a,
+0xa6c00010, 0xaec00028, 0xa6c50008, 0x96d30026,
+0x36750001, 0xa6d50026, 0xaec0002c, 0x3c021000,
+0xac8201b8, 0xa0012f2, 0x1203821, 0x14c0fef8,
+0x3c060001, 0x266b0004, 0x3165ffff, 0x36c60002,
+0x3c038000, 0x8c7301b8, 0x660fffe, 0x8f890008,
+0x3c0d8000, 0x35ac0180, 0xad800000, 0x512000dd,
+0x3c098000, 0x24af0012, 0x12f702b, 0x51c000d9,
+0x3c098000, 0x96f20020, 0x3c198000, 0x2418001a,
+0x3256ffff, 0x372a0180, 0x30f54000, 0xa158000b,
+0x12a000d5, 0x26c3fffe, 0x123f82b, 0x17e000d3,
+0x2404fffe, 0x35080001, 0xa5430014, 0xaf880004,
+0x2413bfff, 0x3c0b8000, 0x1135024, 0x35680180,
+0xa505000e, 0xa505001a, 0xa5060008, 0xa50a0026,
+0xa5070010, 0x3c071000, 0xae8701b8, 0xa0013ab,
+0x1821, 0x749c0, 0x2583ffff, 0x1460fe16,
+0xaf830020, 0x1203821, 0xa0012f2, 0xaf800024,
+0xe001054, 0x0, 0x8f870000, 0xa001379,
+0xaf82000c, 0x240300ff, 0x1163fe0b, 0x749c0,
+0x10c00038, 0xb7600, 0xb20c0, 0x3c090801,
+0x25299478, 0x891821, 0x24020001, 0xa0620000,
+0x3c160801, 0x26d69478, 0x3c020801, 0x2442947c,
+0x962821, 0x749c0, 0x828821, 0xafc02,
+0xae290000, 0xa0bf0001, 0x3c046000, 0x8c981820,
+0x24190001, 0x1793804, 0x3073025, 0x1203821,
+0xa4aa0002, 0xac861820, 0xa0012f3, 0x3c068000,
+0x91030001, 0x24160001, 0x1076ff27, 0x24090001,
+0x24050002, 0x10650004, 0x30e60040, 0x24090001,
+0xa0013ab, 0x1201821, 0x50c0fffd, 0x24090001,
+0x954c0010, 0x950a0002, 0x3187ffff, 0x5147fe98,
+0x1201821, 0xa00150b, 0x24090001, 0x30ef0040,
+0x11e0ff19, 0x0, 0x95590010, 0x95180002,
+0x33350fff, 0x1715ff14, 0x313200ff, 0xa00141e,
+0x24090001, 0xe6e03, 0x5a2000f, 0x316b007f,
+0x10e30008, 0xb20c0, 0x3c100801, 0x26109478,
+0x901821, 0xa0014ee, 0x24020002, 0xa00147b,
+0xaf800020, 0x3c0f0801, 0x25ef9478, 0x8f1821,
+0xa0014ee, 0x24020003, 0xa001523, 0xaf8b0020,
+0x3a080, 0x2869821, 0x8e720004, 0x3c116000,
+0xa001299, 0x2512821, 0xa0012b0, 0xaf840028,
+0x8c644000, 0x30930100, 0x1260004b, 0x24090004,
+0x3c190800, 0x8f390024, 0x32d80004, 0xafa90010,
+0x17000003, 0x3332000d, 0x241f0002, 0xafbf0010,
+0x71ac2, 0x386a0001, 0x2ea603ef, 0x31420001,
+0x38cb0001, 0x4b4025, 0x11000003, 0x32d3fffb,
+0x2416fffb, 0x2569024, 0x30ec0100, 0x11800016,
+0x32480001, 0x3c0e0f00, 0xee2824, 0x3c0d0200,
+0x10ad0011, 0x3c1f8000, 0x37e90100, 0x91380013,
+0x8faf0010, 0x2419fffe, 0x330400ff, 0x24870004,
+0x2599024, 0x721c0, 0x12400002, 0x26f3025,
+0x3266ffff, 0xe000fdb, 0x32a5ffff, 0x1240fe99,
+0x2021, 0x32480001, 0x1100000e, 0x324a0004,
+0x8fab0010, 0x24020001, 0x12420002, 0x26b3025,
+0x3266ffff, 0x2021, 0xe000fdb, 0x32a5ffff,
+0x2406fffe, 0x2469024, 0x1240fe8a, 0x2021,
+0x324a0004, 0x5140000e, 0x24040001, 0x8fb60010,
+0x24030004, 0x12430002, 0x2763025, 0x3266ffff,
+0x2413fffb, 0x32a5ffff, 0x24040100, 0xe000fdb,
+0x253a824, 0x12a0fe7b, 0x2021, 0x24040001,
+0xa0013ab, 0x801821, 0x3c0c0800, 0x8d8c0024,
+0x31920001, 0x5240fe73, 0x2021, 0x32a5ffff,
+0x36c60002, 0xe000fdb, 0x2021, 0xa001400,
+0x2021, 0x24020003, 0x35230180, 0xa062000b,
+0xa0014cc, 0x2413bfff, 0x2404fffe, 0xa0014ca,
+0x1044024, 0x3c038000, 0x34640100, 0x8c850000,
+0x30a2003e, 0x14400008, 0x0, 0xac600048,
+0x8c870000, 0x30e607c0, 0x10c00005, 0x0,
+0xac60004c, 0xac600050, 0x3e00008, 0x24020001,
+0xac600054, 0xac600040, 0x8c880000, 0x31043800,
+0x1080fff9, 0x0, 0x24020001, 0x3e00008,
+0xac600044, 0x3c038000, 0x8c6201b8, 0x440fffe,
+0x34670180, 0xace40000, 0x24080001, 0xace00004,
+0xa4e50008, 0x24050002, 0xa0e8000a, 0x34640140,
+0xa0e5000b, 0x9483000a, 0x14c00008, 0xa4e30010,
+0xace00024, 0x3c078000, 0x34e90180, 0x3c041000,
+0xad200028, 0x3e00008, 0xace401b8, 0x8c860004,
+0x3c041000, 0xace60024, 0x3c078000, 0x34e90180,
+0xad200028, 0x3e00008, 0xace401b8, 0x3c068000,
+0x8cc201b8, 0x440fffe, 0x34c70180, 0x24090002,
+0xace40000, 0xace40004, 0xa4e50008, 0xa0e9000a,
+0x34c50140, 0xa0e9000b, 0x94a8000a, 0x3c041000,
+0xa4e80010, 0xace00024, 0x8ca30004, 0xace30028,
+0x3e00008, 0xacc401b8, 0x3c039000, 0x34620001,
+0x822025, 0x3c038000, 0xac640020, 0x8c650020,
+0x4a0fffe, 0x0, 0x3e00008, 0x0,
+0x3c028000, 0x34430001, 0x832025, 0x3e00008,
+0xac440020, 0x27bdffe0, 0x3c098000, 0xafbf0018,
+0xafb10014, 0xafb00010, 0x35280140, 0x8d100000,
+0x91040009, 0x91070008, 0x91050008, 0x308400ff,
+0x30e600ff, 0x61a00, 0x2c820081, 0x833025,
+0x1040002a, 0x30a50080, 0x46080, 0x3c0d0801,
+0x25ad90e8, 0x18d5821, 0x8d6a0000, 0x1400008,
+0x0, 0x3c038000, 0x34620140, 0x9445000a,
+0x14a0001e, 0x8f91fcb8, 0x92270005, 0x30e60004,
+0x14c0001a, 0x0, 0xe0015e5, 0x2002021,
+0x922a0005, 0x2002021, 0x35490004, 0xe0015ef,
+0xa2290005, 0x92280005, 0x31040004, 0x14800002,
+0x0, 0xd, 0x922d0000, 0x240b0020,
+0x31ac00ff, 0x158b0009, 0x3c058000, 0x8cae01b8,
+0x5c0fffe, 0x34b10180, 0xae300000, 0x3c0f1000,
+0x24100005, 0xa230000b, 0xacaf01b8, 0xd,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x2002021, 0xc02821, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x24060001, 0xa0015b4,
+0x27bd0020, 0xd, 0x2002021, 0xc02821,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3021,
+0xa0015b4, 0x27bd0020, 0x14a0ffe8, 0x0,
+0x2002021, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0xc02821, 0xa0015d2, 0x27bd0020, 0x3c078000,
+0x8cee01b8, 0x5c0fffe, 0x34f00180, 0x241f0002,
+0xa21f000b, 0x34f80140, 0xa6060008, 0x9719000a,
+0x3c0f1000, 0xa6190010, 0x8f110004, 0xa6110012,
+0xacef01b8, 0xa001630, 0x8fbf0018, 0x27bdffe8,
+0xafbf0010, 0xe000fd4, 0x0, 0x3c028000,
+0x8fbf0010, 0x2021, 0xac400180, 0xa0010a6,
+0x27bd0018, 0x3084ffff, 0x30a5ffff, 0x10800007,
+0x1821, 0x30820001, 0x10400002, 0x42042,
+0x651821, 0x1480fffb, 0x52840, 0x3e00008,
+0x601021, 0x10c00007, 0x0, 0x8ca20000,
+0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb,
+0x24840004, 0x3e00008, 0x0, 0x10a00008,
+0x24a3ffff, 0xac860000, 0x0, 0x0,
+0x2402ffff, 0x2463ffff, 0x1462fffa, 0x24840004,
+0x3e00008, 0x0, 0x3c038000, 0x27bdfff8,
0x34620180, 0xafa20000, 0x308c00ff, 0x30ad00ff,
0x30ce00ff, 0x3c0b8000, 0x8d6401b8, 0x480fffe,
0x0, 0x8fa90000, 0x8d680128, 0x8faa0000,
@@ -10680,137 +10874,129 @@ u32 bce_RXP_b09FwText[(0x7908/4) + 1] = {
0x8ca80050, 0x882023, 0x4800008, 0x8fbf0010,
0x8caa0034, 0x24040039, 0x2821, 0xca4823,
0x5200005, 0x24060012, 0x8fbf0010, 0x24020001,
-0x3e00008, 0x27bd0018, 0xe001447, 0x0,
+0x3e00008, 0x27bd0018, 0xe001689, 0x0,
0x8fbf0010, 0x24020001, 0x3e00008, 0x27bd0018,
-0x27bdffc8, 0xafb1002c, 0xa08821, 0xafb20030,
-0x27a50010, 0x809021, 0x2202021, 0xafbf0034,
-0xe0013c6, 0xafb00028, 0x14400081, 0x3c0c8008,
-0x918b0011, 0x918a0012, 0x35860080, 0x8cc80054,
-0x316500ff, 0x314900ff, 0xa92821, 0xa8382b,
-0x14e0004f, 0x8fa30010, 0x94df005c, 0x30660004,
-0x10c00056, 0x33e4ffff, 0x8fa2001c, 0x82102b,
-0x54400005, 0x2c830080, 0x30670004, 0x14e0007e,
-0x24040218, 0x2c830080, 0x10600002, 0x808021,
-0x24100080, 0xe0012a5, 0x2402021, 0x3c038008,
-0x34660080, 0x24070001, 0xacc7000c, 0x90c20008,
-0x106040, 0x34670100, 0x305f007f, 0xa0df0008,
-0x8e390004, 0x27380001, 0xacd80030, 0xa4d0005c,
-0x8cce003c, 0x962f000e, 0x1cf6821, 0xaccd0020,
-0x8ccb003c, 0x16c5021, 0xacca001c, 0x8e290004,
-0xace90000, 0x8e250008, 0xace50004, 0x8fa80010,
-0x31040008, 0x5480002f, 0x93a60020, 0xa0c0004e,
-0x90c5004e, 0x2408ffdf, 0x3c188008, 0xa0e50008,
-0x90c40008, 0x370c0080, 0x24090050, 0x888024,
-0xa0d00008, 0x8e390008, 0xad990038, 0x8f0e0014,
-0x8d8f0030, 0x1cf6821, 0xad8d0034, 0x918b0000,
-0x316a00ff, 0x11490029, 0x26480100, 0xe0012af,
-0x2402021, 0x24040038, 0x2821, 0xe001447,
-0x2406000a, 0x8fbf0034, 0x8fb20030, 0x8fb1002c,
-0x8fb00028, 0x24020001, 0x3e00008, 0x27bd0038,
-0x94d8005c, 0x8cd00054, 0x330effff, 0x2057823,
-0x1cf682b, 0x15a0ffac, 0x8fa30010, 0x8cd90054,
-0x30660004, 0x14c0ffac, 0x3252023, 0xa0014a5,
-0x2c820218, 0x3c188008, 0x370c0080, 0xa0e60008,
-0x8e390008, 0x24090050, 0xad990038, 0x8f0e0014,
-0x8d8f0030, 0x1cf6821, 0xad8d0034, 0x918b0000,
-0x316a00ff, 0x1549ffd9, 0x26480100, 0x2406ff80,
-0x1062824, 0x3c048000, 0xac850028, 0x8e270008,
-0x3103007f, 0x3c10800c, 0x70f821, 0xafe700d0,
-0x8e220008, 0xaf9f0024, 0xa0014e0, 0xafe200d4,
-0x8e230008, 0x3c048008, 0x34820080, 0xac430054,
-0x2402021, 0xe001436, 0xac400030, 0x24040038,
-0x2405008d, 0xe001447, 0x24060012, 0x8fbf0034,
-0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x24020001,
-0x3e00008, 0x27bd0038, 0xa0014aa, 0x8fa4001c,
-0x27bdffe8, 0xafbf0010, 0x90a6000d, 0x30c70010,
-0x10e0000c, 0x804021, 0x3c028008, 0x8c440004,
-0x8ca30008, 0x10640008, 0x30c90004, 0x30c50004,
-0x10a0001c, 0x8fbf0010, 0x24020001, 0x3e00008,
-0x27bd0018, 0x30c90004, 0x11200010, 0x30cb0012,
-0x10e0fff9, 0x8fbf0010, 0x3c088008, 0x8ca70008,
-0x8d060004, 0x14e6fff5, 0x24020001, 0x24040038,
-0x2405008d, 0xe001447, 0x24060012, 0x8fbf0010,
-0x24020001, 0x3e00008, 0x27bd0018, 0x240a0012,
-0x156affe9, 0x8fbf0010, 0x1002021, 0xa001489,
-0x27bd0018, 0x2021, 0xa000cb8, 0x27bd0018,
-0x3c050800, 0x24a55598, 0x3c040800, 0x24847358,
-0x3c020800, 0x244255a0, 0x24030006, 0x3c010800,
-0xac257ac8, 0x3c010800, 0xac247acc, 0x3c010800,
-0xac227ad0, 0x3c010800, 0xa0237ad4, 0x3e00008,
-0x0, 0x3e00008, 0x24020001, 0x3c028000,
-0x308800ff, 0x34470180, 0x3c068000, 0x8cc301b8,
-0x460fffe, 0x0, 0x8cc50128, 0x2418ff80,
-0x3c0d800a, 0x24af0100, 0x1f87024, 0x31ec007f,
-0xacce0024, 0x18d2021, 0xace50000, 0x948b00da,
-0x35096000, 0x24080002, 0x316affff, 0xacea0004,
-0x24020001, 0xa4e90008, 0xa0e8000b, 0xace00024,
-0x3c071000, 0xacc701b8, 0xaf840024, 0x3e00008,
-0xaf850054, 0x8c990004, 0x8f8d0024, 0x2409ffbf,
-0x325c023, 0xac980004, 0x91af00c4, 0x2403ffef,
-0x31ee007f, 0xa1ae00c4, 0x8c8c0020, 0x938b0030,
-0x8f860024, 0x358a0002, 0xaf8b0048, 0xa7800044,
-0xac8a0020, 0xa4c000ac, 0x90c800c4, 0x1093824,
-0xa0c700c4, 0x8f840024, 0xac8000dc, 0x908500c4,
-0xa31024, 0x3e00008, 0xa08200c4, 0x3c028000,
-0x34450180, 0x3c048000, 0x8c8301b8, 0x460fffe,
-0x8f890054, 0x24076083, 0x24060002, 0xaca90000,
-0x8c880124, 0xaca80004, 0xa4a70008, 0xa0a6000b,
-0x3c051000, 0x3e00008, 0xac8501b8, 0x93880030,
-0x8f890048, 0x8f820024, 0x30c600ff, 0x1093823,
-0x30e900ff, 0x1221821, 0x30a500ff, 0x24680078,
-0x10c00002, 0x1243821, 0x803821, 0x30e40003,
-0x14800003, 0x30aa0003, 0x1140000d, 0x312b0003,
-0x10a00009, 0x1021, 0x90ed0000, 0x244e0001,
-0x31c200ff, 0x45602b, 0xa10d0000, 0x24e70001,
-0x1580fff9, 0x25080001, 0x3e00008, 0x0,
-0x1560fff3, 0x0, 0x10a0fffb, 0x1021,
-0x8cf80000, 0x24590004, 0x332200ff, 0x45782b,
-0xad180000, 0x24e70004, 0x15e0fff9, 0x25080004,
-0x3e00008, 0x0, 0x93850030, 0x93880040,
-0x8f870048, 0x43200, 0x3103007f, 0xe5102b,
-0x30c47f00, 0x1040000f, 0x642825, 0x8f840024,
-0x3c098000, 0x8c8a00dc, 0xad2a00a4, 0x3c038000,
-0xa35825, 0xac6b00a0, 0x8c6c00a0, 0x580fffe,
-0x0, 0x8c6d00ac, 0xac8d00dc, 0x3e00008,
-0x8c6200a8, 0xa0015e8, 0x8f840024, 0x93880041,
-0x3c028000, 0x805021, 0x310300fe, 0xa3830041,
-0x30abffff, 0x30cc00ff, 0x30e7ffff, 0x34480180,
-0x3c098000, 0x8d2401b8, 0x480fffe, 0x8f8d0054,
-0x24180016, 0xad0d0000, 0x8d220124, 0x8f8d0024,
-0xad020004, 0x8d590020, 0xa5070008, 0x240201b4,
-0xa119000a, 0xa118000b, 0x952f0120, 0x8d4e0008,
-0x8d470004, 0x97830044, 0x8d590024, 0x1cf3021,
-0xc72821, 0xa32023, 0x2418ffff, 0xa504000c,
-0xa50b000e, 0xa5020010, 0xa50c0012, 0xad190018,
-0xad180024, 0x95af00d8, 0x3c0b1000, 0x2407fff7,
-0x31eeffff, 0xad0e0028, 0x8dac0074, 0xad0c002c,
-0xad2b01b8, 0x8d460020, 0xc72824, 0x3e00008,
-0xad450020, 0x8f880024, 0x805821, 0x30e7ffff,
-0x910900c6, 0x3c028000, 0x30a5ffff, 0x312400ff,
-0x41a00, 0x675025, 0x30c600ff, 0x34470180,
-0x3c098000, 0x8d2c01b8, 0x580fffe, 0x8f820054,
-0x240f0017, 0xace20000, 0x8d390124, 0xacf90004,
-0x8d780020, 0xa4ea0008, 0x241901b4, 0xa0f8000a,
-0xa0ef000b, 0x95230120, 0x8d6e0008, 0x8d6d0004,
-0x97840044, 0x1c35021, 0x14d6021, 0x1841023,
-0xa4e2000c, 0xa4e5000e, 0xa4f90010, 0xa4e60012,
-0xace00014, 0x8d780024, 0x240dffff, 0xacf80018,
-0x8d0f006c, 0xacef001c, 0x8d0e0068, 0x3c0f1000,
-0xacee0020, 0xaced0024, 0x950a00ae, 0x240dfff7,
-0x3146ffff, 0xace60028, 0x950c0070, 0x95040072,
-0x31837fff, 0x3ca00, 0x3082ffff, 0x322c021,
-0xacf8002c, 0xad2f01b8, 0x950e0072, 0x8d6a0020,
-0xae3021, 0x14d2824, 0xa5060072, 0x3e00008,
-0xad650020, 0x3c028000, 0x34460180, 0x3c058000,
-0x8ca301b8, 0x460fffe, 0x24090018, 0xacc40000,
-0xa0c9000b, 0x8f880024, 0x3c041000, 0x950700ae,
-0xa4c70010, 0xacc00030, 0x3e00008, 0xaca401b8,
+0x27bdffc8, 0xafb20030, 0xafb00028, 0xafbf0034,
+0xafb1002c, 0xa08021, 0x90a5000d, 0x30a60010,
+0x10c00010, 0x809021, 0x3c028008, 0x8c440004,
+0x8e030008, 0x1064000c, 0x30a70005, 0x30a60005,
+0x10c00093, 0x24040001, 0x8fbf0034, 0x8fb20030,
+0x8fb1002c, 0x8fb00028, 0x801021, 0x3e00008,
+0x27bd0038, 0x30a70005, 0x10e0000f, 0x30ab0012,
+0x10c00006, 0x24040001, 0x3c098008, 0x8e080008,
+0x8d250004, 0x5105009c, 0x24040038, 0x8fbf0034,
+0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x801021,
+0x3e00008, 0x27bd0038, 0x240a0012, 0x156affe6,
+0x24040001, 0x2002021, 0x27a50010, 0xe000cb6,
+0xafa00010, 0x1440007c, 0x3c198008, 0x37240080,
+0x90980008, 0x33110008, 0x1220000a, 0x8fa70010,
+0x30ff0100, 0x13e000a4, 0x8fa30014, 0x8c860058,
+0x661023, 0x4400004, 0x3c0a8008, 0xac830058,
+0x8fa70010, 0x3c0a8008, 0x35480080, 0x91090008,
+0x31240008, 0x14800002, 0x24080003, 0x4021,
+0x3c1f8008, 0x93f10011, 0x93f90012, 0x37e60080,
+0x8ccc0054, 0x333800ff, 0x3087821, 0x322d00ff,
+0xf7080, 0x1ae2821, 0xac582b, 0x1160006f,
+0x0, 0x94ca005c, 0x8cc90054, 0x3144ffff,
+0x1251023, 0x82182b, 0x14600068, 0x0,
+0x8ccb0054, 0x1651823, 0x30ec0004, 0x1180006c,
+0x83080, 0x8fa8001c, 0x68102b, 0x10400062,
+0x30ed0004, 0x661023, 0x2c460080, 0x10c00002,
+0x408821, 0x24110080, 0xe0015e5, 0x2402021,
+0x3c0d8008, 0x35a60080, 0x24070001, 0xacc7000c,
+0x90c80008, 0x114840, 0x35a70100, 0x310c007f,
+0xa0cc0008, 0x8e050004, 0x24ab0001, 0xaccb0030,
+0xa4d1005c, 0x8cca003c, 0x9602000e, 0x1422021,
+0xacc40020, 0x8cc3003c, 0x69f821, 0xacdf001c,
+0x8e190004, 0xacf90000, 0x8e180008, 0xacf80004,
+0x8fb10010, 0x322f0008, 0x55e00047, 0x93a60020,
+0xa0c0004e, 0x90d8004e, 0x2411ffdf, 0xa0f80008,
+0x90cf0008, 0x1f17024, 0xa0ce0008, 0x8e050008,
+0x3c0b8008, 0x35690080, 0xad250038, 0x8d6a0014,
+0x8d220030, 0x24190050, 0x1422021, 0xad240034,
+0x91230000, 0x307f00ff, 0x13f90036, 0x264f0100,
+0xe0015ef, 0x2402021, 0x24040038, 0x2821,
+0xe001689, 0x2406000a, 0xa0016ee, 0x24040001,
+0xe000d28, 0x2021, 0x8fbf0034, 0x8fb20030,
+0x8fb1002c, 0x8fb00028, 0x402021, 0x801021,
+0x3e00008, 0x27bd0038, 0x8e0e0008, 0x3c0f8008,
+0x35f00080, 0xae0e0054, 0x2402021, 0xae000030,
+0xe0015e5, 0x0, 0x920d0025, 0x2402021,
+0x35ac0020, 0xe0015ef, 0xa20c0025, 0xe000cac,
+0x2402021, 0x24040038, 0x2405008d, 0xe001689,
+0x24060012, 0xa0016ee, 0x24040001, 0x94c5005c,
+0xa001729, 0x30a3ffff, 0x24070218, 0x11a0ff9e,
+0xe61023, 0x8fae001c, 0xa001731, 0x1c61023,
+0xa00172e, 0x2c620218, 0xa0e60008, 0xa00175b,
+0x8e050008, 0x2406ff80, 0x1e6c024, 0x3c118000,
+0xae380028, 0x8e0d0008, 0x31e7007f, 0x3c0e800c,
+0xee6021, 0xad8d00e0, 0x8e080008, 0xaf8c0034,
+0xa001767, 0xad8800e4, 0xac800058, 0x90850008,
+0x2403fff7, 0xa33824, 0xa0870008, 0xa00170c,
+0x8fa70010, 0x3c050800, 0x24a55f04, 0x3c040800,
+0x24846e50, 0x3c020800, 0x24425f0c, 0x24030006,
+0x3c010801, 0xac2594f8, 0x3c010801, 0xac2494fc,
+0x3c010801, 0xac229500, 0x3c010801, 0xa0239504,
+0x3e00008, 0x0, 0x3e00008, 0x24020001,
+0x3c028000, 0x308800ff, 0x34470180, 0x3c068000,
+0x8cc301b8, 0x460fffe, 0x0, 0x8cc50128,
+0x2418ff80, 0x3c0d800a, 0x24af0100, 0x1f87024,
+0x31ec007f, 0xacce0024, 0x18d2021, 0xace50000,
+0x948b00ea, 0x35096000, 0x24080002, 0x316affff,
+0xacea0004, 0x24020001, 0xa4e90008, 0xa0e8000b,
+0xace00024, 0x3c071000, 0xacc701b8, 0xaf840034,
+0x3e00008, 0xaf850068, 0x93880044, 0x8f89005c,
+0x8f820034, 0x30c600ff, 0x1093823, 0x30e900ff,
+0x1221821, 0x30a500ff, 0x24680088, 0x10c00002,
+0x1243821, 0x803821, 0x30e40003, 0x14800003,
+0x30aa0003, 0x1140000d, 0x312b0003, 0x10a00009,
+0x1021, 0x90ed0000, 0x244e0001, 0x31c200ff,
+0x45602b, 0xa10d0000, 0x24e70001, 0x1580fff9,
+0x25080001, 0x3e00008, 0x0, 0x1560fff3,
+0x0, 0x10a0fffb, 0x1021, 0x8cf80000,
+0x24590004, 0x332200ff, 0x45782b, 0xad180000,
+0x24e70004, 0x15e0fff9, 0x25080004, 0x3e00008,
+0x0, 0x93850044, 0x93880054, 0x8f87005c,
+0x43200, 0x3103007f, 0xe5102b, 0x30c47f00,
+0x1040000f, 0x642825, 0x8f840034, 0x3c098000,
+0x8c8a00ec, 0xad2a00a4, 0x3c038000, 0xa35825,
+0xac6b00a0, 0x8c6c00a0, 0x580fffe, 0x0,
+0x8c6d00ac, 0xac8d00ec, 0x3e00008, 0x8c6200a8,
+0xa001819, 0x8f840034, 0x93880055, 0x3c028000,
+0x805021, 0x310300fe, 0xa3830055, 0x30abffff,
+0x30cc00ff, 0x30e7ffff, 0x34480180, 0x3c098000,
+0x8d2401b8, 0x480fffe, 0x8f8d0068, 0x24180016,
+0xad0d0000, 0x8d220124, 0x8f8d0034, 0xad020004,
+0x8d590020, 0xa5070008, 0x240201c4, 0xa119000a,
+0xa118000b, 0x952f0120, 0x8d4e0008, 0x8d470004,
+0x97830058, 0x8d590024, 0x1cf3021, 0xc72821,
+0xa32023, 0x2418ffff, 0xa504000c, 0xa50b000e,
+0xa5020010, 0xa50c0012, 0xad190018, 0xad180024,
+0x95af00e8, 0x3c0b1000, 0x2407fff7, 0x31eeffff,
+0xad0e0028, 0x8dac0084, 0xad0c002c, 0xad2b01b8,
+0x8d460020, 0xc72824, 0x3e00008, 0xad450020,
+0x8f880034, 0x805821, 0x30e7ffff, 0x910900d6,
+0x3c028000, 0x30a5ffff, 0x312400ff, 0x41a00,
+0x675025, 0x30c600ff, 0x34470180, 0x3c098000,
+0x8d2c01b8, 0x580fffe, 0x8f820068, 0x240f0017,
+0xace20000, 0x8d390124, 0xacf90004, 0x8d780020,
+0xa4ea0008, 0x241901c4, 0xa0f8000a, 0xa0ef000b,
+0x95230120, 0x8d6e0008, 0x8d6d0004, 0x97840058,
+0x1c35021, 0x14d6021, 0x1841023, 0xa4e2000c,
+0xa4e5000e, 0xa4f90010, 0xa4e60012, 0xace00014,
+0x8d780024, 0x240dffff, 0xacf80018, 0x8d0f007c,
+0xacef001c, 0x8d0e0078, 0x3c0f1000, 0xacee0020,
+0xaced0024, 0x950a00be, 0x240dfff7, 0x3146ffff,
+0xace60028, 0x950c0080, 0x95040082, 0x31837fff,
+0x3ca00, 0x3082ffff, 0x322c021, 0xacf8002c,
+0xad2f01b8, 0x950e0082, 0x8d6a0020, 0xae3021,
+0x14d2824, 0xa5060082, 0x3e00008, 0xad650020,
0x3c028000, 0x34450180, 0x3c048000, 0x8c8301b8,
-0x460fffe, 0x8f8a002c, 0x24060019, 0x9549001c,
+0x460fffe, 0x8f8a0040, 0x24060019, 0x9549001c,
0x3128ffff, 0x839c0, 0xaca70000, 0xa0a6000b,
-0x3c051000, 0x3e00008, 0xac8501b8, 0x8f870034,
+0x3c051000, 0x3e00008, 0xac8501b8, 0x8f870048,
0x804021, 0x30c400ff, 0x3c068000, 0x8cc201b8,
-0x440fffe, 0x8f890054, 0x93830050, 0x34996000,
+0x440fffe, 0x8f890068, 0x93830064, 0x34996000,
0xaca90000, 0xa0a30005, 0x8ce20010, 0x240f0002,
0x2403fff7, 0xa4a20006, 0xa4b90008, 0x8d180020,
0xa0b8000a, 0xa0af000b, 0x8cee0000, 0xacae0010,
@@ -10818,628 +11004,924 @@ u32 bce_RXP_b09FwText[(0x7908/4) + 1] = {
0x8ceb0020, 0xacab0028, 0x8cea002c, 0x3c071000,
0xacaa002c, 0x8d090024, 0xaca90018, 0xacc701b8,
0x8d050020, 0xa32024, 0x3e00008, 0xad040020,
-0x93850050, 0x24030001, 0x27bdffe8, 0xa33004,
-0x2ca20020, 0xafb00010, 0xafbf0014, 0xc01821,
-0x10400013, 0x2410fffe, 0x3c070800, 0x8ce73190,
-0xe61024, 0x3c088000, 0x35050180, 0x14400005,
-0x24060084, 0x8f890024, 0x240a0004, 0x2410ffff,
-0xa12a00ec, 0xe001684, 0x0, 0x2001021,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x3c060800, 0x8cc63194, 0xa0016b6, 0xc31024,
-0x8f87002c, 0x27bdffe0, 0xafb20018, 0xafb10014,
-0xafb00010, 0xafbf001c, 0x30d000ff, 0x90e6000d,
-0xa08821, 0x809021, 0x30c5007f, 0xa0e5000d,
-0x8f850024, 0x8e230018, 0x8ca200c0, 0x1062002e,
-0x240a000e, 0xe0016a9, 0xa38a0050, 0x2409ffff,
-0x10490022, 0x2404ffff, 0x52000020, 0x2021,
-0x8e260000, 0x3c0c0010, 0xcc5824, 0x15600039,
-0x3c0e0008, 0xce6824, 0x55a0003f, 0x2402021,
-0x3c180002, 0xd88024, 0x1200001f, 0x3c0a0004,
-0x8f87002c, 0x8ce20014, 0x8ce30010, 0x8ce50014,
-0x43f823, 0x3e5c82b, 0x13200005, 0x2402021,
-0x8e24002c, 0x8cf10010, 0x10910031, 0x2402021,
-0x24020012, 0xa3820050, 0xe0016a9, 0x2412ffff,
-0x10520002, 0x2404ffff, 0x2021, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x801021,
-0x3e00008, 0x27bd0020, 0x90a800c4, 0x35040020,
-0xa0016df, 0xa0a400c4, 0xca4824, 0x1520000b,
-0x8f8b002c, 0x8f8d002c, 0x8dac0010, 0x1580000b,
-0x2402021, 0x8e2e002c, 0x51c0ffec, 0x2021,
-0x2402021, 0xa0016fa, 0x24020017, 0x8d660010,
-0x50c0ffe6, 0x2021, 0x2402021, 0xa0016fa,
-0x24020011, 0x2402021, 0x24020015, 0xe0016a9,
-0xa3820050, 0x240fffff, 0x104fffdc, 0x2404ffff,
-0xa0016e9, 0x8e260000, 0xa001720, 0x24020014,
-0x3c080004, 0xc83824, 0x50e0ffd4, 0x2021,
-0x2402021, 0xa0016fa, 0x24020013, 0x8f860024,
-0x27bdffe0, 0xafb10014, 0xafbf0018, 0xafb00010,
-0x90c300c4, 0x30a500ff, 0x30620020, 0x10400008,
-0x808821, 0x8ccb00c0, 0x2409ffdf, 0x256a0001,
-0xacca00c0, 0x90c800c4, 0x1093824, 0xa0c700c4,
-0x14a00040, 0x3c0c8000, 0x8f840024, 0x908700c4,
-0x2418ffbf, 0x2406ffef, 0x30e3007f, 0xa08300c4,
-0x979f0044, 0x8f820048, 0x8f8d0024, 0x3e2c823,
-0xa7990044, 0xa5a000ac, 0x91af00c4, 0x1f87024,
-0xa1ae00c4, 0x8f8c0024, 0xa18000c7, 0x8f8a0024,
-0xa5400072, 0xad4000dc, 0x914500c4, 0xa65824,
-0xa14b00c4, 0x8f900020, 0x8f840048, 0x97860044,
-0x2042821, 0x10c0000f, 0xaf850020, 0xa3800040,
-0x3c078000, 0x8e2c0008, 0x94ed0120, 0x8e2b0004,
-0x18d5021, 0x14b8021, 0x2062023, 0x3086ffff,
-0x30c8000f, 0x39090001, 0x31310001, 0x16200009,
-0xa3880040, 0x93860030, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0x27bd0020, 0xaf85004c, 0x3e00008,
-0xaf860048, 0xc87023, 0x8fbf0018, 0x93860030,
-0x8fb10014, 0x8fb00010, 0x34ef0c00, 0x10f2821,
-0x27bd0020, 0xacee0084, 0xaf85004c, 0x3e00008,
-0xaf860048, 0x35900180, 0x2002821, 0xe001684,
-0x24060082, 0x8f840024, 0x908600c4, 0x30c50040,
-0x50a0ffba, 0xa3800050, 0x8f850034, 0x3c068000,
-0x8ccd01b8, 0x5a0fffe, 0x8f890054, 0x24086082,
-0x24070002, 0xae090000, 0xa6080008, 0xa207000b,
-0x8ca30008, 0x3c0e1000, 0xae030010, 0x8ca2000c,
-0xae020014, 0x8cbf0014, 0xae1f0018, 0x8cb90018,
-0xae190024, 0x8cb80024, 0xae180028, 0x8caf0028,
-0xae0f002c, 0xacce01b8, 0xa001744, 0xa3800050,
-0x8f8a0024, 0x27bdffe0, 0xafb10014, 0xafb00010,
-0x8f880048, 0xafbf0018, 0x93890028, 0x954200ac,
-0x30d100ff, 0x109182b, 0x808021, 0x30ac00ff,
-0x3047ffff, 0x5821, 0x14600003, 0x310600ff,
-0x1203021, 0x1095823, 0x97830044, 0x68202b,
-0x1480001b, 0x0, 0x10680043, 0x240a0001,
-0x118a0048, 0x34e70880, 0x3165ffff, 0xe001626,
-0x2002021, 0xe001666, 0x8f840054, 0x8f840024,
-0x948d0070, 0x25ac0001, 0xa48c0070, 0x948b0070,
-0x3c060800, 0x8cc63188, 0x31677fff, 0x10e6004f,
-0x0, 0x2002021, 0x2202821, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0xa001730, 0x27bd0020,
-0x914400c4, 0x2406ff80, 0x868825, 0xa15100c4,
-0x97840044, 0x3088ffff, 0x1100001c, 0x93890028,
-0x8f8e0024, 0x2419efff, 0x8bf823, 0x95d800ac,
-0x168682b, 0x33e900ff, 0x3197824, 0xa5cf00ac,
-0x51a0002a, 0x1005821, 0x8e050020, 0x2408fffb,
-0x24030001, 0xa81024, 0xae020020, 0x11830025,
-0x34e78000, 0x2002021, 0x3165ffff, 0xe001626,
-0x1203021, 0x978b0044, 0x8f870048, 0xa7800044,
-0xeb8023, 0xaf900048, 0x93890028, 0x8f8c0024,
+0x8f860034, 0x27bdffe0, 0xafb10014, 0xafbf0018,
+0xafb00010, 0x90c300d4, 0x30a500ff, 0x30620020,
+0x10400008, 0x808821, 0x8ccb00d0, 0x2409ffdf,
+0x256a0001, 0xacca00d0, 0x90c800d4, 0x1093824,
+0xa0c700d4, 0x14a00040, 0x3c0c8000, 0x8f840034,
+0x908700d4, 0x2418ffbf, 0x2406ffef, 0x30e3007f,
+0xa08300d4, 0x979f0058, 0x8f82005c, 0x8f8d0034,
+0x3e2c823, 0xa7990058, 0xa5a000bc, 0x91af00d4,
+0x1f87024, 0xa1ae00d4, 0x8f8c0034, 0xa18000d7,
+0x8f8a0034, 0xa5400082, 0xad4000ec, 0x914500d4,
+0xa65824, 0xa14b00d4, 0x8f900030, 0x8f84005c,
+0x97860058, 0x2042821, 0x10c0000f, 0xaf850030,
+0xa3800054, 0x3c078000, 0x8e2c0008, 0x94ed0120,
+0x8e2b0004, 0x18d5021, 0x14b8021, 0x2062023,
+0x3086ffff, 0x30c8000f, 0x39090001, 0x31310001,
+0x16200009, 0xa3880054, 0x93860044, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x27bd0020, 0xaf850060,
+0x3e00008, 0xaf86005c, 0xc87023, 0x8fbf0018,
+0x93860044, 0x8fb10014, 0x8fb00010, 0x34ef0c00,
+0x10f2821, 0x27bd0020, 0xacee0084, 0xaf850060,
+0x3e00008, 0xaf86005c, 0x35900180, 0x2002821,
+0xe0018a6, 0x24060082, 0x8f840034, 0x908600d4,
+0x30c50040, 0x50a0ffba, 0xa3800064, 0x8f850048,
+0x3c068000, 0x8ccd01b8, 0x5a0fffe, 0x8f890068,
+0x24086082, 0x24070002, 0xae090000, 0xa6080008,
+0xa207000b, 0x8ca30008, 0x3c0e1000, 0xae030010,
+0x8ca2000c, 0xae020014, 0x8cbf0014, 0xae1f0018,
+0x8cb90018, 0xae190024, 0x8cb80024, 0xae180028,
+0x8caf0028, 0xae0f002c, 0xacce01b8, 0xa0018df,
+0xa3800064, 0x8f8a0034, 0x27bdffe0, 0xafb10014,
+0xafb00010, 0x8f88005c, 0xafbf0018, 0x93890038,
+0x954200bc, 0x30d100ff, 0x109182b, 0x808021,
+0x30ac00ff, 0x3047ffff, 0x5821, 0x14600003,
+0x310600ff, 0x1203021, 0x1095823, 0x97830058,
+0x68202b, 0x14800027, 0x0, 0x10680056,
+0x24190001, 0x11990063, 0x34e70880, 0x3165ffff,
+0xe001857, 0x2002021, 0x8f830068, 0x3c078000,
+0x34e60180, 0x3c058000, 0x8cab01b8, 0x560fffe,
+0x240a0018, 0x8f840034, 0xacc30000, 0xa0ca000b,
+0x948900be, 0x3c081000, 0xa4c90010, 0xacc00030,
+0xaca801b8, 0x94820080, 0x24430001, 0xa4830080,
+0x949f0080, 0x3c060800, 0x8cc63188, 0x33ec7fff,
+0x1186005e, 0x0, 0x2002021, 0x2202821,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0xa0018cb,
+0x27bd0020, 0x914400d4, 0x2403ff80, 0x838825,
+0xa15100d4, 0x97840058, 0x3088ffff, 0x51000023,
+0x938c0038, 0x8f850034, 0x2402efff, 0x8b7823,
+0x94ae00bc, 0x168502b, 0x31e900ff, 0x1c26824,
+0xa4ad00bc, 0x51400039, 0x1005821, 0x3c1f8000,
+0x37e60100, 0x8cd80004, 0x3c190001, 0x3194024,
+0x55000001, 0x34e74000, 0x8e0a0020, 0x2403fffb,
+0x24110001, 0x1432024, 0xae040020, 0x1191002d,
+0x34e78000, 0x2002021, 0x1203021, 0xe001857,
+0x3165ffff, 0x97870058, 0x8f89005c, 0xa7800058,
+0x1278023, 0xaf90005c, 0x938c0038, 0x8f8b0034,
0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x27bd0020,
-0x3e00008, 0xa18900c7, 0x8e080020, 0x2409fffb,
-0x34e78000, 0x1092824, 0xae050020, 0x158affba,
-0x34e70880, 0x2002021, 0xe0015f4, 0x3165ffff,
+0x3e00008, 0xa16c00d7, 0x3c0d8000, 0x35aa0100,
+0x8d480004, 0x3c090001, 0x1092824, 0x54a00001,
+0x34e74000, 0x8e0f0020, 0x2418fffb, 0x34e78000,
+0x1f87024, 0x24190001, 0xae0e0020, 0x1599ff9f,
+0x34e70880, 0x2002021, 0xe001825, 0x3165ffff,
0x2002021, 0x2202821, 0x8fbf0018, 0x8fb10014,
-0x8fb00010, 0xa001730, 0x27bd0020, 0xa0017e7,
-0x4821, 0x2002021, 0x3165ffff, 0xe0015f4,
-0x1203021, 0x978b0044, 0x8f870048, 0xa7800044,
-0xeb8023, 0xa0017f7, 0xaf900048, 0x94890070,
-0x240a8000, 0x12a4024, 0xa4880070, 0x90850070,
-0x90990070, 0x30a200ff, 0x219c2, 0x3f827,
-0x1fc1c0, 0x332f007f, 0x1f87025, 0xa08e0070,
-0xa0017cf, 0x2002021, 0x8f880024, 0x24030001,
-0x910a0078, 0x910500c7, 0x25090078, 0x3147003f,
-0x24e6ffe0, 0xc31804, 0x2cc20020, 0x30670019,
-0xa3850028, 0x1040001a, 0xaf890034, 0x3c0a8000,
-0x354b0002, 0x24050001, 0x24060001, 0x14e00016,
-0x6b1024, 0x2821, 0x1440000f, 0x30630020,
-0x1060000f, 0x24050001, 0x8d060074, 0x8d190074,
-0x2403ff80, 0xc31024, 0x27940, 0x3338007f,
-0x1f86825, 0x3c0e1000, 0x1ae6025, 0xad4c0830,
-0x91280001, 0x31060001, 0xa0017a5, 0x0,
-0x3e00008, 0x0, 0x8d0f0074, 0x8d0d0074,
-0x2418ff80, 0x1f87024, 0xe4140, 0x31ac007f,
-0x10c5025, 0x3c0b1000, 0x14b3825, 0x3c098000,
-0xa0017a5, 0xad270830, 0x27bdffd8, 0xafb00010,
-0x8f900034, 0xafb40020, 0xafb10014, 0xafbf0024,
-0xafb3001c, 0xafb20018, 0x8e050010, 0x3c020800,
-0x8c4231b0, 0x8f860038, 0x30a73fff, 0xe2182b,
-0x8cd20014, 0x808821, 0x8cd30020, 0x10600007,
-0xa021, 0x90cb000d, 0x240aff80, 0x14b4824,
-0x312800ff, 0x1500000c, 0x56382, 0x2202021,
-0x2411000d, 0xa3910050, 0x8fbf0024, 0x8fb40020,
+0x8fb00010, 0xa0018cb, 0x27bd0020, 0xa00198e,
+0x4821, 0x2002021, 0x1203021, 0xe001825,
+0x3165ffff, 0x97870058, 0x8f89005c, 0xa7800058,
+0x1278023, 0xa0019a5, 0xaf90005c, 0x948c0080,
+0x241f8000, 0x19f3024, 0xa4860080, 0x908b0080,
+0x908f0080, 0x316700ff, 0x7c9c2, 0x19c027,
+0x1871c0, 0x31ed007f, 0x1ae2825, 0xa0850080,
+0xa001976, 0x2002021, 0x93850064, 0x24030001,
+0x27bdffe8, 0xa33004, 0x2ca20020, 0xafb00010,
+0xafbf0014, 0xc01821, 0x10400013, 0x2410fffe,
+0x3c070800, 0x8ce73190, 0xe61024, 0x3c088000,
+0x35050180, 0x14400005, 0x24060084, 0x8f890034,
+0x240a0004, 0x2410ffff, 0xa12a00fc, 0xe0018a6,
+0x0, 0x2001021, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x3c060800, 0x8cc63194,
+0xa0019ee, 0xc31024, 0x8f870040, 0x27bdffe0,
+0xafb20018, 0xafb10014, 0xafb00010, 0xafbf001c,
+0x30d000ff, 0x90e6000d, 0xa08821, 0x809021,
+0x30c5007f, 0xa0e5000d, 0x8f850034, 0x8e230018,
+0x8ca200d0, 0x1062002e, 0x240a000e, 0xe0019e1,
+0xa38a0064, 0x2409ffff, 0x10490022, 0x2404ffff,
+0x52000020, 0x2021, 0x8e260000, 0x3c0c0010,
+0xcc5824, 0x15600039, 0x3c0e0008, 0xce6824,
+0x55a0003f, 0x2402021, 0x3c180002, 0xd88024,
+0x1200001f, 0x3c0a0004, 0x8f870040, 0x8ce20014,
+0x8ce30010, 0x8ce50014, 0x43f823, 0x3e5c82b,
+0x13200005, 0x2402021, 0x8e24002c, 0x8cf10010,
+0x10910031, 0x2402021, 0x24020012, 0xa3820064,
+0xe0019e1, 0x2412ffff, 0x10520002, 0x2404ffff,
+0x2021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x801021, 0x3e00008, 0x27bd0020,
+0x90a800d4, 0x35040020, 0xa001a17, 0xa0a400d4,
+0xca4824, 0x1520000b, 0x8f8b0040, 0x8f8d0040,
+0x8dac0010, 0x1580000b, 0x2402021, 0x8e2e002c,
+0x51c0ffec, 0x2021, 0x2402021, 0xa001a32,
+0x24020017, 0x8d660010, 0x50c0ffe6, 0x2021,
+0x2402021, 0xa001a32, 0x24020011, 0x2402021,
+0x24020015, 0xe0019e1, 0xa3820064, 0x240fffff,
+0x104fffdc, 0x2404ffff, 0xa001a21, 0x8e260000,
+0xa001a58, 0x24020014, 0x3c080004, 0xc83824,
+0x50e0ffd4, 0x2021, 0x2402021, 0xa001a32,
+0x24020013, 0x8f850034, 0x27bdffd8, 0xafb3001c,
+0xafb20018, 0xafb10014, 0xafb00010, 0xafbf0020,
+0x90a700d4, 0x8f900048, 0x2412ffff, 0x34e20040,
+0x92060000, 0xa0a200d4, 0x8e030010, 0x809821,
+0x10720006, 0x30d1003f, 0x2408000d, 0xe0019e1,
+0xa3880064, 0x10520025, 0x2404ffff, 0x8f8a0034,
+0x8e090018, 0x8d4400d0, 0x11240007, 0x2602021,
+0x240c000e, 0xe0019e1, 0xa38c0064, 0x240bffff,
+0x104b001a, 0x2404ffff, 0x24040020, 0x12240004,
+0x8f8d0034, 0x91af00d4, 0x35ee0020, 0xa1ae00d4,
+0x8f850050, 0x10a00019, 0x0, 0x1224004a,
+0x8f980034, 0x8f92fcb8, 0x97100080, 0x9651000a,
+0x52300048, 0x8f93003c, 0x3c1f0800, 0x8fff318c,
+0x3e5c82b, 0x1720001e, 0x2602021, 0x2821,
+0xe001940, 0x24060001, 0x2021, 0x8fbf0020,
0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0xa0016a9, 0x27bd0028, 0x31850003, 0x54a0fff4,
-0x2202021, 0x94cf001c, 0x8f8e0024, 0x8e070028,
-0xa5cf00d8, 0x8ccd0010, 0x24d3023, 0x10e6005c,
-0x2402001f, 0xe0016a9, 0xa3820050, 0x241fffff,
-0x105f004e, 0x2404ffff, 0x8f83003c, 0x8f88002c,
-0x2639821, 0x8d090010, 0x1231023, 0x8f83001c,
-0xad020010, 0xad130020, 0x8c670074, 0xf3202b,
-0x14800062, 0x2202021, 0x8f860038, 0x8e0c0024,
-0x8cc50024, 0x11850007, 0x2202021, 0x240e001c,
-0xe0016a9, 0xa38e0050, 0x240dffff, 0x104d0037,
-0x2404ffff, 0x8f84002c, 0x8c980024, 0x270f0001,
-0xac8f0024, 0x12720044, 0x8f99001c, 0x8f320074,
-0x12530041, 0x3c0a0080, 0x8e090000, 0x12a1024,
-0x1440003a, 0x0, 0x8e040014, 0x2412ffff,
-0x10920006, 0x240b001b, 0x2202021, 0xe0016a9,
-0xa38b0050, 0x10520021, 0x2404ffff, 0x8e030000,
-0x3c0c0001, 0x6c2824, 0x10a00013, 0x3c060080,
-0x66a024, 0x16800009, 0x2002821, 0x2202021,
-0x240e001a, 0xe0016a9, 0xa38e0050, 0x240dffff,
-0x104d0012, 0x2404ffff, 0x2002821, 0x2202021,
-0xe0016c9, 0x24060001, 0x2410ffff, 0x2404ffff,
-0x1050000a, 0x24140001, 0x8f8f002c, 0x2202021,
-0x2803021, 0x95f20034, 0x24050001, 0x26580001,
-0xe0017a5, 0xa5f80034, 0x2021, 0x8fbf0024,
-0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x801021, 0x3e00008, 0x27bd0028,
-0x8f83003c, 0xe3c821, 0x259c02b, 0x1300ffa8,
-0x8f88002c, 0xa00188e, 0x24020018, 0xac800020,
-0xa0018b8, 0x8e040014, 0x8e1f0000, 0x3c070080,
-0x3e79824, 0x1660fff9, 0x2408001a, 0x2202021,
-0xe0016a9, 0xa3880050, 0x2403ffff, 0x1443ffba,
-0x2404ffff, 0xa0018e1, 0x8fbf0024, 0x240b001d,
-0xe0016a9, 0xa38b0050, 0x240affff, 0x144aff9a,
-0x2404ffff, 0xa0018e1, 0x8fbf0024, 0x8f850024,
-0x27bdffd8, 0xafb3001c, 0xafb20018, 0xafb10014,
-0xafb00010, 0xafbf0020, 0x90a700c4, 0x8f900034,
-0x2412ffff, 0x34e20040, 0x92060000, 0xa0a200c4,
-0x8e030010, 0x809821, 0x10720006, 0x30d1003f,
-0x2408000d, 0xe0016a9, 0xa3880050, 0x10520026,
-0x2406ffff, 0x8f8a0024, 0x8e090018, 0x8d4400c0,
-0x11240007, 0x240c000e, 0x2602021, 0xe0016a9,
-0xa38c0050, 0x240bffff, 0x104b001b, 0x2406ffff,
-0x24040020, 0x12240004, 0x8f8d0024, 0x91af00c4,
-0x35ee0020, 0xa1ae00c4, 0x8f85003c, 0x10a0001a,
-0x0, 0x1224004b, 0x8f980024, 0x8f92fed4,
-0x2406fffd, 0x97100070, 0x9651000a, 0x1230000b,
-0x8fbf0020, 0x3c1f0800, 0x8fff318c, 0x3e5c82b,
-0x1720001e, 0x2602021, 0x2821, 0xe0017a5,
-0x24060001, 0x3021, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0xc01021,
-0x3e00008, 0x27bd0028, 0x5224002a, 0x8e030014,
-0x8f840024, 0x94890070, 0x25280001, 0xa4880070,
-0x94870070, 0x3c050800, 0x8ca53188, 0x30e27fff,
-0x1045000e, 0x0, 0x2602021, 0xe001730,
-0x24050001, 0xa001943, 0x3021, 0x2402002d,
-0xa3820050, 0xe0016a9, 0x2413ffff, 0x1453ffe1,
-0x2406ffff, 0xa001944, 0x8fbf0020, 0x94980070,
-0x24198000, 0x24050001, 0x3199024, 0xa4920070,
-0x90910070, 0x908d0070, 0x323000ff, 0x1079c2,
-0xf7027, 0xe61c0, 0x31ab007f, 0x16c5025,
-0xa08a0070, 0xe001730, 0x2602021, 0xa001943,
-0x3021, 0x2406ffff, 0x1466ffd6, 0x8f840024,
-0x2602021, 0xe001730, 0x24050001, 0xa001943,
-0x3021, 0x2602021, 0xa00195d, 0x2402000a,
-0x8f880024, 0x27bdffe8, 0xafb00010, 0xafbf0014,
-0x910a00c4, 0x8f870034, 0x808021, 0x35490040,
-0x8ce60010, 0xa10900c4, 0x3c020800, 0x8c4231b0,
-0x30c53fff, 0xa2182b, 0x10600007, 0x8f850038,
+0x801021, 0x3e00008, 0x27bd0028, 0x5224002a,
+0x8e050014, 0x8f840034, 0x948a0080, 0x25490001,
+0xa4890080, 0x94880080, 0x3c020800, 0x8c423188,
+0x31077fff, 0x10e2000e, 0x0, 0x2602021,
+0xe0018cb, 0x24050001, 0xa001aa2, 0x2021,
+0x2402002d, 0xe0019e1, 0xa3820064, 0x2403ffff,
+0x1443ffe1, 0x2404ffff, 0xa001aa3, 0x8fbf0020,
+0x94990080, 0x241f8000, 0x24050001, 0x33fc024,
+0xa4980080, 0x90920080, 0x908e0080, 0x325100ff,
+0x1181c2, 0x107827, 0xf69c0, 0x31cc007f,
+0x18d5825, 0xa08b0080, 0xe0018cb, 0x2602021,
+0xa001aa2, 0x2021, 0x2406ffff, 0x54a6ffd6,
+0x8f840034, 0x2602021, 0xe0018cb, 0x24050001,
+0xa001aa2, 0x2021, 0x2602021, 0xa001abc,
+0x2402000a, 0x2404fffd, 0xa001aa2, 0xaf93005c,
+0x8f880034, 0x27bdffe8, 0xafb00010, 0xafbf0014,
+0x910a00d4, 0x8f870048, 0x808021, 0x35490040,
+0x8ce60010, 0xa10900d4, 0x3c020800, 0x8c4231b0,
+0x30c53fff, 0xa2182b, 0x10600007, 0x8f85004c,
0x240dff80, 0x90ae000d, 0x1ae6024, 0x318b00ff,
0x15600008, 0x6c382, 0x2002021, 0x2403000d,
-0x8fbf0014, 0x8fb00010, 0x27bd0018, 0xa0016a9,
-0xa3830050, 0x33060003, 0x240f0002, 0x54cffff7,
-0x2002021, 0x94a2001c, 0x8f850024, 0x24190023,
-0xa4a200d8, 0x8ce80000, 0x81e02, 0x307f003f,
-0x13f90035, 0x3c0a0083, 0x8ce80018, 0x8ca600c0,
-0x11060008, 0x0, 0x2405000e, 0xe0016a9,
-0xa3850050, 0x2407ffff, 0x10470018, 0x2404ffff,
-0x8f850024, 0x90a900c4, 0x35240020, 0xa0a400c4,
-0x8f8c002c, 0x918e000d, 0x31cd007f, 0xa18d000d,
-0x8f83003c, 0x1060001c, 0x2002021, 0x8f840038,
+0x8fbf0014, 0x8fb00010, 0x27bd0018, 0xa0019e1,
+0xa3830064, 0x33060003, 0x240f0002, 0x54cffff7,
+0x2002021, 0x94a2001c, 0x8f850034, 0x24190023,
+0xa4a200e8, 0x8ce80000, 0x81e02, 0x307f003f,
+0x13f90035, 0x3c0a0083, 0x8ce80018, 0x8ca600d0,
+0x11060008, 0x0, 0x2405000e, 0xe0019e1,
+0xa3850064, 0x2407ffff, 0x10470018, 0x2404ffff,
+0x8f850034, 0x90a900d4, 0x35240020, 0xa0a400d4,
+0x8f8c0040, 0x918e000d, 0x31cd007f, 0xa18d000d,
+0x8f830050, 0x1060001c, 0x2002021, 0x8f84004c,
0x8c980010, 0x303782b, 0x11e0000d, 0x24190018,
-0x2002021, 0xa3990050, 0xe0016a9, 0x2410ffff,
+0x2002021, 0xa3990064, 0xe0019e1, 0x2410ffff,
0x10500002, 0x2404ffff, 0x2021, 0x8fbf0014,
0x8fb00010, 0x801021, 0x3e00008, 0x27bd0018,
-0x8c860010, 0x8f9f002c, 0x2002021, 0xc31023,
-0xafe20010, 0x24050001, 0xe0017a5, 0x24060001,
-0xa0019cc, 0x2021, 0xe001730, 0x24050001,
-0xa0019cc, 0x2021, 0x10a5824, 0x156affd9,
-0x8f8c002c, 0xa0a600ec, 0xa0019b9, 0xa3860042,
-0x27bdffd8, 0xafb00010, 0x8f900034, 0xafb20018,
-0xafbf0020, 0xafb3001c, 0xafb10014, 0x8e110010,
-0x3c030800, 0x8c6331b0, 0x32253fff, 0xa3102b,
-0x10400008, 0x809021, 0x8f860038, 0x2409ff80,
-0x90ca000d, 0x12a4024, 0x310700ff, 0x14e0000b,
-0x116b82, 0x2402021, 0x2412000d, 0xa3920050,
-0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0xa0016a9, 0x27bd0028, 0x31ac0003,
-0x240b0001, 0x558bfff4, 0x2402021, 0x90cf000d,
-0x31ee0008, 0x11c00060, 0x8f93003c, 0x16600009,
-0x24020027, 0x8e19000c, 0x8cd80020, 0x17380005,
-0x24020020, 0x8e020008, 0x8cdf0024, 0x105f0040,
-0x24020020, 0xe0016a9, 0xa3820050, 0x2406ffff,
-0x10460033, 0x2404ffff, 0x8f99002c, 0x240afff7,
-0x3c13800e, 0x9329000d, 0x2404ff80, 0x3c0d8000,
-0x12af824, 0xa33f000d, 0x8f99001c, 0x3c080800,
-0x8d0831ac, 0x8f830054, 0x97270078, 0x8f9f002c,
-0x1031021, 0x30e57fff, 0x53040, 0x467821,
-0x31f8007f, 0x3136021, 0x1e47024, 0xadae002c,
-0xa5910000, 0x8feb0028, 0x256a0001, 0xafea0028,
-0x8fe3002c, 0x8e09002c, 0x694021, 0xafe8002c,
-0x8e07002c, 0xafe70030, 0x8e050014, 0xafe50034,
-0x97e6003a, 0x24c20001, 0xa7e2003a, 0x97330078,
-0x3c100800, 0x8e1031b0, 0x26630001, 0x30717fff,
-0x12300027, 0x603021, 0x8f8f001c, 0x2402021,
-0x24050001, 0xe001730, 0xa5e60078, 0x2021,
-0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x801021, 0x3e00008, 0x27bd0028,
-0x8e050014, 0x2413ffff, 0x10b3001d, 0x8f830024,
-0x8e080018, 0x8c6700c0, 0x15070009, 0x2402000e,
-0x8e0a0024, 0x8cc90028, 0x15490005, 0x24020021,
-0x8e070028, 0x8ccb002c, 0x10eb0013, 0x2402001f,
-0xe0016a9, 0xa3820050, 0x1453ffb3, 0x2404ffff,
-0xa001a4e, 0x8fbf0020, 0xa001a16, 0x24020024,
-0x240e8000, 0x6e6824, 0x31acffff, 0xc5bc2,
-0x317100ff, 0x118027, 0xa001a47, 0x1033c0,
-0xa001a65, 0x24020025, 0x8e05002c, 0x10a0ffec,
-0x24020023, 0x8f8e001c, 0x8dcd0074, 0x1a5602b,
-0x1580ffe7, 0x24020026, 0x8ccf0014, 0xa7c021,
-0x1f8202b, 0x1080ff99, 0x8f99002c, 0x2402021,
-0xa001a65, 0x24020022, 0x27bdffe0, 0xafb00010,
-0x8f900034, 0xafb10014, 0xafbf0018, 0x8e050010,
-0x3c030800, 0x8c6331b0, 0x808821, 0x30a43fff,
-0x83102b, 0x10400007, 0x8f860038, 0x2409ff80,
-0x90ca000d, 0x12a4024, 0x310700ff, 0x14e00009,
-0x8f8b003c, 0x2410000d, 0x2202021, 0xa3900050,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0xa0016a9,
-0x27bd0020, 0x11600008, 0x5c382, 0x8f8f0024,
-0x8f8efed4, 0x2407fffd, 0x95ec0070, 0x95cd000a,
-0x11ac0038, 0x8fbf0018, 0x33050003, 0x14a00010,
-0x0, 0x92190002, 0x13200041, 0x0,
-0x8e060024, 0x50c0000f, 0x92040003, 0x2202021,
-0x2402000f, 0xe0016a9, 0xa3820050, 0x2408ffff,
-0x14480007, 0x2407ffff, 0xa001ae2, 0x8fbf0018,
-0x90c3000d, 0x30640008, 0x10800037, 0x2202021,
-0x92040003, 0x24070002, 0x308900ff, 0x15270005,
-0x308f00ff, 0x8f8a003c, 0x11400031, 0x240c002c,
-0x308f00ff, 0x39e50010, 0x2cad0001, 0x2dee0001,
-0x2002821, 0x1cd3025, 0xe0016c9, 0x2202021,
-0x2410ffff, 0x1050000e, 0x2407ffff, 0x8f83003c,
-0x10600017, 0x2202021, 0x3c190800, 0x8f39318c,
-0x323c02b, 0x5700000c, 0x2411002d, 0x2202021,
-0x2821, 0xe0017a5, 0x24060001, 0x3821,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0xe01021,
-0x3e00008, 0x27bd0020, 0xe0016a9, 0xa3910050,
-0x1450fff6, 0x2407ffff, 0xa001ae2, 0x8fbf0018,
-0xe001730, 0x24050001, 0xa001ae1, 0x3821,
-0x8cdf0024, 0x8e020024, 0x545fffc1, 0x2202021,
-0xa001ac2, 0x92040003, 0xa001ab6, 0x24020010,
-0x2202021, 0xe0016a9, 0xa38c0050, 0x240bffff,
-0x104bffe3, 0x2407ffff, 0xa001ac9, 0x92040003,
+0x8c860010, 0x8f9f0040, 0x2002021, 0xc31023,
+0xafe20010, 0x24050001, 0xe001940, 0x24060001,
+0xa001b2e, 0x2021, 0xe0018cb, 0x24050001,
+0xa001b2e, 0x2021, 0x10a5824, 0x156affd9,
+0x8f8c0040, 0xa0a600fc, 0xa001b1b, 0xa3860056,
0x30a500ff, 0x24060001, 0x24a90001, 0xc9102b,
0x1040000c, 0x4021, 0x240a0001, 0xa61823,
0x308b0001, 0x24c60001, 0x6a3804, 0x42042,
0x11600002, 0xc9182b, 0x1074025, 0x1460fff8,
0xa61823, 0x3e00008, 0x1001021, 0x27bdffd8,
-0xafb00018, 0x8f900034, 0xafb1001c, 0xafbf0020,
+0xafb00018, 0x8f900048, 0xafb1001c, 0xafbf0020,
0x2403ffff, 0x2411002f, 0xafa30010, 0x92060000,
-0x24050008, 0x26100001, 0x662026, 0xe001b01,
+0x24050008, 0x26100001, 0x662026, 0xe001b47,
0x308400ff, 0x21e00, 0x3c021edc, 0x34466f41,
-0xa001b29, 0x1021, 0x10a00009, 0x801821,
+0xa001b6f, 0x1021, 0x10a00009, 0x801821,
0x24450001, 0x30a2ffff, 0x2c450008, 0x461fffa,
0x32040, 0x862026, 0x14a0fff9, 0x801821,
-0xe001b01, 0x24050020, 0x8fa30010, 0x2629ffff,
+0xe001b47, 0x24050020, 0x8fa30010, 0x2629ffff,
0x313100ff, 0x34202, 0x240700ff, 0x1627ffe2,
0x1021826, 0x35027, 0xafaa0014, 0xafaa0010,
0x3021, 0x27a80010, 0x27a70014, 0xe67823,
0x91ed0003, 0x24ce0001, 0xc86021, 0x31c600ff,
0x2ccb0004, 0x1560fff9, 0xa18d0000, 0x8fa20010,
0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0028, 0x93830030, 0x27bdffe0, 0x24020034,
-0xafb10014, 0xafb00010, 0xafbf001c, 0xafb20018,
-0x808821, 0x10620062, 0xa08021, 0x92040004,
-0x14800045, 0x8f880024, 0xa3800028, 0x8e050004,
-0x8d0600c8, 0x3c0700ff, 0x34e3ffff, 0xa32824,
-0xc5102b, 0x1440004d, 0xaf85003c, 0x978a0044,
-0x8f870048, 0x1471023, 0x10a00032, 0xa7820044,
-0x8f98001c, 0x304cffff, 0x9312007c, 0x127882,
-0x31f10001, 0x117080, 0x1c56821, 0x18d582b,
-0x11600061, 0x8f860024, 0x8f890020, 0x8f84004c,
-0x1089005e, 0x3c023f01, 0x8e1f0000, 0x3c102500,
-0x3e2c824, 0x1730007a, 0x8f840034, 0x8f870034,
-0x8f860024, 0x8ce30000, 0xacc30078, 0x8ce50010,
-0xacc50088, 0x8f870048, 0x8f85003c, 0x938d0028,
-0x30ae0003, 0xe4023, 0x310a0003, 0x14d4021,
-0xa3880028, 0x94cb00ac, 0x1276021, 0xaf8c0020,
-0x35691000, 0xa4c900ac, 0x16200051, 0x1452021,
-0xaf840048, 0x2021, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x801021, 0x3e00008,
-0x27bd0020, 0x8f840020, 0xaf800048, 0x873021,
-0xa001b92, 0xaf860020, 0x241f000c, 0xa39f0050,
-0xe0016a9, 0x2202021, 0x2419ffff, 0x1059ffee,
-0x2404ffff, 0x8f880024, 0xa3800028, 0x8e050004,
-0x8d0600c8, 0x3c0700ff, 0x34e3ffff, 0xa32824,
-0xc5102b, 0x1040ffb5, 0xaf85003c, 0x2202021,
-0x24090019, 0xa3890050, 0xe0016a9, 0x2411ffff,
-0x1051ffdd, 0x2404ffff, 0xa001b64, 0x8f85003c,
-0x8f840024, 0x8f870034, 0x8cf20030, 0x908600c4,
-0x30c50010, 0x14a00010, 0x8f830048, 0x2c680005,
-0x15000028, 0x0, 0x908a00c4, 0x246bfffc,
-0x31490010, 0x15200008, 0x316400ff, 0x8f8d004c,
-0x8f8c0020, 0x11ac0004, 0x388f0001, 0x31ee0001,
-0x15c0002f, 0x0, 0xe001b14, 0x0,
-0xa001beb, 0x0, 0x8f890020, 0x938d0028,
-0x30ae0003, 0xe4023, 0x310a0003, 0x14d4021,
-0xa3880028, 0x94cb00ac, 0x1276021, 0xaf8c0020,
-0x35691000, 0xa4c900ac, 0x1220ffb1, 0x1452021,
-0x25180004, 0xa3980028, 0x94cf00ac, 0x24920004,
-0xaf920048, 0x35f12000, 0xa4d100ac, 0xa001b93,
-0x2021, 0x8c8200dc, 0x1242ff6c, 0x2202021,
-0x24180005, 0xa3980050, 0xe0016a9, 0x2412ffff,
-0x1452ff66, 0x2404ffff, 0xa001b94, 0x8fbf001c,
-0x30e500ff, 0xe0015b0, 0x3021, 0x8f860024,
-0x8f870048, 0x8f890020, 0xa001b84, 0x8f85003c,
-0xe0015db, 0x0, 0xa001beb, 0x0,
-0x93830042, 0x27bdffe0, 0x24020002, 0xafb20018,
-0xafb10014, 0xafbf001c, 0x808821, 0xafb00010,
-0x9021, 0x10620055, 0x2404fffd, 0x97830044,
-0x8f850048, 0x3066ffff, 0xc5202b, 0x1480005b,
-0x93870030, 0x3c088000, 0x95040120, 0x10e50052,
-0x8f8a0020, 0x8f84004c, 0x30a500ff, 0xe0015b0,
-0x24060001, 0x8f9f0054, 0x3c058000, 0x3c194080,
-0x27ed0178, 0x31b00078, 0x240eff80, 0x2195825,
-0x34af0900, 0x31b80007, 0x1ae6024, 0xacac0800,
-0x30f8021, 0xacab0810, 0x2202021, 0x2002821,
-0xe001b4e, 0xaf900034, 0x2403ffff, 0x10430033,
-0x2404ffff, 0x8e0c0010, 0x3c070800, 0x8ce731b0,
-0x92060000, 0x31843fff, 0x87102b, 0x10400023,
-0x30cd003f, 0x8f980054, 0x47180, 0x3c040800,
-0x8c8431a8, 0x2409ff80, 0x93900041, 0x984021,
-0x10e2021, 0x897024, 0xe5140, 0x3c098000,
-0x3099007f, 0x3c0f0080, 0x8f880024, 0x35250940,
-0x35e20001, 0x1593825, 0x308b0078, 0x30860007,
-0x3c031000, 0x3c1f800c, 0xc5c021, 0x1625825,
-0xe35025, 0x33f7821, 0x36050001, 0xad2e0804,
-0xaf980038, 0xad2b0814, 0xaf8f002c, 0xad2e0028,
-0xad040074, 0xad2a0830, 0xa3850041, 0x93830042,
-0x24100003, 0x50700027, 0x25a3ffe0, 0x240c0001,
-0x106c001c, 0x24060023, 0x2402021, 0x8fbf001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x801021,
-0x3e00008, 0x27bd0020, 0x31490003, 0x5520ffae,
-0x8f84004c, 0xa001c27, 0x8f90004c, 0x8f84004c,
-0x306500ff, 0xe0015b0, 0x24060001, 0x938b0030,
-0x24050034, 0x11650018, 0x97830044, 0x8f850048,
-0x3062ffff, 0xa25823, 0xaf8b0048, 0xa001c5f,
-0xa7800044, 0x11a60037, 0x0, 0x2202021,
-0x2411000b, 0xe0016a9, 0xa3910050, 0xa001c5f,
-0x409021, 0x2c720020, 0x1240fff8, 0x3f880,
-0x3c070800, 0x24e77960, 0x3e7c821, 0x8f2d0000,
-0x1a00008, 0x0, 0x8f850048, 0x2ca20005,
-0x5440001d, 0xa7800044, 0x978a0044, 0x3148ffff,
-0xa84823, 0x2d2f0005, 0x11e00003, 0x314400ff,
-0x24aefffc, 0x31c400ff, 0x8f90004c, 0x8f980020,
-0x12180004, 0x38990001, 0x332d0001, 0x15a00029,
-0x0, 0x8f910024, 0x922500c4, 0x34a30010,
-0xa22300c4, 0x97830044, 0x8f850048, 0x8f840024,
-0x3062ffff, 0xa25823, 0xac8000dc, 0xa7800044,
-0xa001c5f, 0xaf8b0048, 0x3062ffff, 0xa25823,
-0xa001c5f, 0xaf8b0048, 0x2403ffff, 0x11830005,
-0x0, 0xe001981, 0x2202021, 0xa001c5f,
-0x409021, 0xe001908, 0x2202021, 0xa001c5f,
-0x409021, 0xe0019e5, 0x2202021, 0xa001c5f,
-0x409021, 0xe00185f, 0x2202021, 0xa001c5f,
-0x409021, 0xe001a87, 0x2202021, 0xa001c5f,
-0x409021, 0xe0015db, 0x0, 0x97830044,
-0x8f850048, 0x306cffff, 0xac3823, 0x2cff0005,
-0x53e0ffa8, 0x3062ffff, 0x8f860024, 0xa7800044,
-0xacc200dc, 0x3062ffff, 0xa25823, 0xa001c5f,
-0xaf8b0048, 0x27bdffd0, 0xafb20018, 0xafb00010,
-0xafbf0028, 0xafb50024, 0xafb40020, 0xafb3001c,
+0x27bd0028, 0x27bdffd0, 0xafb3001c, 0xafb00010,
+0xafbf0028, 0xafb50024, 0xafb40020, 0xafb20018,
0xafb10014, 0x3c0c8000, 0x8d880128, 0x240fff80,
-0x3c07800a, 0x25100100, 0x250b0080, 0x20f6824,
-0x3205007f, 0x16f7024, 0xad8e0090, 0xa72821,
-0xad8d0024, 0x90a700ec, 0x3169007f, 0x3c0a8004,
-0x12a1821, 0xa3870042, 0x9066007c, 0x809021,
-0xaf83001c, 0x30c20002, 0xaf880054, 0xaf850024,
+0x3c06800a, 0x25100100, 0x250b0080, 0x20f6824,
+0x3205007f, 0x16f7024, 0xad8e0090, 0xa62821,
+0xad8d0024, 0x90a600fc, 0x3169007f, 0x3c0a8004,
+0x12a1821, 0xa3860056, 0x9067007c, 0x809821,
+0xaf83002c, 0x30e20002, 0xaf880068, 0xaf850034,
0xa01821, 0x14400002, 0x24040034, 0x24040030,
-0xa3840030, 0x8c6600cc, 0x30f100ff, 0x24040004,
-0xaf860048, 0x12240004, 0xa3800050, 0x8e530004,
-0x1660001d, 0x3c088000, 0x93870041, 0x30f20001,
-0x1240000f, 0x8fbf0028, 0x8cb80074, 0x8ca40074,
-0x2419ff80, 0x3198824, 0x117140, 0x308f007f,
-0x1cf6025, 0x3c0d2000, 0x18d5825, 0x30f500fe,
-0x3c0a8000, 0xad4b0830, 0xa3950041, 0x8fbf0028,
-0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x24020001, 0x27bd0030,
-0x3e00008, 0xaca600cc, 0x8e590008, 0x951f0120,
-0x8e460010, 0x33fc021, 0x3307ffff, 0x30f5000f,
-0x32b40001, 0xaf860020, 0x1680003b, 0xa3950040,
-0x35060c00, 0x2a61021, 0xf51823, 0xad030084,
-0xaf82004c, 0x8e490004, 0x3128ffff, 0x1100002b,
-0xa7890044, 0x2410ff80, 0x3c158000, 0x3c142000,
-0xa001d4d, 0x2413fffe, 0x90ae00c4, 0x20e6824,
-0x31ac00ff, 0x1580002a, 0x2402021, 0x93840041,
-0x97860044, 0x308f0001, 0x11e0000b, 0x2642824,
-0x8f890024, 0x8d230074, 0x8d280074, 0xa3850041,
-0x701024, 0x2c940, 0x311f007f, 0x33fc025,
-0x3148825, 0xaeb10830, 0x10c00010, 0x8f850024,
-0x90a700c4, 0x2075824, 0x316a00ff, 0x1540ffe6,
-0x2402021, 0xe001c01, 0x97910044, 0x1040ffe8,
-0x93840041, 0x2405fffd, 0x54450005, 0x8e430020,
-0x2202821, 0xe001586, 0x2402021, 0x8e430020,
-0x30700004, 0x1600000a, 0x2414fffb, 0x8f850024,
-0xa001d03, 0x8f860048, 0xa001d2e, 0xaf86004c,
-0xe00182b, 0x0, 0xa001d3d, 0x93840041,
-0x749824, 0xe0015a0, 0xae530020, 0x8f850024,
-0xa001d03, 0x8f860048, 0x27bdffd8, 0xafb3001c,
-0xafb10014, 0xafbf0020, 0xafb20018, 0xafb00010,
-0x3c028000, 0x8c520140, 0x8c4b0148, 0x3c048000,
-0xb8c02, 0x322300ff, 0x317300ff, 0x8c8501b8,
-0x4a0fffe, 0x34900180, 0xae120000, 0x8c870144,
-0x2464fff0, 0x24060002, 0x2c830013, 0xae070004,
-0xa6110008, 0xa206000b, 0xae130024, 0x1060004f,
-0x8fbf0020, 0x44880, 0x3c0a0800, 0x254a79e0,
-0x12a4021, 0x8d040000, 0x800008, 0x0,
-0x3c100800, 0x8e1031a8, 0x31733fff, 0x138980,
-0x2122821, 0x240cff80, 0xb12021, 0x264d0100,
-0x26470080, 0x3c0f8000, 0x3c038004, 0x31a8007f,
-0x30e9007f, 0x308a007f, 0x3c0e800a, 0x3c02800c,
-0x8cc024, 0x1ac3024, 0xecc824, 0x1239821,
-0x1428021, 0xade60024, 0x10ef821, 0xadf90090,
-0xadf80028, 0xaf90002c, 0xaf9f0024, 0xaf93001c,
-0xe001675, 0x1608021, 0x3c038000, 0x8c6b01b8,
-0x560fffe, 0x8f87002c, 0x8f860024, 0x34650180,
-0x90f9000d, 0xacb20000, 0x24c20078, 0x19c600,
-0x187e03, 0xf9027, 0x1227c2, 0xa4b00006,
-0x10800070, 0x240e6082, 0xa4ae0008, 0xa0a00005,
-0x240f0002, 0xa0af000b, 0x4c400, 0x8f8b001c,
-0x3c192700, 0x3199025, 0xacb20010, 0xaca00014,
-0xaca00024, 0xaca00028, 0xaca0002c, 0x8d730038,
-0x2411ff80, 0xacb30018, 0x90f0000d, 0x2302824,
-0x30a400ff, 0x10800005, 0x8fbf0020, 0x90ec000d,
-0x319f007f, 0xa0ff000d, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3c0a1000,
-0x3c0d8000, 0x27bd0028, 0x3e00008, 0xadaa01b8,
-0x265f0100, 0x2405ff80, 0x33f8007f, 0x3c068000,
-0x3e57824, 0x3c19800a, 0x3192021, 0xaccf0024,
-0x908e00c4, 0xae6824, 0x31ac00ff, 0x1180ffea,
-0xaf840024, 0x248e0078, 0x95cd0012, 0x3c0c0800,
-0x8d8c31a8, 0x3c03800c, 0x31ab3fff, 0x1924821,
-0xb5180, 0x12a4021, 0x3104007f, 0x1051024,
-0x833821, 0xacc20028, 0xe001675, 0xaf87002c,
-0x3c038000, 0x8c6501b8, 0x4a0fffe, 0x0,
-0xae120000, 0x8c720144, 0xae120004, 0xa6110008,
-0x24110002, 0xa211000b, 0xae130024, 0xa001dd8,
-0x8fbf0020, 0x3c126000, 0x8e452c08, 0x3c03f003,
-0x3462ffff, 0xa2f824, 0xae5f2c08, 0x8e582c08,
-0x3c1901b0, 0x3199825, 0xae532c08, 0xa001dd8,
-0x8fbf0020, 0x264d0100, 0x31af007f, 0x3c10800a,
-0x240eff80, 0x1f02821, 0x1ae6024, 0x3c0b8000,
-0xad6c0024, 0x1660ffb8, 0xaf850024, 0x24110003,
-0xa0b100ec, 0xa001dd8, 0x8fbf0020, 0x26480100,
-0x310a007f, 0x3c0b800a, 0x2409ff80, 0x14b3021,
-0x1092024, 0x3c078000, 0xace40024, 0xa001dd7,
-0xaf860024, 0x944d0012, 0x321f3fff, 0x31ac3fff,
-0x159fff8d, 0x240e6082, 0x90c300c4, 0x2409ff80,
-0x1231024, 0x304a00ff, 0x1140ff87, 0x0,
-0x24070004, 0xa0c700ec, 0x8f87002c, 0x24086084,
-0x2406000d, 0xa4a80008, 0xa0a60005, 0xa001dc2,
-0x240f0002, 0x0 };
-u32 bce_RXP_b09FwData[(0x0/4) + 1] = { 0x0 };
-u32 bce_RXP_b09FwRodata[(0x124/4) + 1] = {
-0x5f865437, 0xe4ac62cc, 0x50103a45,
-0x36621985, 0xbf14c0e8, 0x1bc27a1e, 0x84f4b556,
-0x94ea6fe, 0x7dda01e7, 0xc04d7481, 0x80080100,
-0x80080080, 0x80080000, 0x8004fbc, 0x8004fbc,
-0x8005098, 0x800506c, 0x8005050, 0x8004f8c,
-0x8004f8c, 0x8004f8c, 0x8004fc4, 0x80072bc,
-0x8007308, 0x80072c8, 0x80071f0, 0x80072c8,
-0x80072f8, 0x80072c8, 0x80071f0, 0x80071f0,
-0x80071f0, 0x80071f0, 0x80071f0, 0x80071f0,
-0x80071f0, 0x80071f0, 0x80071f0, 0x80071f0,
-0x80072e8, 0x80072d8, 0x80071f0, 0x80071f0,
-0x80071f0, 0x80071f0, 0x80071f0, 0x80071f0,
-0x80071f0, 0x80071f0, 0x80071f0, 0x80071f0,
-0x80071f0, 0x80071f0, 0x80072d8, 0x8007890,
-0x800775c, 0x8007858, 0x800775c, 0x8007828,
-0x8007644, 0x800775c, 0x800775c, 0x800775c,
-0x800775c, 0x800775c, 0x800775c, 0x800775c,
-0x800775c, 0x800775c, 0x800775c, 0x800775c,
-0x800775c, 0x8007784, 0x0 };
-u32 bce_RXP_b09FwBss[(0x20/4) + 1] = { 0x0 };
-u32 bce_RXP_b09FwSbss[(0x58/4) + 1] = { 0x0 };
-u32 bce_RXP_b09FwSdata[(0x0/4) + 1] = { 0x0 };
+0xa3840044, 0x8c7200dc, 0x30d100ff, 0x24040004,
+0xaf92005c, 0x12240004, 0xa3800064, 0x8e740004,
+0x1680001e, 0x3c088000, 0x93860055, 0x30c70001,
+0x50e0000f, 0x8f86005c, 0x8ca40084, 0x8ca80084,
+0x2413ff80, 0x936024, 0xc4940, 0x3110007f,
+0x1307825, 0x3c192000, 0x1f96825, 0x30df00fe,
+0x3c038000, 0xac6d0830, 0xa39f0055, 0x8f86005c,
+0x8fbf0028, 0x8fb50024, 0x8fb40020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x24020001,
+0x27bd0030, 0x3e00008, 0xaca600dc, 0x8e7f0008,
+0x95020120, 0x8e670010, 0x3e2c821, 0x3326ffff,
+0x30d8000f, 0x33150001, 0xaf870030, 0x16a00058,
+0xa3980054, 0x35090c00, 0x3093821, 0xd81823,
+0xad030084, 0xaf870060, 0x8e6a0004, 0x3148ffff,
+0x1100007e, 0xa78a0058, 0x90ac00d4, 0x2407ff80,
+0xec3024, 0x30cb00ff, 0x1560004b, 0x97860058,
+0x938e0056, 0x240d0002, 0x30d5ffff, 0x11cd02a2,
+0xa021, 0x8f85005c, 0x2a5802b, 0x160000bc,
+0x93880044, 0x3c118000, 0x96240120, 0x310400ff,
+0x14850088, 0x8f840060, 0x8f980030, 0x33120003,
+0x56400085, 0x30a500ff, 0x8f900060, 0x310c00ff,
+0x24060034, 0x11860095, 0xaf900048, 0x92040004,
+0x14800119, 0x8f8e0034, 0xa3800038, 0x8e0d0004,
+0x8dc800d8, 0x3c0600ff, 0x34ccffff, 0x1ac3024,
+0x106182b, 0x14600121, 0xaf860050, 0x8f87005c,
+0x97980058, 0xaf87003c, 0x3074023, 0x10c000c7,
+0xa7880058, 0x8f91002c, 0x30c30003, 0x35823,
+0x922a007c, 0x31710003, 0x2261021, 0xa2082,
+0x30920001, 0x124880, 0x492821, 0x311fffff,
+0x3e5c82b, 0x13200120, 0x8f880034, 0x8f850030,
+0x8f880060, 0x1105025a, 0x3c0e3f01, 0x8e060000,
+0x3c0c2500, 0xce6824, 0x11ac0163, 0x8f840048,
+0x30e500ff, 0xe0017e1, 0x3021, 0x8f880034,
+0x8f87005c, 0x8f850030, 0xa001d4e, 0x8f860050,
+0xa001bed, 0xaf870060, 0x90ac00d4, 0xec2024,
+0x309000ff, 0x12000016, 0x93860055, 0x90b50088,
+0x90b400d7, 0x24a80088, 0x32a2003f, 0x2446ffe0,
+0x2cd10020, 0xa3940038, 0x1220000c, 0xaf880048,
+0x240e0001, 0xce2004, 0x308a0019, 0x1540012b,
+0x3c068000, 0x34d80002, 0x985824, 0x1560022e,
+0x30920020, 0x16400234, 0x0, 0x93860055,
+0x30ce0001, 0x11c0000f, 0x97880058, 0x8ca90084,
+0x8caf0084, 0x2410ff80, 0x130c824, 0x191940,
+0x31ed007f, 0x6d3825, 0x3c1f2000, 0xff9025,
+0x30cb00fe, 0x3c188000, 0xaf120830, 0xa38b0055,
+0x97880058, 0x1500ff84, 0x0, 0x8e630020,
+0x306c0004, 0x1180ff51, 0x93860055, 0x2404fffb,
+0x643024, 0x3c038000, 0xae660020, 0x34660180,
+0x8c7301b8, 0x660fffe, 0x8f8e0068, 0x346a0100,
+0x3c150001, 0xacce0000, 0x8c620124, 0x24076085,
+0xacc20004, 0x8d540004, 0x2958824, 0x52200001,
+0x24076083, 0x24120002, 0x3c181000, 0x3c0b8000,
+0xa4c70008, 0xa0d2000b, 0xad7801b8, 0xa001bc2,
+0x93860055, 0x30a500ff, 0xe0017e1, 0x24060001,
+0x8f880068, 0x3c058000, 0x34a90900, 0x25020188,
+0x93880044, 0x304a0007, 0x304b0078, 0x3c034080,
+0x2407ff80, 0x163c825, 0x1498021, 0x47f824,
+0x310c00ff, 0x24060034, 0xacbf0800, 0xaf900048,
+0xacb90810, 0x5586ff6e, 0x92040004, 0x8f840034,
+0x8e110030, 0x908e00d4, 0x31cd0010, 0x15a00010,
+0x8f83005c, 0x2c6f0005, 0x15e000e4, 0x0,
+0x909800d4, 0x2465fffc, 0x33120010, 0x16400008,
+0x30a400ff, 0x8f9f0060, 0x8f990030, 0x13f90004,
+0x38870001, 0x30e20001, 0x144001c8, 0x0,
+0xe001b5a, 0x0, 0xa001d8f, 0x0,
+0x8f840060, 0x30c500ff, 0xe0017e1, 0x24060001,
+0x938e0044, 0x240a0034, 0x11ca00a0, 0x8f850034,
+0x8f86005c, 0x97830058, 0x3062ffff, 0xc28823,
+0xaf91005c, 0xa7800058, 0x1280ff90, 0x2801821,
+0x2414fffd, 0x5474ffa2, 0x8e630020, 0x8e690004,
+0x2403ffbf, 0x240bffef, 0x135c823, 0xae790004,
+0x90af00d4, 0x31ed007f, 0xa0ad00d4, 0x8e660020,
+0x8f980034, 0xa7800058, 0x34df0002, 0xae7f0020,
+0xa70000bc, 0x931200d4, 0x2434024, 0xa30800d4,
+0x8f950034, 0xaea000ec, 0x92ae00d4, 0x1cb5024,
+0xa2aa00d4, 0xa001c6e, 0x8f850034, 0x8f910030,
+0xaf80005c, 0x2275821, 0xaf8b0030, 0x2021,
+0x2403ffff, 0x108301b4, 0x8f850034, 0x8e0c0010,
+0x3c0d0800, 0x8dad31b0, 0x92080000, 0x31843fff,
+0x8d802b, 0x12000023, 0x310d003f, 0x3c190800,
+0x8f3931a8, 0x8f9f0068, 0x47980, 0x2408ff80,
+0x33f2021, 0x8fc821, 0x93850055, 0x328f824,
+0x3c060080, 0x3c0f8000, 0x34d80001, 0x1f9140,
+0x3331007f, 0x8f860034, 0x2515025, 0x35ee0940,
+0x332b0078, 0x33300007, 0x3c031000, 0x3c02800c,
+0x1789025, 0x20e4821, 0x143c025, 0x2223821,
+0x34ae0001, 0xadff0804, 0xaf89004c, 0xadf20814,
+0xaf870040, 0xadff0028, 0xacd90084, 0xadf80830,
+0xa38e0055, 0x93830056, 0x24070003, 0x50670028,
+0x25a3ffe0, 0x240c0001, 0x146cffab, 0x8f850034,
+0x24110023, 0x11b10084, 0x0, 0x2402000b,
+0x2602021, 0xe0019e1, 0xa3820064, 0x40a021,
+0xa001cc9, 0x8f850034, 0x2602021, 0x240b000c,
+0xe0019e1, 0xa38b0064, 0x240affff, 0x104affbc,
+0x2404ffff, 0x8f8e0034, 0xa3800038, 0x8e0d0004,
+0x8dc800d8, 0x3c0600ff, 0x34ccffff, 0x1ac3024,
+0x106182b, 0x1060fee1, 0xaf860050, 0x2602021,
+0x24120019, 0xe0019e1, 0xa3920064, 0x240fffff,
+0x104fffab, 0x2404ffff, 0xa001c1a, 0x8f860050,
+0x2c740020, 0x1280ffde, 0x2402000b, 0x32880,
+0x3c110801, 0x263192ec, 0xb14821, 0x8d2d0000,
+0x1a00008, 0x0, 0x8f850030, 0xa71021,
+0x93850038, 0xaf820030, 0x2251821, 0xa3830038,
+0x951f00bc, 0x2262821, 0x37f91000, 0xa51900bc,
+0x5240ff92, 0xaf85005c, 0x246a0004, 0xa38a0038,
+0x950900bc, 0x24a40004, 0xaf84005c, 0x35322000,
+0xa51200bc, 0xa001ceb, 0x2021, 0x8f86005c,
+0x2ccb0005, 0x1560ff60, 0x97830058, 0x3072ffff,
+0xd24023, 0x2d180005, 0x13000003, 0x306400ff,
+0x24dffffc, 0x33e400ff, 0x8f850060, 0x8f860030,
+0x10a60004, 0x388f0001, 0x31ed0001, 0x15a00138,
+0x0, 0x8f840034, 0x908c00d4, 0x35870010,
+0xa08700d4, 0x8f850034, 0x8f86005c, 0x97830058,
+0xaca000ec, 0xa001cc6, 0x3062ffff, 0x8caa0084,
+0x8cb50084, 0x3c041000, 0x1471024, 0x28940,
+0x32b4007f, 0x2343025, 0xc46025, 0x3c088000,
+0x24050001, 0x2602021, 0x24060001, 0xe001940,
+0xad0c0830, 0xa001c5a, 0x8f850034, 0x8c8200ec,
+0x1222fe7e, 0x2602021, 0x24090005, 0xa3890064,
+0xe0019e1, 0x2411ffff, 0x1451fe78, 0x2404ffff,
+0xa001cec, 0x2403ffff, 0x8f8f0048, 0x8f880034,
+0x8df80000, 0xad180088, 0x8de70010, 0xad070098,
+0x8f87005c, 0xa001d4e, 0x8f860050, 0x2407ffff,
+0x11870005, 0x0, 0xe001ae3, 0x2602021,
+0xa001d27, 0x40a021, 0xe001a68, 0x2602021,
+0xa001d27, 0x40a021, 0x8f900048, 0x3c090800,
+0x8d2931b0, 0x8e110010, 0x32323fff, 0x249682b,
+0x11a0000c, 0x240aff80, 0x8f85004c, 0x90ae000d,
+0x14e1024, 0x304c00ff, 0x11800007, 0x2602021,
+0x11c382, 0x33030003, 0x240b0001, 0x106b0105,
+0x0, 0x2602021, 0x2418000d, 0xe0019e1,
+0xa3980064, 0x402021, 0x8f850034, 0xa001cc9,
+0x80a021, 0x8f900048, 0x3c0a0800, 0x8d4a31b0,
+0x8f85004c, 0x8e040010, 0xa021, 0x8cb10014,
+0x30823fff, 0x4a602b, 0x8cb20020, 0x5180ffee,
+0x2602021, 0x90b8000d, 0x240bff80, 0x1787024,
+0x31c300ff, 0x5060ffe8, 0x2602021, 0x44382,
+0x31060003, 0x14c0ffe4, 0x2602021, 0x94bf001c,
+0x8f990034, 0x8e060028, 0xa73f00e8, 0x8caf0010,
+0x22f2023, 0x14c40139, 0x2602021, 0x8f830050,
+0xc36821, 0x22d382b, 0x14e00135, 0x24020018,
+0x8f8a0040, 0x8f82002c, 0x2439021, 0x8d4b0010,
+0x1637023, 0xad4e0010, 0xad520020, 0x8c4c0074,
+0x192282b, 0x14a00156, 0x2602021, 0x8f84004c,
+0x8e080024, 0x8c860024, 0x11060007, 0x2602021,
+0x2419001c, 0xe0019e1, 0xa3990064, 0x240fffff,
+0x104fffc5, 0x2404ffff, 0x8f840040, 0x8c870024,
+0x24ff0001, 0xac9f0024, 0x12510133, 0x8f8d002c,
+0x8db10074, 0x12320130, 0x3c0b0080, 0x8e0e0000,
+0x1cb5024, 0x15400075, 0x0, 0x8e030014,
+0x2411ffff, 0x10710006, 0x2602021, 0x2418001b,
+0xe0019e1, 0xa3980064, 0x1051ffaf, 0x2404ffff,
+0x8e030000, 0x3c080001, 0x683024, 0x10c00013,
+0x3c040080, 0x64a024, 0x16800009, 0x2002821,
+0x2602021, 0x2419001a, 0xe0019e1, 0xa3990064,
+0x240fffff, 0x104fffa0, 0x2404ffff, 0x2002821,
+0x2602021, 0xe001a01, 0x24060001, 0x2410ffff,
+0x1050ff99, 0x2404ffff, 0x24140001, 0x8f9f0040,
+0x2602021, 0x2803021, 0x97f10034, 0x24050001,
+0x26270001, 0xa7e70034, 0xe001940, 0x0,
+0x2021, 0x8f850034, 0xa001cc9, 0x80a021,
+0x8f900048, 0x3c140800, 0x8e9431b0, 0x8e070010,
+0x30e83fff, 0x114302b, 0x10c00061, 0x8f86004c,
+0x241fff80, 0x90c5000d, 0x3e52024, 0x309200ff,
+0x5240005c, 0x2602021, 0x8f8d0050, 0x11a00007,
+0x78b82, 0x8f850034, 0x8f89fcb8, 0x94af0080,
+0x9539000a, 0x132f00f6, 0x8f87003c, 0x322c0003,
+0x15800063, 0x0, 0x92020002, 0x104000d7,
+0x0, 0x8e0a0024, 0x154000d8, 0x2602021,
+0x92040003, 0x24060002, 0x308800ff, 0x15060005,
+0x308500ff, 0x8f940050, 0x528000f2, 0x2602021,
+0x308500ff, 0x38ad0010, 0x2da40001, 0x2cbf0001,
+0x3e43025, 0x2002821, 0xe001a01, 0x2602021,
+0x2410ffff, 0x105000be, 0x8f850034, 0x8f830050,
+0x106000c4, 0x24050001, 0x3c190800, 0x8f39318c,
+0x323782b, 0x15e000b1, 0x2409002d, 0x2602021,
+0x2821, 0xe001940, 0x24060001, 0x8f850034,
+0x1821, 0xa001cc9, 0x60a021, 0xe00180c,
+0x0, 0xa001d8f, 0x0, 0xac800020,
+0xa001e0f, 0x8e030014, 0x2821, 0x2602021,
+0xe001940, 0x24060001, 0xa001c5a, 0x8f850034,
+0xa001d4e, 0x8f880034, 0x8cb00084, 0x8cb90084,
+0x3c031000, 0x2074824, 0x96940, 0x332f007f,
+0x1aff825, 0x3e32825, 0xacc50830, 0x91070001,
+0x24050001, 0x2602021, 0xe001940, 0x30e60001,
+0xa001c5a, 0x8f850034, 0x938f0044, 0x2403fffd,
+0xa001ccb, 0xaf8f005c, 0xa001ccb, 0x2403ffff,
+0x2602021, 0x2410000d, 0xe0019e1, 0xa3900064,
+0x401821, 0x8f850034, 0xa001cc9, 0x60a021,
+0xe00180c, 0x0, 0x97830058, 0x8f86005c,
+0x3070ffff, 0xd04823, 0x2d390005, 0x1320fe12,
+0x8f850034, 0xaca200ec, 0xa001cc6, 0x3062ffff,
+0x90c3000d, 0x30780008, 0x5700ffa2, 0x92040003,
+0x2602021, 0x24020010, 0xe0019e1, 0xa3820064,
+0x2403ffff, 0x5443ff9b, 0x92040003, 0xa001ea9,
+0x8f850034, 0x90a8000d, 0x31060008, 0x10c00095,
+0x8f940050, 0x1680009e, 0x2602021, 0x8e0f000c,
+0x8ca40020, 0x55e40005, 0x2602021, 0x8e1f0008,
+0x8cb90024, 0x13f9003a, 0x2602021, 0x24020020,
+0xe0019e1, 0xa3820064, 0x2405ffff, 0x1045feee,
+0x2404ffff, 0x8f8f0040, 0x240cfff7, 0x2403ff80,
+0x91e9000d, 0x3c14800e, 0x3c0b8000, 0x12cc824,
+0xa1f9000d, 0x8f8f002c, 0x3c070800, 0x8ce731ac,
+0x8f8d0068, 0x95e50078, 0x8f990040, 0xed9021,
+0x30bf7fff, 0x1f2040, 0x2443021, 0x30c8007f,
+0xc3c024, 0x1147021, 0xad78002c, 0xa5d10000,
+0x8f2a0028, 0x25420001, 0xaf220028, 0x8f29002c,
+0x8e0c002c, 0x12c6821, 0xaf2d002c, 0x8e07002c,
+0xaf270030, 0x8e050014, 0xaf250034, 0x973f003a,
+0x27e40001, 0xa724003a, 0x95f20078, 0x3c100800,
+0x8e1031b0, 0x26430001, 0x30717fff, 0x1230005c,
+0x603021, 0x8f83002c, 0x2602021, 0x24050001,
+0xe0018cb, 0xa4660078, 0xa001e38, 0x2021,
+0x8e070014, 0x2412ffff, 0x10f20063, 0x8f8c0034,
+0x8e090018, 0x8d8d00d0, 0x152d005d, 0x2602021,
+0x8e0a0024, 0x8ca20028, 0x11420053, 0x24020021,
+0xe0019e1, 0xa3820064, 0x1452ffbe, 0x2404ffff,
+0x8f850034, 0xa001cc9, 0x80a021, 0x2402001f,
+0xe0019e1, 0xa3820064, 0x2409ffff, 0x1049fea2,
+0x2404ffff, 0xa001deb, 0x8f830050, 0x2602021,
+0xe0019e1, 0xa3890064, 0x1450ff51, 0x8f850034,
+0x2403ffff, 0xa001cc9, 0x60a021, 0x8cce0024,
+0x8e0b0024, 0x116eff2a, 0x2602021, 0xa001ebd,
+0x2402000f, 0xe0018cb, 0x2602021, 0x8f850034,
+0xa001e7c, 0x1821, 0x8e090000, 0x3c050080,
+0x1259024, 0x1640ff45, 0x2402001a, 0x2602021,
+0xe0019e1, 0xa3820064, 0x240cffff, 0x144cfecb,
+0x2404ffff, 0x8f850034, 0xa001cc9, 0x80a021,
+0x2403fffd, 0x60a021, 0xa001cc9, 0xaf87005c,
+0x2418001d, 0xe0019e1, 0xa3980064, 0x2403ffff,
+0x1443fea6, 0x2404ffff, 0x8f850034, 0xa001cc9,
+0x80a021, 0x2412002c, 0xe0019e1, 0xa3920064,
+0x2403ffff, 0x1043ff50, 0x8f850034, 0xa001e63,
+0x92040003, 0x2602021, 0xa001ed3, 0x24020024,
+0x240b8000, 0x6b7024, 0x31caffff, 0xa13c2,
+0x305100ff, 0x118027, 0xa001f04, 0x1033c0,
+0xa001ed3, 0x24020027, 0x8e060028, 0x8cae002c,
+0x10ce0008, 0x2602021, 0xa001f17, 0x2402001f,
+0xa001f17, 0x2402000e, 0x2602021, 0xa001f17,
+0x24020025, 0x8e04002c, 0x1080000d, 0x8f83002c,
+0x8c780074, 0x304582b, 0x5560000c, 0x2602021,
+0x8ca80014, 0x86a021, 0x114302b, 0x10c0ff5a,
+0x8f8f0040, 0x2602021, 0xa001f17, 0x24020022,
+0x2602021, 0xa001f17, 0x24020023, 0xa001f17,
+0x24020026, 0x27bdffd8, 0xafb3001c, 0xafb10014,
+0xafbf0020, 0xafb20018, 0xafb00010, 0x3c028000,
+0x8c520140, 0x8c4b0148, 0x3c048000, 0xb8c02,
+0x322300ff, 0x317300ff, 0x8c8501b8, 0x4a0fffe,
+0x34900180, 0xae120000, 0x8c870144, 0x2464fff0,
+0x24060002, 0x2c830013, 0xae070004, 0xa6110008,
+0xa206000b, 0xae130024, 0x1060004f, 0x8fbf0020,
+0x44880, 0x3c0a0801, 0x254a936c, 0x12a4021,
+0x8d040000, 0x800008, 0x0, 0x3c030800,
+0x8c6331a8, 0x31693fff, 0x99980, 0x728021,
+0x2137021, 0x2405ff80, 0x264d0100, 0x264c0080,
+0x3c028000, 0x31b1007f, 0x3198007f, 0x31ca007f,
+0x3c1f800a, 0x3c198004, 0x3c0f800c, 0x1c52024,
+0x1a53024, 0x1853824, 0x14f1821, 0xac460024,
+0x23f4021, 0x3194821, 0xac470090, 0xac440028,
+0xaf830040, 0xaf880034, 0xaf89002c, 0xe001897,
+0x1608021, 0x3c038000, 0x8c6b01b8, 0x560fffe,
+0x8f870040, 0x8f860034, 0x34650180, 0x90e8000d,
+0xacb20000, 0xa4b00006, 0x82600, 0x41603,
+0x29027, 0x1227c2, 0x10800081, 0x24c20088,
+0x241f6082, 0xa4bf0008, 0xa0a00005, 0x24020002,
+0xa0a2000b, 0x8f8b002c, 0x42400, 0x3c082700,
+0x889025, 0xacb20010, 0xaca00014, 0xaca00024,
+0xaca00028, 0xaca0002c, 0x8d690038, 0x2413ff80,
+0xaca90018, 0x90e3000d, 0x2638024, 0x320500ff,
+0x10a00005, 0x8fbf0020, 0x90ed000d, 0x31ac007f,
+0xa0ec000d, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x3c0a1000, 0x3c0e8000,
+0x27bd0028, 0x3e00008, 0xadca01b8, 0x265f0100,
+0x2405ff80, 0x33f8007f, 0x3c068000, 0x3e57824,
+0x3c19800a, 0x3192021, 0xaccf0024, 0x908e00d4,
+0xae6824, 0x31ac00ff, 0x11800024, 0xaf840034,
+0x248e0088, 0x95cd0012, 0x3c0c0800, 0x8d8c31a8,
+0x31ab3fff, 0x1924821, 0xb5180, 0x12a4021,
+0x1052024, 0xacc40028, 0x3107007f, 0x3c06800c,
+0xe62021, 0x9083000d, 0xa31024, 0x304500ff,
+0x10a0ffd8, 0xaf840040, 0x9098000d, 0x330f0010,
+0x15e0ffd5, 0x8fbf0020, 0xe001897, 0x0,
+0x3c038000, 0x8c7901b8, 0x720fffe, 0x0,
+0xae120000, 0x8c7f0144, 0xae1f0004, 0xa6110008,
+0x24110002, 0xa211000b, 0xae130024, 0x3c130801,
+0x92739528, 0x32700001, 0x5200ffc3, 0x8fbf0020,
+0xe0020d4, 0x2402021, 0xa001ff1, 0x8fbf0020,
+0x3c126000, 0x8e452c08, 0x3c03f003, 0x3462ffff,
+0xa2f824, 0xae5f2c08, 0x8e582c08, 0x3c1901c0,
+0x3199825, 0xae532c08, 0xa001ff1, 0x8fbf0020,
+0x264d0100, 0x31af007f, 0x3c10800a, 0x240eff80,
+0x1f02821, 0x1ae6024, 0x3c0b8000, 0xad6c0024,
+0x1660ffa8, 0xaf850034, 0x24110003, 0xa0b100fc,
+0xa001ff1, 0x8fbf0020, 0x26480100, 0x310a007f,
+0x3c0b800a, 0x2409ff80, 0x14b3021, 0x1092024,
+0x3c078000, 0xace40024, 0xa001ff0, 0xaf860034,
+0x944e0012, 0x320c3fff, 0x31cd3fff, 0x15acff7d,
+0x241f6082, 0x90d900d4, 0x2418ff80, 0x3197824,
+0x31ea00ff, 0x1140ff77, 0x0, 0x24070004,
+0xa0c700fc, 0x8f870040, 0x24116084, 0x2406000d,
+0xa4b10008, 0xa0a60005, 0xa001fdb, 0x24020002,
+0x3c040001, 0x24849514, 0x24030014, 0x240200fe,
+0x3c010800, 0xac2431ec, 0x3c010800, 0xac2331e8,
+0x3c010801, 0xa4229530, 0x3c040801, 0x24849530,
+0x1821, 0x643021, 0xa0c30004, 0x24630001,
+0x2c6500ff, 0x54a0fffc, 0x643021, 0x3c070800,
+0x24e70100, 0x3e00008, 0xaf870074, 0xa05821,
+0x804821, 0x1021, 0x14a00012, 0x5021,
+0xa0020d0, 0x0, 0x3c010801, 0xa4209530,
+0x3c050801, 0x94a59530, 0x8f820074, 0x3c0c0801,
+0x258c9530, 0xe21821, 0xac2021, 0x14b302b,
+0xa0890004, 0x1021, 0xa4600008, 0x10c00039,
+0x1004821, 0x8f860074, 0x93840, 0xe94021,
+0x83880, 0xe62821, 0x90a8000b, 0x90b9000a,
+0x82040, 0x881021, 0x21880, 0x66c021,
+0xa319000a, 0x8f850074, 0xe57821, 0x91ee000a,
+0x91e6000b, 0xe6840, 0x1ae6021, 0xc2080,
+0x851021, 0xa046000b, 0x3c030801, 0x9063952a,
+0x10600022, 0x2462ffff, 0x8f830034, 0x3c010801,
+0xa022952a, 0x906c00ff, 0x11800004, 0x0,
+0x906e00ff, 0x25cdffff, 0xa06d00ff, 0x3c190801,
+0x97399530, 0x27230001, 0x3078ffff, 0x2f0f00ff,
+0x11e0ffc9, 0x254a0001, 0x3c010801, 0xa4239530,
+0x3c050801, 0x94a59530, 0x8f820074, 0x3c0c0801,
+0x258c9530, 0xe21821, 0xac2021, 0x14b302b,
+0xa0890004, 0x1021, 0xa4600008, 0x14c0ffc9,
+0x1004821, 0x3e00008, 0x0, 0x3e00008,
+0x24020002, 0x27bdffe0, 0x24850100, 0x2407ff80,
+0xafb00010, 0xafbf0018, 0xafb10014, 0xa71824,
+0x3c108000, 0x30a4007f, 0x3c06800a, 0x862821,
+0x8e110024, 0xae030024, 0x90a200ff, 0x14400008,
+0xaf850034, 0xa0a00009, 0x8fbf0018, 0xae110024,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
+0x90a900fd, 0x90a800ff, 0x312400ff, 0xe002082,
+0x310500ff, 0x8f850034, 0x8fbf0018, 0xa0a00009,
+0xae110024, 0x8fb10014, 0x8fb00010, 0x3e00008,
+0x27bd0020, 0x27bdffd0, 0xafb20020, 0xafb1001c,
+0xafb00018, 0xafbf002c, 0xafb40028, 0xafb30024,
+0x3c098000, 0x95330116, 0x35320c00, 0x952f011a,
+0x3271ffff, 0x2328021, 0x8e080004, 0x31eeffff,
+0x248b0100, 0x10e6821, 0x240cff80, 0x25a5ffff,
+0x16c5024, 0x3166007f, 0x3c07800a, 0xad2a0024,
+0xc73021, 0xaf850070, 0xaf88006c, 0x3c010801,
+0xa0209529, 0x90c30009, 0x200d021, 0x809821,
+0x306300ff, 0x28620005, 0x10400048, 0xaf860034,
+0x28640002, 0x1480008e, 0x24140001, 0x240d0005,
+0x3c010801, 0xa02d950d, 0x90cc00fd, 0x3c010801,
+0xa020950e, 0x3c010801, 0xa020950f, 0x90cb000a,
+0x240aff80, 0x318500ff, 0x14b4824, 0x312700ff,
+0x10e0000c, 0x5821, 0x3c128008, 0x36510080,
+0x8e2f0030, 0x8cd0005c, 0x1f07023, 0x5c0018e,
+0x8f87006c, 0x90d4000a, 0x3284007f, 0xa0c4000a,
+0x8f860034, 0x3c118008, 0x36300080, 0x8e0f0030,
+0x8f87006c, 0xef7023, 0x19c000ee, 0x0,
+0x90d40009, 0x24120002, 0x328400ff, 0x10920247,
+0x0, 0x8cc20058, 0xe2f823, 0x27f9ffff,
+0x1b200130, 0x0, 0x90c50009, 0x24080004,
+0x30a300ff, 0x10680057, 0x240a0001, 0x3c010801,
+0xa02a950d, 0x90c900ff, 0x25270001, 0x3c010801,
+0xa027950c, 0x3c030801, 0x9063950d, 0x24060005,
+0x1066006a, 0x2c780005, 0x130000c4, 0x9021,
+0x3f880, 0x3c040801, 0x248493b8, 0x3e4c821,
+0x8f250000, 0xa00008, 0x0, 0x241800ff,
+0x1078005c, 0x0, 0x90cc000a, 0x90ca0009,
+0x3c080801, 0x91089529, 0x31870080, 0xea4825,
+0x3c010801, 0xa0299514, 0x90c500fd, 0x3c140801,
+0x9294952a, 0x31110001, 0x3c010801, 0xa0259515,
+0x90df00fe, 0x3c010801, 0xa03f9516, 0x90d200ff,
+0x3c010801, 0xa0329517, 0x8cd90054, 0x3c010801,
+0xac399518, 0x8cd00058, 0x3c010801, 0xac30951c,
+0x8cc3005c, 0x3c010801, 0xac349524, 0x3c010801,
+0xac239520, 0x16200008, 0x8fbf002c, 0x8fb40028,
+0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
+0x3e00008, 0x27bd0030, 0x3c118000, 0x9624010e,
+0xe000fd4, 0x3094ffff, 0x3c0b0801, 0x8d6b952c,
+0x2603821, 0x2802821, 0xae2b0180, 0x3c130801,
+0x8e73950c, 0x1602021, 0x24060083, 0xe001046,
+0xafb30010, 0x8fbf002c, 0x8fb40028, 0x8fb30024,
+0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
+0x27bd0030, 0x3c180800, 0x8f1831fc, 0x270f0001,
+0x3c010800, 0xac2f31fc, 0xa002165, 0x0,
+0x1474ffb9, 0x0, 0xa0c000ff, 0x3c050800,
+0x8ca531e4, 0x3c030800, 0x8c6331e0, 0x3c020800,
+0x8c423204, 0x8f990034, 0x34a80001, 0x241f0002,
+0x3c010801, 0xac23952c, 0x3c010801, 0xa0289528,
+0x3c010801, 0xa022952b, 0xa33f0009, 0xa00211e,
+0x8f860034, 0xe0020d4, 0x0, 0xa002165,
+0x8f860034, 0x3c1f0801, 0x93ff950c, 0x24190001,
+0x13f90229, 0x8f87006c, 0x3c100801, 0x92109510,
+0x3c060801, 0x90c6950e, 0x10c00005, 0x200a021,
+0x3c040801, 0x90849511, 0x109001e4, 0x8f870074,
+0x108840, 0x8f9f0074, 0x2304821, 0x9c880,
+0x33f7021, 0x95d80008, 0x270f0001, 0xa5cf0008,
+0x3c040801, 0x90849511, 0x3c050801, 0x90a5950e,
+0xe002082, 0x0, 0x8f870074, 0x2302021,
+0x43080, 0xc72021, 0x8c850004, 0x8f820070,
+0xa24023, 0x5020006, 0xac820004, 0x8c8a0000,
+0x8f83006c, 0x1431023, 0x5c400001, 0xac830000,
+0x8f860034, 0x90cb00ff, 0x2d6c0002, 0x5580002d,
+0x24140001, 0x230f821, 0x1f4080, 0x1072821,
+0x90b9000b, 0x8cae0004, 0x19c040, 0x3197821,
+0xf1880, 0x671021, 0x8c4d0000, 0x1ae8823,
+0x2630ffff, 0x5e00001f, 0x24140001, 0x8c440004,
+0x8caa0000, 0x8a4823, 0x19200019, 0x240e0004,
+0x3c010801, 0xa02e950d, 0x90ad000b, 0x8cab0004,
+0xd8840, 0x22d8021, 0x101080, 0x471021,
+0x8c440004, 0x1646023, 0x5820200, 0x94430008,
+0x90df00fe, 0x90b9000b, 0x33e500ff, 0x54b90004,
+0x107a021, 0xa0d400fe, 0x8f870074, 0x107a021,
+0x9284000b, 0xe002082, 0x24050001, 0x8f860034,
+0x24140001, 0x12540096, 0x2e500001, 0x16000042,
+0x3c08ffff, 0x24190002, 0x1659ff3f, 0x0,
+0xa0c000ff, 0x8f860034, 0xa0d20009, 0xa002165,
+0x8f860034, 0x90c70009, 0x24040002, 0x30e300ff,
+0x1064016f, 0x24090004, 0x10690152, 0x8f880070,
+0x8cce0054, 0x10e6823, 0x25b10001, 0x6200175,
+0x24180004, 0x3c010801, 0xa038950d, 0x3c010801,
+0xa020950c, 0x90d400fd, 0x90d200ff, 0x2e4f0002,
+0x15e0ff14, 0x328400ff, 0x43840, 0x8f890074,
+0x90df00ff, 0xe41021, 0x22080, 0x89c821,
+0x2fe50002, 0x9324000b, 0x14a0ff0a, 0x24070002,
+0x41840, 0x648021, 0x105880, 0x1692821,
+0x8cac0004, 0x10c5023, 0x540ff02, 0x0,
+0x3c030801, 0x9063950e, 0x14600005, 0x246f0001,
+0x3c010801, 0xa0249511, 0x3c010801, 0xa027950f,
+0x3c010801, 0xa02f950e, 0x90ce00ff, 0x24e70001,
+0x31cd00ff, 0x1a7882b, 0x1220ffe9, 0x90a4000b,
+0xa002154, 0x0, 0x3c050801, 0x8ca5950c,
+0x3c120004, 0xa8f824, 0x13f20006, 0x24020005,
+0x3c090801, 0x9129950d, 0x15200002, 0x24020003,
+0x24020005, 0x3c010801, 0xa0229529, 0x90c700ff,
+0x14e00120, 0x24020002, 0xa0c20009, 0xa002165,
+0x8f860034, 0x90cc00ff, 0x1180feda, 0x240a0001,
+0x8f8c0070, 0x8f890074, 0x240f0003, 0x1806821,
+0x1160001e, 0x240e0002, 0x54040, 0x105a021,
+0x142080, 0x899021, 0x8e510004, 0x1918023,
+0x600fecc, 0x0, 0x3c020801, 0x9042950e,
+0x14400005, 0x24580001, 0x3c010801, 0xa02a950f,
+0x3c010801, 0xa0259511, 0x3c010801, 0xa038950e,
+0x90df00ff, 0x1051021, 0x2c880, 0x33e500ff,
+0x254a0001, 0x3292021, 0xaa402b, 0x1500feb9,
+0x9085000b, 0x1560ffe5, 0x54040, 0x54040,
+0x1051821, 0x31080, 0x3c010801, 0xa02a950c,
+0x3c010801, 0xa0259510, 0x491821, 0x8c640004,
+0xe4f823, 0x27f9ffff, 0x1f20ffe9, 0x0,
+0x8c630000, 0xe35823, 0x560013a, 0x1a38823,
+0x10e30117, 0x184c023, 0x1b00fea2, 0x0,
+0x3c010801, 0xa02e950d, 0xa002293, 0x240b0001,
+0x240e0004, 0xa0ce0009, 0x3c0d0800, 0x8dad31f8,
+0x8f860034, 0x25a20001, 0x3c010800, 0xac2231f8,
+0xa002165, 0x0, 0x8cd9005c, 0xf9c023,
+0x1f00fe7b, 0x0, 0x8cdf005c, 0x10ffff65,
+0x8f840070, 0x8cc3005c, 0x834023, 0x25020001,
+0x1c40ff60, 0x0, 0x8cc9005c, 0x24870001,
+0xe9282b, 0x10a0fe94, 0x3c0d8000, 0x8dab0104,
+0x3c0c0001, 0x16c5024, 0x1140fe8f, 0x24020010,
+0x3c010801, 0xa0229529, 0xa002165, 0x0,
+0x8f910070, 0x8f860034, 0x26220001, 0xacc2005c,
+0xa002220, 0x24140001, 0x8f870034, 0x2404ff80,
+0x8821, 0x90e9000a, 0x24140001, 0x1243025,
+0xa0e6000a, 0x3c050801, 0x90a5950e, 0x3c040801,
+0x90849511, 0xe002082, 0x0, 0x8f860034,
+0x8f850074, 0x90c800fd, 0x310700ff, 0x74040,
+0x107f821, 0x1fc080, 0x305c821, 0x9323000b,
+0xa0c300fd, 0x8f850074, 0x8f860034, 0x3056021,
+0x918f000b, 0xf7040, 0x1cf6821, 0xd8080,
+0x2051021, 0x8c4b0000, 0xaccb0054, 0x8d840004,
+0x8f830070, 0x645023, 0x19400002, 0x24820001,
+0x24620001, 0x1074821, 0xacc2005c, 0x93080,
+0xc54021, 0xe02021, 0x24050001, 0xe002082,
+0x9110000b, 0x8f860034, 0x90c500ff, 0x10a0ff0c,
+0x107040, 0x8f850074, 0x1d06821, 0xd1080,
+0x455821, 0x8d640000, 0x8f8c0070, 0x1845023,
+0x25470001, 0x4e0ff02, 0x26310001, 0x3c030801,
+0x9063950e, 0x2e2f0002, 0x24780001, 0x3c010801,
+0xa038950e, 0x3c010801, 0xa034950f, 0x11e0fef8,
+0x2003821, 0xa0022f3, 0x74040, 0x8f840034,
+0x8f830070, 0x8c850058, 0xa34023, 0x502fe9a,
+0xac830058, 0xa0021c9, 0x0, 0x3c070801,
+0x90e7952a, 0x240200ff, 0x10e200be, 0x8f860034,
+0x3c110801, 0x96319532, 0x3c030801, 0x24639530,
+0x26250001, 0x3230ffff, 0x30abffff, 0x2036021,
+0x2d6a00ff, 0x1540008d, 0x91870004, 0x3c010801,
+0xa4209532, 0x8f880034, 0x74840, 0x1272821,
+0x911800ff, 0x53080, 0x24050001, 0x27140001,
+0xa11400ff, 0x3c120801, 0x9252952a, 0x8f880074,
+0x8f8e006c, 0x264f0001, 0xc82021, 0x3c010801,
+0xa02f952a, 0xac8e0000, 0x8f8d0070, 0xa4850008,
+0xac8d0004, 0x3c030801, 0x9063950c, 0x14600077,
+0x9021, 0x3c010801, 0xa025950c, 0xa087000b,
+0x8f8c0074, 0xcc5021, 0xa147000a, 0x8f820034,
+0xa04700fd, 0x8f840034, 0xa08700fe, 0x8f860034,
+0x8f9f006c, 0xacdf0054, 0x8f990070, 0xacd90058,
+0x8f8d0074, 0x127c021, 0x185880, 0x16da021,
+0x928f000a, 0xf7040, 0x1cf1821, 0x38880,
+0x22d8021, 0xa207000b, 0x8f860074, 0x1666021,
+0x918a000b, 0xa1040, 0x4a2021, 0x42880,
+0xa64021, 0xa107000a, 0x3c078008, 0x34e90080,
+0x8d220030, 0x8f860034, 0xacc2005c, 0xa002220,
+0x24140001, 0x90ca00ff, 0x1540fead, 0x8f880070,
+0xa0c40009, 0xa002165, 0x8f860034, 0xa0c000fd,
+0x8f980034, 0x24060001, 0xa30000fe, 0x3c010801,
+0xa026950d, 0x3c010801, 0xa020950c, 0xa002154,
+0x0, 0x90cb00ff, 0x3c040801, 0x9084952b,
+0x316c00ff, 0x184502b, 0x1540000f, 0x24020003,
+0x24020004, 0xa0c20009, 0xa002165, 0x8f860034,
+0x90c3000a, 0x2410ff80, 0x2035824, 0x316c00ff,
+0x1180fdc1, 0x0, 0x3c010801, 0xa020950d,
+0xa002154, 0x0, 0xa0c20009, 0xa002165,
+0x8f860034, 0x90d4000a, 0x2412ff80, 0x2544824,
+0x312800ff, 0x1500fff4, 0x24020008, 0x3c010801,
+0xa0229529, 0xa002165, 0x0, 0x108840,
+0x8f8b006c, 0x2301821, 0x36880, 0x1a72021,
+0xac8b0000, 0x8f8a0070, 0x240c0001, 0xa48c0008,
+0xac8a0004, 0x3c050801, 0x90a5950e, 0x24020001,
+0x10a2fe1e, 0x24a5ffff, 0xa0021df, 0x9084000b,
+0x184a023, 0x1a80fd8b, 0x0, 0x3c010801,
+0xa02e950d, 0xa002293, 0x240b0001, 0x3c010801,
+0xa4259532, 0xa002345, 0x8f880034, 0x240b0001,
+0x106b0022, 0x8f980034, 0x8f850034, 0x90bf00ff,
+0x33f900ff, 0x1079002b, 0x0, 0x3c1f0801,
+0x93ff9510, 0x1fc840, 0x33fc021, 0x18a080,
+0x2887821, 0x91ee000a, 0xa08e000a, 0x8f8d0074,
+0x3c030801, 0x90639510, 0xcd8821, 0xa00236b,
+0xa223000b, 0x26300001, 0x6000031, 0x1a49023,
+0x640002b, 0x24020003, 0x3c010801, 0xa02f950d,
+0xa002293, 0x240b0001, 0x8f890034, 0xa0021c9,
+0xad270054, 0xa00221f, 0x24120001, 0x931400fd,
+0xa094000b, 0x8f880034, 0x8f8f0074, 0x910e00fe,
+0xcf6821, 0xa1ae000a, 0x8f910034, 0xa22700fd,
+0x8f83006c, 0x8f900034, 0xae030054, 0xa00236c,
+0x8f8d0074, 0x90b000fe, 0xa090000a, 0x8f8b0034,
+0x8f8c0074, 0x916a00fd, 0xcc1021, 0xa04a000b,
+0x8f840034, 0xa08700fe, 0x8f860070, 0x8f850034,
+0xaca60058, 0xa00236c, 0x8f8d0074, 0x94b80008,
+0xaca40004, 0x3037821, 0xa002213, 0xa4af0008,
+0x3c010801, 0xa022950d, 0xa002154, 0x0,
+0x90cf0009, 0x240d0004, 0x31ee00ff, 0x11cdfd85,
+0x24020001, 0x3c010801, 0xa022950d, 0xa002154,
+0x0, 0x0 };
+u32 bce_RXP_b09FwData[(0x0/4) + 1] = { 0x0 };
+u32 bce_RXP_b09FwRodata[(0x33c/4) + 1] = {
+0x8003344,
+0x8003344, 0x8003420, 0x80033f4, 0x80033d8,
+0x8003328, 0x8003328, 0x8003328, 0x800334c,
+0x80080100, 0x80080080, 0x80080000, 0x5f865437,
+0xe4ac62cc, 0x50103a45, 0x36621985, 0xbf14c0e8,
+0x1bc27a1e, 0x84f4b556, 0x94ea6fe, 0x7dda01e7,
+0xc04d7481, 0x80058d0, 0x8005914, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058d0,
+0x80058b8, 0x80058b8, 0x800591c, 0x80058b8,
+0x8005830, 0x80058b8, 0x80058b8, 0x800591c,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058f0, 0x80058b8,
+0x80058f0, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058f4, 0x80058f0, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058f4, 0x80058f4,
+0x80058b8, 0x80058f4, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x80058b8, 0x80058b8, 0x80058b8,
+0x80058b8, 0x8005938, 0x8007688, 0x80078ec,
+0x8007694, 0x8007488, 0x8007694, 0x8007720,
+0x8007694, 0x8007488, 0x8007488, 0x8007488,
+0x8007488, 0x8007488, 0x8007488, 0x8007488,
+0x8007488, 0x8007488, 0x8007488, 0x80076b4,
+0x80076a4, 0x8007488, 0x8007488, 0x8007488,
+0x8007488, 0x8007488, 0x8007488, 0x8007488,
+0x8007488, 0x8007488, 0x8007488, 0x8007488,
+0x8007488, 0x80076a4, 0x8008134, 0x8007fc0,
+0x80080fc, 0x8007fc0, 0x80080cc, 0x8007ea8,
+0x8007fc0, 0x8007fc0, 0x8007fc0, 0x8007fc0,
+0x8007fc0, 0x8007fc0, 0x8007fc0, 0x8007fc0,
+0x8007fc0, 0x8007fc0, 0x8007fc0, 0x8007fc0,
+0x8007fe8, 0x8008b6c, 0x8008cc8, 0x8008ca8,
+0x8008710, 0x8008b84, 0x0 };
+u32 bce_RXP_b09FwBss[(0x1bc/4) + 1] = { 0x0 };
+u32 bce_RXP_b09FwSbss[(0x78/4) + 1] = { 0x0 };
+u32 bce_RXP_b09FwSdata[(0x0/4) + 1] = { 0x0 };
-int bce_CP_b09FwReleaseMajor = 0x1;
-int bce_CP_b09FwReleaseMinor = 0x0;
-int bce_CP_b09FwReleaseFix = 0x0;
-u32 bce_CP_b09FwStartAddr = 0x08000080;
-u32 bce_CP_b09FwTextAddr = 0x08000000;
-int bce_CP_b09FwTextLen = 0x5418;
-u32 bce_CP_b09FwDataAddr = 0x080055a0;
-int bce_CP_b09FwDataLen = 0x84;
-u32 bce_CP_b09FwRodataAddr = 0x08005418;
-int bce_CP_b09FwRodataLen = 0x16c;
-u32 bce_CP_b09FwBssAddr = 0x080056b8;
-int bce_CP_b09FwBssLen = 0x19c;
-u32 bce_CP_b09FwSbssAddr = 0x08005624;
-int bce_CP_b09FwSbssLen = 0x91;
-u32 bce_CP_b09FwSDataAddr = 0x00000000;
-int bce_CP_b09FwSDataLen = 0x0;
-u32 bce_CP_b09FwText[(0x5418/4) + 1] = {
-0xa000020,
-0x0, 0x0, 0xd, 0x6370342e,
-0x362e3136, 0x0, 0x4061004, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x38003c00, 0x0, 0x0, 0x0,
-0x0, 0x20, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x21003800, 0x1, 0x2b, 0x0,
-0x10000003, 0x0, 0xd, 0xd,
-0x3c020800, 0x24425624, 0x3c030800, 0x24635854,
-0xac400000, 0x43202b, 0x1480fffd, 0x24420004,
-0x3c1d0800, 0x37bd9ffc, 0x3a0f021, 0x3c100800,
-0x26100080, 0x3c1c0800, 0x279c5624, 0xe000286,
-0x0, 0xd, 0xa01821, 0x801021,
-0x802821, 0x3c046000, 0x3c076000, 0x24060008,
-0x10600006, 0x34842078, 0x8c420000, 0xace22008,
-0x8c630000, 0x3e00008, 0xace3200c, 0xa000e38,
-0x0, 0x24030040, 0x3c026000, 0x3e00008,
-0xac432000, 0x3c076000, 0x8f860000, 0x8ce52074,
-0x861021, 0xa2182b, 0x14600007, 0x2821,
-0x8f8afdfc, 0x24050001, 0xa1440013, 0x8f890000,
-0x1244021, 0xaf880000, 0x3e00008, 0xa01021,
-0x8f84fdfc, 0x8f850000, 0x90860013, 0x30c300ff,
-0xa31023, 0xaf820000, 0x3e00008, 0xa0800013,
-0x8f84fdfc, 0x27bdffe8, 0xafb00010, 0xafbf0014,
-0x90890011, 0x90870011, 0x24020028, 0x312800ff,
-0x39060028, 0x30e300ff, 0x2485002c, 0x2cd00001,
-0x10620016, 0x2484001c, 0xe000037, 0x0,
-0x8f8ffdfc, 0x3c056000, 0x24020204, 0x95ee003e,
-0x95ed003c, 0xe5c00, 0x31acffff, 0x16c5025,
-0xacaa2010, 0x52000001, 0x24020004, 0xaca22000,
-0x0, 0x0, 0x0, 0x8fbf0014,
-0x8fb00010, 0x3e00008, 0x27bd0018, 0xa00006f,
-0x2821, 0x8f85fdfc, 0x27bdffd8, 0xafbf0020,
-0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010,
-0x809821, 0x90a40011, 0x24b0001c, 0x24b1002c,
-0x308300ff, 0x38620028, 0xe000059, 0x2c520001,
-0xe000061, 0x0, 0x2002021, 0x12400002,
-0x2202821, 0x2821, 0xe000037, 0x0,
-0x8f8dfdfc, 0x3c088000, 0x3c056000, 0x95ac003e,
-0x95ab003c, 0x2683025, 0xc4c00, 0x316affff,
-0x12a3825, 0xaca72010, 0x24020202, 0xaca62014,
-0x52400001, 0x24020002, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x27bd0028,
-0x3e00008, 0xaca22000, 0x27bdffe0, 0xafb20018,
-0xafb10014, 0xafb00010, 0xafbf001c, 0x3c116000,
-0x8e232074, 0x8f820000, 0x30d0ffff, 0x30f2ffff,
-0x1062000c, 0x2406008f, 0xe000037, 0x0,
-0x3c06801f, 0x104400, 0x34c5ff00, 0x1123825,
-0x24040002, 0xae272010, 0x3021, 0xae252014,
-0xae242000, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0xc01021, 0x3e00008, 0x27bd0020,
-0x27bdffe0, 0xafb00010, 0x30d0ffff, 0xafbf0018,
-0xafb10014, 0xe000037, 0x30f1ffff, 0x102400,
-0x918025, 0x3c036000, 0xac702010, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x24020004, 0xac622000,
-0x27bd0020, 0x3e00008, 0x1021, 0x27bdffe8,
-0x3c0c6018, 0xafbf0010, 0x8d985000, 0x2419ff7f,
-0x3c088000, 0x3197824, 0x35ee380c, 0x340d8071,
-0x240a0031, 0x24090c00, 0xad8e5000, 0x3c0b800a,
-0xad8d53bc, 0xad0a0008, 0xad090024, 0xe0004a9,
-0xaf8b002c, 0xe000467, 0x0, 0xe000046,
-0x0, 0x3c076000, 0x8ce50808, 0x2406fff0,
-0x3c035709, 0xa62024, 0x3462f000, 0x10820043,
-0x241f0001, 0xe000bca, 0xaf800038, 0x3c066016,
-0x3c086014, 0x8cc70000, 0x8d0500a0, 0x3c03ffff,
-0xe32024, 0x3c025353, 0x52fc2, 0x10820044,
-0x34c87c00, 0x950201f2, 0xa7800050, 0x10400003,
-0xa7800060, 0x384c1e1e, 0xa78c0050, 0x950201f8,
-0x10400004, 0x8f8e0038, 0x384d1e1e, 0xa78d0060,
-0x8f8e0038, 0x11c00004, 0x97870060, 0x240f0020,
-0xa78f0050, 0x97870060, 0x30e4ffff, 0x2c980081,
-0x17000003, 0x97860050, 0x24070080, 0x24040080,
-0x2cd90401, 0x53200001, 0x24060400, 0x3c036000,
-0x8c650438, 0x241f103c, 0x30a2ffff, 0x505f002a,
-0xa3800062, 0x5480000c, 0xa3800062, 0x24020050,
-0xa3820062, 0x93880062, 0x1100000a, 0x8fbf0010,
-0x27bd0018, 0xa7800060, 0xa7800050, 0xa7800058,
-0x3e00008, 0xa7800076, 0x93880062, 0x1500fff8,
-0x8fbf0010, 0x27bd0018, 0xa7870060, 0xa7860050,
-0xa7800058, 0x3e00008, 0xa7800076, 0xaf9f0038,
-0xe000bca, 0x0, 0x3c066016, 0x3c086014,
-0x8cc70000, 0x8d0500a0, 0x3c03ffff, 0xe32024,
-0x3c025353, 0x52fc2, 0x1482ffbe, 0x34c87c00,
-0x55880, 0x1665021, 0x8d490004, 0x3c066000,
-0xa00010e, 0x1264021, 0x8d0a003c, 0x31490001,
-0x11200009, 0x0, 0x1080ffd5, 0x24020050,
-0x8d0b00c8, 0x31640001, 0x1480ffd3, 0x93880062,
-0xa000131, 0x24020051, 0x1480ffcf, 0x93880062,
-0xa000131, 0x24020050, 0x3083ffff, 0x8f88002c,
-0x8f870028, 0x32140, 0x3c058000, 0x3c020050,
+int bce_CP_b09FwReleaseMajor = 0x6;
+int bce_CP_b09FwReleaseMinor = 0x0;
+int bce_CP_b09FwReleaseFix = 0x11;
+u32 bce_CP_b09FwStartAddr = 0x080000a0;
+u32 bce_CP_b09FwTextAddr = 0x08000000;
+int bce_CP_b09FwTextLen = 0x5744;
+u32 bce_CP_b09FwDataAddr = 0x08005920;
+int bce_CP_b09FwDataLen = 0x84;
+u32 bce_CP_b09FwRodataAddr = 0x08005744;
+int bce_CP_b09FwRodataLen = 0x1c0;
+u32 bce_CP_b09FwBssAddr = 0x08005a58;
+int bce_CP_b09FwBssLen = 0x19c;
+u32 bce_CP_b09FwSbssAddr = 0x080059b0;
+int bce_CP_b09FwSbssLen = 0xa8;
+u32 bce_CP_b09FwSDataAddr = 0x00000000;
+int bce_CP_b09FwSDataLen = 0x0;
+u32 bce_CP_b09FwText[(0x5744/4) + 1] = {
+0xa000028, 0x0, 0x0,
+0xd, 0x6370362e, 0x302e3137, 0x0,
+0x6001104, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x38003c00, 0x0,
+0x0, 0x0, 0x0, 0x20,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x21003800, 0x1,
+0x2b, 0x0, 0x4, 0x30d40,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x10000003, 0x0,
+0xd, 0xd, 0x3c020800, 0x244259ac,
+0x3c030800, 0x24635bf4, 0xac400000, 0x43202b,
+0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd9ffc,
+0x3a0f021, 0x3c100800, 0x261000a0, 0x3c1c0800,
+0x279c59ac, 0xe0002f6, 0x0, 0xd,
+0x27bdffb4, 0xafa10000, 0xafa20004, 0xafa30008,
+0xafa4000c, 0xafa50010, 0xafa60014, 0xafa70018,
+0xafa8001c, 0xafa90020, 0xafaa0024, 0xafab0028,
+0xafac002c, 0xafad0030, 0xafae0034, 0xafaf0038,
+0xafb8003c, 0xafb90040, 0xafbc0044, 0xafbf0048,
+0xe000820, 0x0, 0x8fbf0048, 0x8fbc0044,
+0x8fb90040, 0x8fb8003c, 0x8faf0038, 0x8fae0034,
+0x8fad0030, 0x8fac002c, 0x8fab0028, 0x8faa0024,
+0x8fa90020, 0x8fa8001c, 0x8fa70018, 0x8fa60014,
+0x8fa50010, 0x8fa4000c, 0x8fa30008, 0x8fa20004,
+0x8fa10000, 0x27bd004c, 0x3c1b6018, 0x8f7a5030,
+0x377b5028, 0x3400008, 0xaf7a0000, 0xa01821,
+0x801021, 0x802821, 0x3c046000, 0x3c076000,
+0x24060008, 0x10600006, 0x34842078, 0x8c420000,
+0xace22008, 0x8c630000, 0x3e00008, 0xace3200c,
+0xa000f81, 0x0, 0x24030040, 0x3c026000,
+0x3e00008, 0xac432000, 0x3c076000, 0x8f860004,
+0x8ce52074, 0x861021, 0xa2182b, 0x14600007,
+0x2821, 0x8f8afda0, 0x24050001, 0xa1440013,
+0x8f890004, 0x1244021, 0xaf880004, 0x3e00008,
+0xa01021, 0x8f84fda0, 0x8f850004, 0x90860013,
+0x30c300ff, 0xa31023, 0xaf820004, 0x3e00008,
+0xa0800013, 0x8f84fda0, 0x27bdffe8, 0xafb00010,
+0xafbf0014, 0x90890011, 0x90870011, 0x24020028,
+0x312800ff, 0x39060028, 0x30e300ff, 0x2485002c,
+0x2cd00001, 0x10620016, 0x2484001c, 0xe00006e,
+0x0, 0x8f8ffda0, 0x3c056000, 0x24020204,
+0x95ee003e, 0x95ed003c, 0xe5c00, 0x31acffff,
+0x16c5025, 0xacaa2010, 0x52000001, 0x24020004,
+0xaca22000, 0x0, 0x0, 0x0,
+0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
+0xa0000a6, 0x2821, 0x8f85fda0, 0x27bdffd8,
+0xafbf0020, 0xafb3001c, 0xafb20018, 0xafb10014,
+0xafb00010, 0x809821, 0x90a40011, 0x24b0001c,
+0x24b1002c, 0x308300ff, 0x38620028, 0xe000090,
+0x2c520001, 0xe000098, 0x0, 0x2002021,
+0x12400002, 0x2202821, 0x2821, 0xe00006e,
+0x0, 0x8f8dfda0, 0x3c088000, 0x3c056000,
+0x95ac003e, 0x95ab003c, 0x2683025, 0xc4c00,
+0x316affff, 0x12a3825, 0xaca72010, 0x24020202,
+0xaca62014, 0x52400001, 0x24020002, 0x8fbf0020,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0x27bd0028, 0x3e00008, 0xaca22000, 0x27bdffe0,
+0xafb20018, 0xafb10014, 0xafb00010, 0xafbf001c,
+0x3c116000, 0x8e232074, 0x8f820004, 0x30d0ffff,
+0x30f2ffff, 0x1062000c, 0x2406008f, 0xe00006e,
+0x0, 0x3c06801f, 0x104400, 0x34c5ff00,
+0x1123825, 0x24040002, 0xae272010, 0x3021,
+0xae252014, 0xae242000, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0xc01021, 0x3e00008,
+0x27bd0020, 0x27bdffe0, 0xafb00010, 0x30d0ffff,
+0xafbf0018, 0xafb10014, 0xe00006e, 0x30f1ffff,
+0x102400, 0x918025, 0x3c036000, 0xac702010,
+0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x24020004,
+0xac622000, 0x27bd0020, 0x3e00008, 0x1021,
+0x27bdffe0, 0x3c046018, 0xafbf0018, 0xafb10014,
+0xafb00010, 0x8c885000, 0x2403ff7f, 0x34028071,
+0x1033824, 0x34e5380c, 0x241f0031, 0x3c198000,
+0xac855000, 0x3c11800a, 0xac8253bc, 0xaf3f0008,
+0xe00054c, 0xaf910040, 0xe00050a, 0x3c116000,
+0xe00007d, 0x0, 0x8e300808, 0x3c0f5709,
+0x2418fff0, 0x2186024, 0x35eee000, 0x35edf000,
+0x18e5026, 0x18d5826, 0x2d460001, 0x2d690001,
+0xaf86004c, 0xe000d09, 0xaf890050, 0x3c066016,
+0x8cc70000, 0x3c086014, 0x8d0500a0, 0x3c03ffff,
+0xe32024, 0x3c025353, 0x52fc2, 0x10820055,
+0x34d07c00, 0x960201f2, 0xa780006c, 0x10400003,
+0xa780007c, 0x384b1e1e, 0xa78b006c, 0x960201f8,
+0x10400004, 0x8f8d0050, 0x384c1e1e, 0xa78c007c,
+0x8f8d0050, 0x11a00005, 0x8f83004c, 0x240e0020,
+0xa78e007c, 0xa78e006c, 0x8f83004c, 0x10600005,
+0x9785007c, 0x240f0020, 0xa78f007c, 0xa78f006c,
+0x9785007c, 0x2cb80081, 0x53000001, 0x24050080,
+0x9784006c, 0x2c910401, 0x52200001, 0x24040400,
+0x1060000b, 0x3c026000, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x27bd0020, 0xa784006c, 0xa785007c,
+0xa380007e, 0xa7800074, 0x3e00008, 0xa7800092,
+0x8c470438, 0x2419103c, 0x30ffffff, 0x13f90003,
+0x30a8ffff, 0x11000046, 0x24030050, 0xa380007e,
+0x9386007e, 0x50c00024, 0xa785007c, 0xa780007c,
+0x9798007c, 0xa780006c, 0xa7800074, 0xa7800092,
+0x3c010800, 0xac380080, 0xe000787, 0x0,
+0x3c0f6000, 0x8ded0808, 0x240efff0, 0x3c0b600e,
+0x260c0388, 0x356a0010, 0x4821, 0x2821,
+0x1ae2024, 0x3c105709, 0xaf8c0010, 0xaf8a0048,
+0xaf890018, 0x10900023, 0xaf850014, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x27bd0020, 0x3e00008,
+0xaf800054, 0x55080, 0x1464821, 0x8d260004,
+0xa000148, 0xd18021, 0x9798007c, 0xa784006c,
+0xa7800074, 0xa7800092, 0x3c010800, 0xac380080,
+0xe000787, 0x0, 0x3c0f6000, 0x8ded0808,
+0x240efff0, 0x3c0b600e, 0x260c0388, 0x356a0010,
+0x4821, 0x2821, 0x1ae2024, 0x3c105709,
+0xaf8c0010, 0xaf8a0048, 0xaf890018, 0x1490ffdf,
+0xaf850014, 0x24110001, 0xaf910054, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
+0xa00017b, 0xa383007e, 0x3083ffff, 0x8f880040,
+0x8f87003c, 0x32140, 0x3c058000, 0x3c020050,
0x824825, 0x3c066000, 0x3c0a0100, 0x34ac0400,
0x8ccd08e0, 0x1aa5824, 0x11600005, 0x0,
0x8ccf08e0, 0x24e70001, 0x1ea7025, 0xacce08e0,
@@ -11449,7 +11931,7 @@ u32 bce_CP_b09FwText[(0x5418/4) + 1] = {
0x0, 0x0, 0x3c038000, 0x8c640000,
0x30820020, 0x1040fffd, 0x3c0f6000, 0x8ded08e0,
0x3c0e0100, 0x1ae1824, 0x1460ffe1, 0x0,
-0xaf870028, 0x3e00008, 0xaf8b003c, 0x8f85002c,
+0xaf87003c, 0x3e00008, 0xaf8b0058, 0x8f850040,
0x240bfff0, 0x3c068000, 0x94a7001a, 0x8ca90024,
0x30ecffff, 0xc38c0, 0xeb5024, 0x12a4021,
0xacc8003c, 0x8ca40024, 0x8cc3003c, 0x831023,
@@ -11465,1354 +11947,1351 @@ u32 bce_CP_b09FwText[(0x5418/4) + 1] = {
0x25a70001, 0xa4a7001a, 0x94ab001a, 0x94ac001e,
0x118b0003, 0x0, 0x3e00008, 0x0,
0x3e00008, 0xa4a0001a, 0x8d2a0400, 0xacaa0010,
-0x8d240404, 0xaca40014, 0xa0001be, 0x3c190020,
-0x8ca20020, 0xa0001a6, 0x3c0f0050, 0xa000194,
-0x0, 0x3c030800, 0x8c630020, 0x8f820034,
-0x27bdffe8, 0x10620008, 0xafbf0010, 0xe0001d8,
-0xaf830034, 0x3c030800, 0x8c630020, 0x24040001,
-0x10640004, 0x8f8c002c, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x8fbf0010, 0x3c058000, 0xa580000a,
-0x958b000a, 0x958a0004, 0x27bd0018, 0x3167ffff,
-0x3149000f, 0x94500, 0xe83025, 0x3e00008,
-0xaca60080, 0x3c020800, 0x8c420020, 0x27bdffc8,
-0xafbf0034, 0xafbe0030, 0xafb7002c, 0xafb60028,
+0x8d240404, 0xaca40014, 0xa000218, 0x3c190020,
+0x8ca20020, 0xa000200, 0x3c0f0050, 0xa0001ee,
+0x0, 0x27bdffe8, 0xafbf0010, 0xe000232,
+0x0, 0x8f890040, 0x8fbf0010, 0x3c038000,
+0xa520000a, 0x9528000a, 0x95270004, 0x27bd0018,
+0x3105ffff, 0x30e6000f, 0x61500, 0xa22025,
+0x3e00008, 0xac640080, 0x3c050800, 0x8ca50020,
+0x8f83000c, 0x27bdffe8, 0xafb00010, 0xafbf0014,
+0x10a30010, 0x8021, 0x24040001, 0x2043004,
+0xa62024, 0xc31024, 0x50440006, 0x26100001,
+0x101880, 0x2787fda4, 0x1480000a, 0x671821,
+0x26100001, 0x2e090002, 0x5520fff3, 0x8f83000c,
+0xaf85000c, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x8c680000, 0x3c058000, 0xaca80024,
+0xe000234, 0x26100001, 0x3c050800, 0x8ca50020,
+0xa000259, 0x2e090002, 0x24050001, 0x851804,
+0x3c040800, 0x8c840020, 0x27bdffc8, 0xafbf0034,
+0x831024, 0xafbe0030, 0xafb7002c, 0xafb60028,
0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018,
-0xafb10014, 0x10400053, 0xafb00010, 0x8f84002c,
-0x94860006, 0x9483000a, 0xc32823, 0x30b6ffff,
-0x12c0004d, 0x8fbf0034, 0x94890018, 0x948a000a,
-0x12a4023, 0x3102ffff, 0x2c2382b, 0x14e00002,
-0x2c02021, 0x402021, 0x2c8c0005, 0x15800002,
-0x80a021, 0x24140004, 0xe000167, 0x2802021,
-0x8f87002c, 0x2809821, 0xaf800030, 0x94ed000a,
-0x2808821, 0x12800051, 0x31b2ffff, 0x3c177000,
-0x3c154000, 0x3c1e6000, 0x8f8f003c, 0x8dee0000,
-0x1d71824, 0x50750053, 0x2202021, 0x2a3802b,
-0x16000038, 0x3c182000, 0x1078004a, 0x0,
-0x24100001, 0x8f830030, 0x1460003c, 0x2915823,
-0x230f823, 0x250c821, 0x33f1ffff, 0x1620ffee,
-0x3332ffff, 0x8f87002c, 0x3c120020, 0x3c118000,
-0xae320030, 0x94ea000a, 0x3c178000, 0x26a4821,
-0xa4e9000a, 0x94e3000a, 0x94e80004, 0x3065ffff,
-0x3106000f, 0x61500, 0xa2f025, 0xaefe0080,
-0x94f4000a, 0x94f50018, 0x12b4003a, 0x13c940,
-0x8cf80014, 0x8cee0010, 0x3195821, 0x7821,
-0x179682b, 0x1cf6021, 0x18d2021, 0xaceb0014,
-0xace40010, 0x2d33823, 0x30f6ffff, 0x16c0ffb6,
-0x8f84002c, 0x8fbf0034, 0x8fbe0030, 0x8fb7002c,
-0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0038, 0x107e001b, 0x0, 0x1477ffc9,
-0x24100001, 0xe0014fc, 0x0, 0x8f830030,
-0x1060ffc8, 0x230f823, 0x2915823, 0x8f87002c,
-0x1702021, 0xa000271, 0x3093ffff, 0x8f830030,
-0x1460ffc8, 0x3c120020, 0x3c118000, 0xa00023a,
-0xae320030, 0xe0003ea, 0x2202021, 0xa00022e,
-0x408021, 0xe0007e2, 0x2402821, 0xa00022e,
-0x408021, 0xe000d99, 0x2202021, 0xa00022e,
-0x408021, 0xe000194, 0x0, 0xa000253,
-0x2d33823, 0x27bdffd0, 0xafb50024, 0xafb40020,
+0xafb10014, 0x10400051, 0xafb00010, 0x8f840040,
+0x94870006, 0x9488000a, 0xe83023, 0x30d5ffff,
+0x12a0004b, 0x8fbf0034, 0x948b0018, 0x948c000a,
+0x16c5023, 0x3142ffff, 0x2a2482b, 0x15200002,
+0x2a02021, 0x402021, 0x2c8f0005, 0x15e00002,
+0x809821, 0x24130004, 0xe0001c1, 0x2602021,
+0x8f870040, 0x2609021, 0xaf800044, 0x94f4000a,
+0x2608021, 0x1260004e, 0x3291ffff, 0x3c167000,
+0x3c144000, 0x3c1e2000, 0x3c176000, 0x8f990058,
+0x8f380000, 0x3161824, 0x1074004f, 0x283f82b,
+0x17e00036, 0x0, 0x107e0047, 0x8f860044,
+0x14c0003a, 0x24030001, 0x2031023, 0x2232021,
+0x3050ffff, 0x1600fff1, 0x3091ffff, 0x8f870040,
+0x3c110020, 0x3c108000, 0xae110030, 0x94eb000a,
+0x3c178000, 0x24b5021, 0xa4ea000a, 0x94e9000a,
+0x94e80004, 0x3123ffff, 0x3106000f, 0x62d00,
+0x65f025, 0xaefe0080, 0x94f3000a, 0x94f60018,
+0x12d30036, 0x122140, 0x8cff0014, 0x8cf40010,
+0x3e46821, 0xc021, 0x1a4782b, 0x2987021,
+0x1cf6021, 0xaced0014, 0xacec0010, 0x2b23823,
+0x30f5ffff, 0x16a0ffb8, 0x8f840040, 0x8fbf0034,
+0x8fbe0030, 0x8fb7002c, 0x8fb60028, 0x8fb50024,
+0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0038, 0x1477ffcc,
+0x8f860044, 0xe000ee2, 0x2002021, 0x401821,
+0x8f860044, 0x10c0ffc9, 0x2031023, 0x2707023,
+0x8f870040, 0x1c36821, 0xa0002e4, 0x31b2ffff,
+0x8f860044, 0x14c0ffc9, 0x3c110020, 0x3c108000,
+0xa0002ae, 0xae110030, 0xe000466, 0x2002021,
+0xa0002db, 0x401821, 0x2002021, 0xe000939,
+0x2202821, 0xa0002db, 0x401821, 0xe0001ee,
+0x0, 0xa0002c7, 0x2b23823, 0x27bdffc8,
+0xafb7002c, 0xafb60028, 0xafb50024, 0xafb40020,
0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010,
-0xafbf0028, 0xe0000e4, 0x3c148000, 0x3c028008,
-0x3c032000, 0x3c010800, 0xac200070, 0x34550080,
-0x34720003, 0x24130001, 0x36900070, 0x2411ff80,
-0xa0002a1, 0x8e060000, 0x3c198000, 0x8f380000,
-0x3b0f0001, 0x31e20001, 0x10400025, 0x8f860084,
-0x8e070000, 0x3c0d0800, 0x8dad003c, 0x3c0a0800,
-0x8d4a0038, 0xe67023, 0x1ae4021, 0x5821,
-0x10e302b, 0x14b4821, 0x1262021, 0x3c010800,
-0xac28003c, 0xaf870084, 0x3c010800, 0xac240038,
-0xe0001da, 0x0, 0x3c050800, 0x8ca50070,
-0x10a0ffe5, 0xa02021, 0x3c050800, 0x8ca50068,
-0x3c060800, 0x8cc6006c, 0xe00149f, 0x0,
-0x3c010800, 0xac200070, 0x3c198000, 0x8f380000,
-0x3b0f0001, 0x31e20001, 0x1440ffdd, 0x8f860084,
-0x8e0c0000, 0x8f8d0084, 0x3c070800, 0x8ce7003c,
-0x3c060800, 0x8cc60038, 0x18d5823, 0xeb2821,
-0xab202b, 0xc24821, 0x1241021, 0x3c010800,
-0xac25003c, 0x3c088000, 0x3c010800, 0xac220038,
-0x8d030100, 0x241f0c00, 0x107f0026, 0x0,
-0x8d180100, 0x240e0020, 0xad180020, 0x92af0000,
-0x31e300ff, 0x106e0023, 0x24190050, 0x10790026,
-0x0, 0x3c048000, 0x8c880100, 0x15000003,
-0x0, 0x56600014, 0x3c044000, 0x8c990100,
-0x8c8f0100, 0x9821, 0x331c024, 0x186940,
-0x31ee007f, 0x1ae6025, 0x1925825, 0xac8b0830,
-0x8c870100, 0x8c890100, 0x24ea0100, 0x1513024,
-0x62940, 0x3123007f, 0xa31025, 0x52f825,
-0xac9f0830, 0x3c044000, 0xae840138, 0xa000299,
-0x0, 0xe0001f6, 0x0, 0xa0002e3,
-0x3c048000, 0x8d040100, 0xe00079b, 0x0,
-0xa0002e3, 0x3c048000, 0x8d040100, 0xe0013b7,
-0x0, 0xa0002e3, 0x3c048000, 0xa4102b,
-0x24030001, 0x10400009, 0x3021, 0x52840,
-0xa4102b, 0x4a00003, 0x31840, 0x5440fffc,
-0x52840, 0x5060000a, 0x4182b, 0x85382b,
-0x54e00004, 0x31842, 0xc33025, 0x852023,
-0x31842, 0x1460fff9, 0x52842, 0x4182b,
-0x3e00008, 0xc31021, 0x3084ffff, 0x30c600ff,
-0x3c078000, 0x8ce201b8, 0x440fffe, 0x64c00,
-0x1243025, 0x3c082000, 0xc82025, 0x3c031000,
-0xace00180, 0xace50184, 0xace40188, 0x3e00008,
-0xace301b8, 0x3c066000, 0x8cc5201c, 0x2402fff0,
-0x30830200, 0x30860100, 0x1060000e, 0xa22824,
-0x34a50001, 0x30873000, 0x10e00005, 0x30830c00,
-0x34a50004, 0x3c046000, 0x3e00008, 0xac85201c,
-0x1060fffd, 0x3c046000, 0x34a50008, 0x3e00008,
-0xac85201c, 0x54c0fff3, 0x34a50002, 0xa00033b,
-0x30873000, 0x27bdffe8, 0xafb00010, 0xafbf0014,
-0x3c076000, 0x24060002, 0x10800011, 0xa08021,
-0x8f83003c, 0xe000332, 0x8c640018, 0x8f82003c,
-0x2021, 0x24060001, 0x8c45000c, 0xe000323,
-0x0, 0x16000002, 0x24020003, 0x1021,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x8ce8201c, 0x2409fff0, 0x1092824, 0xace5201c,
-0x8f87003c, 0xa000358, 0x8ce5000c, 0x3c02600e,
-0x804021, 0x34460100, 0x24090018, 0x0,
-0x0, 0x0, 0x3c0a0050, 0x3c038000,
-0x35470200, 0xac680038, 0x34640400, 0xac65003c,
-0xac670030, 0x8c6c0000, 0x318b0020, 0x1160fffd,
-0x2407ffff, 0x2403007f, 0x8c8d0000, 0x2463ffff,
-0x24840004, 0xaccd0000, 0x1467fffb, 0x24c60004,
-0x0, 0x0, 0x0, 0x24a40200,
-0x85282b, 0x3c030020, 0x3c0e8000, 0x2529ffff,
-0x1054021, 0xadc30030, 0x1520ffe0, 0x802821,
-0x3e00008, 0x0, 0x8f82003c, 0x27bdffd8,
-0xafb3001c, 0xafbf0020, 0xafb20018, 0xafb10014,
-0xafb00010, 0x94460002, 0x809821, 0x8c520018,
-0x2cc30081, 0x8c480004, 0x8c470008, 0x8c51000c,
-0x8c490010, 0x10600007, 0x8c4a0014, 0x2cc40004,
-0x14800013, 0x30eb0007, 0x30c50003, 0x10a00010,
-0x0, 0x2410008b, 0x2002021, 0x2202821,
-0xe000323, 0x24060003, 0x16600002, 0x24020003,
-0x1021, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028,
-0x1560fff1, 0x2410008b, 0x3c0c8000, 0x3c030020,
-0x241f0001, 0xad830030, 0xaf9f0030, 0x0,
-0x0, 0x0, 0x2419fff0, 0x24d8000f,
-0x3197824, 0x3c1000d0, 0xad880038, 0x1f07025,
-0x24cd0003, 0x3c08600e, 0xad87003c, 0x35850400,
-0xad8e0030, 0xd3882, 0x3504003c, 0x3c038000,
-0x8c6b0000, 0x31620020, 0x1040fffd, 0x0,
-0x10e00008, 0x24e3ffff, 0x2407ffff, 0x8ca80000,
-0x2463ffff, 0x24a50004, 0xac880000, 0x1467fffb,
-0x24840004, 0x3c04600e, 0xac860038, 0x0,
-0x0, 0x0, 0x3c070020, 0x3c068000,
-0x1202021, 0x1402821, 0xacc70030, 0xe000368,
-0x8021, 0xe000332, 0x2402021, 0xa0003a8,
-0x2002021, 0x27bdffd8, 0xafb20018, 0x3092ffff,
-0xafb10014, 0xafbf0020, 0xafb3001c, 0xafb00010,
-0x1240002d, 0x8821, 0xa0003fe, 0x24130003,
-0x50b30042, 0x8ce5000c, 0xd, 0x26390001,
-0x3331ffff, 0x24f80020, 0x232382b, 0x10e00022,
-0xaf98003c, 0x8f820030, 0x1440001f, 0x8f87003c,
-0x3c067000, 0x3c032000, 0x8ce40000, 0x862824,
-0x14a30019, 0x8f850044, 0x44402, 0x3c098000,
-0x898024, 0x14a0ffea, 0x310600ff, 0x240a0002,
-0x10ca0030, 0x28cb0003, 0x11600017, 0x0,
-0x24040001, 0x14c4ffe6, 0x26390001, 0x2002821,
-0xe00034a, 0x24040001, 0x8f87003c, 0xaf820044,
-0x26390001, 0x3331ffff, 0x24f80020, 0x232382b,
-0x14e0ffe0, 0xaf98003c, 0x2201021, 0x8fbf0020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x10d3001b, 0x240c0004,
-0x14ccffcf, 0x26390001, 0x308dffff, 0xd19c0,
-0x3c048000, 0x8c8e01b8, 0x5c0fffe, 0x3c0f1000,
-0x3c102004, 0xac830180, 0xac800184, 0xac900188,
-0xac8f01b8, 0xa0003f9, 0x26390001, 0xe000323,
-0x24040084, 0x1600ffbd, 0x8f87003c, 0xa0003f8,
-0xaf800044, 0x2002821, 0xe00034a, 0x2021,
-0xa000418, 0x8f87003c, 0xe00038f, 0x2002021,
-0x8f87003c, 0xa000419, 0xaf820044, 0x449c2,
-0x3127003f, 0x44342, 0x3c028000, 0x82040,
-0x24031680, 0x2ce60020, 0xac43002c, 0x24eaffe0,
-0x24820001, 0x14c00003, 0x30a900ff, 0x801021,
-0x314700ff, 0x26080, 0x3c0d8000, 0x240a0001,
-0x18d2021, 0x3c0b000e, 0xea2804, 0x8b3021,
-0x11200005, 0x53827, 0x8cce0000, 0x1c53825,
-0x3e00008, 0xacc70000, 0x8cd80000, 0x3077824,
-0x3e00008, 0xaccf0000, 0x27bdffe0, 0xafb10014,
-0xafb00010, 0xafbf0018, 0x3c076000, 0x8ce40808,
-0x3402f000, 0x3c116000, 0x3083f000, 0x240501c0,
-0x3c04800e, 0x3021, 0x10620006, 0x24100001,
-0x8cea0808, 0x3149f000, 0x3928e000, 0x8382b,
-0x78040, 0x3c0d0200, 0xae2d0814, 0x240c1680,
-0x3c0b8000, 0x8e274400, 0xe000e42, 0xad6c002c,
-0x12000004, 0x3c021691, 0x24050001, 0x12050010,
-0x3c023d6c, 0x345800e0, 0xae384408, 0x3c110800,
-0x8e31007c, 0x8fbf0018, 0x3c066000, 0x118540,
-0x360f1680, 0x8fb10014, 0x8fb00010, 0x3c0e0200,
-0x27bd0020, 0xaccf4420, 0x3e00008, 0xacce0810,
-0x3c0218da, 0x345800e0, 0xae384408, 0x3c110800,
-0x8e31007c, 0x8fbf0018, 0x3c066000, 0x118540,
-0x360f1680, 0x8fb10014, 0x8fb00010, 0x3c0e0200,
-0x27bd0020, 0xaccf4420, 0x3e00008, 0xacce0810,
-0xa000448, 0x24050001, 0xa000448, 0x2821,
-0x24020400, 0xa782000c, 0xa7800004, 0x2021,
-0x3c060800, 0x24c656b8, 0x2405ffff, 0x24890001,
-0x44080, 0x3124ffff, 0x1061821, 0x2c870020,
-0x14e0fffa, 0xac650000, 0x24040400, 0xa784000e,
-0xa7800006, 0x2021, 0x3c060800, 0x24c65738,
-0x2405ffff, 0x248d0001, 0x46080, 0x31a4ffff,
-0x1865821, 0x2c8a0020, 0x1540fffa, 0xad650000,
-0xa7800010, 0xa7800008, 0xa780000a, 0x2021,
-0x3c060800, 0x24c657b8, 0x2405ffff, 0x24990001,
-0x4c080, 0x3324ffff, 0x3067821, 0x2c8e0004,
-0x15c0fffa, 0xade50000, 0x3c056000, 0x8ca73d00,
-0x2403e08f, 0xe31024, 0x34460140, 0x3e00008,
-0xaca63d00, 0x2487007f, 0x731c2, 0x24c5ffff,
-0x518c2, 0x24640001, 0x3082ffff, 0x238c0,
-0xa7840018, 0x3c010800, 0xac270030, 0xaf800014,
-0x2821, 0x2021, 0x3021, 0x24890001,
-0xa72821, 0x3124ffff, 0x2ca81701, 0x11000003,
-0x2c830080, 0x1460fff9, 0x24c60001, 0xc02821,
-0xaf860014, 0x10c0001d, 0xa7860012, 0x24caffff,
-0xa1142, 0x3c080800, 0x250857b8, 0x1040000a,
-0x2021, 0x403021, 0x2407ffff, 0x248e0001,
-0x46880, 0x31c4ffff, 0x1a86021, 0x86582b,
-0x1560fffa, 0xad870000, 0x30a2001f, 0x50400008,
-0x43080, 0x24030001, 0x43c804, 0x41080,
-0x487821, 0x2738ffff, 0x3e00008, 0xadf80000,
-0xc82021, 0x2405ffff, 0xac850000, 0x3e00008,
-0x0, 0x30a5ffff, 0x30c6ffff, 0x30a8001f,
-0x806021, 0x30e700ff, 0x52942, 0x5021,
-0x10c0001d, 0x24090001, 0x240b0001, 0x25180001,
-0x10b2004, 0x330800ff, 0x1267826, 0x390e0020,
-0x2ded0001, 0x2dc20001, 0x1a21825, 0x1060000d,
-0x1445025, 0x5c880, 0x32c4021, 0x1001821,
-0x10e0000f, 0xa2027, 0x8d040000, 0x8a1825,
-0xad030000, 0x24ad0001, 0x4021, 0x5021,
-0x31a5ffff, 0x252e0001, 0x31c9ffff, 0xc9102b,
-0x1040ffe7, 0x25180001, 0x3e00008, 0x0,
-0x8d0a0000, 0x1444024, 0xa00052e, 0xac680000,
-0x27bdffe8, 0x30a5ffff, 0x30c6ffff, 0xafb00010,
-0xafbf0014, 0x30e7ffff, 0x5021, 0x3410ffff,
-0x6021, 0x24af001f, 0xc04821, 0x24180001,
-0x24190020, 0x5e00016, 0x1e01021, 0x2f943,
-0x19f682a, 0x9702b, 0x1ae4024, 0x11000017,
-0xc1880, 0x641021, 0x10e00005, 0x8c4b0000,
-0xf84004, 0x83823, 0x1675824, 0x3821,
-0x15400041, 0x4021, 0x55600016, 0x3169ffff,
-0x258b0001, 0x316cffff, 0x5e1ffec, 0x1e01021,
-0x24a2003e, 0x2f943, 0x19f682a, 0x9702b,
-0x1ae4024, 0x1500ffeb, 0xc1880, 0x15460005,
-0x3402ffff, 0x2002821, 0xe000512, 0x3821,
-0x2001021, 0x8fbf0014, 0x8fb00010, 0x3e00008,
-0x27bd0018, 0x15200003, 0x1601821, 0xb1c02,
-0x24080010, 0x306a00ff, 0x15400005, 0x306e000f,
-0x250d0008, 0x31a02, 0x31a800ff, 0x306e000f,
-0x15c00005, 0x307f0003, 0x25100004, 0x31902,
-0x320800ff, 0x307f0003, 0x17e00005, 0x38690001,
-0x25020002, 0x31882, 0x304800ff, 0x38690001,
-0x31230001, 0x10600004, 0x310300ff, 0x250a0001,
-0x314800ff, 0x310300ff, 0xc6940, 0x1a34021,
-0x240a0001, 0x10caffd5, 0x3110ffff, 0x246e0001,
-0x31c800ff, 0x1119ffc6, 0x38c90001, 0x2d1f0020,
-0x53e0001c, 0x258b0001, 0x240d0001, 0xa0005a5,
-0x240e0020, 0x51460017, 0x258b0001, 0x25090001,
-0x312800ff, 0x2d090020, 0x51200012, 0x258b0001,
-0x25430001, 0x10d5004, 0x14b1024, 0x25090001,
-0x1440fff4, 0x306affff, 0x3127ffff, 0x10ee000c,
-0x2582ffff, 0x304cffff, 0x5021, 0x3410ffff,
-0x312800ff, 0x2d090020, 0x5520fff2, 0x25430001,
-0x258b0001, 0x1464826, 0xa00055f, 0x316cffff,
-0x3821, 0x5021, 0xa0005b1, 0x3410ffff,
-0x27bdffd8, 0xafb00010, 0x30f0ffff, 0xafb10014,
-0x103942, 0x3211ffe0, 0x71080, 0xafb3001c,
-0xb12823, 0x30d3ffff, 0xafb20018, 0x30a5ffff,
-0x809021, 0x2603021, 0x442021, 0xafbf0020,
-0xe00053d, 0x3207001f, 0x2228821, 0x3403ffff,
-0x2402021, 0x2002821, 0x2603021, 0x3821,
-0x10430009, 0x3231ffff, 0x2201021, 0x8fbf0020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0xe00053d, 0x0,
-0x408821, 0x2201021, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0028, 0x42400, 0x3c036000, 0xac603d08,
-0x10a00002, 0x34821006, 0x34821016, 0x3e00008,
-0xac623d04, 0x27bdffe0, 0xafb00010, 0x309000ff,
-0x2e020006, 0xafbf0018, 0x10400008, 0xafb10014,
-0x103080, 0x3c030800, 0x24635424, 0xc32821,
-0x8ca40000, 0x800008, 0x0, 0x2021,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x801021,
-0x3e00008, 0x27bd0020, 0x97910012, 0x16200051,
-0x2021, 0x3c020800, 0x90420033, 0xa000618,
-0x0, 0x978d000e, 0x15a00031, 0x2021,
-0xa000618, 0x24020008, 0x9787000c, 0x14e0001a,
-0x1821, 0x602021, 0x24020001, 0x1080ffe9,
-0x8fbf0018, 0x429c2, 0x453021, 0xa6582b,
-0x1160ffe4, 0x3c088000, 0x3c072000, 0x569c0,
-0x1a76025, 0xad0c0020, 0x3c038008, 0x2402001f,
-0x2442ffff, 0xac600000, 0x441fffd, 0x24630004,
-0x24a50001, 0xa6702b, 0x15c0fff5, 0x569c0,
-0xa000602, 0x8fbf0018, 0x97870004, 0x3c040800,
-0x248456b8, 0x24050400, 0xe0005bd, 0x24060001,
-0x978b000c, 0x24440001, 0x308affff, 0x2569ffff,
-0x2d480400, 0x402821, 0x15000040, 0xa789000c,
-0x24ac3800, 0xc19c0, 0xa000616, 0xa7800004,
-0x97870006, 0x3c040800, 0x24845738, 0x24050400,
-0xe0005bd, 0x24060001, 0x9799000e, 0x24440001,
-0x3098ffff, 0x272fffff, 0x2f0e0400, 0x408821,
-0x15c0002c, 0xa78f000e, 0xa7800006, 0x3a020003,
-0x26240100, 0x3084ffff, 0xe0005ea, 0x2c450001,
-0x11f8c0, 0x27f00100, 0x1021c0, 0xa000618,
-0x24020008, 0x97850016, 0x9787000a, 0x3c040800,
-0x248457b8, 0xe0005bd, 0x24060001, 0x97870012,
-0x8f890014, 0x24450001, 0x30a8ffff, 0x24e3ffff,
-0x109302b, 0x408021, 0x14c00018, 0xa7830012,
-0xa780000a, 0x97850018, 0xe000e2c, 0x2002021,
-0x244a0500, 0x3144ffff, 0xe0005ea, 0x24050001,
-0x3c050800, 0x94a50032, 0xe000e2c, 0x2002021,
-0x24452100, 0x3c020800, 0x90420033, 0xa000618,
-0x521c0, 0xa000650, 0xa7840006, 0x24ac3800,
-0xc19c0, 0xa000616, 0xa7840004, 0xa00066a,
-0xa785000a, 0x308400ff, 0x27bdffe8, 0x2c820006,
-0xafbf0014, 0xafb00010, 0x10400015, 0xa03821,
-0x44080, 0x3c030800, 0x2463543c, 0x1032821,
-0x8ca40000, 0x800008, 0x0, 0x24cc007f,
-0x751c2, 0xc59c2, 0x3170ffff, 0x2547c400,
-0x30e5ffff, 0x27840004, 0x2003021, 0xe000512,
-0x24070001, 0x97860010, 0x2062021, 0xa7840010,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x3c050800, 0x8ca50030, 0x779c2, 0xe00030c,
-0x25e4df00, 0x3045ffff, 0x3c040800, 0x248457b8,
-0x24060001, 0xe000512, 0x24070001, 0x978e0012,
-0x8fbf0014, 0x8fb00010, 0x25cd0001, 0x27bd0018,
-0x3e00008, 0xa78d0012, 0x7c9c2, 0x2738ff00,
-0x1878c2, 0x31f0ffff, 0x3c040800, 0x24845738,
-0x2002821, 0x24060001, 0xe000512, 0x24070001,
-0x978d000e, 0x260e0100, 0xe8400, 0x25ac0001,
-0x3c0b6000, 0xa78c000e, 0xad603d08, 0x36040006,
-0x3021, 0x3c076000, 0x8ce23d04, 0x305f0006,
-0x17e0fffd, 0x24c90001, 0x61b00, 0x312600ff,
-0x644025, 0x2cc50004, 0xace83d04, 0x14a0fff6,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x751c2, 0x2549c800, 0x24060001, 0x24070001,
-0x3c040800, 0x248456b8, 0xe000512, 0x3125ffff,
-0x9787000c, 0x8fbf0014, 0x8fb00010, 0x24e60001,
-0x27bd0018, 0x3e00008, 0xa786000c, 0x3084ffff,
-0x30a5ffff, 0x3c068000, 0x8cc201b8, 0x440fffe,
-0x3c084080, 0x883825, 0x3c031000, 0xacc00180,
-0xacc50184, 0xacc70188, 0x3e00008, 0xacc301b8,
-0x3084ffff, 0x3c068000, 0x8cc201b8, 0x440fffe,
-0x3c084038, 0x8ca70000, 0x882825, 0x3c031000,
-0xacc70180, 0xacc50188, 0x3e00008, 0xacc301b8,
-0x8f83005c, 0x8f860054, 0x1066000b, 0x804021,
-0x3c070800, 0x24e757c8, 0x328c0, 0xa71021,
-0x8c440000, 0x24630001, 0x10880005, 0x3063000f,
-0x5466fffa, 0x328c0, 0x3e00008, 0x1021,
-0x3c070800, 0x24e757cc, 0xa73021, 0x3e00008,
-0x8cc20000, 0x3c039000, 0x34620001, 0x822025,
-0x3c038000, 0xac640020, 0x8c650020, 0x4a0fffe,
-0x0, 0x3e00008, 0x0, 0x3c028000,
-0x34430001, 0x832025, 0x3e00008, 0xac440020,
-0x27bdffe0, 0xafb10014, 0x3091ffff, 0xafb00010,
-0xafbf0018, 0x12200012, 0xa08021, 0x8ca50000,
-0x14a00011, 0x24040002, 0x3c068000, 0x8cc201b8,
-0x440fffe, 0x3c074000, 0x2272025, 0x8fbf0018,
-0x8fb10014, 0x8fb00010, 0x3c031000, 0x27bd0020,
-0xacc50180, 0xacc40188, 0x3e00008, 0xacc301b8,
-0xa00072b, 0x8ca50000, 0xe000682, 0x24060200,
-0x2821, 0xa00072b, 0xae000000, 0x3087ffff,
-0x3c068000, 0x8cc201b8, 0x440fffe, 0x3c0a4006,
-0x8ca90000, 0xea4025, 0xacc90180, 0x8ca40004,
-0x3c031000, 0xacc40184, 0xacc80188, 0x3e00008,
-0xacc301b8, 0x8f83fdf8, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0x90670008, 0x801021, 0x802821,
-0x30e60040, 0x2021, 0x10c00008, 0x8c500000,
-0xe000086, 0x2002021, 0x2002021, 0x8fbf0014,
-0x8fb00010, 0xa0004a5, 0x27bd0018, 0xe000740,
-0x0, 0xe000086, 0x2002021, 0x2002021,
-0x8fbf0014, 0x8fb00010, 0xa0004a5, 0x27bd0018,
-0x27bdffe0, 0xafb00010, 0x8f90fdf8, 0xafbf001c,
-0xafb20018, 0xafb10014, 0x92060001, 0x808821,
-0xe000712, 0x30d20004, 0x92040005, 0x1129c2,
-0xa6050000, 0x34830040, 0xa2030005, 0xe00071c,
-0x2202021, 0xe0004a7, 0x2202021, 0x24020001,
-0xae02000c, 0x2202821, 0xa6020010, 0x24040002,
-0xa6020012, 0x24060200, 0xa6020014, 0xe000682,
-0xa6020016, 0x1640000f, 0x8fbf001c, 0x978c0058,
-0x3c0b0800, 0x8d6b0078, 0x2588ffff, 0x3109ffff,
-0x256a0001, 0x12a382b, 0x10e00006, 0xa7880058,
-0x3c0f6006, 0x240e0016, 0x35ed0010, 0xadae0050,
+0xafbf0030, 0xe00011b, 0x24130001, 0x3c047fff,
+0x3c038008, 0x3c022000, 0x3c010800, 0xac200070,
+0x3496ffff, 0x34770080, 0x34520003, 0x3c1512c0,
+0x24140001, 0x3c108000, 0x2411ff80, 0xe000245,
+0x0, 0x8f870048, 0x8f8b0018, 0x8f890014,
+0x8cea00ec, 0x8ce800e8, 0x14b302b, 0x1092823,
+0xa61023, 0x14400006, 0x14b1823, 0x1440000e,
+0x3c058000, 0x2a3602b, 0x1180000b, 0x0,
+0x3c056000, 0x8cee00ec, 0x8ced00e8, 0x8ca4180c,
+0xaf8e0018, 0x4800053, 0xaf8d0014, 0x8f8f0010,
+0xadf40000, 0x3c058000, 0x8cbf0000, 0x3bf90001,
+0x33380001, 0x1700ffe1, 0x3c038000, 0x8c620100,
+0x24060c00, 0x10460009, 0x0, 0x8c680100,
+0x2d043080, 0x54800010, 0x3c048000, 0x8c690100,
+0x2d233181, 0x1060000c, 0x3c048000, 0x8caa0100,
+0x11460004, 0x2021, 0x8ca60100, 0x24c5ff81,
+0x30a400ff, 0x8e0b0100, 0xe000269, 0xae0b0024,
+0xa00034f, 0x3c048000, 0x8c8d0100, 0x2dac3300,
+0x11800022, 0x0, 0x3c070800, 0x8ce70098,
+0x24ee0001, 0x3c010800, 0xac2e0098, 0x3c048000,
+0x8c820100, 0x14400003, 0x0, 0x56600014,
+0x3c044000, 0x8c9f0100, 0x8c980100, 0x9821,
+0x3f1c824, 0x193940, 0x330f007f, 0xef7025,
+0x1d26825, 0xac8d0830, 0x8c8c0100, 0x8c850100,
+0x258b0100, 0x1713024, 0x65140, 0x30a3007f,
+0x1434825, 0x1324025, 0xac880830, 0x3c044000,
+0xae040138, 0xa00030e, 0x0, 0x8c990100,
+0x240f0020, 0xac990020, 0x92f80000, 0x330300ff,
+0x106f000c, 0x241f0050, 0x547fffdd, 0x3c048000,
+0x8c840100, 0xe00154e, 0x0, 0xa00034f,
+0x3c048000, 0x963824, 0xaca7180c, 0xa000327,
+0x8f8f0010, 0x8c850100, 0xe0008f7, 0x24040080,
+0xa00034f, 0x3c048000, 0xa4102b, 0x24030001,
+0x10400009, 0x3021, 0x52840, 0xa4102b,
+0x4a00003, 0x31840, 0x5440fffc, 0x52840,
+0x5060000a, 0x4182b, 0x85382b, 0x54e00004,
+0x31842, 0xc33025, 0x852023, 0x31842,
+0x1460fff9, 0x52842, 0x4182b, 0x3e00008,
+0xc31021, 0x3084ffff, 0x30c600ff, 0x3c078000,
+0x8ce201b8, 0x440fffe, 0x64c00, 0x1243025,
+0x3c082000, 0xc82025, 0x3c031000, 0xace00180,
+0xace50184, 0xace40188, 0x3e00008, 0xace301b8,
+0x3c066000, 0x8cc5201c, 0x2402fff0, 0x30830200,
+0x30860100, 0x1060000e, 0xa22824, 0x34a50001,
+0x30873000, 0x10e00005, 0x30830c00, 0x34a50004,
+0x3c046000, 0x3e00008, 0xac85201c, 0x1060fffd,
+0x3c046000, 0x34a50008, 0x3e00008, 0xac85201c,
+0x54c0fff3, 0x34a50002, 0xa0003b0, 0x30873000,
+0x27bdffe8, 0xafb00010, 0xafbf0014, 0x3c076000,
+0x24060002, 0x10800011, 0xa08021, 0x8f830058,
+0xe0003a7, 0x8c640018, 0x8f820058, 0x2021,
+0x24060001, 0x8c45000c, 0xe000398, 0x0,
+0x16000002, 0x24020003, 0x1021, 0x8fbf0014,
+0x8fb00010, 0x3e00008, 0x27bd0018, 0x8ce8201c,
+0x2409fff0, 0x1092824, 0xace5201c, 0x8f870058,
+0xa0003cd, 0x8ce5000c, 0x3c02600e, 0x804021,
+0x34460100, 0x24090018, 0x0, 0x0,
+0x0, 0x3c0a0050, 0x3c038000, 0x35470200,
+0xac680038, 0x34640400, 0xac65003c, 0xac670030,
+0x8c6c0000, 0x318b0020, 0x1160fffd, 0x2407ffff,
+0x2403007f, 0x8c8d0000, 0x2463ffff, 0x24840004,
+0xaccd0000, 0x1467fffb, 0x24c60004, 0x0,
+0x0, 0x0, 0x24a40200, 0x85282b,
+0x3c030020, 0x3c0e8000, 0x2529ffff, 0x1054021,
+0xadc30030, 0x1520ffe0, 0x802821, 0x3e00008,
+0x0, 0x8f820058, 0x27bdffd8, 0xafb3001c,
+0xafbf0020, 0xafb20018, 0xafb10014, 0xafb00010,
+0x94460002, 0x809821, 0x8c520018, 0x2cc30081,
+0x8c480004, 0x8c470008, 0x8c51000c, 0x8c490010,
+0x10600007, 0x8c4a0014, 0x2cc40004, 0x14800013,
+0x30eb0007, 0x30c50003, 0x10a00010, 0x0,
+0x2410008b, 0x2002021, 0x2202821, 0xe000398,
+0x24060003, 0x16600002, 0x24020003, 0x1021,
+0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0028, 0x1560fff1,
+0x2410008b, 0x3c0c8000, 0x3c030020, 0x241f0001,
+0xad830030, 0xaf9f0044, 0x0, 0x0,
+0x0, 0x2419fff0, 0x24d8000f, 0x3197824,
+0x3c1000d0, 0xad880038, 0x1f07025, 0x24cd0003,
+0x3c08600e, 0xad87003c, 0x35850400, 0xad8e0030,
+0xd3882, 0x3504003c, 0x3c038000, 0x8c6b0000,
+0x31620020, 0x1040fffd, 0x0, 0x10e00008,
+0x24e3ffff, 0x2407ffff, 0x8ca80000, 0x2463ffff,
+0x24a50004, 0xac880000, 0x1467fffb, 0x24840004,
+0x3c05600e, 0xaca60038, 0x0, 0x0,
+0x0, 0x8f860054, 0x3c040020, 0x3c078000,
+0xace40030, 0x54c00006, 0x1202021, 0x2402021,
+0xe0003a7, 0x8021, 0xa00041d, 0x2002021,
+0xe0003dd, 0x1402821, 0x2402021, 0xe0003a7,
+0x8021, 0xa00041d, 0x2002021, 0x27bdffe0,
+0xafb20018, 0x3092ffff, 0xafb10014, 0xafbf001c,
+0xafb00010, 0x1640000d, 0x8821, 0xa000493,
+0x2201021, 0x24050003, 0x50850027, 0x8ce5000c,
+0xd, 0x26280001, 0x3111ffff, 0x24e20020,
+0x232802b, 0x12000019, 0xaf820058, 0x8f820044,
+0x14400016, 0x8f870058, 0x3c067000, 0x3c032000,
+0x8ce50000, 0xa62024, 0x14830010, 0x8f840060,
+0x54402, 0x3c098000, 0xa98024, 0x1480ffe9,
+0x310600ff, 0x2cca000b, 0x5140ffeb, 0x26280001,
+0x66880, 0x3c0e0800, 0x25ce5758, 0x1ae6021,
+0x8d8b0000, 0x1600008, 0x0, 0x2201021,
0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018,
-0xafb10014, 0xafb00010, 0xe000712, 0x808821,
-0x8f85fdf8, 0x2202021, 0x90a30005, 0xe00071c,
-0x307000ff, 0x2402003e, 0x12020005, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0xe000398, 0x24040084,
+0x1600ffd8, 0x8f870058, 0xa000474, 0xaf800060,
+0x2002821, 0xe0003bf, 0x24040001, 0x8f870058,
+0xa000474, 0xaf820060, 0x2002821, 0xe0003bf,
+0x2021, 0xa0004a3, 0x8f870058, 0xe000404,
+0x2002021, 0x8f870058, 0xa000474, 0xaf820060,
+0x30afffff, 0xf19c0, 0x3c048000, 0x8c9001b8,
+0x600fffe, 0x3c192004, 0x3c181000, 0xac830180,
+0xac800184, 0xac990188, 0xac9801b8, 0xa000475,
+0x26280001, 0x90e20003, 0x90e30002, 0x2021,
+0x2fe00, 0x33a00, 0xff2825, 0x24060008,
+0xe000398, 0x0, 0x1600ffdc, 0x24020003,
+0x8f870058, 0x1021, 0xa000474, 0xaf820060,
+0x90e80002, 0x2021, 0x24060009, 0xa0004c3,
+0x82e00, 0x90e4000c, 0x240900ff, 0x308500ff,
+0x10a90015, 0x3021, 0x90f90002, 0x90f80003,
+0x308f00ff, 0x94eb0004, 0x196e00, 0x187400,
+0xf6200, 0x1862025, 0x1ae5025, 0x14b2825,
+0x3084ff8b, 0xa0004c3, 0x2406000a, 0x90e30002,
+0x90ff0004, 0x2021, 0x33600, 0xdf2825,
+0xa0004c3, 0x2406000b, 0xa0004d5, 0x2406008b,
+0x449c2, 0x3127003f, 0x44342, 0x3c028000,
+0x82040, 0x24031680, 0x2ce60020, 0xac43002c,
+0x24eaffe0, 0x24820001, 0x14c00003, 0x30a900ff,
+0x801021, 0x314700ff, 0x26080, 0x3c0d8000,
+0x240a0001, 0x18d2021, 0x3c0b000e, 0xea2804,
+0x8b3021, 0x11200005, 0x53827, 0x8cce0000,
+0x1c53825, 0x3e00008, 0xacc70000, 0x8cd80000,
+0x3077824, 0x3e00008, 0xaccf0000, 0x27bdffe0,
+0xafb10014, 0xafb00010, 0xafbf0018, 0x3c076000,
+0x8ce40808, 0x3402f000, 0x3c116000, 0x3083f000,
+0x240501c0, 0x3c04800e, 0x3021, 0x10620006,
+0x24100001, 0x8cea0808, 0x3149f000, 0x3928e000,
+0x8382b, 0x78040, 0x3c0d0200, 0xae2d0814,
+0x240c1680, 0x3c0b8000, 0x8e274400, 0xe000f8b,
+0xad6c002c, 0x12000004, 0x3c021691, 0x24050001,
+0x12050010, 0x3c023d2c, 0x345800e0, 0xae384408,
+0x3c110800, 0x8e31007c, 0x8fbf0018, 0x3c066000,
+0x118540, 0x360f1680, 0x8fb10014, 0x8fb00010,
+0x3c0e0200, 0x27bd0020, 0xaccf4420, 0x3e00008,
+0xacce0810, 0x3c0218da, 0x345800e0, 0xae384408,
+0x3c110800, 0x8e31007c, 0x8fbf0018, 0x3c066000,
+0x118540, 0x360f1680, 0x8fb10014, 0x8fb00010,
+0x3c0e0200, 0x27bd0020, 0xaccf4420, 0x3e00008,
+0xacce0810, 0xa0004eb, 0x24050001, 0xa0004eb,
+0x2821, 0x24020400, 0xa7820024, 0xa780001c,
+0x2021, 0x3c060800, 0x24c65a58, 0x2405ffff,
+0x24890001, 0x44080, 0x3124ffff, 0x1061821,
+0x2c870020, 0x14e0fffa, 0xac650000, 0x24040400,
+0xa7840026, 0xa780001e, 0x2021, 0x3c060800,
+0x24c65ad8, 0x2405ffff, 0x248d0001, 0x46080,
+0x31a4ffff, 0x1865821, 0x2c8a0020, 0x1540fffa,
+0xad650000, 0xa7800028, 0xa7800020, 0xa7800022,
+0x2021, 0x3c060800, 0x24c65b58, 0x2405ffff,
+0x24990001, 0x4c080, 0x3324ffff, 0x3067821,
+0x2c8e0004, 0x15c0fffa, 0xade50000, 0x3c056000,
+0x8ca73d00, 0x2403e08f, 0xe31024, 0x34460140,
+0x3e00008, 0xaca63d00, 0x2487007f, 0x731c2,
+0x24c5ffff, 0x518c2, 0x24640001, 0x3082ffff,
+0x238c0, 0xa7840030, 0x3c010800, 0xac270030,
+0xaf80002c, 0x2821, 0x2021, 0x3021,
+0x24890001, 0xa72821, 0x3124ffff, 0x2ca81701,
+0x11000003, 0x2c830080, 0x1460fff9, 0x24c60001,
+0xc02821, 0xaf86002c, 0x10c0001d, 0xa786002a,
+0x24caffff, 0xa1142, 0x3c080800, 0x25085b58,
+0x1040000a, 0x2021, 0x403021, 0x2407ffff,
+0x248e0001, 0x46880, 0x31c4ffff, 0x1a86021,
+0x86582b, 0x1560fffa, 0xad870000, 0x30a2001f,
+0x50400008, 0x43080, 0x24030001, 0x43c804,
+0x41080, 0x487821, 0x2738ffff, 0x3e00008,
+0xadf80000, 0xc82021, 0x2405ffff, 0xac850000,
+0x3e00008, 0x0, 0x30a5ffff, 0x30c6ffff,
+0x30a8001f, 0x806021, 0x30e700ff, 0x52942,
+0x5021, 0x10c0001d, 0x24090001, 0x240b0001,
+0x25180001, 0x10b2004, 0x330800ff, 0x1267826,
+0x390e0020, 0x2ded0001, 0x2dc20001, 0x1a21825,
+0x1060000d, 0x1445025, 0x5c880, 0x32c4021,
+0x1001821, 0x10e0000f, 0xa2027, 0x8d040000,
+0x8a1825, 0xad030000, 0x24ad0001, 0x4021,
+0x5021, 0x31a5ffff, 0x252e0001, 0x31c9ffff,
+0xc9102b, 0x1040ffe7, 0x25180001, 0x3e00008,
+0x0, 0x8d0a0000, 0x1444024, 0xa0005d1,
+0xac680000, 0x27bdffe8, 0x30a5ffff, 0x30c6ffff,
+0xafb00010, 0xafbf0014, 0x30e7ffff, 0x5021,
+0x3410ffff, 0x6021, 0x24af001f, 0xc04821,
+0x24180001, 0x24190020, 0x5e00016, 0x1e01021,
+0x2f943, 0x19f682a, 0x9702b, 0x1ae4024,
+0x11000017, 0xc1880, 0x641021, 0x10e00005,
+0x8c4b0000, 0xf84004, 0x83823, 0x1675824,
+0x3821, 0x15400041, 0x4021, 0x55600016,
+0x3169ffff, 0x258b0001, 0x316cffff, 0x5e1ffec,
+0x1e01021, 0x24a2003e, 0x2f943, 0x19f682a,
+0x9702b, 0x1ae4024, 0x1500ffeb, 0xc1880,
+0x15460005, 0x3402ffff, 0x2002821, 0xe0005b5,
+0x3821, 0x2001021, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x15200003, 0x1601821,
+0xb1c02, 0x24080010, 0x306a00ff, 0x15400005,
+0x306e000f, 0x250d0008, 0x31a02, 0x31a800ff,
+0x306e000f, 0x15c00005, 0x307f0003, 0x25100004,
+0x31902, 0x320800ff, 0x307f0003, 0x17e00005,
+0x38690001, 0x25020002, 0x31882, 0x304800ff,
+0x38690001, 0x31230001, 0x10600004, 0x310300ff,
+0x250a0001, 0x314800ff, 0x310300ff, 0xc6940,
+0x1a34021, 0x240a0001, 0x10caffd5, 0x3110ffff,
+0x246e0001, 0x31c800ff, 0x1119ffc6, 0x38c90001,
+0x2d1f0020, 0x53e0001c, 0x258b0001, 0x240d0001,
+0xa000648, 0x240e0020, 0x51460017, 0x258b0001,
+0x25090001, 0x312800ff, 0x2d090020, 0x51200012,
+0x258b0001, 0x25430001, 0x10d5004, 0x14b1024,
+0x25090001, 0x1440fff4, 0x306affff, 0x3127ffff,
+0x10ee000c, 0x2582ffff, 0x304cffff, 0x5021,
+0x3410ffff, 0x312800ff, 0x2d090020, 0x5520fff2,
+0x25430001, 0x258b0001, 0x1464826, 0xa000602,
+0x316cffff, 0x3821, 0x5021, 0xa000654,
+0x3410ffff, 0x27bdffd8, 0xafb00010, 0x30f0ffff,
+0xafb10014, 0x103942, 0x3211ffe0, 0x71080,
+0xafb3001c, 0xb12823, 0x30d3ffff, 0xafb20018,
+0x30a5ffff, 0x809021, 0x2603021, 0x442021,
+0xafbf0020, 0xe0005e0, 0x3207001f, 0x2228821,
+0x3403ffff, 0x2402021, 0x2002821, 0x2603021,
+0x3821, 0x10430009, 0x3231ffff, 0x2201021,
+0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0028, 0xe0005e0,
+0x0, 0x408821, 0x2201021, 0x8fbf0020,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0028, 0x42400, 0x3c036000,
+0xac603d08, 0x10a00002, 0x34821006, 0x34821016,
+0x3e00008, 0xac623d04, 0x27bdffe0, 0xafb00010,
+0x309000ff, 0x2e020006, 0xafbf0018, 0x10400008,
+0xafb10014, 0x103080, 0x3c030800, 0x24635784,
+0xc32821, 0x8ca40000, 0x800008, 0x0,
+0x2021, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x801021, 0x3e00008, 0x27bd0020, 0x9791002a,
+0x16200051, 0x2021, 0x3c020800, 0x90420033,
+0xa0006bb, 0x0, 0x978d0026, 0x15a00031,
+0x2021, 0xa0006bb, 0x24020008, 0x97870024,
+0x14e0001a, 0x1821, 0x602021, 0x24020001,
+0x1080ffe9, 0x8fbf0018, 0x429c2, 0x453021,
+0xa6582b, 0x1160ffe4, 0x3c088000, 0x3c072000,
+0x569c0, 0x1a76025, 0xad0c0020, 0x3c038008,
+0x2402001f, 0x2442ffff, 0xac600000, 0x441fffd,
+0x24630004, 0x24a50001, 0xa6702b, 0x15c0fff5,
+0x569c0, 0xa0006a5, 0x8fbf0018, 0x9787001c,
+0x3c040800, 0x24845a58, 0x24050400, 0xe000660,
+0x24060001, 0x978b0024, 0x24440001, 0x308affff,
+0x2569ffff, 0x2d480400, 0x402821, 0x15000040,
+0xa7890024, 0x24ac3800, 0xc19c0, 0xa0006b9,
+0xa780001c, 0x9787001e, 0x3c040800, 0x24845ad8,
+0x24050400, 0xe000660, 0x24060001, 0x97990026,
+0x24440001, 0x3098ffff, 0x272fffff, 0x2f0e0400,
+0x408821, 0x15c0002c, 0xa78f0026, 0xa780001e,
+0x3a020003, 0x26240100, 0x3084ffff, 0xe00068d,
+0x2c450001, 0x11f8c0, 0x27f00100, 0x1021c0,
+0xa0006bb, 0x24020008, 0x9785002e, 0x97870022,
+0x3c040800, 0x24845b58, 0xe000660, 0x24060001,
+0x9787002a, 0x8f89002c, 0x24450001, 0x30a8ffff,
+0x24e3ffff, 0x109302b, 0x408021, 0x14c00018,
+0xa783002a, 0xa7800022, 0x97850030, 0xe000f75,
+0x2002021, 0x244a0500, 0x3144ffff, 0xe00068d,
+0x24050001, 0x3c050800, 0x94a50032, 0xe000f75,
+0x2002021, 0x24452100, 0x3c020800, 0x90420033,
+0xa0006bb, 0x521c0, 0xa0006f3, 0xa784001e,
+0x24ac3800, 0xc19c0, 0xa0006b9, 0xa784001c,
+0xa00070d, 0xa7850022, 0x308400ff, 0x27bdffe8,
+0x2c820006, 0xafbf0014, 0xafb00010, 0x10400015,
+0xa03821, 0x44080, 0x3c030800, 0x2463579c,
+0x1032821, 0x8ca40000, 0x800008, 0x0,
+0x24cc007f, 0x751c2, 0xc59c2, 0x3170ffff,
+0x2547c400, 0x30e5ffff, 0x2784001c, 0x2003021,
+0xe0005b5, 0x24070001, 0x97860028, 0x2062021,
+0xa7840028, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x3c050800, 0x8ca50030, 0x779c2,
+0xe000381, 0x25e4df00, 0x3045ffff, 0x3c040800,
+0x24845b58, 0x24060001, 0xe0005b5, 0x24070001,
+0x978e002a, 0x8fbf0014, 0x8fb00010, 0x25cd0001,
+0x27bd0018, 0x3e00008, 0xa78d002a, 0x7c9c2,
+0x2738ff00, 0x1878c2, 0x31f0ffff, 0x3c040800,
+0x24845ad8, 0x2002821, 0x24060001, 0xe0005b5,
+0x24070001, 0x978d0026, 0x260e0100, 0xe8400,
+0x25ac0001, 0x3c0b6000, 0xa78c0026, 0xad603d08,
+0x36040006, 0x3021, 0x3c076000, 0x8ce23d04,
+0x305f0006, 0x17e0fffd, 0x24c90001, 0x61b00,
+0x312600ff, 0x644025, 0x2cc50004, 0xace83d04,
+0x14a0fff6, 0x8fbf0014, 0x8fb00010, 0x3e00008,
+0x27bd0018, 0x751c2, 0x2549c800, 0x24060001,
+0x24070001, 0x3c040800, 0x24845a58, 0xe0005b5,
+0x3125ffff, 0x97870024, 0x8fbf0014, 0x8fb00010,
+0x24e60001, 0x27bd0018, 0x3e00008, 0xa7860024,
+0x3c066018, 0x3c090800, 0x252900fc, 0xacc9502c,
+0x8cc85000, 0x3c058000, 0x3c020002, 0x35070080,
+0xacc75000, 0x3c040800, 0x24841fe0, 0x3c030800,
+0x24631f98, 0xaca50008, 0xaca2000c, 0x3c010800,
+0xac2459a4, 0x3c010800, 0xac2359a8, 0x3e00008,
+0x24020001, 0xa03021, 0x3c1c0800, 0x279c59ac,
+0x3c0c0400, 0x3c0b0002, 0x8b3826, 0x8c4026,
+0x2ce20001, 0x7502b, 0x2d050001, 0xa4880,
+0x3c030800, 0x246359a4, 0x452025, 0x1231821,
+0x10800003, 0x1021, 0xac660000, 0x24020001,
+0x3e00008, 0x0, 0x3c1c0800, 0x279c59ac,
+0x3c0b0400, 0x3c0a0002, 0x8a3026, 0x8b3826,
+0x2cc20001, 0x6482b, 0x2ce50001, 0x94080,
+0x3c030800, 0x246359a4, 0x452025, 0x1031821,
+0x10800005, 0x1021, 0x3c0c0800, 0x258c1f98,
+0xac6c0000, 0x24020001, 0x3e00008, 0x0,
+0x3c090002, 0x3c080400, 0x883026, 0x893826,
+0x2cc30001, 0x802821, 0x2ce40001, 0x831025,
+0x1040000b, 0x3021, 0x3c1c0800, 0x279c59ac,
+0x3c0a8000, 0x8d4e0008, 0x24060001, 0x1ca6825,
+0xad4d0008, 0x8d4c000c, 0x1855825, 0xad4b000c,
+0x3e00008, 0xc01021, 0x3c1c0800, 0x279c59ac,
+0x3c058000, 0x8ca6000c, 0x42027, 0x24020001,
+0xc41824, 0x3e00008, 0xaca3000c, 0x3c020002,
+0x1082000b, 0x3c056000, 0x3c070400, 0x10870003,
+0x0, 0x3e00008, 0x0, 0x8ca908d0,
+0x240afffd, 0x12a4024, 0x3e00008, 0xaca808d0,
+0x8ca408d0, 0x2406fffe, 0x861824, 0x3e00008,
+0xaca308d0, 0x3c05601a, 0x34a60010, 0x8cc30080,
+0x27bdfff8, 0x8cc50084, 0xafa30000, 0x93a40000,
+0x24020010, 0x10820003, 0xafa50004, 0x3e00008,
+0x27bd0008, 0x93a70001, 0x14e00014, 0x97ac0002,
+0x97b80002, 0x3c0f8000, 0x330efffc, 0x1cf6821,
+0xada50000, 0xa3a00000, 0x3c066000, 0x8cc708d0,
+0x2408fffe, 0x3c04601a, 0xe82824, 0xacc508d0,
+0x8fa30004, 0x8fa20000, 0x34990010, 0x27bd0008,
+0xaf220080, 0x3e00008, 0xaf230084, 0x3c0b8000,
+0x318afffc, 0x14b4821, 0x8d280000, 0xa00080c,
+0xafa80004, 0x27bdffe8, 0xafbf0010, 0x3c1c0800,
+0x279c59ac, 0x3c058000, 0x8ca4000c, 0x8ca20004,
+0x3c030002, 0x442824, 0x10a0000a, 0xa31824,
+0x3c060400, 0x3c040002, 0x14600009, 0xa61024,
+0x1440000f, 0x3c040400, 0xd, 0x3c1c0800,
+0x279c59ac, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x3c020800, 0x8c4259a4, 0x40f809, 0x0,
+0x3c1c0800, 0x279c59ac, 0xa000835, 0x8fbf0010,
+0x3c020800, 0x8c4259a8, 0x40f809, 0x0,
+0xa00083b, 0x0, 0x3c088000, 0x8d0201b8,
+0x440fffe, 0x35090180, 0xad240000, 0x3c031000,
+0x24040040, 0xad250004, 0xa1240008, 0xa1260009,
+0xa527000a, 0x3e00008, 0xad0301b8, 0x3084ffff,
+0x803821, 0x30a5ffff, 0x2021, 0xa000845,
+0x24060080, 0x3087ffff, 0x8ca40000, 0x24060038,
+0xa000845, 0x2821, 0x8f830078, 0x8f860070,
+0x1066000b, 0x804021, 0x3c070800, 0x24e75b68,
+0x328c0, 0xa71021, 0x8c440000, 0x24630001,
+0x10880005, 0x3063000f, 0x5466fffa, 0x328c0,
+0x3e00008, 0x1021, 0x3c070800, 0x24e75b6c,
+0xa73021, 0x3e00008, 0x8cc20000, 0x3c039000,
+0x34620001, 0x822025, 0x3c038000, 0xac640020,
+0x8c650020, 0x4a0fffe, 0x0, 0x3e00008,
+0x0, 0x3c028000, 0x34430001, 0x832025,
+0x3e00008, 0xac440020, 0x27bdffe0, 0xafb10014,
+0x3091ffff, 0xafb00010, 0xafbf0018, 0x12200013,
+0xa08021, 0x8ca20000, 0x24040002, 0x24060200,
+0x1040000f, 0x402821, 0xe000725, 0x0,
+0x1021, 0xae000000, 0x2203821, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x402021, 0x2821,
+0x3021, 0xa000845, 0x27bd0020, 0x8ca20000,
+0x2203821, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x402021, 0x2821, 0x3021, 0xa000845,
+0x27bd0020, 0xa01021, 0x3087ffff, 0x8ca50004,
+0x8c440000, 0xa000845, 0x24060006, 0x8f83fd9c,
+0x27bdffe8, 0xafbf0014, 0xafb00010, 0x90670008,
+0x801021, 0x802821, 0x30e60040, 0x2021,
+0x10c00008, 0x8c500000, 0xe0000bd, 0x2002021,
+0x2002021, 0x8fbf0014, 0x8fb00010, 0xa000548,
+0x27bd0018, 0xe0008a4, 0x0, 0xe0000bd,
+0x2002021, 0x2002021, 0x8fbf0014, 0x8fb00010,
+0xa000548, 0x27bd0018, 0x27bdffe0, 0xafb00010,
+0x8f90fd9c, 0xafbf001c, 0xafb20018, 0xafb10014,
+0x92060001, 0x808821, 0xe000872, 0x30d20004,
+0x92040005, 0x1129c2, 0xa6050000, 0x34830040,
+0xa2030005, 0xe00087c, 0x2202021, 0xe00054a,
+0x2202021, 0x24020001, 0xae02000c, 0x2202821,
+0xa6020010, 0x24040002, 0xa6020012, 0x24060200,
+0xa6020014, 0xe000725, 0xa6020016, 0x1640000f,
+0x8fbf001c, 0x978c0074, 0x3c0b0800, 0x8d6b0078,
+0x2588ffff, 0x3109ffff, 0x256a0001, 0x12a382b,
+0x10e00006, 0xa7880074, 0x3c0f6006, 0x240e0016,
+0x35ed0010, 0xadae0050, 0x8fbf001c, 0x8fb20018,
0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
-0x3c058000, 0x8ca40178, 0x480fffe, 0x24070007,
-0x3c061000, 0xacb10140, 0x2202021, 0xa0a70144,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0xaca60178,
-0xa000769, 0x27bd0020, 0x27bdffe0, 0xafb00010,
-0xafbf0018, 0xafb10014, 0x3c108000, 0x8e110020,
-0x0, 0xe0004a7, 0xae040020, 0xae110020,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0020, 0x3084ffff, 0x3c068000, 0x8cc201b8,
-0x440fffe, 0x3c084035, 0x883825, 0x3c031000,
-0xacc50180, 0xacc00184, 0xacc70188, 0x3e00008,
-0xacc301b8, 0x3084ffff, 0x3c068000, 0x8cc201b8,
-0x440fffe, 0x3c084036, 0x883825, 0x3c031000,
-0xacc50180, 0xacc00184, 0xacc70188, 0x3e00008,
-0xacc301b8, 0x27bdffd0, 0xafb50024, 0x3095ffff,
-0xafb60028, 0xafb40020, 0xafbf002c, 0xafb3001c,
-0xafb20018, 0xafb10014, 0xafb00010, 0x30b6ffff,
-0x12a00027, 0xa021, 0x8f92003c, 0x8e430000,
-0x3c068000, 0x24020040, 0x33e02, 0x32c02,
-0x30e4007f, 0x669824, 0x1482001d, 0x30a500ff,
-0x8f83004c, 0x2c68000a, 0x51000010, 0x8f860030,
-0x35880, 0x3c0c0800, 0x258c5458, 0x16c5021,
-0x8d490000, 0x1200008, 0x0, 0x2d44821,
-0x3125ffff, 0xe0006e4, 0x24040084, 0x16600002,
-0x8f92003c, 0xaf80004c, 0x8f860030, 0x26580020,
-0x268f0001, 0x3009021, 0x31f4ffff, 0x14c00004,
-0xaf98003c, 0x295282b, 0x14a0ffdc, 0x0,
-0x2801021, 0x8fbf002c, 0x8fb60028, 0x8fb50024,
-0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0030, 0x24070034,
-0x14a70146, 0x0, 0x9247000e, 0x8f99fdfc,
-0x8f90fdf8, 0x24181600, 0xa3270019, 0x924a000d,
-0x3c088000, 0x3c07800c, 0xa32a0018, 0x96440012,
-0x3c0f6000, 0x3c117fff, 0xa604005c, 0x965f0010,
-0x3622ffff, 0x240a0005, 0x33e5ffff, 0xae050054,
-0x8e46001c, 0xad180028, 0x8ce90000, 0x8dee4448,
-0x1266826, 0x1cd3021, 0xae060038, 0x8e030038,
-0x24cb0001, 0x3c0e7f00, 0xae03003c, 0x8e0c003c,
-0xaf2c0004, 0xae0b0020, 0x8e130020, 0xae13001c,
-0xa320001b, 0xae02002c, 0xa32a0012, 0x8e440014,
-0x24130050, 0xae040034, 0x8e1f0034, 0xaf3f0014,
-0x8e450018, 0xae050048, 0x9258000c, 0xa218004e,
-0x920f0008, 0x35e90020, 0xa2090008, 0x8e0d0018,
-0x1ae1824, 0x346c4000, 0xae0c0018, 0x920b0000,
-0x317200ff, 0x125302ad, 0x2413ff80, 0x3c040800,
-0x24845848, 0xe00074e, 0x0, 0x24030004,
-0x24080001, 0x3c050800, 0x8ca55848, 0x3c048000,
-0xa2030025, 0xa2080005, 0x8c900178, 0x600fffe,
-0x8f92003c, 0x240e0002, 0x3c0d1000, 0xac850140,
-0xa08e0144, 0xac8d0178, 0xa00080b, 0xaf80004c,
-0x2cad0037, 0x11a0ff99, 0x8f860030, 0x58080,
-0x3c110800, 0x26315480, 0x2117821, 0x8dee0000,
-0x1c00008, 0x0, 0x24100004, 0x14b0008e,
-0x3c078000, 0x3c0c0800, 0x8d8c5848, 0x8f86fdf8,
-0xacec0020, 0x8e4b0008, 0x8f98fdfc, 0x24090050,
-0xaccb0030, 0x8e430008, 0xacc30050, 0x8e42000c,
-0xacc20034, 0x8e4a0010, 0xacca0038, 0x8e440010,
-0xacc40054, 0x8e5f0014, 0xacdf003c, 0x8e590018,
-0xaf190004, 0x8e4f001c, 0xaccf0020, 0x90d10000,
-0x322500ff, 0x10a9027d, 0x0, 0x8cd10034,
-0x8ccf0030, 0x22f3023, 0x4c000f3, 0x2404008c,
-0x126000f0, 0x24020003, 0xa00080b, 0xaf82004c,
-0x24180005, 0x14b80068, 0x3c0b8000, 0x3c0c0800,
-0x8d8c5848, 0x8f86fdf8, 0xad6c0020, 0x8e430004,
-0x8f9ffdfc, 0x24072000, 0xacc3001c, 0x92420008,
-0x24120008, 0xa3e20019, 0x8f8a003c, 0x91440009,
-0xa3e40018, 0x8f85003c, 0x90b9000a, 0x332400ff,
-0x10920010, 0x28880009, 0x150000bc, 0x240d0002,
-0x24090020, 0x1089000b, 0x34078000, 0x28910021,
-0x16200008, 0x24074000, 0x240f0040, 0x108f0005,
-0x3c070001, 0x24180080, 0x10980002, 0x3c070002,
-0x24074000, 0x8cc40018, 0x3c0aff00, 0x8af824,
-0x3e7c825, 0xacd90018, 0x90b2000b, 0xa0d20027,
-0x8f83003c, 0x9465000c, 0x10a00231, 0x0,
-0x9467000c, 0x3c1f8000, 0xa4c7005c, 0x9062000e,
-0x2403ffbf, 0x24070004, 0xa0c20008, 0x8f8a003c,
-0x9144000f, 0xa0c40009, 0x8f88003c, 0x8d120010,
-0x8ff90074, 0x2592823, 0xacc50058, 0x8d180014,
-0xacd8002c, 0x950f0018, 0x31f1ffff, 0xacd10040,
-0x9509001a, 0x3130ffff, 0xacd00044, 0x8d0e001c,
-0xacce0048, 0x950d0002, 0xa4cd0078, 0x910c000e,
-0xa0cc0008, 0x90cb0008, 0x1631024, 0x126001d7,
-0xa0c20008, 0x8f92003c, 0xa00080b, 0xaf87004c,
-0x24060006, 0x14a60014, 0x3c0e8000, 0x3c100800,
-0x8e105848, 0x8f8cfdf4, 0xadd00020, 0x8e4d0018,
-0x8f86fdf8, 0x8f8bfdfc, 0xad8d0000, 0x8cc80038,
-0x24040005, 0xad880004, 0x8cc3003c, 0x12600081,
-0xad630000, 0xa00080b, 0xaf84004c, 0x24090007,
-0x10a9004b, 0x24040006, 0x3c050800, 0x24a55848,
-0xe000721, 0x24040081, 0x8f92003c, 0x13102b,
-0xa00080b, 0xaf82004c, 0x241f0023, 0x14bffff6,
-0x3c0c8000, 0x3c030800, 0x8c635848, 0x8f8bfdfc,
-0xad830020, 0x8f91fdf8, 0x8e460004, 0x25640020,
-0x26450014, 0xae260028, 0x24060003, 0xe000e38,
-0x25700030, 0x8f87003c, 0x2002021, 0x24060003,
-0xe000e38, 0x24e50008, 0x3c040800, 0x24845848,
-0xe00074e, 0x0, 0x92220000, 0x24040050,
-0x304a00ff, 0x5544ffe1, 0x8f92003c, 0xe000e23,
-0x0, 0xa000910, 0x8f92003c, 0x24080033,
-0x14a80032, 0x3c028000, 0x3c110800, 0x8e315848,
-0x8f89fdfc, 0xac510020, 0x8e4a0008, 0x240f0028,
-0x8f8dfdf8, 0xad2a0030, 0x8e44000c, 0x24060009,
-0xad240034, 0x8e5f0010, 0xad3f0038, 0x8e590014,
-0xad390020, 0x8e450018, 0xad250024, 0x8e58001c,
-0xad380028, 0xa12f0011, 0x8e4e0004, 0x12600031,
-0xadae0028, 0x8f92003c, 0xa00080b, 0xaf86004c,
-0x24110022, 0x14b1ffb8, 0x0, 0x24040007,
-0x3c180800, 0x8f185848, 0x3c0f8000, 0xadf80020,
-0x5660feb1, 0xaf84004c, 0x3c040800, 0x24845848,
-0xe00074e, 0x24130050, 0x8f99fdf8, 0x93320000,
-0x324500ff, 0x10b3016c, 0x0, 0x8f92003c,
-0x2021, 0xa00080b, 0xaf84004c, 0x3c050800,
-0x24a55848, 0xe0006f1, 0x24040081, 0xa000910,
-0x8f92003c, 0x2d49821, 0x3265ffff, 0xe0006e4,
-0x24040084, 0xa00080b, 0x8f92003c, 0x108dff51,
-0x24070400, 0x28870003, 0x10e001aa, 0x24100004,
-0x240e0001, 0x548eff4b, 0x24074000, 0xa0008c6,
-0x24070100, 0x3c050800, 0x24a55848, 0xe000740,
-0x24040082, 0x8f92003c, 0x3021, 0xa00080b,
-0xaf86004c, 0x3c040800, 0x24845848, 0x8cc20038,
-0xe00074e, 0x8cc3003c, 0x8f92003c, 0xa000966,
-0x2021, 0x24040082, 0x3c050800, 0x24a55848,
-0xe000740, 0x0, 0x8f92003c, 0x1021,
-0xa00080b, 0xaf82004c, 0x8e500004, 0x8f91fdf8,
-0x3c0a8000, 0xad500020, 0x92220005, 0x2002821,
-0x30460002, 0x14c00187, 0x2404008a, 0x8f92fdfc,
-0x2002821, 0x2404008d, 0x924b001b, 0x31630020,
-0x14600180, 0x0, 0x922d0009, 0x240c0012,
-0x31a800ff, 0x110c017b, 0x24040081, 0xe000712,
-0x2002021, 0x9245001b, 0x240e0004, 0x2002021,
-0x34a90042, 0xa249001b, 0xe00071c, 0xa22e0025,
-0x3c048000, 0x8c910178, 0x620fffe, 0x24180002,
-0xac900140, 0xa0980144, 0x8f92003c, 0x3c0f1000,
-0xac8f0178, 0xa000911, 0x13102b, 0x8e500004,
-0x8f91fdf8, 0x3c1f8000, 0xaff00020, 0x92390005,
-0x2002821, 0x33270002, 0x14e0001a, 0x2404008a,
-0x92260009, 0x24120012, 0x30c400ff, 0x10920111,
-0x0, 0x92230009, 0x240a0004, 0x306200ff,
-0x104a010c, 0x0, 0xe000712, 0x2002021,
-0x8f88fdfc, 0x240cfffe, 0x2002021, 0x910e001b,
-0x35cd0020, 0xa10d001b, 0xa2320009, 0x922b0005,
-0x16c9024, 0xe00071c, 0xa2320005, 0x2002821,
-0x2021, 0xe0007d6, 0x0, 0xa000910,
-0x8f92003c, 0x8e510004, 0x3c028000, 0x3c100800,
-0x26105848, 0xac510020, 0x3c010800, 0xac315848,
-0x92460003, 0x30c40004, 0x10800169, 0x8f84fdf8,
-0x24020006, 0xa0820009, 0x924d001b, 0x2408ffc0,
-0x31ac003f, 0x1885825, 0xa08b0008, 0x92430003,
-0x306a0001, 0x15400160, 0x0, 0x8e420008,
-0xae020008, 0x3c020800, 0x8c425850, 0x1040015f,
-0x8f8efdfc, 0x281c2, 0x8f85fdf8, 0xa5d0000c,
-0x8e5f000c, 0x240f0001, 0x24090014, 0xaddf002c,
-0x8e590010, 0xadd9001c, 0x96470016, 0xa5c7003c,
-0x96580014, 0xa5d8003e, 0xacaf000c, 0xa4af0010,
-0xa4af0012, 0xa4af0014, 0xa4af0016, 0x12600163,
-0xa1c90011, 0x92440003, 0x30920002, 0x2e530001,
-0x8f92003c, 0x26620008, 0xa00080b, 0xaf82004c,
-0x8e460004, 0x3c058000, 0x3c048008, 0xaca60020,
-0x8e470008, 0x90890000, 0x24110050, 0x312200ff,
-0x105100bc, 0x24050088, 0x3c048000, 0x8c8f01b8,
-0x5e0fffe, 0x13802b, 0x3c184009, 0xb81025,
-0xaf90004c, 0x3c101000, 0xac860180, 0xac870184,
-0xac820188, 0xac9001b8, 0xa00080c, 0x8f860030,
-0x8e450004, 0x3c068000, 0x3c098008, 0xacc50020,
-0x913f0000, 0x24040050, 0x33f900ff, 0x132400b4,
-0x24060088, 0x3c048000, 0x8c8a01b8, 0x540fffe,
-0x3c0e400e, 0xce6825, 0x3c081000, 0xac850180,
-0xac800184, 0xac8d0188, 0xac8801b8, 0x912b0000,
-0x240cff80, 0x24040004, 0x16c1825, 0x24060030,
-0xe000682, 0xa1230000, 0xa000910, 0x8f92003c,
-0x8e500004, 0x8f91fdfc, 0x3c0f8000, 0xadf00020,
-0x9225001b, 0x30a90010, 0x1120007c, 0x24030081,
-0x3c048000, 0x8c8701b8, 0x4e0fffe, 0x3c1f401f,
-0xac900180, 0x7f1025, 0x13c82b, 0x3c101000,
-0xac800184, 0xaf99004c, 0xac820188, 0xac9001b8,
-0xa00080c, 0x8f860030, 0x8e44001c, 0xe0006fd,
-0x0, 0x104000fc, 0x403821, 0x8f92003c,
-0x24060089, 0x3c058000, 0x8cae01b8, 0x5c0fffe,
-0x0, 0xaca70180, 0x8e50001c, 0x3c114001,
-0x13782b, 0xd13825, 0x3c131000, 0xacb00184,
-0xaf8f004c, 0xaca70188, 0xacb301b8, 0xa00080c,
-0x8f860030, 0x96590002, 0x3c100800, 0x26105848,
-0x33380004, 0x130000a7, 0x3c046000, 0x8e5f001c,
-0x3c068000, 0xacdf0020, 0x3c010800, 0xac3f5848,
-0x964f0002, 0x31e70001, 0x14e000e7, 0x0,
-0x8e420004, 0xae020008, 0x3c100800, 0x8e105850,
-0x120000dd, 0x3c068000, 0x8f85fdf8, 0x24100001,
-0x8cbf0018, 0x8f91fdfc, 0x8f89fdf4, 0x3e6c825,
-0xacb90018, 0xa0a00005, 0xacb0000c, 0x3c180800,
-0x8f185850, 0x8f87003c, 0xa4b00010, 0x1879c2,
-0xa4b00012, 0xa4b00014, 0xa4b00016, 0xa62f000c,
-0x8cee0008, 0x8f8d003c, 0x8f8c003c, 0xae2e002c,
-0x8da8000c, 0x24070002, 0xae28001c, 0x918b0010,
-0xa22b0011, 0x8f83003c, 0x906a0011, 0xa12a0008,
-0x8f82003c, 0x90440012, 0xa0a4004e, 0x8f92003c,
-0x92460013, 0xa2260012, 0x8f92003c, 0x965f0014,
-0xa63f003c, 0x96590016, 0xa639003e, 0x8e580018,
-0xae380014, 0x5660fd4c, 0xaf87004c, 0x3c050800,
-0x24a55848, 0xe000721, 0x2021, 0x8f92003c,
-0x3821, 0xa00080b, 0xaf87004c, 0x3c050800,
-0x24a55848, 0xe000740, 0x24040082, 0x8f92003c,
-0xa0008f3, 0x3821, 0xe000e23, 0x0,
-0x8f92003c, 0xa000966, 0x2021, 0xe000712,
-0x2002021, 0x9232001b, 0x2002021, 0x36580010,
-0xe00071c, 0xa238001b, 0x8f92003c, 0xa000a59,
-0x1821, 0xe0007d6, 0x24040081, 0xa000910,
-0x8f92003c, 0x9243000c, 0x306a0001, 0x11400003,
-0x0, 0x964b000e, 0xa48b002c, 0x9248000c,
-0x310c0002, 0x1180ff3c, 0x2821, 0x964e0012,
-0x8e4d0014, 0xa48e001a, 0xa000a27, 0xac8d001c,
-0x8f83005c, 0x8f870054, 0x1067ff4a, 0x3021,
-0x3c080800, 0x250857cc, 0x320c0, 0x883021,
-0x8cd10000, 0x122500c8, 0x24620001, 0x3043000f,
-0x1467fffa, 0x320c0, 0xa000a3e, 0x3021,
-0x3c050800, 0x24a55848, 0xe000740, 0x2404008b,
-0x8f92003c, 0xa0008f3, 0x13382b, 0x3c0c0800,
-0x8d8c5848, 0x24d9fffe, 0x25910100, 0x322b007f,
-0x1679021, 0x2331024, 0xad020028, 0xae4600d0,
-0xae4000d4, 0xa00085c, 0xae59001c, 0xacc00054,
-0x3c090800, 0x8d295848, 0x3c05800c, 0x34a80100,
-0xace90028, 0x8e500014, 0xad1000d0, 0x8e4e0014,
-0xad0e00d4, 0x8e4d0010, 0x25a7fffe, 0xa000898,
-0xad07001c, 0x5490fda3, 0x24074000, 0xa0008c6,
-0x24071000, 0xe0007ca, 0x0, 0xa000910,
-0x8f92003c, 0x8c83442c, 0x3c05dead, 0x34b2beef,
-0x3c010800, 0xac205848, 0x1072004f, 0x0,
-0x3c046c62, 0x34827970, 0x14620008, 0x24040002,
-0x978a0058, 0x97830050, 0x2002821, 0x143482b,
-0x11200019, 0x24040092, 0x24040002, 0xe0005f2,
-0x24050200, 0x3c0b8000, 0xad620020, 0x3c010800,
-0xac225848, 0x1040000d, 0x8f8e003c, 0x240c0028,
-0x24040003, 0x91cd0010, 0x31a800ff, 0x550c0001,
-0x24040001, 0xe00004a, 0x0, 0x10400004,
-0x24040083, 0xa000a89, 0x8f92003c, 0x24040083,
-0x3c050800, 0x24a55848, 0xe000721, 0x0,
-0x8f92003c, 0x13382b, 0xa00080b, 0xaf87004c,
-0xa0009f2, 0x24020012, 0x8e440008, 0xe0006fd,
-0x0, 0xa0009fe, 0xae020008, 0x3c050800,
-0x24a55848, 0xe0006f1, 0x24040087, 0x8f92003c,
-0xa000a1b, 0x13102b, 0x24040004, 0xe0005f2,
-0x24050030, 0x14400017, 0x403821, 0x8f92003c,
-0xa000a6e, 0x24060083, 0x3c050800, 0x24a55848,
-0xa000b53, 0x24040087, 0x8e440004, 0xe0006fd,
-0x0, 0xa000a8f, 0xae020008, 0x3c050800,
-0x24a55848, 0xe000740, 0x24040082, 0x8f92003c,
-0xa000a1b, 0x1021, 0x8c83442c, 0xa000b32,
-0x3c046c62, 0x8f92003c, 0x3c088008, 0x3c0c8000,
-0x240b0050, 0x240a0001, 0xad820020, 0xa10b0000,
-0xa10a0001, 0x92490004, 0xa1090018, 0x92440005,
-0xa1040019, 0x92430006, 0x3c040800, 0x248457cc,
-0xa103001a, 0x92420007, 0x3c030800, 0x246357c8,
-0xa102001b, 0x92450008, 0xa105001c, 0x92460009,
-0xa106001d, 0x925f000a, 0xa11f001e, 0x9259000b,
-0xa119001f, 0x9258000c, 0xa1180020, 0x9251000d,
-0xa1110021, 0x9250000e, 0xa1100022, 0x924f000f,
-0xa10f0023, 0x924e0010, 0xa10e0024, 0x924d0011,
-0xa10d0025, 0x964c0014, 0xa50c0028, 0x964b0016,
-0x8f8a0054, 0x8f98005c, 0xa50b002a, 0x96490018,
-0xa10c0, 0x25450001, 0xa509002c, 0x8e46001c,
-0x44c821, 0x43f821, 0x30a5000f, 0xafe60000,
-0xaf270000, 0x10b80003, 0xaf850054, 0xa000a6e,
-0x3021, 0x24ad0001, 0x31a8000f, 0x3021,
-0xa000a6e, 0xaf88005c, 0x3c070800, 0x24e757c8,
-0x879021, 0xacc00000, 0x3021, 0xa000a3e,
-0xae400000, 0x3c048201, 0x3c036000, 0x34820e02,
-0xac603d68, 0xaf80007c, 0x3e00008, 0xac623d6c,
-0x27bdffe8, 0xafb00010, 0x3090ffff, 0x101842,
-0x2c620041, 0xafbf0014, 0x14400002, 0x24040080,
-0x24030040, 0x3c010800, 0xac300060, 0x3c010800,
-0xac230064, 0xe000e2c, 0x602821, 0x244802bf,
-0x2409ff80, 0x1092824, 0x103980, 0x103040,
-0x8fbf0014, 0x8fb00010, 0xa72021, 0x861821,
-0xaf830064, 0x3c010800, 0xac250058, 0x3c010800,
-0xac24005c, 0x3e00008, 0x27bd0018, 0x308300ff,
-0x30c6ffff, 0x30e400ff, 0x3c088000, 0x8d0201b8,
-0x440fffe, 0x35400, 0x1443825, 0x3c096000,
-0xe92025, 0x3c031000, 0xad050180, 0xad060184,
-0xad040188, 0x3e00008, 0xad0301b8, 0x8f86003c,
-0x3c096012, 0x35270010, 0x8ccb0004, 0x3c0c600e,
-0x35850010, 0x316a0006, 0x2d480001, 0xace800c4,
-0x8cc40004, 0xaca43180, 0x8cc20008, 0x94c30002,
-0xaca23184, 0x3e00008, 0xa7830074, 0x8f85003c,
-0x8f87ff50, 0x8f86ff58, 0x8cae0004, 0x3c0f6012,
-0x35e80010, 0xacee0068, 0x8cad0008, 0xaced006c,
-0x8cac0010, 0xaccc004c, 0x8cab000c, 0xaccb0048,
-0x94ca0054, 0x3c020800, 0x8c420044, 0x25490001,
-0xa4c90054, 0x94c40054, 0x3083ffff, 0x10620017,
-0x0, 0x3c020800, 0x8c420040, 0xa4c20052,
+0x27bdffe0, 0xafb10014, 0xafbf0018, 0xafb00010,
+0x10800004, 0xa08821, 0x24020080, 0x10820007,
+0x0, 0xd, 0x8fbf0018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0020, 0xe000872,
+0xa02021, 0x8f86fd9c, 0x2202021, 0x90c50005,
+0xe00087c, 0x30b000ff, 0x2403003e, 0x1603fff1,
+0x3c068000, 0x8cc40178, 0x480fffe, 0x34c80140,
+0x24090007, 0x3c071000, 0xad110000, 0x2202021,
+0xa1090004, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0xacc70178, 0xa0008c5, 0x27bd0020, 0x27bdffe0,
+0xafb00010, 0xafbf0018, 0xafb10014, 0x3c108000,
+0x8e110020, 0x0, 0xe00054a, 0xae040020,
+0xae110020, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+0x3e00008, 0x27bd0020, 0x3084ffff, 0x803821,
+0x24060035, 0xa02021, 0xa000845, 0x2821,
+0x3084ffff, 0x803821, 0x24060036, 0xa02021,
+0xa000845, 0x2821, 0x27bdffd0, 0xafb50024,
+0x3095ffff, 0xafb60028, 0xafb40020, 0xafbf002c,
+0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010,
+0x30b6ffff, 0x12a00027, 0xa021, 0x8f920058,
+0x8e430000, 0x3c068000, 0x24020040, 0x33e02,
+0x32c02, 0x30e4007f, 0x669824, 0x1482001d,
+0x30a500ff, 0x8f830068, 0x2c68000a, 0x11000010,
+0x8f8d0044, 0x35880, 0x3c0c0800, 0x258c57b8,
+0x16c5021, 0x8d490000, 0x1200008, 0x0,
+0x2d43021, 0x30c5ffff, 0xe000852, 0x24040084,
+0x16600002, 0x8f920058, 0xaf800068, 0x8f8d0044,
+0x26590020, 0x26980001, 0x3209021, 0x3314ffff,
+0x15a00004, 0xaf990058, 0x295202b, 0x1480ffdc,
+0x0, 0x2801021, 0x8fbf002c, 0x8fb60028,
+0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030,
+0x24070034, 0x14a70149, 0x0, 0x9247000e,
+0x8f9ffda0, 0x8f90fd9c, 0x24181600, 0xa3e70019,
+0x9242000d, 0x3c088000, 0x3c07800c, 0xa3e20018,
+0x964a0012, 0x3c0d6000, 0x3c117fff, 0xa60a005c,
+0x96440010, 0x3623ffff, 0x24020005, 0x3099ffff,
+0xae190054, 0x8e46001c, 0xad180028, 0x8cef0000,
+0x8dae4448, 0x1e64826, 0x1c93021, 0xae060038,
+0x8e050038, 0x24cb0001, 0x3c0e7f00, 0xae05003c,
+0x8e0c003c, 0xafec0004, 0xae0b0020, 0x8e130020,
+0xae13001c, 0xa3e0001b, 0xae03002c, 0xa3e20012,
+0x8e4a0014, 0x24130050, 0xae0a0034, 0x8e040034,
+0xafe40014, 0x8e590018, 0xae190048, 0x9258000c,
+0xa218004e, 0x920d0008, 0x35af0020, 0xa20f0008,
+0x8e090018, 0x12e2824, 0x34ac4000, 0xae0c0018,
+0x920b0000, 0x317200ff, 0x1253027f, 0x2403ff80,
+0x3c040800, 0x24845be8, 0xe0008aa, 0x0,
+0x3c110800, 0x8e315be8, 0xe000872, 0x2202021,
+0x24050004, 0x24080001, 0xa2050025, 0x2202021,
+0xe00087c, 0xa2080005, 0x3c058000, 0x8cb00178,
+0x600fffe, 0x8f920058, 0x34ae0140, 0x240f0002,
+0x3c091000, 0xadd10000, 0xa1cf0004, 0xaca90178,
+0xa000962, 0xaf800068, 0x2cad0037, 0x51a0ff94,
+0x8f8d0044, 0x58080, 0x3c110800, 0x263157e0,
+0x2117821, 0x8dee0000, 0x1c00008, 0x0,
+0x24110004, 0x14b1008c, 0x3c078000, 0x3c080800,
+0x8d085be8, 0x8f86fd9c, 0xace80020, 0x8e450008,
+0x8f99fda0, 0x240d0050, 0xacc50030, 0x8e4c0008,
+0xaccc0050, 0x8e4b000c, 0xaccb0034, 0x8e430010,
+0xacc30038, 0x8e4a0010, 0xacca0054, 0x8e420014,
+0xacc2003c, 0x8e5f0018, 0xaf3f0004, 0x8e50001c,
+0xacd00020, 0x90c40000, 0x309800ff, 0x130d024a,
+0x0, 0x8cc40034, 0x8cd00030, 0x903023,
+0x4c000f1, 0x2404008c, 0x126000ee, 0x24020003,
+0xa000962, 0xaf820068, 0x24190005, 0x14b90066,
+0x3c058000, 0x3c080800, 0x8d085be8, 0x8f86fd9c,
+0xaca80020, 0x8e4c0004, 0x8f8afda0, 0x24072000,
+0xaccc001c, 0x924b0008, 0x24120008, 0xa14b0019,
+0x8f820058, 0x90430009, 0xa1430018, 0x8f850058,
+0x90bf000a, 0x33e400ff, 0x10920010, 0x28890009,
+0x152000ba, 0x240e0002, 0x240d0020, 0x108d000b,
+0x34078000, 0x28980021, 0x17000008, 0x24074000,
+0x24100040, 0x10900005, 0x3c070001, 0x24190080,
+0x10990002, 0x3c070002, 0x24074000, 0x8cc20018,
+0x3c03ff00, 0x435024, 0x147f825, 0xacdf0018,
+0x90b2000b, 0xa0d20027, 0x8f830058, 0x9464000c,
+0x108001fe, 0x0, 0x9467000c, 0x3c1f8000,
+0x2405ffbf, 0xa4c7005c, 0x9063000e, 0x24070004,
+0xa0c30008, 0x8f820058, 0x904a000f, 0xa0ca0009,
+0x8f890058, 0x8d320010, 0x8fe40074, 0x244c823,
+0xacd90058, 0x8d300014, 0xacd0002c, 0x95380018,
+0x330dffff, 0xaccd0040, 0x9531001a, 0x322fffff,
+0xaccf0044, 0x8d2e001c, 0xacce0048, 0x9128000e,
+0xa0c80008, 0x90cc0008, 0x1855824, 0x126001b6,
+0xa0cb0008, 0x8f920058, 0xa000962, 0xaf870068,
+0x24060006, 0x14a60014, 0x3c0e8000, 0x3c0f0800,
+0x8def5be8, 0x8f85fd98, 0xadcf0020, 0x8e490018,
+0x8f86fd9c, 0x8f8bfda0, 0xaca90000, 0x8cc80038,
+0x24040005, 0xaca80004, 0x8ccc003c, 0x12600081,
+0xad6c0000, 0xa000962, 0xaf840068, 0x24110007,
+0x10b1004b, 0x24040006, 0x3c050800, 0x24a55be8,
+0xe000881, 0x24040081, 0x8f920058, 0x13102b,
+0xa000962, 0xaf820068, 0x241f0023, 0x14bffff6,
+0x3c0c8000, 0x3c050800, 0x8ca55be8, 0x8f8bfda0,
+0xad850020, 0x8f91fd9c, 0x8e460004, 0x25640020,
+0x26450014, 0xae260028, 0x24060003, 0xe000f81,
+0x25700030, 0x8f870058, 0x2002021, 0x24060003,
+0xe000f81, 0x24e50008, 0x3c040800, 0x24845be8,
+0xe0008aa, 0x0, 0x92230000, 0x240a0050,
+0x306200ff, 0x544affe1, 0x8f920058, 0xe000f6c,
+0x0, 0xa000a6a, 0x8f920058, 0x24080033,
+0x14a80032, 0x3c038000, 0x3c110800, 0x8e315be8,
+0x8f8ffda0, 0xac710020, 0x8e420008, 0x240d0028,
+0x8f89fd9c, 0xade20030, 0x8e4a000c, 0x24060009,
+0xadea0034, 0x8e5f0010, 0xadff0038, 0x8e440014,
+0xade40020, 0x8e590018, 0xadf90024, 0x8e58001c,
+0xadf80028, 0xa1ed0011, 0x8e4e0004, 0x12600031,
+0xad2e0028, 0x8f920058, 0xa000962, 0xaf860068,
+0x240d0022, 0x14adffb8, 0x0, 0x24040007,
+0x3c100800, 0x8e105be8, 0x3c188000, 0xaf100020,
+0x5660feae, 0xaf840068, 0x3c040800, 0x24845be8,
+0xe0008aa, 0x24130050, 0x8f84fd9c, 0x90920000,
+0x325900ff, 0x1333014b, 0x0, 0x8f920058,
+0x2021, 0xa000962, 0xaf840068, 0x3c050800,
+0x24a55be8, 0xe000858, 0x24040081, 0xa000a6a,
+0x8f920058, 0x2d49821, 0x3265ffff, 0xe000852,
+0x24040084, 0xa000962, 0x8f920058, 0x108eff53,
+0x24070400, 0x28870003, 0x10e00179, 0x24110004,
+0x240f0001, 0x548fff4d, 0x24074000, 0xa000a22,
+0x24070100, 0x3c050800, 0x24a55be8, 0xe0008a4,
+0x24040082, 0x8f920058, 0x3021, 0xa000962,
+0xaf860068, 0x3c040800, 0x24845be8, 0x8cc20038,
+0xe0008aa, 0x8cc3003c, 0x8f920058, 0xa000ac0,
+0x2021, 0x24040082, 0x3c050800, 0x24a55be8,
+0xe0008a4, 0x0, 0x8f920058, 0x1021,
+0xa000962, 0xaf820068, 0x8e500004, 0x8f91fd9c,
+0x3c078000, 0xacf00020, 0x922c0005, 0x2002821,
+0x318b0002, 0x15600156, 0x2404008a, 0x8f92fda0,
+0x2404008d, 0x9245001b, 0x30a60020, 0x14c00150,
+0x2002821, 0x922e0009, 0x24080012, 0x31c900ff,
+0x1128014b, 0x24040081, 0xe000872, 0x2002021,
+0x9258001b, 0x240f0004, 0x2002021, 0x370d0042,
+0xa24d001b, 0xe00087c, 0xa22f0025, 0x3c058000,
+0x8ca40178, 0x480fffe, 0x34b90140, 0x241f0002,
+0xaf300000, 0xa33f0004, 0x8f920058, 0x3c101000,
+0xacb00178, 0xa000a6b, 0x13102b, 0x8e500004,
+0x8f91fd9c, 0x3c038000, 0xac700020, 0x922a0005,
+0x2002821, 0x31420002, 0x14400017, 0x2404008a,
+0x922c0009, 0x24120004, 0x2002821, 0x318b00ff,
+0x11720011, 0x24040081, 0xe000872, 0x2002021,
+0x8f89fda0, 0x24080012, 0x2405fffe, 0x912f001b,
+0x2002021, 0x35ee0020, 0xa12e001b, 0xa2280009,
+0x92260005, 0xc53824, 0xe00087c, 0xa2270005,
+0x2002821, 0x2021, 0xe000933, 0x0,
+0xa000a6a, 0x8f920058, 0x8e4c0004, 0x3c078000,
+0x3c100800, 0x26105be8, 0xacec0020, 0x3c010800,
+0xac2c5be8, 0x924b0003, 0x31710004, 0x1220013b,
+0x8f84fd9c, 0x24020006, 0xa0820009, 0x924f001b,
+0x240effc0, 0x31e9003f, 0x12e4025, 0xa0880008,
+0x92450003, 0x30a60001, 0x14c00132, 0x0,
+0x8e420008, 0xae020008, 0x3c020800, 0x8c425bf0,
+0x10400131, 0x8f90fda0, 0x219c2, 0x8f8dfd9c,
+0xa603000c, 0x8e4a000c, 0x24180001, 0x24040014,
+0xae0a002c, 0x8e420010, 0xae02001c, 0x965f0016,
+0xa61f003c, 0x96590014, 0xa619003e, 0xadb8000c,
+0xa5b80010, 0xa5b80012, 0xa5b80014, 0xa5b80016,
+0x12600144, 0xa2040011, 0x92510003, 0x32320002,
+0x2e530001, 0x8f920058, 0x26620008, 0xa000962,
+0xaf820068, 0x8e440004, 0x3c198000, 0x3c068008,
+0xaf240020, 0x8e450008, 0x90d80000, 0x240d0050,
+0x331100ff, 0x122d009c, 0x24070088, 0x24060009,
+0xe000845, 0x0, 0xa000a6a, 0x8f920058,
+0x8e500004, 0x3c098000, 0x3c118008, 0xad300020,
+0x92280000, 0x24050050, 0x310400ff, 0x10850110,
+0x24070088, 0x2002021, 0x2821, 0xe000845,
+0x2406000e, 0x922d0000, 0x2418ff80, 0x2002821,
+0x1b88025, 0x24040004, 0x24060030, 0xe000725,
+0xa2300000, 0xa000a6a, 0x8f920058, 0x8e500004,
+0x8f91fda0, 0x3c028000, 0xac500020, 0x923f001b,
+0x33f90010, 0x1320006c, 0x24070081, 0x2002021,
+0x2821, 0x2406001f, 0xe000845, 0x0,
+0xa000a6a, 0x8f920058, 0x8e44001c, 0xe00085d,
+0x0, 0x104000e3, 0x404821, 0x8f880058,
+0x24070089, 0x1202021, 0x8d05001c, 0x24060001,
+0xe000845, 0x0, 0xa000a6a, 0x8f920058,
+0x96490002, 0x3c100800, 0x26105be8, 0x31280004,
+0x11000097, 0x3c046000, 0x8e4e001c, 0x3c0f8000,
+0xadee0020, 0x3c010800, 0xac2e5be8, 0x96470002,
+0x30e40001, 0x148000e6, 0x0, 0x8e420004,
+0xae020008, 0x3c100800, 0x8e105bf0, 0x120000ec,
+0x3c0f8000, 0x8f92fd9c, 0x24100001, 0x8e4e0018,
+0x8f8dfda0, 0x8f9ffd98, 0x1cf4825, 0xae490018,
+0xa2400005, 0xae50000c, 0x3c080800, 0x8d085bf0,
+0x8f840058, 0xa6500010, 0x839c2, 0xa6500012,
+0xa6500014, 0xa6500016, 0xa5a7000c, 0x8c8c0008,
+0x8f8b0058, 0x8f8a0058, 0xadac002c, 0x8d63000c,
+0x24070002, 0xada3001c, 0x91460010, 0xa1a60011,
+0x8f820058, 0x90450011, 0xa3e50008, 0x8f990058,
+0x93380012, 0xa258004e, 0x8f910058, 0x922f0013,
+0xa1af0012, 0x8f920058, 0x964e0014, 0xa5ae003c,
+0x96490016, 0xa5a9003e, 0x8e480018, 0xada80014,
+0x5660fd6a, 0xaf870068, 0x3c050800, 0x24a55be8,
+0xe000881, 0x2021, 0x8f920058, 0x3821,
+0xa000962, 0xaf870068, 0x3c050800, 0x24a55be8,
+0xe0008a4, 0x24040082, 0x8f920058, 0xa000a4d,
+0x3821, 0xe000f6c, 0x0, 0x8f920058,
+0xa000ac0, 0x2021, 0xe000872, 0x2002021,
+0x9223001b, 0x2002021, 0x346a0010, 0xe00087c,
+0xa22a001b, 0x3821, 0x2002021, 0x2821,
+0xa000ba5, 0x2406001f, 0x9242000c, 0x305f0001,
+0x13e00003, 0x0, 0x964a000e, 0xa4ca002c,
+0x924b000c, 0x31630002, 0x50600006, 0x3821,
+0x8e470014, 0x964c0012, 0xacc7001c, 0xa4cc001a,
+0x3821, 0xa000b7f, 0x24060009, 0x3c050800,
+0x24a55be8, 0xe0008a4, 0x2404008b, 0x8f920058,
+0xa000a4d, 0x13382b, 0x3c0c0800, 0x8d8c5be8,
+0x24dffffe, 0x25930100, 0x326b007f, 0x1679021,
+0x2638824, 0xad110028, 0xae4600e0, 0xae4000e4,
+0xa0009b3, 0xae5f001c, 0xacc00054, 0x3c0d0800,
+0x8dad5be8, 0x3c18800c, 0x37090100, 0xaced0028,
+0x8e510014, 0xad3100e0, 0x8e4f0014, 0xad2f00e4,
+0x8e4e0010, 0x25c7fffe, 0xa0009f4, 0xad27001c,
+0x5491fdd6, 0x24074000, 0xa000a22, 0x24071000,
+0xe00092d, 0x0, 0xa000a6a, 0x8f920058,
+0x8c83442c, 0x3c12dead, 0x3651beef, 0x3c010800,
+0xac205be8, 0x10710062, 0x0, 0x3c196c62,
+0x37387970, 0x14780008, 0x24040002, 0x97850074,
+0x9782006c, 0x24040092, 0xa2f82b, 0x13e00019,
+0x2002821, 0x24040002, 0xe000695, 0x24050200,
+0x3c068000, 0xacc20020, 0x3c010800, 0xac225be8,
+0x1040000d, 0x8f8c0058, 0x240a0028, 0x24040003,
+0x918b0010, 0x316300ff, 0x546a0001, 0x24040001,
+0xe000081, 0x0, 0x10400004, 0x24040083,
+0xa000bc2, 0x8f920058, 0x24040083, 0x3c050800,
+0x24a55be8, 0xe000881, 0x0, 0x8f920058,
+0x13382b, 0xa000962, 0xaf870068, 0xa000b49,
+0x24020012, 0x8e440008, 0xe00085d, 0x0,
+0xa000b55, 0xae020008, 0x3c050800, 0x24a55be8,
+0xe000858, 0x24040087, 0x8f920058, 0xa000b72,
+0x13102b, 0x24040004, 0xe000695, 0x24050030,
+0x1440002a, 0x404821, 0x8f880058, 0x24070083,
+0x1202021, 0x8d05001c, 0xa000bb3, 0x24060001,
+0x8f830078, 0x8f860070, 0x1066feee, 0x3821,
+0x3c070800, 0x24e75b6c, 0x320c0, 0x872821,
+0x8cae0000, 0x11d0005d, 0x246f0001, 0x31e3000f,
+0x5466fffa, 0x320c0, 0xa000b8c, 0x3821,
+0x8e440004, 0xe00085d, 0x0, 0xa000bc8,
+0xae020008, 0x3c050800, 0x24a55be8, 0xe0008a4,
+0x24040082, 0x8f920058, 0xa000b72, 0x1021,
+0x3c050800, 0x24a55be8, 0xa000c7c, 0x24040087,
+0x8c83442c, 0xa000c5b, 0x3c196c62, 0x8f880058,
+0x3c078008, 0x3c0c8000, 0x240b0050, 0x240a0001,
+0xad820020, 0xa0eb0000, 0xa0ea0001, 0x91030004,
+0xa0e30018, 0x91040005, 0xa0e40019, 0x91060006,
+0x3c040800, 0x24845b6c, 0xa0e6001a, 0x91020007,
+0x3c060800, 0x24c65b68, 0xa0e2001b, 0x91050008,
+0xa0e5001c, 0x911f0009, 0xa0ff001d, 0x9119000a,
+0xa0f9001e, 0x9118000b, 0xa0f8001f, 0x9112000c,
+0xa0f20020, 0x9111000d, 0xa0f10021, 0x9110000e,
+0xa0f00022, 0x910f000f, 0xa0ef0023, 0x910e0010,
+0xa0ee0024, 0x910d0011, 0xa0ed0025, 0x950c0014,
+0xa4ec0028, 0x950b0016, 0x8f8a0070, 0x8f920078,
+0xa4eb002a, 0x95030018, 0xa10c0, 0x25450001,
+0xa4e3002c, 0x8d1f001c, 0x44c021, 0x46c821,
+0x30a5000f, 0xaf3f0000, 0xaf090000, 0x10b20006,
+0xaf850070, 0x3821, 0x8d05001c, 0x1202021,
+0xa000bb3, 0x24060001, 0x24ad0001, 0x31a7000f,
+0xaf870078, 0xa000cf9, 0x3821, 0x3c060800,
+0x24c65b68, 0x869021, 0x3821, 0xaca00000,
+0xa000b8c, 0xae400000, 0x3c048201, 0x3c036000,
+0x34820e02, 0xac603d68, 0xaf800098, 0x3e00008,
+0xac623d6c, 0x27bdffe8, 0xafb00010, 0x3090ffff,
+0x101842, 0x2c620041, 0xafbf0014, 0x14400002,
+0x24040080, 0x24030040, 0x3c010800, 0xac300060,
+0x3c010800, 0xac230064, 0xe000f75, 0x602821,
+0x244802bf, 0x2409ff80, 0x1092824, 0x103980,
+0x103040, 0x8fbf0014, 0x8fb00010, 0xa72021,
+0x861821, 0xaf830080, 0x3c010800, 0xac250058,
+0x3c010800, 0xac24005c, 0x3e00008, 0x27bd0018,
+0x308300ff, 0x30c6ffff, 0x30e400ff, 0x3c088000,
+0x8d0201b8, 0x440fffe, 0x35400, 0x1443825,
+0x3c096000, 0xe92025, 0x3c031000, 0xad050180,
+0xad060184, 0xad040188, 0x3e00008, 0xad0301b8,
+0x8f850058, 0x3c0a6012, 0x35480010, 0x8cac0004,
+0x3c0d600e, 0x35a60010, 0x318b0006, 0x2d690001,
+0xad0900c4, 0x8ca70004, 0xacc73180, 0x8ca20008,
+0x94a40002, 0xacc23184, 0x8ca3001c, 0x4600003,
+0xa7840090, 0x3e00008, 0x0, 0x8caf0018,
+0xaccf31d0, 0x8cae001c, 0x3e00008, 0xacce31d4,
+0x8f850058, 0x8f87ff28, 0x8f86ff30, 0x8cae0004,
+0x3c0f6012, 0x35e80010, 0xacee0078, 0x8cad0008,
+0xaced007c, 0x8cac0010, 0xaccc004c, 0x8cab000c,
+0xaccb0048, 0x94ca0054, 0x3c020800, 0x8c420044,
+0x25490001, 0xa4c90054, 0x94c40054, 0x3083ffff,
+0x10620017, 0x0, 0x3c020800, 0x8c420040,
+0xa4c20052, 0x8ca30018, 0xace30030, 0x8ca20014,
+0xace2002c, 0x8cb90018, 0xacf90038, 0x8cb80014,
+0x24050001, 0xacf80034, 0x8d0600bc, 0x50c50019,
+0x8d0200b4, 0x8d0200b8, 0xa4e20048, 0x94e40048,
+0xa4e4004a, 0x94e800ea, 0x3e00008, 0x3102ffff,
+0x3c020800, 0x8c420024, 0xa4c00054, 0xa4c20052,
0x8ca30018, 0xace30030, 0x8ca20014, 0xace2002c,
0x8cb90018, 0xacf90038, 0x8cb80014, 0x24050001,
-0xacf80034, 0x8d0600bc, 0x50c50019, 0x8d0200b4,
-0x8d0200b8, 0xa4e20048, 0x94e40048, 0xa4e4004a,
-0x94e800da, 0x3e00008, 0x3102ffff, 0x3c020800,
-0x8c420024, 0xa4c00054, 0xa4c20052, 0x8ca30018,
-0xace30030, 0x8ca20014, 0xace2002c, 0x8cb90018,
-0xacf90038, 0x8cb80014, 0x24050001, 0xacf80034,
-0x8d0600bc, 0x54c5ffeb, 0x8d0200b8, 0x8d0200b4,
-0xa4e20048, 0x94e40048, 0xa4e4004a, 0x94e800da,
-0x3e00008, 0x3102ffff, 0x8f86003c, 0x3c048000,
-0x8cc90008, 0x8cc80008, 0x929c0, 0x839c0,
-0xac870020, 0x90c30007, 0x30620004, 0x1040003a,
-0xaf850078, 0x90cb0007, 0x316a0008, 0x11400039,
-0x8f87ff54, 0x8ccd000c, 0x8cce0014, 0x1ae602b,
-0x11800032, 0x0, 0x8cc2000c, 0xace20070,
-0x8ccb0018, 0x8f85ff50, 0x8f88ff58, 0xaceb0074,
-0x8cca0010, 0x2402fff8, 0xacaa00c8, 0x8cc9000c,
-0xad090060, 0x8cc4001c, 0xaca400c0, 0x90e3007c,
-0x62c824, 0xa0f9007c, 0x90d80007, 0x330f0008,
-0x11e00004, 0x0, 0x90ed007c, 0x35ac0001,
-0xa0ec007c, 0x90cf0007, 0x31ee0001, 0x11c00009,
-0x0, 0x90e4007c, 0x24180002, 0x34820002,
-0xa0e2007c, 0x90a300ec, 0x307900ff, 0x13380013,
-0x24080034, 0x90c90007, 0x31260002, 0x10c00004,
-0x0, 0x90eb007c, 0x356a0004, 0xa0ea007c,
-0x90ed007d, 0x31ac003f, 0xa0ec007d, 0x94a700da,
-0x3e00008, 0x30e2ffff, 0x8f87ff54, 0xa000c68,
-0x8cc20014, 0xa000c69, 0xace00070, 0xa000c8a,
-0xaca800cc, 0x8f8c003c, 0x27bdffd8, 0xafb3001c,
-0xafb20018, 0xafb00010, 0xafbf0020, 0xafb10014,
-0x918f0015, 0x3c13600e, 0x36730010, 0x31eb000f,
-0xa38b0080, 0x8d8f0004, 0x8d8b0008, 0x959f0012,
-0x95990010, 0x9584001a, 0x9598001e, 0x958e001c,
-0x33edffff, 0x332affff, 0x3089ffff, 0x3308ffff,
-0x31c7ffff, 0x3c010800, 0xac2d0024, 0x3c010800,
-0xac290044, 0x3c010800, 0xac2a0040, 0xae683178,
-0xae67317c, 0x91850015, 0x95910016, 0x3c126012,
-0x36520010, 0x30a200ff, 0x3230ffff, 0xae623188,
-0xae5000b4, 0x91830014, 0x959f0018, 0x24060001,
-0x66c804, 0x33f8ffff, 0xae5900b8, 0xae5800bc,
-0x918e0014, 0xaf8f0068, 0x3c086006, 0x31cd00ff,
-0xae4d00c0, 0x918a0015, 0x9584000e, 0x3c07600a,
-0x314900ff, 0xaf8b006c, 0x3084ffff, 0xae4900c8,
-0x35110010, 0xe000bd1, 0x34f00410, 0x3c020800,
-0x8c420060, 0x3c030800, 0x8c630064, 0x3c060800,
-0x8cc60058, 0x3c050800, 0x8ca5005c, 0x8f840064,
-0x8fbf0020, 0xae23004c, 0xae65319c, 0xae030054,
-0xae4500dc, 0xae6231a0, 0xae6331a4, 0xae663198,
-0xae220048, 0x8fb3001c, 0xae020050, 0x8fb10014,
-0xae4200e0, 0xae4300e4, 0xae4600d8, 0x8fb00010,
-0x8fb20018, 0xa0004da, 0x27bd0028, 0x97850076,
-0x97830060, 0x27bdffe8, 0xafb00010, 0xa3102b,
-0xafbf0014, 0x24040005, 0x8f90003c, 0x10400055,
-0x24090002, 0xe0005f2, 0x8f850064, 0xaf820078,
-0x24040003, 0x1040004f, 0x24090002, 0x3c068000,
-0xe00004a, 0xacc20020, 0x24070001, 0x24082000,
-0x1040004d, 0x24040005, 0x978e0076, 0x8f8aff54,
-0x24090050, 0x25c50001, 0xa7850076, 0xa1490000,
-0x3c0d0800, 0x8dad0064, 0x24038000, 0x8f84ff50,
-0xd6600, 0xad4c0018, 0xa5400006, 0x954b000a,
-0x8f85ff58, 0x2402ff80, 0x1633024, 0xa546000a,
-0x915f000a, 0x4821, 0x3e2c825, 0xa159000a,
-0xa0a00008, 0xa140004c, 0xa08000c5, 0x96180002,
-0x97830074, 0x3c020004, 0xa49800da, 0x960f0002,
-0x2418ffbf, 0x25ee2401, 0xa48e00ae, 0x8e0d0004,
-0xacad0044, 0x8e0c0008, 0xacac0040, 0xa4a00050,
-0xa4a00054, 0x8e0b000c, 0x240c0030, 0xac8b0028,
-0x8e060010, 0xac860024, 0xa480003e, 0xa487004e,
-0xa4870050, 0xa483003c, 0xad420074, 0xac8800c8,
-0xaca80060, 0xa08700ec, 0x909f00c4, 0x33f9007f,
-0xa09900c4, 0x909000c4, 0x2187824, 0xa08f00c4,
-0x914e007c, 0x35cd0001, 0xa14d007c, 0x938b0080,
-0xad480070, 0xac8c00cc, 0xa08b00c6, 0x8f88006c,
-0x8f870068, 0xac8800b4, 0xac8700b8, 0xa5400078,
-0xa540007a, 0x8fbf0014, 0x8fb00010, 0x1201021,
-0x3e00008, 0x27bd0018, 0x8f850078, 0xe000682,
-0x8f860064, 0xa000d56, 0x24090002, 0x27bdffe0,
-0xafb00010, 0x8f90003c, 0xafb10014, 0xafbf0018,
-0x8e090004, 0xe0004a7, 0x921c0, 0x8e080004,
-0x8f84ff50, 0x8f82ff58, 0x839c0, 0x3c068000,
-0xacc70020, 0x948500da, 0x90430013, 0x1460001c,
-0x30b1ffff, 0x8f8cff54, 0x918b0008, 0x316a0040,
-0x1540000b, 0x0, 0x8e0d0004, 0x2203021,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x24040022,
-0x3821, 0xd29c0, 0xa000bf0, 0x27bd0020,
-0xe000061, 0x0, 0x8e0d0004, 0x2203021,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x24040022,
-0x3821, 0xd29c0, 0xa000bf0, 0x27bd0020,
-0xe000059, 0x0, 0x8e0d0004, 0x2203021,
-0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x24040022,
-0x3821, 0xd29c0, 0xa000bf0, 0x27bd0020,
-0x27bdffe0, 0xafb20018, 0x3092ffff, 0xafb00010,
-0xafbf001c, 0xafb10014, 0x1240001e, 0x8021,
-0x8f86003c, 0x8cc50000, 0x24030006, 0x53f02,
-0x51402, 0x30e40007, 0x14830016, 0x304500ff,
-0x2ca80006, 0x11000040, 0x55880, 0x3c0c0800,
-0x258c555c, 0x16c5021, 0x8d490000, 0x1200008,
-0x0, 0x8f8e007c, 0x240d0001, 0x11cd0050,
-0x24020002, 0xaf82007c, 0x26090001, 0x3130ffff,
-0x24c80020, 0x212202b, 0x1003021, 0x1480ffe5,
-0xaf88003c, 0x2001021, 0x8fbf001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020,
-0x93870062, 0x54e00034, 0x3021, 0xe000c9e,
-0x0, 0x8f86003c, 0xa000db6, 0x24020001,
-0x8f87007c, 0x24050002, 0x10e50031, 0x24040013,
-0x2821, 0x3021, 0x24070001, 0xe000bf0,
-0x0, 0xa000db7, 0x8f86003c, 0x8f83007c,
-0x24020002, 0x1462fff6, 0x24040012, 0xe000c53,
-0x0, 0x8f850078, 0x403021, 0x24040012,
-0xe000bf0, 0x3821, 0xa000db7, 0x8f86003c,
-0x8f83007c, 0x24110003, 0x10710029, 0x241f0002,
-0x107fffce, 0x26090001, 0x24040010, 0x2821,
-0x3021, 0xa000dd4, 0x24070001, 0x8f91007c,
-0x24060002, 0x1626fff9, 0x24040010, 0xe000cf8,
-0x0, 0x14400023, 0x8f98003c, 0x8f86003c,
-0xa000db6, 0x24020003, 0x24040014, 0xe000bf0,
-0x2821, 0x8f86003c, 0xa000db6, 0x24020002,
-0xe000d60, 0x0, 0xa000db7, 0x8f86003c,
-0xe000c00, 0x0, 0x24190002, 0x24040014,
-0x2821, 0x3021, 0x3821, 0xaf99007c,
-0xe000bf0, 0x0, 0xa000db7, 0x8f86003c,
-0xe000c10, 0x0, 0x8f850078, 0x24190002,
-0x403021, 0x24040010, 0x3821, 0xa000e0d,
-0xaf99007c, 0x403821, 0x24040010, 0x970f0002,
-0x2821, 0xe000bf0, 0x31e6ffff, 0x8f86003c,
-0xa000db7, 0xaf91007c, 0x8f84ff54, 0x3c077fff,
-0x34e6ffff, 0x8c850018, 0x24020001, 0xa61824,
-0xac830018, 0x3e00008, 0xa0820005, 0x3084ffff,
-0x30a5ffff, 0x10800007, 0x1821, 0x30820001,
-0x10400002, 0x42042, 0x651821, 0x1480fffb,
-0x52840, 0x3e00008, 0x601021, 0x10c00007,
-0x0, 0x8ca20000, 0x24c6ffff, 0x24a50004,
-0xac820000, 0x14c0fffb, 0x24840004, 0x3e00008,
-0x0, 0x10a00008, 0x24a3ffff, 0xac860000,
-0x0, 0x0, 0x2402ffff, 0x2463ffff,
-0x1462fffa, 0x24840004, 0x3e00008, 0x0,
-0x411c0, 0x3e00008, 0x24420240, 0x27bdffe8,
-0xafb00010, 0x808021, 0xafbf0014, 0xe000e4d,
-0xa02021, 0x504821, 0x240aff80, 0x8fbf0014,
-0x8fb00010, 0x12a3024, 0x3127007f, 0x3c08800a,
-0x3c042100, 0xe81021, 0xc42825, 0x3c038000,
-0x27bd0018, 0xac650024, 0xaf820020, 0xac400000,
-0xac650024, 0x3e00008, 0xac400040, 0x3c0d0800,
+0xacf80034, 0x8d0600bc, 0x54c5ffeb, 0x8d0200b8,
+0x8d0200b4, 0xa4e20048, 0x94e40048, 0xa4e4004a,
+0x94e800ea, 0x3e00008, 0x3102ffff, 0x8f860058,
+0x3c048000, 0x8cc90008, 0x8cc80008, 0x929c0,
+0x839c0, 0xac870020, 0x90c30007, 0x30620004,
+0x1040003e, 0xaf850094, 0x90cb0007, 0x316a0008,
+0x1140003d, 0x8f87ff2c, 0x8ccd000c, 0x8cce0014,
+0x1ae602b, 0x11800036, 0x0, 0x8cc2000c,
+0xace20070, 0x8ccb0018, 0x8f85ff28, 0x8f88ff30,
+0xaceb0074, 0x8cca0010, 0x2402fff8, 0xacaa00d8,
+0x8cc9000c, 0xad090060, 0x8cc4001c, 0xaca400d0,
+0x90e3007c, 0x62c824, 0xa0f9007c, 0x90d80007,
+0x330f0008, 0x11e00004, 0x0, 0x90ed007c,
+0x35ac0001, 0xa0ec007c, 0x90cf0007, 0x31ee0001,
+0x11c00006, 0x0, 0x90e3007c, 0x24180034,
+0x34790002, 0xa0f9007c, 0xacb800dc, 0x90c20007,
+0x30460002, 0x10c00004, 0x0, 0x90e8007c,
+0x35040004, 0xa0e4007c, 0x90ed007d, 0x3c0b600e,
+0x356a0010, 0x31ac003f, 0xa0ec007d, 0x8d4931d4,
+0x31270001, 0x10e00002, 0x240e0001, 0xa0ae0009,
+0x94af00ea, 0x3e00008, 0x31e2ffff, 0x8f87ff2c,
+0xa000daf, 0x8cc20014, 0xa000db0, 0xace00070,
+0x8f8c0058, 0x27bdffd8, 0xafb3001c, 0xafb20018,
+0xafb00010, 0xafbf0020, 0xafb10014, 0x918f0015,
+0x3c13600e, 0x36730010, 0x31eb000f, 0xa38b009c,
+0x8d8f0004, 0x8d8b0008, 0x959f0012, 0x95990010,
+0x9584001a, 0x9598001e, 0x958e001c, 0x33edffff,
+0x332affff, 0x3089ffff, 0x3308ffff, 0x31c7ffff,
+0x3c010800, 0xac2d0024, 0x3c010800, 0xac290044,
+0x3c010800, 0xac2a0040, 0xae683178, 0xae67317c,
+0x91850015, 0x95910016, 0x3c126012, 0x36520010,
+0x30a200ff, 0x3230ffff, 0xae623188, 0xae5000b4,
+0x91830014, 0x959f0018, 0x24060001, 0x66c804,
+0x33f8ffff, 0xae5900b8, 0xae5800bc, 0x918e0014,
+0xaf8f0084, 0x3c086006, 0x31cd00ff, 0xae4d00c0,
+0x918a0015, 0x9584000e, 0x3c07600a, 0x314900ff,
+0xaf8b0088, 0x3084ffff, 0xae4900c8, 0x35110010,
+0xe000d10, 0x34f00410, 0x3c020800, 0x8c420060,
+0x3c030800, 0x8c630064, 0x3c060800, 0x8cc60058,
+0x3c050800, 0x8ca5005c, 0x8f840080, 0x8fbf0020,
+0xae23004c, 0xae65319c, 0xae030054, 0xae4500dc,
+0xae6231a0, 0xae6331a4, 0xae663198, 0xae220048,
+0x8fb3001c, 0xae020050, 0x8fb10014, 0xae4200e0,
+0xae4300e4, 0xae4600d8, 0x8fb00010, 0x8fb20018,
+0xa00057d, 0x27bd0028, 0x97850092, 0x9783007c,
+0x27bdffe8, 0xafb00010, 0xa3102b, 0xafbf0014,
+0x24040005, 0x8f900058, 0x10400055, 0x24090002,
+0xe000695, 0x8f850080, 0xaf820094, 0x24040003,
+0x1040004f, 0x24090002, 0x3c068000, 0xe000081,
+0xacc20020, 0x24070001, 0x24082000, 0x1040004d,
+0x24040005, 0x978e0092, 0x8f8aff2c, 0x24090050,
+0x25c50001, 0xa7850092, 0xa1490000, 0x3c0d0800,
+0x8dad0064, 0x24038000, 0x8f84ff28, 0xd6600,
+0xad4c0018, 0xa5400006, 0x954b000a, 0x8f85ff30,
+0x2402ff80, 0x1633024, 0xa546000a, 0x915f000a,
+0x4821, 0x3e2c825, 0xa159000a, 0xa0a00008,
+0xa140004c, 0xa08000d5, 0x96180002, 0x97830090,
+0x3c020004, 0xa49800ea, 0x960f0002, 0x2418ffbf,
+0x25ee2401, 0xa48e00be, 0x8e0d0004, 0xacad0044,
+0x8e0c0008, 0xacac0040, 0xa4a00050, 0xa4a00054,
+0x8e0b000c, 0x240c0030, 0xac8b0028, 0x8e060010,
+0xac860024, 0xa480003e, 0xa487004e, 0xa4870050,
+0xa483003c, 0xad420074, 0xac8800d8, 0xaca80060,
+0xa08700fc, 0x909f00d4, 0x33f9007f, 0xa09900d4,
+0x909000d4, 0x2187824, 0xa08f00d4, 0x914e007c,
+0x35cd0001, 0xa14d007c, 0x938b009c, 0xad480070,
+0xac8c00dc, 0xa08b00d6, 0x8f880088, 0x8f870084,
+0xac8800c4, 0xac8700c8, 0xa5400078, 0xa540007a,
+0x8fbf0014, 0x8fb00010, 0x1201021, 0x3e00008,
+0x27bd0018, 0x8f850094, 0xe000725, 0x8f860080,
+0xa000e9f, 0x24090002, 0x27bdffe0, 0xafb00010,
+0x8f900058, 0xafb10014, 0xafbf0018, 0x8e090004,
+0xe00054a, 0x921c0, 0x8e080004, 0x8f84ff28,
+0x8f82ff30, 0x839c0, 0x3c068000, 0xacc70020,
+0x948500ea, 0x90430013, 0x1460001c, 0x30b1ffff,
+0x8f8cff2c, 0x918b0008, 0x316a0040, 0x1540000b,
+0x0, 0x8e0d0004, 0x2203021, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x24040022, 0x3821,
+0xd29c0, 0xa000d2f, 0x27bd0020, 0xe000098,
+0x0, 0x8e0d0004, 0x2203021, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x24040022, 0x3821,
+0xd29c0, 0xa000d2f, 0x27bd0020, 0xe000090,
+0x0, 0x8e0d0004, 0x2203021, 0x8fbf0018,
+0x8fb10014, 0x8fb00010, 0x24040022, 0x3821,
+0xd29c0, 0xa000d2f, 0x27bd0020, 0x27bdffe0,
+0xafb20018, 0x3092ffff, 0xafb00010, 0xafbf001c,
+0xafb10014, 0x1240001e, 0x8021, 0x8f860058,
+0x8cc50000, 0x24030006, 0x53f02, 0x51402,
+0x30e40007, 0x14830016, 0x304500ff, 0x2ca80006,
+0x11000040, 0x55880, 0x3c0c0800, 0x258c58bc,
+0x16c5021, 0x8d490000, 0x1200008, 0x0,
+0x8f8e0098, 0x240d0001, 0x11cd0050, 0x24020002,
+0xaf820098, 0x26090001, 0x3130ffff, 0x24c80020,
+0x212202b, 0x1003021, 0x1480ffe5, 0xaf880058,
+0x2001021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0020, 0x9387007e,
+0x54e00034, 0x3021, 0xe000de7, 0x0,
+0x8f860058, 0xa000eff, 0x24020001, 0x8f870098,
+0x24050002, 0x10e50031, 0x24040013, 0x2821,
+0x3021, 0x24070001, 0xe000d2f, 0x0,
+0xa000f00, 0x8f860058, 0x8f830098, 0x24020002,
+0x1462fff6, 0x24040012, 0xe000d9a, 0x0,
+0x8f850094, 0x403021, 0x24040012, 0xe000d2f,
+0x3821, 0xa000f00, 0x8f860058, 0x8f830098,
+0x24110003, 0x10710029, 0x241f0002, 0x107fffce,
+0x26090001, 0x24040010, 0x2821, 0x3021,
+0xa000f1d, 0x24070001, 0x8f910098, 0x24060002,
+0x1626fff9, 0x24040010, 0xe000e41, 0x0,
+0x14400023, 0x8f980058, 0x8f860058, 0xa000eff,
+0x24020003, 0x24040014, 0xe000d2f, 0x2821,
+0x8f860058, 0xa000eff, 0x24020002, 0xe000ea9,
+0x0, 0xa000f00, 0x8f860058, 0xe000d3f,
+0x0, 0x24190002, 0x24040014, 0x2821,
+0x3021, 0x3821, 0xaf990098, 0xe000d2f,
+0x0, 0xa000f00, 0x8f860058, 0xe000d57,
+0x0, 0x8f850094, 0x24190002, 0x403021,
+0x24040010, 0x3821, 0xa000f56, 0xaf990098,
+0x403821, 0x24040010, 0x970f0002, 0x2821,
+0xe000d2f, 0x31e6ffff, 0x8f860058, 0xa000f00,
+0xaf910098, 0x8f84ff2c, 0x3c077fff, 0x34e6ffff,
+0x8c850018, 0x24020001, 0xa61824, 0xac830018,
+0x3e00008, 0xa0820005, 0x3084ffff, 0x30a5ffff,
+0x10800007, 0x1821, 0x30820001, 0x10400002,
+0x42042, 0x651821, 0x1480fffb, 0x52840,
+0x3e00008, 0x601021, 0x10c00007, 0x0,
+0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
+0x14c0fffb, 0x24840004, 0x3e00008, 0x0,
+0x10a00008, 0x24a3ffff, 0xac860000, 0x0,
+0x0, 0x2402ffff, 0x2463ffff, 0x1462fffa,
+0x24840004, 0x3e00008, 0x0, 0x411c0,
+0x3e00008, 0x24420240, 0x27bdffe8, 0xafb00010,
+0x808021, 0xafbf0014, 0xe000f96, 0xa02021,
+0x504821, 0x240aff80, 0x8fbf0014, 0x8fb00010,
+0x12a3024, 0x3127007f, 0x3c08800a, 0x3c042100,
+0xe81021, 0xc42825, 0x3c038000, 0x27bd0018,
+0xac650024, 0xaf820038, 0xac400000, 0xac650024,
+0x3e00008, 0xac400040, 0x3c0d0800, 0x8dad0058,
+0x56180, 0x240aff80, 0x1a45821, 0x16c4821,
+0x12a3024, 0x3127007f, 0x3c08800c, 0x3c042100,
+0xe81021, 0xc42825, 0x3c038000, 0xac650028,
+0xaf820034, 0x3e00008, 0xac400024, 0x30a5ffff,
+0x3c068000, 0x8cc201b8, 0x440fffe, 0x3c086015,
+0xa83825, 0x3c031000, 0xacc40180, 0xacc00184,
+0xacc70188, 0x3e00008, 0xacc301b8, 0x3c0d0800,
0x8dad0058, 0x56180, 0x240aff80, 0x1a45821,
-0x16c4821, 0x12a3024, 0x3127007f, 0x3c08800c,
-0x3c042100, 0xe81021, 0xc42825, 0x3c038000,
-0xac650028, 0xaf82001c, 0x3e00008, 0xac400024,
-0x30a5ffff, 0x3c068000, 0x8cc201b8, 0x440fffe,
-0x3c086015, 0xa83825, 0x3c031000, 0xacc40180,
-0xacc00184, 0xacc70188, 0x3e00008, 0xacc301b8,
-0x3c0d0800, 0x8dad0058, 0x56180, 0x240aff80,
-0x1a45821, 0x16c4021, 0x10a4824, 0x93140,
-0x3107007f, 0xc72825, 0x3c042000, 0xa41825,
-0x3c028000, 0xac430830, 0x3e00008, 0xaf80001c,
-0x27bdffe8, 0xafb00010, 0x808021, 0xafbf0014,
-0xe000e4d, 0xa02021, 0x504821, 0x240bff80,
-0x12b5024, 0xa3940, 0x3128007f, 0x3c062000,
-0x8fbf0014, 0x8fb00010, 0xe82825, 0x34c20001,
-0xa21825, 0x3c048000, 0x27bd0018, 0xac830830,
-0x3e00008, 0xaf800020, 0x3c058008, 0x8ca70060,
-0x3c068008, 0x87102b, 0x14400011, 0x2c834000,
-0x8ca80060, 0x2d034000, 0x1060000f, 0x24034000,
-0x8cc90060, 0x89282b, 0x14a00002, 0x801821,
-0x8cc30060, 0x35a42, 0xb3080, 0x3c0a0800,
-0x254a55a0, 0xca2021, 0x3e00008, 0x8c820000,
-0x1460fff3, 0x24034000, 0x35a42, 0xb3080,
-0x3c0a0800, 0x254a55a0, 0xca2021, 0x3e00008,
-0x8c820000, 0x3c058008, 0x90a60008, 0x93840090,
-0x24c20001, 0x304200ff, 0x3043007f, 0x1064000c,
-0x23827, 0xa0a20008, 0x3c048000, 0x8c850178,
-0x4a0fffe, 0x8f8a0088, 0x24090002, 0x3c081000,
-0xac8a0140, 0xa0890144, 0x3e00008, 0xac880178,
-0xa000ed2, 0x30e20080, 0x27bdffc8, 0x3c058008,
+0x16c4021, 0x10a4824, 0x93140, 0x3107007f,
+0xc72825, 0x3c042000, 0xa41825, 0x3c028000,
+0xac430830, 0x3e00008, 0xaf800034, 0x27bdffe8,
+0xafb00010, 0x808021, 0xafbf0014, 0xe000f96,
+0xa02021, 0x504821, 0x240bff80, 0x12b5024,
+0xa3940, 0x3128007f, 0x3c062000, 0x8fbf0014,
+0x8fb00010, 0xe82825, 0x34c20001, 0xa21825,
+0x3c048000, 0x27bd0018, 0xac830830, 0x3e00008,
+0xaf800038, 0x3c058008, 0x8ca70060, 0x3c068008,
+0x87102b, 0x14400011, 0x2c834000, 0x8ca80060,
+0x2d034000, 0x1060000f, 0x24034000, 0x8cc90060,
+0x89282b, 0x14a00002, 0x801821, 0x8cc30060,
+0x35a42, 0xb3080, 0x3c0a0800, 0x254a5920,
+0xca2021, 0x3e00008, 0x8c820000, 0x1460fff3,
+0x24034000, 0x35a42, 0xb3080, 0x3c0a0800,
+0x254a5920, 0xca2021, 0x3e00008, 0x8c820000,
+0x3c058008, 0x90a60008, 0x938400ab, 0x24c20001,
+0x304200ff, 0x3043007f, 0x1064000c, 0x23827,
+0xa0a20008, 0x3c048000, 0x8c850178, 0x4a0fffe,
+0x8f8a00a0, 0x24090002, 0x3c081000, 0xac8a0140,
+0xa0890144, 0x3e00008, 0xac880178, 0xa00101b,
+0x30e20080, 0x27bdffd8, 0xafb20018, 0x8f9200a4,
+0xafbf0020, 0xafb3001c, 0xafb00010, 0xafb10014,
+0x8f930034, 0x8e590028, 0x3c100080, 0x3c0effef,
+0xae790000, 0x8e580024, 0xa260000a, 0x35cdffff,
+0xae780004, 0x9251002c, 0x3c0bff9f, 0x356affff,
+0xa271000c, 0x8e6f000c, 0x3c080040, 0xa271000b,
+0x1f06025, 0x18d4824, 0x12a3824, 0xe83025,
+0xae66000c, 0x8e450004, 0xae600018, 0x3c0400ff,
+0xae650014, 0x8e43002c, 0x3482ffff, 0xa6600008,
+0x62f824, 0xae7f0010, 0x8e590008, 0x8f9000a0,
+0x964e0012, 0xae790020, 0x8e51000c, 0x31d83fff,
+0x187980, 0xae710024, 0x8e4d0014, 0x1f06021,
+0x31cb0001, 0xae6d0028, 0x8e4a0018, 0xc41c2,
+0xb4b80, 0xae6a002c, 0x8e46001c, 0x1093821,
+0xa667001c, 0xae660030, 0x96450002, 0x8e440020,
+0xa665001e, 0xae640034, 0x92430033, 0x30620004,
+0x54400006, 0x92470000, 0x3c028008, 0x34430100,
+0x8c7f00d0, 0xae7f0030, 0x92470000, 0x8f860038,
+0xa0c70030, 0x92450033, 0x30a40002, 0x50800007,
+0x92510001, 0x8f880038, 0x240bff80, 0x910a0030,
+0x14b4825, 0xa1090030, 0x92510001, 0x8f900038,
+0x240cffbf, 0x2404ffdf, 0xa2110031, 0x8f8d0038,
+0x3c188008, 0x37110080, 0x91af003c, 0x31ee007f,
+0xa1ae003c, 0x8f890038, 0x912b003c, 0x16c5024,
+0xa12a003c, 0x8f9f0038, 0x8e680014, 0x93e6003c,
+0x2d070001, 0x71140, 0xc42824, 0xa21825,
+0xa3e3003c, 0x8f870038, 0x96590012, 0xa4f90032,
+0x8e450004, 0x922e007c, 0x30b00003, 0x107823,
+0x31ed0003, 0xad1021, 0x31cc0002, 0x15800002,
+0x24460034, 0x24460030, 0x3c028008, 0x34430080,
+0x907f007c, 0xbfc824, 0x33380004, 0x17000002,
+0x24c20004, 0xc01021, 0x8f980038, 0x24190002,
+0xace20034, 0xa3190000, 0x924f003f, 0x8f8e0038,
+0x3c0c8008, 0x358b0080, 0xa1cf0001, 0x8f910038,
+0x924d003f, 0x8e440004, 0xa62d0002, 0x956a005c,
+0xe000ff4, 0x3150ffff, 0x24b80, 0x2093825,
+0x3c084200, 0xe82825, 0xae250004, 0x8e440038,
+0x8f850038, 0xaca40018, 0x8e460034, 0xaca6001c,
+0xaca0000c, 0xaca00010, 0xa4a00014, 0xa4a00016,
+0xa4a00020, 0xa4a00022, 0xaca00024, 0x8e620014,
+0x50400001, 0x24020001, 0x8fbf0020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0xaca20008,
+0xa001013, 0x27bd0028, 0x27bdffc8, 0x3c058008,
0x34a40080, 0xafbf0034, 0xafbe0030, 0xafb7002c,
0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c,
0xafb20018, 0xafb10014, 0xafb00010, 0x94830078,
-0x9482007a, 0x104300cd, 0x2405ffff, 0x3c1e8008,
-0x80b821, 0xa000fae, 0x3c168000, 0x108a00c8,
-0x8fbf0034, 0x8f840088, 0x3c0b0800, 0x8d6b005c,
-0x240aff80, 0x3c07800e, 0x1644021, 0x10a4824,
-0xaec9002c, 0x96e6007a, 0x3102007f, 0x471821,
-0x30c57fff, 0x58040, 0x203a821, 0x96bf0000,
-0x3c190800, 0x8f390058, 0x240fff80, 0x33f53fff,
-0x3248821, 0x15c180, 0x2389021, 0x24f5824,
-0x3c0c0100, 0x16c5025, 0x324e007f, 0x3c0d800c,
-0x1cd9021, 0x2802821, 0xe000e50, 0xaeca0028,
-0x8e480010, 0x8e490030, 0x8f860020, 0x24020002,
-0x1093823, 0xae470010, 0xa0c20000, 0x96e3005c,
-0x8e440030, 0x8f910020, 0xe000eab, 0x3070ffff,
-0x22b80, 0x205c825, 0x3c1f4200, 0x33fc025,
-0xae380004, 0x8e510004, 0x8f870020, 0x8e4f0000,
-0x24080008, 0xacf1001c, 0xacef0018, 0xace0000c,
-0xace00010, 0x9250000a, 0x24060005, 0x2405c000,
-0x320e00ff, 0xa4ee0014, 0x964d0008, 0x2e09821,
-0xa4ed0016, 0x924c000a, 0x3c0d8008, 0x318b00ff,
-0xa4eb0020, 0x96440008, 0x35ac0100, 0xa4e40022,
-0xace00024, 0x924a000b, 0x314900ff, 0xa4e90002,
-0xa0e80001, 0x8e420030, 0x8f830020, 0x2408ffbf,
-0xac620008, 0xa0660030, 0x8f8e0020, 0x2403ffdf,
-0x95df0032, 0x3e5c824, 0x335c025, 0xa5d80032,
-0x91d10032, 0x322f003f, 0x35f00040, 0xa1d00032,
-0x8f890020, 0xad200034, 0x8d8b00c0, 0xad2b0038,
-0x9124003c, 0x3c0b7fff, 0x308a007f, 0xa12a003c,
-0x8f860020, 0x3564ffff, 0x90c7003c, 0xe81024,
-0xa0c2003c, 0x8f990020, 0x9325003c, 0xa3f824,
-0xa33f003c, 0x8e580034, 0x8f8c0020, 0xad980040,
-0x8e4f002c, 0x8e510030, 0x1f18023, 0xad900044,
-0x918e0048, 0x31cd007f, 0xa18d0048, 0x8f850020,
-0x8e4a0030, 0x8ca90048, 0x1444024, 0x1363824,
-0xe83025, 0xaca60048, 0x9242000a, 0xa0a2004c,
-0x96430008, 0x8f9f0020, 0xa7e3004e, 0x8e500030,
-0x8e440030, 0xe00030c, 0x8fc50060, 0x92f1007c,
-0x2c140, 0x2c900, 0x3197821, 0x322e0002,
-0x402821, 0x11c00003, 0x20f8021, 0x22080,
-0x2048021, 0x926d007c, 0x31ac0004, 0x11800002,
-0x57080, 0x20e8021, 0x8e440030, 0x8f870020,
-0x24058000, 0x308b0003, 0xb5023, 0x31490003,
-0x2094021, 0xace80034, 0x9664007a, 0x9662007a,
-0x9670007a, 0x30467fff, 0x24c30001, 0x307f7fff,
-0x205c824, 0x33fc025, 0xa678007a, 0x9671007a,
-0x3c120800, 0x8e520060, 0x322f7fff, 0x11f20028,
-0x0, 0x8f840088, 0xe000e85, 0x2a02821,
-0x8f840088, 0xe000e95, 0x2802821, 0xe000eca,
-0x0, 0x96f30078, 0x96f4007a, 0x1293000f,
-0x2821, 0x3c098008, 0x35240100, 0x93c80008,
-0x908700c5, 0x3114007f, 0x30e400ff, 0x284302b,
-0x14c0ff3e, 0x268a0001, 0x938d0090, 0x268b0001,
-0x8d6021, 0x158bff3c, 0x8f840088, 0x8fbf0034,
+0x9482007a, 0x10430051, 0x2405ffff, 0x80f021,
+0xa001123, 0x80b821, 0x108b004d, 0x8fbf0034,
+0x8f8600a0, 0x3c180800, 0x8f18005c, 0x2411ff80,
+0x3c168000, 0x3067821, 0x1f18024, 0xaed0002c,
+0x96ee007a, 0x31ec007f, 0x3c0d800e, 0x31cb7fff,
+0x18d5021, 0xb4840, 0x12aa821, 0x96a40000,
+0x3c080800, 0x8d080058, 0x2405ff80, 0x30953fff,
+0x1061821, 0x153980, 0x67c821, 0x325f824,
+0x3c020100, 0x3e29025, 0x3338007f, 0x3c11800c,
+0xaed20028, 0x3119021, 0x9250000d, 0x320f0004,
+0x11e00037, 0x2e09821, 0x96e3007a, 0x96e8007a,
+0x96e5007a, 0x24048000, 0x31077fff, 0x24e30001,
+0x30627fff, 0xa4f824, 0x3e2c825, 0xa6f9007a,
+0x96e6007a, 0x3c140800, 0x8e940060, 0x30d67fff,
+0x12d400c1, 0x0, 0x8e580018, 0x8f8400a0,
+0x2a02821, 0x2713ffff, 0xe000fce, 0xae53002c,
+0x97d50078, 0x97d4007a, 0x12950010, 0x2821,
+0x3c098008, 0x35240100, 0x3c0a8008, 0x91480008,
+0x908700d5, 0x3114007f, 0x30e400ff, 0x284302b,
+0x14c0ffb9, 0x268b0001, 0x938e00ab, 0x268c0001,
+0x8e6821, 0x15acffb7, 0x8f8600a0, 0x8fbf0034,
0x8fbe0030, 0x8fb7002c, 0x8fb60028, 0x8fb50024,
0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
0x8fb00010, 0xa01021, 0x3e00008, 0x27bd0038,
-0x967f007a, 0x3e5c824, 0xa679007a, 0x9278007a,
-0x926e007a, 0x331100ff, 0x1179c2, 0xf9027,
-0x1269c0, 0x31cc007f, 0x18d2825, 0xa265007a,
-0xa000fa3, 0x8f840088, 0x3c038000, 0x3084ffff,
-0x30a5ffff, 0xac640018, 0xac65001c, 0x3e00008,
-0x8c620014, 0x27bdffa8, 0x3c068008, 0xafbf0054,
-0xafbe0050, 0xafb7004c, 0xafb60048, 0xafb50044,
-0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034,
-0xafb00030, 0x34c80100, 0x910500c5, 0x90c70008,
-0x3084ffff, 0x30a500ff, 0x30e2007f, 0x45182a,
-0xafa40010, 0xa7a00018, 0x1060009c, 0xafa00014,
-0x90ca0008, 0x3149007f, 0xa93023, 0x24d4ffff,
-0x14882b, 0x8fb30010, 0x13902b, 0x2328024,
-0x52000085, 0x8fb40014, 0x3c038008, 0x94790052,
+0xc02021, 0xe000f99, 0x2802821, 0x8e4b0010,
+0x8e4c0030, 0x8f840038, 0x24090002, 0x16c5023,
+0xae4a0010, 0xa0890000, 0x96e3005c, 0x8e440030,
+0x8f910038, 0xe000ff4, 0x3070ffff, 0x24380,
+0x2083825, 0x3c024200, 0xe22825, 0xae250004,
+0x8e5f0004, 0x8f8a0038, 0x8e590000, 0x240b0008,
+0xad5f001c, 0xad590018, 0xad40000c, 0xad400010,
+0x9246000a, 0x24040005, 0x2408c000, 0x30d000ff,
+0xa5500014, 0x96580008, 0xa5580016, 0x9251000a,
+0x3c188008, 0x322f00ff, 0xa54f0020, 0x964e0008,
+0x37110100, 0xa54e0022, 0xad400024, 0x924d000b,
+0x31ac00ff, 0xa54c0002, 0xa14b0001, 0x8e490030,
+0x8f830038, 0x240bffbf, 0xac690008, 0xa0640030,
+0x8f900038, 0x2403ffdf, 0x96070032, 0xe82824,
+0xb51025, 0xa6020032, 0x921f0032, 0x33f9003f,
+0x37260040, 0xa2060032, 0x8f8c0038, 0xad800034,
+0x8e2f00d0, 0xad8f0038, 0x918e003c, 0x3c0f7fff,
+0x31cd007f, 0xa18d003c, 0x8f840038, 0x35eeffff,
+0x908a003c, 0x14b4824, 0xa089003c, 0x8f850038,
+0x90a8003c, 0x1033824, 0xa0a7003c, 0x8e420034,
+0x8f910038, 0x3c038008, 0xae220040, 0x8e59002c,
+0x8e5f0030, 0x33f3023, 0xae260044, 0x92300048,
+0x3218007f, 0xa2380048, 0x8f880038, 0x8e4d0030,
+0x8d0c0048, 0x1ae5824, 0x1965024, 0x14b4825,
+0xad090048, 0x9244000a, 0xa104004c, 0x96470008,
+0x8f850038, 0xa4a7004e, 0x8e500030, 0x8e440030,
+0xe000381, 0x8c650060, 0x92f9007c, 0x2f940,
+0x402821, 0x21100, 0x3e23021, 0x33360002,
+0x12c00003, 0x2068021, 0x5b080, 0x2168021,
+0x926d007c, 0x31b30004, 0x12600002, 0x57080,
+0x20e8021, 0x8e4b0030, 0x8f880038, 0x24058000,
+0x316a0003, 0xa4823, 0x31240003, 0x2041821,
+0xad030034, 0x96e4007a, 0x96f0007a, 0x96f1007a,
+0x32027fff, 0x24470001, 0x30ff7fff, 0x225c824,
+0x33f3025, 0xa6e6007a, 0x96f8007a, 0x3c120800,
+0x8e520060, 0x330f7fff, 0x11f20018, 0x0,
+0x8f8400a0, 0xe000fce, 0x2a02821, 0x8f8400a0,
+0xe000fde, 0x2802821, 0xe001013, 0x0,
+0xa00111f, 0x0, 0x96f1007a, 0x2248024,
+0xa6f0007a, 0x92ef007a, 0x92eb007a, 0x31ee00ff,
+0xe69c2, 0xd6027, 0xc51c0, 0x3169007f,
+0x12a2025, 0xa001119, 0xa2e4007a, 0x96e6007a,
+0xc5c024, 0xa6f8007a, 0x92ef007a, 0x92f3007a,
+0x31f200ff, 0x1271c2, 0xe6827, 0xdb1c0,
+0x326c007f, 0x1962825, 0xa2e5007a, 0xa0011d0,
+0x8f8400a0, 0x3c038000, 0x3084ffff, 0x30a5ffff,
+0xac640018, 0xac65001c, 0x3e00008, 0x8c620014,
+0x27bdffa0, 0x3c068008, 0xafbf005c, 0xafbe0058,
+0xafb70054, 0xafb60050, 0xafb5004c, 0xafb40048,
+0xafb30044, 0xafb20040, 0xafb1003c, 0xafb00038,
+0x34c80100, 0x910500d5, 0x90c70008, 0x3084ffff,
+0x30a500ff, 0x30e2007f, 0x45182a, 0xafa40010,
+0xa7a00018, 0xa7a00026, 0x10600055, 0xafa00014,
+0x90ca0008, 0x3149007f, 0xa93023, 0x24d3ffff,
+0x13802b, 0x8fb40010, 0x14902b, 0x2128824,
+0x52200088, 0x8fb30014, 0x3c038008, 0x94790052,
0x947e0050, 0x8fb60010, 0x33ec023, 0x18bc00,
0x171403, 0x16fc00, 0x2c2a82a, 0x16a00002,
-0x1f2c03, 0x402821, 0x143c00, 0x72403,
+0x1f2c03, 0x402821, 0x133c00, 0x72403,
0xa4102a, 0x54400001, 0xa02021, 0x28850009,
-0x14a00002, 0x80b021, 0x24160008, 0x3c0c8008,
-0x8d860048, 0x165980, 0x8d88004c, 0x3c038000,
-0x3169ffff, 0x3c0a0010, 0x12a2025, 0x34700400,
-0xac660038, 0xaf90008c, 0xac68003c, 0xac640030,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x8c6e0000, 0x31cd0020, 0x11a0fffd, 0x16902a,
-0x2517824, 0x11e00036, 0xb821, 0x3c158000,
-0x3c118008, 0x92220008, 0x8ea40100, 0x8821,
-0x305e007f, 0xe000e50, 0x3c02821, 0x8e1f0010,
-0x8ea40100, 0x33f93fff, 0x3202821, 0xe000e68,
-0xafb9001c, 0x92180000, 0x3302003f, 0x2c530008,
-0x5260000d, 0x8021, 0x24050001, 0x451804,
-0x3067005d, 0x14e000b1, 0x8f92008c, 0x30640002,
-0x1480014d, 0x8f86008c, 0x30680080, 0x5500004a,
-0x96180012, 0x8021, 0x8ea40100, 0xe000e85,
-0x8fa5001c, 0x8ea40100, 0xe000e95, 0x3c02821,
-0x1200004f, 0x3c078008, 0x26e40001, 0x8f8c008c,
-0x4bc00, 0x291a023, 0x17bc03, 0x2f6302a,
-0x14882b, 0x259f0040, 0x24120001, 0xd1f024,
-0x3e08021, 0xaf9f008c, 0x17c0ffcd, 0xafb20014,
-0x3c078008, 0x94e80050, 0x8fb30010, 0x3c058000,
-0x2e81021, 0x3c0d0020, 0xa4e20050, 0xacad0030,
-0x94f50050, 0x94f60052, 0x2775023, 0x3149ffff,
-0x12d50041, 0xafa90010, 0x8cf6004c, 0x174980,
-0x8cf70048, 0x2c9f821, 0x2021, 0x3e9302b,
-0x2e46021, 0x1868021, 0xacff004c, 0xacf00048,
-0x8fb30010, 0x13902b, 0x2328024, 0x1600ff7f,
-0x3c038008, 0x8fb40014, 0x8fbf0054, 0x8fbe0050,
-0x3a820001, 0x8fb7004c, 0x8fb60048, 0x8fb50044,
-0x8fb40040, 0x8fb3003c, 0x8fb20038, 0x8fb10034,
-0x8fb00030, 0x3e00008, 0x27bd0058, 0x90cf0008,
-0x938c0090, 0x31ee007f, 0xae6823, 0x18d5821,
-0xa000ff9, 0x2574ffff, 0x8f840088, 0x24100001,
-0xa7b80018, 0xe000e79, 0x97a50018, 0x8ea40100,
-0xe000e85, 0x8fa5001c, 0x8ea40100, 0xe000e95,
-0x3c02821, 0x1600ffb5, 0x26e40001, 0x3c078008,
-0x94e80050, 0x8fb30010, 0x3c058000, 0x2e81021,
-0x3c0d0020, 0xa4e20050, 0xacad0030, 0x94f50050,
-0x94f60052, 0x2775023, 0x3149ffff, 0x14882b,
-0x16d5ffc1, 0xafa90010, 0x94fe0054, 0x8cf00044,
-0x33d8fffe, 0x1878c0, 0x20f7021, 0xacae003c,
-0x8cf90044, 0x8ca3003c, 0x3235823, 0x196002ea,
-0x0, 0x8cf20040, 0x26420001, 0xaca20038,
+0x14a00002, 0x80a021, 0x24140008, 0x3c0c8008,
+0x8d860048, 0x145980, 0x8d88004c, 0x3c038000,
+0x3169ffff, 0x3c0a0010, 0x12a2025, 0x34710400,
+0xac660038, 0xaf9100a4, 0xac68003c, 0xac640030,
+0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0,
+0x8c6e0000, 0x31cd0020, 0x11a0fffd, 0x14782a,
+0x1f01024, 0x10400039, 0xa821, 0x3c168008,
+0x92d70008, 0x3c128000, 0x8e440100, 0x32f6007f,
+0xe000f99, 0x2c02821, 0x8e390010, 0x8e440100,
+0x9021, 0x33373fff, 0xe000fb1, 0x2e02821,
+0x92380000, 0x3302003f, 0x2c500008, 0x52000010,
+0x8821, 0x21080, 0x3c030800, 0x246358e4,
+0x43f821, 0x8ffe0000, 0x3c00008, 0x0,
+0x90cf0008, 0x938c00ab, 0x31ee007f, 0xae6823,
+0x18d5821, 0xa001217, 0x2573ffff, 0x8821,
+0x3c1e8000, 0x8fc40100, 0xe000fce, 0x2e02821,
+0x8fc40100, 0xe000fde, 0x2c02821, 0x1220000f,
+0x13802b, 0x8f8b00a4, 0x26a40001, 0x4ac00,
+0x2729823, 0x15ac03, 0x25780040, 0x2b4b02a,
+0x13802b, 0x24170001, 0x3008821, 0x2d01024,
+0xaf9800a4, 0x1440ffc9, 0xafb70014, 0x3c078008,
+0x94e20050, 0x8fae0010, 0x3c058000, 0x2a28821,
+0x3c060020, 0xa4f10050, 0xaca60030, 0x94f40050,
+0x94ef0052, 0x1d51823, 0x306cffff, 0x11f4001e,
+0xafac0010, 0x8cef004c, 0x156180, 0x8cf50048,
+0x1ec2821, 0x2021, 0xac582b, 0x2a4c021,
+0x30bb021, 0xace5004c, 0xacf60048, 0x8fb40010,
+0x14902b, 0x2128824, 0x1620ff7c, 0x3c038008,
+0x8fb30014, 0x8fbf005c, 0x8fbe0058, 0x3a620001,
+0x8fb70054, 0x8fb60050, 0x8fb5004c, 0x8fb40048,
+0x8fb30044, 0x8fb20040, 0x8fb1003c, 0x8fb00038,
+0x3e00008, 0x27bd0060, 0x94fe0054, 0x8cf20044,
+0x33c9fffe, 0x9c8c0, 0x259f821, 0xacbf003c,
+0x8ce80044, 0x8cad003c, 0x10d5023, 0x1940003b,
+0x0, 0x8cf70040, 0x26e20001, 0xaca20038,
0x3c050050, 0x34a70010, 0x3c038000, 0xac670030,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
-0x8c7f0000, 0x33e60020, 0x10c0fffd, 0x3c108008,
-0x960d0054, 0x3c178000, 0x3c068008, 0x31b30001,
-0x1350c0, 0x157b021, 0x8ec90400, 0x3c070800,
-0x8ce70044, 0x3c040020, 0xacc90048, 0x8ed50404,
-0x240c0001, 0xacd5004c, 0x10ec02d0, 0xaee40030,
-0x96180052, 0x3c050800, 0x8ca50040, 0xb87821,
-0xa60f0052, 0x960e0054, 0x25c30001, 0xa6030054,
-0x96190054, 0x3324ffff, 0x5487ff0f, 0x8fb30010,
-0x30a5ffff, 0xe000fd7, 0xa6000054, 0x3c050800,
-0x8ca50024, 0x96120052, 0x453823, 0x247f023,
-0xa61e0052, 0xa000ffb, 0x8fb30010, 0x8f93001c,
-0x3c070080, 0x8e440028, 0x3c1fffef, 0x37f9ffff,
-0xae640000, 0x8e420024, 0xa260000a, 0x3c0fff9f,
-0xae620004, 0x9245002c, 0x35eeffff, 0x3c0c0040,
-0xa265000c, 0x8e71000c, 0xa265000b, 0x3c0600ff,
-0x227c025, 0x3196824, 0x1ae5824, 0x16c5025,
-0xae6a000c, 0x8e490004, 0xae600018, 0x34d0ffff,
-0xae690014, 0x8e48002c, 0x8f820088, 0xa6600008,
-0x1102024, 0xae640010, 0x8e510008, 0x96470012,
-0xae710020, 0x8e58000c, 0x30e33fff, 0x32980,
-0xae780024, 0x8e4c0014, 0xa2f821, 0x30f90001,
-0xae6c0028, 0x8e4b0018, 0x1f71c2, 0x197b80,
-0xae6b002c, 0x8e49001c, 0x1cf6821, 0xa66d001c,
-0xae690030, 0x964a0002, 0x8e460020, 0xa66a001e,
-0xae660034, 0x92430033, 0x30700004, 0x56000006,
-0x924b0000, 0x3c068008, 0x34d00100, 0x8e0800c0,
-0xae680030, 0x924b0000, 0x8f8a0020, 0xa14b0030,
-0x92490033, 0x31230002, 0x50600007, 0x92440001,
-0x8f8c0020, 0x240fff80, 0x918e0030, 0x1cf6825,
-0xa18d0030, 0x92440001, 0x8f820020, 0x2418ffbf,
-0x240affdf, 0xa0440031, 0x8f990020, 0x3c088008,
-0x35040080, 0x9331003c, 0x323f007f, 0xa33f003c,
-0x8f8d0020, 0x91af003c, 0x1f87024, 0xa1ae003c,
-0x8f870020, 0x8e6c0014, 0x90e3003c, 0x2d8b0001,
-0xb4940, 0x6a3024, 0xc98025, 0xa0f0003c,
-0x96450012, 0x8f870020, 0xa4e50032, 0x8e450004,
-0x909f007c, 0x30a20003, 0x28823, 0x32390003,
-0xb91021, 0x33f80002, 0x17000002, 0x24440034,
-0x24440030, 0x3c038008, 0x34660080, 0x90c9007c,
-0xa98024, 0x32080004, 0x15000002, 0x24830004,
-0x801821, 0x8f840020, 0x24080002, 0xace30034,
-0xa0880000, 0x9242003f, 0x8f9f0020, 0x3c188008,
-0x370f0080, 0xa3e20001, 0x8f910020, 0x9259003f,
-0x8e440004, 0xa6390002, 0x95ee005c, 0xe000eab,
-0x31d0ffff, 0x26b80, 0x20d5825, 0x3c0c4200,
-0x16c2825, 0xae250004, 0x8e4a0038, 0x8f850020,
-0xacaa0018, 0x8e470034, 0xaca7001c, 0xaca0000c,
-0xaca00010, 0xa4a00014, 0xa4a00016, 0xa4a00020,
-0xa4a00022, 0xaca00024, 0x8e620014, 0x50400001,
-0x24020001, 0xaca20008, 0xe000eca, 0x24110001,
-0xa00104f, 0x24100001, 0x90d30001, 0x32720020,
-0x1240018a, 0x24100001, 0x3c0a8008, 0x35470080,
-0x90e3007c, 0x8f93001c, 0xafa00024, 0x30690001,
-0x11200011, 0xafb00020, 0x3c058008, 0x8ccb0014,
-0x8cac0060, 0x16c882b, 0x16200003, 0x1602821,
-0x3c108008, 0x8e050060, 0x3c0f8008, 0x35e30080,
-0x8c6e0070, 0xae682b, 0x15a00002, 0xa02021,
-0x8c640070, 0xafa40024, 0x8f82ff5c, 0x8cc40014,
-0x8c590070, 0x99c02b, 0x53000001, 0x8c440070,
-0x8fa20024, 0x82f823, 0x13e00003, 0xafbf0028,
-0x24040002, 0xafa40020, 0x8fb20020, 0x292402b,
-0x1500015b, 0x1821, 0x8cc50038, 0x8e6b000c,
-0x3c0c0080, 0xae650000, 0x8cc90034, 0x3c11ff9f,
-0x16c5025, 0xae690004, 0x90c8003f, 0x3623ffff,
-0x1431024, 0x3c120020, 0x3c04ffef, 0xa268000b,
-0x523825, 0x349fffff, 0xffc024, 0x3c190008,
-0x8f87008c, 0x3197825, 0xae6f000c, 0x8ced0014,
-0xae600018, 0x8fb10024, 0xae6d0014, 0x8cf00018,
-0x8fae0028, 0xae70001c, 0x8ce50008, 0x22e6021,
-0xae650024, 0x8ceb000c, 0xa6600038, 0xa660003a,
-0xae6c002c, 0xae600028, 0xae6b0020, 0x8cea0014,
-0x8fa30028, 0x1514823, 0x1233023, 0x10c00011,
-0xae660010, 0x90e9003d, 0x8e620004, 0x8e7f0000,
-0x99100, 0x527821, 0x2021, 0x1f2c82b,
-0x3e4c021, 0x3197021, 0xae6f0004, 0xae6e0000,
-0x90ed003d, 0xa26d000a, 0x8f90008c, 0x96060006,
-0xa6660008, 0x8f980020, 0x24190002, 0x3c0f8008,
-0x8fa40024, 0x35ee0080, 0xa3190000, 0x95cd005c,
-0x8f920020, 0xe000eab, 0x31b0ffff, 0x22b80,
-0x2056025, 0x3c064200, 0x8f85008c, 0x1865825,
-0xae4b0004, 0x8f840020, 0x8cb10038, 0xac910018,
-0x8ca30034, 0xac83001c, 0xac80000c, 0xac800010,
-0xa4800014, 0xa4800016, 0xa4800020, 0xa4800022,
-0xac800024, 0x90aa003f, 0x8fa70024, 0xa48a0002,
-0x10e0000c, 0x24090001, 0x8fbf0028, 0x53e00188,
-0x90a2003d, 0x90a2003e, 0x24480001, 0xa0880001,
-0x8f850020, 0x8fa40024, 0xaca40008, 0xa00122f,
-0x3c118008, 0xa0890001, 0x8f850020, 0x24020001,
-0xaca20008, 0x3c118008, 0x36230080, 0x906a007c,
-0x31470002, 0x14e00002, 0x24060034, 0x24060030,
-0x8f8d008c, 0x3c0f8008, 0x35ee0080, 0x91ac0000,
-0x91c8007c, 0x8fb00024, 0xa0ac0030, 0x8f91008c,
-0x8f820020, 0x8faa0024, 0x92270001, 0x32120003,
-0x240b0004, 0xa0470031, 0x1721823, 0x8f84008c,
-0x8f8b0020, 0x241fc000, 0x94980012, 0x95790032,
-0x30690003, 0x330f3fff, 0x33f7024, 0x1cf6825,
-0xa56d0032, 0x91650032, 0xca3021, 0xc93021,
-0x30b0003f, 0x360c0040, 0xa16c0032, 0x8fb20024,
-0x31070004, 0x12400002, 0x8f850020, 0xc73021,
-0x3c048008, 0xaca60034, 0x34880100, 0x8d1900c0,
-0x8fbf0024, 0x240dffbf, 0xacb90038, 0x90af003c,
-0x2ff80001, 0x2412ffdf, 0x31ee007f, 0xa0ae003c,
-0x8f8b0020, 0x188940, 0x9170003c, 0x20d6024,
-0xa16c003c, 0x8f870020, 0x90e3003c, 0x725024,
-0x1511025, 0xa0e2003c, 0x8f88008c, 0x8f990020,
-0x8d090020, 0xaf290040, 0x8d060024, 0xaf260044,
-0x8d040028, 0xaf240048, 0x8d1f002c, 0xaf3f004c,
-0xe000eca, 0x0, 0x8fb80020, 0x24050002,
-0x5705009f, 0x8fa30020, 0x3c1f8000, 0x3c128008,
-0x8fe40100, 0x92580008, 0x8f92ff5c, 0xe000e50,
-0x3305007f, 0x8f8e0020, 0x8faf0020, 0x8fa40028,
-0xa1cf0000, 0x9659005c, 0x8f910020, 0xe000eab,
-0x3330ffff, 0x25b80, 0x20b6825, 0x3c084200,
-0x8f8b008c, 0x1a83025, 0xae260004, 0x8d700038,
-0x8f860020, 0x2821, 0x51100, 0xacd00018,
-0x8d6c0034, 0x3c047fff, 0x3488ffff, 0xaccc001c,
-0x9171003e, 0x8cca001c, 0x8cdf0018, 0x113900,
-0x111f02, 0x1477021, 0x434825, 0x1c7c02b,
-0x3e97821, 0x1f8c821, 0xacce001c, 0xacd90018,
-0xacc0000c, 0xacc00010, 0x916d003e, 0x8faa0028,
-0x24070005, 0xa4cd0014, 0x95700004, 0x2418c000,
-0x148c824, 0xa4d00016, 0x916c003e, 0x1402021,
-0xa4cc0020, 0x95650004, 0xa4c50022, 0xacc00024,
-0x9163003f, 0xa4c30002, 0x9171003d, 0x26220001,
-0xa0c20001, 0x8f890020, 0x3c028008, 0x34460100,
-0xad2a0008, 0xa1270030, 0x8f910020, 0x8f9f008c,
-0x2402ff80, 0x962f0032, 0x97ee0012, 0x30f8024,
-0x31cd3fff, 0x20d6025, 0xa62c0032, 0x92250032,
-0x2418ffbf, 0x2410ffdf, 0x30ab003f, 0x35630040,
-0xa2230032, 0x8f9f0020, 0x2403ffff, 0xafe00034,
-0x8cca00c0, 0xafea0038, 0x93e7003c, 0x30e9007f,
-0xa3e9003c, 0x8f8d0020, 0x3c098000, 0x91af003c,
-0x1f87024, 0xa1ae003c, 0x8f8b0020, 0x916c003c,
-0x1902824, 0xa165003c, 0x8f870020, 0xace30040,
-0x8fb10024, 0x3c038008, 0xacf10044, 0x90ea0048,
-0x1423025, 0xa0e60048, 0x8f900020, 0x8f8e008c,
-0x8e1f0048, 0x3e9c024, 0x3197825, 0xae0f0048,
-0x91cd003e, 0xa20d004c, 0x8f8c008c, 0x8f8b0020,
-0x95850004, 0xa565004e, 0xe00030c, 0x8c650060,
-0x924a007c, 0x402821, 0x8fa60028, 0x21140,
-0x58900, 0x513821, 0x31490002, 0x11200003,
-0xc71821, 0x52080, 0x641821, 0x3c028008,
-0x344a0080, 0x9147007c, 0x30e90004, 0x11200003,
-0x8fb90028, 0x56080, 0x6c1821, 0x240b0004,
-0x8f910020, 0x33300003, 0x1704023, 0x310d0003,
-0x6d3021, 0xae260034, 0x3c038008, 0xa6650038,
-0x3c058000, 0x8ca40100, 0x90730008, 0xe000e95,
-0x3265007f, 0xe000eca, 0x0, 0x8fa30020,
-0x3782b, 0xf8023, 0x290a024, 0x608021,
-0x608821, 0xa00104f, 0x10802b, 0x8f91001c,
-0x8cd80038, 0x24190003, 0xa6200008, 0xae380000,
-0x8ccf0034, 0xa220000a, 0x8f8e008c, 0xae2f0004,
-0x3c050080, 0x91cb003f, 0xa239000c, 0x8e28000c,
-0x3c0dff9f, 0xa22b000b, 0x1051025, 0x35a3ffff,
-0x3c13ffef, 0x8f8e008c, 0x433824, 0x366affff,
-0xea4824, 0xae29000c, 0x8dc40014, 0x95d80012,
-0x8f860088, 0xae240010, 0x8dcc0014, 0xae200018,
-0xae200020, 0xae2c0014, 0xae200024, 0x8ddf0018,
-0x330c3fff, 0xc9180, 0xae3f0028, 0x8dcf0008,
-0x246c821, 0x330b0001, 0xae2f0030, 0x8dc3000c,
-0x8f930020, 0x1941c2, 0xb2b80, 0x1056821,
-0x24020002, 0x3c0a8008, 0xa62d001c, 0xa6200034,
-0xae23002c, 0x35470080, 0xa2620000, 0x94e9005c,
-0x8f990020, 0x3c044200, 0x313fffff, 0x3e43025,
-0xaf260004, 0x8f98008c, 0x240e0001, 0x2402c000,
-0x8f120038, 0x24060034, 0xaf320018, 0x8f0f0034,
-0x3c128008, 0x36580080, 0xaf2f001c, 0xaf20000c,
+0x8c780000, 0x33160020, 0x12c0fffd, 0x3c118008,
+0x96220054, 0x3c158000, 0x3c068008, 0x304e0001,
+0xe18c0, 0x757821, 0x8dec0400, 0x3c070800,
+0x8ce70044, 0x3c040020, 0xaccc0048, 0x8df40404,
+0x240b0001, 0xacd4004c, 0x10eb0260, 0xaea40030,
+0x96390052, 0x3c050800, 0x8ca50040, 0xb99021,
+0xa6320052, 0x963f0054, 0x27ed0001, 0xa62d0054,
+0x96260054, 0x30c4ffff, 0x5487ff2f, 0x8fb40010,
+0x30a5ffff, 0xe0011f4, 0xa6200054, 0x3c070800,
+0x8ce70024, 0x963e0052, 0x47b823, 0x3d74823,
+0xa6290052, 0xa001219, 0x8fb40010, 0x8ce20040,
+0xa0012be, 0x0, 0x92240001, 0x24070001,
+0x3085007f, 0x14a7001c, 0x97ad0026, 0x8e2b0014,
+0x240cc000, 0x316a3fff, 0x1ac4824, 0x3c060800,
+0x8cc60060, 0x12a4025, 0x31043fff, 0x86882b,
+0x12200011, 0xa7a80026, 0x3c050800, 0x8ca50058,
+0x8f9100a0, 0x43980, 0x2402ff80, 0xb11821,
+0x67f821, 0x3e2f024, 0x33f8007f, 0x3c128000,
+0x3c19800e, 0xae5e002c, 0x3197021, 0x91d0000d,
+0x360f0004, 0xa1cf000d, 0xe001028, 0x24120001,
+0x24110001, 0x3c1e8000, 0x8fc40100, 0xe000fce,
+0x2e02821, 0x8fc40100, 0xe000fde, 0x2c02821,
+0x1620ff55, 0x8f8b00a4, 0xa001286, 0x13802b,
+0x8f8600a4, 0x90c80001, 0x31040020, 0x10800191,
+0x24100001, 0x3c048008, 0x348b0080, 0x916a007c,
+0x8f9e0034, 0xafa0002c, 0x31490001, 0x1120000f,
+0xafb00028, 0x8ccd0014, 0x8c8e0060, 0x1ae602b,
+0x15800002, 0x1a03821, 0x8c870060, 0x3c188008,
+0x37030080, 0x8c700070, 0xf0782b, 0x15e00002,
+0xe02021, 0x8c640070, 0xafa4002c, 0x3c028008,
+0x34450080, 0x8cd20014, 0x8cbf0070, 0x25fc82b,
+0x17200002, 0x2402021, 0x8ca40070, 0x8fa7002c,
+0x871823, 0x10600003, 0xafa30030, 0x24050002,
+0xafa50028, 0x8fa40028, 0x264882b, 0x162000ba,
+0x1821, 0x8cd00038, 0x8fce000c, 0x3c0f0080,
+0xafd00000, 0x8ccd0034, 0x3c0cff9f, 0x1cf5825,
+0xafcd0004, 0x90ca003f, 0x3586ffff, 0x1662024,
+0x3c090020, 0x3c08ffef, 0xa3ca000b, 0x893825,
+0x3511ffff, 0xf11824, 0x3c050008, 0x8f8700a4,
+0x65c825, 0xafd9000c, 0x8ce20014, 0xafc00018,
+0x8fa60030, 0xafc20014, 0x8cf80018, 0x8fb0002c,
+0x3c1ffffb, 0xafd8001c, 0x8cef0008, 0x37f2ffff,
+0x3326824, 0xafcf0024, 0x8cec000c, 0x2067021,
+0xafcd000c, 0xa7c00038, 0xa7c0003a, 0xafce002c,
+0xafcc0020, 0xafc00028, 0x8cea0014, 0x8fab002c,
+0x14b4823, 0x1264023, 0x11000011, 0xafc80010,
+0x90eb003d, 0x8fc90004, 0x8fc80000, 0xb5100,
+0x12a2821, 0x1021, 0xaa882b, 0x1021821,
+0x71f821, 0xafc50004, 0xafdf0000, 0x90f2003d,
+0xa3d2000a, 0x8f9900a4, 0x97380006, 0xa7d80008,
+0x8f910038, 0x24080002, 0x3c038008, 0xa2280000,
+0x34650080, 0x94bf005c, 0x8fa4002c, 0x33f0ffff,
+0xe000ff4, 0x8f920038, 0x2cb80, 0x8f8500a4,
+0x2197825, 0x3c184200, 0x1f87025, 0xae4e0004,
+0x8f840038, 0x8cad0038, 0xac8d0018, 0x8cac0034,
+0xac8c001c, 0xac80000c, 0xac800010, 0xa4800014,
+0xa4800016, 0xa4800020, 0xa4800022, 0xac800024,
+0x90a6003f, 0x8fa7002c, 0xa4860002, 0x50e00192,
+0x24070001, 0x8fa20030, 0x50400002, 0x90a2003d,
+0x90a2003e, 0x244a0001, 0xa08a0001, 0x8f840038,
+0x8fa9002c, 0xac890008, 0x3c128008, 0x364d0080,
+0x91ac007c, 0x31860002, 0x14c00002, 0x24070034,
+0x24070030, 0x8f8500a4, 0x3c198008, 0x373f0080,
+0x90b00000, 0x93f9007c, 0x240e0004, 0xa0900030,
+0x8f8f00a4, 0x8fb8002c, 0x8f8d0038, 0x91f20001,
+0x33040003, 0x1c46023, 0xa1b20031, 0x8f8e0038,
+0x8f8600a4, 0x2402c000, 0x95ca0032, 0x94c90012,
+0x8fab002c, 0x1424024, 0x31233fff, 0x1038825,
+0xa5d10032, 0x91d00032, 0x31850003, 0xebf821,
+0x3218003f, 0x370f0040, 0xa1cf0032, 0x8fa4002c,
+0x3e53821, 0x33280004, 0x10800002, 0x8f850038,
+0xe83821, 0x3c0a8008, 0xaca70034, 0x35490100,
+0x8d2800d0, 0x8fa3002c, 0x2419ffbf, 0xaca80038,
+0x90b1003c, 0x2c640001, 0x240fffdf, 0x3227007f,
+0xa0a7003c, 0x8f980038, 0x49140, 0x931f003c,
+0x3f98024, 0xa310003c, 0x8f8c0038, 0x918e003c,
+0x1cf6824, 0x1b23025, 0xa186003c, 0x8f8900a4,
+0x8f880038, 0x8d2b0020, 0xad0b0040, 0x8d220024,
+0xad020044, 0x8d2a0028, 0xad0a0048, 0x8d23002c,
+0xe001013, 0xad03004c, 0x8fb10028, 0x24070002,
+0x12270011, 0x8fa30028, 0x3282b, 0x58023,
+0x2709824, 0x608021, 0x609021, 0xa00126f,
+0x10882b, 0x96290012, 0x8f8400a0, 0x9021,
+0x3125ffff, 0xa7a90018, 0xe000fc2, 0x24110001,
+0xa00131d, 0x3c1e8000, 0x3c0b8000, 0x3c128008,
+0x8d640100, 0x92490008, 0x8f92ff34, 0xe000f99,
+0x3125007f, 0x8f990038, 0x8fa70028, 0x8fa40030,
+0xa3270000, 0x965f005c, 0x33f0ffff, 0xe000ff4,
+0x8f910038, 0x26b80, 0x20d8025, 0x3c084200,
+0x8f8d00a4, 0x2085025, 0xae2a0004, 0x8da50038,
+0x8f8a0038, 0x7821, 0xf1100, 0xad450018,
+0x8db80034, 0x3c047fff, 0x3488ffff, 0xad58001c,
+0x91a6003e, 0x8d4c001c, 0x8d490018, 0x61900,
+0x67702, 0x183c821, 0x4e5825, 0x323882b,
+0x12b3821, 0xf1f821, 0xad59001c, 0xad5f0018,
+0xad40000c, 0xad400010, 0x91b0003e, 0x8fa40030,
+0x24090005, 0xa5500014, 0x95a50004, 0x2419c000,
+0x884024, 0xa5450016, 0x91b8003e, 0xa5580020,
+0x95af0004, 0xa54f0022, 0xad400024, 0x91ae003f,
+0xa54e0002, 0x91a6003e, 0x91ac003d, 0x1861023,
+0x244b0001, 0xa14b0001, 0x8f910038, 0x8fa30030,
+0x3c028008, 0x344b0100, 0xae230008, 0xa2290030,
+0x8f8c0038, 0x8f8700a4, 0x959f0032, 0x94f00012,
+0x2407ffbf, 0x33fc024, 0x32053fff, 0x3057825,
+0xa58f0032, 0x918e0032, 0x2418ffdf, 0x31cd003f,
+0x35a60040, 0xa1860032, 0x8f910038, 0x240dffff,
+0x240cff80, 0xae200034, 0x8d6a00d0, 0xae2a0038,
+0x9223003c, 0x3069007f, 0xa229003c, 0x8f900038,
+0x3c038000, 0x9219003c, 0x327f824, 0xa21f003c,
+0x8f8e0038, 0x91c5003c, 0xb87824, 0xa1cf003c,
+0x8f8a0038, 0x3c0e8008, 0xad4d0040, 0x8fa6002c,
+0xad460044, 0x91420048, 0x4c5825, 0xa14b0048,
+0x8f900038, 0x8f9900a4, 0x8e090048, 0x1238824,
+0x2283825, 0xae070048, 0x933f003e, 0xa21f004c,
+0x8f9800a4, 0x8f8f0038, 0x97050004, 0xa5e5004e,
+0xe000381, 0x8dc50060, 0x9246007c, 0x8fac0030,
+0x26940, 0x29100, 0x402821, 0x30cb0002,
+0x1b21021, 0x156000aa, 0x1823021, 0x3c0e8008,
+0x35c20080, 0x904c007c, 0x31830004, 0x10600003,
+0x8fb90030, 0x57880, 0xcf3021, 0x241f0004,
+0x8f910038, 0x332d0003, 0x3ed8023, 0x32080003,
+0xc85021, 0xae2a0034, 0x3c188000, 0xa7c50038,
+0x3c068008, 0x8f040100, 0x90de0008, 0xe000fde,
+0x33c5007f, 0xe001013, 0x0, 0xa00140d,
+0x8fa30028, 0x8f980034, 0x8cc90038, 0x241f0003,
+0xa7000008, 0xaf090000, 0x8cc50034, 0xa300000a,
+0x8f9900a4, 0xaf050004, 0x3c080080, 0x932d003f,
+0xa31f000c, 0x8f0a000c, 0x3c02ff9f, 0xa30d000b,
+0x148f025, 0x3451ffff, 0x3c12ffef, 0x8f9900a4,
+0x3d17024, 0x3646ffff, 0x1c61824, 0xaf03000c,
+0x8f2c0014, 0x97290012, 0x8f8400a0, 0xaf0c0010,
+0x8f2f0014, 0xaf000018, 0xaf000020, 0xaf0f0014,
+0xaf000024, 0x8f270018, 0x312f3fff, 0xf5980,
+0xaf070028, 0x8f250008, 0x164f821, 0x312d0001,
+0xaf050030, 0x8f31000c, 0x8f920038, 0x1f51c2,
+0xd4380, 0x1481021, 0x241e0002, 0x3c068008,
+0xa702001c, 0xa7000034, 0xaf11002c, 0xa25e0000,
+0x34d20080, 0x964e005c, 0x8f990038, 0x3c034200,
+0x31ccffff, 0x1833825, 0xaf270004, 0x8f8b00a4,
+0x24050001, 0x2402c000, 0x8d640038, 0x24070034,
+0xaf240018, 0x8d690034, 0xaf29001c, 0xaf20000c,
0xaf200010, 0xa7200014, 0xa7200016, 0xa7200020,
-0xa7200022, 0xaf200024, 0xa7300002, 0xa32e0001,
-0x8f8d0020, 0x8f8b008c, 0xadb00008, 0x91680000,
-0xa1a80030, 0x8f91008c, 0x8f830020, 0x92250001,
-0xa0650031, 0x8f9f0020, 0x97f30032, 0x2625024,
-0x14c3825, 0xa7e70032, 0x93e90032, 0x3124003f,
-0xa3e40032, 0x930f007c, 0x31ee0002, 0x15c00002,
-0x8f840020, 0x24060030, 0x3c0e8008, 0xac860034,
-0x35d10100, 0x8e3900c0, 0x2403ffbf, 0x2008821,
-0xac990038, 0x908b003c, 0x10802b, 0x3165007f,
-0xa085003c, 0x8f8d0020, 0x91a8003c, 0x1031024,
-0xa1a2003c, 0x8f870020, 0x90f3003c, 0x366a0020,
-0xa0ea003c, 0x8f9f008c, 0x8f920020, 0x8fe90020,
-0xae490040, 0x8fe40024, 0xae440044, 0x8fec0028,
-0xae4c0048, 0x8fe6002c, 0xe000eca, 0xae46004c,
-0xa00104f, 0x0, 0xa0010c0, 0x8ce20040,
-0x24480001, 0xa0880001, 0x8f850020, 0x8fa40024,
-0xaca40008, 0xa00122f, 0x3c118008, 0x94cb0052,
-0x3c080800, 0x8d080024, 0x10b1021, 0xa4c20052,
-0xa000ffb, 0x8fb30010, 0x27bdffe0, 0x3c0d8008,
-0xafb20018, 0xafb00010, 0xafbf001c, 0xafb10014,
-0x35b20080, 0x8e4c0018, 0x35a80100, 0x964b0006,
-0x95a70050, 0x910900ec, 0xc5602, 0x1672823,
-0x3143007f, 0x312600ff, 0x24020003, 0xa3830090,
-0xaf840088, 0x10c2001b, 0x30b0ffff, 0x910600ec,
-0x24120005, 0x30c200ff, 0x10520033, 0x0,
-0x16000009, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
+0xa7200022, 0xaf200024, 0xa7300002, 0xa3250001,
+0x8f880038, 0x8f9f00a4, 0xad100008, 0x93ed0000,
+0xa10d0030, 0x8f8a00a4, 0x8f980038, 0x91510001,
+0xa3110031, 0x8f8b0038, 0x957e0032, 0x3c27024,
+0x1cf6025, 0xa56c0032, 0x91630032, 0x3064003f,
+0xa1640032, 0x9249007c, 0x31250002, 0x14a00002,
+0x8f840038, 0x24070030, 0x3c198008, 0xac870034,
+0x37320100, 0x8e5f00d0, 0x240affbf, 0x2009021,
+0xac9f0038, 0x908d003c, 0x31a8007f, 0xa088003c,
+0x8f9e0038, 0x93c2003c, 0x4a8824, 0xa3d1003c,
+0x8f830038, 0x10882b, 0x9066003c, 0x34ce0020,
+0xa06e003c, 0x8f8400a4, 0x8f980038, 0x8c8c0020,
+0xaf0c0040, 0x8c8f0024, 0xaf0f0044, 0x8c870028,
+0xaf070048, 0x8c8b002c, 0xaf0b004c, 0xe001013,
+0x3c1e8000, 0xa001270, 0x0, 0x94c80052,
+0x3c0a0800, 0x8d4a0024, 0x1488821, 0xa4d10052,
+0xa001219, 0x8fb40010, 0xa0870001, 0x8f840038,
+0x240b0001, 0xac8b0008, 0xa0013be, 0x3c128008,
+0x52080, 0xa0014a2, 0xc43021, 0x27bdffe0,
+0x3c0d8008, 0xafb20018, 0xafb00010, 0xafbf001c,
+0xafb10014, 0x35b20080, 0x8e4c0018, 0x35a80100,
+0x964b0006, 0x95a70050, 0x910900fc, 0xc5602,
+0x1672823, 0x3143007f, 0x312600ff, 0x24020003,
+0xaf8300a8, 0xaf8400a0, 0x10c2001b, 0x30b0ffff,
+0x910600fc, 0x24120005, 0x30c200ff, 0x10520033,
+0x0, 0x16000009, 0x8fbf001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x240d0c00, 0x3c0c8000,
+0x27bd0020, 0x3e00008, 0xad8d0024, 0xe0011fb,
+0x2002021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
0x8fb00010, 0x240d0c00, 0x3c0c8000, 0x27bd0020,
-0x3e00008, 0xad8d0024, 0xe000fde, 0x2002021,
-0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x240d0c00, 0x3c0c8000, 0x27bd0020, 0x3e00008,
-0xad8d0024, 0x96580078, 0x9651007a, 0x924e007d,
-0x2387826, 0x31e8ffff, 0x31c400c0, 0x14800009,
-0x2d110001, 0x16000037, 0x0, 0x5620ffe2,
-0x8fbf001c, 0xe000edf, 0x0, 0xa0013d3,
-0x8fbf001c, 0x1620ffda, 0x0, 0xe000edf,
-0x0, 0x1440ffd8, 0x8fbf001c, 0x16000022,
-0x0, 0x925f007d, 0x33e2003f, 0xa242007d,
-0xa0013d3, 0x8fbf001c, 0x950900da, 0x8f860064,
-0x802821, 0x24040005, 0xe000682, 0x3130ffff,
-0x97830076, 0x3c048000, 0x2465ffff, 0xa7850076,
-0x8c8a01b8, 0x540fffe, 0x0, 0xac800180,
-0x8fbf001c, 0xac900184, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3c076013, 0x3c0b1000, 0x240d0c00,
-0x3c0c8000, 0x27bd0020, 0xac870188, 0xac8b01b8,
-0x3e00008, 0xad8d0024, 0xe000fde, 0x2002021,
-0x5040ffb1, 0x8fbf001c, 0x925f007d, 0xa001400,
-0x33e2003f, 0xe000fde, 0x2002021, 0x1440ffaa,
-0x8fbf001c, 0x12200007, 0x0, 0x9259007d,
-0x3330003f, 0x36020040, 0xa242007d, 0xa0013d3,
-0x8fbf001c, 0xe000edf, 0x0, 0x5040ff9e,
-0x8fbf001c, 0x9259007d, 0x3330003f, 0xa00142f,
-0x36020040, 0x411c0, 0x3e00008, 0x24420240,
-0x3c050006, 0x851025, 0x3c038000, 0xac620030,
-0x0, 0x0, 0x0, 0x3c058000,
-0x8ca70000, 0x30e60010, 0x10c0fffd, 0x0,
-0x8cab003c, 0x8caa003c, 0x1644821, 0x12a402b,
-0x11000004, 0x3c068000, 0x8cad0038, 0x25ac0001,
-0xacac0038, 0x8ccf003c, 0x1e47021, 0x3e00008,
-0xacce003c, 0x27bdffd0, 0xafb20018, 0xafb00010,
-0xafbf0028, 0xafb50024, 0xafb40020, 0xafb3001c,
-0xafb10014, 0xa09021, 0x14a00012, 0x808021,
-0x8f820024, 0x21880, 0x14600037, 0x24040010,
-0xe00143d, 0x0, 0x8fbf0028, 0x8fb50024,
-0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x1021, 0x27bd0030, 0x3e00008,
-0xaf800024, 0x10a0001e, 0x8821, 0x3c138000,
-0x24140020, 0xa00147c, 0x3c150005, 0x26310004,
-0x232502b, 0x11400017, 0x2401021, 0x8f880024,
-0x8e070000, 0x24040080, 0x84880, 0x1331821,
-0x25060001, 0xac670400, 0x26100004, 0x14d4fff3,
-0xaf860024, 0xe00143d, 0x0, 0xae750030,
-0x0, 0x0, 0x0, 0x0,
-0x26310004, 0x232502b, 0x1540ffec, 0xaf800024,
-0x2401021, 0x8fbf0028, 0x8fb50024, 0x8fb40020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0030, 0x32023, 0x3085000f,
-0xa001465, 0x652021, 0x27bdffd8, 0x3c038000,
-0xa03821, 0xac670038, 0xafb10014, 0xac66003c,
-0x808821, 0x3c060022, 0xac660030, 0xafb00010,
-0xac710028, 0x3c10800c, 0x3c04800c, 0x24050070,
-0xafbf0024, 0xafb40020, 0xafb3001c, 0xe001456,
-0xafb20018, 0x26040080, 0xe001456, 0x24050080,
-0x26040100, 0xe001456, 0x240500f0, 0x3c020800,
-0x8c420064, 0x10400013, 0x8021, 0x3c148000,
-0x2413ff80, 0x3c12800c, 0xe00143a, 0x2002021,
-0x514821, 0x312a007f, 0x1334024, 0x1522021,
-0x24050050, 0xae880028, 0xe001456, 0x26100001,
-0x3c050800, 0x8ca50064, 0x205202b, 0x1480fff2,
-0x0, 0x3c060800, 0x8cc60060, 0x10c00015,
-0x8021, 0x3c148000, 0x2413ff80, 0x3c12800c,
-0x3c190800, 0x8f390058, 0x10c180, 0x24050040,
-0x3317821, 0x1f86821, 0x31ae007f, 0x1b36024,
-0x1d22021, 0xae8c0028, 0xe001456, 0x26100001,
-0x3c060800, 0x8cc60060, 0x206582b, 0x1560fff0,
-0x0, 0x3c100800, 0x8e10005c, 0x2414ff80,
-0x3c1f800c, 0x2119821, 0x2749024, 0x3262007f,
-0x3c118000, 0x5f2021, 0xae320028, 0xe001456,
-0x62840, 0x8fbf0024, 0x8fb40020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x2021,
-0x2821, 0xa001456, 0x27bd0028, 0x8f83003c,
-0x8c620004, 0x10400003, 0x0, 0x3e00008,
-0x0, 0x8c640010, 0x8c650008, 0xa00149f,
-0x8c66000c, 0x0 };
-u32 bce_CP_b09FwData[(0x84/4) + 1] = {
-0x0,
-0x1b, 0xf, 0xa, 0x8,
-0x6, 0x5, 0x5, 0x4,
-0x4, 0x3, 0x3, 0x3,
-0x3, 0x3, 0x2, 0x2,
+0x3e00008, 0xad8d0024, 0x96580078, 0x9651007a,
+0x924e007d, 0x2387826, 0x31e8ffff, 0x31c400c0,
+0x14800009, 0x2d110001, 0x16000037, 0x0,
+0x5620ffe2, 0x8fbf001c, 0xe0010d1, 0x0,
+0xa00156a, 0x8fbf001c, 0x1620ffda, 0x0,
+0xe0010d1, 0x0, 0x1440ffd8, 0x8fbf001c,
+0x16000022, 0x0, 0x925f007d, 0x33e2003f,
+0xa242007d, 0xa00156a, 0x8fbf001c, 0x950900ea,
+0x8f860080, 0x802821, 0x24040005, 0xe000725,
+0x3130ffff, 0x97830092, 0x3c048000, 0x2465ffff,
+0xa7850092, 0x8c8a01b8, 0x540fffe, 0x0,
+0xac800180, 0x8fbf001c, 0xac900184, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x3c076013, 0x3c0b1000,
+0x240d0c00, 0x3c0c8000, 0x27bd0020, 0xac870188,
+0xac8b01b8, 0x3e00008, 0xad8d0024, 0xe0011fb,
+0x2002021, 0x5040ffb1, 0x8fbf001c, 0x925f007d,
+0xa001597, 0x33e2003f, 0xe0011fb, 0x2002021,
+0x1440ffaa, 0x8fbf001c, 0x12200007, 0x0,
+0x9259007d, 0x3330003f, 0x36020040, 0xa242007d,
+0xa00156a, 0x8fbf001c, 0xe0010d1, 0x0,
+0x5040ff9e, 0x8fbf001c, 0x9259007d, 0x3330003f,
+0xa0015c6, 0x36020040, 0x0 };
+u32 bce_CP_b09FwData[(0x84/4) + 1] = {
+0x0, 0x1b, 0xf,
+0xa, 0x8, 0x6, 0x5,
+0x5, 0x4, 0x4, 0x3,
+0x3, 0x3, 0x3, 0x3,
0x2, 0x2, 0x2, 0x2,
0x2, 0x2, 0x2, 0x2,
0x2, 0x2, 0x2, 0x2,
-0x2, 0x1, 0x1, 0x1,
-0x0 };
-u32 bce_CP_b09FwRodata[(0x16c/4) + 1] = {
+0x2, 0x2, 0x2, 0x1,
+0x1, 0x1, 0x0 };
+u32 bce_CP_b09FwRodata[(0x1c0/4) + 1] = {
0x80080100,
-0x80080080, 0x80080000, 0x8001800, 0x8001800,
-0x8001838, 0x8001838, 0x800184c, 0x800181c,
-0x8001a74, 0x8001a40, 0x8001acc, 0x8001acc,
-0x8001b54, 0x8001a84, 0x80080240, 0x80021c4,
-0x8002010, 0x80021ec, 0x8002284, 0x80023d4,
-0x8002420, 0x8002544, 0x800244c, 0x80024d0,
-0x8002080, 0x80029f8, 0x800299c, 0x800202c,
-0x800202c, 0x800202c, 0x80025b8, 0x80025b8,
-0x800202c, 0x800202c, 0x8002874, 0x800202c,
-0x800202c, 0x800202c, 0x800202c, 0x80028d4,
-0x800202c, 0x800202c, 0x800202c, 0x800202c,
-0x800202c, 0x800202c, 0x800202c, 0x800202c,
-0x800202c, 0x800202c, 0x800202c, 0x800202c,
-0x800202c, 0x800202c, 0x8002440, 0x800202c,
-0x800202c, 0x8002944, 0x800202c, 0x800202c,
-0x800202c, 0x800202c, 0x800202c, 0x800202c,
-0x800202c, 0x800202c, 0x800202c, 0x800202c,
-0x800202c, 0x800202c, 0x800202c, 0x800202c,
-0x800202c, 0x800202c, 0x800202c, 0x8002798,
-0x800202c, 0x800202c, 0x8002700, 0x800265c,
-0x80037c0, 0x8003794, 0x8003760, 0x8003734,
-0x8003714, 0x80036c8, 0x80080100, 0x80080080,
-0x80080000, 0x80080080, 0x0 };
-u32 bce_CP_b09FwBss[(0x19c/4) + 1] = { 0x0 };
-u32 bce_CP_b09FwSbss[(0x91/4) + 1] = { 0x0 };
-u32 bce_CP_b09FwSdata[(0x0/4) + 1] = { 0x0 };
+0x80080080, 0x80080000, 0xc00, 0x3080,
+0x80011d0, 0x800127c, 0x8001294, 0x80012a8,
+0x80012bc, 0x80011d0, 0x80011d0, 0x80012f0,
+0x800132c, 0x8001340, 0x8001388, 0x8001a8c,
+0x8001a8c, 0x8001ac4, 0x8001ac4, 0x8001ad8,
+0x8001aa8, 0x8001d00, 0x8001ccc, 0x8001d58,
+0x8001d58, 0x8001de0, 0x8001d10, 0x80080240,
+0x8002734, 0x800256c, 0x800275c, 0x80027f4,
+0x800293c, 0x8002988, 0x8002aac, 0x80029b4,
+0x8002a38, 0x80025dc, 0x8002edc, 0x8002ea4,
+0x8002588, 0x8002588, 0x8002588, 0x8002b20,
+0x8002b20, 0x8002588, 0x8002588, 0x8002dd0,
+0x8002588, 0x8002588, 0x8002588, 0x8002588,
+0x8002e0c, 0x8002588, 0x8002588, 0x8002588,
+0x8002588, 0x8002588, 0x8002588, 0x8002588,
+0x8002588, 0x8002588, 0x8002588, 0x8002588,
+0x8002588, 0x8002588, 0x8002588, 0x80029a8,
+0x8002588, 0x8002588, 0x8002e68, 0x8002588,
+0x8002588, 0x8002588, 0x8002588, 0x8002588,
+0x8002588, 0x8002588, 0x8002588, 0x8002588,
+0x8002588, 0x8002588, 0x8002588, 0x8002588,
+0x8002588, 0x8002588, 0x8002588, 0x8002588,
+0x8002cf4, 0x8002588, 0x8002588, 0x8002c68,
+0x8002bc4, 0x8003ce4, 0x8003cb8, 0x8003c84,
+0x8003c58, 0x8003c38, 0x8003bec, 0x80080100,
+0x80080080, 0x80080000, 0x80080080, 0x8004c64,
+0x8004c9c, 0x8004be4, 0x8004c64, 0x8004c64,
+0x80049b8, 0x8004c64, 0x8005050, 0x0 };
+u32 bce_CP_b09FwBss[(0x19c/4) + 1] = { 0x0 };
+u32 bce_CP_b09FwSbss[(0xa8/4) + 1] = { 0x0 };
+u32 bce_CP_b09FwSdata[(0x0/4) + 1] = { 0x0 };
u32 bce_xi_rv2p_proc1[] = {
- 0x00000010, 0xb1800002,
- 0x0000001f, 0x05030100,
+ 0x00000010, 0xb1800006,
+ 0x0000001f, 0x05060011,
+ 0x00000008, 0x0500ffff,
+ 0x00000018, 0x00020000,
+ 0x00000008, 0x050000ff,
+ 0x00000018, 0x00020000,
0x00000008, 0xac000001,
- 0x00000000, 0x05000000,
+ 0x00000008, 0x07800000,
0x0000000c, 0x2f800001,
0x00000000, 0x2b000000,
0x00000000, 0x2b800000,
- 0x00000010, 0x203f006c,
+ 0x00000010, 0x91e10002,
+ 0x00000008, 0xac000001,
+ 0x00000010, 0x203f003b,
0x00000010, 0x213f0003,
- 0x00000010, 0x20bf003b,
+ 0x00000010, 0x20bf0015,
0x00000018, 0x8000fffd,
- 0x00000010, 0xb1b8b015,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c380000,
- 0x00000008, 0x2c800000,
- 0x00000008, 0x2d000000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000007c,
- 0x00000008, 0x2d80011c,
- 0x00000008, 0x02000001,
- 0x00000010, 0x91de0000,
- 0x0000000f, 0x42e0001c,
- 0x00000010, 0x91840a17,
- 0x00000010, 0x08660016,
- 0x0000000c, 0x29800002,
0x0000000c, 0x1f800002,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a00000f,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ffe8,
- 0x00000008, 0x02000001,
- 0x0000000f, 0x42e0001c,
- 0x00000010, 0x91840a19,
- 0x00000008, 0x2c800006,
- 0x00000008, 0x2d000006,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800106,
- 0x00000018, 0x80000070,
- 0x00000010, 0x08660013,
- 0x00000018, 0x8000fff1,
+ 0x00000018, 0x8000fff9,
0x00000008, 0xb1000001,
0x00000008, 0x2c80010c,
0x00000008, 0x2d000008,
0x00000008, 0x2d800001,
- 0x00000018, 0x80000069,
+ 0x00000018, 0x8000003c,
0x0000000b, 0x2fdf0002,
0x0000000c, 0x1f800002,
0x00000000, 0x2c070000,
0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffd3,
+ 0x00000018, 0x8000ffef,
0x0000000b, 0x2fdf0002,
0x0000000c, 0x1f800000,
0x00000000, 0x2c070000,
0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffcd,
- 0x0000000c, 0x1f800002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffca,
- 0x0000000c, 0x29800002,
+ 0x00000018, 0x8000ffea,
0x0000000c, 0x1f800002,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a000005,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ffc4,
- 0x00000008, 0x02240045,
+ 0x00000018, 0x8000ffe8,
+ 0x00000008, 0x02240025,
0x00000018, 0x00040000,
- 0x00000018, 0x8000001c,
- 0x00000018, 0x8000001e,
- 0x00000018, 0x80000052,
- 0x00000018, 0x8000009e,
- 0x00000018, 0x8000009d,
0x00000018, 0x80000000,
+ 0x00000018, 0x8000001b,
+ 0x00000018, 0x80000042,
0x00000018, 0x80000000,
0x00000018, 0x80000000,
0x00000018, 0x80000000,
@@ -12820,88 +13299,75 @@ u32 bce_xi_rv2p_proc1[] = {
0x00000018, 0x80000000,
0x00000018, 0x80000000,
0x00000018, 0x80000000,
- 0x00000018, 0x800000e4,
0x00000018, 0x80000000,
0x00000018, 0x80000000,
- 0x00000018, 0x80000015,
- 0x00000018, 0x8000001b,
0x00000018, 0x80000000,
- 0x00000018, 0x800000b4,
- 0x00000018, 0x8000002e,
- 0x00000018, 0x800000e4,
- 0x00000018, 0x8000010f,
+ 0x00000018, 0x8000008e,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000008d,
+ 0x00000018, 0x800000b7,
+ 0x00000018, 0x80000084,
0x00000018, 0x800000da,
- 0x00000018, 0x80000133,
- 0x00000018, 0x8000003b,
+ 0x00000018, 0x8000002b,
0x00000018, 0x80000000,
- 0x00000018, 0x80000071,
- 0x0000000c, 0x1f800001,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffa3,
+ 0x00000018, 0x8000006b,
0x00000010, 0x91d40000,
0x0000000c, 0x29800001,
0x0000000c, 0x1f800001,
0x00000008, 0x2a000002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff9d,
- 0x00000010, 0x91d40000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000000, 0x29420000,
- 0x00000008, 0x2a000002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff96,
- 0x00000018, 0x8000ff95,
- 0x00000010, 0xb1bcb00a,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c3c0000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x80000016,
- 0x00000018, 0x800000ac,
- 0x00000010, 0x2c6201ba,
- 0x00000018, 0x80000005,
- 0x00000008, 0x2c80010d,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x0000000c, 0x29800000,
- 0x0000000c, 0x1f800000,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a000006,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ff80,
- 0x00000010, 0x91d40000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000008, 0x2a00000b,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff7a,
+ 0x00000008, 0x07800000,
+ 0x00000018, 0x8000ffc4,
+ 0x00000008, 0x03800100,
+ 0x00000010, 0xb73c0e00,
+ 0x00000018, 0x80000000,
0x00000018, 0x00020000,
0x00000000, 0x06820000,
- 0x00000010, 0xb18a0006,
- 0x00000000, 0x860c1400,
- 0x00000010, 0xb18c0004,
- 0x00000000, 0x05000000,
+ 0x00000010, 0xb18f0004,
+ 0x00000010, 0xb18f1403,
0x00000008, 0x2a000001,
0x00000010, 0x91d40000,
+ 0x00000000, 0x07801400,
0x00000018, 0x000d0000,
0x00000000, 0x05020000,
0x00000010, 0x91de0000,
0x00000018, 0x000a0000,
+ 0x00000000, 0x06820000,
+ 0x00000010, 0x91de0000,
+ 0x00000009, 0x0561ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x30e1ffff,
+ 0x00000018, 0x8000ffa9,
+ 0x00000001, 0x05611400,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0xb0e10001,
+ 0x00000018, 0x000d0000,
+ 0x00000000, 0x06820000,
+ 0x00000010, 0x91de0000,
+ 0x00000009, 0x0562ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x3162ffff,
+ 0x00000018, 0x8000ff9f,
+ 0x00000001, 0x05621400,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0xb1620001,
+ 0x00000018, 0x000d0000,
0x00000010, 0xb1a0b013,
0x0000000b, 0x2fdf0002,
0x00000000, 0x2c200000,
0x00000008, 0x2c800000,
0x00000008, 0x2d000000,
0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ffee,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ffdb,
0x00000008, 0x2d80011c,
0x00000010, 0x001f0000,
- 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000ffe2,
0x0000000f, 0x47600008,
0x0000000f, 0x060e0001,
0x00000000, 0x0f580000,
@@ -12909,7 +13375,7 @@ u32 bce_xi_rv2p_proc1[] = {
0x00000000, 0x0ae50000,
0x00000009, 0x0b66ffff,
0x00000000, 0x0d610000,
- 0x00000018, 0x80000013,
+ 0x00000018, 0x80000015,
0x0000000f, 0x47600008,
0x0000000b, 0x2fdf0002,
0x00000008, 0x2c800000,
@@ -12919,43 +13385,53 @@ u32 bce_xi_rv2p_proc1[] = {
0x0000000f, 0x060e0001,
0x00000010, 0x001f0000,
0x00000000, 0x0f580000,
- 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000ffd0,
0x00000000, 0x0a640000,
0x00000000, 0x0ae50000,
0x00000009, 0x0b66ffff,
0x00000000, 0x0d610000,
0x00000000, 0x02620000,
+ 0x00000000, 0x02e00000,
0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x30050000,
0x00000000, 0x31040000,
0x00000000, 0x309a0000,
+ 0x00000010, 0x0060000a,
+ 0x00000008, 0x05160001,
+ 0x00000010, 0xba9a1403,
+ 0x00000000, 0x03000000,
+ 0x00000018, 0x80000006,
+ 0x00000018, 0x8000ff6c,
+ 0x00000010, 0xb6061404,
+ 0x00000008, 0x03060001,
+ 0x00000008, 0x2a000001,
+ 0x00000018, 0x8000ff71,
0x00000000, 0x0c961800,
0x00000009, 0x0c99ffff,
0x00000004, 0xcc993400,
- 0x00000010, 0xb1963202,
+ 0x00000010, 0xba992c02,
0x00000008, 0x0f800000,
0x0000000c, 0x29800001,
- 0x00000010, 0x00220002,
0x0000000c, 0x29520001,
0x0000000c, 0x29520000,
+ 0x00000008, 0x22800002,
0x00000008, 0x0200000e,
0x00000008, 0x0280001a,
0x00000010, 0xb1c40a02,
0x00000008, 0x02000003,
- 0x00000008, 0x22000001,
0x0000000c, 0x1f800001,
0x00000000, 0x2adf0000,
0x00000000, 0x2a000800,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ff36,
+ 0x00000018, 0x8000ff60,
0x0000000b, 0x2fdf0002,
0x00000010, 0x91d40000,
0x00000008, 0x2a000001,
0x00000000, 0x2c200000,
+ 0x00000010, 0x91d40000,
0x00000008, 0x2c800000,
0x00000008, 0x2d000000,
0x00000008, 0x2d80011c,
- 0x00000010, 0x91d40000,
- 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000ff9f,
0x00000008, 0x2c800006,
0x00000008, 0x2d000006,
0x00000000, 0x30800000,
@@ -12966,100 +13442,19 @@ u32 bce_xi_rv2p_proc1[] = {
0x00000010, 0x91de0000,
0x00000000, 0x2adf0000,
0x00000008, 0x2a000010,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff21,
- 0x00000010, 0x91a0b009,
- 0x00000008, 0x2c80010d,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x00000018, 0x8000ffab,
- 0x00000018, 0x80000010,
- 0x00000008, 0xac000001,
- 0x00000018, 0x8000000b,
- 0x00000000, 0x0380b000,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c004000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ff9a,
- 0x00000018, 0x80000030,
- 0x00000018, 0x80000006,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c000e00,
- 0x00000008, 0x2a000007,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ff0b,
- 0x00000000, 0x06820000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x0ce70007,
- 0x00000009, 0x0562ffff,
- 0x00000010, 0xba6c1405,
- 0x00000000, 0x2adf0000,
- 0x00000000, 0x21000000,
- 0x00000008, 0x2a000005,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2c80010c,
- 0x00000008, 0x2d000008,
- 0x0000000c, 0x31620018,
- 0x00000008, 0x2d800001,
- 0x00000018, 0x8000ff8c,
- 0x00000018, 0x000d0000,
- 0x00000010, 0xb1a0b00e,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c200000,
- 0x00000010, 0x91d40000,
- 0x00000018, 0x80000014,
- 0x00000010, 0x2c620002,
- 0x00000018, 0x8000000b,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c070000,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000feed,
- 0x00000008, 0x2c80010d,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a00000a,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000fee2,
- 0x00000000, 0x05020000,
- 0x00000008, 0x2c80010c,
- 0x00000008, 0x2d000008,
- 0x00000008, 0x2d800134,
- 0x00000000, 0x00000000,
- 0x00000010, 0x205f0000,
- 0x00000008, 0x2c800140,
- 0x00000008, 0x2d00003c,
- 0x00000008, 0x2d80011c,
- 0x00000000, 0x00000000,
- 0x00000010, 0x205f0000,
- 0x00000008, 0x2c800080,
- 0x00000008, 0x2d000000,
- 0x00000008, 0x2d800108,
- 0x00000000, 0x00000000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x000a0000,
+ 0x00000008, 0x07800000,
+ 0x00000018, 0x8000ff4b,
0x00000010, 0x91d40000,
- 0x00000008, 0x0600aaaa,
- 0x00000018, 0x8000ff56,
+ 0x00000008, 0x050000aa,
+ 0x00000018, 0x8000ff89,
0x0000000c, 0x29800001,
0x0000000c, 0x1f800001,
0x00000008, 0x2a000009,
- 0x00000008, 0x0500aaaa,
- 0x00000018, 0x8000fec9,
+ 0x00000018, 0x8000ff44,
0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ff4e,
- 0x00000010, 0x91a03c02,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ff82,
+ 0x00000010, 0x91a0b002,
0x00000010, 0xb1e66207,
0x0000000b, 0x2fdf0002,
0x00000000, 0x2c310000,
@@ -13073,7 +13468,7 @@ u32 bce_xi_rv2p_proc1[] = {
0x00000000, 0x2ca70000,
0x00000008, 0x2d000010,
0x00000008, 0x2d800108,
- 0x00000018, 0x8000ff47,
+ 0x00000018, 0x8000ff7a,
0x00000010, 0xb1a60010,
0x00000010, 0x001f0000,
0x0000000f, 0x0f300007,
@@ -13096,13 +13491,12 @@ u32 bce_xi_rv2p_proc1[] = {
0x00000000, 0x2adf0000,
0x00000008, 0x2a00000c,
0x00000010, 0x009f0000,
- 0x00000000, 0x0f200000,
+ 0x00000000, 0x2c200000,
0x0000000c, 0x1f800001,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000fe9d,
+ 0x00000018, 0x8000ff19,
0x00000010, 0x91d40000,
- 0x00000008, 0x0600aaaa,
- 0x00000018, 0x8000ff22,
+ 0x00000008, 0x050000aa,
+ 0x00000018, 0x8000ff57,
0x0000000f, 0x47220008,
0x00000009, 0x070e000f,
0x00000008, 0x070e0008,
@@ -13121,7 +13515,7 @@ u32 bce_xi_rv2p_proc1[] = {
0x00000000, 0x0c960a00,
0x00000009, 0x0c99ffff,
0x00000008, 0x0d00ffff,
- 0x00000010, 0xb1963202,
+ 0x00000010, 0xba992c02,
0x00000008, 0x0f800005,
0x00000010, 0xb1a80008,
0x00000010, 0x205f0000,
@@ -13130,72 +13524,65 @@ u32 bce_xi_rv2p_proc1[] = {
0x00000000, 0x2ca70000,
0x00000008, 0x2d000010,
0x00000008, 0x2d800108,
- 0x00000018, 0x8000ff0e,
+ 0x00000018, 0x8000ff42,
0x0000000c, 0x29800001,
0x00000010, 0x001f0000,
0x0000000c, 0x1f800001,
0x00000000, 0x2adf0000,
0x00000008, 0x2a00000d,
- 0x00000008, 0x0500aaaa,
- 0x00000018, 0x8000fe77,
+ 0x00000018, 0x8000fef4,
0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000fefc,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ff32,
0x0000000c, 0x29800001,
0x0000000c, 0x1f800001,
0x00000008, 0x2a000007,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000fe6f,
- 0x00000008, 0x03050004,
- 0x00000006, 0x83040c00,
- 0x00000008, 0x02850200,
- 0x00000000, 0x86050c00,
- 0x00000001, 0x860c0e00,
- 0x00000008, 0x02040004,
- 0x00000000, 0x02041800,
- 0x00000000, 0x83871800,
- 0x00000018, 0x00020000,
+ 0x00000018, 0x8000feed,
};
u32 bce_xi_rv2p_proc2[] = {
0x00000010, 0xb1800004,
- 0x0000001f, 0x05030100,
+ 0x0000001f, 0x05060011,
0x00000008, 0x050000ff,
0x00000018, 0x00020000,
0x00000000, 0x2a000000,
0x00000010, 0xb1d40000,
+ 0x00000010, 0x91de0000,
+ 0x00000010, 0x20530000,
+ 0x00000010, 0x001f0000,
+ 0x00000000, 0x2f80aa00,
0x0000000c, 0x29800001,
- 0x00000008, 0x02540009,
+ 0x00000008, 0x0254000f,
+ 0x00000000, 0x2c400000,
+ 0x00000000, 0x0f400000,
0x00000009, 0x2952003f,
0x00000018, 0x00040000,
- 0x00000018, 0x80000010,
0x00000018, 0x80000011,
- 0x00000018, 0x8000003a,
+ 0x00000018, 0x80000012,
+ 0x00000018, 0x80000038,
+ 0x00000018, 0x80000111,
+ 0x00000018, 0x80000110,
+ 0x00000018, 0x8000010f,
0x00000018, 0x8000010f,
- 0x00000018, 0x8000010e,
- 0x00000018, 0x8000010d,
- 0x00000018, 0x8000010d,
0x00000018, 0x80000000,
- 0x00000018, 0x8000011f,
- 0x00000018, 0x80000109,
- 0x00000018, 0x8000000c,
- 0x00000018, 0x80000123,
- 0x00000018, 0x80000175,
- 0x00000018, 0x80000067,
- 0x00000018, 0x800000da,
- 0x00000018, 0x800000e8,
+ 0x00000018, 0x80000128,
+ 0x00000018, 0x8000010b,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000012c,
+ 0x00000018, 0x8000017a,
+ 0x00000018, 0x8000005a,
+ 0x00000018, 0x800000c4,
+ 0x00000018, 0x800000c5,
+ 0x00000018, 0x80000104,
0x00000000, 0x2a000000,
- 0x00000018, 0x8000ffea,
+ 0x00000018, 0x8000ffe3,
0x00000000, 0x2a000000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ffe6,
- 0x00000000, 0x2a000000,
- 0x00000018, 0x8000ffe4,
+ 0x00000018, 0x8000ffe0,
0x00000018, 0x00020000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963421,
+ 0x00000010, 0xb99a2c21,
0x00000010, 0x205f0000,
0x00000000, 0x2c1e0000,
0x00000008, 0x2c800006,
@@ -13206,7 +13593,7 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000000, 0x0d610000,
0x00000018, 0x000a0000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963416,
+ 0x00000010, 0xb99a2c16,
0x00000010, 0x205f0000,
0x00000000, 0x09d80000,
0x00000000, 0x2c1e0000,
@@ -13219,7 +13606,7 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000000, 0x2c130000,
0x00000018, 0x000a0000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963409,
+ 0x00000010, 0xb99a2c09,
0x00000010, 0x205f0000,
0x00000000, 0x2c1e0000,
0x00000008, 0x2c800006,
@@ -13229,31 +13616,25 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000010, 0x91de0000,
0x00000000, 0x0d7a0000,
0x00000018, 0x000a0000,
- 0x00000010, 0x91de0000,
- 0x00000010, 0x001f0000,
- 0x00000000, 0x2f80aa00,
0x00000000, 0x2a000000,
+ 0x00000008, 0x22000001,
0x00000000, 0x0d610000,
- 0x00000000, 0x03620000,
- 0x00000000, 0x2c400000,
- 0x00000000, 0x02638c00,
- 0x00000000, 0x26460000,
- 0x00000008, 0x02040012,
- 0x00000010, 0xb9060827,
- 0x00000000, 0x0f580000,
+ 0x00000010, 0x21c20024,
+ 0x00000010, 0xb1c60002,
+ 0x00000010, 0x234200a2,
+ 0x00000009, 0x0b66ffff,
+ 0x00000010, 0xba9a2c20,
0x00000000, 0x0a640000,
0x00000000, 0x0ae50000,
- 0x00000009, 0x0b66ffff,
0x00000000, 0x0c000000,
0x00000000, 0x0b800000,
0x00000008, 0x0cc60012,
- 0x00000018, 0x8000ffcb,
+ 0x00000018, 0x8000ffd0,
0x00000008, 0x0f800003,
0x00000000, 0x00000000,
0x00000010, 0x009f0000,
0x00000008, 0x27110012,
0x00000000, 0x66900000,
- 0x00000008, 0xa31b0012,
0x00000010, 0xb1980003,
0x00000010, 0x001f0000,
0x00000008, 0x0f800004,
@@ -13261,39 +13642,30 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000008, 0x2c80000c,
0x00000008, 0x2d00000c,
0x00000010, 0x009f0000,
+ 0x00000010, 0x91c60005,
+ 0x00000010, 0x001f0000,
+ 0x00000010, 0xba9a2c03,
+ 0x00000008, 0x0f800004,
+ 0x00000018, 0x8000fffd,
0x00000000, 0x25960000,
0x0000000c, 0x29800000,
- 0x00000000, 0x06660000,
- 0x00000000, 0x86611800,
- 0x00000009, 0x0260000f,
- 0x0000000f, 0x02040002,
- 0x00000010, 0xb60c0803,
- 0x0000000c, 0x1fbf0000,
- 0x0000000c, 0x33660010,
0x00000000, 0x32140000,
0x00000000, 0x32950000,
0x00000005, 0x73662c00,
0x00000000, 0x31e32e00,
0x00000008, 0x2d800010,
- 0x00000010, 0x20530000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000ff8f,
+ 0x00000018, 0x8000ff95,
0x00000000, 0x23000000,
0x00000009, 0x25e6ffff,
0x00000008, 0x2200000b,
0x0000000c, 0x69520000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ff88,
- 0x00000010, 0x91de0000,
- 0x00000010, 0x001f0000,
- 0x00000000, 0x2f80aa00,
+ 0x00000018, 0x8000ff8f,
0x00000000, 0x2a000000,
- 0x00000000, 0x2c400000,
0x00000008, 0x2c800040,
0x00000008, 0x2d000020,
0x00000008, 0x2d80011c,
- 0x00000000, 0x00000000,
+ 0x00000008, 0x22000001,
0x00000010, 0x91de0000,
0x0000000f, 0x42ea0010,
0x00000010, 0x004f0004,
@@ -13301,21 +13673,22 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000008, 0x02490012,
0x00000010, 0xb5840a00,
0x00000000, 0x0d610000,
- 0x00000010, 0xba66345a,
- 0x00000000, 0x03620000,
- 0x00000010, 0xb8630c58,
+ 0x00000010, 0xba663457,
0x00000008, 0x83050012,
0x00000010, 0x004f0002,
0x00000000, 0x03490000,
0x00000001, 0x83068c00,
0x00000000, 0x83c60c00,
- 0x00000010, 0xb1870010,
+ 0x00000010, 0xb1870013,
0x00000000, 0x0b6e0000,
- 0x00000018, 0x8000ff6a,
- 0x00000001, 0x06691400,
- 0x00000010, 0x918c0002,
+ 0x00000009, 0x0569ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x34e9ffff,
+ 0x00000018, 0x8000ff74,
+ 0x00000001, 0x05691400,
+ 0x00000010, 0x918a0002,
0x00000008, 0xb4e90001,
- 0x00000010, 0xb1e92c4c,
+ 0x00000010, 0xbae92c48,
0x00000000, 0x86692c00,
0x00000000, 0x02000000,
0x00000009, 0x02eaffff,
@@ -13324,9 +13697,7 @@ u32 bce_xi_rv2p_proc2[] = {
0x0000000f, 0x460c0001,
0x0000000f, 0x02850001,
0x00000010, 0x918c01fc,
- 0x00000010, 0xb7040e43,
- 0x00000000, 0x2c400000,
- 0x00000000, 0x0f400000,
+ 0x00000010, 0xb7040e3f,
0x00000000, 0x0d610000,
0x00000000, 0x0a640000,
0x00000000, 0x0ae50000,
@@ -13339,7 +13710,6 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000010, 0x009f0000,
0x00000008, 0x27110012,
0x00000000, 0x66900000,
- 0x00000000, 0x26460000,
0x00000000, 0x23060000,
0x00000010, 0xb1980005,
0x00000010, 0x001f0000,
@@ -13389,9 +13759,7 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000008, 0x2c800050,
0x00000008, 0x2d000030,
0x00000008, 0x2d80000c,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ff1e,
- 0x00000000, 0x26460000,
+ 0x00000018, 0x8000ff2c,
0x00000000, 0x23000000,
0x00000009, 0x25e6ffff,
0x00000000, 0x0b6e0000,
@@ -13399,81 +13767,108 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000008, 0x2200001b,
0x0000000c, 0x69520000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ff14,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000ff24,
0x00000000, 0x2a000000,
- 0x00000010, 0x003f000c,
- 0x00000000, 0x06660000,
- 0x00000000, 0x86611800,
- 0x00000009, 0x026000f0,
- 0x00000010, 0xb70c0808,
- 0x00000000, 0x2c400000,
- 0x0000000c, 0x73660010,
- 0x00000008, 0x2c800018,
- 0x00000008, 0x2d000018,
- 0x00000008, 0x2d800002,
- 0x0000000c, 0x5fbf0000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000ff05,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000ff22,
0x00000000, 0x2a000000,
- 0x00000000, 0x2c400000,
- 0x0000000c, 0x73660010,
- 0x00000008, 0x2c800018,
- 0x00000008, 0x2d000018,
- 0x00000008, 0x2d800002,
- 0x0000000c, 0x5fbf0000,
- 0x00000010, 0x91de0000,
- 0x00000008, 0x2c800003,
- 0x00000008, 0x2d000003,
- 0x00000009, 0x3060fff0,
- 0x00000008, 0x2d800001,
0x0000000c, 0x29800000,
0x00000010, 0x91de0000,
0x00000008, 0x2c80001a,
0x00000008, 0x2d00001a,
- 0x00000000, 0x33000000,
+ 0x00000005, 0x73660000,
0x00000008, 0x2d800002,
0x00000000, 0x31800000,
0x00000010, 0x91de0000,
0x00000008, 0x2c80000c,
0x00000008, 0x2d00000c,
0x00000008, 0x2d800004,
+ 0x00000018, 0x8000ff15,
+ 0x00000008, 0x06660001,
+ 0x00000010, 0xba9a197f,
+ 0x00000000, 0x0a640000,
+ 0x00000000, 0x0ae50000,
+ 0x00000009, 0x0b66ffff,
+ 0x00000000, 0x0c000000,
+ 0x00000000, 0x0b800000,
+ 0x00000008, 0x0cc60012,
+ 0x00000018, 0x8000ff2e,
+ 0x00000008, 0x0f800003,
+ 0x00000000, 0x00000000,
+ 0x00000010, 0x009f0000,
+ 0x00000008, 0x27110012,
+ 0x00000000, 0x66900000,
+ 0x00000010, 0x919b3200,
+ 0x00000010, 0x02930000,
+ 0x00000010, 0xb1980003,
+ 0x00000010, 0x001f0000,
+ 0x00000008, 0x0f800004,
+ 0x0000000c, 0x29800000,
+ 0x00000010, 0x001f0000,
+ 0x00000010, 0xba9a2c00,
+ 0x00000000, 0x31e32e00,
+ 0x00000000, 0x0b800000,
+ 0x00000000, 0x8ccc8c00,
+ 0x00000010, 0xb5cc8c02,
+ 0x00000008, 0x0c800001,
+ 0x00000018, 0x8000ff1b,
+ 0x00000008, 0x0f800003,
0x00000010, 0x20530000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000feea,
- 0x00000018, 0x8000fee9,
+ 0x0000000c, 0x69520001,
+ 0x00000000, 0x22c58c00,
+ 0x00000010, 0x009f0000,
+ 0x00000000, 0x27110000,
+ 0x00000000, 0x26900000,
+ 0x00000000, 0x231b0000,
+ 0x00000010, 0xb1980003,
+ 0x00000010, 0x001f0000,
+ 0x00000008, 0x0f800004,
+ 0x00000008, 0x22000003,
+ 0x00000008, 0x2c80000c,
+ 0x00000008, 0x2d00000c,
+ 0x00000010, 0x009f0000,
+ 0x00000000, 0x25960000,
+ 0x0000000c, 0x29800000,
+ 0x00000000, 0x32140000,
+ 0x00000000, 0x32950000,
+ 0x00000005, 0x73662c00,
+ 0x00000000, 0x31e32e00,
+ 0x00000008, 0x2d800010,
+ 0x00000018, 0x8000fee2,
+ 0x00000018, 0x8000fee1,
0x00000000, 0x2a000000,
0x00000010, 0x001f0000,
0x00000000, 0x0f008000,
0x00000008, 0x0f800007,
- 0x00000018, 0x80000014,
+ 0x00000018, 0x8000001b,
+ 0x00000000, 0x280a0000,
0x00000000, 0x05020000,
0x00000008, 0x22000009,
- 0x00000000, 0x286d0000,
0x00000000, 0x29000000,
0x0000000f, 0x65680010,
+ 0x00000000, 0x248a0000,
0x00000003, 0xf66c9400,
0x00000010, 0xb972a004,
0x0000000c, 0x73e70019,
0x0000000c, 0x21420004,
- 0x00000000, 0x3bf60000,
+ 0x00000000, 0x3cf80000,
0x0000000c, 0x29800000,
0x00000010, 0x20530000,
0x00000008, 0x22000008,
0x0000000c, 0x61420004,
0x00000018, 0x000a0000,
+ 0x00000000, 0x05020000,
+ 0x0000000c, 0x61420000,
+ 0x00000010, 0x01420003,
+ 0x0000000c, 0x33e7001d,
+ 0x0000000c, 0x61420002,
+ 0x00000018, 0x000a0000,
0x00000000, 0x2a000000,
0x00000010, 0x001f0000,
0x0000000f, 0x0f470007,
0x00000008, 0x0f800008,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000fece,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2fd50000,
- 0x00000010, 0x001f0000,
+ 0x00000010, 0x009f0000,
+ 0x00000018, 0x8000febf,
0x00000000, 0x33510000,
0x00000000, 0x2a000000,
0x00000010, 0xb1c60023,
@@ -13548,13 +13943,11 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000008, 0x2d80000c,
0x00000000, 0x00000000,
0x00000010, 0x91de0000,
- 0x00000010, 0x05c20003,
- 0x00000000, 0x33000000,
+ 0x00000010, 0x05c20004,
0x00000008, 0x0f800007,
- 0x00000010, 0x20530000,
+ 0x00000000, 0x33000000,
0x00000010, 0x009f0000,
- 0x00000018, 0x8000fe7b,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000fe70,
0x00000000, 0x2a000000,
0x0000000f, 0x0f500007,
0x00000010, 0xb1c6002d,
@@ -13613,485 +14006,358 @@ u32 bce_xi_rv2p_proc2[] = {
0x00000008, 0x22000017,
0x0000000c, 0x29800000,
0x00000010, 0x001f0000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000fe3e,
+ 0x00000018, 0x8000fe35,
};
u32 bce_xi90_rv2p_proc1[] = {
- 0x00000010, 0xb1800002,
- 0x0000001f, 0x03030100,
- 0x00000008, 0xac000001,
- 0x00000000, 0x05000000,
- 0x0000000c, 0x2f800001,
- 0x00000000, 0x2b000000,
- 0x00000000, 0x2b800000,
- 0x00000010, 0x203f006c,
- 0x00000010, 0x213f0003,
- 0x00000010, 0x20bf003b,
- 0x00000018, 0x8000fffd,
- 0x00000010, 0xb1b8b015,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c380000,
- 0x00000008, 0x2c800000,
- 0x00000008, 0x2d000000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000008f,
- 0x00000008, 0x2d80011c,
- 0x00000008, 0x02000001,
- 0x00000010, 0x91de0000,
- 0x0000000f, 0x42e0001c,
- 0x00000010, 0x91840a17,
- 0x00000010, 0x08660016,
- 0x0000000c, 0x29800002,
- 0x0000000c, 0x1f800002,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a00000f,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ffe8,
- 0x00000008, 0x02000001,
- 0x0000000f, 0x42e0001c,
- 0x00000010, 0x91840a19,
- 0x00000008, 0x2c800006,
- 0x00000008, 0x2d000006,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800106,
- 0x00000018, 0x80000083,
- 0x00000010, 0x08660013,
- 0x00000018, 0x8000fff1,
- 0x00000008, 0xb1000001,
- 0x00000008, 0x2c80010c,
- 0x00000008, 0x2d000008,
- 0x00000008, 0x2d800001,
- 0x00000018, 0x8000007c,
- 0x0000000b, 0x2fdf0002,
- 0x0000000c, 0x1f800002,
- 0x00000000, 0x2c070000,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffd3,
- 0x0000000b, 0x2fdf0002,
- 0x0000000c, 0x1f800000,
- 0x00000000, 0x2c070000,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffcd,
- 0x0000000c, 0x1f800002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffca,
- 0x0000000c, 0x29800002,
- 0x0000000c, 0x1f800002,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a000005,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ffc4,
- 0x00000008, 0x02240045,
- 0x00000018, 0x00040000,
- 0x00000018, 0x8000001c,
- 0x00000018, 0x8000001e,
- 0x00000018, 0x80000065,
- 0x00000018, 0x800000ad,
- 0x00000018, 0x800000ac,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000000,
- 0x00000018, 0x800000f3,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000015,
- 0x00000018, 0x8000001b,
- 0x00000018, 0x80000000,
- 0x00000018, 0x800000c3,
- 0x00000018, 0x8000002e,
- 0x00000018, 0x800000f3,
- 0x00000018, 0x8000011e,
- 0x00000018, 0x800000e9,
- 0x00000018, 0x80000142,
- 0x00000018, 0x8000004e,
- 0x00000018, 0x80000000,
- 0x00000018, 0x80000080,
- 0x0000000c, 0x1f800001,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ffa3,
- 0x00000010, 0x91d40000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000008, 0x2a000002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff9d,
- 0x00000010, 0x91d40000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000000, 0x29420000,
- 0x00000008, 0x2a000002,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff96,
- 0x00000018, 0x8000ff95,
- 0x00000010, 0xb1bcb00a,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c3c0000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x80000029,
- 0x00000018, 0x800000bb,
- 0x00000010, 0x2c6201ba,
- 0x00000018, 0x80000005,
- 0x00000008, 0x2c80010d,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x0000000c, 0x29800000,
- 0x0000000c, 0x1f800000,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a000006,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ff80,
- 0x00000010, 0x91d40000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000008, 0x2a00000b,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff7a,
- 0x00000000, 0x02020000,
- 0x00000000, 0x029a0000,
- 0x00000000, 0x060c2c00,
- 0x00000004, 0xc60c3400,
- 0x00000010, 0x001f0000,
- 0x00000010, 0xb196180c,
- 0x00000008, 0x06960004,
- 0x00000009, 0x068dfffc,
- 0x00000004, 0xcd051a00,
- 0x00000004, 0xcc9a1800,
- 0x00000010, 0x20d70000,
- 0x0000000c, 0x2b560000,
- 0x00000000, 0x00000000,
- 0x00000000, 0x00000000,
- 0x00000010, 0x20d70000,
- 0x00000008, 0x0f800001,
- 0x00000010, 0xb18001f4,
- 0x00000010, 0x001f0000,
- 0x0000000c, 0x6b560000,
- 0x00000018, 0x00040000,
- 0x00000000, 0x06820000,
- 0x00000010, 0xb18a0006,
- 0x00000000, 0x860c1400,
- 0x00000010, 0xb18c0004,
- 0x00000000, 0x05000000,
- 0x00000008, 0x2a000001,
- 0x00000010, 0x91d40000,
- 0x00000018, 0x000d0000,
- 0x00000000, 0x05020000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x000a0000,
- 0x00000010, 0xb1a0b013,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c200000,
- 0x00000008, 0x2c800000,
- 0x00000008, 0x2d000000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ffee,
- 0x00000008, 0x2d80011c,
- 0x00000010, 0x001f0000,
- 0x00000010, 0x91de0000,
- 0x0000000f, 0x47600008,
- 0x0000000f, 0x060e0001,
- 0x00000000, 0x0f580000,
- 0x00000000, 0x0a640000,
- 0x00000000, 0x0ae50000,
- 0x00000009, 0x0b66ffff,
- 0x00000000, 0x0d610000,
- 0x00000018, 0x80000013,
- 0x0000000f, 0x47600008,
- 0x0000000b, 0x2fdf0002,
- 0x00000008, 0x2c800000,
- 0x00000008, 0x2d000000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d80011c,
- 0x0000000f, 0x060e0001,
- 0x00000010, 0x001f0000,
- 0x00000000, 0x0f580000,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x0a640000,
- 0x00000000, 0x0ae50000,
- 0x00000009, 0x0b66ffff,
- 0x00000000, 0x0d610000,
- 0x00000000, 0x02620000,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x31040000,
- 0x00000000, 0x309a0000,
- 0x00000018, 0x8000ffbc,
- 0x0000000c, 0x29800001,
- 0x00000010, 0x00220002,
- 0x0000000c, 0x29520001,
- 0x0000000c, 0x29520000,
- 0x00000008, 0x0200000e,
- 0x00000008, 0x0280001a,
- 0x00000010, 0xb1c40a02,
- 0x00000008, 0x02000003,
- 0x00000008, 0x22000001,
- 0x0000000c, 0x1f800001,
- 0x00000000, 0x2adf0000,
- 0x00000000, 0x2a000800,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000ff27,
- 0x0000000b, 0x2fdf0002,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2a000001,
- 0x00000000, 0x2c200000,
- 0x00000008, 0x2c800000,
- 0x00000008, 0x2d000000,
- 0x00000008, 0x2d80011c,
- 0x00000010, 0x91d40000,
- 0x00000010, 0x91de0000,
- 0x00000008, 0x2c800006,
- 0x00000008, 0x2d000006,
- 0x00000000, 0x30800000,
- 0x00000000, 0x31000000,
- 0x00000008, 0x2d800006,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a000010,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000ff12,
- 0x00000010, 0x91a0b009,
- 0x00000008, 0x2c80010d,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x00000018, 0x8000ffaf,
- 0x00000018, 0x80000010,
- 0x00000008, 0xac000001,
- 0x00000018, 0x8000000b,
- 0x00000000, 0x0380b000,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c004000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ff9e,
- 0x00000018, 0x80000030,
- 0x00000018, 0x80000006,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c000e00,
- 0x00000008, 0x2a000007,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000fefc,
- 0x00000000, 0x06820000,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x0ce70007,
- 0x00000009, 0x0562ffff,
- 0x00000010, 0xba6c1405,
- 0x00000000, 0x2adf0000,
- 0x00000000, 0x21000000,
- 0x00000008, 0x2a000005,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2c80010c,
- 0x00000008, 0x2d000008,
- 0x0000000c, 0x31620018,
- 0x00000008, 0x2d800001,
- 0x00000018, 0x8000ff90,
- 0x00000018, 0x000d0000,
- 0x00000010, 0xb1a0b00e,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x03d80000,
- 0x00000000, 0x2c200000,
- 0x00000010, 0x91d40000,
- 0x00000018, 0x80000014,
- 0x00000010, 0x2c620002,
- 0x00000018, 0x8000000b,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c070000,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000fede,
- 0x00000008, 0x2c80010d,
- 0x00000008, 0x2d000009,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x2d800107,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a00000a,
- 0x00000000, 0x05000000,
- 0x00000018, 0x8000fed3,
- 0x00000000, 0x05020000,
- 0x00000008, 0x2c80010c,
- 0x00000008, 0x2d000008,
- 0x00000008, 0x2d800134,
- 0x00000000, 0x00000000,
- 0x00000010, 0x205f0000,
- 0x00000008, 0x2c800140,
- 0x00000008, 0x2d00003c,
- 0x00000008, 0x2d80011c,
- 0x00000000, 0x00000000,
- 0x00000010, 0x205f0000,
- 0x00000008, 0x2c800080,
- 0x00000008, 0x2d000000,
- 0x00000008, 0x2d800108,
- 0x00000000, 0x00000000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x000a0000,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x0600aaaa,
- 0x00000018, 0x8000ff5a,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000008, 0x2a000009,
- 0x00000008, 0x0500aaaa,
- 0x00000018, 0x8000feba,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ff52,
- 0x00000010, 0x91a03c02,
- 0x00000010, 0xb1e66207,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c310000,
- 0x00000009, 0x2cb1007f,
- 0x00000008, 0x2cd90000,
- 0x00000008, 0x2d000000,
- 0x00000008, 0x2d80010d,
- 0x00000010, 0xb1a80006,
- 0x00000010, 0x205f0000,
- 0x00000000, 0x2c200000,
- 0x00000000, 0x2ca70000,
- 0x00000008, 0x2d000010,
- 0x00000008, 0x2d800108,
- 0x00000018, 0x8000ff4b,
- 0x00000010, 0xb1a60010,
- 0x00000010, 0x001f0000,
- 0x0000000f, 0x0f300007,
- 0x00000000, 0x0a600000,
- 0x00000000, 0x0ae10000,
- 0x0000000f, 0x4b620008,
- 0x00000009, 0x0b1600ff,
- 0x00000000, 0x0d620000,
- 0x00000009, 0x0d1a00ff,
- 0x00000010, 0x07300003,
- 0x0000000c, 0x0d1a0008,
- 0x0000000c, 0x0b160008,
- 0x0000000f, 0x4ce30018,
- 0x00000000, 0x0c992c00,
- 0x00000004, 0xcc993400,
- 0x00000008, 0x0f800000,
- 0x0000000c, 0x29800001,
- 0x00000000, 0x33310000,
- 0x00000008, 0x22000016,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a00000c,
- 0x00000010, 0x009f0000,
- 0x00000000, 0x0f200000,
- 0x0000000c, 0x1f800001,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000fe8e,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x0600aaaa,
- 0x00000018, 0x8000ff26,
- 0x0000000f, 0x47220008,
- 0x00000009, 0x070e000f,
- 0x00000008, 0x070e0008,
- 0x00000008, 0x02800001,
- 0x00000007, 0x02851c00,
- 0x00000008, 0x82850001,
- 0x00000000, 0x02854c00,
- 0x00000007, 0x42851c00,
- 0x00000003, 0xc3aa5200,
- 0x00000000, 0x03b10e00,
- 0x00000007, 0x4b071c00,
- 0x0000000f, 0x0f300007,
- 0x0000000f, 0x0a960003,
- 0x00000000, 0x0a955c00,
- 0x00000000, 0x4a005a00,
- 0x00000000, 0x0c960a00,
- 0x00000009, 0x0c99ffff,
- 0x00000008, 0x0d00ffff,
- 0x00000010, 0xb1963202,
- 0x00000008, 0x0f800005,
- 0x00000010, 0xb1a80008,
- 0x00000010, 0x205f0000,
- 0x0000000b, 0x2fdf0002,
- 0x00000000, 0x2c200000,
- 0x00000000, 0x2ca70000,
- 0x00000008, 0x2d000010,
- 0x00000008, 0x2d800108,
- 0x00000018, 0x8000ff12,
- 0x0000000c, 0x29800001,
- 0x00000010, 0x001f0000,
- 0x0000000c, 0x1f800001,
- 0x00000000, 0x2adf0000,
- 0x00000008, 0x2a00000d,
- 0x00000008, 0x0500aaaa,
- 0x00000018, 0x8000fe68,
- 0x00000010, 0x91d40000,
- 0x00000008, 0x06005555,
- 0x00000018, 0x8000ff00,
- 0x0000000c, 0x29800001,
- 0x0000000c, 0x1f800001,
- 0x00000008, 0x2a000007,
- 0x00000008, 0x05005555,
- 0x00000018, 0x8000fe60,
- 0x00000008, 0x03050004,
- 0x00000006, 0x83040c00,
- 0x00000008, 0x02850200,
- 0x00000000, 0x86050c00,
- 0x00000001, 0x860c0e00,
- 0x00000008, 0x02040004,
- 0x00000000, 0x02041800,
- 0x00000000, 0x83871800,
- 0x00000018, 0x00020000,
+ 0x00000010, 0xb1800006,
+ 0x0000001f, 0x03060011,
+ 0x00000008, 0x0500ffff,
+ 0x00000018, 0x00020000,
+ 0x00000008, 0x050000ff,
+ 0x00000018, 0x00020000,
+ 0x00000008, 0xac000001,
+ 0x00000008, 0x07800000,
+ 0x0000000c, 0x2f800001,
+ 0x00000000, 0x2b000000,
+ 0x00000000, 0x2b800000,
+ 0x00000010, 0x91e10002,
+ 0x00000008, 0xac000001,
+ 0x00000010, 0x203f003b,
+ 0x00000010, 0x213f0003,
+ 0x00000010, 0x20bf0015,
+ 0x00000018, 0x8000fffd,
+ 0x0000000c, 0x1f800002,
+ 0x00000018, 0x8000fff9,
+ 0x00000008, 0xb1000001,
+ 0x00000008, 0x2c80010c,
+ 0x00000008, 0x2d000008,
+ 0x00000008, 0x2d800001,
+ 0x00000018, 0x8000004f,
+ 0x0000000b, 0x2fdf0002,
+ 0x0000000c, 0x1f800002,
+ 0x00000000, 0x2c070000,
+ 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000ffef,
+ 0x0000000b, 0x2fdf0002,
+ 0x0000000c, 0x1f800000,
+ 0x00000000, 0x2c070000,
+ 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000ffea,
+ 0x0000000c, 0x1f800002,
+ 0x00000018, 0x8000ffe8,
+ 0x00000008, 0x02240025,
+ 0x00000018, 0x00040000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000001b,
+ 0x00000018, 0x80000055,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000009d,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000009c,
+ 0x00000018, 0x800000c6,
+ 0x00000018, 0x80000093,
+ 0x00000018, 0x800000e9,
+ 0x00000018, 0x8000003e,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000007a,
+ 0x00000010, 0x91d40000,
+ 0x0000000c, 0x29800001,
+ 0x0000000c, 0x1f800001,
+ 0x00000008, 0x2a000002,
+ 0x00000008, 0x07800000,
+ 0x00000018, 0x8000ffc4,
+ 0x00000008, 0x03800100,
+ 0x00000010, 0xb73c0e00,
+ 0x00000018, 0x80000000,
+ 0x00000000, 0x02020000,
+ 0x00000000, 0x029a0000,
+ 0x00000000, 0x060c2c00,
+ 0x00000004, 0xc60c3400,
+ 0x00000010, 0x001f0000,
+ 0x00000010, 0xba8c2c0c,
+ 0x00000008, 0x06960004,
+ 0x00000009, 0x068dfffc,
+ 0x00000004, 0xcd051a00,
+ 0x00000004, 0xcc9a1800,
+ 0x00000010, 0x20d70000,
+ 0x0000000c, 0x2b560000,
+ 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000,
+ 0x00000010, 0x20d70000,
+ 0x00000008, 0x0f800001,
+ 0x00000010, 0xb18001f4,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6b560000,
+ 0x00000018, 0x00040000,
+ 0x00000000, 0x06820000,
+ 0x00000010, 0xb18f0004,
+ 0x00000010, 0xb18f1403,
+ 0x00000008, 0x2a000001,
+ 0x00000010, 0x91d40000,
+ 0x00000000, 0x07801400,
+ 0x00000018, 0x000d0000,
+ 0x00000000, 0x05020000,
+ 0x00000010, 0x91de0000,
+ 0x00000018, 0x000a0000,
+ 0x00000000, 0x06820000,
+ 0x00000010, 0x91de0000,
+ 0x00000009, 0x0561ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x30e1ffff,
+ 0x00000018, 0x8000ff96,
+ 0x00000001, 0x05611400,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0xb0e10001,
+ 0x00000018, 0x000d0000,
+ 0x00000000, 0x06820000,
+ 0x00000010, 0x91de0000,
+ 0x00000009, 0x0562ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x3162ffff,
+ 0x00000018, 0x8000ff8c,
+ 0x00000001, 0x05621400,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0xb1620001,
+ 0x00000018, 0x000d0000,
+ 0x00000010, 0xb1a0b013,
+ 0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x2c200000,
+ 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000,
+ 0x00000010, 0x91d40000,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ffdb,
+ 0x00000008, 0x2d80011c,
+ 0x00000010, 0x001f0000,
+ 0x00000018, 0x8000ffe2,
+ 0x0000000f, 0x47600008,
+ 0x0000000f, 0x060e0001,
+ 0x00000000, 0x0f580000,
+ 0x00000000, 0x0a640000,
+ 0x00000000, 0x0ae50000,
+ 0x00000009, 0x0b66ffff,
+ 0x00000000, 0x0d610000,
+ 0x00000018, 0x80000015,
+ 0x0000000f, 0x47600008,
+ 0x0000000b, 0x2fdf0002,
+ 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000,
+ 0x00000010, 0x91d40000,
+ 0x00000008, 0x2d80011c,
+ 0x0000000f, 0x060e0001,
+ 0x00000010, 0x001f0000,
+ 0x00000000, 0x0f580000,
+ 0x00000018, 0x8000ffd0,
+ 0x00000000, 0x0a640000,
+ 0x00000000, 0x0ae50000,
+ 0x00000009, 0x0b66ffff,
+ 0x00000000, 0x0d610000,
+ 0x00000000, 0x02620000,
+ 0x00000000, 0x02e00000,
+ 0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x30050000,
+ 0x00000000, 0x31040000,
+ 0x00000000, 0x309a0000,
+ 0x00000010, 0x0060000a,
+ 0x00000008, 0x05160001,
+ 0x00000010, 0xba9a1403,
+ 0x00000000, 0x03000000,
+ 0x00000018, 0x80000006,
+ 0x00000018, 0x8000ff59,
+ 0x00000010, 0xb6061404,
+ 0x00000008, 0x03060001,
+ 0x00000008, 0x2a000001,
+ 0x00000018, 0x8000ff5e,
+ 0x00000018, 0x8000ff9d,
+ 0x0000000c, 0x29800001,
+ 0x0000000c, 0x29520001,
+ 0x0000000c, 0x29520000,
+ 0x00000008, 0x22800002,
+ 0x00000008, 0x0200000e,
+ 0x00000008, 0x0280001a,
+ 0x00000010, 0xb1c40a02,
+ 0x00000008, 0x02000003,
+ 0x0000000c, 0x1f800001,
+ 0x00000000, 0x2adf0000,
+ 0x00000000, 0x2a000800,
+ 0x00000018, 0x8000ff51,
+ 0x0000000b, 0x2fdf0002,
+ 0x00000010, 0x91d40000,
+ 0x00000008, 0x2a000001,
+ 0x00000000, 0x2c200000,
+ 0x00000010, 0x91d40000,
+ 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000,
+ 0x00000008, 0x2d80011c,
+ 0x00000018, 0x8000ffa3,
+ 0x00000008, 0x2c800006,
+ 0x00000008, 0x2d000006,
+ 0x00000000, 0x30800000,
+ 0x00000000, 0x31000000,
+ 0x00000008, 0x2d800006,
+ 0x0000000c, 0x29800001,
+ 0x0000000c, 0x1f800001,
+ 0x00000010, 0x91de0000,
+ 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a000010,
+ 0x00000008, 0x07800000,
+ 0x00000018, 0x8000ff3c,
+ 0x00000010, 0x91d40000,
+ 0x00000008, 0x050000aa,
+ 0x00000018, 0x8000ff8d,
+ 0x0000000c, 0x29800001,
+ 0x0000000c, 0x1f800001,
+ 0x00000008, 0x2a000009,
+ 0x00000018, 0x8000ff35,
+ 0x00000010, 0x91d40000,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ff86,
+ 0x00000010, 0x91a0b002,
+ 0x00000010, 0xb1e66207,
+ 0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x2c310000,
+ 0x00000009, 0x2cb1007f,
+ 0x00000008, 0x2cd90000,
+ 0x00000008, 0x2d000000,
+ 0x00000008, 0x2d80010d,
+ 0x00000010, 0xb1a80006,
+ 0x00000010, 0x205f0000,
+ 0x00000000, 0x2c200000,
+ 0x00000000, 0x2ca70000,
+ 0x00000008, 0x2d000010,
+ 0x00000008, 0x2d800108,
+ 0x00000018, 0x8000ff7e,
+ 0x00000010, 0xb1a60010,
+ 0x00000010, 0x001f0000,
+ 0x0000000f, 0x0f300007,
+ 0x00000000, 0x0a600000,
+ 0x00000000, 0x0ae10000,
+ 0x0000000f, 0x4b620008,
+ 0x00000009, 0x0b1600ff,
+ 0x00000000, 0x0d620000,
+ 0x00000009, 0x0d1a00ff,
+ 0x00000010, 0x07300003,
+ 0x0000000c, 0x0d1a0008,
+ 0x0000000c, 0x0b160008,
+ 0x0000000f, 0x4ce30018,
+ 0x00000000, 0x0c992c00,
+ 0x00000004, 0xcc993400,
+ 0x00000008, 0x0f800000,
+ 0x0000000c, 0x29800001,
+ 0x00000000, 0x33310000,
+ 0x00000008, 0x22000016,
+ 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a00000c,
+ 0x00000010, 0x009f0000,
+ 0x00000000, 0x2c200000,
+ 0x0000000c, 0x1f800001,
+ 0x00000018, 0x8000ff0a,
+ 0x00000010, 0x91d40000,
+ 0x00000008, 0x050000aa,
+ 0x00000018, 0x8000ff5b,
+ 0x0000000f, 0x47220008,
+ 0x00000009, 0x070e000f,
+ 0x00000008, 0x070e0008,
+ 0x00000008, 0x02800001,
+ 0x00000007, 0x02851c00,
+ 0x00000008, 0x82850001,
+ 0x00000000, 0x02854c00,
+ 0x00000007, 0x42851c00,
+ 0x00000003, 0xc3aa5200,
+ 0x00000000, 0x03b10e00,
+ 0x00000007, 0x4b071c00,
+ 0x0000000f, 0x0f300007,
+ 0x0000000f, 0x0a960003,
+ 0x00000000, 0x0a955c00,
+ 0x00000000, 0x4a005a00,
+ 0x00000000, 0x0c960a00,
+ 0x00000009, 0x0c99ffff,
+ 0x00000008, 0x0d00ffff,
+ 0x00000010, 0xba992c02,
+ 0x00000008, 0x0f800005,
+ 0x00000010, 0xb1a80008,
+ 0x00000010, 0x205f0000,
+ 0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x2c200000,
+ 0x00000000, 0x2ca70000,
+ 0x00000008, 0x2d000010,
+ 0x00000008, 0x2d800108,
+ 0x00000018, 0x8000ff46,
+ 0x0000000c, 0x29800001,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x1f800001,
+ 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a00000d,
+ 0x00000018, 0x8000fee5,
+ 0x00000010, 0x91d40000,
+ 0x00000008, 0x05000055,
+ 0x00000018, 0x8000ff36,
+ 0x0000000c, 0x29800001,
+ 0x0000000c, 0x1f800001,
+ 0x00000008, 0x2a000007,
+ 0x00000018, 0x8000fede,
};
u32 bce_xi90_rv2p_proc2[] = {
0x00000010, 0xb1800004,
- 0x0000001f, 0x03030100,
+ 0x0000001f, 0x03060011,
0x00000008, 0x050000ff,
0x00000018, 0x00020000,
0x00000000, 0x2a000000,
0x00000010, 0xb1d40000,
+ 0x00000010, 0x91de0000,
+ 0x00000010, 0x20530000,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6bd70001,
+ 0x00000000, 0x2f80aa00,
0x0000000c, 0x29800001,
- 0x00000008, 0x02540009,
+ 0x00000008, 0x02540010,
+ 0x00000000, 0x2c400000,
+ 0x00000000, 0x0f400000,
0x00000009, 0x2952003f,
0x00000018, 0x00040000,
- 0x00000018, 0x80000010,
0x00000018, 0x80000011,
- 0x00000018, 0x8000004b,
- 0x00000018, 0x8000013c,
- 0x00000018, 0x8000013b,
- 0x00000018, 0x8000013a,
- 0x00000018, 0x8000013a,
- 0x00000018, 0x80000000,
- 0x00000018, 0x8000014d,
+ 0x00000018, 0x80000012,
+ 0x00000018, 0x80000047,
+ 0x00000018, 0x80000137,
0x00000018, 0x80000136,
- 0x00000018, 0x8000000c,
- 0x00000018, 0x80000152,
- 0x00000018, 0x800001ac,
- 0x00000018, 0x80000080,
- 0x00000018, 0x80000107,
- 0x00000018, 0x80000115,
+ 0x00000018, 0x80000135,
+ 0x00000018, 0x80000135,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x8000014f,
+ 0x00000018, 0x80000131,
+ 0x00000018, 0x80000000,
+ 0x00000018, 0x80000155,
+ 0x00000018, 0x800001a6,
+ 0x00000018, 0x8000006d,
+ 0x00000018, 0x800000e4,
+ 0x00000018, 0x800000e5,
+ 0x00000018, 0x8000012a,
0x00000000, 0x2a000000,
- 0x00000018, 0x8000ffea,
+ 0x00000018, 0x8000ffe2,
0x00000000, 0x2a000000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ffe6,
- 0x00000000, 0x2a000000,
- 0x00000018, 0x8000ffe4,
- 0x00000000, 0x03820000,
0x00000018, 0x8000ffdf,
+ 0x00000000, 0x03820000,
+ 0x00000018, 0x8000ffda,
0x00000001, 0x0c161400,
0x00000000, 0x8c181400,
0x00000010, 0x91980003,
@@ -14100,16 +14366,14 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000008, 0x0c960001,
0x00000000, 0x0c000000,
0x00000000, 0x0d190000,
- 0x00000010, 0x20560000,
- 0x0000000c, 0x2bd70001,
0x00000008, 0x0f800001,
0x00000000, 0x00000000,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
- 0x00000010, 0x011301f1,
+ 0x00000010, 0x011301f3,
0x00000018, 0x00070000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963421,
+ 0x00000010, 0xb99a2c21,
0x00000010, 0x205f0000,
0x00000000, 0x2c1e0000,
0x00000008, 0x2c800006,
@@ -14120,7 +14384,7 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x0d610000,
0x00000018, 0x000a0000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963416,
+ 0x00000010, 0xb99a2c16,
0x00000010, 0x205f0000,
0x00000000, 0x09d80000,
0x00000000, 0x2c1e0000,
@@ -14133,7 +14397,7 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x2c130000,
0x00000018, 0x000a0000,
0x00000000, 0x05020000,
- 0x00000010, 0x91963409,
+ 0x00000010, 0xb99a2c09,
0x00000010, 0x205f0000,
0x00000000, 0x2c1e0000,
0x00000008, 0x2c800006,
@@ -14143,80 +14407,60 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000010, 0x91de0000,
0x00000000, 0x0d7a0000,
0x00000018, 0x000a0000,
- 0x00000010, 0x91de0000,
- 0x00000010, 0x001f0000,
- 0x0000000c, 0x6bd70001,
- 0x00000000, 0x2f80aa00,
0x00000000, 0x2a000000,
+ 0x00000008, 0x22000001,
0x00000000, 0x0d610000,
- 0x00000000, 0x03620000,
- 0x00000000, 0x2c400000,
- 0x00000000, 0x02638c00,
- 0x00000000, 0x26460000,
- 0x00000008, 0x02040012,
- 0x00000010, 0xb906082e,
- 0x00000000, 0x0f580000,
+ 0x00000010, 0x21c20028,
+ 0x00000010, 0xb1c60002,
+ 0x00000010, 0x234200b3,
+ 0x00000009, 0x0b66ffff,
+ 0x00000010, 0xba9a2c24,
0x00000000, 0x0a640000,
0x00000000, 0x0ae50000,
- 0x00000009, 0x0b66ffff,
0x00000000, 0x0c000000,
0x00000000, 0x0b800000,
0x00000008, 0x0cc60012,
- 0x00000018, 0x8000ffca,
- 0x00000010, 0x20560000,
- 0x0000000c, 0x2bd70001,
+ 0x00000018, 0x8000ffd0,
0x00000008, 0x0f800003,
0x00000000, 0x00000000,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
0x00000008, 0x27110012,
0x00000000, 0x66900000,
- 0x00000008, 0xa31b0012,
- 0x00000010, 0xb1980006,
+ 0x00000010, 0xb1980004,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
- 0x00000010, 0x20560000,
- 0x0000000c, 0x2bd70001,
0x00000008, 0x0f800004,
0x00000008, 0x22000003,
0x00000008, 0x2c80000c,
0x00000008, 0x2d00000c,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
+ 0x00000010, 0x91c60006,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6bd70001,
+ 0x00000010, 0xba9a2c03,
+ 0x00000008, 0x0f800004,
+ 0x00000018, 0x8000fffc,
0x00000000, 0x25960000,
0x0000000c, 0x29800000,
- 0x00000000, 0x06660000,
- 0x00000000, 0x86611800,
- 0x00000009, 0x0260000f,
- 0x0000000f, 0x02040002,
- 0x00000010, 0xb60c0803,
- 0x0000000c, 0x1fbf0000,
- 0x0000000c, 0x33660010,
0x00000000, 0x32140000,
0x00000000, 0x32950000,
0x00000005, 0x73662c00,
0x00000000, 0x31e32e00,
0x00000008, 0x2d800010,
- 0x00000010, 0x20530000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000ff76,
+ 0x00000018, 0x8000ff81,
0x00000000, 0x23000000,
0x00000009, 0x25e6ffff,
0x00000008, 0x2200000b,
0x0000000c, 0x69520000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000ff6f,
- 0x00000010, 0x91de0000,
- 0x00000010, 0x001f0000,
- 0x0000000c, 0x6bd70001,
- 0x00000000, 0x2f80aa00,
+ 0x00000018, 0x8000ff7b,
0x00000000, 0x2a000000,
- 0x00000000, 0x2c400000,
0x00000008, 0x2c800040,
0x00000008, 0x2d000020,
0x00000008, 0x2d80011c,
- 0x00000000, 0x00000000,
+ 0x00000008, 0x22000001,
0x00000010, 0x91de0000,
0x0000000f, 0x42ea0010,
0x00000010, 0x004f0004,
@@ -14224,21 +14468,22 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000008, 0x02490012,
0x00000010, 0xb5840a00,
0x00000000, 0x0d610000,
- 0x00000010, 0xba66346d,
- 0x00000000, 0x03620000,
- 0x00000010, 0xb8630c6b,
+ 0x00000010, 0xba663464,
0x00000008, 0x83050012,
0x00000010, 0x004f0002,
0x00000000, 0x03490000,
0x00000001, 0x83068c00,
0x00000000, 0x83c60c00,
- 0x00000010, 0xb1870010,
+ 0x00000010, 0xb1870013,
0x00000000, 0x0b6e0000,
- 0x00000018, 0x8000ff50,
- 0x00000001, 0x06691400,
- 0x00000010, 0x918c0002,
+ 0x00000009, 0x0569ffff,
+ 0x00000010, 0x918a0002,
+ 0x00000008, 0x34e9ffff,
+ 0x00000018, 0x8000ff60,
+ 0x00000001, 0x05691400,
+ 0x00000010, 0x918a0002,
0x00000008, 0xb4e90001,
- 0x00000010, 0xb1e92c5f,
+ 0x00000010, 0xbae92c55,
0x00000000, 0x86692c00,
0x00000000, 0x02000000,
0x00000009, 0x02eaffff,
@@ -14247,9 +14492,7 @@ u32 bce_xi90_rv2p_proc2[] = {
0x0000000f, 0x460c0001,
0x0000000f, 0x02850001,
0x00000010, 0x918c01fc,
- 0x00000010, 0xb7040e56,
- 0x00000000, 0x2c400000,
- 0x00000000, 0x0f400000,
+ 0x00000010, 0xb7040e4c,
0x00000000, 0x0d610000,
0x00000000, 0x0a640000,
0x00000000, 0x0ae50000,
@@ -14257,21 +14500,16 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x0c000000,
0x00000000, 0x0b800000,
0x00000008, 0x0c860012,
- 0x00000010, 0x20560000,
- 0x0000000c, 0x2bd70001,
0x00000008, 0x0f800003,
0x0000000c, 0x29520000,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
0x00000008, 0x27110012,
0x00000000, 0x66900000,
- 0x00000000, 0x26460000,
0x00000000, 0x23060000,
- 0x00000010, 0xb1980009,
+ 0x00000010, 0xb1980007,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
- 0x00000010, 0x20560000,
- 0x0000000c, 0x2bd70001,
0x00000008, 0x0f800004,
0x00000000, 0x00000000,
0x00000010, 0x001f0000,
@@ -14281,7 +14519,7 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x31e32e00,
0x00000005, 0x73662c00,
0x00000000, 0x25960000,
- 0x00000010, 0xb1870021,
+ 0x00000010, 0xb187001f,
0x0000000c, 0x29800000,
0x0000000f, 0x0f6b0007,
0x00000000, 0x0d690000,
@@ -14290,7 +14528,7 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x0b6e0000,
0x00000000, 0x0b800000,
0x00000000, 0x0c870000,
- 0x00000018, 0x8000ff18,
+ 0x00000018, 0x8000ff2f,
0x00000001, 0x0c161400,
0x00000000, 0x8c181400,
0x00000008, 0x0c960001,
@@ -14298,8 +14536,6 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000008, 0x0c990001,
0x00000000, 0x0d190000,
0x00000000, 0x0c000000,
- 0x00000010, 0x20560000,
- 0x0000000c, 0x2bd70001,
0x00000008, 0x0f800001,
0x00000010, 0x20530000,
0x0000000c, 0x69520001,
@@ -14311,7 +14547,7 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x26900000,
0x00000010, 0xb8170e03,
0x0000000c, 0x29800000,
- 0x00000018, 0x8000ffeb,
+ 0x00000018, 0x8000ffed,
0x00000000, 0x82970e00,
0x00000000, 0xa3120a00,
0x00000008, 0x2200001a,
@@ -14331,9 +14567,7 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000008, 0x2c800050,
0x00000008, 0x2d000030,
0x00000008, 0x2d80000c,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000fef1,
- 0x00000000, 0x26460000,
+ 0x00000018, 0x8000ff0b,
0x00000000, 0x23000000,
0x00000009, 0x25e6ffff,
0x00000000, 0x0b6e0000,
@@ -14341,87 +14575,120 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000008, 0x2200001b,
0x0000000c, 0x69520000,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000fee7,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000ff03,
0x00000000, 0x2a000000,
- 0x00000010, 0x003f000c,
- 0x00000000, 0x06660000,
- 0x00000000, 0x86611800,
- 0x00000009, 0x026000f0,
- 0x00000010, 0xb70c0808,
- 0x00000000, 0x2c400000,
- 0x0000000c, 0x73660010,
- 0x00000008, 0x2c800018,
- 0x00000008, 0x2d000018,
- 0x00000008, 0x2d800002,
- 0x0000000c, 0x5fbf0000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000fed8,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000ff01,
0x00000000, 0x2a000000,
- 0x00000000, 0x2c400000,
- 0x0000000c, 0x73660010,
- 0x00000008, 0x2c800018,
- 0x00000008, 0x2d000018,
- 0x00000008, 0x2d800002,
- 0x0000000c, 0x5fbf0000,
- 0x00000010, 0x91de0000,
- 0x00000008, 0x2c800003,
- 0x00000008, 0x2d000003,
- 0x00000009, 0x3060fff0,
- 0x00000008, 0x2d800001,
0x0000000c, 0x29800000,
0x00000010, 0x91de0000,
0x00000008, 0x2c80001a,
0x00000008, 0x2d00001a,
- 0x00000000, 0x33000000,
+ 0x00000005, 0x73660000,
0x00000008, 0x2d800002,
0x00000000, 0x31800000,
0x00000010, 0x91de0000,
0x00000008, 0x2c80000c,
0x00000008, 0x2d00000c,
0x00000008, 0x2d800004,
+ 0x00000018, 0x8000fef4,
+ 0x00000008, 0x06660001,
+ 0x00000010, 0xba9a1972,
+ 0x00000000, 0x0a640000,
+ 0x00000000, 0x0ae50000,
+ 0x00000009, 0x0b66ffff,
+ 0x00000000, 0x0c000000,
+ 0x00000000, 0x0b800000,
+ 0x00000008, 0x0cc60012,
+ 0x00000018, 0x8000ff1d,
+ 0x00000008, 0x0f800003,
+ 0x00000000, 0x00000000,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6bd70001,
+ 0x00000008, 0x27110012,
+ 0x00000000, 0x66900000,
+ 0x00000010, 0x919b3200,
+ 0x00000010, 0x02930000,
+ 0x00000010, 0xb1980003,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6bd70001,
+ 0x00000008, 0x0f800004,
+ 0x0000000c, 0x29800000,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6bd70001,
+ 0x00000010, 0xba9a2c00,
+ 0x00000000, 0x31e32e00,
+ 0x00000000, 0x0b800000,
+ 0x00000000, 0x8ccc8c00,
+ 0x00000010, 0xb5cc8c02,
+ 0x00000008, 0x0c800001,
+ 0x00000018, 0x8000ff07,
+ 0x00000008, 0x0f800003,
0x00000010, 0x20530000,
- 0x00000010, 0x91de0000,
- 0x00000018, 0x8000febd,
- 0x00000018, 0x8000febc,
+ 0x0000000c, 0x69520001,
+ 0x00000000, 0x22c58c00,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6bd70001,
+ 0x00000000, 0x27110000,
+ 0x00000000, 0x26900000,
+ 0x00000000, 0x231b0000,
+ 0x00000010, 0xb1980003,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6bd70001,
+ 0x00000008, 0x0f800004,
+ 0x00000008, 0x22000003,
+ 0x00000008, 0x2c80000c,
+ 0x00000008, 0x2d00000c,
+ 0x00000010, 0x001f0000,
+ 0x0000000c, 0x6bd70001,
+ 0x00000000, 0x25960000,
+ 0x0000000c, 0x29800000,
+ 0x00000000, 0x32140000,
+ 0x00000000, 0x32950000,
+ 0x00000005, 0x73662c00,
+ 0x00000000, 0x31e32e00,
+ 0x00000008, 0x2d800010,
+ 0x00000018, 0x8000febb,
+ 0x00000018, 0x8000feba,
0x00000000, 0x2a000000,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
0x00000000, 0x0f008000,
0x00000008, 0x0f800007,
- 0x00000018, 0x80000015,
+ 0x00000018, 0x8000001c,
+ 0x00000000, 0x280a0000,
0x00000000, 0x05020000,
0x00000008, 0x22000009,
- 0x00000000, 0x286d0000,
0x00000000, 0x29000000,
0x0000000f, 0x65680010,
+ 0x00000000, 0x248a0000,
0x00000003, 0xf66c9400,
0x00000010, 0xb972a004,
0x0000000c, 0x73e70019,
0x0000000c, 0x21420004,
- 0x00000000, 0x3bf60000,
+ 0x00000000, 0x3cf80000,
0x0000000c, 0x29800000,
0x00000010, 0x20530000,
0x00000008, 0x22000008,
0x0000000c, 0x61420004,
0x00000018, 0x000a0000,
+ 0x00000000, 0x05020000,
+ 0x0000000c, 0x61420000,
+ 0x00000010, 0x01420003,
+ 0x0000000c, 0x33e7001d,
+ 0x0000000c, 0x61420002,
+ 0x00000018, 0x000a0000,
0x00000000, 0x2a000000,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
0x0000000f, 0x0f470007,
0x00000008, 0x0f800008,
0x0000000c, 0x29800000,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000fe9f,
- 0x00000010, 0x91de0000,
- 0x00000000, 0x2fd50000,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
+ 0x00000018, 0x8000fe95,
0x00000000, 0x33510000,
0x00000000, 0x2a000000,
- 0x00000010, 0xb1c60029,
+ 0x00000010, 0xb1c60025,
0x0000000f, 0x0f500007,
0x00000000, 0x0a600000,
0x00000000, 0x0ae10000,
@@ -14436,8 +14703,6 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x0cc60000,
0x00000000, 0x0b800000,
0x00000000, 0x06980000,
- 0x00000010, 0x20560000,
- 0x0000000c, 0x2bd70001,
0x00000008, 0x0f800003,
0x00000010, 0x06c20004,
0x0000000c, 0x29000002,
@@ -14450,7 +14715,7 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x27111a00,
0x00000000, 0x66900000,
0x0000000c, 0x29520000,
- 0x00000010, 0xb197320c,
+ 0x00000010, 0xb197320a,
0x0000000c, 0x29800000,
0x00000000, 0x06980000,
0x00000010, 0x20530000,
@@ -14458,10 +14723,8 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000000, 0x22c58c00,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
- 0x00000010, 0x20560000,
- 0x0000000c, 0x2bd70001,
0x00000008, 0x0f800003,
- 0x00000018, 0x8000ffef,
+ 0x00000018, 0x8000fff1,
0x00000010, 0xb1c80013,
0x00000010, 0xb1c60003,
0x0000000c, 0x29800000,
@@ -14499,14 +14762,12 @@ u32 bce_xi90_rv2p_proc2[] = {
0x00000008, 0x2d80000c,
0x00000000, 0x00000000,
0x00000010, 0x91de0000,
- 0x00000010, 0x05c20003,
- 0x00000000, 0x33000000,
+ 0x00000010, 0x05c20005,
0x00000008, 0x0f800007,
- 0x00000010, 0x20530000,
+ 0x00000000, 0x33000000,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
- 0x00000018, 0x8000fe44,
- 0x00000000, 0x2fd50000,
+ 0x00000018, 0x8000fe43,
0x00000000, 0x2a000000,
0x0000000f, 0x0f500007,
0x00000010, 0xb1c60030,
@@ -14569,14 +14830,13 @@ u32 bce_xi90_rv2p_proc2[] = {
0x0000000c, 0x29800000,
0x00000010, 0x001f0000,
0x0000000c, 0x6bd70001,
- 0x00000010, 0x20530000,
- 0x00000018, 0x8000fe03,
+ 0x00000018, 0x8000fe04,
};
-/*
+/*
* The RV2P block must be configured for the system
- * page size, or more specifically, the number of
+ * page size, or more specifically, the number of
* usable rx_bd's per page, and should be called
* as follows prior to loading the RV2P firmware:
*
diff --git a/freebsd/sys/dev/bce/if_bcereg.h b/freebsd/sys/dev/bce/if_bcereg.h
index 1f2ed1df..14b5affe 100644
--- a/freebsd/sys/dev/bce/if_bcereg.h
+++ b/freebsd/sys/dev/bce/if_bcereg.h
@@ -302,18 +302,18 @@
#define BCE_CP_INTR 0x00000008
#define BCE_CP_UNLOAD 0x00000010
#define BCE_CP_RESET 0x00000020
-#define BCE_CP_PHY 0x00000040
+#define BCE_CP_PHY 0x00000040
#define BCE_CP_NVRAM 0x00000080
-#define BCE_CP_FIRMWARE 0x00000100
-#define BCE_CP_CTX 0x00000200
-#define BCE_CP_REG 0x00000400
+#define BCE_CP_FIRMWARE 0x00000100
+#define BCE_CP_CTX 0x00000200
+#define BCE_CP_REG 0x00000400
#define BCE_CP_MISC 0x00400000
#define BCE_CP_SPECIAL 0x00800000
-#define BCE_CP_ALL 0x00FFFFFF
+#define BCE_CP_ALL 0x00FFFFFF
#define BCE_CP_MASK 0x00FFFFFF
-#define BCE_LEVEL_FATAL 0x00000000
+#define BCE_LEVEL_FATAL 0x00000000
#define BCE_LEVEL_WARN 0x01000000
#define BCE_LEVEL_INFO 0x02000000
#define BCE_LEVEL_VERBOSE 0x03000000
@@ -326,28 +326,28 @@
#define BCE_INFO_LOAD (BCE_CP_LOAD | BCE_LEVEL_INFO)
#define BCE_VERBOSE_LOAD (BCE_CP_LOAD | BCE_LEVEL_VERBOSE)
#define BCE_EXTREME_LOAD (BCE_CP_LOAD | BCE_LEVEL_EXTREME)
-#define BCE_INSANE_LOAD (BCE_CP_LOAD | BCE_LEVEL_INSANE)
+#define BCE_INSANE_LOAD (BCE_CP_LOAD | BCE_LEVEL_INSANE)
#define BCE_WARN_SEND (BCE_CP_SEND | BCE_LEVEL_WARN)
#define BCE_INFO_SEND (BCE_CP_SEND | BCE_LEVEL_INFO)
#define BCE_VERBOSE_SEND (BCE_CP_SEND | BCE_LEVEL_VERBOSE)
#define BCE_EXTREME_SEND (BCE_CP_SEND | BCE_LEVEL_EXTREME)
-#define BCE_INSANE_SEND (BCE_CP_SEND | BCE_LEVEL_INSANE)
+#define BCE_INSANE_SEND (BCE_CP_SEND | BCE_LEVEL_INSANE)
#define BCE_WARN_RECV (BCE_CP_RECV | BCE_LEVEL_WARN)
#define BCE_INFO_RECV (BCE_CP_RECV | BCE_LEVEL_INFO)
#define BCE_VERBOSE_RECV (BCE_CP_RECV | BCE_LEVEL_VERBOSE)
#define BCE_EXTREME_RECV (BCE_CP_RECV | BCE_LEVEL_EXTREME)
-#define BCE_INSANE_RECV (BCE_CP_RECV | BCE_LEVEL_INSANE)
+#define BCE_INSANE_RECV (BCE_CP_RECV | BCE_LEVEL_INSANE)
#define BCE_WARN_INTR (BCE_CP_INTR | BCE_LEVEL_WARN)
#define BCE_INFO_INTR (BCE_CP_INTR | BCE_LEVEL_INFO)
#define BCE_VERBOSE_INTR (BCE_CP_INTR | BCE_LEVEL_VERBOSE)
#define BCE_EXTREME_INTR (BCE_CP_INTR | BCE_LEVEL_EXTREME)
-#define BCE_INSANE_INTR (BCE_CP_INTR | BCE_LEVEL_INSANE)
+#define BCE_INSANE_INTR (BCE_CP_INTR | BCE_LEVEL_INSANE)
-#define BCE_WARN_UNLOAD (BCE_CP_UNLOAD | BCE_LEVEL_WARN)
-#define BCE_INFO_UNLOAD (BCE_CP_UNLOAD | BCE_LEVEL_INFO)
+#define BCE_WARN_UNLOAD (BCE_CP_UNLOAD | BCE_LEVEL_WARN)
+#define BCE_INFO_UNLOAD (BCE_CP_UNLOAD | BCE_LEVEL_INFO)
#define BCE_VERBOSE_UNLOAD (BCE_CP_UNLOAD | BCE_LEVEL_VERBOSE)
#define BCE_EXTREME_UNLOAD (BCE_CP_UNLOAD | BCE_LEVEL_EXTREME)
#define BCE_INSANE_UNLOAD (BCE_CP_UNLOAD | BCE_LEVEL_INSANE)
@@ -360,8 +360,8 @@
#define BCE_WARN_PHY (BCE_CP_PHY | BCE_LEVEL_WARN)
#define BCE_INFO_PHY (BCE_CP_PHY | BCE_LEVEL_INFO)
-#define BCE_VERBOSE_PHY (BCE_CP_PHY | BCE_LEVEL_VERBOSE)
-#define BCE_EXTREME_PHY (BCE_CP_PHY | BCE_LEVEL_EXTREME)
+#define BCE_VERBOSE_PHY (BCE_CP_PHY | BCE_LEVEL_VERBOSE)
+#define BCE_EXTREME_PHY (BCE_CP_PHY | BCE_LEVEL_EXTREME)
#define BCE_INSANE_PHY (BCE_CP_PHY | BCE_LEVEL_INSANE)
#define BCE_WARN_NVRAM (BCE_CP_NVRAM | BCE_LEVEL_WARN)
@@ -372,40 +372,40 @@
#define BCE_WARN_FIRMWARE (BCE_CP_FIRMWARE | BCE_LEVEL_WARN)
#define BCE_INFO_FIRMWARE (BCE_CP_FIRMWARE | BCE_LEVEL_INFO)
-#define BCE_VERBOSE_FIRMWARE (BCE_CP_FIRMWARE | BCE_LEVEL_VERBOSE)
-#define BCE_EXTREME_FIRMWARE (BCE_CP_FIRMWARE | BCE_LEVEL_EXTREME)
-#define BCE_INSANE_FIRMWARE (BCE_CP_FIRMWARE | BCE_LEVEL_INSANE)
+#define BCE_VERBOSE_FIRMWARE (BCE_CP_FIRMWARE | BCE_LEVEL_VERBOSE)
+#define BCE_EXTREME_FIRMWARE (BCE_CP_FIRMWARE | BCE_LEVEL_EXTREME)
+#define BCE_INSANE_FIRMWARE (BCE_CP_FIRMWARE | BCE_LEVEL_INSANE)
#define BCE_WARN_CTX (BCE_CP_CTX | BCE_LEVEL_WARN)
#define BCE_INFO_CTX (BCE_CP_CTX | BCE_LEVEL_INFO)
-#define BCE_VERBOSE_CTX (BCE_CP_CTX | BCE_LEVEL_VERBOSE)
-#define BCE_EXTREME_CTX (BCE_CP_CTX | BCE_LEVEL_EXTREME)
+#define BCE_VERBOSE_CTX (BCE_CP_CTX | BCE_LEVEL_VERBOSE)
+#define BCE_EXTREME_CTX (BCE_CP_CTX | BCE_LEVEL_EXTREME)
#define BCE_INSANE_CTX (BCE_CP_CTX | BCE_LEVEL_INSANE)
#define BCE_WARN_REG (BCE_CP_REG | BCE_LEVEL_WARN)
#define BCE_INFO_REG (BCE_CP_REG | BCE_LEVEL_INFO)
-#define BCE_VERBOSE_REG (BCE_CP_REG | BCE_LEVEL_VERBOSE)
-#define BCE_EXTREME_REG (BCE_CP_REG | BCE_LEVEL_EXTREME)
+#define BCE_VERBOSE_REG (BCE_CP_REG | BCE_LEVEL_VERBOSE)
+#define BCE_EXTREME_REG (BCE_CP_REG | BCE_LEVEL_EXTREME)
#define BCE_INSANE_REG (BCE_CP_REG | BCE_LEVEL_INSANE)
#define BCE_WARN_MISC (BCE_CP_MISC | BCE_LEVEL_WARN)
#define BCE_INFO_MISC (BCE_CP_MISC | BCE_LEVEL_INFO)
#define BCE_VERBOSE_MISC (BCE_CP_MISC | BCE_LEVEL_VERBOSE)
#define BCE_EXTREME_MISC (BCE_CP_MISC | BCE_LEVEL_EXTREME)
-#define BCE_INSANE_MISC (BCE_CP_MISC | BCE_LEVEL_INSANE)
+#define BCE_INSANE_MISC (BCE_CP_MISC | BCE_LEVEL_INSANE)
#define BCE_WARN_SPECIAL (BCE_CP_SPECIAL | BCE_LEVEL_WARN)
#define BCE_INFO_SPECIAL (BCE_CP_SPECIAL | BCE_LEVEL_INFO)
-#define BCE_VERBOSE_SPECIAL (BCE_CP_SPECIAL | BCE_LEVEL_VERBOSE)
-#define BCE_EXTREME_SPECIAL (BCE_CP_SPECIAL | BCE_LEVEL_EXTREME)
+#define BCE_VERBOSE_SPECIAL (BCE_CP_SPECIAL | BCE_LEVEL_VERBOSE)
+#define BCE_EXTREME_SPECIAL (BCE_CP_SPECIAL | BCE_LEVEL_EXTREME)
#define BCE_INSANE_SPECIAL (BCE_CP_SPECIAL | BCE_LEVEL_INSANE)
-#define BCE_FATAL (BCE_CP_ALL | BCE_LEVEL_FATAL)
-#define BCE_WARN (BCE_CP_ALL | BCE_LEVEL_WARN)
-#define BCE_INFO (BCE_CP_ALL | BCE_LEVEL_INFO)
+#define BCE_FATAL (BCE_CP_ALL | BCE_LEVEL_FATAL)
+#define BCE_WARN (BCE_CP_ALL | BCE_LEVEL_WARN)
+#define BCE_INFO (BCE_CP_ALL | BCE_LEVEL_INFO)
#define BCE_VERBOSE (BCE_CP_ALL | BCE_LEVEL_VERBOSE)
#define BCE_EXTREME (BCE_CP_ALL | BCE_LEVEL_EXTREME)
-#define BCE_INSANE (BCE_CP_ALL | BCE_LEVEL_INSANE)
+#define BCE_INSANE (BCE_CP_ALL | BCE_LEVEL_INSANE)
#define BCE_CODE_PATH(cp) ((cp & BCE_CP_MASK) & bce_debug)
#define BCE_MSG_LEVEL(lv) \
@@ -576,7 +576,6 @@ default: DBPRINT(sc, BCE_INSANE_PHY, \
#define BCE_CHIP_NUM_5706 0x57060000
#define BCE_CHIP_NUM_5708 0x57080000
#define BCE_CHIP_NUM_5709 0x57090000
-#define BCE_CHIP_NUM_5716 0x57160000
#define BCE_CHIP_REV(sc) (((sc)->bce_chipid) & 0x0000f000)
#define BCE_CHIP_REV_Ax 0x00000000
@@ -601,7 +600,6 @@ default: DBPRINT(sc, BCE_INSANE_PHY, \
#define BCE_CHIP_ID_5709_B1 0x57091010
#define BCE_CHIP_ID_5709_B2 0x57091020
#define BCE_CHIP_ID_5709_C0 0x57092000
-#define BCE_CHIP_ID_5716_C0 0x57162000
#define BCE_CHIP_BOND_ID(sc) (((sc)->bce_chipid) & 0xf)
@@ -625,7 +623,7 @@ struct bce_type {
u_int16_t bce_did;
u_int16_t bce_svid;
u_int16_t bce_sdid;
- char *bce_name;
+ const char *bce_name;
};
/****************************************************************************/
@@ -719,7 +717,7 @@ struct flash_spec {
u32 page_size;
u32 addr_mask;
u32 total_size;
- u8 *name;
+ const u8 *name;
};
@@ -816,6 +814,23 @@ struct flash_spec {
#define BCE_DRV_PULSE_SEQ_MASK 0x00007fff
#define BCE_MB_ARGS_0 0x00000014
+#define BCE_NETLINK_SPEED_10HALF (1<<0)
+#define BCE_NETLINK_SPEED_10FULL (1<<1)
+#define BCE_NETLINK_SPEED_100HALF (1<<2)
+#define BCE_NETLINK_SPEED_100FULL (1<<3)
+#define BCE_NETLINK_SPEED_1000HALF (1<<4)
+#define BCE_NETLINK_SPEED_1000FULL (1<<5)
+#define BCE_NETLINK_SPEED_2500HALF (1<<6)
+#define BCE_NETLINK_SPEED_2500FULL (1<<7)
+#define BCE_NETLINK_SPEED_10GHALF (1<<8)
+#define BCE_NETLINK_SPEED_10GFULL (1<<9)
+#define BCE_NETLINK_ANEG_ENB (1<<10)
+#define BCE_NETLINK_PHY_APP_REMOTE (1<<11)
+#define BCE_NETLINK_FC_PAUSE_SYM (1<<12)
+#define BCE_NETLINK_FC_PAUSE_ASYM (1<<13)
+#define BCE_NETLINK_ETH_AT_WIRESPEED (1<<14)
+#define BCE_NETLINK_PHY_RESET (1<<15)
+
#define BCE_MB_ARGS_1 0x00000018
/* Indicate to the firmware not to go into the
@@ -1081,6 +1096,26 @@ struct flash_spec {
#define BCE_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff
#define BCE_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff
+#define BCE_FW_EVT_CODE_MB 0x00000354
+#define BCE_FW_EVT_CODE_SW_TIMER_EXPIRE_EVENT 0x00000000
+#define BCE_FW_EVT_CODE_LINK_EVENT 0x00000001
+
+#define BCE_DRV_ACK_CAP_MB 0x00000364
+#define BCE_DRV_ACK_CAP_SIGNATURE_MAGIC 0x35450000
+
+#define BCE_FW_CAP_MB 0x00000368
+#define BCE_FW_CAP_SIGNATURE_MAGIC 0xaa550000
+#define BCE_FW_ACK_SIGNATURE_MAGIC 0x52500000
+#define BCE_FW_CAP_SIGNATURE_MAGIC_MASK 0xffff0000
+#define BCE_FW_CAP_REMOTE_PHY_CAP 0x00000001
+#define BCE_FW_CAP_REMOTE_PHY_PRESENT 0x00000002
+#define BCE_FW_CAP_MFW_KEEP_VLAN 0x00000008
+#define BCE_FW_CAP_BC_KEEP_VLAN 0x00000010
+
+#define BCE_RPHY_SERDES_LINK 0x00000374
+
+#define BCE_RPHY_COPPER_LINK 0x00000378
+
#define HOST_VIEW_SHMEM_BASE 0x167c00
/*
@@ -1155,20 +1190,19 @@ struct tx_bd {
u32 tx_bd_haddr_lo;
u32 tx_bd_mss_nbytes;
u16 tx_bd_flags;
+#define TX_BD_FLAGS_CONN_FAULT (1<<0)
+#define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1)
+#define TX_BD_FLAGS_IP_CKSUM (1<<2)
+#define TX_BD_FLAGS_VLAN_TAG (1<<3)
+#define TX_BD_FLAGS_COAL_NOW (1<<4)
+#define TX_BD_FLAGS_DONT_GEN_CRC (1<<5)
+#define TX_BD_FLAGS_END (1<<6)
+#define TX_BD_FLAGS_START (1<<7)
+#define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8)
+#define TX_BD_FLAGS_SW_FLAGS (1<<13)
+#define TX_BD_FLAGS_SW_SNAP (1<<14)
+#define TX_BD_FLAGS_SW_LSO (1<<15)
u16 tx_bd_vlan_tag;
- #define TX_BD_FLAGS_CONN_FAULT (1<<0)
- #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1)
- #define TX_BD_FLAGS_IP_CKSUM (1<<2)
- #define TX_BD_FLAGS_VLAN_TAG (1<<3)
- #define TX_BD_FLAGS_COAL_NOW (1<<4)
- #define TX_BD_FLAGS_DONT_GEN_CRC (1<<5)
- #define TX_BD_FLAGS_END (1<<6)
- #define TX_BD_FLAGS_START (1<<7)
- #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8)
- #define TX_BD_FLAGS_SW_FLAGS (1<<13)
- #define TX_BD_FLAGS_SW_SNAP (1<<14)
- #define TX_BD_FLAGS_SW_LSO (1<<15)
-
};
@@ -1180,11 +1214,10 @@ struct rx_bd {
u32 rx_bd_haddr_lo;
u32 rx_bd_len;
u32 rx_bd_flags;
- #define RX_BD_FLAGS_NOPUSH (1<<0)
- #define RX_BD_FLAGS_DUMMY (1<<1)
- #define RX_BD_FLAGS_END (1<<2)
- #define RX_BD_FLAGS_START (1<<3)
-
+#define RX_BD_FLAGS_NOPUSH (1<<0)
+#define RX_BD_FLAGS_DUMMY (1<<1)
+#define RX_BD_FLAGS_END (1<<2)
+#define RX_BD_FLAGS_START (1<<3)
};
@@ -1387,6 +1420,7 @@ struct l2_fhdr {
#define L2_FHDR_ERRORS_ALIGNMENT (1<<19)
#define L2_FHDR_ERRORS_TOO_SHORT (1<<20)
#define L2_FHDR_ERRORS_GIANT_FRAME (1<<21)
+ #define L2_FHDR_ERRORS_IPV4_BAD_LEN (1<<22)
#define L2_FHDR_ERRORS_TCP_XSUM (1<<28)
#define L2_FHDR_ERRORS_UDP_XSUM (1<<31)
@@ -1405,36 +1439,39 @@ struct l2_fhdr {
};
#define BCE_L2FHDR_PRINTFB \
- "\20" \
+ "\20" \
"\40UDP_XSUM_ERR" \
- "\37b30" \
- "\36b29" \
+ "\37b30" \
+ "\36b29" \
"\35TCP_XSUM_ERR" \
- "\34b27" \
- "\33b26" \
- "\32b25" \
- "\31b24" \
- "\30b23" \
- "\27b22" \
+ "\34b27" \
+ "\33b26" \
+ "\32b25" \
+ "\31b24" \
+ "\30b23" \
+ "\27IPv4_BAL_LEN" \
"\26GIANT_ERR" \
"\25SHORT_ERR" \
"\24ALIGN_ERR" \
"\23PHY_ERR" \
"\22CRC_ERR" \
- "\21SPLIT" \
- "\20UDP" \
- "\17TCP" \
- "\16IP" \
- "\15b12" \
- "\14b11" \
- "\13b10" \
- "\12b09" \
- "\11RSS" \
- "\10SNAP" \
- "\07VLAN" \
- "\06P4" \
- "\05P3" \
- "\04P2"
+ "\21SPLIT" \
+ "\20UDP" \
+ "\17TCP" \
+ "\16IP" \
+ "\15SORT_b3" \
+ "\14SORT_b2" \
+ "\13SORT_b1" \
+ "\12SORT_b0" \
+ "\11RSS" \
+ "\10SNAP" \
+ "\07VLAN" \
+ "\06P4" \
+ "\05P3" \
+ "\04P2" \
+ "\03RULE_b2" \
+ "\02RULE_b1" \
+ "\01RULE_b0"
/*
@@ -1965,7 +2002,7 @@ struct l2_fhdr {
#define BCE_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27)
#define BCE_MISC_ENABLE_CLR_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
#define BCE_MISC_ENABLE_CLR_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
-
+
#define BCE_MISC_ENABLE_CLR_DEFAULT 0x17ffffff
#define BCE_MISC_CLOCK_CONTROL_BITS 0x00000818
@@ -6150,18 +6187,20 @@ struct l2_fhdr {
* Page count must remain a power of 2 for all
* of the math to work correctly.
*/
-#define TX_PAGES 2
-#define TOTAL_TX_BD_PER_PAGE (BCM_PAGE_SIZE / sizeof(struct tx_bd))
-#define USABLE_TX_BD_PER_PAGE (TOTAL_TX_BD_PER_PAGE - 1)
-#define TOTAL_TX_BD (TOTAL_TX_BD_PER_PAGE * TX_PAGES)
-#define USABLE_TX_BD (USABLE_TX_BD_PER_PAGE * TX_PAGES)
-#define MAX_TX_BD (TOTAL_TX_BD - 1)
+#define DEFAULT_TX_PAGES 2
+#define MAX_TX_PAGES 8
+#define TOTAL_TX_BD_PER_PAGE (BCM_PAGE_SIZE / sizeof(struct tx_bd))
+#define USABLE_TX_BD_PER_PAGE (TOTAL_TX_BD_PER_PAGE - 1)
+#define MAX_TX_BD_AVAIL (MAX_TX_PAGES * TOTAL_TX_BD_PER_PAGE)
+#define TOTAL_TX_BD_ALLOC (TOTAL_TX_BD_PER_PAGE * sc->tx_pages)
+#define USABLE_TX_BD_ALLOC (USABLE_TX_BD_PER_PAGE * sc->tx_pages)
+#define MAX_TX_BD_ALLOC (TOTAL_TX_BD_ALLOC - 1)
/* Advance to the next tx_bd, skipping any next page pointers. */
#define NEXT_TX_BD(x) (((x) & USABLE_TX_BD_PER_PAGE) == \
(USABLE_TX_BD_PER_PAGE - 1)) ? (x) + 2 : (x) + 1
-#define TX_CHAIN_IDX(x) ((x) & MAX_TX_BD)
+#define TX_CHAIN_IDX(x) ((x) & MAX_TX_BD_ALLOC)
#define TX_PAGE(x) (((x) & ~USABLE_TX_BD_PER_PAGE) >> (BCM_PAGE_BITS - 4))
#define TX_IDX(x) ((x) & USABLE_TX_BD_PER_PAGE)
@@ -6170,45 +6209,46 @@ struct l2_fhdr {
* Page count must remain a power of 2 for all
* of the math to work correctly.
*/
-#define RX_PAGES 2
-#define TOTAL_RX_BD_PER_PAGE (BCM_PAGE_SIZE / sizeof(struct rx_bd))
-#define USABLE_RX_BD_PER_PAGE (TOTAL_RX_BD_PER_PAGE - 1)
-#define TOTAL_RX_BD (TOTAL_RX_BD_PER_PAGE * RX_PAGES)
-#define USABLE_RX_BD (USABLE_RX_BD_PER_PAGE * RX_PAGES)
-#define MAX_RX_BD (TOTAL_RX_BD - 1)
+#define DEFAULT_RX_PAGES 2
+#define MAX_RX_PAGES 8
+#define TOTAL_RX_BD_PER_PAGE (BCM_PAGE_SIZE / sizeof(struct rx_bd))
+#define USABLE_RX_BD_PER_PAGE (TOTAL_RX_BD_PER_PAGE - 1)
+#define MAX_RX_BD_AVAIL (MAX_RX_PAGES * TOTAL_RX_BD_PER_PAGE)
+#define TOTAL_RX_BD_ALLOC (TOTAL_RX_BD_PER_PAGE * sc->rx_pages)
+#define USABLE_RX_BD_ALLOC (USABLE_RX_BD_PER_PAGE * sc->rx_pages)
+#define MAX_RX_BD_ALLOC (TOTAL_RX_BD_ALLOC - 1)
/* Advance to the next rx_bd, skipping any next page pointers. */
#define NEXT_RX_BD(x) (((x) & USABLE_RX_BD_PER_PAGE) == \
(USABLE_RX_BD_PER_PAGE - 1)) ? (x) + 2 : (x) + 1
-#define RX_CHAIN_IDX(x) ((x) & MAX_RX_BD)
+#define RX_CHAIN_IDX(x) ((x) & MAX_RX_BD_ALLOC)
#define RX_PAGE(x) (((x) & ~USABLE_RX_BD_PER_PAGE) >> (BCM_PAGE_BITS - 4))
#define RX_IDX(x) ((x) & USABLE_RX_BD_PER_PAGE)
-#ifdef BCE_JUMBO_HDRSPLIT
/*
* To accomodate jumbo frames, the page chain should
* be 4 times larger than the receive chain.
*/
-#define PG_PAGES (RX_PAGES * 4)
-#define TOTAL_PG_BD_PER_PAGE (BCM_PAGE_SIZE / sizeof(struct rx_bd))
-#define USABLE_PG_BD_PER_PAGE (TOTAL_PG_BD_PER_PAGE - 1)
-#define TOTAL_PG_BD (TOTAL_PG_BD_PER_PAGE * PG_PAGES)
-#define USABLE_PG_BD (USABLE_PG_BD_PER_PAGE * PG_PAGES)
-#define MAX_PG_BD (TOTAL_PG_BD - 1)
+#define DEFAULT_PG_PAGES (DEFAULT_RX_PAGES * 4)
+#define MAX_PG_PAGES (MAX_RX_PAGES * 4)
+#define TOTAL_PG_BD_PER_PAGE (BCM_PAGE_SIZE / sizeof(struct rx_bd))
+#define USABLE_PG_BD_PER_PAGE (TOTAL_PG_BD_PER_PAGE - 1)
+#define MAX_PG_BD_AVAIL (MAX_PG_PAGES * TOTAL_PG_BD_PER_PAGE)
+#define TOTAL_PG_BD_ALLOC (TOTAL_PG_BD_PER_PAGE * sc->pg_pages)
+#define USABLE_PG_BD_ALLOC (USABLE_PG_BD_PER_PAGE * sc->pg_pages)
+#define MAX_PG_BD_ALLOC (TOTAL_PG_BD_ALLOC - 1)
/* Advance to the next pg_bd, skipping any next page pointers. */
#define NEXT_PG_BD(x) (((x) & USABLE_PG_BD_PER_PAGE) == \
(USABLE_PG_BD_PER_PAGE - 1)) ? (x) + 2 : (x) + 1
-#define PG_CHAIN_IDX(x) ((x) & MAX_PG_BD)
+#define PG_CHAIN_IDX(x) ((x) & MAX_PG_BD_ALLOC)
#define PG_PAGE(x) (((x) & ~USABLE_PG_BD_PER_PAGE) >> (BCM_PAGE_BITS - 4))
#define PG_IDX(x) ((x) & USABLE_PG_BD_PER_PAGE)
-#endif /* BCE_JUMBO_HDRSPLIT */
-
#define CTX_INIT_RETRY_COUNT 10
/* Context size. */
@@ -6236,6 +6276,15 @@ struct l2_fhdr {
#define TX_CID 16
#define RX_CID 0
+#define DEFAULT_TX_QUICK_CONS_TRIP_INT 20
+#define DEFAULT_TX_QUICK_CONS_TRIP 20
+#define DEFAULT_TX_TICKS_INT 80
+#define DEFAULT_TX_TICKS 80
+#define DEFAULT_RX_QUICK_CONS_TRIP_INT 6
+#define DEFAULT_RX_QUICK_CONS_TRIP 6
+#define DEFAULT_RX_TICKS_INT 18
+#define DEFAULT_RX_TICKS 18
+
/****************************************************************************/
/* BCE Processor Firmwware Load Definitions */
/****************************************************************************/
@@ -6270,19 +6319,19 @@ struct fw_info {
u32 text_addr;
u32 text_len;
u32 text_index;
- u32 *text;
+ const u32 *text;
/* Data section. */
u32 data_addr;
u32 data_len;
u32 data_index;
- u32 *data;
+ const u32 *data;
/* SBSS section. */
u32 sbss_addr;
u32 sbss_len;
u32 sbss_index;
- u32 *sbss;
+ const u32 *sbss;
/* BSS section. */
u32 bss_addr;
@@ -6373,7 +6422,7 @@ struct fw_info {
struct bce_softc
{
- /* Interface info. Must be first!! */
+ /* Interface info */
struct ifnet *bce_ifp;
/* Parent device handle */
@@ -6403,10 +6452,7 @@ struct bce_softc
struct mtx bce_mtx;
/* Interrupt handler. */
- driver_intr_t *bce_intr;
void *bce_intrhand;
- int bce_irq_rid;
- int bce_msi_count;
/* ASIC Chip ID. */
u32 bce_chipid;
@@ -6442,6 +6488,8 @@ struct bce_softc
#define BCE_PHY_INT_MODE_AUTO_POLLING_FLAG 0x00000100
#define BCE_PHY_INT_MODE_LINK_READY_FLAG 0x00000200
#define BCE_PHY_IEEE_CLAUSE_45_FLAG 0x00000400
+#define BCE_PHY_REMOTE_CAP_FLAG 0x00000800
+#define BCE_PHY_REMOTE_PORT_FIBER_FLAG 0x00001000
/* Values that need to be shared with the PHY driver. */
u32 bce_shared_hw_cfg;
@@ -6459,7 +6507,7 @@ struct bce_softc
u16 link_speed;
/* Flash NVRAM settings */
- struct flash_spec *bce_flash_info;
+ const struct flash_spec *bce_flash_info;
/* Flash NVRAM size */
u32 bce_flash_size;
@@ -6468,7 +6516,7 @@ struct bce_softc
u32 bce_shmem_base;
/* Name string */
- char *bce_name;
+ const char *bce_name;
/* Tracks the version of bootcode firmware. */
char bce_bc_ver[32];
@@ -6530,26 +6578,27 @@ struct bce_softc
/* The device handle for the MII bus child device. */
device_t bce_miibus;
- /* Driver maintained TX chain pointers and byte counter. */
+ /* Driver maintained RX chain pointers and byte counter. */
u16 rx_prod;
u16 rx_cons;
/* Counts the bytes used in the RX chain. */
u32 rx_prod_bseq;
+
+ /* Driver maintained TX chain pointers and byte counter. */
u16 tx_prod;
u16 tx_cons;
/* Counts the bytes used in the TX chain. */
u32 tx_prod_bseq;
-#ifdef BCE_JUMBO_HDRSPLIT
+ /* Driver maintained PG chain pointers. */
u16 pg_prod;
u16 pg_cons;
-#endif
int bce_link_up;
- struct callout bce_tick_callout;
- struct callout bce_pulse_callout;
+ struct callout bce_tick_callout;
+ struct callout bce_pulse_callout;
/* Ticks until chip reset */
int watchdog_timer;
@@ -6559,10 +6608,7 @@ struct bce_softc
int rx_bd_mbuf_alloc_size;
int rx_bd_mbuf_data_len;
int rx_bd_mbuf_align_pad;
-
-#ifdef BCE_JUMBO_HDRSPLIT
int pg_bd_mbuf_alloc_size;
-#endif
/* Receive mode settings (i.e promiscuous, multicast, etc.). */
u32 rx_mode;
@@ -6571,30 +6617,31 @@ struct bce_softc
bus_dma_tag_t parent_tag;
/* H/W maintained TX buffer descriptor chain structure. */
+ int tx_pages;
bus_dma_tag_t tx_bd_chain_tag;
- bus_dmamap_t tx_bd_chain_map[TX_PAGES];
- struct tx_bd *tx_bd_chain[TX_PAGES];
- bus_addr_t tx_bd_chain_paddr[TX_PAGES];
+ bus_dmamap_t tx_bd_chain_map[MAX_TX_PAGES];
+ struct tx_bd *tx_bd_chain[MAX_TX_PAGES];
+ bus_addr_t tx_bd_chain_paddr[MAX_TX_PAGES];
/* H/W maintained RX buffer descriptor chain structure. */
+ int rx_pages;
bus_dma_tag_t rx_bd_chain_tag;
- bus_dmamap_t rx_bd_chain_map[RX_PAGES];
- struct rx_bd *rx_bd_chain[RX_PAGES];
- bus_addr_t rx_bd_chain_paddr[RX_PAGES];
+ bus_dmamap_t rx_bd_chain_map[MAX_RX_PAGES];
+ struct rx_bd *rx_bd_chain[MAX_RX_PAGES];
+ bus_addr_t rx_bd_chain_paddr[MAX_RX_PAGES];
-#ifdef BCE_JUMBO_HDRSPLIT
/* H/W maintained page buffer descriptor chain structure. */
+ int pg_pages;
bus_dma_tag_t pg_bd_chain_tag;
- bus_dmamap_t pg_bd_chain_map[PG_PAGES];
- struct rx_bd *pg_bd_chain[PG_PAGES];
- bus_addr_t pg_bd_chain_paddr[PG_PAGES];
-#endif
+ bus_dmamap_t pg_bd_chain_map[MAX_PG_PAGES];
+ struct rx_bd *pg_bd_chain[MAX_PG_PAGES];
+ bus_addr_t pg_bd_chain_paddr[MAX_PG_PAGES];
/* H/W maintained status block. */
bus_dma_tag_t status_tag;
bus_dmamap_t status_map;
struct status_block *status_block;
- bus_addr_t status_block_paddr;
+ bus_addr_t status_block_paddr;
/* Driver maintained status block values. */
u16 last_status_idx;
@@ -6605,49 +6652,41 @@ struct bce_softc
bus_dma_tag_t stats_tag;
bus_dmamap_t stats_map;
struct statistics_block *stats_block;
- bus_addr_t stats_block_paddr;
+ bus_addr_t stats_block_paddr;
/* H/W maintained context block. */
- int ctx_pages;
+ int ctx_pages;
bus_dma_tag_t ctx_tag;
/* BCM5709/16 use host memory for context. */
bus_dmamap_t ctx_map[BCE_MAX_CONTEXT];
- void *ctx_block[BCE_MAX_CONTEXT];
- bus_addr_t ctx_paddr[BCE_MAX_CONTEXT];
+ void *ctx_block[BCE_MAX_CONTEXT];
+ bus_addr_t ctx_paddr[BCE_MAX_CONTEXT];
/* Bus tag for RX/TX mbufs. */
bus_dma_tag_t rx_mbuf_tag;
bus_dma_tag_t tx_mbuf_tag;
-
-#ifdef BCE_JUMBO_HDRSPLIT
bus_dma_tag_t pg_mbuf_tag;
-#endif
/* S/W maintained mbuf TX chain structure. */
- bus_dmamap_t tx_mbuf_map[TOTAL_TX_BD];
- struct mbuf *tx_mbuf_ptr[TOTAL_TX_BD];
+ bus_dmamap_t tx_mbuf_map[MAX_TX_BD_AVAIL];
+ struct mbuf *tx_mbuf_ptr[MAX_TX_BD_AVAIL];
/* S/W maintained mbuf RX chain structure. */
- bus_dmamap_t rx_mbuf_map[TOTAL_RX_BD];
- struct mbuf *rx_mbuf_ptr[TOTAL_RX_BD];
+ bus_dmamap_t rx_mbuf_map[MAX_RX_BD_AVAIL];
+ struct mbuf *rx_mbuf_ptr[MAX_RX_BD_AVAIL];
-#ifdef BCE_JUMBO_HDRSPLIT
/* S/W maintained mbuf page chain structure. */
- bus_dmamap_t pg_mbuf_map[TOTAL_PG_BD];
- struct mbuf *pg_mbuf_ptr[TOTAL_PG_BD];
-#endif
+ bus_dmamap_t pg_mbuf_map[MAX_PG_BD_AVAIL];
+ struct mbuf *pg_mbuf_ptr[MAX_PG_BD_AVAIL];
/* Track the number of buffer descriptors in use. */
u16 free_rx_bd;
u16 max_rx_bd;
u16 used_tx_bd;
u16 max_tx_bd;
-
-#ifdef BCE_JUMBO_HDRSPLIT
u16 free_pg_bd;
u16 max_pg_bd;
-#endif
/* Provides access to hardware statistics through sysctl. */
u64 stat_IfHCInOctets;
@@ -6733,64 +6772,63 @@ struct bce_softc
/* Track the number of enqueued mbufs. */
int debug_tx_mbuf_alloc;
int debug_rx_mbuf_alloc;
-
-#ifdef BCE_JUMBO_HDRSPLIT
int debug_pg_mbuf_alloc;
-#endif
/* Track how many and what type of interrupts are generated. */
- u32 interrupts_generated;
- u32 interrupts_handled;
- u32 interrupts_rx;
- u32 interrupts_tx;
- u32 phy_interrupts;
-
- /* Track interrupt time (25MHz clock). */
- u64 rx_intr_time;
- u64 tx_intr_time;
+ u64 interrupts_generated;
+ u64 interrupts_handled;
+ u64 interrupts_rx;
+ u64 interrupts_tx;
+ u64 phy_interrupts;
/* Lowest number of rx_bd's free. */
- u32 rx_low_watermark;
+ u16 rx_low_watermark;
/* Number of times the RX chain was empty. */
- u32 rx_empty_count;
+ u64 rx_empty_count;
-#ifdef BCE_JUMBO_HDRSPLIT
/* Lowest number of pages free. */
- u32 pg_low_watermark;
+ u16 pg_low_watermark;
/* Number of times the page chain was empty. */
- u32 pg_empty_count;
-#endif
+ u64 pg_empty_count;
/* Greatest number of tx_bd's used. */
- u32 tx_hi_watermark;
+ u16 tx_hi_watermark;
/* Number of times the TX chain was full. */
- u32 tx_full_count;
+ u64 tx_full_count;
/* Number of TSO frames requested. */
- u32 tso_frames_requested;
+ u64 tso_frames_requested;
/* Number of TSO frames completed. */
- u32 tso_frames_completed;
+ u64 tso_frames_completed;
/* Number of TSO frames failed. */
- u32 tso_frames_failed;
+ u64 tso_frames_failed;
/* Number of IP checksum offload frames.*/
- u32 csum_offload_ip;
+ u64 csum_offload_ip;
/* Number of TCP/UDP checksum offload frames.*/
- u32 csum_offload_tcp_udp;
+ u64 csum_offload_tcp_udp;
/* Number of VLAN tagged frames received. */
- u32 vlan_tagged_frames_rcvd;
+ u64 vlan_tagged_frames_rcvd;
/* Number of VLAN tagged frames stripped. */
- u32 vlan_tagged_frames_stripped;
-#endif
-};
+ u64 vlan_tagged_frames_stripped;
+
+ /* Number of split header frames received. */
+ u64 split_header_frames_rcvd;
+
+ /* Number of split header TCP frames received. */
+ u64 split_header_tcp_frames_rcvd;
-#endif /* __BCEREG_HH_DEFINED */
+ /* Buffer with NVRAM contents for the NIC. */
+ u8 *nvram_buf;
+#endif /* BCE_DEBUG */
+};
+#endif /* __BCEREG_H_DEFINED */
diff --git a/freebsd/sys/dev/bfe/if_bfe.c b/freebsd/sys/dev/bfe/if_bfe.c
index 74746c28..d793c054 100644
--- a/freebsd/sys/dev/bfe/if_bfe.c
+++ b/freebsd/sys/dev/bfe/if_bfe.c
@@ -139,16 +139,12 @@ static device_method_t bfe_methods[] = {
DEVMETHOD(device_suspend, bfe_suspend),
DEVMETHOD(device_resume, bfe_resume),
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
-
/* MII interface */
DEVMETHOD(miibus_readreg, bfe_miibus_readreg),
DEVMETHOD(miibus_writereg, bfe_miibus_writereg),
DEVMETHOD(miibus_statchg, bfe_miibus_statchg),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t bfe_driver = {
@@ -1738,18 +1734,15 @@ bfe_ifmedia_upd(struct ifnet *ifp)
{
struct bfe_softc *sc;
struct mii_data *mii;
+ struct mii_softc *miisc;
int error;
sc = ifp->if_softc;
BFE_LOCK(sc);
mii = device_get_softc(sc->bfe_miibus);
- if (mii->mii_instance) {
- struct mii_softc *miisc;
- for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
- miisc = LIST_NEXT(miisc, mii_list))
- mii_phy_reset(miisc);
- }
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ mii_phy_reset(miisc);
error = mii_mediachg(mii);
BFE_UNLOCK(sc);
diff --git a/freebsd/sys/dev/bge/if_bge.c b/freebsd/sys/dev/bge/if_bge.c
index 06f5ba7b..14a90eb7 100644
--- a/freebsd/sys/dev/bge/if_bge.c
+++ b/freebsd/sys/dev/bge/if_bge.c
@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
*
* The Broadcom BCM5700 is based on technology originally developed by
* Alteon Networks as part of the Tigon I and Tigon II gigabit ethernet
- * MAC chips. The BCM5700, sometimes refered to as the Tigon III, has
+ * MAC chips. The BCM5700, sometimes referred to as the Tigon III, has
* two on-board MIPS R4000 CPUs and can have as much as 16MB of external
* SSRAM. The BCM5700 supports TCP, UDP and IP checksum offload, jumbo
* frames, highly configurable RX filtering, and 16 RX and TX queues
@@ -173,6 +173,7 @@ static const struct bge_type {
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5715S },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5717 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5718 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM5719 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5720 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5721 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5722 },
@@ -216,9 +217,17 @@ static const struct bge_type {
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5906 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM5906M },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57760 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM57761 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM57762 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM57765 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM57766 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57780 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM57781 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM57785 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57788 },
{ BCOM_VENDORID, BCOM_DEVICEID_BCM57790 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM57791 },
+ { BCOM_VENDORID, BCOM_DEVICEID_BCM57795 },
{ SK_VENDORID, SK_DEVICEID_ALTIMA },
@@ -295,6 +304,8 @@ static const struct bge_revision {
{ BGE_CHIPID_BCM5715_A3, "BCM5715 A3" },
{ BGE_CHIPID_BCM5717_A0, "BCM5717 A0" },
{ BGE_CHIPID_BCM5717_B0, "BCM5717 B0" },
+ { BGE_CHIPID_BCM5719_A0, "BCM5719 A0" },
+ { BGE_CHIPID_BCM5720_A0, "BCM5720 A0" },
{ BGE_CHIPID_BCM5755_A0, "BCM5755 A0" },
{ BGE_CHIPID_BCM5755_A1, "BCM5755 A1" },
{ BGE_CHIPID_BCM5755_A2, "BCM5755 A2" },
@@ -309,6 +320,8 @@ static const struct bge_revision {
{ BGE_CHIPID_BCM5787_A2, "BCM5754/5787 A2" },
{ BGE_CHIPID_BCM5906_A1, "BCM5906 A1" },
{ BGE_CHIPID_BCM5906_A2, "BCM5906 A2" },
+ { BGE_CHIPID_BCM57765_A0, "BCM57765 A0" },
+ { BGE_CHIPID_BCM57765_B0, "BCM57765 B0" },
{ BGE_CHIPID_BCM57780_A0, "BCM57780 A0" },
{ BGE_CHIPID_BCM57780_A1, "BCM57780 A1" },
@@ -337,8 +350,12 @@ static const struct bge_revision bge_majorrevs[] = {
/* 5754 and 5787 share the same ASIC ID */
{ BGE_ASICREV_BCM5787, "unknown BCM5754/5787" },
{ BGE_ASICREV_BCM5906, "unknown BCM5906" },
+ { BGE_ASICREV_BCM57765, "unknown BCM57765" },
+ { BGE_ASICREV_BCM57766, "unknown BCM57766" },
{ BGE_ASICREV_BCM57780, "unknown BCM57780" },
{ BGE_ASICREV_BCM5717, "unknown BCM5717" },
+ { BGE_ASICREV_BCM5719, "unknown BCM5719" },
+ { BGE_ASICREV_BCM5720, "unknown BCM5720" },
{ 0, NULL }
};
@@ -350,6 +367,7 @@ static const struct bge_revision bge_majorrevs[] = {
#define BGE_IS_575X_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_575X_PLUS)
#define BGE_IS_5755_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5755_PLUS)
#define BGE_IS_5717_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5717_PLUS)
+#define BGE_IS_57765_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_57765_PLUS)
const struct bge_revision * bge_lookup_rev(uint32_t);
const struct bge_vendor * bge_lookup_vendor(uint16_t);
@@ -368,6 +386,9 @@ static void bge_dma_free(struct bge_softc *);
static int bge_dma_ring_alloc(struct bge_softc *, bus_size_t, bus_size_t,
bus_dma_tag_t *, uint8_t **, bus_dmamap_t *, bus_addr_t *, const char *);
+static void bge_devinfo(struct bge_softc *);
+static int bge_mbox_reorder(struct bge_softc *);
+
static int bge_get_eaddr_fw(struct bge_softc *sc, uint8_t ether_addr[]);
static int bge_get_eaddr_mem(struct bge_softc *, uint8_t[]);
static int bge_get_eaddr_nvram(struct bge_softc *, uint8_t[]);
@@ -396,6 +417,7 @@ static void bge_start(struct ifnet *);
static int bge_ioctl(struct ifnet *, u_long, caddr_t);
static void bge_init_locked(struct bge_softc *);
static void bge_init(void *);
+static void bge_stop_block(struct bge_softc *, bus_size_t, uint32_t);
static void bge_stop(struct bge_softc *);
static void bge_watchdog(struct bge_softc *);
static int bge_shutdown(device_t);
@@ -426,6 +448,7 @@ static int bge_init_tx_ring(struct bge_softc *);
static int bge_chipinit(struct bge_softc *);
static int bge_blockinit(struct bge_softc *);
+static uint32_t bge_dma_swap_options(struct bge_softc *);
static int bge_has_eaddr(struct bge_softc *);
static uint32_t bge_readmem_ind(struct bge_softc *, int);
@@ -444,8 +467,9 @@ static void bge_miibus_statchg(device_t);
static int bge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
#endif
-#define BGE_RESET_START 1
-#define BGE_RESET_STOP 2
+#define BGE_RESET_SHUTDOWN 0
+#define BGE_RESET_START 1
+#define BGE_RESET_SUSPEND 2
static void bge_sig_post_reset(struct bge_softc *, int);
static void bge_sig_legacy(struct bge_softc *, int);
static void bge_sig_pre_reset(struct bge_softc *, int);
@@ -453,6 +477,13 @@ static void bge_stop_fw(struct bge_softc *);
static int bge_reset(struct bge_softc *);
static void bge_link_upd(struct bge_softc *);
+static void bge_ape_lock_init(struct bge_softc *);
+static void bge_ape_read_fw_ver(struct bge_softc *);
+static int bge_ape_lock(struct bge_softc *, int);
+static void bge_ape_unlock(struct bge_softc *, int);
+static void bge_ape_send_event(struct bge_softc *, uint32_t);
+static void bge_ape_driver_state_change(struct bge_softc *, int);
+
/*
* The BGE_REGISTER_DEBUG option is only for low-level debugging. It may
* leak information to untrusted users. It is also known to cause alignment
@@ -461,6 +492,7 @@ static void bge_link_upd(struct bge_softc *);
#ifdef BGE_REGISTER_DEBUG
static int bge_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
static int bge_sysctl_reg_read(SYSCTL_HANDLER_ARGS);
+static int bge_sysctl_ape_read(SYSCTL_HANDLER_ARGS);
static int bge_sysctl_mem_read(SYSCTL_HANDLER_ARGS);
#endif
static void bge_add_sysctls(struct bge_softc *);
@@ -479,16 +511,12 @@ static device_method_t bge_methods[] = {
DEVMETHOD(device_suspend, bge_suspend),
DEVMETHOD(device_resume, bge_resume),
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
-
/* MII interface */
DEVMETHOD(miibus_readreg, bge_miibus_readreg),
DEVMETHOD(miibus_writereg, bge_miibus_writereg),
DEVMETHOD(miibus_statchg, bge_miibus_statchg),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t bge_driver = {
@@ -625,6 +653,320 @@ bge_writembx(struct bge_softc *sc, int off, int val)
off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI;
CSR_WRITE_4(sc, off, val);
+ if ((sc->bge_flags & BGE_FLAG_MBOX_REORDER) != 0)
+ CSR_READ_4(sc, off);
+}
+
+/*
+ * Clear all stale locks and select the lock for this driver instance.
+ */
+static void
+bge_ape_lock_init(struct bge_softc *sc)
+{
+ uint32_t bit, regbase;
+ int i;
+
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+ regbase = BGE_APE_LOCK_GRANT;
+ else
+ regbase = BGE_APE_PER_LOCK_GRANT;
+
+ /* Clear any stale locks. */
+ for (i = BGE_APE_LOCK_PHY0; i <= BGE_APE_LOCK_GPIO; i++) {
+ switch (i) {
+ case BGE_APE_LOCK_PHY0:
+ case BGE_APE_LOCK_PHY1:
+ case BGE_APE_LOCK_PHY2:
+ case BGE_APE_LOCK_PHY3:
+ bit = BGE_APE_LOCK_GRANT_DRIVER0;
+ break;
+ default:
+ if (sc->bge_func_addr != 0)
+ bit = BGE_APE_LOCK_GRANT_DRIVER0;
+ else
+ bit = (1 << sc->bge_func_addr);
+ }
+ APE_WRITE_4(sc, regbase + 4 * i, bit);
+ }
+
+ /* Select the PHY lock based on the device's function number. */
+ switch (sc->bge_func_addr) {
+ case 0:
+ sc->bge_phy_ape_lock = BGE_APE_LOCK_PHY0;
+ break;
+ case 1:
+ sc->bge_phy_ape_lock = BGE_APE_LOCK_PHY1;
+ break;
+ case 2:
+ sc->bge_phy_ape_lock = BGE_APE_LOCK_PHY2;
+ break;
+ case 3:
+ sc->bge_phy_ape_lock = BGE_APE_LOCK_PHY3;
+ break;
+ default:
+ device_printf(sc->bge_dev,
+ "PHY lock not supported on this function\n");
+ }
+}
+
+/*
+ * Check for APE firmware, set flags, and print version info.
+ */
+static void
+bge_ape_read_fw_ver(struct bge_softc *sc)
+{
+ const char *fwtype;
+ uint32_t apedata, features;
+
+ /* Check for a valid APE signature in shared memory. */
+ apedata = APE_READ_4(sc, BGE_APE_SEG_SIG);
+ if (apedata != BGE_APE_SEG_SIG_MAGIC) {
+ sc->bge_mfw_flags &= ~ BGE_MFW_ON_APE;
+ return;
+ }
+
+ /* Check if APE firmware is running. */
+ apedata = APE_READ_4(sc, BGE_APE_FW_STATUS);
+ if ((apedata & BGE_APE_FW_STATUS_READY) == 0) {
+ device_printf(sc->bge_dev, "APE signature found "
+ "but FW status not ready! 0x%08x\n", apedata);
+ return;
+ }
+
+ sc->bge_mfw_flags |= BGE_MFW_ON_APE;
+
+ /* Fetch the APE firwmare type and version. */
+ apedata = APE_READ_4(sc, BGE_APE_FW_VERSION);
+ features = APE_READ_4(sc, BGE_APE_FW_FEATURES);
+ if ((features & BGE_APE_FW_FEATURE_NCSI) != 0) {
+ sc->bge_mfw_flags |= BGE_MFW_TYPE_NCSI;
+ fwtype = "NCSI";
+ } else if ((features & BGE_APE_FW_FEATURE_DASH) != 0) {
+ sc->bge_mfw_flags |= BGE_MFW_TYPE_DASH;
+ fwtype = "DASH";
+ } else
+ fwtype = "UNKN";
+
+ /* Print the APE firmware version. */
+ device_printf(sc->bge_dev, "APE FW version: %s v%d.%d.%d.%d\n",
+ fwtype,
+ (apedata & BGE_APE_FW_VERSION_MAJMSK) >> BGE_APE_FW_VERSION_MAJSFT,
+ (apedata & BGE_APE_FW_VERSION_MINMSK) >> BGE_APE_FW_VERSION_MINSFT,
+ (apedata & BGE_APE_FW_VERSION_REVMSK) >> BGE_APE_FW_VERSION_REVSFT,
+ (apedata & BGE_APE_FW_VERSION_BLDMSK));
+}
+
+static int
+bge_ape_lock(struct bge_softc *sc, int locknum)
+{
+ uint32_t bit, gnt, req, status;
+ int i, off;
+
+ if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) == 0)
+ return (0);
+
+ /* Lock request/grant registers have different bases. */
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5761) {
+ req = BGE_APE_LOCK_REQ;
+ gnt = BGE_APE_LOCK_GRANT;
+ } else {
+ req = BGE_APE_PER_LOCK_REQ;
+ gnt = BGE_APE_PER_LOCK_GRANT;
+ }
+
+ off = 4 * locknum;
+
+ switch (locknum) {
+ case BGE_APE_LOCK_GPIO:
+ /* Lock required when using GPIO. */
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+ return (0);
+ if (sc->bge_func_addr == 0)
+ bit = BGE_APE_LOCK_REQ_DRIVER0;
+ else
+ bit = (1 << sc->bge_func_addr);
+ break;
+ case BGE_APE_LOCK_GRC:
+ /* Lock required to reset the device. */
+ if (sc->bge_func_addr == 0)
+ bit = BGE_APE_LOCK_REQ_DRIVER0;
+ else
+ bit = (1 << sc->bge_func_addr);
+ break;
+ case BGE_APE_LOCK_MEM:
+ /* Lock required when accessing certain APE memory. */
+ if (sc->bge_func_addr == 0)
+ bit = BGE_APE_LOCK_REQ_DRIVER0;
+ else
+ bit = (1 << sc->bge_func_addr);
+ break;
+ case BGE_APE_LOCK_PHY0:
+ case BGE_APE_LOCK_PHY1:
+ case BGE_APE_LOCK_PHY2:
+ case BGE_APE_LOCK_PHY3:
+ /* Lock required when accessing PHYs. */
+ bit = BGE_APE_LOCK_REQ_DRIVER0;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ /* Request a lock. */
+ APE_WRITE_4(sc, req + off, bit);
+
+ /* Wait up to 1 second to acquire lock. */
+ for (i = 0; i < 20000; i++) {
+ status = APE_READ_4(sc, gnt + off);
+ if (status == bit)
+ break;
+ DELAY(50);
+ }
+
+ /* Handle any errors. */
+ if (status != bit) {
+ device_printf(sc->bge_dev, "APE lock %d request failed! "
+ "request = 0x%04x[0x%04x], status = 0x%04x[0x%04x]\n",
+ locknum, req + off, bit & 0xFFFF, gnt + off,
+ status & 0xFFFF);
+ /* Revoke the lock request. */
+ APE_WRITE_4(sc, gnt + off, bit);
+ return (EBUSY);
+ }
+
+ return (0);
+}
+
+static void
+bge_ape_unlock(struct bge_softc *sc, int locknum)
+{
+ uint32_t bit, gnt;
+ int off;
+
+ if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) == 0)
+ return;
+
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+ gnt = BGE_APE_LOCK_GRANT;
+ else
+ gnt = BGE_APE_PER_LOCK_GRANT;
+
+ off = 4 * locknum;
+
+ switch (locknum) {
+ case BGE_APE_LOCK_GPIO:
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5761)
+ return;
+ if (sc->bge_func_addr == 0)
+ bit = BGE_APE_LOCK_GRANT_DRIVER0;
+ else
+ bit = (1 << sc->bge_func_addr);
+ break;
+ case BGE_APE_LOCK_GRC:
+ if (sc->bge_func_addr == 0)
+ bit = BGE_APE_LOCK_GRANT_DRIVER0;
+ else
+ bit = (1 << sc->bge_func_addr);
+ break;
+ case BGE_APE_LOCK_MEM:
+ if (sc->bge_func_addr == 0)
+ bit = BGE_APE_LOCK_GRANT_DRIVER0;
+ else
+ bit = (1 << sc->bge_func_addr);
+ break;
+ case BGE_APE_LOCK_PHY0:
+ case BGE_APE_LOCK_PHY1:
+ case BGE_APE_LOCK_PHY2:
+ case BGE_APE_LOCK_PHY3:
+ bit = BGE_APE_LOCK_GRANT_DRIVER0;
+ break;
+ default:
+ return;
+ }
+
+ APE_WRITE_4(sc, gnt + off, bit);
+}
+
+/*
+ * Send an event to the APE firmware.
+ */
+static void
+bge_ape_send_event(struct bge_softc *sc, uint32_t event)
+{
+ uint32_t apedata;
+ int i;
+
+ /* NCSI does not support APE events. */
+ if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) == 0)
+ return;
+
+ /* Wait up to 1ms for APE to service previous event. */
+ for (i = 10; i > 0; i--) {
+ if (bge_ape_lock(sc, BGE_APE_LOCK_MEM) != 0)
+ break;
+ apedata = APE_READ_4(sc, BGE_APE_EVENT_STATUS);
+ if ((apedata & BGE_APE_EVENT_STATUS_EVENT_PENDING) == 0) {
+ APE_WRITE_4(sc, BGE_APE_EVENT_STATUS, event |
+ BGE_APE_EVENT_STATUS_EVENT_PENDING);
+ bge_ape_unlock(sc, BGE_APE_LOCK_MEM);
+ APE_WRITE_4(sc, BGE_APE_EVENT, BGE_APE_EVENT_1);
+ break;
+ }
+ bge_ape_unlock(sc, BGE_APE_LOCK_MEM);
+ DELAY(100);
+ }
+ if (i == 0)
+ device_printf(sc->bge_dev, "APE event 0x%08x send timed out\n",
+ event);
+}
+
+static void
+bge_ape_driver_state_change(struct bge_softc *sc, int kind)
+{
+ uint32_t apedata, event;
+
+ if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) == 0)
+ return;
+
+ switch (kind) {
+ case BGE_RESET_START:
+ /* If this is the first load, clear the load counter. */
+ apedata = APE_READ_4(sc, BGE_APE_HOST_SEG_SIG);
+ if (apedata != BGE_APE_HOST_SEG_SIG_MAGIC)
+ APE_WRITE_4(sc, BGE_APE_HOST_INIT_COUNT, 0);
+ else {
+ apedata = APE_READ_4(sc, BGE_APE_HOST_INIT_COUNT);
+ APE_WRITE_4(sc, BGE_APE_HOST_INIT_COUNT, ++apedata);
+ }
+ APE_WRITE_4(sc, BGE_APE_HOST_SEG_SIG,
+ BGE_APE_HOST_SEG_SIG_MAGIC);
+ APE_WRITE_4(sc, BGE_APE_HOST_SEG_LEN,
+ BGE_APE_HOST_SEG_LEN_MAGIC);
+
+ /* Add some version info if bge(4) supports it. */
+ APE_WRITE_4(sc, BGE_APE_HOST_DRIVER_ID,
+ BGE_APE_HOST_DRIVER_ID_MAGIC(1, 0));
+ APE_WRITE_4(sc, BGE_APE_HOST_BEHAVIOR,
+ BGE_APE_HOST_BEHAV_NO_PHYLOCK);
+ APE_WRITE_4(sc, BGE_APE_HOST_HEARTBEAT_INT_MS,
+ BGE_APE_HOST_HEARTBEAT_INT_DISABLE);
+ APE_WRITE_4(sc, BGE_APE_HOST_DRVR_STATE,
+ BGE_APE_HOST_DRVR_STATE_START);
+ event = BGE_APE_EVENT_STATUS_STATE_START;
+ break;
+ case BGE_RESET_SHUTDOWN:
+ APE_WRITE_4(sc, BGE_APE_HOST_DRVR_STATE,
+ BGE_APE_HOST_DRVR_STATE_UNLOAD);
+ event = BGE_APE_EVENT_STATUS_STATE_UNLOAD;
+ break;
+ case BGE_RESET_SUSPEND:
+ event = BGE_APE_EVENT_STATUS_STATE_SUSPEND;
+ break;
+ default:
+ return;
+ }
+
+ bge_ape_send_event(sc, event | BGE_APE_EVENT_STATUS_DRIVER_EVNT |
+ BGE_APE_EVENT_STATUS_STATE_CHNGE);
}
/*
@@ -791,6 +1133,9 @@ bge_miibus_readreg(device_t dev, int phy, int reg)
sc = device_get_softc(dev);
+ if (bge_ape_lock(sc, sc->bge_phy_ape_lock) != 0)
+ return (0);
+
/* Clear the autopoll bit if set, otherwise may trigger PCI errors. */
if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
CSR_WRITE_4(sc, BGE_MI_MODE,
@@ -825,6 +1170,8 @@ bge_miibus_readreg(device_t dev, int phy, int reg)
DELAY(80);
}
+ bge_ape_unlock(sc, sc->bge_phy_ape_lock);
+
if (val & BGE_MICOMM_READFAIL)
return (0);
@@ -843,6 +1190,9 @@ bge_miibus_writereg(device_t dev, int phy, int reg, int val)
(reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL))
return (0);
+ if (bge_ape_lock(sc, sc->bge_phy_ape_lock) != 0)
+ return (0);
+
/* Clear the autopoll bit if set, otherwise may trigger PCI errors. */
if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
CSR_WRITE_4(sc, BGE_MI_MODE,
@@ -868,9 +1218,11 @@ bge_miibus_writereg(device_t dev, int phy, int reg, int val)
DELAY(80);
}
+ bge_ape_unlock(sc, sc->bge_phy_ape_lock);
+
if (i == BGE_TIMEOUT)
device_printf(sc->bge_dev,
- "PHY write timed out (phy %d, reg %d, val %d)\n",
+ "PHY write timed out (phy %d, reg %d, val 0x%04x)\n",
phy, reg, val);
return (0);
@@ -881,7 +1233,11 @@ bge_miibus_statchg(device_t dev)
{
struct bge_softc *sc;
struct mii_data *mii;
+ uint32_t mac_mode, rx_mode, tx_mode;
+
sc = device_get_softc(dev);
+ if ((sc->bge_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
mii = device_get_softc(sc->bge_miibus);
if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
@@ -907,30 +1263,40 @@ bge_miibus_statchg(device_t dev)
sc->bge_link = 0;
if (sc->bge_link == 0)
return;
- BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE);
+
+ /*
+ * APE firmware touches these registers to keep the MAC
+ * connected to the outside world. Try to keep the
+ * accesses atomic.
+ */
+
+ /* Set the port mode (MII/GMII) to match the link speed. */
+ mac_mode = CSR_READ_4(sc, BGE_MAC_MODE) &
+ ~(BGE_MACMODE_PORTMODE | BGE_MACMODE_HALF_DUPLEX);
+ tx_mode = CSR_READ_4(sc, BGE_TX_MODE);
+ rx_mode = CSR_READ_4(sc, BGE_RX_MODE);
+
if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX)
- BGE_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_GMII);
+ mac_mode |= BGE_PORTMODE_GMII;
else
- BGE_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_MII);
+ mac_mode |= BGE_PORTMODE_MII;
+ /* Set MAC flow control behavior to match link flow control settings. */
+ tx_mode &= ~BGE_TXMODE_FLOWCTL_ENABLE;
+ rx_mode &= ~BGE_RXMODE_FLOWCTL_ENABLE;
if (IFM_OPTIONS(mii->mii_media_active & IFM_FDX) != 0) {
- BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
- if ((IFM_OPTIONS(mii->mii_media_active) &
- IFM_ETH_TXPAUSE) != 0)
- BGE_SETBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE);
- else
- BGE_CLRBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE);
- if ((IFM_OPTIONS(mii->mii_media_active) &
- IFM_ETH_RXPAUSE) != 0)
- BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE);
- else
- BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE);
- } else {
- BGE_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX);
- BGE_CLRBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE);
- BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE);
- }
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
+ tx_mode |= BGE_TXMODE_FLOWCTL_ENABLE;
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
+ rx_mode |= BGE_RXMODE_FLOWCTL_ENABLE;
+ } else
+ mac_mode |= BGE_MACMODE_HALF_DUPLEX;
+
+ CSR_WRITE_4(sc, BGE_MAC_MODE, mac_mode);
+ DELAY(40);
+ CSR_WRITE_4(sc, BGE_TX_MODE, tx_mode);
+ CSR_WRITE_4(sc, BGE_RX_MODE, rx_mode);
}
/*
@@ -945,10 +1311,19 @@ bge_newbuf_std(struct bge_softc *sc, int i)
bus_dmamap_t map;
int error, nsegs;
- m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (m == NULL)
- return (ENOBUFS);
- m->m_len = m->m_pkthdr.len = MCLBYTES;
+ if (sc->bge_flags & BGE_FLAG_JUMBO_STD &&
+ (sc->bge_ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
+ ETHER_VLAN_ENCAP_LEN > (MCLBYTES - ETHER_ALIGN))) {
+ m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
+ if (m == NULL)
+ return (ENOBUFS);
+ m->m_len = m->m_pkthdr.len = MJUM9BYTES;
+ } else {
+ m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL)
+ return (ENOBUFS);
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
+ }
if ((sc->bge_flags & BGE_FLAG_RX_ALIGNBUG) == 0)
m_adj(m, ETHER_ALIGN);
@@ -1015,7 +1390,7 @@ bge_newbuf_jumbo(struct bge_softc *sc, int i)
return (error);
}
- if (sc->bge_cdata.bge_rx_jumbo_chain[i] == NULL) {
+ if (sc->bge_cdata.bge_rx_jumbo_chain[i] != NULL) {
bus_dmamap_sync(sc->bge_cdata.bge_mtag_jumbo,
sc->bge_cdata.bge_rx_jumbo_dmamap[i], BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->bge_cdata.bge_mtag_jumbo,
@@ -1289,18 +1664,27 @@ bge_sig_pre_reset(struct bge_softc *sc, int type)
* Some chips don't like this so only do this if ASF is enabled
*/
if (sc->bge_asf_mode)
- bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER);
+ bge_writemem_ind(sc, BGE_SRAM_FW_MB, BGE_SRAM_FW_MB_MAGIC);
if (sc->bge_asf_mode & ASF_NEW_HANDSHAKE) {
switch (type) {
case BGE_RESET_START:
- bge_writemem_ind(sc, BGE_SDI_STATUS, 0x1); /* START */
+ bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+ BGE_FW_DRV_STATE_START);
+ break;
+ case BGE_RESET_SHUTDOWN:
+ bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+ BGE_FW_DRV_STATE_UNLOAD);
break;
- case BGE_RESET_STOP:
- bge_writemem_ind(sc, BGE_SDI_STATUS, 0x2); /* UNLOAD */
+ case BGE_RESET_SUSPEND:
+ bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+ BGE_FW_DRV_STATE_SUSPEND);
break;
}
}
+
+ if (type == BGE_RESET_START || type == BGE_RESET_SUSPEND)
+ bge_ape_driver_state_change(sc, type);
}
static void
@@ -1310,14 +1694,18 @@ bge_sig_post_reset(struct bge_softc *sc, int type)
if (sc->bge_asf_mode & ASF_NEW_HANDSHAKE) {
switch (type) {
case BGE_RESET_START:
- bge_writemem_ind(sc, BGE_SDI_STATUS, 0x80000001);
+ bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+ BGE_FW_DRV_STATE_START_DONE);
/* START DONE */
break;
- case BGE_RESET_STOP:
- bge_writemem_ind(sc, BGE_SDI_STATUS, 0x80000002);
+ case BGE_RESET_SHUTDOWN:
+ bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+ BGE_FW_DRV_STATE_UNLOAD_DONE);
break;
}
}
+ if (type == BGE_RESET_SHUTDOWN)
+ bge_ape_driver_state_change(sc, type);
}
static void
@@ -1327,10 +1715,12 @@ bge_sig_legacy(struct bge_softc *sc, int type)
if (sc->bge_asf_mode) {
switch (type) {
case BGE_RESET_START:
- bge_writemem_ind(sc, BGE_SDI_STATUS, 0x1); /* START */
+ bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+ BGE_FW_DRV_STATE_START);
break;
- case BGE_RESET_STOP:
- bge_writemem_ind(sc, BGE_SDI_STATUS, 0x2); /* UNLOAD */
+ case BGE_RESET_SHUTDOWN:
+ bge_writemem_ind(sc, BGE_SRAM_FW_DRV_STATE_MB,
+ BGE_FW_DRV_STATE_UNLOAD);
break;
}
}
@@ -1342,25 +1732,39 @@ bge_stop_fw(struct bge_softc *sc)
int i;
if (sc->bge_asf_mode) {
- bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_FW, BGE_FW_PAUSE);
- CSR_WRITE_4(sc, BGE_CPU_EVENT,
- CSR_READ_4(sc, BGE_CPU_EVENT) | (1 << 14));
+ bge_writemem_ind(sc, BGE_SRAM_FW_CMD_MB, BGE_FW_CMD_PAUSE);
+ CSR_WRITE_4(sc, BGE_RX_CPU_EVENT,
+ CSR_READ_4(sc, BGE_RX_CPU_EVENT) | BGE_RX_CPU_DRV_EVENT);
for (i = 0; i < 100; i++ ) {
- if (!(CSR_READ_4(sc, BGE_CPU_EVENT) & (1 << 14)))
+ if (!(CSR_READ_4(sc, BGE_RX_CPU_EVENT) &
+ BGE_RX_CPU_DRV_EVENT))
break;
DELAY(10);
}
}
}
+static uint32_t
+bge_dma_swap_options(struct bge_softc *sc)
+{
+ uint32_t dma_options;
+
+ dma_options = BGE_MODECTL_WORDSWAP_NONFRAME |
+ BGE_MODECTL_BYTESWAP_DATA | BGE_MODECTL_WORDSWAP_DATA;
+#if BYTE_ORDER == BIG_ENDIAN
+ dma_options |= BGE_MODECTL_BYTESWAP_NONFRAME;
+#endif
+ return (dma_options);
+}
+
/*
* Do endian, PCI and DMA initialization.
*/
static int
bge_chipinit(struct bge_softc *sc)
{
- uint32_t dma_rw_ctl, misc_ctl;
+ uint32_t dma_rw_ctl, misc_ctl, mode_ctl;
uint16_t val;
int i;
@@ -1370,9 +1774,6 @@ bge_chipinit(struct bge_softc *sc)
misc_ctl |= BGE_PCIMISCCTL_TAGGED_STATUS;
pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, misc_ctl, 4);
- /* Clear the MAC control register */
- CSR_WRITE_4(sc, BGE_MAC_MODE, 0);
-
/*
* Clear the MAC statistics block in the NIC's
* internal memory.
@@ -1402,8 +1803,10 @@ bge_chipinit(struct bge_softc *sc)
dma_rw_ctl = BGE_PCIDMARWCTL_RD_CMD_SHIFT(6) |
BGE_PCIDMARWCTL_WR_CMD_SHIFT(7);
if (sc->bge_flags & BGE_FLAG_PCIE) {
- /* Read watermark not used, 128 bytes for write. */
- dma_rw_ctl |= BGE_PCIDMARWCTL_WR_WAT_SHIFT(3);
+ if (sc->bge_mps >= 256)
+ dma_rw_ctl |= BGE_PCIDMARWCTL_WR_WAT_SHIFT(7);
+ else
+ dma_rw_ctl |= BGE_PCIDMARWCTL_WR_WAT_SHIFT(3);
} else if (sc->bge_flags & BGE_FLAG_PCIX) {
if (BGE_IS_5714_FAMILY(sc)) {
/* 256 bytes for read and write. */
@@ -1460,16 +1863,34 @@ bge_chipinit(struct bge_softc *sc)
if (sc->bge_asicrev == BGE_ASICREV_BCM5703 ||
sc->bge_asicrev == BGE_ASICREV_BCM5704)
dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA;
- if (BGE_IS_5717_PLUS(sc))
+ if (BGE_IS_5717_PLUS(sc)) {
dma_rw_ctl &= ~BGE_PCIDMARWCTL_DIS_CACHE_ALIGNMENT;
+ if (sc->bge_chipid == BGE_CHIPID_BCM57765_A0)
+ dma_rw_ctl &= ~BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK;
+ /*
+ * Enable HW workaround for controllers that misinterpret
+ * a status tag update and leave interrupts permanently
+ * disabled.
+ */
+ if (sc->bge_asicrev != BGE_ASICREV_BCM5717 &&
+ sc->bge_asicrev != BGE_ASICREV_BCM57765)
+ dma_rw_ctl |= BGE_PCIDMARWCTL_TAGGED_STATUS_WA;
+ }
pci_write_config(sc->bge_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4);
/*
* Set up general mode register.
*/
- CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_DMA_SWAP_OPTIONS |
- BGE_MODECTL_MAC_ATTN_INTR | BGE_MODECTL_HOST_SEND_BDS |
- BGE_MODECTL_TX_NO_PHDR_CSUM);
+ mode_ctl = bge_dma_swap_options(sc);
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+ /* Retain Host-2-BMC settings written by APE firmware. */
+ mode_ctl |= CSR_READ_4(sc, BGE_MODE_CTL) &
+ (BGE_MODECTL_BYTESWAP_B2HRX_DATA |
+ BGE_MODECTL_WORDSWAP_B2HRX_DATA |
+ BGE_MODECTL_B2HRX_ENABLE | BGE_MODECTL_HTX2B_ENABLE);
+ }
+ mode_ctl |= BGE_MODECTL_MAC_ATTN_INTR | BGE_MODECTL_HOST_SEND_BDS |
+ BGE_MODECTL_TX_NO_PHDR_CSUM;
/*
* BCM5701 B5 have a bug causing data corruption when using
@@ -1479,13 +1900,15 @@ bge_chipinit(struct bge_softc *sc)
*/
if (sc->bge_asicrev == BGE_ASICREV_BCM5701 &&
sc->bge_chipid == BGE_CHIPID_BCM5701_B5)
- BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_FORCE_PCI32);
+ mode_ctl |= BGE_MODECTL_FORCE_PCI32;
/*
* Tell the firmware the driver is running
*/
if (sc->bge_asf_mode & ASF_STACKUP)
- BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+ mode_ctl |= BGE_MODECTL_STACKUP;
+
+ CSR_WRITE_4(sc, BGE_MODE_CTL, mode_ctl);
/*
* Disable memory write invalidate. Apparently it is not supported
@@ -1517,7 +1940,7 @@ bge_blockinit(struct bge_softc *sc)
struct bge_rcb *rcb;
bus_size_t vrcb;
bge_hostaddr taddr;
- uint32_t val;
+ uint32_t dmactl, val;
int i, limit;
/*
@@ -1545,7 +1968,7 @@ bge_blockinit(struct bge_softc *sc)
}
/* Configure mbuf pool watermarks */
- if (sc->bge_asicrev == BGE_ASICREV_BCM5717) {
+ if (BGE_IS_5717_PLUS(sc)) {
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
if (sc->bge_ifp->if_mtu > ETHERMTU) {
CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x7e);
@@ -1573,22 +1996,27 @@ bge_blockinit(struct bge_softc *sc)
CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10);
/* Enable buffer manager */
- if (!(BGE_IS_5705_PLUS(sc))) {
- CSR_WRITE_4(sc, BGE_BMAN_MODE,
- BGE_BMANMODE_ENABLE | BGE_BMANMODE_LOMBUF_ATTN);
+ val = BGE_BMANMODE_ENABLE | BGE_BMANMODE_LOMBUF_ATTN;
+ /*
+ * Change the arbitration algorithm of TXMBUF read request to
+ * round-robin instead of priority based for BCM5719. When
+ * TXFIFO is almost empty, RDMA will hold its request until
+ * TXFIFO is not almost empty.
+ */
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+ val |= BGE_BMANMODE_NO_TX_UNDERRUN;
+ CSR_WRITE_4(sc, BGE_BMAN_MODE, val);
- /* Poll for buffer manager start indication */
- for (i = 0; i < BGE_TIMEOUT; i++) {
- DELAY(10);
- if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE)
- break;
- }
+ /* Poll for buffer manager start indication */
+ for (i = 0; i < BGE_TIMEOUT; i++) {
+ DELAY(10);
+ if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE)
+ break;
+ }
- if (i == BGE_TIMEOUT) {
- device_printf(sc->bge_dev,
- "buffer manager failed to start\n");
- return (ENXIO);
- }
+ if (i == BGE_TIMEOUT) {
+ device_printf(sc->bge_dev, "buffer manager failed to start\n");
+ return (ENXIO);
}
/* Enable flow-through queues */
@@ -1674,7 +2102,9 @@ bge_blockinit(struct bge_softc *sc)
rcb->bge_maxlen_flags =
BGE_RCB_MAXLEN_FLAGS(BGE_MAX_FRAMELEN, 0);
}
- if (sc->bge_asicrev == BGE_ASICREV_BCM5717)
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5720)
rcb->bge_nicaddr = BGE_STD_RX_RINGS_5717;
else
rcb->bge_nicaddr = BGE_STD_RX_RINGS;
@@ -1706,7 +2136,9 @@ bge_blockinit(struct bge_softc *sc)
BUS_DMASYNC_PREREAD);
rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0,
BGE_RCB_FLAG_USE_EXT_RX_BD | BGE_RCB_FLAG_RING_DISABLED);
- if (sc->bge_asicrev == BGE_ASICREV_BCM5717)
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5720)
rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS_5717;
else
rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS;
@@ -1794,7 +2226,9 @@ bge_blockinit(struct bge_softc *sc)
BGE_HOSTADDR(taddr, sc->bge_ldata.bge_tx_ring_paddr);
RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_hi, taddr.bge_addr_hi);
RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo);
- if (sc->bge_asicrev == BGE_ASICREV_BCM5717)
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5720)
RCB_WRITE_4(sc, vrcb, bge_nicaddr, BGE_SEND_RING_5717);
else
RCB_WRITE_4(sc, vrcb, bge_nicaddr,
@@ -1807,12 +2241,15 @@ bge_blockinit(struct bge_softc *sc)
* 'ring diabled' bit in the flags field of all the receive
* return ring control blocks, located in NIC memory.
*/
- if (sc->bge_asicrev == BGE_ASICREV_BCM5717) {
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5720) {
/* Should be 17, use 16 until we get an SRAM map. */
limit = 16;
} else if (!BGE_IS_5705_PLUS(sc))
limit = BGE_RX_RINGS_MAX;
- else if (sc->bge_asicrev == BGE_ASICREV_BCM5755)
+ else if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
+ BGE_IS_57765_PLUS(sc))
limit = 4;
else
limit = 1;
@@ -1850,7 +2287,11 @@ bge_blockinit(struct bge_softc *sc)
BGE_TX_BACKOFF_SEED_MASK);
/* Set inter-packet gap */
- CSR_WRITE_4(sc, BGE_TX_LENGTHS, 0x2620);
+ val = 0x2620;
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5720)
+ val |= CSR_READ_4(sc, BGE_TX_LENGTHS) &
+ (BGE_TXLEN_JMB_FRM_LEN_MSK | BGE_TXLEN_CNT_DN_VAL_MSK);
+ CSR_WRITE_4(sc, BGE_TX_LENGTHS, val);
/*
* Specify which ring to use for packets that don't match
@@ -1940,6 +2381,7 @@ bge_blockinit(struct bge_softc *sc)
if (!(BGE_IS_5705_PLUS(sc)))
CSR_WRITE_4(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE);
+ /* Turn on DMA, clear stats. */
val = BGE_MACMODE_TXDMA_ENB | BGE_MACMODE_RXDMA_ENB |
BGE_MACMODE_RX_STATS_CLEAR | BGE_MACMODE_TX_STATS_CLEAR |
BGE_MACMODE_RX_STATS_ENB | BGE_MACMODE_TX_STATS_ENB |
@@ -1952,8 +2394,12 @@ bge_blockinit(struct bge_softc *sc)
else
val |= BGE_PORTMODE_MII;
- /* Turn on DMA, clear stats */
+ /* Allow APE to send/receive frames. */
+ if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) != 0)
+ val |= BGE_MACMODE_APE_RX_EN | BGE_MACMODE_APE_TX_EN;
+
CSR_WRITE_4(sc, BGE_MAC_MODE, val);
+ DELAY(40);
/* Set misc. local control, enable interrupts on attentions */
CSR_WRITE_4(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN);
@@ -2005,20 +2451,61 @@ bge_blockinit(struct bge_softc *sc)
sc->bge_asicrev == BGE_ASICREV_BCM57780)
val |= BGE_RDMAMODE_TSO6_ENABLE;
}
+
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+ val |= CSR_READ_4(sc, BGE_RDMA_MODE) &
+ BGE_RDMAMODE_H2BNC_VLAN_DET;
+ /*
+ * Allow multiple outstanding read requests from
+ * non-LSO read DMA engine.
+ */
+ val &= ~BGE_RDMAMODE_MULT_DMA_RD_DIS;
+ }
+
if (sc->bge_asicrev == BGE_ASICREV_BCM5761 ||
sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
sc->bge_asicrev == BGE_ASICREV_BCM5785 ||
sc->bge_asicrev == BGE_ASICREV_BCM57780 ||
BGE_IS_5717_PLUS(sc)) {
+ dmactl = CSR_READ_4(sc, BGE_RDMA_RSRVCTRL);
+ /*
+ * Adjust tx margin to prevent TX data corruption and
+ * fix internal FIFO overflow.
+ */
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
+ sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
+ dmactl &= ~(BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK |
+ BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK |
+ BGE_RDMA_RSRVCTRL_TXMRGN_MASK);
+ dmactl |= BGE_RDMA_RSRVCTRL_FIFO_LWM_1_5K |
+ BGE_RDMA_RSRVCTRL_FIFO_HWM_1_5K |
+ BGE_RDMA_RSRVCTRL_TXMRGN_320B;
+ }
/*
* Enable fix for read DMA FIFO overruns.
* The fix is to limit the number of RX BDs
* the hardware would fetch at a fime.
*/
- CSR_WRITE_4(sc, BGE_RDMA_RSRVCTRL,
- CSR_READ_4(sc, BGE_RDMA_RSRVCTRL) |
+ CSR_WRITE_4(sc, BGE_RDMA_RSRVCTRL, dmactl |
BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
}
+
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719) {
+ CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL,
+ CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) |
+ BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K |
+ BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K);
+ } else if (sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+ /*
+ * Allow 4KB burst length reads for non-LSO frames.
+ * Enable 512B burst length reads for buffer descriptors.
+ */
+ CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL,
+ CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL) |
+ BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 |
+ BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K);
+ }
+
CSR_WRITE_4(sc, BGE_RDMA_MODE, val);
DELAY(40);
@@ -2145,20 +2632,21 @@ bge_lookup_vendor(uint16_t vid)
static int
bge_probe(device_t dev)
{
- const struct bge_type *t = bge_devs;
+ char buf[96];
+ char model[64];
+ const struct bge_revision *br;
+ const char *pname;
struct bge_softc *sc = device_get_softc(dev);
- uint16_t vid, did;
+ const struct bge_type *t = bge_devs;
+ const struct bge_vendor *v;
+ uint32_t id;
+ uint16_t did, vid;
sc->bge_dev = dev;
vid = pci_get_vendor(dev);
did = pci_get_device(dev);
while(t->bge_vid != 0) {
if ((vid == t->bge_vid) && (did == t->bge_did)) {
- char model[64], buf[96];
- const struct bge_revision *br;
- const struct bge_vendor *v;
- uint32_t id;
-
id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
BGE_PCIMISCCTL_ASICREV_SHIFT;
if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) {
@@ -2169,9 +2657,22 @@ bge_probe(device_t dev)
switch (pci_get_device(dev)) {
case BCOM_DEVICEID_BCM5717:
case BCOM_DEVICEID_BCM5718:
+ case BCOM_DEVICEID_BCM5719:
+ case BCOM_DEVICEID_BCM5720:
id = pci_read_config(dev,
BGE_PCI_GEN2_PRODID_ASICREV, 4);
break;
+ case BCOM_DEVICEID_BCM57761:
+ case BCOM_DEVICEID_BCM57762:
+ case BCOM_DEVICEID_BCM57765:
+ case BCOM_DEVICEID_BCM57766:
+ case BCOM_DEVICEID_BCM57781:
+ case BCOM_DEVICEID_BCM57785:
+ case BCOM_DEVICEID_BCM57791:
+ case BCOM_DEVICEID_BCM57795:
+ id = pci_read_config(dev,
+ BGE_PCI_GEN15_PRODID_ASICREV, 4);
+ break;
default:
id = pci_read_config(dev,
BGE_PCI_PRODID_ASICREV, 4);
@@ -2179,20 +2680,13 @@ bge_probe(device_t dev)
}
br = bge_lookup_rev(id);
v = bge_lookup_vendor(vid);
- {
-#if __FreeBSD_version > 700024
- const char *pname;
-
- if (bge_has_eaddr(sc) &&
- pci_get_vpd_ident(dev, &pname) == 0)
- snprintf(model, 64, "%s", pname);
- else
-#endif
- snprintf(model, 64, "%s %s",
- v->v_name,
- br != NULL ? br->br_name :
- "NetXtreme Ethernet Controller");
- }
+ if (bge_has_eaddr(sc) &&
+ pci_get_vpd_ident(dev, &pname) == 0)
+ snprintf(model, 64, "%s", pname);
+ else
+ snprintf(model, 64, "%s %s", v->v_name,
+ br != NULL ? br->br_name :
+ "NetXtreme Ethernet Controller");
snprintf(buf, 96, "%s, %sASIC rev. %#08x", model,
br != NULL ? "" : "unknown ", id);
device_set_desc_copy(dev, buf);
@@ -2238,10 +2732,11 @@ bge_dma_free(struct bge_softc *sc)
if (sc->bge_cdata.bge_rx_mtag)
bus_dma_tag_destroy(sc->bge_cdata.bge_rx_mtag);
+ if (sc->bge_cdata.bge_mtag_jumbo)
+ bus_dma_tag_destroy(sc->bge_cdata.bge_mtag_jumbo);
if (sc->bge_cdata.bge_tx_mtag)
bus_dma_tag_destroy(sc->bge_cdata.bge_tx_mtag);
-
/* Destroy standard RX ring. */
if (sc->bge_cdata.bge_rx_std_ring_map)
bus_dmamap_unload(sc->bge_cdata.bge_rx_std_ring_tag,
@@ -2393,7 +2888,7 @@ static int
bge_dma_alloc(struct bge_softc *sc)
{
bus_addr_t lowaddr;
- bus_size_t boundary, sbsz, txsegsz, txmaxsegsz;
+ bus_size_t boundary, sbsz, rxmaxsegsz, txsegsz, txmaxsegsz;
int i, error;
lowaddr = BUS_SPACE_MAXADDR;
@@ -2487,10 +2982,10 @@ bge_dma_alloc(struct bge_softc *sc)
* XXX
* watchdog timeout issue was observed on BCM5704 which
* lives behind PCI-X bridge(e.g AMD 8131 PCI-X bridge).
- * Limiting DMA address space to 32bits seems to address
- * it.
+ * Both limiting DMA address space to 32bits and flushing
+ * mailbox write seem to address the issue.
*/
- if (sc->bge_flags & BGE_FLAG_PCIX)
+ if (sc->bge_pcixcap != 0)
lowaddr = BUS_SPACE_MAXADDR_32BIT;
}
error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev),
@@ -2521,9 +3016,13 @@ bge_dma_alloc(struct bge_softc *sc)
}
/* Create tag for Rx mbufs. */
+ if (sc->bge_flags & BGE_FLAG_JUMBO_STD)
+ rxmaxsegsz = MJUM9BYTES;
+ else
+ rxmaxsegsz = MCLBYTES;
error = bus_dma_tag_create(sc->bge_cdata.bge_buffer_tag, 1, 0,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1,
- MCLBYTES, 0, NULL, NULL, &sc->bge_cdata.bge_rx_mtag);
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, rxmaxsegsz, 1,
+ rxmaxsegsz, 0, NULL, NULL, &sc->bge_cdata.bge_rx_mtag);
if (error) {
device_printf(sc->bge_dev, "could not allocate RX dma tag\n");
@@ -2619,6 +3118,9 @@ bge_can_use_msi(struct bge_softc *sc)
{
int can_use_msi = 0;
+ if (sc->bge_msi == 0)
+ return (0);
+
/* Disable MSI for polling(4). */
#ifdef DEVICE_POLLING
return (0);
@@ -2646,18 +3148,114 @@ bge_can_use_msi(struct bge_softc *sc)
}
static int
+bge_mbox_reorder(struct bge_softc *sc)
+{
+ /* Lists of PCI bridges that are known to reorder mailbox writes. */
+ static const struct mbox_reorder {
+ const uint16_t vendor;
+ const uint16_t device;
+ const char *desc;
+ } mbox_reorder_lists[] = {
+ { 0x1022, 0x7450, "AMD-8131 PCI-X Bridge" },
+ };
+ devclass_t pci, pcib;
+ device_t bus, dev;
+ int i;
+
+ pci = devclass_find("pci");
+ pcib = devclass_find("pcib");
+ dev = sc->bge_dev;
+ bus = device_get_parent(dev);
+ for (;;) {
+ dev = device_get_parent(bus);
+ bus = device_get_parent(dev);
+ if (device_get_devclass(dev) != pcib)
+ break;
+ for (i = 0; i < nitems(mbox_reorder_lists); i++) {
+ if (pci_get_vendor(dev) ==
+ mbox_reorder_lists[i].vendor &&
+ pci_get_device(dev) ==
+ mbox_reorder_lists[i].device) {
+ device_printf(sc->bge_dev,
+ "enabling MBOX workaround for %s\n",
+ mbox_reorder_lists[i].desc);
+ return (1);
+ }
+ }
+ if (device_get_devclass(bus) != pci)
+ break;
+ }
+ return (0);
+}
+
+static void
+bge_devinfo(struct bge_softc *sc)
+{
+ uint32_t cfg, clk;
+
+ device_printf(sc->bge_dev,
+ "CHIP ID 0x%08x; ASIC REV 0x%02x; CHIP REV 0x%02x; ",
+ sc->bge_chipid, sc->bge_asicrev, sc->bge_chiprev);
+ if (sc->bge_flags & BGE_FLAG_PCIE)
+ printf("PCI-E\n");
+ else if (sc->bge_flags & BGE_FLAG_PCIX) {
+ printf("PCI-X ");
+ cfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID_MASK;
+ if (cfg == BGE_MISCCFG_BOARD_ID_5704CIOBE)
+ clk = 133;
+ else {
+ clk = CSR_READ_4(sc, BGE_PCI_CLKCTL) & 0x1F;
+ switch (clk) {
+ case 0:
+ clk = 33;
+ break;
+ case 2:
+ clk = 50;
+ break;
+ case 4:
+ clk = 66;
+ break;
+ case 6:
+ clk = 100;
+ break;
+ case 7:
+ clk = 133;
+ break;
+ }
+ }
+ printf("%u MHz\n", clk);
+ } else {
+ if (sc->bge_pcixcap != 0)
+ printf("PCI on PCI-X ");
+ else
+ printf("PCI ");
+ cfg = pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4);
+ if (cfg & BGE_PCISTATE_PCI_BUSSPEED)
+ clk = 66;
+ else
+ clk = 33;
+ if (cfg & BGE_PCISTATE_32BIT_BUS)
+ printf("%u MHz; 32bit\n", clk);
+ else
+ printf("%u MHz; 64bit\n", clk);
+ }
+}
+
+static int
bge_attach(device_t dev)
{
struct ifnet *ifp;
struct bge_softc *sc;
- uint32_t hwcfg = 0, misccfg;
+ uint32_t hwcfg = 0, misccfg, pcistate;
u_char eaddr[ETHER_ADDR_LEN];
- int capmask, error, f, msicount, phy_addr, reg, rid, trys;
+ int capmask, error, msicount, reg, rid, trys;
sc = device_get_softc(dev);
sc->bge_dev = dev;
+ BGE_LOCK_INIT(sc, device_get_nameunit(dev));
TASK_INIT(&sc->bge_intr_task, 0, bge_intr_task, sc);
+ callout_init_mtx(&sc->bge_stat_ch, &sc->bge_mtx, 0);
/*
* Map control/status registers.
@@ -2669,12 +3267,13 @@ bge_attach(device_t dev)
RF_ACTIVE);
if (sc->bge_res == NULL) {
- device_printf (sc->bge_dev, "couldn't map memory\n");
+ device_printf (sc->bge_dev, "couldn't map BAR0 memory\n");
error = ENXIO;
goto fail;
}
/* Save various chip information. */
+ sc->bge_func_addr = pci_get_function(dev);
sc->bge_chipid =
pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
BGE_PCIMISCCTL_ASICREV_SHIFT;
@@ -2686,9 +3285,22 @@ bge_attach(device_t dev)
switch (pci_get_device(dev)) {
case BCOM_DEVICEID_BCM5717:
case BCOM_DEVICEID_BCM5718:
+ case BCOM_DEVICEID_BCM5719:
+ case BCOM_DEVICEID_BCM5720:
sc->bge_chipid = pci_read_config(dev,
BGE_PCI_GEN2_PRODID_ASICREV, 4);
break;
+ case BCOM_DEVICEID_BCM57761:
+ case BCOM_DEVICEID_BCM57762:
+ case BCOM_DEVICEID_BCM57765:
+ case BCOM_DEVICEID_BCM57766:
+ case BCOM_DEVICEID_BCM57781:
+ case BCOM_DEVICEID_BCM57785:
+ case BCOM_DEVICEID_BCM57791:
+ case BCOM_DEVICEID_BCM57795:
+ sc->bge_chipid = pci_read_config(dev,
+ BGE_PCI_GEN15_PRODID_ASICREV, 4);
+ break;
default:
sc->bge_chipid = pci_read_config(dev,
BGE_PCI_PRODID_ASICREV, 4);
@@ -2698,7 +3310,7 @@ bge_attach(device_t dev)
sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
/* Set default PHY address. */
- phy_addr = 1;
+ sc->bge_phy_addr = 1;
/*
* PHY address mapping for various devices.
*
@@ -2707,47 +3319,58 @@ bge_attach(device_t dev)
* BCM57XX | 1 | X | X | X |
* BCM5704 | 1 | X | 1 | X |
* BCM5717 | 1 | 8 | 2 | 9 |
+ * BCM5719 | 1 | 8 | 2 | 9 |
+ * BCM5720 | 1 | 8 | 2 | 9 |
+ *
+ * | F2 Cu | F2 Sr | F3 Cu | F3 Sr |
+ * ---------+-------+-------+-------+-------+
+ * BCM57XX | X | X | X | X |
+ * BCM5704 | X | X | X | X |
+ * BCM5717 | X | X | X | X |
+ * BCM5719 | 3 | 10 | 4 | 11 |
+ * BCM5720 | X | X | X | X |
*
* Other addresses may respond but they are not
* IEEE compliant PHYs and should be ignored.
*/
- if (sc->bge_asicrev == BGE_ASICREV_BCM5717) {
- f = pci_get_function(dev);
- if (sc->bge_chipid == BGE_CHIPID_BCM5717_A0) {
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5717 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+ if (sc->bge_chipid != BGE_CHIPID_BCM5717_A0) {
if (CSR_READ_4(sc, BGE_SGDIG_STS) &
BGE_SGDIGSTS_IS_SERDES)
- phy_addr = f + 8;
+ sc->bge_phy_addr = sc->bge_func_addr + 8;
else
- phy_addr = f + 1;
- } else if (sc->bge_chipid == BGE_CHIPID_BCM5717_B0) {
+ sc->bge_phy_addr = sc->bge_func_addr + 1;
+ } else {
if (CSR_READ_4(sc, BGE_CPMU_PHY_STRAP) &
BGE_CPMU_PHY_STRAP_IS_SERDES)
- phy_addr = f + 8;
+ sc->bge_phy_addr = sc->bge_func_addr + 8;
else
- phy_addr = f + 1;
+ sc->bge_phy_addr = sc->bge_func_addr + 1;
}
}
- /*
- * Don't enable Ethernet@WireSpeed for the 5700, 5906, or the
- * 5705 A0 and A1 chips.
- */
- if (sc->bge_asicrev != BGE_ASICREV_BCM5700 &&
- sc->bge_asicrev != BGE_ASICREV_BCM5906 &&
- sc->bge_chipid != BGE_CHIPID_BCM5705_A0 &&
- sc->bge_chipid != BGE_CHIPID_BCM5705_A1 &&
- !BGE_IS_5717_PLUS(sc))
- sc->bge_phy_flags |= BGE_PHY_WIRESPEED;
-
if (bge_has_eaddr(sc))
sc->bge_flags |= BGE_FLAG_EADDR;
/* Save chipset family. */
switch (sc->bge_asicrev) {
+ case BGE_ASICREV_BCM57765:
+ case BGE_ASICREV_BCM57766:
+ sc->bge_flags |= BGE_FLAG_57765_PLUS;
+ /* FALLTHROUGH */
case BGE_ASICREV_BCM5717:
+ case BGE_ASICREV_BCM5719:
+ case BGE_ASICREV_BCM5720:
sc->bge_flags |= BGE_FLAG_5717_PLUS | BGE_FLAG_5755_PLUS |
BGE_FLAG_575X_PLUS | BGE_FLAG_5705_PLUS | BGE_FLAG_JUMBO |
- BGE_FLAG_SHORT_DMA_BUG | BGE_FLAG_JUMBO_FRAME;
+ BGE_FLAG_JUMBO_FRAME;
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
+ sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
+ /* Jumbo frame on BCM5719 A0 does not work. */
+ sc->bge_flags &= ~BGE_FLAG_JUMBO;
+ }
break;
case BGE_ASICREV_BCM5755:
case BGE_ASICREV_BCM5761:
@@ -2767,49 +3390,54 @@ bge_attach(device_t dev)
case BGE_ASICREV_BCM5714_A0:
case BGE_ASICREV_BCM5780:
case BGE_ASICREV_BCM5714:
- sc->bge_flags |= BGE_FLAG_5714_FAMILY /* | BGE_FLAG_JUMBO */;
+ sc->bge_flags |= BGE_FLAG_5714_FAMILY | BGE_FLAG_JUMBO_STD;
/* FALLTHROUGH */
case BGE_ASICREV_BCM5750:
case BGE_ASICREV_BCM5752:
case BGE_ASICREV_BCM5906:
sc->bge_flags |= BGE_FLAG_575X_PLUS;
- if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
- sc->bge_flags |= BGE_FLAG_SHORT_DMA_BUG;
/* FALLTHROUGH */
case BGE_ASICREV_BCM5705:
sc->bge_flags |= BGE_FLAG_5705_PLUS;
break;
}
- /* Set various PHY bug flags. */
- if (sc->bge_chipid == BGE_CHIPID_BCM5701_A0 ||
- sc->bge_chipid == BGE_CHIPID_BCM5701_B0)
- sc->bge_phy_flags |= BGE_PHY_CRC_BUG;
- if (sc->bge_chiprev == BGE_CHIPREV_5703_AX ||
- sc->bge_chiprev == BGE_CHIPREV_5704_AX)
- sc->bge_phy_flags |= BGE_PHY_ADC_BUG;
- if (sc->bge_chipid == BGE_CHIPID_BCM5704_A0)
- sc->bge_phy_flags |= BGE_PHY_5704_A0_BUG;
- if (pci_get_subvendor(dev) == DELL_VENDORID)
- sc->bge_phy_flags |= BGE_PHY_NO_3LED;
- if ((BGE_IS_5705_PLUS(sc)) &&
- sc->bge_asicrev != BGE_ASICREV_BCM5906 &&
- sc->bge_asicrev != BGE_ASICREV_BCM5717 &&
- sc->bge_asicrev != BGE_ASICREV_BCM5785 &&
- sc->bge_asicrev != BGE_ASICREV_BCM57780) {
- if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
- sc->bge_asicrev == BGE_ASICREV_BCM5761 ||
- sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
- sc->bge_asicrev == BGE_ASICREV_BCM5787) {
- if (pci_get_device(dev) != BCOM_DEVICEID_BCM5722 &&
- pci_get_device(dev) != BCOM_DEVICEID_BCM5756)
- sc->bge_phy_flags |= BGE_PHY_JITTER_BUG;
- if (pci_get_device(dev) == BCOM_DEVICEID_BCM5755M)
- sc->bge_phy_flags |= BGE_PHY_ADJUST_TRIM;
- } else
- sc->bge_phy_flags |= BGE_PHY_BER_BUG;
+ /* Identify chips with APE processor. */
+ switch (sc->bge_asicrev) {
+ case BGE_ASICREV_BCM5717:
+ case BGE_ASICREV_BCM5719:
+ case BGE_ASICREV_BCM5720:
+ case BGE_ASICREV_BCM5761:
+ sc->bge_flags |= BGE_FLAG_APE;
+ break;
}
+ /* Chips with APE need BAR2 access for APE registers/memory. */
+ if ((sc->bge_flags & BGE_FLAG_APE) != 0) {
+ rid = PCIR_BAR(2);
+ sc->bge_res2 = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->bge_res2 == NULL) {
+ device_printf (sc->bge_dev,
+ "couldn't map BAR2 memory\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ /* Enable APE register/memory access by host driver. */
+ pcistate = pci_read_config(dev, BGE_PCI_PCISTATE, 4);
+ pcistate |= BGE_PCISTATE_ALLOW_APE_CTLSPC_WR |
+ BGE_PCISTATE_ALLOW_APE_SHMEM_WR |
+ BGE_PCISTATE_ALLOW_APE_PSPACE_WR;
+ pci_write_config(dev, BGE_PCI_PCISTATE, pcistate, 4);
+
+ bge_ape_lock_init(sc);
+ bge_ape_read_fw_ver(sc);
+ }
+
+ /* Add SYSCTLs, requires the chipset family to be set. */
+ bge_add_sysctls(sc);
+
/* Identify the chips that use an CPMU. */
if (BGE_IS_5717_PLUS(sc) ||
sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
@@ -2826,17 +3454,28 @@ bge_attach(device_t dev)
sc->bge_mi_mode |= BGE_MIMODE_AUTOPOLL;
/*
- * All controllers that are not 5755 or higher have 4GB
- * boundary DMA bug.
+ * All Broadcom controllers have 4GB boundary DMA bug.
* Whenever an address crosses a multiple of the 4GB boundary
* (including 4GB, 8Gb, 12Gb, etc.) and makes the transition
* from 0xX_FFFF_FFFF to 0x(X+1)_0000_0000 an internal DMA
* state machine will lockup and cause the device to hang.
*/
- if (BGE_IS_5755_PLUS(sc) == 0)
- sc->bge_flags |= BGE_FLAG_4G_BNDRY_BUG;
+ sc->bge_flags |= BGE_FLAG_4G_BNDRY_BUG;
+
+ /* BCM5755 or higher and BCM5906 have short DMA bug. */
+ if (BGE_IS_5755_PLUS(sc) || sc->bge_asicrev == BGE_ASICREV_BCM5906)
+ sc->bge_flags |= BGE_FLAG_SHORT_DMA_BUG;
- misccfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID;
+ /*
+ * BCM5719 cannot handle DMA requests for DMA segments that
+ * have larger than 4KB in size. However the maximum DMA
+ * segment size created in DMA tag is 4KB for TSO, so we
+ * wouldn't encounter the issue here.
+ */
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+ sc->bge_flags |= BGE_FLAG_4K_RDMA_BUG;
+
+ misccfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID_MASK;
if (sc->bge_asicrev == BGE_ASICREV_BCM5705) {
if (misccfg == BGE_MISCCFG_BOARD_ID_5788 ||
misccfg == BGE_MISCCFG_BOARD_ID_5788M)
@@ -2859,6 +3498,7 @@ bge_attach(device_t dev)
sc->bge_asicrev == BGE_ASICREV_BCM5906) {
/* These chips are 10/100 only. */
capmask &= ~BMSR_EXTSTAT;
+ sc->bge_phy_flags |= BGE_PHY_NO_WIRESPEED;
}
/*
@@ -2876,6 +3516,11 @@ bge_attach(device_t dev)
if (BGE_IS_5717_PLUS(sc)) {
/* BCM5717 requires different TSO configuration. */
sc->bge_flags |= BGE_FLAG_TSO3;
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
+ sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
+ /* TSO on BCM5719 A0 does not work. */
+ sc->bge_flags &= ~BGE_FLAG_TSO3;
+ }
} else if (BGE_IS_5755_PLUS(sc)) {
/*
* BCM5754 and BCM5787 shares the same ASIC id so
@@ -2888,9 +3533,9 @@ bge_attach(device_t dev)
sc->bge_flags |= BGE_FLAG_TSO;
}
- /*
+ /*
* Check if this is a PCI-X or PCI Express device.
- */
+ */
if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
/*
* Found a PCI Express capabilities register, this
@@ -2898,8 +3543,16 @@ bge_attach(device_t dev)
*/
sc->bge_flags |= BGE_FLAG_PCIE;
sc->bge_expcap = reg;
- if (pci_get_max_read_req(dev) != 4096)
- pci_set_max_read_req(dev, 4096);
+ /* Extract supported maximum payload size. */
+ sc->bge_mps = pci_read_config(dev, sc->bge_expcap +
+ PCIER_DEVICE_CAP, 2);
+ sc->bge_mps = 128 << (sc->bge_mps & PCIEM_CAP_MAX_PAYLOAD);
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5720)
+ sc->bge_expmrq = 2048;
+ else
+ sc->bge_expmrq = 4096;
+ pci_set_max_read_req(dev, sc->bge_expmrq);
} else {
/*
* Check if the device is in PCI-X Mode.
@@ -2920,6 +3573,16 @@ bge_attach(device_t dev)
if (BGE_IS_5714_FAMILY(sc) && (sc->bge_flags & BGE_FLAG_PCIX))
sc->bge_flags |= BGE_FLAG_40BIT_BUG;
/*
+ * Some PCI-X bridges are known to trigger write reordering to
+ * the mailbox registers. Typical phenomena is watchdog timeouts
+ * caused by out-of-order TX completions. Enable workaround for
+ * PCI-X devices that live behind these bridges.
+ * Note, PCI-X controllers can run in PCI mode so we can't use
+ * BGE_FLAG_PCIX flag to detect PCI-X controllers.
+ */
+ if (sc->bge_pcixcap != 0 && bge_mbox_reorder(sc) != 0)
+ sc->bge_flags |= BGE_FLAG_MBOX_REORDER;
+ /*
* Allocate the interrupt, using MSI if possible. These devices
* support 8 MSI messages, but only the first one is used in
* normal operation.
@@ -2958,44 +3621,33 @@ bge_attach(device_t dev)
goto fail;
}
- device_printf(dev,
- "CHIP ID 0x%08x; ASIC REV 0x%02x; CHIP REV 0x%02x; %s\n",
- sc->bge_chipid, sc->bge_asicrev, sc->bge_chiprev,
- (sc->bge_flags & BGE_FLAG_PCIX) ? "PCI-X" :
- ((sc->bge_flags & BGE_FLAG_PCIE) ? "PCI-E" : "PCI"));
-
- BGE_LOCK_INIT(sc, device_get_nameunit(dev));
-
- /* Try to reset the chip. */
- if (bge_reset(sc)) {
- device_printf(sc->bge_dev, "chip reset failed\n");
- error = ENXIO;
- goto fail;
- }
+ bge_devinfo(sc);
sc->bge_asf_mode = 0;
- if (bge_allow_asf && (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG)
- == BGE_MAGIC_NUMBER)) {
- if (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG)
- & BGE_HWCFG_ASF) {
- sc->bge_asf_mode |= ASF_ENABLE;
- sc->bge_asf_mode |= ASF_STACKUP;
- if (BGE_IS_575X_PLUS(sc))
- sc->bge_asf_mode |= ASF_NEW_HANDSHAKE;
+ /* No ASF if APE present. */
+ if ((sc->bge_flags & BGE_FLAG_APE) == 0) {
+ if (bge_allow_asf && (bge_readmem_ind(sc, BGE_SRAM_DATA_SIG) ==
+ BGE_SRAM_DATA_SIG_MAGIC)) {
+ if (bge_readmem_ind(sc, BGE_SRAM_DATA_CFG) &
+ BGE_HWCFG_ASF) {
+ sc->bge_asf_mode |= ASF_ENABLE;
+ sc->bge_asf_mode |= ASF_STACKUP;
+ if (BGE_IS_575X_PLUS(sc))
+ sc->bge_asf_mode |= ASF_NEW_HANDSHAKE;
+ }
}
}
- /* Try to reset the chip again the nice way. */
bge_stop_fw(sc);
- bge_sig_pre_reset(sc, BGE_RESET_STOP);
+ bge_sig_pre_reset(sc, BGE_RESET_SHUTDOWN);
if (bge_reset(sc)) {
device_printf(sc->bge_dev, "chip reset failed\n");
error = ENXIO;
goto fail;
}
- bge_sig_legacy(sc, BGE_RESET_STOP);
- bge_sig_post_reset(sc, BGE_RESET_STOP);
+ bge_sig_legacy(sc, BGE_RESET_SHUTDOWN);
+ bge_sig_post_reset(sc, BGE_RESET_SHUTDOWN);
if (bge_chipinit(sc)) {
device_printf(sc->bge_dev, "chip initialization failed\n");
@@ -3026,8 +3678,6 @@ bge_attach(device_t dev)
goto fail;
}
- bge_add_sysctls(sc);
-
/* Set default tuneable values. */
sc->bge_stat_ticks = BGE_TICKS_PER_SEC;
sc->bge_rx_coal_ticks = 150;
@@ -3090,8 +3740,8 @@ bge_attach(device_t dev)
* by its PCI subsystem ID, as we do below for the SysKonnect
* SK-9D41.
*/
- if (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG) == BGE_MAGIC_NUMBER)
- hwcfg = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG);
+ if (bge_readmem_ind(sc, BGE_SRAM_DATA_SIG) == BGE_SRAM_DATA_SIG_MAGIC)
+ hwcfg = bge_readmem_ind(sc, BGE_SRAM_DATA_CFG);
else if ((sc->bge_flags & BGE_FLAG_EADDR) &&
(sc->bge_asicrev != BGE_ASICREV_BCM5906)) {
if (bge_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET,
@@ -3106,12 +3756,52 @@ bge_attach(device_t dev)
/* The SysKonnect SK-9D41 is a 1000baseSX card. */
if ((pci_read_config(dev, BGE_PCI_SUBSYS, 4) >> 16) ==
SK_SUBSYSID_9D41 || (hwcfg & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER) {
- if (BGE_IS_5714_FAMILY(sc))
+ if (BGE_IS_5705_PLUS(sc)) {
sc->bge_flags |= BGE_FLAG_MII_SERDES;
- else
+ sc->bge_phy_flags |= BGE_PHY_NO_WIRESPEED;
+ } else
sc->bge_flags |= BGE_FLAG_TBI;
}
+ /* Set various PHY bug flags. */
+ if (sc->bge_chipid == BGE_CHIPID_BCM5701_A0 ||
+ sc->bge_chipid == BGE_CHIPID_BCM5701_B0)
+ sc->bge_phy_flags |= BGE_PHY_CRC_BUG;
+ if (sc->bge_chiprev == BGE_CHIPREV_5703_AX ||
+ sc->bge_chiprev == BGE_CHIPREV_5704_AX)
+ sc->bge_phy_flags |= BGE_PHY_ADC_BUG;
+ if (sc->bge_chipid == BGE_CHIPID_BCM5704_A0)
+ sc->bge_phy_flags |= BGE_PHY_5704_A0_BUG;
+ if (pci_get_subvendor(dev) == DELL_VENDORID)
+ sc->bge_phy_flags |= BGE_PHY_NO_3LED;
+ if ((BGE_IS_5705_PLUS(sc)) &&
+ sc->bge_asicrev != BGE_ASICREV_BCM5906 &&
+ sc->bge_asicrev != BGE_ASICREV_BCM5785 &&
+ sc->bge_asicrev != BGE_ASICREV_BCM57780 &&
+ !BGE_IS_5717_PLUS(sc)) {
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5761 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5787) {
+ if (pci_get_device(dev) != BCOM_DEVICEID_BCM5722 &&
+ pci_get_device(dev) != BCOM_DEVICEID_BCM5756)
+ sc->bge_phy_flags |= BGE_PHY_JITTER_BUG;
+ if (pci_get_device(dev) == BCOM_DEVICEID_BCM5755M)
+ sc->bge_phy_flags |= BGE_PHY_ADJUST_TRIM;
+ } else
+ sc->bge_phy_flags |= BGE_PHY_BER_BUG;
+ }
+
+ /*
+ * Don't enable Ethernet@WireSpeed for the 5700 or the
+ * 5705 A0 and A1 chips.
+ */
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5700 ||
+ (sc->bge_asicrev == BGE_ASICREV_BCM5705 &&
+ (sc->bge_chipid != BGE_CHIPID_BCM5705_A0 &&
+ sc->bge_chipid != BGE_CHIPID_BCM5705_A1)))
+ sc->bge_phy_flags |= BGE_PHY_NO_WIRESPEED;
+
if (sc->bge_flags & BGE_FLAG_TBI) {
ifmedia_init(&sc->bge_ifmedia, IFM_IMASK, bge_ifmedia_upd,
bge_ifmedia_sts);
@@ -3135,13 +3825,13 @@ again:
bge_asf_driver_up(sc);
error = mii_attach(dev, &sc->bge_miibus, ifp, bge_ifmedia_upd,
- bge_ifmedia_sts, capmask, phy_addr, MII_OFFSET_ANY,
+ bge_ifmedia_sts, capmask, sc->bge_phy_addr, MII_OFFSET_ANY,
MIIF_DOPAUSE | MIIF_FORCEPAUSE);
if (error != 0) {
if (trys++ < 4) {
device_printf(sc->bge_dev, "Try again\n");
- bge_miibus_writereg(sc->bge_dev, 1, MII_BMCR,
- BMCR_RESET);
+ bge_miibus_writereg(sc->bge_dev,
+ sc->bge_phy_addr, MII_BMCR, BMCR_RESET);
goto again;
}
device_printf(sc->bge_dev, "attaching PHYs failed\n");
@@ -3171,7 +3861,6 @@ again:
* Call MI attach routine.
*/
ether_ifattach(ifp, eaddr);
- callout_init_mtx(&sc->bge_stat_ch, &sc->bge_mtx, 0);
/* Tell upper layer we support long frames. */
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
@@ -3179,7 +3868,6 @@ again:
/*
* Hookup IRQ last.
*/
-#if __FreeBSD_version > 700030
if (BGE_IS_5755_PLUS(sc) && sc->bge_flags & BGE_FLAG_MSI) {
/* Take advantage of single-shot MSI. */
CSR_WRITE_4(sc, BGE_MSI_MODE, CSR_READ_4(sc, BGE_MSI_MODE) &
@@ -3189,7 +3877,7 @@ again:
if (sc->bge_tq == NULL) {
device_printf(dev, "could not create taskqueue.\n");
ether_ifdetach(ifp);
- error = ENXIO;
+ error = ENOMEM;
goto fail;
}
taskqueue_start_threads(&sc->bge_tq, 1, PI_NET, "%s taskq",
@@ -3197,27 +3885,19 @@ again:
error = bus_setup_intr(dev, sc->bge_irq,
INTR_TYPE_NET | INTR_MPSAFE, bge_msi_intr, NULL, sc,
&sc->bge_intrhand);
- if (error)
- ether_ifdetach(ifp);
} else
error = bus_setup_intr(dev, sc->bge_irq,
INTR_TYPE_NET | INTR_MPSAFE, NULL, bge_intr, sc,
&sc->bge_intrhand);
-#else
- error = bus_setup_intr(dev, sc->bge_irq, INTR_TYPE_NET | INTR_MPSAFE,
- bge_intr, sc, &sc->bge_intrhand);
-#endif
if (error) {
- bge_detach(dev);
+ ether_ifdetach(ifp);
device_printf(sc->bge_dev, "couldn't set up irq\n");
}
- return (0);
-
fail:
- bge_release_resources(sc);
-
+ if (error)
+ bge_detach(dev);
return (error);
}
@@ -3235,16 +3915,16 @@ bge_detach(device_t dev)
ether_poll_deregister(ifp);
#endif
- BGE_LOCK(sc);
- bge_stop(sc);
- bge_reset(sc);
- BGE_UNLOCK(sc);
-
- callout_drain(&sc->bge_stat_ch);
+ if (device_is_attached(dev)) {
+ ether_ifdetach(ifp);
+ BGE_LOCK(sc);
+ bge_stop(sc);
+ BGE_UNLOCK(sc);
+ callout_drain(&sc->bge_stat_ch);
+ }
if (sc->bge_tq)
taskqueue_drain(sc->bge_tq, &sc->bge_intr_task);
- ether_ifdetach(ifp);
if (sc->bge_flags & BGE_FLAG_TBI) {
ifmedia_removeall(&sc->bge_ifmedia);
@@ -3282,6 +3962,10 @@ bge_release_resources(struct bge_softc *sc)
bus_release_resource(dev, SYS_RES_MEMORY,
PCIR_BAR(0), sc->bge_res);
+ if (sc->bge_res2 != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ PCIR_BAR(2), sc->bge_res2);
+
if (sc->bge_ifp != NULL)
if_free(sc->bge_ifp);
@@ -3295,13 +3979,18 @@ static int
bge_reset(struct bge_softc *sc)
{
device_t dev;
- uint32_t cachesize, command, pcistate, reset, val;
+ uint32_t cachesize, command, mac_mode, mac_mode_mask, reset, val;
void (*write_op)(struct bge_softc *, int, int);
uint16_t devctl;
int i;
dev = sc->bge_dev;
+ mac_mode_mask = BGE_MACMODE_HALF_DUPLEX | BGE_MACMODE_PORTMODE;
+ if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) != 0)
+ mac_mode_mask |= BGE_MACMODE_APE_RX_EN | BGE_MACMODE_APE_TX_EN;
+ mac_mode = CSR_READ_4(sc, BGE_MAC_MODE) & mac_mode_mask;
+
if (BGE_IS_575X_PLUS(sc) && !BGE_IS_5714_FAMILY(sc) &&
(sc->bge_asicrev != BGE_ASICREV_BCM5906)) {
if (sc->bge_flags & BGE_FLAG_PCIE)
@@ -3311,10 +4000,26 @@ bge_reset(struct bge_softc *sc)
} else
write_op = bge_writereg_ind;
+ if (sc->bge_asicrev != BGE_ASICREV_BCM5700 &&
+ sc->bge_asicrev != BGE_ASICREV_BCM5701) {
+ CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1);
+ for (i = 0; i < 8000; i++) {
+ if (CSR_READ_4(sc, BGE_NVRAM_SWARB) &
+ BGE_NVRAMSWARB_GNT1)
+ break;
+ DELAY(20);
+ }
+ if (i == 8000) {
+ if (bootverbose)
+ device_printf(dev, "NVRAM lock timedout!\n");
+ }
+ }
+ /* Take APE lock when performing reset. */
+ bge_ape_lock(sc, BGE_APE_LOCK_GRC);
+
/* Save some important PCI state. */
cachesize = pci_read_config(dev, BGE_PCI_CACHESZ, 4);
command = pci_read_config(dev, BGE_PCI_CMD, 4);
- pcistate = pci_read_config(dev, BGE_PCI_PCISTATE, 4);
pci_write_config(dev, BGE_PCI_MISC_CTL,
BGE_PCIMISCCTL_INDIRECT_ACCESS | BGE_PCIMISCCTL_MASK_PCI_INTR |
@@ -3331,16 +4036,19 @@ bge_reset(struct bge_softc *sc)
/*
* Write the magic number to SRAM at offset 0xB50.
* When firmware finishes its initialization it will
- * write ~BGE_MAGIC_NUMBER to the same location.
+ * write ~BGE_SRAM_FW_MB_MAGIC to the same location.
*/
- bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER);
+ bge_writemem_ind(sc, BGE_SRAM_FW_MB, BGE_SRAM_FW_MB_MAGIC);
reset = BGE_MISCCFG_RESET_CORE_CLOCKS | BGE_32BITTIME_66MHZ;
/* XXX: Broadcom Linux driver. */
if (sc->bge_flags & BGE_FLAG_PCIE) {
- if (CSR_READ_4(sc, 0x7E2C) == 0x60) /* PCIE 1.0 */
- CSR_WRITE_4(sc, 0x7E2C, 0x20);
+ if (sc->bge_asicrev != BGE_ASICREV_BCM5785 &&
+ (sc->bge_flags & BGE_FLAG_5717_PLUS) == 0) {
+ if (CSR_READ_4(sc, 0x7E2C) == 0x60) /* PCIE 1.0 */
+ CSR_WRITE_4(sc, 0x7E2C, 0x20);
+ }
if (sc->bge_chipid != BGE_CHIPID_BCM5750_A0) {
/* Prevent PCIE link training during global reset */
CSR_WRITE_4(sc, BGE_MISC_CFG, 1 << 29);
@@ -3348,16 +4056,6 @@ bge_reset(struct bge_softc *sc)
}
}
- /*
- * Set GPHY Power Down Override to leave GPHY
- * powered up in D0 uninitialized.
- */
- if (BGE_IS_5705_PLUS(sc))
- reset |= BGE_MISCCFG_GPHY_PD_OVERRIDE;
-
- /* Issue global reset */
- write_op(sc, BGE_MISC_CFG, reset);
-
if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
val = CSR_READ_4(sc, BGE_VCPU_STATUS);
CSR_WRITE_4(sc, BGE_VCPU_STATUS,
@@ -3367,7 +4065,21 @@ bge_reset(struct bge_softc *sc)
val & ~BGE_VCPU_EXT_CTRL_HALT_CPU);
}
- DELAY(1000);
+ /*
+ * Set GPHY Power Down Override to leave GPHY
+ * powered up in D0 uninitialized.
+ */
+ if (BGE_IS_5705_PLUS(sc) &&
+ (sc->bge_flags & BGE_FLAG_CPMU_PRESENT) == 0)
+ reset |= BGE_MISCCFG_GPHY_PD_OVERRIDE;
+
+ /* Issue global reset */
+ write_op(sc, BGE_MISC_CFG, reset);
+
+ if (sc->bge_flags & BGE_FLAG_PCIE)
+ DELAY(100 * 1000);
+ else
+ DELAY(1000);
/* XXX: Broadcom Linux driver. */
if (sc->bge_flags & BGE_FLAG_PCIE) {
@@ -3377,28 +4089,35 @@ bge_reset(struct bge_softc *sc)
pci_write_config(dev, 0xC4, val | (1 << 15), 4);
}
devctl = pci_read_config(dev,
- sc->bge_expcap + PCIR_EXPRESS_DEVICE_CTL, 2);
+ sc->bge_expcap + PCIER_DEVICE_CTL, 2);
/* Clear enable no snoop and disable relaxed ordering. */
- devctl &= ~(PCIM_EXP_CTL_RELAXED_ORD_ENABLE |
- PCIM_EXP_CTL_NOSNOOP_ENABLE);
- /* Set PCIE max payload size to 128. */
- devctl &= ~PCIM_EXP_CTL_MAX_PAYLOAD;
- pci_write_config(dev, sc->bge_expcap + PCIR_EXPRESS_DEVICE_CTL,
+ devctl &= ~(PCIEM_CTL_RELAXED_ORD_ENABLE |
+ PCIEM_CTL_NOSNOOP_ENABLE);
+ pci_write_config(dev, sc->bge_expcap + PCIER_DEVICE_CTL,
devctl, 2);
+ pci_set_max_read_req(dev, sc->bge_expmrq);
/* Clear error status. */
- pci_write_config(dev, sc->bge_expcap + PCIR_EXPRESS_DEVICE_STA,
- PCIM_EXP_STA_CORRECTABLE_ERROR |
- PCIM_EXP_STA_NON_FATAL_ERROR | PCIM_EXP_STA_FATAL_ERROR |
- PCIM_EXP_STA_UNSUPPORTED_REQ, 2);
+ pci_write_config(dev, sc->bge_expcap + PCIER_DEVICE_STA,
+ PCIEM_STA_CORRECTABLE_ERROR |
+ PCIEM_STA_NON_FATAL_ERROR | PCIEM_STA_FATAL_ERROR |
+ PCIEM_STA_UNSUPPORTED_REQ, 2);
}
/* Reset some of the PCI state that got zapped by reset. */
pci_write_config(dev, BGE_PCI_MISC_CTL,
BGE_PCIMISCCTL_INDIRECT_ACCESS | BGE_PCIMISCCTL_MASK_PCI_INTR |
BGE_HIF_SWAP_OPTIONS | BGE_PCIMISCCTL_PCISTATE_RW, 4);
+ val = BGE_PCISTATE_ROM_ENABLE | BGE_PCISTATE_ROM_RETRY_ENABLE;
+ if (sc->bge_chipid == BGE_CHIPID_BCM5704_A0 &&
+ (sc->bge_flags & BGE_FLAG_PCIX) != 0)
+ val |= BGE_PCISTATE_RETRY_SAME_DMA;
+ if ((sc->bge_mfw_flags & BGE_MFW_ON_APE) != 0)
+ val |= BGE_PCISTATE_ALLOW_APE_CTLSPC_WR |
+ BGE_PCISTATE_ALLOW_APE_SHMEM_WR |
+ BGE_PCISTATE_ALLOW_APE_PSPACE_WR;
+ pci_write_config(dev, BGE_PCI_PCISTATE, val, 4);
pci_write_config(dev, BGE_PCI_CACHESZ, cachesize, 4);
pci_write_config(dev, BGE_PCI_CMD, command, 4);
- write_op(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
/*
* Disable PCI-X relaxed ordering to ensure status block update
* comes first then packet buffer DMA. Otherwise driver may
@@ -3419,7 +4138,7 @@ bge_reset(struct bge_softc *sc)
pci_write_config(dev, sc->bge_pcixcap + PCIXR_COMMAND,
devctl, 2);
}
- /* Re-enable MSI, if neccesary, and enable the memory arbiter. */
+ /* Re-enable MSI, if necessary, and enable the memory arbiter. */
if (BGE_IS_5714_FAMILY(sc)) {
/* This chip disables MSI on reset. */
if (sc->bge_flags & BGE_FLAG_MSI) {
@@ -3437,6 +4156,16 @@ bge_reset(struct bge_softc *sc)
} else
CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE);
+ /* Fix up byte swapping. */
+ CSR_WRITE_4(sc, BGE_MODE_CTL, bge_dma_swap_options(sc));
+
+ val = CSR_READ_4(sc, BGE_MAC_MODE);
+ val = (val & ~mac_mode_mask) | mac_mode;
+ CSR_WRITE_4(sc, BGE_MAC_MODE, val);
+ DELAY(40);
+
+ bge_ape_unlock(sc, BGE_APE_LOCK_GRC);
+
if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
for (i = 0; i < BGE_TIMEOUT; i++) {
val = CSR_READ_4(sc, BGE_VCPU_STATUS);
@@ -3457,8 +4186,8 @@ bge_reset(struct bge_softc *sc)
*/
for (i = 0; i < BGE_TIMEOUT; i++) {
DELAY(10);
- val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM);
- if (val == ~BGE_MAGIC_NUMBER)
+ val = bge_readmem_ind(sc, BGE_SRAM_FW_MB);
+ if (val == ~BGE_SRAM_FW_MB_MAGIC)
break;
}
@@ -3466,33 +4195,12 @@ bge_reset(struct bge_softc *sc)
device_printf(dev,
"firmware handshake timed out, found 0x%08x\n",
val);
+ /* BCM57765 A0 needs additional time before accessing. */
+ if (sc->bge_chipid == BGE_CHIPID_BCM57765_A0)
+ DELAY(10 * 1000); /* XXX */
}
/*
- * XXX Wait for the value of the PCISTATE register to
- * return to its original pre-reset state. This is a
- * fairly good indicator of reset completion. If we don't
- * wait for the reset to fully complete, trying to read
- * from the device's non-PCI registers may yield garbage
- * results.
- */
- for (i = 0; i < BGE_TIMEOUT; i++) {
- if (pci_read_config(dev, BGE_PCI_PCISTATE, 4) == pcistate)
- break;
- DELAY(10);
- }
-
- /* Fix up byte swapping. */
- CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_DMA_SWAP_OPTIONS |
- BGE_MODECTL_BYTESWAP_DATA);
-
- /* Tell the ASF firmware we are up */
- if (sc->bge_asf_mode & ASF_STACKUP)
- BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
-
- CSR_WRITE_4(sc, BGE_MAC_MODE, 0);
-
- /*
* The 5704 in TBI mode apparently needs some special
* adjustment to insure the SERDES drive level is set
* to 1.2V.
@@ -3506,14 +4214,17 @@ bge_reset(struct bge_softc *sc)
/* XXX: Broadcom Linux driver. */
if (sc->bge_flags & BGE_FLAG_PCIE &&
- sc->bge_asicrev != BGE_ASICREV_BCM5717 &&
+ !BGE_IS_5717_PLUS(sc) &&
sc->bge_chipid != BGE_CHIPID_BCM5750_A0 &&
sc->bge_asicrev != BGE_ASICREV_BCM5785) {
/* Enable Data FIFO protection. */
val = CSR_READ_4(sc, 0x7C00);
CSR_WRITE_4(sc, 0x7C00, val | (1 << 25));
}
- DELAY(10000);
+
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5720)
+ BGE_CLRBIT(sc, BGE_CPMU_CLCK_ORIDE,
+ CPMU_CLCK_ORIDE_MAC_ORIDE_EN);
return (0);
}
@@ -3573,7 +4284,8 @@ bge_rxeof(struct bge_softc *sc, uint16_t rx_prod, int holdlck)
sc->bge_cdata.bge_rx_return_ring_map, BUS_DMASYNC_POSTREAD);
bus_dmamap_sync(sc->bge_cdata.bge_rx_std_ring_tag,
sc->bge_cdata.bge_rx_std_ring_map, BUS_DMASYNC_POSTWRITE);
- if (ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN >
+ if (BGE_IS_JUMBO_CAPABLE(sc) &&
+ ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN >
(MCLBYTES - ETHER_ALIGN))
bus_dmamap_sync(sc->bge_cdata.bge_rx_jumbo_ring_tag,
sc->bge_cdata.bge_rx_jumbo_ring_map, BUS_DMASYNC_POSTWRITE);
@@ -3655,14 +4367,8 @@ bge_rxeof(struct bge_softc *sc, uint16_t rx_prod, int holdlck)
* attach that information to the packet.
*/
if (have_tag) {
-#if __FreeBSD_version > 700022
m->m_pkthdr.ether_vtag = vlan_tag;
m->m_flags |= M_VLANTAG;
-#else
- VLAN_INPUT_TAG_NEW(ifp, m, vlan_tag);
- if (m == NULL)
- continue;
-#endif
}
if (holdlck != 0) {
@@ -3804,10 +4510,12 @@ bge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
sc->bge_cdata.bge_status_map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ /* Fetch updates from the status block. */
rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx;
tx_cons = sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx;
statusword = sc->bge_ldata.bge_status_block->bge_status;
+ /* Clear the status so the next pass only sees the changes. */
sc->bge_ldata.bge_status_block->bge_status = 0;
bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
@@ -3875,11 +4583,12 @@ bge_intr_task(void *arg, int pending)
sc->bge_cdata.bge_status_map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
- /* Save producer/consumer indexess. */
+ /* Save producer/consumer indices. */
rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx;
tx_cons = sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx;
status = sc->bge_ldata.bge_status_block->bge_status;
status_tag = sc->bge_ldata.bge_status_block->bge_status_tag << 24;
+ /* Dirty the status flag. */
sc->bge_ldata.bge_status_block->bge_status = 0;
bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
sc->bge_cdata.bge_status_map,
@@ -3903,7 +4612,7 @@ bge_intr_task(void *arg, int pending)
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
/* Check TX ring producer/consumer. */
bge_txeof(sc, tx_cons);
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
bge_start_locked(ifp);
}
BGE_UNLOCK(sc);
@@ -3999,12 +4708,14 @@ bge_asf_driver_up(struct bge_softc *sc)
sc->bge_asf_count --;
else {
sc->bge_asf_count = 2;
- bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_FW,
- BGE_FW_DRV_ALIVE);
- bge_writemem_ind(sc, BGE_SOFTWARE_GENNCOMM_FW_LEN, 4);
- bge_writemem_ind(sc, BGE_SOFTWARE_GENNCOMM_FW_DATA, 3);
- CSR_WRITE_4(sc, BGE_CPU_EVENT,
- CSR_READ_4(sc, BGE_CPU_EVENT) | (1 << 14));
+ bge_writemem_ind(sc, BGE_SRAM_FW_CMD_MB,
+ BGE_FW_CMD_DRV_ALIVE);
+ bge_writemem_ind(sc, BGE_SRAM_FW_CMD_LEN_MB, 4);
+ bge_writemem_ind(sc, BGE_SRAM_FW_CMD_DATA_MB,
+ BGE_FW_HB_TIMEOUT_SEC);
+ CSR_WRITE_4(sc, BGE_RX_CPU_EVENT,
+ CSR_READ_4(sc, BGE_RX_CPU_EVENT) |
+ BGE_RX_CPU_DRV_EVENT);
}
}
}
@@ -4020,13 +4731,15 @@ bge_tick(void *xsc)
/* Synchronize with possible callout reset/stop. */
if (callout_pending(&sc->bge_stat_ch) ||
!callout_active(&sc->bge_stat_ch))
- return;
+ return;
if (BGE_IS_5705_PLUS(sc))
bge_stats_update_regs(sc);
else
bge_stats_update(sc);
+ /* XXX Add APE heartbeat check here? */
+
if ((sc->bge_flags & BGE_FLAG_TBI) == 0) {
mii = device_get_softc(sc->bge_miibus);
/*
@@ -4135,8 +4848,30 @@ bge_stats_update_regs(struct bge_softc *sc)
CSR_READ_4(sc, BGE_RXLP_LOCSTAT_DMA_HPWRQ_FULL);
stats->NoMoreRxBDs +=
CSR_READ_4(sc, BGE_RXLP_LOCSTAT_OUT_OF_BDS);
- stats->InputDiscards +=
- CSR_READ_4(sc, BGE_RXLP_LOCSTAT_IFIN_DROPS);
+ /*
+ * XXX
+ * Unlike other controllers, BGE_RXLP_LOCSTAT_IFIN_DROPS
+ * counter of BCM5717, BCM5718, BCM5719 A0 and BCM5720 A0
+ * includes number of unwanted multicast frames. This comes
+ * from silicon bug and known workaround to get rough(not
+ * exact) counter is to enable interrupt on MBUF low water
+ * attention. This can be accomplished by setting
+ * BGE_HCCMODE_ATTN bit of BGE_HCC_MODE,
+ * BGE_BMANMODE_LOMBUF_ATTN bit of BGE_BMAN_MODE and
+ * BGE_MODECTL_FLOWCTL_ATTN_INTR bit of BGE_MODE_CTL.
+ * However that change would generate more interrupts and
+ * there are still possibilities of losing multiple frames
+ * during BGE_MODECTL_FLOWCTL_ATTN_INTR interrupt handling.
+ * Given that the workaround still would not get correct
+ * counter I don't think it's worth to implement it. So
+ * ignore reading the counter on controllers that have the
+ * silicon bug.
+ */
+ if (sc->bge_asicrev != BGE_ASICREV_BCM5717 &&
+ sc->bge_chipid != BGE_CHIPID_BCM5719_A0 &&
+ sc->bge_chipid != BGE_CHIPID_BCM5720_A0)
+ stats->InputDiscards +=
+ CSR_READ_4(sc, BGE_RXLP_LOCSTAT_IFIN_DROPS);
stats->InputErrors +=
CSR_READ_4(sc, BGE_RXLP_LOCSTAT_IFIN_ERRORS);
stats->RecvThresholdHit +=
@@ -4207,6 +4942,12 @@ bge_stats_update(struct bge_softc *sc)
ifp->if_collisions += (uint32_t)(cnt - sc->bge_tx_collisions);
sc->bge_tx_collisions = cnt;
+ cnt = READ_STAT(sc, stats, nicNoMoreRxBDs.bge_addr_lo);
+ ifp->if_ierrors += (uint32_t)(cnt - sc->bge_rx_nobds);
+ sc->bge_rx_nobds = cnt;
+ cnt = READ_STAT(sc, stats, ifInErrors.bge_addr_lo);
+ ifp->if_ierrors += (uint32_t)(cnt - sc->bge_rx_inerrs);
+ sc->bge_rx_inerrs = cnt;
cnt = READ_STAT(sc, stats, ifInDiscards.bge_addr_lo);
ifp->if_ierrors += (uint32_t)(cnt - sc->bge_rx_discards);
sc->bge_rx_discards = cnt;
@@ -4411,10 +5152,6 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head, uint32_t *txidx)
return (error);
}
}
- if (m->m_flags & M_LASTFRAG)
- csum_flags |= BGE_TXBDFLAG_IP_FRAG_END;
- else if (m->m_flags & M_FRAG)
- csum_flags |= BGE_TXBDFLAG_IP_FRAG;
}
if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0) {
@@ -4468,21 +5205,10 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head, uint32_t *txidx)
bus_dmamap_sync(sc->bge_cdata.bge_tx_mtag, map, BUS_DMASYNC_PREWRITE);
-#if __FreeBSD_version > 700022
if (m->m_flags & M_VLANTAG) {
csum_flags |= BGE_TXBDFLAG_VLAN_TAG;
vlan_tag = m->m_pkthdr.ether_vtag;
}
-#else
- {
- struct m_tag *mtag;
-
- if ((mtag = VLAN_OUTPUT_TAG(sc->bge_ifp, m)) != NULL) {
- csum_flags |= BGE_TXBDFLAG_VLAN_TAG;
- vlan_tag = VLAN_TAG_VALUE(mtag);
- }
- }
-#endif
for (i = 0; ; i++) {
d = &sc->bge_ldata.bge_tx_ring[idx];
d->bge_addr.bge_addr_lo = BGE_ADDR_LO(segs[i].ds_addr);
@@ -4547,29 +5273,6 @@ bge_start_locked(struct ifnet *ifp)
break;
/*
- * XXX
- * The code inside the if() block is never reached since we
- * must mark CSUM_IP_FRAGS in our if_hwassist to start getting
- * requests to checksum TCP/UDP in a fragmented packet.
- *
- * XXX
- * safety overkill. If this is a fragmented packet chain
- * with delayed TCP/UDP checksums, then only encapsulate
- * it if we have enough descriptors to handle the entire
- * chain at once.
- * (paranoia -- may not actually be needed)
- */
- if (m_head->m_flags & M_FIRSTFRAG &&
- m_head->m_pkthdr.csum_flags & (CSUM_DELAY_DATA)) {
- if ((BGE_TX_RING_CNT - sc->bge_txcnt) <
- m_head->m_pkthdr.csum_data + 16) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
- }
-
- /*
* Pack the data into the transmit ring. If we
* don't have room, set the OACTIVE flag and wait
* for the NIC to drain the ring.
@@ -4719,7 +5422,8 @@ bge_init_locked(struct bge_softc *sc)
}
/* Init jumbo RX ring. */
- if (ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN >
+ if (BGE_IS_JUMBO_CAPABLE(sc) &&
+ ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN >
(MCLBYTES - ETHER_ALIGN)) {
if (bge_init_rx_ring_jumbo(sc) != 0) {
device_printf(sc->bge_dev,
@@ -4742,11 +5446,21 @@ bge_init_locked(struct bge_softc *sc)
mode = CSR_READ_4(sc, BGE_TX_MODE);
if (BGE_IS_5755_PLUS(sc) || sc->bge_asicrev == BGE_ASICREV_BCM5906)
mode |= BGE_TXMODE_MBUF_LOCKUP_FIX;
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+ mode &= ~(BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE);
+ mode |= CSR_READ_4(sc, BGE_TX_MODE) &
+ (BGE_TXMODE_JMB_FRM_LEN | BGE_TXMODE_CNT_DN_MODE);
+ }
/* Turn on transmitter. */
CSR_WRITE_4(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE);
+ DELAY(100);
/* Turn on receiver. */
- BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE);
+ mode = CSR_READ_4(sc, BGE_RX_MODE);
+ if (BGE_IS_5755_PLUS(sc))
+ mode |= BGE_RXMODE_IPV6_ENABLE;
+ CSR_WRITE_4(sc,BGE_RX_MODE, mode | BGE_RXMODE_ENABLE);
+ DELAY(10);
/*
* Set the number of good frames to receive after RX MBUF
@@ -4754,7 +5468,10 @@ bge_init_locked(struct bge_softc *sc)
* this number of frames, it will drop subsequent incoming
* frames until the MBUF High Watermark is reached.
*/
- CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2);
+ if (sc->bge_asicrev == BGE_ASICREV_BCM57765)
+ CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1);
+ else
+ CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2);
/* Clear MAC statistics. */
if (BGE_IS_5705_PLUS(sc))
@@ -4779,11 +5496,11 @@ bge_init_locked(struct bge_softc *sc)
bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
}
- bge_ifmedia_upd_locked(ifp);
-
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ bge_ifmedia_upd_locked(ifp);
+
callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc);
}
@@ -4860,6 +5577,7 @@ bge_ifmedia_upd_locked(struct ifnet *ifp)
BGE_SETBIT(sc, BGE_MAC_MODE,
BGE_MACMODE_HALF_DUPLEX);
}
+ DELAY(40);
break;
default:
return (EINVAL);
@@ -4869,9 +5587,8 @@ bge_ifmedia_upd_locked(struct ifnet *ifp)
sc->bge_link_evt++;
mii = device_get_softc(sc->bge_miibus);
- if (mii->mii_instance)
- LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
- mii_phy_reset(miisc);
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ mii_phy_reset(miisc);
mii_mediachg(mii);
/*
@@ -4944,14 +5661,19 @@ bge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
switch (command) {
case SIOCSIFMTU:
- BGE_LOCK(sc);
- if (ifr->ifr_mtu < ETHERMIN ||
- ((BGE_IS_JUMBO_CAPABLE(sc)) &&
- ifr->ifr_mtu > BGE_JUMBO_MTU) ||
- ((!BGE_IS_JUMBO_CAPABLE(sc)) &&
- ifr->ifr_mtu > ETHERMTU))
+ if (BGE_IS_JUMBO_CAPABLE(sc) ||
+ (sc->bge_flags & BGE_FLAG_JUMBO_STD)) {
+ if (ifr->ifr_mtu < ETHERMIN ||
+ ifr->ifr_mtu > BGE_JUMBO_MTU) {
+ error = EINVAL;
+ break;
+ }
+ } else if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU) {
error = EINVAL;
- else if (ifp->if_mtu != ifr->ifr_mtu) {
+ break;
+ }
+ BGE_LOCK(sc);
+ if (ifp->if_mtu != ifr->ifr_mtu) {
ifp->if_mtu = ifr->ifr_mtu;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
@@ -5106,6 +5828,20 @@ bge_watchdog(struct bge_softc *sc)
ifp->if_oerrors++;
}
+static void
+bge_stop_block(struct bge_softc *sc, bus_size_t reg, uint32_t bit)
+{
+ int i;
+
+ BGE_CLRBIT(sc, reg, bit);
+
+ for (i = 0; i < BGE_TIMEOUT; i++) {
+ if ((CSR_READ_4(sc, reg) & bit) == 0)
+ return;
+ DELAY(100);
+ }
+}
+
/*
* Stop the adapter and free any mbufs allocated to the
* RX and TX lists.
@@ -5129,40 +5865,41 @@ bge_stop(struct bge_softc *sc)
* Tell firmware we're shutting down.
*/
bge_stop_fw(sc);
- bge_sig_pre_reset(sc, BGE_RESET_STOP);
+ bge_sig_pre_reset(sc, BGE_RESET_SHUTDOWN);
/*
* Disable all of the receiver blocks.
*/
- BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE);
- if (!(BGE_IS_5705_PLUS(sc)))
- BGE_CLRBIT(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE);
+ bge_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE);
+ bge_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE);
+ bge_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE);
+ if (BGE_IS_5700_FAMILY(sc))
+ bge_stop_block(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE);
+ bge_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE);
+ bge_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
+ bge_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE);
/*
* Disable all of the transmit blocks.
*/
- BGE_CLRBIT(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE);
- if (!(BGE_IS_5705_PLUS(sc)))
- BGE_CLRBIT(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE);
+ bge_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE);
+ bge_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE);
+ bge_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE);
+ bge_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE);
+ bge_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE);
+ if (BGE_IS_5700_FAMILY(sc))
+ bge_stop_block(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE);
+ bge_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE);
/*
* Shut down all of the memory managers and related
* state machines.
*/
- BGE_CLRBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE);
- BGE_CLRBIT(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE);
- if (!(BGE_IS_5705_PLUS(sc)))
- BGE_CLRBIT(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE);
+ bge_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE);
+ bge_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE);
+ if (BGE_IS_5700_FAMILY(sc))
+ bge_stop_block(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE);
+
CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF);
CSR_WRITE_4(sc, BGE_FTQ_RESET, 0);
if (!(BGE_IS_5705_PLUS(sc))) {
@@ -5174,8 +5911,8 @@ bge_stop(struct bge_softc *sc)
bge_stats_update_regs(sc);
bge_reset(sc);
- bge_sig_legacy(sc, BGE_RESET_STOP);
- bge_sig_post_reset(sc, BGE_RESET_STOP);
+ bge_sig_legacy(sc, BGE_RESET_SHUTDOWN);
+ bge_sig_post_reset(sc, BGE_RESET_SHUTDOWN);
/*
* Keep the ASF firmware running if up.
@@ -5217,7 +5954,6 @@ bge_shutdown(device_t dev)
sc = device_get_softc(dev);
BGE_LOCK(sc);
bge_stop(sc);
- bge_reset(sc);
BGE_UNLOCK(sc);
return (0);
@@ -5304,9 +6040,10 @@ bge_link_upd(struct bge_softc *sc)
/* Clear the interrupt. */
CSR_WRITE_4(sc, BGE_MAC_EVT_ENB,
BGE_EVTENB_MI_INTERRUPT);
- bge_miibus_readreg(sc->bge_dev, 1, BRGPHY_MII_ISR);
- bge_miibus_writereg(sc->bge_dev, 1, BRGPHY_MII_IMR,
- BRGPHY_INTRS);
+ bge_miibus_readreg(sc->bge_dev, sc->bge_phy_addr,
+ BRGPHY_MII_ISR);
+ bge_miibus_writereg(sc->bge_dev, sc->bge_phy_addr,
+ BRGPHY_MII_IMR, BRGPHY_INTRS);
}
return;
}
@@ -5316,9 +6053,11 @@ bge_link_upd(struct bge_softc *sc)
if (status & BGE_MACSTAT_TBI_PCS_SYNCHED) {
if (!sc->bge_link) {
sc->bge_link++;
- if (sc->bge_asicrev == BGE_ASICREV_BCM5704)
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5704) {
BGE_CLRBIT(sc, BGE_MAC_MODE,
BGE_MACMODE_TBI_SEND_CFGS);
+ DELAY(40);
+ }
CSR_WRITE_4(sc, BGE_MAC_STS, 0xFFFFFFFF);
if (bootverbose)
if_printf(sc->bge_ifp, "link UP\n");
@@ -5367,7 +6106,7 @@ bge_link_upd(struct bge_softc *sc)
bge_miibus_statchg(sc->bge_dev);
}
- /* Clear the attention. */
+ /* Disable MAC attention when link is up. */
CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED |
BGE_MACSTAT_CFG_CHANGED | BGE_MACSTAT_MI_COMPLETE |
BGE_MACSTAT_LINK_CHANGED);
@@ -5391,7 +6130,11 @@ bge_add_sysctls(struct bge_softc *sc)
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "reg_read",
CTLTYPE_INT | CTLFLAG_RW, sc, 0, bge_sysctl_reg_read, "I",
- "Register Read");
+ "MAC Register Read");
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "ape_read",
+ CTLTYPE_INT | CTLFLAG_RW, sc, 0, bge_sysctl_ape_read, "I",
+ "APE Register Read");
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "mem_read",
CTLTYPE_INT | CTLFLAG_RW, sc, 0, bge_sysctl_mem_read, "I",
@@ -5420,6 +6163,12 @@ bge_add_sysctls(struct bge_softc *sc)
"Number of fragmented TX buffers of a frame allowed before "
"forced collapsing");
+ sc->bge_msi = 1;
+ snprintf(tn, sizeof(tn), "dev.bge.%d.msi", unit);
+ TUNABLE_INT_FETCH(tn, &sc->bge_msi);
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO, "msi",
+ CTLFLAG_RD, &sc->bge_msi, 0, "Enable MSI");
+
/*
* It seems all Broadcom controllers have a bug that can generate UDP
* datagrams with checksum value 0 when TX UDP checksum offloading is
@@ -5693,8 +6442,7 @@ bge_sysctl_debug_info(SYSCTL_HANDLER_ARGS)
{
struct bge_softc *sc;
uint16_t *sbdata;
- int error;
- int result;
+ int error, result, sbsz;
int i, j;
result = -1;
@@ -5705,14 +6453,21 @@ bge_sysctl_debug_info(SYSCTL_HANDLER_ARGS)
if (result == 1) {
sc = (struct bge_softc *)arg1;
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5700 &&
+ sc->bge_chipid != BGE_CHIPID_BCM5700_C0)
+ sbsz = BGE_STATUS_BLK_SZ;
+ else
+ sbsz = 32;
sbdata = (uint16_t *)sc->bge_ldata.bge_status_block;
printf("Status Block:\n");
- for (i = 0x0; i < (BGE_STATUS_BLK_SZ / 4); ) {
+ BGE_LOCK(sc);
+ bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
+ sc->bge_cdata.bge_status_map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ for (i = 0x0; i < sbsz / sizeof(uint16_t); ) {
printf("%06x:", i);
- for (j = 0; j < 8; j++) {
- printf(" %04x", sbdata[i]);
- i += 4;
- }
+ for (j = 0; j < 8; j++)
+ printf(" %04x", sbdata[i++]);
printf("\n");
}
@@ -5725,8 +6480,11 @@ bge_sysctl_debug_info(SYSCTL_HANDLER_ARGS)
}
printf("\n");
}
+ BGE_UNLOCK(sc);
printf("Hardware Flags:\n");
+ if (BGE_IS_5717_PLUS(sc))
+ printf(" - 5717 Plus\n");
if (BGE_IS_5755_PLUS(sc))
printf(" - 5755 Plus\n");
if (BGE_IS_575X_PLUS(sc))
@@ -5775,6 +6533,28 @@ bge_sysctl_reg_read(SYSCTL_HANDLER_ARGS)
}
static int
+bge_sysctl_ape_read(SYSCTL_HANDLER_ARGS)
+{
+ struct bge_softc *sc;
+ int error;
+ uint16_t result;
+ uint32_t val;
+
+ result = -1;
+ error = sysctl_handle_int(oidp, &result, 0, req);
+ if (error || (req->newptr == NULL))
+ return (error);
+
+ if (result < 0x8000) {
+ sc = (struct bge_softc *)arg1;
+ val = APE_READ_4(sc, result);
+ printf("reg 0x%06X = 0x%08X\n", result, val);
+ }
+
+ return (error);
+}
+
+static int
bge_sysctl_mem_read(SYSCTL_HANDLER_ARGS)
{
struct bge_softc *sc;
@@ -5816,11 +6596,11 @@ bge_get_eaddr_mem(struct bge_softc *sc, uint8_t ether_addr[])
{
uint32_t mac_addr;
- mac_addr = bge_readmem_ind(sc, 0x0c14);
+ mac_addr = bge_readmem_ind(sc, BGE_SRAM_MAC_ADDR_HIGH_MB);
if ((mac_addr >> 16) == 0x484b) {
ether_addr[0] = (uint8_t)(mac_addr >> 8);
ether_addr[1] = (uint8_t)mac_addr;
- mac_addr = bge_readmem_ind(sc, 0x0c18);
+ mac_addr = bge_readmem_ind(sc, BGE_SRAM_MAC_ADDR_LOW_MB);
ether_addr[2] = (uint8_t)(mac_addr >> 24);
ether_addr[3] = (uint8_t)(mac_addr >> 16);
ether_addr[4] = (uint8_t)(mac_addr >> 8);
diff --git a/freebsd/sys/dev/bge/if_bgereg.h b/freebsd/sys/dev/bge/if_bgereg.h
index 6a9c2e81..93617cd1 100644
--- a/freebsd/sys/dev/bge/if_bgereg.h
+++ b/freebsd/sys/dev/bge/if_bgereg.h
@@ -71,12 +71,15 @@
#define BGE_STATS_BLOCK_END 0x00000AFF
#define BGE_STATUS_BLOCK 0x00000B00
#define BGE_STATUS_BLOCK_END 0x00000B4F
-#define BGE_SOFTWARE_GENCOMM 0x00000B50
-#define BGE_SOFTWARE_GENCOMM_SIG 0x00000B54
-#define BGE_SOFTWARE_GENCOMM_NICCFG 0x00000B58
-#define BGE_SOFTWARE_GENCOMM_FW 0x00000B78
-#define BGE_SOFTWARE_GENNCOMM_FW_LEN 0x00000B7C
-#define BGE_SOFTWARE_GENNCOMM_FW_DATA 0x00000B80
+#define BGE_SRAM_FW_MB 0x00000B50
+#define BGE_SRAM_DATA_SIG 0x00000B54
+#define BGE_SRAM_DATA_CFG 0x00000B58
+#define BGE_SRAM_FW_CMD_MB 0x00000B78
+#define BGE_SRAM_FW_CMD_LEN_MB 0x00000B7C
+#define BGE_SRAM_FW_CMD_DATA_MB 0x00000B80
+#define BGE_SRAM_FW_DRV_STATE_MB 0x00000C04
+#define BGE_SRAM_MAC_ADDR_HIGH_MB 0x00000C14
+#define BGE_SRAM_MAC_ADDR_LOW_MB 0x00000C18
#define BGE_SOFTWARE_GENCOMM_END 0x00000FFF
#define BGE_UNMAPPED 0x00001000
#define BGE_UNMAPPED_END 0x00001FFF
@@ -87,8 +90,24 @@
#define BGE_SEND_RING_1_TO_4_END 0x00005FFF
/* Firmware interface */
-#define BGE_FW_DRV_ALIVE 0x00000001
-#define BGE_FW_PAUSE 0x00000002
+#define BGE_SRAM_DATA_SIG_MAGIC 0x4B657654 /* 'KevT' */
+
+#define BGE_FW_CMD_DRV_ALIVE 0x00000001
+#define BGE_FW_CMD_PAUSE 0x00000002
+#define BGE_FW_CMD_IPV4_ADDR_CHANGE 0x00000003
+#define BGE_FW_CMD_IPV6_ADDR_CHANGE 0x00000004
+#define BGE_FW_CMD_LINK_UPDATE 0x0000000C
+#define BGE_FW_CMD_DRV_ALIVE2 0x0000000D
+#define BGE_FW_CMD_DRV_ALIVE3 0x0000000E
+
+#define BGE_FW_HB_TIMEOUT_SEC 3
+
+#define BGE_FW_DRV_STATE_START 0x00000001
+#define BGE_FW_DRV_STATE_START_DONE 0x80000001
+#define BGE_FW_DRV_STATE_UNLOAD 0x00000002
+#define BGE_FW_DRV_STATE_UNLOAD_DONE 0x80000002
+#define BGE_FW_DRV_STATE_WOL 0x00000003
+#define BGE_FW_DRV_STATE_SUSPEND 0x00000004
/* Mappings for internal memory configuration */
#define BGE_STD_RX_RINGS 0x00006000
@@ -223,6 +242,7 @@
#define BGE_PCI_ISR_MBX_LO 0xB4
#define BGE_PCI_PRODID_ASICREV 0xBC
#define BGE_PCI_GEN2_PRODID_ASICREV 0xF4
+#define BGE_PCI_GEN15_PRODID_ASICREV 0xFC
/* PCI Misc. Host control register */
#define BGE_PCIMISCCTL_CLEAR_INTA 0x00000001
@@ -238,15 +258,6 @@
#define BGE_PCIMISCCTL_ASICREV_SHIFT 16
#define BGE_HIF_SWAP_OPTIONS (BGE_PCIMISCCTL_ENDIAN_WORDSWAP)
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define BGE_DMA_SWAP_OPTIONS \
- BGE_MODECTL_WORDSWAP_NONFRAME| \
- BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA
-#else
-#define BGE_DMA_SWAP_OPTIONS \
- BGE_MODECTL_WORDSWAP_NONFRAME|BGE_MODECTL_BYTESWAP_NONFRAME| \
- BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA
-#endif
#define BGE_INIT \
(BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_CLEAR_INTA| \
@@ -318,6 +329,10 @@
#define BGE_CHIPID_BCM57780_A1 0x57780001
#define BGE_CHIPID_BCM5717_A0 0x05717000
#define BGE_CHIPID_BCM5717_B0 0x05717100
+#define BGE_CHIPID_BCM5719_A0 0x05719000
+#define BGE_CHIPID_BCM5720_A0 0x05720000
+#define BGE_CHIPID_BCM57765_A0 0x57785000
+#define BGE_CHIPID_BCM57765_B0 0x57785100
/* shorthand one */
#define BGE_ASICREV(x) ((x) >> 12)
@@ -339,9 +354,13 @@
#define BGE_ASICREV_USE_PRODID_REG 0x0f
/* BGE_PCI_PRODID_ASICREV ASIC rev. identifiers. */
#define BGE_ASICREV_BCM5717 0x5717
+#define BGE_ASICREV_BCM5719 0x5719
+#define BGE_ASICREV_BCM5720 0x5720
#define BGE_ASICREV_BCM5761 0x5761
#define BGE_ASICREV_BCM5784 0x5784
#define BGE_ASICREV_BCM5785 0x5785
+#define BGE_ASICREV_BCM57765 0x57785
+#define BGE_ASICREV_BCM57766 0x57766
#define BGE_ASICREV_BCM57780 0x57780
/* chip revisions */
@@ -381,6 +400,9 @@
#define BGE_PCIDMARWCTL_RD_CMD_SHIFT(x) ((x) << 24)
#define BGE_PCIDMARWCTL_WR_CMD_SHIFT(x) ((x) << 28)
+#define BGE_PCIDMARWCTL_TAGGED_STATUS_WA 0x00000080
+#define BGE_PCIDMARWCTL_CRDRDR_RDMA_MRRS_MSK 0x00000380
+
#define BGE_PCI_READ_BNDRY_DISABLE 0x00000000
#define BGE_PCI_READ_BNDRY_16BYTES 0x00000100
#define BGE_PCI_READ_BNDRY_32BYTES 0x00000200
@@ -409,10 +431,14 @@
#define BGE_PCISTATE_PCI_BUSMODE 0x00000004 /* 1 = PCI, 0 = PCI-X */
#define BGE_PCISTATE_PCI_BUSSPEED 0x00000008 /* 1 = 66/133, 0 = 33/66 */
#define BGE_PCISTATE_32BIT_BUS 0x00000010 /* 1 = 32bit, 0 = 64bit */
-#define BGE_PCISTATE_WANT_EXPROM 0x00000020
-#define BGE_PCISTATE_EXPROM_RETRY 0x00000040
+#define BGE_PCISTATE_ROM_ENABLE 0x00000020
+#define BGE_PCISTATE_ROM_RETRY_ENABLE 0x00000040
#define BGE_PCISTATE_FLATVIEW_MODE 0x00000100
#define BGE_PCISTATE_PCI_TGT_RETRY_MAX 0x00000E00
+#define BGE_PCISTATE_RETRY_SAME_DMA 0x00002000
+#define BGE_PCISTATE_ALLOW_APE_CTLSPC_WR 0x00010000
+#define BGE_PCISTATE_ALLOW_APE_SHMEM_WR 0x00020000
+#define BGE_PCISTATE_ALLOW_APE_PSPACE_WR 0x00040000
/*
* PCI Clock Control register -- note, this register is read only
@@ -438,6 +464,8 @@
#define PCIM_CMD_INTxDIS 0x0400
#endif
+/* BAR0 (MAC) Register Definitions */
+
/*
* High priority mailbox registers
* Each mailbox is 64-bits wide, though we only use the
@@ -720,6 +748,8 @@
#define BGE_MACMODE_TXDMA_ENB 0x00200000
#define BGE_MACMODE_RXDMA_ENB 0x00400000
#define BGE_MACMODE_FRMHDR_DMA_ENB 0x00800000
+#define BGE_MACMODE_APE_RX_EN 0x08000000
+#define BGE_MACMODE_APE_TX_EN 0x10000000
#define BGE_PORTMODE_NONE 0x00000000
#define BGE_PORTMODE_MII 0x00000004
@@ -779,6 +809,8 @@
#define BGE_TXMODE_BIGBACKOFF_ENABLE 0x00000020
#define BGE_TXMODE_LONGPAUSE_ENABLE 0x00000040
#define BGE_TXMODE_MBUF_LOCKUP_FIX 0x00000100
+#define BGE_TXMODE_JMB_FRM_LEN 0x00400000
+#define BGE_TXMODE_CNT_DN_MODE 0x00800000
/* Transmit MAC status register */
#define BGE_TXSTAT_RX_XOFFED 0x00000001
@@ -792,6 +824,8 @@
#define BGE_TXLEN_SLOTTIME 0x000000FF
#define BGE_TXLEN_IPG 0x00000F00
#define BGE_TXLEN_CRS 0x00003000
+#define BGE_TXLEN_JMB_FRM_LEN_MSK 0x00FF0000
+#define BGE_TXLEN_CNT_DN_VAL_MSK 0xFF000000
/* Receive MAC mode register */
#define BGE_RXMODE_RESET 0x00000001
@@ -803,6 +837,7 @@
#define BGE_RXMODE_RX_PROMISC 0x00000100
#define BGE_RXMODE_RX_NO_CRC_CHECK 0x00000200
#define BGE_RXMODE_RX_KEEP_VLAN_DIAG 0x00000400
+#define BGE_RXMODE_IPV6_ENABLE 0x01000000
/* Receive MAC status register */
#define BGE_RXSTAT_REMOTE_XOFFED 0x00000001
@@ -1249,6 +1284,7 @@
#define BGE_CPMU_LSPD_1000MB_CLK 0x360C
#define BGE_CPMU_LNK_AWARE_PWRMD 0x3610
#define BGE_CPMU_HST_ACC 0x361C
+#define BGE_CPMU_CLCK_ORIDE 0x3624
#define BGE_CPMU_CLCK_STAT 0x3630
#define BGE_CPMU_MUTEX_REQ 0x365C
#define BGE_CPMU_MUTEX_GNT 0x3660
@@ -1276,6 +1312,9 @@
#define BGE_CPMU_HST_ACC_MACCLK_MASK 0x001F0000
#define BGE_CPMU_HST_ACC_MACCLK_6_25 0x00130000
+/* Clock Speed Override Policy register */
+#define CPMU_CLCK_ORIDE_MAC_ORIDE_EN 0x80000000
+
/* CPMU Clock Status register */
#define BGE_CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001F0000
#define BGE_CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000
@@ -1488,6 +1527,7 @@
#define BGE_BMANMODE_ATTN 0x00000004
#define BGE_BMANMODE_TESTMODE 0x00000008
#define BGE_BMANMODE_LOMBUF_ATTN 0x00000010
+#define BGE_BMANMODE_NO_TX_UNDERRUN 0x80000000
/* Buffer manager status register */
#define BGE_BMANSTAT_ERRO 0x00000004
@@ -1500,6 +1540,7 @@
#define BGE_RDMA_MODE 0x4800
#define BGE_RDMA_STATUS 0x4804
#define BGE_RDMA_RSRVCTRL 0x4900
+#define BGE_RDMA_LSO_CRPTEN_CTRL 0x4910
/* Read DMA mode register */
#define BGE_RDMAMODE_RESET 0x00000001
@@ -1521,6 +1562,7 @@
#define BGE_RDMAMODE_MULT_DMA_RD_DIS 0x01000000
#define BGE_RDMAMODE_TSO4_ENABLE 0x08000000
#define BGE_RDMAMODE_TSO6_ENABLE 0x10000000
+#define BGE_RDMAMODE_H2BNC_VLAN_DET 0x20000000
/* Read DMA status register */
#define BGE_RDMASTAT_PCI_TGT_ABRT_ATTN 0x00000004
@@ -1534,6 +1576,32 @@
/* Read DMA Reserved Control register */
#define BGE_RDMA_RSRVCTRL_FIFO_OFLW_FIX 0x00000004
+#define BGE_RDMA_RSRVCTRL_FIFO_LWM_1_5K 0x00000C00
+#define BGE_RDMA_RSRVCTRL_FIFO_HWM_1_5K 0x000C0000
+#define BGE_RDMA_RSRVCTRL_TXMRGN_320B 0x28000000
+#define BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK 0x00000FF0
+#define BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK 0x000FF000
+#define BGE_RDMA_RSRVCTRL_TXMRGN_MASK 0xFFE00000
+
+#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 0x00020000
+#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K 0x00030000
+#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K 0x000C0000
+
+/* BD Read DMA Mode register */
+#define BGE_RDMA_BD_MODE 0x4A00
+/* BD Read DMA Mode status register */
+#define BGE_RDMA_BD_STATUS 0x4A04
+
+#define BGE_RDMA_BD_MODE_RESET 0x00000001
+#define BGE_RDMA_BD_MODE_ENABLE 0x00000002
+
+/* Non-LSO Read DMA Mode register */
+#define BGE_RDMA_NON_LSO_MODE 0x4B00
+/* Non-LSO Read DMA Mode status register */
+#define BGE_RDMA_NON_LSO_STATUS 0x4B04
+
+#define BGE_RDMA_NON_LSO_MODE_RESET 0x00000001
+#define BGE_RDMA_NON_LSO_MODE_ENABLE 0x00000002
/*
* Write DMA control registers
@@ -1855,7 +1923,8 @@
#define BGE_MODE_CTL 0x6800
#define BGE_MISC_CFG 0x6804
#define BGE_MISC_LOCAL_CTL 0x6808
-#define BGE_CPU_EVENT 0x6810
+#define BGE_RX_CPU_EVENT 0x6810
+#define BGE_TX_CPU_EVENT 0x6820
#define BGE_EE_ADDR 0x6838
#define BGE_EE_DATA 0x683C
#define BGE_EE_CTL 0x6840
@@ -1863,6 +1932,8 @@
#define BGE_EE_DELAY 0x6848
#define BGE_FASTBOOT_PC 0x6894
+#define BGE_RX_CPU_DRV_EVENT 0x00004000
+
/*
* NVRAM Control registers
*/
@@ -1919,14 +1990,18 @@
#define BGE_MODECTL_WORDSWAP_NONFRAME 0x00000004
#define BGE_MODECTL_BYTESWAP_DATA 0x00000010
#define BGE_MODECTL_WORDSWAP_DATA 0x00000020
+#define BGE_MODECTL_BYTESWAP_B2HRX_DATA 0x00000040
+#define BGE_MODECTL_WORDSWAP_B2HRX_DATA 0x00000080
#define BGE_MODECTL_NO_FRAME_CRACKING 0x00000200
#define BGE_MODECTL_NO_RX_CRC 0x00000400
#define BGE_MODECTL_RX_BADFRAMES 0x00000800
#define BGE_MODECTL_NO_TX_INTR 0x00002000
#define BGE_MODECTL_NO_RX_INTR 0x00004000
#define BGE_MODECTL_FORCE_PCI32 0x00008000
+#define BGE_MODECTL_B2HRX_ENABLE 0x00008000
#define BGE_MODECTL_STACKUP 0x00010000
#define BGE_MODECTL_HOST_SEND_BDS 0x00020000
+#define BGE_MODECTL_HTX2B_ENABLE 0x00040000
#define BGE_MODECTL_TX_NO_PHDR_CSUM 0x00100000
#define BGE_MODECTL_RX_NO_PHDR_CSUM 0x00800000
#define BGE_MODECTL_TX_ATTN_INTR 0x01000000
@@ -1940,7 +2015,9 @@
/* Misc. config register */
#define BGE_MISCCFG_RESET_CORE_CLOCKS 0x00000001
#define BGE_MISCCFG_TIMER_PRESCALER 0x000000FE
-#define BGE_MISCCFG_BOARD_ID 0x0001E000
+#define BGE_MISCCFG_BOARD_ID_MASK 0x0001E000
+#define BGE_MISCCFG_BOARD_ID_5704 0x00000000
+#define BGE_MISCCFG_BOARD_ID_5704CIOBE 0x00004000
#define BGE_MISCCFG_BOARD_ID_5788 0x00010000
#define BGE_MISCCFG_BOARD_ID_5788M 0x00018000
#define BGE_MISCCFG_EPHY_IDDQ 0x00200000
@@ -2013,6 +2090,112 @@
#define BGE_MEMWIN_START 0x00008000
#define BGE_MEMWIN_END 0x0000FFFF
+/* BAR1 (APE) Register Definitions */
+
+#define BGE_APE_GPIO_MSG 0x0008
+#define BGE_APE_EVENT 0x000C
+#define BGE_APE_LOCK_REQ 0x002C
+#define BGE_APE_LOCK_GRANT 0x004C
+
+#define BGE_APE_GPIO_MSG_SHIFT 4
+
+#define BGE_APE_EVENT_1 0x00000001
+
+#define BGE_APE_LOCK_REQ_DRIVER0 0x00001000
+
+#define BGE_APE_LOCK_GRANT_DRIVER0 0x00001000
+
+/* APE Shared Memory block (writable by APE only) */
+#define BGE_APE_SEG_SIG 0x4000
+#define BGE_APE_FW_STATUS 0x400C
+#define BGE_APE_FW_FEATURES 0x4010
+#define BGE_APE_FW_BEHAVIOR 0x4014
+#define BGE_APE_FW_VERSION 0x4018
+#define BGE_APE_FW_HEARTBEAT_INTERVAL 0x4024
+#define BGE_APE_FW_HEARTBEAT 0x4028
+#define BGE_APE_FW_ERROR_FLAGS 0x4074
+
+#define BGE_APE_SEG_SIG_MAGIC 0x41504521
+
+#define BGE_APE_FW_STATUS_READY 0x00000100
+
+#define BGE_APE_FW_FEATURE_DASH 0x00000001
+#define BGE_APE_FW_FEATURE_NCSI 0x00000002
+
+#define BGE_APE_FW_VERSION_MAJMSK 0xFF000000
+#define BGE_APE_FW_VERSION_MAJSFT 24
+#define BGE_APE_FW_VERSION_MINMSK 0x00FF0000
+#define BGE_APE_FW_VERSION_MINSFT 16
+#define BGE_APE_FW_VERSION_REVMSK 0x0000FF00
+#define BGE_APE_FW_VERSION_REVSFT 8
+#define BGE_APE_FW_VERSION_BLDMSK 0x000000FF
+
+/* Host Shared Memory block (writable by host only) */
+#define BGE_APE_HOST_SEG_SIG 0x4200
+#define BGE_APE_HOST_SEG_LEN 0x4204
+#define BGE_APE_HOST_INIT_COUNT 0x4208
+#define BGE_APE_HOST_DRIVER_ID 0x420C
+#define BGE_APE_HOST_BEHAVIOR 0x4210
+#define BGE_APE_HOST_HEARTBEAT_INT_MS 0x4214
+#define BGE_APE_HOST_HEARTBEAT_COUNT 0x4218
+#define BGE_APE_HOST_DRVR_STATE 0x421C
+#define BGE_APE_HOST_WOL_SPEED 0x4224
+
+#define BGE_APE_HOST_SEG_SIG_MAGIC 0x484F5354
+
+#define BGE_APE_HOST_SEG_LEN_MAGIC 0x00000020
+
+#define BGE_APE_HOST_DRIVER_ID_FBSD 0xF6000000
+#define BGE_APE_HOST_DRIVER_ID_MAGIC(maj, min) \
+ (BGE_APE_HOST_DRIVER_ID_FBSD | \
+ ((maj) & 0xffd) << 16 | ((min) & 0xff) << 8)
+
+#define BGE_APE_HOST_BEHAV_NO_PHYLOCK 0x00000001
+
+#define BGE_APE_HOST_HEARTBEAT_INT_DISABLE 0
+#define BGE_APE_HOST_HEARTBEAT_INT_5SEC 5000
+
+#define BGE_APE_HOST_DRVR_STATE_START 0x00000001
+#define BGE_APE_HOST_DRVR_STATE_UNLOAD 0x00000002
+#define BGE_APE_HOST_DRVR_STATE_WOL 0x00000003
+#define BGE_APE_HOST_DRVR_STATE_SUSPEND 0x00000004
+
+#define BGE_APE_HOST_WOL_SPEED_AUTO 0x00008000
+
+#define BGE_APE_EVENT_STATUS 0x4300
+
+#define BGE_APE_EVENT_STATUS_DRIVER_EVNT 0x00000010
+#define BGE_APE_EVENT_STATUS_STATE_CHNGE 0x00000500
+#define BGE_APE_EVENT_STATUS_STATE_START 0x00010000
+#define BGE_APE_EVENT_STATUS_STATE_UNLOAD 0x00020000
+#define BGE_APE_EVENT_STATUS_STATE_WOL 0x00030000
+#define BGE_APE_EVENT_STATUS_STATE_SUSPEND 0x00040000
+#define BGE_APE_EVENT_STATUS_EVENT_PENDING 0x80000000
+
+#define BGE_APE_DEBUG_LOG 0x4E00
+#define BGE_APE_DEBUG_LOG_LEN 0x0100
+
+#define BGE_APE_PER_LOCK_REQ 0x8400
+#define BGE_APE_PER_LOCK_GRANT 0x8420
+
+#define BGE_APE_LOCK_PER_REQ_DRIVER0 0x00001000
+#define BGE_APE_LOCK_PER_REQ_DRIVER1 0x00000002
+#define BGE_APE_LOCK_PER_REQ_DRIVER2 0x00000004
+#define BGE_APE_LOCK_PER_REQ_DRIVER3 0x00000008
+
+#define BGE_APE_PER_LOCK_GRANT_DRIVER0 0x00001000
+#define BGE_APE_PER_LOCK_GRANT_DRIVER1 0x00000002
+#define BGE_APE_PER_LOCK_GRANT_DRIVER2 0x00000004
+#define BGE_APE_PER_LOCK_GRANT_DRIVER3 0x00000008
+
+/* APE Mutex Resources */
+#define BGE_APE_LOCK_PHY0 0
+#define BGE_APE_LOCK_GRC 1
+#define BGE_APE_LOCK_PHY1 2
+#define BGE_APE_LOCK_PHY2 3
+#define BGE_APE_LOCK_MEM 4
+#define BGE_APE_LOCK_PHY3 5
+#define BGE_APE_LOCK_GPIO 7
#define BGE_MEMWIN_READ(sc, x, val) \
do { \
@@ -2032,10 +2215,10 @@
* This magic number is written to the firmware mailbox at 0xb50
* before a software reset is issued. After the internal firmware
* has completed its initialization it will write the opposite of
- * this value, ~BGE_MAGIC_NUMBER, to the same location, allowing the
- * driver to synchronize with the firmware.
+ * this value, ~BGE_SRAM_FW_MB_MAGIC, to the same location,
+ * allowing the driver to synchronize with the firmware.
*/
-#define BGE_MAGIC_NUMBER 0x4B657654
+#define BGE_SRAM_FW_MB_MAGIC 0x4B657654
typedef struct {
uint32_t bge_addr_hi;
@@ -2255,7 +2438,9 @@ struct bge_status_block {
#define BCOM_DEVICEID_BCM5715S 0x1679
#define BCOM_DEVICEID_BCM5717 0x1655
#define BCOM_DEVICEID_BCM5718 0x1656
-#define BCOM_DEVICEID_BCM5720 0x1658
+#define BCOM_DEVICEID_BCM5719 0x1657
+#define BCOM_DEVICEID_BCM5720_PP 0x1658 /* Not released to public. */
+#define BCOM_DEVICEID_BCM5720 0x165F
#define BCOM_DEVICEID_BCM5721 0x1659
#define BCOM_DEVICEID_BCM5722 0x165A
#define BCOM_DEVICEID_BCM5723 0x165B
@@ -2298,9 +2483,17 @@ struct bge_status_block {
#define BCOM_DEVICEID_BCM5906 0x1712
#define BCOM_DEVICEID_BCM5906M 0x1713
#define BCOM_DEVICEID_BCM57760 0x1690
+#define BCOM_DEVICEID_BCM57761 0x16B0
+#define BCOM_DEVICEID_BCM57762 0x1682
+#define BCOM_DEVICEID_BCM57765 0x16B4
+#define BCOM_DEVICEID_BCM57766 0x1686
#define BCOM_DEVICEID_BCM57780 0x1692
+#define BCOM_DEVICEID_BCM57781 0x16B1
+#define BCOM_DEVICEID_BCM57785 0x16B5
#define BCOM_DEVICEID_BCM57788 0x1691
#define BCOM_DEVICEID_BCM57790 0x1694
+#define BCOM_DEVICEID_BCM57791 0x16B2
+#define BCOM_DEVICEID_BCM57795 0x16B6
/*
* Alteon AceNIC PCI vendor/device ID.
@@ -2599,7 +2792,7 @@ struct bge_gib {
#define BGE_INC(x, y) (x) = (x + 1) % y
/*
- * Register access macros. The Tigon always uses memory mapped register
+ * BAR0 MAC register access macros. The Tigon always uses memory mapped register
* accesses and all registers must be accessed with 32 bit operations.
*/
@@ -2614,6 +2807,18 @@ struct bge_gib {
#define BGE_CLRBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, (CSR_READ_4(sc, reg) & ~(x)))
+/* BAR2 APE register access macros. */
+#define APE_WRITE_4(sc, reg, val) \
+ bus_write_4(sc->bge_res2, reg, val)
+
+#define APE_READ_4(sc, reg) \
+ bus_read_4(sc->bge_res2, reg)
+
+#define APE_SETBIT(sc, reg, x) \
+ APE_WRITE_4(sc, reg, (APE_READ_4(sc, reg) | (x)))
+#define APE_CLRBIT(sc, reg, x) \
+ APE_WRITE_4(sc, reg, (APE_READ_4(sc, reg) & ~(x)))
+
#define PCI_SETBIT(dev, reg, x, s) \
pci_write_config(dev, reg, (pci_read_config(dev, reg, s) | (x)), s)
#define PCI_CLRBIT(dev, reg, x, s) \
@@ -2740,18 +2945,22 @@ struct bge_softc {
device_t bge_miibus;
void *bge_intrhand;
struct resource *bge_irq;
- struct resource *bge_res;
+ struct resource *bge_res; /* MAC mapped I/O */
+ struct resource *bge_res2; /* APE mapped I/O */
struct ifmedia bge_ifmedia; /* TBI media info */
int bge_expcap;
+ int bge_expmrq;
int bge_msicap;
int bge_pcixcap;
uint32_t bge_flags;
#define BGE_FLAG_TBI 0x00000001
#define BGE_FLAG_JUMBO 0x00000002
+#define BGE_FLAG_JUMBO_STD 0x00000004
#define BGE_FLAG_EADDR 0x00000008
#define BGE_FLAG_MII_SERDES 0x00000010
#define BGE_FLAG_CPMU_PRESENT 0x00000020
#define BGE_FLAG_TAGGED_STATUS 0x00000040
+#define BGE_FLAG_APE 0x00000080
#define BGE_FLAG_MSI 0x00000100
#define BGE_FLAG_PCIX 0x00000200
#define BGE_FLAG_PCIE 0x00000400
@@ -2765,12 +2974,23 @@ struct bge_softc {
#define BGE_FLAG_5755_PLUS 0x00100000
#define BGE_FLAG_5788 0x00200000
#define BGE_FLAG_5717_PLUS 0x00400000
+#define BGE_FLAG_57765_PLUS 0x00800000
#define BGE_FLAG_40BIT_BUG 0x01000000
#define BGE_FLAG_4G_BNDRY_BUG 0x02000000
#define BGE_FLAG_RX_ALIGNBUG 0x04000000
#define BGE_FLAG_SHORT_DMA_BUG 0x08000000
+#define BGE_FLAG_4K_RDMA_BUG 0x10000000
+#define BGE_FLAG_MBOX_REORDER 0x20000000
+ uint32_t bge_mfw_flags; /* Management F/W flags */
+#define BGE_MFW_ON_RXCPU 0x00000001
+#define BGE_MFW_ON_APE 0x00000002
+#define BGE_MFW_TYPE_NCSI 0x00000004
+#define BGE_MFW_TYPE_DASH 0x00000008
+ int bge_phy_ape_lock;
+ int bge_func_addr;
+ int bge_phy_addr;
uint32_t bge_phy_flags;
-#define BGE_PHY_WIRESPEED 0x00000001
+#define BGE_PHY_NO_WIRESPEED 0x00000001
#define BGE_PHY_ADC_BUG 0x00000002
#define BGE_PHY_5704_A0_BUG 0x00000004
#define BGE_PHY_JITTER_BUG 0x00000008
@@ -2783,6 +3003,7 @@ struct bge_softc {
uint32_t bge_chiprev;
uint8_t bge_asf_mode;
uint8_t bge_asf_count;
+ uint16_t bge_mps;
struct bge_ring_data bge_ldata; /* rings */
struct bge_chain_data bge_cdata; /* mbufs */
uint16_t bge_tx_saved_considx;
@@ -2805,9 +3026,12 @@ struct bge_softc {
int bge_timer;
int bge_forced_collapse;
int bge_forced_udpcsum;
+ int bge_msi;
int bge_csum_features;
struct callout bge_stat_ch;
uint32_t bge_rx_discards;
+ uint32_t bge_rx_inerrs;
+ uint32_t bge_rx_nobds;
uint32_t bge_tx_discards;
uint32_t bge_tx_collisions;
#ifdef DEVICE_POLLING
diff --git a/freebsd/sys/dev/dc/dcphy.c b/freebsd/sys/dev/dc/dcphy.c
index fcfa7d6c..b1fe5545 100644
--- a/freebsd/sys/dev/dc/dcphy.c
+++ b/freebsd/sys/dev/dc/dcphy.c
@@ -98,7 +98,7 @@ static device_method_t dcphy_methods[] = {
DEVMETHOD(device_attach, dcphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t dcphy_devclass;
@@ -160,7 +160,7 @@ dcphy_attach(device_t dev)
/*
* Apparently, we can neither isolate nor do loopback.
*/
- sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP | MIIF_NOMANPAUSE;
/*dcphy_reset(sc);*/
dc_sc = mii->mii_ifp->if_softc;
@@ -224,17 +224,12 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
/*dcphy_reset(sc);*/
(void) dcphy_auto(sc);
break;
- case IFM_100_T4:
- /*
- * XXX Not supported as a manual setting right now.
- */
- return (EINVAL);
case IFM_100_TX:
dcphy_reset(sc);
DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
mode |= DC_NETCFG_PORTSEL | DC_NETCFG_PCS |
DC_NETCFG_SCRAMBLER;
- if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
+ if ((ife->ifm_media & IFM_FDX) != 0)
mode |= DC_NETCFG_FULLDUPLEX;
else
mode &= ~DC_NETCFG_FULLDUPLEX;
@@ -243,7 +238,7 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
case IFM_10_T:
DC_CLRBIT(dc_sc, DC_SIARESET, DC_SIA_RESET);
DC_CLRBIT(dc_sc, DC_10BTCTRL, 0xFFFF);
- if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
+ if ((ife->ifm_media & IFM_FDX) != 0)
DC_SETBIT(dc_sc, DC_10BTCTRL, 0x7F3D);
else
DC_SETBIT(dc_sc, DC_10BTCTRL, 0x7F3F);
@@ -251,7 +246,7 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
mode &= ~DC_NETCFG_PORTSEL;
mode |= DC_NETCFG_SPEEDSEL;
- if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
+ if ((ife->ifm_media & IFM_FDX) != 0)
mode |= DC_NETCFG_FULLDUPLEX;
else
mode &= ~DC_NETCFG_FULLDUPLEX;
@@ -310,7 +305,7 @@ static void
dcphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
- int reg, anlpar, tstat = 0;
+ int anlpar, tstat;
struct dc_softc *dc_sc;
dc_sc = mii->mii_ifp->if_softc;
@@ -321,13 +316,12 @@ dcphy_status(struct mii_softc *sc)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return;
- reg = CSR_READ_4(dc_sc, DC_10BTSTAT);
- if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100))
+ tstat = CSR_READ_4(dc_sc, DC_10BTSTAT);
+ if (!(tstat & DC_TSTAT_LS10) || !(tstat & DC_TSTAT_LS100))
mii->mii_media_status |= IFM_ACTIVE;
if (CSR_READ_4(dc_sc, DC_10BTCTRL) & DC_TCTL_AUTONEGENBL) {
/* Erg, still trying, I guess... */
- tstat = CSR_READ_4(dc_sc, DC_10BTSTAT);
if ((tstat & DC_TSTAT_ANEGSTAT) != DC_ASTAT_AUTONEGCMP) {
if ((DC_IS_MACRONIX(dc_sc) || DC_IS_PNICII(dc_sc)) &&
(tstat & DC_TSTAT_ANEGSTAT) == DC_ASTAT_DISABLE)
@@ -367,9 +361,9 @@ dcphy_status(struct mii_softc *sc)
* and hope that the user is clever enough to manually
* change the media settings if we're wrong.
*/
- if (!(reg & DC_TSTAT_LS100))
+ if (!(tstat & DC_TSTAT_LS100))
mii->mii_media_active |= IFM_100_TX | IFM_HDX;
- else if (!(reg & DC_TSTAT_LS10))
+ else if (!(tstat & DC_TSTAT_LS10))
mii->mii_media_active |= IFM_10_T | IFM_HDX;
else
mii->mii_media_active |= IFM_NONE;
diff --git a/freebsd/sys/dev/dc/if_dc.c b/freebsd/sys/dev/dc/if_dc.c
index 9b60bc06..37bc2d42 100644
--- a/freebsd/sys/dev/dc/if_dc.c
+++ b/freebsd/sys/dev/dc/if_dc.c
@@ -46,8 +46,8 @@ __FBSDID("$FreeBSD$");
* ASIX Electronics AX88141 (www.asix.com.tw)
* ADMtek AL981 (www.admtek.com.tw)
* ADMtek AN983 (www.admtek.com.tw)
- * ADMtek cardbus AN985 (www.admtek.com.tw)
- * Netgear FA511 (www.netgear.com) Appears to be rebadged ADMTek cardbus AN985
+ * ADMtek CardBus AN985 (www.admtek.com.tw)
+ * Netgear FA511 (www.netgear.com) Appears to be rebadged ADMTek CardBus AN985
* Davicom DM9100, DM9102, DM9102A (www.davicom8.com)
* Accton EN1217 (www.accton.com)
* Xircom X3201 (www.xircom.com)
@@ -124,12 +124,13 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <dev/mii/mii.h>
+#include <dev/mii/mii_bitbang.h>
#include <dev/mii/miivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#define DC_USEIOSPACE
+#define DC_USEIOSPACE
#include <dev/dc/if_dcreg.h>
@@ -167,7 +168,7 @@ static const struct dc_type dc_devs[] = {
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN983), 0,
"ADMtek AN983 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN985), 0,
- "ADMtek AN985 cardBus 10/100BaseTX or clone" },
+ "ADMtek AN985 CardBus 10/100BaseTX or clone" },
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9511), 0,
"ADMtek ADM9511 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9513), 0,
@@ -226,6 +227,10 @@ static const struct dc_type dc_devs[] = {
"Linksys PCMPC200 CardBus 10/100" },
{ DC_DEVID(DC_VENDORID_LINKSYS, DC_DEVICEID_PCMPC200_AB09), 0,
"Linksys PCMPC200 CardBus 10/100" },
+ { DC_DEVID(DC_VENDORID_ULI, DC_DEVICEID_M5261), 0,
+ "ULi M5261 FastEthernet" },
+ { DC_DEVID(DC_VENDORID_ULI, DC_DEVICEID_M5263), 0,
+ "ULi M5263 FastEthernet" },
{ 0, 0, NULL }
};
@@ -235,7 +240,8 @@ static int dc_detach(device_t);
static int dc_suspend(device_t);
static int dc_resume(device_t);
static const struct dc_type *dc_devtype(device_t);
-static int dc_newbuf(struct dc_softc *, int, int);
+static void dc_discard_rxbuf(struct dc_softc *, int);
+static int dc_newbuf(struct dc_softc *, int);
static int dc_encap(struct dc_softc *, struct mbuf **);
static void dc_pnic_rx_bug_war(struct dc_softc *, int);
static int dc_rx_resync(struct dc_softc *);
@@ -253,34 +259,35 @@ static void dc_stop(struct dc_softc *);
static void dc_watchdog(void *);
static int dc_shutdown(device_t);
static int dc_ifmedia_upd(struct ifnet *);
+static int dc_ifmedia_upd_locked(struct dc_softc *);
static void dc_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int dc_dma_alloc(struct dc_softc *);
+static void dc_dma_free(struct dc_softc *);
+static void dc_dma_map_addr(void *, bus_dma_segment_t *, int, int);
+
static void dc_delay(struct dc_softc *);
static void dc_eeprom_idle(struct dc_softc *);
static void dc_eeprom_putbyte(struct dc_softc *, int);
-static void dc_eeprom_getword(struct dc_softc *, int, u_int16_t *);
-static void dc_eeprom_getword_pnic(struct dc_softc *, int, u_int16_t *);
-static void dc_eeprom_getword_xircom(struct dc_softc *, int, u_int16_t *);
+static void dc_eeprom_getword(struct dc_softc *, int, uint16_t *);
+static void dc_eeprom_getword_pnic(struct dc_softc *, int, uint16_t *);
+static void dc_eeprom_getword_xircom(struct dc_softc *, int, uint16_t *);
static void dc_eeprom_width(struct dc_softc *);
static void dc_read_eeprom(struct dc_softc *, caddr_t, int, int, int);
-static void dc_mii_writebit(struct dc_softc *, int);
-static int dc_mii_readbit(struct dc_softc *);
-static void dc_mii_sync(struct dc_softc *);
-static void dc_mii_send(struct dc_softc *, u_int32_t, int);
-static int dc_mii_readreg(struct dc_softc *, struct dc_mii_frame *);
-static int dc_mii_writereg(struct dc_softc *, struct dc_mii_frame *);
static int dc_miibus_readreg(device_t, int, int);
static int dc_miibus_writereg(device_t, int, int, int);
static void dc_miibus_statchg(device_t);
static void dc_miibus_mediainit(device_t);
static void dc_setcfg(struct dc_softc *, int);
+static void dc_netcfg_wait(struct dc_softc *);
static uint32_t dc_mchash_le(struct dc_softc *, const uint8_t *);
static uint32_t dc_mchash_be(const uint8_t *);
static void dc_setfilt_21143(struct dc_softc *);
static void dc_setfilt_asix(struct dc_softc *);
static void dc_setfilt_admtek(struct dc_softc *);
+static void dc_setfilt_uli(struct dc_softc *);
static void dc_setfilt_xircom(struct dc_softc *);
static void dc_setfilt(struct dc_softc *);
@@ -289,19 +296,38 @@ static void dc_reset(struct dc_softc *);
static int dc_list_rx_init(struct dc_softc *);
static int dc_list_tx_init(struct dc_softc *);
-static void dc_read_srom(struct dc_softc *, int);
-static void dc_parse_21143_srom(struct dc_softc *);
-static void dc_decode_leaf_sia(struct dc_softc *, struct dc_eblock_sia *);
-static void dc_decode_leaf_mii(struct dc_softc *, struct dc_eblock_mii *);
-static void dc_decode_leaf_sym(struct dc_softc *, struct dc_eblock_sym *);
+static int dc_read_srom(struct dc_softc *, int);
+static int dc_parse_21143_srom(struct dc_softc *);
+static int dc_decode_leaf_sia(struct dc_softc *, struct dc_eblock_sia *);
+static int dc_decode_leaf_mii(struct dc_softc *, struct dc_eblock_mii *);
+static int dc_decode_leaf_sym(struct dc_softc *, struct dc_eblock_sym *);
static void dc_apply_fixup(struct dc_softc *, int);
+static int dc_check_multiport(struct dc_softc *);
+
+/*
+ * MII bit-bang glue
+ */
+static uint32_t dc_mii_bitbang_read(device_t);
+static void dc_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops dc_mii_bitbang_ops = {
+ dc_mii_bitbang_read,
+ dc_mii_bitbang_write,
+ {
+ DC_SIO_MII_DATAOUT, /* MII_BIT_MDO */
+ DC_SIO_MII_DATAIN, /* MII_BIT_MDI */
+ DC_SIO_MII_CLK, /* MII_BIT_MDC */
+ 0, /* MII_BIT_DIR_HOST_PHY */
+ DC_SIO_MII_DIR, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
#ifdef DC_USEIOSPACE
-#define DC_RES SYS_RES_IOPORT
-#define DC_RID DC_PCI_CFBIO
+#define DC_RES SYS_RES_IOPORT
+#define DC_RID DC_PCI_CFBIO
#else
-#define DC_RES SYS_RES_MEMORY
-#define DC_RID DC_PCI_CFBMA
+#define DC_RES SYS_RES_MEMORY
+#define DC_RID DC_PCI_CFBMA
#endif
static device_method_t dc_methods[] = {
@@ -313,17 +339,13 @@ static device_method_t dc_methods[] = {
DEVMETHOD(device_resume, dc_resume),
DEVMETHOD(device_shutdown, dc_shutdown),
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
-
/* MII interface */
DEVMETHOD(miibus_readreg, dc_miibus_readreg),
DEVMETHOD(miibus_writereg, dc_miibus_writereg),
DEVMETHOD(miibus_statchg, dc_miibus_statchg),
DEVMETHOD(miibus_mediainit, dc_miibus_mediainit),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t dc_driver = {
@@ -334,17 +356,18 @@ static driver_t dc_driver = {
static devclass_t dc_devclass;
-DRIVER_MODULE(dc, pci, dc_driver, dc_devclass, 0, 0);
-DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
+DRIVER_MODULE_ORDERED(dc, pci, dc_driver, dc_devclass, NULL, NULL,
+ SI_ORDER_ANY);
+DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, NULL, NULL);
-#define DC_SETBIT(sc, reg, x) \
+#define DC_SETBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | (x))
-#define DC_CLRBIT(sc, reg, x) \
+#define DC_CLRBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~(x))
-#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
-#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
+#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
+#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
static void
dc_delay(struct dc_softc *sc)
@@ -491,10 +514,10 @@ dc_eeprom_putbyte(struct dc_softc *sc, int addr)
* the EEPROM.
*/
static void
-dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, u_int16_t *dest)
+dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, uint16_t *dest)
{
int i;
- u_int32_t r;
+ uint32_t r;
CSR_WRITE_4(sc, DC_PN_SIOCTL, DC_PN_EEOPCODE_READ | addr);
@@ -502,7 +525,7 @@ dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, u_int16_t *dest)
DELAY(1);
r = CSR_READ_4(sc, DC_SIO);
if (!(r & DC_PN_SIOCTL_BUSY)) {
- *dest = (u_int16_t)(r & 0xFFFF);
+ *dest = (uint16_t)(r & 0xFFFF);
return;
}
}
@@ -514,17 +537,17 @@ dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, u_int16_t *dest)
* the EEPROM, too.
*/
static void
-dc_eeprom_getword_xircom(struct dc_softc *sc, int addr, u_int16_t *dest)
+dc_eeprom_getword_xircom(struct dc_softc *sc, int addr, uint16_t *dest)
{
SIO_SET(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ);
addr *= 2;
CSR_WRITE_4(sc, DC_ROM, addr | 0x160);
- *dest = (u_int16_t)CSR_READ_4(sc, DC_SIO) & 0xff;
+ *dest = (uint16_t)CSR_READ_4(sc, DC_SIO) & 0xff;
addr += 1;
CSR_WRITE_4(sc, DC_ROM, addr | 0x160);
- *dest |= ((u_int16_t)CSR_READ_4(sc, DC_SIO) & 0xff) << 8;
+ *dest |= ((uint16_t)CSR_READ_4(sc, DC_SIO) & 0xff) << 8;
SIO_CLR(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ);
}
@@ -533,10 +556,10 @@ dc_eeprom_getword_xircom(struct dc_softc *sc, int addr, u_int16_t *dest)
* Read a word of data stored in the EEPROM at address 'addr.'
*/
static void
-dc_eeprom_getword(struct dc_softc *sc, int addr, u_int16_t *dest)
+dc_eeprom_getword(struct dc_softc *sc, int addr, uint16_t *dest)
{
int i;
- u_int16_t word = 0;
+ uint16_t word = 0;
/* Force EEPROM to idle state. */
dc_eeprom_idle(sc);
@@ -582,7 +605,7 @@ static void
dc_read_eeprom(struct dc_softc *sc, caddr_t dest, int off, int cnt, int be)
{
int i;
- u_int16_t word = 0, *ptr;
+ uint16_t word = 0, *ptr;
for (i = 0; i < cnt; i++) {
if (DC_IS_PNIC(sc))
@@ -591,7 +614,7 @@ dc_read_eeprom(struct dc_softc *sc, caddr_t dest, int off, int cnt, int be)
dc_eeprom_getword_xircom(sc, off + i, &word);
else
dc_eeprom_getword(sc, off + i, &word);
- ptr = (u_int16_t *)(dest + (i * 2));
+ ptr = (uint16_t *)(dest + (i * 2));
if (be)
*ptr = be16toh(word);
else
@@ -600,185 +623,45 @@ dc_read_eeprom(struct dc_softc *sc, caddr_t dest, int off, int cnt, int be)
}
/*
- * The following two routines are taken from the Macronix 98713
- * Application Notes pp.19-21.
- */
-/*
- * Write a bit to the MII bus.
+ * Write the MII serial port for the MII bit-bang module.
*/
static void
-dc_mii_writebit(struct dc_softc *sc, int bit)
+dc_mii_bitbang_write(device_t dev, uint32_t val)
{
- uint32_t reg;
+ struct dc_softc *sc;
- reg = DC_SIO_ROMCTL_WRITE | (bit != 0 ? DC_SIO_MII_DATAOUT : 0);
- CSR_WRITE_4(sc, DC_SIO, reg);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
+ sc = device_get_softc(dev);
- CSR_WRITE_4(sc, DC_SIO, reg | DC_SIO_MII_CLK);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- CSR_WRITE_4(sc, DC_SIO, reg);
+ CSR_WRITE_4(sc, DC_SIO, val);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
}
/*
- * Read a bit from the MII bus.
+ * Read the MII serial port for the MII bit-bang module.
*/
-static int
-dc_mii_readbit(struct dc_softc *sc)
+static uint32_t
+dc_mii_bitbang_read(device_t dev)
{
- uint32_t reg;
-
- reg = DC_SIO_ROMCTL_READ | DC_SIO_MII_DIR;
- CSR_WRITE_4(sc, DC_SIO, reg);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- (void)CSR_READ_4(sc, DC_SIO);
- CSR_WRITE_4(sc, DC_SIO, reg | DC_SIO_MII_CLK);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- CSR_WRITE_4(sc, DC_SIO, reg);
- CSR_BARRIER_4(sc, DC_SIO,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
- if (CSR_READ_4(sc, DC_SIO) & DC_SIO_MII_DATAIN)
- return (1);
-
- return (0);
-}
+ struct dc_softc *sc;
+ uint32_t val;
-/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
- */
-static void
-dc_mii_sync(struct dc_softc *sc)
-{
- int i;
+ sc = device_get_softc(dev);
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
+ val = CSR_READ_4(sc, DC_SIO);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- DELAY(1);
-
- for (i = 0; i < 32; i++)
- dc_mii_writebit(sc, 1);
-}
-
-/*
- * Clock a series of bits through the MII.
- */
-static void
-dc_mii_send(struct dc_softc *sc, u_int32_t bits, int cnt)
-{
- int i;
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1)
- dc_mii_writebit(sc, bits & i);
-}
-
-/*
- * Read an PHY register through the MII.
- */
-static int
-dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
-{
- int i;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = DC_MII_STARTDELIM;
- frame->mii_opcode = DC_MII_READOP;
-
- /*
- * Sync the PHYs.
- */
- dc_mii_sync(sc);
-
- /*
- * Send command/address info.
- */
- dc_mii_send(sc, frame->mii_stdelim, 2);
- dc_mii_send(sc, frame->mii_opcode, 2);
- dc_mii_send(sc, frame->mii_phyaddr, 5);
- dc_mii_send(sc, frame->mii_regaddr, 5);
-
- /*
- * Now try reading data bits. If the turnaround failed, we still
- * need to clock through 16 cycles to keep the PHY(s) in sync.
- */
- frame->mii_turnaround = dc_mii_readbit(sc);
- if (frame->mii_turnaround != 0) {
- for (i = 0; i < 16; i++)
- dc_mii_readbit(sc);
- goto fail;
- }
- for (i = 0x8000; i; i >>= 1) {
- if (dc_mii_readbit(sc))
- frame->mii_data |= i;
- }
-
-fail:
-
- /* Clock the idle bits. */
- dc_mii_writebit(sc, 0);
- dc_mii_writebit(sc, 0);
-
- if (frame->mii_turnaround != 0)
- return (1);
- return (0);
-}
-
-/*
- * Write to a PHY register through the MII.
- */
-static int
-dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
-{
- /*
- * Set up frame for TX.
- */
- frame->mii_stdelim = DC_MII_STARTDELIM;
- frame->mii_opcode = DC_MII_WRITEOP;
- frame->mii_turnaround = DC_MII_TURNAROUND;
-
- /*
- * Sync the PHYs.
- */
- dc_mii_sync(sc);
-
- dc_mii_send(sc, frame->mii_stdelim, 2);
- dc_mii_send(sc, frame->mii_opcode, 2);
- dc_mii_send(sc, frame->mii_phyaddr, 5);
- dc_mii_send(sc, frame->mii_regaddr, 5);
- dc_mii_send(sc, frame->mii_turnaround, 2);
- dc_mii_send(sc, frame->mii_data, 16);
-
- /* Clock the idle bits. */
- dc_mii_writebit(sc, 0);
- dc_mii_writebit(sc, 0);
-
- return (0);
+ return (val);
}
static int
dc_miibus_readreg(device_t dev, int phy, int reg)
{
- struct dc_mii_frame frame;
- struct dc_softc *sc;
+ struct dc_softc *sc;
int i, rval, phy_reg = 0;
sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
if (sc->dc_pmode != DC_PMODE_MII) {
if (phy == (MII_NPHY - 1)) {
@@ -822,6 +705,23 @@ dc_miibus_readreg(device_t dev, int phy, int reg)
return (0);
}
+ if (sc->dc_type == DC_TYPE_ULI_M5263) {
+ CSR_WRITE_4(sc, DC_ROM,
+ ((phy << DC_ULI_PHY_ADDR_SHIFT) & DC_ULI_PHY_ADDR_MASK) |
+ ((reg << DC_ULI_PHY_REG_SHIFT) & DC_ULI_PHY_REG_MASK) |
+ DC_ULI_PHY_OP_READ);
+ for (i = 0; i < DC_TIMEOUT; i++) {
+ DELAY(1);
+ rval = CSR_READ_4(sc, DC_ROM);
+ if ((rval & DC_ULI_PHY_OP_DONE) != 0) {
+ return (rval & DC_ULI_PHY_DATA_MASK);
+ }
+ }
+ if (i == DC_TIMEOUT)
+ device_printf(dev, "phy read timed out\n");
+ return (0);
+ }
+
if (DC_IS_COMET(sc)) {
switch (reg) {
case MII_BMCR:
@@ -853,34 +753,29 @@ dc_miibus_readreg(device_t dev, int phy, int reg)
}
rval = CSR_READ_4(sc, phy_reg) & 0x0000FFFF;
-
if (rval == 0xFFFF)
return (0);
return (rval);
}
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
if (sc->dc_type == DC_TYPE_98713) {
phy_reg = CSR_READ_4(sc, DC_NETCFG);
CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL);
}
- dc_mii_readreg(sc, &frame);
+ rval = mii_bitbang_readreg(dev, &dc_mii_bitbang_ops, phy, reg);
if (sc->dc_type == DC_TYPE_98713)
CSR_WRITE_4(sc, DC_NETCFG, phy_reg);
- return (frame.mii_data);
+ return (rval);
}
static int
dc_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct dc_softc *sc;
- struct dc_mii_frame frame;
int i, phy_reg = 0;
sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
if (DC_IS_PNIC(sc)) {
CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_WRITE |
@@ -892,6 +787,16 @@ dc_miibus_writereg(device_t dev, int phy, int reg, int data)
return (0);
}
+ if (sc->dc_type == DC_TYPE_ULI_M5263) {
+ CSR_WRITE_4(sc, DC_ROM,
+ ((phy << DC_ULI_PHY_ADDR_SHIFT) & DC_ULI_PHY_ADDR_MASK) |
+ ((reg << DC_ULI_PHY_REG_SHIFT) & DC_ULI_PHY_REG_MASK) |
+ ((data << DC_ULI_PHY_DATA_SHIFT) & DC_ULI_PHY_DATA_MASK) |
+ DC_ULI_PHY_OP_WRITE);
+ DELAY(1);
+ return (0);
+ }
+
if (DC_IS_COMET(sc)) {
switch (reg) {
case MII_BMCR:
@@ -926,15 +831,11 @@ dc_miibus_writereg(device_t dev, int phy, int reg, int data)
return (0);
}
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
-
if (sc->dc_type == DC_TYPE_98713) {
phy_reg = CSR_READ_4(sc, DC_NETCFG);
CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL);
}
- dc_mii_writereg(sc, &frame);
+ mii_bitbang_writereg(dev, &dc_mii_bitbang_ops, phy, reg, data);
if (sc->dc_type == DC_TYPE_98713)
CSR_WRITE_4(sc, DC_NETCFG, phy_reg);
@@ -945,22 +846,34 @@ static void
dc_miibus_statchg(device_t dev)
{
struct dc_softc *sc;
+ struct ifnet *ifp;
struct mii_data *mii;
struct ifmedia *ifm;
sc = device_get_softc(dev);
- if (DC_IS_ADMTEK(sc))
- return;
mii = device_get_softc(sc->dc_miibus);
+ ifp = sc->dc_ifp;
+ if (mii == NULL || ifp == NULL ||
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
ifm = &mii->mii_media;
- if (DC_IS_DAVICOM(sc) &&
- IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) {
+ if (DC_IS_DAVICOM(sc) && IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) {
dc_setcfg(sc, ifm->ifm_media);
- sc->dc_if_media = ifm->ifm_media;
- } else {
+ return;
+ } else if (!DC_IS_ADMTEK(sc))
dc_setcfg(sc, mii->mii_media_active);
- sc->dc_if_media = mii->mii_media_active;
+
+ sc->dc_link = 0;
+ if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
+ (IFM_ACTIVE | IFM_AVALID)) {
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_10_T:
+ case IFM_100_TX:
+ sc->dc_link = 1;
+ break;
+ }
}
}
@@ -990,9 +903,9 @@ dc_miibus_mediainit(device_t dev)
ifmedia_add(ifm, IFM_ETHER | IFM_HPNA_1, 0, NULL);
}
-#define DC_BITS_512 9
-#define DC_BITS_128 7
-#define DC_BITS_64 6
+#define DC_BITS_512 9
+#define DC_BITS_128 7
+#define DC_BITS_64 6
static uint32_t
dc_mchash_le(struct dc_softc *sc, const uint8_t *addr)
@@ -1056,7 +969,7 @@ dc_setfilt_21143(struct dc_softc *sc)
{
uint16_t eaddr[(ETHER_ADDR_LEN+1)/2];
struct dc_desc *sframe;
- u_int32_t h, *sp;
+ uint32_t h, *sp;
struct ifmultiaddr *ifma;
struct ifnet *ifp;
int i;
@@ -1066,11 +979,11 @@ dc_setfilt_21143(struct dc_softc *sc)
i = sc->dc_cdata.dc_tx_prod;
DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT);
sc->dc_cdata.dc_tx_cnt++;
- sframe = &sc->dc_ldata->dc_tx_list[i];
+ sframe = &sc->dc_ldata.dc_tx_list[i];
sp = sc->dc_cdata.dc_sbuf;
bzero(sp, DC_SFRAME_LEN);
- sframe->dc_data = htole32(sc->dc_saddr);
+ sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr));
sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |
DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT);
@@ -1109,6 +1022,9 @@ dc_setfilt_21143(struct dc_softc *sc)
sp[41] = DC_SP_MAC(eaddr[2]);
sframe->dc_status = htole32(DC_TXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap, BUS_DMASYNC_PREWRITE);
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
/*
@@ -1129,7 +1045,7 @@ dc_setfilt_admtek(struct dc_softc *sc)
struct ifnet *ifp;
struct ifmultiaddr *ifma;
int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
+ uint32_t hashes[2] = { 0, 0 };
ifp = sc->dc_ifp;
@@ -1190,7 +1106,7 @@ dc_setfilt_asix(struct dc_softc *sc)
struct ifnet *ifp;
struct ifmultiaddr *ifma;
int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
+ uint32_t hashes[2] = { 0, 0 };
ifp = sc->dc_ifp;
@@ -1254,13 +1170,104 @@ dc_setfilt_asix(struct dc_softc *sc)
}
static void
+dc_setfilt_uli(struct dc_softc *sc)
+{
+ uint8_t eaddr[ETHER_ADDR_LEN];
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ struct dc_desc *sframe;
+ uint32_t filter, *sp;
+ uint8_t *ma;
+ int i, mcnt;
+
+ ifp = sc->dc_ifp;
+
+ i = sc->dc_cdata.dc_tx_prod;
+ DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT);
+ sc->dc_cdata.dc_tx_cnt++;
+ sframe = &sc->dc_ldata.dc_tx_list[i];
+ sp = sc->dc_cdata.dc_sbuf;
+ bzero(sp, DC_SFRAME_LEN);
+
+ sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr));
+ sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |
+ DC_TXCTL_TLINK | DC_FILTER_PERFECT | DC_TXCTL_FINT);
+
+ sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf;
+
+ /* Set station address. */
+ bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN);
+ *sp++ = DC_SP_MAC(eaddr[1] << 8 | eaddr[0]);
+ *sp++ = DC_SP_MAC(eaddr[3] << 8 | eaddr[2]);
+ *sp++ = DC_SP_MAC(eaddr[5] << 8 | eaddr[4]);
+
+ /* Set broadcast address. */
+ *sp++ = DC_SP_MAC(0xFFFF);
+ *sp++ = DC_SP_MAC(0xFFFF);
+ *sp++ = DC_SP_MAC(0xFFFF);
+
+ /* Extract current filter configuration. */
+ filter = CSR_READ_4(sc, DC_NETCFG);
+ filter &= ~(DC_NETCFG_RX_PROMISC | DC_NETCFG_RX_ALLMULTI);
+
+ /* Now build perfect filters. */
+ mcnt = 0;
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ if (mcnt >= DC_ULI_FILTER_NPERF) {
+ filter |= DC_NETCFG_RX_ALLMULTI;
+ break;
+ }
+ ma = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
+ *sp++ = DC_SP_MAC(ma[1] << 8 | ma[0]);
+ *sp++ = DC_SP_MAC(ma[3] << 8 | ma[2]);
+ *sp++ = DC_SP_MAC(ma[5] << 8 | ma[4]);
+ mcnt++;
+ }
+ if_maddr_runlock(ifp);
+
+ for (; mcnt < DC_ULI_FILTER_NPERF; mcnt++) {
+ *sp++ = DC_SP_MAC(0xFFFF);
+ *sp++ = DC_SP_MAC(0xFFFF);
+ *sp++ = DC_SP_MAC(0xFFFF);
+ }
+
+ if (filter & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON))
+ CSR_WRITE_4(sc, DC_NETCFG,
+ filter & ~(DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
+ if (ifp->if_flags & IFF_PROMISC)
+ filter |= DC_NETCFG_RX_PROMISC | DC_NETCFG_RX_ALLMULTI;
+ if (ifp->if_flags & IFF_ALLMULTI)
+ filter |= DC_NETCFG_RX_ALLMULTI;
+ CSR_WRITE_4(sc, DC_NETCFG,
+ filter & ~(DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
+ if (filter & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON))
+ CSR_WRITE_4(sc, DC_NETCFG, filter);
+
+ sframe->dc_status = htole32(DC_TXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap, BUS_DMASYNC_PREWRITE);
+ CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
+
+ /*
+ * Wait some time...
+ */
+ DELAY(1000);
+
+ sc->dc_wdog_timer = 5;
+}
+
+static void
dc_setfilt_xircom(struct dc_softc *sc)
{
uint16_t eaddr[(ETHER_ADDR_LEN+1)/2];
struct ifnet *ifp;
struct ifmultiaddr *ifma;
struct dc_desc *sframe;
- u_int32_t h, *sp;
+ uint32_t h, *sp;
int i;
ifp = sc->dc_ifp;
@@ -1269,11 +1276,11 @@ dc_setfilt_xircom(struct dc_softc *sc)
i = sc->dc_cdata.dc_tx_prod;
DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT);
sc->dc_cdata.dc_tx_cnt++;
- sframe = &sc->dc_ldata->dc_tx_list[i];
+ sframe = &sc->dc_ldata.dc_tx_list[i];
sp = sc->dc_cdata.dc_sbuf;
bzero(sp, DC_SFRAME_LEN);
- sframe->dc_data = htole32(sc->dc_saddr);
+ sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr));
sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |
DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT);
@@ -1313,8 +1320,10 @@ dc_setfilt_xircom(struct dc_softc *sc)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
sframe->dc_status = htole32(DC_TXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap, BUS_DMASYNC_PREWRITE);
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
/*
@@ -1339,10 +1348,39 @@ dc_setfilt(struct dc_softc *sc)
if (DC_IS_ADMTEK(sc))
dc_setfilt_admtek(sc);
+ if (DC_IS_ULI(sc))
+ dc_setfilt_uli(sc);
+
if (DC_IS_XIRCOM(sc))
dc_setfilt_xircom(sc);
}
+static void
+dc_netcfg_wait(struct dc_softc *sc)
+{
+ uint32_t isr;
+ int i;
+
+ for (i = 0; i < DC_TIMEOUT; i++) {
+ isr = CSR_READ_4(sc, DC_ISR);
+ if (isr & DC_ISR_TX_IDLE &&
+ ((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
+ (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT))
+ break;
+ DELAY(10);
+ }
+ if (i == DC_TIMEOUT) {
+ if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc))
+ device_printf(sc->dc_dev,
+ "%s: failed to force tx to idle state\n", __func__);
+ if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
+ (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
+ !DC_HAS_BROKEN_RXSTATE(sc))
+ device_printf(sc->dc_dev,
+ "%s: failed to force rx to idle state\n", __func__);
+ }
+}
+
/*
* In order to fiddle with the 'full-duplex' and '100Mbps' bits in
* the netconfig register, we first have to put the transmit and/or
@@ -1351,8 +1389,7 @@ dc_setfilt(struct dc_softc *sc)
static void
dc_setcfg(struct dc_softc *sc, int media)
{
- int i, restart = 0, watchdogreg;
- u_int32_t isr;
+ int restart = 0, watchdogreg;
if (IFM_SUBTYPE(media) == IFM_NONE)
return;
@@ -1360,28 +1397,7 @@ dc_setcfg(struct dc_softc *sc, int media)
if (CSR_READ_4(sc, DC_NETCFG) & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) {
restart = 1;
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
-
- for (i = 0; i < DC_TIMEOUT; i++) {
- isr = CSR_READ_4(sc, DC_ISR);
- if (isr & DC_ISR_TX_IDLE &&
- ((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
- (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT))
- break;
- DELAY(10);
- }
-
- if (i == DC_TIMEOUT) {
- if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc))
- device_printf(sc->dc_dev,
- "%s: failed to force tx to idle state\n",
- __func__);
- if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
- (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
- !DC_HAS_BROKEN_RXSTATE(sc))
- device_printf(sc->dc_dev,
- "%s: failed to force rx to idle state\n",
- __func__);
- }
+ dc_netcfg_wait(sc);
}
if (IFM_SUBTYPE(media) == IFM_100_TX) {
@@ -1405,8 +1421,6 @@ dc_setcfg(struct dc_softc *sc, int media)
if (!DC_IS_DAVICOM(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
- if (DC_IS_INTEL(sc))
- dc_apply_fixup(sc, IFM_AUTO);
} else {
if (DC_IS_PNIC(sc)) {
DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_SPEEDSEL);
@@ -1416,10 +1430,6 @@ dc_setcfg(struct dc_softc *sc, int media)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER);
- if (DC_IS_INTEL(sc))
- dc_apply_fixup(sc,
- (media & IFM_GMASK) == IFM_FDX ?
- IFM_100_TX | IFM_FDX : IFM_100_TX);
}
}
@@ -1443,8 +1453,6 @@ dc_setcfg(struct dc_softc *sc, int media)
if (!DC_IS_DAVICOM(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
- if (DC_IS_INTEL(sc))
- dc_apply_fixup(sc, IFM_AUTO);
} else {
if (DC_IS_PNIC(sc)) {
DC_PN_GPIO_CLRBIT(sc, DC_PN_GPIO_SPEEDSEL);
@@ -1464,9 +1472,6 @@ dc_setcfg(struct dc_softc *sc, int media)
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
DC_CLRBIT(sc, DC_10BTCTRL,
DC_TCTL_AUTONEGENBL);
- dc_apply_fixup(sc,
- (media & IFM_GMASK) == IFM_FDX ?
- IFM_10_T | IFM_FDX : IFM_10_T);
DELAY(20000);
}
}
@@ -1514,7 +1519,7 @@ dc_reset(struct dc_softc *sc)
}
if (DC_IS_ASIX(sc) || DC_IS_ADMTEK(sc) || DC_IS_CONEXANT(sc) ||
- DC_IS_XIRCOM(sc) || DC_IS_INTEL(sc)) {
+ DC_IS_XIRCOM(sc) || DC_IS_INTEL(sc) || DC_IS_ULI(sc)) {
DELAY(10000);
DC_CLRBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET);
i = 0;
@@ -1538,7 +1543,7 @@ dc_reset(struct dc_softc *sc)
*/
if (DC_IS_INTEL(sc)) {
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
- CSR_WRITE_4(sc, DC_10BTCTRL, 0);
+ CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFFFFFF);
CSR_WRITE_4(sc, DC_WATCHDOG, 0);
}
}
@@ -1547,8 +1552,8 @@ static const struct dc_type *
dc_devtype(device_t dev)
{
const struct dc_type *t;
- u_int32_t devid;
- u_int8_t rev;
+ uint32_t devid;
+ uint8_t rev;
t = dc_devs;
devid = pci_get_devid(dev);
@@ -1591,9 +1596,9 @@ static void
dc_apply_fixup(struct dc_softc *sc, int media)
{
struct dc_mediainfo *m;
- u_int8_t *p;
+ uint8_t *p;
int i;
- u_int32_t reg;
+ uint32_t reg;
m = sc->dc_mi;
@@ -1617,12 +1622,16 @@ dc_apply_fixup(struct dc_softc *sc, int media)
}
}
-static void
+static int
dc_decode_leaf_sia(struct dc_softc *sc, struct dc_eblock_sia *l)
{
struct dc_mediainfo *m;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (m == NULL) {
+ device_printf(sc->dc_dev, "Could not allocate mediainfo\n");
+ return (ENOMEM);
+ }
switch (l->dc_sia_code & ~DC_SIA_CODE_EXT) {
case DC_SIA_CODE_10BT:
m->dc_media = IFM_10_T;
@@ -1648,25 +1657,30 @@ dc_decode_leaf_sia(struct dc_softc *sc, struct dc_eblock_sia *l)
if (l->dc_sia_code & DC_SIA_CODE_EXT) {
m->dc_gp_len = 2;
m->dc_gp_ptr =
- (u_int8_t *)&l->dc_un.dc_sia_ext.dc_sia_gpio_ctl;
+ (uint8_t *)&l->dc_un.dc_sia_ext.dc_sia_gpio_ctl;
} else {
m->dc_gp_len = 2;
m->dc_gp_ptr =
- (u_int8_t *)&l->dc_un.dc_sia_noext.dc_sia_gpio_ctl;
+ (uint8_t *)&l->dc_un.dc_sia_noext.dc_sia_gpio_ctl;
}
m->dc_next = sc->dc_mi;
sc->dc_mi = m;
sc->dc_pmode = DC_PMODE_SIA;
+ return (0);
}
-static void
+static int
dc_decode_leaf_sym(struct dc_softc *sc, struct dc_eblock_sym *l)
{
struct dc_mediainfo *m;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (m == NULL) {
+ device_printf(sc->dc_dev, "Could not allocate mediainfo\n");
+ return (ENOMEM);
+ }
if (l->dc_sym_code == DC_SYM_CODE_100BT)
m->dc_media = IFM_100_TX;
@@ -1674,26 +1688,31 @@ dc_decode_leaf_sym(struct dc_softc *sc, struct dc_eblock_sym *l)
m->dc_media = IFM_100_TX | IFM_FDX;
m->dc_gp_len = 2;
- m->dc_gp_ptr = (u_int8_t *)&l->dc_sym_gpio_ctl;
+ m->dc_gp_ptr = (uint8_t *)&l->dc_sym_gpio_ctl;
m->dc_next = sc->dc_mi;
sc->dc_mi = m;
sc->dc_pmode = DC_PMODE_SYM;
+ return (0);
}
-static void
+static int
dc_decode_leaf_mii(struct dc_softc *sc, struct dc_eblock_mii *l)
{
struct dc_mediainfo *m;
- u_int8_t *p;
+ uint8_t *p;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (m == NULL) {
+ device_printf(sc->dc_dev, "Could not allocate mediainfo\n");
+ return (ENOMEM);
+ }
/* We abuse IFM_AUTO to represent MII. */
m->dc_media = IFM_AUTO;
m->dc_gp_len = l->dc_gpr_len;
- p = (u_int8_t *)l;
+ p = (uint8_t *)l;
p += sizeof(struct dc_eblock_mii);
m->dc_gp_ptr = p;
p += 2 * l->dc_gpr_len;
@@ -1703,24 +1722,30 @@ dc_decode_leaf_mii(struct dc_softc *sc, struct dc_eblock_mii *l)
m->dc_next = sc->dc_mi;
sc->dc_mi = m;
+ return (0);
}
-static void
+static int
dc_read_srom(struct dc_softc *sc, int bits)
{
int size;
- size = 2 << bits;
- sc->dc_srom = malloc(size, M_DEVBUF, M_NOWAIT);
+ size = DC_ROM_SIZE(bits);
+ sc->dc_srom = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (sc->dc_srom == NULL) {
+ device_printf(sc->dc_dev, "Could not allocate SROM buffer\n");
+ return (ENOMEM);
+ }
dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (size / 2), 0);
+ return (0);
}
-static void
+static int
dc_parse_21143_srom(struct dc_softc *sc)
{
struct dc_leaf_hdr *lhdr;
struct dc_eblock_hdr *hdr;
- int have_mii, i, loff;
+ int error, have_mii, i, loff;
char *ptr;
have_mii = 0;
@@ -1747,20 +1772,21 @@ dc_parse_21143_srom(struct dc_softc *sc)
*/
ptr = (char *)lhdr;
ptr += sizeof(struct dc_leaf_hdr) - 1;
+ error = 0;
for (i = 0; i < lhdr->dc_mcnt; i++) {
hdr = (struct dc_eblock_hdr *)ptr;
switch (hdr->dc_type) {
case DC_EBLOCK_MII:
- dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr);
+ error = dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr);
break;
case DC_EBLOCK_SIA:
if (! have_mii)
- dc_decode_leaf_sia(sc,
+ error = dc_decode_leaf_sia(sc,
(struct dc_eblock_sia *)hdr);
break;
case DC_EBLOCK_SYM:
if (! have_mii)
- dc_decode_leaf_sym(sc,
+ error = dc_decode_leaf_sym(sc,
(struct dc_eblock_sym *)hdr);
break;
default:
@@ -1770,12 +1796,13 @@ dc_parse_21143_srom(struct dc_softc *sc)
ptr += (hdr->dc_len & 0x7F);
ptr++;
}
+ return (error);
}
static void
dc_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- u_int32_t *paddr;
+ bus_addr_t *paddr;
KASSERT(nseg == 1,
("%s: wrong number of segments (%d)", __func__, nseg));
@@ -1783,6 +1810,208 @@ dc_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
*paddr = segs->ds_addr;
}
+static int
+dc_dma_alloc(struct dc_softc *sc)
+{
+ int error, i;
+
+ error = bus_dma_tag_create(bus_get_dma_tag(sc->dc_dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0,
+ NULL, NULL, &sc->dc_ptag);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to allocate parent DMA tag\n");
+ goto fail;
+ }
+
+ /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
+ error = bus_dma_tag_create(sc->dc_ptag, DC_LIST_ALIGN, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, DC_RX_LIST_SZ, 1,
+ DC_RX_LIST_SZ, 0, NULL, NULL, &sc->dc_rx_ltag);
+ if (error) {
+ device_printf(sc->dc_dev, "failed to create RX list DMA tag\n");
+ goto fail;
+ }
+
+ error = bus_dma_tag_create(sc->dc_ptag, DC_LIST_ALIGN, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, DC_TX_LIST_SZ, 1,
+ DC_TX_LIST_SZ, 0, NULL, NULL, &sc->dc_tx_ltag);
+ if (error) {
+ device_printf(sc->dc_dev, "failed to create TX list DMA tag\n");
+ goto fail;
+ }
+
+ /* RX descriptor list. */
+ error = bus_dmamem_alloc(sc->dc_rx_ltag,
+ (void **)&sc->dc_ldata.dc_rx_list, BUS_DMA_NOWAIT |
+ BUS_DMA_ZERO | BUS_DMA_COHERENT, &sc->dc_rx_lmap);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to allocate DMA'able memory for RX list\n");
+ goto fail;
+ }
+ error = bus_dmamap_load(sc->dc_rx_ltag, sc->dc_rx_lmap,
+ sc->dc_ldata.dc_rx_list, DC_RX_LIST_SZ, dc_dma_map_addr,
+ &sc->dc_ldata.dc_rx_list_paddr, BUS_DMA_NOWAIT);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to load DMA'able memory for RX list\n");
+ goto fail;
+ }
+ /* TX descriptor list. */
+ error = bus_dmamem_alloc(sc->dc_tx_ltag,
+ (void **)&sc->dc_ldata.dc_tx_list, BUS_DMA_NOWAIT |
+ BUS_DMA_ZERO | BUS_DMA_COHERENT, &sc->dc_tx_lmap);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to allocate DMA'able memory for TX list\n");
+ goto fail;
+ }
+ error = bus_dmamap_load(sc->dc_tx_ltag, sc->dc_tx_lmap,
+ sc->dc_ldata.dc_tx_list, DC_TX_LIST_SZ, dc_dma_map_addr,
+ &sc->dc_ldata.dc_tx_list_paddr, BUS_DMA_NOWAIT);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "cannot load DMA'able memory for TX list\n");
+ goto fail;
+ }
+
+ /*
+ * Allocate a busdma tag and DMA safe memory for the multicast
+ * setup frame.
+ */
+ error = bus_dma_tag_create(sc->dc_ptag, DC_LIST_ALIGN, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ DC_SFRAME_LEN + DC_MIN_FRAMELEN, 1, DC_SFRAME_LEN + DC_MIN_FRAMELEN,
+ 0, NULL, NULL, &sc->dc_stag);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to create DMA tag for setup frame\n");
+ goto fail;
+ }
+ error = bus_dmamem_alloc(sc->dc_stag, (void **)&sc->dc_cdata.dc_sbuf,
+ BUS_DMA_NOWAIT, &sc->dc_smap);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to allocate DMA'able memory for setup frame\n");
+ goto fail;
+ }
+ error = bus_dmamap_load(sc->dc_stag, sc->dc_smap, sc->dc_cdata.dc_sbuf,
+ DC_SFRAME_LEN, dc_dma_map_addr, &sc->dc_saddr, BUS_DMA_NOWAIT);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "cannot load DMA'able memory for setup frame\n");
+ goto fail;
+ }
+
+ /* Allocate a busdma tag for RX mbufs. */
+ error = bus_dma_tag_create(sc->dc_ptag, DC_RXBUF_ALIGN, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ MCLBYTES, 1, MCLBYTES, 0, NULL, NULL, &sc->dc_rx_mtag);
+ if (error) {
+ device_printf(sc->dc_dev, "failed to create RX mbuf tag\n");
+ goto fail;
+ }
+
+ /* Allocate a busdma tag for TX mbufs. */
+ error = bus_dma_tag_create(sc->dc_ptag, 1, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ MCLBYTES * DC_MAXFRAGS, DC_MAXFRAGS, MCLBYTES,
+ 0, NULL, NULL, &sc->dc_tx_mtag);
+ if (error) {
+ device_printf(sc->dc_dev, "failed to create TX mbuf tag\n");
+ goto fail;
+ }
+
+ /* Create the TX/RX busdma maps. */
+ for (i = 0; i < DC_TX_LIST_CNT; i++) {
+ error = bus_dmamap_create(sc->dc_tx_mtag, 0,
+ &sc->dc_cdata.dc_tx_map[i]);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to create TX mbuf dmamap\n");
+ goto fail;
+ }
+ }
+ for (i = 0; i < DC_RX_LIST_CNT; i++) {
+ error = bus_dmamap_create(sc->dc_rx_mtag, 0,
+ &sc->dc_cdata.dc_rx_map[i]);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to create RX mbuf dmamap\n");
+ goto fail;
+ }
+ }
+ error = bus_dmamap_create(sc->dc_rx_mtag, 0, &sc->dc_sparemap);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to create spare RX mbuf dmamap\n");
+ goto fail;
+ }
+
+fail:
+ return (error);
+}
+
+static void
+dc_dma_free(struct dc_softc *sc)
+{
+ int i;
+
+ /* RX buffers. */
+ if (sc->dc_rx_mtag != NULL) {
+ for (i = 0; i < DC_RX_LIST_CNT; i++) {
+ if (sc->dc_cdata.dc_rx_map[i] != NULL)
+ bus_dmamap_destroy(sc->dc_rx_mtag,
+ sc->dc_cdata.dc_rx_map[i]);
+ }
+ if (sc->dc_sparemap != NULL)
+ bus_dmamap_destroy(sc->dc_rx_mtag, sc->dc_sparemap);
+ bus_dma_tag_destroy(sc->dc_rx_mtag);
+ }
+
+ /* TX buffers. */
+ if (sc->dc_rx_mtag != NULL) {
+ for (i = 0; i < DC_TX_LIST_CNT; i++) {
+ if (sc->dc_cdata.dc_tx_map[i] != NULL)
+ bus_dmamap_destroy(sc->dc_tx_mtag,
+ sc->dc_cdata.dc_tx_map[i]);
+ }
+ bus_dma_tag_destroy(sc->dc_tx_mtag);
+ }
+
+ /* RX descriptor list. */
+ if (sc->dc_rx_ltag) {
+ if (sc->dc_rx_lmap != NULL)
+ bus_dmamap_unload(sc->dc_rx_ltag, sc->dc_rx_lmap);
+ if (sc->dc_rx_lmap != NULL && sc->dc_ldata.dc_rx_list != NULL)
+ bus_dmamem_free(sc->dc_rx_ltag, sc->dc_ldata.dc_rx_list,
+ sc->dc_rx_lmap);
+ bus_dma_tag_destroy(sc->dc_rx_ltag);
+ }
+
+ /* TX descriptor list. */
+ if (sc->dc_tx_ltag) {
+ if (sc->dc_tx_lmap != NULL)
+ bus_dmamap_unload(sc->dc_tx_ltag, sc->dc_tx_lmap);
+ if (sc->dc_tx_lmap != NULL && sc->dc_ldata.dc_tx_list != NULL)
+ bus_dmamem_free(sc->dc_tx_ltag, sc->dc_ldata.dc_tx_list,
+ sc->dc_tx_lmap);
+ bus_dma_tag_destroy(sc->dc_tx_ltag);
+ }
+
+ /* multicast setup frame. */
+ if (sc->dc_stag) {
+ if (sc->dc_smap != NULL)
+ bus_dmamap_unload(sc->dc_stag, sc->dc_smap);
+ if (sc->dc_smap != NULL && sc->dc_cdata.dc_sbuf != NULL)
+ bus_dmamem_free(sc->dc_stag, sc->dc_cdata.dc_sbuf,
+ sc->dc_smap);
+ bus_dma_tag_destroy(sc->dc_stag);
+ }
+}
+
/*
* Attach the interface. Allocate softc structures, do ifmedia
* setup and ethernet/BPF attach.
@@ -1791,12 +2020,14 @@ static int
dc_attach(device_t dev)
{
uint32_t eaddr[(ETHER_ADDR_LEN+3)/4];
- u_int32_t command;
+ uint32_t command;
struct dc_softc *sc;
struct ifnet *ifp;
- u_int32_t reg, revision;
- int error, i, mac_offset, phy, rid, tmp;
- u_int8_t *mac;
+ struct dc_mediainfo *m;
+ uint32_t reg, revision;
+ uint16_t *srom;
+ int error, mac_offset, n, phy, rid, tmp;
+ uint8_t *mac;
sc = device_get_softc(dev);
sc->dc_dev = dev;
@@ -1836,6 +2067,7 @@ dc_attach(device_t dev)
sc->dc_info = dc_devtype(dev);
revision = pci_get_revid(dev);
+ error = 0;
/* Get the eeprom width, but PNIC and XIRCOM have diff eeprom */
if (sc->dc_info->dc_devid !=
DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C168) &&
@@ -1849,7 +2081,9 @@ dc_attach(device_t dev)
sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_REDUCED_MII_POLL;
/* Save EEPROM contents so we can parse them later. */
- dc_read_srom(sc, sc->dc_romwidth);
+ error = dc_read_srom(sc, sc->dc_romwidth);
+ if (error != 0)
+ goto fail;
break;
case DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9009):
case DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9100):
@@ -1868,7 +2102,9 @@ dc_attach(device_t dev)
sc->dc_flags |= DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_TX_ADMTEK_WAR;
sc->dc_pmode = DC_PMODE_MII;
- dc_read_srom(sc, sc->dc_romwidth);
+ error = dc_read_srom(sc, sc->dc_romwidth);
+ if (error != 0)
+ goto fail;
break;
case DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN983):
case DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN985):
@@ -1935,6 +2171,12 @@ dc_attach(device_t dev)
sc->dc_flags |= DC_TX_STORENFWD | DC_TX_INTR_ALWAYS;
sc->dc_flags |= DC_PNIC_RX_BUG_WAR;
sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, M_NOWAIT);
+ if (sc->dc_pnic_rx_buf == NULL) {
+ device_printf(sc->dc_dev,
+ "Could not allocate PNIC RX buffer\n");
+ error = ENOMEM;
+ goto fail;
+ }
if (revision < DC_REVISION_82C169)
sc->dc_pmode = DC_PMODE_SYM;
break;
@@ -1960,7 +2202,24 @@ dc_attach(device_t dev)
sc->dc_flags |= DC_TX_INTR_ALWAYS;
sc->dc_flags |= DC_REDUCED_MII_POLL;
sc->dc_pmode = DC_PMODE_MII;
- dc_read_srom(sc, sc->dc_romwidth);
+ error = dc_read_srom(sc, sc->dc_romwidth);
+ if (error != 0)
+ goto fail;
+ break;
+ case DC_DEVID(DC_VENDORID_ULI, DC_DEVICEID_M5261):
+ case DC_DEVID(DC_VENDORID_ULI, DC_DEVICEID_M5263):
+ if (sc->dc_info->dc_devid ==
+ DC_DEVID(DC_VENDORID_ULI, DC_DEVICEID_M5261))
+ sc->dc_type = DC_TYPE_ULI_M5261;
+ else
+ sc->dc_type = DC_TYPE_ULI_M5263;
+ /* TX buffers should be aligned on 4 byte boundary. */
+ sc->dc_flags |= DC_TX_INTR_ALWAYS | DC_TX_COALESCE |
+ DC_TX_ALIGN;
+ sc->dc_pmode = DC_PMODE_MII;
+ error = dc_read_srom(sc, sc->dc_romwidth);
+ if (error != 0)
+ goto fail;
break;
default:
device_printf(dev, "unknown device: %x\n",
@@ -1991,9 +2250,11 @@ dc_attach(device_t dev)
* The tricky ones are the Macronix/PNIC II and the
* Intel 21143.
*/
- if (DC_IS_INTEL(sc))
- dc_parse_21143_srom(sc);
- else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
+ if (DC_IS_INTEL(sc)) {
+ error = dc_parse_21143_srom(sc);
+ if (error != 0)
+ goto fail;
+ } else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
if (sc->dc_type == DC_TYPE_98713)
sc->dc_pmode = DC_PMODE_MII;
else
@@ -2057,101 +2318,70 @@ dc_attach(device_t dev)
}
bcopy(mac, eaddr, ETHER_ADDR_LEN);
break;
+ case DC_TYPE_ULI_M5261:
+ case DC_TYPE_ULI_M5263:
+ srom = (uint16_t *)sc->dc_srom;
+ if (srom == NULL || *srom == 0xFFFF || *srom == 0) {
+ /*
+ * No valid SROM present, read station address
+ * from ID Table.
+ */
+ device_printf(dev,
+ "Reading station address from ID Table.\n");
+ CSR_WRITE_4(sc, DC_BUSCTL, 0x10000);
+ CSR_WRITE_4(sc, DC_SIARESET, 0x01C0);
+ CSR_WRITE_4(sc, DC_10BTCTRL, 0x0000);
+ CSR_WRITE_4(sc, DC_10BTCTRL, 0x0010);
+ CSR_WRITE_4(sc, DC_10BTCTRL, 0x0000);
+ CSR_WRITE_4(sc, DC_SIARESET, 0x0000);
+ CSR_WRITE_4(sc, DC_SIARESET, 0x01B0);
+ mac = (uint8_t *)eaddr;
+ for (n = 0; n < ETHER_ADDR_LEN; n++)
+ mac[n] = (uint8_t)CSR_READ_4(sc, DC_10BTCTRL);
+ CSR_WRITE_4(sc, DC_SIARESET, 0x0000);
+ CSR_WRITE_4(sc, DC_BUSCTL, 0x0000);
+ DELAY(10);
+ } else
+ dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3,
+ 0);
+ break;
default:
dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0);
break;
}
- /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
- error = bus_dma_tag_create(bus_get_dma_tag(dev), PAGE_SIZE, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- sizeof(struct dc_list_data), 1, sizeof(struct dc_list_data),
- 0, NULL, NULL, &sc->dc_ltag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamem_alloc(sc->dc_ltag, (void **)&sc->dc_ldata,
- BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->dc_lmap);
- if (error) {
- device_printf(dev, "failed to allocate DMA safe memory\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamap_load(sc->dc_ltag, sc->dc_lmap, sc->dc_ldata,
- sizeof(struct dc_list_data), dc_dma_map_addr, &sc->dc_laddr,
- BUS_DMA_NOWAIT);
- if (error) {
- device_printf(dev, "cannot get address of the descriptors\n");
- error = ENXIO;
- goto fail;
- }
-
+ bcopy(eaddr, sc->dc_eaddr, sizeof(eaddr));
/*
- * Allocate a busdma tag and DMA safe memory for the multicast
- * setup frame.
+ * If we still have invalid station address, see whether we can
+ * find station address for chip 0. Some multi-port controllers
+ * just store station address for chip 0 if they have a shared
+ * SROM.
*/
- error = bus_dma_tag_create(bus_get_dma_tag(dev), PAGE_SIZE, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- DC_SFRAME_LEN + DC_MIN_FRAMELEN, 1, DC_SFRAME_LEN + DC_MIN_FRAMELEN,
- 0, NULL, NULL, &sc->dc_stag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamem_alloc(sc->dc_stag, (void **)&sc->dc_cdata.dc_sbuf,
- BUS_DMA_NOWAIT, &sc->dc_smap);
- if (error) {
- device_printf(dev, "failed to allocate DMA safe memory\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamap_load(sc->dc_stag, sc->dc_smap, sc->dc_cdata.dc_sbuf,
- DC_SFRAME_LEN, dc_dma_map_addr, &sc->dc_saddr, BUS_DMA_NOWAIT);
- if (error) {
- device_printf(dev, "cannot get address of the descriptors\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Allocate a busdma tag for mbufs. */
- error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- MCLBYTES * DC_MAXFRAGS, DC_MAXFRAGS, MCLBYTES,
- 0, NULL, NULL, &sc->dc_mtag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Create the TX/RX busdma maps. */
- for (i = 0; i < DC_TX_LIST_CNT; i++) {
- error = bus_dmamap_create(sc->dc_mtag, 0,
- &sc->dc_cdata.dc_tx_map[i]);
- if (error) {
- device_printf(dev, "failed to init TX ring\n");
- error = ENXIO;
- goto fail;
- }
- }
- for (i = 0; i < DC_RX_LIST_CNT; i++) {
- error = bus_dmamap_create(sc->dc_mtag, 0,
- &sc->dc_cdata.dc_rx_map[i]);
- if (error) {
- device_printf(dev, "failed to init RX ring\n");
- error = ENXIO;
+ if ((sc->dc_eaddr[0] == 0 && (sc->dc_eaddr[1] & ~0xffff) == 0) ||
+ (sc->dc_eaddr[0] == 0xffffffff &&
+ (sc->dc_eaddr[1] & 0xffff) == 0xffff)) {
+ error = dc_check_multiport(sc);
+ if (error == 0) {
+ bcopy(sc->dc_eaddr, eaddr, sizeof(eaddr));
+ /* Extract media information. */
+ if (DC_IS_INTEL(sc) && sc->dc_srom != NULL) {
+ while (sc->dc_mi != NULL) {
+ m = sc->dc_mi->dc_next;
+ free(sc->dc_mi, M_DEVBUF);
+ sc->dc_mi = m;
+ }
+ error = dc_parse_21143_srom(sc);
+ if (error != 0)
+ goto fail;
+ }
+ } else if (error == ENOMEM)
goto fail;
- }
+ else
+ error = 0;
}
- error = bus_dmamap_create(sc->dc_mtag, 0, &sc->dc_sparemap);
- if (error) {
- device_printf(dev, "failed to init RX ring\n");
- error = ENXIO;
+
+ if ((error = dc_dma_alloc(sc)) != 0)
goto fail;
- }
ifp = sc->dc_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
@@ -2225,9 +2455,6 @@ dc_attach(device_t dev)
if (sc->dc_pmode != DC_PMODE_SIA)
sc->dc_pmode = DC_PMODE_SYM;
sc->dc_flags |= DC_21143_NWAY;
- mii_attach(dev, &sc->dc_miibus, ifp, dc_ifmedia_upd,
- dc_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY,
- MII_OFFSET_ANY, 0);
/*
* For non-MII cards, we need to have the 21143
* drive the LEDs. Except there are some systems
@@ -2238,7 +2465,9 @@ dc_attach(device_t dev)
if (!(pci_get_subvendor(dev) == 0x1033 &&
pci_get_subdevice(dev) == 0x8028))
sc->dc_flags |= DC_TULIP_LEDS;
- error = 0;
+ error = mii_attach(dev, &sc->dc_miibus, ifp, dc_ifmedia_upd,
+ dc_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY,
+ MII_OFFSET_ANY, 0);
}
if (error) {
@@ -2300,7 +2529,6 @@ dc_detach(device_t dev)
struct dc_softc *sc;
struct ifnet *ifp;
struct dc_mediainfo *m;
- int i;
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized"));
@@ -2308,7 +2536,7 @@ dc_detach(device_t dev)
ifp = sc->dc_ifp;
#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING)
+ if (ifp != NULL && ifp->if_capenable & IFCAP_POLLING)
ether_poll_deregister(ifp);
#endif
@@ -2332,30 +2560,10 @@ dc_detach(device_t dev)
if (sc->dc_res)
bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res);
- if (ifp)
+ if (ifp != NULL)
if_free(ifp);
- if (sc->dc_cdata.dc_sbuf != NULL)
- bus_dmamem_free(sc->dc_stag, sc->dc_cdata.dc_sbuf, sc->dc_smap);
- if (sc->dc_ldata != NULL)
- bus_dmamem_free(sc->dc_ltag, sc->dc_ldata, sc->dc_lmap);
- if (sc->dc_mtag) {
- for (i = 0; i < DC_TX_LIST_CNT; i++)
- if (sc->dc_cdata.dc_tx_map[i] != NULL)
- bus_dmamap_destroy(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[i]);
- for (i = 0; i < DC_RX_LIST_CNT; i++)
- if (sc->dc_cdata.dc_rx_map[i] != NULL)
- bus_dmamap_destroy(sc->dc_mtag,
- sc->dc_cdata.dc_rx_map[i]);
- bus_dmamap_destroy(sc->dc_mtag, sc->dc_sparemap);
- }
- if (sc->dc_stag)
- bus_dma_tag_destroy(sc->dc_stag);
- if (sc->dc_mtag)
- bus_dma_tag_destroy(sc->dc_mtag);
- if (sc->dc_ltag)
- bus_dma_tag_destroy(sc->dc_ltag);
+ dc_dma_free(sc);
free(sc->dc_pnic_rx_buf, M_DEVBUF);
@@ -2382,25 +2590,26 @@ dc_list_tx_init(struct dc_softc *sc)
int i, nexti;
cd = &sc->dc_cdata;
- ld = sc->dc_ldata;
+ ld = &sc->dc_ldata;
for (i = 0; i < DC_TX_LIST_CNT; i++) {
if (i == DC_TX_LIST_CNT - 1)
nexti = 0;
else
nexti = i + 1;
+ ld->dc_tx_list[i].dc_status = 0;
+ ld->dc_tx_list[i].dc_ctl = 0;
+ ld->dc_tx_list[i].dc_data = 0;
ld->dc_tx_list[i].dc_next = htole32(DC_TXDESC(sc, nexti));
cd->dc_tx_chain[i] = NULL;
- ld->dc_tx_list[i].dc_data = 0;
- ld->dc_tx_list[i].dc_ctl = 0;
}
cd->dc_tx_prod = cd->dc_tx_cons = cd->dc_tx_cnt = 0;
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
+ cd->dc_tx_pkts = 0;
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return (0);
}
-
/*
* Initialize the RX descriptors and allocate mbufs for them. Note that
* we arrange the descriptors in a closed ring, so that the last descriptor
@@ -2414,10 +2623,10 @@ dc_list_rx_init(struct dc_softc *sc)
int i, nexti;
cd = &sc->dc_cdata;
- ld = sc->dc_ldata;
+ ld = &sc->dc_ldata;
for (i = 0; i < DC_RX_LIST_CNT; i++) {
- if (dc_newbuf(sc, i, 1) != 0)
+ if (dc_newbuf(sc, i) != 0)
return (ENOBUFS);
if (i == DC_RX_LIST_CNT - 1)
nexti = 0;
@@ -2427,7 +2636,7 @@ dc_list_rx_init(struct dc_softc *sc)
}
cd->dc_rx_prod = 0;
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return (0);
}
@@ -2436,23 +2645,18 @@ dc_list_rx_init(struct dc_softc *sc)
* Initialize an RX descriptor and attach an MBUF cluster.
*/
static int
-dc_newbuf(struct dc_softc *sc, int i, int alloc)
+dc_newbuf(struct dc_softc *sc, int i)
{
- struct mbuf *m_new;
- bus_dmamap_t tmp;
+ struct mbuf *m;
+ bus_dmamap_t map;
bus_dma_segment_t segs[1];
int error, nseg;
- if (alloc) {
- m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (m_new == NULL)
- return (ENOBUFS);
- } else {
- m_new = sc->dc_cdata.dc_rx_chain[i];
- m_new->m_data = m_new->m_ext.ext_buf;
- }
- m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
- m_adj(m_new, sizeof(u_int64_t));
+ m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL)
+ return (ENOBUFS);
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
+ m_adj(m, sizeof(u_int64_t));
/*
* If this is a PNIC chip, zero the buffer. This is part
@@ -2460,31 +2664,31 @@ dc_newbuf(struct dc_softc *sc, int i, int alloc)
* 82c169 chips.
*/
if (sc->dc_flags & DC_PNIC_RX_BUG_WAR)
- bzero(mtod(m_new, char *), m_new->m_len);
+ bzero(mtod(m, char *), m->m_len);
- /* No need to remap the mbuf if we're reusing it. */
- if (alloc) {
- error = bus_dmamap_load_mbuf_sg(sc->dc_mtag, sc->dc_sparemap,
- m_new, segs, &nseg, 0);
- if (error) {
- m_freem(m_new);
- return (error);
- }
- KASSERT(nseg == 1,
- ("%s: wrong number of segments (%d)", __func__, nseg));
- sc->dc_ldata->dc_rx_list[i].dc_data = htole32(segs->ds_addr);
- bus_dmamap_unload(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i]);
- tmp = sc->dc_cdata.dc_rx_map[i];
- sc->dc_cdata.dc_rx_map[i] = sc->dc_sparemap;
- sc->dc_sparemap = tmp;
- sc->dc_cdata.dc_rx_chain[i] = m_new;
- }
-
- sc->dc_ldata->dc_rx_list[i].dc_ctl = htole32(DC_RXCTL_RLINK | DC_RXLEN);
- sc->dc_ldata->dc_rx_list[i].dc_status = htole32(DC_RXSTAT_OWN);
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i],
+ error = bus_dmamap_load_mbuf_sg(sc->dc_rx_mtag, sc->dc_sparemap,
+ m, segs, &nseg, 0);
+ if (error) {
+ m_freem(m);
+ return (error);
+ }
+ KASSERT(nseg == 1, ("%s: wrong number of segments (%d)", __func__,
+ nseg));
+ if (sc->dc_cdata.dc_rx_chain[i] != NULL)
+ bus_dmamap_unload(sc->dc_rx_mtag, sc->dc_cdata.dc_rx_map[i]);
+
+ map = sc->dc_cdata.dc_rx_map[i];
+ sc->dc_cdata.dc_rx_map[i] = sc->dc_sparemap;
+ sc->dc_sparemap = map;
+ sc->dc_cdata.dc_rx_chain[i] = m;
+ bus_dmamap_sync(sc->dc_rx_mtag, sc->dc_cdata.dc_rx_map[i],
BUS_DMASYNC_PREREAD);
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
+
+ sc->dc_ldata.dc_rx_list[i].dc_ctl = htole32(DC_RXCTL_RLINK | DC_RXLEN);
+ sc->dc_ldata.dc_rx_list[i].dc_data =
+ htole32(DC_ADDR_LO(segs[0].ds_addr));
+ sc->dc_ldata.dc_rx_list[i].dc_status = htole32(DC_RXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return (0);
}
@@ -2541,7 +2745,7 @@ dc_newbuf(struct dc_softc *sc, int i, int alloc)
* the time.
*/
-#define DC_WHOLEFRAME (DC_RXSTAT_FIRSTFRAG | DC_RXSTAT_LASTFRAG)
+#define DC_WHOLEFRAME (DC_RXSTAT_FIRSTFRAG | DC_RXSTAT_LASTFRAG)
static void
dc_pnic_rx_bug_war(struct dc_softc *sc, int idx)
{
@@ -2550,16 +2754,16 @@ dc_pnic_rx_bug_war(struct dc_softc *sc, int idx)
struct mbuf *m = NULL;
unsigned char *ptr;
int i, total_len;
- u_int32_t rxstat = 0;
+ uint32_t rxstat = 0;
i = sc->dc_pnic_rx_bug_save;
- cur_rx = &sc->dc_ldata->dc_rx_list[idx];
+ cur_rx = &sc->dc_ldata.dc_rx_list[idx];
ptr = sc->dc_pnic_rx_buf;
bzero(ptr, DC_RXLEN * 5);
/* Copy all the bytes from the bogus buffers. */
while (1) {
- c = &sc->dc_ldata->dc_rx_list[i];
+ c = &sc->dc_ldata.dc_rx_list[i];
rxstat = le32toh(c->dc_status);
m = sc->dc_cdata.dc_rx_chain[i];
bcopy(mtod(m, char *), ptr, DC_RXLEN);
@@ -2567,7 +2771,7 @@ dc_pnic_rx_bug_war(struct dc_softc *sc, int idx)
/* If this is the last buffer, break out. */
if (i == idx || rxstat & DC_RXSTAT_LASTFRAG)
break;
- dc_newbuf(sc, i, 0);
+ dc_discard_rxbuf(sc, i);
DC_INC(i, DC_RX_LIST_CNT);
}
@@ -2592,7 +2796,6 @@ dc_pnic_rx_bug_war(struct dc_softc *sc, int idx)
* the status word to make it look like a successful
* frame reception.
*/
- dc_newbuf(sc, i, 0);
bcopy(ptr, mtod(m, char *), total_len);
cur_rx->dc_status = htole32(rxstat | DC_RXSTAT_FIRSTFRAG);
}
@@ -2617,7 +2820,7 @@ dc_rx_resync(struct dc_softc *sc)
pos = sc->dc_cdata.dc_rx_prod;
for (i = 0; i < DC_RX_LIST_CNT; i++) {
- cur_rx = &sc->dc_ldata->dc_rx_list[pos];
+ cur_rx = &sc->dc_ldata.dc_rx_list[pos];
if (!(le32toh(cur_rx->dc_status) & DC_RXSTAT_OWN))
break;
DC_INC(pos, DC_RX_LIST_CNT);
@@ -2633,6 +2836,22 @@ dc_rx_resync(struct dc_softc *sc)
return (EAGAIN);
}
+static void
+dc_discard_rxbuf(struct dc_softc *sc, int i)
+{
+ struct mbuf *m;
+
+ if (sc->dc_flags & DC_PNIC_RX_BUG_WAR) {
+ m = sc->dc_cdata.dc_rx_chain[i];
+ bzero(mtod(m, char *), m->m_len);
+ }
+
+ sc->dc_ldata.dc_rx_list[i].dc_ctl = htole32(DC_RXCTL_RLINK | DC_RXLEN);
+ sc->dc_ldata.dc_rx_list[i].dc_status = htole32(DC_RXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap, BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+}
+
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
@@ -2640,22 +2859,22 @@ dc_rx_resync(struct dc_softc *sc)
static int
dc_rxeof(struct dc_softc *sc)
{
- struct mbuf *m, *m0;
+ struct mbuf *m;
struct ifnet *ifp;
struct dc_desc *cur_rx;
int i, total_len, rx_npkts;
- u_int32_t rxstat;
+ uint32_t rxstat;
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
- i = sc->dc_cdata.dc_rx_prod;
- total_len = 0;
rx_npkts = 0;
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, BUS_DMASYNC_POSTREAD);
- while (!(le32toh(sc->dc_ldata->dc_rx_list[i].dc_status) &
- DC_RXSTAT_OWN)) {
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap, BUS_DMASYNC_POSTREAD |
+ BUS_DMASYNC_POSTWRITE);
+ for (i = sc->dc_cdata.dc_rx_prod;
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0;
+ DC_INC(i, DC_RX_LIST_CNT)) {
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
if (sc->rxcycles <= 0)
@@ -2663,21 +2882,22 @@ dc_rxeof(struct dc_softc *sc)
sc->rxcycles--;
}
#endif
- cur_rx = &sc->dc_ldata->dc_rx_list[i];
+ cur_rx = &sc->dc_ldata.dc_rx_list[i];
rxstat = le32toh(cur_rx->dc_status);
+ if ((rxstat & DC_RXSTAT_OWN) != 0)
+ break;
m = sc->dc_cdata.dc_rx_chain[i];
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i],
+ bus_dmamap_sync(sc->dc_rx_mtag, sc->dc_cdata.dc_rx_map[i],
BUS_DMASYNC_POSTREAD);
total_len = DC_RXBYTES(rxstat);
+ rx_npkts++;
if (sc->dc_flags & DC_PNIC_RX_BUG_WAR) {
if ((rxstat & DC_WHOLEFRAME) != DC_WHOLEFRAME) {
if (rxstat & DC_RXSTAT_FIRSTFRAG)
sc->dc_pnic_rx_bug_save = i;
- if ((rxstat & DC_RXSTAT_LASTFRAG) == 0) {
- DC_INC(i, DC_RX_LIST_CNT);
+ if ((rxstat & DC_RXSTAT_LASTFRAG) == 0)
continue;
- }
dc_pnic_rx_bug_war(sc, i);
rxstat = le32toh(cur_rx->dc_status);
total_len = DC_RXBYTES(rxstat);
@@ -2699,11 +2919,11 @@ dc_rxeof(struct dc_softc *sc)
ifp->if_ierrors++;
if (rxstat & DC_RXSTAT_COLLSEEN)
ifp->if_collisions++;
- dc_newbuf(sc, i, 0);
- if (rxstat & DC_RXSTAT_CRCERR) {
- DC_INC(i, DC_RX_LIST_CNT);
+ dc_discard_rxbuf(sc, i);
+ if (rxstat & DC_RXSTAT_CRCERR)
continue;
- } else {
+ else {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
dc_init_locked(sc);
return (rx_npkts);
}
@@ -2722,29 +2942,32 @@ dc_rxeof(struct dc_softc *sc)
* if the allocation fails, then use m_devget and leave the
* existing buffer in the receive ring.
*/
- if (dc_newbuf(sc, i, 1) == 0) {
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = m->m_len = total_len;
- DC_INC(i, DC_RX_LIST_CNT);
- } else
-#endif
+ if (dc_newbuf(sc, i) != 0) {
+ dc_discard_rxbuf(sc, i);
+ ifp->if_iqdrops++;
+ continue;
+ }
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = total_len;
+#else
{
+ struct mbuf *m0;
+
m0 = m_devget(mtod(m, char *), total_len,
ETHER_ALIGN, ifp, NULL);
- dc_newbuf(sc, i, 0);
- DC_INC(i, DC_RX_LIST_CNT);
+ dc_discard_rxbuf(sc, i);
if (m0 == NULL) {
- ifp->if_ierrors++;
+ ifp->if_iqdrops++;
continue;
}
m = m0;
}
+#endif
ifp->if_ipackets++;
DC_UNLOCK(sc);
(*ifp->if_input)(ifp, m);
DC_LOCK(sc);
- rx_npkts++;
}
sc->dc_cdata.dc_rx_prod = i;
@@ -2758,10 +2981,13 @@ dc_rxeof(struct dc_softc *sc)
static void
dc_txeof(struct dc_softc *sc)
{
- struct dc_desc *cur_tx = NULL;
+ struct dc_desc *cur_tx;
struct ifnet *ifp;
- int idx;
- u_int32_t ctl, txstat;
+ int idx, setup;
+ uint32_t ctl, txstat;
+
+ if (sc->dc_cdata.dc_tx_cnt == 0)
+ return;
ifp = sc->dc_ifp;
@@ -2769,36 +2995,40 @@ dc_txeof(struct dc_softc *sc)
* Go through our tx list and free mbufs for those
* frames that have been transmitted.
*/
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, BUS_DMASYNC_POSTREAD);
- idx = sc->dc_cdata.dc_tx_cons;
- while (idx != sc->dc_cdata.dc_tx_prod) {
-
- cur_tx = &sc->dc_ldata->dc_tx_list[idx];
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_POSTREAD |
+ BUS_DMASYNC_POSTWRITE);
+ setup = 0;
+ for (idx = sc->dc_cdata.dc_tx_cons; idx != sc->dc_cdata.dc_tx_prod;
+ DC_INC(idx, DC_TX_LIST_CNT), sc->dc_cdata.dc_tx_cnt--) {
+ cur_tx = &sc->dc_ldata.dc_tx_list[idx];
txstat = le32toh(cur_tx->dc_status);
ctl = le32toh(cur_tx->dc_ctl);
if (txstat & DC_TXSTAT_OWN)
break;
- if (!(ctl & DC_TXCTL_LASTFRAG) || ctl & DC_TXCTL_SETUP) {
- if (ctl & DC_TXCTL_SETUP) {
- /*
- * Yes, the PNIC is so brain damaged
- * that it will sometimes generate a TX
- * underrun error while DMAing the RX
- * filter setup frame. If we detect this,
- * we have to send the setup frame again,
- * or else the filter won't be programmed
- * correctly.
- */
- if (DC_IS_PNIC(sc)) {
- if (txstat & DC_TXSTAT_ERRSUM)
- dc_setfilt(sc);
- }
- sc->dc_cdata.dc_tx_chain[idx] = NULL;
+ if (sc->dc_cdata.dc_tx_chain[idx] == NULL)
+ continue;
+
+ if (ctl & DC_TXCTL_SETUP) {
+ cur_tx->dc_ctl = htole32(ctl & ~DC_TXCTL_SETUP);
+ setup++;
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap,
+ BUS_DMASYNC_POSTWRITE);
+ /*
+ * Yes, the PNIC is so brain damaged
+ * that it will sometimes generate a TX
+ * underrun error while DMAing the RX
+ * filter setup frame. If we detect this,
+ * we have to send the setup frame again,
+ * or else the filter won't be programmed
+ * correctly.
+ */
+ if (DC_IS_PNIC(sc)) {
+ if (txstat & DC_TXSTAT_ERRSUM)
+ dc_setfilt(sc);
}
- sc->dc_cdata.dc_tx_cnt--;
- DC_INC(idx, DC_TX_LIST_CNT);
+ sc->dc_cdata.dc_tx_chain[idx] = NULL;
continue;
}
@@ -2831,34 +3061,30 @@ dc_txeof(struct dc_softc *sc)
if (txstat & DC_TXSTAT_LATECOLL)
ifp->if_collisions++;
if (!(txstat & DC_TXSTAT_UNDERRUN)) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
dc_init_locked(sc);
return;
}
- }
-
+ } else
+ ifp->if_opackets++;
ifp->if_collisions += (txstat & DC_TXSTAT_COLLCNT) >> 3;
- ifp->if_opackets++;
- if (sc->dc_cdata.dc_tx_chain[idx] != NULL) {
- bus_dmamap_sync(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[idx],
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[idx]);
- m_freem(sc->dc_cdata.dc_tx_chain[idx]);
- sc->dc_cdata.dc_tx_chain[idx] = NULL;
- }
-
- sc->dc_cdata.dc_tx_cnt--;
- DC_INC(idx, DC_TX_LIST_CNT);
+ bus_dmamap_sync(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx],
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx]);
+ m_freem(sc->dc_cdata.dc_tx_chain[idx]);
+ sc->dc_cdata.dc_tx_chain[idx] = NULL;
}
sc->dc_cdata.dc_tx_cons = idx;
- if (DC_TX_LIST_CNT - sc->dc_cdata.dc_tx_cnt > DC_TX_LIST_RSVD)
+ if (sc->dc_cdata.dc_tx_cnt <= DC_TX_LIST_CNT - DC_TX_LIST_RSVD) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
- if (sc->dc_cdata.dc_tx_cnt == 0)
- sc->dc_wdog_timer = 0;
+ if (sc->dc_cdata.dc_tx_cnt == 0)
+ sc->dc_wdog_timer = 0;
+ }
+ if (setup > 0)
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
static void
@@ -2867,13 +3093,20 @@ dc_tick(void *xsc)
struct dc_softc *sc;
struct mii_data *mii;
struct ifnet *ifp;
- u_int32_t r;
+ uint32_t r;
sc = xsc;
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
mii = device_get_softc(sc->dc_miibus);
+ /*
+ * Reclaim transmitted frames for controllers that do
+ * not generate TX completion interrupt for every frame.
+ */
+ if (sc->dc_flags & DC_TX_USE_TX_INTR)
+ dc_txeof(sc);
+
if (sc->dc_flags & DC_REDUCED_MII_POLL) {
if (sc->dc_flags & DC_21143_NWAY) {
r = CSR_READ_4(sc, DC_10BTSTAT);
@@ -2896,11 +3129,8 @@ dc_tick(void *xsc)
*/
if ((DC_HAS_BROKEN_RXSTATE(sc) || (CSR_READ_4(sc,
DC_ISR) & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
- sc->dc_cdata.dc_tx_cnt == 0) {
+ sc->dc_cdata.dc_tx_cnt == 0)
mii_tick(mii);
- if (!(mii->mii_media_status & IFM_ACTIVE))
- sc->dc_link = 0;
- }
}
} else
mii_tick(mii);
@@ -2924,12 +3154,8 @@ dc_tick(void *xsc)
* that time, packets will stay in the send queue, and once the
* link comes up, they will be flushed out to the wire.
*/
- if (!sc->dc_link && mii->mii_media_status & IFM_ACTIVE &&
- IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
- sc->dc_link++;
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start_locked(ifp);
- }
+ if (sc->dc_link != 0 && !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ dc_start_locked(ifp);
if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
@@ -2944,47 +3170,57 @@ dc_tick(void *xsc)
static void
dc_tx_underrun(struct dc_softc *sc)
{
- u_int32_t isr;
- int i;
+ uint32_t netcfg, isr;
+ int i, reinit;
- if (DC_IS_DAVICOM(sc))
- dc_init_locked(sc);
+ reinit = 0;
+ netcfg = CSR_READ_4(sc, DC_NETCFG);
+ device_printf(sc->dc_dev, "TX underrun -- ");
+ if ((sc->dc_flags & DC_TX_STORENFWD) == 0) {
+ if (sc->dc_txthresh + DC_TXTHRESH_INC > DC_TXTHRESH_MAX) {
+ printf("using store and forward mode\n");
+ netcfg |= DC_NETCFG_STORENFWD;
+ } else {
+ printf("increasing TX threshold\n");
+ sc->dc_txthresh += DC_TXTHRESH_INC;
+ netcfg &= ~DC_NETCFG_TX_THRESH;
+ netcfg |= sc->dc_txthresh;
+ }
- if (DC_IS_INTEL(sc)) {
- /*
- * The real 21143 requires that the transmitter be idle
- * in order to change the transmit threshold or store
- * and forward state.
- */
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
+ if (DC_IS_INTEL(sc)) {
+ /*
+ * The real 21143 requires that the transmitter be idle
+ * in order to change the transmit threshold or store
+ * and forward state.
+ */
+ CSR_WRITE_4(sc, DC_NETCFG, netcfg & ~DC_NETCFG_TX_ON);
- for (i = 0; i < DC_TIMEOUT; i++) {
- isr = CSR_READ_4(sc, DC_ISR);
- if (isr & DC_ISR_TX_IDLE)
- break;
- DELAY(10);
- }
- if (i == DC_TIMEOUT) {
- device_printf(sc->dc_dev,
- "%s: failed to force tx to idle state\n",
- __func__);
- dc_init_locked(sc);
+ for (i = 0; i < DC_TIMEOUT; i++) {
+ isr = CSR_READ_4(sc, DC_ISR);
+ if (isr & DC_ISR_TX_IDLE)
+ break;
+ DELAY(10);
+ }
+ if (i == DC_TIMEOUT) {
+ device_printf(sc->dc_dev,
+ "%s: failed to force tx to idle state\n",
+ __func__);
+ reinit++;
+ }
}
+ } else {
+ printf("resetting\n");
+ reinit++;
}
- device_printf(sc->dc_dev, "TX underrun -- ");
- sc->dc_txthresh += DC_TXTHRESH_INC;
- if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
- printf("using store and forward mode\n");
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
+ if (reinit == 0) {
+ CSR_WRITE_4(sc, DC_NETCFG, netcfg);
+ if (DC_IS_INTEL(sc))
+ CSR_WRITE_4(sc, DC_NETCFG, netcfg | DC_NETCFG_TX_ON);
} else {
- printf("increasing TX threshold\n");
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
- DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
+ sc->dc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ dc_init_locked(sc);
}
-
- if (DC_IS_INTEL(sc))
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
}
#ifdef DEVICE_POLLING
@@ -3011,7 +3247,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
dc_start_locked(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
- u_int32_t status;
+ uint32_t status;
status = CSR_READ_4(sc, DC_ISR);
status &= (DC_ISR_RX_WATDOGTIMEO | DC_ISR_RX_NOBUF |
@@ -3025,7 +3261,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
CSR_WRITE_4(sc, DC_ISR, status);
if (status & (DC_ISR_RX_WATDOGTIMEO | DC_ISR_RX_NOBUF)) {
- u_int32_t r = CSR_READ_4(sc, DC_FRAMESDISCARDED);
+ uint32_t r = CSR_READ_4(sc, DC_FRAMESDISCARDED);
ifp->if_ierrors += (r & 0xffff) + ((r >> 17) & 0x7ff);
if (dc_rx_resync(sc))
@@ -3040,7 +3276,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
if (status & DC_ISR_BUS_ERR) {
if_printf(ifp, "%s: bus error\n", __func__);
- dc_reset(sc);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
dc_init_locked(sc);
}
}
@@ -3054,17 +3290,20 @@ dc_intr(void *arg)
{
struct dc_softc *sc;
struct ifnet *ifp;
- u_int32_t status;
+ uint32_t r, status;
+ int n;
sc = arg;
if (sc->suspended)
return;
- if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
- return;
-
DC_LOCK(sc);
+ status = CSR_READ_4(sc, DC_ISR);
+ if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0) {
+ DC_UNLOCK(sc);
+ return;
+ }
ifp = sc->dc_ifp;
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
@@ -3072,29 +3311,17 @@ dc_intr(void *arg)
return;
}
#endif
-
- /* Suppress unwanted interrupts */
- if (!(ifp->if_flags & IFF_UP)) {
- if (CSR_READ_4(sc, DC_ISR) & DC_INTRS)
- dc_stop(sc);
- DC_UNLOCK(sc);
- return;
- }
-
/* Disable interrupts. */
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
- while (((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS) &&
- status != 0xFFFFFFFF &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-
+ for (n = 16; n > 0; n--) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ break;
+ /* Ack interrupts. */
CSR_WRITE_4(sc, DC_ISR, status);
if (status & DC_ISR_RX_OK) {
- int curpkts;
- curpkts = ifp->if_ipackets;
- dc_rxeof(sc);
- if (curpkts == ifp->if_ipackets) {
+ if (dc_rxeof(sc) == 0) {
while (dc_rx_resync(sc))
dc_rxeof(sc);
}
@@ -3116,26 +3343,31 @@ dc_intr(void *arg)
if ((status & DC_ISR_RX_WATDOGTIMEO)
|| (status & DC_ISR_RX_NOBUF)) {
- int curpkts;
- curpkts = ifp->if_ipackets;
- dc_rxeof(sc);
- if (curpkts == ifp->if_ipackets) {
+ r = CSR_READ_4(sc, DC_FRAMESDISCARDED);
+ ifp->if_ierrors += (r & 0xffff) + ((r >> 17) & 0x7ff);
+ if (dc_rxeof(sc) == 0) {
while (dc_rx_resync(sc))
dc_rxeof(sc);
}
}
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ dc_start_locked(ifp);
+
if (status & DC_ISR_BUS_ERR) {
- dc_reset(sc);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
dc_init_locked(sc);
+ DC_UNLOCK(sc);
+ return;
}
+ status = CSR_READ_4(sc, DC_ISR);
+ if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0)
+ break;
}
/* Re-enable interrupts. */
- CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
-
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start_locked(ifp);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
DC_UNLOCK(sc);
}
@@ -3148,16 +3380,11 @@ static int
dc_encap(struct dc_softc *sc, struct mbuf **m_head)
{
bus_dma_segment_t segs[DC_MAXFRAGS];
+ bus_dmamap_t map;
struct dc_desc *f;
struct mbuf *m;
int cur, defragged, error, first, frag, i, idx, nseg;
- /*
- * If there's no way we can send any packets, return now.
- */
- if (DC_TX_LIST_CNT - sc->dc_cdata.dc_tx_cnt <= DC_TX_LIST_RSVD)
- return (ENOBUFS);
-
m = NULL;
defragged = 0;
if (sc->dc_flags & DC_TX_COALESCE &&
@@ -3191,7 +3418,7 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
}
idx = sc->dc_cdata.dc_tx_prod;
- error = bus_dmamap_load_mbuf_sg(sc->dc_mtag,
+ error = bus_dmamap_load_mbuf_sg(sc->dc_tx_mtag,
sc->dc_cdata.dc_tx_map[idx], *m_head, segs, &nseg, 0);
if (error == EFBIG) {
if (defragged != 0 || (m = m_collapse(*m_head, M_DONTWAIT,
@@ -3201,7 +3428,7 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
return (defragged != 0 ? error : ENOBUFS);
}
*m_head = m;
- error = bus_dmamap_load_mbuf_sg(sc->dc_mtag,
+ error = bus_dmamap_load_mbuf_sg(sc->dc_tx_mtag,
sc->dc_cdata.dc_tx_map[idx], *m_head, segs, &nseg, 0);
if (error != 0) {
m_freem(*m_head);
@@ -3218,26 +3445,34 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
return (EIO);
}
+ /* Check descriptor overruns. */
+ if (sc->dc_cdata.dc_tx_cnt + nseg > DC_TX_LIST_CNT - DC_TX_LIST_RSVD) {
+ bus_dmamap_unload(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx]);
+ return (ENOBUFS);
+ }
+ bus_dmamap_sync(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx],
+ BUS_DMASYNC_PREWRITE);
+
first = cur = frag = sc->dc_cdata.dc_tx_prod;
for (i = 0; i < nseg; i++) {
if ((sc->dc_flags & DC_TX_ADMTEK_WAR) &&
(frag == (DC_TX_LIST_CNT - 1)) &&
(first != sc->dc_cdata.dc_tx_first)) {
- bus_dmamap_unload(sc->dc_mtag,
+ bus_dmamap_unload(sc->dc_tx_mtag,
sc->dc_cdata.dc_tx_map[first]);
m_freem(*m_head);
*m_head = NULL;
return (ENOBUFS);
}
- f = &sc->dc_ldata->dc_tx_list[frag];
+ f = &sc->dc_ldata.dc_tx_list[frag];
f->dc_ctl = htole32(DC_TXCTL_TLINK | segs[i].ds_len);
if (i == 0) {
f->dc_status = 0;
f->dc_ctl |= htole32(DC_TXCTL_FIRSTFRAG);
} else
f->dc_status = htole32(DC_TXSTAT_OWN);
- f->dc_data = htole32(segs[i].ds_addr);
+ f->dc_data = htole32(DC_ADDR_LO(segs[i].ds_addr));
cur = frag;
DC_INC(frag, DC_TX_LIST_CNT);
}
@@ -3245,20 +3480,30 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
sc->dc_cdata.dc_tx_prod = frag;
sc->dc_cdata.dc_tx_cnt += nseg;
sc->dc_cdata.dc_tx_chain[cur] = *m_head;
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_LASTFRAG);
+ sc->dc_ldata.dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_LASTFRAG);
if (sc->dc_flags & DC_TX_INTR_FIRSTFRAG)
- sc->dc_ldata->dc_tx_list[first].dc_ctl |=
+ sc->dc_ldata.dc_tx_list[first].dc_ctl |=
htole32(DC_TXCTL_FINT);
if (sc->dc_flags & DC_TX_INTR_ALWAYS)
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
- if (sc->dc_flags & DC_TX_USE_TX_INTR && sc->dc_cdata.dc_tx_cnt > 64)
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
- sc->dc_ldata->dc_tx_list[first].dc_status = htole32(DC_TXSTAT_OWN);
+ sc->dc_ldata.dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
+ if (sc->dc_flags & DC_TX_USE_TX_INTR &&
+ ++sc->dc_cdata.dc_tx_pkts >= 8) {
+ sc->dc_cdata.dc_tx_pkts = 0;
+ sc->dc_ldata.dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
+ }
+ sc->dc_ldata.dc_tx_list[first].dc_status = htole32(DC_TXSTAT_OWN);
+
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ /*
+ * Swap the last and the first dmamaps to ensure the map for
+ * this transmission is placed at the last descriptor.
+ */
+ map = sc->dc_cdata.dc_tx_map[cur];
+ sc->dc_cdata.dc_tx_map[cur] = sc->dc_cdata.dc_tx_map[first];
+ sc->dc_cdata.dc_tx_map[first] = map;
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_tx_map[idx],
- BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return (0);
}
@@ -3284,23 +3529,27 @@ static void
dc_start_locked(struct ifnet *ifp)
{
struct dc_softc *sc;
- struct mbuf *m_head = NULL;
- unsigned int queued = 0;
- int idx;
+ struct mbuf *m_head;
+ int queued;
sc = ifp->if_softc;
DC_LOCK_ASSERT(sc);
- if (!sc->dc_link && ifp->if_snd.ifq_len < 10)
- return;
-
- if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING || sc->dc_link == 0)
return;
- idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
+ sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
- while (sc->dc_cdata.dc_tx_chain[idx] == NULL) {
+ for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
+ /*
+ * If there's no way we can send any packets, return now.
+ */
+ if (sc->dc_cdata.dc_tx_cnt > DC_TX_LIST_CNT - DC_TX_LIST_RSVD) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
if (m_head == NULL)
break;
@@ -3312,7 +3561,6 @@ dc_start_locked(struct ifnet *ifp)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
- idx = sc->dc_cdata.dc_tx_prod;
queued++;
/*
@@ -3320,11 +3568,6 @@ dc_start_locked(struct ifnet *ifp)
* to him.
*/
BPF_MTAP(ifp, m_head);
-
- if (sc->dc_flags & DC_TX_ONE) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
}
if (queued > 0) {
@@ -3354,9 +3597,13 @@ dc_init_locked(struct dc_softc *sc)
{
struct ifnet *ifp = sc->dc_ifp;
struct mii_data *mii;
+ struct ifmedia *ifm;
DC_LOCK_ASSERT(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
mii = device_get_softc(sc->dc_miibus);
/*
@@ -3364,11 +3611,15 @@ dc_init_locked(struct dc_softc *sc)
*/
dc_stop(sc);
dc_reset(sc);
+ if (DC_IS_INTEL(sc)) {
+ ifm = &mii->mii_media;
+ dc_apply_fixup(sc, ifm->ifm_media);
+ }
/*
* Set cache alignment and burst length.
*/
- if (DC_IS_ASIX(sc) || DC_IS_DAVICOM(sc))
+ if (DC_IS_ASIX(sc) || DC_IS_DAVICOM(sc) || DC_IS_ULI(sc))
CSR_WRITE_4(sc, DC_BUSCTL, 0);
else
CSR_WRITE_4(sc, DC_BUSCTL, DC_BUSCTL_MRME | DC_BUSCTL_MRLE);
@@ -3481,6 +3732,11 @@ dc_init_locked(struct dc_softc *sc)
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
CSR_WRITE_4(sc, DC_ISR, 0xFFFFFFFF);
+ /* Initialize TX jabber and RX watchdog timer. */
+ if (DC_IS_ULI(sc))
+ CSR_WRITE_4(sc, DC_WATCHDOG, DC_WDOG_JABBERCLK |
+ DC_WDOG_HOSTUNJAB);
+
/* Enable transmitter. */
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
@@ -3507,12 +3763,14 @@ dc_init_locked(struct dc_softc *sc)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF);
- mii_mediachg(mii);
- dc_setcfg(sc, sc->dc_if_media);
-
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ dc_ifmedia_upd_locked(sc);
+
+ /* Clear missed frames and overflow counter. */
+ CSR_READ_4(sc, DC_FRAMESDISCARDED);
+
/* Don't start the ticker if this is a homePNA link. */
if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_HPNA_1)
sc->dc_link = 1;
@@ -3534,23 +3792,37 @@ static int
dc_ifmedia_upd(struct ifnet *ifp)
{
struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
+ int error;
sc = ifp->if_softc;
- mii = device_get_softc(sc->dc_miibus);
DC_LOCK(sc);
- mii_mediachg(mii);
- ifm = &mii->mii_media;
-
- if (DC_IS_DAVICOM(sc) &&
- IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
- dc_setcfg(sc, ifm->ifm_media);
- else
- sc->dc_link = 0;
+ error = dc_ifmedia_upd_locked(sc);
DC_UNLOCK(sc);
+ return (error);
+}
- return (0);
+static int
+dc_ifmedia_upd_locked(struct dc_softc *sc)
+{
+ struct mii_data *mii;
+ struct ifmedia *ifm;
+ int error;
+
+ DC_LOCK_ASSERT(sc);
+
+ sc->dc_link = 0;
+ mii = device_get_softc(sc->dc_miibus);
+ error = mii_mediachg(mii);
+ if (error == 0) {
+ ifm = &mii->mii_media;
+ if (DC_IS_INTEL(sc))
+ dc_setcfg(sc, ifm->ifm_media);
+ else if (DC_IS_DAVICOM(sc) &&
+ IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
+ dc_setcfg(sc, ifm->ifm_media);
+ }
+
+ return (error);
}
/*
@@ -3600,7 +3872,7 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (need_setfilt)
dc_setfilt(sc);
} else {
- sc->dc_txthresh = 0;
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
dc_init_locked(sc);
}
} else {
@@ -3609,14 +3881,13 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
sc->dc_if_flags = ifp->if_flags;
DC_UNLOCK(sc);
- error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
DC_LOCK(sc);
- dc_setfilt(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ dc_setfilt(sc);
DC_UNLOCK(sc);
- error = 0;
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
@@ -3674,8 +3945,7 @@ dc_watchdog(void *xsc)
ifp->if_oerrors++;
device_printf(sc->dc_dev, "watchdog timeout\n");
- dc_stop(sc);
- dc_reset(sc);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
dc_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
@@ -3693,36 +3963,49 @@ dc_stop(struct dc_softc *sc)
struct dc_list_data *ld;
struct dc_chain_data *cd;
int i;
- u_int32_t ctl;
+ uint32_t ctl, netcfg;
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
- ld = sc->dc_ldata;
+ ld = &sc->dc_ldata;
cd = &sc->dc_cdata;
callout_stop(&sc->dc_stat_ch);
callout_stop(&sc->dc_wdog_ch);
sc->dc_wdog_timer = 0;
+ sc->dc_link = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
+ netcfg = CSR_READ_4(sc, DC_NETCFG);
+ if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON))
+ CSR_WRITE_4(sc, DC_NETCFG,
+ netcfg & ~(DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
+ /* Wait the completion of TX/RX SM. */
+ if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON))
+ dc_netcfg_wait(sc);
+
CSR_WRITE_4(sc, DC_TXADDR, 0x00000000);
CSR_WRITE_4(sc, DC_RXADDR, 0x00000000);
- sc->dc_link = 0;
/*
* Free data in the RX lists.
*/
for (i = 0; i < DC_RX_LIST_CNT; i++) {
if (cd->dc_rx_chain[i] != NULL) {
+ bus_dmamap_sync(sc->dc_rx_mtag,
+ cd->dc_rx_map[i], BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->dc_rx_mtag,
+ cd->dc_rx_map[i]);
m_freem(cd->dc_rx_chain[i]);
cd->dc_rx_chain[i] = NULL;
}
}
- bzero(&ld->dc_rx_list, sizeof(ld->dc_rx_list));
+ bzero(ld->dc_rx_list, DC_RX_LIST_SZ);
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/*
* Free the TX list buffers.
@@ -3730,17 +4013,22 @@ dc_stop(struct dc_softc *sc)
for (i = 0; i < DC_TX_LIST_CNT; i++) {
if (cd->dc_tx_chain[i] != NULL) {
ctl = le32toh(ld->dc_tx_list[i].dc_ctl);
- if ((ctl & DC_TXCTL_SETUP) ||
- !(ctl & DC_TXCTL_LASTFRAG)) {
- cd->dc_tx_chain[i] = NULL;
- continue;
+ if (ctl & DC_TXCTL_SETUP) {
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap,
+ BUS_DMASYNC_POSTWRITE);
+ } else {
+ bus_dmamap_sync(sc->dc_tx_mtag,
+ cd->dc_tx_map[i], BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->dc_tx_mtag,
+ cd->dc_tx_map[i]);
+ m_freem(cd->dc_tx_chain[i]);
}
- bus_dmamap_unload(sc->dc_mtag, cd->dc_tx_map[i]);
- m_freem(cd->dc_tx_chain[i]);
cd->dc_tx_chain[i] = NULL;
}
}
- bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
+ bzero(ld->dc_tx_list, DC_TX_LIST_SZ);
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
/*
@@ -3804,3 +4092,52 @@ dc_shutdown(device_t dev)
return (0);
}
+
+static int
+dc_check_multiport(struct dc_softc *sc)
+{
+ struct dc_softc *dsc;
+ devclass_t dc;
+ device_t child;
+ uint8_t *eaddr;
+ int unit;
+
+ dc = devclass_find("dc");
+ for (unit = 0; unit < devclass_get_maxunit(dc); unit++) {
+ child = devclass_get_device(dc, unit);
+ if (child == NULL)
+ continue;
+ if (child == sc->dc_dev)
+ continue;
+ if (device_get_parent(child) != device_get_parent(sc->dc_dev))
+ continue;
+ if (unit > device_get_unit(sc->dc_dev))
+ continue;
+ if (device_is_attached(child) == 0)
+ continue;
+ dsc = device_get_softc(child);
+ device_printf(sc->dc_dev,
+ "Using station address of %s as base\n",
+ device_get_nameunit(child));
+ bcopy(dsc->dc_eaddr, sc->dc_eaddr, ETHER_ADDR_LEN);
+ eaddr = (uint8_t *)sc->dc_eaddr;
+ eaddr[5]++;
+ /* Prepare SROM to parse again. */
+ if (DC_IS_INTEL(sc) && dsc->dc_srom != NULL &&
+ sc->dc_romwidth != 0) {
+ free(sc->dc_srom, M_DEVBUF);
+ sc->dc_romwidth = dsc->dc_romwidth;
+ sc->dc_srom = malloc(DC_ROM_SIZE(sc->dc_romwidth),
+ M_DEVBUF, M_NOWAIT);
+ if (sc->dc_srom == NULL) {
+ device_printf(sc->dc_dev,
+ "Could not allocate SROM buffer\n");
+ return (ENOMEM);
+ }
+ bcopy(dsc->dc_srom, sc->dc_srom,
+ DC_ROM_SIZE(sc->dc_romwidth));
+ }
+ return (0);
+ }
+ return (ENOENT);
+}
diff --git a/freebsd/sys/dev/dc/if_dcreg.h b/freebsd/sys/dev/dc/if_dcreg.h
index b918ce49..0a61b7d1 100644
--- a/freebsd/sys/dev/dc/if_dcreg.h
+++ b/freebsd/sys/dev/dc/if_dcreg.h
@@ -36,23 +36,23 @@
* 21143 and clone common register definitions.
*/
-#define DC_BUSCTL 0x00 /* bus control */
-#define DC_TXSTART 0x08 /* tx start demand */
-#define DC_RXSTART 0x10 /* rx start demand */
-#define DC_RXADDR 0x18 /* rx descriptor list start addr */
-#define DC_TXADDR 0x20 /* tx descriptor list start addr */
-#define DC_ISR 0x28 /* interrupt status register */
-#define DC_NETCFG 0x30 /* network config register */
-#define DC_IMR 0x38 /* interrupt mask */
-#define DC_FRAMESDISCARDED 0x40 /* # of discarded frames */
-#define DC_SIO 0x48 /* MII and ROM/EEPROM access */
-#define DC_ROM 0x50 /* ROM programming address */
-#define DC_TIMER 0x58 /* general timer */
-#define DC_10BTSTAT 0x60 /* SIA status */
-#define DC_SIARESET 0x68 /* SIA connectivity */
-#define DC_10BTCTRL 0x70 /* SIA transmit and receive */
-#define DC_WATCHDOG 0x78 /* SIA and general purpose port */
-#define DC_SIAGP 0x78 /* SIA and general purpose port (X3201) */
+#define DC_BUSCTL 0x00 /* bus control */
+#define DC_TXSTART 0x08 /* tx start demand */
+#define DC_RXSTART 0x10 /* rx start demand */
+#define DC_RXADDR 0x18 /* rx descriptor list start addr */
+#define DC_TXADDR 0x20 /* tx descriptor list start addr */
+#define DC_ISR 0x28 /* interrupt status register */
+#define DC_NETCFG 0x30 /* network config register */
+#define DC_IMR 0x38 /* interrupt mask */
+#define DC_FRAMESDISCARDED 0x40 /* # of discarded frames */
+#define DC_SIO 0x48 /* MII and ROM/EEPROM access */
+#define DC_ROM 0x50 /* ROM programming address */
+#define DC_TIMER 0x58 /* general timer */
+#define DC_10BTSTAT 0x60 /* SIA status */
+#define DC_SIARESET 0x68 /* SIA connectivity */
+#define DC_10BTCTRL 0x70 /* SIA transmit and receive */
+#define DC_WATCHDOG 0x78 /* SIA and general purpose port */
+#define DC_SIAGP 0x78 /* SIA and general purpose port (X3201) */
/*
* There are two general 'types' of MX chips that we need to be
@@ -64,437 +64,453 @@
* 'magic' numbers we write to CSR16. The PNIC II falls into the
* 98713A/98715/98715A/98725 category.
*/
-#define DC_TYPE_98713 0x1
-#define DC_TYPE_98713A 0x2
-#define DC_TYPE_987x5 0x3
+#define DC_TYPE_98713 0x1
+#define DC_TYPE_98713A 0x2
+#define DC_TYPE_987x5 0x3
/* Other type of supported chips. */
-#define DC_TYPE_21143 0x4 /* Intel 21143 */
-#define DC_TYPE_ASIX 0x5 /* ASIX AX88140A/AX88141 */
-#define DC_TYPE_AL981 0x6 /* ADMtek AL981 Comet */
-#define DC_TYPE_AN983 0x7 /* ADMtek AN983 Centaur */
-#define DC_TYPE_DM9102 0x8 /* Davicom DM9102 */
-#define DC_TYPE_PNICII 0x9 /* 82c115 PNIC II */
-#define DC_TYPE_PNIC 0xA /* 82c168/82c169 PNIC I */
+#define DC_TYPE_21143 0x4 /* Intel 21143 */
+#define DC_TYPE_ASIX 0x5 /* ASIX AX88140A/AX88141 */
+#define DC_TYPE_AL981 0x6 /* ADMtek AL981 Comet */
+#define DC_TYPE_AN983 0x7 /* ADMtek AN983 Centaur */
+#define DC_TYPE_DM9102 0x8 /* Davicom DM9102 */
+#define DC_TYPE_PNICII 0x9 /* 82c115 PNIC II */
+#define DC_TYPE_PNIC 0xA /* 82c168/82c169 PNIC I */
#define DC_TYPE_XIRCOM 0xB /* Xircom X3201 */
-#define DC_TYPE_CONEXANT 0xC /* Conexant LANfinity RS7112 */
+#define DC_TYPE_CONEXANT 0xC /* Conexant LANfinity RS7112 */
+#define DC_TYPE_ULI_M5261 0xD /* ALi/ULi M5261 */
+#define DC_TYPE_ULI_M5263 0xE /* ALi/ULi M5263 */
-#define DC_IS_MACRONIX(x) \
+#define DC_IS_MACRONIX(x) \
(x->dc_type == DC_TYPE_98713 || \
x->dc_type == DC_TYPE_98713A || \
x->dc_type == DC_TYPE_987x5)
-#define DC_IS_ADMTEK(x) \
+#define DC_IS_ADMTEK(x) \
(x->dc_type == DC_TYPE_AL981 || \
x->dc_type == DC_TYPE_AN983)
-#define DC_IS_INTEL(x) (x->dc_type == DC_TYPE_21143)
-#define DC_IS_ASIX(x) (x->dc_type == DC_TYPE_ASIX)
-#define DC_IS_COMET(x) (x->dc_type == DC_TYPE_AL981)
-#define DC_IS_CENTAUR(x) (x->dc_type == DC_TYPE_AN983)
-#define DC_IS_DAVICOM(x) (x->dc_type == DC_TYPE_DM9102)
-#define DC_IS_PNICII(x) (x->dc_type == DC_TYPE_PNICII)
-#define DC_IS_PNIC(x) (x->dc_type == DC_TYPE_PNIC)
+#define DC_IS_ULI(x) \
+ (x->dc_type == DC_TYPE_ULI_M5261 || \
+ x->dc_type == DC_TYPE_ULI_M5263)
+
+#define DC_IS_INTEL(x) (x->dc_type == DC_TYPE_21143)
+#define DC_IS_ASIX(x) (x->dc_type == DC_TYPE_ASIX)
+#define DC_IS_COMET(x) (x->dc_type == DC_TYPE_AL981)
+#define DC_IS_CENTAUR(x) (x->dc_type == DC_TYPE_AN983)
+#define DC_IS_DAVICOM(x) (x->dc_type == DC_TYPE_DM9102)
+#define DC_IS_PNICII(x) (x->dc_type == DC_TYPE_PNICII)
+#define DC_IS_PNIC(x) (x->dc_type == DC_TYPE_PNIC)
#define DC_IS_XIRCOM(x) (x->dc_type == DC_TYPE_XIRCOM)
-#define DC_IS_CONEXANT(x) (x->dc_type == DC_TYPE_CONEXANT)
+#define DC_IS_CONEXANT(x) (x->dc_type == DC_TYPE_CONEXANT)
/* MII/symbol mode port types */
-#define DC_PMODE_MII 0x1
-#define DC_PMODE_SYM 0x2
-#define DC_PMODE_SIA 0x3
+#define DC_PMODE_MII 0x1
+#define DC_PMODE_SYM 0x2
+#define DC_PMODE_SIA 0x3
/*
* Bus control bits.
*/
-#define DC_BUSCTL_RESET 0x00000001
-#define DC_BUSCTL_ARBITRATION 0x00000002
-#define DC_BUSCTL_SKIPLEN 0x0000007C
-#define DC_BUSCTL_BUF_BIGENDIAN 0x00000080
-#define DC_BUSCTL_BURSTLEN 0x00003F00
-#define DC_BUSCTL_CACHEALIGN 0x0000C000
-#define DC_BUSCTL_TXPOLL 0x000E0000
-#define DC_BUSCTL_DBO 0x00100000
-#define DC_BUSCTL_MRME 0x00200000
-#define DC_BUSCTL_MRLE 0x00800000
-#define DC_BUSCTL_MWIE 0x01000000
-#define DC_BUSCTL_ONNOW_ENB 0x04000000
-
-#define DC_SKIPLEN_1LONG 0x00000004
-#define DC_SKIPLEN_2LONG 0x00000008
-#define DC_SKIPLEN_3LONG 0x00000010
-#define DC_SKIPLEN_4LONG 0x00000020
-#define DC_SKIPLEN_5LONG 0x00000040
-
-#define DC_CACHEALIGN_NONE 0x00000000
-#define DC_CACHEALIGN_8LONG 0x00004000
-#define DC_CACHEALIGN_16LONG 0x00008000
-#define DC_CACHEALIGN_32LONG 0x0000C000
-
-#define DC_BURSTLEN_USECA 0x00000000
-#define DC_BURSTLEN_1LONG 0x00000100
-#define DC_BURSTLEN_2LONG 0x00000200
-#define DC_BURSTLEN_4LONG 0x00000400
-#define DC_BURSTLEN_8LONG 0x00000800
-#define DC_BURSTLEN_16LONG 0x00001000
-#define DC_BURSTLEN_32LONG 0x00002000
-
-#define DC_TXPOLL_OFF 0x00000000
-#define DC_TXPOLL_1 0x00020000
-#define DC_TXPOLL_2 0x00040000
-#define DC_TXPOLL_3 0x00060000
-#define DC_TXPOLL_4 0x00080000
-#define DC_TXPOLL_5 0x000A0000
-#define DC_TXPOLL_6 0x000C0000
-#define DC_TXPOLL_7 0x000E0000
+#define DC_BUSCTL_RESET 0x00000001
+#define DC_BUSCTL_ARBITRATION 0x00000002
+#define DC_BUSCTL_SKIPLEN 0x0000007C
+#define DC_BUSCTL_BUF_BIGENDIAN 0x00000080
+#define DC_BUSCTL_BURSTLEN 0x00003F00
+#define DC_BUSCTL_CACHEALIGN 0x0000C000
+#define DC_BUSCTL_TXPOLL 0x000E0000
+#define DC_BUSCTL_DBO 0x00100000
+#define DC_BUSCTL_MRME 0x00200000
+#define DC_BUSCTL_MRLE 0x00800000
+#define DC_BUSCTL_MWIE 0x01000000
+#define DC_BUSCTL_ONNOW_ENB 0x04000000
+
+#define DC_SKIPLEN_1LONG 0x00000004
+#define DC_SKIPLEN_2LONG 0x00000008
+#define DC_SKIPLEN_3LONG 0x00000010
+#define DC_SKIPLEN_4LONG 0x00000020
+#define DC_SKIPLEN_5LONG 0x00000040
+
+#define DC_CACHEALIGN_NONE 0x00000000
+#define DC_CACHEALIGN_8LONG 0x00004000
+#define DC_CACHEALIGN_16LONG 0x00008000
+#define DC_CACHEALIGN_32LONG 0x0000C000
+
+#define DC_BURSTLEN_USECA 0x00000000
+#define DC_BURSTLEN_1LONG 0x00000100
+#define DC_BURSTLEN_2LONG 0x00000200
+#define DC_BURSTLEN_4LONG 0x00000400
+#define DC_BURSTLEN_8LONG 0x00000800
+#define DC_BURSTLEN_16LONG 0x00001000
+#define DC_BURSTLEN_32LONG 0x00002000
+
+#define DC_TXPOLL_OFF 0x00000000
+#define DC_TXPOLL_1 0x00020000
+#define DC_TXPOLL_2 0x00040000
+#define DC_TXPOLL_3 0x00060000
+#define DC_TXPOLL_4 0x00080000
+#define DC_TXPOLL_5 0x000A0000
+#define DC_TXPOLL_6 0x000C0000
+#define DC_TXPOLL_7 0x000E0000
/*
* Interrupt status bits.
*/
-#define DC_ISR_TX_OK 0x00000001
-#define DC_ISR_TX_IDLE 0x00000002
-#define DC_ISR_TX_NOBUF 0x00000004
-#define DC_ISR_TX_JABBERTIMEO 0x00000008
-#define DC_ISR_LINKGOOD 0x00000010
-#define DC_ISR_TX_UNDERRUN 0x00000020
-#define DC_ISR_RX_OK 0x00000040
-#define DC_ISR_RX_NOBUF 0x00000080
-#define DC_ISR_RX_READ 0x00000100
-#define DC_ISR_RX_WATDOGTIMEO 0x00000200
-#define DC_ISR_TX_EARLY 0x00000400
-#define DC_ISR_TIMER_EXPIRED 0x00000800
-#define DC_ISR_LINKFAIL 0x00001000
-#define DC_ISR_BUS_ERR 0x00002000
-#define DC_ISR_RX_EARLY 0x00004000
-#define DC_ISR_ABNORMAL 0x00008000
-#define DC_ISR_NORMAL 0x00010000
-#define DC_ISR_RX_STATE 0x000E0000
-#define DC_ISR_TX_STATE 0x00700000
-#define DC_ISR_BUSERRTYPE 0x03800000
-#define DC_ISR_100MBPSLINK 0x08000000
-#define DC_ISR_MAGICKPACK 0x10000000
-
-#define DC_RXSTATE_STOPPED 0x00000000 /* 000 - Stopped */
-#define DC_RXSTATE_FETCH 0x00020000 /* 001 - Fetching descriptor */
-#define DC_RXSTATE_ENDCHECK 0x00040000 /* 010 - check for rx end */
-#define DC_RXSTATE_WAIT 0x00060000 /* 011 - waiting for packet */
-#define DC_RXSTATE_SUSPEND 0x00080000 /* 100 - suspend rx */
-#define DC_RXSTATE_CLOSE 0x000A0000 /* 101 - close tx desc */
-#define DC_RXSTATE_FLUSH 0x000C0000 /* 110 - flush from FIFO */
-#define DC_RXSTATE_DEQUEUE 0x000E0000 /* 111 - dequeue from FIFO */
+#define DC_ISR_TX_OK 0x00000001
+#define DC_ISR_TX_IDLE 0x00000002
+#define DC_ISR_TX_NOBUF 0x00000004
+#define DC_ISR_TX_JABBERTIMEO 0x00000008
+#define DC_ISR_LINKGOOD 0x00000010
+#define DC_ISR_TX_UNDERRUN 0x00000020
+#define DC_ISR_RX_OK 0x00000040
+#define DC_ISR_RX_NOBUF 0x00000080
+#define DC_ISR_RX_READ 0x00000100
+#define DC_ISR_RX_WATDOGTIMEO 0x00000200
+#define DC_ISR_TX_EARLY 0x00000400
+#define DC_ISR_TIMER_EXPIRED 0x00000800
+#define DC_ISR_LINKFAIL 0x00001000
+#define DC_ISR_BUS_ERR 0x00002000
+#define DC_ISR_RX_EARLY 0x00004000
+#define DC_ISR_ABNORMAL 0x00008000
+#define DC_ISR_NORMAL 0x00010000
+#define DC_ISR_RX_STATE 0x000E0000
+#define DC_ISR_TX_STATE 0x00700000
+#define DC_ISR_BUSERRTYPE 0x03800000
+#define DC_ISR_100MBPSLINK 0x08000000
+#define DC_ISR_MAGICKPACK 0x10000000
+
+#define DC_RXSTATE_STOPPED 0x00000000 /* 000 - Stopped */
+#define DC_RXSTATE_FETCH 0x00020000 /* 001 - Fetching descriptor */
+#define DC_RXSTATE_ENDCHECK 0x00040000 /* 010 - check for rx end */
+#define DC_RXSTATE_WAIT 0x00060000 /* 011 - waiting for packet */
+#define DC_RXSTATE_SUSPEND 0x00080000 /* 100 - suspend rx */
+#define DC_RXSTATE_CLOSE 0x000A0000 /* 101 - close tx desc */
+#define DC_RXSTATE_FLUSH 0x000C0000 /* 110 - flush from FIFO */
+#define DC_RXSTATE_DEQUEUE 0x000E0000 /* 111 - dequeue from FIFO */
#define DC_HAS_BROKEN_RXSTATE(x) \
(DC_IS_CENTAUR(x) || DC_IS_CONEXANT(x) || (DC_IS_DAVICOM(x) && \
pci_get_revid((x)->dc_dev) >= DC_REVISION_DM9102A))
-#define DC_TXSTATE_RESET 0x00000000 /* 000 - reset */
-#define DC_TXSTATE_FETCH 0x00100000 /* 001 - fetching descriptor */
-#define DC_TXSTATE_WAITEND 0x00200000 /* 010 - wait for tx end */
-#define DC_TXSTATE_READING 0x00300000 /* 011 - read and enqueue */
-#define DC_TXSTATE_RSVD 0x00400000 /* 100 - reserved */
-#define DC_TXSTATE_SETUP 0x00500000 /* 101 - setup packet */
-#define DC_TXSTATE_SUSPEND 0x00600000 /* 110 - suspend tx */
-#define DC_TXSTATE_CLOSE 0x00700000 /* 111 - close tx desc */
+#define DC_TXSTATE_RESET 0x00000000 /* 000 - reset */
+#define DC_TXSTATE_FETCH 0x00100000 /* 001 - fetching descriptor */
+#define DC_TXSTATE_WAITEND 0x00200000 /* 010 - wait for tx end */
+#define DC_TXSTATE_READING 0x00300000 /* 011 - read and enqueue */
+#define DC_TXSTATE_RSVD 0x00400000 /* 100 - reserved */
+#define DC_TXSTATE_SETUP 0x00500000 /* 101 - setup packet */
+#define DC_TXSTATE_SUSPEND 0x00600000 /* 110 - suspend tx */
+#define DC_TXSTATE_CLOSE 0x00700000 /* 111 - close tx desc */
/*
* Network config bits.
*/
-#define DC_NETCFG_RX_HASHPERF 0x00000001
-#define DC_NETCFG_RX_ON 0x00000002
-#define DC_NETCFG_RX_HASHONLY 0x00000004
-#define DC_NETCFG_RX_BADFRAMES 0x00000008
-#define DC_NETCFG_RX_INVFILT 0x00000010
-#define DC_NETCFG_BACKOFFCNT 0x00000020
-#define DC_NETCFG_RX_PROMISC 0x00000040
-#define DC_NETCFG_RX_ALLMULTI 0x00000080
-#define DC_NETCFG_FULLDUPLEX 0x00000200
-#define DC_NETCFG_LOOPBACK 0x00000C00
-#define DC_NETCFG_FORCECOLL 0x00001000
-#define DC_NETCFG_TX_ON 0x00002000
-#define DC_NETCFG_TX_THRESH 0x0000C000
-#define DC_NETCFG_TX_BACKOFF 0x00020000
-#define DC_NETCFG_PORTSEL 0x00040000 /* 0 == 10, 1 == 100 */
-#define DC_NETCFG_HEARTBEAT 0x00080000
-#define DC_NETCFG_STORENFWD 0x00200000
-#define DC_NETCFG_SPEEDSEL 0x00400000 /* 1 == 10, 0 == 100 */
-#define DC_NETCFG_PCS 0x00800000
-#define DC_NETCFG_SCRAMBLER 0x01000000
-#define DC_NETCFG_NO_RXCRC 0x02000000
-#define DC_NETCFG_RX_ALL 0x40000000
-#define DC_NETCFG_CAPEFFECT 0x80000000
-
-#define DC_OPMODE_NORM 0x00000000
-#define DC_OPMODE_INTLOOP 0x00000400
-#define DC_OPMODE_EXTLOOP 0x00000800
+#define DC_NETCFG_RX_HASHPERF 0x00000001
+#define DC_NETCFG_RX_ON 0x00000002
+#define DC_NETCFG_RX_HASHONLY 0x00000004
+#define DC_NETCFG_RX_BADFRAMES 0x00000008
+#define DC_NETCFG_RX_INVFILT 0x00000010
+#define DC_NETCFG_BACKOFFCNT 0x00000020
+#define DC_NETCFG_RX_PROMISC 0x00000040
+#define DC_NETCFG_RX_ALLMULTI 0x00000080
+#define DC_NETCFG_FULLDUPLEX 0x00000200
+#define DC_NETCFG_LOOPBACK 0x00000C00
+#define DC_NETCFG_FORCECOLL 0x00001000
+#define DC_NETCFG_TX_ON 0x00002000
+#define DC_NETCFG_TX_THRESH 0x0000C000
+#define DC_NETCFG_TX_BACKOFF 0x00020000
+#define DC_NETCFG_PORTSEL 0x00040000 /* 0 == 10, 1 == 100 */
+#define DC_NETCFG_HEARTBEAT 0x00080000
+#define DC_NETCFG_STORENFWD 0x00200000
+#define DC_NETCFG_SPEEDSEL 0x00400000 /* 1 == 10, 0 == 100 */
+#define DC_NETCFG_PCS 0x00800000
+#define DC_NETCFG_SCRAMBLER 0x01000000
+#define DC_NETCFG_NO_RXCRC 0x02000000
+#define DC_NETCFG_RX_ALL 0x40000000
+#define DC_NETCFG_CAPEFFECT 0x80000000
+
+#define DC_OPMODE_NORM 0x00000000
+#define DC_OPMODE_INTLOOP 0x00000400
+#define DC_OPMODE_EXTLOOP 0x00000800
#if 0
-#define DC_TXTHRESH_72BYTES 0x00000000
-#define DC_TXTHRESH_96BYTES 0x00004000
-#define DC_TXTHRESH_128BYTES 0x00008000
-#define DC_TXTHRESH_160BYTES 0x0000C000
+#define DC_TXTHRESH_72BYTES 0x00000000
+#define DC_TXTHRESH_96BYTES 0x00004000
+#define DC_TXTHRESH_128BYTES 0x00008000
+#define DC_TXTHRESH_160BYTES 0x0000C000
#endif
-#define DC_TXTHRESH_MIN 0x00000000
-#define DC_TXTHRESH_INC 0x00004000
-#define DC_TXTHRESH_MAX 0x0000C000
+#define DC_TXTHRESH_MIN 0x00000000
+#define DC_TXTHRESH_INC 0x00004000
+#define DC_TXTHRESH_MAX 0x0000C000
/*
* Interrupt mask bits.
*/
-#define DC_IMR_TX_OK 0x00000001
-#define DC_IMR_TX_IDLE 0x00000002
-#define DC_IMR_TX_NOBUF 0x00000004
-#define DC_IMR_TX_JABBERTIMEO 0x00000008
-#define DC_IMR_LINKGOOD 0x00000010
-#define DC_IMR_TX_UNDERRUN 0x00000020
-#define DC_IMR_RX_OK 0x00000040
-#define DC_IMR_RX_NOBUF 0x00000080
-#define DC_IMR_RX_READ 0x00000100
-#define DC_IMR_RX_WATDOGTIMEO 0x00000200
-#define DC_IMR_TX_EARLY 0x00000400
-#define DC_IMR_TIMER_EXPIRED 0x00000800
-#define DC_IMR_LINKFAIL 0x00001000
-#define DC_IMR_BUS_ERR 0x00002000
-#define DC_IMR_RX_EARLY 0x00004000
-#define DC_IMR_ABNORMAL 0x00008000
-#define DC_IMR_NORMAL 0x00010000
-#define DC_IMR_100MBPSLINK 0x08000000
-#define DC_IMR_MAGICKPACK 0x10000000
-
-#define DC_INTRS \
+#define DC_IMR_TX_OK 0x00000001
+#define DC_IMR_TX_IDLE 0x00000002
+#define DC_IMR_TX_NOBUF 0x00000004
+#define DC_IMR_TX_JABBERTIMEO 0x00000008
+#define DC_IMR_LINKGOOD 0x00000010
+#define DC_IMR_TX_UNDERRUN 0x00000020
+#define DC_IMR_RX_OK 0x00000040
+#define DC_IMR_RX_NOBUF 0x00000080
+#define DC_IMR_RX_READ 0x00000100
+#define DC_IMR_RX_WATDOGTIMEO 0x00000200
+#define DC_IMR_TX_EARLY 0x00000400
+#define DC_IMR_TIMER_EXPIRED 0x00000800
+#define DC_IMR_LINKFAIL 0x00001000
+#define DC_IMR_BUS_ERR 0x00002000
+#define DC_IMR_RX_EARLY 0x00004000
+#define DC_IMR_ABNORMAL 0x00008000
+#define DC_IMR_NORMAL 0x00010000
+#define DC_IMR_100MBPSLINK 0x08000000
+#define DC_IMR_MAGICKPACK 0x10000000
+
+#define DC_INTRS \
(DC_IMR_RX_OK|DC_IMR_TX_OK|DC_IMR_RX_NOBUF|DC_IMR_RX_WATDOGTIMEO|\
DC_IMR_TX_NOBUF|DC_IMR_TX_UNDERRUN|DC_IMR_BUS_ERR| \
DC_IMR_ABNORMAL|DC_IMR_NORMAL/*|DC_IMR_TX_EARLY*/)
/*
* Serial I/O (EEPROM/ROM) bits.
*/
-#define DC_SIO_EE_CS 0x00000001 /* EEPROM chip select */
-#define DC_SIO_EE_CLK 0x00000002 /* EEPROM clock */
-#define DC_SIO_EE_DATAIN 0x00000004 /* EEPROM data output */
-#define DC_SIO_EE_DATAOUT 0x00000008 /* EEPROM data input */
-#define DC_SIO_ROMDATA4 0x00000010
-#define DC_SIO_ROMDATA5 0x00000020
-#define DC_SIO_ROMDATA6 0x00000040
-#define DC_SIO_ROMDATA7 0x00000080
-#define DC_SIO_EESEL 0x00000800
-#define DC_SIO_ROMSEL 0x00001000
-#define DC_SIO_ROMCTL_WRITE 0x00002000
-#define DC_SIO_ROMCTL_READ 0x00004000
-#define DC_SIO_MII_CLK 0x00010000 /* MDIO clock */
-#define DC_SIO_MII_DATAOUT 0x00020000 /* MDIO data out */
-#define DC_SIO_MII_DIR 0x00040000 /* MDIO dir */
-#define DC_SIO_MII_DATAIN 0x00080000 /* MDIO data in */
-
-#define DC_EECMD_WRITE 0x140
-#define DC_EECMD_READ 0x180
-#define DC_EECMD_ERASE 0x1c0
-
-#define DC_EE_NODEADDR_OFFSET 0x70
-#define DC_EE_NODEADDR 10
+#define DC_SIO_EE_CS 0x00000001 /* EEPROM chip select */
+#define DC_SIO_EE_CLK 0x00000002 /* EEPROM clock */
+#define DC_SIO_EE_DATAIN 0x00000004 /* EEPROM data output */
+#define DC_SIO_EE_DATAOUT 0x00000008 /* EEPROM data input */
+#define DC_SIO_ROMDATA4 0x00000010
+#define DC_SIO_ROMDATA5 0x00000020
+#define DC_SIO_ROMDATA6 0x00000040
+#define DC_SIO_ROMDATA7 0x00000080
+#define DC_SIO_EESEL 0x00000800
+#define DC_SIO_ROMSEL 0x00001000
+#define DC_SIO_ROMCTL_WRITE 0x00002000
+#define DC_SIO_ROMCTL_READ 0x00004000
+#define DC_SIO_MII_CLK 0x00010000 /* MDIO clock */
+#define DC_SIO_MII_DATAOUT 0x00020000 /* MDIO data out */
+#define DC_SIO_MII_DIR 0x00040000 /* MDIO dir */
+#define DC_SIO_MII_DATAIN 0x00080000 /* MDIO data in */
+
+#define DC_EECMD_WRITE 0x140
+#define DC_EECMD_READ 0x180
+#define DC_EECMD_ERASE 0x1c0
+
+#define DC_EE_NODEADDR_OFFSET 0x70
+#define DC_EE_NODEADDR 10
/*
* General purpose timer register
*/
-#define DC_TIMER_VALUE 0x0000FFFF
-#define DC_TIMER_CONTINUOUS 0x00010000
+#define DC_TIMER_VALUE 0x0000FFFF
+#define DC_TIMER_CONTINUOUS 0x00010000
/*
* 10baseT status register
*/
-#define DC_TSTAT_MIIACT 0x00000001 /* MII port activity */
-#define DC_TSTAT_LS100 0x00000002 /* link status of 100baseTX */
-#define DC_TSTAT_LS10 0x00000004 /* link status of 10baseT */
-#define DC_TSTAT_AUTOPOLARITY 0x00000008
-#define DC_TSTAT_AUIACT 0x00000100 /* AUI activity */
-#define DC_TSTAT_10BTACT 0x00000200 /* 10baseT activity */
-#define DC_TSTAT_NSN 0x00000400 /* non-stable FLPs detected */
-#define DC_TSTAT_REMFAULT 0x00000800
-#define DC_TSTAT_ANEGSTAT 0x00007000
-#define DC_TSTAT_LP_CAN_NWAY 0x00008000 /* link partner supports NWAY */
-#define DC_TSTAT_LPCODEWORD 0xFFFF0000 /* link partner's code word */
-
-#define DC_ASTAT_DISABLE 0x00000000
-#define DC_ASTAT_TXDISABLE 0x00001000
-#define DC_ASTAT_ABDETECT 0x00002000
-#define DC_ASTAT_ACKDETECT 0x00003000
-#define DC_ASTAT_CMPACKDETECT 0x00004000
-#define DC_ASTAT_AUTONEGCMP 0x00005000
-#define DC_ASTAT_LINKCHECK 0x00006000
+#define DC_TSTAT_MIIACT 0x00000001 /* MII port activity */
+#define DC_TSTAT_LS100 0x00000002 /* link status of 100baseTX */
+#define DC_TSTAT_LS10 0x00000004 /* link status of 10baseT */
+#define DC_TSTAT_AUTOPOLARITY 0x00000008
+#define DC_TSTAT_AUIACT 0x00000100 /* AUI activity */
+#define DC_TSTAT_10BTACT 0x00000200 /* 10baseT activity */
+#define DC_TSTAT_NSN 0x00000400 /* non-stable FLPs detected */
+#define DC_TSTAT_REMFAULT 0x00000800
+#define DC_TSTAT_ANEGSTAT 0x00007000
+#define DC_TSTAT_LP_CAN_NWAY 0x00008000 /* link partner supports NWAY */
+#define DC_TSTAT_LPCODEWORD 0xFFFF0000 /* link partner's code word */
+
+#define DC_ASTAT_DISABLE 0x00000000
+#define DC_ASTAT_TXDISABLE 0x00001000
+#define DC_ASTAT_ABDETECT 0x00002000
+#define DC_ASTAT_ACKDETECT 0x00003000
+#define DC_ASTAT_CMPACKDETECT 0x00004000
+#define DC_ASTAT_AUTONEGCMP 0x00005000
+#define DC_ASTAT_LINKCHECK 0x00006000
/*
* PHY reset register
*/
-#define DC_SIA_RESET 0x00000001
-#define DC_SIA_AUI 0x00000008 /* AUI or 10baseT */
+#define DC_SIA_RESET 0x00000001
+#define DC_SIA_AUI 0x00000008 /* AUI or 10baseT */
/*
* 10baseT control register
*/
-#define DC_TCTL_ENCODER_ENB 0x00000001
-#define DC_TCTL_LOOPBACK 0x00000002
-#define DC_TCTL_DRIVER_ENB 0x00000004
-#define DC_TCTL_LNKPULSE_ENB 0x00000008
-#define DC_TCTL_HALFDUPLEX 0x00000040
-#define DC_TCTL_AUTONEGENBL 0x00000080
-#define DC_TCTL_RX_SQUELCH 0x00000100
-#define DC_TCTL_COLL_SQUELCH 0x00000200
-#define DC_TCTL_COLL_DETECT 0x00000400
-#define DC_TCTL_SQE_ENB 0x00000800
-#define DC_TCTL_LINKTEST 0x00001000
-#define DC_TCTL_AUTOPOLARITY 0x00002000
-#define DC_TCTL_SET_POL_PLUS 0x00004000
-#define DC_TCTL_AUTOSENSE 0x00008000 /* 10bt/AUI autosense */
-#define DC_TCTL_100BTXHALF 0x00010000
-#define DC_TCTL_100BTXFULL 0x00020000
-#define DC_TCTL_100BT4 0x00040000
+#define DC_TCTL_ENCODER_ENB 0x00000001
+#define DC_TCTL_LOOPBACK 0x00000002
+#define DC_TCTL_DRIVER_ENB 0x00000004
+#define DC_TCTL_LNKPULSE_ENB 0x00000008
+#define DC_TCTL_HALFDUPLEX 0x00000040
+#define DC_TCTL_AUTONEGENBL 0x00000080
+#define DC_TCTL_RX_SQUELCH 0x00000100
+#define DC_TCTL_COLL_SQUELCH 0x00000200
+#define DC_TCTL_COLL_DETECT 0x00000400
+#define DC_TCTL_SQE_ENB 0x00000800
+#define DC_TCTL_LINKTEST 0x00001000
+#define DC_TCTL_AUTOPOLARITY 0x00002000
+#define DC_TCTL_SET_POL_PLUS 0x00004000
+#define DC_TCTL_AUTOSENSE 0x00008000 /* 10bt/AUI autosense */
+#define DC_TCTL_100BTXHALF 0x00010000
+#define DC_TCTL_100BTXFULL 0x00020000
+#define DC_TCTL_100BT4 0x00040000
/*
* Watchdog timer register
*/
-#define DC_WDOG_JABBERDIS 0x00000001
-#define DC_WDOG_HOSTUNJAB 0x00000002
-#define DC_WDOG_JABBERCLK 0x00000004
-#define DC_WDOG_RXWDOGDIS 0x00000010
-#define DC_WDOG_RXWDOGCLK 0x00000020
-#define DC_WDOG_MUSTBEZERO 0x00000100
-#define DC_WDOG_AUIBNC 0x00100000
-#define DC_WDOG_ACTIVITY 0x00200000
-#define DC_WDOG_RX_MATCH 0x00400000
-#define DC_WDOG_LINK 0x00800000
-#define DC_WDOG_CTLWREN 0x08000000
+#define DC_WDOG_JABBERDIS 0x00000001
+#define DC_WDOG_HOSTUNJAB 0x00000002
+#define DC_WDOG_JABBERCLK 0x00000004
+#define DC_WDOG_RXWDOGDIS 0x00000010
+#define DC_WDOG_RXWDOGCLK 0x00000020
+#define DC_WDOG_MUSTBEZERO 0x00000100
+#define DC_WDOG_AUIBNC 0x00100000
+#define DC_WDOG_ACTIVITY 0x00200000
+#define DC_WDOG_RX_MATCH 0x00400000
+#define DC_WDOG_LINK 0x00800000
+#define DC_WDOG_CTLWREN 0x08000000
/*
* SIA and General Purpose Port register (X3201)
*/
-#define DC_SIAGP_RXMATCH 0x40000000
-#define DC_SIAGP_INT1 0x20000000
-#define DC_SIAGP_INT0 0x10000000
-#define DC_SIAGP_WRITE_EN 0x08000000
-#define DC_SIAGP_RXMATCH_EN 0x04000000
-#define DC_SIAGP_INT1_EN 0x02000000
-#define DC_SIAGP_INT0_EN 0x01000000
-#define DC_SIAGP_LED3 0x00800000
-#define DC_SIAGP_LED2 0x00400000
-#define DC_SIAGP_LED1 0x00200000
-#define DC_SIAGP_LED0 0x00100000
-#define DC_SIAGP_MD_GP3_OUTPUT 0x00080000
-#define DC_SIAGP_MD_GP2_OUTPUT 0x00040000
-#define DC_SIAGP_MD_GP1_OUTPUT 0x00020000
-#define DC_SIAGP_MD_GP0_OUTPUT 0x00010000
+#define DC_SIAGP_RXMATCH 0x40000000
+#define DC_SIAGP_INT1 0x20000000
+#define DC_SIAGP_INT0 0x10000000
+#define DC_SIAGP_WRITE_EN 0x08000000
+#define DC_SIAGP_RXMATCH_EN 0x04000000
+#define DC_SIAGP_INT1_EN 0x02000000
+#define DC_SIAGP_INT0_EN 0x01000000
+#define DC_SIAGP_LED3 0x00800000
+#define DC_SIAGP_LED2 0x00400000
+#define DC_SIAGP_LED1 0x00200000
+#define DC_SIAGP_LED0 0x00100000
+#define DC_SIAGP_MD_GP3_OUTPUT 0x00080000
+#define DC_SIAGP_MD_GP2_OUTPUT 0x00040000
+#define DC_SIAGP_MD_GP1_OUTPUT 0x00020000
+#define DC_SIAGP_MD_GP0_OUTPUT 0x00010000
/*
* Size of a setup frame.
*/
-#define DC_SFRAME_LEN 192
+#define DC_SFRAME_LEN 192
/*
* 21x4x TX/RX list structure.
*/
struct dc_desc {
- u_int32_t dc_status;
- u_int32_t dc_ctl;
- u_int32_t dc_ptr1;
- u_int32_t dc_ptr2;
+ uint32_t dc_status;
+ uint32_t dc_ctl;
+ uint32_t dc_ptr1;
+ uint32_t dc_ptr2;
};
-#define dc_data dc_ptr1
-#define dc_next dc_ptr2
-
-#define DC_RXSTAT_FIFOOFLOW 0x00000001
-#define DC_RXSTAT_CRCERR 0x00000002
-#define DC_RXSTAT_DRIBBLE 0x00000004
-#define DC_RXSTAT_MIIERE 0x00000008
-#define DC_RXSTAT_WATCHDOG 0x00000010
-#define DC_RXSTAT_FRAMETYPE 0x00000020 /* 0 == IEEE 802.3 */
-#define DC_RXSTAT_COLLSEEN 0x00000040
-#define DC_RXSTAT_GIANT 0x00000080
-#define DC_RXSTAT_LASTFRAG 0x00000100
-#define DC_RXSTAT_FIRSTFRAG 0x00000200
-#define DC_RXSTAT_MULTICAST 0x00000400
-#define DC_RXSTAT_RUNT 0x00000800
-#define DC_RXSTAT_RXTYPE 0x00003000
-#define DC_RXSTAT_DE 0x00004000
-#define DC_RXSTAT_RXERR 0x00008000
-#define DC_RXSTAT_RXLEN 0x3FFF0000
-#define DC_RXSTAT_OWN 0x80000000
-
-#define DC_RXBYTES(x) ((x & DC_RXSTAT_RXLEN) >> 16)
-#define DC_RXSTAT (DC_RXSTAT_FIRSTFRAG|DC_RXSTAT_LASTFRAG|DC_RXSTAT_OWN)
-
-#define DC_RXCTL_BUFLEN1 0x00000FFF
-#define DC_RXCTL_BUFLEN2 0x00FFF000
-#define DC_RXCTL_RLINK 0x01000000
-#define DC_RXCTL_RLAST 0x02000000
-
-#define DC_TXSTAT_DEFER 0x00000001
-#define DC_TXSTAT_UNDERRUN 0x00000002
-#define DC_TXSTAT_LINKFAIL 0x00000003
-#define DC_TXSTAT_COLLCNT 0x00000078
-#define DC_TXSTAT_SQE 0x00000080
-#define DC_TXSTAT_EXCESSCOLL 0x00000100
-#define DC_TXSTAT_LATECOLL 0x00000200
-#define DC_TXSTAT_NOCARRIER 0x00000400
-#define DC_TXSTAT_CARRLOST 0x00000800
-#define DC_TXSTAT_JABTIMEO 0x00004000
-#define DC_TXSTAT_ERRSUM 0x00008000
-#define DC_TXSTAT_OWN 0x80000000
-
-#define DC_TXCTL_BUFLEN1 0x000007FF
-#define DC_TXCTL_BUFLEN2 0x003FF800
-#define DC_TXCTL_FILTTYPE0 0x00400000
-#define DC_TXCTL_PAD 0x00800000
-#define DC_TXCTL_TLINK 0x01000000
-#define DC_TXCTL_TLAST 0x02000000
-#define DC_TXCTL_NOCRC 0x04000000
-#define DC_TXCTL_SETUP 0x08000000
-#define DC_TXCTL_FILTTYPE1 0x10000000
-#define DC_TXCTL_FIRSTFRAG 0x20000000
-#define DC_TXCTL_LASTFRAG 0x40000000
-#define DC_TXCTL_FINT 0x80000000
-
-#define DC_FILTER_PERFECT 0x00000000
-#define DC_FILTER_HASHPERF 0x00400000
-#define DC_FILTER_INVERSE 0x10000000
-#define DC_FILTER_HASHONLY 0x10400000
-
-#define DC_MAXFRAGS 16
+#define dc_data dc_ptr1
+#define dc_next dc_ptr2
+
+#define DC_RXSTAT_FIFOOFLOW 0x00000001
+#define DC_RXSTAT_CRCERR 0x00000002
+#define DC_RXSTAT_DRIBBLE 0x00000004
+#define DC_RXSTAT_MIIERE 0x00000008
+#define DC_RXSTAT_WATCHDOG 0x00000010
+#define DC_RXSTAT_FRAMETYPE 0x00000020 /* 0 == IEEE 802.3 */
+#define DC_RXSTAT_COLLSEEN 0x00000040
+#define DC_RXSTAT_GIANT 0x00000080
+#define DC_RXSTAT_LASTFRAG 0x00000100
+#define DC_RXSTAT_FIRSTFRAG 0x00000200
+#define DC_RXSTAT_MULTICAST 0x00000400
+#define DC_RXSTAT_RUNT 0x00000800
+#define DC_RXSTAT_RXTYPE 0x00003000
+#define DC_RXSTAT_DE 0x00004000
+#define DC_RXSTAT_RXERR 0x00008000
+#define DC_RXSTAT_RXLEN 0x3FFF0000
+#define DC_RXSTAT_OWN 0x80000000
+
+#define DC_RXBYTES(x) ((x & DC_RXSTAT_RXLEN) >> 16)
+#define DC_RXSTAT (DC_RXSTAT_FIRSTFRAG|DC_RXSTAT_LASTFRAG|DC_RXSTAT_OWN)
+
+#define DC_RXCTL_BUFLEN1 0x00000FFF
+#define DC_RXCTL_BUFLEN2 0x00FFF000
+#define DC_RXCTL_RLINK 0x01000000
+#define DC_RXCTL_RLAST 0x02000000
+
+#define DC_TXSTAT_DEFER 0x00000001
+#define DC_TXSTAT_UNDERRUN 0x00000002
+#define DC_TXSTAT_LINKFAIL 0x00000003
+#define DC_TXSTAT_COLLCNT 0x00000078
+#define DC_TXSTAT_SQE 0x00000080
+#define DC_TXSTAT_EXCESSCOLL 0x00000100
+#define DC_TXSTAT_LATECOLL 0x00000200
+#define DC_TXSTAT_NOCARRIER 0x00000400
+#define DC_TXSTAT_CARRLOST 0x00000800
+#define DC_TXSTAT_JABTIMEO 0x00004000
+#define DC_TXSTAT_ERRSUM 0x00008000
+#define DC_TXSTAT_OWN 0x80000000
+
+#define DC_TXCTL_BUFLEN1 0x000007FF
+#define DC_TXCTL_BUFLEN2 0x003FF800
+#define DC_TXCTL_FILTTYPE0 0x00400000
+#define DC_TXCTL_PAD 0x00800000
+#define DC_TXCTL_TLINK 0x01000000
+#define DC_TXCTL_TLAST 0x02000000
+#define DC_TXCTL_NOCRC 0x04000000
+#define DC_TXCTL_SETUP 0x08000000
+#define DC_TXCTL_FILTTYPE1 0x10000000
+#define DC_TXCTL_FIRSTFRAG 0x20000000
+#define DC_TXCTL_LASTFRAG 0x40000000
+#define DC_TXCTL_FINT 0x80000000
+
+#define DC_FILTER_PERFECT 0x00000000
+#define DC_FILTER_HASHPERF 0x00400000
+#define DC_FILTER_INVERSE 0x10000000
+#define DC_FILTER_HASHONLY 0x10400000
+
+#define DC_MAXFRAGS 16
#ifdef DEVICE_POLLING
-#define DC_RX_LIST_CNT 192
+#define DC_RX_LIST_CNT 192
#else
-#define DC_RX_LIST_CNT 64
+#define DC_RX_LIST_CNT 64
#endif
-#define DC_TX_LIST_CNT 256
-#define DC_TX_LIST_RSVD 5
-#define DC_MIN_FRAMELEN 60
-#define DC_RXLEN 1536
+#define DC_TX_LIST_CNT 256
+#define DC_TX_LIST_RSVD 5
+#define DC_MIN_FRAMELEN 60
+#define DC_RXLEN 1536
-#define DC_INC(x, y) (x) = (x + 1) % y
+#define DC_INC(x, y) (x) = (x + 1) % y
+
+#define DC_LIST_ALIGN (sizeof(struct dc_desc))
+#define DC_RXBUF_ALIGN 4
/* Macros to easily get the DMA address of a descriptor. */
-#define DC_RXDESC(sc, i) (sc->dc_laddr + \
- (uintptr_t)(sc->dc_ldata->dc_rx_list + i) - (uintptr_t)sc->dc_ldata)
-#define DC_TXDESC(sc, i) (sc->dc_laddr + \
- (uintptr_t)(sc->dc_ldata->dc_tx_list + i) - (uintptr_t)sc->dc_ldata)
+#define DC_ADDR_LO(x) ((uint64_t)(x) & 0xFFFFFFFF)
+#define DC_RXDESC(sc, i) \
+ (DC_ADDR_LO(sc->dc_ldata.dc_rx_list_paddr + (sizeof(struct dc_desc) * i)))
+#define DC_TXDESC(sc, i) \
+ (DC_ADDR_LO(sc->dc_ldata.dc_tx_list_paddr + (sizeof(struct dc_desc) * i)))
#if BYTE_ORDER == BIG_ENDIAN
-#define DC_SP_MAC(x) ((x) << 16)
+#define DC_SP_MAC(x) ((x) << 16)
#else
-#define DC_SP_MAC(x) (x)
+#define DC_SP_MAC(x) (x)
#endif
struct dc_list_data {
- struct dc_desc dc_rx_list[DC_RX_LIST_CNT];
- struct dc_desc dc_tx_list[DC_TX_LIST_CNT];
+ struct dc_desc *dc_rx_list;
+ bus_addr_t dc_rx_list_paddr;
+ struct dc_desc *dc_tx_list;
+ bus_addr_t dc_tx_list_paddr;
};
+#define DC_RX_LIST_SZ ((sizeof(struct dc_desc) * DC_RX_LIST_CNT))
+#define DC_TX_LIST_SZ ((sizeof(struct dc_desc) * DC_TX_LIST_CNT))
+
struct dc_chain_data {
struct mbuf *dc_rx_chain[DC_RX_LIST_CNT];
struct mbuf *dc_tx_chain[DC_TX_LIST_CNT];
bus_dmamap_t dc_rx_map[DC_RX_LIST_CNT];
bus_dmamap_t dc_tx_map[DC_TX_LIST_CNT];
- u_int32_t *dc_sbuf;
- u_int8_t dc_pad[DC_MIN_FRAMELEN];
+ uint32_t *dc_sbuf;
+ uint8_t dc_pad[DC_MIN_FRAMELEN];
+ int dc_tx_pkts;
int dc_tx_first;
int dc_tx_prod;
int dc_tx_cons;
@@ -504,39 +520,21 @@ struct dc_chain_data {
struct dc_mediainfo {
int dc_media;
- u_int8_t *dc_gp_ptr;
- u_int8_t dc_gp_len;
- u_int8_t *dc_reset_ptr;
- u_int8_t dc_reset_len;
+ uint8_t *dc_gp_ptr;
+ uint8_t dc_gp_len;
+ uint8_t *dc_reset_ptr;
+ uint8_t dc_reset_len;
struct dc_mediainfo *dc_next;
};
struct dc_type {
- u_int32_t dc_devid;
- u_int8_t dc_minrev;
- char *dc_name;
-};
-
-struct dc_mii_frame {
- u_int8_t mii_stdelim;
- u_int8_t mii_opcode;
- u_int8_t mii_phyaddr;
- u_int8_t mii_regaddr;
- u_int8_t mii_turnaround;
- u_int16_t mii_data;
+ uint32_t dc_devid;
+ uint8_t dc_minrev;
+ const char *dc_name;
};
/*
- * MII constants
- */
-#define DC_MII_STARTDELIM 0x01
-#define DC_MII_READOP 0x02
-#define DC_MII_WRITEOP 0x01
-#define DC_MII_TURNAROUND 0x02
-
-
-/*
* Registers specific to clone devices.
* This mainly relates to RX filter programming: not all 21x4x clones
* use the standard DEC filter programming mechanism.
@@ -546,42 +544,42 @@ struct dc_mii_frame {
* ADMtek specific registers and constants for the AL981 and AN983.
* The AN983 doesn't use the magic PHY registers.
*/
-#define DC_AL_CR 0x88 /* command register */
-#define DC_AL_PAR0 0xA4 /* station address */
-#define DC_AL_PAR1 0xA8 /* station address */
-#define DC_AL_MAR0 0xAC /* multicast hash filter */
-#define DC_AL_MAR1 0xB0 /* multicast hash filter */
-#define DC_AL_BMCR 0xB4 /* built in PHY control */
-#define DC_AL_BMSR 0xB8 /* built in PHY status */
-#define DC_AL_VENID 0xBC /* built in PHY ID0 */
-#define DC_AL_DEVID 0xC0 /* built in PHY ID1 */
-#define DC_AL_ANAR 0xC4 /* built in PHY autoneg advert */
-#define DC_AL_LPAR 0xC8 /* bnilt in PHY link part. ability */
-#define DC_AL_ANER 0xCC /* built in PHY autoneg expansion */
-
-#define DC_AL_CR_ATUR 0x00000001 /* automatic TX underrun recovery */
-#define DC_ADMTEK_PHYADDR 0x1
-#define DC_AL_EE_NODEADDR 4
+#define DC_AL_CR 0x88 /* command register */
+#define DC_AL_PAR0 0xA4 /* station address */
+#define DC_AL_PAR1 0xA8 /* station address */
+#define DC_AL_MAR0 0xAC /* multicast hash filter */
+#define DC_AL_MAR1 0xB0 /* multicast hash filter */
+#define DC_AL_BMCR 0xB4 /* built in PHY control */
+#define DC_AL_BMSR 0xB8 /* built in PHY status */
+#define DC_AL_VENID 0xBC /* built in PHY ID0 */
+#define DC_AL_DEVID 0xC0 /* built in PHY ID1 */
+#define DC_AL_ANAR 0xC4 /* built in PHY autoneg advert */
+#define DC_AL_LPAR 0xC8 /* bnilt in PHY link part. ability */
+#define DC_AL_ANER 0xCC /* built in PHY autoneg expansion */
+
+#define DC_AL_CR_ATUR 0x00000001 /* automatic TX underrun recovery */
+#define DC_ADMTEK_PHYADDR 0x1
+#define DC_AL_EE_NODEADDR 4
/* End of ADMtek specific registers */
/*
* ASIX specific registers.
*/
-#define DC_AX_FILTIDX 0x68 /* RX filter index */
-#define DC_AX_FILTDATA 0x70 /* RX filter data */
+#define DC_AX_FILTIDX 0x68 /* RX filter index */
+#define DC_AX_FILTDATA 0x70 /* RX filter data */
/*
* Special ASIX-specific bits in the ASIX NETCFG register (CSR6).
*/
-#define DC_AX_NETCFG_RX_BROAD 0x00000100
+#define DC_AX_NETCFG_RX_BROAD 0x00000100
/*
* RX Filter Index Register values
*/
-#define DC_AX_FILTIDX_PAR0 0x00000000
-#define DC_AX_FILTIDX_PAR1 0x00000001
-#define DC_AX_FILTIDX_MAR0 0x00000002
-#define DC_AX_FILTIDX_MAR1 0x00000003
+#define DC_AX_FILTIDX_PAR0 0x00000000
+#define DC_AX_FILTIDX_PAR1 0x00000001
+#define DC_AX_FILTIDX_MAR0 0x00000002
+#define DC_AX_FILTIDX_MAR1 0x00000003
/* End of ASIX specific registers */
/*
@@ -590,22 +588,22 @@ struct dc_mii_frame {
* a magic packet register, which we need to tweak a bit per the
* Macronix application notes.
*/
-#define DC_MX_MAGICPACKET 0x80
-#define DC_MX_NWAYSTAT 0xA0
+#define DC_MX_MAGICPACKET 0x80
+#define DC_MX_NWAYSTAT 0xA0
/*
* Magic packet register
*/
-#define DC_MX_MPACK_DISABLE 0x00400000
+#define DC_MX_MPACK_DISABLE 0x00400000
/*
* NWAY status register.
*/
-#define DC_MX_NWAY_10BTHALF 0x08000000
-#define DC_MX_NWAY_10BTFULL 0x10000000
-#define DC_MX_NWAY_100BTHALF 0x20000000
-#define DC_MX_NWAY_100BTFULL 0x40000000
-#define DC_MX_NWAY_100BT4 0x80000000
+#define DC_MX_NWAY_10BTHALF 0x08000000
+#define DC_MX_NWAY_10BTFULL 0x10000000
+#define DC_MX_NWAY_100BTHALF 0x20000000
+#define DC_MX_NWAY_100BTFULL 0x40000000
+#define DC_MX_NWAY_100BT4 0x80000000
/*
* These are magic values that must be written into CSR16
@@ -613,10 +611,10 @@ struct dc_mii_frame {
* operating mode. The magic numbers are documented in the
* Macronix 98715 application notes.
*/
-#define DC_MX_MAGIC_98713 0x0F370000
-#define DC_MX_MAGIC_98713A 0x0B3C0000
-#define DC_MX_MAGIC_98715 0x0B3C0000
-#define DC_MX_MAGIC_98725 0x0B3C0000
+#define DC_MX_MAGIC_98713 0x0F370000
+#define DC_MX_MAGIC_98713A 0x0B3C0000
+#define DC_MX_MAGIC_98715 0x0B3C0000
+#define DC_MX_MAGIC_98725 0x0B3C0000
/* End of Macronix specific registers */
/*
@@ -624,20 +622,20 @@ struct dc_mii_frame {
* The PNIC has its own special NWAY support, which doesn't work,
* and shortcut ways of reading the EEPROM and MII bus.
*/
-#define DC_PN_GPIO 0x60 /* general purpose pins control */
-#define DC_PN_PWRUP_CFG 0x90 /* config register, set by EEPROM */
-#define DC_PN_SIOCTL 0x98 /* serial EEPROM control register */
-#define DC_PN_MII 0xA0 /* MII access register */
-#define DC_PN_NWAY 0xB8 /* Internal NWAY register */
+#define DC_PN_GPIO 0x60 /* general purpose pins control */
+#define DC_PN_PWRUP_CFG 0x90 /* config register, set by EEPROM */
+#define DC_PN_SIOCTL 0x98 /* serial EEPROM control register */
+#define DC_PN_MII 0xA0 /* MII access register */
+#define DC_PN_NWAY 0xB8 /* Internal NWAY register */
/* Serial I/O EEPROM register */
-#define DC_PN_SIOCTL_DATA 0x0000003F
-#define DC_PN_SIOCTL_OPCODE 0x00000300
-#define DC_PN_SIOCTL_BUSY 0x80000000
+#define DC_PN_SIOCTL_DATA 0x0000003F
+#define DC_PN_SIOCTL_OPCODE 0x00000300
+#define DC_PN_SIOCTL_BUSY 0x80000000
-#define DC_PN_EEOPCODE_ERASE 0x00000300
-#define DC_PN_EEOPCODE_READ 0x00000600
-#define DC_PN_EEOPCODE_WRITE 0x00000100
+#define DC_PN_EEOPCODE_ERASE 0x00000300
+#define DC_PN_EEOPCODE_READ 0x00000600
+#define DC_PN_EEOPCODE_WRITE 0x00000100
/*
* The first two general purpose pins control speed selection and
@@ -646,63 +644,63 @@ struct dc_mii_frame {
* loopback bits set accordingly when changing media. Physically, this
* will set the state of a relay mounted on the card.
*/
-#define DC_PN_GPIO_DATA0 0x000000001
-#define DC_PN_GPIO_DATA1 0x000000002
-#define DC_PN_GPIO_DATA2 0x000000004
-#define DC_PN_GPIO_DATA3 0x000000008
-#define DC_PN_GPIO_CTL0 0x000000010
-#define DC_PN_GPIO_CTL1 0x000000020
-#define DC_PN_GPIO_CTL2 0x000000040
-#define DC_PN_GPIO_CTL3 0x000000080
-#define DC_PN_GPIO_SPEEDSEL DC_PN_GPIO_DATA0/* 1 == 100Mbps, 0 == 10Mbps */
-#define DC_PN_GPIO_100TX_LOOP DC_PN_GPIO_DATA1/* 1 == normal, 0 == loop */
-#define DC_PN_GPIO_BNC_ENB DC_PN_GPIO_DATA2
-#define DC_PN_GPIO_100TX_LNK DC_PN_GPIO_DATA3
-#define DC_PN_GPIO_SETBIT(sc, r) \
+#define DC_PN_GPIO_DATA0 0x000000001
+#define DC_PN_GPIO_DATA1 0x000000002
+#define DC_PN_GPIO_DATA2 0x000000004
+#define DC_PN_GPIO_DATA3 0x000000008
+#define DC_PN_GPIO_CTL0 0x000000010
+#define DC_PN_GPIO_CTL1 0x000000020
+#define DC_PN_GPIO_CTL2 0x000000040
+#define DC_PN_GPIO_CTL3 0x000000080
+#define DC_PN_GPIO_SPEEDSEL DC_PN_GPIO_DATA0/* 1 == 100Mbps, 0 == 10Mbps */
+#define DC_PN_GPIO_100TX_LOOP DC_PN_GPIO_DATA1/* 1 == normal, 0 == loop */
+#define DC_PN_GPIO_BNC_ENB DC_PN_GPIO_DATA2
+#define DC_PN_GPIO_100TX_LNK DC_PN_GPIO_DATA3
+#define DC_PN_GPIO_SETBIT(sc, r) \
DC_SETBIT(sc, DC_PN_GPIO, ((r) | (r << 4)))
-#define DC_PN_GPIO_CLRBIT(sc, r) \
+#define DC_PN_GPIO_CLRBIT(sc, r) \
{ \
DC_SETBIT(sc, DC_PN_GPIO, ((r) << 4)); \
DC_CLRBIT(sc, DC_PN_GPIO, (r)); \
}
-
+
/* shortcut MII access register */
-#define DC_PN_MII_DATA 0x0000FFFF
-#define DC_PN_MII_RESERVER 0x00020000
-#define DC_PN_MII_REGADDR 0x007C0000
-#define DC_PN_MII_PHYADDR 0x0F800000
-#define DC_PN_MII_OPCODE 0x30000000
-#define DC_PN_MII_BUSY 0x80000000
+#define DC_PN_MII_DATA 0x0000FFFF
+#define DC_PN_MII_RESERVER 0x00020000
+#define DC_PN_MII_REGADDR 0x007C0000
+#define DC_PN_MII_PHYADDR 0x0F800000
+#define DC_PN_MII_OPCODE 0x30000000
+#define DC_PN_MII_BUSY 0x80000000
-#define DC_PN_MIIOPCODE_READ 0x60020000
-#define DC_PN_MIIOPCODE_WRITE 0x50020000
+#define DC_PN_MIIOPCODE_READ 0x60020000
+#define DC_PN_MIIOPCODE_WRITE 0x50020000
/* Internal NWAY bits */
-#define DC_PN_NWAY_RESET 0x00000001 /* reset */
-#define DC_PN_NWAY_PDOWN 0x00000002 /* power down */
-#define DC_PN_NWAY_BYPASS 0x00000004 /* bypass */
-#define DC_PN_NWAY_AUILOWCUR 0x00000008 /* AUI low current */
-#define DC_PN_NWAY_TPEXTEND 0x00000010 /* low squelch voltage */
-#define DC_PN_NWAY_POLARITY 0x00000020 /* 0 == on, 1 == off */
-#define DC_PN_NWAY_TP 0x00000040 /* 1 == tp, 0 == AUI */
-#define DC_PN_NWAY_AUIVOLT 0x00000080 /* 1 == full, 0 == half */
-#define DC_PN_NWAY_DUPLEX 0x00000100 /* LED, 1 == full, 0 == half */
-#define DC_PN_NWAY_LINKTEST 0x00000200 /* 0 == on, 1 == off */
-#define DC_PN_NWAY_AUTODETECT 0x00000400 /* 1 == off, 0 == on */
-#define DC_PN_NWAY_SPEEDSEL 0x00000800 /* LED, 0 = 10, 1 == 100 */
-#define DC_PN_NWAY_NWAY_ENB 0x00001000 /* 0 == off, 1 == on */
-#define DC_PN_NWAY_CAP10HDX 0x00002000
-#define DC_PN_NWAY_CAP10FDX 0x00004000
-#define DC_PN_NWAY_CAP100FDX 0x00008000
-#define DC_PN_NWAY_CAP100HDX 0x00010000
-#define DC_PN_NWAY_CAP100T4 0x00020000
-#define DC_PN_NWAY_ANEGRESTART 0x02000000 /* resets when aneg done */
-#define DC_PN_NWAY_REMFAULT 0x04000000
-#define DC_PN_NWAY_LPAR10HDX 0x08000000
-#define DC_PN_NWAY_LPAR10FDX 0x10000000
-#define DC_PN_NWAY_LPAR100FDX 0x20000000
-#define DC_PN_NWAY_LPAR100HDX 0x40000000
-#define DC_PN_NWAY_LPAR100T4 0x80000000
+#define DC_PN_NWAY_RESET 0x00000001 /* reset */
+#define DC_PN_NWAY_PDOWN 0x00000002 /* power down */
+#define DC_PN_NWAY_BYPASS 0x00000004 /* bypass */
+#define DC_PN_NWAY_AUILOWCUR 0x00000008 /* AUI low current */
+#define DC_PN_NWAY_TPEXTEND 0x00000010 /* low squelch voltage */
+#define DC_PN_NWAY_POLARITY 0x00000020 /* 0 == on, 1 == off */
+#define DC_PN_NWAY_TP 0x00000040 /* 1 == tp, 0 == AUI */
+#define DC_PN_NWAY_AUIVOLT 0x00000080 /* 1 == full, 0 == half */
+#define DC_PN_NWAY_DUPLEX 0x00000100 /* LED, 1 == full, 0 == half */
+#define DC_PN_NWAY_LINKTEST 0x00000200 /* 0 == on, 1 == off */
+#define DC_PN_NWAY_AUTODETECT 0x00000400 /* 1 == off, 0 == on */
+#define DC_PN_NWAY_SPEEDSEL 0x00000800 /* LED, 0 = 10, 1 == 100 */
+#define DC_PN_NWAY_NWAY_ENB 0x00001000 /* 0 == off, 1 == on */
+#define DC_PN_NWAY_CAP10HDX 0x00002000
+#define DC_PN_NWAY_CAP10FDX 0x00004000
+#define DC_PN_NWAY_CAP100FDX 0x00008000
+#define DC_PN_NWAY_CAP100HDX 0x00010000
+#define DC_PN_NWAY_CAP100T4 0x00020000
+#define DC_PN_NWAY_ANEGRESTART 0x02000000 /* resets when aneg done */
+#define DC_PN_NWAY_REMFAULT 0x04000000
+#define DC_PN_NWAY_LPAR10HDX 0x08000000
+#define DC_PN_NWAY_LPAR10FDX 0x10000000
+#define DC_PN_NWAY_LPAR100FDX 0x20000000
+#define DC_PN_NWAY_LPAR100HDX 0x40000000
+#define DC_PN_NWAY_LPAR100T4 0x80000000
/* End of PNIC specific registers */
@@ -710,44 +708,64 @@ struct dc_mii_frame {
* CONEXANT specific registers.
*/
-#define DC_CONEXANT_PHYADDR 0x1
-#define DC_CONEXANT_EE_NODEADDR 0x19A
+#define DC_CONEXANT_PHYADDR 0x1
+#define DC_CONEXANT_EE_NODEADDR 0x19A
/* End of CONEXANT specific registers */
+/*
+ * ULi M5263 specific registers.
+ */
+#define DC_ULI_FILTER_NPERF 14
+
+#define DC_ULI_PHY_DATA_MASK 0x0000FFFF
+#define DC_ULI_PHY_REG_MASK 0x001F0000
+#define DC_ULI_PHY_ADDR_MASK 0x03E00000
+#define DC_ULI_PHY_OP_WRITE 0x04000000
+#define DC_ULI_PHY_OP_READ 0x08000000
+#define DC_ULI_PHY_OP_DONE 0x10000000
+
+#define DC_ULI_PHY_DATA_SHIFT 0
+#define DC_ULI_PHY_REG_SHIFT 16
+#define DC_ULI_PHY_ADDR_SHIFT 21
+
+/* End of ULi M5263 specific registers */
struct dc_softc {
struct ifnet *dc_ifp; /* interface info */
device_t dc_dev; /* device info */
bus_space_handle_t dc_bhandle; /* bus space handle */
bus_space_tag_t dc_btag; /* bus space tag */
- bus_dma_tag_t dc_ltag; /* tag for descriptor ring */
- bus_dmamap_t dc_lmap; /* map for descriptor ring */
- u_int32_t dc_laddr; /* DMA address of dc_ldata */
- bus_dma_tag_t dc_mtag; /* tag for mbufs */
+ bus_dma_tag_t dc_ptag; /* parent DMA tag */
bus_dmamap_t dc_sparemap;
+ bus_dma_tag_t dc_rx_ltag; /* tag for RX descriptors */
+ bus_dmamap_t dc_rx_lmap;
+ bus_dma_tag_t dc_tx_ltag; /* tag for TX descriptors */
+ bus_dmamap_t dc_tx_lmap;
bus_dma_tag_t dc_stag; /* tag for the setup frame */
bus_dmamap_t dc_smap; /* map for the setup frame */
- u_int32_t dc_saddr; /* DMA address of setup frame */
+ bus_addr_t dc_saddr; /* DMA address of setup frame */
+ bus_dma_tag_t dc_rx_mtag; /* tag for RX mbufs */
+ bus_dma_tag_t dc_tx_mtag; /* tag for TX mbufs */
void *dc_intrhand;
struct resource *dc_irq;
struct resource *dc_res;
const struct dc_type *dc_info; /* adapter info */
device_t dc_miibus;
- u_int8_t dc_type;
- u_int8_t dc_pmode;
- u_int8_t dc_link;
- u_int8_t dc_cachesize;
+ uint8_t dc_type;
+ uint8_t dc_pmode;
+ uint8_t dc_link;
+ uint8_t dc_cachesize;
int dc_romwidth;
int dc_pnic_rx_bug_save;
unsigned char *dc_pnic_rx_buf;
int dc_if_flags;
- int dc_if_media;
- u_int32_t dc_flags;
- u_int32_t dc_txthresh;
- u_int8_t *dc_srom;
+ uint32_t dc_flags;
+ uint32_t dc_txthresh;
+ uint32_t dc_eaddr[2];
+ uint8_t *dc_srom;
struct dc_mediainfo *dc_mi;
- struct dc_list_data *dc_ldata;
+ struct dc_list_data dc_ldata;
struct dc_chain_data dc_cdata;
struct callout dc_stat_ch;
struct callout dc_wdog_ch;
@@ -764,38 +782,36 @@ struct dc_softc {
#define DC_UNLOCK(_sc) mtx_unlock(&(_sc)->dc_mtx)
#define DC_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->dc_mtx, MA_OWNED)
-#define DC_TX_POLL 0x00000001
-#define DC_TX_COALESCE 0x00000002
-#define DC_TX_ADMTEK_WAR 0x00000004
-#define DC_TX_USE_TX_INTR 0x00000008
-#define DC_RX_FILTER_TULIP 0x00000010
-#define DC_TX_INTR_FIRSTFRAG 0x00000020
-#define DC_PNIC_RX_BUG_WAR 0x00000040
-#define DC_TX_FIXED_RING 0x00000080
-#define DC_TX_STORENFWD 0x00000100
-#define DC_REDUCED_MII_POLL 0x00000200
-#define DC_TX_INTR_ALWAYS 0x00000400
-#define DC_21143_NWAY 0x00000800
-#define DC_128BIT_HASH 0x00001000
-#define DC_64BIT_HASH 0x00002000
-#define DC_TULIP_LEDS 0x00004000
-#define DC_TX_ONE 0x00008000
-#define DC_TX_ALIGN 0x00010000 /* align mbuf on tx */
+#define DC_TX_POLL 0x00000001
+#define DC_TX_COALESCE 0x00000002
+#define DC_TX_ADMTEK_WAR 0x00000004
+#define DC_TX_USE_TX_INTR 0x00000008
+#define DC_RX_FILTER_TULIP 0x00000010
+#define DC_TX_INTR_FIRSTFRAG 0x00000020
+#define DC_PNIC_RX_BUG_WAR 0x00000040
+#define DC_TX_FIXED_RING 0x00000080
+#define DC_TX_STORENFWD 0x00000100
+#define DC_REDUCED_MII_POLL 0x00000200
+#define DC_TX_INTR_ALWAYS 0x00000400
+#define DC_21143_NWAY 0x00000800
+#define DC_128BIT_HASH 0x00001000
+#define DC_64BIT_HASH 0x00002000
+#define DC_TULIP_LEDS 0x00004000
+#define DC_TX_ALIGN 0x00010000 /* align mbuf on tx */
/*
* register space access macros
*/
-#define CSR_WRITE_4(sc, reg, val) \
+#define CSR_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->dc_btag, sc->dc_bhandle, reg, val)
-#define CSR_READ_4(sc, reg) \
+#define CSR_READ_4(sc, reg) \
bus_space_read_4(sc->dc_btag, sc->dc_bhandle, reg)
-#define CSR_BARRIER_4(sc, reg, flags) \
+#define CSR_BARRIER_4(sc, reg, flags) \
bus_space_barrier(sc->dc_btag, sc->dc_bhandle, reg, 4, flags)
-#define DC_TIMEOUT 1000
-#define ETHER_ALIGN 2
+#define DC_TIMEOUT 1000
/*
* General constants that are fun to know.
@@ -804,12 +820,12 @@ struct dc_softc {
/*
* DEC PCI vendor ID
*/
-#define DC_VENDORID_DEC 0x1011
+#define DC_VENDORID_DEC 0x1011
/*
* DEC/Intel 21143 PCI device ID
*/
-#define DC_DEVICEID_21143 0x0019
+#define DC_DEVICEID_21143 0x0019
/*
* Macronix PCI vendor ID
@@ -819,118 +835,118 @@ struct dc_softc {
/*
* Macronix PMAC device IDs.
*/
-#define DC_DEVICEID_98713 0x0512
-#define DC_DEVICEID_987x5 0x0531
-#define DC_DEVICEID_98727 0x0532
-#define DC_DEVICEID_98732 0x0532
+#define DC_DEVICEID_98713 0x0512
+#define DC_DEVICEID_987x5 0x0531
+#define DC_DEVICEID_98727 0x0532
+#define DC_DEVICEID_98732 0x0532
/* Macronix PCI revision codes. */
-#define DC_REVISION_98713 0x00
-#define DC_REVISION_98713A 0x10
-#define DC_REVISION_98715 0x20
-#define DC_REVISION_98715AEC_C 0x25
-#define DC_REVISION_98725 0x30
+#define DC_REVISION_98713 0x00
+#define DC_REVISION_98713A 0x10
+#define DC_REVISION_98715 0x20
+#define DC_REVISION_98715AEC_C 0x25
+#define DC_REVISION_98725 0x30
/*
* Compex PCI vendor ID.
*/
-#define DC_VENDORID_CP 0x11F6
+#define DC_VENDORID_CP 0x11F6
/*
* Compex PMAC PCI device IDs.
*/
-#define DC_DEVICEID_98713_CP 0x9881
+#define DC_DEVICEID_98713_CP 0x9881
/*
* Lite-On PNIC PCI vendor ID
*/
-#define DC_VENDORID_LO 0x11AD
+#define DC_VENDORID_LO 0x11AD
/*
* 82c168/82c169 PNIC device IDs. Both chips have the same device
* ID but different revisions. Revision 0x10 is the 82c168, and
* 0x20 is the 82c169.
*/
-#define DC_DEVICEID_82C168 0x0002
+#define DC_DEVICEID_82C168 0x0002
-#define DC_REVISION_82C168 0x10
-#define DC_REVISION_82C169 0x20
+#define DC_REVISION_82C168 0x10
+#define DC_REVISION_82C169 0x20
/*
* Lite-On PNIC II device ID. Note: this is actually a Macronix 98715A
* with wake on lan/magic packet support.
*/
-#define DC_DEVICEID_82C115 0xc115
+#define DC_DEVICEID_82C115 0xc115
/*
* Davicom vendor ID.
*/
-#define DC_VENDORID_DAVICOM 0x1282
+#define DC_VENDORID_DAVICOM 0x1282
/*
* Davicom device IDs.
*/
-#define DC_DEVICEID_DM9009 0x9009
-#define DC_DEVICEID_DM9100 0x9100
-#define DC_DEVICEID_DM9102 0x9102
+#define DC_DEVICEID_DM9009 0x9009
+#define DC_DEVICEID_DM9100 0x9100
+#define DC_DEVICEID_DM9102 0x9102
/*
* The DM9102A has the same PCI device ID as the DM9102,
* but a higher revision code.
*/
-#define DC_REVISION_DM9102 0x10
-#define DC_REVISION_DM9102A 0x30
+#define DC_REVISION_DM9102 0x10
+#define DC_REVISION_DM9102A 0x30
/*
* ADMtek vendor ID.
*/
-#define DC_VENDORID_ADMTEK 0x1317
+#define DC_VENDORID_ADMTEK 0x1317
/*
* ADMtek device IDs.
*/
-#define DC_DEVICEID_AL981 0x0981
-#define DC_DEVICEID_AN983 0x0985
-#define DC_DEVICEID_AN985 0x1985
-#define DC_DEVICEID_ADM9511 0x9511
-#define DC_DEVICEID_ADM9513 0x9513
+#define DC_DEVICEID_AL981 0x0981
+#define DC_DEVICEID_AN983 0x0985
+#define DC_DEVICEID_AN985 0x1985
+#define DC_DEVICEID_ADM9511 0x9511
+#define DC_DEVICEID_ADM9513 0x9513
/*
* 3COM PCI vendor ID
*/
-#define DC_VENDORID_3COM 0x10b7
+#define DC_VENDORID_3COM 0x10b7
/*
* 3COM OfficeConnect 10/100B (3CSOHO100B-TX)
*/
-#define DC_DEVICEID_3CSOHOB 0x9300
+#define DC_DEVICEID_3CSOHOB 0x9300
/*
* ASIX vendor ID.
*/
-#define DC_VENDORID_ASIX 0x125B
+#define DC_VENDORID_ASIX 0x125B
/*
* ASIX device IDs.
*/
-#define DC_DEVICEID_AX88140A 0x1400
+#define DC_DEVICEID_AX88140A 0x1400
/*
* The ASIX AX88140 and ASIX AX88141 have the same vendor and
* device IDs but different revision values.
*/
-#define DC_REVISION_88140 0x00
-#define DC_REVISION_88141 0x10
+#define DC_REVISION_88140 0x00
+#define DC_REVISION_88141 0x10
/*
* Accton vendor ID.
*/
-#define DC_VENDORID_ACCTON 0x1113
+#define DC_VENDORID_ACCTON 0x1113
/*
* Accton device IDs.
*/
-#define DC_DEVICEID_EN1217 0x1217
+#define DC_DEVICEID_EN1217 0x1217
#define DC_DEVICEID_EN2242 0x1216
/*
@@ -956,69 +972,80 @@ struct dc_softc {
/*
* Abocom vendor ID
*/
-#define DC_VENDORID_ABOCOM 0x13d1
+#define DC_VENDORID_ABOCOM 0x13d1
/*
* Abocom device IDs.
*/
-#define DC_DEVICEID_FE2500 0xAB02
-#define DC_DEVICEID_FE2500MX 0xab08
+#define DC_DEVICEID_FE2500 0xAB02
+#define DC_DEVICEID_FE2500MX 0xab08
/*
* Conexant vendor ID.
*/
-#define DC_VENDORID_CONEXANT 0x14f1
+#define DC_VENDORID_CONEXANT 0x14f1
/*
* Conexant device IDs.
*/
-#define DC_DEVICEID_RS7112 0x1803
+#define DC_DEVICEID_RS7112 0x1803
/*
* Planex vendor ID
*/
-#define DC_VENDORID_PLANEX 0x14ea
+#define DC_VENDORID_PLANEX 0x14ea
/*
* Planex device IDs.
*/
-#define DC_DEVICEID_FNW3602T 0xab08
+#define DC_DEVICEID_FNW3602T 0xab08
/*
* Not sure who this vendor should be, so we'll go with HAWKING until
* I can locate the right one.
*/
-#define DC_VENDORID_HAWKING 0x17b3
+#define DC_VENDORID_HAWKING 0x17b3
/*
* Sure looks like an abocom device ID, but it found on my hawking PN672TX
* card. Use that for now, and upgrade later.
*/
-#define DC_DEVICEID_HAWKING_PN672TX 0xab08
+#define DC_DEVICEID_HAWKING_PN672TX 0xab08
/*
* Microsoft device ID.
*/
-#define DC_VENDORID_MICROSOFT 0x1414
+#define DC_VENDORID_MICROSOFT 0x1414
/*
* Supported Microsoft PCI and cardbus NICs. These are really
* ADMtek parts in disguise.
*/
-#define DC_DEVICEID_MSMN120 0x0001
-#define DC_DEVICEID_MSMN130 0x0002
+#define DC_DEVICEID_MSMN120 0x0001
+#define DC_DEVICEID_MSMN130 0x0002
/*
* Linksys vendor ID.
*/
-#define DC_VENDORID_LINKSYS 0x1737
+#define DC_VENDORID_LINKSYS 0x1737
/*
* Linksys device IDs.
*/
-#define DC_DEVICEID_PCMPC200_AB08 0xab08
-#define DC_DEVICEID_PCMPC200_AB09 0xab09
+#define DC_DEVICEID_PCMPC200_AB08 0xab08
+#define DC_DEVICEID_PCMPC200_AB09 0xab09
+
+/*
+ * ULi vendor ID.
+ */
+#define DC_VENDORID_ULI 0x10b9
+
+/*
+ * ULi device IDs.
+ */
+#define DC_DEVICEID_M5261 0x5261
+#define DC_DEVICEID_M5263 0x5263
#define DC_DEVID(vendor, device) ((device) << 16 | (vendor))
@@ -1027,112 +1054,114 @@ struct dc_softc {
* other PCI registers.
*/
-#define DC_PCI_CFBIO PCIR_BAR(0) /* Base I/O address */
-#define DC_PCI_CFBMA PCIR_BAR(1) /* Base memory address */
-#define DC_PCI_CFDD 0x40 /* Device and driver area */
-#define DC_PCI_CWUA0 0x44 /* Wake-Up LAN addr 0 */
-#define DC_PCI_CWUA1 0x48 /* Wake-Up LAN addr 1 */
-#define DC_PCI_SOP0 0x4C /* SecureON passwd 0 */
-#define DC_PCI_SOP1 0x50 /* SecureON passwd 1 */
-#define DC_PCI_CWUC 0x54 /* Configuration Wake-Up cmd */
+#define DC_PCI_CFBIO PCIR_BAR(0) /* Base I/O address */
+#define DC_PCI_CFBMA PCIR_BAR(1) /* Base memory address */
+#define DC_PCI_CFDD 0x40 /* Device and driver area */
+#define DC_PCI_CWUA0 0x44 /* Wake-Up LAN addr 0 */
+#define DC_PCI_CWUA1 0x48 /* Wake-Up LAN addr 1 */
+#define DC_PCI_SOP0 0x4C /* SecureON passwd 0 */
+#define DC_PCI_SOP1 0x50 /* SecureON passwd 1 */
+#define DC_PCI_CWUC 0x54 /* Configuration Wake-Up cmd */
-#define DC_21143_PB_REV 0x00000030
-#define DC_21143_TB_REV 0x00000030
-#define DC_21143_PC_REV 0x00000030
-#define DC_21143_TC_REV 0x00000030
-#define DC_21143_PD_REV 0x00000041
-#define DC_21143_TD_REV 0x00000041
+#define DC_21143_PB_REV 0x00000030
+#define DC_21143_TB_REV 0x00000030
+#define DC_21143_PC_REV 0x00000030
+#define DC_21143_TC_REV 0x00000030
+#define DC_21143_PD_REV 0x00000041
+#define DC_21143_TD_REV 0x00000041
/* Configuration and driver area */
-#define DC_CFDD_DRVUSE 0x0000FFFF
-#define DC_CFDD_SNOOZE_MODE 0x40000000
-#define DC_CFDD_SLEEP_MODE 0x80000000
+#define DC_CFDD_DRVUSE 0x0000FFFF
+#define DC_CFDD_SNOOZE_MODE 0x40000000
+#define DC_CFDD_SLEEP_MODE 0x80000000
/* Configuration wake-up command register */
-#define DC_CWUC_MUST_BE_ZERO 0x00000001
-#define DC_CWUC_SECUREON_ENB 0x00000002
-#define DC_CWUC_FORCE_WUL 0x00000004
-#define DC_CWUC_BNC_ABILITY 0x00000008
-#define DC_CWUC_AUI_ABILITY 0x00000010
-#define DC_CWUC_TP10_ABILITY 0x00000020
-#define DC_CWUC_MII_ABILITY 0x00000040
-#define DC_CWUC_SYM_ABILITY 0x00000080
-#define DC_CWUC_LOCK 0x00000100
+#define DC_CWUC_MUST_BE_ZERO 0x00000001
+#define DC_CWUC_SECUREON_ENB 0x00000002
+#define DC_CWUC_FORCE_WUL 0x00000004
+#define DC_CWUC_BNC_ABILITY 0x00000008
+#define DC_CWUC_AUI_ABILITY 0x00000010
+#define DC_CWUC_TP10_ABILITY 0x00000020
+#define DC_CWUC_MII_ABILITY 0x00000040
+#define DC_CWUC_SYM_ABILITY 0x00000080
+#define DC_CWUC_LOCK 0x00000100
/*
* SROM nonsense.
*/
-#define DC_IB_CTLRCNT 0x13
-#define DC_IB_LEAF0_CNUM 0x1A
-#define DC_IB_LEAF0_OFFSET 0x1B
+#define DC_ROM_SIZE(bits) (2 << (bits))
+
+#define DC_IB_CTLRCNT 0x13
+#define DC_IB_LEAF0_CNUM 0x1A
+#define DC_IB_LEAF0_OFFSET 0x1B
struct dc_info_leaf {
- u_int16_t dc_conntype;
- u_int8_t dc_blkcnt;
- u_int8_t dc_rsvd;
- u_int16_t dc_infoblk;
+ uint16_t dc_conntype;
+ uint8_t dc_blkcnt;
+ uint8_t dc_rsvd;
+ uint16_t dc_infoblk;
};
-#define DC_CTYPE_10BT 0x0000
-#define DC_CTYPE_10BT_NWAY 0x0100
-#define DC_CTYPE_10BT_FDX 0x0204
-#define DC_CTYPE_10B2 0x0001
-#define DC_CTYPE_10B5 0x0002
-#define DC_CTYPE_100BT 0x0003
-#define DC_CTYPE_100BT_FDX 0x0205
-#define DC_CTYPE_100T4 0x0006
-#define DC_CTYPE_100FX 0x0007
-#define DC_CTYPE_100FX_FDX 0x0208
-#define DC_CTYPE_MII_10BT 0x0009
-#define DC_CTYPE_MII_10BT_FDX 0x020A
-#define DC_CTYPE_MII_100BT 0x000D
-#define DC_CTYPE_MII_100BT_FDX 0x020E
-#define DC_CTYPE_MII_100T4 0x000F
-#define DC_CTYPE_MII_100FX 0x0010
-#define DC_CTYPE_MII_100FX_FDX 0x0211
-#define DC_CTYPE_DYN_PUP_AUTOSENSE 0x0800
-#define DC_CTYPE_PUP_AUTOSENSE 0x8800
-#define DC_CTYPE_NOMEDIA 0xFFFF
-
-#define DC_EBLOCK_SIA 0x0002
-#define DC_EBLOCK_MII 0x0003
-#define DC_EBLOCK_SYM 0x0004
-#define DC_EBLOCK_RESET 0x0005
-#define DC_EBLOCK_PHY_SHUTDOWN 0x0006
+#define DC_CTYPE_10BT 0x0000
+#define DC_CTYPE_10BT_NWAY 0x0100
+#define DC_CTYPE_10BT_FDX 0x0204
+#define DC_CTYPE_10B2 0x0001
+#define DC_CTYPE_10B5 0x0002
+#define DC_CTYPE_100BT 0x0003
+#define DC_CTYPE_100BT_FDX 0x0205
+#define DC_CTYPE_100T4 0x0006
+#define DC_CTYPE_100FX 0x0007
+#define DC_CTYPE_100FX_FDX 0x0208
+#define DC_CTYPE_MII_10BT 0x0009
+#define DC_CTYPE_MII_10BT_FDX 0x020A
+#define DC_CTYPE_MII_100BT 0x000D
+#define DC_CTYPE_MII_100BT_FDX 0x020E
+#define DC_CTYPE_MII_100T4 0x000F
+#define DC_CTYPE_MII_100FX 0x0010
+#define DC_CTYPE_MII_100FX_FDX 0x0211
+#define DC_CTYPE_DYN_PUP_AUTOSENSE 0x0800
+#define DC_CTYPE_PUP_AUTOSENSE 0x8800
+#define DC_CTYPE_NOMEDIA 0xFFFF
+
+#define DC_EBLOCK_SIA 0x0002
+#define DC_EBLOCK_MII 0x0003
+#define DC_EBLOCK_SYM 0x0004
+#define DC_EBLOCK_RESET 0x0005
+#define DC_EBLOCK_PHY_SHUTDOWN 0x0006
struct dc_leaf_hdr {
- u_int16_t dc_mtype;
- u_int8_t dc_mcnt;
- u_int8_t dc_rsvd;
+ uint16_t dc_mtype;
+ uint8_t dc_mcnt;
+ uint8_t dc_rsvd;
};
struct dc_eblock_hdr {
- u_int8_t dc_len;
- u_int8_t dc_type;
+ uint8_t dc_len;
+ uint8_t dc_type;
};
struct dc_eblock_sia {
struct dc_eblock_hdr dc_sia_hdr;
- u_int8_t dc_sia_code;
+ uint8_t dc_sia_code;
union {
struct dc_sia_ext { /* if (dc_sia_code & DC_SIA_CODE_EXT) */
- u_int8_t dc_sia_mediaspec[6]; /* CSR13, CSR14, CSR15 */
- u_int8_t dc_sia_gpio_ctl[2];
- u_int8_t dc_sia_gpio_dat[2];
+ uint8_t dc_sia_mediaspec[6]; /* CSR13, CSR14, CSR15 */
+ uint8_t dc_sia_gpio_ctl[2];
+ uint8_t dc_sia_gpio_dat[2];
} dc_sia_ext;
struct dc_sia_noext {
- u_int8_t dc_sia_gpio_ctl[2];
- u_int8_t dc_sia_gpio_dat[2];
+ uint8_t dc_sia_gpio_ctl[2];
+ uint8_t dc_sia_gpio_dat[2];
} dc_sia_noext;
} dc_un;
};
-#define DC_SIA_CODE_10BT 0x00
-#define DC_SIA_CODE_10B2 0x01
-#define DC_SIA_CODE_10B5 0x02
-#define DC_SIA_CODE_10BT_FDX 0x04
-#define DC_SIA_CODE_EXT 0x40
+#define DC_SIA_CODE_10BT 0x00
+#define DC_SIA_CODE_10B2 0x01
+#define DC_SIA_CODE_10B5 0x02
+#define DC_SIA_CODE_10BT_FDX 0x04
+#define DC_SIA_CODE_EXT 0x40
/*
* Note that the first word in the gpr and reset
@@ -1140,11 +1169,11 @@ struct dc_eblock_sia {
*/
struct dc_eblock_mii {
struct dc_eblock_hdr dc_mii_hdr;
- u_int8_t dc_mii_phynum;
- u_int8_t dc_gpr_len;
-/* u_int16_t dc_gpr_dat[n]; */
-/* u_int8_t dc_reset_len; */
-/* u_int16_t dc_reset_dat[n]; */
+ uint8_t dc_mii_phynum;
+ uint8_t dc_gpr_len;
+/* uint16_t dc_gpr_dat[n]; */
+/* uint8_t dc_reset_len; */
+/* uint16_t dc_reset_dat[n]; */
/* There are other fields after these, but we don't
* care about them since they can be determined by looking
* at the PHY.
@@ -1153,20 +1182,20 @@ struct dc_eblock_mii {
struct dc_eblock_sym {
struct dc_eblock_hdr dc_sym_hdr;
- u_int8_t dc_sym_code;
- u_int8_t dc_sym_gpio_ctl[2];
- u_int8_t dc_sym_gpio_dat[2];
- u_int8_t dc_sym_cmd[2];
+ uint8_t dc_sym_code;
+ uint8_t dc_sym_gpio_ctl[2];
+ uint8_t dc_sym_gpio_dat[2];
+ uint8_t dc_sym_cmd[2];
};
-#define DC_SYM_CODE_100BT 0x03
-#define DC_SYM_CODE_100BT_FDX 0x05
-#define DC_SYM_CODE_100T4 0x06
-#define DC_SYM_CODE_100FX 0x07
-#define DC_SYM_CODE_100FX_FDX 0x08
+#define DC_SYM_CODE_100BT 0x03
+#define DC_SYM_CODE_100BT_FDX 0x05
+#define DC_SYM_CODE_100T4 0x06
+#define DC_SYM_CODE_100FX 0x07
+#define DC_SYM_CODE_100FX_FDX 0x08
struct dc_eblock_reset {
struct dc_eblock_hdr dc_reset_hdr;
- u_int8_t dc_reset_len;
-/* u_int16_t dc_reset_dat[n]; */
+ uint8_t dc_reset_len;
+/* uint16_t dc_reset_dat[n]; */
};
diff --git a/freebsd/sys/dev/dc/pnphy.c b/freebsd/sys/dev/dc/pnphy.c
index b59ddf61..0b589e82 100644
--- a/freebsd/sys/dev/dc/pnphy.c
+++ b/freebsd/sys/dev/dc/pnphy.c
@@ -68,14 +68,6 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/miibus_if.h>
-#define DC_SETBIT(sc, reg, x) \
- CSR_WRITE_4(sc, reg, \
- CSR_READ_4(sc, reg) | x)
-
-#define DC_CLRBIT(sc, reg, x) \
- CSR_WRITE_4(sc, reg, \
- CSR_READ_4(sc, reg) & ~x)
-
static int pnphy_probe(device_t);
static int pnphy_attach(device_t);
@@ -85,7 +77,7 @@ static device_method_t pnphy_methods[] = {
DEVMETHOD(device_attach, pnphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t pnphy_devclass;
@@ -143,7 +135,7 @@ pnphy_attach(device_t dev)
/*
* Apparently, we can neither isolate nor do loopback.
*/
- sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP | MIIF_NOMANPAUSE;
sc->mii_capabilities =
BMSR_100TXFDX | BMSR_100TXHDX | BMSR_10TFDX | BMSR_10THDX;
@@ -172,23 +164,19 @@ pnphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
+ /*
+ * Note that auto-negotiation is broken on this chip.
+ */
switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /* NWAY is busted on this chip */
- case IFM_100_T4:
- /*
- * XXX Not supported as a manual setting right now.
- */
- return (EINVAL);
case IFM_100_TX:
mii->mii_media_active = IFM_ETHER | IFM_100_TX;
- if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
+ if ((ife->ifm_media & IFM_FDX) != 0)
mii->mii_media_active |= IFM_FDX;
MIIBUS_STATCHG(sc->mii_dev);
return (0);
case IFM_10_T:
mii->mii_media_active = IFM_ETHER | IFM_10_T;
- if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
+ if ((ife->ifm_media & IFM_FDX) != 0)
mii->mii_media_active |= IFM_FDX;
MIIBUS_STATCHG(sc->mii_dev);
return (0);
@@ -228,15 +216,14 @@ pnphy_status(struct mii_softc *sc)
mii->mii_media_active = IFM_ETHER;
reg = CSR_READ_4(dc_sc, DC_ISR);
-
if (!(reg & DC_ISR_LINKFAIL))
mii->mii_media_status |= IFM_ACTIVE;
-
- if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_SPEEDSEL)
+ reg = CSR_READ_4(dc_sc, DC_NETCFG);
+ if (reg & DC_NETCFG_SPEEDSEL)
mii->mii_media_active |= IFM_10_T;
else
mii->mii_media_active |= IFM_100_TX;
- if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_FULLDUPLEX)
+ if (reg & DC_NETCFG_FULLDUPLEX)
mii->mii_media_active |= IFM_FDX;
else
mii->mii_media_active |= IFM_HDX;
diff --git a/freebsd/sys/dev/e1000/e1000_80003es2lan.c b/freebsd/sys/dev/e1000/e1000_80003es2lan.c
index 79fba337..79950c8a 100644
--- a/freebsd/sys/dev/e1000/e1000_80003es2lan.c
+++ b/freebsd/sys/dev/e1000/e1000_80003es2lan.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -53,18 +53,18 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
- u32 offset,
- u16 *data);
+ u32 offset,
+ u16 *data);
static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
- u32 offset,
- u16 data);
+ u32 offset,
+ u16 data);
static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
+ u16 words, u16 *data);
static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
- u16 *duplex);
+ u16 *duplex);
static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw);
static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
@@ -74,9 +74,9 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
- u16 *data);
+ u16 *data);
static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
- u16 data);
+ u16 data);
static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw);
static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
@@ -88,11 +88,11 @@ static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
* with a lower bound at "index" and the upper bound at
* "index + 5".
*/
-static const u16 e1000_gg82563_cable_length_table[] =
- { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
+static const u16 e1000_gg82563_cable_length_table[] = {
+ 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
#define GG82563_CABLE_LENGTH_TABLE_SIZE \
- (sizeof(e1000_gg82563_cable_length_table) / \
- sizeof(e1000_gg82563_cable_length_table[0]))
+ (sizeof(e1000_gg82563_cable_length_table) / \
+ sizeof(e1000_gg82563_cable_length_table[0]))
/**
* e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
@@ -106,34 +106,34 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_phy_params_80003es2lan");
if (hw->phy.media_type != e1000_media_type_copper) {
- phy->type = e1000_phy_none;
+ phy->type = e1000_phy_none;
goto out;
} else {
phy->ops.power_up = e1000_power_up_phy_copper;
phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
}
- phy->addr = 1;
- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- phy->reset_delay_us = 100;
- phy->type = e1000_phy_gg82563;
-
- phy->ops.acquire = e1000_acquire_phy_80003es2lan;
- phy->ops.check_polarity = e1000_check_polarity_m88;
- phy->ops.check_reset_block = e1000_check_reset_block_generic;
- phy->ops.commit = e1000_phy_sw_reset_generic;
- phy->ops.get_cfg_done = e1000_get_cfg_done_80003es2lan;
- phy->ops.get_info = e1000_get_phy_info_m88;
- phy->ops.release = e1000_release_phy_80003es2lan;
- phy->ops.reset = e1000_phy_hw_reset_generic;
- phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
+ phy->addr = 1;
+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->reset_delay_us = 100;
+ phy->type = e1000_phy_gg82563;
+
+ phy->ops.acquire = e1000_acquire_phy_80003es2lan;
+ phy->ops.check_polarity = e1000_check_polarity_m88;
+ phy->ops.check_reset_block = e1000_check_reset_block_generic;
+ phy->ops.commit = e1000_phy_sw_reset_generic;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_80003es2lan;
+ phy->ops.get_info = e1000_get_phy_info_m88;
+ phy->ops.release = e1000_release_phy_80003es2lan;
+ phy->ops.reset = e1000_phy_hw_reset_generic;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan;
- phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan;
- phy->ops.read_reg = e1000_read_phy_reg_gg82563_80003es2lan;
- phy->ops.write_reg = e1000_write_phy_reg_gg82563_80003es2lan;
+ phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan;
+ phy->ops.read_reg = e1000_read_phy_reg_gg82563_80003es2lan;
+ phy->ops.write_reg = e1000_write_phy_reg_gg82563_80003es2lan;
- phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan;
+ phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan;
/* This can only be done after all function pointers are setup. */
ret_val = e1000_get_phy_id(hw);
@@ -160,19 +160,19 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_nvm_params_80003es2lan");
- nvm->opcode_bits = 8;
- nvm->delay_usec = 1;
+ nvm->opcode_bits = 8;
+ nvm->delay_usec = 1;
switch (nvm->override) {
case e1000_nvm_override_spi_large:
- nvm->page_size = 32;
+ nvm->page_size = 32;
nvm->address_bits = 16;
break;
case e1000_nvm_override_spi_small:
- nvm->page_size = 8;
+ nvm->page_size = 8;
nvm->address_bits = 8;
break;
default:
- nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
+ nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
break;
}
@@ -180,7 +180,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
nvm->type = e1000_nvm_eeprom_spi;
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
- E1000_EECD_SIZE_EX_SHIFT);
+ E1000_EECD_SIZE_EX_SHIFT);
/*
* Added to a constant, "size" becomes the left-shift value
@@ -191,16 +191,16 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
/* EEPROM access above 16k is unsupported */
if (size > 14)
size = 14;
- nvm->word_size = 1 << size;
+ nvm->word_size = 1 << size;
/* Function Pointers */
- nvm->ops.acquire = e1000_acquire_nvm_80003es2lan;
- nvm->ops.read = e1000_read_nvm_eerd;
- nvm->ops.release = e1000_release_nvm_80003es2lan;
- nvm->ops.update = e1000_update_nvm_checksum_generic;
+ nvm->ops.acquire = e1000_acquire_nvm_80003es2lan;
+ nvm->ops.read = e1000_read_nvm_eerd;
+ nvm->ops.release = e1000_release_nvm_80003es2lan;
+ nvm->ops.update = e1000_update_nvm_checksum_generic;
nvm->ops.valid_led_default = e1000_valid_led_default_generic;
- nvm->ops.validate = e1000_validate_nvm_checksum_generic;
- nvm->ops.write = e1000_write_nvm_80003es2lan;
+ nvm->ops.validate = e1000_validate_nvm_checksum_generic;
+ nvm->ops.write = e1000_write_nvm_80003es2lan;
return E1000_SUCCESS;
}
@@ -221,13 +221,13 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
hw->phy.media_type = e1000_media_type_internal_serdes;
mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
mac->ops.setup_physical_interface =
- e1000_setup_fiber_serdes_link_generic;
+ e1000_setup_fiber_serdes_link_generic;
break;
default:
hw->phy.media_type = e1000_media_type_copper;
mac->ops.check_for_link = e1000_check_for_copper_link_generic;
mac->ops.setup_physical_interface =
- e1000_setup_copper_link_80003es2lan;
+ e1000_setup_copper_link_80003es2lan;
break;
}
@@ -240,9 +240,8 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
/* FWSM register */
mac->has_fwsm = TRUE;
/* ARC supported; valid only if manageability features are enabled. */
- mac->arc_subsystem_valid =
- (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK)
- ? TRUE : FALSE;
+ mac->arc_subsystem_valid = (E1000_READ_REG(hw, E1000_FWSM) &
+ E1000_FWSM_MODE_MASK) ? TRUE : FALSE;
/* Adaptive IFS not supported */
mac->adaptive_ifs = FALSE;
@@ -336,7 +335,7 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
}
/**
- * e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register
+ * e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register
* @hw: pointer to the HW structure
*
* Acquire the semaphore to access the Kumeran interface.
@@ -354,7 +353,7 @@ static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
}
/**
- * e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register
+ * e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register
* @hw: pointer to the HW structure
*
* Release the semaphore used to access the Kumeran interface
@@ -494,7 +493,7 @@ static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
* Read the GG82563 PHY register.
**/
static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
- u32 offset, u16 *data)
+ u32 offset, u16 *data)
{
s32 ret_val;
u32 page_select;
@@ -544,14 +543,14 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
usec_delay(200);
ret_val = e1000_read_phy_reg_mdic(hw,
- MAX_PHY_REG_ADDRESS & offset,
- data);
+ MAX_PHY_REG_ADDRESS & offset,
+ data);
usec_delay(200);
} else {
ret_val = e1000_read_phy_reg_mdic(hw,
- MAX_PHY_REG_ADDRESS & offset,
- data);
+ MAX_PHY_REG_ADDRESS & offset,
+ data);
}
e1000_release_phy_80003es2lan(hw);
@@ -569,7 +568,7 @@ out:
* Write to the GG82563 PHY register.
**/
static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
- u32 offset, u16 data)
+ u32 offset, u16 data)
{
s32 ret_val;
u32 page_select;
@@ -619,14 +618,14 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
usec_delay(200);
ret_val = e1000_write_phy_reg_mdic(hw,
- MAX_PHY_REG_ADDRESS & offset,
- data);
+ MAX_PHY_REG_ADDRESS & offset,
+ data);
usec_delay(200);
} else {
ret_val = e1000_write_phy_reg_mdic(hw,
- MAX_PHY_REG_ADDRESS & offset,
- data);
+ MAX_PHY_REG_ADDRESS & offset,
+ data);
}
e1000_release_phy_80003es2lan(hw);
@@ -645,7 +644,7 @@ out:
* Write "words" of data to the ESB2 NVM.
**/
static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data)
+ u16 words, u16 *data)
{
DEBUGFUNC("e1000_write_nvm_80003es2lan");
@@ -735,11 +734,10 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
usec_delay(1);
if (hw->phy.autoneg_wait_to_complete) {
- DEBUGOUT("Waiting for forced speed/duplex link "
- "on GG82563 phy.\n");
+ DEBUGOUT("Waiting for forced speed/duplex link on GG82563 phy.\n");
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
- 100000, &link);
+ 100000, &link);
if (ret_val)
goto out;
@@ -755,12 +753,13 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
/* Try once more */
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
- 100000, &link);
+ 100000, &link);
if (ret_val)
goto out;
}
- ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data);
+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+ &phy_data);
if (ret_val)
goto out;
@@ -779,7 +778,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
* duplex.
*/
phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
- ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+ phy_data);
out:
return ret_val;
@@ -832,21 +832,20 @@ out:
* Retrieve the current speed and duplex configuration.
**/
static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
- u16 *duplex)
+ u16 *duplex)
{
s32 ret_val;
DEBUGFUNC("e1000_get_link_up_info_80003es2lan");
if (hw->phy.media_type == e1000_media_type_copper) {
- ret_val = e1000_get_speed_and_duplex_copper_generic(hw,
- speed,
- duplex);
+ ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
+ duplex);
hw->phy.ops.cfg_on_link_up(hw);
} else {
ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw,
- speed,
- duplex);
+ speed,
+ duplex);
}
return ret_val;
@@ -860,7 +859,7 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
**/
static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
{
- u32 ctrl, icr;
+ u32 ctrl;
s32 ret_val;
DEBUGFUNC("e1000_reset_hw_80003es2lan");
@@ -896,7 +895,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
/* Clear any pending interrupt events. */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
ret_val = e1000_check_alt_mac_addr_generic(hw);
@@ -915,6 +914,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
struct e1000_mac_info *mac = &hw->mac;
u32 reg_data;
s32 ret_val;
+ u16 kum_reg_data;
u16 i;
DEBUGFUNC("e1000_init_hw_80003es2lan");
@@ -942,16 +942,23 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
/* Setup link and flow control */
ret_val = mac->ops.setup_link(hw);
+ /* Disable IBIST slave mode (far-end loopback) */
+ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ &kum_reg_data);
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+
/* Set the transmit descriptor write-back policy */
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
- E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
+ E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
/* ...for both queues. */
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
- E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
+ E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
/* Enable retransmit on late collisions */
@@ -979,9 +986,9 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
hw->dev_spec._80003es2lan.mdic_wa_enable = TRUE;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
- E1000_KMRNCTRLSTA_OFFSET >>
- E1000_KMRNCTRLSTA_OFFSET_SHIFT,
- &i);
+ E1000_KMRNCTRLSTA_OFFSET >>
+ E1000_KMRNCTRLSTA_OFFSET_SHIFT,
+ &i);
if (!ret_val) {
if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
@@ -1054,11 +1061,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan");
- if (phy->reset_disable)
- goto skip_reset;
-
- ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
- &data);
+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
if (ret_val)
goto out;
@@ -1066,8 +1069,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
/* Use 25MHz for both link down and 1000Base-T for Tx clock. */
data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
- ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
- data);
+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
if (ret_val)
goto out;
@@ -1120,7 +1122,6 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
goto out;
}
-skip_reset:
/* Bypass Rx and Tx FIFO's */
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
@@ -1130,14 +1131,12 @@ skip_reset:
goto out;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
- E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
- &data);
+ E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, &data);
if (ret_val)
goto out;
data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
- E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
- data);
+ E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, data);
if (ret_val)
goto out;
@@ -1167,18 +1166,18 @@ skip_reset:
/* Enable Electrical Idle on the PHY */
data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
- data);
+ data);
if (ret_val)
goto out;
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
- &data);
+ &data);
if (ret_val)
goto out;
data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
- data);
+ data);
if (ret_val)
goto out;
}
@@ -1226,27 +1225,25 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
* polling the phy; this fixes erroneous timeouts at 10Mbps.
*/
ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
- 0xFFFF);
+ 0xFFFF);
if (ret_val)
goto out;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
- &reg_data);
+ &reg_data);
if (ret_val)
goto out;
reg_data |= 0x3F;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
- reg_data);
+ reg_data);
if (ret_val)
goto out;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
- E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
- &reg_data);
+ E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, &reg_data);
if (ret_val)
goto out;
reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
- E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
- reg_data);
+ E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, reg_data);
if (ret_val)
goto out;
@@ -1277,9 +1274,8 @@ static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_configure_on_link_up");
if (hw->phy.media_type == e1000_media_type_copper) {
- ret_val = e1000_get_speed_and_duplex_copper_generic(hw,
- &speed,
- &duplex);
+ ret_val = e1000_get_speed_and_duplex_copper_generic(hw, &speed,
+ &duplex);
if (ret_val)
goto out;
@@ -1312,8 +1308,8 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
- E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
- reg_data);
+ E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+ reg_data);
if (ret_val)
goto out;
@@ -1325,12 +1321,12 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
do {
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
- &reg_data);
+ &reg_data);
if (ret_val)
goto out;
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
- &reg_data2);
+ &reg_data2);
if (ret_val)
goto out;
i++;
@@ -1341,7 +1337,8 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
else
reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
- ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+ reg_data);
out:
return ret_val;
@@ -1365,8 +1362,7 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
- E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
- reg_data);
+ E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, reg_data);
if (ret_val)
goto out;
@@ -1378,19 +1374,20 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
do {
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
- &reg_data);
+ &reg_data);
if (ret_val)
goto out;
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
- &reg_data2);
+ &reg_data2);
if (ret_val)
goto out;
i++;
} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
- ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+ reg_data);
out:
return ret_val;
@@ -1407,7 +1404,7 @@ out:
* Release the semaphore before exiting.
**/
static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
- u16 *data)
+ u16 *data)
{
u32 kmrnctrlsta;
s32 ret_val = E1000_SUCCESS;
@@ -1419,8 +1416,9 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
goto out;
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
- E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
+ E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
+ E1000_WRITE_FLUSH(hw);
usec_delay(2);
@@ -1444,7 +1442,7 @@ out:
* before exiting.
**/
static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
- u16 data)
+ u16 data)
{
u32 kmrnctrlsta;
s32 ret_val = E1000_SUCCESS;
@@ -1456,8 +1454,9 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
goto out;
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
- E1000_KMRNCTRLSTA_OFFSET) | data;
+ E1000_KMRNCTRLSTA_OFFSET) | data;
E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
+ E1000_WRITE_FLUSH(hw);
usec_delay(2);
diff --git a/freebsd/sys/dev/e1000/e1000_80003es2lan.h b/freebsd/sys/dev/e1000/e1000_80003es2lan.h
index 3ab1ec9d..157468e4 100644
--- a/freebsd/sys/dev/e1000/e1000_80003es2lan.h
+++ b/freebsd/sys/dev/e1000/e1000_80003es2lan.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2009, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,48 +35,47 @@
#ifndef _E1000_80003ES2LAN_H_
#define _E1000_80003ES2LAN_H_
-#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00
-#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02
-#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10
-#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F
+#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00
+#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02
+#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10
+#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F
-#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008
-#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800
-#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010
+#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008
+#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800
+#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010
#define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
-#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000
-#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000
+#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000
+#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000
-#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C
-#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004
+#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C
+#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004
#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
-#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000
+#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000
-#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8
-#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9
+#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8
+#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9
/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
-#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Disabled */
-#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060
-#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */
-#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */
-#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */
+#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Disabled */
+#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060
+#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */
+#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */
+#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */
/* PHY Specific Control Register 2 (Page 0, Register 26) */
-#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000
- /* 1=Reverse Auto-Negotiation */
+#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Nego */
/* MAC Specific Control Register (Page 2, Register 21) */
/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
-#define GG82563_MSCR_TX_CLK_MASK 0x0007
-#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004
-#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005
-#define GG82563_MSCR_TX_CLK_1000MBPS_2_5 0x0006
-#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007
+#define GG82563_MSCR_TX_CLK_MASK 0x0007
+#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004
+#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005
+#define GG82563_MSCR_TX_CLK_1000MBPS_2_5 0x0006
+#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007
-#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */
+#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */
/* DSP Distance Register (Page 5, Register 26) */
/*
@@ -86,19 +85,19 @@
* 3 = 110-140M
* 4 = >140M
*/
-#define GG82563_DSPD_CABLE_LENGTH 0x0007
+#define GG82563_DSPD_CABLE_LENGTH 0x0007
/* Kumeran Mode Control Register (Page 193, Register 16) */
-#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800
+#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800
/* Max number of times Kumeran read/write should be validated */
-#define GG82563_MAX_KMRN_RETRY 0x5
+#define GG82563_MAX_KMRN_RETRY 0x5
/* Power Management Control Register (Page 193, Register 20) */
-#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001
- /* 1=Enable SERDES Electrical Idle */
+/* 1=Enable SERDES Electrical Idle */
+#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001
/* In-Band Control Register (Page 194, Register 18) */
-#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */
+#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */
#endif
diff --git a/freebsd/sys/dev/e1000/e1000_82540.c b/freebsd/sys/dev/e1000/e1000_82540.c
index c0e8932f..e8c46f3b 100644
--- a/freebsd/sys/dev/e1000/e1000_82540.c
+++ b/freebsd/sys/dev/e1000/e1000_82540.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -74,23 +74,23 @@ static s32 e1000_init_phy_params_82540(struct e1000_hw *hw)
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS;
- phy->addr = 1;
- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- phy->reset_delay_us = 10000;
- phy->type = e1000_phy_m88;
+ phy->addr = 1;
+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->reset_delay_us = 10000;
+ phy->type = e1000_phy_m88;
/* Function Pointers */
- phy->ops.check_polarity = e1000_check_polarity_m88;
- phy->ops.commit = e1000_phy_sw_reset_generic;
- phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
- phy->ops.get_cable_length = e1000_get_cable_length_m88;
- phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
- phy->ops.read_reg = e1000_read_phy_reg_m88;
- phy->ops.reset = e1000_phy_hw_reset_generic;
- phy->ops.write_reg = e1000_write_phy_reg_m88;
- phy->ops.get_info = e1000_get_phy_info_m88;
- phy->ops.power_up = e1000_power_up_phy_copper;
- phy->ops.power_down = e1000_power_down_phy_copper_82540;
+ phy->ops.check_polarity = e1000_check_polarity_m88;
+ phy->ops.commit = e1000_phy_sw_reset_generic;
+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
+ phy->ops.get_cable_length = e1000_get_cable_length_m88;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
+ phy->ops.read_reg = e1000_read_phy_reg_m88;
+ phy->ops.reset = e1000_phy_hw_reset_generic;
+ phy->ops.write_reg = e1000_write_phy_reg_m88;
+ phy->ops.get_info = e1000_get_phy_info_m88;
+ phy->ops.power_up = e1000_power_up_phy_copper;
+ phy->ops.power_down = e1000_power_down_phy_copper_82540;
ret_val = e1000_get_phy_id(hw);
if (ret_val)
@@ -127,32 +127,32 @@ static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_nvm_params_82540");
- nvm->type = e1000_nvm_eeprom_microwire;
- nvm->delay_usec = 50;
- nvm->opcode_bits = 3;
+ nvm->type = e1000_nvm_eeprom_microwire;
+ nvm->delay_usec = 50;
+ nvm->opcode_bits = 3;
switch (nvm->override) {
case e1000_nvm_override_microwire_large:
- nvm->address_bits = 8;
- nvm->word_size = 256;
+ nvm->address_bits = 8;
+ nvm->word_size = 256;
break;
case e1000_nvm_override_microwire_small:
- nvm->address_bits = 6;
- nvm->word_size = 64;
+ nvm->address_bits = 6;
+ nvm->word_size = 64;
break;
default:
- nvm->address_bits = eecd & E1000_EECD_SIZE ? 8 : 6;
- nvm->word_size = eecd & E1000_EECD_SIZE ? 256 : 64;
+ nvm->address_bits = eecd & E1000_EECD_SIZE ? 8 : 6;
+ nvm->word_size = eecd & E1000_EECD_SIZE ? 256 : 64;
break;
}
/* Function Pointers */
- nvm->ops.acquire = e1000_acquire_nvm_generic;
- nvm->ops.read = e1000_read_nvm_microwire;
- nvm->ops.release = e1000_release_nvm_generic;
- nvm->ops.update = e1000_update_nvm_checksum_generic;
- nvm->ops.valid_led_default = e1000_valid_led_default_generic;
- nvm->ops.validate = e1000_validate_nvm_checksum_generic;
- nvm->ops.write = e1000_write_nvm_microwire;
+ nvm->ops.acquire = e1000_acquire_nvm_generic;
+ nvm->ops.read = e1000_read_nvm_microwire;
+ nvm->ops.release = e1000_release_nvm_generic;
+ nvm->ops.update = e1000_update_nvm_checksum_generic;
+ nvm->ops.valid_led_default = e1000_valid_led_default_generic;
+ nvm->ops.validate = e1000_validate_nvm_checksum_generic;
+ nvm->ops.write = e1000_write_nvm_microwire;
return E1000_SUCCESS;
}
@@ -204,9 +204,9 @@ static s32 e1000_init_mac_params_82540(struct e1000_hw *hw)
mac->ops.setup_link = e1000_setup_link_generic;
/* physical interface setup */
mac->ops.setup_physical_interface =
- (hw->phy.media_type == e1000_media_type_copper)
- ? e1000_setup_copper_link_82540
- : e1000_setup_fiber_serdes_link_82540;
+ (hw->phy.media_type == e1000_media_type_copper)
+ ? e1000_setup_copper_link_82540
+ : e1000_setup_fiber_serdes_link_82540;
/* check for link */
switch (hw->phy.media_type) {
case e1000_media_type_copper:
@@ -225,9 +225,9 @@ static s32 e1000_init_mac_params_82540(struct e1000_hw *hw)
}
/* link info */
mac->ops.get_link_up_info =
- (hw->phy.media_type == e1000_media_type_copper)
- ? e1000_get_speed_and_duplex_copper_generic
- : e1000_get_speed_and_duplex_fiber_serdes_generic;
+ (hw->phy.media_type == e1000_media_type_copper)
+ ? e1000_get_speed_and_duplex_copper_generic
+ : e1000_get_speed_and_duplex_fiber_serdes_generic;
/* multicast address update */
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
/* writing VFTA */
@@ -275,7 +275,7 @@ void e1000_init_function_pointers_82540(struct e1000_hw *hw)
**/
static s32 e1000_reset_hw_82540(struct e1000_hw *hw)
{
- u32 ctrl, icr, manc;
+ u32 ctrl, manc;
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_reset_hw_82540");
@@ -320,7 +320,7 @@ static s32 e1000_reset_hw_82540(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_MANC, manc);
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
return ret_val;
}
@@ -380,7 +380,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw)
txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
- E1000_TXDCTL_FULL_TX_DESC_WB;
+ E1000_TXDCTL_FULL_TX_DESC_WB;
E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
/*
@@ -433,11 +433,13 @@ static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw)
if (hw->mac.type == e1000_82545_rev_3 ||
hw->mac.type == e1000_82546_rev_3) {
- ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &data);
+ ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
+ &data);
if (ret_val)
goto out;
data |= 0x00000008;
- ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, data);
+ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+ data);
if (ret_val)
goto out;
}
@@ -514,9 +516,8 @@ static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw)
if (nvm_data != NVM_RESERVED_WORD) {
/* Adjust serdes output amplitude only. */
nvm_data &= NVM_SERDES_AMPLITUDE_MASK;
- ret_val = hw->phy.ops.write_reg(hw,
- M88E1000_PHY_EXT_CTRL,
- nvm_data);
+ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_EXT_CTRL,
+ nvm_data);
if (ret_val)
goto out;
}
@@ -541,9 +542,8 @@ static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw)
/* Set PHY register 30, page 5, bit 8 to 0 */
- ret_val = hw->phy.ops.read_reg(hw,
- M88E1000_PHY_PAGE_SELECT,
- &default_page);
+ ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_PAGE_SELECT,
+ &default_page);
if (ret_val)
goto out;
@@ -576,7 +576,7 @@ static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw)
goto out;
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
- default_page);
+ default_page);
out:
return ret_val;
@@ -593,7 +593,6 @@ out:
**/
static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw)
{
- struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS;
u16 nvm_data;
@@ -610,20 +609,18 @@ static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw)
if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) {
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
- 0x000B);
+ 0x000B);
if (ret_val) {
ret_val = -E1000_ERR_PHY;
goto out;
}
- ret_val = hw->phy.ops.write_reg(hw,
- M88E1000_PHY_GEN_CONTROL,
- 0x8104);
+ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL,
+ 0x8104);
if (ret_val) {
ret_val = -E1000_ERR_PHY;
goto out;
}
- phy->reset_disable = FALSE;
}
out:
diff --git a/freebsd/sys/dev/e1000/e1000_82541.c b/freebsd/sys/dev/e1000/e1000_82541.c
index 2b655738..a3c05f82 100644
--- a/freebsd/sys/dev/e1000/e1000_82541.c
+++ b/freebsd/sys/dev/e1000/e1000_82541.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -555,8 +555,6 @@ static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw)
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
- hw->phy.reset_disable = FALSE;
-
/* Earlier revs of the IGP phy require us to force MDI. */
if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) {
dev_spec->dsp_config = e1000_dsp_config_disabled;
@@ -650,7 +648,7 @@ static s32 e1000_check_for_link_82541(struct e1000_hw *hw)
* of MAC speed/duplex configuration. So we only need to
* configure Collision Distance in the MAC.
*/
- e1000_config_collision_dist_generic(hw);
+ mac->ops.config_collision_dist(hw);
/*
* Configure Flow Control now that Auto-Neg has completed.
diff --git a/freebsd/sys/dev/e1000/e1000_82542.c b/freebsd/sys/dev/e1000/e1000_82542.c
index 1e2f8671..4d6986ac 100644
--- a/freebsd/sys/dev/e1000/e1000_82542.c
+++ b/freebsd/sys/dev/e1000/e1000_82542.c
@@ -57,7 +57,6 @@ static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index);
static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw);
static s32 e1000_read_mac_addr_82542(struct e1000_hw *hw);
-
/**
* e1000_init_phy_params_82542 - Init PHY func ptrs.
* @hw: pointer to the HW structure
@@ -198,7 +197,7 @@ static s32 e1000_reset_hw_82542(struct e1000_hw *hw)
{
struct e1000_bus_info *bus = &hw->bus;
s32 ret_val = E1000_SUCCESS;
- u32 ctrl, icr;
+ u32 ctrl;
DEBUGFUNC("e1000_reset_hw_82542");
@@ -229,7 +228,7 @@ static s32 e1000_reset_hw_82542(struct e1000_hw *hw)
msec_delay(2);
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
if (hw->revision_id == E1000_REVISION_2) {
if (bus->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
diff --git a/freebsd/sys/dev/e1000/e1000_82543.c b/freebsd/sys/dev/e1000/e1000_82543.c
index ccf5bddf..f0b58519 100644
--- a/freebsd/sys/dev/e1000/e1000_82543.c
+++ b/freebsd/sys/dev/e1000/e1000_82543.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -1085,7 +1085,6 @@ static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
ret_val = hw->phy.ops.reset(hw);
if (ret_val)
goto out;
- hw->phy.reset_disable = FALSE;
} else {
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
@@ -1133,7 +1132,7 @@ static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
DEBUGOUT("Valid link established!!!\n");
/* Config the MAC and PHY after link is up */
if (hw->mac.type == e1000_82544) {
- e1000_config_collision_dist_generic(hw);
+ hw->mac.ops.config_collision_dist(hw);
} else {
ret_val = e1000_config_mac_to_phy_82543(hw);
if (ret_val)
@@ -1167,7 +1166,7 @@ static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw)
/* Take the link out of reset */
ctrl &= ~E1000_CTRL_LRST;
- e1000_config_collision_dist_generic(hw);
+ hw->mac.ops.config_collision_dist(hw);
ret_val = e1000_commit_fc_settings_generic(hw);
if (ret_val)
@@ -1266,7 +1265,7 @@ static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
* settings.
*/
if (mac->type == e1000_82544)
- e1000_config_collision_dist_generic(hw);
+ hw->mac.ops.config_collision_dist(hw);
else {
ret_val = e1000_config_mac_to_phy_82543(hw);
if (ret_val) {
@@ -1440,7 +1439,7 @@ static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw)
if (phy_data & M88E1000_PSSR_DPLX)
ctrl |= E1000_CTRL_FD;
- e1000_config_collision_dist_generic(hw);
+ hw->mac.ops.config_collision_dist(hw);
/*
* Set up speed in the Device Control register depending on
diff --git a/freebsd/sys/dev/e1000/e1000_82571.c b/freebsd/sys/dev/e1000/e1000_82571.c
index 8faf6f91..fe87aa71 100644
--- a/freebsd/sys/dev/e1000/e1000_82571.c
+++ b/freebsd/sys/dev/e1000/e1000_82571.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -34,8 +34,7 @@
******************************************************************************/
/*$FreeBSD$*/
-/*
- * 82571EB Gigabit Ethernet Controller
+/* 82571EB Gigabit Ethernet Controller
* 82571EB Gigabit Ethernet Controller (Copper)
* 82571EB Gigabit Ethernet Controller (Fiber)
* 82571EB Dual Port Gigabit Mezzanine Adapter
@@ -57,18 +56,15 @@
#include <rtems/bsd/local/e1000_api.h>
#endif
-static s32 e1000_init_phy_params_82571(struct e1000_hw *hw);
-static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw);
-static s32 e1000_init_mac_params_82571(struct e1000_hw *hw);
static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw);
static void e1000_release_nvm_82571(struct e1000_hw *hw);
static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
+ u16 words, u16 *data);
static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw);
static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw);
static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw);
static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw,
- bool active);
+ bool active);
static s32 e1000_reset_hw_82571(struct e1000_hw *hw);
static s32 e1000_init_hw_82571(struct e1000_hw *hw);
static void e1000_clear_vfta_82571(struct e1000_hw *hw);
@@ -84,13 +80,16 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw);
static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);
static s32 e1000_get_phy_id_82571(struct e1000_hw *hw);
static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
-static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw);
static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw);
static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw);
static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw);
+static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw,
+ bool active);
+static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw,
+ bool active);
static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);
static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
+ u16 words, u16 *data);
static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw);
static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);
@@ -101,106 +100,107 @@ static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);
static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- struct e1000_dev_spec_82571 *dev_spec = &hw->dev_spec._82571;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_init_phy_params_82571");
if (hw->phy.media_type != e1000_media_type_copper) {
phy->type = e1000_phy_none;
- goto out;
+ return E1000_SUCCESS;
}
- phy->addr = 1;
- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- phy->reset_delay_us = 100;
+ phy->addr = 1;
+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->reset_delay_us = 100;
- phy->ops.check_reset_block = e1000_check_reset_block_generic;
- phy->ops.reset = e1000_phy_hw_reset_generic;
- phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82571;
- phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
- phy->ops.power_up = e1000_power_up_phy_copper;
- phy->ops.power_down = e1000_power_down_phy_copper_82571;
+ phy->ops.check_reset_block = e1000_check_reset_block_generic;
+ phy->ops.reset = e1000_phy_hw_reset_generic;
+ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82571;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
+ phy->ops.power_up = e1000_power_up_phy_copper;
+ phy->ops.power_down = e1000_power_down_phy_copper_82571;
switch (hw->mac.type) {
case e1000_82571:
case e1000_82572:
- phy->type = e1000_phy_igp_2;
- phy->ops.get_cfg_done = e1000_get_cfg_done_82571;
- phy->ops.get_info = e1000_get_phy_info_igp;
- phy->ops.check_polarity = e1000_check_polarity_igp;
+ phy->type = e1000_phy_igp_2;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_82571;
+ phy->ops.get_info = e1000_get_phy_info_igp;
+ phy->ops.check_polarity = e1000_check_polarity_igp;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
- phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
- phy->ops.read_reg = e1000_read_phy_reg_igp;
- phy->ops.write_reg = e1000_write_phy_reg_igp;
- phy->ops.acquire = e1000_get_hw_semaphore_82571;
- phy->ops.release = e1000_put_hw_semaphore_82571;
-
- /* This uses above function pointers */
- ret_val = e1000_get_phy_id_82571(hw);
-
- /* Verify PHY ID */
- if (phy->id != IGP01E1000_I_PHY_ID) {
- ret_val = -E1000_ERR_PHY;
- DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
- goto out;
- }
+ phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
+ phy->ops.read_reg = e1000_read_phy_reg_igp;
+ phy->ops.write_reg = e1000_write_phy_reg_igp;
+ phy->ops.acquire = e1000_get_hw_semaphore_82571;
+ phy->ops.release = e1000_put_hw_semaphore_82571;
break;
case e1000_82573:
- phy->type = e1000_phy_m88;
- phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
- phy->ops.get_info = e1000_get_phy_info_m88;
- phy->ops.check_polarity = e1000_check_polarity_m88;
- phy->ops.commit = e1000_phy_sw_reset_generic;
+ phy->type = e1000_phy_m88;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
+ phy->ops.get_info = e1000_get_phy_info_m88;
+ phy->ops.check_polarity = e1000_check_polarity_m88;
+ phy->ops.commit = e1000_phy_sw_reset_generic;
+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
+ phy->ops.get_cable_length = e1000_get_cable_length_m88;
+ phy->ops.read_reg = e1000_read_phy_reg_m88;
+ phy->ops.write_reg = e1000_write_phy_reg_m88;
+ phy->ops.acquire = e1000_get_hw_semaphore_82571;
+ phy->ops.release = e1000_put_hw_semaphore_82571;
+ break;
+ case e1000_82574:
+ case e1000_82583:
+ E1000_MUTEX_INIT(&hw->dev_spec._82571.swflag_mutex);
+
+ phy->type = e1000_phy_bm;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
+ phy->ops.get_info = e1000_get_phy_info_m88;
+ phy->ops.check_polarity = e1000_check_polarity_m88;
+ phy->ops.commit = e1000_phy_sw_reset_generic;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
- phy->ops.get_cable_length = e1000_get_cable_length_m88;
- phy->ops.read_reg = e1000_read_phy_reg_m88;
- phy->ops.write_reg = e1000_write_phy_reg_m88;
- phy->ops.acquire = e1000_get_hw_semaphore_82571;
- phy->ops.release = e1000_put_hw_semaphore_82571;
+ phy->ops.get_cable_length = e1000_get_cable_length_m88;
+ phy->ops.read_reg = e1000_read_phy_reg_bm2;
+ phy->ops.write_reg = e1000_write_phy_reg_bm2;
+ phy->ops.acquire = e1000_get_hw_semaphore_82574;
+ phy->ops.release = e1000_put_hw_semaphore_82574;
+ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574;
+ break;
+ default:
+ return -E1000_ERR_PHY;
+ break;
+ }
- /* This uses above function pointers */
- ret_val = e1000_get_phy_id_82571(hw);
+ /* This can only be done after all function pointers are setup. */
+ ret_val = e1000_get_phy_id_82571(hw);
+ if (ret_val) {
+ DEBUGOUT("Error getting PHY ID\n");
+ return ret_val;
+ }
- /* Verify PHY ID */
- if (phy->id != M88E1111_I_PHY_ID) {
+ /* Verify phy id */
+ switch (hw->mac.type) {
+ case e1000_82571:
+ case e1000_82572:
+ if (phy->id != IGP01E1000_I_PHY_ID)
+ ret_val = -E1000_ERR_PHY;
+ break;
+ case e1000_82573:
+ if (phy->id != M88E1111_I_PHY_ID)
ret_val = -E1000_ERR_PHY;
- DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
- goto out;
- }
break;
case e1000_82574:
case e1000_82583:
- E1000_MUTEX_INIT(&dev_spec->swflag_mutex);
-
- phy->type = e1000_phy_bm;
- phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
- phy->ops.get_info = e1000_get_phy_info_m88;
- phy->ops.check_polarity = e1000_check_polarity_m88;
- phy->ops.commit = e1000_phy_sw_reset_generic;
- phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
- phy->ops.get_cable_length = e1000_get_cable_length_m88;
- phy->ops.read_reg = e1000_read_phy_reg_bm2;
- phy->ops.write_reg = e1000_write_phy_reg_bm2;
- phy->ops.acquire = e1000_get_hw_semaphore_82574;
- phy->ops.release = e1000_put_hw_semaphore_82574;
-
- /* This uses above function pointers */
- ret_val = e1000_get_phy_id_82571(hw);
- /* Verify PHY ID */
- if (phy->id != BME1000_E_PHY_ID_R2) {
+ if (phy->id != BME1000_E_PHY_ID_R2)
ret_val = -E1000_ERR_PHY;
- DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
- goto out;
- }
break;
default:
ret_val = -E1000_ERR_PHY;
- goto out;
break;
}
-out:
+ if (ret_val)
+ DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
+
return ret_val;
}
@@ -240,8 +240,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
if (((eecd >> 15) & 0x3) == 0x3) {
nvm->type = e1000_nvm_flash_hw;
nvm->word_size = 2048;
- /*
- * Autonomous Flash update bit must be cleared due
+ /* Autonomous Flash update bit must be cleared due
* to Flash update issue.
*/
eecd &= ~E1000_EECD_AUPDEN;
@@ -252,9 +251,8 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
default:
nvm->type = e1000_nvm_eeprom_spi;
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
- E1000_EECD_SIZE_EX_SHIFT);
- /*
- * Added to a constant, "size" becomes the left-shift value
+ E1000_EECD_SIZE_EX_SHIFT);
+ /* Added to a constant, "size" becomes the left-shift value
* for setting word_size.
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
@@ -262,7 +260,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
/* EEPROM access above 16k is unsupported */
if (size > 14)
size = 14;
- nvm->word_size = 1 << size;
+ nvm->word_size = 1 << size;
break;
}
@@ -278,11 +276,11 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
nvm->ops.release = e1000_release_nvm_82571;
break;
}
- nvm->ops.read = e1000_read_nvm_eerd;
- nvm->ops.update = e1000_update_nvm_checksum_82571;
- nvm->ops.validate = e1000_validate_nvm_checksum_82571;
+ nvm->ops.read = e1000_read_nvm_eerd;
+ nvm->ops.update = e1000_update_nvm_checksum_82571;
+ nvm->ops.validate = e1000_validate_nvm_checksum_82571;
nvm->ops.valid_led_default = e1000_valid_led_default_82571;
- nvm->ops.write = e1000_write_nvm_82571;
+ nvm->ops.write = e1000_write_nvm_82571;
return E1000_SUCCESS;
}
@@ -362,8 +360,6 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
mac->ops.read_mac_addr = e1000_read_mac_addr_82571;
/* ID LED init */
mac->ops.id_led_init = e1000_id_led_init_generic;
- /* blink LED */
- mac->ops.blink_led = e1000_blink_led_generic;
/* setup LED */
mac->ops.setup_led = e1000_setup_led_generic;
/* cleanup LED */
@@ -379,16 +375,15 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
mac->ops.set_lan_id = e1000_set_lan_id_single_port;
mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
mac->ops.led_on = e1000_led_on_generic;
+ mac->ops.blink_led = e1000_blink_led_generic;
/* FWSM register */
mac->has_fwsm = TRUE;
- /*
- * ARC supported; valid only if manageability features are
+ /* ARC supported; valid only if manageability features are
* enabled.
*/
- mac->arc_subsystem_valid =
- (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK)
- ? TRUE : FALSE;
+ mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) &
+ E1000_FWSM_MODE_MASK);
break;
case e1000_82574:
case e1000_82583:
@@ -399,14 +394,14 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
default:
mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
mac->ops.led_on = e1000_led_on_generic;
+ mac->ops.blink_led = e1000_blink_led_generic;
/* FWSM register */
mac->has_fwsm = TRUE;
break;
}
- /*
- * Ensure that the inter-port SWSM.SMBI lock bit is clear before
+ /* Ensure that the inter-port SWSM.SMBI lock bit is clear before
* first NVM or PHY acess. This should be done for single-port
* devices, and for one port only on dual-port devices so that
* for those devices we can still use the SMBI lock to synchronize
@@ -419,11 +414,12 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
if (!(swsm2 & E1000_SWSM2_LOCK)) {
/* Only do this for the first interface on this card */
- E1000_WRITE_REG(hw, E1000_SWSM2,
- swsm2 | E1000_SWSM2_LOCK);
+ E1000_WRITE_REG(hw, E1000_SWSM2, swsm2 |
+ E1000_SWSM2_LOCK);
force_clear_smbi = TRUE;
- } else
+ } else {
force_clear_smbi = FALSE;
+ }
break;
default:
force_clear_smbi = TRUE;
@@ -443,10 +439,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_SWSM, swsm & ~E1000_SWSM_SMBI);
}
- /*
- * Initialze device specific counter of SMBI acquisition
- * timeouts.
- */
+ /* Initialze device specific counter of SMBI acquisition timeouts. */
hw->dev_spec._82571.smb_counter = 0;
return E1000_SUCCESS;
@@ -477,7 +470,7 @@ void e1000_init_function_pointers_82571(struct e1000_hw *hw)
static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 phy_id = 0;
DEBUGFUNC("e1000_get_phy_id_82571");
@@ -485,8 +478,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
switch (hw->mac.type) {
case e1000_82571:
case e1000_82572:
- /*
- * The 82571 firmware may still be configuring the PHY.
+ /* The 82571 firmware may still be configuring the PHY.
* In this case, we cannot access the PHY until the
* configuration is done. So we explicitly set the
* PHY ID.
@@ -494,29 +486,29 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
phy->id = IGP01E1000_I_PHY_ID;
break;
case e1000_82573:
- ret_val = e1000_get_phy_id(hw);
+ return e1000_get_phy_id(hw);
break;
case e1000_82574:
case e1000_82583:
ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
if (ret_val)
- goto out;
+ return ret_val;
phy->id = (u32)(phy_id << 16);
usec_delay(20);
ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
if (ret_val)
- goto out;
+ return ret_val;
phy->id |= (u32)(phy_id);
phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
break;
default:
- ret_val = -E1000_ERR_PHY;
+ return -E1000_ERR_PHY;
break;
}
-out:
- return ret_val;
+
+ return E1000_SUCCESS;
}
/**
@@ -528,15 +520,13 @@ out:
static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
{
u32 swsm;
- s32 ret_val = E1000_SUCCESS;
s32 sw_timeout = hw->nvm.word_size + 1;
s32 fw_timeout = hw->nvm.word_size + 1;
s32 i = 0;
DEBUGFUNC("e1000_get_hw_semaphore_82571");
- /*
- * If we have timedout 3 times on trying to acquire
+ /* If we have timedout 3 times on trying to acquire
* the inter-port SMBI semaphore, there is old code
* operating on the other port, and it is not
* releasing SMBI. Modify the number of times that
@@ -576,12 +566,10 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
/* Release semaphores */
e1000_put_hw_semaphore_82571(hw);
DEBUGOUT("Driver can't access the NVM\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -613,22 +601,19 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
{
u32 extcnf_ctrl;
- s32 ret_val = E1000_SUCCESS;
s32 i = 0;
DEBUGFUNC("e1000_get_hw_semaphore_82573");
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
- extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
do {
+ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
break;
- extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-
msec_delay(2);
i++;
} while (i < MDIO_OWNERSHIP_TIMEOUT);
@@ -637,12 +622,10 @@ static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
/* Release semaphores */
e1000_put_hw_semaphore_82573(hw);
DEBUGOUT("Driver can't access the PHY\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -699,6 +682,62 @@ static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw)
}
/**
+ * e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state
+ * @hw: pointer to the HW structure
+ * @active: TRUE to enable LPLU, FALSE to disable
+ *
+ * Sets the LPLU D0 state according to the active flag.
+ * LPLU will not be activated unless the
+ * device autonegotiation advertisement meets standards of
+ * either 10 or 10/100 or 10/100/1000 at all duplexes.
+ * This is a function pointer entry point only called by
+ * PHY setup routines.
+ **/
+static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active)
+{
+ u32 data = E1000_READ_REG(hw, E1000_POEMB);
+
+ DEBUGFUNC("e1000_set_d0_lplu_state_82574");
+
+ if (active)
+ data |= E1000_PHY_CTRL_D0A_LPLU;
+ else
+ data &= ~E1000_PHY_CTRL_D0A_LPLU;
+
+ E1000_WRITE_REG(hw, E1000_POEMB, data);
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3
+ * @hw: pointer to the HW structure
+ * @active: boolean used to enable/disable lplu
+ *
+ * The low power link up (lplu) state is set to the power management level D3
+ * when active is TRUE, else clear lplu for D3. LPLU
+ * is used during Dx states where the power conservation is most important.
+ * During driver activity, SmartSpeed should be enabled so performance is
+ * maintained.
+ **/
+static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active)
+{
+ u32 data = E1000_READ_REG(hw, E1000_POEMB);
+
+ DEBUGFUNC("e1000_set_d3_lplu_state_82574");
+
+ if (!active) {
+ data &= ~E1000_PHY_CTRL_NOND0A_LPLU;
+ } else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+ (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) ||
+ (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) {
+ data |= E1000_PHY_CTRL_NOND0A_LPLU;
+ }
+
+ E1000_WRITE_REG(hw, E1000_POEMB, data);
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_acquire_nvm_82571 - Request for access to the EEPROM
* @hw: pointer to the HW structure
*
@@ -715,7 +754,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
ret_val = e1000_get_hw_semaphore_82571(hw);
if (ret_val)
- goto out;
+ return ret_val;
switch (hw->mac.type) {
case e1000_82573:
@@ -728,7 +767,6 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
if (ret_val)
e1000_put_hw_semaphore_82571(hw);
-out:
return ret_val;
}
@@ -759,9 +797,9 @@ static void e1000_release_nvm_82571(struct e1000_hw *hw)
* EEPROM will most likely contain an invalid checksum.
**/
static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+ u16 *data)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_write_nvm_82571");
@@ -801,31 +839,27 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
ret_val = e1000_update_nvm_checksum_generic(hw);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * If our nvm is an EEPROM, then we're done
+ /* If our nvm is an EEPROM, then we're done
* otherwise, commit the checksum to the flash NVM.
*/
if (hw->nvm.type != e1000_nvm_flash_hw)
- goto out;
+ return E1000_SUCCESS;
/* Check for pending operations. */
for (i = 0; i < E1000_FLASH_UPDATES; i++) {
msec_delay(1);
- if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0)
+ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD))
break;
}
- if (i == E1000_FLASH_UPDATES) {
- ret_val = -E1000_ERR_NVM;
- goto out;
- }
+ if (i == E1000_FLASH_UPDATES)
+ return -E1000_ERR_NVM;
/* Reset the firmware if using STM opcode. */
if ((E1000_READ_REG(hw, E1000_FLOP) & 0xFF00) == E1000_STM_OPCODE) {
- /*
- * The enabling of and the actual reset must be done
+ /* The enabling of and the actual reset must be done
* in two write cycles.
*/
E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET_ENABLE);
@@ -839,17 +873,14 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
for (i = 0; i < E1000_FLASH_UPDATES; i++) {
msec_delay(1);
- if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0)
+ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD))
break;
}
- if (i == E1000_FLASH_UPDATES) {
- ret_val = -E1000_ERR_NVM;
- goto out;
- }
+ if (i == E1000_FLASH_UPDATES)
+ return -E1000_ERR_NVM;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -884,23 +915,21 @@ static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw)
* EEPROM will most likely contain an invalid checksum.
**/
static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data)
+ u16 words, u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 i, eewr = 0;
- s32 ret_val = 0;
+ s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_nvm_eewr_82571");
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
for (i = 0; i < words; i++) {
@@ -919,7 +948,6 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
break;
}
-out:
return ret_val;
}
@@ -932,7 +960,6 @@ out:
static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw)
{
s32 timeout = PHY_CFG_TIMEOUT;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_get_cfg_done_82571");
@@ -945,12 +972,10 @@ static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw)
}
if (!timeout) {
DEBUGOUT("MNG configuration cycle has not completed.\n");
- ret_val = -E1000_ERR_RESET;
- goto out;
+ return -E1000_ERR_RESET;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -967,74 +992,74 @@ out:
static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 data;
DEBUGFUNC("e1000_set_d0_lplu_state_82571");
if (!(phy->ops.read_reg))
- goto out;
+ return E1000_SUCCESS;
ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
if (ret_val)
- goto out;
+ return ret_val;
if (active) {
data |= IGP02E1000_PM_D0_LPLU;
ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- data);
+ data);
if (ret_val)
- goto out;
+ return ret_val;
/* When LPLU is enabled, we should disable SmartSpeed */
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ &data);
+ if (ret_val)
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- data);
+ data);
if (ret_val)
- goto out;
+ return ret_val;
} else {
data &= ~IGP02E1000_PM_D0_LPLU;
ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- data);
- /*
- * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ data);
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
* important. During driver activity we should enable
* SmartSpeed, so performance is maintained.
*/
if (phy->smart_speed == e1000_smart_speed_on) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data |= IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
} else if (phy->smart_speed == e1000_smart_speed_off) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
}
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1045,13 +1070,12 @@ out:
**/
static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
{
- u32 ctrl, ctrl_ext, icr;
+ u32 ctrl, ctrl_ext, eecd, tctl;
s32 ret_val;
DEBUGFUNC("e1000_reset_hw_82571");
- /*
- * Prevent the PCI-E bus from sticking if there is no TLP connection
+ /* Prevent the PCI-E bus from sticking if there is no TLP connection
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = e1000_disable_pcie_master_generic(hw);
@@ -1062,13 +1086,14 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
E1000_WRITE_REG(hw, E1000_RCTL, 0);
- E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+ tctl = E1000_READ_REG(hw, E1000_TCTL);
+ tctl &= ~E1000_TCTL_EN;
+ E1000_WRITE_REG(hw, E1000_TCTL, tctl);
E1000_WRITE_FLUSH(hw);
msec_delay(10);
- /*
- * Must acquire the MDIO ownership before MAC reset.
+ /* Must acquire the MDIO ownership before MAC reset.
* Ownership defaults to firmware after a reset.
*/
switch (hw->mac.type) {
@@ -1111,15 +1136,23 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
ret_val = e1000_get_auto_rd_done_generic(hw);
if (ret_val)
/* We don't want to continue accessing MAC registers. */
- goto out;
+ return ret_val;
- /*
- * Phy configuration from NVM just starts after EECD_AUTO_RD is set.
+ /* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
* Need to wait for Phy configuration completion before accessing
* NVM and Phy.
*/
switch (hw->mac.type) {
+ case e1000_82571:
+ case e1000_82572:
+ /* REQ and GNT bits need to be cleared when using AUTO_RD
+ * to access the EEPROM.
+ */
+ eecd = E1000_READ_REG(hw, E1000_EECD);
+ eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT);
+ E1000_WRITE_REG(hw, E1000_EECD, eecd);
+ break;
case e1000_82573:
case e1000_82574:
case e1000_82583:
@@ -1131,13 +1164,13 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
/* Clear any pending interrupt events. */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
if (hw->mac.type == e1000_82571) {
/* Install any alternate MAC address into RAR0 */
ret_val = e1000_check_alt_mac_addr_generic(hw);
if (ret_val)
- goto out;
+ return ret_val;
e1000_set_laa_state_82571(hw, TRUE);
}
@@ -1146,8 +1179,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
if (hw->phy.media_type == e1000_media_type_internal_serdes)
hw->mac.serdes_link_state = e1000_serdes_link_down;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1169,16 +1201,15 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
/* Initialize identification LED */
ret_val = mac->ops.id_led_init(hw);
+ /* An error is not fatal and we should not stop init due to this */
if (ret_val)
DEBUGOUT("Error initializing identification LED\n");
- /* This is not fatal and we should not stop init due to this */
/* Disabling VLAN filtering */
DEBUGOUT("Initializing the IEEE VLAN\n");
mac->ops.clear_vfta(hw);
- /* Setup the receive address. */
- /*
+ /* Setup the receive address.
* If, however, a locally administered address was assigned to the
* 82571, we must reserve a RAR for it to work around an issue where
* resetting one port will reload the MAC on the other port.
@@ -1198,8 +1229,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
/* Set the transmit descriptor write-back policy */
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
- E1000_TXDCTL_FULL_TX_DESC_WB |
- E1000_TXDCTL_COUNT_DESC;
+ E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
/* ...for both queues. */
@@ -1216,14 +1246,13 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
default:
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
- E1000_TXDCTL_FULL_TX_DESC_WB |
- E1000_TXDCTL_COUNT_DESC;
+ E1000_TXDCTL_FULL_TX_DESC_WB |
+ E1000_TXDCTL_COUNT_DESC;
E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
break;
}
- /*
- * Clear all of the statistics registers (clear on read). It is
+ /* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
* is no link.
@@ -1263,6 +1292,10 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
case e1000_82572:
reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26);
break;
+ case e1000_82574:
+ case e1000_82583:
+ reg |= (1 << 26);
+ break;
default:
break;
}
@@ -1318,8 +1351,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_PBA_ECC, reg);
}
- /*
- * Workaround for hardware errata.
+ /* Workaround for hardware errata.
* Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572
*/
if ((hw->mac.type == e1000_82571) ||
@@ -1329,6 +1361,15 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
}
+ /* Disable IPv6 extension header parsing because some malformed
+ * IPv6 headers can hang the Rx.
+ */
+ if (hw->mac.type <= e1000_82573) {
+ reg = E1000_READ_REG(hw, E1000_RFCTL);
+ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
+ E1000_WRITE_REG(hw, E1000_RFCTL, reg);
+ }
+
/* PCI-Ex Control Registers */
switch (hw->mac.type) {
case e1000_82574:
@@ -1337,12 +1378,11 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
reg |= (1 << 22);
E1000_WRITE_REG(hw, E1000_GCR, reg);
- /*
- * Workaround for hardware errata.
+ /* Workaround for hardware errata.
* apply workaround for hardware errata documented in errata
* docs Fixes issue where some error prone or unreliable PCIe
* completions are occurring, particularly with ASPM enabled.
- * Without fix, issue can cause tx timeouts.
+ * Without fix, issue can cause Tx timeouts.
*/
reg = E1000_READ_REG(hw, E1000_GCR2);
reg |= 1;
@@ -1376,25 +1416,25 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw)
case e1000_82574:
case e1000_82583:
if (hw->mng_cookie.vlan_id != 0) {
- /*
- * The VFTA is a 4096b bit-field, each identifying
+ /* The VFTA is a 4096b bit-field, each identifying
* a single VLAN ID. The following operations
* determine which 32b entry (i.e. offset) into the
* array we want to set the VLAN ID (i.e. bit) of
* the manageability unit.
*/
vfta_offset = (hw->mng_cookie.vlan_id >>
- E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK;
- vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id &
- E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
+ E1000_VFTA_ENTRY_SHIFT) &
+ E1000_VFTA_ENTRY_MASK;
+ vfta_bit_in_reg =
+ 1 << (hw->mng_cookie.vlan_id &
+ E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
}
break;
default:
break;
}
for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
- /*
- * If the offset we want to clear is the same offset of the
+ /* If the offset we want to clear is the same offset of the
* manageability VLAN ID, then clear all bits except that of
* the manageability unit.
*/
@@ -1436,8 +1476,7 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw)
ctrl = hw->mac.ledctl_mode2;
if (!(E1000_STATUS_LU & E1000_READ_REG(hw, E1000_STATUS))) {
- /*
- * If no link, then turn LED on by setting the invert bit
+ /* If no link, then turn LED on by setting the invert bit
* for each LED that's "on" (0x0E) in ledctl_mode2.
*/
for (i = 0; i < 4; i++)
@@ -1460,30 +1499,28 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
{
u16 status_1kbt = 0;
u16 receive_errors = 0;
- bool phy_hung = FALSE;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_check_phy_82574");
- /*
- * Read PHY Receive Error counter first, if its is max - all F's then
+ /* Read PHY Receive Error counter first, if its is max - all F's then
* read the Base1000T status register If both are max then PHY is hung.
*/
ret_val = hw->phy.ops.read_reg(hw, E1000_RECEIVE_ERROR_COUNTER,
- &receive_errors);
+ &receive_errors);
if (ret_val)
- goto out;
- if (receive_errors == E1000_RECEIVE_ERROR_MAX) {
+ return FALSE;
+ if (receive_errors == E1000_RECEIVE_ERROR_MAX) {
ret_val = hw->phy.ops.read_reg(hw, E1000_BASE1000T_STATUS,
- &status_1kbt);
+ &status_1kbt);
if (ret_val)
- goto out;
+ return FALSE;
if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) ==
E1000_IDLE_ERROR_COUNT_MASK)
- phy_hung = TRUE;
+ return TRUE;
}
-out:
- return phy_hung;
+
+ return FALSE;
}
@@ -1501,8 +1538,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_setup_link_82571");
- /*
- * 82573 does not have a word in the NVM to determine
+ /* 82573 does not have a word in the NVM to determine
* the default flow control setting, so we explicitly
* set it to full.
*/
@@ -1516,6 +1552,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
default:
break;
}
+
return e1000_setup_link_generic(hw);
}
@@ -1548,17 +1585,14 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
ret_val = e1000_copper_link_setup_igp(hw);
break;
default:
- ret_val = -E1000_ERR_PHY;
+ return -E1000_ERR_PHY;
break;
}
if (ret_val)
- goto out;
-
- ret_val = e1000_setup_copper_link_generic(hw);
+ return ret_val;
-out:
- return ret_val;
+ return e1000_setup_copper_link_generic(hw);
}
/**
@@ -1575,14 +1609,14 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
switch (hw->mac.type) {
case e1000_82571:
case e1000_82572:
- /*
- * If SerDes loopback mode is entered, there is no form
+ /* If SerDes loopback mode is entered, there is no form
* of reset to take the adapter out of that mode. So we
* have to explicitly take the adapter out of loopback
* mode. This prevents drivers from twiddling their thumbs
* if another tool failed to take it out of loopback mode.
*/
- E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
+ E1000_WRITE_REG(hw, E1000_SCTL,
+ E1000_SCTL_DISABLE_SERDES_LOOPBACK);
break;
default:
break;
@@ -1606,7 +1640,7 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
*
* 1) down
* 2) autoneg_progress
- * 3) autoneg_complete (the link sucessfully autonegotiated)
+ * 3) autoneg_complete (the link successfully autonegotiated)
* 4) forced_up (the link has been forced up, it did not autonegotiate)
*
**/
@@ -1624,16 +1658,17 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
ctrl = E1000_READ_REG(hw, E1000_CTRL);
status = E1000_READ_REG(hw, E1000_STATUS);
+ E1000_READ_REG(hw, E1000_RXCW);
+ /* SYNCH bit and IV bit are sticky */
+ usec_delay(10);
rxcw = E1000_READ_REG(hw, E1000_RXCW);
if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
-
/* Receiver is synchronized with no invalid bits. */
switch (mac->serdes_link_state) {
case e1000_serdes_link_autoneg_complete:
if (!(status & E1000_STATUS_LU)) {
- /*
- * We have lost link, retry autoneg before
+ /* We have lost link, retry autoneg before
* reporting link failure
*/
mac->serdes_link_state =
@@ -1646,15 +1681,12 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
break;
case e1000_serdes_link_forced_up:
- /*
- * If we are receiving /C/ ordered sets, re-enable
+ /* If we are receiving /C/ ordered sets, re-enable
* auto-negotiation in the TXCW register and disable
* forced link in the Device Control register in an
* attempt to auto-negotiate with our link partner.
- * If the partner code word is null, stop forcing
- * and restart auto negotiation.
*/
- if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) {
+ if (rxcw & E1000_RXCW_C) {
/* Enable autoneg, and unforce link up */
E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
E1000_WRITE_REG(hw, E1000_CTRL,
@@ -1670,8 +1702,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
case e1000_serdes_link_autoneg_progress:
if (rxcw & E1000_RXCW_C) {
- /*
- * We received /C/ ordered sets, meaning the
+ /* We received /C/ ordered sets, meaning the
* link partner has autonegotiated, and we can
* trust the Link Up (LU) status bit.
*/
@@ -1687,8 +1718,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
DEBUGOUT("AN_PROG -> DOWN\n");
}
} else {
- /*
- * The link partner did not autoneg.
+ /* The link partner did not autoneg.
* Force link up and full duplex, and change
* state to forced.
*/
@@ -1705,7 +1735,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
break;
}
mac->serdes_link_state =
- e1000_serdes_link_forced_up;
+ e1000_serdes_link_forced_up;
mac->serdes_has_link = TRUE;
DEBUGOUT("AN_PROG -> FORCED_UP\n");
}
@@ -1713,16 +1743,15 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
case e1000_serdes_link_down:
default:
- /*
- * The link was down but the receiver has now gained
+ /* The link was down but the receiver has now gained
* valid sync, so lets see if we can bring the link
* up.
*/
E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
- E1000_WRITE_REG(hw, E1000_CTRL,
- (ctrl & ~E1000_CTRL_SLU));
+ E1000_WRITE_REG(hw, E1000_CTRL, (ctrl &
+ ~E1000_CTRL_SLU));
mac->serdes_link_state =
- e1000_serdes_link_autoneg_progress;
+ e1000_serdes_link_autoneg_progress;
mac->serdes_has_link = FALSE;
DEBUGOUT("DOWN -> AN_PROG\n");
break;
@@ -1733,20 +1762,21 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
mac->serdes_link_state = e1000_serdes_link_down;
DEBUGOUT("ANYSTATE -> DOWN\n");
} else {
- /*
- * Check several times, if Sync and Config
- * both are consistently 1 then simply ignore
- * the Invalid bit and restart Autoneg
+ /* Check several times, if SYNCH bit and CONFIG
+ * bit both are consistently 1 then simply ignore
+ * the IV bit and restart Autoneg
*/
for (i = 0; i < AN_RETRY_COUNT; i++) {
usec_delay(10);
rxcw = E1000_READ_REG(hw, E1000_RXCW);
- if ((rxcw & E1000_RXCW_IV) &&
- !((rxcw & E1000_RXCW_SYNCH) &&
- (rxcw & E1000_RXCW_C))) {
+ if ((rxcw & E1000_RXCW_SYNCH) &&
+ (rxcw & E1000_RXCW_C))
+ continue;
+
+ if (rxcw & E1000_RXCW_IV) {
mac->serdes_has_link = FALSE;
mac->serdes_link_state =
- e1000_serdes_link_down;
+ e1000_serdes_link_down;
DEBUGOUT("ANYSTATE -> DOWN\n");
break;
}
@@ -1757,7 +1787,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
txcw |= E1000_TXCW_ANE;
E1000_WRITE_REG(hw, E1000_TXCW, txcw);
mac->serdes_link_state =
- e1000_serdes_link_autoneg_progress;
+ e1000_serdes_link_autoneg_progress;
mac->serdes_has_link = FALSE;
DEBUGOUT("ANYSTATE -> AN_PROG\n");
}
@@ -1784,7 +1814,7 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
switch (hw->mac.type) {
@@ -1801,8 +1831,7 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
break;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1839,15 +1868,14 @@ void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state)
/* If workaround is activated... */
if (state)
- /*
- * Hold a copy of the LAA in RAR[14] This is done so that
+ /* Hold a copy of the LAA in RAR[14] This is done so that
* between the time RAR[0] gets clobbered and the time it
* gets fixed, the actual LAA is in one of the RARs and no
* incoming packets directed to this port are dropped.
* Eventually the LAA will be in RAR[0] and RAR[14].
*/
- e1000_rar_set_generic(hw, hw->mac.addr,
- hw->mac.rar_entry_count - 1);
+ hw->mac.ops.rar_set(hw, hw->mac.addr,
+ hw->mac.rar_entry_count - 1);
return;
}
@@ -1864,25 +1892,23 @@ void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state)
static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
{
struct e1000_nvm_info *nvm = &hw->nvm;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 data;
DEBUGFUNC("e1000_fix_nvm_checksum_82571");
if (nvm->type != e1000_nvm_flash_hw)
- goto out;
+ return E1000_SUCCESS;
- /*
- * Check bit 4 of word 10h. If it is 0, firmware is done updating
+ /* Check bit 4 of word 10h. If it is 0, firmware is done updating
* 10h-12h. Checksum may need to be fixed.
*/
ret_val = nvm->ops.read(hw, 0x10, 1, &data);
if (ret_val)
- goto out;
+ return ret_val;
if (!(data & 0x10)) {
- /*
- * Read 0x23 and check bit 15. This bit is a 1
+ /* Read 0x23 and check bit 15. This bit is a 1
* when the checksum has already been fixed. If
* the checksum is still wrong and this bit is a
* 1, we need to return bad checksum. Otherwise,
@@ -1891,19 +1917,20 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
*/
ret_val = nvm->ops.read(hw, 0x23, 1, &data);
if (ret_val)
- goto out;
+ return ret_val;
if (!(data & 0x8000)) {
data |= 0x8000;
ret_val = nvm->ops.write(hw, 0x23, 1, &data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = nvm->ops.update(hw);
+ if (ret_val)
+ return ret_val;
}
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
@@ -1913,25 +1940,21 @@ out:
**/
static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
-
DEBUGFUNC("e1000_read_mac_addr_82571");
if (hw->mac.type == e1000_82571) {
- /*
- * If there's an alternate MAC address place it in RAR0
+ s32 ret_val;
+
+ /* If there's an alternate MAC address place it in RAR0
* so that it will override the Si installed default perm
* address.
*/
ret_val = e1000_check_alt_mac_addr_generic(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- ret_val = e1000_read_mac_addr_generic(hw);
-
-out:
- return ret_val;
+ return e1000_read_mac_addr_generic(hw);
}
/**
@@ -1946,7 +1969,7 @@ static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw)
struct e1000_phy_info *phy = &hw->phy;
struct e1000_mac_info *mac = &hw->mac;
- if (!(phy->ops.check_reset_block))
+ if (!phy->ops.check_reset_block)
return;
/* If the management interface is not enabled, then power down */
diff --git a/freebsd/sys/dev/e1000/e1000_82575.c b/freebsd/sys/dev/e1000/e1000_82575.c
index 4ce9d194..c7d00b54 100644
--- a/freebsd/sys/dev/e1000/e1000_82575.c
+++ b/freebsd/sys/dev/e1000/e1000_82575.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -38,19 +38,21 @@
* 82575EB Gigabit Network Connection
* 82575EB Gigabit Backplane Connection
* 82575GB Gigabit Network Connection
- * 82575GB Gigabit Network Connection
* 82576 Gigabit Network Connection
* 82576 Quad Port Gigabit Mezzanine Adapter
+ * 82580 Gigabit Network Connection
+ * I350 Gigabit Network Connection
*/
#ifdef __rtems__
#include <dev/e1000/e1000_api.h>
+#include <dev/e1000/e1000_i210.h>
#else
#include <rtems/bsd/local/e1000_api.h>
-#endif
+#include <rtems/bsd/local/e1000_i210.h>
+#endif /* __rtems__ */
static s32 e1000_init_phy_params_82575(struct e1000_hw *hw);
-static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw);
static s32 e1000_init_mac_params_82575(struct e1000_hw *hw);
static s32 e1000_acquire_phy_82575(struct e1000_hw *hw);
static void e1000_release_phy_82575(struct e1000_hw *hw);
@@ -59,28 +61,34 @@ static void e1000_release_nvm_82575(struct e1000_hw *hw);
static s32 e1000_check_for_link_82575(struct e1000_hw *hw);
static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw);
static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
- u16 *duplex);
+ u16 *duplex);
static s32 e1000_init_hw_82575(struct e1000_hw *hw);
static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw);
static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
- u16 *data);
+ u16 *data);
static s32 e1000_reset_hw_82575(struct e1000_hw *hw);
static s32 e1000_reset_hw_82580(struct e1000_hw *hw);
-static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw,
- u32 offset, u16 *data);
-static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw,
- u32 offset, u16 data);
+static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw,
+ u32 offset, u16 *data);
+static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw,
+ u32 offset, u16 data);
+static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw,
+ bool active);
+static s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw,
+ bool active);
static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw,
- bool active);
+ bool active);
static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw);
static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw);
+static s32 e1000_get_media_type_82575(struct e1000_hw *hw);
+static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw);
static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data);
static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw,
- u32 offset, u16 data);
+ u32 offset, u16 data);
static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw);
static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
- u16 *speed, u16 *duplex);
+ u16 *speed, u16 *duplex);
static s32 e1000_get_phy_id_82575(struct e1000_hw *hw);
static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask);
static bool e1000_sgmii_active_82575(struct e1000_hw *hw);
@@ -92,10 +100,31 @@ static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw);
static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw);
static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw);
static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw);
-
-static const u16 e1000_82580_rxpbs_table[] =
- { 36, 72, 144, 1, 2, 4, 8, 16,
- 35, 70, 140 };
+static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw,
+ u16 offset);
+static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
+ u16 offset);
+static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw);
+static void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value);
+static void e1000_clear_vfta_i350(struct e1000_hw *hw);
+
+static void e1000_i2c_start(struct e1000_hw *hw);
+static void e1000_i2c_stop(struct e1000_hw *hw);
+static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data);
+static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data);
+static s32 e1000_get_i2c_ack(struct e1000_hw *hw);
+static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data);
+static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data);
+static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl);
+static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl);
+static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data);
+static bool e1000_get_i2c_data(u32 *i2cctl);
+
+static const u16 e1000_82580_rxpbs_table[] = {
+ 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 };
#define E1000_82580_RXPBS_TABLE_SIZE \
(sizeof(e1000_82580_rxpbs_table)/sizeof(u16))
@@ -121,6 +150,9 @@ static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw)
ext_mdio = !!(reg & E1000_MDIC_DEST);
break;
case e1000_82580:
+ case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
reg = E1000_READ_REG(hw, E1000_MDICNFG);
ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
break;
@@ -142,6 +174,9 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_phy_params_82575");
+ phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic;
+ phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic;
+
if (hw->phy.media_type != e1000_media_type_copper) {
phy->type = e1000_phy_none;
goto out;
@@ -150,37 +185,47 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
phy->ops.power_up = e1000_power_up_phy_copper;
phy->ops.power_down = e1000_power_down_phy_copper_82575;
- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- phy->reset_delay_us = 100;
+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->reset_delay_us = 100;
- phy->ops.acquire = e1000_acquire_phy_82575;
- phy->ops.check_reset_block = e1000_check_reset_block_generic;
- phy->ops.commit = e1000_phy_sw_reset_generic;
- phy->ops.get_cfg_done = e1000_get_cfg_done_82575;
- phy->ops.release = e1000_release_phy_82575;
+ phy->ops.acquire = e1000_acquire_phy_82575;
+ phy->ops.check_reset_block = e1000_check_reset_block_generic;
+ phy->ops.commit = e1000_phy_sw_reset_generic;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_82575;
+ phy->ops.release = e1000_release_phy_82575;
ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
if (e1000_sgmii_active_82575(hw)) {
- phy->ops.reset = e1000_phy_hw_reset_sgmii_82575;
+ phy->ops.reset = e1000_phy_hw_reset_sgmii_82575;
ctrl_ext |= E1000_CTRL_I2C_ENA;
} else {
- phy->ops.reset = e1000_phy_hw_reset_generic;
+ phy->ops.reset = e1000_phy_hw_reset_generic;
ctrl_ext &= ~E1000_CTRL_I2C_ENA;
}
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
e1000_reset_mdicnfg_82580(hw);
-
+
if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) {
- phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575;
- phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575;
- } else if (hw->mac.type >= e1000_82580) {
- phy->ops.read_reg = e1000_read_phy_reg_82580;
- phy->ops.write_reg = e1000_write_phy_reg_82580;
+ phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575;
+ phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575;
} else {
- phy->ops.read_reg = e1000_read_phy_reg_igp;
- phy->ops.write_reg = e1000_write_phy_reg_igp;
+ switch (hw->mac.type) {
+ case e1000_82580:
+ case e1000_i350:
+ phy->ops.read_reg = e1000_read_phy_reg_82580;
+ phy->ops.write_reg = e1000_write_phy_reg_82580;
+ break;
+ case e1000_i210:
+ case e1000_i211:
+ phy->ops.read_reg = e1000_read_phy_reg_gs40g;
+ phy->ops.write_reg = e1000_write_phy_reg_gs40g;
+ break;
+ default:
+ phy->ops.read_reg = e1000_read_phy_reg_igp;
+ phy->ops.write_reg = e1000_write_phy_reg_igp;
+ }
}
/* Set phy->phy_addr and phy->id. */
@@ -188,29 +233,51 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
/* Verify phy id and set remaining function pointers */
switch (phy->id) {
+ case I347AT4_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
+ case M88E1340M_E_PHY_ID:
case M88E1111_I_PHY_ID:
- phy->type = e1000_phy_m88;
- phy->ops.check_polarity = e1000_check_polarity_m88;
- phy->ops.get_info = e1000_get_phy_info_m88;
- phy->ops.get_cable_length = e1000_get_cable_length_m88;
+ phy->type = e1000_phy_m88;
+ phy->ops.check_polarity = e1000_check_polarity_m88;
+ phy->ops.get_info = e1000_get_phy_info_m88;
+ if (phy->id == I347AT4_E_PHY_ID ||
+ phy->id == M88E1112_E_PHY_ID ||
+ phy->id == M88E1340M_E_PHY_ID)
+ phy->ops.get_cable_length =
+ e1000_get_cable_length_m88_gen2;
+ else
+ phy->ops.get_cable_length = e1000_get_cable_length_m88;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
break;
case IGP03E1000_E_PHY_ID:
case IGP04E1000_E_PHY_ID:
- phy->type = e1000_phy_igp_3;
- phy->ops.check_polarity = e1000_check_polarity_igp;
- phy->ops.get_info = e1000_get_phy_info_igp;
- phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
+ phy->type = e1000_phy_igp_3;
+ phy->ops.check_polarity = e1000_check_polarity_igp;
+ phy->ops.get_info = e1000_get_phy_info_igp;
+ phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
- phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575;
- phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
+ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
break;
case I82580_I_PHY_ID:
- phy->type = e1000_phy_82580;
- phy->ops.check_polarity = e1000_check_polarity_82577;
- phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82577;
- phy->ops.get_cable_length = e1000_get_cable_length_82577;
- phy->ops.get_info = e1000_get_phy_info_82577;
+ case I350_I_PHY_ID:
+ phy->type = e1000_phy_82580;
+ phy->ops.check_polarity = e1000_check_polarity_82577;
+ phy->ops.force_speed_duplex =
+ e1000_phy_force_speed_duplex_82577;
+ phy->ops.get_cable_length = e1000_get_cable_length_82577;
+ phy->ops.get_info = e1000_get_phy_info_82577;
+ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
+ break;
+ case I210_I_PHY_ID:
+ phy->type = e1000_phy_i210;
+ phy->ops.check_polarity = e1000_check_polarity_m88;
+ phy->ops.get_info = e1000_get_phy_info_m88;
+ phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
+ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
break;
default:
ret_val = -E1000_ERR_PHY;
@@ -225,7 +292,7 @@ out:
* e1000_init_nvm_params_82575 - Init NVM func ptrs.
* @hw: pointer to the HW structure
**/
-static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
+s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
@@ -233,47 +300,74 @@ static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_nvm_params_82575");
- nvm->opcode_bits = 8;
- nvm->delay_usec = 1;
- switch (nvm->override) {
- case e1000_nvm_override_spi_large:
- nvm->page_size = 32;
- nvm->address_bits = 16;
- break;
- case e1000_nvm_override_spi_small:
- nvm->page_size = 8;
- nvm->address_bits = 8;
- break;
- default:
- nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
- nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
- break;
- }
-
- nvm->type = e1000_nvm_eeprom_spi;
-
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
- E1000_EECD_SIZE_EX_SHIFT);
-
+ E1000_EECD_SIZE_EX_SHIFT);
/*
* Added to a constant, "size" becomes the left-shift value
* for setting word_size.
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
- /* EEPROM access above 16k is unsupported */
- if (size > 14)
- size = 14;
+ /* Just in case size is out of range, cap it to the largest
+ * EEPROM size supported
+ */
+ if (size > 15)
+ size = 15;
+
nvm->word_size = 1 << size;
+ if (hw->mac.type < e1000_i210) {
+ nvm->opcode_bits = 8;
+ nvm->delay_usec = 1;
+
+ switch (nvm->override) {
+ case e1000_nvm_override_spi_large:
+ nvm->page_size = 32;
+ nvm->address_bits = 16;
+ break;
+ case e1000_nvm_override_spi_small:
+ nvm->page_size = 8;
+ nvm->address_bits = 8;
+ break;
+ default:
+ nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
+ nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ?
+ 16 : 8;
+ break;
+ }
+ if (nvm->word_size == (1 << 15))
+ nvm->page_size = 128;
+
+ nvm->type = e1000_nvm_eeprom_spi;
+ } else {
+ nvm->type = e1000_nvm_flash_hw;
+ }
/* Function Pointers */
- nvm->ops.acquire = e1000_acquire_nvm_82575;
- nvm->ops.read = e1000_read_nvm_eerd;
- nvm->ops.release = e1000_release_nvm_82575;
- nvm->ops.update = e1000_update_nvm_checksum_generic;
+ nvm->ops.acquire = e1000_acquire_nvm_82575;
+ nvm->ops.release = e1000_release_nvm_82575;
+ if (nvm->word_size < (1 << 15))
+ nvm->ops.read = e1000_read_nvm_eerd;
+ else
+ nvm->ops.read = e1000_read_nvm_spi;
+
+ nvm->ops.write = e1000_write_nvm_spi;
+ nvm->ops.validate = e1000_validate_nvm_checksum_generic;
+ nvm->ops.update = e1000_update_nvm_checksum_generic;
nvm->ops.valid_led_default = e1000_valid_led_default_82575;
- nvm->ops.validate = e1000_validate_nvm_checksum_generic;
- nvm->ops.write = e1000_write_nvm_spi;
+
+ /* override generic family function pointers for specific descendants */
+ switch (hw->mac.type) {
+ case e1000_82580:
+ nvm->ops.validate = e1000_validate_nvm_checksum_82580;
+ nvm->ops.update = e1000_update_nvm_checksum_82580;
+ break;
+ case e1000_i350:
+ nvm->ops.validate = e1000_validate_nvm_checksum_i350;
+ nvm->ops.update = e1000_update_nvm_checksum_i350;
+ break;
+ default:
+ break;
+ }
return E1000_SUCCESS;
}
@@ -286,34 +380,11 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
- u32 ctrl_ext = 0;
DEBUGFUNC("e1000_init_mac_params_82575");
- /* Set media type */
- /*
- * The 82575 uses bits 22:23 for link mode. The mode can be changed
- * based on the EEPROM. We cannot rely upon device ID. There
- * is no distinguishable difference between fiber and internal
- * SerDes mode on the 82575. There can be an external PHY attached
- * on the SGMII interface. For this, we'll set sgmii_active to TRUE.
- */
- hw->phy.media_type = e1000_media_type_copper;
- dev_spec->sgmii_active = FALSE;
-
- ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
- switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
- case E1000_CTRL_EXT_LINK_MODE_SGMII:
- dev_spec->sgmii_active = TRUE;
- break;
- case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
- case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
- hw->phy.media_type = e1000_media_type_internal_serdes;
- break;
- default:
- break;
- }
-
+ /* Derives media type */
+ e1000_get_media_type_82575(hw);
/* Set mta register count */
mac->mta_reg_count = 128;
/* Set uta register count */
@@ -324,14 +395,24 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
if (mac->type == e1000_82580)
mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
+ if (mac->type == e1000_i350)
+ mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
+
+ /* Enable EEE default settings for EEE supported devices */
+ if (mac->type >= e1000_i350)
+ dev_spec->eee_disable = FALSE;
+
+ /* Allow a single clear of the SW semaphore on I210 and newer */
+ if (mac->type >= e1000_i210)
+ dev_spec->clear_semaphore_once = TRUE;
+
/* Set if part includes ASF firmware */
mac->asf_firmware_present = TRUE;
/* FWSM register */
mac->has_fwsm = TRUE;
/* ARC supported; valid only if manageability features are enabled. */
mac->arc_subsystem_valid =
- (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK)
- ? TRUE : FALSE;
+ !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK);
/* Function pointers */
@@ -348,27 +429,34 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->ops.setup_link = e1000_setup_link_generic;
/* physical interface link setup */
mac->ops.setup_physical_interface =
- (hw->phy.media_type == e1000_media_type_copper)
- ? e1000_setup_copper_link_82575
- : e1000_setup_serdes_link_82575;
+ (hw->phy.media_type == e1000_media_type_copper)
+ ? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575;
/* physical interface shutdown */
mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575;
/* physical interface power up */
mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575;
/* check for link */
mac->ops.check_for_link = e1000_check_for_link_82575;
- /* receive address register setting */
- mac->ops.rar_set = e1000_rar_set_generic;
/* read mac address */
mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
/* configure collision distance */
mac->ops.config_collision_dist = e1000_config_collision_dist_82575;
/* multicast address update */
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
- /* writing VFTA */
- mac->ops.write_vfta = e1000_write_vfta_generic;
- /* clearing VFTA */
- mac->ops.clear_vfta = e1000_clear_vfta_generic;
+ if (mac->type == e1000_i350) {
+ /* writing VFTA */
+ mac->ops.write_vfta = e1000_write_vfta_i350;
+ /* clearing VFTA */
+ mac->ops.clear_vfta = e1000_clear_vfta_i350;
+ } else {
+ /* writing VFTA */
+ mac->ops.write_vfta = e1000_write_vfta_generic;
+ /* clearing VFTA */
+ mac->ops.clear_vfta = e1000_clear_vfta_generic;
+ }
+ if (hw->mac.type >= e1000_82580)
+ mac->ops.validate_mdi_setting =
+ e1000_validate_mdi_setting_crossover_generic;
/* ID LED init */
mac->ops.id_led_init = e1000_id_led_init_generic;
/* blink LED */
@@ -384,6 +472,13 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
/* link info */
mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
+ /* acquire SW_FW sync */
+ mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575;
+ mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575;
+ if (mac->type >= e1000_i210) {
+ mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210;
+ mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210;
+ }
/* set lan id for port to determine which phy lock to use */
hw->mac.ops.set_lan_id(hw);
@@ -426,7 +521,7 @@ static s32 e1000_acquire_phy_82575(struct e1000_hw *hw)
else if (hw->bus.func == E1000_FUNC_3)
mask = E1000_SWFW_PHY3_SM;
- return e1000_acquire_swfw_sync_82575(hw, mask);
+ return hw->mac.ops.acquire_swfw_sync(hw, mask);
}
/**
@@ -448,7 +543,7 @@ static void e1000_release_phy_82575(struct e1000_hw *hw)
else if (hw->bus.func == E1000_FUNC_3)
mask = E1000_SWFW_PHY3_SM;
- e1000_release_swfw_sync_82575(hw, mask);
+ hw->mac.ops.release_swfw_sync(hw, mask);
}
/**
@@ -461,7 +556,7 @@ static void e1000_release_phy_82575(struct e1000_hw *hw)
* interface and stores the retrieved information in data.
**/
static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
- u16 *data)
+ u16 *data)
{
s32 ret_val = -E1000_ERR_PARAM;
@@ -494,7 +589,7 @@ out:
* media independent interface.
**/
static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
- u16 data)
+ u16 data)
{
s32 ret_val = -E1000_ERR_PARAM;
@@ -556,6 +651,9 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
phy->addr = mdic >> E1000_MDIC_PHY_SHIFT;
break;
case e1000_82580:
+ case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
mdic = E1000_READ_REG(hw, E1000_MDICNFG);
mdic &= E1000_MDICNFG_PHY_MASK;
phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
@@ -572,7 +670,7 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
/* Power on sgmii phy if it is disabled */
ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
E1000_WRITE_REG(hw, E1000_CTRL_EXT,
- ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
+ ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
E1000_WRITE_FLUSH(hw);
msec_delay(300);
@@ -584,8 +682,7 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id);
if (ret_val == E1000_SUCCESS) {
DEBUGOUT2("Vendor ID 0x%08X read at address %u\n",
- phy_id,
- phy->addr);
+ phy_id, phy->addr);
/*
* At the time of this writing, The M88 part is
* the only supported SGMII PHY product.
@@ -594,7 +691,7 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
break;
} else {
DEBUGOUT1("PHY address %u was unreadable\n",
- phy->addr);
+ phy->addr);
}
}
@@ -680,22 +777,22 @@ static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active)
if (active) {
data |= IGP02E1000_PM_D0_LPLU;
ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- data);
+ data);
if (ret_val)
goto out;
/* When LPLU is enabled, we should disable SmartSpeed */
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ &data);
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- data);
+ data);
if (ret_val)
goto out;
} else {
data &= ~IGP02E1000_PM_D0_LPLU;
ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- data);
+ data);
/*
* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
@@ -704,28 +801,28 @@ static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active)
*/
if (phy->smart_speed == e1000_smart_speed_on) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
goto out;
data |= IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
goto out;
} else if (phy->smart_speed == e1000_smart_speed_off) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
goto out;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
goto out;
}
@@ -736,6 +833,101 @@ out:
}
/**
+ * e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
+ * @hw: pointer to the HW structure
+ * @active: TRUE to enable LPLU, FALSE to disable
+ *
+ * Sets the LPLU D0 state according to the active flag. When
+ * activating LPLU this function also disables smart speed
+ * and vice versa. LPLU will not be activated unless the
+ * device autonegotiation advertisement meets standards of
+ * either 10 or 10/100 or 10/100/1000 at all duplexes.
+ * This is a function pointer entry point only called by
+ * PHY setup routines.
+ **/
+static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = E1000_SUCCESS;
+ u32 data;
+
+ DEBUGFUNC("e1000_set_d0_lplu_state_82580");
+
+ data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+
+ if (active) {
+ data |= E1000_82580_PM_D0_LPLU;
+
+ /* When LPLU is enabled, we should disable SmartSpeed */
+ data &= ~E1000_82580_PM_SPD;
+ } else {
+ data &= ~E1000_82580_PM_D0_LPLU;
+
+ /*
+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained.
+ */
+ if (phy->smart_speed == e1000_smart_speed_on)
+ data |= E1000_82580_PM_SPD;
+ else if (phy->smart_speed == e1000_smart_speed_off)
+ data &= ~E1000_82580_PM_SPD;
+ }
+
+ E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
+ return ret_val;
+}
+
+/**
+ * e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3
+ * @hw: pointer to the HW structure
+ * @active: boolean used to enable/disable lplu
+ *
+ * Success returns 0, Failure returns 1
+ *
+ * The low power link up (lplu) state is set to the power management level D3
+ * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
+ * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
+ * is used during Dx states where the power conservation is most important.
+ * During driver activity, SmartSpeed should be enabled so performance is
+ * maintained.
+ **/
+s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = E1000_SUCCESS;
+ u32 data;
+
+ DEBUGFUNC("e1000_set_d3_lplu_state_82580");
+
+ data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+
+ if (!active) {
+ data &= ~E1000_82580_PM_D3_LPLU;
+ /*
+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained.
+ */
+ if (phy->smart_speed == e1000_smart_speed_on)
+ data |= E1000_82580_PM_SPD;
+ else if (phy->smart_speed == e1000_smart_speed_off)
+ data &= ~E1000_82580_PM_SPD;
+ } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+ data |= E1000_82580_PM_D3_LPLU;
+ /* When LPLU is enabled, we should disable SmartSpeed */
+ data &= ~E1000_82580_PM_SPD;
+ }
+
+ E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
+ return ret_val;
+}
+
+/**
* e1000_acquire_nvm_82575 - Request for access to EEPROM
* @hw: pointer to the HW structure
*
@@ -754,8 +946,32 @@ static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw)
if (ret_val)
goto out;
- ret_val = e1000_acquire_nvm_generic(hw);
+ /*
+ * Check if there is some access
+ * error this access may hook on
+ */
+ if (hw->mac.type == e1000_i350) {
+ u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+ if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT |
+ E1000_EECD_TIMEOUT)) {
+ /* Clear all access error flags */
+ E1000_WRITE_REG(hw, E1000_EECD, eecd |
+ E1000_EECD_ERROR_CLR);
+ DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
+ }
+ }
+ if (hw->mac.type == e1000_82580) {
+ u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+ if (eecd & E1000_EECD_BLOCKED) {
+ /* Clear access error flag */
+ E1000_WRITE_REG(hw, E1000_EECD, eecd |
+ E1000_EECD_BLOCKED);
+ DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
+ }
+ }
+
+ ret_val = e1000_acquire_nvm_generic(hw);
if (ret_val)
e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
@@ -775,6 +991,7 @@ static void e1000_release_nvm_82575(struct e1000_hw *hw)
DEBUGFUNC("e1000_release_nvm_82575");
e1000_release_nvm_generic(hw);
+
e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
}
@@ -844,8 +1061,8 @@ static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
DEBUGFUNC("e1000_release_swfw_sync_82575");
- while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS);
- /* Empty */
+ while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS)
+ ; /* Empty */
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
swfw_sync &= ~mask;
@@ -888,7 +1105,7 @@ static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
DEBUGOUT("MNG configuration cycle has not completed.\n");
/* If EEPROM is not marked present, init the PHY manually */
- if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) &&
+ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) &&
(hw->phy.type == e1000_phy_igp_3))
e1000_phy_init_script_igp3(hw);
@@ -906,7 +1123,7 @@ static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
* Otherwise, use the generic function to get the link speed and duplex info.
**/
static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
- u16 *duplex)
+ u16 *duplex)
{
s32 ret_val;
@@ -914,10 +1131,10 @@ static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
if (hw->phy.media_type != e1000_media_type_copper)
ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed,
- duplex);
+ duplex);
else
ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
- duplex);
+ duplex);
return ret_val;
}
@@ -938,13 +1155,23 @@ static s32 e1000_check_for_link_82575(struct e1000_hw *hw)
if (hw->phy.media_type != e1000_media_type_copper) {
ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
- &duplex);
+ &duplex);
/*
* Use this flag to determine if link needs to be checked or
* not. If we have link clear the flag so that we do not
* continue to check for link.
*/
hw->mac.get_link_status = !hw->mac.serdes_has_link;
+
+ /*
+ * Configure Flow Control now that Auto-Neg has completed.
+ * First, we need to restore the desired flow control
+ * settings because we may have had to re-autoneg with a
+ * different link partner.
+ */
+ ret_val = e1000_config_fc_after_link_up_generic(hw);
+ if (ret_val)
+ DEBUGOUT("Error configuring flow control\n");
} else {
ret_val = e1000_check_for_copper_link_generic(hw);
}
@@ -991,18 +1218,13 @@ static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw)
* duplex, then store the values in the pointers provided.
**/
static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
- u16 *speed, u16 *duplex)
+ u16 *speed, u16 *duplex)
{
struct e1000_mac_info *mac = &hw->mac;
u32 pcs;
DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575");
- /* Set up defaults for the return values of this function */
- mac->serdes_has_link = FALSE;
- *speed = 0;
- *duplex = 0;
-
/*
* Read the PCS Status register for link state. For non-copper mode,
* the status register is not accurate. The PCS status register is
@@ -1011,28 +1233,29 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT);
/*
- * The link up bit determines when link is up on autoneg. The sync ok
- * gets set once both sides sync up and agree upon link. Stable link
- * can be determined by checking for both link up and link sync ok
+ * The link up bit determines when link is up on autoneg.
*/
- if ((pcs & E1000_PCS_LSTS_LINK_OK) && (pcs & E1000_PCS_LSTS_SYNK_OK)) {
+ if (pcs & E1000_PCS_LSTS_LINK_OK) {
mac->serdes_has_link = TRUE;
/* Detect and store PCS speed */
- if (pcs & E1000_PCS_LSTS_SPEED_1000) {
+ if (pcs & E1000_PCS_LSTS_SPEED_1000)
*speed = SPEED_1000;
- } else if (pcs & E1000_PCS_LSTS_SPEED_100) {
+ else if (pcs & E1000_PCS_LSTS_SPEED_100)
*speed = SPEED_100;
- } else {
+ else
*speed = SPEED_10;
- }
/* Detect and store PCS duplex */
- if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) {
+ if (pcs & E1000_PCS_LSTS_DUPLEX_FULL)
*duplex = FULL_DUPLEX;
- } else {
+ else
*duplex = HALF_DUPLEX;
- }
+
+ } else {
+ mac->serdes_has_link = FALSE;
+ *speed = 0;
+ *duplex = 0;
}
return E1000_SUCCESS;
@@ -1082,7 +1305,7 @@ void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw)
**/
static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
{
- u32 ctrl, icr;
+ u32 ctrl;
s32 ret_val;
DEBUGFUNC("e1000_reset_hw_82575");
@@ -1092,15 +1315,13 @@ static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = e1000_disable_pcie_master_generic(hw);
- if (ret_val) {
+ if (ret_val)
DEBUGOUT("PCI-E Master disable polling has failed.\n");
- }
/* set the completion timeout for interface */
ret_val = e1000_set_pcie_completion_timeout(hw);
- if (ret_val) {
+ if (ret_val)
DEBUGOUT("PCI-E Set completion timeout has failed.\n");
- }
DEBUGOUT("Masking off all interrupts\n");
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
@@ -1127,12 +1348,12 @@ static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
}
/* If EEPROM is not present, run manual init scripts */
- if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0)
+ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES))
e1000_reset_init_script_82575(hw);
/* Clear any pending interrupt events. */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
/* Install any alternate MAC address into RAR0 */
ret_val = e1000_check_alt_mac_addr_generic(hw);
@@ -1181,6 +1402,9 @@ static s32 e1000_init_hw_82575(struct e1000_hw *hw)
/* Setup link and flow control */
ret_val = mac->ops.setup_link(hw);
+ /* Set the default MTU size */
+ hw->dev_spec._82575.mtu = 1500;
+
/*
* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
@@ -1203,7 +1427,8 @@ static s32 e1000_init_hw_82575(struct e1000_hw *hw)
static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
{
u32 ctrl;
- s32 ret_val;
+ s32 ret_val;
+ u32 phpm_reg;
DEBUGFUNC("e1000_setup_copper_link_82575");
@@ -1212,11 +1437,18 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+ /* Clear Go Link Disconnect bit */
+ if (hw->mac.type >= e1000_82580) {
+ phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+ phpm_reg &= ~E1000_82580_PM_GO_LINKD;
+ E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg);
+ }
+
ret_val = e1000_setup_serdes_link_82575(hw);
if (ret_val)
goto out;
- if (e1000_sgmii_active_82575(hw) && !hw->phy.reset_disable) {
+ if (e1000_sgmii_active_82575(hw)) {
/* allow time for SFP cage time to power up phy */
msec_delay(300);
@@ -1227,8 +1459,19 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
}
}
switch (hw->phy.type) {
+ case e1000_phy_i210:
case e1000_phy_m88:
- ret_val = e1000_copper_link_setup_m88(hw);
+ switch (hw->phy.id) {
+ case I347AT4_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
+ case M88E1340M_E_PHY_ID:
+ case I210_I_PHY_ID:
+ ret_val = e1000_copper_link_setup_m88_gen2(hw);
+ break;
+ default:
+ ret_val = e1000_copper_link_setup_m88(hw);
+ break;
+ }
break;
case e1000_phy_igp_3:
ret_val = e1000_copper_link_setup_igp(hw);
@@ -1260,14 +1503,16 @@ out:
**/
static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
{
- u32 ctrl_ext, ctrl_reg, reg;
+ u32 ctrl_ext, ctrl_reg, reg, anadv_reg;
bool pcs_autoneg;
+ s32 ret_val = E1000_SUCCESS;
+ u16 data;
DEBUGFUNC("e1000_setup_serdes_link_82575");
if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
!e1000_sgmii_active_82575(hw))
- return E1000_SUCCESS;
+ return ret_val;
/*
* On the 82575, SerDes loopback mode persists until it is
@@ -1306,13 +1551,25 @@ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
pcs_autoneg = FALSE;
/* fall through to default case */
default:
+ if (hw->mac.type == e1000_82575 ||
+ hw->mac.type == e1000_82576) {
+ ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+
+ if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT)
+ pcs_autoneg = FALSE;
+ }
+
/*
* non-SGMII modes only supports a speed of 1000/Full for the
* link so it is best to just force the MAC and let the pcs
* link either autoneg or be forced to 1000/Full
*/
ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD |
- E1000_CTRL_FD | E1000_CTRL_FRCDPX;
+ E1000_CTRL_FD | E1000_CTRL_FRCDPX;
/* set speed of 1000/Full if speed/duplex is forced */
reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL;
@@ -1328,31 +1585,203 @@ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
* However, both are supported by the hardware and some drivers/tools.
*/
reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
- E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
-
- /*
- * We force flow control to prevent the CTRL register values from being
- * overwritten by the autonegotiated flow control values
- */
- reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+ E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
if (pcs_autoneg) {
/* Set PCS register for autoneg */
reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
+
+ /* Disable force flow control for autoneg */
+ reg &= ~E1000_PCS_LCTL_FORCE_FCTRL;
+
+ /* Configure flow control advertisement for autoneg */
+ anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV);
+ anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE);
+
+ switch (hw->fc.requested_mode) {
+ case e1000_fc_full:
+ case e1000_fc_rx_pause:
+ anadv_reg |= E1000_TXCW_ASM_DIR;
+ anadv_reg |= E1000_TXCW_PAUSE;
+ break;
+ case e1000_fc_tx_pause:
+ anadv_reg |= E1000_TXCW_ASM_DIR;
+ break;
+ default:
+ break;
+ }
+
+ E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg);
+
DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
} else {
/* Set PCS register for forced link */
- reg |= E1000_PCS_LCTL_FSD; /* Force Speed */
+ reg |= E1000_PCS_LCTL_FSD; /* Force Speed */
+
+ /* Force flow control for forced link */
+ reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+
DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
}
E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg);
- if (!e1000_sgmii_active_82575(hw))
+ if (!pcs_autoneg && !e1000_sgmii_active_82575(hw))
e1000_force_mac_fc_generic(hw);
- return E1000_SUCCESS;
+ return ret_val;
+}
+
+/**
+ * e1000_get_media_type_82575 - derives current media type.
+ * @hw: pointer to the HW structure
+ *
+ * The media type is chosen reflecting few settings.
+ * The following are taken into account:
+ * - link mode set in the current port Init Control Word #3
+ * - current link mode settings in CSR register
+ * - MDIO vs. I2C PHY control interface chosen
+ * - SFP module media type
+ **/
+static s32 e1000_get_media_type_82575(struct e1000_hw *hw)
+{
+ struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+ s32 ret_val = E1000_SUCCESS;
+ u32 ctrl_ext = 0;
+ u32 link_mode = 0;
+
+ /* Set internal phy as default */
+ dev_spec->sgmii_active = FALSE;
+ dev_spec->module_plugged = FALSE;
+
+ /* Get CSR setting */
+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+
+ /* extract link mode setting */
+ link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
+
+ switch (link_mode) {
+ case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
+ hw->phy.media_type = e1000_media_type_internal_serdes;
+ break;
+ case E1000_CTRL_EXT_LINK_MODE_GMII:
+ hw->phy.media_type = e1000_media_type_copper;
+ break;
+ case E1000_CTRL_EXT_LINK_MODE_SGMII:
+ /* Get phy control interface type set (MDIO vs. I2C)*/
+ if (e1000_sgmii_uses_mdio_82575(hw)) {
+ hw->phy.media_type = e1000_media_type_copper;
+ dev_spec->sgmii_active = TRUE;
+ break;
+ }
+ /* fall through for I2C based SGMII */
+ case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
+ /* read media type from SFP EEPROM */
+ ret_val = e1000_set_sfp_media_type_82575(hw);
+ if ((ret_val != E1000_SUCCESS) ||
+ (hw->phy.media_type == e1000_media_type_unknown)) {
+ /*
+ * If media type was not identified then return media
+ * type defined by the CTRL_EXT settings.
+ */
+ hw->phy.media_type = e1000_media_type_internal_serdes;
+
+ if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) {
+ hw->phy.media_type = e1000_media_type_copper;
+ dev_spec->sgmii_active = TRUE;
+ }
+
+ break;
+ }
+
+ /* do not change link mode for 100BaseFX */
+ if (dev_spec->eth_flags.e100_base_fx)
+ break;
+
+ /* change current link mode setting */
+ ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
+
+ if (hw->phy.media_type == e1000_media_type_copper)
+ ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII;
+ else
+ ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
+
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+
+ break;
+ }
+
+ return ret_val;
+}
+
+/**
+ * e1000_set_sfp_media_type_82575 - derives SFP module media type.
+ * @hw: pointer to the HW structure
+ *
+ * The media type is chosen based on SFP module.
+ * compatibility flags retrieved from SFP ID EEPROM.
+ **/
+static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_ERR_CONFIG;
+ u32 ctrl_ext = 0;
+ struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+ struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags;
+ u8 tranceiver_type = 0;
+ s32 timeout = 3;
+
+ /* Turn I2C interface ON and power on sfp cage */
+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA);
+
+ E1000_WRITE_FLUSH(hw);
+
+ /* Read SFP module data */
+ while (timeout) {
+ ret_val = e1000_read_sfp_data_byte(hw,
+ E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET),
+ &tranceiver_type);
+ if (ret_val == E1000_SUCCESS)
+ break;
+ msec_delay(100);
+ timeout--;
+ }
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+
+ ret_val = e1000_read_sfp_data_byte(hw,
+ E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET),
+ (u8 *)eth_flags);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+
+ /* Check if there is some SFP module plugged and powered */
+ if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) ||
+ (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) {
+ dev_spec->module_plugged = TRUE;
+ if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) {
+ hw->phy.media_type = e1000_media_type_internal_serdes;
+ } else if (eth_flags->e100_base_fx) {
+ dev_spec->sgmii_active = TRUE;
+ hw->phy.media_type = e1000_media_type_internal_serdes;
+ } else if (eth_flags->e1000_base_t) {
+ dev_spec->sgmii_active = TRUE;
+ hw->phy.media_type = e1000_media_type_copper;
+ } else {
+ hw->phy.media_type = e1000_media_type_unknown;
+ DEBUGOUT("PHY module has not been recognized\n");
+ goto out;
+ }
+ } else {
+ hw->phy.media_type = e1000_media_type_unknown;
+ }
+ ret_val = E1000_SUCCESS;
+out:
+ /* Restore I2C interface setting */
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+ return ret_val;
}
/**
@@ -1376,7 +1805,7 @@ static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data)
}
if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
- switch(hw->phy.media_type) {
+ switch (hw->phy.media_type) {
case e1000_media_type_internal_serdes:
*data = ID_LED_DEFAULT_82575_SERDES;
break;
@@ -1411,7 +1840,7 @@ static bool e1000_sgmii_active_82575(struct e1000_hw *hw)
* Inits recommended HW defaults after a reset when there is no EEPROM
* detected. This is only for the 82575.
**/
-static s32 e1000_reset_init_script_82575(struct e1000_hw* hw)
+static s32 e1000_reset_init_script_82575(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_reset_init_script_82575");
@@ -1576,7 +2005,7 @@ static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
}
/**
- * e1000_rx_fifo_flush_82575 - Clean rx fifo after RX enable
+ * e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable
* @hw: pointer to the HW structure
*
* After rx enable if managability is enabled then there is likely some
@@ -1594,11 +2023,11 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN))
return;
- /* Disable all RX queues */
+ /* Disable all Rx queues */
for (i = 0; i < 4; i++) {
rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i));
E1000_WRITE_REG(hw, E1000_RXDCTL(i),
- rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
+ rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
}
/* Poll all queues to verify they have shut down */
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
@@ -1632,7 +2061,7 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
E1000_WRITE_FLUSH(hw);
msec_delay(2);
- /* Enable RX queues that were previously enabled and restore our
+ /* Enable Rx queues that were previously enabled and restore our
* previous state
*/
for (i = 0; i < 4; i++)
@@ -1684,14 +2113,14 @@ static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw)
* 16ms to 55ms
*/
ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
- &pcie_devctl2);
+ &pcie_devctl2);
if (ret_val)
goto out;
pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
- &pcie_devctl2);
+ &pcie_devctl2);
out:
/* disable completion timeout resend */
gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
@@ -1700,7 +2129,6 @@ out:
return ret_val;
}
-
/**
* e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
* @hw: pointer to the hardware struct
@@ -1721,13 +2149,29 @@ void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
E1000_DTXSWC_VLAN_SPOOF_MASK);
/* The PF can spoof - it has to in order to
* support emulation mode NICs */
- dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
+ dtxswc ^= (1 << pf | 1 << (pf +
+ E1000_DTXSWC_VLAN_SPOOF_SHIFT));
} else {
dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
E1000_DTXSWC_VLAN_SPOOF_MASK);
}
E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
break;
+ case e1000_i350:
+ dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
+ if (enable) {
+ dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
+ E1000_DTXSWC_VLAN_SPOOF_MASK);
+ /* The PF can spoof - it has to in order to
+ * support emulation mode NICs
+ */
+ dtxswc ^= (1 << pf | 1 << (pf +
+ E1000_DTXSWC_VLAN_SPOOF_SHIFT));
+ } else {
+ dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
+ E1000_DTXSWC_VLAN_SPOOF_MASK);
+ }
+ E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
default:
break;
}
@@ -1753,6 +2197,14 @@ void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
break;
+ case e1000_i350:
+ dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
+ if (enable)
+ dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ else
+ dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
+ break;
default:
/* Currently no other hardware supports loopback */
break;
@@ -1845,7 +2297,7 @@ static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u32 mdicnfg;
- u16 nvm_data;
+ u16 nvm_data = 0;
DEBUGFUNC("e1000_reset_mdicnfg_82580");
@@ -1855,8 +2307,8 @@ static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw)
goto out;
ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
- NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
- &nvm_data);
+ NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
+ &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
goto out;
@@ -1884,13 +2336,17 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
s32 ret_val = E1000_SUCCESS;
/* BH SW mailbox bit in SW_FW_SYNC */
u16 swmbsw_mask = E1000_SW_SYNCH_MB;
- u32 ctrl, icr;
+ u32 ctrl;
bool global_device_reset = hw->dev_spec._82575.global_device_reset;
DEBUGFUNC("e1000_reset_hw_82580");
hw->dev_spec._82575.global_device_reset = FALSE;
+ /* 82580 does not reliably do global_device_reset due to hw errata */
+ if (hw->mac.type == e1000_82580)
+ global_device_reset = FALSE;
+
/* Get current control state. */
ctrl = E1000_READ_REG(hw, E1000_CTRL);
@@ -1911,17 +2367,18 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
msec_delay(10);
/* Determine whether or not a global dev reset is requested */
- if (global_device_reset &&
- e1000_acquire_swfw_sync_82575(hw, swmbsw_mask))
+ if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw,
+ swmbsw_mask))
global_device_reset = FALSE;
- if (global_device_reset &&
- !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STAT_DEV_RST_SET))
+ if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) &
+ E1000_STAT_DEV_RST_SET))
ctrl |= E1000_CTRL_DEV_RST;
else
ctrl |= E1000_CTRL_RST;
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+ E1000_WRITE_FLUSH(hw);
/* Add delay to insure DEV_RST has time to complete */
if (global_device_reset)
@@ -1938,7 +2395,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
}
/* If EEPROM is not present, run manual init scripts */
- if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0)
+ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES))
e1000_reset_init_script_82575(hw);
/* clear global device reset status bit */
@@ -1946,7 +2403,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
/* Clear any pending interrupt events. */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
ret_val = e1000_reset_mdicnfg_82580(hw);
if (ret_val)
@@ -1957,13 +2414,13 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
/* Release semaphore */
if (global_device_reset)
- e1000_release_swfw_sync_82575(hw, swmbsw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swmbsw_mask);
return ret_val;
}
/**
- * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual RX PBA size
+ * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size
* @data: data received by reading RXPBS register
*
* The 82580 uses a table based approach for packet buffer allocation sizes.
@@ -1981,3 +2438,859 @@ u16 e1000_rxpbs_adjust_82580(u32 data)
return ret_val;
}
+
+/**
+ * e1000_validate_nvm_checksum_with_offset - Validate EEPROM
+ * checksum
+ * @hw: pointer to the HW structure
+ * @offset: offset in words of the checksum protected region
+ *
+ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ * and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ DEBUGFUNC("e1000_validate_nvm_checksum_with_offset");
+
+ for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+
+ if (checksum != (u16) NVM_SUM) {
+ DEBUGOUT("NVM Checksum Invalid\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_update_nvm_checksum_with_offset - Update EEPROM
+ * checksum
+ * @hw: pointer to the HW structure
+ * @offset: offset in words of the checksum protected region
+ *
+ * Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ * up to the checksum. Then calculates the EEPROM checksum and writes the
+ * value to the EEPROM.
+ **/
+s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+ s32 ret_val;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_with_offset");
+
+ for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error while updating checksum.\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+ checksum = (u16) NVM_SUM - checksum;
+ ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
+ &checksum);
+ if (ret_val)
+ DEBUGOUT("NVM Write Error while updating checksum.\n");
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Calculates the EEPROM section checksum by reading/adding each word of
+ * the EEPROM and then verifies that the sum of the EEPROM is
+ * equal to 0xBABA.
+ **/
+static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 eeprom_regions_count = 1;
+ u16 j, nvm_data;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_validate_nvm_checksum_82580");
+
+ ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ goto out;
+ }
+
+ if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
+ /* if chekcsums compatibility bit is set validate checksums
+ * for all 4 ports. */
+ eeprom_regions_count = 4;
+ }
+
+ for (j = 0; j < eeprom_regions_count; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_validate_nvm_checksum_with_offset(hw,
+ nvm_offset);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_update_nvm_checksum_82580 - Update EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Updates the EEPROM section checksums for all 4 ports by reading/adding
+ * each word of the EEPROM up to the checksum. Then calculates the EEPROM
+ * checksum and writes the value to the EEPROM.
+ **/
+static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 j, nvm_data;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_82580");
+
+ ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n");
+ goto out;
+ }
+
+ if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) {
+ /* set compatibility bit to validate checksums appropriately */
+ nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
+ ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
+ &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n");
+ goto out;
+ }
+ }
+
+ for (j = 0; j < 4; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
+ if (ret_val)
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Calculates the EEPROM section checksum by reading/adding each word of
+ * the EEPROM and then verifies that the sum of the EEPROM is
+ * equal to 0xBABA.
+ **/
+static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 j;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_validate_nvm_checksum_i350");
+
+ for (j = 0; j < 4; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_validate_nvm_checksum_with_offset(hw,
+ nvm_offset);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_update_nvm_checksum_i350 - Update EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Updates the EEPROM section checksums for all 4 ports by reading/adding
+ * each word of the EEPROM up to the checksum. Then calculates the EEPROM
+ * checksum and writes the value to the EEPROM.
+ **/
+static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 j;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_i350");
+
+ for (j = 0; j < 4; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_set_eee_i350 - Enable/disable EEE support
+ * @hw: pointer to the HW structure
+ *
+ * Enable/disable EEE based on setting in dev_spec structure.
+ *
+ **/
+s32 e1000_set_eee_i350(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u32 ipcnfg, eeer;
+
+ DEBUGFUNC("e1000_set_eee_i350");
+
+ if ((hw->mac.type < e1000_i350) ||
+ (hw->phy.media_type != e1000_media_type_copper))
+ goto out;
+ ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG);
+ eeer = E1000_READ_REG(hw, E1000_EEER);
+
+ /* enable or disable per user setting */
+ if (!(hw->dev_spec._82575.eee_disable)) {
+ u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU);
+
+ ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+ eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
+ E1000_EEER_LPI_FC);
+
+ /* This bit should not be set in normal operation. */
+ if (eee_su & E1000_EEE_SU_LPI_CLK_STP)
+ DEBUGOUT("LPI Clock Stop Bit should not be set!\n");
+ } else {
+ ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+ eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
+ E1000_EEER_LPI_FC);
+ }
+ E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg);
+ E1000_WRITE_REG(hw, E1000_EEER, eeer);
+ E1000_READ_REG(hw, E1000_IPCNFG);
+ E1000_READ_REG(hw, E1000_EEER);
+out:
+
+ return ret_val;
+}
+
+/* Due to a hw errata, if the host tries to configure the VFTA register
+ * while performing queries from the BMC or DMA, then the VFTA in some
+ * cases won't be written.
+ */
+
+/**
+ * e1000_clear_vfta_i350 - Clear VLAN filter table
+ * @hw: pointer to the HW structure
+ *
+ * Clears the register array which contains the VLAN filter table by
+ * setting all the values to 0.
+ **/
+void e1000_clear_vfta_i350(struct e1000_hw *hw)
+{
+ u32 offset;
+ int i;
+
+ DEBUGFUNC("e1000_clear_vfta_350");
+
+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+ for (i = 0; i < 10; i++)
+ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
+
+ E1000_WRITE_FLUSH(hw);
+ }
+}
+
+/**
+ * e1000_write_vfta_i350 - Write value to VLAN filter table
+ * @hw: pointer to the HW structure
+ * @offset: register offset in VLAN filter table
+ * @value: register value written to VLAN filter table
+ *
+ * Writes value at the given offset in the register array which stores
+ * the VLAN filter table.
+ **/
+void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
+{
+ int i;
+
+ DEBUGFUNC("e1000_write_vfta_350");
+
+ for (i = 0; i < 10; i++)
+ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
+
+ E1000_WRITE_FLUSH(hw);
+}
+
+
+/**
+ * e1000_set_i2c_bb - Enable I2C bit-bang
+ * @hw: pointer to the HW structure
+ *
+ * Enable I2C bit-bang interface
+ *
+ **/
+s32 e1000_set_i2c_bb(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u32 ctrl_ext, i2cparams;
+
+ DEBUGFUNC("e1000_set_i2c_bb");
+
+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_I2C_ENA;
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH(hw);
+
+ i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS);
+ i2cparams |= E1000_I2CBB_EN;
+ i2cparams |= E1000_I2C_DATA_OE_N;
+ i2cparams |= E1000_I2C_CLK_OE_N;
+ E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams);
+ E1000_WRITE_FLUSH(hw);
+
+ return ret_val;
+}
+
+/**
+ * e1000_read_i2c_byte_generic - Reads 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to read
+ * @dev_addr: device address
+ * @data: value read
+ *
+ * Performs byte read operation over I2C interface at
+ * a specified device address.
+ **/
+s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data)
+{
+ s32 status = E1000_SUCCESS;
+ u32 max_retry = 10;
+ u32 retry = 1;
+ u16 swfw_mask = 0;
+
+ bool nack = TRUE;
+
+ DEBUGFUNC("e1000_read_i2c_byte_generic");
+
+ swfw_mask = E1000_SWFW_PHY0_SM;
+
+ do {
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
+ != E1000_SUCCESS) {
+ status = E1000_ERR_SWFW_SYNC;
+ goto read_byte_out;
+ }
+
+ e1000_i2c_start(hw);
+
+ /* Device Address and write indication */
+ status = e1000_clock_out_i2c_byte(hw, dev_addr);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_get_i2c_ack(hw);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_clock_out_i2c_byte(hw, byte_offset);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_get_i2c_ack(hw);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ e1000_i2c_start(hw);
+
+ /* Device Address and read indication */
+ status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1));
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_get_i2c_ack(hw);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_clock_in_i2c_byte(hw, data);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_clock_out_i2c_bit(hw, nack);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ e1000_i2c_stop(hw);
+ break;
+
+fail:
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+ msec_delay(100);
+ e1000_i2c_bus_clear(hw);
+ retry++;
+ if (retry < max_retry)
+ DEBUGOUT("I2C byte read error - Retrying.\n");
+ else
+ DEBUGOUT("I2C byte read error.\n");
+
+ } while (retry < max_retry);
+
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+read_byte_out:
+
+ return status;
+}
+
+/**
+ * e1000_write_i2c_byte_generic - Writes 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @dev_addr: device address
+ * @data: value to write
+ *
+ * Performs byte write operation over I2C interface at
+ * a specified device address.
+ **/
+s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data)
+{
+ s32 status = E1000_SUCCESS;
+ u32 max_retry = 1;
+ u32 retry = 0;
+ u16 swfw_mask = 0;
+
+ DEBUGFUNC("e1000_write_i2c_byte_generic");
+
+ swfw_mask = E1000_SWFW_PHY0_SM;
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) {
+ status = E1000_ERR_SWFW_SYNC;
+ goto write_byte_out;
+ }
+
+ do {
+ e1000_i2c_start(hw);
+
+ status = e1000_clock_out_i2c_byte(hw, dev_addr);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_get_i2c_ack(hw);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_clock_out_i2c_byte(hw, byte_offset);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_get_i2c_ack(hw);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_clock_out_i2c_byte(hw, data);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ status = e1000_get_i2c_ack(hw);
+ if (status != E1000_SUCCESS)
+ goto fail;
+
+ e1000_i2c_stop(hw);
+ break;
+
+fail:
+ e1000_i2c_bus_clear(hw);
+ retry++;
+ if (retry < max_retry)
+ DEBUGOUT("I2C byte write error - Retrying.\n");
+ else
+ DEBUGOUT("I2C byte write error.\n");
+ } while (retry < max_retry);
+
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+write_byte_out:
+
+ return status;
+}
+
+/**
+ * e1000_i2c_start - Sets I2C start condition
+ * @hw: pointer to hardware structure
+ *
+ * Sets I2C start condition (High -> Low on SDA while SCL is High)
+ **/
+static void e1000_i2c_start(struct e1000_hw *hw)
+{
+ u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+ DEBUGFUNC("e1000_i2c_start");
+
+ /* Start condition must begin with data and clock high */
+ e1000_set_i2c_data(hw, &i2cctl, 1);
+ e1000_raise_i2c_clk(hw, &i2cctl);
+
+ /* Setup time for start condition (4.7us) */
+ usec_delay(E1000_I2C_T_SU_STA);
+
+ e1000_set_i2c_data(hw, &i2cctl, 0);
+
+ /* Hold time for start condition (4us) */
+ usec_delay(E1000_I2C_T_HD_STA);
+
+ e1000_lower_i2c_clk(hw, &i2cctl);
+
+ /* Minimum low period of clock is 4.7 us */
+ usec_delay(E1000_I2C_T_LOW);
+
+}
+
+/**
+ * e1000_i2c_stop - Sets I2C stop condition
+ * @hw: pointer to hardware structure
+ *
+ * Sets I2C stop condition (Low -> High on SDA while SCL is High)
+ **/
+static void e1000_i2c_stop(struct e1000_hw *hw)
+{
+ u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+ DEBUGFUNC("e1000_i2c_stop");
+
+ /* Stop condition must begin with data low and clock high */
+ e1000_set_i2c_data(hw, &i2cctl, 0);
+ e1000_raise_i2c_clk(hw, &i2cctl);
+
+ /* Setup time for stop condition (4us) */
+ usec_delay(E1000_I2C_T_SU_STO);
+
+ e1000_set_i2c_data(hw, &i2cctl, 1);
+
+ /* bus free time between stop and start (4.7us)*/
+ usec_delay(E1000_I2C_T_BUF);
+}
+
+/**
+ * e1000_clock_in_i2c_byte - Clocks in one byte via I2C
+ * @hw: pointer to hardware structure
+ * @data: data byte to clock in
+ *
+ * Clocks in one byte data via I2C data/clock
+ **/
+static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data)
+{
+ s32 i;
+ bool bit = 0;
+
+ DEBUGFUNC("e1000_clock_in_i2c_byte");
+
+ *data = 0;
+ for (i = 7; i >= 0; i--) {
+ e1000_clock_in_i2c_bit(hw, &bit);
+ *data |= bit << i;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_clock_out_i2c_byte - Clocks out one byte via I2C
+ * @hw: pointer to hardware structure
+ * @data: data byte clocked out
+ *
+ * Clocks out one byte data via I2C data/clock
+ **/
+static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data)
+{
+ s32 status = E1000_SUCCESS;
+ s32 i;
+ u32 i2cctl;
+ bool bit = 0;
+
+ DEBUGFUNC("e1000_clock_out_i2c_byte");
+
+ for (i = 7; i >= 0; i--) {
+ bit = (data >> i) & 0x1;
+ status = e1000_clock_out_i2c_bit(hw, bit);
+
+ if (status != E1000_SUCCESS)
+ break;
+ }
+
+ /* Release SDA line (set high) */
+ i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+ i2cctl |= E1000_I2C_DATA_OE_N;
+ E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl);
+ E1000_WRITE_FLUSH(hw);
+
+ return status;
+}
+
+/**
+ * e1000_get_i2c_ack - Polls for I2C ACK
+ * @hw: pointer to hardware structure
+ *
+ * Clocks in/out one bit via I2C data/clock
+ **/
+static s32 e1000_get_i2c_ack(struct e1000_hw *hw)
+{
+ s32 status = E1000_SUCCESS;
+ u32 i = 0;
+ u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+ u32 timeout = 10;
+ bool ack = TRUE;
+
+ DEBUGFUNC("e1000_get_i2c_ack");
+
+ e1000_raise_i2c_clk(hw, &i2cctl);
+
+ /* Minimum high period of clock is 4us */
+ usec_delay(E1000_I2C_T_HIGH);
+
+ /* Wait until SCL returns high */
+ for (i = 0; i < timeout; i++) {
+ usec_delay(1);
+ i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+ if (i2cctl & E1000_I2C_CLK_IN)
+ break;
+ }
+ if (!(i2cctl & E1000_I2C_CLK_IN))
+ return E1000_ERR_I2C;
+
+ ack = e1000_get_i2c_data(&i2cctl);
+ if (ack) {
+ DEBUGOUT("I2C ack was not received.\n");
+ status = E1000_ERR_I2C;
+ }
+
+ e1000_lower_i2c_clk(hw, &i2cctl);
+
+ /* Minimum low period of clock is 4.7 us */
+ usec_delay(E1000_I2C_T_LOW);
+
+ return status;
+}
+
+/**
+ * e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
+ * @hw: pointer to hardware structure
+ * @data: read data value
+ *
+ * Clocks in one bit via I2C data/clock
+ **/
+static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data)
+{
+ u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+ DEBUGFUNC("e1000_clock_in_i2c_bit");
+
+ e1000_raise_i2c_clk(hw, &i2cctl);
+
+ /* Minimum high period of clock is 4us */
+ usec_delay(E1000_I2C_T_HIGH);
+
+ i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+ *data = e1000_get_i2c_data(&i2cctl);
+
+ e1000_lower_i2c_clk(hw, &i2cctl);
+
+ /* Minimum low period of clock is 4.7 us */
+ usec_delay(E1000_I2C_T_LOW);
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
+ * @hw: pointer to hardware structure
+ * @data: data value to write
+ *
+ * Clocks out one bit via I2C data/clock
+ **/
+static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data)
+{
+ s32 status;
+ u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+
+ DEBUGFUNC("e1000_clock_out_i2c_bit");
+
+ status = e1000_set_i2c_data(hw, &i2cctl, data);
+ if (status == E1000_SUCCESS) {
+ e1000_raise_i2c_clk(hw, &i2cctl);
+
+ /* Minimum high period of clock is 4us */
+ usec_delay(E1000_I2C_T_HIGH);
+
+ e1000_lower_i2c_clk(hw, &i2cctl);
+
+ /* Minimum low period of clock is 4.7 us.
+ * This also takes care of the data hold time.
+ */
+ usec_delay(E1000_I2C_T_LOW);
+ } else {
+ status = E1000_ERR_I2C;
+ DEBUGOUT1("I2C data was not set to %X\n", data);
+ }
+
+ return status;
+}
+/**
+ * e1000_raise_i2c_clk - Raises the I2C SCL clock
+ * @hw: pointer to hardware structure
+ * @i2cctl: Current value of I2CCTL register
+ *
+ * Raises the I2C clock line '0'->'1'
+ **/
+static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
+{
+ DEBUGFUNC("e1000_raise_i2c_clk");
+
+ *i2cctl |= E1000_I2C_CLK_OUT;
+ *i2cctl &= ~E1000_I2C_CLK_OE_N;
+ E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
+ E1000_WRITE_FLUSH(hw);
+
+ /* SCL rise time (1000ns) */
+ usec_delay(E1000_I2C_T_RISE);
+}
+
+/**
+ * e1000_lower_i2c_clk - Lowers the I2C SCL clock
+ * @hw: pointer to hardware structure
+ * @i2cctl: Current value of I2CCTL register
+ *
+ * Lowers the I2C clock line '1'->'0'
+ **/
+static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
+{
+
+ DEBUGFUNC("e1000_lower_i2c_clk");
+
+ *i2cctl &= ~E1000_I2C_CLK_OUT;
+ *i2cctl &= ~E1000_I2C_CLK_OE_N;
+ E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
+ E1000_WRITE_FLUSH(hw);
+
+ /* SCL fall time (300ns) */
+ usec_delay(E1000_I2C_T_FALL);
+}
+
+/**
+ * e1000_set_i2c_data - Sets the I2C data bit
+ * @hw: pointer to hardware structure
+ * @i2cctl: Current value of I2CCTL register
+ * @data: I2C data value (0 or 1) to set
+ *
+ * Sets the I2C data bit
+ **/
+static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data)
+{
+ s32 status = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_set_i2c_data");
+
+ if (data)
+ *i2cctl |= E1000_I2C_DATA_OUT;
+ else
+ *i2cctl &= ~E1000_I2C_DATA_OUT;
+
+ *i2cctl &= ~E1000_I2C_DATA_OE_N;
+ *i2cctl |= E1000_I2C_CLK_OE_N;
+ E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
+ E1000_WRITE_FLUSH(hw);
+
+ /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
+ usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA);
+
+ *i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+ if (data != e1000_get_i2c_data(i2cctl)) {
+ status = E1000_ERR_I2C;
+ DEBUGOUT1("Error - I2C data was not set to %X.\n", data);
+ }
+
+ return status;
+}
+
+/**
+ * e1000_get_i2c_data - Reads the I2C SDA data bit
+ * @hw: pointer to hardware structure
+ * @i2cctl: Current value of I2CCTL register
+ *
+ * Returns the I2C data bit value
+ **/
+static bool e1000_get_i2c_data(u32 *i2cctl)
+{
+ bool data;
+
+ DEBUGFUNC("e1000_get_i2c_data");
+
+ if (*i2cctl & E1000_I2C_DATA_IN)
+ data = 1;
+ else
+ data = 0;
+
+ return data;
+}
+
+/**
+ * e1000_i2c_bus_clear - Clears the I2C bus
+ * @hw: pointer to hardware structure
+ *
+ * Clears the I2C bus by sending nine clock pulses.
+ * Used when data line is stuck low.
+ **/
+void e1000_i2c_bus_clear(struct e1000_hw *hw)
+{
+ u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
+ u32 i;
+
+ DEBUGFUNC("e1000_i2c_bus_clear");
+
+ e1000_i2c_start(hw);
+
+ e1000_set_i2c_data(hw, &i2cctl, 1);
+
+ for (i = 0; i < 9; i++) {
+ e1000_raise_i2c_clk(hw, &i2cctl);
+
+ /* Min high period of clock is 4us */
+ usec_delay(E1000_I2C_T_HIGH);
+
+ e1000_lower_i2c_clk(hw, &i2cctl);
+
+ /* Min low period of clock is 4.7us*/
+ usec_delay(E1000_I2C_T_LOW);
+ }
+
+ e1000_i2c_start(hw);
+
+ /* Put the i2c bus back to default state */
+ e1000_i2c_stop(hw);
+}
+
+
diff --git a/freebsd/sys/dev/e1000/e1000_82575.h b/freebsd/sys/dev/e1000/e1000_82575.h
index eb05262d..c6bbe186 100644
--- a/freebsd/sys/dev/e1000/e1000_82575.h
+++ b/freebsd/sys/dev/e1000/e1000_82575.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,10 +35,10 @@
#ifndef _E1000_82575_H_
#define _E1000_82575_H_
-#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
- (ID_LED_DEF1_DEF2 << 8) | \
- (ID_LED_DEF1_DEF2 << 4) | \
- (ID_LED_OFF1_ON2))
+#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
+ (ID_LED_DEF1_DEF2 << 8) | \
+ (ID_LED_DEF1_DEF2 << 4) | \
+ (ID_LED_OFF1_ON2))
/*
* Receive Address Register Count
* Number of high/low register pairs in the RAR. The RAR (Receive Address
@@ -49,12 +49,13 @@
* For 82576, there are an additional set of RARs that begin at an offset
* separate from the first set of RARs.
*/
-#define E1000_RAR_ENTRIES_82575 16
-#define E1000_RAR_ENTRIES_82576 24
-#define E1000_RAR_ENTRIES_82580 24
-#define E1000_SW_SYNCH_MB 0x00000100
-#define E1000_STAT_DEV_RST_SET 0x00100000
-#define E1000_CTRL_DEV_RST 0x20000000
+#define E1000_RAR_ENTRIES_82575 16
+#define E1000_RAR_ENTRIES_82576 24
+#define E1000_RAR_ENTRIES_82580 24
+#define E1000_RAR_ENTRIES_I350 32
+#define E1000_SW_SYNCH_MB 0x00000100
+#define E1000_STAT_DEV_RST_SET 0x00100000
+#define E1000_CTRL_DEV_RST 0x20000000
#ifdef E1000_BIT_FIELDS
struct e1000_adv_data_desc {
@@ -62,137 +63,138 @@ struct e1000_adv_data_desc {
union {
u32 data;
struct {
- u32 datalen :16; /* Data buffer length */
- u32 rsvd :4;
- u32 dtyp :4; /* Descriptor type */
- u32 dcmd :8; /* Descriptor command */
+ u32 datalen:16; /* Data buffer length */
+ u32 rsvd:4;
+ u32 dtyp:4; /* Descriptor type */
+ u32 dcmd:8; /* Descriptor command */
} config;
} lower;
union {
u32 data;
struct {
- u32 status :4; /* Descriptor status */
- u32 idx :4;
- u32 popts :6; /* Packet Options */
- u32 paylen :18; /* Payload length */
+ u32 status:4; /* Descriptor status */
+ u32 idx:4;
+ u32 popts:6; /* Packet Options */
+ u32 paylen:18; /* Payload length */
} options;
} upper;
};
-#define E1000_TXD_DTYP_ADV_C 0x2 /* Advanced Context Descriptor */
-#define E1000_TXD_DTYP_ADV_D 0x3 /* Advanced Data Descriptor */
-#define E1000_ADV_TXD_CMD_DEXT 0x20 /* Descriptor extension (0 = legacy) */
-#define E1000_ADV_TUCMD_IPV4 0x2 /* IP Packet Type: 1=IPv4 */
-#define E1000_ADV_TUCMD_IPV6 0x0 /* IP Packet Type: 0=IPv6 */
-#define E1000_ADV_TUCMD_L4T_UDP 0x0 /* L4 Packet TYPE of UDP */
-#define E1000_ADV_TUCMD_L4T_TCP 0x4 /* L4 Packet TYPE of TCP */
-#define E1000_ADV_TUCMD_MKRREQ 0x10 /* Indicates markers are required */
-#define E1000_ADV_DCMD_EOP 0x1 /* End of Packet */
-#define E1000_ADV_DCMD_IFCS 0x2 /* Insert FCS (Ethernet CRC) */
-#define E1000_ADV_DCMD_RS 0x8 /* Report Status */
-#define E1000_ADV_DCMD_VLE 0x40 /* Add VLAN tag */
-#define E1000_ADV_DCMD_TSE 0x80 /* TCP Seg enable */
+#define E1000_TXD_DTYP_ADV_C 0x2 /* Advanced Context Descriptor */
+#define E1000_TXD_DTYP_ADV_D 0x3 /* Advanced Data Descriptor */
+#define E1000_ADV_TXD_CMD_DEXT 0x20 /* Descriptor extension (0 = legacy) */
+#define E1000_ADV_TUCMD_IPV4 0x2 /* IP Packet Type: 1=IPv4 */
+#define E1000_ADV_TUCMD_IPV6 0x0 /* IP Packet Type: 0=IPv6 */
+#define E1000_ADV_TUCMD_L4T_UDP 0x0 /* L4 Packet TYPE of UDP */
+#define E1000_ADV_TUCMD_L4T_TCP 0x4 /* L4 Packet TYPE of TCP */
+#define E1000_ADV_TUCMD_MKRREQ 0x10 /* Indicates markers are required */
+#define E1000_ADV_DCMD_EOP 0x1 /* End of Packet */
+#define E1000_ADV_DCMD_IFCS 0x2 /* Insert FCS (Ethernet CRC) */
+#define E1000_ADV_DCMD_RS 0x8 /* Report Status */
+#define E1000_ADV_DCMD_VLE 0x40 /* Add VLAN tag */
+#define E1000_ADV_DCMD_TSE 0x80 /* TCP Seg enable */
/* Extended Device Control */
-#define E1000_CTRL_EXT_NSICR 0x00000001 /* Disable Intr Clear all on read */
+#define E1000_CTRL_EXT_NSICR 0x00000001 /* Disable Intr Clear all on read */
struct e1000_adv_context_desc {
union {
u32 ip_config;
struct {
- u32 iplen :9;
- u32 maclen :7;
- u32 vlan_tag :16;
+ u32 iplen:9;
+ u32 maclen:7;
+ u32 vlan_tag:16;
} fields;
} ip_setup;
u32 seq_num;
union {
u64 l4_config;
struct {
- u32 mkrloc :9;
- u32 tucmd :11;
- u32 dtyp :4;
- u32 adv :8;
- u32 rsvd :4;
- u32 idx :4;
- u32 l4len :8;
- u32 mss :16;
+ u32 mkrloc:9;
+ u32 tucmd:11;
+ u32 dtyp:4;
+ u32 adv:8;
+ u32 rsvd:4;
+ u32 idx:4;
+ u32 l4len:8;
+ u32 mss:16;
} fields;
} l4_setup;
};
#endif
/* SRRCTL bit definitions */
-#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
-#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
-#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
-#define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000
-#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
-#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
-#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
-#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
+#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
+#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
+#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
+#define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000
+#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
+#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
+#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
-#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
-#define E1000_SRRCTL_TIMESTAMP 0x40000000
-#define E1000_SRRCTL_DROP_EN 0x80000000
-
-#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
-#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
-
-#define E1000_TX_HEAD_WB_ENABLE 0x1
-#define E1000_TX_SEQNUM_WB_ENABLE 0x2
-
-#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002
-#define E1000_MRQC_ENABLE_VMDQ 0x00000003
-#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
-#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
-#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
-#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
-#define E1000_MRQC_ENABLE_RSS_8Q 0x00000002
-
-#define E1000_VMRCTL_MIRROR_PORT_SHIFT 8
-#define E1000_VMRCTL_MIRROR_DSTPORT_MASK (7 << E1000_VMRCTL_MIRROR_PORT_SHIFT)
-#define E1000_VMRCTL_POOL_MIRROR_ENABLE (1 << 0)
-#define E1000_VMRCTL_UPLINK_MIRROR_ENABLE (1 << 1)
-#define E1000_VMRCTL_DOWNLINK_MIRROR_ENABLE (1 << 2)
+#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
+#define E1000_SRRCTL_TIMESTAMP 0x40000000
+#define E1000_SRRCTL_DROP_EN 0x80000000
+
+#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
+#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
+
+#define E1000_TX_HEAD_WB_ENABLE 0x1
+#define E1000_TX_SEQNUM_WB_ENABLE 0x2
+
+#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002
+#define E1000_MRQC_ENABLE_VMDQ 0x00000003
+#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
+#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
+#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
+#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
+#define E1000_MRQC_ENABLE_RSS_8Q 0x00000002
+
+#define E1000_VMRCTL_MIRROR_PORT_SHIFT 8
+#define E1000_VMRCTL_MIRROR_DSTPORT_MASK (7 << \
+ E1000_VMRCTL_MIRROR_PORT_SHIFT)
+#define E1000_VMRCTL_POOL_MIRROR_ENABLE (1 << 0)
+#define E1000_VMRCTL_UPLINK_MIRROR_ENABLE (1 << 1)
+#define E1000_VMRCTL_DOWNLINK_MIRROR_ENABLE (1 << 2)
#define E1000_EICR_TX_QUEUE ( \
- E1000_EICR_TX_QUEUE0 | \
- E1000_EICR_TX_QUEUE1 | \
- E1000_EICR_TX_QUEUE2 | \
- E1000_EICR_TX_QUEUE3)
+ E1000_EICR_TX_QUEUE0 | \
+ E1000_EICR_TX_QUEUE1 | \
+ E1000_EICR_TX_QUEUE2 | \
+ E1000_EICR_TX_QUEUE3)
#define E1000_EICR_RX_QUEUE ( \
- E1000_EICR_RX_QUEUE0 | \
- E1000_EICR_RX_QUEUE1 | \
- E1000_EICR_RX_QUEUE2 | \
- E1000_EICR_RX_QUEUE3)
+ E1000_EICR_RX_QUEUE0 | \
+ E1000_EICR_RX_QUEUE1 | \
+ E1000_EICR_RX_QUEUE2 | \
+ E1000_EICR_RX_QUEUE3)
-#define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE
-#define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE
+#define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE
+#define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE
#define EIMS_ENABLE_MASK ( \
- E1000_EIMS_RX_QUEUE | \
- E1000_EIMS_TX_QUEUE | \
- E1000_EIMS_TCP_TIMER | \
- E1000_EIMS_OTHER)
+ E1000_EIMS_RX_QUEUE | \
+ E1000_EIMS_TX_QUEUE | \
+ E1000_EIMS_TCP_TIMER | \
+ E1000_EIMS_OTHER)
/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
-#define E1000_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */
-#define E1000_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */
-#define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
-#define E1000_IMIREXT_CTRL_URG 0x00002000 /* Check URG bit in header */
-#define E1000_IMIREXT_CTRL_ACK 0x00004000 /* Check ACK bit in header */
-#define E1000_IMIREXT_CTRL_PSH 0x00008000 /* Check PSH bit in header */
-#define E1000_IMIREXT_CTRL_RST 0x00010000 /* Check RST bit in header */
-#define E1000_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */
-#define E1000_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */
-#define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
+#define E1000_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */
+#define E1000_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */
+#define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
+#define E1000_IMIREXT_CTRL_URG 0x00002000 /* Check URG bit in header */
+#define E1000_IMIREXT_CTRL_ACK 0x00004000 /* Check ACK bit in header */
+#define E1000_IMIREXT_CTRL_PSH 0x00008000 /* Check PSH bit in header */
+#define E1000_IMIREXT_CTRL_RST 0x00010000 /* Check RST bit in header */
+#define E1000_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */
+#define E1000_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */
+#define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
/* Receive Descriptor - Advanced */
union e1000_adv_rx_desc {
struct {
- __le64 pkt_addr; /* Packet buffer address */
- __le64 hdr_addr; /* Header buffer address */
+ __le64 pkt_addr; /* Packet buffer address */
+ __le64 hdr_addr; /* Header buffer address */
} read;
struct {
struct {
@@ -200,79 +202,79 @@ union e1000_adv_rx_desc {
__le32 data;
struct {
__le16 pkt_info; /*RSS type, Pkt type*/
- __le16 hdr_info; /* Split Header,
- * header buffer len*/
+ /* Split Header, header buffer len */
+ __le16 hdr_info;
} hs_rss;
} lo_dword;
union {
- __le32 rss; /* RSS Hash */
+ __le32 rss; /* RSS Hash */
struct {
- __le16 ip_id; /* IP id */
- __le16 csum; /* Packet Checksum */
+ __le16 ip_id; /* IP id */
+ __le16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
struct {
- __le32 status_error; /* ext status/error */
- __le16 length; /* Packet length */
- __le16 vlan; /* VLAN tag */
+ __le32 status_error; /* ext status/error */
+ __le16 length; /* Packet length */
+ __le16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
-#define E1000_RXDADV_RSSTYPE_MASK 0x0000000F
-#define E1000_RXDADV_RSSTYPE_SHIFT 12
-#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
-#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
-#define E1000_RXDADV_SPLITHEADER_EN 0x00001000
-#define E1000_RXDADV_SPH 0x8000
-#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */
-#define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
-#define E1000_RXDADV_ERR_HBO 0x00800000
+#define E1000_RXDADV_RSSTYPE_MASK 0x0000000F
+#define E1000_RXDADV_RSSTYPE_SHIFT 12
+#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
+#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
+#define E1000_RXDADV_SPLITHEADER_EN 0x00001000
+#define E1000_RXDADV_SPH 0x8000
+#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */
+#define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
+#define E1000_RXDADV_ERR_HBO 0x00800000
/* RSS Hash results */
-#define E1000_RXDADV_RSSTYPE_NONE 0x00000000
-#define E1000_RXDADV_RSSTYPE_IPV4_TCP 0x00000001
-#define E1000_RXDADV_RSSTYPE_IPV4 0x00000002
-#define E1000_RXDADV_RSSTYPE_IPV6_TCP 0x00000003
-#define E1000_RXDADV_RSSTYPE_IPV6_EX 0x00000004
-#define E1000_RXDADV_RSSTYPE_IPV6 0x00000005
+#define E1000_RXDADV_RSSTYPE_NONE 0x00000000
+#define E1000_RXDADV_RSSTYPE_IPV4_TCP 0x00000001
+#define E1000_RXDADV_RSSTYPE_IPV4 0x00000002
+#define E1000_RXDADV_RSSTYPE_IPV6_TCP 0x00000003
+#define E1000_RXDADV_RSSTYPE_IPV6_EX 0x00000004
+#define E1000_RXDADV_RSSTYPE_IPV6 0x00000005
#define E1000_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006
-#define E1000_RXDADV_RSSTYPE_IPV4_UDP 0x00000007
-#define E1000_RXDADV_RSSTYPE_IPV6_UDP 0x00000008
+#define E1000_RXDADV_RSSTYPE_IPV4_UDP 0x00000007
+#define E1000_RXDADV_RSSTYPE_IPV6_UDP 0x00000008
#define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009
/* RSS Packet Types as indicated in the receive descriptor */
-#define E1000_RXDADV_PKTTYPE_NONE 0x00000000
-#define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */
-#define E1000_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */
-#define E1000_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPV6 hdr present */
-#define E1000_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPV6 hdr + extensions */
-#define E1000_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */
-#define E1000_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */
-#define E1000_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */
-#define E1000_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */
-
-#define E1000_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */
-#define E1000_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */
-#define E1000_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */
-#define E1000_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */
-#define E1000_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */
-#define E1000_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */
+#define E1000_RXDADV_PKTTYPE_NONE 0x00000000
+#define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */
+#define E1000_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */
+#define E1000_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPV6 hdr present */
+#define E1000_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPV6 hdr + extensions */
+#define E1000_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */
+#define E1000_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */
+#define E1000_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */
+#define E1000_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */
+
+#define E1000_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */
+#define E1000_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */
+#define E1000_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */
+#define E1000_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */
+#define E1000_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */
+#define E1000_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */
/* LinkSec results */
/* Security Processing bit Indication */
-#define E1000_RXDADV_LNKSEC_STATUS_SECP 0x00020000
-#define E1000_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000
-#define E1000_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000
-#define E1000_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000
-#define E1000_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000
-
-#define E1000_RXDADV_IPSEC_STATUS_SECP 0x00020000
-#define E1000_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000
-#define E1000_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000
-#define E1000_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000
-#define E1000_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED 0x18000000
+#define E1000_RXDADV_LNKSEC_STATUS_SECP 0x00020000
+#define E1000_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000
+#define E1000_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000
+#define E1000_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000
+#define E1000_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000
+
+#define E1000_RXDADV_IPSEC_STATUS_SECP 0x00020000
+#define E1000_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000
+#define E1000_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000
+#define E1000_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000
+#define E1000_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED 0x18000000
/* Transmit Descriptor - Advanced */
union e1000_adv_tx_desc {
@@ -289,25 +291,26 @@ union e1000_adv_tx_desc {
};
/* Adv Transmit Descriptor Config Masks */
-#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
-#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
-#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
-#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
-#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
-#define E1000_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */
-#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
-#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
-#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
-#define E1000_ADVTXD_MAC_LINKSEC 0x00040000 /* Apply LinkSec on packet */
-#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
-#define E1000_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED present in WB */
-#define E1000_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */
-#define E1000_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */
-#define E1000_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */
-#define E1000_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
-#define E1000_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU*/
-#define E1000_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */
-#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
+#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
+#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
+#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
+#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
+#define E1000_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */
+#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
+#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
+#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
+#define E1000_ADVTXD_MAC_LINKSEC 0x00040000 /* Apply LinkSec on pkt */
+#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp pkt */
+#define E1000_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED prsnt in WB */
+#define E1000_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */
+#define E1000_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */
+#define E1000_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */
+#define E1000_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
+/* 1st & Last TSO-full iSCSI PDU*/
+#define E1000_ADVTXD_POPTS_ISCO_FULL 0x00001800
+#define E1000_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */
+#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
/* Context descriptors */
struct e1000_adv_tx_context_desc {
@@ -317,65 +320,69 @@ struct e1000_adv_tx_context_desc {
__le32 mss_l4len_idx;
};
-#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
-#define E1000_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */
-#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
-#define E1000_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
-#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
-#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
-#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
-#define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
+#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
+#define E1000_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */
+#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
+#define E1000_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
+#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
+#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
+#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
+#define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
/* IPSec Encrypt Enable for ESP */
-#define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000
-#define E1000_ADVTXD_TUCMD_MKRREQ 0x00002000 /* Req requires Markers and CRC */
-#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
-#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
+#define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000
+/* Req requires Markers and CRC */
+#define E1000_ADVTXD_TUCMD_MKRREQ 0x00002000
+#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
+#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
/* Adv ctxt IPSec SA IDX mask */
-#define E1000_ADVTXD_IPSEC_SA_INDEX_MASK 0x000000FF
+#define E1000_ADVTXD_IPSEC_SA_INDEX_MASK 0x000000FF
/* Adv ctxt IPSec ESP len mask */
-#define E1000_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF
+#define E1000_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF
/* Additional Transmit Descriptor Control definitions */
-#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
-#define E1000_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. write-back flushing */
+#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
+#define E1000_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. wbk flushing */
/* Tx Queue Arbitration Priority 0=low, 1=high */
-#define E1000_TXDCTL_PRIORITY 0x08000000
+#define E1000_TXDCTL_PRIORITY 0x08000000
/* Additional Receive Descriptor Control definitions */
-#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
-#define E1000_RXDCTL_SWFLSH 0x04000000 /* Rx Desc. write-back flushing */
+#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
+#define E1000_RXDCTL_SWFLSH 0x04000000 /* Rx Desc. wbk flushing */
/* Direct Cache Access (DCA) definitions */
-#define E1000_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */
-#define E1000_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */
+#define E1000_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */
+#define E1000_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */
-#define E1000_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */
-#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
+#define E1000_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */
+#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
-#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
-#define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
-#define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */
-#define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
+#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
+#define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
+#define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header ena */
+#define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload ena */
+#define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx Desc Relax Order */
-#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
-#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
-#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
+#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
+#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
+#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */
+#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
+#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */
-#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
-#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
-#define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */
-#define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */
+#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
+#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
+#define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */
+#define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */
/* Additional interrupt register bit definitions */
-#define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */
-#define E1000_IMS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */
-#define E1000_ICS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */
+#define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */
+#define E1000_IMS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */
+#define E1000_ICS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */
/* ETQF register bit definitions */
-#define E1000_ETQF_FILTER_ENABLE (1 << 26)
-#define E1000_ETQF_IMM_INT (1 << 29)
-#define E1000_ETQF_1588 (1 << 30)
-#define E1000_ETQF_QUEUE_ENABLE (1 << 31)
+#define E1000_ETQF_FILTER_ENABLE (1 << 26)
+#define E1000_ETQF_IMM_INT (1 << 29)
+#define E1000_ETQF_1588 (1 << 30)
+#define E1000_ETQF_QUEUE_ENABLE (1 << 31)
/*
* ETQF filter list: one static filter per filter consumer. This is
* to avoid filter collisions later. Add new filters
@@ -384,82 +391,94 @@ struct e1000_adv_tx_context_desc {
* Current filters:
* EAPOL 802.1x (0x888e): Filter 0
*/
-#define E1000_ETQF_FILTER_EAPOL 0
-
-#define E1000_FTQF_VF_BP 0x00008000
-#define E1000_FTQF_1588_TIME_STAMP 0x08000000
-#define E1000_FTQF_MASK 0xF0000000
-#define E1000_FTQF_MASK_PROTO_BP 0x10000000
-#define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000
-#define E1000_FTQF_MASK_DEST_ADDR_BP 0x40000000
-#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
-
-#define E1000_NVM_APME_82575 0x0400
-#define MAX_NUM_VFS 8
-
-#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
-#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
-#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
-#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
-#define E1000_DTXSWC_LLE_SHIFT 16
-#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */
+#define E1000_ETQF_FILTER_EAPOL 0
+
+#define E1000_FTQF_VF_BP 0x00008000
+#define E1000_FTQF_1588_TIME_STAMP 0x08000000
+#define E1000_FTQF_MASK 0xF0000000
+#define E1000_FTQF_MASK_PROTO_BP 0x10000000
+#define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000
+#define E1000_FTQF_MASK_DEST_ADDR_BP 0x40000000
+#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
+
+#define E1000_NVM_APME_82575 0x0400
+#define MAX_NUM_VFS 7
+
+#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof cntrl */
+#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof cntrl */
+#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
+#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
+#define E1000_DTXSWC_LLE_SHIFT 16
+#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */
/* Easy defines for setting default pool, would normally be left a zero */
-#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
-#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
+#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
+#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
/* Other useful VMD_CTL register defines */
-#define E1000_VT_CTL_IGNORE_MAC (1 << 28)
-#define E1000_VT_CTL_DISABLE_DEF_POOL (1 << 29)
-#define E1000_VT_CTL_VM_REPL_EN (1 << 30)
+#define E1000_VT_CTL_IGNORE_MAC (1 << 28)
+#define E1000_VT_CTL_DISABLE_DEF_POOL (1 << 29)
+#define E1000_VT_CTL_VM_REPL_EN (1 << 30)
/* Per VM Offload register setup */
-#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
-#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */
-#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */
-#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */
-#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */
-#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */
-#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
-#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
-#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
-#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
-
-
-#define E1000_VLVF_ARRAY_SIZE 32
-#define E1000_VLVF_VLANID_MASK 0x00000FFF
-#define E1000_VLVF_POOLSEL_SHIFT 12
-#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
-#define E1000_VLVF_LVLAN 0x00100000
-#define E1000_VLVF_VLANID_ENABLE 0x80000000
-
-#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
-#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
-
-#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
-
-#define E1000_IOVCTL 0x05BBC
-#define E1000_IOVCTL_REUSE_VFQ 0x00000001
-
-#define E1000_RPLOLR_STRVLAN 0x40000000
-#define E1000_RPLOLR_STRCRC 0x80000000
-
-#define E1000_TCTL_EXT_COLD 0x000FFC00
-#define E1000_TCTL_EXT_COLD_SHIFT 10
-
-#define E1000_DTXCTL_8023LL 0x0004
-#define E1000_DTXCTL_VLAN_ADDED 0x0008
-#define E1000_DTXCTL_OOS_ENABLE 0x0010
-#define E1000_DTXCTL_MDP_EN 0x0020
-#define E1000_DTXCTL_SPOOF_INT 0x0040
-
-#define ALL_QUEUES 0xFFFF
-
-/* RX packet buffer size defines */
-#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
+#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
+#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */
+#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */
+#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */
+#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */
+#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */
+#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
+#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
+#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
+#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
+
+#define E1000_VMOLR_VPE 0x00800000 /* VLAN promiscuous enable */
+#define E1000_VMOLR_UPE 0x20000000 /* Unicast promisuous enable */
+#define E1000_DVMOLR_HIDVLAN 0x20000000 /* Vlan hiding enable */
+#define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
+#define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */
+
+#define E1000_PBRWAC_WALPB 0x00000007 /* Wrap around event on LAN Rx PB */
+#define E1000_PBRWAC_PBE 0x00000008 /* Rx packet buffer empty */
+
+#define E1000_VLVF_ARRAY_SIZE 32
+#define E1000_VLVF_VLANID_MASK 0x00000FFF
+#define E1000_VLVF_POOLSEL_SHIFT 12
+#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
+#define E1000_VLVF_LVLAN 0x00100000
+#define E1000_VLVF_VLANID_ENABLE 0x80000000
+
+#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
+#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
+
+#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
+
+#define E1000_IOVCTL 0x05BBC
+#define E1000_IOVCTL_REUSE_VFQ 0x00000001
+
+#define E1000_RPLOLR_STRVLAN 0x40000000
+#define E1000_RPLOLR_STRCRC 0x80000000
+
+#define E1000_TCTL_EXT_COLD 0x000FFC00
+#define E1000_TCTL_EXT_COLD_SHIFT 10
+
+#define E1000_DTXCTL_8023LL 0x0004
+#define E1000_DTXCTL_VLAN_ADDED 0x0008
+#define E1000_DTXCTL_OOS_ENABLE 0x0010
+#define E1000_DTXCTL_MDP_EN 0x0020
+#define E1000_DTXCTL_SPOOF_INT 0x0040
+
+#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT (1 << 14)
+
+#define ALL_QUEUES 0xFFFF
+
+/* Rx packet buffer size defines */
+#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable);
void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf);
void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable);
+s32 e1000_init_nvm_params_82575(struct e1000_hw *hw);
+
enum e1000_promisc_type {
e1000_promisc_disabled = 0, /* all promisc modes disabled */
e1000_promisc_unicast = 1, /* unicast promiscuous enabled */
@@ -472,4 +491,24 @@ void e1000_vfta_set_vf(struct e1000_hw *, u16, bool);
void e1000_rlpml_set_vf(struct e1000_hw *, u16);
s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type);
u16 e1000_rxpbs_adjust_82580(u32 data);
+s32 e1000_set_eee_i350(struct e1000_hw *);
+
+/* I2C SDA and SCL timing parameters for standard mode */
+#define E1000_I2C_T_HD_STA 4
+#define E1000_I2C_T_LOW 5
+#define E1000_I2C_T_HIGH 4
+#define E1000_I2C_T_SU_STA 5
+#define E1000_I2C_T_HD_DATA 5
+#define E1000_I2C_T_SU_DATA 1
+#define E1000_I2C_T_RISE 1
+#define E1000_I2C_T_FALL 1
+#define E1000_I2C_T_SU_STO 4
+#define E1000_I2C_T_BUF 5
+
+s32 e1000_set_i2c_bb(struct e1000_hw *hw);
+s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data);
+s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data);
+void e1000_i2c_bus_clear(struct e1000_hw *hw);
#endif /* _E1000_82575_H_ */
diff --git a/freebsd/sys/dev/e1000/e1000_api.c b/freebsd/sys/dev/e1000/e1000_api.c
index 17b4c817..5fec9941 100644
--- a/freebsd/sys/dev/e1000/e1000_api.c
+++ b/freebsd/sys/dev/e1000/e1000_api.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -283,7 +283,6 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_ICH10_D_BM_LM:
case E1000_DEV_ID_ICH10_D_BM_LF:
case E1000_DEV_ID_ICH10_D_BM_V:
- case E1000_DEV_ID_ICH10_HANKSVILLE:
mac->type = e1000_ich10lan;
break;
case E1000_DEV_ID_PCH_D_HV_DM:
@@ -296,10 +295,15 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_PCH2_LV_V:
mac->type = e1000_pch2lan;
break;
+ case E1000_DEV_ID_PCH_LPT_I217_LM:
+ case E1000_DEV_ID_PCH_LPT_I217_V:
+ case E1000_DEV_ID_PCH_LPTLP_I218_LM:
+ case E1000_DEV_ID_PCH_LPTLP_I218_V:
+ mac->type = e1000_pch_lpt;
+ break;
case E1000_DEV_ID_82575EB_COPPER:
case E1000_DEV_ID_82575EB_FIBER_SERDES:
case E1000_DEV_ID_82575GB_QUAD_COPPER:
- case E1000_DEV_ID_82575GB_QUAD_COPPER_PM:
mac->type = e1000_82575;
break;
case E1000_DEV_ID_82576:
@@ -320,11 +324,37 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82580_QUAD_FIBER:
case E1000_DEV_ID_DH89XXCC_SGMII:
case E1000_DEV_ID_DH89XXCC_SERDES:
+ case E1000_DEV_ID_DH89XXCC_BACKPLANE:
+ case E1000_DEV_ID_DH89XXCC_SFP:
mac->type = e1000_82580;
break;
+ case E1000_DEV_ID_I350_COPPER:
+ case E1000_DEV_ID_I350_FIBER:
+ case E1000_DEV_ID_I350_SERDES:
+ case E1000_DEV_ID_I350_SGMII:
+ case E1000_DEV_ID_I350_DA4:
+ mac->type = e1000_i350;
+ break;
+ case E1000_DEV_ID_I210_COPPER:
+ case E1000_DEV_ID_I210_COPPER_OEM1:
+ case E1000_DEV_ID_I210_COPPER_IT:
+ case E1000_DEV_ID_I210_FIBER:
+ case E1000_DEV_ID_I210_SERDES:
+ case E1000_DEV_ID_I210_SGMII:
+ mac->type = e1000_i210;
+ break;
+ case E1000_DEV_ID_I211_COPPER:
+ mac->type = e1000_i211;
+ break;
case E1000_DEV_ID_82576_VF:
+ case E1000_DEV_ID_82576_VF_HV:
mac->type = e1000_vfadapt;
break;
+ case E1000_DEV_ID_I350_VF:
+ case E1000_DEV_ID_I350_VF_HV:
+ mac->type = e1000_vfadapt_i350;
+ break;
+
default:
/* Should never have loaded on this device */
ret_val = -E1000_ERR_MAC_INIT;
@@ -338,10 +368,10 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
* e1000_setup_init_funcs - Initializes function pointers
* @hw: pointer to the HW structure
* @init_device: TRUE will initialize the rest of the function pointers
- * getting the device ready for use. FALSE will only set
- * MAC type and the function pointers for the other init
- * functions. Passing FALSE will not generate any hardware
- * reads or writes.
+ * getting the device ready for use. FALSE will only set
+ * MAC type and the function pointers for the other init
+ * functions. Passing FALSE will not generate any hardware
+ * reads or writes.
*
* This function must be called by a driver in order to use the rest
* of the 'shared' code files. Called by drivers only.
@@ -413,16 +443,25 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_ich10lan:
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
e1000_init_function_pointers_ich8lan(hw);
break;
case e1000_82575:
case e1000_82576:
case e1000_82580:
+ case e1000_i350:
e1000_init_function_pointers_82575(hw);
break;
+ case e1000_i210:
+ case e1000_i211:
+ e1000_init_function_pointers_i210(hw);
+ break;
case e1000_vfadapt:
e1000_init_function_pointers_vf(hw);
break;
+ case e1000_vfadapt_i350:
+ e1000_init_function_pointers_vf(hw);
+ break;
default:
DEBUGOUT("Hardware not supported\n");
ret_val = -E1000_ERR_CONFIG;
@@ -509,11 +548,11 @@ void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
* The caller must have a packed mc_addr_list of multicast addresses.
**/
void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
- u32 mc_addr_count)
+ u32 mc_addr_count)
{
if (hw->mac.ops.update_mc_addr_list)
hw->mac.ops.update_mc_addr_list(hw, mc_addr_list,
- mc_addr_count);
+ mc_addr_count);
}
/**
@@ -847,14 +886,10 @@ bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
* It also does alignment considerations to do the writes in most efficient
* way. Also fills up the sum of the buffer in *buffer parameter.
**/
-s32 e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer, u16 length,
- u16 offset, u8 *sum)
+s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
+ u16 offset, u8 *sum)
{
- if (hw->mac.ops.mng_host_if_write)
- return hw->mac.ops.mng_host_if_write(hw, buffer, length,
- offset, sum);
-
- return E1000_NOT_IMPLEMENTED;
+ return e1000_mng_host_if_write_generic(hw, buffer, length, offset, sum);
}
/**
@@ -865,12 +900,9 @@ s32 e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer, u16 length,
* Writes the command header after does the checksum calculation.
**/
s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
- struct e1000_host_mng_command_header *hdr)
+ struct e1000_host_mng_command_header *hdr)
{
- if (hw->mac.ops.mng_write_cmd_header)
- return hw->mac.ops.mng_write_cmd_header(hw, hdr);
-
- return E1000_NOT_IMPLEMENTED;
+ return e1000_mng_write_cmd_header_generic(hw, hdr);
}
/**
@@ -883,25 +915,22 @@ s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
* and also checks whether the previous command is completed. It busy waits
* in case of previous command is not completed.
**/
-s32 e1000_mng_enable_host_if(struct e1000_hw * hw)
+s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
{
- if (hw->mac.ops.mng_enable_host_if)
- return hw->mac.ops.mng_enable_host_if(hw);
-
- return E1000_NOT_IMPLEMENTED;
+ return e1000_mng_enable_host_if_generic(hw);
}
/**
- * e1000_wait_autoneg - Waits for autonegotiation completion
+ * e1000_set_obff_timer - Set Optimized Buffer Flush/Fill timer
* @hw: pointer to the HW structure
+ * @itr: u32 indicating itr value
*
- * Waits for autoneg to complete. Currently no func pointer exists and all
- * implementations are handled in the generic version of this function.
+ * Set the OBFF timer based on the given interrupt rate.
**/
-s32 e1000_wait_autoneg(struct e1000_hw *hw)
+s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr)
{
- if (hw->mac.ops.wait_autoneg)
- return hw->mac.ops.wait_autoneg(hw);
+ if (hw->mac.ops.set_obff_timer)
+ return hw->mac.ops.set_obff_timer(hw, itr);
return E1000_SUCCESS;
}
@@ -1179,21 +1208,6 @@ s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size)
}
/**
- * e1000_read_pba_num - Read device part number
- * @hw: pointer to the HW structure
- * @pba_num: pointer to device part number
- *
- * Reads the product board assembly (PBA) number from the EEPROM and stores
- * the value in pba_num.
- * Currently no func pointer exists and all implementations are handled in the
- * generic version of this function.
- **/
-s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
-{
- return e1000_read_pba_num_generic(hw, pba_num);
-}
-
-/**
* e1000_validate_nvm_checksum - Verifies NVM (EEPROM) checksum
* @hw: pointer to the HW structure
*
@@ -1283,7 +1297,7 @@ s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
* This is a function pointer entry point called by drivers.
**/
s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset,
- u8 data)
+ u8 data)
{
return e1000_write_8bit_ctrl_reg_generic(hw, reg, offset, data);
}
diff --git a/freebsd/sys/dev/e1000/e1000_api.h b/freebsd/sys/dev/e1000/e1000_api.h
index c28fc2de..3dc5a3fd 100644
--- a/freebsd/sys/dev/e1000/e1000_api.h
+++ b/freebsd/sys/dev/e1000/e1000_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -41,91 +41,89 @@
#include <rtems/bsd/local/e1000_hw.h>
#endif
-extern void e1000_init_function_pointers_82542(struct e1000_hw *hw);
-extern void e1000_init_function_pointers_82543(struct e1000_hw *hw);
-extern void e1000_init_function_pointers_82540(struct e1000_hw *hw);
-extern void e1000_init_function_pointers_82571(struct e1000_hw *hw);
-extern void e1000_init_function_pointers_82541(struct e1000_hw *hw);
-extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw);
-extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw);
-extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
-extern void e1000_rx_fifo_flush_82575(struct e1000_hw *hw);
-extern void e1000_init_function_pointers_vf(struct e1000_hw *hw);
-extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw);
-extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82542(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82543(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82540(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82571(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82541(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
+extern void e1000_rx_fifo_flush_82575(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_vf(struct e1000_hw *hw);
+extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw);
+extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw);
+extern void e1000_init_function_pointers_i210(struct e1000_hw *hw);
-s32 e1000_set_mac_type(struct e1000_hw *hw);
-s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device);
-s32 e1000_init_mac_params(struct e1000_hw *hw);
-s32 e1000_init_nvm_params(struct e1000_hw *hw);
-s32 e1000_init_phy_params(struct e1000_hw *hw);
-s32 e1000_init_mbx_params(struct e1000_hw *hw);
-s32 e1000_get_bus_info(struct e1000_hw *hw);
+s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr);
+s32 e1000_set_mac_type(struct e1000_hw *hw);
+s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device);
+s32 e1000_init_mac_params(struct e1000_hw *hw);
+s32 e1000_init_nvm_params(struct e1000_hw *hw);
+s32 e1000_init_phy_params(struct e1000_hw *hw);
+s32 e1000_init_mbx_params(struct e1000_hw *hw);
+s32 e1000_get_bus_info(struct e1000_hw *hw);
void e1000_clear_vfta(struct e1000_hw *hw);
void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
-s32 e1000_force_mac_fc(struct e1000_hw *hw);
-s32 e1000_check_for_link(struct e1000_hw *hw);
-s32 e1000_reset_hw(struct e1000_hw *hw);
-s32 e1000_init_hw(struct e1000_hw *hw);
-s32 e1000_setup_link(struct e1000_hw *hw);
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed,
- u16 *duplex);
-s32 e1000_disable_pcie_master(struct e1000_hw *hw);
+s32 e1000_force_mac_fc(struct e1000_hw *hw);
+s32 e1000_check_for_link(struct e1000_hw *hw);
+s32 e1000_reset_hw(struct e1000_hw *hw);
+s32 e1000_init_hw(struct e1000_hw *hw);
+s32 e1000_setup_link(struct e1000_hw *hw);
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex);
+s32 e1000_disable_pcie_master(struct e1000_hw *hw);
void e1000_config_collision_dist(struct e1000_hw *hw);
void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
-u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
-void e1000_update_mc_addr_list(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count);
-s32 e1000_setup_led(struct e1000_hw *hw);
-s32 e1000_cleanup_led(struct e1000_hw *hw);
-s32 e1000_check_reset_block(struct e1000_hw *hw);
-s32 e1000_blink_led(struct e1000_hw *hw);
-s32 e1000_led_on(struct e1000_hw *hw);
-s32 e1000_led_off(struct e1000_hw *hw);
+u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
+void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
+ u32 mc_addr_count);
+s32 e1000_setup_led(struct e1000_hw *hw);
+s32 e1000_cleanup_led(struct e1000_hw *hw);
+s32 e1000_check_reset_block(struct e1000_hw *hw);
+s32 e1000_blink_led(struct e1000_hw *hw);
+s32 e1000_led_on(struct e1000_hw *hw);
+s32 e1000_led_off(struct e1000_hw *hw);
s32 e1000_id_led_init(struct e1000_hw *hw);
void e1000_reset_adaptive(struct e1000_hw *hw);
void e1000_update_adaptive(struct e1000_hw *hw);
-s32 e1000_get_cable_length(struct e1000_hw *hw);
-s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
-s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data);
-s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data);
-s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
- u32 offset, u8 data);
-s32 e1000_get_phy_info(struct e1000_hw *hw);
+s32 e1000_get_cable_length(struct e1000_hw *hw);
+s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
+s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset,
+ u8 data);
+s32 e1000_get_phy_info(struct e1000_hw *hw);
void e1000_release_phy(struct e1000_hw *hw);
-s32 e1000_acquire_phy(struct e1000_hw *hw);
-s32 e1000_cfg_on_link_up(struct e1000_hw *hw);
-s32 e1000_phy_hw_reset(struct e1000_hw *hw);
-s32 e1000_phy_commit(struct e1000_hw *hw);
+s32 e1000_acquire_phy(struct e1000_hw *hw);
+s32 e1000_cfg_on_link_up(struct e1000_hw *hw);
+s32 e1000_phy_hw_reset(struct e1000_hw *hw);
+s32 e1000_phy_commit(struct e1000_hw *hw);
void e1000_power_up_phy(struct e1000_hw *hw);
void e1000_power_down_phy(struct e1000_hw *hw);
-s32 e1000_read_mac_addr(struct e1000_hw *hw);
-s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *part_num);
-s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num,
- u32 pba_num_size);
-s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size);
+s32 e1000_read_mac_addr(struct e1000_hw *hw);
+s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size);
+s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size);
void e1000_reload_nvm(struct e1000_hw *hw);
-s32 e1000_update_nvm_checksum(struct e1000_hw *hw);
-s32 e1000_validate_nvm_checksum(struct e1000_hw *hw);
-s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
-s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
-s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data);
-s32 e1000_wait_autoneg(struct e1000_hw *hw);
-s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
-s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
+s32 e1000_update_nvm_checksum(struct e1000_hw *hw);
+s32 e1000_validate_nvm_checksum(struct e1000_hw *hw);
+s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
+s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
bool e1000_check_mng_mode(struct e1000_hw *hw);
bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
-s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
-s32 e1000_mng_host_if_write(struct e1000_hw *hw,
- u8 *buffer, u16 length, u16 offset, u8 *sum);
-s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
- struct e1000_host_mng_command_header *hdr);
-s32 e1000_mng_write_dhcp_info(struct e1000_hw * hw,
- u8 *buffer, u16 length);
+s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
+s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
+ u16 offset, u8 *sum);
+s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
+ struct e1000_host_mng_command_header *hdr);
+s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length);
u32 e1000_translate_register_82542(u32 reg);
+
+
/*
* TBI_ACCEPT macro definition:
*
@@ -157,14 +155,17 @@ u32 e1000_translate_register_82542(u32 reg);
/* The carrier extension symbol, as received by the NIC. */
#define CARRIER_EXTENSION 0x0F
-#define TBI_ACCEPT(a, status, errors, length, last_byte, min_frame_size, max_frame_size) \
- (e1000_tbi_sbp_enabled_82543(a) && \
- (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
- ((last_byte) == CARRIER_EXTENSION) && \
- (((status) & E1000_RXD_STAT_VP) ? \
- (((length) > (min_frame_size - VLAN_TAG_SIZE)) && \
- ((length) <= (max_frame_size + 1))) : \
- (((length) > min_frame_size) && \
- ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1)))))
+#define TBI_ACCEPT(a, status, errors, length, last_byte, \
+ min_frame_size, max_frame_size) \
+ (e1000_tbi_sbp_enabled_82543(a) && \
+ (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
+ ((last_byte) == CARRIER_EXTENSION) && \
+ (((status) & E1000_RXD_STAT_VP) ? \
+ (((length) > (min_frame_size - VLAN_TAG_SIZE)) && \
+ ((length) <= (max_frame_size + 1))) : \
+ (((length) > min_frame_size) && \
+ ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1)))))
-#endif
+#define E1000_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define E1000_DIVIDE_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) /* ceil(a/b) */
+#endif /* _E1000_API_H_ */
diff --git a/freebsd/sys/dev/e1000/e1000_defines.h b/freebsd/sys/dev/e1000/e1000_defines.h
index 5d09ad92..48c04b01 100644
--- a/freebsd/sys/dev/e1000/e1000_defines.h
+++ b/freebsd/sys/dev/e1000/e1000_defines.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -41,820 +41,546 @@
/* Definitions for power management and wakeup registers */
/* Wake Up Control */
-#define E1000_WUC_APME 0x00000001 /* APM Enable */
-#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */
-#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
-#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */
-#define E1000_WUC_LSCWE 0x00000010 /* Link Status wake up enable */
-#define E1000_WUC_LSCWO 0x00000020 /* Link Status wake up override */
-#define E1000_WUC_SPM 0x80000000 /* Enable SPM */
-#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */
-#define E1000_WUC_FLX6_PHY 0x4000 /* Flexible Filter 6 Enable */
-#define E1000_WUC_FLX7_PHY 0x8000 /* Flexible Filter 7 Enable */
+#define E1000_WUC_APME 0x00000001 /* APM Enable */
+#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */
+#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */
/* Wake Up Filter Control */
-#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
-#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
-#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
-#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
-#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
-#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */
-#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
-#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
-#define E1000_WUFC_IGNORE_TCO_PHY 0x00000800 /* Ignore WakeOn TCO packets */
-#define E1000_WUFC_FLX0_PHY 0x00001000 /* Flexible Filter 0 Enable */
-#define E1000_WUFC_FLX1_PHY 0x00002000 /* Flexible Filter 1 Enable */
-#define E1000_WUFC_FLX2_PHY 0x00004000 /* Flexible Filter 2 Enable */
-#define E1000_WUFC_FLX3_PHY 0x00008000 /* Flexible Filter 3 Enable */
-#define E1000_WUFC_FLX4_PHY 0x00000200 /* Flexible Filter 4 Enable */
-#define E1000_WUFC_FLX5_PHY 0x00000400 /* Flexible Filter 5 Enable */
-#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */
-#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
-#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
-#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
-#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
-#define E1000_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */
-#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */
-#define E1000_WUFC_FLX6 0x00400000 /* Flexible Filter 6 Enable */
-#define E1000_WUFC_FLX7 0x00800000 /* Flexible Filter 7 Enable */
-#define E1000_WUFC_ALL_FILTERS_PHY_4 0x0000F0FF /*Mask for all wakeup filters*/
-#define E1000_WUFC_FLX_OFFSET_PHY 12 /* Offset to the Flexible Filters bits */
-#define E1000_WUFC_FLX_FILTERS_PHY_4 0x0000F000 /*Mask for 4 flexible filters*/
-#define E1000_WUFC_ALL_FILTERS_PHY_6 0x0000F6FF /*Mask for 6 wakeup filters */
-#define E1000_WUFC_FLX_FILTERS_PHY_6 0x0000F600 /*Mask for 6 flexible filters*/
-#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */
-#define E1000_WUFC_ALL_FILTERS_6 0x003F00FF /* Mask for all 6 wakeup filters*/
-#define E1000_WUFC_ALL_FILTERS_8 0x00FF00FF /* Mask for all 8 wakeup filters*/
-#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */
-#define E1000_WUFC_FLX_FILTERS 0x000F0000 /*Mask for the 4 flexible filters */
-#define E1000_WUFC_FLX_FILTERS_6 0x003F0000 /* Mask for 6 flexible filters */
-#define E1000_WUFC_FLX_FILTERS_8 0x00FF0000 /* Mask for 8 flexible filters */
-/*
- * For 82576 to utilize Extended filter masks in addition to
- * existing (filter) masks
- */
-#define E1000_WUFC_EXT_FLX_FILTERS 0x00300000 /* Ext. FLX filter mask */
+#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
+#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
+#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
+#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
+#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */
+#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
+#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
/* Wake Up Status */
-#define E1000_WUS_LNKC E1000_WUFC_LNKC
-#define E1000_WUS_MAG E1000_WUFC_MAG
-#define E1000_WUS_EX E1000_WUFC_EX
-#define E1000_WUS_MC E1000_WUFC_MC
-#define E1000_WUS_BC E1000_WUFC_BC
-#define E1000_WUS_ARP E1000_WUFC_ARP
-#define E1000_WUS_IPV4 E1000_WUFC_IPV4
-#define E1000_WUS_IPV6 E1000_WUFC_IPV6
-#define E1000_WUS_FLX0_PHY E1000_WUFC_FLX0_PHY
-#define E1000_WUS_FLX1_PHY E1000_WUFC_FLX1_PHY
-#define E1000_WUS_FLX2_PHY E1000_WUFC_FLX2_PHY
-#define E1000_WUS_FLX3_PHY E1000_WUFC_FLX3_PHY
-#define E1000_WUS_FLX_FILTERS_PHY_4 E1000_WUFC_FLX_FILTERS_PHY_4
-#define E1000_WUS_FLX0 E1000_WUFC_FLX0
-#define E1000_WUS_FLX1 E1000_WUFC_FLX1
-#define E1000_WUS_FLX2 E1000_WUFC_FLX2
-#define E1000_WUS_FLX3 E1000_WUFC_FLX3
-#define E1000_WUS_FLX4 E1000_WUFC_FLX4
-#define E1000_WUS_FLX5 E1000_WUFC_FLX5
-#define E1000_WUS_FLX6 E1000_WUFC_FLX6
-#define E1000_WUS_FLX7 E1000_WUFC_FLX7
-#define E1000_WUS_FLX4_PHY E1000_WUFC_FLX4_PHY
-#define E1000_WUS_FLX5_PHY E1000_WUFC_FLX5_PHY
-#define E1000_WUS_FLX6_PHY 0x0400
-#define E1000_WUS_FLX7_PHY 0x0800
-#define E1000_WUS_FLX_FILTERS E1000_WUFC_FLX_FILTERS
-#define E1000_WUS_FLX_FILTERS_6 E1000_WUFC_FLX_FILTERS_6
-#define E1000_WUS_FLX_FILTERS_8 E1000_WUFC_FLX_FILTERS_8
-#define E1000_WUS_FLX_FILTERS_PHY_6 E1000_WUFC_FLX_FILTERS_PHY_6
-
-/* Wake Up Packet Length */
-#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */
-
-/* Four Flexible Filters are supported */
-#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
-/* Six Flexible Filters are supported */
-#define E1000_FLEXIBLE_FILTER_COUNT_MAX_6 6
-/* Eight Flexible Filters are supported */
-#define E1000_FLEXIBLE_FILTER_COUNT_MAX_8 8
-/* Two Extended Flexible Filters are supported (82576) */
-#define E1000_EXT_FLEXIBLE_FILTER_COUNT_MAX 2
-#define E1000_FHFT_LENGTH_OFFSET 0xFC /* Length byte in FHFT */
-#define E1000_FHFT_LENGTH_MASK 0x0FF /* Length in lower byte */
-
-/* Each Flexible Filter is at most 128 (0x80) bytes in length */
-#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128
-
-#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
-#define E1000_FFLT_SIZE_6 E1000_FLEXIBLE_FILTER_COUNT_MAX_6
-#define E1000_FFLT_SIZE_8 E1000_FLEXIBLE_FILTER_COUNT_MAX_8
-#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
-#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+#define E1000_WUS_LNKC E1000_WUFC_LNKC
+#define E1000_WUS_MAG E1000_WUFC_MAG
+#define E1000_WUS_EX E1000_WUFC_EX
+#define E1000_WUS_MC E1000_WUFC_MC
+#define E1000_WUS_BC E1000_WUFC_BC
/* Extended Device Control */
-#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */
-#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */
-#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
-#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */
-#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */
-/* Reserved (bits 4,5) in >= 82575 */
-#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Definable Pin 4 */
-#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Definable Pin 5 */
-#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA
-#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Definable Pin 6 */
-#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */
+#define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */
+#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* SW Definable Pin 4 data */
+#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* SW Definable Pin 6 data */
+#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* SW Definable Pin 3 data */
/* SDP 4/5 (bits 8,9) are reserved in >= 82575 */
-#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */
-#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */
-#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */
-#define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */
-#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */
-#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
-#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */
+#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */
+#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */
+#define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */
+#define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */
+#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
/* Physical Func Reset Done Indication */
-#define E1000_CTRL_EXT_PFRSTD 0x00004000
-#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
-#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
-#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
-#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_82580_MASK 0x01C00000 /*82580 bit 24:22*/
-#define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX 0x00400000
-#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
-#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000
-#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_PCIX_SERDES 0x00800000
-#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000
-#define E1000_CTRL_EXT_EIAME 0x01000000
-#define E1000_CTRL_EXT_IRCA 0x00000001
-#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000
-#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000
-#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
-#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
-#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
-#define E1000_CTRL_EXT_CANC 0x04000000 /* Int delay cancellation */
-#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
-/* IAME enable bit (27) was removed in >= 82575 */
-#define E1000_CTRL_EXT_IAME 0x08000000 /* Int acknowledge Auto-mask */
-#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error
- * detection enabled */
-#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity
- * error detection enable */
-#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000
-#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */
-#define E1000_CTRL_EXT_LSECCK 0x00001000
-#define E1000_CTRL_EXT_PHYPDEN 0x00100000
-#define E1000_I2CCMD_REG_ADDR_SHIFT 16
-#define E1000_I2CCMD_REG_ADDR 0x00FF0000
-#define E1000_I2CCMD_PHY_ADDR_SHIFT 24
-#define E1000_I2CCMD_PHY_ADDR 0x07000000
-#define E1000_I2CCMD_OPCODE_READ 0x08000000
-#define E1000_I2CCMD_OPCODE_WRITE 0x00000000
-#define E1000_I2CCMD_RESET 0x10000000
-#define E1000_I2CCMD_READY 0x20000000
-#define E1000_I2CCMD_INTERRUPT_ENA 0x40000000
-#define E1000_I2CCMD_ERROR 0x80000000
-#define E1000_MAX_SGMII_PHY_REG_ADDR 255
-#define E1000_I2CCMD_PHY_TIMEOUT 200
-#define E1000_IVAR_VALID 0x80
-#define E1000_GPIE_NSICR 0x00000001
-#define E1000_GPIE_MSIX_MODE 0x00000010
-#define E1000_GPIE_EIAME 0x40000000
-#define E1000_GPIE_PBA 0x80000000
+#define E1000_CTRL_EXT_PFRSTD 0x00004000
+#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
+#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clk Gating */
+#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
+/* Offset of the link mode field in Ctrl Ext register */
+#define E1000_CTRL_EXT_LINK_MODE_OFFSET 22
+#define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX 0x00400000
+#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000
+#define E1000_CTRL_EXT_EIAME 0x01000000
+#define E1000_CTRL_EXT_IRCA 0x00000001
+#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */
+#define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */
+#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */
+#define E1000_CTRL_EXT_LSECCK 0x00001000
+#define E1000_CTRL_EXT_PHYPDEN 0x00100000
+#define E1000_I2CCMD_REG_ADDR_SHIFT 16
+#define E1000_I2CCMD_PHY_ADDR_SHIFT 24
+#define E1000_I2CCMD_OPCODE_READ 0x08000000
+#define E1000_I2CCMD_OPCODE_WRITE 0x00000000
+#define E1000_I2CCMD_READY 0x20000000
+#define E1000_I2CCMD_ERROR 0x80000000
+#define E1000_I2CCMD_SFP_DATA_ADDR(a) (0x0000 + (a))
+#define E1000_I2CCMD_SFP_DIAG_ADDR(a) (0x0100 + (a))
+#define E1000_MAX_SGMII_PHY_REG_ADDR 255
+#define E1000_I2CCMD_PHY_TIMEOUT 200
+#define E1000_IVAR_VALID 0x80
+#define E1000_GPIE_NSICR 0x00000001
+#define E1000_GPIE_MSIX_MODE 0x00000010
+#define E1000_GPIE_EIAME 0x40000000
+#define E1000_GPIE_PBA 0x80000000
/* Receive Descriptor bit definitions */
-#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
-#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
-#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
-#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
-#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
-#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
-#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
-#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */
-#define E1000_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */
-#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */
-#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */
-#define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */
-#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */
-#define E1000_RXD_ERR_CE 0x01 /* CRC Error */
-#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
-#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */
-#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */
-#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */
-#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */
-#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
-#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
-#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */
-#define E1000_RXD_SPC_PRI_SHIFT 13
-#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */
-#define E1000_RXD_SPC_CFI_SHIFT 12
-
-#define E1000_RXDEXT_STATERR_CE 0x01000000
-#define E1000_RXDEXT_STATERR_SE 0x02000000
-#define E1000_RXDEXT_STATERR_SEQ 0x04000000
-#define E1000_RXDEXT_STATERR_CXE 0x10000000
-#define E1000_RXDEXT_STATERR_TCPE 0x20000000
-#define E1000_RXDEXT_STATERR_IPE 0x40000000
-#define E1000_RXDEXT_STATERR_RXE 0x80000000
-
-#define E1000_RXDEXT_LSECH 0x01000000
-#define E1000_RXDEXT_LSECE_MASK 0x60000000
-#define E1000_RXDEXT_LSECE_NO_ERROR 0x00000000
-#define E1000_RXDEXT_LSECE_NO_SA_MATCH 0x20000000
-#define E1000_RXDEXT_LSECE_REPLAY_DETECT 0x40000000
-#define E1000_RXDEXT_LSECE_BAD_SIG 0x60000000
+#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
+#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
+#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
+#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
+#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
+#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
+#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
+#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */
+#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */
+#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */
+#define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */
+#define E1000_RXD_ERR_CE 0x01 /* CRC Error */
+#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
+#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */
+#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */
+#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */
+#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */
+#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
+#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
+
+#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */
+#define E1000_RXDEXT_STATERR_LB 0x00040000
+#define E1000_RXDEXT_STATERR_CE 0x01000000
+#define E1000_RXDEXT_STATERR_SE 0x02000000
+#define E1000_RXDEXT_STATERR_SEQ 0x04000000
+#define E1000_RXDEXT_STATERR_CXE 0x10000000
+#define E1000_RXDEXT_STATERR_TCPE 0x20000000
+#define E1000_RXDEXT_STATERR_IPE 0x40000000
+#define E1000_RXDEXT_STATERR_RXE 0x80000000
/* mask to determine if packets should be dropped due to frame errors */
#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
- E1000_RXD_ERR_CE | \
- E1000_RXD_ERR_SE | \
- E1000_RXD_ERR_SEQ | \
- E1000_RXD_ERR_CXE | \
- E1000_RXD_ERR_RXE)
+ E1000_RXD_ERR_CE | \
+ E1000_RXD_ERR_SE | \
+ E1000_RXD_ERR_SEQ | \
+ E1000_RXD_ERR_CXE | \
+ E1000_RXD_ERR_RXE)
/* Same mask, but for extended and packet split descriptors */
#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
- E1000_RXDEXT_STATERR_CE | \
- E1000_RXDEXT_STATERR_SE | \
- E1000_RXDEXT_STATERR_SEQ | \
- E1000_RXDEXT_STATERR_CXE | \
- E1000_RXDEXT_STATERR_RXE)
-
-#define E1000_MRQC_ENABLE_MASK 0x00000007
-#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001
-#define E1000_MRQC_ENABLE_RSS_INT 0x00000004
-#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
-#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
-#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
-#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
-#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
-#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
-#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
-
-#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000
-#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF
+ E1000_RXDEXT_STATERR_CE | \
+ E1000_RXDEXT_STATERR_SE | \
+ E1000_RXDEXT_STATERR_SEQ | \
+ E1000_RXDEXT_STATERR_CXE | \
+ E1000_RXDEXT_STATERR_RXE)
+
+#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
+#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
+#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
+
+#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000
/* Management Control */
-#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
-#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
-#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */
-#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */
-#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */
-#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */
-#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */
-#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */
-#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
-/* Enable Neighbor Discovery Filtering */
-#define E1000_MANC_NEIGHBOR_EN 0x00004000
-#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */
-#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */
-#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
-#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
-#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */
-#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
+#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
+#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
+#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
+#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
+#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
/* Enable MAC address filtering */
-#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000
+#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000
/* Enable MNG packets to host memory */
-#define E1000_MANC_EN_MNG2HOST 0x00200000
-/* Enable IP address filtering */
-#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000
-#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */
-#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */
-#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */
-#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */
-#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */
-#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */
-#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */
-#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */
-
-#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */
-#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */
-
-#define E1000_MANC2H_PORT_623 0x00000020 /* Port 0x26f */
-#define E1000_MANC2H_PORT_664 0x00000040 /* Port 0x298 */
-#define E1000_MDEF_PORT_623 0x00000800 /* Port 0x26f */
-#define E1000_MDEF_PORT_664 0x00000400 /* Port 0x298 */
+#define E1000_MANC_EN_MNG2HOST 0x00200000
+
+#define E1000_MANC2H_PORT_623 0x00000020 /* Port 0x26f */
+#define E1000_MANC2H_PORT_664 0x00000040 /* Port 0x298 */
+#define E1000_MDEF_PORT_623 0x00000800 /* Port 0x26f */
+#define E1000_MDEF_PORT_664 0x00000400 /* Port 0x298 */
/* Receive Control */
-#define E1000_RCTL_RST 0x00000001 /* Software reset */
-#define E1000_RCTL_EN 0x00000002 /* enable */
-#define E1000_RCTL_SBP 0x00000004 /* store bad packet */
-#define E1000_RCTL_UPE 0x00000008 /* unicast promisc enable */
-#define E1000_RCTL_MPE 0x00000010 /* multicast promisc enable */
-#define E1000_RCTL_LPE 0x00000020 /* long packet enable */
-#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */
-#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
-#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */
-#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
-#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */
-#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
-#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min thresh size */
-#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min thresh size */
-#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min thresh size */
-#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
-#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */
-#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */
-#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */
-#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */
-#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */
-#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
+#define E1000_RCTL_RST 0x00000001 /* Software reset */
+#define E1000_RCTL_EN 0x00000002 /* enable */
+#define E1000_RCTL_SBP 0x00000004 /* store bad packet */
+#define E1000_RCTL_UPE 0x00000008 /* unicast promisc enable */
+#define E1000_RCTL_MPE 0x00000010 /* multicast promisc enable */
+#define E1000_RCTL_LPE 0x00000020 /* long packet enable */
+#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */
+#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
+#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
+#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
+#define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */
+#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
+#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */
+#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
-#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
-#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
-#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
-#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
+#define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024 0x00010000 /* Rx buffer size 1024 */
+#define E1000_RCTL_SZ_512 0x00020000 /* Rx buffer size 512 */
+#define E1000_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */
/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
-#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
-#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
-#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
-#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
-#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
-#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
-#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */
-#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
-#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
-#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
-#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */
-#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */
-
-/*
- * Use byte values for the following shift parameters
+#define E1000_RCTL_SZ_16384 0x00010000 /* Rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192 0x00020000 /* Rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096 0x00030000 /* Rx buffer size 4096 */
+#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
+#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
+#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
+#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */
+#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
+#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
+#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
+
+/* Use byte values for the following shift parameters
* Usage:
* psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
- * E1000_PSRCTL_BSIZE0_MASK) |
- * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
- * E1000_PSRCTL_BSIZE1_MASK) |
- * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
- * E1000_PSRCTL_BSIZE2_MASK) |
- * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
- * E1000_PSRCTL_BSIZE3_MASK))
+ * E1000_PSRCTL_BSIZE0_MASK) |
+ * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
+ * E1000_PSRCTL_BSIZE1_MASK) |
+ * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
+ * E1000_PSRCTL_BSIZE2_MASK) |
+ * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
+ * E1000_PSRCTL_BSIZE3_MASK))
* where value0 = [128..16256], default=256
* value1 = [1024..64512], default=4096
* value2 = [0..64512], default=4096
* value3 = [0..64512], default=0
*/
-#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F
-#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00
-#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000
-#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000
+#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F
+#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00
+#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000
+#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000
-#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */
-#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */
-#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */
-#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */
+#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */
+#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */
+#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */
+#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */
/* SWFW_SYNC Definitions */
-#define E1000_SWFW_EEP_SM 0x01
-#define E1000_SWFW_PHY0_SM 0x02
-#define E1000_SWFW_PHY1_SM 0x04
-#define E1000_SWFW_CSR_SM 0x08
-#define E1000_SWFW_PHY2_SM 0x20
-#define E1000_SWFW_PHY3_SM 0x40
-
-/* FACTPS Definitions */
-#define E1000_FACTPS_LFS 0x40000000 /* LAN Function Select */
+#define E1000_SWFW_EEP_SM 0x01
+#define E1000_SWFW_PHY0_SM 0x02
+#define E1000_SWFW_PHY1_SM 0x04
+#define E1000_SWFW_CSR_SM 0x08
+#define E1000_SWFW_PHY2_SM 0x20
+#define E1000_SWFW_PHY3_SM 0x40
+#define E1000_SWFW_SW_MNG_SM 0x400
+
/* Device Control */
-#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
-#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */
-#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */
+#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
+#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */
#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master reqs */
-#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
-#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */
-#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */
-#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */
-#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
-#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */
-#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */
-#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */
-#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */
-#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */
-#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
-#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
-#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
-#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
-#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock
- * indication in SDP[0] */
-#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through
- * PHYRST_N pin */
-#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external
- * LINK_0 and LINK_1 pins */
-#define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */
-#define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */
-#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
-#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
-#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
-#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */
-#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */
-#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
-#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */
-#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */
-#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */
-#define E1000_CTRL_RST 0x04000000 /* Global reset */
-#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
-#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
-#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */
-#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
-#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
-#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to ME */
-#define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */
-
-/*
- * Bit definitions for the Management Data IO (MDIO) and Management Data
- * Clock (MDC) pins in the Device Control Register.
- */
-#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0
-#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0
-#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2
-#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2
-#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3
-#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3
-#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR
-#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA
-
-#define E1000_CONNSW_ENRGSRC 0x4
-#define E1000_PCS_CFG_PCS_EN 8
-#define E1000_PCS_LCTL_FLV_LINK_UP 1
-#define E1000_PCS_LCTL_FSV_10 0
-#define E1000_PCS_LCTL_FSV_100 2
-#define E1000_PCS_LCTL_FSV_1000 4
-#define E1000_PCS_LCTL_FDV_FULL 8
-#define E1000_PCS_LCTL_FSD 0x10
-#define E1000_PCS_LCTL_FORCE_LINK 0x20
-#define E1000_PCS_LCTL_LOW_LINK_LATCH 0x40
-#define E1000_PCS_LCTL_FORCE_FCTRL 0x80
-#define E1000_PCS_LCTL_AN_ENABLE 0x10000
-#define E1000_PCS_LCTL_AN_RESTART 0x20000
-#define E1000_PCS_LCTL_AN_TIMEOUT 0x40000
-#define E1000_PCS_LCTL_AN_SGMII_BYPASS 0x80000
-#define E1000_PCS_LCTL_AN_SGMII_TRIGGER 0x100000
-#define E1000_PCS_LCTL_FAST_LINK_TIMER 0x1000000
-#define E1000_PCS_LCTL_LINK_OK_FIX 0x2000000
-#define E1000_PCS_LCTL_CRS_ON_NI 0x4000000
-#define E1000_ENABLE_SERDES_LOOPBACK 0x0410
-
-#define E1000_PCS_LSTS_LINK_OK 1
-#define E1000_PCS_LSTS_SPEED_10 0
-#define E1000_PCS_LSTS_SPEED_100 2
-#define E1000_PCS_LSTS_SPEED_1000 4
-#define E1000_PCS_LSTS_DUPLEX_FULL 8
-#define E1000_PCS_LSTS_SYNK_OK 0x10
-#define E1000_PCS_LSTS_AN_COMPLETE 0x10000
-#define E1000_PCS_LSTS_AN_PAGE_RX 0x20000
-#define E1000_PCS_LSTS_AN_TIMED_OUT 0x40000
-#define E1000_PCS_LSTS_AN_REMOTE_FAULT 0x80000
-#define E1000_PCS_LSTS_AN_ERROR_RWS 0x100000
+#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
+#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */
+#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
+#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */
+#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */
+#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */
+#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */
+#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */
+#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
+#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
+#define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */
+#define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */
+#define E1000_CTRL_MEHE 0x00080000 /* Memory Error Handling Enable */
+#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
+#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
+#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
+#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */
+#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 /* PHY PM enable */
+#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */
+#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
+#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */
+#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */
+#define E1000_CTRL_RST 0x04000000 /* Global reset */
+#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
+#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
+#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
+#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
+#define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */
+
+#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2
+#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2
+#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3
+#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3
+
+#define E1000_CONNSW_ENRGSRC 0x4
+#define E1000_CONNSW_PHYSD 0x400
+#define E1000_CONNSW_SERDESD 0x200
+#define E1000_PCS_CFG_PCS_EN 8
+#define E1000_PCS_LCTL_FLV_LINK_UP 1
+#define E1000_PCS_LCTL_FSV_10 0
+#define E1000_PCS_LCTL_FSV_100 2
+#define E1000_PCS_LCTL_FSV_1000 4
+#define E1000_PCS_LCTL_FDV_FULL 8
+#define E1000_PCS_LCTL_FSD 0x10
+#define E1000_PCS_LCTL_FORCE_LINK 0x20
+#define E1000_PCS_LCTL_FORCE_FCTRL 0x80
+#define E1000_PCS_LCTL_AN_ENABLE 0x10000
+#define E1000_PCS_LCTL_AN_RESTART 0x20000
+#define E1000_PCS_LCTL_AN_TIMEOUT 0x40000
+#define E1000_ENABLE_SERDES_LOOPBACK 0x0410
+
+#define E1000_PCS_LSTS_LINK_OK 1
+#define E1000_PCS_LSTS_SPEED_100 2
+#define E1000_PCS_LSTS_SPEED_1000 4
+#define E1000_PCS_LSTS_DUPLEX_FULL 8
+#define E1000_PCS_LSTS_SYNK_OK 0x10
+#define E1000_PCS_LSTS_AN_COMPLETE 0x10000
/* Device Status */
-#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
-#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
-#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
-#define E1000_STATUS_FUNC_SHIFT 2
-#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */
-#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */
-#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
-#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */
-#define E1000_STATUS_SPEED_MASK 0x000000C0
-#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
-#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
-#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
-#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */
-#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */
-#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */
-#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state.
- * Clear on write '0'. */
-#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */
-#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */
-#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
-#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
-#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */
-#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */
-#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */
-#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */
-#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */
-#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */
-#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution
- * disabled */
-#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */
-#define E1000_STATUS_FUSE_8 0x04000000
-#define E1000_STATUS_FUSE_9 0x08000000
-#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */
-#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */
+#define E1000_STATUS_FD 0x00000001 /* Duplex 0=half 1=full */
+#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
+#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
+#define E1000_STATUS_FUNC_SHIFT 2
+#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */
+#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
+#define E1000_STATUS_SPEED_MASK 0x000000C0
+#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
+#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
+#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
+#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Compltn by NVM */
+#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */
+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */
+#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
+#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
+#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */
+#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */
/* Constants used to interpret the masked PCI-X bus speed. */
-#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */
-#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */
-#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /*PCI-X bus speed 100-133 MHz*/
+#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus spd 50-66MHz */
+#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus spd 66-100MHz */
+#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus spd 100-133MHz*/
-#define SPEED_10 10
-#define SPEED_100 100
-#define SPEED_1000 1000
-#define HALF_DUPLEX 1
-#define FULL_DUPLEX 2
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
-#define PHY_FORCE_TIME 20
+#define PHY_FORCE_TIME 20
-#define ADVERTISE_10_HALF 0x0001
-#define ADVERTISE_10_FULL 0x0002
-#define ADVERTISE_100_HALF 0x0004
-#define ADVERTISE_100_FULL 0x0008
-#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
-#define ADVERTISE_1000_FULL 0x0020
+#define ADVERTISE_10_HALF 0x0001
+#define ADVERTISE_10_FULL 0x0002
+#define ADVERTISE_100_HALF 0x0004
+#define ADVERTISE_100_FULL 0x0008
+#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL 0x0020
/* 1000/H is not supported, nor spec-compliant. */
-#define E1000_ALL_SPEED_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
- ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
- ADVERTISE_1000_FULL)
-#define E1000_ALL_NOT_GIG (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
- ADVERTISE_100_HALF | ADVERTISE_100_FULL)
-#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL)
-#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL)
-#define E1000_ALL_FULL_DUPLEX (ADVERTISE_10_FULL | ADVERTISE_100_FULL | \
- ADVERTISE_1000_FULL)
-#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF)
-
-#define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX
+#define E1000_ALL_SPEED_DUPLEX ( \
+ ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
+ ADVERTISE_100_FULL | ADVERTISE_1000_FULL)
+#define E1000_ALL_NOT_GIG ( \
+ ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
+ ADVERTISE_100_FULL)
+#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL)
+#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL)
+#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF)
+
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX
/* LED Control */
-#define E1000_PHY_LED0_MODE_MASK 0x00000007
-#define E1000_PHY_LED0_IVRT 0x00000008
-#define E1000_PHY_LED0_BLINK 0x00000010
-#define E1000_PHY_LED0_MASK 0x0000001F
-
-#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F
-#define E1000_LEDCTL_LED0_MODE_SHIFT 0
-#define E1000_LEDCTL_LED0_BLINK_RATE 0x00000020
-#define E1000_LEDCTL_LED0_IVRT 0x00000040
-#define E1000_LEDCTL_LED0_BLINK 0x00000080
-#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00
-#define E1000_LEDCTL_LED1_MODE_SHIFT 8
-#define E1000_LEDCTL_LED1_BLINK_RATE 0x00002000
-#define E1000_LEDCTL_LED1_IVRT 0x00004000
-#define E1000_LEDCTL_LED1_BLINK 0x00008000
-#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000
-#define E1000_LEDCTL_LED2_MODE_SHIFT 16
-#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000
-#define E1000_LEDCTL_LED2_IVRT 0x00400000
-#define E1000_LEDCTL_LED2_BLINK 0x00800000
-#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000
-#define E1000_LEDCTL_LED3_MODE_SHIFT 24
-#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000
-#define E1000_LEDCTL_LED3_IVRT 0x40000000
-#define E1000_LEDCTL_LED3_BLINK 0x80000000
-
-#define E1000_LEDCTL_MODE_LINK_10_1000 0x0
-#define E1000_LEDCTL_MODE_LINK_100_1000 0x1
-#define E1000_LEDCTL_MODE_LINK_UP 0x2
-#define E1000_LEDCTL_MODE_ACTIVITY 0x3
-#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4
-#define E1000_LEDCTL_MODE_LINK_10 0x5
-#define E1000_LEDCTL_MODE_LINK_100 0x6
-#define E1000_LEDCTL_MODE_LINK_1000 0x7
-#define E1000_LEDCTL_MODE_PCIX_MODE 0x8
-#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9
-#define E1000_LEDCTL_MODE_COLLISION 0xA
-#define E1000_LEDCTL_MODE_BUS_SPEED 0xB
-#define E1000_LEDCTL_MODE_BUS_SIZE 0xC
-#define E1000_LEDCTL_MODE_PAUSED 0xD
-#define E1000_LEDCTL_MODE_LED_ON 0xE
-#define E1000_LEDCTL_MODE_LED_OFF 0xF
+#define E1000_PHY_LED0_MODE_MASK 0x00000007
+#define E1000_PHY_LED0_IVRT 0x00000008
+#define E1000_PHY_LED0_MASK 0x0000001F
+
+#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F
+#define E1000_LEDCTL_LED0_MODE_SHIFT 0
+#define E1000_LEDCTL_LED0_IVRT 0x00000040
+#define E1000_LEDCTL_LED0_BLINK 0x00000080
+
+#define E1000_LEDCTL_MODE_LINK_UP 0x2
+#define E1000_LEDCTL_MODE_LED_ON 0xE
+#define E1000_LEDCTL_MODE_LED_OFF 0xF
/* Transmit Descriptor bit definitions */
-#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */
-#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */
-#define E1000_TXD_POPTS_SHIFT 8 /* POPTS shift */
-#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
-#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
-#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */
-#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
-#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */
-#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */
-#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */
-#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */
-#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
-#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */
-#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */
-#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */
-#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */
-#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */
-#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */
-#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */
-#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
-#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
-/* Extended desc bits for Linksec and timesync */
-#define E1000_TXD_CMD_LINKSEC 0x10000000 /* Apply LinkSec on packet */
-#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
+#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */
+#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */
+#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
+#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
+#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */
+#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */
+#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */
+#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */
+#define E1000_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */
+#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
+#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */
+#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */
+#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */
+#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */
+#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */
+#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */
+#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */
+#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
+#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
+#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
/* Transmit Control */
-#define E1000_TCTL_RST 0x00000001 /* software reset */
-#define E1000_TCTL_EN 0x00000002 /* enable tx */
-#define E1000_TCTL_BCE 0x00000004 /* busy check enable */
-#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
-#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
-#define E1000_TCTL_COLD 0x003ff000 /* collision distance */
-#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */
-#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */
-#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
-#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */
-#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
+#define E1000_TCTL_EN 0x00000002 /* enable Tx */
+#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
+#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
+#define E1000_TCTL_COLD 0x003ff000 /* collision distance */
+#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
+#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
/* Transmit Arbitration Count */
-#define E1000_TARC0_ENABLE 0x00000400 /* Enable Tx Queue 0 */
+#define E1000_TARC0_ENABLE 0x00000400 /* Enable Tx Queue 0 */
/* SerDes Control */
-#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
+#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
+#define E1000_SCTL_ENABLE_SERDES_LOOPBACK 0x0410
/* Receive Checksum Control */
-#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */
-#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */
-#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
-#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */
-#define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
-#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
-#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
+#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */
+#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
+#define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
+#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
+#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
/* Header split receive */
-#define E1000_RFCTL_ISCSI_DIS 0x00000001
-#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E
-#define E1000_RFCTL_ISCSI_DWC_SHIFT 1
-#define E1000_RFCTL_NFSW_DIS 0x00000040
-#define E1000_RFCTL_NFSR_DIS 0x00000080
-#define E1000_RFCTL_NFS_VER_MASK 0x00000300
-#define E1000_RFCTL_NFS_VER_SHIFT 8
-#define E1000_RFCTL_IPV6_DIS 0x00000400
-#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800
-#define E1000_RFCTL_ACK_DIS 0x00001000
-#define E1000_RFCTL_ACKD_DIS 0x00002000
-#define E1000_RFCTL_IPFRSP_DIS 0x00004000
-#define E1000_RFCTL_EXTEN 0x00008000
-#define E1000_RFCTL_IPV6_EX_DIS 0x00010000
-#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
-#define E1000_RFCTL_LEF 0x00040000
+#define E1000_RFCTL_NFSW_DIS 0x00000040
+#define E1000_RFCTL_NFSR_DIS 0x00000080
+#define E1000_RFCTL_ACK_DIS 0x00001000
+#define E1000_RFCTL_EXTEN 0x00008000
+#define E1000_RFCTL_IPV6_EX_DIS 0x00010000
+#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
+#define E1000_RFCTL_LEF 0x00040000
/* Collision related configuration parameters */
-#define E1000_COLLISION_THRESHOLD 15
-#define E1000_CT_SHIFT 4
-#define E1000_COLLISION_DISTANCE 63
-#define E1000_COLD_SHIFT 12
+#define E1000_COLLISION_THRESHOLD 15
+#define E1000_CT_SHIFT 4
+#define E1000_COLLISION_DISTANCE 63
+#define E1000_COLD_SHIFT 12
/* Default values for the transmit IPG register */
-#define DEFAULT_82542_TIPG_IPGT 10
-#define DEFAULT_82543_TIPG_IPGT_FIBER 9
-#define DEFAULT_82543_TIPG_IPGT_COPPER 8
+#define DEFAULT_82542_TIPG_IPGT 10
+#define DEFAULT_82543_TIPG_IPGT_FIBER 9
+#define DEFAULT_82543_TIPG_IPGT_COPPER 8
-#define E1000_TIPG_IPGT_MASK 0x000003FF
-#define E1000_TIPG_IPGR1_MASK 0x000FFC00
-#define E1000_TIPG_IPGR2_MASK 0x3FF00000
+#define E1000_TIPG_IPGT_MASK 0x000003FF
-#define DEFAULT_82542_TIPG_IPGR1 2
-#define DEFAULT_82543_TIPG_IPGR1 8
-#define E1000_TIPG_IPGR1_SHIFT 10
+#define DEFAULT_82542_TIPG_IPGR1 2
+#define DEFAULT_82543_TIPG_IPGR1 8
+#define E1000_TIPG_IPGR1_SHIFT 10
-#define DEFAULT_82542_TIPG_IPGR2 10
-#define DEFAULT_82543_TIPG_IPGR2 6
-#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
-#define E1000_TIPG_IPGR2_SHIFT 20
+#define DEFAULT_82542_TIPG_IPGR2 10
+#define DEFAULT_82543_TIPG_IPGR2 6
+#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
+#define E1000_TIPG_IPGR2_SHIFT 20
/* Ethertype field values */
-#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */
+#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */
-#define ETHERNET_FCS_SIZE 4
-#define MAX_JUMBO_FRAME_SIZE 0x3F00
+#define ETHERNET_FCS_SIZE 4
+#define MAX_JUMBO_FRAME_SIZE 0x3F00
/* Extended Configuration Control and Size */
-#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
-#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
-#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
-#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
-#define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080
-#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000
-#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16
-#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000
-#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16
-
-#define E1000_PHY_CTRL_SPD_EN 0x00000001
-#define E1000_PHY_CTRL_D0A_LPLU 0x00000002
-#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004
-#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008
-#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040
-
-#define E1000_KABGTXD_BGSQLBIAS 0x00050000
+#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
+#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
+#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
+#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
+#define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080
+#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000
+#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16
+
+#define E1000_PHY_CTRL_D0A_LPLU 0x00000002
+#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004
+#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008
+#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040
+
+#define E1000_KABGTXD_BGSQLBIAS 0x00050000
+
+/* Low Power IDLE Control */
+#define E1000_LPIC_LPIET_SHIFT 24 /* Low Power Idle Entry Time */
/* PBA constants */
-#define E1000_PBA_6K 0x0006 /* 6KB */
-#define E1000_PBA_8K 0x0008 /* 8KB */
-#define E1000_PBA_10K 0x000A /* 10KB */
-#define E1000_PBA_12K 0x000C /* 12KB */
-#define E1000_PBA_14K 0x000E /* 14KB */
-#define E1000_PBA_16K 0x0010 /* 16KB */
-#define E1000_PBA_18K 0x0012
-#define E1000_PBA_20K 0x0014
-#define E1000_PBA_22K 0x0016
-#define E1000_PBA_24K 0x0018
-#define E1000_PBA_26K 0x001A
-#define E1000_PBA_30K 0x001E
-#define E1000_PBA_32K 0x0020
-#define E1000_PBA_34K 0x0022
-#define E1000_PBA_35K 0x0023
-#define E1000_PBA_38K 0x0026
-#define E1000_PBA_40K 0x0028
-#define E1000_PBA_48K 0x0030 /* 48KB */
-#define E1000_PBA_64K 0x0040 /* 64KB */
-
-#define E1000_PBS_16K E1000_PBA_16K
-#define E1000_PBS_24K E1000_PBA_24K
-
-#define IFS_MAX 80
-#define IFS_MIN 40
-#define IFS_RATIO 4
-#define IFS_STEP 10
-#define MIN_NUM_XMITS 1000
+#define E1000_PBA_8K 0x0008 /* 8KB */
+#define E1000_PBA_10K 0x000A /* 10KB */
+#define E1000_PBA_12K 0x000C /* 12KB */
+#define E1000_PBA_14K 0x000E /* 14KB */
+#define E1000_PBA_16K 0x0010 /* 16KB */
+#define E1000_PBA_18K 0x0012
+#define E1000_PBA_20K 0x0014
+#define E1000_PBA_22K 0x0016
+#define E1000_PBA_24K 0x0018
+#define E1000_PBA_26K 0x001A
+#define E1000_PBA_30K 0x001E
+#define E1000_PBA_32K 0x0020
+#define E1000_PBA_34K 0x0022
+#define E1000_PBA_35K 0x0023
+#define E1000_PBA_38K 0x0026
+#define E1000_PBA_40K 0x0028
+#define E1000_PBA_48K 0x0030 /* 48KB */
+#define E1000_PBA_64K 0x0040 /* 64KB */
+
+#define E1000_PBA_RXA_MASK 0xFFFF
+
+#define E1000_PBS_16K E1000_PBA_16K
+
+/* Uncorrectable/correctable ECC Error counts and enable bits */
+#define E1000_PBECCSTS_CORR_ERR_CNT_MASK 0x000000FF
+#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000FF00
+#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8
+#define E1000_PBECCSTS_ECC_ENABLE 0x00010000
+
+#define IFS_MAX 80
+#define IFS_MIN 40
+#define IFS_RATIO 4
+#define IFS_STEP 10
+#define MIN_NUM_XMITS 1000
/* SW Semaphore Register */
-#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
-#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
-#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */
-#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
+#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
+#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
+#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
-#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */
+#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */
/* Interrupt Cause Read */
-#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
-#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
-#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
-#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
-#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
-#define E1000_ICR_RXO 0x00000040 /* rx overrun */
-#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
-#define E1000_ICR_VMMB 0x00000100 /* VM MB event */
-#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */
-#define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */
-#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */
-#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */
-#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */
-#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
-#define E1000_ICR_TXD_LOW 0x00008000
-#define E1000_ICR_SRPD 0x00010000
-#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */
-#define E1000_ICR_MNG 0x00040000 /* Manageability event */
-#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */
-#define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */
-#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver
- * should claim the interrupt */
-#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* Q0 Rx desc FIFO parity error */
-#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* Q0 Tx desc FIFO parity error */
-#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity err */
-#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */
-#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* Q1 Rx desc FIFO parity error */
-#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* Q1 Tx desc FIFO parity error */
-#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */
-#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW
- * bit in the FWSM */
-#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates
- * an interrupt */
-#define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */
-#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */
-#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */
-#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */
-#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */
-#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */
-#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */
-#define E1000_ICR_FER 0x00400000 /* Fatal Error */
+#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
+#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
+#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
+#define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */
+#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */
+#define E1000_ICR_RXO 0x00000040 /* Rx overrun */
+#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */
+#define E1000_ICR_VMMB 0x00000100 /* VM MB event */
+#define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */
+#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */
+#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */
+#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */
+#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
+#define E1000_ICR_TXD_LOW 0x00008000
+#define E1000_ICR_MNG 0x00040000 /* Manageability event */
+#define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */
+#define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */
+#define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */
+/* If this bit asserted, the driver should claim the interrupt */
+#define E1000_ICR_INT_ASSERTED 0x80000000
+#define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */
+#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */
+#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */
+#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */
+#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */
+#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */
+#define E1000_ICR_FER 0x00400000 /* Fatal Error */
+
+#define E1000_ICR_THS 0x00800000 /* ICR.THS: Thermal Sensor Event*/
+#define E1000_ICR_MDDET 0x10000000 /* Malicious Driver Detect */
+
+#define E1000_ITR_MASK 0x000FFFFF /* ITR value bitfield */
+#define E1000_ITR_MULT 256 /* ITR mulitplier in nsec */
/* PBA ECC Register */
-#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */
-#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */
-#define E1000_PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */
-#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
-#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */
+#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */
+#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */
+#define E1000_PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */
+#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
+#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */
/* Extended Interrupt Cause Read */
-#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */
-#define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */
-#define E1000_EICR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */
-#define E1000_EICR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */
-#define E1000_EICR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */
-#define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */
-#define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */
-#define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */
-#define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */
-#define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */
+#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */
+#define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */
+#define E1000_EICR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */
+#define E1000_EICR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */
+#define E1000_EICR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */
+#define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */
+#define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */
+#define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */
+#define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */
+#define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */
/* TCP Timer */
-#define E1000_TCPTIMER_KS 0x00000100 /* KickStart */
-#define E1000_TCPTIMER_COUNT_ENABLE 0x00000200 /* Count Enable */
-#define E1000_TCPTIMER_COUNT_FINISH 0x00000400 /* Count finish */
-#define E1000_TCPTIMER_LOOP 0x00000800 /* Loop */
-
-/*
- * This defines the bits that are set in the Interrupt Mask
- * Set/Read Register. Each bit is documented below:
- * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
- * o RXSEQ = Receive Sequence Error
- */
-#define POLL_IMS_ENABLE_MASK ( \
- E1000_IMS_RXDMT0 | \
- E1000_IMS_RXSEQ)
+#define E1000_TCPTIMER_KS 0x00000100 /* KickStart */
+#define E1000_TCPTIMER_COUNT_ENABLE 0x00000200 /* Count Enable */
+#define E1000_TCPTIMER_COUNT_FINISH 0x00000400 /* Count finish */
+#define E1000_TCPTIMER_LOOP 0x00000800 /* Loop */
-/*
- * This defines the bits that are set in the Interrupt Mask
+/* This defines the bits that are set in the Interrupt Mask
* Set/Read Register. Each bit is documented below:
* o RXT0 = Receiver Timer Interrupt (ring 0)
* o TXDW = Transmit Descriptor Written Back
@@ -863,861 +589,831 @@
* o LSC = Link Status Change
*/
#define IMS_ENABLE_MASK ( \
- E1000_IMS_RXT0 | \
- E1000_IMS_TXDW | \
- E1000_IMS_RXDMT0 | \
- E1000_IMS_RXSEQ | \
- E1000_IMS_LSC)
+ E1000_IMS_RXT0 | \
+ E1000_IMS_TXDW | \
+ E1000_IMS_RXDMT0 | \
+ E1000_IMS_RXSEQ | \
+ E1000_IMS_LSC)
/* Interrupt Mask Set */
-#define E1000_IMS_TXDW E1000_ICR_TXDW /* Tx desc written back */
-#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
-#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
-#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */
-#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
-#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
-#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */
-#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
-#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */
-#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */
-#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
-#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
-#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
-#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
-#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
-#define E1000_IMS_SRPD E1000_ICR_SRPD
-#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */
-#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */
-#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */
-#define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */
-#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO
- * parity error */
-#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO
- * parity error */
-#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer
- * parity error */
-#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity
- * error */
-#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO
- * parity error */
-#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO
- * parity error */
-#define E1000_IMS_DSW E1000_ICR_DSW
-#define E1000_IMS_PHYINT E1000_ICR_PHYINT
-#define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
-#define E1000_IMS_EPRST E1000_ICR_EPRST
-#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */
-#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */
-#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */
-#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */
-#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */
-#define E1000_IMS_FER E1000_ICR_FER /* Fatal Error */
-
+#define E1000_IMS_TXDW E1000_ICR_TXDW /* Tx desc written back */
+#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
+#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
+#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */
+#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
+#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
+#define E1000_IMS_RXO E1000_ICR_RXO /* Rx overrun */
+#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */
+#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */
+#define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */
+#define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */
+#define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
+#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */
+#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */
+#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */
+#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */
+#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */
+#define E1000_IMS_FER E1000_ICR_FER /* Fatal Error */
+
+#define E1000_IMS_THS E1000_ICR_THS /* ICR.TS: Thermal Sensor Event*/
+#define E1000_IMS_MDDET E1000_ICR_MDDET /* Malicious Driver Detect */
/* Extended Interrupt Mask Set */
-#define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
-#define E1000_EIMS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
-#define E1000_EIMS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */
-#define E1000_EIMS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */
-#define E1000_EIMS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */
-#define E1000_EIMS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */
-#define E1000_EIMS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */
-#define E1000_EIMS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */
-#define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */
-#define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */
+#define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
+#define E1000_EIMS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
+#define E1000_EIMS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */
+#define E1000_EIMS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */
+#define E1000_EIMS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */
+#define E1000_EIMS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */
+#define E1000_EIMS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */
+#define E1000_EIMS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */
+#define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */
+#define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */
/* Interrupt Cause Set */
-#define E1000_ICS_TXDW E1000_ICR_TXDW /* Tx desc written back */
-#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
-#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
-#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
-#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
-#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */
-#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
-#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */
-#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */
-#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
-#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
-#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
-#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
-#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW
-#define E1000_ICS_SRPD E1000_ICR_SRPD
-#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */
-#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */
-#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */
-#define E1000_ICS_DRSTA E1000_ICR_DRSTA /* Device Reset Aserted */
-#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO
- * parity error */
-#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO
- * parity error */
-#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer
- * parity error */
-#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity
- * error */
-#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO
- * parity error */
-#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO
- * parity error */
-#define E1000_ICS_DSW E1000_ICR_DSW
-#define E1000_ICS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
-#define E1000_ICS_PHYINT E1000_ICR_PHYINT
-#define E1000_ICS_EPRST E1000_ICR_EPRST
+#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
+#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
+#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
/* Extended Interrupt Cause Set */
-#define E1000_EICS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
-#define E1000_EICS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
-#define E1000_EICS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */
-#define E1000_EICS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */
-#define E1000_EICS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */
-#define E1000_EICS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */
-#define E1000_EICS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */
-#define E1000_EICS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */
-#define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */
-#define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */
-
-#define E1000_EITR_ITR_INT_MASK 0x0000FFFF
+#define E1000_EICS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
+#define E1000_EICS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
+#define E1000_EICS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */
+#define E1000_EICS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */
+#define E1000_EICS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */
+#define E1000_EICS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */
+#define E1000_EICS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */
+#define E1000_EICS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */
+#define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */
+#define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */
+
+#define E1000_EITR_ITR_INT_MASK 0x0000FFFF
/* E1000_EITR_CNT_IGNR is only for 82576 and newer */
#define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
/* Transmit Descriptor Control */
-#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
-#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
-#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
-#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
-#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
-#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
+#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
+#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
/* Enable the counting of descriptors still to be processed. */
-#define E1000_TXDCTL_COUNT_DESC 0x00400000
+#define E1000_TXDCTL_COUNT_DESC 0x00400000
/* Flow Control Constants */
-#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
-#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
-#define FLOW_CONTROL_TYPE 0x8808
+#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
+#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
+#define FLOW_CONTROL_TYPE 0x8808
/* 802.1q VLAN Packet Size */
-#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
-#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
+#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
+#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
-/* Receive Address */
-/*
+/* Receive Address
* Number of high/low register pairs in the RAR. The RAR (Receive Address
* Registers) holds the directed and multicast addresses that we monitor.
* Technically, we have 16 spots. However, we reserve one of these spots
* (RAR[15]) for our directed address used by controllers with
* manageability enabled, allowing us room for 15 multicast addresses.
*/
-#define E1000_RAR_ENTRIES 15
-#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
-#define E1000_RAL_MAC_ADDR_LEN 4
-#define E1000_RAH_MAC_ADDR_LEN 2
-#define E1000_RAH_POOL_MASK 0x03FC0000
-#define E1000_RAH_POOL_1 0x00040000
+#define E1000_RAR_ENTRIES 15
+#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
+#define E1000_RAL_MAC_ADDR_LEN 4
+#define E1000_RAH_MAC_ADDR_LEN 2
+#define E1000_RAH_QUEUE_MASK_82575 0x000C0000
+#define E1000_RAH_POOL_1 0x00040000
/* Error Codes */
-#define E1000_SUCCESS 0
-#define E1000_ERR_NVM 1
-#define E1000_ERR_PHY 2
-#define E1000_ERR_CONFIG 3
-#define E1000_ERR_PARAM 4
-#define E1000_ERR_MAC_INIT 5
-#define E1000_ERR_PHY_TYPE 6
-#define E1000_ERR_RESET 9
-#define E1000_ERR_MASTER_REQUESTS_PENDING 10
-#define E1000_ERR_HOST_INTERFACE_COMMAND 11
-#define E1000_BLK_PHY_RESET 12
-#define E1000_ERR_SWFW_SYNC 13
-#define E1000_NOT_IMPLEMENTED 14
-#define E1000_ERR_MBX 15
-#define E1000_ERR_INVALID_ARGUMENT 16
-#define E1000_ERR_NO_SPACE 17
-#define E1000_ERR_NVM_PBA_SECTION 18
+#define E1000_SUCCESS 0
+#define E1000_ERR_NVM 1
+#define E1000_ERR_PHY 2
+#define E1000_ERR_CONFIG 3
+#define E1000_ERR_PARAM 4
+#define E1000_ERR_MAC_INIT 5
+#define E1000_ERR_PHY_TYPE 6
+#define E1000_ERR_RESET 9
+#define E1000_ERR_MASTER_REQUESTS_PENDING 10
+#define E1000_ERR_HOST_INTERFACE_COMMAND 11
+#define E1000_BLK_PHY_RESET 12
+#define E1000_ERR_SWFW_SYNC 13
+#define E1000_NOT_IMPLEMENTED 14
+#define E1000_ERR_MBX 15
+#define E1000_ERR_INVALID_ARGUMENT 16
+#define E1000_ERR_NO_SPACE 17
+#define E1000_ERR_NVM_PBA_SECTION 18
+#define E1000_ERR_I2C 19
+#define E1000_ERR_INVM_VALUE_NOT_FOUND 20
/* Loop limit on how long we wait for auto-negotiation to complete */
-#define FIBER_LINK_UP_LIMIT 50
-#define COPPER_LINK_UP_LIMIT 10
-#define PHY_AUTO_NEG_LIMIT 45
-#define PHY_FORCE_LIMIT 20
+#define FIBER_LINK_UP_LIMIT 50
+#define COPPER_LINK_UP_LIMIT 10
+#define PHY_AUTO_NEG_LIMIT 45
+#define PHY_FORCE_LIMIT 20
/* Number of 100 microseconds we wait for PCI Express master disable */
-#define MASTER_DISABLE_TIMEOUT 800
+#define MASTER_DISABLE_TIMEOUT 800
/* Number of milliseconds we wait for PHY configuration done after MAC reset */
-#define PHY_CFG_TIMEOUT 100
+#define PHY_CFG_TIMEOUT 100
/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */
-#define MDIO_OWNERSHIP_TIMEOUT 10
+#define MDIO_OWNERSHIP_TIMEOUT 10
/* Number of milliseconds for NVM auto read done after MAC reset. */
-#define AUTO_READ_DONE_TIMEOUT 10
+#define AUTO_READ_DONE_TIMEOUT 10
/* Flow Control */
-#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */
-#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */
-#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */
-#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
+#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */
+#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */
+#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
/* Transmit Configuration Word */
-#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
-#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */
-#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */
-#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */
-#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */
-#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */
-#define E1000_TXCW_NP 0x00008000 /* TXCW next page */
-#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */
-#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */
-#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */
+#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
+#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */
+#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */
+#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */
+#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */
/* Receive Configuration Word */
-#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */
-#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */
-#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */
-#define E1000_RXCW_CC 0x10000000 /* Receive config change */
-#define E1000_RXCW_C 0x20000000 /* Receive config */
-#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */
-#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */
-
-#define E1000_TSYNCTXCTL_VALID 0x00000001 /* tx timestamp valid */
-#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable tx timestampping */
-
-#define E1000_TSYNCRXCTL_VALID 0x00000001 /* rx timestamp valid */
-#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* rx type mask */
-#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00
-#define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02
-#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04
-#define E1000_TSYNCRXCTL_TYPE_ALL 0x08
-#define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A
-#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable rx timestampping */
-
-#define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF
-#define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00
-#define E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01
-#define E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE 0x02
-#define E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE 0x03
-#define E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE 0x04
-
-#define E1000_TSYNCRXCFG_PTP_V2_MSGID_MASK 0x00000F00
-#define E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE 0x0000
-#define E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE 0x0100
-#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE 0x0200
-#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE 0x0300
-#define E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE 0x0800
-#define E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE 0x0900
-#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE 0x0A00
-#define E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE 0x0B00
-#define E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE 0x0C00
-#define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE 0x0D00
-
-#define E1000_TIMINCA_16NS_SHIFT 24
+#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */
+#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */
+#define E1000_RXCW_C 0x20000000 /* Receive config */
+#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */
+
+#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */
+#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
+
+#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */
+#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
+#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00
+#define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02
+#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04
+#define E1000_TSYNCRXCTL_TYPE_ALL 0x08
+#define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A
+#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */
+#define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */
+
+#define E1000_RXMTRL_PTP_V1_SYNC_MESSAGE 0x00000000
+#define E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE 0x00010000
+
+#define E1000_RXMTRL_PTP_V2_SYNC_MESSAGE 0x00000000
+#define E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE 0x01000000
+
+#define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF
+#define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00
+#define E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01
+#define E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE 0x02
+#define E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE 0x03
+#define E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE 0x04
+
+#define E1000_TSYNCRXCFG_PTP_V2_MSGID_MASK 0x00000F00
+#define E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE 0x0000
+#define E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE 0x0100
+#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE 0x0200
+#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE 0x0300
+#define E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE 0x0800
+#define E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE 0x0900
+#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE 0x0A00
+#define E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE 0x0B00
+#define E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE 0x0C00
+#define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE 0x0D00
+
+#define E1000_TIMINCA_16NS_SHIFT 24
+#define E1000_TIMINCA_INCPERIOD_SHIFT 24
+#define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF
+
+#define E1000_TSICR_TXTS 0x00000002
+#define E1000_TSIM_TXTS 0x00000002
/* TUPLE Filtering Configuration */
-#define E1000_TTQF_DISABLE_MASK 0xF0008000 /* TTQF Disable Mask */
-#define E1000_TTQF_QUEUE_ENABLE 0x100 /* TTQF Queue Enable Bit */
-#define E1000_TTQF_PROTOCOL_MASK 0xFF /* TTQF Protocol Mask */
+#define E1000_TTQF_DISABLE_MASK 0xF0008000 /* TTQF Disable Mask */
+#define E1000_TTQF_QUEUE_ENABLE 0x100 /* TTQF Queue Enable Bit */
+#define E1000_TTQF_PROTOCOL_MASK 0xFF /* TTQF Protocol Mask */
/* TTQF TCP Bit, shift with E1000_TTQF_PROTOCOL SHIFT */
-#define E1000_TTQF_PROTOCOL_TCP 0x0
+#define E1000_TTQF_PROTOCOL_TCP 0x0
/* TTQF UDP Bit, shift with E1000_TTQF_PROTOCOL_SHIFT */
-#define E1000_TTQF_PROTOCOL_UDP 0x1
+#define E1000_TTQF_PROTOCOL_UDP 0x1
/* TTQF SCTP Bit, shift with E1000_TTQF_PROTOCOL_SHIFT */
-#define E1000_TTQF_PROTOCOL_SCTP 0x2
-#define E1000_TTQF_PROTOCOL_SHIFT 5 /* TTQF Protocol Shift */
-#define E1000_TTQF_QUEUE_SHIFT 16 /* TTQF Queue Shfit */
-#define E1000_TTQF_RX_QUEUE_MASK 0x70000 /* TTQF Queue Mask */
-#define E1000_TTQF_MASK_ENABLE 0x10000000 /* TTQF Mask Enable Bit */
-#define E1000_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */
-#define E1000_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */
-#define E1000_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */
-#define E1000_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */
-
-#define E1000_MDICNFG_EXT_MDIO 0x80000000 /* MDI ext/int destination */
-#define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */
-#define E1000_MDICNFG_PHY_MASK 0x03E00000
-#define E1000_MDICNFG_PHY_SHIFT 21
-
+#define E1000_TTQF_PROTOCOL_SCTP 0x2
+#define E1000_TTQF_PROTOCOL_SHIFT 5 /* TTQF Protocol Shift */
+#define E1000_TTQF_QUEUE_SHIFT 16 /* TTQF Queue Shfit */
+#define E1000_TTQF_RX_QUEUE_MASK 0x70000 /* TTQF Queue Mask */
+#define E1000_TTQF_MASK_ENABLE 0x10000000 /* TTQF Mask Enable Bit */
+#define E1000_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */
+#define E1000_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */
+#define E1000_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */
+#define E1000_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */
+
+#define E1000_MDICNFG_EXT_MDIO 0x80000000 /* MDI ext/int destination */
+#define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */
+#define E1000_MDICNFG_PHY_MASK 0x03E00000
+#define E1000_MDICNFG_PHY_SHIFT 21
+
+#define E1000_THSTAT_LOW_EVENT 0x20000000 /* Low thermal threshold */
+#define E1000_THSTAT_MID_EVENT 0x00200000 /* Mid thermal threshold */
+#define E1000_THSTAT_HIGH_EVENT 0x00002000 /* High thermal threshold */
+#define E1000_THSTAT_PWR_DOWN 0x00000001 /* Power Down Event */
+#define E1000_THSTAT_LINK_THROTTLE 0x00000002 /* Link Spd Throttle Event */
+
+/* I350 EEE defines */
+#define E1000_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */
+#define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */
+#define E1000_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */
+#define E1000_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */
+#define E1000_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */
+/* EEE status */
+#define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */
+#define E1000_EEER_RX_LPI_STATUS 0x40000000 /* Rx in LPI state */
+#define E1000_EEER_TX_LPI_STATUS 0x80000000 /* Tx in LPI state */
+#define E1000_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */
/* PCI Express Control */
-#define E1000_GCR_RXD_NO_SNOOP 0x00000001
-#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
-#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004
-#define E1000_GCR_TXD_NO_SNOOP 0x00000008
-#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010
-#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020
-#define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000
-#define E1000_GCR_CMPL_TMOUT_10ms 0x00001000
-#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000
-#define E1000_GCR_CAP_VER2 0x00040000
-
-#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \
- E1000_GCR_RXDSCW_NO_SNOOP | \
- E1000_GCR_RXDSCR_NO_SNOOP | \
- E1000_GCR_TXD_NO_SNOOP | \
- E1000_GCR_TXDSCW_NO_SNOOP | \
- E1000_GCR_TXDSCR_NO_SNOOP)
+#define E1000_GCR_RXD_NO_SNOOP 0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004
+#define E1000_GCR_TXD_NO_SNOOP 0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020
+#define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000
+#define E1000_GCR_CMPL_TMOUT_10ms 0x00001000
+#define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000
+#define E1000_GCR_CAP_VER2 0x00040000
+
+#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \
+ E1000_GCR_RXDSCW_NO_SNOOP | \
+ E1000_GCR_RXDSCR_NO_SNOOP | \
+ E1000_GCR_TXD_NO_SNOOP | \
+ E1000_GCR_TXDSCW_NO_SNOOP | \
+ E1000_GCR_TXDSCR_NO_SNOOP)
+
+/* mPHY address control and data registers */
+#define E1000_MPHY_ADDR_CTL 0x0024 /* Address Control Reg */
+#define E1000_MPHY_ADDR_CTL_OFFSET_MASK 0xFFFF0000
+#define E1000_MPHY_DATA 0x0E10 /* Data Register */
+
+/* AFE CSR Offset for PCS CLK */
+#define E1000_MPHY_PCS_CLK_REG_OFFSET 0x0004
+/* Override for near end digital loopback. */
+#define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10
/* PHY Control Register */
-#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
-#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
-#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
-#define MII_CR_POWER_DOWN 0x0800 /* Power down */
-#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
-#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
-#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
-#define MII_CR_SPEED_1000 0x0040
-#define MII_CR_SPEED_100 0x2000
-#define MII_CR_SPEED_10 0x0000
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_1000 0x0040
+#define MII_CR_SPEED_100 0x2000
+#define MII_CR_SPEED_10 0x0000
/* PHY Status Register */
-#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
-#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
-#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
-#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
/* Autoneg Advertisement Register */
-#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
-#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
-#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
-#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
-#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
-#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
-#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
-#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
-#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
-#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
+#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
/* Link Partner Ability Register (Base Page) */
-#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
-#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */
-#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */
-#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */
-#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */
-#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */
-#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
-#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
-#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */
-#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */
-#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP 10T Half Dplx Capable */
+#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP 10T Full Dplx Capable */
+#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP 100TX Half Dplx Capable */
+#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP 100TX Full Dplx Capable */
+#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asym Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */
/* Autoneg Expansion Register */
-#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */
-#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */
-#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */
-#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
-#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */
+#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD 0x0002 /* LP 10T Half Dplx Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP 10T Full Dplx Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP 100TX Half Dplx Capable */
+#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP 100TX Full Dplx Capable */
/* 1000BASE-T Control Register */
-#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */
-#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
-#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
-#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */
- /* 0=DTE device */
-#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
- /* 0=Configure PHY as Slave */
-#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
- /* 0=Automatic Master/Slave config */
+#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+/* 1=Repeater/switch device port 0=DTE device */
+#define CR_1000T_REPEATER_DTE 0x0400
+/* 1=Configure PHY as Master 0=Configure PHY as Slave */
+#define CR_1000T_MS_VALUE 0x0800
+/* 1=Master/Slave manual config value 0=Automatic Master/Slave config */
+#define CR_1000T_MS_ENABLE 0x1000
#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
-#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
-#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
-#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
-#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
/* 1000BASE-T Status Register */
-#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */
-#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */
-#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
-#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
-#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
-#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
-#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local Tx is Master, 0=Slave */
-#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle err since last rd */
+#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asym pause direction bit */
+#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local Tx Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
-#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5
+#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5
/* PHY 1000 MII Register/Bit Definitions */
/* PHY Registers defined by IEEE */
-#define PHY_CONTROL 0x00 /* Control Register */
-#define PHY_STATUS 0x01 /* Status Register */
-#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
-#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
-#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
-#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
-#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */
-#define PHY_NEXT_PAGE_TX 0x07 /* Next Page Tx */
-#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
-#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
-#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
-#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
-
-#define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */
+#define PHY_CONTROL 0x00 /* Control Register */
+#define PHY_STATUS 0x01 /* Status Register */
+#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page Tx */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
+
+#define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */
/* NVM Control */
-#define E1000_EECD_SK 0x00000001 /* NVM Clock */
-#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */
-#define E1000_EECD_DI 0x00000004 /* NVM Data In */
-#define E1000_EECD_DO 0x00000008 /* NVM Data Out */
-#define E1000_EECD_FWE_MASK 0x00000030
-#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */
-#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */
-#define E1000_EECD_FWE_SHIFT 4
-#define E1000_EECD_REQ 0x00000040 /* NVM Access Request */
-#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */
-#define E1000_EECD_PRES 0x00000100 /* NVM Present */
-#define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */
+#define E1000_EECD_SK 0x00000001 /* NVM Clock */
+#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */
+#define E1000_EECD_DI 0x00000004 /* NVM Data In */
+#define E1000_EECD_DO 0x00000008 /* NVM Data Out */
+#define E1000_EECD_REQ 0x00000040 /* NVM Access Request */
+#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */
+#define E1000_EECD_PRES 0x00000100 /* NVM Present */
+#define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */
+#define E1000_EECD_BLOCKED 0x00008000 /* Bit banging access blocked flag */
+#define E1000_EECD_ABORT 0x00010000 /* NVM operation aborted flag */
+#define E1000_EECD_TIMEOUT 0x00020000 /* NVM read operation timeout flag */
+#define E1000_EECD_ERROR_CLR 0x00040000 /* NVM error status clear bit */
/* NVM Addressing bits based on type 0=small, 1=large */
-#define E1000_EECD_ADDR_BITS 0x00000400
-#define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
+#define E1000_EECD_ADDR_BITS 0x00000400
+#define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
#ifndef E1000_NVM_GRANT_ATTEMPTS
-#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
+#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
#endif
-#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
-#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
-#define E1000_EECD_SIZE_EX_SHIFT 11
-#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */
-#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */
-#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */
-#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
-#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
-#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
-#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
-#define E1000_EECD_SECVAL_SHIFT 22
-#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
-
-#define E1000_NVM_SWDPIN0 0x0001 /* SWDPIN 0 NVM Value */
-#define E1000_NVM_LED_LOGIC 0x0020 /* Led Logic Word */
-#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */
-#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
-#define E1000_NVM_RW_REG_START 1 /* Start operation */
-#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
-#define E1000_NVM_POLL_WRITE 1 /* Flag for polling for write complete */
-#define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */
-#define E1000_FLASH_UPDATES 2000
+#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
+#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
+#define E1000_EECD_SIZE_EX_SHIFT 11
+#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
+#define E1000_EECD_AUPDEN 0x00100000 /* Ena Auto FLASH update */
+#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
+#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
+#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
+#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done */
+#define E1000_EECD_FLASH_DETECTED_I210 0x00080000 /* FLASH detected */
+#define E1000_EECD_SEC1VAL_I210 0x02000000 /* Sector One Valid */
+#define E1000_FLUDONE_ATTEMPTS 20000
+#define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
+#define E1000_I210_FIFO_SEL_RX 0x00
+#define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i))
+#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0)
+#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06
+#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01
+
+#define E1000_I210_FLASH_SECTOR_SIZE 0x1000 /* 4KB FLASH sector unit size */
+/* Secure FLASH mode requires removing MSb */
+#define E1000_I210_FW_PTR_MASK 0x7FFF
+/* Firmware code revision field word offset*/
+#define E1000_I210_FW_VER_OFFSET 328
+
+#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */
+#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
+#define E1000_NVM_RW_REG_START 1 /* Start operation */
+#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
+#define E1000_NVM_POLL_WRITE 1 /* Flag for polling for write complete */
+#define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */
+#define E1000_FLASH_UPDATES 2000
/* NVM Word Offsets */
-#define NVM_COMPAT 0x0003
-#define NVM_ID_LED_SETTINGS 0x0004
-#define NVM_VERSION 0x0005
-#define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */
-#define NVM_PHY_CLASS_WORD 0x0007
-#define NVM_INIT_CONTROL1_REG 0x000A
-#define NVM_INIT_CONTROL2_REG 0x000F
-#define NVM_SWDEF_PINS_CTRL_PORT_1 0x0010
-#define NVM_INIT_CONTROL3_PORT_B 0x0014
-#define NVM_INIT_3GIO_3 0x001A
-#define NVM_SWDEF_PINS_CTRL_PORT_0 0x0020
-#define NVM_INIT_CONTROL3_PORT_A 0x0024
-#define NVM_CFG 0x0012
-#define NVM_FLASH_VERSION 0x0032
-#define NVM_ALT_MAC_ADDR_PTR 0x0037
-#define NVM_CHECKSUM_REG 0x003F
-
-#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */
-#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */
-#define E1000_NVM_CFG_DONE_PORT_2 0x100000 /* ...for third port */
-#define E1000_NVM_CFG_DONE_PORT_3 0x200000 /* ...for fourth port */
-
-#define NVM_82580_LAN_FUNC_OFFSET(a) (a ? (0x40 + (0x40 * a)) : 0)
+#define NVM_COMPAT 0x0003
+#define NVM_ID_LED_SETTINGS 0x0004
+#define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */
+#define NVM_PHY_CLASS_WORD 0x0007
+#define E1000_I210_NVM_FW_MODULE_PTR 0x0010
+#define E1000_I350_NVM_FW_MODULE_PTR 0x0051
+#define NVM_FUTURE_INIT_WORD1 0x0019
+#define NVM_MAC_ADDR 0x0000
+#define NVM_SUB_DEV_ID 0x000B
+#define NVM_SUB_VEN_ID 0x000C
+#define NVM_DEV_ID 0x000D
+#define NVM_VEN_ID 0x000E
+#define NVM_INIT_CTRL_2 0x000F
+#define NVM_INIT_CTRL_4 0x0013
+#define NVM_LED_1_CFG 0x001C
+#define NVM_LED_0_2_CFG 0x001F
+
+#define NVM_COMPAT_VALID_CSUM 0x0001
+#define NVM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040
+
+#define NVM_INIT_CONTROL2_REG 0x000F
+#define NVM_INIT_CONTROL3_PORT_B 0x0014
+#define NVM_INIT_3GIO_3 0x001A
+#define NVM_SWDEF_PINS_CTRL_PORT_0 0x0020
+#define NVM_INIT_CONTROL3_PORT_A 0x0024
+#define NVM_CFG 0x0012
+#define NVM_ALT_MAC_ADDR_PTR 0x0037
+#define NVM_CHECKSUM_REG 0x003F
+#define NVM_COMPATIBILITY_REG_3 0x0003
+#define NVM_COMPATIBILITY_BIT_MASK 0x8000
+
+#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */
+#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */
+#define E1000_NVM_CFG_DONE_PORT_2 0x100000 /* ...for third port */
+#define E1000_NVM_CFG_DONE_PORT_3 0x200000 /* ...for fourth port */
+
+#define NVM_82580_LAN_FUNC_OFFSET(a) ((a) ? (0x40 + (0x40 * (a))) : 0)
/* Mask bits for fields in Word 0x24 of the NVM */
-#define NVM_WORD24_COM_MDIO 0x0008 /* MDIO interface shared */
-#define NVM_WORD24_EXT_MDIO 0x0004 /* MDIO accesses routed external */
+#define NVM_WORD24_COM_MDIO 0x0008 /* MDIO interface shared */
+#define NVM_WORD24_EXT_MDIO 0x0004 /* MDIO accesses routed extrnl */
+/* Offset of Link Mode bits for 82575/82576 */
+#define NVM_WORD24_LNK_MODE_OFFSET 8
+/* Offset of Link Mode bits for 82580 up */
+#define NVM_WORD24_82580_LNK_MODE_OFFSET 4
+
/* Mask bits for fields in Word 0x0f of the NVM */
-#define NVM_WORD0F_PAUSE_MASK 0x3000
-#define NVM_WORD0F_PAUSE 0x1000
-#define NVM_WORD0F_ASM_DIR 0x2000
-#define NVM_WORD0F_ANE 0x0800
-#define NVM_WORD0F_SWPDIO_EXT_MASK 0x00F0
-#define NVM_WORD0F_LPLU 0x0001
+#define NVM_WORD0F_PAUSE_MASK 0x3000
+#define NVM_WORD0F_PAUSE 0x1000
+#define NVM_WORD0F_ASM_DIR 0x2000
+#define NVM_WORD0F_SWPDIO_EXT_MASK 0x00F0
/* Mask bits for fields in Word 0x1a of the NVM */
-#define NVM_WORD1A_ASPM_MASK 0x000C
+#define NVM_WORD1A_ASPM_MASK 0x000C
/* Mask bits for fields in Word 0x03 of the EEPROM */
-#define NVM_COMPAT_LOM 0x0800
+#define NVM_COMPAT_LOM 0x0800
/* length of string needed to store PBA number */
-#define E1000_PBANUM_LENGTH 11
+#define E1000_PBANUM_LENGTH 11
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
-#define NVM_SUM 0xBABA
-
-#define NVM_MAC_ADDR_OFFSET 0
-#define NVM_PBA_OFFSET_0 8
-#define NVM_PBA_OFFSET_1 9
-#define NVM_PBA_PTR_GUARD 0xFAFA
-#define NVM_RESERVED_WORD 0xFFFF
-#define NVM_PHY_CLASS_A 0x8000
-#define NVM_SERDES_AMPLITUDE_MASK 0x000F
-#define NVM_SIZE_MASK 0x1C00
-#define NVM_SIZE_SHIFT 10
-#define NVM_WORD_SIZE_BASE_SHIFT 6
-#define NVM_SWDPIO_EXT_SHIFT 4
+#define NVM_SUM 0xBABA
+
+/* PBA (printed board assembly) number words */
+#define NVM_PBA_OFFSET_0 8
+#define NVM_PBA_OFFSET_1 9
+#define NVM_PBA_PTR_GUARD 0xFAFA
+#define NVM_RESERVED_WORD 0xFFFF
+#define NVM_PHY_CLASS_A 0x8000
+#define NVM_SERDES_AMPLITUDE_MASK 0x000F
+#define NVM_SIZE_MASK 0x1C00
+#define NVM_SIZE_SHIFT 10
+#define NVM_WORD_SIZE_BASE_SHIFT 6
+#define NVM_SWDPIO_EXT_SHIFT 4
/* NVM Commands - Microwire */
-#define NVM_READ_OPCODE_MICROWIRE 0x6 /* NVM read opcode */
-#define NVM_WRITE_OPCODE_MICROWIRE 0x5 /* NVM write opcode */
-#define NVM_ERASE_OPCODE_MICROWIRE 0x7 /* NVM erase opcode */
-#define NVM_EWEN_OPCODE_MICROWIRE 0x13 /* NVM erase/write enable */
-#define NVM_EWDS_OPCODE_MICROWIRE 0x10 /* NVM erase/write disable */
+#define NVM_READ_OPCODE_MICROWIRE 0x6 /* NVM read opcode */
+#define NVM_WRITE_OPCODE_MICROWIRE 0x5 /* NVM write opcode */
+#define NVM_ERASE_OPCODE_MICROWIRE 0x7 /* NVM erase opcode */
+#define NVM_EWEN_OPCODE_MICROWIRE 0x13 /* NVM erase/write enable */
+#define NVM_EWDS_OPCODE_MICROWIRE 0x10 /* NVM erase/write disable */
/* NVM Commands - SPI */
-#define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
-#define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */
-#define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */
-#define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */
-#define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */
-#define NVM_WRDI_OPCODE_SPI 0x04 /* NVM reset Write Enable latch */
-#define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */
-#define NVM_WRSR_OPCODE_SPI 0x01 /* NVM write Status register */
+#define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
+#define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */
+#define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */
+#define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */
+#define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */
+#define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */
/* SPI NVM Status Register */
-#define NVM_STATUS_RDY_SPI 0x01
-#define NVM_STATUS_WEN_SPI 0x02
-#define NVM_STATUS_BP0_SPI 0x04
-#define NVM_STATUS_BP1_SPI 0x08
-#define NVM_STATUS_WPEN_SPI 0x80
+#define NVM_STATUS_RDY_SPI 0x01
/* Word definitions for ID LED Settings */
-#define ID_LED_RESERVED_0000 0x0000
-#define ID_LED_RESERVED_FFFF 0xFFFF
-#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \
- (ID_LED_OFF1_OFF2 << 8) | \
- (ID_LED_DEF1_DEF2 << 4) | \
- (ID_LED_DEF1_DEF2))
-#define ID_LED_DEF1_DEF2 0x1
-#define ID_LED_DEF1_ON2 0x2
-#define ID_LED_DEF1_OFF2 0x3
-#define ID_LED_ON1_DEF2 0x4
-#define ID_LED_ON1_ON2 0x5
-#define ID_LED_ON1_OFF2 0x6
-#define ID_LED_OFF1_DEF2 0x7
-#define ID_LED_OFF1_ON2 0x8
-#define ID_LED_OFF1_OFF2 0x9
-
-#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF
-#define IGP_ACTIVITY_LED_ENABLE 0x0300
-#define IGP_LED3_MODE 0x07000000
+#define ID_LED_RESERVED_0000 0x0000
+#define ID_LED_RESERVED_FFFF 0xFFFF
+#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \
+ (ID_LED_OFF1_OFF2 << 8) | \
+ (ID_LED_DEF1_DEF2 << 4) | \
+ (ID_LED_DEF1_DEF2))
+#define ID_LED_DEF1_DEF2 0x1
+#define ID_LED_DEF1_ON2 0x2
+#define ID_LED_DEF1_OFF2 0x3
+#define ID_LED_ON1_DEF2 0x4
+#define ID_LED_ON1_ON2 0x5
+#define ID_LED_ON1_OFF2 0x6
+#define ID_LED_OFF1_DEF2 0x7
+#define ID_LED_OFF1_ON2 0x8
+#define ID_LED_OFF1_OFF2 0x9
+
+#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF
+#define IGP_ACTIVITY_LED_ENABLE 0x0300
+#define IGP_LED3_MODE 0x07000000
/* PCI/PCI-X/PCI-EX Config space */
-#define PCIX_COMMAND_REGISTER 0xE6
-#define PCIX_STATUS_REGISTER_LO 0xE8
-#define PCIX_STATUS_REGISTER_HI 0xEA
-#define PCI_HEADER_TYPE_REGISTER 0x0E
-#define PCIE_LINK_STATUS 0x12
-#define PCIE_DEVICE_CONTROL2 0x28
-
-#define PCIX_COMMAND_MMRBC_MASK 0x000C
-#define PCIX_COMMAND_MMRBC_SHIFT 0x2
-#define PCIX_STATUS_HI_MMRBC_MASK 0x0060
-#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5
-#define PCIX_STATUS_HI_MMRBC_4K 0x3
-#define PCIX_STATUS_HI_MMRBC_2K 0x2
-#define PCIX_STATUS_LO_FUNC_MASK 0x7
-#define PCI_HEADER_TYPE_MULTIFUNC 0x80
-#define PCIE_LINK_WIDTH_MASK 0x3F0
-#define PCIE_LINK_WIDTH_SHIFT 4
-#define PCIE_LINK_SPEED_MASK 0x0F
-#define PCIE_LINK_SPEED_2500 0x01
-#define PCIE_LINK_SPEED_5000 0x02
-#define PCIE_DEVICE_CONTROL2_16ms 0x0005
+#define PCIX_COMMAND_REGISTER 0xE6
+#define PCIX_STATUS_REGISTER_LO 0xE8
+#define PCIX_STATUS_REGISTER_HI 0xEA
+#define PCI_HEADER_TYPE_REGISTER 0x0E
+#define PCIE_LINK_STATUS 0x12
+#define PCIE_DEVICE_CONTROL2 0x28
+
+#define PCIX_COMMAND_MMRBC_MASK 0x000C
+#define PCIX_COMMAND_MMRBC_SHIFT 0x2
+#define PCIX_STATUS_HI_MMRBC_MASK 0x0060
+#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5
+#define PCIX_STATUS_HI_MMRBC_4K 0x3
+#define PCIX_STATUS_HI_MMRBC_2K 0x2
+#define PCIX_STATUS_LO_FUNC_MASK 0x7
+#define PCI_HEADER_TYPE_MULTIFUNC 0x80
+#define PCIE_LINK_WIDTH_MASK 0x3F0
+#define PCIE_LINK_WIDTH_SHIFT 4
+#define PCIE_LINK_SPEED_MASK 0x0F
+#define PCIE_LINK_SPEED_2500 0x01
+#define PCIE_LINK_SPEED_5000 0x02
+#define PCIE_DEVICE_CONTROL2_16ms 0x0005
#ifndef ETH_ADDR_LEN
-#define ETH_ADDR_LEN 6
+#define ETH_ADDR_LEN 6
#endif
-#define PHY_REVISION_MASK 0xFFFFFFF0
-#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
-#define MAX_PHY_MULTI_PAGE_REG 0xF
+#define PHY_REVISION_MASK 0xFFFFFFF0
+#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
+#define MAX_PHY_MULTI_PAGE_REG 0xF
-/* Bit definitions for valid PHY IDs. */
-/*
+/* Bit definitions for valid PHY IDs.
* I = Integrated
* E = External
*/
-#define M88E1000_E_PHY_ID 0x01410C50
-#define M88E1000_I_PHY_ID 0x01410C30
-#define M88E1011_I_PHY_ID 0x01410C20
-#define IGP01E1000_I_PHY_ID 0x02A80380
-#define M88E1011_I_REV_4 0x04
-#define M88E1111_I_PHY_ID 0x01410CC0
-#define GG82563_E_PHY_ID 0x01410CA0
-#define IGP03E1000_E_PHY_ID 0x02A80390
-#define IFE_E_PHY_ID 0x02A80330
-#define IFE_PLUS_E_PHY_ID 0x02A80320
-#define IFE_C_E_PHY_ID 0x02A80310
-#define BME1000_E_PHY_ID 0x01410CB0
-#define BME1000_E_PHY_ID_R2 0x01410CB1
-#define I82577_E_PHY_ID 0x01540050
-#define I82578_E_PHY_ID 0x004DD040
-#define I82579_E_PHY_ID 0x01540090
-#define I82580_I_PHY_ID 0x015403A0
-#define IGP04E1000_E_PHY_ID 0x02A80391
-#define M88_VENDOR 0x0141
+#define M88E1000_E_PHY_ID 0x01410C50
+#define M88E1000_I_PHY_ID 0x01410C30
+#define M88E1011_I_PHY_ID 0x01410C20
+#define IGP01E1000_I_PHY_ID 0x02A80380
+#define M88E1111_I_PHY_ID 0x01410CC0
+#define M88E1112_E_PHY_ID 0x01410C90
+#define I347AT4_E_PHY_ID 0x01410DC0
+#define M88E1340M_E_PHY_ID 0x01410DF0
+#define GG82563_E_PHY_ID 0x01410CA0
+#define IGP03E1000_E_PHY_ID 0x02A80390
+#define IFE_E_PHY_ID 0x02A80330
+#define IFE_PLUS_E_PHY_ID 0x02A80320
+#define IFE_C_E_PHY_ID 0x02A80310
+#define BME1000_E_PHY_ID 0x01410CB0
+#define BME1000_E_PHY_ID_R2 0x01410CB1
+#define I82577_E_PHY_ID 0x01540050
+#define I82578_E_PHY_ID 0x004DD040
+#define I82579_E_PHY_ID 0x01540090
+#define I217_E_PHY_ID 0x015400A0
+#define I82580_I_PHY_ID 0x015403A0
+#define I350_I_PHY_ID 0x015403B0
+#define I210_I_PHY_ID 0x01410C00
+#define IGP04E1000_E_PHY_ID 0x02A80391
+#define M88_VENDOR 0x0141
/* M88E1000 Specific Registers */
-#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
-#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */
-#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */
-#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */
-#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */
-#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */
-
-#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */
-#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */
-#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */
-#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
-#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
+#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Reg */
+#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Reg */
+#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Cntrl */
+#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */
+
+#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */
+#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for pg number setting */
+#define M88E1000_PHY_GEN_CONTROL 0x1E /* meaning depends on reg 29 */
+#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
+#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
/* M88E1000 PHY Specific Control Register */
-#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
-#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reverse enabled */
-#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
-/* 1=CLK125 low, 0=CLK125 toggling */
-#define M88E1000_PSCR_CLK125_DISABLE 0x0010
-#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
- /* Manual MDI configuration */
-#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reverse enabled */
+/* MDI Crossover Mode bits 6:5 Manual MDI configuration */
+#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000
+#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
-#define M88E1000_PSCR_AUTO_X_1000T 0x0040
+#define M88E1000_PSCR_AUTO_X_1000T 0x0040
/* Auto crossover enabled all speeds */
-#define M88E1000_PSCR_AUTO_X_MODE 0x0060
-/*
- * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold
- * 0=Normal 10BASE-T Rx Threshold
- */
-#define M88E1000_PSCR_EN_10BT_EXT_DIST 0x0080
-/* 1=5-bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
-#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100
-#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
-#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
-#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Tx */
+#define M88E1000_PSCR_AUTO_X_MODE 0x0060
+#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Tx */
/* M88E1000 PHY Specific Status Register */
-#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */
-#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */
-#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */
-#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */
-/*
- * 0 = <50M
+#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */
+#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */
+#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */
+/* 0 = <50M
* 1 = 50-80M
* 2 = 80-110M
* 3 = 110-140M
* 4 = >140M
*/
-#define M88E1000_PSSR_CABLE_LENGTH 0x0380
-#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */
-#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
-#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */
-#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
-#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
-#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */
-#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */
-#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
-
-#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
-
-/* M88E1000 Extended PHY Specific Control Register */
-#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
-/*
- * 1 = Lost lock detect enabled.
- * Will assert lost lock and bring
- * link down if idle not seen
- * within 1ms in 1000BASE-T
- */
-#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000
-/*
- * Number of times we will attempt to autonegotiate before downshifting if we
+#define M88E1000_PSSR_CABLE_LENGTH 0x0380
+#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */
+#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
+#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
+#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */
+#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+
+#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
+
+/* Number of times we will attempt to autonegotiate before downshifting if we
* are the master
*/
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800
-#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00
-/*
- * Number of times we will attempt to autonegotiate before downshifting if we
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000
+/* Number of times we will attempt to autonegotiate before downshifting if we
* are the slave
*/
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200
-#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300
-#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
+#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
+/* Intel I347AT4 Registers */
+#define I347AT4_PCDL 0x10 /* PHY Cable Diagnostics Length */
+#define I347AT4_PCDC 0x15 /* PHY Cable Diagnostics Control */
+#define I347AT4_PAGE_SELECT 0x16
+
+/* I347AT4 Extended PHY Specific Control Register */
+
+/* Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
+#define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800
+#define I347AT4_PSCR_DOWNSHIFT_MASK 0x7000
+#define I347AT4_PSCR_DOWNSHIFT_1X 0x0000
+#define I347AT4_PSCR_DOWNSHIFT_2X 0x1000
+#define I347AT4_PSCR_DOWNSHIFT_3X 0x2000
+#define I347AT4_PSCR_DOWNSHIFT_4X 0x3000
+#define I347AT4_PSCR_DOWNSHIFT_5X 0x4000
+#define I347AT4_PSCR_DOWNSHIFT_6X 0x5000
+#define I347AT4_PSCR_DOWNSHIFT_7X 0x6000
+#define I347AT4_PSCR_DOWNSHIFT_8X 0x7000
+
+/* I347AT4 PHY Cable Diagnostics Control */
+#define I347AT4_PCDC_CABLE_LENGTH_UNIT 0x0400 /* 0=cm 1=meters */
+
+/* M88E1112 only registers */
+#define M88E1112_VCT_DSP_DISTANCE 0x001A
/* M88EC018 Rev 2 specific DownShift settings */
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X 0x0000
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X 0x0200
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X 0x0400
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X 0x0600
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X 0x0A00
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00
-#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00
-
-#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020
-#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800
+
+#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020
+#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C
/* BME1000 PHY Specific Control Register */
-#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */
+#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */
-/*
- * Bits...
+/* Bits...
* 15-5: page
* 4-0: register offset
*/
-#define GG82563_PAGE_SHIFT 5
-#define GG82563_REG(page, reg) \
- (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
-#define GG82563_MIN_ALT_REG 30
+#define GG82563_PAGE_SHIFT 5
+#define GG82563_REG(page, reg) \
+ (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+#define GG82563_MIN_ALT_REG 30
/* GG82563 Specific Registers */
-#define GG82563_PHY_SPEC_CTRL \
- GG82563_REG(0, 16) /* PHY Specific Control */
-#define GG82563_PHY_SPEC_STATUS \
- GG82563_REG(0, 17) /* PHY Specific Status */
-#define GG82563_PHY_INT_ENABLE \
- GG82563_REG(0, 18) /* Interrupt Enable */
-#define GG82563_PHY_SPEC_STATUS_2 \
- GG82563_REG(0, 19) /* PHY Specific Status 2 */
-#define GG82563_PHY_RX_ERR_CNTR \
- GG82563_REG(0, 21) /* Receive Error Counter */
-#define GG82563_PHY_PAGE_SELECT \
- GG82563_REG(0, 22) /* Page Select */
-#define GG82563_PHY_SPEC_CTRL_2 \
- GG82563_REG(0, 26) /* PHY Specific Control 2 */
-#define GG82563_PHY_PAGE_SELECT_ALT \
- GG82563_REG(0, 29) /* Alternate Page Select */
-#define GG82563_PHY_TEST_CLK_CTRL \
- GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */
-
-#define GG82563_PHY_MAC_SPEC_CTRL \
- GG82563_REG(2, 21) /* MAC Specific Control Register */
-#define GG82563_PHY_MAC_SPEC_CTRL_2 \
- GG82563_REG(2, 26) /* MAC Specific Control 2 */
-
-#define GG82563_PHY_DSP_DISTANCE \
- GG82563_REG(5, 26) /* DSP Distance */
+#define GG82563_PHY_SPEC_CTRL GG82563_REG(0, 16) /* PHY Spec Cntrl */
+#define GG82563_PHY_PAGE_SELECT GG82563_REG(0, 22) /* Page Select */
+#define GG82563_PHY_SPEC_CTRL_2 GG82563_REG(0, 26) /* PHY Spec Cntrl2 */
+#define GG82563_PHY_PAGE_SELECT_ALT GG82563_REG(0, 29) /* Alt Page Select */
+
+/* MAC Specific Control Register */
+#define GG82563_PHY_MAC_SPEC_CTRL GG82563_REG(2, 21)
+
+#define GG82563_PHY_DSP_DISTANCE GG82563_REG(5, 26) /* DSP Distance */
/* Page 193 - Port Control Registers */
-#define GG82563_PHY_KMRN_MODE_CTRL \
- GG82563_REG(193, 16) /* Kumeran Mode Control */
-#define GG82563_PHY_PORT_RESET \
- GG82563_REG(193, 17) /* Port Reset */
-#define GG82563_PHY_REVISION_ID \
- GG82563_REG(193, 18) /* Revision ID */
-#define GG82563_PHY_DEVICE_ID \
- GG82563_REG(193, 19) /* Device ID */
-#define GG82563_PHY_PWR_MGMT_CTRL \
- GG82563_REG(193, 20) /* Power Management Control */
-#define GG82563_PHY_RATE_ADAPT_CTRL \
- GG82563_REG(193, 25) /* Rate Adaptation Control */
+/* Kumeran Mode Control */
+#define GG82563_PHY_KMRN_MODE_CTRL GG82563_REG(193, 16)
+#define GG82563_PHY_PWR_MGMT_CTRL GG82563_REG(193, 20) /* Pwr Mgt Ctrl */
/* Page 194 - KMRN Registers */
-#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \
- GG82563_REG(194, 16) /* FIFO's Control/Status */
-#define GG82563_PHY_KMRN_CTRL \
- GG82563_REG(194, 17) /* Control */
-#define GG82563_PHY_INBAND_CTRL \
- GG82563_REG(194, 18) /* Inband Control */
-#define GG82563_PHY_KMRN_DIAGNOSTIC \
- GG82563_REG(194, 19) /* Diagnostic */
-#define GG82563_PHY_ACK_TIMEOUTS \
- GG82563_REG(194, 20) /* Acknowledge Timeouts */
-#define GG82563_PHY_ADV_ABILITY \
- GG82563_REG(194, 21) /* Advertised Ability */
-#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \
- GG82563_REG(194, 23) /* Link Partner Advertised Ability */
-#define GG82563_PHY_ADV_NEXT_PAGE \
- GG82563_REG(194, 24) /* Advertised Next Page */
-#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \
- GG82563_REG(194, 25) /* Link Partner Advertised Next page */
-#define GG82563_PHY_KMRN_MISC \
- GG82563_REG(194, 26) /* Misc. */
+#define GG82563_PHY_INBAND_CTRL GG82563_REG(194, 18) /* Inband Ctrl */
/* MDI Control */
-#define E1000_MDIC_DATA_MASK 0x0000FFFF
-#define E1000_MDIC_REG_MASK 0x001F0000
-#define E1000_MDIC_REG_SHIFT 16
-#define E1000_MDIC_PHY_MASK 0x03E00000
-#define E1000_MDIC_PHY_SHIFT 21
-#define E1000_MDIC_OP_WRITE 0x04000000
-#define E1000_MDIC_OP_READ 0x08000000
-#define E1000_MDIC_READY 0x10000000
-#define E1000_MDIC_INT_EN 0x20000000
-#define E1000_MDIC_ERROR 0x40000000
-#define E1000_MDIC_DEST 0x80000000
+#define E1000_MDIC_REG_MASK 0x001F0000
+#define E1000_MDIC_REG_SHIFT 16
+#define E1000_MDIC_PHY_MASK 0x03E00000
+#define E1000_MDIC_PHY_SHIFT 21
+#define E1000_MDIC_OP_WRITE 0x04000000
+#define E1000_MDIC_OP_READ 0x08000000
+#define E1000_MDIC_READY 0x10000000
+#define E1000_MDIC_ERROR 0x40000000
+#define E1000_MDIC_DEST 0x80000000
/* SerDes Control */
-#define E1000_GEN_CTL_READY 0x80000000
-#define E1000_GEN_CTL_ADDRESS_SHIFT 8
-#define E1000_GEN_POLL_TIMEOUT 640
+#define E1000_GEN_CTL_READY 0x80000000
+#define E1000_GEN_CTL_ADDRESS_SHIFT 8
+#define E1000_GEN_POLL_TIMEOUT 640
/* LinkSec register fields */
-#define E1000_LSECTXCAP_SUM_MASK 0x00FF0000
-#define E1000_LSECTXCAP_SUM_SHIFT 16
-#define E1000_LSECRXCAP_SUM_MASK 0x00FF0000
-#define E1000_LSECRXCAP_SUM_SHIFT 16
-
-#define E1000_LSECTXCTRL_EN_MASK 0x00000003
-#define E1000_LSECTXCTRL_DISABLE 0x0
-#define E1000_LSECTXCTRL_AUTH 0x1
-#define E1000_LSECTXCTRL_AUTH_ENCRYPT 0x2
-#define E1000_LSECTXCTRL_AISCI 0x00000020
-#define E1000_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00
-#define E1000_LSECTXCTRL_RSV_MASK 0x000000D8
-
-#define E1000_LSECRXCTRL_EN_MASK 0x0000000C
-#define E1000_LSECRXCTRL_EN_SHIFT 2
-#define E1000_LSECRXCTRL_DISABLE 0x0
-#define E1000_LSECRXCTRL_CHECK 0x1
-#define E1000_LSECRXCTRL_STRICT 0x2
-#define E1000_LSECRXCTRL_DROP 0x3
-#define E1000_LSECRXCTRL_PLSH 0x00000040
-#define E1000_LSECRXCTRL_RP 0x00000080
-#define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33
-
+#define E1000_LSECTXCAP_SUM_MASK 0x00FF0000
+#define E1000_LSECTXCAP_SUM_SHIFT 16
+#define E1000_LSECRXCAP_SUM_MASK 0x00FF0000
+#define E1000_LSECRXCAP_SUM_SHIFT 16
+
+#define E1000_LSECTXCTRL_EN_MASK 0x00000003
+#define E1000_LSECTXCTRL_DISABLE 0x0
+#define E1000_LSECTXCTRL_AUTH 0x1
+#define E1000_LSECTXCTRL_AUTH_ENCRYPT 0x2
+#define E1000_LSECTXCTRL_AISCI 0x00000020
+#define E1000_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00
+#define E1000_LSECTXCTRL_RSV_MASK 0x000000D8
+
+#define E1000_LSECRXCTRL_EN_MASK 0x0000000C
+#define E1000_LSECRXCTRL_EN_SHIFT 2
+#define E1000_LSECRXCTRL_DISABLE 0x0
+#define E1000_LSECRXCTRL_CHECK 0x1
+#define E1000_LSECRXCTRL_STRICT 0x2
+#define E1000_LSECRXCTRL_DROP 0x3
+#define E1000_LSECRXCTRL_PLSH 0x00000040
+#define E1000_LSECRXCTRL_RP 0x00000080
+#define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33
+
+/* Tx Rate-Scheduler Config fields */
+#define E1000_RTTBCNRC_RS_ENA 0x80000000
+#define E1000_RTTBCNRC_RF_DEC_MASK 0x00003FFF
+#define E1000_RTTBCNRC_RF_INT_SHIFT 14
+#define E1000_RTTBCNRC_RF_INT_MASK \
+ (E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT)
/* DMA Coalescing register fields */
-#define E1000_DMACR_DMACWT_MASK 0x00003FFF /* DMA Coalescing
- * Watchdog Timer */
-#define E1000_DMACR_DMACTHR_MASK 0x00FF0000 /* DMA Coalescing Receive
- * Threshold */
-#define E1000_DMACR_DMACTHR_SHIFT 16
-#define E1000_DMACR_DMAC_LX_MASK 0x30000000 /* Lx when no PCIe
- * transactions */
-#define E1000_DMACR_DMAC_LX_SHIFT 28
-#define E1000_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */
-
-#define E1000_DMCTXTH_DMCTTHR_MASK 0x00000FFF /* DMA Coalescing Transmit
- * Threshold */
-
-#define E1000_DMCTLX_TTLX_MASK 0x00000FFF /* Time to LX request */
-
-#define E1000_DMCRTRH_UTRESH_MASK 0x0007FFFF /* Receive Traffic Rate
- * Threshold */
-#define E1000_DMCRTRH_LRPRCW 0x80000000 /* Rcv packet rate in
- * current window */
-
-#define E1000_DMCCNT_CCOUNT_MASK 0x01FFFFFF /* DMA Coal Rcv Traffic
- * Current Cnt */
-
-#define E1000_FCRTC_RTH_COAL_MASK 0x0003FFF0 /* Flow ctrl Rcv Threshold
- * High val */
-#define E1000_FCRTC_RTH_COAL_SHIFT 4
-#define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision based
- on DMA coal */
-
-
+/* DMA Coalescing Watchdog Timer */
+#define E1000_DMACR_DMACWT_MASK 0x00003FFF
+/* DMA Coalescing Rx Threshold */
+#define E1000_DMACR_DMACTHR_MASK 0x00FF0000
+#define E1000_DMACR_DMACTHR_SHIFT 16
+/* Lx when no PCIe transactions */
+#define E1000_DMACR_DMAC_LX_MASK 0x30000000
+#define E1000_DMACR_DMAC_LX_SHIFT 28
+#define E1000_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */
+/* DMA Coalescing BMC-to-OS Watchdog Enable */
+#define E1000_DMACR_DC_BMC2OSW_EN 0x00008000
+
+/* DMA Coalescing Transmit Threshold */
+#define E1000_DMCTXTH_DMCTTHR_MASK 0x00000FFF
+
+#define E1000_DMCTLX_TTLX_MASK 0x00000FFF /* Time to LX request */
+
+/* Rx Traffic Rate Threshold */
+#define E1000_DMCRTRH_UTRESH_MASK 0x0007FFFF
+/* Rx packet rate in current window */
+#define E1000_DMCRTRH_LRPRCW 0x80000000
+
+/* DMA Coal Rx Traffic Current Count */
+#define E1000_DMCCNT_CCOUNT_MASK 0x01FFFFFF
+
+/* Flow ctrl Rx Threshold High val */
+#define E1000_FCRTC_RTH_COAL_MASK 0x0003FFF0
+#define E1000_FCRTC_RTH_COAL_SHIFT 4
+/* Lx power decision based on DMA coal */
+#define E1000_PCIEMISC_LX_DECISION 0x00000080
+
+#define E1000_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */
+#define E1000_RXPBS_SIZE_I210_MASK 0x0000003F /* Rx packet buffer size */
+#define E1000_TXPB0S_SIZE_I210_MASK 0x0000003F /* Tx packet buffer 0 size */
+#define E1000_DOBFFCTL_OBFFTHR_MASK 0x000000FF /* OBFF threshold */
+#define E1000_DOBFFCTL_EXIT_ACT_MASK 0x01000000 /* Exit active CB */
+
+/* Proxy Filter Control */
+#define E1000_PROXYFC_D0 0x00000001 /* Enable offload in D0 */
+#define E1000_PROXYFC_EX 0x00000004 /* Directed exact proxy */
+#define E1000_PROXYFC_MC 0x00000008 /* Directed MC Proxy */
+#define E1000_PROXYFC_BC 0x00000010 /* Broadcast Proxy Enable */
+#define E1000_PROXYFC_ARP_DIRECTED 0x00000020 /* Directed ARP Proxy Ena */
+#define E1000_PROXYFC_IPV4 0x00000040 /* Directed IPv4 Enable */
+#define E1000_PROXYFC_IPV6 0x00000080 /* Directed IPv6 Enable */
+#define E1000_PROXYFC_NS 0x00000200 /* IPv6 Neighbor Solicitation */
+#define E1000_PROXYFC_ARP 0x00000800 /* ARP Request Proxy Ena */
+/* Proxy Status */
+#define E1000_PROXYS_CLEAR 0xFFFFFFFF /* Clear */
+
+/* Firmware Status */
+#define E1000_FWSTS_FWRI 0x80000000 /* FW Reset Indication */
+/* VF Control */
+#define E1000_VTCTRL_RST 0x04000000 /* Reset VF */
+
+#define E1000_STATUS_LAN_ID_MASK 0x00000000C /* Mask for Lan ID field */
+/* Lan ID bit field offset in status register */
+#define E1000_STATUS_LAN_ID_OFFSET 2
+#define E1000_VFTA_ENTRIES 128
#endif /* _E1000_DEFINES_H_ */
diff --git a/freebsd/sys/dev/e1000/e1000_hw.h b/freebsd/sys/dev/e1000/e1000_hw.h
index e5dfe84d..e47a7593 100644
--- a/freebsd/sys/dev/e1000/e1000_hw.h
+++ b/freebsd/sys/dev/e1000/e1000_hw.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -47,132 +47,151 @@
struct e1000_hw;
-#define E1000_DEV_ID_82542 0x1000
-#define E1000_DEV_ID_82543GC_FIBER 0x1001
-#define E1000_DEV_ID_82543GC_COPPER 0x1004
-#define E1000_DEV_ID_82544EI_COPPER 0x1008
-#define E1000_DEV_ID_82544EI_FIBER 0x1009
-#define E1000_DEV_ID_82544GC_COPPER 0x100C
-#define E1000_DEV_ID_82544GC_LOM 0x100D
-#define E1000_DEV_ID_82540EM 0x100E
-#define E1000_DEV_ID_82540EM_LOM 0x1015
-#define E1000_DEV_ID_82540EP_LOM 0x1016
-#define E1000_DEV_ID_82540EP 0x1017
-#define E1000_DEV_ID_82540EP_LP 0x101E
-#define E1000_DEV_ID_82545EM_COPPER 0x100F
-#define E1000_DEV_ID_82545EM_FIBER 0x1011
-#define E1000_DEV_ID_82545GM_COPPER 0x1026
-#define E1000_DEV_ID_82545GM_FIBER 0x1027
-#define E1000_DEV_ID_82545GM_SERDES 0x1028
-#define E1000_DEV_ID_82546EB_COPPER 0x1010
-#define E1000_DEV_ID_82546EB_FIBER 0x1012
-#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
-#define E1000_DEV_ID_82546GB_COPPER 0x1079
-#define E1000_DEV_ID_82546GB_FIBER 0x107A
-#define E1000_DEV_ID_82546GB_SERDES 0x107B
-#define E1000_DEV_ID_82546GB_PCIE 0x108A
-#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
-#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
-#define E1000_DEV_ID_82541EI 0x1013
-#define E1000_DEV_ID_82541EI_MOBILE 0x1018
-#define E1000_DEV_ID_82541ER_LOM 0x1014
-#define E1000_DEV_ID_82541ER 0x1078
-#define E1000_DEV_ID_82541GI 0x1076
-#define E1000_DEV_ID_82541GI_LF 0x107C
-#define E1000_DEV_ID_82541GI_MOBILE 0x1077
-#define E1000_DEV_ID_82547EI 0x1019
-#define E1000_DEV_ID_82547EI_MOBILE 0x101A
-#define E1000_DEV_ID_82547GI 0x1075
-#define E1000_DEV_ID_82571EB_COPPER 0x105E
-#define E1000_DEV_ID_82571EB_FIBER 0x105F
-#define E1000_DEV_ID_82571EB_SERDES 0x1060
-#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9
-#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA
-#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
-#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
-#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5
-#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC
-#define E1000_DEV_ID_82572EI_COPPER 0x107D
-#define E1000_DEV_ID_82572EI_FIBER 0x107E
-#define E1000_DEV_ID_82572EI_SERDES 0x107F
-#define E1000_DEV_ID_82572EI 0x10B9
-#define E1000_DEV_ID_82573E 0x108B
-#define E1000_DEV_ID_82573E_IAMT 0x108C
-#define E1000_DEV_ID_82573L 0x109A
-#define E1000_DEV_ID_82574L 0x10D3
-#define E1000_DEV_ID_82574LA 0x10F6
-#define E1000_DEV_ID_82583V 0x150C
-#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
-#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
-#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA
-#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB
-#define E1000_DEV_ID_ICH8_82567V_3 0x1501
-#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049
-#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A
-#define E1000_DEV_ID_ICH8_IGP_C 0x104B
-#define E1000_DEV_ID_ICH8_IFE 0x104C
-#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4
-#define E1000_DEV_ID_ICH8_IFE_G 0x10C5
-#define E1000_DEV_ID_ICH8_IGP_M 0x104D
-#define E1000_DEV_ID_ICH9_IGP_M 0x10BF
-#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5
-#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB
-#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD
-#define E1000_DEV_ID_ICH9_BM 0x10E5
-#define E1000_DEV_ID_ICH9_IGP_C 0x294C
-#define E1000_DEV_ID_ICH9_IFE 0x10C0
-#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3
-#define E1000_DEV_ID_ICH9_IFE_G 0x10C2
-#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC
-#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD
-#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE
-#define E1000_DEV_ID_ICH10_HANKSVILLE 0xF0FE
-#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE
-#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF
-#define E1000_DEV_ID_ICH10_D_BM_V 0x1525
-
-#define E1000_DEV_ID_PCH_M_HV_LM 0x10EA
-#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB
-#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF
-#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0
-#define E1000_DEV_ID_PCH2_LV_LM 0x1502
-#define E1000_DEV_ID_PCH2_LV_V 0x1503
-#define E1000_DEV_ID_82576 0x10C9
-#define E1000_DEV_ID_82576_FIBER 0x10E6
-#define E1000_DEV_ID_82576_SERDES 0x10E7
-#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
-#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526
-#define E1000_DEV_ID_82576_NS 0x150A
-#define E1000_DEV_ID_82576_NS_SERDES 0x1518
-#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
-#define E1000_DEV_ID_82576_VF 0x10CA
-#define E1000_DEV_ID_82575EB_COPPER 0x10A7
-#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
-#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
-#define E1000_DEV_ID_82575GB_QUAD_COPPER_PM 0x10E2
-#define E1000_DEV_ID_82580_COPPER 0x150E
-#define E1000_DEV_ID_82580_FIBER 0x150F
-#define E1000_DEV_ID_82580_SERDES 0x1510
-#define E1000_DEV_ID_82580_SGMII 0x1511
-#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
-#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
-#define E1000_DEV_ID_DH89XXCC_SGMII 0x0436
-#define E1000_DEV_ID_DH89XXCC_SERDES 0x0438
-#define E1000_REVISION_0 0
-#define E1000_REVISION_1 1
-#define E1000_REVISION_2 2
-#define E1000_REVISION_3 3
-#define E1000_REVISION_4 4
-
-#define E1000_FUNC_0 0
-#define E1000_FUNC_1 1
-#define E1000_FUNC_2 2
-#define E1000_FUNC_3 3
-
-#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0
-#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3
-#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6
-#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9
+#define E1000_DEV_ID_82542 0x1000
+#define E1000_DEV_ID_82543GC_FIBER 0x1001
+#define E1000_DEV_ID_82543GC_COPPER 0x1004
+#define E1000_DEV_ID_82544EI_COPPER 0x1008
+#define E1000_DEV_ID_82544EI_FIBER 0x1009
+#define E1000_DEV_ID_82544GC_COPPER 0x100C
+#define E1000_DEV_ID_82544GC_LOM 0x100D
+#define E1000_DEV_ID_82540EM 0x100E
+#define E1000_DEV_ID_82540EM_LOM 0x1015
+#define E1000_DEV_ID_82540EP_LOM 0x1016
+#define E1000_DEV_ID_82540EP 0x1017
+#define E1000_DEV_ID_82540EP_LP 0x101E
+#define E1000_DEV_ID_82545EM_COPPER 0x100F
+#define E1000_DEV_ID_82545EM_FIBER 0x1011
+#define E1000_DEV_ID_82545GM_COPPER 0x1026
+#define E1000_DEV_ID_82545GM_FIBER 0x1027
+#define E1000_DEV_ID_82545GM_SERDES 0x1028
+#define E1000_DEV_ID_82546EB_COPPER 0x1010
+#define E1000_DEV_ID_82546EB_FIBER 0x1012
+#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
+#define E1000_DEV_ID_82546GB_COPPER 0x1079
+#define E1000_DEV_ID_82546GB_FIBER 0x107A
+#define E1000_DEV_ID_82546GB_SERDES 0x107B
+#define E1000_DEV_ID_82546GB_PCIE 0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
+#define E1000_DEV_ID_82541EI 0x1013
+#define E1000_DEV_ID_82541EI_MOBILE 0x1018
+#define E1000_DEV_ID_82541ER_LOM 0x1014
+#define E1000_DEV_ID_82541ER 0x1078
+#define E1000_DEV_ID_82541GI 0x1076
+#define E1000_DEV_ID_82541GI_LF 0x107C
+#define E1000_DEV_ID_82541GI_MOBILE 0x1077
+#define E1000_DEV_ID_82547EI 0x1019
+#define E1000_DEV_ID_82547EI_MOBILE 0x101A
+#define E1000_DEV_ID_82547GI 0x1075
+#define E1000_DEV_ID_82571EB_COPPER 0x105E
+#define E1000_DEV_ID_82571EB_FIBER 0x105F
+#define E1000_DEV_ID_82571EB_SERDES 0x1060
+#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9
+#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA
+#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
+#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
+#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5
+#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC
+#define E1000_DEV_ID_82572EI_COPPER 0x107D
+#define E1000_DEV_ID_82572EI_FIBER 0x107E
+#define E1000_DEV_ID_82572EI_SERDES 0x107F
+#define E1000_DEV_ID_82572EI 0x10B9
+#define E1000_DEV_ID_82573E 0x108B
+#define E1000_DEV_ID_82573E_IAMT 0x108C
+#define E1000_DEV_ID_82573L 0x109A
+#define E1000_DEV_ID_82574L 0x10D3
+#define E1000_DEV_ID_82574LA 0x10F6
+#define E1000_DEV_ID_82583V 0x150C
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
+#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
+#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA
+#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB
+#define E1000_DEV_ID_ICH8_82567V_3 0x1501
+#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049
+#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A
+#define E1000_DEV_ID_ICH8_IGP_C 0x104B
+#define E1000_DEV_ID_ICH8_IFE 0x104C
+#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4
+#define E1000_DEV_ID_ICH8_IFE_G 0x10C5
+#define E1000_DEV_ID_ICH8_IGP_M 0x104D
+#define E1000_DEV_ID_ICH9_IGP_M 0x10BF
+#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5
+#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB
+#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD
+#define E1000_DEV_ID_ICH9_BM 0x10E5
+#define E1000_DEV_ID_ICH9_IGP_C 0x294C
+#define E1000_DEV_ID_ICH9_IFE 0x10C0
+#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3
+#define E1000_DEV_ID_ICH9_IFE_G 0x10C2
+#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC
+#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD
+#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE
+#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE
+#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF
+#define E1000_DEV_ID_ICH10_D_BM_V 0x1525
+#define E1000_DEV_ID_PCH_M_HV_LM 0x10EA
+#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB
+#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF
+#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0
+#define E1000_DEV_ID_PCH2_LV_LM 0x1502
+#define E1000_DEV_ID_PCH2_LV_V 0x1503
+#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A
+#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B
+#define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A
+#define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559
+#define E1000_DEV_ID_82576 0x10C9
+#define E1000_DEV_ID_82576_FIBER 0x10E6
+#define E1000_DEV_ID_82576_SERDES 0x10E7
+#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
+#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526
+#define E1000_DEV_ID_82576_NS 0x150A
+#define E1000_DEV_ID_82576_NS_SERDES 0x1518
+#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
+#define E1000_DEV_ID_82576_VF 0x10CA
+#define E1000_DEV_ID_82576_VF_HV 0x152D
+#define E1000_DEV_ID_I350_VF 0x1520
+#define E1000_DEV_ID_I350_VF_HV 0x152F
+#define E1000_DEV_ID_82575EB_COPPER 0x10A7
+#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
+#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
+#define E1000_DEV_ID_82580_COPPER 0x150E
+#define E1000_DEV_ID_82580_FIBER 0x150F
+#define E1000_DEV_ID_82580_SERDES 0x1510
+#define E1000_DEV_ID_82580_SGMII 0x1511
+#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
+#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
+#define E1000_DEV_ID_I350_COPPER 0x1521
+#define E1000_DEV_ID_I350_FIBER 0x1522
+#define E1000_DEV_ID_I350_SERDES 0x1523
+#define E1000_DEV_ID_I350_SGMII 0x1524
+#define E1000_DEV_ID_I350_DA4 0x1546
+#define E1000_DEV_ID_I210_COPPER 0x1533
+#define E1000_DEV_ID_I210_COPPER_OEM1 0x1534
+#define E1000_DEV_ID_I210_COPPER_IT 0x1535
+#define E1000_DEV_ID_I210_FIBER 0x1536
+#define E1000_DEV_ID_I210_SERDES 0x1537
+#define E1000_DEV_ID_I210_SGMII 0x1538
+#define E1000_DEV_ID_I211_COPPER 0x1539
+#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438
+#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A
+#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C
+#define E1000_DEV_ID_DH89XXCC_SFP 0x0440
+
+#define E1000_REVISION_0 0
+#define E1000_REVISION_1 1
+#define E1000_REVISION_2 2
+#define E1000_REVISION_3 3
+#define E1000_REVISION_4 4
+
+#define E1000_FUNC_0 0
+#define E1000_FUNC_1 1
+#define E1000_FUNC_2 2
+#define E1000_FUNC_3 3
+
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9
enum e1000_mac_type {
e1000_undefined = 0,
@@ -199,10 +218,15 @@ enum e1000_mac_type {
e1000_ich10lan,
e1000_pchlan,
e1000_pch2lan,
+ e1000_pch_lpt,
e1000_82575,
e1000_82576,
e1000_82580,
+ e1000_i350,
+ e1000_i210,
+ e1000_i211,
e1000_vfadapt,
+ e1000_vfadapt_i350,
e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */
};
@@ -244,8 +268,10 @@ enum e1000_phy_type {
e1000_phy_82578,
e1000_phy_82577,
e1000_phy_82579,
+ e1000_phy_i217,
e1000_phy_82580,
e1000_phy_vf,
+ e1000_phy_i210,
};
enum e1000_bus_type {
@@ -339,9 +365,9 @@ enum e1000_serdes_link_state {
struct e1000_rx_desc {
__le64 buffer_addr; /* Address of the descriptor's data buffer */
__le16 length; /* Length of data DMAed into data buffer */
- __le16 csum; /* Packet checksum */
- u8 status; /* Descriptor status */
- u8 errors; /* Descriptor Errors */
+ __le16 csum; /* Packet checksum */
+ u8 status; /* Descriptor status */
+ u8 errors; /* Descriptor Errors */
__le16 special;
};
@@ -353,9 +379,9 @@ union e1000_rx_desc_extended {
} read;
struct {
struct {
- __le32 mrq; /* Multiple Rx Queues */
+ __le32 mrq; /* Multiple Rx Queues */
union {
- __le32 rss; /* RSS Hash */
+ __le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
@@ -365,7 +391,7 @@ union e1000_rx_desc_extended {
struct {
__le32 status_error; /* ext status/error */
__le16 length;
- __le16 vlan; /* VLAN tag */
+ __le16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
@@ -379,9 +405,9 @@ union e1000_rx_desc_packet_split {
} read;
struct {
struct {
- __le32 mrq; /* Multiple Rx Queues */
+ __le32 mrq; /* Multiple Rx Queues */
union {
- __le32 rss; /* RSS Hash */
+ __le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
@@ -390,8 +416,8 @@ union e1000_rx_desc_packet_split {
} lower;
struct {
__le32 status_error; /* ext status/error */
- __le16 length0; /* length of buffer 0 */
- __le16 vlan; /* VLAN tag */
+ __le16 length0; /* length of buffer 0 */
+ __le16 vlan; /* VLAN tag */
} middle;
struct {
__le16 header_status;
@@ -407,16 +433,16 @@ struct e1000_tx_desc {
union {
__le32 data;
struct {
- __le16 length; /* Data buffer length */
- u8 cso; /* Checksum offset */
- u8 cmd; /* Descriptor control */
+ __le16 length; /* Data buffer length */
+ u8 cso; /* Checksum offset */
+ u8 cmd; /* Descriptor control */
} flags;
} lower;
union {
__le32 data;
struct {
- u8 status; /* Descriptor status */
- u8 css; /* Checksum start */
+ u8 status; /* Descriptor status */
+ u8 css; /* Checksum start */
__le16 special;
} fields;
} upper;
@@ -427,37 +453,37 @@ struct e1000_context_desc {
union {
__le32 ip_config;
struct {
- u8 ipcss; /* IP checksum start */
- u8 ipcso; /* IP checksum offset */
- __le16 ipcse; /* IP checksum end */
+ u8 ipcss; /* IP checksum start */
+ u8 ipcso; /* IP checksum offset */
+ __le16 ipcse; /* IP checksum end */
} ip_fields;
} lower_setup;
union {
__le32 tcp_config;
struct {
- u8 tucss; /* TCP checksum start */
- u8 tucso; /* TCP checksum offset */
- __le16 tucse; /* TCP checksum end */
+ u8 tucss; /* TCP checksum start */
+ u8 tucso; /* TCP checksum offset */
+ __le16 tucse; /* TCP checksum end */
} tcp_fields;
} upper_setup;
__le32 cmd_and_length;
union {
__le32 data;
struct {
- u8 status; /* Descriptor status */
- u8 hdr_len; /* Header length */
- __le16 mss; /* Maximum segment size */
+ u8 status; /* Descriptor status */
+ u8 hdr_len; /* Header length */
+ __le16 mss; /* Maximum segment size */
} fields;
} tcp_seg_setup;
};
/* Offload data descriptor */
struct e1000_data_desc {
- __le64 buffer_addr; /* Address of the descriptor's buffer address */
+ __le64 buffer_addr; /* Address of the descriptor's buffer address */
union {
__le32 data;
struct {
- __le16 length; /* Data buffer length */
+ __le16 length; /* Data buffer length */
u8 typ_len_ext;
u8 cmd;
} flags;
@@ -465,8 +491,8 @@ struct e1000_data_desc {
union {
__le32 data;
struct {
- u8 status; /* Descriptor status */
- u8 popts; /* Packet Options */
+ u8 status; /* Descriptor status */
+ u8 popts; /* Packet Options */
__le16 special;
} fields;
} upper;
@@ -550,6 +576,10 @@ struct e1000_hw_stats {
u64 scvpc;
u64 hrmpc;
u64 doosync;
+ u64 o2bgptc;
+ u64 o2bspc;
+ u64 b2ospc;
+ u64 b2ogprc;
};
struct e1000_vf_stats {
@@ -608,7 +638,7 @@ struct e1000_host_command_header {
u8 checksum;
};
-#define E1000_HI_MAX_DATA_LENGTH 252
+#define E1000_HI_MAX_DATA_LENGTH 252
struct e1000_host_command_info {
struct e1000_host_command_header command_header;
u8 command_data[E1000_HI_MAX_DATA_LENGTH];
@@ -623,7 +653,7 @@ struct e1000_host_mng_command_header {
u16 command_length;
};
-#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
+#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
struct e1000_host_mng_command_info {
struct e1000_host_mng_command_header command_header;
u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
@@ -643,13 +673,13 @@ struct e1000_host_mng_command_info {
#include <rtems/bsd/local/e1000_mbx.h>
#endif
+/* Function pointers for the MAC. */
struct e1000_mac_operations {
- /* Function pointers for the MAC. */
s32 (*init_params)(struct e1000_hw *);
s32 (*id_led_init)(struct e1000_hw *);
s32 (*blink_led)(struct e1000_hw *);
+ bool (*check_mng_mode)(struct e1000_hw *);
s32 (*check_for_link)(struct e1000_hw *);
- bool (*check_mng_mode)(struct e1000_hw *hw);
s32 (*cleanup_led)(struct e1000_hw *);
void (*clear_hw_cntrs)(struct e1000_hw *);
void (*clear_vfta)(struct e1000_hw *);
@@ -671,13 +701,25 @@ struct e1000_mac_operations {
void (*rar_set)(struct e1000_hw *, u8*, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
s32 (*validate_mdi_setting)(struct e1000_hw *);
- s32 (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*);
- s32 (*mng_write_cmd_header)(struct e1000_hw *hw,
- struct e1000_host_mng_command_header*);
- s32 (*mng_enable_host_if)(struct e1000_hw *);
- s32 (*wait_autoneg)(struct e1000_hw *);
+ s32 (*set_obff_timer)(struct e1000_hw *, u32);
+ s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
+ void (*release_swfw_sync)(struct e1000_hw *, u16);
};
+/* When to use various PHY register access functions:
+ *
+ * Func Caller
+ * Function Does Does When to use
+ * ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * X_reg L,P,A n/a for simple PHY reg accesses
+ * X_reg_locked P,A L for multiple accesses of different regs
+ * on different pages
+ * X_reg_page A L,P for multiple accesses of different regs
+ * on the same page
+ *
+ * Where X=[read|write], L=locking, P=sets page, A=register access
+ *
+ */
struct e1000_phy_operations {
s32 (*init_params)(struct e1000_hw *);
s32 (*acquire)(struct e1000_hw *);
@@ -689,18 +731,24 @@ struct e1000_phy_operations {
s32 (*get_cfg_done)(struct e1000_hw *hw);
s32 (*get_cable_length)(struct e1000_hw *);
s32 (*get_info)(struct e1000_hw *);
+ s32 (*set_page)(struct e1000_hw *, u16);
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
+ s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *);
void (*release)(struct e1000_hw *);
s32 (*reset)(struct e1000_hw *);
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
s32 (*write_reg)(struct e1000_hw *, u32, u16);
s32 (*write_reg_locked)(struct e1000_hw *, u32, u16);
+ s32 (*write_reg_page)(struct e1000_hw *, u32, u16);
void (*power_up)(struct e1000_hw *);
void (*power_down)(struct e1000_hw *);
+ s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
+ s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
};
+/* Function pointers for the NVM. */
struct e1000_nvm_operations {
s32 (*init_params)(struct e1000_hw *);
s32 (*acquire)(struct e1000_hw *);
@@ -715,8 +763,8 @@ struct e1000_nvm_operations {
struct e1000_mac_info {
struct e1000_mac_operations ops;
- u8 addr[6];
- u8 perm_addr[6];
+ u8 addr[ETH_ADDR_LEN];
+ u8 perm_addr[ETH_ADDR_LEN];
enum e1000_mac_type type;
@@ -755,6 +803,7 @@ struct e1000_mac_info {
enum e1000_serdes_link_state serdes_link_state;
bool serdes_has_link;
bool tx_pkt_filtering;
+ u32 max_frame_size;
};
struct e1000_phy_info {
@@ -786,7 +835,6 @@ struct e1000_phy_info {
bool disable_polarity_correction;
bool is_mdix;
bool polarity_correction;
- bool reset_disable;
bool speed_downgraded;
bool autoneg_wait_to_complete;
};
@@ -816,14 +864,14 @@ struct e1000_bus_info {
};
struct e1000_fc_info {
- u32 high_water; /* Flow control high-water mark */
- u32 low_water; /* Flow control low-water mark */
- u16 pause_time; /* Flow control pause timer */
- u16 refresh_time; /* Flow control refresh timer */
- bool send_xon; /* Flow control send XON */
- bool strict_ieee; /* Strict IEEE mode */
- enum e1000_fc_mode current_mode; /* FC mode in effect */
- enum e1000_fc_mode requested_mode; /* FC mode requested by caller */
+ u32 high_water; /* Flow control high-water mark */
+ u32 low_water; /* Flow control low-water mark */
+ u16 pause_time; /* Flow control pause timer */
+ u16 refresh_time; /* Flow control refresh timer */
+ bool send_xon; /* Flow control send XON */
+ bool strict_ieee; /* Strict IEEE mode */
+ enum e1000_fc_mode current_mode; /* FC mode in effect */
+ enum e1000_fc_mode requested_mode; /* FC mode requested by caller */
};
struct e1000_mbx_operations {
@@ -895,16 +943,22 @@ struct e1000_dev_spec_ich8lan {
E1000_MUTEX swflag_mutex;
bool nvm_k1_enabled;
bool eee_disable;
+ u16 eee_lp_ability;
};
struct e1000_dev_spec_82575 {
bool sgmii_active;
bool global_device_reset;
+ bool eee_disable;
+ bool module_plugged;
+ bool clear_semaphore_once;
+ u32 mtu;
+ struct sfp_e1000_flags eth_flags;
};
struct e1000_dev_spec_vf {
- u32 vf_number;
- u32 v2p_mailbox;
+ u32 vf_number;
+ u32 v2p_mailbox;
};
struct e1000_hw {
@@ -923,14 +977,14 @@ struct e1000_hw {
struct e1000_host_mng_dhcp_cookie mng_cookie;
union {
- struct e1000_dev_spec_82541 _82541;
- struct e1000_dev_spec_82542 _82542;
- struct e1000_dev_spec_82543 _82543;
- struct e1000_dev_spec_82571 _82571;
+ struct e1000_dev_spec_82541 _82541;
+ struct e1000_dev_spec_82542 _82542;
+ struct e1000_dev_spec_82543 _82543;
+ struct e1000_dev_spec_82571 _82571;
struct e1000_dev_spec_80003es2lan _80003es2lan;
- struct e1000_dev_spec_ich8lan ich8lan;
- struct e1000_dev_spec_82575 _82575;
- struct e1000_dev_spec_vf vf;
+ struct e1000_dev_spec_ich8lan ich8lan;
+ struct e1000_dev_spec_82575 _82575;
+ struct e1000_dev_spec_vf vf;
} dev_spec;
u16 device_id;
@@ -948,6 +1002,7 @@ struct e1000_hw {
#include <dev/e1000/e1000_80003es2lan.h>
#include <dev/e1000/e1000_ich8lan.h>
#include <dev/e1000/e1000_82575.h>
+#include <dev/e1000/e1000_i210.h>
#else
#include <rtems/bsd/local/e1000_82541.h>
#include <rtems/bsd/local/e1000_82543.h>
@@ -955,7 +1010,8 @@ struct e1000_hw {
#include <rtems/bsd/local/e1000_80003es2lan.h>
#include <rtems/bsd/local/e1000_ich8lan.h>
#include <rtems/bsd/local/e1000_82575.h>
-#endif
+#include <rtems/bsd/local/e1000_i210.h>
+#endif /* __rtems__ */
/* These functions must be implemented by drivers */
void e1000_pci_clear_mwi(struct e1000_hw *hw);
diff --git a/freebsd/sys/dev/e1000/e1000_i210.h b/freebsd/sys/dev/e1000/e1000_i210.h
new file mode 100644
index 00000000..d7711fe0
--- /dev/null
+++ b/freebsd/sys/dev/e1000/e1000_i210.h
@@ -0,0 +1,92 @@
+/******************************************************************************
+
+ Copyright (c) 2001-2013, Intel Corporation
+ 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.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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$*/
+
+#ifndef _E1000_I210_H_
+#define _E1000_I210_H_
+
+s32 e1000_update_flash_i210(struct e1000_hw *hw);
+s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw);
+s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw);
+s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data);
+s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data);
+s32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data);
+s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
+void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
+
+#define E1000_STM_OPCODE 0xDB00
+#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
+
+#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \
+ (u8)((invm_dword) & 0x7)
+#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \
+ (u8)(((invm_dword) & 0x0000FE00) >> 9)
+#define INVM_DWORD_TO_WORD_DATA(invm_dword) \
+ (u16)(((invm_dword) & 0xFFFF0000) >> 16)
+
+enum E1000_INVM_STRUCTURE_TYPE {
+ E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00,
+ E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01,
+ E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02,
+ E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03,
+ E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04,
+ E1000_INVM_INVALIDATED_STRUCTURE = 0x0F,
+};
+
+#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8
+#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1
+#define E1000_INVM_ULT_BYTES_SIZE 8
+#define E1000_INVM_RECORD_SIZE_IN_BYTES 4
+#define E1000_INVM_VER_FIELD_ONE 0x1FF8
+#define E1000_INVM_VER_FIELD_TWO 0x7FE000
+#define E1000_INVM_IMGTYPE_FIELD 0x1F800000
+
+#define E1000_INVM_MAJOR_MASK 0x3F0
+#define E1000_INVM_MINOR_MASK 0xF
+#define E1000_INVM_MAJOR_SHIFT 4
+
+#define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \
+ (ID_LED_DEF1_DEF2 << 4) | \
+ (ID_LED_OFF1_OFF2))
+#define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \
+ (ID_LED_DEF1_DEF2 << 4) | \
+ (ID_LED_DEF1_DEF2))
+
+/* NVM offset defaults for I211 devices */
+#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243
+#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1
+#define NVM_LED_1_CFG_DEFAULT_I211 0x0184
+#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C
+#endif
diff --git a/freebsd/sys/dev/e1000/e1000_ich8lan.c b/freebsd/sys/dev/e1000/e1000_ich8lan.c
index 6bf287c8..44e09538 100644
--- a/freebsd/sys/dev/e1000/e1000_ich8lan.c
+++ b/freebsd/sys/dev/e1000/e1000_ich8lan.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -34,8 +34,7 @@
******************************************************************************/
/*$FreeBSD$*/
-/*
- * 82562G 10/100 Network Connection
+/* 82562G 10/100 Network Connection
* 82562G-2 10/100 Network Connection
* 82562GT 10/100 Network Connection
* 82562GT-2 10/100 Network Connection
@@ -70,10 +69,6 @@
#include <rtems/bsd/local/e1000_api.h>
#endif
-static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw);
-static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw);
-static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw);
-static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw);
static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw);
static void e1000_release_swflag_ich8lan(struct e1000_hw *hw);
static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw);
@@ -81,29 +76,34 @@ static void e1000_release_nvm_ich8lan(struct e1000_hw *hw);
static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
+static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index);
+static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw,
+ u8 *mc_addr_list,
+ u32 mc_addr_count);
static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw);
static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw);
static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw,
- bool active);
+ bool active);
static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw,
- bool active);
+ bool active);
static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
+ u16 words, u16 *data);
static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
+ u16 words, u16 *data);
static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw);
static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw);
static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw,
- u16 *data);
+ u16 *data);
static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw);
static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw);
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw);
static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw);
static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);
static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
+static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw);
static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw,
- u16 *speed, u16 *duplex);
+ u16 *speed, u16 *duplex);
static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
static s32 e1000_led_on_ich8lan(struct e1000_hw *hw);
static s32 e1000_led_off_ich8lan(struct e1000_hw *hw);
@@ -114,44 +114,37 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);
-static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout);
-static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw);
static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw,
- u32 offset, u8 *data);
+ u32 offset, u8 *data);
static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
- u8 size, u16 *data);
+ u8 size, u16 *data);
static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw,
- u32 offset, u16 *data);
+ u32 offset, u16 *data);
static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
- u32 offset, u8 byte);
-static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw,
- u32 offset, u8 data);
-static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
- u8 size, u16 data);
+ u32 offset, u8 byte);
static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);
static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw);
-static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
-static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw);
static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
+static s32 e1000_set_obff_timer_pch_lpt(struct e1000_hw *hw, u32 itr);
/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
/* Offset 04h HSFSTS */
union ich8_hws_flash_status {
struct ich8_hsfsts {
- u16 flcdone :1; /* bit 0 Flash Cycle Done */
- u16 flcerr :1; /* bit 1 Flash Cycle Error */
- u16 dael :1; /* bit 2 Direct Access error Log */
- u16 berasesz :2; /* bit 4:3 Sector Erase Size */
- u16 flcinprog :1; /* bit 5 flash cycle in Progress */
- u16 reserved1 :2; /* bit 13:6 Reserved */
- u16 reserved2 :6; /* bit 13:6 Reserved */
- u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */
- u16 flockdn :1; /* bit 15 Flash Config Lock-Down */
+ u16 flcdone:1; /* bit 0 Flash Cycle Done */
+ u16 flcerr:1; /* bit 1 Flash Cycle Error */
+ u16 dael:1; /* bit 2 Direct Access error Log */
+ u16 berasesz:2; /* bit 4:3 Sector Erase Size */
+ u16 flcinprog:1; /* bit 5 flash cycle in Progress */
+ u16 reserved1:2; /* bit 13:6 Reserved */
+ u16 reserved2:6; /* bit 13:6 Reserved */
+ u16 fldesvalid:1; /* bit 14 Flash Descriptor Valid */
+ u16 flockdn:1; /* bit 15 Flash Config Lock-Down */
} hsf_status;
u16 regval;
};
@@ -160,11 +153,11 @@ union ich8_hws_flash_status {
/* Offset 06h FLCTL */
union ich8_hws_flash_ctrl {
struct ich8_hsflctl {
- u16 flcgo :1; /* 0 Flash Cycle Go */
- u16 flcycle :2; /* 2:1 Flash Cycle */
- u16 reserved :5; /* 7:3 Reserved */
- u16 fldbcount :2; /* 9:8 Flash Data Byte Count */
- u16 flockdn :6; /* 15:10 Reserved */
+ u16 flcgo:1; /* 0 Flash Cycle Go */
+ u16 flcycle:2; /* 2:1 Flash Cycle */
+ u16 reserved:5; /* 7:3 Reserved */
+ u16 fldbcount:2; /* 9:8 Flash Data Byte Count */
+ u16 flockdn:6; /* 15:10 Reserved */
} hsf_ctrl;
u16 regval;
};
@@ -172,115 +165,268 @@ union ich8_hws_flash_ctrl {
/* ICH Flash Region Access Permissions */
union ich8_hws_flash_regacc {
struct ich8_flracc {
- u32 grra :8; /* 0:7 GbE region Read Access */
- u32 grwa :8; /* 8:15 GbE region Write Access */
- u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */
- u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */
+ u32 grra:8; /* 0:7 GbE region Read Access */
+ u32 grwa:8; /* 8:15 GbE region Write Access */
+ u32 gmrag:8; /* 23:16 GbE Master Read Access Grant */
+ u32 gmwag:8; /* 31:24 GbE Master Write Access Grant */
} hsf_flregacc;
u16 regval;
};
/**
- * e1000_init_phy_params_pchlan - Initialize PHY function pointers
+ * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers
* @hw: pointer to the HW structure
*
- * Initialize family-specific PHY parameters and function pointers.
+ * Test access to the PHY registers by reading the PHY ID registers. If
+ * the PHY ID is already known (e.g. resume path) compare it with known ID,
+ * otherwise assume the read PHY ID is correct if it is valid.
+ *
+ * Assumes the sw/fw/hw semaphore is already acquired.
**/
-static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
+static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
{
- struct e1000_phy_info *phy = &hw->phy;
- u32 ctrl, fwsm;
- s32 ret_val = E1000_SUCCESS;
+ u16 phy_reg = 0;
+ u32 phy_id = 0;
+ s32 ret_val;
+ u16 retry_count;
- DEBUGFUNC("e1000_init_phy_params_pchlan");
+ for (retry_count = 0; retry_count < 2; retry_count++) {
+ ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_reg);
+ if (ret_val || (phy_reg == 0xFFFF))
+ continue;
+ phy_id = (u32)(phy_reg << 16);
+
+ ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_reg);
+ if (ret_val || (phy_reg == 0xFFFF)) {
+ phy_id = 0;
+ continue;
+ }
+ phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
+ break;
+ }
+
+ if (hw->phy.id) {
+ if (hw->phy.id == phy_id)
+ return TRUE;
+ } else if (phy_id) {
+ hw->phy.id = phy_id;
+ hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK);
+ return TRUE;
+ }
- phy->addr = 1;
- phy->reset_delay_us = 100;
-
- phy->ops.acquire = e1000_acquire_swflag_ich8lan;
- phy->ops.check_reset_block = e1000_check_reset_block_ich8lan;
- phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan;
- phy->ops.read_reg = e1000_read_phy_reg_hv;
- phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked;
- phy->ops.release = e1000_release_swflag_ich8lan;
- phy->ops.reset = e1000_phy_hw_reset_ich8lan;
- phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
- phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
- phy->ops.write_reg = e1000_write_phy_reg_hv;
- phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
- phy->ops.power_up = e1000_power_up_phy_copper;
- phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-
- /*
- * The MAC-PHY interconnect may still be in SMBus mode
- * after Sx->S0. If the manageability engine (ME) is
- * disabled, then toggle the LANPHYPC Value bit to force
- * the interconnect to PCIe mode.
+ /* In case the PHY needs to be in mdio slow mode,
+ * set slow mode and try to get the PHY id again.
*/
- fwsm = E1000_READ_REG(hw, E1000_FWSM);
- if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) {
- ctrl = E1000_READ_REG(hw, E1000_CTRL);
- ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
- ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
- E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
- usec_delay(10);
- ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
- E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
- msec_delay(50);
+ hw->phy.ops.release(hw);
+ ret_val = e1000_set_mdio_slow_mode_hv(hw);
+ if (!ret_val)
+ ret_val = e1000_get_phy_id(hw);
+ hw->phy.ops.acquire(hw);
- /*
- * Gate automatic PHY configuration by hardware on
- * non-managed 82579
+ return !ret_val;
+}
+
+/**
+ * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds
+ * @hw: pointer to the HW structure
+ *
+ * Workarounds/flow necessary for PHY initialization during driver load
+ * and resume paths.
+ **/
+static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
+{
+ u32 mac_reg, fwsm = E1000_READ_REG(hw, E1000_FWSM);
+ s32 ret_val;
+ u16 phy_reg;
+
+ DEBUGFUNC("e1000_init_phy_workarounds_pchlan");
+
+ /* Gate automatic PHY configuration by hardware on managed and
+ * non-managed 82579 and newer adapters.
+ */
+ e1000_gate_hw_phy_config_ich8lan(hw, TRUE);
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ DEBUGOUT("Failed to initialize PHY flow\n");
+ goto out;
+ }
+
+ /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is
+ * inaccessible and resetting the PHY is not blocked, toggle the
+ * LANPHYPC Value bit to force the interconnect to PCIe mode.
+ */
+ switch (hw->mac.type) {
+ case e1000_pch_lpt:
+ if (e1000_phy_is_accessible_pchlan(hw))
+ break;
+
+ /* Before toggling LANPHYPC, see if PHY is accessible by
+ * forcing MAC to SMBus mode first.
*/
- if (hw->mac.type == e1000_pch2lan)
- e1000_gate_hw_phy_config_ich8lan(hw, TRUE);
+ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+
+ /* fall-through */
+ case e1000_pch2lan:
+ if (e1000_phy_is_accessible_pchlan(hw)) {
+ if (hw->mac.type == e1000_pch_lpt) {
+ /* Unforce SMBus mode in PHY */
+ hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL,
+ &phy_reg);
+ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL,
+ phy_reg);
+
+ /* Unforce SMBus mode in MAC */
+ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+ }
+ break;
+ }
+
+ /* fall-through */
+ case e1000_pchlan:
+ if ((hw->mac.type == e1000_pchlan) &&
+ (fwsm & E1000_ICH_FWSM_FW_VALID))
+ break;
+
+ if (hw->phy.ops.check_reset_block(hw)) {
+ DEBUGOUT("Required LANPHYPC toggle blocked by ME\n");
+ break;
+ }
+
+ DEBUGOUT("Toggling LANPHYPC\n");
+
+ /* Set Phy Config Counter to 50msec */
+ mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM3);
+ mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ E1000_WRITE_REG(hw, E1000_FEXTNVM3, mac_reg);
+
+ if (hw->mac.type == e1000_pch_lpt) {
+ /* Toggling LANPHYPC brings the PHY out of SMBus mode
+ * So ensure that the MAC is also out of SMBus mode
+ */
+ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+ }
+
+ /* Toggle LANPHYPC Value bit */
+ mac_reg = E1000_READ_REG(hw, E1000_CTRL);
+ mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
+ mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE;
+ E1000_WRITE_REG(hw, E1000_CTRL, mac_reg);
+ E1000_WRITE_FLUSH(hw);
+ usec_delay(10);
+ mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+ E1000_WRITE_REG(hw, E1000_CTRL, mac_reg);
+ E1000_WRITE_FLUSH(hw);
+ if (hw->mac.type < e1000_pch_lpt) {
+ msec_delay(50);
+ } else {
+ u16 count = 20;
+ do {
+ msec_delay(5);
+ } while (!(E1000_READ_REG(hw, E1000_CTRL_EXT) &
+ E1000_CTRL_EXT_LPCD) && count--);
+ }
+ break;
+ default:
+ break;
}
- /*
- * Reset the PHY before any acccess to it. Doing so, ensures that
- * the PHY is in a known good state before we read/write PHY registers.
- * The generic reset is sufficient here, because we haven't determined
- * the PHY type yet.
+ hw->phy.ops.release(hw);
+
+ /* Reset the PHY before any access to it. Doing so, ensures
+ * that the PHY is in a known good state before we read/write
+ * PHY registers. The generic reset is sufficient here,
+ * because we haven't determined the PHY type yet.
*/
ret_val = e1000_phy_hw_reset_generic(hw);
- if (ret_val)
- goto out;
+out:
/* Ungate automatic PHY configuration on non-managed 82579 */
- if ((hw->mac.type == e1000_pch2lan) &&
+ if ((hw->mac.type == e1000_pch2lan) &&
!(fwsm & E1000_ICH_FWSM_FW_VALID)) {
msec_delay(10);
e1000_gate_hw_phy_config_ich8lan(hw, FALSE);
}
+ return ret_val;
+}
+
+/**
+ * e1000_init_phy_params_pchlan - Initialize PHY function pointers
+ * @hw: pointer to the HW structure
+ *
+ * Initialize family-specific PHY parameters and function pointers.
+ **/
+static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+
+ DEBUGFUNC("e1000_init_phy_params_pchlan");
+
+ phy->addr = 1;
+ phy->reset_delay_us = 100;
+
+ phy->ops.acquire = e1000_acquire_swflag_ich8lan;
+ phy->ops.check_reset_block = e1000_check_reset_block_ich8lan;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan;
+ phy->ops.set_page = e1000_set_page_igp;
+ phy->ops.read_reg = e1000_read_phy_reg_hv;
+ phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked;
+ phy->ops.read_reg_page = e1000_read_phy_reg_page_hv;
+ phy->ops.release = e1000_release_swflag_ich8lan;
+ phy->ops.reset = e1000_phy_hw_reset_ich8lan;
+ phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
+ phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
+ phy->ops.write_reg = e1000_write_phy_reg_hv;
+ phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
+ phy->ops.write_reg_page = e1000_write_phy_reg_page_hv;
+ phy->ops.power_up = e1000_power_up_phy_copper;
+ phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
phy->id = e1000_phy_unknown;
- switch (hw->mac.type) {
- default:
- ret_val = e1000_get_phy_id(hw);
- if (ret_val)
- goto out;
- if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
+ if (ret_val)
+ return ret_val;
+
+ if (phy->id == e1000_phy_unknown)
+ switch (hw->mac.type) {
+ default:
+ ret_val = e1000_get_phy_id(hw);
+ if (ret_val)
+ return ret_val;
+ if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+ break;
+ /* fall-through */
+ case e1000_pch2lan:
+ case e1000_pch_lpt:
+ /* In case the PHY needs to be in mdio slow mode,
+ * set slow mode and try to get the PHY id again.
+ */
+ ret_val = e1000_set_mdio_slow_mode_hv(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_get_phy_id(hw);
+ if (ret_val)
+ return ret_val;
break;
- /* fall-through */
- case e1000_pch2lan:
- /*
- * In case the PHY needs to be in mdio slow mode,
- * set slow mode and try to get the PHY id again.
- */
- ret_val = e1000_set_mdio_slow_mode_hv(hw);
- if (ret_val)
- goto out;
- ret_val = e1000_get_phy_id(hw);
- if (ret_val)
- goto out;
- break;
- }
+ }
phy->type = e1000_get_phy_type_from_id(phy->id);
switch (phy->type) {
case e1000_phy_82577:
case e1000_phy_82579:
+ case e1000_phy_i217:
phy->ops.check_polarity = e1000_check_polarity_82577;
phy->ops.force_speed_duplex =
e1000_phy_force_speed_duplex_82577;
@@ -299,7 +445,6 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
break;
}
-out:
return ret_val;
}
@@ -312,29 +457,28 @@ out:
static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 i = 0;
DEBUGFUNC("e1000_init_phy_params_ich8lan");
- phy->addr = 1;
- phy->reset_delay_us = 100;
-
- phy->ops.acquire = e1000_acquire_swflag_ich8lan;
- phy->ops.check_reset_block = e1000_check_reset_block_ich8lan;
- phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
- phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan;
- phy->ops.read_reg = e1000_read_phy_reg_igp;
- phy->ops.release = e1000_release_swflag_ich8lan;
- phy->ops.reset = e1000_phy_hw_reset_ich8lan;
- phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan;
- phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan;
- phy->ops.write_reg = e1000_write_phy_reg_igp;
- phy->ops.power_up = e1000_power_up_phy_copper;
- phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
-
- /*
- * We may need to do this twice - once for IGP and if that fails,
+ phy->addr = 1;
+ phy->reset_delay_us = 100;
+
+ phy->ops.acquire = e1000_acquire_swflag_ich8lan;
+ phy->ops.check_reset_block = e1000_check_reset_block_ich8lan;
+ phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan;
+ phy->ops.read_reg = e1000_read_phy_reg_igp;
+ phy->ops.release = e1000_release_swflag_ich8lan;
+ phy->ops.reset = e1000_phy_hw_reset_ich8lan;
+ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan;
+ phy->ops.write_reg = e1000_write_phy_reg_igp;
+ phy->ops.power_up = e1000_power_up_phy_copper;
+ phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
+
+ /* We may need to do this twice - once for IGP and if that fails,
* we'll set BM func pointers and try again
*/
ret_val = e1000_determine_phy_address(hw);
@@ -344,7 +488,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
ret_val = e1000_determine_phy_address(hw);
if (ret_val) {
DEBUGOUT("Cannot determine PHY addr. Erroring out\n");
- goto out;
+ return ret_val;
}
}
@@ -354,7 +498,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
msec_delay(1);
ret_val = e1000_get_phy_id(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
/* Verify phy id */
@@ -388,12 +532,11 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
break;
default:
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
+ break;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -408,7 +551,6 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
struct e1000_nvm_info *nvm = &hw->nvm;
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 gfpreg, sector_base_addr, sector_end_addr;
- s32 ret_val = E1000_SUCCESS;
u16 i;
DEBUGFUNC("e1000_init_nvm_params_ich8lan");
@@ -416,16 +558,14 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
/* Can't read flash registers if the register set isn't mapped. */
if (!hw->flash_address) {
DEBUGOUT("ERROR: Flash registers not mapped\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
nvm->type = e1000_nvm_flash_sw;
gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
- /*
- * sector_X_addr is a "sector"-aligned address (4096 bytes)
+ /* sector_X_addr is a "sector"-aligned address (4096 bytes)
* Add 1 to sector_end_addr since this sector is included in
* the overall size.
*/
@@ -435,12 +575,11 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
/* flash_base_addr is byte-aligned */
nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
- /*
- * find total size of the NVM, then cut in half since the total
+ /* find total size of the NVM, then cut in half since the total
* size represents two separate NVM banks.
*/
nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
- << FLASH_SECTOR_ADDR_SHIFT;
+ << FLASH_SECTOR_ADDR_SHIFT;
nvm->flash_bank_size /= 2;
/* Adjust to word count */
nvm->flash_bank_size /= sizeof(u16);
@@ -457,16 +596,15 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
E1000_MUTEX_INIT(&dev_spec->swflag_mutex);
/* Function Pointers */
- nvm->ops.acquire = e1000_acquire_nvm_ich8lan;
- nvm->ops.release = e1000_release_nvm_ich8lan;
- nvm->ops.read = e1000_read_nvm_ich8lan;
- nvm->ops.update = e1000_update_nvm_checksum_ich8lan;
+ nvm->ops.acquire = e1000_acquire_nvm_ich8lan;
+ nvm->ops.release = e1000_release_nvm_ich8lan;
+ nvm->ops.read = e1000_read_nvm_ich8lan;
+ nvm->ops.update = e1000_update_nvm_checksum_ich8lan;
nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan;
- nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan;
- nvm->ops.write = e1000_write_nvm_ich8lan;
+ nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan;
+ nvm->ops.write = e1000_write_nvm_ich8lan;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -479,7 +617,6 @@ out:
static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
- u16 pci_cfg;
DEBUGFUNC("e1000_init_mac_params_ich8lan");
@@ -524,7 +661,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
/* clear hardware counters */
mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan;
- /* LED operations */
+ /* LED and other operations */
switch (mac->type) {
case e1000_ich8lan:
case e1000_ich9lan:
@@ -547,10 +684,11 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES;
mac->ops.rar_set = e1000_rar_set_pch2lan;
/* fall-through */
+ case e1000_pch_lpt:
+ /* multicast address update for pch2 */
+ mac->ops.update_mc_addr_list =
+ e1000_update_mc_addr_list_pch2lan;
case e1000_pchlan:
- /* save PCH revision_id */
- e1000_read_pci_cfg(hw, 0x2, &pci_cfg);
- hw->revision_id = (u8)(pci_cfg &= 0x000F);
/* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
/* ID LED init */
@@ -567,50 +705,386 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
break;
}
+ if (mac->type == e1000_pch_lpt) {
+ mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
+ mac->ops.rar_set = e1000_rar_set_pch_lpt;
+ mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt;
+ mac->ops.set_obff_timer = e1000_set_obff_timer_pch_lpt;
+ }
+
/* Enable PCS Lock-loss workaround for ICH8 */
if (mac->type == e1000_ich8lan)
e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, TRUE);
- /* Gate automatic PHY configuration by hardware on managed 82579 */
- if ((mac->type == e1000_pch2lan) &&
- (E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID))
- e1000_gate_hw_phy_config_ich8lan(hw, TRUE);
-
return E1000_SUCCESS;
}
/**
+ * __e1000_access_emi_reg_locked - Read/write EMI register
+ * @hw: pointer to the HW structure
+ * @addr: EMI address to program
+ * @data: pointer to value to read/write from/to the EMI address
+ * @read: boolean flag to indicate read or write
+ *
+ * This helper function assumes the SW/FW/HW Semaphore is already acquired.
+ **/
+static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address,
+ u16 *data, bool read)
+{
+ s32 ret_val;
+
+ DEBUGFUNC("__e1000_access_emi_reg_locked");
+
+ ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, address);
+ if (ret_val)
+ return ret_val;
+
+ if (read)
+ ret_val = hw->phy.ops.read_reg_locked(hw, I82579_EMI_DATA,
+ data);
+ else
+ ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA,
+ *data);
+
+ return ret_val;
+}
+
+/**
+ * e1000_read_emi_reg_locked - Read Extended Management Interface register
+ * @hw: pointer to the HW structure
+ * @addr: EMI address to program
+ * @data: value to be read from the EMI address
+ *
+ * Assumes the SW/FW/HW Semaphore is already acquired.
+ **/
+s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data)
+{
+ DEBUGFUNC("e1000_read_emi_reg_locked");
+
+ return __e1000_access_emi_reg_locked(hw, addr, data, TRUE);
+}
+
+/**
+ * e1000_write_emi_reg_locked - Write Extended Management Interface register
+ * @hw: pointer to the HW structure
+ * @addr: EMI address to program
+ * @data: value to be written to the EMI address
+ *
+ * Assumes the SW/FW/HW Semaphore is already acquired.
+ **/
+static s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data)
+{
+ DEBUGFUNC("e1000_read_emi_reg_locked");
+
+ return __e1000_access_emi_reg_locked(hw, addr, &data, FALSE);
+}
+
+/**
* e1000_set_eee_pchlan - Enable/disable EEE support
* @hw: pointer to the HW structure
*
- * Enable/disable EEE based on setting in dev_spec structure. The bits in
- * the LPI Control register will remain set only if/when link is up.
+ * Enable/disable EEE based on setting in dev_spec structure, the duplex of
+ * the link and the EEE capabilities of the link partner. The LPI Control
+ * register bits will remain set only if/when link is up.
**/
static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
- u16 phy_reg;
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ s32 ret_val;
+ u16 lpi_ctrl;
DEBUGFUNC("e1000_set_eee_pchlan");
- if (hw->phy.type != e1000_phy_82579)
- goto out;
+ if ((hw->phy.type != e1000_phy_82579) &&
+ (hw->phy.type != e1000_phy_i217))
+ return E1000_SUCCESS;
- ret_val = hw->phy.ops.read_reg(hw, I82579_LPI_CTRL, &phy_reg);
+ ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
- if (hw->dev_spec.ich8lan.eee_disable)
- phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK;
- else
- phy_reg |= I82579_LPI_CTRL_ENABLE_MASK;
+ ret_val = hw->phy.ops.read_reg_locked(hw, I82579_LPI_CTRL, &lpi_ctrl);
+ if (ret_val)
+ goto release;
+
+ /* Clear bits that enable EEE in various speeds */
+ lpi_ctrl &= ~I82579_LPI_CTRL_ENABLE_MASK;
+
+ /* Enable EEE if not disabled by user */
+ if (!dev_spec->eee_disable) {
+ u16 lpa, pcs_status, data;
+
+ /* Save off link partner's EEE ability */
+ switch (hw->phy.type) {
+ case e1000_phy_82579:
+ lpa = I82579_EEE_LP_ABILITY;
+ pcs_status = I82579_EEE_PCS_STATUS;
+ break;
+ case e1000_phy_i217:
+ lpa = I217_EEE_LP_ABILITY;
+ pcs_status = I217_EEE_PCS_STATUS;
+ break;
+ default:
+ ret_val = -E1000_ERR_PHY;
+ goto release;
+ }
+ ret_val = e1000_read_emi_reg_locked(hw, lpa,
+ &dev_spec->eee_lp_ability);
+ if (ret_val)
+ goto release;
+
+ /* Enable EEE only for speeds in which the link partner is
+ * EEE capable.
+ */
+ if (dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED)
+ lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE;
+
+ if (dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) {
+ hw->phy.ops.read_reg_locked(hw, PHY_LP_ABILITY, &data);
+ if (data & NWAY_LPAR_100TX_FD_CAPS)
+ lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE;
+ else
+ /* EEE is not supported in 100Half, so ignore
+ * partner's EEE in 100 ability if full-duplex
+ * is not advertised.
+ */
+ dev_spec->eee_lp_ability &=
+ ~I82579_EEE_100_SUPPORTED;
+ }
+
+ /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */
+ ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data);
+ if (ret_val)
+ goto release;
+ }
+
+ ret_val = hw->phy.ops.write_reg_locked(hw, I82579_LPI_CTRL, lpi_ctrl);
+release:
+ hw->phy.ops.release(hw);
- ret_val = hw->phy.ops.write_reg(hw, I82579_LPI_CTRL, phy_reg);
-out:
return ret_val;
}
/**
+ * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP
+ * @hw: pointer to the HW structure
+ * @link: link up bool flag
+ *
+ * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
+ * preventing further DMA write requests. Workaround the issue by disabling
+ * the de-assertion of the clock request when in 1Gpbs mode.
+ **/
+static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
+{
+ u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
+ s32 ret_val = E1000_SUCCESS;
+
+ if (link && (E1000_READ_REG(hw, E1000_STATUS) &
+ E1000_STATUS_SPEED_1000)) {
+ u16 kmrn_reg;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val =
+ e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
+ &kmrn_reg);
+ if (ret_val)
+ goto release;
+
+ ret_val =
+ e1000_write_kmrn_reg_locked(hw,
+ E1000_KMRNCTRLSTA_K1_CONFIG,
+ kmrn_reg &
+ ~E1000_KMRNCTRLSTA_K1_ENABLE);
+ if (ret_val)
+ goto release;
+
+ usec_delay(10);
+
+ E1000_WRITE_REG(hw, E1000_FEXTNVM6,
+ fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK);
+
+ ret_val =
+ e1000_write_kmrn_reg_locked(hw,
+ E1000_KMRNCTRLSTA_K1_CONFIG,
+ kmrn_reg);
+release:
+ hw->phy.ops.release(hw);
+ } else {
+ /* clear FEXTNVM6 bit 8 on link down or 10/100 */
+ E1000_WRITE_REG(hw, E1000_FEXTNVM6,
+ fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
+ }
+
+ return ret_val;
+}
+
+static u64 e1000_ltr2ns(u16 ltr)
+{
+ u32 value, scale;
+
+ /* Determine the latency in nsec based on the LTR value & scale */
+ value = ltr & E1000_LTRV_VALUE_MASK;
+ scale = (ltr & E1000_LTRV_SCALE_MASK) >> E1000_LTRV_SCALE_SHIFT;
+
+ return value * (1 << (scale * E1000_LTRV_SCALE_FACTOR));
+}
+
+/**
+ * e1000_platform_pm_pch_lpt - Set platform power management values
+ * @hw: pointer to the HW structure
+ * @link: bool indicating link status
+ *
+ * Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like"
+ * GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed
+ * when link is up (which must not exceed the maximum latency supported
+ * by the platform), otherwise specify there is no LTR requirement.
+ * Unlike TRUE-PCIe devices which set the LTR maximum snoop/no-snoop
+ * latencies in the LTR Extended Capability Structure in the PCIe Extended
+ * Capability register set, on this device LTR is set by writing the
+ * equivalent snoop/no-snoop latencies in the LTRV register in the MAC and
+ * set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB)
+ * message to the PMC.
+ *
+ * Use the LTR value to calculate the Optimized Buffer Flush/Fill (OBFF)
+ * high-water mark.
+ **/
+static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
+{
+ u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) |
+ link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND;
+ u16 lat_enc = 0; /* latency encoded */
+ s32 obff_hwm = 0;
+
+ DEBUGFUNC("e1000_platform_pm_pch_lpt");
+
+ if (link) {
+ u16 speed, duplex, scale = 0;
+ u16 max_snoop, max_nosnoop;
+ u16 max_ltr_enc; /* max LTR latency encoded */
+ s64 lat_ns; /* latency (ns) */
+ s64 value;
+ u32 rxa;
+
+ if (!hw->mac.max_frame_size) {
+ DEBUGOUT("max_frame_size not set.\n");
+ return -E1000_ERR_CONFIG;
+ }
+
+ hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
+ if (!speed) {
+ DEBUGOUT("Speed not set.\n");
+ return -E1000_ERR_CONFIG;
+ }
+
+ /* Rx Packet Buffer Allocation size (KB) */
+ rxa = E1000_READ_REG(hw, E1000_PBA) & E1000_PBA_RXA_MASK;
+
+ /* Determine the maximum latency tolerated by the device.
+ *
+ * Per the PCIe spec, the tolerated latencies are encoded as
+ * a 3-bit encoded scale (only 0-5 are valid) multiplied by
+ * a 10-bit value (0-1023) to provide a range from 1 ns to
+ * 2^25*(2^10-1) ns. The scale is encoded as 0=2^0ns,
+ * 1=2^5ns, 2=2^10ns,...5=2^25ns.
+ */
+ lat_ns = ((s64)rxa * 1024 -
+ (2 * (s64)hw->mac.max_frame_size)) * 8 * 1000;
+ if (lat_ns < 0)
+ lat_ns = 0;
+ else
+ lat_ns /= speed;
+
+ value = lat_ns;
+ while (value > E1000_LTRV_VALUE_MASK) {
+ scale++;
+ value = E1000_DIVIDE_ROUND_UP(value, (1 << 5));
+ }
+ if (scale > E1000_LTRV_SCALE_MAX) {
+ DEBUGOUT1("Invalid LTR latency scale %d\n", scale);
+ return -E1000_ERR_CONFIG;
+ }
+ lat_enc = (u16)((scale << E1000_LTRV_SCALE_SHIFT) | value);
+
+ /* Determine the maximum latency tolerated by the platform */
+ e1000_read_pci_cfg(hw, E1000_PCI_LTR_CAP_LPT, &max_snoop);
+ e1000_read_pci_cfg(hw, E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop);
+ max_ltr_enc = E1000_MAX(max_snoop, max_nosnoop);
+
+ if (lat_enc > max_ltr_enc) {
+ lat_enc = max_ltr_enc;
+ lat_ns = e1000_ltr2ns(max_ltr_enc);
+ }
+
+ if (lat_ns) {
+ lat_ns *= speed * 1000;
+ lat_ns /= 8;
+ lat_ns /= 1000000000;
+ obff_hwm = (s32)(rxa - lat_ns);
+ }
+
+ if ((obff_hwm < 0) || (obff_hwm > E1000_SVT_OFF_HWM_MASK)) {
+ DEBUGOUT1("Invalid high water mark %d\n", obff_hwm);
+ return -E1000_ERR_CONFIG;
+ }
+ }
+
+ /* Set Snoop and No-Snoop latencies the same */
+ reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT);
+ E1000_WRITE_REG(hw, E1000_LTRV, reg);
+
+ /* Set OBFF high water mark */
+ reg = E1000_READ_REG(hw, E1000_SVT) & ~E1000_SVT_OFF_HWM_MASK;
+ reg |= obff_hwm;
+ E1000_WRITE_REG(hw, E1000_SVT, reg);
+
+ /* Enable OBFF */
+ reg = E1000_READ_REG(hw, E1000_SVCR);
+ reg |= E1000_SVCR_OFF_EN;
+ /* Always unblock interrupts to the CPU even when the system is
+ * in OBFF mode. This ensures that small round-robin traffic
+ * (like ping) does not get dropped or experience long latency.
+ */
+ reg |= E1000_SVCR_OFF_MASKINT;
+ E1000_WRITE_REG(hw, E1000_SVCR, reg);
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_set_obff_timer_pch_lpt - Update Optimized Buffer Flush/Fill timer
+ * @hw: pointer to the HW structure
+ * @itr: interrupt throttling rate
+ *
+ * Configure OBFF with the updated interrupt rate.
+ **/
+static s32 e1000_set_obff_timer_pch_lpt(struct e1000_hw *hw, u32 itr)
+{
+ u32 svcr;
+ s32 timer;
+
+ DEBUGFUNC("e1000_set_obff_timer_pch_lpt");
+
+ /* Convert ITR value into microseconds for OBFF timer */
+ timer = itr & E1000_ITR_MASK;
+ timer = (timer * E1000_ITR_MULT) / 1000;
+
+ if ((timer < 0) || (timer > E1000_ITR_MASK)) {
+ DEBUGOUT1("Invalid OBFF timer %d\n", timer);
+ return -E1000_ERR_CONFIG;
+ }
+
+ svcr = E1000_READ_REG(hw, E1000_SVCR);
+ svcr &= ~E1000_SVCR_OFF_TIMER_MASK;
+ svcr |= timer << E1000_SVCR_OFF_TIMER_SHIFT;
+ E1000_WRITE_REG(hw, E1000_SVCR, svcr);
+
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_check_for_copper_link_ich8lan - Check for link (Copper)
* @hw: pointer to the HW structure
*
@@ -623,54 +1097,116 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
struct e1000_mac_info *mac = &hw->mac;
s32 ret_val;
bool link;
+ u16 phy_reg;
DEBUGFUNC("e1000_check_for_copper_link_ich8lan");
- /*
- * We only want to go out to the PHY registers to see if Auto-Neg
+ /* We only want to go out to the PHY registers to see if Auto-Neg
* has completed and/or if our link status has changed. The
* get_link_status flag is set upon receiving a Link Status
* Change or Rx Sequence Error interrupt.
*/
- if (!mac->get_link_status) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
+ if (!mac->get_link_status)
+ return E1000_SUCCESS;
- /*
- * First we want to see if the MII Status Register reports
+ /* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
* of the PHY.
*/
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (hw->mac.type == e1000_pchlan) {
ret_val = e1000_k1_gig_workaround_hv(hw, link);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (!link)
- goto out; /* No link detected */
+ /* When connected at 10Mbps half-duplex, 82579 parts are excessively
+ * aggressive resulting in many collisions. To avoid this, increase
+ * the IPG and reduce Rx latency in the PHY.
+ */
+ if ((hw->mac.type == e1000_pch2lan) && link) {
+ u32 reg;
+ reg = E1000_READ_REG(hw, E1000_STATUS);
+ if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) {
+ reg = E1000_READ_REG(hw, E1000_TIPG);
+ reg &= ~E1000_TIPG_IPGT_MASK;
+ reg |= 0xFF;
+ E1000_WRITE_REG(hw, E1000_TIPG, reg);
+
+ /* Reduce Rx latency in analog PHY */
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
- mac->get_link_status = FALSE;
+ ret_val = e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0);
- if (hw->phy.type == e1000_phy_82578) {
- ret_val = e1000_link_stall_workaround_hv(hw);
+ hw->phy.ops.release(hw);
+
+ if (ret_val)
+ return ret_val;
+ }
+ }
+
+ /* Work-around I218 hang issue */
+ if ((hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+ (hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
+ ret_val = e1000_k1_workaround_lpt_lp(hw, link);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (hw->mac.type == e1000_pch2lan) {
+ if (hw->mac.type == e1000_pch_lpt) {
+ /* Set platform power management values for Latency Tolerance
+ * Reporting (LTR) and Optimized Buffer Flush/Fill (OBFF).
+ */
+ ret_val = e1000_platform_pm_pch_lpt(hw, link);
+ if (ret_val)
+ return ret_val;
+ }
+
+ /* Clear link partner's EEE ability */
+ hw->dev_spec.ich8lan.eee_lp_ability = 0;
+
+ if (!link)
+ return E1000_SUCCESS; /* No link detected */
+
+ mac->get_link_status = FALSE;
+
+ switch (hw->mac.type) {
+ case e1000_pch2lan:
ret_val = e1000_k1_workaround_lv(hw);
if (ret_val)
- goto out;
+ return ret_val;
+ /* fall-thru */
+ case e1000_pchlan:
+ if (hw->phy.type == e1000_phy_82578) {
+ ret_val = e1000_link_stall_workaround_hv(hw);
+ if (ret_val)
+ return ret_val;
+ }
+
+ /* Workaround for PCHx parts in half-duplex:
+ * Set the number of preambles removed from the packet
+ * when it is passed from the PHY to the MAC to prevent
+ * the MAC from misinterpreting the packet type.
+ */
+ hw->phy.ops.read_reg(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg);
+ phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK;
+
+ if ((E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FD) !=
+ E1000_STATUS_FD)
+ phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT);
+
+ hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg);
+ break;
+ default:
+ break;
}
- /*
- * Check if there was DownShift, must be checked
+ /* Check if there was DownShift, must be checked
* immediately after link-up
*/
e1000_check_downshift_generic(hw);
@@ -678,26 +1214,21 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
/* Enable/Disable EEE after link up */
ret_val = e1000_set_eee_pchlan(hw);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * If we are forcing speed/duplex, then we simply return since
+ /* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
*/
- if (!mac->autoneg) {
- ret_val = -E1000_ERR_CONFIG;
- goto out;
- }
+ if (!mac->autoneg)
+ return -E1000_ERR_CONFIG;
- /*
- * Auto-Neg is enabled. Auto Speed Detection takes care
+ /* Auto-Neg is enabled. Auto Speed Detection takes care
* of MAC speed/duplex configuration. So we only need to
* configure Collision Distance in the MAC.
*/
- e1000_config_collision_dist_generic(hw);
+ mac->ops.config_collision_dist(hw);
- /*
- * Configure Flow Control now that Auto-Neg has completed.
+ /* Configure Flow Control now that Auto-Neg has completed.
* First, we need to restore the desired flow control
* settings because we may have had to re-autoneg with a
* different link partner.
@@ -706,7 +1237,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (ret_val)
DEBUGOUT("Error configuring flow control\n");
-out:
return ret_val;
}
@@ -730,6 +1260,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
break;
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
hw->phy.ops.init_params = e1000_init_phy_params_pchlan;
break;
default:
@@ -793,7 +1324,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
}
if (!timeout) {
- DEBUGOUT("SW/FW/HW has locked the resource for too long.\n");
+ DEBUGOUT("SW has already locked the resource.\n");
ret_val = -E1000_ERR_CONFIG;
goto out;
}
@@ -813,7 +1344,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
}
if (!timeout) {
- DEBUGOUT("Failed to acquire the semaphore.\n");
+ DEBUGOUT2("Failed to acquire the semaphore, FW or HW has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n",
+ E1000_READ_REG(hw, E1000_FWSM), extcnf_ctrl);
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
ret_val = -E1000_ERR_CONFIG;
@@ -841,8 +1373,13 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_release_swflag_ich8lan");
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
- extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
- E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
+
+ if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) {
+ extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+ E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
+ } else {
+ DEBUGOUT("Semaphore unexpectedly released by sw/fw/hw\n");
+ }
E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex);
@@ -907,13 +1444,12 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
DEBUGFUNC("e1000_rar_set_pch2lan");
- /*
- * HW expects these in little endian so we reverse the byte order
+ /* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
rar_low = ((u32) addr[0] |
- ((u32) addr[1] << 8) |
- ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+ ((u32) addr[1] << 8) |
+ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
@@ -930,11 +1466,19 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
}
if (index < hw->mac.rar_entry_count) {
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+ if (ret_val)
+ goto out;
+
E1000_WRITE_REG(hw, E1000_SHRAL(index - 1), rar_low);
E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG(hw, E1000_SHRAH(index - 1), rar_high);
E1000_WRITE_FLUSH(hw);
+ e1000_release_swflag_ich8lan(hw);
+
/* verify the register updates */
if ((E1000_READ_REG(hw, E1000_SHRAL(index - 1)) == rar_low) &&
(E1000_READ_REG(hw, E1000_SHRAH(index - 1)) == rar_high))
@@ -944,10 +1488,133 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
(index - 1), E1000_READ_REG(hw, E1000_FWSM));
}
+out:
+ DEBUGOUT1("Failed to write receive address at index %d\n", index);
+}
+
+/**
+ * e1000_rar_set_pch_lpt - Set receive address registers
+ * @hw: pointer to the HW structure
+ * @addr: pointer to the receive address
+ * @index: receive address array register
+ *
+ * Sets the receive address register array at index to the address passed
+ * in by addr. For LPT, RAR[0] is the base address register that is to
+ * contain the MAC address. SHRA[0-10] are the shared receive address
+ * registers that are shared between the Host and manageability engine (ME).
+ **/
+static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+ u32 rar_low, rar_high;
+ u32 wlock_mac;
+
+ DEBUGFUNC("e1000_rar_set_pch_lpt");
+
+ /* HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
+ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+
+ rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+ /* If MAC address zero, no need to set the AV bit */
+ if (rar_low || rar_high)
+ rar_high |= E1000_RAH_AV;
+
+ if (index == 0) {
+ E1000_WRITE_REG(hw, E1000_RAL(index), rar_low);
+ E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_REG(hw, E1000_RAH(index), rar_high);
+ E1000_WRITE_FLUSH(hw);
+ return;
+ }
+
+ /* The manageability engine (ME) can lock certain SHRAR registers that
+ * it is using - those registers are unavailable for use.
+ */
+ if (index < hw->mac.rar_entry_count) {
+ wlock_mac = E1000_READ_REG(hw, E1000_FWSM) &
+ E1000_FWSM_WLOCK_MAC_MASK;
+ wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT;
+
+ /* Check if all SHRAR registers are locked */
+ if (wlock_mac == 1)
+ goto out;
+
+ if ((wlock_mac == 0) || (index <= wlock_mac)) {
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+
+ if (ret_val)
+ goto out;
+
+ E1000_WRITE_REG(hw, E1000_SHRAL_PCH_LPT(index - 1),
+ rar_low);
+ E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_REG(hw, E1000_SHRAH_PCH_LPT(index - 1),
+ rar_high);
+ E1000_WRITE_FLUSH(hw);
+
+ e1000_release_swflag_ich8lan(hw);
+
+ /* verify the register updates */
+ if ((E1000_READ_REG(hw, E1000_SHRAL_PCH_LPT(index - 1)) == rar_low) &&
+ (E1000_READ_REG(hw, E1000_SHRAH_PCH_LPT(index - 1)) == rar_high))
+ return;
+ }
+ }
+
+out:
DEBUGOUT1("Failed to write receive address at index %d\n", index);
}
/**
+ * e1000_update_mc_addr_list_pch2lan - Update Multicast addresses
+ * @hw: pointer to the HW structure
+ * @mc_addr_list: array of multicast addresses to program
+ * @mc_addr_count: number of multicast addresses to program
+ *
+ * Updates entire Multicast Table Array of the PCH2 MAC and PHY.
+ * The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw,
+ u8 *mc_addr_list,
+ u32 mc_addr_count)
+{
+ u16 phy_reg = 0;
+ int i;
+ s32 ret_val;
+
+ DEBUGFUNC("e1000_update_mc_addr_list_pch2lan");
+
+ e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count);
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return;
+
+ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+ if (ret_val)
+ goto release;
+
+ for (i = 0; i < hw->mac.mta_reg_count; i++) {
+ hw->phy.ops.write_reg_page(hw, BM_MTA(i),
+ (u16)(hw->mac.mta_shadow[i] &
+ 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, (BM_MTA(i) + 1),
+ (u16)((hw->mac.mta_shadow[i] >> 16) &
+ 0xFFFF));
+ }
+
+ e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+
+release:
+ hw->phy.ops.release(hw);
+}
+
+/**
* e1000_check_reset_block_ich8lan - Check if PHY reset is blocked
* @hw: pointer to the HW structure
*
@@ -961,13 +1628,10 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_reset_block_ich8lan");
- if (hw->phy.reset_disable)
- return E1000_BLK_PHY_RESET;
-
fwsm = E1000_READ_REG(hw, E1000_FWSM);
return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? E1000_SUCCESS
- : E1000_BLK_PHY_RESET;
+ : E1000_BLK_PHY_RESET;
}
/**
@@ -981,21 +1645,34 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
{
u16 phy_data;
u32 strap = E1000_READ_REG(hw, E1000_STRAP);
- s32 ret_val = E1000_SUCCESS;
+ u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >>
+ E1000_STRAP_SMT_FREQ_SHIFT;
+ s32 ret_val;
strap &= E1000_STRAP_SMBUS_ADDRESS_MASK;
ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data &= ~HV_SMB_ADDR_MASK;
phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
- ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
-out:
- return ret_val;
+ if (hw->phy.type == e1000_phy_i217) {
+ /* Restore SMBus frequency */
+ if (freq--) {
+ phy_data &= ~HV_SMB_ADDR_FREQ_MASK;
+ phy_data |= (freq & (1 << 0)) <<
+ HV_SMB_ADDR_FREQ_LOW_SHIFT;
+ phy_data |= (freq & (1 << 1)) <<
+ (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1);
+ } else {
+ DEBUGOUT("Unsupported SMB frequency in PHY\n");
+ }
+ }
+
+ return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
}
/**
@@ -1014,8 +1691,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_sw_lcd_config_ich8lan");
- /*
- * Initialize the PHY from the NVM on ICH platforms. This
+ /* Initialize the PHY from the NVM on ICH platforms. This
* is needed due to an issue where the NVM configuration is
* not properly autoloaded after power transitions.
* Therefore, after each PHY reset, we will load the
@@ -1034,6 +1710,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
/* Fall-thru */
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
break;
default:
@@ -1046,45 +1723,42 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
data = E1000_READ_REG(hw, E1000_FEXTNVM);
if (!(data & sw_cfg_mask))
- goto out;
+ goto release;
- /*
- * Make sure HW does not configure LCD from PHY
+ /* Make sure HW does not configure LCD from PHY
* extended configuration before SW configuration
*/
data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
- if (!(hw->mac.type == e1000_pch2lan)) {
- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- goto out;
- }
+ if ((hw->mac.type < e1000_pch2lan) &&
+ (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE))
+ goto release;
cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE);
cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
if (!cnf_size)
- goto out;
+ goto release;
cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
- if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
- (hw->mac.type == e1000_pchlan)) ||
- (hw->mac.type == e1000_pch2lan)) {
- /*
- * HW configures the SMBus address and LEDs when the
+ if (((hw->mac.type == e1000_pchlan) &&
+ !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) ||
+ (hw->mac.type > e1000_pchlan)) {
+ /* HW configures the SMBus address and LEDs when the
* OEM and LCD Write Enable bits are set in the NVM.
* When both NVM bits are cleared, SW will configure
* them instead.
*/
ret_val = e1000_write_smbus_addr(hw);
if (ret_val)
- goto out;
+ goto release;
data = E1000_READ_REG(hw, E1000_LEDCTL);
ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG,
(u16)data);
if (ret_val)
- goto out;
+ goto release;
}
/* Configure LCD from extended configuration region. */
@@ -1096,12 +1770,12 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2), 1,
&reg_data);
if (ret_val)
- goto out;
+ goto release;
ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2 + 1),
1, &reg_addr);
if (ret_val)
- goto out;
+ goto release;
/* Save off the PHY page for future writes. */
if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
@@ -1115,10 +1789,10 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr,
reg_data);
if (ret_val)
- goto out;
+ goto release;
}
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -1142,57 +1816,57 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
DEBUGFUNC("e1000_k1_gig_workaround_hv");
if (hw->mac.type != e1000_pchlan)
- goto out;
+ return E1000_SUCCESS;
/* Wrap the whole flow with the sw flag */
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
/* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
if (link) {
if (hw->phy.type == e1000_phy_82578) {
ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS,
- &status_reg);
+ &status_reg);
if (ret_val)
goto release;
status_reg &= BM_CS_STATUS_LINK_UP |
- BM_CS_STATUS_RESOLVED |
- BM_CS_STATUS_SPEED_MASK;
+ BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_MASK;
if (status_reg == (BM_CS_STATUS_LINK_UP |
- BM_CS_STATUS_RESOLVED |
- BM_CS_STATUS_SPEED_1000))
+ BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_1000))
k1_enable = FALSE;
}
if (hw->phy.type == e1000_phy_82577) {
ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS,
- &status_reg);
+ &status_reg);
if (ret_val)
goto release;
status_reg &= HV_M_STATUS_LINK_UP |
- HV_M_STATUS_AUTONEG_COMPLETE |
- HV_M_STATUS_SPEED_MASK;
+ HV_M_STATUS_AUTONEG_COMPLETE |
+ HV_M_STATUS_SPEED_MASK;
if (status_reg == (HV_M_STATUS_LINK_UP |
- HV_M_STATUS_AUTONEG_COMPLETE |
- HV_M_STATUS_SPEED_1000))
+ HV_M_STATUS_AUTONEG_COMPLETE |
+ HV_M_STATUS_SPEED_1000))
k1_enable = FALSE;
}
/* Link stall fix for link up */
ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
- 0x0100);
+ 0x0100);
if (ret_val)
goto release;
} else {
/* Link stall fix for link down */
ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
- 0x4100);
+ 0x4100);
if (ret_val)
goto release;
}
@@ -1201,7 +1875,7 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
release:
hw->phy.ops.release(hw);
-out:
+
return ret_val;
}
@@ -1217,7 +1891,7 @@ out:
**/
s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u32 ctrl_reg = 0;
u32 ctrl_ext = 0;
u32 reg = 0;
@@ -1225,22 +1899,20 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
DEBUGFUNC("e1000_configure_k1_ich8lan");
- ret_val = e1000_read_kmrn_reg_locked(hw,
- E1000_KMRNCTRLSTA_K1_CONFIG,
- &kmrn_reg);
+ ret_val = e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
+ &kmrn_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (k1_enable)
kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
else
kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE;
- ret_val = e1000_write_kmrn_reg_locked(hw,
- E1000_KMRNCTRLSTA_K1_CONFIG,
- kmrn_reg);
+ ret_val = e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
+ kmrn_reg);
if (ret_val)
- goto out;
+ return ret_val;
usec_delay(20);
ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
@@ -1251,13 +1923,14 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
E1000_WRITE_REG(hw, E1000_CTRL, reg);
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
+ E1000_WRITE_FLUSH(hw);
usec_delay(20);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg);
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH(hw);
usec_delay(20);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1269,7 +1942,7 @@ out:
* collectively called OEM bits. The OEM Write Enable bit and SW Config bit
* in NVM determines whether HW should configure LPLU and Gbe Disable.
**/
-s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
+static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
{
s32 ret_val = 0;
u32 mac_reg;
@@ -1277,28 +1950,28 @@ s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
DEBUGFUNC("e1000_oem_bits_config_ich8lan");
- if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan))
+ if (hw->mac.type < e1000_pchlan)
return ret_val;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- if (!(hw->mac.type == e1000_pch2lan)) {
+ if (hw->mac.type == e1000_pchlan) {
mac_reg = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
- goto out;
+ goto release;
}
mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM);
if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
- goto out;
+ goto release;
mac_reg = E1000_READ_REG(hw, E1000_PHY_CTRL);
ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg);
if (ret_val)
- goto out;
+ goto release;
oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);
@@ -1309,18 +1982,23 @@ s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
oem_reg |= HV_OEM_BITS_LPLU;
} else {
- if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE)
+ if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE |
+ E1000_PHY_CTRL_NOND0A_GBE_DISABLE))
oem_reg |= HV_OEM_BITS_GBE_DIS;
- if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU)
+ if (mac_reg & (E1000_PHY_CTRL_D0A_LPLU |
+ E1000_PHY_CTRL_NOND0A_LPLU))
oem_reg |= HV_OEM_BITS_LPLU;
}
- /* Restart auto-neg to activate the bits */
- if (!hw->phy.ops.check_reset_block(hw))
+
+ /* Set Restart auto-neg to activate the bits */
+ if ((d0_state || (hw->mac.type != e1000_pchlan)) &&
+ !hw->phy.ops.check_reset_block(hw))
oem_reg |= HV_OEM_BITS_RESTART_AN;
+
ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
@@ -1328,20 +2006,6 @@ out:
/**
- * e1000_hv_phy_powerdown_workaround_ich8lan - Power down workaround on Sx
- * @hw: pointer to the HW structure
- **/
-s32 e1000_hv_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
-{
- DEBUGFUNC("e1000_hv_phy_powerdown_workaround_ich8lan");
-
- if ((hw->phy.type != e1000_phy_82577) || (hw->revision_id > 2))
- return E1000_SUCCESS;
-
- return hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0444);
-}
-
-/**
* e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
* @hw: pointer to the HW structure
**/
@@ -1375,39 +2039,13 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_hv_phy_workarounds_ich8lan");
if (hw->mac.type != e1000_pchlan)
- goto out;
+ return E1000_SUCCESS;
/* Set MDIO slow mode before any other MDIO access */
if (hw->phy.type == e1000_phy_82577) {
ret_val = e1000_set_mdio_slow_mode_hv(hw);
if (ret_val)
- goto out;
- }
-
- /* Hanksville M Phy init for IEEE. */
- if ((hw->revision_id == 2) &&
- (hw->phy.type == e1000_phy_82577) &&
- ((hw->phy.revision == 2) || (hw->phy.revision == 3))) {
- hw->phy.ops.write_reg(hw, 0x10, 0x8823);
- hw->phy.ops.write_reg(hw, 0x11, 0x0018);
- hw->phy.ops.write_reg(hw, 0x10, 0x8824);
- hw->phy.ops.write_reg(hw, 0x11, 0x0016);
- hw->phy.ops.write_reg(hw, 0x10, 0x8825);
- hw->phy.ops.write_reg(hw, 0x11, 0x001A);
- hw->phy.ops.write_reg(hw, 0x10, 0x888C);
- hw->phy.ops.write_reg(hw, 0x11, 0x0007);
- hw->phy.ops.write_reg(hw, 0x10, 0x888D);
- hw->phy.ops.write_reg(hw, 0x11, 0x0007);
- hw->phy.ops.write_reg(hw, 0x10, 0x888E);
- hw->phy.ops.write_reg(hw, 0x11, 0x0007);
- hw->phy.ops.write_reg(hw, 0x10, 0x8827);
- hw->phy.ops.write_reg(hw, 0x11, 0x0001);
- hw->phy.ops.write_reg(hw, 0x10, 0x8835);
- hw->phy.ops.write_reg(hw, 0x11, 0x0001);
- hw->phy.ops.write_reg(hw, 0x10, 0x8834);
- hw->phy.ops.write_reg(hw, 0x11, 0x0001);
- hw->phy.ops.write_reg(hw, 0x10, 0x8833);
- hw->phy.ops.write_reg(hw, 0x11, 0x0002);
+ return ret_val;
}
if (((hw->phy.type == e1000_phy_82577) &&
@@ -1416,89 +2054,61 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
/* Disable generation of early preamble */
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 25), 0x4431);
if (ret_val)
- goto out;
+ return ret_val;
/* Preamble tuning for SSC */
- ret_val = hw->phy.ops.write_reg(hw, PHY_REG(770, 16), 0xA204);
+ ret_val = hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA,
+ 0xA204);
if (ret_val)
- goto out;
+ return ret_val;
}
if (hw->phy.type == e1000_phy_82578) {
- if (hw->revision_id < 3) {
- /* PHY config */
- ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x29,
- 0x66C0);
- if (ret_val)
- goto out;
-
- /* PHY config */
- ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x1E,
- 0xFFFF);
- if (ret_val)
- goto out;
- }
-
- /*
- * Return registers to default by doing a soft reset then
+ /* Return registers to default by doing a soft reset then
* writing 0x3140 to the control register.
*/
if (hw->phy.revision < 2) {
e1000_phy_sw_reset_generic(hw);
ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL,
- 0x3140);
+ 0x3140);
}
}
- if ((hw->revision_id == 2) &&
- (hw->phy.type == e1000_phy_82577) &&
- ((hw->phy.revision == 2) || (hw->phy.revision == 3))) {
- /*
- * Workaround for OEM (GbE) not operating after reset -
- * restart AN (twice)
- */
- ret_val = hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0400);
- if (ret_val)
- goto out;
- ret_val = hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0400);
- if (ret_val)
- goto out;
- }
-
/* Select page 0 */
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
hw->phy.addr = 1;
ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
hw->phy.ops.release(hw);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * Configure the K1 Si workaround during phy reset assuming there is
+ /* Configure the K1 Si workaround during phy reset assuming there is
* link so that it disables K1 if link is in 1Gbps.
*/
ret_val = e1000_k1_gig_workaround_hv(hw, TRUE);
if (ret_val)
- goto out;
+ return ret_val;
/* Workaround for link disconnects on a busy hub in half duplex */
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
- ret_val = hw->phy.ops.read_reg_locked(hw,
- PHY_REG(BM_PORT_CTRL_PAGE, 17),
- &phy_data);
+ return ret_val;
+ ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
if (ret_val)
goto release;
- ret_val = hw->phy.ops.write_reg_locked(hw,
- PHY_REG(BM_PORT_CTRL_PAGE, 17),
- phy_data & 0x00FF);
+ ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG,
+ phy_data & 0x00FF);
+ if (ret_val)
+ goto release;
+
+ /* set MSE higher to enable link to stay up when noise is high */
+ ret_val = e1000_write_emi_reg_locked(hw, I82577_MSE_THRESHOLD, 0x0034);
release:
hw->phy.ops.release(hw);
-out:
+
return ret_val;
}
@@ -1509,19 +2119,38 @@ out:
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
{
u32 mac_reg;
- u16 i;
+ u16 i, phy_reg = 0;
+ s32 ret_val;
DEBUGFUNC("e1000_copy_rx_addrs_to_phy_ich8lan");
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return;
+ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+ if (ret_val)
+ goto release;
+
/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
mac_reg = E1000_READ_REG(hw, E1000_RAL(i));
- hw->phy.ops.write_reg(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
- hw->phy.ops.write_reg(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
+ (u16)(mac_reg & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_M(i),
+ (u16)((mac_reg >> 16) & 0xFFFF));
+
mac_reg = E1000_READ_REG(hw, E1000_RAH(i));
- hw->phy.ops.write_reg(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
- hw->phy.ops.write_reg(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_H(i),
+ (u16)(mac_reg & 0xFFFF));
+ hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i),
+ (u16)((mac_reg & E1000_RAH_AV)
+ >> 16));
}
+
+ e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+
+release:
+ hw->phy.ops.release(hw);
}
static u32 e1000_calc_rx_da_crc(u8 mac[])
@@ -1557,18 +2186,18 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
DEBUGFUNC("e1000_lv_jumbo_workaround_ich8lan");
- if (hw->mac.type != e1000_pch2lan)
- goto out;
+ if (hw->mac.type < e1000_pch2lan)
+ return E1000_SUCCESS;
/* disable Rx path while enabling/disabling workaround */
hw->phy.ops.read_reg(hw, PHY_REG(769, 20), &phy_reg);
- ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg | (1 << 14));
+ ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 20),
+ phy_reg | (1 << 14));
if (ret_val)
- goto out;
+ return ret_val;
if (enable) {
- /*
- * Write Rx addresses (rar_entry_count for RAL/H, +4 for
+ /* Write Rx addresses (rar_entry_count for RAL/H, +4 for
* SHRAL/H) and initial CRC values to the MAC
*/
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
@@ -1607,24 +2236,24 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
E1000_KMRNCTRLSTA_CTRL_OFFSET,
&data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_write_kmrn_reg_generic(hw,
E1000_KMRNCTRLSTA_CTRL_OFFSET,
data | (1 << 0));
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_read_kmrn_reg_generic(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
&data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~(0xF << 8);
data |= (0xB << 8);
ret_val = e1000_write_kmrn_reg_generic(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
data);
if (ret_val)
- goto out;
+ return ret_val;
/* Enable jumbo frame workaround in the PHY */
hw->phy.ops.read_reg(hw, PHY_REG(769, 23), &data);
@@ -1632,25 +2261,26 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
data |= (0x37 << 5);
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 23), data);
if (ret_val)
- goto out;
+ return ret_val;
hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &data);
data &= ~(1 << 13);
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 16), data);
if (ret_val)
- goto out;
+ return ret_val;
hw->phy.ops.read_reg(hw, PHY_REG(776, 20), &data);
data &= ~(0x3FF << 2);
data |= (0x1A << 2);
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 20), data);
if (ret_val)
- goto out;
- ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0xFE00);
+ return ret_val;
+ ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0xF100);
if (ret_val)
- goto out;
+ return ret_val;
hw->phy.ops.read_reg(hw, HV_PM_CTRL, &data);
- ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data | (1 << 10));
+ ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data |
+ (1 << 10));
if (ret_val)
- goto out;
+ return ret_val;
} else {
/* Write MAC register values back to h/w defaults */
mac_reg = E1000_READ_REG(hw, E1000_FFLT_DBG);
@@ -1665,56 +2295,55 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
E1000_KMRNCTRLSTA_CTRL_OFFSET,
&data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_write_kmrn_reg_generic(hw,
E1000_KMRNCTRLSTA_CTRL_OFFSET,
data & ~(1 << 0));
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_read_kmrn_reg_generic(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
&data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~(0xF << 8);
data |= (0xB << 8);
ret_val = e1000_write_kmrn_reg_generic(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
data);
if (ret_val)
- goto out;
+ return ret_val;
/* Write PHY register values back to h/w defaults */
hw->phy.ops.read_reg(hw, PHY_REG(769, 23), &data);
data &= ~(0x7F << 5);
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 23), data);
if (ret_val)
- goto out;
+ return ret_val;
hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &data);
data |= (1 << 13);
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 16), data);
if (ret_val)
- goto out;
+ return ret_val;
hw->phy.ops.read_reg(hw, PHY_REG(776, 20), &data);
data &= ~(0x3FF << 2);
data |= (0x8 << 2);
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 20), data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0x7E00);
if (ret_val)
- goto out;
+ return ret_val;
hw->phy.ops.read_reg(hw, HV_PM_CTRL, &data);
- ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data & ~(1 << 10));
+ ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data &
+ ~(1 << 10));
if (ret_val)
- goto out;
+ return ret_val;
}
/* re-enable Rx path after enabling/disabling workaround */
- ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14));
-
-out:
- return ret_val;
+ return hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg &
+ ~(1 << 14));
}
/**
@@ -1728,12 +2357,25 @@ static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_lv_phy_workarounds_ich8lan");
if (hw->mac.type != e1000_pch2lan)
- goto out;
+ return E1000_SUCCESS;
/* Set MDIO slow mode before any other MDIO access */
ret_val = e1000_set_mdio_slow_mode_hv(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+ /* set MSE higher to enable link to stay up when noise is high */
+ ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_THRESHOLD, 0x0034);
+ if (ret_val)
+ goto release;
+ /* drop link after 5 times MSE threshold was reached */
+ ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_LINK_DOWN, 0x0005);
+release:
+ hw->phy.ops.release(hw);
-out:
return ret_val;
}
@@ -1748,38 +2390,57 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
s32 ret_val = E1000_SUCCESS;
u16 status_reg = 0;
u32 mac_reg;
+ u16 phy_reg;
DEBUGFUNC("e1000_k1_workaround_lv");
if (hw->mac.type != e1000_pch2lan)
- goto out;
+ return E1000_SUCCESS;
/* Set K1 beacon duration based on 1Gbps speed or otherwise */
ret_val = hw->phy.ops.read_reg(hw, HV_M_STATUS, &status_reg);
if (ret_val)
- goto out;
+ return ret_val;
if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
== (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
- if (status_reg & HV_M_STATUS_SPEED_1000)
+ ret_val = hw->phy.ops.read_reg(hw, I82579_LPI_CTRL, &phy_reg);
+ if (ret_val)
+ return ret_val;
+
+ if (status_reg & HV_M_STATUS_SPEED_1000) {
+ u16 pm_phy_reg;
+
mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
- else
+ phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+ /* LV 1G Packet drop issue wa */
+ ret_val = hw->phy.ops.read_reg(hw, HV_PM_CTRL,
+ &pm_phy_reg);
+ if (ret_val)
+ return ret_val;
+ pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA;
+ ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL,
+ pm_phy_reg);
+ if (ret_val)
+ return ret_val;
+ } else {
mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
-
+ phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+ }
E1000_WRITE_REG(hw, E1000_FEXTNVM4, mac_reg);
+ ret_val = hw->phy.ops.write_reg(hw, I82579_LPI_CTRL, phy_reg);
}
-out:
return ret_val;
}
/**
* e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware
* @hw: pointer to the HW structure
- * @gate: boolean set to TRUE to gate, FALSE to un-gate
+ * @gate: boolean set to TRUE to gate, FALSE to ungate
*
* Gate/ungate the automatic PHY configuration via hardware; perform
* the configuration via software instead.
@@ -1790,7 +2451,7 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
DEBUGFUNC("e1000_gate_hw_phy_config_ich8lan");
- if (hw->mac.type != e1000_pch2lan)
+ if (hw->mac.type < e1000_pch2lan)
return;
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
@@ -1801,35 +2462,6 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG;
E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
- return;
-}
-
-/**
- * e1000_hv_phy_tuning_workaround_ich8lan - This is a Phy tuning work around
- * needed for Nahum3 + Hanksville testing, requested by HW team
- **/
-static s32 e1000_hv_phy_tuning_workaround_ich8lan(struct e1000_hw *hw)
-{
- s32 ret_val = E1000_SUCCESS;
-
- DEBUGFUNC("e1000_hv_phy_tuning_workaround_ich8lan");
-
- ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 25), 0x4431);
- if (ret_val)
- goto out;
-
- ret_val = hw->phy.ops.write_reg(hw, PHY_REG(770, 16), 0xA204);
- if (ret_val)
- goto out;
-
- ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x29, 0x66C0);
- if (ret_val)
- goto out;
-
- ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x1E, 0xFFFF);
-
-out:
- return ret_val;
}
/**
@@ -1852,8 +2484,7 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
usec_delay(100);
} while ((!data) && --loop);
- /*
- * If basic configuration is incomplete before the above loop
+ /* If basic configuration is incomplete before the above loop
* count reaches 0, loading the configuration from NVM will
* leave the PHY in a bad state possibly resulting in no link.
*/
@@ -1878,7 +2509,7 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_post_phy_reset_ich8lan");
if (hw->phy.ops.check_reset_block(hw))
- goto out;
+ return E1000_SUCCESS;
/* Allow time for h/w to get to quiescent state after reset */
msec_delay(10);
@@ -1888,43 +2519,50 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
case e1000_pchlan:
ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
break;
case e1000_pch2lan:
ret_val = e1000_lv_phy_workarounds_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
break;
default:
break;
}
- if (hw->device_id == E1000_DEV_ID_ICH10_HANKSVILLE) {
- ret_val = e1000_hv_phy_tuning_workaround_ich8lan(hw);
- if (ret_val)
- goto out;
+ /* Clear the host wakeup bit after lcd reset */
+ if (hw->mac.type >= e1000_pchlan) {
+ hw->phy.ops.read_reg(hw, BM_PORT_GEN_CFG, &reg);
+ reg &= ~BM_WUC_HOST_WU_BIT;
+ hw->phy.ops.write_reg(hw, BM_PORT_GEN_CFG, reg);
}
- /* Dummy read to clear the phy wakeup bit after lcd reset */
- if (hw->mac.type >= e1000_pchlan)
- hw->phy.ops.read_reg(hw, BM_WUC, &reg);
-
/* Configure the LCD with the extended configuration region in NVM */
ret_val = e1000_sw_lcd_config_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
/* Configure the LCD with the OEM bits in NVM */
ret_val = e1000_oem_bits_config_ich8lan(hw, TRUE);
- /* Ungate automatic PHY configuration on non-managed 82579 */
- if ((hw->mac.type == e1000_pch2lan) &&
- !(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) {
- msec_delay(10);
- e1000_gate_hw_phy_config_ich8lan(hw, FALSE);
+ if (hw->mac.type == e1000_pch2lan) {
+ /* Ungate automatic PHY configuration on non-managed 82579 */
+ if (!(E1000_READ_REG(hw, E1000_FWSM) &
+ E1000_ICH_FWSM_FW_VALID)) {
+ msec_delay(10);
+ e1000_gate_hw_phy_config_ich8lan(hw, FALSE);
+ }
+
+ /* Set EEE LPI Update Timer to 200usec */
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_write_emi_reg_locked(hw,
+ I82579_LPI_UPDATE_TIMER,
+ 0x1387);
+ hw->phy.ops.release(hw);
}
-out:
return ret_val;
}
@@ -1949,12 +2587,9 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
ret_val = e1000_phy_hw_reset_generic(hw);
if (ret_val)
- goto out;
-
- ret_val = e1000_post_phy_reset_ich8lan(hw);
+ return ret_val;
-out:
- return ret_val;
+ return e1000_post_phy_reset_ich8lan(hw);
}
/**
@@ -1970,25 +2605,24 @@ out:
**/
static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 oem_reg;
DEBUGFUNC("e1000_set_lplu_state_pchlan");
ret_val = hw->phy.ops.read_reg(hw, HV_OEM_BITS, &oem_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (active)
oem_reg |= HV_OEM_BITS_LPLU;
else
oem_reg &= ~HV_OEM_BITS_LPLU;
- oem_reg |= HV_OEM_BITS_RESTART_AN;
- ret_val = hw->phy.ops.write_reg(hw, HV_OEM_BITS, oem_reg);
+ if (!hw->phy.ops.check_reset_block(hw))
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
-out:
- return ret_val;
+ return hw->phy.ops.write_reg(hw, HV_OEM_BITS, oem_reg);
}
/**
@@ -2014,7 +2648,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan");
if (phy->type == e1000_phy_ife)
- goto out;
+ return E1000_SUCCESS;
phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
@@ -2023,10 +2657,9 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
if (phy->type != e1000_phy_igp_3)
- goto out;
+ return E1000_SUCCESS;
- /*
- * Call gig speed drop workaround on LPLU before accessing
+ /* Call gig speed drop workaround on LPLU before accessing
* any PHY registers
*/
if (hw->mac.type == e1000_ich8lan)
@@ -2034,58 +2667,58 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
/* When LPLU is enabled, we should disable SmartSpeed */
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
+ if (ret_val)
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
} else {
phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
if (phy->type != e1000_phy_igp_3)
- goto out;
+ return E1000_SUCCESS;
- /*
- * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
* important. During driver activity we should enable
* SmartSpeed, so performance is maintained.
*/
if (phy->smart_speed == e1000_smart_speed_on) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data |= IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
} else if (phy->smart_speed == e1000_smart_speed_off) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
}
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2117,52 +2750,50 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
if (phy->type != e1000_phy_igp_3)
- goto out;
+ return E1000_SUCCESS;
- /*
- * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
* important. During driver activity we should enable
* SmartSpeed, so performance is maintained.
*/
if (phy->smart_speed == e1000_smart_speed_on) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data |= IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
} else if (phy->smart_speed == e1000_smart_speed_off) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
}
} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
- (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
- (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
if (phy->type != e1000_phy_igp_3)
- goto out;
+ return E1000_SUCCESS;
- /*
- * Call gig speed drop workaround on LPLU before accessing
+ /* Call gig speed drop workaround on LPLU before accessing
* any PHY registers
*/
if (hw->mac.type == e1000_ich8lan)
@@ -2170,18 +2801,17 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
/* When LPLU is enabled, we should disable SmartSpeed */
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
}
-out:
return ret_val;
}
@@ -2200,7 +2830,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
u8 sig_byte = 0;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan");
@@ -2215,10 +2845,9 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
else
*bank = 0;
- goto out;
+ return E1000_SUCCESS;
}
- DEBUGOUT("Unable to determine valid NVM bank via EEC - "
- "reading flash signature\n");
+ DEBUGOUT("Unable to determine valid NVM bank via EEC - reading flash signature\n");
/* fall-thru */
default:
/* set bank to 0 in case flash read fails */
@@ -2226,33 +2855,30 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
/* Check bank 0 */
ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset,
- &sig_byte);
+ &sig_byte);
if (ret_val)
- goto out;
+ return ret_val;
if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
E1000_ICH_NVM_SIG_VALUE) {
*bank = 0;
- goto out;
+ return E1000_SUCCESS;
}
/* Check bank 1 */
ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset +
- bank1_offset,
- &sig_byte);
+ bank1_offset,
+ &sig_byte);
if (ret_val)
- goto out;
+ return ret_val;
if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
E1000_ICH_NVM_SIG_VALUE) {
*bank = 1;
- goto out;
+ return E1000_SUCCESS;
}
DEBUGOUT("ERROR: No valid NVM bank present\n");
- ret_val = -E1000_ERR_NVM;
- break;
+ return -E1000_ERR_NVM;
}
-out:
- return ret_val;
}
/**
@@ -2265,7 +2891,7 @@ out:
* Reads a word(s) from the NVM using the flash access registers.
**/
static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+ u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
@@ -2296,13 +2922,12 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
ret_val = E1000_SUCCESS;
for (i = 0; i < words; i++) {
- if ((dev_spec->shadow_ram) &&
- (dev_spec->shadow_ram[offset+i].modified)) {
+ if (dev_spec->shadow_ram[offset+i].modified) {
data[i] = dev_spec->shadow_ram[offset+i].value;
} else {
ret_val = e1000_read_flash_word_ich8lan(hw,
- act_offset + i,
- &word);
+ act_offset + i,
+ &word);
if (ret_val)
break;
data[i] = word;
@@ -2329,17 +2954,15 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
{
union ich8_hws_flash_status hsfsts;
s32 ret_val = -E1000_ERR_NVM;
- s32 i = 0;
DEBUGFUNC("e1000_flash_cycle_init_ich8lan");
hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
/* Check if the flash descriptor is valid */
- if (hsfsts.hsf_status.fldesvalid == 0) {
- DEBUGOUT("Flash descriptor invalid. "
- "SW Sequencing must be used.");
- goto out;
+ if (!hsfsts.hsf_status.fldesvalid) {
+ DEBUGOUT("Flash descriptor invalid. SW Sequencing must be used.\n");
+ return -E1000_ERR_NVM;
}
/* Clear FCERR and DAEL in hw status by writing 1 */
@@ -2348,8 +2971,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
- /*
- * Either we should have a hardware SPI cycle in progress
+ /* Either we should have a hardware SPI cycle in progress
* bit to check against, in order to start a new cycle or
* FDONE bit should be changed in the hardware so that it
* is 1 after hardware reset, which can then be used as an
@@ -2357,9 +2979,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
* completed.
*/
- if (hsfsts.hsf_status.flcinprog == 0) {
- /*
- * There is no cycle running at present,
+ if (!hsfsts.hsf_status.flcinprog) {
+ /* There is no cycle running at present,
* so we can start a cycle.
* Begin by setting Flash Cycle Done.
*/
@@ -2367,33 +2988,32 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
ret_val = E1000_SUCCESS;
} else {
- /*
- * Otherwise poll for sometime so the current
+ s32 i;
+
+ /* Otherwise poll for sometime so the current
* cycle has a chance to end before giving up.
*/
for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
hsfsts.regval = E1000_READ_FLASH_REG16(hw,
- ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcinprog == 0) {
+ ICH_FLASH_HSFSTS);
+ if (!hsfsts.hsf_status.flcinprog) {
ret_val = E1000_SUCCESS;
break;
}
usec_delay(1);
}
if (ret_val == E1000_SUCCESS) {
- /*
- * Successful in waiting for previous cycle to timeout,
+ /* Successful in waiting for previous cycle to timeout,
* now set the Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
- hsfsts.regval);
+ hsfsts.regval);
} else {
- DEBUGOUT("Flash controller busy, cannot get access");
+ DEBUGOUT("Flash controller busy, cannot get access\n");
}
}
-out:
return ret_val;
}
@@ -2408,7 +3028,6 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
{
union ich8_hws_flash_ctrl hsflctl;
union ich8_hws_flash_status hsfsts;
- s32 ret_val = -E1000_ERR_NVM;
u32 i = 0;
DEBUGFUNC("e1000_flash_cycle_ich8lan");
@@ -2421,15 +3040,15 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
/* wait till FDONE bit is set to 1 */
do {
hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcdone == 1)
+ if (hsfsts.hsf_status.flcdone)
break;
usec_delay(1);
} while (i++ < timeout);
- if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0)
- ret_val = E1000_SUCCESS;
+ if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr)
+ return E1000_SUCCESS;
- return ret_val;
+ return -E1000_ERR_NVM;
}
/**
@@ -2442,24 +3061,17 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
* to bytes before read.
**/
static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
- u16 *data)
+ u16 *data)
{
- s32 ret_val;
-
DEBUGFUNC("e1000_read_flash_word_ich8lan");
- if (!data) {
- ret_val = -E1000_ERR_NVM;
- goto out;
- }
+ if (!data)
+ return -E1000_ERR_NVM;
/* Must convert offset into bytes. */
offset <<= 1;
- ret_val = e1000_read_flash_data_ich8lan(hw, offset, 2, data);
-
-out:
- return ret_val;
+ return e1000_read_flash_data_ich8lan(hw, offset, 2, data);
}
/**
@@ -2471,19 +3083,18 @@ out:
* Reads a single byte from the NVM using the flash access registers.
**/
static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
- u8 *data)
+ u8 *data)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 word = 0;
ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
if (ret_val)
- goto out;
+ return ret_val;
*data = (u8)word;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2496,7 +3107,7 @@ out:
* Reads a byte or word from the NVM using the flash access registers.
**/
static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
- u8 size, u16 *data)
+ u8 size, u16 *data)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
@@ -2508,10 +3119,10 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
DEBUGFUNC("e1000_read_flash_data_ich8lan");
if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
- goto out;
+ return -E1000_ERR_NVM;
flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
- hw->nvm.flash_base_addr;
+ hw->nvm.flash_base_addr;
do {
usec_delay(1);
@@ -2529,10 +3140,9 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
ret_val = e1000_flash_cycle_ich8lan(hw,
- ICH_FLASH_READ_COMMAND_TIMEOUT);
+ ICH_FLASH_READ_COMMAND_TIMEOUT);
- /*
- * Check if FCERR is set to 1, if set to 1, clear it
+ /* Check if FCERR is set to 1, if set to 1, clear it
* and try the whole sequence a few more times, else
* read in (shift in) the Flash Data0, the order is
* least significant byte first msb to lsb
@@ -2545,26 +3155,23 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
*data = (u16)(flash_data & 0x0000FFFF);
break;
} else {
- /*
- * If we've gotten here, then things are probably
+ /* If we've gotten here, then things are probably
* completely hosed, but if the error condition is
* detected, it won't hurt to give it another try...
* ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
hsfsts.regval = E1000_READ_FLASH_REG16(hw,
- ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1) {
+ ICH_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcerr) {
/* Repeat for some time before giving up. */
continue;
- } else if (hsfsts.hsf_status.flcdone == 0) {
- DEBUGOUT("Timeout error - flash cycle "
- "did not complete.");
+ } else if (!hsfsts.hsf_status.flcdone) {
+ DEBUGOUT("Timeout error - flash cycle did not complete.\n");
break;
}
}
} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
-out:
return ret_val;
}
@@ -2578,11 +3185,10 @@ out:
* Writes a byte or word to the NVM using the flash access registers.
**/
static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+ u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
- s32 ret_val = E1000_SUCCESS;
u16 i;
DEBUGFUNC("e1000_write_nvm_ich8lan");
@@ -2590,8 +3196,7 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
nvm->ops.acquire(hw);
@@ -2603,8 +3208,7 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
nvm->ops.release(hw);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2637,8 +3241,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
nvm->ops.acquire(hw);
- /*
- * We're writing to the opposite bank so if we're on bank 1,
+ /* We're writing to the opposite bank so if we're on bank 1,
* write to bank 0 etc. We also need to erase the segment that
* is going to be written
*/
@@ -2663,8 +3266,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
}
for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
- /*
- * Determine whether to write the value stored
+ /* Determine whether to write the value stored
* in the other NVM bank or a modified value stored
* in the shadow RAM
*/
@@ -2672,14 +3274,13 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
data = dev_spec->shadow_ram[i].value;
} else {
ret_val = e1000_read_flash_word_ich8lan(hw, i +
- old_bank_offset,
- &data);
+ old_bank_offset,
+ &data);
if (ret_val)
break;
}
- /*
- * If the word is 0x13, then make sure the signature bits
+ /* If the word is 0x13, then make sure the signature bits
* (15:14) are 11b until the commit has completed.
* This will allow us to write 10b which indicates the
* signature is valid. We want to do this after the write
@@ -2695,21 +3296,20 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
usec_delay(100);
/* Write the bytes to the new bank. */
ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
- act_offset,
- (u8)data);
+ act_offset,
+ (u8)data);
if (ret_val)
break;
usec_delay(100);
ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
- act_offset + 1,
- (u8)(data >> 8));
+ act_offset + 1,
+ (u8)(data >> 8));
if (ret_val)
break;
}
- /*
- * Don't bother writing the segment valid bits if sector
+ /* Don't bother writing the segment valid bits if sector
* programming failed.
*/
if (ret_val) {
@@ -2717,8 +3317,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
goto release;
}
- /*
- * Finally validate the new segment by setting bit 15:14
+ /* Finally validate the new segment by setting bit 15:14
* to 10b in word 0x13 , this can be done without an
* erase as well since these bits are 11 to start with
* and we need to change bit 14 to 0b
@@ -2730,13 +3329,12 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
data &= 0xBFFF;
ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
- act_offset * 2 + 1,
- (u8)(data >> 8));
+ act_offset * 2 + 1,
+ (u8)(data >> 8));
if (ret_val)
goto release;
- /*
- * And invalidate the previously valid segment by setting
+ /* And invalidate the previously valid segment by setting
* its signature word (0x13) high_byte to 0b. This can be
* done without an erase because flash erase sets all bits
* to 1's. We can write 1's to 0's without an erase
@@ -2755,8 +3353,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
release:
nvm->ops.release(hw);
- /*
- * Reload the EEPROM, or else modifications will not appear
+ /* Reload the EEPROM, or else modifications will not appear
* until after the next adapter reset.
*/
if (!ret_val) {
@@ -2781,35 +3378,44 @@ out:
**/
static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 data;
+ u16 word;
+ u16 valid_csum_mask;
DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan");
- /*
- * Read 0x19 and check bit 6. If this bit is 0, the checksum
- * needs to be fixed. This bit is an indication that the NVM
- * was prepared by OEM software and did not calculate the
- * checksum...a likely scenario.
+ /* Read NVM and check Invalid Image CSUM bit. If this bit is 0,
+ * the checksum needs to be fixed. This bit is an indication that
+ * the NVM was prepared by OEM software and did not calculate
+ * the checksum...a likely scenario.
*/
- ret_val = hw->nvm.ops.read(hw, 0x19, 1, &data);
+ switch (hw->mac.type) {
+ case e1000_pch_lpt:
+ word = NVM_COMPAT;
+ valid_csum_mask = NVM_COMPAT_VALID_CSUM;
+ break;
+ default:
+ word = NVM_FUTURE_INIT_WORD1;
+ valid_csum_mask = NVM_FUTURE_INIT_WORD1_VALID_CSUM;
+ break;
+ }
+
+ ret_val = hw->nvm.ops.read(hw, word, 1, &data);
if (ret_val)
- goto out;
+ return ret_val;
- if ((data & 0x40) == 0) {
- data |= 0x40;
- ret_val = hw->nvm.ops.write(hw, 0x19, 1, &data);
+ if (!(data & valid_csum_mask)) {
+ data |= valid_csum_mask;
+ ret_val = hw->nvm.ops.write(hw, word, 1, &data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = hw->nvm.ops.update(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- ret_val = e1000_validate_nvm_checksum_generic(hw);
-
-out:
- return ret_val;
+ return e1000_validate_nvm_checksum_generic(hw);
}
/**
@@ -2822,23 +3428,23 @@ out:
* Writes one/two bytes to the NVM using the flash access registers.
**/
static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
- u8 size, u16 data)
+ u8 size, u16 data)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
u32 flash_linear_addr;
u32 flash_data = 0;
- s32 ret_val = -E1000_ERR_NVM;
+ s32 ret_val;
u8 count = 0;
DEBUGFUNC("e1000_write_ich8_data");
if (size < 1 || size > 2 || data > size * 0xff ||
offset > ICH_FLASH_LINEAR_ADDR_MASK)
- goto out;
+ return -E1000_ERR_NVM;
flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
- hw->nvm.flash_base_addr;
+ hw->nvm.flash_base_addr;
do {
usec_delay(1);
@@ -2862,33 +3468,29 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
- /*
- * check if FCERR is set to 1 , if set to 1, clear it
+ /* check if FCERR is set to 1 , if set to 1, clear it
* and try the whole sequence a few more times else done
*/
ret_val = e1000_flash_cycle_ich8lan(hw,
- ICH_FLASH_WRITE_COMMAND_TIMEOUT);
+ ICH_FLASH_WRITE_COMMAND_TIMEOUT);
if (ret_val == E1000_SUCCESS)
break;
- /*
- * If we're here, then things are most likely
+ /* If we're here, then things are most likely
* completely hosed, but if the error condition
* is detected, it won't hurt to give it another
* try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1)
+ if (hsfsts.hsf_status.flcerr)
/* Repeat for some time before giving up. */
continue;
- if (hsfsts.hsf_status.flcdone == 0) {
- DEBUGOUT("Timeout error - flash cycle "
- "did not complete.");
+ if (!hsfsts.hsf_status.flcdone) {
+ DEBUGOUT("Timeout error - flash cycle did not complete.\n");
break;
}
} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
-out:
return ret_val;
}
@@ -2901,7 +3503,7 @@ out:
* Writes a single byte to the NVM using the flash access registers.
**/
static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
- u8 data)
+ u8 data)
{
u16 word = (u16)data;
@@ -2920,7 +3522,7 @@ static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
* Goes through a retry algorithm before giving up.
**/
static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
- u32 offset, u8 byte)
+ u32 offset, u8 byte)
{
s32 ret_val;
u16 program_retries;
@@ -2928,8 +3530,8 @@ static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan");
ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
- if (ret_val == E1000_SUCCESS)
- goto out;
+ if (!ret_val)
+ return ret_val;
for (program_retries = 0; program_retries < 100; program_retries++) {
DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset);
@@ -2938,13 +3540,10 @@ static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
if (ret_val == E1000_SUCCESS)
break;
}
- if (program_retries == 100) {
- ret_val = -E1000_ERR_NVM;
- goto out;
- }
+ if (program_retries == 100)
+ return -E1000_ERR_NVM;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2963,7 +3562,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
u32 flash_linear_addr;
/* bank size is in 16bit words - adjust to bytes */
u32 flash_bank_size = nvm->flash_bank_size * 2;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
s32 count = 0;
s32 j, iteration, sector_size;
@@ -2971,8 +3570,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
- /*
- * Determine HW Sector size: Read BERASE bits of hw flash status
+ /* Determine HW Sector size: Read BERASE bits of hw flash status
* register
* 00: The Hw sector is 256 bytes, hence we need to erase 16
* consecutive sectors. The start index for the nth Hw sector
@@ -3003,8 +3601,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
iteration = 1;
break;
default:
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
/* Start with the base address, then add the sector offset. */
@@ -3016,49 +3613,45 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
/* Steps */
ret_val = e1000_flash_cycle_init_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * Write a value 11 (block Erase) in Flash
+ /* Write a value 11 (block Erase) in Flash
* Cycle field in hw flash control
*/
hsflctl.regval = E1000_READ_FLASH_REG16(hw,
- ICH_FLASH_HSFCTL);
+ ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
- hsflctl.regval);
+ hsflctl.regval);
- /*
- * Write the last 24 bits of an index within the
+ /* Write the last 24 bits of an index within the
* block into Flash Linear address field in Flash
* Address.
*/
flash_linear_addr += (j * sector_size);
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR,
- flash_linear_addr);
+ flash_linear_addr);
ret_val = e1000_flash_cycle_ich8lan(hw,
- ICH_FLASH_ERASE_COMMAND_TIMEOUT);
+ ICH_FLASH_ERASE_COMMAND_TIMEOUT);
if (ret_val == E1000_SUCCESS)
break;
- /*
- * Check if FCERR is set to 1. If 1,
+ /* Check if FCERR is set to 1. If 1,
* clear it and try the whole sequence
* a few more times else Done
*/
hsfsts.regval = E1000_READ_FLASH_REG16(hw,
ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1)
+ if (hsfsts.hsf_status.flcerr)
/* repeat for some time before giving up */
continue;
- else if (hsfsts.hsf_status.flcdone == 0)
- goto out;
+ else if (!hsfsts.hsf_status.flcdone)
+ return ret_val;
} while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT);
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -3079,15 +3672,13 @@ static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data)
ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
- if (*data == ID_LED_RESERVED_0000 ||
- *data == ID_LED_RESERVED_FFFF)
+ if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
*data = ID_LED_DEFAULT_ICH8LAN;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -3116,7 +3707,7 @@ static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw)
/* Get default ID LED modes */
ret_val = hw->nvm.ops.valid_led_default(hw, &data);
if (ret_val)
- goto out;
+ return ret_val;
mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL);
mac->ledctl_mode1 = mac->ledctl_default;
@@ -3161,8 +3752,7 @@ static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw)
}
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -3181,8 +3771,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
ret_val = e1000_get_bus_info_pcie_generic(hw);
- /*
- * ICH devices are "PCI Express"-ish. They have
+ /* ICH devices are "PCI Express"-ish. They have
* a configuration space, but do not contain
* PCI Express Capability registers, so bus width
* must be hardcoded.
@@ -3203,14 +3792,13 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
{
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
- u16 reg;
- u32 ctrl, icr, kab;
+ u16 kum_cfg;
+ u32 ctrl, reg;
s32 ret_val;
DEBUGFUNC("e1000_reset_hw_ich8lan");
- /*
- * Prevent the PCI-E bus from sticking if there is no TLP connection
+ /* Prevent the PCI-E bus from sticking if there is no TLP connection
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = e1000_disable_pcie_master_generic(hw);
@@ -3220,8 +3808,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
DEBUGOUT("Masking off all interrupts\n");
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- /*
- * Disable the Transmit and Receive units. Then delay to allow
+ /* Disable the Transmit and Receive units. Then delay to allow
* any pending transactions to complete before we hit the MAC
* with the global reset.
*/
@@ -3241,11 +3828,11 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
if (hw->mac.type == e1000_pchlan) {
/* Save the NVM K1 bit setting*/
- ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &reg);
+ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg);
if (ret_val)
return ret_val;
- if (reg & E1000_NVM_K1_ENABLE)
+ if (kum_cfg & E1000_NVM_K1_ENABLE)
dev_spec->nvm_k1_enabled = TRUE;
else
dev_spec->nvm_k1_enabled = FALSE;
@@ -3254,15 +3841,13 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ctrl = E1000_READ_REG(hw, E1000_CTRL);
if (!hw->phy.ops.check_reset_block(hw)) {
- /*
- * Full-chip reset requires MAC and PHY reset at the same
+ /* Full-chip reset requires MAC and PHY reset at the same
* time to make sure the interface between MAC and the
* external PHY is reset.
*/
ctrl |= E1000_CTRL_PHY_RST;
- /*
- * Gate automatic PHY configuration by hardware on
+ /* Gate automatic PHY configuration by hardware on
* non-managed 82579
*/
if ((hw->mac.type == e1000_pch2lan) &&
@@ -3272,23 +3857,31 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ret_val = e1000_acquire_swflag_ich8lan(hw);
DEBUGOUT("Issuing a global reset to ich8lan\n");
E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST));
+ /* cannot issue a flush here because it hangs the hardware */
msec_delay(20);
+ /* Set Phy Config Counter to 50msec */
+ if (hw->mac.type == e1000_pch2lan) {
+ reg = E1000_READ_REG(hw, E1000_FEXTNVM3);
+ reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ E1000_WRITE_REG(hw, E1000_FEXTNVM3, reg);
+ }
+
if (!ret_val)
- e1000_release_swflag_ich8lan(hw);
+ E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex);
if (ctrl & E1000_CTRL_PHY_RST) {
ret_val = hw->phy.ops.get_cfg_done(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_post_phy_reset_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- /*
- * For PCH, this write will make sure that any noise
+ /* For PCH, this write will make sure that any noise
* will be detected as a CRC error and be dropped rather than show up
* as a bad packet to the DMA engine.
*/
@@ -3296,14 +3889,13 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_CRC_OFFSET, 0x65656565);
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
- kab = E1000_READ_REG(hw, E1000_KABGTXD);
- kab |= E1000_KABGTXD_BGSQLBIAS;
- E1000_WRITE_REG(hw, E1000_KABGTXD, kab);
+ reg = E1000_READ_REG(hw, E1000_KABGTXD);
+ reg |= E1000_KABGTXD_BGSQLBIAS;
+ E1000_WRITE_REG(hw, E1000_KABGTXD, reg);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -3331,9 +3923,9 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
/* Initialize identification LED */
ret_val = mac->ops.id_led_init(hw);
+ /* An error is not fatal and we should not stop init due to this */
if (ret_val)
DEBUGOUT("Error initializing identification LED\n");
- /* This is not fatal and we should not stop init due to this */
/* Setup the receive address. */
e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
@@ -3343,13 +3935,14 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
for (i = 0; i < mac->mta_reg_count; i++)
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
- /*
- * The 82578 Rx buffer will stall if wakeup is enabled in host and
- * the ME. Reading the BM_WUC register will clear the host wakeup bit.
+ /* The 82578 Rx buffer will stall if wakeup is enabled in host and
+ * the ME. Disable wakeup by clearing the host wakeup bit.
* Reset the phy after disabling host wakeup to reset the Rx buffer.
*/
if (hw->phy.type == e1000_phy_82578) {
- hw->phy.ops.read_reg(hw, BM_WUC, &i);
+ hw->phy.ops.read_reg(hw, BM_PORT_GEN_CFG, &i);
+ i &= ~BM_WUC_HOST_WU_BIT;
+ hw->phy.ops.write_reg(hw, BM_PORT_GEN_CFG, i);
ret_val = e1000_phy_hw_reset_ich8lan(hw);
if (ret_val)
return ret_val;
@@ -3363,17 +3956,16 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB;
txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
- E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
+ E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
txdctl = E1000_READ_REG(hw, E1000_TXDCTL(1));
txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB;
txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
- E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
+ E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl);
- /*
- * ICH8 has opposite polarity of no_snoop bits.
+ /* ICH8 has opposite polarity of no_snoop bits.
* By default, we should use snoop behavior.
*/
if (mac->type == e1000_ich8lan)
@@ -3386,8 +3978,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
- /*
- * Clear all of the statistics registers (clear on read). It is
+ /* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
* is no link.
@@ -3396,6 +3987,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
return ret_val;
}
+
/**
* e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits
* @hw: pointer to the HW structure
@@ -3450,14 +4042,29 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_STATUS, reg);
}
- /*
- * work-around descriptor data corruption issue during nfs v2 udp
+ /* work-around descriptor data corruption issue during nfs v2 udp
* traffic, just disable the nfs filtering capability
*/
reg = E1000_READ_REG(hw, E1000_RFCTL);
reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
+ /* Disable IPv6 extension header parsing because some malformed
+ * IPv6 headers can hang the Rx.
+ */
+ if (hw->mac.type == e1000_ich8lan)
+ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
E1000_WRITE_REG(hw, E1000_RFCTL, reg);
+ /* Enable ECC on Lynxpoint */
+ if (hw->mac.type == e1000_pch_lpt) {
+ reg = E1000_READ_REG(hw, E1000_PBECCSTS);
+ reg |= E1000_PBECCSTS_ECC_ENABLE;
+ E1000_WRITE_REG(hw, E1000_PBECCSTS, reg);
+
+ reg = E1000_READ_REG(hw, E1000_CTRL);
+ reg |= E1000_CTRL_MEHE;
+ E1000_WRITE_REG(hw, E1000_CTRL, reg);
+ }
+
return;
}
@@ -3473,23 +4080,21 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
**/
static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_setup_link_ich8lan");
if (hw->phy.ops.check_reset_block(hw))
- goto out;
+ return E1000_SUCCESS;
- /*
- * ICH parts do not have a word in the NVM to determine
+ /* ICH parts do not have a word in the NVM to determine
* the default flow control setting, so we explicitly
* set it to full.
*/
if (hw->fc.requested_mode == e1000_fc_default)
hw->fc.requested_mode = e1000_fc_full;
- /*
- * Save off the requested flow control mode for use later. Depending
+ /* Save off the requested flow control mode for use later. Depending
* on the link partner's capabilities, we may or may not use this mode.
*/
hw->fc.current_mode = hw->fc.requested_mode;
@@ -3500,25 +4105,23 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
/* Continue to configure the copper link. */
ret_val = hw->mac.ops.setup_physical_interface(hw);
if (ret_val)
- goto out;
+ return ret_val;
E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
+ (hw->phy.type == e1000_phy_i217) ||
(hw->phy.type == e1000_phy_82577)) {
E1000_WRITE_REG(hw, E1000_FCRTV_PCH, hw->fc.refresh_time);
ret_val = hw->phy.ops.write_reg(hw,
- PHY_REG(BM_PORT_CTRL_PAGE, 27),
- hw->fc.pause_time);
+ PHY_REG(BM_PORT_CTRL_PAGE, 27),
+ hw->fc.pause_time);
if (ret_val)
- goto out;
+ return ret_val;
}
- ret_val = e1000_set_fc_watermarks_generic(hw);
-
-out:
- return ret_val;
+ return e1000_set_fc_watermarks_generic(hw);
}
/**
@@ -3542,50 +4145,49 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
- /*
- * Set the mac to wait the maximum time between each iteration
+ /* Set the mac to wait the maximum time between each iteration
* and increase the max iterations when polling the phy;
* this fixes erroneous timeouts at 10Mbps.
*/
ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_TIMEOUTS,
- 0xFFFF);
+ 0xFFFF);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_read_kmrn_reg_generic(hw,
- E1000_KMRNCTRLSTA_INBAND_PARAM,
- &reg_data);
+ E1000_KMRNCTRLSTA_INBAND_PARAM,
+ &reg_data);
if (ret_val)
- goto out;
+ return ret_val;
reg_data |= 0x3F;
ret_val = e1000_write_kmrn_reg_generic(hw,
- E1000_KMRNCTRLSTA_INBAND_PARAM,
- reg_data);
+ E1000_KMRNCTRLSTA_INBAND_PARAM,
+ reg_data);
if (ret_val)
- goto out;
+ return ret_val;
switch (hw->phy.type) {
case e1000_phy_igp_3:
ret_val = e1000_copper_link_setup_igp(hw);
if (ret_val)
- goto out;
+ return ret_val;
break;
case e1000_phy_bm:
case e1000_phy_82578:
ret_val = e1000_copper_link_setup_m88(hw);
if (ret_val)
- goto out;
+ return ret_val;
break;
case e1000_phy_82577:
case e1000_phy_82579:
ret_val = e1000_copper_link_setup_82577(hw);
if (ret_val)
- goto out;
+ return ret_val;
break;
case e1000_phy_ife:
ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL,
- &reg_data);
+ &reg_data);
if (ret_val)
- goto out;
+ return ret_val;
reg_data &= ~IFE_PMC_AUTO_MDIX;
@@ -3602,17 +4204,42 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
break;
}
ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL,
- reg_data);
+ reg_data);
if (ret_val)
- goto out;
+ return ret_val;
break;
default:
break;
}
- ret_val = e1000_setup_copper_link_generic(hw);
-out:
- return ret_val;
+ return e1000_setup_copper_link_generic(hw);
+}
+
+/**
+ * e1000_setup_copper_link_pch_lpt - Configure MAC/PHY interface
+ * @hw: pointer to the HW structure
+ *
+ * Calls the PHY specific link setup function and then calls the
+ * generic setup_copper_link to finish configuring the link for
+ * Lynxpoint PCH devices
+ **/
+static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw)
+{
+ u32 ctrl;
+ s32 ret_val;
+
+ DEBUGFUNC("e1000_setup_copper_link_pch_lpt");
+
+ ctrl = E1000_READ_REG(hw, E1000_CTRL);
+ ctrl |= E1000_CTRL_SLU;
+ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+ ret_val = e1000_copper_link_setup_82577(hw);
+ if (ret_val)
+ return ret_val;
+
+ return e1000_setup_copper_link_generic(hw);
}
/**
@@ -3626,7 +4253,7 @@ out:
* gigabit speeds.
**/
static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
- u16 *duplex)
+ u16 *duplex)
{
s32 ret_val;
@@ -3634,7 +4261,7 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex);
if (ret_val)
- goto out;
+ return ret_val;
if ((hw->mac.type == e1000_ich8lan) &&
(hw->phy.type == e1000_phy_igp_3) &&
@@ -3642,7 +4269,6 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw);
}
-out:
return ret_val;
}
@@ -3665,41 +4291,36 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
{
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 phy_ctrl;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 i, data;
bool link;
DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan");
- if (!(dev_spec->kmrn_lock_loss_workaround_enabled))
- goto out;
+ if (!dev_spec->kmrn_lock_loss_workaround_enabled)
+ return E1000_SUCCESS;
- /*
- * Make sure link is up before proceeding. If not just return.
+ /* Make sure link is up before proceeding. If not just return.
* Attempting this while link is negotiating fouled up link
* stability
*/
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
- if (!link) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
+ if (!link)
+ return E1000_SUCCESS;
for (i = 0; i < 10; i++) {
/* read once to clear */
ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data);
if (ret_val)
- goto out;
+ return ret_val;
/* and again to get new status */
ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data);
if (ret_val)
- goto out;
+ return ret_val;
/* check for PCS lock */
- if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
+ if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS))
+ return E1000_SUCCESS;
/* Issue PHY reset */
hw->phy.ops.reset(hw);
@@ -3708,20 +4329,16 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
/* Disable GigE link negotiation */
phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE |
- E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+ E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
- /*
- * Call gig speed drop workaround on Gig disable before accessing
+ /* Call gig speed drop workaround on Gig disable before accessing
* any PHY registers
*/
e1000_gig_downshift_workaround_ich8lan(hw);
/* unable to acquire PCS lock */
- ret_val = -E1000_ERR_PHY;
-
-out:
- return ret_val;
+ return -E1000_ERR_PHY;
}
/**
@@ -3733,7 +4350,7 @@ out:
* /disabled - FALSE).
**/
void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
- bool state)
+ bool state)
{
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
@@ -3768,18 +4385,17 @@ void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_igp3_phy_powerdown_workaround_ich8lan");
if (hw->phy.type != e1000_phy_igp_3)
- goto out;
+ return;
/* Try the workaround twice (if needed) */
do {
/* Disable link */
reg = E1000_READ_REG(hw, E1000_PHY_CTRL);
reg |= (E1000_PHY_CTRL_GBE_DISABLE |
- E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+ E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
E1000_WRITE_REG(hw, E1000_PHY_CTRL, reg);
- /*
- * Call gig speed drop workaround on Gig disable before
+ /* Call gig speed drop workaround on Gig disable before
* accessing any PHY registers
*/
if (hw->mac.type == e1000_ich8lan)
@@ -3789,7 +4405,7 @@ void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data);
data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
hw->phy.ops.write_reg(hw, IGP3_VR_CTRL,
- data | IGP3_VR_CTRL_MODE_SHUTDOWN);
+ data | IGP3_VR_CTRL_MODE_SHUTDOWN);
/* Read it back and test */
hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data);
@@ -3802,9 +4418,6 @@ void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_CTRL, reg | E1000_CTRL_PHY_RST);
retry++;
} while (retry);
-
-out:
- return;
}
/**
@@ -3815,61 +4428,148 @@ out:
* LPLU, Gig disable, MDIC PHY reset):
* 1) Set Kumeran Near-end loopback
* 2) Clear Kumeran Near-end loopback
- * Should only be called for ICH8[m] devices with IGP_3 Phy.
+ * Should only be called for ICH8[m] devices with any 1G Phy.
**/
void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 reg_data;
DEBUGFUNC("e1000_gig_downshift_workaround_ich8lan");
if ((hw->mac.type != e1000_ich8lan) ||
- (hw->phy.type != e1000_phy_igp_3))
- goto out;
+ (hw->phy.type == e1000_phy_ife))
+ return;
ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
- &reg_data);
+ &reg_data);
if (ret_val)
- goto out;
+ return;
reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK;
ret_val = e1000_write_kmrn_reg_generic(hw,
- E1000_KMRNCTRLSTA_DIAG_OFFSET,
- reg_data);
+ E1000_KMRNCTRLSTA_DIAG_OFFSET,
+ reg_data);
if (ret_val)
- goto out;
+ return;
reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK;
- ret_val = e1000_write_kmrn_reg_generic(hw,
- E1000_KMRNCTRLSTA_DIAG_OFFSET,
- reg_data);
-out:
- return;
+ e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
+ reg_data);
}
/**
- * e1000_disable_gig_wol_ich8lan - disable gig during WoL
+ * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
* @hw: pointer to the HW structure
*
* During S0 to Sx transition, it is possible the link remains at gig
* instead of negotiating to a lower speed. Before going to Sx, set
- * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
- * to a lower speed.
- *
- * Should only be called for applicable parts.
+ * 'Gig Disable' to force link speed negotiation to a lower speed based on
+ * the LPLU setting in the NVM or custom setting. For PCH and newer parts,
+ * the OEM bits PHY register (LED, GbE disable and LPLU configurations) also
+ * needs to be written.
+ * Parts that support (and are linked to a partner which support) EEE in
+ * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power
+ * than 10Mbps w/o EEE.
**/
-void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw)
+void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 phy_ctrl;
s32 ret_val;
- DEBUGFUNC("e1000_disable_gig_wol_ich8lan");
+ DEBUGFUNC("e1000_suspend_workarounds_ich8lan");
phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
- phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE;
+ phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
+
+ if (hw->phy.type == e1000_phy_i217) {
+ u16 phy_reg, device_id = hw->device_id;
+
+ if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+ (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
+ u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
+
+ E1000_WRITE_REG(hw, E1000_FEXTNVM6,
+ fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
+ }
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
+ if (!dev_spec->eee_disable) {
+ u16 eee_advert;
+
+ ret_val =
+ e1000_read_emi_reg_locked(hw,
+ I217_EEE_ADVERTISEMENT,
+ &eee_advert);
+ if (ret_val)
+ goto release;
+
+ /* Disable LPLU if both link partners support 100BaseT
+ * EEE and 100Full is advertised on both ends of the
+ * link.
+ */
+ if ((eee_advert & I82579_EEE_100_SUPPORTED) &&
+ (dev_spec->eee_lp_ability &
+ I82579_EEE_100_SUPPORTED) &&
+ (hw->phy.autoneg_advertised & ADVERTISE_100_FULL))
+ phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
+ E1000_PHY_CTRL_NOND0A_LPLU);
+ }
+
+ /* For i217 Intel Rapid Start Technology support,
+ * when the system is going into Sx and no manageability engine
+ * is present, the driver must configure proxy to reset only on
+ * power good. LPI (Low Power Idle) state must also reset only
+ * on power good, as well as the MTA (Multicast table array).
+ * The SMBus release must also be disabled on LCD reset.
+ */
+ if (!(E1000_READ_REG(hw, E1000_FWSM) &
+ E1000_ICH_FWSM_FW_VALID)) {
+ /* Enable proxy to reset only on power good. */
+ hw->phy.ops.read_reg_locked(hw, I217_PROXY_CTRL,
+ &phy_reg);
+ phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
+ hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL,
+ phy_reg);
+
+ /* Set bit enable LPI (EEE) to reset only on
+ * power good.
+ */
+ hw->phy.ops.read_reg_locked(hw, I217_SxCTRL, &phy_reg);
+ phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET;
+ hw->phy.ops.write_reg_locked(hw, I217_SxCTRL, phy_reg);
+
+ /* Disable the SMB release on LCD reset. */
+ hw->phy.ops.read_reg_locked(hw, I217_MEMPWR, &phy_reg);
+ phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE;
+ hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg);
+ }
+
+ /* Enable MTA to reset for Intel Rapid Start Technology
+ * Support
+ */
+ hw->phy.ops.read_reg_locked(hw, I217_CGFREG, &phy_reg);
+ phy_reg |= I217_CGFREG_ENABLE_MTA_RESET;
+ hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg);
+
+release:
+ hw->phy.ops.release(hw);
+ }
+out:
E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
+ if (hw->mac.type == e1000_ich8lan)
+ e1000_gig_downshift_workaround_ich8lan(hw);
+
if (hw->mac.type >= e1000_pchlan) {
e1000_oem_bits_config_ich8lan(hw, FALSE);
+
+ /* Reset PHY to activate OEM bits on 82577/8 */
+ if (hw->mac.type == e1000_pchlan)
+ e1000_phy_hw_reset_generic(hw);
+
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return;
@@ -3881,6 +4581,74 @@ void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw)
}
/**
+ * e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0
+ * @hw: pointer to the HW structure
+ *
+ * During Sx to S0 transitions on non-managed devices or managed devices
+ * on which PHY resets are not blocked, if the PHY registers cannot be
+ * accessed properly by the s/w toggle the LANPHYPC value to power cycle
+ * the PHY.
+ * On i217, setup Intel Rapid Start Technology.
+ **/
+void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
+{
+ s32 ret_val;
+
+ DEBUGFUNC("e1000_resume_workarounds_pchlan");
+
+ if (hw->mac.type < e1000_pch2lan)
+ return;
+
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
+ if (ret_val) {
+ DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val);
+ return;
+ }
+
+ /* For i217 Intel Rapid Start Technology support when the system
+ * is transitioning from Sx and no manageability engine is present
+ * configure SMBus to restore on reset, disable proxy, and enable
+ * the reset on MTA (Multicast table array).
+ */
+ if (hw->phy.type == e1000_phy_i217) {
+ u16 phy_reg;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ DEBUGOUT("Failed to setup iRST\n");
+ return;
+ }
+
+ if (!(E1000_READ_REG(hw, E1000_FWSM) &
+ E1000_ICH_FWSM_FW_VALID)) {
+ /* Restore clear on SMB if no manageability engine
+ * is present
+ */
+ ret_val = hw->phy.ops.read_reg_locked(hw, I217_MEMPWR,
+ &phy_reg);
+ if (ret_val)
+ goto release;
+ phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE;
+ hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg);
+
+ /* Disable Proxy */
+ hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL, 0);
+ }
+ /* Enable reset on MTA */
+ ret_val = hw->phy.ops.read_reg_locked(hw, I217_CGFREG,
+ &phy_reg);
+ if (ret_val)
+ goto release;
+ phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET;
+ hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg);
+release:
+ if (ret_val)
+ DEBUGOUT1("Error %d in resume workarounds\n", ret_val);
+ hw->phy.ops.release(hw);
+ }
+}
+
+/**
* e1000_cleanup_led_ich8lan - Restore the default LED operation
* @hw: pointer to the HW structure
*
@@ -3892,7 +4660,7 @@ static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw)
if (hw->phy.type == e1000_phy_ife)
return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
- 0);
+ 0);
E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
return E1000_SUCCESS;
@@ -3910,7 +4678,7 @@ static s32 e1000_led_on_ich8lan(struct e1000_hw *hw)
if (hw->phy.type == e1000_phy_ife)
return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
- (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
+ (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2);
return E1000_SUCCESS;
@@ -3928,7 +4696,7 @@ static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
if (hw->phy.type == e1000_phy_ife)
return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
- (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
+ (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
return E1000_SUCCESS;
@@ -3945,7 +4713,7 @@ static s32 e1000_setup_led_pchlan(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_led_pchlan");
return hw->phy.ops.write_reg(hw, HV_LED_CONFIG,
- (u16)hw->mac.ledctl_mode1);
+ (u16)hw->mac.ledctl_mode1);
}
/**
@@ -3959,7 +4727,7 @@ static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw)
DEBUGFUNC("e1000_cleanup_led_pchlan");
return hw->phy.ops.write_reg(hw, HV_LED_CONFIG,
- (u16)hw->mac.ledctl_default);
+ (u16)hw->mac.ledctl_default);
}
/**
@@ -3975,8 +4743,7 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw)
DEBUGFUNC("e1000_led_on_pchlan");
- /*
- * If no link, then turn LED on by setting the invert bit
+ /* If no link, then turn LED on by setting the invert bit
* for each LED that's mode is "link_up" in ledctl_mode2.
*/
if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
@@ -4008,8 +4775,7 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
DEBUGFUNC("e1000_led_off_pchlan");
- /*
- * If no link, then turn LED off by clearing the invert bit
+ /* If no link, then turn LED off by clearing the invert bit
* for each LED that's mode is "link_up" in ledctl_mode1.
*/
if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
@@ -4056,8 +4822,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
} else {
ret_val = e1000_get_auto_rd_done_generic(hw);
if (ret_val) {
- /*
- * When auto config read does not complete, do not
+ /* When auto config read does not complete, do not
* return with an error. This can happen in situations
* where there is no eeprom and prevents getting link.
*/
@@ -4075,7 +4840,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
/* If EEPROM is not marked present, init the IGP 3 PHY manually */
if (hw->mac.type <= e1000_ich9lan) {
- if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) &&
+ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) &&
(hw->phy.type == e1000_phy_igp_3)) {
e1000_phy_init_script_igp3(hw);
}
@@ -4117,6 +4882,7 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
{
u16 phy_data;
+ s32 ret_val;
DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan");
@@ -4139,21 +4905,31 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
/* Clear PHY statistics registers */
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
+ (hw->phy.type == e1000_phy_i217) ||
(hw->phy.type == e1000_phy_82577)) {
- hw->phy.ops.read_reg(hw, HV_SCC_UPPER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_ECOL_UPPER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_ECOL_LOWER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_MCC_UPPER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_MCC_LOWER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_LATECOL_UPPER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_LATECOL_LOWER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_COLC_UPPER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_COLC_LOWER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_DC_UPPER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_DC_LOWER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_TNCRS_UPPER, &phy_data);
- hw->phy.ops.read_reg(hw, HV_TNCRS_LOWER, &phy_data);
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return;
+ ret_val = hw->phy.ops.set_page(hw,
+ HV_STATS_PAGE << IGP_PAGE_SHIFT);
+ if (ret_val)
+ goto release;
+ hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
+ hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
+release:
+ hw->phy.ops.release(hw);
}
}
diff --git a/freebsd/sys/dev/e1000/e1000_ich8lan.h b/freebsd/sys/dev/e1000/e1000_ich8lan.h
index 2935af56..bf928981 100644
--- a/freebsd/sys/dev/e1000/e1000_ich8lan.h
+++ b/freebsd/sys/dev/e1000/e1000_ich8lan.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,212 +35,243 @@
#ifndef _E1000_ICH8LAN_H_
#define _E1000_ICH8LAN_H_
-#define ICH_FLASH_GFPREG 0x0000
-#define ICH_FLASH_HSFSTS 0x0004
-#define ICH_FLASH_HSFCTL 0x0006
-#define ICH_FLASH_FADDR 0x0008
-#define ICH_FLASH_FDATA0 0x0010
+#define ICH_FLASH_GFPREG 0x0000
+#define ICH_FLASH_HSFSTS 0x0004
+#define ICH_FLASH_HSFCTL 0x0006
+#define ICH_FLASH_FADDR 0x0008
+#define ICH_FLASH_FDATA0 0x0010
/* Requires up to 10 seconds when MNG might be accessing part. */
-#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000
-#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000
-#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000
-#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
-#define ICH_FLASH_CYCLE_REPEAT_COUNT 10
+#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000
+#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000
+#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000
+#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
+#define ICH_FLASH_CYCLE_REPEAT_COUNT 10
-#define ICH_CYCLE_READ 0
-#define ICH_CYCLE_WRITE 2
-#define ICH_CYCLE_ERASE 3
+#define ICH_CYCLE_READ 0
+#define ICH_CYCLE_WRITE 2
+#define ICH_CYCLE_ERASE 3
-#define FLASH_GFPREG_BASE_MASK 0x1FFF
-#define FLASH_SECTOR_ADDR_SHIFT 12
+#define FLASH_GFPREG_BASE_MASK 0x1FFF
+#define FLASH_SECTOR_ADDR_SHIFT 12
-#define ICH_FLASH_SEG_SIZE_256 256
-#define ICH_FLASH_SEG_SIZE_4K 4096
-#define ICH_FLASH_SEG_SIZE_8K 8192
-#define ICH_FLASH_SEG_SIZE_64K 65536
-#define ICH_FLASH_SECTOR_SIZE 4096
+#define ICH_FLASH_SEG_SIZE_256 256
+#define ICH_FLASH_SEG_SIZE_4K 4096
+#define ICH_FLASH_SEG_SIZE_8K 8192
+#define ICH_FLASH_SEG_SIZE_64K 65536
-#define ICH_FLASH_REG_MAPSIZE 0x00A0
-
-#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */
-#define E1000_ICH_FWSM_DISSW 0x10000000 /* FW Disables SW Writes */
+#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */
/* FW established a valid mode */
-#define E1000_ICH_FWSM_FW_VALID 0x00008000
+#define E1000_ICH_FWSM_FW_VALID 0x00008000
+#define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */
+#define E1000_ICH_FWSM_PCIM2PCI_COUNT 2000
-#define E1000_ICH_MNG_IAMT_MODE 0x2
+#define E1000_ICH_MNG_IAMT_MODE 0x2
-#define E1000_FWSM_PROXY_MODE 0x00000008 /* FW is in proxy mode */
+#define E1000_FWSM_WLOCK_MAC_MASK 0x0380
+#define E1000_FWSM_WLOCK_MAC_SHIFT 7
/* Shared Receive Address Registers */
-#define E1000_SHRAL(_i) (0x05438 + ((_i) * 8))
-#define E1000_SHRAH(_i) (0x0543C + ((_i) * 8))
-#define E1000_SHRAH_AV 0x80000000 /* Addr Valid bit */
-#define E1000_SHRAH_MAV 0x40000000 /* Multicast Addr Valid bit */
-
-#define E1000_H2ME 0x05B50 /* Host to ME */
-#define E1000_H2ME_LSECREQ 0x00000001 /* Linksec Request */
-#define E1000_H2ME_LSECA 0x00000002 /* Linksec Active */
-#define E1000_H2ME_LSECSF 0x00000004 /* Linksec Failed */
-#define E1000_H2ME_LSECD 0x00000008 /* Linksec Disabled */
-#define E1000_H2ME_SLCAPD 0x00000010 /* Start LCAPD */
-#define E1000_H2ME_IPV4_ARP_EN 0x00000020 /* Arp Offload enable bit */
-#define E1000_H2ME_IPV6_NS_EN 0x00000040 /* NS Offload enable bit */
-
-#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \
- (ID_LED_OFF1_OFF2 << 8) | \
- (ID_LED_OFF1_ON2 << 4) | \
- (ID_LED_DEF1_DEF2))
-
-#define E1000_ICH_NVM_SIG_WORD 0x13
-#define E1000_ICH_NVM_SIG_MASK 0xC000
-#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0
-#define E1000_ICH_NVM_SIG_VALUE 0x80
-
-#define E1000_ICH8_LAN_INIT_TIMEOUT 1500
-
-#define E1000_FEXTNVM_SW_CONFIG 1
-#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M */
-
-#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7
-#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7
-#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3
-
-#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
-
-#define E1000_ICH_RAR_ENTRIES 7
-#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */
-
-#define PHY_PAGE_SHIFT 5
-#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
- ((reg) & MAX_PHY_REG_ADDRESS))
-#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */
-#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */
-#define IGP3_CAPABILITY PHY_REG(776, 19) /* Capability */
-#define IGP3_PM_CTRL PHY_REG(769, 20) /* Power Management Control */
-
-#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002
-#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300
-#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200
-#define IGP3_PM_CTRL_FORCE_PWR_DOWN 0x0020
+#define E1000_SHRAL_PCH_LPT(_i) (0x05408 + ((_i) * 8))
+#define E1000_SHRAH_PCH_LPT(_i) (0x0540C + ((_i) * 8))
+
+#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \
+ (ID_LED_OFF1_OFF2 << 8) | \
+ (ID_LED_OFF1_ON2 << 4) | \
+ (ID_LED_DEF1_DEF2))
+
+#define E1000_ICH_NVM_SIG_WORD 0x13
+#define E1000_ICH_NVM_SIG_MASK 0xC000
+#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0
+#define E1000_ICH_NVM_SIG_VALUE 0x80
+
+#define E1000_ICH8_LAN_INIT_TIMEOUT 1500
+
+#define E1000_FEXTNVM_SW_CONFIG 1
+#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M */
+
+#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000
+#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000
+
+#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7
+#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7
+#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3
+
+#define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100
+
+#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
+
+#define E1000_ICH_RAR_ENTRIES 7
+#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */
+#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */
+
+#define PHY_PAGE_SHIFT 5
+#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
+ ((reg) & MAX_PHY_REG_ADDRESS))
+#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */
+#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */
+
+#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002
+#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300
+#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200
/* PHY Wakeup Registers and defines */
-#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0)
-#define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
-#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
-#define BM_WUS PHY_REG(BM_WUC_PAGE, 3)
-#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2)))
-#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2)))
-#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2)))
-#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2)))
-#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1)))
-#define BM_IPAV (BM_PHY_REG(BM_WUC_PAGE, 64))
-#define BM_IP4AT_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 82 + ((_i) * 2)))
-#define BM_IP4AT_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 83 + ((_i) * 2)))
-
-#define BM_SHRAL_LOWER(_i) (BM_PHY_REG(BM_WUC_PAGE, 44 + ((_i) * 4)))
-#define BM_SHRAL_UPPER(_i) (BM_PHY_REG(BM_WUC_PAGE, 45 + ((_i) * 4)))
-#define BM_SHRAH_LOWER(_i) (BM_PHY_REG(BM_WUC_PAGE, 46 + ((_i) * 4)))
-#define BM_SHRAH_UPPER(_i) (BM_PHY_REG(BM_WUC_PAGE, 47 + ((_i) * 4)))
-
-#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */
-#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */
-#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */
-#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */
-#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */
-#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */
-#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */
+#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17)
+#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0)
+#define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
+#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
+#define BM_WUS PHY_REG(BM_WUC_PAGE, 3)
+#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2)))
+#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2)))
+#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2)))
+#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2)))
+#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1)))
+
+#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */
+#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */
+#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */
+#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */
+#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */
+#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */
+#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */
#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */
-#define HV_MUX_DATA_CTRL PHY_REG(776, 16)
-#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400
-#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004
-#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */
-#define HV_SCC_LOWER PHY_REG(778, 17)
-#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */
-#define HV_ECOL_LOWER PHY_REG(778, 19)
-#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */
-#define HV_MCC_LOWER PHY_REG(778, 21)
-#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */
-#define HV_LATECOL_LOWER PHY_REG(778, 24)
-#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */
-#define HV_COLC_LOWER PHY_REG(778, 26)
-#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */
-#define HV_DC_LOWER PHY_REG(778, 28)
-#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */
-#define HV_TNCRS_LOWER PHY_REG(778, 30)
-
-#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */
-
-#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
-#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */
+#define HV_MUX_DATA_CTRL PHY_REG(776, 16)
+#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400
+#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004
+#define HV_STATS_PAGE 778
+#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */
+#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17)
+#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */
+#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19)
+#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */
+#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21)
+#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */
+#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24)
+#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */
+#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26)
+#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */
+#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28)
+#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */
+#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30)
+
+#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */
+
+#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
+#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */
+
+/* SMBus Control Phy Register */
+#define CV_SMB_CTRL PHY_REG(769, 23)
+#define CV_SMB_CTRL_FORCE_SMBUS 0x0001
/* SMBus Address Phy Register */
-#define HV_SMB_ADDR PHY_REG(768, 26)
-#define HV_SMB_ADDR_MASK 0x007F
-#define HV_SMB_ADDR_PEC_EN 0x0200
-#define HV_SMB_ADDR_VALID 0x0080
+#define HV_SMB_ADDR PHY_REG(768, 26)
+#define HV_SMB_ADDR_MASK 0x007F
+#define HV_SMB_ADDR_PEC_EN 0x0200
+#define HV_SMB_ADDR_VALID 0x0080
+#define HV_SMB_ADDR_FREQ_MASK 0x1100
+#define HV_SMB_ADDR_FREQ_LOW_SHIFT 8
+#define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12
/* Strapping Option Register - RO */
-#define E1000_STRAP 0x0000C
-#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
-#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+#define E1000_STRAP 0x0000C
+#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
+#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+#define E1000_STRAP_SMT_FREQ_MASK 0x00003000
+#define E1000_STRAP_SMT_FREQ_SHIFT 12
/* OEM Bits Phy Register */
-#define HV_OEM_BITS PHY_REG(768, 25)
-#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */
-#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */
-#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */
-
-#define LCD_CFG_PHY_ADDR_BIT 0x0020 /* Phy address bit from LCD Config word */
+#define HV_OEM_BITS PHY_REG(768, 25)
+#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */
+#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */
+#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */
/* KMRN Mode Control */
#define HV_KMRN_MODE_CTRL PHY_REG(769, 16)
#define HV_KMRN_MDIO_SLOW 0x0400
+/* KMRN FIFO Control and Status */
+#define HV_KMRN_FIFO_CTRLSTA PHY_REG(770, 16)
+#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK 0x7000
+#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT 12
+
/* PHY Power Management Control */
#define HV_PM_CTRL PHY_REG(770, 17)
+#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100
-#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */
+#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */
/* PHY Low Power Idle Control */
-#define I82579_LPI_CTRL PHY_REG(772, 20)
-#define I82579_LPI_CTRL_ENABLE_MASK 0x6000
-
-/*
- * Additional interrupts need to be handled for ICH family:
- * DSW = The FW changed the status of the DISSW bit in FWSM
- * PHYINT = The LAN connected device generates an interrupt
- * EPRST = Manageability reset event
- */
-#define IMS_ICH_ENABLE_MASK (\
- E1000_IMS_DSW | \
- E1000_IMS_PHYINT | \
- E1000_IMS_EPRST)
-
-/* Additional interrupt register bit definitions */
-#define E1000_ICR_LSECPNC 0x00004000 /* PN threshold - client */
-#define E1000_IMS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */
-#define E1000_ICS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */
-
-/* Security Processing bit Indication */
-#define E1000_RXDEXT_LINKSEC_STATUS_LSECH 0x01000000
-#define E1000_RXDEXT_LINKSEC_ERROR_BIT_MASK 0x60000000
-#define E1000_RXDEXT_LINKSEC_ERROR_NO_SA_MATCH 0x20000000
-#define E1000_RXDEXT_LINKSEC_ERROR_REPLAY_ERROR 0x40000000
-#define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG 0x60000000
+#define I82579_LPI_CTRL PHY_REG(772, 20)
+#define I82579_LPI_CTRL_100_ENABLE 0x2000
+#define I82579_LPI_CTRL_1000_ENABLE 0x4000
+#define I82579_LPI_CTRL_ENABLE_MASK 0x6000
+#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80
+
+/* Extended Management Interface (EMI) Registers */
+#define I82579_EMI_ADDR 0x10
+#define I82579_EMI_DATA 0x11
+#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
+#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */
+#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */
+#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
+#define I82579_RX_CONFIG 0x3412 /* Receive configuration */
+#define I82579_EEE_PCS_STATUS 0x182D /* IEEE MMD Register 3.1 >> 8 */
+#define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */
+#define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */
+#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */
+#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
+#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE supported */
+#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */
+#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */
+#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
+#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
+
+#define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */
+#define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */
+
+/* Intel Rapid Start Technology Support */
+#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70)
+#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080
+#define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28)
+#define I217_SxCTRL_ENABLE_LPI_RESET 0x1000
+#define I217_CGFREG PHY_REG(772, 29)
+#define I217_CGFREG_ENABLE_MTA_RESET 0x0002
+#define I217_MEMPWR PHY_REG(772, 26)
+#define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010
/* Receive Address Initial CRC Calculation */
#define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4))
+/* Latency Tolerance Reporting */
+#define E1000_LTRV 0x000F8
+#define E1000_LTRV_VALUE_MASK 0x000003FF
+#define E1000_LTRV_SCALE_MAX 5
+#define E1000_LTRV_SCALE_FACTOR 5
+#define E1000_LTRV_SCALE_SHIFT 10
+#define E1000_LTRV_SCALE_MASK 0x00001C00
+#define E1000_LTRV_REQ_SHIFT 15
+#define E1000_LTRV_NOSNOOP_SHIFT 16
+#define E1000_LTRV_SEND (1 << 30)
+
+/* Proprietary Latency Tolerance Reporting PCI Capability */
+#define E1000_PCI_LTR_CAP_LPT 0xA8
+
+/* OBFF Control & Threshold Defines */
+#define E1000_SVCR_OFF_EN 0x00000001
+#define E1000_SVCR_OFF_MASKINT 0x00001000
+#define E1000_SVCR_OFF_TIMER_MASK 0xFFFF0000
+#define E1000_SVCR_OFF_TIMER_SHIFT 16
+#define E1000_SVT_OFF_HWM_MASK 0x0000001F
+
void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
- bool state);
+ bool state);
void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
-void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw);
+void e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
-s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_config);
-s32 e1000_hv_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
-#endif
+s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data);
+#endif /* _E1000_ICH8LAN_H_ */
diff --git a/freebsd/sys/dev/e1000/e1000_mac.c b/freebsd/sys/dev/e1000/e1000_mac.c
index 0a78d95d..2d59acce 100644
--- a/freebsd/sys/dev/e1000/e1000_mac.c
+++ b/freebsd/sys/dev/e1000/e1000_mac.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,8 @@
static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
+static void e1000_config_collision_dist_generic(struct e1000_hw *hw);
+static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
/**
* e1000_init_mac_ops_generic - Initialize MAC function pointers
@@ -74,12 +76,9 @@ void e1000_init_mac_ops_generic(struct e1000_hw *hw)
mac->ops.setup_link = e1000_null_ops_generic;
mac->ops.get_link_up_info = e1000_null_link_info;
mac->ops.check_for_link = e1000_null_ops_generic;
- mac->ops.wait_autoneg = e1000_wait_autoneg_generic;
+ mac->ops.set_obff_timer = e1000_null_set_obff_timer;
/* Management */
mac->ops.check_mng_mode = e1000_null_mng_mode;
- mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic;
- mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic;
- mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic;
/* VLAN, MC, etc. */
mac->ops.update_mc_addr_list = e1000_null_update_mc;
mac->ops.clear_vfta = e1000_null_mac_generic;
@@ -122,8 +121,7 @@ s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d)
* e1000_null_mng_mode - No-op function, return FALSE
* @hw: pointer to the HW structure
**/
-bool e1000_null_mng_mode(struct e1000_hw *hw)
-{
+bool e1000_null_mng_mode(struct e1000_hw *hw) {
DEBUGFUNC("e1000_null_mng_mode");
return FALSE;
}
@@ -159,6 +157,16 @@ void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a)
}
/**
+ * e1000_null_set_obff_timer - No-op function, return 0
+ * @hw: pointer to the HW structure
+ **/
+s32 e1000_null_set_obff_timer(struct e1000_hw *hw, u32 a)
+{
+ DEBUGFUNC("e1000_null_set_obff_timer");
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_get_bus_info_pci_generic - Get PCI(x) bus information
* @hw: pointer to the HW structure
*
@@ -183,8 +191,8 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw)
/* Bus speed */
if (bus->type == e1000_bus_type_pci) {
bus->speed = (status & E1000_STATUS_PCI66)
- ? e1000_bus_speed_66
- : e1000_bus_speed_33;
+ ? e1000_bus_speed_66
+ : e1000_bus_speed_33;
} else {
switch (status & E1000_STATUS_PCIX_SPEED) {
case E1000_STATUS_PCIX_SPEED_66:
@@ -204,8 +212,8 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw)
/* Bus width */
bus->width = (status & E1000_STATUS_BUS64)
- ? e1000_bus_width_64
- : e1000_bus_width_32;
+ ? e1000_bus_width_64
+ : e1000_bus_width_32;
/* Which PCI(-X) function? */
mac->ops.set_lan_id(hw);
@@ -232,9 +240,8 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
bus->type = e1000_bus_type_pci_express;
- ret_val = e1000_read_pcie_cap_reg(hw,
- PCIE_LINK_STATUS,
- &pcie_link_status);
+ ret_val = e1000_read_pcie_cap_reg(hw, PCIE_LINK_STATUS,
+ &pcie_link_status);
if (ret_val) {
bus->width = e1000_bus_width_unknown;
bus->speed = e1000_bus_speed_unknown;
@@ -250,10 +257,9 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
bus->speed = e1000_bus_speed_unknown;
break;
}
-
+
bus->width = (enum e1000_bus_width)((pcie_link_status &
- PCIE_LINK_WIDTH_MASK) >>
- PCIE_LINK_WIDTH_SHIFT);
+ PCIE_LINK_WIDTH_MASK) >> PCIE_LINK_WIDTH_SHIFT);
}
mac->ops.set_lan_id(hw);
@@ -274,8 +280,7 @@ static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
struct e1000_bus_info *bus = &hw->bus;
u32 reg;
- /*
- * The status register reports the correct function number
+ /* The status register reports the correct function number
* for the device regardless of function swap state.
*/
reg = E1000_READ_REG(hw, E1000_STATUS);
@@ -298,7 +303,7 @@ void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw)
if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) {
status = E1000_READ_REG(hw, E1000_STATUS);
bus->func = (status & E1000_STATUS_FUNC_MASK)
- >> E1000_STATUS_FUNC_SHIFT;
+ >> E1000_STATUS_FUNC_SHIFT;
} else {
bus->func = 0;
}
@@ -358,7 +363,7 @@ void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
* @hw: pointer to the HW structure
* @rar_count: receive address registers
*
- * Setups the receive address registers by setting the base receive address
+ * Setup the receive address registers by setting the base receive address
* register to the devices MAC address and clearing all the other receive
* address registers to 0.
**/
@@ -395,7 +400,7 @@ void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count)
s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
{
u32 i;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 offset, nvm_alt_mac_addr_offset, nvm_data;
u8 alt_mac_addr[ETH_ADDR_LEN];
@@ -403,25 +408,29 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &nvm_data);
if (ret_val)
- goto out;
+ return ret_val;
- /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */
- if (!((nvm_data & NVM_COMPAT_LOM) ||
- (hw->device_id == E1000_DEV_ID_82571EB_SERDES_DUAL) ||
- (hw->device_id == E1000_DEV_ID_82571EB_SERDES_QUAD)))
- goto out;
+ /* not supported on older hardware or 82573 */
+ if ((hw->mac.type < e1000_82571) || (hw->mac.type == e1000_82573))
+ return E1000_SUCCESS;
+
+ /* Alternate MAC address is handled by the option ROM for 82580
+ * and newer. SW support not required.
+ */
+ if (hw->mac.type >= e1000_82580)
+ return E1000_SUCCESS;
ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1,
- &nvm_alt_mac_addr_offset);
+ &nvm_alt_mac_addr_offset);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
- if (nvm_alt_mac_addr_offset == 0xFFFF) {
+ if ((nvm_alt_mac_addr_offset == 0xFFFF) ||
+ (nvm_alt_mac_addr_offset == 0x0000))
/* There is no Alternate MAC Address */
- goto out;
- }
+ return E1000_SUCCESS;
if (hw->bus.func == E1000_FUNC_1)
nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
@@ -435,7 +444,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
@@ -445,18 +454,16 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
/* if multicast bit is set, the alternate address will not be used */
if (alt_mac_addr[0] & 0x01) {
DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n");
- goto out;
+ return E1000_SUCCESS;
}
- /*
- * We have a valid alternate MAC address, and we want to treat it the
+ /* We have a valid alternate MAC address, and we want to treat it the
* same as the normal permanent MAC address stored by the HW into the
* RAR. Do this by mapping this address into RAR0.
*/
hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -468,19 +475,17 @@ out:
* Sets the receive address array register at index to the address passed
* in by addr.
**/
-void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
+static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
{
u32 rar_low, rar_high;
DEBUGFUNC("e1000_rar_set_generic");
- /*
- * HW expects these in little endian so we reverse the byte order
+ /* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
- rar_low = ((u32) addr[0] |
- ((u32) addr[1] << 8) |
- ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
+ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
@@ -488,8 +493,7 @@ void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
if (rar_low || rar_high)
rar_high |= E1000_RAH_AV;
- /*
- * Some bridges will combine consecutive 32-bit writes into
+ /* Some bridges will combine consecutive 32-bit writes into
* a single burst write, which will malfunction on some parts.
* The flushes avoid this.
*/
@@ -500,43 +504,6 @@ void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
}
/**
- * e1000_update_mc_addr_list_generic - Update Multicast addresses
- * @hw: pointer to the HW structure
- * @mc_addr_list: array of multicast addresses to program
- * @mc_addr_count: number of multicast addresses to program
- *
- * Updates entire Multicast Table Array.
- * The caller must have a packed mc_addr_list of multicast addresses.
- **/
-void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count)
-{
- u32 hash_value, hash_bit, hash_reg;
- int i;
-
- DEBUGFUNC("e1000_update_mc_addr_list_generic");
-
- /* clear mta_shadow */
- memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
-
- /* update mta_shadow from mc_addr_list */
- for (i = 0; (u32) i < mc_addr_count; i++) {
- hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
-
- hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
- hash_bit = hash_value & 0x1F;
-
- hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
- mc_addr_list += (ETH_ADDR_LEN);
- }
-
- /* replace the entire MTA table */
- for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
- E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
- E1000_WRITE_FLUSH(hw);
-}
-
-/**
* e1000_hash_mc_addr_generic - Generate a multicast hash value
* @hw: pointer to the HW structure
* @mc_addr: pointer to a multicast address
@@ -554,15 +521,13 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
/* Register count multiplied by bits per register */
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
- /*
- * For a mc_filter_type of 0, bit_shift is the number of left-shifts
+ /* For a mc_filter_type of 0, bit_shift is the number of left-shifts
* where 0xFF would still fall within the hash mask.
*/
while (hash_mask >> bit_shift != 0xFF)
bit_shift++;
- /*
- * The portion of the address that is used for the hash table
+ /* The portion of the address that is used for the hash table
* is determined by the mc_filter_type setting.
* The algorithm is such that there is a total of 8 bits of shifting.
* The bit_shift for a mc_filter_type of 0 represents the number of
@@ -580,7 +545,7 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
* values resulting from each mc_filter_type...
* [0] [1] [2] [3] [4] [5]
* 01 AA 00 12 34 56
- * LSB MSB
+ * LSB MSB
*
* case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563
* case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6
@@ -603,12 +568,49 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
}
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
- (((u16) mc_addr[5]) << bit_shift)));
+ (((u16) mc_addr[5]) << bit_shift)));
return hash_value;
}
/**
+ * e1000_update_mc_addr_list_generic - Update Multicast addresses
+ * @hw: pointer to the HW structure
+ * @mc_addr_list: array of multicast addresses to program
+ * @mc_addr_count: number of multicast addresses to program
+ *
+ * Updates entire Multicast Table Array.
+ * The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
+ u8 *mc_addr_list, u32 mc_addr_count)
+{
+ u32 hash_value, hash_bit, hash_reg;
+ int i;
+
+ DEBUGFUNC("e1000_update_mc_addr_list_generic");
+
+ /* clear mta_shadow */
+ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+
+ /* update mta_shadow from mc_addr_list */
+ for (i = 0; (u32) i < mc_addr_count; i++) {
+ hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
+
+ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+ hash_bit = hash_value & 0x1F;
+
+ hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
+ mc_addr_list += (ETH_ADDR_LEN);
+ }
+
+ /* replace the entire MTA table */
+ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
+ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
+ E1000_WRITE_FLUSH(hw);
+}
+
+/**
* e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value
* @hw: pointer to the HW structure
*
@@ -633,9 +635,9 @@ void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw)
e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);
e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);
cmd_mmrbc = (pcix_cmd & PCIX_COMMAND_MMRBC_MASK) >>
- PCIX_COMMAND_MMRBC_SHIFT;
+ PCIX_COMMAND_MMRBC_SHIFT;
stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
- PCIX_STATUS_HI_MMRBC_SHIFT;
+ PCIX_STATUS_HI_MMRBC_SHIFT;
if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
if (cmd_mmrbc > stat_mmrbc) {
@@ -710,55 +712,45 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_for_copper_link");
- /*
- * We only want to go out to the PHY registers to see if Auto-Neg
+ /* We only want to go out to the PHY registers to see if Auto-Neg
* has completed and/or if our link status has changed. The
* get_link_status flag is set upon receiving a Link Status
* Change or Rx Sequence Error interrupt.
*/
- if (!mac->get_link_status) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
+ if (!mac->get_link_status)
+ return E1000_SUCCESS;
- /*
- * First we want to see if the MII Status Register reports
+ /* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
* of the PHY.
*/
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
- goto out; /* No link detected */
+ return E1000_SUCCESS; /* No link detected */
mac->get_link_status = FALSE;
- /*
- * Check if there was DownShift, must be checked
+ /* Check if there was DownShift, must be checked
* immediately after link-up
*/
e1000_check_downshift_generic(hw);
- /*
- * If we are forcing speed/duplex, then we simply return since
+ /* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
*/
- if (!mac->autoneg) {
- ret_val = -E1000_ERR_CONFIG;
- goto out;
- }
+ if (!mac->autoneg)
+ return -E1000_ERR_CONFIG;
- /*
- * Auto-Neg is enabled. Auto Speed Detection takes care
+ /* Auto-Neg is enabled. Auto Speed Detection takes care
* of MAC speed/duplex configuration. So we only need to
* configure Collision Distance in the MAC.
*/
mac->ops.config_collision_dist(hw);
- /*
- * Configure Flow Control now that Auto-Neg has completed.
+ /* Configure Flow Control now that Auto-Neg has completed.
* First, we need to restore the desired flow control
* settings because we may have had to re-autoneg with a
* different link partner.
@@ -767,7 +759,6 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
if (ret_val)
DEBUGOUT("Error configuring flow control\n");
-out:
return ret_val;
}
@@ -784,7 +775,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
u32 rxcw;
u32 ctrl;
u32 status;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_check_for_fiber_link_generic");
@@ -792,8 +783,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
status = E1000_READ_REG(hw, E1000_STATUS);
rxcw = E1000_READ_REG(hw, E1000_RXCW);
- /*
- * If we don't have link (auto-negotiation failed or link partner
+ /* If we don't have link (auto-negotiation failed or link partner
* cannot auto-negotiate), the cable is plugged in (we have signal),
* and our link partner is not trying to auto-negotiate with us (we
* are receiving idles or data), we need to force link up. We also
@@ -801,13 +791,13 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
* was just plugged in. The autoneg_failed flag does this.
*/
/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
- if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&
- (!(rxcw & E1000_RXCW_C))) {
- if (mac->autoneg_failed == 0) {
- mac->autoneg_failed = 1;
- goto out;
+ if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) &&
+ !(rxcw & E1000_RXCW_C)) {
+ if (!mac->autoneg_failed) {
+ mac->autoneg_failed = TRUE;
+ return E1000_SUCCESS;
}
- DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+ DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
/* Disable auto-negotiation in the TXCW register */
E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -821,24 +811,22 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
ret_val = e1000_config_fc_after_link_up_generic(hw);
if (ret_val) {
DEBUGOUT("Error configuring flow control\n");
- goto out;
+ return ret_val;
}
} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
- /*
- * If we are forcing link and we are receiving /C/ ordered
+ /* If we are forcing link and we are receiving /C/ ordered
* sets, re-enable auto-negotiation in the TXCW register
* and disable forced link in the Device Control register
* in an attempt to auto-negotiate with our link partner.
*/
- DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+ DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
mac->serdes_has_link = TRUE;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -854,7 +842,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
u32 rxcw;
u32 ctrl;
u32 status;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_check_for_serdes_link_generic");
@@ -862,20 +850,19 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
status = E1000_READ_REG(hw, E1000_STATUS);
rxcw = E1000_READ_REG(hw, E1000_RXCW);
- /*
- * If we don't have link (auto-negotiation failed or link partner
+ /* If we don't have link (auto-negotiation failed or link partner
* cannot auto-negotiate), and our link partner is not trying to
* auto-negotiate with us (we are receiving idles or data),
* we need to force link up. We also need to give auto-negotiation
* time to complete.
*/
/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
- if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
- if (mac->autoneg_failed == 0) {
- mac->autoneg_failed = 1;
- goto out;
+ if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) {
+ if (!mac->autoneg_failed) {
+ mac->autoneg_failed = TRUE;
+ return E1000_SUCCESS;
}
- DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+ DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
/* Disable auto-negotiation in the TXCW register */
E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -889,23 +876,21 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
ret_val = e1000_config_fc_after_link_up_generic(hw);
if (ret_val) {
DEBUGOUT("Error configuring flow control\n");
- goto out;
+ return ret_val;
}
} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
- /*
- * If we are forcing link and we are receiving /C/ ordered
+ /* If we are forcing link and we are receiving /C/ ordered
* sets, re-enable auto-negotiation in the TXCW register
* and disable forced link in the Device Control register
* in an attempt to auto-negotiate with our link partner.
*/
- DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+ DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
mac->serdes_has_link = TRUE;
} else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) {
- /*
- * If we force link for non-auto-negotiation switch, check
+ /* If we force link for non-auto-negotiation switch, check
* link status based on MAC synchronization for internal
* serdes media type.
*/
@@ -932,12 +917,10 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
if (rxcw & E1000_RXCW_SYNCH) {
if (!(rxcw & E1000_RXCW_IV)) {
mac->serdes_has_link = TRUE;
- DEBUGOUT("SERDES: Link up - autoneg "
- "completed sucessfully.\n");
+ DEBUGOUT("SERDES: Link up - autoneg completed successfully.\n");
} else {
mac->serdes_has_link = FALSE;
- DEBUGOUT("SERDES: Link down - invalid"
- "codewords detected in autoneg.\n");
+ DEBUGOUT("SERDES: Link down - invalid codewords detected in autoneg.\n");
}
} else {
mac->serdes_has_link = FALSE;
@@ -949,8 +932,47 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
}
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_set_default_fc_generic - Set flow control default values
+ * @hw: pointer to the HW structure
+ *
+ * Read the EEPROM for the default values for flow control and store the
+ * values.
+ **/
+s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 nvm_data;
+
+ DEBUGFUNC("e1000_set_default_fc_generic");
+
+ /* Read and store word 0x0F of the EEPROM. This word contains bits
+ * that determine the hardware's default PAUSE (flow control) mode,
+ * a bit that determines whether the HW defaults to enabling or
+ * disabling auto-negotiation, and the direction of the
+ * SW defined pins. If there is no SW over-ride of the flow
+ * control setting, then the variable hw->fc will
+ * be initialized based on a value in the EEPROM.
+ */
+ ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
+
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ return ret_val;
+ }
+
+ if (!(nvm_data & NVM_WORD0F_PAUSE_MASK))
+ hw->fc.requested_mode = e1000_fc_none;
+ else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
+ NVM_WORD0F_ASM_DIR)
+ hw->fc.requested_mode = e1000_fc_tx_pause;
+ else
+ hw->fc.requested_mode = e1000_fc_full;
+
+ return E1000_SUCCESS;
}
/**
@@ -965,29 +987,26 @@ out:
**/
s32 e1000_setup_link_generic(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_setup_link_generic");
- /*
- * In the case of the phy reset being blocked, we already have a link.
+ /* In the case of the phy reset being blocked, we already have a link.
* We do not need to set it up again.
*/
- if (e1000_check_reset_block(hw))
- goto out;
+ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw))
+ return E1000_SUCCESS;
- /*
- * If requested flow control is set to default, set flow control
+ /* If requested flow control is set to default, set flow control
* based on the EEPROM flow control settings.
*/
if (hw->fc.requested_mode == e1000_fc_default) {
ret_val = e1000_set_default_fc_generic(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- /*
- * Save off the requested flow control mode for use later. Depending
+ /* Save off the requested flow control mode for use later. Depending
* on the link partner's capabilities, we may or may not use this mode.
*/
hw->fc.current_mode = hw->fc.requested_mode;
@@ -998,10 +1017,9 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
/* Call the necessary media_type subroutine to configure the link. */
ret_val = hw->mac.ops.setup_physical_interface(hw);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * Initialize the flow control address, type, and PAUSE timer
+ /* Initialize the flow control address, type, and PAUSE timer
* registers to their default values. This is done even if flow
* control is disabled, because it does not hurt anything to
* initialize these registers.
@@ -1013,87 +1031,76 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
- ret_val = e1000_set_fc_watermarks_generic(hw);
-
-out:
- return ret_val;
+ return e1000_set_fc_watermarks_generic(hw);
}
/**
- * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes
+ * e1000_commit_fc_settings_generic - Configure flow control
* @hw: pointer to the HW structure
*
- * Configures collision distance and flow control for fiber and serdes
- * links. Upon successful setup, poll for link.
+ * Write the flow control settings to the Transmit Config Word Register (TXCW)
+ * base on the flow control settings in e1000_mac_info.
**/
-s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
+s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
- u32 ctrl;
- s32 ret_val = E1000_SUCCESS;
-
- DEBUGFUNC("e1000_setup_fiber_serdes_link_generic");
-
- ctrl = E1000_READ_REG(hw, E1000_CTRL);
-
- /* Take the link out of reset */
- ctrl &= ~E1000_CTRL_LRST;
-
- mac->ops.config_collision_dist(hw);
-
- ret_val = e1000_commit_fc_settings_generic(hw);
- if (ret_val)
- goto out;
-
- /*
- * Since auto-negotiation is enabled, take the link out of reset (the
- * link will be in reset, because we previously reset the chip). This
- * will restart auto-negotiation. If auto-negotiation is successful
- * then the link-up status bit will be set and the flow control enable
- * bits (RFCE and TFCE) will be set according to their negotiated value.
- */
- DEBUGOUT("Auto-negotiation enabled\n");
+ u32 txcw;
- E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
- msec_delay(1);
+ DEBUGFUNC("e1000_commit_fc_settings_generic");
- /*
- * For these adapters, the SW definable pin 1 is set when the optics
- * detect a signal. If we have a signal, then poll for a "Link-Up"
- * indication.
+ /* Check for a software override of the flow control settings, and
+ * setup the device accordingly. If auto-negotiation is enabled, then
+ * software will have to set the "PAUSE" bits to the correct value in
+ * the Transmit Config Word Register (TXCW) and re-start auto-
+ * negotiation. However, if auto-negotiation is disabled, then
+ * software will have to manually configure the two flow control enable
+ * bits in the CTRL register.
+ *
+ * The possible values of the "fc" parameter are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames,
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but we
+ * do not support receiving pause frames).
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
*/
- if (hw->phy.media_type == e1000_media_type_internal_serdes ||
- (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
- ret_val = e1000_poll_fiber_serdes_link_generic(hw);
- } else {
- DEBUGOUT("No signal detected\n");
+ switch (hw->fc.current_mode) {
+ case e1000_fc_none:
+ /* Flow control completely disabled by a software over-ride. */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
+ break;
+ case e1000_fc_rx_pause:
+ /* Rx Flow control is enabled and Tx Flow control is disabled
+ * by a software over-ride. Since there really isn't a way to
+ * advertise that we are capable of Rx Pause ONLY, we will
+ * advertise that we support both symmetric and asymmetric Rx
+ * PAUSE. Later, we will disable the adapter's ability to send
+ * PAUSE frames.
+ */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+ break;
+ case e1000_fc_tx_pause:
+ /* Tx Flow control is enabled, and Rx Flow control is disabled,
+ * by a software over-ride.
+ */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
+ break;
+ case e1000_fc_full:
+ /* Flow control (both Rx and Tx) is enabled by a software
+ * over-ride.
+ */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+ break;
+ default:
+ DEBUGOUT("Flow control param set incorrectly\n");
+ return -E1000_ERR_CONFIG;
+ break;
}
-out:
- return ret_val;
-}
-
-/**
- * e1000_config_collision_dist_generic - Configure collision distance
- * @hw: pointer to the HW structure
- *
- * Configures the collision distance to the default value and is used
- * during link setup.
- **/
-void e1000_config_collision_dist_generic(struct e1000_hw *hw)
-{
- u32 tctl;
-
- DEBUGFUNC("e1000_config_collision_dist_generic");
-
- tctl = E1000_READ_REG(hw, E1000_TCTL);
-
- tctl &= ~E1000_TCTL_COLD;
- tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+ E1000_WRITE_REG(hw, E1000_TXCW, txcw);
+ mac->txcw = txcw;
- E1000_WRITE_REG(hw, E1000_TCTL, tctl);
- E1000_WRITE_FLUSH(hw);
+ return E1000_SUCCESS;
}
/**
@@ -1107,12 +1114,11 @@ s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
u32 i, status;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_poll_fiber_serdes_link_generic");
- /*
- * If we have a signal (the cable is plugged in, or assumed TRUE for
+ /* If we have a signal (the cable is plugged in, or assumed TRUE for
* serdes media) then poll for a "Link-Up" indication in the Device
* Status Register. Time-out if a link isn't seen in 500 milliseconds
* seconds (Auto-negotiation should complete in less than 500
@@ -1126,9 +1132,8 @@ s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
}
if (i == FIBER_LINK_UP_LIMIT) {
DEBUGOUT("Never got a valid link from auto-neg!!!\n");
- mac->autoneg_failed = 1;
- /*
- * AutoNeg failed to achieve a link, so we'll call
+ mac->autoneg_failed = TRUE;
+ /* AutoNeg failed to achieve a link, so we'll call
* mac->check_for_link. This routine will force the
* link up if we detect a signal. This will allow us to
* communicate with non-autonegotiating link partners.
@@ -1136,95 +1141,91 @@ s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
ret_val = mac->ops.check_for_link(hw);
if (ret_val) {
DEBUGOUT("Error while checking for link\n");
- goto out;
+ return ret_val;
}
- mac->autoneg_failed = 0;
+ mac->autoneg_failed = FALSE;
} else {
- mac->autoneg_failed = 0;
+ mac->autoneg_failed = FALSE;
DEBUGOUT("Valid Link Found\n");
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
- * e1000_commit_fc_settings_generic - Configure flow control
+ * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes
* @hw: pointer to the HW structure
*
- * Write the flow control settings to the Transmit Config Word Register (TXCW)
- * base on the flow control settings in e1000_mac_info.
+ * Configures collision distance and flow control for fiber and serdes
+ * links. Upon successful setup, poll for link.
**/
-s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
{
- struct e1000_mac_info *mac = &hw->mac;
- u32 txcw;
- s32 ret_val = E1000_SUCCESS;
+ u32 ctrl;
+ s32 ret_val;
- DEBUGFUNC("e1000_commit_fc_settings_generic");
+ DEBUGFUNC("e1000_setup_fiber_serdes_link_generic");
- /*
- * Check for a software override of the flow control settings, and
- * setup the device accordingly. If auto-negotiation is enabled, then
- * software will have to set the "PAUSE" bits to the correct value in
- * the Transmit Config Word Register (TXCW) and re-start auto-
- * negotiation. However, if auto-negotiation is disabled, then
- * software will have to manually configure the two flow control enable
- * bits in the CTRL register.
- *
- * The possible values of the "fc" parameter are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause frames,
- * but not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames but we
- * do not support receiving pause frames).
- * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+ /* Take the link out of reset */
+ ctrl &= ~E1000_CTRL_LRST;
+
+ hw->mac.ops.config_collision_dist(hw);
+
+ ret_val = e1000_commit_fc_settings_generic(hw);
+ if (ret_val)
+ return ret_val;
+
+ /* Since auto-negotiation is enabled, take the link out of reset (the
+ * link will be in reset, because we previously reset the chip). This
+ * will restart auto-negotiation. If auto-negotiation is successful
+ * then the link-up status bit will be set and the flow control enable
+ * bits (RFCE and TFCE) will be set according to their negotiated value.
*/
- switch (hw->fc.current_mode) {
- case e1000_fc_none:
- /* Flow control completely disabled by a software over-ride. */
- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
- break;
- case e1000_fc_rx_pause:
- /*
- * Rx Flow control is enabled and Tx Flow control is disabled
- * by a software over-ride. Since there really isn't a way to
- * advertise that we are capable of Rx Pause ONLY, we will
- * advertise that we support both symmetric and asymmetric Rx
- * PAUSE. Later, we will disable the adapter's ability to send
- * PAUSE frames.
- */
- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
- break;
- case e1000_fc_tx_pause:
- /*
- * Tx Flow control is enabled, and Rx Flow control is disabled,
- * by a software over-ride.
- */
- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
- break;
- case e1000_fc_full:
- /*
- * Flow control (both Rx and Tx) is enabled by a software
- * over-ride.
- */
- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
- break;
- default:
- DEBUGOUT("Flow control param set incorrectly\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
- break;
- }
+ DEBUGOUT("Auto-negotiation enabled\n");
- E1000_WRITE_REG(hw, E1000_TXCW, txcw);
- mac->txcw = txcw;
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+ E1000_WRITE_FLUSH(hw);
+ msec_delay(1);
+
+ /* For these adapters, the SW definable pin 1 is set when the optics
+ * detect a signal. If we have a signal, then poll for a "Link-Up"
+ * indication.
+ */
+ if (hw->phy.media_type == e1000_media_type_internal_serdes ||
+ (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
+ ret_val = e1000_poll_fiber_serdes_link_generic(hw);
+ } else {
+ DEBUGOUT("No signal detected\n");
+ }
-out:
return ret_val;
}
/**
+ * e1000_config_collision_dist_generic - Configure collision distance
+ * @hw: pointer to the HW structure
+ *
+ * Configures the collision distance to the default value and is used
+ * during link setup.
+ **/
+static void e1000_config_collision_dist_generic(struct e1000_hw *hw)
+{
+ u32 tctl;
+
+ DEBUGFUNC("e1000_config_collision_dist_generic");
+
+ tctl = E1000_READ_REG(hw, E1000_TCTL);
+
+ tctl &= ~E1000_TCTL_COLD;
+ tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+
+ E1000_WRITE_REG(hw, E1000_TCTL, tctl);
+ E1000_WRITE_FLUSH(hw);
+}
+
+/**
* e1000_set_fc_watermarks_generic - Set flow control high/low watermarks
* @hw: pointer to the HW structure
*
@@ -1238,16 +1239,14 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw)
DEBUGFUNC("e1000_set_fc_watermarks_generic");
- /*
- * Set the flow control receive threshold registers. Normally,
+ /* Set the flow control receive threshold registers. Normally,
* these registers will be set to a default threshold that may be
* adjusted later by the driver's runtime code. However, if the
* ability to transmit pause frames is not enabled, then these
* registers will be set to 0.
*/
if (hw->fc.current_mode & e1000_fc_tx_pause) {
- /*
- * We need to set up the Receive Threshold high and low water
+ /* We need to set up the Receive Threshold high and low water
* marks as well as (optionally) enabling the transmission of
* XON frames.
*/
@@ -1264,48 +1263,6 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw)
}
/**
- * e1000_set_default_fc_generic - Set flow control default values
- * @hw: pointer to the HW structure
- *
- * Read the EEPROM for the default values for flow control and store the
- * values.
- **/
-s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
-{
- s32 ret_val = E1000_SUCCESS;
- u16 nvm_data;
-
- DEBUGFUNC("e1000_set_default_fc_generic");
-
- /*
- * Read and store word 0x0F of the EEPROM. This word contains bits
- * that determine the hardware's default PAUSE (flow control) mode,
- * a bit that determines whether the HW defaults to enabling or
- * disabling auto-negotiation, and the direction of the
- * SW defined pins. If there is no SW over-ride of the flow
- * control setting, then the variable hw->fc will
- * be initialized based on a value in the EEPROM.
- */
- ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
-
- if (ret_val) {
- DEBUGOUT("NVM Read Error\n");
- goto out;
- }
-
- if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
- hw->fc.requested_mode = e1000_fc_none;
- else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
- NVM_WORD0F_ASM_DIR)
- hw->fc.requested_mode = e1000_fc_tx_pause;
- else
- hw->fc.requested_mode = e1000_fc_full;
-
-out:
- return ret_val;
-}
-
-/**
* e1000_force_mac_fc_generic - Force the MAC's flow control settings
* @hw: pointer to the HW structure
*
@@ -1318,14 +1275,12 @@ out:
s32 e1000_force_mac_fc_generic(struct e1000_hw *hw)
{
u32 ctrl;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_force_mac_fc_generic");
ctrl = E1000_READ_REG(hw, E1000_CTRL);
- /*
- * Because we didn't get link via the internal auto-negotiation
+ /* Because we didn't get link via the internal auto-negotiation
* mechanism (we either forced link or we got link via PHY
* auto-neg), we have to manually enable/disable transmit an
* receive flow control.
@@ -1361,14 +1316,12 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw)
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1385,13 +1338,13 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
s32 ret_val = E1000_SUCCESS;
+ u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg;
u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
u16 speed, duplex;
DEBUGFUNC("e1000_config_fc_after_link_up_generic");
- /*
- * Check for the case where we have fiber media and auto-neg failed
+ /* Check for the case where we have fiber media and auto-neg failed
* so we had to force link. In this case, we need to force the
* configuration of the MAC to match the "fc" parameter.
*/
@@ -1406,52 +1359,47 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
if (ret_val) {
DEBUGOUT("Error forcing flow control settings\n");
- goto out;
+ return ret_val;
}
- /*
- * Check for the case where we have copper media and auto-neg is
+ /* Check for the case where we have copper media and auto-neg is
* enabled. In this case, we need to check and see if Auto-Neg
* has completed, and if so, how the PHY and link partner has
* flow control configured.
*/
if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
- /*
- * Read the MII Status Register and check to see if AutoNeg
+ /* Read the MII Status Register and check to see if AutoNeg
* has completed. We read this twice because this reg has
* some "sticky" (latched) bits.
*/
ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
- DEBUGOUT("Copper PHY and Auto Neg "
- "has not completed.\n");
- goto out;
+ DEBUGOUT("Copper PHY and Auto Neg has not completed.\n");
+ return ret_val;
}
- /*
- * The AutoNeg process has completed, so we now need to
+ /* The AutoNeg process has completed, so we now need to
* read both the Auto Negotiation Advertisement
* Register (Address 4) and the Auto_Negotiation Base
* Page Ability Register (Address 5) to determine how
* flow control was negotiated.
*/
ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
- &mii_nway_adv_reg);
+ &mii_nway_adv_reg);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
- &mii_nway_lp_ability_reg);
+ &mii_nway_lp_ability_reg);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * Two bits in the Auto Negotiation Advertisement Register
+ /* Two bits in the Auto Negotiation Advertisement Register
* (Address 4) and two bits in the Auto Negotiation Base
* Page Ability Register (Address 5) determine flow control
* for both the PHY and the link partner. The following
@@ -1486,24 +1434,21 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
*/
if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
- /*
- * Now we need to check if the user selected Rx ONLY
+ /* Now we need to check if the user selected Rx ONLY
* of pause frames. In this case, we had to advertise
* FULL flow control because we could not advertise Rx
* ONLY. Hence, we must now check to see if we need to
- * turn OFF the TRANSMISSION of PAUSE frames.
+ * turn OFF the TRANSMISSION of PAUSE frames.
*/
if (hw->fc.requested_mode == e1000_fc_full) {
hw->fc.current_mode = e1000_fc_full;
- DEBUGOUT("Flow Control = FULL.\r\n");
+ DEBUGOUT("Flow Control = FULL.\n");
} else {
hw->fc.current_mode = e1000_fc_rx_pause;
- DEBUGOUT("Flow Control = "
- "Rx PAUSE frames only.\r\n");
+ DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
}
}
- /*
- * For receiving PAUSE frames ONLY.
+ /* For receiving PAUSE frames ONLY.
*
* LOCAL DEVICE | LINK PARTNER
* PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
@@ -1511,14 +1456,13 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
* 0 | 1 | 1 | 1 | e1000_fc_tx_pause
*/
else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
hw->fc.current_mode = e1000_fc_tx_pause;
- DEBUGOUT("Flow Control = Tx PAUSE frames only.\r\n");
+ DEBUGOUT("Flow Control = Tx PAUSE frames only.\n");
}
- /*
- * For transmitting PAUSE frames ONLY.
+ /* For transmitting PAUSE frames ONLY.
*
* LOCAL DEVICE | LINK PARTNER
* PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
@@ -1526,47 +1470,167 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
* 1 | 1 | 0 | 1 | e1000_fc_rx_pause
*/
else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
- !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
hw->fc.current_mode = e1000_fc_rx_pause;
- DEBUGOUT("Flow Control = Rx PAUSE frames only.\r\n");
+ DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
} else {
- /*
- * Per the IEEE spec, at this point flow control
+ /* Per the IEEE spec, at this point flow control
* should be disabled.
*/
hw->fc.current_mode = e1000_fc_none;
- DEBUGOUT("Flow Control = NONE.\r\n");
+ DEBUGOUT("Flow Control = NONE.\n");
}
- /*
- * Now we need to do one last check... If we auto-
+ /* Now we need to do one last check... If we auto-
* negotiated to HALF DUPLEX, flow control should not be
* enabled per IEEE 802.3 spec.
*/
ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
if (ret_val) {
DEBUGOUT("Error getting link speed and duplex\n");
- goto out;
+ return ret_val;
}
if (duplex == HALF_DUPLEX)
hw->fc.current_mode = e1000_fc_none;
- /*
- * Now we call a subroutine to actually force the MAC
+ /* Now we call a subroutine to actually force the MAC
* controller to use the correct flow control settings.
*/
ret_val = e1000_force_mac_fc_generic(hw);
if (ret_val) {
DEBUGOUT("Error forcing flow control settings\n");
- goto out;
+ return ret_val;
}
}
-out:
- return ret_val;
+ /* Check for the case where we have SerDes media and auto-neg is
+ * enabled. In this case, we need to check and see if Auto-Neg
+ * has completed, and if so, how the PHY and link partner has
+ * flow control configured.
+ */
+ if ((hw->phy.media_type == e1000_media_type_internal_serdes) &&
+ mac->autoneg) {
+ /* Read the PCS_LSTS and check to see if AutoNeg
+ * has completed.
+ */
+ pcs_status_reg = E1000_READ_REG(hw, E1000_PCS_LSTAT);
+
+ if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) {
+ DEBUGOUT("PCS Auto Neg has not completed.\n");
+ return ret_val;
+ }
+
+ /* The AutoNeg process has completed, so we now need to
+ * read both the Auto Negotiation Advertisement
+ * Register (PCS_ANADV) and the Auto_Negotiation Base
+ * Page Ability Register (PCS_LPAB) to determine how
+ * flow control was negotiated.
+ */
+ pcs_adv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV);
+ pcs_lp_ability_reg = E1000_READ_REG(hw, E1000_PCS_LPAB);
+
+ /* Two bits in the Auto Negotiation Advertisement Register
+ * (PCS_ANADV) and two bits in the Auto Negotiation Base
+ * Page Ability Register (PCS_LPAB) determine flow control
+ * for both the PHY and the link partner. The following
+ * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+ * 1999, describes these PAUSE resolution bits and how flow
+ * control is determined based upon these settings.
+ * NOTE: DC = Don't Care
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+ *-------|---------|-------|---------|--------------------
+ * 0 | 0 | DC | DC | e1000_fc_none
+ * 0 | 1 | 0 | DC | e1000_fc_none
+ * 0 | 1 | 1 | 0 | e1000_fc_none
+ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause
+ * 1 | 0 | 0 | DC | e1000_fc_none
+ * 1 | DC | 1 | DC | e1000_fc_full
+ * 1 | 1 | 0 | 0 | e1000_fc_none
+ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
+ *
+ * Are both PAUSE bits set to 1? If so, this implies
+ * Symmetric Flow Control is enabled at both ends. The
+ * ASM_DIR bits are irrelevant per the spec.
+ *
+ * For Symmetric Flow Control:
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 1 | DC | 1 | DC | e1000_fc_full
+ *
+ */
+ if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+ (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) {
+ /* Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise Rx
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == e1000_fc_full) {
+ hw->fc.current_mode = e1000_fc_full;
+ DEBUGOUT("Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = e1000_fc_rx_pause;
+ DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
+ }
+ }
+ /* For receiving PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 0 | 1 | 1 | 1 | e1000_fc_tx_pause
+ */
+ else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) &&
+ (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+ (pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+ (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+ hw->fc.current_mode = e1000_fc_tx_pause;
+ DEBUGOUT("Flow Control = Tx PAUSE frames only.\n");
+ }
+ /* For transmitting PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
+ */
+ else if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+ (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+ !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+ (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+ hw->fc.current_mode = e1000_fc_rx_pause;
+ DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
+ } else {
+ /* Per the IEEE spec, at this point flow control
+ * should be disabled.
+ */
+ hw->fc.current_mode = e1000_fc_none;
+ DEBUGOUT("Flow Control = NONE.\n");
+ }
+
+ /* Now we call a subroutine to actually force the MAC
+ * controller to use the correct flow control settings.
+ */
+ pcs_ctrl_reg = E1000_READ_REG(hw, E1000_PCS_LCTL);
+ pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+ E1000_WRITE_REG(hw, E1000_PCS_LCTL, pcs_ctrl_reg);
+
+ ret_val = e1000_force_mac_fc_generic(hw);
+ if (ret_val) {
+ DEBUGOUT("Error forcing flow control settings\n");
+ return ret_val;
+ }
+ }
+
+ return E1000_SUCCESS;
}
/**
@@ -1579,7 +1643,7 @@ out:
* speed and duplex for copper connections.
**/
s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
- u16 *duplex)
+ u16 *duplex)
{
u32 status;
@@ -1618,7 +1682,7 @@ s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
* for fiber/serdes links.
**/
s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
- u16 *speed, u16 *duplex)
+ u16 *speed, u16 *duplex)
{
DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic");
@@ -1637,7 +1701,6 @@ s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
{
u32 swsm;
- s32 ret_val = E1000_SUCCESS;
s32 timeout = hw->nvm.word_size + 1;
s32 i = 0;
@@ -1655,8 +1718,7 @@ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
if (i == timeout) {
DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
/* Get the FW semaphore. */
@@ -1675,12 +1737,10 @@ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
/* Release semaphores */
e1000_put_hw_semaphore_generic(hw);
DEBUGOUT("Driver can't access the NVM\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1711,7 +1771,6 @@ void e1000_put_hw_semaphore_generic(struct e1000_hw *hw)
s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
{
s32 i = 0;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_get_auto_rd_done_generic");
@@ -1724,12 +1783,10 @@ s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
if (i == AUTO_READ_DONE_TIMEOUT) {
DEBUGOUT("Auto read by HW from NVM has not completed.\n");
- ret_val = -E1000_ERR_RESET;
- goto out;
+ return -E1000_ERR_RESET;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1749,14 +1806,13 @@ s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data)
ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
*data = ID_LED_DEFAULT;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1778,7 +1834,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw)
ret_val = hw->nvm.ops.valid_led_default(hw, &data);
if (ret_val)
- goto out;
+ return ret_val;
mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL);
mac->ledctl_mode1 = mac->ledctl_default;
@@ -1822,8 +1878,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw)
}
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1836,31 +1891,26 @@ out:
s32 e1000_setup_led_generic(struct e1000_hw *hw)
{
u32 ledctl;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_setup_led_generic");
- if (hw->mac.ops.setup_led != e1000_setup_led_generic) {
- ret_val = -E1000_ERR_CONFIG;
- goto out;
- }
+ if (hw->mac.ops.setup_led != e1000_setup_led_generic)
+ return -E1000_ERR_CONFIG;
if (hw->phy.media_type == e1000_media_type_fiber) {
ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
hw->mac.ledctl_default = ledctl;
/* Turn off LED0 */
- ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
- E1000_LEDCTL_LED0_BLINK |
- E1000_LEDCTL_LED0_MODE_MASK);
+ ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK |
+ E1000_LEDCTL_LED0_MODE_MASK);
ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
- E1000_LEDCTL_LED0_MODE_SHIFT);
+ E1000_LEDCTL_LED0_MODE_SHIFT);
E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
} else if (hw->phy.media_type == e1000_media_type_copper) {
E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1896,16 +1946,28 @@ s32 e1000_blink_led_generic(struct e1000_hw *hw)
ledctl_blink = E1000_LEDCTL_LED0_BLINK |
(E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
} else {
- /*
- * set the blink bit for each LED that's "on" (0x0E)
- * in ledctl_mode2
+ /* Set the blink bit for each LED that's "on" (0x0E)
+ * (or "off" if inverted) in ledctl_mode2. The blink
+ * logic in hardware only works when mode is set to "on"
+ * so it must be changed accordingly when the mode is
+ * "off" and inverted.
*/
ledctl_blink = hw->mac.ledctl_mode2;
- for (i = 0; i < 4; i++)
- if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
- E1000_LEDCTL_MODE_LED_ON)
- ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
- (i * 8));
+ for (i = 0; i < 32; i += 8) {
+ u32 mode = (hw->mac.ledctl_mode2 >> i) &
+ E1000_LEDCTL_LED0_MODE_MASK;
+ u32 led_default = hw->mac.ledctl_default >> i;
+
+ if ((!(led_default & E1000_LEDCTL_LED0_IVRT) &&
+ (mode == E1000_LEDCTL_MODE_LED_ON)) ||
+ ((led_default & E1000_LEDCTL_LED0_IVRT) &&
+ (mode == E1000_LEDCTL_MODE_LED_OFF))) {
+ ledctl_blink &=
+ ~(E1000_LEDCTL_LED0_MODE_MASK << i);
+ ledctl_blink |= (E1000_LEDCTL_LED0_BLINK |
+ E1000_LEDCTL_MODE_LED_ON) << i;
+ }
+ }
}
E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink);
@@ -1985,7 +2047,7 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
DEBUGFUNC("e1000_set_pcie_no_snoop_generic");
if (hw->bus.type != e1000_bus_type_pci_express)
- goto out;
+ return;
if (no_snoop) {
gcr = E1000_READ_REG(hw, E1000_GCR);
@@ -1993,8 +2055,6 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
gcr |= no_snoop;
E1000_WRITE_REG(hw, E1000_GCR, gcr);
}
-out:
- return;
}
/**
@@ -2012,12 +2072,11 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw)
{
u32 ctrl;
s32 timeout = MASTER_DISABLE_TIMEOUT;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_disable_pcie_master_generic");
if (hw->bus.type != e1000_bus_type_pci_express)
- goto out;
+ return E1000_SUCCESS;
ctrl = E1000_READ_REG(hw, E1000_CTRL);
ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
@@ -2033,11 +2092,10 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw)
if (!timeout) {
DEBUGOUT("Master requests are pending.\n");
- ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING;
+ return -E1000_ERR_MASTER_REQUESTS_PENDING;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2054,7 +2112,7 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw)
if (!mac->adaptive_ifs) {
DEBUGOUT("Not in Adaptive IFS mode!\n");
- goto out;
+ return;
}
mac->current_ifs_val = 0;
@@ -2065,8 +2123,6 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw)
mac->in_ifs_mode = FALSE;
E1000_WRITE_REG(hw, E1000_AIT, 0);
-out:
- return;
}
/**
@@ -2084,7 +2140,7 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw)
if (!mac->adaptive_ifs) {
DEBUGOUT("Not in Adaptive IFS mode!\n");
- goto out;
+ return;
}
if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) {
@@ -2096,7 +2152,8 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw)
else
mac->current_ifs_val +=
mac->ifs_step_size;
- E1000_WRITE_REG(hw, E1000_AIT, mac->current_ifs_val);
+ E1000_WRITE_REG(hw, E1000_AIT,
+ mac->current_ifs_val);
}
}
} else {
@@ -2107,8 +2164,6 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_AIT, 0);
}
}
-out:
- return;
}
/**
@@ -2120,19 +2175,29 @@ out:
**/
static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
-
DEBUGFUNC("e1000_validate_mdi_setting_generic");
if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) {
DEBUGOUT("Invalid MDI setting detected\n");
hw->phy.mdix = 1;
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_validate_mdi_setting_crossover_generic - Verify MDI/MDIx settings
+ * @hw: pointer to the HW structure
+ *
+ * Validate the MDI/MDIx setting, allowing for auto-crossover during forced
+ * operation.
+ **/
+s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw)
+{
+ DEBUGFUNC("e1000_validate_mdi_setting_crossover_generic");
+
+ return E1000_SUCCESS;
}
/**
@@ -2147,10 +2212,9 @@ out:
* completion.
**/
s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
- u32 offset, u8 data)
+ u32 offset, u8 data)
{
u32 i, regvalue = 0;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_8bit_ctrl_reg_generic");
@@ -2167,10 +2231,8 @@ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
}
if (!(regvalue & E1000_GEN_CTL_READY)) {
DEBUGOUT1("Reg %08x did not indicate ready\n", reg);
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
diff --git a/freebsd/sys/dev/e1000/e1000_mac.h b/freebsd/sys/dev/e1000/e1000_mac.h
index 348d660f..3e2ccded 100644
--- a/freebsd/sys/dev/e1000/e1000_mac.h
+++ b/freebsd/sys/dev/e1000/e1000_mac.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,10 +35,6 @@
#ifndef _E1000_MAC_H_
#define _E1000_MAC_H_
-/*
- * Functions that should not be called directly from drivers but can be used
- * by other files in this 'shared code'
- */
void e1000_init_mac_ops_generic(struct e1000_hw *hw);
void e1000_null_mac_generic(struct e1000_hw *hw);
s32 e1000_null_ops_generic(struct e1000_hw *hw);
@@ -47,6 +43,7 @@ bool e1000_null_mng_mode(struct e1000_hw *hw);
void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a);
void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b);
void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a);
+s32 e1000_null_set_obff_timer(struct e1000_hw *hw, u32 a);
s32 e1000_blink_led_generic(struct e1000_hw *hw);
s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw);
s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw);
@@ -64,31 +61,30 @@ void e1000_set_lan_id_single_port(struct e1000_hw *hw);
void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw);
s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw);
s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
- u16 *duplex);
+ u16 *duplex);
s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
- u16 *speed, u16 *duplex);
+ u16 *speed, u16 *duplex);
s32 e1000_id_led_init_generic(struct e1000_hw *hw);
s32 e1000_led_on_generic(struct e1000_hw *hw);
s32 e1000_led_off_generic(struct e1000_hw *hw);
void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count);
+ u8 *mc_addr_list, u32 mc_addr_count);
s32 e1000_set_default_fc_generic(struct e1000_hw *hw);
s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw);
s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw);
s32 e1000_setup_led_generic(struct e1000_hw *hw);
s32 e1000_setup_link_generic(struct e1000_hw *hw);
+s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw);
s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
- u32 offset, u8 data);
+ u32 offset, u8 data);
u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr);
void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw);
void e1000_clear_vfta_generic(struct e1000_hw *hw);
-void e1000_config_collision_dist_generic(struct e1000_hw *hw);
void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count);
void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw);
void e1000_put_hw_semaphore_generic(struct e1000_hw *hw);
-void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw);
void e1000_reset_adaptive_generic(struct e1000_hw *hw);
void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop);
diff --git a/freebsd/sys/dev/e1000/e1000_manage.c b/freebsd/sys/dev/e1000/e1000_manage.c
index 540b8a0c..1646f435 100644
--- a/freebsd/sys/dev/e1000/e1000_manage.c
+++ b/freebsd/sys/dev/e1000/e1000_manage.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -40,8 +40,6 @@
#include <rtems/bsd/local/e1000_api.h>
#endif
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
-
/**
* e1000_calculate_checksum - Calculate checksum for buffer
* @buffer: pointer to EEPROM
@@ -50,10 +48,10 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
* Calculates the checksum for some buffer on a specified length. The
* checksum calculated is returned.
**/
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
+u8 e1000_calculate_checksum(u8 *buffer, u32 length)
{
u32 i;
- u8 sum = 0;
+ u8 sum = 0;
DEBUGFUNC("e1000_calculate_checksum");
@@ -79,23 +77,20 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
{
u32 hicr;
- s32 ret_val = E1000_SUCCESS;
u8 i;
DEBUGFUNC("e1000_mng_enable_host_if_generic");
- if (!(hw->mac.arc_subsystem_valid)) {
+ if (!hw->mac.arc_subsystem_valid) {
DEBUGOUT("ARC subsystem not valid.\n");
- ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
- goto out;
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* Check that the host interface is enabled. */
hicr = E1000_READ_REG(hw, E1000_HICR);
- if ((hicr & E1000_HICR_EN) == 0) {
+ if (!(hicr & E1000_HICR_EN)) {
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
- ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
- goto out;
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* check the previous command is completed */
for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
@@ -107,12 +102,10 @@ s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
DEBUGOUT("Previous command timeout failed .\n");
- ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
- goto out;
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -130,7 +123,7 @@ bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
return (fwsm & E1000_FWSM_MODE_MASK) ==
- (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
}
/**
@@ -155,17 +148,16 @@ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
/* No manageability, no filtering */
if (!hw->mac.ops.check_mng_mode(hw)) {
hw->mac.tx_pkt_filtering = FALSE;
- goto out;
+ return hw->mac.tx_pkt_filtering;
}
- /*
- * If we can't read from the host interface for whatever
+ /* If we can't read from the host interface for whatever
* reason, disable filtering.
*/
- ret_val = hw->mac.ops.mng_enable_host_if(hw);
+ ret_val = e1000_mng_enable_host_if_generic(hw);
if (ret_val != E1000_SUCCESS) {
hw->mac.tx_pkt_filtering = FALSE;
- goto out;
+ return hw->mac.tx_pkt_filtering;
}
/* Read in the header. Length and offset are in dwords. */
@@ -173,79 +165,28 @@ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
for (i = 0; i < len; i++)
*(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
- offset + i);
+ offset + i);
hdr_csum = hdr->checksum;
hdr->checksum = 0;
csum = e1000_calculate_checksum((u8 *)hdr,
- E1000_MNG_DHCP_COOKIE_LENGTH);
- /*
- * If either the checksums or signature don't match, then
+ E1000_MNG_DHCP_COOKIE_LENGTH);
+ /* If either the checksums or signature don't match, then
* the cookie area isn't considered valid, in which case we
* take the safe route of assuming Tx filtering is enabled.
*/
if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
hw->mac.tx_pkt_filtering = TRUE;
- goto out;
+ return hw->mac.tx_pkt_filtering;
}
/* Cookie area is valid, make the final check for filtering. */
- if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
+ if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
hw->mac.tx_pkt_filtering = FALSE;
- goto out;
- }
-out:
return hw->mac.tx_pkt_filtering;
}
/**
- * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
- * @hw: pointer to the HW structure
- * @buffer: pointer to the host interface
- * @length: size of the buffer
- *
- * Writes the DHCP information to the host interface.
- **/
-s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
- u16 length)
-{
- struct e1000_host_mng_command_header hdr;
- s32 ret_val;
- u32 hicr;
-
- DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
-
- hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
- hdr.command_length = length;
- hdr.reserved1 = 0;
- hdr.reserved2 = 0;
- hdr.checksum = 0;
-
- /* Enable the host interface */
- ret_val = hw->mac.ops.mng_enable_host_if(hw);
- if (ret_val)
- goto out;
-
- /* Populate the host interface with the contents of "buffer". */
- ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
- sizeof(hdr), &(hdr.checksum));
- if (ret_val)
- goto out;
-
- /* Write the manageability command header */
- ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
- if (ret_val)
- goto out;
-
- /* Tell the ARC a new command is pending. */
- hicr = E1000_READ_REG(hw, E1000_HICR);
- E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
-
-out:
- return ret_val;
-}
-
-/**
* e1000_mng_write_cmd_header_generic - Writes manageability command header
* @hw: pointer to the HW structure
* @hdr: pointer to the host interface command header
@@ -253,7 +194,7 @@ out:
* Writes the command header after does the checksum calculation.
**/
s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
- struct e1000_host_mng_command_header *hdr)
+ struct e1000_host_mng_command_header *hdr)
{
u16 i, length = sizeof(struct e1000_host_mng_command_header);
@@ -267,7 +208,7 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
/* Write the relevant command block into the ram area. */
for (i = 0; i < length; i++) {
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
- *((u32 *) hdr + i));
+ *((u32 *) hdr + i));
E1000_WRITE_FLUSH(hw);
}
@@ -287,22 +228,19 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
* way. Also fills up the sum of the buffer in *buffer parameter.
**/
s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
- u16 length, u16 offset, u8 *sum)
+ u16 length, u16 offset, u8 *sum)
{
u8 *tmp;
u8 *bufptr = buffer;
u32 data = 0;
- s32 ret_val = E1000_SUCCESS;
u16 remaining, i, j, prev_bytes;
DEBUGFUNC("e1000_mng_host_if_write_generic");
/* sum = only sum of the data and it is not checksum */
- if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
- ret_val = -E1000_ERR_PARAM;
- goto out;
- }
+ if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
+ return -E1000_ERR_PARAM;
tmp = (u8 *)&data;
prev_bytes = offset & 0x3;
@@ -325,8 +263,7 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
/* Calculate length in DWORDs */
length >>= 2;
- /*
- * The device driver writes the relevant command block into the
+ /* The device driver writes the relevant command block into the
* ram area.
*/
for (i = 0; i < length; i++) {
@@ -336,7 +273,7 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
}
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
- data);
+ data);
}
if (remaining) {
for (j = 0; j < sizeof(u32); j++) {
@@ -347,11 +284,57 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
*sum += *(tmp + j);
}
- E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
+ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
+ data);
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
+ * @hw: pointer to the HW structure
+ * @buffer: pointer to the host interface
+ * @length: size of the buffer
+ *
+ * Writes the DHCP information to the host interface.
+ **/
+s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
+ u16 length)
+{
+ struct e1000_host_mng_command_header hdr;
+ s32 ret_val;
+ u32 hicr;
+
+ DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
+
+ hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
+ hdr.command_length = length;
+ hdr.reserved1 = 0;
+ hdr.reserved2 = 0;
+ hdr.checksum = 0;
+
+ /* Enable the host interface */
+ ret_val = e1000_mng_enable_host_if_generic(hw);
+ if (ret_val)
+ return ret_val;
+
+ /* Populate the host interface with the contents of "buffer". */
+ ret_val = e1000_mng_host_if_write_generic(hw, buffer, length,
+ sizeof(hdr), &(hdr.checksum));
+ if (ret_val)
+ return ret_val;
+
+ /* Write the manageability command header */
+ ret_val = e1000_mng_write_cmd_header_generic(hw, &hdr);
+ if (ret_val)
+ return ret_val;
+
+ /* Tell the ARC a new command is pending. */
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
+
+ return E1000_SUCCESS;
}
/**
@@ -365,17 +348,16 @@ bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
{
u32 manc;
u32 fwsm, factps;
- bool ret_val = FALSE;
DEBUGFUNC("e1000_enable_mng_pass_thru");
if (!hw->mac.asf_firmware_present)
- goto out;
+ return FALSE;
manc = E1000_READ_REG(hw, E1000_MANC);
if (!(manc & E1000_MANC_RCV_TCO_EN))
- goto out;
+ return FALSE;
if (hw->mac.has_fwsm) {
fwsm = E1000_READ_REG(hw, E1000_FWSM);
@@ -383,10 +365,8 @@ bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
if (!(factps & E1000_FACTPS_MNGCG) &&
((fwsm & E1000_FWSM_MODE_MASK) ==
- (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
- ret_val = TRUE;
- goto out;
- }
+ (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
+ return TRUE;
} else if ((hw->mac.type == e1000_82574) ||
(hw->mac.type == e1000_82583)) {
u16 data;
@@ -396,17 +376,205 @@ bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
if (!(factps & E1000_FACTPS_MNGCG) &&
((data & E1000_NVM_INIT_CTRL2_MNGM) ==
- (e1000_mng_mode_pt << 13))) {
- ret_val = TRUE;
- goto out;
- }
+ (e1000_mng_mode_pt << 13)))
+ return TRUE;
} else if ((manc & E1000_MANC_SMBUS_EN) &&
- !(manc & E1000_MANC_ASF_EN)) {
- ret_val = TRUE;
- goto out;
+ !(manc & E1000_MANC_ASF_EN)) {
+ return TRUE;
}
-out:
- return ret_val;
+ return FALSE;
}
+/**
+ * e1000_host_interface_command - Writes buffer to host interface
+ * @hw: pointer to the HW structure
+ * @buffer: contains a command to write
+ * @length: the byte length of the buffer, must be multiple of 4 bytes
+ *
+ * Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS
+ * else returns E1000_ERR_HOST_INTERFACE_COMMAND.
+ **/
+s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
+{
+ u32 hicr, i;
+
+ DEBUGFUNC("e1000_host_interface_command");
+
+ if (!(hw->mac.arc_subsystem_valid)) {
+ DEBUGOUT("Hardware doesn't support host interface command.\n");
+ return E1000_SUCCESS;
+ }
+
+ if (!hw->mac.asf_firmware_present) {
+ DEBUGOUT("Firmware is not present.\n");
+ return E1000_SUCCESS;
+ }
+
+ if (length == 0 || length & 0x3 ||
+ length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
+ DEBUGOUT("Buffer length failure.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ /* Check that the host interface is enabled. */
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ if (!(hicr & E1000_HICR_EN)) {
+ DEBUGOUT("E1000_HOST_EN bit disabled.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ /* Calculate length in DWORDs */
+ length >>= 2;
+
+ /* The device driver writes the relevant command block
+ * into the ram area.
+ */
+ for (i = 0; i < length; i++)
+ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
+ *((u32 *)buffer + i));
+
+ /* Setting this bit tells the ARC that a new command is pending. */
+ E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
+
+ for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ if (!(hicr & E1000_HICR_C))
+ break;
+ msec_delay(1);
+ }
+
+ /* Check command successful completion. */
+ if (i == E1000_HI_COMMAND_TIMEOUT ||
+ (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
+ DEBUGOUT("Command has failed with no status valid.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ for (i = 0; i < length; i++)
+ *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
+ E1000_HOST_IF,
+ i);
+
+ return E1000_SUCCESS;
+}
+/**
+ * e1000_load_firmware - Writes proxy FW code buffer to host interface
+ * and execute.
+ * @hw: pointer to the HW structure
+ * @buffer: contains a firmware to write
+ * @length: the byte length of the buffer, must be multiple of 4 bytes
+ *
+ * Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled
+ * in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND.
+ **/
+s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length)
+{
+ u32 hicr, hibba, fwsm, icr, i;
+
+ DEBUGFUNC("e1000_load_firmware");
+
+ if (hw->mac.type < e1000_i210) {
+ DEBUGOUT("Hardware doesn't support loading FW by the driver\n");
+ return -E1000_ERR_CONFIG;
+ }
+
+ /* Check that the host interface is enabled. */
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ if (!(hicr & E1000_HICR_EN)) {
+ DEBUGOUT("E1000_HOST_EN bit disabled.\n");
+ return -E1000_ERR_CONFIG;
+ }
+ if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) {
+ DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n");
+ return -E1000_ERR_CONFIG;
+ }
+
+ if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) {
+ DEBUGOUT("Buffer length failure.\n");
+ return -E1000_ERR_INVALID_ARGUMENT;
+ }
+
+ /* Clear notification from ROM-FW by reading ICR register */
+ icr = E1000_READ_REG(hw, E1000_ICR_V2);
+
+ /* Reset ROM-FW */
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ hicr |= E1000_HICR_FW_RESET_ENABLE;
+ E1000_WRITE_REG(hw, E1000_HICR, hicr);
+ hicr |= E1000_HICR_FW_RESET;
+ E1000_WRITE_REG(hw, E1000_HICR, hicr);
+ E1000_WRITE_FLUSH(hw);
+
+ /* Wait till MAC notifies about its readiness after ROM-FW reset */
+ for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) {
+ icr = E1000_READ_REG(hw, E1000_ICR_V2);
+ if (icr & E1000_ICR_MNG)
+ break;
+ msec_delay(1);
+ }
+
+ /* Check for timeout */
+ if (i == E1000_HI_COMMAND_TIMEOUT) {
+ DEBUGOUT("FW reset failed.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ /* Wait till MAC is ready to accept new FW code */
+ for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
+ fwsm = E1000_READ_REG(hw, E1000_FWSM);
+ if ((fwsm & E1000_FWSM_FW_VALID) &&
+ ((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT ==
+ E1000_FWSM_HI_EN_ONLY_MODE))
+ break;
+ msec_delay(1);
+ }
+
+ /* Check for timeout */
+ if (i == E1000_HI_COMMAND_TIMEOUT) {
+ DEBUGOUT("FW reset failed.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ /* Calculate length in DWORDs */
+ length >>= 2;
+
+ /* The device driver writes the relevant FW code block
+ * into the ram area in DWORDs via 1kB ram addressing window.
+ */
+ for (i = 0; i < length; i++) {
+ if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) {
+ /* Point to correct 1kB ram window */
+ hibba = E1000_HI_FW_BASE_ADDRESS +
+ ((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) *
+ (i / E1000_HI_FW_BLOCK_DWORD_LENGTH));
+
+ E1000_WRITE_REG(hw, E1000_HIBBA, hibba);
+ }
+
+ E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
+ i % E1000_HI_FW_BLOCK_DWORD_LENGTH,
+ *((u32 *)buffer + i));
+ }
+
+ /* Setting this bit tells the ARC that a new FW is ready to execute. */
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
+
+ for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ if (!(hicr & E1000_HICR_C))
+ break;
+ msec_delay(1);
+ }
+
+ /* Check for successful FW start. */
+ if (i == E1000_HI_COMMAND_TIMEOUT) {
+ DEBUGOUT("New FW did not start within timeout period.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ return E1000_SUCCESS;
+}
+
+
diff --git a/freebsd/sys/dev/e1000/e1000_manage.h b/freebsd/sys/dev/e1000/e1000_manage.h
index 146caeb5..51f17671 100644
--- a/freebsd/sys/dev/e1000/e1000_manage.h
+++ b/freebsd/sys/dev/e1000/e1000_manage.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2012, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -39,12 +39,15 @@ bool e1000_check_mng_mode_generic(struct e1000_hw *hw);
bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw);
s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw);
s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
- u16 length, u16 offset, u8 *sum);
+ u16 length, u16 offset, u8 *sum);
s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
- struct e1000_host_mng_command_header *hdr);
+ struct e1000_host_mng_command_header *hdr);
s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
- u8 *buffer, u16 length);
+ u8 *buffer, u16 length);
bool e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+u8 e1000_calculate_checksum(u8 *buffer, u32 length);
+s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length);
+s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length);
enum e1000_mng_mode {
e1000_mng_mode_none = 0,
@@ -54,35 +57,40 @@ enum e1000_mng_mode {
e1000_mng_mode_host_if_only
};
-#define E1000_FACTPS_MNGCG 0x20000000
+#define E1000_FACTPS_MNGCG 0x20000000
-#define E1000_FWSM_MODE_MASK 0xE
-#define E1000_FWSM_MODE_SHIFT 1
+#define E1000_FWSM_MODE_MASK 0xE
+#define E1000_FWSM_MODE_SHIFT 1
+#define E1000_FWSM_FW_VALID 0x00008000
+#define E1000_FWSM_HI_EN_ONLY_MODE 0x4
-#define E1000_MNG_IAMT_MODE 0x3
-#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10
-#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0
-#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10
-#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
-#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1
-#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
+#define E1000_MNG_IAMT_MODE 0x3
+#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10
+#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0
+#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10
+#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
+#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1
+#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
-#define E1000_VFTA_ENTRY_SHIFT 5
-#define E1000_VFTA_ENTRY_MASK 0x7F
-#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
+#define E1000_VFTA_ENTRY_SHIFT 5
+#define E1000_VFTA_ENTRY_MASK 0x7F
+#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
-#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */
-#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */
-#define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */
-
-#define E1000_HICR_EN 0x01 /* Enable bit - RO */
+#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */
+#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */
+#define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI cmd limit */
+#define E1000_HI_FW_BASE_ADDRESS 0x10000
+#define E1000_HI_FW_MAX_LENGTH (64 * 1024) /* Num of bytes */
+#define E1000_HI_FW_BLOCK_DWORD_LENGTH 256 /* Num of DWORDs per page */
+#define E1000_HICR_MEMORY_BASE_EN 0x200 /* MB Enable bit - RO */
+#define E1000_HICR_EN 0x01 /* Enable bit - RO */
/* Driver sets this bit when done to put command in RAM */
-#define E1000_HICR_C 0x02
-#define E1000_HICR_SV 0x04 /* Status Validity */
-#define E1000_HICR_FW_RESET_ENABLE 0x40
-#define E1000_HICR_FW_RESET 0x80
+#define E1000_HICR_C 0x02
+#define E1000_HICR_SV 0x04 /* Status Validity */
+#define E1000_HICR_FW_RESET_ENABLE 0x40
+#define E1000_HICR_FW_RESET 0x80
/* Intel(R) Active Management Technology signature */
-#define E1000_IAMT_SIGNATURE 0x544D4149
+#define E1000_IAMT_SIGNATURE 0x544D4149
#endif
diff --git a/freebsd/sys/dev/e1000/e1000_mbx.c b/freebsd/sys/dev/e1000/e1000_mbx.c
index 5236837a..7408d814 100644
--- a/freebsd/sys/dev/e1000/e1000_mbx.c
+++ b/freebsd/sys/dev/e1000/e1000_mbx.c
@@ -742,7 +742,9 @@ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
- if (hw->mac.type == e1000_82576) {
+ switch (hw->mac.type) {
+ case e1000_82576:
+ case e1000_i350:
mbx->timeout = 0;
mbx->usec_delay = 0;
@@ -761,8 +763,8 @@ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
mbx->stats.reqs = 0;
mbx->stats.acks = 0;
mbx->stats.rsts = 0;
+ default:
+ return E1000_SUCCESS;
}
-
- return E1000_SUCCESS;
}
diff --git a/freebsd/sys/dev/e1000/e1000_nvm.c b/freebsd/sys/dev/e1000/e1000_nvm.c
index 8fefe31c..370dca32 100644
--- a/freebsd/sys/dev/e1000/e1000_nvm.c
+++ b/freebsd/sys/dev/e1000/e1000_nvm.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -233,7 +233,6 @@ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
{
u32 attempts = 100000;
u32 i, reg = 0;
- s32 ret_val = -E1000_ERR_NVM;
DEBUGFUNC("e1000_poll_eerd_eewr_done");
@@ -243,15 +242,13 @@ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
else
reg = E1000_READ_REG(hw, E1000_EEWR);
- if (reg & E1000_NVM_RW_REG_DONE) {
- ret_val = E1000_SUCCESS;
- break;
- }
+ if (reg & E1000_NVM_RW_REG_DONE)
+ return E1000_SUCCESS;
usec_delay(5);
}
- return ret_val;
+ return -E1000_ERR_NVM;
}
/**
@@ -266,7 +263,6 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
{
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_acquire_nvm_generic");
@@ -285,10 +281,10 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
DEBUGOUT("Could not acquire NVM grant\n");
- ret_val = -E1000_ERR_NVM;
+ return -E1000_ERR_NVM;
}
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -319,8 +315,7 @@ static void e1000_standby_nvm(struct e1000_hw *hw)
usec_delay(nvm->delay_usec);
e1000_lower_eec_clk(hw, &eecd);
- } else
- if (nvm->type == e1000_nvm_eeprom_spi) {
+ } else if (nvm->type == e1000_nvm_eeprom_spi) {
/* Toggle CS to flush commands */
eecd |= E1000_EECD_CS;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
@@ -388,8 +383,6 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
- s32 ret_val = E1000_SUCCESS;
- u16 timeout = 0;
u8 spi_stat_reg;
DEBUGFUNC("e1000_ready_nvm_eeprom");
@@ -401,23 +394,23 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
/* Set CS */
eecd |= E1000_EECD_CS;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
- } else
- if (nvm->type == e1000_nvm_eeprom_spi) {
+ } else if (nvm->type == e1000_nvm_eeprom_spi) {
+ u16 timeout = NVM_MAX_RETRY_SPI;
+
/* Clear SK and CS */
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
E1000_WRITE_REG(hw, E1000_EECD, eecd);
+ E1000_WRITE_FLUSH(hw);
usec_delay(1);
- timeout = NVM_MAX_RETRY_SPI;
- /*
- * Read "Status Register" repeatedly until the LSB is cleared.
+ /* Read "Status Register" repeatedly until the LSB is cleared.
* The EEPROM will signal that the command has been completed
* by clearing bit 0 of the internal status register. If it's
* not cleared within 'timeout', then error out.
*/
while (timeout) {
e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
- hw->nvm.opcode_bits);
+ hw->nvm.opcode_bits);
spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
break;
@@ -429,13 +422,11 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
if (!timeout) {
DEBUGOUT("SPI NVM Status error\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -457,20 +448,18 @@ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
DEBUGFUNC("e1000_read_nvm_spi");
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
ret_val = nvm->ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_ready_nvm_eeprom(hw);
if (ret_val)
@@ -485,8 +474,7 @@ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
- /*
- * Read the data. SPI NVMs increment the address with each byte
+ /* Read the data. SPI NVMs increment the address with each byte
* read and will roll over if reading beyond the end. This allows
* us to read the whole NVM from any offset
*/
@@ -498,7 +486,6 @@ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
release:
nvm->ops.release(hw);
-out:
return ret_val;
}
@@ -512,7 +499,7 @@ out:
* Reads a 16 bit word from the EEPROM.
**/
s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+ u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 i = 0;
@@ -521,20 +508,18 @@ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
DEBUGFUNC("e1000_read_nvm_microwire");
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
ret_val = nvm->ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_ready_nvm_eeprom(hw);
if (ret_val)
@@ -546,8 +531,7 @@ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
e1000_shift_out_eec_bits(hw, (u16)(offset + i),
nvm->address_bits);
- /*
- * Read the data. For microwire, each word requires the
+ /* Read the data. For microwire, each word requires the
* overhead of setup and tear-down.
*/
data[i] = e1000_shift_in_eec_bits(hw, 16);
@@ -557,7 +541,6 @@ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
release:
nvm->ops.release(hw);
-out:
return ret_val;
}
@@ -578,15 +561,13 @@ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
DEBUGFUNC("e1000_read_nvm_eerd");
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* too many words for the offset, and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
for (i = 0; i < words; i++) {
@@ -599,10 +580,9 @@ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
break;
data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
- E1000_NVM_RW_REG_DATA);
+ E1000_NVM_RW_REG_DATA);
}
-out:
return ret_val;
}
@@ -621,43 +601,42 @@ out:
s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
- s32 ret_val;
+ s32 ret_val = -E1000_ERR_NVM;
u16 widx = 0;
DEBUGFUNC("e1000_write_nvm_spi");
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
- ret_val = nvm->ops.acquire(hw);
- if (ret_val)
- goto out;
-
while (widx < words) {
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
- ret_val = e1000_ready_nvm_eeprom(hw);
+ ret_val = nvm->ops.acquire(hw);
if (ret_val)
- goto release;
+ return ret_val;
+
+ ret_val = e1000_ready_nvm_eeprom(hw);
+ if (ret_val) {
+ nvm->ops.release(hw);
+ return ret_val;
+ }
e1000_standby_nvm(hw);
/* Send the WRITE ENABLE command (8 bit opcode) */
e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
- nvm->opcode_bits);
+ nvm->opcode_bits);
e1000_standby_nvm(hw);
- /*
- * Some SPI eeproms use the 8th address bit embedded in the
+ /* Some SPI eeproms use the 8th address bit embedded in the
* opcode
*/
if ((nvm->address_bits == 8) && (offset >= 128))
@@ -666,7 +645,7 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
/* Send the Write command (8-bit opcode + addr) */
e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
- nvm->address_bits);
+ nvm->address_bits);
/* Loop to allow for up to whole page write of eeprom */
while (widx < words) {
@@ -680,13 +659,10 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
break;
}
}
+ msec_delay(10);
+ nvm->ops.release(hw);
}
- msec_delay(10);
-release:
- nvm->ops.release(hw);
-
-out:
return ret_val;
}
@@ -703,7 +679,7 @@ out:
* EEPROM will most likely contain an invalid checksum.
**/
s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+ u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
s32 ret_val;
@@ -713,27 +689,25 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
DEBUGFUNC("e1000_write_nvm_microwire");
- /*
- * A check for invalid values: offset too large, too many words,
+ /* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
ret_val = nvm->ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_ready_nvm_eeprom(hw);
if (ret_val)
goto release;
e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE,
- (u16)(nvm->opcode_bits + 2));
+ (u16)(nvm->opcode_bits + 2));
e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
@@ -741,10 +715,10 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
while (words_written < words) {
e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE,
- nvm->opcode_bits);
+ nvm->opcode_bits);
e1000_shift_out_eec_bits(hw, (u16)(offset + words_written),
- nvm->address_bits);
+ nvm->address_bits);
e1000_shift_out_eec_bits(hw, data[words_written], 16);
@@ -769,14 +743,13 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words,
}
e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE,
- (u16)(nvm->opcode_bits + 2));
+ (u16)(nvm->opcode_bits + 2));
e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
release:
nvm->ops.release(hw);
-out:
return ret_val;
}
@@ -789,8 +762,8 @@ out:
* Reads the product board assembly (PBA) number from the EEPROM and stores
* the value in pba_num.
**/
-s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
- u32 pba_num_size)
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+ u32 pba_num_size)
{
s32 ret_val;
u16 nvm_data;
@@ -802,32 +775,30 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
if (pba_num == NULL) {
DEBUGOUT("PBA string buffer was null\n");
- ret_val = E1000_ERR_INVALID_ARGUMENT;
- goto out;
+ return -E1000_ERR_INVALID_ARGUMENT;
}
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
- /*
- * if nvm_data is not ptr guard the PBA must be in legacy format which
+ /* if nvm_data is not ptr guard the PBA must be in legacy format which
* means pba_ptr is actually our second data word for the PBA number
* and we can decode it into an ascii string
*/
if (nvm_data != NVM_PBA_PTR_GUARD) {
DEBUGOUT("NVM PBA number is not stored as string\n");
- /* we will need 11 characters to store the PBA */
- if (pba_num_size < 11) {
+ /* make sure callers buffer is big enough to store the PBA */
+ if (pba_num_size < E1000_PBANUM_LENGTH) {
DEBUGOUT("PBA string buffer too small\n");
return E1000_ERR_NO_SPACE;
}
@@ -855,25 +826,23 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
pba_num[offset] += 'A' - 0xA;
}
- goto out;
+ return E1000_SUCCESS;
}
ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
if (length == 0xFFFF || length == 0) {
DEBUGOUT("NVM PBA number section invalid length\n");
- ret_val = E1000_ERR_NVM_PBA_SECTION;
- goto out;
+ return -E1000_ERR_NVM_PBA_SECTION;
}
/* check if pba_num buffer is big enough */
if (pba_num_size < (((u32)length * 2) - 1)) {
DEBUGOUT("PBA string buffer too small\n");
- ret_val = E1000_ERR_NO_SPACE;
- goto out;
+ return -E1000_ERR_NO_SPACE;
}
/* trim pba length from start of string */
@@ -884,15 +853,14 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
pba_num[offset * 2] = (u8)(nvm_data >> 8);
pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
}
pba_num[offset * 2] = '\0';
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -914,85 +882,233 @@ s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size)
if (pba_num_size == NULL) {
DEBUGOUT("PBA buffer size was null\n");
- ret_val = E1000_ERR_INVALID_ARGUMENT;
- goto out;
+ return -E1000_ERR_INVALID_ARGUMENT;
}
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
/* if data is not ptr guard the PBA must be in legacy format */
if (nvm_data != NVM_PBA_PTR_GUARD) {
- *pba_num_size = 11;
- goto out;
+ *pba_num_size = E1000_PBANUM_LENGTH;
+ return E1000_SUCCESS;
}
ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
if (length == 0xFFFF || length == 0) {
DEBUGOUT("NVM PBA number section invalid length\n");
- ret_val = E1000_ERR_NVM_PBA_SECTION;
- goto out;
+ return -E1000_ERR_NVM_PBA_SECTION;
}
- /*
- * Convert from length in u16 values to u8 chars, add 1 for NULL,
+ /* Convert from length in u16 values to u8 chars, add 1 for NULL,
* and subtract 2 because length field is included in length.
*/
*pba_num_size = ((u32)length * 2) - 1;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
+
/**
- * e1000_read_pba_num_generic - Read device part number
+ * e1000_read_pba_raw
* @hw: pointer to the HW structure
- * @pba_num: pointer to device part number
+ * @eeprom_buf: optional pointer to EEPROM image
+ * @eeprom_buf_size: size of EEPROM image in words
+ * @max_pba_block_size: PBA block size limit
+ * @pba: pointer to output PBA structure
+ *
+ * Reads PBA from EEPROM image when eeprom_buf is not NULL.
+ * Reads PBA from physical EEPROM device when eeprom_buf is NULL.
*
- * Reads the product board assembly (PBA) number from the EEPROM and stores
- * the value in pba_num.
**/
-s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num)
+s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
+ u32 eeprom_buf_size, u16 max_pba_block_size,
+ struct e1000_pba *pba)
{
- s32 ret_val;
- u16 nvm_data;
+ s32 ret_val;
+ u16 pba_block_size;
- DEBUGFUNC("e1000_read_pba_num_generic");
+ if (pba == NULL)
+ return -E1000_ERR_PARAM;
- ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
- if (ret_val) {
- DEBUGOUT("NVM Read Error\n");
- goto out;
- } else if (nvm_data == NVM_PBA_PTR_GUARD) {
- DEBUGOUT("NVM Not Supported\n");
- ret_val = E1000_NOT_IMPLEMENTED;
- goto out;
+ if (eeprom_buf == NULL) {
+ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2,
+ &pba->word[0]);
+ if (ret_val)
+ return ret_val;
+ } else {
+ if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
+ pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
+ pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
+ } else {
+ return -E1000_ERR_PARAM;
+ }
}
- *pba_num = (u32)(nvm_data << 16);
- ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
- if (ret_val) {
- DEBUGOUT("NVM Read Error\n");
- goto out;
+ if (pba->word[0] == NVM_PBA_PTR_GUARD) {
+ if (pba->pba_block == NULL)
+ return -E1000_ERR_PARAM;
+
+ ret_val = e1000_get_pba_block_size(hw, eeprom_buf,
+ eeprom_buf_size,
+ &pba_block_size);
+ if (ret_val)
+ return ret_val;
+
+ if (pba_block_size > max_pba_block_size)
+ return -E1000_ERR_PARAM;
+
+ if (eeprom_buf == NULL) {
+ ret_val = e1000_read_nvm(hw, pba->word[1],
+ pba_block_size,
+ pba->pba_block);
+ if (ret_val)
+ return ret_val;
+ } else {
+ if (eeprom_buf_size > (u32)(pba->word[1] +
+ pba->pba_block[0])) {
+ memcpy(pba->pba_block,
+ &eeprom_buf[pba->word[1]],
+ pba_block_size * sizeof(u16));
+ } else {
+ return -E1000_ERR_PARAM;
+ }
+ }
}
- *pba_num |= nvm_data;
-out:
- return ret_val;
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_write_pba_raw
+ * @hw: pointer to the HW structure
+ * @eeprom_buf: optional pointer to EEPROM image
+ * @eeprom_buf_size: size of EEPROM image in words
+ * @pba: pointer to PBA structure
+ *
+ * Writes PBA to EEPROM image when eeprom_buf is not NULL.
+ * Writes PBA to physical EEPROM device when eeprom_buf is NULL.
+ *
+ **/
+s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
+ u32 eeprom_buf_size, struct e1000_pba *pba)
+{
+ s32 ret_val;
+
+ if (pba == NULL)
+ return -E1000_ERR_PARAM;
+
+ if (eeprom_buf == NULL) {
+ ret_val = e1000_write_nvm(hw, NVM_PBA_OFFSET_0, 2,
+ &pba->word[0]);
+ if (ret_val)
+ return ret_val;
+ } else {
+ if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
+ eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0];
+ eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1];
+ } else {
+ return -E1000_ERR_PARAM;
+ }
+ }
+
+ if (pba->word[0] == NVM_PBA_PTR_GUARD) {
+ if (pba->pba_block == NULL)
+ return -E1000_ERR_PARAM;
+
+ if (eeprom_buf == NULL) {
+ ret_val = e1000_write_nvm(hw, pba->word[1],
+ pba->pba_block[0],
+ pba->pba_block);
+ if (ret_val)
+ return ret_val;
+ } else {
+ if (eeprom_buf_size > (u32)(pba->word[1] +
+ pba->pba_block[0])) {
+ memcpy(&eeprom_buf[pba->word[1]],
+ pba->pba_block,
+ pba->pba_block[0] * sizeof(u16));
+ } else {
+ return -E1000_ERR_PARAM;
+ }
+ }
+ }
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_get_pba_block_size
+ * @hw: pointer to the HW structure
+ * @eeprom_buf: optional pointer to EEPROM image
+ * @eeprom_buf_size: size of EEPROM image in words
+ * @pba_data_size: pointer to output variable
+ *
+ * Returns the size of the PBA block in words. Function operates on EEPROM
+ * image if the eeprom_buf pointer is not NULL otherwise it accesses physical
+ * EEPROM device.
+ *
+ **/
+s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf,
+ u32 eeprom_buf_size, u16 *pba_block_size)
+{
+ s32 ret_val;
+ u16 pba_word[2];
+ u16 length;
+
+ DEBUGFUNC("e1000_get_pba_block_size");
+
+ if (eeprom_buf == NULL) {
+ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]);
+ if (ret_val)
+ return ret_val;
+ } else {
+ if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
+ pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
+ pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
+ } else {
+ return -E1000_ERR_PARAM;
+ }
+ }
+
+ if (pba_word[0] == NVM_PBA_PTR_GUARD) {
+ if (eeprom_buf == NULL) {
+ ret_val = e1000_read_nvm(hw, pba_word[1] + 0, 1,
+ &length);
+ if (ret_val)
+ return ret_val;
+ } else {
+ if (eeprom_buf_size > pba_word[1])
+ length = eeprom_buf[pba_word[1] + 0];
+ else
+ return -E1000_ERR_PARAM;
+ }
+
+ if (length == 0xFFFF || length == 0)
+ return -E1000_ERR_NVM_PBA_SECTION;
+ } else {
+ /* PBA number in legacy format, there is no PBA Block. */
+ length = 0;
+ }
+
+ if (pba_block_size != NULL)
+ *pba_block_size = length;
+
+ return E1000_SUCCESS;
}
/**
@@ -1033,7 +1149,7 @@ s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
**/
s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 checksum = 0;
u16 i, nvm_data;
@@ -1043,19 +1159,17 @@ s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
- goto out;
+ return ret_val;
}
checksum += nvm_data;
}
if (checksum != (u16) NVM_SUM) {
DEBUGOUT("NVM Checksum Invalid\n");
- ret_val = -E1000_ERR_NVM;
- goto out;
+ return -E1000_ERR_NVM;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1078,7 +1192,7 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error while updating checksum.\n");
- goto out;
+ return ret_val;
}
checksum += nvm_data;
}
@@ -1087,7 +1201,6 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
if (ret_val)
DEBUGOUT("NVM Write Error while updating checksum.\n");
-out:
return ret_val;
}
@@ -1111,3 +1224,4 @@ static void e1000_reload_nvm_generic(struct e1000_hw *hw)
E1000_WRITE_FLUSH(hw);
}
+
diff --git a/freebsd/sys/dev/e1000/e1000_nvm.h b/freebsd/sys/dev/e1000/e1000_nvm.h
index 36ee4448..34077b24 100644
--- a/freebsd/sys/dev/e1000/e1000_nvm.h
+++ b/freebsd/sys/dev/e1000/e1000_nvm.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,14 @@
#ifndef _E1000_NVM_H_
#define _E1000_NVM_H_
+#if !defined(NO_READ_PBA_RAW) || !defined(NO_WRITE_PBA_RAW)
+struct e1000_pba {
+ u16 word[2];
+ u16 *pba_block;
+};
+#endif
+
+
void e1000_init_nvm_ops_generic(struct e1000_hw *hw);
s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c);
void e1000_null_nvm_generic(struct e1000_hw *hw);
@@ -44,27 +52,31 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw);
s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
s32 e1000_read_mac_addr_generic(struct e1000_hw *hw);
-s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num);
s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
- u32 pba_num_size);
+ u32 pba_num_size);
s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size);
+s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
+ u32 eeprom_buf_size, u16 max_pba_block_size,
+ struct e1000_pba *pba);
+s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf,
+ u32 eeprom_buf_size, struct e1000_pba *pba);
+s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf,
+ u32 eeprom_buf_size, u16 *pba_block_size);
s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
+ u16 words, u16 *data);
s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data);
+ u16 *data);
s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data);
s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw);
-s32 e1000_write_nvm_eewr(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
+ u16 words, u16 *data);
s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data);
+ u16 *data);
s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw);
void e1000_stop_nvm(struct e1000_hw *hw);
void e1000_release_nvm_generic(struct e1000_hw *hw);
-#define E1000_STM_OPCODE 0xDB00
+#define E1000_STM_OPCODE 0xDB00
#endif
diff --git a/freebsd/sys/dev/e1000/e1000_osdep.c b/freebsd/sys/dev/e1000/e1000_osdep.c
index e02899ad..2d59a9db 100644
--- a/freebsd/sys/dev/e1000/e1000_osdep.c
+++ b/freebsd/sys/dev/e1000/e1000_osdep.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2009, Intel Corporation
+ Copyright (c) 2001-2010, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,7 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
device_t dev = ((struct e1000_osdep *)hw->back)->dev;
u32 offset;
- pci_find_extcap(dev, PCIY_EXPRESS, &offset);
+ pci_find_cap(dev, PCIY_EXPRESS, &offset);
*value = pci_read_config(dev, offset + reg, 2);
return (E1000_SUCCESS);
}
@@ -95,7 +95,7 @@ e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
device_t dev = ((struct e1000_osdep *)hw->back)->dev;
u32 offset;
- pci_find_extcap(dev, PCIY_EXPRESS, &offset);
+ pci_find_cap(dev, PCIY_EXPRESS, &offset);
pci_write_config(dev, offset + reg, *value, 2);
return (E1000_SUCCESS);
}
diff --git a/freebsd/sys/dev/e1000/e1000_osdep.h b/freebsd/sys/dev/e1000/e1000_osdep.h
index e3db3ec5..345536a4 100644
--- a/freebsd/sys/dev/e1000/e1000_osdep.h
+++ b/freebsd/sys/dev/e1000/e1000_osdep.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -66,23 +66,27 @@
#define MSGOUT(S, A, B) printf(S "\n", A, B)
#define DEBUGFUNC(F) DEBUGOUT(F);
#define DEBUGOUT(S) do {} while (0)
-#define DEBUGOUT1(S,A) do {} while (0)
+/* This define is needed or shared code will not build */
+#define DEBUGOUT1(S,A) if (0) printf(S,A);
#define DEBUGOUT2(S,A,B) do {} while (0)
#define DEBUGOUT3(S,A,B,C) do {} while (0)
#define DEBUGOUT7(S,A,B,C,D,E,F,G) do {} while (0)
#define STATIC static
#define FALSE 0
-#define false FALSE
#define TRUE 1
+#ifndef __bool_true_false_are_defined
+#define false FALSE
#define true TRUE
+#endif
#define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */
#define PCI_COMMAND_REGISTER PCIR_COMMAND
/* Mutex used in the shared code */
#define E1000_MUTEX struct mtx
#define E1000_MUTEX_INIT(mutex) mtx_init((mutex), #mutex, \
- MTX_NETWORK_LOCK, MTX_DEF)
+ MTX_NETWORK_LOCK, \
+ MTX_DEF | MTX_DUPOK)
#define E1000_MUTEX_DESTROY(mutex) mtx_destroy(mutex)
#define E1000_MUTEX_LOCK(mutex) mtx_lock(mutex)
#define E1000_MUTEX_TRYLOCK(mutex) mtx_trylock(mutex)
@@ -97,8 +101,10 @@ typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
#ifndef __rtems__
+#ifndef __bool_true_false_are_defined
typedef boolean_t bool;
#endif
+#endif /* __rtems__ */
#define __le16 u16
#define __le32 u32
diff --git a/freebsd/sys/dev/e1000/e1000_phy.c b/freebsd/sys/dev/e1000/e1000_phy.c
index c5365e51..73f03d74 100644
--- a/freebsd/sys/dev/e1000/e1000_phy.c
+++ b/freebsd/sys/dev/e1000/e1000_phy.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -40,32 +40,32 @@
#include <rtems/bsd/local/e1000_api.h>
#endif
-static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
+static s32 e1000_wait_autoneg(struct e1000_hw *hw);
static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
- u16 *data, bool read);
+ u16 *data, bool read, bool page_set);
static u32 e1000_get_phy_addr_for_hv_page(u32 page);
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
- u16 *data, bool read);
+ u16 *data, bool read);
/* Cable length tables */
-static const u16 e1000_m88_cable_length_table[] =
- { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
+static const u16 e1000_m88_cable_length_table[] = {
+ 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
#define M88E1000_CABLE_LENGTH_TABLE_SIZE \
- (sizeof(e1000_m88_cable_length_table) / \
- sizeof(e1000_m88_cable_length_table[0]))
-
-static const u16 e1000_igp_2_cable_length_table[] =
- { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
- 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
- 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
- 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
- 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
- 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
- 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
- 104, 109, 114, 118, 121, 124};
+ (sizeof(e1000_m88_cable_length_table) / \
+ sizeof(e1000_m88_cable_length_table[0]))
+
+static const u16 e1000_igp_2_cable_length_table[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
+ 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
+ 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
+ 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
+ 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
+ 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
+ 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
+ 124};
#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
- (sizeof(e1000_igp_2_cable_length_table) / \
- sizeof(e1000_igp_2_cable_length_table[0]))
+ (sizeof(e1000_igp_2_cable_length_table) / \
+ sizeof(e1000_igp_2_cable_length_table[0]))
/**
* e1000_init_phy_ops_generic - Initialize PHY function pointers
@@ -88,20 +88,35 @@ void e1000_init_phy_ops_generic(struct e1000_hw *hw)
phy->ops.get_cfg_done = e1000_null_ops_generic;
phy->ops.get_cable_length = e1000_null_ops_generic;
phy->ops.get_info = e1000_null_ops_generic;
+ phy->ops.set_page = e1000_null_set_page;
phy->ops.read_reg = e1000_null_read_reg;
phy->ops.read_reg_locked = e1000_null_read_reg;
+ phy->ops.read_reg_page = e1000_null_read_reg;
phy->ops.release = e1000_null_phy_generic;
phy->ops.reset = e1000_null_ops_generic;
phy->ops.set_d0_lplu_state = e1000_null_lplu_state;
phy->ops.set_d3_lplu_state = e1000_null_lplu_state;
phy->ops.write_reg = e1000_null_write_reg;
phy->ops.write_reg_locked = e1000_null_write_reg;
+ phy->ops.write_reg_page = e1000_null_write_reg;
phy->ops.power_up = e1000_null_phy_generic;
phy->ops.power_down = e1000_null_phy_generic;
+ phy->ops.read_i2c_byte = e1000_read_i2c_byte_null;
+ phy->ops.write_i2c_byte = e1000_write_i2c_byte_null;
phy->ops.cfg_on_link_up = e1000_null_ops_generic;
}
/**
+ * e1000_null_set_page - No-op function, return 0
+ * @hw: pointer to the HW structure
+ **/
+s32 e1000_null_set_page(struct e1000_hw *hw, u16 data)
+{
+ DEBUGFUNC("e1000_null_set_page");
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_null_read_reg - No-op function, return 0
* @hw: pointer to the HW structure
**/
@@ -142,6 +157,38 @@ s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data)
}
/**
+ * e1000_read_i2c_byte_null - No-op function, return 0
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @dev_addr: device address
+ * @data: data value read
+ *
+ **/
+s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data)
+{
+ DEBUGFUNC("e1000_read_i2c_byte_null");
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_write_i2c_byte_null - No-op function, return 0
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @dev_addr: device address
+ * @data: data value to write
+ *
+ **/
+s32 e1000_write_i2c_byte_null(struct e1000_hw *hw,
+ u8 byte_offset,
+ u8 dev_addr,
+ u8 data)
+{
+ DEBUGFUNC("e1000_write_i2c_byte_null");
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_check_reset_block_generic - Check if PHY reset is blocked
* @hw: pointer to the HW structure
*
@@ -177,30 +224,30 @@ s32 e1000_get_phy_id(struct e1000_hw *hw)
DEBUGFUNC("e1000_get_phy_id");
- if (!(phy->ops.read_reg))
- goto out;
+ if (!phy->ops.read_reg)
+ return E1000_SUCCESS;
while (retry_count < 2) {
ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
if (ret_val)
- goto out;
+ return ret_val;
phy->id = (u32)(phy_id << 16);
usec_delay(20);
ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
if (ret_val)
- goto out;
+ return ret_val;
phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
- goto out;
+ return E1000_SUCCESS;
retry_count++;
}
-out:
- return ret_val;
+
+ return E1000_SUCCESS;
}
/**
@@ -211,21 +258,18 @@ out:
**/
s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_phy_reset_dsp_generic");
- if (!(hw->phy.ops.write_reg))
- goto out;
+ if (!hw->phy.ops.write_reg)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
if (ret_val)
- goto out;
-
- ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
+ return ret_val;
-out:
- return ret_val;
+ return hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
}
/**
@@ -241,7 +285,6 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
{
struct e1000_phy_info *phy = &hw->phy;
u32 i, mdic = 0;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_phy_reg_mdic");
@@ -250,23 +293,17 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
return -E1000_ERR_PARAM;
}
- /*
- * Set up Op-code, Phy Address, and register offset in the MDI
+ /* Set up Op-code, Phy Address, and register offset in the MDI
* Control register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
*/
mdic = ((offset << E1000_MDIC_REG_SHIFT) |
- (phy->addr << E1000_MDIC_PHY_SHIFT) |
- (E1000_MDIC_OP_READ));
+ (phy->addr << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_READ));
E1000_WRITE_REG(hw, E1000_MDIC, mdic);
- /* Workaround for Si errata */
- if ((hw->phy.type == e1000_phy_82577) && (hw->revision_id <= 2))
- msec_delay(10);
-
- /*
- * Poll the ready bit to see if the MDI read completed
+ /* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
* the lower time out
*/
@@ -278,25 +315,27 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
}
if (!(mdic & E1000_MDIC_READY)) {
DEBUGOUT("MDI Read did not complete\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
if (mdic & E1000_MDIC_ERROR) {
DEBUGOUT("MDI Error\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
+ }
+ if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
+ DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n",
+ offset,
+ (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
+ return -E1000_ERR_PHY;
}
*data = (u16) mdic;
-
- /*
- * Allow some time after each MDIC transaction to avoid
+
+ /* Allow some time after each MDIC transaction to avoid
* reading duplicate data in the next MDIC transaction.
*/
if (hw->mac.type == e1000_pch2lan)
usec_delay(100);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -311,7 +350,6 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
{
struct e1000_phy_info *phy = &hw->phy;
u32 i, mdic = 0;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_phy_reg_mdic");
@@ -320,24 +358,18 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
return -E1000_ERR_PARAM;
}
- /*
- * Set up Op-code, Phy Address, and register offset in the MDI
+ /* Set up Op-code, Phy Address, and register offset in the MDI
* Control register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
*/
mdic = (((u32)data) |
- (offset << E1000_MDIC_REG_SHIFT) |
- (phy->addr << E1000_MDIC_PHY_SHIFT) |
- (E1000_MDIC_OP_WRITE));
+ (offset << E1000_MDIC_REG_SHIFT) |
+ (phy->addr << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_WRITE));
E1000_WRITE_REG(hw, E1000_MDIC, mdic);
- /* Workaround for Si errata */
- if ((hw->phy.type == e1000_phy_82577) && (hw->revision_id <= 2))
- msec_delay(10);
-
- /*
- * Poll the ready bit to see if the MDI read completed
+ /* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
* the lower time out
*/
@@ -349,24 +381,26 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
}
if (!(mdic & E1000_MDIC_READY)) {
DEBUGOUT("MDI Write did not complete\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
if (mdic & E1000_MDIC_ERROR) {
DEBUGOUT("MDI Error\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
+ }
+ if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
+ DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n",
+ offset,
+ (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
+ return -E1000_ERR_PHY;
}
- /*
- * Allow some time after each MDIC transaction to avoid
+ /* Allow some time after each MDIC transaction to avoid
* reading duplicate data in the next MDIC transaction.
*/
if (hw->mac.type == e1000_pch2lan)
usec_delay(100);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -385,14 +419,13 @@ s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data)
DEBUGFUNC("e1000_read_phy_reg_i2c");
- /*
- * Set up Op-code, Phy Address, and register address in the I2CCMD
+ /* Set up Op-code, Phy Address, and register address in the I2CCMD
* register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
*/
i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
- (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
- (E1000_I2CCMD_OPCODE_READ));
+ (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
+ (E1000_I2CCMD_OPCODE_READ));
E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
@@ -434,18 +467,24 @@ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
DEBUGFUNC("e1000_write_phy_reg_i2c");
+ /* Prevent overwritting SFP I2C EEPROM which is at A0 address.*/
+ if ((hw->phy.addr == 0) || (hw->phy.addr > 7)) {
+ DEBUGOUT1("PHY I2C Address %d is out of range.\n",
+ hw->phy.addr);
+ return -E1000_ERR_CONFIG;
+ }
+
/* Swap the data bytes for the I2C interface */
phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
- /*
- * Set up Op-code, Phy Address, and register address in the I2CCMD
+ /* Set up Op-code, Phy Address, and register address in the I2CCMD
* register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
*/
i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
- (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
- E1000_I2CCMD_OPCODE_WRITE |
- phy_data_swapped);
+ (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
+ E1000_I2CCMD_OPCODE_WRITE |
+ phy_data_swapped);
E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
@@ -469,6 +508,134 @@ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
}
/**
+ * e1000_read_sfp_data_byte - Reads SFP module data.
+ * @hw: pointer to the HW structure
+ * @offset: byte location offset to be read
+ * @data: read data buffer pointer
+ *
+ * Reads one byte from SFP module data stored
+ * in SFP resided EEPROM memory or SFP diagnostic area.
+ * Function should be called with
+ * E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
+ * E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
+ * access
+ **/
+s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data)
+{
+ u32 i = 0;
+ u32 i2ccmd = 0;
+ u32 data_local = 0;
+
+ DEBUGFUNC("e1000_read_sfp_data_byte");
+
+ if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
+ DEBUGOUT("I2CCMD command address exceeds upper limit\n");
+ return -E1000_ERR_PHY;
+ }
+
+ /* Set up Op-code, EEPROM Address,in the I2CCMD
+ * register. The MAC will take care of interfacing with the
+ * EEPROM to retrieve the desired data.
+ */
+ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+ E1000_I2CCMD_OPCODE_READ);
+
+ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
+
+ /* Poll the ready bit to see if the I2C read completed */
+ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+ usec_delay(50);
+ data_local = E1000_READ_REG(hw, E1000_I2CCMD);
+ if (data_local & E1000_I2CCMD_READY)
+ break;
+ }
+ if (!(data_local & E1000_I2CCMD_READY)) {
+ DEBUGOUT("I2CCMD Read did not complete\n");
+ return -E1000_ERR_PHY;
+ }
+ if (data_local & E1000_I2CCMD_ERROR) {
+ DEBUGOUT("I2CCMD Error bit set\n");
+ return -E1000_ERR_PHY;
+ }
+ *data = (u8) data_local & 0xFF;
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_write_sfp_data_byte - Writes SFP module data.
+ * @hw: pointer to the HW structure
+ * @offset: byte location offset to write to
+ * @data: data to write
+ *
+ * Writes one byte to SFP module data stored
+ * in SFP resided EEPROM memory or SFP diagnostic area.
+ * Function should be called with
+ * E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
+ * E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
+ * access
+ **/
+s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
+{
+ u32 i = 0;
+ u32 i2ccmd = 0;
+ u32 data_local = 0;
+
+ DEBUGFUNC("e1000_write_sfp_data_byte");
+
+ if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
+ DEBUGOUT("I2CCMD command address exceeds upper limit\n");
+ return -E1000_ERR_PHY;
+ }
+ /* The programming interface is 16 bits wide
+ * so we need to read the whole word first
+ * then update appropriate byte lane and write
+ * the updated word back.
+ */
+ /* Set up Op-code, EEPROM Address,in the I2CCMD
+ * register. The MAC will take care of interfacing
+ * with an EEPROM to write the data given.
+ */
+ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+ E1000_I2CCMD_OPCODE_READ);
+ /* Set a command to read single word */
+ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
+ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+ usec_delay(50);
+ /* Poll the ready bit to see if lastly
+ * launched I2C operation completed
+ */
+ i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
+ if (i2ccmd & E1000_I2CCMD_READY) {
+ /* Check if this is READ or WRITE phase */
+ if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) ==
+ E1000_I2CCMD_OPCODE_READ) {
+ /* Write the selected byte
+ * lane and update whole word
+ */
+ data_local = i2ccmd & 0xFF00;
+ data_local |= data;
+ i2ccmd = ((offset <<
+ E1000_I2CCMD_REG_ADDR_SHIFT) |
+ E1000_I2CCMD_OPCODE_WRITE | data_local);
+ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
+ } else {
+ break;
+ }
+ }
+ }
+ if (!(i2ccmd & E1000_I2CCMD_READY)) {
+ DEBUGOUT("I2CCMD Write did not complete\n");
+ return -E1000_ERR_PHY;
+ }
+ if (i2ccmd & E1000_I2CCMD_ERROR) {
+ DEBUGOUT("I2CCMD Error bit set\n");
+ return -E1000_ERR_PHY;
+ }
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_read_phy_reg_m88 - Read m88 PHY register
* @hw: pointer to the HW structure
* @offset: register offset to be read
@@ -480,23 +647,22 @@ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
**/
s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_read_phy_reg_m88");
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
+ data);
hw->phy.ops.release(hw);
-out:
return ret_val;
}
@@ -511,27 +677,46 @@ out:
**/
s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_write_phy_reg_m88");
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
+ data);
hw->phy.ops.release(hw);
-out:
return ret_val;
}
/**
+ * e1000_set_page_igp - Set page as on IGP-like PHY(s)
+ * @hw: pointer to the HW structure
+ * @page: page to set (shifted left when necessary)
+ *
+ * Sets PHY page required for PHY register access. Assumes semaphore is
+ * already acquired. Note, this function sets phy.addr to 1 so the caller
+ * must set it appropriately (if necessary) after this function returns.
+ **/
+s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
+{
+ DEBUGFUNC("e1000_set_page_igp");
+
+ DEBUGOUT1("Setting page 0x%x\n", page);
+
+ hw->phy.addr = 1;
+
+ return e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
+}
+
+/**
* __e1000_read_phy_reg_igp - Read igp PHY register
* @hw: pointer to the HW structure
* @offset: register offset to be read
@@ -543,36 +728,32 @@ out:
* semaphores before exiting.
**/
static s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
- bool locked)
+ bool locked)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("__e1000_read_phy_reg_igp");
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ if (offset > MAX_PHY_MULTI_PAGE_REG)
ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (u16)offset);
- if (ret_val)
- goto release;
- }
-
- ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-
-release:
+ IGP01E1000_PHY_PAGE_SELECT,
+ (u16)offset);
+ if (!ret_val)
+ ret_val = e1000_read_phy_reg_mdic(hw,
+ MAX_PHY_REG_ADDRESS & offset,
+ data);
if (!locked)
hw->phy.ops.release(hw);
-out:
+
return ret_val;
}
@@ -616,37 +797,32 @@ s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
* at the offset. Release any acquired semaphores before exiting.
**/
static s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
- bool locked)
+ bool locked)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_phy_reg_igp");
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ if (offset > MAX_PHY_MULTI_PAGE_REG)
ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (u16)offset);
- if (ret_val)
- goto release;
- }
-
- ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-
-release:
+ IGP01E1000_PHY_PAGE_SELECT,
+ (u16)offset);
+ if (!ret_val)
+ ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS &
+ offset,
+ data);
if (!locked)
hw->phy.ops.release(hw);
-out:
return ret_val;
}
@@ -690,25 +866,27 @@ s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
* Release any acquired semaphores before exiting.
**/
static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
- bool locked)
+ bool locked)
{
u32 kmrnctrlsta;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("__e1000_read_kmrn_reg");
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ s32 ret_val = E1000_SUCCESS;
+
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
- E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
+ E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
+ E1000_WRITE_FLUSH(hw);
usec_delay(2);
@@ -718,8 +896,7 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
if (!locked)
hw->phy.ops.release(hw);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -764,33 +941,34 @@ s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
* before exiting.
**/
static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
- bool locked)
+ bool locked)
{
u32 kmrnctrlsta;
- s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_kmrn_reg_generic");
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ s32 ret_val = E1000_SUCCESS;
+
+ if (!hw->phy.ops.acquire)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
- E1000_KMRNCTRLSTA_OFFSET) | data;
+ E1000_KMRNCTRLSTA_OFFSET) | data;
E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
+ E1000_WRITE_FLUSH(hw);
usec_delay(2);
if (!locked)
hw->phy.ops.release(hw);
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -822,6 +1000,46 @@ s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
}
/**
+ * e1000_set_master_slave_mode - Setup PHY for Master/slave mode
+ * @hw: pointer to the HW structure
+ *
+ * Sets up Master/slave mode
+ **/
+static s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ /* Resolve Master/Slave mode */
+ ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* load defaults for future use */
+ hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ e1000_ms_force_master :
+ e1000_ms_force_slave) : e1000_ms_auto;
+
+ switch (hw->phy.ms_type) {
+ case e1000_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ /* fall-through */
+ default:
+ break;
+ }
+
+ return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
+}
+
+/**
* e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
* @hw: pointer to the HW structure
*
@@ -834,33 +1052,58 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
DEBUGFUNC("e1000_copper_link_setup_82577");
- if (hw->phy.reset_disable) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
-
if (hw->phy.type == e1000_phy_82580) {
ret_val = hw->phy.ops.reset(hw);
if (ret_val) {
DEBUGOUT("Error resetting the PHY.\n");
- goto out;
+ return ret_val;
}
}
- /* Enable CRS on TX. This must be set for half-duplex operation. */
+ /* Enable CRS on Tx. This must be set for half-duplex operation.
+ * Not required on some PHYs.
+ */
ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
+ if ((hw->phy.type != e1000_phy_82579) &&
+ (hw->phy.type != e1000_phy_i217))
+ phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
/* Enable downshift */
phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
ret_val = hw->phy.ops.write_reg(hw, I82577_CFG_REG, phy_data);
+ if (ret_val)
+ return ret_val;
-out:
- return ret_val;
+ /* Set MDI/MDIX mode */
+ ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
+ if (ret_val)
+ return ret_val;
+ phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
+ /* Options:
+ * 0 - Auto (default)
+ * 1 - MDI mode
+ * 2 - MDI-X mode
+ */
+ switch (hw->phy.mdix) {
+ case 1:
+ break;
+ case 2:
+ phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX;
+ break;
+ case 0:
+ default:
+ phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX;
+ break;
+ }
+ ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ return e1000_set_master_slave_mode(hw);
}
/**
@@ -878,23 +1121,17 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
DEBUGFUNC("e1000_copper_link_setup_m88");
- if (phy->reset_disable) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
/* Enable CRS on Tx. This must be set for half-duplex operation. */
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
/* For BM PHY this bit is downshift enable */
- if (phy->type == e1000_phy_bm)
- phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX;
+ if (phy->type != e1000_phy_bm)
+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
- /*
- * Options:
+ /* Options:
* MDI/MDI-X = 0 (default)
* 0 - Auto for all speeds
* 1 - MDI mode
@@ -919,36 +1156,50 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
break;
}
- /*
- * Options:
+ /* Options:
* disable_polarity_correction = 0 (default)
* Automatic Correction for Reversed Cable Polarity
* 0 - Disabled
* 1 - Enabled
*/
phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
- if (phy->disable_polarity_correction == 1)
+ if (phy->disable_polarity_correction)
phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
/* Enable downshift on BM (disabled by default) */
- if (phy->type == e1000_phy_bm)
+ if (phy->type == e1000_phy_bm) {
+ /* For 82574/82583, first disable then enable downshift */
+ if (phy->id == BME1000_E_PHY_ID_R2) {
+ phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT;
+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ /* Commit the changes. */
+ ret_val = phy->ops.commit(hw);
+ if (ret_val) {
+ DEBUGOUT("Error committing the PHY changes\n");
+ return ret_val;
+ }
+ }
+
phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
+ }
ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
if ((phy->type == e1000_phy_m88) &&
(phy->revision < E1000_REVISION_4) &&
(phy->id != BME1000_E_PHY_ID_R2)) {
- /*
- * Force TX_CLK in the Extended PHY Specific Control Register
+ /* Force TX_CLK in the Extended PHY Specific Control Register
* to 25MHz clock.
*/
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- &phy_data);
+ &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data |= M88E1000_EPSCR_TX_CLK_25;
@@ -960,52 +1211,135 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
} else {
/* Configure Master and Slave downshift values */
phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
- M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
- M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
}
ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- phy_data);
+ phy_data);
if (ret_val)
- goto out;
+ return ret_val;
}
if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
/* Set PHY page 0, register 29 to 0x0003 */
ret_val = phy->ops.write_reg(hw, 29, 0x0003);
if (ret_val)
- goto out;
+ return ret_val;
/* Set PHY page 0, register 30 to 0x0000 */
ret_val = phy->ops.write_reg(hw, 30, 0x0000);
if (ret_val)
- goto out;
+ return ret_val;
}
/* Commit the changes. */
ret_val = phy->ops.commit(hw);
if (ret_val) {
DEBUGOUT("Error committing the PHY changes\n");
- goto out;
+ return ret_val;
}
if (phy->type == e1000_phy_82578) {
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- &phy_data);
+ &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/* 82578 PHY - set the downshift count to 1x. */
phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- phy_data);
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
+
+ if (phy->type == e1000_phy_i210) {
+ ret_val = e1000_set_master_slave_mode(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
+ * @hw: pointer to the HW structure
+ *
+ * Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
+ * Also enables and sets the downshift parameters.
+ **/
+s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_setup_m88_gen2");
+
+
+ /* Enable CRS on Tx. This must be set for half-duplex operation. */
+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+ * 1 - MDI mode
+ * 2 - MDI-X mode
+ * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+ */
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+ switch (phy->mdix) {
+ case 1:
+ phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+ break;
+ case 2:
+ phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+ break;
+ case 3:
+ /* M88E1112 does not support this mode) */
+ if (phy->id != M88E1112_E_PHY_ID) {
+ phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+ break;
+ }
+ case 0:
+ default:
+ phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+ break;
+ }
+
+ /* Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+ * 0 - Disabled
+ * 1 - Enabled
+ */
+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+ if (phy->disable_polarity_correction)
+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+
+ /* Enable downshift and setting it to X6 */
+ phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
+ phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
+ phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
+
+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Commit the changes. */
+ ret_val = phy->ops.commit(hw);
+ if (ret_val) {
+ DEBUGOUT("Error committing the PHY changes\n");
+ return ret_val;
+ }
+
+ return E1000_SUCCESS;
}
/**
@@ -1023,25 +1357,19 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
DEBUGFUNC("e1000_copper_link_setup_igp");
- if (phy->reset_disable) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
ret_val = hw->phy.ops.reset(hw);
if (ret_val) {
DEBUGOUT("Error resetting the PHY.\n");
- goto out;
+ return ret_val;
}
- /*
- * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
+ /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid
* timeout issues when LFS is enabled.
*/
msec_delay(100);
- /*
- * The NVM settings will configure LPLU in D3 for
+ /* The NVM settings will configure LPLU in D3 for
* non-IGP1 PHYs.
*/
if (phy->type == e1000_phy_igp) {
@@ -1049,7 +1377,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
ret_val = hw->phy.ops.set_d3_lplu_state(hw, FALSE);
if (ret_val) {
DEBUGOUT("Error Disabling LPLU D3\n");
- goto out;
+ return ret_val;
}
}
@@ -1058,13 +1386,13 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
ret_val = hw->phy.ops.set_d0_lplu_state(hw, FALSE);
if (ret_val) {
DEBUGOUT("Error Disabling LPLU D0\n");
- goto out;
+ return ret_val;
}
}
/* Configure mdi-mdix settings */
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCR_AUTO_MDIX;
@@ -1082,141 +1410,43 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
}
ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);
if (ret_val)
- goto out;
+ return ret_val;
/* set auto-master slave resolution settings */
if (hw->mac.autoneg) {
- /*
- * when autonegotiation advertisement is only 1000Mbps then we
+ /* when autonegotiation advertisement is only 1000Mbps then we
* should disable SmartSpeed and enable Auto MasterSlave
* resolution as hardware default.
*/
if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {
/* Disable SmartSpeed */
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
/* Set auto Master/Slave resolution process */
ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~CR_1000T_MS_ENABLE;
ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
if (ret_val)
- goto out;
- }
-
- ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
- if (ret_val)
- goto out;
-
- /* load defaults for future use */
- phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ?
- ((data & CR_1000T_MS_VALUE) ?
- e1000_ms_force_master :
- e1000_ms_force_slave) :
- e1000_ms_auto;
-
- switch (phy->ms_type) {
- case e1000_ms_force_master:
- data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
- break;
- case e1000_ms_force_slave:
- data |= CR_1000T_MS_ENABLE;
- data &= ~(CR_1000T_MS_VALUE);
- break;
- case e1000_ms_auto:
- data &= ~CR_1000T_MS_ENABLE;
- default:
- break;
+ return ret_val;
}
- ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
- if (ret_val)
- goto out;
- }
-
-out:
- return ret_val;
-}
-
-/**
- * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
- * @hw: pointer to the HW structure
- *
- * Performs initial bounds checking on autoneg advertisement parameter, then
- * configure to advertise the full capability. Setup the PHY to autoneg
- * and restart the negotiation process between the link partner. If
- * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
- **/
-s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
-{
- struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val;
- u16 phy_ctrl;
-
- DEBUGFUNC("e1000_copper_link_autoneg");
-
- /*
- * Perform some bounds checking on the autoneg advertisement
- * parameter.
- */
- phy->autoneg_advertised &= phy->autoneg_mask;
-
- /*
- * If autoneg_advertised is zero, we assume it was not defaulted
- * by the calling code so we set to advertise full capability.
- */
- if (phy->autoneg_advertised == 0)
- phy->autoneg_advertised = phy->autoneg_mask;
-
- DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
- ret_val = e1000_phy_setup_autoneg(hw);
- if (ret_val) {
- DEBUGOUT("Error Setting up Auto-Negotiation\n");
- goto out;
- }
- DEBUGOUT("Restarting Auto-Neg\n");
- /*
- * Restart auto-negotiation by setting the Auto Neg Enable bit and
- * the Auto Neg Restart bit in the PHY control register.
- */
- ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
- if (ret_val)
- goto out;
-
- phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
- ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
- if (ret_val)
- goto out;
-
- /*
- * Does the user want to wait for Auto-Neg to complete here, or
- * check at a later time (for example, callback routine).
- */
- if (phy->autoneg_wait_to_complete) {
- ret_val = hw->mac.ops.wait_autoneg(hw);
- if (ret_val) {
- DEBUGOUT("Error while waiting for "
- "autoneg to complete\n");
- goto out;
- }
+ ret_val = e1000_set_master_slave_mode(hw);
}
- hw->mac.get_link_status = TRUE;
-
-out:
return ret_val;
}
@@ -1243,33 +1473,31 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
/* Read the MII Auto-Neg Advertisement Register (Address 4). */
ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
/* Read the MII 1000Base-T Control Register (Address 9). */
ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
- &mii_1000t_ctrl_reg);
+ &mii_1000t_ctrl_reg);
if (ret_val)
- goto out;
+ return ret_val;
}
- /*
- * Need to parse both autoneg_advertised and fc and set up
+ /* Need to parse both autoneg_advertised and fc and set up
* the appropriate PHY registers. First we will parse for
* autoneg_advertised software override. Since we can advertise
* a plethora of combinations, we need to check each bit
* individually.
*/
- /*
- * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ /* First we clear all the 10/100 mb speed bits in the Auto-Neg
* Advertisement Register (Address 4) and the 1000 mb speed bits in
* the 1000Base-T Control Register (Address 9).
*/
mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
- NWAY_AR_100TX_HD_CAPS |
- NWAY_AR_10T_FD_CAPS |
- NWAY_AR_10T_HD_CAPS);
+ NWAY_AR_100TX_HD_CAPS |
+ NWAY_AR_10T_FD_CAPS |
+ NWAY_AR_10T_HD_CAPS);
mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised);
@@ -1308,8 +1536,7 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
}
- /*
- * Check for a software override of the flow control settings, and
+ /* Check for a software override of the flow control settings, and
* setup the PHY advertisement registers accordingly. If
* auto-negotiation is enabled, then software will have to set the
* "PAUSE" bits to the correct value in the Auto-Negotiation
@@ -1328,15 +1555,13 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
*/
switch (hw->fc.current_mode) {
case e1000_fc_none:
- /*
- * Flow control (Rx & Tx) is completely disabled by a
+ /* Flow control (Rx & Tx) is completely disabled by a
* software over-ride.
*/
mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
break;
case e1000_fc_rx_pause:
- /*
- * Rx Flow control is enabled, and Tx Flow control is
+ /* Rx Flow control is enabled, and Tx Flow control is
* disabled, by a software over-ride.
*
* Since there really isn't a way to advertise that we are
@@ -1348,41 +1573,97 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
break;
case e1000_fc_tx_pause:
- /*
- * Tx Flow control is enabled, and Rx Flow control is
+ /* Tx Flow control is enabled, and Rx Flow control is
* disabled, by a software over-ride.
*/
mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
break;
case e1000_fc_full:
- /*
- * Flow control (both Rx and Tx) is enabled by a software
+ /* Flow control (both Rx and Tx) is enabled by a software
* over-ride.
*/
mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
if (ret_val)
- goto out;
+ return ret_val;
DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
- if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
- ret_val = phy->ops.write_reg(hw,
- PHY_1000T_CTRL,
- mii_1000t_ctrl_reg);
- if (ret_val)
- goto out;
+ if (phy->autoneg_mask & ADVERTISE_1000_FULL)
+ ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
+ mii_1000t_ctrl_reg);
+
+ return ret_val;
+}
+
+/**
+ * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
+ * @hw: pointer to the HW structure
+ *
+ * Performs initial bounds checking on autoneg advertisement parameter, then
+ * configure to advertise the full capability. Setup the PHY to autoneg
+ * and restart the negotiation process between the link partner. If
+ * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
+ **/
+s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_ctrl;
+
+ DEBUGFUNC("e1000_copper_link_autoneg");
+
+ /* Perform some bounds checking on the autoneg advertisement
+ * parameter.
+ */
+ phy->autoneg_advertised &= phy->autoneg_mask;
+
+ /* If autoneg_advertised is zero, we assume it was not defaulted
+ * by the calling code so we set to advertise full capability.
+ */
+ if (!phy->autoneg_advertised)
+ phy->autoneg_advertised = phy->autoneg_mask;
+
+ DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+ ret_val = e1000_phy_setup_autoneg(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Setting up Auto-Negotiation\n");
+ return ret_val;
}
+ DEBUGOUT("Restarting Auto-Neg\n");
+
+ /* Restart auto-negotiation by setting the Auto Neg Enable bit and
+ * the Auto Neg Restart bit in the PHY control register.
+ */
+ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
+ if (ret_val)
+ return ret_val;
+
+ phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+ ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
+ if (ret_val)
+ return ret_val;
+
+ /* Does the user want to wait for Auto-Neg to complete here, or
+ * check at a later time (for example, callback routine).
+ */
+ if (phy->autoneg_wait_to_complete) {
+ ret_val = e1000_wait_autoneg(hw);
+ if (ret_val) {
+ DEBUGOUT("Error while waiting for autoneg to complete\n");
+ return ret_val;
+ }
+ }
+
+ hw->mac.get_link_status = TRUE;
-out:
return ret_val;
}
@@ -1403,46 +1684,40 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_copper_link_generic");
if (hw->mac.autoneg) {
- /*
- * Setup autoneg and flow control advertisement and perform
+ /* Setup autoneg and flow control advertisement and perform
* autonegotiation.
*/
ret_val = e1000_copper_link_autoneg(hw);
if (ret_val)
- goto out;
+ return ret_val;
} else {
- /*
- * PHY will be set to 10H, 10F, 100H or 100F
+ /* PHY will be set to 10H, 10F, 100H or 100F
* depending on user settings.
*/
DEBUGOUT("Forcing Speed and Duplex\n");
ret_val = hw->phy.ops.force_speed_duplex(hw);
if (ret_val) {
DEBUGOUT("Error Forcing Speed and Duplex\n");
- goto out;
+ return ret_val;
}
}
- /*
- * Check link status. Wait up to 100 microseconds for link to become
+ /* Check link status. Wait up to 100 microseconds for link to become
* valid.
*/
- ret_val = e1000_phy_has_link_generic(hw,
- COPPER_LINK_UP_LIMIT,
- 10,
- &link);
+ ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
+ &link);
if (ret_val)
- goto out;
+ return ret_val;
if (link) {
DEBUGOUT("Valid link established!!!\n");
- e1000_config_collision_dist_generic(hw);
+ hw->mac.ops.config_collision_dist(hw);
ret_val = e1000_config_fc_after_link_up_generic(hw);
} else {
DEBUGOUT("Unable to establish link!!!\n");
}
-out:
return ret_val;
}
@@ -1465,28 +1740,27 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &phy_data);
ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * Clear Auto-Crossover to force MDI manually. IGP requires MDI
+ /* Clear Auto-Crossover to force MDI manually. IGP requires MDI
* forced whenever speed and duplex are forced.
*/
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
DEBUGOUT1("IGP PSCR: %X\n", phy_data);
@@ -1495,26 +1769,19 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
if (phy->autoneg_wait_to_complete) {
DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n");
- ret_val = e1000_phy_has_link_generic(hw,
- PHY_FORCE_LIMIT,
- 100000,
- &link);
+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+ 100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
DEBUGOUT("Link taking longer than expected.\n");
/* Try once more */
- ret_val = e1000_phy_has_link_generic(hw,
- PHY_FORCE_LIMIT,
- 100000,
- &link);
- if (ret_val)
- goto out;
+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+ 100000, &link);
}
-out:
return ret_val;
}
@@ -1537,99 +1804,120 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
DEBUGFUNC("e1000_phy_force_speed_duplex_m88");
- /*
- * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
- * forced whenever speed and duplex are forced.
- */
- ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- goto out;
+ /* I210 and I211 devices support Auto-Crossover in forced operation. */
+ if (phy->type != e1000_phy_i210) {
+ /* Clear Auto-Crossover to force MDI manually. M88E1000
+ * requires MDI forced whenever speed and duplex are forced.
+ */
+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
- phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
- ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
- if (ret_val)
- goto out;
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &phy_data);
ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
/* Reset the phy to commit changes. */
ret_val = hw->phy.ops.commit(hw);
if (ret_val)
- goto out;
+ return ret_val;
if (phy->autoneg_wait_to_complete) {
DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n");
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
- 100000, &link);
+ 100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
- if (hw->phy.type != e1000_phy_m88) {
+ bool reset_dsp = TRUE;
+
+ switch (hw->phy.id) {
+ case I347AT4_E_PHY_ID:
+ case M88E1340M_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
+ case I210_I_PHY_ID:
+ reset_dsp = FALSE;
+ break;
+ default:
+ if (hw->phy.type != e1000_phy_m88)
+ reset_dsp = FALSE;
+ break;
+ }
+
+ if (!reset_dsp) {
DEBUGOUT("Link taking longer than expected.\n");
} else {
- /*
- * We didn't get link.
+ /* We didn't get link.
* Reset the DSP and cross our fingers.
*/
ret_val = phy->ops.write_reg(hw,
M88E1000_PHY_PAGE_SELECT,
0x001d);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_phy_reset_dsp_generic(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
}
/* Try once more */
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
- 100000, &link);
+ 100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
}
if (hw->phy.type != e1000_phy_m88)
- goto out;
+ return E1000_SUCCESS;
+ if (hw->phy.id == I347AT4_E_PHY_ID ||
+ hw->phy.id == M88E1340M_E_PHY_ID ||
+ hw->phy.id == M88E1112_E_PHY_ID)
+ return E1000_SUCCESS;
+ if (hw->phy.id == I210_I_PHY_ID)
+ return E1000_SUCCESS;
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * Resetting the phy means we need to re-force TX_CLK in the
+ /* Resetting the phy means we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25MHz clock from
* the reset value of 2.5MHz.
*/
phy_data |= M88E1000_EPSCR_TX_CLK_25;
ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * In addition, we must re-enable CRS on Tx for both half and full
+ /* In addition, we must re-enable CRS on Tx for both half and full
* duplex.
*/
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-out:
return ret_val;
}
@@ -1652,25 +1940,25 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &data);
ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data);
if (ret_val)
- goto out;
+ return ret_val;
/* Disable MDI-X support for 10/100 */
ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IFE_PMC_AUTO_MDIX;
data &= ~IFE_PMC_FORCE_MDIX;
ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data);
if (ret_val)
- goto out;
+ return ret_val;
DEBUGOUT1("IFE PMC: %X\n", data);
@@ -1679,27 +1967,22 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
if (phy->autoneg_wait_to_complete) {
DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n");
- ret_val = e1000_phy_has_link_generic(hw,
- PHY_FORCE_LIMIT,
- 100000,
- &link);
+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+ 100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
DEBUGOUT("Link taking longer than expected.\n");
/* Try once more */
- ret_val = e1000_phy_has_link_generic(hw,
- PHY_FORCE_LIMIT,
- 100000,
- &link);
+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+ 100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -1750,16 +2033,15 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) {
ctrl |= E1000_CTRL_SPD_100;
*phy_ctrl |= MII_CR_SPEED_100;
- *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
+ *phy_ctrl &= ~MII_CR_SPEED_1000;
DEBUGOUT("Forcing 100mb\n");
} else {
ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
- *phy_ctrl |= MII_CR_SPEED_10;
*phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
DEBUGOUT("Forcing 10mb\n");
}
- e1000_config_collision_dist_generic(hw);
+ hw->mac.ops.config_collision_dist(hw);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
}
@@ -1781,78 +2063,76 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 data;
DEBUGFUNC("e1000_set_d3_lplu_state_generic");
- if (!(hw->phy.ops.read_reg))
- goto out;
+ if (!hw->phy.ops.read_reg)
+ return E1000_SUCCESS;
ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
if (ret_val)
- goto out;
+ return ret_val;
if (!active) {
data &= ~IGP02E1000_PM_D3_LPLU;
ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- data);
+ data);
if (ret_val)
- goto out;
- /*
- * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ return ret_val;
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most
* important. During driver activity we should enable
* SmartSpeed, so performance is maintained.
*/
if (phy->smart_speed == e1000_smart_speed_on) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data |= IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
} else if (phy->smart_speed == e1000_smart_speed_off) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
- goto out;
+ return ret_val;
}
} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
- (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
- (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
data |= IGP02E1000_PM_D3_LPLU;
ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- data);
+ data);
if (ret_val)
- goto out;
+ return ret_val;
/* When LPLU is enabled, we should disable SmartSpeed */
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- data);
+ data);
}
-out:
return ret_val;
}
@@ -1873,32 +2153,31 @@ s32 e1000_check_downshift_generic(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_downshift_generic");
switch (phy->type) {
+ case e1000_phy_i210:
case e1000_phy_m88:
case e1000_phy_gg82563:
case e1000_phy_bm:
case e1000_phy_82578:
- offset = M88E1000_PHY_SPEC_STATUS;
- mask = M88E1000_PSSR_DOWNSHIFT;
+ offset = M88E1000_PHY_SPEC_STATUS;
+ mask = M88E1000_PSSR_DOWNSHIFT;
break;
case e1000_phy_igp:
case e1000_phy_igp_2:
case e1000_phy_igp_3:
- offset = IGP01E1000_PHY_LINK_HEALTH;
- mask = IGP01E1000_PLHR_SS_DOWNGRADE;
+ offset = IGP01E1000_PHY_LINK_HEALTH;
+ mask = IGP01E1000_PLHR_SS_DOWNGRADE;
break;
default:
/* speed downshift not supported */
phy->speed_downgraded = FALSE;
- ret_val = E1000_SUCCESS;
- goto out;
+ return E1000_SUCCESS;
}
ret_val = phy->ops.read_reg(hw, offset, &phy_data);
if (!ret_val)
- phy->speed_downgraded = (phy_data & mask) ? TRUE : FALSE;
+ phy->speed_downgraded = !!(phy_data & mask);
-out:
return ret_val;
}
@@ -1922,8 +2201,8 @@ s32 e1000_check_polarity_m88(struct e1000_hw *hw)
if (!ret_val)
phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY)
- ? e1000_rev_polarity_reversed
- : e1000_rev_polarity_normal;
+ ? e1000_rev_polarity_reversed
+ : e1000_rev_polarity_normal;
return ret_val;
}
@@ -1945,35 +2224,32 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_polarity_igp");
- /*
- * Polarity is determined based on the speed of
+ /* Polarity is determined based on the speed of
* our connection.
*/
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS) {
- offset = IGP01E1000_PHY_PCS_INIT_REG;
- mask = IGP01E1000_PHY_POLARITY_MASK;
+ offset = IGP01E1000_PHY_PCS_INIT_REG;
+ mask = IGP01E1000_PHY_POLARITY_MASK;
} else {
- /*
- * This really only applies to 10Mbps since
+ /* This really only applies to 10Mbps since
* there is no polarity for 100Mbps (always 0).
*/
- offset = IGP01E1000_PHY_PORT_STATUS;
- mask = IGP01E1000_PSSR_POLARITY_REVERSED;
+ offset = IGP01E1000_PHY_PORT_STATUS;
+ mask = IGP01E1000_PSSR_POLARITY_REVERSED;
}
ret_val = phy->ops.read_reg(hw, offset, &data);
if (!ret_val)
phy->cable_polarity = (data & mask)
- ? e1000_rev_polarity_reversed
- : e1000_rev_polarity_normal;
+ ? e1000_rev_polarity_reversed
+ : e1000_rev_polarity_normal;
-out:
return ret_val;
}
@@ -1991,8 +2267,7 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_polarity_ife");
- /*
- * Polarity is determined based on the reversal feature being enabled.
+ /* Polarity is determined based on the reversal feature being enabled.
*/
if (phy->polarity_correction) {
offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
@@ -2006,27 +2281,27 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw)
if (!ret_val)
phy->cable_polarity = (phy_data & mask)
- ? e1000_rev_polarity_reversed
- : e1000_rev_polarity_normal;
+ ? e1000_rev_polarity_reversed
+ : e1000_rev_polarity_normal;
return ret_val;
}
/**
- * e1000_wait_autoneg_generic - Wait for auto-neg completion
+ * e1000_wait_autoneg - Wait for auto-neg completion
* @hw: pointer to the HW structure
*
* Waits for auto-negotiation to complete or for the auto-negotiation time
* limit to expire, which ever happens first.
**/
-s32 e1000_wait_autoneg_generic(struct e1000_hw *hw)
+static s32 e1000_wait_autoneg(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u16 i, phy_status;
- DEBUGFUNC("e1000_wait_autoneg_generic");
+ DEBUGFUNC("e1000_wait_autoneg");
- if (!(hw->phy.ops.read_reg))
+ if (!hw->phy.ops.read_reg)
return E1000_SUCCESS;
/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
@@ -2042,8 +2317,7 @@ s32 e1000_wait_autoneg_generic(struct e1000_hw *hw)
msec_delay(100);
}
- /*
- * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
+ /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
* has completed.
*/
return ret_val;
@@ -2059,26 +2333,24 @@ s32 e1000_wait_autoneg_generic(struct e1000_hw *hw)
* Polls the PHY status register for link, 'iterations' number of times.
**/
s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
- u32 usec_interval, bool *success)
+ u32 usec_interval, bool *success)
{
s32 ret_val = E1000_SUCCESS;
u16 i, phy_status;
DEBUGFUNC("e1000_phy_has_link_generic");
- if (!(hw->phy.ops.read_reg))
+ if (!hw->phy.ops.read_reg)
return E1000_SUCCESS;
for (i = 0; i < iterations; i++) {
- /*
- * Some PHYs require the PHY_STATUS register to be read
+ /* Some PHYs require the PHY_STATUS register to be read
* twice due to the link bit being sticky. No harm doing
* it across the board.
*/
ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
if (ret_val)
- /*
- * If the first read fails, another entity may have
+ /* If the first read fails, another entity may have
* ownership of the resources, wait and try again to
* see if they have relinquished the resources yet.
*/
@@ -2094,7 +2366,7 @@ s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
usec_delay(usec_interval);
}
- *success = (i < iterations) ? TRUE : FALSE;
+ *success = (i < iterations);
return ret_val;
}
@@ -2124,21 +2396,129 @@ s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
- M88E1000_PSSR_CABLE_LENGTH_SHIFT;
- if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
- ret_val = -E1000_ERR_PHY;
- goto out;
- }
+ M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+
+ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
+ return -E1000_ERR_PHY;
phy->min_cable_length = e1000_m88_cable_length_table[index];
phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-out:
+ return E1000_SUCCESS;
+}
+
+s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_data, phy_data2, is_cm;
+ u16 index, default_page;
+
+ DEBUGFUNC("e1000_get_cable_length_m88_gen2");
+
+ switch (hw->phy.id) {
+ case I210_I_PHY_ID:
+ /* Get cable length from PHY Cable Diagnostics Control Reg */
+ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+ (I347AT4_PCDL + phy->addr),
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Check if the unit of cable length is meters or cm */
+ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+ I347AT4_PCDC, &phy_data2);
+ if (ret_val)
+ return ret_val;
+
+ is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+ /* Populate the phy structure with cable length in meters */
+ phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->cable_length = phy_data / (is_cm ? 100 : 1);
+ break;
+ case M88E1340M_E_PHY_ID:
+ case I347AT4_E_PHY_ID:
+ /* Remember the original page select and set it to 7 */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+ &default_page);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
+ if (ret_val)
+ return ret_val;
+
+ /* Get cable length from PHY Cable Diagnostics Control Reg */
+ ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Check if the unit of cable length is meters or cm */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
+ if (ret_val)
+ return ret_val;
+
+ is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+ /* Populate the phy structure with cable length in meters */
+ phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->cable_length = phy_data / (is_cm ? 100 : 1);
+
+ /* Reset the page select to its original value */
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+ default_page);
+ if (ret_val)
+ return ret_val;
+ break;
+
+ case M88E1112_E_PHY_ID:
+ /* Remember the original page select and set it to 5 */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+ &default_page);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+ M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+
+ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
+ return -E1000_ERR_PHY;
+
+ phy->min_cable_length = e1000_m88_cable_length_table[index];
+ phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
+
+ phy->cable_length = (phy->min_cable_length +
+ phy->max_cable_length) / 2;
+
+ /* Reset the page select to its original value */
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+ default_page);
+ if (ret_val)
+ return ret_val;
+
+ break;
+ default:
+ return -E1000_ERR_PHY;
+ }
+
return ret_val;
}
@@ -2156,15 +2536,16 @@ out:
s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 phy_data, i, agc_value = 0;
u16 cur_agc_index, max_agc_index = 0;
u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
- u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
- {IGP02E1000_PHY_AGC_A,
- IGP02E1000_PHY_AGC_B,
- IGP02E1000_PHY_AGC_C,
- IGP02E1000_PHY_AGC_D};
+ static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
+ IGP02E1000_PHY_AGC_A,
+ IGP02E1000_PHY_AGC_B,
+ IGP02E1000_PHY_AGC_C,
+ IGP02E1000_PHY_AGC_D
+ };
DEBUGFUNC("e1000_get_cable_length_igp_2");
@@ -2172,23 +2553,20 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- /*
- * Getting bits 15:9, which represent the combination of
+ /* Getting bits 15:9, which represent the combination of
* coarse and fine gain values. The result is a number
* that can be put into the lookup table to obtain the
* approximate cable length.
*/
cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
- IGP02E1000_AGC_LENGTH_MASK;
+ IGP02E1000_AGC_LENGTH_MASK;
/* Array index bound check. */
if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
- (cur_agc_index == 0)) {
- ret_val = -E1000_ERR_PHY;
- goto out;
- }
+ (cur_agc_index == 0))
+ return -E1000_ERR_PHY;
/* Remove min & max AGC values from calculation. */
if (e1000_igp_2_cable_length_table[min_agc_index] >
@@ -2202,18 +2580,17 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
}
agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] +
- e1000_igp_2_cable_length_table[max_agc_index]);
+ e1000_igp_2_cable_length_table[max_agc_index]);
agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
/* Calculate cable length with the error range of +/- 10 meters. */
phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
- (agc_value - IGP02E1000_AGC_RANGE) : 0;
+ (agc_value - IGP02E1000_AGC_RANGE) : 0;
phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE;
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2237,53 +2614,51 @@ s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
if (phy->media_type != e1000_media_type_copper) {
DEBUGOUT("Phy info is only valid for copper media\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
DEBUGOUT("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL)
- ? TRUE : FALSE;
+ phy->polarity_correction = !!(phy_data &
+ M88E1000_PSCR_POLARITY_REVERSAL);
ret_val = e1000_check_polarity_m88(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? TRUE : FALSE;
+ phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX);
if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
ret_val = hw->phy.ops.get_cable_length(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
- ? e1000_1000t_rx_status_ok
- : e1000_1000t_rx_status_not_ok;
+ ? e1000_1000t_rx_status_ok
+ : e1000_1000t_rx_status_not_ok;
phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS)
- ? e1000_1000t_rx_status_ok
- : e1000_1000t_rx_status_not_ok;
+ ? e1000_1000t_rx_status_ok
+ : e1000_1000t_rx_status_not_ok;
} else {
/* Set values to "undefined" */
phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
@@ -2291,7 +2666,6 @@ s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
phy->remote_rx = e1000_1000t_rx_status_undefined;
}
-out:
return ret_val;
}
@@ -2315,50 +2689,48 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
DEBUGOUT("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
phy->polarity_correction = TRUE;
ret_val = e1000_check_polarity_igp(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? TRUE : FALSE;
+ phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX);
if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS) {
ret_val = phy->ops.get_cable_length(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
- ? e1000_1000t_rx_status_ok
- : e1000_1000t_rx_status_not_ok;
+ ? e1000_1000t_rx_status_ok
+ : e1000_1000t_rx_status_not_ok;
phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
- ? e1000_1000t_rx_status_ok
- : e1000_1000t_rx_status_not_ok;
+ ? e1000_1000t_rx_status_ok
+ : e1000_1000t_rx_status_not_ok;
} else {
phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
phy->local_rx = e1000_1000t_rx_status_undefined;
phy->remote_rx = e1000_1000t_rx_status_undefined;
}
-out:
return ret_val;
}
@@ -2379,44 +2751,41 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
DEBUGOUT("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);
if (ret_val)
- goto out;
- phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)
- ? FALSE : TRUE;
+ return ret_val;
+ phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE);
if (phy->polarity_correction) {
ret_val = e1000_check_polarity_ife(hw);
if (ret_val)
- goto out;
+ return ret_val;
} else {
/* Polarity is forced */
phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
- ? e1000_rev_polarity_reversed
- : e1000_rev_polarity_normal;
+ ? e1000_rev_polarity_reversed
+ : e1000_rev_polarity_normal;
}
ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? TRUE : FALSE;
+ phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS);
/* The following parameters are undefined for 10/100 operation. */
phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
phy->local_rx = e1000_1000t_rx_status_undefined;
phy->remote_rx = e1000_1000t_rx_status_undefined;
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -2428,26 +2797,25 @@ out:
**/
s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 phy_ctrl;
DEBUGFUNC("e1000_phy_sw_reset_generic");
- if (!(hw->phy.ops.read_reg))
- goto out;
+ if (!hw->phy.ops.read_reg)
+ return E1000_SUCCESS;
ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
if (ret_val)
- goto out;
+ return ret_val;
phy_ctrl |= MII_CR_RESET;
ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
if (ret_val)
- goto out;
+ return ret_val;
usec_delay(1);
-out:
return ret_val;
}
@@ -2463,20 +2831,20 @@ out:
s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u32 ctrl;
DEBUGFUNC("e1000_phy_hw_reset_generic");
- ret_val = phy->ops.check_reset_block(hw);
- if (ret_val) {
- ret_val = E1000_SUCCESS;
- goto out;
+ if (phy->ops.check_reset_block) {
+ ret_val = phy->ops.check_reset_block(hw);
+ if (ret_val)
+ return E1000_SUCCESS;
}
ret_val = phy->ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ctrl = E1000_READ_REG(hw, E1000_CTRL);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST);
@@ -2491,10 +2859,7 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
phy->ops.release(hw);
- ret_val = phy->ops.get_cfg_done(hw);
-
-out:
- return ret_val;
+ return phy->ops.get_cfg_done(hw);
}
/**
@@ -2576,15 +2941,13 @@ s32 e1000_phy_init_script_igp3(struct e1000_hw *hw)
hw->phy.ops.write_reg(hw, 0x1796, 0x0008);
/* Change cg_icount + enable integbp for channels BCD */
hw->phy.ops.write_reg(hw, 0x1798, 0xD008);
- /*
- * Change cg_icount + enable integbp + change prop_factor_master
+ /* Change cg_icount + enable integbp + change prop_factor_master
* to 8 for channel A
*/
hw->phy.ops.write_reg(hw, 0x1898, 0xD918);
/* Disable AHT in Slave mode on channel A */
hw->phy.ops.write_reg(hw, 0x187A, 0x0800);
- /*
- * Enable LPLU and disable AN to 1000 in non-D0a states,
+ /* Enable LPLU and disable AN to 1000 in non-D0a states,
* Enable SPD+B2B
*/
hw->phy.ops.write_reg(hw, 0x0019, 0x008D);
@@ -2613,6 +2976,9 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
case M88E1000_E_PHY_ID:
case M88E1111_I_PHY_ID:
case M88E1011_I_PHY_ID:
+ case I347AT4_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
+ case M88E1340M_E_PHY_ID:
phy_type = e1000_phy_m88;
break;
case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */
@@ -2642,9 +3008,15 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
case I82579_E_PHY_ID:
phy_type = e1000_phy_82579;
break;
+ case I217_E_PHY_ID:
+ phy_type = e1000_phy_i217;
+ break;
case I82580_I_PHY_ID:
phy_type = e1000_phy_82580;
break;
+ case I210_I_PHY_ID:
+ phy_type = e1000_phy_i210;
+ break;
default:
phy_type = e1000_phy_unknown;
break;
@@ -2662,7 +3034,6 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
**/
s32 e1000_determine_phy_address(struct e1000_hw *hw)
{
- s32 ret_val = -E1000_ERR_PHY_TYPE;
u32 phy_addr = 0;
u32 i;
enum e1000_phy_type phy_type = e1000_phy_unknown;
@@ -2677,21 +3048,18 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw)
e1000_get_phy_id(hw);
phy_type = e1000_get_phy_type_from_id(hw->phy.id);
- /*
- * If phy_type is valid, break - we found our
+ /* If phy_type is valid, break - we found our
* PHY address
*/
- if (phy_type != e1000_phy_unknown) {
- ret_val = E1000_SUCCESS;
- goto out;
- }
+ if (phy_type != e1000_phy_unknown)
+ return E1000_SUCCESS;
+
msec_delay(1);
i++;
} while (i < 10);
}
-out:
- return ret_val;
+ return -E1000_ERR_PHY_TYPE;
}
/**
@@ -2722,9 +3090,7 @@ static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
{
s32 ret_val;
- u32 page_select = 0;
u32 page = offset >> IGP_PAGE_SHIFT;
- u32 page_shift = 0;
DEBUGFUNC("e1000_write_phy_reg_bm");
@@ -2735,15 +3101,16 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
- FALSE);
- goto out;
+ FALSE, FALSE);
+ goto release;
}
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
if (offset > MAX_PHY_MULTI_PAGE_REG) {
- /*
- * Page select is register 31 for phy address 1 and 22 for
+ u32 page_shift, page_select;
+
+ /* Page select is register 31 for phy address 1 and 22 for
* phy address 2 and 3. Page select is shifted only for
* phy address 1.
*/
@@ -2757,15 +3124,15 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw, page_select,
- (page << page_shift));
+ (page << page_shift));
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
+ data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -2783,9 +3150,7 @@ out:
s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
{
s32 ret_val;
- u32 page_select = 0;
u32 page = offset >> IGP_PAGE_SHIFT;
- u32 page_shift = 0;
DEBUGFUNC("e1000_read_phy_reg_bm");
@@ -2796,15 +3161,16 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
- TRUE);
- goto out;
+ TRUE, FALSE);
+ goto release;
}
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
if (offset > MAX_PHY_MULTI_PAGE_REG) {
- /*
- * Page select is register 31 for phy address 1 and 22 for
+ u32 page_shift, page_select;
+
+ /* Page select is register 31 for phy address 1 and 22 for
* phy address 2 and 3. Page select is shifted only for
* phy address 1.
*/
@@ -2818,14 +3184,14 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw, page_select,
- (page << page_shift));
+ (page << page_shift));
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-out:
+ data);
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -2845,7 +3211,7 @@ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
s32 ret_val;
u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
- DEBUGFUNC("e1000_write_phy_reg_bm2");
+ DEBUGFUNC("e1000_read_phy_reg_bm2");
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
@@ -2854,25 +3220,24 @@ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
- TRUE);
- goto out;
+ TRUE, FALSE);
+ goto release;
}
hw->phy.addr = 1;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
-
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
- page);
+ page);
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-out:
+ data);
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -2900,8 +3265,8 @@ s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
- FALSE);
- goto out;
+ FALSE, FALSE);
+ goto release;
}
hw->phy.addr = 1;
@@ -2909,124 +3274,188 @@ s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
if (offset > MAX_PHY_MULTI_PAGE_REG) {
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
- page);
+ page);
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
+ data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
/**
- * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
+ * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
+ * @hw: pointer to the HW structure
+ * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
+ *
+ * Assumes semaphore already acquired and phy_reg points to a valid memory
+ * address to store contents of the BM_WUC_ENABLE_REG register.
+ **/
+s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
+{
+ s32 ret_val;
+ u16 temp;
+
+ DEBUGFUNC("e1000_enable_phy_wakeup_reg_access_bm");
+
+ if (!phy_reg)
+ return -E1000_ERR_PARAM;
+
+ /* All page select, port ctrl and wakeup registers use phy address 1 */
+ hw->phy.addr = 1;
+
+ /* Select Port Control Registers page */
+ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+ if (ret_val) {
+ DEBUGOUT("Could not set Port Control page\n");
+ return ret_val;
+ }
+
+ ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+ if (ret_val) {
+ DEBUGOUT2("Could not read PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+ return ret_val;
+ }
+
+ /* Enable both PHY wakeup mode and Wakeup register page writes.
+ * Prevent a power state change by disabling ME and Host PHY wakeup.
+ */
+ temp = *phy_reg;
+ temp |= BM_WUC_ENABLE_BIT;
+ temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
+
+ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
+ if (ret_val) {
+ DEBUGOUT2("Could not write PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+ return ret_val;
+ }
+
+ /* Select Host Wakeup Registers page - caller now able to write
+ * registers on the Wakeup registers page
+ */
+ return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+}
+
+/**
+ * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
+ * @hw: pointer to the HW structure
+ * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
+ *
+ * Restore BM_WUC_ENABLE_REG to its original value.
+ *
+ * Assumes semaphore already acquired and *phy_reg is the contents of the
+ * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
+ * caller.
+ **/
+s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
+{
+ s32 ret_val;
+
+ DEBUGFUNC("e1000_disable_phy_wakeup_reg_access_bm");
+
+ if (!phy_reg)
+ return -E1000_ERR_PARAM;
+
+ /* Select Port Control Registers page */
+ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+ if (ret_val) {
+ DEBUGOUT("Could not set Port Control page\n");
+ return ret_val;
+ }
+
+ /* Restore 769.17 to its original value */
+ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
+ if (ret_val)
+ DEBUGOUT2("Could not restore PHY register %d.%d\n",
+ BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+
+ return ret_val;
+}
+
+/**
+ * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
* @hw: pointer to the HW structure
* @offset: register offset to be read or written
* @data: pointer to the data to read or write
* @read: determines if operation is read or write
+ * @page_set: BM_WUC_PAGE already set and access enabled
*
- * Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retrieved information in data. Release any acquired
- * semaphores before exiting. Note that procedure to read the wakeup
- * registers are different. It works as such:
- * 1) Set page 769, register 17, bit 2 = 1
+ * Read the PHY register at offset and store the retrieved information in
+ * data, or write data to PHY register at offset. Note the procedure to
+ * access the PHY wakeup registers is different than reading the other PHY
+ * registers. It works as such:
+ * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1
* 2) Set page to 800 for host (801 if we were manageability)
* 3) Write the address using the address opcode (0x11)
* 4) Read or write the data using the data opcode (0x12)
- * 5) Restore 769_17.2 to its original value
+ * 5) Restore 769.17.2 to its original value
*
- * Assumes semaphore already acquired.
+ * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
+ * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
+ *
+ * Assumes semaphore is already acquired. When page_set==TRUE, assumes
+ * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
+ * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
**/
static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
- u16 *data, bool read)
+ u16 *data, bool read, bool page_set)
{
s32 ret_val;
u16 reg = BM_PHY_REG_NUM(offset);
+ u16 page = BM_PHY_REG_PAGE(offset);
u16 phy_reg = 0;
DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
- /* Gig must be disabled for MDIO accesses to page 800 */
+ /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
if ((hw->mac.type == e1000_pchlan) &&
(!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
- DEBUGOUT("Attempting to access page 800 while gig enabled.\n");
-
- /* All operations in this function are phy address 1 */
- hw->phy.addr = 1;
+ DEBUGOUT1("Attempting to access page %d while gig enabled.\n",
+ page);
- /* Set page 769 */
- e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
-
- ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
- if (ret_val) {
- DEBUGOUT("Could not read PHY page 769\n");
- goto out;
- }
-
- /* First clear bit 4 to avoid a power state change */
- phy_reg &= ~(BM_WUC_HOST_WU_BIT);
- ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
- if (ret_val) {
- DEBUGOUT("Could not clear PHY page 769 bit 4\n");
- goto out;
- }
-
- /* Write bit 2 = 1, and clear bit 4 to 769_17 */
- ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG,
- phy_reg | BM_WUC_ENABLE_BIT);
- if (ret_val) {
- DEBUGOUT("Could not write PHY page 769 bit 2\n");
- goto out;
+ if (!page_set) {
+ /* Enable access to PHY wakeup registers */
+ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+ if (ret_val) {
+ DEBUGOUT("Could not enable PHY wakeup reg access\n");
+ return ret_val;
+ }
}
- /* Select page 800 */
- ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+ DEBUGOUT2("Accessing PHY page %d reg 0x%x\n", page, reg);
- /* Write the page 800 offset value using opcode 0x11 */
+ /* Write the Wakeup register page offset value using opcode 0x11 */
ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
if (ret_val) {
- DEBUGOUT("Could not write address opcode to page 800\n");
- goto out;
+ DEBUGOUT1("Could not write address opcode to page %d\n", page);
+ return ret_val;
}
if (read) {
- /* Read the page 800 value using opcode 0x12 */
+ /* Read the Wakeup register page value using opcode 0x12 */
ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
- data);
+ data);
} else {
- /* Write the page 800 value using opcode 0x12 */
+ /* Write the Wakeup register page value using opcode 0x12 */
ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
- *data);
+ *data);
}
if (ret_val) {
- DEBUGOUT("Could not access data value from page 800\n");
- goto out;
+ DEBUGOUT2("Could not access PHY reg %d.%d\n", page, reg);
+ return ret_val;
}
- /*
- * Restore 769_17.2 to its original value
- * Set page 769
- */
- e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
- (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
-
- /* Clear 769_17.2 */
- ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
- if (ret_val) {
- DEBUGOUT("Could not clear PHY page 769 bit 2\n");
- goto out;
- }
+ if (!page_set)
+ ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
-out:
return ret_val;
}
@@ -3041,10 +3470,16 @@ out:
void e1000_power_up_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;
+ u16 power_reg = 0;
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
+ if (hw->phy.type == e1000_phy_i210) {
+ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+ power_reg &= ~GS40G_CS_POWER_DOWN;
+ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+ }
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
}
@@ -3059,10 +3494,17 @@ void e1000_power_up_phy_copper(struct e1000_hw *hw)
void e1000_power_down_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;
+ u16 power_reg = 0;
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
+ /* i210 Phy requires an additional bit for power up/down */
+ if (hw->phy.type == e1000_phy_i210) {
+ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+ power_reg |= GS40G_CS_POWER_DOWN;
+ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+ }
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
msec_delay(1);
}
@@ -3079,11 +3521,12 @@ void e1000_power_down_phy_copper(struct e1000_hw *hw)
* semaphore before exiting.
**/
static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
- bool locked)
+ bool locked, bool page_set)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
+ u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
DEBUGFUNC("__e1000_read_phy_reg_hv");
@@ -3095,39 +3538,38 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
- ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
- data, TRUE);
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+ TRUE, page_set);
goto out;
}
if (page > 0 && page < HV_INTC_FC_PAGE_START) {
ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
- data, TRUE);
+ data, TRUE);
goto out;
}
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
+ if (!page_set) {
+ if (page == HV_INTC_FC_PAGE_START)
+ page = 0;
- if (page == HV_INTC_FC_PAGE_START)
- page = 0;
+ if (reg > MAX_PHY_MULTI_PAGE_REG) {
+ /* Page is shifted left, PHY expects (page x 32) */
+ ret_val = e1000_set_page_igp(hw,
+ (page << IGP_PAGE_SHIFT));
- if (reg > MAX_PHY_MULTI_PAGE_REG) {
- u32 phy_addr = hw->phy.addr;
+ hw->phy.addr = phy_addr;
- hw->phy.addr = 1;
-
- /* Page is shifted left, PHY expects (page x 32) */
- ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (page << IGP_PAGE_SHIFT));
- hw->phy.addr = phy_addr;
-
- if (ret_val)
- goto out;
+ if (ret_val)
+ goto out;
+ }
}
+ DEBUGOUT3("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+ page << IGP_PAGE_SHIFT, reg);
+
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
- data);
+ data);
out:
if (!locked)
hw->phy.ops.release(hw);
@@ -3147,7 +3589,7 @@ out:
**/
s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
{
- return __e1000_read_phy_reg_hv(hw, offset, data, FALSE);
+ return __e1000_read_phy_reg_hv(hw, offset, data, FALSE, FALSE);
}
/**
@@ -3161,7 +3603,21 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
**/
s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
{
- return __e1000_read_phy_reg_hv(hw, offset, data, TRUE);
+ return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, FALSE);
+}
+
+/**
+ * e1000_read_phy_reg_page_hv - Read HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Reads the PHY register at offset and stores the retrieved information
+ * in data. Assumes semaphore already acquired and page already set.
+ **/
+s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, true);
}
/**
@@ -3175,11 +3631,12 @@ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
* at the offset. Release any acquired semaphores before exiting.
**/
static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
- bool locked)
+ bool locked, bool page_set)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
+ u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
DEBUGFUNC("__e1000_write_phy_reg_hv");
@@ -3191,55 +3648,54 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
- ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
- &data, FALSE);
+ ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+ FALSE, page_set);
goto out;
}
if (page > 0 && page < HV_INTC_FC_PAGE_START) {
ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
- &data, FALSE);
+ &data, FALSE);
goto out;
}
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
- if (page == HV_INTC_FC_PAGE_START)
- page = 0;
-
- /*
- * Workaround MDIO accesses being disabled after entering IEEE Power
- * Down (whenever bit 11 of the PHY Control register is set)
- */
- if ((hw->phy.type == e1000_phy_82578) &&
- (hw->phy.revision >= 1) &&
- (hw->phy.addr == 2) &&
- ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
- (data & (1 << 11))) {
- u16 data2 = 0x7EFF;
- ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
- &data2, FALSE);
- if (ret_val)
- goto out;
- }
+ if (!page_set) {
+ if (page == HV_INTC_FC_PAGE_START)
+ page = 0;
- if (reg > MAX_PHY_MULTI_PAGE_REG) {
- u32 phy_addr = hw->phy.addr;
+ /* Workaround MDIO accesses being disabled after entering IEEE
+ * Power Down (when bit 11 of the PHY Control register is set)
+ */
+ if ((hw->phy.type == e1000_phy_82578) &&
+ (hw->phy.revision >= 1) &&
+ (hw->phy.addr == 2) &&
+ !(MAX_PHY_REG_ADDRESS & reg) &&
+ (data & (1 << 11))) {
+ u16 data2 = 0x7EFF;
+ ret_val = e1000_access_phy_debug_regs_hv(hw,
+ (1 << 6) | 0x3,
+ &data2, FALSE);
+ if (ret_val)
+ goto out;
+ }
- hw->phy.addr = 1;
+ if (reg > MAX_PHY_MULTI_PAGE_REG) {
+ /* Page is shifted left, PHY expects (page x 32) */
+ ret_val = e1000_set_page_igp(hw,
+ (page << IGP_PAGE_SHIFT));
- /* Page is shifted left, PHY expects (page x 32) */
- ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (page << IGP_PAGE_SHIFT));
- hw->phy.addr = phy_addr;
+ hw->phy.addr = phy_addr;
- if (ret_val)
- goto out;
+ if (ret_val)
+ goto out;
+ }
}
+ DEBUGOUT3("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+ page << IGP_PAGE_SHIFT, reg);
+
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
- data);
+ data);
out:
if (!locked)
@@ -3259,7 +3715,7 @@ out:
**/
s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
{
- return __e1000_write_phy_reg_hv(hw, offset, data, FALSE);
+ return __e1000_write_phy_reg_hv(hw, offset, data, FALSE, FALSE);
}
/**
@@ -3273,7 +3729,21 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
**/
s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
{
- return __e1000_write_phy_reg_hv(hw, offset, data, TRUE);
+ return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, FALSE);
+}
+
+/**
+ * e1000_write_phy_reg_page_hv - Write HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Writes the data to PHY register at the offset. Assumes semaphore
+ * already acquired and page already set.
+ **/
+s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, true);
}
/**
@@ -3295,24 +3765,25 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
* @hw: pointer to the HW structure
* @offset: register offset to be read or written
* @data: pointer to the data to be read or written
- * @read: determines if operation is read or written
+ * @read: determines if operation is read or write
*
* Reads the PHY register at offset and stores the retreived information
* in data. Assumes semaphore already acquired. Note that the procedure
- * to read these regs uses the address port and data port to read/write.
+ * to access these regs uses the address port and data port to read/write.
+ * These accesses done with PHY address 2 and without using pages.
**/
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
- u16 *data, bool read)
+ u16 *data, bool read)
{
s32 ret_val;
- u32 addr_reg = 0;
- u32 data_reg = 0;
+ u32 addr_reg;
+ u32 data_reg;
DEBUGFUNC("e1000_access_phy_debug_regs_hv");
/* This takes care of the difference with desktop vs mobile phy */
addr_reg = (hw->phy.type == e1000_phy_82578) ?
- I82578_ADDR_REG : I82577_ADDR_REG;
+ I82578_ADDR_REG : I82577_ADDR_REG;
data_reg = addr_reg + 1;
/* All operations in this function are phy address 2 */
@@ -3321,8 +3792,8 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
/* masking with 0x3F to remove the page from offset */
ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
if (ret_val) {
- DEBUGOUT("Could not write PHY the HV address register\n");
- goto out;
+ DEBUGOUT("Could not write the Address Offset port register\n");
+ return ret_val;
}
/* Read or write the data value next */
@@ -3331,12 +3802,9 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
else
ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data);
- if (ret_val) {
- DEBUGOUT("Could not read data value from HV data register\n");
- goto out;
- }
+ if (ret_val)
+ DEBUGOUT("Could not access the Data port register\n");
-out:
return ret_val;
}
@@ -3359,41 +3827,36 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
DEBUGFUNC("e1000_link_stall_workaround_hv");
if (hw->phy.type != e1000_phy_82578)
- goto out;
+ return E1000_SUCCESS;
/* Do not apply workaround if in PHY loopback bit 14 set */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);
if (data & PHY_CONTROL_LB)
- goto out;
+ return E1000_SUCCESS;
/* check if link is up and at 1Gbps */
ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
- data &= BM_CS_STATUS_LINK_UP |
- BM_CS_STATUS_RESOLVED |
- BM_CS_STATUS_SPEED_MASK;
+ data &= BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_MASK;
- if (data != (BM_CS_STATUS_LINK_UP |
- BM_CS_STATUS_RESOLVED |
- BM_CS_STATUS_SPEED_1000))
- goto out;
+ if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_1000))
+ return E1000_SUCCESS;
msec_delay(200);
/* flush the packets in the fifo buffer */
ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
- HV_MUX_DATA_CTRL_GEN_TO_MAC |
- HV_MUX_DATA_CTRL_FORCE_SPEED);
+ (HV_MUX_DATA_CTRL_GEN_TO_MAC |
+ HV_MUX_DATA_CTRL_FORCE_SPEED));
if (ret_val)
- goto out;
-
- ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
- HV_MUX_DATA_CTRL_GEN_TO_MAC);
+ return ret_val;
-out:
- return ret_val;
+ return hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
+ HV_MUX_DATA_CTRL_GEN_TO_MAC);
}
/**
@@ -3416,8 +3879,8 @@ s32 e1000_check_polarity_82577(struct e1000_hw *hw)
if (!ret_val)
phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
- ? e1000_rev_polarity_reversed
- : e1000_rev_polarity_normal;
+ ? e1000_rev_polarity_reversed
+ : e1000_rev_polarity_normal;
return ret_val;
}
@@ -3439,39 +3902,32 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &phy_data);
ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
usec_delay(1);
if (phy->autoneg_wait_to_complete) {
DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n");
- ret_val = e1000_phy_has_link_generic(hw,
- PHY_FORCE_LIMIT,
- 100000,
- &link);
+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+ 100000, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
DEBUGOUT("Link taking longer than expected.\n");
/* Try once more */
- ret_val = e1000_phy_has_link_generic(hw,
- PHY_FORCE_LIMIT,
- 100000,
- &link);
- if (ret_val)
- goto out;
+ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+ 100000, &link);
}
-out:
return ret_val;
}
@@ -3495,51 +3951,49 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
DEBUGOUT("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
phy->polarity_correction = TRUE;
ret_val = e1000_check_polarity_82577(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
if (ret_val)
- goto out;
+ return ret_val;
- phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? TRUE : FALSE;
+ phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX);
if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
I82577_PHY_STATUS2_SPEED_1000MBPS) {
ret_val = hw->phy.ops.get_cable_length(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
- ? e1000_1000t_rx_status_ok
- : e1000_1000t_rx_status_not_ok;
+ ? e1000_1000t_rx_status_ok
+ : e1000_1000t_rx_status_not_ok;
phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
- ? e1000_1000t_rx_status_ok
- : e1000_1000t_rx_status_not_ok;
+ ? e1000_1000t_rx_status_ok
+ : e1000_1000t_rx_status_not_ok;
} else {
phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
phy->local_rx = e1000_1000t_rx_status_undefined;
phy->remote_rx = e1000_1000t_rx_status_undefined;
}
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -3559,16 +4013,79 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
- I82577_DSTATUS_CABLE_LENGTH_SHIFT;
+ I82577_DSTATUS_CABLE_LENGTH_SHIFT;
if (length == E1000_CABLE_LENGTH_UNDEFINED)
- ret_val = -E1000_ERR_PHY;
+ return -E1000_ERR_PHY;
phy->cable_length = length;
-out:
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_write_phy_reg_gs40g - Write GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore, if necessary, then writes the data to PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ s32 ret_val;
+ u16 page = offset >> GS40G_PAGE_SHIFT;
+
+ DEBUGFUNC("e1000_write_phy_reg_gs40g");
+
+ offset = offset & GS40G_OFFSET_MASK;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ if (ret_val)
+ goto release;
+ ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
+
+release:
+ hw->phy.ops.release(hw);
return ret_val;
}
+
+/**
+ * e1000_read_phy_reg_gs40g - Read GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: lower half is register offset to read to
+ * upper half is page to use.
+ * @data: data to read at register offset
+ *
+ * Acquires semaphore, if necessary, then reads the data in the PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ s32 ret_val;
+ u16 page = offset >> GS40G_PAGE_SHIFT;
+
+ DEBUGFUNC("e1000_read_phy_reg_gs40g");
+
+ offset = offset & GS40G_OFFSET_MASK;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ if (ret_val)
+ goto release;
+ ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
+
+release:
+ hw->phy.ops.release(hw);
+ return ret_val;
+}
+
diff --git a/freebsd/sys/dev/e1000/e1000_phy.h b/freebsd/sys/dev/e1000/e1000_phy.h
index c42ef6c6..9911df77 100644
--- a/freebsd/sys/dev/e1000/e1000_phy.h
+++ b/freebsd/sys/dev/e1000/e1000_phy.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,11 @@ s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data);
void e1000_null_phy_generic(struct e1000_hw *hw);
s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active);
s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_null_set_page(struct e1000_hw *hw, u16 data);
+s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data);
+s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data);
s32 e1000_check_downshift_generic(struct e1000_hw *hw);
s32 e1000_check_polarity_m88(struct e1000_hw *hw);
s32 e1000_check_polarity_igp(struct e1000_hw *hw);
@@ -49,10 +54,12 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
s32 e1000_copper_link_autoneg(struct e1000_hw *hw);
s32 e1000_copper_link_setup_igp(struct e1000_hw *hw);
s32 e1000_copper_link_setup_m88(struct e1000_hw *hw);
+s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
s32 e1000_get_cable_length_m88(struct e1000_hw *hw);
+s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw);
s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw);
s32 e1000_get_cfg_done_generic(struct e1000_hw *hw);
s32 e1000_get_phy_id(struct e1000_hw *hw);
@@ -65,25 +72,26 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw);
s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw);
s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page);
s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active);
s32 e1000_setup_copper_link_generic(struct e1000_hw *hw);
-s32 e1000_wait_autoneg_generic(struct e1000_hw *hw);
s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data);
-s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
- u32 usec_interval, bool *success);
+ u32 usec_interval, bool *success);
s32 e1000_phy_init_script_igp3(struct e1000_hw *hw);
enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id);
s32 e1000_determine_phy_address(struct e1000_hw *hw);
s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg);
+s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg);
s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
void e1000_power_up_phy_copper(struct e1000_hw *hw);
@@ -92,44 +100,60 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
+s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data);
s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
s32 e1000_check_polarity_82577(struct e1000_hw *hw);
s32 e1000_get_phy_info_82577(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw);
s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
+s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
-#define E1000_MAX_PHY_ADDR 4
+#define E1000_MAX_PHY_ADDR 8
/* IGP01E1000 Specific Registers */
-#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
-#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */
-#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */
-#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */
-#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */
-#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */
-#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */
-#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */
-#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */
-#define IGP_PAGE_SHIFT 5
-#define PHY_REG_MASK 0x1F
+#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
+#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */
+#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */
+#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */
+#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */
+#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */
+#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */
+#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */
+#define IGP_PAGE_SHIFT 5
+#define PHY_REG_MASK 0x1F
+
+/* GS40G - I210 PHY defines */
+#define GS40G_PAGE_SELECT 0x16
+#define GS40G_PAGE_SHIFT 16
+#define GS40G_OFFSET_MASK 0xFFFF
+#define GS40G_PAGE_2 0x20000
+#define GS40G_MAC_REG2 0x15
+#define GS40G_MAC_LB 0x4140
+#define GS40G_MAC_SPEED_1G 0X0006
+#define GS40G_COPPER_SPEC 0x0010
+#define GS40G_CS_POWER_DOWN 0x0002
/* BM/HV Specific Registers */
-#define BM_PORT_CTRL_PAGE 769
-#define BM_PCIE_PAGE 770
-#define BM_WUC_PAGE 800
-#define BM_WUC_ADDRESS_OPCODE 0x11
-#define BM_WUC_DATA_OPCODE 0x12
-#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE
-#define BM_WUC_ENABLE_REG 17
-#define BM_WUC_ENABLE_BIT (1 << 2)
-#define BM_WUC_HOST_WU_BIT (1 << 4)
-
-#define PHY_UPPER_SHIFT 21
+#define BM_PORT_CTRL_PAGE 769
+#define BM_WUC_PAGE 800
+#define BM_WUC_ADDRESS_OPCODE 0x11
+#define BM_WUC_DATA_OPCODE 0x12
+#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE
+#define BM_WUC_ENABLE_REG 17
+#define BM_WUC_ENABLE_BIT (1 << 2)
+#define BM_WUC_HOST_WU_BIT (1 << 4)
+#define BM_WUC_ME_WU_BIT (1 << 5)
+
+#define PHY_UPPER_SHIFT 21
#define BM_PHY_REG(page, reg) \
(((reg) & MAX_PHY_REG_ADDRESS) |\
(((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\
@@ -141,125 +165,151 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
(((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\
~MAX_PHY_REG_ADDRESS)))
-#define HV_INTC_FC_PAGE_START 768
-#define I82578_ADDR_REG 29
-#define I82577_ADDR_REG 16
-#define I82577_CFG_REG 22
-#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15)
-#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */
-#define I82577_CTRL_REG 23
+#define HV_INTC_FC_PAGE_START 768
+#define I82578_ADDR_REG 29
+#define I82577_ADDR_REG 16
+#define I82577_CFG_REG 22
+#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15)
+#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */
+#define I82577_CTRL_REG 23
/* 82577 specific PHY registers */
-#define I82577_PHY_CTRL_2 18
-#define I82577_PHY_LBK_CTRL 19
-#define I82577_PHY_STATUS_2 26
-#define I82577_PHY_DIAG_STATUS 31
+#define I82577_PHY_CTRL_2 18
+#define I82577_PHY_LBK_CTRL 19
+#define I82577_PHY_STATUS_2 26
+#define I82577_PHY_DIAG_STATUS 31
/* I82577 PHY Status 2 */
-#define I82577_PHY_STATUS2_REV_POLARITY 0x0400
-#define I82577_PHY_STATUS2_MDIX 0x0800
-#define I82577_PHY_STATUS2_SPEED_MASK 0x0300
-#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200
-#define I82577_PHY_STATUS2_SPEED_100MBPS 0x0100
+#define I82577_PHY_STATUS2_REV_POLARITY 0x0400
+#define I82577_PHY_STATUS2_MDIX 0x0800
+#define I82577_PHY_STATUS2_SPEED_MASK 0x0300
+#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200
/* I82577 PHY Control 2 */
-#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400
-#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200
+#define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200
+#define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400
+#define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600
/* I82577 PHY Diagnostics Status */
-#define I82577_DSTATUS_CABLE_LENGTH 0x03FC
-#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
+#define I82577_DSTATUS_CABLE_LENGTH 0x03FC
+#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
+
+/* 82580 PHY Power Management */
+#define E1000_82580_PHY_POWER_MGMT 0xE14
+#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
+#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
+#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
+#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */
/* BM PHY Copper Specific Control 1 */
-#define BM_CS_CTRL1 16
-#define BM_CS_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */
+#define BM_CS_CTRL1 16
/* BM PHY Copper Specific Status */
-#define BM_CS_STATUS 17
-#define BM_CS_STATUS_ENERGY_DETECT 0x0010 /* Energy Detect Status */
-#define BM_CS_STATUS_LINK_UP 0x0400
-#define BM_CS_STATUS_RESOLVED 0x0800
-#define BM_CS_STATUS_SPEED_MASK 0xC000
-#define BM_CS_STATUS_SPEED_1000 0x8000
+#define BM_CS_STATUS 17
+#define BM_CS_STATUS_LINK_UP 0x0400
+#define BM_CS_STATUS_RESOLVED 0x0800
+#define BM_CS_STATUS_SPEED_MASK 0xC000
+#define BM_CS_STATUS_SPEED_1000 0x8000
/* 82577 Mobile Phy Status Register */
-#define HV_M_STATUS 26
-#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000
-#define HV_M_STATUS_SPEED_MASK 0x0300
-#define HV_M_STATUS_SPEED_1000 0x0200
-#define HV_M_STATUS_LINK_UP 0x0040
+#define HV_M_STATUS 26
+#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000
+#define HV_M_STATUS_SPEED_MASK 0x0300
+#define HV_M_STATUS_SPEED_1000 0x0200
+#define HV_M_STATUS_LINK_UP 0x0040
-#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
-#define IGP01E1000_PHY_POLARITY_MASK 0x0078
+#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
+#define IGP01E1000_PHY_POLARITY_MASK 0x0078
-#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
-#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
+#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
+#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
-#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
+#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
/* Enable flexible speed on link-up */
-#define IGP01E1000_GMII_FLEX_SPD 0x0010
-#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */
-
-#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */
-#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
-#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
-
-#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
-
-#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
-#define IGP01E1000_PSSR_MDIX 0x0800
-#define IGP01E1000_PSSR_SPEED_MASK 0xC000
-#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
-
-#define IGP02E1000_PHY_CHANNEL_NUM 4
-#define IGP02E1000_PHY_AGC_A 0x11B1
-#define IGP02E1000_PHY_AGC_B 0x12B1
-#define IGP02E1000_PHY_AGC_C 0x14B1
-#define IGP02E1000_PHY_AGC_D 0x18B1
-
-#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
-#define IGP02E1000_AGC_LENGTH_MASK 0x7F
-#define IGP02E1000_AGC_RANGE 15
-
-#define IGP03E1000_PHY_MISC_CTRL 0x1B
-#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */
-
-#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
-
-#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000
-#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16
-#define E1000_KMRNCTRLSTA_REN 0x00200000
-#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */
-#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
-#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
-#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
-#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
-#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
-#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002
-#define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */
-
-#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
-#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */
-#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */
-#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */
+#define IGP01E1000_GMII_FLEX_SPD 0x0010
+#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */
+
+#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */
+#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
+#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
+
+#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
+
+#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
+#define IGP01E1000_PSSR_MDIX 0x0800
+#define IGP01E1000_PSSR_SPEED_MASK 0xC000
+#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
+
+#define IGP02E1000_PHY_CHANNEL_NUM 4
+#define IGP02E1000_PHY_AGC_A 0x11B1
+#define IGP02E1000_PHY_AGC_B 0x12B1
+#define IGP02E1000_PHY_AGC_C 0x14B1
+#define IGP02E1000_PHY_AGC_D 0x18B1
+
+#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
+#define IGP02E1000_AGC_LENGTH_MASK 0x7F
+#define IGP02E1000_AGC_RANGE 15
+
+#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
+
+#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000
+#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16
+#define E1000_KMRNCTRLSTA_REN 0x00200000
+#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */
+#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
+#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
+#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
+#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */
+#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
+#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
+#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 /* enable K1 */
+#define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */
+
+#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
+#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */
+#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */
+#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */
/* IFE PHY Extended Status Control */
-#define IFE_PESC_POLARITY_REVERSED 0x0100
+#define IFE_PESC_POLARITY_REVERSED 0x0100
/* IFE PHY Special Control */
-#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010
-#define IFE_PSC_FORCE_POLARITY 0x0020
-#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100
+#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010
+#define IFE_PSC_FORCE_POLARITY 0x0020
/* IFE PHY Special Control and LED Control */
-#define IFE_PSCL_PROBE_MODE 0x0020
-#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
-#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
+#define IFE_PSCL_PROBE_MODE 0x0020
+#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
+#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
/* IFE PHY MDIX Control */
-#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */
-#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */
-#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */
+#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */
+#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */
+#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto, 0=disable */
+
+/* SFP modules ID memory locations */
+#define E1000_SFF_IDENTIFIER_OFFSET 0x00
+#define E1000_SFF_IDENTIFIER_SFF 0x02
+#define E1000_SFF_IDENTIFIER_SFP 0x03
+
+#define E1000_SFF_ETH_FLAGS_OFFSET 0x06
+/* Flags for SFP modules compatible with ETH up to 1Gb */
+struct sfp_e1000_flags {
+ u8 e1000_base_sx:1;
+ u8 e1000_base_lx:1;
+ u8 e1000_base_cx:1;
+ u8 e1000_base_t:1;
+ u8 e100_base_lx:1;
+ u8 e100_base_fx:1;
+ u8 e10_base_bx10:1;
+ u8 e10_base_px:1;
+};
+
+/* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */
+#define E1000_SFF_VENDOR_OUI_TYCO 0x00407600
+#define E1000_SFF_VENDOR_OUI_FTL 0x00906500
+#define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
+#define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
#endif
diff --git a/freebsd/sys/dev/e1000/e1000_regs.h b/freebsd/sys/dev/e1000/e1000_regs.h
index 38ccff32..516d377a 100644
--- a/freebsd/sys/dev/e1000/e1000_regs.h
+++ b/freebsd/sys/dev/e1000/e1000_regs.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,514 +35,642 @@
#ifndef _E1000_REGS_H_
#define _E1000_REGS_H_
-#define E1000_CTRL 0x00000 /* Device Control - RW */
-#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
-#define E1000_STATUS 0x00008 /* Device Status - RO */
-#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
-#define E1000_EERD 0x00014 /* EEPROM Read - RW */
-#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
-#define E1000_FLA 0x0001C /* Flash Access - RW */
-#define E1000_MDIC 0x00020 /* MDI Control - RW */
-#define E1000_MDICNFG 0x00E04 /* MDI Config - RW */
-#define E1000_REGISTER_SET_SIZE 0x20000 /* CSR Size */
-#define E1000_EEPROM_INIT_CTRL_WORD_2 0x0F /* EEPROM Init Ctrl Word 2 */
-#define E1000_BARCTRL 0x5BBC /* BAR ctrl reg */
-#define E1000_BARCTRL_FLSIZE 0x0700 /* BAR ctrl Flsize */
-#define E1000_BARCTRL_CSRSIZE 0x2000 /* BAR ctrl CSR size */
-#define E1000_SCTL 0x00024 /* SerDes Control - RW */
-#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
-#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
-#define E1000_FEXT 0x0002C /* Future Extended - RW */
-#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
-#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
-#define E1000_FCT 0x00030 /* Flow Control Type - RW */
-#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
-#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
-#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
-#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
-#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
-#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
-#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
-#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
-#define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */
-#define E1000_SVCR 0x000F0
-#define E1000_SVT 0x000F4
-#define E1000_RCTL 0x00100 /* Rx Control - RW */
-#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
-#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */
-#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */
-#define E1000_PBA_ECC 0x01100 /* PBA ECC Register */
-#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
-#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
-#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
-#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
-#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
-#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
-#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
-#define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */
-#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
-#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
-#define E1000_TCTL 0x00400 /* Tx Control - RW */
-#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */
-#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */
-#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */
-#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
-#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
-#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
-#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
-#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
-#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
-#define E1000_PBS 0x01008 /* Packet Buffer Size */
-#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
-#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
-#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
-#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
-#define E1000_FLSWCTL 0x01030 /* FLASH control register */
-#define E1000_FLSWDATA 0x01034 /* FLASH data register */
-#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
-#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
-#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
-#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
-#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */
-#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */
-#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
-#define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */
-#define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */
-#define E1000_ICR_V2 0x01500 /* Interrupt Cause - new location - RC */
-#define E1000_ICS_V2 0x01504 /* Interrupt Cause Set - new location - WO */
-#define E1000_IMS_V2 0x01508 /* Interrupt Mask Set/Read - new location - RW */
-#define E1000_IMC_V2 0x0150C /* Interrupt Mask Clear - new location - WO */
-#define E1000_IAM_V2 0x01510 /* Interrupt Ack Auto Mask - new location - RW */
-#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
-#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
-#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
-#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
-#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n)))
-#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */
-#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
+#define E1000_CTRL 0x00000 /* Device Control - RW */
+#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
+#define E1000_STATUS 0x00008 /* Device Status - RO */
+#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
+#define E1000_EERD 0x00014 /* EEPROM Read - RW */
+#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
+#define E1000_FLA 0x0001C /* Flash Access - RW */
+#define E1000_MDIC 0x00020 /* MDI Control - RW */
+#define E1000_MDICNFG 0x00E04 /* MDI Config - RW */
+#define E1000_REGISTER_SET_SIZE 0x20000 /* CSR Size */
+#define E1000_EEPROM_INIT_CTRL_WORD_2 0x0F /* EEPROM Init Ctrl Word 2 */
+#define E1000_EEPROM_PCIE_CTRL_WORD_2 0x28 /* EEPROM PCIe Ctrl Word 2 */
+#define E1000_BARCTRL 0x5BBC /* BAR ctrl reg */
+#define E1000_BARCTRL_FLSIZE 0x0700 /* BAR ctrl Flsize */
+#define E1000_BARCTRL_CSRSIZE 0x2000 /* BAR ctrl CSR size */
+#define E1000_I350_BARCTRL 0x5BFC /* BAR ctrl reg */
+#define E1000_I350_DTXMXPKTSZ 0x355C /* Maximum sent packet size reg*/
+#define E1000_SCTL 0x00024 /* SerDes Control - RW */
+#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
+#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
+#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
+#define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */
+#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
+#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */
+#define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */
+#define E1000_FCT 0x00030 /* Flow Control Type - RW */
+#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
+#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
+#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
+#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
+#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
+#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
+#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
+#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
+#define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */
+#define E1000_SVCR 0x000F0
+#define E1000_SVT 0x000F4
+#define E1000_LPIC 0x000FC /* Low Power IDLE control */
+#define E1000_RCTL 0x00100 /* Rx Control - RW */
+#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
+#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */
+#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */
+#define E1000_PBA_ECC 0x01100 /* PBA ECC Register */
+#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
+#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
+#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
+#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
+#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
+#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
+#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
+#define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */
+#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
+#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
+#define E1000_TCTL 0x00400 /* Tx Control - RW */
+#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */
+#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */
+#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */
+#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
+#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
+#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
+#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
+#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
+#define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */
+#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
+#define E1000_PBS 0x01008 /* Packet Buffer Size */
+#define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */
+#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
+#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
+#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
+#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
+#define E1000_FLSWCTL 0x01030 /* FLASH control register */
+#define E1000_FLSWDATA 0x01034 /* FLASH data register */
+#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
+#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
+#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
+#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
+#define E1000_I2CBB_EN 0x00000100 /* I2C - Bit Bang Enable */
+#define E1000_I2C_CLK_OUT 0x00000200 /* I2C- Clock */
+#define E1000_I2C_DATA_OUT 0x00000400 /* I2C- Data Out */
+#define E1000_I2C_DATA_OE_N 0x00000800 /* I2C- Data Output Enable */
+#define E1000_I2C_DATA_IN 0x00001000 /* I2C- Data In */
+#define E1000_I2C_CLK_OE_N 0x00002000 /* I2C- Clock Output Enable */
+#define E1000_I2C_CLK_IN 0x00004000 /* I2C- Clock In */
+#define E1000_I2C_CLK_STRETCH_DIS 0x00008000 /* I2C- Dis Clk Stretching */
+#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */
+#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */
+#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
+#define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */
+#define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */
+#define E1000_ICR_V2 0x01500 /* Intr Cause - new location - RC */
+#define E1000_ICS_V2 0x01504 /* Intr Cause Set - new location - WO */
+#define E1000_IMS_V2 0x01508 /* Intr Mask Set/Read - new location - RW */
+#define E1000_IMC_V2 0x0150C /* Intr Mask Clear - new location - WO */
+#define E1000_IAM_V2 0x01510 /* Intr Ack Auto Mask - new location - RW */
+#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
+#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
+#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
+#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
+#define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */
+#define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */
+#define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */
+#define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */
+#define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */
+#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */
+#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
/* Split and Replication Rx Control - RW */
-#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */
-#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */
-#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */
-#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */
-#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */
-#define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */
-#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
-#define E1000_IRPBS 0x02404 /* Same as RXPBS, renamed for newer adapters - RW */
-#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
-#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
-/*
- * Convenience macros
+#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */
+#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */
+#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */
+#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */
+#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */
+#define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */
+#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
+#define E1000_IRPBS 0x02404 /* Same as RXPBS, renamed for newer Si - RW */
+#define E1000_PBRWAC 0x024E8 /* Rx packet buffer wrap around counter - RO */
+#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
+#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
+#define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */
+#define E1000_I210_FLMNGCTL 0x12038
+#define E1000_I210_FLMNGDATA 0x1203C
+#define E1000_I210_FLMNGCNT 0x12040
+
+#define E1000_I210_FLSWCTL 0x12048
+#define E1000_I210_FLSWDATA 0x1204C
+#define E1000_I210_FLSWCNT 0x12050
+
+#define E1000_I210_FLA 0x1201C
+
+#define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n))
+#define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */
+
+/* QAV Tx mode control register */
+#define E1000_I210_TQAVCTRL 0x3570
+
+/* QAV Tx mode control register bitfields masks */
+/* QAV enable */
+#define E1000_TQAVCTRL_MODE (1 << 0)
+/* Fetching arbitration type */
+#define E1000_TQAVCTRL_FETCH_ARB (1 << 4)
+/* Fetching timer enable */
+#define E1000_TQAVCTRL_FETCH_TIMER_ENABLE (1 << 5)
+/* Launch arbitration type */
+#define E1000_TQAVCTRL_LAUNCH_ARB (1 << 8)
+/* Launch timer enable */
+#define E1000_TQAVCTRL_LAUNCH_TIMER_ENABLE (1 << 9)
+/* SP waits for SR enable */
+#define E1000_TQAVCTRL_SP_WAIT_SR (1 << 10)
+/* Fetching timer correction */
+#define E1000_TQAVCTRL_FETCH_TIMER_DELTA_OFFSET 16
+#define E1000_TQAVCTRL_FETCH_TIMER_DELTA \
+ (0xFFFF << E1000_TQAVCTRL_FETCH_TIMER_DELTA_OFFSET)
+
+/* High credit registers where _n can be 0 or 1. */
+#define E1000_I210_TQAVHC(_n) (0x300C + 0x40 * (_n))
+
+/* Queues fetch arbitration priority control register */
+#define E1000_I210_TQAVARBCTRL 0x3574
+/* Queues priority masks where _n and _p can be 0-3. */
+#define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p) ((_p) << (2 * _n))
+/* QAV Tx mode control registers where _n can be 0 or 1. */
+#define E1000_I210_TQAVCC(_n) (0x3004 + 0x40 * (_n))
+
+/* QAV Tx mode control register bitfields masks */
+#define E1000_TQAVCC_IDLE_SLOPE 0xFFFF /* Idle slope */
+#define E1000_TQAVCC_KEEP_CREDITS (1 << 30) /* Keep credits opt enable */
+#define E1000_TQAVCC_QUEUE_MODE (1 << 31) /* SP vs. SR Tx mode */
+
+/* Good transmitted packets counter registers */
+#define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n)))
+
+/* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */
+#define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * _n))
+
+/* Convenience macros
*
* Note: "_n" is the queue number of the register to be written to.
*
* Example usage:
* E1000_RDBAL_REG(current_rx_queue)
*/
-#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
- (0x0C000 + ((_n) * 0x40)))
-#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
- (0x0C004 + ((_n) * 0x40)))
-#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
- (0x0C008 + ((_n) * 0x40)))
-#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
- (0x0C00C + ((_n) * 0x40)))
-#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
- (0x0C010 + ((_n) * 0x40)))
-#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \
- (0x0C014 + ((_n) * 0x40)))
-#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n)
-#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
- (0x0C018 + ((_n) * 0x40)))
-#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
- (0x0C028 + ((_n) * 0x40)))
-#define E1000_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \
- (0x0C030 + ((_n) * 0x40)))
-#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
- (0x0E000 + ((_n) * 0x40)))
-#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
- (0x0E004 + ((_n) * 0x40)))
-#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
- (0x0E008 + ((_n) * 0x40)))
-#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
- (0x0E010 + ((_n) * 0x40)))
-#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \
- (0x0E014 + ((_n) * 0x40)))
+#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
+ (0x0C000 + ((_n) * 0x40)))
+#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
+ (0x0C004 + ((_n) * 0x40)))
+#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
+ (0x0C008 + ((_n) * 0x40)))
+#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
+ (0x0C00C + ((_n) * 0x40)))
+#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
+ (0x0C010 + ((_n) * 0x40)))
+#define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \
+ (0x0C014 + ((_n) * 0x40)))
+#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n)
+#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
+ (0x0C018 + ((_n) * 0x40)))
+#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
+ (0x0C028 + ((_n) * 0x40)))
+#define E1000_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \
+ (0x0C030 + ((_n) * 0x40)))
+#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
+ (0x0E000 + ((_n) * 0x40)))
+#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
+ (0x0E004 + ((_n) * 0x40)))
+#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
+ (0x0E008 + ((_n) * 0x40)))
+#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
+ (0x0E010 + ((_n) * 0x40)))
+#define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \
+ (0x0E014 + ((_n) * 0x40)))
#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n)
-#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
- (0x0E018 + ((_n) * 0x40)))
-#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
- (0x0E028 + ((_n) * 0x40)))
-#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \
- (0x0E038 + ((_n) * 0x40)))
-#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \
- (0x0E03C + ((_n) * 0x40)))
-#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100))
-#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */
-#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
-#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */
-#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
-#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
-#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
- (0x054E0 + ((_i - 16) * 8)))
-#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
- (0x054E4 + ((_i - 16) * 8)))
-#define E1000_SHRAL(_i) (0x05438 + ((_i) * 8))
-#define E1000_SHRAH(_i) (0x0543C + ((_i) * 8))
-#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
-#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
-#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
-#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
-#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
-#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
-#define E1000_PBSLAC 0x03100 /* Packet Buffer Slave Access Control */
-#define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) /* Packet Buffer DWORD (_n) */
-#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */
-#define E1000_ITPBS 0x03404 /* Same as TXPBS, renamed for newer adpaters - RW */
-#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */
-#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */
-#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */
-#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */
-#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */
-#define E1000_TDPUMB 0x0357C /* DMA Tx Descriptor uC Mail Box - RW */
-#define E1000_TDPUAD 0x03580 /* DMA Tx Descriptor uC Addr Command - RW */
-#define E1000_TDPUWD 0x03584 /* DMA Tx Descriptor uC Data Write - RW */
-#define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */
-#define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */
-#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */
-#define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */
-#define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */
-#define E1000_DTXMXSZRQ 0x03540 /* DMA Tx Max Total Allow Size Requests - RW */
-#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */
-#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */
-#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
-#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
-#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
-#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
-#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
-#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
-#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
-#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
-#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
-#define E1000_COLC 0x04028 /* Collision Count - R/clr */
-#define E1000_DC 0x04030 /* Defer Count - R/clr */
-#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */
-#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
-#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
-#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
-#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */
-#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */
-#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
-#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
-#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
-#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
-#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
-#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
-#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
-#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
-#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
-#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
-#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
-#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
-#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
-#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
-#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
-#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
-#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
-#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
-#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */
-#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */
-#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */
-#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */
-#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
-#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
-#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
-#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
-#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */
-#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
-#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */
-#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */
-#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */
-#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
-#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
-#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
-#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
-#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
-#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
-#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
-#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
-#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
-#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */
-#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
-#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */
-#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */
-#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */
-#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */
-#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */
-#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */
-#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
-#define E1000_CRC_OFFSET 0x05F50 /* CRC Offset register */
+#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
+ (0x0E018 + ((_n) * 0x40)))
+#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
+ (0x0E028 + ((_n) * 0x40)))
+#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \
+ (0x0E038 + ((_n) * 0x40)))
+#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \
+ (0x0E03C + ((_n) * 0x40)))
+#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100))
+#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */
+#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
+#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */
+#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
+#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
+#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
+ (0x054E0 + ((_i - 16) * 8)))
+#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
+ (0x054E4 + ((_i - 16) * 8)))
+#define E1000_SHRAL(_i) (0x05438 + ((_i) * 8))
+#define E1000_SHRAH(_i) (0x0543C + ((_i) * 8))
+#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
+#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
+#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
+#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
+#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
+#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
+#define E1000_PBSLAC 0x03100 /* Pkt Buffer Slave Access Control */
+#define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) /* Pkt Buffer DWORD */
+#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */
+/* Same as TXPBS, renamed for newer Si - RW */
+#define E1000_ITPBS 0x03404
+#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */
+#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */
+#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */
+#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */
+#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */
+#define E1000_TDPUMB 0x0357C /* DMA Tx Desc uC Mail Box - RW */
+#define E1000_TDPUAD 0x03580 /* DMA Tx Desc uC Addr Command - RW */
+#define E1000_TDPUWD 0x03584 /* DMA Tx Desc uC Data Write - RW */
+#define E1000_TDPURD 0x03588 /* DMA Tx Desc uC Data Read - RW */
+#define E1000_TDPUCTL 0x0358C /* DMA Tx Desc uC Control - RW */
+#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */
+#define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */
+#define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */
+/* DMA Tx Max Total Allow Size Reqs - RW */
+#define E1000_DTXMXSZRQ 0x03540
+#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */
+#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */
+#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
+#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
+#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
+#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
+#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
+#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
+#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
+#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
+#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
+#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
+#define E1000_COLC 0x04028 /* Collision Count - R/clr */
+#define E1000_DC 0x04030 /* Defer Count - R/clr */
+#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */
+#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
+#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
+#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
+#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */
+#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */
+#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
+#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
+#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
+#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
+#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
+#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
+#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
+#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
+#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
+#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
+#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
+#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
+#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
+#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
+#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
+#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
+#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
+#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
+#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */
+#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */
+#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */
+#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */
+#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
+#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
+#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
+#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
+#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */
+#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
+#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */
+#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */
+#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */
+#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
+#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
+#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
+#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
+#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
+#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
+#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
+#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
+#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
+#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */
+#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
+#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */
+#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */
+#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */
+#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */
+#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */
+#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */
+#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
+#define E1000_CRC_OFFSET 0x05F50 /* CRC Offset register */
-#define E1000_VFGPRC 0x00F10
-#define E1000_VFGORC 0x00F18
-#define E1000_VFMPRC 0x00F3C
-#define E1000_VFGPTC 0x00F14
-#define E1000_VFGOTC 0x00F34
-#define E1000_VFGOTLBC 0x00F50
-#define E1000_VFGPTLBC 0x00F44
-#define E1000_VFGORLBC 0x00F48
-#define E1000_VFGPRLBC 0x00F40
+#define E1000_VFGPRC 0x00F10
+#define E1000_VFGORC 0x00F18
+#define E1000_VFMPRC 0x00F3C
+#define E1000_VFGPTC 0x00F14
+#define E1000_VFGOTC 0x00F34
+#define E1000_VFGOTLBC 0x00F50
+#define E1000_VFGPTLBC 0x00F44
+#define E1000_VFGORLBC 0x00F48
+#define E1000_VFGPRLBC 0x00F40
/* Virtualization statistical counters */
-#define E1000_PFVFGPRC(_n) (0x010010 + (0x100 * (_n)))
-#define E1000_PFVFGPTC(_n) (0x010014 + (0x100 * (_n)))
-#define E1000_PFVFGORC(_n) (0x010018 + (0x100 * (_n)))
-#define E1000_PFVFGOTC(_n) (0x010034 + (0x100 * (_n)))
-#define E1000_PFVFMPRC(_n) (0x010038 + (0x100 * (_n)))
-#define E1000_PFVFGPRLBC(_n) (0x010040 + (0x100 * (_n)))
-#define E1000_PFVFGPTLBC(_n) (0x010044 + (0x100 * (_n)))
-#define E1000_PFVFGORLBC(_n) (0x010048 + (0x100 * (_n)))
-#define E1000_PFVFGOTLBC(_n) (0x010050 + (0x100 * (_n)))
+#define E1000_PFVFGPRC(_n) (0x010010 + (0x100 * (_n)))
+#define E1000_PFVFGPTC(_n) (0x010014 + (0x100 * (_n)))
+#define E1000_PFVFGORC(_n) (0x010018 + (0x100 * (_n)))
+#define E1000_PFVFGOTC(_n) (0x010034 + (0x100 * (_n)))
+#define E1000_PFVFMPRC(_n) (0x010038 + (0x100 * (_n)))
+#define E1000_PFVFGPRLBC(_n) (0x010040 + (0x100 * (_n)))
+#define E1000_PFVFGPTLBC(_n) (0x010044 + (0x100 * (_n)))
+#define E1000_PFVFGORLBC(_n) (0x010048 + (0x100 * (_n)))
+#define E1000_PFVFGOTLBC(_n) (0x010050 + (0x100 * (_n)))
-#define E1000_LSECTXUT 0x04300 /* LinkSec Tx Untagged Packet Count - OutPktsUntagged */
-#define E1000_LSECTXPKTE 0x04304 /* LinkSec Encrypted Tx Packets Count - OutPktsEncrypted */
-#define E1000_LSECTXPKTP 0x04308 /* LinkSec Protected Tx Packet Count - OutPktsProtected */
-#define E1000_LSECTXOCTE 0x0430C /* LinkSec Encrypted Tx Octets Count - OutOctetsEncrypted */
-#define E1000_LSECTXOCTP 0x04310 /* LinkSec Protected Tx Octets Count - OutOctetsProtected */
-#define E1000_LSECRXUT 0x04314 /* LinkSec Untagged non-Strict Rx Packet Count - InPktsUntagged/InPktsNoTag */
-#define E1000_LSECRXOCTD 0x0431C /* LinkSec Rx Octets Decrypted Count - InOctetsDecrypted */
-#define E1000_LSECRXOCTV 0x04320 /* LinkSec Rx Octets Validated - InOctetsValidated */
-#define E1000_LSECRXBAD 0x04324 /* LinkSec Rx Bad Tag - InPktsBadTag */
-#define E1000_LSECRXNOSCI 0x04328 /* LinkSec Rx Packet No SCI Count - InPktsNoSci */
-#define E1000_LSECRXUNSCI 0x0432C /* LinkSec Rx Packet Unknown SCI Count - InPktsUnknownSci */
-#define E1000_LSECRXUNCH 0x04330 /* LinkSec Rx Unchecked Packets Count - InPktsUnchecked */
-#define E1000_LSECRXDELAY 0x04340 /* LinkSec Rx Delayed Packet Count - InPktsDelayed */
-#define E1000_LSECRXLATE 0x04350 /* LinkSec Rx Late Packets Count - InPktsLate */
-#define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) /* LinkSec Rx Packet OK Count - InPktsOk */
-#define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) /* LinkSec Rx Invalid Count - InPktsInvalid */
-#define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) /* LinkSec Rx Not Valid Count - InPktsNotValid */
-#define E1000_LSECRXUNSA 0x043C0 /* LinkSec Rx Unused SA Count - InPktsUnusedSa */
-#define E1000_LSECRXNUSA 0x043D0 /* LinkSec Rx Not Using SA Count - InPktsNotUsingSa */
-#define E1000_LSECTXCAP 0x0B000 /* LinkSec Tx Capabilities Register - RO */
-#define E1000_LSECRXCAP 0x0B300 /* LinkSec Rx Capabilities Register - RO */
-#define E1000_LSECTXCTRL 0x0B004 /* LinkSec Tx Control - RW */
-#define E1000_LSECRXCTRL 0x0B304 /* LinkSec Rx Control - RW */
-#define E1000_LSECTXSCL 0x0B008 /* LinkSec Tx SCI Low - RW */
-#define E1000_LSECTXSCH 0x0B00C /* LinkSec Tx SCI High - RW */
-#define E1000_LSECTXSA 0x0B010 /* LinkSec Tx SA0 - RW */
-#define E1000_LSECTXPN0 0x0B018 /* LinkSec Tx SA PN 0 - RW */
-#define E1000_LSECTXPN1 0x0B01C /* LinkSec Tx SA PN 1 - RW */
-#define E1000_LSECRXSCL 0x0B3D0 /* LinkSec Rx SCI Low - RW */
-#define E1000_LSECRXSCH 0x0B3E0 /* LinkSec Rx SCI High - RW */
-#define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 0 - WO */
-#define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 1 - WO */
-#define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */
-#define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */
-/*
- * LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit
+/* LinkSec */
+#define E1000_LSECTXUT 0x04300 /* Tx Untagged Pkt Cnt */
+#define E1000_LSECTXPKTE 0x04304 /* Encrypted Tx Pkts Cnt */
+#define E1000_LSECTXPKTP 0x04308 /* Protected Tx Pkt Cnt */
+#define E1000_LSECTXOCTE 0x0430C /* Encrypted Tx Octets Cnt */
+#define E1000_LSECTXOCTP 0x04310 /* Protected Tx Octets Cnt */
+#define E1000_LSECRXUT 0x04314 /* Untagged non-Strict Rx Pkt Cnt */
+#define E1000_LSECRXOCTD 0x0431C /* Rx Octets Decrypted Count */
+#define E1000_LSECRXOCTV 0x04320 /* Rx Octets Validated */
+#define E1000_LSECRXBAD 0x04324 /* Rx Bad Tag */
+#define E1000_LSECRXNOSCI 0x04328 /* Rx Packet No SCI Count */
+#define E1000_LSECRXUNSCI 0x0432C /* Rx Packet Unknown SCI Count */
+#define E1000_LSECRXUNCH 0x04330 /* Rx Unchecked Packets Count */
+#define E1000_LSECRXDELAY 0x04340 /* Rx Delayed Packet Count */
+#define E1000_LSECRXLATE 0x04350 /* Rx Late Packets Count */
+#define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) /* Rx Pkt OK Cnt */
+#define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) /* Rx Invalid Cnt */
+#define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) /* Rx Not Valid Cnt */
+#define E1000_LSECRXUNSA 0x043C0 /* Rx Unused SA Count */
+#define E1000_LSECRXNUSA 0x043D0 /* Rx Not Using SA Count */
+#define E1000_LSECTXCAP 0x0B000 /* Tx Capabilities Register - RO */
+#define E1000_LSECRXCAP 0x0B300 /* Rx Capabilities Register - RO */
+#define E1000_LSECTXCTRL 0x0B004 /* Tx Control - RW */
+#define E1000_LSECRXCTRL 0x0B304 /* Rx Control - RW */
+#define E1000_LSECTXSCL 0x0B008 /* Tx SCI Low - RW */
+#define E1000_LSECTXSCH 0x0B00C /* Tx SCI High - RW */
+#define E1000_LSECTXSA 0x0B010 /* Tx SA0 - RW */
+#define E1000_LSECTXPN0 0x0B018 /* Tx SA PN 0 - RW */
+#define E1000_LSECTXPN1 0x0B01C /* Tx SA PN 1 - RW */
+#define E1000_LSECRXSCL 0x0B3D0 /* Rx SCI Low - RW */
+#define E1000_LSECRXSCH 0x0B3E0 /* Rx SCI High - RW */
+/* LinkSec Tx 128-bit Key 0 - WO */
+#define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n)))
+/* LinkSec Tx 128-bit Key 1 - WO */
+#define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n)))
+#define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* Rx SAs - RW */
+#define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* Rx SAs - RW */
+/* LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit
* key - RW.
*/
-#define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m)))
+#define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m)))
-#define E1000_SSVPC 0x041A0 /* Switch Security Violation Packet Count */
-#define E1000_IPSCTRL 0xB430 /* IpSec Control Register */
-#define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */
-#define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */
-#define E1000_IPSRXIPADDR(_n) (0x0B420+ (0x04 * (_n))) /* IPSec Rx IPv4/v6 Address - RW */
-#define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n))) /* IPSec Rx 128-bit Key - RW */
-#define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */
-#define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */
-#define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n))) /* IPSec Tx 128-bit Key - RW */
-#define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */
-#define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */
-#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
-#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
-#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
-#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */
-#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
-#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */
-#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */
-#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
-#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */
-#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */
-#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
-#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
-#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
-#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
-#define E1000_LENERRS 0x04138 /* Length Errors Count */
-#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
-#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */
-#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
-#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
-#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
-#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */
-#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */
-#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */
-#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */
-#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
-#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
-#define E1000_RA 0x05400 /* Receive Address - RW Array */
-#define E1000_RA2 0x054E0 /* 2nd half of receive address array - RW Array */
-#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
-#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
-#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */
-#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */
-#define E1000_WUC 0x05800 /* Wakeup Control - RW */
-#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
-#define E1000_WUS 0x05810 /* Wakeup Status - RO */
-#define E1000_MANC 0x05820 /* Management Control - RW */
-#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
-#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
-#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
-#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
-#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
-#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
-#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
-#define E1000_HOST_IF 0x08800 /* Host Interface */
-#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
-#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
-#define E1000_FHFT(_n) (0x09000 + (_n * 0x100)) /* Flexible Host Filter Table */
-#define E1000_FHFT_EXT(_n) (0x09A00 + (_n * 0x100)) /* Ext Flexible Host Filter Table */
+#define E1000_SSVPC 0x041A0 /* Switch Security Violation Pkt Cnt */
+#define E1000_IPSCTRL 0xB430 /* IpSec Control Register */
+#define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */
+#define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */
+/* IPSec Rx IPv4/v6 Address - RW */
+#define E1000_IPSRXIPADDR(_n) (0x0B420 + (0x04 * (_n)))
+/* IPSec Rx 128-bit Key - RW */
+#define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n)))
+#define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */
+#define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */
+/* IPSec Tx 128-bit Key - RW */
+#define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n)))
+#define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */
+#define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */
+#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
+#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
+#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
+#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */
+#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
+#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */
+#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */
+#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
+#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */
+#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */
+#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
+#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
+#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
+#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
+#define E1000_LENERRS 0x04138 /* Length Errors Count */
+#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
+#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */
+#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
+#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
+#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
+#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Pg - RW */
+#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */
+#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */
+#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
+#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
+#define E1000_RA 0x05400 /* Receive Address - RW Array */
+#define E1000_RA2 0x054E0 /* 2nd half of Rx address array - RW Array */
+#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
+#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
+#define E1000_CIAA 0x05B88 /* Config Indirect Access Address - RW */
+#define E1000_CIAD 0x05B8C /* Config Indirect Access Data - RW */
+#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */
+#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */
+#define E1000_WUC 0x05800 /* Wakeup Control - RW */
+#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
+#define E1000_WUS 0x05810 /* Wakeup Status - RO */
+#define E1000_MANC 0x05820 /* Management Control - RW */
+#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
+#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
+#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
+#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
+#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
+#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
+#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
+#define E1000_HOST_IF 0x08800 /* Host Interface */
+#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
+#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
+#define E1000_HIBBA 0x8F40 /* Host Interface Buffer Base Address */
+/* Flexible Host Filter Table */
+#define E1000_FHFT(_n) (0x09000 + ((_n) * 0x100))
+/* Ext Flexible Host Filter Table */
+#define E1000_FHFT_EXT(_n) (0x09A00 + ((_n) * 0x100))
-#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
-#define E1000_MDPHYA 0x0003C /* PHY address - RW */
-#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
-#define E1000_MDEF(_n) (0x05890 + (4 * (_n))) /* Mngmt Decision Filters */
-#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
-#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
-#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
-#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
-#define E1000_GCR 0x05B00 /* PCI-Ex Control */
-#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
-#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
-#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
-#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
-#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
-#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
-#define E1000_SWSM 0x05B50 /* SW Semaphore */
-#define E1000_FWSM 0x05B54 /* FW Semaphore */
-#define E1000_SWSM2 0x05B58 /* Driver-only SW semaphore (not used by BOOT agents) */
-#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */
-#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
-#define E1000_UFUSE 0x05B78 /* UFUSE - RO */
-#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
-#define E1000_HICR 0x08F00 /* Host Interface Control */
+#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
+#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
+/* Management Decision Filters */
+#define E1000_MDEF(_n) (0x05890 + (4 * (_n)))
+#define E1000_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */
+#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
+#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
+#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
+#define E1000_GCR 0x05B00 /* PCI-Ex Control */
+#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
+#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
+#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
+#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
+#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
+#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
+#define E1000_SWSM 0x05B50 /* SW Semaphore */
+#define E1000_FWSM 0x05B54 /* FW Semaphore */
+/* Driver-only SW semaphore (not used by BOOT agents) */
+#define E1000_SWSM2 0x05B58
+#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */
+#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
+#define E1000_UFUSE 0x05B78 /* UFUSE - RO */
+#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
+#define E1000_HICR 0x08F00 /* Host Interface Control */
+#define E1000_FWSTS 0x08F0C /* FW Status */
/* RSS registers */
-#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
-#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
-#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
-#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/
-#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */
-#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register
- * (_i) - RW */
-#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr
- * low reg - RW */
-#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr
- * upper reg - RW */
-#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry
- * message reg - RW */
-#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry
- * vector ctrl reg - RW */
-#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */
-#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */
-#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
-#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
-#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
+#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
+#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
+#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
+#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/
+#define E1000_IMIRVP 0x05AC0 /* Immediate INT Rx VLAN Priority -RW */
+#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Alloc Reg -RW */
+#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */
+#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
+#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
+#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
/* VT Registers */
-#define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */
-#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */
-#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */
-#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */
-#define E1000_VFRE 0x00C8C /* VF Receive Enables */
-#define E1000_VFTE 0x00C90 /* VF Transmit Enables */
-#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */
-#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */
-#define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */
-#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
-#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
-#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
-#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */
+#define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */
+#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */
+#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */
+#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */
+#define E1000_VFRE 0x00C8C /* VF Receive Enables */
+#define E1000_VFTE 0x00C90 /* VF Transmit Enables */
+#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */
+#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */
+#define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */
+#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
+#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
+#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
+#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */
+#define E1000_VMRVLAN 0x05D90 /* Virtual Mirror Rule VLAN */
+#define E1000_VMRVM 0x05DA0 /* Virtual Mirror Rule VM */
+#define E1000_MDFB 0x03558 /* Malicious Driver free block */
+#define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */
+#define E1000_TXSWC 0x05ACC /* Tx Switch Control */
+#define E1000_SCCRL 0x05DB0 /* Storm Control Control */
+#define E1000_BSCTRH 0x05DB8 /* Broadcast Storm Control Threshold */
+#define E1000_MSCTRH 0x05DBC /* Multicast Storm Control Threshold */
/* These act per VF so an array friendly macro is used */
-#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
-#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
-#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
-#define E1000_VFVMBMEM(_n) (0x00800 + (_n))
-#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n)))
-#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine
- * Filter - RW */
-#define E1000_VMVIR(_n) (0x03700 + (4 * (_n)))
-/* Time Sync */
-#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
-#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
-#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
-#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */
-#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */
-#define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */
-#define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */
-#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
-#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
-#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */
-#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */
-#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */
-#define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
-#define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */
-#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */
-#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */
+#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
+#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
+#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
+#define E1000_VFVMBMEM(_n) (0x00800 + (_n))
+#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n)))
+/* VLAN Virtual Machine Filter - RW */
+#define E1000_VLVF(_n) (0x05D00 + (4 * (_n)))
+#define E1000_VMVIR(_n) (0x03700 + (4 * (_n)))
+#define E1000_DVMOLR(_n) (0x0C038 + (0x40 * (_n))) /* DMA VM offload */
+#define E1000_VTCTRL(_n) (0x10000 + (0x100 * (_n))) /* VT Control */
+#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
+#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
+#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
+#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */
+#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */
+#define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */
+#define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */
+#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
+#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
+#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */
+#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */
+#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */
+#define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */
+#define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */
+#define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
+#define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */
+#define E1000_TSICR 0x0B66C /* Interrupt Cause Register */
+#define E1000_TSIM 0x0B674 /* Interrupt Mask Register */
+#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */
+#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */
/* Filtering Registers */
-#define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */
-#define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */
-#define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */
-#define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */
-#define E1000_TTQF(_n) (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */
-#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
-#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
+#define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */
+#define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */
+#define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */
+#define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */
+#define E1000_TTQF(_n) (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */
+#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
+#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
-#define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */
-#define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */
-#define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */
-#define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */
-#define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */
-#define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4)) /* Tx Desc plane TC Rate-scheduler config */
-#define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Config */
-#define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Config */
-#define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler Status */
-#define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler MMW */
-#define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Status */
-#define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4)) /* Tx Packet plane TC Rate-scheduler MMW */
-#define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Status */
-#define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler MMW */
-#define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4)) /* Tx Desc plane VM Rate-Scheduler MMW*/
-#define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4)) /* Tx BCN Rate-Scheduler MMW */
-#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */
-#define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */
-#define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */
-#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */
-#define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */
-#define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */
-#define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */
-#define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */
-#define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */
-#define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */
-#define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */
-#define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */
-#define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */
-#define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */
+#define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */
+#define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */
+#define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */
+#define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */
+#define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */
+/* Tx Desc plane TC Rate-scheduler config */
+#define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4))
+/* Tx Packet plane TC Rate-Scheduler Config */
+#define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4))
+/* Rx Packet plane TC Rate-Scheduler Config */
+#define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4))
+/* Tx Desc Plane TC Rate-Scheduler Status */
+#define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4))
+/* Tx Desc Plane TC Rate-Scheduler MMW */
+#define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4))
+/* Tx Packet plane TC Rate-Scheduler Status */
+#define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4))
+/* Tx Packet plane TC Rate-scheduler MMW */
+#define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4))
+/* Rx Packet plane TC Rate-Scheduler Status */
+#define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4))
+/* Rx Packet plane TC Rate-Scheduler MMW */
+#define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4))
+/* Tx Desc plane VM Rate-Scheduler MMW*/
+#define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4))
+/* Tx BCN Rate-Scheduler MMW */
+#define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4))
+#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */
+#define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */
+#define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */
+#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */
+#define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */
+#define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */
+#define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */
+#define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */
+#define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */
+#define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */
+#define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */
+#define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */
+#define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */
+#define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */
/* DMA Coalescing registers */
-#define E1000_DMACR 0x02508 /* Control Register */
-#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */
-#define E1000_DMCTLX 0x02514 /* Time to Lx Request */
-#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */
-#define E1000_DMCCNT 0x05DD4 /* Current RX Count */
-#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */
-#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
+#define E1000_DMACR 0x02508 /* Control Register */
+#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */
+#define E1000_DMCTLX 0x02514 /* Time to Lx Request */
+#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */
+#define E1000_DMCCNT 0x05DD4 /* Current Rx Count */
+#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */
+#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
/* PCIe Parity Status Register */
-#define E1000_PCIEERRSTS 0x05BA8
+#define E1000_PCIEERRSTS 0x05BA8
+
+#define E1000_PROXYS 0x5F64 /* Proxying Status */
+#define E1000_PROXYFC 0x5F60 /* Proxying Filter Control */
+/* Thermal sensor configuration and status registers */
+#define E1000_THMJT 0x08100 /* Junction Temperature */
+#define E1000_THLOWTC 0x08104 /* Low Threshold Control */
+#define E1000_THMIDTC 0x08108 /* Mid Threshold Control */
+#define E1000_THHIGHTC 0x0810C /* High Threshold Control */
+#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
+
+/* Energy Efficient Ethernet "EEE" registers */
+#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */
+#define E1000_LTRC 0x01A0 /* Latency Tolerance Reporting Control */
+#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/
+#define E1000_EEE_SU 0x0E34 /* EEE Setup */
+#define E1000_TLPIC 0x4148 /* EEE Tx LPI Count - TLPIC */
+#define E1000_RLPIC 0x414C /* EEE Rx LPI Count - RLPIC */
+
+/* OS2BMC Registers */
+#define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */
+#define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */
+#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */
+#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */
+
+#define E1000_DOBFFCTL 0x3F24 /* DMA OBFF Control Register */
#endif
diff --git a/freebsd/sys/dev/e1000/e1000_vf.c b/freebsd/sys/dev/e1000/e1000_vf.c
index de6feb6a..c5fab9b3 100644
--- a/freebsd/sys/dev/e1000/e1000_vf.c
+++ b/freebsd/sys/dev/e1000/e1000_vf.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -40,21 +40,21 @@
#include <rtems/bsd/local/e1000_api.h>
#endif
-static s32 e1000_init_phy_params_vf(struct e1000_hw *hw);
-static s32 e1000_init_nvm_params_vf(struct e1000_hw *hw);
-static void e1000_release_vf(struct e1000_hw *hw);
-static s32 e1000_acquire_vf(struct e1000_hw *hw);
-static s32 e1000_setup_link_vf(struct e1000_hw *hw);
-static s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw);
-static s32 e1000_init_mac_params_vf(struct e1000_hw *hw);
-static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
-static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
- u16 *duplex);
-static s32 e1000_init_hw_vf(struct e1000_hw *hw);
-static s32 e1000_reset_hw_vf(struct e1000_hw *hw);
-static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, u32);
-static void e1000_rar_set_vf(struct e1000_hw *, u8 *, u32);
-static s32 e1000_read_mac_addr_vf(struct e1000_hw *);
+static s32 e1000_init_phy_params_vf(struct e1000_hw *hw);
+static s32 e1000_init_nvm_params_vf(struct e1000_hw *hw);
+static void e1000_release_vf(struct e1000_hw *hw);
+static s32 e1000_acquire_vf(struct e1000_hw *hw);
+static s32 e1000_setup_link_vf(struct e1000_hw *hw);
+static s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw);
+static s32 e1000_init_mac_params_vf(struct e1000_hw *hw);
+static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
+static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
+ u16 *duplex);
+static s32 e1000_init_hw_vf(struct e1000_hw *hw);
+static s32 e1000_reset_hw_vf(struct e1000_hw *hw);
+static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, u32);
+static void e1000_rar_set_vf(struct e1000_hw *, u8 *, u32);
+static s32 e1000_read_mac_addr_vf(struct e1000_hw *);
/**
* e1000_init_phy_params_vf - Inits PHY params
@@ -223,7 +223,7 @@ static s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw)
* the status register's data which is often stale and inaccurate.
**/
static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
- u16 *duplex)
+ u16 *duplex)
{
s32 status;
@@ -292,7 +292,7 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
if (!ret_val) {
if (msgbuf[0] == (E1000_VF_RESET |
- E1000_VT_MSGTYPE_ACK))
+ E1000_VT_MSGTYPE_ACK))
memcpy(hw->mac.perm_addr, addr, 6);
else
ret_val = -E1000_ERR_MAC_INIT;
@@ -373,11 +373,22 @@ static u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
bit_shift++;
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
- (((u16) mc_addr[5]) << bit_shift)));
+ (((u16) mc_addr[5]) << bit_shift)));
return hash_value;
}
+static void e1000_write_msg_read_ack(struct e1000_hw *hw,
+ u32 *msg, u16 size)
+{
+ struct e1000_mbx_info *mbx = &hw->mbx;
+ u32 retmsg[E1000_VFMAILBOX_SIZE];
+ s32 retval = mbx->ops.write_posted(hw, msg, size, 0);
+
+ if (!retval)
+ mbx->ops.read_posted(hw, retmsg, E1000_VFMAILBOX_SIZE, 0);
+}
+
/**
* e1000_update_mc_addr_list_vf - Update Multicast addresses
* @hw: pointer to the HW structure
@@ -388,9 +399,8 @@ static u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
* The caller must have a packed mc_addr_list of multicast addresses.
**/
void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count)
+ u8 *mc_addr_list, u32 mc_addr_count)
{
- struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[E1000_VFMAILBOX_SIZE];
u16 *hash_list = (u16 *)&msgbuf[1];
u32 hash_value;
@@ -424,7 +434,7 @@ void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
mc_addr_list += ETH_ADDR_LEN;
}
- mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE, 0);
+ e1000_write_msg_read_ack(hw, msgbuf, E1000_VFMAILBOX_SIZE);
}
/**
@@ -435,7 +445,6 @@ void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
**/
void e1000_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
{
- struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2];
msgbuf[0] = E1000_VF_SET_VLAN;
@@ -444,7 +453,7 @@ void e1000_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
if (set)
msgbuf[0] |= E1000_VF_SET_VLAN_ADD;
- mbx->ops.write_posted(hw, msgbuf, 2, 0);
+ e1000_write_msg_read_ack(hw, msgbuf, 2);
}
/** e1000_rlpml_set_vf - Set the maximum receive packet length
@@ -453,13 +462,12 @@ void e1000_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
**/
void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
{
- struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2];
msgbuf[0] = E1000_VF_SET_LPE;
msgbuf[1] = max_size;
- mbx->ops.write_posted(hw, msgbuf, 2, 0);
+ e1000_write_msg_read_ack(hw, msgbuf, 2);
}
/**
@@ -536,8 +544,8 @@ static s32 e1000_check_for_link_vf(struct e1000_hw *hw)
* or a virtual function reset
*/
- /* If we were hit with a reset drop the link */
- if (!mbx->ops.check_for_rst(hw, 0))
+ /* If we were hit with a reset or timeout drop the link */
+ if (!mbx->ops.check_for_rst(hw, 0) || !mbx->timeout)
mac->get_link_status = TRUE;
if (!mac->get_link_status)
diff --git a/freebsd/sys/dev/e1000/e1000_vf.h b/freebsd/sys/dev/e1000/e1000_vf.h
index 8d02eda3..a07c1e3e 100644
--- a/freebsd/sys/dev/e1000/e1000_vf.h
+++ b/freebsd/sys/dev/e1000/e1000_vf.h
@@ -48,6 +48,7 @@
struct e1000_hw;
#define E1000_DEV_ID_82576_VF 0x10CA
+#define E1000_DEV_ID_I350_VF 0x1520
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
@@ -94,9 +95,10 @@ union e1000_adv_rx_desc {
union {
u32 data;
struct {
- u16 pkt_info; /* RSS type, Packet type */
- u16 hdr_info; /* Split Header,
- * header buffer length */
+ /* RSS type, Packet type */
+ u16 pkt_info;
+ /* Split Header, header buffer len */
+ u16 hdr_info;
} hs_rss;
} lo_dword;
union {
@@ -160,6 +162,7 @@ struct e1000_adv_tx_context_desc {
enum e1000_mac_type {
e1000_undefined = 0,
e1000_vfadapt,
+ e1000_vfadapt_i350,
e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */
};
@@ -259,8 +262,8 @@ struct e1000_mbx_info {
};
struct e1000_dev_spec_vf {
- u32 vf_number;
- u32 v2p_mailbox;
+ u32 vf_number;
+ u32 v2p_mailbox;
};
struct e1000_hw {
@@ -274,7 +277,7 @@ struct e1000_hw {
struct e1000_mbx_info mbx;
union {
- struct e1000_dev_spec_vf vf;
+ struct e1000_dev_spec_vf vf;
} dev_spec;
u16 device_id;
diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c
index c0fffc30..330b67bf 100644
--- a/freebsd/sys/dev/e1000/if_em.c
+++ b/freebsd/sys/dev/e1000/if_em.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,7 @@
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include <rtems/bsd/local/opt_device_polling.h>
#include <rtems/bsd/local/opt_inet.h>
+#include <rtems/bsd/local/opt_inet6.h>
#endif
#include <rtems/bsd/sys/param.h>
@@ -101,7 +102,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char em_driver_version[] = "7.1.9";
+char em_driver_version[] = "7.3.7";
/*********************************************************************
* PCI Device ID Table
@@ -179,6 +180,12 @@ static em_vendor_info_t em_vendor_info_array[] =
{ 0x8086, E1000_DEV_ID_PCH_D_HV_DC, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH2_LV_LM, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH2_LV_V, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_LPT_I217_LM, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_LPT_I217_V, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_LPTLP_I218_LM,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_LPTLP_I218_V,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@@ -200,13 +207,14 @@ static int em_detach(device_t);
static int em_shutdown(device_t);
static int em_suspend(device_t);
static int em_resume(device_t);
-static void em_start(struct ifnet *);
-static void em_start_locked(struct ifnet *, struct tx_ring *);
#ifdef EM_MULTIQUEUE
static int em_mq_start(struct ifnet *, struct mbuf *);
static int em_mq_start_locked(struct ifnet *,
struct tx_ring *, struct mbuf *);
static void em_qflush(struct ifnet *);
+#else
+static void em_start(struct ifnet *);
+static void em_start_locked(struct ifnet *, struct tx_ring *);
#endif
static int em_ioctl(struct ifnet *, u_long, caddr_t);
static void em_init(void *);
@@ -241,7 +249,7 @@ static void em_enable_intr(struct adapter *);
static void em_disable_intr(struct adapter *);
static void em_update_stats_counters(struct adapter *);
static void em_add_hw_stats(struct adapter *adapter);
-static bool em_txeof(struct tx_ring *);
+static void em_txeof(struct tx_ring *);
static bool em_rxeof(struct rx_ring *, int, int *);
#ifndef __NO_STRICT_ALIGNMENT
static int em_fixup_rx(struct rx_ring *);
@@ -292,10 +300,10 @@ static void em_handle_tx(void *context, int pending);
static void em_handle_rx(void *context, int pending);
static void em_handle_link(void *context, int pending);
-static void em_add_rx_process_limit(struct adapter *, const char *,
- const char *, int *, int);
-static void em_set_flow_cntrl(struct adapter *, const char *,
+static void em_set_sysctl_value(struct adapter *, const char *,
const char *, int *, int);
+static int em_set_flowcntl(SYSCTL_HANDLER_ARGS);
+static int em_sysctl_eee(SYSCTL_HANDLER_ARGS);
static __inline void em_rx_discard(struct rx_ring *, int);
@@ -315,7 +323,7 @@ static device_method_t em_methods[] = {
DEVMETHOD(device_shutdown, em_shutdown),
DEVMETHOD(device_suspend, em_suspend),
DEVMETHOD(device_resume, em_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t em_driver = {
@@ -340,42 +348,74 @@ MODULE_DEPEND(em, ether, 1, 1, 1);
#define CSUM_TSO 0
#endif
+static SYSCTL_NODE(_hw, OID_AUTO, em, CTLFLAG_RD, 0, "EM driver parameters");
+
static int em_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV);
static int em_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR);
TUNABLE_INT("hw.em.tx_int_delay", &em_tx_int_delay_dflt);
TUNABLE_INT("hw.em.rx_int_delay", &em_rx_int_delay_dflt);
+SYSCTL_INT(_hw_em, OID_AUTO, tx_int_delay, CTLFLAG_RDTUN, &em_tx_int_delay_dflt,
+ 0, "Default transmit interrupt delay in usecs");
+SYSCTL_INT(_hw_em, OID_AUTO, rx_int_delay, CTLFLAG_RDTUN, &em_rx_int_delay_dflt,
+ 0, "Default receive interrupt delay in usecs");
static int em_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV);
static int em_rx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_RADV);
TUNABLE_INT("hw.em.tx_abs_int_delay", &em_tx_abs_int_delay_dflt);
TUNABLE_INT("hw.em.rx_abs_int_delay", &em_rx_abs_int_delay_dflt);
+SYSCTL_INT(_hw_em, OID_AUTO, tx_abs_int_delay, CTLFLAG_RDTUN,
+ &em_tx_abs_int_delay_dflt, 0,
+ "Default transmit interrupt delay limit in usecs");
+SYSCTL_INT(_hw_em, OID_AUTO, rx_abs_int_delay, CTLFLAG_RDTUN,
+ &em_rx_abs_int_delay_dflt, 0,
+ "Default receive interrupt delay limit in usecs");
static int em_rxd = EM_DEFAULT_RXD;
static int em_txd = EM_DEFAULT_TXD;
TUNABLE_INT("hw.em.rxd", &em_rxd);
TUNABLE_INT("hw.em.txd", &em_txd);
+SYSCTL_INT(_hw_em, OID_AUTO, rxd, CTLFLAG_RDTUN, &em_rxd, 0,
+ "Number of receive descriptors per queue");
+SYSCTL_INT(_hw_em, OID_AUTO, txd, CTLFLAG_RDTUN, &em_txd, 0,
+ "Number of transmit descriptors per queue");
static int em_smart_pwr_down = FALSE;
TUNABLE_INT("hw.em.smart_pwr_down", &em_smart_pwr_down);
+SYSCTL_INT(_hw_em, OID_AUTO, smart_pwr_down, CTLFLAG_RDTUN, &em_smart_pwr_down,
+ 0, "Set to true to leave smart power down enabled on newer adapters");
/* Controls whether promiscuous also shows bad packets */
static int em_debug_sbp = FALSE;
TUNABLE_INT("hw.em.sbp", &em_debug_sbp);
+SYSCTL_INT(_hw_em, OID_AUTO, sbp, CTLFLAG_RDTUN, &em_debug_sbp, 0,
+ "Show bad packets in promiscuous mode");
static int em_enable_msix = TRUE;
TUNABLE_INT("hw.em.enable_msix", &em_enable_msix);
+SYSCTL_INT(_hw_em, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &em_enable_msix, 0,
+ "Enable MSI-X interrupts");
/* How many packets rxeof tries to clean at a time */
static int em_rx_process_limit = 100;
TUNABLE_INT("hw.em.rx_process_limit", &em_rx_process_limit);
+SYSCTL_INT(_hw_em, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
+ &em_rx_process_limit, 0,
+ "Maximum number of received packets to process "
+ "at a time, -1 means unlimited");
-/* Flow control setting - default to FULL */
-static int em_fc_setting = e1000_fc_full;
-TUNABLE_INT("hw.em.fc_setting", &em_fc_setting);
+/* Energy efficient ethernet - default to OFF */
+static int eee_setting = 1;
+TUNABLE_INT("hw.em.eee_setting", &eee_setting);
+SYSCTL_INT(_hw_em, OID_AUTO, eee_setting, CTLFLAG_RDTUN, &eee_setting, 0,
+ "Enable Energy Efficient Ethernet");
/* Global used in WOL setup with multiport cards */
static int global_quad_port_a = 0;
+#ifdef DEV_NETMAP /* see ixgbe.c for details */
+#include <dev/netmap/if_em_netmap.h>
+#endif /* DEV_NETMAP */
+
/*********************************************************************
* Device identification routine
*
@@ -441,12 +481,19 @@ static int
em_attach(device_t dev)
{
struct adapter *adapter;
+ struct e1000_hw *hw;
int error = 0;
INIT_DEBUGOUT("em_attach: begin");
+ if (resource_disabled("em", device_get_unit(dev))) {
+ device_printf(dev, "Disabled by device hint\n");
+ return (ENXIO);
+ }
+
adapter = device_get_softc(dev);
adapter->dev = adapter->osdep.dev = dev;
+ hw = &adapter->hw;
EM_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
/* SYSCTL stuff */
@@ -460,6 +507,11 @@ em_attach(device_t dev)
OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
em_sysctl_debug_info, "I", "Debug Information");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "fc", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
+ em_set_flowcntl, "I", "Flow Control");
+
callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
/* Determine hardware and mac info */
@@ -478,11 +530,12 @@ em_attach(device_t dev)
** must happen after the MAC is
** identified
*/
- if ((adapter->hw.mac.type == e1000_ich8lan) ||
- (adapter->hw.mac.type == e1000_ich9lan) ||
- (adapter->hw.mac.type == e1000_ich10lan) ||
- (adapter->hw.mac.type == e1000_pchlan) ||
- (adapter->hw.mac.type == e1000_pch2lan)) {
+ if ((hw->mac.type == e1000_ich8lan) ||
+ (hw->mac.type == e1000_ich9lan) ||
+ (hw->mac.type == e1000_ich10lan) ||
+ (hw->mac.type == e1000_pchlan) ||
+ (hw->mac.type == e1000_pch2lan) ||
+ (hw->mac.type == e1000_pch_lpt)) {
int rid = EM_BAR_TYPE_FLASH;
adapter->flash = bus_alloc_resource_any(dev,
SYS_RES_MEMORY, &rid, RF_ACTIVE);
@@ -492,7 +545,7 @@ em_attach(device_t dev)
goto err_pci;
}
/* This is used in the shared code */
- adapter->hw.flash_address = (u8 *)adapter->flash;
+ hw->flash_address = (u8 *)adapter->flash;
adapter->osdep.flash_bus_space_tag =
rman_get_bustag(adapter->flash);
adapter->osdep.flash_bus_space_handle =
@@ -500,42 +553,37 @@ em_attach(device_t dev)
}
/* Do Shared Code initialization */
- if (e1000_setup_init_funcs(&adapter->hw, TRUE)) {
+ if (e1000_setup_init_funcs(hw, TRUE)) {
device_printf(dev, "Setup of Shared code failed\n");
error = ENXIO;
goto err_pci;
}
- e1000_get_bus_info(&adapter->hw);
+ e1000_get_bus_info(hw);
/* Set up some sysctls for the tunable interrupt delays */
em_add_int_delay_sysctl(adapter, "rx_int_delay",
"receive interrupt delay in usecs", &adapter->rx_int_delay,
- E1000_REGISTER(&adapter->hw, E1000_RDTR), em_rx_int_delay_dflt);
+ E1000_REGISTER(hw, E1000_RDTR), em_rx_int_delay_dflt);
em_add_int_delay_sysctl(adapter, "tx_int_delay",
"transmit interrupt delay in usecs", &adapter->tx_int_delay,
- E1000_REGISTER(&adapter->hw, E1000_TIDV), em_tx_int_delay_dflt);
+ E1000_REGISTER(hw, E1000_TIDV), em_tx_int_delay_dflt);
em_add_int_delay_sysctl(adapter, "rx_abs_int_delay",
"receive interrupt delay limit in usecs",
&adapter->rx_abs_int_delay,
- E1000_REGISTER(&adapter->hw, E1000_RADV),
+ E1000_REGISTER(hw, E1000_RADV),
em_rx_abs_int_delay_dflt);
em_add_int_delay_sysctl(adapter, "tx_abs_int_delay",
"transmit interrupt delay limit in usecs",
&adapter->tx_abs_int_delay,
- E1000_REGISTER(&adapter->hw, E1000_TADV),
+ E1000_REGISTER(hw, E1000_TADV),
em_tx_abs_int_delay_dflt);
/* Sysctl for limiting the amount of work done in the taskqueue */
- em_add_rx_process_limit(adapter, "rx_processing_limit",
+ em_set_sysctl_value(adapter, "rx_processing_limit",
"max number of rx packets to process", &adapter->rx_process_limit,
em_rx_process_limit);
- /* Sysctl for setting the interface flow control */
- em_set_flow_cntrl(adapter, "flow_control",
- "configure flow control",
- &adapter->fc_setting, em_fc_setting);
-
/*
* Validate number of transmit and receive descriptors. It
* must not exceed hardware maximum, and must be multiple
@@ -557,29 +605,29 @@ em_attach(device_t dev)
} else
adapter->num_rx_desc = em_rxd;
- adapter->hw.mac.autoneg = DO_AUTO_NEG;
- adapter->hw.phy.autoneg_wait_to_complete = FALSE;
- adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
+ hw->mac.autoneg = DO_AUTO_NEG;
+ hw->phy.autoneg_wait_to_complete = FALSE;
+ hw->phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
/* Copper options */
- if (adapter->hw.phy.media_type == e1000_media_type_copper) {
- adapter->hw.phy.mdix = AUTO_ALL_MODES;
- adapter->hw.phy.disable_polarity_correction = FALSE;
- adapter->hw.phy.ms_type = EM_MASTER_SLAVE;
+ if (hw->phy.media_type == e1000_media_type_copper) {
+ hw->phy.mdix = AUTO_ALL_MODES;
+ hw->phy.disable_polarity_correction = FALSE;
+ hw->phy.ms_type = EM_MASTER_SLAVE;
}
/*
* Set the frame limits assuming
* standard ethernet sized frames.
*/
- adapter->max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE;
- adapter->min_frame_size = ETH_ZLEN + ETHERNET_FCS_SIZE;
+ adapter->hw.mac.max_frame_size =
+ ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE;
/*
* This controls when hardware reports transmit completion
* status.
*/
- adapter->hw.mac.report_tx_early = 1;
+ hw->mac.report_tx_early = 1;
/*
** Get queue/ring memory
@@ -599,25 +647,34 @@ em_attach(device_t dev)
}
/* Check SOL/IDER usage */
- if (e1000_check_reset_block(&adapter->hw))
+ if (e1000_check_reset_block(hw))
device_printf(dev, "PHY reset is blocked"
" due to SOL/IDER session.\n");
+ /* Sysctl for setting Energy Efficient Ethernet */
+ hw->dev_spec.ich8lan.eee_disable = eee_setting;
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "eee_control", CTLTYPE_INT|CTLFLAG_RW,
+ adapter, 0, em_sysctl_eee, "I",
+ "Disable Energy Efficient Ethernet");
+
/*
** Start from a known state, this is
** important in reading the nvm and
** mac from that.
*/
- e1000_reset_hw(&adapter->hw);
+ e1000_reset_hw(hw);
+
/* Make sure we have a good EEPROM before we read from it */
- if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
+ if (e1000_validate_nvm_checksum(hw) < 0) {
/*
** Some PCI-E parts fail the first check due to
** the link being in sleep state, call it again,
** if it fails a second time its a real issue.
*/
- if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
+ if (e1000_validate_nvm_checksum(hw) < 0) {
device_printf(dev,
"The EEPROM Checksum Is Not Valid\n");
error = EIO;
@@ -626,14 +683,14 @@ em_attach(device_t dev)
}
/* Copy the permanent MAC address out of the EEPROM */
- if (e1000_read_mac_addr(&adapter->hw) < 0) {
+ if (e1000_read_mac_addr(hw) < 0) {
device_printf(dev, "EEPROM read error while reading MAC"
" address\n");
error = EIO;
goto err_late;
}
- if (!em_is_valid_ether_addr(adapter->hw.mac.addr)) {
+ if (!em_is_valid_ether_addr(hw->mac.addr)) {
device_printf(dev, "Invalid MAC address\n");
error = EIO;
goto err_late;
@@ -663,7 +720,7 @@ em_attach(device_t dev)
/* Initialize statistics */
em_update_stats_counters(adapter);
- adapter->hw.mac.get_link_status = 1;
+ hw->mac.get_link_status = 1;
em_update_link_status(adapter);
/* Register for VLAN events */
@@ -679,10 +736,14 @@ em_attach(device_t dev)
em_get_hw_control(adapter);
/* Tell the stack that the interface is not active */
- adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ adapter->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
adapter->led_dev = led_create(em_led_func, adapter,
device_get_nameunit(dev));
+#ifdef DEV_NETMAP
+ em_netmap_attach(adapter);
+#endif /* DEV_NETMAP */
INIT_DEBUGOUT("em_attach: end");
@@ -754,6 +815,10 @@ em_detach(device_t dev)
ether_ifdetach(adapter->ifp);
callout_drain(&adapter->timer);
+#ifdef DEV_NETMAP
+ netmap_detach(ifp);
+#endif /* DEV_NETMAP */
+
em_free_pci_resources(adapter);
bus_generic_detach(dev);
if_free(ifp);
@@ -802,29 +867,44 @@ static int
em_resume(device_t dev)
{
struct adapter *adapter = device_get_softc(dev);
+ struct tx_ring *txr = adapter->tx_rings;
struct ifnet *ifp = adapter->ifp;
EM_CORE_LOCK(adapter);
+ if (adapter->hw.mac.type == e1000_pch2lan)
+ e1000_resume_workarounds_pchlan(&adapter->hw);
em_init_locked(adapter);
em_init_manageability(adapter);
+
+ if ((ifp->if_flags & IFF_UP) &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) && adapter->link_active) {
+ for (int i = 0; i < adapter->num_queues; i++, txr++) {
+ EM_TX_LOCK(txr);
+#ifdef EM_MULTIQUEUE
+ if (!drbr_empty(ifp, txr->br))
+ em_mq_start_locked(ifp, txr, NULL);
+#else
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ em_start_locked(ifp, txr);
+#endif
+ EM_TX_UNLOCK(txr);
+ }
+ }
EM_CORE_UNLOCK(adapter);
- em_start(ifp);
return bus_generic_resume(dev);
}
+#ifdef EM_MULTIQUEUE
/*********************************************************************
- * Transmit entry point
+ * Multiqueue Transmit routines
*
- * em_start is called by the stack to initiate a transmit.
- * The driver will remain in this routine as long as there are
- * packets to transmit and transmit resources are available.
- * In case resources are not available stack is notified and
- * the packet is requeued.
+ * em_mq_start is called by the stack to initiate a transmit.
+ * however, if busy the driver can queue the request rather
+ * than do an immediate send. It is this that is an advantage
+ * in this driver, rather than also having multiple tx queues.
**********************************************************************/
-
-#ifdef EM_MULTIQUEUE
static int
em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
{
@@ -839,37 +919,30 @@ em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
return (err);
}
- /* Call cleanup if number of TX descriptors low */
- if (txr->tx_avail <= EM_TX_CLEANUP_THRESHOLD)
- em_txeof(txr);
-
enq = 0;
- if (m == NULL) {
- next = drbr_dequeue(ifp, txr->br);
- } else if (drbr_needs_enqueue(ifp, txr->br)) {
- if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
+ if (m != NULL) {
+ err = drbr_enqueue(ifp, txr->br, m);
+ if (err)
return (err);
- next = drbr_dequeue(ifp, txr->br);
- } else
- next = m;
+ }
/* Process the queue */
- while (next != NULL) {
+ while ((next = drbr_peek(ifp, txr->br)) != NULL) {
if ((err = em_xmit(txr, &next)) != 0) {
- if (next != NULL)
- err = drbr_enqueue(ifp, txr->br, next);
- break;
+ if (next == NULL)
+ drbr_advance(ifp, txr->br);
+ else
+ drbr_putback(ifp, txr->br, next);
+ break;
}
+ drbr_advance(ifp, txr->br);
enq++;
- drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);
+ ifp->if_obytes += next->m_pkthdr.len;
+ if (next->m_flags & M_MCAST)
+ ifp->if_omcasts++;
ETHER_BPF_MTAP(ifp, next);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
break;
- if (txr->tx_avail < EM_MAX_SCATTER) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
- next = drbr_dequeue(ifp, txr->br);
}
if (enq > 0) {
@@ -877,6 +950,11 @@ em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
txr->queue_status = EM_QUEUE_WORKING;
txr->watchdog_time = ticks;
}
+
+ if (txr->tx_avail < EM_MAX_SCATTER)
+ em_txeof(txr);
+ if (txr->tx_avail < EM_MAX_SCATTER)
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (err);
}
@@ -917,8 +995,7 @@ em_qflush(struct ifnet *ifp)
}
if_qflush(ifp);
}
-
-#endif /* EM_MULTIQUEUE */
+#else /* !EM_MULTIQUEUE */
static void
em_start_locked(struct ifnet *ifp, struct tx_ring *txr)
@@ -935,11 +1012,10 @@ em_start_locked(struct ifnet *ifp, struct tx_ring *txr)
if (!adapter->link_active)
return;
- /* Call cleanup if number of TX descriptors low */
- if (txr->tx_avail <= EM_TX_CLEANUP_THRESHOLD)
- em_txeof(txr);
-
while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+ /* Call cleanup if number of TX descriptors low */
+ if (txr->tx_avail <= EM_TX_CLEANUP_THRESHOLD)
+ em_txeof(txr);
if (txr->tx_avail < EM_MAX_SCATTER) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
@@ -954,7 +1030,6 @@ em_start_locked(struct ifnet *ifp, struct tx_ring *txr)
if (em_xmit(txr, &m_head)) {
if (m_head == NULL)
break;
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
break;
}
@@ -983,6 +1058,7 @@ em_start(struct ifnet *ifp)
}
return;
}
+#endif /* EM_MULTIQUEUE */
/*********************************************************************
* Ioctl entry point
@@ -997,11 +1073,12 @@ static int
em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct adapter *adapter = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *)data;
-#ifdef INET
- struct ifaddr *ifa = (struct ifaddr *)data;
+ struct ifreq *ifr = (struct ifreq *)data;
+#if defined(INET) || defined(INET6)
+ struct ifaddr *ifa = (struct ifaddr *)data;
#endif
- int error = 0;
+ bool avoid_reset = FALSE;
+ int error = 0;
if (adapter->in_detach)
return (error);
@@ -1009,23 +1086,26 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
switch (command) {
case SIOCSIFADDR:
#ifdef INET
- if (ifa->ifa_addr->sa_family == AF_INET) {
- /*
- * XXX
- * Since resetting hardware takes a very long time
- * and results in link renegotiation we only
- * initialize the hardware only when it is absolutely
- * required.
- */
+ if (ifa->ifa_addr->sa_family == AF_INET)
+ avoid_reset = TRUE;
+#endif
+#ifdef INET6
+ if (ifa->ifa_addr->sa_family == AF_INET6)
+ avoid_reset = TRUE;
+#endif
+ /*
+ ** Calling init results in link renegotiation,
+ ** so we avoid doing it when possible.
+ */
+ if (avoid_reset) {
ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- EM_CORE_LOCK(adapter);
- em_init_locked(adapter);
- EM_CORE_UNLOCK(adapter);
- }
- arp_ifinit(ifp, ifa);
- } else
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ em_init(adapter);
+#ifdef INET
+ if (!(ifp->if_flags & IFF_NOARP))
+ arp_ifinit(ifp, ifa);
#endif
+ } else
error = ether_ioctl(ifp, command, data);
break;
case SIOCSIFMTU:
@@ -1041,7 +1121,9 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
case e1000_ich9lan:
case e1000_ich10lan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
case e1000_82574:
+ case e1000_82583:
case e1000_80003es2lan: /* 9K Jumbo Frame size */
max_frame_size = 9234;
break;
@@ -1049,7 +1131,6 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
max_frame_size = 4096;
break;
/* Adapters that do not support jumbo frames */
- case e1000_82583:
case e1000_ich8lan:
max_frame_size = ETHER_MAX_LEN;
break;
@@ -1064,7 +1145,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
ifp->if_mtu = ifr->ifr_mtu;
- adapter->max_frame_size =
+ adapter->hw.mac.max_frame_size =
ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
em_init_locked(adapter);
EM_CORE_UNLOCK(adapter);
@@ -1104,11 +1185,6 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
break;
case SIOCSIFMEDIA:
- /*
- ** As the speed/duplex settings are being
- ** changed, we need to reset the PHY.
- */
- adapter->hw.phy.reset_disable = FALSE;
/* Check SOL/IDER usage */
EM_CORE_LOCK(adapter);
if (e1000_check_reset_block(&adapter->hw)) {
@@ -1167,6 +1243,10 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
reinit = 1;
}
+ if (mask & IFCAP_VLAN_HWTSO) {
+ ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
+ reinit = 1;
+ }
if ((mask & IFCAP_WOL) &&
(ifp->if_capabilities & IFCAP_WOL) != 0) {
if (mask & IFCAP_WOL_MCAST)
@@ -1205,7 +1285,6 @@ em_init_locked(struct adapter *adapter)
{
struct ifnet *ifp = adapter->ifp;
device_t dev = adapter->dev;
- u32 pba;
INIT_DEBUGOUT("em_init: begin");
@@ -1214,46 +1293,6 @@ em_init_locked(struct adapter *adapter)
em_disable_intr(adapter);
callout_stop(&adapter->timer);
- /*
- * Packet Buffer Allocation (PBA)
- * Writing PBA sets the receive portion of the buffer
- * the remainder is used for the transmit buffer.
- */
- switch (adapter->hw.mac.type) {
- /* Total Packet Buffer on these is 48K */
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
- pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */
- break;
- case e1000_82573: /* 82573: Total Packet Buffer is 32K */
- pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */
- break;
- case e1000_82574:
- case e1000_82583:
- pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */
- break;
- case e1000_ich8lan:
- pba = E1000_PBA_8K;
- break;
- case e1000_ich9lan:
- case e1000_ich10lan:
- pba = E1000_PBA_10K;
- break;
- case e1000_pchlan:
- case e1000_pch2lan:
- pba = E1000_PBA_26K;
- break;
- default:
- if (adapter->max_frame_size > 8192)
- pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */
- else
- pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */
- }
-
- INIT_DEBUGOUT1("em_init: pba=%dK",pba);
- E1000_WRITE_REG(&adapter->hw, E1000_PBA, pba);
-
/* Get the latest mac address, User can use a LAA */
bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr,
ETHER_ADDR_LEN);
@@ -1301,9 +1340,9 @@ em_init_locked(struct adapter *adapter)
** Figure out the desired mbuf
** pool for doing jumbos
*/
- if (adapter->max_frame_size <= 2048)
+ if (adapter->hw.mac.max_frame_size <= 2048)
adapter->rx_mbuf_sz = MCLBYTES;
- else if (adapter->max_frame_size <= 4096)
+ else if (adapter->hw.mac.max_frame_size <= 4096)
adapter->rx_mbuf_sz = MJUMPAGESIZE;
else
adapter->rx_mbuf_sz = MJUM9BYTES;
@@ -1332,6 +1371,7 @@ em_init_locked(struct adapter *adapter)
/* Don't lose promiscuous settings */
em_set_promisc(adapter);
+ /* Set the interface as ACTIVE */
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -1362,9 +1402,6 @@ em_init_locked(struct adapter *adapter)
/* AMT based hardware can now take control from firmware */
if (adapter->has_manage && adapter->has_amt)
em_get_hw_control(adapter);
-
- /* Don't reset the phy next time init gets called */
- adapter->hw.phy.reset_disable = TRUE;
}
static void
@@ -1483,12 +1520,10 @@ em_handle_que(void *context, int pending)
struct ifnet *ifp = adapter->ifp;
struct tx_ring *txr = adapter->tx_rings;
struct rx_ring *rxr = adapter->rx_rings;
- bool more;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- more = em_rxeof(rxr, adapter->rx_process_limit, NULL);
-
+ bool more = em_rxeof(rxr, adapter->rx_process_limit, NULL);
EM_TX_LOCK(txr);
em_txeof(txr);
#ifdef EM_MULTIQUEUE
@@ -1498,7 +1533,6 @@ em_handle_que(void *context, int pending)
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start_locked(ifp, txr);
#endif
- em_txeof(txr);
EM_TX_UNLOCK(txr);
if (more) {
taskqueue_enqueue(adapter->tq, &adapter->que_task);
@@ -1521,17 +1555,21 @@ em_msix_tx(void *arg)
{
struct tx_ring *txr = arg;
struct adapter *adapter = txr->adapter;
- bool more;
+ struct ifnet *ifp = adapter->ifp;
++txr->tx_irq;
EM_TX_LOCK(txr);
- more = em_txeof(txr);
+ em_txeof(txr);
+#ifdef EM_MULTIQUEUE
+ if (!drbr_empty(ifp, txr->br))
+ em_mq_start_locked(ifp, txr, NULL);
+#else
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ em_start_locked(ifp, txr);
+#endif
+ /* Reenable this interrupt */
+ E1000_WRITE_REG(&adapter->hw, E1000_IMS, txr->ims);
EM_TX_UNLOCK(txr);
- if (more)
- taskqueue_enqueue(txr->tq, &txr->tx_task);
- else
- /* Reenable this interrupt */
- E1000_WRITE_REG(&adapter->hw, E1000_IMS, txr->ims);
return;
}
@@ -1549,6 +1587,8 @@ em_msix_rx(void *arg)
bool more;
++rxr->rx_irq;
+ if (!(adapter->ifp->if_drv_flags & IFF_DRV_RUNNING))
+ return;
more = em_rxeof(rxr, adapter->rx_process_limit, NULL);
if (more)
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
@@ -1612,7 +1652,6 @@ em_handle_tx(void *context, int pending)
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start_locked(ifp, txr);
#endif
- em_txeof(txr);
E1000_WRITE_REG(&adapter->hw, E1000_IMS, txr->ims);
EM_TX_UNLOCK(txr);
}
@@ -1621,6 +1660,7 @@ static void
em_handle_link(void *context, int pending)
{
struct adapter *adapter = context;
+ struct tx_ring *txr = adapter->tx_rings;
struct ifnet *ifp = adapter->ifp;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
@@ -1632,6 +1672,19 @@ em_handle_link(void *context, int pending)
callout_reset(&adapter->timer, hz, em_local_timer, adapter);
E1000_WRITE_REG(&adapter->hw, E1000_IMS,
EM_MSIX_LINK | E1000_IMS_LSC);
+ if (adapter->link_active) {
+ for (int i = 0; i < adapter->num_queues; i++, txr++) {
+ EM_TX_LOCK(txr);
+#ifdef EM_MULTIQUEUE
+ if (!drbr_empty(ifp, txr->br))
+ em_mq_start_locked(ifp, txr, NULL);
+#else
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ em_start_locked(ifp, txr);
+#endif
+ EM_TX_UNLOCK(txr);
+ }
+ }
EM_CORE_UNLOCK(adapter);
}
@@ -1767,8 +1820,9 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
u32 txd_upper, txd_lower, txd_used, txd_saved;
int ip_off, poff;
int nsegs, i, j, first, last = 0;
- int error, do_tso, tso_desc = 0;
+ int error, do_tso, tso_desc = 0, remap = 1;
+retry:
m_head = *m_headp;
txd_upper = txd_lower = txd_used = txd_saved = 0;
do_tso = ((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0);
@@ -1792,7 +1846,7 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
if (do_tso || (m_head->m_next != NULL &&
m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD)) {
if (M_WRITABLE(*m_headp) == 0) {
- m_head = m_dup(*m_headp, M_DONTWAIT);
+ m_head = m_dup(*m_headp, M_NOWAIT);
m_freem(*m_headp);
if (m_head == NULL) {
*m_headp = NULL;
@@ -1906,10 +1960,10 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
* All other errors, in particular EINVAL, are fatal and prevent the
* mbuf chain from ever going through. Drop it and report error.
*/
- if (error == EFBIG) {
+ if (error == EFBIG && remap) {
struct mbuf *m;
- m = m_defrag(*m_headp, M_DONTWAIT);
+ m = m_defrag(*m_headp, M_NOWAIT);
if (m == NULL) {
adapter->mbuf_alloc_failed++;
m_freem(*m_headp);
@@ -1918,20 +1972,9 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
}
*m_headp = m;
- /* Try it again */
- error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
- *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
- if (error == ENOMEM) {
- adapter->no_tx_dma_setup++;
- return (error);
- } else if (error != 0) {
- adapter->no_tx_dma_setup++;
- m_freem(*m_headp);
- *m_headp = NULL;
- return (error);
- }
-
+ /* Try it again, but only once */
+ remap = 0;
+ goto retry;
} else if (error == ENOMEM) {
adapter->no_tx_dma_setup++;
return (error);
@@ -1971,6 +2014,14 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
em_transmit_checksum_setup(txr, m_head,
ip_off, ip, &txd_upper, &txd_lower);
+ if (m_head->m_flags & M_VLANTAG) {
+ /* Set the vlan id. */
+ txd_upper |=
+ (htole16(m_head->m_pkthdr.ether_vtag) << 16);
+ /* Tell hardware to add tag */
+ txd_lower |= htole32(E1000_TXD_CMD_VLE);
+ }
+
i = txr->next_avail_desc;
/* Set up our transmit descriptors */
@@ -2028,15 +2079,13 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
if (tso_desc) /* TSO used an extra for sentinel */
txr->tx_avail -= txd_used;
- if (m_head->m_flags & M_VLANTAG) {
- /* Set the vlan id. */
- ctxd->upper.fields.special =
- htole16(m_head->m_pkthdr.ether_vtag);
- /* Tell hardware to add tag */
- ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE);
- }
-
tx_buffer->m_head = m_head;
+ /*
+ ** Here we swap the map so the last descriptor,
+ ** which gets the completion interrupt has the
+ ** real map, and the first descriptor gets the
+ ** unused map from this descriptor.
+ */
tx_buffer_mapped->map = tx_buffer->map;
tx_buffer->map = map;
bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);
@@ -2187,6 +2236,8 @@ em_local_timer(void *arg)
struct adapter *adapter = arg;
struct ifnet *ifp = adapter->ifp;
struct tx_ring *txr = adapter->tx_rings;
+ struct rx_ring *rxr = adapter->rx_rings;
+ u32 trigger;
EM_CORE_LOCK_ASSERT(adapter);
@@ -2198,23 +2249,32 @@ em_local_timer(void *arg)
e1000_get_laa_state_82571(&adapter->hw))
e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
- /*
- ** Don't do TX watchdog check if we've been paused
- */
- if (adapter->pause_frames) {
- adapter->pause_frames = 0;
- goto out;
- }
+ /* Mask to use in the irq trigger */
+ if (adapter->msix_mem)
+ trigger = rxr->ims; /* RX for 82574 */
+ else
+ trigger = E1000_ICS_RXDMT0;
+
/*
** Check on the state of the TX queue(s), this
** can be done without the lock because its RO
** and the HUNG state will be static if set.
*/
- for (int i = 0; i < adapter->num_queues; i++, txr++)
- if (txr->queue_status == EM_QUEUE_HUNG)
+ for (int i = 0; i < adapter->num_queues; i++, txr++) {
+ if ((txr->queue_status == EM_QUEUE_HUNG) &&
+ (adapter->pause_frames == 0))
goto hung;
-out:
+ /* Schedule a TX tasklet if needed */
+ if (txr->tx_avail <= EM_MAX_SCATTER)
+ taskqueue_enqueue(txr->tq, &txr->tx_task);
+ }
+
+ adapter->pause_frames = 0;
callout_reset(&adapter->timer, hz, em_local_timer, adapter);
+#ifndef DEVICE_POLLING
+ /* Trigger an RX interrupt to guarantee mbuf refresh */
+ E1000_WRITE_REG(&adapter->hw, E1000_ICS, trigger);
+#endif
return;
hung:
/* Looks like we're hung */
@@ -2228,6 +2288,7 @@ hung:
txr->me, txr->tx_avail, txr->next_to_clean);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
adapter->watchdog_events++;
+ adapter->pause_frames = 0;
em_init_locked(adapter);
}
@@ -2326,7 +2387,8 @@ em_stop(void *arg)
callout_stop(&adapter->timer);
/* Tell the stack that the interface is no longer active */
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
/* Unarm watchdog timer. */
for (int i = 0; i < adapter->num_queues; i++, txr++) {
@@ -2422,6 +2484,7 @@ int
em_allocate_legacy(struct adapter *adapter)
{
device_t dev = adapter->dev;
+ struct tx_ring *txr = adapter->tx_rings;
int error, rid = 0;
/* Manually turn off all interrupts */
@@ -2443,11 +2506,17 @@ em_allocate_legacy(struct adapter *adapter)
* deferred processing contexts.
*/
TASK_INIT(&adapter->que_task, 0, em_handle_que, adapter);
- TASK_INIT(&adapter->link_task, 0, em_handle_link, adapter);
adapter->tq = taskqueue_create_fast("em_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &adapter->tq);
- taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
+ taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s que",
device_get_nameunit(adapter->dev));
+ /* Use a TX only tasklet for local timer */
+ TASK_INIT(&txr->tx_task, 0, em_handle_tx, txr);
+ txr->tq = taskqueue_create_fast("em_txq", M_NOWAIT,
+ taskqueue_thread_enqueue, &txr->tq);
+ taskqueue_start_threads(&txr->tq, 1, PI_NET, "%s txq",
+ device_get_nameunit(adapter->dev));
+ TASK_INIT(&adapter->link_task, 0, em_handle_link, adapter);
if ((error = bus_setup_intr(dev, adapter->res, INTR_TYPE_NET,
em_irq_fast, NULL, adapter, &adapter->tag)) != 0) {
device_printf(dev, "Failed to register fast interrupt "
@@ -2464,7 +2533,8 @@ em_allocate_legacy(struct adapter *adapter)
*
* Setup the MSIX Interrupt handlers
* This is not really Multiqueue, rather
- * its just multiple interrupt vectors.
+ * its just seperate interrupt vectors
+ * for TX, RX, and Link.
*
**********************************************************************/
int
@@ -2656,7 +2726,6 @@ em_setup_msix(struct adapter *adapter)
device_t dev = adapter->dev;
int val = 0;
-
/*
** Setup MSI/X for Hartwell: tests have shown
** use of two queues to be unstable, and to
@@ -2676,16 +2745,18 @@ em_setup_msix(struct adapter *adapter)
goto msi;
}
val = pci_msix_count(dev);
- if (val < 3) {
+ /* We only need 3 vectors */
+ if (val > 3)
+ val = 3;
+ if ((val != 3) && (val != 5)) {
bus_release_resource(dev, SYS_RES_MEMORY,
PCIR_BAR(EM_MSIX_BAR), adapter->msix_mem);
adapter->msix_mem = NULL;
device_printf(adapter->dev,
- "MSIX: insufficient vectors, using MSI\n");
+ "MSIX: incorrect vectors, using MSI\n");
goto msi;
}
- val = 3;
- adapter->num_queues = 1;
+
if (pci_alloc_msix(dev, &val) == 0) {
device_printf(adapter->dev,
"Using MSIX interrupts "
@@ -2720,6 +2791,7 @@ em_reset(struct adapter *adapter)
struct ifnet *ifp = adapter->ifp;
struct e1000_hw *hw = &adapter->hw;
u16 rx_buffer_size;
+ u32 pba;
INIT_DEBUGOUT("em_reset: begin");
@@ -2735,6 +2807,49 @@ em_reset(struct adapter *adapter)
}
/*
+ * Packet Buffer Allocation (PBA)
+ * Writing PBA sets the receive portion of the buffer
+ * the remainder is used for the transmit buffer.
+ */
+ switch (hw->mac.type) {
+ /* Total Packet Buffer on these is 48K */
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_80003es2lan:
+ pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */
+ break;
+ case e1000_82573: /* 82573: Total Packet Buffer is 32K */
+ pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */
+ break;
+ case e1000_82574:
+ case e1000_82583:
+ pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */
+ break;
+ case e1000_ich8lan:
+ pba = E1000_PBA_8K;
+ break;
+ case e1000_ich9lan:
+ case e1000_ich10lan:
+ /* Boost Receive side for jumbo frames */
+ if (adapter->hw.mac.max_frame_size > 4096)
+ pba = E1000_PBA_14K;
+ else
+ pba = E1000_PBA_10K;
+ break;
+ case e1000_pchlan:
+ case e1000_pch2lan:
+ case e1000_pch_lpt:
+ pba = E1000_PBA_26K;
+ break;
+ default:
+ if (adapter->hw.mac.max_frame_size > 8192)
+ pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */
+ else
+ pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */
+ }
+ E1000_WRITE_REG(&adapter->hw, E1000_PBA, pba);
+
+ /*
* These parameters control the automatic generation (Tx) and
* response (Rx) to Ethernet PAUSE frames.
* - High water mark should allow for at least two frames to be
@@ -2749,11 +2864,15 @@ em_reset(struct adapter *adapter)
* - The pause time is fairly large at 1000 x 512ns = 512 usec.
*/
rx_buffer_size = ((E1000_READ_REG(hw, E1000_PBA) & 0xffff) << 10 );
-
hw->fc.high_water = rx_buffer_size -
- roundup2(adapter->max_frame_size, 1024);
+ roundup2(adapter->hw.mac.max_frame_size, 1024);
hw->fc.low_water = hw->fc.high_water - 1500;
+ if (adapter->fc) /* locally set flow control value? */
+ hw->fc.requested_mode = adapter->fc;
+ else
+ hw->fc.requested_mode = e1000_fc_full;
+
if (hw->mac.type == e1000_80003es2lan)
hw->fc.pause_time = 0xFFFF;
else
@@ -2761,15 +2880,23 @@ em_reset(struct adapter *adapter)
hw->fc.send_xon = TRUE;
- /* Set Flow control, use the tunable location if sane */
- hw->fc.requested_mode = adapter->fc_setting;
-
- /* Workaround: no TX flow ctrl for PCH */
- if (hw->mac.type == e1000_pchlan)
+ /* Device specific overrides/settings */
+ switch (hw->mac.type) {
+ case e1000_pchlan:
+ /* Workaround: no TX flow ctrl for PCH */
hw->fc.requested_mode = e1000_fc_rx_pause;
-
- /* Override - settings for PCH2LAN, ya its magic :) */
- if (hw->mac.type == e1000_pch2lan) {
+ hw->fc.pause_time = 0xFFFF; /* override */
+ if (ifp->if_mtu > ETHERMTU) {
+ hw->fc.high_water = 0x3500;
+ hw->fc.low_water = 0x1500;
+ } else {
+ hw->fc.high_water = 0x5000;
+ hw->fc.low_water = 0x3000;
+ }
+ hw->fc.refresh_time = 0x1000;
+ break;
+ case e1000_pch2lan:
+ case e1000_pch_lpt:
hw->fc.high_water = 0x5C20;
hw->fc.low_water = 0x5048;
hw->fc.pause_time = 0x0650;
@@ -2779,13 +2906,26 @@ em_reset(struct adapter *adapter)
E1000_WRITE_REG(hw, E1000_PBA, 12);
else
E1000_WRITE_REG(hw, E1000_PBA, 26);
+ break;
+ case e1000_ich9lan:
+ case e1000_ich10lan:
+ if (ifp->if_mtu > ETHERMTU) {
+ hw->fc.high_water = 0x2800;
+ hw->fc.low_water = hw->fc.high_water - 8;
+ break;
+ }
+ /* else fall thru */
+ default:
+ if (hw->mac.type == e1000_80003es2lan)
+ hw->fc.pause_time = 0xFFFF;
+ break;
}
/* Issue a global reset */
e1000_reset_hw(hw);
E1000_WRITE_REG(hw, E1000_WUC, 0);
em_disable_aspm(adapter);
-
+ /* and a re-init */
if (e1000_init_hw(hw) < 0) {
device_printf(dev, "Hardware Initialization Failed\n");
return;
@@ -2815,43 +2955,40 @@ em_setup_interface(device_t dev, struct adapter *adapter)
return (-1);
}
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_mtu = ETHERMTU;
ifp->if_init = em_init;
ifp->if_softc = adapter;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = em_ioctl;
+#ifdef EM_MULTIQUEUE
+ /* Multiqueue stack interface */
+ ifp->if_transmit = em_mq_start;
+ ifp->if_qflush = em_qflush;
+#else
ifp->if_start = em_start;
IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1);
ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1;
IFQ_SET_READY(&ifp->if_snd);
+#endif
ether_ifattach(ifp, adapter->hw.mac.addr);
ifp->if_capabilities = ifp->if_capenable = 0;
-#ifdef EM_MULTIQUEUE
- /* Multiqueue tx functions */
- ifp->if_transmit = em_mq_start;
- ifp->if_qflush = em_qflush;
-#endif
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
- ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
-
- /* Enable TSO by default, can disable with ifconfig */
ifp->if_capabilities |= IFCAP_TSO4;
- ifp->if_capenable |= IFCAP_TSO4;
-
/*
* Tell the upper layer(s) we
* support full VLAN capability
*/
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
- ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
- ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
+ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
+ | IFCAP_VLAN_HWTSO
+ | IFCAP_VLAN_MTU;
+ ifp->if_capenable = ifp->if_capabilities;
/*
- ** Dont turn this on by default, if vlans are
+ ** Don't turn this on by default, if vlans are
** created on another pseudo device (eg. lagg)
** then vlan events are not passed thru, breaking
** operation, but with HW FILTER off it works. If
@@ -3188,9 +3325,17 @@ em_setup_transmit_ring(struct tx_ring *txr)
struct adapter *adapter = txr->adapter;
struct em_buffer *txbuf;
int i;
+#ifdef DEV_NETMAP
+ struct netmap_adapter *na = NA(adapter->ifp);
+ struct netmap_slot *slot;
+#endif /* DEV_NETMAP */
/* Clear the old descriptor contents */
EM_TX_LOCK(txr);
+#ifdef DEV_NETMAP
+ slot = netmap_reset(na, NR_TX, txr->me, 0);
+#endif /* DEV_NETMAP */
+
bzero((void *)txr->tx_base,
(sizeof(struct e1000_tx_desc)) * adapter->num_tx_desc);
/* Reset indices */
@@ -3207,6 +3352,19 @@ em_setup_transmit_ring(struct tx_ring *txr)
m_freem(txbuf->m_head);
txbuf->m_head = NULL;
}
+#ifdef DEV_NETMAP
+ if (slot) {
+ int si = netmap_idx_n2k(&na->tx_rings[txr->me], i);
+ uint64_t paddr;
+ void *addr;
+
+ addr = PNMB(slot + si, &paddr);
+ txr->tx_base[i].buffer_addr = htole64(paddr);
+ /* reload the map for netmap mode */
+ netmap_load_map(txr->txtag, txbuf->map, addr);
+ }
+#endif /* DEV_NETMAP */
+
/* clear the watch index */
txbuf->next_eop = -1;
}
@@ -3279,11 +3437,6 @@ em_initialize_transmit_unit(struct adapter *adapter)
/* Set the default values for the Tx Inter Packet Gap timer */
switch (adapter->hw.mac.type) {
- case e1000_82542:
- tipg = DEFAULT_82542_TIPG_IPGT;
- tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
- tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
- break;
case e1000_80003es2lan:
tipg = DEFAULT_82543_TIPG_IPGR1;
tipg |= DEFAULT_80003ES2LAN_TIPG_IPGR2 <<
@@ -3647,7 +3800,7 @@ em_tso_setup(struct tx_ring *txr, struct mbuf *mp, int ip_off,
* tx_buffer is put back on the free queue.
*
**********************************************************************/
-static bool
+static void
em_txeof(struct tx_ring *txr)
{
struct adapter *adapter = txr->adapter;
@@ -3657,11 +3810,24 @@ em_txeof(struct tx_ring *txr)
struct ifnet *ifp = adapter->ifp;
EM_TX_LOCK_ASSERT(txr);
+#ifdef DEV_NETMAP
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(ifp);
+
+ selwakeuppri(&na->tx_rings[txr->me].si, PI_NET);
+ EM_TX_UNLOCK(txr);
+ EM_CORE_LOCK(adapter);
+ selwakeuppri(&na->tx_si, PI_NET);
+ EM_CORE_UNLOCK(adapter);
+ EM_TX_LOCK(txr);
+ return;
+ }
+#endif /* DEV_NETMAP */
/* No work, make sure watchdog is off */
if (txr->tx_avail == adapter->num_tx_desc) {
txr->queue_status = EM_QUEUE_IDLE;
- return (FALSE);
+ return;
}
processed = 0;
@@ -3738,19 +3904,19 @@ em_txeof(struct tx_ring *txr)
txr->queue_status = EM_QUEUE_HUNG;
/*
- * If we have enough room, clear IFF_DRV_OACTIVE
+ * If we have a minimum free, clear IFF_DRV_OACTIVE
* to tell the stack that it is OK to send packets.
+ * Notice that all writes of OACTIVE happen under the
+ * TX lock which, with a single queue, guarantees
+ * sanity.
*/
- if (txr->tx_avail > EM_TX_CLEANUP_THRESHOLD) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- /* Disable watchdog if all clean */
- if (txr->tx_avail == adapter->num_tx_desc) {
- txr->queue_status = EM_QUEUE_IDLE;
- return (FALSE);
- }
- }
+ if (txr->tx_avail >= EM_MAX_SCATTER)
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- return (TRUE);
+ /* Disable watchdog if all clean */
+ if (txr->tx_avail == adapter->num_tx_desc) {
+ txr->queue_status = EM_QUEUE_IDLE;
+ }
}
@@ -3766,14 +3932,22 @@ em_refresh_mbufs(struct rx_ring *rxr, int limit)
struct mbuf *m;
bus_dma_segment_t segs[1];
struct em_buffer *rxbuf;
- int i, error, nsegs, cleaned;
+ int i, j, error, nsegs;
+ bool cleaned = FALSE;
+
+ i = j = rxr->next_to_refresh;
+ /*
+ ** Get one descriptor beyond
+ ** our work mark to control
+ ** the loop.
+ */
+ if (++j == adapter->num_rx_desc)
+ j = 0;
- i = rxr->next_to_refresh;
- cleaned = -1;
- while (i != limit) {
+ while (j != limit) {
rxbuf = &rxr->rx_buffers[i];
if (rxbuf->m_head == NULL) {
- m = m_getjcl(M_DONTWAIT, MT_DATA,
+ m = m_getjcl(M_NOWAIT, MT_DATA,
M_PKTHDR, adapter->rx_mbuf_sz);
/*
** If we have a temporary resource shortage
@@ -3804,21 +3978,22 @@ em_refresh_mbufs(struct rx_ring *rxr, int limit)
bus_dmamap_sync(rxr->rxtag,
rxbuf->map, BUS_DMASYNC_PREREAD);
rxr->rx_base[i].buffer_addr = htole64(segs[0].ds_addr);
+ cleaned = TRUE;
- cleaned = i;
- /* Calculate next index */
- if (++i == adapter->num_rx_desc)
- i = 0;
+ i = j; /* Next is precalulated for us */
rxr->next_to_refresh = i;
+ /* Calculate next controlling index */
+ if (++j == adapter->num_rx_desc)
+ j = 0;
}
update:
/*
** Update the tail pointer only if,
** and as far as we have refreshed.
*/
- if (cleaned != -1) /* Update tail index */
+ if (cleaned)
E1000_WRITE_REG(&adapter->hw,
- E1000_RDT(rxr->me), cleaned);
+ E1000_RDT(rxr->me), rxr->next_to_refresh);
return;
}
@@ -3896,7 +4071,11 @@ em_setup_receive_ring(struct rx_ring *rxr)
struct adapter *adapter = rxr->adapter;
struct em_buffer *rxbuf;
bus_dma_segment_t seg[1];
- int rsize, nsegs, error;
+ int rsize, nsegs, error = 0;
+#ifdef DEV_NETMAP
+ struct netmap_adapter *na = NA(adapter->ifp);
+ struct netmap_slot *slot;
+#endif
/* Clear the ring contents */
@@ -3904,6 +4083,9 @@ em_setup_receive_ring(struct rx_ring *rxr)
rsize = roundup2(adapter->num_rx_desc *
sizeof(struct e1000_rx_desc), EM_DBA_ALIGN);
bzero((void *)rxr->rx_base, rsize);
+#ifdef DEV_NETMAP
+ slot = netmap_reset(na, NR_RX, 0, 0);
+#endif
/*
** Free current RX buffer structs and their mbufs
@@ -3915,17 +4097,32 @@ em_setup_receive_ring(struct rx_ring *rxr)
BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(rxr->rxtag, rxbuf->map);
m_freem(rxbuf->m_head);
+ rxbuf->m_head = NULL; /* mark as freed */
}
}
/* Now replenish the mbufs */
- for (int j = 0; j != adapter->num_rx_desc; ++j) {
-
+ for (int j = 0; j != adapter->num_rx_desc; ++j) {
rxbuf = &rxr->rx_buffers[j];
- rxbuf->m_head = m_getjcl(M_DONTWAIT, MT_DATA,
+#ifdef DEV_NETMAP
+ if (slot) {
+ int si = netmap_idx_n2k(&na->rx_rings[rxr->me], j);
+ uint64_t paddr;
+ void *addr;
+
+ addr = PNMB(slot + si, &paddr);
+ netmap_load_map(rxr->rxtag, rxbuf->map, addr);
+ /* Update descriptor */
+ rxr->rx_base[j].buffer_addr = htole64(paddr);
+ continue;
+ }
+#endif /* DEV_NETMAP */
+ rxbuf->m_head = m_getjcl(M_NOWAIT, MT_DATA,
M_PKTHDR, adapter->rx_mbuf_sz);
- if (rxbuf->m_head == NULL)
- return (ENOBUFS);
+ if (rxbuf->m_head == NULL) {
+ error = ENOBUFS;
+ goto fail;
+ }
rxbuf->m_head->m_len = adapter->rx_mbuf_sz;
rxbuf->m_head->m_flags &= ~M_HASFCS; /* we strip it */
rxbuf->m_head->m_pkthdr.len = adapter->rx_mbuf_sz;
@@ -3937,7 +4134,7 @@ em_setup_receive_ring(struct rx_ring *rxr)
if (error != 0) {
m_freem(rxbuf->m_head);
rxbuf->m_head = NULL;
- return (error);
+ goto fail;
}
bus_dmamap_sync(rxr->rxtag,
rxbuf->map, BUS_DMASYNC_PREREAD);
@@ -3945,17 +4142,14 @@ em_setup_receive_ring(struct rx_ring *rxr)
/* Update descriptor */
rxr->rx_base[j].buffer_addr = htole64(seg[0].ds_addr);
}
-
-
- /* Setup our descriptor indices */
rxr->next_to_check = 0;
rxr->next_to_refresh = 0;
-
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+fail:
EM_RX_UNLOCK(rxr);
- return (0);
+ return (error);
}
/*********************************************************************
@@ -3967,9 +4161,9 @@ static int
em_setup_receive_structures(struct adapter *adapter)
{
struct rx_ring *rxr = adapter->rx_rings;
- int j;
+ int q;
- for (j = 0; j < adapter->num_queues; j++, rxr++)
+ for (q = 0; q < adapter->num_queues; q++, rxr++)
if (em_setup_receive_ring(rxr))
goto fail;
@@ -3978,9 +4172,9 @@ fail:
/*
* Free RX buffers allocated so far, we will only handle
* the rings that completed, the failing case will have
- * cleaned up for itself. 'j' failed, so its the terminus.
+ * cleaned up for itself. 'q' failed, so its the terminus.
*/
- for (int i = 0; i < j; ++i) {
+ for (int i = 0; i < q; ++i) {
rxr = &adapter->rx_rings[i];
for (int n = 0; n < adapter->num_rx_desc; n++) {
struct em_buffer *rxbuf;
@@ -3993,6 +4187,8 @@ fail:
rxbuf->m_head = NULL;
}
}
+ rxr->next_to_check = 0;
+ rxr->next_to_refresh = 0;
}
return (ENOBUFS);
@@ -4048,6 +4244,8 @@ em_free_receive_buffers(struct rx_ring *rxr)
}
free(rxr->rx_buffers, M_DEVBUF);
rxr->rx_buffers = NULL;
+ rxr->next_to_check = 0;
+ rxr->next_to_refresh = 0;
}
if (rxr->rxtag != NULL) {
@@ -4083,7 +4281,9 @@ em_initialize_receive_unit(struct adapter *adapter)
* up the descriptor ring
*/
rctl = E1000_READ_REG(hw, E1000_RCTL);
- E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+ /* Do not disable if ever enabled on this hardware */
+ if ((hw->mac.type != e1000_82574) && (hw->mac.type != e1000_82583))
+ E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
E1000_WRITE_REG(&adapter->hw, E1000_RADV,
adapter->rx_abs_int_delay.value);
@@ -4097,14 +4297,13 @@ em_initialize_receive_unit(struct adapter *adapter)
** When using MSIX interrupts we need to throttle
** using the EITR register (82574 only)
*/
- if (hw->mac.type == e1000_82574)
+ if (hw->mac.type == e1000_82574) {
for (int i = 0; i < 4; i++)
E1000_WRITE_REG(hw, E1000_EITR_82574(i),
DEFAULT_ITR);
-
- /* Disable accelerated ackknowledge */
- if (adapter->hw.mac.type == e1000_82574)
+ /* Disable accelerated acknowledge */
E1000_WRITE_REG(hw, E1000_RFCTL, E1000_RFCTL_ACK_DIS);
+ }
if (ifp->if_capenable & IFCAP_RXCSUM) {
rxcsum = E1000_READ_REG(hw, E1000_RXCSUM);
@@ -4131,20 +4330,34 @@ em_initialize_receive_unit(struct adapter *adapter)
E1000_WRITE_REG(hw, E1000_RDBAL(i), (u32)bus_addr);
/* Setup the Head and Tail Descriptor Pointers */
E1000_WRITE_REG(hw, E1000_RDH(i), 0);
+#ifdef DEV_NETMAP
+ /*
+ * an init() while a netmap client is active must
+ * preserve the rx buffers passed to userspace.
+ * In this driver it means we adjust RDT to
+ * something different from na->num_rx_desc - 1.
+ */
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(adapter->ifp);
+ struct netmap_kring *kring = &na->rx_rings[i];
+ int t = na->num_rx_desc - 1 - kring->nr_hwavail;
+
+ E1000_WRITE_REG(hw, E1000_RDT(i), t);
+ } else
+#endif /* DEV_NETMAP */
E1000_WRITE_REG(hw, E1000_RDT(i), adapter->num_rx_desc - 1);
}
- /* Set early receive threshold on appropriate hw */
+ /* Set PTHRESH for improved jumbo performance */
if (((adapter->hw.mac.type == e1000_ich9lan) ||
(adapter->hw.mac.type == e1000_pch2lan) ||
(adapter->hw.mac.type == e1000_ich10lan)) &&
(ifp->if_mtu > ETHERMTU)) {
u32 rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0));
E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 3);
- E1000_WRITE_REG(hw, E1000_ERT, 0x100 | (1 << 13));
}
- if (adapter->hw.mac.type == e1000_pch2lan) {
+ if (adapter->hw.mac.type >= e1000_pch2lan) {
if (ifp->if_mtu > ETHERMTU)
e1000_lv_jumbo_workaround_ich8lan(hw, TRUE);
else
@@ -4208,6 +4421,20 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
EM_RX_LOCK(rxr);
+#ifdef DEV_NETMAP
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(ifp);
+
+ na->rx_rings[rxr->me].nr_kflags |= NKR_PENDINTR;
+ selwakeuppri(&na->rx_rings[rxr->me].si, PI_NET);
+ EM_RX_UNLOCK(rxr);
+ EM_CORE_LOCK(adapter);
+ selwakeuppri(&na->rx_si, PI_NET);
+ EM_CORE_UNLOCK(adapter);
+ return (0);
+ }
+#endif /* DEV_NETMAP */
+
for (i = rxr->next_to_check, processed = 0; count != 0;) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
@@ -4228,7 +4455,7 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
if ((cur->errors & E1000_RXD_ERR_FRAME_ERR_MASK) ||
(rxr->discard == TRUE)) {
- ifp->if_ierrors++;
+ adapter->dropped_pkts++;
++rxr->rx_discarded;
if (!eop) /* Catch subsequent segs */
rxr->discard = TRUE;
@@ -4264,21 +4491,16 @@ em_rxeof(struct rx_ring *rxr, int count, int *done)
ifp->if_ipackets++;
em_receive_checksum(cur, sendmp);
#ifndef __NO_STRICT_ALIGNMENT
- if (adapter->max_frame_size >
+ if (adapter->hw.mac.max_frame_size >
(MCLBYTES - ETHER_ALIGN) &&
em_fixup_rx(rxr) != 0)
goto skip;
#endif
if (status & E1000_RXD_STAT_VP) {
sendmp->m_pkthdr.ether_vtag =
- (le16toh(cur->special) &
- E1000_RXD_SPC_VLAN_MASK);
+ le16toh(cur->special);
sendmp->m_flags |= M_VLANTAG;
}
-#ifdef EM_MULTIQUEUE
- sendmp->m_pkthdr.flowid = rxr->msix;
- sendmp->m_flags |= M_FLOWID;
-#endif
#ifndef __NO_STRICT_ALIGNMENT
skip:
#endif
@@ -4311,7 +4533,8 @@ next_desc:
}
/* Catch any remaining refresh work */
- em_refresh_mbufs(rxr, i);
+ if (e1000_rx_unrefreshed(rxr))
+ em_refresh_mbufs(rxr, i);
rxr->next_to_check = i;
if (done != NULL)
@@ -4373,7 +4596,7 @@ em_fixup_rx(struct rx_ring *rxr)
bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len);
m->m_data += ETHER_HDR_LEN;
} else {
- MGETHDR(n, M_DONTWAIT, MT_DATA);
+ MGETHDR(n, M_NOWAIT, MT_DATA);
if (n != NULL) {
bcopy(m->m_data, n->m_data, ETHER_HDR_LEN);
m->m_data += ETHER_HDR_LEN;
@@ -4739,7 +4962,7 @@ em_enable_wakeup(device_t dev)
u32 pmc, ctrl, ctrl_ext, rctl;
u16 status;
- if ((pci_find_extcap(dev, PCIY_PMG, &pmc) != 0))
+ if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0))
return;
/* Advertise the wakeup capability */
@@ -4751,10 +4974,8 @@ em_enable_wakeup(device_t dev)
if ((adapter->hw.mac.type == e1000_ich8lan) ||
(adapter->hw.mac.type == e1000_pchlan) ||
(adapter->hw.mac.type == e1000_ich9lan) ||
- (adapter->hw.mac.type == e1000_ich10lan)) {
- e1000_disable_gig_wol_ich8lan(&adapter->hw);
- e1000_hv_phy_powerdown_workaround_ich8lan(&adapter->hw);
- }
+ (adapter->hw.mac.type == e1000_ich10lan))
+ e1000_suspend_workarounds_ich8lan(&adapter->hw);
/* Keep the laser running on Fiber adapters */
if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
@@ -4909,15 +5130,15 @@ em_disable_aspm(struct adapter *adapter)
default:
return;
}
- if (pci_find_extcap(dev, PCIY_EXPRESS, &base) != 0)
+ if (pci_find_cap(dev, PCIY_EXPRESS, &base) != 0)
return;
- reg = base + PCIR_EXPRESS_LINK_CAP;
+ reg = base + PCIER_LINK_CAP;
link_cap = pci_read_config(dev, reg, 2);
- if ((link_cap & PCIM_LINK_CAP_ASPM) == 0)
+ if ((link_cap & PCIEM_LINK_CAP_ASPM) == 0)
return;
- reg = base + PCIR_EXPRESS_LINK_CTL;
+ reg = base + PCIER_LINK_CTL;
link_ctrl = pci_read_config(dev, reg, 2);
- link_ctrl &= 0xFFFC; /* turn off bit 1 and 2 */
+ link_ctrl &= ~PCIEM_LINK_CTL_ASPMC;
pci_write_config(dev, reg, link_ctrl, 2);
return;
}
@@ -5072,8 +5293,8 @@ em_add_hw_stats(struct adapter *adapter)
char namebuf[QUEUE_NAME_LEN];
/* Driver Statistics */
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "link_irq",
- CTLFLAG_RD, &adapter->link_irq, 0,
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
+ CTLFLAG_RD, &adapter->link_irq,
"Link MSIX IRQ Handled");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail",
CTLFLAG_RD, &adapter->mbuf_alloc_failed,
@@ -5095,11 +5316,11 @@ em_add_hw_stats(struct adapter *adapter)
"Watchdog timeouts");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control",
- CTLFLAG_RD, adapter, E1000_CTRL,
+ CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_CTRL,
em_sysctl_reg_handler, "IU",
"Device Control Register");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_control",
- CTLFLAG_RD, adapter, E1000_RCTL,
+ CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RCTL,
em_sysctl_reg_handler, "IU",
"Receiver Control Register");
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water",
@@ -5116,11 +5337,13 @@ em_add_hw_stats(struct adapter *adapter)
queue_list = SYSCTL_CHILDREN(queue_node);
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head",
- CTLFLAG_RD, adapter, E1000_TDH(txr->me),
+ CTLTYPE_UINT | CTLFLAG_RD, adapter,
+ E1000_TDH(txr->me),
em_sysctl_reg_handler, "IU",
"Transmit Descriptor Head");
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail",
- CTLFLAG_RD, adapter, E1000_TDT(txr->me),
+ CTLTYPE_UINT | CTLFLAG_RD, adapter,
+ E1000_TDT(txr->me),
em_sysctl_reg_handler, "IU",
"Transmit Descriptor Tail");
SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tx_irq",
@@ -5131,11 +5354,13 @@ em_add_hw_stats(struct adapter *adapter)
"Queue No Descriptor Available");
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head",
- CTLFLAG_RD, adapter, E1000_RDH(rxr->me),
+ CTLTYPE_UINT | CTLFLAG_RD, adapter,
+ E1000_RDH(rxr->me),
em_sysctl_reg_handler, "IU",
"Receive Descriptor Head");
SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail",
- CTLFLAG_RD, adapter, E1000_RDT(rxr->me),
+ CTLTYPE_UINT | CTLFLAG_RD, adapter,
+ E1000_RDT(rxr->me),
em_sysctl_reg_handler, "IU",
"Receive Descriptor Tail");
SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "rx_irq",
@@ -5149,147 +5374,147 @@ em_add_hw_stats(struct adapter *adapter)
CTLFLAG_RD, NULL, "Statistics");
stat_list = SYSCTL_CHILDREN(stat_node);
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "excess_coll",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll",
CTLFLAG_RD, &stats->ecol,
"Excessive collisions");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "single_coll",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "single_coll",
CTLFLAG_RD, &stats->scc,
"Single collisions");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "multiple_coll",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "multiple_coll",
CTLFLAG_RD, &stats->mcc,
"Multiple collisions");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "late_coll",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "late_coll",
CTLFLAG_RD, &stats->latecol,
"Late collisions");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "collision_count",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "collision_count",
CTLFLAG_RD, &stats->colc,
"Collision Count");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "symbol_errors",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "symbol_errors",
CTLFLAG_RD, &adapter->stats.symerrs,
"Symbol Errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "sequence_errors",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "sequence_errors",
CTLFLAG_RD, &adapter->stats.sec,
"Sequence Errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "defer_count",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "defer_count",
CTLFLAG_RD, &adapter->stats.dc,
"Defer Count");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "missed_packets",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "missed_packets",
CTLFLAG_RD, &adapter->stats.mpc,
"Missed Packets");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_no_buff",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_no_buff",
CTLFLAG_RD, &adapter->stats.rnbc,
"Receive No Buffers");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_undersize",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersize",
CTLFLAG_RD, &adapter->stats.ruc,
"Receive Undersize");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
CTLFLAG_RD, &adapter->stats.rfc,
"Fragmented Packets Received ");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_oversize",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversize",
CTLFLAG_RD, &adapter->stats.roc,
"Oversized Packets Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_jabber",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabber",
CTLFLAG_RD, &adapter->stats.rjc,
"Recevied Jabber");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_errs",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_errs",
CTLFLAG_RD, &adapter->stats.rxerrc,
"Receive Errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "crc_errs",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs",
CTLFLAG_RD, &adapter->stats.crcerrs,
"CRC errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "alignment_errs",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "alignment_errs",
CTLFLAG_RD, &adapter->stats.algnerrc,
"Alignment Errors");
/* On 82575 these are collision counts */
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs",
CTLFLAG_RD, &adapter->stats.cexterr,
"Collision/Carrier extension errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
CTLFLAG_RD, &adapter->stats.xonrxc,
"XON Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xon_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd",
CTLFLAG_RD, &adapter->stats.xontxc,
"XON Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
CTLFLAG_RD, &adapter->stats.xoffrxc,
"XOFF Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
CTLFLAG_RD, &adapter->stats.xofftxc,
"XOFF Transmitted");
/* Packet Reception Stats */
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd",
CTLFLAG_RD, &adapter->stats.tpr,
"Total Packets Received ");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
CTLFLAG_RD, &adapter->stats.gprc,
"Good Packets Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd",
CTLFLAG_RD, &adapter->stats.bprc,
"Broadcast Packets Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd",
CTLFLAG_RD, &adapter->stats.mprc,
"Multicast Packets Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
CTLFLAG_RD, &adapter->stats.prc64,
"64 byte frames received ");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
CTLFLAG_RD, &adapter->stats.prc127,
"65-127 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
CTLFLAG_RD, &adapter->stats.prc255,
"128-255 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
CTLFLAG_RD, &adapter->stats.prc511,
"256-511 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
CTLFLAG_RD, &adapter->stats.prc1023,
"512-1023 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
CTLFLAG_RD, &adapter->stats.prc1522,
"1023-1522 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd",
CTLFLAG_RD, &adapter->stats.gorc,
"Good Octets Received");
/* Packet Transmission Stats */
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
CTLFLAG_RD, &adapter->stats.gotc,
"Good Octets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
CTLFLAG_RD, &adapter->stats.tpt,
"Total Packets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
CTLFLAG_RD, &adapter->stats.gptc,
"Good Packets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
CTLFLAG_RD, &adapter->stats.bptc,
"Broadcast Packets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
CTLFLAG_RD, &adapter->stats.mptc,
"Multicast Packets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
CTLFLAG_RD, &adapter->stats.ptc64,
"64 byte frames transmitted ");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
CTLFLAG_RD, &adapter->stats.ptc127,
"65-127 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
CTLFLAG_RD, &adapter->stats.ptc255,
"128-255 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
CTLFLAG_RD, &adapter->stats.ptc511,
"256-511 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
CTLFLAG_RD, &adapter->stats.ptc1023,
"512-1023 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
CTLFLAG_RD, &adapter->stats.ptc1522,
"1024-1522 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tso_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_txd",
CTLFLAG_RD, &adapter->stats.tsctc,
"TSO Contexts Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail",
CTLFLAG_RD, &adapter->stats.tsctfc,
"TSO Contexts Failed");
@@ -5300,39 +5525,39 @@ em_add_hw_stats(struct adapter *adapter)
CTLFLAG_RD, NULL, "Interrupt Statistics");
int_list = SYSCTL_CHILDREN(int_node);
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "asserts",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "asserts",
CTLFLAG_RD, &adapter->stats.iac,
"Interrupt Assertion Count");
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_pkt_timer",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_pkt_timer",
CTLFLAG_RD, &adapter->stats.icrxptc,
"Interrupt Cause Rx Pkt Timer Expire Count");
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_abs_timer",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_abs_timer",
CTLFLAG_RD, &adapter->stats.icrxatc,
"Interrupt Cause Rx Abs Timer Expire Count");
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_pkt_timer",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "tx_pkt_timer",
CTLFLAG_RD, &adapter->stats.ictxptc,
"Interrupt Cause Tx Pkt Timer Expire Count");
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_abs_timer",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "tx_abs_timer",
CTLFLAG_RD, &adapter->stats.ictxatc,
"Interrupt Cause Tx Abs Timer Expire Count");
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_queue_empty",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "tx_queue_empty",
CTLFLAG_RD, &adapter->stats.ictxqec,
"Interrupt Cause Tx Queue Empty Count");
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "tx_queue_min_thresh",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "tx_queue_min_thresh",
CTLFLAG_RD, &adapter->stats.ictxqmtc,
"Interrupt Cause Tx Queue Min Thresh Count");
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_desc_min_thresh",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_desc_min_thresh",
CTLFLAG_RD, &adapter->stats.icrxdmtc,
"Interrupt Cause Rx Desc Min Thresh Count");
- SYSCTL_ADD_QUAD(ctx, int_list, OID_AUTO, "rx_overrun",
+ SYSCTL_ADD_UQUAD(ctx, int_list, OID_AUTO, "rx_overrun",
CTLFLAG_RD, &adapter->stats.icrxoc,
"Interrupt Cause Receiver Overrun Count");
}
@@ -5347,7 +5572,7 @@ em_add_hw_stats(struct adapter *adapter)
static int
em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS)
{
- struct adapter *adapter;
+ struct adapter *adapter = (struct adapter *)arg1;
int error;
int result;
@@ -5362,10 +5587,8 @@ em_sysctl_nvm_info(SYSCTL_HANDLER_ARGS)
* first 32 16-bit words of the EEPROM to
* the screen.
*/
- if (result == 1) {
- adapter = (struct adapter *)arg1;
+ if (result == 1)
em_print_nvm_info(adapter);
- }
return (error);
}
@@ -5446,7 +5669,7 @@ em_add_int_delay_sysctl(struct adapter *adapter, const char *name,
}
static void
-em_add_rx_process_limit(struct adapter *adapter, const char *name,
+em_set_sysctl_value(struct adapter *adapter, const char *name,
const char *description, int *limit, int value)
{
*limit = value;
@@ -5455,14 +5678,68 @@ em_add_rx_process_limit(struct adapter *adapter, const char *name,
OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
}
-static void
-em_set_flow_cntrl(struct adapter *adapter, const char *name,
- const char *description, int *limit, int value)
+
+/*
+** Set flow control using sysctl:
+** Flow control values:
+** 0 - off
+** 1 - rx pause
+** 2 - tx pause
+** 3 - full
+*/
+static int
+em_set_flowcntl(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ static int input = 3; /* default is full */
+ struct adapter *adapter = (struct adapter *) arg1;
+
+ error = sysctl_handle_int(oidp, &input, 0, req);
+
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (input == adapter->fc) /* no change? */
+ return (error);
+
+ switch (input) {
+ case e1000_fc_rx_pause:
+ case e1000_fc_tx_pause:
+ case e1000_fc_full:
+ case e1000_fc_none:
+ adapter->hw.fc.requested_mode = input;
+ adapter->fc = input;
+ break;
+ default:
+ /* Do nothing */
+ return (error);
+ }
+
+ adapter->hw.fc.current_mode = adapter->hw.fc.requested_mode;
+ e1000_force_mac_fc(&adapter->hw);
+ return (error);
+}
+
+/*
+** Manage Energy Efficient Ethernet:
+** Control values:
+** 0/1 - enabled/disabled
+*/
+static int
+em_sysctl_eee(SYSCTL_HANDLER_ARGS)
{
- *limit = value;
- SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
- OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
+ struct adapter *adapter = (struct adapter *) arg1;
+ int error, value;
+
+ value = adapter->hw.dev_spec.ich8lan.eee_disable;
+ error = sysctl_handle_int(oidp, &value, 0, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ EM_CORE_LOCK(adapter);
+ adapter->hw.dev_spec.ich8lan.eee_disable = (value != 0);
+ em_init_locked(adapter);
+ EM_CORE_UNLOCK(adapter);
+ return (0);
}
static int
@@ -5501,10 +5778,11 @@ em_print_debug_info(struct adapter *adapter)
printf("Interface is RUNNING ");
else
printf("Interface is NOT RUNNING\n");
+
if (adapter->ifp->if_drv_flags & IFF_DRV_OACTIVE)
- printf("and ACTIVE\n");
- else
printf("and INACTIVE\n");
+ else
+ printf("and ACTIVE\n");
device_printf(dev, "hw tdh = %d, hw tdt = %d\n",
E1000_READ_REG(&adapter->hw, E1000_TDH(0)),
diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h
index 19ccf0a6..20ba1267 100644
--- a/freebsd/sys/dev/e1000/if_em.h
+++ b/freebsd/sys/dev/e1000/if_em.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -212,6 +212,11 @@
#define EM_BAR_MEM_TYPE_64BIT 0x00000004
#define EM_MSIX_BAR 3 /* On 82575 */
+/* More backward compatibility */
+#if __FreeBSD_version < 900000
+#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD
+#endif
+
/* Defines for printing debug information */
#define DEBUG_INIT 0
#define DEBUG_IOCTL 0
@@ -414,11 +419,11 @@ struct adapter {
u32 shadow_vfta[EM_VFTA_SIZE];
/* Info about the interface */
- u8 link_active;
+ u16 link_active;
+ u16 fc;
u16 link_speed;
u16 link_duplex;
u32 smartspeed;
- u32 fc_setting;
struct em_int_delay_info tx_int_delay;
struct em_int_delay_info tx_abs_int_delay;
@@ -459,6 +464,22 @@ struct em_buffer {
bus_dmamap_t map; /* bus_dma map for packet */
};
+
+/*
+** Find the number of unrefreshed RX descriptors
+*/
+static inline u16
+e1000_rx_unrefreshed(struct rx_ring *rxr)
+{
+ struct adapter *adapter = rxr->adapter;
+
+ if (rxr->next_to_check > rxr->next_to_refresh)
+ return (rxr->next_to_check - rxr->next_to_refresh - 1);
+ else
+ return ((adapter->num_rx_desc + rxr->next_to_check) -
+ rxr->next_to_refresh - 1);
+}
+
#define EM_CORE_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->core_mtx, _name, "EM Core Lock", MTX_DEF)
#define EM_TX_LOCK_INIT(_sc, _name) \
diff --git a/freebsd/sys/dev/e1000/if_igb.c b/freebsd/sys/dev/e1000/if_igb.c
index 27d9c92b..bf88f60f 100644
--- a/freebsd/sys/dev/e1000/if_igb.c
+++ b/freebsd/sys/dev/e1000/if_igb.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include <rtems/bsd/local/opt_device_polling.h>
#include <rtems/bsd/local/opt_inet.h>
+#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/local/opt_altq.h>
#endif
@@ -107,7 +108,7 @@ int igb_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char igb_driver_version[] = "version - 2.0.7";
+char igb_driver_version[] = "version - 2.3.9 - 8";
/*********************************************************************
@@ -149,6 +150,22 @@ static igb_vendor_info_t igb_vendor_info_array[] =
PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_DH89XXCC_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_DH89XXCC_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_DH89XXCC_SFP, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_DH89XXCC_BACKPLANE,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_VF, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I210_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I210_COPPER_IT, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I210_COPPER_OEM1,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I210_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I210_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I210_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I211_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@@ -170,13 +187,14 @@ static int igb_detach(device_t);
static int igb_shutdown(device_t);
static int igb_suspend(device_t);
static int igb_resume(device_t);
-static void igb_start(struct ifnet *);
-static void igb_start_locked(struct tx_ring *, struct ifnet *ifp);
#if __FreeBSD_version >= 800000
static int igb_mq_start(struct ifnet *, struct mbuf *);
-static int igb_mq_start_locked(struct ifnet *,
- struct tx_ring *, struct mbuf *);
+static int igb_mq_start_locked(struct ifnet *, struct tx_ring *);
static void igb_qflush(struct ifnet *);
+static void igb_deferred_mq_start(void *, int);
+#else
+static void igb_start(struct ifnet *);
+static void igb_start_locked(struct tx_ring *, struct ifnet *ifp);
#endif
static int igb_ioctl(struct ifnet *, u_long, caddr_t);
static void igb_init(void *);
@@ -220,19 +238,11 @@ static __inline void igb_rx_discard(struct rx_ring *, int);
static __inline void igb_rx_input(struct rx_ring *,
struct ifnet *, struct mbuf *, u32);
-#ifdef __rtems__
-/* XXX report inconsistent proto/body to FreeBSD */
static bool igb_rxeof(struct igb_queue *, int, int *);
-#else
-static boolean_t igb_rxeof(struct igb_queue *, int, int *);
-#endif
static void igb_rx_checksum(u32, struct mbuf *, u32);
-#ifdef __rtems__
-/* XXX report inconsistent proto/body to FreeBSD */
static bool igb_tx_ctx_setup(struct tx_ring *, struct mbuf *);
-#else
-#endif
-static boolean_t igb_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
+static bool igb_tso_setup(struct tx_ring *, struct mbuf *, int,
+ struct ip *, struct tcphdr *);
static void igb_set_promisc(struct adapter *);
static void igb_disable_promisc(struct adapter *);
static void igb_set_multi(struct adapter *);
@@ -264,14 +274,17 @@ static void igb_enable_wakeup(device_t);
static void igb_led_func(void *, int);
static int igb_irq_fast(void *);
-static void igb_add_rx_process_limit(struct adapter *, const char *,
- const char *, int *, int);
+static void igb_msix_que(void *);
+static void igb_msix_link(void *);
static void igb_handle_que(void *context, int pending);
static void igb_handle_link(void *context, int pending);
+static void igb_handle_link_locked(struct adapter *);
-/* These are MSIX only irq handlers */
-static void igb_msix_que(void *);
-static void igb_msix_link(void *);
+static void igb_set_sysctl_value(struct adapter *, const char *,
+ const char *, int *, int);
+static int igb_set_flowcntl(SYSCTL_HANDLER_ARGS);
+static int igb_sysctl_dmac(SYSCTL_HANDLER_ARGS);
+static int igb_sysctl_eee(SYSCTL_HANDLER_ARGS);
#ifdef DEVICE_POLLING
static poll_handler_t igb_poll;
@@ -289,7 +302,7 @@ static device_method_t igb_methods[] = {
DEVMETHOD(device_shutdown, igb_shutdown),
DEVMETHOD(device_suspend, igb_suspend),
DEVMETHOD(device_resume, igb_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t igb_driver = {
@@ -305,11 +318,17 @@ MODULE_DEPEND(igb, ether, 1, 1, 1);
* Tunable default values.
*********************************************************************/
+static SYSCTL_NODE(_hw, OID_AUTO, igb, CTLFLAG_RD, 0, "IGB driver parameters");
+
/* Descriptor defaults */
static int igb_rxd = IGB_DEFAULT_RXD;
static int igb_txd = IGB_DEFAULT_TXD;
TUNABLE_INT("hw.igb.rxd", &igb_rxd);
TUNABLE_INT("hw.igb.txd", &igb_txd);
+SYSCTL_INT(_hw_igb, OID_AUTO, rxd, CTLFLAG_RDTUN, &igb_rxd, 0,
+ "Number of receive descriptors per queue");
+SYSCTL_INT(_hw_igb, OID_AUTO, txd, CTLFLAG_RDTUN, &igb_txd, 0,
+ "Number of transmit descriptors per queue");
/*
** AIM: Adaptive Interrupt Moderation
@@ -319,6 +338,8 @@ TUNABLE_INT("hw.igb.txd", &igb_txd);
*/
static int igb_enable_aim = TRUE;
TUNABLE_INT("hw.igb.enable_aim", &igb_enable_aim);
+SYSCTL_INT(_hw_igb, OID_AUTO, enable_aim, CTLFLAG_RW, &igb_enable_aim, 0,
+ "Enable adaptive interrupt moderation");
/*
* MSIX should be the default for best performance,
@@ -326,12 +347,26 @@ TUNABLE_INT("hw.igb.enable_aim", &igb_enable_aim);
*/
static int igb_enable_msix = 1;
TUNABLE_INT("hw.igb.enable_msix", &igb_enable_msix);
+SYSCTL_INT(_hw_igb, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &igb_enable_msix, 0,
+ "Enable MSI-X interrupts");
/*
** Tuneable Interrupt rate
*/
static int igb_max_interrupt_rate = 8000;
TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate);
+SYSCTL_INT(_hw_igb, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
+ &igb_max_interrupt_rate, 0, "Maximum interrupts per second");
+
+#if __FreeBSD_version >= 800000
+/*
+** Tuneable number of buffers in the buf-ring (drbr_xxx)
+*/
+static int igb_buf_ring_size = IGB_BR_SIZE;
+TUNABLE_INT("hw.igb.buf_ring_size", &igb_buf_ring_size);
+SYSCTL_INT(_hw_igb, OID_AUTO, buf_ring_size, CTLFLAG_RDTUN,
+ &igb_buf_ring_size, 0, "Size of the bufring");
+#endif
/*
** Header split causes the packet header to
@@ -341,8 +376,10 @@ TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate);
** into the header and thus use no cluster. Its
** a very workload dependent type feature.
*/
-static bool igb_header_split = FALSE;
+static int igb_header_split = FALSE;
TUNABLE_INT("hw.igb.hdr_split", &igb_header_split);
+SYSCTL_INT(_hw_igb, OID_AUTO, header_split, CTLFLAG_RDTUN, &igb_header_split, 0,
+ "Enable receive mbuf header split");
/*
** This will autoconfigure based on
@@ -350,15 +387,26 @@ TUNABLE_INT("hw.igb.hdr_split", &igb_header_split);
*/
static int igb_num_queues = 0;
TUNABLE_INT("hw.igb.num_queues", &igb_num_queues);
+SYSCTL_INT(_hw_igb, OID_AUTO, num_queues, CTLFLAG_RDTUN, &igb_num_queues, 0,
+ "Number of queues to configure, 0 indicates autoconfigure");
+
+/*
+** Global variable to store last used CPU when binding queues
+** to CPUs in igb_allocate_msix. Starts at CPU_FIRST and increments when a
+** queue is bound to a cpu.
+*/
+static int igb_last_bind_cpu = -1;
/* How many packets rxeof tries to clean at a time */
static int igb_rx_process_limit = 100;
TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit);
+SYSCTL_INT(_hw_igb, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
+ &igb_rx_process_limit, 0,
+ "Maximum number of received packets to process at a time, -1 means unlimited");
-/* Flow control setting - default to FULL */
-static int igb_fc_setting = e1000_fc_full;
-TUNABLE_INT("hw.igb.fc_setting", &igb_fc_setting);
-
+#ifdef DEV_NETMAP /* see ixgbe.c for details */
+#include <dev/netmap/if_igb_netmap.h>
+#endif /* DEV_NETMAP */
/*********************************************************************
* Device identification routine
*
@@ -429,6 +477,11 @@ igb_attach(device_t dev)
INIT_DEBUGOUT("igb_attach: begin");
+ if (resource_disabled("igb", device_get_unit(dev))) {
+ device_printf(dev, "Disabled by device hint\n");
+ return (ENXIO);
+ }
+
adapter = device_get_softc(dev);
adapter->dev = adapter->osdep.dev = dev;
IGB_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
@@ -439,15 +492,14 @@ igb_attach(device_t dev)
OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
igb_sysctl_nvm_info, "I", "NVM Information");
- SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
- OID_AUTO, "flow_control", CTLTYPE_INT|CTLFLAG_RW,
- &igb_fc_setting, 0, "Flow Control");
+ igb_set_sysctl_value(adapter, "enable_aim",
+ "Interrupt Moderation", &adapter->enable_aim,
+ igb_enable_aim);
- SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW,
- &igb_enable_aim, 1, "Interrupt Moderation");
+ OID_AUTO, "fc", CTLTYPE_INT|CTLFLAG_RW,
+ adapter, 0, igb_set_flowcntl, "I", "Flow Control");
callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
@@ -470,10 +522,10 @@ igb_attach(device_t dev)
e1000_get_bus_info(&adapter->hw);
- /* Sysctls for limiting the amount of work done in the taskqueue */
- igb_add_rx_process_limit(adapter, "rx_processing_limit",
- "max number of rx packets to process", &adapter->rx_process_limit,
- igb_rx_process_limit);
+ /* Sysctl for limiting the amount of work done in the taskqueue */
+ igb_set_sysctl_value(adapter, "rx_processing_limit",
+ "max number of rx packets to process",
+ &adapter->rx_process_limit, igb_rx_process_limit);
/*
* Validate number of transmit and receive descriptors. It
@@ -522,7 +574,7 @@ igb_attach(device_t dev)
}
/* Allocate the appropriate stats memory */
- if (adapter->hw.mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
adapter->stats =
(struct e1000_vf_stats *)malloc(sizeof \
(struct e1000_vf_stats), M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -546,6 +598,21 @@ igb_attach(device_t dev)
goto err_late;
}
+ /* Some adapter-specific advanced features */
+ if (adapter->hw.mac.type >= e1000_i350) {
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "dmac", CTLTYPE_INT|CTLFLAG_RW,
+ adapter, 0, igb_sysctl_dmac, "I", "DMA Coalesce");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "eee_disabled", CTLTYPE_INT|CTLFLAG_RW,
+ adapter, 0, igb_sysctl_eee, "I",
+ "Disable Energy Efficient Ethernet");
+ if (adapter->hw.phy.media_type == e1000_media_type_copper)
+ e1000_set_eee_i350(&adapter->hw);
+ }
+
/*
** Start from a known state, this is
** important in reading the nvm and
@@ -554,7 +621,9 @@ igb_attach(device_t dev)
e1000_reset_hw(&adapter->hw);
/* Make sure we have a good EEPROM before we read from it */
- if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
+ if (((adapter->hw.mac.type != e1000_i210) &&
+ (adapter->hw.mac.type != e1000_i211)) &&
+ (e1000_validate_nvm_checksum(&adapter->hw) < 0)) {
/*
** Some PCI-E parts fail the first check due to
** the link being in sleep state, call it again,
@@ -584,16 +653,6 @@ igb_attach(device_t dev)
goto err_late;
}
- /*
- ** Configure Interrupts
- */
- if ((adapter->msix > 1) && (igb_enable_msix))
- error = igb_allocate_msix(adapter);
- else /* MSI or Legacy */
- error = igb_allocate_legacy(adapter);
- if (error)
- goto err_late;
-
/* Setup OS specific network interface */
if (igb_setup_interface(dev, adapter) != 0)
goto err_late;
@@ -632,23 +691,38 @@ igb_attach(device_t dev)
igb_add_hw_stats(adapter);
/* Tell the stack that the interface is not active */
- adapter->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ adapter->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
adapter->led_dev = led_create(igb_led_func, adapter,
device_get_nameunit(dev));
+ /*
+ ** Configure Interrupts
+ */
+ if ((adapter->msix > 1) && (igb_enable_msix))
+ error = igb_allocate_msix(adapter);
+ else /* MSI or Legacy */
+ error = igb_allocate_legacy(adapter);
+ if (error)
+ goto err_late;
+
+#ifdef DEV_NETMAP
+ igb_netmap_attach(adapter);
+#endif /* DEV_NETMAP */
INIT_DEBUGOUT("igb_attach: end");
return (0);
err_late:
+ igb_detach(dev);
igb_free_transmit_structures(adapter);
igb_free_receive_structures(adapter);
igb_release_hw_control(adapter);
- if (adapter->ifp != NULL)
- if_free(adapter->ifp);
err_pci:
igb_free_pci_resources(adapter);
+ if (adapter->ifp != NULL)
+ if_free(adapter->ifp);
free(adapter->mta, M_DEVBUF);
IGB_CORE_LOCK_DESTROY(adapter);
@@ -679,6 +753,8 @@ igb_detach(device_t dev)
return (EBUSY);
}
+ ether_ifdetach(adapter->ifp);
+
if (adapter->led_dev != NULL)
led_destroy(adapter->led_dev);
@@ -710,17 +786,19 @@ igb_detach(device_t dev)
if (adapter->vlan_detach != NULL)
EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
- ether_ifdetach(adapter->ifp);
-
callout_drain(&adapter->timer);
+#ifdef DEV_NETMAP
+ netmap_detach(adapter->ifp);
+#endif /* DEV_NETMAP */
igb_free_pci_resources(adapter);
bus_generic_detach(dev);
if_free(ifp);
igb_free_transmit_structures(adapter);
igb_free_receive_structures(adapter);
- free(adapter->mta, M_DEVBUF);
+ if (adapter->mta != NULL)
+ free(adapter->mta, M_DEVBUF);
IGB_CORE_LOCK_DESTROY(adapter);
@@ -769,6 +847,7 @@ static int
igb_resume(device_t dev)
{
struct adapter *adapter = device_get_softc(dev);
+ struct tx_ring *txr = adapter->tx_rings;
struct ifnet *ifp = adapter->ifp;
IGB_CORE_LOCK(adapter);
@@ -776,15 +855,29 @@ igb_resume(device_t dev)
igb_init_manageability(adapter);
if ((ifp->if_flags & IFF_UP) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING))
- igb_start(ifp);
-
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) && adapter->link_active) {
+ for (int i = 0; i < adapter->num_queues; i++, txr++) {
+ IGB_TX_LOCK(txr);
+#if __FreeBSD_version >= 800000
+ /* Process the stack queue only if not depleted */
+ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) &&
+ !drbr_empty(ifp, txr->br))
+ igb_mq_start_locked(ifp, txr);
+#else
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ igb_start_locked(txr, ifp);
+#endif
+ IGB_TX_UNLOCK(txr);
+ }
+ }
IGB_CORE_UNLOCK(adapter);
return bus_generic_resume(dev);
}
+#if __FreeBSD_version < 800000
+
/*********************************************************************
* Transmit entry point
*
@@ -814,8 +907,8 @@ igb_start_locked(struct tx_ring *txr, struct ifnet *ifp)
igb_txeof(txr);
while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
- if (txr->tx_avail <= IGB_TX_OP_THRESHOLD) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ if (txr->tx_avail <= IGB_MAX_SCATTER) {
+ txr->queue_status |= IGB_QUEUE_DEPLETED;
break;
}
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
@@ -826,10 +919,10 @@ igb_start_locked(struct tx_ring *txr, struct ifnet *ifp)
* NULL on failure. In that event, we can't requeue.
*/
if (igb_xmit(txr, &m_head)) {
- if (m_head == NULL)
- break;
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
+ if (m_head != NULL)
+ IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
+ if (txr->tx_avail <= IGB_MAX_SCATTER)
+ txr->queue_status |= IGB_QUEUE_DEPLETED;
break;
}
@@ -838,7 +931,7 @@ igb_start_locked(struct tx_ring *txr, struct ifnet *ifp)
/* Set watchdog on */
txr->watchdog_time = ticks;
- txr->queue_status = IGB_QUEUE_WORKING;
+ txr->queue_status |= IGB_QUEUE_WORKING;
}
}
@@ -861,9 +954,11 @@ igb_start(struct ifnet *ifp)
return;
}
-#if __FreeBSD_version >= 800000
+#else /* __FreeBSD_version >= 800000 */
+
/*
-** Multiqueue Transmit driver
+** Multiqueue Transmit Entry:
+** quick turnaround to the stack
**
*/
static int
@@ -872,83 +967,81 @@ igb_mq_start(struct ifnet *ifp, struct mbuf *m)
struct adapter *adapter = ifp->if_softc;
struct igb_queue *que;
struct tx_ring *txr;
- int i = 0, err = 0;
+ int i, err = 0;
/* Which queue to use */
if ((m->m_flags & M_FLOWID) != 0)
i = m->m_pkthdr.flowid % adapter->num_queues;
-
+ else
+ i = curcpu % adapter->num_queues;
txr = &adapter->tx_rings[i];
que = &adapter->queues[i];
- if (IGB_TX_TRYLOCK(txr)) {
- err = igb_mq_start_locked(ifp, txr, m);
- IGB_TX_UNLOCK(txr);
- } else {
- err = drbr_enqueue(ifp, txr->br, m);
- taskqueue_enqueue(que->tq, &que->que_task);
- }
+ err = drbr_enqueue(ifp, txr->br, m);
+ taskqueue_enqueue(que->tq, &txr->txq_task);
return (err);
}
static int
-igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
+igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr)
{
struct adapter *adapter = txr->adapter;
- struct mbuf *next;
- int err = 0, enq;
+ struct mbuf *buf;
+ int err = 0, enq = 0;
IGB_TX_LOCK_ASSERT(txr);
- if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING || adapter->link_active == 0) {
- if (m != NULL)
- err = drbr_enqueue(ifp, txr->br, m);
- return (err);
- }
-
- /* Call cleanup if number of TX descriptors low */
- if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD)
- igb_txeof(txr);
-
- enq = 0;
- if (m == NULL) {
- next = drbr_dequeue(ifp, txr->br);
- } else if (drbr_needs_enqueue(ifp, txr->br)) {
- if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
- return (err);
- next = drbr_dequeue(ifp, txr->br);
- } else
- next = m;
+ if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) ||
+ adapter->link_active == 0)
+ return (ENETDOWN);
/* Process the queue */
- while (next != NULL) {
- if ((err = igb_xmit(txr, &next)) != 0) {
- if (next != NULL)
- err = drbr_enqueue(ifp, txr->br, next);
+ buf = drbr_dequeue(ifp, txr->br);
+ while (buf != NULL) {
+ if ((err = igb_xmit(txr, &buf)) != 0) {
+ if (buf != NULL)
+ err = drbr_enqueue(ifp, txr->br, buf);
break;
}
enq++;
- drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);
- ETHER_BPF_MTAP(ifp, next);
+ ifp->if_obytes += buf->m_pkthdr.len;
+ if (buf->m_flags & M_MCAST)
+ ifp->if_omcasts++;
+ ETHER_BPF_MTAP(ifp, buf);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
break;
- if (txr->tx_avail <= IGB_TX_OP_THRESHOLD) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
- next = drbr_dequeue(ifp, txr->br);
+ buf = drbr_dequeue(ifp, txr->br);
}
if (enq > 0) {
/* Set the watchdog */
- txr->queue_status = IGB_QUEUE_WORKING;
+ txr->queue_status |= IGB_QUEUE_WORKING;
txr->watchdog_time = ticks;
}
+ if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD)
+ igb_txeof(txr);
+ if (txr->tx_avail <= IGB_MAX_SCATTER)
+ txr->queue_status |= IGB_QUEUE_DEPLETED;
return (err);
}
/*
+ * Called from a taskqueue to drain queued transmit packets.
+ */
+static void
+igb_deferred_mq_start(void *arg, int pending)
+{
+ struct tx_ring *txr = arg;
+ struct adapter *adapter = txr->adapter;
+ struct ifnet *ifp = adapter->ifp;
+
+ IGB_TX_LOCK(txr);
+ if (!drbr_empty(ifp, txr->br))
+ igb_mq_start_locked(ifp, txr);
+ IGB_TX_UNLOCK(txr);
+}
+
+/*
** Flush all ring buffers
*/
static void
@@ -981,11 +1074,12 @@ static int
igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct adapter *adapter = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *)data;
-#ifdef INET
- struct ifaddr *ifa = (struct ifaddr *)data;
+ struct ifreq *ifr = (struct ifreq *)data;
+#if defined(INET) || defined(INET6)
+ struct ifaddr *ifa = (struct ifaddr *)data;
#endif
- int error = 0;
+ bool avoid_reset = FALSE;
+ int error = 0;
if (adapter->in_detach)
return (error);
@@ -993,24 +1087,26 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
switch (command) {
case SIOCSIFADDR:
#ifdef INET
- if (ifa->ifa_addr->sa_family == AF_INET) {
- /*
- * XXX
- * Since resetting hardware takes a very long time
- * and results in link renegotiation we only
- * initialize the hardware only when it is absolutely
- * required.
- */
+ if (ifa->ifa_addr->sa_family == AF_INET)
+ avoid_reset = TRUE;
+#endif
+#ifdef INET6
+ if (ifa->ifa_addr->sa_family == AF_INET6)
+ avoid_reset = TRUE;
+#endif
+ /*
+ ** Calling init results in link renegotiation,
+ ** so we avoid doing it when possible.
+ */
+ if (avoid_reset) {
ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- IGB_CORE_LOCK(adapter);
- igb_init_locked(adapter);
- IGB_CORE_UNLOCK(adapter);
- }
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ igb_init(adapter);
+#ifdef INET
if (!(ifp->if_flags & IFF_NOARP))
arp_ifinit(ifp, ifa);
- } else
#endif
+ } else
error = ether_ioctl(ifp, command, data);
break;
case SIOCSIFMTU:
@@ -1069,11 +1165,6 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
break;
case SIOCSIFMEDIA:
- /*
- ** As the speed/duplex settings are being
- ** changed, we need toreset the PHY.
- */
- adapter->hw.phy.reset_disable = FALSE;
/* Check SOL/IDER usage */
IGB_CORE_LOCK(adapter);
if (e1000_check_reset_block(&adapter->hw)) {
@@ -1131,6 +1222,10 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
reinit = 1;
}
+ if (mask & IFCAP_VLAN_HWTSO) {
+ ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
+ reinit = 1;
+ }
if (mask & IFCAP_LRO) {
ifp->if_capenable ^= IFCAP_LRO;
reinit = 1;
@@ -1227,18 +1322,9 @@ igb_init_locked(struct adapter *adapter)
}
igb_initialize_receive_units(adapter);
- /* Use real VLAN Filter support? */
- if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
- if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
- /* Use real VLAN Filter support */
- igb_setup_vlan_hw_support(adapter);
- else {
- u32 ctrl;
- ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
- ctrl |= E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
- }
- }
+ /* Enable VLAN support */
+ if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
+ igb_setup_vlan_hw_support(adapter);
/* Don't lose promiscuous settings */
igb_set_promisc(adapter);
@@ -1264,12 +1350,13 @@ igb_init_locked(struct adapter *adapter)
else
#endif /* DEVICE_POLLING */
{
- igb_enable_intr(adapter);
- E1000_WRITE_REG(&adapter->hw, E1000_ICS, E1000_ICS_LSC);
+ igb_enable_intr(adapter);
+ E1000_WRITE_REG(&adapter->hw, E1000_ICS, E1000_ICS_LSC);
}
- /* Don't reset the phy next time init gets called */
- adapter->hw.phy.reset_disable = TRUE;
+ /* Set Energy Efficient Ethernet */
+ if (adapter->hw.phy.media_type == e1000_media_type_copper)
+ e1000_set_eee_i350(&adapter->hw);
}
static void
@@ -1294,19 +1381,21 @@ igb_handle_que(void *context, int pending)
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
bool more;
- more = igb_rxeof(que, -1, NULL);
+ more = igb_rxeof(que, adapter->rx_process_limit, NULL);
IGB_TX_LOCK(txr);
- if (igb_txeof(txr))
- more = TRUE;
+ igb_txeof(txr);
#if __FreeBSD_version >= 800000
- if (!drbr_empty(ifp, txr->br))
- igb_mq_start_locked(ifp, txr, NULL);
+ /* Process the stack queue only if not depleted */
+ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) &&
+ !drbr_empty(ifp, txr->br))
+ igb_mq_start_locked(ifp, txr);
#else
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
igb_start_locked(txr, ifp);
#endif
IGB_TX_UNLOCK(txr);
+ /* Do we need another? */
if (more) {
taskqueue_enqueue(que->tq, &que->que_task);
return;
@@ -1330,8 +1419,35 @@ igb_handle_link(void *context, int pending)
{
struct adapter *adapter = context;
+ IGB_CORE_LOCK(adapter);
+ igb_handle_link_locked(adapter);
+ IGB_CORE_UNLOCK(adapter);
+}
+
+static void
+igb_handle_link_locked(struct adapter *adapter)
+{
+ struct tx_ring *txr = adapter->tx_rings;
+ struct ifnet *ifp = adapter->ifp;
+
+ IGB_CORE_LOCK_ASSERT(adapter);
adapter->hw.mac.get_link_status = 1;
igb_update_link_status(adapter);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && adapter->link_active) {
+ for (int i = 0; i < adapter->num_queues; i++, txr++) {
+ IGB_TX_LOCK(txr);
+#if __FreeBSD_version >= 800000
+ /* Process the stack queue only if not depleted */
+ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) &&
+ !drbr_empty(ifp, txr->br))
+ igb_mq_start_locked(ifp, txr);
+#else
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ igb_start_locked(txr, ifp);
+#endif
+ IGB_TX_UNLOCK(txr);
+ }
+ }
}
/*********************************************************************
@@ -1379,12 +1495,6 @@ igb_irq_fast(void *arg)
}
#ifdef DEVICE_POLLING
-/*********************************************************************
- *
- * Legacy polling routine : if using this code you MUST be sure that
- * multiqueue is not defined, ie, set igb_num_queues to 1.
- *
- *********************************************************************/
#if __FreeBSD_version >= 800000
#define POLL_RETURN_COUNT(a) (a)
static int
@@ -1395,8 +1505,8 @@ static void
igb_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct adapter *adapter = ifp->if_softc;
- struct igb_queue *que = adapter->queues;
- struct tx_ring *txr = adapter->tx_rings;
+ struct igb_queue *que;
+ struct tx_ring *txr;
u32 reg_icr, rx_done = 0;
u32 loop = IGB_MAX_LOOP;
bool more;
@@ -1411,34 +1521,40 @@ igb_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
/* Link status change */
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))
- igb_handle_link(adapter, 0);
+ igb_handle_link_locked(adapter);
if (reg_icr & E1000_ICR_RXO)
adapter->rx_overruns++;
}
IGB_CORE_UNLOCK(adapter);
- igb_rxeof(que, count, &rx_done);
+ for (int i = 0; i < adapter->num_queues; i++) {
+ que = &adapter->queues[i];
+ txr = que->txr;
- IGB_TX_LOCK(txr);
- do {
- more = igb_txeof(txr);
- } while (loop-- && more);
+ igb_rxeof(que, count, &rx_done);
+
+ IGB_TX_LOCK(txr);
+ do {
+ more = igb_txeof(txr);
+ } while (loop-- && more);
#if __FreeBSD_version >= 800000
- if (!drbr_empty(ifp, txr->br))
- igb_mq_start_locked(ifp, txr, NULL);
+ if (!drbr_empty(ifp, txr->br))
+ igb_mq_start_locked(ifp, txr);
#else
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- igb_start_locked(txr, ifp);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ igb_start_locked(txr, ifp);
#endif
- IGB_TX_UNLOCK(txr);
+ IGB_TX_UNLOCK(txr);
+ }
+
return POLL_RETURN_COUNT(rx_done);
}
#endif /* DEVICE_POLLING */
/*********************************************************************
*
- * MSIX TX Interrupt Service routine
+ * MSIX Que Interrupt Service routine
*
**********************************************************************/
static void
@@ -1446,21 +1562,31 @@ igb_msix_que(void *arg)
{
struct igb_queue *que = arg;
struct adapter *adapter = que->adapter;
+ struct ifnet *ifp = adapter->ifp;
struct tx_ring *txr = que->txr;
struct rx_ring *rxr = que->rxr;
u32 newitr = 0;
- bool more_tx, more_rx;
+ bool more_rx;
E1000_WRITE_REG(&adapter->hw, E1000_EIMC, que->eims);
++que->irqs;
IGB_TX_LOCK(txr);
- more_tx = igb_txeof(txr);
+ igb_txeof(txr);
+#if __FreeBSD_version >= 800000
+ /* Process the stack queue only if not depleted */
+ if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) &&
+ !drbr_empty(ifp, txr->br))
+ igb_mq_start_locked(ifp, txr);
+#else
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ igb_start_locked(txr, ifp);
+#endif
IGB_TX_UNLOCK(txr);
more_rx = igb_rxeof(que, adapter->rx_process_limit, NULL);
- if (igb_enable_aim == FALSE)
+ if (adapter->enable_aim == FALSE)
goto no_calc;
/*
** Do Adaptive Interrupt Moderation:
@@ -1513,7 +1639,7 @@ igb_msix_que(void *arg)
no_calc:
/* Schedule a clean task if needed*/
- if (more_tx || more_rx)
+ if (more_rx)
taskqueue_enqueue(que->tq, &que->que_task);
else
/* Reenable this interrupt */
@@ -1560,7 +1686,6 @@ static void
igb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct adapter *adapter = ifp->if_softc;
- u_char fiber_type = IFM_1000_SX;
INIT_DEBUGOUT("igb_media_status: begin");
@@ -1577,26 +1702,31 @@ igb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
ifmr->ifm_status |= IFM_ACTIVE;
- if ((adapter->hw.phy.media_type == e1000_media_type_fiber) ||
- (adapter->hw.phy.media_type == e1000_media_type_internal_serdes))
- ifmr->ifm_active |= fiber_type | IFM_FDX;
- else {
- switch (adapter->link_speed) {
- case 10:
- ifmr->ifm_active |= IFM_10_T;
- break;
- case 100:
- ifmr->ifm_active |= IFM_100_TX;
- break;
- case 1000:
- ifmr->ifm_active |= IFM_1000_T;
- break;
- }
- if (adapter->link_duplex == FULL_DUPLEX)
- ifmr->ifm_active |= IFM_FDX;
+ switch (adapter->link_speed) {
+ case 10:
+ ifmr->ifm_active |= IFM_10_T;
+ break;
+ case 100:
+ /*
+ ** Support for 100Mb SFP - these are Fiber
+ ** but the media type appears as serdes
+ */
+ if (adapter->hw.phy.media_type ==
+ e1000_media_type_internal_serdes)
+ ifmr->ifm_active |= IFM_100_FX;
else
- ifmr->ifm_active |= IFM_HDX;
+ ifmr->ifm_active |= IFM_100_TX;
+ break;
+ case 1000:
+ ifmr->ifm_active |= IFM_1000_T;
+ break;
}
+
+ if (adapter->link_duplex == FULL_DUPLEX)
+ ifmr->ifm_active |= IFM_FDX;
+ else
+ ifmr->ifm_active |= IFM_HDX;
+
IGB_CORE_UNLOCK(adapter);
}
@@ -1661,10 +1791,8 @@ igb_media_change(struct ifnet *ifp)
/*********************************************************************
*
* This routine maps the mbufs to Advanced TX descriptors.
- * used by the 82575 adapter.
*
**********************************************************************/
-
static int
igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
{
@@ -1673,35 +1801,123 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
bus_dmamap_t map;
struct igb_tx_buffer *tx_buffer, *tx_buffer_mapped;
union e1000_adv_tx_desc *txd = NULL;
- struct mbuf *m_head;
- u32 olinfo_status = 0, cmd_type_len = 0;
- int nsegs, i, j, error, first, last = 0;
- u32 hdrlen = 0;
-
- m_head = *m_headp;
-
+ struct mbuf *m_head = *m_headp;
+ struct ether_vlan_header *eh = NULL;
+ struct ip *ip = NULL;
+ struct tcphdr *th = NULL;
+ u32 hdrlen, cmd_type_len, olinfo_status = 0;
+ int ehdrlen, poff;
+ int nsegs, i, first, last = 0;
+ int error, do_tso, remap = 1;
/* Set basic descriptor constants */
- cmd_type_len |= E1000_ADVTXD_DTYP_DATA;
+ cmd_type_len = E1000_ADVTXD_DTYP_DATA;
cmd_type_len |= E1000_ADVTXD_DCMD_IFCS | E1000_ADVTXD_DCMD_DEXT;
if (m_head->m_flags & M_VLANTAG)
cmd_type_len |= E1000_ADVTXD_DCMD_VLE;
- /*
- * Force a cleanup if number of TX descriptors
- * available hits the threshold
- */
- if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD) {
- igb_txeof(txr);
- /* Now do we at least have a minimal? */
- if (txr->tx_avail <= IGB_TX_OP_THRESHOLD) {
- txr->no_desc_avail++;
+retry:
+ m_head = *m_headp;
+ do_tso = ((m_head->m_pkthdr.csum_flags & CSUM_TSO) != 0);
+ hdrlen = ehdrlen = poff = 0;
+
+ /*
+ * Intel recommends entire IP/TCP header length reside in a single
+ * buffer. If multiple descriptors are used to describe the IP and
+ * TCP header, each descriptor should describe one or more
+ * complete headers; descriptors referencing only parts of headers
+ * are not supported. If all layer headers are not coalesced into
+ * a single buffer, each buffer should not cross a 4KB boundary,
+ * or be larger than the maximum read request size.
+ * Controller also requires modifing IP/TCP header to make TSO work
+ * so we firstly get a writable mbuf chain then coalesce ethernet/
+ * IP/TCP header into a single buffer to meet the requirement of
+ * controller. This also simplifies IP/TCP/UDP checksum offloading
+ * which also has similiar restrictions.
+ */
+ if (do_tso || m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) {
+ if (do_tso || (m_head->m_next != NULL &&
+ m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD)) {
+ if (M_WRITABLE(*m_headp) == 0) {
+ m_head = m_dup(*m_headp, M_NOWAIT);
+ m_freem(*m_headp);
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
+ *m_headp = m_head;
+ }
+ }
+ /*
+ * Assume IPv4, we don't have TSO/checksum offload support
+ * for IPv6 yet.
+ */
+ ehdrlen = sizeof(struct ether_header);
+ m_head = m_pullup(m_head, ehdrlen);
+ if (m_head == NULL) {
+ *m_headp = NULL;
return (ENOBUFS);
}
+ eh = mtod(m_head, struct ether_vlan_header *);
+ if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
+ ehdrlen = sizeof(struct ether_vlan_header);
+ m_head = m_pullup(m_head, ehdrlen);
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
+ }
+ m_head = m_pullup(m_head, ehdrlen + sizeof(struct ip));
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
+ ip = (struct ip *)(mtod(m_head, char *) + ehdrlen);
+ poff = ehdrlen + (ip->ip_hl << 2);
+ if (do_tso) {
+ m_head = m_pullup(m_head, poff + sizeof(struct tcphdr));
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
+ /*
+ * The pseudo TCP checksum does not include TCP payload
+ * length so driver should recompute the checksum here
+ * what hardware expect to see. This is adherence of
+ * Microsoft's Large Send specification.
+ */
+ th = (struct tcphdr *)(mtod(m_head, char *) + poff);
+ th->th_sum = in_pseudo(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr, htons(IPPROTO_TCP));
+ /* Keep track of the full header length */
+ hdrlen = poff + (th->th_off << 2);
+ } else if (m_head->m_pkthdr.csum_flags & CSUM_TCP) {
+ m_head = m_pullup(m_head, poff + sizeof(struct tcphdr));
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
+ th = (struct tcphdr *)(mtod(m_head, char *) + poff);
+ m_head = m_pullup(m_head, poff + (th->th_off << 2));
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
+ ip = (struct ip *)(mtod(m_head, char *) + ehdrlen);
+ th = (struct tcphdr *)(mtod(m_head, char *) + poff);
+ } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) {
+ m_head = m_pullup(m_head, poff + sizeof(struct udphdr));
+ if (m_head == NULL) {
+ *m_headp = NULL;
+ return (ENOBUFS);
+ }
+ ip = (struct ip *)(mtod(m_head, char *) + ehdrlen);
+ }
+ *m_headp = m_head;
}
/*
- * Map the packet for DMA.
+ * Map the packet for DMA
*
* Capture the first descriptor index,
* this descriptor will have the index
@@ -1716,10 +1932,19 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
*m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
- if (error == EFBIG) {
+ /*
+ * There are two types of errors we can (try) to handle:
+ * - EFBIG means the mbuf chain was too long and bus_dma ran
+ * out of segments. Defragment the mbuf chain and try again.
+ * - ENOMEM means bus_dma could not obtain enough bounce buffers
+ * at this point in time. Defer sending and try again later.
+ * All other errors, in particular EINVAL, are fatal and prevent the
+ * mbuf chain from ever going through. Drop it and report error.
+ */
+ if (error == EFBIG && remap) {
struct mbuf *m;
- m = m_defrag(*m_headp, M_DONTWAIT);
+ m = m_defrag(*m_headp, M_NOWAIT);
if (m == NULL) {
adapter->mbuf_defrag_failed++;
m_freem(*m_headp);
@@ -1728,19 +1953,9 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
}
*m_headp = m;
- /* Try it again */
- error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
- *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
- if (error == ENOMEM) {
- adapter->no_tx_dma_setup++;
- return (error);
- } else if (error != 0) {
- adapter->no_tx_dma_setup++;
- m_freem(*m_headp);
- *m_headp = NULL;
- return (error);
- }
+ /* Try it again, but only once */
+ remap = 0;
+ goto retry;
} else if (error == ENOMEM) {
adapter->no_tx_dma_setup++;
return (error);
@@ -1751,29 +1966,35 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
return (error);
}
- /* Check again to be sure we have enough descriptors */
- if (nsegs > (txr->tx_avail - 2)) {
+ /*
+ ** Make sure we don't overrun the ring,
+ ** we need nsegs descriptors and one for
+ ** the context descriptor used for the
+ ** offloads.
+ */
+ if ((nsegs + 1) > (txr->tx_avail - 2)) {
txr->no_desc_avail++;
bus_dmamap_unload(txr->txtag, map);
return (ENOBUFS);
}
m_head = *m_headp;
- /*
- * Set up the context descriptor:
- * used when any hardware offload is done.
- * This includes CSUM, VLAN, and TSO. It
- * will use the first descriptor.
+ /* Do hardware assists:
+ * Set up the context descriptor, used
+ * when any hardware offload is done.
+ * This includes CSUM, VLAN, and TSO.
+ * It will use the first descriptor.
*/
- if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
- if (igb_tso_setup(txr, m_head, &hdrlen)) {
+
+ if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
+ if (igb_tso_setup(txr, m_head, ehdrlen, ip, th)) {
cmd_type_len |= E1000_ADVTXD_DCMD_TSE;
olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
} else
- return (ENXIO);
+ return (ENXIO);
} else if (igb_tx_ctx_setup(txr, m_head))
- olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
+ olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
/* Calculate payload length */
olinfo_status |= ((m_head->m_pkthdr.len - hdrlen)
@@ -1785,7 +2006,7 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
/* Set up our transmit descriptors */
i = txr->next_avail_desc;
- for (j = 0; j < nsegs; j++) {
+ for (int j = 0; j < nsegs; j++) {
bus_size_t seg_len;
bus_addr_t seg_addr;
@@ -1806,8 +2027,14 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
txr->next_avail_desc = i;
txr->tx_avail -= nsegs;
-
tx_buffer->m_head = m_head;
+
+ /*
+ ** Here we swap the map so the last descriptor,
+ ** which gets the completion interrupt has the
+ ** real map, and the first descriptor gets the
+ ** unused map from this descriptor.
+ */
tx_buffer_mapped->map = tx_buffer->map;
tx_buffer->map = map;
bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);
@@ -1825,6 +2052,7 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
*/
tx_buffer = &txr->tx_buffers[first];
tx_buffer->next_eop = last;
+ /* Update the watchdog time early and often */
txr->watchdog_time = ticks;
/*
@@ -1837,9 +2065,7 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
++txr->tx_packets;
return (0);
-
}
-
static void
igb_set_promisc(struct adapter *adapter)
{
@@ -1847,7 +2073,7 @@ igb_set_promisc(struct adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 reg;
- if (hw->mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
e1000_promisc_set_vf(hw, e1000_promisc_enabled);
return;
}
@@ -1869,7 +2095,7 @@ igb_disable_promisc(struct adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 reg;
- if (hw->mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
e1000_promisc_set_vf(hw, e1000_promisc_disabled);
return;
}
@@ -1946,7 +2172,10 @@ igb_local_timer(void *arg)
{
struct adapter *adapter = arg;
device_t dev = adapter->dev;
+ struct ifnet *ifp = adapter->ifp;
struct tx_ring *txr = adapter->tx_rings;
+ struct igb_queue *que = adapter->queues;
+ int hung = 0, busy = 0;
IGB_CORE_LOCK_ASSERT(adapter);
@@ -1954,23 +2183,34 @@ igb_local_timer(void *arg)
igb_update_link_status(adapter);
igb_update_stats_counters(adapter);
- /*
- ** If flow control has paused us since last checking
- ** it invalidates the watchdog timing, so dont run it.
- */
- if (adapter->pause_frames) {
- adapter->pause_frames = 0;
- goto out;
- }
-
/*
- ** Watchdog: check for time since any descriptor was cleaned
+ ** Check the TX queues status
+ ** - central locked handling of OACTIVE
+ ** - watchdog only if all queues show hung
*/
- for (int i = 0; i < adapter->num_queues; i++, txr++)
- if (txr->queue_status == IGB_QUEUE_HUNG)
- goto timeout;
-out:
+ for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
+ if ((txr->queue_status & IGB_QUEUE_HUNG) &&
+ (adapter->pause_frames == 0))
+ ++hung;
+ if (txr->queue_status & IGB_QUEUE_DEPLETED)
+ ++busy;
+ if ((txr->queue_status & IGB_QUEUE_IDLE) == 0)
+ taskqueue_enqueue(que->tq, &que->que_task);
+ }
+ if (hung == adapter->num_queues)
+ goto timeout;
+ if (busy == adapter->num_queues)
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ else if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) &&
+ (busy < adapter->num_queues))
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ adapter->pause_frames = 0;
callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
+#ifndef DEVICE_POLLING
+ /* Schedule all queue interrupts - deadlock protection */
+ E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->que_mask);
+#endif
return;
timeout:
@@ -1989,11 +2229,15 @@ timeout:
static void
igb_update_link_status(struct adapter *adapter)
{
- struct e1000_hw *hw = &adapter->hw;
- struct ifnet *ifp = adapter->ifp;
- device_t dev = adapter->dev;
- struct tx_ring *txr = adapter->tx_rings;
- u32 link_check = 0;
+ struct e1000_hw *hw = &adapter->hw;
+ struct e1000_fc_info *fc = &hw->fc;
+ struct ifnet *ifp = adapter->ifp;
+ device_t dev = adapter->dev;
+ struct tx_ring *txr = adapter->tx_rings;
+ u32 link_check, thstat, ctrl;
+ char *flowctl = NULL;
+
+ link_check = thstat = ctrl = 0;
/* Get the cached link value or read for real */
switch (hw->phy.media_type) {
@@ -2023,17 +2267,44 @@ igb_update_link_status(struct adapter *adapter)
break;
}
+ /* Check for thermal downshift or shutdown */
+ if (hw->mac.type == e1000_i350) {
+ thstat = E1000_READ_REG(hw, E1000_THSTAT);
+ ctrl = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ }
+
+ /* Get the flow control for display */
+ switch (fc->current_mode) {
+ case e1000_fc_rx_pause:
+ flowctl = "RX";
+ break;
+ case e1000_fc_tx_pause:
+ flowctl = "TX";
+ break;
+ case e1000_fc_full:
+ flowctl = "Full";
+ break;
+ case e1000_fc_none:
+ default:
+ flowctl = "None";
+ break;
+ }
+
/* Now we check if a transition has happened */
if (link_check && (adapter->link_active == 0)) {
e1000_get_speed_and_duplex(&adapter->hw,
&adapter->link_speed, &adapter->link_duplex);
if (bootverbose)
- device_printf(dev, "Link is up %d Mbps %s\n",
+ device_printf(dev, "Link is up %d Mbps %s,"
+ " Flow Control: %s\n",
adapter->link_speed,
((adapter->link_duplex == FULL_DUPLEX) ?
- "Full Duplex" : "Half Duplex"));
+ "Full Duplex" : "Half Duplex"), flowctl);
adapter->link_active = 1;
ifp->if_baudrate = adapter->link_speed * 1000000;
+ if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) &&
+ (thstat & E1000_THSTAT_LINK_THROTTLE))
+ device_printf(dev, "Link: thermal downshift\n");
/* This can sleep */
if_link_state_change(ifp, LINK_STATE_UP);
} else if (!link_check && (adapter->link_active == 1)) {
@@ -2041,10 +2312,13 @@ igb_update_link_status(struct adapter *adapter)
adapter->link_duplex = 0;
if (bootverbose)
device_printf(dev, "Link is Down\n");
+ if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) &&
+ (thstat & E1000_THSTAT_PWR_DOWN))
+ device_printf(dev, "Link: thermal shutdown\n");
adapter->link_active = 0;
/* This can sleep */
if_link_state_change(ifp, LINK_STATE_DOWN);
- /* Turn off watchdogs */
+ /* Reset queue state */
for (int i = 0; i < adapter->num_queues; i++, txr++)
txr->queue_status = IGB_QUEUE_IDLE;
}
@@ -2073,9 +2347,10 @@ igb_stop(void *arg)
callout_stop(&adapter->timer);
/* Tell the stack that the interface is no longer active */
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- /* Unarm watchdog timer. */
+ /* Disarm watchdog timer. */
for (int i = 0; i < adapter->num_queues; i++, txr++) {
IGB_TX_LOCK(txr);
txr->queue_status = IGB_QUEUE_IDLE;
@@ -2123,6 +2398,13 @@ igb_identify_hardware(struct adapter *adapter)
/* Set MAC type early for PCI setup */
e1000_set_mac_type(&adapter->hw);
+
+ /* Are we a VF device? */
+ if ((adapter->hw.mac.type == e1000_vfadapt) ||
+ (adapter->hw.mac.type == e1000_vfadapt_i350))
+ adapter->vf_ifp = 1;
+ else
+ adapter->vf_ifp = 0;
}
static int
@@ -2163,6 +2445,7 @@ igb_allocate_legacy(struct adapter *adapter)
{
device_t dev = adapter->dev;
struct igb_queue *que = adapter->queues;
+ struct tx_ring *txr = adapter->tx_rings;
int error, rid = 0;
/* Turn off all interrupts */
@@ -2181,6 +2464,10 @@ igb_allocate_legacy(struct adapter *adapter)
return (ENXIO);
}
+#if __FreeBSD_version >= 800000
+ TASK_INIT(&txr->txq_task, 0, igb_deferred_mq_start, txr);
+#endif
+
/*
* Try allocating a fast interrupt and the associated deferred
* processing contexts.
@@ -2218,6 +2505,9 @@ igb_allocate_msix(struct adapter *adapter)
struct igb_queue *que = adapter->queues;
int error, rid, vector = 0;
+ /* Be sure to start with all interrupts disabled */
+ E1000_WRITE_REG(&adapter->hw, E1000_IMC, ~0);
+ E1000_WRITE_FLUSH(&adapter->hw);
for (int i = 0; i < adapter->num_queues; i++, vector++, que++) {
rid = vector +1;
@@ -2249,11 +2539,22 @@ igb_allocate_msix(struct adapter *adapter)
** Bind the msix vector, and thus the
** rings to the corresponding cpu.
*/
- if (adapter->num_queues > 1)
- bus_bind_intr(dev, que->res, i);
+ if (adapter->num_queues > 1) {
+ if (igb_last_bind_cpu < 0)
+ igb_last_bind_cpu = CPU_FIRST();
+ bus_bind_intr(dev, que->res, igb_last_bind_cpu);
+ device_printf(dev,
+ "Bound queue %d to cpu %d\n",
+ i,igb_last_bind_cpu);
+ igb_last_bind_cpu = CPU_NEXT(igb_last_bind_cpu);
+ }
+#if __FreeBSD_version >= 800000
+ TASK_INIT(&que->txr->txq_task, 0, igb_deferred_mq_start,
+ que->txr);
+#endif
/* Make tasklet for deferred handling */
TASK_INIT(&que->que_task, 0, igb_handle_que, que);
- que->tq = taskqueue_create_fast("igb_que", M_NOWAIT,
+ que->tq = taskqueue_create("igb_que", M_NOWAIT,
taskqueue_thread_enqueue, &que->tq);
taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",
device_get_nameunit(adapter->dev));
@@ -2292,7 +2593,7 @@ igb_configure_queues(struct adapter *adapter)
u32 tmp, ivar = 0, newitr = 0;
/* First turn on RSS capability */
- if (adapter->hw.mac.type > e1000_82575)
+ if (adapter->hw.mac.type != e1000_82575)
E1000_WRITE_REG(hw, E1000_GPIE,
E1000_GPIE_MSIX_MODE | E1000_GPIE_EIAME |
E1000_GPIE_PBA | E1000_GPIE_NSICR);
@@ -2300,7 +2601,11 @@ igb_configure_queues(struct adapter *adapter)
/* Turn on MSIX */
switch (adapter->hw.mac.type) {
case e1000_82580:
+ case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
case e1000_vfadapt:
+ case e1000_vfadapt_i350:
/* RX entries */
for (int i = 0; i < adapter->num_queues; i++) {
u32 index = i >> 1;
@@ -2328,13 +2633,12 @@ igb_configure_queues(struct adapter *adapter)
ivar |= (que->msix | E1000_IVAR_VALID) << 8;
}
E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
- adapter->eims_mask |= que->eims;
+ adapter->que_mask |= que->eims;
}
/* And for the link interrupt */
ivar = (adapter->linkvec | E1000_IVAR_VALID) << 8;
adapter->link_mask = 1 << adapter->linkvec;
- adapter->eims_mask |= adapter->link_mask;
E1000_WRITE_REG(hw, E1000_IVAR_MISC, ivar);
break;
case e1000_82576:
@@ -2351,7 +2655,7 @@ igb_configure_queues(struct adapter *adapter)
ivar |= (que->msix | E1000_IVAR_VALID) << 16;
}
E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
- adapter->eims_mask |= que->eims;
+ adapter->que_mask |= que->eims;
}
/* TX entries */
for (int i = 0; i < adapter->num_queues; i++) {
@@ -2366,13 +2670,12 @@ igb_configure_queues(struct adapter *adapter)
ivar |= (que->msix | E1000_IVAR_VALID) << 24;
}
E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
- adapter->eims_mask |= que->eims;
+ adapter->que_mask |= que->eims;
}
/* And for the link interrupt */
ivar = (adapter->linkvec | E1000_IVAR_VALID) << 8;
adapter->link_mask = 1 << adapter->linkvec;
- adapter->eims_mask |= adapter->link_mask;
E1000_WRITE_REG(hw, E1000_IVAR_MISC, ivar);
break;
@@ -2393,14 +2696,13 @@ igb_configure_queues(struct adapter *adapter)
que->eims = tmp;
E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0),
i, que->eims);
- adapter->eims_mask |= que->eims;
+ adapter->que_mask |= que->eims;
}
/* Link */
E1000_WRITE_REG(hw, E1000_MSIXBM(adapter->linkvec),
E1000_EIMS_OTHER);
adapter->link_mask |= E1000_EIMS_OTHER;
- adapter->eims_mask |= adapter->link_mask;
default:
break;
}
@@ -2461,13 +2763,24 @@ igb_free_pci_resources(struct adapter *adapter)
else
(adapter->msix != 0) ? (rid = 1):(rid = 0);
+ que = adapter->queues;
if (adapter->tag != NULL) {
+ taskqueue_drain(que->tq, &adapter->link_task);
bus_teardown_intr(dev, adapter->res, adapter->tag);
adapter->tag = NULL;
}
if (adapter->res != NULL)
bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res);
+ for (int i = 0; i < adapter->num_queues; i++, que++) {
+ if (que->tq != NULL) {
+#if __FreeBSD_version >= 800000
+ taskqueue_drain(que->tq, &que->txr->txq_task);
+#endif
+ taskqueue_drain(que->tq, &que->que_task);
+ taskqueue_free(que->tq);
+ }
+ }
mem:
if (adapter->msix)
pci_release_msi(dev);
@@ -2489,7 +2802,7 @@ static int
igb_setup_msix(struct adapter *adapter)
{
device_t dev = adapter->dev;
- int rid, want, queues, msgs;
+ int rid, want, queues, msgs, maxqueues;
/* tuneable override */
if (igb_enable_msix == 0)
@@ -2520,16 +2833,29 @@ igb_setup_msix(struct adapter *adapter)
/* Manual override */
if (igb_num_queues != 0)
queues = igb_num_queues;
- if (queues > 8) /* max queues */
- queues = 8;
- /* Can have max of 4 queues on 82575 */
- if ((adapter->hw.mac.type == e1000_82575) && (queues > 4))
- queues = 4;
-
- /* Limit the VF adapter to one queue */
- if (adapter->hw.mac.type == e1000_vfadapt)
- queues = 1;
+ /* Sanity check based on HW */
+ switch (adapter->hw.mac.type) {
+ case e1000_82575:
+ maxqueues = 4;
+ break;
+ case e1000_82576:
+ case e1000_82580:
+ case e1000_i350:
+ maxqueues = 8;
+ break;
+ case e1000_i210:
+ maxqueues = 4;
+ break;
+ case e1000_i211:
+ maxqueues = 2;
+ break;
+ default: /* VF interfaces */
+ maxqueues = 1;
+ break;
+ }
+ if (queues > maxqueues)
+ queues = maxqueues;
/*
** One vector (RX/TX pair) per queue
@@ -2543,7 +2869,7 @@ igb_setup_msix(struct adapter *adapter)
"MSIX Configuration Problem, "
"%d vectors configured, but %d queues wanted!\n",
msgs, want);
- return (ENXIO);
+ return (0);
}
if ((msgs) && pci_alloc_msix(dev, &msgs) == 0) {
device_printf(adapter->dev,
@@ -2553,9 +2879,11 @@ igb_setup_msix(struct adapter *adapter)
}
msi:
msgs = pci_msi_count(dev);
- if (msgs == 1 && pci_alloc_msi(dev, &msgs) == 0)
- device_printf(adapter->dev,"Using MSI interrupt\n");
- return (msgs);
+ if (msgs == 1 && pci_alloc_msi(dev, &msgs) == 0) {
+ device_printf(adapter->dev," Using MSI interrupt\n");
+ return (msgs);
+ }
+ return (0);
}
/*********************************************************************
@@ -2589,10 +2917,18 @@ igb_reset(struct adapter *adapter)
break;
case e1000_82576:
case e1000_vfadapt:
- pba = E1000_PBA_64K;
+ pba = E1000_READ_REG(hw, E1000_RXPBS);
+ pba &= E1000_RXPBS_SIZE_MASK_82576;
break;
case e1000_82580:
- pba = E1000_PBA_35K;
+ case e1000_i350:
+ case e1000_vfadapt_i350:
+ pba = E1000_READ_REG(hw, E1000_RXPBS);
+ pba = e1000_rxpbs_adjust_82580(pba);
+ break;
+ case e1000_i210:
+ case e1000_i211:
+ pba = E1000_PBA_34K;
default:
break;
}
@@ -2647,14 +2983,10 @@ igb_reset(struct adapter *adapter)
fc->pause_time = IGB_FC_PAUSE_TIME;
fc->send_xon = TRUE;
-
- /* Set Flow control, use the tunable location if sane */
- if ((igb_fc_setting >= 0) && (igb_fc_setting < 4))
- fc->requested_mode = igb_fc_setting;
+ if (adapter->fc)
+ fc->requested_mode = adapter->fc;
else
- fc->requested_mode = e1000_fc_none;
-
- fc->current_mode = fc->requested_mode;
+ fc->requested_mode = e1000_fc_default;
/* Issue a global reset */
e1000_reset_hw(hw);
@@ -2663,28 +2995,48 @@ igb_reset(struct adapter *adapter)
if (e1000_init_hw(hw) < 0)
device_printf(dev, "Hardware Initialization Failed\n");
- if (hw->mac.type == e1000_82580) {
- u32 reg;
+ /* Setup DMA Coalescing */
+ if ((hw->mac.type > e1000_82580) &&
+ (hw->mac.type != e1000_i211)) {
+ u32 dmac;
+ u32 reg = ~E1000_DMACR_DMAC_EN;
- hwm = (pba << 10) - (2 * adapter->max_frame_size);
- /*
- * 0x80000000 - enable DMA COAL
- * 0x10000000 - use L0s as low power
- * 0x20000000 - use L1 as low power
- * X << 16 - exit dma coal when rx data exceeds X kB
- * Y - upper limit to stay in dma coal in units of 32usecs
- */
- E1000_WRITE_REG(hw, E1000_DMACR,
- 0xA0000006 | ((hwm << 6) & 0x00FF0000));
+ if (adapter->dmac == 0) { /* Disabling it */
+ E1000_WRITE_REG(hw, E1000_DMACR, reg);
+ goto reset_out;
+ }
- /* set hwm to PBA - 2 * max frame size */
- E1000_WRITE_REG(hw, E1000_FCRTC, hwm);
- /*
- * This sets the time to wait before requesting transition to
- * low power state to number of usecs needed to receive 1 512
- * byte frame at gigabit line rate
- */
- E1000_WRITE_REG(hw, E1000_DMCTLX, 4);
+ /* Set starting thresholds */
+ E1000_WRITE_REG(hw, E1000_DMCTXTH, 0);
+ E1000_WRITE_REG(hw, E1000_DMCRTRH, 0);
+
+ hwm = 64 * pba - adapter->max_frame_size / 16;
+ if (hwm < 64 * (pba - 6))
+ hwm = 64 * (pba - 6);
+ reg = E1000_READ_REG(hw, E1000_FCRTC);
+ reg &= ~E1000_FCRTC_RTH_COAL_MASK;
+ reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT)
+ & E1000_FCRTC_RTH_COAL_MASK);
+ E1000_WRITE_REG(hw, E1000_FCRTC, reg);
+
+
+ dmac = pba - adapter->max_frame_size / 512;
+ if (dmac < pba - 10)
+ dmac = pba - 10;
+ reg = E1000_READ_REG(hw, E1000_DMACR);
+ reg &= ~E1000_DMACR_DMACTHR_MASK;
+ reg = ((dmac << E1000_DMACR_DMACTHR_SHIFT)
+ & E1000_DMACR_DMACTHR_MASK);
+ /* transition to L0x or L1 if available..*/
+ reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);
+ /* timer = value in adapter->dmac in 32usec intervals */
+ reg |= (adapter->dmac >> 5);
+ E1000_WRITE_REG(hw, E1000_DMACR, reg);
+
+ /* Set the interval before transition */
+ reg = E1000_READ_REG(hw, E1000_DMCTLX);
+ reg |= 0x80000004;
+ E1000_WRITE_REG(hw, E1000_DMCTLX, reg);
/* free space in tx packet buffer to wake from DMA coal */
E1000_WRITE_REG(hw, E1000_DMCTXTH,
@@ -2692,10 +3044,18 @@ igb_reset(struct adapter *adapter)
/* make low power state decision controlled by DMA coal */
reg = E1000_READ_REG(hw, E1000_PCIEMISC);
+ reg &= ~E1000_PCIEMISC_LX_DECISION;
+ E1000_WRITE_REG(hw, E1000_PCIEMISC, reg);
+ device_printf(dev, "DMA Coalescing enabled\n");
+
+ } else if (hw->mac.type == e1000_82580) {
+ u32 reg = E1000_READ_REG(hw, E1000_PCIEMISC);
+ E1000_WRITE_REG(hw, E1000_DMACR, 0);
E1000_WRITE_REG(hw, E1000_PCIEMISC,
- reg | E1000_PCIEMISC_LX_DECISION);
+ reg & ~E1000_PCIEMISC_LX_DECISION);
}
+reset_out:
E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
e1000_get_phy_info(hw);
e1000_check_for_link(hw);
@@ -2720,19 +3080,19 @@ igb_setup_interface(device_t dev, struct adapter *adapter)
return (-1);
}
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_mtu = ETHERMTU;
ifp->if_init = igb_init;
ifp->if_softc = adapter;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = igb_ioctl;
- ifp->if_start = igb_start;
#if __FreeBSD_version >= 800000
ifp->if_transmit = igb_mq_start;
ifp->if_qflush = igb_qflush;
-#endif
+#else
+ ifp->if_start = igb_start;
IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1);
ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1;
IFQ_SET_READY(&ifp->if_snd);
+#endif
ether_ifattach(ifp, adapter->hw.mac.addr);
@@ -2755,15 +3115,19 @@ igb_setup_interface(device_t dev, struct adapter *adapter)
* support full VLAN capability.
*/
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
- ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
- ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
+ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
+ | IFCAP_VLAN_HWTSO
+ | IFCAP_VLAN_MTU;
+ ifp->if_capenable |= IFCAP_VLAN_HWTAGGING
+ | IFCAP_VLAN_HWTSO
+ | IFCAP_VLAN_MTU;
/*
- ** Dont turn this on by default, if vlans are
+ ** Don't turn this on by default, if vlans are
** created on another pseudo device (eg. lagg)
** then vlan events are not passed thru, breaking
** operation, but with HW FILTER off it works. If
- ** using vlans directly on the em driver you can
+ ** using vlans directly on the igb driver you can
** enable this and get full hardware tag filtering.
*/
ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
@@ -2837,7 +3201,7 @@ igb_dma_malloc(struct adapter *adapter, bus_size_t size,
}
error = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr,
- BUS_DMA_NOWAIT, &dma->dma_map);
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
if (error) {
device_printf(adapter->dev,
"%s: bus_dmamem_alloc(%ju) failed: %d\n",
@@ -2966,7 +3330,7 @@ igb_allocate_queues(struct adapter *adapter)
}
#if __FreeBSD_version >= 800000
/* Allocate a buf ring */
- txr->br = buf_ring_alloc(IGB_BR_SIZE, M_DEVBUF,
+ txr->br = buf_ring_alloc(igb_buf_ring_size, M_DEVBUF,
M_WAITOK, &txr->tx_mtx);
#endif
}
@@ -3105,9 +3469,16 @@ igb_setup_transmit_ring(struct tx_ring *txr)
struct adapter *adapter = txr->adapter;
struct igb_tx_buffer *txbuf;
int i;
+#ifdef DEV_NETMAP
+ struct netmap_adapter *na = NA(adapter->ifp);
+ struct netmap_slot *slot;
+#endif /* DEV_NETMAP */
/* Clear the old descriptor contents */
IGB_TX_LOCK(txr);
+#ifdef DEV_NETMAP
+ slot = netmap_reset(na, NR_TX, txr->me, 0);
+#endif /* DEV_NETMAP */
bzero((void *)txr->tx_base,
(sizeof(union e1000_adv_tx_desc)) * adapter->num_tx_desc);
/* Reset indices */
@@ -3124,6 +3495,13 @@ igb_setup_transmit_ring(struct tx_ring *txr)
m_freem(txbuf->m_head);
txbuf->m_head = NULL;
}
+#ifdef DEV_NETMAP
+ if (slot) {
+ int si = netmap_idx_n2k(&na->tx_rings[txr->me], i);
+ /* no need to set the address */
+ netmap_load_map(txr->txtag, txbuf->map, NMB(slot + si));
+ }
+#endif /* DEV_NETMAP */
/* clear the watch index */
txbuf->next_eop = -1;
}
@@ -3195,7 +3573,7 @@ igb_initialize_transmit_units(struct adapter *adapter)
E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl);
}
- if (adapter->hw.mac.type == e1000_vfadapt)
+ if (adapter->vf_ifp)
return;
e1000_config_collision_dist(hw);
@@ -3289,8 +3667,9 @@ igb_free_transmit_buffers(struct tx_ring *txr)
* Setup work for hardware segmentation offload (TSO)
*
**********************************************************************/
-static boolean_t
-igb_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *hdrlen)
+static bool
+igb_tso_setup(struct tx_ring *txr, struct mbuf *mp, int ehdrlen,
+ struct ip *ip, struct tcphdr *th)
{
struct adapter *adapter = txr->adapter;
struct e1000_adv_tx_context_desc *TXD;
@@ -3298,45 +3677,15 @@ igb_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *hdrlen)
u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
u32 mss_l4len_idx = 0;
u16 vtag = 0;
- int ctxd, ehdrlen, ip_hlen, tcp_hlen;
- struct ether_vlan_header *eh;
- struct ip *ip;
- struct tcphdr *th;
-
-
- /*
- * Determine where frame payload starts.
- * Jump over vlan headers if already present
- */
- eh = mtod(mp, struct ether_vlan_header *);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
- ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- else
- ehdrlen = ETHER_HDR_LEN;
-
- /* Ensure we have at least the IP+TCP header in the first mbuf. */
- if (mp->m_len < ehdrlen + sizeof(struct ip) + sizeof(struct tcphdr))
- return FALSE;
+ int ctxd, ip_hlen, tcp_hlen;
- /* Only supports IPV4 for now */
ctxd = txr->next_avail_desc;
tx_buffer = &txr->tx_buffers[ctxd];
TXD = (struct e1000_adv_tx_context_desc *) &txr->tx_base[ctxd];
- ip = (struct ip *)(mp->m_data + ehdrlen);
- if (ip->ip_p != IPPROTO_TCP)
- return FALSE; /* 0 */
ip->ip_sum = 0;
ip_hlen = ip->ip_hl << 2;
- th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
- th->th_sum = in_pseudo(ip->ip_src.s_addr,
- ip->ip_dst.s_addr, htons(IPPROTO_TCP));
tcp_hlen = th->th_off << 2;
- /*
- * Calculate header length, this is used
- * in the transmit desc in igb_xmit
- */
- *hdrlen = ehdrlen + ip_hlen + tcp_hlen;
/* VLAN MACLEN IPLEN */
if (mp->m_flags & M_VLANTAG) {
@@ -3519,6 +3868,19 @@ igb_txeof(struct tx_ring *txr)
IGB_TX_LOCK_ASSERT(txr);
+#ifdef DEV_NETMAP
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(ifp);
+
+ selwakeuppri(&na->tx_rings[txr->me].si, PI_NET);
+ IGB_TX_UNLOCK(txr);
+ IGB_CORE_LOCK(adapter);
+ selwakeuppri(&na->tx_si, PI_NET);
+ IGB_CORE_UNLOCK(adapter);
+ IGB_TX_LOCK(txr);
+ return FALSE;
+ }
+#endif /* DEV_NETMAP */
if (txr->tx_avail == adapter->num_tx_desc) {
txr->queue_status = IGB_QUEUE_IDLE;
return FALSE;
@@ -3598,25 +3960,23 @@ igb_txeof(struct tx_ring *txr)
** for too long indicates a hang.
*/
if ((!processed) && ((ticks - txr->watchdog_time) > IGB_WATCHDOG))
- txr->queue_status = IGB_QUEUE_HUNG;
-
+ txr->queue_status |= IGB_QUEUE_HUNG;
/*
- * If we have enough room, clear IFF_DRV_OACTIVE
- * to tell the stack that it is OK to send packets.
+ * If we have a minimum free,
+ * clear depleted state bit
*/
- if (txr->tx_avail > IGB_TX_CLEANUP_THRESHOLD) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- /* All clean, turn off the watchdog */
- if (txr->tx_avail == adapter->num_tx_desc) {
- txr->queue_status = IGB_QUEUE_IDLE;
- return (FALSE);
- }
+ if (txr->tx_avail >= IGB_QUEUE_THRESHOLD)
+ txr->queue_status &= ~IGB_QUEUE_DEPLETED;
+
+ /* All clean, turn off the watchdog */
+ if (txr->tx_avail == adapter->num_tx_desc) {
+ txr->queue_status = IGB_QUEUE_IDLE;
+ return (FALSE);
}
return (TRUE);
}
-
/*********************************************************************
*
* Refresh mbuf buffers for RX descriptor rings
@@ -3634,17 +3994,25 @@ igb_refresh_mbufs(struct rx_ring *rxr, int limit)
bus_dma_segment_t pseg[1];
struct igb_rx_buf *rxbuf;
struct mbuf *mh, *mp;
- int i, nsegs, error, cleaned;
+ int i, j, nsegs, error;
+ bool refreshed = FALSE;
- i = rxr->next_to_refresh;
- cleaned = -1; /* Signify no completions */
- while (i != limit) {
+ i = j = rxr->next_to_refresh;
+ /*
+ ** Get one descriptor beyond
+ ** our work mark to control
+ ** the loop.
+ */
+ if (++j == adapter->num_rx_desc)
+ j = 0;
+
+ while (j != limit) {
rxbuf = &rxr->rx_buffers[i];
/* No hdr mbuf used with header split off */
if (rxr->hdr_split == FALSE)
goto no_split;
if (rxbuf->m_head == NULL) {
- mh = m_gethdr(M_DONTWAIT, MT_DATA);
+ mh = m_gethdr(M_NOWAIT, MT_DATA);
if (mh == NULL)
goto update;
} else
@@ -3670,7 +4038,7 @@ igb_refresh_mbufs(struct rx_ring *rxr, int limit)
htole64(hseg[0].ds_addr);
no_split:
if (rxbuf->m_pack == NULL) {
- mp = m_getjcl(M_DONTWAIT, MT_DATA,
+ mp = m_getjcl(M_NOWAIT, MT_DATA,
M_PKTHDR, adapter->rx_mbuf_sz);
if (mp == NULL)
goto update;
@@ -3693,18 +4061,17 @@ no_split:
BUS_DMASYNC_PREREAD);
rxr->rx_base[i].read.pkt_addr =
htole64(pseg[0].ds_addr);
+ refreshed = TRUE; /* I feel wefreshed :) */
- cleaned = i;
- /* Calculate next index */
- if (++i == adapter->num_rx_desc)
- i = 0;
- /* This is the work marker for refresh */
+ i = j; /* our next is precalculated */
rxr->next_to_refresh = i;
+ if (++j == adapter->num_rx_desc)
+ j = 0;
}
update:
- if (cleaned != -1) /* If we refreshed some, bump tail */
+ if (refreshed) /* update tail */
E1000_WRITE_REG(&adapter->hw,
- E1000_RDT(rxr->me), cleaned);
+ E1000_RDT(rxr->me), rxr->next_to_refresh);
return;
}
@@ -3796,12 +4163,11 @@ fail:
static void
igb_free_receive_ring(struct rx_ring *rxr)
{
- struct adapter *adapter;
+ struct adapter *adapter = rxr->adapter;
struct igb_rx_buf *rxbuf;
- int i;
- adapter = rxr->adapter;
- for (i = 0; i < adapter->num_rx_desc; i++) {
+
+ for (int i = 0; i < adapter->num_rx_desc; i++) {
rxbuf = &rxr->rx_buffers[i];
if (rxbuf->m_head != NULL) {
bus_dmamap_sync(rxr->htag, rxbuf->hmap,
@@ -3838,6 +4204,10 @@ igb_setup_receive_ring(struct rx_ring *rxr)
bus_dma_segment_t pseg[1], hseg[1];
struct lro_ctrl *lro = &rxr->lro;
int rsize, nsegs, error = 0;
+#ifdef DEV_NETMAP
+ struct netmap_adapter *na = NA(rxr->adapter->ifp);
+ struct netmap_slot *slot;
+#endif /* DEV_NETMAP */
adapter = rxr->adapter;
dev = adapter->dev;
@@ -3845,6 +4215,9 @@ igb_setup_receive_ring(struct rx_ring *rxr)
/* Clear the ring contents */
IGB_RX_LOCK(rxr);
+#ifdef DEV_NETMAP
+ slot = netmap_reset(na, NR_RX, rxr->me, 0);
+#endif /* DEV_NETMAP */
rsize = roundup2(adapter->num_rx_desc *
sizeof(union e1000_adv_rx_desc), IGB_DBA_ALIGN);
bzero((void *)rxr->rx_base, rsize);
@@ -3863,11 +4236,25 @@ igb_setup_receive_ring(struct rx_ring *rxr)
struct mbuf *mh, *mp;
rxbuf = &rxr->rx_buffers[j];
+#ifdef DEV_NETMAP
+ if (slot) {
+ /* slot sj is mapped to the i-th NIC-ring entry */
+ int sj = netmap_idx_n2k(&na->rx_rings[rxr->me], j);
+ uint64_t paddr;
+ void *addr;
+
+ addr = PNMB(slot + sj, &paddr);
+ netmap_load_map(rxr->ptag, rxbuf->pmap, addr);
+ /* Update descriptor */
+ rxr->rx_base[j].read.pkt_addr = htole64(paddr);
+ continue;
+ }
+#endif /* DEV_NETMAP */
if (rxr->hdr_split == FALSE)
goto skip_head;
/* First the header */
- rxbuf->m_head = m_gethdr(M_DONTWAIT, MT_DATA);
+ rxbuf->m_head = m_gethdr(M_NOWAIT, MT_DATA);
if (rxbuf->m_head == NULL) {
error = ENOBUFS;
goto fail;
@@ -3889,7 +4276,7 @@ igb_setup_receive_ring(struct rx_ring *rxr)
skip_head:
/* Now the payload cluster */
- rxbuf->m_pack = m_getjcl(M_DONTWAIT, MT_DATA,
+ rxbuf->m_pack = m_getjcl(M_NOWAIT, MT_DATA,
M_PKTHDR, adapter->rx_mbuf_sz);
if (rxbuf->m_pack == NULL) {
error = ENOBUFS;
@@ -3911,7 +4298,7 @@ skip_head:
/* Setup our descriptor indices */
rxr->next_to_check = 0;
- rxr->next_to_refresh = 0;
+ rxr->next_to_refresh = adapter->num_rx_desc - 1;
rxr->lro_enabled = FALSE;
rxr->rx_split_packets = 0;
rxr->rx_bytes = 0;
@@ -3949,6 +4336,7 @@ fail:
return (error);
}
+
/*********************************************************************
*
* Initialize all receive rings.
@@ -3971,8 +4359,8 @@ fail:
* the rings that completed, the failing case will have
* cleaned up for itself. 'i' is the endpoint.
*/
- for (int j = 0; j > i; ++j) {
- rxr = &adapter->rx_rings[i];
+ for (int j = 0; j < i; ++j) {
+ rxr = &adapter->rx_rings[j];
IGB_RX_LOCK(rxr);
igb_free_receive_ring(rxr);
IGB_RX_UNLOCK(rxr);
@@ -4006,7 +4394,7 @@ igb_initialize_receive_units(struct adapter *adapter)
/*
** Set up for header split
*/
- if (rxr->hdr_split) {
+ if (igb_header_split) {
/* Use a standard mbuf for the header */
srrctl |= IGB_HDR_BUF << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
@@ -4144,9 +4532,29 @@ igb_initialize_receive_units(struct adapter *adapter)
* - needs to be after enable
*/
for (int i = 0; i < adapter->num_queues; i++) {
- E1000_WRITE_REG(hw, E1000_RDH(i), 0);
- E1000_WRITE_REG(hw, E1000_RDT(i),
- adapter->num_rx_desc - 1);
+ rxr = &adapter->rx_rings[i];
+ E1000_WRITE_REG(hw, E1000_RDH(i), rxr->next_to_check);
+#ifdef DEV_NETMAP
+ /*
+ * an init() while a netmap client is active must
+ * preserve the rx buffers passed to userspace.
+ * In this driver it means we adjust RDT to
+ * somthing different from next_to_refresh
+ * (which is not used in netmap mode).
+ */
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(adapter->ifp);
+ struct netmap_kring *kring = &na->rx_rings[i];
+ int t = rxr->next_to_refresh - kring->nr_hwavail;
+
+ if (t >= adapter->num_rx_desc)
+ t -= adapter->num_rx_desc;
+ else if (t < 0)
+ t += adapter->num_rx_desc;
+ E1000_WRITE_REG(hw, E1000_RDT(i), t);
+ } else
+#endif /* DEV_NETMAP */
+ E1000_WRITE_REG(hw, E1000_RDT(i), rxr->next_to_refresh);
}
return;
}
@@ -4325,6 +4733,20 @@ igb_rxeof(struct igb_queue *que, int count, int *done)
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+#ifdef DEV_NETMAP
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(ifp);
+
+ na->rx_rings[rxr->me].nr_kflags |= NKR_PENDINTR;
+ selwakeuppri(&na->rx_rings[rxr->me].si, PI_NET);
+ IGB_RX_UNLOCK(rxr);
+ IGB_CORE_LOCK(adapter);
+ selwakeuppri(&na->rx_si, PI_NET);
+ IGB_CORE_UNLOCK(adapter);
+ return (0);
+ }
+#endif /* DEV_NETMAP */
+
/* Main clean loop */
for (i = rxr->next_to_check; count != 0;) {
struct mbuf *sendmp, *mh, *mp;
@@ -4344,14 +4766,18 @@ igb_rxeof(struct igb_queue *que, int count, int *done)
rxbuf = &rxr->rx_buffers[i];
plen = le16toh(cur->wb.upper.length);
ptype = le32toh(cur->wb.lower.lo_dword.data) & IGB_PKTTYPE_MASK;
- vtag = le16toh(cur->wb.upper.vlan);
+ if ((adapter->hw.mac.type == e1000_i350) &&
+ (staterr & E1000_RXDEXT_STATERR_LB))
+ vtag = be16toh(cur->wb.upper.vlan);
+ else
+ vtag = le16toh(cur->wb.upper.vlan);
hdr = le16toh(cur->wb.lower.lo_dword.hs_rss.hdr_info);
eop = ((staterr & E1000_RXD_STAT_EOP) == E1000_RXD_STAT_EOP);
/* Make sure all segments of a bad packet are discarded */
if (((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) != 0) ||
(rxr->discard)) {
- ifp->if_ierrors++;
+ adapter->dropped_pkts++;
++rxr->rx_discarded;
if (!eop) /* Catch subsequent segs */
rxr->discard = TRUE;
@@ -4479,10 +4905,8 @@ next_desc:
}
/* Catch any remainders */
- if (processed != 0) {
+ if (igb_rx_unrefreshed(rxr))
igb_refresh_mbufs(rxr, i);
- processed = 0;
- }
rxr->next_to_check = i;
@@ -4494,19 +4918,11 @@ next_desc:
tcp_lro_flush(lro, queued);
}
- IGB_RX_UNLOCK(rxr);
-
if (done != NULL)
- *done = rxdone;
+ *done += rxdone;
- /*
- ** We still have cleaning to do?
- ** Schedule another interrupt if so.
- */
- if ((staterr & E1000_RXD_STAT_DD) != 0)
- return (TRUE);
-
- return (FALSE);
+ IGB_RX_UNLOCK(rxr);
+ return ((staterr & E1000_RXD_STAT_DD) ? TRUE : FALSE);
}
/*********************************************************************
@@ -4581,9 +4997,9 @@ igb_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
bit = vtag & 0x1F;
adapter->shadow_vfta[index] |= (1 << bit);
++adapter->num_vlans;
- /* Re-init to load the changes */
+ /* Change hw filter setting */
if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
- igb_init_locked(adapter);
+ igb_setup_vlan_hw_support(adapter);
IGB_CORE_UNLOCK(adapter);
}
@@ -4608,9 +5024,9 @@ igb_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
bit = vtag & 0x1F;
adapter->shadow_vfta[index] &= ~(1 << bit);
--adapter->num_vlans;
- /* Re-init to load the changes */
+ /* Change hw filter setting */
if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
- igb_init_locked(adapter);
+ igb_setup_vlan_hw_support(adapter);
IGB_CORE_UNLOCK(adapter);
}
@@ -4618,49 +5034,48 @@ static void
igb_setup_vlan_hw_support(struct adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
+ struct ifnet *ifp = adapter->ifp;
u32 reg;
- /*
- ** We get here thru init_locked, meaning
- ** a soft reset, this has already cleared
- ** the VFTA and other state, so if there
- ** have been no vlan's registered do nothing.
- */
- if (adapter->num_vlans == 0)
- return;
+ if (adapter->vf_ifp) {
+ e1000_rlpml_set_vf(hw,
+ adapter->max_frame_size + VLAN_TAG_SIZE);
+ return;
+ }
+
+ reg = E1000_READ_REG(hw, E1000_CTRL);
+ reg |= E1000_CTRL_VME;
+ E1000_WRITE_REG(hw, E1000_CTRL, reg);
+
+ /* Enable the Filter Table */
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
+ reg = E1000_READ_REG(hw, E1000_RCTL);
+ reg &= ~E1000_RCTL_CFIEN;
+ reg |= E1000_RCTL_VFE;
+ E1000_WRITE_REG(hw, E1000_RCTL, reg);
+ }
+ /* Update the frame size */
+ E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
+ adapter->max_frame_size + VLAN_TAG_SIZE);
+
+ /* Don't bother with table if no vlans */
+ if ((adapter->num_vlans == 0) ||
+ ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0))
+ return;
/*
** A soft reset zero's out the VFTA, so
** we need to repopulate it now.
*/
for (int i = 0; i < IGB_VFTA_SIZE; i++)
if (adapter->shadow_vfta[i] != 0) {
- if (hw->mac.type == e1000_vfadapt)
+ if (adapter->vf_ifp)
e1000_vfta_set_vf(hw,
adapter->shadow_vfta[i], TRUE);
else
- E1000_WRITE_REG_ARRAY(hw, E1000_VFTA,
- i, adapter->shadow_vfta[i]);
+ e1000_write_vfta(hw,
+ i, adapter->shadow_vfta[i]);
}
-
- if (hw->mac.type == e1000_vfadapt)
- e1000_rlpml_set_vf(hw,
- adapter->max_frame_size + VLAN_TAG_SIZE);
- else {
- reg = E1000_READ_REG(hw, E1000_CTRL);
- reg |= E1000_CTRL_VME;
- E1000_WRITE_REG(hw, E1000_CTRL, reg);
-
- /* Enable the Filter Table */
- reg = E1000_READ_REG(hw, E1000_RCTL);
- reg &= ~E1000_RCTL_CFIEN;
- reg |= E1000_RCTL_VFE;
- E1000_WRITE_REG(hw, E1000_RCTL, reg);
-
- /* Update the frame size */
- E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
- adapter->max_frame_size + VLAN_TAG_SIZE);
- }
}
static void
@@ -4668,12 +5083,10 @@ igb_enable_intr(struct adapter *adapter)
{
/* With RSS set up what to auto clear */
if (adapter->msix_mem) {
- E1000_WRITE_REG(&adapter->hw, E1000_EIAC,
- adapter->eims_mask);
- E1000_WRITE_REG(&adapter->hw, E1000_EIAM,
- adapter->eims_mask);
- E1000_WRITE_REG(&adapter->hw, E1000_EIMS,
- adapter->eims_mask);
+ u32 mask = (adapter->que_mask | adapter->link_mask);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIAC, mask);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIAM, mask);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIMS, mask);
E1000_WRITE_REG(&adapter->hw, E1000_IMS,
E1000_IMS_LSC);
} else {
@@ -4750,7 +5163,7 @@ igb_get_hw_control(struct adapter *adapter)
{
u32 ctrl_ext;
- if (adapter->hw.mac.type == e1000_vfadapt)
+ if (adapter->vf_ifp)
return;
/* Let firmware know the driver has taken over */
@@ -4770,7 +5183,7 @@ igb_release_hw_control(struct adapter *adapter)
{
u32 ctrl_ext;
- if (adapter->hw.mac.type == e1000_vfadapt)
+ if (adapter->vf_ifp)
return;
/* Let firmware taken over control of h/w */
@@ -4849,7 +5262,7 @@ igb_update_stats_counters(struct adapter *adapter)
** small controlled set of stats, do only
** those and return.
*/
- if (adapter->hw.mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
igb_update_vf_stats_counters(adapter);
return;
}
@@ -5190,7 +5603,7 @@ igb_add_hw_stats(struct adapter *adapter)
** VF adapter has a very limited set of stats
** since its not managing the metal, so to speak.
*/
- if (adapter->hw.mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
CTLFLAG_RD, &stats->gprc,
"Good Packets Received");
@@ -5507,7 +5920,7 @@ igb_print_nvm_info(struct adapter *adapter)
}
static void
-igb_add_rx_process_limit(struct adapter *adapter, const char *name,
+igb_set_sysctl_value(struct adapter *adapter, const char *name,
const char *description, int *limit, int value)
{
*limit = value;
@@ -5515,3 +5928,112 @@ igb_add_rx_process_limit(struct adapter *adapter, const char *name,
SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
}
+
+/*
+** Set flow control using sysctl:
+** Flow control values:
+** 0 - off
+** 1 - rx pause
+** 2 - tx pause
+** 3 - full
+*/
+static int
+igb_set_flowcntl(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ static int input = 3; /* default is full */
+ struct adapter *adapter = (struct adapter *) arg1;
+
+ error = sysctl_handle_int(oidp, &input, 0, req);
+
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ switch (input) {
+ case e1000_fc_rx_pause:
+ case e1000_fc_tx_pause:
+ case e1000_fc_full:
+ case e1000_fc_none:
+ adapter->hw.fc.requested_mode = input;
+ adapter->fc = input;
+ break;
+ default:
+ /* Do nothing */
+ return (error);
+ }
+
+ adapter->hw.fc.current_mode = adapter->hw.fc.requested_mode;
+ e1000_force_mac_fc(&adapter->hw);
+ return (error);
+}
+
+/*
+** Manage DMA Coalesce:
+** Control values:
+** 0/1 - off/on
+** Legal timer values are:
+** 250,500,1000-10000 in thousands
+*/
+static int
+igb_sysctl_dmac(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ int error;
+
+ error = sysctl_handle_int(oidp, &adapter->dmac, 0, req);
+
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ switch (adapter->dmac) {
+ case 0:
+ /*Disabling */
+ break;
+ case 1: /* Just enable and use default */
+ adapter->dmac = 1000;
+ break;
+ case 250:
+ case 500:
+ case 1000:
+ case 2000:
+ case 3000:
+ case 4000:
+ case 5000:
+ case 6000:
+ case 7000:
+ case 8000:
+ case 9000:
+ case 10000:
+ /* Legal values - allow */
+ break;
+ default:
+ /* Do nothing, illegal value */
+ adapter->dmac = 0;
+ return (error);
+ }
+ /* Reinit the interface */
+ igb_init(adapter);
+ return (error);
+}
+
+/*
+** Manage Energy Efficient Ethernet:
+** Control values:
+** 0/1 - enabled/disabled
+*/
+static int
+igb_sysctl_eee(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *adapter = (struct adapter *) arg1;
+ int error, value;
+
+ value = adapter->hw.dev_spec._82575.eee_disable;
+ error = sysctl_handle_int(oidp, &value, 0, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ IGB_CORE_LOCK(adapter);
+ adapter->hw.dev_spec._82575.eee_disable = (value != 0);
+ igb_init_locked(adapter);
+ IGB_CORE_UNLOCK(adapter);
+ return (0);
+}
diff --git a/freebsd/sys/dev/e1000/if_igb.h b/freebsd/sys/dev/e1000/if_igb.h
index c77e9f17..51d8987a 100644
--- a/freebsd/sys/dev/e1000/if_igb.h
+++ b/freebsd/sys/dev/e1000/if_igb.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@
#define IGB_MAX_TXD 4096
/*
- * IGB_RXD: Maximum number of Transmit Descriptors
+ * IGB_RXD: Maximum number of Receive Descriptors
*
* This value is the number of receive descriptors allocated by the driver.
* Increasing this value allows the driver to buffer more incoming packets.
@@ -132,10 +132,9 @@
/*
* This parameter controls when the driver calls the routine to reclaim
- * transmit descriptors.
+ * transmit descriptors. Cleaning earlier seems a win.
*/
-#define IGB_TX_CLEANUP_THRESHOLD (adapter->num_tx_desc / 8)
-#define IGB_TX_OP_THRESHOLD (adapter->num_tx_desc / 32)
+#define IGB_TX_CLEANUP_THRESHOLD (adapter->num_tx_desc / 2)
/*
* This parameter controls whether or not autonegotation is enabled.
@@ -180,8 +179,7 @@
#define IGB_TX_PTHRESH 8
#define IGB_TX_HTHRESH 1
-#define IGB_TX_WTHRESH (((hw->mac.type == e1000_82576 || \
- hw->mac.type == e1000_vfadapt) && \
+#define IGB_TX_WTHRESH ((hw->mac.type != e1000_82575 && \
adapter->msix_mem) ? 1 : 16)
#define MAX_NUM_MULTICAST_ADDRESSES 128
@@ -190,9 +188,13 @@
#define IGB_TX_BUFFER_SIZE ((uint32_t) 1514)
#define IGB_FC_PAUSE_TIME 0x0680
#define IGB_EEPROM_APME 0x400;
-#define IGB_QUEUE_IDLE 0
-#define IGB_QUEUE_WORKING 1
-#define IGB_QUEUE_HUNG 2
+/* Queue minimum free for use */
+#define IGB_QUEUE_THRESHOLD (adapter->num_tx_desc / 8)
+/* Queue bit defines */
+#define IGB_QUEUE_IDLE 1
+#define IGB_QUEUE_WORKING 2
+#define IGB_QUEUE_HUNG 4
+#define IGB_QUEUE_DEPLETED 8
/*
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
@@ -297,6 +299,7 @@ struct tx_ring {
struct igb_tx_buffer *tx_buffers;
#if __FreeBSD_version >= 800000
struct buf_ring *br;
+ struct task txq_task;
#endif
bus_dma_tag_t txtag;
@@ -361,7 +364,7 @@ struct adapter {
struct resource *msix_mem;
struct resource *res;
void *tag;
- u32 eims_mask;
+ u32 que_mask;
int linkvec;
int link_mask;
@@ -378,6 +381,7 @@ struct adapter {
struct mtx core_mtx;
int igb_insert_vlan_header;
u16 num_queues;
+ u16 vf_ifp; /* a VF interface */
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
@@ -396,10 +400,13 @@ struct adapter {
u32 shadow_vfta[IGB_VFTA_SIZE];
/* Info about the interface */
- u8 link_active;
+ u16 link_active;
+ u16 fc;
u16 link_speed;
u16 link_duplex;
u32 smartspeed;
+ u32 dmac;
+ int enable_aim;
/* Interface queues */
struct igb_queue *queues;
@@ -481,6 +488,21 @@ struct igb_rx_buf {
bus_dmamap_t pmap; /* bus_dma map for packet */
};
+/*
+** Find the number of unrefreshed RX descriptors
+*/
+static inline u16
+igb_rx_unrefreshed(struct rx_ring *rxr)
+{
+ struct adapter *adapter = rxr->adapter;
+
+ if (rxr->next_to_check > rxr->next_to_refresh)
+ return (rxr->next_to_check - rxr->next_to_refresh - 1);
+ else
+ return ((adapter->num_rx_desc + rxr->next_to_check) -
+ rxr->next_to_refresh - 1);
+}
+
#define IGB_CORE_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->core_mtx, _name, "IGB Core Lock", MTX_DEF)
#define IGB_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
@@ -509,7 +531,7 @@ struct igb_rx_buf {
cur |= new; \
}
-#if __FreeBSD_version < 800504
+#if __FreeBSD_version >= 800000 && __FreeBSD_version < 800504
static __inline int
drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
{
diff --git a/freebsd/sys/dev/e1000/if_lem.c b/freebsd/sys/dev/e1000/if_lem.c
index 402a6f48..4c4bbf2d 100644
--- a/freebsd/sys/dev/e1000/if_lem.c
+++ b/freebsd/sys/dev/e1000/if_lem.c
@@ -2,7 +2,7 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2012, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,7 @@
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include <rtems/bsd/local/opt_device_polling.h>
#include <rtems/bsd/local/opt_inet.h>
+#include <rtems/bsd/local/opt_inet6.h>
#endif
#include <rtems/bsd/sys/param.h>
@@ -91,7 +92,7 @@
/*********************************************************************
* Legacy Em Driver version:
*********************************************************************/
-char lem_driver_version[] = "1.0.3";
+char lem_driver_version[] = "1.0.5";
/*********************************************************************
* PCI Device ID Table
@@ -245,15 +246,12 @@ static void lem_enable_wakeup(device_t);
static int lem_enable_phy_wakeup(struct adapter *);
static void lem_led_func(void *, int);
-#ifdef EM_LEGACY_IRQ
static void lem_intr(void *);
-#else /* FAST IRQ */
static int lem_irq_fast(void *);
static void lem_handle_rxtx(void *context, int pending);
static void lem_handle_link(void *context, int pending);
static void lem_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int);
-#endif /* ~EM_LEGACY_IRQ */
#ifdef DEVICE_POLLING
static poll_handler_t lem_poll;
@@ -271,7 +269,7 @@ static device_method_t lem_methods[] = {
DEVMETHOD(device_shutdown, lem_shutdown),
DEVMETHOD(device_suspend, lem_suspend),
DEVMETHOD(device_resume, lem_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t lem_driver = {
@@ -310,11 +308,13 @@ TUNABLE_INT("hw.em.txd", &lem_txd);
TUNABLE_INT("hw.em.smart_pwr_down", &lem_smart_pwr_down);
TUNABLE_INT("hw.em.sbp", &lem_debug_sbp);
-#ifndef EM_LEGACY_IRQ
+/* Interrupt style - default to fast */
+static int lem_use_legacy_irq = 0;
+TUNABLE_INT("hw.em.use_legacy_irq", &lem_use_legacy_irq);
+
/* How many packets rxeof tries to clean at a time */
static int lem_rx_process_limit = 100;
TUNABLE_INT("hw.em.rx_process_limit", &lem_rx_process_limit);
-#endif
/* Flow control setting - default to FULL */
static int lem_fc_setting = e1000_fc_full;
@@ -323,6 +323,10 @@ TUNABLE_INT("hw.em.fc_setting", &lem_fc_setting);
/* Global used in WOL setup with multiport cards */
static int global_quad_port_a = 0;
+#ifdef DEV_NETMAP /* see ixgbe.c for details */
+#include <dev/netmap/if_lem_netmap.h>
+#endif /* DEV_NETMAP */
+
/*********************************************************************
* Device identification routine
*
@@ -447,16 +451,14 @@ lem_attach(device_t dev)
lem_tx_abs_int_delay_dflt);
}
-#ifndef EM_LEGACY_IRQ
/* Sysctls for limiting the amount of work done in the taskqueue */
lem_add_rx_process_limit(adapter, "rx_processing_limit",
"max number of rx packets to process", &adapter->rx_process_limit,
lem_rx_process_limit);
-#endif
/* Sysctl for setting the interface flow control */
lem_set_flow_cntrl(adapter, "flow_control",
- "max number of rx packets to process",
+ "flow control setting",
&adapter->fc_setting, lem_fc_setting);
/*
@@ -653,6 +655,9 @@ lem_attach(device_t dev)
adapter->led_dev = led_create(lem_led_func, adapter,
device_get_nameunit(dev));
+#ifdef DEV_NETMAP
+ lem_netmap_attach(adapter);
+#endif /* DEV_NETMAP */
INIT_DEBUGOUT("lem_attach: end");
return (0);
@@ -731,6 +736,9 @@ lem_detach(device_t dev)
callout_drain(&adapter->timer);
callout_drain(&adapter->tx_fifo_timer);
+#ifdef DEV_NETMAP
+ netmap_detach(ifp);
+#endif /* DEV_NETMAP */
lem_free_pci_resources(adapter);
bus_generic_detach(dev);
if_free(ifp);
@@ -887,11 +895,12 @@ static int
lem_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct adapter *adapter = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *)data;
-#ifdef INET
- struct ifaddr *ifa = (struct ifaddr *)data;
+ struct ifreq *ifr = (struct ifreq *)data;
+#if defined(INET) || defined(INET6)
+ struct ifaddr *ifa = (struct ifaddr *)data;
#endif
- int error = 0;
+ bool avoid_reset = FALSE;
+ int error = 0;
if (adapter->in_detach)
return (error);
@@ -899,23 +908,26 @@ lem_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
switch (command) {
case SIOCSIFADDR:
#ifdef INET
- if (ifa->ifa_addr->sa_family == AF_INET) {
- /*
- * XXX
- * Since resetting hardware takes a very long time
- * and results in link renegotiation we only
- * initialize the hardware only when it is absolutely
- * required.
- */
+ if (ifa->ifa_addr->sa_family == AF_INET)
+ avoid_reset = TRUE;
+#endif
+#ifdef INET6
+ if (ifa->ifa_addr->sa_family == AF_INET6)
+ avoid_reset = TRUE;
+#endif
+ /*
+ ** Calling init results in link renegotiation,
+ ** so we avoid doing it when possible.
+ */
+ if (avoid_reset) {
ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- EM_CORE_LOCK(adapter);
- lem_init_locked(adapter);
- EM_CORE_UNLOCK(adapter);
- }
- arp_ifinit(ifp, ifa);
- } else
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ lem_init(adapter);
+#ifdef INET
+ if (!(ifp->if_flags & IFF_NOARP))
+ arp_ifinit(ifp, ifa);
#endif
+ } else
error = ether_ioctl(ifp, command, data);
break;
case SIOCSIFMTU:
@@ -1184,22 +1196,6 @@ lem_init_locked(struct adapter *adapter)
callout_reset(&adapter->timer, hz, lem_local_timer, adapter);
e1000_clear_hw_cntrs_base_generic(&adapter->hw);
- /* MSI/X configuration for 82574 */
- if (adapter->hw.mac.type == e1000_82574) {
- int tmp;
- tmp = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
- tmp |= E1000_CTRL_EXT_PBA_CLR;
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, tmp);
- /*
- ** Set the IVAR - interrupt vector routing.
- ** Each nibble represents a vector, high bit
- ** is enable, other 3 bits are the MSIX table
- ** entry, we map RXQ0 to 0, TXQ0 to 1, and
- ** Link (other) to 2, hence the magic number.
- */
- E1000_WRITE_REG(&adapter->hw, E1000_IVAR, 0x800A0908);
- }
-
#ifdef DEVICE_POLLING
/*
* Only enable interrupts if we are not polling, make sure
@@ -1214,9 +1210,6 @@ lem_init_locked(struct adapter *adapter)
/* AMT based hardware can now take control from firmware */
if (adapter->has_manage && adapter->has_amt)
lem_get_hw_control(adapter);
-
- /* Don't reset the phy next time init gets called */
- adapter->hw.phy.reset_disable = TRUE;
}
static void
@@ -1271,7 +1264,6 @@ lem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
}
#endif /* DEVICE_POLLING */
-#ifdef EM_LEGACY_IRQ
/*********************************************************************
*
* Legacy Interrupt Service routine
@@ -1285,7 +1277,8 @@ lem_intr(void *arg)
u32 reg_icr;
- if (ifp->if_capenable & IFCAP_POLLING)
+ if ((ifp->if_capenable & IFCAP_POLLING) ||
+ ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))
return;
EM_CORE_LOCK(adapter);
@@ -1293,11 +1286,10 @@ lem_intr(void *arg)
if (reg_icr & E1000_ICR_RXO)
adapter->rx_overruns++;
- if ((reg_icr == 0xffffffff) || (reg_icr == 0))
- goto out;
-
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- goto out;
+ if ((reg_icr == 0xffffffff) || (reg_icr == 0)) {
+ EM_CORE_UNLOCK(adapter);
+ return;
+ }
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
callout_stop(&adapter->timer);
@@ -1307,23 +1299,22 @@ lem_intr(void *arg)
lem_tx_purge(adapter);
callout_reset(&adapter->timer, hz,
lem_local_timer, adapter);
- goto out;
+ EM_CORE_UNLOCK(adapter);
+ return;
}
- EM_TX_LOCK(adapter);
+ EM_CORE_UNLOCK(adapter);
lem_rxeof(adapter, -1, NULL);
+
+ EM_TX_LOCK(adapter);
lem_txeof(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
lem_start_locked(ifp);
EM_TX_UNLOCK(adapter);
-
-out:
- EM_CORE_UNLOCK(adapter);
return;
}
-#else /* EM_FAST_IRQ, then fast interrupt routines only */
static void
lem_handle_link(void *context, int pending)
@@ -1407,7 +1398,6 @@ lem_irq_fast(void *arg)
adapter->rx_overruns++;
return FILTER_HANDLED;
}
-#endif /* ~EM_LEGACY_IRQ */
/*********************************************************************
@@ -1515,11 +1505,6 @@ lem_media_change(struct ifnet *ifp)
device_printf(adapter->dev, "Unsupported media type\n");
}
- /* As the speed/duplex settings my have changed we need to
- * reset the PHY.
- */
- adapter->hw.phy.reset_disable = FALSE;
-
lem_init_locked(adapter);
EM_CORE_UNLOCK(adapter);
@@ -1588,7 +1573,7 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp)
if (error == EFBIG) {
struct mbuf *m;
- m = m_defrag(*m_headp, M_DONTWAIT);
+ m = m_defrag(*m_headp, M_NOWAIT);
if (m == NULL) {
adapter->mbuf_alloc_failed++;
m_freem(*m_headp);
@@ -2209,19 +2194,21 @@ lem_allocate_irq(struct adapter *adapter)
return (ENXIO);
}
-#ifdef EM_LEGACY_IRQ
- /* We do Legacy setup */
- if ((error = bus_setup_intr(dev, adapter->res[0],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter,
- &adapter->tag[0])) != 0) {
- device_printf(dev, "Failed to register interrupt handler");
- return (error);
+ /* Do Legacy setup? */
+ if (lem_use_legacy_irq) {
+ if ((error = bus_setup_intr(dev, adapter->res[0],
+ INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter,
+ &adapter->tag[0])) != 0) {
+ device_printf(dev,
+ "Failed to register interrupt handler");
+ return (error);
+ }
+ return (0);
}
-#else /* FAST_IRQ */
/*
- * Try allocating a fast interrupt and the associated deferred
- * processing contexts.
+ * Use a Fast interrupt and the associated
+ * deferred processing contexts.
*/
TASK_INIT(&adapter->rxtx_task, 0, lem_handle_rxtx, adapter);
TASK_INIT(&adapter->link_task, 0, lem_handle_link, adapter);
@@ -2238,7 +2225,6 @@ lem_allocate_irq(struct adapter *adapter)
adapter->tq = NULL;
return (error);
}
-#endif /* EM_LEGACY_IRQ */
return (0);
}
@@ -2349,7 +2335,6 @@ lem_setup_interface(device_t dev, struct adapter *adapter)
return (-1);
}
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_mtu = ETHERMTU;
ifp->if_init = lem_init;
ifp->if_softc = adapter;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
@@ -2644,6 +2629,11 @@ static void
lem_setup_transmit_structures(struct adapter *adapter)
{
struct em_buffer *tx_buffer;
+#ifdef DEV_NETMAP
+ /* we are already locked */
+ struct netmap_adapter *na = NA(adapter->ifp);
+ struct netmap_slot *slot = netmap_reset(na, NR_TX, 0, 0);
+#endif /* DEV_NETMAP */
/* Clear the old ring contents */
bzero(adapter->tx_desc_base,
@@ -2657,10 +2647,24 @@ lem_setup_transmit_structures(struct adapter *adapter)
bus_dmamap_unload(adapter->txtag, tx_buffer->map);
m_freem(tx_buffer->m_head);
tx_buffer->m_head = NULL;
+#ifdef DEV_NETMAP
+ if (slot) {
+ /* the i-th NIC entry goes to slot si */
+ int si = netmap_idx_n2k(&na->tx_rings[0], i);
+ uint64_t paddr;
+ void *addr;
+
+ addr = PNMB(slot + si, &paddr);
+ adapter->tx_desc_base[si].buffer_addr = htole64(paddr);
+ /* reload the map for netmap mode */
+ netmap_load_map(adapter->txtag, tx_buffer->map, addr);
+ }
+#endif /* DEV_NETMAP */
tx_buffer->next_eop = -1;
}
/* Reset state */
+ adapter->last_hw_offload = 0;
adapter->next_avail_tx_desc = 0;
adapter->next_tx_to_clean = 0;
adapter->num_tx_desc_avail = adapter->num_tx_desc;
@@ -2957,6 +2961,12 @@ lem_txeof(struct adapter *adapter)
EM_TX_LOCK_ASSERT(adapter);
+#ifdef DEV_NETMAP
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ selwakeuppri(&NA(ifp)->tx_rings[0].si, PI_NET);
+ return;
+ }
+#endif /* DEV_NETMAP */
if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
return;
@@ -3072,7 +3082,7 @@ lem_get_buf(struct adapter *adapter, int i)
struct em_buffer *rx_buffer;
int error, nsegs;
- m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
adapter->mbuf_cluster_failed++;
return (ENOBUFS);
@@ -3187,6 +3197,11 @@ lem_setup_receive_structures(struct adapter *adapter)
{
struct em_buffer *rx_buffer;
int i, error;
+#ifdef DEV_NETMAP
+ /* we are already under lock */
+ struct netmap_adapter *na = NA(adapter->ifp);
+ struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0);
+#endif
/* Reset descriptor ring */
bzero(adapter->rx_desc_base,
@@ -3206,6 +3221,20 @@ lem_setup_receive_structures(struct adapter *adapter)
/* Allocate new ones. */
for (i = 0; i < adapter->num_rx_desc; i++) {
+#ifdef DEV_NETMAP
+ if (slot) {
+ /* the i-th NIC entry goes to slot si */
+ int si = netmap_idx_n2k(&na->rx_rings[0], i);
+ uint64_t paddr;
+ void *addr;
+
+ addr = PNMB(slot + si, &paddr);
+ netmap_load_map(adapter->rxtag, rx_buffer->map, addr);
+ /* Update descriptor */
+ adapter->rx_desc_base[i].buffer_addr = htole64(paddr);
+ continue;
+ }
+#endif /* DEV_NETMAP */
error = lem_get_buf(adapter, i);
if (error)
return (error);
@@ -3253,20 +3282,6 @@ lem_initialize_receive_unit(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR);
}
- /*
- ** When using MSIX interrupts we need to throttle
- ** using the EITR register (82574 only)
- */
- if (adapter->msix)
- for (int i = 0; i < 4; i++)
- E1000_WRITE_REG(&adapter->hw,
- E1000_EITR_82574(i), DEFAULT_ITR);
-
- /* Disable accelerated ackknowledge */
- if (adapter->hw.mac.type == e1000_82574)
- E1000_WRITE_REG(&adapter->hw,
- E1000_RFCTL, E1000_RFCTL_ACK_DIS);
-
/* Setup the Base and Length of the Rx Descriptor Ring */
bus_addr = adapter->rxdma.dma_paddr;
E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0),
@@ -3330,6 +3345,18 @@ lem_initialize_receive_unit(struct adapter *adapter)
* Tail Descriptor Pointers
*/
E1000_WRITE_REG(&adapter->hw, E1000_RDH(0), 0);
+#ifdef DEV_NETMAP
+ /* preserve buffers already made available to clients */
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(adapter->ifp);
+ struct netmap_kring *kring = &na->rx_rings[0];
+ int t = na->num_rx_desc - 1 - kring->nr_hwavail;
+
+ if (t >= na->num_rx_desc)
+ t -= na->num_rx_desc;
+ E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), t);
+ } else
+#endif /* DEV_NETMAP */
E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), adapter->num_rx_desc - 1);
return;
@@ -3400,7 +3427,7 @@ lem_free_receive_structures(struct adapter *adapter)
static bool
lem_rxeof(struct adapter *adapter, int count, int *done)
{
- struct ifnet *ifp = adapter->ifp;;
+ struct ifnet *ifp = adapter->ifp;
struct mbuf *mp;
u8 status = 0, accept_frame = 0, eop = 0;
u16 len, desc_len, prev_len_adj;
@@ -3413,6 +3440,16 @@ lem_rxeof(struct adapter *adapter, int count, int *done)
bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
BUS_DMASYNC_POSTREAD);
+#ifdef DEV_NETMAP
+ if (ifp->if_capenable & IFCAP_NETMAP) {
+ struct netmap_adapter *na = NA(ifp);
+ na->rx_rings[0].nr_kflags |= NKR_PENDINTR;
+ selwakeuppri(&na->rx_rings[0].si, PI_NET);
+ EM_RX_UNLOCK(adapter);
+ return (0);
+ }
+#endif /* DEV_NETMAP */
+
if (!((current_desc->status) & E1000_RXD_STAT_DD)) {
if (done != NULL)
*done = rx_sent;
@@ -3516,8 +3553,7 @@ lem_rxeof(struct adapter *adapter, int count, int *done)
#endif
if (status & E1000_RXD_STAT_VP) {
adapter->fmp->m_pkthdr.ether_vtag =
- (le16toh(current_desc->special) &
- E1000_RXD_SPC_VLAN_MASK);
+ le16toh(current_desc->special);
adapter->fmp->m_flags |= M_VLANTAG;
}
#ifndef __NO_STRICT_ALIGNMENT
@@ -3528,7 +3564,7 @@ skip:
adapter->lmp = NULL;
}
} else {
- ifp->if_ierrors++;
+ adapter->dropped_pkts++;
discard:
/* Reuse loaded DMA map and just update mbuf chain */
mp = adapter->rx_buffer_area[i].m_head;
@@ -3604,7 +3640,7 @@ lem_fixup_rx(struct adapter *adapter)
bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len);
m->m_data += ETHER_HDR_LEN;
} else {
- MGETHDR(n, M_DONTWAIT, MT_DATA);
+ MGETHDR(n, M_NOWAIT, MT_DATA);
if (n != NULL) {
bcopy(m->m_data, n->m_data, ETHER_HDR_LEN);
m->m_data += ETHER_HDR_LEN;
@@ -3753,10 +3789,6 @@ lem_setup_vlan_hw_support(struct adapter *adapter)
reg &= ~E1000_RCTL_CFIEN;
reg |= E1000_RCTL_VFE;
E1000_WRITE_REG(hw, E1000_RCTL, reg);
-
- /* Update the frame size */
- E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
- adapter->max_frame_size + VLAN_TAG_SIZE);
}
static void
@@ -3765,10 +3797,6 @@ lem_enable_intr(struct adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 ims_mask = IMS_ENABLE_MASK;
- if (adapter->msix) {
- E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK);
- ims_mask |= EM_MSIX_MASK;
- }
E1000_WRITE_REG(hw, E1000_IMS, ims_mask);
}
@@ -3777,9 +3805,7 @@ lem_disable_intr(struct adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
- if (adapter->msix)
- E1000_WRITE_REG(hw, EM_EIAC, 0);
- E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
}
/*
@@ -3946,7 +3972,7 @@ lem_enable_wakeup(device_t dev)
u32 pmc, ctrl, ctrl_ext, rctl;
u16 status;
- if ((pci_find_extcap(dev, PCIY_PMG, &pmc) != 0))
+ if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0))
return;
/* Advertise the wakeup capability */
@@ -4304,11 +4330,11 @@ lem_add_hw_stats(struct adapter *adapter)
"Watchdog timeouts");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "device_control",
- CTLFLAG_RD, adapter, E1000_CTRL,
+ CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_CTRL,
lem_sysctl_reg_handler, "IU",
"Device Control Register");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_control",
- CTLFLAG_RD, adapter, E1000_RCTL,
+ CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RCTL,
lem_sysctl_reg_handler, "IU",
"Receiver Control Register");
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_high_water",
@@ -4317,27 +4343,27 @@ lem_add_hw_stats(struct adapter *adapter)
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "fc_low_water",
CTLFLAG_RD, &adapter->hw.fc.low_water, 0,
"Flow Control Low Watermark");
- SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "fifo_workaround",
+ SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_workaround",
CTLFLAG_RD, &adapter->tx_fifo_wrk_cnt,
"TX FIFO workaround events");
- SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "fifo_reset",
+ SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "fifo_reset",
CTLFLAG_RD, &adapter->tx_fifo_reset_cnt,
"TX FIFO resets");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_head",
- CTLFLAG_RD, adapter, E1000_TDH(0),
+ CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDH(0),
lem_sysctl_reg_handler, "IU",
"Transmit Descriptor Head");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txd_tail",
- CTLFLAG_RD, adapter, E1000_TDT(0),
+ CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_TDT(0),
lem_sysctl_reg_handler, "IU",
"Transmit Descriptor Tail");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_head",
- CTLFLAG_RD, adapter, E1000_RDH(0),
+ CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDH(0),
lem_sysctl_reg_handler, "IU",
"Receive Descriptor Head");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxd_tail",
- CTLFLAG_RD, adapter, E1000_RDT(0),
+ CTLTYPE_UINT | CTLFLAG_RD, adapter, E1000_RDT(0),
lem_sysctl_reg_handler, "IU",
"Receive Descriptor Tail");
@@ -4348,146 +4374,146 @@ lem_add_hw_stats(struct adapter *adapter)
CTLFLAG_RD, NULL, "Statistics");
stat_list = SYSCTL_CHILDREN(stat_node);
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "excess_coll",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "excess_coll",
CTLFLAG_RD, &stats->ecol,
"Excessive collisions");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "single_coll",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "single_coll",
CTLFLAG_RD, &stats->scc,
"Single collisions");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "multiple_coll",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "multiple_coll",
CTLFLAG_RD, &stats->mcc,
"Multiple collisions");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "late_coll",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "late_coll",
CTLFLAG_RD, &stats->latecol,
"Late collisions");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "collision_count",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "collision_count",
CTLFLAG_RD, &stats->colc,
"Collision Count");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "symbol_errors",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "symbol_errors",
CTLFLAG_RD, &adapter->stats.symerrs,
"Symbol Errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "sequence_errors",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "sequence_errors",
CTLFLAG_RD, &adapter->stats.sec,
"Sequence Errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "defer_count",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "defer_count",
CTLFLAG_RD, &adapter->stats.dc,
"Defer Count");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "missed_packets",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "missed_packets",
CTLFLAG_RD, &adapter->stats.mpc,
"Missed Packets");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_no_buff",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_no_buff",
CTLFLAG_RD, &adapter->stats.rnbc,
"Receive No Buffers");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_undersize",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersize",
CTLFLAG_RD, &adapter->stats.ruc,
"Receive Undersize");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
CTLFLAG_RD, &adapter->stats.rfc,
"Fragmented Packets Received ");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_oversize",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversize",
CTLFLAG_RD, &adapter->stats.roc,
"Oversized Packets Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_jabber",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabber",
CTLFLAG_RD, &adapter->stats.rjc,
"Recevied Jabber");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "recv_errs",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_errs",
CTLFLAG_RD, &adapter->stats.rxerrc,
"Receive Errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "crc_errs",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs",
CTLFLAG_RD, &adapter->stats.crcerrs,
"CRC errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "alignment_errs",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "alignment_errs",
CTLFLAG_RD, &adapter->stats.algnerrc,
"Alignment Errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "coll_ext_errs",
CTLFLAG_RD, &adapter->stats.cexterr,
"Collision/Carrier extension errors");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
CTLFLAG_RD, &adapter->stats.xonrxc,
"XON Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xon_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd",
CTLFLAG_RD, &adapter->stats.xontxc,
"XON Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
CTLFLAG_RD, &adapter->stats.xoffrxc,
"XOFF Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
CTLFLAG_RD, &adapter->stats.xofftxc,
"XOFF Transmitted");
/* Packet Reception Stats */
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_recvd",
CTLFLAG_RD, &adapter->stats.tpr,
"Total Packets Received ");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
CTLFLAG_RD, &adapter->stats.gprc,
"Good Packets Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_recvd",
CTLFLAG_RD, &adapter->stats.bprc,
"Broadcast Packets Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_recvd",
CTLFLAG_RD, &adapter->stats.mprc,
"Multicast Packets Received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
CTLFLAG_RD, &adapter->stats.prc64,
"64 byte frames received ");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
CTLFLAG_RD, &adapter->stats.prc127,
"65-127 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
CTLFLAG_RD, &adapter->stats.prc255,
"128-255 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
CTLFLAG_RD, &adapter->stats.prc511,
"256-511 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
CTLFLAG_RD, &adapter->stats.prc1023,
"512-1023 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
CTLFLAG_RD, &adapter->stats.prc1522,
"1023-1522 byte frames received");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_recvd",
CTLFLAG_RD, &adapter->stats.gorc,
"Good Octets Received");
/* Packet Transmission Stats */
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
CTLFLAG_RD, &adapter->stats.gotc,
"Good Octets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
CTLFLAG_RD, &adapter->stats.tpt,
"Total Packets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
CTLFLAG_RD, &adapter->stats.gptc,
"Good Packets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
CTLFLAG_RD, &adapter->stats.bptc,
"Broadcast Packets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
CTLFLAG_RD, &adapter->stats.mptc,
"Multicast Packets Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
CTLFLAG_RD, &adapter->stats.ptc64,
"64 byte frames transmitted ");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
CTLFLAG_RD, &adapter->stats.ptc127,
"65-127 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
CTLFLAG_RD, &adapter->stats.ptc255,
"128-255 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
CTLFLAG_RD, &adapter->stats.ptc511,
"256-511 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
CTLFLAG_RD, &adapter->stats.ptc1023,
"512-1023 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
CTLFLAG_RD, &adapter->stats.ptc1522,
"1024-1522 byte frames transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tso_txd",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_txd",
CTLFLAG_RD, &adapter->stats.tsctc,
"TSO Contexts Transmitted");
- SYSCTL_ADD_QUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail",
+ SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tso_ctx_fail",
CTLFLAG_RD, &adapter->stats.tsctfc,
"TSO Contexts Failed");
}
@@ -4613,7 +4639,6 @@ lem_set_flow_cntrl(struct adapter *adapter, const char *name,
OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
}
-#ifndef EM_LEGACY_IRQ
static void
lem_add_rx_process_limit(struct adapter *adapter, const char *name,
const char *description, int *limit, int value)
@@ -4623,4 +4648,3 @@ lem_add_rx_process_limit(struct adapter *adapter, const char *name,
SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
}
-#endif
diff --git a/freebsd/sys/dev/e1000/if_lem.h b/freebsd/sys/dev/e1000/if_lem.h
index 21287b61..29d26af5 100644
--- a/freebsd/sys/dev/e1000/if_lem.h
+++ b/freebsd/sys/dev/e1000/if_lem.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -217,6 +217,10 @@
#define EM_BAR_MEM_TYPE_64BIT 0x00000004
#define EM_MSIX_BAR 3 /* On 82575 */
+#if __FreeBSD_version < 900000
+#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD
+#endif
+
/* Defines for printing debug information */
#define DEBUG_INIT 0
#define DEBUG_IOCTL 0
diff --git a/freebsd/sys/dev/fxp/if_fxp.c b/freebsd/sys/dev/fxp/if_fxp.c
index 7bc247dc..2b1f51d6 100644
--- a/freebsd/sys/dev/fxp/if_fxp.c
+++ b/freebsd/sys/dev/fxp/if_fxp.c
@@ -89,7 +89,7 @@ MODULE_DEPEND(fxp, miibus, 1, 1, 1);
#include <rtems/bsd/local/miibus_if.h>
/*
- * NOTE! On the Alpha, we have an alignment constraint. The
+ * NOTE! On !x86 we typically have an alignment constraint. The
* card DMAs the packet immediately following the RFA. However,
* the first thing in the packet is a 14-byte Ethernet header.
* This means that the packet is misaligned. To compensate,
@@ -113,7 +113,7 @@ static int tx_threshold = 64;
*
* See struct fxp_cb_config for the bit definitions.
*/
-static const u_char const fxp_cb_config_template[] = {
+static const u_char fxp_cb_config_template[] = {
0x0, 0x0, /* cb_status */
0x0, 0x0, /* cb_command */
0x0, 0x0, 0x0, 0x0, /* link_addr */
@@ -157,7 +157,7 @@ static const u_char const fxp_cb_config_template[] = {
* particular variants, but we don't currently differentiate between
* them.
*/
-static const struct fxp_ident const fxp_ident_table[] = {
+static const struct fxp_ident fxp_ident_table[] = {
{ 0x1029, -1, 0, "Intel 82559 PCI/CardBus Pro/100" },
{ 0x1030, -1, 0, "Intel 82559 Pro/100 Ethernet" },
{ 0x1031, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
@@ -196,7 +196,7 @@ static const struct fxp_ident const fxp_ident_table[] = {
{ 0x1229, 0x08, 0, "Intel 82559 Pro/100 Ethernet" },
{ 0x1229, 0x09, 0, "Intel 82559ER Pro/100 Ethernet" },
{ 0x1229, 0x0c, 0, "Intel 82550 Pro/100 Ethernet" },
- { 0x1229, 0x0d, 0, "Intel 82550 Pro/100 Ethernet" },
+ { 0x1229, 0x0d, 0, "Intel 82550C Pro/100 Ethernet" },
{ 0x1229, 0x0e, 0, "Intel 82550 Pro/100 Ethernet" },
{ 0x1229, 0x0f, 0, "Intel 82551 Pro/100 Ethernet" },
{ 0x1229, 0x10, 0, "Intel 82551 Pro/100 Ethernet" },
@@ -238,11 +238,11 @@ static int fxp_ioctl(struct ifnet *ifp, u_long command,
caddr_t data);
static void fxp_watchdog(struct fxp_softc *sc);
static void fxp_add_rfabuf(struct fxp_softc *sc,
- struct fxp_rx *rxp);
+ struct fxp_rx *rxp);
static void fxp_discard_rfabuf(struct fxp_softc *sc,
- struct fxp_rx *rxp);
+ struct fxp_rx *rxp);
static int fxp_new_rfabuf(struct fxp_softc *sc,
- struct fxp_rx *rxp);
+ struct fxp_rx *rxp);
static int fxp_mc_addrs(struct fxp_softc *sc);
static void fxp_mc_setup(struct fxp_softc *sc);
static uint16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset,
@@ -250,6 +250,7 @@ static uint16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset,
static void fxp_eeprom_putword(struct fxp_softc *sc, int offset,
uint16_t data);
static void fxp_autosize_eeprom(struct fxp_softc *sc);
+static void fxp_load_eeprom(struct fxp_softc *sc);
static void fxp_read_eeprom(struct fxp_softc *sc, u_short *data,
int offset, int words);
static void fxp_write_eeprom(struct fxp_softc *sc, u_short *data,
@@ -274,7 +275,7 @@ static int sysctl_hw_fxp_int_delay(SYSCTL_HANDLER_ARGS);
static void fxp_scb_wait(struct fxp_softc *sc);
static void fxp_scb_cmd(struct fxp_softc *sc, int cmd);
static void fxp_dma_wait(struct fxp_softc *sc,
- volatile uint16_t *status, bus_dma_tag_t dmat,
+ volatile uint16_t *status, bus_dma_tag_t dmat,
bus_dmamap_t map);
static device_method_t fxp_methods[] = {
@@ -428,7 +429,7 @@ fxp_attach(device_t dev)
struct fxp_rx *rxp;
struct ifnet *ifp;
uint32_t val;
- uint16_t data, myea[ETHER_ADDR_LEN / 2];
+ uint16_t data;
u_char eaddr[ETHER_ADDR_LEN];
int error, flags, i, pmc, prefer_iomap;
@@ -500,6 +501,7 @@ fxp_attach(device_t dev)
* Find out how large of an SEEPROM we have.
*/
fxp_autosize_eeprom(sc);
+ fxp_load_eeprom(sc);
/*
* Find out the chip revision; lump all 82557 revs together.
@@ -509,7 +511,7 @@ fxp_attach(device_t dev)
/* Assume ICH controllers are 82559. */
sc->revision = FXP_REV_82559_A0;
} else {
- fxp_read_eeprom(sc, &data, 5, 1);
+ data = sc->eeprom[FXP_EEPROM_MAP_CNTR];
if ((data >> 8) == 1)
sc->revision = FXP_REV_82557;
else
@@ -521,15 +523,27 @@ fxp_attach(device_t dev)
*/
if (sc->revision >= FXP_REV_82558_A4 &&
sc->revision != FXP_REV_82559S_A) {
- fxp_read_eeprom(sc, &data, 10, 1);
+ data = sc->eeprom[FXP_EEPROM_MAP_ID];
if ((data & 0x20) != 0 &&
pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0)
sc->flags |= FXP_FLAG_WOLCAP;
}
+ if (sc->revision == FXP_REV_82550_C) {
+ /*
+ * 82550C with server extension requires microcode to
+ * receive fragmented UDP datagrams. However if the
+ * microcode is used for client-only featured 82550C
+ * it locks up controller.
+ */
+ data = sc->eeprom[FXP_EEPROM_MAP_COMPAT];
+ if ((data & 0x0400) == 0)
+ sc->flags |= FXP_FLAG_NO_UCODE;
+ }
+
/* Receiver lock-up workaround detection. */
if (sc->revision < FXP_REV_82558_A4) {
- fxp_read_eeprom(sc, &data, 3, 1);
+ data = sc->eeprom[FXP_EEPROM_MAP_COMPAT];
if ((data & 0x03) != 0x03) {
sc->flags |= FXP_FLAG_RXBUG;
device_printf(dev, "Enabling Rx lock-up workaround\n");
@@ -539,7 +553,7 @@ fxp_attach(device_t dev)
/*
* Determine whether we must use the 503 serial interface.
*/
- fxp_read_eeprom(sc, &data, 6, 1);
+ data = sc->eeprom[FXP_EEPROM_MAP_PRI_PHY];
if (sc->revision == FXP_REV_82557 && (data & FXP_PHY_DEVICE_MASK) != 0
&& (data & FXP_PHY_SERIAL_ONLY))
sc->flags |= FXP_FLAG_SERIAL_MEDIA;
@@ -559,7 +573,7 @@ fxp_attach(device_t dev)
*/
if ((sc->ident->ich >= 2 && sc->ident->ich <= 3) ||
(sc->ident->ich == 0 && sc->revision >= FXP_REV_82559_A0)) {
- fxp_read_eeprom(sc, &data, 10, 1);
+ data = sc->eeprom[FXP_EEPROM_MAP_ID];
if (data & 0x02) { /* STB enable */
uint16_t cksum;
int i;
@@ -567,27 +581,24 @@ fxp_attach(device_t dev)
device_printf(dev,
"Disabling dynamic standby mode in EEPROM\n");
data &= ~0x02;
- fxp_write_eeprom(sc, &data, 10, 1);
+ sc->eeprom[FXP_EEPROM_MAP_ID] = data;
+ fxp_write_eeprom(sc, &data, FXP_EEPROM_MAP_ID, 1);
device_printf(dev, "New EEPROM ID: 0x%x\n", data);
cksum = 0;
- for (i = 0; i < (1 << sc->eeprom_size) - 1; i++) {
- fxp_read_eeprom(sc, &data, i, 1);
- cksum += data;
- }
+ for (i = 0; i < (1 << sc->eeprom_size) - 1; i++)
+ cksum += sc->eeprom[i];
i = (1 << sc->eeprom_size) - 1;
cksum = 0xBABA - cksum;
- fxp_read_eeprom(sc, &data, i, 1);
fxp_write_eeprom(sc, &cksum, i, 1);
device_printf(dev,
"EEPROM checksum @ 0x%x: 0x%x -> 0x%x\n",
- i, data, cksum);
-#if 1
+ i, sc->eeprom[i], cksum);
+ sc->eeprom[i] = cksum;
/*
* If the user elects to continue, try the software
* workaround, as it is better than nothing.
*/
sc->flags |= FXP_FLAG_CU_RESUME_BUG;
-#endif
}
}
@@ -677,13 +688,14 @@ fxp_attach(device_t dev)
}
error = bus_dmamem_alloc(sc->fxp_stag, (void **)&sc->fxp_stats,
- BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->fxp_smap);
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->fxp_smap);
if (error) {
device_printf(dev, "could not allocate stats DMA memory\n");
goto fail;
}
error = bus_dmamap_load(sc->fxp_stag, sc->fxp_smap, sc->fxp_stats,
- sizeof(struct fxp_stats), fxp_dma_map_addr, &sc->stats_addr, 0);
+ sizeof(struct fxp_stats), fxp_dma_map_addr, &sc->stats_addr,
+ BUS_DMA_NOWAIT);
if (error) {
device_printf(dev, "could not load the stats DMA buffer\n");
goto fail;
@@ -699,7 +711,7 @@ fxp_attach(device_t dev)
}
error = bus_dmamem_alloc(sc->cbl_tag, (void **)&sc->fxp_desc.cbl_list,
- BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->cbl_map);
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->cbl_map);
if (error) {
device_printf(dev, "could not allocate TxCB DMA memory\n");
goto fail;
@@ -707,7 +719,7 @@ fxp_attach(device_t dev)
error = bus_dmamap_load(sc->cbl_tag, sc->cbl_map,
sc->fxp_desc.cbl_list, FXP_TXCB_SZ, fxp_dma_map_addr,
- &sc->fxp_desc.cbl_addr, 0);
+ &sc->fxp_desc.cbl_addr, BUS_DMA_NOWAIT);
if (error) {
device_printf(dev, "could not load TxCB DMA buffer\n");
goto fail;
@@ -724,14 +736,15 @@ fxp_attach(device_t dev)
}
error = bus_dmamem_alloc(sc->mcs_tag, (void **)&sc->mcsp,
- BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->mcs_map);
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->mcs_map);
if (error) {
device_printf(dev,
"could not allocate multicast setup DMA memory\n");
goto fail;
}
error = bus_dmamap_load(sc->mcs_tag, sc->mcs_map, sc->mcsp,
- sizeof(struct fxp_cb_mcs), fxp_dma_map_addr, &sc->mcs_addr, 0);
+ sizeof(struct fxp_cb_mcs), fxp_dma_map_addr, &sc->mcs_addr,
+ BUS_DMA_NOWAIT);
if (error) {
device_printf(dev,
"can't load the multicast setup DMA buffer\n");
@@ -779,21 +792,20 @@ fxp_attach(device_t dev)
/*
* Read MAC address.
*/
- fxp_read_eeprom(sc, myea, 0, 3);
- eaddr[0] = myea[0] & 0xff;
- eaddr[1] = myea[0] >> 8;
- eaddr[2] = myea[1] & 0xff;
- eaddr[3] = myea[1] >> 8;
- eaddr[4] = myea[2] & 0xff;
- eaddr[5] = myea[2] >> 8;
+ eaddr[0] = sc->eeprom[FXP_EEPROM_MAP_IA0] & 0xff;
+ eaddr[1] = sc->eeprom[FXP_EEPROM_MAP_IA0] >> 8;
+ eaddr[2] = sc->eeprom[FXP_EEPROM_MAP_IA1] & 0xff;
+ eaddr[3] = sc->eeprom[FXP_EEPROM_MAP_IA1] >> 8;
+ eaddr[4] = sc->eeprom[FXP_EEPROM_MAP_IA2] & 0xff;
+ eaddr[5] = sc->eeprom[FXP_EEPROM_MAP_IA2] >> 8;
if (bootverbose) {
device_printf(dev, "PCI IDs: %04x %04x %04x %04x %04x\n",
pci_get_vendor(dev), pci_get_device(dev),
pci_get_subvendor(dev), pci_get_subdevice(dev),
pci_get_revid(dev));
- fxp_read_eeprom(sc, &data, 10, 1);
device_printf(dev, "Dynamic Standby mode is %s\n",
- data & 0x02 ? "enabled" : "disabled");
+ sc->eeprom[FXP_EEPROM_MAP_ID] & 0x02 ? "enabled" :
+ "disabled");
}
/*
@@ -902,7 +914,7 @@ fxp_attach(device_t dev)
FXP_LOCK(sc);
/* Clear wakeup events. */
CSR_WRITE_1(sc, FXP_CSR_PMDR, CSR_READ_1(sc, FXP_CSR_PMDR));
- fxp_init_body(sc, 1);
+ fxp_init_body(sc, 0);
fxp_stop(sc);
FXP_UNLOCK(sc);
}
@@ -1064,7 +1076,8 @@ fxp_suspend(device_t dev)
pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
sc->flags |= FXP_FLAG_WOL;
/* Reconfigure hardware to accept magic frames. */
- fxp_init_body(sc, 1);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ fxp_init_body(sc, 0);
}
pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2);
}
@@ -1289,6 +1302,23 @@ fxp_write_eeprom(struct fxp_softc *sc, u_short *data, int offset, int words)
fxp_eeprom_putword(sc, offset + i, data[i]);
}
+static void
+fxp_load_eeprom(struct fxp_softc *sc)
+{
+ int i;
+ uint16_t cksum;
+
+ fxp_read_eeprom(sc, sc->eeprom, 0, 1 << sc->eeprom_size);
+ cksum = 0;
+ for (i = 0; i < (1 << sc->eeprom_size) - 1; i++)
+ cksum += sc->eeprom[i];
+ cksum = 0xBABA - cksum;
+ if (cksum != sc->eeprom[(1 << sc->eeprom_size) - 1])
+ device_printf(sc->dev,
+ "EEPROM checksum mismatch! (0x%04x -> 0x%04x)\n",
+ cksum, sc->eeprom[(1 << sc->eeprom_size) - 1]);
+}
+
/*
* Grab the softc lock and call the real fxp_start_body() routine
*/
@@ -1456,7 +1486,7 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
return (ENOBUFS);
}
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
- m = m_pullup(m, poff + sizeof(struct tcphdr) + tcp->th_off);
+ m = m_pullup(m, poff + (tcp->th_off << 2));
if (m == NULL) {
*m_head = NULL;
return (ENOBUFS);
@@ -1543,7 +1573,7 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
}
*m_head = m;
error = bus_dmamap_load_mbuf_sg(sc->fxp_txmtag, txp->tx_map,
- *m_head, segs, &nseg, 0);
+ *m_head, segs, &nseg, 0);
if (error != 0) {
m_freem(*m_head);
*m_head = NULL;
@@ -1943,11 +1973,11 @@ fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp, uint8_t statack,
/* Adjust for appended checksum bytes. */
total_len -= 2;
}
- if (total_len < sizeof(struct ether_header) ||
+ if (total_len < (int)sizeof(struct ether_header) ||
total_len > (MCLBYTES - RFA_ALIGNMENT_FUDGE -
sc->rfa_size) ||
status & (FXP_RFA_STATUS_CRC |
- FXP_RFA_STATUS_ALIGN)) {
+ FXP_RFA_STATUS_ALIGN | FXP_RFA_STATUS_OVERRUN)) {
m_freem(m);
fxp_add_rfabuf(sc, rxp);
continue;
@@ -2050,7 +2080,7 @@ fxp_update_stats(struct fxp_softc *sc)
*/
sc->rx_idle_secs++;
}
- ifp->if_ierrors +=
+ ifp->if_ierrors +=
le32toh(sp->rx_crc_errors) +
le32toh(sp->rx_alignment_errors) +
le32toh(sp->rx_rnr_errors) +
@@ -2113,8 +2143,10 @@ fxp_tick(void *xsc)
*/
if (sc->rx_idle_secs > FXP_MAX_RX_IDLE) {
sc->rx_idle_secs = 0;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
fxp_init_body(sc, 1);
+ }
return;
}
/*
@@ -2177,7 +2209,7 @@ fxp_stop(struct fxp_softc *sc)
txp = sc->fxp_desc.tx_list;
if (txp != NULL) {
for (i = 0; i < FXP_NTXCB; i++) {
- if (txp[i].tx_mbuf != NULL) {
+ if (txp[i].tx_mbuf != NULL) {
bus_dmamap_sync(sc->fxp_txmtag, txp[i].tx_map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->fxp_txmtag,
@@ -2212,6 +2244,7 @@ fxp_watchdog(struct fxp_softc *sc)
device_printf(sc->dev, "device timeout\n");
sc->ifp->if_oerrors++;
+ sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
fxp_init_body(sc, 1);
}
@@ -2246,6 +2279,10 @@ fxp_init_body(struct fxp_softc *sc, int setmedia)
int i, prm;
FXP_LOCK_ASSERT(sc, MA_OWNED);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
/*
* Cancel any pending I/O
*/
@@ -2557,14 +2594,12 @@ fxp_ifmedia_upd(struct ifnet *ifp)
{
struct fxp_softc *sc = ifp->if_softc;
struct mii_data *mii;
+ struct mii_softc *miisc;
mii = device_get_softc(sc->miibus);
FXP_LOCK(sc);
- if (mii->mii_instance) {
- struct mii_softc *miisc;
- LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
- mii_phy_reset(miisc);
- }
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ mii_phy_reset(miisc);
mii_mediachg(mii);
FXP_UNLOCK(sc);
return (0);
@@ -2584,12 +2619,6 @@ fxp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
-
- if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_10_T &&
- sc->flags & FXP_FLAG_CU_RESUME_BUG)
- sc->cu_resume_bug = 1;
- else
- sc->cu_resume_bug = 0;
FXP_UNLOCK(sc);
}
@@ -2782,12 +2811,18 @@ fxp_miibus_statchg(device_t dev)
(IFM_AVALID | IFM_ACTIVE))
return;
+ if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T &&
+ sc->flags & FXP_FLAG_CU_RESUME_BUG)
+ sc->cu_resume_bug = 1;
+ else
+ sc->cu_resume_bug = 0;
/*
* Call fxp_init_body in order to adjust the flow control settings.
* Note that the 82557 doesn't support hardware flow control.
*/
if (sc->revision == FXP_REV_82557)
return;
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
fxp_init_body(sc, 0);
}
@@ -2811,9 +2846,10 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_flags & IFF_UP) {
if (((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) &&
((ifp->if_flags ^ sc->if_flags) &
- (IFF_PROMISC | IFF_ALLMULTI | IFF_LINK0)) != 0)
- fxp_init_body(sc, 1);
- else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ (IFF_PROMISC | IFF_ALLMULTI | IFF_LINK0)) != 0) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ fxp_init_body(sc, 0);
+ } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
fxp_init_body(sc, 1);
} else {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
@@ -2825,8 +2861,12 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
case SIOCADDMULTI:
case SIOCDELMULTI:
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
- fxp_init(sc);
+ FXP_LOCK(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ fxp_init_body(sc, 0);
+ }
+ FXP_UNLOCK(sc);
break;
case SIOCSIFMEDIA:
@@ -2915,8 +2955,10 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM);
reinit++;
}
- if (reinit > 0 && ifp->if_flags & IFF_UP)
- fxp_init_body(sc, 1);
+ if (reinit > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ fxp_init_body(sc, 0);
+ }
FXP_UNLOCK(sc);
VLAN_CAPABILITIES(ifp);
break;
@@ -3026,7 +3068,7 @@ static const struct ucode {
int length;
u_short int_delay_offset;
u_short bundle_max_offset;
-} const ucode_table[] = {
+} ucode_table[] = {
{ FXP_REV_82558_A4, UCODE(fxp_ucode_d101a), D101_CPUSAVER_DWORD, 0 },
{ FXP_REV_82558_B0, UCODE(fxp_ucode_d101b0), D101_CPUSAVER_DWORD, 0 },
{ FXP_REV_82559_A0, UCODE(fxp_ucode_d101ma),
@@ -3039,6 +3081,8 @@ static const struct ucode {
D102_C_CPUSAVER_DWORD, D102_C_CPUSAVER_BUNDLE_MAX_DWORD },
{ FXP_REV_82551_F, UCODE(fxp_ucode_d102e),
D102_E_CPUSAVER_DWORD, D102_E_CPUSAVER_BUNDLE_MAX_DWORD },
+ { FXP_REV_82551_10, UCODE(fxp_ucode_d102e),
+ D102_E_CPUSAVER_DWORD, D102_E_CPUSAVER_BUNDLE_MAX_DWORD },
{ 0, NULL, 0, 0, 0 }
};
@@ -3049,6 +3093,9 @@ fxp_load_ucode(struct fxp_softc *sc)
struct fxp_cb_ucode *cbp;
int i;
+ if (sc->flags & FXP_FLAG_NO_UCODE)
+ return;
+
for (uc = ucode_table; uc->ucode != NULL; uc++)
if (sc->revision == uc->revision)
break;
@@ -3081,6 +3128,7 @@ fxp_load_ucode(struct fxp_softc *sc)
sc->tunable_int_delay,
uc->bundle_max_offset == 0 ? 0 : sc->tunable_bundle_max);
sc->flags |= FXP_FLAG_UCODE;
+ bzero(cbp, FXP_TXCB_SZ);
}
#define FXP_SYSCTL_STAT_ADD(c, h, n, p, d) \
diff --git a/freebsd/sys/dev/fxp/if_fxpreg.h b/freebsd/sys/dev/fxp/if_fxpreg.h
index bb6a88b2..cc764b54 100644
--- a/freebsd/sys/dev/fxp/if_fxpreg.h
+++ b/freebsd/sys/dev/fxp/if_fxpreg.h
@@ -448,6 +448,24 @@ struct fxp_stats {
#define FXP_EEPROM_OPC_READ 0x6
/*
+ * EEPROM map
+ */
+#define FXP_EEPROM_MAP_IA0 0x00 /* Station address */
+#define FXP_EEPROM_MAP_IA1 0x01
+#define FXP_EEPROM_MAP_IA2 0x02
+#define FXP_EEPROM_MAP_COMPAT 0x03 /* Compatibility */
+#define FXP_EEPROM_MAP_CNTR 0x05 /* Controller/connector type */
+#define FXP_EEPROM_MAP_PRI_PHY 0x06 /* Primary PHY record */
+#define FXP_EEPROM_MAP_SEC_PHY 0x07 /* Secondary PHY record */
+#define FXP_EEPROM_MAP_PWA0 0x08 /* Printed wire assembly num. */
+#define FXP_EEPROM_MAP_PWA1 0x09 /* Printed wire assembly num. */
+#define FXP_EEPROM_MAP_ID 0x0A /* EEPROM ID */
+#define FXP_EEPROM_MAP_SUBSYS 0x0B /* Subsystem ID */
+#define FXP_EEPROM_MAP_SUBVEN 0x0C /* Subsystem vendor ID */
+#define FXP_EEPROM_MAP_CKSUM64 0x3F /* 64-word EEPROM checksum */
+#define FXP_EEPROM_MAP_CKSUM256 0xFF /* 256-word EEPROM checksum */
+
+/*
* Management Data Interface opcodes
*/
#define FXP_MDI_WRITE 0x1
diff --git a/freebsd/sys/dev/fxp/if_fxpvar.h b/freebsd/sys/dev/fxp/if_fxpvar.h
index 5c2cf80b..253c4ff1 100644
--- a/freebsd/sys/dev/fxp/if_fxpvar.h
+++ b/freebsd/sys/dev/fxp/if_fxpvar.h
@@ -219,6 +219,7 @@ struct fxp_softc {
int if_flags;
uint8_t rfa_size;
uint32_t tx_cmd;
+ uint16_t eeprom[256];
};
#define FXP_FLAG_MWI_ENABLE 0x0001 /* MWI enable */
@@ -236,6 +237,7 @@ struct fxp_softc {
#define FXP_FLAG_WOLCAP 0x2000 /* WOL capability */
#define FXP_FLAG_WOL 0x4000 /* WOL active */
#define FXP_FLAG_RXBUG 0x8000 /* Rx lock-up bug */
+#define FXP_FLAG_NO_UCODE 0x10000 /* ucode is not applicable */
/* Macros to ease CSR access. */
#define CSR_READ_1(sc, reg) bus_read_1(sc->fxp_res[0], reg)
diff --git a/freebsd/sys/dev/led/led.c b/freebsd/sys/dev/led/led.c
index db609a45..c87f7f9d 100644
--- a/freebsd/sys/dev/led/led.c
+++ b/freebsd/sys/dev/led/led.c
@@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$");
struct ledsc {
LIST_ENTRY(ledsc) list;
+ char *name;
void *private;
int unit;
led_t *func;
@@ -85,71 +86,43 @@ led_timeout(void *p)
}
static int
-led_state(struct cdev *dev, struct sbuf *sb, int state)
+led_state(struct ledsc *sc, struct sbuf **sb, int state)
{
struct sbuf *sb2 = NULL;
- struct ledsc *sc;
- mtx_lock(&led_mtx);
- sc = dev->si_drv1;
- if (sc != NULL) {
- sb2 = sc->spec;
- sc->spec = sb;
- if (sb != NULL) {
- sc->str = sbuf_data(sb);
- sc->ptr = sc->str;
- } else {
- sc->str = NULL;
- sc->ptr = NULL;
- sc->func(sc->private, state);
- }
- sc->count = 0;
+ sb2 = sc->spec;
+ sc->spec = *sb;
+ if (*sb != NULL) {
+ sc->str = sbuf_data(*sb);
+ sc->ptr = sc->str;
+ } else {
+ sc->str = NULL;
+ sc->ptr = NULL;
+ sc->func(sc->private, state);
}
- mtx_unlock(&led_mtx);
- if (sb2 != NULL)
- sbuf_delete(sb2);
- if (sc == NULL)
- return (ENXIO);
+ sc->count = 0;
+ *sb = sb2;
return(0);
}
static int
-led_write(struct cdev *dev, struct uio *uio, int ioflag)
+led_parse(const char *s, struct sbuf **sb, int *state)
{
- int error;
- char *s, *s2;
- struct sbuf *sb = NULL;
- int i;
-
- if (dev->si_drv1 == NULL)
- return (ENXIO);
-
- if (uio->uio_resid > 512)
- return (EINVAL);
- s2 = s = malloc(uio->uio_resid + 1, M_DEVBUF, M_WAITOK);
- s[uio->uio_resid] = '\0';
- error = uiomove(s, uio->uio_resid, uio);
- if (error) {
- free(s2, M_DEVBUF);
- return (error);
- }
+ int i, error;
/*
* Handle "on" and "off" immediately so people can flash really
* fast from userland if they want to
*/
if (*s == '0' || *s == '1') {
- error = led_state(dev, NULL, *s & 1);
- free(s2, M_DEVBUF);
- return(error);
+ *state = *s & 1;
+ return (0);
}
- sb = sbuf_new_auto();
- if (sb == NULL) {
- free(s2, M_DEVBUF);
+ *state = 0;
+ *sb = sbuf_new_auto();
+ if (*sb == NULL)
return (ENOMEM);
- }
-
switch(s[0]) {
/*
* Flash, default is 100msec/100msec.
@@ -160,7 +133,7 @@ led_write(struct cdev *dev, struct uio *uio, int ioflag)
i = s[1] - '1';
else
i = 0;
- sbuf_printf(sb, "%c%c", 'A' + i, 'a' + i);
+ sbuf_printf(*sb, "%c%c", 'A' + i, 'a' + i);
break;
/*
* Digits, flashes out numbers.
@@ -174,10 +147,10 @@ led_write(struct cdev *dev, struct uio *uio, int ioflag)
if (i == 0)
i = 10;
for (; i > 1; i--)
- sbuf_cat(sb, "Aa");
- sbuf_cat(sb, "Aj");
+ sbuf_cat(*sb, "Aa");
+ sbuf_cat(*sb, "Aj");
}
- sbuf_cat(sb, "jj");
+ sbuf_cat(*sb, "jj");
break;
/*
* String, roll your own.
@@ -192,7 +165,7 @@ led_write(struct cdev *dev, struct uio *uio, int ioflag)
(*s >= 'A' && *s <= 'J') ||
*s == 'U' || *s <= 'u' ||
*s == '.')
- sbuf_bcat(sb, s, 1);
+ sbuf_bcat(*sb, s, 1);
}
break;
/*
@@ -207,33 +180,82 @@ led_write(struct cdev *dev, struct uio *uio, int ioflag)
case 'm':
for(s++; *s; s++) {
if (*s == '.')
- sbuf_cat(sb, "aA");
+ sbuf_cat(*sb, "aA");
else if (*s == '-')
- sbuf_cat(sb, "aC");
+ sbuf_cat(*sb, "aC");
else if (*s == ' ')
- sbuf_cat(sb, "b");
+ sbuf_cat(*sb, "b");
else if (*s == '\n')
- sbuf_cat(sb, "d");
+ sbuf_cat(*sb, "d");
}
- sbuf_cat(sb, "j");
+ sbuf_cat(*sb, "j");
break;
default:
- sbuf_delete(sb);
- free(s2, M_DEVBUF);
+ sbuf_delete(*sb);
return (EINVAL);
}
- sbuf_finish(sb);
- free(s2, M_DEVBUF);
- if (sbuf_overflowed(sb)) {
- sbuf_delete(sb);
- return (ENOMEM);
+ error = sbuf_finish(*sb);
+ if (error != 0 || sbuf_len(*sb) == 0) {
+ *sb = NULL;
+ return (error);
}
- if (sbuf_len(sb) == 0) {
- sbuf_delete(sb);
- return (0);
+ return (0);
+}
+
+static int
+led_write(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct ledsc *sc;
+ char *s;
+ struct sbuf *sb = NULL;
+ int error, state = 0;
+
+ if (uio->uio_resid > 512)
+ return (EINVAL);
+ s = malloc(uio->uio_resid + 1, M_DEVBUF, M_WAITOK);
+ s[uio->uio_resid] = '\0';
+ error = uiomove(s, uio->uio_resid, uio);
+ if (error) {
+ free(s, M_DEVBUF);
+ return (error);
}
+ error = led_parse(s, &sb, &state);
+ free(s, M_DEVBUF);
+ if (error)
+ return (error);
+ mtx_lock(&led_mtx);
+ sc = dev->si_drv1;
+ if (sc != NULL)
+ error = led_state(sc, &sb, state);
+ mtx_unlock(&led_mtx);
+ if (sb != NULL)
+ sbuf_delete(sb);
+ return (error);
+}
+
+int
+led_set(char const *name, char const *cmd)
+{
+ struct ledsc *sc;
+ struct sbuf *sb = NULL;
+ int error, state = 0;
- return (led_state(dev, sb, 0));
+ error = led_parse(cmd, &sb, &state);
+ if (error)
+ return (error);
+ mtx_lock(&led_mtx);
+ LIST_FOREACH(sc, &led_list, list) {
+ if (strcmp(sc->name, name) == 0)
+ break;
+ }
+ if (sc != NULL)
+ error = led_state(sc, &sb, state);
+ else
+ error = ENOENT;
+ mtx_unlock(&led_mtx);
+ if (sb != NULL)
+ sbuf_delete(sb);
+ return (0);
}
static struct cdevsw led_cdevsw = {
@@ -256,6 +278,7 @@ led_create_state(led_t *func, void *priv, char const *name, int state)
sc = malloc(sizeof *sc, M_LED, M_WAITOK | M_ZERO);
sx_xlock(&led_sx);
+ sc->name = strdup(name, M_LED);
sc->unit = alloc_unr(led_unit);
sc->private = priv;
sc->func = func;
@@ -293,6 +316,7 @@ led_destroy(struct cdev *dev)
destroy_dev(dev);
if (sc->spec != NULL)
sbuf_delete(sc->spec);
+ free(sc->name, M_LED);
free(sc, M_LED);
sx_xunlock(&led_sx);
}
diff --git a/freebsd/sys/dev/led/led.h b/freebsd/sys/dev/led/led.h
index bbf301e5..84992c20 100644
--- a/freebsd/sys/dev/led/led.h
+++ b/freebsd/sys/dev/led/led.h
@@ -18,4 +18,6 @@ struct cdev *led_create_state(led_t *, void *, char const *, int);
struct cdev *led_create(led_t *, void *, char const *);
void led_destroy(struct cdev *);
+int led_set(char const *, char const *);
+
#endif
diff --git a/freebsd/sys/dev/mii/brgphy.c b/freebsd/sys/dev/mii/brgphy.c
index 5633413c..bd80e61e 100644
--- a/freebsd/sys/dev/mii/brgphy.c
+++ b/freebsd/sys/dev/mii/brgphy.c
@@ -87,7 +87,7 @@ static device_method_t brgphy_methods[] = {
DEVMETHOD(device_attach, brgphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t brgphy_devclass;
@@ -144,6 +144,10 @@ static const struct mii_phydesc brgphys[] = {
MII_PHY_DESC(xxBROADCOM_ALT1, BCM5761),
MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709S),
MII_PHY_DESC(xxBROADCOM_ALT2, BCM5717C),
+ MII_PHY_DESC(xxBROADCOM_ALT2, BCM5719C),
+ MII_PHY_DESC(xxBROADCOM_ALT2, BCM5720C),
+ MII_PHY_DESC(xxBROADCOM_ALT2, BCM57765),
+ MII_PHY_DESC(xxBROADCOM_ALT2, BCM57780),
MII_PHY_DESC(BROADCOM2, BCM5906),
MII_PHY_END
};
@@ -215,16 +219,20 @@ brgphy_attach(device_t dev)
bsc->mii_model = MII_MODEL(ma->mii_id2);
bsc->mii_rev = MII_REV(ma->mii_id2);
bsc->serdes_flags = 0;
+ ifp = sc->mii_pdata->mii_ifp;
if (bootverbose)
device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n",
bsc->mii_oui, bsc->mii_model, bsc->mii_rev);
+ /* Find the MAC driver associated with this PHY. */
+ if (strcmp(ifp->if_dname, "bge") == 0)
+ bge_sc = ifp->if_softc;
+ else if (strcmp(ifp->if_dname, "bce") == 0)
+ bce_sc = ifp->if_softc;
+
/* Handle any special cases based on the PHY ID */
switch (bsc->mii_oui) {
- case MII_OUI_BROADCOM:
- case MII_OUI_BROADCOM2:
- break;
case MII_OUI_xxBROADCOM:
switch (bsc->mii_model) {
case MII_MODEL_xxBROADCOM_BCM5706:
@@ -244,7 +252,8 @@ brgphy_attach(device_t dev)
sc->mii_flags |= MIIF_HAVEFIBER;
}
break;
- } break;
+ }
+ break;
case MII_OUI_xxBROADCOM_ALT1:
switch (bsc->mii_model) {
case MII_MODEL_xxBROADCOM_ALT1_BCM5708S:
@@ -252,25 +261,19 @@ brgphy_attach(device_t dev)
sc->mii_flags |= MIIF_HAVEFIBER;
break;
case MII_MODEL_xxBROADCOM_ALT1_BCM5709S:
- bsc->serdes_flags |= BRGPHY_5709S;
+ /*
+ * XXX
+ * 5720S and 5709S shares the same PHY id.
+ * Assume 5720S PHY if parent device is bge(4).
+ */
+ if (bge_sc != NULL)
+ bsc->serdes_flags |= BRGPHY_5708S;
+ else
+ bsc->serdes_flags |= BRGPHY_5709S;
sc->mii_flags |= MIIF_HAVEFIBER;
break;
}
break;
- case MII_OUI_xxBROADCOM_ALT2:
- /* No special handling yet. */
- break;
- default:
- device_printf(dev, "Unrecognized OUI for PHY!\n");
- }
-
- ifp = sc->mii_pdata->mii_ifp;
-
- /* Find the MAC driver associated with this PHY. */
- if (strcmp(ifp->if_dname, "bge") == 0) {
- bge_sc = ifp->if_softc;
- } else if (strcmp(ifp->if_dname, "bce") == 0) {
- bce_sc = ifp->if_softc;
}
brgphy_reset(sc);
@@ -400,8 +403,6 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
sc->mii_media_status != mii->mii_media_status ||
cmd == MII_MEDIACHG) {
switch (bsc->mii_oui) {
- case MII_OUI_BROADCOM:
- break;
case MII_OUI_xxBROADCOM:
switch (bsc->mii_model) {
case MII_MODEL_xxBROADCOM_BCM5400:
@@ -419,8 +420,6 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
}
break;
- case MII_OUI_xxBROADCOM_ALT1:
- break;
}
}
mii_phy_update(sc, cmd);
@@ -454,7 +453,7 @@ brgphy_setmedia(struct mii_softc *sc, int media)
break;
}
- if ((media & IFM_GMASK) == IFM_FDX) {
+ if ((media & IFM_FDX) != 0) {
bmcr |= BRGPHY_BMCR_FDX;
gig = BRGPHY_1000CTL_AFD;
} else {
@@ -637,6 +636,11 @@ brgphy_mii_phy_auto(struct mii_softc *sc, int media)
(sc->mii_flags & MIIF_FORCEPAUSE) != 0)
anar |= BRGPHY_ANAR_PC | BRGPHY_ANAR_ASP;
PHY_WRITE(sc, BRGPHY_MII_ANAR, anar);
+ ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD;
+ if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
+ ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC;
+ PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
+ PHY_READ(sc, BRGPHY_MII_1000CTL);
} else {
anar = BRGPHY_SERDES_ANAR_FDX | BRGPHY_SERDES_ANAR_HDX;
if ((media & IFM_FLOW) != 0 ||
@@ -645,12 +649,6 @@ brgphy_mii_phy_auto(struct mii_softc *sc, int media)
PHY_WRITE(sc, BRGPHY_SERDES_ANAR, anar);
}
- ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD;
- if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
- ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC;
- PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
- ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);
-
PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_AUTOEN |
BRGPHY_BMCR_STARTNEG);
PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
@@ -913,15 +911,25 @@ brgphy_reset(struct mii_softc *sc)
struct bge_softc *bge_sc = NULL;
struct bce_softc *bce_sc = NULL;
struct ifnet *ifp;
- int val;
+ int i, val;
+
+ /*
+ * Perform a reset. Note that at least some Broadcom PHYs default to
+ * being powered down as well as isolated after a reset but don't work
+ * if one or both of these bits are cleared. However, they just work
+ * fine if both bits remain set, so we don't use mii_phy_reset() here.
+ */
+ PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET);
- /* Perform a standard PHY reset. */
- mii_phy_reset(sc);
+ /* Wait 100ms for it to complete. */
+ for (i = 0; i < 100; i++) {
+ if ((PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_RESET) == 0)
+ break;
+ DELAY(1000);
+ }
/* Handle any PHY specific procedures following the reset. */
switch (bsc->mii_oui) {
- case MII_OUI_BROADCOM:
- break;
case MII_OUI_xxBROADCOM:
switch (bsc->mii_model) {
case MII_MODEL_xxBROADCOM_BCM5400:
@@ -939,8 +947,14 @@ brgphy_reset(struct mii_softc *sc)
break;
}
break;
- case MII_OUI_xxBROADCOM_ALT1:
case MII_OUI_xxBROADCOM_ALT2:
+ switch (bsc->mii_model) {
+ case MII_MODEL_xxBROADCOM_ALT2_BCM5717C:
+ case MII_MODEL_xxBROADCOM_ALT2_BCM5719C:
+ case MII_MODEL_xxBROADCOM_ALT2_BCM5720C:
+ case MII_MODEL_xxBROADCOM_ALT2_BCM57765:
+ return;
+ }
break;
}
@@ -968,9 +982,10 @@ brgphy_reset(struct mii_softc *sc)
if (bge_sc->bge_phy_flags & BGE_PHY_JITTER_BUG)
brgphy_fixup_jitter_bug(sc);
- brgphy_jumbo_settings(sc, ifp->if_mtu);
+ if (bge_sc->bge_flags & BGE_FLAG_JUMBO)
+ brgphy_jumbo_settings(sc, ifp->if_mtu);
- if (bge_sc->bge_phy_flags & BGE_PHY_WIRESPEED)
+ if ((bge_sc->bge_phy_flags & BGE_PHY_NO_WIRESPEED) == 0)
brgphy_ethernet_wirespeed(sc);
/* Enable Link LED on Dell boxes */
diff --git a/freebsd/sys/dev/mii/brgphyreg.h b/freebsd/sys/dev/mii/brgphyreg.h
index 3f5ee5df..b3535d59 100644
--- a/freebsd/sys/dev/mii/brgphyreg.h
+++ b/freebsd/sys/dev/mii/brgphyreg.h
@@ -59,7 +59,7 @@
#define BRGPHY_BMSR_EXTSTS 0x0100 /* Extended status present */
#define BRGPHY_BMSR_PRESUB 0x0040 /* Preamble surpression */
#define BRGPHY_BMSR_ACOMP 0x0020 /* Autoneg complete */
-#define BRGPHY_BMSR_RFAULT 0x0010 /* Remote fault condition occured */
+#define BRGPHY_BMSR_RFAULT 0x0010 /* Remote fault condition occurred */
#define BRGPHY_BMSR_ANEG 0x0008 /* Autoneg capable */
#define BRGPHY_BMSR_LINK 0x0004 /* Link status */
#define BRGPHY_BMSR_JABBER 0x0002 /* Jabber detected */
diff --git a/freebsd/sys/dev/mii/icsphy.c b/freebsd/sys/dev/mii/icsphy.c
index e2315bc8..3c178c52 100644
--- a/freebsd/sys/dev/mii/icsphy.c
+++ b/freebsd/sys/dev/mii/icsphy.c
@@ -96,7 +96,7 @@ static device_method_t icsphy_methods[] = {
DEVMETHOD(device_attach, icsphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t icsphy_devclass;
@@ -149,7 +149,7 @@ icsphy_attach(device_t dev)
sc->mii_service = icsphy_service;
sc->mii_pdata = mii;
- sc->mii_flags |= MIIF_NOISOLATE;
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOMANPAUSE;
ifmedia_add(&mii->mii_media,
IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
@@ -242,7 +242,8 @@ icsphy_status(struct mii_softc *sc)
else
mii->mii_media_active |= IFM_10_T;
if (qpr & QPR_FDX)
- mii->mii_media_active |= IFM_FDX;
+ mii->mii_media_active |=
+ IFM_FDX | mii_phy_flowstatus(sc);
else
mii->mii_media_active |= IFM_HDX;
} else
diff --git a/freebsd/sys/dev/mii/mii.c b/freebsd/sys/dev/mii/mii.c
index 5b949156..2e2e6c79 100644
--- a/freebsd/sys/dev/mii/mii.c
+++ b/freebsd/sys/dev/mii/mii.c
@@ -46,11 +46,10 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/malloc.h>
#include <sys/module.h>
-#include <sys/bus.h>
+#include <sys/bus.h>
#include <net/if.h>
#include <net/if_media.h>
-#include <net/route.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
@@ -59,18 +58,20 @@ MODULE_VERSION(miibus, 1);
#include <rtems/bsd/local/miibus_if.h>
-static int miibus_print_child(device_t dev, device_t child);
-static int miibus_read_ivar(device_t dev, device_t child, int which,
- uintptr_t *result);
-static int miibus_child_location_str(device_t bus, device_t child, char *buf,
- size_t buflen);
-static int miibus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
- size_t buflen);
-static int miibus_readreg(device_t, int, int);
-static int miibus_writereg(device_t, int, int, int);
-static void miibus_statchg(device_t);
-static void miibus_linkchg(device_t);
-static void miibus_mediainit(device_t);
+static device_attach_t miibus_attach;
+static bus_child_location_str_t miibus_child_location_str;
+static bus_child_pnpinfo_str_t miibus_child_pnpinfo_str;
+static device_detach_t miibus_detach;
+static bus_hinted_child_t miibus_hinted_child;
+static bus_print_child_t miibus_print_child;
+static device_probe_t miibus_probe;
+static bus_read_ivar_t miibus_read_ivar;
+static miibus_readreg_t miibus_readreg;
+static miibus_statchg_t miibus_statchg;
+static miibus_writereg_t miibus_writereg;
+static miibus_linkchg_t miibus_linkchg;
+static miibus_mediainit_t miibus_mediainit;
+
static device_method_t miibus_methods[] = {
/* device interface */
@@ -82,18 +83,18 @@ static device_method_t miibus_methods[] = {
/* bus interface */
DEVMETHOD(bus_print_child, miibus_print_child),
DEVMETHOD(bus_read_ivar, miibus_read_ivar),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_child_pnpinfo_str, miibus_child_pnpinfo_str),
DEVMETHOD(bus_child_location_str, miibus_child_location_str),
+ DEVMETHOD(bus_hinted_child, miibus_hinted_child),
/* MII interface */
DEVMETHOD(miibus_readreg, miibus_readreg),
DEVMETHOD(miibus_writereg, miibus_writereg),
- DEVMETHOD(miibus_statchg, miibus_statchg),
- DEVMETHOD(miibus_linkchg, miibus_linkchg),
- DEVMETHOD(miibus_mediainit, miibus_mediainit),
+ DEVMETHOD(miibus_statchg, miibus_statchg),
+ DEVMETHOD(miibus_linkchg, miibus_linkchg),
+ DEVMETHOD(miibus_mediainit, miibus_mediainit),
- { 0, 0 }
+ DEVMETHOD_END
};
devclass_t miibus_devclass;
@@ -108,10 +109,11 @@ struct miibus_ivars {
struct ifnet *ifp;
ifm_change_cb_t ifmedia_upd;
ifm_stat_cb_t ifmedia_sts;
- int mii_flags;
+ u_int mii_flags;
+ u_int mii_offset;
};
-int
+static int
miibus_probe(device_t dev)
{
@@ -120,7 +122,7 @@ miibus_probe(device_t dev)
return (BUS_PROBE_SPECIFIC);
}
-int
+static int
miibus_attach(device_t dev)
{
struct miibus_ivars *ivars;
@@ -130,7 +132,6 @@ miibus_attach(device_t dev)
int i, nchildren;
mii = device_get_softc(dev);
- nchildren = 0;
if (device_get_children(dev, &children, &nchildren) == 0) {
for (i = 0; i < nchildren; i++) {
ma = device_get_ivars(children[i]);
@@ -153,7 +154,7 @@ miibus_attach(device_t dev)
return (bus_generic_attach(dev));
}
-int
+static int
miibus_detach(device_t dev)
{
struct mii_data *mii;
@@ -202,7 +203,7 @@ miibus_read_ivar(device_t dev, device_t child __unused, int which,
}
static int
-miibus_child_pnpinfo_str(device_t bus __unused, device_t child, char *buf,
+miibus_child_pnpinfo_str(device_t dev __unused, device_t child, char *buf,
size_t buflen)
{
struct mii_attach_args *ma;
@@ -215,7 +216,7 @@ miibus_child_pnpinfo_str(device_t bus __unused, device_t child, char *buf,
}
static int
-miibus_child_location_str(device_t bus __unused, device_t child, char *buf,
+miibus_child_location_str(device_t dev __unused, device_t child, char *buf,
size_t buflen)
{
struct mii_attach_args *ma;
@@ -225,6 +226,60 @@ miibus_child_location_str(device_t bus __unused, device_t child, char *buf,
return (0);
}
+static void
+miibus_hinted_child(device_t dev, const char *name, int unit)
+{
+ struct miibus_ivars *ivars;
+ struct mii_attach_args *args, *ma;
+ device_t *children, phy;
+ int i, nchildren;
+ u_int val;
+
+ if (resource_int_value(name, unit, "phyno", &val) != 0)
+ return;
+ if (device_get_children(dev, &children, &nchildren) != 0)
+ return;
+ ma = NULL;
+ for (i = 0; i < nchildren; i++) {
+ args = device_get_ivars(children[i]);
+ if (args->mii_phyno == val) {
+ ma = args;
+ break;
+ }
+ }
+ free(children, M_TEMP);
+
+ /*
+ * Don't add a PHY that was automatically identified by having media
+ * in its BMSR twice, only allow to alter its attach arguments.
+ */
+ if (ma == NULL) {
+ ma = malloc(sizeof(struct mii_attach_args), M_DEVBUF,
+ M_NOWAIT);
+ if (ma == NULL)
+ return;
+ phy = device_add_child(dev, name, unit);
+ if (phy == NULL) {
+ free(ma, M_DEVBUF);
+ return;
+ }
+ ivars = device_get_ivars(dev);
+ ma->mii_phyno = val;
+ ma->mii_offset = ivars->mii_offset++;
+ ma->mii_id1 = 0;
+ ma->mii_id2 = 0;
+ ma->mii_capmask = BMSR_DEFCAPMASK;
+ device_set_ivars(phy, ma);
+ }
+
+ if (resource_int_value(name, unit, "id1", &val) == 0)
+ ma->mii_id1 = val;
+ if (resource_int_value(name, unit, "id2", &val) == 0)
+ ma->mii_id2 = val;
+ if (resource_int_value(name, unit, "capmask", &val) == 0)
+ ma->mii_capmask = val;
+}
+
static int
miibus_readreg(device_t dev, int phy, int reg)
{
@@ -274,7 +329,7 @@ miibus_linkchg(device_t dev)
MIIBUS_LINKCHG(parent);
mii = device_get_softc(dev);
-
+
if (mii->mii_media_status & IFM_AVALID) {
if (mii->mii_media_status & IFM_ACTIVE)
link_state = LINK_STATE_UP;
@@ -319,9 +374,10 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
int phyloc, int offloc, int flags)
{
struct miibus_ivars *ivars;
- struct mii_attach_args ma, *args;
+ struct mii_attach_args *args, ma;
device_t *children, phy;
- int bmsr, first, i, nchildren, offset, phymax, phymin, rv;
+ int bmsr, first, i, nchildren, phymax, phymin, rv;
+ uint32_t phymask;
if (phyloc != MII_PHY_ANY && offloc != MII_OFFSET_ANY) {
printf("%s: phyloc and offloc specified\n", __func__);
@@ -374,38 +430,41 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
* has been allocated.
*/
ma.mii_data = device_get_softc(*miibus);
- }
+ }
ma.mii_capmask = capmask;
- phy = NULL;
- offset = 0;
+ if (resource_int_value(device_get_name(*miibus),
+ device_get_unit(*miibus), "phymask", &phymask) != 0)
+ phymask = 0xffffffff;
+
+ if (device_get_children(*miibus, &children, &nchildren) != 0) {
+ children = NULL;
+ nchildren = 0;
+ }
+ ivars->mii_offset = 0;
for (ma.mii_phyno = phymin; ma.mii_phyno <= phymax; ma.mii_phyno++) {
/*
* Make sure we haven't already configured a PHY at this
* address. This allows mii_attach() to be called
* multiple times.
*/
- if (device_get_children(*miibus, &children, &nchildren) == 0) {
- for (i = 0; i < nchildren; i++) {
- args = device_get_ivars(children[i]);
- if (args->mii_phyno == ma.mii_phyno) {
- /*
- * Yes, there is already something
- * configured at this address.
- */
- free(children, M_TEMP);
- goto skip;
- }
+ for (i = 0; i < nchildren; i++) {
+ args = device_get_ivars(children[i]);
+ if (args->mii_phyno == ma.mii_phyno) {
+ /*
+ * Yes, there is already something
+ * configured at this address.
+ */
+ goto skip;
}
- free(children, M_TEMP);
}
/*
* Check to see if there is a PHY at this address. Note,
* many braindead PHYs report 0/0 in their ID registers,
* so we test for media in the BMSR.
- */
+ */
bmsr = MIIBUS_READREG(dev, ma.mii_phyno, MII_BMSR);
if (bmsr == 0 || bmsr == 0xffff ||
(bmsr & (BMSR_EXTSTAT | BMSR_MEDIAMASK)) == 0) {
@@ -417,14 +476,20 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
* There is a PHY at this address. If we were given an
* `offset' locator, skip this PHY if it doesn't match.
*/
- if (offloc != MII_OFFSET_ANY && offloc != offset)
+ if (offloc != MII_OFFSET_ANY && offloc != ivars->mii_offset)
+ goto skip;
+
+ /*
+ * Skip this PHY if it's not included in the phymask hint.
+ */
+ if ((phymask & (1 << ma.mii_phyno)) == 0)
goto skip;
/*
- * Extract the IDs. Braindead PHYs will be handled by
+ * Extract the IDs. Braindead PHYs will be handled by
* the `ukphy' driver, as we have no ID information to
* match on.
- */
+ */
ma.mii_id1 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR1);
ma.mii_id2 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR2);
@@ -440,11 +505,20 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
}
device_set_ivars(phy, args);
skip:
- offset++;
+ ivars->mii_offset++;
}
+ free(children, M_TEMP);
if (first != 0) {
- if (phy == NULL) {
+ rv = device_set_driver(*miibus, &miibus_driver);
+ if (rv != 0)
+ goto fail;
+ bus_enumerate_hinted_children(*miibus);
+ rv = device_get_children(*miibus, &children, &nchildren);
+ if (rv != 0)
+ goto fail;
+ free(children, M_TEMP);
+ if (nchildren == 0) {
rv = ENXIO;
goto fail;
}
diff --git a/freebsd/sys/dev/mii/mii.h b/freebsd/sys/dev/mii/mii.h
index 1d887d23..5316f1eb 100644
--- a/freebsd/sys/dev/mii/mii.h
+++ b/freebsd/sys/dev/mii/mii.h
@@ -89,15 +89,9 @@
* info available in register 15, but 802.3 section 22.2.4.3 also
* states that that all 1000 Mb/s capable PHYs will set this bit to 1.
*/
-#if 0
-#define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX|BMSR_10TFDX| \
- BMSR_10THDX|BMSR_ANEG)
-#else
-/* NetBSD uses: */
#define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX| \
BMSR_10TFDX|BMSR_10THDX|BMSR_100T2FDX|BMSR_100T2HDX)
-#endif
/*
* Convert BMSR media capabilities to ANAR bits for autonegotiation.
diff --git a/freebsd/sys/dev/mii/mii_bitbang.h b/freebsd/sys/dev/mii/mii_bitbang.h
new file mode 100644
index 00000000..2bc74276
--- /dev/null
+++ b/freebsd/sys/dev/mii/mii_bitbang.h
@@ -0,0 +1,54 @@
+/* $NetBSD: mii_bitbang.h,v 1.6 2009/05/12 14:31:27 cegger Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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$
+ */
+
+#define MII_BIT_MDO 0 /* data out (host->PHY) */
+#define MII_BIT_MDI 1 /* data in (PHY->host) */
+#define MII_BIT_MDC 2 /* clock */
+#define MII_BIT_DIR_HOST_PHY 3 /* set direction: host->PHY */
+#define MII_BIT_DIR_PHY_HOST 4 /* set direction: PHY->host */
+#define MII_NBITS 5
+
+struct mii_bitbang_ops {
+ uint32_t (*mbo_read)(device_t);
+ void (*mbo_write)(device_t, uint32_t);
+ uint32_t mbo_bits[MII_NBITS];
+};
+
+typedef const struct mii_bitbang_ops *mii_bitbang_ops_t;
+
+int mii_bitbang_readreg(device_t dev, mii_bitbang_ops_t ops,
+ int phy, int reg);
+void mii_bitbang_sync(device_t dev, mii_bitbang_ops_t ops);
+void mii_bitbang_writereg(device_t dev, mii_bitbang_ops_t ops,
+ int phy, int reg, int val);
diff --git a/freebsd/sys/dev/mii/mii_physubr.c b/freebsd/sys/dev/mii/mii_physubr.c
index 3b6e0042..80996d38 100644
--- a/freebsd/sys/dev/mii/mii_physubr.c
+++ b/freebsd/sys/dev/mii/mii_physubr.c
@@ -111,7 +111,7 @@ mii_phy_setmedia(struct mii_softc *sc)
/*
* Force renegotiation if MIIF_DOPAUSE or MIIF_FORCEANEG.
* The former is necessary as we might switch from flow-
- * control advertisment being off to on or vice versa.
+ * control advertisement being off to on or vice versa.
*/
if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 ||
(sc->mii_flags & (MIIF_DOPAUSE | MIIF_FORCEANEG)) != 0)
@@ -137,8 +137,9 @@ mii_phy_setmedia(struct mii_softc *sc)
gtcr |= GTCR_ADV_MS;
}
- if ((ife->ifm_media & IFM_GMASK) == (IFM_FDX | IFM_FLOW) ||
- (sc->mii_flags & MIIF_FORCEPAUSE) != 0) {
+ if ((ife->ifm_media & IFM_FDX) != 0 &&
+ ((ife->ifm_media & IFM_FLOW) != 0 ||
+ (sc->mii_flags & MIIF_FORCEPAUSE) != 0)) {
if ((sc->mii_flags & MIIF_IS_1000X) != 0)
anar |= ANAR_X_PAUSE_TOWARDS;
else {
@@ -186,7 +187,8 @@ mii_phy_auto(struct mii_softc *sc)
ANAR_CSMA;
if ((ife->ifm_media & IFM_FLOW) != 0 ||
(sc->mii_flags & MIIF_FORCEPAUSE) != 0) {
- if ((sc->mii_capabilities & BMSR_100TXFDX) != 0)
+ if ((sc->mii_capabilities &
+ (BMSR_10TFDX | BMSR_100TXFDX)) != 0)
anar |= ANAR_FC;
/* XXX Only 1000BASE-T has PAUSE_ASYM? */
if (((sc->mii_flags & MIIF_HAVE_GTCR) != 0) &&
@@ -260,7 +262,7 @@ void
mii_phy_reset(struct mii_softc *sc)
{
struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur;
- int reg, i;
+ int i, reg;
if ((sc->mii_flags & MIIF_NOISOLATE) != 0)
reg = BMCR_RESET;
@@ -276,11 +278,14 @@ mii_phy_reset(struct mii_softc *sc)
DELAY(1000);
}
- if ((sc->mii_flags & MIIF_NOISOLATE) == 0) {
- if ((ife == NULL && sc->mii_inst != 0) ||
- (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst))
- PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
- }
+ /* NB: a PHY may default to being powered down and/or isolated. */
+ reg &= ~(BMCR_PDOWN | BMCR_ISO);
+ if ((sc->mii_flags & MIIF_NOISOLATE) == 0 &&
+ ((ife == NULL && sc->mii_inst != 0) ||
+ (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst)))
+ reg |= BMCR_ISO;
+ if (PHY_READ(sc, MII_BMCR) != reg)
+ PHY_WRITE(sc, MII_BMCR, reg);
}
void
@@ -425,9 +430,11 @@ mii_phy_add_media(struct mii_softc *sc)
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
#define PRINT(s) printf("%s%s", sep, s); sep = ", "
- if ((sc->mii_flags & MIIF_NOISOLATE) == 0)
+ if ((sc->mii_flags & MIIF_NOISOLATE) == 0) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
MII_MEDIA_NONE);
+ PRINT("none");
+ }
/*
* There are different interpretations for the bits in
diff --git a/freebsd/sys/dev/mii/miivar.h b/freebsd/sys/dev/mii/miivar.h
index d56ea18d..ac58ac20 100644
--- a/freebsd/sys/dev/mii/miivar.h
+++ b/freebsd/sys/dev/mii/miivar.h
@@ -38,7 +38,7 @@
#include <sys/queue.h>
/*
- * Media Independent Interface configuration defintions.
+ * Media Independent Interface data structure defintions
*/
struct mii_softc;
@@ -65,13 +65,13 @@ struct mii_data {
* request is made.
*/
LIST_HEAD(mii_listhead, mii_softc) mii_phys;
- int mii_instance;
+ u_int mii_instance;
/*
* PHY driver fills this in with active media status.
*/
- int mii_media_status;
- int mii_media_active;
+ u_int mii_media_status;
+ u_int mii_media_active;
/*
* Calls from MII layer into network interface driver.
@@ -105,19 +105,19 @@ struct mii_softc {
LIST_ENTRY(mii_softc) mii_list; /* entry on parent's PHY list */
- int mii_phy; /* our MII address */
- int mii_inst; /* instance for ifmedia */
+ u_int mii_phy; /* our MII address */
+ u_int mii_inst; /* instance for ifmedia */
mii_downcall_t mii_service; /* our downcall */
struct mii_data *mii_pdata; /* pointer to parent's mii_data */
- int mii_flags; /* misc. flags; see below */
- int mii_capabilities; /* capabilities from BMSR */
- int mii_extcapabilities; /* extended capabilities */
- int mii_ticks; /* MII_TICK counter */
- int mii_anegticks; /* ticks before retrying aneg */
- int mii_media_active; /* last active media */
- int mii_media_status; /* last active status */
+ u_int mii_flags; /* misc. flags; see below */
+ u_int mii_capabilities; /* capabilities from BMSR */
+ u_int mii_extcapabilities; /* extended capabilities */
+ u_int mii_ticks; /* MII_TICK counter */
+ u_int mii_anegticks; /* ticks before retrying aneg */
+ u_int mii_media_active; /* last active media */
+ u_int mii_media_status; /* last active status */
};
typedef struct mii_softc mii_softc_t;
@@ -134,7 +134,7 @@ typedef struct mii_softc mii_softc_t;
#define MIIF_IS_HPNA 0x00000200 /* is a HomePNA device */
#define MIIF_FORCEANEG 0x00000400 /* force auto-negotiation */
#define MIIF_NOMANPAUSE 0x00100000 /* no manual PAUSE selection */
-#define MIIF_FORCEPAUSE 0x00200000 /* force PAUSE advertisment */
+#define MIIF_FORCEPAUSE 0x00200000 /* force PAUSE advertisement */
#define MIIF_MACPRIV0 0x01000000 /* private to the MAC driver */
#define MIIF_MACPRIV1 0x02000000 /* private to the MAC driver */
#define MIIF_MACPRIV2 0x04000000 /* private to the MAC driver */
@@ -161,10 +161,11 @@ typedef struct mii_softc mii_softc_t;
*/
struct mii_attach_args {
struct mii_data *mii_data; /* pointer to parent data */
- int mii_phyno; /* MII address */
- int mii_id1; /* PHY ID register 1 */
- int mii_id2; /* PHY ID register 2 */
- int mii_capmask; /* capability mask from BMSR */
+ u_int mii_phyno; /* MII address */
+ u_int mii_offset; /* first PHY, second PHY, etc. */
+ uint32_t mii_id1; /* PHY ID register 1 */
+ uint32_t mii_id2; /* PHY ID register 2 */
+ u_int mii_capmask; /* capability mask for BMSR */
};
typedef struct mii_attach_args mii_attach_args_t;
@@ -172,8 +173,8 @@ typedef struct mii_attach_args mii_attach_args_t;
* Used to match a PHY.
*/
struct mii_phydesc {
- u_int32_t mpd_oui; /* the PHY's OUI */
- u_int32_t mpd_model; /* the PHY's model */
+ uint32_t mpd_oui; /* the PHY's OUI */
+ uint32_t mpd_model; /* the PHY's model */
const char *mpd_name; /* the PHY's name */
};
#define MII_PHY_DESC(a, b) { MII_OUI_ ## a, MII_MODEL_ ## a ## _ ## b, \
@@ -184,9 +185,9 @@ struct mii_phydesc {
* An array of these structures map MII media types to BMCR/ANAR settings.
*/
struct mii_media {
- int mm_bmcr; /* BMCR settings for this media */
- int mm_anar; /* ANAR settings for this media */
- int mm_gtcr; /* 100base-T2 or 1000base-T CR */
+ u_int mm_bmcr; /* BMCR settings for this media */
+ u_int mm_anar; /* ANAR settings for this media */
+ u_int mm_gtcr; /* 100base-T2 or 1000base-T CR */
};
#define MII_MEDIA_NONE 0
@@ -219,15 +220,11 @@ enum miibus_device_ivars {
#define MIIBUS_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(miibus, var, MIIBUS, ivar, type)
-MIIBUS_ACCESSOR(flags, FLAGS, int)
+MIIBUS_ACCESSOR(flags, FLAGS, u_int)
extern devclass_t miibus_devclass;
extern driver_t miibus_driver;
-int miibus_probe(device_t);
-int miibus_attach(device_t);
-int miibus_detach(device_t);
-
int mii_attach(device_t, device_t *, struct ifnet *, ifm_change_cb_t,
ifm_stat_cb_t, int, int, int, int);
int mii_anar(int);
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index 8552fdb7..1a3b2312 100644
--- a/freebsd/sys/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
@@ -82,10 +82,31 @@ __FBSDID("$FreeBSD$");
#define ACPI_PWR_FOR_SLEEP(x, y, z)
#endif
+/*
+ * XXX: Due to a limitation of the bus_dma_tag_create() API, we cannot
+ * specify a 4GB boundary on 32-bit targets. Usually this does not
+ * matter as it is ok to use a boundary of 0 on these systems.
+ * However, in the case of PAE, DMA addresses can cross a 4GB
+ * boundary, so as a workaround use a 2GB boundary.
+ */
+#if (BUS_SPACE_MAXADDR > 0xFFFFFFFF)
+#ifdef PAE
+#define PCI_DMA_BOUNDARY 0x80000000
+#else
+#define PCI_DMA_BOUNDARY 0x100000000
+#endif
+#endif
+
+#define PCIR_IS_BIOS(cfg, reg) \
+ (((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) || \
+ ((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1))
+
static pci_addr_t pci_mapbase(uint64_t mapreg);
static const char *pci_maptype(uint64_t mapreg);
static int pci_mapsize(uint64_t testval);
static int pci_maprange(uint64_t mapreg);
+static pci_addr_t pci_rombase(uint64_t mapreg);
+static int pci_romsize(uint64_t testval);
static void pci_fixancient(pcicfgregs *cfg);
static int pci_printf(pcicfgregs *cfg, const char *fmt, ...);
@@ -101,10 +122,11 @@ static void pci_load_vendor_data(void);
static int pci_describe_parse_line(char **ptr, int *vendor,
int *device, char **desc);
static char *pci_describe_device(device_t dev);
+static bus_dma_tag_t pci_get_dma_tag(device_t bus, device_t dev);
static int pci_modevent(module_t mod, int what, void *arg);
static void pci_hdrtypedata(device_t pcib, int b, int s, int f,
pcicfgregs *cfg);
-static void pci_read_extcap(device_t pcib, pcicfgregs *cfg);
+static void pci_read_cap(device_t pcib, pcicfgregs *cfg);
static int pci_read_vpd_reg(device_t pcib, pcicfgregs *cfg,
int reg, uint32_t *data);
#if 0
@@ -143,14 +165,16 @@ static device_method_t pci_methods[] = {
DEVMETHOD(bus_setup_intr, pci_setup_intr),
DEVMETHOD(bus_teardown_intr, pci_teardown_intr),
+ DEVMETHOD(bus_get_dma_tag, pci_get_dma_tag),
DEVMETHOD(bus_get_resource_list,pci_get_resource_list),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_delete_resource, pci_delete_resource),
DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method),
DEVMETHOD(bus_child_location_str, pci_child_location_str_method),
DEVMETHOD(bus_remap_intr, pci_remap_intr_method),
@@ -175,10 +199,10 @@ static device_method_t pci_methods[] = {
DEVMETHOD(pci_msi_count, pci_msi_count_method),
DEVMETHOD(pci_msix_count, pci_msix_count_method),
- { 0, 0 }
+ DEVMETHOD_END
};
-DEFINE_CLASS_0(pci, pci_driver, pci_methods, 0);
+DEFINE_CLASS_0(pci, pci_driver, pci_methods, sizeof(struct pci_softc));
static devclass_t pci_devclass;
DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0);
@@ -187,18 +211,18 @@ MODULE_VERSION(pci, 1);
static char *pci_vendordata;
static size_t pci_vendordata_size;
-
struct pci_quirk {
uint32_t devid; /* Vendor/device of the card */
int type;
#define PCI_QUIRK_MAP_REG 1 /* PCI map register in weird place */
#define PCI_QUIRK_DISABLE_MSI 2 /* MSI/MSI-X doesn't work */
#define PCI_QUIRK_ENABLE_MSI_VM 3 /* Older chipset in VM where MSI works */
+#define PCI_QUIRK_UNMAP_REG 4 /* Ignore PCI map register */
int arg1;
int arg2;
};
-struct pci_quirk pci_quirks[] = {
+static const struct pci_quirk pci_quirks[] = {
/* The Intel 82371AB and 82443MX has a map register at offset 0x90. */
{ 0x71138086, PCI_QUIRK_MAP_REG, 0x90, 0 },
{ 0x719b8086, PCI_QUIRK_MAP_REG, 0x90, 0 },
@@ -231,11 +255,28 @@ struct pci_quirk pci_quirks[] = {
{ 0x74501022, PCI_QUIRK_DISABLE_MSI, 0, 0 },
/*
+ * MSI-X allocation doesn't work properly for devices passed through
+ * by VMware up to at least ESXi 5.1.
+ */
+ { 0x079015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCI/PCI-X */
+ { 0x07a015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCIe */
+
+ /*
* Some virtualization environments emulate an older chipset
* but support MSI just fine. QEMU uses the Intel 82440.
*/
{ 0x12378086, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 },
+ /*
+ * HPET MMIO base address may appear in Bar1 for AMD SB600 SMBus
+ * controller depending on SoftPciRst register (PM_IO 0x55 [7]).
+ * It prevents us from attaching hpet(4) when the bit is unset.
+ * Note this quirk only affects SB600 revision A13 and earlier.
+ * For SB600 A21 and later, firmware must set the bit to hide it.
+ * For SB700 and later, it is unused and hardcoded to zero.
+ */
+ { 0x43851002, PCI_QUIRK_UNMAP_REG, 0x14, 0 },
+
{ 0 }
};
@@ -296,7 +337,7 @@ static int pci_usb_takeover = 1;
static int pci_usb_takeover = 0;
#endif
TUNABLE_INT("hw.pci.usb_early_takeover", &pci_usb_takeover);
-SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RD | CTLFLAG_TUN,
+SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RDTUN,
&pci_usb_takeover, 1, "Enable early takeover of USB controllers.\n\
Disable this if you depend on BIOS emulation of USB devices, that is\n\
you use USB devices (like keyboard or mouse) but do not load USB drivers");
@@ -348,6 +389,21 @@ pci_find_device(uint16_t vendor, uint16_t device)
}
#endif /* __rtems__ */
+device_t
+pci_find_class(uint8_t class, uint8_t subclass)
+{
+ struct pci_devinfo *dinfo;
+
+ STAILQ_FOREACH(dinfo, &pci_devq, pci_links) {
+ if (dinfo->cfg.baseclass == class &&
+ dinfo->cfg.subclass == subclass) {
+ return (dinfo->cfg.dev);
+ }
+ }
+
+ return (NULL);
+}
+
static int
pci_printf(pcicfgregs *cfg, const char *fmt, ...)
{
@@ -406,6 +462,34 @@ pci_mapsize(uint64_t testval)
return (ln2size);
}
+/* return base address of device ROM */
+
+static pci_addr_t
+pci_rombase(uint64_t mapreg)
+{
+
+ return (mapreg & PCIM_BIOS_ADDR_MASK);
+}
+
+/* return log2 of map size decided for device ROM */
+
+static int
+pci_romsize(uint64_t testval)
+{
+ int ln2size;
+
+ testval = pci_rombase(testval);
+ ln2size = 0;
+ if (testval != 0) {
+ while ((testval & 1) == 0)
+ {
+ ln2size++;
+ testval >>= 1;
+ }
+ }
+ return (ln2size);
+}
+
/* return log2 of address range supported by map register */
static int
@@ -510,12 +594,13 @@ pci_read_device(device_t pcib, int d, int b, int s, int f, size_t size)
cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
cfg->hdrtype &= ~PCIM_MFDEV;
+ STAILQ_INIT(&cfg->maps);
pci_fixancient(cfg);
pci_hdrtypedata(pcib, b, s, f, cfg);
if (REG(PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT)
- pci_read_extcap(pcib, cfg);
+ pci_read_cap(pcib, cfg);
STAILQ_INSERT_TAIL(devlist_head, devlist_entry, pci_links);
@@ -543,7 +628,7 @@ pci_read_device(device_t pcib, int d, int b, int s, int f, size_t size)
}
static void
-pci_read_extcap(device_t pcib, pcicfgregs *cfg)
+pci_read_cap(device_t pcib, pcicfgregs *cfg)
{
#define REG(n, w) PCIB_READ_CONFIG(pcib, cfg->bus, cfg->slot, cfg->func, n, w)
#define WREG(n, v, w) PCIB_WRITE_CONFIG(pcib, cfg->bus, cfg->slot, cfg->func, n, v, w)
@@ -591,10 +676,14 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg)
cfg->pp.pp_data = ptr + PCIR_POWER_DATA;
}
break;
-#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
case PCIY_HT: /* HyperTransport */
/* Determine HT-specific capability type. */
val = REG(ptr + PCIR_HT_COMMAND, 2);
+
+ if ((val & 0xe000) == PCIM_HTCAP_SLAVE)
+ cfg->ht.ht_slave = ptr;
+
+#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
switch (val & PCIM_HTCMD_CAP_MASK) {
case PCIM_HTCAP_MSI_MAPPING:
if (!(val & PCIM_HTCMD_MSI_FIXED)) {
@@ -606,7 +695,7 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg)
4);
if (addr != MSI_INTEL_ADDR_BASE)
device_printf(pcib,
- "HT Bridge at pci%d:%d:%d:%d has non-default MSI window 0x%llx\n",
+ "HT device at pci%d:%d:%d:%d has non-default MSI window 0x%llx\n",
cfg->domain, cfg->bus,
cfg->slot, cfg->func,
(long long)addr);
@@ -618,8 +707,8 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg)
cfg->ht.ht_msiaddr = addr;
break;
}
- break;
#endif
+ break;
case PCIY_MSI: /* PCI MSI */
cfg->msi.msi_location = ptr;
cfg->msi.msi_ctrl = REG(ptr + PCIR_MSI_CTRL, 2);
@@ -673,6 +762,23 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg)
break;
}
}
+
+#if defined(__powerpc__)
+ /*
+ * Enable the MSI mapping window for all HyperTransport
+ * slaves. PCI-PCI bridges have their windows enabled via
+ * PCIB_MAP_MSI().
+ */
+ if (cfg->ht.ht_slave != 0 && cfg->ht.ht_msimap != 0 &&
+ !(cfg->ht.ht_msictrl & PCIM_HTCMD_MSI_ENABLE)) {
+ device_printf(pcib,
+ "Enabling MSI window for HyperTransport slave at pci%d:%d:%d:%d\n",
+ cfg->domain, cfg->bus, cfg->slot, cfg->func);
+ cfg->ht.ht_msictrl |= PCIM_HTCMD_MSI_ENABLE;
+ WREG(cfg->ht.ht_msimap + PCIR_HT_COMMAND, cfg->ht.ht_msictrl,
+ 2);
+ }
+#endif
/* REG and WREG use carry through to next functions */
}
@@ -1068,11 +1174,9 @@ pci_get_vpd_readonly_method(device_t dev, device_t child, const char *kw,
if (memcmp(kw, cfg->vpd.vpd_ros[i].keyword,
sizeof(cfg->vpd.vpd_ros[i].keyword)) == 0) {
*vptr = cfg->vpd.vpd_ros[i].value;
+ return (0);
}
- if (i != cfg->vpd.vpd_rocnt)
- return (0);
-
*vptr = NULL;
return (ENXIO);
}
@@ -1286,8 +1390,11 @@ pci_alloc_msix_method(device_t dev, device_t child, int *count)
for (i = 0; i < max; i++) {
/* Allocate a message. */
error = PCIB_ALLOC_MSIX(device_get_parent(dev), child, &irq);
- if (error)
+ if (error) {
+ if (i == 0)
+ return (error);
break;
+ }
resource_list_add(&dinfo->resources, SYS_RES_IRQ, i + 1, irq,
irq, 1);
}
@@ -1620,10 +1727,10 @@ pci_get_max_read_req(device_t dev)
int cap;
uint16_t val;
- if (pci_find_extcap(dev, PCIY_EXPRESS, &cap) != 0)
+ if (pci_find_cap(dev, PCIY_EXPRESS, &cap) != 0)
return (0);
- val = pci_read_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, 2);
- val &= PCIM_EXP_CTL_MAX_READ_REQUEST;
+ val = pci_read_config(dev, cap + PCIER_DEVICE_CTL, 2);
+ val &= PCIEM_CTL_MAX_READ_REQUEST;
val >>= 12;
return (1 << (val + 7));
}
@@ -1634,17 +1741,17 @@ pci_set_max_read_req(device_t dev, int size)
int cap;
uint16_t val;
- if (pci_find_extcap(dev, PCIY_EXPRESS, &cap) != 0)
+ if (pci_find_cap(dev, PCIY_EXPRESS, &cap) != 0)
return (0);
if (size < 128)
size = 128;
if (size > 4096)
size = 4096;
size = (1 << (fls(size) - 1));
- val = pci_read_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, 2);
- val &= ~PCIM_EXP_CTL_MAX_READ_REQUEST;
+ val = pci_read_config(dev, cap + PCIER_DEVICE_CTL, 2);
+ val &= ~PCIEM_CTL_MAX_READ_REQUEST;
val |= (fls(size) - 8) << 12;
- pci_write_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, val, 2);
+ pci_write_config(dev, cap + PCIER_DEVICE_CTL, val, 2);
return (size);
}
@@ -1804,7 +1911,7 @@ pci_remap_intr_method(device_t bus, device_t dev, u_int irq)
int
pci_msi_device_blacklisted(device_t dev)
{
- struct pci_quirk *q;
+ const struct pci_quirk *q;
if (!pci_honor_msi_blacklist)
return (0);
@@ -1824,7 +1931,7 @@ pci_msi_device_blacklisted(device_t dev)
static int
pci_msi_vm_chipset(device_t dev)
{
- struct pci_quirk *q;
+ const struct pci_quirk *q;
for (q = &pci_quirks[0]; q->devid; q++) {
if (q->devid == pci_get_devid(dev) &&
@@ -1918,7 +2025,7 @@ pci_alloc_msi_method(device_t dev, device_t child, int *count)
for (;;) {
/* Try to allocate N messages. */
error = PCIB_ALLOC_MSI(device_get_parent(dev), child, actual,
- cfg->msi.msi_msgnum, irqs);
+ actual, irqs);
if (error == 0)
break;
if (actual == 1)
@@ -2061,6 +2168,7 @@ int
pci_freecfg(struct pci_devinfo *dinfo)
{
struct devlist *devlist_head;
+ struct pci_map *pm, *next;
int i;
devlist_head = &pci_devq;
@@ -2074,6 +2182,9 @@ pci_freecfg(struct pci_devinfo *dinfo)
free(dinfo->cfg.vpd.vpd_w[i].value, M_DEVBUF);
free(dinfo->cfg.vpd.vpd_w, M_DEVBUF);
}
+ STAILQ_FOREACH_SAFE(pm, &dinfo->cfg.maps, pm_link, next) {
+ free(pm, M_DEVBUF);
+ }
STAILQ_REMOVE(devlist_head, dinfo, pci_devinfo, pci_links);
free(dinfo, M_DEVBUF);
@@ -2348,10 +2459,27 @@ pci_memen(device_t dev)
static void
pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp)
{
+ struct pci_devinfo *dinfo;
pci_addr_t map, testval;
int ln2range;
uint16_t cmd;
+ /*
+ * The device ROM BAR is special. It is always a 32-bit
+ * memory BAR. Bit 0 is special and should not be set when
+ * sizing the BAR.
+ */
+ dinfo = device_get_ivars(dev);
+ if (PCIR_IS_BIOS(&dinfo->cfg, reg)) {
+ map = pci_read_config(dev, reg, 4);
+ pci_write_config(dev, reg, 0xfffffffe, 4);
+ testval = pci_read_config(dev, reg, 4);
+ pci_write_config(dev, reg, map, 4);
+ *mapp = map;
+ *testvalp = testval;
+ return;
+ }
+
map = pci_read_config(dev, reg, 4);
ln2range = pci_maprange(map);
if (ln2range == 64)
@@ -2393,16 +2521,100 @@ pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp)
}
static void
-pci_write_bar(device_t dev, int reg, pci_addr_t base)
+pci_write_bar(device_t dev, struct pci_map *pm, pci_addr_t base)
{
- pci_addr_t map;
+ struct pci_devinfo *dinfo;
int ln2range;
- map = pci_read_config(dev, reg, 4);
- ln2range = pci_maprange(map);
- pci_write_config(dev, reg, base, 4);
+ /* The device ROM BAR is always a 32-bit memory BAR. */
+ dinfo = device_get_ivars(dev);
+ if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg))
+ ln2range = 32;
+ else
+ ln2range = pci_maprange(pm->pm_value);
+ pci_write_config(dev, pm->pm_reg, base, 4);
+ if (ln2range == 64)
+ pci_write_config(dev, pm->pm_reg + 4, base >> 32, 4);
+ pm->pm_value = pci_read_config(dev, pm->pm_reg, 4);
if (ln2range == 64)
- pci_write_config(dev, reg + 4, base >> 32, 4);
+ pm->pm_value |= (pci_addr_t)pci_read_config(dev,
+ pm->pm_reg + 4, 4) << 32;
+}
+
+struct pci_map *
+pci_find_bar(device_t dev, int reg)
+{
+ struct pci_devinfo *dinfo;
+ struct pci_map *pm;
+
+ dinfo = device_get_ivars(dev);
+ STAILQ_FOREACH(pm, &dinfo->cfg.maps, pm_link) {
+ if (pm->pm_reg == reg)
+ return (pm);
+ }
+ return (NULL);
+}
+
+int
+pci_bar_enabled(device_t dev, struct pci_map *pm)
+{
+ struct pci_devinfo *dinfo;
+ uint16_t cmd;
+
+ dinfo = device_get_ivars(dev);
+ if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) &&
+ !(pm->pm_value & PCIM_BIOS_ENABLE))
+ return (0);
+ cmd = pci_read_config(dev, PCIR_COMMAND, 2);
+ if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) || PCI_BAR_MEM(pm->pm_value))
+ return ((cmd & PCIM_CMD_MEMEN) != 0);
+ else
+ return ((cmd & PCIM_CMD_PORTEN) != 0);
+}
+
+static struct pci_map *
+pci_add_bar(device_t dev, int reg, pci_addr_t value, pci_addr_t size)
+{
+ struct pci_devinfo *dinfo;
+ struct pci_map *pm, *prev;
+
+ dinfo = device_get_ivars(dev);
+ pm = malloc(sizeof(*pm), M_DEVBUF, M_WAITOK | M_ZERO);
+ pm->pm_reg = reg;
+ pm->pm_value = value;
+ pm->pm_size = size;
+ STAILQ_FOREACH(prev, &dinfo->cfg.maps, pm_link) {
+ KASSERT(prev->pm_reg != pm->pm_reg, ("duplicate map %02x",
+ reg));
+ if (STAILQ_NEXT(prev, pm_link) == NULL ||
+ STAILQ_NEXT(prev, pm_link)->pm_reg > pm->pm_reg)
+ break;
+ }
+ if (prev != NULL)
+ STAILQ_INSERT_AFTER(&dinfo->cfg.maps, prev, pm, pm_link);
+ else
+ STAILQ_INSERT_TAIL(&dinfo->cfg.maps, pm, pm_link);
+ return (pm);
+}
+
+static void
+pci_restore_bars(device_t dev)
+{
+ struct pci_devinfo *dinfo;
+ struct pci_map *pm;
+ int ln2range;
+
+ dinfo = device_get_ivars(dev);
+ STAILQ_FOREACH(pm, &dinfo->cfg.maps, pm_link) {
+ if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg))
+ ln2range = 32;
+ else
+ ln2range = pci_maprange(pm->pm_value);
+ pci_write_config(dev, pm->pm_reg, pm->pm_value, 4);
+ if (ln2range == 64)
+ pci_write_config(dev, pm->pm_reg + 4,
+ pm->pm_value >> 32, 4);
+ }
}
/*
@@ -2413,12 +2625,24 @@ static int
pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
int force, int prefetch)
{
+ struct pci_map *pm;
pci_addr_t base, map, testval;
pci_addr_t start, end, count;
int barlen, basezero, maprange, mapsize, type;
uint16_t cmd;
struct resource *res;
+ /*
+ * The BAR may already exist if the device is a CardBus card
+ * whose CIS is stored in this BAR.
+ */
+ pm = pci_find_bar(dev, reg);
+ if (pm != NULL) {
+ maprange = pci_maprange(pm->pm_value);
+ barlen = maprange == 64 ? 2 : 1;
+ return (barlen);
+ }
+
pci_read_bar(dev, reg, &map, &testval);
if (PCI_BAR_MEM(map)) {
type = SYS_RES_MEMORY;
@@ -2449,6 +2673,8 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
(type == SYS_RES_IOPORT && mapsize < 2))
return (barlen);
+ /* Save a record of this BAR. */
+ pm = pci_add_bar(dev, reg, map, mapsize);
if (bootverbose) {
printf("\tmap[%02x]: type %s, range %2d, base %#jx, size %2d",
reg, pci_maptype(map), maprange, (uintmax_t)base, mapsize);
@@ -2507,13 +2733,13 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
return (barlen);
}
- count = 1 << mapsize;
+ count = (pci_addr_t)1 << mapsize;
if (basezero || base == pci_mapbase(testval)) {
start = 0; /* Let the parent decide. */
- end = ~0ULL;
+ end = ~0ul;
} else {
start = base;
- end = base + (1 << mapsize) - 1;
+ end = base + count - 1;
}
resource_list_add(rl, type, reg, start, end, count);
@@ -2538,7 +2764,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
start = rman_get_start(res);
rman_set_device(res, bus);
}
- pci_write_bar(dev, reg, start);
+ pci_write_bar(dev, pm, start);
return (barlen);
}
@@ -2780,12 +3006,18 @@ ehci_early_takeover(device_t self)
void
pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
{
- struct pci_devinfo *dinfo = device_get_ivars(dev);
- pcicfgregs *cfg = &dinfo->cfg;
- struct resource_list *rl = &dinfo->resources;
- struct pci_quirk *q;
+ struct pci_devinfo *dinfo;
+ pcicfgregs *cfg;
+ struct resource_list *rl;
+ const struct pci_quirk *q;
+ uint32_t devid;
int i;
+ dinfo = device_get_ivars(dev);
+ cfg = &dinfo->cfg;
+ rl = &dinfo->resources;
+ devid = (cfg->device << 16) | cfg->vendor;
+
/* ATA devices needs special map treatment */
if ((pci_get_class(dev) == PCIC_STORAGE) &&
(pci_get_subclass(dev) == PCIS_STORAGE_IDE) &&
@@ -2794,18 +3026,29 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
!pci_read_config(dev, PCIR_BAR(2), 4))) )
pci_ata_maps(bus, dev, rl, force, prefetchmask);
else
- for (i = 0; i < cfg->nummaps;)
+ for (i = 0; i < cfg->nummaps;) {
+ /*
+ * Skip quirked resources.
+ */
+ for (q = &pci_quirks[0]; q->devid != 0; q++)
+ if (q->devid == devid &&
+ q->type == PCI_QUIRK_UNMAP_REG &&
+ q->arg1 == PCIR_BAR(i))
+ break;
+ if (q->devid != 0) {
+ i++;
+ continue;
+ }
i += pci_add_map(bus, dev, PCIR_BAR(i), rl, force,
prefetchmask & (1 << i));
+ }
/*
* Add additional, quirked resources.
*/
- for (q = &pci_quirks[0]; q->devid; q++) {
- if (q->devid == ((cfg->device << 16) | cfg->vendor)
- && q->type == PCI_QUIRK_MAP_REG)
+ for (q = &pci_quirks[0]; q->devid != 0; q++)
+ if (q->devid == devid && q->type == PCI_QUIRK_MAP_REG)
pci_add_map(bus, dev, q->arg1, rl, force, 0);
- }
if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) {
#ifdef __PCI_REROUTE_INTERRUPT
@@ -2889,10 +3132,49 @@ pci_probe(device_t dev)
return (BUS_PROBE_GENERIC);
}
+int
+pci_attach_common(device_t dev)
+{
+ struct pci_softc *sc;
+ int busno, domain;
+#ifdef PCI_DMA_BOUNDARY
+ int error, tag_valid;
+#endif
+
+ sc = device_get_softc(dev);
+ domain = pcib_get_domain(dev);
+ busno = pcib_get_bus(dev);
+ if (bootverbose)
+ device_printf(dev, "domain=%d, physical bus=%d\n",
+ domain, busno);
+#ifdef PCI_DMA_BOUNDARY
+ tag_valid = 0;
+ if (device_get_devclass(device_get_parent(device_get_parent(dev))) !=
+ devclass_find("pci")) {
+ error = bus_dma_tag_create(bus_get_dma_tag(dev), 1,
+ PCI_DMA_BOUNDARY, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
+ NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED,
+ BUS_SPACE_MAXSIZE, 0, NULL, NULL, &sc->sc_dma_tag);
+ if (error)
+ device_printf(dev, "Failed to create DMA tag: %d\n",
+ error);
+ else
+ tag_valid = 1;
+ }
+ if (!tag_valid)
+#endif
+ sc->sc_dma_tag = bus_get_dma_tag(dev);
+ return (0);
+}
+
static int
pci_attach(device_t dev)
{
- int busno, domain;
+ int busno, domain, error;
+
+ error = pci_attach_common(dev);
+ if (error)
+ return (error);
/*
* Since there can be multiple independantly numbered PCI
@@ -2902,9 +3184,6 @@ pci_attach(device_t dev)
*/
domain = pcib_get_domain(dev);
busno = pcib_get_bus(dev);
- if (bootverbose)
- device_printf(dev, "domain=%d, physical bus=%d\n",
- domain, busno);
pci_add_children(dev, domain, busno, sizeof(struct pci_devinfo));
return (bus_generic_attach(dev));
}
@@ -2927,7 +3206,7 @@ pci_suspend(device_t dev)
return (error);
for (i = 0; i < numdevs; i++) {
child = devlist[i];
- dinfo = (struct pci_devinfo *) device_get_ivars(child);
+ dinfo = device_get_ivars(child);
pci_cfg_save(child, dinfo, 0);
}
@@ -3215,11 +3494,11 @@ pci_print_child(device_t dev, device_t child)
return (retval);
}
-static struct
+static const struct
{
- int class;
- int subclass;
- char *desc;
+ int class;
+ int subclass;
+ const char *desc;
} pci_nomatch_tab[] = {
{PCIC_OLD, -1, "old"},
{PCIC_OLD, PCIS_OLD_NONVGA, "non-VGA display device"},
@@ -3233,6 +3512,7 @@ static struct
{PCIC_STORAGE, PCIS_STORAGE_ATA_ADMA, "ATA (ADMA)"},
{PCIC_STORAGE, PCIS_STORAGE_SATA, "SATA"},
{PCIC_STORAGE, PCIS_STORAGE_SAS, "SAS"},
+ {PCIC_STORAGE, PCIS_STORAGE_NVM, "NVM"},
{PCIC_NETWORK, -1, "network"},
{PCIC_NETWORK, PCIS_NETWORK_ETHERNET, "ethernet"},
{PCIC_NETWORK, PCIS_NETWORK_TOKENRING, "token ring"},
@@ -3310,8 +3590,9 @@ static struct
void
pci_probe_nomatch(device_t dev, device_t child)
{
- int i;
- char *cp, *scp, *device;
+ int i;
+ const char *cp, *scp;
+ char *device;
/*
* Look for a listing for this device in a loaded device database.
@@ -3343,8 +3624,7 @@ pci_probe_nomatch(device_t dev, device_t child)
}
printf(" at device %d.%d (no driver attached)\n",
pci_get_slot(child), pci_get_function(child));
- pci_cfg_save(child, (struct pci_devinfo *)device_get_ivars(child), 1);
- return;
+ pci_cfg_save(child, device_get_ivars(child), 1);
}
/*
@@ -3590,7 +3870,6 @@ pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
}
}
-
#include <rtems/bsd/local/opt_ddb.h>
#ifdef DDB
#include <ddb/ddb.h>
@@ -3649,24 +3928,41 @@ pci_alloc_map(device_t dev, device_t child, int type, int *rid,
struct resource_list *rl = &dinfo->resources;
struct resource_list_entry *rle;
struct resource *res;
+ struct pci_map *pm;
pci_addr_t map, testval;
int mapsize;
- /*
- * Weed out the bogons, and figure out how large the BAR/map
- * is. Bars that read back 0 here are bogus and unimplemented.
- * Note: atapci in legacy mode are special and handled elsewhere
- * in the code. If you have a atapci device in legacy mode and
- * it fails here, that other code is broken.
- */
res = NULL;
- pci_read_bar(child, *rid, &map, &testval);
+ pm = pci_find_bar(child, *rid);
+ if (pm != NULL) {
+ /* This is a BAR that we failed to allocate earlier. */
+ mapsize = pm->pm_size;
+ map = pm->pm_value;
+ } else {
+ /*
+ * Weed out the bogons, and figure out how large the
+ * BAR/map is. BARs that read back 0 here are bogus
+ * and unimplemented. Note: atapci in legacy mode are
+ * special and handled elsewhere in the code. If you
+ * have a atapci device in legacy mode and it fails
+ * here, that other code is broken.
+ */
+ pci_read_bar(child, *rid, &map, &testval);
- /* Ignore a BAR with a base of 0. */
- if (pci_mapbase(testval) == 0)
- goto out;
+ /*
+ * Determine the size of the BAR and ignore BARs with a size
+ * of 0. Device ROM BARs use a different mask value.
+ */
+ if (PCIR_IS_BIOS(&dinfo->cfg, *rid))
+ mapsize = pci_romsize(testval);
+ else
+ mapsize = pci_mapsize(testval);
+ if (mapsize == 0)
+ goto out;
+ pm = pci_add_bar(child, *rid, map, mapsize);
+ }
- if (PCI_BAR_MEM(testval)) {
+ if (PCI_BAR_MEM(map) || PCIR_IS_BIOS(&dinfo->cfg, *rid)) {
if (type != SYS_RES_MEMORY) {
if (bootverbose)
device_printf(dev,
@@ -3693,16 +3989,15 @@ pci_alloc_map(device_t dev, device_t child, int type, int *rid,
* situation where we might allocate the excess to
* another driver, which won't work.
*/
- mapsize = pci_mapsize(testval);
- count = 1UL << mapsize;
+ count = (pci_addr_t)1 << mapsize;
if (RF_ALIGNMENT(flags) < mapsize)
flags = (flags & ~RF_ALIGNMENT_MASK) | RF_ALIGNMENT_LOG2(mapsize);
- if (PCI_BAR_MEM(testval) && (testval & PCIM_BAR_MEM_PREFETCH))
+ if (PCI_BAR_MEM(map) && (map & PCIM_BAR_MEM_PREFETCH))
flags |= RF_PREFETCHABLE;
/*
* Allocate enough resource, and then write back the
- * appropriate bar for that resource.
+ * appropriate BAR for that resource.
*/
res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid,
start, end, count, flags & ~RF_ACTIVE);
@@ -3726,12 +4021,11 @@ pci_alloc_map(device_t dev, device_t child, int type, int *rid,
"Lazy allocation of %#lx bytes rid %#x type %d at %#lx\n",
count, *rid, type, rman_get_start(res));
map = rman_get_start(res);
- pci_write_bar(child, *rid, map);
+ pci_write_bar(child, pm, map);
out:;
return (res);
}
-
struct resource *
pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
@@ -3770,6 +4064,26 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
break;
case SYS_RES_IOPORT:
case SYS_RES_MEMORY:
+#ifdef NEW_PCIB
+ /*
+ * PCI-PCI bridge I/O window resources are not BARs.
+ * For those allocations just pass the request up the
+ * tree.
+ */
+ if (cfg->hdrtype == PCIM_HDRTYPE_BRIDGE) {
+ switch (*rid) {
+ case PCIR_IOBASEL_1:
+ case PCIR_MEMBASE_1:
+ case PCIR_PMBASEL_1:
+ /*
+ * XXX: Should we bother creating a resource
+ * list entry?
+ */
+ return (bus_generic_alloc_resource(dev, child,
+ type, rid, start, end, count, flags));
+ }
+ }
+#endif
/* Allocate resources for this BAR if needed. */
rle = resource_list_find(rl, type, *rid);
if (rle == NULL) {
@@ -3839,6 +4153,7 @@ int
pci_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
+ struct pci_devinfo *dinfo;
int error;
error = bus_generic_activate_resource(dev, child, type, rid, r);
@@ -3847,6 +4162,11 @@ pci_activate_resource(device_t dev, device_t child, int type, int rid,
/* Enable decoding in the command register when activating BARs. */
if (device_get_parent(child) == dev) {
+ /* Device ROMs need their decoding explicitly enabled. */
+ dinfo = device_get_ivars(child);
+ if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid))
+ pci_write_bar(child, pci_find_bar(child, rid),
+ rman_get_start(r) | PCIM_BIOS_ENABLE);
switch (type) {
case SYS_RES_IOPORT:
case SYS_RES_MEMORY:
@@ -3857,6 +4177,27 @@ pci_activate_resource(device_t dev, device_t child, int type, int rid,
return (error);
}
+int
+pci_deactivate_resource(device_t dev, device_t child, int type,
+ int rid, struct resource *r)
+{
+ struct pci_devinfo *dinfo;
+ int error;
+
+ error = bus_generic_deactivate_resource(dev, child, type, rid, r);
+ if (error)
+ return (error);
+
+ /* Disable decoding for device ROMs. */
+ if (device_get_parent(child) == dev) {
+ dinfo = device_get_ivars(child);
+ if (type == SYS_RES_MEMORY && PCIR_IS_BIOS(&dinfo->cfg, rid))
+ pci_write_bar(child, pci_find_bar(child, rid),
+ rman_get_start(r));
+ }
+ return (0);
+}
+
void
pci_delete_resource(device_t dev, device_t child, int type, int rid)
{
@@ -3892,7 +4233,7 @@ pci_delete_resource(device_t dev, device_t child, int type, int rid)
switch (type) {
case SYS_RES_IOPORT:
case SYS_RES_MEMORY:
- pci_write_bar(child, rid, 0);
+ pci_write_bar(child, pci_find_bar(child, rid), 0);
break;
}
#endif
@@ -3909,6 +4250,14 @@ pci_get_resource_list (device_t dev, device_t child)
return (&dinfo->resources);
}
+bus_dma_tag_t
+pci_get_dma_tag(device_t bus, device_t dev)
+{
+ struct pci_softc *sc = device_get_softc(bus);
+
+ return (sc->sc_dma_tag);
+}
+
uint32_t
pci_read_config_method(device_t dev, device_t child, int reg, int width)
{
@@ -3991,7 +4340,6 @@ pci_modevent(module_t mod, int what, void *arg)
void
pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
{
- int i;
/*
* Only do header type 0 devices. Type 1 devices are bridges,
@@ -4011,12 +4359,9 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
* the noise on boot by doing nothing if we are already in
* state D0.
*/
- if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
+ if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0)
pci_set_powerstate(dev, PCI_POWERSTATE_D0);
- }
- for (i = 0; i < dinfo->cfg.nummaps; i++)
- pci_write_config(dev, PCIR_BAR(i), dinfo->cfg.bar[i], 4);
- pci_write_config(dev, PCIR_BIOS, dinfo->cfg.bios, 4);
+ pci_restore_bars(dev);
pci_write_config(dev, PCIR_COMMAND, dinfo->cfg.cmdreg, 2);
pci_write_config(dev, PCIR_INTLINE, dinfo->cfg.intline, 1);
pci_write_config(dev, PCIR_INTPIN, dinfo->cfg.intpin, 1);
@@ -4037,7 +4382,6 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
void
pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate)
{
- int i;
uint32_t cls;
int ps;
@@ -4050,9 +4394,6 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate)
*/
if (dinfo->cfg.hdrtype != 0)
return;
- for (i = 0; i < dinfo->cfg.nummaps; i++)
- dinfo->cfg.bar[i] = pci_read_config(dev, PCIR_BAR(i), 4);
- dinfo->cfg.bios = pci_read_config(dev, PCIR_BIOS, 4);
/*
* Some drivers apparently write to these registers w/o updating our
@@ -4117,3 +4458,22 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate)
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D3)
pci_set_powerstate(dev, PCI_POWERSTATE_D3);
}
+
+/* Wrapper APIs suitable for device driver use. */
+void
+pci_save_state(device_t dev)
+{
+ struct pci_devinfo *dinfo;
+
+ dinfo = device_get_ivars(dev);
+ pci_cfg_save(dev, dinfo, 0);
+}
+
+void
+pci_restore_state(device_t dev)
+{
+ struct pci_devinfo *dinfo;
+
+ dinfo = device_get_ivars(dev);
+ pci_cfg_restore(dev, dinfo);
+}
diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c
index 470386a3..432ba7b9 100644
--- a/freebsd/sys/dev/pci/pci_pci.c
+++ b/freebsd/sys/dev/pci/pci_pci.c
@@ -38,14 +38,16 @@ __FBSDID("$FreeBSD$");
*/
#include <rtems/bsd/sys/param.h>
-#include <sys/systm.h>
+#include <sys/bus.h>
#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/malloc.h>
#include <sys/module.h>
-#include <sys/bus.h>
-#include <machine/bus.h>
#include <sys/rman.h>
#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <machine/bus.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
@@ -66,11 +68,16 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
+#ifdef NEW_PCIB
+ DEVMETHOD(bus_adjust_resource, pcib_adjust_resource),
+ DEVMETHOD(bus_release_resource, pcib_release_resource),
+#else
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+#endif
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
@@ -87,7 +94,7 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
@@ -95,6 +102,243 @@ static devclass_t pcib_devclass;
DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc));
DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0);
+#ifdef NEW_PCIB
+/*
+ * XXX Todo:
+ * - properly handle the ISA enable bit. If it is set, we should change
+ * the behavior of the I/O window resource and rman to not allocate the
+ * blocked ranges (upper 768 bytes of each 1K in the first 64k of the
+ * I/O port address space).
+ */
+
+/*
+ * Is a resource from a child device sub-allocated from one of our
+ * resource managers?
+ */
+static int
+pcib_is_resource_managed(struct pcib_softc *sc, int type, struct resource *r)
+{
+
+ switch (type) {
+ case SYS_RES_IOPORT:
+ return (rman_is_region_manager(r, &sc->io.rman));
+ case SYS_RES_MEMORY:
+ /* Prefetchable resources may live in either memory rman. */
+ if (rman_get_flags(r) & RF_PREFETCHABLE &&
+ rman_is_region_manager(r, &sc->pmem.rman))
+ return (1);
+ return (rman_is_region_manager(r, &sc->mem.rman));
+ }
+ return (0);
+}
+
+static int
+pcib_is_window_open(struct pcib_window *pw)
+{
+
+ return (pw->valid && pw->base < pw->limit);
+}
+
+/*
+ * XXX: If RF_ACTIVE did not also imply allocating a bus space tag and
+ * handle for the resource, we could pass RF_ACTIVE up to the PCI bus
+ * when allocating the resource windows and rely on the PCI bus driver
+ * to do this for us.
+ */
+static void
+pcib_activate_window(struct pcib_softc *sc, int type)
+{
+
+ PCI_ENABLE_IO(device_get_parent(sc->dev), sc->dev, type);
+}
+
+static void
+pcib_write_windows(struct pcib_softc *sc, int mask)
+{
+ device_t dev;
+ uint32_t val;
+
+ dev = sc->dev;
+ if (sc->io.valid && mask & WIN_IO) {
+ val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
+ if ((val & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
+ pci_write_config(dev, PCIR_IOBASEH_1,
+ sc->io.base >> 16, 2);
+ pci_write_config(dev, PCIR_IOLIMITH_1,
+ sc->io.limit >> 16, 2);
+ }
+ pci_write_config(dev, PCIR_IOBASEL_1, sc->io.base >> 8, 1);
+ pci_write_config(dev, PCIR_IOLIMITL_1, sc->io.limit >> 8, 1);
+ }
+
+ if (mask & WIN_MEM) {
+ pci_write_config(dev, PCIR_MEMBASE_1, sc->mem.base >> 16, 2);
+ pci_write_config(dev, PCIR_MEMLIMIT_1, sc->mem.limit >> 16, 2);
+ }
+
+ if (sc->pmem.valid && mask & WIN_PMEM) {
+ val = pci_read_config(dev, PCIR_PMBASEL_1, 2);
+ if ((val & PCIM_BRPM_MASK) == PCIM_BRPM_64) {
+ pci_write_config(dev, PCIR_PMBASEH_1,
+ sc->pmem.base >> 32, 4);
+ pci_write_config(dev, PCIR_PMLIMITH_1,
+ sc->pmem.limit >> 32, 4);
+ }
+ pci_write_config(dev, PCIR_PMBASEL_1, sc->pmem.base >> 16, 2);
+ pci_write_config(dev, PCIR_PMLIMITL_1, sc->pmem.limit >> 16, 2);
+ }
+}
+
+static void
+pcib_alloc_window(struct pcib_softc *sc, struct pcib_window *w, int type,
+ int flags, pci_addr_t max_address)
+{
+ char buf[64];
+ int error, rid;
+
+ if (max_address != (u_long)max_address)
+ max_address = ~0ul;
+ w->rman.rm_start = 0;
+ w->rman.rm_end = max_address;
+ w->rman.rm_type = RMAN_ARRAY;
+ snprintf(buf, sizeof(buf), "%s %s window",
+ device_get_nameunit(sc->dev), w->name);
+ w->rman.rm_descr = strdup(buf, M_DEVBUF);
+ error = rman_init(&w->rman);
+ if (error)
+ panic("Failed to initialize %s %s rman",
+ device_get_nameunit(sc->dev), w->name);
+
+ if (!pcib_is_window_open(w))
+ return;
+
+ if (w->base > max_address || w->limit > max_address) {
+ device_printf(sc->dev,
+ "initial %s window has too many bits, ignoring\n", w->name);
+ return;
+ }
+ rid = w->reg;
+ w->res = bus_alloc_resource(sc->dev, type, &rid, w->base, w->limit,
+ w->limit - w->base + 1, flags);
+ if (w->res == NULL) {
+ device_printf(sc->dev,
+ "failed to allocate initial %s window: %#jx-%#jx\n",
+ w->name, (uintmax_t)w->base, (uintmax_t)w->limit);
+ w->base = max_address;
+ w->limit = 0;
+ pcib_write_windows(sc, w->mask);
+ return;
+ }
+ pcib_activate_window(sc, type);
+
+ error = rman_manage_region(&w->rman, rman_get_start(w->res),
+ rman_get_end(w->res));
+ if (error)
+ panic("Failed to initialize rman with resource");
+}
+
+/*
+ * Initialize I/O windows.
+ */
+static void
+pcib_probe_windows(struct pcib_softc *sc)
+{
+ pci_addr_t max;
+ device_t dev;
+ uint32_t val;
+
+ dev = sc->dev;
+
+ /* Determine if the I/O port window is implemented. */
+ val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
+ if (val == 0) {
+ /*
+ * If 'val' is zero, then only 16-bits of I/O space
+ * are supported.
+ */
+ pci_write_config(dev, PCIR_IOBASEL_1, 0xff, 1);
+ if (pci_read_config(dev, PCIR_IOBASEL_1, 1) != 0) {
+ sc->io.valid = 1;
+ pci_write_config(dev, PCIR_IOBASEL_1, 0, 1);
+ }
+ } else
+ sc->io.valid = 1;
+
+ /* Read the existing I/O port window. */
+ if (sc->io.valid) {
+ sc->io.reg = PCIR_IOBASEL_1;
+ sc->io.step = 12;
+ sc->io.mask = WIN_IO;
+ sc->io.name = "I/O port";
+ if ((val & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
+ sc->io.base = PCI_PPBIOBASE(
+ pci_read_config(dev, PCIR_IOBASEH_1, 2), val);
+ sc->io.limit = PCI_PPBIOLIMIT(
+ pci_read_config(dev, PCIR_IOLIMITH_1, 2),
+ pci_read_config(dev, PCIR_IOLIMITL_1, 1));
+ max = 0xffffffff;
+ } else {
+ sc->io.base = PCI_PPBIOBASE(0, val);
+ sc->io.limit = PCI_PPBIOLIMIT(0,
+ pci_read_config(dev, PCIR_IOLIMITL_1, 1));
+ max = 0xffff;
+ }
+ pcib_alloc_window(sc, &sc->io, SYS_RES_IOPORT, 0, max);
+ }
+
+ /* Read the existing memory window. */
+ sc->mem.valid = 1;
+ sc->mem.reg = PCIR_MEMBASE_1;
+ sc->mem.step = 20;
+ sc->mem.mask = WIN_MEM;
+ sc->mem.name = "memory";
+ sc->mem.base = PCI_PPBMEMBASE(0,
+ pci_read_config(dev, PCIR_MEMBASE_1, 2));
+ sc->mem.limit = PCI_PPBMEMLIMIT(0,
+ pci_read_config(dev, PCIR_MEMLIMIT_1, 2));
+ pcib_alloc_window(sc, &sc->mem, SYS_RES_MEMORY, 0, 0xffffffff);
+
+ /* Determine if the prefetchable memory window is implemented. */
+ val = pci_read_config(dev, PCIR_PMBASEL_1, 2);
+ if (val == 0) {
+ /*
+ * If 'val' is zero, then only 32-bits of memory space
+ * are supported.
+ */
+ pci_write_config(dev, PCIR_PMBASEL_1, 0xffff, 2);
+ if (pci_read_config(dev, PCIR_PMBASEL_1, 2) != 0) {
+ sc->pmem.valid = 1;
+ pci_write_config(dev, PCIR_PMBASEL_1, 0, 2);
+ }
+ } else
+ sc->pmem.valid = 1;
+
+ /* Read the existing prefetchable memory window. */
+ if (sc->pmem.valid) {
+ sc->pmem.reg = PCIR_PMBASEL_1;
+ sc->pmem.step = 20;
+ sc->pmem.mask = WIN_PMEM;
+ sc->pmem.name = "prefetch";
+ if ((val & PCIM_BRPM_MASK) == PCIM_BRPM_64) {
+ sc->pmem.base = PCI_PPBMEMBASE(
+ pci_read_config(dev, PCIR_PMBASEH_1, 4), val);
+ sc->pmem.limit = PCI_PPBMEMLIMIT(
+ pci_read_config(dev, PCIR_PMLIMITH_1, 4),
+ pci_read_config(dev, PCIR_PMLIMITL_1, 2));
+ max = 0xffffffffffffffff;
+ } else {
+ sc->pmem.base = PCI_PPBMEMBASE(0, val);
+ sc->pmem.limit = PCI_PPBMEMLIMIT(0,
+ pci_read_config(dev, PCIR_PMLIMITL_1, 2));
+ max = 0xffffffff;
+ }
+ pcib_alloc_window(sc, &sc->pmem, SYS_RES_MEMORY,
+ RF_PREFETCHABLE, max);
+ }
+}
+
+#else
+
/*
* Is the prefetch window open (eg, can we allocate memory in it?)
*/
@@ -121,6 +365,7 @@ pcib_is_io_open(struct pcib_softc *sc)
{
return (sc->iobase > 0 && sc->iobase < sc->iolimit);
}
+#endif
/*
* Generic device interface
@@ -140,7 +385,9 @@ void
pcib_attach_common(device_t dev)
{
struct pcib_softc *sc;
+#ifndef NEW_PCIB
uint8_t iolow;
+#endif
struct sysctl_ctx_list *sctx;
struct sysctl_oid *soid;
@@ -173,6 +420,7 @@ pcib_attach_common(device_t dev)
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus",
CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number");
+#ifndef NEW_PCIB
/*
* Determine current I/O decode.
*/
@@ -217,6 +465,7 @@ pcib_attach_common(device_t dev)
sc->pmemlimit = PCI_PPBMEMLIMIT(0,
pci_read_config(dev, PCIR_PMLIMITL_1, 2));
}
+#endif
/*
* Quirk handling.
@@ -289,18 +538,35 @@ pcib_attach_common(device_t dev)
if ((pci_get_devid(dev) & 0xff00ffff) == 0x24008086 ||
pci_read_config(dev, PCIR_PROGIF, 1) == PCIP_BRIDGE_PCI_SUBTRACTIVE)
sc->flags |= PCIB_SUBTRACTIVE;
-
+
+#ifdef NEW_PCIB
+ pcib_probe_windows(sc);
+#endif
if (bootverbose) {
device_printf(dev, " domain %d\n", sc->domain);
device_printf(dev, " secondary bus %d\n", sc->secbus);
device_printf(dev, " subordinate bus %d\n", sc->subbus);
- device_printf(dev, " I/O decode 0x%x-0x%x\n", sc->iobase, sc->iolimit);
+#ifdef NEW_PCIB
+ if (pcib_is_window_open(&sc->io))
+ device_printf(dev, " I/O decode 0x%jx-0x%jx\n",
+ (uintmax_t)sc->io.base, (uintmax_t)sc->io.limit);
+ if (pcib_is_window_open(&sc->mem))
+ device_printf(dev, " memory decode 0x%jx-0x%jx\n",
+ (uintmax_t)sc->mem.base, (uintmax_t)sc->mem.limit);
+ if (pcib_is_window_open(&sc->pmem))
+ device_printf(dev, " prefetched decode 0x%jx-0x%jx\n",
+ (uintmax_t)sc->pmem.base, (uintmax_t)sc->pmem.limit);
+#else
+ if (pcib_is_io_open(sc))
+ device_printf(dev, " I/O decode 0x%x-0x%x\n",
+ sc->iobase, sc->iolimit);
if (pcib_is_nonprefetch_open(sc))
device_printf(dev, " memory decode 0x%jx-0x%jx\n",
(uintmax_t)sc->membase, (uintmax_t)sc->memlimit);
if (pcib_is_prefetch_open(sc))
device_printf(dev, " prefetched decode 0x%jx-0x%jx\n",
(uintmax_t)sc->pmembase, (uintmax_t)sc->pmemlimit);
+#endif
else
device_printf(dev, " no prefetched decode\n");
if (sc->flags & PCIB_SUBTRACTIVE)
@@ -320,6 +586,13 @@ pcib_attach_common(device_t dev)
* would be more widely routed than absolutely necessary. We could
* then do a walk of the tree later and fix it.
*/
+
+ /*
+ * Always enable busmastering on bridges so that transactions
+ * initiated on the secondary bus are passed through to the
+ * primary bus.
+ */
+ pci_enable_busmaster(dev);
}
int
@@ -371,6 +644,377 @@ pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
return(ENOENT);
}
+#ifdef NEW_PCIB
+static const char *
+pcib_child_name(device_t child)
+{
+ static char buf[64];
+
+ if (device_get_nameunit(child) != NULL)
+ return (device_get_nameunit(child));
+ snprintf(buf, sizeof(buf), "pci%d:%d:%d:%d", pci_get_domain(child),
+ pci_get_bus(child), pci_get_slot(child), pci_get_function(child));
+ return (buf);
+}
+
+/*
+ * Attempt to allocate a resource from the existing resources assigned
+ * to a window.
+ */
+static struct resource *
+pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w,
+ device_t child, int type, int *rid, u_long start, u_long end, u_long count,
+ u_int flags)
+{
+ struct resource *res;
+
+ if (!pcib_is_window_open(w))
+ return (NULL);
+
+ res = rman_reserve_resource(&w->rman, start, end, count,
+ flags & ~RF_ACTIVE, child);
+ if (res == NULL)
+ return (NULL);
+
+ if (bootverbose)
+ device_printf(sc->dev,
+ "allocated %s range (%#lx-%#lx) for rid %x of %s\n",
+ w->name, rman_get_start(res), rman_get_end(res), *rid,
+ pcib_child_name(child));
+ rman_set_rid(res, *rid);
+
+ /*
+ * If the resource should be active, pass that request up the
+ * tree. This assumes the parent drivers can handle
+ * activating sub-allocated resources.
+ */
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, res) != 0) {
+ rman_release_resource(res);
+ return (NULL);
+ }
+ }
+
+ return (res);
+}
+
+/*
+ * Attempt to grow a window to make room for a given resource request.
+ * The 'step' parameter is log_2 of the desired I/O window's alignment.
+ */
+static int
+pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ u_long align, start_free, end_free, front, back, wmask;
+ int error, rid;
+
+ /*
+ * Clamp the desired resource range to the maximum address
+ * this window supports. Reject impossible requests.
+ */
+ if (!w->valid)
+ return (EINVAL);
+ if (end > w->rman.rm_end)
+ end = w->rman.rm_end;
+ if (start + count - 1 > end || start + count < start)
+ return (EINVAL);
+ wmask = (1ul << w->step) - 1;
+
+ /*
+ * If there is no resource at all, just try to allocate enough
+ * aligned space for this resource.
+ */
+ if (w->res == NULL) {
+ if (RF_ALIGNMENT(flags) < w->step) {
+ flags &= ~RF_ALIGNMENT_MASK;
+ flags |= RF_ALIGNMENT_LOG2(w->step);
+ }
+ start &= ~wmask;
+ end |= wmask;
+ count = roundup2(count, 1ul << w->step);
+ rid = w->reg;
+ w->res = bus_alloc_resource(sc->dev, type, &rid, start, end,
+ count, flags & ~RF_ACTIVE);
+ if (w->res == NULL) {
+ if (bootverbose)
+ device_printf(sc->dev,
+ "failed to allocate initial %s window (%#lx-%#lx,%#lx)\n",
+ w->name, start, end, count);
+ return (ENXIO);
+ }
+ if (bootverbose)
+ device_printf(sc->dev,
+ "allocated initial %s window of %#lx-%#lx\n",
+ w->name, rman_get_start(w->res),
+ rman_get_end(w->res));
+ error = rman_manage_region(&w->rman, rman_get_start(w->res),
+ rman_get_end(w->res));
+ if (error) {
+ if (bootverbose)
+ device_printf(sc->dev,
+ "failed to add initial %s window to rman\n",
+ w->name);
+ bus_release_resource(sc->dev, type, w->reg, w->res);
+ w->res = NULL;
+ return (error);
+ }
+ pcib_activate_window(sc, type);
+ goto updatewin;
+ }
+
+ /*
+ * See if growing the window would help. Compute the minimum
+ * amount of address space needed on both the front and back
+ * ends of the existing window to satisfy the allocation.
+ *
+ * For each end, build a candidate region adjusting for the
+ * required alignment, etc. If there is a free region at the
+ * edge of the window, grow from the inner edge of the free
+ * region. Otherwise grow from the window boundary.
+ *
+ * XXX: Special case: if w->res is completely empty and the
+ * request size is larger than w->res, we should find the
+ * optimal aligned buffer containing w->res and allocate that.
+ */
+ if (bootverbose)
+ device_printf(sc->dev,
+ "attempting to grow %s window for (%#lx-%#lx,%#lx)\n",
+ w->name, start, end, count);
+ align = 1ul << RF_ALIGNMENT(flags);
+ if (start < rman_get_start(w->res)) {
+ if (rman_first_free_region(&w->rman, &start_free, &end_free) !=
+ 0 || start_free != rman_get_start(w->res))
+ end_free = rman_get_start(w->res);
+ if (end_free > end)
+ end_free = end + 1;
+
+ /* Move end_free down until it is properly aligned. */
+ end_free &= ~(align - 1);
+ end_free--;
+ front = end_free - (count - 1);
+
+ /*
+ * The resource would now be allocated at (front,
+ * end_free). Ensure that fits in the (start, end)
+ * bounds. end_free is checked above. If 'front' is
+ * ok, ensure it is properly aligned for this window.
+ * Also check for underflow.
+ */
+ if (front >= start && front <= end_free) {
+ if (bootverbose)
+ printf("\tfront candidate range: %#lx-%#lx\n",
+ front, end_free);
+ front &= ~wmask;
+ front = rman_get_start(w->res) - front;
+ } else
+ front = 0;
+ } else
+ front = 0;
+ if (end > rman_get_end(w->res)) {
+ if (rman_last_free_region(&w->rman, &start_free, &end_free) !=
+ 0 || end_free != rman_get_end(w->res))
+ start_free = rman_get_end(w->res) + 1;
+ if (start_free < start)
+ start_free = start;
+
+ /* Move start_free up until it is properly aligned. */
+ start_free = roundup2(start_free, align);
+ back = start_free + count - 1;
+
+ /*
+ * The resource would now be allocated at (start_free,
+ * back). Ensure that fits in the (start, end)
+ * bounds. start_free is checked above. If 'back' is
+ * ok, ensure it is properly aligned for this window.
+ * Also check for overflow.
+ */
+ if (back <= end && start_free <= back) {
+ if (bootverbose)
+ printf("\tback candidate range: %#lx-%#lx\n",
+ start_free, back);
+ back |= wmask;
+ back -= rman_get_end(w->res);
+ } else
+ back = 0;
+ } else
+ back = 0;
+
+ /*
+ * Try to allocate the smallest needed region first.
+ * If that fails, fall back to the other region.
+ */
+ error = ENOSPC;
+ while (front != 0 || back != 0) {
+ if (front != 0 && (front <= back || back == 0)) {
+ error = bus_adjust_resource(sc->dev, type, w->res,
+ rman_get_start(w->res) - front,
+ rman_get_end(w->res));
+ if (error == 0)
+ break;
+ front = 0;
+ } else {
+ error = bus_adjust_resource(sc->dev, type, w->res,
+ rman_get_start(w->res),
+ rman_get_end(w->res) + back);
+ if (error == 0)
+ break;
+ back = 0;
+ }
+ }
+
+ if (error)
+ return (error);
+ if (bootverbose)
+ device_printf(sc->dev, "grew %s window to %#lx-%#lx\n",
+ w->name, rman_get_start(w->res), rman_get_end(w->res));
+
+ /* Add the newly allocated region to the resource manager. */
+ if (w->base != rman_get_start(w->res)) {
+ KASSERT(w->limit == rman_get_end(w->res), ("both ends moved"));
+ error = rman_manage_region(&w->rman, rman_get_start(w->res),
+ w->base - 1);
+ } else {
+ KASSERT(w->limit != rman_get_end(w->res),
+ ("neither end moved"));
+ error = rman_manage_region(&w->rman, w->limit + 1,
+ rman_get_end(w->res));
+ }
+ if (error) {
+ if (bootverbose)
+ device_printf(sc->dev,
+ "failed to expand %s resource manager\n", w->name);
+ bus_adjust_resource(sc->dev, type, w->res, w->base, w->limit);
+ return (error);
+ }
+
+updatewin:
+ /* Save the new window. */
+ w->base = rman_get_start(w->res);
+ w->limit = rman_get_end(w->res);
+ KASSERT((w->base & wmask) == 0, ("start address is not aligned"));
+ KASSERT((w->limit & wmask) == wmask, ("end address is not aligned"));
+ pcib_write_windows(sc, w->mask);
+ return (0);
+}
+
+/*
+ * We have to trap resource allocation requests and ensure that the bridge
+ * is set up to, or capable of handling them.
+ */
+struct resource *
+pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct pcib_softc *sc;
+ struct resource *r;
+
+ sc = device_get_softc(dev);
+
+ /*
+ * VGA resources are decoded iff the VGA enable bit is set in
+ * the bridge control register. VGA resources do not fall into
+ * the resource windows and are passed up to the parent.
+ */
+ if ((type == SYS_RES_IOPORT && pci_is_vga_ioport_range(start, end)) ||
+ (type == SYS_RES_MEMORY && pci_is_vga_memory_range(start, end))) {
+ if (sc->bridgectl & PCIB_BCR_VGA_ENABLE)
+ return (bus_generic_alloc_resource(dev, child, type,
+ rid, start, end, count, flags));
+ else
+ return (NULL);
+ }
+
+ switch (type) {
+ case SYS_RES_IOPORT:
+ r = pcib_suballoc_resource(sc, &sc->io, child, type, rid, start,
+ end, count, flags);
+ if (r != NULL || (sc->flags & PCIB_SUBTRACTIVE) != 0)
+ break;
+ if (pcib_grow_window(sc, &sc->io, type, start, end, count,
+ flags) == 0)
+ r = pcib_suballoc_resource(sc, &sc->io, child, type,
+ rid, start, end, count, flags);
+ break;
+ case SYS_RES_MEMORY:
+ /*
+ * For prefetchable resources, prefer the prefetchable
+ * memory window, but fall back to the regular memory
+ * window if that fails. Try both windows before
+ * attempting to grow a window in case the firmware
+ * has used a range in the regular memory window to
+ * map a prefetchable BAR.
+ */
+ if (flags & RF_PREFETCHABLE) {
+ r = pcib_suballoc_resource(sc, &sc->pmem, child, type,
+ rid, start, end, count, flags);
+ if (r != NULL)
+ break;
+ }
+ r = pcib_suballoc_resource(sc, &sc->mem, child, type, rid,
+ start, end, count, flags);
+ if (r != NULL || (sc->flags & PCIB_SUBTRACTIVE) != 0)
+ break;
+ if (flags & RF_PREFETCHABLE) {
+ if (pcib_grow_window(sc, &sc->pmem, type, start, end,
+ count, flags) == 0) {
+ r = pcib_suballoc_resource(sc, &sc->pmem, child,
+ type, rid, start, end, count, flags);
+ if (r != NULL)
+ break;
+ }
+ }
+ if (pcib_grow_window(sc, &sc->mem, type, start, end, count,
+ flags & ~RF_PREFETCHABLE) == 0)
+ r = pcib_suballoc_resource(sc, &sc->mem, child, type,
+ rid, start, end, count, flags);
+ break;
+ default:
+ return (bus_generic_alloc_resource(dev, child, type, rid,
+ start, end, count, flags));
+ }
+
+ /*
+ * If attempts to suballocate from the window fail but this is a
+ * subtractive bridge, pass the request up the tree.
+ */
+ if (sc->flags & PCIB_SUBTRACTIVE && r == NULL)
+ return (bus_generic_alloc_resource(dev, child, type, rid,
+ start, end, count, flags));
+ return (r);
+}
+
+int
+pcib_adjust_resource(device_t bus, device_t child, int type, struct resource *r,
+ u_long start, u_long end)
+{
+ struct pcib_softc *sc;
+
+ sc = device_get_softc(bus);
+ if (pcib_is_resource_managed(sc, type, r))
+ return (rman_adjust_resource(r, start, end));
+ return (bus_generic_adjust_resource(bus, child, type, r, start, end));
+}
+
+int
+pcib_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct pcib_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (pcib_is_resource_managed(sc, type, r)) {
+ if (rman_get_flags(r) & RF_ACTIVE) {
+ error = bus_deactivate_resource(child, type, rid, r);
+ if (error)
+ return (error);
+ }
+ return (rman_release_resource(r));
+ }
+ return (bus_generic_release_resource(dev, child, type, rid, r));
+}
+#else
/*
* We have to trap resource allocation requests and ensure that the bridge
* is set up to, or capable of handling them.
@@ -526,6 +1170,7 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
count, flags));
}
+#endif
/*
* PCIB interface.
diff --git a/freebsd/sys/dev/pci/pci_private.h b/freebsd/sys/dev/pci/pci_private.h
index e45afb7a..b3ff50d5 100644
--- a/freebsd/sys/dev/pci/pci_private.h
+++ b/freebsd/sys/dev/pci/pci_private.h
@@ -38,11 +38,16 @@
*/
DECLARE_CLASS(pci_driver);
+struct pci_softc {
+ bus_dma_tag_t sc_dma_tag;
+};
+
void pci_add_children(device_t dev, int domain, int busno,
size_t dinfo_size);
void pci_add_child(device_t bus, struct pci_devinfo *dinfo);
void pci_add_resources(device_t bus, device_t dev, int force,
uint32_t prefetchmask);
+int pci_attach_common(device_t dev);
void pci_driver_added(device_t dev, driver_t *driver);
int pci_print_child(device_t dev, device_t child);
void pci_probe_nomatch(device_t dev, device_t child);
@@ -86,6 +91,8 @@ int pci_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r);
int pci_activate_resource(device_t dev, device_t child, int type,
int rid, struct resource *r);
+int pci_deactivate_resource(device_t dev, device_t child, int type,
+ int rid, struct resource *r);
void pci_delete_resource(device_t dev, device_t child,
int type, int rid);
struct resource_list *pci_get_resource_list (device_t dev, device_t child);
diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c
index e7306476..3df4d73b 100644
--- a/freebsd/sys/dev/pci/pci_user.c
+++ b/freebsd/sys/dev/pci/pci_user.c
@@ -313,8 +313,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
struct pci_io *io;
struct pci_bar_io *bio;
struct pci_match_conf *pattern_buf;
- struct resource_list_entry *rle;
- uint32_t value;
+ struct pci_map *pm;
size_t confsz, iolen, pbufsz;
int error, ionum, i, num_patterns;
#ifdef PRE7_COMPAT
@@ -689,54 +688,14 @@ getconfexit:
error = ENODEV;
break;
}
- dinfo = device_get_ivars(pcidev);
-
- /*
- * Look for a resource list entry matching the requested BAR.
- *
- * XXX: This will not find BARs that are not initialized, but
- * maybe that is ok?
- */
- rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY,
- bio->pbi_reg);
- if (rle == NULL)
- rle = resource_list_find(&dinfo->resources,
- SYS_RES_IOPORT, bio->pbi_reg);
- if (rle == NULL || rle->res == NULL) {
+ pm = pci_find_bar(pcidev, bio->pbi_reg);
+ if (pm == NULL) {
error = EINVAL;
break;
}
-
- /*
- * Ok, we have a resource for this BAR. Read the lower
- * 32 bits to get any flags.
- */
- value = pci_read_config(pcidev, bio->pbi_reg, 4);
- if (PCI_BAR_MEM(value)) {
- if (rle->type != SYS_RES_MEMORY) {
- error = EINVAL;
- break;
- }
- value &= ~PCIM_BAR_MEM_BASE;
- } else {
- if (rle->type != SYS_RES_IOPORT) {
- error = EINVAL;
- break;
- }
- value &= ~PCIM_BAR_IO_BASE;
- }
- bio->pbi_base = rman_get_start(rle->res) | value;
- bio->pbi_length = rman_get_size(rle->res);
-
- /*
- * Check the command register to determine if this BAR
- * is enabled.
- */
- value = pci_read_config(pcidev, PCIR_COMMAND, 2);
- if (rle->type == SYS_RES_MEMORY)
- bio->pbi_enabled = (value & PCIM_CMD_MEMEN) != 0;
- else
- bio->pbi_enabled = (value & PCIM_CMD_PORTEN) != 0;
+ bio->pbi_base = pm->pm_value;
+ bio->pbi_length = (pci_addr_t)1 << pm->pm_size;
+ bio->pbi_enabled = pci_bar_enabled(pcidev, pm);
error = 0;
break;
default:
diff --git a/freebsd/sys/dev/pci/pcib_private.h b/freebsd/sys/dev/pci/pcib_private.h
index 20f8da92..0fbc8df5 100644
--- a/freebsd/sys/dev/pci/pcib_private.h
+++ b/freebsd/sys/dev/pci/pcib_private.h
@@ -37,6 +37,25 @@
* Export portions of generic PCI:PCI bridge support so that it can be
* used by subclasses.
*/
+DECLARE_CLASS(pcib_driver);
+
+#ifdef NEW_PCIB
+#define WIN_IO 0x1
+#define WIN_MEM 0x2
+#define WIN_PMEM 0x4
+
+struct pcib_window {
+ pci_addr_t base; /* base address */
+ pci_addr_t limit; /* topmost address */
+ struct rman rman;
+ struct resource *res;
+ int reg; /* resource id from parent */
+ int valid;
+ int mask; /* WIN_* bitmask of this window */
+ int step; /* log_2 of window granularity */
+ const char *name;
+};
+#endif
/*
* Bridge-specific data.
@@ -52,12 +71,18 @@ struct pcib_softc
u_int pribus; /* primary bus number */
u_int secbus; /* secondary bus number */
u_int subbus; /* subordinate bus number */
+#ifdef NEW_PCIB
+ struct pcib_window io; /* I/O port window */
+ struct pcib_window mem; /* memory window */
+ struct pcib_window pmem; /* prefetchable memory window */
+#else
pci_addr_t pmembase; /* base address of prefetchable memory */
pci_addr_t pmemlimit; /* topmost address of prefetchable memory */
pci_addr_t membase; /* base address of memory window */
pci_addr_t memlimit; /* topmost address of memory window */
uint32_t iobase; /* base address of port window */
uint32_t iolimit; /* topmost address of port window */
+#endif
uint16_t secstat; /* secondary bus status register */
uint16_t bridgectl; /* bridge control register */
uint8_t seclat; /* secondary bus latency timer */
@@ -73,6 +98,12 @@ int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value);
struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags);
+#ifdef NEW_PCIB
+int pcib_adjust_resource(device_t bus, device_t child, int type,
+ struct resource *r, u_long start, u_long end);
+int pcib_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r);
+#endif
int pcib_maxslots(device_t dev);
uint32_t pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width);
void pcib_write_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, uint32_t val, int width);
diff --git a/freebsd/sys/dev/pci/pcireg.h b/freebsd/sys/dev/pci/pcireg.h
index 9b4ad87b..0127e776 100644
--- a/freebsd/sys/dev/pci/pcireg.h
+++ b/freebsd/sys/dev/pci/pcireg.h
@@ -64,6 +64,7 @@
#define PCIM_CMD_BACKTOBACK 0x0200
#define PCIM_CMD_INTxDIS 0x0400
#define PCIR_STATUS 0x06
+#define PCIM_STATUS_INTxSTATE 0x0008
#define PCIM_STATUS_CAPPRESENT 0x0010
#define PCIM_STATUS_66CAPABLE 0x0020
#define PCIM_STATUS_BACKTOBACK 0x0080
@@ -135,11 +136,22 @@
#define PCIZ_VC 0x0002 /* Virtual Channel */
#define PCIZ_SERNUM 0x0003 /* Device Serial Number */
#define PCIZ_PWRBDGT 0x0004 /* Power Budgeting */
+#define PCIZ_RCLINK_DCL 0x0005 /* Root Complex Link Declaration */
+#define PCIZ_RCLINK_CTL 0x0006 /* Root Complex Internal Link Control */
+#define PCIZ_RCEC_ASSOC 0x0007 /* Root Complex Event Collector Association */
+#define PCIZ_MFVC 0x0008 /* Multi-Function Virtual Channel */
+#define PCIZ_RCRB 0x000a /* RCRB Header */
#define PCIZ_VENDOR 0x000b /* Vendor Unique */
#define PCIZ_ACS 0x000d /* Access Control Services */
#define PCIZ_ARI 0x000e /* Alternative Routing-ID Interpretation */
#define PCIZ_ATS 0x000f /* Address Translation Services */
#define PCIZ_SRIOV 0x0010 /* Single Root IO Virtualization */
+#define PCIZ_MULTICAST 0x0012 /* Multicast */
+#define PCIZ_RESIZE_BAR 0x0015 /* Resizable BAR */
+#define PCIZ_DPA 0x0016 /* Dynamic Power Allocation */
+#define PCIZ_TPH_REQ 0x0017 /* TPH Requester */
+#define PCIZ_LTR 0x0018 /* Latency Tolerance Reporting */
+#define PCIZ_SEC_PCIE 0x0019 /* Secondary PCI Express */
/* config registers for header type 0 devices */
@@ -213,6 +225,7 @@
#define PCIM_BRPM_64 0x1
#define PCIM_BRPM_MASK 0xf
+#define PCIR_BIOS_1 0x38
#define PCIR_BRIDGECTL_1 0x3e
/* config registers for header type 2 (CardBus) devices */
@@ -263,6 +276,9 @@
#define PCIS_STORAGE_SATA 0x06
#define PCIP_STORAGE_SATA_AHCI_1_0 0x01
#define PCIS_STORAGE_SAS 0x07
+#define PCIS_STORAGE_NVM 0x08
+#define PCIP_STORAGE_NVM_NVMHCI_1_0 0x01
+#define PCIP_STORAGE_NVM_ENTERPRISE_NVMHCI_1_0 0x02
#define PCIS_STORAGE_OTHER 0x80
#define PCIC_NETWORK 0x02
@@ -367,6 +383,7 @@
#define PCIP_SERIALBUS_USB_UHCI 0x00
#define PCIP_SERIALBUS_USB_OHCI 0x10
#define PCIP_SERIALBUS_USB_EHCI 0x20
+#define PCIP_SERIALBUS_USB_XHCI 0x30
#define PCIP_SERIALBUS_USB_DEVICE 0xfe
#define PCIS_SERIALBUS_FC 0x04
#define PCIS_SERIALBUS_SMBUS 0x05
@@ -612,56 +629,258 @@
#define PCIR_SUBVENDCAP_ID 0x4
/* PCI Express definitions */
-#define PCIR_EXPRESS_FLAGS 0x2
-#define PCIM_EXP_FLAGS_VERSION 0x000F
-#define PCIM_EXP_FLAGS_TYPE 0x00F0
-#define PCIM_EXP_TYPE_ENDPOINT 0x0000
-#define PCIM_EXP_TYPE_LEGACY_ENDPOINT 0x0010
-#define PCIM_EXP_TYPE_ROOT_PORT 0x0040
-#define PCIM_EXP_TYPE_UPSTREAM_PORT 0x0050
-#define PCIM_EXP_TYPE_DOWNSTREAM_PORT 0x0060
-#define PCIM_EXP_TYPE_PCI_BRIDGE 0x0070
-#define PCIM_EXP_TYPE_PCIE_BRIDGE 0x0080
-#define PCIM_EXP_TYPE_ROOT_INT_EP 0x0090
-#define PCIM_EXP_TYPE_ROOT_EC 0x00a0
-#define PCIM_EXP_FLAGS_SLOT 0x0100
-#define PCIM_EXP_FLAGS_IRQ 0x3e00
-#define PCIR_EXPRESS_DEVICE_CAP 0x4
-#define PCIM_EXP_CAP_MAX_PAYLOAD 0x0007
-#define PCIR_EXPRESS_DEVICE_CTL 0x8
-#define PCIM_EXP_CTL_NFER_ENABLE 0x0002
-#define PCIM_EXP_CTL_FER_ENABLE 0x0004
-#define PCIM_EXP_CTL_URR_ENABLE 0x0008
-#define PCIM_EXP_CTL_RELAXED_ORD_ENABLE 0x0010
-#define PCIM_EXP_CTL_MAX_PAYLOAD 0x00e0
-#define PCIM_EXP_CTL_NOSNOOP_ENABLE 0x0800
-#define PCIM_EXP_CTL_MAX_READ_REQUEST 0x7000
-#define PCIR_EXPRESS_DEVICE_STA 0xa
-#define PCIM_EXP_STA_CORRECTABLE_ERROR 0x0001
-#define PCIM_EXP_STA_NON_FATAL_ERROR 0x0002
-#define PCIM_EXP_STA_FATAL_ERROR 0x0004
-#define PCIM_EXP_STA_UNSUPPORTED_REQ 0x0008
-#define PCIM_EXP_STA_AUX_POWER 0x0010
-#define PCIM_EXP_STA_TRANSACTION_PND 0x0020
-#define PCIR_EXPRESS_LINK_CAP 0xc
-#define PCIM_LINK_CAP_MAX_SPEED 0x0000000f
-#define PCIM_LINK_CAP_MAX_WIDTH 0x000003f0
-#define PCIM_LINK_CAP_ASPM 0x00000c00
-#define PCIM_LINK_CAP_L0S_EXIT 0x00007000
-#define PCIM_LINK_CAP_L1_EXIT 0x00038000
-#define PCIM_LINK_CAP_PORT 0xff000000
-#define PCIR_EXPRESS_LINK_CTL 0x10
-#define PCIR_EXPRESS_LINK_STA 0x12
-#define PCIM_LINK_STA_SPEED 0x000f
-#define PCIM_LINK_STA_WIDTH 0x03f0
-#define PCIM_LINK_STA_TRAINING_ERROR 0x0400
-#define PCIM_LINK_STA_TRAINING 0x0800
-#define PCIM_LINK_STA_SLOT_CLOCK 0x1000
-#define PCIR_EXPRESS_SLOT_CAP 0x14
-#define PCIR_EXPRESS_SLOT_CTL 0x18
-#define PCIR_EXPRESS_SLOT_STA 0x1a
-#define PCIR_EXPRESS_ROOT_CTL 0x1c
-#define PCIR_EXPRESS_ROOT_STA 0x20
+#define PCIER_FLAGS 0x2
+#define PCIEM_FLAGS_VERSION 0x000F
+#define PCIEM_FLAGS_TYPE 0x00F0
+#define PCIEM_TYPE_ENDPOINT 0x0000
+#define PCIEM_TYPE_LEGACY_ENDPOINT 0x0010
+#define PCIEM_TYPE_ROOT_PORT 0x0040
+#define PCIEM_TYPE_UPSTREAM_PORT 0x0050
+#define PCIEM_TYPE_DOWNSTREAM_PORT 0x0060
+#define PCIEM_TYPE_PCI_BRIDGE 0x0070
+#define PCIEM_TYPE_PCIE_BRIDGE 0x0080
+#define PCIEM_TYPE_ROOT_INT_EP 0x0090
+#define PCIEM_TYPE_ROOT_EC 0x00a0
+#define PCIEM_FLAGS_SLOT 0x0100
+#define PCIEM_FLAGS_IRQ 0x3e00
+#define PCIER_DEVICE_CAP 0x4
+#define PCIEM_CAP_MAX_PAYLOAD 0x00000007
+#define PCIEM_CAP_PHANTHOM_FUNCS 0x00000018
+#define PCIEM_CAP_EXT_TAG_FIELD 0x00000020
+#define PCIEM_CAP_L0S_LATENCY 0x000001c0
+#define PCIEM_CAP_L1_LATENCY 0x00000e00
+#define PCIEM_CAP_ROLE_ERR_RPT 0x00008000
+#define PCIEM_CAP_SLOT_PWR_LIM_VAL 0x03fc0000
+#define PCIEM_CAP_SLOT_PWR_LIM_SCALE 0x0c000000
+#define PCIEM_CAP_FLR 0x10000000
+#define PCIER_DEVICE_CTL 0x8
+#define PCIEM_CTL_COR_ENABLE 0x0001
+#define PCIEM_CTL_NFER_ENABLE 0x0002
+#define PCIEM_CTL_FER_ENABLE 0x0004
+#define PCIEM_CTL_URR_ENABLE 0x0008
+#define PCIEM_CTL_RELAXED_ORD_ENABLE 0x0010
+#define PCIEM_CTL_MAX_PAYLOAD 0x00e0
+#define PCIEM_CTL_EXT_TAG_FIELD 0x0100
+#define PCIEM_CTL_PHANTHOM_FUNCS 0x0200
+#define PCIEM_CTL_AUX_POWER_PM 0x0400
+#define PCIEM_CTL_NOSNOOP_ENABLE 0x0800
+#define PCIEM_CTL_MAX_READ_REQUEST 0x7000
+#define PCIEM_CTL_BRDG_CFG_RETRY 0x8000 /* PCI-E - PCI/PCI-X bridges */
+#define PCIEM_CTL_INITIATE_FLR 0x8000 /* FLR capable endpoints */
+#define PCIER_DEVICE_STA 0xa
+#define PCIEM_STA_CORRECTABLE_ERROR 0x0001
+#define PCIEM_STA_NON_FATAL_ERROR 0x0002
+#define PCIEM_STA_FATAL_ERROR 0x0004
+#define PCIEM_STA_UNSUPPORTED_REQ 0x0008
+#define PCIEM_STA_AUX_POWER 0x0010
+#define PCIEM_STA_TRANSACTION_PND 0x0020
+#define PCIER_LINK_CAP 0xc
+#define PCIEM_LINK_CAP_MAX_SPEED 0x0000000f
+#define PCIEM_LINK_CAP_MAX_WIDTH 0x000003f0
+#define PCIEM_LINK_CAP_ASPM 0x00000c00
+#define PCIEM_LINK_CAP_L0S_EXIT 0x00007000
+#define PCIEM_LINK_CAP_L1_EXIT 0x00038000
+#define PCIEM_LINK_CAP_CLOCK_PM 0x00040000
+#define PCIEM_LINK_CAP_SURPRISE_DOWN 0x00080000
+#define PCIEM_LINK_CAP_DL_ACTIVE 0x00100000
+#define PCIEM_LINK_CAP_LINK_BW_NOTIFY 0x00200000
+#define PCIEM_LINK_CAP_ASPM_COMPLIANCE 0x00400000
+#define PCIEM_LINK_CAP_PORT 0xff000000
+#define PCIER_LINK_CTL 0x10
+#define PCIEM_LINK_CTL_ASPMC_DIS 0x0000
+#define PCIEM_LINK_CTL_ASPMC_L0S 0x0001
+#define PCIEM_LINK_CTL_ASPMC_L1 0x0002
+#define PCIEM_LINK_CTL_ASPMC 0x0003
+#define PCIEM_LINK_CTL_RCB 0x0008
+#define PCIEM_LINK_CTL_LINK_DIS 0x0010
+#define PCIEM_LINK_CTL_RETRAIN_LINK 0x0020
+#define PCIEM_LINK_CTL_COMMON_CLOCK 0x0040
+#define PCIEM_LINK_CTL_EXTENDED_SYNC 0x0080
+#define PCIEM_LINK_CTL_ECPM 0x0100
+#define PCIEM_LINK_CTL_HAWD 0x0200
+#define PCIEM_LINK_CTL_LBMIE 0x0400
+#define PCIEM_LINK_CTL_LABIE 0x0800
+#define PCIER_LINK_STA 0x12
+#define PCIEM_LINK_STA_SPEED 0x000f
+#define PCIEM_LINK_STA_WIDTH 0x03f0
+#define PCIEM_LINK_STA_TRAINING_ERROR 0x0400
+#define PCIEM_LINK_STA_TRAINING 0x0800
+#define PCIEM_LINK_STA_SLOT_CLOCK 0x1000
+#define PCIEM_LINK_STA_DL_ACTIVE 0x2000
+#define PCIEM_LINK_STA_LINK_BW_MGMT 0x4000
+#define PCIEM_LINK_STA_LINK_AUTO_BW 0x8000
+#define PCIER_SLOT_CAP 0x14
+#define PCIEM_SLOT_CAP_APB 0x00000001
+#define PCIEM_SLOT_CAP_PCP 0x00000002
+#define PCIEM_SLOT_CAP_MRLSP 0x00000004
+#define PCIEM_SLOT_CAP_AIP 0x00000008
+#define PCIEM_SLOT_CAP_PIP 0x00000010
+#define PCIEM_SLOT_CAP_HPS 0x00000020
+#define PCIEM_SLOT_CAP_HPC 0x00000040
+#define PCIEM_SLOT_CAP_SPLV 0x00007f80
+#define PCIEM_SLOT_CAP_SPLS 0x00018000
+#define PCIEM_SLOT_CAP_EIP 0x00020000
+#define PCIEM_SLOT_CAP_NCCS 0x00040000
+#define PCIEM_SLOT_CAP_PSN 0xfff80000
+#define PCIER_SLOT_CTL 0x18
+#define PCIEM_SLOT_CTL_ABPE 0x0001
+#define PCIEM_SLOT_CTL_PFDE 0x0002
+#define PCIEM_SLOT_CTL_MRLSCE 0x0004
+#define PCIEM_SLOT_CTL_PDCE 0x0008
+#define PCIEM_SLOT_CTL_CCIE 0x0010
+#define PCIEM_SLOT_CTL_HPIE 0x0020
+#define PCIEM_SLOT_CTL_AIC 0x00c0
+#define PCIEM_SLOT_CTL_PIC 0x0300
+#define PCIEM_SLOT_CTL_PCC 0x0400
+#define PCIEM_SLOT_CTL_EIC 0x0800
+#define PCIEM_SLOT_CTL_DLLSCE 0x1000
+#define PCIER_SLOT_STA 0x1a
+#define PCIEM_SLOT_STA_ABP 0x0001
+#define PCIEM_SLOT_STA_PFD 0x0002
+#define PCIEM_SLOT_STA_MRLSC 0x0004
+#define PCIEM_SLOT_STA_PDC 0x0008
+#define PCIEM_SLOT_STA_CC 0x0010
+#define PCIEM_SLOT_STA_MRLSS 0x0020
+#define PCIEM_SLOT_STA_PDS 0x0040
+#define PCIEM_SLOT_STA_EIS 0x0080
+#define PCIEM_SLOT_STA_DLLSC 0x0100
+#define PCIER_ROOT_CTL 0x1c
+#define PCIER_ROOT_CAP 0x1e
+#define PCIER_ROOT_STA 0x20
+#define PCIER_DEVICE_CAP2 0x24
+#define PCIER_DEVICE_CTL2 0x28
+#define PCIEM_CTL2_COMP_TIMEOUT_VAL 0x000f
+#define PCIEM_CTL2_COMP_TIMEOUT_DIS 0x0010
+#define PCIEM_CTL2_ARI 0x0020
+#define PCIEM_CTL2_ATOMIC_REQ_ENABLE 0x0040
+#define PCIEM_CTL2_ATOMIC_EGR_BLOCK 0x0080
+#define PCIEM_CTL2_ID_ORDERED_REQ_EN 0x0100
+#define PCIEM_CTL2_ID_ORDERED_CMP_EN 0x0200
+#define PCIEM_CTL2_LTR_ENABLE 0x0400
+#define PCIEM_CTL2_OBFF 0x6000
+#define PCIEM_OBFF_DISABLE 0x0000
+#define PCIEM_OBFF_MSGA_ENABLE 0x2000
+#define PCIEM_OBFF_MSGB_ENABLE 0x4000
+#define PCIEM_OBFF_WAKE_ENABLE 0x6000
+#define PCIEM_CTL2_END2END_TLP 0x8000
+#define PCIER_DEVICE_STA2 0x2a
+#define PCIER_LINK_CAP2 0x2c
+#define PCIER_LINK_CTL2 0x30
+#define PCIER_LINK_STA2 0x32
+#define PCIER_SLOT_CAP2 0x34
+#define PCIER_SLOT_CTL2 0x38
+#define PCIER_SLOT_STA2 0x3a
+
+/* Old compatibility definitions for PCI Express registers */
+#define PCIR_EXPRESS_FLAGS PCIER_FLAGS
+#define PCIM_EXP_FLAGS_VERSION PCIEM_FLAGS_VERSION
+#define PCIM_EXP_FLAGS_TYPE PCIEM_FLAGS_TYPE
+#define PCIM_EXP_TYPE_ENDPOINT PCIEM_TYPE_ENDPOINT
+#define PCIM_EXP_TYPE_LEGACY_ENDPOINT PCIEM_TYPE_LEGACY_ENDPOINT
+#define PCIM_EXP_TYPE_ROOT_PORT PCIEM_TYPE_ROOT_PORT
+#define PCIM_EXP_TYPE_UPSTREAM_PORT PCIEM_TYPE_UPSTREAM_PORT
+#define PCIM_EXP_TYPE_DOWNSTREAM_PORT PCIEM_TYPE_DOWNSTREAM_PORT
+#define PCIM_EXP_TYPE_PCI_BRIDGE PCIEM_TYPE_PCI_BRIDGE
+#define PCIM_EXP_TYPE_PCIE_BRIDGE PCIEM_TYPE_PCIE_BRIDGE
+#define PCIM_EXP_TYPE_ROOT_INT_EP PCIEM_TYPE_ROOT_INT_EP
+#define PCIM_EXP_TYPE_ROOT_EC PCIEM_TYPE_ROOT_EC
+#define PCIM_EXP_FLAGS_SLOT PCIEM_FLAGS_SLOT
+#define PCIM_EXP_FLAGS_IRQ PCIEM_FLAGS_IRQ
+#define PCIR_EXPRESS_DEVICE_CAP PCIER_DEVICE_CAP
+#define PCIM_EXP_CAP_MAX_PAYLOAD PCIEM_CAP_MAX_PAYLOAD
+#define PCIM_EXP_CAP_PHANTHOM_FUNCS PCIEM_CAP_PHANTHOM_FUNCS
+#define PCIM_EXP_CAP_EXT_TAG_FIELD PCIEM_CAP_EXT_TAG_FIELD
+#define PCIM_EXP_CAP_L0S_LATENCY PCIEM_CAP_L0S_LATENCY
+#define PCIM_EXP_CAP_L1_LATENCY PCIEM_CAP_L1_LATENCY
+#define PCIM_EXP_CAP_ROLE_ERR_RPT PCIEM_CAP_ROLE_ERR_RPT
+#define PCIM_EXP_CAP_SLOT_PWR_LIM_VAL PCIEM_CAP_SLOT_PWR_LIM_VAL
+#define PCIM_EXP_CAP_SLOT_PWR_LIM_SCALE PCIEM_CAP_SLOT_PWR_LIM_SCALE
+#define PCIM_EXP_CAP_FLR PCIEM_CAP_FLR
+#define PCIR_EXPRESS_DEVICE_CTL PCIER_DEVICE_CTL
+#define PCIM_EXP_CTL_COR_ENABLE PCIEM_CTL_COR_ENABLE
+#define PCIM_EXP_CTL_NFER_ENABLE PCIEM_CTL_NFER_ENABLE
+#define PCIM_EXP_CTL_FER_ENABLE PCIEM_CTL_FER_ENABLE
+#define PCIM_EXP_CTL_URR_ENABLE PCIEM_CTL_URR_ENABLE
+#define PCIM_EXP_CTL_RELAXED_ORD_ENABLE PCIEM_CTL_RELAXED_ORD_ENABLE
+#define PCIM_EXP_CTL_MAX_PAYLOAD PCIEM_CTL_MAX_PAYLOAD
+#define PCIM_EXP_CTL_EXT_TAG_FIELD PCIEM_CTL_EXT_TAG_FIELD
+#define PCIM_EXP_CTL_PHANTHOM_FUNCS PCIEM_CTL_PHANTHOM_FUNCS
+#define PCIM_EXP_CTL_AUX_POWER_PM PCIEM_CTL_AUX_POWER_PM
+#define PCIM_EXP_CTL_NOSNOOP_ENABLE PCIEM_CTL_NOSNOOP_ENABLE
+#define PCIM_EXP_CTL_MAX_READ_REQUEST PCIEM_CTL_MAX_READ_REQUEST
+#define PCIM_EXP_CTL_BRDG_CFG_RETRY PCIEM_CTL_BRDG_CFG_RETRY
+#define PCIM_EXP_CTL_INITIATE_FLR PCIEM_CTL_INITIATE_FLR
+#define PCIR_EXPRESS_DEVICE_STA PCIER_DEVICE_STA
+#define PCIM_EXP_STA_CORRECTABLE_ERROR PCIEM_STA_CORRECTABLE_ERROR
+#define PCIM_EXP_STA_NON_FATAL_ERROR PCIEM_STA_NON_FATAL_ERROR
+#define PCIM_EXP_STA_FATAL_ERROR PCIEM_STA_FATAL_ERROR
+#define PCIM_EXP_STA_UNSUPPORTED_REQ PCIEM_STA_UNSUPPORTED_REQ
+#define PCIM_EXP_STA_AUX_POWER PCIEM_STA_AUX_POWER
+#define PCIM_EXP_STA_TRANSACTION_PND PCIEM_STA_TRANSACTION_PND
+#define PCIR_EXPRESS_LINK_CAP PCIER_LINK_CAP
+#define PCIM_LINK_CAP_MAX_SPEED PCIEM_LINK_CAP_MAX_SPEED
+#define PCIM_LINK_CAP_MAX_WIDTH PCIEM_LINK_CAP_MAX_WIDTH
+#define PCIM_LINK_CAP_ASPM PCIEM_LINK_CAP_ASPM
+#define PCIM_LINK_CAP_L0S_EXIT PCIEM_LINK_CAP_L0S_EXIT
+#define PCIM_LINK_CAP_L1_EXIT PCIEM_LINK_CAP_L1_EXIT
+#define PCIM_LINK_CAP_CLOCK_PM PCIEM_LINK_CAP_CLOCK_PM
+#define PCIM_LINK_CAP_SURPRISE_DOWN PCIEM_LINK_CAP_SURPRISE_DOWN
+#define PCIM_LINK_CAP_DL_ACTIVE PCIEM_LINK_CAP_DL_ACTIVE
+#define PCIM_LINK_CAP_LINK_BW_NOTIFY PCIEM_LINK_CAP_LINK_BW_NOTIFY
+#define PCIM_LINK_CAP_ASPM_COMPLIANCE PCIEM_LINK_CAP_ASPM_COMPLIANCE
+#define PCIM_LINK_CAP_PORT PCIEM_LINK_CAP_PORT
+#define PCIR_EXPRESS_LINK_CTL PCIER_LINK_CTL
+#define PCIM_EXP_LINK_CTL_ASPMC_DIS PCIEM_LINK_CTL_ASPMC_DIS
+#define PCIM_EXP_LINK_CTL_ASPMC_L0S PCIEM_LINK_CTL_ASPMC_L0S
+#define PCIM_EXP_LINK_CTL_ASPMC_L1 PCIEM_LINK_CTL_ASPMC_L1
+#define PCIM_EXP_LINK_CTL_ASPMC PCIEM_LINK_CTL_ASPMC
+#define PCIM_EXP_LINK_CTL_RCB PCIEM_LINK_CTL_RCB
+#define PCIM_EXP_LINK_CTL_LINK_DIS PCIEM_LINK_CTL_LINK_DIS
+#define PCIM_EXP_LINK_CTL_RETRAIN_LINK PCIEM_LINK_CTL_RETRAIN_LINK
+#define PCIM_EXP_LINK_CTL_COMMON_CLOCK PCIEM_LINK_CTL_COMMON_CLOCK
+#define PCIM_EXP_LINK_CTL_EXTENDED_SYNC PCIEM_LINK_CTL_EXTENDED_SYNC
+#define PCIM_EXP_LINK_CTL_ECPM PCIEM_LINK_CTL_ECPM
+#define PCIM_EXP_LINK_CTL_HAWD PCIEM_LINK_CTL_HAWD
+#define PCIM_EXP_LINK_CTL_LBMIE PCIEM_LINK_CTL_LBMIE
+#define PCIM_EXP_LINK_CTL_LABIE PCIEM_LINK_CTL_LABIE
+#define PCIR_EXPRESS_LINK_STA PCIER_LINK_STA
+#define PCIM_LINK_STA_SPEED PCIEM_LINK_STA_SPEED
+#define PCIM_LINK_STA_WIDTH PCIEM_LINK_STA_WIDTH
+#define PCIM_LINK_STA_TRAINING_ERROR PCIEM_LINK_STA_TRAINING_ERROR
+#define PCIM_LINK_STA_TRAINING PCIEM_LINK_STA_TRAINING
+#define PCIM_LINK_STA_SLOT_CLOCK PCIEM_LINK_STA_SLOT_CLOCK
+#define PCIM_LINK_STA_DL_ACTIVE PCIEM_LINK_STA_DL_ACTIVE
+#define PCIM_LINK_STA_LINK_BW_MGMT PCIEM_LINK_STA_LINK_BW_MGMT
+#define PCIM_LINK_STA_LINK_AUTO_BW PCIEM_LINK_STA_LINK_AUTO_BW
+#define PCIR_EXPRESS_SLOT_CAP PCIER_SLOT_CAP
+#define PCIR_EXPRESS_SLOT_CTL PCIER_SLOT_CTL
+#define PCIR_EXPRESS_SLOT_STA PCIER_SLOT_STA
+#define PCIR_EXPRESS_ROOT_CTL PCIER_ROOT_CTL
+#define PCIR_EXPRESS_ROOT_CAP PCIER_ROOT_CAP
+#define PCIR_EXPRESS_ROOT_STA PCIER_ROOT_STA
+#define PCIR_EXPRESS_DEVICE_CAP2 PCIER_DEVICE_CAP2
+#define PCIR_EXPRESS_DEVICE_CTL2 PCIER_DEVICE_CTL2
+#define PCIM_EXP_CTL2_COMP_TIMEOUT_VAL PCIEM_CTL2_COMP_TIMEOUT_VAL
+#define PCIM_EXP_CTL2_COMP_TIMEOUT_DIS PCIEM_CTL2_COMP_TIMEOUT_DIS
+#define PCIM_EXP_CTL2_ARI PCIEM_CTL2_ARI
+#define PCIM_EXP_CTL2_ATOMIC_REQ_ENABLE PCIEM_CTL2_ATOMIC_REQ_ENABLE
+#define PCIM_EXP_CTL2_ATOMIC_EGR_BLOCK PCIEM_CTL2_ATOMIC_EGR_BLOCK
+#define PCIM_EXP_CTL2_ID_ORDERED_REQ_EN PCIEM_CTL2_ID_ORDERED_REQ_EN
+#define PCIM_EXP_CTL2_ID_ORDERED_CMP_EN PCIEM_CTL2_ID_ORDERED_CMP_EN
+#define PCIM_EXP_CTL2_LTR_ENABLE PCIEM_CTL2_LTR_ENABLE
+#define PCIM_EXP_CTL2_OBFF PCIEM_CTL2_OBFF
+#define PCIM_EXP_OBFF_DISABLE PCIEM_OBFF_DISABLE
+#define PCIM_EXP_OBFF_MSGA_ENABLE PCIEM_OBFF_MSGA_ENABLE
+#define PCIM_EXP_OBFF_MSGB_ENABLE PCIEM_OBFF_MSGB_ENABLE
+#define PCIM_EXP_OBFF_WAKE_ENABLE PCIEM_OBFF_WAKE_ENABLE
+#define PCIM_EXP_CTL2_END2END_TLP PCIEM_CTL2_END2END_TLP
+#define PCIR_EXPRESS_DEVICE_STA2 PCIER_DEVICE_STA2
+#define PCIR_EXPRESS_LINK_CAP2 PCIER_LINK_CAP2
+#define PCIR_EXPRESS_LINK_CTL2 PCIER_LINK_CTL2
+#define PCIR_EXPRESS_LINK_STA2 PCIER_LINK_STA2
+#define PCIR_EXPRESS_SLOT_CAP2 PCIER_SLOT_CAP2
+#define PCIR_EXPRESS_SLOT_CTL2 PCIER_SLOT_CTL2
+#define PCIR_EXPRESS_SLOT_STA2 PCIER_SLOT_STA2
/* MSI-X definitions */
#define PCIR_MSIX_CTRL 0x2
@@ -692,6 +911,7 @@
#define PCIR_AER_UC_STATUS 0x04
#define PCIM_AER_UC_TRAINING_ERROR 0x00000001
#define PCIM_AER_UC_DL_PROTOCOL_ERROR 0x00000010
+#define PCIM_AER_UC_SURPRISE_LINK_DOWN 0x00000020
#define PCIM_AER_UC_POISONED_TLP 0x00001000
#define PCIM_AER_UC_FC_PROTOCOL_ERROR 0x00002000
#define PCIM_AER_UC_COMPLETION_TIMEOUT 0x00004000
@@ -702,6 +922,10 @@
#define PCIM_AER_UC_ECRC_ERROR 0x00080000
#define PCIM_AER_UC_UNSUPPORTED_REQUEST 0x00100000
#define PCIM_AER_UC_ACS_VIOLATION 0x00200000
+#define PCIM_AER_UC_INTERNAL_ERROR 0x00400000
+#define PCIM_AER_UC_MC_BLOCKED_TLP 0x00800000
+#define PCIM_AER_UC_ATOMIC_EGRESS_BLK 0x01000000
+#define PCIM_AER_UC_TLP_PREFIX_BLOCKED 0x02000000
#define PCIR_AER_UC_MASK 0x08 /* Shares bits with UC_STATUS */
#define PCIR_AER_UC_SEVERITY 0x0c /* Shares bits with UC_STATUS */
#define PCIR_AER_COR_STATUS 0x10
@@ -710,6 +934,9 @@
#define PCIM_AER_COR_BAD_DLLP 0x00000080
#define PCIM_AER_COR_REPLAY_ROLLOVER 0x00000100
#define PCIM_AER_COR_REPLAY_TIMEOUT 0x00001000
+#define PCIM_AER_COR_ADVISORY_NF_ERROR 0x00002000
+#define PCIM_AER_COR_INTERNAL_ERROR 0x00004000
+#define PCIM_AER_COR_HEADER_LOG_OVFLOW 0x00008000
#define PCIR_AER_COR_MASK 0x14 /* Shares bits with COR_STATUS */
#define PCIR_AER_CAP_CONTROL 0x18
#define PCIM_AER_FIRST_ERROR_PTR 0x0000001f
@@ -717,6 +944,9 @@
#define PCIM_AER_ECRC_GEN_ENABLE 0x00000040
#define PCIM_AER_ECRC_CHECK_CAPABLE 0x00000080
#define PCIM_AER_ECRC_CHECK_ENABLE 0x00000100
+#define PCIM_AER_MULT_HDR_CAPABLE 0x00000200
+#define PCIM_AER_MULT_HDR_ENABLE 0x00000400
+#define PCIM_AER_TLP_PREFIX_LOG_PRESENT 0x00000800
#define PCIR_AER_HEADER_LOG 0x1c
#define PCIR_AER_ROOTERR_CMD 0x2c /* Only for root complex ports */
#define PCIM_AER_ROOTERR_COR_ENABLE 0x00000001
@@ -733,6 +963,7 @@
#define PCIM_AER_ROOTERR_INT_MESSAGE 0xf8000000
#define PCIR_AER_COR_SOURCE_ID 0x34 /* Only for root complex ports */
#define PCIR_AER_ERR_SOURCE_ID 0x36 /* Only for root complex ports */
+#define PCIR_AER_TLP_PREFIX_LOG 0x38 /* Only for TLP prefix functions */
/* Virtual Channel definitions */
#define PCIR_VC_CAP1 0x04
diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h
index 8e2da638..63adb09d 100644
--- a/freebsd/sys/dev/pci/pcivar.h
+++ b/freebsd/sys/dev/pci/pcivar.h
@@ -46,7 +46,14 @@ struct pcicfg_pp {
uint8_t pp_pmcsr; /* config space address of PMCSR reg */
uint8_t pp_data; /* config space address of PCI power data reg */
};
-
+
+struct pci_map {
+ pci_addr_t pm_value; /* Raw BAR value */
+ pci_addr_t pm_size;
+ uint8_t pm_reg;
+ STAILQ_ENTRY(pci_map) pm_link;
+};
+
struct vpd_readonly {
char keyword[2];
char *value;
@@ -110,6 +117,7 @@ struct pcicfg_msix {
/* Interesting values for HyperTransport */
struct pcicfg_ht {
+ uint8_t ht_slave; /* Non-zero if device is an HT slave. */
uint8_t ht_msimap; /* Offset of MSI mapping cap registers. */
uint16_t ht_msictrl; /* MSI mapping control */
uint64_t ht_msiaddr; /* MSI mapping base address */
@@ -119,8 +127,7 @@ struct pcicfg_ht {
typedef struct pcicfg {
struct device *dev; /* device which owns this */
- uint32_t bar[PCI_MAXMAPS_0]; /* BARs */
- uint32_t bios; /* BIOS mapping */
+ STAILQ_HEAD(, pci_map) maps; /* BARs */
uint16_t subvendor; /* card vendor ID */
uint16_t subdevice; /* card device ID, assigned by card vendor */
@@ -403,9 +410,15 @@ pci_get_powerstate(device_t dev)
}
static __inline int
+pci_find_cap(device_t dev, int capability, int *capreg)
+{
+ return (PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg));
+}
+
+static __inline int
pci_find_extcap(device_t dev, int capability, int *capreg)
{
- return PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg);
+ return (PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg));
}
static __inline int
@@ -446,9 +459,7 @@ pci_msix_count(device_t dev)
device_t pci_find_bsf(uint8_t, uint8_t, uint8_t);
device_t pci_find_dbsf(uint32_t, uint8_t, uint8_t, uint8_t);
-#ifndef __rtems__
device_t pci_find_device(uint16_t, uint16_t);
-#endif /* __rtems__ */
/* Can be used by drivers to manage the MSI-X table. */
int pci_pending_msix(device_t dev, u_int index);
@@ -458,6 +469,8 @@ int pci_msi_device_blacklisted(device_t dev);
void pci_ht_map_msi(device_t dev, uint64_t addr);
int pci_get_max_read_req(device_t dev);
+void pci_restore_state(device_t dev);
+void pci_save_state(device_t dev);
int pci_set_max_read_req(device_t dev, int size);
#endif /* _SYS_BUS_H_ */
@@ -475,4 +488,7 @@ STAILQ_HEAD(devlist, pci_devinfo);
extern struct devlist pci_devq;
extern uint32_t pci_generation;
+struct pci_map *pci_find_bar(device_t dev, int reg);
+int pci_bar_enabled(device_t dev, struct pci_map *pm);
+
#endif /* _PCIVAR_H_ */
diff --git a/freebsd/sys/dev/re/if_re.c b/freebsd/sys/dev/re/if_re.c
index 2327aa1f..a290d73c 100644
--- a/freebsd/sys/dev/re/if_re.c
+++ b/freebsd/sys/dev/re/if_re.c
@@ -159,8 +159,12 @@ MODULE_DEPEND(re, miibus, 1, 1, 1);
#include <rtems/bsd/local/miibus_if.h>
/* Tunables. */
+static int intr_filter = 0;
+TUNABLE_INT("hw.re.intr_filter", &intr_filter);
static int msi_disable = 0;
TUNABLE_INT("hw.re.msi_disable", &msi_disable);
+static int msix_disable = 0;
+TUNABLE_INT("hw.re.msix_disable", &msix_disable);
static int prefer_iomap = 0;
TUNABLE_INT("hw.re.prefer_iomap", &prefer_iomap);
@@ -169,15 +173,17 @@ TUNABLE_INT("hw.re.prefer_iomap", &prefer_iomap);
/*
* Various supported device vendors/types and their names.
*/
-static struct rl_type re_devs[] = {
+static const struct rl_type re_devs[] = {
{ DLINK_VENDORID, DLINK_DEVICEID_528T, 0,
"D-Link DGE-528(T) Gigabit Ethernet Adapter" },
+ { DLINK_VENDORID, DLINK_DEVICEID_530T_REVC, 0,
+ "D-Link DGE-530(T) Gigabit Ethernet Adapter" },
{ RT_VENDORID, RT_DEVICEID_8139, 0,
"RealTek 8139C+ 10/100BaseTX" },
{ RT_VENDORID, RT_DEVICEID_8101E, 0,
- "RealTek 8101E/8102E/8102EL/8103E PCIe 10/100baseTX" },
+ "RealTek 810xE PCIe 10/100baseTX" },
{ RT_VENDORID, RT_DEVICEID_8168, 0,
- "RealTek 8168/8111 B/C/CP/D/DP/E PCIe Gigabit Ethernet" },
+ "RealTek 8168/8111 B/C/CP/D/DP/E/F PCIe Gigabit Ethernet" },
{ RT_VENDORID, RT_DEVICEID_8169, 0,
"RealTek 8169/8169S/8169SB(L)/8110S/8110SB(L) Gigabit Ethernet" },
{ RT_VENDORID, RT_DEVICEID_8169SC, 0,
@@ -190,40 +196,47 @@ static struct rl_type re_devs[] = {
"US Robotics 997902 (RTL8169S) Gigabit Ethernet" }
};
-static struct rl_hwrev re_hwrevs[] = {
- { RL_HWREV_8139, RL_8139, "" },
- { RL_HWREV_8139A, RL_8139, "A" },
- { RL_HWREV_8139AG, RL_8139, "A-G" },
- { RL_HWREV_8139B, RL_8139, "B" },
- { RL_HWREV_8130, RL_8139, "8130" },
- { RL_HWREV_8139C, RL_8139, "C" },
- { RL_HWREV_8139D, RL_8139, "8139D/8100B/8100C" },
- { RL_HWREV_8139CPLUS, RL_8139CPLUS, "C+"},
- { RL_HWREV_8168_SPIN1, RL_8169, "8168"},
- { RL_HWREV_8169, RL_8169, "8169"},
- { RL_HWREV_8169S, RL_8169, "8169S"},
- { RL_HWREV_8110S, RL_8169, "8110S"},
- { RL_HWREV_8169_8110SB, RL_8169, "8169SB/8110SB"},
- { RL_HWREV_8169_8110SC, RL_8169, "8169SC/8110SC"},
- { RL_HWREV_8169_8110SBL, RL_8169, "8169SBL/8110SBL"},
- { RL_HWREV_8169_8110SCE, RL_8169, "8169SC/8110SC"},
- { RL_HWREV_8100, RL_8139, "8100"},
- { RL_HWREV_8101, RL_8139, "8101"},
- { RL_HWREV_8100E, RL_8169, "8100E"},
- { RL_HWREV_8101E, RL_8169, "8101E"},
- { RL_HWREV_8102E, RL_8169, "8102E"},
- { RL_HWREV_8102EL, RL_8169, "8102EL"},
- { RL_HWREV_8102EL_SPIN1, RL_8169, "8102EL"},
- { RL_HWREV_8103E, RL_8169, "8103E"},
- { RL_HWREV_8168_SPIN2, RL_8169, "8168"},
- { RL_HWREV_8168_SPIN3, RL_8169, "8168"},
- { RL_HWREV_8168C, RL_8169, "8168C/8111C"},
- { RL_HWREV_8168C_SPIN2, RL_8169, "8168C/8111C"},
- { RL_HWREV_8168CP, RL_8169, "8168CP/8111CP"},
- { RL_HWREV_8168D, RL_8169, "8168D/8111D"},
- { RL_HWREV_8168DP, RL_8169, "8168DP/8111DP"},
- { RL_HWREV_8168E, RL_8169, "8168E/8111E"},
- { 0, 0, NULL }
+static const struct rl_hwrev re_hwrevs[] = {
+ { RL_HWREV_8139, RL_8139, "", RL_MTU },
+ { RL_HWREV_8139A, RL_8139, "A", RL_MTU },
+ { RL_HWREV_8139AG, RL_8139, "A-G", RL_MTU },
+ { RL_HWREV_8139B, RL_8139, "B", RL_MTU },
+ { RL_HWREV_8130, RL_8139, "8130", RL_MTU },
+ { RL_HWREV_8139C, RL_8139, "C", RL_MTU },
+ { RL_HWREV_8139D, RL_8139, "8139D/8100B/8100C", RL_MTU },
+ { RL_HWREV_8139CPLUS, RL_8139CPLUS, "C+", RL_MTU },
+ { RL_HWREV_8168B_SPIN1, RL_8169, "8168", RL_JUMBO_MTU },
+ { RL_HWREV_8169, RL_8169, "8169", RL_JUMBO_MTU },
+ { RL_HWREV_8169S, RL_8169, "8169S", RL_JUMBO_MTU },
+ { RL_HWREV_8110S, RL_8169, "8110S", RL_JUMBO_MTU },
+ { RL_HWREV_8169_8110SB, RL_8169, "8169SB/8110SB", RL_JUMBO_MTU },
+ { RL_HWREV_8169_8110SC, RL_8169, "8169SC/8110SC", RL_JUMBO_MTU },
+ { RL_HWREV_8169_8110SBL, RL_8169, "8169SBL/8110SBL", RL_JUMBO_MTU },
+ { RL_HWREV_8169_8110SCE, RL_8169, "8169SC/8110SC", RL_JUMBO_MTU },
+ { RL_HWREV_8100, RL_8139, "8100", RL_MTU },
+ { RL_HWREV_8101, RL_8139, "8101", RL_MTU },
+ { RL_HWREV_8100E, RL_8169, "8100E", RL_MTU },
+ { RL_HWREV_8101E, RL_8169, "8101E", RL_MTU },
+ { RL_HWREV_8102E, RL_8169, "8102E", RL_MTU },
+ { RL_HWREV_8102EL, RL_8169, "8102EL", RL_MTU },
+ { RL_HWREV_8102EL_SPIN1, RL_8169, "8102EL", RL_MTU },
+ { RL_HWREV_8103E, RL_8169, "8103E", RL_MTU },
+ { RL_HWREV_8401E, RL_8169, "8401E", RL_MTU },
+ { RL_HWREV_8402, RL_8169, "8402", RL_MTU },
+ { RL_HWREV_8105E, RL_8169, "8105E", RL_MTU },
+ { RL_HWREV_8105E_SPIN1, RL_8169, "8105E", RL_MTU },
+ { RL_HWREV_8168B_SPIN2, RL_8169, "8168", RL_JUMBO_MTU },
+ { RL_HWREV_8168B_SPIN3, RL_8169, "8168", RL_JUMBO_MTU },
+ { RL_HWREV_8168C, RL_8169, "8168C/8111C", RL_JUMBO_MTU_6K },
+ { RL_HWREV_8168C_SPIN2, RL_8169, "8168C/8111C", RL_JUMBO_MTU_6K },
+ { RL_HWREV_8168CP, RL_8169, "8168CP/8111CP", RL_JUMBO_MTU_6K },
+ { RL_HWREV_8168D, RL_8169, "8168D/8111D", RL_JUMBO_MTU_9K },
+ { RL_HWREV_8168DP, RL_8169, "8168DP/8111DP", RL_JUMBO_MTU_9K },
+ { RL_HWREV_8168E, RL_8169, "8168E/8111E", RL_JUMBO_MTU_9K},
+ { RL_HWREV_8168E_VL, RL_8169, "8168E/8111E-VL", RL_JUMBO_MTU_6K},
+ { RL_HWREV_8168F, RL_8169, "8168F/8111F", RL_JUMBO_MTU_9K},
+ { RL_HWREV_8411, RL_8169, "8411", RL_JUMBO_MTU_9K},
+ { 0, 0, NULL, 0 }
};
static int re_probe (device_t);
@@ -237,7 +250,9 @@ static int re_allocmem (device_t, struct rl_softc *);
static __inline void re_discard_rxbuf
(struct rl_softc *, int);
static int re_newbuf (struct rl_softc *, int);
+static int re_jumbo_newbuf (struct rl_softc *, int);
static int re_rx_list_init (struct rl_softc *);
+static int re_jrx_list_init (struct rl_softc *);
static int re_tx_list_init (struct rl_softc *);
#ifdef RE_FIXUP_RX
static __inline void re_fixup_rx
@@ -250,10 +265,11 @@ static int re_poll (struct ifnet *, enum poll_cmd, int);
static int re_poll_locked (struct ifnet *, enum poll_cmd, int);
#endif
static int re_intr (void *);
+static void re_intr_msi (void *);
static void re_tick (void *);
-static void re_tx_task (void *, int);
static void re_int_task (void *, int);
static void re_start (struct ifnet *);
+static void re_start_locked (struct ifnet *);
static int re_ioctl (struct ifnet *, u_long, caddr_t);
static void re_init (void *);
static void re_init_locked (struct rl_softc *);
@@ -275,10 +291,12 @@ static int re_miibus_readreg (device_t, int, int);
static int re_miibus_writereg (device_t, int, int, int);
static void re_miibus_statchg (device_t);
+static void re_set_jumbo (struct rl_softc *, int);
static void re_set_rxmode (struct rl_softc *);
static void re_reset (struct rl_softc *);
static void re_setwol (struct rl_softc *);
static void re_clrwol (struct rl_softc *);
+static void re_set_linkspeed (struct rl_softc *);
#ifdef RE_DIAG
static int re_diag (struct rl_softc *);
@@ -286,6 +304,8 @@ static int re_diag (struct rl_softc *);
static void re_add_sysctls (struct rl_softc *);
static int re_sysctl_stats (SYSCTL_HANDLER_ARGS);
+static int sysctl_int_range (SYSCTL_HANDLER_ARGS, int, int);
+static int sysctl_hw_re_int_mod (SYSCTL_HANDLER_ARGS);
static device_method_t re_methods[] = {
/* Device interface */
@@ -296,16 +316,12 @@ static device_method_t re_methods[] = {
DEVMETHOD(device_resume, re_resume),
DEVMETHOD(device_shutdown, re_shutdown),
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
-
/* MII interface */
DEVMETHOD(miibus_readreg, re_miibus_readreg),
DEVMETHOD(miibus_writereg, re_miibus_writereg),
DEVMETHOD(miibus_statchg, re_miibus_statchg),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t re_driver = {
@@ -700,7 +716,7 @@ re_reset(struct rl_softc *sc)
if ((sc->rl_flags & RL_FLAG_MACRESET) != 0)
CSR_WRITE_1(sc, 0x82, 1);
- if (sc->rl_hwrev == RL_HWREV_8169S)
+ if (sc->rl_hwrev->rl_rev == RL_HWREV_8169S)
re_gmii_writereg(sc->rl_dev, 1, 0x0b, 0);
}
@@ -855,7 +871,7 @@ re_diag(struct rl_softc *sc)
device_printf(sc->rl_dev, "expected TX data: %6D/%6D/0x%x\n",
dst, ":", src, ":", ETHERTYPE_IP);
device_printf(sc->rl_dev, "received RX data: %6D/%6D/0x%x\n",
- eh->ether_dhost, ":", eh->ether_shost, ":",
+ eh->ether_dhost, ":", eh->ether_shost, ":",
ntohs(eh->ether_type));
device_printf(sc->rl_dev, "You may have a defective 32-bit "
"NIC plugged into a 64-bit PCI slot.\n");
@@ -890,7 +906,7 @@ done:
static int
re_probe(device_t dev)
{
- struct rl_type *t;
+ const struct rl_type *t;
uint16_t devid, vendor;
uint16_t revid, sdevid;
int i;
@@ -992,6 +1008,17 @@ re_allocmem(device_t dev, struct rl_softc *sc)
* Allocate map for RX mbufs.
*/
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) {
+ error = bus_dma_tag_create(sc->rl_parent_tag, sizeof(uint64_t),
+ 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ MJUM9BYTES, 1, MJUM9BYTES, 0, NULL, NULL,
+ &sc->rl_ldata.rl_jrx_mtag);
+ if (error) {
+ device_printf(dev,
+ "could not allocate jumbo RX DMA tag\n");
+ return (error);
+ }
+ }
error = bus_dma_tag_create(sc->rl_parent_tag, sizeof(uint64_t), 0,
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
MCLBYTES, 1, MCLBYTES, 0, NULL, NULL, &sc->rl_ldata.rl_rx_mtag);
@@ -1083,6 +1110,24 @@ re_allocmem(device_t dev, struct rl_softc *sc)
/* Create DMA maps for RX buffers */
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) {
+ error = bus_dmamap_create(sc->rl_ldata.rl_jrx_mtag, 0,
+ &sc->rl_ldata.rl_jrx_sparemap);
+ if (error) {
+ device_printf(dev,
+ "could not create spare DMA map for jumbo RX\n");
+ return (error);
+ }
+ for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) {
+ error = bus_dmamap_create(sc->rl_ldata.rl_jrx_mtag, 0,
+ &sc->rl_ldata.rl_jrx_desc[i].rx_dmamap);
+ if (error) {
+ device_printf(dev,
+ "could not create DMA map for jumbo RX\n");
+ return (error);
+ }
+ }
+ }
error = bus_dmamap_create(sc->rl_ldata.rl_rx_mtag, 0,
&sc->rl_ldata.rl_rx_sparemap);
if (error) {
@@ -1141,11 +1186,12 @@ re_attach(device_t dev)
u_int16_t as[ETHER_ADDR_LEN / 2];
struct rl_softc *sc;
struct ifnet *ifp;
- struct rl_hwrev *hw_rev;
+ const struct rl_hwrev *hw_rev;
+ u_int32_t cap, ctl;
int hwrev;
u_int16_t devid, re_did = 0;
int error = 0, i, phy, rid;
- int msic, reg;
+ int msic, msixc, reg;
uint8_t cfg;
sc = device_get_softc(dev);
@@ -1195,23 +1241,53 @@ re_attach(device_t dev)
sc->rl_btag = rman_get_bustag(sc->rl_res);
sc->rl_bhandle = rman_get_bushandle(sc->rl_res);
- msic = 0;
+ msic = pci_msi_count(dev);
+ msixc = pci_msix_count(dev);
if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
sc->rl_flags |= RL_FLAG_PCIE;
- if (devid != RT_DEVICEID_8101E) {
- /* Set PCIe maximum read request size to 2048. */
- if (pci_get_max_read_req(dev) < 2048)
- pci_set_max_read_req(dev, 2048);
+ sc->rl_expcap = reg;
+ }
+ if (bootverbose) {
+ device_printf(dev, "MSI count : %d\n", msic);
+ device_printf(dev, "MSI-X count : %d\n", msixc);
+ }
+ if (msix_disable > 0)
+ msixc = 0;
+ if (msi_disable > 0)
+ msic = 0;
+ /* Prefer MSI-X to MSI. */
+ if (msixc > 0) {
+ msixc = 1;
+ rid = PCIR_BAR(4);
+ sc->rl_res_pba = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE);
+ if (sc->rl_res_pba == NULL) {
+ device_printf(sc->rl_dev,
+ "could not allocate MSI-X PBA resource\n");
+ }
+ if (sc->rl_res_pba != NULL &&
+ pci_alloc_msix(dev, &msixc) == 0) {
+ if (msixc == 1) {
+ device_printf(dev, "Using %d MSI-X message\n",
+ msixc);
+ sc->rl_flags |= RL_FLAG_MSIX;
+ } else
+ pci_release_msi(dev);
+ }
+ if ((sc->rl_flags & RL_FLAG_MSIX) == 0) {
+ if (sc->rl_res_pba != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, rid,
+ sc->rl_res_pba);
+ sc->rl_res_pba = NULL;
+ msixc = 0;
}
- msic = pci_msi_count(dev);
- if (bootverbose)
- device_printf(dev, "MSI count : %d\n", msic);
}
- if (msic > 0 && msi_disable == 0) {
+ /* Prefer MSI to INTx. */
+ if (msixc == 0 && msic > 0) {
msic = 1;
if (pci_alloc_msi(dev, &msic) == 0) {
if (msic == RL_MSI_MESSAGES) {
- device_printf(dev, "Using %d MSI messages\n",
+ device_printf(dev, "Using %d MSI message\n",
msic);
sc->rl_flags |= RL_FLAG_MSI;
/* Explicitly set MSI enable bit. */
@@ -1223,10 +1299,12 @@ re_attach(device_t dev)
} else
pci_release_msi(dev);
}
+ if ((sc->rl_flags & RL_FLAG_MSI) == 0)
+ msic = 0;
}
/* Allocate interrupt */
- if ((sc->rl_flags & RL_FLAG_MSI) == 0) {
+ if ((sc->rl_flags & (RL_FLAG_MSI | RL_FLAG_MSIX)) == 0) {
rid = 0;
sc->rl_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
@@ -1260,10 +1338,22 @@ re_attach(device_t dev)
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
}
- /* Reset the adapter. */
- RL_LOCK(sc);
- re_reset(sc);
- RL_UNLOCK(sc);
+ /* Disable ASPM L0S/L1. */
+ if (sc->rl_expcap != 0) {
+ cap = pci_read_config(dev, sc->rl_expcap +
+ PCIER_LINK_CAP, 2);
+ if ((cap & PCIEM_LINK_CAP_ASPM) != 0) {
+ ctl = pci_read_config(dev, sc->rl_expcap +
+ PCIER_LINK_CTL, 2);
+ if ((ctl & 0x0003) != 0) {
+ ctl &= ~0x0003;
+ pci_write_config(dev, sc->rl_expcap +
+ PCIER_LINK_CTL, ctl, 2);
+ device_printf(dev, "ASPM disabled\n");
+ }
+ } else
+ device_printf(dev, "no ASPM capability\n");
+ }
hw_rev = re_hwrevs;
hwrev = CSR_READ_4(sc, RL_TXCFG);
@@ -1282,7 +1372,7 @@ re_attach(device_t dev)
while (hw_rev->rl_desc != NULL) {
if (hw_rev->rl_rev == hwrev) {
sc->rl_type = hw_rev->rl_type;
- sc->rl_hwrev = hw_rev->rl_rev;
+ sc->rl_hwrev = hw_rev;
break;
}
hw_rev++;
@@ -1295,32 +1385,42 @@ re_attach(device_t dev)
switch (hw_rev->rl_rev) {
case RL_HWREV_8139CPLUS:
- sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_FASTETHER |
- RL_FLAG_AUTOPAD;
+ sc->rl_flags |= RL_FLAG_FASTETHER | RL_FLAG_AUTOPAD;
break;
case RL_HWREV_8100E:
case RL_HWREV_8101E:
- sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_PHYWAKE |
- RL_FLAG_FASTETHER;
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_FASTETHER;
break;
case RL_HWREV_8102E:
case RL_HWREV_8102EL:
case RL_HWREV_8102EL_SPIN1:
- sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_PHYWAKE |
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 |
+ RL_FLAG_MACSTAT | RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP |
+ RL_FLAG_AUTOPAD;
+ break;
+ case RL_HWREV_8103E:
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 |
+ RL_FLAG_MACSTAT | RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP |
+ RL_FLAG_AUTOPAD | RL_FLAG_MACSLEEP;
+ break;
+ case RL_HWREV_8401E:
+ case RL_HWREV_8105E:
+ case RL_HWREV_8105E_SPIN1:
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD;
break;
- case RL_HWREV_8103E:
- sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_PHYWAKE |
+ case RL_HWREV_8402:
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD |
- RL_FLAG_MACSLEEP;
+ RL_FLAG_CMDSTOP_WAIT_TXQ;
break;
- case RL_HWREV_8168_SPIN1:
- case RL_HWREV_8168_SPIN2:
+ case RL_HWREV_8168B_SPIN1:
+ case RL_HWREV_8168B_SPIN2:
sc->rl_flags |= RL_FLAG_WOLRXENB;
/* FALLTHROUGH */
- case RL_HWREV_8168_SPIN3:
+ case RL_HWREV_8168B_SPIN3:
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_MACSTAT;
break;
case RL_HWREV_8168C_SPIN2:
@@ -1331,27 +1431,34 @@ re_attach(device_t dev)
sc->rl_flags |= RL_FLAG_MACSLEEP;
/* FALLTHROUGH */
case RL_HWREV_8168CP:
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
+ RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
+ RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 | RL_FLAG_WOL_MANLINK;
+ break;
case RL_HWREV_8168D:
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
+ RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
+ RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 |
+ RL_FLAG_WOL_MANLINK;
+ break;
case RL_HWREV_8168DP:
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
- RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
- RL_FLAG_AUTOPAD;
- /*
- * These controllers support jumbo frame but it seems
- * that enabling it requires touching additional magic
- * registers. Depending on MAC revisions some
- * controllers need to disable checksum offload. So
- * disable jumbo frame until I have better idea what
- * it really requires to make it support.
- * RTL8168C/CP : supports up to 6KB jumbo frame.
- * RTL8111C/CP : supports up to 9KB jumbo frame.
- */
- sc->rl_flags |= RL_FLAG_NOJUMBO;
+ RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_AUTOPAD |
+ RL_FLAG_JUMBOV2 | RL_FLAG_WAIT_TXPOLL | RL_FLAG_WOL_MANLINK;
break;
case RL_HWREV_8168E:
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM |
RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT |
- RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_NOJUMBO;
+ RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 |
+ RL_FLAG_WOL_MANLINK;
+ break;
+ case RL_HWREV_8168E_VL:
+ case RL_HWREV_8168F:
+ case RL_HWREV_8411:
+ sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
+ RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
+ RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 |
+ RL_FLAG_CMDSTOP_WAIT_TXQ | RL_FLAG_WOL_MANLINK;
break;
case RL_HWREV_8169_8110SB:
case RL_HWREV_8169_8110SBL:
@@ -1368,14 +1475,35 @@ re_attach(device_t dev)
break;
}
+ if (sc->rl_hwrev->rl_rev == RL_HWREV_8139CPLUS) {
+ sc->rl_cfg0 = RL_8139_CFG0;
+ sc->rl_cfg1 = RL_8139_CFG1;
+ sc->rl_cfg2 = 0;
+ sc->rl_cfg3 = RL_8139_CFG3;
+ sc->rl_cfg4 = RL_8139_CFG4;
+ sc->rl_cfg5 = RL_8139_CFG5;
+ } else {
+ sc->rl_cfg0 = RL_CFG0;
+ sc->rl_cfg1 = RL_CFG1;
+ sc->rl_cfg2 = RL_CFG2;
+ sc->rl_cfg3 = RL_CFG3;
+ sc->rl_cfg4 = RL_CFG4;
+ sc->rl_cfg5 = RL_CFG5;
+ }
+
+ /* Reset the adapter. */
+ RL_LOCK(sc);
+ re_reset(sc);
+ RL_UNLOCK(sc);
+
/* Enable PME. */
CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE);
- cfg = CSR_READ_1(sc, RL_CFG1);
+ cfg = CSR_READ_1(sc, sc->rl_cfg1);
cfg |= RL_CFG1_PME;
- CSR_WRITE_1(sc, RL_CFG1, cfg);
- cfg = CSR_READ_1(sc, RL_CFG5);
+ CSR_WRITE_1(sc, sc->rl_cfg1, cfg);
+ cfg = CSR_READ_1(sc, sc->rl_cfg5);
cfg &= RL_CFG5_PME_STS;
- CSR_WRITE_1(sc, RL_CFG5, cfg);
+ CSR_WRITE_1(sc, sc->rl_cfg5, cfg);
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
if ((sc->rl_flags & RL_FLAG_PAR) != 0) {
@@ -1397,7 +1525,7 @@ re_attach(device_t dev)
re_read_eeprom(sc, (caddr_t)as, RL_EE_EADDR, 3);
for (i = 0; i < ETHER_ADDR_LEN / 2; i++)
as[i] = le16toh(as[i]);
- bcopy(as, eaddr, sizeof(eaddr));
+ bcopy(as, eaddr, ETHER_ADDR_LEN);
}
if (sc->rl_type == RL_8169) {
@@ -1437,50 +1565,51 @@ re_attach(device_t dev)
}
/* Take PHY out of power down mode. */
- if ((sc->rl_flags & RL_FLAG_PHYWAKE_PM) != 0)
+ if ((sc->rl_flags & RL_FLAG_PHYWAKE_PM) != 0) {
CSR_WRITE_1(sc, RL_PMCH, CSR_READ_1(sc, RL_PMCH) | 0x80);
+ if (hw_rev->rl_rev == RL_HWREV_8401E)
+ CSR_WRITE_1(sc, 0xD1, CSR_READ_1(sc, 0xD1) & ~0x08);
+ }
if ((sc->rl_flags & RL_FLAG_PHYWAKE) != 0) {
re_gmii_writereg(dev, 1, 0x1f, 0);
re_gmii_writereg(dev, 1, 0x0e, 0);
}
-#define RE_PHYAD_INTERNAL 0
-
- /* Do MII setup. */
- phy = RE_PHYAD_INTERNAL;
- if (sc->rl_type == RL_8169)
- phy = 1;
- error = mii_attach(dev, &sc->rl_miibus, ifp, re_ifmedia_upd,
- re_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, MIIF_DOPAUSE);
- if (error != 0) {
- device_printf(dev, "attaching PHYs failed\n");
- goto fail;
- }
-
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = re_ioctl;
ifp->if_start = re_start;
- ifp->if_hwassist = RE_CSUM_FEATURES;
- ifp->if_capabilities = IFCAP_HWCSUM;
+ /*
+ * RTL8168/8111C generates wrong IP checksummed frame if the
+ * packet has IP options so disable TX IP checksum offloading.
+ */
+ if (sc->rl_hwrev->rl_rev == RL_HWREV_8168C ||
+ sc->rl_hwrev->rl_rev == RL_HWREV_8168C_SPIN2)
+ ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+ else
+ ifp->if_hwassist = CSUM_IP | CSUM_TCP | CSUM_UDP;
+ ifp->if_hwassist |= CSUM_TSO;
+ ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_TSO4;
ifp->if_capenable = ifp->if_capabilities;
ifp->if_init = re_init;
IFQ_SET_MAXLEN(&ifp->if_snd, RL_IFQ_MAXLEN);
ifp->if_snd.ifq_drv_maxlen = RL_IFQ_MAXLEN;
IFQ_SET_READY(&ifp->if_snd);
- TASK_INIT(&sc->rl_txtask, 1, re_tx_task, ifp);
TASK_INIT(&sc->rl_inttask, 0, re_int_task, sc);
- /*
- * XXX
- * Still have no idea how to make TSO work on 8168C, 8168CP,
- * 8111C and 8111CP.
- */
- if ((sc->rl_flags & RL_FLAG_DESCV2) == 0) {
- ifp->if_hwassist |= CSUM_TSO;
- ifp->if_capabilities |= IFCAP_TSO4 | IFCAP_VLAN_HWTSO;
+#define RE_PHYAD_INTERNAL 0
+
+ /* Do MII setup. */
+ phy = RE_PHYAD_INTERNAL;
+ if (sc->rl_type == RL_8169)
+ phy = 1;
+ error = mii_attach(dev, &sc->rl_miibus, ifp, re_ifmedia_upd,
+ re_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, MIIF_DOPAUSE);
+ if (error != 0) {
+ device_printf(dev, "attaching PHYs failed\n");
+ goto fail;
}
/*
@@ -1496,10 +1625,11 @@ re_attach(device_t dev)
if (pci_find_extcap(sc->rl_dev, PCIY_PMG, &reg) == 0)
ifp->if_capabilities |= IFCAP_WOL;
ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_capenable &= ~(IFCAP_WOL_UCAST | IFCAP_WOL_MCAST);
/*
- * Don't enable TSO by default. Under certain
- * circumtances the controller generated corrupted
- * packets in TSO size.
+ * Don't enable TSO by default. It is known to generate
+ * corrupted TCP segments(bad TCP options) under certain
+ * circumtances.
*/
ifp->if_hwassist &= ~CSUM_TSO;
ifp->if_capenable &= ~(IFCAP_TSO4 | IFCAP_VLAN_HWTSO);
@@ -1531,19 +1661,19 @@ re_attach(device_t dev)
}
#endif
+#ifdef RE_TX_MODERATION
+ intr_filter = 1;
+#endif
/* Hook interrupt last to avoid having to lock softc */
- if ((sc->rl_flags & RL_FLAG_MSI) == 0)
+ if ((sc->rl_flags & (RL_FLAG_MSI | RL_FLAG_MSIX)) != 0 &&
+ intr_filter == 0) {
+ error = bus_setup_intr(dev, sc->rl_irq[0],
+ INTR_TYPE_NET | INTR_MPSAFE, NULL, re_intr_msi, sc,
+ &sc->rl_intrhand[0]);
+ } else {
error = bus_setup_intr(dev, sc->rl_irq[0],
INTR_TYPE_NET | INTR_MPSAFE, re_intr, NULL, sc,
&sc->rl_intrhand[0]);
- else {
- for (i = 0; i < RL_MSI_MESSAGES; i++) {
- error = bus_setup_intr(dev, sc->rl_irq[i],
- INTR_TYPE_NET | INTR_MPSAFE, re_intr, NULL, sc,
- &sc->rl_intrhand[i]);
- if (error != 0)
- break;
- }
}
if (error) {
device_printf(dev, "couldn't set up irq\n");
@@ -1590,7 +1720,6 @@ re_detach(device_t dev)
RL_UNLOCK(sc);
callout_drain(&sc->rl_stat_callout);
taskqueue_drain(taskqueue_fast, &sc->rl_inttask);
- taskqueue_drain(taskqueue_fast, &sc->rl_txtask);
/*
* Force off the IFF_UP flag here, in case someone
* still had a BPF descriptor attached to this
@@ -1615,30 +1744,25 @@ re_detach(device_t dev)
* stopped here.
*/
- for (i = 0; i < RL_MSI_MESSAGES; i++) {
- if (sc->rl_intrhand[i] != NULL) {
- bus_teardown_intr(dev, sc->rl_irq[i],
- sc->rl_intrhand[i]);
- sc->rl_intrhand[i] = NULL;
- }
+ if (sc->rl_intrhand[0] != NULL) {
+ bus_teardown_intr(dev, sc->rl_irq[0], sc->rl_intrhand[0]);
+ sc->rl_intrhand[0] = NULL;
}
if (ifp != NULL)
if_free(ifp);
- if ((sc->rl_flags & RL_FLAG_MSI) == 0) {
- if (sc->rl_irq[0] != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, 0,
- sc->rl_irq[0]);
- sc->rl_irq[0] = NULL;
- }
- } else {
- for (i = 0, rid = 1; i < RL_MSI_MESSAGES; i++, rid++) {
- if (sc->rl_irq[i] != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, rid,
- sc->rl_irq[i]);
- sc->rl_irq[i] = NULL;
- }
- }
+ if ((sc->rl_flags & (RL_FLAG_MSI | RL_FLAG_MSIX)) == 0)
+ rid = 0;
+ else
+ rid = 1;
+ if (sc->rl_irq[0] != NULL) {
+ bus_release_resource(dev, SYS_RES_IRQ, rid, sc->rl_irq[0]);
+ sc->rl_irq[0] = NULL;
+ }
+ if ((sc->rl_flags & (RL_FLAG_MSI | RL_FLAG_MSIX)) != 0)
pci_release_msi(dev);
+ if (sc->rl_res_pba) {
+ rid = PCIR_BAR(4);
+ bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->rl_res_pba);
}
if (sc->rl_res)
bus_release_resource(dev, sc->rl_res_type, sc->rl_res_id,
@@ -1673,21 +1797,35 @@ re_detach(device_t dev)
/* Destroy all the RX and TX buffer maps */
if (sc->rl_ldata.rl_tx_mtag) {
- for (i = 0; i < sc->rl_ldata.rl_tx_desc_cnt; i++)
- bus_dmamap_destroy(sc->rl_ldata.rl_tx_mtag,
- sc->rl_ldata.rl_tx_desc[i].tx_dmamap);
+ for (i = 0; i < sc->rl_ldata.rl_tx_desc_cnt; i++) {
+ if (sc->rl_ldata.rl_tx_desc[i].tx_dmamap)
+ bus_dmamap_destroy(sc->rl_ldata.rl_tx_mtag,
+ sc->rl_ldata.rl_tx_desc[i].tx_dmamap);
+ }
bus_dma_tag_destroy(sc->rl_ldata.rl_tx_mtag);
}
if (sc->rl_ldata.rl_rx_mtag) {
- for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++)
- bus_dmamap_destroy(sc->rl_ldata.rl_rx_mtag,
- sc->rl_ldata.rl_rx_desc[i].rx_dmamap);
+ for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) {
+ if (sc->rl_ldata.rl_rx_desc[i].rx_dmamap)
+ bus_dmamap_destroy(sc->rl_ldata.rl_rx_mtag,
+ sc->rl_ldata.rl_rx_desc[i].rx_dmamap);
+ }
if (sc->rl_ldata.rl_rx_sparemap)
bus_dmamap_destroy(sc->rl_ldata.rl_rx_mtag,
sc->rl_ldata.rl_rx_sparemap);
bus_dma_tag_destroy(sc->rl_ldata.rl_rx_mtag);
}
-
+ if (sc->rl_ldata.rl_jrx_mtag) {
+ for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) {
+ if (sc->rl_ldata.rl_jrx_desc[i].rx_dmamap)
+ bus_dmamap_destroy(sc->rl_ldata.rl_jrx_mtag,
+ sc->rl_ldata.rl_jrx_desc[i].rx_dmamap);
+ }
+ if (sc->rl_ldata.rl_jrx_sparemap)
+ bus_dmamap_destroy(sc->rl_ldata.rl_jrx_mtag,
+ sc->rl_ldata.rl_jrx_sparemap);
+ bus_dma_tag_destroy(sc->rl_ldata.rl_jrx_mtag);
+ }
/* Unload and free the stats buffer and map */
if (sc->rl_ldata.rl_stag) {
@@ -1715,7 +1853,11 @@ re_discard_rxbuf(struct rl_softc *sc, int idx)
struct rl_rxdesc *rxd;
uint32_t cmdstat;
- rxd = &sc->rl_ldata.rl_rx_desc[idx];
+ if (sc->rl_ifp->if_mtu > RL_MTU &&
+ (sc->rl_flags & RL_FLAG_JUMBOV2) != 0)
+ rxd = &sc->rl_ldata.rl_jrx_desc[idx];
+ else
+ rxd = &sc->rl_ldata.rl_rx_desc[idx];
desc = &sc->rl_ldata.rl_rx_list[idx];
desc->rl_vlanctl = 0;
cmdstat = rxd->rx_size;
@@ -1788,6 +1930,59 @@ re_newbuf(struct rl_softc *sc, int idx)
return (0);
}
+static int
+re_jumbo_newbuf(struct rl_softc *sc, int idx)
+{
+ struct mbuf *m;
+ struct rl_rxdesc *rxd;
+ bus_dma_segment_t segs[1];
+ bus_dmamap_t map;
+ struct rl_desc *desc;
+ uint32_t cmdstat;
+ int error, nsegs;
+
+ m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
+ if (m == NULL)
+ return (ENOBUFS);
+ m->m_len = m->m_pkthdr.len = MJUM9BYTES;
+#ifdef RE_FIXUP_RX
+ m_adj(m, RE_ETHER_ALIGN);
+#endif
+ error = bus_dmamap_load_mbuf_sg(sc->rl_ldata.rl_jrx_mtag,
+ sc->rl_ldata.rl_jrx_sparemap, m, segs, &nsegs, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ KASSERT(nsegs == 1, ("%s: %d segment returned!", __func__, nsegs));
+
+ rxd = &sc->rl_ldata.rl_jrx_desc[idx];
+ if (rxd->rx_m != NULL) {
+ bus_dmamap_sync(sc->rl_ldata.rl_jrx_mtag, rxd->rx_dmamap,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->rl_ldata.rl_jrx_mtag, rxd->rx_dmamap);
+ }
+
+ rxd->rx_m = m;
+ map = rxd->rx_dmamap;
+ rxd->rx_dmamap = sc->rl_ldata.rl_jrx_sparemap;
+ rxd->rx_size = segs[0].ds_len;
+ sc->rl_ldata.rl_jrx_sparemap = map;
+ bus_dmamap_sync(sc->rl_ldata.rl_jrx_mtag, rxd->rx_dmamap,
+ BUS_DMASYNC_PREREAD);
+
+ desc = &sc->rl_ldata.rl_rx_list[idx];
+ desc->rl_vlanctl = 0;
+ desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(segs[0].ds_addr));
+ desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(segs[0].ds_addr));
+ cmdstat = segs[0].ds_len;
+ if (idx == sc->rl_ldata.rl_rx_desc_cnt - 1)
+ cmdstat |= RL_RDESC_CMD_EOR;
+ desc->rl_cmdstat = htole32(cmdstat | RL_RDESC_CMD_OWN);
+
+ return (0);
+}
+
#ifdef RE_FIXUP_RX
static __inline void
re_fixup_rx(struct mbuf *m)
@@ -1853,6 +2048,31 @@ re_rx_list_init(struct rl_softc *sc)
sc->rl_ldata.rl_rx_prodidx = 0;
sc->rl_head = sc->rl_tail = NULL;
+ sc->rl_int_rx_act = 0;
+
+ return (0);
+}
+
+static int
+re_jrx_list_init(struct rl_softc *sc)
+{
+ int error, i;
+
+ bzero(sc->rl_ldata.rl_rx_list,
+ sc->rl_ldata.rl_rx_desc_cnt * sizeof(struct rl_desc));
+ for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) {
+ sc->rl_ldata.rl_jrx_desc[i].rx_m = NULL;
+ if ((error = re_jumbo_newbuf(sc, i)) != 0)
+ return (error);
+ }
+
+ bus_dmamap_sync(sc->rl_ldata.rl_rx_list_tag,
+ sc->rl_ldata.rl_rx_list_map,
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+
+ sc->rl_ldata.rl_rx_prodidx = 0;
+ sc->rl_head = sc->rl_tail = NULL;
+ sc->rl_int_rx_act = 0;
return (0);
}
@@ -1867,14 +2087,18 @@ re_rxeof(struct rl_softc *sc, int *rx_npktsp)
{
struct mbuf *m;
struct ifnet *ifp;
- int i, total_len;
+ int i, rxerr, total_len;
struct rl_desc *cur_rx;
u_int32_t rxstat, rxvlan;
- int maxpkt = 16, rx_npkts = 0;
+ int jumbo, maxpkt = 16, rx_npkts = 0;
RL_LOCK_ASSERT(sc);
ifp = sc->rl_ifp;
+ if (ifp->if_mtu > RL_MTU && (sc->rl_flags & RL_FLAG_JUMBOV2) != 0)
+ jumbo = 1;
+ else
+ jumbo = 0;
/* Invalidate the descriptor memory */
@@ -1892,9 +2116,21 @@ re_rxeof(struct rl_softc *sc, int *rx_npktsp)
break;
total_len = rxstat & sc->rl_rxlenmask;
rxvlan = le32toh(cur_rx->rl_vlanctl);
- m = sc->rl_ldata.rl_rx_desc[i].rx_m;
+ if (jumbo != 0)
+ m = sc->rl_ldata.rl_jrx_desc[i].rx_m;
+ else
+ m = sc->rl_ldata.rl_rx_desc[i].rx_m;
- if (!(rxstat & RL_RDESC_STAT_EOF)) {
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0 &&
+ (rxstat & (RL_RDESC_STAT_SOF | RL_RDESC_STAT_EOF)) !=
+ (RL_RDESC_STAT_SOF | RL_RDESC_STAT_EOF)) {
+ /*
+ * RTL8168C or later controllers do not
+ * support multi-fragment packet.
+ */
+ re_discard_rxbuf(sc, i);
+ continue;
+ } else if ((rxstat & RL_RDESC_STAT_EOF) == 0) {
if (re_newbuf(sc, i) != 0) {
/*
* If this is part of a multi-fragment packet,
@@ -1941,27 +2177,36 @@ re_rxeof(struct rl_softc *sc, int *rx_npktsp)
* if total_len > 2^13-1, both _RXERRSUM and _GIANT will be
* set, but if CRC is clear, it will still be a valid frame.
*/
- if (rxstat & RL_RDESC_STAT_RXERRSUM && !(total_len > 8191 &&
- (rxstat & RL_RDESC_STAT_ERRS) == RL_RDESC_STAT_GIANT)) {
- ifp->if_ierrors++;
- /*
- * If this is part of a multi-fragment packet,
- * discard all the pieces.
- */
- if (sc->rl_head != NULL) {
- m_freem(sc->rl_head);
- sc->rl_head = sc->rl_tail = NULL;
+ if ((rxstat & RL_RDESC_STAT_RXERRSUM) != 0) {
+ rxerr = 1;
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) == 0 &&
+ total_len > 8191 &&
+ (rxstat & RL_RDESC_STAT_ERRS) == RL_RDESC_STAT_GIANT)
+ rxerr = 0;
+ if (rxerr != 0) {
+ ifp->if_ierrors++;
+ /*
+ * If this is part of a multi-fragment packet,
+ * discard all the pieces.
+ */
+ if (sc->rl_head != NULL) {
+ m_freem(sc->rl_head);
+ sc->rl_head = sc->rl_tail = NULL;
+ }
+ re_discard_rxbuf(sc, i);
+ continue;
}
- re_discard_rxbuf(sc, i);
- continue;
}
/*
* If allocating a replacement mbuf fails,
* reload the current one.
*/
-
- if (re_newbuf(sc, i) != 0) {
+ if (jumbo != 0)
+ rxerr = re_jumbo_newbuf(sc, i);
+ else
+ rxerr = re_newbuf(sc, i);
+ if (rxerr != 0) {
ifp->if_iqdrops++;
if (sc->rl_head != NULL) {
m_freem(sc->rl_head);
@@ -1972,9 +2217,13 @@ re_rxeof(struct rl_softc *sc, int *rx_npktsp)
}
if (sc->rl_head != NULL) {
- m->m_len = total_len % RE_RX_DESC_BUFLEN;
- if (m->m_len == 0)
- m->m_len = RE_RX_DESC_BUFLEN;
+ if (jumbo != 0)
+ m->m_len = total_len;
+ else {
+ m->m_len = total_len % RE_RX_DESC_BUFLEN;
+ if (m->m_len == 0)
+ m->m_len = RE_RX_DESC_BUFLEN;
+ }
/*
* Special case: if there's 4 bytes or less
* in this buffer, the mbuf can be discarded:
@@ -2194,7 +2443,7 @@ re_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
re_txeof(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask);
+ re_start_locked(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
u_int16_t status;
@@ -2297,7 +2546,7 @@ re_int_task(void *arg, int npending)
}
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask);
+ re_start_locked(ifp);
RL_UNLOCK(sc);
@@ -2309,6 +2558,87 @@ re_int_task(void *arg, int npending)
CSR_WRITE_2(sc, RL_IMR, RL_INTRS_CPLUS);
}
+static void
+re_intr_msi(void *xsc)
+{
+ struct rl_softc *sc;
+ struct ifnet *ifp;
+ uint16_t intrs, status;
+
+ sc = xsc;
+ RL_LOCK(sc);
+
+ ifp = sc->rl_ifp;
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING) {
+ RL_UNLOCK(sc);
+ return;
+ }
+#endif
+ /* Disable interrupts. */
+ CSR_WRITE_2(sc, RL_IMR, 0);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ RL_UNLOCK(sc);
+ return;
+ }
+
+ intrs = RL_INTRS_CPLUS;
+ status = CSR_READ_2(sc, RL_ISR);
+ CSR_WRITE_2(sc, RL_ISR, status);
+ if (sc->rl_int_rx_act > 0) {
+ intrs &= ~(RL_ISR_RX_OK | RL_ISR_RX_ERR | RL_ISR_FIFO_OFLOW |
+ RL_ISR_RX_OVERRUN);
+ status &= ~(RL_ISR_RX_OK | RL_ISR_RX_ERR | RL_ISR_FIFO_OFLOW |
+ RL_ISR_RX_OVERRUN);
+ }
+
+ if (status & (RL_ISR_TIMEOUT_EXPIRED | RL_ISR_RX_OK | RL_ISR_RX_ERR |
+ RL_ISR_FIFO_OFLOW | RL_ISR_RX_OVERRUN)) {
+ re_rxeof(sc, NULL);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ if (sc->rl_int_rx_mod != 0 &&
+ (status & (RL_ISR_RX_OK | RL_ISR_RX_ERR |
+ RL_ISR_FIFO_OFLOW | RL_ISR_RX_OVERRUN)) != 0) {
+ /* Rearm one-shot timer. */
+ CSR_WRITE_4(sc, RL_TIMERCNT, 1);
+ intrs &= ~(RL_ISR_RX_OK | RL_ISR_RX_ERR |
+ RL_ISR_FIFO_OFLOW | RL_ISR_RX_OVERRUN);
+ sc->rl_int_rx_act = 1;
+ } else {
+ intrs |= RL_ISR_RX_OK | RL_ISR_RX_ERR |
+ RL_ISR_FIFO_OFLOW | RL_ISR_RX_OVERRUN;
+ sc->rl_int_rx_act = 0;
+ }
+ }
+ }
+
+ /*
+ * Some chips will ignore a second TX request issued
+ * while an existing transmission is in progress. If
+ * the transmitter goes idle but there are still
+ * packets waiting to be sent, we need to restart the
+ * channel here to flush them out. This only seems to
+ * be required with the PCIe devices.
+ */
+ if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) &&
+ (sc->rl_flags & RL_FLAG_PCIE))
+ CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
+ if (status & (RL_ISR_TX_OK | RL_ISR_TX_ERR | RL_ISR_TX_DESC_UNAVAIL))
+ re_txeof(sc);
+
+ if (status & RL_ISR_SYSTEM_ERR) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ re_init_locked(sc);
+ }
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ re_start_locked(ifp);
+ CSR_WRITE_2(sc, RL_IMR, intrs);
+ }
+ RL_UNLOCK(sc);
+}
+
static int
re_encap(struct rl_softc *sc, struct mbuf **m_head)
{
@@ -2415,11 +2745,17 @@ re_encap(struct rl_softc *sc, struct mbuf **m_head)
*/
vlanctl = 0;
csum_flags = 0;
- if (((*m_head)->m_pkthdr.csum_flags & CSUM_TSO) != 0)
- csum_flags = RL_TDESC_CMD_LGSEND |
- ((uint32_t)(*m_head)->m_pkthdr.tso_segsz <<
- RL_TDESC_CMD_MSSVAL_SHIFT);
- else {
+ if (((*m_head)->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
+ if ((sc->rl_flags & RL_FLAG_DESCV2) != 0) {
+ csum_flags |= RL_TDESC_CMD_LGSEND;
+ vlanctl |= ((uint32_t)(*m_head)->m_pkthdr.tso_segsz <<
+ RL_TDESC_CMD_MSSVALV2_SHIFT);
+ } else {
+ csum_flags |= RL_TDESC_CMD_LGSEND |
+ ((uint32_t)(*m_head)->m_pkthdr.tso_segsz <<
+ RL_TDESC_CMD_MSSVAL_SHIFT);
+ }
+ } else {
/*
* Unconditionally enable IP checksum if TCP or UDP
* checksum is required. Otherwise, TCP/UDP checksum
@@ -2496,19 +2832,21 @@ re_encap(struct rl_softc *sc, struct mbuf **m_head)
}
static void
-re_tx_task(void *arg, int npending)
+re_start(struct ifnet *ifp)
{
- struct ifnet *ifp;
+ struct rl_softc *sc;
- ifp = arg;
- re_start(ifp);
+ sc = ifp->if_softc;
+ RL_LOCK(sc);
+ re_start_locked(ifp);
+ RL_UNLOCK(sc);
}
/*
* Main transmit routine for C+ and gigE NICs.
*/
static void
-re_start(struct ifnet *ifp)
+re_start_locked(struct ifnet *ifp)
{
struct rl_softc *sc;
struct mbuf *m_head;
@@ -2516,13 +2854,9 @@ re_start(struct ifnet *ifp)
sc = ifp->if_softc;
- RL_LOCK(sc);
-
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING || (sc->rl_flags & RL_FLAG_LINK) == 0) {
- RL_UNLOCK(sc);
+ IFF_DRV_RUNNING || (sc->rl_flags & RL_FLAG_LINK) == 0)
return;
- }
for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
sc->rl_ldata.rl_tx_free > 1;) {
@@ -2552,7 +2886,6 @@ re_start(struct ifnet *ifp)
if (sc->rl_ldata.rl_tx_free != sc->rl_ldata.rl_tx_desc_cnt)
CSR_WRITE_4(sc, RL_TIMERCNT, 1);
#endif
- RL_UNLOCK(sc);
return;
}
@@ -2580,8 +2913,59 @@ re_start(struct ifnet *ifp)
* Set a timeout in case the chip goes out to lunch.
*/
sc->rl_watchdog_timer = 5;
+}
- RL_UNLOCK(sc);
+static void
+re_set_jumbo(struct rl_softc *sc, int jumbo)
+{
+
+ if (sc->rl_hwrev->rl_rev == RL_HWREV_8168E_VL) {
+ pci_set_max_read_req(sc->rl_dev, 4096);
+ return;
+ }
+
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG);
+ if (jumbo != 0) {
+ CSR_WRITE_1(sc, sc->rl_cfg3, CSR_READ_1(sc, sc->rl_cfg3) |
+ RL_CFG3_JUMBO_EN0);
+ switch (sc->rl_hwrev->rl_rev) {
+ case RL_HWREV_8168DP:
+ break;
+ case RL_HWREV_8168E:
+ CSR_WRITE_1(sc, sc->rl_cfg4,
+ CSR_READ_1(sc, sc->rl_cfg4) | 0x01);
+ break;
+ default:
+ CSR_WRITE_1(sc, sc->rl_cfg4,
+ CSR_READ_1(sc, sc->rl_cfg4) | RL_CFG4_JUMBO_EN1);
+ }
+ } else {
+ CSR_WRITE_1(sc, sc->rl_cfg3, CSR_READ_1(sc, sc->rl_cfg3) &
+ ~RL_CFG3_JUMBO_EN0);
+ switch (sc->rl_hwrev->rl_rev) {
+ case RL_HWREV_8168DP:
+ break;
+ case RL_HWREV_8168E:
+ CSR_WRITE_1(sc, sc->rl_cfg4,
+ CSR_READ_1(sc, sc->rl_cfg4) & ~0x01);
+ break;
+ default:
+ CSR_WRITE_1(sc, sc->rl_cfg4,
+ CSR_READ_1(sc, sc->rl_cfg4) & ~RL_CFG4_JUMBO_EN1);
+ }
+ }
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
+
+ switch (sc->rl_hwrev->rl_rev) {
+ case RL_HWREV_8168DP:
+ pci_set_max_read_req(sc->rl_dev, 4096);
+ break;
+ default:
+ if (jumbo != 0)
+ pci_set_max_read_req(sc->rl_dev, 512);
+ else
+ pci_set_max_read_req(sc->rl_dev, 4096);
+ }
}
static void
@@ -2622,6 +3006,45 @@ re_init_locked(struct rl_softc *sc)
re_reset(sc);
/*
+ * For C+ mode, initialize the RX descriptors and mbufs.
+ */
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) {
+ if (ifp->if_mtu > RL_MTU) {
+ if (re_jrx_list_init(sc) != 0) {
+ device_printf(sc->rl_dev,
+ "no memory for jumbo RX buffers\n");
+ re_stop(sc);
+ return;
+ }
+ /* Disable checksum offloading for jumbo frames. */
+ ifp->if_capenable &= ~(IFCAP_HWCSUM | IFCAP_TSO4);
+ ifp->if_hwassist &= ~(RE_CSUM_FEATURES | CSUM_TSO);
+ } else {
+ if (re_rx_list_init(sc) != 0) {
+ device_printf(sc->rl_dev,
+ "no memory for RX buffers\n");
+ re_stop(sc);
+ return;
+ }
+ }
+ re_set_jumbo(sc, ifp->if_mtu > RL_MTU);
+ } else {
+ if (re_rx_list_init(sc) != 0) {
+ device_printf(sc->rl_dev, "no memory for RX buffers\n");
+ re_stop(sc);
+ return;
+ }
+ if ((sc->rl_flags & RL_FLAG_PCIE) != 0 &&
+ pci_get_device(sc->rl_dev) != RT_DEVICEID_8101E) {
+ if (ifp->if_mtu > RL_MTU)
+ pci_set_max_read_req(sc->rl_dev, 512);
+ else
+ pci_set_max_read_req(sc->rl_dev, 4096);
+ }
+ }
+ re_tx_list_init(sc);
+
+ /*
* Enable C+ RX and TX mode, as well as VLAN stripping and
* RX checksum offload. We must configure the C+ register
* before all others.
@@ -2638,12 +3061,12 @@ re_init_locked(struct rl_softc *sc)
} else
cfg |= RL_CPLUSCMD_RXENB | RL_CPLUSCMD_TXENB;
CSR_WRITE_2(sc, RL_CPLUS_CMD, cfg);
- if (sc->rl_hwrev == RL_HWREV_8169_8110SC ||
- sc->rl_hwrev == RL_HWREV_8169_8110SCE) {
+ if (sc->rl_hwrev->rl_rev == RL_HWREV_8169_8110SC ||
+ sc->rl_hwrev->rl_rev == RL_HWREV_8169_8110SCE) {
reg = 0x000fff00;
- if ((CSR_READ_1(sc, RL_CFG2) & RL_CFG2_PCI66MHZ) != 0)
+ if ((CSR_READ_1(sc, sc->rl_cfg2) & RL_CFG2_PCI66MHZ) != 0)
reg |= 0x000000ff;
- if (sc->rl_hwrev == RL_HWREV_8169_8110SCE)
+ if (sc->rl_hwrev->rl_rev == RL_HWREV_8169_8110SCE)
reg |= 0x00f00000;
CSR_WRITE_4(sc, 0x7c, reg);
/* Disable interrupt mitigation. */
@@ -2673,12 +3096,6 @@ re_init_locked(struct rl_softc *sc)
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
/*
- * For C+ mode, initialize the RX descriptors and mbufs.
- */
- re_rx_list_init(sc);
- re_tx_list_init(sc);
-
- /*
* Load the addresses of the RX and TX lists into the chip.
*/
@@ -2719,20 +3136,8 @@ re_init_locked(struct rl_softc *sc)
/* Configure interrupt moderation. */
if (sc->rl_type == RL_8169) {
- switch (sc->rl_hwrev) {
- case RL_HWREV_8100E:
- case RL_HWREV_8101E:
- case RL_HWREV_8102E:
- case RL_HWREV_8102EL:
- case RL_HWREV_8102EL_SPIN1:
- case RL_HWREV_8103E:
- CSR_WRITE_2(sc, RL_INTRMOD, 0);
- break;
- default:
- /* Magic from vendor. */
- CSR_WRITE_2(sc, RL_INTRMOD, 0x5100);
- break;
- }
+ /* Magic from vendor. */
+ CSR_WRITE_2(sc, RL_INTRMOD, 0x5100);
}
#ifdef DEVICE_POLLING
@@ -2763,18 +3168,35 @@ re_init_locked(struct rl_softc *sc)
CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB);
#endif
-#ifdef RE_TX_MODERATION
/*
* Initialize the timer interrupt register so that
* a timer interrupt will be generated once the timer
* reaches a certain number of ticks. The timer is
- * reloaded on each transmit. This gives us TX interrupt
+ * reloaded on each transmit.
+ */
+#ifdef RE_TX_MODERATION
+ /*
+ * Use timer interrupt register to moderate TX interrupt
* moderation, which dramatically improves TX frame rate.
*/
if (sc->rl_type == RL_8169)
CSR_WRITE_4(sc, RL_TIMERINT_8169, 0x800);
else
CSR_WRITE_4(sc, RL_TIMERINT, 0x400);
+#else
+ /*
+ * Use timer interrupt register to moderate RX interrupt
+ * moderation.
+ */
+ if ((sc->rl_flags & (RL_FLAG_MSI | RL_FLAG_MSIX)) != 0 &&
+ intr_filter == 0) {
+ if (sc->rl_type == RL_8169)
+ CSR_WRITE_4(sc, RL_TIMERINT_8169,
+ RL_USECS(sc->rl_int_rx_mod));
+ } else {
+ if (sc->rl_type == RL_8169)
+ CSR_WRITE_4(sc, RL_TIMERINT_8169, RL_USECS(0));
+ }
#endif
/*
@@ -2782,24 +3204,40 @@ re_init_locked(struct rl_softc *sc)
* size so we can receive jumbo frames.
*/
if (sc->rl_type == RL_8169) {
- if ((sc->rl_flags & (RL_FLAG_PCIE | RL_FLAG_NOJUMBO)) ==
- (RL_FLAG_PCIE | RL_FLAG_NOJUMBO))
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) {
+ /*
+ * For controllers that use new jumbo frame scheme,
+ * set maximum size of jumbo frame depedning on
+ * controller revisions.
+ */
+ if (ifp->if_mtu > RL_MTU)
+ CSR_WRITE_2(sc, RL_MAXRXPKTLEN,
+ sc->rl_hwrev->rl_max_mtu +
+ ETHER_VLAN_ENCAP_LEN + ETHER_HDR_LEN +
+ ETHER_CRC_LEN);
+ else
+ CSR_WRITE_2(sc, RL_MAXRXPKTLEN,
+ RE_RX_DESC_BUFLEN);
+ } else if ((sc->rl_flags & RL_FLAG_PCIE) != 0 &&
+ sc->rl_hwrev->rl_max_mtu == RL_MTU) {
+ /* RTL810x has no jumbo frame support. */
CSR_WRITE_2(sc, RL_MAXRXPKTLEN, RE_RX_DESC_BUFLEN);
- else
+ } else
CSR_WRITE_2(sc, RL_MAXRXPKTLEN, 16383);
}
if (sc->rl_testmode)
return;
- mii_mediachg(mii);
-
- CSR_WRITE_1(sc, RL_CFG1, CSR_READ_1(sc, RL_CFG1) | RL_CFG1_DRVLOAD);
+ CSR_WRITE_1(sc, sc->rl_cfg1, CSR_READ_1(sc, sc->rl_cfg1) |
+ RL_CFG1_DRVLOAD);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->rl_flags &= ~RL_FLAG_LINK;
+ mii_mediachg(mii);
+
sc->rl_watchdog_timer = 0;
callout_reset(&sc->rl_stat_callout, hz, re_tick, sc);
}
@@ -2837,9 +3275,9 @@ re_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
RL_LOCK(sc);
mii_pollstat(mii);
- RL_UNLOCK(sc);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
+ RL_UNLOCK(sc);
}
static int
@@ -2848,26 +3286,30 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct rl_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
struct mii_data *mii;
+ uint32_t rev;
int error = 0;
switch (command) {
case SIOCSIFMTU:
- if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > RL_JUMBO_MTU) {
- error = EINVAL;
- break;
- }
- if ((sc->rl_flags & RL_FLAG_NOJUMBO) != 0 &&
- ifr->ifr_mtu > RL_MAX_FRAMELEN) {
+ if (ifr->ifr_mtu < ETHERMIN ||
+ ifr->ifr_mtu > sc->rl_hwrev->rl_max_mtu) {
error = EINVAL;
break;
}
RL_LOCK(sc);
- if (ifp->if_mtu != ifr->ifr_mtu)
+ if (ifp->if_mtu != ifr->ifr_mtu) {
ifp->if_mtu = ifr->ifr_mtu;
- if (ifp->if_mtu > RL_TSO_MTU &&
- (ifp->if_capenable & IFCAP_TSO4) != 0) {
- ifp->if_capenable &= ~IFCAP_TSO4;
- ifp->if_hwassist &= ~CSUM_TSO;
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0 &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ re_init_locked(sc);
+ }
+ if (ifp->if_mtu > RL_TSO_MTU &&
+ (ifp->if_capenable & IFCAP_TSO4) != 0) {
+ ifp->if_capenable &= ~(IFCAP_TSO4 |
+ IFCAP_VLAN_HWTSO);
+ ifp->if_hwassist &= ~CSUM_TSO;
+ }
VLAN_CAPABILITIES(ifp);
}
RL_UNLOCK(sc);
@@ -2927,16 +3369,28 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
}
#endif /* DEVICE_POLLING */
- if (mask & IFCAP_HWCSUM) {
- ifp->if_capenable ^= IFCAP_HWCSUM;
- if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist |= RE_CSUM_FEATURES;
- else
+ RL_LOCK(sc);
+ if ((mask & IFCAP_TXCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
+ ifp->if_capenable ^= IFCAP_TXCSUM;
+ if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) {
+ rev = sc->rl_hwrev->rl_rev;
+ if (rev == RL_HWREV_8168C ||
+ rev == RL_HWREV_8168C_SPIN2)
+ ifp->if_hwassist |= CSUM_TCP | CSUM_UDP;
+ else
+ ifp->if_hwassist |= RE_CSUM_FEATURES;
+ } else
ifp->if_hwassist &= ~RE_CSUM_FEATURES;
reinit = 1;
}
+ if ((mask & IFCAP_RXCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_RXCSUM) != 0) {
+ ifp->if_capenable ^= IFCAP_RXCSUM;
+ reinit = 1;
+ }
if ((mask & IFCAP_TSO4) != 0 &&
- (ifp->if_capabilities & IFCAP_TSO) != 0) {
+ (ifp->if_capabilities & IFCAP_TSO4) != 0) {
ifp->if_capenable ^= IFCAP_TSO4;
if ((IFCAP_TSO4 & ifp->if_capenable) != 0)
ifp->if_hwassist |= CSUM_TSO;
@@ -2959,6 +3413,10 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
ifp->if_capenable &= ~IFCAP_VLAN_HWTSO;
reinit = 1;
}
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0 &&
+ (mask & (IFCAP_HWCSUM | IFCAP_TSO4 |
+ IFCAP_VLAN_HWTSO)) != 0)
+ reinit = 1;
if ((mask & IFCAP_WOL) != 0 &&
(ifp->if_capabilities & IFCAP_WOL) != 0) {
if ((mask & IFCAP_WOL_UCAST) != 0)
@@ -2970,8 +3428,9 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
if (reinit && ifp->if_drv_flags & IFF_DRV_RUNNING) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- re_init(sc);
+ re_init_locked(sc);
}
+ RL_UNLOCK(sc);
VLAN_CAPABILITIES(ifp);
}
break;
@@ -2999,7 +3458,7 @@ re_watchdog(struct rl_softc *sc)
if_printf(ifp, "watchdog timeout (missed Tx interrupts) "
"-- recovering\n");
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask);
+ re_start_locked(ifp);
return;
}
@@ -3010,7 +3469,7 @@ re_watchdog(struct rl_softc *sc)
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
re_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask);
+ re_start_locked(ifp);
}
/*
@@ -3033,10 +3492,42 @@ re_stop(struct rl_softc *sc)
callout_stop(&sc->rl_stat_callout);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- if ((sc->rl_flags & RL_FLAG_CMDSTOP) != 0)
+ /*
+ * Disable accepting frames to put RX MAC into idle state.
+ * Otherwise it's possible to get frames while stop command
+ * execution is in progress and controller can DMA the frame
+ * to already freed RX buffer during that period.
+ */
+ CSR_WRITE_4(sc, RL_RXCFG, CSR_READ_4(sc, RL_RXCFG) &
+ ~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_INDIV | RL_RXCFG_RX_MULTI |
+ RL_RXCFG_RX_BROAD));
+
+ if ((sc->rl_flags & RL_FLAG_WAIT_TXPOLL) != 0) {
+ for (i = RL_TIMEOUT; i > 0; i--) {
+ if ((CSR_READ_1(sc, sc->rl_txstart) &
+ RL_TXSTART_START) == 0)
+ break;
+ DELAY(20);
+ }
+ if (i == 0)
+ device_printf(sc->rl_dev,
+ "stopping TX poll timed out!\n");
+ CSR_WRITE_1(sc, RL_COMMAND, 0x00);
+ } else if ((sc->rl_flags & RL_FLAG_CMDSTOP) != 0) {
CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_STOPREQ | RL_CMD_TX_ENB |
RL_CMD_RX_ENB);
- else
+ if ((sc->rl_flags & RL_FLAG_CMDSTOP_WAIT_TXQ) != 0) {
+ for (i = RL_TIMEOUT; i > 0; i--) {
+ if ((CSR_READ_4(sc, RL_TXCFG) &
+ RL_TXCFG_QUEUE_EMPTY) != 0)
+ break;
+ DELAY(100);
+ }
+ if (i == 0)
+ device_printf(sc->rl_dev,
+ "stopping TXQ timed out!\n");
+ }
+ } else
CSR_WRITE_1(sc, RL_COMMAND, 0x00);
DELAY(1000);
CSR_WRITE_2(sc, RL_IMR, 0x0000);
@@ -3048,7 +3539,6 @@ re_stop(struct rl_softc *sc)
}
/* Free the TX list buffers. */
-
for (i = 0; i < sc->rl_ldata.rl_tx_desc_cnt; i++) {
txd = &sc->rl_ldata.rl_tx_desc[i];
if (txd->tx_m != NULL) {
@@ -3062,11 +3552,10 @@ re_stop(struct rl_softc *sc)
}
/* Free the RX list buffers. */
-
for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) {
rxd = &sc->rl_ldata.rl_rx_desc[i];
if (rxd->rx_m != NULL) {
- bus_dmamap_sync(sc->rl_ldata.rl_tx_mtag,
+ bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag,
rxd->rx_dmamap, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->rl_ldata.rl_rx_mtag,
rxd->rx_dmamap);
@@ -3074,6 +3563,20 @@ re_stop(struct rl_softc *sc)
rxd->rx_m = NULL;
}
}
+
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) {
+ for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) {
+ rxd = &sc->rl_ldata.rl_jrx_desc[i];
+ if (rxd->rx_m != NULL) {
+ bus_dmamap_sync(sc->rl_ldata.rl_jrx_mtag,
+ rxd->rx_dmamap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->rl_ldata.rl_jrx_mtag,
+ rxd->rx_dmamap);
+ m_freem(rxd->rx_m);
+ rxd->rx_m = NULL;
+ }
+ }
+ }
}
/*
@@ -3162,6 +3665,74 @@ re_shutdown(device_t dev)
}
static void
+re_set_linkspeed(struct rl_softc *sc)
+{
+ struct mii_softc *miisc;
+ struct mii_data *mii;
+ int aneg, i, phyno;
+
+ RL_LOCK_ASSERT(sc);
+
+ mii = device_get_softc(sc->rl_miibus);
+ mii_pollstat(mii);
+ aneg = 0;
+ if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
+ (IFM_ACTIVE | IFM_AVALID)) {
+ switch IFM_SUBTYPE(mii->mii_media_active) {
+ case IFM_10_T:
+ case IFM_100_TX:
+ return;
+ case IFM_1000_T:
+ aneg++;
+ break;
+ default:
+ break;
+ }
+ }
+ miisc = LIST_FIRST(&mii->mii_phys);
+ phyno = miisc->mii_phy;
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ mii_phy_reset(miisc);
+ re_miibus_writereg(sc->rl_dev, phyno, MII_100T2CR, 0);
+ re_miibus_writereg(sc->rl_dev, phyno,
+ MII_ANAR, ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA);
+ re_miibus_writereg(sc->rl_dev, phyno,
+ MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
+ DELAY(1000);
+ if (aneg != 0) {
+ /*
+ * Poll link state until re(4) get a 10/100Mbps link.
+ */
+ for (i = 0; i < MII_ANEGTICKS_GIGE; i++) {
+ mii_pollstat(mii);
+ if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID))
+ == (IFM_ACTIVE | IFM_AVALID)) {
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_10_T:
+ case IFM_100_TX:
+ return;
+ default:
+ break;
+ }
+ }
+ RL_UNLOCK(sc);
+ pause("relnk", hz);
+ RL_LOCK(sc);
+ }
+ if (i == MII_ANEGTICKS_GIGE)
+ device_printf(sc->rl_dev,
+ "establishing a link failed, WOL may not work!");
+ }
+ /*
+ * No link, force MAC to have 100Mbps, full-duplex link.
+ * MAC does not require reprogramming on resolved speed/duplex,
+ * so this is just for completeness.
+ */
+ mii->mii_media_status = IFM_AVALID | IFM_ACTIVE;
+ mii->mii_media_active = IFM_ETHER | IFM_100_TX | IFM_FDX;
+}
+
+static void
re_setwol(struct rl_softc *sc)
{
struct ifnet *ifp;
@@ -3181,40 +3752,44 @@ re_setwol(struct rl_softc *sc)
CSR_WRITE_1(sc, RL_GPIO,
CSR_READ_1(sc, RL_GPIO) & ~0x01);
}
- if ((ifp->if_capenable & IFCAP_WOL) != 0 &&
- (sc->rl_flags & RL_FLAG_WOLRXENB) != 0)
- CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RX_ENB);
+ if ((ifp->if_capenable & IFCAP_WOL) != 0) {
+ re_set_rxmode(sc);
+ if ((sc->rl_flags & RL_FLAG_WOL_MANLINK) != 0)
+ re_set_linkspeed(sc);
+ if ((sc->rl_flags & RL_FLAG_WOLRXENB) != 0)
+ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RX_ENB);
+ }
/* Enable config register write. */
CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE);
/* Enable PME. */
- v = CSR_READ_1(sc, RL_CFG1);
+ v = CSR_READ_1(sc, sc->rl_cfg1);
v &= ~RL_CFG1_PME;
if ((ifp->if_capenable & IFCAP_WOL) != 0)
v |= RL_CFG1_PME;
- CSR_WRITE_1(sc, RL_CFG1, v);
+ CSR_WRITE_1(sc, sc->rl_cfg1, v);
- v = CSR_READ_1(sc, RL_CFG3);
+ v = CSR_READ_1(sc, sc->rl_cfg3);
v &= ~(RL_CFG3_WOL_LINK | RL_CFG3_WOL_MAGIC);
if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
v |= RL_CFG3_WOL_MAGIC;
- CSR_WRITE_1(sc, RL_CFG3, v);
-
- /* Config register write done. */
- CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
+ CSR_WRITE_1(sc, sc->rl_cfg3, v);
- v = CSR_READ_1(sc, RL_CFG5);
- v &= ~(RL_CFG5_WOL_BCAST | RL_CFG5_WOL_MCAST | RL_CFG5_WOL_UCAST);
- v &= ~RL_CFG5_WOL_LANWAKE;
+ v = CSR_READ_1(sc, sc->rl_cfg5);
+ v &= ~(RL_CFG5_WOL_BCAST | RL_CFG5_WOL_MCAST | RL_CFG5_WOL_UCAST |
+ RL_CFG5_WOL_LANWAKE);
if ((ifp->if_capenable & IFCAP_WOL_UCAST) != 0)
v |= RL_CFG5_WOL_UCAST;
if ((ifp->if_capenable & IFCAP_WOL_MCAST) != 0)
v |= RL_CFG5_WOL_MCAST | RL_CFG5_WOL_BCAST;
if ((ifp->if_capenable & IFCAP_WOL) != 0)
v |= RL_CFG5_WOL_LANWAKE;
- CSR_WRITE_1(sc, RL_CFG5, v);
+ CSR_WRITE_1(sc, sc->rl_cfg5, v);
+
+ /* Config register write done. */
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
- if ((ifp->if_capenable & IFCAP_WOL) != 0 &&
+ if ((ifp->if_capenable & IFCAP_WOL) == 0 &&
(sc->rl_flags & RL_FLAG_PHYWAKE_PM) != 0)
CSR_WRITE_1(sc, RL_PMCH, CSR_READ_1(sc, RL_PMCH) & ~0x80);
/*
@@ -3245,17 +3820,17 @@ re_clrwol(struct rl_softc *sc)
/* Enable config register write. */
CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE);
- v = CSR_READ_1(sc, RL_CFG3);
+ v = CSR_READ_1(sc, sc->rl_cfg3);
v &= ~(RL_CFG3_WOL_LINK | RL_CFG3_WOL_MAGIC);
- CSR_WRITE_1(sc, RL_CFG3, v);
+ CSR_WRITE_1(sc, sc->rl_cfg3, v);
/* Config register write done. */
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
- v = CSR_READ_1(sc, RL_CFG5);
+ v = CSR_READ_1(sc, sc->rl_cfg5);
v &= ~(RL_CFG5_WOL_BCAST | RL_CFG5_WOL_MCAST | RL_CFG5_WOL_UCAST);
v &= ~RL_CFG5_WOL_LANWAKE;
- CSR_WRITE_1(sc, RL_CFG5, v);
+ CSR_WRITE_1(sc, sc->rl_cfg5, v);
}
static void
@@ -3263,6 +3838,7 @@ re_add_sysctls(struct rl_softc *sc)
{
struct sysctl_ctx_list *ctx;
struct sysctl_oid_list *children;
+ int error;
ctx = device_get_sysctl_ctx(sc->rl_dev);
children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->rl_dev));
@@ -3270,6 +3846,26 @@ re_add_sysctls(struct rl_softc *sc)
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "stats",
CTLTYPE_INT | CTLFLAG_RW, sc, 0, re_sysctl_stats, "I",
"Statistics Information");
+ if ((sc->rl_flags & (RL_FLAG_MSI | RL_FLAG_MSIX)) == 0)
+ return;
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "int_rx_mod",
+ CTLTYPE_INT | CTLFLAG_RW, &sc->rl_int_rx_mod, 0,
+ sysctl_hw_re_int_mod, "I", "re RX interrupt moderation");
+ /* Pull in device tunables. */
+ sc->rl_int_rx_mod = RL_TIMER_DEFAULT;
+ error = resource_int_value(device_get_name(sc->rl_dev),
+ device_get_unit(sc->rl_dev), "int_rx_mod", &sc->rl_int_rx_mod);
+ if (error == 0) {
+ if (sc->rl_int_rx_mod < RL_TIMER_MIN ||
+ sc->rl_int_rx_mod > RL_TIMER_MAX) {
+ device_printf(sc->rl_dev, "int_rx_mod value out of "
+ "range; using default: %d\n",
+ RL_TIMER_DEFAULT);
+ sc->rl_int_rx_mod = RL_TIMER_DEFAULT;
+ }
+ }
+
}
static int
@@ -3287,6 +3883,10 @@ re_sysctl_stats(SYSCTL_HANDLER_ARGS)
if (result == 1) {
sc = (struct rl_softc *)arg1;
RL_LOCK(sc);
+ if ((sc->rl_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ RL_UNLOCK(sc);
+ goto done;
+ }
bus_dmamap_sync(sc->rl_ldata.rl_stag,
sc->rl_ldata.rl_smap, BUS_DMASYNC_PREREAD);
CSR_WRITE_4(sc, RL_DUMPSTATS_HI,
@@ -3310,6 +3910,7 @@ re_sysctl_stats(SYSCTL_HANDLER_ARGS)
"DUMP statistics request timedout\n");
return (ETIMEDOUT);
}
+done:
stats = sc->rl_ldata.rl_stats;
printf("%s statistics:\n", device_get_nameunit(sc->rl_dev));
printf("Tx frames : %ju\n",
@@ -3342,3 +3943,29 @@ re_sysctl_stats(SYSCTL_HANDLER_ARGS)
return (error);
}
+
+static int
+sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
+{
+ int error, value;
+
+ if (arg1 == NULL)
+ return (EINVAL);
+ value = *(int *)arg1;
+ error = sysctl_handle_int(oidp, &value, 0, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ if (value < low || value > high)
+ return (EINVAL);
+ *(int *)arg1 = value;
+
+ return (0);
+}
+
+static int
+sysctl_hw_re_int_mod(SYSCTL_HANDLER_ARGS)
+{
+
+ return (sysctl_int_range(oidp, arg1, arg2, req, RL_TIMER_MIN,
+ RL_TIMER_MAX));
+}
diff --git a/freebsd/sys/dev/smc/if_smc.c b/freebsd/sys/dev/smc/if_smc.c
index 236eb546..2f4e0f1e 100644
--- a/freebsd/sys/dev/smc/if_smc.c
+++ b/freebsd/sys/dev/smc/if_smc.c
@@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
#include <dev/smc/if_smcvar.h>
#include <dev/mii/mii.h>
+#include <dev/mii/mii_bitbang.h>
#include <dev/mii/miivar.h>
#define SMC_LOCK(sc) mtx_lock(&(sc)->smc_mtx)
@@ -125,11 +126,33 @@ static timeout_t smc_watchdog;
static poll_handler_t smc_poll;
#endif
+/*
+ * MII bit-bang glue
+ */
+static uint32_t smc_mii_bitbang_read(device_t);
+static void smc_mii_bitbang_write(device_t, uint32_t);
+
+static const struct mii_bitbang_ops smc_mii_bitbang_ops = {
+ smc_mii_bitbang_read,
+ smc_mii_bitbang_write,
+ {
+ MGMT_MDO, /* MII_BIT_MDO */
+ MGMT_MDI, /* MII_BIT_MDI */
+ MGMT_MCLK, /* MII_BIT_MDC */
+ MGMT_MDOE, /* MII_BIT_DIR_HOST_PHY */
+ 0, /* MII_BIT_DIR_PHY_HOST */
+ }
+};
+
static __inline void
smc_select_bank(struct smc_softc *sc, uint16_t bank)
{
+ bus_barrier(sc->smc_reg, BSR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
bus_write_2(sc->smc_reg, BSR, bank & BSR_BANK_MASK);
+ bus_barrier(sc->smc_reg, BSR, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
/* Never call this when not in bank 2. */
@@ -145,35 +168,35 @@ smc_mmu_wait(struct smc_softc *sc)
}
static __inline uint8_t
-smc_read_1(struct smc_softc *sc, bus_addr_t offset)
+smc_read_1(struct smc_softc *sc, bus_size_t offset)
{
return (bus_read_1(sc->smc_reg, offset));
}
static __inline void
-smc_write_1(struct smc_softc *sc, bus_addr_t offset, uint8_t val)
+smc_write_1(struct smc_softc *sc, bus_size_t offset, uint8_t val)
{
bus_write_1(sc->smc_reg, offset, val);
}
static __inline uint16_t
-smc_read_2(struct smc_softc *sc, bus_addr_t offset)
+smc_read_2(struct smc_softc *sc, bus_size_t offset)
{
return (bus_read_2(sc->smc_reg, offset));
}
static __inline void
-smc_write_2(struct smc_softc *sc, bus_addr_t offset, uint16_t val)
+smc_write_2(struct smc_softc *sc, bus_size_t offset, uint16_t val)
{
bus_write_2(sc->smc_reg, offset, val);
}
static __inline void
-smc_read_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap,
+smc_read_multi_2(struct smc_softc *sc, bus_size_t offset, uint16_t *datap,
bus_size_t count)
{
@@ -181,13 +204,21 @@ smc_read_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap,
}
static __inline void
-smc_write_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap,
+smc_write_multi_2(struct smc_softc *sc, bus_size_t offset, uint16_t *datap,
bus_size_t count)
{
bus_write_multi_2(sc->smc_reg, offset, datap, count);
}
+static __inline void
+smc_barrier(struct smc_softc *sc, bus_size_t offset, bus_size_t length,
+ int flags)
+{
+
+ bus_barrier(sc->smc_reg, offset, length, flags);
+}
+
int
smc_probe(device_t dev)
{
@@ -540,6 +571,7 @@ smc_task_tx(void *context, int pending)
struct smc_softc *sc;
struct mbuf *m, *m0;
u_int packet, len;
+ int last_len;
uint8_t *data;
(void)pending;
@@ -592,16 +624,18 @@ smc_task_tx(void *context, int pending)
* Push the data out to the device.
*/
data = NULL;
+ last_len = 0;
for (; m != NULL; m = m->m_next) {
data = mtod(m, uint8_t *);
smc_write_multi_2(sc, DATA0, (uint16_t *)data, m->m_len / 2);
+ last_len = m->m_len;
}
/*
* Push out the control byte and and the odd byte if needed.
*/
if ((len & 1) != 0 && data != NULL)
- smc_write_2(sc, DATA0, (CTRL_ODD << 8) | data[m->m_len - 1]);
+ smc_write_2(sc, DATA0, (CTRL_ODD << 8) | data[last_len - 1]);
else
smc_write_2(sc, DATA0, 0);
@@ -899,70 +933,43 @@ smc_task_intr(void *context, int pending)
SMC_UNLOCK(sc);
}
-static u_int
-smc_mii_readbits(struct smc_softc *sc, int nbits)
+static uint32_t
+smc_mii_bitbang_read(device_t dev)
{
- u_int mgmt, mask, val;
+ struct smc_softc *sc;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
SMC_ASSERT_LOCKED(sc);
KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3,
- ("%s: smc_mii_readbits called with bank %d (!= 3)",
+ ("%s: smc_mii_bitbang_read called with bank %d (!= 3)",
device_get_nameunit(sc->smc_dev),
smc_read_2(sc, BSR) & BSR_BANK_MASK));
- /*
- * Set up the MGMT (aka MII) register.
- */
- mgmt = smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO);
- smc_write_2(sc, MGMT, mgmt);
-
- /*
- * Read the bits in.
- */
- for (mask = 1 << (nbits - 1), val = 0; mask; mask >>= 1) {
- if (smc_read_2(sc, MGMT) & MGMT_MDI)
- val |= mask;
-
- smc_write_2(sc, MGMT, mgmt);
- DELAY(1);
- smc_write_2(sc, MGMT, mgmt | MGMT_MCLK);
- DELAY(1);
- }
+ val = smc_read_2(sc, MGMT);
+ smc_barrier(sc, MGMT, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
return (val);
}
static void
-smc_mii_writebits(struct smc_softc *sc, u_int val, int nbits)
+smc_mii_bitbang_write(device_t dev, uint32_t val)
{
- u_int mgmt, mask;
+ struct smc_softc *sc;
+
+ sc = device_get_softc(dev);
SMC_ASSERT_LOCKED(sc);
KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3,
- ("%s: smc_mii_writebits called with bank %d (!= 3)",
+ ("%s: smc_mii_bitbang_write called with bank %d (!= 3)",
device_get_nameunit(sc->smc_dev),
smc_read_2(sc, BSR) & BSR_BANK_MASK));
- /*
- * Set up the MGMT (aka MII) register).
- */
- mgmt = smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO);
- mgmt |= MGMT_MDOE;
-
- /*
- * Push the bits out.
- */
- for (mask = 1 << (nbits - 1); mask; mask >>= 1) {
- if (val & mask)
- mgmt |= MGMT_MDO;
- else
- mgmt &= ~MGMT_MDO;
-
- smc_write_2(sc, MGMT, mgmt);
- DELAY(1);
- smc_write_2(sc, MGMT, mgmt | MGMT_MCLK);
- DELAY(1);
- }
+ smc_write_2(sc, MGMT, val);
+ smc_barrier(sc, MGMT, 2,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
int
@@ -977,26 +984,7 @@ smc_miibus_readreg(device_t dev, int phy, int reg)
smc_select_bank(sc, 3);
- /*
- * Send out the idle pattern.
- */
- smc_mii_writebits(sc, 0xffffffff, 32);
-
- /*
- * Start code + read opcode + phy address + phy register
- */
- smc_mii_writebits(sc, 6 << 10 | phy << 5 | reg, 14);
-
- /*
- * Turnaround + data
- */
- val = smc_mii_readbits(sc, 18);
-
- /*
- * Reset the MDIO interface.
- */
- smc_write_2(sc, MGMT,
- smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO));
+ val = mii_bitbang_readreg(dev, &smc_mii_bitbang_ops, phy, reg);
SMC_UNLOCK(sc);
return (val);
@@ -1013,23 +1001,7 @@ smc_miibus_writereg(device_t dev, int phy, int reg, int data)
smc_select_bank(sc, 3);
- /*
- * Send idle pattern.
- */
- smc_mii_writebits(sc, 0xffffffff, 32);
-
- /*
- * Start code + write opcode + phy address + phy register + turnaround
- * + data.
- */
- smc_mii_writebits(sc, 5 << 28 | phy << 23 | reg << 18 | 2 << 16 | data,
- 32);
-
- /*
- * Reset MDIO interface.
- */
- smc_write_2(sc, MGMT,
- smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO));
+ mii_bitbang_writereg(dev, &smc_mii_bitbang_ops, phy, reg, data);
SMC_UNLOCK(sc);
return (0);
diff --git a/freebsd/sys/dev/usb/controller/ehci.c b/freebsd/sys/dev/usb/controller/ehci.c
index 8a98f608..d126e9a9 100644
--- a/freebsd/sys/dev/usb/controller/ehci.c
+++ b/freebsd/sys/dev/usb/controller/ehci.c
@@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -98,20 +97,20 @@ static int ehciiaadbug = 0;
static int ehcilostintrbug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci");
-SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&ehcidebug, 0, "Debug level");
-SYSCTL_INT(_hw_usb_ehci, OID_AUTO, no_hs, CTLFLAG_RW,
- &ehcinohighspeed, 0, "Disable High Speed USB");
-SYSCTL_INT(_hw_usb_ehci, OID_AUTO, iaadbug, CTLFLAG_RW,
- &ehciiaadbug, 0, "Enable doorbell bug workaround");
-SYSCTL_INT(_hw_usb_ehci, OID_AUTO, lostintrbug, CTLFLAG_RW,
- &ehcilostintrbug, 0, "Enable lost interrupt bug workaround");
-
TUNABLE_INT("hw.usb.ehci.debug", &ehcidebug);
+SYSCTL_INT(_hw_usb_ehci, OID_AUTO, no_hs, CTLFLAG_RW | CTLFLAG_TUN,
+ &ehcinohighspeed, 0, "Disable High Speed USB");
TUNABLE_INT("hw.usb.ehci.no_hs", &ehcinohighspeed);
+SYSCTL_INT(_hw_usb_ehci, OID_AUTO, iaadbug, CTLFLAG_RW | CTLFLAG_TUN,
+ &ehciiaadbug, 0, "Enable doorbell bug workaround");
TUNABLE_INT("hw.usb.ehci.iaadbug", &ehciiaadbug);
+SYSCTL_INT(_hw_usb_ehci, OID_AUTO, lostintrbug, CTLFLAG_RW | CTLFLAG_TUN,
+ &ehcilostintrbug, 0, "Enable lost interrupt bug workaround");
TUNABLE_INT("hw.usb.ehci.lostintrbug", &ehcilostintrbug);
+
static void ehci_dump_regs(ehci_softc_t *sc);
static void ehci_dump_sqh(ehci_softc_t *sc, ehci_qh_t *sqh);
@@ -191,7 +190,7 @@ ehci_reset(ehci_softc_t *sc)
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
for (i = 0; i < 100; i++) {
- usb_pause_mtx(NULL, hz / 1000);
+ usb_pause_mtx(NULL, hz / 128);
hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
if (!hcr) {
if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) {
@@ -215,7 +214,7 @@ ehci_reset(ehci_softc_t *sc)
return (0);
}
}
- device_printf(sc->sc_bus.bdev, "reset timeout\n");
+ device_printf(sc->sc_bus.bdev, "Reset timeout\n");
return (USB_ERR_IOERROR);
}
@@ -227,7 +226,7 @@ ehci_hcreset(ehci_softc_t *sc)
EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
for (i = 0; i < 100; i++) {
- usb_pause_mtx(NULL, hz / 1000);
+ usb_pause_mtx(NULL, hz / 128);
hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
if (hcr)
break;
@@ -240,7 +239,60 @@ ehci_hcreset(ehci_softc_t *sc)
*/
device_printf(sc->sc_bus.bdev, "stop timeout\n");
- return ehci_reset(sc);
+ return (ehci_reset(sc));
+}
+
+static int
+ehci_init_sub(struct ehci_softc *sc)
+{
+ struct usb_page_search buf_res;
+ uint32_t cparams;
+ uint32_t hcr;
+ uint8_t i;
+
+ cparams = EREAD4(sc, EHCI_HCCPARAMS);
+
+ DPRINTF("cparams=0x%x\n", cparams);
+
+ if (EHCI_HCC_64BIT(cparams)) {
+ DPRINTF("HCC uses 64-bit structures\n");
+
+ /* MUST clear segment register if 64 bit capable */
+ EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
+ }
+
+ usbd_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
+ EOWRITE4(sc, EHCI_PERIODICLISTBASE, buf_res.physaddr);
+
+ usbd_get_page(&sc->sc_hw.async_start_pc, 0, &buf_res);
+ EOWRITE4(sc, EHCI_ASYNCLISTADDR, buf_res.physaddr | EHCI_LINK_QH);
+
+ /* enable interrupts */
+ EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
+
+ /* turn on controller */
+ EOWRITE4(sc, EHCI_USBCMD,
+ EHCI_CMD_ITC_1 | /* 1 microframes interrupt delay */
+ (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) |
+ EHCI_CMD_ASE |
+ EHCI_CMD_PSE |
+ EHCI_CMD_RS);
+
+ /* Take over port ownership */
+ EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF);
+
+ for (i = 0; i < 100; i++) {
+ usb_pause_mtx(NULL, hz / 128);
+ hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
+ if (!hcr) {
+ break;
+ }
+ }
+ if (hcr) {
+ device_printf(sc->sc_bus.bdev, "Run timeout\n");
+ return (USB_ERR_IOERROR);
+ }
+ return (USB_ERR_NORMAL_COMPLETION);
}
usb_error_t
@@ -249,8 +301,6 @@ ehci_init(ehci_softc_t *sc)
struct usb_page_search buf_res;
uint32_t version;
uint32_t sparams;
- uint32_t cparams;
- uint32_t hcr;
uint16_t i;
uint16_t x;
uint16_t y;
@@ -262,6 +312,8 @@ ehci_init(ehci_softc_t *sc)
usb_callout_init_mtx(&sc->sc_tmo_pcd, &sc->sc_bus.bus_mtx, 0);
usb_callout_init_mtx(&sc->sc_tmo_poll, &sc->sc_bus.bus_mtx, 0);
+ sc->sc_offs = EHCI_CAPLENGTH(EREAD4(sc, EHCI_CAPLEN_HCIVERSION));
+
#ifdef USB_DEBUG
if (ehciiaadbug)
sc->sc_flags |= EHCI_SCFLG_IAADBUG;
@@ -272,8 +324,6 @@ ehci_init(ehci_softc_t *sc)
}
#endif
- sc->sc_offs = EHCI_CAPLENGTH(EREAD4(sc, EHCI_CAPLEN_HCIVERSION));
-
version = EHCI_HCIVERSION(EREAD4(sc, EHCI_CAPLEN_HCIVERSION));
device_printf(sc->sc_bus.bdev, "EHCI version %x.%x\n",
version >> 8, version & 0xff);
@@ -282,15 +332,6 @@ ehci_init(ehci_softc_t *sc)
DPRINTF("sparams=0x%x\n", sparams);
sc->sc_noport = EHCI_HCS_N_PORTS(sparams);
- cparams = EREAD4(sc, EHCI_HCCPARAMS);
- DPRINTF("cparams=0x%x\n", cparams);
-
- if (EHCI_HCC_64BIT(cparams)) {
- DPRINTF("HCC uses 64-bit structures\n");
-
- /* MUST clear segment register if 64 bit capable */
- EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
- }
sc->sc_bus.usbrev = USB_REV_2_0;
/* Reset the controller */
@@ -467,9 +508,6 @@ ehci_init(ehci_softc_t *sc)
[i & (EHCI_VIRTUAL_FRAMELIST_COUNT - 1)]->itd_self;
}
}
- /* setup sync list pointer */
- EOWRITE4(sc, EHCI_PERIODICLISTBASE, buf_res.physaddr);
-
usbd_get_page(&sc->sc_hw.async_start_pc, 0, &buf_res);
if (1) {
@@ -514,35 +552,8 @@ ehci_init(ehci_softc_t *sc)
}
#endif
- /* setup async list pointer */
- EOWRITE4(sc, EHCI_ASYNCLISTADDR, buf_res.physaddr | EHCI_LINK_QH);
-
-
- /* enable interrupts */
- EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-
- /* turn on controller */
- EOWRITE4(sc, EHCI_USBCMD,
- EHCI_CMD_ITC_1 | /* 1 microframes interrupt delay */
- (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) |
- EHCI_CMD_ASE |
- EHCI_CMD_PSE |
- EHCI_CMD_RS);
-
- /* Take over port ownership */
- EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF);
-
- for (i = 0; i < 100; i++) {
- usb_pause_mtx(NULL, hz / 1000);
- hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
- if (!hcr) {
- break;
- }
- }
- if (hcr) {
- device_printf(sc->sc_bus.bdev, "run timeout\n");
- return (USB_ERR_IOERROR);
- }
+ /* finial setup */
+ err = ehci_init_sub(sc);
if (!err) {
/* catch any lost interrupts */
@@ -576,137 +587,28 @@ ehci_detach(ehci_softc_t *sc)
usb_callout_drain(&sc->sc_tmo_poll);
}
-void
+static void
ehci_suspend(ehci_softc_t *sc)
{
- uint32_t cmd;
- uint32_t hcr;
- uint8_t i;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- for (i = 1; i <= sc->sc_noport; i++) {
- cmd = EOREAD4(sc, EHCI_PORTSC(i));
- if (((cmd & EHCI_PS_PO) == 0) &&
- ((cmd & EHCI_PS_PE) == EHCI_PS_PE)) {
- EOWRITE4(sc, EHCI_PORTSC(i),
- cmd | EHCI_PS_SUSP);
- }
- }
-
- sc->sc_cmd = EOREAD4(sc, EHCI_USBCMD);
-
- cmd = sc->sc_cmd & ~(EHCI_CMD_ASE | EHCI_CMD_PSE);
- EOWRITE4(sc, EHCI_USBCMD, cmd);
-
- for (i = 0; i < 100; i++) {
- hcr = EOREAD4(sc, EHCI_USBSTS) &
- (EHCI_STS_ASS | EHCI_STS_PSS);
-
- if (hcr == 0) {
- break;
- }
- usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
- }
-
- if (hcr != 0) {
- device_printf(sc->sc_bus.bdev, "reset timeout\n");
- }
- cmd &= ~EHCI_CMD_RS;
- EOWRITE4(sc, EHCI_USBCMD, cmd);
-
- for (i = 0; i < 100; i++) {
- hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
- if (hcr == EHCI_STS_HCH) {
- break;
- }
- usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
- }
+ DPRINTF("stopping the HC\n");
- if (hcr != EHCI_STS_HCH) {
- device_printf(sc->sc_bus.bdev,
- "config timeout\n");
- }
- USB_BUS_UNLOCK(&sc->sc_bus);
+ /* reset HC */
+ ehci_hcreset(sc);
}
-void
+static void
ehci_resume(ehci_softc_t *sc)
{
- struct usb_page_search buf_res;
- uint32_t cmd;
- uint32_t hcr;
- uint8_t i;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* restore things in case the bios doesn't */
- EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
-
- usbd_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
- EOWRITE4(sc, EHCI_PERIODICLISTBASE, buf_res.physaddr);
-
- usbd_get_page(&sc->sc_hw.async_start_pc, 0, &buf_res);
- EOWRITE4(sc, EHCI_ASYNCLISTADDR, buf_res.physaddr | EHCI_LINK_QH);
-
- EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-
- hcr = 0;
- for (i = 1; i <= sc->sc_noport; i++) {
- cmd = EOREAD4(sc, EHCI_PORTSC(i));
- if (((cmd & EHCI_PS_PO) == 0) &&
- ((cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP)) {
- EOWRITE4(sc, EHCI_PORTSC(i),
- cmd | EHCI_PS_FPR);
- hcr = 1;
- }
- }
-
- if (hcr) {
- usb_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_WAIT));
-
- for (i = 1; i <= sc->sc_noport; i++) {
- cmd = EOREAD4(sc, EHCI_PORTSC(i));
- if (((cmd & EHCI_PS_PO) == 0) &&
- ((cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP)) {
- EOWRITE4(sc, EHCI_PORTSC(i),
- cmd & ~EHCI_PS_FPR);
- }
- }
- }
- EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd);
-
- for (i = 0; i < 100; i++) {
- hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
- if (hcr != EHCI_STS_HCH) {
- break;
- }
- usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
- }
- if (hcr == EHCI_STS_HCH) {
- device_printf(sc->sc_bus.bdev, "config timeout\n");
- }
-
- USB_BUS_UNLOCK(&sc->sc_bus);
+ /* reset HC */
+ ehci_hcreset(sc);
- usb_pause_mtx(NULL,
- USB_MS_TO_TICKS(USB_RESUME_WAIT));
+ /* setup HC */
+ ehci_init_sub(sc);
/* catch any lost interrupts */
ehci_do_poll(&sc->sc_bus);
}
-void
-ehci_shutdown(ehci_softc_t *sc)
-{
- DPRINTF("stopping the HC\n");
-
- if (ehci_hcreset(sc)) {
- DPRINTF("reset failed!\n");
- }
-}
-
#ifdef USB_DEBUG
static void
ehci_dump_regs(ehci_softc_t *sc)
@@ -1183,6 +1085,28 @@ _ehci_remove_qh(ehci_qh_t *sqh, ehci_qh_t *last)
return (last);
}
+static void
+ehci_data_toggle_update(struct usb_xfer *xfer, uint16_t actlen, uint16_t xlen)
+{
+ uint16_t rem;
+ uint8_t dt;
+
+ /* count number of full packets */
+ dt = (actlen / xfer->max_packet_size) & 1;
+
+ /* compute remainder */
+ rem = actlen % xfer->max_packet_size;
+
+ if (rem > 0)
+ dt ^= 1; /* short packet at the end */
+ else if (actlen != xlen)
+ dt ^= 1; /* zero length packet at the end */
+ else if (xlen == 0)
+ dt ^= 1; /* zero length transfer */
+
+ xfer->endpoint->toggle_next ^= dt;
+}
+
static usb_error_t
ehci_non_isoc_done_sub(struct usb_xfer *xfer)
{
@@ -1216,7 +1140,10 @@ ehci_non_isoc_done_sub(struct usb_xfer *xfer)
status |= EHCI_QTD_HALTED;
} else if (xfer->aframes != xfer->nframes) {
xfer->frlengths[xfer->aframes] += td->len - len;
+ /* manually update data toggle */
+ ehci_data_toggle_update(xfer, td->len - len, td->len);
}
+
/* Check for last transfer */
if (((void *)td) == xfer->td_transfer_last) {
td = NULL;
@@ -1298,9 +1225,6 @@ ehci_non_isoc_done(struct usb_xfer *xfer)
status = hc32toh(sc, qh->qh_qtd.qtd_status);
- xfer->endpoint->toggle_next =
- (status & EHCI_QTD_TOGGLE_MASK) ? 1 : 0;
-
/* reset scanner */
xfer->td_transfer_cache = xfer->td_transfer_first;
@@ -1879,6 +1803,8 @@ ehci_setup_standard_chain(struct usb_xfer *xfer, ehci_qh_t **qh_last)
if (xfer->flags_int.control_xfr) {
if (xfer->flags_int.control_hdr) {
+ xfer->endpoint->toggle_next = 0;
+
temp.qtd_status &=
htohc32(temp.sc, EHCI_QTD_SET_CERR(3));
temp.qtd_status |= htohc32(temp.sc,
@@ -2474,9 +2400,9 @@ ehci_device_isoc_fs_open(struct usb_xfer *xfer)
EHCI_SITD_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
EHCI_SITD_SET_PORT(xfer->xroot->udev->hs_port_no);
- if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN) {
+ if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN)
sitd_portaddr |= EHCI_SITD_SET_DIR_IN;
- }
+
sitd_portaddr = htohc32(sc, sitd_portaddr);
/* initialize all TD's */
@@ -2512,9 +2438,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
{
struct usb_page_search buf_res;
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- struct usb_fs_isoc_schedule *fss_start;
- struct usb_fs_isoc_schedule *fss_end;
- struct usb_fs_isoc_schedule *fss;
ehci_sitd_t *td;
ehci_sitd_t *td_last = NULL;
ehci_sitd_t **pp_last;
@@ -2526,7 +2449,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
uint16_t tlen;
uint8_t sa;
uint8_t sb;
- uint8_t error;
#ifdef USB_DEBUG
uint8_t once = 1;
@@ -2571,9 +2493,8 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
* pre-compute when the isochronous transfer will be finished:
*/
xfer->isoc_time_complete =
- usbd_fs_isoc_schedule_isoc_time_expand
- (xfer->xroot->udev, &fss_start, &fss_end, nframes) + buf_offset +
- xfer->nframes;
+ usb_isoc_time_expand(&sc->sc_bus, nframes) +
+ buf_offset + xfer->nframes;
/* get the real number of frames */
@@ -2596,19 +2517,14 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
xfer->qh_pos = xfer->endpoint->isoc_next;
- fss = fss_start + (xfer->qh_pos % USB_ISOC_TIME_MAX);
-
while (nframes--) {
if (td == NULL) {
panic("%s:%d: out of TD's\n",
__FUNCTION__, __LINE__);
}
- if (pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]) {
+ if (pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT])
pp_last = &sc->sc_isoc_fs_p_last[0];
- }
- if (fss >= fss_end) {
- fss = fss_start;
- }
+
/* reuse sitd_portaddr and sitd_back from last transfer */
if (*plen > xfer->max_frame_size) {
@@ -2623,17 +2539,19 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
#endif
*plen = xfer->max_frame_size;
}
- /*
- * We currently don't care if the ISOCHRONOUS schedule is
- * full!
- */
- error = usbd_fs_isoc_schedule_alloc(fss, &sa, *plen);
- if (error) {
+
+ /* allocate a slot */
+
+ sa = usbd_fs_isoc_schedule_alloc_slot(xfer,
+ xfer->isoc_time_complete - nframes - 1);
+
+ if (sa == 255) {
/*
- * The FULL speed schedule is FULL! Set length
- * to zero.
+ * Schedule is FULL, set length to zero:
*/
+
*plen = 0;
+ sa = USB_FS_ISOC_UFRAME_MAX - 1;
}
if (*plen) {
/*
@@ -2713,7 +2631,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
pp_last++;
plen++;
- fss++;
td_last = td;
td = td->obj_next;
}
@@ -2723,11 +2640,29 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
/* update isoc_next */
xfer->endpoint->isoc_next = (pp_last - &sc->sc_isoc_fs_p_last[0]) &
(EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
+
+ /*
+ * We don't allow cancelling of the SPLIT transaction USB FULL
+ * speed transfer, because it disturbs the bandwidth
+ * computation algorithm.
+ */
+ xfer->flags_int.can_cancel_immed = 0;
}
static void
ehci_device_isoc_fs_start(struct usb_xfer *xfer)
{
+ /*
+ * We don't allow cancelling of the SPLIT transaction USB FULL
+ * speed transfer, because it disturbs the bandwidth
+ * computation algorithm.
+ */
+ xfer->flags_int.can_cancel_immed = 0;
+
+ /* set a default timeout */
+ if (xfer->timeout == 0)
+ xfer->timeout = 500; /* ms */
+
/* put transfer on interrupt queue */
ehci_transfer_intr_enqueue(xfer);
}
@@ -3087,13 +3022,8 @@ static const struct ehci_config_desc ehci_confd = {
static const
struct usb_hub_descriptor ehci_hubd =
{
- 0, /* dynamic length */
- UDESC_HUB,
- 0,
- {0, 0},
- 0,
- 0,
- {0},
+ .bDescLength = 0, /* dynamic length */
+ .bDescriptorType = UDESC_HUB,
};
static void
@@ -3348,7 +3278,7 @@ ehci_roothub_exec(struct usb_device *udev,
break;
case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
len = 16;
- bzero(sc->sc_hub_desc.temp, 16);
+ memset(sc->sc_hub_desc.temp, 0, 16);
break;
case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
DPRINTFN(9, "get port status i=%d\n",
@@ -3441,7 +3371,7 @@ ehci_roothub_exec(struct usb_device *udev,
/* Wait for reset to complete. */
usb_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_PORT_ROOT_RESET_DELAY));
+ USB_MS_TO_TICKS(usb_port_root_reset_delay));
/* Terminate reset sequence. */
if (!(sc->sc_flags & EHCI_SCFLG_NORESTERM))
@@ -3887,8 +3817,24 @@ ehci_device_suspend(struct usb_device *udev)
}
USB_BUS_UNLOCK(udev->bus);
+}
- return;
+static void
+ehci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state)
+{
+ struct ehci_softc *sc = EHCI_BUS2SC(bus);
+
+ switch (state) {
+ case USB_HW_POWER_SUSPEND:
+ case USB_HW_POWER_SHUTDOWN:
+ ehci_suspend(sc);
+ break;
+ case USB_HW_POWER_RESUME:
+ ehci_resume(sc);
+ break;
+ default:
+ break;
+ }
}
static void
@@ -3934,6 +3880,7 @@ struct usb_bus_methods ehci_bus_methods =
.device_resume = ehci_device_resume,
.device_suspend = ehci_device_suspend,
.set_hw_power = ehci_set_hw_power,
+ .set_hw_power_sleep = ehci_set_hw_power_sleep,
.roothub_exec = ehci_roothub_exec,
.xfer_poll = ehci_do_poll,
};
diff --git a/freebsd/sys/dev/usb/controller/ehci.h b/freebsd/sys/dev/usb/controller/ehci.h
index 19d32426..a64d48a0 100644
--- a/freebsd/sys/dev/usb/controller/ehci.h
+++ b/freebsd/sys/dev/usb/controller/ehci.h
@@ -14,13 +14,6 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -340,8 +333,6 @@ typedef struct ehci_softc {
uint32_t sc_terminate_self; /* TD short packet termination pointer */
uint32_t sc_eintrs;
- uint32_t sc_cmd; /* shadow of cmd register during
- * suspend */
uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT];
uint16_t sc_id_vendor; /* vendor ID for root hub */
@@ -478,9 +469,6 @@ usb_bus_mem_cb_t ehci_iterate_hw_softc;
usb_error_t ehci_reset(ehci_softc_t *sc);
usb_error_t ehci_init(ehci_softc_t *sc);
void ehci_detach(struct ehci_softc *sc);
-void ehci_suspend(struct ehci_softc *sc);
-void ehci_resume(struct ehci_softc *sc);
-void ehci_shutdown(ehci_softc_t *sc);
void ehci_interrupt(ehci_softc_t *sc);
#endif /* _EHCI_H_ */
diff --git a/freebsd/sys/dev/usb/controller/ohci.c b/freebsd/sys/dev/usb/controller/ohci.c
index 6390156a..19ecf296 100644
--- a/freebsd/sys/dev/usb/controller/ohci.c
+++ b/freebsd/sys/dev/usb/controller/ohci.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -84,9 +83,8 @@ __FBSDID("$FreeBSD$");
static int ohcidebug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
-SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&ohcidebug, 0, "ohci debug level");
-
TUNABLE_INT("hw.usb.ohci.debug", &ohcidebug);
static void ohci_dumpregs(ohci_softc_t *);
@@ -169,7 +167,7 @@ ohci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
}
static usb_error_t
-ohci_controller_init(ohci_softc_t *sc)
+ohci_controller_init(ohci_softc_t *sc, int do_suspend)
{
struct usb_page_search buf_res;
uint32_t i;
@@ -236,6 +234,11 @@ reset:
}
#endif
+ if (do_suspend) {
+ OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_SUSPEND);
+ return (USB_ERR_NORMAL_COMPLETION);
+ }
+
/* The controller is now in SUSPEND state, we have 2ms to finish. */
/* set up HC registers */
@@ -418,13 +421,12 @@ ohci_init(ohci_softc_t *sc)
sc->sc_bus.usbrev = USB_REV_1_0;
- if (ohci_controller_init(sc)) {
+ if (ohci_controller_init(sc, 0) != 0)
return (USB_ERR_INVAL);
- } else {
- /* catch any lost interrupts */
- ohci_do_poll(&sc->sc_bus);
- return (USB_ERR_NORMAL_COMPLETION);
- }
+
+ /* catch any lost interrupts */
+ ohci_do_poll(&sc->sc_bus);
+ return (USB_ERR_NORMAL_COMPLETION);
}
/*
@@ -448,75 +450,32 @@ ohci_detach(struct ohci_softc *sc)
usb_callout_drain(&sc->sc_tmo_rhsc);
}
-/* NOTE: suspend/resume is called from
- * interrupt context and cannot sleep!
- */
-void
+static void
ohci_suspend(ohci_softc_t *sc)
{
- uint32_t ctl;
-
- USB_BUS_LOCK(&sc->sc_bus);
+ DPRINTF("\n");
#ifdef USB_DEBUG
- DPRINTF("\n");
- if (ohcidebug > 2) {
+ if (ohcidebug > 2)
ohci_dumpregs(sc);
- }
#endif
- ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK;
- if (sc->sc_control == 0) {
- /*
- * Preserve register values, in case that APM BIOS
- * does not recover them.
- */
- sc->sc_control = ctl;
- sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE);
- }
- ctl |= OHCI_HCFS_SUSPEND;
- OWRITE4(sc, OHCI_CONTROL, ctl);
-
- usb_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_WAIT));
-
- USB_BUS_UNLOCK(&sc->sc_bus);
+ /* reset HC and leave it suspended */
+ ohci_controller_init(sc, 1);
}
-void
+static void
ohci_resume(ohci_softc_t *sc)
{
- uint32_t ctl;
+ DPRINTF("\n");
#ifdef USB_DEBUG
- DPRINTF("\n");
- if (ohcidebug > 2) {
+ if (ohcidebug > 2)
ohci_dumpregs(sc);
- }
#endif
- /* some broken BIOSes never initialize the Controller chip */
- ohci_controller_init(sc);
-
- USB_BUS_LOCK(&sc->sc_bus);
- if (sc->sc_intre) {
- OWRITE4(sc, OHCI_INTERRUPT_ENABLE,
- sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE));
- }
- if (sc->sc_control)
- ctl = sc->sc_control;
- else
- ctl = OREAD4(sc, OHCI_CONTROL);
- ctl |= OHCI_HCFS_RESUME;
- OWRITE4(sc, OHCI_CONTROL, ctl);
- usb_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_DELAY));
- ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL;
- OWRITE4(sc, OHCI_CONTROL, ctl);
- usb_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_RECOVERY));
- sc->sc_control = sc->sc_intre = 0;
- USB_BUS_UNLOCK(&sc->sc_bus);
+ /* some broken BIOSes never initialize the Controller chip */
+ ohci_controller_init(sc, 0);
/* catch any lost interrupts */
ohci_do_poll(&sc->sc_bus);
@@ -2122,13 +2081,8 @@ struct ohci_config_desc ohci_confd =
static const
struct usb_hub_descriptor ohci_hubd =
{
- 0, /* dynamic length */
- UDESC_HUB,
- 0,
- {0, 0},
- 0,
- 0,
- {0},
+ .bDescLength = 0, /* dynamic length */
+ .bDescriptorType = UDESC_HUB,
};
static usb_error_t
@@ -2350,7 +2304,7 @@ ohci_roothub_exec(struct usb_device *udev,
case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
len = 16;
- bzero(sc->sc_hub_desc.temp, 16);
+ memset(sc->sc_hub_desc.temp, 0, 16);
break;
case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
DPRINTFN(9, "get port status i=%d\n",
@@ -2391,7 +2345,7 @@ ohci_roothub_exec(struct usb_device *udev,
for (v = 0;; v++) {
if (v < 12) {
usb_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_PORT_ROOT_RESET_DELAY));
+ USB_MS_TO_TICKS(usb_port_root_reset_delay));
if ((OREAD4(sc, port) & UPS_RESET) == 0) {
break;
@@ -2716,6 +2670,24 @@ ohci_device_suspend(struct usb_device *udev)
}
static void
+ohci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state)
+{
+ struct ohci_softc *sc = OHCI_BUS2SC(bus);
+
+ switch (state) {
+ case USB_HW_POWER_SUSPEND:
+ case USB_HW_POWER_SHUTDOWN:
+ ohci_suspend(sc);
+ break;
+ case USB_HW_POWER_RESUME:
+ ohci_resume(sc);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
ohci_set_hw_power(struct usb_bus *bus)
{
struct ohci_softc *sc = OHCI_BUS2SC(bus);
@@ -2759,6 +2731,7 @@ struct usb_bus_methods ohci_bus_methods =
.device_resume = ohci_device_resume,
.device_suspend = ohci_device_suspend,
.set_hw_power = ohci_set_hw_power,
+ .set_hw_power_sleep = ohci_set_hw_power_sleep,
.roothub_exec = ohci_roothub_exec,
.xfer_poll = ohci_do_poll,
};
diff --git a/freebsd/sys/dev/usb/controller/ohci.h b/freebsd/sys/dev/usb/controller/ohci.h
index c878af07..fad1a9fe 100644
--- a/freebsd/sys/dev/usb/controller/ohci.h
+++ b/freebsd/sys/dev/usb/controller/ohci.h
@@ -15,13 +15,6 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -250,8 +243,6 @@ typedef struct ohci_softc {
bus_space_handle_t sc_io_hdl;
uint32_t sc_eintrs; /* enabled interrupts */
- uint32_t sc_control; /* Preserved during suspend/standby */
- uint32_t sc_intre;
uint16_t sc_intr_stat[OHCI_NO_EDS];
uint16_t sc_id_vendor;
@@ -269,8 +260,6 @@ usb_bus_mem_cb_t ohci_iterate_hw_softc;
usb_error_t ohci_init(ohci_softc_t *sc);
void ohci_detach(struct ohci_softc *sc);
-void ohci_suspend(ohci_softc_t *sc);
-void ohci_resume(ohci_softc_t *sc);
void ohci_interrupt(ohci_softc_t *sc);
#endif /* _OHCI_H_ */
diff --git a/freebsd/sys/dev/usb/controller/ohcireg.h b/freebsd/sys/dev/usb/controller/ohcireg.h
index 9127a02a..7f14875c 100644
--- a/freebsd/sys/dev/usb/controller/ohcireg.h
+++ b/freebsd/sys/dev/usb/controller/ohcireg.h
@@ -15,13 +15,6 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
diff --git a/freebsd/sys/dev/usb/controller/usb_controller.c b/freebsd/sys/dev/usb/controller/usb_controller.c
index f4220daf..ce3263dd 100644
--- a/freebsd/sys/dev/usb/controller/usb_controller.c
+++ b/freebsd/sys/dev/usb/controller/usb_controller.c
@@ -36,7 +36,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -63,12 +62,17 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#include <dev/usb/usb_pf.h>
+#include <rtems/bsd/local/usb_if.h>
/* function prototypes */
static device_probe_t usb_probe;
static device_attach_t usb_attach;
static device_detach_t usb_detach;
+static device_suspend_t usb_suspend;
+static device_resume_t usb_resume;
+static device_shutdown_t usb_shutdown;
static void usb_attach_sub(device_t, struct usb_bus *);
@@ -85,8 +89,18 @@ SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0,
#ifndef __rtems__
static int usb_no_boot_wait = 0;
TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
-SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RDTUN, &usb_no_boot_wait, 0,
- "No device enumerate waiting at boot.");
+SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RD|CTLFLAG_TUN, &usb_no_boot_wait, 0,
+ "No USB device enumerate waiting at boot.");
+
+static int usb_no_suspend_wait = 0;
+TUNABLE_INT("hw.usb.no_suspend_wait", &usb_no_suspend_wait);
+SYSCTL_INT(_hw_usb, OID_AUTO, no_suspend_wait, CTLFLAG_RW|CTLFLAG_TUN,
+ &usb_no_suspend_wait, 0, "No USB device waiting at system suspend.");
+
+static int usb_no_shutdown_wait = 0;
+TUNABLE_INT("hw.usb.no_shutdown_wait", &usb_no_shutdown_wait);
+SYSCTL_INT(_hw_usb, OID_AUTO, no_shutdown_wait, CTLFLAG_RW|CTLFLAG_TUN,
+ &usb_no_shutdown_wait, 0, "No USB device waiting at system shutdown.");
#endif /* __rtems__ */
static devclass_t usb_devclass;
@@ -95,9 +109,9 @@ static device_method_t usb_methods[] = {
DEVMETHOD(device_probe, usb_probe),
DEVMETHOD(device_attach, usb_attach),
DEVMETHOD(device_detach, usb_detach),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, usb_suspend),
+ DEVMETHOD(device_resume, usb_resume),
+ DEVMETHOD(device_shutdown, usb_shutdown),
{0, 0}
};
@@ -190,12 +204,12 @@ usb_detach(device_t dev)
usb_root_mount_rel(bus);
USB_BUS_LOCK(bus);
- if (usb_proc_msignal(&bus->explore_proc,
- &bus->detach_msg[0], &bus->detach_msg[1])) {
- /* ignore */
- }
- /* Wait for detach to complete */
+ /* Queue detach job */
+ usb_proc_msignal(&bus->explore_proc,
+ &bus->detach_msg[0], &bus->detach_msg[1]);
+
+ /* Wait for detach to complete */
usb_proc_mwait(&bus->explore_proc,
&bus->detach_msg[0], &bus->detach_msg[1]);
@@ -214,6 +228,96 @@ usb_detach(device_t dev)
usb_proc_free(&bus->control_xfer_proc);
+#if USB_HAVE_PF
+ usbpf_detach(bus);
+#endif
+ return (0);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_suspend
+ *------------------------------------------------------------------------*/
+static int
+usb_suspend(device_t dev)
+{
+ struct usb_bus *bus = device_get_softc(dev);
+
+ DPRINTF("\n");
+
+ if (bus == NULL) {
+ /* was never setup properly */
+ return (0);
+ }
+
+ USB_BUS_LOCK(bus);
+ usb_proc_msignal(&bus->explore_proc,
+ &bus->suspend_msg[0], &bus->suspend_msg[1]);
+#ifndef __rtems__
+ if (usb_no_suspend_wait == 0) {
+ /* wait for suspend callback to be executed */
+ usb_proc_mwait(&bus->explore_proc,
+ &bus->suspend_msg[0], &bus->suspend_msg[1]);
+ }
+#endif /* __rtems__ */
+ USB_BUS_UNLOCK(bus);
+
+ return (0);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_resume
+ *------------------------------------------------------------------------*/
+static int
+usb_resume(device_t dev)
+{
+ struct usb_bus *bus = device_get_softc(dev);
+
+ DPRINTF("\n");
+
+ if (bus == NULL) {
+ /* was never setup properly */
+ return (0);
+ }
+
+ USB_BUS_LOCK(bus);
+ usb_proc_msignal(&bus->explore_proc,
+ &bus->resume_msg[0], &bus->resume_msg[1]);
+ USB_BUS_UNLOCK(bus);
+
+ return (0);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_shutdown
+ *------------------------------------------------------------------------*/
+static int
+usb_shutdown(device_t dev)
+{
+ struct usb_bus *bus = device_get_softc(dev);
+
+ DPRINTF("\n");
+
+ if (bus == NULL) {
+ /* was never setup properly */
+ return (0);
+ }
+
+ device_printf(bus->bdev, "Controller shutdown\n");
+
+ USB_BUS_LOCK(bus);
+#ifndef __rtems__
+ usb_proc_msignal(&bus->explore_proc,
+ &bus->shutdown_msg[0], &bus->shutdown_msg[1]);
+ if (usb_no_shutdown_wait == 0) {
+ /* wait for shutdown callback to be executed */
+ usb_proc_mwait(&bus->explore_proc,
+ &bus->shutdown_msg[0], &bus->shutdown_msg[1]);
+ }
+#endif /* __rtems__ */
+ USB_BUS_UNLOCK(bus);
+
+ device_printf(bus->bdev, "Controller shutdown complete\n");
+
return (0);
}
@@ -231,6 +335,9 @@ usb_bus_explore(struct usb_proc_msg *pm)
bus = ((struct usb_bus_msg *)pm)->bus;
udev = bus->devices[USB_ROOT_HUB_ADDR];
+ if (bus->no_explore != 0)
+ return;
+
if (udev && udev->hub) {
if (bus->do_probe) {
@@ -301,6 +408,168 @@ usb_bus_detach(struct usb_proc_msg *pm)
bus->bdev = NULL;
}
+/*------------------------------------------------------------------------*
+ * usb_bus_suspend
+ *
+ * This function is used to suspend the USB contoller.
+ *------------------------------------------------------------------------*/
+static void
+usb_bus_suspend(struct usb_proc_msg *pm)
+{
+ struct usb_bus *bus;
+ struct usb_device *udev;
+ usb_error_t err;
+ uint8_t do_unlock;
+
+ bus = ((struct usb_bus_msg *)pm)->bus;
+ udev = bus->devices[USB_ROOT_HUB_ADDR];
+
+ if (udev == NULL || bus->bdev == NULL)
+ return;
+
+ USB_BUS_UNLOCK(bus);
+
+ /*
+ * We use the shutdown event here because the suspend and
+ * resume events are reserved for the USB port suspend and
+ * resume. The USB system suspend is implemented like full
+ * shutdown and all connected USB devices will be disconnected
+ * subsequently. At resume all USB devices will be
+ * re-connected again.
+ */
+
+ bus_generic_shutdown(bus->bdev);
+
+ do_unlock = usbd_enum_lock(udev);
+
+ err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX);
+ if (err)
+ device_printf(bus->bdev, "Could not unconfigure root HUB\n");
+
+ USB_BUS_LOCK(bus);
+ bus->hw_power_state = 0;
+ bus->no_explore = 1;
+ USB_BUS_UNLOCK(bus);
+
+ if (bus->methods->set_hw_power != NULL)
+ (bus->methods->set_hw_power) (bus);
+
+ if (bus->methods->set_hw_power_sleep != NULL)
+ (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SUSPEND);
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
+ USB_BUS_LOCK(bus);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bus_resume
+ *
+ * This function is used to resume the USB contoller.
+ *------------------------------------------------------------------------*/
+static void
+usb_bus_resume(struct usb_proc_msg *pm)
+{
+ struct usb_bus *bus;
+ struct usb_device *udev;
+ usb_error_t err;
+ uint8_t do_unlock;
+
+ bus = ((struct usb_bus_msg *)pm)->bus;
+ udev = bus->devices[USB_ROOT_HUB_ADDR];
+
+ if (udev == NULL || bus->bdev == NULL)
+ return;
+
+ USB_BUS_UNLOCK(bus);
+
+ do_unlock = usbd_enum_lock(udev);
+#if 0
+ DEVMETHOD(usb_take_controller, NULL); /* dummy */
+#endif
+ USB_TAKE_CONTROLLER(device_get_parent(bus->bdev));
+
+ USB_BUS_LOCK(bus);
+ bus->hw_power_state =
+ USB_HW_POWER_CONTROL |
+ USB_HW_POWER_BULK |
+ USB_HW_POWER_INTERRUPT |
+ USB_HW_POWER_ISOC |
+ USB_HW_POWER_NON_ROOT_HUB;
+ bus->no_explore = 0;
+ USB_BUS_UNLOCK(bus);
+
+ if (bus->methods->set_hw_power_sleep != NULL)
+ (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_RESUME);
+
+ if (bus->methods->set_hw_power != NULL)
+ (bus->methods->set_hw_power) (bus);
+
+ /* restore USB configuration to index 0 */
+ err = usbd_set_config_index(udev, 0);
+ if (err)
+ device_printf(bus->bdev, "Could not configure root HUB\n");
+
+ /* probe and attach */
+ err = usb_probe_and_attach(udev, USB_IFACE_INDEX_ANY);
+ if (err) {
+ device_printf(bus->bdev, "Could not probe and "
+ "attach root HUB\n");
+ }
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
+ USB_BUS_LOCK(bus);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bus_shutdown
+ *
+ * This function is used to shutdown the USB contoller.
+ *------------------------------------------------------------------------*/
+static void
+usb_bus_shutdown(struct usb_proc_msg *pm)
+{
+ struct usb_bus *bus;
+ struct usb_device *udev;
+ usb_error_t err;
+ uint8_t do_unlock;
+
+ bus = ((struct usb_bus_msg *)pm)->bus;
+ udev = bus->devices[USB_ROOT_HUB_ADDR];
+
+ if (udev == NULL || bus->bdev == NULL)
+ return;
+
+ USB_BUS_UNLOCK(bus);
+
+ bus_generic_shutdown(bus->bdev);
+
+ do_unlock = usbd_enum_lock(udev);
+
+ err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX);
+ if (err)
+ device_printf(bus->bdev, "Could not unconfigure root HUB\n");
+
+ USB_BUS_LOCK(bus);
+ bus->hw_power_state = 0;
+ bus->no_explore = 1;
+ USB_BUS_UNLOCK(bus);
+
+ if (bus->methods->set_hw_power != NULL)
+ (bus->methods->set_hw_power) (bus);
+
+ if (bus->methods->set_hw_power_sleep != NULL)
+ (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SHUTDOWN);
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
+ USB_BUS_LOCK(bus);
+}
+
static void
usb_power_wdog(void *arg)
{
@@ -370,7 +639,7 @@ usb_bus_attach(struct usb_proc_msg *pm)
case USB_REV_3_0:
speed = USB_SPEED_SUPER;
- device_printf(bus->bdev, "4.8Gbps Super Speed USB v3.0\n");
+ device_printf(bus->bdev, "5.0Gbps Super Speed USB v3.0\n");
break;
default:
@@ -379,8 +648,6 @@ usb_bus_attach(struct usb_proc_msg *pm)
return;
}
- USB_BUS_UNLOCK(bus);
-
/* default power_mask value */
bus->hw_power_state =
USB_HW_POWER_CONTROL |
@@ -389,13 +656,15 @@ usb_bus_attach(struct usb_proc_msg *pm)
USB_HW_POWER_ISOC |
USB_HW_POWER_NON_ROOT_HUB;
+ USB_BUS_UNLOCK(bus);
+
/* make sure power is set at least once */
if (bus->methods->set_hw_power != NULL) {
(bus->methods->set_hw_power) (bus);
}
- /* Allocate the Root USB device */
+ /* allocate the Root USB device */
child = usb_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
speed, USB_MODE_HOST);
@@ -442,6 +711,9 @@ usb_attach_sub(device_t dev, struct usb_bus *bus)
usb_devclass_ptr = devclass_find("usbus");
mtx_unlock(&Giant);
+#if USB_HAVE_PF
+ usbpf_attach(bus);
+#endif
/* Initialise USB process messages */
bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
bus->explore_msg[0].bus = bus;
@@ -458,31 +730,44 @@ usb_attach_sub(device_t dev, struct usb_bus *bus)
bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach;
bus->attach_msg[1].bus = bus;
+ bus->suspend_msg[0].hdr.pm_callback = &usb_bus_suspend;
+ bus->suspend_msg[0].bus = bus;
+ bus->suspend_msg[1].hdr.pm_callback = &usb_bus_suspend;
+ bus->suspend_msg[1].bus = bus;
+
+ bus->resume_msg[0].hdr.pm_callback = &usb_bus_resume;
+ bus->resume_msg[0].bus = bus;
+ bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume;
+ bus->resume_msg[1].bus = bus;
+
+ bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown;
+ bus->shutdown_msg[0].bus = bus;
+ bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown;
+ bus->shutdown_msg[1].bus = bus;
+
/* Create USB explore and callback processes */
if (usb_proc_create(&bus->giant_callback_proc,
&bus->bus_mtx, pname, USB_PRI_MED)) {
- printf("WARNING: Creation of USB Giant "
+ device_printf(dev, "WARNING: Creation of USB Giant "
"callback process failed.\n");
} else if (usb_proc_create(&bus->non_giant_callback_proc,
&bus->bus_mtx, pname, USB_PRI_HIGH)) {
- printf("WARNING: Creation of USB non-Giant "
+ device_printf(dev, "WARNING: Creation of USB non-Giant "
"callback process failed.\n");
} else if (usb_proc_create(&bus->explore_proc,
&bus->bus_mtx, pname, USB_PRI_MED)) {
- printf("WARNING: Creation of USB explore "
+ device_printf(dev, "WARNING: Creation of USB explore "
"process failed.\n");
} else if (usb_proc_create(&bus->control_xfer_proc,
&bus->bus_mtx, pname, USB_PRI_MED)) {
- printf("WARNING: Creation of USB control transfer "
+ device_printf(dev, "WARNING: Creation of USB control transfer "
"process failed.\n");
} else {
/* Get final attach going */
USB_BUS_LOCK(bus);
- if (usb_proc_msignal(&bus->explore_proc,
- &bus->attach_msg[0], &bus->attach_msg[1])) {
- /* ignore */
- }
+ usb_proc_msignal(&bus->explore_proc,
+ &bus->attach_msg[0], &bus->attach_msg[1]);
USB_BUS_UNLOCK(bus);
/* Do initial explore */
diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c
index 6f50452b..6ae14acf 100644
--- a/freebsd/sys/dev/usb/quirk/usb_quirk.c
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c
@@ -36,7 +36,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -97,11 +96,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC),
USB_QUIRK(LOGITECH, UN53B, 0x0000, 0xffff, UQ_NO_STRINGS),
USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
-
- /*
- * XXX The following quirks should have a more specific revision
- * number:
- */
+ /* Quirks for printer devices */
USB_QUIRK(HP, 895C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
USB_QUIRK(HP, 880C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
USB_QUIRK(HP, 815C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
@@ -130,6 +125,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(METAGEEK2, WISPYDBX, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
USB_QUIRK(TENX, UAUDIO0, 0x0101, 0x0101, UQ_AUDIO_SWAP_LR),
/* MS keyboards do weird things */
+ USB_QUIRK(MICROSOFT, NATURAL4000, 0x0000, 0xFFFF, UQ_KBD_BOOTPROTO),
USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, UQ_MS_LEADING_BYTE),
/* umodem(4) device quirks */
USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
@@ -139,7 +135,9 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(SIEMENS2, ES75, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
USB_QUIRK(QUALCOMM, CDMA_MSM, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
USB_QUIRK(QUALCOMM2, CDMA_MSM, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
+ USB_QUIRK(CURITEL, UM150, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
USB_QUIRK(CURITEL, UM175, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
+ USB_QUIRK(VERTEX, VW110L, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
/* USB Mass Storage Class Quirks */
USB_QUIRK_VP(USB_VENDOR_ASAHIOPTICAL, 0, UQ_MSC_NO_RS_CLEAR_UA,
@@ -154,12 +152,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(AIPTEK, POCKETCAM3M, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
- USB_QUIRK(AIPTEK2, SUNPLUS_TECH, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ALCOR, SDCR_6335, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
- UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ALCOR, SDCR_6362, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
- UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ALCOR, AU6390, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(ALCOR, UMCR_9361, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(ALCOR, TRANSCEND, 0x0142, 0x0142, UQ_MSC_FORCE_WIRE_BBB,
@@ -181,22 +173,21 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(CENTURY, EX35QUAT, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
- USB_QUIRK(CENTURY, EX35SW4_SB4, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(CYPRESS, XX6830XX, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(DESKNOTE, UCR_61S2B, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(DMI, CFSM_RW, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_GETMAXLUN),
- USB_QUIRK(DMI, DISK, 0x000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
+ USB_QUIRK(EMTEC, RUF2PS, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(EPSON, STYLUS_875DC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(EPSON, STYLUS_895, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(FEIYA, 5IN1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
+ USB_QUIRK(FEIYA, ELANGO, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(FREECOM, DVD, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
- USB_QUIRK(FREECOM, HDD, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(FUJIPHOTO, MASS0100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(GENESYS, GL641USB2IDE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -240,7 +231,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */
- USB_QUIRK(JMICRON, JM20336, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_SYNC_CACHE),
@@ -287,8 +277,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_ATAPI),
USB_QUIRK(MYSON, HEDEN, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(MYSON, HEDEN_8813, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(MYSON, STARREADER, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(NEODIO, ND3260, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ),
USB_QUIRK(NETAC, CF_CARD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -315,7 +303,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(ONSPEC, READER, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(ONSPEC, UCF100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
- UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY | UQ_MSC_NO_GETMAXLUN),
+ UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(ONSPEC2, IMAGEMATE_SDDR55, 0x0000, 0xffff,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(PANASONIC, KXL840AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -325,7 +313,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(PANASONIC, KXLCB35AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(PANASONIC, LS120CAM, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_UFI),
- USB_QUIRK(PHILIPS, SPE3030CC, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(PLEXTOR, 40_12_40U, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY),
USB_QUIRK(PNY, ATTACHE2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -336,7 +323,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN,
USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
- USB_QUIRK(SAMSUNG, YP_U4, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(SANDISK, SDDR05A, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
UQ_MSC_NO_GETMAXLUN),
@@ -353,6 +339,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
USB_QUIRK(SANDISK, SDDR31, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
+ USB_QUIRK(SANDISK, IMAGEMATE_SDDR289, 0x0000, 0xffff,
+ UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(SCANLOGIC, SL11R, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(SHUTTLE, EUSB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
@@ -456,12 +444,39 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_ATAPI),
USB_QUIRK(MEIZU, M6_SL, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ACTIONS, MP4, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
- UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ASUS, GMSC, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(CHIPSBANK, USBMEMSTICK, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(CHIPSBANK, USBMEMSTICK1, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(NEWLINK, USB2IDEBRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
+
+ /* Non-standard USB MIDI devices */
+ USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, SC8850, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, SD90, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, UM880N, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, UA100, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, UM4, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, U8, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, UM2, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, SC8820, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, PC300, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, SK500, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, SCD70, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, UM550, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, SD20, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, SD80, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(ROLAND, UA700, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(MEDELI, DD305, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY),
+
+ /* Non-standard USB AUDIO devices */
+ USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+
+ /*
+ * Quirks for manufacturers which USB devices does not respond
+ * after issuing non-supported commands:
+ */
+ USB_QUIRK(ALCOR, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_TEST_UNIT_READY, UQ_MATCH_VENDOR_ONLY),
+ USB_QUIRK(APPLE, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
+ USB_QUIRK(FEIYA, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
+ USB_QUIRK(REALTEK, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
+ USB_QUIRK(INITIO, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
};
#undef USB_QUIRK_VP
#undef USB_QUIRK
@@ -480,6 +495,7 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = {
[UQ_HID_IGNORE] = "UQ_HID_IGNORE",
[UQ_KBD_IGNORE] = "UQ_KBD_IGNORE",
[UQ_KBD_BOOTPROTO] = "UQ_KBD_BOOTPROTO",
+ [UQ_UMS_IGNORE] = "UQ_UMS_IGNORE",
[UQ_MS_BAD_CLASS] = "UQ_MS_BAD_CLASS",
[UQ_MS_LEADING_BYTE] = "UQ_MS_LEADING_BYTE",
[UQ_MS_REVZ] = "UQ_MS_REVZ",
@@ -526,6 +542,9 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = {
[UQ_MSC_EJECT_SAEL_M460] = "UQ_MSC_EJECT_SAEL_M460",
[UQ_MSC_EJECT_HUAWEISCSI] = "UQ_MSC_EJECT_HUAWEISCSI",
[UQ_MSC_EJECT_TCT] = "UQ_MSC_EJECT_TCT",
+ [UQ_BAD_MIDI] = "UQ_BAD_MIDI",
+ [UQ_AU_VENDOR_CLASS] = "UQ_AU_VENDOR_CLASS",
+ [UQ_SINGLE_CMD_MIDI] = "UQ_SINGLE_CMD_MIDI",
};
/*------------------------------------------------------------------------*
@@ -553,9 +572,9 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
uint16_t x;
uint16_t y;
- if (quirk == UQ_NONE) {
- return (0);
- }
+ if (quirk == UQ_NONE)
+ goto done;
+
mtx_lock(&usb_quirk_mtx);
for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
@@ -589,7 +608,8 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
break;
}
mtx_unlock(&usb_quirk_mtx);
- return (0);
+done:
+ return (0); /* no quirk match */
}
static struct usb_quirk_entry *
@@ -770,7 +790,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data,
}
if (x == USB_SUB_QUIRKS_MAX) {
/* all quirk entries are unused - release */
- memset(pqe, 0, sizeof(pqe));
+ memset(pqe, 0, sizeof(*pqe));
}
mtx_unlock(&usb_quirk_mtx);
return (0); /* success */
diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.h b/freebsd/sys/dev/usb/quirk/usb_quirk.h
index 522b15a4..f2c10dd8 100644
--- a/freebsd/sys/dev/usb/quirk/usb_quirk.h
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.h
@@ -29,7 +29,7 @@
enum {
/*
- * Keep in sync with theusb_quirk_str usb_quirk.c, and with the
+ * Keep in sync with usb_quirk_str in usb_quirk.c, and with
* share/man/man4/usb_quirk.4
*/
UQ_NONE, /* not a valid quirk */
@@ -49,6 +49,7 @@ enum {
UQ_HID_IGNORE, /* device should be ignored by hid class */
UQ_KBD_IGNORE, /* device should be ignored by kbd class */
UQ_KBD_BOOTPROTO, /* device should set the boot protocol */
+ UQ_UMS_IGNORE, /* device should be ignored by ums class */
UQ_MS_BAD_CLASS, /* doesn't identify properly */
UQ_MS_LEADING_BYTE, /* mouse sends an unknown leading byte */
UQ_MS_REVZ, /* mouse has Z-axis reversed */
@@ -64,7 +65,10 @@ enum {
UQ_CFG_INDEX_0, /* select configuration index 0 by default */
UQ_ASSUME_CM_OVER_DATA, /* assume cm over data feature */
- /* USB Mass Storage Quirks. See "storage/umass.c" for a detailed description. */
+ /*
+ * USB Mass Storage Quirks. See "storage/umass.c" for a
+ * detailed description.
+ */
UQ_MSC_NO_TEST_UNIT_READY, /* send start/stop instead of TUR */
UQ_MSC_NO_RS_CLEAR_UA, /* does not reset Unit Att. */
UQ_MSC_NO_START_STOP, /* does not support start/stop */
@@ -100,6 +104,10 @@ enum {
UQ_MSC_EJECT_HUAWEISCSI, /* ejects after Huawei SCSI command */
UQ_MSC_EJECT_TCT, /* ejects after TCT SCSI command */
+ UQ_BAD_MIDI, /* device claims MIDI class, but isn't */
+ UQ_AU_VENDOR_CLASS, /* audio device uses vendor and not audio class */
+ UQ_SINGLE_CMD_MIDI, /* at most one command per USB packet */
+
USB_QUIRK_MAX
};
diff --git a/freebsd/sys/dev/usb/storage/umass.c b/freebsd/sys/dev/usb/storage/umass.c
index f59062d9..9c448466 100644
--- a/freebsd/sys/dev/usb/storage/umass.c
+++ b/freebsd/sys/dev/usb/storage/umass.c
@@ -112,7 +112,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -177,9 +176,8 @@ __FBSDID("$FreeBSD$");
static int umass_debug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass");
-SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&umass_debug, 0, "umass debug level");
-
TUNABLE_INT("hw.usb.umass.debug", &umass_debug);
#else
#define DIF(...) do { } while (0)
@@ -726,6 +724,11 @@ MODULE_VERSION(umass, 1);
* USB device probe/attach/detach
*/
+static const STRUCT_USB_HOST_ID __used umass_devs[] = {
+ /* generic mass storage class */
+ {USB_IFACE_CLASS(UICLASS_MASS),},
+};
+
static uint16_t
umass_get_proto(struct usb_interface *iface)
{
@@ -787,6 +790,7 @@ umass_probe_proto(device_t dev, struct usb_attach_arg *uaa)
uint32_t proto = umass_get_proto(uaa->iface);
memset(&ret, 0, sizeof(ret));
+ ret.error = BUS_PROBE_GENERIC;
/* Search for protocol enforcement */
@@ -875,10 +879,6 @@ umass_probe(device_t dev)
if (uaa->usb_mode != USB_MODE_HOST) {
return (ENXIO);
}
- if (uaa->use_generic == 0) {
- /* give other drivers a try first */
- return (ENXIO);
- }
temp = umass_probe_proto(dev, uaa);
return (temp.error);
@@ -894,7 +894,7 @@ umass_attach(device_t dev)
int32_t err;
/*
- * NOTE: the softc struct is bzero-ed in device_set_driver.
+ * NOTE: the softc struct is cleared in device_set_driver.
* We can safely call umass_detach without specifically
* initializing the struct.
*/
@@ -1028,12 +1028,6 @@ umass_attach(device_t dev)
sc->cam_scsi_sense.opcode = REQUEST_SENSE;
sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY;
- /*
- * some devices need a delay after that the configuration value is
- * set to function properly:
- */
- usb_pause_mtx(NULL, hz);
-
/* register the SIM */
err = umass_cam_attach_sim(sc);
if (err) {
@@ -1316,11 +1310,13 @@ umass_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
}
sc->cbw.bCDBLength = sc->sc_transfer.cmd_len;
- bcopy(sc->sc_transfer.cmd_data, sc->cbw.CBWCDB,
+ memcpy(sc->cbw.CBWCDB, sc->sc_transfer.cmd_data,
sc->sc_transfer.cmd_len);
- bzero(sc->sc_transfer.cmd_data + sc->sc_transfer.cmd_len,
- sizeof(sc->cbw.CBWCDB) - sc->sc_transfer.cmd_len);
+ memset(sc->sc_transfer.cmd_data +
+ sc->sc_transfer.cmd_len, 0,
+ sizeof(sc->cbw.CBWCDB) -
+ sc->sc_transfer.cmd_len);
DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw));
@@ -1491,9 +1487,9 @@ umass_t_bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
/* Zero missing parts of the CSW: */
- if (actlen < sizeof(sc->csw)) {
- bzero(&sc->csw, sizeof(sc->csw));
- }
+ if (actlen < (int)sizeof(sc->csw))
+ memset(&sc->csw, 0, sizeof(sc->csw));
+
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_out(pc, 0, &sc->csw, actlen);
@@ -1856,9 +1852,23 @@ umass_t_cbi_command_callback(struct usb_xfer *xfer, usb_error_t error)
break;
default: /* Error */
- umass_tr_error(xfer, error);
- /* skip reset */
- sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
+ /*
+ * STALL on the control pipe can be result of the command error.
+ * Attempt to clear this STALL same as for bulk pipe also
+ * results in command completion interrupt, but ASC/ASCQ there
+ * look like not always valid, so don't bother about it.
+ */
+ if ((error == USB_ERR_STALLED) ||
+ (sc->sc_transfer.callback == &umass_cam_cb)) {
+ sc->sc_transfer.ccb = NULL;
+ (sc->sc_transfer.callback)
+ (sc, ccb, sc->sc_transfer.data_len,
+ STATUS_CMD_UNKNOWN);
+ } else {
+ umass_tr_error(xfer, error);
+ /* skip reset */
+ sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
+ }
break;
}
}
@@ -2011,7 +2021,7 @@ umass_t_cbi_status_callback(struct usb_xfer *xfer, usb_error_t error)
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
- if (actlen < sizeof(sc->sbl)) {
+ if (actlen < (int)sizeof(sc->sbl)) {
goto tr_setup;
}
pc = usbd_xfer_get_frame(xfer, 0);
@@ -2616,17 +2626,9 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
/*
* The wire protocol failed and will hopefully have
* recovered. We return an error to CAM and let CAM
- * retry the command if necessary. In case of SCSI IO
- * commands we ask the CAM layer to check the
- * condition first. This is a quick hack to make
- * certain devices work.
+ * retry the command if necessary.
*/
- if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
- } else {
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- }
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
xpt_done(ccb);
break;
}
@@ -2761,7 +2763,7 @@ umass_scsi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
if (sc->sc_quirks & NO_TEST_UNIT_READY) {
DPRINTF(sc, UDMASS_SCSI, "Converted TEST_UNIT_READY "
"to START_UNIT\n");
- bzero(sc->sc_transfer.cmd_data, cmd_len);
+ memset(sc->sc_transfer.cmd_data, 0, cmd_len);
sc->sc_transfer.cmd_data[0] = START_STOP_UNIT;
sc->sc_transfer.cmd_data[4] = SSS_START;
return (1);
@@ -2774,14 +2776,14 @@ umass_scsi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
* information.
*/
if (sc->sc_quirks & FORCE_SHORT_INQUIRY) {
- bcopy(cmd_ptr, sc->sc_transfer.cmd_data, cmd_len);
+ memcpy(sc->sc_transfer.cmd_data, cmd_ptr, cmd_len);
sc->sc_transfer.cmd_data[4] = SHORT_INQUIRY_LENGTH;
return (1);
}
break;
}
- bcopy(cmd_ptr, sc->sc_transfer.cmd_data, cmd_len);
+ memcpy(sc->sc_transfer.cmd_data, cmd_ptr, cmd_len);
return (1);
}
@@ -2816,10 +2818,11 @@ umass_rbc_transform(struct umass_softc *sc, uint8_t *cmd_ptr, uint8_t cmd_len)
case REQUEST_SENSE:
case PREVENT_ALLOW:
- bcopy(cmd_ptr, sc->sc_transfer.cmd_data, cmd_len);
+ memcpy(sc->sc_transfer.cmd_data, cmd_ptr, cmd_len);
if ((sc->sc_quirks & RBC_PAD_TO_12) && (cmd_len < 12)) {
- bzero(sc->sc_transfer.cmd_data + cmd_len, 12 - cmd_len);
+ memset(sc->sc_transfer.cmd_data + cmd_len,
+ 0, 12 - cmd_len);
cmd_len = 12;
}
sc->sc_transfer.cmd_len = cmd_len;
@@ -2847,7 +2850,7 @@ umass_ufi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
sc->sc_transfer.cmd_len = UFI_COMMAND_LENGTH;
/* Zero the command data */
- bzero(sc->sc_transfer.cmd_data, UFI_COMMAND_LENGTH);
+ memset(sc->sc_transfer.cmd_data, 0, UFI_COMMAND_LENGTH);
switch (cmd_ptr[0]) {
/*
@@ -2904,7 +2907,7 @@ umass_ufi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
return (0); /* failure */
}
- bcopy(cmd_ptr, sc->sc_transfer.cmd_data, cmd_len);
+ memcpy(sc->sc_transfer.cmd_data, cmd_ptr, cmd_len);
return (1); /* success */
}
@@ -2925,7 +2928,7 @@ umass_atapi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
sc->sc_transfer.cmd_len = ATAPI_COMMAND_LENGTH;
/* Zero the command data */
- bzero(sc->sc_transfer.cmd_data, ATAPI_COMMAND_LENGTH);
+ memset(sc->sc_transfer.cmd_data, 0, ATAPI_COMMAND_LENGTH);
switch (cmd_ptr[0]) {
/*
@@ -2939,7 +2942,7 @@ umass_atapi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
* information.
*/
if (sc->sc_quirks & FORCE_SHORT_INQUIRY) {
- bcopy(cmd_ptr, sc->sc_transfer.cmd_data, cmd_len);
+ memcpy(sc->sc_transfer.cmd_data, cmd_ptr, cmd_len);
sc->sc_transfer.cmd_data[4] = SHORT_INQUIRY_LENGTH;
return (1);
@@ -3000,7 +3003,7 @@ umass_atapi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
break;
}
- bcopy(cmd_ptr, sc->sc_transfer.cmd_data, cmd_len);
+ memcpy(sc->sc_transfer.cmd_data, cmd_ptr, cmd_len);
return (1); /* success */
}
diff --git a/freebsd/sys/dev/usb/usb.h b/freebsd/sys/dev/usb/usb.h
index 433a0471..2f216d27 100644
--- a/freebsd/sys/dev/usb/usb.h
+++ b/freebsd/sys/dev/usb/usb.h
@@ -93,31 +93,29 @@ MALLOC_DECLARE(M_USBHC);
#define USB_POWER_MODE_SUSPEND 3 /* force suspend */
#define USB_POWER_MODE_RESUME 4 /* force resume */
-#if 0
/* These are the values from the USB specification. */
-#define USB_PORT_RESET_DELAY 10 /* ms */
-#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */
-#define USB_PORT_RESET_RECOVERY 10 /* ms */
-#define USB_PORT_POWERUP_DELAY 100 /* ms */
-#define USB_PORT_RESUME_DELAY 20 /* ms */
-#define USB_SET_ADDRESS_SETTLE 2 /* ms */
-#define USB_RESUME_DELAY (20*5) /* ms */
-#define USB_RESUME_WAIT 10 /* ms */
-#define USB_RESUME_RECOVERY 10 /* ms */
-#define USB_EXTRA_POWER_UP_TIME 0 /* ms */
-#else
+#define USB_PORT_RESET_DELAY_SPEC 10 /* ms */
+#define USB_PORT_ROOT_RESET_DELAY_SPEC 50 /* ms */
+#define USB_PORT_RESET_RECOVERY_SPEC 10 /* ms */
+#define USB_PORT_POWERUP_DELAY_SPEC 100 /* ms */
+#define USB_PORT_RESUME_DELAY_SPEC 20 /* ms */
+#define USB_SET_ADDRESS_SETTLE_SPEC 2 /* ms */
+#define USB_RESUME_DELAY_SPEC (20*5) /* ms */
+#define USB_RESUME_WAIT_SPEC 10 /* ms */
+#define USB_RESUME_RECOVERY_SPEC 10 /* ms */
+#define USB_EXTRA_POWER_UP_TIME_SPEC 0 /* ms */
+
/* Allow for marginal and non-conforming devices. */
-#define USB_PORT_RESET_DELAY 50 /* ms */
-#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */
-#define USB_PORT_RESET_RECOVERY 250 /* ms */
-#define USB_PORT_POWERUP_DELAY 300 /* ms */
-#define USB_PORT_RESUME_DELAY (20*2) /* ms */
-#define USB_SET_ADDRESS_SETTLE 10 /* ms */
-#define USB_RESUME_DELAY (50*5) /* ms */
-#define USB_RESUME_WAIT 50 /* ms */
-#define USB_RESUME_RECOVERY 50 /* ms */
-#define USB_EXTRA_POWER_UP_TIME 20 /* ms */
-#endif
+#define USB_PORT_RESET_DELAY 50 /* ms */
+#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */
+#define USB_PORT_RESET_RECOVERY 250 /* ms */
+#define USB_PORT_POWERUP_DELAY 300 /* ms */
+#define USB_PORT_RESUME_DELAY (20*2) /* ms */
+#define USB_SET_ADDRESS_SETTLE 10 /* ms */
+#define USB_RESUME_DELAY (50*5) /* ms */
+#define USB_RESUME_WAIT 50 /* ms */
+#define USB_RESUME_RECOVERY 50 /* ms */
+#define USB_EXTRA_POWER_UP_TIME 20 /* ms */
#define USB_MIN_POWER 100 /* mA */
#define USB_MAX_POWER 500 /* mA */
@@ -323,7 +321,7 @@ struct usb_devcap_usb2ext_descriptor {
uByte bLength;
uByte bDescriptorType;
uByte bDevCapabilityType;
- uByte bmAttributes;
+ uDWord bmAttributes;
#define USB_V2EXT_LPM 0x02
} __packed;
typedef struct usb_devcap_usb2ext_descriptor usb_devcap_usb2ext_descriptor_t;
@@ -336,7 +334,7 @@ struct usb_devcap_ss_descriptor {
uWord wSpeedsSupported;
uByte bFunctionalitySupport;
uByte bU1DevExitLat;
- uByte bU2DevExitLat;
+ uWord wU2DevExitLat;
} __packed;
typedef struct usb_devcap_ss_descriptor usb_devcap_ss_descriptor_t;
@@ -686,7 +684,9 @@ struct usb_port_status {
#define UPS_PORT_LS_HOT_RST 0x09
#define UPS_PORT_LS_COMP_MODE 0x0A
#define UPS_PORT_LS_LOOPBACK 0x0B
+#define UPS_PORT_LS_RESUME 0x0F
#define UPS_PORT_POWER 0x0100
+#define UPS_PORT_POWER_SS 0x0200 /* super-speed only */
#define UPS_LOW_SPEED 0x0200
#define UPS_HIGH_SPEED 0x0400
#define UPS_OTHER_SPEED 0x0600 /* currently FreeBSD specific */
diff --git a/freebsd/sys/dev/usb/usb_bus.h b/freebsd/sys/dev/usb/usb_bus.h
index c9840fcb..459219bd 100644
--- a/freebsd/sys/dev/usb/usb_bus.h
+++ b/freebsd/sys/dev/usb/usb_bus.h
@@ -71,6 +71,9 @@ struct usb_bus {
struct usb_bus_msg explore_msg[2];
struct usb_bus_msg detach_msg[2];
struct usb_bus_msg attach_msg[2];
+ struct usb_bus_msg suspend_msg[2];
+ struct usb_bus_msg resume_msg[2];
+ struct usb_bus_msg shutdown_msg[2];
/*
* This mutex protects the USB hardware:
*/
@@ -88,6 +91,8 @@ struct usb_bus {
struct usb_bus_methods *methods; /* filled by HC driver */
struct usb_device **devices;
+ struct ifnet *ifp; /* only for USB Packet Filter */
+
usb_power_mask_t hw_power_state; /* see USB_HW_POWER_XXX */
usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
@@ -98,17 +103,8 @@ struct usb_bus {
enum usb_revision usbrev; /* USB revision. See "USB_REV_XXX". */
uint8_t devices_max; /* maximum number of USB devices */
- uint8_t do_probe; /* set if USB BUS should be re-probed */
-
- /*
- * The scratch area can only be used inside the explore thread
- * belonging to the give serial bus.
- */
- union {
- struct usb_hw_ep_scratch hw_ep_scratch[1];
- struct usb_temp_setup temp_setup[1];
- uint8_t data[255];
- } scratch[1];
+ uint8_t do_probe; /* set if USB should be re-probed */
+ uint8_t no_explore; /* don't explore USB ports */
};
#endif /* _USB_BUS_H_ */
diff --git a/freebsd/sys/dev/usb/usb_busdma.c b/freebsd/sys/dev/usb/usb_busdma.c
index e08bcbd3..4aa8e1f4 100644
--- a/freebsd/sys/dev/usb/usb_busdma.c
+++ b/freebsd/sys/dev/usb/usb_busdma.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -83,9 +82,9 @@ void
usbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
struct usb_page_search *res)
{
+#if USB_HAVE_BUSDMA
struct usb_page *page;
-#if USB_HAVE_BUSDMA
if (pc->page_start) {
/* Case 1 - something has been loaded into DMA */
@@ -111,7 +110,7 @@ usbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
res->length = USB_PAGE_SIZE - offset;
res->physaddr = page->physaddr + offset;
} else {
- res->length = 0 - 1;
+ res->length = (usb_size_t)-1;
res->physaddr = page->physaddr + offset;
}
if (!pc->buffer) {
@@ -126,7 +125,7 @@ usbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
/* Case 2 - Plain PIO */
res->buffer = USB_ADD_BYTES(pc->buffer, offset);
- res->length = 0 - 1;
+ res->length = (usb_size_t)-1;
#if USB_HAVE_BUSDMA
res->physaddr = 0;
#endif
@@ -148,7 +147,7 @@ usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
if (buf_res.length > len) {
buf_res.length = len;
}
- bcopy(ptr, buf_res.buffer, buf_res.length);
+ memcpy(buf_res.buffer, ptr, buf_res.length);
offset += buf_res.length;
len -= buf_res.length;
@@ -270,7 +269,7 @@ usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset,
if (res.length > len) {
res.length = len;
}
- bcopy(res.buffer, ptr, res.length);
+ memcpy(ptr, res.buffer, res.length);
offset += res.length;
len -= res.length;
@@ -328,7 +327,7 @@ usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
if (res.length > len) {
res.length = len;
}
- bzero(res.buffer, res.length);
+ memset(res.buffer, 0, res.length);
offset += res.length;
len -= res.length;
@@ -563,7 +562,7 @@ usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
bus_dmamem_free(utag->tag, ptr, map);
goto error;
}
- bzero(ptr, size);
+ memset(ptr, 0, size);
usb_pc_cpu_flush(pc);
@@ -800,7 +799,7 @@ usb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
struct mtx *mtx, usb_dma_callback_t *func,
uint8_t ndmabits, uint8_t nudt)
{
- bzero(udpt, sizeof(*udpt));
+ memset(udpt, 0, sizeof(*udpt));
/* sanity checking */
if ((nudt == 0) ||
@@ -821,7 +820,7 @@ usb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
udpt->dma_bits = ndmabits;
while (nudt--) {
- bzero(udt, sizeof(*udt));
+ memset(udt, 0, sizeof(*udt));
udt->tag_parent = udpt;
udt++;
}
diff --git a/freebsd/sys/dev/usb/usb_cdc.h b/freebsd/sys/dev/usb/usb_cdc.h
index 23fd111c..b8f59fae 100644
--- a/freebsd/sys/dev/usb/usb_cdc.h
+++ b/freebsd/sys/dev/usb/usb_cdc.h
@@ -17,13 +17,6 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
diff --git a/freebsd/sys/dev/usb/usb_controller.h b/freebsd/sys/dev/usb/usb_controller.h
index 6b15dab9..ad871913 100644
--- a/freebsd/sys/dev/usb/usb_controller.h
+++ b/freebsd/sys/dev/usb/usb_controller.h
@@ -40,7 +40,6 @@ struct usb_page_cache;
struct usb_setup_params;
struct usb_hw_ep_profile;
struct usb_fs_isoc_schedule;
-struct usb_config_descriptor;
struct usb_endpoint_descriptor;
/* typedefs */
@@ -66,7 +65,7 @@ struct usb_bus_methods {
void (*device_suspend) (struct usb_device *);
void (*device_resume) (struct usb_device *);
void (*set_hw_power) (struct usb_bus *);
-
+ void (*set_hw_power_sleep) (struct usb_bus *, uint32_t);
/*
* The following flag is set if one or more control transfers are
* active:
@@ -92,6 +91,18 @@ struct usb_bus_methods {
* are present on the given USB bus:
*/
#define USB_HW_POWER_NON_ROOT_HUB 0x10
+ /*
+ * The following flag is set if we are suspending
+ */
+#define USB_HW_POWER_SUSPEND 0x20
+ /*
+ * The following flag is set if we are resuming
+ */
+#define USB_HW_POWER_RESUME 0x40
+ /*
+ * The following flag is set if we are shutting down
+ */
+#define USB_HW_POWER_SHUTDOWN 0x60
/* USB Device mode only - Mandatory */
@@ -169,57 +180,14 @@ struct usb_hw_ep_profile {
uint8_t support_out:1; /* OUT-token is supported */
};
-/*
- * The following structure is used when trying to allocate hardware
- * endpoints for an USB configuration in USB device side mode.
- */
-struct usb_hw_ep_scratch_sub {
- const struct usb_hw_ep_profile *pf;
- uint16_t max_frame_size;
- uint8_t hw_endpoint_out;
- uint8_t hw_endpoint_in;
- uint8_t needs_ep_type;
- uint8_t needs_in:1;
- uint8_t needs_out:1;
-};
-
-/*
- * The following structure is used when trying to allocate hardware
- * endpoints for an USB configuration in USB device side mode.
- */
-struct usb_hw_ep_scratch {
- struct usb_hw_ep_scratch_sub ep[USB_EP_MAX];
- struct usb_hw_ep_scratch_sub *ep_max;
- struct usb_config_descriptor *cd;
- struct usb_device *udev;
- struct usb_bus_methods *methods;
- uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16];
- uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16];
-};
-
-/*
- * The following structure is used when generating USB descriptors
- * from USB templates.
- */
-struct usb_temp_setup {
- void *buf;
- usb_size_t size;
- enum usb_dev_speed usb_speed;
- uint8_t self_powered;
- uint8_t bNumEndpoints;
- uint8_t bInterfaceNumber;
- uint8_t bAlternateSetting;
- uint8_t bConfigurationValue;
- usb_error_t err;
-};
-
/* prototypes */
void usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
uint8_t usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat, usb_bus_mem_cb_t *cb);
void usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
uint16_t usb_isoc_time_expand(struct usb_bus *bus, uint16_t isoc_time_curr);
-uint16_t usbd_fs_isoc_schedule_isoc_time_expand(struct usb_device *udev, struct usb_fs_isoc_schedule **pp_start, struct usb_fs_isoc_schedule **pp_end, uint16_t isoc_time);
-uint8_t usbd_fs_isoc_schedule_alloc(struct usb_fs_isoc_schedule *fss, uint8_t *pstart, uint16_t len);
+#if USB_HAVE_TT_SUPPORT
+uint8_t usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t isoc_time);
+#endif
#endif /* _USB_CONTROLLER_H_ */
diff --git a/freebsd/sys/dev/usb/usb_core.c b/freebsd/sys/dev/usb/usb_core.c
index 38504363..27e07adf 100644
--- a/freebsd/sys/dev/usb/usb_core.c
+++ b/freebsd/sys/dev/usb/usb_core.c
@@ -40,7 +40,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
diff --git a/freebsd/sys/dev/usb/usb_debug.c b/freebsd/sys/dev/usb/usb_debug.c
index 40dafa20..159bf7ea 100644
--- a/freebsd/sys/dev/usb/usb_debug.c
+++ b/freebsd/sys/dev/usb/usb_debug.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -66,11 +65,59 @@
int usb_debug = 0;
SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging");
-SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&usb_debug, 0, "Debug level");
-
TUNABLE_INT("hw.usb.debug", &usb_debug);
+#ifdef USB_DEBUG
+/*
+ * Sysctls to modify timings/delays
+ */
+static SYSCTL_NODE(_hw_usb, OID_AUTO, timings, CTLFLAG_RW, 0, "Timings");
+static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS);
+
+TUNABLE_INT("hw.usb.timings.port_reset_delay", (int *)&usb_port_reset_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_reset_delay, sizeof(usb_port_reset_delay),
+ usb_timings_sysctl_handler, "IU", "Port Reset Delay");
+TUNABLE_INT("hw.usb.timings.port_root_reset_delay", (int *)&usb_port_root_reset_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_root_reset_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_root_reset_delay, sizeof(usb_port_root_reset_delay),
+ usb_timings_sysctl_handler, "IU", "Root Port Reset Delay");
+TUNABLE_INT("hw.usb.timings.port_reset_recovery", (int *)&usb_port_reset_recovery);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_recovery, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_reset_recovery, sizeof(usb_port_reset_recovery),
+ usb_timings_sysctl_handler, "IU", "Port Reset Recovery");
+TUNABLE_INT("hw.usb.timings.port_powerup_delay", (int *)&usb_port_powerup_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_powerup_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_powerup_delay, sizeof(usb_port_powerup_delay),
+ usb_timings_sysctl_handler, "IU", "Port PowerUp Delay");
+TUNABLE_INT("hw.usb.timings.port_resume_delay", (int *)&usb_port_resume_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_resume_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_port_resume_delay, sizeof(usb_port_resume_delay),
+ usb_timings_sysctl_handler, "IU", "Port Resume Delay");
+TUNABLE_INT("hw.usb.timings.set_address_settle", (int *)&usb_set_address_settle);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, set_address_settle, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_set_address_settle, sizeof(usb_set_address_settle),
+ usb_timings_sysctl_handler, "IU", "Set Address Settle");
+TUNABLE_INT("hw.usb.timings.resume_delay", (int *)&usb_resume_delay);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_resume_delay, sizeof(usb_resume_delay),
+ usb_timings_sysctl_handler, "IU", "Resume Delay");
+TUNABLE_INT("hw.usb.timings.resume_wait", (int *)&usb_resume_wait);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_wait, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_resume_wait, sizeof(usb_resume_wait),
+ usb_timings_sysctl_handler, "IU", "Resume Wait");
+TUNABLE_INT("hw.usb.timings.resume_recovery", (int *)&usb_resume_recovery);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_recovery, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_resume_recovery, sizeof(usb_resume_recovery),
+ usb_timings_sysctl_handler, "IU", "Resume Recovery");
+TUNABLE_INT("hw.usb.timings.extra_power_up_time", (int *)&usb_extra_power_up_time);
+SYSCTL_PROC(_hw_usb_timings, OID_AUTO, extra_power_up_time, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN,
+ &usb_extra_power_up_time, sizeof(usb_extra_power_up_time),
+ usb_timings_sysctl_handler, "IU", "Extra PowerUp Time");
+#endif
+
/*------------------------------------------------------------------------*
* usb_dump_iface
*
@@ -177,3 +224,87 @@ usb_dump_xfer(struct usb_xfer *xfer)
xfer->endpoint->edesc->bEndpointAddress,
xfer->endpoint->edesc->bmAttributes);
}
+
+#ifdef USB_DEBUG
+unsigned int usb_port_reset_delay = USB_PORT_RESET_DELAY;
+unsigned int usb_port_root_reset_delay = USB_PORT_ROOT_RESET_DELAY;
+unsigned int usb_port_reset_recovery = USB_PORT_RESET_RECOVERY;
+unsigned int usb_port_powerup_delay = USB_PORT_POWERUP_DELAY;
+unsigned int usb_port_resume_delay = USB_PORT_RESUME_DELAY;
+unsigned int usb_set_address_settle = USB_SET_ADDRESS_SETTLE;
+unsigned int usb_resume_delay = USB_RESUME_DELAY;
+unsigned int usb_resume_wait = USB_RESUME_WAIT;
+unsigned int usb_resume_recovery = USB_RESUME_RECOVERY;
+unsigned int usb_extra_power_up_time = USB_EXTRA_POWER_UP_TIME;
+
+/*------------------------------------------------------------------------*
+ * usb_timings_sysctl_handler
+ *
+ * This function updates timings variables, adjusting them where necessary.
+ *------------------------------------------------------------------------*/
+static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+ unsigned int val;
+
+ /*
+ * Attempt to get a coherent snapshot by making a copy of the data.
+ */
+ if (arg1)
+ val = *(unsigned int *)arg1;
+ else
+ val = arg2;
+ error = SYSCTL_OUT(req, &val, sizeof(int));
+ if (error || !req->newptr)
+ return (error);
+
+ if (!arg1)
+ return EPERM;
+
+ error = SYSCTL_IN(req, &val, sizeof(unsigned int));
+ if (error)
+ return (error);
+
+ /*
+ * Now make sure the values are decent, and certainly no lower than
+ * what the USB spec prescribes.
+ */
+ unsigned int *p = (unsigned int *)arg1;
+ if (p == &usb_port_reset_delay) {
+ if (val < USB_PORT_RESET_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_port_root_reset_delay) {
+ if (val < USB_PORT_ROOT_RESET_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_port_reset_recovery) {
+ if (val < USB_PORT_RESET_RECOVERY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_port_powerup_delay) {
+ if (val < USB_PORT_POWERUP_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_port_resume_delay) {
+ if (val < USB_PORT_RESUME_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_set_address_settle) {
+ if (val < USB_SET_ADDRESS_SETTLE_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_resume_delay) {
+ if (val < USB_RESUME_DELAY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_resume_wait) {
+ if (val < USB_RESUME_WAIT_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_resume_recovery) {
+ if (val < USB_RESUME_RECOVERY_SPEC)
+ return (EINVAL);
+ } else if (p == &usb_extra_power_up_time) {
+ if (val < USB_EXTRA_POWER_UP_TIME_SPEC)
+ return (EINVAL);
+ } else {
+ /* noop */
+ }
+
+ *p = val;
+ return 0;
+}
+#endif
diff --git a/freebsd/sys/dev/usb/usb_debug.h b/freebsd/sys/dev/usb/usb_debug.h
index 8718c89b..038ba7f4 100644
--- a/freebsd/sys/dev/usb/usb_debug.h
+++ b/freebsd/sys/dev/usb/usb_debug.h
@@ -59,4 +59,28 @@ void usb_dump_queue(struct usb_endpoint *ep);
void usb_dump_endpoint(struct usb_endpoint *ep);
void usb_dump_xfer(struct usb_xfer *xfer);
+#ifdef USB_DEBUG
+extern unsigned int usb_port_reset_delay;
+extern unsigned int usb_port_root_reset_delay;
+extern unsigned int usb_port_reset_recovery;
+extern unsigned int usb_port_powerup_delay;
+extern unsigned int usb_port_resume_delay;
+extern unsigned int usb_set_address_settle;
+extern unsigned int usb_resume_delay;
+extern unsigned int usb_resume_wait;
+extern unsigned int usb_resume_recovery;
+extern unsigned int usb_extra_power_up_time;
+#else
+#define usb_port_reset_delay USB_PORT_RESET_DELAY
+#define usb_port_root_reset_delay USB_PORT_ROOT_RESET_DELAY
+#define usb_port_reset_recovery USB_PORT_RESET_RECOVERY
+#define usb_port_powerup_delay USB_PORT_POWERUP_DELAY
+#define usb_port_resume_delay USB_PORT_RESUME_DELAY
+#define usb_set_address_settle USB_SET_ADDRESS_SETTLE
+#define usb_resume_delay USB_RESUME_DELAY
+#define usb_resume_wait USB_RESUME_WAIT
+#define usb_resume_recovery USB_RESUME_RECOVERY
+#define usb_extra_power_up_time USB_EXTRA_POWER_UP_TIME
+#endif
+
#endif /* _USB_DEBUG_H_ */
diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c
index eaad5952..a22de719 100644
--- a/freebsd/sys/dev/usb/usb_dev.c
+++ b/freebsd/sys/dev/usb/usb_dev.c
@@ -37,7 +37,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -87,9 +86,8 @@
static int usb_fifo_debug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, dev, CTLFLAG_RW, 0, "USB device");
-SYSCTL_INT(_hw_usb_dev, OID_AUTO, debug, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb_dev, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&usb_fifo_debug, 0, "Debug Level");
-
TUNABLE_INT("hw.usb.dev.debug", &usb_fifo_debug);
#endif
@@ -220,10 +218,10 @@ usb_ref_device(struct usb_cdev_privdata *cpd,
mtx_unlock(&usb_ref_lock);
/*
- * We need to grab the sx-lock before grabbing the
- * FIFO refs to avoid deadlock at detach!
+ * We need to grab the enumeration SX-lock before
+ * grabbing the FIFO refs to avoid deadlock at detach!
*/
- usbd_enum_lock(cpd->udev);
+ crd->do_unlock = usbd_enum_lock(cpd->udev);
mtx_lock(&usb_ref_lock);
@@ -284,9 +282,10 @@ usb_ref_device(struct usb_cdev_privdata *cpd,
return (0);
error:
- if (crd->is_uref) {
+ if (crd->do_unlock)
usbd_enum_unlock(cpd->udev);
+ if (crd->is_uref) {
if (--(cpd->udev->refcount) == 0) {
cv_signal(&cpd->udev->ref_cv);
}
@@ -338,7 +337,7 @@ usb_unref_device(struct usb_cdev_privdata *cpd,
DPRINTFN(2, "cpd=%p is_uref=%d\n", cpd, crd->is_uref);
- if (crd->is_uref)
+ if (crd->do_unlock)
usbd_enum_unlock(cpd->udev);
mtx_lock(&usb_ref_lock);
@@ -916,10 +915,23 @@ usb_close(void *arg)
DPRINTFN(2, "cpd=%p\n", cpd);
- err = usb_ref_device(cpd, &refs, 1);
- if (err) {
- free(cpd, M_USBDEV);
- return;
+ err = usb_ref_device(cpd, &refs, 0);
+ if (err)
+ goto done;
+
+ /*
+ * If this function is not called directly from the root HUB
+ * thread, there is usually a need to lock the enumeration
+ * lock. Check this.
+ */
+ if (!usbd_enum_is_locked(cpd->udev)) {
+
+ DPRINTFN(2, "Locking enumeration\n");
+
+ /* reference device */
+ err = usb_usb_ref_device(cpd, &refs);
+ if (err)
+ goto done;
}
if (cpd->fflags & FREAD) {
usb_fifo_close(refs.rxfifo, cpd->fflags);
@@ -927,10 +939,9 @@ usb_close(void *arg)
if (cpd->fflags & FWRITE) {
usb_fifo_close(refs.txfifo, cpd->fflags);
}
-
usb_unref_device(cpd, &refs);
+done:
free(cpd, M_USBDEV);
- return;
}
static void
@@ -1646,14 +1657,13 @@ usb_fifo_check_methods(struct usb_fifo_methods *pm)
int
usb_fifo_attach(struct usb_device *udev, void *priv_sc,
struct mtx *priv_mtx, struct usb_fifo_methods *pm,
- struct usb_fifo_sc *f_sc, uint16_t unit, uint16_t subunit,
+ struct usb_fifo_sc *f_sc, uint16_t unit, int16_t subunit,
uint8_t iface_index, uid_t uid, gid_t gid, int mode)
{
struct usb_fifo *f_tx;
struct usb_fifo *f_rx;
char devname[32];
uint8_t n;
- struct usb_fs_privdata* pd;
f_sc->fp[USB_FIFO_TX] = NULL;
f_sc->fp[USB_FIFO_RX] = NULL;
@@ -1724,7 +1734,7 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc,
if (pm->basename[n] == NULL) {
continue;
}
- if (subunit == 0xFFFF) {
+ if (subunit < 0) {
if (snprintf(devname, sizeof(devname),
"%s%u%s", pm->basename[n],
unit, pm->postfix[n] ?
@@ -1733,7 +1743,7 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc,
}
} else {
if (snprintf(devname, sizeof(devname),
- "%s%u.%u%s", pm->basename[n],
+ "%s%u.%d%s", pm->basename[n],
unit, subunit, pm->postfix[n] ?
pm->postfix[n] : "")) {
/* ignore */
@@ -1751,22 +1761,10 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc,
usb_alloc_symlink(devname);
}
- /*
- * Initialize device private data - this is used to find the
- * actual USB device itself.
- */
- pd = malloc(sizeof(struct usb_fs_privdata), M_USBDEV, M_WAITOK | M_ZERO);
- pd->bus_index = device_get_unit(udev->bus->bdev);
- pd->dev_index = udev->device_index;
- pd->ep_addr = -1; /* not an endpoint */
- pd->fifo_index = f_tx->fifo_index & f_rx->fifo_index;
- pd->mode = FREAD|FWRITE;
-
- /* Now, create the device itself */
- f_sc->dev = make_dev(&usb_devsw, 0, uid, gid, mode,
- "%s", devname);
- /* XXX setting si_drv1 and creating the device is not atomic! */
- f_sc->dev->si_drv1 = pd;
+ /* Create the device */
+ f_sc->dev = usb_make_dev(udev, devname, -1,
+ f_tx->fifo_index & f_rx->fifo_index,
+ FREAD|FWRITE, uid, gid, mode);
}
DPRINTFN(2, "attached %p/%p\n", f_tx, f_rx);
@@ -1815,14 +1813,8 @@ usb_fifo_free_buffer(struct usb_fifo *f)
}
/* reset queues */
- bzero(&f->free_q, sizeof(f->free_q));
- bzero(&f->used_q, sizeof(f->used_q));
-}
-
-static void
-usb_fifo_cleanup(void* ptr)
-{
- free(ptr, M_USBDEV);
+ memset(&f->free_q, 0, sizeof(f->free_q));
+ memset(&f->used_q, 0, sizeof(f->used_q));
}
void
@@ -1837,11 +1829,9 @@ usb_fifo_detach(struct usb_fifo_sc *f_sc)
f_sc->fp[USB_FIFO_TX] = NULL;
f_sc->fp[USB_FIFO_RX] = NULL;
- if (f_sc->dev != NULL) {
- destroy_dev_sched_cb(f_sc->dev,
- usb_fifo_cleanup, f_sc->dev->si_drv1);
- f_sc->dev = NULL;
- }
+ usb_destroy_dev(f_sc->dev);
+
+ f_sc->dev = NULL;
DPRINTFN(2, "detached %p\n", f_sc);
}
@@ -1923,7 +1913,7 @@ usb_fifo_put_data_linear(struct usb_fifo *f, void *ptr,
io_len = MIN(len, m->cur_data_len);
- bcopy(ptr, m->cur_data_ptr, io_len);
+ memcpy(m->cur_data_ptr, ptr, io_len);
m->cur_data_len = io_len;
ptr = USB_ADD_BYTES(ptr, io_len);
@@ -2066,7 +2056,7 @@ usb_fifo_get_data_linear(struct usb_fifo *f, void *ptr,
io_len = MIN(len, m->cur_data_len);
- bcopy(m->cur_data_ptr, ptr, io_len);
+ memcpy(ptr, m->cur_data_ptr, io_len);
len -= io_len;
ptr = USB_ADD_BYTES(ptr, io_len);
diff --git a/freebsd/sys/dev/usb/usb_dev.h b/freebsd/sys/dev/usb/usb_dev.h
index aa9197f5..9a7cf210 100644
--- a/freebsd/sys/dev/usb/usb_dev.h
+++ b/freebsd/sys/dev/usb/usb_dev.h
@@ -82,6 +82,7 @@ struct usb_cdev_refdata {
uint8_t is_write; /* location has write access */
uint8_t is_uref; /* USB refcount decr. needed */
uint8_t is_usbfs; /* USB-FS is active */
+ uint8_t do_unlock; /* USB enum unlock needed */
};
struct usb_fs_privdata {
diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c
index a2db2727..a38e3d1c 100644
--- a/freebsd/sys/dev/usb/usb_device.c
+++ b/freebsd/sys/dev/usb/usb_device.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -90,7 +89,7 @@ static void usb_init_endpoint(struct usb_device *, uint8_t,
struct usb_endpoint *);
static void usb_unconfigure(struct usb_device *, uint8_t);
static void usb_detach_device_sub(struct usb_device *, device_t *,
- uint8_t);
+ char **, uint8_t);
static uint8_t usb_probe_and_attach_sub(struct usb_device *,
struct usb_attach_arg *);
static void usb_init_attach_arg(struct usb_device *,
@@ -100,13 +99,13 @@ static void usb_suspend_resume_sub(struct usb_device *, device_t,
static void usbd_clear_stall_proc(struct usb_proc_msg *_pm);
static usb_error_t usb_config_parse(struct usb_device *, uint8_t, uint8_t);
static void usbd_set_device_strings(struct usb_device *);
-#if USB_HAVE_UGEN
+#if USB_HAVE_DEVCTL
static void usb_notify_addq(const char *type, struct usb_device *);
+#endif
+#if USB_HAVE_UGEN
static void usb_fifo_free_wrap(struct usb_device *, uint8_t, uint8_t);
-static struct cdev *usb_make_dev(struct usb_device *, int, int);
static void usb_cdev_create(struct usb_device *);
static void usb_cdev_free(struct usb_device *);
-static void usb_cdev_cleanup(void *);
#endif
/* This variable is global to allow easy access to it: */
@@ -115,7 +114,7 @@ int usb_template = 0;
#ifndef __rtems__
TUNABLE_INT("hw.usb.usb_template", &usb_template);
-SYSCTL_INT(_hw_usb, OID_AUTO, template, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb, OID_AUTO, template, CTLFLAG_RW | CTLFLAG_TUN,
&usb_template, 0, "Selected USB device side template");
#endif /* __rtems__ */
@@ -126,11 +125,11 @@ static int usb_lang_mask = 0x00FF;
#ifndef __rtems__
TUNABLE_INT("hw.usb.usb_lang_id", &usb_lang_id);
-SYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_id, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_id, CTLFLAG_RW | CTLFLAG_TUN,
&usb_lang_id, 0, "Preferred USB language ID");
TUNABLE_INT("hw.usb.usb_lang_mask", &usb_lang_mask);
-SYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_mask, CTLFLAG_RW,
+SYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_mask, CTLFLAG_RW | CTLFLAG_TUN,
&usb_lang_mask, 0, "Preferred USB language mask");
#endif /* __rtems__ */
@@ -450,13 +449,8 @@ usb_unconfigure(struct usb_device *udev, uint8_t flag)
{
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
/* detach all interface drivers */
usb_detach_device(udev, USB_IFACE_INDEX_ANY, flag);
@@ -519,13 +513,8 @@ usbd_set_config_index(struct usb_device *udev, uint8_t index)
DPRINTFN(6, "udev=%p index=%d\n", udev, index);
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
usb_unconfigure(udev, 0);
@@ -757,10 +746,13 @@ usb_config_parse(struct usb_device *udev, uint8_t iface_index, uint8_t cmd)
if (do_init) {
/* setup the USB interface structure */
iface->idesc = id;
- /* default setting */
- iface->parent_iface_index = USB_IFACE_INDEX_ANY;
/* set alternate index */
iface->alt_index = alt_index;
+ /* set default interface parent */
+ if (iface_index == USB_IFACE_INDEX_ANY) {
+ iface->parent_iface_index =
+ USB_IFACE_INDEX_ANY;
+ }
}
DPRINTFN(5, "found idesc nendpt=%d\n", id->bNumEndpoints);
@@ -875,13 +867,9 @@ usbd_set_alt_interface_index(struct usb_device *udev,
usb_error_t err;
uint8_t do_unlock;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
+
if (iface == NULL) {
err = USB_ERR_INVAL;
goto done;
@@ -918,7 +906,6 @@ usbd_set_alt_interface_index(struct usb_device *udev,
done:
if (do_unlock)
usbd_enum_unlock(udev);
-
return (err);
}
@@ -1039,9 +1026,10 @@ usb_reset_iface_endpoints(struct usb_device *udev, uint8_t iface_index)
*------------------------------------------------------------------------*/
static void
usb_detach_device_sub(struct usb_device *udev, device_t *ppdev,
- uint8_t flag)
+ char **ppnpinfo, uint8_t flag)
{
device_t dev;
+ char *pnpinfo;
int err;
dev = *ppdev;
@@ -1073,11 +1061,17 @@ usb_detach_device_sub(struct usb_device *udev, device_t *ppdev,
goto error;
}
}
+
+ pnpinfo = *ppnpinfo;
+ if (pnpinfo != NULL) {
+ *ppnpinfo = NULL;
+ free(pnpinfo, M_USBDEV);
+ }
return;
error:
/* Detach is not allowed to fail in the USB world */
- panic("A USB driver would not detach\n");
+ panic("usb_detach_device_sub: A USB driver would not detach\n");
}
/*------------------------------------------------------------------------*
@@ -1126,7 +1120,8 @@ usb_detach_device(struct usb_device *udev, uint8_t iface_index,
/* looks like the end of the USB interfaces */
break;
}
- usb_detach_device_sub(udev, &iface->subdev, flag);
+ usb_detach_device_sub(udev, &iface->subdev,
+ &iface->pnpinfo, flag);
}
}
@@ -1228,17 +1223,20 @@ usbd_set_parent_iface(struct usb_device *udev, uint8_t iface_index,
{
struct usb_interface *iface;
+ if (udev == NULL) {
+ /* nothing to do */
+ return;
+ }
iface = usbd_get_iface(udev, iface_index);
- if (iface) {
+ if (iface != NULL)
iface->parent_iface_index = parent_index;
- }
}
static void
usb_init_attach_arg(struct usb_device *udev,
struct usb_attach_arg *uaa)
{
- bzero(uaa, sizeof(*uaa));
+ memset(uaa, 0, sizeof(*uaa));
uaa->device = udev;
uaa->usb_mode = udev->flags.usb_mode;
@@ -1278,13 +1276,8 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index)
DPRINTF("udev == NULL\n");
return (USB_ERR_INVAL);
}
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (udev->curr_config_index == USB_UNCONFIG_INDEX) {
/* do nothing - no configuration has been set */
@@ -1294,6 +1287,21 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index)
usb_init_attach_arg(udev, &uaa);
+ /*
+ * If the whole USB device is targeted, invoke the USB event
+ * handler(s):
+ */
+ if (iface_index == USB_IFACE_INDEX_ANY) {
+
+ EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa);
+
+ if (uaa.dev_state != UAA_DEV_READY) {
+ /* leave device unconfigured */
+ usb_unconfigure(udev, 0);
+ goto done;
+ }
+ }
+
/* Check if only one interface should be probed: */
if (iface_index != USB_IFACE_INDEX_ANY) {
i = iface_index;
@@ -1331,7 +1339,6 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index)
uaa.info.bIfaceIndex = i;
uaa.info.bIfaceNum =
iface->idesc->bInterfaceNumber;
- uaa.use_generic = 0;
uaa.driver_info = 0; /* reset driver_info */
DPRINTFN(2, "iclass=%u/%u/%u iindex=%u/%u\n",
@@ -1341,32 +1348,22 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index)
uaa.info.bIfaceIndex,
uaa.info.bIfaceNum);
- /* try specific interface drivers first */
-
- if (usb_probe_and_attach_sub(udev, &uaa)) {
- /* ignore */
- }
- /* try generic interface drivers last */
-
- uaa.use_generic = 1;
- uaa.driver_info = 0; /* reset driver_info */
-
- if (usb_probe_and_attach_sub(udev, &uaa)) {
- /* ignore */
- }
- }
+ usb_probe_and_attach_sub(udev, &uaa);
- if (uaa.temp_dev) {
- /* remove the last created child; it is unused */
-
- if (device_delete_child(udev->parent_dev, uaa.temp_dev)) {
+ /*
+ * Remove the leftover child, if any, to enforce that
+ * a new nomatch devd event is generated for the next
+ * interface if no driver is found:
+ */
+ if (uaa.temp_dev == NULL)
+ continue;
+ if (device_delete_child(udev->parent_dev, uaa.temp_dev))
DPRINTFN(0, "device delete child failed\n");
- }
+ uaa.temp_dev = NULL;
}
done:
if (do_unlock)
usbd_enum_unlock(udev);
-
return (0);
}
@@ -1490,12 +1487,12 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
struct usb_device *adev;
struct usb_device *hub;
uint8_t *scratch_ptr;
- size_t scratch_size;
usb_error_t err;
uint8_t device_index;
uint8_t config_index;
uint8_t config_quirk;
uint8_t set_config_failed;
+ uint8_t do_unlock;
DPRINTF("parent_dev=%p, bus=%p, parent_hub=%p, depth=%u, "
"port_index=%u, port_no=%u, speed=%u, usb_mode=%u\n",
@@ -1530,11 +1527,8 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
return (NULL);
}
/* initialise our SX-lock */
- sx_init_flags(&udev->ctrl_sx, "USB device SX lock", SX_DUPOK);
-
- /* initialise our SX-lock */
sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK);
- sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_DUPOK);
+ sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS);
cv_init(&udev->ctrlreq_cv, "WCTRL");
cv_init(&udev->ref_cv, "UGONE");
@@ -1618,10 +1612,12 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
LIST_INIT(&udev->pd_list);
/* Create the control endpoint device */
- udev->ctrl_dev = usb_make_dev(udev, 0, FREAD|FWRITE);
+ udev->ctrl_dev = usb_make_dev(udev, NULL, 0, 0,
+ FREAD|FWRITE, UID_ROOT, GID_OPERATOR, 0600);
/* Create a link from /dev/ugenX.X to the default endpoint */
- make_dev_alias(udev->ctrl_dev, "%s", udev->ugen_name);
+ if (udev->ctrl_dev != NULL)
+ make_dev_alias(udev->ctrl_dev->cdev, "%s", udev->ugen_name);
#endif
/* Initialise device */
if (bus->methods->device_init != NULL) {
@@ -1712,8 +1708,11 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
* device descriptor. If no strings are present there we
* simply disable all USB strings.
*/
- scratch_ptr = udev->bus->scratch[0].data;
- scratch_size = sizeof(udev->bus->scratch[0].data);
+
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
+
+ scratch_ptr = udev->scratch.data;
if (udev->ddesc.iManufacturer ||
udev->ddesc.iProduct ||
@@ -1738,7 +1737,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
mask = usb_lang_mask;
/* align length correctly */
- scratch_ptr[0] &= ~1;
+ scratch_ptr[0] &= ~1U;
/* fix compiler warning */
langid = 0;
@@ -1759,6 +1758,9 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
udev->langid = langid;
}
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
/* assume 100mA bus powered for now. Changed when configured. */
udev->power = USB_MIN_POWER;
/* fetch the vendor and product strings from the device */
@@ -1842,12 +1844,20 @@ repeat_set_config:
}
}
}
-#ifndef __rtems__
- EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa);
-#endif /* __rtems__ */
- if (uaa.dev_state != UAA_DEV_READY) {
- /* leave device unconfigured */
- usb_unconfigure(udev, 0);
+ if (set_config_failed == 0 && config_index == 0 &&
+ usb_test_quirk(&uaa, UQ_MSC_NO_SYNC_CACHE) == 0 &&
+ usb_test_quirk(&uaa, UQ_MSC_NO_GETMAXLUN) == 0) {
+
+ /*
+ * Try to figure out if there are any MSC quirks we
+ * should apply automatically:
+ */
+ err = usb_msc_auto_quirk(udev, 0);
+
+ if (err != 0) {
+ set_config_failed = 1;
+ goto repeat_set_config;
+ }
}
config_done:
@@ -1866,7 +1876,9 @@ config_done:
printf("%s: <%s> at %s\n", udev->ugen_name,
usb_get_manufacturer(udev),
device_get_nameunit(udev->bus->bdev));
+#endif
+#if USB_HAVE_DEVCTL
usb_notify_addq("ATTACH", udev);
#endif
done:
@@ -1881,11 +1893,12 @@ done:
}
#if USB_HAVE_UGEN
-static struct cdev *
-usb_make_dev(struct usb_device *udev, int ep, int mode)
+struct usb_fs_privdata *
+usb_make_dev(struct usb_device *udev, const char *devname, int ep,
+ int fi, int rwmode, uid_t uid, gid_t gid, int mode)
{
struct usb_fs_privdata* pd;
- char devname[20];
+ char buffer[32];
/* Store information to locate ourselves again later */
pd = malloc(sizeof(struct usb_fs_privdata), M_USBDEV,
@@ -1893,16 +1906,39 @@ usb_make_dev(struct usb_device *udev, int ep, int mode)
pd->bus_index = device_get_unit(udev->bus->bdev);
pd->dev_index = udev->device_index;
pd->ep_addr = ep;
- pd->mode = mode;
+ pd->fifo_index = fi;
+ pd->mode = rwmode;
/* Now, create the device itself */
- snprintf(devname, sizeof(devname), "%u.%u.%u",
- pd->bus_index, pd->dev_index, pd->ep_addr);
- pd->cdev = make_dev(&usb_devsw, 0, UID_ROOT,
- GID_OPERATOR, 0600, USB_DEVICE_DIR "/%s", devname);
+ if (devname == NULL) {
+ devname = buffer;
+ snprintf(buffer, sizeof(buffer), USB_DEVICE_DIR "/%u.%u.%u",
+ pd->bus_index, pd->dev_index, pd->ep_addr);
+ }
+
+ pd->cdev = make_dev(&usb_devsw, 0, uid, gid, mode, "%s", devname);
+
+ if (pd->cdev == NULL) {
+ DPRINTFN(0, "Failed to create device %s\n", devname);
+ free(pd, M_USBDEV);
+ return (NULL);
+ }
+
+ /* XXX setting si_drv1 and creating the device is not atomic! */
pd->cdev->si_drv1 = pd;
- return (pd->cdev);
+ return (pd);
+}
+
+void
+usb_destroy_dev(struct usb_fs_privdata *pd)
+{
+ if (pd == NULL)
+ return;
+
+ destroy_dev(pd->cdev);
+
+ free(pd, M_USBDEV);
}
static void
@@ -1912,7 +1948,6 @@ usb_cdev_create(struct usb_device *udev)
struct usb_endpoint_descriptor *ed;
struct usb_descriptor *desc;
struct usb_fs_privdata* pd;
- struct cdev *dev;
int inmode, outmode, inmask, outmask, mode;
uint8_t ep;
@@ -1954,14 +1989,16 @@ usb_cdev_create(struct usb_device *udev)
/* Create all available endpoints except EP0 */
for (ep = 1; ep < 16; ep++) {
- mode = inmask & (1 << ep) ? inmode : 0;
- mode |= outmask & (1 << ep) ? outmode : 0;
+ mode = (inmask & (1 << ep)) ? inmode : 0;
+ mode |= (outmask & (1 << ep)) ? outmode : 0;
if (mode == 0)
continue; /* no IN or OUT endpoint */
- dev = usb_make_dev(udev, ep, mode);
- pd = dev->si_drv1;
- LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next);
+ pd = usb_make_dev(udev, NULL, ep, 0,
+ mode, UID_ROOT, GID_OPERATOR, 0600);
+
+ if (pd != NULL)
+ LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next);
}
}
@@ -1969,25 +2006,16 @@ static void
usb_cdev_free(struct usb_device *udev)
{
struct usb_fs_privdata* pd;
- struct cdev* pcdev;
DPRINTFN(2, "Freeing device nodes\n");
while ((pd = LIST_FIRST(&udev->pd_list)) != NULL) {
KASSERT(pd->cdev->si_drv1 == pd, ("privdata corrupt"));
- pcdev = pd->cdev;
- pd->cdev = NULL;
LIST_REMOVE(pd, pd_next);
- if (pcdev != NULL)
- destroy_dev_sched_cb(pcdev, usb_cdev_cleanup, pd);
- }
-}
-static void
-usb_cdev_cleanup(void* arg)
-{
- free(arg, M_USBDEV);
+ usb_destroy_dev(pd);
+ }
}
#endif
@@ -2012,9 +2040,11 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
bus = udev->bus;
usb_set_device_state(udev, USB_STATE_DETACHED);
-#if USB_HAVE_UGEN
+#if USB_HAVE_DEVCTL
usb_notify_addq("DETACH", udev);
+#endif
+#if USB_HAVE_UGEN
printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name,
usb_get_manufacturer(udev), device_get_nameunit(bus->bdev));
@@ -2041,8 +2071,7 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
}
mtx_unlock(&usb_ref_lock);
- destroy_dev_sched_cb(udev->ctrl_dev, usb_cdev_cleanup,
- udev->ctrl_dev->si_drv1);
+ usb_destroy_dev(udev->ctrl_dev);
#endif
if (udev->flags.usb_mode == USB_MODE_DEVICE) {
@@ -2068,7 +2097,6 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
&udev->cs_msg[0], &udev->cs_msg[1]);
USB_BUS_UNLOCK(udev->bus);
- sx_destroy(&udev->ctrl_sx);
sx_destroy(&udev->enum_sx);
sx_destroy(&udev->sr_sx);
@@ -2231,9 +2259,13 @@ usbd_set_device_strings(struct usb_device *udev)
size_t temp_size;
uint16_t vendor_id;
uint16_t product_id;
+ uint8_t do_unlock;
+
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
- temp_ptr = (char *)udev->bus->scratch[0].data;
- temp_size = sizeof(udev->bus->scratch[0].data);
+ temp_ptr = (char *)udev->scratch.data;
+ temp_size = sizeof(udev->scratch.data);
vendor_id = UGETW(udd->idVendor);
product_id = UGETW(udd->idProduct);
@@ -2288,6 +2320,9 @@ usbd_set_device_strings(struct usb_device *udev)
snprintf(temp_ptr, temp_size, "product 0x%04x", product_id);
udev->product = strdup(temp_ptr, M_USB);
}
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
}
/*
@@ -2350,8 +2385,22 @@ uint8_t
usb_test_quirk(const struct usb_attach_arg *uaa, uint16_t quirk)
{
uint8_t found;
+ uint8_t x;
+
+ if (quirk == UQ_NONE)
+ return (0);
+
+ /* search the automatic per device quirks first */
+
+ for (x = 0; x != USB_MAX_AUTO_QUIRK; x++) {
+ if (uaa->device->autoQuirk[x] == quirk)
+ return (1);
+ }
+
+ /* search global quirk table, if any */
found = (usb_test_quirk_p) (&uaa->info, quirk);
+
return (found);
}
@@ -2381,7 +2430,7 @@ usbd_get_device_index(struct usb_device *udev)
return (udev->device_index);
}
-#if USB_HAVE_UGEN
+#if USB_HAVE_DEVCTL
/*------------------------------------------------------------------------*
* usb_notify_addq
*
@@ -2417,29 +2466,37 @@ usb_notify_addq_compat(const char *type, struct usb_device *udev)
/* String it all together. */
snprintf(data, buf_size,
"%s"
+#if USB_HAVE_UGEN
"%s "
+#endif
+ "at port=%u "
"vendor=0x%04x "
"product=0x%04x "
"devclass=0x%02x "
"devsubclass=0x%02x "
"sernum=\"%s\" "
"release=0x%04x "
- "at "
- "port=%u "
- "on "
- "%s\n",
+#if USB_HAVE_UGEN
+ "on %s\n"
+#endif
+ "",
ntype,
+#if USB_HAVE_UGEN
udev->ugen_name,
+#endif
+ udev->port_no,
UGETW(udev->ddesc.idVendor),
UGETW(udev->ddesc.idProduct),
udev->ddesc.bDeviceClass,
udev->ddesc.bDeviceSubClass,
usb_get_serial(udev),
- UGETW(udev->ddesc.bcdDevice),
- udev->port_no,
- udev->parent_hub != NULL ?
+ UGETW(udev->ddesc.bcdDevice)
+#if USB_HAVE_UGEN
+ , udev->parent_hub != NULL ?
udev->parent_hub->ugen_name :
- device_get_nameunit(device_get_parent(udev->bus->bdev)));
+ device_get_nameunit(device_get_parent(udev->bus->bdev))
+#endif
+ );
devctl_queue_data(data);
}
@@ -2459,7 +2516,10 @@ usb_notify_addq(const char *type, struct usb_device *udev)
/* announce the device */
sb = sbuf_new_auto();
sbuf_printf(sb,
+#if USB_HAVE_UGEN
+ "ugen=%s "
"cdev=%s "
+#endif
"vendor=0x%04x "
"product=0x%04x "
"devclass=0x%02x "
@@ -2468,8 +2528,14 @@ usb_notify_addq(const char *type, struct usb_device *udev)
"release=0x%04x "
"mode=%s "
"port=%u "
- "parent=%s\n",
+#if USB_HAVE_UGEN
+ "parent=%s"
+#endif
+ "",
+#if USB_HAVE_UGEN
udev->ugen_name,
+ udev->ugen_name,
+#endif
UGETW(udev->ddesc.idVendor),
UGETW(udev->ddesc.idProduct),
udev->ddesc.bDeviceClass,
@@ -2477,10 +2543,13 @@ usb_notify_addq(const char *type, struct usb_device *udev)
usb_get_serial(udev),
UGETW(udev->ddesc.bcdDevice),
(udev->flags.usb_mode == USB_MODE_HOST) ? "host" : "device",
- udev->port_no,
- udev->parent_hub != NULL ?
- udev->parent_hub->ugen_name :
- device_get_nameunit(device_get_parent(udev->bus->bdev)));
+ udev->port_no
+#if USB_HAVE_UGEN
+ , udev->parent_hub != NULL ?
+ udev->parent_hub->ugen_name :
+ device_get_nameunit(device_get_parent(udev->bus->bdev))
+#endif
+ );
sbuf_finish(sb);
devctl_notify("USB", "DEVICE", type, sbuf_data(sb));
sbuf_delete(sb);
@@ -2495,7 +2564,10 @@ usb_notify_addq(const char *type, struct usb_device *udev)
sb = sbuf_new_auto();
sbuf_printf(sb,
+#if USB_HAVE_UGEN
+ "ugen=%s "
"cdev=%s "
+#endif
"vendor=0x%04x "
"product=0x%04x "
"devclass=0x%02x "
@@ -2507,8 +2579,11 @@ usb_notify_addq(const char *type, struct usb_device *udev)
"endpoints=%d "
"intclass=0x%02x "
"intsubclass=0x%02x "
- "intprotocol=0x%02x\n",
+ "intprotocol=0x%02x",
+#if USB_HAVE_UGEN
+ udev->ugen_name,
udev->ugen_name,
+#endif
UGETW(udev->ddesc.idVendor),
UGETW(udev->ddesc.idProduct),
udev->ddesc.bDeviceClass,
@@ -2526,7 +2601,9 @@ usb_notify_addq(const char *type, struct usb_device *udev)
sbuf_delete(sb);
}
}
+#endif
+#if USB_HAVE_UGEN
/*------------------------------------------------------------------------*
* usb_fifo_free_wrap
*
@@ -2633,11 +2710,17 @@ usbd_device_attached(struct usb_device *udev)
return (udev->state > USB_STATE_DETACHED);
}
-/* The following function locks enumerating the given USB device. */
-
-void
+/*
+ * The following function locks enumerating the given USB device. If
+ * the lock is already grabbed this function returns zero. Else a
+ * non-zero value is returned.
+ */
+uint8_t
usbd_enum_lock(struct usb_device *udev)
{
+ if (sx_xlocked(&udev->enum_sx))
+ return (0);
+
sx_xlock(&udev->enum_sx);
sx_xlock(&udev->sr_sx);
/*
@@ -2646,6 +2729,7 @@ usbd_enum_lock(struct usb_device *udev)
* locked multiple times.
*/
mtx_lock(&Giant);
+ return (1);
}
/* The following function unlocks enumerating the given USB device. */
@@ -2691,3 +2775,51 @@ usbd_enum_is_locked(struct usb_device *udev)
{
return (sx_xlocked(&udev->enum_sx));
}
+
+/*
+ * The following function is used to set the per-interface specific
+ * plug and play information. The string referred to by the pnpinfo
+ * argument can safely be freed after calling this function. The
+ * pnpinfo of an interface will be reset at device detach or when
+ * passing a NULL argument to this function. This function
+ * returns zero on success, else a USB_ERR_XXX failure code.
+ */
+
+usb_error_t
+usbd_set_pnpinfo(struct usb_device *udev, uint8_t iface_index, const char *pnpinfo)
+{
+ struct usb_interface *iface;
+
+ iface = usbd_get_iface(udev, iface_index);
+ if (iface == NULL)
+ return (USB_ERR_INVAL);
+
+ if (iface->pnpinfo != NULL) {
+ free(iface->pnpinfo, M_USBDEV);
+ iface->pnpinfo = NULL;
+ }
+
+ if (pnpinfo == NULL || pnpinfo[0] == 0)
+ return (0); /* success */
+
+ iface->pnpinfo = strdup(pnpinfo, M_USBDEV);
+ if (iface->pnpinfo == NULL)
+ return (USB_ERR_NOMEM);
+
+ return (0); /* success */
+}
+
+usb_error_t
+usbd_add_dynamic_quirk(struct usb_device *udev, uint16_t quirk)
+{
+ uint8_t x;
+
+ for (x = 0; x != USB_MAX_AUTO_QUIRK; x++) {
+ if (udev->autoQuirk[x] == 0 ||
+ udev->autoQuirk[x] == quirk) {
+ udev->autoQuirk[x] = quirk;
+ return (0); /* success */
+ }
+ }
+ return (USB_ERR_NOMEM);
+}
diff --git a/freebsd/sys/dev/usb/usb_device.h b/freebsd/sys/dev/usb/usb_device.h
index c8bc5eb9..03ddf1e6 100644
--- a/freebsd/sys/dev/usb/usb_device.h
+++ b/freebsd/sys/dev/usb/usb_device.h
@@ -27,8 +27,18 @@
#ifndef _USB_DEVICE_H_
#define _USB_DEVICE_H_
-struct usb_symlink; /* UGEN */
+#ifndef USB_GLOBAL_INCLUDE_FILE
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_transfer.h>
+#endif
+
+struct usb_bus_methods;
+struct usb_config_descriptor;
struct usb_device; /* linux compat */
+struct usb_fs_privdata;
+struct usb_hw_ep_profile;
+struct usb_symlink; /* UGEN */
#define USB_CTRL_XFER_MAX 2
@@ -107,13 +117,70 @@ struct usb_power_save {
};
/*
+ * The following structure is used when trying to allocate hardware
+ * endpoints for an USB configuration in USB device side mode.
+ */
+struct usb_hw_ep_scratch_sub {
+ const struct usb_hw_ep_profile *pf;
+ uint16_t max_frame_size;
+ uint8_t hw_endpoint_out;
+ uint8_t hw_endpoint_in;
+ uint8_t needs_ep_type;
+ uint8_t needs_in:1;
+ uint8_t needs_out:1;
+};
+
+/*
+ * The following structure is used when trying to allocate hardware
+ * endpoints for an USB configuration in USB device side mode.
+ */
+struct usb_hw_ep_scratch {
+ struct usb_hw_ep_scratch_sub ep[USB_EP_MAX];
+ struct usb_hw_ep_scratch_sub *ep_max;
+ struct usb_config_descriptor *cd;
+ struct usb_device *udev;
+ struct usb_bus_methods *methods;
+ uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16];
+ uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16];
+};
+
+/*
+ * The following structure is used when generating USB descriptors
+ * from USB templates.
+ */
+struct usb_temp_setup {
+ void *buf;
+ usb_size_t size;
+ enum usb_dev_speed usb_speed;
+ uint8_t self_powered;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bConfigurationValue;
+ usb_error_t err;
+};
+
+/*
+ * The scratch area for USB devices. Access to this structure is
+ * protected by the enumeration SX lock.
+ */
+union usb_device_scratch {
+ struct usb_hw_ep_scratch hw_ep_scratch[1];
+ struct usb_temp_setup temp_setup[1];
+ struct {
+ struct usb_xfer dummy;
+ struct usb_setup_params parm;
+ } xfer_setup[1];
+ uint8_t data[255];
+};
+
+/*
* The following structure defines an USB device. There exists one of
* these structures for every USB device.
*/
struct usb_device {
struct usb_clear_stall_msg cs_msg[2]; /* generic clear stall
* messages */
- struct sx ctrl_sx;
struct sx enum_sx;
struct sx sr_sx;
struct mtx device_mtx;
@@ -135,7 +202,7 @@ struct usb_device {
#if USB_HAVE_UGEN
struct usb_fifo *fifo[USB_FIFO_MAX];
struct usb_symlink *ugen_symlink; /* our generic symlink */
- struct cdev *ctrl_dev; /* Control Endpoint 0 device node */
+ struct usb_fs_privdata *ctrl_dev; /* Control Endpoint 0 device node */
LIST_HEAD(,usb_fs_privdata) pd_list;
char ugen_name[20]; /* name of ugenX.X device */
#endif
@@ -187,6 +254,12 @@ struct usb_device {
struct usb_host_endpoint *linux_endpoint_end;
uint16_t devnum;
#endif
+
+ uint32_t clear_stall_errors; /* number of clear-stall failures */
+
+ uint16_t autoQuirk[USB_MAX_AUTO_QUIRK]; /* dynamic quirks */
+
+ union usb_device_scratch scratch;
};
/* globals */
@@ -200,6 +273,11 @@ struct usb_device *usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
struct usb_device *parent_hub, uint8_t depth,
uint8_t port_index, uint8_t port_no,
enum usb_dev_speed speed, enum usb_hc_mode mode);
+#if USB_HAVE_UGEN
+struct usb_fs_privdata *usb_make_dev(struct usb_device *, const char *,
+ int, int, int, uid_t, gid_t, int);
+void usb_destroy_dev(struct usb_fs_privdata *);
+#endif
usb_error_t usb_probe_and_attach(struct usb_device *udev,
uint8_t iface_index);
void usb_detach_device(struct usb_device *, uint8_t, uint8_t);
@@ -218,7 +296,7 @@ struct usb_endpoint *usb_endpoint_foreach(struct usb_device *udev, struct usb_en
void usb_set_device_state(struct usb_device *, enum usb_dev_state);
enum usb_dev_state usb_get_device_state(struct usb_device *);
-void usbd_enum_lock(struct usb_device *);
+uint8_t usbd_enum_lock(struct usb_device *);
void usbd_enum_unlock(struct usb_device *);
void usbd_sr_lock(struct usb_device *);
void usbd_sr_unlock(struct usb_device *);
diff --git a/freebsd/sys/dev/usb/usb_dynamic.c b/freebsd/sys/dev/usb/usb_dynamic.c
index cb54d10f..31e78225 100644
--- a/freebsd/sys/dev/usb/usb_dynamic.c
+++ b/freebsd/sys/dev/usb/usb_dynamic.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
diff --git a/freebsd/sys/dev/usb/usb_error.c b/freebsd/sys/dev/usb/usb_error.c
index 4505490d..9f6e4569 100644
--- a/freebsd/sys/dev/usb/usb_error.c
+++ b/freebsd/sys/dev/usb/usb_error.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
diff --git a/freebsd/sys/dev/usb/usb_freebsd.h b/freebsd/sys/dev/usb/usb_freebsd.h
index 3045ec32..8f9bb4c6 100644
--- a/freebsd/sys/dev/usb/usb_freebsd.h
+++ b/freebsd/sys/dev/usb/usb_freebsd.h
@@ -34,6 +34,7 @@
/* Default USB configuration */
#ifndef __rtems__
#define USB_HAVE_UGEN 1
+#define USB_HAVE_DEVCTL 1
#define USB_HAVE_BUSDMA 1
#define USB_HAVE_COMPAT_LINUX 1
#define USB_HAVE_USER_IO 1
@@ -41,6 +42,7 @@
#define USB_HAVE_TT_SUPPORT 1
#define USB_HAVE_POWERD 1
#define USB_HAVE_MSCTEST 1
+#define USB_HAVE_PF 1
#endif /* __rtems__ */
#define USB_TD_GET_PROC(td) (td)->td_proc
@@ -58,6 +60,9 @@
#define USB_HUB_MAX_DEPTH 5
#define USB_EP0_BUFSIZE 1024 /* bytes */
+#define USB_CS_RESET_LIMIT 20 /* failures = 20 * 50 ms = 1sec */
+
+#define USB_MAX_AUTO_QUIRK 4 /* maximum number of dynamic quirks */
typedef uint32_t usb_timeout_t; /* milliseconds */
typedef uint32_t usb_frlength_t; /* bytes */
diff --git a/freebsd/sys/dev/usb/usb_generic.c b/freebsd/sys/dev/usb/usb_generic.c
index 60b24794..4e439e15 100644
--- a/freebsd/sys/dev/usb/usb_generic.c
+++ b/freebsd/sys/dev/usb/usb_generic.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -130,9 +129,8 @@ struct usb_fifo_methods usb_ugen_methods = {
static int ugen_debug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB generic");
-SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW, &ugen_debug,
+SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &ugen_debug,
0, "Debug level");
-
TUNABLE_INT("hw.usb.ugen.debug", &ugen_debug);
#endif
@@ -243,7 +241,7 @@ ugen_open_pipe_write(struct usb_fifo *f)
/* transfers are already opened */
return (0);
}
- bzero(usb_config, sizeof(usb_config));
+ memset(usb_config, 0, sizeof(usb_config));
usb_config[1].type = UE_CONTROL;
usb_config[1].endpoint = 0;
@@ -311,7 +309,7 @@ ugen_open_pipe_read(struct usb_fifo *f)
/* transfers are already opened */
return (0);
}
- bzero(usb_config, sizeof(usb_config));
+ memset(usb_config, 0, sizeof(usb_config));
usb_config[1].type = UE_CONTROL;
usb_config[1].endpoint = 0;
@@ -717,13 +715,20 @@ ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
return (error);
}
+/*
+ * This function is called having the enumeration SX locked which
+ * protects the scratch area used.
+ */
static int
ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
{
- void *ptr = f->udev->bus->scratch[0].data;
- uint16_t size = sizeof(f->udev->bus->scratch[0].data);
+ void *ptr;
+ uint16_t size;
int error;
+ ptr = f->udev->scratch.data;
+ size = sizeof(f->udev->scratch.data);
+
if (usbd_req_get_string_desc(f->udev, NULL, ptr,
size, ugd->ugd_lang_id, ugd->ugd_string_index)) {
error = EINVAL;
@@ -955,18 +960,22 @@ ugen_re_enumerate(struct usb_fifo *f)
}
if (udev->flags.usb_mode != USB_MODE_HOST) {
/* not possible in device side mode */
+ DPRINTFN(6, "device mode\n");
return (ENOTTY);
}
+ if (udev->parent_hub == NULL) {
+ /* the root HUB cannot be re-enumerated */
+ DPRINTFN(6, "cannot reset root HUB\n");
+ return (EINVAL);
+ }
/* make sure all FIFO's are gone */
/* else there can be a deadlock */
if (ugen_fs_uninit(f)) {
/* ignore any errors */
DPRINTFN(6, "no FIFOs\n");
}
- if (udev->re_enumerate_wait == 0) {
- udev->re_enumerate_wait = 1;
- usb_needs_explore(udev->bus, 0);
- }
+ /* start re-enumeration of device */
+ usbd_start_re_enumerate(udev);
return (0);
}
@@ -1396,10 +1405,12 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
} u;
struct usb_endpoint *ep;
struct usb_endpoint_descriptor *ed;
+ struct usb_xfer *xfer;
int error = 0;
uint8_t iface_index;
uint8_t isread;
uint8_t ep_index;
+ uint8_t pre_scale;
u.addr = addr;
@@ -1421,11 +1432,11 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
case USB_FS_START:
error = ugen_fs_copy_in(f, u.pstart->ep_index);
- if (error) {
+ if (error)
break;
- }
mtx_lock(f->priv_mtx);
- usbd_transfer_start(f->fs_xfer[u.pstart->ep_index]);
+ xfer = f->fs_xfer[u.pstart->ep_index];
+ usbd_transfer_start(xfer);
mtx_unlock(f->priv_mtx);
break;
@@ -1435,7 +1446,19 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
break;
}
mtx_lock(f->priv_mtx);
- usbd_transfer_stop(f->fs_xfer[u.pstop->ep_index]);
+ xfer = f->fs_xfer[u.pstart->ep_index];
+ if (usbd_transfer_pending(xfer)) {
+ usbd_transfer_stop(xfer);
+ /*
+ * Check if the USB transfer was stopped
+ * before it was even started. Else a cancel
+ * callback will be pending.
+ */
+ if (!xfer->flags_int.transferring) {
+ ugen_fs_set_complete(xfer->priv_sc,
+ USB_P2U(xfer->priv_fifo));
+ }
+ }
mtx_unlock(f->priv_mtx);
break;
@@ -1451,6 +1474,12 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
if (u.popen->max_bufsize > USB_FS_MAX_BUFSIZE) {
u.popen->max_bufsize = USB_FS_MAX_BUFSIZE;
}
+ if (u.popen->max_frames & USB_FS_MAX_FRAMES_PRE_SCALE) {
+ pre_scale = 1;
+ u.popen->max_frames &= ~USB_FS_MAX_FRAMES_PRE_SCALE;
+ } else {
+ pre_scale = 0;
+ }
if (u.popen->max_frames > USB_FS_MAX_FRAMES) {
u.popen->max_frames = USB_FS_MAX_FRAMES;
break;
@@ -1471,13 +1500,15 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
}
iface_index = ep->iface_index;
- bzero(usb_config, sizeof(usb_config));
+ memset(usb_config, 0, sizeof(usb_config));
usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
usb_config[0].direction = ed->bEndpointAddress & (UE_DIR_OUT | UE_DIR_IN);
usb_config[0].interval = USB_DEFAULT_INTERVAL;
usb_config[0].flags.proxy_buffer = 1;
+ if (pre_scale != 0)
+ usb_config[0].flags.pre_scale_frames = 1;
usb_config[0].callback = &ugen_ctrl_fs_callback;
usb_config[0].timeout = 0; /* no timeout */
usb_config[0].frames = u.popen->max_frames;
@@ -1519,6 +1550,10 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
f->fs_xfer[u.popen->ep_index]->max_frame_size;
u.popen->max_bufsize =
f->fs_xfer[u.popen->ep_index]->max_data_length;
+ /* update number of frames */
+ u.popen->max_frames =
+ f->fs_xfer[u.popen->ep_index]->nframes;
+ /* store index of endpoint */
f->fs_xfer[u.popen->ep_index]->priv_fifo =
((uint8_t *)0) + u.popen->ep_index;
} else {
@@ -2139,7 +2174,16 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
break;
}
+ /*
+ * Detach the currently attached driver.
+ */
usb_detach_device(f->udev, n, 0);
+
+ /*
+ * Set parent to self, this should keep attach away
+ * until the next set configuration event.
+ */
+ usbd_set_parent_iface(f->udev, n, n);
break;
case USB_SET_POWER_MODE:
diff --git a/freebsd/sys/dev/usb/usb_handle_request.c b/freebsd/sys/dev/usb/usb_handle_request.c
index 97d30394..d1df80a1 100644
--- a/freebsd/sys/dev/usb/usb_handle_request.c
+++ b/freebsd/sys/dev/usb/usb_handle_request.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -148,6 +147,7 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
{
struct usb_device *udev = xfer->xroot->udev;
usb_error_t err = 0;
+ uint8_t do_unlock;
/*
* We need to protect against other threads doing probe and
@@ -155,7 +155,8 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
*/
USB_XFER_UNLOCK(xfer);
- usbd_enum_lock(udev);
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (conf_no == USB_UNCONFIG_NO) {
conf_no = USB_UNCONFIG_INDEX;
@@ -178,7 +179,8 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
goto done;
}
done:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (err);
}
@@ -190,13 +192,8 @@ usb_check_alt_setting(struct usb_device *udev,
uint8_t do_unlock;
usb_error_t err = 0;
- /* automatic locking */
- if (usbd_enum_is_locked(udev)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- usbd_enum_lock(udev);
- }
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
err = USB_ERR_INVAL;
@@ -225,6 +222,7 @@ usb_handle_iface_request(struct usb_xfer *xfer,
int error;
uint8_t iface_index;
uint8_t temp_state;
+ uint8_t do_unlock;
if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
iface_index = req.wIndex[0]; /* unicast */
@@ -238,7 +236,8 @@ usb_handle_iface_request(struct usb_xfer *xfer,
*/
USB_XFER_UNLOCK(xfer);
- usbd_enum_lock(udev);
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
error = ENXIO;
@@ -354,17 +353,20 @@ tr_repeat:
goto tr_stalled;
}
tr_valid:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (0);
tr_short:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (USB_ERR_SHORT_XFER);
tr_stalled:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (USB_ERR_STALLED);
}
@@ -440,8 +442,10 @@ usb_handle_remote_wakeup(struct usb_xfer *xfer, uint8_t is_on)
USB_BUS_UNLOCK(bus);
+#if USB_HAVE_POWERD
/* In case we are out of sync, update the power state. */
usb_bus_power_update(udev->bus);
+#endif
return (0); /* success */
}
@@ -467,7 +471,6 @@ usb_handle_request(struct usb_xfer *xfer)
uint16_t rem; /* data remainder */
uint16_t max_len; /* max fragment length */
uint16_t wValue;
- uint16_t wIndex;
uint8_t state;
uint8_t is_complete = 1;
usb_error_t err;
@@ -533,11 +536,10 @@ usb_handle_request(struct usb_xfer *xfer)
/* get some request fields decoded */
wValue = UGETW(req.wValue);
- wIndex = UGETW(req.wIndex);
DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x "
"off=0x%x rem=0x%x, state=%d\n", req.bmRequestType,
- req.bRequest, wValue, wIndex, off, rem, state);
+ req.bRequest, wValue, UGETW(req.wIndex), off, rem, state);
/* demultiplex the control request */
diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c
index e99cdb0b..0dc146df 100644
--- a/freebsd/sys/dev/usb/usb_hid.c
+++ b/freebsd/sys/dev/usb/usb_hid.c
@@ -21,13 +21,6 @@ __FBSDID("$FreeBSD$");
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -50,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -435,7 +427,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h)
s->loc_size = dval & mask;
break;
case 8:
- hid_switch_rid(s, c, dval);
+ hid_switch_rid(s, c, dval & mask);
break;
case 9:
/* mask because value is unsigned */
@@ -622,7 +614,7 @@ hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, uint8_t *id)
* hid_locate
*------------------------------------------------------------------------*/
int
-hid_locate(const void *desc, usb_size_t size, uint32_t u, enum hid_kind k,
+hid_locate(const void *desc, usb_size_t size, int32_t u, enum hid_kind k,
uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id)
{
struct hid_data *d;
@@ -712,10 +704,47 @@ hid_get_data_unsigned(const uint8_t *buf, usb_size_t len, struct hid_location *l
}
/*------------------------------------------------------------------------*
+ * hid_put_data
+ *------------------------------------------------------------------------*/
+void
+hid_put_data_unsigned(uint8_t *buf, usb_size_t len,
+ struct hid_location *loc, unsigned int value)
+{
+ uint32_t hpos = loc->pos;
+ uint32_t hsize = loc->size;
+ uint64_t data;
+ uint64_t mask;
+ uint32_t rpos;
+ uint8_t n;
+
+ DPRINTFN(11, "hid_put_data: loc %d/%d = %u\n", hpos, hsize, value);
+
+ /* Range check and limit */
+ if (hsize == 0)
+ return;
+ if (hsize > 32)
+ hsize = 32;
+
+ /* Put data in a safe way */
+ rpos = (hpos / 8);
+ n = (hsize + 7) / 8;
+ data = ((uint64_t)value) << (hpos % 8);
+ mask = ((1ULL << hsize) - 1ULL) << (hpos % 8);
+ rpos += n;
+ while (n--) {
+ rpos--;
+ if (rpos < len) {
+ buf[rpos] &= ~(mask >> (8 * n));
+ buf[rpos] |= (data >> (8 * n));
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*
* hid_is_collection
*------------------------------------------------------------------------*/
int
-hid_is_collection(const void *desc, usb_size_t size, uint32_t usage)
+hid_is_collection(const void *desc, usb_size_t size, int32_t usage)
{
struct hid_data *hd;
struct hid_item hi;
diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c
index c20bde30..c5887797 100644
--- a/freebsd/sys/dev/usb/usb_hub.c
+++ b/freebsd/sys/dev/usb/usb_hub.c
@@ -40,7 +40,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -80,9 +79,8 @@
static int uhub_debug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB");
-SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW, &uhub_debug, 0,
+SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &uhub_debug, 0,
"Debug level");
-
TUNABLE_INT("hw.usb.uhub.debug", &uhub_debug);
#endif
@@ -112,6 +110,7 @@ struct uhub_softc {
#define UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol)
#define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB)
#define UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT)
+#define UHUB_IS_MULTI_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBMTT)
#define UHUB_IS_SUPER_SPEED(sc) (UHUB_PROTO(sc) == UDPROTO_SSHUB)
/* prototypes for type checking: */
@@ -243,11 +242,18 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up)
/* check if device should be re-enumerated */
if (child->flags.usb_mode == USB_MODE_HOST) {
- usbd_enum_lock(child);
+ uint8_t do_unlock;
+
+ do_unlock = usbd_enum_lock(child);
if (child->re_enumerate_wait) {
- err = usbd_set_config_index(child, USB_UNCONFIG_INDEX);
- if (err == 0)
- err = usbd_req_re_enumerate(child, NULL);
+ err = usbd_set_config_index(child,
+ USB_UNCONFIG_INDEX);
+ if (err != 0) {
+ DPRINTF("Unconfigure failed: "
+ "%s: Ignored.\n",
+ usbd_errstr(err));
+ }
+ err = usbd_req_re_enumerate(child, NULL);
if (err == 0)
err = usbd_set_config_index(child, 0);
if (err == 0) {
@@ -257,7 +263,8 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up)
child->re_enumerate_wait = 0;
err = 0;
}
- usbd_enum_unlock(child);
+ if (do_unlock)
+ usbd_enum_unlock(child);
}
/* check if probe and attach should be done */
@@ -325,6 +332,7 @@ uhub_reattach_port(struct uhub_softc *sc, uint8_t portno)
enum usb_dev_speed speed;
enum usb_hc_mode mode;
usb_error_t err;
+ uint16_t power_mask;
uint8_t timeout;
DPRINTF("reattaching port %d\n", portno);
@@ -367,10 +375,27 @@ repeat:
}
/* check if there is no power on the port and print a warning */
- if (!(sc->sc_st.port_status & UPS_PORT_POWER)) {
+ switch (udev->speed) {
+ case USB_SPEED_HIGH:
+ case USB_SPEED_FULL:
+ case USB_SPEED_LOW:
+ power_mask = UPS_PORT_POWER;
+ break;
+ case USB_SPEED_SUPER:
+ if (udev->parent_hub == NULL)
+ power_mask = UPS_PORT_POWER;
+ else
+ power_mask = UPS_PORT_POWER_SS;
+ break;
+ default:
+ power_mask = 0;
+ break;
+ }
+ if (!(sc->sc_st.port_status & power_mask)) {
DPRINTF("WARNING: strange, connected port %d "
"has no power\n", portno);
}
+
/* check if the device is in Host Mode */
if (!(sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)) {
@@ -394,7 +419,7 @@ repeat:
/* wait for maximum device power up time */
usb_pause_mtx(NULL,
- USB_MS_TO_TICKS(USB_PORT_POWERUP_DELAY));
+ USB_MS_TO_TICKS(usb_port_powerup_delay));
/* reset port, which implies enabling it */
@@ -607,12 +632,15 @@ uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno)
}
} else {
switch (UPS_PORT_LINK_STATE_GET(sc->sc_st.port_status)) {
- case UPS_PORT_LS_U0:
- case UPS_PORT_LS_U1:
+ case UPS_PORT_LS_U3:
+ is_suspend = 1;
+ break;
+ case UPS_PORT_LS_SS_INA:
+ usbd_req_warm_reset_port(udev, NULL, portno);
is_suspend = 0;
break;
default:
- is_suspend = 1;
+ is_suspend = 0;
break;
}
}
@@ -629,8 +657,7 @@ uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno)
*/
if (is_suspend == 0)
usb_dev_resume_peer(child);
- else if ((child->flags.usb_mode == USB_MODE_DEVICE) ||
- (usb_device_20_compatible(child) == 0))
+ else if (child->flags.usb_mode == USB_MODE_DEVICE)
usb_dev_suspend_peer(child);
}
done:
@@ -688,6 +715,7 @@ uhub_explore(struct usb_device *udev)
usb_error_t err;
uint8_t portno;
uint8_t x;
+ uint8_t do_unlock;
hub = udev->hub;
sc = hub->hubsoftc;
@@ -704,6 +732,13 @@ uhub_explore(struct usb_device *udev)
DPRINTF("Device is suspended!\n");
return (0);
}
+
+ /*
+ * Make sure we don't race against user-space applications
+ * like LibUSB:
+ */
+ do_unlock = usbd_enum_lock(udev);
+
for (x = 0; x != hub->nports; x++) {
up = hub->ports + x;
portno = x + 1;
@@ -765,7 +800,8 @@ uhub_explore(struct usb_device *udev)
break;
}
}
- if (sc->sc_st.port_change & (UPS_C_SUSPEND | UPS_C_PORT_LINK_STATE)) {
+ if (sc->sc_st.port_change & (UPS_C_SUSPEND |
+ UPS_C_PORT_LINK_STATE)) {
err = uhub_suspend_resume_port(sc, portno);
if (err) {
/* most likely the HUB is gone */
@@ -781,6 +817,9 @@ uhub_explore(struct usb_device *udev)
up->restartcnt = 0;
}
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
/* initial status checked */
sc->sc_flags |= UHUB_FLAG_DID_EXPLORE;
@@ -916,6 +955,16 @@ uhub_attach(device_t dev)
"bus powered HUB. HUB ignored\n");
goto error;
}
+
+ if (UHUB_IS_MULTI_TT(sc)) {
+ err = usbd_set_alt_interface_index(udev, 0, 1);
+ if (err) {
+ device_printf(dev, "MTT could not be enabled\n");
+ goto error;
+ }
+ device_printf(dev, "MTT enabled\n");
+ }
+
/* get HUB descriptor */
DPRINTFN(2, "Getting HUB descriptor\n");
@@ -936,7 +985,7 @@ uhub_attach(device_t dev)
/* get power delay */
pwrdly = ((hubdesc20.bPwrOn2PwrGood * UHD_PWRON_FACTOR) +
- USB_EXTRA_POWER_UP_TIME);
+ usb_extra_power_up_time);
/* get complete HUB descriptor */
if (nports >= 8) {
@@ -981,7 +1030,7 @@ uhub_attach(device_t dev)
/* get power delay */
pwrdly = ((hubdesc30.bPwrOn2PwrGood * UHD_PWRON_FACTOR) +
- USB_EXTRA_POWER_UP_TIME);
+ usb_extra_power_up_time);
/* get complete HUB descriptor */
if (nports >= 8) {
@@ -1010,7 +1059,7 @@ uhub_attach(device_t dev)
/* default number of ports */
nports = 1;
/* default power delay */
- pwrdly = ((10 * UHD_PWRON_FACTOR) + USB_EXTRA_POWER_UP_TIME);
+ pwrdly = ((10 * UHD_PWRON_FACTOR) + usb_extra_power_up_time);
break;
}
if (nports == 0) {
@@ -1025,10 +1074,6 @@ uhub_attach(device_t dev)
}
udev->hub = hub;
-#if USB_HAVE_TT_SUPPORT
- /* init FULL-speed ISOCHRONOUS schedule */
- usbd_fs_isoc_schedule_init_all(hub->fs_isoc_schedule);
-#endif
/* initialize HUB structure */
hub->hubsoftc = sc;
hub->explore = &uhub_explore;
@@ -1332,15 +1377,21 @@ uhub_child_pnpinfo_string(device_t parent, device_t child,
"devclass=0x%02x devsubclass=0x%02x "
"sernum=\"%s\" "
"release=0x%04x "
- "intclass=0x%02x intsubclass=0x%02x",
+ "mode=%s "
+ "intclass=0x%02x intsubclass=0x%02x "
+ "intprotocol=0x%02x " "%s%s",
UGETW(res.udev->ddesc.idVendor),
UGETW(res.udev->ddesc.idProduct),
res.udev->ddesc.bDeviceClass,
res.udev->ddesc.bDeviceSubClass,
usb_get_serial(res.udev),
UGETW(res.udev->ddesc.bcdDevice),
+ (res.udev->flags.usb_mode == USB_MODE_HOST) ? "host" : "device",
iface->idesc->bInterfaceClass,
- iface->idesc->bInterfaceSubClass);
+ iface->idesc->bInterfaceSubClass,
+ iface->idesc->bInterfaceProtocol,
+ iface->pnpinfo ? " " : "",
+ iface->pnpinfo ? iface->pnpinfo : "");
} else {
if (buflen) {
buf[0] = '\0';
@@ -1393,7 +1444,7 @@ static uint8_t
usb_intr_find_best_slot(usb_size_t *ptr, uint8_t start,
uint8_t end, uint8_t mask)
{
- usb_size_t min = 0 - 1;
+ usb_size_t min = (usb_size_t)-1;
usb_size_t sum;
uint8_t x;
uint8_t y;
@@ -1618,42 +1669,6 @@ usb_hs_bandwidth_free(struct usb_xfer *xfer)
}
/*------------------------------------------------------------------------*
- * usbd_fs_isoc_schedule_init_sub
- *
- * This function initialises an USB FULL speed isochronous schedule
- * entry.
- *------------------------------------------------------------------------*/
-#if USB_HAVE_TT_SUPPORT
-static void
-usbd_fs_isoc_schedule_init_sub(struct usb_fs_isoc_schedule *fss)
-{
- fss->total_bytes = (USB_FS_ISOC_UFRAME_MAX *
- USB_FS_BYTES_PER_HS_UFRAME);
- fss->frame_bytes = (USB_FS_BYTES_PER_HS_UFRAME);
- fss->frame_slot = 0;
-}
-#endif
-
-/*------------------------------------------------------------------------*
- * usbd_fs_isoc_schedule_init_all
- *
- * This function will reset the complete USB FULL speed isochronous
- * bandwidth schedule.
- *------------------------------------------------------------------------*/
-#if USB_HAVE_TT_SUPPORT
-void
-usbd_fs_isoc_schedule_init_all(struct usb_fs_isoc_schedule *fss)
-{
- struct usb_fs_isoc_schedule *fss_end = fss + USB_ISOC_TIME_MAX;
-
- while (fss != fss_end) {
- usbd_fs_isoc_schedule_init_sub(fss);
- fss++;
- }
-}
-#endif
-
-/*------------------------------------------------------------------------*
* usb_isoc_time_expand
*
* This function will expand the time counter from 7-bit to 16-bit.
@@ -1685,114 +1700,130 @@ usb_isoc_time_expand(struct usb_bus *bus, uint16_t isoc_time_curr)
}
/*------------------------------------------------------------------------*
- * usbd_fs_isoc_schedule_isoc_time_expand
+ * usbd_fs_isoc_schedule_alloc_slot
*
- * This function does multiple things. First of all it will expand the
- * passed isochronous time, which is the return value. Then it will
- * store where the current FULL speed isochronous schedule is
- * positioned in time and where the end is. See "pp_start" and
- * "pp_end" arguments.
+ * This function will allocate bandwidth for an isochronous FULL speed
+ * transaction in the FULL speed schedule.
*
* Returns:
- * Expanded version of "isoc_time".
- *
- * NOTE: This function depends on being called regularly with
- * intervals less than "USB_ISOC_TIME_MAX".
+ * <8: Success
+ * Else: Error
*------------------------------------------------------------------------*/
#if USB_HAVE_TT_SUPPORT
-uint16_t
-usbd_fs_isoc_schedule_isoc_time_expand(struct usb_device *udev,
- struct usb_fs_isoc_schedule **pp_start,
- struct usb_fs_isoc_schedule **pp_end,
- uint16_t isoc_time)
+uint8_t
+usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t isoc_time)
{
- struct usb_fs_isoc_schedule *fss_end;
- struct usb_fs_isoc_schedule *fss_a;
- struct usb_fs_isoc_schedule *fss_b;
- struct usb_hub *hs_hub;
+ struct usb_xfer *xfer;
+ struct usb_xfer *pipe_xfer;
+ struct usb_bus *bus;
+ usb_frlength_t len;
+ usb_frlength_t data_len;
+ uint16_t delta;
+ uint16_t slot;
+ uint8_t retval;
- isoc_time = usb_isoc_time_expand(udev->bus, isoc_time);
+ data_len = 0;
+ slot = 0;
- hs_hub = udev->parent_hs_hub->hub;
+ bus = isoc_xfer->xroot->bus;
- if (hs_hub != NULL) {
+ TAILQ_FOREACH(xfer, &bus->intr_q.head, wait_entry) {
- fss_a = hs_hub->fs_isoc_schedule +
- (hs_hub->isoc_last_time % USB_ISOC_TIME_MAX);
+ /* skip self, if any */
- hs_hub->isoc_last_time = isoc_time;
+ if (xfer == isoc_xfer)
+ continue;
+
+ /* check if this USB transfer is going through the same TT */
+
+ if (xfer->xroot->udev->parent_hs_hub !=
+ isoc_xfer->xroot->udev->parent_hs_hub) {
+ continue;
+ }
+ if ((isoc_xfer->xroot->udev->parent_hs_hub->
+ ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT) &&
+ (xfer->xroot->udev->hs_port_no !=
+ isoc_xfer->xroot->udev->hs_port_no)) {
+ continue;
+ }
+ if (xfer->endpoint->methods != isoc_xfer->endpoint->methods)
+ continue;
- fss_b = hs_hub->fs_isoc_schedule +
- (isoc_time % USB_ISOC_TIME_MAX);
+ /* check if isoc_time is part of this transfer */
- fss_end = hs_hub->fs_isoc_schedule + USB_ISOC_TIME_MAX;
+ delta = xfer->isoc_time_complete - isoc_time;
+ if (delta > 0 && delta <= xfer->nframes) {
+ delta = xfer->nframes - delta;
- *pp_start = hs_hub->fs_isoc_schedule;
- *pp_end = fss_end;
+ len = xfer->frlengths[delta];
+ len += 8;
+ len *= 7;
+ len /= 6;
- while (fss_a != fss_b) {
- if (fss_a == fss_end) {
- fss_a = hs_hub->fs_isoc_schedule;
+ data_len += len;
+ }
+
+ /* check double buffered transfers */
+
+ TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q.head,
+ wait_entry) {
+
+ /* skip self, if any */
+
+ if (pipe_xfer == isoc_xfer)
continue;
+
+ /* check if isoc_time is part of this transfer */
+
+ delta = pipe_xfer->isoc_time_complete - isoc_time;
+ if (delta > 0 && delta <= pipe_xfer->nframes) {
+ delta = pipe_xfer->nframes - delta;
+
+ len = pipe_xfer->frlengths[delta];
+ len += 8;
+ len *= 7;
+ len /= 6;
+
+ data_len += len;
}
- usbd_fs_isoc_schedule_init_sub(fss_a);
- fss_a++;
}
+ }
- } else {
-
- *pp_start = NULL;
- *pp_end = NULL;
+ while (data_len >= USB_FS_BYTES_PER_HS_UFRAME) {
+ data_len -= USB_FS_BYTES_PER_HS_UFRAME;
+ slot++;
}
- return (isoc_time);
-}
-#endif
-/*------------------------------------------------------------------------*
- * usbd_fs_isoc_schedule_alloc
- *
- * This function will allocate bandwidth for an isochronous FULL speed
- * transaction in the FULL speed schedule. The microframe slot where
- * the transaction should be started is stored in the byte pointed to
- * by "pstart". The "len" argument specifies the length of the
- * transaction in bytes.
- *
- * Returns:
- * 0: Success
- * Else: Error
- *------------------------------------------------------------------------*/
-#if USB_HAVE_TT_SUPPORT
-uint8_t
-usbd_fs_isoc_schedule_alloc(struct usb_fs_isoc_schedule *fss,
- uint8_t *pstart, uint16_t len)
-{
- uint8_t slot = fss->frame_slot;
+ /* check for overflow */
+
+ if (slot >= USB_FS_ISOC_UFRAME_MAX)
+ return (255);
- /* Compute overhead and bit-stuffing */
+ retval = slot;
- len += 8;
+ delta = isoc_xfer->isoc_time_complete - isoc_time;
+ if (delta > 0 && delta <= isoc_xfer->nframes) {
+ delta = isoc_xfer->nframes - delta;
- len *= 7;
- len /= 6;
+ len = isoc_xfer->frlengths[delta];
+ len += 8;
+ len *= 7;
+ len /= 6;
- if (len > fss->total_bytes) {
- *pstart = 0; /* set some dummy value */
- return (1); /* error */
+ data_len += len;
}
- if (len > 0) {
- fss->total_bytes -= len;
+ while (data_len >= USB_FS_BYTES_PER_HS_UFRAME) {
+ data_len -= USB_FS_BYTES_PER_HS_UFRAME;
+ slot++;
+ }
- while (len >= fss->frame_bytes) {
- len -= fss->frame_bytes;
- fss->frame_bytes = USB_FS_BYTES_PER_HS_UFRAME;
- fss->frame_slot++;
- }
+ /* check for overflow */
- fss->frame_bytes -= len;
- }
- *pstart = slot;
- return (0); /* success */
+ if (slot >= USB_FS_ISOC_UFRAME_MAX)
+ return (255);
+
+ return (retval);
}
#endif
@@ -2046,7 +2077,6 @@ usb_peer_should_wakeup(struct usb_device *udev)
(udev->pwr_save.write_refs != 0) ||
((udev->pwr_save.read_refs != 0) &&
(udev->flags.usb_mode == USB_MODE_HOST) &&
- (usb_device_20_compatible(udev) != 0) &&
(usb_peer_can_wakeup(udev) == 0)));
}
@@ -2112,7 +2142,7 @@ usb_bus_powerd(struct usb_bus *bus)
/* reset counters */
- mintime = 0 - 1;
+ mintime = (usb_ticks_t)-1;
type_refs[0] = 0;
type_refs[1] = 0;
type_refs[2] = 0;
@@ -2149,7 +2179,7 @@ usb_bus_powerd(struct usb_bus *bus)
}
}
- if (mintime >= (1 * hz)) {
+ if (mintime >= (usb_ticks_t)(1 * hz)) {
/* recompute power masks */
DPRINTF("Recomputing power masks\n");
bus->hw_power_state = 0;
@@ -2226,10 +2256,18 @@ usb_dev_resume_peer(struct usb_device *udev)
DPRINTFN(0, "Resuming port failed\n");
return;
}
+ } else {
+ /* resume current port (Valid in Host and Device Mode) */
+ err = usbd_req_set_port_link_state(udev->parent_hub,
+ NULL, udev->port_no, UPS_PORT_LS_U0);
+ if (err) {
+ DPRINTFN(0, "Resuming port failed\n");
+ return;
+ }
}
/* resume settle time */
- usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY));
+ usb_pause_mtx(NULL, USB_MS_TO_TICKS(usb_port_resume_delay));
if (bus->methods->device_resume != NULL) {
/* resume USB device on the USB controller */
@@ -2267,8 +2305,7 @@ usb_dev_resume_peer(struct usb_device *udev)
usbd_sr_unlock(udev);
/* check if peer has wakeup capability */
- if (usb_peer_can_wakeup(udev) &&
- usb_device_20_compatible(udev)) {
+ if (usb_peer_can_wakeup(udev)) {
/* clear remote wakeup */
err = usbd_req_clear_device_feature(udev,
NULL, UF_DEVICE_REMOTE_WAKEUP);
@@ -2329,8 +2366,7 @@ repeat:
}
}
- if (usb_peer_can_wakeup(udev) &&
- usb_device_20_compatible(udev)) {
+ if (usb_peer_can_wakeup(udev)) {
/*
* This request needs to be done before we set
* "udev->flags.self_suspended":
@@ -2362,8 +2398,7 @@ repeat:
USB_BUS_UNLOCK(udev->bus);
if (err != 0) {
- if (usb_peer_can_wakeup(udev) &&
- usb_device_20_compatible(udev)) {
+ if (usb_peer_can_wakeup(udev)) {
/* allow device to do remote wakeup */
err = usbd_req_clear_device_feature(udev,
NULL, UF_DEVICE_REMOTE_WAKEUP);
@@ -2385,7 +2420,7 @@ repeat:
NULL, udev->port_no, UHF_PORT_SUSPEND);
/* resume settle time */
- usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY));
+ usb_pause_mtx(NULL, USB_MS_TO_TICKS(usb_port_resume_delay));
}
DPRINTF("Suspend was cancelled!\n");
return;
@@ -2419,6 +2454,14 @@ repeat:
DPRINTFN(0, "Suspending port failed\n");
return;
}
+ } else {
+ /* suspend current port */
+ err = usbd_req_set_port_link_state(udev->parent_hub,
+ NULL, udev->port_no, UPS_PORT_LS_U3);
+ if (err) {
+ DPRINTFN(0, "Suspending port failed\n");
+ return;
+ }
}
udev = udev->parent_hub;
@@ -2472,3 +2515,19 @@ usbd_filter_power_mode(struct usb_device *udev, uint8_t power_mode)
/* use fixed power mode given by hardware driver */
return (temp);
}
+
+/*------------------------------------------------------------------------*
+ * usbd_start_re_enumerate
+ *
+ * This function starts re-enumeration of the given USB device. This
+ * function does not need to be called BUS-locked. This function does
+ * not wait until the re-enumeration is completed.
+ *------------------------------------------------------------------------*/
+void
+usbd_start_re_enumerate(struct usb_device *udev)
+{
+ if (udev->re_enumerate_wait == 0) {
+ udev->re_enumerate_wait = 1;
+ usb_needs_explore(udev->bus, 0);
+ }
+}
diff --git a/freebsd/sys/dev/usb/usb_hub.h b/freebsd/sys/dev/usb/usb_hub.h
index 0f595997..23a1fa4f 100644
--- a/freebsd/sys/dev/usb/usb_hub.h
+++ b/freebsd/sys/dev/usb/usb_hub.h
@@ -38,22 +38,9 @@ struct usb_port {
};
/*
- * The following structure defines how many bytes are
- * left in an 1ms USB time slot.
- */
-struct usb_fs_isoc_schedule {
- uint16_t total_bytes;
- uint8_t frame_bytes;
- uint8_t frame_slot;
-};
-
-/*
* The following structure defines an USB HUB.
*/
struct usb_hub {
-#if USB_HAVE_TT_SUPPORT
- struct usb_fs_isoc_schedule fs_isoc_schedule[USB_ISOC_TIME_MAX];
-#endif
struct usb_device *hubudev; /* the HUB device */
usb_error_t (*explore) (struct usb_device *hub);
void *hubsoftc;
@@ -68,7 +55,6 @@ struct usb_hub {
void usb_hs_bandwidth_alloc(struct usb_xfer *xfer);
void usb_hs_bandwidth_free(struct usb_xfer *xfer);
-void usbd_fs_isoc_schedule_init_all(struct usb_fs_isoc_schedule *fss);
void usb_bus_port_set_device(struct usb_bus *bus, struct usb_port *up,
struct usb_device *udev, uint8_t device_index);
struct usb_device *usb_bus_port_get_device(struct usb_bus *bus,
diff --git a/freebsd/sys/dev/usb/usb_ioctl.h b/freebsd/sys/dev/usb/usb_ioctl.h
index f9018e28..9af6ee5c 100644
--- a/freebsd/sys/dev/usb/usb_ioctl.h
+++ b/freebsd/sys/dev/usb/usb_ioctl.h
@@ -39,15 +39,37 @@
#define USB_DEVICE_NAME "usbctl"
#define USB_DEVICE_DIR "usb"
#define USB_GENERIC_NAME "ugen"
+#define USB_TEMPLATE_SYSCTL "hw.usb.template" /* integer type */
+
+/* Definition of valid template sysctl values */
+
+enum {
+ USB_TEMP_MSC, /* USB Mass Storage */
+ USB_TEMP_CDCE, /* USB CDC Ethernet */
+ USB_TEMP_MTP, /* Message Transfer Protocol */
+ USB_TEMP_MODEM, /* USB CDC Modem */
+ USB_TEMP_AUDIO, /* USB Audio */
+ USB_TEMP_KBD, /* USB Keyboard */
+ USB_TEMP_MOUSE, /* USB Mouse */
+ USB_TEMP_MAX,
+};
struct usb_read_dir {
+#ifdef COMPAT_32BIT
+ uint64_t urd_data;
+#else
void *urd_data;
+#endif
uint32_t urd_startentry;
uint32_t urd_maxlen;
};
struct usb_ctl_request {
+#ifdef COMPAT_32BIT
+ uint64_t ucr_data;
+#else
void *ucr_data;
+#endif
uint16_t ucr_flags;
uint16_t ucr_actlen; /* actual length transferred */
uint8_t ucr_addr; /* zero - currently not used */
@@ -60,7 +82,11 @@ struct usb_alt_interface {
};
struct usb_gen_descriptor {
+#ifdef COMPAT_32BIT
+ uint64_t ugd_data;
+#else
void *ugd_data;
+#endif
uint16_t ugd_lang_id;
uint16_t ugd_maxlen;
uint16_t ugd_actlen;
@@ -126,9 +152,14 @@ struct usb_fs_endpoint {
* NOTE: isochronous USB transfer only use one buffer, but can have
* multiple frame lengths !
*/
+#ifdef COMPAT_32BIT
+ uint64_t ppBuffer;
+ uint64_t pLength;
+#else
void **ppBuffer; /* pointer to userland buffers */
uint32_t *pLength; /* pointer to frame lengths, updated
* to actual length */
+#endif
uint32_t nFrames; /* number of frames */
uint32_t aFrames; /* actual number of frames */
uint16_t flags;
@@ -150,7 +181,11 @@ struct usb_fs_endpoint {
struct usb_fs_init {
/* userland pointer to endpoints structure */
+#ifdef COMPAT_32BIT
+ uint64_t pEndpoints;
+#else
struct usb_fs_endpoint *pEndpoints;
+#endif
/* maximum number of endpoints */
uint8_t ep_index_max;
};
@@ -162,8 +197,9 @@ struct usb_fs_uninit {
struct usb_fs_open {
#define USB_FS_MAX_BUFSIZE (1 << 18)
uint32_t max_bufsize;
-#define USB_FS_MAX_FRAMES (1 << 12)
- uint32_t max_frames;
+#define USB_FS_MAX_FRAMES (1U << 12)
+#define USB_FS_MAX_FRAMES_PRE_SCALE (1U << 31) /* for ISOCHRONOUS transfers */
+ uint32_t max_frames; /* read and write */
uint16_t max_packet_length; /* read only */
uint8_t dev_index; /* currently unused */
uint8_t ep_index;
@@ -253,6 +289,10 @@ struct usb_gen_quirk {
#define USB_GET_CM_OVER_DATA _IOR ('U', 180, int)
#define USB_SET_CM_OVER_DATA _IOW ('U', 181, int)
+/* GPIO control */
+#define USB_GET_GPIO _IOR ('U', 182, int)
+#define USB_SET_GPIO _IOW ('U', 183, int)
+
/* USB file system interface */
#define USB_FS_START _IOW ('U', 192, struct usb_fs_start)
#define USB_FS_STOP _IOW ('U', 193, struct usb_fs_stop)
diff --git a/freebsd/sys/dev/usb/usb_lookup.c b/freebsd/sys/dev/usb/usb_lookup.c
index b7ce2522..ed752fed 100644
--- a/freebsd/sys/dev/usb/usb_lookup.c
+++ b/freebsd/sys/dev/usb/usb_lookup.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -45,6 +44,8 @@
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
+#include <sys/limits.h>
+#include <sys/endian.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -108,13 +109,6 @@ usbd_lookup_id_by_info(const struct usb_device_id *id, usb_size_t sizeof_id,
(id->bDeviceProtocol != info->bDeviceProtocol)) {
continue;
}
- if ((info->bDeviceClass == 0xFF) &&
- (!(id->match_flag_vendor)) &&
- ((id->match_flag_int_class) ||
- (id->match_flag_int_subclass) ||
- (id->match_flag_int_protocol))) {
- continue;
- }
if ((id->match_flag_int_class) &&
(id->bInterfaceClass != info->bInterfaceClass)) {
continue;
@@ -154,3 +148,108 @@ usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id,
}
return (ENXIO);
}
+
+/*------------------------------------------------------------------------*
+ * Export the USB device ID format we use to userspace tools.
+ *------------------------------------------------------------------------*/
+#if BYTE_ORDER == BIG_ENDIAN
+#define U16_XOR "8"
+#define U32_XOR "12"
+#define U64_XOR "56"
+#define U8_BITFIELD_XOR "7"
+#define U16_BITFIELD_XOR "15"
+#define U32_BITFIELD_XOR "31"
+#define U64_BITFIELD_XOR "63"
+#else
+#define U16_XOR "0"
+#define U32_XOR "0"
+#define U64_XOR "0"
+#define U8_BITFIELD_XOR "0"
+#define U16_BITFIELD_XOR "0"
+#define U32_BITFIELD_XOR "0"
+#define U64_BITFIELD_XOR "0"
+#endif
+
+#if USB_HAVE_COMPAT_LINUX
+#define MFL_SIZE "1"
+#else
+#define MFL_SIZE "0"
+#endif
+
+#ifdef KLD_MODULE
+static const char __section("bus_autoconf_format") __used usb_id_format[] = {
+
+ /* Declare that three different sections use the same format */
+
+ "usb_host_id{256,:}"
+ "usb_device_id{256,:}"
+ "usb_dual_id{256,:}"
+
+ /* List size of fields in the usb_device_id structure */
+
+#if ULONG_MAX >= 0xFFFFFFFFUL
+ "unused{0,8}"
+ "unused{0,8}"
+ "unused{0,8}"
+ "unused{0,8}"
+#if ULONG_MAX >= 0xFFFFFFFFFFFFFFFFULL
+ "unused{0,8}"
+ "unused{0,8}"
+ "unused{0,8}"
+ "unused{0,8}"
+#endif
+#else
+#error "Please update code."
+#endif
+
+ "idVendor[0]{" U16_XOR ",8}"
+ "idVendor[1]{" U16_XOR ",8}"
+ "idProduct[0]{" U16_XOR ",8}"
+ "idProduct[1]{" U16_XOR ",8}"
+ "bcdDevice_lo[0]{" U16_XOR ",8}"
+ "bcdDevice_lo[1]{" U16_XOR ",8}"
+ "bcdDevice_hi[0]{" U16_XOR ",8}"
+ "bcdDevice_hi[1]{" U16_XOR ",8}"
+
+ "bDeviceClass{0,8}"
+ "bDeviceSubClass{0,8}"
+ "bDeviceProtocol{0,8}"
+ "bInterfaceClass{0,8}"
+ "bInterfaceSubClass{0,8}"
+ "bInterfaceProtocol{0,8}"
+
+ "mf_vendor{" U8_BITFIELD_XOR ",1}"
+ "mf_product{" U8_BITFIELD_XOR ",1}"
+ "mf_dev_lo{" U8_BITFIELD_XOR ",1}"
+ "mf_dev_hi{" U8_BITFIELD_XOR ",1}"
+
+ "mf_dev_class{" U8_BITFIELD_XOR ",1}"
+ "mf_dev_subclass{" U8_BITFIELD_XOR ",1}"
+ "mf_dev_protocol{" U8_BITFIELD_XOR ",1}"
+ "mf_int_class{" U8_BITFIELD_XOR ",1}"
+
+ "mf_int_subclass{" U8_BITFIELD_XOR ",1}"
+ "mf_int_protocol{" U8_BITFIELD_XOR ",1}"
+ "unused{" U8_BITFIELD_XOR ",6}"
+
+ "mfl_vendor{" U16_XOR "," MFL_SIZE "}"
+ "mfl_product{" U16_XOR "," MFL_SIZE "}"
+ "mfl_dev_lo{" U16_XOR "," MFL_SIZE "}"
+ "mfl_dev_hi{" U16_XOR "," MFL_SIZE "}"
+
+ "mfl_dev_class{" U16_XOR "," MFL_SIZE "}"
+ "mfl_dev_subclass{" U16_XOR "," MFL_SIZE "}"
+ "mfl_dev_protocol{" U16_XOR "," MFL_SIZE "}"
+ "mfl_int_class{" U16_XOR "," MFL_SIZE "}"
+
+ "mfl_int_subclass{" U16_XOR "," MFL_SIZE "}"
+ "mfl_int_protocol{" U16_XOR "," MFL_SIZE "}"
+ "unused{" U16_XOR "," MFL_SIZE "}"
+ "unused{" U16_XOR "," MFL_SIZE "}"
+
+ "unused{" U16_XOR "," MFL_SIZE "}"
+ "unused{" U16_XOR "," MFL_SIZE "}"
+ "unused{" U16_XOR "," MFL_SIZE "}"
+ "unused{" U16_XOR "," MFL_SIZE "}"
+};
+#endif
diff --git a/freebsd/sys/dev/usb/usb_mbuf.c b/freebsd/sys/dev/usb/usb_mbuf.c
index f2649679..c6ee8ee5 100644
--- a/freebsd/sys/dev/usb/usb_mbuf.c
+++ b/freebsd/sys/dev/usb/usb_mbuf.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
diff --git a/freebsd/sys/dev/usb/usb_msctest.c b/freebsd/sys/dev/usb/usb_msctest.c
index 77f199be..018809d7 100644
--- a/freebsd/sys/dev/usb/usb_msctest.c
+++ b/freebsd/sys/dev/usb/usb_msctest.c
@@ -2,7 +2,7 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,7 +42,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -87,7 +86,10 @@ enum {
DIR_NONE,
};
+#define SCSI_MAX_LEN 0x100
#define SCSI_INQ_LEN 0x24
+#define SCSI_SENSE_LEN 0xFF
+
static uint8_t scsi_test_unit_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_inquiry[] = { 0x12, 0x00, 0x00, 0x00, SCSI_INQ_LEN, 0x00 };
static uint8_t scsi_rezero_init[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -100,6 +102,10 @@ static uint8_t scsi_huawei_eject[] = { 0x11, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_tct_eject[] = { 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 };
+static uint8_t scsi_sync_cache[] = { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
#define BULK_SIZE 64 /* dummy */
#define ERR_CSW_FAILED -1
@@ -153,7 +159,7 @@ struct bbb_transfer {
uint8_t status_try;
int error;
- uint8_t buffer[256];
+ uint8_t buffer[SCSI_MAX_LEN] __aligned(4);
};
static usb_callback_t bbb_command_callback;
@@ -167,7 +173,7 @@ static void bbb_done(struct bbb_transfer *, int);
static void bbb_transfer_start(struct bbb_transfer *, uint8_t);
static void bbb_data_clear_stall_callback(struct usb_xfer *, uint8_t,
uint8_t);
-static uint8_t bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
+static int bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
void *, size_t, void *, size_t, usb_timeout_t);
static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t);
static void bbb_detach(struct bbb_transfer *);
@@ -179,6 +185,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = sizeof(struct bbb_cbw),
+ .flags = {.ext_buffer = 1,},
.callback = &bbb_command_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@@ -188,7 +195,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
+ .flags = {.ext_buffer = 1,.proxy_buffer = 1,.short_xfer_ok = 1,},
.callback = &bbb_data_read_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@@ -207,7 +214,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = BULK_SIZE,
- .flags = {.proxy_buffer = 1,},
+ .flags = {.ext_buffer = 1,.proxy_buffer = 1,},
.callback = &bbb_data_write_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@@ -226,7 +233,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = sizeof(struct bbb_csw),
- .flags = {.short_xfer_ok = 1,},
+ .flags = {.ext_buffer = 1,.short_xfer_ok = 1,},
.callback = &bbb_status_callback,
.timeout = 1 * USB_MS_HZ, /* 1 second */
},
@@ -414,7 +421,8 @@ static void
bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct bbb_transfer *sc = usbd_xfer_softc(xfer);
- int actlen, sumlen;
+ int actlen;
+ int sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
@@ -423,7 +431,7 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
/* very simple status check */
- if (actlen < sizeof(sc->csw)) {
+ if (actlen < (int)sizeof(sc->csw)) {
bbb_done(sc, USB_ERR_SHORT_XFER);
} else if (sc->csw.bCSWStatus == CSWSTATUS_GOOD) {
bbb_done(sc, 0); /* success */
@@ -458,7 +466,7 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
* 0: Success
* Else: Failure
*------------------------------------------------------------------------*/
-static uint8_t
+static int
bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
void *data_ptr, size_t data_len, void *cmd_ptr, size_t cmd_len,
usb_timeout_t data_timeout)
@@ -471,8 +479,8 @@ bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
sc->data_timeout = (data_timeout + USB_MS_HZ);
sc->actlen = 0;
sc->cmd_len = cmd_len;
- bzero(&sc->cbw.CBWCDB, sizeof(sc->cbw.CBWCDB));
- bcopy(cmd_ptr, &sc->cbw.CBWCDB, cmd_len);
+ memset(&sc->cbw.CBWCDB, 0, sizeof(sc->cbw.CBWCDB));
+ memcpy(&sc->cbw.CBWCDB, cmd_ptr, cmd_len);
DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, &sc->cbw.CBWCDB, ":");
mtx_lock(&sc->mtx);
@@ -492,6 +500,19 @@ bbb_attach(struct usb_device *udev, uint8_t iface_index)
struct usb_interface_descriptor *id;
struct bbb_transfer *sc;
usb_error_t err;
+ uint8_t do_unlock;
+
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
+
+ /*
+ * Make sure any driver which is hooked up to this interface,
+ * like umass is gone:
+ */
+ usb_detach_device(udev, iface_index, 0);
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
iface = usbd_get_iface(udev, iface_index);
if (iface == NULL)
@@ -552,9 +573,10 @@ int
usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
{
struct bbb_transfer *sc;
- usb_error_t err;
- uint8_t timeout, is_cdrom;
+ uint8_t timeout;
+ uint8_t is_cdrom;
uint8_t sid_type;
+ int err;
sc = bbb_attach(udev, iface_index);
if (sc == NULL)
@@ -580,6 +602,142 @@ usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
return (is_cdrom);
}
+static uint8_t
+usb_msc_get_max_lun(struct usb_device *udev, uint8_t iface_index)
+{
+ struct usb_device_request req;
+ usb_error_t err;
+ uint8_t buf = 0;
+
+
+ /* The Get Max Lun command is a class-specific request. */
+ req.bmRequestType = UT_READ_CLASS_INTERFACE;
+ req.bRequest = 0xFE; /* GET_MAX_LUN */
+ USETW(req.wValue, 0);
+ req.wIndex[0] = iface_index;
+ req.wIndex[1] = 0;
+ USETW(req.wLength, 1);
+
+ err = usbd_do_request(udev, NULL, &req, &buf);
+ if (err)
+ buf = 0;
+
+ return (buf);
+}
+
+usb_error_t
+usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
+{
+ struct bbb_transfer *sc;
+ uint8_t timeout;
+ uint8_t is_no_direct;
+ uint8_t sid_type;
+ int err;
+
+ sc = bbb_attach(udev, iface_index);
+ if (sc == NULL)
+ return (0);
+
+ /*
+ * Some devices need a delay after that the configuration
+ * value is set to function properly:
+ */
+ usb_pause_mtx(NULL, hz);
+
+ if (usb_msc_get_max_lun(udev, iface_index) == 0) {
+ DPRINTF("Device has only got one LUN.\n");
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_GETMAXLUN);
+ }
+
+ is_no_direct = 1;
+ for (timeout = 4; timeout; timeout--) {
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+ SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
+ USB_MS_HZ);
+
+ if (err == 0 && sc->actlen > 0) {
+ sid_type = sc->buffer[0] & 0x1F;
+ if (sid_type == 0x00)
+ is_no_direct = 0;
+ break;
+ } else if (err != ERR_CSW_FAILED)
+ break; /* non retryable error */
+ usb_pause_mtx(NULL, hz);
+ }
+
+ if (is_no_direct) {
+ DPRINTF("Device is not direct access.\n");
+ goto done;
+ }
+
+ err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
+ &scsi_test_unit_ready, sizeof(scsi_test_unit_ready),
+ USB_MS_HZ);
+
+ if (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+
+ err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
+ &scsi_sync_cache, sizeof(scsi_sync_cache),
+ USB_MS_HZ);
+
+ if (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+
+ DPRINTF("Device doesn't handle synchronize cache\n");
+
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+ }
+
+ /* clear sense status of any failed commands on the device */
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+ SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
+ USB_MS_HZ);
+
+ DPRINTF("Inquiry = %d\n", err);
+
+ if (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+ SCSI_SENSE_LEN, &scsi_request_sense,
+ sizeof(scsi_request_sense), USB_MS_HZ);
+
+ DPRINTF("Request sense = %d\n", err);
+
+ if (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+
+done:
+ bbb_detach(sc);
+ return (0);
+
+error:
+ bbb_detach(sc);
+
+ DPRINTF("Device did not respond, enabling all quirks\n");
+
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY);
+
+ /* Need to re-enumerate the device */
+ usbd_req_re_enumerate(udev, NULL);
+
+ return (USB_ERR_STALLED);
+}
+
usb_error_t
usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
{
diff --git a/freebsd/sys/dev/usb/usb_msctest.h b/freebsd/sys/dev/usb/usb_msctest.h
index 807d5f5d..e4a717fe 100644
--- a/freebsd/sys/dev/usb/usb_msctest.h
+++ b/freebsd/sys/dev/usb/usb_msctest.h
@@ -40,5 +40,7 @@ int usb_iface_is_cdrom(struct usb_device *udev,
uint8_t iface_index);
usb_error_t usb_msc_eject(struct usb_device *udev,
uint8_t iface_index, int method);
+usb_error_t usb_msc_auto_quirk(struct usb_device *udev,
+ uint8_t iface_index);
#endif /* _USB_MSCTEST_H_ */
diff --git a/freebsd/sys/dev/usb/usb_parse.c b/freebsd/sys/dev/usb/usb_parse.c
index 6b055db7..f2529d12 100644
--- a/freebsd/sys/dev/usb/usb_parse.c
+++ b/freebsd/sys/dev/usb/usb_parse.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
diff --git a/freebsd/sys/dev/usb/usb_pf.h b/freebsd/sys/dev/usb/usb_pf.h
new file mode 100644
index 00000000..9d51e98c
--- /dev/null
+++ b/freebsd/sys/dev/usb/usb_pf.h
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 1990, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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$
+ */
+
+#ifndef _DEV_USB_PF_H
+#define _DEV_USB_PF_H
+
+struct usbpf_pkthdr {
+ uint32_t up_totlen; /* Total length including all headers */
+ uint32_t up_busunit; /* Host controller unit number */
+ uint8_t up_address; /* USB device index */
+ uint8_t up_mode; /* Mode of transfer */
+#define USBPF_MODE_HOST 0
+#define USBPF_MODE_DEVICE 1
+ uint8_t up_type; /* points SUBMIT / DONE */
+ uint8_t up_xfertype; /* Transfer type, see USB2.0 spec. */
+ uint32_t up_flags; /* Transfer flags */
+#define USBPF_FLAG_FORCE_SHORT_XFER (1 << 0)
+#define USBPF_FLAG_SHORT_XFER_OK (1 << 1)
+#define USBPF_FLAG_SHORT_FRAMES_OK (1 << 2)
+#define USBPF_FLAG_PIPE_BOF (1 << 3)
+#define USBPF_FLAG_PROXY_BUFFER (1 << 4)
+#define USBPF_FLAG_EXT_BUFFER (1 << 5)
+#define USBPF_FLAG_MANUAL_STATUS (1 << 6)
+#define USBPF_FLAG_NO_PIPE_OK (1 << 7)
+#define USBPF_FLAG_STALL_PIPE (1 << 8)
+ uint32_t up_status; /* Transfer status */
+#define USBPF_STATUS_OPEN (1 << 0)
+#define USBPF_STATUS_TRANSFERRING (1 << 1)
+#define USBPF_STATUS_DID_DMA_DELAY (1 << 2)
+#define USBPF_STATUS_DID_CLOSE (1 << 3)
+#define USBPF_STATUS_DRAINING (1 << 4)
+#define USBPF_STATUS_STARTED (1 << 5)
+#define USBPF_STATUS_BW_RECLAIMED (1 << 6)
+#define USBPF_STATUS_CONTROL_XFR (1 << 7)
+#define USBPF_STATUS_CONTROL_HDR (1 << 8)
+#define USBPF_STATUS_CONTROL_ACT (1 << 9)
+#define USBPF_STATUS_CONTROL_STALL (1 << 10)
+#define USBPF_STATUS_SHORT_FRAMES_OK (1 << 11)
+#define USBPF_STATUS_SHORT_XFER_OK (1 << 12)
+#define USBPF_STATUS_BDMA_ENABLE (1 << 13)
+#define USBPF_STATUS_BDMA_NO_POST_SYNC (1 << 14)
+#define USBPF_STATUS_BDMA_SETUP (1 << 15)
+#define USBPF_STATUS_ISOCHRONOUS_XFR (1 << 16)
+#define USBPF_STATUS_CURR_DMA_SET (1 << 17)
+#define USBPF_STATUS_CAN_CANCEL_IMMED (1 << 18)
+#define USBPF_STATUS_DOING_CALLBACK (1 << 19)
+ uint32_t up_error; /* USB error, see USB_ERR_XXX */
+ uint32_t up_interval; /* For interrupt and isoc (ms) */
+ uint32_t up_frames; /* Number of following frames */
+ uint32_t up_packet_size; /* Packet size used */
+ uint32_t up_packet_count; /* Packet count used */
+ uint32_t up_endpoint; /* USB endpoint / stream ID */
+ uint8_t up_speed; /* USB speed, see USB_SPEED_XXX */
+ /* sizeof(struct usbpf_pkthdr) == 128 bytes */
+ uint8_t up_reserved[83];
+};
+
+struct usbpf_framehdr {
+ /*
+ * The frame length field excludes length of frame header and
+ * any alignment.
+ */
+ uint32_t length;
+#define USBPF_FRAME_ALIGN(x) (((x) + 3) & ~3)
+ uint32_t flags;
+#define USBPF_FRAMEFLAG_READ (1 << 0)
+#define USBPF_FRAMEFLAG_DATA_FOLLOWS (1 << 1)
+};
+
+#define USBPF_HDR_LEN 128 /* bytes */
+#define USBPF_FRAME_HDR_LEN 8 /* bytes */
+
+extern uint8_t usbpf_pkthdr_size_ok[
+ (sizeof(struct usbpf_pkthdr) == USBPF_HDR_LEN) ? 1 : -1];
+extern uint8_t usbpf_framehdr_size_ok[
+ (sizeof(struct usbpf_framehdr) == USBPF_FRAME_HDR_LEN) ? 1 : -1];
+
+#define USBPF_XFERTAP_SUBMIT 0
+#define USBPF_XFERTAP_DONE 1
+
+#ifdef _KERNEL
+void usbpf_attach(struct usb_bus *);
+void usbpf_detach(struct usb_bus *);
+void usbpf_xfertap(struct usb_xfer *, int);
+#endif
+
+#endif
diff --git a/freebsd/sys/dev/usb/usb_process.c b/freebsd/sys/dev/usb/usb_process.c
index 8cb00473..99e2d306 100644
--- a/freebsd/sys/dev/usb/usb_process.c
+++ b/freebsd/sys/dev/usb/usb_process.c
@@ -36,7 +36,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -70,11 +69,17 @@ static int usb_pcount;
#define USB_THREAD_CREATE(f, s, p, ...) \
kproc_kthread_add((f), (s), &usbproc, (p), RFHIGHPID, \
0, "usb", __VA_ARGS__)
+#if (__FreeBSD_version >= 900000)
+#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check()
+#else
+#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check(curthread)
+#endif
#define USB_THREAD_SUSPEND(p) kthread_suspend(p,0)
#define USB_THREAD_EXIT(err) kthread_exit()
#else
#define USB_THREAD_CREATE(f, s, p, ...) \
kthread_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__)
+#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check(curproc)
#define USB_THREAD_SUSPEND(p) kthread_suspend(p,0)
#define USB_THREAD_EXIT(err) kthread_exit(err)
#endif
@@ -83,9 +88,8 @@ static int usb_pcount;
static int usb_proc_debug;
SYSCTL_NODE(_hw_usb, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process");
-SYSCTL_INT(_hw_usb_proc, OID_AUTO, debug, CTLFLAG_RW, &usb_proc_debug, 0,
+SYSCTL_INT(_hw_usb_proc, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &usb_proc_debug, 0,
"Debug level");
-
TUNABLE_INT("hw.usb.proc.debug", &usb_proc_debug);
#endif
@@ -101,6 +105,11 @@ usb_process(void *arg)
struct usb_proc_msg *pm;
struct thread *td;
+ /* in case of attach error, check for suspended */
+#ifndef __rtems__
+ USB_THREAD_SUSPEND_CHECK();
+#endif /* __rtems__ */
+
/* adjust priority */
td = curthread;
#ifndef __rtems__
@@ -365,7 +374,12 @@ usb_proc_is_gone(struct usb_process *up)
if (up->up_gone)
return (1);
- mtx_assert(up->up_mtx, MA_OWNED);
+ /*
+ * Allow calls when up_mtx is NULL, before the USB process
+ * structure is initialised.
+ */
+ if (up->up_mtx != NULL)
+ mtx_assert(up->up_mtx, MA_OWNED);
return (0);
}
@@ -471,7 +485,7 @@ usb_proc_drain(struct usb_process *up)
/*------------------------------------------------------------------------*
* usb_proc_rewakeup
*
- * This function is called to re-wakeup the the given USB
+ * This function is called to re-wakeup the given USB
* process. This usually happens after that the USB system has been in
* polling mode, like during a panic. This function must be called
* having "up->up_mtx" locked.
diff --git a/freebsd/sys/dev/usb/usb_process.h b/freebsd/sys/dev/usb/usb_process.h
index b4159af1..23cf6607 100644
--- a/freebsd/sys/dev/usb/usb_process.h
+++ b/freebsd/sys/dev/usb/usb_process.h
@@ -27,11 +27,13 @@
#ifndef _USB_PROCESS_H_
#define _USB_PROCESS_H_
+#include <sys/interrupt.h>
#include <sys/priority.h>
+#include <sys/runq.h>
/* defines */
-#define USB_PRI_HIGH PI_NET
-#define USB_PRI_MED PI_DISK
+#define USB_PRI_HIGH PI_SWI(SWI_NET)
+#define USB_PRI_MED PI_SWI(SWI_CAMBIO)
#define USB_PROC_WAIT_TIMEOUT 2
#define USB_PROC_WAIT_DRAIN 1
diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c
index 8d17c202..cb3b030c 100644
--- a/freebsd/sys/dev/usb/usb_request.c
+++ b/freebsd/sys/dev/usb/usb_request.c
@@ -36,7 +36,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -70,22 +69,19 @@
#include <dev/usb/usb_bus.h>
#include <sys/ctype.h>
-#ifdef USB_DEBUG
-static int usb_pr_poll_delay = USB_PORT_RESET_DELAY;
-static int usb_pr_recovery_delay = USB_PORT_RESET_RECOVERY;
+static int usb_no_cs_fail;
-SYSCTL_INT(_hw_usb, OID_AUTO, pr_poll_delay, CTLFLAG_RW,
- &usb_pr_poll_delay, 0, "USB port reset poll delay in ms");
-SYSCTL_INT(_hw_usb, OID_AUTO, pr_recovery_delay, CTLFLAG_RW,
- &usb_pr_recovery_delay, 0, "USB port reset recovery delay in ms");
+SYSCTL_INT(_hw_usb, OID_AUTO, no_cs_fail, CTLFLAG_RW,
+ &usb_no_cs_fail, 0, "USB clear stall failures are ignored, if set");
+#ifdef USB_DEBUG
#ifdef USB_REQ_DEBUG
/* The following structures are used in connection to fault injection. */
struct usb_ctrl_debug {
int bus_index; /* target bus */
int dev_index; /* target address */
int ds_fail; /* fail data stage */
- int ss_fail; /* fail data stage */
+ int ss_fail; /* fail status stage */
int ds_delay; /* data stage delay in ms */
int ss_delay; /* status stage delay in ms */
int bmRequestType_value;
@@ -241,6 +237,10 @@ usb_do_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
+tr_transferred:
+ /* reset error counter */
+ udev->clear_stall_errors = 0;
+
if (ep == NULL)
goto tr_setup; /* device was unconfigured */
if (ep->edesc &&
@@ -292,8 +292,30 @@ tr_setup:
goto tr_setup;
default:
- if (xfer->error == USB_ERR_CANCELLED) {
+ if (error == USB_ERR_CANCELLED)
break;
+
+ DPRINTF("Clear stall failed.\n");
+
+ /*
+ * Some VMs like VirtualBox always return failure on
+ * clear-stall which we sometimes should just ignore.
+ */
+ if (usb_no_cs_fail)
+ goto tr_transferred;
+ if (udev->clear_stall_errors == USB_CS_RESET_LIMIT)
+ goto tr_setup;
+
+ if (error == USB_ERR_TIMEOUT) {
+ udev->clear_stall_errors = USB_CS_RESET_LIMIT;
+ DPRINTF("Trying to re-enumerate.\n");
+ usbd_start_re_enumerate(udev);
+ } else {
+ udev->clear_stall_errors++;
+ if (udev->clear_stall_errors == USB_CS_RESET_LIMIT) {
+ DPRINTF("Trying to re-enumerate.\n");
+ usbd_start_re_enumerate(udev);
+ }
}
goto tr_setup;
}
@@ -362,9 +384,8 @@ usbd_get_hr_func(struct usb_device *udev)
* than 30 seconds is treated like a 30 second timeout. This USB stack
* does not allow control requests without a timeout.
*
- * NOTE: This function is thread safe. All calls to
- * "usbd_do_request_flags" will be serialised by the use of an
- * internal "sx_lock".
+ * NOTE: This function is thread safe. All calls to "usbd_do_request_flags"
+ * will be serialized by the use of the USB device enumeration lock.
*
* Returns:
* 0: Success
@@ -388,7 +409,7 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx,
uint16_t length;
uint16_t temp;
uint16_t acttemp;
- uint8_t enum_locked;
+ uint8_t do_unlock;
if (timeout < 50) {
/* timeout is too small */
@@ -400,8 +421,6 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx,
}
length = UGETW(req->wLength);
- enum_locked = usbd_enum_is_locked(udev);
-
DPRINTFN(5, "udev=%p bmRequestType=0x%02x bRequest=0x%02x "
"wValue=0x%02x%02x wIndex=0x%02x%02x wLength=0x%02x%02x\n",
udev, req->bmRequestType, req->bRequest,
@@ -432,17 +451,16 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx,
}
/*
- * We need to allow suspend and resume at this point, else the
- * control transfer will timeout if the device is suspended!
+ * Grab the USB device enumeration SX-lock serialization is
+ * achieved when multiple threads are involved:
*/
- if (enum_locked)
- usbd_sr_unlock(udev);
+ do_unlock = usbd_enum_lock(udev);
/*
- * Grab the default sx-lock so that serialisation
- * is achieved when multiple threads are involved:
+ * We need to allow suspend and resume at this point, else the
+ * control transfer will timeout if the device is suspended!
*/
- sx_xlock(&udev->ctrl_sx);
+ usbd_sr_unlock(udev);
hr_func = usbd_get_hr_func(udev);
@@ -489,7 +507,7 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx,
}
} else
#endif
- bcopy(desc, data, length);
+ memcpy(data, desc, length);
}
goto done; /* success */
}
@@ -686,10 +704,10 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx,
USB_XFER_UNLOCK(xfer);
done:
- sx_xunlock(&udev->ctrl_sx);
+ usbd_sr_lock(udev);
- if (enum_locked)
- usbd_sr_lock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
if ((mtx != NULL) && (mtx != &Giant))
mtx_lock(mtx);
@@ -757,52 +775,52 @@ usbd_req_reset_port(struct usb_device *udev, struct mtx *mtx, uint8_t port)
struct usb_port_status ps;
usb_error_t err;
uint16_t n;
+ uint16_t status;
+ uint16_t change;
-#ifdef USB_DEBUG
- uint16_t pr_poll_delay;
- uint16_t pr_recovery_delay;
+ DPRINTF("\n");
-#endif
- err = usbd_req_set_port_feature(udev, mtx, port, UHF_PORT_RESET);
- if (err) {
+ /* clear any leftover port reset changes first */
+ usbd_req_clear_port_feature(
+ udev, mtx, port, UHF_C_PORT_RESET);
+
+ /* assert port reset on the given port */
+ err = usbd_req_set_port_feature(
+ udev, mtx, port, UHF_PORT_RESET);
+
+ /* check for errors */
+ if (err)
goto done;
- }
#ifdef USB_DEBUG
- /* range check input parameters */
- pr_poll_delay = usb_pr_poll_delay;
- if (pr_poll_delay < 1) {
- pr_poll_delay = 1;
- } else if (pr_poll_delay > 1000) {
- pr_poll_delay = 1000;
- }
- pr_recovery_delay = usb_pr_recovery_delay;
- if (pr_recovery_delay > 1000) {
- pr_recovery_delay = 1000;
- }
#endif
n = 0;
while (1) {
-#ifdef USB_DEBUG
/* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_poll_delay));
- n += pr_poll_delay;
-#else
- /* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_DELAY));
- n += USB_PORT_RESET_DELAY;
-#endif
+ usb_pause_mtx(mtx, USB_MS_TO_TICKS(usb_port_reset_delay));
+ n += usb_port_reset_delay;
err = usbd_req_get_port_status(udev, mtx, &ps, port);
- if (err) {
+ if (err)
goto done;
- }
+
+ status = UGETW(ps.wPortStatus);
+ change = UGETW(ps.wPortChange);
+
/* if the device disappeared, just give up */
- if (!(UGETW(ps.wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) {
+ if (!(status & UPS_CURRENT_CONNECT_STATUS))
goto done;
- }
+
/* check if reset is complete */
- if (UGETW(ps.wPortChange) & UPS_C_PORT_RESET) {
+ if (change & UPS_C_PORT_RESET)
break;
- }
+
+ /*
+ * Some Virtual Machines like VirtualBox 4.x fail to
+ * generate a port reset change event. Check if reset
+ * is no longer asserted.
+ */
+ if (!(status & UPS_RESET))
+ break;
+
/* check for timeout */
if (n > 1000) {
n = 0;
@@ -813,21 +831,16 @@ usbd_req_reset_port(struct usb_device *udev, struct mtx *mtx, uint8_t port)
/* clear port reset first */
err = usbd_req_clear_port_feature(
udev, mtx, port, UHF_C_PORT_RESET);
- if (err) {
+ if (err)
goto done;
- }
+
/* check for timeout */
if (n == 0) {
err = USB_ERR_TIMEOUT;
goto done;
}
-#ifdef USB_DEBUG
- /* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_recovery_delay));
-#else
/* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_RECOVERY));
-#endif
+ usb_pause_mtx(mtx, USB_MS_TO_TICKS(usb_port_reset_recovery));
done:
DPRINTFN(2, "port %d reset returning error=%s\n",
@@ -849,57 +862,64 @@ done:
* disabled.
*------------------------------------------------------------------------*/
usb_error_t
-usbd_req_warm_reset_port(struct usb_device *udev, struct mtx *mtx, uint8_t port)
+usbd_req_warm_reset_port(struct usb_device *udev, struct mtx *mtx,
+ uint8_t port)
{
struct usb_port_status ps;
usb_error_t err;
uint16_t n;
+ uint16_t status;
+ uint16_t change;
-#ifdef USB_DEBUG
- uint16_t pr_poll_delay;
- uint16_t pr_recovery_delay;
+ DPRINTF("\n");
-#endif
- err = usbd_req_set_port_feature(udev, mtx, port, UHF_BH_PORT_RESET);
- if (err) {
+ err = usbd_req_get_port_status(udev, mtx, &ps, port);
+ if (err)
goto done;
+
+ status = UGETW(ps.wPortStatus);
+
+ switch (UPS_PORT_LINK_STATE_GET(status)) {
+ case UPS_PORT_LS_U3:
+ case UPS_PORT_LS_COMP_MODE:
+ case UPS_PORT_LS_LOOPBACK:
+ case UPS_PORT_LS_SS_INA:
+ break;
+ default:
+ DPRINTF("Wrong state for warm reset\n");
+ return (0);
}
-#ifdef USB_DEBUG
- /* range check input parameters */
- pr_poll_delay = usb_pr_poll_delay;
- if (pr_poll_delay < 1) {
- pr_poll_delay = 1;
- } else if (pr_poll_delay > 1000) {
- pr_poll_delay = 1000;
- }
- pr_recovery_delay = usb_pr_recovery_delay;
- if (pr_recovery_delay > 1000) {
- pr_recovery_delay = 1000;
- }
-#endif
+
+ /* clear any leftover warm port reset changes first */
+ usbd_req_clear_port_feature(udev, mtx,
+ port, UHF_C_BH_PORT_RESET);
+
+ /* set warm port reset */
+ err = usbd_req_set_port_feature(udev, mtx,
+ port, UHF_BH_PORT_RESET);
+ if (err)
+ goto done;
+
n = 0;
while (1) {
-#ifdef USB_DEBUG
- /* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_poll_delay));
- n += pr_poll_delay;
-#else
/* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_DELAY));
- n += USB_PORT_RESET_DELAY;
-#endif
+ usb_pause_mtx(mtx, USB_MS_TO_TICKS(usb_port_reset_delay));
+ n += usb_port_reset_delay;
err = usbd_req_get_port_status(udev, mtx, &ps, port);
- if (err) {
+ if (err)
goto done;
- }
+
+ status = UGETW(ps.wPortStatus);
+ change = UGETW(ps.wPortChange);
+
/* if the device disappeared, just give up */
- if (!(UGETW(ps.wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) {
+ if (!(status & UPS_CURRENT_CONNECT_STATUS))
goto done;
- }
+
/* check if reset is complete */
- if (UGETW(ps.wPortChange) & UPS_C_BH_PORT_RESET) {
+ if (change & UPS_C_BH_PORT_RESET)
break;
- }
+
/* check for timeout */
if (n > 1000) {
n = 0;
@@ -910,21 +930,16 @@ usbd_req_warm_reset_port(struct usb_device *udev, struct mtx *mtx, uint8_t port)
/* clear port reset first */
err = usbd_req_clear_port_feature(
udev, mtx, port, UHF_C_BH_PORT_RESET);
- if (err) {
+ if (err)
goto done;
- }
+
/* check for timeout */
if (n == 0) {
err = USB_ERR_TIMEOUT;
goto done;
}
-#ifdef USB_DEBUG
- /* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_recovery_delay));
-#else
/* wait for the device to recover from reset */
- usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_RECOVERY));
-#endif
+ usb_pause_mtx(mtx, USB_MS_TO_TICKS(usb_port_reset_recovery));
done:
DPRINTFN(2, "port %d warm reset returning error=%s\n",
@@ -1119,14 +1134,21 @@ usbd_req_get_string_any(struct usb_device *udev, struct mtx *mtx, char *buf,
}
/*
- * Filter by default - we don't allow greater and less than
- * signs because they might confuse the dmesg printouts!
+ * Filter by default - We only allow alphanumerical
+ * and a few more to avoid any problems with scripts
+ * and daemons.
*/
- if ((*s == '<') || (*s == '>') || (!isprint(*s))) {
- /* silently skip bad character */
- continue;
+ if (isalpha(*s) ||
+ isdigit(*s) ||
+ *s == '-' ||
+ *s == '+' ||
+ *s == ' ' ||
+ *s == '.' ||
+ *s == ',') {
+ /* allowed */
+ s++;
}
- s++;
+ /* silently skip bad character */
}
*s = 0; /* zero terminate resulting string */
return (USB_ERR_NORMAL_COMPLETION);
@@ -1222,7 +1244,7 @@ usbd_req_get_config_desc(struct usb_device *udev, struct mtx *mtx,
goto done;
}
/* Extra sanity checking */
- if (UGETW(d->wTotalLength) < sizeof(*d)) {
+ if (UGETW(d->wTotalLength) < (uint16_t)sizeof(*d)) {
err = USB_ERR_INVAL;
}
done:
@@ -1476,7 +1498,7 @@ usbd_req_set_address(struct usb_device *udev, struct mtx *mtx, uint16_t addr)
done:
/* allow device time to set new address */
usb_pause_mtx(mtx,
- USB_MS_TO_TICKS(USB_SET_ADDRESS_SETTLE));
+ USB_MS_TO_TICKS(usb_set_address_settle));
return (err);
}
@@ -1725,7 +1747,7 @@ usbd_req_get_report(struct usb_device *udev, struct mtx *mtx, void *data,
struct usb_interface *iface = usbd_get_iface(udev, iface_index);
struct usb_device_request req;
- if ((iface == NULL) || (iface->idesc == NULL) || (id == 0)) {
+ if ((iface == NULL) || (iface->idesc == NULL)) {
return (USB_ERR_INVAL);
}
DPRINTFN(5, "len=%d\n", len);
@@ -1932,6 +1954,27 @@ usbd_req_re_enumerate(struct usb_device *udev, struct mtx *mtx)
return (USB_ERR_INVAL);
}
retry:
+ /*
+ * Try to reset the High Speed parent HUB of a LOW- or FULL-
+ * speed device, if any.
+ */
+ if (udev->parent_hs_hub != NULL &&
+ udev->speed != USB_SPEED_HIGH) {
+ DPRINTF("Trying to reset parent High Speed TT.\n");
+ err = usbd_req_reset_tt(udev->parent_hs_hub, NULL,
+ udev->hs_port_no);
+ if (err) {
+ DPRINTF("Resetting parent High "
+ "Speed TT failed (%s).\n",
+ usbd_errstr(err));
+ }
+ }
+
+ /* Try to warm reset first */
+ if (parent_hub->speed == USB_SPEED_SUPER)
+ usbd_req_warm_reset_port(parent_hub, mtx, udev->port_no);
+
+ /* Try to reset the parent HUB port. */
err = usbd_req_reset_port(parent_hub, mtx, udev->port_no);
if (err) {
DPRINTFN(0, "addr=%d, port reset failed, %s\n",
@@ -2029,3 +2072,89 @@ usbd_req_set_device_feature(struct usb_device *udev, struct mtx *mtx,
USETW(req.wLength, 0);
return (usbd_do_request(udev, mtx, &req, 0));
}
+
+/*------------------------------------------------------------------------*
+ * usbd_req_reset_tt
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_req_reset_tt(struct usb_device *udev, struct mtx *mtx,
+ uint8_t port)
+{
+ struct usb_device_request req;
+
+ /* For single TT HUBs the port should be 1 */
+
+ if (udev->ddesc.bDeviceClass == UDCLASS_HUB &&
+ udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBSTT)
+ port = 1;
+
+ req.bmRequestType = UT_WRITE_CLASS_OTHER;
+ req.bRequest = UR_RESET_TT;
+ USETW(req.wValue, 0);
+ req.wIndex[0] = port;
+ req.wIndex[1] = 0;
+ USETW(req.wLength, 0);
+ return (usbd_do_request(udev, mtx, &req, 0));
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_req_clear_tt_buffer
+ *
+ * For single TT HUBs the port should be 1.
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_req_clear_tt_buffer(struct usb_device *udev, struct mtx *mtx,
+ uint8_t port, uint8_t addr, uint8_t type, uint8_t endpoint)
+{
+ struct usb_device_request req;
+ uint16_t wValue;
+
+ /* For single TT HUBs the port should be 1 */
+
+ if (udev->ddesc.bDeviceClass == UDCLASS_HUB &&
+ udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBSTT)
+ port = 1;
+
+ wValue = (endpoint & 0xF) | ((addr & 0x7F) << 4) |
+ ((endpoint & 0x80) << 8) | ((type & 3) << 12);
+
+ req.bmRequestType = UT_WRITE_CLASS_OTHER;
+ req.bRequest = UR_CLEAR_TT_BUFFER;
+ USETW(req.wValue, wValue);
+ req.wIndex[0] = port;
+ req.wIndex[1] = 0;
+ USETW(req.wLength, 0);
+ return (usbd_do_request(udev, mtx, &req, 0));
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_req_set_port_link_state
+ *
+ * USB 3.0 specific request
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_req_set_port_link_state(struct usb_device *udev, struct mtx *mtx,
+ uint8_t port, uint8_t link_state)
+{
+ struct usb_device_request req;
+
+ req.bmRequestType = UT_WRITE_CLASS_OTHER;
+ req.bRequest = UR_SET_FEATURE;
+ USETW(req.wValue, UHF_PORT_LINK_STATE);
+ req.wIndex[0] = port;
+ req.wIndex[1] = link_state;
+ USETW(req.wLength, 0);
+ return (usbd_do_request(udev, mtx, &req, 0));
+}
diff --git a/freebsd/sys/dev/usb/usb_request.h b/freebsd/sys/dev/usb/usb_request.h
index 12f373d5..74823af2 100644
--- a/freebsd/sys/dev/usb/usb_request.h
+++ b/freebsd/sys/dev/usb/usb_request.h
@@ -85,5 +85,11 @@ usb_error_t usbd_req_set_hub_u2_timeout(struct usb_device *udev,
struct mtx *mtx, uint8_t port, uint8_t timeout);
usb_error_t usbd_req_set_hub_depth(struct usb_device *udev,
struct mtx *mtx, uint16_t depth);
+usb_error_t usbd_req_reset_tt(struct usb_device *udev, struct mtx *mtx,
+ uint8_t port);
+usb_error_t usbd_req_clear_tt_buffer(struct usb_device *udev, struct mtx *mtx,
+ uint8_t port, uint8_t addr, uint8_t type, uint8_t endpoint);
+usb_error_t usbd_req_set_port_link_state(struct usb_device *udev,
+ struct mtx *mtx, uint8_t port, uint8_t link_state);
#endif /* _USB_REQUEST_H_ */
diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c
index 17a492e5..a8b0b0ac 100644
--- a/freebsd/sys/dev/usb/usb_transfer.c
+++ b/freebsd/sys/dev/usb/usb_transfer.c
@@ -24,7 +24,7 @@
* 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.
- */
+ */
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -45,6 +44,7 @@
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
+#include <sys/proc.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -62,6 +62,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#include <dev/usb/usb_pf.h>
#ifdef __rtems__
#include <machine/rtems-bsd-cache.h>
#endif /* __rtems__ */
@@ -228,12 +229,12 @@ usbd_transfer_setup_sub_malloc(struct usb_setup_params *parm,
* Try multi-allocation chunks to reduce the number of DMA
* allocations, hence DMA allocations are slow.
*/
- if (size >= PAGE_SIZE) {
+ if (size >= USB_PAGE_SIZE) {
n_dma_pc = count;
n_obj = 1;
} else {
/* compute number of objects per page */
- n_obj = (PAGE_SIZE / size);
+ n_obj = (USB_PAGE_SIZE / size);
/*
* Compute number of DMA chunks, rounded up
* to nearest one:
@@ -483,6 +484,8 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
xfer->fps_shift--;
if (xfer->fps_shift > 3)
xfer->fps_shift = 3;
+ if (xfer->flags.pre_scale_frames != 0)
+ xfer->nframes <<= (3 - xfer->fps_shift);
break;
}
@@ -674,9 +677,13 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
}
xfer->max_data_length -= REQ_SIZE;
}
- /* setup "frlengths" */
+ /*
+ * Setup "frlengths" and shadow "frlengths" for keeping the
+ * initial frame lengths when a USB transfer is complete. This
+ * information is useful when computing isochronous offsets.
+ */
xfer->frlengths = parm->xfer_length_ptr;
- parm->xfer_length_ptr += n_frlengths;
+ parm->xfer_length_ptr += 2 * n_frlengths;
/* setup "frbuffers" */
xfer->frbuffers = parm->xfer_page_cache_ptr;
@@ -833,20 +840,17 @@ usbd_transfer_setup(struct usb_device *udev,
const struct usb_config *setup_start, uint16_t n_setup,
void *priv_sc, struct mtx *xfer_mtx)
{
- struct usb_xfer dummy;
- struct usb_setup_params parm;
const struct usb_config *setup_end = setup_start + n_setup;
const struct usb_config *setup;
+ struct usb_setup_params *parm;
struct usb_endpoint *ep;
struct usb_xfer_root *info;
struct usb_xfer *xfer;
void *buf = NULL;
+ usb_error_t error = 0;
uint16_t n;
uint16_t refcount;
-
- parm.err = 0;
- refcount = 0;
- info = NULL;
+ uint8_t do_unlock;
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
"usbd_transfer_setup can sleep!");
@@ -865,31 +869,40 @@ usbd_transfer_setup(struct usb_device *udev,
DPRINTFN(6, "using global lock\n");
xfer_mtx = &Giant;
}
- /* sanity checks */
+
+ /* more sanity checks */
+
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
if (setup->bufsize == (usb_frlength_t)-1) {
- parm.err = USB_ERR_BAD_BUFSIZE;
+ error = USB_ERR_BAD_BUFSIZE;
DPRINTF("invalid bufsize\n");
}
if (setup->callback == NULL) {
- parm.err = USB_ERR_NO_CALLBACK;
+ error = USB_ERR_NO_CALLBACK;
DPRINTF("no callback\n");
}
ppxfer[n] = NULL;
}
- if (parm.err) {
- goto done;
- }
- bzero(&parm, sizeof(parm));
+ if (error)
+ return (error);
+
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
+
+ refcount = 0;
+ info = NULL;
- parm.udev = udev;
- parm.speed = usbd_get_speed(udev);
- parm.hc_max_packet_count = 1;
+ parm = &udev->scratch.xfer_setup[0].parm;
+ memset(parm, 0, sizeof(*parm));
- if (parm.speed >= USB_SPEED_MAX) {
- parm.err = USB_ERR_INVAL;
+ parm->udev = udev;
+ parm->speed = usbd_get_speed(udev);
+ parm->hc_max_packet_count = 1;
+
+ if (parm->speed >= USB_SPEED_MAX) {
+ parm->err = USB_ERR_INVAL;
goto done;
}
/* setup all transfers */
@@ -904,22 +917,22 @@ usbd_transfer_setup(struct usb_device *udev,
info = USB_ADD_BYTES(buf, 0);
info->memory_base = buf;
- info->memory_size = parm.size[0];
+ info->memory_size = parm->size[0];
#if USB_HAVE_BUSDMA
- info->dma_page_cache_start = USB_ADD_BYTES(buf, parm.size[4]);
- info->dma_page_cache_end = USB_ADD_BYTES(buf, parm.size[5]);
+ info->dma_page_cache_start = USB_ADD_BYTES(buf, parm->size[4]);
+ info->dma_page_cache_end = USB_ADD_BYTES(buf, parm->size[5]);
#endif
- info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm.size[5]);
- info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm.size[2]);
+ info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm->size[5]);
+ info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm->size[2]);
cv_init(&info->cv_drain, "WDRAIN");
info->xfer_mtx = xfer_mtx;
#if USB_HAVE_BUSDMA
usb_dma_tag_setup(&info->dma_parent_tag,
- parm.dma_tag_p, udev->bus->dma_parent_tag[0].tag,
- xfer_mtx, &usb_bdma_done_event, 32, parm.dma_tag_max);
+ parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag,
+ xfer_mtx, &usb_bdma_done_event, 32, parm->dma_tag_max);
#endif
info->bus = udev->bus;
@@ -954,9 +967,9 @@ usbd_transfer_setup(struct usb_device *udev,
}
/* reset sizes */
- parm.size[0] = 0;
- parm.buf = buf;
- parm.size[0] += sizeof(info[0]);
+ parm->size[0] = 0;
+ parm->buf = buf;
+ parm->size[0] += sizeof(info[0]);
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
@@ -975,22 +988,22 @@ usbd_transfer_setup(struct usb_device *udev,
if ((setup->usb_mode != USB_MODE_DUAL) &&
(setup->usb_mode != udev->flags.usb_mode))
continue;
- parm.err = USB_ERR_NO_PIPE;
+ parm->err = USB_ERR_NO_PIPE;
goto done;
}
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store current setup pointer */
- parm.curr_setup = setup;
+ parm->curr_setup = setup;
if (buf) {
/*
* Common initialization of the
* "usb_xfer" structure.
*/
- xfer = USB_ADD_BYTES(buf, parm.size[0]);
+ xfer = USB_ADD_BYTES(buf, parm->size[0]);
xfer->address = udev->address;
xfer->priv_sc = priv_sc;
xfer->xroot = info;
@@ -1005,26 +1018,26 @@ usbd_transfer_setup(struct usb_device *udev,
* before we have allocated any
* memory:
*/
- xfer = &dummy;
- bzero(&dummy, sizeof(dummy));
+ xfer = &udev->scratch.xfer_setup[0].dummy;
+ memset(xfer, 0, sizeof(*xfer));
refcount++;
}
/* set transfer endpoint pointer */
xfer->endpoint = ep;
- parm.size[0] += sizeof(xfer[0]);
- parm.methods = xfer->endpoint->methods;
- parm.curr_xfer = xfer;
+ parm->size[0] += sizeof(xfer[0]);
+ parm->methods = xfer->endpoint->methods;
+ parm->curr_xfer = xfer;
/*
* Call the Host or Device controller transfer
* setup routine:
*/
- (udev->bus->methods->xfer_setup) (&parm);
+ (udev->bus->methods->xfer_setup) (parm);
/* check for error */
- if (parm.err)
+ if (parm->err)
goto done;
if (buf) {
@@ -1039,7 +1052,7 @@ usbd_transfer_setup(struct usb_device *udev,
*/
USB_BUS_LOCK(info->bus);
if (xfer->endpoint->refcount_alloc >= USB_EP_REF_MAX)
- parm.err = USB_ERR_INVAL;
+ parm->err = USB_ERR_INVAL;
xfer->endpoint->refcount_alloc++;
@@ -1062,22 +1075,22 @@ usbd_transfer_setup(struct usb_device *udev,
}
/* check for error */
- if (parm.err)
+ if (parm->err)
goto done;
}
- if (buf || parm.err) {
+ if (buf != NULL || parm->err != 0)
goto done;
- }
- if (refcount == 0) {
- /* no transfers - nothing to do ! */
+
+ /* if no transfers, nothing to do */
+ if (refcount == 0)
goto done;
- }
+
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[1] = parm.size[0];
+ parm->size[1] = parm->size[0];
/*
* The number of DMA tags required depends on
@@ -1085,72 +1098,72 @@ usbd_transfer_setup(struct usb_device *udev,
* for maximum number of DMA tags per endpoint
* is two.
*/
- parm.dma_tag_max += 2 * MIN(n_setup, USB_EP_MAX);
+ parm->dma_tag_max += 2 * MIN(n_setup, USB_EP_MAX);
/*
* DMA tags for QH, TD, Data and more.
*/
- parm.dma_tag_max += 8;
+ parm->dma_tag_max += 8;
- parm.dma_tag_p += parm.dma_tag_max;
+ parm->dma_tag_p += parm->dma_tag_max;
- parm.size[0] += ((uint8_t *)parm.dma_tag_p) -
+ parm->size[0] += ((uint8_t *)parm->dma_tag_p) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[3] = parm.size[0];
+ parm->size[3] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.dma_page_ptr) -
+ parm->size[0] += ((uint8_t *)parm->dma_page_ptr) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* store offset temporarily */
- parm.size[4] = parm.size[0];
+ parm->size[4] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.dma_page_cache_ptr) -
+ parm->size[0] += ((uint8_t *)parm->dma_page_cache_ptr) -
((uint8_t *)0);
/* store end offset temporarily */
- parm.size[5] = parm.size[0];
+ parm->size[5] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.xfer_page_cache_ptr) -
+ parm->size[0] += ((uint8_t *)parm->xfer_page_cache_ptr) -
((uint8_t *)0);
/* store end offset temporarily */
- parm.size[2] = parm.size[0];
+ parm->size[2] = parm->size[0];
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
- parm.size[6] = parm.size[0];
+ parm->size[6] = parm->size[0];
- parm.size[0] += ((uint8_t *)parm.xfer_length_ptr) -
+ parm->size[0] += ((uint8_t *)parm->xfer_length_ptr) -
((uint8_t *)0);
/* align data properly */
- parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
/* allocate zeroed memory */
- buf = malloc(parm.size[0], M_USB, M_WAITOK | M_ZERO);
+ buf = malloc(parm->size[0], M_USB, M_WAITOK | M_ZERO);
if (buf == NULL) {
- parm.err = USB_ERR_NOMEM;
+ parm->err = USB_ERR_NOMEM;
DPRINTFN(0, "cannot allocate memory block for "
"configuration (%d bytes)\n",
- parm.size[0]);
+ parm->size[0]);
goto done;
}
- parm.dma_tag_p = USB_ADD_BYTES(buf, parm.size[1]);
- parm.dma_page_ptr = USB_ADD_BYTES(buf, parm.size[3]);
- parm.dma_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[4]);
- parm.xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[5]);
- parm.xfer_length_ptr = USB_ADD_BYTES(buf, parm.size[6]);
+ parm->dma_tag_p = USB_ADD_BYTES(buf, parm->size[1]);
+ parm->dma_page_ptr = USB_ADD_BYTES(buf, parm->size[3]);
+ parm->dma_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[4]);
+ parm->xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[5]);
+ parm->xfer_length_ptr = USB_ADD_BYTES(buf, parm->size[6]);
}
done:
@@ -1166,10 +1179,17 @@ done:
usbd_transfer_unsetup_sub(info, 0);
}
}
- if (parm.err) {
+
+ /* check if any errors happened */
+ if (parm->err)
usbd_transfer_unsetup(ppxfer, n_setup);
- }
- return (parm.err);
+
+ error = parm->err;
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
+ return (error);
}
/*------------------------------------------------------------------------*
@@ -1178,7 +1198,9 @@ done:
static void
usbd_transfer_unsetup_sub(struct usb_xfer_root *info, uint8_t needs_delay)
{
+#if USB_HAVE_BUSDMA
struct usb_page_cache *pc;
+#endif
USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
@@ -1605,9 +1627,12 @@ usbd_transfer_submit(struct usb_xfer *xfer)
USB_BUS_UNLOCK(bus);
return;
}
- /* compute total transfer length */
+ /* compute some variables */
for (x = 0; x != xfer->nframes; x++) {
+ /* make a copy of the frlenghts[] */
+ xfer->frlengths[x + xfer->max_frame_count] = xfer->frlengths[x];
+ /* compute total transfer length */
xfer->sumlen += xfer->frlengths[x];
if (xfer->sumlen < xfer->frlengths[x]) {
/* length wrapped around */
@@ -1699,11 +1724,12 @@ usbd_pipe_enter(struct usb_xfer *xfer)
DPRINTF("enter\n");
+ /* the transfer can now be cancelled */
+ xfer->flags_int.can_cancel_immed = 1;
+
/* enter the transfer */
(ep->methods->enter) (xfer);
- xfer->flags_int.can_cancel_immed = 1;
-
/* check for transfer error */
if (xfer->error) {
/* some error has happened */
@@ -1940,6 +1966,17 @@ usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
return (&xfer->frbuffers[frindex]);
}
+void *
+usbd_xfer_get_frame_buffer(struct usb_xfer *xfer, usb_frcount_t frindex)
+{
+ struct usb_page_search page_info;
+
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
+ usbd_get_page(&xfer->frbuffers[frindex], 0, &page_info);
+ return (page_info.buffer);
+}
+
/*------------------------------------------------------------------------*
* usbd_xfer_get_fps_shift
*
@@ -1996,6 +2033,22 @@ usbd_xfer_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex,
*len = xfer->frlengths[frindex];
}
+/*------------------------------------------------------------------------*
+ * usbd_xfer_old_frame_length
+ *
+ * This function returns the framelength of the given frame at the
+ * time the transfer was submitted. This function can be used to
+ * compute the starting data pointer of the next isochronous frame
+ * when an isochronous transfer has completed.
+ *------------------------------------------------------------------------*/
+usb_frlength_t
+usbd_xfer_old_frame_length(struct usb_xfer *xfer, usb_frcount_t frindex)
+{
+ KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
+ return (xfer->frlengths[frindex + xfer->max_frame_count]);
+}
+
void
usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes,
int *nframes)
@@ -2226,6 +2279,10 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq)
}
}
+#if USB_HAVE_PF
+ if (xfer->usb_state != USB_ST_SETUP)
+ usbpf_xfertap(xfer, USBPF_XFERTAP_DONE);
+#endif
/* call processing routine */
(xfer->callback) (xfer, xfer->error);
@@ -2413,12 +2470,18 @@ usbd_transfer_start_cb(void *arg)
DPRINTF("start\n");
- /* start the transfer */
- (ep->methods->start) (xfer);
+#if USB_HAVE_PF
+ usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT);
+#endif
+ /* the transfer can now be cancelled */
xfer->flags_int.can_cancel_immed = 1;
- /* check for error */
+ /* start USB transfer, if no error */
+ if (xfer->error == 0)
+ (ep->methods->start) (xfer);
+
+ /* check for transfer error */
if (xfer->error) {
/* some error has happened */
usbd_transfer_done(xfer, 0);
@@ -2590,12 +2653,17 @@ usbd_pipe_start(struct usb_xfer_queue *pq)
}
DPRINTF("start\n");
- /* start USB transfer */
- (ep->methods->start) (xfer);
-
+#if USB_HAVE_PF
+ usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT);
+#endif
+ /* the transfer can now be cancelled */
xfer->flags_int.can_cancel_immed = 1;
- /* check for error */
+ /* start USB transfer, if no error */
+ if (xfer->error == 0)
+ (ep->methods->start) (xfer);
+
+ /* check for transfer error */
if (xfer->error) {
/* some error has happened */
usbd_transfer_done(xfer, 0);
@@ -2690,7 +2758,8 @@ usbd_callback_wrapper_sub(struct usb_xfer *xfer)
(bus->methods->start_dma_delay) (xfer);
} else {
usbd_transfer_timeout_ms(xfer,
- (void *)&usb_dma_delay_done_cb, temp);
+ (void (*)(void *))&usb_dma_delay_done_cb,
+ temp);
}
USB_BUS_UNLOCK(bus);
return (1); /* wait for new callback */
@@ -2921,6 +2990,11 @@ repeat:
usbd_transfer_unsetup(udev->ctrl_xfer, USB_CTRL_XFER_MAX);
/*
+ * Reset clear stall error counter.
+ */
+ udev->clear_stall_errors = 0;
+
+ /*
* Try to setup a new USB transfer for the
* default control endpoint:
*/
diff --git a/freebsd/sys/dev/usb/usb_util.c b/freebsd/sys/dev/usb/usb_util.c
index 14c0476a..aeafa8a5 100644
--- a/freebsd/sys/dev/usb/usb_util.c
+++ b/freebsd/sys/dev/usb/usb_util.c
@@ -34,7 +34,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
-#include <sys/linker_set.h>
#include <sys/module.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
@@ -99,6 +98,7 @@ device_set_usb_desc(device_t dev)
struct usb_interface *iface;
char *temp_p;
usb_error_t err;
+ uint8_t do_unlock;
if (dev == NULL) {
/* should not happen */
@@ -120,19 +120,26 @@ device_set_usb_desc(device_t dev)
err = 0;
}
- temp_p = (char *)udev->bus->scratch[0].data;
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
- if (!err) {
+ temp_p = (char *)udev->scratch.data;
+
+ if (err == 0) {
/* try to get the interface string ! */
- err = usbd_req_get_string_any
- (udev, NULL, temp_p,
- sizeof(udev->bus->scratch), iface->idesc->iInterface);
+ err = usbd_req_get_string_any(udev, NULL, temp_p,
+ sizeof(udev->scratch.data),
+ iface->idesc->iInterface);
}
- if (err) {
+ if (err != 0) {
/* use default description */
usb_devinfo(udev, temp_p,
- sizeof(udev->bus->scratch));
+ sizeof(udev->scratch.data));
}
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
device_set_desc_copy(dev, temp_p);
device_printf(dev, "<%s> on %s\n", temp_p,
device_get_nameunit(udev->bus->bdev));
diff --git a/freebsd/sys/dev/usb/usbdi.h b/freebsd/sys/dev/usb/usbdi.h
index 1c2d412b..245777f0 100644
--- a/freebsd/sys/dev/usb/usbdi.h
+++ b/freebsd/sys/dev/usb/usbdi.h
@@ -37,6 +37,7 @@ struct usb_page_search;
struct usb_process;
struct usb_proc_msg;
struct usb_mbuf;
+struct usb_fs_privdata;
struct mbuf;
typedef enum { /* keep in sync with usb_errstr_table */
@@ -171,6 +172,7 @@ struct usb_interface {
struct usb_host_interface *cur_altsetting;
struct usb_device *linux_udev;
void *bsd_priv_sc; /* device specific information */
+ char *pnpinfo; /* additional PnP-info for this interface */
uint8_t num_altsetting; /* number of alternate settings */
uint8_t bsd_iface_index;
};
@@ -194,6 +196,16 @@ struct usb_xfer_flags {
uint8_t stall_pipe:1; /* set if the endpoint belonging to
* this USB transfer should be stalled
* before starting this transfer! */
+ uint8_t pre_scale_frames:1; /* "usb_config->frames" is
+ * assumed to give the
+ * buffering time in
+ * milliseconds and is
+ * converted into the nearest
+ * number of frames when the
+ * USB transfer is setup. This
+ * option only has effect for
+ * ISOCHRONOUS transfers.
+ */
};
/*
@@ -217,6 +229,27 @@ struct usb_config {
};
/*
+ * Use these macro when defining USB device ID arrays if you want to
+ * have your driver module automatically loaded in host, device or
+ * both modes respectivly:
+ */
+#ifndef __rtems__
+#define STRUCT_USB_HOST_ID \
+ struct usb_device_id __section("usb_host_id")
+#define STRUCT_USB_DEVICE_ID \
+ struct usb_device_id __section("usb_device_id")
+#define STRUCT_USB_DUAL_ID \
+ struct usb_device_id __section("usb_dual_id")
+#else /* __rtems__ */
+#define STRUCT_USB_HOST_ID \
+ struct usb_device_id
+#define STRUCT_USB_DEVICE_ID \
+ struct usb_device_id
+#define STRUCT_USB_DUAL_ID \
+ struct usb_device_id
+#endif /* __rtems__ */
+
+/*
* The following structure is used when looking up an USB driver for
* an USB device. It is inspired by the Linux structure called
* "usb_device_id".
@@ -247,12 +280,15 @@ struct usb_device_id {
uint8_t match_flag_product:1;
uint8_t match_flag_dev_lo:1;
uint8_t match_flag_dev_hi:1;
+
uint8_t match_flag_dev_class:1;
uint8_t match_flag_dev_subclass:1;
uint8_t match_flag_dev_protocol:1;
uint8_t match_flag_int_class:1;
+
uint8_t match_flag_int_subclass:1;
uint8_t match_flag_int_protocol:1;
+ uint8_t match_flag_unused:6;
#if USB_HAVE_COMPAT_LINUX
/* which fields to match against */
@@ -268,7 +304,10 @@ struct usb_device_id {
#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
#endif
-};
+} __aligned(32);
+
+/* check that the size of the structure above is correct */
+extern char usb_device_id_assert[(sizeof(struct usb_device_id) == 32) ? 1 : -1];
#define USB_VENDOR(vend) \
.match_flag_vendor = 1, .idVendor = (vend)
@@ -346,7 +385,6 @@ struct usb_attach_arg {
struct usb_interface *iface; /* current interface */
enum usb_hc_mode usb_mode; /* host or device mode */
uint8_t port;
- uint8_t use_generic; /* hint for generic drivers */
uint8_t dev_state;
#define UAA_DEV_READY 0
#define UAA_DEV_DISABLED 1
@@ -421,7 +459,7 @@ struct usb_fifo_methods {
struct usb_fifo_sc {
struct usb_fifo *fp[2];
- struct cdev* dev;
+ struct usb_fs_privdata *dev;
};
const char *usbd_errstr(usb_error_t error);
@@ -444,6 +482,10 @@ enum usb_hc_mode usbd_get_mode(struct usb_device *udev);
enum usb_dev_speed usbd_get_speed(struct usb_device *udev);
void device_set_usb_desc(device_t dev);
void usb_pause_mtx(struct mtx *mtx, int _ticks);
+usb_error_t usbd_set_pnpinfo(struct usb_device *udev,
+ uint8_t iface_index, const char *pnpinfo);
+usb_error_t usbd_add_dynamic_quirk(struct usb_device *udev,
+ uint16_t quirk);
const struct usb_device_id *usbd_lookup_id_by_info(
const struct usb_device_id *id, usb_size_t sizeof_id,
@@ -483,10 +525,13 @@ void usbd_set_power_mode(struct usb_device *udev, uint8_t power_mode);
uint8_t usbd_filter_power_mode(struct usb_device *udev, uint8_t power_mode);
uint8_t usbd_device_attached(struct usb_device *udev);
+usb_frlength_t
+ usbd_xfer_old_frame_length(struct usb_xfer *xfer, usb_frcount_t frindex);
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen,
int *aframes, int *nframes);
struct usb_page_cache *usbd_xfer_get_frame(struct usb_xfer *xfer,
usb_frcount_t frindex);
+void *usbd_xfer_get_frame_buffer(struct usb_xfer *, usb_frcount_t);
void *usbd_xfer_softc(struct usb_xfer *xfer);
void *usbd_xfer_get_priv(struct usb_xfer *xfer);
void usbd_xfer_set_priv(struct usb_xfer *xfer, void *);
@@ -528,10 +573,11 @@ void usbd_m_copy_in(struct usb_page_cache *cache, usb_frlength_t dst_offset,
struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len);
void usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
usb_frlength_t len);
+void usbd_start_re_enumerate(struct usb_device *udev);
int usb_fifo_attach(struct usb_device *udev, void *priv_sc,
struct mtx *priv_mtx, struct usb_fifo_methods *pm,
- struct usb_fifo_sc *f_sc, uint16_t unit, uint16_t subunit,
+ struct usb_fifo_sc *f_sc, uint16_t unit, int16_t subunit,
uint8_t iface_index, uid_t uid, gid_t gid, int mode);
void usb_fifo_detach(struct usb_fifo_sc *f_sc);
int usb_fifo_alloc_buffer(struct usb_fifo *f, uint32_t bufsize,
diff --git a/freebsd/sys/dev/usb/usbhid.h b/freebsd/sys/dev/usb/usbhid.h
index c07454f7..f40232aa 100644
--- a/freebsd/sys/dev/usb/usbhid.h
+++ b/freebsd/sys/dev/usb/usbhid.h
@@ -226,14 +226,16 @@ void hid_end_parse(struct hid_data *s);
int hid_get_item(struct hid_data *s, struct hid_item *h);
int hid_report_size(const void *buf, usb_size_t len, enum hid_kind k,
uint8_t *id);
-int hid_locate(const void *desc, usb_size_t size, uint32_t usage,
+int hid_locate(const void *desc, usb_size_t size, int32_t usage,
enum hid_kind kind, uint8_t index, struct hid_location *loc,
uint32_t *flags, uint8_t *id);
int32_t hid_get_data(const uint8_t *buf, usb_size_t len,
struct hid_location *loc);
uint32_t hid_get_data_unsigned(const uint8_t *buf, usb_size_t len,
struct hid_location *loc);
-int hid_is_collection(const void *desc, usb_size_t size, uint32_t usage);
+void hid_put_data_unsigned(uint8_t *buf, usb_size_t len,
+ struct hid_location *loc, unsigned int value);
+int hid_is_collection(const void *desc, usb_size_t size, int32_t usage);
struct usb_hid_descriptor *hid_get_descriptor_from_usb(
struct usb_config_descriptor *cd,
struct usb_interface_descriptor *id);
diff --git a/freebsd/sys/h8300/h8300/legacy.c b/freebsd/sys/h8300/h8300/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/h8300/h8300/legacy.c
+++ b/freebsd/sys/h8300/h8300/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/h8300/include/machine/legacyvar.h b/freebsd/sys/h8300/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/h8300/include/machine/legacyvar.h
+++ b/freebsd/sys/h8300/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/h8300/pci/pci_bus.c b/freebsd/sys/h8300/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/h8300/pci/pci_bus.c
+++ b/freebsd/sys/h8300/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/i386/i386/legacy.c b/freebsd/sys/i386/i386/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/i386/i386/legacy.c
+++ b/freebsd/sys/i386/i386/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/i386/include/machine/cpufunc.h b/freebsd/sys/i386/include/machine/cpufunc.h
index fd8f2ddc..50314ecf 100644
--- a/freebsd/sys/i386/include/machine/cpufunc.h
+++ b/freebsd/sys/i386/include/machine/cpufunc.h
@@ -148,6 +148,13 @@ cpu_mwait(int extensions, int hints)
}
static __inline void
+lfence(void)
+{
+
+ __asm __volatile("lfence" : : : "memory");
+}
+
+static __inline void
mfence(void)
{
diff --git a/freebsd/sys/i386/include/machine/intr_machdep.h b/freebsd/sys/i386/include/machine/intr_machdep.h
index 0dbef09d..fc490b35 100644
--- a/freebsd/sys/i386/include/machine/intr_machdep.h
+++ b/freebsd/sys/i386/include/machine/intr_machdep.h
@@ -60,10 +60,10 @@
* - 1 ??? dummy counter.
* - 2 counters for each I/O interrupt.
* - 1 counter for each CPU for lapic timer.
- * - 7 counters for each CPU for IPI counters for SMP.
+ * - 9 counters for each CPU for IPI counters for SMP.
*/
#ifdef SMP
-#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + (1 + 7) * MAXCPU)
+#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + (1 + 9) * MAXCPU)
#else
#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + 1)
#endif
@@ -94,7 +94,7 @@ struct pic {
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
int (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
- STAILQ_ENTRY(pic) pics;
+ TAILQ_ENTRY(pic) pics;
};
/* Flags for pic_disable_source() */
diff --git a/freebsd/sys/i386/include/machine/legacyvar.h b/freebsd/sys/i386/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/i386/include/machine/legacyvar.h
+++ b/freebsd/sys/i386/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/i386/include/machine/specialreg.h b/freebsd/sys/i386/include/machine/specialreg.h
index 823f2ec3..1dfbbf4e 100644
--- a/freebsd/sys/i386/include/machine/specialreg.h
+++ b/freebsd/sys/i386/include/machine/specialreg.h
@@ -66,6 +66,7 @@
#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */
#define CR4_FXSR 0x00000200 /* Fast FPU save/restore used by OS */
#define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */
+#define CR4_XSAVE 0x00040000 /* XSETBV/XGETBV */
/*
* Bits in AMD64 special registers. EFER is 64 bits wide.
@@ -120,6 +121,7 @@
#define CPUID2_TM2 0x00000100
#define CPUID2_SSSE3 0x00000200
#define CPUID2_CNXTID 0x00000400
+#define CPUID2_FMA 0x00001000
#define CPUID2_CX16 0x00002000
#define CPUID2_XTPR 0x00004000
#define CPUID2_PDCM 0x00008000
@@ -130,7 +132,23 @@
#define CPUID2_X2APIC 0x00200000
#define CPUID2_MOVBE 0x00400000
#define CPUID2_POPCNT 0x00800000
+#define CPUID2_TSCDLT 0x01000000
#define CPUID2_AESNI 0x02000000
+#define CPUID2_XSAVE 0x04000000
+#define CPUID2_OSXSAVE 0x08000000
+#define CPUID2_AVX 0x10000000
+#define CPUID2_F16C 0x20000000
+#define CPUID2_RDRAND 0x40000000
+#define CPUID2_HV 0x80000000
+
+/*
+ * Important bits in the Thermal and Power Management flags
+ * CPUID.6 EAX and ECX.
+ */
+#define CPUTPM1_SENSOR 0x00000001
+#define CPUTPM1_TURBO 0x00000002
+#define CPUTPM1_ARAT 0x00000004
+#define CPUTPM2_EFFREQ 0x00000001
/*
* Important bits in the AMD extended cpuid flags
@@ -157,9 +175,14 @@
#define AMDID2_PREFETCH 0x00000100
#define AMDID2_OSVW 0x00000200
#define AMDID2_IBS 0x00000400
-#define AMDID2_SSE5 0x00000800
+#define AMDID2_XOP 0x00000800
#define AMDID2_SKINIT 0x00001000
#define AMDID2_WDT 0x00002000
+#define AMDID2_LWP 0x00008000
+#define AMDID2_FMA4 0x00010000
+#define AMDID2_NODE_ID 0x00080000
+#define AMDID2_TBM 0x00200000
+#define AMDID2_TOPOLOGY 0x00400000
/*
* CPUID instruction 1 eax info
@@ -205,11 +228,14 @@
#define AMDPM_100MHZ_STEPS 0x00000040
#define AMDPM_HW_PSTATE 0x00000080
#define AMDPM_TSC_INVARIANT 0x00000100
+#define AMDPM_CPB 0x00000200
/*
* AMD extended function 8000_0008h ecx info
*/
#define AMDID_CMP_CORES 0x000000ff
+#define AMDID_COREID_SIZE 0x0000f000
+#define AMDID_COREID_SIZE_SHIFT 12
/*
* CPUID manufacturers identifiers
@@ -245,6 +271,8 @@
#define MSR_BIOS_SIGN 0x08b
#define MSR_PERFCTR0 0x0c1
#define MSR_PERFCTR1 0x0c2
+#define MSR_MPERF 0x0e7
+#define MSR_APERF 0x0e8
#define MSR_IA32_EXT_CONFIG 0x0ee /* Undocumented. Core Solo/Duo only */
#define MSR_MTRRcap 0x0fe
#define MSR_BBL_CR_ADDR 0x116
@@ -553,7 +581,8 @@
#define AMD_WT_ALLOC_FRE 0x10000 /* fixed (A0000-FFFFF) range enable */
/* AMD64 MSR's */
-#define MSR_EFER 0xc0000080 /* extended features */
+#define MSR_EFER 0xc0000080 /* extended features */
+#define MSR_HWCR 0xc0010015
#define MSR_K8_UCODE_UPDATE 0xc0010020 /* update microcode */
#define MSR_MC0_CTL_MASK 0xc0010044
diff --git a/freebsd/sys/i386/pci/pci_bus.c b/freebsd/sys/i386/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/i386/pci/pci_bus.c
+++ b/freebsd/sys/i386/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/kern/init_main.c b/freebsd/sys/kern/init_main.c
index 84b44410..604a7f2b 100644
--- a/freebsd/sys/kern/init_main.c
+++ b/freebsd/sys/kern/init_main.c
@@ -321,6 +321,7 @@ print_version(void *data __unused)
while (len > 0 && version[len - 1] == '\n')
len--;
printf("%.*s %s\n", len, version, machine);
+ printf("%s\n", compiler_version);
}
SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t,
@@ -394,6 +395,7 @@ struct sysentvec null_sysvec = {
.sv_set_syscall_retval = null_set_syscall_retval,
.sv_fetch_syscall_args = null_fetch_syscall_args,
.sv_syscallnames = NULL,
+ .sv_schedtail = NULL,
};
#endif /* __rtems__ */
@@ -478,7 +480,7 @@ proc0_init(void *dummy __unused)
td->td_user_pri = PUSER;
td->td_base_user_pri = PUSER;
td->td_priority = PVM;
- td->td_base_pri = PUSER;
+ td->td_base_pri = PVM;
td->td_oncpu = 0;
td->td_flags = TDF_INMEM|TDP_KTHREAD;
td->td_cpuset = cpuset_thread0();
diff --git a/freebsd/sys/kern/kern_event.c b/freebsd/sys/kern/kern_event.c
index d318c8ba..62498b25 100644
--- a/freebsd/sys/kern/kern_event.c
+++ b/freebsd/sys/kern/kern_event.c
@@ -530,6 +530,10 @@ knote_fork(struct knlist *list, int pid)
}
#endif /* __rtems__ */
+/*
+ * XXX: EVFILT_TIMER should perhaps live in kern_time.c beside the
+ * interval timer support code.
+ */
static int
timertoticks(intptr_t data)
{
@@ -543,7 +547,6 @@ timertoticks(intptr_t data)
return tticks;
}
-/* XXX - move to kern_timeout.c? */
static void
filt_timerexpire(void *knx)
{
@@ -553,9 +556,16 @@ filt_timerexpire(void *knx)
kn->kn_data++;
KNOTE_ACTIVATE(kn, 0); /* XXX - handle locking */
+ /*
+ * timertoticks() uses tvtohz() which always adds 1 to allow
+ * for the time until the next clock interrupt being strictly
+ * less than 1 clock tick. We don't want that here since we
+ * want to appear to be in sync with the clock interrupt even
+ * when we're delayed.
+ */
if ((kn->kn_flags & EV_ONESHOT) != EV_ONESHOT) {
calloutp = (struct callout *)kn->kn_hook;
- callout_reset_curcpu(calloutp, timertoticks(kn->kn_sdata),
+ callout_reset_curcpu(calloutp, timertoticks(kn->kn_sdata) - 1,
filt_timerexpire, kn);
}
}
@@ -563,7 +573,6 @@ filt_timerexpire(void *knx)
/*
* data contains amount of time to sleep, in milliseconds
*/
-/* XXX - move to kern_timeout.c? */
static int
filt_timerattach(struct knote *kn)
{
@@ -587,7 +596,6 @@ filt_timerattach(struct knote *kn)
return (0);
}
-/* XXX - move to kern_timeout.c? */
static void
filt_timerdetach(struct knote *kn)
{
@@ -600,7 +608,6 @@ filt_timerdetach(struct knote *kn)
kn->kn_status |= KN_DETACHED; /* knlist_remove usually clears it */
}
-/* XXX - move to kern_timeout.c? */
static int
filt_timer(struct knote *kn, long hint)
{
@@ -1851,6 +1858,7 @@ kqueue_close(struct file *fp, struct thread *td)
rtems_libio_unlock();
#endif /* __rtems__ */
+ seldrain(&kq->kq_sel);
knlist_destroy(&kq->kq_sel.si_note);
mtx_destroy(&kq->kq_lock);
#ifndef __rtems__
diff --git a/freebsd/sys/kern/kern_hhook.c b/freebsd/sys/kern/kern_hhook.c
new file mode 100644
index 00000000..3a5503a6
--- /dev/null
+++ b/freebsd/sys/kern/kern_hhook.c
@@ -0,0 +1,456 @@
+#include <machine/rtems-bsd-config.h>
+
+/*-
+ * Copyright (c) 2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Lawrence Stewart while studying at the Centre
+ * for Advanced Internet Architectures, Swinburne University of Technology,
+ * made possible in part by grants from the FreeBSD Foundation and Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by Lawrence Stewart under sponsorship from the FreeBSD Foundation.
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <rtems/bsd/sys/param.h>
+#include <sys/kernel.h>
+#include <sys/hhook.h>
+#include <sys/khelp.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/module_khelp.h>
+#include <sys/osd.h>
+#include <sys/queue.h>
+#include <sys/refcount.h>
+#include <sys/systm.h>
+
+#include <net/vnet.h>
+
+struct hhook {
+ hhook_func_t hhk_func;
+ struct helper *hhk_helper;
+ void *hhk_udata;
+ STAILQ_ENTRY(hhook) hhk_next;
+};
+
+static MALLOC_DEFINE(M_HHOOK, "hhook", "Helper hooks are linked off hhook_head lists");
+
+LIST_HEAD(hhookheadhead, hhook_head);
+VNET_DEFINE(struct hhookheadhead, hhook_head_list);
+#define V_hhook_head_list VNET(hhook_head_list)
+
+static struct mtx hhook_head_list_lock;
+MTX_SYSINIT(hhookheadlistlock, &hhook_head_list_lock, "hhook_head list lock",
+ MTX_DEF);
+
+/* Private function prototypes. */
+static void hhook_head_destroy(struct hhook_head *hhh);
+
+#define HHHLIST_LOCK() mtx_lock(&hhook_head_list_lock)
+#define HHHLIST_UNLOCK() mtx_unlock(&hhook_head_list_lock)
+#define HHHLIST_LOCK_ASSERT() mtx_assert(&hhook_head_list_lock, MA_OWNED)
+
+#define HHH_LOCK_INIT(hhh) rm_init(&(hhh)->hhh_lock, "hhook_head rm lock")
+#define HHH_LOCK_DESTROY(hhh) rm_destroy(&(hhh)->hhh_lock)
+#define HHH_WLOCK(hhh) rm_wlock(&(hhh)->hhh_lock)
+#define HHH_WUNLOCK(hhh) rm_wunlock(&(hhh)->hhh_lock)
+#define HHH_RLOCK(hhh, rmpt) rm_rlock(&(hhh)->hhh_lock, (rmpt))
+#define HHH_RUNLOCK(hhh, rmpt) rm_runlock(&(hhh)->hhh_lock, (rmpt))
+
+/*
+ * Run all helper hook functions for a given hook point.
+ */
+void
+hhook_run_hooks(struct hhook_head *hhh, void *ctx_data, struct osd *hosd)
+{
+ struct hhook *hhk;
+ void *hdata;
+ struct rm_priotracker rmpt;
+
+ KASSERT(hhh->hhh_refcount > 0, ("hhook_head %p refcount is 0", hhh));
+
+ HHH_RLOCK(hhh, &rmpt);
+ STAILQ_FOREACH(hhk, &hhh->hhh_hooks, hhk_next) {
+ if (hhk->hhk_helper->h_flags & HELPER_NEEDS_OSD) {
+ hdata = osd_get(OSD_KHELP, hosd, hhk->hhk_helper->h_id);
+ if (hdata == NULL)
+ continue;
+ } else
+ hdata = NULL;
+
+ /*
+ * XXXLAS: We currently ignore the int returned by the hook,
+ * but will likely want to handle it in future to allow hhook to
+ * be used like pfil and effect changes at the hhook calling
+ * site e.g. we could define a new hook type of HHOOK_TYPE_PFIL
+ * and standardise what particular return values mean and set
+ * the context data to pass exactly the same information as pfil
+ * hooks currently receive, thus replicating pfil with hhook.
+ */
+ hhk->hhk_func(hhh->hhh_type, hhh->hhh_id, hhk->hhk_udata,
+ ctx_data, hdata, hosd);
+ }
+ HHH_RUNLOCK(hhh, &rmpt);
+}
+
+/*
+ * Register a new helper hook function with a helper hook point.
+ */
+int
+hhook_add_hook(struct hhook_head *hhh, struct hookinfo *hki, uint32_t flags)
+{
+ struct hhook *hhk, *tmp;
+ int error;
+
+ error = 0;
+
+ if (hhh == NULL)
+ return (ENOENT);
+
+ hhk = malloc(sizeof(struct hhook), M_HHOOK,
+ M_ZERO | ((flags & HHOOK_WAITOK) ? M_WAITOK : M_NOWAIT));
+
+ if (hhk == NULL)
+ return (ENOMEM);
+
+ hhk->hhk_helper = hki->hook_helper;
+ hhk->hhk_func = hki->hook_func;
+ hhk->hhk_udata = hki->hook_udata;
+
+ HHH_WLOCK(hhh);
+ STAILQ_FOREACH(tmp, &hhh->hhh_hooks, hhk_next) {
+ if (tmp->hhk_func == hki->hook_func &&
+ tmp->hhk_udata == hki->hook_udata) {
+ /* The helper hook function is already registered. */
+ error = EEXIST;
+ break;
+ }
+ }
+
+ if (!error) {
+ STAILQ_INSERT_TAIL(&hhh->hhh_hooks, hhk, hhk_next);
+ hhh->hhh_nhooks++;
+ } else
+ free(hhk, M_HHOOK);
+
+ HHH_WUNLOCK(hhh);
+
+ return (error);
+}
+
+/*
+ * Lookup a helper hook point and register a new helper hook function with it.
+ */
+int
+hhook_add_hook_lookup(struct hookinfo *hki, uint32_t flags)
+{
+ struct hhook_head *hhh;
+ int error;
+
+ hhh = hhook_head_get(hki->hook_type, hki->hook_id);
+
+ if (hhh == NULL)
+ return (ENOENT);
+
+ error = hhook_add_hook(hhh, hki, flags);
+ hhook_head_release(hhh);
+
+ return (error);
+}
+
+/*
+ * Remove a helper hook function from a helper hook point.
+ */
+int
+hhook_remove_hook(struct hhook_head *hhh, struct hookinfo *hki)
+{
+ struct hhook *tmp;
+
+ if (hhh == NULL)
+ return (ENOENT);
+
+ HHH_WLOCK(hhh);
+ STAILQ_FOREACH(tmp, &hhh->hhh_hooks, hhk_next) {
+ if (tmp->hhk_func == hki->hook_func &&
+ tmp->hhk_udata == hki->hook_udata) {
+ STAILQ_REMOVE(&hhh->hhh_hooks, tmp, hhook, hhk_next);
+ free(tmp, M_HHOOK);
+ hhh->hhh_nhooks--;
+ break;
+ }
+ }
+ HHH_WUNLOCK(hhh);
+
+ return (0);
+}
+
+/*
+ * Lookup a helper hook point and remove a helper hook function from it.
+ */
+int
+hhook_remove_hook_lookup(struct hookinfo *hki)
+{
+ struct hhook_head *hhh;
+
+ hhh = hhook_head_get(hki->hook_type, hki->hook_id);
+
+ if (hhh == NULL)
+ return (ENOENT);
+
+ hhook_remove_hook(hhh, hki);
+ hhook_head_release(hhh);
+
+ return (0);
+}
+
+/*
+ * Register a new helper hook point.
+ */
+int
+hhook_head_register(int32_t hhook_type, int32_t hhook_id, struct hhook_head **hhh,
+ uint32_t flags)
+{
+ struct hhook_head *tmphhh;
+
+ tmphhh = hhook_head_get(hhook_type, hhook_id);
+
+ if (tmphhh != NULL) {
+ /* Hook point previously registered. */
+ hhook_head_release(tmphhh);
+ return (EEXIST);
+ }
+
+ /* XXXLAS: Need to implement support for non-virtualised hooks. */
+ if ((flags & HHOOK_HEADISINVNET) == 0) {
+ printf("%s: only vnet-style virtualised hooks can be used\n",
+ __func__);
+ return (EINVAL);
+ }
+
+ tmphhh = malloc(sizeof(struct hhook_head), M_HHOOK,
+ M_ZERO | ((flags & HHOOK_WAITOK) ? M_WAITOK : M_NOWAIT));
+
+ if (tmphhh == NULL)
+ return (ENOMEM);
+
+ tmphhh->hhh_type = hhook_type;
+ tmphhh->hhh_id = hhook_id;
+ tmphhh->hhh_nhooks = 0;
+ STAILQ_INIT(&tmphhh->hhh_hooks);
+ HHH_LOCK_INIT(tmphhh);
+
+ if (hhh != NULL)
+ refcount_init(&tmphhh->hhh_refcount, 1);
+ else
+ refcount_init(&tmphhh->hhh_refcount, 0);
+
+ if (flags & HHOOK_HEADISINVNET) {
+ tmphhh->hhh_flags |= HHH_ISINVNET;
+ HHHLIST_LOCK();
+ LIST_INSERT_HEAD(&V_hhook_head_list, tmphhh, hhh_next);
+ HHHLIST_UNLOCK();
+ } else {
+ /* XXXLAS: Add tmphhh to the non-virtualised list. */
+ }
+
+ *hhh = tmphhh;
+
+ return (0);
+}
+
+static void
+hhook_head_destroy(struct hhook_head *hhh)
+{
+ struct hhook *tmp, *tmp2;
+
+ HHHLIST_LOCK_ASSERT();
+
+ LIST_REMOVE(hhh, hhh_next);
+ HHH_WLOCK(hhh);
+ STAILQ_FOREACH_SAFE(tmp, &hhh->hhh_hooks, hhk_next, tmp2)
+ free(tmp, M_HHOOK);
+ HHH_WUNLOCK(hhh);
+ HHH_LOCK_DESTROY(hhh);
+ free(hhh, M_HHOOK);
+}
+
+/*
+ * Remove a helper hook point.
+ */
+int
+hhook_head_deregister(struct hhook_head *hhh)
+{
+ int error;
+
+ error = 0;
+
+ HHHLIST_LOCK();
+ if (hhh == NULL)
+ error = ENOENT;
+ else if (hhh->hhh_refcount > 1)
+ error = EBUSY;
+ else
+ hhook_head_destroy(hhh);
+ HHHLIST_UNLOCK();
+
+ return (error);
+}
+
+/*
+ * Remove a helper hook point via a hhook_head lookup.
+ */
+int
+hhook_head_deregister_lookup(int32_t hhook_type, int32_t hhook_id)
+{
+ struct hhook_head *hhh;
+ int error;
+
+ hhh = hhook_head_get(hhook_type, hhook_id);
+ error = hhook_head_deregister(hhh);
+
+ if (error == EBUSY)
+ hhook_head_release(hhh);
+
+ return (error);
+}
+
+/*
+ * Lookup and return the hhook_head struct associated with the specified type
+ * and id, or NULL if not found. If found, the hhook_head's refcount is bumped.
+ */
+struct hhook_head *
+hhook_head_get(int32_t hhook_type, int32_t hhook_id)
+{
+ struct hhook_head *hhh;
+
+ /* XXXLAS: Pick hhook_head_list based on hhook_head flags. */
+ HHHLIST_LOCK();
+ LIST_FOREACH(hhh, &V_hhook_head_list, hhh_next) {
+ if (hhh->hhh_type == hhook_type && hhh->hhh_id == hhook_id) {
+ refcount_acquire(&hhh->hhh_refcount);
+ break;
+ }
+ }
+ HHHLIST_UNLOCK();
+
+ return (hhh);
+}
+
+void
+hhook_head_release(struct hhook_head *hhh)
+{
+
+ refcount_release(&hhh->hhh_refcount);
+}
+
+/*
+ * Check the hhook_head private flags and return the appropriate public
+ * representation of the flag to the caller. The function is implemented in a
+ * way that allows us to cope with other subsystems becoming virtualised in the
+ * future.
+ */
+uint32_t
+hhook_head_is_virtualised(struct hhook_head *hhh)
+{
+ uint32_t ret;
+
+ ret = 0;
+
+ if (hhh != NULL) {
+ if (hhh->hhh_flags & HHH_ISINVNET)
+ ret = HHOOK_HEADISINVNET;
+ }
+
+ return (ret);
+}
+
+uint32_t
+hhook_head_is_virtualised_lookup(int32_t hook_type, int32_t hook_id)
+{
+ struct hhook_head *hhh;
+ uint32_t ret;
+
+ hhh = hhook_head_get(hook_type, hook_id);
+
+ if (hhh == NULL)
+ return (0);
+
+ ret = hhook_head_is_virtualised(hhh);
+ hhook_head_release(hhh);
+
+ return (ret);
+}
+
+/*
+ * Vnet created and being initialised.
+ */
+static void
+hhook_vnet_init(const void *unused __unused)
+{
+
+ LIST_INIT(&V_hhook_head_list);
+}
+
+/*
+ * Vnet being torn down and destroyed.
+ */
+static void
+hhook_vnet_uninit(const void *unused __unused)
+{
+ struct hhook_head *hhh, *tmphhh;
+
+ /*
+ * If subsystems which export helper hook points use the hhook KPI
+ * correctly, the loop below should have no work to do because the
+ * subsystem should have already called hhook_head_deregister().
+ */
+ HHHLIST_LOCK();
+ LIST_FOREACH_SAFE(hhh, &V_hhook_head_list, hhh_next, tmphhh) {
+ printf("%s: hhook_head type=%d, id=%d cleanup required\n",
+ __func__, hhh->hhh_type, hhh->hhh_id);
+ hhook_head_destroy(hhh);
+ }
+ HHHLIST_UNLOCK();
+}
+
+
+/*
+ * When a vnet is created and being initialised, init the V_hhook_head_list.
+ */
+VNET_SYSINIT(hhook_vnet_init, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST,
+ hhook_vnet_init, NULL);
+
+/*
+ * The hhook KPI provides a mechanism for subsystems which export helper hook
+ * points to clean up on vnet tear down, but in case the KPI is misused,
+ * provide a function to clean up and free memory for a vnet being destroyed.
+ */
+VNET_SYSUNINIT(hhook_vnet_uninit, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST,
+ hhook_vnet_uninit, NULL);
diff --git a/freebsd/sys/kern/kern_intr.c b/freebsd/sys/kern/kern_intr.c
index b23ce519..336866c8 100644
--- a/freebsd/sys/kern/kern_intr.c
+++ b/freebsd/sys/kern/kern_intr.c
@@ -148,22 +148,18 @@ intr_priority(enum intr_type flags)
INTR_TYPE_CAM | INTR_TYPE_MISC | INTR_TYPE_CLK | INTR_TYPE_AV);
switch (flags) {
case INTR_TYPE_TTY:
- pri = PI_TTYLOW;
+ pri = PI_TTY;
break;
case INTR_TYPE_BIO:
- /*
- * XXX We need to refine this. BSD/OS distinguishes
- * between tape and disk priorities.
- */
pri = PI_DISK;
break;
case INTR_TYPE_NET:
pri = PI_NET;
break;
case INTR_TYPE_CAM:
- pri = PI_DISK; /* XXX or PI_CAM? */
+ pri = PI_DISK;
break;
- case INTR_TYPE_AV: /* Audio/video */
+ case INTR_TYPE_AV:
pri = PI_AV;
break;
case INTR_TYPE_CLK:
@@ -202,6 +198,9 @@ ithread_update(struct intr_thread *ithd)
/* Update name and priority. */
strlcpy(td->td_name, ie->ie_fullname, sizeof(td->td_name));
+#ifdef KTR
+ sched_clear_tdname(td);
+#endif
thread_lock(td);
#ifndef __rtems__
sched_prio(td, pri);
@@ -1118,6 +1117,7 @@ int
swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler,
void *arg, int pri, enum intr_type flags, void **cookiep)
{
+ struct thread *td;
struct intr_event *ie;
int error;
@@ -1138,16 +1138,15 @@ swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler,
*eventp = ie;
}
error = intr_event_add_handler(ie, name, NULL, handler, arg,
- (pri * RQ_PPQ) + PI_SOFT, flags, cookiep);
+ PI_SWI(pri), flags, cookiep);
if (error)
return (error);
#ifndef __rtems__
if (pri == SWI_CLOCK) {
- struct proc *p;
- p = ie->ie_thread->it_thread->td_proc;
- PROC_LOCK(p);
- p->p_flag |= P_NOLOAD;
- PROC_UNLOCK(p);
+ td = ie->ie_thread->it_thread;
+ thread_lock(td);
+ td->td_flags |= TDF_NOLOAD;
+ thread_unlock(td);
}
#else /* __rtems__ */
// Do _not_ ignore the thread in the load avarage
@@ -1742,18 +1741,13 @@ db_dump_intrhand(struct intr_handler *ih)
case PI_AV:
db_printf("AV ");
break;
- case PI_TTYHIGH:
- case PI_TTYLOW:
+ case PI_TTY:
db_printf("TTY ");
break;
- case PI_TAPE:
- db_printf("TAPE");
- break;
case PI_NET:
db_printf("NET ");
break;
case PI_DISK:
- case PI_DISKLOW:
db_printf("DISK");
break;
case PI_DULL:
diff --git a/freebsd/sys/kern/kern_khelp.c b/freebsd/sys/kern/kern_khelp.c
new file mode 100644
index 00000000..ce8dd662
--- /dev/null
+++ b/freebsd/sys/kern/kern_khelp.c
@@ -0,0 +1,475 @@
+#include <machine/rtems-bsd-config.h>
+
+/*-
+ * Copyright (c) 2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Lawrence Stewart while studying at the Centre
+ * for Advanced Internet Architectures, Swinburne University of Technology,
+ * made possible in part by grants from the FreeBSD Foundation and Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by Lawrence Stewart under sponsorship from the FreeBSD Foundation.
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <rtems/bsd/sys/param.h>
+#include <sys/kernel.h>
+#include <sys/hhook.h>
+#include <sys/jail.h>
+#include <sys/khelp.h>
+#include <rtems/bsd/sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/module_khelp.h>
+#include <sys/osd.h>
+#include <sys/queue.h>
+#include <sys/refcount.h>
+#include <sys/rwlock.h>
+#include <sys/systm.h>
+
+#include <net/vnet.h>
+
+static struct rwlock khelp_list_lock;
+RW_SYSINIT(khelplistlock, &khelp_list_lock, "helper list lock");
+
+static TAILQ_HEAD(helper_head, helper) helpers = TAILQ_HEAD_INITIALIZER(helpers);
+
+/* Private function prototypes. */
+static inline void khelp_remove_osd(struct helper *h, struct osd *hosd);
+
+#define KHELP_LIST_WLOCK() rw_wlock(&khelp_list_lock)
+#define KHELP_LIST_WUNLOCK() rw_wunlock(&khelp_list_lock)
+#define KHELP_LIST_RLOCK() rw_rlock(&khelp_list_lock)
+#define KHELP_LIST_RUNLOCK() rw_runlock(&khelp_list_lock)
+#define KHELP_LIST_LOCK_ASSERT() rw_assert(&khelp_list_lock, RA_LOCKED)
+
+int
+khelp_register_helper(struct helper *h)
+{
+ struct helper *tmph;
+ int error, i, inserted;
+
+ error = 0;
+ inserted = 0;
+ refcount_init(&h->h_refcount, 0);
+ h->h_id = osd_register(OSD_KHELP, NULL, NULL);
+
+ /* It's only safe to add the hooks after osd_register(). */
+ if (h->h_nhooks > 0) {
+ for (i = 0; i < h->h_nhooks && !error; i++) {
+ /* We don't require the module to assign hook_helper. */
+ h->h_hooks[i].hook_helper = h;
+ error = khelp_add_hhook(&h->h_hooks[i], HHOOK_NOWAIT);
+ }
+
+ if (error) {
+ for (i--; i >= 0; i--)
+ khelp_remove_hhook(&h->h_hooks[i]);
+
+ osd_deregister(OSD_KHELP, h->h_id);
+ }
+ }
+
+ if (!error) {
+ KHELP_LIST_WLOCK();
+ /*
+ * Keep list of helpers sorted in descending h_id order. Due to
+ * the way osd_set() works, a sorted list ensures
+ * init_helper_osd() will operate with improved efficiency.
+ */
+ TAILQ_FOREACH(tmph, &helpers, h_next) {
+ if (tmph->h_id < h->h_id) {
+ TAILQ_INSERT_BEFORE(tmph, h, h_next);
+ inserted = 1;
+ break;
+ }
+ }
+
+ if (!inserted)
+ TAILQ_INSERT_TAIL(&helpers, h, h_next);
+ KHELP_LIST_WUNLOCK();
+ }
+
+ return (error);
+}
+
+int
+khelp_deregister_helper(struct helper *h)
+{
+ struct helper *tmph;
+ int error, i;
+
+ error = 0;
+
+ KHELP_LIST_WLOCK();
+ if (h->h_refcount > 0)
+ error = EBUSY;
+ else {
+ error = ENOENT;
+ TAILQ_FOREACH(tmph, &helpers, h_next) {
+ if (tmph == h) {
+ TAILQ_REMOVE(&helpers, h, h_next);
+ error = 0;
+ break;
+ }
+ }
+ }
+ KHELP_LIST_WUNLOCK();
+
+ if (!error) {
+ if (h->h_nhooks > 0) {
+ for (i = 0; i < h->h_nhooks; i++)
+ khelp_remove_hhook(&h->h_hooks[i]);
+ }
+ osd_deregister(OSD_KHELP, h->h_id);
+ }
+
+ return (error);
+}
+
+int
+khelp_init_osd(uint32_t classes, struct osd *hosd)
+{
+ struct helper *h;
+ void *hdata;
+ int error;
+
+ KASSERT(hosd != NULL, ("struct osd not initialised!"));
+
+ error = 0;
+
+ KHELP_LIST_RLOCK();
+ TAILQ_FOREACH(h, &helpers, h_next) {
+ /* If helper is correct class and needs to store OSD... */
+ if (h->h_classes & classes && h->h_flags & HELPER_NEEDS_OSD) {
+ hdata = uma_zalloc(h->h_zone, M_NOWAIT);
+ if (hdata == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ osd_set(OSD_KHELP, hosd, h->h_id, hdata);
+ refcount_acquire(&h->h_refcount);
+ }
+ }
+
+ if (error) {
+ /* Delete OSD that was assigned prior to the error. */
+ TAILQ_FOREACH(h, &helpers, h_next) {
+ if (h->h_classes & classes)
+ khelp_remove_osd(h, hosd);
+ }
+ }
+ KHELP_LIST_RUNLOCK();
+
+ return (error);
+}
+
+int
+khelp_destroy_osd(struct osd *hosd)
+{
+ struct helper *h;
+ int error;
+
+ KASSERT(hosd != NULL, ("struct osd not initialised!"));
+
+ error = 0;
+
+ KHELP_LIST_RLOCK();
+ /*
+ * Clean up all khelp related OSD.
+ *
+ * XXXLAS: Would be nice to use something like osd_exit() here but it
+ * doesn't have the right semantics for this purpose.
+ */
+ TAILQ_FOREACH(h, &helpers, h_next)
+ khelp_remove_osd(h, hosd);
+ KHELP_LIST_RUNLOCK();
+
+ return (error);
+}
+
+static inline void
+khelp_remove_osd(struct helper *h, struct osd *hosd)
+{
+ void *hdata;
+
+ if (h->h_flags & HELPER_NEEDS_OSD) {
+ /*
+ * If the current helper uses OSD and calling osd_get()
+ * on the helper's h_id returns non-NULL, the helper has
+ * OSD attached to 'hosd' which needs to be cleaned up.
+ */
+ hdata = osd_get(OSD_KHELP, hosd, h->h_id);
+ if (hdata != NULL) {
+ uma_zfree(h->h_zone, hdata);
+ osd_del(OSD_KHELP, hosd, h->h_id);
+ refcount_release(&h->h_refcount);
+ }
+ }
+}
+
+void *
+khelp_get_osd(struct osd *hosd, int32_t id)
+{
+
+ return (osd_get(OSD_KHELP, hosd, id));
+}
+
+int32_t
+khelp_get_id(char *hname)
+{
+ struct helper *h;
+ int32_t id;
+
+ id = -1;
+
+ KHELP_LIST_RLOCK();
+ TAILQ_FOREACH(h, &helpers, h_next) {
+ if (strncmp(h->h_name, hname, HELPER_NAME_MAXLEN) == 0) {
+ id = h->h_id;
+ break;
+ }
+ }
+ KHELP_LIST_RUNLOCK();
+
+ return (id);
+}
+
+int
+khelp_add_hhook(struct hookinfo *hki, uint32_t flags)
+{
+ VNET_ITERATOR_DECL(vnet_iter);
+ int error;
+
+ error = 0;
+
+ /*
+ * XXXLAS: If a helper is dynamically adding a helper hook function at
+ * runtime using this function, we should update the helper's h_hooks
+ * struct member to include the additional hookinfo struct.
+ */
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ error = hhook_add_hook_lookup(hki, flags);
+ CURVNET_RESTORE();
+#ifdef VIMAGE
+ if (error)
+ break;
+#endif
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
+
+ return (error);
+}
+
+int
+khelp_remove_hhook(struct hookinfo *hki)
+{
+ VNET_ITERATOR_DECL(vnet_iter);
+ int error;
+
+ error = 0;
+
+ /*
+ * XXXLAS: If a helper is dynamically removing a helper hook function at
+ * runtime using this function, we should update the helper's h_hooks
+ * struct member to remove the defunct hookinfo struct.
+ */
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ error = hhook_remove_hook_lookup(hki);
+ CURVNET_RESTORE();
+#ifdef VIMAGE
+ if (error)
+ break;
+#endif
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
+
+ return (error);
+}
+
+#ifndef __rtems__
+int
+khelp_modevent(module_t mod, int event_type, void *data)
+{
+ struct khelp_modevent_data *kmd;
+ int error;
+
+ kmd = (struct khelp_modevent_data *)data;
+ error = 0;
+
+ switch(event_type) {
+ case MOD_LOAD:
+ if (kmd->helper->h_flags & HELPER_NEEDS_OSD) {
+ if (kmd->uma_zsize <= 0) {
+ printf("Use KHELP_DECLARE_MOD_UMA() instead!\n");
+ error = EDOOFUS;
+ break;
+ }
+ kmd->helper->h_zone = uma_zcreate(kmd->name,
+ kmd->uma_zsize, kmd->umactor, kmd->umadtor, NULL,
+ NULL, 0, 0);
+ if (kmd->helper->h_zone == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ }
+ strlcpy(kmd->helper->h_name, kmd->name, HELPER_NAME_MAXLEN);
+ kmd->helper->h_hooks = kmd->hooks;
+ kmd->helper->h_nhooks = kmd->nhooks;
+ if (kmd->helper->mod_init != NULL)
+ error = kmd->helper->mod_init();
+ if (!error)
+ error = khelp_register_helper(kmd->helper);
+ break;
+
+ case MOD_QUIESCE:
+ case MOD_SHUTDOWN:
+ case MOD_UNLOAD:
+ error = khelp_deregister_helper(kmd->helper);
+ if (!error) {
+ if (kmd->helper->h_flags & HELPER_NEEDS_OSD)
+ uma_zdestroy(kmd->helper->h_zone);
+ if (kmd->helper->mod_destroy != NULL)
+ kmd->helper->mod_destroy();
+ } else if (error == ENOENT)
+ /* Do nothing and allow unload if helper not in list. */
+ error = 0;
+ else if (error == EBUSY)
+ printf("Khelp module \"%s\" can't unload until its "
+ "refcount drops from %d to 0.\n", kmd->name,
+ kmd->helper->h_refcount);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+#endif /* __rtems__ */
+
+/*
+ * This function is called in two separate situations:
+ *
+ * - When the kernel is booting, it is called directly by the SYSINIT framework
+ * to allow Khelp modules which were compiled into the kernel or loaded by the
+ * boot loader to insert their non-virtualised hook functions into the kernel.
+ *
+ * - When the kernel is booting or a vnet is created, this function is also
+ * called indirectly through khelp_vnet_init() by the vnet initialisation code.
+ * In this situation, Khelp modules are able to insert their virtualised hook
+ * functions into the virtualised hook points in the vnet which is being
+ * initialised. In the case where the kernel is not compiled with "options
+ * VIMAGE", this step is still run once at boot, but the hook functions get
+ * transparently inserted into the standard unvirtualised network stack.
+ */
+static void
+khelp_init(const void *vnet)
+{
+ struct helper *h;
+ int error, i, vinit;
+ int32_t htype, hid;
+
+ error = 0;
+ vinit = vnet != NULL;
+
+ KHELP_LIST_RLOCK();
+ TAILQ_FOREACH(h, &helpers, h_next) {
+ for (i = 0; i < h->h_nhooks && !error; i++) {
+ htype = h->h_hooks[i].hook_type;
+ hid = h->h_hooks[i].hook_id;
+
+ /*
+ * If we're doing a virtualised init (vinit != 0) and
+ * the hook point is virtualised, or we're doing a plain
+ * sysinit at boot and the hook point is not
+ * virtualised, insert the hook.
+ */
+ if ((hhook_head_is_virtualised_lookup(htype, hid) ==
+ HHOOK_HEADISINVNET && vinit) ||
+ (!hhook_head_is_virtualised_lookup(htype, hid) &&
+ !vinit)) {
+ error = hhook_add_hook_lookup(&h->h_hooks[i],
+ HHOOK_NOWAIT);
+ }
+ }
+
+ if (error) {
+ /* Remove any helper's hooks we successfully added. */
+ for (i--; i >= 0; i--)
+ hhook_remove_hook_lookup(&h->h_hooks[i]);
+
+ printf("%s: Failed to add hooks for helper \"%s\" (%p)",
+ __func__, h->h_name, h);
+ if (vinit)
+ printf(" to vnet %p.\n", vnet);
+ else
+ printf(".\n");
+
+ error = 0;
+ }
+ }
+ KHELP_LIST_RUNLOCK();
+}
+
+/*
+ * Vnet created and being initialised.
+ */
+static void
+khelp_vnet_init(const void *unused __unused)
+{
+
+ khelp_init(TD_TO_VNET(curthread));
+}
+
+
+/*
+ * As the kernel boots, allow Khelp modules which were compiled into the kernel
+ * or loaded by the boot loader to insert their non-virtualised hook functions
+ * into the kernel.
+ */
+SYSINIT(khelp_init, SI_SUB_PROTO_END, SI_ORDER_FIRST, khelp_init, NULL);
+
+/*
+ * When a vnet is created and being initialised, we need to insert the helper
+ * hook functions for all currently registered Khelp modules into the vnet's
+ * helper hook points. The hhook KPI provides a mechanism for subsystems which
+ * export helper hook points to clean up on vnet shutdown, so we don't need a
+ * VNET_SYSUNINIT for Khelp.
+ */
+VNET_SYSINIT(khelp_vnet_init, SI_SUB_PROTO_END, SI_ORDER_FIRST,
+ khelp_vnet_init, NULL);
diff --git a/freebsd/sys/kern/kern_linker.c b/freebsd/sys/kern/kern_linker.c
index d2318552..90c73a70 100644
--- a/freebsd/sys/kern/kern_linker.c
+++ b/freebsd/sys/kern/kern_linker.c
@@ -71,6 +71,9 @@ int kld_debug = 0;
#define KLD_LOCK() sx_xlock(&kld_sx)
#define KLD_UNLOCK() sx_xunlock(&kld_sx)
+#define KLD_DOWNGRADE() sx_downgrade(&kld_sx)
+#define KLD_LOCK_READ() sx_slock(&kld_sx)
+#define KLD_UNLOCK_READ() sx_sunlock(&kld_sx)
#define KLD_LOCKED() sx_xlocked(&kld_sx)
#define KLD_LOCK_ASSERT() do { \
if (!cold) \
@@ -389,7 +392,7 @@ linker_load_file(const char *filename, linker_file_t *result)
{
linker_class_t lc;
linker_file_t lf;
- int foundfile, error;
+ int foundfile, error, modules;
/* Refuse to load modules if securelevel raised */
if (prison0.pr_securelevel > 0)
@@ -428,11 +431,22 @@ linker_load_file(const char *filename, linker_file_t *result)
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
return (error);
}
+ modules = !TAILQ_EMPTY(&lf->modules);
KLD_UNLOCK();
linker_file_register_sysctls(lf);
linker_file_sysinit(lf);
KLD_LOCK();
lf->flags |= LINKER_FILE_LINKED;
+
+ /*
+ * If all of the modules in this file failed
+ * to load, unload the file and return an
+ * error of ENOEXEC.
+ */
+ if (modules && TAILQ_EMPTY(&lf->modules)) {
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+ return (ENOEXEC);
+ }
*result = lf;
return (0);
}
@@ -636,7 +650,7 @@ linker_file_unload(linker_file_t file, int flags)
/*
* Inform any modules associated with this file that they are
- * being be unloaded.
+ * being unloaded.
*/
MOD_XLOCK;
for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
@@ -647,8 +661,12 @@ linker_file_unload(linker_file_t file, int flags)
* Give the module a chance to veto the unload.
*/
if ((error = module_unload(mod)) != 0) {
+#ifdef KLD_DEBUG
+ MOD_SLOCK;
KLD_DPF(FILE, ("linker_file_unload: module %s"
- " failed unload\n", mod));
+ " failed unload\n", module_getname(mod)));
+ MOD_SUNLOCK;
+#endif
return (error);
}
MOD_XLOCK;
@@ -1030,18 +1048,24 @@ kern_kldload(struct thread *td, const char *file, int *fileid)
KLD_LOCK();
error = linker_load_module(kldname, modname, NULL, NULL, &lf);
- if (error)
- goto unlock;
+ if (error) {
+ KLD_UNLOCK();
+ goto done;
+ }
+ lf->userrefs++;
+ if (fileid != NULL)
+ *fileid = lf->id;
#ifdef HWPMC_HOOKS
+ KLD_DOWNGRADE();
pkm.pm_file = lf->filename;
pkm.pm_address = (uintptr_t) lf->address;
PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
-#endif
- lf->userrefs++;
- if (fileid != NULL)
- *fileid = lf->id;
-unlock:
+ KLD_UNLOCK_READ();
+#else
KLD_UNLOCK();
+#endif
+
+done:
CURVNET_RESTORE();
return (error);
}
@@ -1113,10 +1137,15 @@ kern_kldunload(struct thread *td, int fileid, int flags)
error = ENOENT;
#ifdef HWPMC_HOOKS
- if (error == 0)
+ if (error == 0) {
+ KLD_DOWNGRADE();
PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
-#endif
+ KLD_UNLOCK_READ();
+ } else
+ KLD_UNLOCK();
+#else
KLD_UNLOCK();
+#endif
CURVNET_RESTORE();
return (error);
}
@@ -1212,29 +1241,39 @@ int
kldstat(struct thread *td, struct kldstat_args *uap)
{
struct kld_file_stat stat;
- linker_file_t lf;
- int error, namelen, version, version_num;
+ int error, version;
/*
* Check the version of the user's structure.
*/
- if ((error = copyin(&uap->stat->version, &version, sizeof(version))) != 0)
+ if ((error = copyin(&uap->stat->version, &version, sizeof(version)))
+ != 0)
return (error);
- if (version == sizeof(struct kld_file_stat_1))
- version_num = 1;
- else if (version == sizeof(struct kld_file_stat))
- version_num = 2;
- else
+ if (version != sizeof(struct kld_file_stat_1) &&
+ version != sizeof(struct kld_file_stat))
return (EINVAL);
+ error = kern_kldstat(td, uap->fileid, &stat);
+ if (error != 0)
+ return (error);
+ return (copyout(&stat, uap->stat, version));
+}
+
+int
+kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat)
+{
+ linker_file_t lf;
+ int namelen;
#ifdef MAC
+ int error;
+
error = mac_kld_check_stat(td->td_ucred);
if (error)
return (error);
#endif
KLD_LOCK();
- lf = linker_find_file_by_id(uap->fileid);
+ lf = linker_find_file_by_id(fileid);
if (lf == NULL) {
KLD_UNLOCK();
return (ENOENT);
@@ -1244,23 +1283,20 @@ kldstat(struct thread *td, struct kldstat_args *uap)
namelen = strlen(lf->filename) + 1;
if (namelen > MAXPATHLEN)
namelen = MAXPATHLEN;
- bcopy(lf->filename, &stat.name[0], namelen);
- stat.refs = lf->refs;
- stat.id = lf->id;
- stat.address = lf->address;
- stat.size = lf->size;
- if (version_num > 1) {
- /* Version 2 fields: */
- namelen = strlen(lf->pathname) + 1;
- if (namelen > MAXPATHLEN)
- namelen = MAXPATHLEN;
- bcopy(lf->pathname, &stat.pathname[0], namelen);
- }
+ bcopy(lf->filename, &stat->name[0], namelen);
+ stat->refs = lf->refs;
+ stat->id = lf->id;
+ stat->address = lf->address;
+ stat->size = lf->size;
+ /* Version 2 fields: */
+ namelen = strlen(lf->pathname) + 1;
+ if (namelen > MAXPATHLEN)
+ namelen = MAXPATHLEN;
+ bcopy(lf->pathname, &stat->pathname[0], namelen);
KLD_UNLOCK();
td->td_retval[0] = 0;
-
- return (copyout(&stat, uap->stat, version));
+ return (0);
}
int
@@ -1928,7 +1964,7 @@ linker_hwpmc_list_objects(void)
int i, nmappings;
nmappings = 0;
- KLD_LOCK();
+ KLD_LOCK_READ();
TAILQ_FOREACH(lf, &linker_files, link)
nmappings++;
@@ -1943,7 +1979,7 @@ linker_hwpmc_list_objects(void)
kobase[i].pm_address = (uintptr_t)lf->address;
i++;
}
- KLD_UNLOCK();
+ KLD_UNLOCK_READ();
KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?"));
diff --git a/freebsd/sys/kern/kern_mib.c b/freebsd/sys/kern/kern_mib.c
index 25058a79..c513463d 100644
--- a/freebsd/sys/kern/kern_mib.c
+++ b/freebsd/sys/kern/kern_mib.c
@@ -108,6 +108,9 @@ SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD,
SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD|CTLFLAG_MPSAFE,
version, 0, "Kernel version");
+SYSCTL_STRING(_kern, OID_AUTO, compiler_version, CTLFLAG_RD|CTLFLAG_MPSAFE,
+ compiler_version, 0, "Version of compiler used to compile kernel");
+
SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD|CTLFLAG_MPSAFE,
ostype, 0, "Operating system type");
diff --git a/freebsd/sys/kern/kern_osd.c b/freebsd/sys/kern/kern_osd.c
new file mode 100644
index 00000000..167607e0
--- /dev/null
+++ b/freebsd/sys/kern/kern_osd.c
@@ -0,0 +1,405 @@
+#include <machine/rtems-bsd-config.h>
+
+/*-
+ * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * 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 AUTHORS 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 AUTHORS 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <rtems/bsd/sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <rtems/bsd/sys/errno.h>
+#include <sys/jail.h>
+#include <sys/malloc.h>
+#include <rtems/bsd/sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rmlock.h>
+#include <sys/sx.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/osd.h>
+
+/* OSD (Object Specific Data) */
+
+static MALLOC_DEFINE(M_OSD, "osd", "Object Specific Data");
+
+static int osd_debug = 0;
+TUNABLE_INT("debug.osd", &osd_debug);
+SYSCTL_INT(_debug, OID_AUTO, osd, CTLFLAG_RW, &osd_debug, 0, "OSD debug level");
+
+#define OSD_DEBUG(...) do { \
+ if (osd_debug) { \
+ printf("OSD (%s:%u): ", __func__, __LINE__); \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ } \
+} while (0)
+
+static void do_osd_del(u_int type, struct osd *osd, u_int slot,
+ int list_locked);
+
+/*
+ * Lists of objects with OSD.
+ *
+ * Lock key:
+ * (m) osd_module_lock
+ * (o) osd_object_lock
+ * (l) osd_list_lock
+ */
+static LIST_HEAD(, osd) osd_list[OSD_LAST + 1]; /* (m) */
+static osd_method_t *osd_methods[OSD_LAST + 1]; /* (m) */
+static u_int osd_nslots[OSD_LAST + 1]; /* (m) */
+static osd_destructor_t *osd_destructors[OSD_LAST + 1]; /* (o) */
+static const u_int osd_nmethods[OSD_LAST + 1] = {
+ [OSD_JAIL] = PR_MAXMETHOD,
+};
+
+static struct sx osd_module_lock[OSD_LAST + 1];
+static struct rmlock osd_object_lock[OSD_LAST + 1];
+static struct mtx osd_list_lock[OSD_LAST + 1];
+
+static void
+osd_default_destructor(void *value __unused)
+{
+ /* Do nothing. */
+}
+
+int
+osd_register(u_int type, osd_destructor_t destructor, osd_method_t *methods)
+{
+ void *newptr;
+ u_int i, m;
+
+ KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
+
+ /*
+ * If no destructor is given, use default one. We need to use some
+ * destructor, because NULL destructor means unused slot.
+ */
+ if (destructor == NULL)
+ destructor = osd_default_destructor;
+
+ sx_xlock(&osd_module_lock[type]);
+ /*
+ * First, we try to find unused slot.
+ */
+ for (i = 0; i < osd_nslots[type]; i++) {
+ if (osd_destructors[type][i] == NULL) {
+ OSD_DEBUG("Unused slot found (type=%u, slot=%u).",
+ type, i);
+ break;
+ }
+ }
+ /*
+ * If no unused slot was found, allocate one.
+ */
+ if (i == osd_nslots[type]) {
+ osd_nslots[type]++;
+ if (osd_nmethods[type] != 0)
+ osd_methods[type] = realloc(osd_methods[type],
+ sizeof(osd_method_t) * osd_nslots[type] *
+ osd_nmethods[type], M_OSD, M_WAITOK);
+ newptr = malloc(sizeof(osd_destructor_t) * osd_nslots[type],
+ M_OSD, M_WAITOK);
+ rm_wlock(&osd_object_lock[type]);
+ bcopy(osd_destructors[type], newptr,
+ sizeof(osd_destructor_t) * i);
+ free(osd_destructors[type], M_OSD);
+ osd_destructors[type] = newptr;
+ rm_wunlock(&osd_object_lock[type]);
+ OSD_DEBUG("New slot allocated (type=%u, slot=%u).",
+ type, i + 1);
+ }
+
+ osd_destructors[type][i] = destructor;
+ if (osd_nmethods[type] != 0) {
+ for (m = 0; m < osd_nmethods[type]; m++)
+ osd_methods[type][i * osd_nmethods[type] + m] =
+ methods != NULL ? methods[m] : NULL;
+ }
+ sx_xunlock(&osd_module_lock[type]);
+ return (i + 1);
+}
+
+void
+osd_deregister(u_int type, u_int slot)
+{
+ struct osd *osd, *tosd;
+
+ KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
+ KASSERT(slot > 0, ("Invalid slot."));
+ KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));
+
+ sx_xlock(&osd_module_lock[type]);
+ rm_wlock(&osd_object_lock[type]);
+ /*
+ * Free all OSD for the given slot.
+ */
+ mtx_lock(&osd_list_lock[type]);
+ LIST_FOREACH_SAFE(osd, &osd_list[type], osd_next, tosd)
+ do_osd_del(type, osd, slot, 1);
+ mtx_unlock(&osd_list_lock[type]);
+ /*
+ * Set destructor to NULL to free the slot.
+ */
+ osd_destructors[type][slot - 1] = NULL;
+ if (slot == osd_nslots[type]) {
+ osd_nslots[type]--;
+ osd_destructors[type] = realloc(osd_destructors[type],
+ sizeof(osd_destructor_t) * osd_nslots[type], M_OSD,
+ M_NOWAIT | M_ZERO);
+ if (osd_nmethods[type] != 0)
+ osd_methods[type] = realloc(osd_methods[type],
+ sizeof(osd_method_t) * osd_nslots[type] *
+ osd_nmethods[type], M_OSD, M_NOWAIT | M_ZERO);
+ /*
+ * We always reallocate to smaller size, so we assume it will
+ * always succeed.
+ */
+ KASSERT(osd_destructors[type] != NULL &&
+ (osd_nmethods[type] == 0 || osd_methods[type] != NULL),
+ ("realloc() failed"));
+ OSD_DEBUG("Deregistration of the last slot (type=%u, slot=%u).",
+ type, slot);
+ } else {
+ OSD_DEBUG("Slot deregistration (type=%u, slot=%u).",
+ type, slot);
+ }
+ rm_wunlock(&osd_object_lock[type]);
+ sx_xunlock(&osd_module_lock[type]);
+}
+
+int
+osd_set(u_int type, struct osd *osd, u_int slot, void *value)
+{
+ struct rm_priotracker tracker;
+
+ KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
+ KASSERT(slot > 0, ("Invalid slot."));
+ KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));
+
+ rm_rlock(&osd_object_lock[type], &tracker);
+ if (slot > osd->osd_nslots) {
+ if (value == NULL) {
+ OSD_DEBUG(
+ "Not allocating null slot (type=%u, slot=%u).",
+ type, slot);
+ rm_runlock(&osd_object_lock[type], &tracker);
+ return (0);
+ } else if (osd->osd_nslots == 0) {
+ /*
+ * First OSD for this object, so we need to allocate
+ * space and put it onto the list.
+ */
+ osd->osd_slots = malloc(sizeof(void *) * slot, M_OSD,
+ M_NOWAIT | M_ZERO);
+ if (osd->osd_slots == NULL) {
+ rm_runlock(&osd_object_lock[type], &tracker);
+ return (ENOMEM);
+ }
+ osd->osd_nslots = slot;
+ mtx_lock(&osd_list_lock[type]);
+ LIST_INSERT_HEAD(&osd_list[type], osd, osd_next);
+ mtx_unlock(&osd_list_lock[type]);
+ OSD_DEBUG("Setting first slot (type=%u).", type);
+ } else {
+ void *newptr;
+
+ /*
+ * Too few slots allocated here, needs to extend
+ * the array.
+ */
+ newptr = realloc(osd->osd_slots, sizeof(void *) * slot,
+ M_OSD, M_NOWAIT | M_ZERO);
+ if (newptr == NULL) {
+ rm_runlock(&osd_object_lock[type], &tracker);
+ return (ENOMEM);
+ }
+ osd->osd_slots = newptr;
+ osd->osd_nslots = slot;
+ OSD_DEBUG("Growing slots array (type=%u).", type);
+ }
+ }
+ OSD_DEBUG("Setting slot value (type=%u, slot=%u, value=%p).", type,
+ slot, value);
+ osd->osd_slots[slot - 1] = value;
+ rm_runlock(&osd_object_lock[type], &tracker);
+ return (0);
+}
+
+void *
+osd_get(u_int type, struct osd *osd, u_int slot)
+{
+ struct rm_priotracker tracker;
+ void *value;
+
+ KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
+ KASSERT(slot > 0, ("Invalid slot."));
+ KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));
+
+ rm_rlock(&osd_object_lock[type], &tracker);
+ if (slot > osd->osd_nslots) {
+ value = NULL;
+ OSD_DEBUG("Slot doesn't exist (type=%u, slot=%u).", type, slot);
+ } else {
+ value = osd->osd_slots[slot - 1];
+ OSD_DEBUG("Returning slot value (type=%u, slot=%u, value=%p).",
+ type, slot, value);
+ }
+ rm_runlock(&osd_object_lock[type], &tracker);
+ return (value);
+}
+
+void
+osd_del(u_int type, struct osd *osd, u_int slot)
+{
+ struct rm_priotracker tracker;
+
+ rm_rlock(&osd_object_lock[type], &tracker);
+ do_osd_del(type, osd, slot, 0);
+ rm_runlock(&osd_object_lock[type], &tracker);
+}
+
+static void
+do_osd_del(u_int type, struct osd *osd, u_int slot, int list_locked)
+{
+ int i;
+
+ KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
+ KASSERT(slot > 0, ("Invalid slot."));
+ KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));
+
+ OSD_DEBUG("Deleting slot (type=%u, slot=%u).", type, slot);
+
+ if (slot > osd->osd_nslots) {
+ OSD_DEBUG("Slot doesn't exist (type=%u, slot=%u).", type, slot);
+ return;
+ }
+ if (osd->osd_slots[slot - 1] != NULL) {
+ osd_destructors[type][slot - 1](osd->osd_slots[slot - 1]);
+ osd->osd_slots[slot - 1] = NULL;
+ }
+ for (i = osd->osd_nslots - 1; i >= 0; i--) {
+ if (osd->osd_slots[i] != NULL) {
+ OSD_DEBUG("Slot still has a value (type=%u, slot=%u).",
+ type, i + 1);
+ break;
+ }
+ }
+ if (i == -1) {
+ /* No values left for this object. */
+ OSD_DEBUG("No more slots left (type=%u).", type);
+ if (!list_locked)
+ mtx_lock(&osd_list_lock[type]);
+ LIST_REMOVE(osd, osd_next);
+ if (!list_locked)
+ mtx_unlock(&osd_list_lock[type]);
+ free(osd->osd_slots, M_OSD);
+ osd->osd_slots = NULL;
+ osd->osd_nslots = 0;
+ } else if (slot == osd->osd_nslots) {
+ /* This was the last slot. */
+ osd->osd_slots = realloc(osd->osd_slots,
+ sizeof(void *) * (i + 1), M_OSD, M_NOWAIT | M_ZERO);
+ /*
+ * We always reallocate to smaller size, so we assume it will
+ * always succeed.
+ */
+ KASSERT(osd->osd_slots != NULL, ("realloc() failed"));
+ osd->osd_nslots = i + 1;
+ OSD_DEBUG("Reducing slots array to %u (type=%u).",
+ osd->osd_nslots, type);
+ }
+}
+
+int
+osd_call(u_int type, u_int method, void *obj, void *data)
+{
+ osd_method_t methodfun;
+ int error, i;
+
+ KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
+ KASSERT(method < osd_nmethods[type], ("Invalid method."));
+
+ /*
+ * Call this method for every slot that defines it, stopping if an
+ * error is encountered.
+ */
+ error = 0;
+ sx_slock(&osd_module_lock[type]);
+ for (i = 0; i < osd_nslots[type]; i++) {
+ methodfun =
+ osd_methods[type][i * osd_nmethods[type] + method];
+ if (methodfun != NULL && (error = methodfun(obj, data)) != 0)
+ break;
+ }
+ sx_sunlock(&osd_module_lock[type]);
+ return (error);
+}
+
+void
+osd_exit(u_int type, struct osd *osd)
+{
+ struct rm_priotracker tracker;
+ u_int i;
+
+ KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
+
+ if (osd->osd_nslots == 0) {
+ KASSERT(osd->osd_slots == NULL, ("Non-null osd_slots."));
+ /* No OSD attached, just leave. */
+ return;
+ }
+
+ rm_rlock(&osd_object_lock[type], &tracker);
+ for (i = 1; i <= osd->osd_nslots; i++) {
+ if (osd_destructors[type][i - 1] != NULL)
+ do_osd_del(type, osd, i, 0);
+ else
+ OSD_DEBUG("Unused slot (type=%u, slot=%u).", type, i);
+ }
+ rm_runlock(&osd_object_lock[type], &tracker);
+ OSD_DEBUG("Object exit (type=%u).", type);
+}
+
+static void
+osd_init(void *arg __unused)
+{
+ u_int i;
+
+ for (i = OSD_FIRST; i <= OSD_LAST; i++) {
+ osd_nslots[i] = 0;
+ LIST_INIT(&osd_list[i]);
+ sx_init(&osd_module_lock[i], "osd_module");
+ rm_init(&osd_object_lock[i], "osd_object");
+ mtx_init(&osd_list_lock[i], "osd_list", NULL, MTX_DEF);
+ osd_destructors[i] = NULL;
+ osd_methods[i] = NULL;
+ }
+}
+SYSINIT(osd, SI_SUB_LOCK, SI_ORDER_ANY, osd_init, NULL);
diff --git a/freebsd/sys/kern/kern_subr.c b/freebsd/sys/kern/kern_subr.c
index ec671200..0cbc75b9 100644
--- a/freebsd/sys/kern/kern_subr.c
+++ b/freebsd/sys/kern/kern_subr.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/ktr.h>
#include <sys/limits.h>
#include <rtems/bsd/sys/lock.h>
+#include <sys/mman.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/malloc.h>
@@ -56,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <sys/vnode.h>
#include <vm/vm.h>
+#include <vm/vm_extern.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
#include <sys/uio.h>
@@ -67,7 +69,11 @@ __FBSDID("$FreeBSD$");
#ifndef __rtems__
SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, NULL, UIO_MAXIOV,
"Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)");
+#endif /* __rtems__ */
+
+static int uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault);
+#ifndef __rtems__
#ifdef ZERO_COPY_SOCKETS
/* Declared in uipc_socket.c */
extern int so_zero_copy_receive;
@@ -132,31 +138,75 @@ retry:
return(KERN_SUCCESS);
}
#endif /* ZERO_COPY_SOCKETS */
+
+int
+copyin_nofault(const void *udaddr, void *kaddr, size_t len)
+{
+ int error, save;
+
+ save = vm_fault_disable_pagefaults();
+ error = copyin(udaddr, kaddr, len);
+ vm_fault_enable_pagefaults(save);
+ return (error);
+}
+
+int
+copyout_nofault(const void *kaddr, void *udaddr, size_t len)
+{
+ int error, save;
+
+ save = vm_fault_disable_pagefaults();
+ error = copyout(kaddr, udaddr, len);
+ vm_fault_enable_pagefaults(save);
+ return (error);
+}
#endif /* __rtems__ */
int
uiomove(void *cp, int n, struct uio *uio)
{
+
+ return (uiomove_faultflag(cp, n, uio, 0));
+}
+
+int
+uiomove_nofault(void *cp, int n, struct uio *uio)
+{
+
+ return (uiomove_faultflag(cp, n, uio, 1));
+}
+
+static int
+uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault)
+{
#ifndef __rtems__
- struct thread *td = curthread;
+ struct thread *td;
#endif /* __rtems__ */
struct iovec *iov;
u_int cnt;
- int error = 0;
-#ifndef __rtems__
- int save = 0;
-#endif /* __rtems__ */
+ int error, newflags, save;
KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
("uiomove: mode"));
- KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
+ KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == td,
("uiomove proc"));
- WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
- "Calling uiomove()");
+ if (!nofault)
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
+ "Calling uiomove()");
#ifndef __rtems__
- save = td->td_pflags & TDP_DEADLKTREAT;
- td->td_pflags |= TDP_DEADLKTREAT;
+ /* XXX does it make a sense to set TDP_DEADLKTREAT for UIO_SYSSPACE ? */
+ newflags = TDP_DEADLKTREAT;
+ if (uio->uio_segflg == UIO_USERSPACE && nofault) {
+ /*
+ * Fail if a non-spurious page fault occurs.
+ */
+ newflags |= TDP_NOFAULTING | TDP_RESETSPUR;
+ }
+ save = curthread_pflags_set(newflags);
+#else /* __rtems__ */
+ (void) newflags;
+ (void) save;
#endif /* __rtems__ */
while (n > 0 && uio->uio_resid) {
@@ -203,8 +253,7 @@ uiomove(void *cp, int n, struct uio *uio)
}
out:
#ifndef __rtems__
- if (save == 0)
- td->td_pflags &= ~TDP_DEADLKTREAT;
+ curthread_pflags_restore(save);
#endif /* __rtems__ */
return (error);
}
@@ -388,9 +437,7 @@ hashinit_flags(int elements, struct malloc_type *type, u_long *hashmask,
LIST_HEAD(generic, generic) *hashtbl;
int i;
- if (elements <= 0)
- panic("hashinit: bad elements");
-
+ KASSERT(elements > 0, ("%s: bad elements", __func__));
/* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */
KASSERT((flags & HASH_WAITOK) ^ (flags & HASH_NOWAIT),
("Bad flags (0x%x) passed to hashinit_flags", flags));
@@ -431,8 +478,7 @@ hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask)
hashtbl = vhashtbl;
for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++)
- if (!LIST_EMPTY(hp))
- panic("hashdestroy: hash not empty");
+ KASSERT(LIST_EMPTY(hp), ("%s: hash not empty", __func__));
free(hashtbl, type);
}
@@ -451,8 +497,7 @@ phashinit(int elements, struct malloc_type *type, u_long *nentries)
LIST_HEAD(generic, generic) *hashtbl;
int i;
- if (elements <= 0)
- panic("phashinit: bad elements");
+ KASSERT(elements > 0, ("%s: bad elements", __func__));
for (i = 1, hashsize = primes[1]; hashsize <= elements;) {
i++;
if (i == NPRIMES)
@@ -471,16 +516,8 @@ phashinit(int elements, struct malloc_type *type, u_long *nentries)
void
uio_yield(void)
{
- struct thread *td;
- td = curthread;
- DROP_GIANT();
- thread_lock(td);
- sched_prio(td, td->td_user_pri);
- mi_switch(SW_INVOL | SWT_RELINQUISH, NULL);
- thread_unlock(td);
- rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
- PICKUP_GIANT();
+ kern_yield(PRI_USER);
}
int
@@ -591,4 +628,55 @@ cloneuio(struct uio *uiop)
bcopy(uiop->uio_iov, uio->uio_iov, iovlen);
return (uio);
}
+
+/*
+ * Map some anonymous memory in user space of size sz, rounded up to the page
+ * boundary.
+ */
+int
+copyout_map(struct thread *td, vm_offset_t *addr, size_t sz)
+{
+ struct vmspace *vms;
+ int error;
+ vm_size_t size;
+
+ vms = td->td_proc->p_vmspace;
+
+ /*
+ * Map somewhere after heap in process memory.
+ */
+ PROC_LOCK(td->td_proc);
+ *addr = round_page((vm_offset_t)vms->vm_daddr +
+ lim_max(td->td_proc, RLIMIT_DATA));
+ PROC_UNLOCK(td->td_proc);
+
+ /* round size up to page boundry */
+ size = (vm_size_t)round_page(sz);
+
+ error = vm_mmap(&vms->vm_map, addr, size, PROT_READ | PROT_WRITE,
+ VM_PROT_ALL, MAP_PRIVATE | MAP_ANON, OBJT_DEFAULT, NULL, 0);
+
+ return (error);
+}
+
+/*
+ * Unmap memory in user space.
+ */
+int
+copyout_unmap(struct thread *td, vm_offset_t addr, size_t sz)
+{
+ vm_map_t map;
+ vm_size_t size;
+
+ if (sz == 0)
+ return (0);
+
+ map = &td->td_proc->p_vmspace->vm_map;
+ size = (vm_size_t)round_page(sz);
+
+ if (vm_map_remove(map, addr, addr + size) != KERN_SUCCESS)
+ return (EINVAL);
+
+ return (0);
+}
#endif /* __rtems__ */
diff --git a/freebsd/sys/kern/kern_sysctl.c b/freebsd/sys/kern/kern_sysctl.c
index 750de376..fad7ec10 100644
--- a/freebsd/sys/kern/kern_sysctl.c
+++ b/freebsd/sys/kern/kern_sysctl.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_ktrace.h>
#include <rtems/bsd/sys/param.h>
+#include <sys/fail.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
@@ -53,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/jail.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
+#include <sys/sbuf.h>
#include <sys/sx.h>
#include <sys/sysproto.h>
#include <sys/uio.h>
@@ -87,13 +89,12 @@ static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
static struct sx sysctllock;
static struct sx sysctlmemlock;
-#define SYSCTL_SLOCK() sx_slock(&sysctllock)
-#define SYSCTL_SUNLOCK() sx_sunlock(&sysctllock)
#define SYSCTL_XLOCK() sx_xlock(&sysctllock)
#define SYSCTL_XUNLOCK() sx_xunlock(&sysctllock)
#define SYSCTL_ASSERT_XLOCKED() sx_assert(&sysctllock, SA_XLOCKED)
-#define SYSCTL_ASSERT_LOCKED() sx_assert(&sysctllock, SA_LOCKED)
#define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock")
+#define SYSCTL_SLEEP(ch, wmesg, timo) \
+ sx_sleep(ch, &sysctllock, 0, wmesg, timo)
static int sysctl_root(SYSCTL_HANDLER_ARGS);
@@ -107,7 +108,7 @@ sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
{
struct sysctl_oid *oidp;
- SYSCTL_ASSERT_LOCKED();
+ SYSCTL_ASSERT_XLOCKED();
SLIST_FOREACH(oidp, list, oid_link) {
if (strcmp(oidp->oid_name, name) == 0) {
return (oidp);
@@ -314,7 +315,7 @@ sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
{
struct sysctl_ctx_entry *e;
- SYSCTL_ASSERT_LOCKED();
+ SYSCTL_ASSERT_XLOCKED();
if (clist == NULL || oidp == NULL)
return(NULL);
TAILQ_FOREACH(e, clist, link) {
@@ -410,10 +411,20 @@ sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
}
sysctl_unregister_oid(oidp);
if (del) {
+ /*
+ * Wait for all threads running the handler to drain.
+ * This preserves the previous behavior when the
+ * sysctl lock was held across a handler invocation,
+ * and is necessary for module unload correctness.
+ */
+ while (oidp->oid_running > 0) {
+ oidp->oid_kind |= CTLFLAG_DYING;
+ SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0);
+ }
if (oidp->oid_descr)
- free((void *)(uintptr_t)(const void *)oidp->oid_descr, M_SYSCTLOID);
- free((void *)(uintptr_t)(const void *)oidp->oid_name,
- M_SYSCTLOID);
+ free(__DECONST(char *, oidp->oid_descr),
+ M_SYSCTLOID);
+ free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID);
free(oidp, M_SYSCTLOID);
}
}
@@ -430,8 +441,6 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr)
{
struct sysctl_oid *oidp;
- ssize_t len;
- char *newname;
/* You have to hook up somewhere.. */
if (parent == NULL)
@@ -458,11 +467,7 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
SLIST_NEXT(oidp, oid_link) = NULL;
oidp->oid_number = number;
oidp->oid_refcnt = 1;
- len = strlen(name);
- newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
- bcopy(name, newname, len + 1);
- newname[len] = '\0';
- oidp->oid_name = newname;
+ oidp->oid_name = strdup(name, M_SYSCTLOID);
oidp->oid_handler = handler;
oidp->oid_kind = CTLFLAG_DYN | kind;
if ((kind & CTLTYPE) == CTLTYPE_NODE) {
@@ -475,12 +480,8 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
oidp->oid_arg2 = arg2;
}
oidp->oid_fmt = fmt;
- if (descr) {
- int len = strlen(descr) + 1;
- oidp->oid_descr = malloc(len, M_SYSCTLOID, M_WAITOK);
- if (oidp->oid_descr)
- strcpy((char *)(uintptr_t)(const void *)oidp->oid_descr, descr);
- }
+ if (descr)
+ oidp->oid_descr = strdup(descr, M_SYSCTLOID);
/* Update the context, if used */
if (clist != NULL)
sysctl_ctx_entry_add(clist, oidp);
@@ -496,16 +497,12 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
void
sysctl_rename_oid(struct sysctl_oid *oidp, const char *name)
{
- ssize_t len;
char *newname;
- void *oldname;
+ char *oldname;
- len = strlen(name);
- newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
- bcopy(name, newname, len + 1);
- newname[len] = '\0';
+ newname = strdup(name, M_SYSCTLOID);
SYSCTL_XLOCK();
- oldname = (void *)(uintptr_t)(const void *)oidp->oid_name;
+ oldname = __DECONST(char *, oidp->oid_name);
oidp->oid_name = newname;
SYSCTL_XUNLOCK();
free(oldname, M_SYSCTLOID);
@@ -582,7 +579,7 @@ sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
int k;
struct sysctl_oid *oidp;
- SYSCTL_ASSERT_LOCKED();
+ SYSCTL_ASSERT_XLOCKED();
SLIST_FOREACH(oidp, l, oid_link) {
for (k=0; k<i; k++)
@@ -623,7 +620,9 @@ sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
if (error)
return (error);
+ SYSCTL_XLOCK();
sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
+ SYSCTL_XUNLOCK();
return (ENOENT);
}
@@ -641,7 +640,7 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
char buf[10];
- SYSCTL_ASSERT_LOCKED();
+ SYSCTL_XLOCK();
while (namelen) {
if (!lsp) {
snprintf(buf,sizeof(buf),"%d",*name);
@@ -650,7 +649,7 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
if (!error)
error = SYSCTL_OUT(req, buf, strlen(buf));
if (error)
- return (error);
+ goto out;
namelen--;
name++;
continue;
@@ -666,7 +665,7 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
error = SYSCTL_OUT(req, oid->oid_name,
strlen(oid->oid_name));
if (error)
- return (error);
+ goto out;
namelen--;
name++;
@@ -677,12 +676,15 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
if (oid->oid_handler)
break;
- lsp2 = (struct sysctl_oid_list *)oid->oid_arg1;
+ lsp2 = SYSCTL_CHILDREN(oid);
break;
}
lsp = lsp2;
}
- return (SYSCTL_OUT(req, "", 1));
+ error = SYSCTL_OUT(req, "", 1);
+ out:
+ SYSCTL_XUNLOCK();
+ return (error);
}
static SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, "");
@@ -693,7 +695,7 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
{
struct sysctl_oid *oidp;
- SYSCTL_ASSERT_LOCKED();
+ SYSCTL_ASSERT_XLOCKED();
*len = level;
SLIST_FOREACH(oidp, lsp, oid_link) {
*next = oidp->oid_number;
@@ -708,7 +710,7 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
if (oidp->oid_handler)
/* We really should call the handler here...*/
return (0);
- lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
+ lsp = SYSCTL_CHILDREN(oidp);
if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1,
len, level+1, oidpp))
return (0);
@@ -723,7 +725,7 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
return (0);
if (oidp->oid_handler)
return (0);
- lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
+ lsp = SYSCTL_CHILDREN(oidp);
if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1,
next+1, len, level+1, oidpp))
return (0);
@@ -735,7 +737,7 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
if (oidp->oid_handler)
continue;
- lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
+ lsp = SYSCTL_CHILDREN(oidp);
if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1,
len, level+1, oidpp))
return (0);
@@ -757,7 +759,9 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
struct sysctl_oid_list *lsp = &sysctl__children;
int newoid[CTL_MAXNAME];
+ SYSCTL_XLOCK();
i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
+ SYSCTL_XUNLOCK();
if (i)
return (ENOENT);
error = SYSCTL_OUT(req, newoid, j * sizeof (int));
@@ -769,39 +773,26 @@ static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, "");
static int
name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
{
- int i;
struct sysctl_oid *oidp;
struct sysctl_oid_list *lsp = &sysctl__children;
char *p;
- SYSCTL_ASSERT_LOCKED();
-
- if (!*name)
- return (ENOENT);
-
- p = name + strlen(name) - 1 ;
- if (*p == '.')
- *p = '\0';
-
- *len = 0;
-
- for (p = name; *p && *p != '.'; p++)
- ;
- i = *p;
- if (i == '.')
- *p = '\0';
+ SYSCTL_ASSERT_XLOCKED();
- oidp = SLIST_FIRST(lsp);
+ for (*len = 0; *len < CTL_MAXNAME;) {
+ p = strsep(&name, ".");
- while (oidp && *len < CTL_MAXNAME) {
- if (strcmp(name, oidp->oid_name)) {
- oidp = SLIST_NEXT(oidp, oid_link);
- continue;
+ oidp = SLIST_FIRST(lsp);
+ for (;; oidp = SLIST_NEXT(oidp, oid_link)) {
+ if (oidp == NULL)
+ return (ENOENT);
+ if (strcmp(p, oidp->oid_name) == 0)
+ break;
}
*oid++ = oidp->oid_number;
(*len)++;
- if (!i) {
+ if (name == NULL || *name == '\0') {
if (oidpp)
*oidpp = oidp;
return (0);
@@ -813,14 +804,7 @@ name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
if (oidp->oid_handler)
break;
- lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
- oidp = SLIST_FIRST(lsp);
- name = p+1;
- for (p = name; *p && *p != '.'; p++)
- ;
- i = *p;
- if (i == '.')
- *p = '\0';
+ lsp = SYSCTL_CHILDREN(oidp);
}
return (ENOENT);
}
@@ -832,8 +816,6 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
int error, oid[CTL_MAXNAME], len;
struct sysctl_oid *op = 0;
- SYSCTL_ASSERT_LOCKED();
-
if (!req->newlen)
return (ENOENT);
if (req->newlen >= MAXPATHLEN) /* XXX arbitrary, undocumented */
@@ -848,8 +830,10 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
}
p [req->newlen] = '\0';
-
+ len = 0;
+ SYSCTL_XLOCK();
error = name2oid(p, oid, &len, &op);
+ SYSCTL_XUNLOCK();
free(p, M_SYSCTL);
@@ -869,16 +853,21 @@ sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
struct sysctl_oid *oid;
int error;
+ SYSCTL_XLOCK();
error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
if (error)
- return (error);
+ goto out;
- if (!oid->oid_fmt)
- return (ENOENT);
+ if (oid->oid_fmt == NULL) {
+ error = ENOENT;
+ goto out;
+ }
error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind));
if (error)
- return (error);
+ goto out;
error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
+ out:
+ SYSCTL_XUNLOCK();
return (error);
}
@@ -892,13 +881,18 @@ sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
struct sysctl_oid *oid;
int error;
+ SYSCTL_XLOCK();
error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
if (error)
- return (error);
+ goto out;
- if (!oid->oid_descr)
- return (ENOENT);
+ if (oid->oid_descr == NULL) {
+ error = ENOENT;
+ goto out;
+ }
error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
+ out:
+ SYSCTL_XUNLOCK();
return (error);
}
@@ -966,7 +960,10 @@ sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
/*
- * Handle a long, signed or unsigned. arg1 points to it.
+ * Handle a long, signed or unsigned.
+ * Two cases:
+ * a variable: point arg1 at it.
+ * a constant: pass it in arg2.
*/
int
@@ -981,9 +978,10 @@ sysctl_handle_long(SYSCTL_HANDLER_ARGS)
/*
* Attempt to get a coherent snapshot by making a copy of the data.
*/
- if (!arg1)
- return (EINVAL);
- tmplong = *(long *)arg1;
+ if (arg1)
+ tmplong = *(long *)arg1;
+ else
+ tmplong = arg2;
#ifdef SCTL_MASK32
if (req->flags & SCTL_MASK32) {
tmpint = tmplong;
@@ -995,18 +993,24 @@ sysctl_handle_long(SYSCTL_HANDLER_ARGS)
if (error || !req->newptr)
return (error);
+ if (!arg1)
+ error = EPERM;
#ifdef SCTL_MASK32
- if (req->flags & SCTL_MASK32) {
+ else if (req->flags & SCTL_MASK32) {
error = SYSCTL_IN(req, &tmpint, sizeof(int));
*(long *)arg1 = (long)tmpint;
- } else
+ }
#endif
+ else
error = SYSCTL_IN(req, arg1, sizeof(long));
return (error);
}
/*
- * Handle a 64 bit int, signed or unsigned. arg1 points to it.
+ * Handle a 64 bit int, signed or unsigned.
+ * Two cases:
+ * a variable: point arg1 at it.
+ * a constant: pass it in arg2.
*/
int
@@ -1018,15 +1022,19 @@ sysctl_handle_quad(SYSCTL_HANDLER_ARGS)
/*
* Attempt to get a coherent snapshot by making a copy of the data.
*/
- if (!arg1)
- return (EINVAL);
- tmpout = *(uint64_t *)arg1;
+ if (arg1)
+ tmpout = *(uint64_t *)arg1;
+ else
+ tmpout = arg2;
error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t));
if (error || !req->newptr)
return (error);
- error = SYSCTL_IN(req, arg1, sizeof(uint64_t));
+ if (!arg1)
+ error = EPERM;
+ else
+ error = SYSCTL_IN(req, arg1, sizeof(uint64_t));
return (error);
}
@@ -1192,9 +1200,9 @@ kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
req.newfunc = sysctl_new_kernel;
req.lock = REQ_LOCKED;
- SYSCTL_SLOCK();
+ SYSCTL_XLOCK();
error = sysctl_root(0, name, namelen, &req);
- SYSCTL_SUNLOCK();
+ SYSCTL_XUNLOCK();
if (req.lock == REQ_WIRED && req.validlen > 0)
vsunlock(req.oldptr, req.validlen);
@@ -1241,8 +1249,8 @@ kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp,
static int
sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
{
- int error = 0;
size_t i, len, origidx;
+ int error;
origidx = req->oldidx;
req->oldidx += l;
@@ -1263,10 +1271,14 @@ sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
else {
if (i > len - origidx)
i = len - origidx;
- error = copyout(p, (char *)req->oldptr + origidx, i);
+ if (req->lock == REQ_WIRED) {
+ error = copyout_nofault(p, (char *)req->oldptr +
+ origidx, i);
+ } else
+ error = copyout(p, (char *)req->oldptr + origidx, i);
+ if (error != 0)
+ return (error);
}
- if (error)
- return (error);
if (i < l)
return (ENOMEM);
return (0);
@@ -1322,37 +1334,43 @@ int
sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
int *nindx, struct sysctl_req *req)
{
+ struct sysctl_oid_list *lsp;
struct sysctl_oid *oid;
int indx;
- SYSCTL_ASSERT_LOCKED();
- oid = SLIST_FIRST(&sysctl__children);
+ SYSCTL_ASSERT_XLOCKED();
+ lsp = &sysctl__children;
indx = 0;
- while (oid && indx < CTL_MAXNAME) {
- if (oid->oid_number == name[indx]) {
- indx++;
- if (oid->oid_kind & CTLFLAG_NOLOCK)
- req->lock = REQ_UNLOCKED;
- if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
- if (oid->oid_handler != NULL ||
- indx == namelen) {
- *noid = oid;
- if (nindx != NULL)
- *nindx = indx;
- return (0);
- }
- oid = SLIST_FIRST(
- (struct sysctl_oid_list *)oid->oid_arg1);
- } else if (indx == namelen) {
+ while (indx < CTL_MAXNAME) {
+ SLIST_FOREACH(oid, lsp, oid_link) {
+ if (oid->oid_number == name[indx])
+ break;
+ }
+ if (oid == NULL)
+ return (ENOENT);
+
+ indx++;
+ if (oid->oid_kind & CTLFLAG_NOLOCK)
+ req->lock = REQ_UNLOCKED;
+ if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
+ if (oid->oid_handler != NULL || indx == namelen) {
*noid = oid;
if (nindx != NULL)
*nindx = indx;
+ KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
+ ("%s found DYING node %p", __func__, oid));
return (0);
- } else {
- return (ENOTDIR);
}
+ lsp = SYSCTL_CHILDREN(oid);
+ } else if (indx == namelen) {
+ *noid = oid;
+ if (nindx != NULL)
+ *nindx = indx;
+ KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
+ ("%s found DYING node %p", __func__, oid));
+ return (0);
} else {
- oid = SLIST_NEXT(oid, oid_link);
+ return (ENOTDIR);
}
}
return (ENOENT);
@@ -1369,7 +1387,7 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
struct sysctl_oid *oid;
int error, indx, lvl;
- SYSCTL_ASSERT_LOCKED();
+ SYSCTL_ASSERT_XLOCKED();
error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
if (error)
@@ -1437,12 +1455,23 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
if (error != 0)
return (error);
#endif
+ oid->oid_running++;
+ SYSCTL_XUNLOCK();
+
if (!(oid->oid_kind & CTLFLAG_MPSAFE))
mtx_lock(&Giant);
error = oid->oid_handler(oid, arg1, arg2, req);
if (!(oid->oid_kind & CTLFLAG_MPSAFE))
mtx_unlock(&Giant);
+#ifndef __rtems__
+ KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error);
+#endif /* __rtems__ */
+
+ SYSCTL_XLOCK();
+ oid->oid_running--;
+ if (oid->oid_running == 0 && (oid->oid_kind & CTLFLAG_DYING) != 0)
+ wakeup(&oid->oid_running);
return (error);
}
@@ -1543,9 +1572,9 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
for (;;) {
req.oldidx = 0;
req.newidx = 0;
- SYSCTL_SLOCK();
+ SYSCTL_XLOCK();
error = sysctl_root(0, name, namelen, &req);
- SYSCTL_SUNLOCK();
+ SYSCTL_XUNLOCK();
if (error != EAGAIN)
break;
uio_yield();
@@ -1569,4 +1598,29 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
}
return (error);
}
+
+/*
+ * Drain into a sysctl struct. The user buffer should be wired if a page
+ * fault would cause issue.
+ */
+static int
+sbuf_sysctl_drain(void *arg, const char *data, int len)
+{
+ struct sysctl_req *req = arg;
+ int error;
+
+ error = SYSCTL_OUT(req, data, len);
+ KASSERT(error >= 0, ("Got unexpected negative value %d", error));
+ return (error == 0 ? len : -error);
+}
+
+struct sbuf *
+sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length,
+ struct sysctl_req *req)
+{
+
+ s = sbuf_new(s, buf, length, SBUF_FIXEDLEN);
+ sbuf_set_drain(s, sbuf_sysctl_drain, req);
+ return (s);
+}
#endif /* __rtems__ */
diff --git a/freebsd/sys/kern/kern_timeout.c b/freebsd/sys/kern/kern_timeout.c
index a7fe5d59..73cbd571 100644
--- a/freebsd/sys/kern/kern_timeout.c
+++ b/freebsd/sys/kern/kern_timeout.c
@@ -58,14 +58,18 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/smp.h>
+#ifdef SMP
+#include <machine/cpu.h>
+#endif
+
#ifdef __rtems__
int ncallout = 16;
#endif /* __rtems__ */
SDT_PROVIDER_DEFINE(callout_execute);
-SDT_PROBE_DEFINE(callout_execute, kernel, , callout_start);
+SDT_PROBE_DEFINE(callout_execute, kernel, , callout_start, callout-start);
SDT_PROBE_ARGTYPE(callout_execute, kernel, , callout_start, 0,
"struct callout *");
-SDT_PROBE_DEFINE(callout_execute, kernel, , callout_end);
+SDT_PROBE_DEFINE(callout_execute, kernel, , callout_end, callout-end);
SDT_PROBE_ARGTYPE(callout_execute, kernel, , callout_end, 0,
"struct callout *");
@@ -88,6 +92,21 @@ SYSCTL_INT(_debug, OID_AUTO, to_avg_mpcalls, CTLFLAG_RD, &avg_mpcalls, 0,
int callwheelsize, callwheelbits, callwheelmask;
/*
+ * The callout cpu migration entity represents informations necessary for
+ * describing the migrating callout to the new callout cpu.
+ * The cached informations are very important for deferring migration when
+ * the migrating callout is already running.
+ */
+struct cc_mig_ent {
+#ifdef SMP
+ void (*ce_migration_func)(void *);
+ void *ce_migration_arg;
+ int ce_migration_cpu;
+ int ce_migration_ticks;
+#endif
+};
+
+/*
* There is one struct callout_cpu per cpu, holding all relevant
* state for the callout processing thread on the individual CPU.
* In particular:
@@ -105,6 +124,7 @@ int callwheelsize, callwheelbits, callwheelmask;
* when the callout should be served.
*/
struct callout_cpu {
+ struct cc_mig_ent cc_migrating_entity;
struct mtx cc_lock;
struct callout *cc_callout;
struct callout_tailq *cc_callwheel;
@@ -119,7 +139,13 @@ struct callout_cpu {
};
#ifdef SMP
+#define cc_migration_func cc_migrating_entity.ce_migration_func
+#define cc_migration_arg cc_migrating_entity.ce_migration_arg
+#define cc_migration_cpu cc_migrating_entity.ce_migration_cpu
+#define cc_migration_ticks cc_migrating_entity.ce_migration_ticks
+
struct callout_cpu cc_cpu[MAXCPU];
+#define CPUBLOCK MAXCPU
#define CC_CPU(cpu) (&cc_cpu[(cpu)])
#define CC_SELF() CC_CPU(PCPU_GET(cpuid))
#else
@@ -129,6 +155,7 @@ struct callout_cpu cc_cpu;
#endif
#define CC_LOCK(cc) mtx_lock_spin(&(cc)->cc_lock)
#define CC_UNLOCK(cc) mtx_unlock_spin(&(cc)->cc_lock)
+#define CC_LOCK_ASSERT(cc) mtx_assert(&(cc)->cc_lock, MA_OWNED)
static int timeout_cpu;
@@ -152,6 +179,35 @@ MALLOC_DEFINE(M_CALLOUT, "callout", "Callout datastructures");
*/
/*
+ * Resets the migration entity tied to a specific callout cpu.
+ */
+static void
+cc_cme_cleanup(struct callout_cpu *cc)
+{
+
+#ifdef SMP
+ cc->cc_migration_cpu = CPUBLOCK;
+ cc->cc_migration_ticks = 0;
+ cc->cc_migration_func = NULL;
+ cc->cc_migration_arg = NULL;
+#endif
+}
+
+/*
+ * Checks if migration is requested by a specific callout cpu.
+ */
+static int
+cc_cme_migrating(struct callout_cpu *cc)
+{
+
+#ifdef SMP
+ return (cc->cc_migration_cpu != CPUBLOCK);
+#else
+ return (0);
+#endif
+}
+
+/*
* kern_timeout_callwheel_alloc() - kernel low level callwheel initialization
*
* This code is called very early in the kernel initialization sequence,
@@ -237,6 +293,7 @@ callout_cpu_init(struct callout_cpu *cc)
for (i = 0; i < callwheelsize; i++) {
TAILQ_INIT(&cc->cc_callwheel[i]);
}
+ cc_cme_cleanup(cc);
if (cc->cc_callout == NULL)
return;
for (i = 0; i < ncallout; i++) {
@@ -247,6 +304,36 @@ callout_cpu_init(struct callout_cpu *cc)
}
}
+#ifdef SMP
+/*
+ * Switches the cpu tied to a specific callout.
+ * The function expects a locked incoming callout cpu and returns with
+ * locked outcoming callout cpu.
+ */
+static struct callout_cpu *
+callout_cpu_switch(struct callout *c, struct callout_cpu *cc, int new_cpu)
+{
+ struct callout_cpu *new_cc;
+
+ MPASS(c != NULL && cc != NULL);
+ CC_LOCK_ASSERT(cc);
+
+ /*
+ * Avoid interrupts and preemption firing after the callout cpu
+ * is blocked in order to avoid deadlocks as the new thread
+ * may be willing to acquire the callout cpu lock.
+ */
+ c->c_cpu = CPUBLOCK;
+ spinlock_enter();
+ CC_UNLOCK(cc);
+ new_cc = CC_CPU(new_cpu);
+ CC_LOCK(new_cc);
+ spinlock_exit();
+ c->c_cpu = new_cpu;
+ return (new_cc);
+}
+#endif
+
#ifndef __rtems__
/*
* kern_timeout_callwheel_init() - initialize previously reserved callwheel
@@ -281,11 +368,9 @@ start_softclock(void *dummy)
panic("died while creating standard software ithreads");
cc->cc_cookie = softclock_ih;
#ifdef SMP
- for (cpu = 0; cpu <= mp_maxid; cpu++) {
+ CPU_FOREACH(cpu) {
if (cpu == timeout_cpu)
continue;
- if (CPU_ABSENT(cpu))
- continue;
cc = CC_CPU(cpu);
if (swi_add(NULL, "clock", softclock, cc, SWI_CLOCK,
INTR_MPSAFE, &cc->cc_cookie))
@@ -340,6 +425,13 @@ callout_lock(struct callout *c)
for (;;) {
cpu = c->c_cpu;
+#ifdef SMP
+ if (cpu == CPUBLOCK) {
+ while (c->c_cpu == CPUBLOCK)
+ cpu_spinwait();
+ continue;
+ }
+#endif
cc = CC_CPU(cpu);
CC_LOCK(cc);
if (cpu == c->c_cpu)
@@ -349,6 +441,202 @@ callout_lock(struct callout *c)
return (cc);
}
+static void
+callout_cc_add(struct callout *c, struct callout_cpu *cc, int to_ticks,
+ void (*func)(void *), void *arg, int cpu)
+{
+
+ CC_LOCK_ASSERT(cc);
+
+ if (to_ticks <= 0)
+ to_ticks = 1;
+ c->c_arg = arg;
+ c->c_flags |= (CALLOUT_ACTIVE | CALLOUT_PENDING);
+ c->c_func = func;
+ c->c_time = cc->cc_ticks + to_ticks;
+ TAILQ_INSERT_TAIL(&cc->cc_callwheel[c->c_time & callwheelmask],
+ c, c_links.tqe);
+}
+
+static void
+callout_cc_del(struct callout *c, struct callout_cpu *cc)
+{
+
+ if (cc->cc_next == c)
+ cc->cc_next = TAILQ_NEXT(c, c_links.tqe);
+ if (c->c_flags & CALLOUT_LOCAL_ALLOC) {
+ c->c_func = NULL;
+ SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle);
+ }
+}
+
+static struct callout *
+softclock_call_cc(struct callout *c, struct callout_cpu *cc, int *mpcalls,
+ int *lockcalls, int *gcalls)
+{
+ void (*c_func)(void *);
+ void *c_arg;
+ struct lock_class *class;
+ struct lock_object *c_lock;
+ int c_flags, sharedlock;
+#ifdef SMP
+ struct callout_cpu *new_cc;
+ void (*new_func)(void *);
+ void *new_arg;
+ int new_cpu, new_ticks;
+#endif
+#ifdef DIAGNOSTIC
+ struct bintime bt1, bt2;
+ struct timespec ts2;
+ static uint64_t maxdt = 36893488147419102LL; /* 2 msec */
+ static timeout_t *lastfunc;
+#endif
+
+ cc->cc_next = TAILQ_NEXT(c, c_links.tqe);
+ class = (c->c_lock != NULL) ? LOCK_CLASS(c->c_lock) : NULL;
+ sharedlock = (c->c_flags & CALLOUT_SHAREDLOCK) ? 0 : 1;
+ c_lock = c->c_lock;
+ c_func = c->c_func;
+ c_arg = c->c_arg;
+ c_flags = c->c_flags;
+ if (c->c_flags & CALLOUT_LOCAL_ALLOC)
+ c->c_flags = CALLOUT_LOCAL_ALLOC;
+ else
+ c->c_flags &= ~CALLOUT_PENDING;
+ cc->cc_curr = c;
+ cc->cc_cancel = 0;
+ CC_UNLOCK(cc);
+ if (c_lock != NULL) {
+ class->lc_lock(c_lock, sharedlock);
+ /*
+ * The callout may have been cancelled
+ * while we switched locks.
+ */
+ if (cc->cc_cancel) {
+ class->lc_unlock(c_lock);
+ goto skip;
+ }
+ /* The callout cannot be stopped now. */
+ cc->cc_cancel = 1;
+
+ if (c_lock == &Giant.lock_object) {
+ (*gcalls)++;
+ CTR3(KTR_CALLOUT, "callout %p func %p arg %p",
+ c, c_func, c_arg);
+ } else {
+ (*lockcalls)++;
+ CTR3(KTR_CALLOUT, "callout lock %p func %p arg %p",
+ c, c_func, c_arg);
+ }
+ } else {
+ (*mpcalls)++;
+ CTR3(KTR_CALLOUT, "callout mpsafe %p func %p arg %p",
+ c, c_func, c_arg);
+ }
+#ifdef DIAGNOSTIC
+ binuptime(&bt1);
+#endif
+#ifndef __rtems__
+ THREAD_NO_SLEEPING();
+ SDT_PROBE(callout_execute, kernel, , callout_start, c, 0, 0, 0, 0);
+#endif /* __rtems__ */
+ c_func(c_arg);
+#ifndef __rtems__
+ SDT_PROBE(callout_execute, kernel, , callout_end, c, 0, 0, 0, 0);
+ THREAD_SLEEPING_OK();
+#endif /* __rtems__ */
+#ifdef DIAGNOSTIC
+ binuptime(&bt2);
+ bintime_sub(&bt2, &bt1);
+ if (bt2.frac > maxdt) {
+ if (lastfunc != c_func || bt2.frac > maxdt * 2) {
+ bintime2timespec(&bt2, &ts2);
+ printf(
+ "Expensive timeout(9) function: %p(%p) %jd.%09ld s\n",
+ c_func, c_arg, (intmax_t)ts2.tv_sec, ts2.tv_nsec);
+ }
+ maxdt = bt2.frac;
+ lastfunc = c_func;
+ }
+#endif
+ CTR1(KTR_CALLOUT, "callout %p finished", c);
+ if ((c_flags & CALLOUT_RETURNUNLOCKED) == 0)
+ class->lc_unlock(c_lock);
+skip:
+ CC_LOCK(cc);
+ /*
+ * If the current callout is locally allocated (from
+ * timeout(9)) then put it on the freelist.
+ *
+ * Note: we need to check the cached copy of c_flags because
+ * if it was not local, then it's not safe to deref the
+ * callout pointer.
+ */
+ if (c_flags & CALLOUT_LOCAL_ALLOC) {
+ KASSERT(c->c_flags == CALLOUT_LOCAL_ALLOC,
+ ("corrupted callout"));
+ c->c_func = NULL;
+ SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle);
+ }
+ cc->cc_curr = NULL;
+ if (cc->cc_waiting) {
+ /*
+ * There is someone waiting for the
+ * callout to complete.
+ * If the callout was scheduled for
+ * migration just cancel it.
+ */
+ if (cc_cme_migrating(cc))
+ cc_cme_cleanup(cc);
+ cc->cc_waiting = 0;
+ CC_UNLOCK(cc);
+ wakeup(&cc->cc_waiting);
+ CC_LOCK(cc);
+ } else if (cc_cme_migrating(cc)) {
+#ifdef SMP
+ /*
+ * If the callout was scheduled for
+ * migration just perform it now.
+ */
+ new_cpu = cc->cc_migration_cpu;
+ new_ticks = cc->cc_migration_ticks;
+ new_func = cc->cc_migration_func;
+ new_arg = cc->cc_migration_arg;
+ cc_cme_cleanup(cc);
+
+ /*
+ * Handle deferred callout stops
+ */
+ if ((c->c_flags & CALLOUT_DFRMIGRATION) == 0) {
+ CTR3(KTR_CALLOUT,
+ "deferred cancelled %p func %p arg %p",
+ c, new_func, new_arg);
+ callout_cc_del(c, cc);
+ goto nextc;
+ }
+
+ c->c_flags &= ~CALLOUT_DFRMIGRATION;
+
+ /*
+ * It should be assert here that the
+ * callout is not destroyed but that
+ * is not easy.
+ */
+ new_cc = callout_cpu_switch(c, cc, new_cpu);
+ callout_cc_add(c, new_cc, new_ticks, new_func, new_arg,
+ new_cpu);
+ CC_UNLOCK(new_cc);
+ CC_LOCK(cc);
+#else
+ panic("migration should not happen");
+#endif
+ }
+#ifdef SMP
+nextc:
+#endif
+ return (cc->cc_next);
+}
+
/*
* The callout mechanism is based on the work of Adam M. Costello and
* George Varghese, published in a technical report entitled "Redesigning
@@ -377,12 +665,6 @@ softclock(void *arg)
int mpcalls;
int lockcalls;
int gcalls;
-#ifdef DIAGNOSTIC
- struct bintime bt1, bt2;
- struct timespec ts2;
- static uint64_t maxdt = 36893488147419102LL; /* 2 msec */
- static timeout_t *lastfunc;
-#endif
#ifndef MAX_SOFTCLOCK_STEPS
#define MAX_SOFTCLOCK_STEPS 100 /* Maximum allowed value of steps. */
@@ -404,7 +686,7 @@ softclock(void *arg)
cc->cc_softticks++;
bucket = &cc->cc_callwheel[curticks & callwheelmask];
c = TAILQ_FIRST(bucket);
- while (c) {
+ while (c != NULL) {
depth++;
if (c->c_time != curticks) {
c = TAILQ_NEXT(c, c_links.tqe);
@@ -419,128 +701,10 @@ softclock(void *arg)
steps = 0;
}
} else {
- void (*c_func)(void *);
- void *c_arg;
- struct lock_class *class;
- struct lock_object *c_lock;
- int c_flags, sharedlock;
-
- cc->cc_next = TAILQ_NEXT(c, c_links.tqe);
TAILQ_REMOVE(bucket, c, c_links.tqe);
- class = (c->c_lock != NULL) ?
- LOCK_CLASS(c->c_lock) : NULL;
- sharedlock = (c->c_flags & CALLOUT_SHAREDLOCK) ?
- 0 : 1;
- c_lock = c->c_lock;
- c_func = c->c_func;
- c_arg = c->c_arg;
- c_flags = c->c_flags;
- if (c->c_flags & CALLOUT_LOCAL_ALLOC) {
- c->c_flags = CALLOUT_LOCAL_ALLOC;
- } else {
- c->c_flags =
- (c->c_flags & ~CALLOUT_PENDING);
- }
- cc->cc_curr = c;
- cc->cc_cancel = 0;
- CC_UNLOCK(cc);
- if (c_lock != NULL) {
- class->lc_lock(c_lock, sharedlock);
- /*
- * The callout may have been cancelled
- * while we switched locks.
- */
- if (cc->cc_cancel) {
- class->lc_unlock(c_lock);
- goto skip;
- }
- /* The callout cannot be stopped now. */
- cc->cc_cancel = 1;
-
- if (c_lock == &Giant.lock_object) {
- gcalls++;
- CTR3(KTR_CALLOUT,
- "callout %p func %p arg %p",
- c, c_func, c_arg);
- } else {
- lockcalls++;
- CTR3(KTR_CALLOUT, "callout lock"
- " %p func %p arg %p",
- c, c_func, c_arg);
- }
- } else {
- mpcalls++;
- CTR3(KTR_CALLOUT,
- "callout mpsafe %p func %p arg %p",
- c, c_func, c_arg);
- }
-#ifdef DIAGNOSTIC
- binuptime(&bt1);
-#endif
-#ifndef __rtems__
- THREAD_NO_SLEEPING();
- SDT_PROBE(callout_execute, kernel, ,
- callout_start, c, 0, 0, 0, 0);
-#endif /* __rtems__ */
- c_func(c_arg);
-#ifndef __rtems__
- SDT_PROBE(callout_execute, kernel, ,
- callout_end, c, 0, 0, 0, 0);
- THREAD_SLEEPING_OK();
-#endif /* __rtems__ */
-#ifdef DIAGNOSTIC
- binuptime(&bt2);
- bintime_sub(&bt2, &bt1);
- if (bt2.frac > maxdt) {
- if (lastfunc != c_func ||
- bt2.frac > maxdt * 2) {
- bintime2timespec(&bt2, &ts2);
- printf(
- "Expensive timeout(9) function: %p(%p) %jd.%09ld s\n",
- c_func, c_arg,
- (intmax_t)ts2.tv_sec,
- ts2.tv_nsec);
- }
- maxdt = bt2.frac;
- lastfunc = c_func;
- }
-#endif
- CTR1(KTR_CALLOUT, "callout %p finished", c);
- if ((c_flags & CALLOUT_RETURNUNLOCKED) == 0)
- class->lc_unlock(c_lock);
- skip:
- CC_LOCK(cc);
- /*
- * If the current callout is locally
- * allocated (from timeout(9))
- * then put it on the freelist.
- *
- * Note: we need to check the cached
- * copy of c_flags because if it was not
- * local, then it's not safe to deref the
- * callout pointer.
- */
- if (c_flags & CALLOUT_LOCAL_ALLOC) {
- KASSERT(c->c_flags ==
- CALLOUT_LOCAL_ALLOC,
- ("corrupted callout"));
- c->c_func = NULL;
- SLIST_INSERT_HEAD(&cc->cc_callfree, c,
- c_links.sle);
- }
- cc->cc_curr = NULL;
- if (cc->cc_waiting) {
- /*
- * There is someone waiting
- * for the callout to complete.
- */
- cc->cc_waiting = 0;
- CC_UNLOCK(cc);
- wakeup(&cc->cc_waiting);
- CC_LOCK(cc);
- }
+ c = softclock_call_cc(c, cc, &mpcalls,
+ &lockcalls, &gcalls);
steps = 0;
- c = cc->cc_next;
}
}
}
@@ -650,7 +814,6 @@ callout_reset_on(struct callout *c, int to_ticks, void (*ftn)(void *),
*/
if (c->c_flags & CALLOUT_LOCAL_ALLOC)
cpu = c->c_cpu;
-retry:
cc = callout_lock(c);
if (cc->cc_curr == c) {
/*
@@ -682,25 +845,31 @@ retry:
cancelled = 1;
c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING);
}
+
+#ifdef SMP
/*
- * If the lock must migrate we have to check the state again as
- * we can't hold both the new and old locks simultaneously.
+ * If the callout must migrate try to perform it immediately.
+ * If the callout is currently running, just defer the migration
+ * to a more appropriate moment.
*/
if (c->c_cpu != cpu) {
- c->c_cpu = cpu;
- CC_UNLOCK(cc);
- goto retry;
+ if (cc->cc_curr == c) {
+ cc->cc_migration_cpu = cpu;
+ cc->cc_migration_ticks = to_ticks;
+ cc->cc_migration_func = ftn;
+ cc->cc_migration_arg = arg;
+ c->c_flags |= CALLOUT_DFRMIGRATION;
+ CTR5(KTR_CALLOUT,
+ "migration of %p func %p arg %p in %d to %u deferred",
+ c, c->c_func, c->c_arg, to_ticks, cpu);
+ CC_UNLOCK(cc);
+ return (cancelled);
+ }
+ cc = callout_cpu_switch(c, cc, cpu);
}
+#endif
- if (to_ticks <= 0)
- to_ticks = 1;
-
- c->c_arg = arg;
- c->c_flags |= (CALLOUT_ACTIVE | CALLOUT_PENDING);
- c->c_func = ftn;
- c->c_time = cc->cc_ticks + to_ticks;
- TAILQ_INSERT_TAIL(&cc->cc_callwheel[c->c_time & callwheelmask],
- c, c_links.tqe);
+ callout_cc_add(c, cc, to_ticks, ftn, arg, cpu);
CTR5(KTR_CALLOUT, "%sscheduled %p func %p arg %p in %d",
cancelled ? "re" : "", c, c->c_func, c->c_arg, to_ticks);
CC_UNLOCK(cc);
@@ -728,13 +897,13 @@ _callout_stop_safe(c, safe)
struct callout *c;
int safe;
{
- struct callout_cpu *cc;
+ struct callout_cpu *cc, *old_cc;
struct lock_class *class;
#ifndef __rtems__
int use_lock, sq_locked;
#else /* __rtems__ */
int use_lock;
-#endif /* __rtems__ */
+#endif /* __rtems__ */
/*
* Some old subsystems don't hold Giant while running a callout_stop(),
@@ -753,9 +922,30 @@ _callout_stop_safe(c, safe)
#ifndef __rtems__
sq_locked = 0;
+ old_cc = NULL;
again:
-#endif /* __rtems__ */
+#endif /* __rtems__ */
cc = callout_lock(c);
+
+#ifndef __rtems__
+ /*
+ * If the callout was migrating while the callout cpu lock was
+ * dropped, just drop the sleepqueue lock and check the states
+ * again.
+ */
+ if (sq_locked != 0 && cc != old_cc) {
+#ifdef SMP
+ CC_UNLOCK(cc);
+ sleepq_release(&old_cc->cc_waiting);
+ sq_locked = 0;
+ old_cc = NULL;
+ goto again;
+#else
+ panic("migration should not happen");
+#endif
+ }
+#endif /* __rtems__ */
+
/*
* If the callout isn't pending, it's not on the queue, so
* don't attempt to remove it from the queue. We can try to
@@ -775,7 +965,7 @@ again:
#ifndef __rtems__
if (sq_locked)
sleepq_release(&cc->cc_waiting);
-#endif /* __rtems__ */
+#endif /* __rtems__ */
return (0);
}
@@ -810,8 +1000,16 @@ again:
CC_UNLOCK(cc);
sleepq_lock(&cc->cc_waiting);
sq_locked = 1;
+ old_cc = cc;
goto again;
}
+
+ /*
+ * Migration could be cancelled here, but
+ * as long as it is still not sure when it
+ * will be packed up, just let softclock()
+ * take care of it.
+ */
cc->cc_waiting = 1;
DROP_GIANT();
CC_UNLOCK(cc);
@@ -820,6 +1018,7 @@ again:
SLEEPQ_SLEEP, 0);
sleepq_wait(&cc->cc_waiting, 0);
sq_locked = 0;
+ old_cc = NULL;
/* Reacquire locks previously released. */
PICKUP_GIANT();
@@ -847,9 +1046,17 @@ again:
cc->cc_cancel = 1;
CTR3(KTR_CALLOUT, "cancelled %p func %p arg %p",
c, c->c_func, c->c_arg);
+ KASSERT(!cc_cme_migrating(cc),
+ ("callout wrongly scheduled for migration"));
CC_UNLOCK(cc);
KASSERT(!sq_locked, ("sleepqueue chain locked"));
return (1);
+ } else if ((c->c_flags & CALLOUT_DFRMIGRATION) != 0) {
+ c->c_flags &= ~CALLOUT_DFRMIGRATION;
+ CTR3(KTR_CALLOUT, "postponing stop %p func %p arg %p",
+ c, c->c_func, c->c_arg);
+ CC_UNLOCK(cc);
+ return (1);
}
CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p",
c, c->c_func, c->c_arg);
@@ -860,23 +1067,16 @@ again:
#ifndef __rtems__
if (sq_locked)
sleepq_release(&cc->cc_waiting);
-#endif /* __rtems__ */
+#endif /* __rtems__ */
c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING);
- if (cc->cc_next == c) {
- cc->cc_next = TAILQ_NEXT(c, c_links.tqe);
- }
- TAILQ_REMOVE(&cc->cc_callwheel[c->c_time & callwheelmask], c,
- c_links.tqe);
-
CTR3(KTR_CALLOUT, "cancelled %p func %p arg %p",
c, c->c_func, c->c_arg);
+ TAILQ_REMOVE(&cc->cc_callwheel[c->c_time & callwheelmask], c,
+ c_links.tqe);
+ callout_cc_del(c, cc);
- if (c->c_flags & CALLOUT_LOCAL_ALLOC) {
- c->c_func = NULL;
- SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle);
- }
CC_UNLOCK(cc);
return (1);
}
diff --git a/freebsd/sys/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c
index 51717b49..78a803e0 100644
--- a/freebsd/sys/kern/subr_bus.c
+++ b/freebsd/sys/kern/subr_bus.c
@@ -430,8 +430,8 @@ static void
devinit(void)
{
#ifndef __rtems__
- devctl_dev = make_dev(&dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
- "devctl");
+ devctl_dev = make_dev_credf(MAKEDEV_ETERNAL, &dev_cdevsw, 0, NULL,
+ UID_ROOT, GID_WHEEL, 0600, "devctl");
mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
cv_init(&devsoftc.cv, "dev cv");
TAILQ_INIT(&devsoftc.devq);
@@ -1058,10 +1058,12 @@ devclass_find(const char *classname)
* is called by devclass_add_driver to accomplish the recursive
* notification of all the children classes of dc, as well as dc.
* Each layer will have BUS_DRIVER_ADDED() called for all instances of
- * the devclass. We do a full search here of the devclass list at
- * each iteration level to save storing children-lists in the devclass
- * structure. If we ever move beyond a few dozen devices doing this,
- * we may need to reevaluate...
+ * the devclass.
+ *
+ * We do a full search here of the devclass list at each iteration
+ * level to save storing children-lists in the devclass structure. If
+ * we ever move beyond a few dozen devices doing this, we may need to
+ * reevaluate...
*
* @param dc the devclass to edit
* @param driver the driver that was just added
@@ -1156,6 +1158,77 @@ devclass_add_driver(devclass_t dc, driver_t *driver, int pass, devclass_t *dcp)
}
/**
+ * @brief Register that a device driver has been deleted from a devclass
+ *
+ * Register that a device driver has been removed from a devclass.
+ * This is called by devclass_delete_driver to accomplish the
+ * recursive notification of all the children classes of busclass, as
+ * well as busclass. Each layer will attempt to detach the driver
+ * from any devices that are children of the bus's devclass. The function
+ * will return an error if a device fails to detach.
+ *
+ * We do a full search here of the devclass list at each iteration
+ * level to save storing children-lists in the devclass structure. If
+ * we ever move beyond a few dozen devices doing this, we may need to
+ * reevaluate...
+ *
+ * @param busclass the devclass of the parent bus
+ * @param dc the devclass of the driver being deleted
+ * @param driver the driver being deleted
+ */
+static int
+devclass_driver_deleted(devclass_t busclass, devclass_t dc, driver_t *driver)
+{
+ devclass_t parent;
+ device_t dev;
+ int error, i;
+
+ /*
+ * Disassociate from any devices. We iterate through all the
+ * devices in the devclass of the driver and detach any which are
+ * using the driver and which have a parent in the devclass which
+ * we are deleting from.
+ *
+ * Note that since a driver can be in multiple devclasses, we
+ * should not detach devices which are not children of devices in
+ * the affected devclass.
+ */
+ for (i = 0; i < dc->maxunit; i++) {
+ if (dc->devices[i]) {
+ dev = dc->devices[i];
+ if (dev->driver == driver && dev->parent &&
+ dev->parent->devclass == busclass) {
+ if ((error = device_detach(dev)) != 0)
+ return (error);
+ BUS_PROBE_NOMATCH(dev->parent, dev);
+ devnomatch(dev);
+ dev->flags |= DF_DONENOMATCH;
+ }
+ }
+ }
+
+ /*
+ * Walk through the children classes. Since we only keep a
+ * single parent pointer around, we walk the entire list of
+ * devclasses looking for children. We set the
+ * DC_HAS_CHILDREN flag when a child devclass is created on
+ * the parent, so we only walk the list for those devclasses
+ * that have children.
+ */
+ if (!(busclass->flags & DC_HAS_CHILDREN))
+ return (0);
+ parent = busclass;
+ TAILQ_FOREACH(busclass, &devclasses, link) {
+ if (busclass->parent == parent) {
+ error = devclass_driver_deleted(busclass, dc, driver);
+ if (error)
+ return (error);
+ }
+ }
+ return (0);
+}
+
+/**
* @brief Delete a device driver from a device class
*
* Delete a device driver from a devclass. This is normally called
@@ -1174,8 +1247,6 @@ devclass_delete_driver(devclass_t busclass, driver_t *driver)
{
devclass_t dc = devclass_find(driver->name);
driverlink_t dl;
- device_t dev;
- int i;
int error;
PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
@@ -1197,27 +1268,9 @@ devclass_delete_driver(devclass_t busclass, driver_t *driver)
return (ENOENT);
}
- /*
- * Disassociate from any devices. We iterate through all the
- * devices in the devclass of the driver and detach any which are
- * using the driver and which have a parent in the devclass which
- * we are deleting from.
- *
- * Note that since a driver can be in multiple devclasses, we
- * should not detach devices which are not children of devices in
- * the affected devclass.
- */
- for (i = 0; i < dc->maxunit; i++) {
- if (dc->devices[i]) {
- dev = dc->devices[i];
- if (dev->driver == driver && dev->parent &&
- dev->parent->devclass == busclass) {
- if ((error = device_detach(dev)) != 0)
- return (error);
- device_set_driver(dev, NULL);
- }
- }
- }
+ error = devclass_driver_deleted(busclass, dc, driver);
+ if (error != 0)
+ return (error);
TAILQ_REMOVE(&busclass->drivers, dl, link);
free(dl, M_BUS);
@@ -1889,7 +1942,7 @@ device_delete_child(device_t dev, device_t child)
PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
/* remove children first */
- while ( (grandchild = TAILQ_FIRST(&child->children)) ) {
+ while ((grandchild = TAILQ_FIRST(&child->children)) != NULL) {
error = device_delete_child(child, grandchild);
if (error)
return (error);
@@ -1908,6 +1961,39 @@ device_delete_child(device_t dev, device_t child)
}
/**
+ * @brief Delete all children devices of the given device, if any.
+ *
+ * This function deletes all children devices of the given device, if
+ * any, using the device_delete_child() function for each device it
+ * finds. If a child device cannot be deleted, this function will
+ * return an error code.
+ *
+ * @param dev the parent device
+ *
+ * @retval 0 success
+ * @retval non-zero a device would not detach
+ */
+int
+device_delete_children(device_t dev)
+{
+ device_t child;
+ int error;
+
+ PDEBUG(("Deleting all children of %s", DEVICENAME(dev)));
+
+ error = 0;
+
+ while ((child = TAILQ_FIRST(&dev->children)) != NULL) {
+ error = device_delete_child(dev, child);
+ if (error) {
+ PDEBUG(("Failed deleting %s", DEVICENAME(child)));
+ break;
+ }
+ }
+ return (error);
+}
+
+/**
* @brief Find a device given a unit number
*
* This is similar to devclass_get_devices() but only searches for
@@ -2001,19 +2087,23 @@ device_probe_child(device_t dev, device_t child)
for (dl = first_matching_driver(dc, child);
dl;
dl = next_matching_driver(dc, child, dl)) {
-
/* If this driver's pass is too high, then ignore it. */
if (dl->pass > bus_current_pass)
continue;
PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
- device_set_driver(child, dl->driver);
+ result = device_set_driver(child, dl->driver);
+ if (result == ENOMEM)
+ return (result);
+ else if (result != 0)
+ continue;
if (!hasclass) {
- if (device_set_devclass(child, dl->driver->name)) {
- printf("driver bug: Unable to set devclass (devname: %s)\n",
- (child ? device_get_name(child) :
- "no device"));
- device_set_driver(child, NULL);
+ if (device_set_devclass(child,
+ dl->driver->name) != 0) {
+ printf("driver bug: Unable to set "
+ "devclass (devname: %s)\n",
+ device_get_name(child));
+ (void)device_set_driver(child, NULL);
continue;
}
}
@@ -2029,7 +2119,7 @@ device_probe_child(device_t dev, device_t child)
/* Reset flags and devclass before the next probe. */
child->devflags = 0;
if (!hasclass)
- device_set_devclass(child, NULL);
+ (void)device_set_devclass(child, NULL);
/*
* If the driver returns SUCCESS, there can be
@@ -2046,7 +2136,7 @@ device_probe_child(device_t dev, device_t child)
* certainly doesn't match.
*/
if (result > 0) {
- device_set_driver(child, NULL);
+ (void)device_set_driver(child, NULL);
continue;
}
@@ -2083,7 +2173,7 @@ device_probe_child(device_t dev, device_t child)
/* XXX What happens if we rebid and got no best? */
if (best) {
/*
- * If this device was atached, and we were asked to
+ * If this device was attached, and we were asked to
* rescan, and it is a different driver, then we have
* to detach the old driver and reattach this new one.
* Note, we don't have to check for DF_REBID here
@@ -2109,7 +2199,9 @@ device_probe_child(device_t dev, device_t child)
if (result != 0)
return (result);
}
- device_set_driver(child, best->driver);
+ result = device_set_driver(child, best->driver);
+ if (result != 0)
+ return (result);
#ifndef __rtems__
resource_int_value(best->driver->name, child->unit,
"flags", &child->devflags);
@@ -2171,6 +2263,11 @@ device_get_children(device_t dev, device_t **devlistp, int *devcountp)
TAILQ_FOREACH(child, &dev->children, link) {
count++;
}
+ if (count == 0) {
+ *devlistp = NULL;
+ *devcountp = 0;
+ return (0);
+ }
#ifdef __rtems__
/* malloc(0) may return NULL */
@@ -2471,12 +2568,13 @@ device_disable(device_t dev)
void
device_busy(device_t dev)
{
- if (dev->state < DS_ATTACHED)
+ if (dev->state < DS_ATTACHING)
panic("device_busy: called for unattached device");
if (dev->busy == 0 && dev->parent)
device_busy(dev->parent);
dev->busy++;
- dev->state = DS_BUSY;
+ if (dev->state == DS_ATTACHED)
+ dev->state = DS_BUSY;
}
/**
@@ -2485,14 +2583,16 @@ device_busy(device_t dev)
void
device_unbusy(device_t dev)
{
- if (dev->state != DS_BUSY)
+ if (dev->busy != 0 && dev->state != DS_BUSY &&
+ dev->state != DS_ATTACHING)
panic("device_unbusy: called for non-busy device %s",
device_get_nameunit(dev));
dev->busy--;
if (dev->busy == 0) {
if (dev->parent)
device_unbusy(dev->parent);
- dev->state = DS_ATTACHED;
+ if (dev->state == DS_BUSY)
+ dev->state = DS_ATTACHED;
}
}
@@ -2602,6 +2702,7 @@ device_set_driver(device_t dev, driver_t *driver)
free(dev->softc, M_BUS_SC);
dev->softc = NULL;
}
+ device_set_desc(dev, NULL);
kobj_delete((kobj_t) dev, NULL);
dev->driver = driver;
if (driver) {
@@ -2724,22 +2825,36 @@ device_attach(device_t dev)
{
int error;
+#ifndef __rtems__
+ if (resource_disabled(dev->driver->name, dev->unit)) {
+ device_disable(dev);
+ if (bootverbose)
+ device_printf(dev, "disabled via hints entry\n");
+ return (ENXIO);
+ }
+#endif /* __rtems__ */
+
device_sysctl_init(dev);
if (!device_is_quiet(dev))
device_print_child(dev->parent, dev);
+ dev->state = DS_ATTACHING;
if ((error = DEVICE_ATTACH(dev)) != 0) {
printf("device_attach: %s%d attach returned %d\n",
dev->driver->name, dev->unit, error);
- /* Unset the class; set in device_probe_child */
- if (dev->devclass == NULL)
- device_set_devclass(dev, NULL);
- device_set_driver(dev, NULL);
+ if (!(dev->flags & DF_FIXEDCLASS))
+ devclass_delete_device(dev->devclass, dev);
+ (void)device_set_driver(dev, NULL);
device_sysctl_fini(dev);
+ KASSERT(dev->busy == 0, ("attach failed but busy"));
dev->state = DS_NOTPRESENT;
return (error);
}
device_sysctl_update(dev);
- dev->state = DS_ATTACHED;
+ if (dev->busy)
+ dev->state = DS_BUSY;
+ else
+ dev->state = DS_ATTACHED;
+ dev->flags &= ~DF_DONENOMATCH;
devadded(dev);
return (0);
}
@@ -2785,8 +2900,7 @@ device_detach(device_t dev)
devclass_delete_device(dev->devclass, dev);
dev->state = DS_NOTPRESENT;
- device_set_driver(dev, NULL);
- device_set_desc(dev, NULL);
+ (void)device_set_driver(dev, NULL);
device_sysctl_fini(dev);
return (0);
@@ -3517,6 +3631,23 @@ bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
}
/**
+ * @brief Helper function for implementing BUS_ADJUST_RESOURCE().
+ *
+ * This simple implementation of BUS_ADJUST_RESOURCE() simply calls the
+ * BUS_ADJUST_RESOURCE() method of the parent of @p dev.
+ */
+int
+bus_generic_adjust_resource(device_t dev, device_t child, int type,
+ struct resource *r, u_long start, u_long end)
+{
+ /* Propagate up the bus hierarchy until someone handles it. */
+ if (dev->parent)
+ return (BUS_ADJUST_RESOURCE(dev->parent, child, type, r, start,
+ end));
+ return (EINVAL);
+}
+
+/**
* @brief Helper function for implementing BUS_ALLOC_RESOURCE().
*
* This simple implementation of BUS_ALLOC_RESOURCE() simply calls the
@@ -3839,6 +3970,21 @@ bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end,
}
/**
+ * @brief Wrapper function for BUS_ADJUST_RESOURCE().
+ *
+ * This function simply calls the BUS_ADJUST_RESOURCE() method of the
+ * parent of @p dev.
+ */
+int
+bus_adjust_resource(device_t dev, int type, struct resource *r, u_long start,
+ u_long end)
+{
+ if (dev->parent == NULL)
+ return (EINVAL);
+ return (BUS_ADJUST_RESOURCE(dev->parent, dev, type, r, start, end));
+}
+
+/**
* @brief Wrapper function for BUS_ACTIVATE_RESOURCE().
*
* This function simply calls the BUS_ACTIVATE_RESOURCE() method of the
@@ -4417,7 +4563,6 @@ print_driver(driver_t *driver, int indent)
print_driver_short(driver, indent);
}
-
static void
print_driver_list(driver_list_t drivers, int indent)
{
diff --git a/freebsd/sys/kern/subr_kobj.c b/freebsd/sys/kern/subr_kobj.c
index e12a1f36..8d182173 100644
--- a/freebsd/sys/kern/subr_kobj.c
+++ b/freebsd/sys/kern/subr_kobj.c
@@ -62,18 +62,9 @@ static struct mtx kobj_mtx;
static int kobj_mutex_inited;
static int kobj_next_id = 1;
-/*
- * In the event that kobj_mtx has not been initialized yet,
- * we will ignore it, and run without locks in order to support
- * use of KOBJ before mutexes are available. This early in the boot
- * process, everything is single threaded and so races should not
- * happen. This is used to provide the PMAP layer on PowerPC, as well
- * as board support.
- */
-
-#define KOBJ_LOCK() if (kobj_mutex_inited) mtx_lock(&kobj_mtx);
-#define KOBJ_UNLOCK() if (kobj_mutex_inited) mtx_unlock(&kobj_mtx);
-#define KOBJ_ASSERT(what) if (kobj_mutex_inited) mtx_assert(&kobj_mtx,what);
+#define KOBJ_LOCK() mtx_lock(&kobj_mtx)
+#define KOBJ_UNLOCK() mtx_unlock(&kobj_mtx)
+#define KOBJ_ASSERT(what) mtx_assert(&kobj_mtx, what);
SYSCTL_UINT(_kern, OID_AUTO, kobj_methodcount, CTLFLAG_RD,
&kobj_next_id, 0, "");
@@ -106,28 +97,11 @@ kobj_error_method(void)
}
static void
-kobj_register_method(struct kobjop_desc *desc)
-{
- KOBJ_ASSERT(MA_OWNED);
-
- if (desc->id == 0) {
- desc->id = kobj_next_id++;
- }
-}
-
-static void
-kobj_unregister_method(struct kobjop_desc *desc)
-{
-}
-
-static void
kobj_class_compile_common(kobj_class_t cls, kobj_ops_t ops)
{
kobj_method_t *m;
int i;
- KOBJ_ASSERT(MA_OWNED);
-
/*
* Don't do anything if we are already compiled.
*/
@@ -137,8 +111,10 @@ kobj_class_compile_common(kobj_class_t cls, kobj_ops_t ops)
/*
* First register any methods which need it.
*/
- for (i = 0, m = cls->methods; m->desc; i++, m++)
- kobj_register_method(m->desc);
+ for (i = 0, m = cls->methods; m->desc; i++, m++) {
+ if (m->desc->id == 0)
+ m->desc->id = kobj_next_id++;
+ }
/*
* Then initialise the ops table.
@@ -161,7 +137,7 @@ kobj_class_compile(kobj_class_t cls)
*/
ops = malloc(sizeof(struct kobj_ops), M_KOBJ, M_NOWAIT);
if (!ops)
- panic("kobj_compile_methods: out of memory");
+ panic("%s: out of memory", __func__);
KOBJ_LOCK();
@@ -184,17 +160,14 @@ void
kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops)
{
- KOBJ_ASSERT(MA_NOTOWNED);
+ KASSERT(kobj_mutex_inited == 0,
+ ("%s: only supported during early cycles", __func__));
/*
* Increment refs to make sure that the ops table is not freed.
*/
- KOBJ_LOCK();
-
cls->refs++;
kobj_class_compile_common(cls, ops);
-
- KOBJ_UNLOCK();
}
static kobj_method_t*
@@ -261,8 +234,6 @@ kobj_lookup_method(kobj_class_t cls,
void
kobj_class_free(kobj_class_t cls)
{
- int i;
- kobj_method_t *m;
void* ops = NULL;
KOBJ_ASSERT(MA_NOTOWNED);
@@ -274,10 +245,9 @@ kobj_class_free(kobj_class_t cls)
*/
if (cls->refs == 0) {
/*
- * Unregister any methods which are no longer used.
+ * For now we don't do anything to unregister any methods
+ * which are no longer used.
*/
- for (i = 0, m = cls->methods; m->desc; i++, m++)
- kobj_unregister_method(m->desc);
/*
* Free memory and clean up.
@@ -310,6 +280,14 @@ kobj_create(kobj_class_t cls,
return obj;
}
+static void
+kobj_init_common(kobj_t obj, kobj_class_t cls)
+{
+
+ obj->ops = cls->ops;
+ cls->refs++;
+}
+
void
kobj_init(kobj_t obj, kobj_class_t cls)
{
@@ -331,13 +309,22 @@ kobj_init(kobj_t obj, kobj_class_t cls)
goto retry;
}
- obj->ops = cls->ops;
- cls->refs++;
+ kobj_init_common(obj, cls);
KOBJ_UNLOCK();
}
void
+kobj_init_static(kobj_t obj, kobj_class_t cls)
+{
+
+ KASSERT(kobj_mutex_inited == 0,
+ ("%s: only supported during early cycles", __func__));
+
+ kobj_init_common(obj, cls);
+}
+
+void
kobj_delete(kobj_t obj, struct malloc_type *mtype)
{
kobj_class_t cls = obj->ops->cls;
diff --git a/freebsd/sys/kern/subr_rman.c b/freebsd/sys/kern/subr_rman.c
index c3c87e44..a1982daf 100644
--- a/freebsd/sys/kern/subr_rman.c
+++ b/freebsd/sys/kern/subr_rman.c
@@ -140,6 +140,8 @@ rman_init(struct rman *rm)
mtx_init(&rman_mtx, "rman head", NULL, MTX_DEF);
}
+ if (rm->rm_start == 0 && rm->rm_end == 0)
+ rm->rm_end = ~0ul;
if (rm->rm_type == RMAN_UNINIT)
panic("rman_init");
if (rm->rm_type == RMAN_GAUGE)
@@ -164,6 +166,8 @@ rman_manage_region(struct rman *rm, u_long start, u_long end)
DPRINTF(("rman_manage_region: <%s> request: start %#lx, end %#lx\n",
rm->rm_descr, start, end));
+ if (start < rm->rm_start || end > rm->rm_end)
+ return EINVAL;
r = int_alloc_resource(M_NOWAIT);
if (r == NULL)
return ENOMEM;
@@ -270,6 +274,164 @@ rman_fini(struct rman *rm)
return 0;
}
+int
+rman_first_free_region(struct rman *rm, u_long *start, u_long *end)
+{
+ struct resource_i *r;
+
+ mtx_lock(rm->rm_mtx);
+ TAILQ_FOREACH(r, &rm->rm_list, r_link) {
+ if (!(r->r_flags & RF_ALLOCATED)) {
+ *start = r->r_start;
+ *end = r->r_end;
+ mtx_unlock(rm->rm_mtx);
+ return (0);
+ }
+ }
+ mtx_unlock(rm->rm_mtx);
+ return (ENOENT);
+}
+
+int
+rman_last_free_region(struct rman *rm, u_long *start, u_long *end)
+{
+ struct resource_i *r;
+
+ mtx_lock(rm->rm_mtx);
+ TAILQ_FOREACH_REVERSE(r, &rm->rm_list, resource_head, r_link) {
+ if (!(r->r_flags & RF_ALLOCATED)) {
+ *start = r->r_start;
+ *end = r->r_end;
+ mtx_unlock(rm->rm_mtx);
+ return (0);
+ }
+ }
+ mtx_unlock(rm->rm_mtx);
+ return (ENOENT);
+}
+
+/* Shrink or extend one or both ends of an allocated resource. */
+int
+rman_adjust_resource(struct resource *rr, u_long start, u_long end)
+{
+ struct resource_i *r, *s, *t, *new;
+ struct rman *rm;
+
+ /* Not supported for shared resources. */
+ r = rr->__r_i;
+ if (r->r_flags & (RF_TIMESHARE | RF_SHAREABLE))
+ return (EINVAL);
+
+ /*
+ * This does not support wholesale moving of a resource. At
+ * least part of the desired new range must overlap with the
+ * existing resource.
+ */
+ if (end < r->r_start || r->r_end < start)
+ return (EINVAL);
+
+ /*
+ * Find the two resource regions immediately adjacent to the
+ * allocated resource.
+ */
+ rm = r->r_rm;
+ mtx_lock(rm->rm_mtx);
+#ifdef INVARIANTS
+ TAILQ_FOREACH(s, &rm->rm_list, r_link) {
+ if (s == r)
+ break;
+ }
+ if (s == NULL)
+ panic("resource not in list");
+#endif
+ s = TAILQ_PREV(r, resource_head, r_link);
+ t = TAILQ_NEXT(r, r_link);
+ KASSERT(s == NULL || s->r_end + 1 == r->r_start,
+ ("prev resource mismatch"));
+ KASSERT(t == NULL || r->r_end + 1 == t->r_start,
+ ("next resource mismatch"));
+
+ /*
+ * See if the changes are permitted. Shrinking is always allowed,
+ * but growing requires sufficient room in the adjacent region.
+ */
+ if (start < r->r_start && (s == NULL || (s->r_flags & RF_ALLOCATED) ||
+ s->r_start > start)) {
+ mtx_unlock(rm->rm_mtx);
+ return (EBUSY);
+ }
+ if (end > r->r_end && (t == NULL || (t->r_flags & RF_ALLOCATED) ||
+ t->r_end < end)) {
+ mtx_unlock(rm->rm_mtx);
+ return (EBUSY);
+ }
+
+ /*
+ * While holding the lock, grow either end of the resource as
+ * needed and shrink either end if the shrinking does not require
+ * allocating a new resource. We can safely drop the lock and then
+ * insert a new range to handle the shrinking case afterwards.
+ */
+ if (start < r->r_start ||
+ (start > r->r_start && s != NULL && !(s->r_flags & RF_ALLOCATED))) {
+ KASSERT(s->r_flags == 0, ("prev is busy"));
+ r->r_start = start;
+ if (s->r_start == start) {
+ TAILQ_REMOVE(&rm->rm_list, s, r_link);
+ free(s, M_RMAN);
+ } else
+ s->r_end = start - 1;
+ }
+ if (end > r->r_end ||
+ (end < r->r_end && t != NULL && !(t->r_flags & RF_ALLOCATED))) {
+ KASSERT(t->r_flags == 0, ("next is busy"));
+ r->r_end = end;
+ if (t->r_end == end) {
+ TAILQ_REMOVE(&rm->rm_list, t, r_link);
+ free(t, M_RMAN);
+ } else
+ t->r_start = end + 1;
+ }
+ mtx_unlock(rm->rm_mtx);
+
+ /*
+ * Handle the shrinking cases that require allocating a new
+ * resource to hold the newly-free region. We have to recheck
+ * if we still need this new region after acquiring the lock.
+ */
+ if (start > r->r_start) {
+ new = int_alloc_resource(M_WAITOK);
+ new->r_start = r->r_start;
+ new->r_end = start - 1;
+ new->r_rm = rm;
+ mtx_lock(rm->rm_mtx);
+ r->r_start = start;
+ s = TAILQ_PREV(r, resource_head, r_link);
+ if (s != NULL && !(s->r_flags & RF_ALLOCATED)) {
+ s->r_end = start - 1;
+ free(new, M_RMAN);
+ } else
+ TAILQ_INSERT_BEFORE(r, new, r_link);
+ mtx_unlock(rm->rm_mtx);
+ }
+ if (end < r->r_end) {
+ new = int_alloc_resource(M_WAITOK);
+ new->r_start = end + 1;
+ new->r_end = r->r_end;
+ new->r_rm = rm;
+ mtx_lock(rm->rm_mtx);
+ r->r_end = end;
+ t = TAILQ_NEXT(r, r_link);
+ if (t != NULL && !(t->r_flags & RF_ALLOCATED)) {
+ t->r_start = end + 1;
+ free(new, M_RMAN);
+ } else
+ TAILQ_INSERT_AFTER(&rm->rm_list, r, new, r_link);
+ mtx_unlock(rm->rm_mtx);
+ }
+ return (0);
+}
+
struct resource *
rman_reserve_resource_bound(struct rman *rm, u_long start, u_long end,
u_long count, u_long bound, u_int flags,
@@ -679,6 +841,7 @@ int_rman_release_resource(struct rman *rm, struct resource_i *r)
* without freeing anything.
*/
r->r_flags &= ~RF_ALLOCATED;
+ r->r_dev = NULL;
return 0;
}
diff --git a/freebsd/sys/kern/subr_sbuf.c b/freebsd/sys/kern/subr_sbuf.c
index 165d17a3..c57392d6 100644
--- a/freebsd/sys/kern/subr_sbuf.c
+++ b/freebsd/sys/kern/subr_sbuf.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <sys/ctype.h>
+#include <rtems/bsd/sys/errno.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/systm.h>
@@ -42,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <machine/stdarg.h>
#else /* _KERNEL */
#include <ctype.h>
+#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -50,6 +52,12 @@ __FBSDID("$FreeBSD$");
#include <sys/sbuf.h>
+struct sbuf_drain {
+ sbuf_drain_func *s_func; /* drain function */
+ void *s_arg; /* user-supplied drain argument */
+ int s_error; /* current error code */
+};
+
#ifdef _KERNEL
static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
#define SBMALLOC(size) malloc(size, M_SBUF, M_WAITOK)
@@ -58,7 +66,6 @@ static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
#define KASSERT(e, m)
#define SBMALLOC(size) malloc(size)
#define SBFREE(buf) free(buf)
-#define min(x,y) MIN(x,y)
#endif /* _KERNEL */
/*
@@ -118,18 +125,24 @@ _assert_sbuf_state(const char *fun, struct sbuf *s, int state)
#endif /* _KERNEL && INVARIANTS */
+#ifdef CTASSERT
+CTASSERT(powerof2(SBUF_MAXEXTENDSIZE));
+CTASSERT(powerof2(SBUF_MAXEXTENDINCR));
+#endif
+
static int
sbuf_extendsize(int size)
{
int newsize;
- newsize = SBUF_MINEXTENDSIZE;
- while (newsize < size) {
- if (newsize < (int)SBUF_MAXEXTENDSIZE)
+ if (size < (int)SBUF_MAXEXTENDSIZE) {
+ newsize = SBUF_MINEXTENDSIZE;
+ while (newsize < size)
newsize *= 2;
- else
- newsize += SBUF_MAXEXTENDINCR;
+ } else {
+ newsize = roundup2(size, SBUF_MAXEXTENDINCR);
}
+ KASSERT(newsize >= size, ("%s: %d < %d\n", __func__, newsize, size));
return (newsize);
}
@@ -186,11 +199,11 @@ sbuf_new(struct sbuf *s, char *buf, int length, int flags)
s->s_flags = flags;
}
s->s_size = length;
- if (buf) {
+ if (buf != NULL) {
s->s_buf = buf;
return (s);
}
- if (flags & SBUF_AUTOEXTEND)
+ if ((flags & SBUF_AUTOEXTEND) != 0)
s->s_size = sbuf_extendsize(s->s_size);
s->s_buf = SBMALLOC(s->s_size);
if (s->s_buf == NULL) {
@@ -243,6 +256,8 @@ sbuf_clear(struct sbuf *s)
SBUF_CLEARFLAG(s, SBUF_FINISHED);
SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
+ if (s->s_drain != NULL)
+ s->s_drain->s_error = 0;
s->s_len = 0;
}
@@ -269,27 +284,125 @@ sbuf_setpos(struct sbuf *s, int pos)
}
/*
+ * Set up a drain function and argument on an sbuf to flush data to
+ * when the sbuf buffer overflows.
+ */
+void
+sbuf_set_drain(struct sbuf *s, sbuf_drain_func *func, void *ctx)
+{
+
+ assert_sbuf_state(s, 0);
+ assert_sbuf_integrity(s);
+ KASSERT((s->s_drain != NULL && func == s->s_drain->s_func) ||
+ s->s_len == 0,
+ ("Cannot change drain to %p on non-empty sbuf %p", func, s));
+ if (func == NULL) {
+ SBFREE(s->s_drain);
+ s->s_drain = NULL;
+ return;
+ }
+ if (s->s_drain == NULL) {
+ s->s_drain = SBMALLOC(sizeof(*s->s_drain));
+ if (s->s_drain == NULL)
+ return;
+ }
+ s->s_drain->s_func = func;
+ s->s_drain->s_arg = ctx;
+ s->s_drain->s_error = 0;
+}
+
+/*
+ * Call the drain and process the return.
+ */
+static int
+sbuf_drain(struct sbuf *s)
+{
+ int len;
+
+ KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
+ len = s->s_drain->s_func(s->s_drain->s_arg, s->s_buf, s->s_len);
+ if (len < 0) {
+ s->s_drain->s_error = -len;
+ SBUF_SETFLAG(s, SBUF_OVERFLOWED);
+ return (s->s_drain->s_error);
+ }
+ KASSERT(len > 0 && len <= s->s_len,
+ ("Bad drain amount %d for sbuf %p", len, s));
+ s->s_len -= len;
+ /*
+ * Fast path for the expected case where all the data was
+ * drained.
+ */
+ if (s->s_len == 0)
+ return (0);
+ /*
+ * Move the remaining characters to the beginning of the
+ * string.
+ */
+ memmove(s->s_buf, s->s_buf + len, s->s_len);
+ return (0);
+}
+
+/*
+ * Append a byte to an sbuf. This is the core function for appending
+ * to an sbuf and is the main place that deals with extending the
+ * buffer and marking overflow.
+ */
+static void
+sbuf_put_byte(int c, struct sbuf *s)
+{
+
+ assert_sbuf_integrity(s);
+ assert_sbuf_state(s, 0);
+
+ if (SBUF_HASOVERFLOWED(s))
+ return;
+ if (SBUF_FREESPACE(s) <= 0) {
+ /*
+ * If there is a drain, use it, otherwise extend the
+ * buffer.
+ */
+ if (s->s_drain != NULL)
+ (void)sbuf_drain(s);
+ else if (sbuf_extend(s, 1) < 0)
+ SBUF_SETFLAG(s, SBUF_OVERFLOWED);
+ if (SBUF_HASOVERFLOWED(s))
+ return;
+ }
+ s->s_buf[s->s_len++] = c;
+}
+
+/*
+ * Append a non-NUL character to an sbuf. This prototype signature is
+ * suitable for use with kvprintf(9).
+ */
+static void
+sbuf_putc_func(int c, void *arg)
+{
+
+ if (c != '\0')
+ sbuf_put_byte(c, arg);
+}
+
+/*
* Append a byte string to an sbuf.
*/
int
sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
{
const char *str = buf;
+ const char *end = str + len;
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
if (SBUF_HASOVERFLOWED(s))
return (-1);
- for (; len; len--) {
- if (!SBUF_HASROOM(s) && sbuf_extend(s, len) < 0)
- break;
- s->s_buf[s->s_len++] = *str++;
- }
- if (len) {
- SBUF_SETFLAG(s, SBUF_OVERFLOWED);
- return (-1);
- }
+ for (; str < end; str++) {
+ sbuf_put_byte(*str, s);
+ if (SBUF_HASOVERFLOWED(s))
+ return (-1);
+ }
return (0);
}
@@ -303,6 +416,8 @@ sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
+ KASSERT(s->s_drain == NULL,
+ ("Nonsensical copyin to sbuf %p with a drain", s));
if (SBUF_HASOVERFLOWED(s))
return (-1);
@@ -310,7 +425,8 @@ sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
return (0);
if (len > SBUF_FREESPACE(s)) {
sbuf_extend(s, len - SBUF_FREESPACE(s));
- len = min(len, SBUF_FREESPACE(s));
+ if (SBUF_FREESPACE(s) < len)
+ len = SBUF_FREESPACE(s);
}
if (copyin(uaddr, s->s_buf + s->s_len, len) != 0)
return (-1);
@@ -347,14 +463,10 @@ sbuf_cat(struct sbuf *s, const char *str)
if (SBUF_HASOVERFLOWED(s))
return (-1);
- while (*str) {
- if (!SBUF_HASROOM(s) && sbuf_extend(s, strlen(str)) < 0)
- break;
- s->s_buf[s->s_len++] = *str++;
- }
- if (*str) {
- SBUF_SETFLAG(s, SBUF_OVERFLOWED);
- return (-1);
+ while (*str != '\0') {
+ sbuf_put_byte(*str++, s);
+ if (SBUF_HASOVERFLOWED(s))
+ return (-1);
}
return (0);
}
@@ -370,6 +482,8 @@ sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
+ KASSERT(s->s_drain == NULL,
+ ("Nonsensical copyin to sbuf %p with a drain", s));
if (SBUF_HASOVERFLOWED(s))
return (-1);
@@ -378,7 +492,8 @@ sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
len = SBUF_FREESPACE(s); /* XXX return 0? */
if (len > SBUF_FREESPACE(s)) {
sbuf_extend(s, len);
- len = min(len, SBUF_FREESPACE(s));
+ if (SBUF_FREESPACE(s) < len)
+ len = SBUF_FREESPACE(s);
}
switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) {
case ENAMETOOLONG:
@@ -412,11 +527,28 @@ sbuf_cpy(struct sbuf *s, const char *str)
/*
* Format the given argument list and append the resulting string to an sbuf.
*/
+#if defined(_KERNEL) && !defined(__rtems__)
+int
+sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
+{
+
+ assert_sbuf_integrity(s);
+ assert_sbuf_state(s, 0);
+
+ KASSERT(fmt != NULL,
+ ("%s called with a NULL format string", __func__));
+
+ (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap);
+ if (SBUF_HASOVERFLOWED(s))
+ return (-1);
+ return (0);
+}
+#else /* !_KERNEL */
int
sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
{
va_list ap_copy;
- int len;
+ int error, len;
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
@@ -427,13 +559,32 @@ sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
if (SBUF_HASOVERFLOWED(s))
return (-1);
+ /*
+ * For the moment, there is no way to get vsnprintf(3) to hand
+ * back a character at a time, to push everything into
+ * sbuf_putc_func() as was done for the kernel.
+ *
+ * In userspace, while drains are useful, there's generally
+ * not a problem attempting to malloc(3) on out of space. So
+ * expand a userland sbuf if there is not enough room for the
+ * data produced by sbuf_[v]printf(3).
+ */
+
+ error = 0;
do {
va_copy(ap_copy, ap);
len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1,
fmt, ap_copy);
va_end(ap_copy);
- } while (len > SBUF_FREESPACE(s) &&
- sbuf_extend(s, len - SBUF_FREESPACE(s)) == 0);
+
+ if (SBUF_FREESPACE(s) >= len)
+ break;
+ /* Cannot print with the current available space. */
+ if (s->s_drain != NULL && s->s_len > 0)
+ error = sbuf_drain(s);
+ else
+ error = sbuf_extend(s, len - SBUF_FREESPACE(s));
+ } while (error == 0);
/*
* s->s_len is the length of the string, without the terminating nul.
@@ -442,9 +593,11 @@ sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
* terminating nul.
*
* vsnprintf() returns the amount that would have been copied,
- * given sufficient space, hence the min() calculation below.
+ * given sufficient space, so don't over-increment s_len.
*/
- s->s_len += min(len, SBUF_FREESPACE(s));
+ if (SBUF_FREESPACE(s) < len)
+ len = SBUF_FREESPACE(s);
+ s->s_len += len;
if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s))
SBUF_SETFLAG(s, SBUF_OVERFLOWED);
@@ -455,6 +608,7 @@ sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
return (-1);
return (0);
}
+#endif /* _KERNEL */
/*
* Format the given arguments and append the resulting string to an sbuf.
@@ -478,17 +632,9 @@ int
sbuf_putc(struct sbuf *s, int c)
{
- assert_sbuf_integrity(s);
- assert_sbuf_state(s, 0);
-
+ sbuf_putc_func(c, s);
if (SBUF_HASOVERFLOWED(s))
return (-1);
- if (!SBUF_HASROOM(s) && sbuf_extend(s, 1) < 0) {
- SBUF_SETFLAG(s, SBUF_OVERFLOWED);
- return (-1);
- }
- if (c != '\0')
- s->s_buf[s->s_len++] = c;
return (0);
}
@@ -501,11 +647,13 @@ sbuf_trim(struct sbuf *s)
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
+ KASSERT(s->s_drain == NULL,
+ ("%s makes no sense on sbuf %p with drain", __func__, s));
if (SBUF_HASOVERFLOWED(s))
return (-1);
- while (s->s_len && isspace(s->s_buf[s->s_len-1]))
+ while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1]))
--s->s_len;
return (0);
@@ -524,16 +672,32 @@ sbuf_overflowed(struct sbuf *s)
/*
* Finish off an sbuf.
*/
-void
+int
sbuf_finish(struct sbuf *s)
{
+ int error = 0;
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
+ if (s->s_drain != NULL) {
+ error = s->s_drain->s_error;
+ while (s->s_len > 0 && error == 0)
+ error = sbuf_drain(s);
+ } else if (SBUF_HASOVERFLOWED(s))
+ error = ENOMEM;
s->s_buf[s->s_len] = '\0';
SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
SBUF_SETFLAG(s, SBUF_FINISHED);
+#ifdef _KERNEL
+ return (error);
+#else
+ /*XXX*/if (error) {
+ errno = error;
+ return (-1);
+ } else
+ return (0);
+#endif
}
/*
@@ -545,6 +709,8 @@ sbuf_data(struct sbuf *s)
assert_sbuf_integrity(s);
assert_sbuf_state(s, SBUF_FINISHED);
+ KASSERT(s->s_drain == NULL,
+ ("%s makes no sense on sbuf %p with drain", __func__, s));
return (s->s_buf);
}
@@ -558,6 +724,8 @@ sbuf_len(struct sbuf *s)
assert_sbuf_integrity(s);
/* don't care if it's finished or not */
+ KASSERT(s->s_drain == NULL,
+ ("%s makes no sense on sbuf %p with drain", __func__, s));
if (SBUF_HASOVERFLOWED(s))
return (-1);
@@ -577,6 +745,8 @@ sbuf_delete(struct sbuf *s)
if (SBUF_ISDYNAMIC(s))
SBFREE(s->s_buf);
+ if (s->s_drain != NULL)
+ SBFREE(s->s_drain);
isdyn = SBUF_ISDYNSTRUCT(s);
bzero(s, sizeof(*s));
if (isdyn)
diff --git a/freebsd/sys/kern/subr_taskqueue.c b/freebsd/sys/kern/subr_taskqueue.c
index bbfe69e4..d2072082 100644
--- a/freebsd/sys/kern/subr_taskqueue.c
+++ b/freebsd/sys/kern/subr_taskqueue.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
+#include <sys/limits.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
@@ -57,7 +58,6 @@ struct taskqueue_busy {
struct taskqueue {
STAILQ_HEAD(, task) tq_queue;
- const char *tq_name;
taskqueue_enqueue_fn tq_enqueue;
void *tq_context;
TAILQ_HEAD(, taskqueue_busy) tq_active;
@@ -110,7 +110,7 @@ TQ_SLEEP(struct taskqueue *tq, void *p, struct mtx *m, int pri, const char *wm,
}
static struct taskqueue *
-_taskqueue_create(const char *name, int mflags,
+_taskqueue_create(const char *name __unused, int mflags,
taskqueue_enqueue_fn enqueue, void *context,
int mtxflags, const char *mtxname)
{
@@ -122,7 +122,6 @@ _taskqueue_create(const char *name, int mflags,
STAILQ_INIT(&queue->tq_queue);
TAILQ_INIT(&queue->tq_active);
- queue->tq_name = name;
queue->tq_enqueue = enqueue;
queue->tq_context = context;
#ifndef __rtems__
@@ -186,7 +185,8 @@ taskqueue_enqueue(struct taskqueue *queue, struct task *task)
* Count multiple enqueues.
*/
if (task->ta_pending) {
- task->ta_pending++;
+ if (task->ta_pending < USHRT_MAX)
+ task->ta_pending++;
TQ_UNLOCK(queue);
return 0;
}
@@ -485,7 +485,7 @@ taskqueue_fast_run(void *dummy)
}
TASKQUEUE_FAST_DEFINE(fast, taskqueue_fast_enqueue, NULL,
- swi_add(NULL, "Fast task queue", taskqueue_fast_run, NULL,
+ swi_add(NULL, "fast taskq", taskqueue_fast_run, NULL,
SWI_TQ_FAST, INTR_MPSAFE, &taskqueue_fast_ih));
int
diff --git a/freebsd/sys/kern/subr_unit.c b/freebsd/sys/kern/subr_unit.c
index 1719ede8..386a470b 100644
--- a/freebsd/sys/kern/subr_unit.c
+++ b/freebsd/sys/kern/subr_unit.c
@@ -43,7 +43,7 @@
*
* If a mutex is not provided when the unit number space is created, a
* default global mutex is used. The advantage to passing a mutex in, is
- * that the the alloc_unrl() function can be called with the mutex already
+ * that the alloc_unrl() function can be called with the mutex already
* held (it will not be released by alloc_unrl()).
*
* The allocation function alloc_unr{l}() never sleeps (but it may block on
@@ -54,7 +54,7 @@
*
* A userland test program is included.
*
- * Memory usage is a very complex function of the the exact allocation
+ * Memory usage is a very complex function of the exact allocation
* pattern, but always very compact:
* * For the very typical case where a single unbroken run of unit
* numbers are allocated 44 bytes are used on i386.
@@ -65,7 +65,7 @@
* in the usermode test program included, the worst case usage
* was 798 bytes on i386 for 5000 allocated and 5000 free units.
* * The worst case is where every other unit number is allocated and
- * the the rest are free. In that case 44 + N/4 bytes are used where
+ * the rest are free. In that case 44 + N/4 bytes are used where
* N is the number of the highest unit allocated.
*/
@@ -630,6 +630,132 @@ alloc_unr(struct unrhdr *uh)
return (i);
}
+static int
+alloc_unr_specificl(struct unrhdr *uh, u_int item, void **p1, void **p2)
+{
+ struct unr *up, *upn;
+ struct unrb *ub;
+ u_int i, last, tl;
+
+ mtx_assert(uh->mtx, MA_OWNED);
+
+ if (item < uh->low + uh->first || item > uh->high)
+ return (-1);
+
+ up = TAILQ_FIRST(&uh->head);
+ /* Ideal split. */
+ if (up == NULL && item - uh->low == uh->first) {
+ uh->first++;
+ uh->last--;
+ uh->busy++;
+ check_unrhdr(uh, __LINE__);
+ return (item);
+ }
+
+ i = item - uh->low - uh->first;
+
+ if (up == NULL) {
+ up = new_unr(uh, p1, p2);
+ up->ptr = NULL;
+ up->len = i;
+ TAILQ_INSERT_TAIL(&uh->head, up, list);
+ up = new_unr(uh, p1, p2);
+ up->ptr = uh;
+ up->len = 1;
+ TAILQ_INSERT_TAIL(&uh->head, up, list);
+ uh->last = uh->high - uh->low - i;
+ uh->busy++;
+ check_unrhdr(uh, __LINE__);
+ return (item);
+ } else {
+ /* Find the item which contains the unit we want to allocate. */
+ TAILQ_FOREACH(up, &uh->head, list) {
+ if (up->len > i)
+ break;
+ i -= up->len;
+ }
+ }
+
+ if (up == NULL) {
+ if (i > 0) {
+ up = new_unr(uh, p1, p2);
+ up->ptr = NULL;
+ up->len = i;
+ TAILQ_INSERT_TAIL(&uh->head, up, list);
+ }
+ up = new_unr(uh, p1, p2);
+ up->ptr = uh;
+ up->len = 1;
+ TAILQ_INSERT_TAIL(&uh->head, up, list);
+ goto done;
+ }
+
+ if (is_bitmap(uh, up)) {
+ ub = up->ptr;
+ if (bit_test(ub->map, i) == 0) {
+ bit_set(ub->map, i);
+ ub->busy++;
+ goto done;
+ } else
+ return (-1);
+ } else if (up->ptr == uh)
+ return (-1);
+
+ KASSERT(up->ptr == NULL,
+ ("alloc_unr_specificl: up->ptr != NULL (up=%p)", up));
+
+ /* Split off the tail end, if any. */
+ tl = up->len - (1 + i);
+ if (tl > 0) {
+ upn = new_unr(uh, p1, p2);
+ upn->ptr = NULL;
+ upn->len = tl;
+ TAILQ_INSERT_AFTER(&uh->head, up, upn, list);
+ }
+
+ /* Split off head end, if any */
+ if (i > 0) {
+ upn = new_unr(uh, p1, p2);
+ upn->len = i;
+ upn->ptr = NULL;
+ TAILQ_INSERT_BEFORE(up, upn, list);
+ }
+ up->len = 1;
+ up->ptr = uh;
+
+done:
+ last = uh->high - uh->low - (item - uh->low);
+ if (uh->last > last)
+ uh->last = last;
+ uh->busy++;
+ collapse_unr(uh, up);
+ check_unrhdr(uh, __LINE__);
+ return (item);
+}
+
+int
+alloc_unr_specific(struct unrhdr *uh, u_int item)
+{
+ void *p1, *p2;
+ int i;
+
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "alloc_unr_specific");
+
+ p1 = Malloc(sizeof(struct unr));
+ p2 = Malloc(sizeof(struct unr));
+
+ mtx_lock(uh->mtx);
+ i = alloc_unr_specificl(uh, item, &p1, &p2);
+ mtx_unlock(uh->mtx);
+
+ if (p1 != NULL)
+ Free(p1);
+ if (p2 != NULL)
+ Free(p2);
+
+ return (i);
+}
+
/*
* Free a unr.
*
@@ -812,6 +938,42 @@ print_unrhdr(struct unrhdr *uh)
}
}
+static void
+test_alloc_unr(struct unrhdr *uh, u_int i, char a[])
+{
+ int j;
+
+ if (a[i]) {
+ printf("F %u\n", i);
+ free_unr(uh, i);
+ a[i] = 0;
+ } else {
+ no_alloc = 1;
+ j = alloc_unr(uh);
+ if (j != -1) {
+ a[j] = 1;
+ printf("A %d\n", j);
+ }
+ no_alloc = 0;
+ }
+}
+
+static void
+test_alloc_unr_specific(struct unrhdr *uh, u_int i, char a[])
+{
+ int j;
+
+ j = alloc_unr_specific(uh, i);
+ if (j == -1) {
+ printf("F %u\n", i);
+ a[i] = 0;
+ free_unr(uh, i);
+ } else {
+ a[i] = 1;
+ printf("A %d\n", j);
+ }
+}
+
/* Number of unrs to test */
#define NN 10000
@@ -827,6 +989,7 @@ main(int argc __unused, const char **argv __unused)
print_unrhdr(uh);
memset(a, 0, sizeof a);
+ srandomdev();
fprintf(stderr, "sizeof(struct unr) %zu\n", sizeof(struct unr));
fprintf(stderr, "sizeof(struct unrb) %zu\n", sizeof(struct unrb));
@@ -840,19 +1003,11 @@ main(int argc __unused, const char **argv __unused)
if (a[i] && (j & 1))
continue;
#endif
- if (a[i]) {
- printf("F %u\n", i);
- free_unr(uh, i);
- a[i] = 0;
- } else {
- no_alloc = 1;
- i = alloc_unr(uh);
- if (i != -1) {
- a[i] = 1;
- printf("A %u\n", i);
- }
- no_alloc = 0;
- }
+ if ((random() & 1) != 0)
+ test_alloc_unr(uh, i, a);
+ else
+ test_alloc_unr_specific(uh, i, a);
+
if (1) /* XXX: change this for detailed debug printout */
print_unrhdr(uh);
check_unrhdr(uh, __LINE__);
diff --git a/freebsd/sys/kern/sys_generic.c b/freebsd/sys/kern/sys_generic.c
index b0201d68..deda7afd 100644
--- a/freebsd/sys/kern/sys_generic.c
+++ b/freebsd/sys/kern/sys_generic.c
@@ -843,6 +843,54 @@ select(struct thread *td, struct select_args *uap)
}
#endif /* __rtems__ */
+/*
+ * In the unlikely case when user specified n greater then the last
+ * open file descriptor, check that no bits are set after the last
+ * valid fd. We must return EBADF if any is set.
+ *
+ * There are applications that rely on the behaviour.
+ *
+ * nd is fd_lastfile + 1.
+ */
+static int
+select_check_badfd(fd_set *fd_in, int nd, int ndu, int abi_nfdbits)
+{
+ char *addr, *oaddr;
+ int b, i, res;
+ uint8_t bits;
+
+ if (nd >= ndu || fd_in == NULL)
+ return (0);
+
+ oaddr = NULL;
+ bits = 0; /* silence gcc */
+ for (i = nd; i < ndu; i++) {
+ b = i / NBBY;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ addr = (char *)fd_in + b;
+#else
+ addr = (char *)fd_in;
+ if (abi_nfdbits == NFDBITS) {
+ addr += rounddown(b, sizeof(fd_mask)) +
+ sizeof(fd_mask) - 1 - b % sizeof(fd_mask);
+ } else {
+ addr += rounddown(b, sizeof(uint32_t)) +
+ sizeof(uint32_t) - 1 - b % sizeof(uint32_t);
+ }
+#endif
+ if (addr != oaddr) {
+ res = fubyte(addr);
+ if (res == -1)
+ return (EFAULT);
+ oaddr = addr;
+ bits = res;
+ }
+ if ((bits & (1 << (i % NBBY))) != 0)
+ return (EBADF);
+ }
+ return (0);
+}
+
int
kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits)
@@ -857,20 +905,30 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
fd_mask s_selbits[howmany(2048, NFDBITS)];
fd_mask *ibits[3], *obits[3], *selbits, *sbp;
struct timeval atv, rtv, ttv;
- int error, timo;
+ int error, lf, ndu, timo;
u_int nbufbytes, ncpbytes, ncpubytes, nfdbits;
if (nd < 0)
return (EINVAL);
+ ndu = nd;
#ifndef __rtems__
- fdp = td->td_proc->p_fd;
- if (nd > fdp->fd_lastfile + 1)
- nd = fdp->fd_lastfile + 1;
+ lf = fdp->fd_lastfile;
#else /* __rtems__ */
(void) fdp;
- if (nd > rtems_libio_number_iops)
- nd = rtems_libio_number_iops;
+ lf = rtems_libio_number_iops;
#endif /* __rtems__ */
+ if (nd > lf + 1)
+ nd = lf + 1;
+
+ error = select_check_badfd(fd_in, nd, ndu, abi_nfdbits);
+ if (error != 0)
+ return (error);
+ error = select_check_badfd(fd_ou, nd, ndu, abi_nfdbits);
+ if (error != 0)
+ return (error);
+ error = select_check_badfd(fd_ex, nd, ndu, abi_nfdbits);
+ if (error != 0)
+ return (error);
/*
* Allocate just enough bits for the non-null fd_sets. Use the
@@ -1204,7 +1262,7 @@ rtems_bsd_poll(td, uap)
struct pollfd *bits;
struct pollfd smallbits[32];
struct timeval atv, rtv, ttv;
- int error = 0, timo;
+ int error, timo;
u_int nfds;
size_t ni;
@@ -1549,6 +1607,23 @@ selfdfree(struct seltd *stp, struct selfd *sfp)
uma_zfree(selfd_zone, sfp);
}
+/* Drain the waiters tied to all the selfd belonging the specified selinfo. */
+void
+seldrain(sip)
+ struct selinfo *sip;
+{
+
+ /*
+ * This feature is already provided by doselwakeup(), thus it is
+ * enough to go for it.
+ * Eventually, the context, should take care to avoid races
+ * between thread calling select()/poll() and file descriptor
+ * detaching, but, again, the races are just the same as
+ * selwakeup().
+ */
+ doselwakeup(sip, -1);
+}
+
/*
* Record a select request.
*/
diff --git a/freebsd/sys/kern/sys_socket.c b/freebsd/sys/kern/sys_socket.c
index 6bb4416e..e86698fa 100644
--- a/freebsd/sys/kern/sys_socket.c
+++ b/freebsd/sys/kern/sys_socket.c
@@ -87,9 +87,7 @@ soo_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
if (error)
return (error);
#endif
- CURVNET_SET(so->so_vnet);
error = soreceive(so, 0, uio, 0, 0, 0);
- CURVNET_RESTORE();
return (error);
}
#ifdef __rtems__
@@ -210,7 +208,6 @@ soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
struct socket *so = fp->f_data;
int error = 0;
- CURVNET_SET(so->so_vnet);
switch (cmd) {
case FIONBIO:
SOCK_LOCK(so);
@@ -297,14 +294,18 @@ soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
*/
if (IOCGROUP(cmd) == 'i')
error = ifioctl(so, cmd, data, td);
- else if (IOCGROUP(cmd) == 'r')
+ else if (IOCGROUP(cmd) == 'r') {
+ CURVNET_SET(so->so_vnet);
error = rtioctl_fib(cmd, data, so->so_fibnum);
- else
+ CURVNET_RESTORE();
+ } else {
+ CURVNET_SET(so->so_vnet);
error = ((*so->so_proto->pr_usrreqs->pru_control)
(so, cmd, data, 0, td));
+ CURVNET_RESTORE();
+ }
break;
}
- CURVNET_RESTORE();
return (error);
}
#ifdef __rtems__
diff --git a/freebsd/sys/kern/uipc_domain.c b/freebsd/sys/kern/uipc_domain.c
index 1b2be102..7a70e246 100644
--- a/freebsd/sys/kern/uipc_domain.c
+++ b/freebsd/sys/kern/uipc_domain.c
@@ -222,7 +222,7 @@ domain_add(void *data)
domains = dp;
KASSERT(domain_init_status >= 1,
- ("attempt to net_add_domain(%s) before domaininit()",
+ ("attempt to domain_add(%s) before domaininit()",
dp->dom_name));
#ifndef INVARIANTS
if (domain_init_status < 1)
diff --git a/freebsd/sys/kern/uipc_mbuf.c b/freebsd/sys/kern/uipc_mbuf.c
index 43255aab..f3b7c10d 100644
--- a/freebsd/sys/kern/uipc_mbuf.c
+++ b/freebsd/sys/kern/uipc_mbuf.c
@@ -282,7 +282,7 @@ mb_free_ext(struct mbuf *m)
}
/*
- * Attach the the cluster from *m to *n, set up m_ext in *n
+ * Attach the cluster from *m to *n, set up m_ext in *n
* and bump the refcount of the cluster.
*/
static void
@@ -1412,6 +1412,11 @@ m_print(const struct mbuf *m, int maxlen)
int pdata;
const struct mbuf *m2;
+ if (m == NULL) {
+ printf("mbuf: %p\n", m);
+ return;
+ }
+
if (m->m_flags & M_PKTHDR)
len = m->m_pkthdr.len;
else
diff --git a/freebsd/sys/kern/uipc_sockbuf.c b/freebsd/sys/kern/uipc_sockbuf.c
index 48195f31..1ee7a831 100644
--- a/freebsd/sys/kern/uipc_sockbuf.c
+++ b/freebsd/sys/kern/uipc_sockbuf.c
@@ -534,9 +534,6 @@ sbappendstream_locked(struct sockbuf *sb, struct mbuf *m)
SBLASTMBUFCHK(sb);
- /* Remove all packet headers and mbuf tags to get a pure data chain. */
- m_demote(m, 1);
-
sbcompress(sb, m, sb->sb_mbtail);
sb->sb_lastrecord = sb->sb_mb;
diff --git a/freebsd/sys/kern/uipc_socket.c b/freebsd/sys/kern/uipc_socket.c
index 473c3df0..5b3b9eef 100644
--- a/freebsd/sys/kern/uipc_socket.c
+++ b/freebsd/sys/kern/uipc_socket.c
@@ -94,6 +94,12 @@
* from a listen queue to a file descriptor, in order to prevent garbage
* collection of the socket at an untimely moment. For a number of reasons,
* these interfaces are not preferred, and should be avoided.
+ *
+ * NOTE: With regard to VNETs the general rule is that callers do not set
+ * curvnet. Exceptions to this rule include soabort(), sodisconnect(),
+ * sofree() (and with that sorele(), sotryfree()), as well as sonewconn()
+ * and sorflush(), which are usually called from a pre-set VNET context.
+ * sopoll() currently does not need a VNET context to be set.
*/
#include <sys/cdefs.h>
@@ -168,6 +174,10 @@ int maxsockets;
MALLOC_DEFINE(M_SONAME, "soname", "socket name");
MALLOC_DEFINE(M_PCB, "pcb", "protocol control block");
+#define VNET_SO_ASSERT(so) \
+ VNET_ASSERT(curvnet != NULL, \
+ ("%s:%d curvnet is NULL, so=%p", __func__, __LINE__, (so)));
+
static int somaxconn = SOMAXCONN;
static int sysctl_somaxconn(SYSCTL_HANDLER_ARGS);
/* XXX: we dont have SYSCTL_USHORT */
@@ -294,6 +304,8 @@ soalloc(struct vnet *vnet)
so->so_gencnt = ++so_gencnt;
++numopensockets;
#ifdef VIMAGE
+ VNET_ASSERT(vnet != NULL, ("%s:%d vnet is NULL, so=%p",
+ __func__, __LINE__, so));
vnet->vnet_sockcnt++;
so->so_vnet = vnet;
#endif
@@ -317,6 +329,8 @@ sodealloc(struct socket *so)
so->so_gencnt = ++so_gencnt;
--numopensockets; /* Could be below, but faster here. */
#ifdef VIMAGE
+ VNET_ASSERT(so->so_vnet != NULL, ("%s:%d so_vnet is NULL, so=%p",
+ __func__, __LINE__, so));
so->so_vnet->vnet_sockcnt--;
#endif
mtx_unlock(&so_global_mtx);
@@ -377,6 +391,7 @@ socreate(int dom, struct socket **aso, int type, int proto,
so->so_type = type;
so->so_cred = crhold(cred);
if ((prp->pr_domain->dom_family == PF_INET) ||
+ (prp->pr_domain->dom_family == PF_INET6) ||
(prp->pr_domain->dom_family == PF_ROUTE))
#ifndef __rtems__
so->so_fibnum = td->td_proc->p_fibnum;
@@ -440,7 +455,8 @@ sonewconn(struct socket *head, int connstatus)
if (over)
#endif
return (NULL);
- VNET_ASSERT(head->so_vnet);
+ VNET_ASSERT(head->so_vnet != NULL, ("%s:%d so_vnet is NULL, head=%p",
+ __func__, __LINE__, head));
so = soalloc(head->so_vnet);
if (so == NULL)
return (NULL);
@@ -459,6 +475,7 @@ sonewconn(struct socket *head, int connstatus)
#endif
knlist_init_mtx(&so->so_rcv.sb_sel.si_note, SOCKBUF_MTX(&so->so_rcv));
knlist_init_mtx(&so->so_snd.sb_sel.si_note, SOCKBUF_MTX(&so->so_snd));
+ VNET_SO_ASSERT(head);
if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat) ||
(*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
sodealloc(so);
@@ -533,8 +550,12 @@ sobind(struct socket *so, struct sockaddr *nam, struct thread *td)
int
solisten(struct socket *so, int backlog, struct thread *td)
{
+ int error;
- return ((*so->so_proto->pr_usrreqs->pru_listen)(so, backlog, td));
+ CURVNET_SET(so->so_vnet);
+ error = (*so->so_proto->pr_usrreqs->pru_listen)(so, backlog, td);
+ CURVNET_RESTORE();
+ return error;
}
int
@@ -617,11 +638,12 @@ sofree(struct socket *so)
so->so_qstate & SQ_COMP, so->so_qstate & SQ_INCOMP));
if (so->so_options & SO_ACCEPTCONN) {
KASSERT((TAILQ_EMPTY(&so->so_comp)), ("sofree: so_comp populated"));
- KASSERT((TAILQ_EMPTY(&so->so_incomp)), ("sofree: so_comp populated"));
+ KASSERT((TAILQ_EMPTY(&so->so_incomp)), ("sofree: so_incomp populated"));
}
SOCK_UNLOCK(so);
ACCEPT_UNLOCK();
+ VNET_SO_ASSERT(so);
if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL)
(*pr->pr_domain->dom_dispose)(so->so_rcv.sb_mb);
if (pr->pr_usrreqs->pru_detach != NULL)
@@ -643,6 +665,8 @@ sofree(struct socket *so)
*/
sbdestroy(&so->so_snd, so);
sbdestroy(&so->so_rcv, so);
+ seldrain(&so->so_snd.sb_sel);
+ seldrain(&so->so_rcv.sb_sel);
knlist_destroy(&so->so_rcv.sb_sel.si_note);
knlist_destroy(&so->so_snd.sb_sel.si_note);
sodealloc(so);
@@ -751,6 +775,7 @@ soabort(struct socket *so)
KASSERT(so->so_state & SS_NOFDREF, ("soabort: !SS_NOFDREF"));
KASSERT((so->so_state & SQ_COMP) == 0, ("soabort: SQ_COMP"));
KASSERT((so->so_state & SQ_INCOMP) == 0, ("soabort: SQ_INCOMP"));
+ VNET_SO_ASSERT(so);
if (so->so_proto->pr_usrreqs->pru_abort != NULL)
(*so->so_proto->pr_usrreqs->pru_abort)(so);
@@ -768,7 +793,10 @@ soaccept(struct socket *so, struct sockaddr **nam)
KASSERT((so->so_state & SS_NOFDREF) != 0, ("soaccept: !NOFDREF"));
so->so_state &= ~SS_NOFDREF;
SOCK_UNLOCK(so);
+
+ CURVNET_SET(so->so_vnet);
error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam);
+ CURVNET_RESTORE();
return (error);
}
@@ -806,8 +834,12 @@ soconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
int
soconnect2(struct socket *so1, struct socket *so2)
{
+ int error;
- return ((*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2));
+ CURVNET_SET(so1->so_vnet);
+ error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2);
+ CURVNET_RESTORE();
+ return (error);
}
int
@@ -819,6 +851,7 @@ sodisconnect(struct socket *so)
return (ENOTCONN);
if (so->so_state & SS_ISDISCONNECTING)
return (EALREADY);
+ VNET_SO_ASSERT(so);
error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so);
return (error);
}
@@ -1084,6 +1117,7 @@ sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio,
* there are probably other places that this also happens. We must
* rethink this.
*/
+ VNET_SO_ASSERT(so);
error = (*so->so_proto->pr_usrreqs->pru_send)(so,
(flags & MSG_OOB) ? PRUS_OOB :
/*
@@ -1273,6 +1307,7 @@ restart:
* places that this also happens. We must rethink
* this.
*/
+ VNET_SO_ASSERT(so);
error = (*so->so_proto->pr_usrreqs->pru_send)(so,
(flags & MSG_OOB) ? PRUS_OOB :
/*
@@ -1339,6 +1374,7 @@ soreceive_rcvoob(struct socket *so, struct uio *uio, int flags)
int error;
KASSERT(flags & MSG_OOB, ("soreceive_rcvoob: (flags & MSG_OOB) == 0"));
+ VNET_SO_ASSERT(so);
m = m_get(M_WAIT, MT_DATA);
error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK);
@@ -1447,8 +1483,10 @@ soreceive_generic(struct socket *so, struct sockaddr **psa, struct uio *uio,
if (mp != NULL)
*mp = NULL;
if ((pr->pr_flags & PR_WANTRCVD) && (so->so_state & SS_ISCONFIRMING)
- && uio->uio_resid)
+ && uio->uio_resid) {
+ VNET_SO_ASSERT(so);
(*pr->pr_usrreqs->pru_rcvd)(so, 0);
+ }
error = sblock(&so->so_rcv, SBLOCKWAIT(flags));
if (error)
@@ -1461,17 +1499,11 @@ restart:
* If we have less data than requested, block awaiting more (subject
* to any timeout) if:
* 1. the current count is less than the low water mark, or
- * 2. MSG_WAITALL is set, and it is possible to do the entire
- * receive operation at once if we block (resid <= hiwat).
- * 3. MSG_DONTWAIT is not set
- * If MSG_WAITALL is set but resid is larger than the receive buffer,
- * we have to do the receive in sections, and thus risk returning a
- * short count if a timeout or signal occurs after we start.
+ * 2. MSG_DONTWAIT is not set
*/
if (m == NULL || (((flags & MSG_DONTWAIT) == 0 &&
so->so_rcv.sb_cc < uio->uio_resid) &&
- (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
- ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
+ so->so_rcv.sb_cc < so->so_rcv.sb_lowat &&
m->m_nextpkt == NULL && (pr->pr_flags & PR_ATOMIC) == 0)) {
KASSERT(m != NULL || !so->so_rcv.sb_cc,
("receive: m == %p so->so_rcv.sb_cc == %u",
@@ -1597,6 +1629,7 @@ dontblock:
cm->m_next = NULL;
if (pr->pr_domain->dom_externalize != NULL) {
SOCKBUF_UNLOCK(&so->so_rcv);
+ VNET_SO_ASSERT(so);
error = (*pr->pr_domain->dom_externalize)
(cm, controlp);
SOCKBUF_LOCK(&so->so_rcv);
@@ -1661,8 +1694,8 @@ dontblock:
* examined ('type'), end the receive operation.
*/
SOCKBUF_LOCK_ASSERT(&so->so_rcv);
- if (m->m_type == MT_OOBDATA) {
- if (type != MT_OOBDATA)
+ if (m->m_type == MT_OOBDATA || m->m_type == MT_CONTROL) {
+ if (type != m->m_type)
break;
} else if (type == MT_OOBDATA)
break;
@@ -1812,15 +1845,22 @@ dontblock:
*/
if (pr->pr_flags & PR_WANTRCVD) {
SOCKBUF_UNLOCK(&so->so_rcv);
+ VNET_SO_ASSERT(so);
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
SOCKBUF_LOCK(&so->so_rcv);
}
SBLASTRECORDCHK(&so->so_rcv);
SBLASTMBUFCHK(&so->so_rcv);
- error = sbwait(&so->so_rcv);
- if (error) {
- SOCKBUF_UNLOCK(&so->so_rcv);
- goto release;
+ /*
+ * We could receive some data while was notifying
+ * the protocol. Skip blocking in this case.
+ */
+ if (so->so_rcv.sb_mb == NULL) {
+ error = sbwait(&so->so_rcv);
+ if (error) {
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ goto release;
+ }
}
m = so->so_rcv.sb_mb;
if (m != NULL)
@@ -1858,6 +1898,7 @@ dontblock:
if (!(flags & MSG_SOCALLBCK) &&
(pr->pr_flags & PR_WANTRCVD)) {
SOCKBUF_UNLOCK(&so->so_rcv);
+ VNET_SO_ASSERT(so);
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
SOCKBUF_LOCK(&so->so_rcv);
}
@@ -2055,6 +2096,7 @@ deliver:
(((flags & MSG_WAITALL) && uio->uio_resid > 0) ||
!(flags & MSG_SOCALLBCK))) {
SOCKBUF_UNLOCK(sb);
+ VNET_SO_ASSERT(so);
(*so->so_proto->pr_usrreqs->pru_rcvd)(so, flags);
SOCKBUF_LOCK(sb);
}
@@ -2266,9 +2308,13 @@ int
soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
{
+ int error;
- return (so->so_proto->pr_usrreqs->pru_soreceive(so, psa, uio, mp0,
+ CURVNET_SET(so->so_vnet);
+ error = (so->so_proto->pr_usrreqs->pru_soreceive(so, psa, uio, mp0,
controlp, flagsp));
+ CURVNET_RESTORE();
+ return (error);
}
int
@@ -2279,17 +2325,19 @@ soshutdown(struct socket *so, int how)
if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR))
return (EINVAL);
+
+ CURVNET_SET(so->so_vnet);
if (pr->pr_usrreqs->pru_flush != NULL) {
(*pr->pr_usrreqs->pru_flush)(so, how);
}
if (how != SHUT_WR)
sorflush(so);
if (how != SHUT_RD) {
- CURVNET_SET(so->so_vnet);
error = (*pr->pr_usrreqs->pru_shutdown)(so);
CURVNET_RESTORE();
return (error);
}
+ CURVNET_RESTORE();
return (0);
}
@@ -2300,6 +2348,8 @@ sorflush(struct socket *so)
struct protosw *pr = so->so_proto;
struct sockbuf asb;
+ VNET_SO_ASSERT(so);
+
/*
* In order to avoid calling dom_dispose with the socket buffer mutex
* held, and in order to generally avoid holding the lock for a long
@@ -2313,7 +2363,6 @@ sorflush(struct socket *so)
* socket buffer. Don't let our acquire be interrupted by a signal
* despite any existing socket disposition on interruptable waiting.
*/
- CURVNET_SET(so->so_vnet);
socantrcvmore(so);
(void) sblock(sb, SBL_WAIT | SBL_NOINTR);
@@ -2337,7 +2386,6 @@ sorflush(struct socket *so)
if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL)
(*pr->pr_domain->dom_dispose)(asb.sb_mb);
sbrelease_internal(&asb, so);
- CURVNET_RESTORE();
}
/*
@@ -2401,11 +2449,14 @@ sosetopt(struct socket *so, struct sockopt *sopt)
struct mac extmac;
#endif
+ CURVNET_SET(so->so_vnet);
error = 0;
if (sopt->sopt_level != SOL_SOCKET) {
- if (so->so_proto && so->so_proto->pr_ctloutput)
- return ((*so->so_proto->pr_ctloutput)
- (so, sopt));
+ if (so->so_proto->pr_ctloutput != NULL) {
+ error = (*so->so_proto->pr_ctloutput)(so, sopt);
+ CURVNET_RESTORE();
+ return (error);
+ }
error = ENOPROTOOPT;
} else {
switch (sopt->sopt_name) {
@@ -2458,15 +2509,16 @@ sosetopt(struct socket *so, struct sockopt *sopt)
case SO_SETFIB:
error = sooptcopyin(sopt, &optval, sizeof optval,
sizeof optval);
- if (optval < 1 || optval > rt_numfibs) {
+ if (optval < 0 || optval >= rt_numfibs) {
error = EINVAL;
goto bad;
}
- if ((so->so_proto->pr_domain->dom_family == PF_INET) ||
- (so->so_proto->pr_domain->dom_family == PF_ROUTE)) {
+ if (((so->so_proto->pr_domain->dom_family == PF_INET) ||
+ (so->so_proto->pr_domain->dom_family == PF_INET6) ||
+ (so->so_proto->pr_domain->dom_family == PF_ROUTE))) {
so->so_fibnum = optval;
/* Note: ignore error */
- if (so->so_proto && so->so_proto->pr_ctloutput)
+ if (so->so_proto->pr_ctloutput)
(*so->so_proto->pr_ctloutput)(so, sopt);
} else {
so->so_fibnum = 0;
@@ -2584,13 +2636,11 @@ sosetopt(struct socket *so, struct sockopt *sopt)
error = ENOPROTOOPT;
break;
}
- if (error == 0 && so->so_proto != NULL &&
- so->so_proto->pr_ctloutput != NULL) {
- (void) ((*so->so_proto->pr_ctloutput)
- (so, sopt));
- }
+ if (error == 0 && so->so_proto->pr_ctloutput != NULL)
+ (void)(*so->so_proto->pr_ctloutput)(so, sopt);
}
bad:
+ CURVNET_RESTORE();
return (error);
}
@@ -2634,13 +2684,15 @@ sogetopt(struct socket *so, struct sockopt *sopt)
struct mac extmac;
#endif
+ CURVNET_SET(so->so_vnet);
error = 0;
if (sopt->sopt_level != SOL_SOCKET) {
- if (so->so_proto && so->so_proto->pr_ctloutput) {
- return ((*so->so_proto->pr_ctloutput)
- (so, sopt));
- } else
- return (ENOPROTOOPT);
+ if (so->so_proto->pr_ctloutput != NULL)
+ error = (*so->so_proto->pr_ctloutput)(so, sopt);
+ else
+ error = ENOPROTOOPT;
+ CURVNET_RESTORE();
+ return (error);
} else {
switch (sopt->sopt_name) {
#ifdef INET
@@ -2677,6 +2729,10 @@ integer:
optval = so->so_type;
goto integer;
+ case SO_PROTOCOL:
+ optval = so->so_proto->pr_protocol;
+ goto integer;
+
case SO_ERROR:
SOCK_LOCK(so);
optval = so->so_error;
@@ -2724,11 +2780,11 @@ integer:
error = sooptcopyin(sopt, &extmac, sizeof(extmac),
sizeof(extmac));
if (error)
- return (error);
+ goto bad;
error = mac_getsockopt_label(sopt->sopt_td->td_ucred,
so, &extmac);
if (error)
- return (error);
+ goto bad;
error = sooptcopyout(sopt, &extmac, sizeof extmac);
#else
error = EOPNOTSUPP;
@@ -2740,11 +2796,11 @@ integer:
error = sooptcopyin(sopt, &extmac, sizeof(extmac),
sizeof(extmac));
if (error)
- return (error);
+ goto bad;
error = mac_getsockopt_peerlabel(
sopt->sopt_td->td_ucred, so, &extmac);
if (error)
- return (error);
+ goto bad;
error = sooptcopyout(sopt, &extmac, sizeof extmac);
#else
error = EOPNOTSUPP;
@@ -2767,8 +2823,12 @@ integer:
error = ENOPROTOOPT;
break;
}
- return (error);
}
+#ifdef MAC
+bad:
+#endif
+ CURVNET_RESTORE();
+ return (error);
}
/* XXX; prepare mbuf for (__FreeBSD__ < 3) routines. */
@@ -2902,6 +2962,10 @@ sopoll(struct socket *so, int events, struct ucred *active_cred,
struct thread *td)
{
+ /*
+ * We do not need to set or assert curvnet as long as everyone uses
+ * sopoll_generic().
+ */
return (so->so_proto->pr_usrreqs->pru_sopoll(so, events, active_cred,
td));
}
diff --git a/freebsd/sys/kern/uipc_syscalls.c b/freebsd/sys/kern/uipc_syscalls.c
index 5ee11b0c..960aae87 100644
--- a/freebsd/sys/kern/uipc_syscalls.c
+++ b/freebsd/sys/kern/uipc_syscalls.c
@@ -368,14 +368,9 @@ rtems_bsd_listen(td, uap)
so = fp->f_data;
#ifdef MAC
error = mac_socket_check_listen(td->td_ucred, so);
- if (error == 0) {
+ if (error == 0)
#endif
- CURVNET_SET(so->so_vnet);
error = solisten(so, uap->backlog, td);
- CURVNET_RESTORE();
-#ifdef MAC
- }
-#endif
fdrop(fp, td);
}
return(error);
@@ -591,9 +586,7 @@ kern_accept(struct thread *td, int s, struct sockaddr **name,
tmp = fflag & FASYNC;
(void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
sa = 0;
- CURVNET_SET(so->so_vnet);
error = soaccept(so, &sa);
- CURVNET_RESTORE();
if (error) {
/*
* return a namelen of zero for older code which might
@@ -953,6 +946,10 @@ kern_sendit(td, s, mp, flags, control, segflg)
return (error);
so = (struct socket *)fp->f_data;
+#ifdef KTRACE
+ if (mp->msg_name != NULL && KTRPOINT(td, KTR_STRUCT))
+ ktrsockaddr(mp->msg_name);
+#endif
#ifdef MAC
if (mp->msg_name != NULL) {
error = mac_socket_check_connect(td->td_ucred, so,
@@ -1253,11 +1250,9 @@ kern_recvit(td, s, mp, fromseg, controlp)
ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
- CURVNET_SET(so->so_vnet);
error = soreceive(so, &fromsa, &auio, (struct mbuf **)0,
(mp->msg_control || controlp) ? &control : (struct mbuf **)0,
&mp->msg_flags);
- CURVNET_RESTORE();
if (error) {
if (auio.uio_resid != (int)len && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
@@ -1720,9 +1715,7 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize)
error = getsock(td->td_proc->p_fd, s, &fp, NULL);
if (error == 0) {
so = fp->f_data;
- CURVNET_SET(so->so_vnet);
error = sosetopt(so, &sopt);
- CURVNET_RESTORE();
fdrop(fp, td);
}
return(error);
@@ -1834,9 +1827,7 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize)
error = getsock(td->td_proc->p_fd, s, &fp, NULL);
if (error == 0) {
so = fp->f_data;
- CURVNET_SET(so->so_vnet);
error = sogetopt(so, &sopt);
- CURVNET_RESTORE();
*valsize = sopt.sopt_valsize;
fdrop(fp, td);
}
@@ -2609,11 +2600,17 @@ retry_space:
}
/*
- * Get a sendfile buf. We usually wait as long
- * as necessary, but this wait can be interrupted.
+ * Get a sendfile buf. When allocating the
+ * first buffer for mbuf chain, we usually
+ * wait as long as necessary, but this wait
+ * can be interrupted. For consequent
+ * buffers, do not sleep, since several
+ * threads might exhaust the buffers and then
+ * deadlock.
*/
- if ((sf = sf_buf_alloc(pg,
- (mnw ? SFB_NOWAIT : SFB_CATCH))) == NULL) {
+ sf = sf_buf_alloc(pg, (mnw || m != NULL) ? SFB_NOWAIT :
+ SFB_CATCH);
+ if (sf == NULL) {
mbstat.sf_allocfail++;
vm_page_lock_queues();
vm_page_unwire(pg, 0);
@@ -2623,7 +2620,8 @@ retry_space:
if (pg->wire_count == 0 && pg->object == NULL)
vm_page_free(pg);
vm_page_unlock_queues();
- error = (mnw ? EAGAIN : EINTR);
+ if (m == NULL)
+ error = (mnw ? EAGAIN : EINTR);
break;
}
@@ -2783,9 +2781,13 @@ sctp_peeloff(td, uap)
error = fgetsock(td, uap->sd, &head, &fflag);
if (error)
goto done2;
+ if (head->so_proto->pr_protocol != IPPROTO_SCTP) {
+ error = EOPNOTSUPP;
+ goto done;
+ }
error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
if (error)
- goto done2;
+ goto done;
/*
* At this point we know we do have a assoc to pull
* we proceed to get the fd setup. This may block
@@ -2901,6 +2903,10 @@ sctp_generic_sendmsg (td, uap)
iov[0].iov_len = uap->mlen;
so = (struct socket *)fp->f_data;
+ if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
+ error = EOPNOTSUPP;
+ goto sctp_bad;
+ }
#ifdef MAC
error = mac_socket_check_send(td->td_ucred, so);
if (error)
@@ -3011,6 +3017,10 @@ sctp_generic_sendmsg_iov(td, uap)
#endif
so = (struct socket *)fp->f_data;
+ if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
+ error = EOPNOTSUPP;
+ goto sctp_bad;
+ }
#ifdef MAC
error = mac_socket_check_send(td->td_ucred, so);
if (error)
@@ -3115,6 +3125,10 @@ sctp_generic_recvmsg(td, uap)
goto out1;
so = fp->f_data;
+ if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
+ error = EOPNOTSUPP;
+ goto out;
+ }
#ifdef MAC
error = mac_socket_check_receive(td->td_ucred, so);
if (error) {
diff --git a/freebsd/sys/lm32/include/machine/legacyvar.h b/freebsd/sys/lm32/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/lm32/include/machine/legacyvar.h
+++ b/freebsd/sys/lm32/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/lm32/lm32/legacy.c b/freebsd/sys/lm32/lm32/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/lm32/lm32/legacy.c
+++ b/freebsd/sys/lm32/lm32/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/lm32/pci/pci_bus.c b/freebsd/sys/lm32/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/lm32/pci/pci_bus.c
+++ b/freebsd/sys/lm32/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/m32c/include/machine/legacyvar.h b/freebsd/sys/m32c/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/m32c/include/machine/legacyvar.h
+++ b/freebsd/sys/m32c/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/m32c/m32c/legacy.c b/freebsd/sys/m32c/m32c/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/m32c/m32c/legacy.c
+++ b/freebsd/sys/m32c/m32c/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/m32c/pci/pci_bus.c b/freebsd/sys/m32c/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/m32c/pci/pci_bus.c
+++ b/freebsd/sys/m32c/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/m32r/include/machine/legacyvar.h b/freebsd/sys/m32r/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/m32r/include/machine/legacyvar.h
+++ b/freebsd/sys/m32r/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/m32r/m32r/legacy.c b/freebsd/sys/m32r/m32r/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/m32r/m32r/legacy.c
+++ b/freebsd/sys/m32r/m32r/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/m32r/pci/pci_bus.c b/freebsd/sys/m32r/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/m32r/pci/pci_bus.c
+++ b/freebsd/sys/m32r/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/m68k/include/machine/legacyvar.h b/freebsd/sys/m68k/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/m68k/include/machine/legacyvar.h
+++ b/freebsd/sys/m68k/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/m68k/m68k/legacy.c b/freebsd/sys/m68k/m68k/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/m68k/m68k/legacy.c
+++ b/freebsd/sys/m68k/m68k/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/m68k/pci/pci_bus.c b/freebsd/sys/m68k/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/m68k/pci/pci_bus.c
+++ b/freebsd/sys/m68k/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/mips/include/machine/legacyvar.h b/freebsd/sys/mips/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/mips/include/machine/legacyvar.h
+++ b/freebsd/sys/mips/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/mips/mips/legacy.c b/freebsd/sys/mips/mips/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/mips/mips/legacy.c
+++ b/freebsd/sys/mips/mips/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/mips/pci/pci_bus.c b/freebsd/sys/mips/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/mips/pci/pci_bus.c
+++ b/freebsd/sys/mips/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/net/bpf.c b/freebsd/sys/net/bpf.c
index d9223313..179d5f0a 100644
--- a/freebsd/sys/net/bpf.c
+++ b/freebsd/sys/net/bpf.c
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/types.h>
#include <rtems/bsd/sys/param.h>
+#include <rtems/bsd/sys/lock.h>
+#include <sys/rwlock.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
@@ -68,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#define BPF_INTERNAL
#include <net/bpf.h>
#include <net/bpf_buffer.h>
#ifdef BPF_JITTER
@@ -141,6 +144,7 @@ static int bpf_bpfd_cnt;
static void bpf_attachd(struct bpf_d *, struct bpf_if *);
static void bpf_detachd(struct bpf_d *);
+static void bpf_detachd_locked(struct bpf_d *);
static void bpf_freed(struct bpf_d *);
static int bpf_movein(struct uio *, int, struct ifnet *, struct mbuf **,
struct sockaddr *, int *, struct bpf_insn *);
@@ -152,7 +156,7 @@ static void catchpacket(struct bpf_d *, u_char *, u_int, u_int,
void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int),
struct timeval *);
static void reset_d(struct bpf_d *);
-static int bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
+static int bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
static int bpf_setdlt(struct bpf_d *, u_int);
static void filt_bpfdetach(struct knote *);
@@ -170,6 +174,12 @@ SYSCTL_INT(_net_bpf, OID_AUTO, zerocopy_enable, CTLFLAG_RW,
SYSCTL_NODE(_net_bpf, OID_AUTO, stats, CTLFLAG_MPSAFE | CTLFLAG_RW,
bpf_stats_sysctl, "bpf statistics portal");
+static VNET_DEFINE(int, bpf_optimize_writers) = 0;
+#define V_bpf_optimize_writers VNET(bpf_optimize_writers)
+SYSCTL_VNET_INT(_net_bpf, OID_AUTO, optimize_writers,
+ CTLFLAG_RW, &VNET_NAME(bpf_optimize_writers), 0,
+ "Do not send packets until BPF program is set");
+
static d_open_t bpfopen;
static d_read_t bpfread;
static d_write_t bpfwrite;
@@ -191,6 +201,37 @@ static struct cdevsw bpf_cdevsw = {
static struct filterops bpfread_filtops =
{ 1, NULL, filt_bpfdetach, filt_bpfread };
+eventhandler_tag bpf_ifdetach_cookie = NULL;
+
+/*
+ * LOCKING MODEL USED BY BPF:
+ * Locks:
+ * 1) global lock (BPF_LOCK). Mutex, used to protect interface addition/removal,
+ * some global counters and every bpf_if reference.
+ * 2) Interface lock. Rwlock, used to protect list of BPF descriptors and their filters.
+ * 3) Descriptor lock. Mutex, used to protect BPF buffers and various structure fields
+ * used by bpf_mtap code.
+ *
+ * Lock order:
+ *
+ * Global lock, interface lock, descriptor lock
+ *
+ * We have to acquire interface lock before descriptor main lock due to BPF_MTAP[2]
+ * working model. In many places (like bpf_detachd) we start with BPF descriptor
+ * (and we need to at least rlock it to get reliable interface pointer). This
+ * gives us potential LOR. As a result, we use global lock to protect from bpf_if
+ * change in every such place.
+ *
+ * Changing d->bd_bif is protected by 1) global lock, 2) interface lock and
+ * 3) descriptor main wlock.
+ * Reading bd_bif can be protected by any of these locks, typically global lock.
+ *
+ * Changing read/write BPF filter is protected by the same three locks,
+ * the same applies for reading.
+ *
+ * Sleeping in global lock is not allowed due to bpfdetach() using it.
+ */
+
/*
* Wrapper functions for various buffering methods. If the set of buffer
* modes expands, we will probably want to introduce a switch data structure
@@ -284,7 +325,6 @@ bpf_canfreebuf(struct bpf_d *d)
static int
bpf_canwritebuf(struct bpf_d *d)
{
-
BPFD_LOCK_ASSERT(d);
switch (d->bd_bufmode) {
@@ -563,17 +603,92 @@ bad:
static void
bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
{
+ int op_w;
+
+ BPF_LOCK_ASSERT();
+
+ /*
+ * Save sysctl value to protect from sysctl change
+ * between reads
+ */
+ op_w = V_bpf_optimize_writers;
+
+ if (d->bd_bif != NULL)
+ bpf_detachd_locked(d);
/*
- * Point d at bp, and add d to the interface's list of listeners.
- * Finally, point the driver's bpf cookie at the interface so
- * it will divert packets to bpf.
+ * Point d at bp, and add d to the interface's list.
+ * Since there are many applicaiotns using BPF for
+ * sending raw packets only (dhcpd, cdpd are good examples)
+ * we can delay adding d to the list of active listeners until
+ * some filter is configured.
*/
- BPFIF_LOCK(bp);
+
+ BPFIF_WLOCK(bp);
+ BPFD_LOCK(d);
+
d->bd_bif = bp;
- LIST_INSERT_HEAD(&bp->bif_dlist, d, bd_next);
+
+ if (op_w != 0) {
+ /* Add to writers-only list */
+ LIST_INSERT_HEAD(&bp->bif_wlist, d, bd_next);
+ /*
+ * We decrement bd_writer on every filter set operation.
+ * First BIOCSETF is done by pcap_open_live() to set up
+ * snap length. After that appliation usually sets its own filter
+ */
+ d->bd_writer = 2;
+ } else
+ LIST_INSERT_HEAD(&bp->bif_dlist, d, bd_next);
+
+ BPFD_UNLOCK(d);
+ BPFIF_WUNLOCK(bp);
bpf_bpfd_cnt++;
- BPFIF_UNLOCK(bp);
+
+ CTR3(KTR_NET, "%s: bpf_attach called by pid %d, adding to %s list",
+ __func__, d->bd_pid, d->bd_writer ? "writer" : "active");
+
+ if (op_w == 0)
+ EVENTHANDLER_INVOKE(bpf_track, bp->bif_ifp, bp->bif_dlt, 1);
+}
+
+/*
+ * Add d to the list of active bp filters.
+ * Reuqires bpf_attachd() to be called before
+ */
+static void
+bpf_upgraded(struct bpf_d *d)
+{
+ struct bpf_if *bp;
+
+ BPF_LOCK_ASSERT();
+
+ bp = d->bd_bif;
+
+ /*
+ * Filter can be set several times without specifying interface.
+ * Mark d as reader and exit.
+ */
+ if (bp == NULL) {
+ BPFD_LOCK(d);
+ d->bd_writer = 0;
+ BPFD_UNLOCK(d);
+ return;
+ }
+
+ BPFIF_WLOCK(bp);
+ BPFD_LOCK(d);
+
+ /* Remove from writers-only list */
+ LIST_REMOVE(d, bd_next);
+ LIST_INSERT_HEAD(&bp->bif_dlist, d, bd_next);
+ /* Mark d as reader */
+ d->bd_writer = 0;
+
+ BPFD_UNLOCK(d);
+ BPFIF_WUNLOCK(bp);
+
+ CTR2(KTR_NET, "%s: upgrade required by pid %d", __func__, d->bd_pid);
EVENTHANDLER_INVOKE(bpf_track, bp->bif_ifp, bp->bif_dlt, 1);
}
@@ -584,26 +699,47 @@ bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
static void
bpf_detachd(struct bpf_d *d)
{
+ BPF_LOCK();
+ bpf_detachd_locked(d);
+ BPF_UNLOCK();
+}
+
+static void
+bpf_detachd_locked(struct bpf_d *d)
+{
int error;
struct bpf_if *bp;
struct ifnet *ifp;
- bp = d->bd_bif;
- BPFIF_LOCK(bp);
+ CTR2(KTR_NET, "%s: detach required by pid %d", __func__, d->bd_pid);
+
+ BPF_LOCK_ASSERT();
+
+ /* Check if descriptor is attached */
+ if ((bp = d->bd_bif) == NULL)
+ return;
+
+ BPFIF_WLOCK(bp);
BPFD_LOCK(d);
- ifp = d->bd_bif->bif_ifp;
+
+ /* Save bd_writer value */
+ error = d->bd_writer;
/*
* Remove d from the interface's descriptor list.
*/
LIST_REMOVE(d, bd_next);
- bpf_bpfd_cnt--;
+ ifp = bp->bif_ifp;
d->bd_bif = NULL;
BPFD_UNLOCK(d);
- BPFIF_UNLOCK(bp);
+ BPFIF_WUNLOCK(bp);
+
+ bpf_bpfd_cnt--;
- EVENTHANDLER_INVOKE(bpf_track, ifp, bp->bif_dlt, 0);
+ /* Call event handler iff d is attached */
+ if (error == 0)
+ EVENTHANDLER_INVOKE(bpf_track, ifp, bp->bif_dlt, 0);
/*
* Check if this descriptor had requested promiscuous mode.
@@ -642,14 +778,11 @@ bpf_dtor(void *data)
d->bd_state = BPF_IDLE;
BPFD_UNLOCK(d);
funsetown(&d->bd_sigio);
- mtx_lock(&bpf_mtx);
- if (d->bd_bif)
- bpf_detachd(d);
- mtx_unlock(&bpf_mtx);
- selwakeuppri(&d->bd_sel, PRINET);
+ bpf_detachd(d);
#ifdef MAC
mac_bpfdesc_destroy(d);
#endif /* MAC */
+ seldrain(&d->bd_sel);
knlist_destroy(&d->bd_sel.si_note);
callout_drain(&d->bd_callout);
bpf_freed(d);
@@ -665,7 +798,7 @@ static int
bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
struct bpf_d *d;
- int error;
+ int error, size;
d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
error = devfs_set_cdevpriv(d, bpf_dtor);
@@ -683,14 +816,18 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
d->bd_bufmode = BPF_BUFMODE_BUFFER;
d->bd_sig = SIGIO;
d->bd_direction = BPF_D_INOUT;
- d->bd_pid = td->td_proc->p_pid;
+ BPF_PID_REFRESH(d, td);
#ifdef MAC
mac_bpfdesc_init(d);
mac_bpfdesc_create(td->td_ucred, d);
#endif
- mtx_init(&d->bd_mtx, devtoname(dev), "bpf cdev lock", MTX_DEF);
- callout_init_mtx(&d->bd_callout, &d->bd_mtx, 0);
- knlist_init_mtx(&d->bd_sel.si_note, &d->bd_mtx);
+ mtx_init(&d->bd_lock, devtoname(dev), "bpf cdev lock", MTX_DEF);
+ callout_init_mtx(&d->bd_callout, &d->bd_lock, 0);
+ knlist_init_mtx(&d->bd_sel.si_note, &d->bd_lock);
+
+ /* Allocate default buffers */
+ size = d->bd_bufsize;
+ bpf_buffer_ioctl_sblen(d, &size);
return (0);
}
@@ -720,7 +857,7 @@ bpfread(struct cdev *dev, struct uio *uio, int ioflag)
non_block = ((ioflag & O_NONBLOCK) != 0);
BPFD_LOCK(d);
- d->bd_pid = curthread->td_proc->p_pid;
+ BPF_PID_REFRESH_CUR(d);
if (d->bd_bufmode != BPF_BUFMODE_BUFFER) {
BPFD_UNLOCK(d);
return (EOPNOTSUPP);
@@ -766,7 +903,7 @@ bpfread(struct cdev *dev, struct uio *uio, int ioflag)
BPFD_UNLOCK(d);
return (EWOULDBLOCK);
}
- error = msleep(d, &d->bd_mtx, PRINET|PCATCH,
+ error = msleep(d, &d->bd_lock, PRINET|PCATCH,
"bpf", d->bd_rtout);
if (error == EINTR || error == ERESTART) {
BPFD_UNLOCK(d);
@@ -883,8 +1020,9 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag)
if (error != 0)
return (error);
- d->bd_pid = curthread->td_proc->p_pid;
+ BPF_PID_REFRESH_CUR(d);
d->bd_wcount++;
+ /* XXX: locking required */
if (d->bd_bif == NULL) {
d->bd_wdcount++;
return (ENXIO);
@@ -905,6 +1043,7 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag)
bzero(&dst, sizeof(dst));
m = NULL;
hlen = 0;
+ /* XXX: bpf_movein() can sleep */
error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, ifp,
&m, &dst, &hlen, d->bd_wfilter);
if (error) {
@@ -964,7 +1103,7 @@ static void
reset_d(struct bpf_d *d)
{
- mtx_assert(&d->bd_mtx, MA_OWNED);
+ BPFD_LOCK_ASSERT(d);
if ((d->bd_hbuf != NULL) &&
(d->bd_bufmode != BPF_BUFMODE_ZBUF || bpf_canfreebuf(d))) {
@@ -1030,7 +1169,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Refresh PID associated with this descriptor.
*/
BPFD_LOCK(d);
- d->bd_pid = td->td_proc->p_pid;
+ BPF_PID_REFRESH(d, td);
if (d->bd_state == BPF_WAITING)
callout_stop(&d->bd_callout);
d->bd_state = BPF_IDLE;
@@ -1081,7 +1220,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case BIOCGDLTLIST32:
case BIOCGRTIMEOUT32:
case BIOCSRTIMEOUT32:
+ BPFD_LOCK(d);
d->bd_compat32 = 1;
+ BPFD_UNLOCK(d);
}
#endif
@@ -1126,7 +1267,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get buffer len [for read()].
*/
case BIOCGBLEN:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_bufsize;
+ BPFD_UNLOCK(d);
break;
/*
@@ -1181,10 +1324,12 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get current data link type.
*/
case BIOCGDLT:
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else
*(u_int *)addr = d->bd_bif->bif_dlt;
+ BPF_UNLOCK();
break;
/*
@@ -1199,6 +1344,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
list32 = (struct bpf_dltlist32 *)addr;
dltlist.bfl_len = list32->bfl_len;
dltlist.bfl_list = PTRIN(list32->bfl_list);
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else {
@@ -1206,31 +1352,37 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
if (error == 0)
list32->bfl_len = dltlist.bfl_len;
}
+ BPF_UNLOCK();
break;
}
#endif
case BIOCGDLTLIST:
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else
error = bpf_getdltlist(d, (struct bpf_dltlist *)addr);
+ BPF_UNLOCK();
break;
/*
* Set data link type.
*/
case BIOCSDLT:
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else
error = bpf_setdlt(d, *(u_int *)addr);
+ BPF_UNLOCK();
break;
/*
* Get interface name.
*/
case BIOCGETIF:
+ BPF_LOCK();
if (d->bd_bif == NULL)
error = EINVAL;
else {
@@ -1240,13 +1392,16 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
strlcpy(ifr->ifr_name, ifp->if_xname,
sizeof(ifr->ifr_name));
}
+ BPF_UNLOCK();
break;
/*
* Set interface.
*/
case BIOCSETIF:
+ BPF_LOCK();
error = bpf_setif(d, (struct ifreq *)addr);
+ BPF_UNLOCK();
break;
/*
@@ -1329,7 +1484,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Set immediate mode.
*/
case BIOCIMMEDIATE:
+ BPFD_LOCK(d);
d->bd_immediate = *(u_int *)addr;
+ BPFD_UNLOCK(d);
break;
case BIOCVERSION:
@@ -1345,21 +1502,27 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get "header already complete" flag
*/
case BIOCGHDRCMPLT:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_hdrcmplt;
+ BPFD_UNLOCK(d);
break;
/*
* Set "header already complete" flag
*/
case BIOCSHDRCMPLT:
+ BPFD_LOCK(d);
d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0;
+ BPFD_UNLOCK(d);
break;
/*
* Get packet direction flag
*/
case BIOCGDIRECTION:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_direction;
+ BPFD_UNLOCK(d);
break;
/*
@@ -1374,7 +1537,9 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case BPF_D_IN:
case BPF_D_INOUT:
case BPF_D_OUT:
+ BPFD_LOCK(d);
d->bd_direction = direction;
+ BPFD_UNLOCK(d);
break;
default:
error = EINVAL;
@@ -1383,26 +1548,38 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
break;
case BIOCFEEDBACK:
+ BPFD_LOCK(d);
d->bd_feedback = *(u_int *)addr;
+ BPFD_UNLOCK(d);
break;
case BIOCLOCK:
+ BPFD_LOCK(d);
d->bd_locked = 1;
+ BPFD_UNLOCK(d);
break;
case FIONBIO: /* Non-blocking I/O */
break;
case FIOASYNC: /* Send signal on receive packets */
+ BPFD_LOCK(d);
d->bd_async = *(int *)addr;
+ BPFD_UNLOCK(d);
break;
case FIOSETOWN:
+ /*
+ * XXX: Add some sort of locking here?
+ * fsetown() can sleep.
+ */
error = fsetown(*(int *)addr, &d->bd_sigio);
break;
case FIOGETOWN:
+ BPFD_LOCK(d);
*(int *)addr = fgetown(&d->bd_sigio);
+ BPFD_UNLOCK(d);
break;
/* This is deprecated, FIOSETOWN should be used instead. */
@@ -1423,16 +1600,23 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
if (sig >= NSIG)
error = EINVAL;
- else
+ else {
+ BPFD_LOCK(d);
d->bd_sig = sig;
+ BPFD_UNLOCK(d);
+ }
break;
}
case BIOCGRSIG:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_sig;
+ BPFD_UNLOCK(d);
break;
case BIOCGETBUFMODE:
+ BPFD_LOCK(d);
*(u_int *)addr = d->bd_bufmode;
+ BPFD_UNLOCK(d);
break;
case BIOCSETBUFMODE:
@@ -1487,95 +1671,130 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
/*
* Set d's packet filter program to fp. If this file already has a filter,
* free it and replace it. Returns EINVAL for bogus requests.
+ *
+ * Note we need global lock here to serialize bpf_setf() and bpf_setif() calls
+ * since reading d->bd_bif can't be protected by d or interface lock due to
+ * lock order.
+ *
+ * Additionally, we have to acquire interface write lock due to bpf_mtap() uses
+ * interface read lock to read all filers.
+ *
*/
static int
bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
{
+#ifdef COMPAT_FREEBSD32
+ struct bpf_program fp_swab;
+ struct bpf_program32 *fp32;
+#endif
struct bpf_insn *fcode, *old;
- u_int wfilter, flen, size;
#ifdef BPF_JITTER
- bpf_jit_filter *ofunc;
+ bpf_jit_filter *jfunc, *ofunc;
#endif
-#ifdef COMPAT_FREEBSD32
- struct bpf_program32 *fp32;
- struct bpf_program fp_swab;
+ size_t size;
+ u_int flen;
+ int need_upgrade;
- if (cmd == BIOCSETWF32 || cmd == BIOCSETF32 || cmd == BIOCSETFNR32) {
+#ifdef COMPAT_FREEBSD32
+ switch (cmd) {
+ case BIOCSETF32:
+ case BIOCSETWF32:
+ case BIOCSETFNR32:
fp32 = (struct bpf_program32 *)fp;
fp_swab.bf_len = fp32->bf_len;
fp_swab.bf_insns = (struct bpf_insn *)(uintptr_t)fp32->bf_insns;
fp = &fp_swab;
- if (cmd == BIOCSETWF32)
+ switch (cmd) {
+ case BIOCSETF32:
+ cmd = BIOCSETF;
+ break;
+ case BIOCSETWF32:
cmd = BIOCSETWF;
+ break;
+ }
+ break;
}
#endif
- if (cmd == BIOCSETWF) {
- old = d->bd_wfilter;
- wfilter = 1;
-#ifdef BPF_JITTER
- ofunc = NULL;
-#endif
- } else {
- wfilter = 0;
- old = d->bd_rfilter;
+
+ fcode = NULL;
#ifdef BPF_JITTER
- ofunc = d->bd_bfilter;
+ jfunc = ofunc = NULL;
#endif
- }
- if (fp->bf_insns == NULL) {
- if (fp->bf_len != 0)
+ need_upgrade = 0;
+
+ /*
+ * Check new filter validness before acquiring any locks.
+ * Allocate memory for new filter, if needed.
+ */
+ flen = fp->bf_len;
+ if (flen > bpf_maxinsns || (fp->bf_insns == NULL && flen != 0))
+ return (EINVAL);
+ size = flen * sizeof(*fp->bf_insns);
+ if (size > 0) {
+ /* We're setting up new filter. Copy and check actual data. */
+ fcode = malloc(size, M_BPF, M_WAITOK);
+ if (copyin(fp->bf_insns, fcode, size) != 0 ||
+ !bpf_validate(fcode, flen)) {
+ free(fcode, M_BPF);
return (EINVAL);
- BPFD_LOCK(d);
- if (wfilter)
- d->bd_wfilter = NULL;
- else {
- d->bd_rfilter = NULL;
-#ifdef BPF_JITTER
- d->bd_bfilter = NULL;
-#endif
- if (cmd == BIOCSETF)
- reset_d(d);
}
- BPFD_UNLOCK(d);
- if (old != NULL)
- free((caddr_t)old, M_BPF);
#ifdef BPF_JITTER
- if (ofunc != NULL)
- bpf_destroy_jit_filter(ofunc);
+ /* Filter is copied inside fcode and is perfectly valid. */
+ jfunc = bpf_jitter(fcode, flen);
#endif
- return (0);
}
- flen = fp->bf_len;
- if (flen > bpf_maxinsns)
- return (EINVAL);
- size = flen * sizeof(*fp->bf_insns);
- fcode = (struct bpf_insn *)malloc(size, M_BPF, M_WAITOK);
- if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
- bpf_validate(fcode, (int)flen)) {
- BPFD_LOCK(d);
- if (wfilter)
- d->bd_wfilter = fcode;
- else {
- d->bd_rfilter = fcode;
+ BPF_LOCK();
+
+ /*
+ * Set up new filter.
+ * Protect filter change by interface lock.
+ * Additionally, we are protected by global lock here.
+ */
+ if (d->bd_bif != NULL)
+ BPFIF_WLOCK(d->bd_bif);
+ BPFD_LOCK(d);
+ if (cmd == BIOCSETWF) {
+ old = d->bd_wfilter;
+ d->bd_wfilter = fcode;
+ } else {
+ old = d->bd_rfilter;
+ d->bd_rfilter = fcode;
#ifdef BPF_JITTER
- d->bd_bfilter = bpf_jitter(fcode, flen);
+ ofunc = d->bd_bfilter;
+ d->bd_bfilter = jfunc;
#endif
- if (cmd == BIOCSETF)
- reset_d(d);
+ if (cmd == BIOCSETF)
+ reset_d(d);
+
+ if (fcode != NULL) {
+ /*
+ * Do not require upgrade by first BIOCSETF
+ * (used to set snaplen) by pcap_open_live().
+ */
+ if (d->bd_writer != 0 && --d->bd_writer == 0)
+ need_upgrade = 1;
+ CTR4(KTR_NET, "%s: filter function set by pid %d, "
+ "bd_writer counter %d, need_upgrade %d",
+ __func__, d->bd_pid, d->bd_writer, need_upgrade);
}
- BPFD_UNLOCK(d);
- if (old != NULL)
- free((caddr_t)old, M_BPF);
+ }
+ BPFD_UNLOCK(d);
+ if (d->bd_bif != NULL)
+ BPFIF_WUNLOCK(d->bd_bif);
+ if (old != NULL)
+ free(old, M_BPF);
#ifdef BPF_JITTER
- if (ofunc != NULL)
- bpf_destroy_jit_filter(ofunc);
+ if (ofunc != NULL)
+ bpf_destroy_jit_filter(ofunc);
#endif
- return (0);
- }
- free((caddr_t)fcode, M_BPF);
- return (EINVAL);
+ /* Move d to active readers list. */
+ if (need_upgrade)
+ bpf_upgraded(d);
+
+ BPF_UNLOCK();
+ return (0);
}
/*
@@ -1589,28 +1808,30 @@ bpf_setif(struct bpf_d *d, struct ifreq *ifr)
struct bpf_if *bp;
struct ifnet *theywant;
+ BPF_LOCK_ASSERT();
+
theywant = ifunit(ifr->ifr_name);
if (theywant == NULL || theywant->if_bpf == NULL)
return (ENXIO);
bp = theywant->if_bpf;
+ /* Check if interface is not being detached from BPF */
+ BPFIF_RLOCK(bp);
+ if (bp->flags & BPFIF_FLAG_DYING) {
+ BPFIF_RUNLOCK(bp);
+ return (ENXIO);
+ }
+ BPFIF_RUNLOCK(bp);
+
/*
* Behavior here depends on the buffering model. If we're using
* kernel memory buffers, then we can allocate them here. If we're
* using zero-copy, then the user process must have registered
* buffers by the time we get here. If not, return an error.
- *
- * XXXRW: There are locking issues here with multi-threaded use: what
- * if two threads try to set the interface at once?
*/
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
- if (d->bd_sbuf == NULL)
- bpf_buffer_alloc(d);
- KASSERT(d->bd_sbuf != NULL, ("bpf_setif: bd_sbuf NULL"));
- break;
-
case BPF_BUFMODE_ZBUF:
if (d->bd_sbuf == NULL)
return (EINVAL);
@@ -1619,15 +1840,8 @@ bpf_setif(struct bpf_d *d, struct ifreq *ifr)
default:
panic("bpf_setif: bufmode %d", d->bd_bufmode);
}
- if (bp != d->bd_bif) {
- if (d->bd_bif)
- /*
- * Detach if attached to something else.
- */
- bpf_detachd(d);
-
+ if (bp != d->bd_bif)
bpf_attachd(d, bp);
- }
BPFD_LOCK(d);
reset_d(d);
BPFD_UNLOCK(d);
@@ -1655,7 +1869,7 @@ bpfpoll(struct cdev *dev, int events, struct thread *td)
*/
revents = events & (POLLOUT | POLLWRNORM);
BPFD_LOCK(d);
- d->bd_pid = td->td_proc->p_pid;
+ BPF_PID_REFRESH(d, td);
if (events & (POLLIN | POLLRDNORM)) {
if (bpf_ready(d))
revents |= events & (POLLIN | POLLRDNORM);
@@ -1690,7 +1904,7 @@ bpfkqfilter(struct cdev *dev, struct knote *kn)
* Refresh PID associated with this descriptor.
*/
BPFD_LOCK(d);
- d->bd_pid = curthread->td_proc->p_pid;
+ BPF_PID_REFRESH_CUR(d);
kn->kn_fop = &bpfread_filtops;
kn->kn_hook = d;
knlist_add(&d->bd_sel.si_note, kn, 1);
@@ -1746,9 +1960,19 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
struct timeval tv;
gottime = 0;
- BPFIF_LOCK(bp);
+
+ BPFIF_RLOCK(bp);
+
LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
- BPFD_LOCK(d);
+ /*
+ * We are not using any locks for d here because:
+ * 1) any filter change is protected by interface
+ * write lock
+ * 2) destroying/detaching d is protected by interface
+ * write lock, too
+ */
+
+ /* XXX: Do not protect counter for the sake of performance. */
++d->bd_rcount;
/*
* NB: We dont call BPF_CHECK_DIRECTION() here since there is no
@@ -1764,6 +1988,11 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
#endif
slen = bpf_filter(d->bd_rfilter, pkt, pktlen, pktlen);
if (slen != 0) {
+ /*
+ * Filter matches. Let's to acquire write lock.
+ */
+ BPFD_LOCK(d);
+
d->bd_fcount++;
if (!gottime) {
microtime(&tv);
@@ -1774,10 +2003,10 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
#endif
catchpacket(d, pkt, pktlen, slen,
bpf_append_bytes, &tv);
+ BPFD_UNLOCK(d);
}
- BPFD_UNLOCK(d);
}
- BPFIF_UNLOCK(bp);
+ BPFIF_RUNLOCK(bp);
}
#define BPF_CHECK_DIRECTION(d, r, i) \
@@ -1786,6 +2015,7 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
/*
* Incoming linkage from device drivers, when packet is in an mbuf chain.
+ * Locking model is explained in bpf_tap().
*/
void
bpf_mtap(struct bpf_if *bp, struct mbuf *m)
@@ -1808,11 +2038,11 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m)
pktlen = m_length(m, NULL);
- BPFIF_LOCK(bp);
+ BPFIF_RLOCK(bp);
+
LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp))
continue;
- BPFD_LOCK(d);
++d->bd_rcount;
#ifdef BPF_JITTER
bf = bpf_jitter_enable != 0 ? d->bd_bfilter : NULL;
@@ -1823,6 +2053,8 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m)
#endif
slen = bpf_filter(d->bd_rfilter, (u_char *)m, pktlen, 0);
if (slen != 0) {
+ BPFD_LOCK(d);
+
d->bd_fcount++;
if (!gottime) {
microtime(&tv);
@@ -1833,10 +2065,10 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m)
#endif
catchpacket(d, (u_char *)m, pktlen, slen,
bpf_append_mbuf, &tv);
+ BPFD_UNLOCK(d);
}
- BPFD_UNLOCK(d);
}
- BPFIF_UNLOCK(bp);
+ BPFIF_RUNLOCK(bp);
}
/*
@@ -1871,14 +2103,17 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
mb.m_len = dlen;
pktlen += dlen;
- BPFIF_LOCK(bp);
+
+ BPFIF_RLOCK(bp);
+
LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp))
continue;
- BPFD_LOCK(d);
++d->bd_rcount;
slen = bpf_filter(d->bd_rfilter, (u_char *)&mb, pktlen, 0);
if (slen != 0) {
+ BPFD_LOCK(d);
+
d->bd_fcount++;
if (!gottime) {
microtime(&tv);
@@ -1889,10 +2124,10 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
#endif
catchpacket(d, (u_char *)&mb, pktlen, slen,
bpf_append_mbuf, &tv);
+ BPFD_UNLOCK(d);
}
- BPFD_UNLOCK(d);
}
- BPFIF_UNLOCK(bp);
+ BPFIF_RUNLOCK(bp);
}
#undef BPF_CHECK_DIRECTION
@@ -2042,7 +2277,7 @@ bpf_freed(struct bpf_d *d)
}
if (d->bd_wfilter != NULL)
free((caddr_t)d->bd_wfilter, M_BPF);
- mtx_destroy(&d->bd_mtx);
+ mtx_destroy(&d->bd_lock);
}
/*
@@ -2072,15 +2307,16 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
panic("bpfattach");
LIST_INIT(&bp->bif_dlist);
+ LIST_INIT(&bp->bif_wlist);
bp->bif_ifp = ifp;
bp->bif_dlt = dlt;
- mtx_init(&bp->bif_mtx, "bpf interface lock", NULL, MTX_DEF);
+ rw_init(&bp->bif_lock, "bpf interface lock");
KASSERT(*driverp == NULL, ("bpfattach2: driverp already initialized"));
*driverp = bp;
- mtx_lock(&bpf_mtx);
+ BPF_LOCK();
LIST_INSERT_HEAD(&bpf_iflist, bp, bif_next);
- mtx_unlock(&bpf_mtx);
+ BPF_UNLOCK();
/*
* Compute the length of the bpf header. This is not necessarily
@@ -2095,42 +2331,95 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
}
/*
- * Detach bpf from an interface. This involves detaching each descriptor
- * associated with the interface, and leaving bd_bif NULL. Notify each
- * descriptor as it's detached so that any sleepers wake up and get
- * ENXIO.
+ * Detach bpf from an interface. This involves detaching each descriptor
+ * associated with the interface. Notify each descriptor as it's detached
+ * so that any sleepers wake up and get ENXIO.
*/
void
bpfdetach(struct ifnet *ifp)
{
struct bpf_if *bp;
struct bpf_d *d;
+#ifdef INVARIANTS
+ int ndetached;
- /* Locate BPF interface information */
- mtx_lock(&bpf_mtx);
- LIST_FOREACH(bp, &bpf_iflist, bif_next) {
- if (ifp == bp->bif_ifp)
- break;
- }
+ ndetached = 0;
+#endif
+
+ BPF_LOCK();
+ /* Find all bpf_if struct's which reference ifp and detach them. */
+ do {
+ LIST_FOREACH(bp, &bpf_iflist, bif_next) {
+ if (ifp == bp->bif_ifp)
+ break;
+ }
+ if (bp != NULL)
+ LIST_REMOVE(bp, bif_next);
+
+ if (bp != NULL) {
+#ifdef INVARIANTS
+ ndetached++;
+#endif
+ while ((d = LIST_FIRST(&bp->bif_dlist)) != NULL) {
+ bpf_detachd_locked(d);
+ BPFD_LOCK(d);
+ bpf_wakeup(d);
+ BPFD_UNLOCK(d);
+ }
+ /* Free writer-only descriptors */
+ while ((d = LIST_FIRST(&bp->bif_wlist)) != NULL) {
+ bpf_detachd_locked(d);
+ BPFD_LOCK(d);
+ bpf_wakeup(d);
+ BPFD_UNLOCK(d);
+ }
+
+ /*
+ * Delay freing bp till interface is detached
+ * and all routes through this interface are removed.
+ * Mark bp as detached to restrict new consumers.
+ */
+ BPFIF_WLOCK(bp);
+ bp->flags |= BPFIF_FLAG_DYING;
+ BPFIF_WUNLOCK(bp);
+ }
+ } while (bp != NULL);
+ BPF_UNLOCK();
- /* Interface wasn't attached */
- if ((bp == NULL) || (bp->bif_ifp == NULL)) {
- mtx_unlock(&bpf_mtx);
+#ifdef INVARIANTS
+ if (ndetached == 0)
printf("bpfdetach: %s was not attached\n", ifp->if_xname);
+#endif
+}
+
+/*
+ * Interface departure handler.
+ * Note departure event does not guarantee interface is going down.
+ */
+static void
+bpf_ifdetach(void *arg __unused, struct ifnet *ifp)
+{
+ struct bpf_if *bp;
+
+ BPF_LOCK();
+ if ((bp = ifp->if_bpf) == NULL) {
+ BPF_UNLOCK();
return;
}
- LIST_REMOVE(bp, bif_next);
- mtx_unlock(&bpf_mtx);
-
- while ((d = LIST_FIRST(&bp->bif_dlist)) != NULL) {
- bpf_detachd(d);
- BPFD_LOCK(d);
- bpf_wakeup(d);
- BPFD_UNLOCK(d);
+ /* Check if bpfdetach() was called previously */
+ if ((bp->flags & BPFIF_FLAG_DYING) == 0) {
+ BPF_UNLOCK();
+ return;
}
- mtx_destroy(&bp->bif_mtx);
+ CTR3(KTR_NET, "%s: freing BPF instance %p for interface %p",
+ __func__, bp, ifp);
+
+ ifp->if_bpf = NULL;
+ BPF_UNLOCK();
+
+ rw_destroy(&bp->bif_lock);
free(bp, M_BPF);
}
@@ -2144,24 +2433,22 @@ bpf_getdltlist(struct bpf_d *d, struct bpf_dltlist *bfl)
struct ifnet *ifp;
struct bpf_if *bp;
+ BPF_LOCK_ASSERT();
+
ifp = d->bd_bif->bif_ifp;
n = 0;
error = 0;
- mtx_lock(&bpf_mtx);
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
if (bp->bif_ifp != ifp)
continue;
if (bfl->bfl_list != NULL) {
- if (n >= bfl->bfl_len) {
- mtx_unlock(&bpf_mtx);
+ if (n >= bfl->bfl_len)
return (ENOMEM);
- }
error = copyout(&bp->bif_dlt,
bfl->bfl_list + n, sizeof(u_int));
}
n++;
}
- mtx_unlock(&bpf_mtx);
bfl->bfl_len = n;
return (error);
}
@@ -2176,18 +2463,19 @@ bpf_setdlt(struct bpf_d *d, u_int dlt)
struct ifnet *ifp;
struct bpf_if *bp;
+ BPF_LOCK_ASSERT();
+
if (d->bd_bif->bif_dlt == dlt)
return (0);
ifp = d->bd_bif->bif_ifp;
- mtx_lock(&bpf_mtx);
+
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
if (bp->bif_ifp == ifp && bp->bif_dlt == dlt)
break;
}
- mtx_unlock(&bpf_mtx);
+
if (bp != NULL) {
opromisc = d->bd_promisc;
- bpf_detachd(d);
bpf_attachd(d, bp);
BPFD_LOCK(d);
reset_d(d);
@@ -2216,6 +2504,11 @@ bpf_drvinit(void *unused)
dev = make_dev(&bpf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "bpf");
/* For compatibility */
make_dev_alias(dev, "bpf0");
+
+ /* Register interface departure handler */
+ bpf_ifdetach_cookie = EVENTHANDLER_REGISTER(
+ ifnet_departure_event, bpf_ifdetach, NULL,
+ EVENTHANDLER_PRI_ANY);
}
/*
@@ -2229,9 +2522,9 @@ bpf_zero_counters(void)
struct bpf_if *bp;
struct bpf_d *bd;
- mtx_lock(&bpf_mtx);
+ BPF_LOCK();
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
- BPFIF_LOCK(bp);
+ BPFIF_RLOCK(bp);
LIST_FOREACH(bd, &bp->bif_dlist, bd_next) {
BPFD_LOCK(bd);
bd->bd_rcount = 0;
@@ -2242,11 +2535,14 @@ bpf_zero_counters(void)
bd->bd_zcopy = 0;
BPFD_UNLOCK(bd);
}
- BPFIF_UNLOCK(bp);
+ BPFIF_RUNLOCK(bp);
}
- mtx_unlock(&bpf_mtx);
+ BPF_UNLOCK();
}
+/*
+ * Fill filter statistics
+ */
static void
bpfstats_fill_xbpf(struct xbpf_d *d, struct bpf_d *bd)
{
@@ -2254,6 +2550,7 @@ bpfstats_fill_xbpf(struct xbpf_d *d, struct bpf_d *bd)
bzero(d, sizeof(*d));
BPFD_LOCK_ASSERT(bd);
d->bd_structsize = sizeof(*d);
+ /* XXX: reading should be protected by global lock */
d->bd_immediate = bd->bd_immediate;
d->bd_promisc = bd->bd_promisc;
d->bd_hdrcmplt = bd->bd_hdrcmplt;
@@ -2278,6 +2575,9 @@ bpfstats_fill_xbpf(struct xbpf_d *d, struct bpf_d *bd)
d->bd_bufmode = bd->bd_bufmode;
}
+/*
+ * Handle `netstat -B' stats request
+ */
static int
bpf_stats_sysctl(SYSCTL_HANDLER_ARGS)
{
@@ -2315,24 +2615,31 @@ bpf_stats_sysctl(SYSCTL_HANDLER_ARGS)
if (bpf_bpfd_cnt == 0)
return (SYSCTL_OUT(req, 0, 0));
xbdbuf = malloc(req->oldlen, M_BPF, M_WAITOK);
- mtx_lock(&bpf_mtx);
+ BPF_LOCK();
if (req->oldlen < (bpf_bpfd_cnt * sizeof(*xbd))) {
- mtx_unlock(&bpf_mtx);
+ BPF_UNLOCK();
free(xbdbuf, M_BPF);
return (ENOMEM);
}
index = 0;
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
- BPFIF_LOCK(bp);
+ BPFIF_RLOCK(bp);
+ /* Send writers-only first */
+ LIST_FOREACH(bd, &bp->bif_wlist, bd_next) {
+ xbd = &xbdbuf[index++];
+ BPFD_LOCK(bd);
+ bpfstats_fill_xbpf(xbd, bd);
+ BPFD_UNLOCK(bd);
+ }
LIST_FOREACH(bd, &bp->bif_dlist, bd_next) {
xbd = &xbdbuf[index++];
BPFD_LOCK(bd);
bpfstats_fill_xbpf(xbd, bd);
BPFD_UNLOCK(bd);
}
- BPFIF_UNLOCK(bp);
+ BPFIF_RUNLOCK(bp);
}
- mtx_unlock(&bpf_mtx);
+ BPF_UNLOCK();
error = SYSCTL_OUT(req, xbdbuf, index * sizeof(*xbd));
free(xbdbuf, M_BPF);
return (error);
diff --git a/freebsd/sys/net/bpf.h b/freebsd/sys/net/bpf.h
index 726483a5..004815ad 100644
--- a/freebsd/sys/net/bpf.h
+++ b/freebsd/sys/net/bpf.h
@@ -917,14 +917,21 @@ SYSCTL_DECL(_net_bpf);
/*
* Descriptor associated with each attached hardware interface.
+ * FIXME: this structure is exposed to external callers to speed up
+ * bpf_peers_present() call. However we cover all fields not needed by
+ * this function via BPF_INTERNAL define
*/
struct bpf_if {
LIST_ENTRY(bpf_if) bif_next; /* list of all interfaces */
LIST_HEAD(, bpf_d) bif_dlist; /* descriptor list */
+#ifdef BPF_INTERNAL
u_int bif_dlt; /* link layer type */
u_int bif_hdrlen; /* length of header (with padding) */
struct ifnet *bif_ifp; /* corresponding interface */
- struct mtx bif_mtx; /* mutex for interface */
+ struct rwlock bif_lock; /* interface lock */
+ LIST_HEAD(, bpf_d) bif_wlist; /* writer-only list */
+ int flags; /* Interface flags */
+#endif
};
void bpf_bufheld(struct bpf_d *d);
diff --git a/freebsd/sys/net/bpf_buffer.c b/freebsd/sys/net/bpf_buffer.c
index 7ebfb0a8..382497f6 100644
--- a/freebsd/sys/net/bpf_buffer.c
+++ b/freebsd/sys/net/bpf_buffer.c
@@ -4,7 +4,7 @@
* Copyright (c) 2007 Seccuris Inc.
* All rights reserved.
*
- * This sofware was developed by Robert N. M. Watson under contract to
+ * This software was developed by Robert N. M. Watson under contract to
* Seccuris Inc.
*
* Redistribution and use in source and binary forms, with or without
@@ -95,21 +95,6 @@ static int bpf_maxbufsize = BPF_MAXBUFSIZE;
SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
&bpf_maxbufsize, 0, "Default capture buffer in bytes");
-void
-bpf_buffer_alloc(struct bpf_d *d)
-{
-
- KASSERT(d->bd_fbuf == NULL, ("bpf_buffer_alloc: bd_fbuf != NULL"));
- KASSERT(d->bd_sbuf == NULL, ("bpf_buffer_alloc: bd_sbuf != NULL"));
- KASSERT(d->bd_hbuf == NULL, ("bpf_buffer_alloc: bd_hbuf != NULL"));
-
- d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
- d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
- d->bd_hbuf = NULL;
- d->bd_slen = 0;
- d->bd_hlen = 0;
-}
-
/*
* Simple data copy to the current kernel buffer.
*/
@@ -185,18 +170,42 @@ int
bpf_buffer_ioctl_sblen(struct bpf_d *d, u_int *i)
{
u_int size;
+ caddr_t fbuf, sbuf;
- BPFD_LOCK(d);
- if (d->bd_bif != NULL) {
- BPFD_UNLOCK(d);
- return (EINVAL);
- }
size = *i;
if (size > bpf_maxbufsize)
*i = size = bpf_maxbufsize;
else if (size < BPF_MINBUFSIZE)
*i = size = BPF_MINBUFSIZE;
+
+ /* Allocate buffers immediately */
+ fbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
+ sbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
+
+ BPFD_LOCK(d);
+ if (d->bd_bif != NULL) {
+ /* Interface already attached, unable to change buffers */
+ BPFD_UNLOCK(d);
+ free(fbuf, M_BPF);
+ free(sbuf, M_BPF);
+ return (EINVAL);
+ }
+
+ /* Free old buffers if set */
+ if (d->bd_fbuf != NULL)
+ free(d->bd_fbuf, M_BPF);
+ if (d->bd_sbuf != NULL)
+ free(d->bd_sbuf, M_BPF);
+
+ /* Fill in new data */
d->bd_bufsize = size;
+ d->bd_fbuf = fbuf;
+ d->bd_sbuf = sbuf;
+
+ d->bd_hbuf = NULL;
+ d->bd_slen = 0;
+ d->bd_hlen = 0;
+
BPFD_UNLOCK(d);
return (0);
}
diff --git a/freebsd/sys/net/bpf_buffer.h b/freebsd/sys/net/bpf_buffer.h
index 82d0310b..c1dc1f3a 100644
--- a/freebsd/sys/net/bpf_buffer.h
+++ b/freebsd/sys/net/bpf_buffer.h
@@ -2,7 +2,7 @@
* Copyright (c) 2007 Seccuris Inc.
* All rights reserved.
*
- * This sofware was developed by Robert N. M. Watson under contract to
+ * This software was developed by Robert N. M. Watson under contract to
* Seccuris Inc.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,6 @@
#error "no user-serviceable parts inside"
#endif
-void bpf_buffer_alloc(struct bpf_d *d);
void bpf_buffer_append_bytes(struct bpf_d *d, caddr_t buf, u_int offset,
void *src, u_int len);
void bpf_buffer_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset,
diff --git a/freebsd/sys/net/bpf_zerocopy.h b/freebsd/sys/net/bpf_zerocopy.h
index c541a15d..a5709b86 100644
--- a/freebsd/sys/net/bpf_zerocopy.h
+++ b/freebsd/sys/net/bpf_zerocopy.h
@@ -2,7 +2,7 @@
* Copyright (c) 2007 Seccuris Inc.
* All rights reserved.
*
- * This sofware was developed by Robert N. M. Watson under contract to
+ * This software was developed by Robert N. M. Watson under contract to
* Seccuris Inc.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/freebsd/sys/net/bpfdesc.h b/freebsd/sys/net/bpfdesc.h
index 03cb20dd..c3265ce1 100644
--- a/freebsd/sys/net/bpfdesc.h
+++ b/freebsd/sys/net/bpfdesc.h
@@ -79,6 +79,7 @@ struct bpf_d {
u_char bd_promisc; /* true if listening promiscuously */
u_char bd_state; /* idle, waiting, or timed out */
u_char bd_immediate; /* true to return on packet arrival */
+ u_char bd_writer; /* non-zero if d is writer-only */
int bd_hdrcmplt; /* false to fill in src lladdr automatically */
int bd_direction; /* select packet direction */
int bd_feedback; /* true to feed back sent packets */
@@ -86,7 +87,7 @@ struct bpf_d {
int bd_sig; /* signal to send upon packet reception */
struct sigio * bd_sigio; /* information for async I/O */
struct selinfo bd_sel; /* bsd select info */
- struct mtx bd_mtx; /* mutex for this descriptor */
+ struct mtx bd_lock; /* per-descriptor lock */
struct callout bd_callout; /* for BPF timeouts with select */
struct label *bd_label; /* MAC label for descriptor */
u_int64_t bd_fcount; /* number of packets which matched filter */
@@ -105,10 +106,16 @@ struct bpf_d {
#define BPF_WAITING 1 /* waiting for read timeout in select */
#define BPF_TIMED_OUT 2 /* read timeout has expired in select */
-#define BPFD_LOCK(bd) mtx_lock(&(bd)->bd_mtx)
-#define BPFD_UNLOCK(bd) mtx_unlock(&(bd)->bd_mtx)
-#define BPFD_LOCK_ASSERT(bd) mtx_assert(&(bd)->bd_mtx, MA_OWNED)
+#define BPFD_LOCK(bd) mtx_lock(&(bd)->bd_lock)
+#define BPFD_UNLOCK(bd) mtx_unlock(&(bd)->bd_lock)
+#define BPFD_LOCK_ASSERT(bd) mtx_assert(&(bd)->bd_lock, MA_OWNED)
+#define BPF_PID_REFRESH(bd, td) (bd)->bd_pid = (td)->td_proc->p_pid
+#define BPF_PID_REFRESH_CUR(bd) (bd)->bd_pid = curthread->td_proc->p_pid
+
+#define BPF_LOCK() mtx_lock(&bpf_mtx)
+#define BPF_UNLOCK() mtx_unlock(&bpf_mtx)
+#define BPF_LOCK_ASSERT() mtx_assert(&bpf_mtx, MA_OWNED)
/*
* External representation of the bpf descriptor
*/
@@ -143,7 +150,11 @@ struct xbpf_d {
u_int64_t bd_spare[4];
};
-#define BPFIF_LOCK(bif) mtx_lock(&(bif)->bif_mtx)
-#define BPFIF_UNLOCK(bif) mtx_unlock(&(bif)->bif_mtx)
+#define BPFIF_RLOCK(bif) rw_rlock(&(bif)->bif_lock)
+#define BPFIF_RUNLOCK(bif) rw_runlock(&(bif)->bif_lock)
+#define BPFIF_WLOCK(bif) rw_wlock(&(bif)->bif_lock)
+#define BPFIF_WUNLOCK(bif) rw_wunlock(&(bif)->bif_lock)
+
+#define BPFIF_FLAG_DYING 1 /* Reject new bpf consumers */
#endif
diff --git a/freebsd/sys/net/bridgestp.c b/freebsd/sys/net/bridgestp.c
index cc7f4e6f..1b2ef7cf 100644
--- a/freebsd/sys/net/bridgestp.c
+++ b/freebsd/sys/net/bridgestp.c
@@ -129,14 +129,14 @@ static int bstp_rerooted(struct bstp_state *, struct bstp_port *);
static uint32_t bstp_calc_path_cost(struct bstp_port *);
static void bstp_notify_state(void *, int);
static void bstp_notify_rtage(void *, int);
-static void bstp_ifupdstatus(struct bstp_state *, struct bstp_port *);
+static void bstp_ifupdstatus(void *, int);
static void bstp_enable_port(struct bstp_state *, struct bstp_port *);
static void bstp_disable_port(struct bstp_state *, struct bstp_port *);
static void bstp_tick(void *);
static void bstp_timer_start(struct bstp_timer *, uint16_t);
static void bstp_timer_stop(struct bstp_timer *);
static void bstp_timer_latch(struct bstp_timer *);
-static int bstp_timer_expired(struct bstp_timer *);
+static int bstp_timer_dectest(struct bstp_timer *);
static void bstp_hello_timer_expiry(struct bstp_state *,
struct bstp_port *);
static void bstp_message_age_expiry(struct bstp_state *,
@@ -448,7 +448,7 @@ bstp_pdu_flags(struct bstp_port *bp)
return (flags);
}
-struct mbuf *
+void
bstp_input(struct bstp_port *bp, struct ifnet *ifp, struct mbuf *m)
{
struct bstp_state *bs = bp->bp_bs;
@@ -458,7 +458,7 @@ bstp_input(struct bstp_port *bp, struct ifnet *ifp, struct mbuf *m)
if (bp->bp_active == 0) {
m_freem(m);
- return (NULL);
+ return;
}
BSTP_LOCK(bs);
@@ -523,7 +523,6 @@ out:
BSTP_UNLOCK(bs);
if (m)
m_freem(m);
- return (NULL);
}
static void
@@ -1680,7 +1679,7 @@ bstp_set_autoptp(struct bstp_port *bp, int set)
if (set) {
bp->bp_flags |= BSTP_PORT_AUTOPTP;
if (bp->bp_role != BSTP_ROLE_DISABLED)
- bstp_ifupdstatus(bs, bp);
+ taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
} else
bp->bp_flags &= ~BSTP_PORT_AUTOPTP;
BSTP_UNLOCK(bs);
@@ -1770,85 +1769,93 @@ bstp_notify_rtage(void *arg, int pending)
}
void
-bstp_linkstate(struct ifnet *ifp, int state)
+bstp_linkstate(struct bstp_port *bp)
{
- struct bstp_state *bs;
- struct bstp_port *bp;
+ struct bstp_state *bs = bp->bp_bs;
- /* search for the stp port */
- mtx_lock(&bstp_list_mtx);
- LIST_FOREACH(bs, &bstp_list, bs_list) {
- BSTP_LOCK(bs);
- LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
- if (bp->bp_ifp == ifp) {
- bstp_ifupdstatus(bs, bp);
- bstp_update_state(bs, bp);
- /* it only exists once so return */
- BSTP_UNLOCK(bs);
- mtx_unlock(&bstp_list_mtx);
- return;
- }
- }
- BSTP_UNLOCK(bs);
- }
- mtx_unlock(&bstp_list_mtx);
+ if (!bp->bp_active)
+ return;
+
+ bstp_ifupdstatus(bp, 0);
+ BSTP_LOCK(bs);
+ bstp_update_state(bs, bp);
+ BSTP_UNLOCK(bs);
}
static void
-bstp_ifupdstatus(struct bstp_state *bs, struct bstp_port *bp)
+bstp_ifupdstatus(void *arg, int pending)
{
+ struct bstp_port *bp = (struct bstp_port *)arg;
+ struct bstp_state *bs = bp->bp_bs;
struct ifnet *ifp = bp->bp_ifp;
struct ifmediareq ifmr;
- int error = 0;
+ int error, changed;
- BSTP_LOCK_ASSERT(bs);
+ if (!bp->bp_active)
+ return;
bzero((char *)&ifmr, sizeof(ifmr));
error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
+ BSTP_LOCK(bs);
+ changed = 0;
if ((error == 0) && (ifp->if_flags & IFF_UP)) {
if (ifmr.ifm_status & IFM_ACTIVE) {
/* A full-duplex link is assumed to be point to point */
if (bp->bp_flags & BSTP_PORT_AUTOPTP) {
- bp->bp_ptp_link =
- ifmr.ifm_active & IFM_FDX ? 1 : 0;
+ int fdx;
+
+ fdx = ifmr.ifm_active & IFM_FDX ? 1 : 0;
+ if (bp->bp_ptp_link ^ fdx) {
+ bp->bp_ptp_link = fdx;
+ changed = 1;
+ }
}
/* Calc the cost if the link was down previously */
if (bp->bp_flags & BSTP_PORT_PNDCOST) {
- bp->bp_path_cost = bstp_calc_path_cost(bp);
+ uint32_t cost;
+
+ cost = bstp_calc_path_cost(bp);
+ if (bp->bp_path_cost != cost) {
+ bp->bp_path_cost = cost;
+ changed = 1;
+ }
bp->bp_flags &= ~BSTP_PORT_PNDCOST;
}
- if (bp->bp_role == BSTP_ROLE_DISABLED)
+ if (bp->bp_role == BSTP_ROLE_DISABLED) {
bstp_enable_port(bs, bp);
+ changed = 1;
+ }
} else {
if (bp->bp_role != BSTP_ROLE_DISABLED) {
bstp_disable_port(bs, bp);
+ changed = 1;
if ((bp->bp_flags & BSTP_PORT_ADMEDGE) &&
bp->bp_protover == BSTP_PROTO_RSTP)
bp->bp_operedge = 1;
}
}
- return;
- }
-
- if (bp->bp_infois != BSTP_INFO_DISABLED)
+ } else if (bp->bp_infois != BSTP_INFO_DISABLED) {
bstp_disable_port(bs, bp);
+ changed = 1;
+ }
+ if (changed)
+ bstp_assign_roles(bs);
+ BSTP_UNLOCK(bs);
}
static void
bstp_enable_port(struct bstp_state *bs, struct bstp_port *bp)
{
bp->bp_infois = BSTP_INFO_AGED;
- bstp_assign_roles(bs);
}
static void
bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp)
{
bp->bp_infois = BSTP_INFO_DISABLED;
- bstp_assign_roles(bs);
}
static void
@@ -1862,30 +1869,34 @@ bstp_tick(void *arg)
if (bs->bs_running == 0)
return;
- /* slow timer to catch missed link events */
- if (bstp_timer_expired(&bs->bs_link_timer)) {
- LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
- bstp_ifupdstatus(bs, bp);
+ CURVNET_SET(bs->bs_vnet);
+
+ /* poll link events on interfaces that do not support linkstate */
+ if (bstp_timer_dectest(&bs->bs_link_timer)) {
+ LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
+ if (!(bp->bp_ifp->if_capabilities & IFCAP_LINKSTATE))
+ taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
+ }
bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER);
}
LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
/* no events need to happen for these */
- bstp_timer_expired(&bp->bp_tc_timer);
- bstp_timer_expired(&bp->bp_recent_root_timer);
- bstp_timer_expired(&bp->bp_forward_delay_timer);
- bstp_timer_expired(&bp->bp_recent_backup_timer);
+ bstp_timer_dectest(&bp->bp_tc_timer);
+ bstp_timer_dectest(&bp->bp_recent_root_timer);
+ bstp_timer_dectest(&bp->bp_forward_delay_timer);
+ bstp_timer_dectest(&bp->bp_recent_backup_timer);
- if (bstp_timer_expired(&bp->bp_hello_timer))
+ if (bstp_timer_dectest(&bp->bp_hello_timer))
bstp_hello_timer_expiry(bs, bp);
- if (bstp_timer_expired(&bp->bp_message_age_timer))
+ if (bstp_timer_dectest(&bp->bp_message_age_timer))
bstp_message_age_expiry(bs, bp);
- if (bstp_timer_expired(&bp->bp_migrate_delay_timer))
+ if (bstp_timer_dectest(&bp->bp_migrate_delay_timer))
bstp_migrate_delay_expiry(bs, bp);
- if (bstp_timer_expired(&bp->bp_edge_delay_timer))
+ if (bstp_timer_dectest(&bp->bp_edge_delay_timer))
bstp_edge_delay_expiry(bs, bp);
/* update the various state machines for the port */
@@ -1895,6 +1906,8 @@ bstp_tick(void *arg)
bp->bp_txcount--;
}
+ CURVNET_RESTORE();
+
callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs);
}
@@ -1922,7 +1935,7 @@ bstp_timer_latch(struct bstp_timer *t)
}
static int
-bstp_timer_expired(struct bstp_timer *t)
+bstp_timer_dectest(struct bstp_timer *t)
{
if (t->active == 0 || t->latched)
return (0);
@@ -2010,24 +2023,33 @@ bstp_reinit(struct bstp_state *bs)
struct bstp_port *bp;
struct ifnet *ifp, *mif;
u_char *e_addr;
+ void *bridgeptr;
static const u_char llzero[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */
BSTP_LOCK_ASSERT(bs);
+ if (LIST_EMPTY(&bs->bs_bplist))
+ goto disablestp;
+
mif = NULL;
+ bridgeptr = LIST_FIRST(&bs->bs_bplist)->bp_ifp->if_bridge;
+ KASSERT(bridgeptr != NULL, ("Invalid bridge pointer"));
/*
* Search through the Ethernet adapters and find the one with the
- * lowest value. The adapter which we take the MAC address from does
- * not need to be part of the bridge, it just needs to be a unique
- * value.
+ * lowest value. Make sure the adapter which we take the MAC address
+ * from is part of this bridge, so we can have more than one independent
+ * bridges in the same STP domain.
*/
IFNET_RLOCK_NOSLEEP();
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_type != IFT_ETHER)
- continue;
+ continue; /* Not Ethernet */
+
+ if (ifp->if_bridge != bridgeptr)
+ continue; /* Not part of our bridge */
if (bstp_addr_cmp(IF_LLADDR(ifp), llzero) == 0)
- continue;
+ continue; /* No mac address set */
if (mif == NULL) {
mif = ifp;
@@ -2039,21 +2061,8 @@ bstp_reinit(struct bstp_state *bs)
}
}
IFNET_RUNLOCK_NOSLEEP();
-
- if (LIST_EMPTY(&bs->bs_bplist) || mif == NULL) {
- /* Set the bridge and root id (lower bits) to zero */
- bs->bs_bridge_pv.pv_dbridge_id =
- ((uint64_t)bs->bs_bridge_priority) << 48;
- bs->bs_bridge_pv.pv_root_id = bs->bs_bridge_pv.pv_dbridge_id;
- bs->bs_root_pv = bs->bs_bridge_pv;
- /* Disable any remaining ports, they will have no MAC address */
- LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
- bp->bp_infois = BSTP_INFO_DISABLED;
- bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
- }
- callout_stop(&bs->bs_bstpcallout);
- return;
- }
+ if (mif == NULL)
+ goto disablestp;
e_addr = IF_LLADDR(mif);
bs->bs_bridge_pv.pv_dbridge_id =
@@ -2076,11 +2085,25 @@ bstp_reinit(struct bstp_state *bs)
LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
bp->bp_port_id = (bp->bp_priority << 8) |
(bp->bp_ifp->if_index & 0xfff);
- bstp_ifupdstatus(bs, bp);
+ taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
}
bstp_assign_roles(bs);
bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER);
+ return;
+
+disablestp:
+ /* Set the bridge and root id (lower bits) to zero */
+ bs->bs_bridge_pv.pv_dbridge_id =
+ ((uint64_t)bs->bs_bridge_priority) << 48;
+ bs->bs_bridge_pv.pv_root_id = bs->bs_bridge_pv.pv_dbridge_id;
+ bs->bs_root_pv = bs->bs_bridge_pv;
+ /* Disable any remaining ports, they will have no MAC address */
+ LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
+ bp->bp_infois = BSTP_INFO_DISABLED;
+ bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
+ }
+ callout_stop(&bs->bs_bstpcallout);
}
static int
@@ -2090,10 +2113,8 @@ bstp_modevent(module_t mod, int type, void *data)
case MOD_LOAD:
mtx_init(&bstp_list_mtx, "bridgestp list", NULL, MTX_DEF);
LIST_INIT(&bstp_list);
- bstp_linkstate_p = bstp_linkstate;
break;
case MOD_UNLOAD:
- bstp_linkstate_p = NULL;
mtx_destroy(&bstp_list_mtx);
break;
default:
@@ -2128,6 +2149,7 @@ bstp_attach(struct bstp_state *bs, struct bstp_cb_ops *cb)
bs->bs_protover = BSTP_PROTO_RSTP;
bs->bs_state_cb = cb->bcb_state;
bs->bs_rtage_cb = cb->bcb_rtage;
+ bs->bs_vnet = curvnet;
getmicrotime(&bs->bs_last_tc_time);
@@ -2184,6 +2206,7 @@ bstp_create(struct bstp_state *bs, struct bstp_port *bp, struct ifnet *ifp)
bp->bp_priority = BSTP_DEFAULT_PORT_PRIORITY;
TASK_INIT(&bp->bp_statetask, 0, bstp_notify_state, bp);
TASK_INIT(&bp->bp_rtagetask, 0, bstp_notify_rtage, bp);
+ TASK_INIT(&bp->bp_mediatask, 0, bstp_ifupdstatus, bp);
/* Init state */
bp->bp_infois = BSTP_INFO_DISABLED;
@@ -2247,4 +2270,5 @@ bstp_destroy(struct bstp_port *bp)
KASSERT(bp->bp_active == 0, ("port is still attached"));
taskqueue_drain(taskqueue_swi, &bp->bp_statetask);
taskqueue_drain(taskqueue_swi, &bp->bp_rtagetask);
+ taskqueue_drain(taskqueue_swi, &bp->bp_mediatask);
}
diff --git a/freebsd/sys/net/bridgestp.h b/freebsd/sys/net/bridgestp.h
index 74086fce..cbb8d53c 100644
--- a/freebsd/sys/net/bridgestp.h
+++ b/freebsd/sys/net/bridgestp.h
@@ -326,6 +326,7 @@ struct bstp_port {
uint8_t bp_txcount;
struct task bp_statetask;
struct task bp_rtagetask;
+ struct task bp_mediatask;
};
/*
@@ -358,6 +359,7 @@ struct bstp_state {
LIST_HEAD(, bstp_port) bs_bplist;
bstp_state_cb_t bs_state_cb;
bstp_rtage_cb_t bs_rtage_cb;
+ struct vnet *bs_vnet;
};
#define BSTP_LOCK_INIT(_bs) mtx_init(&(_bs)->bs_mtx, "bstp", NULL, MTX_DEF)
@@ -368,8 +370,6 @@ struct bstp_state {
extern const uint8_t bstp_etheraddr[];
-extern void (*bstp_linkstate_p)(struct ifnet *ifp, int state);
-
void bstp_attach(struct bstp_state *, struct bstp_cb_ops *);
void bstp_detach(struct bstp_state *);
void bstp_init(struct bstp_state *);
@@ -378,7 +378,7 @@ int bstp_create(struct bstp_state *, struct bstp_port *, struct ifnet *);
int bstp_enable(struct bstp_port *);
void bstp_disable(struct bstp_port *);
void bstp_destroy(struct bstp_port *);
-void bstp_linkstate(struct ifnet *, int);
+void bstp_linkstate(struct bstp_port *);
int bstp_set_htime(struct bstp_state *, int);
int bstp_set_fdelay(struct bstp_state *, int);
int bstp_set_maxage(struct bstp_state *, int);
@@ -391,6 +391,6 @@ int bstp_set_edge(struct bstp_port *, int);
int bstp_set_autoedge(struct bstp_port *, int);
int bstp_set_ptp(struct bstp_port *, int);
int bstp_set_autoptp(struct bstp_port *, int);
-struct mbuf *bstp_input(struct bstp_port *, struct ifnet *, struct mbuf *);
+void bstp_input(struct bstp_port *, struct ifnet *, struct mbuf *);
#endif /* _KERNEL */
diff --git a/freebsd/sys/net/ieee8023ad_lacp.c b/freebsd/sys/net/ieee8023ad_lacp.c
index 6e06ffe5..1b4418a2 100644
--- a/freebsd/sys/net/ieee8023ad_lacp.c
+++ b/freebsd/sys/net/ieee8023ad_lacp.c
@@ -814,10 +814,10 @@ lacp_select_tx_port(struct lagg_softc *sc, struct mbuf *m)
return (NULL);
}
- if (m->m_flags & M_FLOWID)
+ if (sc->use_flowid && (m->m_flags & M_FLOWID))
hash = m->m_pkthdr.flowid;
else
- hash = lagg_hashmbuf(m, lsc->lsc_hashkey);
+ hash = lagg_hashmbuf(sc, m, lsc->lsc_hashkey);
hash %= pm->pm_count;
lp = pm->pm_map[hash];
diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c
index 918f8c4e..5dffd06d 100644
--- a/freebsd/sys/net/if.c
+++ b/freebsd/sys/net/if.c
@@ -60,6 +60,8 @@
#include <sys/taskqueue.h>
#include <sys/domain.h>
#include <sys/jail.h>
+#include <sys/priv.h>
+
#include <machine/stdarg.h>
#include <vm/uma.h>
@@ -104,7 +106,7 @@ SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
TUNABLE_INT("net.link.ifqmaxlen", &ifqmaxlen);
-SYSCTL_UINT(_net_link, OID_AUTO, ifqmaxlen, CTLFLAG_RDTUN,
+SYSCTL_INT(_net_link, OID_AUTO, ifqmaxlen, CTLFLAG_RDTUN,
&ifqmaxlen, 0, "max send queue size");
/* Log link state change events */
@@ -126,7 +128,7 @@ MALLOC_DEFINE(M_IFDESCR, "ifdescr", "ifnet descriptions");
static struct sx ifdescr_sx;
SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifnet descr");
-void (*bstp_linkstate_p)(struct ifnet *ifp, int state);
+void (*bridge_linkstate_p)(struct ifnet *ifp);
void (*ng_ether_link_state_p)(struct ifnet *ifp, int state);
void (*lagg_linkstate_p)(struct ifnet *ifp, int state);
/* These are external hooks for CARP. */
@@ -277,6 +279,7 @@ ifindex_alloc_locked(u_short *idxp)
IFNET_WLOCK_ASSERT();
+retry:
/*
* Try to find an empty slot below V_if_index. If we fail, take the
* next slot.
@@ -289,10 +292,12 @@ ifindex_alloc_locked(u_short *idxp)
/* Catch if_index overflow. */
if (idx < 1)
return (ENOSPC);
+ if (idx >= V_if_indexlim) {
+ if_grow();
+ goto retry;
+ }
if (idx > V_if_index)
V_if_index = idx;
- if (V_if_index >= V_if_indexlim)
- if_grow();
*idxp = idx;
return (0);
}
@@ -362,10 +367,12 @@ vnet_if_init(const void *unused __unused)
TAILQ_INIT(&V_ifnet);
TAILQ_INIT(&V_ifg_head);
+ IFNET_WLOCK();
if_grow(); /* create initial table */
+ IFNET_WUNLOCK();
vnet_if_clone_init();
}
-VNET_SYSINIT(vnet_if_init, SI_SUB_INIT_IF, SI_ORDER_FIRST, vnet_if_init,
+VNET_SYSINIT(vnet_if_init, SI_SUB_INIT_IF, SI_ORDER_SECOND, vnet_if_init,
NULL);
/* ARGSUSED*/
@@ -376,7 +383,7 @@ if_init(void *dummy __unused)
IFNET_LOCK_INIT();
if_clone_init();
}
-SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_SECOND, if_init, NULL);
+SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_FIRST, if_init, NULL);
#ifdef VIMAGE
@@ -384,8 +391,10 @@ static void
vnet_if_uninit(const void *unused __unused)
{
- VNET_ASSERT(TAILQ_EMPTY(&V_ifnet));
- VNET_ASSERT(TAILQ_EMPTY(&V_ifg_head));
+ VNET_ASSERT(TAILQ_EMPTY(&V_ifnet), ("%s:%d tailq &V_ifnet=%p "
+ "not empty", __func__, __LINE__, &V_ifnet));
+ VNET_ASSERT(TAILQ_EMPTY(&V_ifg_head), ("%s:%d tailq &V_ifg_head=%p "
+ "not empty", __func__, __LINE__, &V_ifg_head));
free((caddr_t)V_ifindex_table, M_IFNET);
}
@@ -396,16 +405,25 @@ VNET_SYSUNINIT(vnet_if_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST,
static void
if_grow(void)
{
+ int oldlim;
u_int n;
struct ifindex_entry *e;
- V_if_indexlim <<= 1;
- n = V_if_indexlim * sizeof(*e);
+ IFNET_WLOCK_ASSERT();
+ oldlim = V_if_indexlim;
+ IFNET_WUNLOCK();
+ n = (oldlim << 1) * sizeof(*e);
e = malloc(n, M_IFNET, M_WAITOK | M_ZERO);
+ IFNET_WLOCK();
+ if (V_if_indexlim != oldlim) {
+ free(e, M_IFNET);
+ return;
+ }
if (V_ifindex_table != NULL) {
memcpy((caddr_t)e, (caddr_t)V_ifindex_table, n/2);
free((caddr_t)V_ifindex_table, M_IFNET);
}
+ V_if_indexlim <<= 1;
V_ifindex_table = e;
}
@@ -472,8 +490,8 @@ if_alloc(u_char type)
}
/*
- * Do the actual work of freeing a struct ifnet, associated index, and layer
- * 2 common structure. This call is made when the last reference to an
+ * Do the actual work of freeing a struct ifnet, and layer 2 common
+ * structure. This call is made when the last reference to an
* interface is released.
*/
static void
@@ -483,13 +501,6 @@ if_free_internal(struct ifnet *ifp)
KASSERT((ifp->if_flags & IFF_DYING),
("if_free_internal: interface not dying"));
- IFNET_WLOCK();
- KASSERT(ifp == ifnet_byindex_locked(ifp->if_index),
- ("%s: freeing unallocated ifnet", ifp->if_xname));
-
- ifindex_free_locked(ifp->if_index);
- IFNET_WUNLOCK();
-
if (if_com_free[ifp->if_alloctype] != NULL)
if_com_free[ifp->if_alloctype](ifp->if_l2com,
ifp->if_alloctype);
@@ -520,6 +531,14 @@ if_free_type(struct ifnet *ifp, u_char type)
ifp->if_alloctype));
ifp->if_flags |= IFF_DYING; /* XXX: Locking */
+
+ IFNET_WLOCK();
+ KASSERT(ifp == ifnet_byindex_locked(ifp->if_index),
+ ("%s: freeing unallocated ifnet", ifp->if_xname));
+
+ ifindex_free_locked(ifp->if_index);
+ IFNET_WUNLOCK();
+
if (!refcount_release(&ifp->if_refcount))
return;
if_free_internal(ifp);
@@ -818,10 +837,10 @@ if_purgemaddrs(struct ifnet *ifp)
struct ifmultiaddr *ifma;
struct ifmultiaddr *next;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
if_delmulti_locked(ifp, ifma, 1);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
}
/*
@@ -1165,10 +1184,10 @@ if_addgroup(struct ifnet *ifp, const char *groupname)
ifgl->ifgl_group = ifg;
ifgm->ifgm_ifp = ifp;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
IFNET_WUNLOCK();
@@ -1195,9 +1214,9 @@ if_delgroup(struct ifnet *ifp, const char *groupname)
return (ENOENT);
}
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
if (ifgm->ifgm_ifp == ifp)
@@ -1238,9 +1257,9 @@ if_delgroups(struct ifnet *ifp)
strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ);
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
if (ifgm->ifgm_ifp == ifp)
@@ -1282,33 +1301,33 @@ if_getgroup(struct ifgroupreq *data, struct ifnet *ifp)
struct ifgroupreq *ifgr = data;
if (ifgr->ifgr_len == 0) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
ifgr->ifgr_len += sizeof(struct ifg_req);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return (0);
}
len = ifgr->ifgr_len;
ifgp = ifgr->ifgr_groups;
/* XXX: wire */
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
if (len < sizeof(ifgrq)) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return (EINVAL);
}
bzero(&ifgrq, sizeof ifgrq);
strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
sizeof(ifgrq.ifgrq_group));
if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return (error);
}
len -= sizeof(ifgrq);
ifgp++;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return (0);
}
@@ -1415,28 +1434,28 @@ void
if_addr_rlock(struct ifnet *ifp)
{
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
}
void
if_addr_runlock(struct ifnet *ifp)
{
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
void
if_maddr_rlock(struct ifnet *ifp)
{
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
}
void
if_maddr_runlock(struct ifnet *ifp)
{
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
/*
@@ -1548,14 +1567,14 @@ ifa_ifwithaddr_internal(struct sockaddr *addr, int getref)
IFNET_RLOCK_NOSLEEP();
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
continue;
if (sa_equal(addr, ifa->ifa_addr)) {
if (getref)
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
/* IP6 doesn't have broadcast */
@@ -1565,11 +1584,11 @@ ifa_ifwithaddr_internal(struct sockaddr *addr, int getref)
sa_equal(ifa->ifa_broadaddr, addr)) {
if (getref)
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
ifa = NULL;
done:
@@ -1603,7 +1622,7 @@ ifa_ifwithbroadaddr(struct sockaddr *addr)
IFNET_RLOCK_NOSLEEP();
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
continue;
@@ -1612,11 +1631,11 @@ ifa_ifwithbroadaddr(struct sockaddr *addr)
ifa->ifa_broadaddr->sa_len != 0 &&
sa_equal(ifa->ifa_broadaddr, addr)) {
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
ifa = NULL;
done:
@@ -1638,18 +1657,18 @@ ifa_ifwithdstaddr(struct sockaddr *addr)
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
continue;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
continue;
if (ifa->ifa_dstaddr != NULL &&
sa_equal(addr, ifa->ifa_dstaddr)) {
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
ifa = NULL;
done:
@@ -1683,12 +1702,12 @@ ifa_ifwithnet(struct sockaddr *addr, int ignore_ptp)
/*
* Scan though each interface, looking for ones that have addresses
* in this address family. Maintain a reference on ifa_maybe once
- * we find one, as we release the IF_ADDR_LOCK() that kept it stable
+ * we find one, as we release the IF_ADDR_RLOCK() that kept it stable
* when we move onto the next interface.
*/
IFNET_RLOCK_NOSLEEP();
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
char *cp, *cp2, *cp3;
@@ -1707,7 +1726,7 @@ next: continue;
if (ifa->ifa_dstaddr != NULL &&
sa_equal(addr, ifa->ifa_dstaddr)) {
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
} else {
@@ -1718,7 +1737,7 @@ next: continue;
if (ifa->ifa_claim_addr) {
if ((*ifa->ifa_claim_addr)(ifa, addr)) {
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
continue;
@@ -1758,7 +1777,7 @@ next: continue;
}
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
ifa = ifa_maybe;
ifa_maybe = NULL;
@@ -1784,7 +1803,7 @@ ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
if (af >= AF_MAX)
return (NULL);
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != af)
continue;
@@ -1816,7 +1835,7 @@ ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
done:
if (ifa != NULL)
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return (ifa);
}
@@ -1936,14 +1955,10 @@ do_link_state_change(void *arg, int pending)
(*ng_ether_link_state_p)(ifp, link_state);
if (ifp->if_carp)
(*carp_linkstate_p)(ifp);
- if (ifp->if_bridge) {
- KASSERT(bstp_linkstate_p != NULL,("if_bridge bstp not loaded!"));
- (*bstp_linkstate_p)(ifp, link_state);
- }
- if (ifp->if_lagg) {
- KASSERT(lagg_linkstate_p != NULL,("if_lagg not loaded!"));
+ if (ifp->if_bridge)
+ (*bridge_linkstate_p)(ifp);
+ if (ifp->if_lagg)
(*lagg_linkstate_p)(ifp, link_state);
- }
if (IS_DEFAULT_VNET(curvnet))
devctl_notify("IFNET", ifp->if_xname,
@@ -2180,6 +2195,20 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
free(odescrbuf, M_IFDESCR);
break;
+ case SIOCGIFFIB:
+ ifr->ifr_fib = ifp->if_fib;
+ break;
+
+ case SIOCSIFFIB:
+ error = priv_check(td, PRIV_NET_SETIFFIB);
+ if (error)
+ return (error);
+ if (ifr->ifr_fib >= rt_numfibs)
+ return (EINVAL);
+
+ ifp->if_fib = ifr->ifr_fib;
+ break;
+
case SIOCSIFFLAGS:
error = priv_check(td, PRIV_NET_SETIFFLAGS);
if (error)
@@ -2379,9 +2408,9 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
* lose a race while we check if the membership
* already exists.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
ifma = if_findmulti(ifp, &ifr->ifr_addr);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (ifma != NULL)
error = EADDRINUSE;
else
@@ -2492,10 +2521,13 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
int error;
int oif_flags;
+ CURVNET_SET(so->so_vnet);
switch (cmd) {
case SIOCGIFCONF:
case OSIOCGIFCONF:
- return (ifconf(cmd, data));
+ error = ifconf(cmd, data);
+ CURVNET_RESTORE();
+ return (error);
#ifdef COMPAT_FREEBSD32
case SIOCGIFCONF32:
@@ -2507,7 +2539,11 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
ifc.ifc_len = ifc32->ifc_len;
ifc.ifc_buf = PTRIN(ifc32->ifc_buf);
- return (ifconf(SIOCGIFCONF, (void *)&ifc));
+ error = ifconf(SIOCGIFCONF, (void *)&ifc);
+ CURVNET_RESTORE();
+ if (error == 0)
+ ifc32->ifc_len = ifc.ifc_len;
+ return (error);
}
#endif
}
@@ -2517,49 +2553,74 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
#ifdef VIMAGE
case SIOCSIFRVNET:
error = priv_check(td, PRIV_NET_SETIFVNET);
- if (error)
- return (error);
- return (if_vmove_reclaim(td, ifr->ifr_name, ifr->ifr_jid));
+ if (error == 0)
+ error = if_vmove_reclaim(td, ifr->ifr_name,
+ ifr->ifr_jid);
+ CURVNET_RESTORE();
+ return (error);
#endif
case SIOCIFCREATE:
case SIOCIFCREATE2:
error = priv_check(td, PRIV_NET_IFCREATE);
- if (error)
- return (error);
- return (if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name),
- cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL));
+ if (error == 0)
+ error = if_clone_create(ifr->ifr_name,
+ sizeof(ifr->ifr_name),
+ cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL);
+ CURVNET_RESTORE();
+ return (error);
case SIOCIFDESTROY:
error = priv_check(td, PRIV_NET_IFDESTROY);
- if (error)
- return (error);
- return if_clone_destroy(ifr->ifr_name);
+ if (error == 0)
+ error = if_clone_destroy(ifr->ifr_name);
+ CURVNET_RESTORE();
+ return (error);
case SIOCIFGCLONERS:
- return (if_clone_list((struct if_clonereq *)data));
+ error = if_clone_list((struct if_clonereq *)data);
+ CURVNET_RESTORE();
+ return (error);
case SIOCGIFGMEMB:
- return (if_getgroupmembers((struct ifgroupreq *)data));
+ error = if_getgroupmembers((struct ifgroupreq *)data);
+ CURVNET_RESTORE();
+ return (error);
}
ifp = ifunit_ref(ifr->ifr_name);
- if (ifp == NULL)
+ if (ifp == NULL) {
+ CURVNET_RESTORE();
return (ENXIO);
+ }
error = ifhwioctl(cmd, ifp, data, td);
if (error != ENOIOCTL) {
if_rele(ifp);
+ CURVNET_RESTORE();
return (error);
}
oif_flags = ifp->if_flags;
if (so->so_proto == NULL) {
if_rele(ifp);
+ CURVNET_RESTORE();
return (EOPNOTSUPP);
}
+
+ /*
+ * Pass the request on to the socket control method, and if the
+ * latter returns EOPNOTSUPP, directly to the interface.
+ *
+ * Make an exception for the legacy SIOCSIF* requests. Drivers
+ * trust SIOCSIFADDR et al to come from an already privileged
+ * layer, and do not perform any credentials checks or input
+ * validation.
+ */
#ifndef COMPAT_43
error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
data,
ifp, td));
- if (error == EOPNOTSUPP && ifp != NULL && ifp->if_ioctl != NULL)
+ if (error == EOPNOTSUPP && ifp != NULL && ifp->if_ioctl != NULL &&
+ cmd != SIOCSIFADDR && cmd != SIOCSIFBRDADDR &&
+ cmd != SIOCSIFDSTADDR && cmd != SIOCSIFNETMASK)
error = (*ifp->if_ioctl)(ifp, cmd, data);
#else
{
@@ -2603,7 +2664,9 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
data,
ifp, td));
if (error == EOPNOTSUPP && ifp != NULL &&
- ifp->if_ioctl != NULL)
+ ifp->if_ioctl != NULL &&
+ cmd != SIOCSIFADDR && cmd != SIOCSIFBRDADDR &&
+ cmd != SIOCSIFDSTADDR && cmd != SIOCSIFNETMASK)
error = (*ifp->if_ioctl)(ifp, cmd, data);
switch (ocmd) {
@@ -2627,6 +2690,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
#endif
}
if_rele(ifp);
+ CURVNET_RESTORE();
return (error);
}
@@ -2776,7 +2840,7 @@ again:
}
addrs = 0;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa = ifa->ifa_addr;
@@ -2808,7 +2872,7 @@ again:
if (!sbuf_overflowed(sb))
valid_len = sbuf_len(sb);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (addrs == 0) {
bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
sbuf_bcat(sb, &ifr, sizeof(ifr));
@@ -2966,13 +3030,13 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa,
* If the address is already present, return a new reference to it;
* otherwise, allocate storage and set up a new address.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
ifma = if_findmulti(ifp, sa);
if (ifma != NULL) {
ifma->ifma_refcount++;
if (retifma != NULL)
*retifma = ifma;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
return (0);
}
@@ -3038,7 +3102,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa,
* pointer is still valid.
*/
rt_newmaddrmsg(RTM_NEWMADDR, ifma);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
/*
* We are certain we have added something, so call down to the
@@ -3058,7 +3122,7 @@ free_llsa_out:
free(llsa, M_IFMADDR);
unlock_out:
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
return (error);
}
@@ -3092,12 +3156,12 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
if (ifp == NULL)
return (ENOENT);
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
lastref = 0;
ifma = if_findmulti(ifp, sa);
if (ifma != NULL)
lastref = if_delmulti_locked(ifp, ifma, 0);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
if (ifma == NULL)
return (ENOENT);
@@ -3119,10 +3183,10 @@ if_delallmulti(struct ifnet *ifp)
struct ifmultiaddr *ifma;
struct ifmultiaddr *next;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
if_delmulti_locked(ifp, ifma, 0);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
}
/*
@@ -3159,7 +3223,7 @@ if_delmulti_ifma(struct ifmultiaddr *ifma)
* If and only if the ifnet instance exists: Acquire the address lock.
*/
if (ifp != NULL)
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
lastref = if_delmulti_locked(ifp, ifma, 0);
@@ -3169,7 +3233,7 @@ if_delmulti_ifma(struct ifmultiaddr *ifma)
* Release the address lock.
* If the group was left: update the hardware hash filter.
*/
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
if (lastref && ifp->if_ioctl != NULL) {
(void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0);
}
@@ -3191,7 +3255,7 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching)
if (ifp != NULL && ifma->ifma_ifp != NULL) {
KASSERT(ifma->ifma_ifp == ifp,
("%s: inconsistent ifp %p", __func__, ifp));
- IF_ADDR_LOCK_ASSERT(ifp);
+ IF_ADDR_WLOCK_ASSERT(ifp);
}
ifp = ifma->ifma_ifp;
@@ -3264,14 +3328,14 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
struct ifaddr *ifa;
struct ifreq ifr;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
ifa = ifp->if_addr;
if (ifa == NULL) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return (EINVAL);
}
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
if (sdl == NULL) {
ifa_free(ifa);
diff --git a/freebsd/sys/net/if.h b/freebsd/sys/net/if.h
index 1a6423f6..25d43ac3 100644
--- a/freebsd/sys/net/if.h
+++ b/freebsd/sys/net/if.h
@@ -145,7 +145,7 @@ struct if_data {
#define IFF_LINK2 0x4000 /* per link layer defined bit */
#define IFF_ALTPHYS IFF_LINK2 /* use alternate physical connection */
#define IFF_MULTICAST 0x8000 /* (i) supports multicast */
-/* 0x10000 */
+#define IFF_CANTCONFIG 0x10000 /* (i) unconfigurable using ioctl(2) */
#define IFF_PPROMISC 0x20000 /* (n) user-requested promisc mode */
#define IFF_MONITOR 0x40000 /* (n) user-requested monitor mode */
#define IFF_STATICARP 0x80000 /* (n) static ARP */
@@ -165,7 +165,7 @@ struct if_data {
#define IFF_CANTCHANGE \
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_DRV_RUNNING|IFF_DRV_OACTIVE|\
IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_SMART|IFF_PROMISC|\
- IFF_DYING)
+ IFF_DYING|IFF_CANTCONFIG)
/*
* Values for if_link_state.
@@ -220,6 +220,7 @@ struct if_data {
#define IFCAP_POLLING_NOCOUNT 0x20000 /* polling ticks cannot be fragmented */
#define IFCAP_VLAN_HWTSO 0x40000 /* can do IFCAP_TSO on VLANs */
#define IFCAP_LINKSTATE 0x80000 /* the runtime link state is dynamic */
+#define IFCAP_NETMAP 0x100000 /* netmap mode supported/enabled */
#define IFCAP_HWCSUM (IFCAP_RXCSUM | IFCAP_TXCSUM)
#define IFCAP_TSO (IFCAP_TSO4 | IFCAP_TSO6)
@@ -232,6 +233,7 @@ struct if_data {
/*
* Message format for use in obtaining information about interfaces
* from getkerninfo and the routing socket
+ * For the new, extensible interface see struct if_msghdrl below.
*/
struct if_msghdr {
u_short ifm_msglen; /* to skip over non-understood messages */
@@ -244,8 +246,34 @@ struct if_msghdr {
};
/*
+ * The 'l' version shall be used by new interfaces, like NET_RT_IFLISTL. It is
+ * extensible after ifm_data_off or within ifm_data. Both the if_msghdr and
+ * if_data now have a member field detailing the struct length in addition to
+ * the routing message length. Macros are provided to find the start of
+ * ifm_data and the start of the socket address strucutres immediately following
+ * struct if_msghdrl given a pointer to struct if_msghdrl.
+ */
+#define IF_MSGHDRL_IFM_DATA(_l) \
+ (struct if_data *)((char *)(_l) + (_l)->ifm_data_off)
+#define IF_MSGHDRL_RTA(_l) \
+ (void *)((uintptr_t)(_l) + (_l)->ifm_len)
+struct if_msghdrl {
+ u_short ifm_msglen; /* to skip over non-understood messages */
+ u_char ifm_version; /* future binary compatibility */
+ u_char ifm_type; /* message type */
+ int ifm_addrs; /* like rtm_addrs */
+ int ifm_flags; /* value of if_flags */
+ u_short ifm_index; /* index for associated ifp */
+ u_short _ifm_spare1; /* spare space to grow if_index, see if_var.h */
+ u_short ifm_len; /* length of if_msghdrl incl. if_data */
+ u_short ifm_data_off; /* offset of if_data from beginning */
+ struct if_data ifm_data;/* statistics and other data about if */
+};
+
+/*
* Message format for use in obtaining information about interface addresses
* from getkerninfo and the routing socket
+ * For the new, extensible interface see struct ifa_msghdrl below.
*/
struct ifa_msghdr {
u_short ifam_msglen; /* to skip over non-understood messages */
@@ -258,6 +286,33 @@ struct ifa_msghdr {
};
/*
+ * The 'l' version shall be used by new interfaces, like NET_RT_IFLISTL. It is
+ * extensible after ifam_metric or within ifam_data. Both the ifa_msghdrl and
+ * if_data now have a member field detailing the struct length in addition to
+ * the routing message length. Macros are provided to find the start of
+ * ifm_data and the start of the socket address strucutres immediately following
+ * struct ifa_msghdrl given a pointer to struct ifa_msghdrl.
+ */
+#define IFA_MSGHDRL_IFAM_DATA(_l) \
+ (struct if_data *)((char *)(_l) + (_l)->ifam_data_off)
+#define IFA_MSGHDRL_RTA(_l) \
+ (void *)((uintptr_t)(_l) + (_l)->ifam_len)
+struct ifa_msghdrl {
+ u_short ifam_msglen; /* to skip over non-understood messages */
+ u_char ifam_version; /* future binary compatibility */
+ u_char ifam_type; /* message type */
+ int ifam_addrs; /* like rtm_addrs */
+ int ifam_flags; /* value of ifa_flags */
+ u_short ifam_index; /* index for associated ifp */
+ u_short _ifam_spare1; /* spare space to grow if_index, see if_var.h */
+ u_short ifam_len; /* length of ifa_msghdrl incl. if_data */
+ u_short ifam_data_off; /* offset of if_data from beginning */
+ int ifam_metric; /* value of ifa_metric */
+ struct if_data ifam_data;/* statistics and other data about if or
+ * address */
+};
+
+/*
* Message format for use in obtaining information about multicast addresses
* from the routing socket
*/
@@ -315,6 +370,7 @@ struct ifreq {
int ifru_media;
caddr_t ifru_data;
int ifru_cap[2];
+ u_int ifru_fib;
} ifr_ifru;
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
@@ -331,6 +387,7 @@ struct ifreq {
#define ifr_reqcap ifr_ifru.ifru_cap[0] /* requested capabilities */
#define ifr_curcap ifr_ifru.ifru_cap[1] /* current capabilities */
#define ifr_index ifr_ifru.ifru_index /* interface index */
+#define ifr_fib ifr_ifru.ifru_fib /* interface fib */
};
#define _SIZEOF_ADDR_IFREQ(ifr) \
diff --git a/freebsd/sys/net/if_arcsubr.c b/freebsd/sys/net/if_arcsubr.c
index dc75b445..e9422068 100644
--- a/freebsd/sys/net/if_arcsubr.c
+++ b/freebsd/sys/net/if_arcsubr.c
@@ -610,6 +610,7 @@ arc_input(struct ifnet *ifp, struct mbuf *m)
m_freem(m);
return;
}
+ M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m);
}
diff --git a/freebsd/sys/net/if_atmsubr.c b/freebsd/sys/net/if_atmsubr.c
index 747bc936..e3ce4ea0 100644
--- a/freebsd/sys/net/if_atmsubr.c
+++ b/freebsd/sys/net/if_atmsubr.c
@@ -334,6 +334,7 @@ atm_input(struct ifnet *ifp, struct atm_pseudohdr *ah, struct mbuf *m,
return;
}
}
+ M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m);
}
diff --git a/freebsd/sys/net/if_bridge.c b/freebsd/sys/net/if_bridge.c
index 5c15a78f..52146381 100644
--- a/freebsd/sys/net/if_bridge.c
+++ b/freebsd/sys/net/if_bridge.c
@@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/protosw.h>
#include <sys/systm.h>
+#include <sys/jail.h>
#include <rtems/bsd/sys/time.h>
#include <sys/socket.h> /* for net/if.h */
#include <sys/sockio.h>
@@ -145,10 +146,10 @@ __FBSDID("$FreeBSD$");
#define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1)
/*
- * Maximum number of addresses to cache.
+ * Default maximum number of addresses to cache.
*/
#ifndef BRIDGE_RTABLE_MAX
-#define BRIDGE_RTABLE_MAX 100
+#define BRIDGE_RTABLE_MAX 2000
#endif
/*
@@ -334,6 +335,10 @@ static int bridge_ip6_checkbasic(struct mbuf **mp);
#endif /* INET6 */
static int bridge_fragment(struct ifnet *, struct mbuf *,
struct ether_header *, int, struct llc *);
+static void bridge_linkstate(struct ifnet *ifp);
+static void bridge_linkcheck(struct bridge_softc *sc);
+
+extern void (*bridge_linkstate_p)(struct ifnet *ifp);
/* The default bridge vlan is 1 (IEEE 802.1Q-2003 Table 9-2) */
#define VLANTAGOF(_m) \
@@ -356,19 +361,26 @@ static int pfil_local_phys = 0; /* run pfil hooks on the physical interface for
locally destined packets */
static int log_stp = 0; /* log STP state changes */
static int bridge_inherit_mac = 0; /* share MAC with first bridge member */
+TUNABLE_INT("net.link.bridge.pfil_onlyip", &pfil_onlyip);
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RW,
&pfil_onlyip, 0, "Only pass IP packets when pfil is enabled");
+TUNABLE_INT("net.link.bridge.ipfw_arp", &pfil_ipfw_arp);
SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp, CTLFLAG_RW,
&pfil_ipfw_arp, 0, "Filter ARP packets through IPFW layer2");
+TUNABLE_INT("net.link.bridge.pfil_bridge", &pfil_bridge);
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RW,
&pfil_bridge, 0, "Packet filter on the bridge interface");
+TUNABLE_INT("net.link.bridge.pfil_member", &pfil_member);
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RW,
&pfil_member, 0, "Packet filter on the member interface");
+TUNABLE_INT("net.link.bridge.pfil_local_phys", &pfil_local_phys);
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys, CTLFLAG_RW,
&pfil_local_phys, 0,
"Packet filter on the physical interface for locally destined packets");
+TUNABLE_INT("net.link.bridge.log_stp", &log_stp);
SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp, CTLFLAG_RW,
&log_stp, 0, "Log STP state changes");
+TUNABLE_INT("net.link.bridge.inherit_mac", &bridge_inherit_mac);
SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac, CTLFLAG_RW,
&bridge_inherit_mac, 0,
"Inherit MAC address from the first bridge member");
@@ -490,6 +502,7 @@ bridge_modevent(module_t mod, int type, void *data)
bridge_input_p = bridge_input;
bridge_output_p = bridge_output;
bridge_dn_p = bridge_dummynet;
+ bridge_linkstate_p = bridge_linkstate;
bridge_detach_cookie = EVENTHANDLER_REGISTER(
ifnet_departure_event, bridge_ifdetach, NULL,
EVENTHANDLER_PRI_ANY);
@@ -502,6 +515,7 @@ bridge_modevent(module_t mod, int type, void *data)
bridge_input_p = NULL;
bridge_output_p = NULL;
bridge_dn_p = NULL;
+ bridge_linkstate_p = NULL;
mtx_destroy(&bridge_list_mtx);
break;
default:
@@ -562,7 +576,8 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
struct bridge_softc *sc, *sc2;
struct ifnet *bifp, *ifp;
- int retry;
+ int fb, retry;
+ unsigned long hostid;
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
@@ -595,17 +610,30 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
IFQ_SET_READY(&ifp->if_snd);
/*
- * Generate a random ethernet address with a locally administered
- * address.
+ * Generate an ethernet address with a locally administered address.
*
* Since we are using random ethernet addresses for the bridge, it is
* possible that we might have address collisions, so make sure that
* this hardware address isn't already in use on another bridge.
+ * The first try uses the hostid and falls back to arc4rand().
*/
+ fb = 0;
+ getcredhostid(curthread->td_ucred, &hostid);
for (retry = 1; retry != 0;) {
- arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1);
- sc->sc_defaddr[0] &= ~1; /* clear multicast bit */
- sc->sc_defaddr[0] |= 2; /* set the LAA bit */
+ if (fb || hostid == 0) {
+ arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1);
+ sc->sc_defaddr[0] &= ~1;/* clear multicast bit */
+ sc->sc_defaddr[0] |= 2; /* set the LAA bit */
+ } else {
+ sc->sc_defaddr[0] = 0x2;
+ sc->sc_defaddr[1] = (hostid >> 24) & 0xff;
+ sc->sc_defaddr[2] = (hostid >> 16) & 0xff;
+ sc->sc_defaddr[3] = (hostid >> 8 ) & 0xff;
+ sc->sc_defaddr[4] = hostid & 0xff;
+ sc->sc_defaddr[5] = ifp->if_dunit & 0xff;
+ }
+
+ fb = 1;
retry = 0;
mtx_lock(&bridge_list_mtx);
LIST_FOREACH(sc2, &bridge_list, sc_list) {
@@ -939,6 +967,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp);
}
+ bridge_linkcheck(sc);
bridge_mutecaps(sc); /* recalcuate now this interface is removed */
bridge_rtdelete(sc, ifs, IFBF_FLUSHALL);
KASSERT(bif->bif_addrcnt == 0,
@@ -1066,17 +1095,16 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
/* Set interface capabilities to the intersection set of all members */
bridge_mutecaps(sc);
+ bridge_linkcheck(sc);
+ /* Place the interface into promiscuous mode */
switch (ifs->if_type) {
- case IFT_ETHER:
- case IFT_L2VLAN:
- /*
- * Place the interface into promiscuous mode.
- */
- BRIDGE_UNLOCK(sc);
- error = ifpromisc(ifs, 1);
- BRIDGE_LOCK(sc);
- break;
+ case IFT_ETHER:
+ case IFT_L2VLAN:
+ BRIDGE_UNLOCK(sc);
+ error = ifpromisc(ifs, 1);
+ BRIDGE_LOCK(sc);
+ break;
}
if (error)
bridge_delete_member(sc, bif, 0);
@@ -2195,11 +2223,9 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
/* Tap off 802.1D packets; they do not get forwarded. */
if (memcmp(eh->ether_dhost, bstp_etheraddr,
ETHER_ADDR_LEN) == 0) {
- m = bstp_input(&bif->bif_stp, ifp, m);
- if (m == NULL) {
- BRIDGE_UNLOCK(sc);
- return (NULL);
- }
+ bstp_input(&bif->bif_stp, ifp, m); /* consumes mbuf */
+ BRIDGE_UNLOCK(sc);
+ return (NULL);
}
if ((bif->bif_flags & IFBIF_STP) &&
@@ -3456,3 +3482,46 @@ out:
m_freem(m);
return (error);
}
+
+static void
+bridge_linkstate(struct ifnet *ifp)
+{
+ struct bridge_softc *sc = ifp->if_bridge;
+ struct bridge_iflist *bif;
+
+ BRIDGE_LOCK(sc);
+ bif = bridge_lookup_member_if(sc, ifp);
+ if (bif == NULL) {
+ BRIDGE_UNLOCK(sc);
+ return;
+ }
+ bridge_linkcheck(sc);
+ BRIDGE_UNLOCK(sc);
+
+ bstp_linkstate(&bif->bif_stp);
+}
+
+static void
+bridge_linkcheck(struct bridge_softc *sc)
+{
+ struct bridge_iflist *bif;
+ int new_link, hasls;
+
+ BRIDGE_LOCK_ASSERT(sc);
+ new_link = LINK_STATE_DOWN;
+ hasls = 0;
+ /* Our link is considered up if at least one of our ports is active */
+ LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
+ if (bif->bif_ifp->if_capabilities & IFCAP_LINKSTATE)
+ hasls++;
+ if (bif->bif_ifp->if_link_state == LINK_STATE_UP) {
+ new_link = LINK_STATE_UP;
+ break;
+ }
+ }
+ if (!LIST_EMPTY(&sc->sc_iflist) && !hasls) {
+ /* If no interfaces support link-state then we default to up */
+ new_link = LINK_STATE_UP;
+ }
+ if_link_state_change(sc->sc_ifp, new_link);
+}
diff --git a/freebsd/sys/net/if_epair.c b/freebsd/sys/net/if_epair.c
index cd7a6c79..fafc0259 100644
--- a/freebsd/sys/net/if_epair.c
+++ b/freebsd/sys/net/if_epair.c
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_clone.h>
+#include <net/if_media.h>
#include <net/if_var.h>
#include <net/if_types.h>
#include <net/netisr.h>
@@ -94,6 +95,8 @@ static struct mbuf *epair_nh_m2cpuid(struct mbuf *, uintptr_t, u_int *);
static void epair_nh_drainedcpu(u_int);
static void epair_start_locked(struct ifnet *);
+static int epair_media_change(struct ifnet *);
+static void epair_media_status(struct ifnet *, struct ifmediareq *);
static int epair_clone_match(struct if_clone *, const char *);
static int epair_clone_create(struct if_clone *, char *, size_t, caddr_t);
@@ -129,6 +132,7 @@ SYSCTL_PROC(_net_link_epair, OID_AUTO, netisr_maxqlen, CTLTYPE_INT|CTLFLAG_RW,
struct epair_softc {
struct ifnet *ifp; /* This ifp. */
struct ifnet *oifp; /* other ifp of pair. */
+ struct ifmedia media; /* Media config (fake). */
u_int refcount; /* # of mbufs in flight. */
u_int cpuid; /* CPU ID assigned upon creation. */
void (*if_qflush)(struct ifnet *);
@@ -191,10 +195,7 @@ epair_dpcpu_init(void)
struct eid_list *s;
u_int cpuid;
- for (cpuid = 0; cpuid <= mp_maxid; cpuid++) {
- if (CPU_ABSENT(cpuid))
- continue;
-
+ CPU_FOREACH(cpuid) {
epair_dpcpu = DPCPU_ID_PTR(cpuid, epair_dpcpu);
/* Initialize per-cpu lock. */
@@ -219,10 +220,7 @@ epair_dpcpu_detach(void)
struct epair_dpcpu *epair_dpcpu;
u_int cpuid;
- for (cpuid = 0; cpuid <= mp_maxid; cpuid++) {
- if (CPU_ABSENT(cpuid))
- continue;
-
+ CPU_FOREACH(cpuid) {
epair_dpcpu = DPCPU_ID_PTR(cpuid, epair_dpcpu);
/* Destroy per-cpu lock. */
@@ -332,10 +330,7 @@ epair_remove_ifp_from_draining(struct ifnet *ifp)
struct epair_ifp_drain *elm, *tvar;
u_int cpuid;
- for (cpuid = 0; cpuid <= mp_maxid; cpuid++) {
- if (CPU_ABSENT(cpuid))
- continue;
-
+ CPU_FOREACH(cpuid) {
epair_dpcpu = DPCPU_ID_PTR(cpuid, epair_dpcpu);
EPAIR_LOCK(epair_dpcpu);
STAILQ_FOREACH_SAFE(elm, &epair_dpcpu->epair_ifp_drain_list,
@@ -622,8 +617,25 @@ epair_qflush(struct ifnet *ifp)
}
static int
+epair_media_change(struct ifnet *ifp __unused)
+{
+
+ /* Do nothing. */
+ return (0);
+}
+
+static void
+epair_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr)
+{
+
+ imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
+ imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX;
+}
+
+static int
epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
+ struct epair_softc *sc;
struct ifreq *ifr;
int error;
@@ -635,6 +647,12 @@ epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = 0;
break;
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ sc = ifp->if_softc;
+ error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd);
+ break;
+
case SIOCSIFMTU:
/* We basically allow all kinds of MTUs. */
ifp->if_mtu = ifr->ifr_mtu;
@@ -794,6 +812,8 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifp->if_dname = ifc->ifc_name;
ifp->if_dunit = unit;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_capabilities = IFCAP_VLAN_MTU;
+ ifp->if_capenable = IFCAP_VLAN_MTU;
ifp->if_start = epair_start;
ifp->if_ioctl = epair_ioctl;
ifp->if_init = epair_init;
@@ -818,6 +838,8 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifp->if_dname = ifc->ifc_name;
ifp->if_dunit = unit;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_capabilities = IFCAP_VLAN_MTU;
+ ifp->if_capenable = IFCAP_VLAN_MTU;
ifp->if_start = epair_start;
ifp->if_ioctl = epair_ioctl;
ifp->if_init = epair_init;
@@ -840,6 +862,14 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
strlcpy(name, sca->ifp->if_xname, len);
DPRINTF("name='%s/%db' created sca=%p scb=%p\n", name, unit, sca, scb);
+ /* Initialise pseudo media types. */
+ ifmedia_init(&sca->media, 0, epair_media_change, epair_media_status);
+ ifmedia_add(&sca->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+ ifmedia_set(&sca->media, IFM_ETHER | IFM_10G_T);
+ ifmedia_init(&scb->media, 0, epair_media_change, epair_media_status);
+ ifmedia_add(&scb->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+ ifmedia_set(&scb->media, IFM_ETHER | IFM_10G_T);
+
/* Tell the world, that we are ready to rock. */
sca->ifp->if_drv_flags |= IFF_DRV_RUNNING;
scb->ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -876,37 +906,41 @@ epair_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
if_link_state_change(oifp, LINK_STATE_DOWN);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
oifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+
+ /*
+ * Get rid of our second half. As the other of the two
+ * interfaces may reside in a different vnet, we need to
+ * switch before freeing them.
+ */
+ CURVNET_SET_QUIET(oifp->if_vnet);
ether_ifdetach(oifp);
- ether_ifdetach(ifp);
/*
* Wait for all packets to be dispatched to if_input.
- * The numbers can only go down as the interfaces are
+ * The numbers can only go down as the interface is
* detached so there is no need to use atomics.
*/
- DPRINTF("sca refcnt=%u scb refcnt=%u\n", sca->refcount, scb->refcount);
- EPAIR_REFCOUNT_ASSERT(sca->refcount == 1 && scb->refcount == 1,
- ("%s: ifp=%p sca->refcount!=1: %d || ifp=%p scb->refcount!=1: %d",
- __func__, ifp, sca->refcount, oifp, scb->refcount));
-
- /*
- * Get rid of our second half.
- */
+ DPRINTF("scb refcnt=%u\n", scb->refcount);
+ EPAIR_REFCOUNT_ASSERT(scb->refcount == 1,
+ ("%s: ifp=%p scb->refcount!=1: %d", __func__, oifp, scb->refcount));
oifp->if_softc = NULL;
error = if_clone_destroyif(ifc, oifp);
if (error)
panic("%s: if_clone_destroyif() for our 2nd iface failed: %d",
__func__, error);
+ if_free(oifp);
+ ifmedia_removeall(&scb->media);
+ free(scb, M_EPAIR);
+ CURVNET_RESTORE();
+ ether_ifdetach(ifp);
/*
- * Finish cleaning up. Free them and release the unit.
- * As the other of the two interfaces my reside in a different vnet,
- * we need to switch before freeing them.
+ * Wait for all packets to be dispatched to if_input.
*/
- CURVNET_SET_QUIET(oifp->if_vnet);
- if_free(oifp);
- CURVNET_RESTORE();
+ DPRINTF("sca refcnt=%u\n", sca->refcount);
+ EPAIR_REFCOUNT_ASSERT(sca->refcount == 1,
+ ("%s: ifp=%p sca->refcount!=1: %d", __func__, ifp, sca->refcount));
if_free(ifp);
- free(scb, M_EPAIR);
+ ifmedia_removeall(&sca->media);
free(sca, M_EPAIR);
ifc_free_unit(ifc, unit);
diff --git a/freebsd/sys/net/if_ethersubr.c b/freebsd/sys/net/if_ethersubr.c
index 02a5d002..b7c48731 100644
--- a/freebsd/sys/net/if_ethersubr.c
+++ b/freebsd/sys/net/if_ethersubr.c
@@ -662,8 +662,10 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
m = (*lagg_input_p)(ifp, m);
if (m != NULL)
ifp = m->m_pkthdr.rcvif;
- else
+ else {
+ CURVNET_RESTORE();
return;
+ }
}
/*
@@ -682,6 +684,7 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
#endif
ifp->if_ierrors++;
m_freem(m);
+ CURVNET_RESTORE();
return;
}
@@ -694,6 +697,8 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
m_adj(m, ETHER_VLAN_ENCAP_LEN);
}
+ M_SETFIB(m, ifp->if_fib);
+
/* Allow ng_ether(4) to claim this frame. */
if (IFP2AC(ifp)->ac_netgraph != NULL) {
KASSERT(ng_ether_input_p != NULL,
diff --git a/freebsd/sys/net/if_faith.c b/freebsd/sys/net/if_faith.c
index d99e16ea..58de362a 100644
--- a/freebsd/sys/net/if_faith.c
+++ b/freebsd/sys/net/if_faith.c
@@ -340,7 +340,7 @@ faithprefix(in6)
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_addr = *in6;
- rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
+ rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL, RT_DEFAULT_FIB);
if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_FAITH &&
(rt->rt_ifp->if_flags & IFF_UP) != 0)
ret = 1;
diff --git a/freebsd/sys/net/if_fddisubr.c b/freebsd/sys/net/if_fddisubr.c
index ba4db83f..154fe2fc 100644
--- a/freebsd/sys/net/if_fddisubr.c
+++ b/freebsd/sys/net/if_fddisubr.c
@@ -552,6 +552,7 @@ fddi_input(ifp, m)
ifp->if_noproto++;
goto dropanyway;
}
+ M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m);
return;
diff --git a/freebsd/sys/net/if_fwsubr.c b/freebsd/sys/net/if_fwsubr.c
index a9931419..df90d48d 100644
--- a/freebsd/sys/net/if_fwsubr.c
+++ b/freebsd/sys/net/if_fwsubr.c
@@ -629,6 +629,7 @@ firewire_input(struct ifnet *ifp, struct mbuf *m, uint16_t src)
return;
}
+ M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m);
}
diff --git a/freebsd/sys/net/if_gif.c b/freebsd/sys/net/if_gif.c
index d9144419..1a8e4c8d 100644
--- a/freebsd/sys/net/if_gif.c
+++ b/freebsd/sys/net/if_gif.c
@@ -37,6 +37,7 @@
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@@ -493,7 +494,7 @@ gif_input(m, af, ifp)
struct ifnet *ifp;
{
int isr, n;
- struct gif_softc *sc = ifp->if_softc;
+ struct gif_softc *sc;
struct etherip_header *eip;
struct ether_header *eh;
struct ifnet *oldifp;
@@ -503,7 +504,7 @@ gif_input(m, af, ifp)
m_freem(m);
return;
}
-
+ sc = ifp->if_softc;
m->m_pkthdr.rcvif = ifp;
#ifdef MAC
@@ -614,6 +615,7 @@ gif_input(m, af, ifp)
ifp->if_ipackets++;
ifp->if_ibytes += m->m_pkthdr.len;
+ M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m);
}
@@ -823,6 +825,12 @@ gif_ioctl(ifp, cmd, data)
}
if (src->sa_len > size)
return EINVAL;
+ error = prison_if(curthread->td_ucred, src);
+ if (error != 0)
+ return (error);
+ error = prison_if(curthread->td_ucred, dst);
+ if (error != 0)
+ return (error);
bcopy((caddr_t)src, (caddr_t)dst, src->sa_len);
#ifdef INET6
if (dst->sa_family == AF_INET6) {
diff --git a/freebsd/sys/net/if_gre.c b/freebsd/sys/net/if_gre.c
index a75e52a4..21f39eb2 100644
--- a/freebsd/sys/net/if_gre.c
+++ b/freebsd/sys/net/if_gre.c
@@ -55,7 +55,9 @@
#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
+#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mbuf.h>
@@ -99,6 +101,14 @@
#define GRENAME "gre"
+#define MTAG_COOKIE_GRE 1307983903
+#define MTAG_GRE_NESTING 1
+struct mtag_gre_nesting {
+ uint16_t count;
+ uint16_t max;
+ struct ifnet *ifp[];
+};
+
/*
* gre_mtx protects all global variables in if_gre.c.
* XXX: gre_softc data not protected yet.
@@ -204,7 +214,6 @@ gre_clone_create(ifc, unit, params)
sc->g_proto = IPPROTO_GRE;
GRE2IFP(sc)->if_flags |= IFF_LINK0;
sc->encap = NULL;
- sc->called = 0;
#ifndef __rtems__
sc->gre_fibnum = curthread->td_proc->p_fibnum;
#else /* __rtems__ */
@@ -252,23 +261,77 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct gre_softc *sc = ifp->if_softc;
struct greip *gh;
struct ip *ip;
+ struct m_tag *mtag;
+ struct mtag_gre_nesting *gt;
+ size_t len;
u_short gre_ip_id = 0;
uint8_t gre_ip_tos = 0;
u_int16_t etype = 0;
struct mobile_h mob_h;
u_int32_t af;
- int extra = 0;
+ int extra = 0, max;
/*
- * gre may cause infinite recursion calls when misconfigured.
- * We'll prevent this by introducing upper limit.
+ * gre may cause infinite recursion calls when misconfigured. High
+ * nesting level may cause stack exhaustion. We'll prevent this by
+ * detecting loops and by introducing upper limit.
*/
- if (++(sc->called) > max_gre_nesting) {
- printf("%s: gre_output: recursively called too many "
- "times(%d)\n", if_name(GRE2IFP(sc)), sc->called);
- m_freem(m);
- error = EIO; /* is there better errno? */
- goto end;
+ mtag = m_tag_locate(m, MTAG_COOKIE_GRE, MTAG_GRE_NESTING, NULL);
+ if (mtag != NULL) {
+ struct ifnet **ifp2;
+
+ gt = (struct mtag_gre_nesting *)(mtag + 1);
+ gt->count++;
+ if (gt->count > min(gt->max,max_gre_nesting)) {
+ printf("%s: hit maximum recursion limit %u on %s\n",
+ __func__, gt->count - 1, ifp->if_xname);
+ m_freem(m);
+ error = EIO; /* is there better errno? */
+ goto end;
+ }
+
+ ifp2 = gt->ifp;
+ for (max = gt->count - 1; max > 0; max--) {
+ if (*ifp2 == ifp)
+ break;
+ ifp2++;
+ }
+ if (*ifp2 == ifp) {
+ printf("%s: detected loop with nexting %u on %s\n",
+ __func__, gt->count-1, ifp->if_xname);
+ m_freem(m);
+ error = EIO; /* is there better errno? */
+ goto end;
+ }
+ *ifp2 = ifp;
+
+ } else {
+ /*
+ * Given that people should NOT increase max_gre_nesting beyond
+ * their real needs, we allocate once per packet rather than
+ * allocating an mtag once per passing through gre.
+ *
+ * Note: the sysctl does not actually check for saneness, so we
+ * limit the maximum numbers of possible recursions here.
+ */
+ max = imin(max_gre_nesting, 256);
+ /* If someone sets the sysctl <= 0, we want at least 1. */
+ max = imax(max, 1);
+ len = sizeof(struct mtag_gre_nesting) +
+ max * sizeof(struct ifnet *);
+ mtag = m_tag_alloc(MTAG_COOKIE_GRE, MTAG_GRE_NESTING, len,
+ M_NOWAIT);
+ if (mtag == NULL) {
+ m_freem(m);
+ error = ENOMEM;
+ goto end;
+ }
+ gt = (struct mtag_gre_nesting *)(mtag + 1);
+ bzero(gt, len);
+ gt->count = 1;
+ gt->max = max;
+ *gt->ifp = ifp;
+ m_tag_prepend(m, mtag);
}
if (!((ifp->if_flags & IFF_UP) &&
@@ -456,7 +519,6 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
(struct ip_moptions *)NULL, (struct inpcb *)NULL);
end:
- sc->called = 0;
if (error)
ifp->if_oerrors++;
return (error);
@@ -649,6 +711,9 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
si.sin_len = sizeof(struct sockaddr_in);
si.sin_addr.s_addr = sc->g_src.s_addr;
sa = sintosa(&si);
+ error = prison_if(curthread->td_ucred, sa);
+ if (error != 0)
+ break;
ifr->ifr_addr = *sa;
break;
case GREGADDRD:
@@ -657,6 +722,9 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
si.sin_len = sizeof(struct sockaddr_in);
si.sin_addr.s_addr = sc->g_dst.s_addr;
sa = sintosa(&si);
+ error = prison_if(curthread->td_ucred, sa);
+ if (error != 0)
+ break;
ifr->ifr_addr = *sa;
break;
case SIOCSIFPHYADDR:
@@ -720,8 +788,14 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
si.sin_family = AF_INET;
si.sin_len = sizeof(struct sockaddr_in);
si.sin_addr.s_addr = sc->g_src.s_addr;
+ error = prison_if(curthread->td_ucred, (struct sockaddr *)&si);
+ if (error != 0)
+ break;
memcpy(&lifr->addr, &si, sizeof(si));
si.sin_addr.s_addr = sc->g_dst.s_addr;
+ error = prison_if(curthread->td_ucred, (struct sockaddr *)&si);
+ if (error != 0)
+ break;
memcpy(&lifr->dstaddr, &si, sizeof(si));
break;
case SIOCGIFPSRCADDR:
@@ -736,6 +810,9 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
si.sin_family = AF_INET;
si.sin_len = sizeof(struct sockaddr_in);
si.sin_addr.s_addr = sc->g_src.s_addr;
+ error = prison_if(curthread->td_ucred, (struct sockaddr *)&si);
+ if (error != 0)
+ break;
bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
break;
case SIOCGIFPDSTADDR:
@@ -750,6 +827,9 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
si.sin_family = AF_INET;
si.sin_len = sizeof(struct sockaddr_in);
si.sin_addr.s_addr = sc->g_dst.s_addr;
+ error = prison_if(curthread->td_ucred, (struct sockaddr *)&si);
+ if (error != 0)
+ break;
bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
break;
case GRESKEY:
diff --git a/freebsd/sys/net/if_gre.h b/freebsd/sys/net/if_gre.h
index 186d4cc6..13b882c8 100644
--- a/freebsd/sys/net/if_gre.h
+++ b/freebsd/sys/net/if_gre.h
@@ -68,8 +68,6 @@ struct gre_softc {
const struct encaptab *encap; /* encapsulation cookie */
- int called; /* infinite recursion preventer */
-
uint32_t key; /* key included in outgoing GRE packets */
/* zero means none */
diff --git a/freebsd/sys/net/if_iso88025subr.c b/freebsd/sys/net/if_iso88025subr.c
index 6a39956e..b52853a2 100644
--- a/freebsd/sys/net/if_iso88025subr.c
+++ b/freebsd/sys/net/if_iso88025subr.c
@@ -682,6 +682,7 @@ iso88025_input(ifp, m)
break;
}
+ M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m);
return;
diff --git a/freebsd/sys/net/if_lagg.c b/freebsd/sys/net/if_lagg.c
index a1c90cdf..5d5064a4 100644
--- a/freebsd/sys/net/if_lagg.c
+++ b/freebsd/sys/net/if_lagg.c
@@ -169,6 +169,11 @@ static int lagg_failover_rx_all = 0; /* Allow input on any failover links */
SYSCTL_INT(_net_link_lagg, OID_AUTO, failover_rx_all, CTLFLAG_RW,
&lagg_failover_rx_all, 0,
"Accept input from any interface in a failover lagg");
+static int def_use_flowid = 1; /* Default value for using M_FLOWID */
+TUNABLE_INT("net.link.lagg.default_use_flowid", &def_use_flowid);
+SYSCTL_INT(_net_link_lagg, OID_AUTO, default_use_flowid, CTLFLAG_RW,
+ &def_use_flowid, 0,
+ "Default setting for using flow id for load sharing");
static int
lagg_modevent(module_t mod, int type, void *data)
@@ -206,6 +211,7 @@ static moduledata_t lagg_mod = {
};
DECLARE_MODULE(if_lagg, lagg_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+MODULE_VERSION(if_lagg, 1);
#if __FreeBSD_version >= 800000
/*
@@ -258,6 +264,8 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params)
struct ifnet *ifp;
int i, error = 0;
static const u_char eaddr[6]; /* 00:00:00:00:00:00 */
+ struct sysctl_oid *oid;
+ char num[14]; /* sufficient for 32 bits */
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
@@ -266,6 +274,17 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params)
return (ENOSPC);
}
+ sysctl_ctx_init(&sc->ctx);
+ snprintf(num, sizeof(num), "%u", unit);
+ sc->use_flowid = def_use_flowid;
+ oid = SYSCTL_ADD_NODE(&sc->ctx, &SYSCTL_NODE_CHILDREN(_net_link, lagg),
+ OID_AUTO, num, CTLFLAG_RD, NULL, "");
+ SYSCTL_ADD_INT(&sc->ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "use_flowid", CTLTYPE_INT|CTLFLAG_RW, &sc->use_flowid, sc->use_flowid,
+ "Use flow id for load sharing");
+ /* Hash all layers by default */
+ sc->sc_flags = LAGG_F_HASHL2|LAGG_F_HASHL3|LAGG_F_HASHL4;
+
sc->sc_proto = LAGG_PROTO_NONE;
for (i = 0; lagg_protos[i].ti_proto != LAGG_PROTO_NONE; i++) {
if (lagg_protos[i].ti_proto == LAGG_PROTO_DEFAULT) {
@@ -345,6 +364,7 @@ lagg_clone_destroy(struct ifnet *ifp)
LAGG_WUNLOCK(sc);
+ sysctl_ctx_free(&sc->ctx);
ifmedia_removeall(&sc->sc_media);
ether_ifdetach(ifp);
if_free_type(ifp, IFT_ETHER);
@@ -738,28 +758,18 @@ fallback:
return (EINVAL);
}
+/*
+ * For direct output to child ports.
+ */
static int
lagg_port_output(struct ifnet *ifp, struct mbuf *m,
struct sockaddr *dst, struct route *ro)
{
struct lagg_port *lp = ifp->if_lagg;
- struct ether_header *eh;
- short type = 0;
switch (dst->sa_family) {
case pseudo_AF_HDRCMPLT:
case AF_UNSPEC:
- eh = (struct ether_header *)dst->sa_data;
- type = eh->ether_type;
- break;
- }
-
- /*
- * Only allow ethernet types required to initiate or maintain the link,
- * aggregated frames take a different path.
- */
- switch (ntohs(type)) {
- case ETHERTYPE_PAE: /* EAPOL PAE/802.1x */
return ((*lp->lp_output)(ifp, m, dst, ro));
}
@@ -776,6 +786,9 @@ lagg_port_ifdetach(void *arg __unused, struct ifnet *ifp)
if ((lp = ifp->if_lagg) == NULL)
return;
+ /* If the ifnet is just being renamed, don't do anything. */
+ if (ifp->if_flags & IFF_RENAMING)
+ return;
sc = lp->lp_softc;
@@ -871,6 +884,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc;
struct lagg_reqall *ra = (struct lagg_reqall *)data;
struct lagg_reqport *rp = (struct lagg_reqport *)data, rpbuf;
+ struct lagg_reqflags *rf = (struct lagg_reqflags *)data;
struct ifreq *ifr = (struct ifreq *)data;
struct lagg_port *lp;
struct ifnet *tpif;
@@ -923,11 +937,11 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = EPROTONOSUPPORT;
break;
}
+ LAGG_WLOCK(sc);
if (sc->sc_proto != LAGG_PROTO_NONE) {
- LAGG_WLOCK(sc);
- error = sc->sc_detach(sc);
- /* Reset protocol and pointers */
+ /* Reset protocol first in case detach unlocks */
sc->sc_proto = LAGG_PROTO_NONE;
+ error = sc->sc_detach(sc);
sc->sc_detach = NULL;
sc->sc_start = NULL;
sc->sc_input = NULL;
@@ -939,10 +953,14 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
sc->sc_lladdr = NULL;
sc->sc_req = NULL;
sc->sc_portreq = NULL;
- LAGG_WUNLOCK(sc);
+ } else if (sc->sc_input != NULL) {
+ /* Still detaching */
+ error = EBUSY;
}
- if (error != 0)
+ if (error != 0) {
+ LAGG_WUNLOCK(sc);
break;
+ }
for (int i = 0; i < (sizeof(lagg_protos) /
sizeof(lagg_protos[0])); i++) {
if (lagg_protos[i].ti_proto == ra->ra_proto) {
@@ -950,7 +968,6 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
printf("%s: using proto %u\n",
sc->sc_ifname,
lagg_protos[i].ti_proto);
- LAGG_WLOCK(sc);
sc->sc_proto = lagg_protos[i].ti_proto;
if (sc->sc_proto != LAGG_PROTO_NONE)
error = lagg_protos[i].ti_attach(sc);
@@ -958,8 +975,25 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
return (error);
}
}
+ LAGG_WUNLOCK(sc);
error = EPROTONOSUPPORT;
break;
+ case SIOCGLAGGFLAGS:
+ rf->rf_flags = sc->sc_flags;
+ break;
+ case SIOCSLAGGHASH:
+ error = priv_check(td, PRIV_NET_LAGG);
+ if (error)
+ break;
+ if ((rf->rf_flags & LAGG_F_HASHMASK) == 0) {
+ error = EINVAL;
+ break;
+ }
+ LAGG_WLOCK(sc);
+ sc->sc_flags &= ~LAGG_F_HASHMASK;
+ sc->sc_flags |= rf->rf_flags & LAGG_F_HASHMASK;
+ LAGG_WUNLOCK(sc);
+ break;
case SIOCGLAGGPORT:
if (rp->rp_portname[0] == '\0' ||
(tpif = ifunit(rp->rp_portname)) == NULL) {
@@ -1215,14 +1249,15 @@ lagg_input(struct ifnet *ifp, struct mbuf *m)
struct lagg_softc *sc = lp->lp_softc;
struct ifnet *scifp = sc->sc_ifp;
+ LAGG_RLOCK(sc);
if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(lp->lp_flags & LAGG_PORT_DISABLED) ||
sc->sc_proto == LAGG_PROTO_NONE) {
+ LAGG_RUNLOCK(sc);
m_freem(m);
return (NULL);
}
- LAGG_RLOCK(sc);
ETHER_BPF_MTAP(scifp, m);
m = (*sc->sc_input)(sc, lp, m);
@@ -1388,42 +1423,55 @@ lagg_gethdr(struct mbuf *m, u_int off, u_int len, void *buf)
}
uint32_t
-lagg_hashmbuf(struct mbuf *m, uint32_t key)
+lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m, uint32_t key)
{
uint16_t etype;
- uint32_t p = 0;
+ uint32_t p = key;
int off;
struct ether_header *eh;
- struct ether_vlan_header vlanbuf;
const struct ether_vlan_header *vlan;
#ifdef INET
const struct ip *ip;
- struct ip ipbuf;
+ const uint32_t *ports;
+ int iphlen;
#endif
#ifdef INET6
const struct ip6_hdr *ip6;
- struct ip6_hdr ip6buf;
uint32_t flow;
#endif
+ union {
+#ifdef INET
+ struct ip ip;
+#endif
+#ifdef INET6
+ struct ip6_hdr ip6;
+#endif
+ struct ether_vlan_header vlan;
+ uint32_t port;
+ } buf;
+
off = sizeof(*eh);
if (m->m_len < off)
goto out;
eh = mtod(m, struct ether_header *);
etype = ntohs(eh->ether_type);
- p = hash32_buf(&eh->ether_shost, ETHER_ADDR_LEN, key);
- p = hash32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
+ if (sc->sc_flags & LAGG_F_HASHL2) {
+ p = hash32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
+ p = hash32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
+ }
/* Special handling for encapsulating VLAN frames */
- if (m->m_flags & M_VLANTAG) {
+ if ((m->m_flags & M_VLANTAG) && (sc->sc_flags & LAGG_F_HASHL2)) {
p = hash32_buf(&m->m_pkthdr.ether_vtag,
sizeof(m->m_pkthdr.ether_vtag), p);
} else if (etype == ETHERTYPE_VLAN) {
- vlan = lagg_gethdr(m, off, sizeof(*vlan), &vlanbuf);
+ vlan = lagg_gethdr(m, off, sizeof(*vlan), &buf);
if (vlan == NULL)
goto out;
- p = hash32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
+ if (sc->sc_flags & LAGG_F_HASHL2)
+ p = hash32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
etype = ntohs(vlan->evl_proto);
off += sizeof(*vlan) - sizeof(*eh);
}
@@ -1431,17 +1479,37 @@ lagg_hashmbuf(struct mbuf *m, uint32_t key)
switch (etype) {
#ifdef INET
case ETHERTYPE_IP:
- ip = lagg_gethdr(m, off, sizeof(*ip), &ipbuf);
+ ip = lagg_gethdr(m, off, sizeof(*ip), &buf);
if (ip == NULL)
goto out;
- p = hash32_buf(&ip->ip_src, sizeof(struct in_addr), p);
- p = hash32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
+ if (sc->sc_flags & LAGG_F_HASHL3) {
+ p = hash32_buf(&ip->ip_src, sizeof(struct in_addr), p);
+ p = hash32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
+ }
+ if (!(sc->sc_flags & LAGG_F_HASHL4))
+ break;
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_SCTP:
+ iphlen = ip->ip_hl << 2;
+ if (iphlen < sizeof(*ip))
+ break;
+ off += iphlen;
+ ports = lagg_gethdr(m, off, sizeof(*ports), &buf);
+ if (ports == NULL)
+ break;
+ p = hash32_buf(ports, sizeof(*ports), p);
+ break;
+ }
break;
#endif
#ifdef INET6
case ETHERTYPE_IPV6:
- ip6 = lagg_gethdr(m, off, sizeof(*ip6), &ip6buf);
+ if (!(sc->sc_flags & LAGG_F_HASHL3))
+ break;
+ ip6 = lagg_gethdr(m, off, sizeof(*ip6), &buf);
if (ip6 == NULL)
goto out;
@@ -1668,10 +1736,10 @@ lagg_lb_start(struct lagg_softc *sc, struct mbuf *m)
struct lagg_port *lp = NULL;
uint32_t p = 0;
- if (m->m_flags & M_FLOWID)
+ if (sc->use_flowid && (m->m_flags & M_FLOWID))
p = m->m_pkthdr.flowid;
else
- p = lagg_hashmbuf(m, lb->lb_key);
+ p = lagg_hashmbuf(sc, m, lb->lb_key);
p %= sc->sc_count;
lp = lb->lb_ports[p];
@@ -1788,7 +1856,7 @@ lagg_lacp_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
etype = ntohs(eh->ether_type);
/* Tap off LACP control messages */
- if (etype == ETHERTYPE_SLOW) {
+ if ((m->m_flags & M_VLANTAG) == 0 && etype == ETHERTYPE_SLOW) {
m = lacp_input(lp, m);
if (m == NULL)
return (NULL);
diff --git a/freebsd/sys/net/if_lagg.h b/freebsd/sys/net/if_lagg.h
index 0034c617..27ab46f2 100644
--- a/freebsd/sys/net/if_lagg.h
+++ b/freebsd/sys/net/if_lagg.h
@@ -21,6 +21,8 @@
#ifndef _NET_LAGG_H
#define _NET_LAGG_H
+#include <sys/sysctl.h>
+
/*
* Global definitions
*/
@@ -29,6 +31,12 @@
#define LAGG_MAX_NAMESIZE 32 /* name of a protocol */
#define LAGG_MAX_STACKING 4 /* maximum number of stacked laggs */
+/* Lagg flags */
+#define LAGG_F_HASHL2 0x00000001 /* hash layer 2 */
+#define LAGG_F_HASHL3 0x00000002 /* hash layer 3 */
+#define LAGG_F_HASHL4 0x00000004 /* hash layer 4 */
+#define LAGG_F_HASHMASK 0x00000007
+
/* Port flags */
#define LAGG_PORT_SLAVE 0x00000000 /* normal enslaved port */
#define LAGG_PORT_MASTER 0x00000001 /* primary port */
@@ -120,6 +128,14 @@ struct lagg_reqall {
#define SIOCGLAGG _IOWR('i', 143, struct lagg_reqall)
#define SIOCSLAGG _IOW('i', 144, struct lagg_reqall)
+struct lagg_reqflags {
+ char rf_ifname[IFNAMSIZ]; /* name of the lagg */
+ uint32_t rf_flags; /* lagg protocol */
+};
+
+#define SIOCGLAGGFLAGS _IOWR('i', 145, struct lagg_reqflags)
+#define SIOCSLAGGHASH _IOW('i', 146, struct lagg_reqflags)
+
#ifdef _KERNEL
/*
* Internal kernel part
@@ -177,6 +193,7 @@ struct lagg_softc {
struct ifmedia sc_media; /* media config */
caddr_t sc_psc; /* protocol data */
uint32_t sc_seq; /* sequence counter */
+ uint32_t sc_flags;
SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */
SLIST_ENTRY(lagg_softc) sc_entries;
@@ -202,6 +219,8 @@ struct lagg_softc {
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
#endif
+ struct sysctl_ctx_list ctx; /* sysctl variables */
+ int use_flowid; /* use M_FLOWID */
};
struct lagg_port {
@@ -240,7 +259,7 @@ extern struct mbuf *(*lagg_input_p)(struct ifnet *, struct mbuf *);
extern void (*lagg_linkstate_p)(struct ifnet *, int );
int lagg_enqueue(struct ifnet *, struct mbuf *);
-uint32_t lagg_hashmbuf(struct mbuf *, uint32_t);
+uint32_t lagg_hashmbuf(struct lagg_softc *, struct mbuf *, uint32_t);
#endif /* _KERNEL */
diff --git a/freebsd/sys/net/if_llatbl.c b/freebsd/sys/net/if_llatbl.c
index 3ffcc21a..80888559 100644
--- a/freebsd/sys/net/if_llatbl.c
+++ b/freebsd/sys/net/if_llatbl.c
@@ -102,18 +102,35 @@ done:
* This function is called by the timer functions
* such as arptimer() and nd6_llinfo_timer(), and
* the caller does the locking.
+ *
+ * Returns the number of held packets, if any, that were dropped.
*/
-void
+size_t
llentry_free(struct llentry *lle)
{
-
+ size_t pkts_dropped;
+ struct mbuf *next;
+
+ pkts_dropped = 0;
LLE_WLOCK_ASSERT(lle);
LIST_REMOVE(lle, lle_next);
- if (lle->la_hold != NULL)
+ while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) {
+ next = lle->la_hold->m_nextpkt;
m_freem(lle->la_hold);
+ lle->la_hold = next;
+ lle->la_numheld--;
+ pkts_dropped++;
+ }
+
+ KASSERT(lle->la_numheld == 0,
+ ("%s: la_numheld %d > 0, pkts_droped %zd", __func__,
+ lle->la_numheld, pkts_dropped));
+ lle->la_flags &= ~LLE_VALID;
LLE_FREE_LOCKED(lle);
+
+ return (pkts_dropped);
}
/*
@@ -214,7 +231,8 @@ lltable_drain(int af)
#endif
void
-lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask)
+lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask,
+ u_int flags)
{
struct lltable *llt;
@@ -223,7 +241,7 @@ lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask)
if (llt->llt_af != af)
continue;
- llt->llt_prefix_free(llt, prefix, mask);
+ llt->llt_prefix_free(llt, prefix, mask, flags);
}
LLTABLE_RUNLOCK();
}
@@ -414,6 +432,7 @@ llatbl_lle_show(struct llentry_sa *la)
db_printf(" lle_tbl=%p\n", lle->lle_tbl);
db_printf(" lle_head=%p\n", lle->lle_head);
db_printf(" la_hold=%p\n", lle->la_hold);
+ db_printf(" la_numheld=%d\n", lle->la_numheld);
db_printf(" la_expire=%ju\n", (uintmax_t)lle->la_expire);
db_printf(" la_flags=0x%04x\n", lle->la_flags);
db_printf(" la_asked=%u\n", lle->la_asked);
diff --git a/freebsd/sys/net/if_llatbl.h b/freebsd/sys/net/if_llatbl.h
index a4d02ab0..8b15e5c8 100644
--- a/freebsd/sys/net/if_llatbl.h
+++ b/freebsd/sys/net/if_llatbl.h
@@ -58,6 +58,7 @@ struct llentry {
struct lltable *lle_tbl;
struct llentries *lle_head;
struct mbuf *la_hold;
+ int la_numheld; /* # of packets currently held */
time_t la_expire;
uint16_t la_flags;
uint16_t la_asked;
@@ -115,19 +116,12 @@ struct llentry {
LLE_WUNLOCK(lle); \
} \
/* guard against invalid refs */ \
- lle = 0; \
+ lle = NULL; \
} while (0)
#define LLE_FREE(lle) do { \
LLE_WLOCK(lle); \
- if ((lle)->lle_refcnt <= 1) \
- (lle)->lle_tbl->llt_free((lle)->lle_tbl, (lle));\
- else { \
- (lle)->lle_refcnt--; \
- LLE_WUNLOCK(lle); \
- } \
- /* guard against invalid refs */ \
- lle = NULL; \
+ LLE_FREE_LOCKED(lle); \
} while (0)
@@ -152,15 +146,13 @@ struct lltable {
int llt_af;
struct ifnet *llt_ifp;
- struct llentry * (*llt_new)(const struct sockaddr *, u_int);
void (*llt_free)(struct lltable *, struct llentry *);
void (*llt_prefix_free)(struct lltable *,
const struct sockaddr *prefix,
- const struct sockaddr *mask);
+ const struct sockaddr *mask,
+ u_int flags);
struct llentry * (*llt_lookup)(struct lltable *, u_int flags,
const struct sockaddr *l3addr);
- int (*llt_rtcheck)(struct ifnet *, u_int flags,
- const struct sockaddr *);
int (*llt_dump)(struct lltable *,
struct sysctl_req *);
};
@@ -185,13 +177,13 @@ MALLOC_DECLARE(M_LLTABLE);
struct lltable *lltable_init(struct ifnet *, int);
void lltable_free(struct lltable *);
void lltable_prefix_free(int, struct sockaddr *,
- struct sockaddr *);
+ struct sockaddr *, u_int);
#if 0
void lltable_drain(int);
#endif
int lltable_sysctl_dumparp(int, struct sysctl_req *);
-void llentry_free(struct llentry *);
+size_t llentry_free(struct llentry *);
int llentry_update(struct llentry **, struct lltable *,
struct sockaddr_storage *, struct ifnet *);
diff --git a/freebsd/sys/net/if_media.c b/freebsd/sys/net/if_media.c
index 46b57b42..3bc6122c 100644
--- a/freebsd/sys/net/if_media.c
+++ b/freebsd/sys/net/if_media.c
@@ -237,7 +237,7 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
/*
* If no change, we're done.
* XXX Automedia may invole software intervention.
- * Keep going in case the the connected media changed.
+ * Keep going in case the connected media changed.
* Similarly, if best match changed (kernel debugger?).
*/
if ((IFM_SUBTYPE(newmedia) != IFM_AUTO) &&
diff --git a/freebsd/sys/net/if_media.h b/freebsd/sys/net/if_media.h
index 337ad685..2c833228 100644
--- a/freebsd/sys/net/if_media.h
+++ b/freebsd/sys/net/if_media.h
@@ -36,7 +36,7 @@
*/
#ifndef _NET_IF_MEDIA_H_
-#define _NET_IF_MEDIA_H_
+#define _NET_IF_MEDIA_H_
/*
* Prototypes and definitions for BSD/OS-compatible network interface
@@ -144,13 +144,12 @@ uint64_t ifmedia_baudrate(int);
#define IFM_10G_LR 18 /* 10GBase-LR 1310nm Single-mode */
#define IFM_10G_SR 19 /* 10GBase-SR 850nm Multi-mode */
#define IFM_10G_CX4 20 /* 10GBase CX4 copper */
-#define IFM_2500_SX 21 /* 2500BaseSX - multi-mode fiber */
-#define IFM_10G_TWINAX 22 /* 10GBase Twinax copper */
-#define IFM_10G_TWINAX_LONG 23 /* 10GBase Twinax Long copper */
-#define IFM_10G_LRM 24 /* 10GBase-LRM 850nm Multi-mode */
-#define IFM_UNKNOWN 25 /* media types not defined yet */
-#define IFM_10G_T 26 /* 10GBase-T - RJ45 */
-
+#define IFM_2500_SX 21 /* 2500BaseSX - multi-mode fiber */
+#define IFM_10G_TWINAX 22 /* 10GBase Twinax copper */
+#define IFM_10G_TWINAX_LONG 23 /* 10GBase Twinax Long copper */
+#define IFM_10G_LRM 24 /* 10GBase-LRM 850nm Multi-mode */
+#define IFM_UNKNOWN 25 /* media types not defined yet */
+#define IFM_10G_T 26 /* 10GBase-T - RJ45 */
/* note 31 is the max! */
@@ -232,20 +231,20 @@ uint64_t ifmedia_baudrate(int);
/*
* ATM
*/
-#define IFM_ATM 0x000000a0
-#define IFM_ATM_UNKNOWN 3
-#define IFM_ATM_UTP_25 4
-#define IFM_ATM_TAXI_100 5
-#define IFM_ATM_TAXI_140 6
-#define IFM_ATM_MM_155 7
-#define IFM_ATM_SM_155 8
-#define IFM_ATM_UTP_155 9
-#define IFM_ATM_MM_622 10
-#define IFM_ATM_SM_622 11
+#define IFM_ATM 0x000000a0
+#define IFM_ATM_UNKNOWN 3
+#define IFM_ATM_UTP_25 4
+#define IFM_ATM_TAXI_100 5
+#define IFM_ATM_TAXI_140 6
+#define IFM_ATM_MM_155 7
+#define IFM_ATM_SM_155 8
+#define IFM_ATM_UTP_155 9
+#define IFM_ATM_MM_622 10
+#define IFM_ATM_SM_622 11
#define IFM_ATM_VIRTUAL 12
-#define IFM_ATM_SDH 0x00000100 /* SDH instead of SONET */
-#define IFM_ATM_NOSCRAMB 0x00000200 /* no scrambling */
-#define IFM_ATM_UNASSIGNED 0x00000400 /* unassigned cells */
+#define IFM_ATM_SDH 0x00000100 /* SDH instead of SONET */
+#define IFM_ATM_NOSCRAMB 0x00000200 /* no scrambling */
+#define IFM_ATM_UNASSIGNED 0x00000400 /* unassigned cells */
/*
* CARP Common Address Redundancy Protocol
@@ -295,22 +294,22 @@ uint64_t ifmedia_baudrate(int);
#define IFM_STATUS_VALID IFM_AVALID
/* List of "status valid" bits, for ifconfig(8). */
-#define IFM_STATUS_VALID_LIST { \
- IFM_AVALID, \
- 0 \
+#define IFM_STATUS_VALID_LIST { \
+ IFM_AVALID, \
+ 0 \
}
/*
* Macros to extract various bits of information from the media word.
*/
-#define IFM_TYPE(x) ((x) & IFM_NMASK)
-#define IFM_SUBTYPE(x) ((x) & IFM_TMASK)
-#define IFM_TYPE_OPTIONS(x) ((x) & IFM_OMASK)
-#define IFM_INST(x) (((x) & IFM_IMASK) >> IFM_ISHIFT)
-#define IFM_OPTIONS(x) ((x) & (IFM_OMASK|IFM_GMASK))
-#define IFM_MODE(x) ((x) & IFM_MMASK)
+#define IFM_TYPE(x) ((x) & IFM_NMASK)
+#define IFM_SUBTYPE(x) ((x) & IFM_TMASK)
+#define IFM_TYPE_OPTIONS(x) ((x) & IFM_OMASK)
+#define IFM_INST(x) (((x) & IFM_IMASK) >> IFM_ISHIFT)
+#define IFM_OPTIONS(x) ((x) & (IFM_OMASK | IFM_GMASK))
+#define IFM_MODE(x) ((x) & IFM_MMASK)
-#define IFM_INST_MAX IFM_INST(IFM_IMASK)
+#define IFM_INST_MAX IFM_INST(IFM_IMASK)
/*
* Macro to create a media word.
@@ -371,6 +370,7 @@ struct ifmedia_description {
}
#define IFM_SUBTYPE_ETHERNET_ALIASES { \
+ { IFM_10_T, "10baseT" }, \
{ IFM_10_T, "UTP" }, \
{ IFM_10_T, "10UTP" }, \
{ IFM_10_2, "BNC" }, \
@@ -390,6 +390,23 @@ struct ifmedia_description {
{ IFM_1000_T, "1000TX" }, \
{ IFM_1000_T, "1000T" }, \
{ IFM_2500_SX, "2500SX" }, \
+ \
+ /* \
+ * Shorthands for common media+option combinations as announced \
+ * by miibus(4) \
+ */ \
+ { IFM_10_T | IFM_FDX, "10baseT-FDX" }, \
+ { IFM_10_T | IFM_FDX | IFM_FLOW, "10baseT-FDX-flow" }, \
+ { IFM_100_TX | IFM_FDX, "100baseTX-FDX" }, \
+ { IFM_100_TX | IFM_FDX | IFM_FLOW, "100baseTX-FDX-flow" }, \
+ { IFM_1000_T | IFM_FDX, "1000baseT-FDX" }, \
+ { IFM_1000_T | IFM_FDX | IFM_FLOW, "1000baseT-FDX-flow" }, \
+ { IFM_1000_T | IFM_FDX | IFM_FLOW | IFM_ETH_MASTER, \
+ "1000baseT-FDX-flow-master" }, \
+ { IFM_1000_T | IFM_FDX | IFM_ETH_MASTER, \
+ "1000baseT-FDX-master" }, \
+ { IFM_1000_T | IFM_ETH_MASTER, "1000baseT-master" }, \
+ \
{ 0, NULL }, \
}
@@ -539,7 +556,7 @@ struct ifmedia_description {
{ 0, NULL }, \
}
-# define IFM_SUBTYPE_ATM_DESCRIPTIONS { \
+#define IFM_SUBTYPE_ATM_DESCRIPTIONS { \
{ IFM_ATM_UNKNOWN, "Unknown" }, \
{ IFM_ATM_UTP_25, "UTP/25.6MBit" }, \
{ IFM_ATM_TAXI_100, "Taxi/100MBit" }, \
@@ -553,7 +570,7 @@ struct ifmedia_description {
{ 0, NULL }, \
}
-# define IFM_SUBTYPE_ATM_ALIASES { \
+#define IFM_SUBTYPE_ATM_ALIASES { \
{ IFM_ATM_UNKNOWN, "UNKNOWN" }, \
{ IFM_ATM_UTP_25, "UTP-25" }, \
{ IFM_ATM_TAXI_100, "TAXI-100" }, \
@@ -574,7 +591,6 @@ struct ifmedia_description {
{ 0, NULL }, \
}
-
#define IFM_SUBTYPE_SHARED_DESCRIPTIONS { \
{ IFM_AUTO, "autoselect" }, \
{ IFM_MANUAL, "manual" }, \
@@ -584,6 +600,13 @@ struct ifmedia_description {
#define IFM_SUBTYPE_SHARED_ALIASES { \
{ IFM_AUTO, "auto" }, \
+ \
+ /* \
+ * Shorthands for common media+option combinations as announced \
+ * by miibus(4) \
+ */ \
+ { IFM_AUTO | IFM_FLOW, "auto-flow" }, \
+ \
{ 0, NULL }, \
}
@@ -598,6 +621,15 @@ struct ifmedia_description {
{ 0, NULL }, \
}
+#define IFM_SHARED_OPTION_ALIASES { \
+ { IFM_FDX, "fdx" }, \
+ { IFM_HDX, "hdx" }, \
+ { IFM_FLOW, "flow" }, \
+ { IFM_LOOP, "loop" }, \
+ { IFM_LOOP, "loopback" }, \
+ { 0, NULL }, \
+}
+
/*
* Baudrate descriptions for the various media types.
*/
@@ -606,7 +638,7 @@ struct ifmedia_baudrate {
uint64_t ifmb_baudrate; /* corresponding baudrate */
};
-#define IFM_BAUDRATE_DESCRIPTIONS { \
+#define IFM_BAUDRATE_DESCRIPTIONS { \
{ IFM_ETHER | IFM_10_T, IF_Mbps(10) }, \
{ IFM_ETHER | IFM_10_2, IF_Mbps(10) }, \
{ IFM_ETHER | IFM_10_5, IF_Mbps(10) }, \
@@ -670,10 +702,10 @@ struct ifmedia_status_description {
const char *ifms_string[2];
};
-#define IFM_STATUS_DESC(ifms, bit) \
+#define IFM_STATUS_DESC(ifms, bit) \
(ifms)->ifms_string[((ifms)->ifms_bit & (bit)) ? 1 : 0]
-#define IFM_STATUS_DESCRIPTIONS { \
+#define IFM_STATUS_DESCRIPTIONS { \
{ IFM_ETHER, IFM_AVALID, IFM_ACTIVE, \
{ "no carrier", "active" } }, \
{ IFM_FDDI, IFM_AVALID, IFM_ACTIVE, \
diff --git a/freebsd/sys/net/if_spppfr.c b/freebsd/sys/net/if_spppfr.c
index be080a7d..f25bad7b 100644
--- a/freebsd/sys/net/if_spppfr.c
+++ b/freebsd/sys/net/if_spppfr.c
@@ -282,6 +282,8 @@ drop: ++ifp->if_ierrors;
if (! (ifp->if_flags & IFF_UP))
goto drop;
+ M_SETFIB(m, ifp->if_fib);
+
/* Check queue. */
if (netisr_queue(isr, m)) { /* (0) on success. */
if (debug)
diff --git a/freebsd/sys/net/if_spppsubr.c b/freebsd/sys/net/if_spppsubr.c
index d5f3487a..01743f47 100644
--- a/freebsd/sys/net/if_spppsubr.c
+++ b/freebsd/sys/net/if_spppsubr.c
@@ -739,6 +739,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m)
goto drop;
SPPP_UNLOCK(sp);
+ M_SETFIB(m, ifp->if_fib);
/* Check queue. */
if (netisr_queue(isr, m)) { /* (0) on success. */
if (debug)
diff --git a/freebsd/sys/net/if_stf.c b/freebsd/sys/net/if_stf.c
index 79466119..a808548c 100644
--- a/freebsd/sys/net/if_stf.c
+++ b/freebsd/sys/net/if_stf.c
@@ -787,6 +787,7 @@ in_stf_input(m, off)
*/
ifp->if_ipackets++;
ifp->if_ibytes += m->m_pkthdr.len;
+ M_SETFIB(m, ifp->if_fib);
netisr_dispatch(NETISR_IPV6, m);
}
diff --git a/freebsd/sys/net/if_tap.c b/freebsd/sys/net/if_tap.c
index cd775369..6e6b6a64 100644
--- a/freebsd/sys/net/if_tap.c
+++ b/freebsd/sys/net/if_tap.c
@@ -44,6 +44,7 @@
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@@ -66,8 +67,9 @@
#include <net/if.h>
#include <net/if_clone.h>
#include <net/if_dl.h>
-#include <net/route.h>
#include <net/if_types.h>
+#include <net/route.h>
+#include <net/vnet.h>
#include <netinet/in.h>
@@ -216,6 +218,8 @@ tap_destroy(struct tap_softc *tp)
KASSERT(!(tp->tap_flags & TAP_OPEN),
("%s flags is out of sync", ifp->if_xname));
+ CURVNET_SET(ifp->if_vnet);
+ seldrain(&tp->tap_rsel);
knlist_destroy(&tp->tap_rsel.si_note);
destroy_dev(tp->tap_dev);
ether_ifdetach(ifp);
@@ -223,6 +227,7 @@ tap_destroy(struct tap_softc *tp)
mtx_destroy(&tp->tap_mtx);
free(tp, M_TAP);
+ CURVNET_RESTORE();
}
static void
@@ -364,6 +369,7 @@ tapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **d
if (unit == -1)
append_unit = 1;
+ CURVNET_SET(CRED_TO_VNET(cred));
/* find any existing device, or allocate new unit number */
i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
if (i) {
@@ -382,6 +388,7 @@ tapclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **d
}
if_clone_create(name, namelen, NULL);
+ CURVNET_RESTORE();
} /* tapclone */
@@ -526,6 +533,7 @@ tapclose(struct cdev *dev, int foo, int bar, struct thread *td)
/* junk all pending output */
mtx_lock(&tp->tap_mtx);
+ CURVNET_SET(ifp->if_vnet);
IF_DRAIN(&ifp->if_snd);
/*
@@ -549,6 +557,8 @@ tapclose(struct cdev *dev, int foo, int bar, struct thread *td)
}
if_link_state_change(ifp, LINK_STATE_DOWN);
+ CURVNET_RESTORE();
+
funsetown(&tp->tap_sigio);
selwakeuppri(&tp->tap_rsel, PZERO+1);
KNOTE_LOCKED(&tp->tap_rsel.si_note, 0);
@@ -950,7 +960,9 @@ tapwrite(struct cdev *dev, struct uio *uio, int flag)
}
/* Pass packet up to parent. */
+ CURVNET_SET(ifp->if_vnet);
(*ifp->if_input)(ifp, m);
+ CURVNET_RESTORE();
ifp->if_ipackets ++; /* ibytes are counted in parent */
return (0);
diff --git a/freebsd/sys/net/if_tun.c b/freebsd/sys/net/if_tun.c
index b6fa0e5a..444113f4 100644
--- a/freebsd/sys/net/if_tun.c
+++ b/freebsd/sys/net/if_tun.c
@@ -128,7 +128,7 @@ static void tunclone(void *arg, struct ucred *cred, char *name,
int namelen, struct cdev **dev);
static void tuncreate(const char *name, struct cdev *dev);
static int tunifioctl(struct ifnet *, u_long, caddr_t);
-static int tuninit(struct ifnet *);
+static void tuninit(struct ifnet *);
static int tunmodevent(module_t, int, void *);
static int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
struct route *ro);
@@ -230,8 +230,8 @@ tunclone(void *arg, struct ucred *cred, char *name, int namelen,
i = clone_create(&tunclones, &tun_cdevsw, &u, dev, 0);
if (i) {
if (append_unit) {
- namelen = snprintf(devname, sizeof(devname), "%s%d", name,
- u);
+ namelen = snprintf(devname, sizeof(devname), "%s%d",
+ name, u);
name = devname;
}
/* No preexisting struct cdev *, create one */
@@ -261,6 +261,7 @@ tun_destroy(struct tun_softc *tp)
if_detach(TUN2IFP(tp));
if_free(TUN2IFP(tp));
destroy_dev(dev);
+ seldrain(&tp->tun_rsel);
knlist_destroy(&tp->tun_rsel.si_note);
mtx_destroy(&tp->tun_mtx);
cv_destroy(&tp->tun_cv);
@@ -504,14 +505,13 @@ tunclose(struct cdev *dev, int foo, int bar, struct thread *td)
return (0);
}
-static int
+static void
tuninit(struct ifnet *ifp)
{
struct tun_softc *tp = ifp->if_softc;
#ifdef INET
struct ifaddr *ifa;
#endif
- int error = 0;
TUNDEBUG(ifp, "tuninit\n");
@@ -538,7 +538,6 @@ tuninit(struct ifnet *ifp)
if_addr_runlock(ifp);
#endif
mtx_unlock(&tp->tun_mtx);
- return (error);
}
/*
@@ -562,12 +561,12 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
mtx_unlock(&tp->tun_mtx);
break;
case SIOCSIFADDR:
- error = tuninit(ifp);
- TUNDEBUG(ifp, "address set, error=%d\n", error);
+ tuninit(ifp);
+ TUNDEBUG(ifp, "address set\n");
break;
case SIOCSIFDSTADDR:
- error = tuninit(ifp);
- TUNDEBUG(ifp, "destination address set, error=%d\n", error);
+ tuninit(ifp);
+ TUNDEBUG(ifp, "destination address set\n");
break;
case SIOCSIFMTU:
ifp->if_mtu = ifr->ifr_mtu;
@@ -587,11 +586,8 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
* tunoutput - queue packets from higher level ready to put out.
*/
static int
-tunoutput(
- struct ifnet *ifp,
- struct mbuf *m0,
- struct sockaddr *dst,
- struct route *ro)
+tunoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
+ struct route *ro)
{
struct tun_softc *tp = ifp->if_softc;
u_short cached_tun_flags;
@@ -671,10 +667,8 @@ tunoutput(
}
error = (ifp->if_transmit)(ifp, m0);
- if (error) {
- ifp->if_collisions++;
+ if (error)
return (ENOBUFS);
- }
ifp->if_opackets++;
return (0);
}
@@ -683,7 +677,8 @@ tunoutput(
* the cdevsw interface is now pretty minimal.
*/
static int
-tunioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
+tunioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
+ struct thread *td)
{
int error;
struct tun_softc *tp = dev->si_drv1;
@@ -875,7 +870,6 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
struct tun_softc *tp = dev->si_drv1;
struct ifnet *ifp = TUN2IFP(tp);
struct mbuf *m;
- int error = 0;
uint32_t family;
int isr;
@@ -895,7 +889,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, 0, M_PKTHDR)) == NULL) {
ifp->if_ierrors++;
- return (error);
+ return (ENOBUFS);
}
m->m_pkthdr.rcvif = ifp;
@@ -950,6 +944,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
ifp->if_ibytes += m->m_pkthdr.len;
ifp->if_ipackets++;
CURVNET_SET(ifp->if_vnet);
+ M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m);
CURVNET_RESTORE();
return (0);
diff --git a/freebsd/sys/net/if_var.h b/freebsd/sys/net/if_var.h
index 172ebe0e..c5c489fb 100644
--- a/freebsd/sys/net/if_var.h
+++ b/freebsd/sys/net/if_var.h
@@ -197,17 +197,18 @@ struct ifnet {
/* protected by if_addr_mtx */
void *if_pf_kif;
void *if_lagg; /* lagg glue */
- u_char if_alloctype; /* if_type at time of allocation */
+ u_char if_alloctype; /* if_type at time of allocation */
/*
* Spare fields are added so that we can modify sensitive data
* structures without changing the kernel binary interface, and must
* be used with care where binary compatibility is required.
*/
- char if_cspare[3];
+ char if_cspare[3];
char *if_description; /* interface description */
- void *if_pspare[7];
- int if_ispare[4];
+ void *if_pspare[7]; /* 1 netmap, 6 TBD */
+ int if_ispare[3];
+ u_int if_fib; /* interface FIB */
};
typedef void if_init_f_t(void *);
@@ -249,9 +250,15 @@ typedef void if_init_f_t(void *);
#define IF_ADDR_LOCK_INIT(if) mtx_init(&(if)->if_addr_mtx, \
"if_addr_mtx", NULL, MTX_DEF)
#define IF_ADDR_LOCK_DESTROY(if) mtx_destroy(&(if)->if_addr_mtx)
-#define IF_ADDR_LOCK(if) mtx_lock(&(if)->if_addr_mtx)
-#define IF_ADDR_UNLOCK(if) mtx_unlock(&(if)->if_addr_mtx)
+#define IF_ADDR_WLOCK(if) mtx_lock(&(if)->if_addr_mtx)
+#define IF_ADDR_WUNLOCK(if) mtx_unlock(&(if)->if_addr_mtx)
+#define IF_ADDR_RLOCK(if) mtx_lock(&(if)->if_addr_mtx)
+#define IF_ADDR_RUNLOCK(if) mtx_unlock(&(if)->if_addr_mtx)
#define IF_ADDR_LOCK_ASSERT(if) mtx_assert(&(if)->if_addr_mtx, MA_OWNED)
+#define IF_ADDR_WLOCK_ASSERT(if) mtx_assert(&(if)->if_addr_mtx, MA_OWNED)
+/* XXX: Compat. */
+#define IF_ADDR_LOCK(if) IF_ADDR_WLOCK(if)
+#define IF_ADDR_UNLOCK(if) IF_ADDR_WUNLOCK(if)
/*
* Function variations on locking macros intended to be used by loadable
diff --git a/freebsd/sys/net/if_vlan.c b/freebsd/sys/net/if_vlan.c
index 576243d9..81c151a5 100644
--- a/freebsd/sys/net/if_vlan.c
+++ b/freebsd/sys/net/if_vlan.c
@@ -36,9 +36,8 @@
* we need to pretend to be enough of an Ethernet implementation
* to make arp work. The way we do this is by telling everyone
* that we are an Ethernet, and then catch the packets that
- * ether_output() left on our output queue when it calls
- * if_start(), rewrite them for use by the real outgoing interface,
- * and ask it to send them.
+ * ether_output() sends to us via if_transmit(), rewrite them for
+ * use by the real outgoing interface, and ask it to send them.
*/
#include <sys/cdefs.h>
@@ -181,16 +180,17 @@ static __inline struct ifvlan * vlan_gethash(struct ifvlantrunk *trunk,
#endif
static void trunk_destroy(struct ifvlantrunk *trunk);
-static void vlan_start(struct ifnet *ifp);
static void vlan_init(void *foo);
static void vlan_input(struct ifnet *ifp, struct mbuf *m);
static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
+static void vlan_qflush(struct ifnet *ifp);
static int vlan_setflag(struct ifnet *ifp, int flag, int status,
int (*func)(struct ifnet *, int));
static int vlan_setflags(struct ifnet *ifp, int status);
static int vlan_setmulti(struct ifnet *ifp);
+static int vlan_transmit(struct ifnet *ifp, struct mbuf *m);
static void vlan_unconfig(struct ifnet *ifp);
-static void vlan_unconfig_locked(struct ifnet *ifp);
+static void vlan_unconfig_locked(struct ifnet *ifp, int departing);
static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag);
static void vlan_link_state(struct ifnet *ifp, int link);
static void vlan_capabilities(struct ifvlan *ifv);
@@ -545,7 +545,7 @@ vlan_ifdetach(void *arg __unused, struct ifnet *ifp)
#ifdef VLAN_ARRAY
for (i = 0; i < VLAN_ARRAY_SIZE; i++)
if ((ifv = ifp->if_vlantrunk->vlans[i])) {
- vlan_unconfig_locked(ifv->ifv_ifp);
+ vlan_unconfig_locked(ifv->ifv_ifp, 1);
if (ifp->if_vlantrunk == NULL)
break;
}
@@ -553,7 +553,7 @@ vlan_ifdetach(void *arg __unused, struct ifnet *ifp)
restart:
for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++)
if ((ifv = LIST_FIRST(&ifp->if_vlantrunk->hash[i]))) {
- vlan_unconfig_locked(ifv->ifv_ifp);
+ vlan_unconfig_locked(ifv->ifv_ifp, 1);
if (ifp->if_vlantrunk)
goto restart; /* trunk->hwidth can change */
else
@@ -809,9 +809,9 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
/* NB: mtu is not set here */
ifp->if_init = vlan_init;
- ifp->if_start = vlan_start;
+ ifp->if_transmit = vlan_transmit;
+ ifp->if_qflush = vlan_qflush;
ifp->if_ioctl = vlan_ioctl;
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_flags = VLAN_IFFLAGS;
ether_ifattach(ifp, eaddr);
/* Now undo some of the damage... */
@@ -823,7 +823,7 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
error = vlan_config(ifv, p, tag);
if (error != 0) {
/*
- * Since we've partialy failed, we need to back
+ * Since we've partially failed, we need to back
* out all the way, otherwise userland could get
* confused. Thus, we destroy the interface.
*/
@@ -867,99 +867,99 @@ vlan_init(void *foo __unused)
}
/*
- * The if_start method for vlan(4) interface. It doesn't
- * raises the IFF_DRV_OACTIVE flag, since it is called
- * only from IFQ_HANDOFF() macro in ether_output_frame().
- * If the interface queue is full, and vlan_start() is
- * not called, the queue would never get emptied and
- * interface would stall forever.
+ * The if_transmit method for vlan(4) interface.
*/
-static void
-vlan_start(struct ifnet *ifp)
+static int
+vlan_transmit(struct ifnet *ifp, struct mbuf *m)
{
struct ifvlan *ifv;
struct ifnet *p;
- struct mbuf *m;
- int error;
+ int error, len, mcast;
ifv = ifp->if_softc;
p = PARENT(ifv);
+ len = m->m_pkthdr.len;
+ mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
- for (;;) {
- IF_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
- BPF_MTAP(ifp, m);
+ BPF_MTAP(ifp, m);
- /*
- * Do not run parent's if_start() if the parent is not up,
- * or parent's driver will cause a system crash.
- */
- if (!UP_AND_RUNNING(p)) {
- m_freem(m);
- ifp->if_collisions++;
- continue;
- }
+ /*
+ * Do not run parent's if_transmit() if the parent is not up,
+ * or parent's driver will cause a system crash.
+ */
+ if (!UP_AND_RUNNING(p)) {
+ m_freem(m);
+ ifp->if_oerrors++;
+ return (0);
+ }
- /*
- * Pad the frame to the minimum size allowed if told to.
- * This option is in accord with IEEE Std 802.1Q, 2003 Ed.,
- * paragraph C.4.4.3.b. It can help to work around buggy
- * bridges that violate paragraph C.4.4.3.a from the same
- * document, i.e., fail to pad short frames after untagging.
- * E.g., a tagged frame 66 bytes long (incl. FCS) is OK, but
- * untagging it will produce a 62-byte frame, which is a runt
- * and requires padding. There are VLAN-enabled network
- * devices that just discard such runts instead or mishandle
- * them somehow.
- */
- if (soft_pad) {
- static char pad[8]; /* just zeros */
- int n;
-
- for (n = ETHERMIN + ETHER_HDR_LEN - m->m_pkthdr.len;
- n > 0; n -= sizeof(pad))
- if (!m_append(m, min(n, sizeof(pad)), pad))
- break;
-
- if (n > 0) {
- if_printf(ifp, "cannot pad short frame\n");
- ifp->if_oerrors++;
- m_freem(m);
- continue;
- }
- }
+ /*
+ * Pad the frame to the minimum size allowed if told to.
+ * This option is in accord with IEEE Std 802.1Q, 2003 Ed.,
+ * paragraph C.4.4.3.b. It can help to work around buggy
+ * bridges that violate paragraph C.4.4.3.a from the same
+ * document, i.e., fail to pad short frames after untagging.
+ * E.g., a tagged frame 66 bytes long (incl. FCS) is OK, but
+ * untagging it will produce a 62-byte frame, which is a runt
+ * and requires padding. There are VLAN-enabled network
+ * devices that just discard such runts instead or mishandle
+ * them somehow.
+ */
+ if (soft_pad) {
+ static char pad[8]; /* just zeros */
+ int n;
- /*
- * If underlying interface can do VLAN tag insertion itself,
- * just pass the packet along. However, we need some way to
- * tell the interface where the packet came from so that it
- * knows how to find the VLAN tag to use, so we attach a
- * packet tag that holds it.
- */
- if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
- m->m_pkthdr.ether_vtag = ifv->ifv_tag;
- m->m_flags |= M_VLANTAG;
- } else {
- m = ether_vlanencap(m, ifv->ifv_tag);
- if (m == NULL) {
- if_printf(ifp,
- "unable to prepend VLAN header\n");
- ifp->if_oerrors++;
- continue;
- }
+ for (n = ETHERMIN + ETHER_HDR_LEN - m->m_pkthdr.len;
+ n > 0; n -= sizeof(pad))
+ if (!m_append(m, min(n, sizeof(pad)), pad))
+ break;
+
+ if (n > 0) {
+ if_printf(ifp, "cannot pad short frame\n");
+ ifp->if_oerrors++;
+ m_freem(m);
+ return (0);
}
+ }
- /*
- * Send it, precisely as ether_output() would have.
- * We are already running at splimp.
- */
- error = (p->if_transmit)(p, m);
- if (!error)
- ifp->if_opackets++;
- else
+ /*
+ * If underlying interface can do VLAN tag insertion itself,
+ * just pass the packet along. However, we need some way to
+ * tell the interface where the packet came from so that it
+ * knows how to find the VLAN tag to use, so we attach a
+ * packet tag that holds it.
+ */
+ if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
+ m->m_pkthdr.ether_vtag = ifv->ifv_tag;
+ m->m_flags |= M_VLANTAG;
+ } else {
+ m = ether_vlanencap(m, ifv->ifv_tag);
+ if (m == NULL) {
+ if_printf(ifp, "unable to prepend VLAN header\n");
ifp->if_oerrors++;
+ return (0);
+ }
}
+
+ /*
+ * Send it, precisely as ether_output() would have.
+ */
+ error = (p->if_transmit)(p, m);
+ if (!error) {
+ ifp->if_opackets++;
+ ifp->if_omcasts += mcast;
+ ifp->if_obytes += len;
+ } else
+ ifp->if_oerrors++;
+ return (error);
+}
+
+/*
+ * The ifp->if_qflush entry point for vlan(4) is a no-op.
+ */
+static void
+vlan_qflush(struct ifnet *ifp __unused)
+{
}
static void
@@ -1165,17 +1165,18 @@ vlan_unconfig(struct ifnet *ifp)
{
VLAN_LOCK();
- vlan_unconfig_locked(ifp);
+ vlan_unconfig_locked(ifp, 0);
VLAN_UNLOCK();
}
static void
-vlan_unconfig_locked(struct ifnet *ifp)
+vlan_unconfig_locked(struct ifnet *ifp, int departing)
{
struct ifvlantrunk *trunk;
struct vlan_mc_entry *mc;
struct ifvlan *ifv;
struct ifnet *parent;
+ int error;
VLAN_LOCK_ASSERT();
@@ -1206,13 +1207,21 @@ vlan_unconfig_locked(struct ifnet *ifp)
ETHER_ADDR_LEN);
/*
- * This may fail if the parent interface is
- * being detached. Regardless, we should do a
- * best effort to free this interface as much
- * as possible as all callers expect vlan
- * destruction to succeed.
+ * If the parent interface is being detached,
+ * all its multicast addresses have already
+ * been removed. Warn about errors if
+ * if_delmulti() does fail, but don't abort as
+ * all callers expect vlan destruction to
+ * succeed.
*/
- (void)if_delmulti(parent, (struct sockaddr *)&sdl);
+ if (!departing) {
+ error = if_delmulti(parent,
+ (struct sockaddr *)&sdl);
+ if (error)
+ if_printf(ifp,
+ "Failed to delete multicast address from parent: %d\n",
+ error);
+ }
SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries);
free(mc, M_VLAN);
}
diff --git a/freebsd/sys/net/netisr.c b/freebsd/sys/net/netisr.c
index 465b0b29..6ba71233 100644
--- a/freebsd/sys/net/netisr.c
+++ b/freebsd/sys/net/netisr.c
@@ -2,8 +2,12 @@
/*-
* Copyright (c) 2007-2009 Robert N. M. Watson
+ * Copyright (c) 2010 Juniper Networks, Inc.
* All rights reserved.
*
+ * This software was developed by Robert N. M. Watson under contract
+ * to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -34,13 +38,13 @@ __FBSDID("$FreeBSD$");
* dispatched) and asynchronous (deferred dispatch) processing of packets by
* registered protocol handlers. Callers pass a protocol identifier and
* packet to netisr, along with a direct dispatch hint, and work will either
- * be immediately processed with the registered handler, or passed to a
- * kernel software interrupt (SWI) thread for deferred dispatch. Callers
- * will generally select one or the other based on:
+ * be immediately processed by the registered handler, or passed to a
+ * software interrupt (SWI) thread for deferred dispatch. Callers will
+ * generally select one or the other based on:
*
- * - Might directly dispatching a netisr handler lead to code reentrance or
+ * - Whether directly dispatching a netisr handler lead to code reentrance or
* lock recursion, such as entering the socket code from the socket code.
- * - Might directly dispatching a netisr handler lead to recursive
+ * - Whether directly dispatching a netisr handler lead to recursive
* processing, such as when decapsulating several wrapped layers of tunnel
* information (IPSEC within IPSEC within ...).
*
@@ -56,9 +60,9 @@ __FBSDID("$FreeBSD$");
* more than one flow.
*
* netisr supports several policy variations, represented by the
- * NETISR_POLICY_* constants, allowing protocols to play a varying role in
+ * NETISR_POLICY_* constants, allowing protocols to play various roles in
* identifying flows, assigning work to CPUs, etc. These are described in
- * detail in netisr.h.
+ * netisr.h.
*/
#include <rtems/bsd/local/opt_ddb.h>
@@ -85,9 +89,11 @@ __FBSDID("$FreeBSD$");
#include <ddb/ddb.h>
#endif
+#define _WANT_NETISR_INTERNAL /* Enable definitions from netisr_internal.h */
#include <net/if.h>
#include <net/if_var.h>
#include <net/netisr.h>
+#include <net/netisr_internal.h>
#include <net/vnet.h>
/*-
@@ -97,13 +103,13 @@ __FBSDID("$FreeBSD$");
*
* The following data structures and fields are protected by this lock:
*
- * - The np array, including all fields of struct netisr_proto.
+ * - The netisr_proto array, including all fields of struct netisr_proto.
* - The nws array, including all fields of struct netisr_worker.
* - The nws_array array.
*
* Note: the NETISR_LOCKING define controls whether read locks are acquired
* in packet processing paths requiring netisr registration stability. This
- * is disabled by default as it can lead to a measurable performance
+ * is disabled by default as it can lead to measurable performance
* degradation even with rmlocks (3%-6% for loopback ping-pong traffic), and
* because netisr registration and unregistration is extremely rare at
* runtime. If it becomes more common, this decision should be revisited.
@@ -158,111 +164,58 @@ SYSCTL_INT(_net_isr, OID_AUTO, direct, CTLFLAG_RW,
*/
static int netisr_maxthreads = -1; /* Max number of threads. */
TUNABLE_INT("net.isr.maxthreads", &netisr_maxthreads);
-SYSCTL_INT(_net_isr, OID_AUTO, maxthreads, CTLFLAG_RD,
+SYSCTL_INT(_net_isr, OID_AUTO, maxthreads, CTLFLAG_RDTUN,
&netisr_maxthreads, 0,
"Use at most this many CPUs for netisr processing");
static int netisr_bindthreads = 0; /* Bind threads to CPUs. */
TUNABLE_INT("net.isr.bindthreads", &netisr_bindthreads);
-SYSCTL_INT(_net_isr, OID_AUTO, bindthreads, CTLFLAG_RD,
+SYSCTL_INT(_net_isr, OID_AUTO, bindthreads, CTLFLAG_RDTUN,
&netisr_bindthreads, 0, "Bind netisr threads to CPUs.");
/*
- * Limit per-workstream queues to at most net.isr.maxqlimit, both for initial
- * configuration and later modification using netisr_setqlimit().
+ * Limit per-workstream mbuf queue limits s to at most net.isr.maxqlimit,
+ * both for initial configuration and later modification using
+ * netisr_setqlimit().
*/
#define NETISR_DEFAULT_MAXQLIMIT 10240
static u_int netisr_maxqlimit = NETISR_DEFAULT_MAXQLIMIT;
TUNABLE_INT("net.isr.maxqlimit", &netisr_maxqlimit);
-SYSCTL_INT(_net_isr, OID_AUTO, maxqlimit, CTLFLAG_RD,
+SYSCTL_UINT(_net_isr, OID_AUTO, maxqlimit, CTLFLAG_RDTUN,
&netisr_maxqlimit, 0,
"Maximum netisr per-protocol, per-CPU queue depth.");
/*
- * The default per-workstream queue limit for protocols that don't initialize
- * the nh_qlimit field of their struct netisr_handler. If this is set above
- * netisr_maxqlimit, we truncate it to the maximum during boot.
+ * The default per-workstream mbuf queue limit for protocols that don't
+ * initialize the nh_qlimit field of their struct netisr_handler. If this is
+ * set above netisr_maxqlimit, we truncate it to the maximum during boot.
*/
#define NETISR_DEFAULT_DEFAULTQLIMIT 256
static u_int netisr_defaultqlimit = NETISR_DEFAULT_DEFAULTQLIMIT;
TUNABLE_INT("net.isr.defaultqlimit", &netisr_defaultqlimit);
-SYSCTL_INT(_net_isr, OID_AUTO, defaultqlimit, CTLFLAG_RD,
+SYSCTL_UINT(_net_isr, OID_AUTO, defaultqlimit, CTLFLAG_RDTUN,
&netisr_defaultqlimit, 0,
"Default netisr per-protocol, per-CPU queue limit if not set by protocol");
/*
- * Each protocol is described by a struct netisr_proto, which holds all
- * global per-protocol information. This data structure is set up by
- * netisr_register(), and derived from the public struct netisr_handler.
- */
-struct netisr_proto {
- const char *np_name; /* Character string protocol name. */
- netisr_handler_t *np_handler; /* Protocol handler. */
- netisr_m2flow_t *np_m2flow; /* Query flow for untagged packet. */
- netisr_m2cpuid_t *np_m2cpuid; /* Query CPU to process packet on. */
- netisr_drainedcpu_t *np_drainedcpu; /* Callback when drained a queue. */
- u_int np_qlimit; /* Maximum per-CPU queue depth. */
- u_int np_policy; /* Work placement policy. */
-};
-
-#define NETISR_MAXPROT 16 /* Compile-time limit. */
-
-/*
- * The np array describes all registered protocols, indexed by protocol
- * number.
+ * Store and export the compile-time constant NETISR_MAXPROT limit on the
+ * number of protocols that can register with netisr at a time. This is
+ * required for crashdump analysis, as it sizes netisr_proto[].
*/
-static struct netisr_proto np[NETISR_MAXPROT];
-
-/*
- * Protocol-specific work for each workstream is described by struct
- * netisr_work. Each work descriptor consists of an mbuf queue and
- * statistics.
- */
-struct netisr_work {
- /*
- * Packet queue, linked by m_nextpkt.
- */
- struct mbuf *nw_head;
- struct mbuf *nw_tail;
- u_int nw_len;
- u_int nw_qlimit;
- u_int nw_watermark;
-
- /*
- * Statistics -- written unlocked, but mostly from curcpu.
- */
- u_int64_t nw_dispatched; /* Number of direct dispatches. */
- u_int64_t nw_hybrid_dispatched; /* "" hybrid dispatches. */
- u_int64_t nw_qdrops; /* "" drops. */
- u_int64_t nw_queued; /* "" enqueues. */
- u_int64_t nw_handled; /* "" handled in worker. */
-};
+static u_int netisr_maxprot = NETISR_MAXPROT;
+SYSCTL_UINT(_net_isr, OID_AUTO, maxprot, CTLFLAG_RD,
+ &netisr_maxprot, 0,
+ "Compile-time limit on the number of protocols supported by netisr.");
/*
- * Workstreams hold a set of ordered work across each protocol, and are
- * described by netisr_workstream. Each workstream is associated with a
- * worker thread, which in turn is pinned to a CPU. Work associated with a
- * workstream can be processd in other threads during direct dispatch;
- * concurrent processing is prevented by the NWS_RUNNING flag, which
- * indicates that a thread is already processing the work queue.
+ * The netisr_proto array describes all registered protocols, indexed by
+ * protocol number. See netisr_internal.h for more details.
*/
-struct netisr_workstream {
- struct intr_event *nws_intr_event; /* Handler for stream. */
- void *nws_swi_cookie; /* swi(9) cookie for stream. */
- struct mtx nws_mtx; /* Synchronize work. */
- u_int nws_cpu; /* CPU pinning. */
- u_int nws_flags; /* Wakeup flags. */
- u_int nws_pendingbits; /* Scheduled protocols. */
-
- /*
- * Each protocol has per-workstream data.
- */
- struct netisr_work nws_work[NETISR_MAXPROT];
-} __aligned(CACHE_LINE_SIZE);
+static struct netisr_proto netisr_proto[NETISR_MAXPROT];
#ifndef __rtems__
/*
- * Per-CPU workstream data.
+ * Per-CPU workstream data. See netisr_internal.h for more details.
*/
DPCPU_DEFINE(struct netisr_workstream, nws);
@@ -278,20 +231,13 @@ static u_int nws_array[MAXCPU];
* CPUs once fully started.
*/
static u_int nws_count;
-SYSCTL_INT(_net_isr, OID_AUTO, numthreads, CTLFLAG_RD,
+SYSCTL_UINT(_net_isr, OID_AUTO, numthreads, CTLFLAG_RD,
&nws_count, 0, "Number of extant netisr threads.");
#else /* __rtems__ */
static struct netisr_workstream rtems_bsd_nws;
#endif /* __rtems__ */
/*
- * Per-workstream flags.
- */
-#define NWS_RUNNING 0x00000001 /* Currently running in a thread. */
-#define NWS_DISPATCHING 0x00000002 /* Currently being direct-dispatched. */
-#define NWS_SCHEDULED 0x00000004 /* Signal issued. */
-
-/*
* Synchronization for each workstream: a mutex protects all mutable fields
* in each stream, including per-protocol state (mbuf queues). The SWI is
* woken up if asynchronous dispatch is required.
@@ -324,7 +270,7 @@ netisr_get_cpuid(u_int cpunumber)
}
/*
- * The default implementation of -> CPU ID mapping.
+ * The default implementation of flow -> CPU ID mapping.
*
* Non-static so that protocols can use it to map their own work to specific
* CPUs in a manner consistent to netisr for affinity purposes.
@@ -381,36 +327,34 @@ netisr_register(const struct netisr_handler *nhp)
* Test that no existing registration exists for this protocol.
*/
NETISR_WLOCK();
- KASSERT(np[proto].np_name == NULL,
+ KASSERT(netisr_proto[proto].np_name == NULL,
("%s(%u, %s): name present", __func__, proto, name));
- KASSERT(np[proto].np_handler == NULL,
+ KASSERT(netisr_proto[proto].np_handler == NULL,
("%s(%u, %s): handler present", __func__, proto, name));
- np[proto].np_name = name;
- np[proto].np_handler = nhp->nh_handler;
- np[proto].np_m2flow = nhp->nh_m2flow;
- np[proto].np_m2cpuid = nhp->nh_m2cpuid;
- np[proto].np_drainedcpu = nhp->nh_drainedcpu;
+ netisr_proto[proto].np_name = name;
+ netisr_proto[proto].np_handler = nhp->nh_handler;
+ netisr_proto[proto].np_m2flow = nhp->nh_m2flow;
+ netisr_proto[proto].np_m2cpuid = nhp->nh_m2cpuid;
+ netisr_proto[proto].np_drainedcpu = nhp->nh_drainedcpu;
if (nhp->nh_qlimit == 0)
- np[proto].np_qlimit = netisr_defaultqlimit;
+ netisr_proto[proto].np_qlimit = netisr_defaultqlimit;
else if (nhp->nh_qlimit > netisr_maxqlimit) {
printf("%s: %s requested queue limit %u capped to "
"net.isr.maxqlimit %u\n", __func__, name, nhp->nh_qlimit,
netisr_maxqlimit);
- np[proto].np_qlimit = netisr_maxqlimit;
+ netisr_proto[proto].np_qlimit = netisr_maxqlimit;
} else
- np[proto].np_qlimit = nhp->nh_qlimit;
- np[proto].np_policy = nhp->nh_policy;
- for (i = 0; i <= mp_maxid; i++) {
- if (CPU_ABSENT(i))
- continue;
+ netisr_proto[proto].np_qlimit = nhp->nh_qlimit;
+ netisr_proto[proto].np_policy = nhp->nh_policy;
+ CPU_FOREACH(i) {
#ifndef __rtems__
npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
#else /* __rtems__ */
npwp = &rtems_bsd_nws.nws_work[proto];
#endif /* __rtems__ */
bzero(npwp, sizeof(*npwp));
- npwp->nw_qlimit = np[proto].np_qlimit;
+ npwp->nw_qlimit = netisr_proto[proto].np_qlimit;
}
NETISR_WUNLOCK();
}
@@ -435,13 +379,11 @@ netisr_clearqdrops(const struct netisr_handler *nhp)
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_WLOCK();
- KASSERT(np[proto].np_handler != NULL,
+ KASSERT(netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
- for (i = 0; i <= mp_maxid; i++) {
- if (CPU_ABSENT(i))
- continue;
+ CPU_FOREACH(i) {
#ifndef __rtems__
npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
#else /* __rtems__ */
@@ -453,7 +395,7 @@ netisr_clearqdrops(const struct netisr_handler *nhp)
}
/*
- * Query the current drop counters across all workstreams for a protocol.
+ * Query current drop counters across all workstreams for a protocol.
*/
void
netisr_getqdrops(const struct netisr_handler *nhp, u_int64_t *qdropp)
@@ -474,13 +416,11 @@ netisr_getqdrops(const struct netisr_handler *nhp, u_int64_t *qdropp)
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_RLOCK(&tracker);
- KASSERT(np[proto].np_handler != NULL,
+ KASSERT(netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
- for (i = 0; i <= mp_maxid; i++) {
- if (CPU_ABSENT(i))
- continue;
+ CPU_FOREACH(i) {
#ifndef __rtems__
npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
#else /* __rtems__ */
@@ -492,7 +432,7 @@ netisr_getqdrops(const struct netisr_handler *nhp, u_int64_t *qdropp)
}
/*
- * Query the current queue limit for per-workstream queues for a protocol.
+ * Query current per-workstream queue limit for a protocol.
*/
void
netisr_getqlimit(const struct netisr_handler *nhp, u_int *qlimitp)
@@ -511,10 +451,10 @@ netisr_getqlimit(const struct netisr_handler *nhp, u_int *qlimitp)
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_RLOCK(&tracker);
- KASSERT(np[proto].np_handler != NULL,
+ KASSERT(netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
- *qlimitp = np[proto].np_qlimit;
+ *qlimitp = netisr_proto[proto].np_qlimit;
NETISR_RUNLOCK(&tracker);
}
@@ -543,14 +483,12 @@ netisr_setqlimit(const struct netisr_handler *nhp, u_int qlimit)
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_WLOCK();
- KASSERT(np[proto].np_handler != NULL,
+ KASSERT(netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
- np[proto].np_qlimit = qlimit;
- for (i = 0; i <= mp_maxid; i++) {
- if (CPU_ABSENT(i))
- continue;
+ netisr_proto[proto].np_qlimit = qlimit;
+ CPU_FOREACH(i) {
#ifndef __rtems__
npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
#else /* __rtems__ */
@@ -608,19 +546,17 @@ netisr_unregister(const struct netisr_handler *nhp)
("%s(%u): protocol too big for %s", __func__, proto, name));
NETISR_WLOCK();
- KASSERT(np[proto].np_handler != NULL,
+ KASSERT(netisr_proto[proto].np_handler != NULL,
("%s(%u): protocol not registered for %s", __func__, proto,
name));
- np[proto].np_name = NULL;
- np[proto].np_handler = NULL;
- np[proto].np_m2flow = NULL;
- np[proto].np_m2cpuid = NULL;
- np[proto].np_qlimit = 0;
- np[proto].np_policy = 0;
- for (i = 0; i <= mp_maxid; i++) {
- if (CPU_ABSENT(i))
- continue;
+ netisr_proto[proto].np_name = NULL;
+ netisr_proto[proto].np_handler = NULL;
+ netisr_proto[proto].np_m2flow = NULL;
+ netisr_proto[proto].np_m2cpuid = NULL;
+ netisr_proto[proto].np_qlimit = 0;
+ netisr_proto[proto].np_policy = 0;
+ CPU_FOREACH(i) {
#ifndef __rtems__
npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
#else /* __rtems__ */
@@ -744,22 +680,23 @@ netisr_process_workstream_proto(struct netisr_workstream *nwsp, u_int proto)
if (local_npw.nw_head == NULL)
local_npw.nw_tail = NULL;
local_npw.nw_len--;
- VNET_ASSERT(m->m_pkthdr.rcvif != NULL);
+ VNET_ASSERT(m->m_pkthdr.rcvif != NULL,
+ ("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m));
CURVNET_SET(m->m_pkthdr.rcvif->if_vnet);
- np[proto].np_handler(m);
+ netisr_proto[proto].np_handler(m);
CURVNET_RESTORE();
}
KASSERT(local_npw.nw_len == 0,
("%s(%u): len %u", __func__, proto, local_npw.nw_len));
- if (np[proto].np_drainedcpu)
- np[proto].np_drainedcpu(nwsp->nws_cpu);
+ if (netisr_proto[proto].np_drainedcpu)
+ netisr_proto[proto].np_drainedcpu(nwsp->nws_cpu);
NWS_LOCK(nwsp);
npwp->nw_handled += handled;
return (handled);
}
/*
- * SWI handler for netisr -- processes prackets in a set of workstreams that
+ * SWI handler for netisr -- processes packets in a set of workstreams that
* it owns, woken up by calls to NWS_SIGNAL(). If this workstream is already
* being direct dispatched, go back to sleep and wait for the dispatching
* thread to wake us up again.
@@ -827,6 +764,11 @@ netisr_queue_workstream(struct netisr_workstream *nwsp, u_int proto,
npwp->nw_len++;
if (npwp->nw_len > npwp->nw_watermark)
npwp->nw_watermark = npwp->nw_len;
+
+ /*
+ * We must set the bit regardless of NWS_RUNNING, so that
+ * swi_net() keeps calling netisr_process_workstream_proto().
+ */
nwsp->nws_pendingbits |= (1 << proto);
if (!(nwsp->nws_flags &
(NWS_RUNNING | NWS_DISPATCHING | NWS_SCHEDULED))) {
@@ -887,10 +829,10 @@ netisr_queue_src(u_int proto, uintptr_t source, struct mbuf *m)
#ifdef NETISR_LOCKING
NETISR_RLOCK(&tracker);
#endif
- KASSERT(np[proto].np_handler != NULL,
+ KASSERT(netisr_proto[proto].np_handler != NULL,
("%s: invalid proto %u", __func__, proto));
- m = netisr_select_cpuid(&np[proto], source, m, &cpuid);
+ m = netisr_select_cpuid(&netisr_proto[proto], source, m, &cpuid);
if (m != NULL) {
KASSERT(!CPU_ABSENT(cpuid), ("%s: CPU %u absent", __func__,
cpuid));
@@ -911,7 +853,7 @@ netisr_queue(u_int proto, struct mbuf *m)
}
/*
- * Dispatch a packet for netisr processing, direct dispatch permitted by
+ * Dispatch a packet for netisr processing; direct dispatch is permitted by
* calling context.
*/
int
@@ -936,7 +878,7 @@ netisr_dispatch_src(u_int proto, uintptr_t source, struct mbuf *m)
#ifdef NETISR_LOCKING
NETISR_RLOCK(&tracker);
#endif
- KASSERT(np[proto].np_handler != NULL,
+ KASSERT(netisr_proto[proto].np_handler != NULL,
("%s: invalid proto %u", __func__, proto));
/*
@@ -951,7 +893,7 @@ netisr_dispatch_src(u_int proto, uintptr_t source, struct mbuf *m)
npwp = &nwsp->nws_work[proto];
npwp->nw_dispatched++;
npwp->nw_handled++;
- np[proto].np_handler(m);
+ netisr_proto[proto].np_handler(m);
error = 0;
goto out_unlock;
}
@@ -961,7 +903,7 @@ netisr_dispatch_src(u_int proto, uintptr_t source, struct mbuf *m)
* dispatch if we're on the right CPU and the netisr worker isn't
* already running.
*/
- m = netisr_select_cpuid(&np[proto], source, m, &cpuid);
+ m = netisr_select_cpuid(&netisr_proto[proto], source, m, &cpuid);
if (m == NULL) {
error = ENOBUFS;
goto out_unlock;
@@ -1000,7 +942,7 @@ netisr_dispatch_src(u_int proto, uintptr_t source, struct mbuf *m)
*/
nwsp->nws_flags |= NWS_DISPATCHING;
NWS_UNLOCK(nwsp);
- np[proto].np_handler(m);
+ netisr_proto[proto].np_handler(m);
NWS_LOCK(nwsp);
nwsp->nws_flags &= ~NWS_DISPATCHING;
npwp->nw_handled++;
@@ -1171,6 +1113,166 @@ netisr_start(void *arg)
SYSINIT(netisr_start, SI_SUB_SMP, SI_ORDER_MIDDLE, netisr_start, NULL);
#endif /* __rtems__ */
+/*
+ * Sysctl monitoring for netisr: query a list of registered protocols.
+ */
+static int
+sysctl_netisr_proto(SYSCTL_HANDLER_ARGS)
+{
+ struct rm_priotracker tracker;
+ struct sysctl_netisr_proto *snpp, *snp_array;
+ struct netisr_proto *npp;
+ u_int counter, proto;
+ int error;
+
+ if (req->newptr != NULL)
+ return (EINVAL);
+ snp_array = malloc(sizeof(*snp_array) * NETISR_MAXPROT, M_TEMP,
+ M_ZERO | M_WAITOK);
+ counter = 0;
+ NETISR_RLOCK(&tracker);
+ for (proto = 0; proto < NETISR_MAXPROT; proto++) {
+ npp = &netisr_proto[proto];
+ if (npp->np_name == NULL)
+ continue;
+ snpp = &snp_array[counter];
+ snpp->snp_version = sizeof(*snpp);
+ strlcpy(snpp->snp_name, npp->np_name, NETISR_NAMEMAXLEN);
+ snpp->snp_proto = proto;
+ snpp->snp_qlimit = npp->np_qlimit;
+ snpp->snp_policy = npp->np_policy;
+ if (npp->np_m2flow != NULL)
+ snpp->snp_flags |= NETISR_SNP_FLAGS_M2FLOW;
+ if (npp->np_m2cpuid != NULL)
+ snpp->snp_flags |= NETISR_SNP_FLAGS_M2CPUID;
+ if (npp->np_drainedcpu != NULL)
+ snpp->snp_flags |= NETISR_SNP_FLAGS_DRAINEDCPU;
+ counter++;
+ }
+ NETISR_RUNLOCK(&tracker);
+ KASSERT(counter <= NETISR_MAXPROT,
+ ("sysctl_netisr_proto: counter too big (%d)", counter));
+ error = SYSCTL_OUT(req, snp_array, sizeof(*snp_array) * counter);
+ free(snp_array, M_TEMP);
+ return (error);
+}
+
+SYSCTL_PROC(_net_isr, OID_AUTO, proto,
+ CTLFLAG_RD|CTLTYPE_STRUCT|CTLFLAG_MPSAFE, 0, 0, sysctl_netisr_proto,
+ "S,sysctl_netisr_proto",
+ "Return list of protocols registered with netisr");
+
+/*
+ * Sysctl monitoring for netisr: query a list of workstreams.
+ */
+static int
+sysctl_netisr_workstream(SYSCTL_HANDLER_ARGS)
+{
+ struct rm_priotracker tracker;
+ struct sysctl_netisr_workstream *snwsp, *snws_array;
+ struct netisr_workstream *nwsp;
+ u_int counter, cpuid;
+ int error;
+
+ if (req->newptr != NULL)
+ return (EINVAL);
+ snws_array = malloc(sizeof(*snws_array) * MAXCPU, M_TEMP,
+ M_ZERO | M_WAITOK);
+ counter = 0;
+ NETISR_RLOCK(&tracker);
+ CPU_FOREACH(cpuid) {
+ nwsp = DPCPU_ID_PTR(cpuid, nws);
+ if (nwsp->nws_intr_event == NULL)
+ continue;
+ NWS_LOCK(nwsp);
+ snwsp = &snws_array[counter];
+ snwsp->snws_version = sizeof(*snwsp);
+
+ /*
+ * For now, we equate workstream IDs and CPU IDs in the
+ * kernel, but expose them independently to userspace in case
+ * that assumption changes in the future.
+ */
+ snwsp->snws_wsid = cpuid;
+ snwsp->snws_cpu = cpuid;
+ if (nwsp->nws_intr_event != NULL)
+ snwsp->snws_flags |= NETISR_SNWS_FLAGS_INTR;
+ NWS_UNLOCK(nwsp);
+ counter++;
+ }
+ NETISR_RUNLOCK(&tracker);
+ KASSERT(counter <= MAXCPU,
+ ("sysctl_netisr_workstream: counter too big (%d)", counter));
+ error = SYSCTL_OUT(req, snws_array, sizeof(*snws_array) * counter);
+ free(snws_array, M_TEMP);
+ return (error);
+}
+
+SYSCTL_PROC(_net_isr, OID_AUTO, workstream,
+ CTLFLAG_RD|CTLTYPE_STRUCT|CTLFLAG_MPSAFE, 0, 0, sysctl_netisr_workstream,
+ "S,sysctl_netisr_workstream",
+ "Return list of workstreams implemented by netisr");
+
+/*
+ * Sysctl monitoring for netisr: query per-protocol data across all
+ * workstreams.
+ */
+static int
+sysctl_netisr_work(SYSCTL_HANDLER_ARGS)
+{
+ struct rm_priotracker tracker;
+ struct sysctl_netisr_work *snwp, *snw_array;
+ struct netisr_workstream *nwsp;
+ struct netisr_proto *npp;
+ struct netisr_work *nwp;
+ u_int counter, cpuid, proto;
+ int error;
+
+ if (req->newptr != NULL)
+ return (EINVAL);
+ snw_array = malloc(sizeof(*snw_array) * MAXCPU * NETISR_MAXPROT,
+ M_TEMP, M_ZERO | M_WAITOK);
+ counter = 0;
+ NETISR_RLOCK(&tracker);
+ CPU_FOREACH(cpuid) {
+ nwsp = DPCPU_ID_PTR(cpuid, nws);
+ if (nwsp->nws_intr_event == NULL)
+ continue;
+ NWS_LOCK(nwsp);
+ for (proto = 0; proto < NETISR_MAXPROT; proto++) {
+ npp = &netisr_proto[proto];
+ if (npp->np_name == NULL)
+ continue;
+ nwp = &nwsp->nws_work[proto];
+ snwp = &snw_array[counter];
+ snwp->snw_version = sizeof(*snwp);
+ snwp->snw_wsid = cpuid; /* See comment above. */
+ snwp->snw_proto = proto;
+ snwp->snw_len = nwp->nw_len;
+ snwp->snw_watermark = nwp->nw_watermark;
+ snwp->snw_dispatched = nwp->nw_dispatched;
+ snwp->snw_hybrid_dispatched =
+ nwp->nw_hybrid_dispatched;
+ snwp->snw_qdrops = nwp->nw_qdrops;
+ snwp->snw_queued = nwp->nw_queued;
+ snwp->snw_handled = nwp->nw_handled;
+ counter++;
+ }
+ NWS_UNLOCK(nwsp);
+ }
+ KASSERT(counter <= MAXCPU * NETISR_MAXPROT,
+ ("sysctl_netisr_work: counter too big (%d)", counter));
+ NETISR_RUNLOCK(&tracker);
+ error = SYSCTL_OUT(req, snw_array, sizeof(*snw_array) * counter);
+ free(snw_array, M_TEMP);
+ return (error);
+}
+
+SYSCTL_PROC(_net_isr, OID_AUTO, work,
+ CTLFLAG_RD|CTLTYPE_STRUCT|CTLFLAG_MPSAFE, 0, 0, sysctl_netisr_work,
+ "S,sysctl_netisr_work",
+ "Return list of per-workstream, per-protocol work in netisr");
+
#ifdef DDB
DB_SHOW_COMMAND(netisr, db_show_netisr)
{
@@ -1181,15 +1283,13 @@ DB_SHOW_COMMAND(netisr, db_show_netisr)
db_printf("%3s %6s %5s %5s %5s %8s %8s %8s %8s\n", "CPU", "Proto",
"Len", "WMark", "Max", "Disp", "HDisp", "Drop", "Queue");
- for (cpuid = 0; cpuid <= mp_maxid; cpuid++) {
- if (CPU_ABSENT(cpuid))
- continue;
+ CPU_FOREACH(cpuid) {
nwsp = DPCPU_ID_PTR(cpuid, nws);
if (nwsp->nws_intr_event == NULL)
continue;
first = 1;
for (proto = 0; proto < NETISR_MAXPROT; proto++) {
- if (np[proto].np_handler == NULL)
+ if (netisr_proto[proto].np_handler == NULL)
continue;
nwp = &nwsp->nws_work[proto];
if (first) {
@@ -1199,7 +1299,7 @@ DB_SHOW_COMMAND(netisr, db_show_netisr)
db_printf("%3s ", "");
db_printf(
"%6s %5d %5d %5d %8ju %8ju %8ju %8ju\n",
- np[proto].np_name, nwp->nw_len,
+ netisr_proto[proto].np_name, nwp->nw_len,
nwp->nw_watermark, nwp->nw_qlimit,
nwp->nw_dispatched, nwp->nw_hybrid_dispatched,
nwp->nw_qdrops, nwp->nw_queued);
diff --git a/freebsd/sys/net/netisr.h b/freebsd/sys/net/netisr.h
index 72e7f17f..cd692f6d 100644
--- a/freebsd/sys/net/netisr.h
+++ b/freebsd/sys/net/netisr.h
@@ -1,7 +1,11 @@
/*-
* Copyright (c) 2007-2009 Robert N. M. Watson
+ * Copyright (c) 2010 Juniper Networks, Inc.
* All rights reserved.
*
+ * This software was developed by Robert N. M. Watson under contract
+ * to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -28,7 +32,6 @@
#ifndef _NET_NETISR_H_
#define _NET_NETISR_H_
-#ifdef _KERNEL
/*
* The netisr (network interrupt service routine) provides a deferred
@@ -39,6 +42,13 @@
* Historically, this was implemented by the BSD software ISR facility; it is
* now implemented via a software ithread (SWI).
*/
+
+/*
+ * Protocol numbers, which are encoded in monitoring applications and kernel
+ * modules. Internally, these are used in bit shift operations so must have
+ * a value 0 < proto < 32; we currently further limit at compile-time to 16
+ * for array-sizing purposes.
+ */
#define NETISR_IP 1
#define NETISR_IGMP 2 /* IGMPv3 output queue */
#define NETISR_ROUTE 3 /* routing socket */
@@ -52,6 +62,78 @@
#define NETISR_NATM 11
#define NETISR_EPAIR 12 /* if_epair(4) */
+/*
+ * Protocol ordering and affinity policy constants. See the detailed
+ * discussion of policies later in the file.
+ */
+#define NETISR_POLICY_SOURCE 1 /* Maintain source ordering. */
+#define NETISR_POLICY_FLOW 2 /* Maintain flow ordering. */
+#define NETISR_POLICY_CPU 3 /* Protocol determines CPU placement. */
+
+/*
+ * Monitoring data structures, exported by sysctl(2).
+ *
+ * Three sysctls are defined. First, a per-protocol structure exported by
+ * net.isr.proto.
+ */
+#define NETISR_NAMEMAXLEN 32
+struct sysctl_netisr_proto {
+ u_int snp_version; /* Length of struct. */
+ char snp_name[NETISR_NAMEMAXLEN]; /* nh_name */
+ u_int snp_proto; /* nh_proto */
+ u_int snp_qlimit; /* nh_qlimit */
+ u_int snp_policy; /* nh_policy */
+ u_int snp_flags; /* Various flags. */
+ u_int _snp_ispare[7];
+};
+
+/*
+ * Flags for sysctl_netisr_proto.snp_flags.
+ */
+#define NETISR_SNP_FLAGS_M2FLOW 0x00000001 /* nh_m2flow */
+#define NETISR_SNP_FLAGS_M2CPUID 0x00000002 /* nh_m2cpuid */
+#define NETISR_SNP_FLAGS_DRAINEDCPU 0x00000004 /* nh_drainedcpu */
+
+/*
+ * Next, a structure per-workstream, with per-protocol data, exported as
+ * net.isr.workstream.
+ */
+struct sysctl_netisr_workstream {
+ u_int snws_version; /* Length of struct. */
+ u_int snws_flags; /* Various flags. */
+ u_int snws_wsid; /* Workstream ID. */
+ u_int snws_cpu; /* nws_cpu */
+ u_int _snws_ispare[12];
+};
+
+/*
+ * Flags for sysctl_netisr_workstream.snws_flags
+ */
+#define NETISR_SNWS_FLAGS_INTR 0x00000001 /* nws_intr_event */
+
+/*
+ * Finally, a per-workstream-per-protocol structure, exported as
+ * net.isr.work.
+ */
+struct sysctl_netisr_work {
+ u_int snw_version; /* Length of struct. */
+ u_int snw_wsid; /* Workstream ID. */
+ u_int snw_proto; /* Protocol number. */
+ u_int snw_len; /* nw_len */
+ u_int snw_watermark; /* nw_watermark */
+ u_int _snw_ispare[3];
+
+ uint64_t snw_dispatched; /* nw_dispatched */
+ uint64_t snw_hybrid_dispatched; /* nw_hybrid_dispatched */
+ uint64_t snw_qdrops; /* nw_qdrops */
+ uint64_t snw_queued; /* nw_queued */
+ uint64_t snw_handled; /* nw_handled */
+
+ uint64_t _snw_llspare[7];
+};
+
+#ifdef _KERNEL
+
/*-
* Protocols express ordering constraints and affinity preferences by
* implementing one or neither of nh_m2flow and nh_m2cpuid, which are used by
@@ -91,10 +173,6 @@ typedef struct mbuf *netisr_m2cpuid_t(struct mbuf *m, uintptr_t source,
typedef struct mbuf *netisr_m2flow_t(struct mbuf *m, uintptr_t source);
typedef void netisr_drainedcpu_t(u_int cpuid);
-#define NETISR_POLICY_SOURCE 1 /* Maintain source ordering. */
-#define NETISR_POLICY_FLOW 2 /* Maintain flow ordering. */
-#define NETISR_POLICY_CPU 3 /* Protocol determines CPU placement. */
-
/*
* Data structure describing a protocol handler.
*/
diff --git a/freebsd/sys/net/netisr_internal.h b/freebsd/sys/net/netisr_internal.h
new file mode 100644
index 00000000..40afaf16
--- /dev/null
+++ b/freebsd/sys/net/netisr_internal.h
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2007-2009 Robert N. M. Watson
+ * Copyright (c) 2010 Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson under contract
+ * to Juniper Networks, Inc.
+ *
+ * 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$
+ */
+
+#ifndef _NET_NETISR_INTERNAL_H_
+#define _NET_NETISR_INTERNAL_H_
+
+#ifndef _WANT_NETISR_INTERNAL
+#error "no user-serviceable parts inside"
+#endif
+
+/*
+ * These definitions are private to the netisr implementation, but provided
+ * here for use by post-mortem crashdump analysis tools. They should not be
+ * used in any other context as they can and will change. Public definitions
+ * may be found in netisr.h.
+ */
+
+#ifndef _KERNEL
+typedef void *netisr_handler_t;
+typedef void *netisr_m2flow_t;
+typedef void *netisr_m2cpuid_t;
+typedef void *netisr_drainedcpu_t;
+#endif
+
+/*
+ * Each protocol is described by a struct netisr_proto, which holds all
+ * global per-protocol information. This data structure is set up by
+ * netisr_register(), and derived from the public struct netisr_handler.
+ */
+struct netisr_proto {
+ const char *np_name; /* Character string protocol name. */
+ netisr_handler_t *np_handler; /* Protocol handler. */
+ netisr_m2flow_t *np_m2flow; /* Query flow for untagged packet. */
+ netisr_m2cpuid_t *np_m2cpuid; /* Query CPU to process packet on. */
+ netisr_drainedcpu_t *np_drainedcpu; /* Callback when drained a queue. */
+ u_int np_qlimit; /* Maximum per-CPU queue depth. */
+ u_int np_policy; /* Work placement policy. */
+};
+
+#define NETISR_MAXPROT 16 /* Compile-time limit. */
+
+/*
+ * Protocol-specific work for each workstream is described by struct
+ * netisr_work. Each work descriptor consists of an mbuf queue and
+ * statistics.
+ */
+struct netisr_work {
+ /*
+ * Packet queue, linked by m_nextpkt.
+ */
+ struct mbuf *nw_head;
+ struct mbuf *nw_tail;
+ u_int nw_len;
+ u_int nw_qlimit;
+ u_int nw_watermark;
+
+ /*
+ * Statistics -- written unlocked, but mostly from curcpu.
+ */
+ u_int64_t nw_dispatched; /* Number of direct dispatches. */
+ u_int64_t nw_hybrid_dispatched; /* "" hybrid dispatches. */
+ u_int64_t nw_qdrops; /* "" drops. */
+ u_int64_t nw_queued; /* "" enqueues. */
+ u_int64_t nw_handled; /* "" handled in worker. */
+};
+
+/*
+ * Workstreams hold a queue of ordered work across each protocol, and are
+ * described by netisr_workstream. Each workstream is associated with a
+ * worker thread, which in turn is pinned to a CPU. Work associated with a
+ * workstream can be processd in other threads during direct dispatch;
+ * concurrent processing is prevented by the NWS_RUNNING flag, which
+ * indicates that a thread is already processing the work queue. It is
+ * important to prevent a directly dispatched packet from "skipping ahead" of
+ * work already in the workstream queue.
+ */
+struct netisr_workstream {
+ struct intr_event *nws_intr_event; /* Handler for stream. */
+ void *nws_swi_cookie; /* swi(9) cookie for stream. */
+ struct mtx nws_mtx; /* Synchronize work. */
+ u_int nws_cpu; /* CPU pinning. */
+ u_int nws_flags; /* Wakeup flags. */
+ u_int nws_pendingbits; /* Scheduled protocols. */
+
+ /*
+ * Each protocol has per-workstream data.
+ */
+ struct netisr_work nws_work[NETISR_MAXPROT];
+} __aligned(CACHE_LINE_SIZE);
+
+/*
+ * Per-workstream flags.
+ */
+#define NWS_RUNNING 0x00000001 /* Currently running in a thread. */
+#define NWS_DISPATCHING 0x00000002 /* Currently being direct-dispatched. */
+#define NWS_SCHEDULED 0x00000004 /* Signal issued. */
+
+#endif /* !_NET_NETISR_INTERNAL_H_ */
diff --git a/freebsd/sys/net/radix_mpath.c b/freebsd/sys/net/radix_mpath.c
index bb7b6fd4..6a3e3ef7 100644
--- a/freebsd/sys/net/radix_mpath.c
+++ b/freebsd/sys/net/radix_mpath.c
@@ -102,10 +102,7 @@ rt_mpath_matchgate(struct rtentry *rt, struct sockaddr *gate)
{
struct radix_node *rn;
- if (!rn_mpath_next((struct radix_node *)rt))
- return rt;
-
- if (!gate)
+ if (!gate || !rt->rt_gateway)
return NULL;
/* beyond here, we use rn as the master copy */
diff --git a/freebsd/sys/net/raw_cb.h b/freebsd/sys/net/raw_cb.h
index 35b546c5..1b347e02 100644
--- a/freebsd/sys/net/raw_cb.h
+++ b/freebsd/sys/net/raw_cb.h
@@ -70,9 +70,14 @@ pr_init_t raw_init;
* Library routines for raw socket usrreq functions; will always be wrapped
* so that protocol-specific functions can be handled.
*/
+typedef int (*raw_input_cb_fn)(struct mbuf *, struct sockproto *,
+ struct sockaddr *, struct rawcb *);
+
int raw_attach(struct socket *, int);
void raw_detach(struct rawcb *);
void raw_input(struct mbuf *, struct sockproto *, struct sockaddr *);
+void raw_input_ext(struct mbuf *, struct sockproto *, struct sockaddr *,
+ raw_input_cb_fn);
/*
* Generic pr_usrreqs entries for raw socket protocols, usually wrapped so
diff --git a/freebsd/sys/net/raw_usrreq.c b/freebsd/sys/net/raw_usrreq.c
index 0723799f..0d7973e9 100644
--- a/freebsd/sys/net/raw_usrreq.c
+++ b/freebsd/sys/net/raw_usrreq.c
@@ -73,6 +73,14 @@ raw_init(void)
void
raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
{
+
+ return (raw_input_ext(m0, proto, src, NULL));
+}
+
+void
+raw_input_ext(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src,
+ raw_input_cb_fn cb)
+{
struct rawcb *rp;
struct mbuf *m = m0;
struct socket *last;
@@ -85,6 +93,8 @@ raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
if (rp->rcb_proto.sp_protocol &&
rp->rcb_proto.sp_protocol != proto->sp_protocol)
continue;
+ if (cb != NULL && (*cb)(m, proto, src, rp) != 0)
+ continue;
if (last) {
struct mbuf *n;
n = m_copy(m, 0, (int)M_COPYALL);
diff --git a/freebsd/sys/net/route.c b/freebsd/sys/net/route.c
index 5827cc00..3821c208 100644
--- a/freebsd/sys/net/route.c
+++ b/freebsd/sys/net/route.c
@@ -37,6 +37,7 @@
***********************************************************************/
#include <rtems/bsd/local/opt_inet.h>
+#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/local/opt_route.h>
#include <rtems/bsd/local/opt_mrouting.h>
#include <rtems/bsd/local/opt_mpath.h>
@@ -69,12 +70,34 @@
#include <vm/uma.h>
+/* We use 4 bits in the mbuf flags, thus we are limited to 16 FIBS. */
+#define RT_MAXFIBS 16
+
+/* Kernel config default option. */
+#ifdef ROUTETABLES
+#if ROUTETABLES <= 0
+#error "ROUTETABLES defined too low"
+#endif
+#if ROUTETABLES > RT_MAXFIBS
+#error "ROUTETABLES defined too big"
+#endif
+#define RT_NUMFIBS ROUTETABLES
+#endif /* ROUTETABLES */
+/* Initialize to default if not otherwise set. */
+#ifndef RT_NUMFIBS
+#define RT_NUMFIBS 1
+#endif
+
u_int rt_numfibs = RT_NUMFIBS;
-SYSCTL_INT(_net, OID_AUTO, fibs, CTLFLAG_RD, &rt_numfibs, 0, "");
+SYSCTL_UINT(_net, OID_AUTO, fibs, CTLFLAG_RD, &rt_numfibs, 0, "");
/*
* Allow the boot code to allow LESS than RT_MAXFIBS to be used.
* We can't do more because storage is statically allocated for now.
- * (for compatibility reasons.. this will change).
+ * (for compatibility reasons.. this will change. When this changes, code should
+ * be refactored to protocol independent parts and protocol dependent parts,
+ * probably hanging of domain(9) specific storage to not need the full
+ * fib * af RNH allocation etc. but allow tuning the number of tables per
+ * address family).
*/
TUNABLE_INT("net.fibs", &rt_numfibs);
@@ -84,9 +107,12 @@ TUNABLE_INT("net.fibs", &rt_numfibs);
* changes for the FIB of the caller when adding a new set of addresses
* to an interface. XXX this is a shotgun aproach to a problem that needs
* a more fine grained solution.. that will come.
+ * XXX also has the problems getting the FIB from curthread which will not
+ * always work given the fib can be overridden and prefixes can be added
+ * from the network stack context.
*/
u_int rt_add_addr_allfibs = 1;
-SYSCTL_INT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RW,
+SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RW,
&rt_add_addr_allfibs, 0, "");
TUNABLE_INT("net.add_addr_allfibs", &rt_add_addr_allfibs);
@@ -118,12 +144,6 @@ VNET_DEFINE(int, rttrash); /* routes not in table but not freed */
static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */
#define V_rtzone VNET(rtzone)
-#if 0
-/* default fib for tunnels to use */
-u_int tunnel_fib = 0;
-SYSCTL_INT(_net, OID_AUTO, tunnelfib, CTLFLAG_RD, &tunnel_fib, 0, "");
-#endif
-
#ifndef __rtems__
/*
* handler for net.my_fibnum
@@ -206,27 +226,23 @@ vnet_route_init(const void *unused __unused)
V_rtzone = uma_zcreate("rtentry", sizeof(struct rtentry), NULL, NULL,
NULL, NULL, UMA_ALIGN_PTR, 0);
for (dom = domains; dom; dom = dom->dom_next) {
- if (dom->dom_rtattach) {
- for (table = 0; table < rt_numfibs; table++) {
- if ( (fam = dom->dom_family) == AF_INET ||
- table == 0) {
- /* for now only AF_INET has > 1 table */
- /* XXX MRT
- * rtattach will be also called
- * from vfs_export.c but the
- * offset will be 0
- * (only for AF_INET and AF_INET6
- * which don't need it anyhow)
- */
- rnh = rt_tables_get_rnh_ptr(table, fam);
- if (rnh == NULL)
- panic("%s: rnh NULL", __func__);
- dom->dom_rtattach((void **)rnh,
- dom->dom_rtoffset);
- } else {
- break;
- }
- }
+ if (dom->dom_rtattach == NULL)
+ continue;
+
+ for (table = 0; table < rt_numfibs; table++) {
+ fam = dom->dom_family;
+ if (table != 0 && fam != AF_INET6 && fam != AF_INET)
+ break;
+
+ /*
+ * XXX MRT rtattach will be also called from
+ * vfs_export.c but the offset will be 0 (only for
+ * AF_INET and AF_INET6 which don't need it anyhow).
+ */
+ rnh = rt_tables_get_rnh_ptr(table, fam);
+ if (rnh == NULL)
+ panic("%s: rnh NULL", __func__);
+ dom->dom_rtattach((void **)rnh, dom->dom_rtoffset);
}
}
}
@@ -243,20 +259,19 @@ vnet_route_uninit(const void *unused __unused)
struct radix_node_head **rnh;
for (dom = domains; dom; dom = dom->dom_next) {
- if (dom->dom_rtdetach) {
- for (table = 0; table < rt_numfibs; table++) {
- if ( (fam = dom->dom_family) == AF_INET ||
- table == 0) {
- /* For now only AF_INET has > 1 tbl. */
- rnh = rt_tables_get_rnh_ptr(table, fam);
- if (rnh == NULL)
- panic("%s: rnh NULL", __func__);
- dom->dom_rtdetach((void **)rnh,
- dom->dom_rtoffset);
- } else {
- break;
- }
- }
+ if (dom->dom_rtdetach == NULL)
+ continue;
+
+ for (table = 0; table < rt_numfibs; table++) {
+ fam = dom->dom_family;
+
+ if (table != 0 && fam != AF_INET6 && fam != AF_INET)
+ break;
+
+ rnh = rt_tables_get_rnh_ptr(table, fam);
+ if (rnh == NULL)
+ panic("%s: rnh NULL", __func__);
+ dom->dom_rtdetach((void **)rnh, dom->dom_rtoffset);
}
}
}
@@ -286,7 +301,8 @@ setfib(struct thread *td, struct setfib_args *uap)
void
rtalloc(struct route *ro)
{
- rtalloc_ign_fib(ro, 0UL, 0);
+
+ rtalloc_ign_fib(ro, 0UL, RT_DEFAULT_FIB);
}
void
@@ -306,7 +322,7 @@ rtalloc_ign(struct route *ro, u_long ignore)
RTFREE(rt);
ro->ro_rt = NULL;
}
- ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, ignore, 0);
+ ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, ignore, RT_DEFAULT_FIB);
if (ro->ro_rt)
RT_UNLOCK(ro->ro_rt);
}
@@ -336,7 +352,8 @@ rtalloc_ign_fib(struct route *ro, u_long ignore, u_int fibnum)
struct rtentry *
rtalloc1(struct sockaddr *dst, int report, u_long ignflags)
{
- return (rtalloc1_fib(dst, report, ignflags, 0));
+
+ return (rtalloc1_fib(dst, report, ignflags, RT_DEFAULT_FIB));
}
struct rtentry *
@@ -344,7 +361,6 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
u_int fibnum)
{
struct radix_node_head *rnh;
- struct rtentry *rt;
struct radix_node *rn;
struct rtentry *newrt;
struct rt_addrinfo info;
@@ -352,17 +368,23 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
int needlock;
KASSERT((fibnum < rt_numfibs), ("rtalloc1_fib: bad fibnum"));
- if (dst->sa_family != AF_INET) /* Only INET supports > 1 fib now */
- fibnum = 0;
+ switch (dst->sa_family) {
+ case AF_INET6:
+ case AF_INET:
+ /* We support multiple FIBs. */
+ break;
+ default:
+ fibnum = RT_DEFAULT_FIB;
+ break;
+ }
rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
newrt = NULL;
+ if (rnh == NULL)
+ goto miss;
+
/*
* Look up the address in the table for that Address Family
*/
- if (rnh == NULL) {
- V_rtstat.rts_unreach++;
- goto miss;
- }
needlock = !(ignflags & RTF_RNH_LOCKED);
if (needlock)
RADIX_NODE_HEAD_RLOCK(rnh);
@@ -372,7 +394,7 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
#endif
rn = rnh->rnh_matchaddr(dst, rnh);
if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) {
- newrt = rt = RNTORT(rn);
+ newrt = RNTORT(rn);
RT_LOCK(newrt);
RT_ADDREF(newrt);
if (needlock)
@@ -387,8 +409,9 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
* Which basically means
* "caint get there frm here"
*/
- V_rtstat.rts_unreach++;
miss:
+ V_rtstat.rts_unreach++;
+
if (report) {
/*
* If required, report the failure to the supervising
@@ -397,8 +420,8 @@ miss:
*/
bzero(&info, sizeof(info));
info.rti_info[RTAX_DST] = dst;
- rt_missmsg(msgtype, &info, 0, err);
- }
+ rt_missmsg_fib(msgtype, &info, 0, err, fibnum);
+ }
done:
if (newrt)
RT_LOCK_ASSERT(newrt);
@@ -499,7 +522,8 @@ rtredirect(struct sockaddr *dst,
int flags,
struct sockaddr *src)
{
- rtredirect_fib(dst, gateway, netmask, flags, src, 0);
+
+ rtredirect_fib(dst, gateway, netmask, flags, src, RT_DEFAULT_FIB);
}
void
@@ -545,7 +569,7 @@ rtredirect_fib(struct sockaddr *dst,
goto done;
/*
* Create a new entry if we just got back a wildcard entry
- * or the the lookup failed. This is necessary for hosts
+ * or the lookup failed. This is necessary for hosts
* which use routing redirects generated by smart gateways
* to dynamically build the routing tables.
*/
@@ -622,7 +646,7 @@ out:
info.rti_info[RTAX_GATEWAY] = gateway;
info.rti_info[RTAX_NETMASK] = netmask;
info.rti_info[RTAX_AUTHOR] = src;
- rt_missmsg(RTM_REDIRECT, &info, flags, error);
+ rt_missmsg_fib(RTM_REDIRECT, &info, flags, error, fibnum);
if (ifa != NULL)
ifa_free(ifa);
}
@@ -630,7 +654,8 @@ out:
int
rtioctl(u_long req, caddr_t data)
{
- return (rtioctl_fib(req, data, 0));
+
+ return (rtioctl_fib(req, data, RT_DEFAULT_FIB));
}
/*
@@ -660,7 +685,8 @@ rtioctl_fib(u_long req, caddr_t data, u_int fibnum)
struct ifaddr *
ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway)
{
- return (ifa_ifwithroute_fib(flags, dst, gateway, 0));
+
+ return (ifa_ifwithroute_fib(flags, dst, gateway, RT_DEFAULT_FIB));
}
struct ifaddr *
@@ -745,7 +771,9 @@ rtrequest(int req,
int flags,
struct rtentry **ret_nrt)
{
- return (rtrequest_fib(req, dst, gateway, netmask, flags, ret_nrt, 0));
+
+ return (rtrequest_fib(req, dst, gateway, netmask, flags, ret_nrt,
+ RT_DEFAULT_FIB));
}
int
@@ -784,7 +812,8 @@ rtrequest_fib(int req,
int
rt_getifa(struct rt_addrinfo *info)
{
- return (rt_getifa_fib(info, 0));
+
+ return (rt_getifa_fib(info, RT_DEFAULT_FIB));
}
/*
@@ -1038,11 +1067,20 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
register struct radix_node_head *rnh;
struct ifaddr *ifa;
struct sockaddr *ndst;
+ struct sockaddr_storage mdst;
#define senderr(x) { error = x ; goto bad; }
KASSERT((fibnum < rt_numfibs), ("rtrequest1_fib: bad fibnum"));
- if (dst->sa_family != AF_INET) /* Only INET supports > 1 fib now */
- fibnum = 0;
+ switch (dst->sa_family) {
+ case AF_INET6:
+ case AF_INET:
+ /* We support multiple FIBs. */
+ break;
+ default:
+ fibnum = RT_DEFAULT_FIB;
+ break;
+ }
+
/*
* Find the correct routing tree to use for this Address Family
*/
@@ -1064,6 +1102,10 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
switch (req) {
case RTM_DELETE:
+ if (netmask) {
+ rt_maskedcopy(dst, (struct sockaddr *)&mdst, netmask);
+ dst = (struct sockaddr *)&mdst;
+ }
#ifdef RADIX_MPATH
if (rn_mpath_capable(rnh)) {
error = rn_mpath_update(req, info, rnh, ret_nrt);
@@ -1144,8 +1186,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
rt->rt_flags = RTF_UP | flags;
rt->rt_fibnum = fibnum;
/*
- * Add the gateway. Possibly re-malloc-ing the storage for it
- *
+ * Add the gateway. Possibly re-malloc-ing the storage for it.
*/
RT_LOCK(rt);
if ((error = rt_setgate(rt, dst, gateway)) != 0) {
@@ -1194,11 +1235,17 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
#ifdef FLOWTABLE
rt0 = NULL;
- /* XXX
- * "flow-table" only support IPv4 at the moment.
- */
+ /* "flow-table" only supports IPv6 and IPv4 at the moment. */
+ switch (dst->sa_family) {
+#ifdef notyet
+#ifdef INET6
+ case AF_INET6:
+#endif
+#endif
#ifdef INET
- if (dst->sa_family == AF_INET) {
+ case AF_INET:
+#endif
+#if defined(INET6) || defined(INET)
rn = rnh->rnh_matchaddr(dst, rnh);
if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) {
struct sockaddr *mask;
@@ -1237,9 +1284,9 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
}
}
}
+#endif/* INET6 || INET */
}
-#endif
-#endif
+#endif /* FLOWTABLE */
/* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes);
@@ -1261,9 +1308,20 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
}
#ifdef FLOWTABLE
else if (rt0 != NULL) {
+ switch (dst->sa_family) {
+#ifdef notyet
+#ifdef INET6
+ case AF_INET6:
+ flowtable_route_flush(V_ip6_ft, rt0);
+ break;
+#endif
+#endif
#ifdef INET
- flowtable_route_flush(V_ip_ft, rt0);
+ case AF_INET:
+ flowtable_route_flush(V_ip_ft, rt0);
+ break;
#endif
+ }
RTFREE(rt0);
}
#endif
@@ -1395,8 +1453,17 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
dst = ifa->ifa_addr;
netmask = ifa->ifa_netmask;
}
- if ( dst->sa_family != AF_INET)
- fibnum = 0;
+ if (dst->sa_len == 0)
+ return(EINVAL);
+ switch (dst->sa_family) {
+ case AF_INET6:
+ case AF_INET:
+ /* We support multiple FIBs. */
+ break;
+ default:
+ fibnum = RT_DEFAULT_FIB;
+ break;
+ }
if (fibnum == -1) {
if (rt_add_addr_allfibs == 0 && cmd == (int)RTM_ADD) {
#ifndef __rtems__
@@ -1413,8 +1480,6 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
startfib = fibnum;
endfib = fibnum;
}
- if (dst->sa_len == 0)
- return(EINVAL);
/*
* If it's a delete, check that if it exists,
@@ -1438,9 +1503,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
* Now go through all the requested tables (fibs) and do the
* requested action. Realistically, this will either be fib 0
* for protocols that don't do multiple tables or all the
- * tables for those that do. XXX For this version only AF_INET.
- * When that changes code should be refactored to protocol
- * independent parts and protocol dependent parts.
+ * tables for those that do.
*/
for ( fibnum = startfib; fibnum <= endfib; fibnum++) {
if (cmd == RTM_DELETE) {
@@ -1494,7 +1557,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
*/
bzero((caddr_t)&info, sizeof(info));
info.rti_ifa = ifa;
- info.rti_flags = flags | ifa->ifa_flags;
+ info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF);
info.rti_info[RTAX_DST] = dst;
/*
* doing this for compatibility reasons
@@ -1514,10 +1577,10 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
#ifdef RADIX_MPATH
/*
* in case address alias finds the first address
- * e.g. ifconfig bge0 192.103.54.246/24
- * e.g. ifconfig bge0 192.103.54.247/24
- * the address set in the route is 192.103.54.246
- * so we need to replace it with 192.103.54.247
+ * e.g. ifconfig bge0 192.0.2.246/24
+ * e.g. ifconfig bge0 192.0.2.247/24
+ * the address set in the route is 192.0.2.246
+ * so we need to replace it with 192.0.2.247
*/
if (memcmp(rt->rt_ifa->ifa_addr,
ifa->ifa_addr, ifa->ifa_addr->sa_len)) {
@@ -1538,7 +1601,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
}
RT_ADDREF(rt);
RT_UNLOCK(rt);
- rt_newaddrmsg(cmd, ifa, error, rt);
+ rt_newaddrmsg_fib(cmd, ifa, error, rt, fibnum);
RT_LOCK(rt);
RT_REMREF(rt);
if (cmd == RTM_DELETE) {
@@ -1580,12 +1643,14 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
return (error);
}
+#ifndef BURN_BRIDGES
/* special one for inet internal use. may not use. */
int
rtinit_fib(struct ifaddr *ifa, int cmd, int flags)
{
return (rtinit1(ifa, cmd, flags, -1));
}
+#endif
/*
* Set up a routing table entry, normally
@@ -1595,7 +1660,7 @@ int
rtinit(struct ifaddr *ifa, int cmd, int flags)
{
struct sockaddr *dst;
- int fib = 0;
+ int fib = RT_DEFAULT_FIB;
if (flags & RTF_HOST) {
dst = ifa->ifa_dstaddr;
@@ -1603,7 +1668,12 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
dst = ifa->ifa_addr;
}
- if (dst->sa_family == AF_INET)
+ switch (dst->sa_family) {
+ case AF_INET6:
+ case AF_INET:
+ /* We do support multiple FIBs. */
fib = -1;
+ break;
+ }
return (rtinit1(ifa, cmd, flags, fib));
}
diff --git a/freebsd/sys/net/route.h b/freebsd/sys/net/route.h
index 4014b3f6..b26ac441 100644
--- a/freebsd/sys/net/route.h
+++ b/freebsd/sys/net/route.h
@@ -86,30 +86,8 @@ struct rt_metrics {
#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ))
-/* MRT compile-time constants */
-#ifdef _KERNEL
- #ifndef ROUTETABLES
- #define RT_NUMFIBS 1
- #define RT_MAXFIBS 1
- #else
- /* while we use 4 bits in the mbuf flags, we are limited to 16 */
- #define RT_MAXFIBS 16
- #if ROUTETABLES > RT_MAXFIBS
- #define RT_NUMFIBS RT_MAXFIBS
- #error "ROUTETABLES defined too big"
- #else
- #if ROUTETABLES == 0
- #define RT_NUMFIBS 1
- #else
- #define RT_NUMFIBS ROUTETABLES
- #endif
- #endif
- #endif
-#endif
-
+#define RT_DEFAULT_FIB 0 /* Explicitly mark fib=0 restricted cases */
extern u_int rt_numfibs; /* number fo usable routing tables */
-extern u_int tunnel_fib; /* tunnels use these */
-extern u_int fwd_fib; /* packets being forwarded use these routes */
/*
* XXX kernel function pointer `rt_output' is visible to applications.
*/
@@ -325,7 +303,6 @@ struct rt_addrinfo {
#define RT_LOCK_INIT(_rt) \
mtx_init(&(_rt)->rt_mtx, "rtentry", NULL, MTX_DEF | MTX_DUPOK)
#define RT_LOCK(_rt) mtx_lock(&(_rt)->rt_mtx)
-#define RT_TRYLOCK(_rt) mtx_trylock(&(_rt)->rt_mtx)
#define RT_UNLOCK(_rt) mtx_unlock(&(_rt)->rt_mtx)
#define RT_LOCK_DESTROY(_rt) mtx_destroy(&(_rt)->rt_mtx)
#define RT_LOCK_ASSERT(_rt) mtx_assert(&(_rt)->rt_mtx, MA_OWNED)
@@ -360,22 +337,6 @@ struct rt_addrinfo {
RTFREE_LOCKED(_rt); \
} while (0)
-#define RT_TEMP_UNLOCK(_rt) do { \
- RT_ADDREF(_rt); \
- RT_UNLOCK(_rt); \
-} while (0)
-
-#define RT_RELOCK(_rt) do { \
- RT_LOCK(_rt); \
- if ((_rt)->rt_refcnt <= 1) { \
- rtfree(_rt); \
- _rt = 0; /* signal that it went away */ \
- } else { \
- RT_REMREF(_rt); \
- /* note that _rt is still valid */ \
- } \
-} while (0)
-
struct radix_node_head *rt_tables_get_rnh(int, int);
struct ifmultiaddr;
@@ -384,7 +345,9 @@ void rt_ieee80211msg(struct ifnet *, int, void *, size_t);
void rt_ifannouncemsg(struct ifnet *, int);
void rt_ifmsg(struct ifnet *);
void rt_missmsg(int, struct rt_addrinfo *, int, int);
+void rt_missmsg_fib(int, struct rt_addrinfo *, int, int, int);
void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
+void rt_newaddrmsg_fib(int, struct ifaddr *, int, struct rtentry *, int);
void rt_newmaddrmsg(int, struct ifmultiaddr *);
int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *);
@@ -418,8 +381,10 @@ void rtredirect(struct sockaddr *, struct sockaddr *,
int rtrequest(int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int, struct rtentry **);
+#ifndef BURN_BRIDGES
/* defaults to "all" FIBs */
int rtinit_fib(struct ifaddr *, int, int);
+#endif
/* XXX MRT NEW VERSIONS THAT USE FIBs
* For now the protocol indepedent versions are the same as the AF_INET ones
diff --git a/freebsd/sys/net/rtsock.c b/freebsd/sys/net/rtsock.c
index bfdecf87..beca84da 100644
--- a/freebsd/sys/net/rtsock.c
+++ b/freebsd/sys/net/rtsock.c
@@ -116,7 +116,34 @@ struct if_msghdr32 {
uint16_t ifm_index;
struct if_data32 ifm_data;
};
-#endif
+
+struct if_msghdrl32 {
+ uint16_t ifm_msglen;
+ uint8_t ifm_version;
+ uint8_t ifm_type;
+ int32_t ifm_addrs;
+ int32_t ifm_flags;
+ uint16_t ifm_index;
+ uint16_t _ifm_spare1;
+ uint16_t ifm_len;
+ uint16_t ifm_data_off;
+ struct if_data32 ifm_data;
+};
+
+struct ifa_msghdrl32 {
+ uint16_t ifam_msglen;
+ uint8_t ifam_version;
+ uint8_t ifam_type;
+ int32_t ifam_addrs;
+ int32_t ifam_flags;
+ uint16_t ifam_index;
+ uint16_t _ifam_spare1;
+ uint16_t ifam_len;
+ uint16_t ifam_data_off;
+ int32_t ifam_metric;
+ struct if_data32 ifam_data;
+};
+#endif /* COMPAT_FREEBSD32 */
MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
@@ -124,6 +151,13 @@ MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
static struct sockaddr route_src = { 2, PF_ROUTE, };
static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
+/*
+ * Used by rtsock/raw_input callback code to decide whether to filter the update
+ * notification to a socket bound to a particular FIB.
+ */
+#define RTS_FILTER_FIB M_PROTO8
+#define RTS_ALLFIBS -1
+
static struct {
int ip_count; /* attached w/ AF_INET */
int ip6_count; /* attached w/ AF_INET6 */
@@ -161,7 +195,7 @@ static void rt_setmetrics(u_long which, const struct rt_metrics *in,
struct rt_metrics_lite *out);
static void rt_getmetrics(const struct rt_metrics_lite *in,
struct rt_metrics *out);
-static void rt_dispatch(struct mbuf *, const struct sockaddr *);
+static void rt_dispatch(struct mbuf *, sa_family_t);
static struct netisr_handler rtsock_nh = {
.nh_name = "rtsock",
@@ -200,6 +234,31 @@ rts_init(void)
}
SYSINIT(rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rts_init, 0);
+static int
+raw_input_rts_cb(struct mbuf *m, struct sockproto *proto, struct sockaddr *src,
+ struct rawcb *rp)
+{
+ int fibnum;
+
+ KASSERT(m != NULL, ("%s: m is NULL", __func__));
+ KASSERT(proto != NULL, ("%s: proto is NULL", __func__));
+ KASSERT(rp != NULL, ("%s: rp is NULL", __func__));
+
+ /* No filtering requested. */
+ if ((m->m_flags & RTS_FILTER_FIB) == 0)
+ return (0);
+
+ /* Check if it is a rts and the fib matches the one of the socket. */
+ fibnum = M_GETFIB(m);
+ if (proto->sp_family != PF_ROUTE ||
+ rp->rcb_socket == NULL ||
+ rp->rcb_socket->so_fibnum == fibnum)
+ return (0);
+
+ /* Filtering requested and no match, the socket shall be skipped. */
+ return (1);
+}
+
static void
rts_input(struct mbuf *m)
{
@@ -216,7 +275,7 @@ rts_input(struct mbuf *m)
} else
route_proto.sp_protocol = 0;
- raw_input(m, &route_proto, &route_src);
+ raw_input_ext(m, &route_proto, &route_src, raw_input_rts_cb);
}
/*
@@ -428,7 +487,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
* Try to find an address on the given outgoing interface
* that belongs to the jail.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa;
sa = ifa->ifa_addr;
@@ -440,7 +499,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (!found) {
/*
* As a last resort return the 'default' jail address.
@@ -470,7 +529,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
* Try to find an address on the given outgoing interface
* that belongs to the jail.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa;
sa = ifa->ifa_addr;
@@ -483,7 +542,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (!found) {
/*
* As a last resort return the 'default' jail address.
@@ -521,6 +580,7 @@ route_output(struct mbuf *m, struct socket *so)
int len, error = 0;
struct ifnet *ifp = NULL;
union sockaddr_union saun;
+ sa_family_t saf = AF_UNSPEC;
#define senderr(e) { error = e; goto flush;}
if (m == NULL || ((m->m_len < sizeof(long)) &&
@@ -561,6 +621,7 @@ route_output(struct mbuf *m, struct socket *so)
(info.rti_info[RTAX_GATEWAY] != NULL &&
info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
senderr(EINVAL);
+ saf = info.rti_info[RTAX_DST]->sa_family;
/*
* Verify that the caller has the appropriate privilege; RTM_GET
* is the only operation the non-superuser is allowed.
@@ -898,6 +959,8 @@ flush:
Free(rtm);
}
if (m) {
+ M_SETFIB(m, so->so_fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
if (rp) {
/*
* XXX insure we don't get a copy by
@@ -905,10 +968,10 @@ flush:
*/
unsigned short family = rp->rcb_proto.sp_family;
rp->rcb_proto.sp_family = 0;
- rt_dispatch(m, info.rti_info[RTAX_DST]);
+ rt_dispatch(m, saf);
rp->rcb_proto.sp_family = family;
} else
- rt_dispatch(m, info.rti_info[RTAX_DST]);
+ rt_dispatch(m, saf);
}
}
return (error);
@@ -984,6 +1047,9 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
return (0);
}
+/*
+ * Used by the routing socket.
+ */
static struct mbuf *
rt_msg1(int type, struct rt_addrinfo *rtinfo)
{
@@ -1051,6 +1117,9 @@ rt_msg1(int type, struct rt_addrinfo *rtinfo)
return (m);
}
+/*
+ * Used by the sysctl code and routing socket.
+ */
static int
rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
{
@@ -1064,17 +1133,31 @@ again:
case RTM_DELADDR:
case RTM_NEWADDR:
- len = sizeof(struct ifa_msghdr);
+ if (w != NULL && w->w_op == NET_RT_IFLISTL) {
+#ifdef COMPAT_FREEBSD32
+ if (w->w_req->flags & SCTL_MASK32)
+ len = sizeof(struct ifa_msghdrl32);
+ else
+#endif
+ len = sizeof(struct ifa_msghdrl);
+ } else
+ len = sizeof(struct ifa_msghdr);
break;
case RTM_IFINFO:
#ifdef COMPAT_FREEBSD32
if (w != NULL && w->w_req->flags & SCTL_MASK32) {
- len = sizeof(struct if_msghdr32);
+ if (w->w_op == NET_RT_IFLISTL)
+ len = sizeof(struct if_msghdrl32);
+ else
+ len = sizeof(struct if_msghdr32);
break;
}
#endif
- len = sizeof(struct if_msghdr);
+ if (w != NULL && w->w_op == NET_RT_IFLISTL)
+ len = sizeof(struct if_msghdrl);
+ else
+ len = sizeof(struct if_msghdr);
break;
case RTM_NEWMADDR:
@@ -1137,7 +1220,8 @@ again:
* destination.
*/
void
-rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
+rt_missmsg_fib(int type, struct rt_addrinfo *rtinfo, int flags, int error,
+ int fibnum)
{
struct rt_msghdr *rtm;
struct mbuf *m;
@@ -1148,11 +1232,26 @@ rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
m = rt_msg1(type, rtinfo);
if (m == NULL)
return;
+
+ if (fibnum != RTS_ALLFIBS) {
+ KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: fibnum out "
+ "of range 0 <= %d < %d", __func__, fibnum, rt_numfibs));
+ M_SETFIB(m, fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
+ }
+
rtm = mtod(m, struct rt_msghdr *);
rtm->rtm_flags = RTF_DONE | flags;
rtm->rtm_errno = error;
rtm->rtm_addrs = rtinfo->rti_addrs;
- rt_dispatch(m, sa);
+ rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC);
+}
+
+void
+rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
+{
+
+ rt_missmsg_fib(type, rtinfo, flags, error, RTS_ALLFIBS);
}
/*
@@ -1177,7 +1276,7 @@ rt_ifmsg(struct ifnet *ifp)
ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
ifm->ifm_data = ifp->if_data;
ifm->ifm_addrs = 0;
- rt_dispatch(m, NULL);
+ rt_dispatch(m, AF_UNSPEC);
}
/*
@@ -1189,7 +1288,8 @@ rt_ifmsg(struct ifnet *ifp)
* copies of it.
*/
void
-rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
+rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt,
+ int fibnum)
{
struct rt_addrinfo info;
struct sockaddr *sa = NULL;
@@ -1247,10 +1347,24 @@ rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
rtm->rtm_errno = error;
rtm->rtm_addrs = info.rti_addrs;
}
- rt_dispatch(m, sa);
+ if (fibnum != RTS_ALLFIBS) {
+ KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: "
+ "fibnum out of range 0 <= %d < %d", __func__,
+ fibnum, rt_numfibs));
+ M_SETFIB(m, fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
+ }
+ rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC);
}
}
+void
+rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
+{
+
+ rt_newaddrmsg_fib(cmd, ifa, error, rt, RTS_ALLFIBS);
+}
+
/*
* This is the analogue to the rt_newaddrmsg which performs the same
* function but for multicast group memberhips. This is easier since
@@ -1283,7 +1397,7 @@ rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
__func__));
ifmam->ifmam_index = ifp->if_index;
ifmam->ifmam_addrs = info.rti_addrs;
- rt_dispatch(m, ifma->ifma_addr);
+ rt_dispatch(m, ifma->ifma_addr ? ifma->ifma_addr->sa_family : AF_UNSPEC);
}
static struct mbuf *
@@ -1343,7 +1457,7 @@ rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
if (m->m_flags & M_PKTHDR)
m->m_pkthdr.len += data_len;
mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
- rt_dispatch(m, NULL);
+ rt_dispatch(m, AF_UNSPEC);
}
}
@@ -1359,11 +1473,11 @@ rt_ifannouncemsg(struct ifnet *ifp, int what)
m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info);
if (m != NULL)
- rt_dispatch(m, NULL);
+ rt_dispatch(m, AF_UNSPEC);
}
static void
-rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
+rt_dispatch(struct mbuf *m, sa_family_t saf)
{
struct m_tag *tag;
@@ -1372,14 +1486,14 @@ rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
* use when injecting the mbuf into the routing socket buffer from
* the netisr.
*/
- if (sa != NULL) {
+ if (saf != AF_UNSPEC) {
tag = m_tag_get(PACKET_TAG_RTSOCKFAM, sizeof(unsigned short),
M_NOWAIT);
if (tag == NULL) {
m_freem(m);
return;
}
- *(unsigned short *)(tag + 1) = sa->sa_family;
+ *(unsigned short *)(tag + 1) = saf;
m_tag_prepend(m, tag);
}
#ifdef VIMAGE
@@ -1473,6 +1587,127 @@ copy_ifdata32(struct if_data *src, struct if_data32 *dst)
#endif
static int
+sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info,
+ struct walkarg *w, int len)
+{
+ struct if_msghdrl *ifm;
+
+#ifdef COMPAT_FREEBSD32
+ if (w->w_req->flags & SCTL_MASK32) {
+ struct if_msghdrl32 *ifm32;
+
+ ifm32 = (struct if_msghdrl32 *)w->w_tmem;
+ ifm32->ifm_addrs = info->rti_addrs;
+ ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+ ifm32->ifm_index = ifp->if_index;
+ ifm32->_ifm_spare1 = 0;
+ ifm32->ifm_len = sizeof(*ifm32);
+ ifm32->ifm_data_off = offsetof(struct if_msghdrl32, ifm_data);
+
+ copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len));
+ }
+#endif
+ ifm = (struct if_msghdrl *)w->w_tmem;
+ ifm->ifm_addrs = info->rti_addrs;
+ ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+ ifm->ifm_index = ifp->if_index;
+ ifm->_ifm_spare1 = 0;
+ ifm->ifm_len = sizeof(*ifm);
+ ifm->ifm_data_off = offsetof(struct if_msghdrl, ifm_data);
+
+ ifm->ifm_data = ifp->if_data;
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
+}
+
+static int
+sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info,
+ struct walkarg *w, int len)
+{
+ struct if_msghdr *ifm;
+
+#ifdef COMPAT_FREEBSD32
+ if (w->w_req->flags & SCTL_MASK32) {
+ struct if_msghdr32 *ifm32;
+
+ ifm32 = (struct if_msghdr32 *)w->w_tmem;
+ ifm32->ifm_addrs = info->rti_addrs;
+ ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+ ifm32->ifm_index = ifp->if_index;
+
+ copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len));
+ }
+#endif
+ ifm = (struct if_msghdr *)w->w_tmem;
+ ifm->ifm_addrs = info->rti_addrs;
+ ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+ ifm->ifm_index = ifp->if_index;
+
+ ifm->ifm_data = ifp->if_data;
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len));
+}
+
+static int
+sysctl_iflist_ifaml(struct ifaddr *ifa, struct rt_addrinfo *info,
+ struct walkarg *w, int len)
+{
+ struct ifa_msghdrl *ifam;
+
+#ifdef COMPAT_FREEBSD32
+ if (w->w_req->flags & SCTL_MASK32) {
+ struct ifa_msghdrl32 *ifam32;
+
+ ifam32 = (struct ifa_msghdrl32 *)w->w_tmem;
+ ifam32->ifam_addrs = info->rti_addrs;
+ ifam32->ifam_flags = ifa->ifa_flags;
+ ifam32->ifam_index = ifa->ifa_ifp->if_index;
+ ifam32->_ifam_spare1 = 0;
+ ifam32->ifam_len = sizeof(*ifam32);
+ ifam32->ifam_data_off =
+ offsetof(struct ifa_msghdrl32, ifam_data);
+ ifam32->ifam_metric = ifa->ifa_metric;
+
+ copy_ifdata32(&ifa->ifa_ifp->if_data, &ifam32->ifam_data);
+
+ return (SYSCTL_OUT(w->w_req, (caddr_t)ifam32, len));
+ }
+#endif
+
+ ifam = (struct ifa_msghdrl *)w->w_tmem;
+ ifam->ifam_addrs = info->rti_addrs;
+ ifam->ifam_flags = ifa->ifa_flags;
+ ifam->ifam_index = ifa->ifa_ifp->if_index;
+ ifam->_ifam_spare1 = 0;
+ ifam->ifam_len = sizeof(*ifam);
+ ifam->ifam_data_off = offsetof(struct ifa_msghdrl, ifam_data);
+ ifam->ifam_metric = ifa->ifa_metric;
+
+ ifam->ifam_data = ifa->if_data;
+
+ return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
+}
+
+static int
+sysctl_iflist_ifam(struct ifaddr *ifa, struct rt_addrinfo *info,
+ struct walkarg *w, int len)
+{
+ struct ifa_msghdr *ifam;
+
+ ifam = (struct ifa_msghdr *)w->w_tmem;
+ ifam->ifam_addrs = info->rti_addrs;
+ ifam->ifam_flags = ifa->ifa_flags;
+ ifam->ifam_index = ifa->ifa_ifp->if_index;
+ ifam->ifam_metric = ifa->ifa_metric;
+
+ return (SYSCTL_OUT(w->w_req, w->w_tmem, len));
+}
+
+static int
sysctl_iflist(int af, struct walkarg *w)
{
struct ifnet *ifp;
@@ -1485,38 +1720,16 @@ sysctl_iflist(int af, struct walkarg *w)
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (w->w_arg && w->w_arg != ifp->if_index)
continue;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
ifa = ifp->if_addr;
info.rti_info[RTAX_IFP] = ifa->ifa_addr;
len = rt_msg2(RTM_IFINFO, &info, NULL, w);
info.rti_info[RTAX_IFP] = NULL;
if (w->w_req && w->w_tmem) {
- struct if_msghdr *ifm;
-
-#ifdef COMPAT_FREEBSD32
- if (w->w_req->flags & SCTL_MASK32) {
- struct if_msghdr32 *ifm32;
-
- ifm32 = (struct if_msghdr32 *)w->w_tmem;
- ifm32->ifm_index = ifp->if_index;
- ifm32->ifm_flags = ifp->if_flags |
- ifp->if_drv_flags;
- copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
- ifm32->ifm_addrs = info.rti_addrs;
- error = SYSCTL_OUT(w->w_req, (caddr_t)ifm32,
- len);
- goto sysctl_out;
- }
-#endif
- ifm = (struct if_msghdr *)w->w_tmem;
- ifm->ifm_index = ifp->if_index;
- ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
- ifm->ifm_data = ifp->if_data;
- ifm->ifm_addrs = info.rti_addrs;
- error = SYSCTL_OUT(w->w_req, (caddr_t)ifm, len);
-#ifdef COMPAT_FREEBSD32
- sysctl_out:
-#endif
+ if (w->w_op == NET_RT_IFLISTL)
+ error = sysctl_iflist_ifml(ifp, &info, w, len);
+ else
+ error = sysctl_iflist_ifm(ifp, &info, w, len);
if (error)
goto done;
}
@@ -1531,25 +1744,23 @@ sysctl_iflist(int af, struct walkarg *w)
info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
len = rt_msg2(RTM_NEWADDR, &info, NULL, w);
if (w->w_req && w->w_tmem) {
- struct ifa_msghdr *ifam;
-
- ifam = (struct ifa_msghdr *)w->w_tmem;
- ifam->ifam_index = ifa->ifa_ifp->if_index;
- ifam->ifam_flags = ifa->ifa_flags;
- ifam->ifam_metric = ifa->ifa_metric;
- ifam->ifam_addrs = info.rti_addrs;
- error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+ if (w->w_op == NET_RT_IFLISTL)
+ error = sysctl_iflist_ifaml(ifa, &info,
+ w, len);
+ else
+ error = sysctl_iflist_ifam(ifa, &info,
+ w, len);
if (error)
goto done;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
info.rti_info[RTAX_BRD] = NULL;
}
done:
if (ifp != NULL)
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
IFNET_RUNLOCK();
return (error);
}
@@ -1570,7 +1781,7 @@ sysctl_ifmalist(int af, struct walkarg *w)
continue;
ifa = ifp->if_addr;
info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (af && af != ifma->ifma_addr->sa_family)
continue;
@@ -1591,12 +1802,12 @@ sysctl_ifmalist(int af, struct walkarg *w)
ifmam->ifmam_addrs = info.rti_addrs;
error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
if (error) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
done:
IFNET_RUNLOCK();
@@ -1662,16 +1873,17 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
rnh = rt_tables_get_rnh(BSD_DEFAULT_FIB, i);
#endif /* __rtems__ */
if (rnh != NULL) {
- RADIX_NODE_HEAD_LOCK(rnh);
+ RADIX_NODE_HEAD_RLOCK(rnh);
error = rnh->rnh_walktree(rnh,
sysctl_dumpentry, &w);
- RADIX_NODE_HEAD_UNLOCK(rnh);
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
} else if (af != 0)
error = EAFNOSUPPORT;
}
break;
case NET_RT_IFLIST:
+ case NET_RT_IFLISTL:
error = sysctl_iflist(af, &w);
break;
diff --git a/freebsd/sys/net/vnet.h b/freebsd/sys/net/vnet.h
index d3c426a4..8ef1c00d 100644
--- a/freebsd/sys/net/vnet.h
+++ b/freebsd/sys/net/vnet.h
@@ -116,22 +116,27 @@ void vnet_destroy(struct vnet *vnet);
* Various macros -- get and set the current network stack, but also
* assertions.
*/
+#if defined(INVARIANTS) || defined(VNET_DEBUG)
+#define VNET_ASSERT(exp, msg) do { \
+ if (!(exp)) \
+ panic msg; \
+} while (0)
+#else
+#define VNET_ASSERT(exp, msg) do { \
+} while (0)
+#endif
+
#ifdef VNET_DEBUG
void vnet_log_recursion(struct vnet *, const char *, int);
-#define VNET_ASSERT(condition) \
- if (!(condition)) { \
- printf("VNET_ASSERT @ %s:%d %s():\n", \
- __FILE__, __LINE__, __FUNCTION__); \
- panic(#condition); \
- }
-
#define CURVNET_SET_QUIET(arg) \
- VNET_ASSERT((arg)->vnet_magic_n == VNET_MAGIC_N); \
+ VNET_ASSERT((arg) != NULL && (arg)->vnet_magic_n == VNET_MAGIC_N, \
+ ("CURVNET_SET at %s:%d %s() curvnet=%p vnet=%p", \
+ __FILE__, __LINE__, __func__, curvnet, (arg))); \
struct vnet *saved_vnet = curvnet; \
const char *saved_vnet_lpush = curthread->td_vnet_lpush; \
curvnet = arg; \
- curthread->td_vnet_lpush = __FUNCTION__;
+ curthread->td_vnet_lpush = __func__;
#define CURVNET_SET_VERBOSE(arg) \
CURVNET_SET_QUIET(arg) \
@@ -141,21 +146,31 @@ void vnet_log_recursion(struct vnet *, const char *, int);
#define CURVNET_SET(arg) CURVNET_SET_VERBOSE(arg)
#define CURVNET_RESTORE() \
- VNET_ASSERT(saved_vnet == NULL || \
- saved_vnet->vnet_magic_n == VNET_MAGIC_N); \
+ VNET_ASSERT(curvnet != NULL && (saved_vnet == NULL || \
+ saved_vnet->vnet_magic_n == VNET_MAGIC_N), \
+ ("CURVNET_RESTORE at %s:%d %s() curvnet=%p saved_vnet=%p", \
+ __FILE__, __LINE__, __func__, curvnet, saved_vnet)); \
curvnet = saved_vnet; \
curthread->td_vnet_lpush = saved_vnet_lpush;
#else /* !VNET_DEBUG */
-#define VNET_ASSERT(condition)
-#define CURVNET_SET(arg) \
+#define CURVNET_SET_QUIET(arg) \
+ VNET_ASSERT((arg) != NULL && (arg)->vnet_magic_n == VNET_MAGIC_N, \
+ ("CURVNET_SET at %s:%d %s() curvnet=%p vnet=%p", \
+ __FILE__, __LINE__, __func__, curvnet, (arg))); \
struct vnet *saved_vnet = curvnet; \
curvnet = arg;
-#define CURVNET_SET_VERBOSE(arg) CURVNET_SET(arg)
-#define CURVNET_SET_QUIET(arg) CURVNET_SET(arg)
+#define CURVNET_SET_VERBOSE(arg) \
+ CURVNET_SET_QUIET(arg)
+
+#define CURVNET_SET(arg) CURVNET_SET_VERBOSE(arg)
#define CURVNET_RESTORE() \
+ VNET_ASSERT(curvnet != NULL && (saved_vnet == NULL || \
+ saved_vnet->vnet_magic_n == VNET_MAGIC_N), \
+ ("CURVNET_RESTORE at %s:%d %s() curvnet=%p saved_vnet=%p", \
+ __FILE__, __LINE__, __func__, curvnet, saved_vnet)); \
curvnet = saved_vnet;
#endif /* VNET_DEBUG */
@@ -191,15 +206,6 @@ extern struct sx vnet_sxlock;
* Virtual network stack memory allocator, which allows global variables to
* be automatically instantiated for each network stack instance.
*/
-__asm__(
-#if defined(__arm__)
- ".section " VNET_SETNAME ", \"aw\", %progbits\n"
-#else
- ".section " VNET_SETNAME ", \"aw\", @progbits\n"
-#endif
- "\t.p2align " __XSTRING(CACHE_LINE_SHIFT) "\n"
- "\t.previous");
-
#define VNET_NAME(n) vnet_entry_##n
#define VNET_DECLARE(t, n) extern t VNET_NAME(n)
#define VNET_DEFINE(t, n) t VNET_NAME(n) __section(VNET_SETNAME) __used
@@ -357,7 +363,7 @@ do { \
*/
#define curvnet NULL
-#define VNET_ASSERT(condition)
+#define VNET_ASSERT(exp, msg)
#define CURVNET_SET(arg)
#define CURVNET_SET_QUIET(arg)
#define CURVNET_RESTORE()
diff --git a/freebsd/sys/net80211/ieee80211.h b/freebsd/sys/net80211/ieee80211.h
index 712c2a8d..e567d9de 100644
--- a/freebsd/sys/net80211/ieee80211.h
+++ b/freebsd/sys/net80211/ieee80211.h
@@ -708,27 +708,32 @@ enum {
IEEE80211_ELEMID_VENDOR = 221, /* vendor private */
/*
- * 802.11s IEs based on D3.03 spec and were not assigned by
- * ANA. Beware changing them because some of them are being
- * kept compatible with Linux.
+ * 802.11s IEs
+ * NB: On vanilla Linux still IEEE80211_ELEMID_MESHPEER = 55,
+ * but they defined a new with id 117 called PEER_MGMT.
+ * NB: complies with open80211
*/
- IEEE80211_ELEMID_MESHCONF = 51,
- IEEE80211_ELEMID_MESHID = 52,
- IEEE80211_ELEMID_MESHLINK = 35,
- IEEE80211_ELEMID_MESHCNGST = 36,
- IEEE80211_ELEMID_MESHPEER = 55,
- IEEE80211_ELEMID_MESHCSA = 38,
- IEEE80211_ELEMID_MESHTIM = 39,
- IEEE80211_ELEMID_MESHAWAKEW = 40,
- IEEE80211_ELEMID_MESHBEACONT = 41,
- IEEE80211_ELEMID_MESHPANN = 48,
- IEEE80211_ELEMID_MESHRANN = 49,
- IEEE80211_ELEMID_MESHPREQ = 68,
- IEEE80211_ELEMID_MESHPREP = 69,
- IEEE80211_ELEMID_MESHPERR = 70,
- IEEE80211_ELEMID_MESHPXU = 53,
- IEEE80211_ELEMID_MESHPXUC = 54,
- IEEE80211_ELEMID_MESHAH = 60, /* Abbreviated Handshake */
+ IEEE80211_ELEMID_MESHCONF = 113,
+ IEEE80211_ELEMID_MESHID = 114,
+ IEEE80211_ELEMID_MESHLINK = 115,
+ IEEE80211_ELEMID_MESHCNGST = 116,
+ IEEE80211_ELEMID_MESHPEER = 117,
+ IEEE80211_ELEMID_MESHCSA = 118,
+ IEEE80211_ELEMID_MESHTIM = 39, /* XXX: remove */
+ IEEE80211_ELEMID_MESHAWAKEW = 119,
+ IEEE80211_ELEMID_MESHBEACONT = 120,
+ /* 121-124 MMCAOP not implemented yet */
+ IEEE80211_ELEMID_MESHPANN = 125, /* XXX: is GANN now, not used */
+ IEEE80211_ELEMID_MESHRANN = 126,
+ /* 127 Extended Capabilities */
+ /* 128-129 reserved */
+ IEEE80211_ELEMID_MESHPREQ = 130,
+ IEEE80211_ELEMID_MESHPREP = 131,
+ IEEE80211_ELEMID_MESHPERR = 132,
+ /* 133-136 reserved */
+ IEEE80211_ELEMID_MESHPXU = 137,
+ IEEE80211_ELEMID_MESHPXUC = 138,
+ IEEE80211_ELEMID_MESHAH = 60, /* XXX: remove */
};
struct ieee80211_tim_ie {
diff --git a/freebsd/sys/net80211/ieee80211_ageq.c b/freebsd/sys/net80211/ieee80211_ageq.c
index 3d164977..d942196a 100644
--- a/freebsd/sys/net80211/ieee80211_ageq.c
+++ b/freebsd/sys/net80211/ieee80211_ageq.c
@@ -156,7 +156,7 @@ ieee80211_ageq_drain_node(struct ieee80211_ageq *aq,
* deltas (in seconds) relative to the head so we can check
* and/or adjust only the head of the list. If a frame's age
* exceeds the time quanta then remove it. The list of removed
- * frames is is returned to the caller joined by m_nextpkt.
+ * frames is returned to the caller joined by m_nextpkt.
*/
struct mbuf *
ieee80211_ageq_age(struct ieee80211_ageq *aq, int quanta)
diff --git a/freebsd/sys/net80211/ieee80211_amrr.c b/freebsd/sys/net80211/ieee80211_amrr.c
index 9043ec61..74b0ab99 100644
--- a/freebsd/sys/net80211/ieee80211_amrr.c
+++ b/freebsd/sys/net80211/ieee80211_amrr.c
@@ -310,10 +310,10 @@ amrr_sysctlattach(struct ieee80211vap *vap,
"amrr_rate_interval", CTLTYPE_INT | CTLFLAG_RW, vap,
0, amrr_sysctl_interval, "I", "amrr operation interval (ms)");
/* XXX bounds check values */
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"amrr_max_sucess_threshold", CTLFLAG_RW,
&amrr->amrr_max_success_threshold, 0, "");
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"amrr_min_sucess_threshold", CTLFLAG_RW,
&amrr->amrr_min_success_threshold, 0, "");
}
diff --git a/freebsd/sys/net80211/ieee80211_freebsd.c b/freebsd/sys/net80211/ieee80211_freebsd.c
index 23623ece..e80a8fbb 100644
--- a/freebsd/sys/net80211/ieee80211_freebsd.c
+++ b/freebsd/sys/net80211/ieee80211_freebsd.c
@@ -235,14 +235,14 @@ ieee80211_sysctl_vattach(struct ieee80211vap *vap)
oid = SYSCTL_ADD_NODE(ctx, &SYSCTL_NODE_CHILDREN(_net, wlan),
OID_AUTO, num, CTLFLAG_RD, NULL, "");
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
- "%parent", CTLFLAG_RD, vap->iv_ic, 0,
+ "%parent", CTLTYPE_STRING | CTLFLAG_RD, vap->iv_ic, 0,
ieee80211_sysctl_parent, "A", "parent device");
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"driver_caps", CTLFLAG_RW, &vap->iv_caps, 0,
"driver capabilities");
#ifdef IEEE80211_DEBUG
vap->iv_debug = ieee80211_debug;
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"debug", CTLFLAG_RW, &vap->iv_debug, 0,
"control debugging printfs");
#endif
@@ -267,19 +267,19 @@ ieee80211_sysctl_vattach(struct ieee80211vap *vap)
ieee80211_sysctl_inact, "I",
"station initial state timeout (sec)");
if (vap->iv_htcaps & IEEE80211_HTC_HT) {
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"ampdu_mintraffic_bk", CTLFLAG_RW,
&vap->iv_ampdu_mintraffic[WME_AC_BK], 0,
"BK traffic tx aggr threshold (pps)");
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"ampdu_mintraffic_be", CTLFLAG_RW,
&vap->iv_ampdu_mintraffic[WME_AC_BE], 0,
"BE traffic tx aggr threshold (pps)");
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"ampdu_mintraffic_vo", CTLFLAG_RW,
&vap->iv_ampdu_mintraffic[WME_AC_VO], 0,
"VO traffic tx aggr threshold (pps)");
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"ampdu_mintraffic_vi", CTLFLAG_RW,
&vap->iv_ampdu_mintraffic[WME_AC_VI], 0,
"VI traffic tx aggr threshold (pps)");
diff --git a/freebsd/sys/net80211/ieee80211_mesh.c b/freebsd/sys/net80211/ieee80211_mesh.c
index 1ed730fc..8997ae8b 100644
--- a/freebsd/sys/net80211/ieee80211_mesh.c
+++ b/freebsd/sys/net80211/ieee80211_mesh.c
@@ -1463,7 +1463,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
meshid = frm;
break;
}
- frm += frm[2] + 2;
+ frm += frm[1] + 2;
}
IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, return);
IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, return);
diff --git a/freebsd/sys/net80211/ieee80211_output.c b/freebsd/sys/net80211/ieee80211_output.c
index 24b49ab4..1c902471 100644
--- a/freebsd/sys/net80211/ieee80211_output.c
+++ b/freebsd/sys/net80211/ieee80211_output.c
@@ -825,7 +825,7 @@ ieee80211_classify(struct ieee80211_node *ni, struct mbuf *m)
uint32_t flow;
uint8_t tos;
/*
- * IPv6 frame, map the DSCP bits from the TOS field.
+ * IPv6 frame, map the DSCP bits from the traffic class field.
*/
m_copydata(m, sizeof(struct ether_header) +
offsetof(struct ip6_hdr, ip6_flow), sizeof(flow),
diff --git a/freebsd/sys/netatalk/aarp.c b/freebsd/sys/netatalk/aarp.c
index d8daf757..0d469f1d 100644
--- a/freebsd/sys/netatalk/aarp.c
+++ b/freebsd/sys/netatalk/aarp.c
@@ -408,7 +408,7 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
* Since we don't know the net, we just look for the first
* phase 1 address on the interface.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead);
aa;
aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
@@ -418,12 +418,12 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
}
}
if (aa == NULL) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
m_freem(m);
return;
}
ifa_ref(&aa->aa_ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
}
diff --git a/freebsd/sys/netatalk/at_control.c b/freebsd/sys/netatalk/at_control.c
index 1c5d0a56..5b31b47a 100644
--- a/freebsd/sys/netatalk/at_control.c
+++ b/freebsd/sys/netatalk/at_control.c
@@ -256,9 +256,9 @@ at_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
*/
aa->aa_ifp = ifp;
ifa_ref(&aa->aa_ifa); /* if_addrhead */
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
} else {
/*
* If we DID find one then we clobber any routes
@@ -359,9 +359,9 @@ at_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
* remove the ifaddr from the interface
*/
ifa = (struct ifaddr *)aa;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
ifa_free(ifa); /* if_addrhead */
/*
diff --git a/freebsd/sys/netinet/cc.h b/freebsd/sys/netinet/cc.h
new file mode 100644
index 00000000..14b4a9de
--- /dev/null
+++ b/freebsd/sys/netinet/cc.h
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) 2007-2008
+ * Swinburne University of Technology, Melbourne, Australia.
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Lawrence Stewart and
+ * James Healy, made possible in part by a grant from the Cisco University
+ * Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
+ *
+ * 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$
+ */
+
+/*
+ * This software was first released in 2007 by James Healy and Lawrence Stewart
+ * whilst working on the NewTCP research project at Swinburne University of
+ * Technology's Centre for Advanced Internet Architectures, Melbourne,
+ * Australia, which was made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ * More details are available at:
+ * http://caia.swin.edu.au/urp/newtcp/
+ */
+
+#ifndef _NETINET_CC_H_
+#define _NETINET_CC_H_
+
+/* XXX: TCP_CA_NAME_MAX define lives in tcp.h for compat reasons. */
+#include <netinet/tcp.h>
+
+/* Global CC vars. */
+extern STAILQ_HEAD(cc_head, cc_algo) cc_list;
+extern const int tcprexmtthresh;
+extern struct cc_algo newreno_cc_algo;
+
+/* Per-netstack bits. */
+VNET_DECLARE(struct cc_algo *, default_cc_ptr);
+#define V_default_cc_ptr VNET(default_cc_ptr)
+
+/* Define the new net.inet.tcp.cc sysctl tree. */
+SYSCTL_DECL(_net_inet_tcp_cc);
+
+/* CC housekeeping functions. */
+int cc_register_algo(struct cc_algo *add_cc);
+int cc_deregister_algo(struct cc_algo *remove_cc);
+
+/*
+ * Wrapper around transport structs that contain same-named congestion
+ * control variables. Allows algos to be shared amongst multiple CC aware
+ * transprots.
+ */
+struct cc_var {
+ void *cc_data; /* Per-connection private CC algorithm data. */
+ int bytes_this_ack; /* # bytes acked by the current ACK. */
+ tcp_seq curack; /* Most recent ACK. */
+ uint32_t flags; /* Flags for cc_var (see below) */
+ int type; /* Indicates which ptr is valid in ccvc. */
+ union ccv_container {
+ struct tcpcb *tcp;
+ struct sctp_nets *sctp;
+ } ccvc;
+};
+
+/* cc_var flags. */
+#define CCF_ABC_SENTAWND 0x0001 /* ABC counted cwnd worth of bytes? */
+#define CCF_CWND_LIMITED 0x0002 /* Are we currently cwnd limited? */
+
+/* ACK types passed to the ack_received() hook. */
+#define CC_ACK 0x0001 /* Regular in sequence ACK. */
+#define CC_DUPACK 0x0002 /* Duplicate ACK. */
+#define CC_PARTIALACK 0x0004 /* Not yet. */
+#define CC_SACK 0x0008 /* Not yet. */
+
+/*
+ * Congestion signal types passed to the cong_signal() hook. The highest order 8
+ * bits (0x01000000 - 0x80000000) are reserved for CC algos to declare their own
+ * congestion signal types.
+ */
+#define CC_ECN 0x00000001 /* ECN marked packet received. */
+#define CC_RTO 0x00000002 /* RTO fired. */
+#define CC_RTO_ERR 0x00000004 /* RTO fired in error. */
+#define CC_NDUPACK 0x00000008 /* Threshold of dupack's reached. */
+
+#define CC_SIGPRIVMASK 0xFF000000 /* Mask to check if sig is private. */
+
+/*
+ * Structure to hold data and function pointers that together represent a
+ * congestion control algorithm.
+ */
+struct cc_algo {
+ char name[TCP_CA_NAME_MAX];
+
+ /* Init global module state on kldload. */
+ int (*mod_init)(void);
+
+ /* Cleanup global module state on kldunload. */
+ int (*mod_destroy)(void);
+
+ /* Init CC state for a new control block. */
+ int (*cb_init)(struct cc_var *ccv);
+
+ /* Cleanup CC state for a terminating control block. */
+ void (*cb_destroy)(struct cc_var *ccv);
+
+ /* Init variables for a newly established connection. */
+ void (*conn_init)(struct cc_var *ccv);
+
+ /* Called on receipt of an ack. */
+ void (*ack_received)(struct cc_var *ccv, uint16_t type);
+
+ /* Called on detection of a congestion signal. */
+ void (*cong_signal)(struct cc_var *ccv, uint32_t type);
+
+ /* Called after exiting congestion recovery. */
+ void (*post_recovery)(struct cc_var *ccv);
+
+ /* Called when data transfer resumes after an idle period. */
+ void (*after_idle)(struct cc_var *ccv);
+
+ STAILQ_ENTRY (cc_algo) entries;
+};
+
+/* Macro to obtain the CC algo's struct ptr. */
+#define CC_ALGO(tp) ((tp)->cc_algo)
+
+/* Macro to obtain the CC algo's data ptr. */
+#define CC_DATA(tp) ((tp)->ccv->cc_data)
+
+/* Macro to obtain the system default CC algo's struct ptr. */
+#define CC_DEFAULT() V_default_cc_ptr
+
+extern struct rwlock cc_list_lock;
+#define CC_LIST_LOCK_INIT() rw_init(&cc_list_lock, "cc_list")
+#define CC_LIST_LOCK_DESTROY() rw_destroy(&cc_list_lock)
+#define CC_LIST_RLOCK() rw_rlock(&cc_list_lock)
+#define CC_LIST_RUNLOCK() rw_runlock(&cc_list_lock)
+#define CC_LIST_WLOCK() rw_wlock(&cc_list_lock)
+#define CC_LIST_WUNLOCK() rw_wunlock(&cc_list_lock)
+#define CC_LIST_LOCK_ASSERT() rw_assert(&cc_list_lock, RA_LOCKED)
+
+#endif /* _NETINET_CC_H_ */
diff --git a/freebsd/sys/netinet/cc/cc.c b/freebsd/sys/netinet/cc/cc.c
new file mode 100644
index 00000000..a5a971e6
--- /dev/null
+++ b/freebsd/sys/netinet/cc/cc.c
@@ -0,0 +1,332 @@
+#include <machine/rtems-bsd-config.h>
+
+/*-
+ * Copyright (c) 2007-2008
+ * Swinburne University of Technology, Melbourne, Australia.
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Lawrence Stewart and
+ * James Healy, made possible in part by a grant from the Cisco University
+ * Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * This software was first released in 2007 by James Healy and Lawrence Stewart
+ * whilst working on the NewTCP research project at Swinburne University of
+ * Technology's Centre for Advanced Internet Architectures, Melbourne,
+ * Australia, which was made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ * More details are available at:
+ * http://caia.swin.edu.au/urp/newtcp/
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <rtems/bsd/sys/param.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <rtems/bsd/sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/rwlock.h>
+#include <sys/sbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <netinet/cc.h>
+#include <netinet/in.h>
+#include <netinet/in_pcb.h>
+#include <netinet/tcp_var.h>
+
+#include <netinet/cc/cc_module.h>
+
+/*
+ * List of available cc algorithms on the current system. First element
+ * is used as the system default CC algorithm.
+ */
+struct cc_head cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
+
+/* Protects the cc_list TAILQ. */
+struct rwlock cc_list_lock;
+
+VNET_DEFINE(struct cc_algo *, default_cc_ptr) = &newreno_cc_algo;
+
+/*
+ * Sysctl handler to show and change the default CC algorithm.
+ */
+static int
+cc_default_algo(SYSCTL_HANDLER_ARGS)
+{
+ char default_cc[TCP_CA_NAME_MAX];
+ struct cc_algo *funcs;
+ int err, found;
+
+ err = found = 0;
+
+ if (req->newptr == NULL) {
+ /* Just print the current default. */
+ CC_LIST_RLOCK();
+ strlcpy(default_cc, CC_DEFAULT()->name, TCP_CA_NAME_MAX);
+ CC_LIST_RUNLOCK();
+ err = sysctl_handle_string(oidp, default_cc, 1, req);
+ } else {
+ /* Find algo with specified name and set it to default. */
+ CC_LIST_RLOCK();
+ STAILQ_FOREACH(funcs, &cc_list, entries) {
+ if (strncmp((char *)req->newptr, funcs->name,
+ TCP_CA_NAME_MAX) == 0) {
+ found = 1;
+ V_default_cc_ptr = funcs;
+ }
+ }
+ CC_LIST_RUNLOCK();
+
+ if (!found)
+ err = ESRCH;
+ }
+
+ return (err);
+}
+
+#ifndef __rtems__
+/*
+ * Sysctl handler to display the list of available CC algorithms.
+ */
+static int
+cc_list_available(SYSCTL_HANDLER_ARGS)
+{
+ struct cc_algo *algo;
+ struct sbuf *s;
+ int err, first, nalgos;
+
+ err = nalgos = 0;
+ first = 1;
+
+ CC_LIST_RLOCK();
+ STAILQ_FOREACH(algo, &cc_list, entries) {
+ nalgos++;
+ }
+ CC_LIST_RUNLOCK();
+
+ s = sbuf_new(NULL, NULL, nalgos * TCP_CA_NAME_MAX, SBUF_FIXEDLEN);
+
+ if (s == NULL)
+ return (ENOMEM);
+
+ /*
+ * It is theoretically possible for the CC list to have grown in size
+ * since the call to sbuf_new() and therefore for the sbuf to be too
+ * small. If this were to happen (incredibly unlikely), the sbuf will
+ * reach an overflow condition, sbuf_printf() will return an error and
+ * the sysctl will fail gracefully.
+ */
+ CC_LIST_RLOCK();
+ STAILQ_FOREACH(algo, &cc_list, entries) {
+ err = sbuf_printf(s, first ? "%s" : ", %s", algo->name);
+ if (err) {
+ /* Sbuf overflow condition. */
+ err = EOVERFLOW;
+ break;
+ }
+ first = 0;
+ }
+ CC_LIST_RUNLOCK();
+
+ if (!err) {
+ sbuf_finish(s);
+ err = sysctl_handle_string(oidp, sbuf_data(s), 1, req);
+ }
+
+ sbuf_delete(s);
+ return (err);
+}
+#endif /* __rtems__ */
+
+/*
+ * Reset the default CC algo to NewReno for any netstack which is using the algo
+ * that is about to go away as its default.
+ */
+static void
+cc_checkreset_default(struct cc_algo *remove_cc)
+{
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ CC_LIST_LOCK_ASSERT();
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ if (strncmp(CC_DEFAULT()->name, remove_cc->name,
+ TCP_CA_NAME_MAX) == 0)
+ V_default_cc_ptr = &newreno_cc_algo;
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
+}
+
+/*
+ * Initialise CC subsystem on system boot.
+ */
+static void
+cc_init(void)
+{
+ CC_LIST_LOCK_INIT();
+ STAILQ_INIT(&cc_list);
+}
+
+/*
+ * Returns non-zero on success, 0 on failure.
+ */
+int
+cc_deregister_algo(struct cc_algo *remove_cc)
+{
+ struct cc_algo *funcs, *tmpfuncs;
+ int err;
+
+ err = ENOENT;
+
+ /* Never allow newreno to be deregistered. */
+ if (&newreno_cc_algo == remove_cc)
+ return (EPERM);
+
+ /* Remove algo from cc_list so that new connections can't use it. */
+ CC_LIST_WLOCK();
+ STAILQ_FOREACH_SAFE(funcs, &cc_list, entries, tmpfuncs) {
+ if (funcs == remove_cc) {
+ cc_checkreset_default(remove_cc);
+ STAILQ_REMOVE(&cc_list, funcs, cc_algo, entries);
+ err = 0;
+ break;
+ }
+ }
+ CC_LIST_WUNLOCK();
+
+ if (!err)
+ /*
+ * XXXLAS:
+ * - We may need to handle non-zero return values in future.
+ * - If we add CC framework support for protocols other than
+ * TCP, we may want a more generic way to handle this step.
+ */
+ tcp_ccalgounload(remove_cc);
+
+ return (err);
+}
+
+/*
+ * Returns 0 on success, non-zero on failure.
+ */
+int
+cc_register_algo(struct cc_algo *add_cc)
+{
+ struct cc_algo *funcs;
+ int err;
+
+ err = 0;
+
+ /*
+ * Iterate over list of registered CC algorithms and make sure
+ * we're not trying to add a duplicate.
+ */
+ CC_LIST_WLOCK();
+ STAILQ_FOREACH(funcs, &cc_list, entries) {
+ if (funcs == add_cc || strncmp(funcs->name, add_cc->name,
+ TCP_CA_NAME_MAX) == 0)
+ err = EEXIST;
+ }
+
+ if (!err)
+ STAILQ_INSERT_TAIL(&cc_list, add_cc, entries);
+
+ CC_LIST_WUNLOCK();
+
+ return (err);
+}
+
+/*
+ * Handles kld related events. Returns 0 on success, non-zero on failure.
+ */
+int
+cc_modevent(module_t mod, int event_type, void *data)
+{
+ struct cc_algo *algo;
+ int err;
+
+ err = 0;
+ algo = (struct cc_algo *)data;
+
+ switch(event_type) {
+ case MOD_LOAD:
+ if (algo->mod_init != NULL)
+ err = algo->mod_init();
+ if (!err)
+ err = cc_register_algo(algo);
+ break;
+
+ case MOD_QUIESCE:
+ case MOD_SHUTDOWN:
+ case MOD_UNLOAD:
+ err = cc_deregister_algo(algo);
+ if (!err && algo->mod_destroy != NULL)
+ algo->mod_destroy();
+ if (err == ENOENT)
+ err = 0;
+ break;
+
+ default:
+ err = EINVAL;
+ break;
+ }
+
+ return (err);
+}
+
+SYSINIT(cc, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, cc_init, NULL);
+
+/* Declare sysctl tree and populate it. */
+SYSCTL_NODE(_net_inet_tcp, OID_AUTO, cc, CTLFLAG_RW, NULL,
+ "congestion control related settings");
+
+SYSCTL_VNET_PROC(_net_inet_tcp_cc, OID_AUTO, algorithm, CTLTYPE_STRING|CTLFLAG_RW,
+ NULL, 0, cc_default_algo, "A", "default congestion control algorithm");
+
+#ifndef __rtems__
+SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, available, CTLTYPE_STRING|CTLFLAG_RD,
+ NULL, 0, cc_list_available, "A",
+ "list available congestion control algorithms");
+#endif /* __rtems__ */
diff --git a/freebsd/sys/netinet/cc/cc_module.h b/freebsd/sys/netinet/cc/cc_module.h
new file mode 100644
index 00000000..6da10df1
--- /dev/null
+++ b/freebsd/sys/netinet/cc/cc_module.h
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * All rights reserved.
+ *
+ * This software was developed by Lawrence Stewart while studying at the Centre
+ * for Advanced Internet Architectures, Swinburne University of Technology, made
+ * possible in part by a grant from the Cisco University Research Program Fund
+ * at Community Foundation Silicon Valley.
+ *
+ * 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$
+ */
+
+/*
+ * This software was first released in 2009 by Lawrence Stewart as part of the
+ * NewTCP research project at Swinburne University of Technology's Centre for
+ * Advanced Internet Architectures, Melbourne, Australia, which was made
+ * possible in part by a grant from the Cisco University Research Program Fund
+ * at Community Foundation Silicon Valley. More details are available at:
+ * http://caia.swin.edu.au/urp/newtcp/
+ */
+
+#ifndef _NETINET_CC_MODULE_H_
+#define _NETINET_CC_MODULE_H_
+
+/*
+ * Allows a CC algorithm to manipulate a commonly named CC variable regardless
+ * of the transport protocol and associated C struct.
+ * XXXLAS: Out of action until the work to support SCTP is done.
+ *
+#define CCV(ccv, what) \
+(*( \
+ (ccv)->type == IPPROTO_TCP ? &(ccv)->ccvc.tcp->what : \
+ &(ccv)->ccvc.sctp->what \
+))
+ */
+#define CCV(ccv, what) (ccv)->ccvc.tcp->what
+
+#define DECLARE_CC_MODULE(ccname, ccalgo) \
+ static moduledata_t cc_##ccname = { \
+ .name = #ccname, \
+ .evhand = cc_modevent, \
+ .priv = ccalgo \
+ }; \
+ DECLARE_MODULE(ccname, cc_##ccname, \
+ SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY)
+
+int cc_modevent(module_t mod, int type, void *data);
+
+#endif /* _NETINET_CC_MODULE_H_ */
diff --git a/freebsd/sys/netinet/cc/cc_newreno.c b/freebsd/sys/netinet/cc/cc_newreno.c
new file mode 100644
index 00000000..e40f6d83
--- /dev/null
+++ b/freebsd/sys/netinet/cc/cc_newreno.c
@@ -0,0 +1,239 @@
+#include <machine/rtems-bsd-config.h>
+
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
+ * The Regents of the University of California.
+ * Copyright (c) 2007-2008,2010
+ * Swinburne University of Technology, Melbourne, Australia.
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Lawrence Stewart, James
+ * Healy and David Hayes, made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * This software was first released in 2007 by James Healy and Lawrence Stewart
+ * whilst working on the NewTCP research project at Swinburne University of
+ * Technology's Centre for Advanced Internet Architectures, Melbourne,
+ * Australia, which was made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ * More details are available at:
+ * http://caia.swin.edu.au/urp/newtcp/
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <rtems/bsd/sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <net/vnet.h>
+
+#include <netinet/cc.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_var.h>
+
+#include <netinet/cc/cc_module.h>
+
+static void newreno_ack_received(struct cc_var *ccv, uint16_t type);
+static void newreno_after_idle(struct cc_var *ccv);
+static void newreno_cong_signal(struct cc_var *ccv, uint32_t type);
+static void newreno_post_recovery(struct cc_var *ccv);
+
+struct cc_algo newreno_cc_algo = {
+ .name = "newreno",
+ .ack_received = newreno_ack_received,
+ .after_idle = newreno_after_idle,
+ .cong_signal = newreno_cong_signal,
+ .post_recovery = newreno_post_recovery,
+};
+
+static void
+newreno_ack_received(struct cc_var *ccv, uint16_t type)
+{
+ if (type == CC_ACK && !IN_RECOVERY(CCV(ccv, t_flags)) &&
+ (ccv->flags & CCF_CWND_LIMITED)) {
+ u_int cw = CCV(ccv, snd_cwnd);
+ u_int incr = CCV(ccv, t_maxseg);
+
+ /*
+ * Regular in-order ACK, open the congestion window.
+ * Method depends on which congestion control state we're
+ * in (slow start or cong avoid) and if ABC (RFC 3465) is
+ * enabled.
+ *
+ * slow start: cwnd <= ssthresh
+ * cong avoid: cwnd > ssthresh
+ *
+ * slow start and ABC (RFC 3465):
+ * Grow cwnd exponentially by the amount of data
+ * ACKed capping the max increment per ACK to
+ * (abc_l_var * maxseg) bytes.
+ *
+ * slow start without ABC (RFC 5681):
+ * Grow cwnd exponentially by maxseg per ACK.
+ *
+ * cong avoid and ABC (RFC 3465):
+ * Grow cwnd linearly by maxseg per RTT for each
+ * cwnd worth of ACKed data.
+ *
+ * cong avoid without ABC (RFC 5681):
+ * Grow cwnd linearly by approximately maxseg per RTT using
+ * maxseg^2 / cwnd per ACK as the increment.
+ * If cwnd > maxseg^2, fix the cwnd increment at 1 byte to
+ * avoid capping cwnd.
+ */
+ if (cw > CCV(ccv, snd_ssthresh)) {
+ if (V_tcp_do_rfc3465) {
+ if (ccv->flags & CCF_ABC_SENTAWND)
+ ccv->flags &= ~CCF_ABC_SENTAWND;
+ else
+ incr = 0;
+ } else
+ incr = max((incr * incr / cw), 1);
+ } else if (V_tcp_do_rfc3465) {
+ /*
+ * In slow-start with ABC enabled and no RTO in sight?
+ * (Must not use abc_l_var > 1 if slow starting after
+ * an RTO. On RTO, snd_nxt = snd_una, so the
+ * snd_nxt == snd_max check is sufficient to
+ * handle this).
+ *
+ * XXXLAS: Find a way to signal SS after RTO that
+ * doesn't rely on tcpcb vars.
+ */
+ if (CCV(ccv, snd_nxt) == CCV(ccv, snd_max))
+ incr = min(ccv->bytes_this_ack,
+ V_tcp_abc_l_var * CCV(ccv, t_maxseg));
+ else
+ incr = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg));
+ }
+ /* ABC is on by default, so incr equals 0 frequently. */
+ if (incr > 0)
+ CCV(ccv, snd_cwnd) = min(cw + incr,
+ TCP_MAXWIN << CCV(ccv, snd_scale));
+ }
+}
+
+static void
+newreno_after_idle(struct cc_var *ccv)
+{
+ int rw;
+
+ /*
+ * If we've been idle for more than one retransmit timeout the old
+ * congestion window is no longer current and we have to reduce it to
+ * the restart window before we can transmit again.
+ *
+ * The restart window is the initial window or the last CWND, whichever
+ * is smaller.
+ *
+ * This is done to prevent us from flooding the path with a full CWND at
+ * wirespeed, overloading router and switch buffers along the way.
+ *
+ * See RFC5681 Section 4.1. "Restarting Idle Connections".
+ */
+ if (V_tcp_do_rfc3390)
+ rw = min(4 * CCV(ccv, t_maxseg),
+ max(2 * CCV(ccv, t_maxseg), 4380));
+ else
+ rw = CCV(ccv, t_maxseg) * 2;
+
+ CCV(ccv, snd_cwnd) = min(rw, CCV(ccv, snd_cwnd));
+}
+
+/*
+ * Perform any necessary tasks before we enter congestion recovery.
+ */
+static void
+newreno_cong_signal(struct cc_var *ccv, uint32_t type)
+{
+ u_int win;
+
+ /* Catch algos which mistakenly leak private signal types. */
+ KASSERT((type & CC_SIGPRIVMASK) == 0,
+ ("%s: congestion signal type 0x%08x is private\n", __func__, type));
+
+ win = max(CCV(ccv, snd_cwnd) / 2 / CCV(ccv, t_maxseg), 2) *
+ CCV(ccv, t_maxseg);
+
+ switch (type) {
+ case CC_NDUPACK:
+ if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
+ if (!IN_CONGRECOVERY(CCV(ccv, t_flags)))
+ CCV(ccv, snd_ssthresh) = win;
+ ENTER_RECOVERY(CCV(ccv, t_flags));
+ }
+ break;
+ case CC_ECN:
+ if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
+ CCV(ccv, snd_ssthresh) = win;
+ CCV(ccv, snd_cwnd) = win;
+ ENTER_CONGRECOVERY(CCV(ccv, t_flags));
+ }
+ break;
+ }
+}
+
+/*
+ * Perform any necessary tasks before we exit congestion recovery.
+ */
+static void
+newreno_post_recovery(struct cc_var *ccv)
+{
+ if (IN_FASTRECOVERY(CCV(ccv, t_flags))) {
+ /*
+ * Fast recovery will conclude after returning from this
+ * function. Window inflation should have left us with
+ * approximately snd_ssthresh outstanding data. But in case we
+ * would be inclined to send a burst, better to do it via the
+ * slow start mechanism.
+ *
+ * XXXLAS: Find a way to do this without needing curack
+ */
+ if (SEQ_GT(ccv->curack + CCV(ccv, snd_ssthresh),
+ CCV(ccv, snd_max)))
+ CCV(ccv, snd_cwnd) = CCV(ccv, snd_max) -
+ ccv->curack + CCV(ccv, t_maxseg);
+ else
+ CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh);
+ }
+}
+
+
+DECLARE_CC_MODULE(newreno, &newreno_cc_algo);
diff --git a/freebsd/sys/netinet/icmp6.h b/freebsd/sys/netinet/icmp6.h
index 5faae7c1..a6e68864 100644
--- a/freebsd/sys/netinet/icmp6.h
+++ b/freebsd/sys/netinet/icmp6.h
@@ -297,8 +297,9 @@ struct nd_opt_hdr { /* Neighbor discovery option header */
#define ND_OPT_PREFIX_INFORMATION 3
#define ND_OPT_REDIRECTED_HEADER 4
#define ND_OPT_MTU 5
-
-#define ND_OPT_ROUTE_INFO 200 /* draft-ietf-ipngwg-router-preference, not officially assigned yet */
+#define ND_OPT_ROUTE_INFO 24 /* RFC 4191 */
+#define ND_OPT_RDNSS 25 /* RFC 6106 */
+#define ND_OPT_DNSSL 31 /* RFC 6106 */
struct nd_opt_prefix_info { /* prefix information */
u_int8_t nd_opt_pi_type;
@@ -338,6 +339,22 @@ struct nd_opt_route_info { /* route info */
/* prefix follows */
} __packed;
+struct nd_opt_rdnss { /* RDNSS option (RFC 6106) */
+ u_int8_t nd_opt_rdnss_type;
+ u_int8_t nd_opt_rdnss_len;
+ u_int16_t nd_opt_rdnss_reserved;
+ u_int32_t nd_opt_rdnss_lifetime;
+ /* followed by list of recursive DNS servers */
+} __packed;
+
+struct nd_opt_dnssl { /* DNSSL option (RFC 6106) */
+ u_int8_t nd_opt_dnssl_type;
+ u_int8_t nd_opt_dnssl_len;
+ u_int16_t nd_opt_dnssl_reserved;
+ u_int32_t nd_opt_dnssl_lifetime;
+ /* followed by list of DNS search domains */
+} __packed;
+
/*
* icmp6 namelookup
*/
diff --git a/freebsd/sys/netinet/icmp_var.h b/freebsd/sys/netinet/icmp_var.h
index 30da6a26..d939cc2e 100644
--- a/freebsd/sys/netinet/icmp_var.h
+++ b/freebsd/sys/netinet/icmp_var.h
@@ -102,7 +102,8 @@ extern int badport_bandlim(int);
#define BANDLIM_RST_CLOSEDPORT 3 /* No connection, and no listeners */
#define BANDLIM_RST_OPENPORT 4 /* No connection, listener */
#define BANDLIM_ICMP6_UNREACH 5
-#define BANDLIM_MAX 5
+#define BANDLIM_SCTP_OOTB 6
+#define BANDLIM_MAX 6
#endif
#endif
diff --git a/freebsd/sys/netinet/if_atm.c b/freebsd/sys/netinet/if_atm.c
index 1c51718d..97b2525c 100644
--- a/freebsd/sys/netinet/if_atm.c
+++ b/freebsd/sys/netinet/if_atm.c
@@ -231,7 +231,9 @@ atm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
npcb->npcb_flags |= NPCB_IP;
npcb->ipaddr.s_addr = sin->sin_addr.s_addr;
/* XXX: move npcb to llinfo when ATM ARP is ready */
+#ifdef __notyet_restored__
rt->rt_llinfo = (caddr_t) npcb;
+#endif
rt->rt_flags |= RTF_LLINFO;
#endif
/*
@@ -257,7 +259,9 @@ failed:
#ifdef NATM
if (npcb) {
npcb_free(npcb, NPCB_DESTROY);
+#ifdef __notyet_restored__
rt->rt_llinfo = NULL;
+#endif
rt->rt_flags &= ~RTF_LLINFO;
}
NATM_UNLOCK();
@@ -275,9 +279,11 @@ failed:
*/
if (rt->rt_flags & RTF_LLINFO) {
NATM_LOCK();
+#ifdef __notyet_restored__
npcb_free((struct natmpcb *)rt->rt_llinfo,
NPCB_DESTROY);
rt->rt_llinfo = NULL;
+#endif
rt->rt_flags &= ~RTF_LLINFO;
NATM_UNLOCK();
}
diff --git a/freebsd/sys/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c
index e7a20c2c..4cd4f8e4 100644
--- a/freebsd/sys/netinet/if_ether.c
+++ b/freebsd/sys/netinet/if_ether.c
@@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_var.h>
#include <net/if_llatbl.h>
#include <netinet/if_ether.h>
-#if defined(INET) || defined(INET6)
+#if defined(INET)
#include <netinet/ip_carp.h>
#endif
@@ -91,13 +91,16 @@ VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for
static VNET_DEFINE(int, arp_proxyall) = 0;
static VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for
* 20 seconds */
-static VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
+VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
+
+static VNET_DEFINE(int, arp_maxhold) = 1;
#define V_arpt_keep VNET(arpt_keep)
#define V_arpt_down VNET(arpt_down)
#define V_arp_maxtries VNET(arp_maxtries)
#define V_arp_proxyall VNET(arp_proxyall)
#define V_arpstat VNET(arpstat)
+#define V_arp_maxhold VNET(arp_maxhold)
SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW,
&VNET_NAME(arpt_keep), 0,
@@ -111,9 +114,15 @@ SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW,
SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW,
&VNET_NAME(arp_proxyall), 0,
"Enable proxy ARP for all suitable requests");
+SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, wait, CTLFLAG_RW,
+ &VNET_NAME(arpt_down), 0,
+ "Incomplete ARP entry lifetime in seconds");
SYSCTL_VNET_STRUCT(_net_link_ether_arp, OID_AUTO, stats, CTLFLAG_RW,
&VNET_NAME(arpstat), arpstat,
"ARP statistics (struct arpstat, net/if_arp.h)");
+SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxhold, CTLFLAG_RW,
+ &VNET_NAME(arp_maxhold), 0,
+ "Number of packets to hold per ARP entry");
static void arp_init(void);
void arprequest(struct ifnet *,
@@ -162,6 +171,7 @@ arptimer(void *arg)
{
struct ifnet *ifp;
struct llentry *lle;
+ int pkts_dropped;
KASSERT(arg != NULL, ("%s: arg NULL", __func__));
lle = (struct llentry *)arg;
@@ -176,18 +186,19 @@ arptimer(void *arg)
callout_active(&lle->la_timer)) {
callout_stop(&lle->la_timer);
LLE_REMREF(lle);
- (void) llentry_free(lle);
+ pkts_dropped = llentry_free(lle);
+ ARPSTAT_ADD(dropped, pkts_dropped);
ARPSTAT_INC(timeouts);
- }
+ } else {
#ifdef DIAGNOSTIC
- else {
struct sockaddr *l3addr = L3_ADDR(lle);
log(LOG_INFO,
"arptimer issue: %p, IPv4 address: \"%s\"\n", lle,
inet_ntoa(
((const struct sockaddr_in *)l3addr)->sin_addr));
- }
#endif
+ LLE_WUNLOCK(lle);
+ }
}
IF_AFDATA_UNLOCK(ifp);
CURVNET_RESTORE();
@@ -275,6 +286,8 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
{
struct llentry *la = 0;
u_int flags = 0;
+ struct mbuf *curr = NULL;
+ struct mbuf *next = NULL;
int error, renew;
*lle = NULL;
@@ -350,15 +363,28 @@ retry:
}
/*
* There is an arptab entry, but no ethernet address
- * response yet. Replace the held mbuf with this
- * latest one.
+ * response yet. Add the mbuf to the list, dropping
+ * the oldest packet if we have exceeded the system
+ * setting.
*/
if (m != NULL) {
+ if (la->la_numheld >= V_arp_maxhold) {
+ if (la->la_hold != NULL) {
+ next = la->la_hold->m_nextpkt;
+ m_freem(la->la_hold);
+ la->la_hold = next;
+ la->la_numheld--;
+ ARPSTAT_INC(dropped);
+ }
+ }
if (la->la_hold != NULL) {
- m_freem(la->la_hold);
- ARPSTAT_INC(dropped);
- }
- la->la_hold = m;
+ curr = la->la_hold;
+ while (curr->m_nextpkt != NULL)
+ curr = curr->m_nextpkt;
+ curr->m_nextpkt = m;
+ } else
+ la->la_hold = m;
+ la->la_numheld++;
if (renew == 0 && (flags & LLE_EXCLUSIVE)) {
flags &= ~LLE_EXCLUSIVE;
LLE_DOWNGRADE(la);
@@ -485,7 +511,6 @@ in_arpinput(struct mbuf *m)
struct rtentry *rt;
struct ifaddr *ifa;
struct in_ifaddr *ia;
- struct mbuf *hold;
struct sockaddr sa;
struct in_addr isaddr, itaddr, myaddr;
u_int8_t *enaddr = NULL;
@@ -580,15 +605,15 @@ in_arpinput(struct mbuf *m)
* No match, use the first inet address on the receive interface
* as a dummy address for the rest of the function.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_INET) {
ia = ifatoia(ifa);
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto match;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/*
* If bridging, fall back to using any inet address.
@@ -657,11 +682,13 @@ match:
bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) {
if (la->la_flags & LLE_STATIC) {
LLE_WUNLOCK(la);
- log(LOG_ERR,
- "arp: %*D attempts to modify permanent "
- "entry for %s on %s\n",
- ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
- inet_ntoa(isaddr), ifp->if_xname);
+ if (log_arp_permanent_modify)
+ log(LOG_ERR,
+ "arp: %*D attempts to modify "
+ "permanent entry for %s on %s\n",
+ ifp->if_addrlen,
+ (u_char *)ar_sha(ah), ":",
+ inet_ntoa(isaddr), ifp->if_xname);
goto reply;
}
if (log_arp_movements) {
@@ -698,15 +725,29 @@ match:
}
la->la_asked = 0;
la->la_preempt = V_arp_maxtries;
- hold = la->la_hold;
- if (hold != NULL) {
+ /*
+ * The packets are all freed within the call to the output
+ * routine.
+ *
+ * NB: The lock MUST be released before the call to the
+ * output routine.
+ */
+ if (la->la_hold != NULL) {
+ struct mbuf *m_hold, *m_hold_next;
+
+ m_hold = la->la_hold;
la->la_hold = NULL;
+ la->la_numheld = 0;
memcpy(&sa, L3_ADDR(la), sizeof(sa));
- }
- LLE_WUNLOCK(la);
- if (hold != NULL)
- (*ifp->if_output)(ifp, hold, &sa, NULL);
- }
+ LLE_WUNLOCK(la);
+ for (; m_hold != NULL; m_hold = m_hold_next) {
+ m_hold_next = m_hold->m_nextpkt;
+ m_hold->m_nextpkt = NULL;
+ (*ifp->if_output)(ifp, m_hold, &sa, NULL);
+ }
+ } else
+ LLE_WUNLOCK(la);
+ } /* end of FIB loop */
reply:
if (op != ARPOP_REQUEST)
goto drop;
@@ -758,7 +799,7 @@ reply:
/*
* Also check that the node which sent the ARP packet
- * is on the the interface we expect it to be on. This
+ * is on the interface we expect it to be on. This
* avoids ARP chaos if an interface is connected to the
* wrong network.
*/
@@ -804,6 +845,7 @@ reply:
ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */
m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln);
m->m_pkthdr.len = m->m_len;
+ m->m_pkthdr.rcvif = NULL;
sa.sa_family = AF_ARP;
sa.sa_len = 2;
(*ifp->if_output)(ifp, m, &sa, NULL);
diff --git a/freebsd/sys/netinet/igmp.c b/freebsd/sys/netinet/igmp.c
index c41b8f71..138a1504 100644
--- a/freebsd/sys/netinet/igmp.c
+++ b/freebsd/sys/netinet/igmp.c
@@ -619,7 +619,7 @@ igmp_ifdetach(struct ifnet *ifp)
igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp;
if (igi->igi_version == IGMP_VERSION_3) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET ||
ifma->ifma_protospec == NULL)
@@ -635,7 +635,7 @@ igmp_ifdetach(struct ifnet *ifp)
}
inm_clear_recorded(inm);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/*
* Free the in_multi reference(s) for this IGMP lifecycle.
*/
@@ -752,7 +752,7 @@ igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip,
* for the interface on which the query arrived,
* except those which are already running.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET ||
ifma->ifma_protospec == NULL)
@@ -780,7 +780,7 @@ igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip,
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
out_locked:
IGMP_UNLOCK();
@@ -853,7 +853,7 @@ igmp_input_v2_query(struct ifnet *ifp, const struct ip *ip,
*/
CTR2(KTR_IGMPV3, "process v2 general query on ifp %p(%s)",
ifp, ifp->if_xname);
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET ||
ifma->ifma_protospec == NULL)
@@ -861,7 +861,7 @@ igmp_input_v2_query(struct ifnet *ifp, const struct ip *ip,
inm = (struct in_multi *)ifma->ifma_protospec;
igmp_v2_update_group(inm, timer);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
} else {
/*
* Group-specific IGMPv2 query, we need only
@@ -1643,7 +1643,7 @@ igmp_fasttimo_vnet(void)
struct ifqueue qrq; /* Query response packets */
struct ifnet *ifp;
struct igmp_ifinfo *igi;
- struct ifmultiaddr *ifma, *tifma;
+ struct ifmultiaddr *ifma;
struct in_multi *inm;
int loop, uri_fasthz;
@@ -1709,9 +1709,8 @@ igmp_fasttimo_vnet(void)
IFQ_SET_MAXLEN(&scq, IGMP_MAX_STATE_CHANGE_PACKETS);
}
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link,
- tifma) {
+ IF_ADDR_RLOCK(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET ||
ifma->ifma_protospec == NULL)
continue;
@@ -1728,7 +1727,7 @@ igmp_fasttimo_vnet(void)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (igi->igi_version == IGMP_VERSION_3) {
struct in_multi *tinm;
@@ -2005,7 +2004,7 @@ igmp_v3_cancel_link_timers(struct igmp_ifinfo *igi)
{
struct ifmultiaddr *ifma;
struct ifnet *ifp;
- struct in_multi *inm;
+ struct in_multi *inm, *tinm;
CTR3(KTR_IGMPV3, "%s: cancel v3 timers on ifp %p(%s)", __func__,
igi->igi_ifp, igi->igi_ifp->if_xname);
@@ -2025,7 +2024,7 @@ igmp_v3_cancel_link_timers(struct igmp_ifinfo *igi)
* for all memberships scoped to this link.
*/
ifp = igi->igi_ifp;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET ||
ifma->ifma_protospec == NULL)
@@ -2051,14 +2050,8 @@ igmp_v3_cancel_link_timers(struct igmp_ifinfo *igi)
* transition to REPORTING to ensure the host leave
* message is sent upstream to the old querier --
* transition to NOT would lose the leave and race.
- *
- * SMPNG: Must drop and re-acquire IF_ADDR_LOCK
- * around inm_release_locked(), as it is not
- * a recursive mutex.
*/
- IF_ADDR_UNLOCK(ifp);
- inm_release_locked(inm);
- IF_ADDR_LOCK(ifp);
+ SLIST_INSERT_HEAD(&igi->igi_relinmhead, inm, inm_nrele);
/* FALLTHROUGH */
case IGMP_G_QUERY_PENDING_MEMBER:
case IGMP_SG_QUERY_PENDING_MEMBER:
@@ -2076,7 +2069,11 @@ igmp_v3_cancel_link_timers(struct igmp_ifinfo *igi)
inm->inm_timer = 0;
_IF_DRAIN(&inm->inm_scq);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
+ SLIST_FOREACH_SAFE(inm, &igi->igi_relinmhead, inm_nrele, tinm) {
+ SLIST_REMOVE_HEAD(&igi->igi_relinmhead, inm_nrele);
+ inm_release_locked(inm);
+ }
}
/*
@@ -2289,13 +2286,11 @@ igmp_change_state(struct in_multi *inm)
*/
KASSERT(inm->inm_ifma != NULL, ("%s: no ifma", __func__));
ifp = inm->inm_ifma->ifma_ifp;
- if (ifp != NULL) {
- /*
- * Sanity check that netinet's notion of ifp is the
- * same as net's.
- */
- KASSERT(inm->inm_ifp == ifp, ("%s: bad ifp", __func__));
- }
+ /*
+ * Sanity check that netinet's notion of ifp is the
+ * same as net's.
+ */
+ KASSERT(inm->inm_ifp == ifp, ("%s: bad ifp", __func__));
IGMP_LOCK();
@@ -3322,7 +3317,7 @@ igmp_v3_merge_state_changes(struct in_multi *inm, struct ifqueue *ifscq)
static void
igmp_v3_dispatch_general_query(struct igmp_ifinfo *igi)
{
- struct ifmultiaddr *ifma, *tifma;
+ struct ifmultiaddr *ifma;
struct ifnet *ifp;
struct in_multi *inm;
int retval, loop;
@@ -3335,8 +3330,8 @@ igmp_v3_dispatch_general_query(struct igmp_ifinfo *igi)
ifp = igi->igi_ifp;
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, tifma) {
+ IF_ADDR_RLOCK(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET ||
ifma->ifma_protospec == NULL)
continue;
@@ -3366,7 +3361,7 @@ igmp_v3_dispatch_general_query(struct igmp_ifinfo *igi)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
loop = (igi->igi_flags & IGIF_LOOPBACK) ? 1 : 0;
igmp_dispatch_queue(&igi->igi_gq, IGMP_MAX_RESPONSE_BURST, loop);
diff --git a/freebsd/sys/netinet/in.c b/freebsd/sys/netinet/in.c
index b9231e13..9d84e82b 100644
--- a/freebsd/sys/netinet/in.c
+++ b/freebsd/sys/netinet/in.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_llatbl.h>
#include <net/if_types.h>
@@ -71,7 +72,7 @@ static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
struct ifnet *, struct thread *);
static int in_addprefix(struct in_ifaddr *, int);
-static int in_scrubprefix(struct in_ifaddr *);
+static int in_scrubprefix(struct in_ifaddr *, u_int);
static void in_socktrim(struct sockaddr_in *);
static int in_ifinit(struct ifnet *,
struct in_ifaddr *, struct sockaddr_in *, int);
@@ -91,6 +92,9 @@ SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW,
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
#define V_ripcbinfo VNET(ripcbinfo)
+VNET_DECLARE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
+#define V_arpstat VNET(arpstat)
+
/*
* Return 1 if an internet address is for a ``local'' host
* (one to which we have a connection). If subnetsarelocal
@@ -340,7 +344,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK();
if (ia == NULL) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
iap = ifatoia(ifa);
if (iap->ia_addr.sin_family == AF_INET) {
@@ -354,7 +358,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
}
if (ia != NULL)
ifa_ref(&ia->ia_ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
if (ia == NULL)
iaIsFirst = 1;
@@ -418,9 +422,9 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
ia->ia_ifp = ifp;
ifa_ref(ifa); /* if_addrhead */
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
ifa_ref(ifa); /* in_ifaddrhead */
IN_IFADDR_WLOCK();
TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
@@ -546,7 +550,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
* is the same as before, then the call is
* un-necessarily executed here.
*/
- in_ifscrub(ifp, ia);
+ in_ifscrub(ifp, ia, LLE_STATIC);
ia->ia_sockmask = ifra->ifra_mask;
ia->ia_sockmask.sin_family = AF_INET;
ia->ia_subnetmask =
@@ -555,7 +559,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
}
if ((ifp->if_flags & IFF_POINTOPOINT) &&
(ifra->ifra_dstaddr.sin_family == AF_INET)) {
- in_ifscrub(ifp, ia);
+ in_ifscrub(ifp, ia, LLE_STATIC);
ia->ia_dstaddr = ifra->ifra_dstaddr;
maskIsNew = 1; /* We lie; but the effect's the same */
}
@@ -583,7 +587,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
/*
* in_ifscrub kills the interface route.
*/
- in_ifscrub(ifp, ia);
+ in_ifscrub(ifp, ia, LLE_STATIC);
/*
* in_ifadown gets rid of all the rest of
@@ -600,7 +604,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
panic("in_control: unsupported ioctl");
}
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
/* Re-check that ia is still part of the list. */
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa == &ia->ia_ifa)
@@ -612,12 +616,12 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
* try it again for the next loop as there is no other exit
* path between here and out.
*/
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
error = EADDRNOTAVAIL;
goto out;
}
TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
ifa_free(&ia->ia_ifa); /* if_addrhead */
IN_IFADDR_WLOCK();
@@ -718,7 +722,7 @@ in_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
if (iflr->flags & IFLR_PREFIX)
return (EINVAL);
- /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
+ /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
bzero(&ifra, sizeof(ifra));
bcopy(iflr->iflr_name, ifra.ifra_name,
sizeof(ifra.ifra_name));
@@ -767,8 +771,9 @@ in_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
}
}
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family != AF_INET6)
+ if (ifa->ifa_addr->sa_family != AF_INET)
continue;
if (match.s_addr == 0)
break;
@@ -777,6 +782,9 @@ in_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
if (candidate.s_addr == match.s_addr)
break;
}
+ if (ifa != NULL)
+ ifa_ref(ifa);
+ IF_ADDR_RUNLOCK(ifp);
if (ifa == NULL)
return (EADDRNOTAVAIL);
ia = (struct in_ifaddr *)ifa;
@@ -795,12 +803,13 @@ in_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
in_mask2len(&ia->ia_sockmask.sin_addr);
iflr->flags = 0; /*XXX*/
+ ifa_free(ifa);
return (0);
} else {
struct in_aliasreq ifra;
- /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
+ /* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
bzero(&ifra, sizeof(ifra));
bcopy(iflr->iflr_name, ifra.ifra_name,
sizeof(ifra.ifra_name));
@@ -813,6 +822,7 @@ in_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
}
bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
ia->ia_sockmask.sin_len);
+ ifa_free(ifa);
return (in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
ifp, td));
@@ -827,10 +837,10 @@ in_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
* Delete any existing route for an interface.
*/
void
-in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
+in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, u_int flags)
{
- in_scrubprefix(ia);
+ in_scrubprefix(ia, flags);
}
/*
@@ -885,7 +895,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
splx(s);
if (scrub) {
ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
- in_ifscrub(ifp, ia);
+ in_ifscrub(ifp, ia, LLE_STATIC);
ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
}
if (IN_CLASSA(i))
@@ -949,7 +959,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
bzero(&ia_ro, sizeof(ia_ro));
*((struct sockaddr_in *)(&ia_ro.ro_dst)) = ia->ia_addr;
- rtalloc_ign_fib(&ia_ro, 0, 0);
+ rtalloc_ign_fib(&ia_ro, 0, RT_DEFAULT_FIB);
if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
(ia_ro.ro_rt->rt_ifp == V_loif)) {
RT_LOCK(ia_ro.ro_rt);
@@ -1035,7 +1045,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
IN_IFADDR_RLOCK();
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia)) {
- p = ia->ia_addr.sin_addr;
+ p = ia->ia_dstaddr.sin_addr;
if (prefix.s_addr != p.s_addr)
continue;
@@ -1093,7 +1103,7 @@ extern void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
* otherwise.
*/
static int
-in_scrubprefix(struct in_ifaddr *target)
+in_scrubprefix(struct in_ifaddr *target, u_int flags)
{
struct in_ifaddr *ia;
struct in_addr prefix, mask, p;
@@ -1124,17 +1134,22 @@ in_scrubprefix(struct in_ifaddr *target)
RT_LOCK(ia_ro.ro_rt);
if (ia_ro.ro_rt->rt_refcnt <= 1)
freeit = 1;
- else
+ else if (flags & LLE_STATIC) {
RT_REMREF(ia_ro.ro_rt);
+ target->ia_flags &= ~IFA_RTSELF;
+ }
RTFREE_LOCKED(ia_ro.ro_rt);
}
- if (freeit)
+ if (freeit && (flags & LLE_STATIC)) {
error = ifa_del_loopback_route((struct ifaddr *)target,
(struct sockaddr *)&target->ia_addr);
- if (error == 0)
- target->ia_flags &= ~IFA_RTSELF;
- /* remove arp cache */
- arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
+ if (error == 0)
+ target->ia_flags &= ~IFA_RTSELF;
+ }
+ if ((flags & LLE_STATIC) &&
+ !(target->ia_ifp->if_flags & IFF_NOARP))
+ /* remove arp cache */
+ arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
}
if (rtinitflags(target))
@@ -1159,7 +1174,8 @@ in_scrubprefix(struct in_ifaddr *target)
p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
}
- if (prefix.s_addr != p.s_addr)
+ if ((prefix.s_addr != p.s_addr) ||
+ !(ia->ia_ifp->if_flags & IFF_UP))
continue;
/*
@@ -1172,17 +1188,24 @@ in_scrubprefix(struct in_ifaddr *target)
* doesn't support such action.
*/
if ((ia->ia_flags & IFA_ROUTE) == 0
- && (ia->ia_ifp->if_type != IFT_CARP)
- ) {
+ && (ia->ia_ifp->if_type != IFT_CARP)) {
+ ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK();
- rtinit(&(target->ia_ifa), (int)RTM_DELETE,
+ error = rtinit(&(target->ia_ifa), (int)RTM_DELETE,
rtinitflags(target));
- target->ia_flags &= ~IFA_ROUTE;
-
+ if (error == 0)
+ target->ia_flags &= ~IFA_ROUTE;
+ else
+ log(LOG_INFO, "in_scrubprefix: err=%d, old prefix delete failed\n",
+ error);
error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
rtinitflags(ia) | RTF_UP);
if (error == 0)
ia->ia_flags |= IFA_ROUTE;
+ else
+ log(LOG_INFO, "in_scrubprefix: err=%d, new prefix add failed\n",
+ error);
+ ifa_free(&ia->ia_ifa);
return (error);
}
}
@@ -1199,15 +1222,18 @@ in_scrubprefix(struct in_ifaddr *target)
mask0.sin_len = sizeof(mask0);
mask0.sin_family = AF_INET;
mask0.sin_addr.s_addr = target->ia_subnetmask;
- lltable_prefix_free(AF_INET, (struct sockaddr *)&prefix0,
- (struct sockaddr *)&mask0);
+ lltable_prefix_free(AF_INET, (struct sockaddr *)&prefix0,
+ (struct sockaddr *)&mask0, flags);
/*
* As no-one seem to have this prefix, we can remove the route.
*/
- rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
- target->ia_flags &= ~IFA_ROUTE;
- return (0);
+ error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
+ if (error == 0)
+ target->ia_flags &= ~IFA_ROUTE;
+ else
+ log(LOG_INFO, "in_scrubprefix: err=%d, prefix delete failed\n", error);
+ return (error);
}
#undef rtinitflags
@@ -1286,7 +1312,7 @@ in_purgemaddrs(struct ifnet *ifp)
* We need to do this as IF_ADDR_LOCK() may be re-acquired
* by code further down.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET ||
ifma->ifma_protospec == NULL)
@@ -1298,7 +1324,7 @@ in_purgemaddrs(struct ifnet *ifp)
inm = (struct in_multi *)ifma->ifma_protospec;
LIST_INSERT_HEAD(&purgeinms, inm, inm_link);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
LIST_FOREACH_SAFE(inm, &purgeinms, inm_link, tinm) {
LIST_REMOVE(inm, inm_link);
@@ -1359,25 +1385,33 @@ in_lltable_free(struct lltable *llt, struct llentry *lle)
static void
in_lltable_prefix_free(struct lltable *llt,
const struct sockaddr *prefix,
- const struct sockaddr *mask)
+ const struct sockaddr *mask,
+ u_int flags)
{
const struct sockaddr_in *pfx = (const struct sockaddr_in *)prefix;
const struct sockaddr_in *msk = (const struct sockaddr_in *)mask;
struct llentry *lle, *next;
register int i;
+ size_t pkts_dropped;
for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
- if (IN_ARE_MASKED_ADDR_EQUAL((struct sockaddr_in *)L3_ADDR(lle),
- pfx, msk)) {
+ /*
+ * (flags & LLE_STATIC) means deleting all entries
+ * including static ARP entries
+ */
+ if (IN_ARE_MASKED_ADDR_EQUAL((struct sockaddr_in *)L3_ADDR(lle),
+ pfx, msk) &&
+ ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC))) {
int canceled;
canceled = callout_drain(&lle->la_timer);
LLE_WLOCK(lle);
if (canceled)
LLE_REMREF(lle);
- llentry_free(lle);
+ pkts_dropped = llentry_free(lle);
+ ARPSTAT_ADD(dropped, pkts_dropped);
}
}
}
@@ -1394,19 +1428,68 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
/* XXX rtalloc1 should take a const param */
rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
- if (rt == NULL || (!(flags & LLE_PUB) &&
- ((rt->rt_flags & RTF_GATEWAY) ||
- (rt->rt_ifp != ifp)))) {
+
+ if (rt == NULL)
+ return (EINVAL);
+
+ /*
+ * If the gateway for an existing host route matches the target L3
+ * address, which is a special route inserted by some implementation
+ * such as MANET, and the interface is of the correct type, then
+ * allow for ARP to proceed.
+ */
+ if (rt->rt_flags & RTF_GATEWAY) {
+ if (!(rt->rt_flags & RTF_HOST) || !rt->rt_ifp ||
+ rt->rt_ifp->if_type != IFT_ETHER ||
+ (rt->rt_ifp->if_flags &
+ (IFF_NOARP | IFF_STATICARP)) != 0 ||
+ memcmp(rt->rt_gateway->sa_data, l3addr->sa_data,
+ sizeof(in_addr_t)) != 0) {
+ RTFREE_LOCKED(rt);
+ return (EINVAL);
+ }
+ }
+
+ /*
+ * Make sure that at least the destination address is covered
+ * by the route. This is for handling the case where 2 or more
+ * interfaces have the same prefix. An incoming packet arrives
+ * on one interface and the corresponding outgoing packet leaves
+ * another interface.
+ */
+ if (!(rt->rt_flags & RTF_HOST) && rt->rt_ifp != ifp) {
+ const char *sa, *mask, *addr, *lim;
+ int len;
+
+ mask = (const char *)rt_mask(rt);
+ /*
+ * Just being extra cautious to avoid some custom
+ * code getting into trouble.
+ */
+ if (mask == NULL) {
+ RTFREE_LOCKED(rt);
+ return (EINVAL);
+ }
+
+ sa = (const char *)rt_key(rt);
+ addr = (const char *)l3addr;
+ len = ((const struct sockaddr_in *)l3addr)->sin_len;
+ lim = addr + len;
+
+ for ( ; addr < lim; sa++, mask++, addr++) {
+ if ((*sa ^ *addr) & *mask) {
#ifdef DIAGNOSTIC
- log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
- inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
+ log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
+ inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
#endif
- if (rt != NULL)
- RTFREE_LOCKED(rt);
- return (EINVAL);
+ RTFREE_LOCKED(rt);
+ return (EINVAL);
+ }
+ }
}
+
RTFREE_LOCKED(rt);
- return 0;
+ return (0);
}
/*
@@ -1576,10 +1659,8 @@ in_domifattach(struct ifnet *ifp)
llt = lltable_init(ifp, AF_INET);
if (llt != NULL) {
- llt->llt_new = in_lltable_new;
llt->llt_free = in_lltable_free;
llt->llt_prefix_free = in_lltable_prefix_free;
- llt->llt_rtcheck = in_lltable_rtcheck;
llt->llt_lookup = in_lltable_lookup;
llt->llt_dump = in_lltable_dump;
}
diff --git a/freebsd/sys/netinet/in.h b/freebsd/sys/netinet/in.h
index c0bc26ec..16df5f24 100644
--- a/freebsd/sys/netinet/in.h
+++ b/freebsd/sys/netinet/in.h
@@ -481,6 +481,7 @@ __END_DECLS
#define IP_RECVTTL 65 /* bool; receive IP TTL w/dgram */
#define IP_MINTTL 66 /* minimum TTL for packet or drop */
#define IP_DONTFRAG 67 /* don't fragment packet */
+#define IP_RECVTOS 68 /* bool; receive IP TOS w/dgram */
/* IPv4 Source Filter Multicast API [RFC3678] */
#define IP_ADD_SOURCE_MEMBERSHIP 70 /* join a source-specific group */
diff --git a/freebsd/sys/netinet/in_mcast.c b/freebsd/sys/netinet/in_mcast.c
index d6a316a5..b5fd6572 100644
--- a/freebsd/sys/netinet/in_mcast.c
+++ b/freebsd/sys/netinet/in_mcast.c
@@ -423,7 +423,7 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group,
return (error);
/* XXX ifma_protospec must be covered by IF_ADDR_LOCK */
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
/*
* If something other than netinet is occupying the link-layer
@@ -447,11 +447,11 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group,
#endif
++inm->inm_refcount;
*pinm = inm;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
return (0);
}
- IF_ADDR_LOCK_ASSERT(ifp);
+ IF_ADDR_WLOCK_ASSERT(ifp);
/*
* A new in_multi record is needed; allocate and initialize it.
@@ -463,7 +463,7 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group,
inm = malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT | M_ZERO);
if (inm == NULL) {
if_delmulti_ifma(ifma);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
return (ENOMEM);
}
inm->inm_addr = *group;
@@ -486,7 +486,7 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group,
*pinm = inm;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
return (0);
}
@@ -1615,6 +1615,8 @@ inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
* has asked for, but we always tell userland how big the
* buffer really needs to be.
*/
+ if (msfr.msfr_nsrcs > in_mcast_maxsocksrc)
+ msfr.msfr_nsrcs = in_mcast_maxsocksrc;
tss = NULL;
if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) {
tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs,
@@ -2777,7 +2779,7 @@ sysctl_ip_mcast_filters(SYSCTL_HANDLER_ARGS)
IN_MULTI_LOCK();
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET ||
ifma->ifma_protospec == NULL)
@@ -2810,7 +2812,7 @@ sysctl_ip_mcast_filters(SYSCTL_HANDLER_ARGS)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
IN_MULTI_UNLOCK();
diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c
index d56eb7ae..c8c1c3b0 100644
--- a/freebsd/sys/netinet/in_pcb.c
+++ b/freebsd/sys/netinet/in_pcb.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_ddb.h>
#include <rtems/bsd/local/opt_ipsec.h>
+#include <rtems/bsd/local/opt_inet.h>
#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/sys/param.h>
@@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$");
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
+#include <netinet6/in6_pcb.h>
#endif /* INET6 */
@@ -277,6 +279,124 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
return (0);
}
+#if defined(INET) || defined(INET6)
+int
+in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
+ struct ucred *cred, int wild)
+{
+ struct inpcbinfo *pcbinfo;
+ struct inpcb *tmpinp;
+ unsigned short *lastport;
+ int count, dorandom, error;
+ u_short aux, first, last, lport;
+#ifdef INET
+ struct in_addr laddr;
+#endif
+
+ pcbinfo = inp->inp_pcbinfo;
+
+ /*
+ * Because no actual state changes occur here, a global write lock on
+ * the pcbinfo isn't required.
+ */
+ INP_INFO_LOCK_ASSERT(pcbinfo);
+ INP_LOCK_ASSERT(inp);
+
+ if (inp->inp_flags & INP_HIGHPORT) {
+ first = V_ipport_hifirstauto; /* sysctl */
+ last = V_ipport_hilastauto;
+ lastport = &pcbinfo->ipi_lasthi;
+ } else if (inp->inp_flags & INP_LOWPORT) {
+ error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0);
+ if (error)
+ return (error);
+ first = V_ipport_lowfirstauto; /* 1023 */
+ last = V_ipport_lowlastauto; /* 600 */
+ lastport = &pcbinfo->ipi_lastlow;
+ } else {
+ first = V_ipport_firstauto; /* sysctl */
+ last = V_ipport_lastauto;
+ lastport = &pcbinfo->ipi_lastport;
+ }
+ /*
+ * For UDP, use random port allocation as long as the user
+ * allows it. For TCP (and as of yet unknown) connections,
+ * use random port allocation only if the user allows it AND
+ * ipport_tick() allows it.
+ */
+ if (V_ipport_randomized &&
+ (!V_ipport_stoprandom || pcbinfo == &V_udbinfo))
+ dorandom = 1;
+ else
+ dorandom = 0;
+ /*
+ * It makes no sense to do random port allocation if
+ * we have the only port available.
+ */
+ if (first == last)
+ dorandom = 0;
+ /* Make sure to not include UDP packets in the count. */
+ if (pcbinfo != &V_udbinfo)
+ V_ipport_tcpallocs++;
+ /*
+ * Instead of having two loops further down counting up or down
+ * make sure that first is always <= last and go with only one
+ * code path implementing all logic.
+ */
+ if (first > last) {
+ aux = first;
+ first = last;
+ last = aux;
+ }
+
+#ifdef INET
+ /* Make the compiler happy. */
+ laddr.s_addr = 0;
+ if ((inp->inp_vflag & (INP_IPV4|INP_IPV6)) == INP_IPV4) {
+ KASSERT(laddrp != NULL, ("%s: laddrp NULL for v4 inp %p",
+ __func__, inp));
+ laddr = *laddrp;
+ }
+#endif
+ lport = *lportp;
+
+ if (dorandom)
+ *lastport = first + (arc4random() % (last - first));
+
+ count = last - first;
+
+ do {
+ if (count-- < 0) /* completely used? */
+ return (EADDRNOTAVAIL);
+ ++*lastport;
+ if (*lastport < first || *lastport > last)
+ *lastport = first;
+ lport = htons(*lastport);
+
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV6) != 0)
+ tmpinp = in6_pcblookup_local(pcbinfo,
+ &inp->in6p_laddr, lport, wild, cred);
+#endif
+#if defined(INET) && defined(INET6)
+ else
+#endif
+#ifdef INET
+ tmpinp = in_pcblookup_local(pcbinfo, laddr,
+ lport, wild, cred);
+#endif
+ } while (tmpinp != NULL);
+
+#ifdef INET
+ if ((inp->inp_vflag & (INP_IPV4|INP_IPV6)) == INP_IPV4)
+ laddrp->s_addr = laddr.s_addr;
+#endif
+ *lportp = lport;
+
+ return (0);
+}
+#endif /* INET || INET6 */
+
/*
* Set up a bind operation on a PCB, performing port allocation
* as required, but do not actually modify the PCB. Callers can
@@ -291,14 +411,12 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
u_short *lportp, struct ucred *cred)
{
struct socket *so = inp->inp_socket;
- unsigned short *lastport;
struct sockaddr_in *sin;
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
struct in_addr laddr;
u_short lport = 0;
int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
int error;
- int dorandom;
/*
* Because no actual state changes occur here, a global write lock on
@@ -427,72 +545,10 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
if (*lportp != 0)
lport = *lportp;
if (lport == 0) {
- u_short first, last, aux;
- int count;
-
- if (inp->inp_flags & INP_HIGHPORT) {
- first = V_ipport_hifirstauto; /* sysctl */
- last = V_ipport_hilastauto;
- lastport = &pcbinfo->ipi_lasthi;
- } else if (inp->inp_flags & INP_LOWPORT) {
- error = priv_check_cred(cred,
- PRIV_NETINET_RESERVEDPORT, 0);
- if (error)
- return error;
- first = V_ipport_lowfirstauto; /* 1023 */
- last = V_ipport_lowlastauto; /* 600 */
- lastport = &pcbinfo->ipi_lastlow;
- } else {
- first = V_ipport_firstauto; /* sysctl */
- last = V_ipport_lastauto;
- lastport = &pcbinfo->ipi_lastport;
- }
- /*
- * For UDP, use random port allocation as long as the user
- * allows it. For TCP (and as of yet unknown) connections,
- * use random port allocation only if the user allows it AND
- * ipport_tick() allows it.
- */
- if (V_ipport_randomized &&
- (!V_ipport_stoprandom || pcbinfo == &V_udbinfo))
- dorandom = 1;
- else
- dorandom = 0;
- /*
- * It makes no sense to do random port allocation if
- * we have the only port available.
- */
- if (first == last)
- dorandom = 0;
- /* Make sure to not include UDP packets in the count. */
- if (pcbinfo != &V_udbinfo)
- V_ipport_tcpallocs++;
- /*
- * Instead of having two loops further down counting up or down
- * make sure that first is always <= last and go with only one
- * code path implementing all logic.
- */
- if (first > last) {
- aux = first;
- first = last;
- last = aux;
- }
-
- if (dorandom)
- *lastport = first +
- (arc4random() % (last - first));
-
- count = last - first;
+ error = in_pcb_lport(inp, &laddr, &lport, cred, wild);
+ if (error != 0)
+ return (error);
- do {
- if (count-- < 0) /* completely used? */
- return (EADDRNOTAVAIL);
- ++*lastport;
- if (*lastport < first || *lastport > last)
- *lastport = first;
- lport = htons(*lastport);
- } while (in_pcblookup_local(pcbinfo, laddr,
- lport, wild, cred));
}
*laddrp = laddr.s_addr;
*lportp = lport;
@@ -615,7 +671,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
ifp = ia->ia_ifp;
ifa_free(&ia->ia_ifa);
ia = NULL;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
sa = ifa->ifa_addr;
@@ -629,10 +685,10 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
if (ia != NULL) {
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/* 3. As a last resort return the 'default' jail address. */
error = prison_get_ip4(cred, laddr);
@@ -674,7 +730,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
*/
ia = NULL;
ifp = sro.ro_rt->rt_ifp;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
sa = ifa->ifa_addr;
if (sa->sa_family != AF_INET)
@@ -687,10 +743,10 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
if (ia != NULL) {
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/* 3. As a last resort return the 'default' jail address. */
error = prison_get_ip4(cred, laddr);
@@ -738,7 +794,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
ifp = ia->ia_ifp;
ifa_free(&ia->ia_ifa);
ia = NULL;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
sa = ifa->ifa_addr;
@@ -753,10 +809,10 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
if (ia != NULL) {
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto done;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
/* 3. As a last resort return the 'default' jail address. */
@@ -858,17 +914,20 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
if (imo->imo_multicast_ifp != NULL) {
ifp = imo->imo_multicast_ifp;
IN_IFADDR_RLOCK();
- TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
- if (ia->ia_ifp == ifp)
+ TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+ if ((ia->ia_ifp == ifp) &&
+ (cred == NULL ||
+ prison_check_ip4(cred,
+ &ia->ia_addr.sin_addr) == 0))
break;
- if (ia == NULL) {
- IN_IFADDR_RUNLOCK();
+ }
+ if (ia == NULL)
error = EADDRNOTAVAIL;
- } else {
+ else {
laddr = ia->ia_addr.sin_addr;
- IN_IFADDR_RUNLOCK();
error = 0;
}
+ IN_IFADDR_RUNLOCK();
}
}
if (error)
@@ -1813,6 +1872,10 @@ db_print_inpflags(int inp_flags)
db_printf("%sINP_DONTFRAG", comma ? ", " : "");
comma = 1;
}
+ if (inp_flags & INP_RECVTOS) {
+ db_printf("%sINP_RECVTOS", comma ? ", " : "");
+ comma = 1;
+ }
if (inp_flags & IN6P_IPV6_V6ONLY) {
db_printf("%sIN6P_IPV6_V6ONLY", comma ? ", " : "");
comma = 1;
diff --git a/freebsd/sys/netinet/in_pcb.h b/freebsd/sys/netinet/in_pcb.h
index 6e3a24be..9f602ce2 100644
--- a/freebsd/sys/netinet/in_pcb.h
+++ b/freebsd/sys/netinet/in_pcb.h
@@ -413,6 +413,7 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
#define INP_DONTFRAG 0x00000800 /* don't fragment packet */
#define INP_BINDANY 0x00001000 /* allow bind to any address */
#define INP_INHASHLIST 0x00002000 /* in_pcbinshash() has been called */
+#define INP_RECVTOS 0x00004000 /* receive incoming IP TOS */
#define IN6P_IPV6_V6ONLY 0x00008000 /* restrict AF_INET6 socket for v6 */
#define IN6P_PKTINFO 0x00010000 /* receive IP6 dst and I/F */
#define IN6P_HOPLIMIT 0x00020000 /* receive hoplimit */
@@ -432,7 +433,7 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
#define IN6P_MTU 0x80000000 /* receive path MTU */
#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|\
- INP_RECVIF|INP_RECVTTL|\
+ INP_RECVIF|INP_RECVTTL|INP_RECVTOS|\
IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|\
IN6P_DSTOPTS|IN6P_RTHDR|IN6P_RTHDRDSTOPTS|\
IN6P_TCLASS|IN6P_AUTOFLOWLABEL|IN6P_RFC2292|\
@@ -486,6 +487,8 @@ extern struct callout ipport_tick_callout;
void in_pcbpurgeif0(struct inpcbinfo *, struct ifnet *);
int in_pcballoc(struct socket *, struct inpcbinfo *);
int in_pcbbind(struct inpcb *, struct sockaddr *, struct ucred *);
+int in_pcb_lport(struct inpcb *, struct in_addr *, u_short *,
+ struct ucred *, int);
int in_pcbbind_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
u_short *, struct ucred *);
int in_pcbconnect(struct inpcb *, struct sockaddr *, struct ucred *);
diff --git a/freebsd/sys/netinet/in_proto.c b/freebsd/sys/netinet/in_proto.c
index db25a54d..8b184cb9 100644
--- a/freebsd/sys/netinet/in_proto.c
+++ b/freebsd/sys/netinet/in_proto.c
@@ -95,6 +95,8 @@ static struct pr_usrreqs nousrreqs;
#include <net/if_pfsync.h>
#endif
+FEATURE(inet, "Internet Protocol version 4");
+
extern struct domain inetdomain;
/* Spacer for loadable protocols. */
@@ -150,7 +152,7 @@ struct protosw inetsw[] = {
},
#ifdef SCTP
{
- .pr_type = SOCK_DGRAM,
+ .pr_type = SOCK_SEQPACKET,
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_SCTP,
.pr_flags = PR_WANTRCVD,
@@ -164,18 +166,6 @@ struct protosw inetsw[] = {
.pr_drain = sctp_drain,
.pr_usrreqs = &sctp_usrreqs
},
-{
- .pr_type = SOCK_SEQPACKET,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_SCTP,
- .pr_flags = PR_WANTRCVD,
- .pr_input = sctp_input,
- .pr_ctlinput = sctp_ctlinput,
- .pr_ctloutput = sctp_ctloutput,
- .pr_drain = sctp_drain,
- .pr_usrreqs = &sctp_usrreqs
-},
-
{
.pr_type = SOCK_STREAM,
.pr_domain = &inetdomain,
diff --git a/freebsd/sys/netinet/in_rmx.c b/freebsd/sys/netinet/in_rmx.c
index dda56194..447605ec 100644
--- a/freebsd/sys/netinet/in_rmx.c
+++ b/freebsd/sys/netinet/in_rmx.c
@@ -29,19 +29,6 @@
* SUCH DAMAGE.
*/
-/*
- * This code does two things necessary for the enhanced TCP metrics to
- * function in a useful manner:
- * 1) It marks all non-host routes as `cloning', thus ensuring that
- * every actual reference to such a route actually gets turned
- * into a reference to a host route to the specific destination
- * requested.
- * 2) When such routes lose all their references, it arranges for them
- * to be deleted in some random collection of circumstances, so that
- * a large quantity of stale routing data is not kept in kernel memory
- * indefinitely. See in_rtqtimo() below for the exact mechanism.
- */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -60,6 +47,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
#include <netinet/ip_var.h>
extern int in_inithead(void **head, int off);
@@ -342,6 +331,13 @@ in_rtqdrain(void)
VNET_LIST_RUNLOCK_NOSLEEP();
}
+void
+in_setmatchfunc(struct radix_node_head *rnh, int val)
+{
+
+ rnh->rnh_matchaddr = (val != 0) ? rn_match : in_matroute;
+}
+
static int _in_rt_was_here;
/*
* Initialize our routing tree.
@@ -367,7 +363,7 @@ in_inithead(void **head, int off)
rnh = *head;
rnh->rnh_addaddr = in_addroute;
- rnh->rnh_matchaddr = in_matroute;
+ in_setmatchfunc(rnh, V_drop_redirect);
rnh->rnh_close = in_clsroute;
if (_in_rt_was_here == 0 ) {
callout_init(&V_rtq_timer, CALLOUT_MPSAFE);
diff --git a/freebsd/sys/netinet/in_var.h b/freebsd/sys/netinet/in_var.h
index cd1d9043..c04d45b9 100644
--- a/freebsd/sys/netinet/in_var.h
+++ b/freebsd/sys/netinet/in_var.h
@@ -396,9 +396,9 @@ inm_lookup(struct ifnet *ifp, const struct in_addr ina)
struct in_multi *inm;
IN_MULTI_LOCK_ASSERT();
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
inm = inm_lookup_locked(ifp, ina);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return (inm);
}
@@ -423,6 +423,7 @@ inm_acquire_locked(struct in_multi *inm)
struct rtentry;
struct route;
struct ip_moptions;
+struct radix_node_head;
int imo_multi_filter(const struct ip_moptions *, const struct ifnet *,
const struct sockaddr *, const struct sockaddr *);
@@ -447,7 +448,7 @@ int in_control(struct socket *, u_long, caddr_t, struct ifnet *,
void in_rtqdrain(void);
void ip_input(struct mbuf *);
int in_ifadown(struct ifaddr *ifa, int);
-void in_ifscrub(struct ifnet *, struct in_ifaddr *);
+void in_ifscrub(struct ifnet *, struct in_ifaddr *, u_int);
struct mbuf *ip_fastforward(struct mbuf *);
void *in_domifattach(struct ifnet *);
void in_domifdetach(struct ifnet *, void *);
@@ -461,6 +462,7 @@ void in_rtredirect(struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct sockaddr *, u_int);
int in_rtrequest(int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int, struct rtentry **, u_int);
+void in_setmatchfunc(struct radix_node_head *, int);
#if 0
int in_rt_getifa(struct rt_addrinfo *, u_int fibnum);
diff --git a/freebsd/sys/netinet/ip.h b/freebsd/sys/netinet/ip.h
index daee533e..6c9482f9 100644
--- a/freebsd/sys/netinet/ip.h
+++ b/freebsd/sys/netinet/ip.h
@@ -92,6 +92,31 @@ struct ip {
#define IPTOS_PREC_ROUTINE 0x00
/*
+ * Definitions for DiffServ Codepoints as per RFC2474
+ */
+#define IPTOS_DSCP_CS0 0x00
+#define IPTOS_DSCP_CS1 0x20
+#define IPTOS_DSCP_AF11 0x28
+#define IPTOS_DSCP_AF12 0x30
+#define IPTOS_DSCP_AF13 0x38
+#define IPTOS_DSCP_CS2 0x40
+#define IPTOS_DSCP_AF21 0x48
+#define IPTOS_DSCP_AF22 0x50
+#define IPTOS_DSCP_AF23 0x58
+#define IPTOS_DSCP_CS3 0x60
+#define IPTOS_DSCP_AF31 0x68
+#define IPTOS_DSCP_AF32 0x70
+#define IPTOS_DSCP_AF33 0x78
+#define IPTOS_DSCP_CS4 0x80
+#define IPTOS_DSCP_AF41 0x88
+#define IPTOS_DSCP_AF42 0x90
+#define IPTOS_DSCP_AF43 0x98
+#define IPTOS_DSCP_CS5 0xa0
+#define IPTOS_DSCP_EF 0xb8
+#define IPTOS_DSCP_CS6 0xc0
+#define IPTOS_DSCP_CS7 0xe0
+
+/*
* ECN (Explicit Congestion Notification) codepoints in RFC3168 mapped to the
* lower 2 bits of the TOS field.
*/
diff --git a/freebsd/sys/netinet/ip_carp.c b/freebsd/sys/netinet/ip_carp.c
index 7b2a7e18..3cfcf707 100644
--- a/freebsd/sys/netinet/ip_carp.c
+++ b/freebsd/sys/netinet/ip_carp.c
@@ -222,7 +222,7 @@ static void carp_set_state(struct carp_softc *, int);
static int carp_addrcount(struct carp_if *, struct in_ifaddr *, int);
enum { CARP_COUNT_MASTER, CARP_COUNT_RUNNING };
-static void carp_multicast_cleanup(struct carp_softc *);
+static void carp_multicast_cleanup(struct carp_softc *, int dofree);
static int carp_set_addr(struct carp_softc *, struct sockaddr_in *);
static int carp_del_addr(struct carp_softc *, struct sockaddr_in *);
static void carp_carpdev_state_locked(struct carp_if *);
@@ -231,7 +231,7 @@ static void carp_sc_state_locked(struct carp_softc *);
static void carp_send_na(struct carp_softc *);
static int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *);
static int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *);
-static void carp_multicast6_cleanup(struct carp_softc *);
+static void carp_multicast6_cleanup(struct carp_softc *, int dofree);
#endif
static LIST_HEAD(, carp_softc) carpif_list;
@@ -283,7 +283,7 @@ carp_hmac_prepare(struct carp_softc *sc)
found = 0;
last = cur;
cur.s_addr = 0xffffffff;
- IF_ADDR_LOCK(SC2IFP(sc));
+ IF_ADDR_RLOCK(SC2IFP(sc));
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr;
if (ifa->ifa_addr->sa_family == AF_INET &&
@@ -293,7 +293,7 @@ carp_hmac_prepare(struct carp_softc *sc)
found++;
}
}
- IF_ADDR_UNLOCK(SC2IFP(sc));
+ IF_ADDR_RUNLOCK(SC2IFP(sc));
if (found)
SHA1Update(&sc->sc_sha1, (void *)&cur, sizeof(cur));
} while (found);
@@ -304,7 +304,7 @@ carp_hmac_prepare(struct carp_softc *sc)
found = 0;
last6 = cur6;
memset(&cur6, 0xff, sizeof(cur6));
- IF_ADDR_LOCK(SC2IFP(sc));
+ IF_ADDR_RLOCK(SC2IFP(sc));
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
if (IN6_IS_SCOPE_EMBED(&in6))
@@ -316,7 +316,7 @@ carp_hmac_prepare(struct carp_softc *sc)
found++;
}
}
- IF_ADDR_UNLOCK(SC2IFP(sc));
+ IF_ADDR_RUNLOCK(SC2IFP(sc));
if (found)
SHA1Update(&sc->sc_sha1, (void *)&cur6, sizeof(cur6));
} while (found);
@@ -470,9 +470,11 @@ carp_clone_destroy(struct ifnet *ifp)
/*
* This function can be called on CARP interface destroy path,
* and in case of the removal of the underlying interface as
- * well. We differentiate these two cases. In the latter case
- * we do not cleanup our multicast memberships, since they
- * are already freed. Also, in the latter case we do not
+ * well. We differentiate these two cases: in case of destruction
+ * of the underlying interface, we do not cleanup our multicast
+ * memberships, since they are already freed. But we purge pointers
+ * to multicast structures, since they are no longer valid, to
+ * avoid panic in future calls to carpdetach(). Also, we do not
* release the lock on return, because the function will be
* called once more, for another CARP instance on the same
* interface.
@@ -497,10 +499,9 @@ carpdetach(struct carp_softc *sc, int unlock)
carp_set_state(sc, INIT);
SC2IFP(sc)->if_flags &= ~IFF_UP;
carp_setrun(sc, 0);
- if (unlock)
- carp_multicast_cleanup(sc);
+ carp_multicast_cleanup(sc, unlock);
#ifdef INET6
- carp_multicast6_cleanup(sc);
+ carp_multicast6_cleanup(sc, unlock);
#endif
if (sc->sc_carpdev != NULL) {
@@ -1141,7 +1142,7 @@ carp_addrcount(struct carp_if *cif, struct in_ifaddr *ia, int type)
(SC2IFP(vh)->if_flags & IFF_UP) &&
(SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING)) ||
(type == CARP_COUNT_MASTER && vh->sc_state == MASTER)) {
- IF_ADDR_LOCK(SC2IFP(vh));
+ IF_ADDR_RLOCK(SC2IFP(vh));
TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist,
ifa_list) {
if (ifa->ifa_addr->sa_family == AF_INET &&
@@ -1149,7 +1150,7 @@ carp_addrcount(struct carp_if *cif, struct in_ifaddr *ia, int type)
ifatoia(ifa)->ia_addr.sin_addr.s_addr)
count++;
}
- IF_ADDR_UNLOCK(SC2IFP(vh));
+ IF_ADDR_RUNLOCK(SC2IFP(vh));
}
}
return (count);
@@ -1189,7 +1190,7 @@ carp_iamatch(struct ifnet *ifp, struct in_ifaddr *ia,
TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
if ((SC2IFP(vh)->if_flags & IFF_UP) &&
(SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING)) {
- IF_ADDR_LOCK(SC2IFP(vh));
+ IF_ADDR_RLOCK(SC2IFP(vh));
TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist,
ifa_list) {
if (ifa->ifa_addr->sa_family ==
@@ -1200,11 +1201,11 @@ carp_iamatch(struct ifnet *ifp, struct in_ifaddr *ia,
if (vh->sc_state ==
MASTER) {
*enaddr = IF_LLADDR(vh->sc_ifp);
- IF_ADDR_UNLOCK(SC2IFP(vh));
+ IF_ADDR_RUNLOCK(SC2IFP(vh));
CARP_UNLOCK(cif);
return (1);
} else {
- IF_ADDR_UNLOCK(SC2IFP(vh));
+ IF_ADDR_RUNLOCK(SC2IFP(vh));
CARP_UNLOCK(cif);
return (0);
}
@@ -1212,7 +1213,7 @@ carp_iamatch(struct ifnet *ifp, struct in_ifaddr *ia,
count++;
}
}
- IF_ADDR_UNLOCK(SC2IFP(vh));
+ IF_ADDR_RUNLOCK(SC2IFP(vh));
}
}
} else {
@@ -1242,7 +1243,7 @@ carp_iamatch6(struct ifnet *ifp, struct in6_addr *taddr)
cif = ifp->if_carp;
CARP_LOCK(cif);
TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
- IF_ADDR_LOCK(SC2IFP(vh));
+ IF_ADDR_RLOCK(SC2IFP(vh));
TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist, ifa_list) {
if (IN6_ARE_ADDR_EQUAL(taddr,
&ifatoia6(ifa)->ia_addr.sin6_addr) &&
@@ -1250,12 +1251,12 @@ carp_iamatch6(struct ifnet *ifp, struct in6_addr *taddr)
(SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING) &&
vh->sc_state == MASTER) {
ifa_ref(ifa);
- IF_ADDR_UNLOCK(SC2IFP(vh));
+ IF_ADDR_RUNLOCK(SC2IFP(vh));
CARP_UNLOCK(cif);
return (ifa);
}
}
- IF_ADDR_UNLOCK(SC2IFP(vh));
+ IF_ADDR_RUNLOCK(SC2IFP(vh));
}
CARP_UNLOCK(cif);
@@ -1273,7 +1274,7 @@ carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr)
cif = ifp->if_carp;
CARP_LOCK(cif);
TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) {
- IF_ADDR_LOCK(SC2IFP(sc));
+ IF_ADDR_RLOCK(SC2IFP(sc));
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
if (IN6_ARE_ADDR_EQUAL(taddr,
&ifatoia6(ifa)->ia_addr.sin6_addr) &&
@@ -1284,7 +1285,7 @@ carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr)
sizeof(struct ifnet *), M_NOWAIT);
if (mtag == NULL) {
/* better a bit than nothing */
- IF_ADDR_UNLOCK(SC2IFP(sc));
+ IF_ADDR_RUNLOCK(SC2IFP(sc));
CARP_UNLOCK(cif);
return (IF_LLADDR(sc->sc_ifp));
}
@@ -1292,12 +1293,12 @@ carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr)
sizeof(struct ifnet *));
m_tag_prepend(m, mtag);
- IF_ADDR_UNLOCK(SC2IFP(sc));
+ IF_ADDR_RUNLOCK(SC2IFP(sc));
CARP_UNLOCK(cif);
return (IF_LLADDR(sc->sc_ifp));
}
}
- IF_ADDR_UNLOCK(SC2IFP(sc));
+ IF_ADDR_RUNLOCK(SC2IFP(sc));
}
CARP_UNLOCK(cif);
@@ -1394,22 +1395,10 @@ carp_setrun(struct carp_softc *sc, sa_family_t af)
switch (sc->sc_state) {
case INIT:
- if (carp_opts[CARPCTL_PREEMPT] && !carp_suppress_preempt) {
- carp_send_ad_locked(sc);
- carp_send_arp(sc);
-#ifdef INET6
- carp_send_na(sc);
-#endif /* INET6 */
- CARP_LOG("%s: INIT -> MASTER (preempting)\n",
- SC2IFP(sc)->if_xname);
- carp_set_state(sc, MASTER);
- carp_setroute(sc, RTM_ADD);
- } else {
- CARP_LOG("%s: INIT -> BACKUP\n", SC2IFP(sc)->if_xname);
- carp_set_state(sc, BACKUP);
- carp_setroute(sc, RTM_DELETE);
- carp_setrun(sc, 0);
- }
+ CARP_LOG("%s: INIT -> BACKUP\n", SC2IFP(sc)->if_xname);
+ carp_set_state(sc, BACKUP);
+ carp_setroute(sc, RTM_DELETE);
+ carp_setrun(sc, 0);
break;
case BACKUP:
callout_stop(&sc->sc_ad_tmo);
@@ -1448,7 +1437,7 @@ carp_setrun(struct carp_softc *sc, sa_family_t af)
}
static void
-carp_multicast_cleanup(struct carp_softc *sc)
+carp_multicast_cleanup(struct carp_softc *sc, int dofree)
{
struct ip_moptions *imo = &sc->sc_imo;
u_int16_t n = imo->imo_num_memberships;
@@ -1456,7 +1445,8 @@ carp_multicast_cleanup(struct carp_softc *sc)
/* Clean up our own multicast memberships */
while (n-- > 0) {
if (imo->imo_membership[n] != NULL) {
- in_delmulti(imo->imo_membership[n]);
+ if (dofree)
+ in_delmulti(imo->imo_membership[n]);
imo->imo_membership[n] = NULL;
}
}
@@ -1468,14 +1458,15 @@ carp_multicast_cleanup(struct carp_softc *sc)
#ifdef INET6
static void
-carp_multicast6_cleanup(struct carp_softc *sc)
+carp_multicast6_cleanup(struct carp_softc *sc, int dofree)
{
struct ip6_moptions *im6o = &sc->sc_im6o;
u_int16_t n = im6o->im6o_num_memberships;
while (n-- > 0) {
if (im6o->im6o_membership[n] != NULL) {
- in6_mc_leave(im6o->im6o_membership[n], NULL);
+ if (dofree)
+ in6_mc_leave(im6o->im6o_membership[n], NULL);
im6o->im6o_membership[n] = NULL;
}
}
@@ -1835,7 +1826,7 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
cleanup:
if (!sc->sc_naddrs6)
- carp_multicast6_cleanup(sc);
+ carp_multicast6_cleanup(sc, 1);
ifa_free(&ia->ia_ifa);
return (error);
}
@@ -1853,7 +1844,7 @@ carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
SC2IFP(sc)->if_flags &= ~IFF_UP;
SC2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
sc->sc_vhid = -1;
- carp_multicast6_cleanup(sc);
+ carp_multicast6_cleanup(sc, 1);
TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list);
if (!--cif->vhif_nvrs) {
CARP_LOCK_DESTROY(cif);
diff --git a/freebsd/sys/netinet/ip_divert.c b/freebsd/sys/netinet/ip_divert.c
index 857df606..d630dd12 100644
--- a/freebsd/sys/netinet/ip_divert.c
+++ b/freebsd/sys/netinet/ip_divert.c
@@ -710,8 +710,8 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
#ifdef SYSCTL_NODE
SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, divert, CTLFLAG_RW, 0, "IPDIVERT");
-SYSCTL_PROC(_net_inet_divert, OID_AUTO, pcblist, CTLFLAG_RD, 0, 0,
- div_pcblist, "S,xinpcb", "List of active divert sockets");
+SYSCTL_PROC(_net_inet_divert, OID_AUTO, pcblist, CTLTYPE_OPAQUE | CTLFLAG_RD,
+ NULL, 0, div_pcblist, "S,xinpcb", "List of active divert sockets");
#endif
struct pr_usrreqs div_usrreqs = {
diff --git a/freebsd/sys/netinet/ip_fw.h b/freebsd/sys/netinet/ip_fw.h
index cf5d8d03..69311a79 100644
--- a/freebsd/sys/netinet/ip_fw.h
+++ b/freebsd/sys/netinet/ip_fw.h
@@ -37,10 +37,10 @@
#define IPFW_DEFAULT_RULE 65535
/*
- * The number of ipfw tables. The maximum allowed table number is the
- * (IPFW_TABLES_MAX - 1).
+ * Default number of ipfw tables.
*/
-#define IPFW_TABLES_MAX 128
+#define IPFW_TABLES_MAX 65535
+#define IPFW_TABLES_DEFAULT 128
/*
* Most commands (queue, pipe, tag, untag, limit...) can have a 16-bit
@@ -57,6 +57,25 @@
#define IP_FW_TABLEARG 65535 /* XXX should use 0 */
/*
+ * Number of entries in the call stack of the call/return commands.
+ * Call stack currently is an uint16_t array with rule numbers.
+ */
+#define IPFW_CALLSTACK_SIZE 16
+
+/* IP_FW3 header/opcodes */
+typedef struct _ip_fw3_opheader {
+ uint16_t opcode; /* Operation opcode */
+ uint16_t reserved[3]; /* Align to 64-bit boundary */
+} ip_fw3_opheader;
+
+
+/* IPFW extented tables support */
+#define IP_FW_TABLE_XADD 86 /* add entry */
+#define IP_FW_TABLE_XDEL 87 /* delete entry */
+#define IP_FW_TABLE_XGETSIZE 88 /* get table size */
+#define IP_FW_TABLE_XLIST 89 /* list table contents */
+
+/*
* The kernel representation of ipfw rules is made of a list of
* 'instructions' (for all practical purposes equivalent to BPF
* instructions), which specify which fields of the packet
@@ -193,6 +212,8 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_SETFIB, /* arg1=FIB number */
O_FIB, /* arg1=FIB desired fib number */
+ O_CALLRETURN, /* arg1=called rule number */
+
O_LAST_OPCODE /* not an opcode! */
};
@@ -380,8 +401,6 @@ struct cfg_redir {
};
#endif
-#define NAT_BUF_LEN 1024
-
#ifdef IPFW_INTERNAL
/* Nat configuration data struct. */
struct cfg_nat {
@@ -562,6 +581,11 @@ struct _ipfw_dyn_rule {
/*
* These are used for lookup tables.
*/
+
+#define IPFW_TABLE_CIDR 1 /* Table for holding IPv4/IPv6 prefixes */
+#define IPFW_TABLE_INTERFACE 2 /* Table for holding interface names */
+#define IPFW_TABLE_MAXTYPE 2 /* Maximum valid number */
+
typedef struct _ipfw_table_entry {
in_addr_t addr; /* network address */
u_int32_t value; /* value */
@@ -569,6 +593,19 @@ typedef struct _ipfw_table_entry {
u_int8_t masklen; /* mask length */
} ipfw_table_entry;
+typedef struct _ipfw_table_xentry {
+ uint16_t len; /* Total entry length */
+ uint8_t type; /* entry type */
+ uint8_t masklen; /* mask length */
+ uint16_t tbl; /* table number */
+ uint32_t value; /* value */
+ union {
+ /* Longest field needs to be aligned by 4-byte boundary */
+ struct in6_addr addr6; /* IPv6 address */
+ char iface[IF_NAMESIZE]; /* interface name */
+ } k;
+} ipfw_table_xentry;
+
typedef struct _ipfw_table {
u_int32_t size; /* size of entries in bytes */
u_int32_t cnt; /* # of entries */
@@ -576,4 +613,13 @@ typedef struct _ipfw_table {
ipfw_table_entry ent[0]; /* entries */
} ipfw_table;
+typedef struct _ipfw_xtable {
+ ip_fw3_opheader opheader; /* eXtended tables are controlled via IP_FW3 */
+ uint32_t size; /* size of entries in bytes */
+ uint32_t cnt; /* # of entries */
+ uint16_t tbl; /* table number */
+ uint8_t type; /* table type */
+ ipfw_table_xentry xent[0]; /* entries */
+} ipfw_xtable;
+
#endif /* _IPFW2_H */
diff --git a/freebsd/sys/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c
index d8d34aa4..1b6ec7d9 100644
--- a/freebsd/sys/netinet/ip_icmp.c
+++ b/freebsd/sys/netinet/ip_icmp.c
@@ -94,11 +94,7 @@ SYSCTL_VNET_UINT(_net_inet_icmp, OID_AUTO, maskfake, CTLFLAG_RW,
&VNET_NAME(icmpmaskfake), 0,
"Fake reply to ICMP Address Mask Request packets.");
-static VNET_DEFINE(int, drop_redirect) = 0;
-#define V_drop_redirect VNET(drop_redirect)
-SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, drop_redirect, CTLFLAG_RW,
- &VNET_NAME(drop_redirect), 0,
- "Ignore ICMP redirects");
+VNET_DEFINE(int, drop_redirect) = 0;
static VNET_DEFINE(int, log_redirect) = 0;
#define V_log_redirect VNET(log_redirect)
@@ -155,6 +151,39 @@ static void icmp_send(struct mbuf *, struct mbuf *);
extern struct protosw inetsw[];
+static int
+sysctl_net_icmp_drop_redir(SYSCTL_HANDLER_ARGS)
+{
+ int error, new;
+ int i;
+ struct radix_node_head *rnh;
+
+ new = V_drop_redirect;
+ error = sysctl_handle_int(oidp, &new, 0, req);
+ if (error == 0 && req->newptr) {
+ new = (new != 0) ? 1 : 0;
+
+ if (new == V_drop_redirect)
+ return (0);
+
+ for (i = 0; i < rt_numfibs; i++) {
+ if ((rnh = rt_tables_get_rnh(i, AF_INET)) == NULL)
+ continue;
+ RADIX_NODE_HEAD_LOCK(rnh);
+ in_setmatchfunc(rnh, new);
+ RADIX_NODE_HEAD_UNLOCK(rnh);
+ }
+
+ V_drop_redirect = new;
+ }
+
+ return (error);
+}
+
+SYSCTL_VNET_PROC(_net_inet_icmp, OID_AUTO, drop_redirect,
+ CTLTYPE_INT|CTLFLAG_RW, 0, 0,
+ sysctl_net_icmp_drop_redir, "I", "Ignore ICMP redirects");
+
/*
* Kernel module interface for updating icmpstat. The argument is an index
* into icmpstat treated as an array of u_long. While this encodes the
@@ -699,7 +728,7 @@ icmp_reflect(struct mbuf *m)
*/
ifp = m->m_pkthdr.rcvif;
if (ifp != NULL && ifp->if_flags & IFF_BROADCAST) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
@@ -707,11 +736,11 @@ icmp_reflect(struct mbuf *m)
if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
t.s_addr) {
t = IA_SIN(ia)->sin_addr;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto match;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
/*
* If the packet was transiting through us, use the address of
@@ -720,16 +749,16 @@ icmp_reflect(struct mbuf *m)
* criteria apply.
*/
if (V_icmp_rfi && ifp != NULL) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
ia = ifatoia(ifa);
t = IA_SIN(ia)->sin_addr;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto match;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
/*
* If the incoming packet was not addressed directly to us, use
@@ -738,16 +767,16 @@ icmp_reflect(struct mbuf *m)
* with normal source selection.
*/
if (V_reply_src[0] != '\0' && (ifp = ifunit(V_reply_src))) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
ia = ifatoia(ifa);
t = IA_SIN(ia)->sin_addr;
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto match;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
}
/*
* If the packet was transiting through us, use the address of
@@ -960,7 +989,8 @@ badport_bandlim(int which)
{ "icmp tstamp response" },
{ "closed port RST response" },
{ "open port RST response" },
- { "icmp6 unreach response" }
+ { "icmp6 unreach response" },
+ { "sctp ootb response" }
};
/*
diff --git a/freebsd/sys/netinet/ip_input.c b/freebsd/sys/netinet/ip_input.c
index 1b7f4319..9d174b3b 100644
--- a/freebsd/sys/netinet/ip_input.c
+++ b/freebsd/sys/netinet/ip_input.c
@@ -512,7 +512,7 @@ tooshort:
}
#ifdef IPSEC
/*
- * Bypass packet filtering for packets from a tunnel (gif).
+ * Bypass packet filtering for packets previously handled by IPsec.
*/
if (ip_ipsec_filtertunnel(m))
goto passin;
@@ -635,7 +635,7 @@ passin:
* into the stack for SIMPLEX interfaces handled by ether_output().
*/
if (ifp != NULL && ifp->if_flags & IFF_BROADCAST) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
@@ -643,23 +643,23 @@ passin:
if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
ip->ip_dst.s_addr) {
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto ours;
}
if (ia->ia_netbroadcast.s_addr == ip->ip_dst.s_addr) {
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto ours;
}
#ifdef BOOTP_COMPAT
if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY) {
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
goto ours;
}
#endif
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
ia = NULL;
}
/* RFC 3927 2.7: Do not forward datagrams for 169.254.0.0/16. */
@@ -1033,7 +1033,7 @@ found:
* segment. If it provides all of our data, drop us, otherwise
* stick new segment in the proper place.
*
- * If some of the data is dropped from the the preceding
+ * If some of the data is dropped from the preceding
* segment, then it's checksum is invalidated.
*/
if (p) {
@@ -1713,6 +1713,12 @@ makedummy:
if (*mp)
mp = &(*mp)->m_next;
}
+ if (inp->inp_flags & INP_RECVTOS) {
+ *mp = sbcreatecontrol((caddr_t) &ip->ip_tos,
+ sizeof(u_char), IP_RECVTOS, IPPROTO_IP);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
}
/*
diff --git a/freebsd/sys/netinet/ip_ipsec.c b/freebsd/sys/netinet/ip_ipsec.c
index f83b2d93..917c2c79 100644
--- a/freebsd/sys/netinet/ip_ipsec.c
+++ b/freebsd/sys/netinet/ip_ipsec.c
@@ -97,7 +97,7 @@ ip_ipsec_filtertunnel(struct mbuf *m)
#if defined(IPSEC)
/*
- * Bypass packet filtering for packets from a tunnel.
+ * Bypass packet filtering for packets previously handled by IPsec.
*/
if (!V_ip4_ipsec_filtertunnel &&
m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
diff --git a/freebsd/sys/netinet/ip_mroute.c b/freebsd/sys/netinet/ip_mroute.c
index 022f2451..1e9cd57a 100644
--- a/freebsd/sys/netinet/ip_mroute.c
+++ b/freebsd/sys/netinet/ip_mroute.c
@@ -2824,7 +2824,7 @@ vnet_mroute_init(const void *unused __unused)
callout_init(&V_bw_meter_ch, CALLOUT_MPSAFE);
}
-VNET_SYSINIT(vnet_mroute_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, vnet_mroute_init,
+VNET_SYSINIT(vnet_mroute_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mroute_init,
NULL);
static void
@@ -2949,4 +2949,4 @@ static moduledata_t ip_mroutemod = {
0
};
-DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE);
diff --git a/freebsd/sys/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c
index c01e0d32..7aedcb50 100644
--- a/freebsd/sys/netinet/ip_output.c
+++ b/freebsd/sys/netinet/ip_output.c
@@ -95,7 +95,7 @@ __FBSDID("$FreeBSD$");
VNET_DEFINE(u_short, ip_id);
#ifdef MBUF_STRESS_TEST
-int mbuf_frag_size = 0;
+static int mbuf_frag_size = 0;
SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_frag_size, CTLFLAG_RW,
&mbuf_frag_size, 0, "Fragment outgoing mbufs to this size");
#endif
@@ -199,8 +199,8 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
hlen = ip->ip_hl << 2;
}
- dst = (struct sockaddr_in *)&ro->ro_dst;
again:
+ dst = (struct sockaddr_in *)&ro->ro_dst;
/*
* If there is a cached route,
* check that it is to the same destination
@@ -958,6 +958,7 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_FAITH:
case IP_ONESBCAST:
case IP_DONTFRAG:
+ case IP_RECVTOS:
error = sooptcopyin(sopt, &optval, sizeof optval,
sizeof optval);
if (error)
@@ -1021,6 +1022,9 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_BINDANY:
OPTSET(INP_BINDANY);
break;
+ case IP_RECVTOS:
+ OPTSET(INP_RECVTOS);
+ break;
}
break;
#undef OPTSET
@@ -1130,6 +1134,7 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_ONESBCAST:
case IP_DONTFRAG:
case IP_BINDANY:
+ case IP_RECVTOS:
switch (sopt->sopt_name) {
case IP_TOS:
@@ -1188,6 +1193,9 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_BINDANY:
optval = OPTBIT(INP_BINDANY);
break;
+ case IP_RECVTOS:
+ optval = OPTBIT(INP_RECVTOS);
+ break;
}
error = sooptcopyout(sopt, &optval, sizeof optval);
break;
diff --git a/freebsd/sys/netinet/ip_var.h b/freebsd/sys/netinet/ip_var.h
index 222b7efe..d196fd04 100644
--- a/freebsd/sys/netinet/ip_var.h
+++ b/freebsd/sys/netinet/ip_var.h
@@ -187,6 +187,7 @@ VNET_DECLARE(struct socket *, ip_mrouter); /* multicast routing daemon */
extern int (*legal_vif_num)(int);
extern u_long (*ip_mcast_src)(int);
VNET_DECLARE(int, rsvp_on);
+VNET_DECLARE(int, drop_redirect);
extern struct pr_usrreqs rip_usrreqs;
#define V_ipstat VNET(ipstat)
@@ -199,6 +200,7 @@ extern struct pr_usrreqs rip_usrreqs;
#define V_ip_rsvpd VNET(ip_rsvpd)
#define V_ip_mrouter VNET(ip_mrouter)
#define V_rsvp_on VNET(rsvp_on)
+#define V_drop_redirect VNET(drop_redirect)
void inp_freemoptions(struct ip_moptions *);
int inp_getmoptions(struct inpcb *, struct sockopt *);
@@ -287,6 +289,7 @@ enum {
};
#define MTAG_IPFW 1148380143 /* IPFW-tagged cookie */
#define MTAG_IPFW_RULE 1262273568 /* rule reference */
+#define MTAG_IPFW_CALL 1308397630 /* call stack */
struct ip_fw_args;
typedef int (*ip_fw_chk_ptr_t)(struct ip_fw_args *args);
diff --git a/freebsd/sys/netinet/ipfw/ip_dn_glue.c b/freebsd/sys/netinet/ipfw/ip_dn_glue.c
index 8c8c3ef8..2b109771 100644
--- a/freebsd/sys/netinet/ipfw/ip_dn_glue.c
+++ b/freebsd/sys/netinet/ipfw/ip_dn_glue.c
@@ -626,7 +626,7 @@ dn_c_copy_pipe(struct dn_schk *s, struct copy_args *a, int nq)
/* These 4 field are the same in pipe7 and pipe8 */
pipe7->next.sle_next = (struct dn_pipe7 *)DN_IS_PIPE;
pipe7->bandwidth = l->bandwidth;
- pipe7->delay = l->delay;
+ pipe7->delay = l->delay * 1000 / hz;
pipe7->pipe_nr = l->link_nr - DN_MAX_ID;
if (!is7) {
@@ -809,7 +809,7 @@ ip_dummynet_compat(struct sockopt *sopt)
if (error)
break;
error = dn_compat_del(v);
- free(v, M_DUMMYNET);
+ free(v, M_TEMP);
break;
case IP_DUMMYNET_CONFIGURE:
@@ -818,7 +818,7 @@ ip_dummynet_compat(struct sockopt *sopt)
if (error)
break;
error = dn_compat_configure(v);
- free(v, M_DUMMYNET);
+ free(v, M_TEMP);
break;
case IP_DUMMYNET_GET: {
diff --git a/freebsd/sys/netinet/ipfw/ip_dn_io.c b/freebsd/sys/netinet/ipfw/ip_dn_io.c
index 72f0c354..ccb91c2e 100644
--- a/freebsd/sys/netinet/ipfw/ip_dn_io.c
+++ b/freebsd/sys/netinet/ipfw/ip_dn_io.c
@@ -47,8 +47,11 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <rtems/bsd/sys/time.h>
#include <sys/sysctl.h>
+
#include <net/if.h> /* IFNAMSIZ, struct ifaddr, ifq head, lock.h mutex.h */
#include <net/netisr.h>
+#include <net/vnet.h>
+
#include <netinet/in.h>
#include <netinet/ip.h> /* ip_len, ip_off */
#include <netinet/ip_var.h> /* ip_output(), IP_FORWARDING */
@@ -71,6 +74,7 @@ __FBSDID("$FreeBSD$");
*/
struct dn_parms dn_cfg;
+//VNET_DEFINE(struct dn_parms, _base_dn_cfg);
static long tick_last; /* Last tick duration (usec). */
static long tick_delta; /* Last vs standard tick diff (usec). */
@@ -102,31 +106,78 @@ SYSCTL_DECL(_net_inet);
SYSCTL_DECL(_net_inet_ip);
SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet, CTLFLAG_RW, 0, "Dummynet");
+/* wrapper to pass dn_cfg fields to SYSCTL_* */
+//#define DC(x) (&(VNET_NAME(_base_dn_cfg).x))
+#define DC(x) (&(dn_cfg.x))
/* parameters */
-SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, hash_size,
- CTLFLAG_RW, &dn_cfg.hash_size, 0, "Default hash table size");
-SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_slot_limit,
- CTLFLAG_RW, &dn_cfg.slot_limit, 0,
- "Upper limit in slots for pipe queue.");
-SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_byte_limit,
- CTLFLAG_RW, &dn_cfg.byte_limit, 0,
- "Upper limit in bytes for pipe queue.");
+
+static int
+sysctl_hash_size(SYSCTL_HANDLER_ARGS)
+{
+ int error, value;
+
+ value = dn_cfg.hash_size;
+ error = sysctl_handle_int(oidp, &value, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (value < 16 || value > 65536)
+ return (EINVAL);
+ dn_cfg.hash_size = value;
+ return (0);
+}
+
+SYSCTL_PROC(_net_inet_ip_dummynet, OID_AUTO, hash_size,
+ CTLTYPE_INT | CTLFLAG_RW, 0, 0, sysctl_hash_size,
+ "I", "Default hash table size");
+
+static int
+sysctl_limits(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ long value;
+
+ if (arg2 != 0)
+ value = dn_cfg.slot_limit;
+ else
+ value = dn_cfg.byte_limit;
+ error = sysctl_handle_long(oidp, &value, 0, req);
+
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (arg2 != 0) {
+ if (value < 1)
+ return (EINVAL);
+ dn_cfg.slot_limit = value;
+ } else {
+ if (value < 1500)
+ return (EINVAL);
+ dn_cfg.byte_limit = value;
+ }
+ return (0);
+}
+
+SYSCTL_PROC(_net_inet_ip_dummynet, OID_AUTO, pipe_slot_limit,
+ CTLTYPE_LONG | CTLFLAG_RW, 0, 1, sysctl_limits,
+ "L", "Upper limit in slots for pipe queue.");
+SYSCTL_PROC(_net_inet_ip_dummynet, OID_AUTO, pipe_byte_limit,
+ CTLTYPE_LONG | CTLFLAG_RW, 0, 0, sysctl_limits,
+ "L", "Upper limit in bytes for pipe queue.");
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, io_fast,
- CTLFLAG_RW, &dn_cfg.io_fast, 0, "Enable fast dummynet io.");
+ CTLFLAG_RW, DC(io_fast), 0, "Enable fast dummynet io.");
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, debug,
- CTLFLAG_RW, &dn_cfg.debug, 0, "Dummynet debug level");
-SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, expire,
- CTLFLAG_RW, &dn_cfg.expire, 0, "Expire empty queues/pipes");
-SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, expire_cycle,
- CTLFLAG_RD, &dn_cfg.expire_cycle, 0, "Expire cycle for queues/pipes");
+ CTLFLAG_RW, DC(debug), 0, "Dummynet debug level");
+SYSCTL_UINT(_net_inet_ip_dummynet, OID_AUTO, expire,
+ CTLFLAG_RW, DC(expire), 0, "Expire empty queues/pipes");
+SYSCTL_UINT(_net_inet_ip_dummynet, OID_AUTO, expire_cycle,
+ CTLFLAG_RD, DC(expire_cycle), 0, "Expire cycle for queues/pipes");
/* RED parameters */
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_lookup_depth,
- CTLFLAG_RD, &dn_cfg.red_lookup_depth, 0, "Depth of RED lookup table");
+ CTLFLAG_RD, DC(red_lookup_depth), 0, "Depth of RED lookup table");
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_avg_pkt_size,
- CTLFLAG_RD, &dn_cfg.red_avg_pkt_size, 0, "RED Medium packet size");
+ CTLFLAG_RD, DC(red_avg_pkt_size), 0, "RED Medium packet size");
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_max_pkt_size,
- CTLFLAG_RD, &dn_cfg.red_max_pkt_size, 0, "RED Max packet size");
+ CTLFLAG_RD, DC(red_max_pkt_size), 0, "RED Max packet size");
/* time adjustment */
SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, tick_delta,
@@ -144,13 +195,13 @@ SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, tick_lost,
/* statistics */
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, schk_count,
- CTLFLAG_RD, &dn_cfg.schk_count, 0, "Number of schedulers");
+ CTLFLAG_RD, DC(schk_count), 0, "Number of schedulers");
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, si_count,
- CTLFLAG_RD, &dn_cfg.si_count, 0, "Number of scheduler instances");
+ CTLFLAG_RD, DC(si_count), 0, "Number of scheduler instances");
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, fsk_count,
- CTLFLAG_RD, &dn_cfg.fsk_count, 0, "Number of flowsets");
+ CTLFLAG_RD, DC(fsk_count), 0, "Number of flowsets");
SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, queue_count,
- CTLFLAG_RD, &dn_cfg.queue_count, 0, "Number of queues");
+ CTLFLAG_RD, DC(queue_count), 0, "Number of queues");
SYSCTL_ULONG(_net_inet_ip_dummynet, OID_AUTO, io_pkt,
CTLFLAG_RD, &io_pkt, 0,
"Number of packets passed to dummynet.");
@@ -160,7 +211,7 @@ SYSCTL_ULONG(_net_inet_ip_dummynet, OID_AUTO, io_pkt_fast,
SYSCTL_ULONG(_net_inet_ip_dummynet, OID_AUTO, io_pkt_drop,
CTLFLAG_RD, &io_pkt_drop, 0,
"Number of packets dropped by dummynet.");
-
+#undef DC
SYSEND
#endif
@@ -463,7 +514,7 @@ serve_sched(struct mq *q, struct dn_sch_inst *si, uint64_t now)
(m->m_pkthdr.len * 8 + extra_bits(m, s));
si->credit -= len_scaled;
/* Move packet in the delay line */
- dn_tag_get(m)->output_time += s->link.delay ;
+ dn_tag_get(m)->output_time = dn_cfg.curr_time + s->link.delay ;
mq_append(&si->dline.mq, m);
}
/*
@@ -498,6 +549,8 @@ dummynet_task(void *context, int pending)
struct timeval t;
struct mq q = { NULL, NULL }; /* queue to accumulate results */
+ CURVNET_SET((struct vnet *)context);
+
DN_BH_WLOCK();
/* Update number of lost(coalesced) ticks. */
@@ -562,6 +615,7 @@ dummynet_task(void *context, int pending)
dn_reschedule();
if (q.head != NULL)
dummynet_send(q.head);
+ CURVNET_RESTORE();
}
/*
@@ -612,7 +666,6 @@ dummynet_send(struct mbuf *m)
break;
case DIR_OUT | PROTO_IPV6:
- SET_HOST_IPLEN(mtod(m, struct ip *));
ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL);
break;
#endif
diff --git a/freebsd/sys/netinet/ipfw/ip_dn_private.h b/freebsd/sys/netinet/ipfw/ip_dn_private.h
index 270f1881..7b0088d9 100644
--- a/freebsd/sys/netinet/ipfw/ip_dn_private.h
+++ b/freebsd/sys/netinet/ipfw/ip_dn_private.h
@@ -150,6 +150,8 @@ struct dn_parms {
uint32_t expire;
uint32_t expire_cycle; /* tick count */
+ int init_done;
+
/* if the upper half is busy doing something long,
* can set the busy flag and we will enqueue packets in
* a queue for later processing.
@@ -354,6 +356,8 @@ enum {
};
extern struct dn_parms dn_cfg;
+//VNET_DECLARE(struct dn_parms, _base_dn_cfg);
+//#define dn_cfg VNET(_base_dn_cfg)
int dummynet_io(struct mbuf **, int , struct ip_fw_args *);
void dummynet_task(void *context, int pending);
diff --git a/freebsd/sys/netinet/ipfw/ip_dummynet.c b/freebsd/sys/netinet/ipfw/ip_dummynet.c
index 5d51c30b..89e5f4db 100644
--- a/freebsd/sys/netinet/ipfw/ip_dummynet.c
+++ b/freebsd/sys/netinet/ipfw/ip_dummynet.c
@@ -99,7 +99,7 @@ find_sched_type(int type, char *name)
struct dn_alg *d;
SLIST_FOREACH(d, &dn_cfg.schedlist, next) {
- if (d->type == type || (name && !strcmp(d->name, name)))
+ if (d->type == type || (name && !strcasecmp(d->name, name)))
return d;
}
return NULL; /* not found */
@@ -110,6 +110,10 @@ ipdn_bound_var(int *v, int dflt, int lo, int hi, const char *msg)
{
int oldv = *v;
const char *op = NULL;
+ if (dflt < lo)
+ dflt = lo;
+ if (dflt > hi)
+ dflt = hi;
if (oldv < lo) {
*v = dflt;
op = "Bump";
@@ -749,9 +753,10 @@ schk_delete_cb(void *obj, void *arg)
#endif
fsk_detach_list(&s->fsk_list, arg ? DN_DESTROY : 0);
/* no more flowset pointing to us now */
- if (s->sch.flags & DN_HAVE_MASK)
+ if (s->sch.flags & DN_HAVE_MASK) {
dn_ht_scan(s->siht, si_destroy, NULL);
- else if (s->siht)
+ dn_ht_free(s->siht, 0);
+ } else if (s->siht)
si_destroy(s->siht, NULL);
if (s->profile) {
free(s->profile, M_DUMMYNET);
@@ -804,6 +809,7 @@ copy_obj(char **start, char *end, void *_o, const char *msg, int i)
/* Adjust burst parameter for link */
struct dn_link *l = (struct dn_link *)*start;
l->burst = div64(l->burst, 8 * hz);
+ l->delay = l->delay * 1000 / hz;
} else if (o->type == DN_SCH) {
/* Set id->id to the number of instances */
struct dn_schk *s = _o;
@@ -1040,7 +1046,7 @@ config_red(struct dn_fsk *fs)
fs->w_q = fs->fs.w_q;
fs->max_p = fs->fs.max_p;
- D("called");
+ ND("called");
/* Doing stuff that was in userland */
i = fs->sched->link.bandwidth;
s = (i <= 0) ? 0 :
@@ -1104,7 +1110,7 @@ config_red(struct dn_fsk *fs)
if (dn_cfg.red_max_pkt_size < 1)
dn_cfg.red_max_pkt_size = 1500;
fs->max_pkt_size = dn_cfg.red_max_pkt_size;
- D("exit");
+ ND("exit");
return 0;
}
@@ -1834,9 +1840,7 @@ dummynet_get(struct sockopt *sopt, void **compat)
#endif
if (l > sizeof(r)) {
/* request larger than default, allocate buffer */
- cmd = malloc(l, M_DUMMYNET, M_WAIT);
- if (cmd == NULL)
- return ENOMEM; //XXX
+ cmd = malloc(l, M_DUMMYNET, M_WAITOK);
error = sooptcopyin(sopt, cmd, l, l);
sopt->sopt_valsize = sopt_valsize;
if (error)
@@ -1892,10 +1896,6 @@ dummynet_get(struct sockopt *sopt, void **compat)
have = need;
start = malloc(have, M_DUMMYNET, M_WAITOK | M_ZERO);
- if (start == NULL) {
- error = ENOMEM;
- goto done;
- }
}
if (start == NULL) {
@@ -2114,14 +2114,10 @@ ip_dn_ctl(struct sockopt *sopt)
static void
ip_dn_init(void)
{
- static int init_done = 0;
-
- if (init_done)
+ if (dn_cfg.init_done)
return;
- init_done = 1;
- if (bootverbose)
- printf("DUMMYNET with IPv6 initialized (100131)\n");
-
+ printf("DUMMYNET %p with IPv6 initialized (100409)\n", curvnet);
+ dn_cfg.init_done = 1;
/* Set defaults here. MSVC does not accept initializers,
* and this is also useful for vimages
*/
@@ -2136,7 +2132,7 @@ ip_dn_init(void)
dn_cfg.red_max_pkt_size = 1500; /* default max packet size */
/* hash tables */
- dn_cfg.max_hash_size = 1024; /* max in the hash tables */
+ dn_cfg.max_hash_size = 65536; /* max in the hash tables */
dn_cfg.hash_size = 64; /* default hash size */
/* create hash tables for schedulers and flowsets.
@@ -2158,10 +2154,8 @@ ip_dn_init(void)
SLIST_INIT(&dn_cfg.schedlist);
DN_LOCK_INIT();
- ip_dn_ctl_ptr = ip_dn_ctl;
- ip_dn_io_ptr = dummynet_io;
- TASK_INIT(&dn_task, 0, dummynet_task, NULL);
+ TASK_INIT(&dn_task, 0, dummynet_task, curvnet);
dn_tq = taskqueue_create_fast("dummynet", M_NOWAIT,
taskqueue_thread_enqueue, &dn_tq);
taskqueue_start_threads(&dn_tq, 1, PI_NET, "dummynet");
@@ -2175,13 +2169,16 @@ ip_dn_init(void)
#ifdef KLD_MODULE
static void
-ip_dn_destroy(void)
+ip_dn_destroy(int last)
{
callout_drain(&dn_timeout);
DN_BH_WLOCK();
- ip_dn_ctl_ptr = NULL;
- ip_dn_io_ptr = NULL;
+ if (last) {
+ ND("removing last instance\n");
+ ip_dn_ctl_ptr = NULL;
+ ip_dn_io_ptr = NULL;
+ }
dummynet_flush();
DN_BH_WUNLOCK();
@@ -2206,13 +2203,15 @@ dummynet_modevent(module_t mod, int type, void *data)
return EEXIST ;
}
ip_dn_init();
+ ip_dn_ctl_ptr = ip_dn_ctl;
+ ip_dn_io_ptr = dummynet_io;
return 0;
} else if (type == MOD_UNLOAD) {
#if !defined(KLD_MODULE)
printf("dummynet statically compiled, cannot unload\n");
return EINVAL ;
#else
- ip_dn_destroy();
+ ip_dn_destroy(1 /* last */);
return 0;
#endif
} else
@@ -2256,13 +2255,13 @@ unload_dn_sched(struct dn_alg *s)
struct dn_alg *tmp, *r;
int err = EINVAL;
- D("called for %s", s->name);
+ ND("called for %s", s->name);
DN_BH_WLOCK();
SLIST_FOREACH_SAFE(r, &dn_cfg.schedlist, next, tmp) {
if (strcmp(s->name, r->name) != 0)
continue;
- D("ref_count = %d", r->ref_count);
+ ND("ref_count = %d", r->ref_count);
err = (r->ref_count != 0) ? EBUSY : 0;
if (err == 0)
SLIST_REMOVE(&dn_cfg.schedlist, r, dn_alg, next);
@@ -2290,8 +2289,24 @@ static moduledata_t dummynet_mod = {
"dummynet", dummynet_modevent, NULL
};
-DECLARE_MODULE(dummynet, dummynet_mod,
- SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY-1);
+#define DN_SI_SUB SI_SUB_PROTO_IFATTACHDOMAIN
+#define DN_MODEV_ORD (SI_ORDER_ANY - 128) /* after ipfw */
+DECLARE_MODULE(dummynet, dummynet_mod, DN_SI_SUB, DN_MODEV_ORD);
MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
-MODULE_VERSION(dummynet, 1);
+MODULE_VERSION(dummynet, 3);
+
+/*
+ * Starting up. Done in order after dummynet_modevent() has been called.
+ * VNET_SYSINIT is also called for each existing vnet and each new vnet.
+ */
+//VNET_SYSINIT(vnet_dn_init, DN_SI_SUB, DN_MODEV_ORD+2, ip_dn_init, NULL);
+
+/*
+ * Shutdown handlers up shop. These are done in REVERSE ORDER, but still
+ * after dummynet_modevent() has been called. Not called on reboot.
+ * VNET_SYSUNINIT is also called for each exiting vnet as it exits.
+ * or when the module is unloaded.
+ */
+//VNET_SYSUNINIT(vnet_dn_uninit, DN_SI_SUB, DN_MODEV_ORD+2, ip_dn_destroy, NULL);
+
/* end of file */
diff --git a/freebsd/sys/netinet/ipfw/ip_fw2.c b/freebsd/sys/netinet/ipfw/ip_fw2.c
index 4328c50e..44781127 100644
--- a/freebsd/sys/netinet/ipfw/ip_fw2.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw2.c
@@ -32,15 +32,12 @@ __FBSDID("$FreeBSD$");
* The FreeBSD IP packet firewall, main file
*/
-#if !defined(KLD_MODULE)
#include <rtems/bsd/local/opt_ipfw.h>
#include <rtems/bsd/local/opt_ipdivert.h>
-#include <rtems/bsd/local/opt_ipdn.h>
#include <rtems/bsd/local/opt_inet.h>
#ifndef INET
#error IPFIREWALL requires INET.
#endif /* INET */
-#endif
#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/local/opt_ipsec.h>
@@ -108,6 +105,9 @@ static VNET_DEFINE(int, ipfw_vnet_ready) = 0;
static VNET_DEFINE(int, fw_deny_unknown_exthdrs);
#define V_fw_deny_unknown_exthdrs VNET(fw_deny_unknown_exthdrs)
+static VNET_DEFINE(int, fw_permit_single_frag6) = 1;
+#define V_fw_permit_single_frag6 VNET(fw_permit_single_frag6)
+
#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
static int default_to_accept = 1;
#else
@@ -116,6 +116,10 @@ static int default_to_accept;
VNET_DEFINE(int, autoinc_step);
+VNET_DEFINE(unsigned int, fw_tables_max);
+/* Use 128 tables by default */
+static unsigned int default_fw_tables = IPFW_TABLES_DEFAULT;
+
/*
* Each rule belongs to one of 32 different sets (0..31).
* The variable set_disable contains one bit per set.
@@ -145,7 +149,7 @@ ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
#ifdef SYSCTL_NODE
uint32_t dummy_def = IPFW_DEFAULT_RULE;
-uint32_t dummy_tables_max = IPFW_TABLES_MAX;
+static int sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS);
SYSBEGIN(f3)
@@ -165,13 +169,14 @@ SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
&dummy_def, 0,
"The default/max possible rule number.");
-SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
- &dummy_tables_max, 0,
- "The maximum number of tables.");
+SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, tables_max,
+ CTLTYPE_UINT|CTLFLAG_RW, 0, 0, sysctl_ipfw_table_num, "IU",
+ "Maximum number of tables");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
&default_to_accept, 0,
"Make the default rule accept all packets.");
TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept);
+TUNABLE_INT("net.inet.ip.fw.tables_max", &default_fw_tables);
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count,
CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0,
"Number of static rules");
@@ -182,6 +187,9 @@ SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,
CTLFLAG_RW | CTLFLAG_SECURE, &VNET_NAME(fw_deny_unknown_exthdrs), 0,
"Deny packets with unknown IPv6 Extension Headers");
+SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, permit_single_frag6,
+ CTLFLAG_RW | CTLFLAG_SECURE, &VNET_NAME(fw_permit_single_frag6), 0,
+ "Permit single packet IPv6 fragments");
#endif /* INET6 */
SYSEND
@@ -338,12 +346,15 @@ tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
}
static int
-iface_match(struct ifnet *ifp, ipfw_insn_if *cmd)
+iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain, uint32_t *tablearg)
{
if (ifp == NULL) /* no iface with this packet, match fails */
return 0;
/* Check by name or by IP address */
if (cmd->name[0] != '\0') { /* match by name */
+ if (cmd->name[0] == '\1') /* use tablearg to match */
+ return ipfw_lookup_table_extended(chain, cmd->p.glob,
+ ifp->if_xname, tablearg, IPFW_TABLE_INTERFACE);
/* Check name */
if (cmd->p.glob) {
if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
@@ -493,7 +504,7 @@ search_ip6_addr_net (struct in6_addr * ip6_addr)
}
static int
-verify_path6(struct in6_addr *src, struct ifnet *ifp)
+verify_path6(struct in6_addr *src, struct ifnet *ifp, u_int fib)
{
struct route_in6 ro;
struct sockaddr_in6 *dst;
@@ -504,9 +515,8 @@ verify_path6(struct in6_addr *src, struct ifnet *ifp)
dst->sin6_family = AF_INET6;
dst->sin6_len = sizeof(*dst);
dst->sin6_addr = *src;
- /* XXX MRT 0 for ipv6 at this time */
- rtalloc_ign((struct route *)&ro, 0);
+ in6_rtalloc_ign(&ro, 0, fib);
if (ro.ro_rt == NULL)
return 0;
@@ -851,13 +861,14 @@ ipfw_chk(struct ip_fw_args *args)
* we have a fragment at this offset of an IPv4 packet.
* offset == 0 means that (if this is an IPv4 packet)
* this is the first or only fragment.
- * For IPv6 offset == 0 means there is no Fragment Header.
- * If offset != 0 for IPv6 always use correct mask to
- * get the correct offset because we add IP6F_MORE_FRAG
- * to be able to dectect the first fragment which would
- * otherwise have offset = 0.
+ * For IPv6 offset|ip6f_mf == 0 means there is no Fragment Header
+ * or there is a single packet fragement (fragement header added
+ * without needed). We will treat a single packet fragment as if
+ * there was no fragment header (or log/block depending on the
+ * V_fw_permit_single_frag6 sysctl setting).
*/
u_short offset = 0;
+ u_short ip6f_mf = 0;
/*
* Local copies of addresses. They are only valid if we have
@@ -923,9 +934,10 @@ ipfw_chk(struct ip_fw_args *args)
* pointer might become stale after other pullups (but we never use it
* this way).
*/
-#define PULLUP_TO(_len, p, T) \
+#define PULLUP_TO(_len, p, T) PULLUP_LEN(_len, p, sizeof(T))
+#define PULLUP_LEN(_len, p, T) \
do { \
- int x = (_len) + sizeof(T); \
+ int x = (_len) + T; \
if ((m)->m_len < x) { \
args->m = m = m_pullup(m, x); \
if (m == NULL) \
@@ -950,7 +962,7 @@ do { \
proto = ip6->ip6_nxt;
/* Search extension headers to find upper layer protocols */
- while (ulp == NULL) {
+ while (ulp == NULL && offset == 0) {
switch (proto) {
case IPPROTO_ICMPV6:
PULLUP_TO(hlen, ulp, struct icmp6_hdr);
@@ -995,9 +1007,11 @@ do { \
ext_hd |= EXT_RTHDR2;
break;
default:
- printf("IPFW2: IPV6 - Unknown Routing "
- "Header type(%d)\n",
- ((struct ip6_rthdr *)ulp)->ip6r_type);
+ if (V_fw_verbose)
+ printf("IPFW2: IPV6 - Unknown "
+ "Routing Header type(%d)\n",
+ ((struct ip6_rthdr *)
+ ulp)->ip6r_type);
if (V_fw_deny_unknown_exthdrs)
return (IP_FW_DENY);
break;
@@ -1015,13 +1029,13 @@ do { \
proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
IP6F_OFF_MASK;
- /* Add IP6F_MORE_FRAG for offset of first
- * fragment to be != 0. */
- offset |= ((struct ip6_frag *)ulp)->ip6f_offlg &
+ ip6f_mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
IP6F_MORE_FRAG;
- if (offset == 0) {
- printf("IPFW2: IPV6 - Invalid Fragment "
- "Header\n");
+ if (V_fw_permit_single_frag6 == 0 &&
+ offset == 0 && ip6f_mf == 0) {
+ if (V_fw_verbose)
+ printf("IPFW2: IPV6 - Invalid "
+ "Fragment Header\n");
if (V_fw_deny_unknown_exthdrs)
return (IP_FW_DENY);
break;
@@ -1092,8 +1106,10 @@ do { \
break;
default:
- printf("IPFW2: IPV6 - Unknown Extension "
- "Header(%d), ext_hd=%x\n", proto, ext_hd);
+ if (V_fw_verbose)
+ printf("IPFW2: IPV6 - Unknown "
+ "Extension Header(%d), ext_hd=%x\n",
+ proto, ext_hd);
if (V_fw_deny_unknown_exthdrs)
return (IP_FW_DENY);
PULLUP_TO(hlen, ulp, struct ip6_ext);
@@ -1133,6 +1149,12 @@ do { \
args->f_id._flags = TCP(ulp)->th_flags;
break;
+ case IPPROTO_SCTP:
+ PULLUP_TO(hlen, ulp, struct sctphdr);
+ src_port = SCTP(ulp)->src_port;
+ dst_port = SCTP(ulp)->dest_port;
+ break;
+
case IPPROTO_UDP:
PULLUP_TO(hlen, ulp, struct udphdr);
dst_port = UDP(ulp)->uh_dport;
@@ -1282,16 +1304,18 @@ do { \
case O_RECV:
match = iface_match(m->m_pkthdr.rcvif,
- (ipfw_insn_if *)cmd);
+ (ipfw_insn_if *)cmd, chain, &tablearg);
break;
case O_XMIT:
- match = iface_match(oif, (ipfw_insn_if *)cmd);
+ match = iface_match(oif, (ipfw_insn_if *)cmd,
+ chain, &tablearg);
break;
case O_VIA:
match = iface_match(oif ? oif :
- m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd);
+ m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd,
+ chain, &tablearg);
break;
case O_MACADDR2:
@@ -1429,6 +1453,17 @@ do { \
((ipfw_insn_u32 *)cmd)->d[0] == v;
else
tablearg = v;
+ } else if (is_ipv6) {
+ uint32_t v = 0;
+ void *pkey = (cmd->opcode == O_IP_DST_LOOKUP) ?
+ &args->f_id.dst_ip6: &args->f_id.src_ip6;
+ match = ipfw_lookup_table_extended(chain,
+ cmd->arg1, pkey, &v,
+ IPFW_TABLE_CIDR);
+ if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
+ match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
+ if (match)
+ tablearg = v;
}
break;
@@ -1612,6 +1647,7 @@ do { \
break;
case O_TCPOPTS:
+ PULLUP_LEN(hlen, ulp, (TCP(ulp)->th_off << 2));
match = (proto == IPPROTO_TCP && offset == 0 &&
tcpopts_match(TCP(ulp), cmd));
break;
@@ -1668,7 +1704,7 @@ do { \
case O_LOG:
ipfw_log(f, hlen, args, m,
- oif, offset, tablearg, ip);
+ oif, offset | ip6f_mf, tablearg, ip);
match = 1;
break;
@@ -1684,7 +1720,7 @@ do { \
#ifdef INET6
is_ipv6 ?
verify_path6(&(args->f_id.src_ip6),
- m->m_pkthdr.rcvif) :
+ m->m_pkthdr.rcvif, args->f_id.fib) :
#endif
verify_path(src_ip, m->m_pkthdr.rcvif,
args->f_id.fib)));
@@ -1696,7 +1732,7 @@ do { \
#ifdef INET6
is_ipv6 ?
verify_path6(&(args->f_id.src_ip6),
- NULL) :
+ NULL, args->f_id.fib) :
#endif
verify_path(src_ip, NULL, args->f_id.fib)));
break;
@@ -1714,7 +1750,8 @@ do { \
#ifdef INET6
is_ipv6 ? verify_path6(
&(args->f_id.src_ip6),
- m->m_pkthdr.rcvif) :
+ m->m_pkthdr.rcvif,
+ args->f_id.fib) :
#endif
verify_path(src_ip,
m->m_pkthdr.rcvif,
@@ -1805,10 +1842,13 @@ do { \
if (mtag != NULL)
m_tag_delete(m, mtag);
match = 0;
- } else if (mtag == NULL) {
- if ((mtag = m_tag_alloc(MTAG_IPFW,
- tag, 0, M_NOWAIT)) != NULL)
- m_tag_prepend(m, mtag);
+ } else {
+ if (mtag == NULL) {
+ mtag = m_tag_alloc( MTAG_IPFW,
+ tag, 0, M_NOWAIT);
+ if (mtag != NULL)
+ m_tag_prepend(m, mtag);
+ }
match = 1;
}
break;
@@ -2040,6 +2080,123 @@ do { \
continue;
break; /* not reached */
+ case O_CALLRETURN: {
+ /*
+ * Implementation of `subroutine' call/return,
+ * in the stack carried in an mbuf tag. This
+ * is different from `skipto' in that any call
+ * address is possible (`skipto' must prevent
+ * backward jumps to avoid endless loops).
+ * We have `return' action when F_NOT flag is
+ * present. The `m_tag_id' field is used as
+ * stack pointer.
+ */
+ struct m_tag *mtag;
+ uint16_t jmpto, *stack;
+
+#define IS_CALL ((cmd->len & F_NOT) == 0)
+#define IS_RETURN ((cmd->len & F_NOT) != 0)
+ /*
+ * Hand-rolled version of m_tag_locate() with
+ * wildcard `type'.
+ * If not already tagged, allocate new tag.
+ */
+ mtag = m_tag_first(m);
+ while (mtag != NULL) {
+ if (mtag->m_tag_cookie ==
+ MTAG_IPFW_CALL)
+ break;
+ mtag = m_tag_next(m, mtag);
+ }
+ if (mtag == NULL && IS_CALL) {
+ mtag = m_tag_alloc(MTAG_IPFW_CALL, 0,
+ IPFW_CALLSTACK_SIZE *
+ sizeof(uint16_t), M_NOWAIT);
+ if (mtag != NULL)
+ m_tag_prepend(m, mtag);
+ }
+
+ /*
+ * On error both `call' and `return' just
+ * continue with next rule.
+ */
+ if (IS_RETURN && (mtag == NULL ||
+ mtag->m_tag_id == 0)) {
+ l = 0; /* exit inner loop */
+ break;
+ }
+ if (IS_CALL && (mtag == NULL ||
+ mtag->m_tag_id >= IPFW_CALLSTACK_SIZE)) {
+ printf("ipfw: call stack error, "
+ "go to next rule\n");
+ l = 0; /* exit inner loop */
+ break;
+ }
+
+ f->pcnt++; /* update stats */
+ f->bcnt += pktlen;
+ f->timestamp = time_uptime;
+ stack = (uint16_t *)(mtag + 1);
+
+ /*
+ * The `call' action may use cached f_pos
+ * (in f->next_rule), whose version is written
+ * in f->next_rule.
+ * The `return' action, however, doesn't have
+ * fixed jump address in cmd->arg1 and can't use
+ * cache.
+ */
+ if (IS_CALL) {
+ stack[mtag->m_tag_id] = f->rulenum;
+ mtag->m_tag_id++;
+ if (cmd->arg1 != IP_FW_TABLEARG &&
+ (uintptr_t)f->x_next == chain->id) {
+ f_pos = (uintptr_t)f->next_rule;
+ } else {
+ jmpto = (cmd->arg1 ==
+ IP_FW_TABLEARG) ? tablearg:
+ cmd->arg1;
+ f_pos = ipfw_find_rule(chain,
+ jmpto, 0);
+ /* update the cache */
+ if (cmd->arg1 !=
+ IP_FW_TABLEARG) {
+ f->next_rule =
+ (void *)(uintptr_t)
+ f_pos;
+ f->x_next =
+ (void *)(uintptr_t)
+ chain->id;
+ }
+ }
+ } else { /* `return' action */
+ mtag->m_tag_id--;
+ jmpto = stack[mtag->m_tag_id] + 1;
+ f_pos = ipfw_find_rule(chain, jmpto, 0);
+ }
+
+ /*
+ * Skip disabled rules, and re-enter
+ * the inner loop with the correct
+ * f_pos, f, l and cmd.
+ * Also clear cmdlen and skip_or
+ */
+ for (; f_pos < chain->n_rules - 1 &&
+ (V_set_disable &
+ (1 << chain->map[f_pos]->set)); f_pos++)
+ ;
+ /* Re-enter the inner loop at the dest rule. */
+ f = chain->map[f_pos];
+ l = f->cmd_len;
+ cmd = f->cmd;
+ cmdlen = 0;
+ skip_or = 0;
+ continue;
+ break; /* NOTREACHED */
+ }
+#undef IS_CALL
+#undef IS_RETURN
+
case O_REJECT:
/*
* Drop the packet and send a reject notice
@@ -2079,7 +2236,8 @@ do { \
case O_FORWARD_IP:
if (args->eh) /* not valid on layer2 pkts */
break;
- if (!q || dyn_dir == MATCH_FORWARD) {
+ if (q == NULL || q->rule != f ||
+ dyn_dir == MATCH_FORWARD) {
struct sockaddr_in *sa;
sa = &(((ipfw_insn_sa *)cmd)->sa);
if (sa->sin_addr.s_addr == INADDR_ANY) {
@@ -2110,14 +2268,21 @@ do { \
done = 1; /* exit outer loop */
break;
- case O_SETFIB:
+ case O_SETFIB: {
+ uint32_t fib;
+
f->pcnt++; /* update stats */
f->bcnt += pktlen;
f->timestamp = time_uptime;
- M_SETFIB(m, cmd->arg1);
- args->f_id.fib = cmd->arg1;
+ fib = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg:
+ cmd->arg1;
+ if (fib >= rt_numfibs)
+ fib = 0;
+ M_SETFIB(m, fib);
+ args->f_id.fib = fib;
l = 0; /* exit inner loop */
break;
+ }
case O_NAT:
if (!IPFW_NAT_LOADED) {
@@ -2127,6 +2292,13 @@ do { \
int nat_id;
set_match(args, f_pos, chain);
+ /* Check if this is 'global' nat rule */
+ if (cmd->arg1 == 0) {
+ retval = ipfw_nat_ptr(args, NULL, m);
+ l = 0;
+ done = 1;
+ break;
+ }
t = ((ipfw_insn_nat *)cmd)->nat;
if (t == NULL) {
nat_id = (cmd->arg1 == IP_FW_TABLEARG) ?
@@ -2209,6 +2381,7 @@ do { \
}
} /* end of inner loop, scan opcodes */
+#undef PULLUP_LEN
if (done)
break;
@@ -2241,6 +2414,26 @@ pullup_failed:
}
/*
+ * Set maximum number of tables that can be used in given VNET ipfw instance.
+ */
+#ifdef SYSCTL_NODE
+static int
+sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ unsigned int ntables;
+
+ ntables = V_fw_tables_max;
+
+ error = sysctl_handle_int(oidp, &ntables, 0, req);
+ /* Read operation or some error */
+ if ((error != 0) || (req->newptr == NULL))
+ return (error);
+
+ return (ipfw_resize_tables(&V_layer3_chain, ntables));
+}
+#endif
+/*
* Module and VNET glue
*/
@@ -2296,6 +2489,10 @@ ipfw_init(void)
printf("limited to %d packets/entry by default\n",
V_verbose_limit);
+ /* Check user-supplied table count for validness */
+ if (default_fw_tables > IPFW_TABLES_MAX)
+ default_fw_tables = IPFW_TABLES_MAX;
+
ipfw_log_bpf(1); /* init */
return (error);
}
@@ -2341,19 +2538,18 @@ vnet_ipfw_init(const void *unused)
/* insert the default rule and create the initial map */
chain->n_rules = 1;
chain->static_len = sizeof(struct ip_fw);
- chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_NOWAIT | M_ZERO);
+ chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO);
if (chain->map)
- rule = malloc(chain->static_len, M_IPFW, M_NOWAIT | M_ZERO);
- if (rule == NULL) {
- if (chain->map)
- free(chain->map, M_IPFW);
- printf("ipfw2: ENOSPC initializing default rule "
- "(support disabled)\n");
- return (ENOSPC);
- }
+ rule = malloc(chain->static_len, M_IPFW, M_WAITOK | M_ZERO);
+
+ /* Set initial number of tables */
+ V_fw_tables_max = default_fw_tables;
error = ipfw_init_tables(chain);
if (error) {
- panic("init_tables"); /* XXX Marko fix this ! */
+ printf("ipfw2: setting up tables failed\n");
+ free(chain->map, M_IPFW);
+ free(rule, M_IPFW);
+ return (ENOSPC);
}
/* fill and insert the default rule */
@@ -2416,12 +2612,12 @@ vnet_ipfw_uninit(const void *unused)
IPFW_UH_WLOCK(chain);
IPFW_WLOCK(chain);
+ ipfw_dyn_uninit(0); /* run the callout_drain */
IPFW_WUNLOCK(chain);
- IPFW_WLOCK(chain);
- ipfw_dyn_uninit(0); /* run the callout_drain */
ipfw_destroy_tables(chain);
reap = NULL;
+ IPFW_WLOCK(chain);
for (i = 0; i < chain->n_rules; i++) {
rule = chain->map[i];
rule->x_next = reap;
diff --git a/freebsd/sys/netinet/ipfw/ip_fw_log.c b/freebsd/sys/netinet/ipfw/ip_fw_log.c
index b529b9e1..773c698e 100644
--- a/freebsd/sys/netinet/ipfw/ip_fw_log.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_log.c
@@ -32,17 +32,12 @@ __FBSDID("$FreeBSD$");
* Logging support for ipfw
*/
-#if !defined(KLD_MODULE)
#include <rtems/bsd/local/opt_ipfw.h>
-#include <rtems/bsd/local/opt_ipdivert.h>
-#include <rtems/bsd/local/opt_ipdn.h>
#include <rtems/bsd/local/opt_inet.h>
#ifndef INET
#error IPFIREWALL requires INET.
#endif /* INET */
-#endif
#include <rtems/bsd/local/opt_inet6.h>
-#include <rtems/bsd/local/opt_ipsec.h>
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
@@ -306,6 +301,13 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
case O_REASS:
action = "Reass";
break;
+ case O_CALLRETURN:
+ if (cmd->len & F_NOT)
+ action = "Return";
+ else
+ snprintf(SNPARGS(action2, 0), "Call %d",
+ cmd->arg1);
+ break;
default:
action = "UNKNOWN";
break;
@@ -328,10 +330,14 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
struct icmp6_hdr *icmp6;
+ u_short ip6f_mf;
#endif
src[0] = '\0';
dst[0] = '\0';
#ifdef INET6
+ ip6f_mf = offset & IP6F_MORE_FRAG;
+ offset &= IP6F_OFF_MASK;
+
if (IS_IP6_FLOW_ID(&(args->f_id))) {
char ip6buf[INET6_ADDRSTRLEN];
snprintf(src, sizeof(src), "[%s]",
@@ -413,8 +419,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
" (frag %08x:%d@%d%s)",
args->f_id.extra,
ntohs(ip6->ip6_plen) - hlen,
- ntohs(offset & IP6F_OFF_MASK) << 3,
- (offset & IP6F_MORE_FRAG) ? "+" : "");
+ ntohs(offset) << 3, ip6f_mf ? "+" : "");
} else
#endif
{
diff --git a/freebsd/sys/netinet/ipfw/ip_fw_nat.c b/freebsd/sys/netinet/ipfw/ip_fw_nat.c
index dd47dedc..294b185e 100644
--- a/freebsd/sys/netinet/ipfw/ip_fw_nat.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_nat.c
@@ -140,7 +140,7 @@ del_redir_spool_cfg(struct cfg_nat *n, struct redir_chain *head)
}
}
-static int
+static void
add_redir_spool_cfg(char *buf, struct cfg_nat *ptr)
{
struct cfg_redir *r, *ser_r;
@@ -201,7 +201,6 @@ add_redir_spool_cfg(char *buf, struct cfg_nat *ptr)
/* And finally hook this redir entry. */
LIST_INSERT_HEAD(&ptr->redir_chain, r, _next);
}
- return (1);
}
static int
@@ -210,7 +209,8 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
struct mbuf *mcl;
struct ip *ip;
/* XXX - libalias duct tape */
- int ldt, retval;
+ int ldt, retval, found;
+ struct ip_fw_chain *chain;
char *c;
ldt = 0;
@@ -259,23 +259,65 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
ldt = 1;
c = mtod(mcl, char *);
- if (args->oif == NULL)
- retval = LibAliasIn(t->lib, c,
- mcl->m_len + M_TRAILINGSPACE(mcl));
- else
- retval = LibAliasOut(t->lib, c,
- mcl->m_len + M_TRAILINGSPACE(mcl));
- if (retval == PKT_ALIAS_RESPOND) {
- m->m_flags |= M_SKIP_FIREWALL;
- retval = PKT_ALIAS_OK;
+
+ /* Check if this is 'global' instance */
+ if (t == NULL) {
+ if (args->oif == NULL) {
+ /* Wrong direction, skip processing */
+ args->m = mcl;
+ return (IP_FW_NAT);
+ }
+
+ found = 0;
+ chain = &V_layer3_chain;
+ IPFW_RLOCK(chain);
+ /* Check every nat entry... */
+ LIST_FOREACH(t, &chain->nat, _next) {
+ if ((t->mode & PKT_ALIAS_SKIP_GLOBAL) != 0)
+ continue;
+ retval = LibAliasOutTry(t->lib, c,
+ mcl->m_len + M_TRAILINGSPACE(mcl), 0);
+ if (retval == PKT_ALIAS_OK) {
+ /* Nat instance recognises state */
+ found = 1;
+ break;
+ }
+ }
+ IPFW_RUNLOCK(chain);
+ if (found != 1) {
+ /* No instance found, return ignore */
+ args->m = mcl;
+ return (IP_FW_NAT);
+ }
+ } else {
+ if (args->oif == NULL)
+ retval = LibAliasIn(t->lib, c,
+ mcl->m_len + M_TRAILINGSPACE(mcl));
+ else
+ retval = LibAliasOut(t->lib, c,
+ mcl->m_len + M_TRAILINGSPACE(mcl));
}
- if (retval != PKT_ALIAS_OK &&
- retval != PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
+
+ /*
+ * We drop packet when:
+ * 1. libalias returns PKT_ALIAS_ERROR;
+ * 2. For incoming packets:
+ * a) for unresolved fragments;
+ * b) libalias returns PKT_ALIAS_IGNORED and
+ * PKT_ALIAS_DENY_INCOMING flag is set.
+ */
+ if (retval == PKT_ALIAS_ERROR ||
+ (args->oif == NULL && (retval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
+ (retval == PKT_ALIAS_IGNORED &&
+ (t->mode & PKT_ALIAS_DENY_INCOMING) != 0)))) {
/* XXX - should i add some logging? */
m_free(mcl);
args->m = NULL;
return (IP_FW_DENY);
}
+
+ if (retval == PKT_ALIAS_RESPOND)
+ mcl->m_flags |= M_SKIP_FIREWALL;
mcl->m_pkthdr.len = mcl->m_len = ntohs(ip->ip_len);
/*
@@ -346,59 +388,57 @@ lookup_nat(struct nat_list *l, int nat_id)
static int
ipfw_nat_cfg(struct sockopt *sopt)
{
- struct cfg_nat *ptr, *ser_n;
+ struct cfg_nat *cfg, *ptr;
char *buf;
struct ip_fw_chain *chain = &V_layer3_chain;
+ size_t len;
+ int gencnt, error = 0;
+
+ len = sopt->sopt_valsize;
+ buf = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
+ if ((error = sooptcopyin(sopt, buf, len, sizeof(struct cfg_nat))) != 0)
+ goto out;
+
+ cfg = (struct cfg_nat *)buf;
+ if (cfg->id < 0) {
+ error = EINVAL;
+ goto out;
+ }
- buf = malloc(NAT_BUF_LEN, M_IPFW, M_WAITOK | M_ZERO);
- sooptcopyin(sopt, buf, NAT_BUF_LEN, sizeof(struct cfg_nat));
- ser_n = (struct cfg_nat *)buf;
-
- /* check valid parameter ser_n->id > 0 ? */
/*
* Find/create nat rule.
*/
IPFW_WLOCK(chain);
- ptr = lookup_nat(&chain->nat, ser_n->id);
+ gencnt = chain->gencnt;
+ ptr = lookup_nat(&chain->nat, cfg->id);
if (ptr == NULL) {
+ IPFW_WUNLOCK(chain);
/* New rule: allocate and init new instance. */
- ptr = malloc(sizeof(struct cfg_nat),
- M_IPFW, M_NOWAIT | M_ZERO);
- if (ptr == NULL) {
- IPFW_WUNLOCK(chain);
- free(buf, M_IPFW);
- return (ENOSPC);
- }
+ ptr = malloc(sizeof(struct cfg_nat), M_IPFW, M_WAITOK | M_ZERO);
ptr->lib = LibAliasInit(NULL);
- if (ptr->lib == NULL) {
- IPFW_WUNLOCK(chain);
- free(ptr, M_IPFW);
- free(buf, M_IPFW);
- return (EINVAL);
- }
LIST_INIT(&ptr->redir_chain);
} else {
- /* Entry already present: temporarly unhook it. */
+ /* Entry already present: temporarily unhook it. */
LIST_REMOVE(ptr, _next);
- flush_nat_ptrs(chain, ser_n->id);
+ flush_nat_ptrs(chain, cfg->id);
+ IPFW_WUNLOCK(chain);
}
- IPFW_WUNLOCK(chain);
/*
* Basic nat configuration.
*/
- ptr->id = ser_n->id;
+ ptr->id = cfg->id;
/*
* XXX - what if this rule doesn't nat any ip and just
* redirect?
* do we set aliasaddress to 0.0.0.0?
*/
- ptr->ip = ser_n->ip;
- ptr->redir_cnt = ser_n->redir_cnt;
- ptr->mode = ser_n->mode;
- LibAliasSetMode(ptr->lib, ser_n->mode, ser_n->mode);
+ ptr->ip = cfg->ip;
+ ptr->redir_cnt = cfg->redir_cnt;
+ ptr->mode = cfg->mode;
+ LibAliasSetMode(ptr->lib, cfg->mode, cfg->mode);
LibAliasSetAddress(ptr->lib, ptr->ip);
- memcpy(ptr->if_name, ser_n->if_name, IF_NAMESIZE);
+ memcpy(ptr->if_name, cfg->if_name, IF_NAMESIZE);
/*
* Redir and LSNAT configuration.
@@ -407,11 +447,19 @@ ipfw_nat_cfg(struct sockopt *sopt)
del_redir_spool_cfg(ptr, &ptr->redir_chain);
/* Add new entries. */
add_redir_spool_cfg(&buf[(sizeof(struct cfg_nat))], ptr);
- free(buf, M_IPFW);
+
IPFW_WLOCK(chain);
+ /* Extra check to avoid race with another ipfw_nat_cfg() */
+ if (gencnt != chain->gencnt &&
+ ((cfg = lookup_nat(&chain->nat, ptr->id)) != NULL))
+ LIST_REMOVE(cfg, _next);
LIST_INSERT_HEAD(&chain->nat, ptr, _next);
+ chain->gencnt++;
IPFW_WUNLOCK(chain);
- return (0);
+
+out:
+ free(buf, M_TEMP);
+ return (error);
}
static int
@@ -441,52 +489,61 @@ ipfw_nat_del(struct sockopt *sopt)
static int
ipfw_nat_get_cfg(struct sockopt *sopt)
{
- uint8_t *data;
+ struct ip_fw_chain *chain = &V_layer3_chain;
struct cfg_nat *n;
struct cfg_redir *r;
struct cfg_spool *s;
- int nat_cnt, off;
- struct ip_fw_chain *chain;
- int err = ENOSPC;
+ char *data;
+ int gencnt, nat_cnt, len, error;
- chain = &V_layer3_chain;
nat_cnt = 0;
- off = sizeof(nat_cnt);
+ len = sizeof(nat_cnt);
- data = malloc(NAT_BUF_LEN, M_IPFW, M_WAITOK | M_ZERO);
IPFW_RLOCK(chain);
- /* Serialize all the data. */
+retry:
+ gencnt = chain->gencnt;
+ /* Estimate memory amount */
LIST_FOREACH(n, &chain->nat, _next) {
nat_cnt++;
- if (off + SOF_NAT >= NAT_BUF_LEN)
- goto nospace;
- bcopy(n, &data[off], SOF_NAT);
- off += SOF_NAT;
+ len += sizeof(struct cfg_nat);
+ LIST_FOREACH(r, &n->redir_chain, _next) {
+ len += sizeof(struct cfg_redir);
+ LIST_FOREACH(s, &r->spool_chain, _next)
+ len += sizeof(struct cfg_spool);
+ }
+ }
+ IPFW_RUNLOCK(chain);
+
+ data = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
+ bcopy(&nat_cnt, data, sizeof(nat_cnt));
+
+ nat_cnt = 0;
+ len = sizeof(nat_cnt);
+
+ IPFW_RLOCK(chain);
+ if (gencnt != chain->gencnt) {
+ free(data, M_TEMP);
+ goto retry;
+ }
+ /* Serialize all the data. */
+ LIST_FOREACH(n, &chain->nat, _next) {
+ bcopy(n, &data[len], sizeof(struct cfg_nat));
+ len += sizeof(struct cfg_nat);
LIST_FOREACH(r, &n->redir_chain, _next) {
- if (off + SOF_REDIR >= NAT_BUF_LEN)
- goto nospace;
- bcopy(r, &data[off], SOF_REDIR);
- off += SOF_REDIR;
+ bcopy(r, &data[len], sizeof(struct cfg_redir));
+ len += sizeof(struct cfg_redir);
LIST_FOREACH(s, &r->spool_chain, _next) {
- if (off + SOF_SPOOL >= NAT_BUF_LEN)
- goto nospace;
- bcopy(s, &data[off], SOF_SPOOL);
- off += SOF_SPOOL;
+ bcopy(s, &data[len], sizeof(struct cfg_spool));
+ len += sizeof(struct cfg_spool);
}
}
}
- err = 0; /* all good */
-nospace:
IPFW_RUNLOCK(chain);
- if (err == 0) {
- bcopy(&nat_cnt, data, sizeof(nat_cnt));
- sooptcopyout(sopt, data, NAT_BUF_LEN);
- } else {
- printf("serialized data buffer not big enough:"
- "please increase NAT_BUF_LEN\n");
- }
- free(data, M_IPFW);
- return (err);
+
+ error = sooptcopyout(sopt, data, len);
+ free(data, M_TEMP);
+
+ return (error);
}
static int
diff --git a/freebsd/sys/netinet/ipfw/ip_fw_pfil.c b/freebsd/sys/netinet/ipfw/ip_fw_pfil.c
index b32a08b7..ebd10c5b 100644
--- a/freebsd/sys/netinet/ipfw/ip_fw_pfil.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_pfil.c
@@ -29,15 +29,12 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#if !defined(KLD_MODULE)
#include <rtems/bsd/local/opt_ipfw.h>
-#include <rtems/bsd/local/opt_ipdn.h>
#include <rtems/bsd/local/opt_inet.h>
+#include <rtems/bsd/local/opt_inet6.h>
#ifndef INET
#error IPFIREWALL requires INET.
#endif /* INET */
-#endif /* KLD_MODULE */
-#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
@@ -129,8 +126,9 @@ again:
args.rule = *((struct ipfw_rule_ref *)(tag+1));
m_tag_delete(*m0, tag);
if (args.rule.info & IPFW_ONEPASS) {
- SET_HOST_IPLEN(mtod(*m0, struct ip *));
- return 0;
+ if (mtod(*m0, struct ip *)->ip_v == 4)
+ SET_HOST_IPLEN(mtod(*m0, struct ip *));
+ return (0);
}
}
@@ -151,7 +149,7 @@ again:
/* next_hop may be set by ipfw_chk */
if (args.next_hop == NULL)
break; /* pass */
-#ifndef IPFIREWALL_FORWARD
+#if !defined(IPFIREWALL_FORWARD) || (!defined(INET6) && !defined(INET))
ret = EACCES;
#else
{
@@ -179,7 +177,7 @@ again:
if (in_localip(args.next_hop->sin_addr))
(*m0)->m_flags |= M_FASTFWD_OURS;
}
-#endif
+#endif /* IPFIREWALL_FORWARD */
break;
case IP_FW_DENY:
diff --git a/freebsd/sys/netinet/ipfw/ip_fw_private.h b/freebsd/sys/netinet/ipfw/ip_fw_private.h
index c29ae0ad..b91c154a 100644
--- a/freebsd/sys/netinet/ipfw/ip_fw_private.h
+++ b/freebsd/sys/netinet/ipfw/ip_fw_private.h
@@ -90,7 +90,7 @@ struct ip_fw_args {
/*
* On return, it points to the matching rule.
* On entry, rule.slot > 0 means the info is valid and
- * contains the the starting rule for an ipfw search.
+ * contains the starting rule for an ipfw search.
* If chain_id == chain->id && slot >0 then jump to that slot.
* Otherwise, we locate the first rule >= rulenum:rule_id
*/
@@ -208,6 +208,9 @@ VNET_DECLARE(u_int32_t, set_disable);
VNET_DECLARE(int, autoinc_step);
#define V_autoinc_step VNET(autoinc_step)
+VNET_DECLARE(unsigned int, fw_tables_max);
+#define V_fw_tables_max VNET(fw_tables_max)
+
struct ip_fw_chain {
struct ip_fw *rules; /* list of rules */
struct ip_fw *reap; /* list of rules to reap */
@@ -216,7 +219,9 @@ struct ip_fw_chain {
int static_len; /* total len of static rules */
struct ip_fw **map; /* array of rule ptrs to ease lookup */
LIST_HEAD(nat_list, cfg_nat) nat; /* list of nat entries */
- struct radix_node_head *tables[IPFW_TABLES_MAX];
+ struct radix_node_head **tables; /* IPv4 tables */
+ struct radix_node_head **xtables; /* extended tables */
+ uint8_t *tabletype; /* Array of table types */
#if defined( __linux__ ) || defined( _WIN32 )
spinlock_t rwmtx;
spinlock_t uh_lock;
@@ -225,6 +230,7 @@ struct ip_fw_chain {
struct rwlock uh_lock; /* lock for upper half */
#endif
uint32_t id; /* ruleset id */
+ uint32_t gencnt; /* generation count */
};
struct sockopt; /* used by tcp_var.h */
@@ -271,16 +277,21 @@ int ipfw_check_hook(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
struct radix_node;
int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
uint32_t *val);
+int ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
+ uint32_t *val, int type);
int ipfw_init_tables(struct ip_fw_chain *ch);
void ipfw_destroy_tables(struct ip_fw_chain *ch);
int ipfw_flush_table(struct ip_fw_chain *ch, uint16_t tbl);
-int ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
- uint8_t mlen, uint32_t value);
-int ipfw_dump_table_entry(struct radix_node *rn, void *arg);
-int ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
- uint8_t mlen);
+int ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
+ uint8_t plen, uint8_t mlen, uint8_t type, uint32_t value);
+int ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
+ uint8_t plen, uint8_t mlen, uint8_t type);
int ipfw_count_table(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
+int ipfw_dump_table_entry(struct radix_node *rn, void *arg);
int ipfw_dump_table(struct ip_fw_chain *ch, ipfw_table *tbl);
+int ipfw_count_xtable(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
+int ipfw_dump_xtable(struct ip_fw_chain *ch, ipfw_xtable *tbl);
+int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables);
/* In ip_fw_nat.c -- XXX to be moved to ip_var.h */
diff --git a/freebsd/sys/netinet/ipfw/ip_fw_sockopt.c b/freebsd/sys/netinet/ipfw/ip_fw_sockopt.c
index b9635416..abfc24a0 100644
--- a/freebsd/sys/netinet/ipfw/ip_fw_sockopt.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_sockopt.c
@@ -35,17 +35,12 @@ __FBSDID("$FreeBSD$");
* the upper half of the ipfw code.
*/
-#if !defined(KLD_MODULE)
#include <rtems/bsd/local/opt_ipfw.h>
-#include <rtems/bsd/local/opt_ipdivert.h>
-#include <rtems/bsd/local/opt_ipdn.h>
#include <rtems/bsd/local/opt_inet.h>
#ifndef INET
#error IPFIREWALL requires INET.
#endif /* INET */
-#endif
#include <rtems/bsd/local/opt_inet6.h>
-#include <rtems/bsd/local/opt_ipsec.h>
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
@@ -351,12 +346,13 @@ del_entry(struct ip_fw_chain *chain, uint32_t arg)
}
if (n == 0) {
- /* A flush request (arg == 0) on empty ruleset
- * returns with no error. On the contrary,
+ /* A flush request (arg == 0 or cmd == 1) on empty
+ * ruleset returns with no error. On the contrary,
* if there is no match on a specific request,
* we return EINVAL.
*/
- error = (arg == 0) ? 0 : EINVAL;
+ if (arg != 0 && cmd != 1)
+ error = EINVAL;
break;
}
@@ -607,7 +603,8 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_SETFIB:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
goto bad_size;
- if (cmd->arg1 >= rt_numfibs) {
+ if ((cmd->arg1 != IP_FW_TABLEARG) &&
+ (cmd->arg1 >= rt_numfibs)) {
printf("ipfw: invalid fib number %d\n",
cmd->arg1);
return EINVAL;
@@ -672,7 +669,6 @@ check_ipfw_struct(struct ip_fw *rule, int size)
cmdlen != F_INSN_SIZE(ipfw_insn_u32))
goto bad_size;
break;
-
case O_MACADDR2:
if (cmdlen != F_INSN_SIZE(ipfw_insn_mac))
goto bad_size;
@@ -751,6 +747,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
#endif
case O_SKIPTO:
case O_REASS:
+ case O_CALLRETURN:
check_size:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
goto bad_size;
@@ -933,6 +930,7 @@ ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space)
}
+#define IP_FW3_OPLENGTH(x) ((x)->sopt_valsize - sizeof(ip_fw3_opheader))
/**
* {set|get}sockopt parser.
*/
@@ -941,10 +939,13 @@ ipfw_ctl(struct sockopt *sopt)
{
#define RULE_MAXSIZE (256*sizeof(u_int32_t))
int error;
- size_t size;
+ size_t size, len, valsize;
struct ip_fw *buf, *rule;
struct ip_fw_chain *chain;
u_int32_t rulenum[2];
+ uint32_t opt;
+ char xbuf[128];
+ ip_fw3_opheader *op3 = NULL;
error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
if (error)
@@ -964,7 +965,21 @@ ipfw_ctl(struct sockopt *sopt)
chain = &V_layer3_chain;
error = 0;
- switch (sopt->sopt_name) {
+ /* Save original valsize before it is altered via sooptcopyin() */
+ valsize = sopt->sopt_valsize;
+ if ((opt = sopt->sopt_name) == IP_FW3) {
+ /*
+ * Copy not less than sizeof(ip_fw3_opheader).
+ * We hope any IP_FW3 command will fit into 128-byte buffer.
+ */
+ if ((error = sooptcopyin(sopt, xbuf, sizeof(xbuf),
+ sizeof(ip_fw3_opheader))) != 0)
+ return (error);
+ op3 = (ip_fw3_opheader *)xbuf;
+ opt = op3->opcode;
+ }
+
+ switch (opt) {
case IP_FW_GET:
/*
* pass up a copy of the current rules. Static rules
@@ -1103,7 +1118,8 @@ ipfw_ctl(struct sockopt *sopt)
if (error)
break;
error = ipfw_add_table_entry(chain, ent.tbl,
- ent.addr, ent.masklen, ent.value);
+ &ent.addr, sizeof(ent.addr), ent.masklen,
+ IPFW_TABLE_CIDR, ent.value);
}
break;
@@ -1116,7 +1132,34 @@ ipfw_ctl(struct sockopt *sopt)
if (error)
break;
error = ipfw_del_table_entry(chain, ent.tbl,
- ent.addr, ent.masklen);
+ &ent.addr, sizeof(ent.addr), ent.masklen, IPFW_TABLE_CIDR);
+ }
+ break;
+
+ case IP_FW_TABLE_XADD: /* IP_FW3 */
+ case IP_FW_TABLE_XDEL: /* IP_FW3 */
+ {
+ ipfw_table_xentry *xent = (ipfw_table_xentry *)(op3 + 1);
+
+ /* Check minimum header size */
+ if (IP_FW3_OPLENGTH(sopt) < offsetof(ipfw_table_xentry, k)) {
+ error = EINVAL;
+ break;
+ }
+
+ /* Check if len field is valid */
+ if (xent->len > sizeof(ipfw_table_xentry)) {
+ error = EINVAL;
+ break;
+ }
+
+ len = xent->len - offsetof(ipfw_table_xentry, k);
+
+ error = (opt == IP_FW_TABLE_XADD) ?
+ ipfw_add_table_entry(chain, xent->tbl, &xent->k,
+ len, xent->masklen, xent->type, xent->value) :
+ ipfw_del_table_entry(chain, xent->tbl, &xent->k,
+ len, xent->masklen, xent->type);
}
break;
@@ -1128,9 +1171,7 @@ ipfw_ctl(struct sockopt *sopt)
sizeof(tbl), sizeof(tbl));
if (error)
break;
- IPFW_WLOCK(chain);
error = ipfw_flush_table(chain, tbl);
- IPFW_WUNLOCK(chain);
}
break;
@@ -1179,6 +1220,62 @@ ipfw_ctl(struct sockopt *sopt)
}
break;
+ case IP_FW_TABLE_XGETSIZE: /* IP_FW3 */
+ {
+ uint32_t *tbl;
+
+ if (IP_FW3_OPLENGTH(sopt) < sizeof(uint32_t)) {
+ error = EINVAL;
+ break;
+ }
+
+ tbl = (uint32_t *)(op3 + 1);
+
+ IPFW_RLOCK(chain);
+ error = ipfw_count_xtable(chain, *tbl, tbl);
+ IPFW_RUNLOCK(chain);
+ if (error)
+ break;
+ error = sooptcopyout(sopt, op3, sopt->sopt_valsize);
+ }
+ break;
+
+ case IP_FW_TABLE_XLIST: /* IP_FW3 */
+ {
+ ipfw_xtable *tbl;
+
+ if ((size = valsize) < sizeof(ipfw_xtable)) {
+ error = EINVAL;
+ break;
+ }
+
+ tbl = malloc(size, M_TEMP, M_ZERO | M_WAITOK);
+ memcpy(tbl, op3, sizeof(ipfw_xtable));
+
+ /* Get maximum number of entries we can store */
+ tbl->size = (size - sizeof(ipfw_xtable)) /
+ sizeof(ipfw_table_xentry);
+ IPFW_RLOCK(chain);
+ error = ipfw_dump_xtable(chain, tbl);
+ IPFW_RUNLOCK(chain);
+ if (error) {
+ free(tbl, M_TEMP);
+ break;
+ }
+
+ /* Revert size field back to bytes */
+ tbl->size = tbl->size * sizeof(ipfw_table_xentry) +
+ sizeof(ipfw_table);
+ /*
+ * Since we call sooptcopyin() with small buffer, sopt_valsize is
+ * decreased to reflect supplied buffer size. Set it back to original value
+ */
+ sopt->sopt_valsize = valsize;
+ error = sooptcopyout(sopt, tbl, size);
+ free(tbl, M_TEMP);
+ }
+ break;
+
/*--- NAT operations are protected by the IPFW_LOCK ---*/
case IP_FW_NAT_CFG:
if (IPFW_NAT_LOADED)
diff --git a/freebsd/sys/netinet/ipfw/ip_fw_table.c b/freebsd/sys/netinet/ipfw/ip_fw_table.c
index a399a7a0..1725b8a5 100644
--- a/freebsd/sys/netinet/ipfw/ip_fw_table.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_table.c
@@ -41,17 +41,12 @@ __FBSDID("$FreeBSD$");
* from userland, because operations are typically fast.
*/
-#if !defined(KLD_MODULE)
#include <rtems/bsd/local/opt_ipfw.h>
-#include <rtems/bsd/local/opt_ipdivert.h>
-#include <rtems/bsd/local/opt_ipdn.h>
#include <rtems/bsd/local/opt_inet.h>
#ifndef INET
#error IPFIREWALL requires INET.
#endif /* INET */
-#endif
#include <rtems/bsd/local/opt_inet6.h>
-#include <rtems/bsd/local/opt_ipsec.h>
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
@@ -83,6 +78,29 @@ struct table_entry {
u_int32_t value;
};
+struct xaddr_iface {
+ uint8_t if_len; /* length of this struct */
+ uint8_t pad[7]; /* Align name */
+ char ifname[IF_NAMESIZE]; /* Interface name */
+};
+
+struct table_xentry {
+ struct radix_node rn[2];
+ union {
+#ifdef INET6
+ struct sockaddr_in6 addr6;
+#endif
+ struct xaddr_iface iface;
+ } a;
+ union {
+#ifdef INET6
+ struct sockaddr_in6 mask6;
+#endif
+ struct xaddr_iface ifmask;
+ } m;
+ u_int32_t value;
+};
+
/*
* The radix code expects addr and mask to be array of bytes,
* with the first byte being the length of the array. rn_inithead
@@ -94,57 +112,281 @@ struct table_entry {
*/
#define KEY_LEN(v) *((uint8_t *)&(v))
#define KEY_OFS (8*offsetof(struct sockaddr_in, sin_addr))
+/*
+ * Do not require radix to compare more than actual IPv4/IPv6 address
+ */
+#define KEY_LEN_INET (offsetof(struct sockaddr_in, sin_addr) + sizeof(in_addr_t))
+#define KEY_LEN_INET6 (offsetof(struct sockaddr_in6, sin6_addr) + sizeof(struct in6_addr))
+#define KEY_LEN_IFACE (offsetof(struct xaddr_iface, ifname))
+
+#define OFF_LEN_INET (8 * offsetof(struct sockaddr_in, sin_addr))
+#define OFF_LEN_INET6 (8 * offsetof(struct sockaddr_in6, sin6_addr))
+#define OFF_LEN_IFACE (8 * offsetof(struct xaddr_iface, ifname))
+
+
+static inline void
+ipv6_writemask(struct in6_addr *addr6, uint8_t mask)
+{
+ uint32_t *cp;
+
+ for (cp = (uint32_t *)addr6; mask >= 32; mask -= 32)
+ *cp++ = 0xFFFFFFFF;
+ *cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0);
+}
int
-ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
- uint8_t mlen, uint32_t value)
+ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
+ uint8_t plen, uint8_t mlen, uint8_t type, uint32_t value)
{
- struct radix_node_head *rnh;
+ struct radix_node_head *rnh, **rnh_ptr;
struct table_entry *ent;
+ struct table_xentry *xent;
struct radix_node *rn;
+ in_addr_t addr;
+ int offset;
+ void *ent_ptr;
+ struct sockaddr *addr_ptr, *mask_ptr;
+ char c;
- if (tbl >= IPFW_TABLES_MAX)
+ if (tbl >= V_fw_tables_max)
return (EINVAL);
- rnh = ch->tables[tbl];
- ent = malloc(sizeof(*ent), M_IPFW_TBL, M_NOWAIT | M_ZERO);
- if (ent == NULL)
- return (ENOMEM);
- ent->value = value;
- KEY_LEN(ent->addr) = KEY_LEN(ent->mask) = 8;
- ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
- ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr;
+
+ switch (type) {
+ case IPFW_TABLE_CIDR:
+ if (plen == sizeof(in_addr_t)) {
+#ifdef INET
+ /* IPv4 case */
+ if (mlen > 32)
+ return (EINVAL);
+ ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
+ ent->value = value;
+ /* Set 'total' structure length */
+ KEY_LEN(ent->addr) = KEY_LEN_INET;
+ KEY_LEN(ent->mask) = KEY_LEN_INET;
+ /* Set offset of IPv4 address in bits */
+ offset = OFF_LEN_INET;
+ ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
+ addr = *((in_addr_t *)paddr);
+ ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr;
+ /* Set pointers */
+ rnh_ptr = &ch->tables[tbl];
+ ent_ptr = ent;
+ addr_ptr = (struct sockaddr *)&ent->addr;
+ mask_ptr = (struct sockaddr *)&ent->mask;
+#endif
+#ifdef INET6
+ } else if (plen == sizeof(struct in6_addr)) {
+ /* IPv6 case */
+ if (mlen > 128)
+ return (EINVAL);
+ xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
+ xent->value = value;
+ /* Set 'total' structure length */
+ KEY_LEN(xent->a.addr6) = KEY_LEN_INET6;
+ KEY_LEN(xent->m.mask6) = KEY_LEN_INET6;
+ /* Set offset of IPv6 address in bits */
+ offset = OFF_LEN_INET6;
+ ipv6_writemask(&xent->m.mask6.sin6_addr, mlen);
+ memcpy(&xent->a.addr6.sin6_addr, paddr, sizeof(struct in6_addr));
+ APPLY_MASK(&xent->a.addr6.sin6_addr, &xent->m.mask6.sin6_addr);
+ /* Set pointers */
+ rnh_ptr = &ch->xtables[tbl];
+ ent_ptr = xent;
+ addr_ptr = (struct sockaddr *)&xent->a.addr6;
+ mask_ptr = (struct sockaddr *)&xent->m.mask6;
+#endif
+ } else {
+ /* Unknown CIDR type */
+ return (EINVAL);
+ }
+ break;
+
+ case IPFW_TABLE_INTERFACE:
+ /* Check if string is terminated */
+ c = ((char *)paddr)[IF_NAMESIZE - 1];
+ ((char *)paddr)[IF_NAMESIZE - 1] = '\0';
+ if (((mlen = strlen((char *)paddr)) == IF_NAMESIZE - 1) && (c != '\0'))
+ return (EINVAL);
+
+ /* Include last \0 into comparison */
+ mlen++;
+
+ xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
+ xent->value = value;
+ /* Set 'total' structure length */
+ KEY_LEN(xent->a.iface) = KEY_LEN_IFACE + mlen;
+ KEY_LEN(xent->m.ifmask) = KEY_LEN_IFACE + mlen;
+ /* Set offset of interface name in bits */
+ offset = OFF_LEN_IFACE;
+ memcpy(xent->a.iface.ifname, paddr, mlen);
+ /* Assume direct match */
+ /* TODO: Add interface pattern matching */
+#if 0
+ memset(xent->m.ifmask.ifname, 0xFF, IF_NAMESIZE);
+ mask_ptr = (struct sockaddr *)&xent->m.ifmask;
+#endif
+ /* Set pointers */
+ rnh_ptr = &ch->xtables[tbl];
+ ent_ptr = xent;
+ addr_ptr = (struct sockaddr *)&xent->a.iface;
+ mask_ptr = NULL;
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
IPFW_WLOCK(ch);
- rn = rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent);
- if (rn == NULL) {
+
+ /* Check if tabletype is valid */
+ if ((ch->tabletype[tbl] != 0) && (ch->tabletype[tbl] != type)) {
IPFW_WUNLOCK(ch);
- free(ent, M_IPFW_TBL);
- return (EEXIST);
+ free(ent_ptr, M_IPFW_TBL);
+ return (EINVAL);
+ }
+
+ /* Check if radix tree exists */
+ if ((rnh = *rnh_ptr) == NULL) {
+ IPFW_WUNLOCK(ch);
+ /* Create radix for a new table */
+ if (!rn_inithead((void **)&rnh, offset)) {
+ free(ent_ptr, M_IPFW_TBL);
+ return (ENOMEM);
+ }
+
+ IPFW_WLOCK(ch);
+ if (*rnh_ptr != NULL) {
+ /* Tree is already attached by other thread */
+ rn_detachhead((void **)&rnh);
+ rnh = *rnh_ptr;
+ /* Check table type another time */
+ if (ch->tabletype[tbl] != type) {
+ IPFW_WUNLOCK(ch);
+ free(ent_ptr, M_IPFW_TBL);
+ return (EINVAL);
+ }
+ } else {
+ *rnh_ptr = rnh;
+ /*
+ * Set table type. It can be set already
+ * (if we have IPv6-only table) but setting
+ * it another time does not hurt
+ */
+ ch->tabletype[tbl] = type;
+ }
}
+
+ rn = rnh->rnh_addaddr(addr_ptr, mask_ptr, rnh, ent_ptr);
IPFW_WUNLOCK(ch);
+
+ if (rn == NULL) {
+ free(ent_ptr, M_IPFW_TBL);
+ return (EEXIST);
+ }
return (0);
}
int
-ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
- uint8_t mlen)
+ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
+ uint8_t plen, uint8_t mlen, uint8_t type)
{
- struct radix_node_head *rnh;
+ struct radix_node_head *rnh, **rnh_ptr;
struct table_entry *ent;
+ in_addr_t addr;
struct sockaddr_in sa, mask;
+ struct sockaddr *sa_ptr, *mask_ptr;
+ char c;
- if (tbl >= IPFW_TABLES_MAX)
+ if (tbl >= V_fw_tables_max)
return (EINVAL);
- rnh = ch->tables[tbl];
- KEY_LEN(sa) = KEY_LEN(mask) = 8;
- mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
- sa.sin_addr.s_addr = addr & mask.sin_addr.s_addr;
+
+ switch (type) {
+ case IPFW_TABLE_CIDR:
+ if (plen == sizeof(in_addr_t)) {
+ /* Set 'total' structure length */
+ KEY_LEN(sa) = KEY_LEN_INET;
+ KEY_LEN(mask) = KEY_LEN_INET;
+ mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
+ addr = *((in_addr_t *)paddr);
+ sa.sin_addr.s_addr = addr & mask.sin_addr.s_addr;
+ rnh_ptr = &ch->tables[tbl];
+ sa_ptr = (struct sockaddr *)&sa;
+ mask_ptr = (struct sockaddr *)&mask;
+#ifdef INET6
+ } else if (plen == sizeof(struct in6_addr)) {
+ /* IPv6 case */
+ if (mlen > 128)
+ return (EINVAL);
+ struct sockaddr_in6 sa6, mask6;
+ memset(&sa6, 0, sizeof(struct sockaddr_in6));
+ memset(&mask6, 0, sizeof(struct sockaddr_in6));
+ /* Set 'total' structure length */
+ KEY_LEN(sa6) = KEY_LEN_INET6;
+ KEY_LEN(mask6) = KEY_LEN_INET6;
+ ipv6_writemask(&mask6.sin6_addr, mlen);
+ memcpy(&sa6.sin6_addr, paddr, sizeof(struct in6_addr));
+ APPLY_MASK(&sa6.sin6_addr, &mask6.sin6_addr);
+ rnh_ptr = &ch->xtables[tbl];
+ sa_ptr = (struct sockaddr *)&sa6;
+ mask_ptr = (struct sockaddr *)&mask6;
+#endif
+ } else {
+ /* Unknown CIDR type */
+ return (EINVAL);
+ }
+ break;
+
+ case IPFW_TABLE_INTERFACE:
+ /* Check if string is terminated */
+ c = ((char *)paddr)[IF_NAMESIZE - 1];
+ ((char *)paddr)[IF_NAMESIZE - 1] = '\0';
+ if (((mlen = strlen((char *)paddr)) == IF_NAMESIZE - 1) && (c != '\0'))
+ return (EINVAL);
+
+ struct xaddr_iface ifname, ifmask;
+ memset(&ifname, 0, sizeof(ifname));
+
+ /* Include last \0 into comparison */
+ mlen++;
+
+ /* Set 'total' structure length */
+ KEY_LEN(ifname) = KEY_LEN_IFACE + mlen;
+ KEY_LEN(ifmask) = KEY_LEN_IFACE + mlen;
+ /* Assume direct match */
+ /* FIXME: Add interface pattern matching */
+#if 0
+ memset(ifmask.ifname, 0xFF, IF_NAMESIZE);
+ mask_ptr = (struct sockaddr *)&ifmask;
+#endif
+ mask_ptr = NULL;
+ memcpy(ifname.ifname, paddr, mlen);
+ /* Set pointers */
+ rnh_ptr = &ch->xtables[tbl];
+ sa_ptr = (struct sockaddr *)&ifname;
+
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
IPFW_WLOCK(ch);
- ent = (struct table_entry *)rnh->rnh_deladdr(&sa, &mask, rnh);
- if (ent == NULL) {
+ if ((rnh = *rnh_ptr) == NULL) {
IPFW_WUNLOCK(ch);
return (ESRCH);
}
+
+ if (ch->tabletype[tbl] != type) {
+ IPFW_WUNLOCK(ch);
+ return (EINVAL);
+ }
+
+ ent = (struct table_entry *)rnh->rnh_deladdr(sa_ptr, mask_ptr, rnh);
IPFW_WUNLOCK(ch);
+
+ if (ent == NULL)
+ return (ESRCH);
+
free(ent, M_IPFW_TBL);
return (0);
}
@@ -165,15 +407,38 @@ flush_table_entry(struct radix_node *rn, void *arg)
int
ipfw_flush_table(struct ip_fw_chain *ch, uint16_t tbl)
{
- struct radix_node_head *rnh;
-
- IPFW_WLOCK_ASSERT(ch);
+ struct radix_node_head *rnh, *xrnh;
- if (tbl >= IPFW_TABLES_MAX)
+ if (tbl >= V_fw_tables_max)
return (EINVAL);
- rnh = ch->tables[tbl];
- KASSERT(rnh != NULL, ("NULL IPFW table"));
- rnh->rnh_walktree(rnh, flush_table_entry, rnh);
+
+ /*
+ * We free both (IPv4 and extended) radix trees and
+ * clear table type here to permit table to be reused
+ * for different type without module reload
+ */
+
+ IPFW_WLOCK(ch);
+ /* Set IPv4 table pointer to zero */
+ if ((rnh = ch->tables[tbl]) != NULL)
+ ch->tables[tbl] = NULL;
+ /* Set extended table pointer to zero */
+ if ((xrnh = ch->xtables[tbl]) != NULL)
+ ch->xtables[tbl] = NULL;
+ /* Zero table type */
+ ch->tabletype[tbl] = 0;
+ IPFW_WUNLOCK(ch);
+
+ if (rnh != NULL) {
+ rnh->rnh_walktree(rnh, flush_table_entry, rnh);
+ rn_detachhead((void **)&rnh);
+ }
+
+ if (xrnh != NULL) {
+ xrnh->rnh_walktree(xrnh, flush_table_entry, xrnh);
+ rn_detachhead((void **)&xrnh);
+ }
+
return (0);
}
@@ -181,31 +446,86 @@ void
ipfw_destroy_tables(struct ip_fw_chain *ch)
{
uint16_t tbl;
- struct radix_node_head *rnh;
- IPFW_WLOCK_ASSERT(ch);
-
- for (tbl = 0; tbl < IPFW_TABLES_MAX; tbl++) {
+ /* Flush all tables */
+ for (tbl = 0; tbl < V_fw_tables_max; tbl++)
ipfw_flush_table(ch, tbl);
- rnh = ch->tables[tbl];
- rn_detachhead((void **)&rnh);
- }
+
+ /* Free pointers itself */
+ free(ch->tables, M_IPFW);
+ free(ch->xtables, M_IPFW);
+ free(ch->tabletype, M_IPFW);
}
int
ipfw_init_tables(struct ip_fw_chain *ch)
-{
- int i;
- uint16_t j;
+{
+ /* Allocate pointers */
+ ch->tables = malloc(V_fw_tables_max * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
+ ch->xtables = malloc(V_fw_tables_max * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
+ ch->tabletype = malloc(V_fw_tables_max * sizeof(uint8_t), M_IPFW, M_WAITOK | M_ZERO);
+ return (0);
+}
- for (i = 0; i < IPFW_TABLES_MAX; i++) {
- if (!rn_inithead((void **)&ch->tables[i], KEY_OFS)) {
- for (j = 0; j < i; j++) {
- (void) ipfw_flush_table(ch, j);
+int
+ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables)
+{
+ struct radix_node_head **tables, **xtables, *rnh;
+ struct radix_node_head **tables_old, **xtables_old;
+ uint8_t *tabletype, *tabletype_old;
+ unsigned int ntables_old, tbl;
+
+ /* Check new value for validity */
+ if (ntables > IPFW_TABLES_MAX)
+ ntables = IPFW_TABLES_MAX;
+
+ /* Allocate new pointers */
+ tables = malloc(ntables * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
+ xtables = malloc(ntables * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
+ tabletype = malloc(ntables * sizeof(uint8_t), M_IPFW, M_WAITOK | M_ZERO);
+
+ IPFW_WLOCK(ch);
+
+ tbl = (ntables >= V_fw_tables_max) ? V_fw_tables_max : ntables;
+
+ /* Copy old table pointers */
+ memcpy(tables, ch->tables, sizeof(void *) * tbl);
+ memcpy(xtables, ch->xtables, sizeof(void *) * tbl);
+ memcpy(tabletype, ch->tabletype, sizeof(uint8_t) * tbl);
+
+ /* Change pointers and number of tables */
+ tables_old = ch->tables;
+ xtables_old = ch->xtables;
+ tabletype_old = ch->tabletype;
+ ch->tables = tables;
+ ch->xtables = xtables;
+ ch->tabletype = tabletype;
+
+ ntables_old = V_fw_tables_max;
+ V_fw_tables_max = ntables;
+
+ IPFW_WUNLOCK(ch);
+
+ /* Check if we need to destroy radix trees */
+ if (ntables < ntables_old) {
+ for (tbl = ntables; tbl < ntables_old; tbl++) {
+ if ((rnh = tables_old[tbl]) != NULL) {
+ rnh->rnh_walktree(rnh, flush_table_entry, rnh);
+ rn_detachhead((void **)&rnh);
+ }
+
+ if ((rnh = xtables_old[tbl]) != NULL) {
+ rnh->rnh_walktree(rnh, flush_table_entry, rnh);
+ rn_detachhead((void **)&rnh);
}
- return (ENOMEM);
}
}
+
+ /* Free old pointers */
+ free(tables_old, M_IPFW);
+ free(xtables_old, M_IPFW);
+ free(tabletype_old, M_IPFW);
+
return (0);
}
@@ -217,10 +537,11 @@ ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
struct table_entry *ent;
struct sockaddr_in sa;
- if (tbl >= IPFW_TABLES_MAX)
+ if (tbl >= V_fw_tables_max)
+ return (0);
+ if ((rnh = ch->tables[tbl]) == NULL)
return (0);
- rnh = ch->tables[tbl];
- KEY_LEN(sa) = 8;
+ KEY_LEN(sa) = KEY_LEN_INET;
sa.sin_addr.s_addr = addr;
ent = (struct table_entry *)(rnh->rnh_lookup(&sa, NULL, rnh));
if (ent != NULL) {
@@ -230,6 +551,46 @@ ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
return (0);
}
+int
+ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
+ uint32_t *val, int type)
+{
+ struct radix_node_head *rnh;
+ struct table_xentry *xent;
+ struct sockaddr_in6 sa6;
+ struct xaddr_iface iface;
+
+ if (tbl >= V_fw_tables_max)
+ return (0);
+ if ((rnh = ch->xtables[tbl]) == NULL)
+ return (0);
+
+ switch (type) {
+ case IPFW_TABLE_CIDR:
+ KEY_LEN(sa6) = KEY_LEN_INET6;
+ memcpy(&sa6.sin6_addr, paddr, sizeof(struct in6_addr));
+ xent = (struct table_xentry *)(rnh->rnh_lookup(&sa6, NULL, rnh));
+ break;
+
+ case IPFW_TABLE_INTERFACE:
+ KEY_LEN(iface) = KEY_LEN_IFACE +
+ strlcpy(iface.ifname, (char *)paddr, IF_NAMESIZE) + 1;
+ /* Assume direct match */
+ /* FIXME: Add interface pattern matching */
+ xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
+ break;
+
+ default:
+ return (0);
+ }
+
+ if (xent != NULL) {
+ *val = xent->value;
+ return (1);
+ }
+ return (0);
+}
+
static int
count_table_entry(struct radix_node *rn, void *arg)
{
@@ -244,10 +605,11 @@ ipfw_count_table(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt)
{
struct radix_node_head *rnh;
- if (tbl >= IPFW_TABLES_MAX)
+ if (tbl >= V_fw_tables_max)
return (EINVAL);
- rnh = ch->tables[tbl];
*cnt = 0;
+ if ((rnh = ch->tables[tbl]) == NULL)
+ return (0);
rnh->rnh_walktree(rnh, count_table_entry, cnt);
return (0);
}
@@ -278,11 +640,124 @@ ipfw_dump_table(struct ip_fw_chain *ch, ipfw_table *tbl)
{
struct radix_node_head *rnh;
- if (tbl->tbl >= IPFW_TABLES_MAX)
+ if (tbl->tbl >= V_fw_tables_max)
return (EINVAL);
- rnh = ch->tables[tbl->tbl];
tbl->cnt = 0;
+ if ((rnh = ch->tables[tbl->tbl]) == NULL)
+ return (0);
rnh->rnh_walktree(rnh, dump_table_entry, tbl);
return (0);
}
+
+static int
+count_table_xentry(struct radix_node *rn, void *arg)
+{
+ uint32_t * const cnt = arg;
+
+ (*cnt) += sizeof(ipfw_table_xentry);
+ return (0);
+}
+
+int
+ipfw_count_xtable(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt)
+{
+ struct radix_node_head *rnh;
+
+ if (tbl >= V_fw_tables_max)
+ return (EINVAL);
+ *cnt = 0;
+ if ((rnh = ch->tables[tbl]) != NULL)
+ rnh->rnh_walktree(rnh, count_table_xentry, cnt);
+ if ((rnh = ch->xtables[tbl]) != NULL)
+ rnh->rnh_walktree(rnh, count_table_xentry, cnt);
+ /* Return zero if table is empty */
+ if (*cnt > 0)
+ (*cnt) += sizeof(ipfw_xtable);
+ return (0);
+}
+
+
+static int
+dump_table_xentry_base(struct radix_node *rn, void *arg)
+{
+ struct table_entry * const n = (struct table_entry *)rn;
+ ipfw_xtable * const tbl = arg;
+ ipfw_table_xentry *xent;
+
+ /* Out of memory, returning */
+ if (tbl->cnt == tbl->size)
+ return (1);
+ xent = &tbl->xent[tbl->cnt];
+ xent->len = sizeof(ipfw_table_xentry);
+ xent->tbl = tbl->tbl;
+ if (in_nullhost(n->mask.sin_addr))
+ xent->masklen = 0;
+ else
+ xent->masklen = 33 - ffs(ntohl(n->mask.sin_addr.s_addr));
+ /* Save IPv4 address as deprecated IPv6 compatible */
+ xent->k.addr6.s6_addr32[3] = n->addr.sin_addr.s_addr;
+ xent->value = n->value;
+ tbl->cnt++;
+ return (0);
+}
+
+static int
+dump_table_xentry_extended(struct radix_node *rn, void *arg)
+{
+ struct table_xentry * const n = (struct table_xentry *)rn;
+ ipfw_xtable * const tbl = arg;
+ ipfw_table_xentry *xent;
+#ifdef INET6
+ int i;
+ uint32_t *v;
+#endif
+ /* Out of memory, returning */
+ if (tbl->cnt == tbl->size)
+ return (1);
+ xent = &tbl->xent[tbl->cnt];
+ xent->len = sizeof(ipfw_table_xentry);
+ xent->tbl = tbl->tbl;
+
+ switch (tbl->type) {
+#ifdef INET6
+ case IPFW_TABLE_CIDR:
+ /* Count IPv6 mask */
+ v = (uint32_t *)&n->m.mask6.sin6_addr;
+ for (i = 0; i < sizeof(struct in6_addr) / 4; i++, v++)
+ xent->masklen += bitcount32(*v);
+ memcpy(&xent->k, &n->a.addr6.sin6_addr, sizeof(struct in6_addr));
+ break;
+#endif
+ case IPFW_TABLE_INTERFACE:
+ /* Assume exact mask */
+ xent->masklen = 8 * IF_NAMESIZE;
+ memcpy(&xent->k, &n->a.iface.ifname, IF_NAMESIZE);
+ break;
+
+ default:
+ /* unknown, skip entry */
+ return (0);
+ }
+
+ xent->value = n->value;
+ tbl->cnt++;
+ return (0);
+}
+
+int
+ipfw_dump_xtable(struct ip_fw_chain *ch, ipfw_xtable *tbl)
+{
+ struct radix_node_head *rnh;
+
+ if (tbl->tbl >= V_fw_tables_max)
+ return (EINVAL);
+ tbl->cnt = 0;
+ tbl->type = ch->tabletype[tbl->tbl];
+ if ((rnh = ch->tables[tbl->tbl]) != NULL)
+ rnh->rnh_walktree(rnh, dump_table_xentry_base, tbl);
+ if ((rnh = ch->xtables[tbl->tbl]) != NULL)
+ rnh->rnh_walktree(rnh, dump_table_xentry_extended, tbl);
+ return (0);
+}
+
/* end of file */
diff --git a/freebsd/sys/netinet/libalias/alias.h b/freebsd/sys/netinet/libalias/alias.h
index 2aed8293..b2615c90 100644
--- a/freebsd/sys/netinet/libalias/alias.h
+++ b/freebsd/sys/netinet/libalias/alias.h
@@ -220,6 +220,12 @@ struct mbuf *m_megapullup(struct mbuf *, int);
*/
#define PKT_ALIAS_REVERSE 0x80
+/*
+ * If PKT_ALIAS_SKIP_GLOBAL is set, nat instance is not checked for matching
+ * states in 'ipfw nat global' rule.
+ */
+#define PKT_ALIAS_SKIP_GLOBAL 0x200
+
/* Function return codes. */
#define PKT_ALIAS_ERROR -1
#define PKT_ALIAS_OK 1
diff --git a/freebsd/sys/netinet/libalias/alias_db.c b/freebsd/sys/netinet/libalias/alias_db.c
index 35b1846b..60a8e06f 100644
--- a/freebsd/sys/netinet/libalias/alias_db.c
+++ b/freebsd/sys/netinet/libalias/alias_db.c
@@ -554,10 +554,6 @@ static void IncrementalCleanup(struct libalias *);
static void DeleteLink(struct alias_link *);
static struct alias_link *
-AddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr,
- u_short, u_short, int, int);
-
-static struct alias_link *
ReLink(struct alias_link *,
struct in_addr, struct in_addr, struct in_addr,
u_short, u_short, int, int);
@@ -574,9 +570,6 @@ static struct alias_link *
#define ALIAS_PORT_MASK_EVEN 0x07ffe
#define GET_NEW_PORT_MAX_ATTEMPTS 20
-#define GET_ALIAS_PORT -1
-#define GET_ALIAS_ID GET_ALIAS_PORT
-
#define FIND_EVEN_ALIAS_BASE 1
/* GetNewPort() allocates port numbers. Note that if a port number
@@ -939,17 +932,12 @@ DeleteLink(struct alias_link *lnk)
}
-static struct alias_link *
-AddLink(struct libalias *la, struct in_addr src_addr,
- struct in_addr dst_addr,
- struct in_addr alias_addr,
- u_short src_port,
- u_short dst_port,
- int alias_port_param, /* if less than zero, alias */
- int link_type)
-{ /* port will be automatically *//* chosen.
- * If greater than */
- u_int start_point; /* zero, equal to alias port */
+struct alias_link *
+AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr,
+ struct in_addr alias_addr, u_short src_port, u_short dst_port,
+ int alias_port_param, int link_type)
+{
+ u_int start_point;
struct alias_link *lnk;
LIBALIAS_LOCK_ASSERT(la);
@@ -2494,9 +2482,18 @@ LibAliasInit(struct libalias *la)
#endif
if (la == NULL) {
+#ifdef _KERNEL
+#ifndef __rtems__
+#undef malloc /* XXX: ugly */
+ la = malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO);
+#else /* __rtems__ */
+ la = _bsd_malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO);
+#endif /* __rtems__ */
+#else
la = calloc(sizeof *la, 1);
if (la == NULL)
return (la);
+#endif
#ifndef _KERNEL /* kernel cleans up on module unload */
if (LIST_EMPTY(&instancehead))
diff --git a/freebsd/sys/netinet/libalias/alias_ftp.c b/freebsd/sys/netinet/libalias/alias_ftp.c
index c8a09413..43411d41 100644
--- a/freebsd/sys/netinet/libalias/alias_ftp.c
+++ b/freebsd/sys/netinet/libalias/alias_ftp.c
@@ -102,38 +102,68 @@ __FBSDID("$FreeBSD$");
#define FTP_CONTROL_PORT_NUMBER 21
static void
-AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
- int maxpacketsize);
+AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
+ int maxpacketsize);
+static void
+AliasHandleFtpIn(struct libalias *, struct ip *, struct alias_link *);
-static int
-fingerprint(struct libalias *la, struct alias_data *ah)
+static int
+fingerprint_out(struct libalias *la, struct alias_data *ah)
{
- if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
- ah->maxpktsize == 0)
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
+ ah->maxpktsize == 0)
return (-1);
- if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER
- || ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
+ if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER ||
+ ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
return (0);
return (-1);
}
-static int
-protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
+static int
+fingerprint_in(struct libalias *la, struct alias_data *ah)
+{
+
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
+ return (-1);
+ if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER ||
+ ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
+ return (0);
+ return (-1);
+}
+
+static int
+protohandler_out(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
-
+
AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpktsize);
return (0);
}
+
+static int
+protohandler_in(struct libalias *la, struct ip *pip, struct alias_data *ah)
+{
+
+ AliasHandleFtpIn(la, pip, ah->lnk);
+ return (0);
+}
+
struct proto_handler handlers[] = {
- {
- .pri = 80,
- .dir = OUT,
- .proto = TCP,
- .fingerprint = &fingerprint,
- .protohandler = &protohandler
- },
+ {
+ .pri = 80,
+ .dir = OUT,
+ .proto = TCP,
+ .fingerprint = &fingerprint_out,
+ .protohandler = &protohandler_out
+ },
+ {
+ .pri = 80,
+ .dir = IN,
+ .proto = TCP,
+ .fingerprint = &fingerprint_in,
+ .protohandler = &protohandler_in
+ },
{ EOH }
};
@@ -258,6 +288,57 @@ AliasHandleFtpOut(
}
}
+static void
+AliasHandleFtpIn(struct libalias *la,
+ struct ip *pip, /* IP packet to examine/patch */
+ struct alias_link *lnk) /* The link to go through (aliased port) */
+{
+ int hlen, tlen, dlen, pflags;
+ char *sptr;
+ struct tcphdr *tc;
+
+ /* Calculate data length of TCP packet */
+ tc = (struct tcphdr *)ip_next(pip);
+ hlen = (pip->ip_hl + tc->th_off) << 2;
+ tlen = ntohs(pip->ip_len);
+ dlen = tlen - hlen;
+
+ /* Place string pointer and beginning of data */
+ sptr = (char *)pip;
+ sptr += hlen;
+
+ /*
+ * Check that data length is not too long and previous message was
+ * properly terminated with CRLF.
+ */
+ pflags = GetProtocolFlags(lnk);
+ if (dlen <= MAX_MESSAGE_SIZE && (pflags & WAIT_CRLF) == 0 &&
+ ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER &&
+ (ParseFtpPortCommand(la, sptr, dlen) != 0 ||
+ ParseFtpEprtCommand(la, sptr, dlen) != 0)) {
+ /*
+ * Alias active mode client requesting data from server
+ * behind NAT. We need to alias server->client connection
+ * to external address client is connecting to.
+ */
+ AddLink(la, GetOriginalAddress(lnk), la->true_addr,
+ GetAliasAddress(lnk), htons(FTP_CONTROL_PORT_NUMBER - 1),
+ htons(la->true_port), GET_ALIAS_PORT, IPPROTO_TCP);
+ }
+ /* Track the msgs which are CRLF term'd for PORT/PASV FW breach */
+ if (dlen) {
+ sptr = (char *)pip; /* start over at beginning */
+ tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may
+ * have grown.
+ */
+ if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n')
+ pflags &= ~WAIT_CRLF;
+ else
+ pflags |= WAIT_CRLF;
+ SetProtocolFlags(lnk, pflags);
+ }
+}
+
static int
ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
{
@@ -578,9 +659,10 @@ NewFtpMessage(struct libalias *la, struct ip *pip,
if (la->true_port < IPPORT_RESERVED)
return;
-/* Establish link to address and port found in FTP control message. */
- ftp_lnk = FindUdpTcpOut(la, la->true_addr, GetDestAddress(lnk),
- htons(la->true_port), 0, IPPROTO_TCP, 1);
+ /* Establish link to address and port found in FTP control message. */
+ ftp_lnk = AddLink(la, la->true_addr, GetDestAddress(lnk),
+ GetAliasAddress(lnk), htons(la->true_port), 0, GET_ALIAS_PORT,
+ IPPROTO_TCP);
if (ftp_lnk != NULL) {
int slen, hlen, tlen, dlen;
diff --git a/freebsd/sys/netinet/libalias/alias_local.h b/freebsd/sys/netinet/libalias/alias_local.h
index 68839da3..307442cd 100644
--- a/freebsd/sys/netinet/libalias/alias_local.h
+++ b/freebsd/sys/netinet/libalias/alias_local.h
@@ -67,6 +67,9 @@
#define LINK_TABLE_OUT_SIZE 4001
#define LINK_TABLE_IN_SIZE 4001
+#define GET_ALIAS_PORT -1
+#define GET_ALIAS_ID GET_ALIAS_PORT
+
struct proxy_entry;
struct libalias {
@@ -249,6 +252,10 @@ DifferentialChecksum(u_short * _cksum, void * _new, void * _old, int _n);
/* Internal data access */
struct alias_link *
+AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr,
+ struct in_addr alias_addr, u_short src_port, u_short dst_port,
+ int alias_param, int link_type);
+struct alias_link *
FindIcmpIn(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr,
u_short _id_alias, int _create);
struct alias_link *
diff --git a/freebsd/sys/netinet/libalias/alias_mod.h b/freebsd/sys/netinet/libalias/alias_mod.h
index 995f61ac..e9dfc724 100644
--- a/freebsd/sys/netinet/libalias/alias_mod.h
+++ b/freebsd/sys/netinet/libalias/alias_mod.h
@@ -44,6 +44,9 @@ MALLOC_DECLARE(M_ALIAS);
#define calloc(x, n) malloc(x*n)
#define free(x) free(x, M_ALIAS)
#else /* __rtems__ */
+#undef malloc
+#undef calloc
+#undef free
#define malloc(x) _bsd_malloc(x, M_ALIAS, M_NOWAIT|M_ZERO)
#define calloc(x, n) malloc(x*n)
#define free(x) _bsd_free(x, M_ALIAS)
diff --git a/freebsd/sys/netinet/libalias/alias_proxy.c b/freebsd/sys/netinet/libalias/alias_proxy.c
index cbd4b99b..89eb2324 100644
--- a/freebsd/sys/netinet/libalias/alias_proxy.c
+++ b/freebsd/sys/netinet/libalias/alias_proxy.c
@@ -212,13 +212,13 @@ RuleAdd(struct libalias *la, struct proxy_entry *entry)
LIBALIAS_LOCK_ASSERT(la);
+ entry->la = la;
if (la->proxyList == NULL) {
la->proxyList = entry;
entry->last = NULL;
entry->next = NULL;
return;
}
- entry->la = la;
rule_index = entry->rule_index;
ptr = la->proxyList;
diff --git a/freebsd/sys/netinet/libalias/alias_sctp.c b/freebsd/sys/netinet/libalias/alias_sctp.c
index fed592f0..ac871fc9 100644
--- a/freebsd/sys/netinet/libalias/alias_sctp.c
+++ b/freebsd/sys/netinet/libalias/alias_sctp.c
@@ -1931,7 +1931,7 @@ UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, str
* @brief Process SCTP message while association is in the process of closing
*
* This function waits for a SHUT-COMP to close the association. Depending on
- * the the setting of sysctl_holddown_timer it may not remove the association
+ * the setting of sysctl_holddown_timer it may not remove the association
* immediately, but leave it up until SN_X_T(la). Only SHUT-COMP, SHUT-ACK, and
* ABORT packets are permitted in this state. All other packets are dropped.
*
diff --git a/freebsd/sys/netinet/raw_ip.c b/freebsd/sys/netinet/raw_ip.c
index 408b529b..d70d8323 100644
--- a/freebsd/sys/netinet/raw_ip.c
+++ b/freebsd/sys/netinet/raw_ip.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_systm.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_mroute.h>
@@ -718,7 +719,7 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
/*
* in_ifscrub kills the interface route.
*/
- in_ifscrub(ia->ia_ifp, ia);
+ in_ifscrub(ia->ia_ifp, ia, 0);
/*
* in_ifadown gets rid of all the rest of the
* routes. This is not quite the right thing
@@ -753,10 +754,18 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
|| (ifp->if_flags & IFF_POINTOPOINT))
flags |= RTF_HOST;
+ err = ifa_del_loopback_route((struct ifaddr *)ia, sa);
+ if (err == 0)
+ ia->ia_flags &= ~IFA_RTSELF;
+
err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
if (err == 0)
ia->ia_flags |= IFA_ROUTE;
+
err = ifa_add_loopback_route((struct ifaddr *)ia, sa);
+ if (err == 0)
+ ia->ia_flags |= IFA_RTSELF;
+
ifa_free(&ia->ia_ifa);
break;
}
@@ -1096,7 +1105,8 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
return (error);
}
-SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, 0, 0,
+SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist,
+ CTLTYPE_OPAQUE | CTLFLAG_RD, NULL, 0,
rip_pcblist, "S,xinpcb", "List of active raw IP sockets");
struct pr_usrreqs rip_usrreqs = {
diff --git a/freebsd/sys/netinet/sctp.h b/freebsd/sys/netinet/sctp.h
index 09e2e465..03cf86a3 100644
--- a/freebsd/sys/netinet/sctp.h
+++ b/freebsd/sys/netinet/sctp.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -27,7 +29,6 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp.h,v 1.18 2005/03/06 16:04:16 itojun Exp $ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -35,6 +36,7 @@ __FBSDID("$FreeBSD$");
#ifndef _NETINET_SCTP_H_
#define _NETINET_SCTP_H_
+
#include <rtems/bsd/sys/types.h>
@@ -89,7 +91,7 @@ struct sctp_paramhdr {
#define SCTP_PEER_ADDR_PARAMS 0x0000000a
#define SCTP_DEFAULT_SEND_PARAM 0x0000000b
/* ancillary data/notification interest options */
-#define SCTP_EVENTS 0x0000000c
+#define SCTP_EVENTS 0x0000000c /* deprecated */
/* Without this applied we will give V4 and V6 addresses on a V6 socket */
#define SCTP_I_WANT_MAPPED_V4_ADDR 0x0000000d
#define SCTP_MAXSEG 0x0000000e
@@ -112,6 +114,13 @@ struct sctp_paramhdr {
#define SCTP_EXPLICIT_EOR 0x0000001b
#define SCTP_REUSE_PORT 0x0000001c /* rw */
#define SCTP_AUTH_DEACTIVATE_KEY 0x0000001d
+#define SCTP_EVENT 0x0000001e
+#define SCTP_RECVRCVINFO 0x0000001f
+#define SCTP_RECVNXTINFO 0x00000020
+#define SCTP_DEFAULT_SNDINFO 0x00000021
+#define SCTP_DEFAULT_PRINFO 0x00000022
+#define SCTP_PEER_ADDR_THLDS 0x00000023
+#define SCTP_REMOTE_UDP_ENCAPS_PORT 0x00000024
/*
* read-only options
@@ -146,8 +155,22 @@ struct sctp_paramhdr {
* field.
*/
-/* these should probably go into sockets API */
-#define SCTP_RESET_STREAMS 0x00001004 /* wo */
+#define SCTP_ENABLE_STREAM_RESET 0x00000900 /* struct
+ * sctp_assoc_value */
+#define SCTP_RESET_STREAMS 0x00000901 /* struct
+ * sctp_reset_streams */
+#define SCTP_RESET_ASSOC 0x00000902 /* sctp_assoc_t */
+#define SCTP_ADD_STREAMS 0x00000903 /* struct
+ * sctp_add_streams */
+
+/* For enable stream reset */
+#define SCTP_ENABLE_RESET_STREAM_REQ 0x00000001
+#define SCTP_ENABLE_RESET_ASSOC_REQ 0x00000002
+#define SCTP_ENABLE_CHANGE_ASSOC_REQ 0x00000004
+#define SCTP_ENABLE_VALUE_MASK 0x00000007
+/* For reset streams */
+#define SCTP_STREAM_RESET_INCOMING 0x00000001
+#define SCTP_STREAM_RESET_OUTGOING 0x00000002
/* here on down are more implementation specific */
@@ -158,7 +181,11 @@ struct sctp_paramhdr {
#define SCTP_CMT_USE_DAC 0x00001201
/* JRS - Pluggable Congestion Control Socket option */
#define SCTP_PLUGGABLE_CC 0x00001202
-
+/* RS - Pluggable Stream Scheduling Socket option */
+#define SCTP_PLUGGABLE_SS 0x00001203
+#define SCTP_SS_VALUE 0x00001204
+#define SCTP_CC_OPTION 0x00001205 /* Options for CC
+ * modules */
/* read only */
#define SCTP_GET_SNDBUF_USE 0x00001101
#define SCTP_GET_STAT_LOG 0x00001103
@@ -238,8 +265,6 @@ struct sctp_paramhdr {
#define SCTP_PEELOFF 0x0000800a
/* the real worker for sctp_getaddrlen() */
#define SCTP_GET_ADDR_LEN 0x0000800b
-/* temporary workaround for Apple listen() issue, no args used */
-#define SCTP_LISTEN_FIX 0x0000800c
/* Debug things that need to be purged */
#define SCTP_SET_INITIAL_DBG_SEQ 0x00009f00
@@ -252,6 +277,35 @@ struct sctp_paramhdr {
#define SCTP_CC_HSTCP 0x00000001
/* HTCP Congestion Control */
#define SCTP_CC_HTCP 0x00000002
+/* RTCC Congestion Control - RFC2581 plus */
+#define SCTP_CC_RTCC 0x00000003
+
+#define SCTP_CC_OPT_RTCC_SETMODE 0x00002000
+#define SCTP_CC_OPT_USE_DCCC_ECN 0x00002001
+#define SCTP_CC_OPT_STEADY_STEP 0x00002002
+
+#define SCTP_CMT_OFF 0
+#define SCTP_CMT_BASE 1
+#define SCTP_CMT_RPV1 2
+#define SCTP_CMT_RPV2 3
+#define SCTP_CMT_MPTCP 4
+#define SCTP_CMT_MAX SCTP_CMT_MPTCP
+
+/* RS - Supported stream scheduling modules for pluggable
+ * stream scheduling
+ */
+/* Default simple round-robin */
+#define SCTP_SS_DEFAULT 0x00000000
+/* Real round-robin */
+#define SCTP_SS_ROUND_ROBIN 0x00000001
+/* Real round-robin per packet */
+#define SCTP_SS_ROUND_ROBIN_PACKET 0x00000002
+/* Priority */
+#define SCTP_SS_PRIORITY 0x00000003
+/* Fair Bandwidth */
+#define SCTP_SS_FAIR_BANDWITH 0x00000004
+/* First-come, first-serve */
+#define SCTP_SS_FIRST_COME 0x00000005
/* fragment interleave constants
@@ -398,6 +452,10 @@ struct sctp_error_unrecognized_chunk {
#define SCTP_BADCRC 0x02
#define SCTP_PACKET_TRUNCATED 0x04
+/* Flag for ECN -CWR */
+#define SCTP_CWR_REDUCE_OVERRIDE 0x01
+#define SCTP_CWR_IN_SAME_WINDOW 0x02
+
#define SCTP_SAT_NETWORK_MIN 400 /* min ms for RTT to set satellite
* time */
#define SCTP_SAT_NETWORK_BURST_INCR 2 /* how many times to multiply maxburst
@@ -442,55 +500,64 @@ struct sctp_error_unrecognized_chunk {
#define SCTP_PCB_FLAGS_SOCKET_GONE 0x10000000
#define SCTP_PCB_FLAGS_SOCKET_ALLGONE 0x20000000
#define SCTP_PCB_FLAGS_SOCKET_CANT_READ 0x40000000
+
/* flags to copy to new PCB */
#define SCTP_PCB_COPY_FLAGS (SCTP_PCB_FLAGS_BOUNDALL|\
SCTP_PCB_FLAGS_WAKEINPUT|\
SCTP_PCB_FLAGS_BOUND_V6)
-
/*
* PCB Features (in sctp_features bitmask)
*/
-#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x00000002
-#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x00000004
-#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x00000008
-#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x00000010
-#define SCTP_PCB_FLAGS_DO_ASCONF 0x00000020
-#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x00000040
-#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x00000080
+#define SCTP_PCB_FLAGS_DO_NOT_PMTUD 0x00000001
+#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x00000002 /* deprecated */
+#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x00000004
+#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x00000008
+#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x00000010
+#define SCTP_PCB_FLAGS_DO_ASCONF 0x00000020
+#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x00000040
+#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x00000080
/* socket options */
-#define SCTP_PCB_FLAGS_NODELAY 0x00000100
-#define SCTP_PCB_FLAGS_AUTOCLOSE 0x00000200
-#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x00000400
-#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x00000800
-#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x00001000
-#define SCTP_PCB_FLAGS_RECVPEERERR 0x00002000
-#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT 0x00004000
-#define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT 0x00008000
-#define SCTP_PCB_FLAGS_ADAPTATIONEVNT 0x00010000
-#define SCTP_PCB_FLAGS_PDAPIEVNT 0x00020000
-#define SCTP_PCB_FLAGS_AUTHEVNT 0x00040000
-#define SCTP_PCB_FLAGS_STREAM_RESETEVNT 0x00080000
-#define SCTP_PCB_FLAGS_NO_FRAGMENT 0x00100000
-#define SCTP_PCB_FLAGS_EXPLICIT_EOR 0x00400000
-#define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x00800000
-#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x01000000
-#define SCTP_PCB_FLAGS_PORTREUSE 0x02000000
-#define SCTP_PCB_FLAGS_DRYEVNT 0x04000000
+#define SCTP_PCB_FLAGS_NODELAY 0x00000100
+#define SCTP_PCB_FLAGS_AUTOCLOSE 0x00000200
+#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x00000400 /* deprecated */
+#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x00000800
+#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x00001000
+#define SCTP_PCB_FLAGS_RECVPEERERR 0x00002000
+#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT 0x00004000 /* deprecated */
+#define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT 0x00008000
+#define SCTP_PCB_FLAGS_ADAPTATIONEVNT 0x00010000
+#define SCTP_PCB_FLAGS_PDAPIEVNT 0x00020000
+#define SCTP_PCB_FLAGS_AUTHEVNT 0x00040000
+#define SCTP_PCB_FLAGS_STREAM_RESETEVNT 0x00080000
+#define SCTP_PCB_FLAGS_NO_FRAGMENT 0x00100000
+#define SCTP_PCB_FLAGS_EXPLICIT_EOR 0x00400000
+#define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x00800000
+#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x01000000
+#define SCTP_PCB_FLAGS_PORTREUSE 0x02000000
+#define SCTP_PCB_FLAGS_DRYEVNT 0x04000000
+#define SCTP_PCB_FLAGS_RECVRCVINFO 0x08000000
+#define SCTP_PCB_FLAGS_RECVNXTINFO 0x10000000
+#define SCTP_PCB_FLAGS_ASSOC_RESETEVNT 0x20000000
+#define SCTP_PCB_FLAGS_STREAM_CHANGEEVNT 0x40000000
+#define SCTP_PCB_FLAGS_RECVNSENDFAILEVNT 0x80000000
+
/*-
* mobility_features parameters (by micchie).Note
* these features are applied against the
* sctp_mobility_features flags.. not the sctp_features
* flags.
*/
-#define SCTP_MOBILITY_BASE 0x00000001
-#define SCTP_MOBILITY_FASTHANDOFF 0x00000002
-#define SCTP_MOBILITY_PRIM_DELETED 0x00000004
+#define SCTP_MOBILITY_BASE 0x00000001
+#define SCTP_MOBILITY_FASTHANDOFF 0x00000002
+#define SCTP_MOBILITY_PRIM_DELETED 0x00000004
#define SCTP_SMALLEST_PMTU 512 /* smallest pmtu allowed when disabling PMTU
* discovery */
+#undef SCTP_PACKED
+
#include <netinet/sctp_uio.h>
/* This dictates the size of the packet
@@ -517,7 +584,6 @@ struct sctp_error_unrecognized_chunk {
#define SCTP_BLK_LOGGING_ENABLE 0x00000001
#define SCTP_CWND_MONITOR_ENABLE 0x00000002
#define SCTP_CWND_LOGGING_ENABLE 0x00000004
-#define SCTP_EARLYFR_LOGGING_ENABLE 0x00000010
#define SCTP_FLIGHT_LOGGING_ENABLE 0x00000020
#define SCTP_FR_LOGGING_ENABLE 0x00000040
#define SCTP_LOCK_LOGGING_ENABLE 0x00000080
@@ -525,25 +591,22 @@ struct sctp_error_unrecognized_chunk {
#define SCTP_MBCNT_LOGGING_ENABLE 0x00000200
#define SCTP_MBUF_LOGGING_ENABLE 0x00000400
#define SCTP_NAGLE_LOGGING_ENABLE 0x00000800
-#define SCTP_RECV_RWND_LOGGING_ENABLE 0x00001000
+#define SCTP_RECV_RWND_LOGGING_ENABLE 0x00001000
#define SCTP_RTTVAR_LOGGING_ENABLE 0x00002000
#define SCTP_SACK_LOGGING_ENABLE 0x00004000
-#define SCTP_SACK_RWND_LOGGING_ENABLE 0x00008000
+#define SCTP_SACK_RWND_LOGGING_ENABLE 0x00008000
#define SCTP_SB_LOGGING_ENABLE 0x00010000
#define SCTP_STR_LOGGING_ENABLE 0x00020000
#define SCTP_WAKE_LOGGING_ENABLE 0x00040000
#define SCTP_LOG_MAXBURST_ENABLE 0x00080000
#define SCTP_LOG_RWND_ENABLE 0x00100000
-#define SCTP_LOG_SACK_ARRIVALS_ENABLE 0x00200000
-#define SCTP_LTRACE_CHUNK_ENABLE 0x00400000
-#define SCTP_LTRACE_ERROR_ENABLE 0x00800000
-#define SCTP_LAST_PACKET_TRACING 0x01000000
-#define SCTP_THRESHOLD_LOGGING 0x02000000
-#define SCTP_LOG_AT_SEND_2_SCTP 0x04000000
-#define SCTP_LOG_AT_SEND_2_OUTQ 0x08000000
-#define SCTP_LOG_TRY_ADVANCE 0x10000000
-
-
-#undef SCTP_PACKED
+#define SCTP_LOG_SACK_ARRIVALS_ENABLE 0x00200000
+#define SCTP_LTRACE_CHUNK_ENABLE 0x00400000
+#define SCTP_LTRACE_ERROR_ENABLE 0x00800000
+#define SCTP_LAST_PACKET_TRACING 0x01000000
+#define SCTP_THRESHOLD_LOGGING 0x02000000
+#define SCTP_LOG_AT_SEND_2_SCTP 0x04000000
+#define SCTP_LOG_AT_SEND_2_OUTQ 0x08000000
+#define SCTP_LOG_TRY_ADVANCE 0x10000000
#endif /* !_NETINET_SCTP_H_ */
diff --git a/freebsd/sys/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c
index 3c24b75d..3e51ed72 100644
--- a/freebsd/sys/netinet/sctp_asconf.c
+++ b/freebsd/sys/netinet/sctp_asconf.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,10 +32,9 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_asconf.c,v 1.24 2005/03/06 16:04:16 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+
#include <netinet/sctp_os.h>
#include <netinet/sctp_var.h>
#include <netinet/sctp_sysctl.h>
@@ -49,53 +50,10 @@ __FBSDID("$FreeBSD$");
* SCTP_DEBUG_ASCONF1: protocol info, general info and errors
* SCTP_DEBUG_ASCONF2: detailed info
*/
-#ifdef SCTP_DEBUG
-#endif /* SCTP_DEBUG */
-
-
-static void
-sctp_asconf_get_source_ip(struct mbuf *m, struct sockaddr *sa)
-{
- struct ip *iph;
- struct sockaddr_in *sin;
-
-#ifdef INET6
- struct sockaddr_in6 *sin6;
-
-#endif
-
- iph = mtod(m, struct ip *);
- if (iph->ip_v == IPVERSION) {
- /* IPv4 source */
- sin = (struct sockaddr_in *)sa;
- bzero(sin, sizeof(*sin));
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(struct sockaddr_in);
- sin->sin_port = 0;
- sin->sin_addr.s_addr = iph->ip_src.s_addr;
- return;
- }
-#ifdef INET6
- else if (iph->ip_v == (IPV6_VERSION >> 4)) {
- /* IPv6 source */
- struct ip6_hdr *ip6;
- sin6 = (struct sockaddr_in6 *)sa;
- bzero(sin6, sizeof(*sin6));
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- sin6->sin6_port = 0;
- ip6 = mtod(m, struct ip6_hdr *);
- sin6->sin6_addr = ip6->ip6_src;
- return;
- }
-#endif /* INET6 */
- else
- return;
-}
/*
- * draft-ietf-tsvwg-addip-sctp
+ * RFC 5061
*
* An ASCONF parameter queue exists per asoc which holds the pending address
* operations. Lists are updated upon receipt of ASCONF-ACK.
@@ -128,7 +86,7 @@ sctp_asconf_success_response(uint32_t id)
if (m_reply == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1,
"asconf_success_response: couldn't get mbuf!\n");
- return NULL;
+ return (NULL);
}
aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
aph->correlation_id = id;
@@ -137,7 +95,7 @@ sctp_asconf_success_response(uint32_t id)
SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
aph->ph.param_length = htons(aph->ph.param_length);
- return m_reply;
+ return (m_reply);
}
static struct mbuf *
@@ -156,7 +114,7 @@ sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv,
if (m_reply == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1,
"asconf_error_response: couldn't get mbuf!\n");
- return NULL;
+ return (NULL);
}
aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
error = (struct sctp_error_cause *)(aph + 1);
@@ -173,7 +131,7 @@ sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv,
"asconf_error_response: tlv_length (%xh) too big\n",
tlv_length);
sctp_m_freem(m_reply); /* discard */
- return NULL;
+ return (NULL);
}
if (error_tlv != NULL) {
tlv = (uint8_t *) (error + 1);
@@ -183,59 +141,70 @@ sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv,
error->length = htons(error->length);
aph->ph.param_length = htons(aph->ph.param_length);
- return m_reply;
+ return (m_reply);
}
static struct mbuf *
-sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
- struct sctp_tcb *stcb, int response_required)
+sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *aph,
+ struct sctp_tcb *stcb, int send_hb, int response_required)
{
+ struct sctp_nets *net;
struct mbuf *m_reply = NULL;
- struct sockaddr_storage sa_source, sa_store;
- struct sctp_ipv4addr_param *v4addr;
+ struct sockaddr_storage sa_store;
+ struct sctp_paramhdr *ph;
uint16_t param_type, param_length, aparam_length;
struct sockaddr *sa;
- struct sockaddr_in *sin;
int zero_address = 0;
+ int bad_address = 0;
+
+#ifdef INET
+ struct sockaddr_in *sin;
+ struct sctp_ipv4addr_param *v4addr;
+#endif
#ifdef INET6
struct sockaddr_in6 *sin6;
struct sctp_ipv6addr_param *v6addr;
-#endif /* INET6 */
+#endif
aparam_length = ntohs(aph->ph.param_length);
- v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
-#ifdef INET6
- v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
-#endif /* INET6 */
- param_type = ntohs(v4addr->ph.param_type);
- param_length = ntohs(v4addr->ph.param_length);
+ ph = (struct sctp_paramhdr *)(aph + 1);
+ param_type = ntohs(ph->param_type);
+ param_length = ntohs(ph->param_length);
sa = (struct sockaddr *)&sa_store;
switch (param_type) {
+#ifdef INET
case SCTP_IPV4_ADDRESS:
if (param_length != sizeof(struct sctp_ipv4addr_param)) {
/* invalid param size */
- return NULL;
+ return (NULL);
}
+ v4addr = (struct sctp_ipv4addr_param *)ph;
sin = (struct sockaddr_in *)&sa_store;
bzero(sin, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_port = stcb->rport;
sin->sin_addr.s_addr = v4addr->addr;
+ if ((sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
+ bad_address = 1;
+ }
if (sin->sin_addr.s_addr == INADDR_ANY)
zero_address = 1;
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
break;
- case SCTP_IPV6_ADDRESS:
+#endif
#ifdef INET6
+ case SCTP_IPV6_ADDRESS:
if (param_length != sizeof(struct sctp_ipv6addr_param)) {
/* invalid param size */
- return NULL;
+ return (NULL);
}
+ v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = (struct sockaddr_in6 *)&sa_store;
bzero(sin6, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
@@ -243,38 +212,35 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
sin6->sin6_port = stcb->rport;
memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
sizeof(struct in6_addr));
+ if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+ bad_address = 1;
+ }
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
zero_address = 1;
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
-#else
- /* IPv6 not enabled! */
- /* FIX ME: currently sends back an invalid param error */
- m_reply = sctp_asconf_error_response(aph->correlation_id,
- SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, aparam_length);
- SCTPDBG(SCTP_DEBUG_ASCONF1,
- "process_asconf_add_ip: v6 disabled- skipping ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
- return m_reply;
-#endif
break;
+#endif
default:
m_reply = sctp_asconf_error_response(aph->correlation_id,
- SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
+ SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
aparam_length);
- return m_reply;
+ return (m_reply);
} /* end switch */
/* if 0.0.0.0/::0, add the source address instead */
if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
- sa = (struct sockaddr *)&sa_source;
- sctp_asconf_get_source_ip(m, sa);
+ sa = src;
SCTPDBG(SCTP_DEBUG_ASCONF1,
"process_asconf_add_ip: using source addr ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
+ SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
}
/* add the address */
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE,
+ if (bad_address) {
+ m_reply = sctp_asconf_error_response(aph->correlation_id,
+ SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
+ aparam_length);
+ } else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
SCTP_ADDR_DYNAMIC_ADDED) != 0) {
SCTPDBG(SCTP_DEBUG_ASCONF1,
"process_asconf_add_ip: error adding address\n");
@@ -288,13 +254,14 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
m_reply =
sctp_asconf_success_response(aph->correlation_id);
}
- sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb,
- NULL, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1);
+ sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
- stcb, NULL);
+ stcb, net);
+ if (send_hb) {
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
+ }
}
-
- return m_reply;
+ return (m_reply);
}
static int
@@ -306,7 +273,7 @@ sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
src_net = sctp_findnet(stcb, src);
if (src_net == NULL) {
/* not found */
- return -1;
+ return (-1);
}
/* delete all destination addresses except the source */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -322,46 +289,47 @@ sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
(struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED);
}
}
- return 0;
+ return (0);
}
static struct mbuf *
-sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
+sctp_process_asconf_delete_ip(struct sockaddr *src,
+ struct sctp_asconf_paramhdr *aph,
struct sctp_tcb *stcb, int response_required)
{
struct mbuf *m_reply = NULL;
- struct sockaddr_storage sa_source, sa_store;
- struct sctp_ipv4addr_param *v4addr;
+ struct sockaddr_storage sa_store;
+ struct sctp_paramhdr *ph;
uint16_t param_type, param_length, aparam_length;
struct sockaddr *sa;
- struct sockaddr_in *sin;
int zero_address = 0;
int result;
+#ifdef INET
+ struct sockaddr_in *sin;
+ struct sctp_ipv4addr_param *v4addr;
+
+#endif
#ifdef INET6
struct sockaddr_in6 *sin6;
struct sctp_ipv6addr_param *v6addr;
-#endif /* INET6 */
-
- /* get the source IP address for src and 0.0.0.0/::0 delete checks */
- sctp_asconf_get_source_ip(m, (struct sockaddr *)&sa_source);
+#endif
aparam_length = ntohs(aph->ph.param_length);
- v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
-#ifdef INET6
- v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
-#endif /* INET6 */
- param_type = ntohs(v4addr->ph.param_type);
- param_length = ntohs(v4addr->ph.param_length);
+ ph = (struct sctp_paramhdr *)(aph + 1);
+ param_type = ntohs(ph->param_type);
+ param_length = ntohs(ph->param_length);
sa = (struct sockaddr *)&sa_store;
switch (param_type) {
+#ifdef INET
case SCTP_IPV4_ADDRESS:
if (param_length != sizeof(struct sctp_ipv4addr_param)) {
/* invalid param size */
- return NULL;
+ return (NULL);
}
+ v4addr = (struct sctp_ipv4addr_param *)ph;
sin = (struct sockaddr_in *)&sa_store;
bzero(sin, sizeof(*sin));
sin->sin_family = AF_INET;
@@ -374,12 +342,14 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
"process_asconf_delete_ip: deleting ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
break;
+#endif
+#ifdef INET6
case SCTP_IPV6_ADDRESS:
if (param_length != sizeof(struct sctp_ipv6addr_param)) {
/* invalid param size */
- return NULL;
+ return (NULL);
}
-#ifdef INET6
+ v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = (struct sockaddr_in6 *)&sa_store;
bzero(sin6, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
@@ -392,35 +362,27 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
SCTPDBG(SCTP_DEBUG_ASCONF1,
"process_asconf_delete_ip: deleting ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
-#else
- /* IPv6 not enabled! No "action" needed; just ack it */
- SCTPDBG(SCTP_DEBUG_ASCONF1,
- "process_asconf_delete_ip: v6 disabled- ignoring: ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
- /* just respond with a "success" ASCONF-ACK */
- return NULL;
-#endif
break;
+#endif
default:
m_reply = sctp_asconf_error_response(aph->correlation_id,
SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
aparam_length);
- return m_reply;
+ return (m_reply);
}
/* make sure the source address is not being deleted */
- if (sctp_cmpaddr(sa, (struct sockaddr *)&sa_source)) {
+ if (sctp_cmpaddr(sa, src)) {
/* trying to delete the source address! */
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete source addr\n");
m_reply = sctp_asconf_error_response(aph->correlation_id,
SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph,
aparam_length);
- return m_reply;
+ return (m_reply);
}
/* if deleting 0.0.0.0/::0, delete all addresses except src addr */
if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
- result = sctp_asconf_del_remote_addrs_except(stcb,
- (struct sockaddr *)&sa_source);
+ result = sctp_asconf_del_remote_addrs_except(stcb, src);
if (result) {
/* src address did not exist? */
@@ -434,7 +396,7 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
m_reply =
sctp_asconf_success_response(aph->correlation_id);
}
- return m_reply;
+ return (m_reply);
}
/* delete the address */
result = sctp_del_remote_addr(stcb, sa);
@@ -456,43 +418,46 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
/* notify upper layer */
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
}
- return m_reply;
+ return (m_reply);
}
static struct mbuf *
-sctp_process_asconf_set_primary(struct mbuf *m,
+sctp_process_asconf_set_primary(struct sockaddr *src,
struct sctp_asconf_paramhdr *aph,
struct sctp_tcb *stcb, int response_required)
{
struct mbuf *m_reply = NULL;
- struct sockaddr_storage sa_source, sa_store;
- struct sctp_ipv4addr_param *v4addr;
+ struct sockaddr_storage sa_store;
+ struct sctp_paramhdr *ph;
uint16_t param_type, param_length, aparam_length;
struct sockaddr *sa;
- struct sockaddr_in *sin;
int zero_address = 0;
+#ifdef INET
+ struct sockaddr_in *sin;
+ struct sctp_ipv4addr_param *v4addr;
+
+#endif
#ifdef INET6
struct sockaddr_in6 *sin6;
struct sctp_ipv6addr_param *v6addr;
-#endif /* INET6 */
+#endif
aparam_length = ntohs(aph->ph.param_length);
- v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
-#ifdef INET6
- v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
-#endif /* INET6 */
- param_type = ntohs(v4addr->ph.param_type);
- param_length = ntohs(v4addr->ph.param_length);
+ ph = (struct sctp_paramhdr *)(aph + 1);
+ param_type = ntohs(ph->param_type);
+ param_length = ntohs(ph->param_length);
sa = (struct sockaddr *)&sa_store;
switch (param_type) {
+#ifdef INET
case SCTP_IPV4_ADDRESS:
if (param_length != sizeof(struct sctp_ipv4addr_param)) {
/* invalid param size */
- return NULL;
+ return (NULL);
}
+ v4addr = (struct sctp_ipv4addr_param *)ph;
sin = (struct sockaddr_in *)&sa_store;
bzero(sin, sizeof(*sin));
sin->sin_family = AF_INET;
@@ -503,12 +468,14 @@ sctp_process_asconf_set_primary(struct mbuf *m,
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
break;
+#endif
+#ifdef INET6
case SCTP_IPV6_ADDRESS:
if (param_length != sizeof(struct sctp_ipv6addr_param)) {
/* invalid param size */
- return NULL;
+ return (NULL);
}
-#ifdef INET6
+ v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = (struct sockaddr_in6 *)&sa_store;
bzero(sin6, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
@@ -519,29 +486,21 @@ sctp_process_asconf_set_primary(struct mbuf *m,
zero_address = 1;
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
-#else
- /* IPv6 not enabled! No "action" needed; just ack it */
- SCTPDBG(SCTP_DEBUG_ASCONF1,
- "process_asconf_set_primary: v6 disabled- ignoring: ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
- /* just respond with a "success" ASCONF-ACK */
- return NULL;
-#endif
break;
+#endif
default:
m_reply = sctp_asconf_error_response(aph->correlation_id,
SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
aparam_length);
- return m_reply;
+ return (m_reply);
}
/* if 0.0.0.0/::0, use the source address instead */
if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
- sa = (struct sockaddr *)&sa_source;
- sctp_asconf_get_source_ip(m, sa);
+ sa = src;
SCTPDBG(SCTP_DEBUG_ASCONF1,
"process_asconf_set_primary: using source addr ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
+ SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
}
/* set the primary address */
if (sctp_set_primary_addr(stcb, sa, NULL) == 0) {
@@ -549,7 +508,12 @@ sctp_process_asconf_set_primary(struct mbuf *m,
"process_asconf_set_primary: primary address set\n");
/* notify upper layer */
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
-
+ if ((stcb->asoc.primary_destination->dest_state & SCTP_ADDR_REACHABLE) &&
+ (!(stcb->asoc.primary_destination->dest_state & SCTP_ADDR_PF)) &&
+ (stcb->asoc.alternate)) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
if (response_required) {
m_reply = sctp_asconf_success_response(aph->correlation_id);
}
@@ -599,7 +563,7 @@ sctp_process_asconf_set_primary(struct mbuf *m,
aparam_length);
}
- return m_reply;
+ return (m_reply);
}
/*
@@ -608,6 +572,7 @@ sctp_process_asconf_set_primary(struct mbuf *m,
*/
void
sctp_handle_asconf(struct mbuf *m, unsigned int offset,
+ struct sockaddr *src,
struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb,
int first)
{
@@ -617,7 +582,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
struct sctp_asconf_ack_chunk *ack_cp;
struct sctp_asconf_paramhdr *aph, *ack_aph;
struct sctp_ipv6addr_param *p_addr;
- unsigned int asconf_limit;
+ unsigned int asconf_limit, cnt;
int error = 0; /* did an error occur? */
/* asconf param buffer */
@@ -634,8 +599,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
asoc = &stcb->asoc;
serial_num = ntohl(cp->serial_number);
- if (compare_with_wrap(asoc->asconf_seq_in, serial_num, MAX_SEQ) ||
- serial_num == asoc->asconf_seq_in) {
+ if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) {
/* got a duplicate ASCONF */
SCTPDBG(SCTP_DEBUG_ASCONF1,
"handle_asconf: got duplicate serial number = %xh\n",
@@ -656,21 +620,18 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
if (first) {
/* delete old cache */
- SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing firstASCONF. Try to delte old cache\n");
+ SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing first ASCONF. Try to delete old cache\n");
- ack = TAILQ_FIRST(&stcb->asoc.asconf_ack_sent);
- while (ack != NULL) {
- ack_next = TAILQ_NEXT(ack, next);
+ TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) {
if (ack->serial_number == serial_num)
break;
SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: delete old(%u) < first(%u)\n",
ack->serial_number, serial_num);
- TAILQ_REMOVE(&stcb->asoc.asconf_ack_sent, ack, next);
+ TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next);
if (ack->data != NULL) {
sctp_m_freem(ack->data);
}
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack);
- ack = ack_next;
}
}
m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
@@ -716,6 +677,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
goto send_reply;
}
/* process through all parameters */
+ cnt = 0;
while (aph != NULL) {
unsigned int param_length, param_type;
@@ -747,12 +709,13 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
switch (param_type) {
case SCTP_ADD_IP_ADDRESS:
asoc->peer_supports_asconf = 1;
- m_result = sctp_process_asconf_add_ip(m, aph, stcb,
- error);
+ m_result = sctp_process_asconf_add_ip(src, aph, stcb,
+ (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
+ cnt++;
break;
case SCTP_DEL_IP_ADDRESS:
asoc->peer_supports_asconf = 1;
- m_result = sctp_process_asconf_delete_ip(m, aph, stcb,
+ m_result = sctp_process_asconf_delete_ip(src, aph, stcb,
error);
break;
case SCTP_ERROR_CAUSE_IND:
@@ -760,7 +723,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
break;
case SCTP_SET_PRIM_ADDR:
asoc->peer_supports_asconf = 1;
- m_result = sctp_process_asconf_set_primary(m, aph,
+ m_result = sctp_process_asconf_set_primary(src, aph,
stcb, error);
break;
case SCTP_NAT_VTAGS:
@@ -829,10 +792,8 @@ send_reply:
ack->last_sent_to = NULL;
ack->data = m_ack;
ack->len = 0;
- n = m_ack;
- while (n) {
+ for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) {
ack->len += SCTP_BUF_LEN(n);
- n = SCTP_BUF_NEXT(n);
}
TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next);
@@ -842,67 +803,16 @@ send_reply:
* this could happen if the source address was just newly
* added
*/
- struct ip *iph;
- struct sctphdr *sh;
- struct sockaddr_storage from_store;
- struct sockaddr *from = (struct sockaddr *)&from_store;
-
SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n");
- /* pullup already done, IP options already stripped */
- iph = mtod(m, struct ip *);
- sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph));
- switch (iph->ip_v) {
- case IPVERSION:
- {
- struct sockaddr_in *from4;
-
- from4 = (struct sockaddr_in *)&from_store;
- bzero(from4, sizeof(*from4));
- from4->sin_family = AF_INET;
- from4->sin_len = sizeof(struct sockaddr_in);
- from4->sin_addr.s_addr = iph->ip_src.s_addr;
- from4->sin_port = sh->src_port;
- break;
- }
-#ifdef INET6
- case IPV6_VERSION >> 4:
- {
- struct ip6_hdr *ip6;
- struct sockaddr_in6 *from6;
-
- ip6 = mtod(m, struct ip6_hdr *);
- from6 = (struct sockaddr_in6 *)&from_store;
- bzero(from6, sizeof(*from6));
- from6->sin6_family = AF_INET6;
- from6->sin6_len = sizeof(struct sockaddr_in6);
- from6->sin6_addr = ip6->ip6_src;
- from6->sin6_port = sh->src_port;
- /*
- * Get the scopes in properly to the sin6
- * addr's
- */
- /* we probably don't need these operations */
- (void)sa6_recoverscope(from6);
- sa6_embedscope(from6,
- MODULE_GLOBAL(ip6_use_defzone));
-
- break;
- }
-#endif
- default:
- /* unknown address type */
- from = NULL;
- }
- if (from != NULL) {
- SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: ");
- SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, from);
- /* look up the from address */
- stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, from);
+ SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: ");
+ SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
+ /* look up the from address */
+ stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, src);
#ifdef SCTP_DEBUG
- if (stcb->asoc.last_control_chunk_from == NULL)
- SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n");
-#endif
+ if (stcb->asoc.last_control_chunk_from == NULL) {
+ SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n");
}
+#endif
}
}
@@ -912,28 +822,36 @@ send_reply:
static uint32_t
sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
{
+ switch (sa->sa_family) {
#ifdef INET6
- if (sa->sa_family == AF_INET6) {
- /* IPv6 sa address */
- /* XXX scopeid */
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
-
- if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
- (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
- sizeof(struct in6_addr)) == 0)) {
- return (1);
+ case AF_INET6:
+ {
+ /* XXX scopeid */
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+ if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
+ (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
+ sizeof(struct in6_addr)) == 0)) {
+ return (1);
+ }
+ break;
}
- } else
-#endif /* INET6 */
- if (sa->sa_family == AF_INET) {
- /* IPv4 sa address */
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+#endif
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
- if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
- (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
- sizeof(struct in_addr)) == 0)) {
- return (1);
+ if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
+ (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
+ sizeof(struct in_addr)) == 0)) {
+ return (1);
+ }
+ break;
}
+#endif
+ default:
+ break;
}
return (0);
}
@@ -942,43 +860,48 @@ sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
* does the address match? returns 0 if not, 1 if so
*/
static uint32_t
-sctp_addr_match(
- struct sctp_ipv6addr_param *v6addr,
- struct sockaddr *sa)
+sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
{
uint16_t param_type, param_length;
- struct sctp_ipv4addr_param *v4addr = (struct sctp_ipv4addr_param *)v6addr;
+ param_type = ntohs(ph->param_type);
+ param_length = ntohs(ph->param_length);
+ switch (sa->sa_family) {
#ifdef INET6
- if (sa->sa_family == AF_INET6) {
- /* IPv6 sa address */
- /* XXX scopeid */
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
-
- param_type = ntohs(v6addr->ph.param_type);
- param_length = ntohs(v6addr->ph.param_length);
-
- if ((param_type == SCTP_IPV6_ADDRESS) &&
- param_length == sizeof(struct sctp_ipv6addr_param) &&
- (memcmp(&v6addr->addr, &sin6->sin6_addr,
- sizeof(struct in6_addr)) == 0)) {
- return (1);
+ case AF_INET6:
+ {
+ /* XXX scopeid */
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ struct sctp_ipv6addr_param *v6addr;
+
+ v6addr = (struct sctp_ipv6addr_param *)ph;
+ if ((param_type == SCTP_IPV6_ADDRESS) &&
+ param_length == sizeof(struct sctp_ipv6addr_param) &&
+ (memcmp(&v6addr->addr, &sin6->sin6_addr,
+ sizeof(struct in6_addr)) == 0)) {
+ return (1);
+ }
+ break;
}
- }
#endif
- if (sa->sa_family == AF_INET) {
- /* IPv4 sa address */
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-
- param_type = ntohs(v4addr->ph.param_type);
- param_length = ntohs(v4addr->ph.param_length);
-
- if ((param_type == SCTP_IPV4_ADDRESS) &&
- param_length == sizeof(struct sctp_ipv4addr_param) &&
- (memcmp(&v4addr->addr, &sin->sin_addr,
- sizeof(struct in_addr)) == 0)) {
- return (1);
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ struct sctp_ipv4addr_param *v4addr;
+
+ v4addr = (struct sctp_ipv4addr_param *)ph;
+ if ((param_type == SCTP_IPV4_ADDRESS) &&
+ param_length == sizeof(struct sctp_ipv4addr_param) &&
+ (memcmp(&v4addr->addr, &sin->sin_addr,
+ sizeof(struct in_addr)) == 0)) {
+ return (1);
+ }
+ break;
}
+#endif
+ default:
+ break;
}
return (0);
}
@@ -1183,17 +1106,25 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
continue;
changed = 0;
- if (net->ro._l_addr.sa.sa_family == AF_INET) {
- if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro))
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro)) {
changed = 1;
- }
+ }
+ break;
+#endif
#ifdef INET6
- if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ case AF_INET6:
if (sctp_v6src_match_nexthop(
- &newifa->address.sin6, (sctp_route_t *) & net->ro))
+ &newifa->address.sin6, (sctp_route_t *) & net->ro)) {
changed = 1;
- }
+ }
+ break;
#endif
+ default:
+ break;
+ }
/*
* if the newly added address does not relate routing
* information, we skip.
@@ -1220,8 +1151,7 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
* flag: 1=success, 0=failure.
*/
static void
-sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr,
- uint16_t type, uint32_t flag)
+sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t flag)
{
/*
* do the necessary asoc list work- if we get a failure indication,
@@ -1266,9 +1196,7 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
struct sockaddr *sa;
/* make sure the request isn't already in the queue */
- for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
- aa = aa_next) {
- aa_next = TAILQ_NEXT(aa, next);
+ TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
/* address match? */
if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
continue;
@@ -1322,31 +1250,40 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
aa->ifa = ifa;
atomic_add_int(&ifa->refcount, 1);
/* correlation_id filled in during send routine later... */
- if (ifa->address.sa.sa_family == AF_INET6) {
- /* IPv6 address */
- struct sockaddr_in6 *sin6;
+ switch (ifa->address.sa.sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
- sa = (struct sockaddr *)sin6;
- aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
- aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
- aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
- sizeof(struct sctp_ipv6addr_param);
- memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
- sizeof(struct in6_addr));
- } else if (ifa->address.sa.sa_family == AF_INET) {
- /* IPv4 address */
- struct sockaddr_in *sin;
+ sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
+ sa = (struct sockaddr *)sin6;
+ aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
+ aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
+ aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
+ sizeof(struct sctp_ipv6addr_param);
+ memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
+ sizeof(struct in6_addr));
+ break;
+ }
+#endif
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
- sin = (struct sockaddr_in *)&ifa->address.sa;
- sa = (struct sockaddr *)sin;
- aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
- aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
- aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
- sizeof(struct sctp_ipv4addr_param);
- memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
- sizeof(struct in_addr));
- } else {
+ sin = (struct sockaddr_in *)&ifa->address.sa;
+ sa = (struct sockaddr *)sin;
+ aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
+ aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
+ aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
+ sizeof(struct sctp_ipv4addr_param);
+ memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
+ sizeof(struct in_addr));
+ break;
+ }
+#endif
+ default:
/* invalid family! */
SCTP_FREE(aa, SCTP_M_ASC_ADDR);
sctp_free_ifa(ifa);
@@ -1356,7 +1293,7 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
#ifdef SCTP_DEBUG
- if (SCTP_BASE_SYSCTL(sctp_debug_on) && SCTP_DEBUG_ASCONF2) {
+ if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
if (type == SCTP_ADD_IP_ADDRESS) {
SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
@@ -1482,9 +1419,7 @@ sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
return (-1);
}
/* make sure the request isn't already in the queue */
- for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
- aa = aa_next) {
- aa_next = TAILQ_NEXT(aa, next);
+ TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
/* address match? */
if (sctp_asconf_addr_match(aa, sa) == 0)
continue;
@@ -1530,26 +1465,37 @@ sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
if (ifa)
atomic_add_int(&ifa->refcount, 1);
/* correlation_id filled in during send routine later... */
- if (sa->sa_family == AF_INET6) {
- /* IPv6 address */
- struct sockaddr_in6 *sin6;
-
- sin6 = (struct sockaddr_in6 *)sa;
- aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
- aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
- aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
- memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
- sizeof(struct in6_addr));
- } else if (sa->sa_family == AF_INET) {
- /* IPv4 address */
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ switch (sa->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ {
+ /* IPv6 address */
+ struct sockaddr_in6 *sin6;
- aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
- aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
- aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
- memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
- sizeof(struct in_addr));
- } else {
+ sin6 = (struct sockaddr_in6 *)sa;
+ aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
+ aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
+ aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
+ memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
+ sizeof(struct in6_addr));
+ break;
+ }
+#endif
+#ifdef INET
+ case AF_INET:
+ {
+ /* IPv4 address */
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+ aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
+ aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
+ aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
+ memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
+ sizeof(struct in_addr));
+ break;
+ }
+#endif
+ default:
/* invalid family! */
SCTP_FREE(aa, SCTP_M_ASC_ADDR);
if (ifa)
@@ -1655,7 +1601,7 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
case SCTP_ADD_IP_ADDRESS:
SCTPDBG(SCTP_DEBUG_ASCONF1,
"process_param_ack: added IP address\n");
- sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, param_type, flag);
+ sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, flag);
break;
case SCTP_DEL_IP_ADDRESS:
SCTPDBG(SCTP_DEBUG_ASCONF1,
@@ -1733,8 +1679,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
*/
if (serial_num == (asoc->asconf_seq_out + 1)) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
- sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED);
*abort_no_unlock = 1;
return;
}
@@ -1838,9 +1783,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
*/
if (last_error_id == 0)
last_error_id--;/* set to "max" value */
- for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
- aa = aa_next) {
- aa_next = TAILQ_NEXT(aa, next);
+ TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
if (aa->sent == 1) {
/*
* implicitly successful or failed if correlation_id
@@ -1921,8 +1864,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
{
int status;
-
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 &&
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 ||
sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
/* subset bound, no ASCONF allowed case, so ignore */
return;
@@ -1933,10 +1875,19 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
*/
/* first, make sure it's a good address family */
- if (ifa->address.sa.sa_family != AF_INET6 &&
- ifa->address.sa.sa_family != AF_INET) {
+ switch (ifa->address.sa.sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ break;
+#endif
+#ifdef INET
+ case AF_INET:
+ break;
+#endif
+ default:
return;
}
+#ifdef INET6
/* make sure we're "allowed" to add this type of addr */
if (ifa->address.sa.sa_family == AF_INET6) {
/* invalid if we're not a v6 endpoint */
@@ -1947,6 +1898,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
return;
}
}
+#endif
/* put this address on the "pending/do not use yet" list */
sctp_add_local_addr_restricted(stcb, ifa);
/*
@@ -1966,7 +1918,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
return;
}
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- if (stcb->asoc.local_scope == 0) {
+ if (stcb->asoc.scope.local_scope == 0) {
return;
}
/* is it the right link local scope? */
@@ -1974,13 +1926,14 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
return;
}
}
- if (stcb->asoc.site_scope == 0 &&
+ if (stcb->asoc.scope.site_scope == 0 &&
IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
return;
}
break;
}
#endif
+#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin;
@@ -1997,12 +1950,13 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* we skip unspecifed addresses */
return;
}
- if (stcb->asoc.ipv4_local_scope == 0 &&
+ if (stcb->asoc.scope.ipv4_local_scope == 0 &&
IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
return;
}
break;
}
+#endif
default:
/* else, not AF_INET or AF_INET6, so skip */
return;
@@ -2026,8 +1980,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
stcb, stcb->asoc.primary_destination);
#else
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- addr_locked);
+ sctp_send_asconf(stcb, NULL, addr_locked);
#endif
}
}
@@ -2036,7 +1989,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
int
-sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val)
+sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
{
struct sctp_asconf_iterator *asc;
struct sctp_ifa *ifa;
@@ -2046,42 +1999,45 @@ sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val)
asc = (struct sctp_asconf_iterator *)ptr;
LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
ifa = l->ifa;
- if (ifa->address.sa.sa_family == AF_INET6) {
+ switch (ifa->address.sa.sa_family) {
+#ifdef INET6
+ case AF_INET6:
/* invalid if we're not a v6 endpoint */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
cnt_invalid++;
if (asc->cnt == cnt_invalid)
return (1);
- else
- continue;
}
- } else if (ifa->address.sa.sa_family == AF_INET) {
- /* invalid if we are a v6 only endpoint */
- struct in6pcb *inp6;
+ break;
+#endif
+#ifdef INET
+ case AF_INET:
+ {
+ /* invalid if we are a v6 only endpoint */
+ struct in6pcb *inp6;
- inp6 = (struct in6pcb *)&inp->ip_inp.inp;
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- SCTP_IPV6_V6ONLY(inp6)) {
- cnt_invalid++;
- if (asc->cnt == cnt_invalid)
- return (1);
- else
- continue;
+ inp6 = (struct in6pcb *)&inp->ip_inp.inp;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
+ SCTP_IPV6_V6ONLY(inp6)) {
+ cnt_invalid++;
+ if (asc->cnt == cnt_invalid)
+ return (1);
+ }
+ break;
}
- } else {
+#endif
+ default:
/* invalid address family */
cnt_invalid++;
if (asc->cnt == cnt_invalid)
return (1);
- else
- continue;
}
}
return (0);
}
static int
-sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
+sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
{
struct sctp_ifa *ifa;
struct sctp_asconf_iterator *asc;
@@ -2100,14 +2056,11 @@ sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
}
}
} else if (l->action == SCTP_DEL_IP_ADDRESS) {
- laddr = LIST_FIRST(&inp->sctp_addr_list);
- while (laddr) {
- nladdr = LIST_NEXT(laddr, sctp_nxt_addr);
+ LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
/* remove only after all guys are done */
if (laddr->ifa == ifa) {
sctp_del_local_addr_ep(inp, ifa);
}
- laddr = nladdr;
}
}
}
@@ -2116,7 +2069,7 @@ sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
void
sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- void *ptr, uint32_t val)
+ void *ptr, uint32_t val SCTP_UNUSED)
{
struct sctp_asconf_iterator *asc;
struct sctp_ifa *ifa;
@@ -2155,7 +2108,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
continue;
}
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- if (stcb->asoc.local_scope == 0) {
+ if (stcb->asoc.scope.local_scope == 0) {
continue;
}
/* is it the right link local scope? */
@@ -2166,6 +2119,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
break;
}
#endif
+#ifdef INET
case AF_INET:
{
/* invalid if we are a v6 only endpoint */
@@ -2183,7 +2137,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* we skip unspecifed addresses */
continue;
}
- if (stcb->asoc.ipv4_local_scope == 0 &&
+ if (stcb->asoc.scope.ipv4_local_scope == 0 &&
IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
continue;
}
@@ -2197,6 +2151,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
break;
}
+#endif
default:
/* invalid address family */
cnt_invalid++;
@@ -2245,13 +2200,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
} else {
/* Need to check scopes for this guy */
- if (sctp_is_address_in_scope(ifa,
- stcb->asoc.ipv4_addr_legal,
- stcb->asoc.ipv6_addr_legal,
- stcb->asoc.loopback_scope,
- stcb->asoc.ipv4_local_scope,
- stcb->asoc.local_scope,
- stcb->asoc.site_scope, 0) == 0) {
+ if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) {
continue;
}
}
@@ -2277,22 +2226,19 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* If we have queued params in the open state, send out an ASCONF.
*/
if (num_queued > 0) {
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- SCTP_ADDR_NOT_LOCKED);
+ sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
}
}
void
-sctp_asconf_iterator_end(void *ptr, uint32_t val)
+sctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED)
{
struct sctp_asconf_iterator *asc;
struct sctp_ifa *ifa;
- struct sctp_laddr *l, *l_next;
+ struct sctp_laddr *l, *nl;
asc = (struct sctp_asconf_iterator *)ptr;
- l = LIST_FIRST(&asc->list_of_work);
- while (l != NULL) {
- l_next = LIST_NEXT(l, sctp_nxt_addr);
+ LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) {
ifa = l->ifa;
if (l->action == SCTP_ADD_IP_ADDRESS) {
/* Clear the defer use flag */
@@ -2301,7 +2247,6 @@ sctp_asconf_iterator_end(void *ptr, uint32_t val)
sctp_free_ifa(ifa);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
SCTP_DECR_LADDR_COUNT();
- l = l_next;
}
SCTP_FREE(asc, SCTP_M_ASC_IT);
}
@@ -2328,7 +2273,7 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
/* set primary queuing succeeded */
SCTPDBG(SCTP_DEBUG_ASCONF1,
"set_primary_ip_address_sa: queued on tcb=%p, ",
- stcb);
+ (void *)stcb);
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
#ifdef SCTP_TIMER_BASED_ASCONF
@@ -2336,13 +2281,12 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
stcb->sctp_ep, stcb,
stcb->asoc.primary_destination);
#else
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- SCTP_ADDR_NOT_LOCKED);
+ sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
#endif
}
} else {
SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
- stcb);
+ (void *)stcb);
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
return (-1);
}
@@ -2365,7 +2309,7 @@ sctp_set_primary_ip_address(struct sctp_ifa *ifa)
SCTP_SET_PRIM_ADDR)) {
/* set primary queuing succeeded */
SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
- stcb);
+ (void *)stcb);
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
#ifdef SCTP_TIMER_BASED_ASCONF
@@ -2373,8 +2317,7 @@ sctp_set_primary_ip_address(struct sctp_ifa *ifa)
stcb->sctp_ep, stcb,
stcb->asoc.primary_destination);
#else
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- SCTP_ADDR_NOT_LOCKED);
+ sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
#endif
}
}
@@ -2390,17 +2333,13 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
struct sctp_asconf_chunk *acp;
struct sctp_asconf_paramhdr *aph;
uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
- struct sctp_ipv6addr_param *p_addr;
+ struct sctp_paramhdr *ph;
int add_cnt, del_cnt;
uint16_t last_param_type;
add_cnt = del_cnt = 0;
last_param_type = 0;
- for (chk = TAILQ_FIRST(&stcb->asoc.asconf_send_queue); chk != NULL;
- chk = nchk) {
- /* get next chk */
- nchk = TAILQ_NEXT(chk, sctp_next);
-
+ TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) {
if (chk->data == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
continue;
@@ -2409,12 +2348,12 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
acp = mtod(chk->data, struct sctp_asconf_chunk *);
offset += sizeof(struct sctp_asconf_chunk);
asconf_limit = ntohs(acp->ch.chunk_length);
- p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
- if (p_addr == NULL) {
+ ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
+ if (ph == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n");
continue;
}
- offset += ntohs(p_addr->ph.param_length);
+ offset += ntohs(ph->param_length);
aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
if (aph == NULL) {
@@ -2443,8 +2382,8 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
break;
}
- p_addr = (struct sctp_ipv6addr_param *)(aph + 1);
- if (sctp_addr_match(p_addr, &sctp_ifa->address.sa) != 0) {
+ ph = (struct sctp_paramhdr *)(aph + 1);
+ if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) {
switch (param_type) {
case SCTP_ADD_IP_ADDRESS:
add_cnt++;
@@ -2473,9 +2412,9 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
*/
if (add_cnt > del_cnt ||
(add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) {
- return 1;
+ return (1);
}
- return 0;
+ return (0);
}
static struct sockaddr *
@@ -2494,58 +2433,78 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
return (NULL);
}
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
- if (stcb->asoc.loopback_scope == 0 &&
+ if (stcb->asoc.scope.loopback_scope == 0 &&
SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
/* Skip if loopback_scope not set */
continue;
}
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
- if (sctp_ifa->address.sa.sa_family == AF_INET &&
- stcb->asoc.ipv4_addr_legal) {
- struct sockaddr_in *sin;
+ switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (stcb->asoc.scope.ipv4_addr_legal) {
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
+ if (sin->sin_addr.s_addr == 0) {
+ /* skip unspecifed addresses */
+ continue;
+ }
+ if (stcb->asoc.scope.ipv4_local_scope == 0 &&
+ IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
+ continue;
- sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
- if (sin->sin_addr.s_addr == 0) {
- /* skip unspecifed addresses */
- continue;
+ if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
+ (!sctp_is_addr_pending(stcb, sctp_ifa)))
+ continue;
+ /*
+ * found a valid local v4 address to
+ * use
+ */
+ if (addr_locked == SCTP_ADDR_NOT_LOCKED)
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (&sctp_ifa->address.sa);
}
- if (stcb->asoc.ipv4_local_scope == 0 &&
- IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
- continue;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (stcb->asoc.scope.ipv6_addr_legal) {
+ struct sockaddr_in6 *sin6;
- if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
- (!sctp_is_addr_pending(stcb, sctp_ifa)))
- continue;
- /* found a valid local v4 address to use */
- if (addr_locked == SCTP_ADDR_NOT_LOCKED)
- SCTP_IPI_ADDR_RUNLOCK();
- return (&sctp_ifa->address.sa);
- } else if (sctp_ifa->address.sa.sa_family == AF_INET6 &&
- stcb->asoc.ipv6_addr_legal) {
- struct sockaddr_in6 *sin6;
+ if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
+ continue;
+ }
+ sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ /*
+ * we skip unspecifed
+ * addresses
+ */
+ continue;
+ }
+ if (stcb->asoc.scope.local_scope == 0 &&
+ IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+ continue;
+ if (stcb->asoc.scope.site_scope == 0 &&
+ IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
+ continue;
- if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
- continue;
- }
- sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
- /* we skip unspecifed addresses */
- continue;
+ if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
+ (!sctp_is_addr_pending(stcb, sctp_ifa)))
+ continue;
+ /*
+ * found a valid local v6 address to
+ * use
+ */
+ if (addr_locked == SCTP_ADDR_NOT_LOCKED)
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (&sctp_ifa->address.sa);
}
- if (stcb->asoc.local_scope == 0 &&
- IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
- continue;
- if (stcb->asoc.site_scope == 0 &&
- IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
- continue;
-
- if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
- (!sctp_is_addr_pending(stcb, sctp_ifa)))
- continue;
- /* found a valid local v6 address to use */
- if (addr_locked == SCTP_ADDR_NOT_LOCKED)
- SCTP_IPI_ADDR_RUNLOCK();
- return (&sctp_ifa->address.sa);
+ break;
+#endif
+ default:
+ break;
}
}
}
@@ -2717,7 +2676,9 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
if (found_addr != NULL) {
- if (found_addr->sa_family == AF_INET6) {
+ switch (found_addr->sa_family) {
+#ifdef INET6
+ case AF_INET6:
/* copy IPv6 address */
lookup->ph.param_type =
htons(SCTP_IPV6_ADDRESS);
@@ -2725,7 +2686,10 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
addr_size = sizeof(struct in6_addr);
addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
found_addr)->sin6_addr;
- } else {
+ break;
+#endif
+#ifdef INET
+ case AF_INET:
/* copy IPv4 address */
lookup->ph.param_type =
htons(SCTP_IPV4_ADDRESS);
@@ -2733,21 +2697,26 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
addr_size = sizeof(struct in_addr);
addr_ptr = (caddr_t)&((struct sockaddr_in *)
found_addr)->sin_addr;
+ break;
+#endif
+ default:
+ p_size = 0;
+ addr_size = 0;
+ addr_ptr = NULL;
+ break;
}
lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
memcpy(lookup->addr, addr_ptr, addr_size);
SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
- lookup_used = 1;
} else {
/* uh oh... don't have any address?? */
SCTPDBG(SCTP_DEBUG_ASCONF1,
"compose_asconf: no lookup addr!\n");
- /* for now, we send a IPv4 address of 0.0.0.0 */
+ /* XXX for now, we send a IPv4 address of 0.0.0.0 */
lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
bzero(lookup->addr, sizeof(struct in_addr));
SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
- lookup_used = 1;
}
}
/* chain it all together */
@@ -2773,9 +2742,17 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
struct sctp_paramhdr tmp_param, *ph;
uint16_t plen, ptype;
struct sctp_ifa *sctp_ifa;
- struct sctp_ipv6addr_param addr_store;
+
+#ifdef INET6
+ struct sctp_ipv6addr_param addr6_store;
struct sockaddr_in6 sin6;
+
+#endif
+#ifdef INET
+ struct sctp_ipv4addr_param addr4_store;
struct sockaddr_in sin;
+
+#endif
struct sockaddr *sa;
uint32_t vrf_id;
@@ -2790,51 +2767,67 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
return;
}
/* init the addresses */
+#ifdef INET6
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
sin6.sin6_port = stcb->rport;
+#endif
+#ifdef INET
bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
sin.sin_port = stcb->rport;
+#endif
/* go through the addresses in the init-ack */
- ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
- sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
+ ph = (struct sctp_paramhdr *)
+ sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
+ (uint8_t *) & tmp_param);
while (ph != NULL) {
ptype = ntohs(ph->param_type);
plen = ntohs(ph->param_length);
- if (ptype == SCTP_IPV6_ADDRESS) {
- struct sctp_ipv6addr_param *a6p;
-
- /* get the entire IPv6 address param */
- a6p = (struct sctp_ipv6addr_param *)
- sctp_m_getptr(m, offset,
- sizeof(struct sctp_ipv6addr_param),
- (uint8_t *) & addr_store);
- if (plen != sizeof(struct sctp_ipv6addr_param) ||
- a6p == NULL) {
- return;
+ switch (ptype) {
+#ifdef INET6
+ case SCTP_IPV6_ADDRESS:
+ {
+ struct sctp_ipv6addr_param *a6p;
+
+ /* get the entire IPv6 address param */
+ a6p = (struct sctp_ipv6addr_param *)
+ sctp_m_getptr(m, offset,
+ sizeof(struct sctp_ipv6addr_param),
+ (uint8_t *) & addr6_store);
+ if (plen != sizeof(struct sctp_ipv6addr_param) ||
+ a6p == NULL) {
+ return;
+ }
+ memcpy(&sin6.sin6_addr, a6p->addr,
+ sizeof(struct in6_addr));
+ sa = (struct sockaddr *)&sin6;
+ break;
}
- memcpy(&sin6.sin6_addr, a6p->addr,
- sizeof(struct in6_addr));
- sa = (struct sockaddr *)&sin6;
- } else if (ptype == SCTP_IPV4_ADDRESS) {
- struct sctp_ipv4addr_param *a4p;
-
- /* get the entire IPv4 address param */
- a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
- sizeof(struct sctp_ipv4addr_param),
- (uint8_t *) & addr_store);
- if (plen != sizeof(struct sctp_ipv4addr_param) ||
- a4p == NULL) {
- return;
+#endif
+#ifdef INET
+ case SCTP_IPV4_ADDRESS:
+ {
+ struct sctp_ipv4addr_param *a4p;
+
+ /* get the entire IPv4 address param */
+ a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
+ sizeof(struct sctp_ipv4addr_param),
+ (uint8_t *) & addr4_store);
+ if (plen != sizeof(struct sctp_ipv4addr_param) ||
+ a4p == NULL) {
+ return;
+ }
+ sin.sin_addr.s_addr = a4p->addr;
+ sa = (struct sockaddr *)&sin;
+ break;
}
- sin.sin_addr.s_addr = a4p->addr;
- sa = (struct sockaddr *)&sin;
- } else {
+#endif
+ default:
goto next_addr;
}
@@ -2868,8 +2861,7 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
stcb->sctp_ep, stcb,
stcb->asoc.primary_destination);
#else
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- SCTP_ADDR_NOT_LOCKED);
+ sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
#endif
}
}
@@ -2899,28 +2891,37 @@ next_addr:
* 1 if found, 0 if not
*/
static uint32_t
-sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset,
- uint32_t length, struct sockaddr *sa)
+sctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct sockaddr *sa)
{
struct sctp_paramhdr tmp_param, *ph;
uint16_t plen, ptype;
- struct sctp_ipv6addr_param addr_store;
+
+#ifdef INET
struct sockaddr_in *sin;
struct sctp_ipv4addr_param *a4p;
+ struct sctp_ipv6addr_param addr4_store;
+#endif
#ifdef INET6
struct sockaddr_in6 *sin6;
struct sctp_ipv6addr_param *a6p;
+ struct sctp_ipv6addr_param addr6_store;
struct sockaddr_in6 sin6_tmp;
-#endif /* INET6 */
+#endif
- if (
+ switch (sa->sa_family) {
+#ifdef INET
+ case AF_INET:
+ break;
+#endif
#ifdef INET6
- (sa->sa_family != AF_INET6) &&
-#endif /* INET6 */
- (sa->sa_family != AF_INET))
+ case AF_INET6:
+ break;
+#endif
+ default:
return (0);
+ }
SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
@@ -2938,55 +2939,68 @@ sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset,
while (ph != NULL) {
ptype = ntohs(ph->param_type);
plen = ntohs(ph->param_length);
+ switch (ptype) {
#ifdef INET6
- if (ptype == SCTP_IPV6_ADDRESS && sa->sa_family == AF_INET6) {
- /* get the entire IPv6 address param */
- a6p = (struct sctp_ipv6addr_param *)
- sctp_m_getptr(m, offset,
- sizeof(struct sctp_ipv6addr_param),
- (uint8_t *) & addr_store);
- if (plen != sizeof(struct sctp_ipv6addr_param) ||
- (ph == NULL) ||
- (a6p == NULL)) {
- return (0);
- }
- sin6 = (struct sockaddr_in6 *)sa;
- if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
- /* create a copy and clear scope */
- memcpy(&sin6_tmp, sin6,
- sizeof(struct sockaddr_in6));
- sin6 = &sin6_tmp;
- in6_clearscope(&sin6->sin6_addr);
- }
- if (memcmp(&sin6->sin6_addr, a6p->addr,
- sizeof(struct in6_addr)) == 0) {
- /* found it */
- return (1);
+ case SCTP_IPV6_ADDRESS:
+ if (sa->sa_family == AF_INET6) {
+ /* get the entire IPv6 address param */
+ if (plen != sizeof(struct sctp_ipv6addr_param)) {
+ break;
+ }
+ /* get the entire IPv6 address param */
+ a6p = (struct sctp_ipv6addr_param *)
+ sctp_m_getptr(m, offset,
+ sizeof(struct sctp_ipv6addr_param),
+ (uint8_t *) & addr6_store);
+ if (a6p == NULL) {
+ return (0);
+ }
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
+ /* create a copy and clear scope */
+ memcpy(&sin6_tmp, sin6,
+ sizeof(struct sockaddr_in6));
+ sin6 = &sin6_tmp;
+ in6_clearscope(&sin6->sin6_addr);
+ }
+ if (memcmp(&sin6->sin6_addr, a6p->addr,
+ sizeof(struct in6_addr)) == 0) {
+ /* found it */
+ return (1);
+ }
}
- } else
+ break;
#endif /* INET6 */
-
- if (ptype == SCTP_IPV4_ADDRESS &&
- sa->sa_family == AF_INET) {
- /* get the entire IPv4 address param */
- a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m,
- offset, sizeof(struct sctp_ipv4addr_param),
- (uint8_t *) & addr_store);
- if (plen != sizeof(struct sctp_ipv4addr_param) ||
- (ph == NULL) ||
- (a4p == NULL)) {
- return (0);
- }
- sin = (struct sockaddr_in *)sa;
- if (sin->sin_addr.s_addr == a4p->addr) {
- /* found it */
- return (1);
+#ifdef INET
+ case SCTP_IPV4_ADDRESS:
+ if (sa->sa_family == AF_INET) {
+ if (plen != sizeof(struct sctp_ipv4addr_param)) {
+ break;
+ }
+ /* get the entire IPv4 address param */
+ a4p = (struct sctp_ipv4addr_param *)
+ sctp_m_getptr(m, offset,
+ sizeof(struct sctp_ipv4addr_param),
+ (uint8_t *) & addr4_store);
+ if (a4p == NULL) {
+ return (0);
+ }
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr == a4p->addr) {
+ /* found it */
+ return (1);
+ }
}
+ break;
+#endif
+ default:
+ break;
}
/* get next parameter */
offset += SCTP_SIZE32(plen);
- if (offset + sizeof(struct sctp_paramhdr) > length)
+ if (offset + sizeof(struct sctp_paramhdr) > length) {
return (0);
+ }
ph = (struct sctp_paramhdr *)
sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
(uint8_t *) & tmp_param);
@@ -3023,8 +3037,7 @@ sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
continue;
}
/* check to see if in the init-ack */
- if (!sctp_addr_in_initack(stcb, m, offset, length,
- &laddr->ifa->address.sa)) {
+ if (!sctp_addr_in_initack(m, offset, length, &laddr->ifa->address.sa)) {
/* try to add it */
sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED);
@@ -3047,6 +3060,15 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
struct sctp_ifa *sctp_ifa;
uint32_t vrf_id;
+#ifdef INET
+ struct sockaddr_in *sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+
+#endif
+
if (stcb) {
vrf_id = stcb->asoc.vrf_id;
} else {
@@ -3070,9 +3092,35 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
continue;
}
+ switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ sin = (struct sockaddr_in *)&sctp_ifa->address.sin;
+ if ((ipv4_scope == 0) &&
+ (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
+ /* private address not in scope */
+ continue;
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6;
+ if ((local_scope == 0) &&
+ (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
+ continue;
+ }
+ if ((site_scope == 0) &&
+ (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
+ continue;
+ }
+ break;
+#endif
+ default:
+ break;
+ }
/* check to see if in the init-ack */
- if (!sctp_addr_in_initack(stcb, m, offset, length,
- &sctp_ifa->address.sa)) {
+ if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) {
/* try to add it */
sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
sctp_ifa, SCTP_ADD_IP_ADDRESS,
@@ -3124,6 +3172,7 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap)
{
struct sctp_ifa *ifa;
+ struct sctp_laddr *laddr, *nladdr;
if (sa->sa_len == 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
@@ -3144,8 +3193,6 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
if (type == SCTP_ADD_IP_ADDRESS) {
sctp_add_local_addr_ep(inp, ifa, type);
} else if (type == SCTP_DEL_IP_ADDRESS) {
- struct sctp_laddr *laddr;
-
if (inp->laddr_count < 2) {
/* can't delete the last local address */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
@@ -3159,11 +3206,19 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
}
}
}
- if (!LIST_EMPTY(&inp->sctp_asoc_list)) {
+ if (LIST_EMPTY(&inp->sctp_asoc_list)) {
/*
* There is no need to start the iterator if the inp
* has no associations.
*/
+ if (type == SCTP_DEL_IP_ADDRESS) {
+ LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
+ if (laddr->ifa == ifa) {
+ sctp_del_local_addr_ep(inp, ifa);
+ }
+ }
+ }
+ } else {
struct sctp_asconf_iterator *asc;
struct sctp_laddr *wi;
@@ -3211,8 +3266,11 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
struct sctp_asconf_addr *aa;
struct sctp_ifa *sctp_ifap;
struct sctp_asconf_tag_param *vtag;
+
+#ifdef INET
struct sockaddr_in *to;
+#endif
#ifdef INET6
struct sockaddr_in6 *to6;
@@ -3260,24 +3318,28 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
memset(aa, 0, sizeof(struct sctp_asconf_addr));
/* fill in asconf address parameter fields */
/* ADD(0.0.0.0) */
- if (net->ro._l_addr.sa.sa_family == AF_INET) {
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
/* No need to add an address, we are using 0.0.0.0 */
TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
- }
+ break;
+#endif
#ifdef INET6
- else if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ case AF_INET6:
aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
/* No need to add an address, we are using 0.0.0.0 */
TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
+ break;
+#endif
}
-#endif /* INET6 */
SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
SCTP_M_ASC_ADDR);
if (aa == NULL) {
@@ -3289,24 +3351,28 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
memset(aa, 0, sizeof(struct sctp_asconf_addr));
/* fill in asconf address parameter fields */
/* ADD(0.0.0.0) */
- if (net->ro._l_addr.sa.sa_family == AF_INET) {
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
/* No need to add an address, we are using 0.0.0.0 */
TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
- }
+ break;
+#endif
#ifdef INET6
- else if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ case AF_INET6:
aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
/* No need to add an address, we are using 0.0.0.0 */
TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
+ break;
+#endif
}
-#endif /* INET6 */
/* Now we must hunt the addresses and add all global addresses */
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
struct sctp_vrf *vrf = NULL;
@@ -3321,18 +3387,20 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
SCTP_IPI_ADDR_RLOCK();
LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
- if (sctp_ifap->address.sa.sa_family == AF_INET) {
+ switch (sctp_ifap->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
to = &sctp_ifap->address.sin;
-
if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
continue;
}
if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
continue;
}
- }
+ break;
+#endif
#ifdef INET6
- else if (sctp_ifap->address.sa.sa_family == AF_INET6) {
+ case AF_INET6:
to6 = &sctp_ifap->address.sin6;
if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
continue;
@@ -3340,8 +3408,11 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
continue;
}
- }
+ break;
#endif
+ default:
+ continue;
+ }
sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
}
}
@@ -3367,18 +3438,20 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
continue;
}
sctp_ifap = laddr->ifa;
- if (sctp_ifap->address.sa.sa_family == AF_INET) {
+ switch (sctp_ifap->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
to = &sctp_ifap->address.sin;
-
if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
continue;
}
if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
continue;
}
- }
+ break;
+#endif
#ifdef INET6
- else if (sctp_ifap->address.sa.sa_family == AF_INET6) {
+ case AF_INET6:
to6 = &sctp_ifap->address.sin6;
if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
continue;
@@ -3386,12 +3459,15 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
continue;
}
- }
+ break;
#endif
+ default:
+ continue;
+ }
sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
}
}
skip_rest:
/* Now we must send the asconf into the queue */
- sctp_send_asconf(stcb, net, 0);
+ sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
}
diff --git a/freebsd/sys/netinet/sctp_asconf.h b/freebsd/sys/netinet/sctp_asconf.h
index bf3d5665..183c99b4 100644
--- a/freebsd/sys/netinet/sctp_asconf.h
+++ b/freebsd/sys/netinet/sctp_asconf.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,8 +30,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_asconf.h,v 1.8 2005/03/06 16:04:16 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -46,8 +46,8 @@ extern void sctp_asconf_cleanup(struct sctp_tcb *, struct sctp_nets *);
extern struct mbuf *sctp_compose_asconf(struct sctp_tcb *, int *, int);
extern void
-sctp_handle_asconf(struct mbuf *, unsigned int, struct sctp_asconf_chunk *,
- struct sctp_tcb *, int i);
+sctp_handle_asconf(struct mbuf *, unsigned int, struct sockaddr *,
+ struct sctp_asconf_chunk *, struct sctp_tcb *, int);
extern void
sctp_handle_asconf_ack(struct mbuf *, int, struct sctp_asconf_ack_chunk *,
diff --git a/freebsd/sys/netinet/sctp_auth.c b/freebsd/sys/netinet/sctp_auth.c
index cf4ebaa9..088ec8c2 100644
--- a/freebsd/sys/netinet/sctp_auth.c
+++ b/freebsd/sys/netinet/sctp_auth.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -284,16 +286,16 @@ sctp_print_key(sctp_key_t * key, const char *str)
uint32_t i;
if (key == NULL) {
- printf("%s: [Null key]\n", str);
+ SCTP_PRINTF("%s: [Null key]\n", str);
return;
}
- printf("%s: len %u, ", str, key->keylen);
+ SCTP_PRINTF("%s: len %u, ", str, key->keylen);
if (key->keylen) {
for (i = 0; i < key->keylen; i++)
- printf("%02x", key->key[i]);
- printf("\n");
+ SCTP_PRINTF("%02x", key->key[i]);
+ SCTP_PRINTF("\n");
} else {
- printf("[Null key]\n");
+ SCTP_PRINTF("[Null key]\n");
}
}
@@ -303,16 +305,16 @@ sctp_show_key(sctp_key_t * key, const char *str)
uint32_t i;
if (key == NULL) {
- printf("%s: [Null key]\n", str);
+ SCTP_PRINTF("%s: [Null key]\n", str);
return;
}
- printf("%s: len %u, ", str, key->keylen);
+ SCTP_PRINTF("%s: len %u, ", str, key->keylen);
if (key->keylen) {
for (i = 0; i < key->keylen; i++)
- printf("%02x", key->key[i]);
- printf("\n");
+ SCTP_PRINTF("%02x", key->key[i]);
+ SCTP_PRINTF("\n");
} else {
- printf("[Null key]\n");
+ SCTP_PRINTF("[Null key]\n");
}
}
@@ -469,7 +471,6 @@ sctp_compute_hashkey(sctp_key_t * key1, sctp_key_t * key2, sctp_key_t * shared)
}
if (sctp_get_keylen(key2)) {
bcopy(key2->key, key_ptr, key2->keylen);
- key_ptr += key2->keylen;
}
} else {
/* key is shared + key2 + key1 */
@@ -483,7 +484,6 @@ sctp_compute_hashkey(sctp_key_t * key1, sctp_key_t * key2, sctp_key_t * shared)
}
if (sctp_get_keylen(key1)) {
bcopy(key1->key, key_ptr, key1->keylen);
- key_ptr += key1->keylen;
}
}
return (new_key);
@@ -593,12 +593,16 @@ sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t key_id)
atomic_add_int(&skey->refcount, 1);
SCTPDBG(SCTP_DEBUG_AUTH2,
"%s: stcb %p key %u refcount acquire to %d\n",
- __FUNCTION__, stcb, key_id, skey->refcount);
+ __FUNCTION__, (void *)stcb, key_id, skey->refcount);
}
}
void
-sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id)
+sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+ SCTP_UNUSED
+#endif
+)
{
sctp_sharedkey_t *skey;
@@ -610,16 +614,16 @@ sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id)
sctp_free_sharedkey(skey);
SCTPDBG(SCTP_DEBUG_AUTH2,
"%s: stcb %p key %u refcount release to %d\n",
- __FUNCTION__, stcb, key_id, skey->refcount);
+ __FUNCTION__, (void *)stcb, key_id, skey->refcount);
/* see if a notification should be generated */
if ((skey->refcount <= 1) && (skey->deactivated)) {
/* notify ULP that key is no longer used */
sctp_ulp_notify(SCTP_NOTIFY_AUTH_FREE_KEY, stcb,
- key_id, 0, SCTP_SO_LOCKED);
+ key_id, 0, so_locked);
SCTPDBG(SCTP_DEBUG_AUTH2,
"%s: stcb %p key %u no longer used, %d\n",
- __FUNCTION__, stcb, key_id, skey->refcount);
+ __FUNCTION__, (void *)stcb, key_id, skey->refcount);
}
}
}
@@ -1799,7 +1803,7 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth,
* shared_key_id, (void
* *)stcb->asoc.authinfo.recv_keyid);
*/
- sctp_notify_authentication(stcb, SCTP_AUTH_NEWKEY,
+ sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY,
shared_key_id, stcb->asoc.authinfo.recv_keyid,
SCTP_SO_NOT_LOCKED);
/* compute a new recv assoc key and cache it */
@@ -1862,7 +1866,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
/* If the socket is gone we are out of here */
return;
}
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTHEVNT))
+ if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_AUTHEVNT))
/* event not enabled */
return;
@@ -1887,7 +1891,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0, m_notify);
+ 0, 0, stcb->asoc.context, 0, 0, 0, m_notify);
if (control == NULL) {
/* no memory */
sctp_m_freem(m_notify);
@@ -1949,9 +1953,6 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
case SCTP_ASCONF_ACK:
peer_supports_asconf = 1;
break;
- case SCTP_AUTHENTICATION:
- peer_supports_auth = 1;
- break;
default:
/* one we don't care about */
break;
diff --git a/freebsd/sys/netinet/sctp_auth.h b/freebsd/sys/netinet/sctp_auth.h
index 36535357..a7ded047 100644
--- a/freebsd/sys/netinet/sctp_auth.h
+++ b/freebsd/sys/netinet/sctp_auth.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -31,8 +33,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __SCTP_AUTH_HH__
-#define __SCTP_AUTH_HH__
+#ifndef _NETINET_SCTP_AUTH_H_
+#define _NETINET_SCTP_AUTH_H_
/* digest lengths */
@@ -87,7 +89,7 @@ typedef struct sctp_hmaclist {
} sctp_hmaclist_t;
/* authentication info */
-typedef struct sctp_authinfo {
+typedef struct sctp_authinformation {
sctp_key_t *random; /* local random key (concatenated) */
uint32_t random_len; /* local random number length for param */
sctp_key_t *peer_random;/* peer's random key (concatenated) */
@@ -96,7 +98,7 @@ typedef struct sctp_authinfo {
uint16_t active_keyid; /* active send keyid */
uint16_t assoc_keyid; /* current send keyid (cached) */
uint16_t recv_keyid; /* last recv keyid (cached) */
-} sctp_authinfo_t;
+} sctp_authinfo_t;
@@ -154,7 +156,9 @@ sctp_copy_skeylist(const struct sctp_keyhead *src,
/* ref counts on shared keys, by key id */
extern void sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t keyid);
-extern void sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t keyid);
+extern void
+sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t keyid,
+ int so_locked);
/* hmac list handling */
diff --git a/freebsd/sys/netinet/sctp_bsd_addr.c b/freebsd/sys/netinet/sctp_bsd_addr.c
index 8612adc9..49549d15 100644
--- a/freebsd/sys/netinet/sctp_bsd_addr.c
+++ b/freebsd/sys/netinet/sctp_bsd_addr.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,8 +32,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -70,25 +70,10 @@ MALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", "sctp time block");
MALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list");
MALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control");
MALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option");
+MALLOC_DEFINE(SCTP_M_MCORE, "sctp_mcore", "sctp mcore queue");
/* Global NON-VNET structure that controls the iterator */
struct iterator_control sctp_it_ctl;
-static int __sctp_thread_based_iterator_started = 0;
-
-
-static void
-sctp_cleanup_itqueue(void)
-{
- struct sctp_iterator *it;
-
- while ((it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead)) != NULL) {
- if (it->function_atend != NULL) {
- (*it->function_atend) (it->pointer, it->val);
- }
- TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
- SCTP_FREE(it, SCTP_M_ITER);
- }
-}
void
@@ -98,20 +83,14 @@ sctp_wakeup_iterator(void)
}
static void
-sctp_iterator_thread(void *v)
+sctp_iterator_thread(void *v SCTP_UNUSED)
{
SCTP_IPI_ITERATOR_WQ_LOCK();
- while (1) {
+ /* In FreeBSD this thread never terminates. */
+ for (;;) {
msleep(&sctp_it_ctl.iterator_running,
&sctp_it_ctl.ipi_iterator_wq_mtx,
0, "waiting_for_work", 0);
- if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) {
- SCTP_IPI_ITERATOR_WQ_DESTROY();
- SCTP_ITERATOR_LOCK_DESTROY();
- sctp_cleanup_itqueue();
- __sctp_thread_based_iterator_started = 0;
- kthread_exit();
- }
sctp_iterator_worker();
}
}
@@ -119,21 +98,21 @@ sctp_iterator_thread(void *v)
void
sctp_startup_iterator(void)
{
- if (__sctp_thread_based_iterator_started) {
+ static int called = 0;
+ int ret;
+
+ if (called) {
/* You only get one */
return;
}
/* init the iterator head */
- __sctp_thread_based_iterator_started = 1;
+ called = 1;
sctp_it_ctl.iterator_running = 0;
sctp_it_ctl.iterator_flags = 0;
sctp_it_ctl.cur_it = NULL;
SCTP_ITERATOR_LOCK_INIT();
SCTP_IPI_ITERATOR_WQ_INIT();
TAILQ_INIT(&sctp_it_ctl.iteratorhead);
-
- int ret;
-
ret = kproc_create(sctp_iterator_thread,
(void *)NULL,
&sctp_it_ctl.thread_proc,
@@ -175,12 +154,12 @@ sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa)
static uint32_t
-sctp_is_desired_interface_type(struct ifaddr *ifa)
+sctp_is_desired_interface_type(struct ifnet *ifn)
{
int result;
/* check the interface type to see if it's one we care about */
- switch (ifa->ifa_ifp->if_type) {
+ switch (ifn->if_type) {
case IFT_ETHER:
case IFT_ISO88023:
case IFT_ISO88024:
@@ -201,9 +180,11 @@ sctp_is_desired_interface_type(struct ifaddr *ifa)
case IFT_SLIP:
case IFT_GIF:
case IFT_L2VLAN:
+ case IFT_STF:
case IFT_IP:
case IFT_IPOVERCDLC:
case IFT_IPOVERCLAW:
+ case IFT_PROPVIRTUAL: /* NetGraph Virtual too */
case IFT_VIRTUALIPADDRESS:
result = 1;
break;
@@ -227,40 +208,59 @@ sctp_init_ifns_for_vrf(int vrfid)
*/
struct ifnet *ifn;
struct ifaddr *ifa;
- struct in6_ifaddr *ifa6;
struct sctp_ifa *sctp_ifa;
uint32_t ifa_flags;
+#ifdef INET6
+ struct in6_ifaddr *ifa6;
+
+#endif
+
IFNET_RLOCK();
TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) {
- IF_ADDR_LOCK(ifn);
+ if (sctp_is_desired_interface_type(ifn) == 0) {
+ /* non desired type */
+ continue;
+ }
+ IF_ADDR_RLOCK(ifn);
TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
if (ifa->ifa_addr == NULL) {
continue;
}
- if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
- /* non inet/inet6 skip */
- continue;
- }
- if (ifa->ifa_addr->sa_family == AF_INET6) {
- if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
- /* skip unspecifed addresses */
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
continue;
}
- } else {
- if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
+ /* skip unspecifed addresses */
continue;
}
- }
- if (sctp_is_desired_interface_type(ifa) == 0) {
- /* non desired type */
+ break;
+#endif
+ default:
continue;
}
- if (ifa->ifa_addr->sa_family == AF_INET6) {
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ ifa_flags = 0;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
ifa6 = (struct in6_ifaddr *)ifa;
ifa_flags = ifa6->ia6_flags;
- } else {
+ break;
+#endif
+ default:
ifa_flags = 0;
+ break;
}
sctp_ifa = sctp_add_addr_to_vrf(vrfid,
(void *)ifn,
@@ -275,7 +275,7 @@ sctp_init_ifns_for_vrf(int vrfid)
sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
}
}
- IF_ADDR_UNLOCK(ifn);
+ IF_ADDR_RUNLOCK(ifn);
}
IFNET_RUNLOCK();
}
@@ -319,37 +319,41 @@ sctp_addr_change(struct ifaddr *ifa, int cmd)
if (ifa->ifa_addr == NULL) {
return;
}
- if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
- /* non inet/inet6 skip */
+ if (sctp_is_desired_interface_type(ifa->ifa_ifp) == 0) {
+ /* non desired type */
return;
}
- if (ifa->ifa_addr->sa_family == AF_INET6) {
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
+ return;
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
ifa_flags = ((struct in6_ifaddr *)ifa)->ia6_flags;
if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
/* skip unspecifed addresses */
return;
}
- } else {
- if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
- return;
- }
- }
-
- if (sctp_is_desired_interface_type(ifa) == 0) {
- /* non desired type */
+ break;
+#endif
+ default:
+ /* non inet/inet6 skip */
return;
}
if (cmd == RTM_ADD) {
(void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp,
- ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type,
- ifa->ifa_ifp->if_xname,
+ ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type, ifa->ifa_ifp->if_xname,
(void *)ifa, ifa->ifa_addr, ifa_flags, 1);
} else {
sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
ifa->ifa_ifp->if_index,
- ifa->ifa_ifp->if_xname
- );
+ ifa->ifa_ifp->if_xname);
+
/*
* We don't bump refcount here so when it completes the
* final delete will happen.
@@ -418,11 +422,12 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
#ifdef SCTP_PACKET_LOGGING
void
-sctp_packet_log(struct mbuf *m, int length)
+sctp_packet_log(struct mbuf *m)
{
int *lenat, thisone;
void *copyto;
uint32_t *tick_tock;
+ int length;
int total_len;
int grabbed_lock = 0;
int value, newval, thisend, thisbegin;
@@ -432,6 +437,7 @@ sctp_packet_log(struct mbuf *m, int length)
* (value) -ticks of log (ticks) o -ip packet o -as logged -
* where this started (thisbegin) x <--end points here
*/
+ length = SCTP_HEADER_LEN(m);
total_len = SCTP_SIZE32((length + (4 * sizeof(int))));
/* Log a packet to the buffer. */
if (total_len > SCTP_PACKET_LOG_SIZE) {
@@ -477,7 +483,7 @@ again_locked:
}
/* Sanity check */
if (thisend >= SCTP_PACKET_LOG_SIZE) {
- printf("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n",
+ SCTP_PRINTF("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n",
thisbegin,
thisend,
SCTP_BASE_VAR(packet_log_writers),
diff --git a/freebsd/sys/netinet/sctp_bsd_addr.h b/freebsd/sys/netinet/sctp_bsd_addr.h
index ae2fa525..24660ca5 100644
--- a/freebsd/sys/netinet/sctp_bsd_addr.h
+++ b/freebsd/sys/netinet/sctp_bsd_addr.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -31,8 +33,9 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_bsd_addr_h__
-#define __sctp_bsd_addr_h__
+#ifndef _NETINET_SCTP_BSD_ADDR_H_
+#define _NETINET_SCTP_BSD_ADDR_H_
+
#include <netinet/sctp_pcb.h>
#if defined(_KERNEL) || defined(__Userspace__)
@@ -50,7 +53,7 @@ void sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa);
#ifdef SCTP_PACKET_LOGGING
-void sctp_packet_log(struct mbuf *m, int length);
+void sctp_packet_log(struct mbuf *m);
int sctp_copy_out_packet_log(uint8_t * target, int length);
#endif
diff --git a/freebsd/sys/netinet/sctp_cc_functions.c b/freebsd/sys/netinet/sctp_cc_functions.c
index e0f8beae..36818feb 100644
--- a/freebsd/sys/netinet/sctp_cc_functions.c
+++ b/freebsd/sys/netinet/sctp_cc_functions.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,6 +32,9 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <netinet/sctp_os.h>
#include <netinet/sctp_var.h>
#include <netinet/sctp_sysctl.h>
@@ -43,47 +48,82 @@
#include <netinet/sctp_timer.h>
#include <netinet/sctp_auth.h>
#include <netinet/sctp_asconf.h>
-#include <netinet/sctp_cc_functions.h>
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+#include <netinet/sctp_dtrace_declare.h>
+
+#define SHIFT_MPTCP_MULTI_N 40
+#define SHIFT_MPTCP_MULTI_Z 16
+#define SHIFT_MPTCP_MULTI 8
-void
+static void
sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
{
struct sctp_association *assoc;
uint32_t cwnd_in_mtu;
assoc = &stcb->asoc;
- /*
- * We take the minimum of the burst limit and the initial congestion
- * window. The initial congestion window is at least two times the
- * MTU.
- */
cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
- if ((assoc->max_burst > 0) && (cwnd_in_mtu > assoc->max_burst))
- cwnd_in_mtu = assoc->max_burst;
- net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
+ if (cwnd_in_mtu == 0) {
+ /* Using 0 means that the value of RFC 4960 is used. */
+ net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
+ } else {
+ /*
+ * We take the minimum of the burst limit and the initial
+ * congestion window.
+ */
+ if ((assoc->max_burst > 0) && (cwnd_in_mtu > assoc->max_burst))
+ cwnd_in_mtu = assoc->max_burst;
+ net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
+ }
+ if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
+ (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
+ /* In case of resource pooling initialize appropriately */
+ net->cwnd /= assoc->numnets;
+ if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
+ net->cwnd = net->mtu - sizeof(struct sctphdr);
+ }
+ }
net->ssthresh = assoc->peers_rwnd;
-
+ SDT_PROBE(sctp, cwnd, net, init,
+ stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
+ 0, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) &
(SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
}
}
-void
+static void
sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
struct sctp_association *asoc)
{
struct sctp_nets *net;
-
+ uint32_t t_ssthresh, t_cwnd;
+ uint64_t t_ucwnd_sbw;
+
+ /* MT FIXME: Don't compute this over and over again */
+ t_ssthresh = 0;
+ t_cwnd = 0;
+ t_ucwnd_sbw = 0;
+ if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
+ (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ t_ssthresh += net->ssthresh;
+ t_cwnd += net->cwnd;
+ if (net->lastsa > 0) {
+ t_ucwnd_sbw += (uint64_t) net->cwnd / (uint64_t) net->lastsa;
+ }
+ }
+ if (t_ucwnd_sbw == 0) {
+ t_ucwnd_sbw = 1;
+ }
+ }
/*-
- * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
+ * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) ||
- (asoc->sctp_cmt_on_off == 1)) {
+ (asoc->sctp_cmt_on_off > 0)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*
@@ -95,11 +135,54 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
struct sctp_tmit_chunk *lchk;
int old_cwnd = net->cwnd;
- net->ssthresh = net->cwnd / 2;
- if (net->ssthresh < (net->mtu * 2)) {
- net->ssthresh = 2 * net->mtu;
+ if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
+ (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
+ if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) {
+ net->ssthresh = (uint32_t) (((uint64_t) 4 *
+ (uint64_t) net->mtu *
+ (uint64_t) net->ssthresh) /
+ (uint64_t) t_ssthresh);
+
+ }
+ if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2) {
+ uint32_t srtt;
+
+ srtt = net->lastsa;
+ /*
+ * lastsa>>3; we don't need
+ * to devide ...
+ */
+ if (srtt == 0) {
+ srtt = 1;
+ }
+ /*
+ * Short Version => Equal to
+ * Contel Version MBe
+ */
+ net->ssthresh = (uint32_t) (((uint64_t) 4 *
+ (uint64_t) net->mtu *
+ (uint64_t) net->cwnd) /
+ ((uint64_t) srtt *
+ t_ucwnd_sbw));
+ /* INCREASE FACTOR */ ;
+ }
+ if ((net->cwnd > t_cwnd / 2) &&
+ (net->ssthresh < net->cwnd - t_cwnd / 2)) {
+ net->ssthresh = net->cwnd - t_cwnd / 2;
+ }
+ if (net->ssthresh < net->mtu) {
+ net->ssthresh = net->mtu;
+ }
+ } else {
+ net->ssthresh = net->cwnd / 2;
+ if (net->ssthresh < (net->mtu * 2)) {
+ net->ssthresh = 2 * net->mtu;
+ }
}
net->cwnd = net->ssthresh;
+ SDT_PROBE(sctp, cwnd, net, fr,
+ stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
+ old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
SCTP_CWND_LOG_FROM_FR);
@@ -129,13 +212,6 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
}
- /*
- * Disable Nonce Sum Checking and store the
- * resync tsn
- */
- asoc->nonce_sum_check = 0;
- asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
-
sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
@@ -151,13 +227,493 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
}
}
-void
-sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
+/* Defines for instantaneous bw decisions */
+#define SCTP_INST_LOOSING 1 /* Loosing to other flows */
+#define SCTP_INST_NEUTRAL 2 /* Neutral, no indication */
+#define SCTP_INST_GAINING 3 /* Gaining, step down possible */
+
+
+static int
+cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
+ uint64_t rtt_offset, uint64_t vtag, uint8_t inst_ind)
+{
+ uint64_t oth, probepoint;
+
+ probepoint = (((uint64_t) net->cwnd) << 32);
+ if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) {
+ /*
+ * rtt increased we don't update bw.. so we don't update the
+ * rtt either.
+ */
+ /* Probe point 5 */
+ probepoint |= ((5 << 16) | 1);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
+ if (net->cc_mod.rtcc.last_step_state == 5)
+ net->cc_mod.rtcc.step_cnt++;
+ else
+ net->cc_mod.rtcc.step_cnt = 1;
+ net->cc_mod.rtcc.last_step_state = 5;
+ if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
+ ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
+ ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
+ /* Try a step down */
+ oth = net->cc_mod.rtcc.vol_reduce;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.step_cnt;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.last_step_state;
+ SDT_PROBE(sctp, cwnd, net, rttstep,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ oth,
+ probepoint);
+ if (net->cwnd > (4 * net->mtu)) {
+ net->cwnd -= net->mtu;
+ net->cc_mod.rtcc.vol_reduce++;
+ } else {
+ net->cc_mod.rtcc.step_cnt = 0;
+ }
+ }
+ }
+ return (1);
+ }
+ if (net->rtt < net->cc_mod.rtcc.lbw_rtt - rtt_offset) {
+ /*
+ * rtt decreased, there could be more room. we update both
+ * the bw and the rtt here to lock this in as a good step
+ * down.
+ */
+ /* Probe point 6 */
+ probepoint |= ((6 << 16) | 0);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ if (net->cc_mod.rtcc.steady_step) {
+ oth = net->cc_mod.rtcc.vol_reduce;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.step_cnt;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.last_step_state;
+ SDT_PROBE(sctp, cwnd, net, rttstep,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ oth,
+ probepoint);
+ if ((net->cc_mod.rtcc.last_step_state == 5) &&
+ (net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step)) {
+ /* Step down worked */
+ net->cc_mod.rtcc.step_cnt = 0;
+ return (1);
+ } else {
+ net->cc_mod.rtcc.last_step_state = 6;
+ net->cc_mod.rtcc.step_cnt = 0;
+ }
+ }
+ net->cc_mod.rtcc.lbw = nbw;
+ net->cc_mod.rtcc.lbw_rtt = net->rtt;
+ net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
+ if (inst_ind == SCTP_INST_GAINING)
+ return (1);
+ else if (inst_ind == SCTP_INST_NEUTRAL)
+ return (1);
+ else
+ return (0);
+ }
+ /*
+ * Ok bw and rtt remained the same .. no update to any
+ */
+ /* Probe point 7 */
+ probepoint |= ((7 << 16) | net->cc_mod.rtcc.ret_from_eq);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
+ if (net->cc_mod.rtcc.last_step_state == 5)
+ net->cc_mod.rtcc.step_cnt++;
+ else
+ net->cc_mod.rtcc.step_cnt = 1;
+ net->cc_mod.rtcc.last_step_state = 5;
+ if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
+ ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
+ ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
+ /* Try a step down */
+ if (net->cwnd > (4 * net->mtu)) {
+ net->cwnd -= net->mtu;
+ net->cc_mod.rtcc.vol_reduce++;
+ return (1);
+ } else {
+ net->cc_mod.rtcc.step_cnt = 0;
+ }
+ }
+ }
+ if (inst_ind == SCTP_INST_GAINING)
+ return (1);
+ else if (inst_ind == SCTP_INST_NEUTRAL)
+ return (1);
+ else
+ return ((int)net->cc_mod.rtcc.ret_from_eq);
+}
+
+static int
+cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
+ uint64_t vtag, uint8_t inst_ind)
+{
+ uint64_t oth, probepoint;
+
+ /* Bandwidth decreased. */
+ probepoint = (((uint64_t) net->cwnd) << 32);
+ if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) {
+ /* rtt increased */
+ /* Did we add more */
+ if ((net->cwnd > net->cc_mod.rtcc.cwnd_at_bw_set) &&
+ (inst_ind != SCTP_INST_LOOSING)) {
+ /* We caused it maybe.. back off? */
+ /* PROBE POINT 1 */
+ probepoint |= ((1 << 16) | 1);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ if (net->cc_mod.rtcc.ret_from_eq) {
+ /*
+ * Switch over to CA if we are less
+ * aggressive
+ */
+ net->ssthresh = net->cwnd - 1;
+ net->partial_bytes_acked = 0;
+ }
+ return (1);
+ }
+ /* Probe point 2 */
+ probepoint |= ((2 << 16) | 0);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ /* Someone else - fight for more? */
+ if (net->cc_mod.rtcc.steady_step) {
+ oth = net->cc_mod.rtcc.vol_reduce;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.step_cnt;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.last_step_state;
+ SDT_PROBE(sctp, cwnd, net, rttstep,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ oth,
+ probepoint);
+ /*
+ * Did we voluntarily give up some? if so take one
+ * back please
+ */
+ if ((net->cc_mod.rtcc.vol_reduce) &&
+ (inst_ind != SCTP_INST_GAINING)) {
+ net->cwnd += net->mtu;
+ net->cc_mod.rtcc.vol_reduce--;
+ }
+ net->cc_mod.rtcc.last_step_state = 2;
+ net->cc_mod.rtcc.step_cnt = 0;
+ }
+ goto out_decision;
+ } else if (net->rtt < net->cc_mod.rtcc.lbw_rtt - rtt_offset) {
+ /* bw & rtt decreased */
+ /* Probe point 3 */
+ probepoint |= ((3 << 16) | 0);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ if (net->cc_mod.rtcc.steady_step) {
+ oth = net->cc_mod.rtcc.vol_reduce;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.step_cnt;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.last_step_state;
+ SDT_PROBE(sctp, cwnd, net, rttstep,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ oth,
+ probepoint);
+ if ((net->cc_mod.rtcc.vol_reduce) &&
+ (inst_ind != SCTP_INST_GAINING)) {
+ net->cwnd += net->mtu;
+ net->cc_mod.rtcc.vol_reduce--;
+ }
+ net->cc_mod.rtcc.last_step_state = 3;
+ net->cc_mod.rtcc.step_cnt = 0;
+ }
+ goto out_decision;
+ }
+ /* The bw decreased but rtt stayed the same */
+ /* Probe point 4 */
+ probepoint |= ((4 << 16) | 0);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ if (net->cc_mod.rtcc.steady_step) {
+ oth = net->cc_mod.rtcc.vol_reduce;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.step_cnt;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.last_step_state;
+ SDT_PROBE(sctp, cwnd, net, rttstep,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ oth,
+ probepoint);
+ if ((net->cc_mod.rtcc.vol_reduce) &&
+ (inst_ind != SCTP_INST_GAINING)) {
+ net->cwnd += net->mtu;
+ net->cc_mod.rtcc.vol_reduce--;
+ }
+ net->cc_mod.rtcc.last_step_state = 4;
+ net->cc_mod.rtcc.step_cnt = 0;
+ }
+out_decision:
+ net->cc_mod.rtcc.lbw = nbw;
+ net->cc_mod.rtcc.lbw_rtt = net->rtt;
+ net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
+ if (inst_ind == SCTP_INST_GAINING) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+static int
+cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t vtag)
+{
+ uint64_t oth, probepoint;
+
+ /*
+ * BW increased, so update and return 0, since all actions in our
+ * table say to do the normal CC update. Note that we pay no
+ * attention to the inst_ind since our overall sum is increasing.
+ */
+ /* PROBE POINT 0 */
+ probepoint = (((uint64_t) net->cwnd) << 32);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ if (net->cc_mod.rtcc.steady_step) {
+ oth = net->cc_mod.rtcc.vol_reduce;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.step_cnt;
+ oth <<= 16;
+ oth |= net->cc_mod.rtcc.last_step_state;
+ SDT_PROBE(sctp, cwnd, net, rttstep,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | nbw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ oth,
+ probepoint);
+ net->cc_mod.rtcc.last_step_state = 0;
+ net->cc_mod.rtcc.step_cnt = 0;
+ net->cc_mod.rtcc.vol_reduce = 0;
+ }
+ net->cc_mod.rtcc.lbw = nbw;
+ net->cc_mod.rtcc.lbw_rtt = net->rtt;
+ net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
+ return (0);
+}
+
+/* RTCC Algoritm to limit growth of cwnd, return
+ * true if you want to NOT allow cwnd growth
+ */
+static int
+cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw)
+{
+ uint64_t bw_offset, rtt_offset;
+ uint64_t probepoint, rtt, vtag;
+ uint64_t bytes_for_this_rtt, inst_bw;
+ uint64_t div, inst_off;
+ int bw_shift;
+ uint8_t inst_ind;
+ int ret;
+
+ /*-
+ * Here we need to see if we want
+ * to limit cwnd growth due to increase
+ * in overall rtt but no increase in bw.
+ * We use the following table to figure
+ * out what we should do. When we return
+ * 0, cc update goes on as planned. If we
+ * return 1, then no cc update happens and cwnd
+ * stays where it is at.
+ * ----------------------------------
+ * BW | RTT | Action
+ * *********************************
+ * INC | INC | return 0
+ * ----------------------------------
+ * INC | SAME | return 0
+ * ----------------------------------
+ * INC | DECR | return 0
+ * ----------------------------------
+ * SAME | INC | return 1
+ * ----------------------------------
+ * SAME | SAME | return 1
+ * ----------------------------------
+ * SAME | DECR | return 0
+ * ----------------------------------
+ * DECR | INC | return 0 or 1 based on if we caused.
+ * ----------------------------------
+ * DECR | SAME | return 0
+ * ----------------------------------
+ * DECR | DECR | return 0
+ * ----------------------------------
+ *
+ * We are a bit fuzz on what an increase or
+ * decrease is. For BW it is the same if
+ * it did not change within 1/64th. For
+ * RTT it stayed the same if it did not
+ * change within 1/32nd
+ */
+ bw_shift = SCTP_BASE_SYSCTL(sctp_rttvar_bw);
+ rtt = stcb->asoc.my_vtag;
+ vtag = (rtt << 32) | (((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport);
+ probepoint = (((uint64_t) net->cwnd) << 32);
+ rtt = net->rtt;
+ if (net->cc_mod.rtcc.rtt_set_this_sack) {
+ net->cc_mod.rtcc.rtt_set_this_sack = 0;
+ bytes_for_this_rtt = net->cc_mod.rtcc.bw_bytes - net->cc_mod.rtcc.bw_bytes_at_last_rttc;
+ net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
+ if (net->rtt) {
+ div = net->rtt / 1000;
+ if (div) {
+ inst_bw = bytes_for_this_rtt / div;
+ inst_off = inst_bw >> bw_shift;
+ if (inst_bw > nbw)
+ inst_ind = SCTP_INST_GAINING;
+ else if ((inst_bw + inst_off) < nbw)
+ inst_ind = SCTP_INST_LOOSING;
+ else
+ inst_ind = SCTP_INST_NEUTRAL;
+ probepoint |= ((0xb << 16) | inst_ind);
+ } else {
+ inst_ind = net->cc_mod.rtcc.last_inst_ind;
+ inst_bw = bytes_for_this_rtt / (uint64_t) (net->rtt);
+ /* Can't determine do not change */
+ probepoint |= ((0xc << 16) | inst_ind);
+ }
+ } else {
+ inst_ind = net->cc_mod.rtcc.last_inst_ind;
+ inst_bw = bytes_for_this_rtt;
+ /* Can't determine do not change */
+ probepoint |= ((0xd << 16) | inst_ind);
+ }
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((nbw << 32) | inst_bw),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | rtt),
+ net->flight_size,
+ probepoint);
+ } else {
+ /* No rtt measurement, use last one */
+ inst_ind = net->cc_mod.rtcc.last_inst_ind;
+ }
+ bw_offset = net->cc_mod.rtcc.lbw >> bw_shift;
+ if (nbw > net->cc_mod.rtcc.lbw + bw_offset) {
+ ret = cc_bw_increase(stcb, net, nbw, vtag);
+ goto out;
+ }
+ rtt_offset = net->cc_mod.rtcc.lbw_rtt >> SCTP_BASE_SYSCTL(sctp_rttvar_rtt);
+ if (nbw < net->cc_mod.rtcc.lbw - bw_offset) {
+ ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, vtag, inst_ind);
+ goto out;
+ }
+ /*
+ * If we reach here then we are in a situation where the bw stayed
+ * the same.
+ */
+ ret = cc_bw_same(stcb, net, nbw, rtt_offset, vtag, inst_ind);
+out:
+ net->cc_mod.rtcc.last_inst_ind = inst_ind;
+ return (ret);
+}
+
+static void
+sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
struct sctp_association *asoc,
- int accum_moved, int reneged_all, int will_exit)
+ int accum_moved, int reneged_all SCTP_UNUSED, int will_exit, int use_rtcc)
{
struct sctp_nets *net;
-
+ int old_cwnd;
+ uint32_t t_ssthresh, t_cwnd, incr;
+ uint64_t t_ucwnd_sbw;
+ uint64_t t_path_mptcp;
+ uint64_t mptcp_like_alpha;
+ uint32_t srtt;
+ uint64_t max_path;
+
+ /* MT FIXME: Don't compute this over and over again */
+ t_ssthresh = 0;
+ t_cwnd = 0;
+ t_ucwnd_sbw = 0;
+ t_path_mptcp = 0;
+ mptcp_like_alpha = 1;
+ if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
+ (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2) ||
+ (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_MPTCP)) {
+ max_path = 0;
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ t_ssthresh += net->ssthresh;
+ t_cwnd += net->cwnd;
+ /* lastsa>>3; we don't need to devide ... */
+ srtt = net->lastsa;
+ if (srtt > 0) {
+ uint64_t tmp;
+
+ t_ucwnd_sbw += (uint64_t) net->cwnd / (uint64_t) srtt;
+ t_path_mptcp += (((uint64_t) net->cwnd) << SHIFT_MPTCP_MULTI_Z) /
+ (((uint64_t) net->mtu) * (uint64_t) srtt);
+ tmp = (((uint64_t) net->cwnd) << SHIFT_MPTCP_MULTI_N) /
+ ((uint64_t) net->mtu * (uint64_t) (srtt * srtt));
+ if (tmp > max_path) {
+ max_path = tmp;
+ }
+ }
+ }
+ if (t_path_mptcp > 0) {
+ mptcp_like_alpha = max_path / (t_path_mptcp * t_path_mptcp);
+ } else {
+ mptcp_like_alpha = 1;
+ }
+ }
+ if (t_ssthresh == 0) {
+ t_ssthresh = 1;
+ }
+ if (t_ucwnd_sbw == 0) {
+ t_ucwnd_sbw = 1;
+ }
/******************************/
/* update cwnd and Early FR */
/******************************/
@@ -168,49 +724,12 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT fast recovery code. Need to debug.
*/
if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
- if (compare_with_wrap(asoc->last_acked_seq,
- net->fast_recovery_tsn, MAX_TSN) ||
- (asoc->last_acked_seq == net->fast_recovery_tsn) ||
- compare_with_wrap(net->pseudo_cumack, net->fast_recovery_tsn, MAX_TSN) ||
- (net->pseudo_cumack == net->fast_recovery_tsn)) {
+ if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
+ SCTP_TSN_GE(net->pseudo_cumack, net->fast_recovery_tsn)) {
net->will_exit_fast_recovery = 1;
}
}
#endif
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- /*
- * So, first of all do we need to have a Early FR
- * timer running?
- */
- if ((!TAILQ_EMPTY(&asoc->sent_queue) &&
- (net->ref_count > 1) &&
- (net->flight_size < net->cwnd)) ||
- (reneged_all)) {
- /*
- * yes, so in this case stop it if its
- * running, and then restart it. Reneging
- * all is a special case where we want to
- * run the Early FR timer and then force the
- * last few unacked to be sent, causing us
- * to illicit a sack with gaps to force out
- * the others.
- */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
- }
- SCTP_STAT_INCR(sctps_earlyfrstrid);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
- } else {
- /* No, stop it if its running */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
- }
- }
- }
/* if nothing was acked on this destination skip it */
if (net->net_ack == 0) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
@@ -218,56 +737,14 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
}
continue;
}
- if (net->net_ack2 > 0) {
- /*
- * Karn's rule applies to clearing error count, this
- * is optional.
- */
- net->error_count = 0;
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
- SCTP_ADDR_NOT_REACHABLE) {
- /* addr came good */
- net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
- net->dest_state |= SCTP_ADDR_REACHABLE;
- sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
- SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
- /* now was it the primary? if so restore */
- if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
- (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
- }
- }
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination
- * is in PF state, set the destination to active
- * state and set the cwnd to one or two MTU's based
- * on whether PF1 or PF2 is being used.
- *
- * Should we stop any running T3 timer here?
- */
- if ((asoc->sctp_cmt_on_off == 1) &&
- (asoc->sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- net->cwnd = net->mtu * asoc->sctp_cmt_pf;
- SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
- net, net->cwnd);
- /*
- * Since the cwnd value is explicitly set,
- * skip the code that updates the cwnd
- * value.
- */
- goto skip_cwnd_update;
- }
- }
#ifdef JANA_CMT_FAST_RECOVERY
/*
* CMT fast recovery code
*/
/*
- * if (sctp_cmt_on_off == 1 &&
- * net->fast_retran_loss_recovery &&
- * net->will_exit_fast_recovery == 0) { @@@ Do something }
- * else if (sctp_cmt_on_off == 0 &&
+ * if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
+ * && net->will_exit_fast_recovery == 0) { @@@ Do something
+ * } else if (sctp_cmt_on_off == 0 &&
* asoc->fast_retran_loss_recovery && will_exit == 0) {
*/
#endif
@@ -279,31 +756,143 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* If we are in loss recovery we skip any cwnd
* update
*/
- goto skip_cwnd_update;
+ return;
+ }
+ /*
+ * Did any measurements go on for this network?
+ */
+ if (use_rtcc && (net->cc_mod.rtcc.tls_needs_set > 0)) {
+ uint64_t nbw;
+
+ /*
+ * At this point our bw_bytes has been updated by
+ * incoming sack information.
+ *
+ * But our bw may not yet be set.
+ *
+ */
+ if ((net->cc_mod.rtcc.new_tot_time / 1000) > 0) {
+ nbw = net->cc_mod.rtcc.bw_bytes / (net->cc_mod.rtcc.new_tot_time / 1000);
+ } else {
+ nbw = net->cc_mod.rtcc.bw_bytes;
+ }
+ if (net->cc_mod.rtcc.lbw) {
+ if (cc_bw_limit(stcb, net, nbw)) {
+ /* Hold here, no update */
+ continue;
+ }
+ } else {
+ uint64_t vtag, probepoint;
+
+ probepoint = (((uint64_t) net->cwnd) << 32);
+ probepoint |= ((0xa << 16) | 0);
+ vtag = (net->rtt << 32) |
+ (((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) |
+ (stcb->rport);
+
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ nbw,
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ net->cc_mod.rtcc.lbw = nbw;
+ net->cc_mod.rtcc.lbw_rtt = net->rtt;
+ if (net->cc_mod.rtcc.rtt_set_this_sack) {
+ net->cc_mod.rtcc.rtt_set_this_sack = 0;
+ net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
+ }
+ }
}
/*
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
* moved.
*/
if (accum_moved ||
- ((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
+ ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
/* If the cumulative ack moved we can proceed */
if (net->cwnd <= net->ssthresh) {
/* We are in slow start */
if (net->flight_size + net->net_ack >= net->cwnd) {
- if (net->net_ack > (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable))) {
- net->cwnd += (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable));
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, net->mtu,
- SCTP_CWND_LOG_FROM_SS);
+ uint32_t limit;
+
+ old_cwnd = net->cwnd;
+ switch (asoc->sctp_cmt_on_off) {
+ case SCTP_CMT_RPV1:
+ limit = (uint32_t) (((uint64_t) net->mtu *
+ (uint64_t) SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
+ (uint64_t) net->ssthresh) /
+ (uint64_t) t_ssthresh);
+ incr = (uint32_t) (((uint64_t) net->net_ack *
+ (uint64_t) net->ssthresh) /
+ (uint64_t) t_ssthresh);
+ if (incr > limit) {
+ incr = limit;
+ }
+ if (incr == 0) {
+ incr = 1;
}
- } else {
- net->cwnd += net->net_ack;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, net->net_ack,
- SCTP_CWND_LOG_FROM_SS);
+ break;
+ case SCTP_CMT_RPV2:
+ /*
+ * lastsa>>3; we don't need
+ * to divide ...
+ */
+ srtt = net->lastsa;
+ if (srtt == 0) {
+ srtt = 1;
}
+ limit = (uint32_t) (((uint64_t) net->mtu *
+ (uint64_t) SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
+ (uint64_t) net->cwnd) /
+ ((uint64_t) srtt * t_ucwnd_sbw));
+ /* INCREASE FACTOR */
+ incr = (uint32_t) (((uint64_t) net->net_ack *
+ (uint64_t) net->cwnd) /
+ ((uint64_t) srtt * t_ucwnd_sbw));
+ /* INCREASE FACTOR */
+ if (incr > limit) {
+ incr = limit;
+ }
+ if (incr == 0) {
+ incr = 1;
+ }
+ break;
+ case SCTP_CMT_MPTCP:
+ limit = (uint32_t) (((uint64_t) net->mtu *
+ mptcp_like_alpha *
+ (uint64_t) SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) >>
+ SHIFT_MPTCP_MULTI);
+ incr = (uint32_t) (((uint64_t) net->net_ack *
+ mptcp_like_alpha) >>
+ SHIFT_MPTCP_MULTI);
+ if (incr > limit) {
+ incr = limit;
+ }
+ if (incr > net->net_ack) {
+ incr = net->net_ack;
+ }
+ if (incr > net->mtu) {
+ incr = net->mtu;
+ }
+ break;
+ default:
+ incr = net->net_ack;
+ if (incr > net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) {
+ incr = net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable);
+ }
+ break;
}
+ net->cwnd += incr;
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
+ sctp_log_cwnd(stcb, net, incr,
+ SCTP_CWND_LOG_FROM_SS);
+ }
+ SDT_PROBE(sctp, cwnd, net, ack,
+ stcb->asoc.my_vtag,
+ ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
+ net,
+ old_cwnd, net->cwnd);
} else {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
sctp_log_cwnd(stcb, net, net->net_ack,
@@ -320,7 +909,52 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
if ((net->flight_size + net->net_ack >= net->cwnd) &&
(net->partial_bytes_acked >= net->cwnd)) {
net->partial_bytes_acked -= net->cwnd;
- net->cwnd += net->mtu;
+ old_cwnd = net->cwnd;
+ switch (asoc->sctp_cmt_on_off) {
+ case SCTP_CMT_RPV1:
+ incr = (uint32_t) (((uint64_t) net->mtu *
+ (uint64_t) net->ssthresh) /
+ (uint64_t) t_ssthresh);
+ if (incr == 0) {
+ incr = 1;
+ }
+ break;
+ case SCTP_CMT_RPV2:
+ /*
+ * lastsa>>3; we don't need
+ * to divide ...
+ */
+ srtt = net->lastsa;
+ if (srtt == 0) {
+ srtt = 1;
+ }
+ incr = (uint32_t) ((uint64_t) net->mtu *
+ (uint64_t) net->cwnd /
+ ((uint64_t) srtt *
+ t_ucwnd_sbw));
+ /* INCREASE FACTOR */
+ if (incr == 0) {
+ incr = 1;
+ }
+ break;
+ case SCTP_CMT_MPTCP:
+ incr = (uint32_t) ((mptcp_like_alpha *
+ (uint64_t) net->cwnd) >>
+ SHIFT_MPTCP_MULTI);
+ if (incr > net->mtu) {
+ incr = net->mtu;
+ }
+ break;
+ default:
+ incr = net->mtu;
+ break;
+ }
+ net->cwnd += incr;
+ SDT_PROBE(sctp, cwnd, net, ack,
+ stcb->asoc.my_vtag,
+ ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
+ net,
+ old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, net->mtu,
SCTP_CWND_LOG_FROM_CA);
@@ -338,69 +972,172 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
SCTP_CWND_LOG_NO_CUMACK);
}
}
-skip_cwnd_update:
- /*
- * NOW, according to Karn's rule do we need to restore the
- * RTO timer back? Check our net_ack2. If not set then we
- * have a ambiguity.. i.e. all data ack'd was sent to more
- * than one place.
- */
- if (net->net_ack2) {
- /* restore any doubled timers */
- net->RTO = ((net->lastsa >> 2) + net->lastsv) >> 1;
- if (net->RTO < stcb->asoc.minrto) {
- net->RTO = stcb->asoc.minrto;
- }
- if (net->RTO > stcb->asoc.maxrto) {
- net->RTO = stcb->asoc.maxrto;
- }
- }
}
}
-void
+static void
+sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net)
+{
+ int old_cwnd;
+
+ old_cwnd = net->cwnd;
+ net->cwnd = net->mtu;
+ SDT_PROBE(sctp, cwnd, net, ack,
+ stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
+ old_cwnd, net->cwnd);
+ SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
+ (void *)net, net->cwnd);
+}
+
+
+static void
sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
{
int old_cwnd = net->cwnd;
+ uint32_t t_ssthresh, t_cwnd;
+ uint64_t t_ucwnd_sbw;
+
+ /* MT FIXME: Don't compute this over and over again */
+ t_ssthresh = 0;
+ t_cwnd = 0;
+ if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
+ (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
+ struct sctp_nets *lnet;
+ uint32_t srtt;
+
+ t_ucwnd_sbw = 0;
+ TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
+ t_ssthresh += lnet->ssthresh;
+ t_cwnd += lnet->cwnd;
+ srtt = lnet->lastsa;
+ /* lastsa>>3; we don't need to divide ... */
+ if (srtt > 0) {
+ t_ucwnd_sbw += (uint64_t) lnet->cwnd / (uint64_t) srtt;
+ }
+ }
+ if (t_ssthresh < 1) {
+ t_ssthresh = 1;
+ }
+ if (t_ucwnd_sbw < 1) {
+ t_ucwnd_sbw = 1;
+ }
+ if (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) {
+ net->ssthresh = (uint32_t) (((uint64_t) 4 *
+ (uint64_t) net->mtu *
+ (uint64_t) net->ssthresh) /
+ (uint64_t) t_ssthresh);
+ } else {
+ uint64_t cc_delta;
- net->ssthresh = max(net->cwnd / 2, 4 * net->mtu);
+ srtt = net->lastsa;
+ /* lastsa>>3; we don't need to divide ... */
+ if (srtt == 0) {
+ srtt = 1;
+ }
+ cc_delta = t_ucwnd_sbw * (uint64_t) srtt / 2;
+ if (cc_delta < t_cwnd) {
+ net->ssthresh = (uint32_t) ((uint64_t) t_cwnd - cc_delta);
+ } else {
+ net->ssthresh = net->mtu;
+ }
+ }
+ if ((net->cwnd > t_cwnd / 2) &&
+ (net->ssthresh < net->cwnd - t_cwnd / 2)) {
+ net->ssthresh = net->cwnd - t_cwnd / 2;
+ }
+ if (net->ssthresh < net->mtu) {
+ net->ssthresh = net->mtu;
+ }
+ } else {
+ net->ssthresh = max(net->cwnd / 2, 4 * net->mtu);
+ }
net->cwnd = net->mtu;
net->partial_bytes_acked = 0;
-
+ SDT_PROBE(sctp, cwnd, net, to,
+ stcb->asoc.my_vtag,
+ ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
+ net,
+ old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
}
}
-void
-sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net)
+static void
+sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *net,
+ int in_window, int num_pkt_lost, int use_rtcc)
{
int old_cwnd = net->cwnd;
- SCTP_STAT_INCR(sctps_ecnereducedcwnd);
- net->ssthresh = net->cwnd / 2;
- if (net->ssthresh < net->mtu) {
- net->ssthresh = net->mtu;
- /* here back off the timer as well, to slow us down */
- net->RTO <<= 1;
- }
- net->cwnd = net->ssthresh;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
+ if ((use_rtcc) && (net->lan_type == SCTP_LAN_LOCAL) && (net->cc_mod.rtcc.use_dccc_ecn)) {
+ /* Data center Congestion Control */
+ if (in_window == 0) {
+ /*
+ * Go to CA with the cwnd at the point we sent the
+ * TSN that was marked with a CE.
+ */
+ if (net->ecn_prev_cwnd < net->cwnd) {
+ /* Restore to prev cwnd */
+ net->cwnd = net->ecn_prev_cwnd - (net->mtu * num_pkt_lost);
+ } else {
+ /* Just cut in 1/2 */
+ net->cwnd /= 2;
+ }
+ /* Drop to CA */
+ net->ssthresh = net->cwnd - (num_pkt_lost * net->mtu);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
+ sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
+ }
+ } else {
+ /*
+ * Further tuning down required over the drastic
+ * orginal cut
+ */
+ net->ssthresh -= (net->mtu * num_pkt_lost);
+ net->cwnd -= (net->mtu * num_pkt_lost);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
+ sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
+ }
+ }
+ SCTP_STAT_INCR(sctps_ecnereducedcwnd);
+ } else {
+ if (in_window == 0) {
+ SCTP_STAT_INCR(sctps_ecnereducedcwnd);
+ net->ssthresh = net->cwnd / 2;
+ if (net->ssthresh < net->mtu) {
+ net->ssthresh = net->mtu;
+ /*
+ * here back off the timer as well, to slow
+ * us down
+ */
+ net->RTO <<= 1;
+ }
+ net->cwnd = net->ssthresh;
+ SDT_PROBE(sctp, cwnd, net, ecn,
+ stcb->asoc.my_vtag,
+ ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
+ net,
+ old_cwnd, net->cwnd);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
+ sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
+ }
+ }
}
+
}
-void
+static void
sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
uint32_t * bottle_bw, uint32_t * on_queue)
{
uint32_t bw_avail;
- int rtt, incr;
+ int rtt;
+ unsigned int incr;
int old_cwnd = net->cwnd;
- /* need real RTT for this calc */
- rtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
+ /* need real RTT in msd for this calc */
+ rtt = net->rtt / 1000;
/* get bottle neck bw */
*bottle_bw = ntohl(cp->bottle_bw);
/* and whats on queue */
@@ -480,8 +1217,11 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
* Take 1/4 of the space left or max burst up .. whichever
* is less.
*/
- incr = min((bw_avail - *on_queue) >> 2,
- stcb->asoc.max_burst * net->mtu);
+ incr = (bw_avail - *on_queue) >> 2;
+ if ((stcb->asoc.max_burst > 0) &&
+ (stcb->asoc.max_burst * net->mtu < incr)) {
+ incr = stcb->asoc.max_burst * net->mtu;
+ }
net->cwnd += incr;
}
if (net->cwnd > bw_avail) {
@@ -494,6 +1234,11 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
}
if (net->cwnd - old_cwnd != 0) {
/* log only changes */
+ SDT_PROBE(sctp, cwnd, net, pd,
+ stcb->asoc.my_vtag,
+ ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
+ net,
+ old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
SCTP_CWND_LOG_FROM_SAT);
@@ -501,7 +1246,7 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
}
}
-void
+static void
sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
struct sctp_nets *net, int burst_limit)
{
@@ -509,34 +1254,258 @@ sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
if (net->ssthresh < net->cwnd)
net->ssthresh = net->cwnd;
- net->cwnd = (net->flight_size + (burst_limit * net->mtu));
+ if (burst_limit) {
+ net->cwnd = (net->flight_size + (burst_limit * net->mtu));
+ SDT_PROBE(sctp, cwnd, net, bl,
+ stcb->asoc.my_vtag,
+ ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
+ net,
+ old_cwnd, net->cwnd);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
+ sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
+ }
+ }
+}
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
+static void
+sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
+ struct sctp_association *asoc,
+ int accum_moved, int reneged_all, int will_exit)
+{
+ /* Passing a zero argument in last disables the rtcc algoritm */
+ sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 0);
+}
+
+static void
+sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
+ int in_window, int num_pkt_lost)
+{
+ /* Passing a zero argument in last disables the rtcc algoritm */
+ sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 0);
+}
+
+/* Here starts the RTCCVAR type CC invented by RRS which
+ * is a slight mod to RFC2581. We reuse a common routine or
+ * two since these algoritms are so close and need to
+ * remain the same.
+ */
+static void
+sctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
+ int in_window, int num_pkt_lost)
+{
+ sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 1);
+}
+
+
+static
+void
+sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets *net,
+ struct sctp_tmit_chunk *tp1)
+{
+ net->cc_mod.rtcc.bw_bytes += tp1->send_size;
+}
+
+static void
+sctp_cwnd_prepare_rtcc_net_for_sack(struct sctp_tcb *stcb SCTP_UNUSED,
+ struct sctp_nets *net)
+{
+ if (net->cc_mod.rtcc.tls_needs_set > 0) {
+ /* We had a bw measurment going on */
+ struct timeval ltls;
+
+ SCTP_GETPTIME_TIMEVAL(&ltls);
+ timevalsub(&ltls, &net->cc_mod.rtcc.tls);
+ net->cc_mod.rtcc.new_tot_time = (ltls.tv_sec * 1000000) + ltls.tv_usec;
}
}
-void
-sctp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, struct sctp_nets *net)
+static void
+sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb,
+ struct sctp_nets *net)
{
- int old_cwnd = net->cwnd;
+ uint64_t vtag, probepoint;
+
+ if (net->cc_mod.rtcc.lbw) {
+ /* Clear the old bw.. we went to 0 in-flight */
+ vtag = (net->rtt << 32) | (((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) |
+ (stcb->rport);
+ probepoint = (((uint64_t) net->cwnd) << 32);
+ /* Probe point 8 */
+ probepoint |= ((8 << 16) | 0);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ ((net->cc_mod.rtcc.lbw << 32) | 0),
+ ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
+ net->flight_size,
+ probepoint);
+ net->cc_mod.rtcc.lbw_rtt = 0;
+ net->cc_mod.rtcc.cwnd_at_bw_set = 0;
+ net->cc_mod.rtcc.lbw = 0;
+ net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
+ net->cc_mod.rtcc.vol_reduce = 0;
+ net->cc_mod.rtcc.bw_tot_time = 0;
+ net->cc_mod.rtcc.bw_bytes = 0;
+ net->cc_mod.rtcc.tls_needs_set = 0;
+ if (net->cc_mod.rtcc.steady_step) {
+ net->cc_mod.rtcc.vol_reduce = 0;
+ net->cc_mod.rtcc.step_cnt = 0;
+ net->cc_mod.rtcc.last_step_state = 0;
+ }
+ if (net->cc_mod.rtcc.ret_from_eq) {
+ /* less aggressive one - reset cwnd too */
+ uint32_t cwnd_in_mtu, cwnd;
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
- /*
- * make a small adjustment to cwnd and force to CA.
- */
- if (net->cwnd > net->mtu)
- /* drop down one MTU after sending */
- net->cwnd -= net->mtu;
- if (net->cwnd < net->ssthresh)
- /* still in SS move to CA */
- net->ssthresh = net->cwnd - 1;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, (old_cwnd - net->cwnd), SCTP_CWND_LOG_FROM_FR);
+ cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
+ if (cwnd_in_mtu == 0) {
+ /*
+ * Using 0 means that the value of RFC 4960
+ * is used.
+ */
+ cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
+ } else {
+ /*
+ * We take the minimum of the burst limit
+ * and the initial congestion window.
+ */
+ if ((stcb->asoc.max_burst > 0) && (cwnd_in_mtu > stcb->asoc.max_burst))
+ cwnd_in_mtu = stcb->asoc.max_burst;
+ cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
+ }
+ if (net->cwnd > cwnd) {
+ /*
+ * Only set if we are not a timeout (i.e.
+ * down to 1 mtu)
+ */
+ net->cwnd = cwnd;
+ }
+ }
+ }
+}
+
+static void
+sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb,
+ struct sctp_nets *net)
+{
+ uint64_t vtag, probepoint;
+
+ sctp_set_initial_cc_param(stcb, net);
+ stcb->asoc.use_precise_time = 1;
+ probepoint = (((uint64_t) net->cwnd) << 32);
+ probepoint |= ((9 << 16) | 0);
+ vtag = (net->rtt << 32) |
+ (((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) |
+ (stcb->rport);
+ SDT_PROBE(sctp, cwnd, net, rttvar,
+ vtag,
+ 0,
+ 0,
+ 0,
+ probepoint);
+ net->cc_mod.rtcc.lbw_rtt = 0;
+ net->cc_mod.rtcc.cwnd_at_bw_set = 0;
+ net->cc_mod.rtcc.vol_reduce = 0;
+ net->cc_mod.rtcc.lbw = 0;
+ net->cc_mod.rtcc.vol_reduce = 0;
+ net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
+ net->cc_mod.rtcc.bw_tot_time = 0;
+ net->cc_mod.rtcc.bw_bytes = 0;
+ net->cc_mod.rtcc.tls_needs_set = 0;
+ net->cc_mod.rtcc.ret_from_eq = SCTP_BASE_SYSCTL(sctp_rttvar_eqret);
+ net->cc_mod.rtcc.steady_step = SCTP_BASE_SYSCTL(sctp_steady_step);
+ net->cc_mod.rtcc.use_dccc_ecn = SCTP_BASE_SYSCTL(sctp_use_dccc_ecn);
+ net->cc_mod.rtcc.step_cnt = 0;
+ net->cc_mod.rtcc.last_step_state = 0;
+
+
+}
+
+static int
+sctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget,
+ struct sctp_cc_option *cc_opt)
+{
+ struct sctp_nets *net;
+
+ if (setorget == 1) {
+ /* a set */
+ if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
+ if ((cc_opt->aid_value.assoc_value != 0) &&
+ (cc_opt->aid_value.assoc_value != 1)) {
+ return (EINVAL);
+ }
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ net->cc_mod.rtcc.ret_from_eq = cc_opt->aid_value.assoc_value;
+ }
+ } else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
+ if ((cc_opt->aid_value.assoc_value != 0) &&
+ (cc_opt->aid_value.assoc_value != 1)) {
+ return (EINVAL);
+ }
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ net->cc_mod.rtcc.use_dccc_ecn = cc_opt->aid_value.assoc_value;
+ }
+ } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ net->cc_mod.rtcc.steady_step = cc_opt->aid_value.assoc_value;
+ }
+ } else {
+ return (EINVAL);
+ }
+ } else {
+ /* a get */
+ if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
+ net = TAILQ_FIRST(&stcb->asoc.nets);
+ if (net == NULL) {
+ return (EFAULT);
+ }
+ cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.ret_from_eq;
+ } else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
+ net = TAILQ_FIRST(&stcb->asoc.nets);
+ if (net == NULL) {
+ return (EFAULT);
+ }
+ cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.use_dccc_ecn;
+ } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
+ net = TAILQ_FIRST(&stcb->asoc.nets);
+ if (net == NULL) {
+ return (EFAULT);
+ }
+ cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.steady_step;
+ } else {
+ return (EINVAL);
+ }
+ }
+ return (0);
+}
+
+static void
+sctp_cwnd_update_rtcc_packet_transmitted(struct sctp_tcb *stcb SCTP_UNUSED,
+ struct sctp_nets *net)
+{
+ if (net->cc_mod.rtcc.tls_needs_set == 0) {
+ SCTP_GETPTIME_TIMEVAL(&net->cc_mod.rtcc.tls);
+ net->cc_mod.rtcc.tls_needs_set = 2;
}
}
+static void
+sctp_cwnd_update_rtcc_after_sack(struct sctp_tcb *stcb,
+ struct sctp_association *asoc,
+ int accum_moved, int reneged_all, int will_exit)
+{
+ /* Passing a one argument at the last enables the rtcc algoritm */
+ sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 1);
+}
+
+static void
+sctp_rtt_rtcc_calculated(struct sctp_tcb *stcb SCTP_UNUSED,
+ struct sctp_nets *net,
+ struct timeval *now SCTP_UNUSED)
+{
+ net->cc_mod.rtcc.rtt_set_this_sack = 1;
+}
+
+/* Here starts Sally Floyds HS-TCP */
+
struct sctp_hs_raise_drop {
int32_t cwnd;
int32_t increase;
@@ -628,9 +1597,7 @@ sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
cur_val = net->cwnd >> 10;
indx = SCTP_HS_TABLE_SIZE - 1;
-#ifdef SCTP_DEBUG
- printf("HS CC CAlled.\n");
-#endif
+
if (cur_val < sctp_cwnd_adjust[0].cwnd) {
/* normal mode */
if (net->net_ack > net->mtu) {
@@ -700,19 +1667,19 @@ sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
}
}
-void
+static void
sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
struct sctp_association *asoc)
{
struct sctp_nets *net;
/*
- * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
+ * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) ||
- (asoc->sctp_cmt_on_off == 1)) {
+ (asoc->sctp_cmt_on_off > 0)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*
@@ -750,13 +1717,6 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
}
- /*
- * Disable Nonce Sum Checking and store the
- * resync tsn
- */
- asoc->nonce_sum_check = 0;
- asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
-
sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
@@ -772,10 +1732,10 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
}
}
-void
+static void
sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
struct sctp_association *asoc,
- int accum_moved, int reneged_all, int will_exit)
+ int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
{
struct sctp_nets *net;
@@ -789,49 +1749,12 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT fast recovery code. Need to debug.
*/
if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
- if (compare_with_wrap(asoc->last_acked_seq,
- net->fast_recovery_tsn, MAX_TSN) ||
- (asoc->last_acked_seq == net->fast_recovery_tsn) ||
- compare_with_wrap(net->pseudo_cumack, net->fast_recovery_tsn, MAX_TSN) ||
- (net->pseudo_cumack == net->fast_recovery_tsn)) {
+ if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
+ SCTP_TSN_GE(net->pseudo_cumack, net->fast_recovery_tsn)) {
net->will_exit_fast_recovery = 1;
}
}
#endif
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- /*
- * So, first of all do we need to have a Early FR
- * timer running?
- */
- if ((!TAILQ_EMPTY(&asoc->sent_queue) &&
- (net->ref_count > 1) &&
- (net->flight_size < net->cwnd)) ||
- (reneged_all)) {
- /*
- * yes, so in this case stop it if its
- * running, and then restart it. Reneging
- * all is a special case where we want to
- * run the Early FR timer and then force the
- * last few unacked to be sent, causing us
- * to illicit a sack with gaps to force out
- * the others.
- */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
- }
- SCTP_STAT_INCR(sctps_earlyfrstrid);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
- } else {
- /* No, stop it if its running */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
- }
- }
- }
/* if nothing was acked on this destination skip it */
if (net->net_ack == 0) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
@@ -839,56 +1762,14 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
}
continue;
}
- if (net->net_ack2 > 0) {
- /*
- * Karn's rule applies to clearing error count, this
- * is optional.
- */
- net->error_count = 0;
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
- SCTP_ADDR_NOT_REACHABLE) {
- /* addr came good */
- net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
- net->dest_state |= SCTP_ADDR_REACHABLE;
- sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
- SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
- /* now was it the primary? if so restore */
- if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
- (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
- }
- }
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination
- * is in PF state, set the destination to active
- * state and set the cwnd to one or two MTU's based
- * on whether PF1 or PF2 is being used.
- *
- * Should we stop any running T3 timer here?
- */
- if ((asoc->sctp_cmt_on_off == 1) &&
- (asoc->sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- net->cwnd = net->mtu * asoc->sctp_cmt_pf;
- SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
- net, net->cwnd);
- /*
- * Since the cwnd value is explicitly set,
- * skip the code that updates the cwnd
- * value.
- */
- goto skip_cwnd_update;
- }
- }
#ifdef JANA_CMT_FAST_RECOVERY
/*
* CMT fast recovery code
*/
/*
- * if (sctp_cmt_on_off == 1 &&
- * net->fast_retran_loss_recovery &&
- * net->will_exit_fast_recovery == 0) { @@@ Do something }
- * else if (sctp_cmt_on_off == 0 &&
+ * if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
+ * && net->will_exit_fast_recovery == 0) { @@@ Do something
+ * } else if (sctp_cmt_on_off == 0 &&
* asoc->fast_retran_loss_recovery && will_exit == 0) {
*/
#endif
@@ -900,14 +1781,14 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
* If we are in loss recovery we skip any cwnd
* update
*/
- goto skip_cwnd_update;
+ return;
}
/*
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
* moved.
*/
if (accum_moved ||
- ((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
+ ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
/* If the cumulative ack moved we can proceed */
if (net->cwnd <= net->ssthresh) {
/* We are in slow start */
@@ -945,23 +1826,6 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
SCTP_CWND_LOG_NO_CUMACK);
}
}
-skip_cwnd_update:
- /*
- * NOW, according to Karn's rule do we need to restore the
- * RTO timer back? Check our net_ack2. If not set then we
- * have a ambiguity.. i.e. all data ack'd was sent to more
- * than one place.
- */
- if (net->net_ack2) {
- /* restore any doubled timers */
- net->RTO = ((net->lastsa >> 2) + net->lastsv) >> 1;
- if (net->RTO < stcb->asoc.minrto) {
- net->RTO = stcb->asoc.minrto;
- }
- if (net->RTO > stcb->asoc.maxrto) {
- net->RTO = stcb->asoc.maxrto;
- }
- }
}
}
@@ -981,19 +1845,19 @@ static int use_bandwidth_switch = 1;
static inline int
between(uint32_t seq1, uint32_t seq2, uint32_t seq3)
{
- return seq3 - seq2 >= seq1 - seq2;
+ return (seq3 - seq2 >= seq1 - seq2);
}
static inline uint32_t
htcp_cong_time(struct htcp *ca)
{
- return sctp_get_tick_count() - ca->last_cong;
+ return (sctp_get_tick_count() - ca->last_cong);
}
static inline uint32_t
htcp_ccount(struct htcp *ca)
{
- return htcp_cong_time(ca) / ca->minRTT;
+ return (htcp_cong_time(ca) / ca->minRTT);
}
static inline void
@@ -1010,39 +1874,39 @@ htcp_reset(struct htcp *ca)
static uint32_t
htcp_cwnd_undo(struct sctp_tcb *stcb, struct sctp_nets *net)
{
- net->htcp_ca.last_cong = net->htcp_ca.undo_last_cong;
- net->htcp_ca.maxRTT = net->htcp_ca.undo_maxRTT;
- net->htcp_ca.old_maxB = net->htcp_ca.undo_old_maxB;
- return max(net->cwnd, ((net->ssthresh / net->mtu << 7) / net->htcp_ca.beta) * net->mtu);
+ net->cc_mod.htcp_ca.last_cong = net->cc_mod.htcp_ca.undo_last_cong;
+ net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.undo_maxRTT;
+ net->cc_mod.htcp_ca.old_maxB = net->cc_mod.htcp_ca.undo_old_maxB;
+ return (max(net->cwnd, ((net->ssthresh / net->mtu << 7) / net->cc_mod.htcp_ca.beta) * net->mtu));
}
#endif
static inline void
-measure_rtt(struct sctp_tcb *stcb, struct sctp_nets *net)
+measure_rtt(struct sctp_nets *net)
{
- uint32_t srtt = net->lastsa >> 3;
+ uint32_t srtt = net->lastsa >> SCTP_RTT_SHIFT;
/* keep track of minimum RTT seen so far, minRTT is zero at first */
- if (net->htcp_ca.minRTT > srtt || !net->htcp_ca.minRTT)
- net->htcp_ca.minRTT = srtt;
+ if (net->cc_mod.htcp_ca.minRTT > srtt || !net->cc_mod.htcp_ca.minRTT)
+ net->cc_mod.htcp_ca.minRTT = srtt;
/* max RTT */
- if (net->fast_retran_ip == 0 && net->ssthresh < 0xFFFF && htcp_ccount(&net->htcp_ca) > 3) {
- if (net->htcp_ca.maxRTT < net->htcp_ca.minRTT)
- net->htcp_ca.maxRTT = net->htcp_ca.minRTT;
- if (net->htcp_ca.maxRTT < srtt && srtt <= net->htcp_ca.maxRTT + MSEC_TO_TICKS(20))
- net->htcp_ca.maxRTT = srtt;
+ if (net->fast_retran_ip == 0 && net->ssthresh < 0xFFFF && htcp_ccount(&net->cc_mod.htcp_ca) > 3) {
+ if (net->cc_mod.htcp_ca.maxRTT < net->cc_mod.htcp_ca.minRTT)
+ net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.minRTT;
+ if (net->cc_mod.htcp_ca.maxRTT < srtt && srtt <= net->cc_mod.htcp_ca.maxRTT + MSEC_TO_TICKS(20))
+ net->cc_mod.htcp_ca.maxRTT = srtt;
}
}
static void
-measure_achieved_throughput(struct sctp_tcb *stcb, struct sctp_nets *net)
+measure_achieved_throughput(struct sctp_nets *net)
{
uint32_t now = sctp_get_tick_count();
if (net->fast_retran_ip == 0)
- net->htcp_ca.bytes_acked = net->net_ack;
+ net->cc_mod.htcp_ca.bytes_acked = net->net_ack;
if (!use_bandwidth_switch)
return;
@@ -1050,29 +1914,28 @@ measure_achieved_throughput(struct sctp_tcb *stcb, struct sctp_nets *net)
/* achieved throughput calculations */
/* JRS - not 100% sure of this statement */
if (net->fast_retran_ip == 1) {
- net->htcp_ca.bytecount = 0;
- net->htcp_ca.lasttime = now;
+ net->cc_mod.htcp_ca.bytecount = 0;
+ net->cc_mod.htcp_ca.lasttime = now;
return;
}
- net->htcp_ca.bytecount += net->net_ack;
-
- if (net->htcp_ca.bytecount >= net->cwnd - ((net->htcp_ca.alpha >> 7 ? : 1) * net->mtu)
- && now - net->htcp_ca.lasttime >= net->htcp_ca.minRTT
- && net->htcp_ca.minRTT > 0) {
- uint32_t cur_Bi = net->htcp_ca.bytecount / net->mtu * hz / (now - net->htcp_ca.lasttime);
+ net->cc_mod.htcp_ca.bytecount += net->net_ack;
+ if ((net->cc_mod.htcp_ca.bytecount >= net->cwnd - (((net->cc_mod.htcp_ca.alpha >> 7) ? (net->cc_mod.htcp_ca.alpha >> 7) : 1) * net->mtu)) &&
+ (now - net->cc_mod.htcp_ca.lasttime >= net->cc_mod.htcp_ca.minRTT) &&
+ (net->cc_mod.htcp_ca.minRTT > 0)) {
+ uint32_t cur_Bi = net->cc_mod.htcp_ca.bytecount / net->mtu * hz / (now - net->cc_mod.htcp_ca.lasttime);
- if (htcp_ccount(&net->htcp_ca) <= 3) {
+ if (htcp_ccount(&net->cc_mod.htcp_ca) <= 3) {
/* just after backoff */
- net->htcp_ca.minB = net->htcp_ca.maxB = net->htcp_ca.Bi = cur_Bi;
+ net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi = cur_Bi;
} else {
- net->htcp_ca.Bi = (3 * net->htcp_ca.Bi + cur_Bi) / 4;
- if (net->htcp_ca.Bi > net->htcp_ca.maxB)
- net->htcp_ca.maxB = net->htcp_ca.Bi;
- if (net->htcp_ca.minB > net->htcp_ca.maxB)
- net->htcp_ca.minB = net->htcp_ca.maxB;
+ net->cc_mod.htcp_ca.Bi = (3 * net->cc_mod.htcp_ca.Bi + cur_Bi) / 4;
+ if (net->cc_mod.htcp_ca.Bi > net->cc_mod.htcp_ca.maxB)
+ net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi;
+ if (net->cc_mod.htcp_ca.minB > net->cc_mod.htcp_ca.maxB)
+ net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB;
}
- net->htcp_ca.bytecount = 0;
- net->htcp_ca.lasttime = now;
+ net->cc_mod.htcp_ca.bytecount = 0;
+ net->cc_mod.htcp_ca.lasttime = now;
}
}
@@ -1137,27 +2000,27 @@ htcp_alpha_update(struct htcp *ca)
* were getting just too full now).
*/
static void
-htcp_param_update(struct sctp_tcb *stcb, struct sctp_nets *net)
+htcp_param_update(struct sctp_nets *net)
{
- uint32_t minRTT = net->htcp_ca.minRTT;
- uint32_t maxRTT = net->htcp_ca.maxRTT;
+ uint32_t minRTT = net->cc_mod.htcp_ca.minRTT;
+ uint32_t maxRTT = net->cc_mod.htcp_ca.maxRTT;
- htcp_beta_update(&net->htcp_ca, minRTT, maxRTT);
- htcp_alpha_update(&net->htcp_ca);
+ htcp_beta_update(&net->cc_mod.htcp_ca, minRTT, maxRTT);
+ htcp_alpha_update(&net->cc_mod.htcp_ca);
/*
* add slowly fading memory for maxRTT to accommodate routing
* changes etc
*/
if (minRTT > 0 && maxRTT > minRTT)
- net->htcp_ca.maxRTT = minRTT + ((maxRTT - minRTT) * 95) / 100;
+ net->cc_mod.htcp_ca.maxRTT = minRTT + ((maxRTT - minRTT) * 95) / 100;
}
static uint32_t
-htcp_recalc_ssthresh(struct sctp_tcb *stcb, struct sctp_nets *net)
+htcp_recalc_ssthresh(struct sctp_nets *net)
{
- htcp_param_update(stcb, net);
- return max(((net->cwnd / net->mtu * net->htcp_ca.beta) >> 7) * net->mtu, 2U * net->mtu);
+ htcp_param_update(net);
+ return (max(((net->cwnd / net->mtu * net->cc_mod.htcp_ca.beta) >> 7) * net->mtu, 2U * net->mtu));
}
static void
@@ -1191,21 +2054,21 @@ htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
}
}
} else {
- measure_rtt(stcb, net);
+ measure_rtt(net);
/*
* In dangerous area, increase slowly. In theory this is
* net->cwnd += alpha / net->cwnd
*/
/* What is snd_cwnd_cnt?? */
- if (((net->partial_bytes_acked / net->mtu * net->htcp_ca.alpha) >> 7) * net->mtu >= net->cwnd) {
+ if (((net->partial_bytes_acked / net->mtu * net->cc_mod.htcp_ca.alpha) >> 7) * net->mtu >= net->cwnd) {
/*-
* Does SCTP have a cwnd clamp?
* if (net->snd_cwnd < net->snd_cwnd_clamp) - Nope (RRS).
*/
net->cwnd += net->mtu;
net->partial_bytes_acked = 0;
- htcp_alpha_update(&net->htcp_ca);
+ htcp_alpha_update(&net->cc_mod.htcp_ca);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, net->mtu,
SCTP_CWND_LOG_FROM_CA);
@@ -1218,7 +2081,7 @@ htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
}
}
- net->htcp_ca.bytes_acked = net->mtu;
+ net->cc_mod.htcp_ca.bytes_acked = net->mtu;
}
}
@@ -1227,22 +2090,22 @@ htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
static uint32_t
htcp_min_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net)
{
- return net->ssthresh;
+ return (net->ssthresh);
}
#endif
static void
-htcp_init(struct sctp_tcb *stcb, struct sctp_nets *net)
+htcp_init(struct sctp_nets *net)
{
- memset(&net->htcp_ca, 0, sizeof(struct htcp));
- net->htcp_ca.alpha = ALPHA_BASE;
- net->htcp_ca.beta = BETA_MIN;
- net->htcp_ca.bytes_acked = net->mtu;
- net->htcp_ca.last_cong = sctp_get_tick_count();
+ memset(&net->cc_mod.htcp_ca, 0, sizeof(struct htcp));
+ net->cc_mod.htcp_ca.alpha = ALPHA_BASE;
+ net->cc_mod.htcp_ca.beta = BETA_MIN;
+ net->cc_mod.htcp_ca.bytes_acked = net->mtu;
+ net->cc_mod.htcp_ca.last_cong = sctp_get_tick_count();
}
-void
+static void
sctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
{
/*
@@ -1251,17 +2114,17 @@ sctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
*/
net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
net->ssthresh = stcb->asoc.peers_rwnd;
- htcp_init(stcb, net);
+ htcp_init(net);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
}
}
-void
+static void
sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
struct sctp_association *asoc,
- int accum_moved, int reneged_all, int will_exit)
+ int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
{
struct sctp_nets *net;
@@ -1275,49 +2138,12 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* CMT fast recovery code. Need to debug.
*/
if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
- if (compare_with_wrap(asoc->last_acked_seq,
- net->fast_recovery_tsn, MAX_TSN) ||
- (asoc->last_acked_seq == net->fast_recovery_tsn) ||
- compare_with_wrap(net->pseudo_cumack, net->fast_recovery_tsn, MAX_TSN) ||
- (net->pseudo_cumack == net->fast_recovery_tsn)) {
+ if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
+ SCTP_TSN_GE(net->pseudo_cumack, net->fast_recovery_tsn)) {
net->will_exit_fast_recovery = 1;
}
}
#endif
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- /*
- * So, first of all do we need to have a Early FR
- * timer running?
- */
- if ((!TAILQ_EMPTY(&asoc->sent_queue) &&
- (net->ref_count > 1) &&
- (net->flight_size < net->cwnd)) ||
- (reneged_all)) {
- /*
- * yes, so in this case stop it if its
- * running, and then restart it. Reneging
- * all is a special case where we want to
- * run the Early FR timer and then force the
- * last few unacked to be sent, causing us
- * to illicit a sack with gaps to force out
- * the others.
- */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
- }
- SCTP_STAT_INCR(sctps_earlyfrstrid);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
- } else {
- /* No, stop it if its running */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
- }
- }
- }
/* if nothing was acked on this destination skip it */
if (net->net_ack == 0) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
@@ -1325,56 +2151,14 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
}
continue;
}
- if (net->net_ack2 > 0) {
- /*
- * Karn's rule applies to clearing error count, this
- * is optional.
- */
- net->error_count = 0;
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
- SCTP_ADDR_NOT_REACHABLE) {
- /* addr came good */
- net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
- net->dest_state |= SCTP_ADDR_REACHABLE;
- sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
- SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
- /* now was it the primary? if so restore */
- if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
- (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
- }
- }
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination
- * is in PF state, set the destination to active
- * state and set the cwnd to one or two MTU's based
- * on whether PF1 or PF2 is being used.
- *
- * Should we stop any running T3 timer here?
- */
- if ((asoc->sctp_cmt_on_off == 1) &&
- (asoc->sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- net->cwnd = net->mtu * asoc->sctp_cmt_pf;
- SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
- net, net->cwnd);
- /*
- * Since the cwnd value is explicitly set,
- * skip the code that updates the cwnd
- * value.
- */
- goto skip_cwnd_update;
- }
- }
#ifdef JANA_CMT_FAST_RECOVERY
/*
* CMT fast recovery code
*/
/*
- * if (sctp_cmt_on_off == 1 &&
- * net->fast_retran_loss_recovery &&
- * net->will_exit_fast_recovery == 0) { @@@ Do something }
- * else if (sctp_cmt_on_off == 0 &&
+ * if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery
+ * && net->will_exit_fast_recovery == 0) { @@@ Do something
+ * } else if (sctp_cmt_on_off == 0 &&
* asoc->fast_retran_loss_recovery && will_exit == 0) {
*/
#endif
@@ -1386,55 +2170,38 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* If we are in loss recovery we skip any cwnd
* update
*/
- goto skip_cwnd_update;
+ return;
}
/*
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
* moved.
*/
if (accum_moved ||
- ((asoc->sctp_cmt_on_off == 1) && net->new_pseudo_cumack)) {
+ ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
htcp_cong_avoid(stcb, net);
- measure_achieved_throughput(stcb, net);
+ measure_achieved_throughput(net);
} else {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
sctp_log_cwnd(stcb, net, net->mtu,
SCTP_CWND_LOG_NO_CUMACK);
}
}
-skip_cwnd_update:
- /*
- * NOW, according to Karn's rule do we need to restore the
- * RTO timer back? Check our net_ack2. If not set then we
- * have a ambiguity.. i.e. all data ack'd was sent to more
- * than one place.
- */
- if (net->net_ack2) {
- /* restore any doubled timers */
- net->RTO = ((net->lastsa >> 2) + net->lastsv) >> 1;
- if (net->RTO < stcb->asoc.minrto) {
- net->RTO = stcb->asoc.minrto;
- }
- if (net->RTO > stcb->asoc.maxrto) {
- net->RTO = stcb->asoc.maxrto;
- }
- }
}
}
-void
+static void
sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
struct sctp_association *asoc)
{
struct sctp_nets *net;
/*
- * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
+ * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
* (net->fast_retran_loss_recovery == 0)))
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if ((asoc->fast_retran_loss_recovery == 0) ||
- (asoc->sctp_cmt_on_off == 1)) {
+ (asoc->sctp_cmt_on_off > 0)) {
/* out of a RFC2582 Fast recovery window? */
if (net->net_ack > 0) {
/*
@@ -1447,8 +2214,8 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
int old_cwnd = net->cwnd;
/* JRS - reset as if state were changed */
- htcp_reset(&net->htcp_ca);
- net->ssthresh = htcp_recalc_ssthresh(stcb, net);
+ htcp_reset(&net->cc_mod.htcp_ca);
+ net->ssthresh = htcp_recalc_ssthresh(net);
net->cwnd = net->ssthresh;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
@@ -1479,13 +2246,6 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
}
- /*
- * Disable Nonce Sum Checking and store the
- * resync tsn
- */
- asoc->nonce_sum_check = 0;
- asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
-
sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
@@ -1501,15 +2261,15 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
}
}
-void
+static void
sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
struct sctp_nets *net)
{
int old_cwnd = net->cwnd;
/* JRS - reset as if the state were being changed to timeout */
- htcp_reset(&net->htcp_ca);
- net->ssthresh = htcp_recalc_ssthresh(stcb, net);
+ htcp_reset(&net->cc_mod.htcp_ca);
+ net->ssthresh = htcp_recalc_ssthresh(net);
net->cwnd = net->mtu;
net->partial_bytes_acked = 0;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
@@ -1517,49 +2277,76 @@ sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
}
}
-void
-sctp_htcp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, struct sctp_nets *net)
-{
- int old_cwnd;
-
- old_cwnd = net->cwnd;
-
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
- net->htcp_ca.last_cong = sctp_get_tick_count();
- /*
- * make a small adjustment to cwnd and force to CA.
- */
- if (net->cwnd > net->mtu)
- /* drop down one MTU after sending */
- net->cwnd -= net->mtu;
- if (net->cwnd < net->ssthresh)
- /* still in SS move to CA */
- net->ssthresh = net->cwnd - 1;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, (old_cwnd - net->cwnd), SCTP_CWND_LOG_FROM_FR);
- }
-}
-
-void
+static void
sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
- struct sctp_nets *net)
+ struct sctp_nets *net, int in_window, int num_pkt_lost SCTP_UNUSED)
{
int old_cwnd;
old_cwnd = net->cwnd;
/* JRS - reset hctp as if state changed */
- htcp_reset(&net->htcp_ca);
- SCTP_STAT_INCR(sctps_ecnereducedcwnd);
- net->ssthresh = htcp_recalc_ssthresh(stcb, net);
- if (net->ssthresh < net->mtu) {
- net->ssthresh = net->mtu;
- /* here back off the timer as well, to slow us down */
- net->RTO <<= 1;
- }
- net->cwnd = net->ssthresh;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
+ if (in_window == 0) {
+ htcp_reset(&net->cc_mod.htcp_ca);
+ SCTP_STAT_INCR(sctps_ecnereducedcwnd);
+ net->ssthresh = htcp_recalc_ssthresh(net);
+ if (net->ssthresh < net->mtu) {
+ net->ssthresh = net->mtu;
+ /* here back off the timer as well, to slow us down */
+ net->RTO <<= 1;
+ }
+ net->cwnd = net->ssthresh;
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
+ sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
+ }
}
}
+
+struct sctp_cc_functions sctp_cc_functions[] = {
+ {
+ .sctp_set_initial_cc_param = sctp_set_initial_cc_param,
+ .sctp_cwnd_update_after_sack = sctp_cwnd_update_after_sack,
+ .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
+ .sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
+ .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
+ .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
+ .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
+ .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
+ },
+ {
+ .sctp_set_initial_cc_param = sctp_set_initial_cc_param,
+ .sctp_cwnd_update_after_sack = sctp_hs_cwnd_update_after_sack,
+ .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
+ .sctp_cwnd_update_after_fr = sctp_hs_cwnd_update_after_fr,
+ .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
+ .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
+ .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
+ .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
+ },
+ {
+ .sctp_set_initial_cc_param = sctp_htcp_set_initial_cc_param,
+ .sctp_cwnd_update_after_sack = sctp_htcp_cwnd_update_after_sack,
+ .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
+ .sctp_cwnd_update_after_fr = sctp_htcp_cwnd_update_after_fr,
+ .sctp_cwnd_update_after_timeout = sctp_htcp_cwnd_update_after_timeout,
+ .sctp_cwnd_update_after_ecn_echo = sctp_htcp_cwnd_update_after_ecn_echo,
+ .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
+ .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
+ },
+ {
+ .sctp_set_initial_cc_param = sctp_set_rtcc_initial_cc_param,
+ .sctp_cwnd_update_after_sack = sctp_cwnd_update_rtcc_after_sack,
+ .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
+ .sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
+ .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
+ .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_rtcc_after_ecn_echo,
+ .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
+ .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
+ .sctp_cwnd_update_packet_transmitted = sctp_cwnd_update_rtcc_packet_transmitted,
+ .sctp_cwnd_update_tsn_acknowledged = sctp_cwnd_update_rtcc_tsn_acknowledged,
+ .sctp_cwnd_new_transmission_begins = sctp_cwnd_new_rtcc_transmission_begins,
+ .sctp_cwnd_prepare_net_for_sack = sctp_cwnd_prepare_rtcc_net_for_sack,
+ .sctp_cwnd_socket_option = sctp_cwnd_rtcc_socket_option,
+ .sctp_rtt_calculated = sctp_rtt_rtcc_calculated
+ }
+};
diff --git a/freebsd/sys/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h
index 212a2f9e..18057009 100644
--- a/freebsd/sys/netinet/sctp_constants.h
+++ b/freebsd/sys/netinet/sctp_constants.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,13 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_constants.h,v 1.17 2005/03/06 16:04:17 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_constants_h__
-#define __sctp_constants_h__
+#ifndef _NETINET_SCTP_CONSTANTS_H_
+#define _NETINET_SCTP_CONSTANTS_H_
/* IANA assigned port number for SCTP over UDP encapsulation */
/* For freebsd we cannot bind the port at
@@ -91,6 +91,8 @@ __FBSDID("$FreeBSD$");
#define SCTP_KTRHEAD_NAME "sctp_iterator"
#define SCTP_KTHREAD_PAGES 0
+#define SCTP_MCORE_NAME "sctp_core_worker"
+
/* If you support Multi-VRF how big to
* make the initial array of VRF's to.
@@ -322,7 +324,6 @@ __FBSDID("$FreeBSD$");
#define SCTP_VERSION_NUMBER 0x3
#define MAX_TSN 0xffffffff
-#define MAX_SEQ 0xffff
/* how many executions every N tick's */
#define SCTP_ITERATOR_MAX_AT_ONCE 20
@@ -344,8 +345,18 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_NO_FR_UNLESS_SEGMENT_SMALLER 1
-/* default max I can burst out after a fast retransmit */
+/* default max I can burst out after a fast retransmit, 0 disables it */
#define SCTP_DEF_MAX_BURST 4
+#define SCTP_DEF_HBMAX_BURST 4
+#define SCTP_DEF_FRMAX_BURST 4
+
+/* RTO calculation flag to say if it
+ * is safe to determine local lan or not.
+ */
+#define SCTP_RTT_FROM_NON_DATA 0
+#define SCTP_RTT_FROM_DATA 1
+
+
/* IP hdr (20/40) + 12+2+2 (enet) + sctp common 12 */
#define SCTP_FIRST_MBUF_RESV 68
/* Packet transmit states in the sent field */
@@ -359,6 +370,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_DATAGRAM_ACKED 10010
#define SCTP_DATAGRAM_MARKED 20010
#define SCTP_FORWARD_TSN_SKIP 30010
+#define SCTP_DATAGRAM_NR_ACKED 40010
/* chunk output send from locations */
#define SCTP_OUTPUT_FROM_USR_SEND 0
@@ -378,10 +390,12 @@ __FBSDID("$FreeBSD$");
#define SCTP_OUTPUT_FROM_COOKIE_ACK 14
#define SCTP_OUTPUT_FROM_DRAIN 15
#define SCTP_OUTPUT_FROM_CLOSING 16
+#define SCTP_OUTPUT_FROM_SOCKOPT 17
+
/* SCTP chunk types are moved sctp.h for application (NAT, FW) use */
/* align to 32-bit sizes */
-#define SCTP_SIZE32(x) ((((x)+3) >> 2) << 2)
+#define SCTP_SIZE32(x) ((((x) + 3) >> 2) << 2)
#define IS_SCTP_CONTROL(a) ((a)->chunk_type != SCTP_DATA)
#define IS_SCTP_DATA(a) ((a)->chunk_type == SCTP_DATA)
@@ -403,7 +417,8 @@ __FBSDID("$FreeBSD$");
#define SCTP_STR_RESET_IN_REQUEST 0x000e
#define SCTP_STR_RESET_TSN_REQUEST 0x000f
#define SCTP_STR_RESET_RESPONSE 0x0010
-#define SCTP_STR_RESET_ADD_STREAMS 0x0011
+#define SCTP_STR_RESET_ADD_OUT_STREAMS 0x0011
+#define SCTP_STR_RESET_ADD_IN_STREAMS 0x0012
#define SCTP_MAX_RESET_PARAMS 2
#define SCTP_STREAM_RESET_TSN_DELTA 0x1000
@@ -412,8 +427,7 @@ __FBSDID("$FreeBSD$");
/*************0x8000 series*************/
#define SCTP_ECN_CAPABLE 0x8000
-/* ECN Nonce: draft-ladha-sctp-ecn-nonce */
-#define SCTP_ECN_NONCE_SUPPORTED 0x8001
+
/* draft-ietf-tsvwg-auth-xxx */
#define SCTP_RANDOM 0x8002
#define SCTP_CHUNK_LIST 0x8003
@@ -445,18 +459,6 @@ __FBSDID("$FreeBSD$");
#define SCTP_HAS_NAT_SUPPORT 0xc007
#define SCTP_NAT_VTAGS 0xc008
-/* Notification error codes */
-#define SCTP_NOTIFY_DATAGRAM_UNSENT 0x0001
-#define SCTP_NOTIFY_DATAGRAM_SENT 0x0002
-#define SCTP_FAILED_THRESHOLD 0x0004
-#define SCTP_HEARTBEAT_SUCCESS 0x0008
-#define SCTP_RESPONSE_TO_USER_REQ 0x0010
-#define SCTP_INTERNAL_ERROR 0x0020
-#define SCTP_SHUTDOWN_GUARD_EXPIRES 0x0040
-#define SCTP_RECEIVED_SACK 0x0080
-#define SCTP_PEER_FAULTY 0x0100
-#define SCTP_ICMP_REFUSED 0x0200
-
/* bits for TOS field */
#define SCTP_ECT0_BIT 0x02
#define SCTP_ECT1_BIT 0x01
@@ -496,19 +498,15 @@ __FBSDID("$FreeBSD$");
/* SCTP reachability state for each address */
#define SCTP_ADDR_REACHABLE 0x001
-#define SCTP_ADDR_NOT_REACHABLE 0x002
+#define SCTP_ADDR_NO_PMTUD 0x002
#define SCTP_ADDR_NOHB 0x004
#define SCTP_ADDR_BEING_DELETED 0x008
#define SCTP_ADDR_NOT_IN_ASSOC 0x010
-#define SCTP_ADDR_WAS_PRIMARY 0x020
-#define SCTP_ADDR_SWITCH_PRIMARY 0x040
#define SCTP_ADDR_OUT_OF_SCOPE 0x080
-#define SCTP_ADDR_DOUBLE_SWITCH 0x100
#define SCTP_ADDR_UNCONFIRMED 0x200
#define SCTP_ADDR_REQ_PRIMARY 0x400
/* JRS 5/13/07 - Added potentially failed state for CMT PF */
-#define SCTP_ADDR_PF 0x800
-#define SCTP_REACHABLE_MASK 0x203
+#define SCTP_ADDR_PF 0x800
/* bound address types (e.g. valid address types to allow) */
#define SCTP_BOUND_V6 0x01
@@ -568,14 +566,13 @@ __FBSDID("$FreeBSD$");
#define SCTP_TIMER_TYPE_EVENTWAKE 13
#define SCTP_TIMER_TYPE_STRRESET 14
#define SCTP_TIMER_TYPE_INPKILL 15
-#define SCTP_TIMER_TYPE_EARLYFR 17
-#define SCTP_TIMER_TYPE_ASOCKILL 18
-#define SCTP_TIMER_TYPE_ADDR_WQ 19
-#define SCTP_TIMER_TYPE_ZERO_COPY 20
-#define SCTP_TIMER_TYPE_ZCOPY_SENDQ 21
-#define SCTP_TIMER_TYPE_PRIM_DELETED 22
+#define SCTP_TIMER_TYPE_ASOCKILL 16
+#define SCTP_TIMER_TYPE_ADDR_WQ 17
+#define SCTP_TIMER_TYPE_ZERO_COPY 18
+#define SCTP_TIMER_TYPE_ZCOPY_SENDQ 19
+#define SCTP_TIMER_TYPE_PRIM_DELETED 20
/* add new timers here - and increment LAST */
-#define SCTP_TIMER_TYPE_LAST 23
+#define SCTP_TIMER_TYPE_LAST 21
#define SCTP_IS_TIMER_TYPE_VALID(t) (((t) > SCTP_TIMER_TYPE_NONE) && \
((t) < SCTP_TIMER_TYPE_LAST))
@@ -644,17 +641,17 @@ __FBSDID("$FreeBSD$");
#define SCTP_DEFAULT_SECRET_LIFE_SEC 3600
#define SCTP_RTO_UPPER_BOUND (60000) /* 60 sec in ms */
-#define SCTP_RTO_UPPER_BOUND_SEC 60 /* for the init timer */
-#define SCTP_RTO_LOWER_BOUND (1000) /* 1 sec in ms */
+#define SCTP_RTO_LOWER_BOUND (1000) /* 1 sec is ms */
#define SCTP_RTO_INITIAL (3000) /* 3 sec in ms */
#define SCTP_INP_KILL_TIMEOUT 20/* number of ms to retry kill of inpcb */
#define SCTP_ASOC_KILL_TIMEOUT 10 /* number of ms to retry kill of inpcb */
-#define SCTP_DEF_MAX_INIT 8
-#define SCTP_DEF_MAX_SEND 10
-#define SCTP_DEF_MAX_PATH_RTX 5
+#define SCTP_DEF_MAX_INIT 8
+#define SCTP_DEF_MAX_SEND 10
+#define SCTP_DEF_MAX_PATH_RTX 5
+#define SCTP_DEF_PATH_PF_THRESHOLD SCTP_DEF_MAX_PATH_RTX
#define SCTP_DEF_PMTU_RAISE_SEC 600 /* 10 min between raise attempts */
@@ -669,7 +666,7 @@ __FBSDID("$FreeBSD$");
/* Send window update (incr * this > hiwat). Should be a power of 2 */
#define SCTP_MINIMAL_RWND (4096) /* minimal rwnd */
-#define SCTP_ADDRMAX 24
+#define SCTP_ADDRMAX 16
/* SCTP DEBUG Switch parameters */
#define SCTP_DEBUG_TIMER1 0x00000001
@@ -745,35 +742,29 @@ __FBSDID("$FreeBSD$");
#define SCTP_NOTIFY_ASSOC_DOWN 2
#define SCTP_NOTIFY_INTERFACE_DOWN 3
#define SCTP_NOTIFY_INTERFACE_UP 4
-#define SCTP_NOTIFY_DG_FAIL 5
-#define SCTP_NOTIFY_STRDATA_ERR 6
-#define SCTP_NOTIFY_ASSOC_ABORTED 7
-#define SCTP_NOTIFY_PEER_OPENED_STREAM 8
-#define SCTP_NOTIFY_STREAM_OPENED_OK 9
+#define SCTP_NOTIFY_SENT_DG_FAIL 5
+#define SCTP_NOTIFY_UNSENT_DG_FAIL 6
+#define SCTP_NOTIFY_SPECIAL_SP_FAIL 7
+#define SCTP_NOTIFY_ASSOC_LOC_ABORTED 8
+#define SCTP_NOTIFY_ASSOC_REM_ABORTED 9
#define SCTP_NOTIFY_ASSOC_RESTART 10
-#define SCTP_NOTIFY_HB_RESP 11
-#define SCTP_NOTIFY_ASCONF_SUCCESS 12
-#define SCTP_NOTIFY_ASCONF_FAILED 13
-#define SCTP_NOTIFY_PEER_SHUTDOWN 14
-#define SCTP_NOTIFY_ASCONF_ADD_IP 15
-#define SCTP_NOTIFY_ASCONF_DELETE_IP 16
-#define SCTP_NOTIFY_ASCONF_SET_PRIMARY 17
-#define SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION 18
-#define SCTP_NOTIFY_INTERFACE_CONFIRMED 20
-#define SCTP_NOTIFY_STR_RESET_RECV 21
-#define SCTP_NOTIFY_STR_RESET_SEND 22
-#define SCTP_NOTIFY_STR_RESET_FAILED_OUT 23
-#define SCTP_NOTIFY_STR_RESET_FAILED_IN 24
-#define SCTP_NOTIFY_AUTH_NEW_KEY 25
-#define SCTP_NOTIFY_AUTH_FREE_KEY 26
-#define SCTP_NOTIFY_SPECIAL_SP_FAIL 27
-#define SCTP_NOTIFY_NO_PEER_AUTH 28
-#define SCTP_NOTIFY_SENDER_DRY 29
-#define SCTP_NOTIFY_STR_RESET_ADD_OK 30
-#define SCTP_NOTIFY_STR_RESET_ADD_FAIL 31
-#define SCTP_NOTIFY_STR_RESET_INSTREAM_ADD_OK 32
-#define SCTP_NOTIFY_MAX 32
-
+#define SCTP_NOTIFY_PEER_SHUTDOWN 11
+#define SCTP_NOTIFY_ASCONF_ADD_IP 12
+#define SCTP_NOTIFY_ASCONF_DELETE_IP 13
+#define SCTP_NOTIFY_ASCONF_SET_PRIMARY 14
+#define SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION 15
+#define SCTP_NOTIFY_INTERFACE_CONFIRMED 16
+#define SCTP_NOTIFY_STR_RESET_RECV 17
+#define SCTP_NOTIFY_STR_RESET_SEND 18
+#define SCTP_NOTIFY_STR_RESET_FAILED_OUT 19
+#define SCTP_NOTIFY_STR_RESET_FAILED_IN 20
+#define SCTP_NOTIFY_STR_RESET_DENIED_OUT 21
+#define SCTP_NOTIFY_STR_RESET_DENIED_IN 22
+#define SCTP_NOTIFY_AUTH_NEW_KEY 23
+#define SCTP_NOTIFY_AUTH_FREE_KEY 24
+#define SCTP_NOTIFY_NO_PEER_AUTH 25
+#define SCTP_NOTIFY_SENDER_DRY 26
+#define SCTP_NOTIFY_REMOTE_ERROR 27
/* This is the value for messages that are NOT completely
* copied down where we will start to split the message.
@@ -906,10 +897,13 @@ __FBSDID("$FreeBSD$");
#define SCTP_MAX_DATA_BUNDLING 256
/* modular comparison */
-/* True if a > b (mod = M) */
-#define compare_with_wrap(a, b, M) (((a > b) && ((a - b) < ((M >> 1) + 1))) || \
- ((b > a) && ((b - a) > ((M >> 1) + 1))))
-
+/* See RFC 1982 for details. */
+#define SCTP_SSN_GT(a, b) (((a < b) && ((uint16_t)(b - a) > (1U<<15))) || \
+ ((a > b) && ((uint16_t)(a - b) < (1U<<15))))
+#define SCTP_SSN_GE(a, b) (SCTP_SSN_GT(a, b) || (a == b))
+#define SCTP_TSN_GT(a, b) (((a < b) && ((uint32_t)(b - a) > (1U<<31))) || \
+ ((a > b) && ((uint32_t)(a - b) < (1U<<31))))
+#define SCTP_TSN_GE(a, b) (SCTP_TSN_GT(a, b) || (a == b))
/* Mapping array manipulation routines */
#define SCTP_IS_TSN_PRESENT(arry, gap) ((arry[(gap >> 3)] >> (gap & 0x07)) & 0x01)
@@ -921,7 +915,7 @@ __FBSDID("$FreeBSD$");
} else { \
gap = (MAX_TSN - mapping_tsn) + tsn + 1; \
} \
- } while(0)
+ } while (0)
#define SCTP_RETRAN_DONE -1
@@ -948,6 +942,17 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_TIME_WAIT 60
+/* How many micro seconds is the cutoff from
+ * local lan type rtt's
+ */
+ /*
+ * We allow 900us for the rtt.
+ */
+#define SCTP_LOCAL_LAN_RTT 900
+#define SCTP_LAN_UNKNOWN 0
+#define SCTP_LAN_LOCAL 1
+#define SCTP_LAN_INTERNET 2
+
#define SCTP_SEND_BUFFER_SPLITTING 0x00000001
#define SCTP_RECV_BUFFER_SPLITTING 0x00000002
@@ -994,19 +999,9 @@ __FBSDID("$FreeBSD$");
#if defined(_KERNEL)
-
-#define SCTP_GETTIME_TIMEVAL(x) (getmicrouptime(x))
-#define SCTP_GETPTIME_TIMEVAL(x) (microuptime(x))
+#define SCTP_GETTIME_TIMEVAL(x) (getmicrouptime(x))
+#define SCTP_GETPTIME_TIMEVAL(x) (microuptime(x))
#endif
-/*#if defined(__FreeBSD__) || defined(__APPLE__)*/
-/*#define SCTP_GETTIME_TIMEVAL(x) { \*/
-/* (x)->tv_sec = ticks / 1000; \*/
-/* (x)->tv_usec = (ticks % 1000) * 1000; \*/
-/*}*/
-
-/*#else*/
-/*#define SCTP_GETTIME_TIMEVAL(x) (microtime(x))*/
-/*#endif __FreeBSD__ */
#if defined(_KERNEL) || defined(__Userspace__)
#define sctp_sowwakeup(inp, so) \
diff --git a/freebsd/sys/netinet/sctp_crc32.c b/freebsd/sys/netinet/sctp_crc32.c
index 3d07f505..bf6da201 100644
--- a/freebsd/sys/netinet/sctp_crc32.c
+++ b/freebsd/sys/netinet/sctp_crc32.c
@@ -2,6 +2,8 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,9 +32,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_crc32.c,v 1.12 2005/03/06 16:04:17 itojun Exp $ */
-
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -124,7 +123,9 @@ void
sctp_delayed_cksum(struct mbuf *m, uint32_t offset)
{
#if defined(SCTP_WITH_NO_CSUM)
+#ifdef INVARIANTS
panic("sctp_delayed_cksum() called when using no SCTP CRC.");
+#endif
#else
uint32_t checksum;
@@ -134,7 +135,7 @@ sctp_delayed_cksum(struct mbuf *m, uint32_t offset)
offset += offsetof(struct sctphdr, checksum);
if (offset + sizeof(uint32_t) > (uint32_t) (m->m_len)) {
- printf("sctp_delayed_cksum(): m->len: %d, off: %d.\n",
+ SCTP_PRINTF("sctp_delayed_cksum(): m->len: %d, off: %d.\n",
(uint32_t) m->m_len, offset);
/*
* XXX this shouldn't happen, but if it does, the correct
diff --git a/freebsd/sys/netinet/sctp_crc32.h b/freebsd/sys/netinet/sctp_crc32.h
index eb7a1bc7..3f98be41 100644
--- a/freebsd/sys/netinet/sctp_crc32.h
+++ b/freebsd/sys/netinet/sctp_crc32.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,13 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_crc32.h,v 1.5 2004/08/17 04:06:16 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __crc32c_h__
-#define __crc32c_h__
+#ifndef _NETINET_SCTP_CRC32_H_
+#define _NETINET_SCTP_CRC32_H_
#if defined(_KERNEL)
#if !defined(SCTP_WITH_NO_CSUM)
diff --git a/freebsd/sys/netinet/sctp_dtrace_declare.h b/freebsd/sys/netinet/sctp_dtrace_declare.h
new file mode 100644
index 00000000..f6fe48bd
--- /dev/null
+++ b/freebsd/sys/netinet/sctp_dtrace_declare.h
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * a) Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * b) 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.
+ *
+ * c) Neither the name of Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifndef _NETINET_SCTP_DTRACE_DECLARE_H_
+#define _NETINET_SCTP_DTRACE_DECLARE_H_
+
+#include <rtems/bsd/local/opt_kdtrace.h>
+#include <sys/kernel.h>
+#include <sys/sdt.h>
+
+/* Declare the SCTP provider */
+SDT_PROVIDER_DECLARE(sctp);
+
+/* The probes we have so far: */
+
+/* One to track a net's cwnd */
+/* initial */
+SDT_PROBE_DECLARE(sctp, cwnd, net, init);
+/* update at a ack -- increase */
+SDT_PROBE_DECLARE(sctp, cwnd, net, ack);
+/* update at a fast retransmit -- decrease */
+SDT_PROBE_DECLARE(sctp, cwnd, net, fr);
+/* update at a time-out -- decrease */
+SDT_PROBE_DECLARE(sctp, cwnd, net, to);
+/* update at a burst-limit -- decrease */
+SDT_PROBE_DECLARE(sctp, cwnd, net, bl);
+/* update at a ECN -- decrease */
+SDT_PROBE_DECLARE(sctp, cwnd, net, ecn);
+/* update at a Packet-Drop -- decrease */
+SDT_PROBE_DECLARE(sctp, cwnd, net, pd);
+/* Rttvar probe declaration */
+SDT_PROBE_DECLARE(sctp, cwnd, net, rttvar);
+SDT_PROBE_DECLARE(sctp, cwnd, net, rttstep);
+
+/* One to track an associations rwnd */
+SDT_PROBE_DECLARE(sctp, rwnd, assoc, val);
+
+/* One to track a net's flight size */
+SDT_PROBE_DECLARE(sctp, flightsize, net, val);
+
+/* One to track an associations flight size */
+SDT_PROBE_DECLARE(sctp, flightsize, assoc, val);
+
+
+
+
+
+
+#endif
diff --git a/freebsd/sys/netinet/sctp_dtrace_define.h b/freebsd/sys/netinet/sctp_dtrace_define.h
new file mode 100644
index 00000000..1eb28f65
--- /dev/null
+++ b/freebsd/sys/netinet/sctp_dtrace_define.h
@@ -0,0 +1,233 @@
+/*-
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * a) Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * b) 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.
+ *
+ * c) Neither the name of Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifndef _NETINET_SCTP_DTRACE_DEFINE_H_
+#define _NETINET_SCTP_DTRACE_DEFINE_H_
+
+#include <rtems/bsd/local/opt_kdtrace.h>
+#include <sys/kernel.h>
+#include <sys/sdt.h>
+
+SDT_PROVIDER_DEFINE(sctp);
+
+/********************************************************/
+/* Cwnd probe - tracks changes in the congestion window on a netp */
+/********************************************************/
+/* Initial */
+SDT_PROBE_DEFINE(sctp, cwnd, net, init, init);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 1, "uint32_t");
+/* The pointer to the struct sctp_nets * changing */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 2, "uintptr_t");
+/* The old value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 3, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 4, "int");
+
+
+/* ACK-INCREASE */
+SDT_PROBE_DEFINE(sctp, cwnd, net, ack, ack);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 1, "uint32_t");
+/* The pointer to the struct sctp_nets * changing */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 2, "uintptr_t");
+/* The old value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 3, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 4, "int");
+
+
+/* ACK-INCREASE */
+SDT_PROBE_DEFINE(sctp, cwnd, net, rttvar, rttvar);
+/* The Vtag << 32 | localport << 16 | remoteport */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 0, "uint64_t");
+/* obw | nbw */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 1, "uint64_t");
+/* bwrtt | newrtt */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 2, "uint64_t");
+/* flight */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 3, "uint64_t");
+/* (cwnd << 32) | point << 16 | retval(0/1) */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 4, "uint64_t");
+
+
+SDT_PROBE_DEFINE(sctp, cwnd, net, rttstep, rttstep);
+/* The Vtag << 32 | localport << 16 | remoteport */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 0, "uint64_t");
+/* obw | nbw */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 1, "uint64_t");
+/* bwrtt | nrtt */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 2, "uint64_t");
+/* cwnd_saved | stepcnt << 16 | oldstep */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 3, "uint64_t");
+/* (cwnd << 32) | point << 16 | retval(0/1) */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 4, "uint64_t");
+
+
+/* FastRetransmit-DECREASE */
+SDT_PROBE_DEFINE(sctp, cwnd, net, fr, fr);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 1, "uint32_t");
+/* The pointer to the struct sctp_nets * changing */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 2, "uintptr_t");
+/* The old value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 3, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 4, "int");
+
+
+/* TimeOut-DECREASE */
+SDT_PROBE_DEFINE(sctp, cwnd, net, to, to);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 1, "uint32_t");
+/* The pointer to the struct sctp_nets * changing */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 2, "uintptr_t");
+/* The old value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 3, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 4, "int");
+
+
+/* BurstLimit-DECREASE */
+SDT_PROBE_DEFINE(sctp, cwnd, net, bl, bl);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 1, "uint32_t");
+/* The pointer to the struct sctp_nets * changing */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 2, "uintptr_t");
+/* The old value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 3, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 4, "int");
+
+
+/* ECN-DECREASE */
+SDT_PROBE_DEFINE(sctp, cwnd, net, ecn, ecn);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 1, "uint32_t");
+/* The pointer to the struct sctp_nets * changing */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 2, "uintptr_t");
+/* The old value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 3, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 4, "int");
+
+
+/* PacketDrop-DECREASE */
+SDT_PROBE_DEFINE(sctp, cwnd, net, pd, pd);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 1, "uint32_t");
+/* The pointer to the struct sctp_nets * changing */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 2, "uintptr_t");
+/* The old value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 3, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 4, "int");
+
+
+
+/********************************************************/
+/* Rwnd probe - tracks changes in the receiver window for an assoc */
+/********************************************************/
+SDT_PROBE_DEFINE(sctp, rwnd, assoc, val, val);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 1, "uint32_t");
+/* The up/down amount */
+SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 2, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 3, "int");
+
+/********************************************************/
+/* flight probe - tracks changes in the flight size on a net or assoc */
+/********************************************************/
+SDT_PROBE_DEFINE(sctp, flightsize, net, val, val);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 1, "uint32_t");
+/* The pointer to the struct sctp_nets * changing */
+SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 2, "uintptr_t");
+/* The up/down amount */
+SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 3, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 4, "int");
+/********************************************************/
+/* The total flight version */
+/********************************************************/
+SDT_PROBE_DEFINE(sctp, flightsize, assoc, val, val);
+/* The Vtag for this end */
+SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 0, "uint32_t");
+/* The port number of the local side << 16 | port number of remote
+ * in network byte order.
+ */
+SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 1, "uint32_t");
+/* The up/down amount */
+SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 2, "int");
+/* The new value of the cwnd */
+SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 3, "int");
+
+#endif
diff --git a/freebsd/sys/netinet/sctp_header.h b/freebsd/sys/netinet/sctp_header.h
index 980845dc..261d9eb6 100644
--- a/freebsd/sys/netinet/sctp_header.h
+++ b/freebsd/sys/netinet/sctp_header.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,13 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_header.h,v 1.14 2005/03/06 16:04:17 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_header_h__
-#define __sctp_header_h__
+#ifndef _NETINET_SCTP_HEADER_H_
+#define _NETINET_SCTP_HEADER_H_
#include <rtems/bsd/sys/time.h>
#include <netinet/sctp.h>
@@ -79,8 +79,7 @@ struct sctp_host_name_param {
/* supported address type */
struct sctp_supported_addr_param {
struct sctp_paramhdr ph;/* type=SCTP_SUPPORTED_ADDRTYPE */
- uint16_t addr_type[SCTP_ARRAY_MIN_LEN]; /* array of supported address
- * types */
+ uint16_t addr_type[2]; /* array of supported address types */
} SCTP_PACKED;
/* ECN parameter */
@@ -96,9 +95,10 @@ struct sctp_heartbeat_info_param {
uint32_t time_value_2;
uint32_t random_value1;
uint32_t random_value2;
- uint16_t user_req;
uint8_t addr_family;
uint8_t addr_len;
+ /* make sure that this structure is 4 byte aligned */
+ uint8_t padding[2];
char address[SCTP_ADDRMAX];
} SCTP_PACKED;
@@ -142,12 +142,6 @@ struct sctp_supported_chunk_types_param {
} SCTP_PACKED;
-/* ECN Nonce: draft-ladha-sctp-ecn-nonce */
-struct sctp_ecn_nonce_supported_param {
- struct sctp_paramhdr ph;/* type = 0x8001 len = 4 */
-} SCTP_PACKED;
-
-
/*
* Structures for DATA chunks
*/
@@ -360,9 +354,15 @@ struct sctp_cookie_ack_chunk {
} SCTP_PACKED;
/* Explicit Congestion Notification Echo (ECNE) */
+struct old_sctp_ecne_chunk {
+ struct sctp_chunkhdr ch;
+ uint32_t tsn;
+} SCTP_PACKED;
+
struct sctp_ecne_chunk {
struct sctp_chunkhdr ch;
uint32_t tsn;
+ uint32_t num_pkts_since_cwr;
} SCTP_PACKED;
/* Congestion Window Reduced (CWR) */
@@ -497,28 +497,19 @@ struct sctp_stream_reset_add_strm {
uint16_t reserved;
} SCTP_PACKED;
-#define SCTP_STREAM_RESET_NOTHING 0x00000000 /* Nothing for me to do */
-#define SCTP_STREAM_RESET_PERFORMED 0x00000001 /* Did it */
-#define SCTP_STREAM_RESET_DENIED 0x00000002 /* refused to do it */
-#define SCTP_STREAM_RESET_ERROR_STR 0x00000003 /* bad Stream no */
-#define SCTP_STREAM_RESET_TRY_LATER 0x00000004 /* collision, try again */
-#define SCTP_STREAM_RESET_BAD_SEQNO 0x00000005 /* bad str-reset seq no */
+#define SCTP_STREAM_RESET_RESULT_NOTHING_TO_DO 0x00000000 /* XXX: unused */
+#define SCTP_STREAM_RESET_RESULT_PERFORMED 0x00000001
+#define SCTP_STREAM_RESET_RESULT_DENIED 0x00000002
+#define SCTP_STREAM_RESET_RESULT_ERR__WRONG_SSN 0x00000003 /* XXX: unused */
+#define SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS 0x00000004
+#define SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO 0x00000005
+#define SCTP_STREAM_RESET_RESULT_IN_PROGRESS 0x00000006 /* XXX: unused */
/*
* convience structures, note that if you are making a request for specific
* streams then the request will need to be an overlay structure.
*/
-struct sctp_stream_reset_out_req {
- struct sctp_chunkhdr ch;
- struct sctp_stream_reset_out_request sr_req;
-} SCTP_PACKED;
-
-struct sctp_stream_reset_in_req {
- struct sctp_chunkhdr ch;
- struct sctp_stream_reset_in_request sr_req;
-} SCTP_PACKED;
-
struct sctp_stream_reset_tsn_req {
struct sctp_chunkhdr ch;
struct sctp_stream_reset_tsn_request sr_req;
diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c
index 082e43b8..c82e570f 100644
--- a/freebsd/sys/netinet/sctp_indata.c
+++ b/freebsd/sys/netinet/sctp_indata.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,8 +32,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_indata.c,v 1.36 2005/03/06 16:04:17 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -137,7 +137,7 @@ sctp_build_readq_entry(struct sctp_tcb *stcb,
read_queue_e->sinfo_ssn = stream_seq;
read_queue_e->sinfo_flags = (flags << 8);
read_queue_e->sinfo_ppid = ppid;
- read_queue_e->sinfo_context = stcb->asoc.context;
+ read_queue_e->sinfo_context = context;
read_queue_e->sinfo_timetolive = 0;
read_queue_e->sinfo_tsn = tsn;
read_queue_e->sinfo_cumtsn = tsn;
@@ -201,95 +201,114 @@ failed_build:
struct mbuf *
-sctp_build_ctl_nchunk(struct sctp_inpcb *inp,
- struct sctp_sndrcvinfo *sinfo)
+sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo)
{
+ struct sctp_extrcvinfo *seinfo;
struct sctp_sndrcvinfo *outinfo;
+ struct sctp_rcvinfo *rcvinfo;
+ struct sctp_nxtinfo *nxtinfo;
struct cmsghdr *cmh;
struct mbuf *ret;
int len;
- int use_extended = 0;
+ int use_extended;
+ int provide_nxt;
- if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
- /* user does not want the sndrcv ctl */
+ if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) &&
+ sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
+ sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) {
+ /* user does not want any ancillary data */
return (NULL);
}
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
- use_extended = 1;
- len = CMSG_LEN(sizeof(struct sctp_extrcvinfo));
+ len = 0;
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
+ len += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
+ }
+ seinfo = (struct sctp_extrcvinfo *)sinfo;
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) &&
+ (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) {
+ provide_nxt = 1;
+ len += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
} else {
- len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
+ provide_nxt = 0;
+ }
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
+ use_extended = 1;
+ len += CMSG_SPACE(sizeof(struct sctp_extrcvinfo));
+ } else {
+ use_extended = 0;
+ len += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
+ }
+ } else {
+ use_extended = 0;
}
-
- ret = sctp_get_mbuf_for_msg(len,
- 0, M_DONTWAIT, 1, MT_DATA);
-
+ ret = sctp_get_mbuf_for_msg(len, 0, M_DONTWAIT, 1, MT_DATA);
if (ret == NULL) {
/* No space */
return (ret);
}
- /* We need a CMSG header followed by the struct */
+ SCTP_BUF_LEN(ret) = 0;
+
+ /* We need a CMSG header followed by the struct */
cmh = mtod(ret, struct cmsghdr *);
- outinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmh);
- cmh->cmsg_level = IPPROTO_SCTP;
- if (use_extended) {
- cmh->cmsg_type = SCTP_EXTRCV;
- cmh->cmsg_len = len;
- memcpy(outinfo, sinfo, len);
- } else {
- cmh->cmsg_type = SCTP_SNDRCV;
- cmh->cmsg_len = len;
- *outinfo = *sinfo;
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
+ cmh->cmsg_level = IPPROTO_SCTP;
+ cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_rcvinfo));
+ cmh->cmsg_type = SCTP_RCVINFO;
+ rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmh);
+ rcvinfo->rcv_sid = sinfo->sinfo_stream;
+ rcvinfo->rcv_ssn = sinfo->sinfo_ssn;
+ rcvinfo->rcv_flags = sinfo->sinfo_flags;
+ rcvinfo->rcv_ppid = sinfo->sinfo_ppid;
+ rcvinfo->rcv_tsn = sinfo->sinfo_tsn;
+ rcvinfo->rcv_cumtsn = sinfo->sinfo_cumtsn;
+ rcvinfo->rcv_context = sinfo->sinfo_context;
+ rcvinfo->rcv_assoc_id = sinfo->sinfo_assoc_id;
+ cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_rcvinfo)));
+ SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
+ }
+ if (provide_nxt) {
+ cmh->cmsg_level = IPPROTO_SCTP;
+ cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_nxtinfo));
+ cmh->cmsg_type = SCTP_NXTINFO;
+ nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmh);
+ nxtinfo->nxt_sid = seinfo->sreinfo_next_stream;
+ nxtinfo->nxt_flags = 0;
+ if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) {
+ nxtinfo->nxt_flags |= SCTP_UNORDERED;
+ }
+ if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) {
+ nxtinfo->nxt_flags |= SCTP_NOTIFICATION;
+ }
+ if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) {
+ nxtinfo->nxt_flags |= SCTP_COMPLETE;
+ }
+ nxtinfo->nxt_ppid = seinfo->sreinfo_next_ppid;
+ nxtinfo->nxt_length = seinfo->sreinfo_next_length;
+ nxtinfo->nxt_assoc_id = seinfo->sreinfo_next_aid;
+ cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo)));
+ SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_nxtinfo));
+ }
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
+ cmh->cmsg_level = IPPROTO_SCTP;
+ outinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmh);
+ if (use_extended) {
+ cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_extrcvinfo));
+ cmh->cmsg_type = SCTP_EXTRCV;
+ memcpy(outinfo, sinfo, sizeof(struct sctp_extrcvinfo));
+ SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_extrcvinfo));
+ } else {
+ cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
+ cmh->cmsg_type = SCTP_SNDRCV;
+ *outinfo = *sinfo;
+ SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
+ }
}
- SCTP_BUF_LEN(ret) = cmh->cmsg_len;
return (ret);
}
-char *
-sctp_build_ctl_cchunk(struct sctp_inpcb *inp,
- int *control_len,
- struct sctp_sndrcvinfo *sinfo)
-{
- struct sctp_sndrcvinfo *outinfo;
- struct cmsghdr *cmh;
- char *buf;
- int len;
- int use_extended = 0;
-
- if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
- /* user does not want the sndrcv ctl */
- return (NULL);
- }
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
- use_extended = 1;
- len = CMSG_LEN(sizeof(struct sctp_extrcvinfo));
- } else {
- len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
- }
- SCTP_MALLOC(buf, char *, len, SCTP_M_CMSG);
- if (buf == NULL) {
- /* No space */
- return (buf);
- }
- /* We need a CMSG header followed by the struct */
- cmh = (struct cmsghdr *)buf;
- outinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmh);
- cmh->cmsg_level = IPPROTO_SCTP;
- if (use_extended) {
- cmh->cmsg_type = SCTP_EXTRCV;
- cmh->cmsg_len = len;
- memcpy(outinfo, sinfo, len);
- } else {
- cmh->cmsg_type = SCTP_SNDRCV;
- cmh->cmsg_len = len;
- *outinfo = *sinfo;
- }
- *control_len = len;
- return (buf);
-}
-
static void
sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
{
@@ -300,7 +319,7 @@ sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
return;
}
cumackp1 = asoc->cumulative_tsn + 1;
- if (compare_with_wrap(cumackp1, tsn, MAX_TSN)) {
+ if (SCTP_TSN_GT(cumackp1, tsn)) {
/*
* this tsn is behind the cum ack and thus we don't need to
* worry about it being moved from one to the other.
@@ -309,7 +328,7 @@ sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
}
SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn);
if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
- printf("gap:%x tsn:%x\n", gap, tsn);
+ SCTP_PRINTF("gap:%x tsn:%x\n", gap, tsn);
sctp_print_mapping_array(asoc);
#ifdef INVARIANTS
panic("Things are really messed up now!!");
@@ -317,13 +336,12 @@ sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
}
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
asoc->highest_tsn_inside_nr_map = tsn;
}
if (tsn == asoc->highest_tsn_inside_map) {
/* We must back down to see what the new highest is */
- for (i = tsn - 1; (compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN) ||
- (i == asoc->mapping_array_base_tsn)); i--) {
+ for (i = tsn - 1; SCTP_TSN_GE(i, asoc->mapping_array_base_tsn); i--) {
SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn);
if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
asoc->highest_tsn_inside_map = i;
@@ -346,13 +364,12 @@ sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
static void
sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
{
- struct sctp_tmit_chunk *chk;
+ struct sctp_tmit_chunk *chk, *nchk;
uint16_t nxt_todel;
uint16_t stream_no;
int end = 0;
int cntDel;
-
- struct sctp_queued_to_read *control, *ctl, *ctlat;
+ struct sctp_queued_to_read *control, *ctl, *nctl;
if (stcb == NULL)
return;
@@ -364,8 +381,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
/* socket above is long gone or going.. */
abandon:
asoc->fragmented_delivery_inprogress = 0;
- chk = TAILQ_FIRST(&asoc->reasmqueue);
- while (chk) {
+ TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
asoc->size_on_reasm_queue -= chk->send_size;
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
@@ -378,18 +394,13 @@ abandon:
chk->data = NULL;
}
/* Now free the address and data */
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
/* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->reasmqueue);
}
return;
}
SCTP_TCB_LOCK_ASSERT(stcb);
- do {
- chk = TAILQ_FIRST(&asoc->reasmqueue);
- if (chk == NULL) {
- return;
- }
+ TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
if (chk->rec.data.TSN_seq != (asoc->tsn_last_delivered + 1)) {
/* Can't deliver more :< */
return;
@@ -487,7 +498,7 @@ abandon:
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
/* free up the chk */
chk->data = NULL;
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
if (asoc->fragmented_delivery_inprogress == 0) {
/*
@@ -498,33 +509,26 @@ abandon:
strm = &asoc->strmin[stream_no];
nxt_todel = strm->last_sequence_delivered + 1;
- ctl = TAILQ_FIRST(&strm->inqueue);
- if (ctl && (nxt_todel == ctl->sinfo_ssn)) {
- while (ctl != NULL) {
- /* Deliver more if we can. */
- if (nxt_todel == ctl->sinfo_ssn) {
- ctlat = TAILQ_NEXT(ctl, next);
- TAILQ_REMOVE(&strm->inqueue, ctl, next);
- asoc->size_on_all_streams -= ctl->length;
- sctp_ucount_decr(asoc->cnt_on_all_streams);
- strm->last_sequence_delivered++;
- sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
- sctp_add_to_readq(stcb->sctp_ep, stcb,
- ctl,
- &stcb->sctp_socket->so_rcv, 1,
- SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
- ctl = ctlat;
- } else {
- break;
- }
- nxt_todel = strm->last_sequence_delivered + 1;
+ TAILQ_FOREACH_SAFE(ctl, &strm->inqueue, next, nctl) {
+ /* Deliver more if we can. */
+ if (nxt_todel == ctl->sinfo_ssn) {
+ TAILQ_REMOVE(&strm->inqueue, ctl, next);
+ asoc->size_on_all_streams -= ctl->length;
+ sctp_ucount_decr(asoc->cnt_on_all_streams);
+ strm->last_sequence_delivered++;
+ sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
+ sctp_add_to_readq(stcb->sctp_ep, stcb,
+ ctl,
+ &stcb->sctp_socket->so_rcv, 1,
+ SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
+ } else {
+ break;
}
+ nxt_todel = strm->last_sequence_delivered + 1;
}
break;
}
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->reasmqueue);
- } while (chk);
+ }
}
/*
@@ -574,9 +578,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
(uint32_t) control->sinfo_stream,
(uint32_t) strm->last_sequence_delivered,
(uint32_t) nxt_todel);
- if (compare_with_wrap(strm->last_sequence_delivered,
- control->sinfo_ssn, MAX_SEQ) ||
- (strm->last_sequence_delivered == control->sinfo_ssn)) {
+ if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) {
/* The incoming sseq is behind where we last delivered? */
SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n",
control->sinfo_ssn, strm->last_sequence_delivered);
@@ -605,9 +607,7 @@ protocol_error:
*ippp = ((control->sinfo_stream << 16) | control->sinfo_ssn);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_1;
- sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
@@ -628,12 +628,10 @@ protocol_error:
control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
- control = TAILQ_FIRST(&strm->inqueue);
- while (control != NULL) {
+ TAILQ_FOREACH_SAFE(control, &strm->inqueue, next, at) {
/* all delivered */
nxt_todel = strm->last_sequence_delivered + 1;
if (nxt_todel == control->sinfo_ssn) {
- at = TAILQ_NEXT(control, next);
TAILQ_REMOVE(&strm->inqueue, control, next);
asoc->size_on_all_streams -= control->length;
sctp_ucount_decr(asoc->cnt_on_all_streams);
@@ -654,7 +652,6 @@ protocol_error:
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD,
SCTP_SO_NOT_LOCKED);
- control = at;
continue;
}
break;
@@ -665,9 +662,7 @@ protocol_error:
* Ok, we did not deliver this guy, find the correct place
* to put it on the queue.
*/
- if ((compare_with_wrap(asoc->cumulative_tsn,
- control->sinfo_tsn, MAX_TSN)) ||
- (control->sinfo_tsn == asoc->cumulative_tsn)) {
+ if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) {
goto protocol_error;
}
if (TAILQ_EMPTY(&strm->inqueue)) {
@@ -678,8 +673,7 @@ protocol_error:
TAILQ_INSERT_HEAD(&strm->inqueue, control, next);
} else {
TAILQ_FOREACH(at, &strm->inqueue, next) {
- if (compare_with_wrap(at->sinfo_ssn,
- control->sinfo_ssn, MAX_SEQ)) {
+ if (SCTP_SSN_GT(at->sinfo_ssn, control->sinfo_ssn)) {
/*
* one in queue is bigger than the
* new one, insert before this one
@@ -758,7 +752,7 @@ sctp_is_all_msg_on_reasm(struct sctp_association *asoc, uint32_t * t_size)
return (0);
}
tsn = chk->rec.data.TSN_seq;
- while (chk) {
+ TAILQ_FOREACH(chk, &asoc->reasmqueue, sctp_next) {
if (tsn != chk->rec.data.TSN_seq) {
return (0);
}
@@ -767,7 +761,6 @@ sctp_is_all_msg_on_reasm(struct sctp_association *asoc, uint32_t * t_size)
return (1);
}
tsn++;
- chk = TAILQ_NEXT(chk, sctp_next);
}
return (0);
}
@@ -850,8 +843,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_tmit_chunk *chk, int *abort_flag)
{
struct mbuf *oper;
- uint32_t cum_ackp1, last_tsn, prev_tsn, post_tsn;
- u_char last_flags;
+ uint32_t cum_ackp1, prev_tsn, post_tsn;
struct sctp_tmit_chunk *at, *prev, *next;
prev = next = NULL;
@@ -898,8 +890,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_2;
- sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
} else if (asoc->fragmented_delivery_inprogress &&
(chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) {
@@ -930,8 +921,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_3;
- sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
} else if (asoc->fragmented_delivery_inprogress) {
/*
@@ -967,8 +957,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_4;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
} else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) !=
SCTP_DATA_UNORDERED &&
@@ -1001,8 +990,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_5;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
}
}
@@ -1011,8 +999,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
/* Find its place */
TAILQ_FOREACH(at, &asoc->reasmqueue, sctp_next) {
- if (compare_with_wrap(at->rec.data.TSN_seq,
- chk->rec.data.TSN_seq, MAX_TSN)) {
+ if (SCTP_TSN_GT(at->rec.data.TSN_seq, chk->rec.data.TSN_seq)) {
/*
* one in queue is bigger than the new one, insert
* before this one
@@ -1036,11 +1023,9 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
sctp_m_freem(chk->data);
chk->data = NULL;
}
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
return;
} else {
- last_flags = at->rec.data.rcv_flags;
- last_tsn = at->rec.data.TSN_seq;
prev = at;
if (TAILQ_NEXT(at, sctp_next) == NULL) {
/*
@@ -1099,8 +1084,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_6;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@@ -1136,9 +1120,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_7;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@@ -1175,9 +1157,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_8;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@@ -1211,9 +1191,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_9;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@@ -1256,9 +1234,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_10;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@@ -1298,9 +1274,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_11;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@@ -1337,9 +1311,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_12;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@@ -1376,9 +1348,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_13;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@@ -1403,8 +1373,7 @@ sctp_does_tsn_belong_to_reasm(struct sctp_association *asoc,
uint32_t tsn_est;
TAILQ_FOREACH(at, &asoc->reasmqueue, sctp_next) {
- if (compare_with_wrap(TSN_seq,
- at->rec.data.TSN_seq, MAX_TSN)) {
+ if (SCTP_TSN_GT(TSN_seq, at->rec.data.TSN_seq)) {
/* is it one bigger? */
tsn_est = at->rec.data.TSN_seq + 1;
if (tsn_est == TSN_seq) {
@@ -1462,7 +1431,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_tmit_chunk *chk;
uint32_t tsn, gap;
struct mbuf *dmbuf;
- int indx, the_len;
+ int the_len;
int need_reasm_check = 0;
uint16_t strmno, strmseq;
struct mbuf *oper;
@@ -1487,8 +1456,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
return (0);
}
SCTP_LTRACE_CHK(stcb->sctp_ep, stcb, ch->ch.chunk_type, tsn);
- if (compare_with_wrap(asoc->cumulative_tsn, tsn, MAX_TSN) ||
- asoc->cumulative_tsn == tsn) {
+ if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) {
/* It is a duplicate */
SCTP_STAT_INCR(sctps_recvdupdata);
if (asoc->numduptsns < SCTP_MAX_DUP_TSNS) {
@@ -1512,7 +1480,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
return (0);
}
}
- if (compare_with_wrap(tsn, *high_tsn, MAX_TSN)) {
+ if (SCTP_TSN_GT(tsn, *high_tsn)) {
*high_tsn = tsn;
}
/* See if we have received this one already */
@@ -1542,7 +1510,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct mbuf *op_err;
op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
- sctp_abort_an_association(stcb->sctp_ep, stcb, 0, op_err, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
}
@@ -1563,7 +1531,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
*/
if (stcb->sctp_socket->so_rcv.sb_cc) {
/* some to read, wake-up */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
@@ -1579,13 +1547,13 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
#endif
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/* now is it in the mapping array of what we have accepted? */
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN) &&
- compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_map) &&
+ SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
/* Nope not in the valid range dump it */
sctp_set_rwnd(stcb, asoc);
if ((asoc->cnt_on_all_streams +
@@ -1595,7 +1563,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
} else {
SCTP_STAT_INCR(sctps_datadroprwnd);
}
- indx = *break_flag;
*break_flag = 1;
return (0);
}
@@ -1630,7 +1597,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
SCTP_STAT_INCR(sctps_badsid);
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
asoc->highest_tsn_inside_nr_map = tsn;
}
if (tsn == (asoc->cumulative_tsn + 1)) {
@@ -1666,9 +1633,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
if ((chunk_flags & SCTP_DATA_FIRST_FRAG) &&
(TAILQ_EMPTY(&asoc->resetHead)) &&
(chunk_flags & SCTP_DATA_UNORDERED) == 0 &&
- (compare_with_wrap(asoc->strmin[strmno].last_sequence_delivered,
- strmseq, MAX_SEQ) ||
- asoc->strmin[strmno].last_sequence_delivered == strmseq)) {
+ SCTP_SSN_GE(asoc->strmin[strmno].last_sequence_delivered, strmseq)) {
/* The incoming sseq is behind where we last delivered? */
SCTPDBG(SCTP_DEBUG_INDATA1, "EVIL/Broken-Dup S-SEQ:%d delivered:%d from peer, Abort!\n",
strmseq, asoc->strmin[strmno].last_sequence_delivered);
@@ -1692,8 +1657,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_14;
- sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
}
@@ -1711,12 +1675,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = dmbuf;
- while (mat) {
+ for (mat = dmbuf; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -1737,10 +1699,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct mbuf *lat;
l_len = 0;
- lat = dmbuf;
- while (lat) {
+ for (lat = dmbuf; lat; lat = SCTP_BUF_NEXT(lat)) {
l_len += SCTP_BUF_LEN(lat);
- lat = SCTP_BUF_NEXT(lat);
}
}
if (l_len > the_len) {
@@ -1779,7 +1739,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
goto failed_express_del;
}
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
asoc->highest_tsn_inside_nr_map = tsn;
}
sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -1817,15 +1777,10 @@ failed_express_del:
if (tsn == (control->sinfo_tsn + 1)) {
/* Yep, we can add it on */
int end = 0;
- uint32_t cumack;
if (chunk_flags & SCTP_DATA_LAST_FRAG) {
end = 1;
}
- cumack = asoc->cumulative_tsn;
- if ((cumack + 1) == tsn)
- cumack = tsn;
-
if (sctp_append_to_readq(stcb->sctp_ep, stcb, control, dmbuf, end,
tsn,
&stcb->sctp_socket->so_rcv)) {
@@ -1833,7 +1788,7 @@ failed_express_del:
goto failed_pdapi_express_del;
}
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
asoc->highest_tsn_inside_nr_map = tsn;
}
SCTP_STAT_INCR(sctps_recvexpressm);
@@ -1867,12 +1822,12 @@ failed_pdapi_express_del:
control = NULL;
if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) {
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
asoc->highest_tsn_inside_nr_map = tsn;
}
} else {
SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap);
- if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_map)) {
asoc->highest_tsn_inside_map = tsn;
}
}
@@ -1965,9 +1920,7 @@ failed_pdapi_express_del:
*ippp = ((strmno << 16) | strmseq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15;
- sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
} else {
@@ -2003,9 +1956,7 @@ failed_pdapi_express_del:
*ippp = ((strmno << 16) | strmseq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
}
@@ -2050,9 +2001,7 @@ failed_pdapi_express_del:
*ippp = ((strmno << 16) | strmseq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_17;
- sctp_abort_an_association(stcb->sctp_ep,
- stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
}
@@ -2082,8 +2031,7 @@ failed_pdapi_express_del:
* singletons I must worry about.
*/
if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) &&
- ((compare_with_wrap(tsn, liste->tsn, MAX_TSN)))
- ) {
+ SCTP_TSN_GT(tsn, liste->tsn)) {
/*
* yep its past where we need to reset... go
* ahead and queue it.
@@ -2092,14 +2040,13 @@ failed_pdapi_express_del:
/* first one on */
TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, control, next);
} else {
- struct sctp_queued_to_read *ctlOn;
+ struct sctp_queued_to_read *ctlOn,
+ *nctlOn;
unsigned char inserted = 0;
- ctlOn = TAILQ_FIRST(&asoc->pending_reply_queue);
- while (ctlOn) {
- if (compare_with_wrap(control->sinfo_tsn,
- ctlOn->sinfo_tsn, MAX_TSN)) {
- ctlOn = TAILQ_NEXT(ctlOn, next);
+ TAILQ_FOREACH_SAFE(ctlOn, &asoc->pending_reply_queue, next, nctlOn) {
+ if (SCTP_TSN_GT(control->sinfo_tsn, ctlOn->sinfo_tsn)) {
+ continue;
} else {
/* found it */
TAILQ_INSERT_BEFORE(ctlOn, control, next);
@@ -2159,36 +2106,34 @@ finish_express_del:
}
/* check the special flag for stream resets */
if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) &&
- ((compare_with_wrap(asoc->cumulative_tsn, liste->tsn, MAX_TSN)) ||
- (asoc->cumulative_tsn == liste->tsn))
- ) {
+ SCTP_TSN_GE(asoc->cumulative_tsn, liste->tsn)) {
/*
* we have finished working through the backlogged TSN's now
* time to reset streams. 1: call reset function. 2: free
* pending_reply space 3: distribute any chunks in
* pending_reply_queue.
*/
- struct sctp_queued_to_read *ctl;
+ struct sctp_queued_to_read *ctl, *nctl;
- sctp_reset_in_stream(stcb, liste->number_entries, liste->req.list_of_streams);
+ sctp_reset_in_stream(stcb, liste->number_entries, liste->list_of_streams);
TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
SCTP_FREE(liste, SCTP_M_STRESET);
/* sa_ignore FREED_MEMORY */
liste = TAILQ_FIRST(&asoc->resetHead);
- ctl = TAILQ_FIRST(&asoc->pending_reply_queue);
- if (ctl && (liste == NULL)) {
+ if (TAILQ_EMPTY(&asoc->resetHead)) {
/* All can be removed */
- while (ctl) {
+ TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) {
TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, next);
sctp_queue_data_to_stream(stcb, asoc, ctl, abort_flag);
if (*abort_flag) {
return (0);
}
- ctl = TAILQ_FIRST(&asoc->pending_reply_queue);
}
- } else if (ctl) {
- /* more than one in queue */
- while (!compare_with_wrap(ctl->sinfo_tsn, liste->tsn, MAX_TSN)) {
+ } else {
+ TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) {
+ if (SCTP_TSN_GT(ctl->sinfo_tsn, liste->tsn)) {
+ break;
+ }
/*
* if ctl->sinfo_tsn is <= liste->tsn we can
* process it which is the NOT of
@@ -2199,7 +2144,6 @@ finish_express_del:
if (*abort_flag) {
return (0);
}
- ctl = TAILQ_FIRST(&asoc->pending_reply_queue);
}
}
/*
@@ -2274,7 +2218,6 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
uint32_t old_cumack, old_base, old_highest, highest_tsn;
asoc = &stcb->asoc;
- at = 0;
old_cumack = asoc->cumulative_tsn;
old_base = asoc->mapping_array_base_tsn;
@@ -2296,8 +2239,8 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
}
asoc->cumulative_tsn = asoc->mapping_array_base_tsn + (at - 1);
- if (compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_map, MAX_TSN) &&
- compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->cumulative_tsn, asoc->highest_tsn_inside_map) &&
+ SCTP_TSN_GT(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map)) {
#ifdef INVARIANTS
panic("huh, cumack 0x%x greater than high-tsn 0x%x in map",
asoc->cumulative_tsn, asoc->highest_tsn_inside_map);
@@ -2312,9 +2255,7 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn;
#endif
}
- if (compare_with_wrap(asoc->highest_tsn_inside_nr_map,
- asoc->highest_tsn_inside_map,
- MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) {
highest_tsn = asoc->highest_tsn_inside_nr_map;
} else {
highest_tsn = asoc->highest_tsn_inside_map;
@@ -2339,7 +2280,7 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
#ifdef INVARIANTS
for (i = 0; i < asoc->mapping_array_size; i++) {
if ((asoc->mapping_array[i]) || (asoc->nr_mapping_array[i])) {
- printf("Error Mapping array's not clean at clear\n");
+ SCTP_PRINTF("Error Mapping array's not clean at clear\n");
sctp_print_mapping_array(asoc);
}
}
@@ -2361,7 +2302,7 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
#ifdef INVARIANTS
panic("impossible slide");
#else
- printf("impossible slide lgap:%x slide_end:%x slide_from:%x? at:%d\n",
+ SCTP_PRINTF("impossible slide lgap:%x slide_end:%x slide_from:%x? at:%d\n",
lgap, slide_end, slide_from, at);
return;
#endif
@@ -2370,7 +2311,7 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
#ifdef INVARIANTS
panic("would overrun buffer");
#else
- printf("Gak, would have overrun map end:%d slide_end:%d\n",
+ SCTP_PRINTF("Gak, would have overrun map end:%d slide_end:%d\n",
asoc->mapping_array_size, slide_end);
slide_end = asoc->mapping_array_size;
#endif
@@ -2424,17 +2365,14 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb)
}
}
-
void
-sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag)
+sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap)
{
struct sctp_association *asoc;
uint32_t highest_tsn;
asoc = &stcb->asoc;
- if (compare_with_wrap(asoc->highest_tsn_inside_nr_map,
- asoc->highest_tsn_inside_map,
- MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) {
highest_tsn = asoc->highest_tsn_inside_nr_map;
} else {
highest_tsn = asoc->highest_tsn_inside_map;
@@ -2454,13 +2392,14 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag)
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18);
}
- sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
- sctp_send_sack(stcb);
+ sctp_send_shutdown(stcb,
+ ((stcb->asoc.alternate) ? stcb->asoc.alternate : stcb->asoc.primary_destination));
+ sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
} else {
int is_a_gap;
/* is there a gap now ? */
- is_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN);
+ is_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn);
/*
* CMT DAC algorithm: increase number of packets received
@@ -2478,7 +2417,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag)
(stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) /* hit limit of pkts */
) {
- if ((stcb->asoc.sctp_cmt_on_off == 1) &&
+ if ((stcb->asoc.sctp_cmt_on_off > 0) &&
(SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) &&
(stcb->asoc.send_sack == 0) &&
(stcb->asoc.numduptsns == 0) &&
@@ -2505,7 +2444,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag)
* there are gaps or duplicates.
*/
(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
- sctp_send_sack(stcb);
+ sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
}
} else {
if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
@@ -2579,8 +2518,11 @@ doit_again:
int
sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
- struct sctphdr *sh, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net, uint32_t * high_tsn)
+ struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh, struct sctp_inpcb *inp,
+ struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t * high_tsn,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port)
{
struct sctp_data_chunk *ch, chunk_buf;
struct sctp_association *asoc;
@@ -2597,12 +2539,12 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
m = *mm;
SCTP_TCB_LOCK_ASSERT(stcb);
asoc = &stcb->asoc;
- if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) {
highest_tsn = asoc->highest_tsn_inside_nr_map;
} else {
highest_tsn = asoc->highest_tsn_inside_map;
}
- was_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN);
+ was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn);
/*
* setup where we got the last DATA packet from for any SACK that
* may need to go out. Don't bump the net. This is done ONLY when a
@@ -2657,7 +2599,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
if (length - *offset < chk_length) {
/* all done, mutulated chunk */
stop_proc = 1;
- break;
+ continue;
}
if (ch->ch.chunk_type == SCTP_DATA) {
if ((size_t)chk_length < sizeof(struct sctp_data_chunk) + 1) {
@@ -2687,8 +2629,10 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_19;
- sctp_abort_association(inp, stcb, m, iphlen, sh,
- op_err, 0, net->port);
+ sctp_abort_association(inp, stcb, m, iphlen,
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
return (2);
}
#ifdef SCTP_AUDITING_ENABLED
@@ -2713,7 +2657,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
* drop rep space left.
*/
stop_proc = 1;
- break;
+ continue;
}
} else {
/* not a data chunk in the data region */
@@ -2721,7 +2665,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
case SCTP_INITIATION:
case SCTP_INITIATION_ACK:
case SCTP_SELECTIVE_ACK:
- case SCTP_NR_SELECTIVE_ACK: /* EY */
+ case SCTP_NR_SELECTIVE_ACK:
case SCTP_HEARTBEAT_REQUEST:
case SCTP_HEARTBEAT_ACK:
case SCTP_ABORT_ASSOCIATION:
@@ -2752,7 +2696,12 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
struct mbuf *op_err;
op_err = sctp_generate_invmanparam(SCTP_CAUSE_PROTOCOL_VIOLATION);
- sctp_abort_association(inp, stcb, m, iphlen, sh, op_err, 0, net->port);
+ sctp_abort_association(inp, stcb,
+ m, iphlen,
+ src, dst,
+ sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
return (2);
}
break;
@@ -2779,11 +2728,13 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
phd->param_length =
htons(chk_length + sizeof(*phd));
SCTP_BUF_LEN(merr) = sizeof(*phd);
- SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset,
- SCTP_SIZE32(chk_length),
- M_DONTWAIT);
+ SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_DONTWAIT);
if (SCTP_BUF_NEXT(merr)) {
- sctp_queue_op_err(stcb, merr);
+ if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
+ sctp_m_freem(merr);
+ } else {
+ sctp_queue_op_err(stcb, merr);
+ }
} else {
sctp_m_freem(merr);
}
@@ -2795,7 +2746,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
} /* else skip this bad chunk and
* continue... */
break;
- }; /* switch of chunk type */
+ } /* switch of chunk type */
}
*offset += SCTP_SIZE32(chk_length);
if ((*offset >= length) || stop_proc) {
@@ -2808,15 +2759,14 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
if (ch == NULL) {
*offset = length;
stop_proc = 1;
- break;
-
+ continue;
}
- } /* while */
+ }
if (break_flag) {
/*
* we need to report rwnd overrun drops.
*/
- sctp_send_packet_dropped(stcb, net, *mm, iphlen, 0);
+ sctp_send_packet_dropped(stcb, net, *mm, length, iphlen, 0);
}
if (num_chunks) {
/*
@@ -2843,10 +2793,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
stcb->asoc.send_sack = 1;
}
/* Start a sack timer or QUEUE a SACK for sending */
- sctp_sack_check(stcb, was_a_gap, &abort_flag);
- if (abort_flag)
- return (2);
-
+ sctp_sack_check(stcb, was_a_gap);
return (0);
}
@@ -2856,7 +2803,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
int *num_frs,
uint32_t * biggest_newly_acked_tsn,
uint32_t * this_sack_lowest_newack,
- int *ecn_seg_sums)
+ int *rto_ok)
{
struct sctp_tmit_chunk *tp1;
unsigned int theTSN;
@@ -2897,11 +2844,6 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
* must be held until
* cum-ack passes
*/
- /*-
- * ECN Nonce: Add the nonce
- * value to the sender's
- * nonce sum
- */
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
/*-
* If it is less than RESEND, it is
@@ -2910,8 +2852,8 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
* via previous Gap Ack Blocks...
* i.e. ACKED or RESEND.
*/
- if (compare_with_wrap(tp1->rec.data.TSN_seq,
- *biggest_newly_acked_tsn, MAX_TSN)) {
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
+ *biggest_newly_acked_tsn)) {
*biggest_newly_acked_tsn = tp1->rec.data.TSN_seq;
}
/*-
@@ -2924,9 +2866,8 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
if (tp1->rec.data.chunk_was_revoked == 0)
tp1->whoTo->saw_newack = 1;
- if (compare_with_wrap(tp1->rec.data.TSN_seq,
- tp1->whoTo->this_sack_highest_newack,
- MAX_TSN)) {
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
+ tp1->whoTo->this_sack_highest_newack)) {
tp1->whoTo->this_sack_highest_newack =
tp1->rec.data.TSN_seq;
}
@@ -2984,6 +2925,10 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
tp1->rec.data.TSN_seq);
}
sctp_flight_size_decrease(tp1);
+ if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) (tp1->whoTo,
+ tp1);
+ }
sctp_total_flight_decrease(stcb, tp1);
tp1->whoTo->net_ack += tp1->send_size;
@@ -2997,22 +2942,26 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
* update RTO too ?
*/
if (tp1->do_rtt) {
- tp1->whoTo->RTO =
- sctp_calculate_rto(stcb,
- &stcb->asoc,
- tp1->whoTo,
- &tp1->sent_rcv_time,
- sctp_align_safe_nocopy);
+ if (*rto_ok) {
+ tp1->whoTo->RTO =
+ sctp_calculate_rto(stcb,
+ &stcb->asoc,
+ tp1->whoTo,
+ &tp1->sent_rcv_time,
+ sctp_align_safe_nocopy,
+ SCTP_RTT_FROM_DATA);
+ *rto_ok = 0;
+ }
+ if (tp1->whoTo->rto_needed == 0) {
+ tp1->whoTo->rto_needed = 1;
+ }
tp1->do_rtt = 0;
}
}
}
if (tp1->sent <= SCTP_DATAGRAM_RESEND) {
- (*ecn_seg_sums) += tp1->rec.data.ect_nonce;
- (*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM;
- if (compare_with_wrap(tp1->rec.data.TSN_seq,
- stcb->asoc.this_sack_highest_gap,
- MAX_TSN)) {
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
+ stcb->asoc.this_sack_highest_gap)) {
stcb->asoc.this_sack_highest_gap =
tp1->rec.data.TSN_seq;
}
@@ -3028,16 +2977,26 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
* All chunks NOT UNSENT fall through here and are marked
* (leave PR-SCTP ones that are to skip alone though)
*/
- if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ if ((tp1->sent != SCTP_FORWARD_TSN_SKIP) &&
+ (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) {
tp1->sent = SCTP_DATAGRAM_MARKED;
-
+ }
if (tp1->rec.data.chunk_was_revoked) {
/* deflate the cwnd */
tp1->whoTo->cwnd -= tp1->book_size;
tp1->rec.data.chunk_was_revoked = 0;
}
/* NR Sack code here */
- if (nr_sacking) {
+ if (nr_sacking &&
+ (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) {
+ if (stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
+ stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number);
+#endif
+ }
+ tp1->sent = SCTP_DATAGRAM_NR_ACKED;
if (tp1->data) {
/*
* sa_ignore
@@ -3052,10 +3011,9 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
}
break;
} /* if (tp1->TSN_seq == theTSN) */
- if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN,
- MAX_TSN))
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, theTSN)) {
break;
-
+ }
tp1 = TAILQ_NEXT(tp1, sctp_next);
if ((tp1 == NULL) && (circled == 0)) {
circled++;
@@ -3077,7 +3035,7 @@ static int
sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc,
uint32_t last_tsn, uint32_t * biggest_tsn_acked,
uint32_t * biggest_newly_acked_tsn, uint32_t * this_sack_lowest_newack,
- int num_seg, int num_nr_seg, int *ecn_seg_sums)
+ int num_seg, int num_nr_seg, int *rto_ok)
{
struct sctp_gap_ack_block *frag, block;
struct sctp_tmit_chunk *tp1;
@@ -3113,7 +3071,7 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct
/* This gap report is not in order, so restart. */
tp1 = TAILQ_FIRST(&asoc->sent_queue);
}
- if (compare_with_wrap((last_tsn + frag_end), *biggest_tsn_acked, MAX_TSN)) {
+ if (SCTP_TSN_GT((last_tsn + frag_end), *biggest_tsn_acked)) {
*biggest_tsn_acked = last_tsn + frag_end;
}
if (i < num_seg) {
@@ -3123,7 +3081,7 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct
}
if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end,
non_revocable, &num_frs, biggest_newly_acked_tsn,
- this_sack_lowest_newack, ecn_seg_sums)) {
+ this_sack_lowest_newack, rto_ok)) {
chunk_freed = 1;
}
prev_frag_end = frag_end;
@@ -3143,23 +3101,18 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
uint32_t biggest_tsn_acked)
{
struct sctp_tmit_chunk *tp1;
- int tot_revoked = 0;
- tp1 = TAILQ_FIRST(&asoc->sent_queue);
- while (tp1) {
- if (compare_with_wrap(tp1->rec.data.TSN_seq, cumack,
- MAX_TSN)) {
+ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cumack)) {
/*
* ok this guy is either ACK or MARKED. If it is
* ACKED it has been previously acked but not this
* time i.e. revoked. If it is MARKED it was ACK'ed
* again.
*/
- if (compare_with_wrap(tp1->rec.data.TSN_seq, biggest_tsn_acked,
- MAX_TSN))
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked)) {
break;
-
-
+ }
if (tp1->sent == SCTP_DATAGRAM_ACKED) {
/* it has been revoked */
tp1->sent = SCTP_DATAGRAM_SENT;
@@ -3182,7 +3135,6 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
* artificial inflation of the flight_size.
*/
tp1->whoTo->cwnd += tp1->book_size;
- tot_revoked++;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
sctp_log_sack(asoc->last_acked_seq,
cumack,
@@ -3198,24 +3150,6 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
}
if (tp1->sent == SCTP_DATAGRAM_UNSENT)
break;
- tp1 = TAILQ_NEXT(tp1, sctp_next);
- }
- if (tot_revoked > 0) {
- /*
- * Setup the ecn nonce re-sync point. We do this since once
- * data is revoked we begin to retransmit things, which do
- * NOT have the ECN bits set. This means we are now out of
- * sync and must wait until we get back in sync with the
- * peer to check ECN bits.
- */
- tp1 = TAILQ_FIRST(&asoc->send_queue);
- if (tp1 == NULL) {
- asoc->nonce_resync_tsn = asoc->sending_seq;
- } else {
- asoc->nonce_resync_tsn = tp1->rec.data.TSN_seq;
- }
- asoc->nonce_wait_for_ecne = 0;
- asoc->nonce_sum_check = 0;
}
}
@@ -3244,7 +3178,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
/* CMT DAC algo: finding out if SACK is a mixed SACK */
- if ((asoc->sctp_cmt_on_off == 1) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->saw_newack)
@@ -3254,12 +3188,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (stcb->asoc.peer_supports_prsctp) {
(void)SCTP_GETTIME_TIMEVAL(&now);
}
- tp1 = TAILQ_FIRST(&asoc->sent_queue);
- while (tp1) {
+ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
strike_flag = 0;
if (tp1->no_fr_allowed) {
/* this one had a timeout or something */
- tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
@@ -3269,8 +3201,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1->sent,
SCTP_FR_LOG_CHECK_STRIKE);
}
- if (compare_with_wrap(tp1->rec.data.TSN_seq, biggest_tsn_acked,
- MAX_TSN) ||
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked) ||
tp1->sent == SCTP_DATAGRAM_UNSENT) {
/* done */
break;
@@ -3281,17 +3212,14 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (timevalcmp(&now, &tp1->rec.data.timetodrop, >)) {
/* Yes so drop it */
if (tp1->data != NULL) {
- (void)sctp_release_pr_sctp_chunk(stcb, tp1,
- (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
+ (void)sctp_release_pr_sctp_chunk(stcb, tp1, 1,
SCTP_SO_NOT_LOCKED);
}
- tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
}
}
- if (compare_with_wrap(tp1->rec.data.TSN_seq,
- asoc->this_sack_highest_gap, MAX_TSN)) {
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->this_sack_highest_gap)) {
/* we are beyond the tsn in the sack */
break;
}
@@ -3302,7 +3230,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
/* Continue strikin FWD-TSN chunks */
tp1->rec.data.fwd_tsn_cnt++;
}
- tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
/*
@@ -3315,10 +3242,9 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* CMT, no data sent to this dest can be marked for
* FR using this SACK.
*/
- tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
- } else if (tp1->whoTo && compare_with_wrap(tp1->rec.data.TSN_seq,
- tp1->whoTo->this_sack_highest_newack, MAX_TSN)) {
+ } else if (tp1->whoTo && SCTP_TSN_GT(tp1->rec.data.TSN_seq,
+ tp1->whoTo->this_sack_highest_newack)) {
/*
* CMT: New acks were receieved for data sent to
* this dest. But no new acks were seen for data
@@ -3327,7 +3253,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* this SACK. This step covers part of the DAC algo
* and the HTNA algo as well.
*/
- tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
/*
@@ -3355,7 +3280,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->sent++;
}
- if ((asoc->sctp_cmt_on_off == 1) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If SACK flag is set to
@@ -3370,7 +3295,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* received after this missing TSN.
*/
if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) &&
- compare_with_wrap(this_sack_lowest_newack, tp1->rec.data.TSN_seq, MAX_TSN)) {
+ SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.TSN_seq)) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(16 + num_dests_sacked,
tp1->rec.data.TSN_seq,
@@ -3402,9 +3327,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
#endif
) {
- if ((compare_with_wrap(biggest_tsn_newly_acked,
- tp1->rec.data.fast_retran_tsn, MAX_TSN)) ||
- (biggest_tsn_newly_acked ==
+ if (SCTP_TSN_GE(biggest_tsn_newly_acked,
tp1->rec.data.fast_retran_tsn)) {
/*
* Strike the TSN, since this ack is
@@ -3421,7 +3344,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1->sent++;
}
strike_flag = 1;
- if ((asoc->sctp_cmt_on_off == 1) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If
@@ -3444,8 +3367,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
*/
if ((tp1->sent < SCTP_DATAGRAM_RESEND) &&
(num_dests_sacked == 1) &&
- compare_with_wrap(this_sack_lowest_newack,
- tp1->rec.data.TSN_seq, MAX_TSN)) {
+ SCTP_TSN_GT(this_sack_lowest_newack,
+ tp1->rec.data.TSN_seq)) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(32 + num_dests_sacked,
tp1->rec.data.TSN_seq,
@@ -3463,8 +3386,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* JRI: TODO: remove code for HTNA algo. CMT's SFR
* algo covers HTNA.
*/
- } else if (compare_with_wrap(tp1->rec.data.TSN_seq,
- biggest_tsn_newly_acked, MAX_TSN)) {
+ } else if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
+ biggest_tsn_newly_acked)) {
/*
* We don't strike these: This is the HTNA
* algorithm i.e. we don't strike If our TSN is
@@ -3482,7 +3405,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->sent++;
}
- if ((asoc->sctp_cmt_on_off == 1) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*
* CMT DAC algorithm: If SACK flag is set to
@@ -3497,7 +3420,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* received after this missing TSN.
*/
if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) &&
- compare_with_wrap(this_sack_lowest_newack, tp1->rec.data.TSN_seq, MAX_TSN)) {
+ SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.TSN_seq)) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(48 + num_dests_sacked,
tp1->rec.data.TSN_seq,
@@ -3522,6 +3445,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->whoTo) {
tp1->whoTo->net_ack++;
sctp_flight_size_decrease(tp1);
+ if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) (tp1->whoTo,
+ tp1);
+ }
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) {
sctp_log_rwnd(SCTP_INCREASE_PEER_RWND,
@@ -3542,17 +3469,18 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->snd_count > tp1->rec.data.timetodrop.tv_sec) {
/* Yes, so drop it */
if (tp1->data != NULL) {
- (void)sctp_release_pr_sctp_chunk(stcb, tp1,
- (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
+ (void)sctp_release_pr_sctp_chunk(stcb, tp1, 1,
SCTP_SO_NOT_LOCKED);
}
/* Make sure to flag we had a FR */
tp1->whoTo->net_ack++;
- tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
}
- /* printf("OK, we are now ready to FR this guy\n"); */
+ /*
+ * SCTP_PRINTF("OK, we are now ready to FR this
+ * guy\n");
+ */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(tp1->rec.data.TSN_seq, tp1->snd_count,
0, SCTP_FR_MARKED);
@@ -3562,7 +3490,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
SCTP_STAT_INCR(sctps_sendmultfastretrans);
}
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
- if (asoc->sctp_cmt_on_off == 1) {
+ if (asoc->sctp_cmt_on_off > 0) {
/*
* CMT: Using RTX_SSTHRESH policy for CMT.
* If CMT is being used, then pick dest with
@@ -3620,7 +3548,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tot_retrans++;
/* mark the sending seq for possible subsequent FR's */
/*
- * printf("Marking TSN for FR new value %x\n",
+ * SCTP_PRINTF("Marking TSN for FR new value %x\n",
* (uint32_t)tpi->rec.data.TSN_seq);
*/
if (TAILQ_EMPTY(&asoc->send_queue)) {
@@ -3652,6 +3580,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* this guy had a RTO calculation pending on
* it, cancel it
*/
+ if ((tp1->whoTo != NULL) &&
+ (tp1->whoTo->rto_needed == 0)) {
+ tp1->whoTo->rto_needed = 1;
+ }
tp1->do_rtt = 0;
}
if (alt != tp1->whoTo) {
@@ -3662,18 +3594,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
atomic_add_int(&alt->ref_count, 1);
}
}
- tp1 = TAILQ_NEXT(tp1, sctp_next);
- } /* while (tp1) */
-
- if (tot_retrans > 0) {
- /*
- * Setup the ecn nonce re-sync point. We do this since once
- * we go to FR something we introduce a Karn's rule scenario
- * and won't know the totals for the ECN bits.
- */
- asoc->nonce_resync_tsn = sending_seq;
- asoc->nonce_wait_for_ecne = 0;
- asoc->nonce_sum_check = 0;
}
}
@@ -3688,15 +3608,16 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
if (asoc->peer_supports_prsctp == 0) {
return (NULL);
}
- tp1 = TAILQ_FIRST(&asoc->sent_queue);
- while (tp1) {
+ TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
if (tp1->sent != SCTP_FORWARD_TSN_SKIP &&
- tp1->sent != SCTP_DATAGRAM_RESEND) {
+ tp1->sent != SCTP_DATAGRAM_RESEND &&
+ tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
/* no chance to advance, out of here */
break;
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
- if (tp1->sent == SCTP_FORWARD_TSN_SKIP) {
+ if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) ||
+ (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) {
sctp_misc_ints(SCTP_FWD_TSN_CHECK,
asoc->advanced_peer_ack_point,
tp1->rec.data.TSN_seq, 0, 0);
@@ -3713,7 +3634,6 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
(void)SCTP_GETTIME_TIMEVAL(&now);
now_filled = 1;
}
- tp2 = TAILQ_NEXT(tp1, sctp_next);
/*
* now we got a chunk which is marked for another
* retransmission to a PR-stream but has run out its chances
@@ -3730,8 +3650,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
/* Yes so drop it */
if (tp1->data) {
(void)sctp_release_pr_sctp_chunk(stcb, tp1,
- (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
- SCTP_SO_NOT_LOCKED);
+ 1, SCTP_SO_NOT_LOCKED);
}
} else {
/*
@@ -3746,12 +3665,10 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
* the chunk, advance our peer ack point and we can check
* the next chunk.
*/
- if (tp1->sent == SCTP_FORWARD_TSN_SKIP) {
+ if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) ||
+ (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) {
/* advance PeerAckPoint goes forward */
- if (compare_with_wrap(tp1->rec.data.TSN_seq,
- asoc->advanced_peer_ack_point,
- MAX_TSN)) {
-
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->advanced_peer_ack_point)) {
asoc->advanced_peer_ack_point = tp1->rec.data.TSN_seq;
a_adv = tp1;
} else if (tp1->rec.data.TSN_seq == asoc->advanced_peer_ack_point) {
@@ -3765,11 +3682,6 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
*/
break;
}
- /*
- * If we hit here we just dumped tp1, move to next tsn on
- * sent queue.
- */
- tp1 = tp2;
}
return (a_adv);
}
@@ -3790,11 +3702,10 @@ sctp_fs_audit(struct sctp_association *asoc)
TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
if (chk->sent < SCTP_DATAGRAM_RESEND) {
- printf("Chk TSN:%u size:%d inflight cnt:%d\n",
+ SCTP_PRINTF("Chk TSN:%u size:%d inflight cnt:%d\n",
chk->rec.data.TSN_seq,
chk->send_size,
- chk->snd_count
- );
+ chk->snd_count);
inflight++;
} else if (chk->sent == SCTP_DATAGRAM_RESEND) {
resend++;
@@ -3811,7 +3722,7 @@ sctp_fs_audit(struct sctp_association *asoc)
#ifdef INVARIANTS
panic("Flight size-express incorrect? \n");
#else
- printf("asoc->total_flight:%d cnt:%d\n",
+ SCTP_PRINTF("asoc->total_flight:%d cnt:%d\n",
entry_flight, entry_cnt);
SCTP_PRINTF("Flight size-express incorrect F:%d I:%d R:%d Ab:%d ACK:%d\n",
@@ -3826,7 +3737,6 @@ sctp_fs_audit(struct sctp_association *asoc)
static void
sctp_window_probe_recovery(struct sctp_tcb *stcb,
struct sctp_association *asoc,
- struct sctp_nets *net,
struct sctp_tmit_chunk *tp1)
{
tp1->window_probe = 0;
@@ -3840,6 +3750,10 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb,
return;
}
/* First setup this by shrinking flight */
+ if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) (tp1->whoTo,
+ tp1);
+ }
sctp_flight_size_decrease(tp1);
sctp_total_flight_decrease(stcb, tp1);
/* Now mark for resend */
@@ -3857,7 +3771,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb,
void
sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
- uint32_t rwnd, int nonce_sum_flag, int *abort_now)
+ uint32_t rwnd, int *abort_now, int ecne_seen)
{
struct sctp_nets *net;
struct sctp_association *asoc;
@@ -3866,6 +3780,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
int win_probe_recovery = 0;
int win_probe_recovered = 0;
int j, done_once = 0;
+ int rto_ok = 1;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_SACK_ARRIVALS_ENABLE) {
sctp_misc_ints(SCTP_SACK_LOG_EXPRESS, cumack,
@@ -3881,7 +3796,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
#endif
asoc = &stcb->asoc;
old_rwnd = asoc->peers_rwnd;
- if (compare_with_wrap(asoc->last_acked_seq, cumack, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->last_acked_seq, cumack)) {
/* old ack */
return;
} else if (asoc->last_acked_seq == cumack) {
@@ -3899,6 +3814,10 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
/* First setup for CC stuff */
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ if (SCTP_TSN_GT(cumack, net->cwr_window_tsn)) {
+ /* Drag along the window_tsn for cwr's */
+ net->cwr_window_tsn = cumack;
+ }
net->prev_cwnd = net->cwnd;
net->net_ack = 0;
net->net_ack2 = 0;
@@ -3909,6 +3828,9 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
*/
net->new_pseudo_cumack = 0;
net->will_exit_fast_recovery = 0;
+ if (stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) (stcb, net);
+ }
}
if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) {
uint32_t send_s;
@@ -3920,8 +3842,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
} else {
send_s = asoc->sending_seq;
}
- if ((cumack == send_s) ||
- compare_with_wrap(cumack, send_s, MAX_TSN)) {
+ if (SCTP_TSN_GE(cumack, send_s)) {
#ifndef INVARIANTS
struct mbuf *oper;
@@ -3947,7 +3868,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
- sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
return;
#endif
}
@@ -3961,22 +3882,13 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
__LINE__);
}
stcb->asoc.overall_error_count = 0;
- if (compare_with_wrap(cumack, asoc->last_acked_seq, MAX_TSN)) {
+ if (SCTP_TSN_GT(cumack, asoc->last_acked_seq)) {
/* process the new consecutive TSN first */
- tp1 = TAILQ_FIRST(&asoc->sent_queue);
- while (tp1) {
- tp2 = TAILQ_NEXT(tp1, sctp_next);
- if (compare_with_wrap(cumack, tp1->rec.data.TSN_seq,
- MAX_TSN) ||
- cumack == tp1->rec.data.TSN_seq) {
+ TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
+ if (SCTP_TSN_GE(cumack, tp1->rec.data.TSN_seq)) {
if (tp1->sent == SCTP_DATAGRAM_UNSENT) {
- printf("Warning, an unsent is now acked?\n");
+ SCTP_PRINTF("Warning, an unsent is now acked?\n");
}
- /*
- * ECN Nonce: Add the nonce to the sender's
- * nonce sum
- */
- asoc->nonce_sum_expect_base += tp1->rec.data.ect_nonce;
if (tp1->sent < SCTP_DATAGRAM_ACKED) {
/*
* If it is less than ACKED, it is
@@ -3992,6 +3904,10 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_decrease(tp1);
+ if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) (tp1->whoTo,
+ tp1);
+ }
/* sa_ignore NO_NULL_CHK */
sctp_total_flight_decrease(stcb, tp1);
}
@@ -4006,15 +3922,23 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
/* update RTO too? */
if (tp1->do_rtt) {
- tp1->whoTo->RTO =
- /*
- * sa_ignore
- * NO_NULL_CHK
- */
- sctp_calculate_rto(stcb,
- asoc, tp1->whoTo,
- &tp1->sent_rcv_time,
- sctp_align_safe_nocopy);
+ if (rto_ok) {
+ tp1->whoTo->RTO =
+ /*
+ * sa_ignore
+ * NO_NULL_CH
+ * K
+ */
+ sctp_calculate_rto(stcb,
+ asoc, tp1->whoTo,
+ &tp1->sent_rcv_time,
+ sctp_align_safe_nocopy,
+ SCTP_RTT_FROM_DATA);
+ rto_ok = 0;
+ }
+ if (tp1->whoTo->rto_needed == 0) {
+ tp1->whoTo->rto_needed = 1;
+ }
tp1->do_rtt = 0;
}
}
@@ -4047,12 +3971,21 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
tp1->whoTo->cwnd -= tp1->book_size;
tp1->rec.data.chunk_was_revoked = 0;
}
- tp1->sent = SCTP_DATAGRAM_ACKED;
+ if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
+ if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number);
+#endif
+ }
+ }
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
if (tp1->data) {
/* sa_ignore NO_NULL_CHK */
sctp_free_bufspace(stcb, asoc, tp1, 1);
sctp_m_freem(tp1->data);
+ tp1->data = NULL;
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
sctp_log_sack(asoc->last_acked_seq,
@@ -4062,10 +3995,8 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
0,
SCTP_LOG_FREE_SENT);
}
- tp1->data = NULL;
asoc->sent_queue_cnt--;
- sctp_free_a_chunk(stcb, tp1);
- tp1 = tp2;
+ sctp_free_a_chunk(stcb, tp1, SCTP_SO_NOT_LOCKED);
} else {
break;
}
@@ -4074,16 +4005,16 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
/* sa_ignore NO_NULL_CHK */
if (stcb->sctp_socket) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SOCKBUF_LOCK(&stcb->sctp_socket->so_snd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) {
/* sa_ignore NO_NULL_CHK */
- sctp_wakeup_log(stcb, cumack, 1, SCTP_WAKESND_FROM_SACK);
+ sctp_wakeup_log(stcb, 1, SCTP_WAKESND_FROM_SACK);
}
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -4097,19 +4028,60 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
#endif
sctp_sowwakeup_locked(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
} else {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) {
- sctp_wakeup_log(stcb, cumack, 1, SCTP_NOWAKE_FROM_SACK);
+ sctp_wakeup_log(stcb, 1, SCTP_NOWAKE_FROM_SACK);
}
}
/* JRS - Use the congestion control given in the CC module */
- if (asoc->last_acked_seq != cumack)
+ if ((asoc->last_acked_seq != cumack) && (ecne_seen == 0)) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ if (net->net_ack2 > 0) {
+ /*
+ * Karn's rule applies to clearing error
+ * count, this is optional.
+ */
+ net->error_count = 0;
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
+ /* addr came good */
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
+ 0, (void *)net, SCTP_SO_NOT_LOCKED);
+ }
+ if (net == stcb->asoc.primary_destination) {
+ if (stcb->asoc.alternate) {
+ /*
+ * release the alternate,
+ * primary is good
+ */
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_PF) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
+ /* Done with this net */
+ net->net_ack = 0;
+ }
+ /* restore any doubled timers */
+ net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
+ if (net->RTO < stcb->asoc.minrto) {
+ net->RTO = stcb->asoc.minrto;
+ }
+ if (net->RTO > stcb->asoc.maxrto) {
+ net->RTO = stcb->asoc.maxrto;
+ }
+ }
+ }
asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, 1, 0, 0);
-
+ }
asoc->last_acked_seq = cumack;
if (TAILQ_EMPTY(&asoc->sent_queue)) {
@@ -4121,54 +4093,6 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
asoc->total_flight = 0;
asoc->total_flight_count = 0;
}
- /* ECN Nonce updates */
- if (asoc->ecn_nonce_allowed) {
- if (asoc->nonce_sum_check) {
- if (nonce_sum_flag != ((asoc->nonce_sum_expect_base) & SCTP_SACK_NONCE_SUM)) {
- if (asoc->nonce_wait_for_ecne == 0) {
- struct sctp_tmit_chunk *lchk;
-
- lchk = TAILQ_FIRST(&asoc->send_queue);
- asoc->nonce_wait_for_ecne = 1;
- if (lchk) {
- asoc->nonce_wait_tsn = lchk->rec.data.TSN_seq;
- } else {
- asoc->nonce_wait_tsn = asoc->sending_seq;
- }
- } else {
- if (compare_with_wrap(asoc->last_acked_seq, asoc->nonce_wait_tsn, MAX_TSN) ||
- (asoc->last_acked_seq == asoc->nonce_wait_tsn)) {
- /*
- * Misbehaving peer. We need
- * to react to this guy
- */
- asoc->ecn_allowed = 0;
- asoc->ecn_nonce_allowed = 0;
- }
- }
- }
- } else {
- /* See if Resynchronization Possible */
- if (compare_with_wrap(asoc->last_acked_seq, asoc->nonce_resync_tsn, MAX_TSN)) {
- asoc->nonce_sum_check = 1;
- /*
- * Now we must calculate what the base is.
- * We do this based on two things, we know
- * the total's for all the segments
- * gap-acked in the SACK (none). We also
- * know the SACK's nonce sum, its in
- * nonce_sum_flag. So we can build a truth
- * table to back-calculate the new value of
- * asoc->nonce_sum_expect_base:
- *
- * SACK-flag-Value Seg-Sums Base 0 0 0
- * 1 0 1 0 1 1 1
- * 1 0
- */
- asoc->nonce_sum_expect_base = (0 ^ nonce_sum_flag) & SCTP_SACK_NONCE_SUM;
- }
- }
- }
/* RWND update */
asoc->peers_rwnd = sctp_sbspace_sub(rwnd,
(uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh))));
@@ -4195,7 +4119,7 @@ again:
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (tp1->window_probe) {
/* move back to data send queue */
- sctp_window_probe_recovery(stcb, asoc, net, tp1);
+ sctp_window_probe_recovery(stcb, asoc, tp1);
break;
}
}
@@ -4228,13 +4152,6 @@ again:
stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_22);
}
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_23);
- }
- }
}
}
if ((j == 0) &&
@@ -4306,23 +4223,21 @@ again:
abort_out_now:
*abort_now = 1;
/* XXX */
- oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
+ oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_DONTWAIT, 1, MT_DATA);
if (oper) {
struct sctp_paramhdr *ph;
- uint32_t *ippp;
- SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
- sizeof(uint32_t);
+ SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr);
ph = mtod(oper, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(oper));
- ippp = (uint32_t *) (ph + 1);
- *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_24);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
- sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
} else {
+ struct sctp_nets *netp;
+
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
@@ -4330,26 +4245,36 @@ again:
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown(stcb,
- stcb->asoc.primary_destination);
+ if (asoc->alternate) {
+ netp = asoc->alternate;
+ } else {
+ netp = asoc->primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
}
} else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
(asoc->stream_queue_cnt == 0)) {
+ struct sctp_nets *netp;
+
if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
goto abort_out_now;
}
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- sctp_send_shutdown_ack(stcb,
- stcb->asoc.primary_destination);
sctp_stop_timers_for_shutdown(stcb);
+ if (asoc->alternate) {
+ netp = asoc->alternate;
+ } else {
+ netp = asoc->primary_destination;
+ }
+ sctp_send_shutdown_ack(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
}
}
/*********************************************/
@@ -4357,7 +4282,7 @@ again:
/* (section 4.2) */
/*********************************************/
/* C1. update advancedPeerAckPoint */
- if (compare_with_wrap(cumack, asoc->advanced_peer_ack_point, MAX_TSN)) {
+ if (SCTP_TSN_GT(cumack, asoc->advanced_peer_ack_point)) {
asoc->advanced_peer_ack_point = cumack;
}
/* PR-Sctp issues need to be addressed too */
@@ -4368,22 +4293,12 @@ again:
old_adv_peer_ack_point = asoc->advanced_peer_ack_point;
lchk = sctp_try_advance_peer_ack_point(stcb, asoc);
/* C3. See if we need to send a Fwd-TSN */
- if (compare_with_wrap(asoc->advanced_peer_ack_point, cumack,
- MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cumack)) {
/*
- * ISSUE with ECN, see FWD-TSN processing for notes
- * on issues that will occur when the ECN NONCE
- * stuff is put into SCTP for cross checking.
+ * ISSUE with ECN, see FWD-TSN processing.
*/
- if (compare_with_wrap(asoc->advanced_peer_ack_point, old_adv_peer_ack_point,
- MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, old_adv_peer_ack_point)) {
send_forward_tsn(stcb, asoc);
- /*
- * ECN Nonce: Disable Nonce Sum check when
- * FWD TSN is sent and store resync tsn
- */
- asoc->nonce_sum_check = 0;
- asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point;
} else if (lchk) {
/* try to FR fwd-tsn's that get lost too */
if (lchk->rec.data.fwd_tsn_cnt >= 3) {
@@ -4408,15 +4323,14 @@ again:
void
sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
- struct sctp_tcb *stcb, struct sctp_nets *net_from,
+ struct sctp_tcb *stcb,
uint16_t num_seg, uint16_t num_nr_seg, uint16_t num_dup,
int *abort_now, uint8_t flags,
- uint32_t cum_ack, uint32_t rwnd)
+ uint32_t cum_ack, uint32_t rwnd, int ecne_seen)
{
struct sctp_association *asoc;
struct sctp_tmit_chunk *tp1, *tp2;
uint32_t last_tsn, biggest_tsn_acked, biggest_tsn_newly_acked, this_sack_lowest_newack;
- uint32_t sav_cum_ack;
uint16_t wake_him = 0;
uint32_t send_s = 0;
long j;
@@ -4426,8 +4340,8 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
int win_probe_recovery = 0;
int win_probe_recovered = 0;
struct sctp_nets *net = NULL;
- int nonce_sum_flag, ecn_seg_sums = 0;
int done_once;
+ int rto_ok = 1;
uint8_t reneged_all = 0;
uint8_t cmt_dac_flag;
@@ -4455,10 +4369,8 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
SCTP_TCB_LOCK_ASSERT(stcb);
/* CMT DAC algo */
this_sack_lowest_newack = 0;
- j = 0;
SCTP_STAT_INCR(sctps_slowpath_sack);
last_tsn = cum_ack;
- nonce_sum_flag = flags & SCTP_SACK_NONCE_SUM;
cmt_dac_flag = flags & SCTP_SACK_CMT_DAC;
#ifdef SCTP_ASOCLOG_OF_TSNS
stcb->asoc.cumack_log[stcb->asoc.cumack_log_at] = cum_ack;
@@ -4491,7 +4403,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
num_dup,
SCTP_LOG_NEW_SACK);
}
- if ((num_dup) && (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_FR_LOGGING_ENABLE | SCTP_EARLYFR_LOGGING_ENABLE))) {
+ if ((num_dup) && (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE)) {
uint16_t i;
uint32_t *dupdata, dblock;
@@ -4514,19 +4426,18 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
tp1 = NULL;
send_s = asoc->sending_seq;
}
- if (cum_ack == send_s ||
- compare_with_wrap(cum_ack, send_s, MAX_TSN)) {
+ if (SCTP_TSN_GE(cum_ack, send_s)) {
struct mbuf *oper;
/*
* no way, we have not even sent this TSN out yet.
* Peer is hopelessly messed up with us.
*/
- printf("NEW cum_ack:%x send_s:%x is smaller or equal\n",
+ SCTP_PRINTF("NEW cum_ack:%x send_s:%x is smaller or equal\n",
cum_ack, send_s);
if (tp1) {
- printf("Got send_s from tsn:%x + 1 of tp1:%p\n",
- tp1->rec.data.TSN_seq, tp1);
+ SCTP_PRINTF("Got send_s from tsn:%x + 1 of tp1:%p\n",
+ tp1->rec.data.TSN_seq, (void *)tp1);
}
hopeless_peer:
*abort_now = 1;
@@ -4546,19 +4457,17 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
- sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
return;
}
}
/**********************/
/* 1) check the range */
/**********************/
- if (compare_with_wrap(asoc->last_acked_seq, last_tsn, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->last_acked_seq, last_tsn)) {
/* acking something behind */
return;
}
- sav_cum_ack = asoc->last_acked_seq;
-
/* update the Rwnd of the peer */
if (TAILQ_EMPTY(&asoc->sent_queue) &&
TAILQ_EMPTY(&asoc->send_queue) &&
@@ -4580,13 +4489,6 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck1);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
- }
- }
net->partial_bytes_acked = 0;
net->flight_size = 0;
}
@@ -4602,6 +4504,10 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
* destination address basis.
*/
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ if (SCTP_TSN_GT(cum_ack, net->cwr_window_tsn)) {
+ /* Drag along the window_tsn for cwr's */
+ net->cwr_window_tsn = cum_ack;
+ }
net->prev_cwnd = net->cwnd;
net->net_ack = 0;
net->net_ack2 = 0;
@@ -4612,19 +4518,14 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
*/
net->new_pseudo_cumack = 0;
net->will_exit_fast_recovery = 0;
+ if (stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) (stcb, net);
+ }
}
/* process the new consecutive TSN first */
- tp1 = TAILQ_FIRST(&asoc->sent_queue);
- while (tp1) {
- if (compare_with_wrap(last_tsn, tp1->rec.data.TSN_seq,
- MAX_TSN) ||
- last_tsn == tp1->rec.data.TSN_seq) {
+ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
+ if (SCTP_TSN_GE(last_tsn, tp1->rec.data.TSN_seq)) {
if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
- /*
- * ECN Nonce: Add the nonce to the sender's
- * nonce sum
- */
- asoc->nonce_sum_expect_base += tp1->rec.data.ect_nonce;
accum_moved = 1;
if (tp1->sent < SCTP_DATAGRAM_ACKED) {
/*
@@ -4656,6 +4557,10 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
}
sctp_flight_size_decrease(tp1);
sctp_total_flight_decrease(stcb, tp1);
+ if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) (tp1->whoTo,
+ tp1);
+ }
}
tp1->whoTo->net_ack += tp1->send_size;
@@ -4673,11 +4578,18 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
/* update RTO too? */
if (tp1->do_rtt) {
- tp1->whoTo->RTO =
- sctp_calculate_rto(stcb,
- asoc, tp1->whoTo,
- &tp1->sent_rcv_time,
- sctp_align_safe_nocopy);
+ if (rto_ok) {
+ tp1->whoTo->RTO =
+ sctp_calculate_rto(stcb,
+ asoc, tp1->whoTo,
+ &tp1->sent_rcv_time,
+ sctp_align_safe_nocopy,
+ SCTP_RTT_FROM_DATA);
+ rto_ok = 0;
+ }
+ if (tp1->whoTo->rto_needed == 0) {
+ tp1->whoTo->rto_needed = 1;
+ }
tp1->do_rtt = 0;
}
}
@@ -4722,12 +4634,13 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
tp1->whoTo->cwnd -= tp1->book_size;
tp1->rec.data.chunk_was_revoked = 0;
}
- tp1->sent = SCTP_DATAGRAM_ACKED;
+ if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
+ tp1->sent = SCTP_DATAGRAM_ACKED;
+ }
}
} else {
break;
}
- tp1 = TAILQ_NEXT(tp1, sctp_next);
}
biggest_tsn_newly_acked = biggest_tsn_acked = last_tsn;
/* always set this up to cum-ack */
@@ -4753,7 +4666,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
*/
if (sctp_handle_segments(m, &offset_seg, stcb, asoc, last_tsn, &biggest_tsn_acked,
&biggest_tsn_newly_acked, &this_sack_lowest_newack,
- num_seg, num_nr_seg, &ecn_seg_sums)) {
+ num_seg, num_nr_seg, &rto_ok)) {
wake_him++;
}
if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) {
@@ -4761,16 +4674,13 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
* validate the biggest_tsn_acked in the gap acks if
* strict adherence is wanted.
*/
- if ((biggest_tsn_acked == send_s) ||
- (compare_with_wrap(biggest_tsn_acked, send_s, MAX_TSN))) {
+ if (SCTP_TSN_GE(biggest_tsn_acked, send_s)) {
/*
* peer is either confused or we are under
* attack. We must abort.
*/
- printf("Hopeless peer! biggest_tsn_acked:%x largest seq:%x\n",
- biggest_tsn_acked,
- send_s);
-
+ SCTP_PRINTF("Hopeless peer! biggest_tsn_acked:%x largest seq:%x\n",
+ biggest_tsn_acked, send_s);
goto hopeless_peer;
}
}
@@ -4778,7 +4688,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
/*******************************************/
/* cancel ALL T3-send timer if accum moved */
/*******************************************/
- if (asoc->sctp_cmt_on_off == 1) {
+ if (asoc->sctp_cmt_on_off > 0) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->new_pseudo_cumack)
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
@@ -4799,39 +4709,30 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
/********************************************/
asoc->last_acked_seq = cum_ack;
- tp1 = TAILQ_FIRST(&asoc->sent_queue);
- if (tp1 == NULL)
- goto done_with_it;
- do {
- if (compare_with_wrap(tp1->rec.data.TSN_seq, cum_ack,
- MAX_TSN)) {
+ TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cum_ack)) {
break;
}
- if (tp1->sent == SCTP_DATAGRAM_UNSENT) {
- /* no more sent on list */
- printf("Warning, tp1->sent == %d and its now acked?\n",
- tp1->sent);
+ if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
+ if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number);
+#endif
+ }
}
- tp2 = TAILQ_NEXT(tp1, sctp_next);
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
if (tp1->pr_sctp_on) {
if (asoc->pr_sctp_cnt != 0)
asoc->pr_sctp_cnt--;
}
- if (TAILQ_EMPTY(&asoc->sent_queue) &&
- (asoc->total_flight > 0)) {
-#ifdef INVARIANTS
- panic("Warning flight size is postive and should be 0");
-#else
- SCTP_PRINTF("Warning flight size incorrect should be 0 is %d\n",
- asoc->total_flight);
-#endif
- asoc->total_flight = 0;
- }
+ asoc->sent_queue_cnt--;
if (tp1->data) {
/* sa_ignore NO_NULL_CHK */
sctp_free_bufspace(stcb, asoc, tp1, 1);
sctp_m_freem(tp1->data);
+ tp1->data = NULL;
if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) {
asoc->sent_queue_cnt_removeable--;
}
@@ -4844,25 +4745,29 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
0,
SCTP_LOG_FREE_SENT);
}
- tp1->data = NULL;
- asoc->sent_queue_cnt--;
- sctp_free_a_chunk(stcb, tp1);
+ sctp_free_a_chunk(stcb, tp1, SCTP_SO_NOT_LOCKED);
wake_him++;
- tp1 = tp2;
- } while (tp1 != NULL);
-
-done_with_it:
+ }
+ if (TAILQ_EMPTY(&asoc->sent_queue) && (asoc->total_flight > 0)) {
+#ifdef INVARIANTS
+ panic("Warning flight size is postive and should be 0");
+#else
+ SCTP_PRINTF("Warning flight size incorrect should be 0 is %d\n",
+ asoc->total_flight);
+#endif
+ asoc->total_flight = 0;
+ }
/* sa_ignore NO_NULL_CHK */
if ((wake_him) && (stcb->sctp_socket)) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SOCKBUF_LOCK(&stcb->sctp_socket->so_snd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) {
- sctp_wakeup_log(stcb, cum_ack, wake_him, SCTP_WAKESND_FROM_SACK);
+ sctp_wakeup_log(stcb, wake_him, SCTP_WAKESND_FROM_SACK);
}
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -4876,19 +4781,17 @@ done_with_it:
}
#endif
sctp_sowwakeup_locked(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
} else {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) {
- sctp_wakeup_log(stcb, cum_ack, wake_him, SCTP_NOWAKE_FROM_SACK);
+ sctp_wakeup_log(stcb, wake_him, SCTP_NOWAKE_FROM_SACK);
}
}
if (asoc->fast_retran_loss_recovery && accum_moved) {
- if (compare_with_wrap(asoc->last_acked_seq,
- asoc->fast_recovery_tsn, MAX_TSN) ||
- asoc->last_acked_seq == asoc->fast_recovery_tsn) {
+ if (SCTP_TSN_GE(asoc->last_acked_seq, asoc->fast_recovery_tsn)) {
/* Setup so we will exit RFC2582 fast recovery */
will_exit_fast_recovery = 1;
}
@@ -4909,37 +4812,33 @@ done_with_it:
} else if (asoc->saw_sack_with_frags) {
int cnt_revoked = 0;
- tp1 = TAILQ_FIRST(&asoc->sent_queue);
- if (tp1 != NULL) {
- /* Peer revoked all dg's marked or acked */
- TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
- if (tp1->sent == SCTP_DATAGRAM_ACKED) {
- tp1->sent = SCTP_DATAGRAM_SENT;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
- sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
- tp1->whoTo->flight_size,
- tp1->book_size,
- (uintptr_t) tp1->whoTo,
- tp1->rec.data.TSN_seq);
- }
- sctp_flight_size_increase(tp1);
- sctp_total_flight_increase(stcb, tp1);
- tp1->rec.data.chunk_was_revoked = 1;
- /*
- * To ensure that this increase in
- * flightsize, which is artificial,
- * does not throttle the sender, we
- * also increase the cwnd
- * artificially.
- */
- tp1->whoTo->cwnd += tp1->book_size;
- cnt_revoked++;
+ /* Peer revoked all dg's marked or acked */
+ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
+ if (tp1->sent == SCTP_DATAGRAM_ACKED) {
+ tp1->sent = SCTP_DATAGRAM_SENT;
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
+ sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
+ tp1->whoTo->flight_size,
+ tp1->book_size,
+ (uintptr_t) tp1->whoTo,
+ tp1->rec.data.TSN_seq);
}
- }
- if (cnt_revoked) {
- reneged_all = 1;
+ sctp_flight_size_increase(tp1);
+ sctp_total_flight_increase(stcb, tp1);
+ tp1->rec.data.chunk_was_revoked = 1;
+ /*
+ * To ensure that this increase in
+ * flightsize, which is artificial, does not
+ * throttle the sender, we also increase the
+ * cwnd artificially.
+ */
+ tp1->whoTo->cwnd += tp1->book_size;
+ cnt_revoked++;
}
}
+ if (cnt_revoked) {
+ reneged_all = 1;
+ }
asoc->saw_sack_with_frags = 0;
}
if (num_nr_seg > 0)
@@ -4948,19 +4847,54 @@ done_with_it:
asoc->saw_sack_with_nr_frags = 0;
/* JRS - Use the congestion control given in the CC module */
- asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery);
-
+ if (ecne_seen == 0) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ if (net->net_ack2 > 0) {
+ /*
+ * Karn's rule applies to clearing error
+ * count, this is optional.
+ */
+ net->error_count = 0;
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
+ /* addr came good */
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
+ 0, (void *)net, SCTP_SO_NOT_LOCKED);
+ }
+ if (net == stcb->asoc.primary_destination) {
+ if (stcb->asoc.alternate) {
+ /*
+ * release the alternate,
+ * primary is good
+ */
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_PF) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
+ /* Done with this net */
+ net->net_ack = 0;
+ }
+ /* restore any doubled timers */
+ net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
+ if (net->RTO < stcb->asoc.minrto) {
+ net->RTO = stcb->asoc.minrto;
+ }
+ if (net->RTO > stcb->asoc.maxrto) {
+ net->RTO = stcb->asoc.maxrto;
+ }
+ }
+ }
+ asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery);
+ }
if (TAILQ_EMPTY(&asoc->sent_queue)) {
/* nothing left in-flight */
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
/* stop all timers */
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_29);
- }
- }
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30);
net->flight_size = 0;
@@ -5017,24 +4951,22 @@ done_with_it:
abort_out_now:
*abort_now = 1;
/* XXX */
- oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
+ oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_DONTWAIT, 1, MT_DATA);
if (oper) {
struct sctp_paramhdr *ph;
- uint32_t *ippp;
- SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
- sizeof(uint32_t);
+ SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr);
ph = mtod(oper, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(oper));
- ippp = (uint32_t *) (ph + 1);
- *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_31);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31;
- sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
return;
} else {
+ struct sctp_nets *netp;
+
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
@@ -5042,27 +4974,37 @@ done_with_it:
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown(stcb,
- stcb->asoc.primary_destination);
+ if (asoc->alternate) {
+ netp = asoc->alternate;
+ } else {
+ netp = asoc->primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
}
return;
} else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
(asoc->stream_queue_cnt == 0)) {
+ struct sctp_nets *netp;
+
if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
goto abort_out_now;
}
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- sctp_send_shutdown_ack(stcb,
- stcb->asoc.primary_destination);
sctp_stop_timers_for_shutdown(stcb);
+ if (asoc->alternate) {
+ netp = asoc->alternate;
+ } else {
+ netp = asoc->primary_destination;
+ }
+ sctp_send_shutdown_ack(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
return;
}
}
@@ -5079,7 +5021,7 @@ done_with_it:
* to be done. Setting this_sack_lowest_newack to the cum_ack will
* automatically ensure that.
*/
- if ((asoc->sctp_cmt_on_off == 1) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac) &&
(cmt_dac_flag == 0)) {
this_sack_lowest_newack = cum_ack;
@@ -5091,70 +5033,13 @@ done_with_it:
/* JRS - Use the congestion control given in the CC module */
asoc->cc_functions.sctp_cwnd_update_after_fr(stcb, asoc);
- /******************************************************************
- * Here we do the stuff with ECN Nonce checking.
- * We basically check to see if the nonce sum flag was incorrect
- * or if resynchronization needs to be done. Also if we catch a
- * misbehaving receiver we give him the kick.
- ******************************************************************/
-
- if (asoc->ecn_nonce_allowed) {
- if (asoc->nonce_sum_check) {
- if (nonce_sum_flag != ((asoc->nonce_sum_expect_base + ecn_seg_sums) & SCTP_SACK_NONCE_SUM)) {
- if (asoc->nonce_wait_for_ecne == 0) {
- struct sctp_tmit_chunk *lchk;
-
- lchk = TAILQ_FIRST(&asoc->send_queue);
- asoc->nonce_wait_for_ecne = 1;
- if (lchk) {
- asoc->nonce_wait_tsn = lchk->rec.data.TSN_seq;
- } else {
- asoc->nonce_wait_tsn = asoc->sending_seq;
- }
- } else {
- if (compare_with_wrap(asoc->last_acked_seq, asoc->nonce_wait_tsn, MAX_TSN) ||
- (asoc->last_acked_seq == asoc->nonce_wait_tsn)) {
- /*
- * Misbehaving peer. We need
- * to react to this guy
- */
- asoc->ecn_allowed = 0;
- asoc->ecn_nonce_allowed = 0;
- }
- }
- }
- } else {
- /* See if Resynchronization Possible */
- if (compare_with_wrap(asoc->last_acked_seq, asoc->nonce_resync_tsn, MAX_TSN)) {
- asoc->nonce_sum_check = 1;
- /*
- * now we must calculate what the base is.
- * We do this based on two things, we know
- * the total's for all the segments
- * gap-acked in the SACK, its stored in
- * ecn_seg_sums. We also know the SACK's
- * nonce sum, its in nonce_sum_flag. So we
- * can build a truth table to back-calculate
- * the new value of
- * asoc->nonce_sum_expect_base:
- *
- * SACK-flag-Value Seg-Sums Base 0 0 0
- * 1 0 1 0 1 1 1
- * 1 0
- */
- asoc->nonce_sum_expect_base = (ecn_seg_sums ^ nonce_sum_flag) & SCTP_SACK_NONCE_SUM;
- }
- }
- }
/* Now are we exiting loss recovery ? */
if (will_exit_fast_recovery) {
/* Ok, we must exit fast recovery */
asoc->fast_retran_loss_recovery = 0;
}
if ((asoc->sat_t3_loss_recovery) &&
- ((compare_with_wrap(asoc->last_acked_seq, asoc->sat_t3_recovery_tsn,
- MAX_TSN) ||
- (asoc->last_acked_seq == asoc->sat_t3_recovery_tsn)))) {
+ SCTP_TSN_GE(asoc->last_acked_seq, asoc->sat_t3_recovery_tsn)) {
/* end satellite t3 loss recovery */
asoc->sat_t3_loss_recovery = 0;
}
@@ -5200,7 +5085,7 @@ again:
*/
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (tp1->window_probe) {
- sctp_window_probe_recovery(stcb, asoc, net, tp1);
+ sctp_window_probe_recovery(stcb, asoc, tp1);
break;
}
}
@@ -5230,13 +5115,6 @@ again:
stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_22);
}
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_23);
- }
- }
}
}
if ((j == 0) &&
@@ -5272,7 +5150,7 @@ again:
/* (section 4.2) */
/*********************************************/
/* C1. update advancedPeerAckPoint */
- if (compare_with_wrap(cum_ack, asoc->advanced_peer_ack_point, MAX_TSN)) {
+ if (SCTP_TSN_GT(cum_ack, asoc->advanced_peer_ack_point)) {
asoc->advanced_peer_ack_point = cum_ack;
}
/* C2. try to further move advancedPeerAckPoint ahead */
@@ -5283,28 +5161,17 @@ again:
old_adv_peer_ack_point = asoc->advanced_peer_ack_point;
lchk = sctp_try_advance_peer_ack_point(stcb, asoc);
/* C3. See if we need to send a Fwd-TSN */
- if (compare_with_wrap(asoc->advanced_peer_ack_point, cum_ack,
- MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cum_ack)) {
/*
- * ISSUE with ECN, see FWD-TSN processing for notes
- * on issues that will occur when the ECN NONCE
- * stuff is put into SCTP for cross checking.
+ * ISSUE with ECN, see FWD-TSN processing.
*/
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
sctp_misc_ints(SCTP_FWD_TSN_CHECK,
0xee, cum_ack, asoc->advanced_peer_ack_point,
old_adv_peer_ack_point);
}
- if (compare_with_wrap(asoc->advanced_peer_ack_point, old_adv_peer_ack_point,
- MAX_TSN)) {
-
+ if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, old_adv_peer_ack_point)) {
send_forward_tsn(stcb, asoc);
- /*
- * ECN Nonce: Disable Nonce Sum check when
- * FWD TSN is sent and store resync tsn
- */
- asoc->nonce_sum_check = 0;
- asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point;
} else if (lchk) {
/* try to FR fwd-tsn's that get lost too */
if (lchk->rec.data.fwd_tsn_cnt >= 3) {
@@ -5328,8 +5195,7 @@ again:
}
void
-sctp_update_acked(struct sctp_tcb *stcb, struct sctp_shutdown_chunk *cp,
- struct sctp_nets *netp, int *abort_flag)
+sctp_update_acked(struct sctp_tcb *stcb, struct sctp_shutdown_chunk *cp, int *abort_flag)
{
/* Copy cum-ack */
uint32_t cum_ack, a_rwnd;
@@ -5339,7 +5205,7 @@ sctp_update_acked(struct sctp_tcb *stcb, struct sctp_shutdown_chunk *cp,
a_rwnd = stcb->asoc.peers_rwnd + stcb->asoc.total_flight;
/* Now call the express sack handling */
- sctp_express_handle_sack(stcb, cum_ack, a_rwnd, 0, abort_flag);
+ sctp_express_handle_sack(stcb, cum_ack, a_rwnd, abort_flag, 0);
}
static void
@@ -5356,11 +5222,8 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
* First deliver anything prior to and including the stream no that
* came in
*/
- ctl = TAILQ_FIRST(&strmin->inqueue);
- while (ctl) {
- nctl = TAILQ_NEXT(ctl, next);
- if (compare_with_wrap(tt, ctl->sinfo_ssn, MAX_SEQ) ||
- (tt == ctl->sinfo_ssn)) {
+ TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next, nctl) {
+ if (SCTP_SSN_GE(tt, ctl->sinfo_ssn)) {
/* this is deliverable now */
TAILQ_REMOVE(&strmin->inqueue, ctl, next);
/* subtract pending on streams */
@@ -5377,16 +5240,13 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
/* no more delivery now. */
break;
}
- ctl = nctl;
}
/*
* now we must deliver things in queue the normal way if any are
* now ready.
*/
tt = strmin->last_sequence_delivered + 1;
- ctl = TAILQ_FIRST(&strmin->inqueue);
- while (ctl) {
- nctl = TAILQ_NEXT(ctl, next);
+ TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next, nctl) {
if (tt == ctl->sinfo_ssn) {
/* this is deliverable now */
TAILQ_REMOVE(&strmin->inqueue, ctl, next);
@@ -5406,7 +5266,6 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
} else {
break;
}
- ctl = nctl;
}
}
@@ -5415,87 +5274,69 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
struct sctp_association *asoc,
uint16_t stream, uint16_t seq)
{
- struct sctp_tmit_chunk *chk, *at;
+ struct sctp_tmit_chunk *chk, *nchk;
- if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
- /* For each one on here see if we need to toss it */
+ /* For each one on here see if we need to toss it */
+ /*
+ * For now large messages held on the reasmqueue that are complete
+ * will be tossed too. We could in theory do more work to spin
+ * through and stop after dumping one msg aka seeing the start of a
+ * new msg at the head, and call the delivery function... to see if
+ * it can be delivered... But for now we just dump everything on the
+ * queue.
+ */
+ TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
/*
- * For now large messages held on the reasmqueue that are
- * complete will be tossed too. We could in theory do more
- * work to spin through and stop after dumping one msg aka
- * seeing the start of a new msg at the head, and call the
- * delivery function... to see if it can be delivered... But
- * for now we just dump everything on the queue.
+ * Do not toss it if on a different stream or marked for
+ * unordered delivery in which case the stream sequence
+ * number has no meaning.
*/
- chk = TAILQ_FIRST(&asoc->reasmqueue);
- while (chk) {
- at = TAILQ_NEXT(chk, sctp_next);
- /*
- * Do not toss it if on a different stream or marked
- * for unordered delivery in which case the stream
- * sequence number has no meaning.
- */
- if ((chk->rec.data.stream_number != stream) ||
- ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)) {
- chk = at;
- continue;
+ if ((chk->rec.data.stream_number != stream) ||
+ ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)) {
+ continue;
+ }
+ if (chk->rec.data.stream_seq == seq) {
+ /* It needs to be tossed */
+ TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
+ if (SCTP_TSN_GT(chk->rec.data.TSN_seq, asoc->tsn_last_delivered)) {
+ asoc->tsn_last_delivered = chk->rec.data.TSN_seq;
+ asoc->str_of_pdapi = chk->rec.data.stream_number;
+ asoc->ssn_of_pdapi = chk->rec.data.stream_seq;
+ asoc->fragment_flags = chk->rec.data.rcv_flags;
}
- if (chk->rec.data.stream_seq == seq) {
- /* It needs to be tossed */
- TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
- if (compare_with_wrap(chk->rec.data.TSN_seq,
- asoc->tsn_last_delivered, MAX_TSN)) {
- asoc->tsn_last_delivered =
- chk->rec.data.TSN_seq;
- asoc->str_of_pdapi =
- chk->rec.data.stream_number;
- asoc->ssn_of_pdapi =
- chk->rec.data.stream_seq;
- asoc->fragment_flags =
- chk->rec.data.rcv_flags;
- }
- asoc->size_on_reasm_queue -= chk->send_size;
- sctp_ucount_decr(asoc->cnt_on_reasm_queue);
-
- /* Clear up any stream problem */
- if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
- SCTP_DATA_UNORDERED &&
- (compare_with_wrap(chk->rec.data.stream_seq,
- asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered,
- MAX_SEQ))) {
- /*
- * We must dump forward this streams
- * sequence number if the chunk is
- * not unordered that is being
- * skipped. There is a chance that
- * if the peer does not include the
- * last fragment in its FWD-TSN we
- * WILL have a problem here since
- * you would have a partial chunk in
- * queue that may not be
- * deliverable. Also if a Partial
- * delivery API as started the user
- * may get a partial chunk. The next
- * read returning a new chunk...
- * really ugly but I see no way
- * around it! Maybe a notify??
- */
- asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered =
- chk->rec.data.stream_seq;
- }
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
- sctp_free_a_chunk(stcb, chk);
- } else if (compare_with_wrap(chk->rec.data.stream_seq, seq, MAX_SEQ)) {
+ asoc->size_on_reasm_queue -= chk->send_size;
+ sctp_ucount_decr(asoc->cnt_on_reasm_queue);
+
+ /* Clear up any stream problem */
+ if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != SCTP_DATA_UNORDERED &&
+ SCTP_SSN_GT(chk->rec.data.stream_seq, asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered)) {
/*
- * If the stream_seq is > than the purging
- * one, we are done
+ * We must dump forward this streams
+ * sequence number if the chunk is not
+ * unordered that is being skipped. There is
+ * a chance that if the peer does not
+ * include the last fragment in its FWD-TSN
+ * we WILL have a problem here since you
+ * would have a partial chunk in queue that
+ * may not be deliverable. Also if a Partial
+ * delivery API as started the user may get
+ * a partial chunk. The next read returning
+ * a new chunk... really ugly but I see no
+ * way around it! Maybe a notify??
*/
- break;
+ asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered = chk->rec.data.stream_seq;
}
- chk = at;
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
+ }
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
+ } else if (SCTP_SSN_GT(chk->rec.data.stream_seq, seq)) {
+ /*
+ * If the stream_seq is > than the purging one, we
+ * are done
+ */
+ break;
}
}
}
@@ -5506,17 +5347,6 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
struct sctp_forward_tsn_chunk *fwd,
int *abort_flag, struct mbuf *m, int offset)
{
- /*
- * ISSUES that MUST be fixed for ECN! When we are the sender of the
- * forward TSN, when the SACK comes back that acknowledges the
- * FWD-TSN we must reset the NONCE sum to match correctly. This will
- * get quite tricky since we may have sent more data interveneing
- * and must carefully account for what the SACK says on the nonce
- * and any gaps that are reported. This work will NOT be done here,
- * but I note it here since it is really related to PR-SCTP and
- * FWD-TSN's
- */
-
/* The pr-sctp fwd tsn */
/*
* here we will perform all the data receiver side steps for
@@ -5531,13 +5361,12 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
*/
struct sctp_association *asoc;
uint32_t new_cum_tsn, gap;
- unsigned int i, fwd_sz, cumack_set_flag, m_size;
+ unsigned int i, fwd_sz, m_size;
uint32_t str_seq;
struct sctp_stream_in *strm;
- struct sctp_tmit_chunk *chk, *at;
+ struct sctp_tmit_chunk *chk, *nchk;
struct sctp_queued_to_read *ctl, *sv;
- cumack_set_flag = 0;
asoc = &stcb->asoc;
if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct sctp_forward_tsn_chunk)) {
SCTPDBG(SCTP_DEBUG_INDATA1,
@@ -5550,8 +5379,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
/*************************************************************/
new_cum_tsn = ntohl(fwd->new_cumulative_tsn);
- if (compare_with_wrap(asoc->cumulative_tsn, new_cum_tsn, MAX_TSN) ||
- asoc->cumulative_tsn == new_cum_tsn) {
+ if (SCTP_TSN_GE(asoc->cumulative_tsn, new_cum_tsn)) {
/* Already got there ... */
return;
}
@@ -5589,8 +5417,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
*ippp = new_cum_tsn;
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_33;
- sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
return;
}
SCTP_STAT_INCR(sctps_fwdtsn_map_over);
@@ -5605,14 +5432,13 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
}
- asoc->last_echo_tsn = asoc->highest_tsn_inside_map;
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
for (i = 0; i <= gap; i++) {
if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, i) &&
!SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, i)) {
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i);
- if (compare_with_wrap(asoc->mapping_array_base_tsn + i, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->mapping_array_base_tsn + i, asoc->highest_tsn_inside_nr_map)) {
asoc->highest_tsn_inside_nr_map = asoc->mapping_array_base_tsn + i;
}
}
@@ -5628,77 +5454,58 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
if (asoc->fragmented_delivery_inprogress) {
sctp_service_reassembly(stcb, asoc);
}
- if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
- /* For each one on here see if we need to toss it */
- /*
- * For now large messages held on the reasmqueue that are
- * complete will be tossed too. We could in theory do more
- * work to spin through and stop after dumping one msg aka
- * seeing the start of a new msg at the head, and call the
- * delivery function... to see if it can be delivered... But
- * for now we just dump everything on the queue.
- */
- chk = TAILQ_FIRST(&asoc->reasmqueue);
- while (chk) {
- at = TAILQ_NEXT(chk, sctp_next);
- if ((compare_with_wrap(new_cum_tsn,
- chk->rec.data.TSN_seq, MAX_TSN)) ||
- (new_cum_tsn == chk->rec.data.TSN_seq)) {
- /* It needs to be tossed */
- TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
- if (compare_with_wrap(chk->rec.data.TSN_seq,
- asoc->tsn_last_delivered, MAX_TSN)) {
- asoc->tsn_last_delivered =
- chk->rec.data.TSN_seq;
- asoc->str_of_pdapi =
- chk->rec.data.stream_number;
- asoc->ssn_of_pdapi =
- chk->rec.data.stream_seq;
- asoc->fragment_flags =
- chk->rec.data.rcv_flags;
- }
- asoc->size_on_reasm_queue -= chk->send_size;
- sctp_ucount_decr(asoc->cnt_on_reasm_queue);
-
- /* Clear up any stream problem */
- if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
- SCTP_DATA_UNORDERED &&
- (compare_with_wrap(chk->rec.data.stream_seq,
- asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered,
- MAX_SEQ))) {
- /*
- * We must dump forward this streams
- * sequence number if the chunk is
- * not unordered that is being
- * skipped. There is a chance that
- * if the peer does not include the
- * last fragment in its FWD-TSN we
- * WILL have a problem here since
- * you would have a partial chunk in
- * queue that may not be
- * deliverable. Also if a Partial
- * delivery API as started the user
- * may get a partial chunk. The next
- * read returning a new chunk...
- * really ugly but I see no way
- * around it! Maybe a notify??
- */
- asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered =
- chk->rec.data.stream_seq;
- }
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
- sctp_free_a_chunk(stcb, chk);
- } else {
+ /* For each one on here see if we need to toss it */
+ /*
+ * For now large messages held on the reasmqueue that are complete
+ * will be tossed too. We could in theory do more work to spin
+ * through and stop after dumping one msg aka seeing the start of a
+ * new msg at the head, and call the delivery function... to see if
+ * it can be delivered... But for now we just dump everything on the
+ * queue.
+ */
+ TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
+ if (SCTP_TSN_GE(new_cum_tsn, chk->rec.data.TSN_seq)) {
+ /* It needs to be tossed */
+ TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
+ if (SCTP_TSN_GT(chk->rec.data.TSN_seq, asoc->tsn_last_delivered)) {
+ asoc->tsn_last_delivered = chk->rec.data.TSN_seq;
+ asoc->str_of_pdapi = chk->rec.data.stream_number;
+ asoc->ssn_of_pdapi = chk->rec.data.stream_seq;
+ asoc->fragment_flags = chk->rec.data.rcv_flags;
+ }
+ asoc->size_on_reasm_queue -= chk->send_size;
+ sctp_ucount_decr(asoc->cnt_on_reasm_queue);
+
+ /* Clear up any stream problem */
+ if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != SCTP_DATA_UNORDERED &&
+ SCTP_SSN_GT(chk->rec.data.stream_seq, asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered)) {
/*
- * Ok we have gone beyond the end of the
- * fwd-tsn's mark.
+ * We must dump forward this streams
+ * sequence number if the chunk is not
+ * unordered that is being skipped. There is
+ * a chance that if the peer does not
+ * include the last fragment in its FWD-TSN
+ * we WILL have a problem here since you
+ * would have a partial chunk in queue that
+ * may not be deliverable. Also if a Partial
+ * delivery API as started the user may get
+ * a partial chunk. The next read returning
+ * a new chunk... really ugly but I see no
+ * way around it! Maybe a notify??
*/
- break;
+ asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered = chk->rec.data.stream_seq;
+ }
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
- chk = at;
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
+ } else {
+ /*
+ * Ok we have gone beyond the end of the fwd-tsn's
+ * mark.
+ */
+ break;
}
}
/*******************************************************/
@@ -5769,17 +5576,15 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
stcb->asoc.control_pdapi = sv;
break;
} else if ((ctl->sinfo_stream == stseq->stream) &&
- (compare_with_wrap(ctl->sinfo_ssn, stseq->sequence, MAX_SEQ))) {
+ SCTP_SSN_GT(ctl->sinfo_ssn, stseq->sequence)) {
/* We are past our victim SSN */
break;
}
}
strm = &asoc->strmin[stseq->stream];
- if (compare_with_wrap(stseq->sequence,
- strm->last_sequence_delivered, MAX_SEQ)) {
+ if (SCTP_SSN_GT(stseq->sequence, strm->last_sequence_delivered)) {
/* Update the sequence number */
- strm->last_sequence_delivered =
- stseq->sequence;
+ strm->last_sequence_delivered = stseq->sequence;
}
/* now kick the stream the new way */
/* sa_ignore NO_NULL_CHK */
diff --git a/freebsd/sys/netinet/sctp_indata.h b/freebsd/sys/netinet/sctp_indata.h
index 79978a5c..5eaa1f4b 100644
--- a/freebsd/sys/netinet/sctp_indata.h
+++ b/freebsd/sys/netinet/sctp_indata.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,13 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_indata.h,v 1.9 2005/03/06 16:04:17 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_indata_h__
-#define __sctp_indata_h__
+#ifndef _NETINET_SCTP_INDATA_H_
+#define _NETINET_SCTP_INDATA_H_
#if defined(_KERNEL) || defined(__Userspace__)
@@ -81,11 +81,6 @@ struct mbuf *
sctp_build_ctl_nchunk(struct sctp_inpcb *inp,
struct sctp_sndrcvinfo *sinfo);
-char *
-sctp_build_ctl_cchunk(struct sctp_inpcb *inp,
- int *control_len,
- struct sctp_sndrcvinfo *sinfo);
-
void sctp_set_rwnd(struct sctp_tcb *, struct sctp_association *);
uint32_t
@@ -93,14 +88,14 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc);
void
sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
- uint32_t rwnd, int nonce_sum_flag, int *abort_now);
+ uint32_t rwnd, int *abort_now, int ecne_seen);
void
sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
- struct sctp_tcb *stcb, struct sctp_nets *net_from,
+ struct sctp_tcb *stcb,
uint16_t num_seg, uint16_t num_nr_seg, uint16_t num_dup,
int *abort_now, uint8_t flags,
- uint32_t cum_ack, uint32_t rwnd);
+ uint32_t cum_ack, uint32_t rwnd, int ecne_seen);
/* draft-ietf-tsvwg-usctp */
void
@@ -113,17 +108,20 @@ struct sctp_tmit_chunk *
void sctp_service_queues(struct sctp_tcb *, struct sctp_association *);
void
-sctp_update_acked(struct sctp_tcb *, struct sctp_shutdown_chunk *,
- struct sctp_nets *, int *);
+ sctp_update_acked(struct sctp_tcb *, struct sctp_shutdown_chunk *, int *);
int
-sctp_process_data(struct mbuf **, int, int *, int, struct sctphdr *,
+sctp_process_data(struct mbuf **, int, int *, int,
+ struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *,
struct sctp_inpcb *, struct sctp_tcb *,
- struct sctp_nets *, uint32_t *);
+ struct sctp_nets *, uint32_t *,
+ uint8_t, uint32_t,
+ uint32_t, uint16_t);
void sctp_slide_mapping_arrays(struct sctp_tcb *stcb);
-void sctp_sack_check(struct sctp_tcb *, int, int *);
+void sctp_sack_check(struct sctp_tcb *, int);
#endif
#endif
diff --git a/freebsd/sys/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c
index 965bec86..817a95f7 100644
--- a/freebsd/sys/netinet/sctp_input.c
+++ b/freebsd/sys/netinet/sctp_input.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,8 +32,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_input.c,v 1.27 2005/03/06 16:04:17 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_timer.h>
#include <netinet/sctp_crc32.h>
#include <netinet/udp.h>
+#include <sys/smp.h>
@@ -81,61 +82,38 @@ sctp_stop_all_cookie_timers(struct sctp_tcb *stcb)
/* INIT handler */
static void
-sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
- struct sctp_init_chunk *cp, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net, int *abort_no_unlock, uint32_t vrf_id, uint16_t port)
+sctp_handle_init(struct mbuf *m, int iphlen, int offset,
+ struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
+ struct sctp_init_chunk *cp, struct sctp_inpcb *inp,
+ struct sctp_tcb *stcb, int *abort_no_unlock,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port)
{
struct sctp_init *init;
struct mbuf *op_err;
- uint32_t init_limit;
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n",
- stcb);
+ (void *)stcb);
if (stcb == NULL) {
SCTP_INP_RLOCK(inp);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
- goto outnow;
- }
- }
- op_err = NULL;
- init = &cp->init;
- /* First are we accepting? */
- if ((inp->sctp_socket->so_qlimit == 0) && (stcb == NULL)) {
- SCTPDBG(SCTP_DEBUG_INPUT2,
- "sctp_handle_init: Abort, so_qlimit:%d\n",
- inp->sctp_socket->so_qlimit);
- /*
- * FIX ME ?? What about TCP model and we have a
- * match/restart case? Actually no fix is needed. the lookup
- * will always find the existing assoc so stcb would not be
- * NULL. It may be questionable to do this since we COULD
- * just send back the INIT-ACK and hope that the app did
- * accept()'s by the time the COOKIE was sent. But there is
- * a price to pay for COOKIE generation and I don't want to
- * pay it on the chance that the app will actually do some
- * accepts(). The App just looses and should NOT be in this
- * state :-)
- */
- sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
- vrf_id, port);
- if (stcb)
- *abort_no_unlock = 1;
- goto outnow;
}
+ /* validate length */
if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) {
- /* Invalid length */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
+ sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
+ use_mflowid, mflowid,
vrf_id, port);
if (stcb)
*abort_no_unlock = 1;
goto outnow;
}
/* validate parameters */
+ init = &cp->init;
if (init->initiate_tag == 0) {
/* protocol error... send abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
+ sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
+ use_mflowid, mflowid,
vrf_id, port);
if (stcb)
*abort_no_unlock = 1;
@@ -144,7 +122,8 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) {
/* invalid parameter... send abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
+ sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
+ use_mflowid, mflowid,
vrf_id, port);
if (stcb)
*abort_no_unlock = 1;
@@ -153,7 +132,8 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
if (init->num_inbound_streams == 0) {
/* protocol error... send abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
+ sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
+ use_mflowid, mflowid,
vrf_id, port);
if (stcb)
*abort_no_unlock = 1;
@@ -162,25 +142,64 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
if (init->num_outbound_streams == 0) {
/* protocol error... send abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
+ sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
+ use_mflowid, mflowid,
vrf_id, port);
if (stcb)
*abort_no_unlock = 1;
goto outnow;
}
- init_limit = offset + ntohs(cp->ch.chunk_length);
if (sctp_validate_init_auth_params(m, offset + sizeof(*cp),
- init_limit)) {
+ offset + ntohs(cp->ch.chunk_length))) {
/* auth parameter(s) error... send abort */
- sctp_abort_association(inp, stcb, m, iphlen, sh, NULL, vrf_id, port);
+ sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, NULL,
+ use_mflowid, mflowid,
+ vrf_id, port);
if (stcb)
*abort_no_unlock = 1;
goto outnow;
}
- /* send an INIT-ACK w/cookie */
- SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n");
- sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, sh, cp, vrf_id, port,
- ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED));
+ /*
+ * We are only accepting if we have a socket with positive
+ * so_qlimit.
+ */
+ if ((stcb == NULL) &&
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
+ (inp->sctp_socket == NULL) ||
+ (inp->sctp_socket->so_qlimit == 0))) {
+ /*
+ * FIX ME ?? What about TCP model and we have a
+ * match/restart case? Actually no fix is needed. the lookup
+ * will always find the existing assoc so stcb would not be
+ * NULL. It may be questionable to do this since we COULD
+ * just send back the INIT-ACK and hope that the app did
+ * accept()'s by the time the COOKIE was sent. But there is
+ * a price to pay for COOKIE generation and I don't want to
+ * pay it on the chance that the app will actually do some
+ * accepts(). The App just looses and should NOT be in this
+ * state :-)
+ */
+ if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) {
+ sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL,
+ use_mflowid, mflowid,
+ vrf_id, port);
+ }
+ goto outnow;
+ }
+ if ((stcb != NULL) &&
+ (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n");
+ sctp_send_shutdown_ack(stcb, NULL);
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
+ } else {
+ SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n");
+ sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, src, dst,
+ sh, cp,
+ use_mflowid, mflowid,
+ vrf_id, port,
+ ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED));
+ }
outnow:
if (stcb == NULL) {
SCTP_INP_RUNLOCK(inp);
@@ -192,11 +211,15 @@ outnow:
*/
int
-sctp_is_there_unsent_data(struct sctp_tcb *stcb)
+sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+ SCTP_UNUSED
+#endif
+)
{
int unsent_data = 0;
+ unsigned int i;
struct sctp_stream_queue_pending *sp;
- struct sctp_stream_out *strq;
struct sctp_association *asoc;
/*
@@ -207,12 +230,11 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb)
*/
asoc = &stcb->asoc;
SCTP_TCB_SEND_LOCK(stcb);
- if (!TAILQ_EMPTY(&asoc->out_wheel)) {
+ if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
/* Check to see if some data queued */
- TAILQ_FOREACH(strq, &asoc->out_wheel, next_spoke) {
- is_there_another:
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
/* sa_ignore FREED_MEMORY */
- sp = TAILQ_FIRST(&strq->outqueue);
+ sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue);
if (sp == NULL) {
continue;
}
@@ -233,7 +255,7 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb)
sp->put_last_out);
}
atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1);
- TAILQ_REMOVE(&strq->outqueue, sp, next);
+ TAILQ_REMOVE(&stcb->asoc.strmout[i].outqueue, sp, next);
if (sp->net) {
sctp_free_remote_addr(sp->net);
sp->net = NULL;
@@ -242,11 +264,10 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb)
sctp_m_freem(sp->data);
sp->data = NULL;
}
- sctp_free_a_strmoq(stcb, sp);
- goto is_there_another;
+ sctp_free_a_strmoq(stcb, sp, so_locked);
} else {
unsent_data++;
- continue;
+ break;
}
}
}
@@ -255,8 +276,7 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb)
}
static int
-sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
- struct sctp_nets *net)
+sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
{
struct sctp_init *init;
struct sctp_association *asoc;
@@ -268,11 +288,13 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
/* save off parameters */
asoc->peer_vtag = ntohl(init->initiate_tag);
asoc->peers_rwnd = ntohl(init->a_rwnd);
+ /* init tsn's */
+ asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1;
+
if (!TAILQ_EMPTY(&asoc->nets)) {
/* update any ssthresh's that may have a default */
TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) {
lnet->ssthresh = asoc->peers_rwnd;
-
if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION);
}
@@ -282,43 +304,43 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) {
unsigned int newcnt;
struct sctp_stream_out *outs;
- struct sctp_stream_queue_pending *sp;
- struct sctp_tmit_chunk *chk, *chk_next;
+ struct sctp_stream_queue_pending *sp, *nsp;
+ struct sctp_tmit_chunk *chk, *nchk;
/* abandon the upper streams */
newcnt = ntohs(init->num_inbound_streams);
- if (!TAILQ_EMPTY(&asoc->send_queue)) {
- chk = TAILQ_FIRST(&asoc->send_queue);
- while (chk) {
- chk_next = TAILQ_NEXT(chk, sctp_next);
- if (chk->rec.data.stream_number >= newcnt) {
- TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
- asoc->send_queue_cnt--;
- if (chk->data != NULL) {
- sctp_free_bufspace(stcb, asoc, chk, 1);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_NOT_LOCKED);
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
+ TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
+ if (chk->rec.data.stream_number >= newcnt) {
+ TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
+ asoc->send_queue_cnt--;
+ if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
+#endif
+ }
+ if (chk->data != NULL) {
+ sctp_free_bufspace(stcb, asoc, chk, 1);
+ sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb,
+ 0, chk, SCTP_SO_NOT_LOCKED);
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
- sctp_free_a_chunk(stcb, chk);
- /* sa_ignore FREED_MEMORY */
}
- chk = chk_next;
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
+ /* sa_ignore FREED_MEMORY */
}
}
if (asoc->strmout) {
for (i = newcnt; i < asoc->pre_open_streams; i++) {
outs = &asoc->strmout[i];
- sp = TAILQ_FIRST(&outs->outqueue);
- while (sp) {
+ TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
TAILQ_REMOVE(&outs->outqueue, sp, next);
asoc->stream_queue_cnt--;
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL,
- stcb, SCTP_NOTIFY_DATAGRAM_UNSENT,
- sp, SCTP_SO_NOT_LOCKED);
+ stcb, 0, sp, SCTP_SO_NOT_LOCKED);
if (sp->data) {
sctp_m_freem(sp->data);
sp->data = NULL;
@@ -328,9 +350,8 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
sp->net = NULL;
}
/* Free the chunk */
- sctp_free_a_strmoq(stcb, sp);
+ sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED);
/* sa_ignore FREED_MEMORY */
- sp = TAILQ_FIRST(&outs->outqueue);
}
}
}
@@ -339,8 +360,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
}
SCTP_TCB_SEND_UNLOCK(stcb);
asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams;
- /* init tsn's */
- asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1;
+
/* EY - nr_sack: initialize highest tsn in nr_mapping_array */
asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
@@ -351,24 +371,22 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
asoc->mapping_array_base_tsn = ntohl(init->initial_tsn);
asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in;
- asoc->last_echo_tsn = asoc->asconf_seq_in;
+
asoc->advanced_peer_ack_point = asoc->last_acked_seq;
/* open the requested streams */
if (asoc->strmin != NULL) {
/* Free the old ones */
- struct sctp_queued_to_read *ctl;
+ struct sctp_queued_to_read *ctl, *nctl;
for (i = 0; i < asoc->streamincnt; i++) {
- ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue);
- while (ctl) {
+ TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) {
TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next);
sctp_free_remote_addr(ctl->whoFrom);
ctl->whoFrom = NULL;
sctp_m_freem(ctl->data);
ctl->data = NULL;
sctp_free_a_readq(stcb, ctl);
- ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue);
}
}
SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
@@ -413,8 +431,11 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
*/
static int
sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
- struct sctphdr *sh, struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
- struct sctp_nets *net, int *abort_no_unlock, uint32_t vrf_id)
+ struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
+ struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
+ struct sctp_nets *net, int *abort_no_unlock,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id)
{
struct sctp_association *asoc;
struct mbuf *op_err;
@@ -431,40 +452,40 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
&abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly);
if (abort_flag) {
/* Send an abort and notify peer */
- sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_CAUSE_PROTOCOL_VIOLATION, op_err, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
*abort_no_unlock = 1;
return (-1);
}
asoc = &stcb->asoc;
asoc->peer_supports_nat = (uint8_t) nat_friendly;
/* process the peer's parameters in the INIT-ACK */
- retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb, net);
+ retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb);
if (retval < 0) {
return (retval);
}
initack_limit = offset + ntohs(cp->ch.chunk_length);
/* load all addresses */
- if ((retval = sctp_load_addresses_from_init(stcb, m, iphlen,
- (offset + sizeof(struct sctp_init_chunk)), initack_limit, sh,
- NULL))) {
+ if ((retval = sctp_load_addresses_from_init(stcb, m,
+ (offset + sizeof(struct sctp_init_chunk)), initack_limit,
+ src, dst, NULL))) {
/* Huh, we should abort */
SCTPDBG(SCTP_DEBUG_INPUT1,
"Load addresses from INIT causes an abort %d\n",
retval);
- sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
- NULL, 0, net->port);
+ sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
+ src, dst, sh, NULL,
+ use_mflowid, mflowid,
+ vrf_id, net->port);
*abort_no_unlock = 1;
return (-1);
}
/* if the peer doesn't support asconf, flush the asconf queue */
if (asoc->peer_supports_asconf == 0) {
- struct sctp_asconf_addr *aparam;
+ struct sctp_asconf_addr *param, *nparam;
- while (!TAILQ_EMPTY(&asoc->asconf_queue)) {
- /* sa_ignore FREED_MEMORY */
- aparam = TAILQ_FIRST(&asoc->asconf_queue);
- TAILQ_REMOVE(&asoc->asconf_queue, aparam, next);
- SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
+ TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) {
+ TAILQ_REMOVE(&asoc->asconf_queue, param, next);
+ SCTP_FREE(param, SCTP_M_ASC_ADDR);
}
}
stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
@@ -495,7 +516,8 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4);
/* calculate the RTO */
- net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy);
+ net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy,
+ SCTP_RTT_FROM_NON_DATA);
retval = sctp_send_cookie_echo(m, offset, stcb, net);
if (retval < 0) {
@@ -527,7 +549,9 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
mp->resv = 0;
}
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
- sh, op_err, 0, net->port);
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, net->port);
*abort_no_unlock = 1;
}
return (retval);
@@ -540,38 +564,58 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
struct sctp_tcb *stcb, struct sctp_nets *net)
{
struct sockaddr_storage store;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
struct sctp_nets *r_net, *f_net;
struct timeval tv;
int req_prim = 0;
+ uint16_t old_error_counter;
+
+#ifdef INET
+ struct sockaddr_in *sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+
+#endif
if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) {
/* Invalid length */
return;
}
- sin = (struct sockaddr_in *)&store;
- sin6 = (struct sockaddr_in6 *)&store;
-
memset(&store, 0, sizeof(store));
- if (cp->heartbeat.hb_info.addr_family == AF_INET &&
- cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
- sin->sin_family = cp->heartbeat.hb_info.addr_family;
- sin->sin_len = cp->heartbeat.hb_info.addr_len;
- sin->sin_port = stcb->rport;
- memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address,
- sizeof(sin->sin_addr));
- } else if (cp->heartbeat.hb_info.addr_family == AF_INET6 &&
- cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
- sin6->sin6_family = cp->heartbeat.hb_info.addr_family;
- sin6->sin6_len = cp->heartbeat.hb_info.addr_len;
- sin6->sin6_port = stcb->rport;
- memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address,
- sizeof(sin6->sin6_addr));
- } else {
+ switch (cp->heartbeat.hb_info.addr_family) {
+#ifdef INET
+ case AF_INET:
+ if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
+ sin = (struct sockaddr_in *)&store;
+ sin->sin_family = cp->heartbeat.hb_info.addr_family;
+ sin->sin_len = cp->heartbeat.hb_info.addr_len;
+ sin->sin_port = stcb->rport;
+ memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address,
+ sizeof(sin->sin_addr));
+ } else {
+ return;
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
+ sin6 = (struct sockaddr_in6 *)&store;
+ sin6->sin6_family = cp->heartbeat.hb_info.addr_family;
+ sin6->sin6_len = cp->heartbeat.hb_info.addr_len;
+ sin6->sin6_port = stcb->rport;
+ memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address,
+ sizeof(sin6->sin6_addr));
+ } else {
+ return;
+ }
+ break;
+#endif
+ default:
return;
}
- r_net = sctp_findnet(stcb, (struct sockaddr *)sin);
+ r_net = sctp_findnet(stcb, (struct sockaddr *)&store);
if (r_net == NULL) {
SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n");
return;
@@ -586,7 +630,6 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) {
stcb->asoc.primary_destination = r_net;
- r_net->dest_state &= ~SCTP_ADDR_WAS_PRIMARY;
r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY;
f_net = TAILQ_FIRST(&stcb->asoc.nets);
if (f_net != r_net) {
@@ -603,43 +646,37 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
}
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net);
}
+ old_error_counter = r_net->error_count;
r_net->error_count = 0;
r_net->hb_responded = 1;
tv.tv_sec = cp->heartbeat.hb_info.time_value_1;
tv.tv_usec = cp->heartbeat.hb_info.time_value_2;
- if (r_net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
- r_net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
+ /* Now lets do a RTO with this */
+ r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy,
+ SCTP_RTT_FROM_NON_DATA);
+ if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) {
r_net->dest_state |= SCTP_ADDR_REACHABLE;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
- SCTP_HEARTBEAT_SUCCESS, (void *)r_net, SCTP_SO_NOT_LOCKED);
- /* now was it the primary? if so restore */
- if (r_net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
- (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, r_net);
- }
+ 0, (void *)r_net, SCTP_SO_NOT_LOCKED);
}
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination is in PF state,
- * set the destination to active state and set the cwnd to one or
- * two MTU's based on whether PF1 or PF2 is being used. If a T3
- * timer is running, for the destination, stop the timer because a
- * PF-heartbeat was received.
- */
- if ((stcb->asoc.sctp_cmt_on_off == 1) &&
- (stcb->asoc.sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
- sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
- stcb, net,
- SCTP_FROM_SCTP_INPUT + SCTP_LOC_5);
- }
- net->dest_state &= ~SCTP_ADDR_PF;
- net->cwnd = net->mtu * stcb->asoc.sctp_cmt_pf;
- SCTPDBG(SCTP_DEBUG_INPUT1, "Destination %p moved from PF to reachable with cwnd %d.\n",
- net, net->cwnd);
+ if (r_net->dest_state & SCTP_ADDR_PF) {
+ r_net->dest_state &= ~SCTP_ADDR_PF;
+ stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
+ }
+ if (old_error_counter > 0) {
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net);
+ }
+ if (r_net == stcb->asoc.primary_destination) {
+ if (stcb->asoc.alternate) {
+ /* release the alternate, primary is good */
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
}
- /* Now lets do a RTO with this */
- r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy);
/* Mobility adaptation */
if (req_prim) {
if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
@@ -730,61 +767,51 @@ sctp_handle_nat_missing_state(struct sctp_tcb *stcb,
static void
-sctp_handle_abort(struct sctp_abort_chunk *cp,
+sctp_handle_abort(struct sctp_abort_chunk *abort,
struct sctp_tcb *stcb, struct sctp_nets *net)
{
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
uint16_t len;
+ uint16_t error;
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n");
if (stcb == NULL)
return;
- len = ntohs(cp->ch.chunk_length);
+ len = ntohs(abort->ch.chunk_length);
if (len > sizeof(struct sctp_chunkhdr)) {
/*
* Need to check the cause codes for our two magic nat
* aborts which don't kill the assoc necessarily.
*/
- struct sctp_abort_chunk *cpnext;
struct sctp_missing_nat_state *natc;
- uint16_t cause;
- cpnext = cp;
- cpnext++;
- natc = (struct sctp_missing_nat_state *)cpnext;
- cause = ntohs(natc->cause);
- if (cause == SCTP_CAUSE_NAT_COLLIDING_STATE) {
+ natc = (struct sctp_missing_nat_state *)(abort + 1);
+ error = ntohs(natc->cause);
+ if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) {
SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n",
- cp->ch.chunk_flags);
+ abort->ch.chunk_flags);
if (sctp_handle_nat_colliding_state(stcb)) {
return;
}
- } else if (cause == SCTP_CAUSE_NAT_MISSING_STATE) {
+ } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) {
SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n",
- cp->ch.chunk_flags);
+ abort->ch.chunk_flags);
if (sctp_handle_nat_missing_state(stcb, net)) {
return;
}
}
+ } else {
+ error = 0;
}
/* stop any receive timers */
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
/* notify user of the abort and clean up... */
- sctp_abort_notification(stcb, 0, SCTP_SO_NOT_LOCKED);
+ sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED);
/* free the tcb */
-#if defined(SCTP_PANIC_ON_ABORT)
- printf("stcb:%p state:%d rport:%d net:%p\n",
- stcb, stcb->asoc.state, stcb->rport, net);
- if (!(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
- panic("Received an ABORT");
- } else {
- printf("No panic its in state %x closed\n", stcb->asoc.state);
- }
-#endif
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@@ -793,7 +820,7 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
#ifdef SCTP_ASOCLOG_OF_TSNS
sctp_print_out_track_log(stcb);
#endif
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -804,20 +831,49 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n");
}
static void
+sctp_start_net_timers(struct sctp_tcb *stcb)
+{
+ uint32_t cnt_hb_sent;
+ struct sctp_nets *net;
+
+ cnt_hb_sent = 0;
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ /*
+ * For each network start: 1) A pmtu timer. 2) A HB timer 3)
+ * If the dest in unconfirmed send a hb as well if under
+ * max_hb_burst have been sent.
+ */
+ sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
+ (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) {
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
+ cnt_hb_sent++;
+ }
+ }
+ if (cnt_hb_sent) {
+ sctp_chunk_output(stcb->sctp_ep, stcb,
+ SCTP_OUTPUT_FROM_COOKIE_ACK,
+ SCTP_SO_NOT_LOCKED);
+ }
+}
+
+
+static void
sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag)
{
struct sctp_association *asoc;
int some_on_streamwheel;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
@@ -835,7 +891,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
/* Shutdown NOT the expected size */
return;
} else {
- sctp_update_acked(stcb, cp, net, abort_flag);
+ sctp_update_acked(stcb, cp, abort_flag);
if (*abort_flag) {
return;
}
@@ -849,7 +905,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
asoc->control_pdapi->pdapi_aborted = 1;
asoc->control_pdapi = NULL;
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -863,7 +919,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
}
#endif
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
@@ -892,7 +948,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
}
/* Now is there unsent data on a stream somewhere? */
- some_on_streamwheel = sctp_is_there_unsent_data(stcb);
+ some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED);
if (!TAILQ_EMPTY(&asoc->send_queue) ||
!TAILQ_EMPTY(&asoc->sent_queue) ||
@@ -902,7 +958,6 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
} else {
/* no outstanding data to send, so move on... */
/* send SHUTDOWN-ACK */
- sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
/* move to SHUTDOWN-ACK-SENT state */
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@@ -911,19 +966,20 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_stop_timers_for_shutdown(stcb);
+ sctp_send_shutdown_ack(stcb, net);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep,
stcb, net);
}
}
static void
-sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
+sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
struct sctp_association *asoc;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
@@ -957,7 +1013,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
asoc->control_pdapi->pdapi_aborted = 1;
asoc->control_pdapi = NULL;
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
@@ -970,15 +1026,15 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
}
#endif
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/* are the queues empty? */
if (!TAILQ_EMPTY(&asoc->send_queue) ||
!TAILQ_EMPTY(&asoc->sent_queue) ||
- !TAILQ_EMPTY(&asoc->out_wheel)) {
- sctp_report_all_outbound(stcb, 0, SCTP_SO_NOT_LOCKED);
+ !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
+ sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED);
}
/* stop the timer */
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9);
@@ -986,16 +1042,15 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
sctp_send_shutdown_complete(stcb, net, 0);
/* notify upper layer protocol */
if (stcb->sctp_socket) {
- sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- /* Set the connected flag to disconnected */
- stcb->sctp_ep->sctp_socket->so_snd.sb_cc = 0;
+ stcb->sctp_socket->so_snd.sb_cc = 0;
}
+ sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
}
SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
/* free the TCB but first save off the ep */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
@@ -1004,7 +1059,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
#endif
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_10);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
@@ -1059,11 +1114,6 @@ sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
case SCTP_HAS_NAT_SUPPORT:
stcb->asoc.peer_supports_nat = 0;
break;
- case SCTP_ECN_NONCE_SUPPORTED:
- stcb->asoc.peer_supports_ecn_nonce = 0;
- stcb->asoc.ecn_nonce_allowed = 0;
- stcb->asoc.ecn_allowed = 0;
- break;
case SCTP_ADD_IP_ADDRESS:
case SCTP_DEL_IP_ADDRESS:
case SCTP_SET_PRIM_ADDR:
@@ -1090,12 +1140,12 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
{
int chklen;
struct sctp_paramhdr *phdr;
- uint16_t error_type;
+ uint16_t error, error_type;
uint16_t error_len;
struct sctp_association *asoc;
int adjust;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
@@ -1105,6 +1155,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
phdr = (struct sctp_paramhdr *)((caddr_t)ch +
sizeof(struct sctp_chunkhdr));
chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr);
+ error = 0;
while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) {
/* Process an Error Cause */
error_type = ntohs(phdr->param_type);
@@ -1115,6 +1166,10 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
chklen, error_len);
return (0);
}
+ if (error == 0) {
+ /* report the first error cause */
+ error = error_type;
+ }
switch (error_type) {
case SCTP_CAUSE_INVALID_STREAM:
case SCTP_CAUSE_MISSING_PARAM:
@@ -1151,9 +1206,9 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
asoc->stale_cookie_count++;
if (asoc->stale_cookie_count >
asoc->max_init_times) {
- sctp_abort_notification(stcb, 0, SCTP_SO_NOT_LOCKED);
+ sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
/* now free the asoc */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -1163,7 +1218,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
#endif
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
return (-1);
@@ -1231,13 +1286,17 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
chklen -= adjust;
phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust);
}
+ sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED);
return (0);
}
static int
sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
- struct sctphdr *sh, struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
- struct sctp_nets *net, int *abort_no_unlock, uint32_t vrf_id)
+ struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
+ struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
+ struct sctp_nets *net, int *abort_no_unlock,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id)
{
struct sctp_init_ack *init_ack;
struct mbuf *op_err;
@@ -1253,8 +1312,10 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) {
/* Invalid length */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
- op_err, 0, net->port);
+ sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, net->port);
*abort_no_unlock = 1;
return (-1);
}
@@ -1263,32 +1324,40 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
if (init_ack->initiate_tag == 0) {
/* protocol error... send an abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
- op_err, 0, net->port);
+ sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, net->port);
*abort_no_unlock = 1;
return (-1);
}
if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) {
/* protocol error... send an abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
- op_err, 0, net->port);
+ sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, net->port);
*abort_no_unlock = 1;
return (-1);
}
if (init_ack->num_inbound_streams == 0) {
/* protocol error... send an abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
- op_err, 0, net->port);
+ sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, net->port);
*abort_no_unlock = 1;
return (-1);
}
if (init_ack->num_outbound_streams == 0) {
/* protocol error... send an abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
- sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
- op_err, 0, net->port);
+ sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, net->port);
*abort_no_unlock = 1;
return (-1);
}
@@ -1310,8 +1379,10 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED);
}
- if (sctp_process_init_ack(m, iphlen, offset, sh, cp, stcb,
- net, abort_no_unlock, vrf_id) < 0) {
+ if (sctp_process_init_ack(m, iphlen, offset, src, dst, sh, cp, stcb,
+ net, abort_no_unlock,
+ use_mflowid, mflowid,
+ vrf_id) < 0) {
/* error in parsing parameters */
return (-1);
}
@@ -1362,10 +1433,12 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
static struct sctp_tcb *
sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
+ struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
struct sctp_inpcb *inp, struct sctp_nets **netp,
struct sockaddr *init_src, int *notification,
int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
+ uint8_t use_mflowid, uint32_t mflowid,
uint32_t vrf_id, uint16_t port);
@@ -1377,10 +1450,13 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
*/
static struct sctp_tcb *
sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
+ struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp,
- struct sockaddr *init_src, int *notification, sctp_assoc_t * sac_assoc_id,
- uint32_t vrf_id, int auth_skipped, uint32_t auth_offset, uint32_t auth_len, uint16_t port)
+ struct sockaddr *init_src, int *notification,
+ int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port)
{
struct sctp_association *asoc;
struct sctp_init_chunk *init_cp, init_buf;
@@ -1388,7 +1464,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
struct sctp_nets *net;
struct mbuf *op_err;
struct sctp_paramhdr *ph;
- int chk_length;
int init_offset, initack_offset, i;
int retval;
int spec_flag = 0;
@@ -1418,7 +1493,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
ph = mtod(op_err, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN);
ph->param_length = htons(sizeof(struct sctp_paramhdr));
- sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag,
+ sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
+ use_mflowid, mflowid,
vrf_id, net->port);
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 2;
@@ -1438,7 +1514,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* could not pull a INIT chunk in cookie */
return (NULL);
}
- chk_length = ntohs(init_cp->ch.chunk_length);
if (init_cp->ch.chunk_type != SCTP_INITIATION) {
return (NULL);
}
@@ -1446,7 +1521,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* find and validate the INIT-ACK chunk in the cookie (my info) the
* INIT-ACK follows the INIT chunk
*/
- initack_offset = init_offset + SCTP_SIZE32(chk_length);
+ initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length));
initack_cp = (struct sctp_init_ack_chunk *)
sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
(uint8_t *) & initack_buf);
@@ -1454,7 +1529,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* could not pull INIT-ACK chunk in cookie */
return (NULL);
}
- chk_length = ntohs(initack_cp->ch.chunk_length);
if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
return (NULL);
}
@@ -1495,7 +1569,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* the right seq no's.
*/
/* First we must process the INIT !! */
- retval = sctp_process_init(init_cp, stcb, net);
+ retval = sctp_process_init(init_cp, stcb);
if (retval < 0) {
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 3;
@@ -1522,7 +1596,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
(inp->sctp_socket->so_qlimit == 0)
) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
@@ -1534,7 +1608,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
stcb->sctp_ep->sctp_flags |=
SCTP_PCB_FLAGS_CONNECTED;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -1547,7 +1621,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
}
#endif
soisconnected(stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
@@ -1559,7 +1633,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
net->hb_responded = 1;
net->RTO = sctp_calculate_rto(stcb, asoc, net,
- &cookie->time_entered, sctp_align_unsafe_makecopy);
+ &cookie->time_entered,
+ sctp_align_unsafe_makecopy,
+ SCTP_RTT_FROM_NON_DATA);
if (stcb->asoc.sctp_autoclose_ticks &&
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) {
@@ -1580,9 +1656,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* somehow abort.. but we do have an existing asoc. This
* really should not fail.
*/
- if (sctp_load_addresses_from_init(stcb, m, iphlen,
+ if (sctp_load_addresses_from_init(stcb, m,
init_offset + sizeof(struct sctp_init_chunk),
- initack_offset, sh, init_src)) {
+ initack_offset, src, dst, init_src)) {
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 4;
return (NULL);
@@ -1643,7 +1719,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
ph = mtod(op_err, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_NAT_COLLIDING_STATE);
ph->param_length = htons(sizeof(struct sctp_paramhdr));
- sctp_send_abort(m, iphlen, sh, 0, op_err, vrf_id, port);
+ sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
return (NULL);
}
if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
@@ -1693,8 +1771,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams);
- /* Note last_cwr_tsn? where is this used? */
- asoc->last_cwr_tsn = asoc->init_seq_number - 1;
if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) {
/*
* Ok the peer probably discarded our data (if we
@@ -1718,15 +1794,15 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
}
/* process the INIT info (peer's info) */
- retval = sctp_process_init(init_cp, stcb, net);
+ retval = sctp_process_init(init_cp, stcb);
if (retval < 0) {
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 9;
return (NULL);
}
- if (sctp_load_addresses_from_init(stcb, m, iphlen,
+ if (sctp_load_addresses_from_init(stcb, m,
init_offset + sizeof(struct sctp_init_chunk),
- initack_offset, sh, init_src)) {
+ initack_offset, src, dst, init_src)) {
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 10;
return (NULL);
@@ -1738,13 +1814,13 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
(inp->sctp_socket->so_qlimit == 0)) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
stcb->sctp_ep->sctp_flags |=
SCTP_PCB_FLAGS_CONNECTED;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -1757,7 +1833,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
}
#endif
soisconnected(stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
@@ -1807,9 +1883,11 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* cookie_new code since we are allowing a duplicate
* association. I hope this works...
*/
- return (sctp_process_cookie_new(m, iphlen, offset, sh, cookie, cookie_len,
+ return (sctp_process_cookie_new(m, iphlen, offset, src, dst,
+ sh, cookie, cookie_len,
inp, netp, init_src, notification,
auth_skipped, auth_offset, auth_len,
+ use_mflowid, mflowid,
vrf_id, port));
}
/*
@@ -1821,7 +1899,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15);
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
- *sac_assoc_id = sctp_get_associd(stcb);
/* notify upper layer */
*notification = SCTP_NOTIFY_ASSOC_RESTART;
atomic_add_int(&stcb->asoc.refcnt, 1);
@@ -1850,7 +1927,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number;
asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
- asoc->last_cwr_tsn = asoc->init_seq_number - 1;
asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
asoc->str_reset_seq_in = asoc->init_seq_number;
@@ -1872,10 +1948,11 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* send up all the data */
SCTP_TCB_SEND_LOCK(stcb);
- sctp_report_all_outbound(stcb, 1, SCTP_SO_NOT_LOCKED);
+ sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_NOT_LOCKED);
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ stcb->asoc.strmout[i].chunks_on_queues = 0;
stcb->asoc.strmout[i].stream_no = i;
- stcb->asoc.strmout[i].next_sequence_sent = 0;
+ stcb->asoc.strmout[i].next_sequence_send = 0;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
}
/* process the INIT-ACK info (my info) */
@@ -1898,7 +1975,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
SCTP_INP_WUNLOCK(stcb->sctp_ep);
SCTP_INP_INFO_WUNLOCK();
- retval = sctp_process_init(init_cp, stcb, net);
+ retval = sctp_process_init(init_cp, stcb);
if (retval < 0) {
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 13;
@@ -1911,9 +1988,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
net->hb_responded = 1;
- if (sctp_load_addresses_from_init(stcb, m, iphlen,
+ if (sctp_load_addresses_from_init(stcb, m,
init_offset + sizeof(struct sctp_init_chunk),
- initack_offset, sh, init_src)) {
+ initack_offset, src, dst, init_src)) {
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 14;
@@ -1942,12 +2019,14 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* cookie-echo chunk length: length of the cookie chunk to: where the init
* was from returns a new TCB
*/
-struct sctp_tcb *
+static struct sctp_tcb *
sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
+ struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
struct sctp_inpcb *inp, struct sctp_nets **netp,
struct sockaddr *init_src, int *notification,
int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
+ uint8_t use_mflowid, uint32_t mflowid,
uint32_t vrf_id, uint16_t port)
{
struct sctp_tcb *stcb;
@@ -1955,17 +2034,21 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
struct sctp_init_ack_chunk *initack_cp, initack_buf;
struct sockaddr_storage sa_store;
struct sockaddr *initack_src = (struct sockaddr *)&sa_store;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
struct sctp_association *asoc;
- int chk_length;
int init_offset, initack_offset, initack_limit;
int retval;
int error = 0;
- uint32_t old_tag;
uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#ifdef INET
+ struct sockaddr_in *sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+
+#endif
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(inp);
@@ -1986,12 +2069,11 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
"process_cookie_new: could not pull INIT chunk hdr\n");
return (NULL);
}
- chk_length = ntohs(init_cp->ch.chunk_length);
if (init_cp->ch.chunk_type != SCTP_INITIATION) {
SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n");
return (NULL);
}
- initack_offset = init_offset + SCTP_SIZE32(chk_length);
+ initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length));
/*
* find and validate the INIT-ACK chunk in the cookie (my info) the
* INIT-ACK follows the INIT chunk
@@ -2004,7 +2086,6 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n");
return (NULL);
}
- chk_length = ntohs(initack_cp->ch.chunk_length);
if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
return (NULL);
}
@@ -2040,7 +2121,9 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
- sh, op_err, vrf_id, port);
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
return (NULL);
}
/* get the correct sctp_nets */
@@ -2049,13 +2132,13 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
asoc = &stcb->asoc;
/* get scope variables out of cookie */
- asoc->ipv4_local_scope = cookie->ipv4_scope;
- asoc->site_scope = cookie->site_scope;
- asoc->local_scope = cookie->local_scope;
- asoc->loopback_scope = cookie->loopback_scope;
+ asoc->scope.ipv4_local_scope = cookie->ipv4_scope;
+ asoc->scope.site_scope = cookie->site_scope;
+ asoc->scope.local_scope = cookie->local_scope;
+ asoc->scope.loopback_scope = cookie->loopback_scope;
- if ((asoc->ipv4_addr_legal != cookie->ipv4_addr_legal) ||
- (asoc->ipv6_addr_legal != cookie->ipv6_addr_legal)) {
+ if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) ||
+ (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal)) {
struct mbuf *op_err;
/*
@@ -2066,29 +2149,29 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
atomic_add_int(&stcb->asoc.refcnt, 1);
op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
- sh, op_err, vrf_id, port);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
/* process the INIT-ACK info (my info) */
- old_tag = asoc->my_vtag;
asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams);
asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number;
asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
- asoc->last_cwr_tsn = asoc->init_seq_number - 1;
asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
asoc->str_reset_seq_in = asoc->init_seq_number;
@@ -2096,35 +2179,35 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
/* process the INIT info (peer's info) */
if (netp)
- retval = sctp_process_init(init_cp, stcb, *netp);
+ retval = sctp_process_init(init_cp, stcb);
else
retval = 0;
if (retval < 0) {
atomic_add_int(&stcb->asoc.refcnt, 1);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
/* load all addresses */
- if (sctp_load_addresses_from_init(stcb, m, iphlen,
- init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh,
- init_src)) {
+ if (sctp_load_addresses_from_init(stcb, m,
+ init_offset + sizeof(struct sctp_init_chunk), initack_offset,
+ src, dst, init_src)) {
atomic_add_int(&stcb->asoc.refcnt, 1);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
@@ -2147,13 +2230,13 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
SCTPDBG(SCTP_DEBUG_AUTH1,
"COOKIE-ECHO: AUTH failed\n");
atomic_add_int(&stcb->asoc.refcnt, 1);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
@@ -2185,14 +2268,19 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
/* warning, we re-use sin, sin6, sa_store here! */
/* pull in local_address (our "from" address) */
- if (cookie->laddr_type == SCTP_IPV4_ADDRESS) {
+ switch (cookie->laddr_type) {
+#ifdef INET
+ case SCTP_IPV4_ADDRESS:
/* source addr is IPv4 */
sin = (struct sockaddr_in *)initack_src;
memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_addr.s_addr = cookie->laddress[0];
- } else if (cookie->laddr_type == SCTP_IPV6_ADDRESS) {
+ break;
+#endif
+#ifdef INET6
+ case SCTP_IPV6_ADDRESS:
/* source addr is IPv6 */
sin6 = (struct sockaddr_in6 *)initack_src;
memset(sin6, 0, sizeof(*sin6));
@@ -2201,15 +2289,17 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
sin6->sin6_scope_id = cookie->scope_id;
memcpy(&sin6->sin6_addr, cookie->laddress,
sizeof(sin6->sin6_addr));
- } else {
+ break;
+#endif
+ default:
atomic_add_int(&stcb->asoc.refcnt, 1);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
@@ -2230,7 +2320,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
* a bit of protection is worth having..
*/
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
@@ -2242,7 +2332,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
}
#endif
soisconnected(stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
} else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
@@ -2266,7 +2356,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
if ((netp) && (*netp)) {
(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
- &cookie->time_entered, sctp_align_unsafe_makecopy);
+ &cookie->time_entered, sctp_align_unsafe_makecopy,
+ SCTP_RTT_FROM_NON_DATA);
}
/* respond with a COOKIE-ACK */
sctp_send_cookie_ack(stcb);
@@ -2304,33 +2395,40 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
*/
static struct mbuf *
sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
+ struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp,
struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp,
int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
- struct sctp_tcb **locked_tcb, uint32_t vrf_id, uint16_t port)
+ struct sctp_tcb **locked_tcb,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port)
{
struct sctp_state_cookie *cookie;
- struct sockaddr_in6 sin6;
- struct sockaddr_in sin;
struct sctp_tcb *l_stcb = *stcb;
struct sctp_inpcb *l_inp;
struct sockaddr *to;
- sctp_assoc_t sac_restart_id;
struct sctp_pcb *ep;
struct mbuf *m_sig;
uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE];
uint8_t *sig;
uint8_t cookie_ok = 0;
- unsigned int size_of_pkt, sig_offset, cookie_offset;
+ unsigned int sig_offset, cookie_offset;
unsigned int cookie_len;
struct timeval now;
struct timeval time_expires;
- struct sockaddr_storage dest_store;
- struct sockaddr *localep_sa = (struct sockaddr *)&dest_store;
- struct ip *iph;
int notification = 0;
struct sctp_nets *netl;
int had_a_existing_tcb = 0;
+ int send_int_conf = 0;
+
+#ifdef INET
+ struct sockaddr_in sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+
+#endif
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_cookie: handling COOKIE-ECHO\n");
@@ -2338,45 +2436,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
if (inp_p == NULL) {
return (NULL);
}
- /* First get the destination address setup too. */
- iph = mtod(m, struct ip *);
- switch (iph->ip_v) {
- case IPVERSION:
- {
- /* its IPv4 */
- struct sockaddr_in *lsin;
-
- lsin = (struct sockaddr_in *)(localep_sa);
- memset(lsin, 0, sizeof(*lsin));
- lsin->sin_family = AF_INET;
- lsin->sin_len = sizeof(*lsin);
- lsin->sin_port = sh->dest_port;
- lsin->sin_addr.s_addr = iph->ip_dst.s_addr;
- size_of_pkt = SCTP_GET_IPV4_LENGTH(iph);
- break;
- }
-#ifdef INET6
- case IPV6_VERSION >> 4:
- {
- /* its IPv6 */
- struct ip6_hdr *ip6;
- struct sockaddr_in6 *lsin6;
-
- lsin6 = (struct sockaddr_in6 *)(localep_sa);
- memset(lsin6, 0, sizeof(*lsin6));
- lsin6->sin6_family = AF_INET6;
- lsin6->sin6_len = sizeof(struct sockaddr_in6);
- ip6 = mtod(m, struct ip6_hdr *);
- lsin6->sin6_port = sh->dest_port;
- lsin6->sin6_addr = ip6->ip6_dst;
- size_of_pkt = SCTP_GET_IPV6_LENGTH(ip6) + iphlen;
- break;
- }
-#endif
- default:
- return (NULL);
- }
-
cookie = &cp->cookie;
cookie_offset = offset + sizeof(struct sctp_chunkhdr);
cookie_len = ntohs(cp->ch.chunk_length);
@@ -2393,11 +2452,10 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
*/
return (NULL);
}
- if (cookie_len > size_of_pkt ||
- cookie_len < sizeof(struct sctp_cookie_echo_chunk) +
+ if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) +
sizeof(struct sctp_init_chunk) +
sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) {
- /* cookie too long! or too small */
+ /* cookie too small */
return (NULL);
}
/*
@@ -2405,11 +2463,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
* calculated in the sctp_hmac_m() call).
*/
sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE;
- if (sig_offset > size_of_pkt) {
- /* packet not correct size! */
- /* XXX this may already be accounted for earlier... */
- return (NULL);
- }
m_sig = m_split(m, sig_offset, M_DONTWAIT);
if (m_sig == NULL) {
/* out of memory or ?? */
@@ -2419,12 +2472,10 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = m_sig;
- while (mat) {
+ for (mat = m_sig; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_SPLIT);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -2535,7 +2586,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
if (tim == 0)
tim = now.tv_usec - cookie->time_entered.tv_usec;
scm->time_usec = htonl(tim);
- sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag,
+ sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
+ use_mflowid, mflowid,
vrf_id, port);
return (NULL);
}
@@ -2549,7 +2601,9 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
* up.
*/
to = NULL;
- if (cookie->addr_type == SCTP_IPV6_ADDRESS) {
+ switch (cookie->addr_type) {
+#ifdef INET6
+ case SCTP_IPV6_ADDRESS:
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
@@ -2558,20 +2612,25 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
memcpy(&sin6.sin6_addr.s6_addr, cookie->address,
sizeof(sin6.sin6_addr.s6_addr));
to = (struct sockaddr *)&sin6;
- } else if (cookie->addr_type == SCTP_IPV4_ADDRESS) {
+ break;
+#endif
+#ifdef INET
+ case SCTP_IPV4_ADDRESS:
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_len = sizeof(sin);
sin.sin_port = sh->src_port;
sin.sin_addr.s_addr = cookie->address[0];
to = (struct sockaddr *)&sin;
- } else {
+ break;
+#endif
+ default:
/* This should not happen */
return (NULL);
}
if ((*stcb == NULL) && to) {
/* Yep, lets check */
- *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, localep_sa, NULL);
+ *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, dst, NULL);
if (*stcb == NULL) {
/*
* We should have only got back the same inp. If we
@@ -2603,7 +2662,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
SCTP_INP_INCR_REF((*stcb)->sctp_ep);
if ((*stcb)->sctp_ep != l_inp) {
SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n",
- (*stcb)->sctp_ep, l_inp);
+ (void *)(*stcb)->sctp_ep, (void *)l_inp);
}
}
}
@@ -2614,21 +2673,33 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
cookie_len -= SCTP_SIGNATURE_SIZE;
if (*stcb == NULL) {
/* this is the "normal" case... get a new TCB */
- *stcb = sctp_process_cookie_new(m, iphlen, offset, sh, cookie,
- cookie_len, *inp_p, netp, to, &notification,
- auth_skipped, auth_offset, auth_len, vrf_id, port);
+ *stcb = sctp_process_cookie_new(m, iphlen, offset, src, dst, sh,
+ cookie, cookie_len, *inp_p,
+ netp, to, &notification,
+ auth_skipped, auth_offset, auth_len,
+ use_mflowid, mflowid,
+ vrf_id, port);
} else {
/* this is abnormal... cookie-echo on existing TCB */
had_a_existing_tcb = 1;
- *stcb = sctp_process_cookie_existing(m, iphlen, offset, sh,
+ *stcb = sctp_process_cookie_existing(m, iphlen, offset,
+ src, dst, sh,
cookie, cookie_len, *inp_p, *stcb, netp, to,
- &notification, &sac_restart_id, vrf_id, auth_skipped, auth_offset, auth_len, port);
+ &notification, auth_skipped, auth_offset, auth_len,
+ use_mflowid, mflowid,
+ vrf_id, port);
}
if (*stcb == NULL) {
/* still no TCB... must be bad cookie-echo */
return (NULL);
}
+ if ((*netp != NULL) && (use_mflowid != 0)) {
+ (*netp)->flowid = mflowid;
+#ifdef INVARIANTS
+ (*netp)->flowidset = 1;
+#endif
+ }
/*
* Ok, we built an association so confirm the address we sent the
* INIT-ACK to.
@@ -2639,10 +2710,9 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
*/
if (netl == NULL) {
/* TSNH! Huh, why do I need to add this address here? */
- int ret;
-
- ret = sctp_add_remote_addr(*stcb, to, SCTP_DONOT_SETSCOPE,
- SCTP_IN_COOKIE_PROC);
+ if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) {
+ return (NULL);
+ }
netl = sctp_findnet(*stcb, to);
}
if (netl) {
@@ -2650,14 +2720,10 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
(void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL,
netl);
- sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
- (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
+ send_int_conf = 1;
}
}
- if (*stcb) {
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, *inp_p,
- *stcb, NULL);
- }
+ sctp_start_net_timers(*stcb);
if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
if (!had_a_existing_tcb ||
(((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
@@ -2674,21 +2740,27 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
* For a restart we will keep the same
* socket, no need to do anything. I THINK!!
*/
- sctp_ulp_notify(notification, *stcb, 0, (void *)&sac_restart_id, SCTP_SO_NOT_LOCKED);
+ sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
+ if (send_int_conf) {
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
+ (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
+ }
return (m);
}
oso = (*inp_p)->sctp_socket;
atomic_add_int(&(*stcb)->asoc.refcnt, 1);
SCTP_TCB_UNLOCK((*stcb));
+ CURVNET_SET(oso->so_vnet);
so = sonewconn(oso, 0
);
+ CURVNET_RESTORE();
SCTP_TCB_LOCK((*stcb));
atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
if (so == NULL) {
struct mbuf *op_err;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *pcb_so;
#endif
@@ -2696,8 +2768,10 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n");
op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
sctp_abort_association(*inp_p, NULL, m, iphlen,
- sh, op_err, vrf_id, port);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
pcb_so = SCTP_INP_SO(*inp_p);
atomic_add_int(&(*stcb)->asoc.refcnt, 1);
SCTP_TCB_UNLOCK((*stcb));
@@ -2706,7 +2780,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(pcb_so, 1);
#endif
return (NULL);
@@ -2729,8 +2803,10 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
inp->sctp_socket = so;
inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
+ inp->sctp_ecn_enable = (*inp_p)->sctp_ecn_enable;
inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
inp->sctp_context = (*inp_p)->sctp_context;
+ inp->local_strreset_support = (*inp_p)->local_strreset_support;
inp->inp_starting_point_for_iterator = NULL;
/*
* copy in the authentication parameters from the
@@ -2786,18 +2862,21 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
/* Switch over to the new guy */
*inp_p = inp;
sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
-
+ if (send_int_conf) {
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
+ (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
+ }
/*
* Pull it from the incomplete queue and wake the
* guy
*/
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
atomic_add_int(&(*stcb)->asoc.refcnt, 1);
SCTP_TCB_UNLOCK((*stcb));
SCTP_SOCKET_LOCK(so, 1);
#endif
soisconnected(so);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_LOCK((*stcb));
atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
SCTP_SOCKET_UNLOCK(so, 1);
@@ -2805,14 +2884,18 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
return (m);
}
}
- if ((notification) && ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
+ if (notification) {
sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
}
+ if (send_int_conf) {
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
+ (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
+ }
return (m);
}
static void
-sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
+sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
struct sctp_tcb *stcb, struct sctp_nets *net)
{
/* cp must not be used, others call this without a c-ack :-) */
@@ -2831,6 +2914,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
/* state change only needed when I am in right state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ sctp_start_net_timers(stcb);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
@@ -2841,42 +2925,50 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
if (asoc->overall_error_count == 0) {
net->RTO = sctp_calculate_rto(stcb, asoc, net,
- &asoc->time_entered, sctp_align_safe_nocopy);
+ &asoc->time_entered, sctp_align_safe_nocopy,
+ SCTP_RTT_FROM_NON_DATA);
}
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
- if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
- SCTP_SOCKET_UNLOCK(so, 1);
- return;
- }
#endif
- soisconnected(stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) {
+ soisconnected(stcb->sctp_socket);
+ }
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
- stcb, net);
/*
* since we did not send a HB make sure we don't double
* things
*/
net->hb_responded = 1;
+ if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
+ /*
+ * We don't need to do the asconf thing, nor hb or
+ * autoclose if the socket is closed.
+ */
+ goto closed_socket;
+ }
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
+ stcb, net);
+
+
if (stcb->asoc.sctp_autoclose_ticks &&
sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) {
sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
@@ -2900,6 +2992,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
#endif
}
}
+closed_socket:
/* Toss the cookie if I can */
sctp_toss_old_cookies(stcb, asoc);
if (!TAILQ_EMPTY(&asoc->sent_queue)) {
@@ -2907,10 +3000,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
struct sctp_tmit_chunk *chk;
chk = TAILQ_FIRST(&asoc->sent_queue);
- if (chk) {
- sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
- stcb, chk->whoTo);
- }
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo);
}
}
@@ -2920,83 +3010,149 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
{
struct sctp_nets *net;
struct sctp_tmit_chunk *lchk;
- uint32_t tsn;
+ struct sctp_ecne_chunk bkup;
+ uint8_t override_bit;
+ uint32_t tsn, window_data_tsn;
+ int len;
+ unsigned int pkt_cnt;
- if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_ecne_chunk)) {
+ len = ntohs(cp->ch.chunk_length);
+ if ((len != sizeof(struct sctp_ecne_chunk)) &&
+ (len != sizeof(struct old_sctp_ecne_chunk))) {
return;
}
+ if (len == sizeof(struct old_sctp_ecne_chunk)) {
+ /* Its the old format */
+ memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk));
+ bkup.num_pkts_since_cwr = htonl(1);
+ cp = &bkup;
+ }
SCTP_STAT_INCR(sctps_recvecne);
tsn = ntohl(cp->tsn);
- /* ECN Nonce stuff: need a resync and disable the nonce sum check */
- /* Also we make sure we disable the nonce_wait */
- lchk = TAILQ_FIRST(&stcb->asoc.send_queue);
+ pkt_cnt = ntohl(cp->num_pkts_since_cwr);
+ lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead);
if (lchk == NULL) {
- stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq;
+ window_data_tsn = stcb->asoc.sending_seq - 1;
} else {
- stcb->asoc.nonce_resync_tsn = lchk->rec.data.TSN_seq;
+ window_data_tsn = lchk->rec.data.TSN_seq;
}
- stcb->asoc.nonce_wait_for_ecne = 0;
- stcb->asoc.nonce_sum_check = 0;
- /* Find where it was sent, if possible */
+ /* Find where it was sent to if possible. */
net = NULL;
- lchk = TAILQ_FIRST(&stcb->asoc.sent_queue);
- while (lchk) {
+ TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) {
if (lchk->rec.data.TSN_seq == tsn) {
net = lchk->whoTo;
+ net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send;
break;
}
- if (compare_with_wrap(lchk->rec.data.TSN_seq, tsn, MAX_SEQ))
+ if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) {
break;
- lchk = TAILQ_NEXT(lchk, sctp_next);
+ }
}
- if (net == NULL)
- /* default is we use the primary */
- net = stcb->asoc.primary_destination;
-
- if (compare_with_wrap(tsn, stcb->asoc.last_cwr_tsn, MAX_TSN)) {
+ if (net == NULL) {
+ /*
+ * What to do. A previous send of a CWR was possibly lost.
+ * See how old it is, we may have it marked on the actual
+ * net.
+ */
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (tsn == net->last_cwr_tsn) {
+ /* Found him, send it off */
+ break;
+ }
+ }
+ if (net == NULL) {
+ /*
+ * If we reach here, we need to send a special CWR
+ * that says hey, we did this a long time ago and
+ * you lost the response.
+ */
+ net = TAILQ_FIRST(&stcb->asoc.nets);
+ if (net == NULL) {
+ /* TSNH */
+ return;
+ }
+ override_bit = SCTP_CWR_REDUCE_OVERRIDE;
+ } else {
+ override_bit = 0;
+ }
+ } else {
+ override_bit = 0;
+ }
+ if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) &&
+ ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) {
/*
* JRS - Use the congestion control given in the pluggable
* CC module
*/
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net);
+ stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt);
/*
- * we reduce once every RTT. So we will only lower cwnd at
- * the next sending seq i.e. the resync_tsn.
+ * We reduce once every RTT. So we will only lower cwnd at
+ * the next sending seq i.e. the window_data_tsn
*/
- stcb->asoc.last_cwr_tsn = stcb->asoc.nonce_resync_tsn;
+ net->cwr_window_tsn = window_data_tsn;
+ net->ecn_ce_pkt_cnt += pkt_cnt;
+ net->lost_cnt = pkt_cnt;
+ net->last_cwr_tsn = tsn;
+ } else {
+ override_bit |= SCTP_CWR_IN_SAME_WINDOW;
+ if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) &&
+ ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) {
+ /*
+ * Another loss in the same window update how many
+ * marks/packets lost we have had.
+ */
+ int cnt = 1;
+
+ if (pkt_cnt > net->lost_cnt) {
+ /* Should be the case */
+ cnt = (pkt_cnt - net->lost_cnt);
+ net->ecn_ce_pkt_cnt += cnt;
+ }
+ net->lost_cnt = pkt_cnt;
+ net->last_cwr_tsn = tsn;
+ /*
+ * Most CC functions will ignore this call, since we
+ * are in-window yet of the initial CE the peer saw.
+ */
+ stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt);
+ }
}
/*
* We always send a CWR this way if our previous one was lost our
* peer will get an update, or if it is not time again to reduce we
- * still get the cwr to the peer.
+ * still get the cwr to the peer. Note we set the override when we
+ * could not find the TSN on the chunk or the destination network.
*/
- sctp_send_cwr(stcb, net, tsn);
+ sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit);
}
static void
-sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb)
+sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net)
{
/*
* Here we get a CWR from the peer. We must look in the outqueue and
- * make sure that we have a covered ECNE in teh control chunk part.
+ * make sure that we have a covered ECNE in the control chunk part.
* If so remove it.
*/
struct sctp_tmit_chunk *chk;
struct sctp_ecne_chunk *ecne;
+ int override;
+ uint32_t cwr_tsn;
+ cwr_tsn = ntohl(cp->tsn);
+
+ override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE;
TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) {
continue;
}
- /*
- * Look for and remove if it is the right TSN. Since there
- * is only ONE ECNE on the control queue at any one time we
- * don't need to worry about more than one!
- */
+ if ((override == 0) && (chk->whoTo != net)) {
+ /* Must be from the right src unless override is set */
+ continue;
+ }
ecne = mtod(chk->data, struct sctp_ecne_chunk *);
- if (compare_with_wrap(ntohl(cp->tsn), ntohl(ecne->tsn),
- MAX_TSN) || (cp->tsn == ecne->tsn)) {
+ if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) {
/* this covers this ECNE, we can remove it */
stcb->asoc.ecn_echo_cnt_onq--;
TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk,
@@ -3006,19 +3162,21 @@ sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb)
chk->data = NULL;
}
stcb->asoc.ctrl_queue_cnt--;
- sctp_free_a_chunk(stcb, chk);
- break;
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
+ if (override == 0) {
+ break;
+ }
}
}
}
static void
-sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
+sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED,
struct sctp_tcb *stcb, struct sctp_nets *net)
{
struct sctp_association *asoc;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
@@ -3043,8 +3201,8 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
/* are the queues empty? they should be */
if (!TAILQ_EMPTY(&asoc->send_queue) ||
!TAILQ_EMPTY(&asoc->sent_queue) ||
- !TAILQ_EMPTY(&asoc->out_wheel)) {
- sctp_report_all_outbound(stcb, 0, SCTP_SO_NOT_LOCKED);
+ !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
+ sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED);
}
}
/* stop the timer */
@@ -3053,7 +3211,7 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
/* free the TCB */
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown_complete: calls free-asoc\n");
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -3062,7 +3220,7 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
return;
@@ -3080,19 +3238,16 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
struct sctp_tmit_chunk *tp1;
tsn = ntohl(desc->tsn_ifany);
- tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
- while (tp1) {
+ TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
if (tp1->rec.data.TSN_seq == tsn) {
/* found it */
break;
}
- if (compare_with_wrap(tp1->rec.data.TSN_seq, tsn,
- MAX_TSN)) {
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) {
/* not found */
tp1 = NULL;
break;
}
- tp1 = TAILQ_NEXT(tp1, sctp_next);
}
if (tp1 == NULL) {
/*
@@ -3100,13 +3255,11 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
* attention to queue seq order.
*/
SCTP_STAT_INCR(sctps_pdrpdnfnd);
- tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
- while (tp1) {
+ TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
if (tp1->rec.data.TSN_seq == tsn) {
/* found it */
break;
}
- tp1 = TAILQ_NEXT(tp1, sctp_next);
}
}
if (tp1 == NULL) {
@@ -3142,17 +3295,15 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
}
}
}
- /*
- * We zero out the nonce so resync not
- * needed
- */
- tp1->rec.data.ect_nonce = 0;
if (tp1->do_rtt) {
/*
* this guy had a RTO calculation
* pending on it, cancel it
*/
+ if (tp1->whoTo->rto_needed == 0) {
+ tp1->whoTo->rto_needed = 1;
+ }
tp1->do_rtt = 0;
}
SCTP_STAT_INCR(sctps_pdrpmark);
@@ -3251,7 +3402,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
case SCTP_SELECTIVE_ACK:
case SCTP_NR_SELECTIVE_ACK:
/* resend the sack */
- sctp_send_sack(stcb);
+ sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
break;
case SCTP_HEARTBEAT_REQUEST:
/* resend a demand HB */
@@ -3260,7 +3411,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
* Only retransmit if we KNOW we wont destroy the
* tcb
*/
- (void)sctp_send_hb(stcb, 1, net);
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
}
break;
case SCTP_SHUTDOWN:
@@ -3314,9 +3465,9 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
}
void
-sctp_reset_in_stream(struct sctp_tcb *stcb, int number_entries, uint16_t * list)
+sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list)
{
- int i;
+ uint32_t i;
uint16_t temp;
/*
@@ -3348,7 +3499,7 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * lis
if (number_entries == 0) {
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
- stcb->asoc.strmout[i].next_sequence_sent = 0;
+ stcb->asoc.strmout[i].next_sequence_send = 0;
}
} else if (number_entries) {
for (i = 0; i < number_entries; i++) {
@@ -3359,7 +3510,7 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * lis
/* no such stream */
continue;
}
- stcb->asoc.strmout[temp].next_sequence_sent = 0;
+ stcb->asoc.strmout[temp].next_sequence_send = 0;
}
}
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
@@ -3370,7 +3521,7 @@ struct sctp_stream_reset_out_request *
sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk)
{
struct sctp_association *asoc;
- struct sctp_stream_reset_out_req *req;
+ struct sctp_chunkhdr *ch;
struct sctp_stream_reset_out_request *r;
struct sctp_tmit_chunk *chk;
int len, clen;
@@ -3393,8 +3544,8 @@ sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chu
*bchk = chk;
}
clen = chk->send_size;
- req = mtod(chk->data, struct sctp_stream_reset_out_req *);
- r = &req->sr_req;
+ ch = mtod(chk->data, struct sctp_chunkhdr *);
+ r = (struct sctp_stream_reset_out_request *)(ch + 1);
if (ntohl(r->request_seq) == seq) {
/* found it */
return (r);
@@ -3431,7 +3582,7 @@ sctp_clean_up_stream_reset(struct sctp_tcb *stcb)
chk->data = NULL;
}
asoc->ctrl_queue_cnt--;
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
/* sa_ignore NO_NULL_CHK */
stcb->asoc.str_reset = NULL;
}
@@ -3464,9 +3615,11 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
asoc->stream_reset_out_is_outstanding = 0;
if (asoc->stream_reset_outstanding)
asoc->stream_reset_outstanding--;
- if (action == SCTP_STREAM_RESET_PERFORMED) {
+ if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
/* do it */
sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams);
+ } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
+ sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
} else {
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
}
@@ -3475,21 +3628,45 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t);
if (asoc->stream_reset_outstanding)
asoc->stream_reset_outstanding--;
- if (action != SCTP_STREAM_RESET_PERFORMED) {
- sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
+ if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
+ sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb,
+ number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
+ } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) {
+ sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb,
+ number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
}
- } else if (type == SCTP_STR_RESET_ADD_STREAMS) {
+ } else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) {
/* Ok we now may have more streams */
+ int num_stream;
+
+ num_stream = stcb->asoc.strm_pending_add_size;
+ if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) {
+ /* TSNH */
+ num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt;
+ }
+ stcb->asoc.strm_pending_add_size = 0;
if (asoc->stream_reset_outstanding)
asoc->stream_reset_outstanding--;
- if (action == SCTP_STREAM_RESET_PERFORMED) {
+ if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
/* Put the new streams into effect */
- stcb->asoc.streamoutcnt = stcb->asoc.strm_realoutsize;
- sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_ADD_OK, stcb,
- (uint32_t) stcb->asoc.streamoutcnt, NULL, SCTP_SO_NOT_LOCKED);
+ stcb->asoc.streamoutcnt += num_stream;
+ sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0);
+ } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
+ sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
+ SCTP_STREAM_CHANGE_DENIED);
} else {
- sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_ADD_FAIL, stcb,
- (uint32_t) stcb->asoc.streamoutcnt, NULL, SCTP_SO_NOT_LOCKED);
+ sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
+ SCTP_STREAM_CHANGE_FAILED);
+ }
+ } else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) {
+ if (asoc->stream_reset_outstanding)
+ asoc->stream_reset_outstanding--;
+ if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
+ sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
+ SCTP_STREAM_CHANGE_DENIED);
+ } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) {
+ sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
+ SCTP_STREAM_CHANGE_FAILED);
}
} else if (type == SCTP_STR_RESET_TSN_REQUEST) {
/**
@@ -3505,7 +3682,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
/* huh ? */
return (0);
}
- if (action == SCTP_STREAM_RESET_PERFORMED) {
+ if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
resp = (struct sctp_stream_reset_response_tsn *)respin;
asoc->stream_reset_outstanding--;
fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk));
@@ -3531,7 +3708,13 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL);
sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL);
-
+ sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0);
+ } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
+ sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1),
+ SCTP_ASSOC_RESET_DENIED);
+ } else {
+ sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1),
+ SCTP_ASSOC_RESET_FAILED);
}
}
/* get rid of the request and get the request flags */
@@ -3561,11 +3744,12 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb,
seq = ntohl(req->request_seq);
if (asoc->str_reset_seq_in == seq) {
- if (trunc) {
+ asoc->last_reset_action[1] = asoc->last_reset_action[0];
+ if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) {
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ } else if (trunc) {
/* Can't do it, since they exceeded our buffer size */
- asoc->last_reset_action[1] = asoc->last_reset_action[0];
- asoc->last_reset_action[0] = SCTP_STREAM_RESET_DENIED;
- sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
} else if (stcb->asoc.stream_reset_out_is_outstanding == 0) {
len = ntohs(req->ph.param_length);
number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t));
@@ -3573,9 +3757,7 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb,
temp = ntohs(req->list_of_streams[i]);
req->list_of_streams[i] = temp;
}
- /* move the reset action back one */
- asoc->last_reset_action[1] = asoc->last_reset_action[0];
- asoc->last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED;
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams,
asoc->str_reset_seq_out,
seq, (asoc->sending_seq - 1));
@@ -3585,17 +3767,16 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb,
stcb->asoc.stream_reset_outstanding++;
} else {
/* Can't do it, since we have sent one out */
- asoc->last_reset_action[1] = asoc->last_reset_action[0];
- asoc->last_reset_action[0] = SCTP_STREAM_RESET_TRY_LATER;
- sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS;
}
+ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
asoc->str_reset_seq_in++;
} else if (asoc->str_reset_seq_in - 1 == seq) {
sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
} else if (asoc->str_reset_seq_in - 2 == seq) {
sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
} else {
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO);
+ sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
}
}
@@ -3617,53 +3798,49 @@ sctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb,
seq = ntohl(req->request_seq);
if (asoc->str_reset_seq_in == seq) {
- fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk));
- fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN;
- fwdtsn.ch.chunk_flags = 0;
- fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1);
- sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0);
- if (abort_flag) {
- return (1);
- }
- stcb->asoc.highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
- sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
- }
- stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map;
- stcb->asoc.mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1;
- memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
- stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map;
- memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size);
- atomic_add_int(&stcb->asoc.sending_seq, 1);
- /* save off historical data for retrans */
- stcb->asoc.last_sending_seq[1] = stcb->asoc.last_sending_seq[0];
- stcb->asoc.last_sending_seq[0] = stcb->asoc.sending_seq;
- stcb->asoc.last_base_tsnsent[1] = stcb->asoc.last_base_tsnsent[0];
- stcb->asoc.last_base_tsnsent[0] = stcb->asoc.mapping_array_base_tsn;
-
- sctp_add_stream_reset_result_tsn(chk,
- ntohl(req->request_seq),
- SCTP_STREAM_RESET_PERFORMED,
- stcb->asoc.sending_seq,
- stcb->asoc.mapping_array_base_tsn);
- sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL);
- sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL);
- stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
- stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED;
-
+ asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0];
+ if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ } else {
+ fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk));
+ fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN;
+ fwdtsn.ch.chunk_flags = 0;
+ fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1);
+ sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0);
+ if (abort_flag) {
+ return (1);
+ }
+ asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA;
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
+ sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
+ }
+ asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map;
+ asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1;
+ memset(asoc->mapping_array, 0, asoc->mapping_array_size);
+ asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map;
+ memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size);
+ atomic_add_int(&asoc->sending_seq, 1);
+ /* save off historical data for retrans */
+ asoc->last_sending_seq[1] = asoc->last_sending_seq[0];
+ asoc->last_sending_seq[0] = asoc->sending_seq;
+ asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0];
+ asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn;
+ sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL);
+ sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL);
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
+ sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0);
+ }
+ sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0],
+ asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]);
asoc->str_reset_seq_in++;
} else if (asoc->str_reset_seq_in - 1 == seq) {
sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0],
- stcb->asoc.last_sending_seq[0],
- stcb->asoc.last_base_tsnsent[0]
- );
+ asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]);
} else if (asoc->str_reset_seq_in - 2 == seq) {
sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1],
- stcb->asoc.last_sending_seq[1],
- stcb->asoc.last_base_tsnsent[1]
- );
+ asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]);
} else {
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO);
+ sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
}
return (0);
}
@@ -3694,15 +3871,14 @@ sctp_handle_str_reset_request_out(struct sctp_tcb *stcb,
/* move the reset action back one */
asoc->last_reset_action[1] = asoc->last_reset_action[0];
- if (trunc) {
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_DENIED);
- asoc->last_reset_action[0] = SCTP_STREAM_RESET_DENIED;
- } else if ((tsn == asoc->cumulative_tsn) ||
- (compare_with_wrap(asoc->cumulative_tsn, tsn, MAX_TSN))) {
+ if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) {
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ } else if (trunc) {
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ } else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) {
/* we can do it now */
sctp_reset_in_stream(stcb, number_entries, req->list_of_streams);
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_PERFORMED);
- asoc->last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED;
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
} else {
/*
* we must queue it up and thus wait for the TSN's
@@ -3716,18 +3892,17 @@ sctp_handle_str_reset_request_out(struct sctp_tcb *stcb,
siz, SCTP_M_STRESET);
if (liste == NULL) {
/* gak out of memory */
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_DENIED);
- asoc->last_reset_action[0] = SCTP_STREAM_RESET_DENIED;
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
return;
}
liste->tsn = tsn;
liste->number_entries = number_entries;
- memcpy(&liste->req, req,
- (sizeof(struct sctp_stream_reset_out_request) + (number_entries * sizeof(uint16_t))));
+ memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t));
TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp);
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_PERFORMED);
- asoc->last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED;
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
}
+ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
asoc->str_reset_seq_in++;
} else if ((asoc->str_reset_seq_in - 1) == seq) {
/*
@@ -3742,7 +3917,7 @@ sctp_handle_str_reset_request_out(struct sctp_tcb *stcb,
*/
sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
} else {
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO);
+ sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
}
}
@@ -3754,10 +3929,10 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
* Peer is requesting to add more streams. If its within our
* max-streams we will allow it.
*/
- uint16_t num_stream, i;
+ uint32_t num_stream, i;
uint32_t seq;
struct sctp_association *asoc = &stcb->asoc;
- struct sctp_queued_to_read *ctl;
+ struct sctp_queued_to_read *ctl, *nctl;
/* Get the number. */
seq = ntohl(str_add->request_seq);
@@ -3765,12 +3940,14 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
/* Now what would be the new total? */
if (asoc->str_reset_seq_in == seq) {
num_stream += stcb->asoc.streamincnt;
- if (num_stream > stcb->asoc.max_inbound_streams) {
+ stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
+ if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ } else if ((num_stream > stcb->asoc.max_inbound_streams) ||
+ (num_stream > 0xffff)) {
/* We must reject it they ask for to many */
denied:
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_DENIED);
- stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
- stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_DENIED;
+ stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
} else {
/* Ok, we can do that :-) */
struct sctp_stream_in *oldstrm;
@@ -3791,8 +3968,7 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered;
stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started;
/* now anything on those queues? */
- while (TAILQ_EMPTY(&oldstrm[i].inqueue) == 0) {
- ctl = TAILQ_FIRST(&oldstrm[i].inqueue);
+ TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) {
TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next);
TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next);
}
@@ -3807,13 +3983,11 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
SCTP_FREE(oldstrm, SCTP_M_STRMI);
/* update the size */
stcb->asoc.streamincnt = num_stream;
- /* Send the ack */
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_PERFORMED);
- stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
- stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED;
- sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_INSTREAM_ADD_OK, stcb,
- (uint32_t) stcb->asoc.streamincnt, NULL, SCTP_SO_NOT_LOCKED);
+ stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
+ sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0);
}
+ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
+ asoc->str_reset_seq_in++;
} else if ((asoc->str_reset_seq_in - 1) == seq) {
/*
* one seq back, just echo back last action since my
@@ -3827,8 +4001,65 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
*/
sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
} else {
- sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO);
+ sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
+
+ }
+}
+
+static void
+sctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk,
+ struct sctp_stream_reset_add_strm *str_add)
+{
+ /*
+ * Peer is requesting to add more streams. If its within our
+ * max-streams we will allow it.
+ */
+ uint16_t num_stream;
+ uint32_t seq;
+ struct sctp_association *asoc = &stcb->asoc;
+ /* Get the number. */
+ seq = ntohl(str_add->request_seq);
+ num_stream = ntohs(str_add->number_of_streams);
+ /* Now what would be the new total? */
+ if (asoc->str_reset_seq_in == seq) {
+ stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
+ if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ } else if (stcb->asoc.stream_reset_outstanding) {
+ /* We must reject it we have something pending */
+ stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS;
+ } else {
+ /* Ok, we can do that :-) */
+ int mychk;
+
+ mychk = stcb->asoc.streamoutcnt;
+ mychk += num_stream;
+ if (mychk < 0x10000) {
+ stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
+ if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) {
+ stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ }
+ } else {
+ stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ }
+ }
+ sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]);
+ asoc->str_reset_seq_in++;
+ } else if ((asoc->str_reset_seq_in - 1) == seq) {
+ /*
+ * one seq back, just echo back last action since my
+ * response was lost.
+ */
+ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
+ } else if ((asoc->str_reset_seq_in - 2) == seq) {
+ /*
+ * two seq back, just echo back last action since my
+ * response was lost.
+ */
+ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
+ } else {
+ sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
}
}
@@ -3837,13 +4068,12 @@ __attribute__((noinline))
#endif
static int
sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset,
- struct sctp_stream_reset_out_req *sr_req)
+ struct sctp_chunkhdr *ch_req)
{
int chk_length, param_len, ptype;
struct sctp_paramhdr pstore;
uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE];
-
- uint32_t seq;
+ uint32_t seq = 0;
int num_req = 0;
int trunc = 0;
struct sctp_tmit_chunk *chk;
@@ -3853,7 +4083,7 @@ __attribute__((noinline))
int num_param = 0;
/* now it may be a reset or a reset-response */
- chk_length = ntohs(sr_req->ch.chunk_length);
+ chk_length = ntohs(ch_req->chunk_length);
/* setup for adding the response */
sctp_alloc_a_chunk(stcb, chk);
@@ -3873,7 +4103,7 @@ strres_nochunk:
sctp_m_freem(chk->data);
chk->data = NULL;
}
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
return (ret_code);
}
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
@@ -3881,8 +4111,7 @@ strres_nochunk:
/* setup chunk parameters */
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->whoTo = stcb->asoc.primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
+ chk->whoTo = NULL;
ch = mtod(chk->data, struct sctp_chunkhdr *);
ch->chunk_type = SCTP_STREAM_RESET;
@@ -3908,7 +4137,6 @@ strres_nochunk:
} else {
trunc = 0;
}
-
if (num_param > SCTP_MAX_RESET_PARAMS) {
/* hit the max of parameters already sorry.. */
break;
@@ -3922,30 +4150,33 @@ strres_nochunk:
seq = ntohl(req_out->response_seq);
if (seq == stcb->asoc.str_reset_seq_out) {
/* implicit ack */
- (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_PERFORMED, NULL);
+ (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL);
}
}
sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc);
- } else if (ptype == SCTP_STR_RESET_ADD_STREAMS) {
+ } else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) {
struct sctp_stream_reset_add_strm *str_add;
str_add = (struct sctp_stream_reset_add_strm *)ph;
num_req++;
sctp_handle_str_reset_add_strm(stcb, chk, str_add);
+ } else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) {
+ struct sctp_stream_reset_add_strm *str_add;
+
+ str_add = (struct sctp_stream_reset_add_strm *)ph;
+ num_req++;
+ sctp_handle_str_reset_add_out_strm(stcb, chk, str_add);
} else if (ptype == SCTP_STR_RESET_IN_REQUEST) {
struct sctp_stream_reset_in_request *req_in;
num_req++;
-
req_in = (struct sctp_stream_reset_in_request *)ph;
-
sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc);
} else if (ptype == SCTP_STR_RESET_TSN_REQUEST) {
struct sctp_stream_reset_tsn_request *req_tsn;
num_req++;
req_tsn = (struct sctp_stream_reset_tsn_request *)ph;
-
if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) {
ret_code = 1;
goto strres_nochunk;
@@ -4150,8 +4381,10 @@ __attribute__((noinline))
#endif
static struct sctp_tcb *
sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
+ struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp,
struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen,
+ uint8_t use_mflowid, uint32_t mflowid,
uint32_t vrf_id, uint16_t port)
{
struct sctp_association *asoc;
@@ -4160,6 +4393,7 @@ __attribute__((noinline))
uint32_t chk_length;
int ret;
int abort_no_unlock = 0;
+ int ecne_seen = 0;
/*
* How big should this be, and should it be alloc'd? Lets try the
@@ -4173,13 +4407,13 @@ __attribute__((noinline))
int auth_skipped = 0;
int asconf_cnt = 0;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n",
- iphlen, *offset, length, stcb);
+ iphlen, *offset, length, (void *)stcb);
/* validate chunk header length... */
if (ntohs(ch->chunk_length) < sizeof(*ch)) {
@@ -4263,8 +4497,10 @@ __attribute__((noinline))
asconf_len = ntohs(asconf_ch->chunk_length);
if (asconf_len < sizeof(struct sctp_asconf_paramhdr))
break;
- stcb = sctp_findassociation_ep_asconf(m, iphlen,
- *offset, sh, &inp, netp, vrf_id);
+ stcb = sctp_findassociation_ep_asconf(m,
+ *offset,
+ dst,
+ sh, &inp, netp, vrf_id);
if (stcb != NULL)
break;
asconf_offset += SCTP_SIZE32(asconf_len);
@@ -4306,7 +4542,8 @@ __attribute__((noinline))
}
if (stcb == NULL) {
/* no association, so it's out of the blue... */
- sctp_handle_ootb(m, iphlen, *offset, sh, inp, NULL,
+ sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp,
+ use_mflowid, mflowid,
vrf_id, port);
*offset = length;
if (locked_tcb) {
@@ -4343,8 +4580,10 @@ __attribute__((noinline))
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
}
- sctp_handle_ootb(m, iphlen, *offset, sh, inp,
- NULL, vrf_id, port);
+ sctp_handle_ootb(m, iphlen, *offset, src, dst,
+ sh, inp,
+ use_mflowid, mflowid,
+ vrf_id, port);
return (NULL);
}
} else {
@@ -4367,7 +4606,6 @@ __attribute__((noinline))
* process all control chunks...
*/
if (((ch->chunk_type == SCTP_SELECTIVE_ACK) ||
- /* EY */
(ch->chunk_type == SCTP_NR_SELECTIVE_ACK) ||
(ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) &&
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
@@ -4481,55 +4719,36 @@ process_control_chunks:
}
switch (ch->chunk_type) {
case SCTP_INITIATION:
- /* must be first and only chunk */
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n");
- if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
- /* We are not interested anymore? */
- if ((stcb) && (stcb->asoc.total_output_queue_size)) {
- /*
- * collision case where we are
- * sending to them too
- */
- ;
- } else {
- if (locked_tcb) {
- SCTP_TCB_UNLOCK(locked_tcb);
- }
- *offset = length;
- return (NULL);
- }
- }
- if ((chk_length > SCTP_LARGEST_INIT_ACCEPTED) ||
- (num_chunks > 1) ||
- (SCTP_BASE_SYSCTL(sctp_strict_init) && (length - *offset > (int)SCTP_SIZE32(chk_length)))) {
+ /* The INIT chunk must be the only chunk. */
+ if ((num_chunks > 1) ||
+ (length - *offset > (int)SCTP_SIZE32(chk_length))) {
+ sctp_abort_association(inp, stcb, m, iphlen,
+ src, dst, sh, NULL,
+ use_mflowid, mflowid,
+ vrf_id, port);
*offset = length;
- if (locked_tcb) {
- SCTP_TCB_UNLOCK(locked_tcb);
- }
return (NULL);
}
- if ((stcb != NULL) &&
- (SCTP_GET_STATE(&stcb->asoc) ==
- SCTP_STATE_SHUTDOWN_ACK_SENT)) {
- sctp_send_shutdown_ack(stcb,
- stcb->asoc.primary_destination);
+ /* Honor our resource limit. */
+ if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) {
+ struct mbuf *op_err;
+
+ op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
+ sctp_abort_association(inp, stcb, m, iphlen,
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
*offset = length;
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
- if (locked_tcb) {
- SCTP_TCB_UNLOCK(locked_tcb);
- }
return (NULL);
}
- if (netp) {
- sctp_handle_init(m, iphlen, *offset, sh,
- (struct sctp_init_chunk *)ch, inp,
- stcb, *netp, &abort_no_unlock, vrf_id, port);
- }
- if (abort_no_unlock)
- return (NULL);
-
+ sctp_handle_init(m, iphlen, *offset, src, dst, sh,
+ (struct sctp_init_chunk *)ch, inp,
+ stcb, &abort_no_unlock,
+ use_mflowid, mflowid,
+ vrf_id, port);
*offset = length;
- if (locked_tcb) {
+ if ((!abort_no_unlock) && (locked_tcb)) {
SCTP_TCB_UNLOCK(locked_tcb);
}
return (NULL);
@@ -4537,7 +4756,6 @@ process_control_chunks:
case SCTP_PAD_CHUNK:
break;
case SCTP_INITIATION_ACK:
- /* must be first and only chunk */
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n");
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
@@ -4550,7 +4768,7 @@ process_control_chunks:
}
*offset = length;
if (stcb) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -4559,15 +4777,16 @@ process_control_chunks:
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
return (NULL);
}
}
+ /* The INIT-ACK chunk must be the only chunk. */
if ((num_chunks > 1) ||
- (SCTP_BASE_SYSCTL(sctp_strict_init) && (length - *offset > (int)SCTP_SIZE32(chk_length)))) {
+ (length - *offset > (int)SCTP_SIZE32(chk_length))) {
*offset = length;
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
@@ -4575,21 +4794,27 @@ process_control_chunks:
return (NULL);
}
if ((netp) && (*netp)) {
- ret = sctp_handle_init_ack(m, iphlen, *offset, sh,
- (struct sctp_init_ack_chunk *)ch, stcb, *netp, &abort_no_unlock, vrf_id);
+ ret = sctp_handle_init_ack(m, iphlen, *offset,
+ src, dst, sh,
+ (struct sctp_init_ack_chunk *)ch,
+ stcb, *netp,
+ &abort_no_unlock,
+ use_mflowid, mflowid,
+ vrf_id);
} else {
ret = -1;
}
+ *offset = length;
+ if (abort_no_unlock) {
+ return (NULL);
+ }
/*
* Special case, I must call the output routine to
* get the cookie echoed
*/
- if (abort_no_unlock)
- return (NULL);
-
- if ((stcb) && ret == 0)
+ if ((stcb != NULL) && (ret == 0)) {
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
- *offset = length;
+ }
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
}
@@ -4603,7 +4828,6 @@ process_control_chunks:
uint16_t num_seg, num_dup;
uint8_t flags;
int offset_seg, offset_dup;
- int nonce_sum_flag;
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n");
SCTP_STAT_INCR(sctps_recvsacks);
@@ -4625,7 +4849,6 @@ process_control_chunks:
}
sack = (struct sctp_sack_chunk *)ch;
flags = ch->chunk_flags;
- nonce_sum_flag = flags & SCTP_SACK_NONCE_SUM;
cum_ack = ntohl(sack->sack.cum_tsn_ack);
num_seg = ntohs(sack->sack.num_gap_ack_blks);
num_dup = ntohs(sack->sack.num_dup_tsns);
@@ -4643,8 +4866,7 @@ process_control_chunks:
stcb->asoc.seen_a_sack_this_pkt = 1;
if ((stcb->asoc.pr_sctp_cnt == 0) &&
(num_seg == 0) &&
- ((compare_with_wrap(cum_ack, stcb->asoc.last_acked_seq, MAX_TSN)) ||
- (cum_ack == stcb->asoc.last_acked_seq)) &&
+ SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) &&
(stcb->asoc.saw_sack_with_frags == 0) &&
(stcb->asoc.saw_sack_with_nr_frags == 0) &&
(!TAILQ_EMPTY(&stcb->asoc.sent_queue))
@@ -4658,14 +4880,12 @@ process_control_chunks:
* with no missing segments to go
* this way too.
*/
- sctp_express_handle_sack(stcb, cum_ack, a_rwnd, nonce_sum_flag,
- &abort_now);
+ sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen);
} else {
if (netp && *netp)
- sctp_handle_sack(m, offset_seg, offset_dup,
- stcb, *netp,
+ sctp_handle_sack(m, offset_seg, offset_dup, stcb,
num_seg, 0, num_dup, &abort_now, flags,
- cum_ack, a_rwnd);
+ cum_ack, a_rwnd, ecne_seen);
}
if (abort_now) {
/* ABORT signal from sack processing */
@@ -4691,7 +4911,6 @@ process_control_chunks:
uint16_t num_seg, num_nr_seg, num_dup;
uint8_t flags;
int offset_seg, offset_dup;
- int nonce_sum_flag;
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n");
SCTP_STAT_INCR(sctps_recvsacks);
@@ -4717,8 +4936,6 @@ process_control_chunks:
}
nr_sack = (struct sctp_nr_sack_chunk *)ch;
flags = ch->chunk_flags;
- nonce_sum_flag = flags & SCTP_SACK_NONCE_SUM;
-
cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack);
num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks);
num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks);
@@ -4737,8 +4954,7 @@ process_control_chunks:
stcb->asoc.seen_a_sack_this_pkt = 1;
if ((stcb->asoc.pr_sctp_cnt == 0) &&
(num_seg == 0) && (num_nr_seg == 0) &&
- ((compare_with_wrap(cum_ack, stcb->asoc.last_acked_seq, MAX_TSN)) ||
- (cum_ack == stcb->asoc.last_acked_seq)) &&
+ SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) &&
(stcb->asoc.saw_sack_with_frags == 0) &&
(stcb->asoc.saw_sack_with_nr_frags == 0) &&
(!TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
@@ -4751,14 +4967,13 @@ process_control_chunks:
* missing segments to go this way
* too.
*/
- sctp_express_handle_sack(stcb, cum_ack, a_rwnd, nonce_sum_flag,
- &abort_now);
+ sctp_express_handle_sack(stcb, cum_ack, a_rwnd,
+ &abort_now, ecne_seen);
} else {
if (netp && *netp)
- sctp_handle_sack(m, offset_seg, offset_dup,
- stcb, *netp,
+ sctp_handle_sack(m, offset_seg, offset_dup, stcb,
num_seg, num_nr_seg, num_dup, &abort_now, flags,
- cum_ack, a_rwnd);
+ cum_ack, a_rwnd, ecne_seen);
}
if (abort_now) {
/* ABORT signal from sack processing */
@@ -4817,7 +5032,7 @@ process_control_chunks:
break;
case SCTP_ABORT_ASSOCIATION:
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n",
- stcb);
+ (void *)stcb);
if ((stcb) && netp && *netp)
sctp_handle_abort((struct sctp_abort_chunk *)ch,
stcb, *netp);
@@ -4826,7 +5041,7 @@ process_control_chunks:
break;
case SCTP_SHUTDOWN:
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n",
- stcb);
+ (void *)stcb);
if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) {
*offset = length;
if (locked_tcb) {
@@ -4846,7 +5061,7 @@ process_control_chunks:
}
break;
case SCTP_SHUTDOWN_ACK:
- SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", stcb);
+ SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", (void *)stcb);
if ((stcb) && (netp) && (*netp))
sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp);
*offset = length;
@@ -4856,14 +5071,13 @@ process_control_chunks:
case SCTP_OPERATION_ERROR:
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n");
if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) {
-
*offset = length;
return (NULL);
}
break;
case SCTP_COOKIE_ECHO:
SCTPDBG(SCTP_DEBUG_INPUT3,
- "SCTP_COOKIE-ECHO, stcb %p\n", stcb);
+ "SCTP_COOKIE-ECHO, stcb %p\n", (void *)stcb);
if ((stcb) && (stcb->asoc.total_output_queue_size)) {
;
} else {
@@ -4888,23 +5102,13 @@ process_control_chunks:
if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) {
- struct mbuf *oper;
- struct sctp_paramhdr *phdr;
-
- oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
- 0, M_DONTWAIT, 1, MT_DATA);
- if (oper) {
- SCTP_BUF_LEN(oper) =
- sizeof(struct sctp_paramhdr);
- phdr = mtod(oper,
- struct sctp_paramhdr *);
- phdr->param_type =
- htons(SCTP_CAUSE_OUT_OF_RESC);
- phdr->param_length =
- htons(sizeof(struct sctp_paramhdr));
- }
- sctp_abort_association(inp, stcb, m,
- iphlen, sh, oper, vrf_id, port);
+ struct mbuf *op_err;
+
+ op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
+ sctp_abort_association(inp, stcb, m, iphlen,
+ src, dst, sh, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
}
*offset = length;
return (NULL);
@@ -4929,13 +5133,17 @@ process_control_chunks:
if (netp) {
ret_buf =
sctp_handle_cookie_echo(m, iphlen,
- *offset, sh,
+ *offset,
+ src, dst,
+ sh,
(struct sctp_cookie_echo_chunk *)ch,
&inp, &stcb, netp,
auth_skipped,
auth_offset,
auth_len,
&locked_tcb,
+ use_mflowid,
+ mflowid,
vrf_id,
port);
} else {
@@ -4950,7 +5158,6 @@ process_control_chunks:
}
SCTPDBG(SCTP_DEBUG_INPUT3,
"GAK, null buffer\n");
- auth_skipped = 0;
*offset = length;
return (NULL);
}
@@ -4967,16 +5174,12 @@ process_control_chunks:
struct sctp_tmit_chunk *chk;
chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
- if (chk) {
- sctp_timer_start(SCTP_TIMER_TYPE_SEND,
- stcb->sctp_ep, stcb,
- chk->whoTo);
- }
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo);
}
}
break;
case SCTP_COOKIE_ACK:
- SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", stcb);
+ SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", (void *)stcb);
if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) {
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
@@ -4988,7 +5191,7 @@ process_control_chunks:
if ((stcb) && (stcb->asoc.total_output_queue_size)) {
;
} else if (stcb) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -4997,7 +5200,7 @@ process_control_chunks:
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
*offset = length;
@@ -5039,6 +5242,7 @@ process_control_chunks:
stcb->asoc.overall_error_count = 0;
sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch,
stcb);
+ ecne_seen = 1;
}
break;
case SCTP_ECN_CWR:
@@ -5061,11 +5265,11 @@ process_control_chunks:
__LINE__);
}
stcb->asoc.overall_error_count = 0;
- sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb);
+ sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp);
}
break;
case SCTP_SHUTDOWN_COMPLETE:
- SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", stcb);
+ SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", (void *)stcb);
/* must be first and only chunk */
if ((num_chunks > 1) ||
(length - *offset > (int)SCTP_SIZE32(chk_length))) {
@@ -5094,7 +5298,7 @@ process_control_chunks:
__LINE__);
}
stcb->asoc.overall_error_count = 0;
- sctp_handle_asconf(m, *offset,
+ sctp_handle_asconf(m, *offset, src,
(struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0);
asconf_cnt++;
}
@@ -5150,7 +5354,7 @@ process_control_chunks:
*fwd_tsn_seen = 1;
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -5159,7 +5363,7 @@ process_control_chunks:
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
*offset = length;
@@ -5193,23 +5397,6 @@ process_control_chunks:
*offset = length;
return (NULL);
}
- if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
- /* We are not interested anymore */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- so = SCTP_INP_SO(inp);
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- SCTP_SOCKET_LOCK(so, 1);
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
-#endif
- (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_30);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- SCTP_SOCKET_UNLOCK(so, 1);
-#endif
- *offset = length;
- return (NULL);
- }
if (stcb->asoc.peer_supports_strreset == 0) {
/*
* hmm, peer should have announced this, but
@@ -5218,7 +5405,7 @@ process_control_chunks:
*/
stcb->asoc.peer_supports_strreset = 1;
}
- if (sctp_handle_stream_reset(stcb, m, *offset, (struct sctp_stream_reset_out_req *)ch)) {
+ if (sctp_handle_stream_reset(stcb, m, *offset, ch)) {
/* stop processing */
*offset = length;
return (NULL);
@@ -5305,23 +5492,24 @@ process_control_chunks:
phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK);
phd->param_length = htons(chk_length + sizeof(*phd));
SCTP_BUF_LEN(mm) = sizeof(*phd);
- SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, SCTP_SIZE32(chk_length),
- M_DONTWAIT);
+ SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_DONTWAIT);
if (SCTP_BUF_NEXT(mm)) {
+ if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
+ sctp_m_freem(mm);
+ } else {
#ifdef SCTP_MBUF_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
- struct mbuf *mat;
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
+ struct mbuf *mat;
- mat = SCTP_BUF_NEXT(mm);
- while (mat) {
- if (SCTP_BUF_IS_EXTENDED(mat)) {
- sctp_log_mb(mat, SCTP_MBUF_ICOPY);
+ for (mat = SCTP_BUF_NEXT(mm); mat; mat = SCTP_BUF_NEXT(mat)) {
+ if (SCTP_BUF_IS_EXTENDED(mat)) {
+ sctp_log_mb(mat, SCTP_MBUF_ICOPY);
+ }
}
- mat = SCTP_BUF_NEXT(mat);
}
- }
#endif
- sctp_queue_op_err(stcb, mm);
+ sctp_queue_op_err(stcb, mm);
+ }
} else {
sctp_m_freem(mm);
}
@@ -5361,69 +5549,6 @@ next_chunk:
}
-/*
- * Process the ECN bits we have something set so we must look to see if it is
- * ECN(0) or ECN(1) or CE
- */
-static void
-sctp_process_ecn_marked_a(struct sctp_tcb *stcb, struct sctp_nets *net,
- uint8_t ecn_bits)
-{
- if ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS) {
- ;
- } else if ((ecn_bits & SCTP_ECT1_BIT) == SCTP_ECT1_BIT) {
- /*
- * we only add to the nonce sum for ECT1, ECT0 does not
- * change the NS bit (that we have yet to find a way to send
- * it yet).
- */
-
- /* ECN Nonce stuff */
- stcb->asoc.receiver_nonce_sum++;
- stcb->asoc.receiver_nonce_sum &= SCTP_SACK_NONCE_SUM;
-
- /*
- * Drag up the last_echo point if cumack is larger since we
- * don't want the point falling way behind by more than
- * 2^^31 and then having it be incorrect.
- */
- if (compare_with_wrap(stcb->asoc.cumulative_tsn,
- stcb->asoc.last_echo_tsn, MAX_TSN)) {
- stcb->asoc.last_echo_tsn = stcb->asoc.cumulative_tsn;
- }
- } else if ((ecn_bits & SCTP_ECT0_BIT) == SCTP_ECT0_BIT) {
- /*
- * Drag up the last_echo point if cumack is larger since we
- * don't want the point falling way behind by more than
- * 2^^31 and then having it be incorrect.
- */
- if (compare_with_wrap(stcb->asoc.cumulative_tsn,
- stcb->asoc.last_echo_tsn, MAX_TSN)) {
- stcb->asoc.last_echo_tsn = stcb->asoc.cumulative_tsn;
- }
- }
-}
-
-static void
-sctp_process_ecn_marked_b(struct sctp_tcb *stcb, struct sctp_nets *net,
- uint32_t high_tsn, uint8_t ecn_bits)
-{
- if ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS) {
- /*
- * we possibly must notify the sender that a congestion
- * window reduction is in order. We do this by adding a ECNE
- * chunk to the output chunk queue. The incoming CWR will
- * remove this chunk.
- */
- if (compare_with_wrap(high_tsn, stcb->asoc.last_echo_tsn,
- MAX_TSN)) {
- /* Yep, we need to add a ECNE */
- sctp_send_ecn_echo(stcb, net, high_tsn);
- stcb->asoc.last_echo_tsn = high_tsn;
- }
- }
-}
-
#ifdef INVARIANTS
#ifdef __GNUC__
__attribute__((noinline))
@@ -5452,34 +5577,152 @@ __attribute__((noinline))
* common input chunk processing (v4 and v6)
*/
void
-sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
- int length, struct sctphdr *sh, struct sctp_chunkhdr *ch,
- struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets *net,
- uint8_t ecn_bits, uint32_t vrf_id, uint16_t port)
+sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length,
+ struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh, struct sctp_chunkhdr *ch,
+#if !defined(SCTP_WITH_NO_CSUM)
+ uint8_t compute_crc,
+#endif
+ uint8_t ecn_bits,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port)
{
- /*
- * Control chunk processing
- */
uint32_t high_tsn;
int fwd_tsn_seen = 0, data_processed = 0;
struct mbuf *m = *mm;
- int abort_flag = 0;
int un_sent;
+ int cnt_ctrl_ready = 0;
+ struct sctp_inpcb *inp = NULL, *inp_decr = NULL;
+ struct sctp_tcb *stcb = NULL;
+ struct sctp_nets *net = NULL;
SCTP_STAT_INCR(sctps_recvdatagrams);
#ifdef SCTP_AUDITING_ENABLED
sctp_audit_log(0xE0, 1);
sctp_auditing(0, inp, stcb, net);
#endif
-
+#if !defined(SCTP_WITH_NO_CSUM)
+ if (compute_crc != 0) {
+ uint32_t check, calc_check;
+
+ check = sh->checksum;
+ sh->checksum = 0;
+ calc_check = sctp_calculate_cksum(m, iphlen);
+ sh->checksum = check;
+ if (calc_check != check) {
+ SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n",
+ calc_check, check, (void *)m, length, iphlen);
+ stcb = sctp_findassociation_addr(m, offset, src, dst,
+ sh, ch, &inp, &net, vrf_id);
+ if ((net != NULL) && (port != 0)) {
+ if (net->port == 0) {
+ sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
+ }
+ net->port = port;
+ }
+ if ((net != NULL) && (use_mflowid != 0)) {
+ net->flowid = mflowid;
+#ifdef INVARIANTS
+ net->flowidset = 1;
+#endif
+ }
+ if ((inp != NULL) && (stcb != NULL)) {
+ sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
+ } else if ((inp != NULL) && (stcb == NULL)) {
+ inp_decr = inp;
+ }
+ SCTP_STAT_INCR(sctps_badsum);
+ SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
+ goto out;
+ }
+ }
+#endif
+ /* Destination port of 0 is illegal, based on RFC4960. */
+ if (sh->dest_port == 0) {
+ SCTP_STAT_INCR(sctps_hdrops);
+ goto out;
+ }
+ stcb = sctp_findassociation_addr(m, offset, src, dst,
+ sh, ch, &inp, &net, vrf_id);
+ if ((net != NULL) && (port != 0)) {
+ if (net->port == 0) {
+ sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
+ }
+ net->port = port;
+ }
+ if ((net != NULL) && (use_mflowid != 0)) {
+ net->flowid = mflowid;
+#ifdef INVARIANTS
+ net->flowidset = 1;
+#endif
+ }
+ if (inp == NULL) {
+ SCTP_STAT_INCR(sctps_noport);
+ if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) {
+ goto out;
+ }
+ if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
+ sctp_send_shutdown_complete2(src, dst, sh,
+ use_mflowid, mflowid,
+ vrf_id, port);
+ goto out;
+ }
+ if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
+ goto out;
+ }
+ if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) {
+ if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
+ ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
+ (ch->chunk_type != SCTP_INIT))) {
+ sctp_send_abort(m, iphlen, src, dst,
+ sh, 0, NULL,
+ use_mflowid, mflowid,
+ vrf_id, port);
+ }
+ }
+ goto out;
+ } else if (stcb == NULL) {
+ inp_decr = inp;
+ }
+#ifdef IPSEC
+ /*-
+ * I very much doubt any of the IPSEC stuff will work but I have no
+ * idea, so I will leave it in place.
+ */
+ if (inp != NULL) {
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (ipsec4_in_reject(m, &inp->ip_inp.inp)) {
+ MODULE_GLOBAL(ipsec4stat).in_polvio++;
+ SCTP_STAT_INCR(sctps_hdrops);
+ goto out;
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (ipsec6_in_reject(m, &inp->ip_inp.inp)) {
+ MODULE_GLOBAL(ipsec6stat).in_polvio++;
+ SCTP_STAT_INCR(sctps_hdrops);
+ goto out;
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+#endif
SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n",
- m, iphlen, offset, length, stcb);
+ (void *)m, iphlen, offset, length, (void *)stcb);
if (stcb) {
/* always clear this before beginning a packet */
stcb->asoc.authenticated = 0;
stcb->asoc.seen_a_sack_this_pkt = 0;
SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n",
- stcb, stcb->asoc.state);
+ (void *)stcb, stcb->asoc.state);
if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) ||
(stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) {
@@ -5490,16 +5733,21 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
* NOT respond to any packet.. its OOTB.
*/
SCTP_TCB_UNLOCK(stcb);
- sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL,
+ stcb = NULL;
+ sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
+ use_mflowid, mflowid,
vrf_id, port);
- goto out_now;
+ goto out;
}
}
if (IS_SCTP_CONTROL(ch)) {
/* process the control portion of the SCTP packet */
/* sa_ignore NO_NULL_CHK */
- stcb = sctp_process_control(m, iphlen, &offset, length, sh, ch,
- inp, stcb, &net, &fwd_tsn_seen, vrf_id, port);
+ stcb = sctp_process_control(m, iphlen, &offset, length,
+ src, dst, sh, ch,
+ inp, stcb, &net, &fwd_tsn_seen,
+ use_mflowid, mflowid,
+ vrf_id, port);
if (stcb) {
/*
* This covers us if the cookie-echo was there and
@@ -5508,7 +5756,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
inp = stcb->sctp_ep;
if ((net) && (port)) {
if (net->port == 0) {
- sctp_pathmtu_adjustment(inp, stcb, net, net->mtu - sizeof(struct udphdr));
+ sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
}
net->port = port;
}
@@ -5529,20 +5777,19 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
/* "silently" ignore */
SCTP_STAT_INCR(sctps_recvauthmissing);
- SCTP_TCB_UNLOCK(stcb);
- goto out_now;
+ goto out;
}
if (stcb == NULL) {
/* out of the blue DATA chunk */
- sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL,
+ sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
+ use_mflowid, mflowid,
vrf_id, port);
- goto out_now;
+ goto out;
}
if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
/* v_tag mismatch! */
SCTP_STAT_INCR(sctps_badvtag);
- SCTP_TCB_UNLOCK(stcb);
- goto out_now;
+ goto out;
}
}
@@ -5552,7 +5799,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
* packet while processing control, or we're done with this
* packet (done or skip rest of data), so we drop it...
*/
- goto out_now;
+ goto out;
}
/*
* DATA chunk processing
@@ -5603,10 +5850,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
/*
* We consider OOTB any data sent during asoc setup.
*/
- sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL,
+ sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
+ use_mflowid, mflowid,
vrf_id, port);
- SCTP_TCB_UNLOCK(stcb);
- goto out_now;
+ goto out;
/* sa_ignore NOTREACHED */
break;
case SCTP_STATE_EMPTY: /* should not happen */
@@ -5614,59 +5861,52 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */
case SCTP_STATE_SHUTDOWN_ACK_SENT:
default:
- SCTP_TCB_UNLOCK(stcb);
- goto out_now;
+ goto out;
/* sa_ignore NOTREACHED */
break;
case SCTP_STATE_OPEN:
case SCTP_STATE_SHUTDOWN_SENT:
break;
}
- /* take care of ECN, part 1. */
- if (stcb->asoc.ecn_allowed &&
- (ecn_bits & (SCTP_ECT0_BIT | SCTP_ECT1_BIT))) {
- sctp_process_ecn_marked_a(stcb, net, ecn_bits);
- }
/* plow through the data chunks while length > offset */
- retval = sctp_process_data(mm, iphlen, &offset, length, sh,
- inp, stcb, net, &high_tsn);
+ retval = sctp_process_data(mm, iphlen, &offset, length,
+ src, dst, sh,
+ inp, stcb, net, &high_tsn,
+ use_mflowid, mflowid,
+ vrf_id, port);
if (retval == 2) {
/*
* The association aborted, NO UNLOCK needed since
* the association is destroyed.
*/
- goto out_now;
+ stcb = NULL;
+ goto out;
}
data_processed = 1;
- if (retval == 0) {
- /* take care of ecn part 2. */
- if (stcb->asoc.ecn_allowed &&
- (ecn_bits & (SCTP_ECT0_BIT | SCTP_ECT1_BIT))) {
- sctp_process_ecn_marked_b(stcb, net, high_tsn,
- ecn_bits);
- }
- }
/*
* Anything important needs to have been m_copy'ed in
* process_data
*/
}
+ /* take care of ecn */
+ if ((data_processed == 1) &&
+ (stcb->asoc.ecn_allowed == 1) &&
+ ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) {
+ /* Yep, we need to add a ECNE */
+ sctp_send_ecn_echo(stcb, net, high_tsn);
+ }
if ((data_processed == 0) && (fwd_tsn_seen)) {
int was_a_gap;
uint32_t highest_tsn;
- if (compare_with_wrap(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) {
highest_tsn = stcb->asoc.highest_tsn_inside_nr_map;
} else {
highest_tsn = stcb->asoc.highest_tsn_inside_map;
}
- was_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN);
+ was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn);
stcb->asoc.send_sack = 1;
- sctp_sack_check(stcb, was_a_gap, &abort_flag);
- if (abort_flag) {
- /* Again, we aborted so NO UNLOCK needed */
- goto out_now;
- }
+ sctp_sack_check(stcb, was_a_gap);
} else if (fwd_tsn_seen) {
stcb->asoc.send_sack = 1;
}
@@ -5682,8 +5922,10 @@ trigger_send:
TAILQ_EMPTY(&stcb->asoc.control_send_queue),
stcb->asoc.total_flight);
un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight);
-
- if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue) ||
+ if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
+ cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq;
+ }
+ if (cnt_ctrl_ready ||
((un_sent) &&
(stcb->asoc.peers_rwnd > 0 ||
(stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
@@ -5695,10 +5937,20 @@ trigger_send:
sctp_audit_log(0xE0, 3);
sctp_auditing(2, inp, stcb, net);
#endif
- SCTP_TCB_UNLOCK(stcb);
-out_now:
+out:
+ if (stcb != NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ if (inp_decr != NULL) {
+ /* reduce ref-count */
+ SCTP_INP_WLOCK(inp_decr);
+ SCTP_INP_DECR_REF(inp_decr);
+ SCTP_INP_WUNLOCK(inp_decr);
+ }
#ifdef INVARIANTS
- sctp_validate_no_locks(inp);
+ if (inp != NULL) {
+ sctp_validate_no_locks(inp);
+ }
#endif
return;
}
@@ -5708,258 +5960,181 @@ static void
sctp_print_mbuf_chain(struct mbuf *m)
{
for (; m; m = SCTP_BUF_NEXT(m)) {
- printf("%p: m_len = %ld\n", m, SCTP_BUF_LEN(m));
+ SCTP_PRINTF("%p: m_len = %ld\n", (void *)m, SCTP_BUF_LEN(m));
if (SCTP_BUF_IS_EXTENDED(m))
- printf("%p: extend_size = %d\n", m, SCTP_BUF_EXTEND_SIZE(m));
+ SCTP_PRINTF("%p: extend_size = %d\n", (void *)m, SCTP_BUF_EXTEND_SIZE(m));
}
}
#endif
+#ifdef INET
void
sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
{
-#ifdef SCTP_MBUF_LOGGING
- struct mbuf *mat;
-
-#endif
struct mbuf *m;
int iphlen;
uint32_t vrf_id = 0;
uint8_t ecn_bits;
+ struct sockaddr_in src, dst;
struct ip *ip;
struct sctphdr *sh;
- struct sctp_inpcb *inp = NULL;
- struct sctp_nets *net;
- struct sctp_tcb *stcb = NULL;
struct sctp_chunkhdr *ch;
- int refcount_up = 0;
- int length, mlen, offset;
+ int length, offset;
#if !defined(SCTP_WITH_NO_CSUM)
- uint32_t check, calc_check;
+ uint8_t compute_crc;
#endif
+ uint32_t mflowid;
+ uint8_t use_mflowid;
+ iphlen = off;
if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
SCTP_RELEASE_PKT(i_pak);
return;
}
- mlen = SCTP_HEADER_LEN(i_pak);
- iphlen = off;
m = SCTP_HEADER_TO_CHAIN(i_pak);
-
- net = NULL;
- SCTP_STAT_INCR(sctps_recvpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
-
-
#ifdef SCTP_MBUF_LOGGING
/* Log in any input mbufs */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
- mat = m;
- while (mat) {
+ struct mbuf *mat;
+
+ for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_INPUT);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(m, mlen);
+#ifdef SCTP_PACKET_LOGGING
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
+ sctp_packet_log(m);
+ }
#endif
- /*
- * Must take out the iphlen, since mlen expects this (only effect lb
- * case)
- */
- mlen -= iphlen;
-
- /*
- * Get IP, SCTP, and first chunk header together in first mbuf.
- */
- ip = mtod(m, struct ip *);
- offset = iphlen + sizeof(*sh) + sizeof(*ch);
+ SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
+ "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
+ m->m_pkthdr.len,
+ if_name(m->m_pkthdr.rcvif),
+ m->m_pkthdr.csum_flags);
+ if (m->m_flags & M_FLOWID) {
+ mflowid = m->m_pkthdr.flowid;
+ use_mflowid = 1;
+ } else {
+ mflowid = 0;
+ use_mflowid = 0;
+ }
+ SCTP_STAT_INCR(sctps_recvpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
+ /* Get IP, SCTP, and first chunk header together in the first mbuf. */
+ offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
if (SCTP_BUF_LEN(m) < offset) {
- if ((m = m_pullup(m, offset)) == 0) {
+ if ((m = m_pullup(m, offset)) == NULL) {
SCTP_STAT_INCR(sctps_hdrops);
return;
}
- ip = mtod(m, struct ip *);
}
- /* validate mbuf chain length with IP payload length */
- if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) {
+ ip = mtod(m, struct ip *);
+ sh = (struct sctphdr *)((caddr_t)ip + iphlen);
+ ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
+ offset -= sizeof(struct sctp_chunkhdr);
+ memset(&src, 0, sizeof(struct sockaddr_in));
+ src.sin_family = AF_INET;
+ src.sin_len = sizeof(struct sockaddr_in);
+ src.sin_port = sh->src_port;
+ src.sin_addr = ip->ip_src;
+ memset(&dst, 0, sizeof(struct sockaddr_in));
+ dst.sin_family = AF_INET;
+ dst.sin_len = sizeof(struct sockaddr_in);
+ dst.sin_port = sh->dest_port;
+ dst.sin_addr = ip->ip_dst;
+ length = ip->ip_len + iphlen;
+ /* Validate mbuf chain length with IP payload length. */
+ if (SCTP_HEADER_LEN(m) != length) {
+ SCTPDBG(SCTP_DEBUG_INPUT1,
+ "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
SCTP_STAT_INCR(sctps_hdrops);
- goto bad;
+ goto out;
}
- sh = (struct sctphdr *)((caddr_t)ip + iphlen);
- ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(*sh));
- SCTPDBG(SCTP_DEBUG_INPUT1,
- "sctp_input() length:%d iphlen:%d\n", mlen, iphlen);
-
/* SCTP does not allow broadcasts or multicasts */
- if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
- goto bad;
+ if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
+ goto out;
}
- if (SCTP_IS_IT_BROADCAST(ip->ip_dst, m)) {
- /*
- * We only look at broadcast if its a front state, All
- * others we will not have a tcb for anyway.
- */
- goto bad;
+ if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) {
+ goto out;
}
- /* validate SCTP checksum */
- SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
- "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
- m->m_pkthdr.len,
- if_name(m->m_pkthdr.rcvif),
- m->m_pkthdr.csum_flags);
+ ecn_bits = ip->ip_tos;
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_recvnocrc);
#else
if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
SCTP_STAT_INCR(sctps_recvhwcrc);
- goto sctp_skip_csum_4;
- }
- check = sh->checksum; /* save incoming checksum */
- sh->checksum = 0; /* prepare for calc */
- calc_check = sctp_calculate_cksum(m, iphlen);
- sh->checksum = check;
- SCTP_STAT_INCR(sctps_recvswcrc);
- if (calc_check != check) {
- SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n",
- calc_check, check, m, mlen, iphlen);
-
- stcb = sctp_findassociation_addr(m, iphlen,
- offset - sizeof(*ch),
- sh, ch, &inp, &net,
- vrf_id);
- if ((net) && (port)) {
- if (net->port == 0) {
- sctp_pathmtu_adjustment(inp, stcb, net, net->mtu - sizeof(struct udphdr));
- }
- net->port = port;
- }
- if ((inp) && (stcb)) {
- sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
- } else if ((inp != NULL) && (stcb == NULL)) {
- refcount_up = 1;
- }
- SCTP_STAT_INCR(sctps_badsum);
- SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
- goto bad;
- }
-sctp_skip_csum_4:
-#endif
- /* destination port of 0 is illegal, based on RFC2960. */
- if (sh->dest_port == 0) {
- SCTP_STAT_INCR(sctps_hdrops);
- goto bad;
- }
- /*
- * Locate pcb and tcb for datagram sctp_findassociation_addr() wants
- * IP/SCTP/first chunk header...
- */
- stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
- sh, ch, &inp, &net, vrf_id);
- if ((net) && (port)) {
- if (net->port == 0) {
- sctp_pathmtu_adjustment(inp, stcb, net, net->mtu - sizeof(struct udphdr));
- }
- net->port = port;
- }
- /* inp's ref-count increased && stcb locked */
- if (inp == NULL) {
- struct sctp_init_chunk *init_chk, chunk_buf;
-
- SCTP_STAT_INCR(sctps_noport);
-#ifdef ICMP_BANDLIM
- /*
- * we use the bandwidth limiting to protect against sending
- * too many ABORTS all at once. In this case these count the
- * same as an ICMP message.
- */
- if (badport_bandlim(0) < 0)
- goto bad;
-#endif /* ICMP_BANDLIM */
- SCTPDBG(SCTP_DEBUG_INPUT1,
- "Sending a ABORT from packet entry!\n");
- if (ch->chunk_type == SCTP_INITIATION) {
- /*
- * we do a trick here to get the INIT tag, dig in
- * and get the tag from the INIT and put it in the
- * common header.
- */
- init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
- iphlen + sizeof(*sh), sizeof(*init_chk),
- (uint8_t *) & chunk_buf);
- if (init_chk != NULL)
- sh->v_tag = init_chk->init.initiate_tag;
- }
- if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
- sctp_send_shutdown_complete2(m, iphlen, sh, vrf_id, port);
- goto bad;
- }
- if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
- goto bad;
- }
- if (ch->chunk_type != SCTP_ABORT_ASSOCIATION)
- sctp_send_abort(m, iphlen, sh, 0, NULL, vrf_id, port);
- goto bad;
- } else if (stcb == NULL) {
- refcount_up = 1;
- }
-#ifdef IPSEC
- /*
- * I very much doubt any of the IPSEC stuff will work but I have no
- * idea, so I will leave it in place.
- */
- if (inp && ipsec4_in_reject(m, &inp->ip_inp.inp)) {
- MODULE_GLOBAL(ipsec4stat).in_polvio++;
- SCTP_STAT_INCR(sctps_hdrops);
- goto bad;
- }
-#endif /* IPSEC */
-
- /*
- * common chunk processing
- */
- length = ip->ip_len + iphlen;
- offset -= sizeof(struct sctp_chunkhdr);
-
- ecn_bits = ip->ip_tos;
-
- /* sa_ignore NO_NULL_CHK */
- sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
- inp, stcb, net, ecn_bits, vrf_id, port);
- /* inp's ref-count reduced && stcb unlocked */
- if (m) {
- sctp_m_freem(m);
- }
- if ((inp) && (refcount_up)) {
- /* reduce ref-count */
- SCTP_INP_DECR_REF(inp);
- }
- return;
-bad:
- if (stcb) {
- SCTP_TCB_UNLOCK(stcb);
- }
- if ((inp) && (refcount_up)) {
- /* reduce ref-count */
- SCTP_INP_DECR_REF(inp);
+ compute_crc = 0;
+ } else {
+ SCTP_STAT_INCR(sctps_recvswcrc);
+ compute_crc = 1;
}
+#endif
+ sctp_common_input_processing(&m, iphlen, offset, length,
+ (struct sockaddr *)&src,
+ (struct sockaddr *)&dst,
+ sh, ch,
+#if !defined(SCTP_WITH_NO_CSUM)
+ compute_crc,
+#endif
+ ecn_bits,
+ use_mflowid, mflowid,
+ vrf_id, port);
+out:
if (m) {
sctp_m_freem(m);
}
return;
}
+
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+extern int *sctp_cpuarry;
+
+#endif
+
void
-sctp_input(i_pak, off)
- struct mbuf *i_pak;
- int off;
+sctp_input(struct mbuf *m, int off)
{
- sctp_input_with_port(i_pak, off, 0);
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+ struct ip *ip;
+ struct sctphdr *sh;
+ int offset;
+ int cpu_to_use;
+ uint32_t flowid, tag;
+
+ if (mp_ncpus > 1) {
+ if (m->m_flags & M_FLOWID) {
+ flowid = m->m_pkthdr.flowid;
+ } else {
+ /*
+ * No flow id built by lower layers fix it so we
+ * create one.
+ */
+ offset = off + sizeof(struct sctphdr);
+ if (SCTP_BUF_LEN(m) < offset) {
+ if ((m = m_pullup(m, offset)) == NULL) {
+ SCTP_STAT_INCR(sctps_hdrops);
+ return;
+ }
+ }
+ ip = mtod(m, struct ip *);
+ sh = (struct sctphdr *)((caddr_t)ip + off);
+ tag = htonl(sh->v_tag);
+ flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port);
+ m->m_pkthdr.flowid = flowid;
+ m->m_flags |= M_FLOWID;
+ }
+ cpu_to_use = sctp_cpuarry[flowid % mp_ncpus];
+ sctp_queue_to_mcore(m, off, cpu_to_use);
+ return;
+ }
+#endif
+ sctp_input_with_port(m, off, 0);
}
+
+#endif
diff --git a/freebsd/sys/netinet/sctp_input.h b/freebsd/sys/netinet/sctp_input.h
index 39f64207..95208032 100644
--- a/freebsd/sys/netinet/sctp_input.h
+++ b/freebsd/sys/netinet/sctp_input.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,30 +30,34 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_input.h,v 1.6 2005/03/06 16:04:17 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_input_h__
-#define __sctp_input_h__
+#ifndef _NETINET_SCTP_INPUT_H_
+#define _NETINET_SCTP_INPUT_H_
#if defined(_KERNEL) || defined(__Userspace__)
void
sctp_common_input_processing(struct mbuf **, int, int, int,
- struct sctphdr *, struct sctp_chunkhdr *, struct sctp_inpcb *,
- struct sctp_tcb *, struct sctp_nets *, uint8_t, uint32_t, uint16_t);
+ struct sockaddr *, struct sockaddr *,
+ struct sctphdr *, struct sctp_chunkhdr *,
+#if !defined(SCTP_WITH_NO_CSUM)
+ uint8_t,
+#endif
+ uint8_t,
+ uint8_t, uint32_t,
+ uint32_t, uint16_t);
struct sctp_stream_reset_out_request *
sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq,
struct sctp_tmit_chunk **bchk);
void
-sctp_reset_in_stream(struct sctp_tcb *stcb, int number_entries,
+sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries,
uint16_t * list);
-int sctp_is_there_unsent_data(struct sctp_tcb *stcb);
+int sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked);
#endif
#endif
diff --git a/freebsd/sys/netinet/sctp_lock_bsd.h b/freebsd/sys/netinet/sctp_lock_bsd.h
index dd9c2ce5..35cdf5f8 100644
--- a/freebsd/sys/netinet/sctp_lock_bsd.h
+++ b/freebsd/sys/netinet/sctp_lock_bsd.h
@@ -1,7 +1,7 @@
-#ifndef __sctp_lock_bsd_h__
-#define __sctp_lock_bsd_h__
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -30,6 +30,12 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifndef _NETINET_SCTP_LOCK_BSD_H_
+#define _NETINET_SCTP_LOCK_BSD_H_
+
/*
* General locking concepts: The goal of our locking is to of course provide
* consistency and yet minimize overhead. We will attempt to use
@@ -68,9 +74,6 @@
* SCTP_INP_INFO_RLOCK() and then when we want to add a new association to
* the SCTP_BASE_INFO() list's we will do a SCTP_INP_INFO_WLOCK().
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
extern struct sctp_foo_stuff sctp_logoff[];
extern int sctp_logoff_stuff;
@@ -97,6 +100,48 @@ extern int sctp_logoff_stuff;
rw_rlock(&SCTP_BASE_INFO(ipi_ep_mtx)); \
} while (0)
+#define SCTP_MCORE_QLOCK_INIT(cpstr) do { \
+ mtx_init(&(cpstr)->que_mtx, \
+ "sctp-mcore_queue","queue_lock", \
+ MTX_DEF|MTX_DUPOK); \
+} while (0)
+
+#define SCTP_MCORE_QLOCK(cpstr) do { \
+ mtx_lock(&(cpstr)->que_mtx); \
+} while (0)
+
+#define SCTP_MCORE_QUNLOCK(cpstr) do { \
+ mtx_unlock(&(cpstr)->que_mtx); \
+} while (0)
+
+#define SCTP_MCORE_QDESTROY(cpstr) do { \
+ if(mtx_owned(&(cpstr)->core_mtx)) { \
+ mtx_unlock(&(cpstr)->que_mtx); \
+ } \
+ mtx_destroy(&(cpstr)->que_mtx); \
+} while (0)
+
+
+#define SCTP_MCORE_LOCK_INIT(cpstr) do { \
+ mtx_init(&(cpstr)->core_mtx, \
+ "sctp-cpulck","cpu_proc_lock", \
+ MTX_DEF|MTX_DUPOK); \
+} while (0)
+
+#define SCTP_MCORE_LOCK(cpstr) do { \
+ mtx_lock(&(cpstr)->core_mtx); \
+} while (0)
+
+#define SCTP_MCORE_UNLOCK(cpstr) do { \
+ mtx_unlock(&(cpstr)->core_mtx); \
+} while (0)
+
+#define SCTP_MCORE_DESTROY(cpstr) do { \
+ if(mtx_owned(&(cpstr)->core_mtx)) { \
+ mtx_unlock(&(cpstr)->core_mtx); \
+ } \
+ mtx_destroy(&(cpstr)->core_mtx); \
+} while (0)
#define SCTP_INP_INFO_WLOCK() do { \
rw_wlock(&SCTP_BASE_INFO(ipi_ep_mtx)); \
diff --git a/freebsd/sys/netinet/sctp_os.h b/freebsd/sys/netinet/sctp_os.h
index fb7c5360..dc6049b6 100644
--- a/freebsd/sys/netinet/sctp_os.h
+++ b/freebsd/sys/netinet/sctp_os.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2006-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -27,10 +29,12 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_os_h__
-#define __sctp_os_h__
+
+#ifndef _NETINET_SCTP_OS_H_
+#define _NETINET_SCTP_OS_H_
/*
* General kernel memory allocation:
diff --git a/freebsd/sys/netinet/sctp_os_bsd.h b/freebsd/sys/netinet/sctp_os_bsd.h
index 991daca2..ca4be706 100644
--- a/freebsd/sys/netinet/sctp_os_bsd.h
+++ b/freebsd/sys/netinet/sctp_os_bsd.h
@@ -1,5 +1,7 @@
/*-
* Copyright (c) 2006-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -27,10 +29,12 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_os_bsd_h__
-#define __sctp_os_bsd_h__
+
+#ifndef _NETINET_SCTP_OS_BSD_H_
+#define _NETINET_SCTP_OS_BSD_H_
/*
* includes
*/
@@ -123,6 +127,7 @@ MALLOC_DECLARE(SCTP_M_TIMW);
MALLOC_DECLARE(SCTP_M_MVRF);
MALLOC_DECLARE(SCTP_M_ITER);
MALLOC_DECLARE(SCTP_M_SOCKOPT);
+MALLOC_DECLARE(SCTP_M_MCORE);
#if defined(SCTP_LOCAL_TRACE_BUF)
@@ -154,12 +159,13 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
*/
#define USER_ADDR_NULL (NULL) /* FIX ME: temp */
+#define SCTP_PRINTF(params...) printf(params)
#if defined(SCTP_DEBUG)
#define SCTPDBG(level, params...) \
{ \
do { \
if (SCTP_BASE_SYSCTL(sctp_debug_on) & level ) { \
- printf(params); \
+ SCTP_PRINTF(params); \
} \
} while (0); \
}
@@ -171,20 +177,10 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
} \
} while (0); \
}
-#define SCTPDBG_PKT(level, iph, sh) \
-{ \
- do { \
- if (SCTP_BASE_SYSCTL(sctp_debug_on) & level) { \
- sctp_print_address_pkt(iph, sh); \
- } \
- } while (0); \
-}
#else
#define SCTPDBG(level, params...)
#define SCTPDBG_ADDR(level, addr)
-#define SCTPDBG_PKT(level, iph, sh)
#endif
-#define SCTP_PRINTF(params...) printf(params)
#ifdef SCTP_LTRACE_CHUNKS
#define SCTP_LTRACE_CHK(a, b, c, d) if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LTRACE_CHUNK_ENABLE) SCTP_CTR6(KTR_SUBSYS, "SCTP:%d[%d]:%x-%x-%x-%x", SCTP_LOG_CHUNK_PROC, 0, a, b, c, d)
@@ -193,12 +189,14 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
#endif
#ifdef SCTP_LTRACE_ERRORS
-#define SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, file, err) if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LTRACE_ERROR_ENABLE) \
- printf("mbuf:%p inp:%p stcb:%p net:%p file:%x line:%d error:%d\n", \
- m, inp, stcb, net, file, __LINE__, err);
-#define SCTP_LTRACE_ERR_RET(inp, stcb, net, file, err) if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LTRACE_ERROR_ENABLE) \
- printf("inp:%p stcb:%p net:%p file:%x line:%d error:%d\n", \
- inp, stcb, net, file, __LINE__, err);
+#define SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, file, err) \
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LTRACE_ERROR_ENABLE) \
+ SCTP_PRINTF("mbuf:%p inp:%p stcb:%p net:%p file:%x line:%d error:%d\n", \
+ m, inp, stcb, net, file, __LINE__, err);
+#define SCTP_LTRACE_ERR_RET(inp, stcb, net, file, err) \
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LTRACE_ERROR_ENABLE) \
+ SCTP_PRINTF("inp:%p stcb:%p net:%p file:%x line:%d error:%d\n", \
+ inp, stcb, net, file, __LINE__, err);
#else
#define SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, file, err)
#define SCTP_LTRACE_ERR_RET(inp, stcb, net, file, err)
@@ -358,7 +356,7 @@ typedef struct callout sctp_os_timer_t;
*/
#define SCTP_HEADER_TO_CHAIN(m) (m)
#define SCTP_DETACH_HEADER_FROM_CHAIN(m)
-#define SCTP_HEADER_LEN(m) (m->m_pkthdr.len)
+#define SCTP_HEADER_LEN(m) ((m)->m_pkthdr.len)
#define SCTP_GET_HEADER_FOR_OUTPUT(o_pak) 0
#define SCTP_RELEASE_HEADER(m)
#define SCTP_RELEASE_PKT(m) sctp_m_freem(m)
@@ -387,10 +385,6 @@ typedef struct callout sctp_os_timer_t;
* its a NOP.
*/
-/* Macro's for getting length from V6/V4 header */
-#define SCTP_GET_IPV4_LENGTH(iph) (iph->ip_len)
-#define SCTP_GET_IPV6_LENGTH(ip6) (ntohs(ip6->ip6_plen))
-
/* get the v6 hop limit */
#define SCTP_GET_HLIM(inp, ro) in6_selecthlim((struct in6pcb *)&inp->ip_inp.inp, (ro ? (ro->ro_rt ? (ro->ro_rt->rt_ifp) : (NULL)) : (NULL)));
@@ -421,6 +415,12 @@ typedef struct callout sctp_os_timer_t;
typedef struct route sctp_route_t;
typedef struct rtentry sctp_rtentry_t;
+/*
+ * XXX multi-FIB support was backed out in r179783 and it seems clear that the
+ * VRF support as currently in FreeBSD is not ready to support multi-FIB.
+ * It might be best to implement multi-FIB support for both v4 and v6 indepedent
+ * of VRFs and leave those to a real MPLS stack.
+ */
#define SCTP_RTALLOC(ro, vrf_id) rtalloc_ign((struct route *)ro, 0UL)
/* Future zero copy wakeup/send function */
diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c
index 648a87a2..30c6f3c0 100644
--- a/freebsd/sys/netinet/sctp_output.c
+++ b/freebsd/sys/netinet/sctp_output.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,8 +32,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_input.h>
#include <netinet/sctp_crc32.h>
#include <netinet/udp.h>
+#include <netinet/udp_var.h>
#include <machine/in_cksum.h>
@@ -1864,15 +1865,10 @@ struct sack_track sack_array[256] = {
int
sctp_is_address_in_scope(struct sctp_ifa *ifa,
- int ipv4_addr_legal,
- int ipv6_addr_legal,
- int loopback_scope,
- int ipv4_local_scope,
- int local_scope,
- int site_scope,
+ struct sctp_scoping *scope,
int do_update)
{
- if ((loopback_scope == 0) &&
+ if ((scope->loopback_scope == 0) &&
(ifa->ifn_p) && SCTP_IFN_IS_IFT_LOOP(ifa->ifn_p)) {
/*
* skip loopback if not in scope *
@@ -1880,8 +1876,9 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa,
return (0);
}
switch (ifa->address.sa.sa_family) {
+#ifdef INET
case AF_INET:
- if (ipv4_addr_legal) {
+ if (scope->ipv4_addr_legal) {
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&ifa->address.sin;
@@ -1889,7 +1886,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa,
/* not in scope , unspecified */
return (0);
}
- if ((ipv4_local_scope == 0) &&
+ if ((scope->ipv4_local_scope == 0) &&
(IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
/* private address not in scope */
return (0);
@@ -1898,9 +1895,10 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa,
return (0);
}
break;
+#endif
#ifdef INET6
case AF_INET6:
- if (ipv6_addr_legal) {
+ if (scope->ipv6_addr_legal) {
struct sockaddr_in6 *sin6;
/*
@@ -1923,7 +1921,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa,
(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
return (0);
}
- if ((site_scope == 0) &&
+ if ((scope->site_scope == 0) &&
(IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
return (0);
}
@@ -1939,21 +1937,27 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa,
}
static struct mbuf *
-sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa)
+sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t * len)
{
struct sctp_paramhdr *parmh;
struct mbuf *mret;
- int len;
+ uint16_t plen;
- if (ifa->address.sa.sa_family == AF_INET) {
- len = sizeof(struct sctp_ipv4addr_param);
- } else if (ifa->address.sa.sa_family == AF_INET6) {
- len = sizeof(struct sctp_ipv6addr_param);
- } else {
- /* unknown type */
+ switch (ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ plen = (uint16_t) sizeof(struct sctp_ipv4addr_param);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ plen = (uint16_t) sizeof(struct sctp_ipv6addr_param);
+ break;
+#endif
+ default:
return (m);
}
- if (M_TRAILINGSPACE(m) >= len) {
+ if (M_TRAILINGSPACE(m) >= plen) {
/* easy side we just drop it on the end */
parmh = (struct sctp_paramhdr *)(SCTP_BUF_AT(m, SCTP_BUF_LEN(m)));
mret = m;
@@ -1963,7 +1967,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa)
while (SCTP_BUF_NEXT(mret) != NULL) {
mret = SCTP_BUF_NEXT(mret);
}
- SCTP_BUF_NEXT(mret) = sctp_get_mbuf_for_msg(len, 0, M_DONTWAIT, 1, MT_DATA);
+ SCTP_BUF_NEXT(mret) = sctp_get_mbuf_for_msg(plen, 0, M_NOWAIT, 1, MT_DATA);
if (SCTP_BUF_NEXT(mret) == NULL) {
/* We are hosed, can't add more addresses */
return (m);
@@ -1973,6 +1977,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa)
}
/* now add the parameter */
switch (ifa->address.sa.sa_family) {
+#ifdef INET
case AF_INET:
{
struct sctp_ipv4addr_param *ipv4p;
@@ -1981,11 +1986,12 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa)
sin = (struct sockaddr_in *)&ifa->address.sin;
ipv4p = (struct sctp_ipv4addr_param *)parmh;
parmh->param_type = htons(SCTP_IPV4_ADDRESS);
- parmh->param_length = htons(len);
+ parmh->param_length = htons(plen);
ipv4p->addr = sin->sin_addr.s_addr;
- SCTP_BUF_LEN(mret) += len;
+ SCTP_BUF_LEN(mret) += plen;
break;
}
+#endif
#ifdef INET6
case AF_INET6:
{
@@ -1995,25 +2001,30 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa)
sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
ipv6p = (struct sctp_ipv6addr_param *)parmh;
parmh->param_type = htons(SCTP_IPV6_ADDRESS);
- parmh->param_length = htons(len);
+ parmh->param_length = htons(plen);
memcpy(ipv6p->addr, &sin6->sin6_addr,
sizeof(ipv6p->addr));
/* clear embedded scope in the address */
in6_clearscope((struct in6_addr *)ipv6p->addr);
- SCTP_BUF_LEN(mret) += len;
+ SCTP_BUF_LEN(mret) += plen;
break;
}
#endif
default:
return (m);
}
+ if (len != NULL) {
+ *len += plen;
+ }
return (mret);
}
struct mbuf *
-sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_scoping *scope,
- struct mbuf *m_at, int cnt_inits_to)
+sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
+ struct sctp_scoping *scope,
+ struct mbuf *m_at, int cnt_inits_to,
+ uint16_t * padding_len, uint16_t * chunk_len)
{
struct sctp_vrf *vrf = NULL;
int cnt, limit_out = 0, total_count;
@@ -2046,13 +2057,10 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_scoping *scope,
continue;
}
LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
- if (sctp_is_address_in_scope(sctp_ifap,
- scope->ipv4_addr_legal,
- scope->ipv6_addr_legal,
- scope->loopback_scope,
- scope->ipv4_local_scope,
- scope->local_scope,
- scope->site_scope, 1) == 0) {
+ if (sctp_is_addr_restricted(stcb, sctp_ifap)) {
+ continue;
+ }
+ if (sctp_is_address_in_scope(sctp_ifap, scope, 1) == 0) {
continue;
}
cnt++;
@@ -2078,16 +2086,22 @@ skip_count:
continue;
}
LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
+ if (sctp_is_addr_restricted(stcb, sctp_ifap)) {
+ continue;
+ }
if (sctp_is_address_in_scope(sctp_ifap,
- scope->ipv4_addr_legal,
- scope->ipv6_addr_legal,
- scope->loopback_scope,
- scope->ipv4_local_scope,
- scope->local_scope,
- scope->site_scope, 0) == 0) {
+ scope, 0) == 0) {
continue;
}
- m_at = sctp_add_addr_to_mbuf(m_at, sctp_ifap);
+ if ((chunk_len != NULL) &&
+ (padding_len != NULL) &&
+ (*padding_len > 0)) {
+ memset(mtod(m_at, caddr_t)+*chunk_len, 0, *padding_len);
+ SCTP_BUF_LEN(m_at) += *padding_len;
+ *chunk_len += *padding_len;
+ *padding_len = 0;
+ }
+ m_at = sctp_add_addr_to_mbuf(m_at, sctp_ifap, chunk_len);
if (limit_out) {
cnt++;
total_count++;
@@ -2129,43 +2143,38 @@ skip_count:
continue;
}
if (sctp_is_address_in_scope(laddr->ifa,
- scope->ipv4_addr_legal,
- scope->ipv6_addr_legal,
- scope->loopback_scope,
- scope->ipv4_local_scope,
- scope->local_scope,
- scope->site_scope, 1) == 0) {
+ scope, 1) == 0) {
continue;
}
cnt++;
}
- if (cnt > SCTP_ADDRESS_LIMIT) {
- limit_out = 1;
- }
/*
* To get through a NAT we only list addresses if we have
* more than one. That way if you just bind a single address
* we let the source of the init dictate our address.
*/
if (cnt > 1) {
+ cnt = cnt_inits_to;
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
- cnt = 0;
if (laddr->ifa == NULL) {
continue;
}
- if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
+ if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
continue;
-
+ }
if (sctp_is_address_in_scope(laddr->ifa,
- scope->ipv4_addr_legal,
- scope->ipv6_addr_legal,
- scope->loopback_scope,
- scope->ipv4_local_scope,
- scope->local_scope,
- scope->site_scope, 0) == 0) {
+ scope, 0) == 0) {
continue;
}
- m_at = sctp_add_addr_to_mbuf(m_at, laddr->ifa);
+ if ((chunk_len != NULL) &&
+ (padding_len != NULL) &&
+ (*padding_len > 0)) {
+ memset(mtod(m_at, caddr_t)+*chunk_len, 0, *padding_len);
+ SCTP_BUF_LEN(m_at) += *padding_len;
+ *chunk_len += *padding_len;
+ *padding_len = 0;
+ }
+ m_at = sctp_add_addr_to_mbuf(m_at, laddr->ifa, chunk_len);
cnt++;
if (cnt >= SCTP_ADDRESS_LIMIT) {
break;
@@ -2193,26 +2202,26 @@ sctp_is_ifa_addr_preferred(struct sctp_ifa *ifa,
* means it is the same scope or higher scope then the destination.
* L = loopback, P = private, G = global
* -----------------------------------------
- * src | dest | result
- * ----------------------------------------
- * L | L | yes
- * -----------------------------------------
- * P | L | yes-v4 no-v6
- * -----------------------------------------
- * G | L | yes-v4 no-v6
- * -----------------------------------------
- * L | P | no
- * -----------------------------------------
- * P | P | yes
- * -----------------------------------------
- * G | P | no
- * -----------------------------------------
- * L | G | no
- * -----------------------------------------
- * P | G | no
- * -----------------------------------------
- * G | G | yes
- * -----------------------------------------
+ * src | dest | result
+ * ----------------------------------------
+ * L | L | yes
+ * -----------------------------------------
+ * P | L | yes-v4 no-v6
+ * -----------------------------------------
+ * G | L | yes-v4 no-v6
+ * -----------------------------------------
+ * L | P | no
+ * -----------------------------------------
+ * P | P | yes
+ * -----------------------------------------
+ * G | P | no
+ * -----------------------------------------
+ * L | G | no
+ * -----------------------------------------
+ * P | G | no
+ * -----------------------------------------
+ * G | G | yes
+ * -----------------------------------------
*/
if (ifa->address.sa.sa_family != fam) {
@@ -2225,6 +2234,7 @@ sctp_is_ifa_addr_preferred(struct sctp_ifa *ifa,
SCTPDBG(SCTP_DEBUG_OUTPUT2, "Is destination preferred:");
SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, &ifa->address.sa);
/* Ok the address may be ok */
+#ifdef INET6
if (fam == AF_INET6) {
/* ok to use deprecated addresses? no lets not! */
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
@@ -2244,6 +2254,7 @@ sctp_is_ifa_addr_preferred(struct sctp_ifa *ifa,
}
}
}
+#endif
/*
* Now that we know what is what, implement or table this could in
* theory be done slicker (it used to be), but this is
@@ -2283,35 +2294,50 @@ sctp_is_ifa_addr_acceptable(struct sctp_ifa *ifa,
{
uint8_t dest_is_global = 0;
- /*
+ /**
* Here we determine if its a acceptable address. A acceptable
* address means it is the same scope or higher scope but we can
* allow for NAT which means its ok to have a global dest and a
* private src.
*
* L = loopback, P = private, G = global
- * ----------------------------------------- src | dest | result
- * ----------------------------------------- L | L | yes
- * ----------------------------------------- P | L |
- * yes-v4 no-v6 ----------------------------------------- G |
- * L | yes ----------------------------------------- L |
- * P | no ----------------------------------------- P | P
- * | yes ----------------------------------------- G | P
- * | yes - May not work -----------------------------------------
- * L | G | no ----------------------------------------- P
- * | G | yes - May not work
- * ----------------------------------------- G | G | yes
+ * -----------------------------------------
+ * src | dest | result
+ * -----------------------------------------
+ * L | L | yes
+ * -----------------------------------------
+ * P | L | yes-v4 no-v6
+ * -----------------------------------------
+ * G | L | yes
+ * -----------------------------------------
+ * L | P | no
+ * -----------------------------------------
+ * P | P | yes
+ * -----------------------------------------
+ * G | P | yes - May not work
+ * -----------------------------------------
+ * L | G | no
+ * -----------------------------------------
+ * P | G | yes - May not work
+ * -----------------------------------------
+ * G | G | yes
* -----------------------------------------
*/
if (ifa->address.sa.sa_family != fam) {
/* forget non matching family */
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "ifa_fam:%d fam:%d\n",
+ ifa->address.sa.sa_family, fam);
return (NULL);
}
/* Ok the address may be ok */
+ SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, &ifa->address.sa);
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "dst_is_loop:%d dest_is_priv:%d\n",
+ dest_is_loop, dest_is_priv);
if ((dest_is_loop == 0) && (dest_is_priv == 0)) {
dest_is_global = 1;
}
+#ifdef INET6
if (fam == AF_INET6) {
/* ok to use deprecated addresses? */
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
@@ -2323,17 +2349,25 @@ sctp_is_ifa_addr_acceptable(struct sctp_ifa *ifa,
return (NULL);
}
}
+#endif
/*
* Now that we know what is what, implement our table. This could in
* theory be done slicker (it used to be), but this is
* straightforward and easier to validate :-)
*/
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "ifa->src_is_loop:%d dest_is_priv:%d\n",
+ ifa->src_is_loop,
+ dest_is_priv);
if ((ifa->src_is_loop == 1) && (dest_is_priv)) {
return (NULL);
}
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "ifa->src_is_loop:%d dest_is_glob:%d\n",
+ ifa->src_is_loop,
+ dest_is_global);
if ((ifa->src_is_loop == 1) && (dest_is_global)) {
return (NULL);
}
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "address is acceptable\n");
/* its an acceptable address */
return (ifa);
}
@@ -2504,7 +2538,6 @@ once_again_too:
static struct sctp_ifa *
sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
- struct sctp_nets *net,
sctp_route_t * ro,
uint32_t vrf_id,
uint8_t dest_is_priv,
@@ -2734,6 +2767,7 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn,
}
}
#endif
+#ifdef INET
/* Avoid topologically incorrect IPv4 address */
if (stcb && fam == AF_INET &&
sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_BASE)) {
@@ -2741,14 +2775,9 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn,
continue;
}
}
+#endif
if (stcb) {
- if (sctp_is_address_in_scope(ifa,
- stcb->asoc.ipv4_addr_legal,
- stcb->asoc.ipv6_addr_legal,
- stcb->asoc.loopback_scope,
- stcb->asoc.ipv4_local_scope,
- stcb->asoc.local_scope,
- stcb->asoc.site_scope, 0) == 0) {
+ if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) {
continue;
}
if (((non_asoc_addr_ok == 0) &&
@@ -2794,13 +2823,7 @@ sctp_count_num_preferred_boundall(struct sctp_ifn *ifn,
continue;
}
if (stcb) {
- if (sctp_is_address_in_scope(ifa,
- stcb->asoc.ipv4_addr_legal,
- stcb->asoc.ipv6_addr_legal,
- stcb->asoc.loopback_scope,
- stcb->asoc.ipv4_local_scope,
- stcb->asoc.local_scope,
- stcb->asoc.site_scope, 0) == 0) {
+ if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) {
continue;
}
if (((non_asoc_addr_ok == 0) &&
@@ -2821,8 +2844,7 @@ sctp_count_num_preferred_boundall(struct sctp_ifn *ifn,
}
static struct sctp_ifa *
-sctp_choose_boundall(struct sctp_inpcb *inp,
- struct sctp_tcb *stcb,
+sctp_choose_boundall(struct sctp_tcb *stcb,
struct sctp_nets *net,
sctp_route_t * ro,
uint32_t vrf_id,
@@ -2838,6 +2860,11 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
uint32_t ifn_index;
struct sctp_vrf *vrf;
+#ifdef INET
+ int retried = 0;
+
+#endif
+
/*-
* For boundall we can use any address in the association.
* If non_asoc_addr_ok is set we can use any address (at least in
@@ -2858,6 +2885,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
ifn = SCTP_GET_IFN_VOID_FROM_ROUTE(ro);
ifn_index = SCTP_GET_IF_INDEX_FROM_ROUTE(ro);
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "ifn from route:%p ifn_index:%d\n", ifn, ifn_index);
emit_ifn = looked_at = sctp_ifn = sctp_find_ifn(ifn, ifn_index);
if (sctp_ifn == NULL) {
/* ?? We don't have this guy ?? */
@@ -2941,7 +2969,7 @@ bound_all_plan_b:
}
SCTPDBG(SCTP_DEBUG_OUTPUT2,
"num preferred:%d on interface:%p cur_addr_num:%d\n",
- num_preferred, sctp_ifn, cur_addr_num);
+ num_preferred, (void *)sctp_ifn, cur_addr_num);
/*
* Ok we have num_eligible_addr set with how many we can
@@ -2966,30 +2994,34 @@ bound_all_plan_b:
}
atomic_add_int(&sifa->refcount, 1);
return (sifa);
-
}
-
+#ifdef INET
+again_with_private_addresses_allowed:
+#endif
/* plan_c: do we have an acceptable address on the emit interface */
+ sifa = NULL;
SCTPDBG(SCTP_DEBUG_OUTPUT2, "Trying Plan C: find acceptable on interface\n");
if (emit_ifn == NULL) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "Jump to Plan D - no emit_ifn\n");
goto plan_d;
}
LIST_FOREACH(sctp_ifa, &emit_ifn->ifalist, next_ifa) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "ifa:%p\n", (void *)sctp_ifa);
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
- (non_asoc_addr_ok == 0))
+ (non_asoc_addr_ok == 0)) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "Defer\n");
continue;
+ }
sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop,
dest_is_priv, fam);
- if (sifa == NULL)
+ if (sifa == NULL) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "IFA not acceptable\n");
continue;
+ }
if (stcb) {
- if (sctp_is_address_in_scope(sifa,
- stcb->asoc.ipv4_addr_legal,
- stcb->asoc.ipv6_addr_legal,
- stcb->asoc.loopback_scope,
- stcb->asoc.ipv4_local_scope,
- stcb->asoc.local_scope,
- stcb->asoc.site_scope, 0) == 0) {
+ if (sctp_is_address_in_scope(sifa, &stcb->asoc.scope, 0) == 0) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "NOT in scope\n");
+ sifa = NULL;
continue;
}
if (((non_asoc_addr_ok == 0) &&
@@ -3001,11 +3033,15 @@ bound_all_plan_b:
* It is restricted for some reason..
* probably not yet added.
*/
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "Its resticted\n");
+ sifa = NULL;
continue;
}
+ } else {
+ SCTP_PRINTF("Stcb is null - no print\n");
}
atomic_add_int(&sifa->refcount, 1);
- return (sifa);
+ goto out;
}
plan_d:
/*
@@ -3014,16 +3050,12 @@ plan_d:
* out and see if we can find an acceptable address somewhere
* amongst all interfaces.
*/
- SCTPDBG(SCTP_DEBUG_OUTPUT2, "Trying Plan D\n");
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "Trying Plan D looked_at is %p\n", (void *)looked_at);
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
if (dest_is_loop == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
/* wrong base scope */
continue;
}
- if ((sctp_ifn == looked_at) && looked_at)
- /* already looked at this guy */
- continue;
-
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
(non_asoc_addr_ok == 0))
@@ -3034,13 +3066,8 @@ plan_d:
if (sifa == NULL)
continue;
if (stcb) {
- if (sctp_is_address_in_scope(sifa,
- stcb->asoc.ipv4_addr_legal,
- stcb->asoc.ipv6_addr_legal,
- stcb->asoc.loopback_scope,
- stcb->asoc.ipv4_local_scope,
- stcb->asoc.local_scope,
- stcb->asoc.site_scope, 0) == 0) {
+ if (sctp_is_address_in_scope(sifa, &stcb->asoc.scope, 0) == 0) {
+ sifa = NULL;
continue;
}
if (((non_asoc_addr_ok == 0) &&
@@ -3052,19 +3079,76 @@ plan_d:
* It is restricted for some
* reason.. probably not yet added.
*/
+ sifa = NULL;
continue;
}
}
- atomic_add_int(&sifa->refcount, 1);
- return (sifa);
+ goto out;
}
}
- /*
- * Ok we can find NO address to source from that is not on our
- * restricted list and non_asoc_address is NOT ok, or it is on our
- * restricted list. We can't source to it :-(
- */
- return (NULL);
+#ifdef INET
+ if ((retried == 0) && (stcb->asoc.scope.ipv4_local_scope == 0)) {
+ stcb->asoc.scope.ipv4_local_scope = 1;
+ retried = 1;
+ goto again_with_private_addresses_allowed;
+ } else if (retried == 1) {
+ stcb->asoc.scope.ipv4_local_scope = 0;
+ }
+#endif
+out:
+#ifdef INET
+ if (sifa) {
+ if (retried == 1) {
+ LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
+ if (dest_is_loop == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
+ /* wrong base scope */
+ continue;
+ }
+ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
+ struct sctp_ifa *tmp_sifa;
+
+ if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
+ (non_asoc_addr_ok == 0))
+ continue;
+ tmp_sifa = sctp_is_ifa_addr_acceptable(sctp_ifa,
+ dest_is_loop,
+ dest_is_priv, fam);
+ if (tmp_sifa == NULL) {
+ continue;
+ }
+ if (tmp_sifa == sifa) {
+ continue;
+ }
+ if (stcb) {
+ if (sctp_is_address_in_scope(tmp_sifa,
+ &stcb->asoc.scope, 0) == 0) {
+ continue;
+ }
+ if (((non_asoc_addr_ok == 0) &&
+ (sctp_is_addr_restricted(stcb, tmp_sifa))) ||
+ (non_asoc_addr_ok &&
+ (sctp_is_addr_restricted(stcb, tmp_sifa)) &&
+ (!sctp_is_addr_pending(stcb, tmp_sifa)))) {
+ /*
+ * It is restricted
+ * for some reason..
+ * probably not yet
+ * added.
+ */
+ continue;
+ }
+ }
+ if ((tmp_sifa->address.sin.sin_family == AF_INET) &&
+ (IN4_ISPRIVATE_ADDRESS(&(tmp_sifa->address.sin.sin_addr)))) {
+ sctp_add_local_addr_restricted(stcb, tmp_sifa);
+ }
+ }
+ }
+ }
+ atomic_add_int(&sifa->refcount, 1);
+ }
+#endif
+ return (sifa);
}
@@ -3077,17 +3161,20 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
struct sctp_nets *net,
int non_asoc_addr_ok, uint32_t vrf_id)
{
+ struct sctp_ifa *answer;
+ uint8_t dest_is_priv, dest_is_loop;
+ sa_family_t fam;
+
+#ifdef INET
struct sockaddr_in *to = (struct sockaddr_in *)&ro->ro_dst;
+#endif
#ifdef INET6
struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&ro->ro_dst;
#endif
- struct sctp_ifa *answer;
- uint8_t dest_is_priv, dest_is_loop;
- sa_family_t fam;
- /*-
+ /**
* Rules: - Find the route if needed, cache if I can. - Look at
* interface address in route, Is it in the bound list. If so we
* have the best source. - If not we must rotate amongst the
@@ -3158,10 +3245,11 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
if (ro->ro_rt == NULL) {
return (NULL);
}
- fam = to->sin_family;
+ fam = ro->ro_dst.sa_family;
dest_is_priv = dest_is_loop = 0;
/* Setup our scopes for the destination */
switch (fam) {
+#ifdef INET
case AF_INET:
/* Scope based on outbound address */
if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
@@ -3174,6 +3262,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
dest_is_priv = 1;
}
break;
+#endif
#ifdef INET6
case AF_INET6:
/* Scope based on outbound address */
@@ -3197,13 +3286,13 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
#endif
}
SCTPDBG(SCTP_DEBUG_OUTPUT2, "Select source addr for:");
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)to);
+ SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&ro->ro_dst);
SCTP_IPI_ADDR_RLOCK();
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
/*
* Bound all case
*/
- answer = sctp_choose_boundall(inp, stcb, net, ro, vrf_id,
+ answer = sctp_choose_boundall(stcb, net, ro, vrf_id,
dest_is_priv, dest_is_loop,
non_asoc_addr_ok, fam);
SCTP_IPI_ADDR_RUNLOCK();
@@ -3213,7 +3302,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
* Subset bound case
*/
if (stcb) {
- answer = sctp_choose_boundspecific_stcb(inp, stcb, net, ro,
+ answer = sctp_choose_boundspecific_stcb(inp, stcb, ro,
vrf_id, dest_is_priv,
dest_is_loop,
non_asoc_addr_ok, fam);
@@ -3228,56 +3317,344 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
}
static int
-sctp_find_cmsg(int c_type, void *data, struct mbuf *control, int cpsize)
+sctp_find_cmsg(int c_type, void *data, struct mbuf *control, size_t cpsize)
{
struct cmsghdr cmh;
- int tlen, at;
+ int tlen, at, found;
+ struct sctp_sndinfo sndinfo;
+ struct sctp_prinfo prinfo;
+ struct sctp_authinfo authinfo;
tlen = SCTP_BUF_LEN(control);
at = 0;
+ found = 0;
/*
* Independent of how many mbufs, find the c_type inside the control
* structure and copy out the data.
*/
while (at < tlen) {
if ((tlen - at) < (int)CMSG_ALIGN(sizeof(cmh))) {
- /* not enough room for one more we are done. */
- return (0);
+ /* There is not enough room for one more. */
+ return (found);
}
m_copydata(control, at, sizeof(cmh), (caddr_t)&cmh);
+ if (cmh.cmsg_len < CMSG_ALIGN(sizeof(cmh))) {
+ /* We dont't have a complete CMSG header. */
+ return (found);
+ }
if (((int)cmh.cmsg_len + at) > tlen) {
- /*
- * this is real messed up since there is not enough
- * data here to cover the cmsg header. We are done.
- */
- return (0);
+ /* We don't have the complete CMSG. */
+ return (found);
}
if ((cmh.cmsg_level == IPPROTO_SCTP) &&
- (c_type == cmh.cmsg_type)) {
- /* found the one we want, copy it out */
- at += CMSG_ALIGN(sizeof(struct cmsghdr));
- if ((int)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < cpsize) {
- /*
- * space of cmsg_len after header not big
- * enough
- */
- return (0);
+ ((c_type == cmh.cmsg_type) ||
+ ((c_type == SCTP_SNDRCV) &&
+ ((cmh.cmsg_type == SCTP_SNDINFO) ||
+ (cmh.cmsg_type == SCTP_PRINFO) ||
+ (cmh.cmsg_type == SCTP_AUTHINFO))))) {
+ if (c_type == cmh.cmsg_type) {
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < cpsize) {
+ return (found);
+ }
+ /* It is exactly what we want. Copy it out. */
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), cpsize, (caddr_t)data);
+ return (1);
+ } else {
+ struct sctp_sndrcvinfo *sndrcvinfo;
+
+ sndrcvinfo = (struct sctp_sndrcvinfo *)data;
+ if (found == 0) {
+ if (cpsize < sizeof(struct sctp_sndrcvinfo)) {
+ return (found);
+ }
+ memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
+ }
+ switch (cmh.cmsg_type) {
+ case SCTP_SNDINFO:
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_sndinfo)) {
+ return (found);
+ }
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_sndinfo), (caddr_t)&sndinfo);
+ sndrcvinfo->sinfo_stream = sndinfo.snd_sid;
+ sndrcvinfo->sinfo_flags = sndinfo.snd_flags;
+ sndrcvinfo->sinfo_ppid = sndinfo.snd_ppid;
+ sndrcvinfo->sinfo_context = sndinfo.snd_context;
+ sndrcvinfo->sinfo_assoc_id = sndinfo.snd_assoc_id;
+ break;
+ case SCTP_PRINFO:
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_prinfo)) {
+ return (found);
+ }
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_prinfo), (caddr_t)&prinfo);
+ sndrcvinfo->sinfo_timetolive = prinfo.pr_value;
+ sndrcvinfo->sinfo_flags |= prinfo.pr_policy;
+ break;
+ case SCTP_AUTHINFO:
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_authinfo)) {
+ return (found);
+ }
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_authinfo), (caddr_t)&authinfo);
+ sndrcvinfo->sinfo_keynumber_valid = 1;
+ sndrcvinfo->sinfo_keynumber = authinfo.auth_keynumber;
+ break;
+ default:
+ return (found);
+ }
+ found = 1;
}
- m_copydata(control, at, cpsize, data);
+ }
+ at += CMSG_ALIGN(cmh.cmsg_len);
+ }
+ return (found);
+}
+
+static int
+sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *error)
+{
+ struct cmsghdr cmh;
+ int tlen, at;
+ struct sctp_initmsg initmsg;
+
+#ifdef INET
+ struct sockaddr_in sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+
+#endif
+
+ tlen = SCTP_BUF_LEN(control);
+ at = 0;
+ while (at < tlen) {
+ if ((tlen - at) < (int)CMSG_ALIGN(sizeof(cmh))) {
+ /* There is not enough room for one more. */
+ *error = EINVAL;
return (1);
- } else {
- at += CMSG_ALIGN(cmh.cmsg_len);
- if (cmh.cmsg_len == 0) {
+ }
+ m_copydata(control, at, sizeof(cmh), (caddr_t)&cmh);
+ if (cmh.cmsg_len < CMSG_ALIGN(sizeof(cmh))) {
+ /* We dont't have a complete CMSG header. */
+ *error = EINVAL;
+ return (1);
+ }
+ if (((int)cmh.cmsg_len + at) > tlen) {
+ /* We don't have the complete CMSG. */
+ *error = EINVAL;
+ return (1);
+ }
+ if (cmh.cmsg_level == IPPROTO_SCTP) {
+ switch (cmh.cmsg_type) {
+ case SCTP_INIT:
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_initmsg)) {
+ *error = EINVAL;
+ return (1);
+ }
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_initmsg), (caddr_t)&initmsg);
+ if (initmsg.sinit_max_attempts)
+ stcb->asoc.max_init_times = initmsg.sinit_max_attempts;
+ if (initmsg.sinit_num_ostreams)
+ stcb->asoc.pre_open_streams = initmsg.sinit_num_ostreams;
+ if (initmsg.sinit_max_instreams)
+ stcb->asoc.max_inbound_streams = initmsg.sinit_max_instreams;
+ if (initmsg.sinit_max_init_timeo)
+ stcb->asoc.initial_init_rto_max = initmsg.sinit_max_init_timeo;
+ if (stcb->asoc.streamoutcnt < stcb->asoc.pre_open_streams) {
+ struct sctp_stream_out *tmp_str;
+ unsigned int i;
+
+ /* Default is NOT correct */
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "Ok, default:%d pre_open:%d\n",
+ stcb->asoc.streamoutcnt, stcb->asoc.pre_open_streams);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_MALLOC(tmp_str,
+ struct sctp_stream_out *,
+ (stcb->asoc.pre_open_streams * sizeof(struct sctp_stream_out)),
+ SCTP_M_STRMO);
+ SCTP_TCB_LOCK(stcb);
+ if (tmp_str != NULL) {
+ SCTP_FREE(stcb->asoc.strmout, SCTP_M_STRMO);
+ stcb->asoc.strmout = tmp_str;
+ stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt = stcb->asoc.pre_open_streams;
+ } else {
+ stcb->asoc.pre_open_streams = stcb->asoc.streamoutcnt;
+ }
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
+ stcb->asoc.strmout[i].chunks_on_queues = 0;
+ stcb->asoc.strmout[i].next_sequence_send = 0;
+ stcb->asoc.strmout[i].stream_no = i;
+ stcb->asoc.strmout[i].last_msg_incomplete = 0;
+ stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
+ }
+ }
+ break;
+#ifdef INET
+ case SCTP_DSTADDRV4:
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct in_addr)) {
+ *error = EINVAL;
+ return (1);
+ }
+ memset(&sin, 0, sizeof(struct sockaddr_in));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_port = stcb->rport;
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct in_addr), (caddr_t)&sin.sin_addr);
+ if ((sin.sin_addr.s_addr == INADDR_ANY) ||
+ (sin.sin_addr.s_addr == INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
+ *error = EINVAL;
+ return (1);
+ }
+ if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, NULL,
+ SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ *error = ENOBUFS;
+ return (1);
+ }
+ break;
+#endif
+#ifdef INET6
+ case SCTP_DSTADDRV6:
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct in6_addr)) {
+ *error = EINVAL;
+ return (1);
+ }
+ memset(&sin6, 0, sizeof(struct sockaddr_in6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_port = stcb->rport;
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct in6_addr), (caddr_t)&sin6.sin6_addr);
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MULTICAST(&sin6.sin6_addr)) {
+ *error = EINVAL;
+ return (1);
+ }
+#ifdef INET
+ if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
+ in6_sin6_2_sin(&sin, &sin6);
+ if ((sin.sin_addr.s_addr == INADDR_ANY) ||
+ (sin.sin_addr.s_addr == INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
+ *error = EINVAL;
+ return (1);
+ }
+ if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, NULL,
+ SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ *error = ENOBUFS;
+ return (1);
+ }
+ } else
+#endif
+ if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin6, NULL,
+ SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ *error = ENOBUFS;
+ return (1);
+ }
+ break;
+#endif
+ default:
break;
}
}
+ at += CMSG_ALIGN(cmh.cmsg_len);
}
- /* not found */
return (0);
}
+static struct sctp_tcb *
+sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p,
+ in_port_t port,
+ struct mbuf *control,
+ struct sctp_nets **net_p,
+ int *error)
+{
+ struct cmsghdr cmh;
+ int tlen, at;
+ struct sctp_tcb *stcb;
+ struct sockaddr *addr;
+
+#ifdef INET
+ struct sockaddr_in sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+
+#endif
+
+ tlen = SCTP_BUF_LEN(control);
+ at = 0;
+ while (at < tlen) {
+ if ((tlen - at) < (int)CMSG_ALIGN(sizeof(cmh))) {
+ /* There is not enough room for one more. */
+ *error = EINVAL;
+ return (NULL);
+ }
+ m_copydata(control, at, sizeof(cmh), (caddr_t)&cmh);
+ if (cmh.cmsg_len < CMSG_ALIGN(sizeof(cmh))) {
+ /* We dont't have a complete CMSG header. */
+ *error = EINVAL;
+ return (NULL);
+ }
+ if (((int)cmh.cmsg_len + at) > tlen) {
+ /* We don't have the complete CMSG. */
+ *error = EINVAL;
+ return (NULL);
+ }
+ if (cmh.cmsg_level == IPPROTO_SCTP) {
+ switch (cmh.cmsg_type) {
+#ifdef INET
+ case SCTP_DSTADDRV4:
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct in_addr)) {
+ *error = EINVAL;
+ return (NULL);
+ }
+ memset(&sin, 0, sizeof(struct sockaddr_in));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_port = port;
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct in_addr), (caddr_t)&sin.sin_addr);
+ addr = (struct sockaddr *)&sin;
+ break;
+#endif
+#ifdef INET6
+ case SCTP_DSTADDRV6:
+ if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct in6_addr)) {
+ *error = EINVAL;
+ return (NULL);
+ }
+ memset(&sin6, 0, sizeof(struct sockaddr_in6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_port = port;
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct in6_addr), (caddr_t)&sin6.sin6_addr);
+#ifdef INET
+ if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
+ in6_sin6_2_sin(&sin, &sin6);
+ addr = (struct sockaddr *)&sin;
+ } else
+#endif
+ addr = (struct sockaddr *)&sin6;
+ break;
+#endif
+ default:
+ addr = NULL;
+ break;
+ }
+ if (addr) {
+ stcb = sctp_findassociation_ep_addr(inp_p, addr, net_p, NULL, NULL);
+ if (stcb != NULL) {
+ return (stcb);
+ }
+ }
+ }
+ at += CMSG_ALIGN(cmh.cmsg_len);
+ }
+ return (NULL);
+}
+
static struct mbuf *
-sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
+sctp_add_cookie(struct mbuf *init, int init_offset,
struct mbuf *initack, int initack_offset, struct sctp_state_cookie *stc_in, uint8_t ** signature)
{
struct mbuf *copy_init, *copy_initack, *m_at, *sig, *mret;
@@ -3303,12 +3680,10 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = copy_init;
- while (mat) {
+ for (mat = copy_init; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -3323,12 +3698,10 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = copy_initack;
- while (mat) {
+ for (mat = copy_initack; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -3345,7 +3718,6 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
/* tack the INIT and then the INIT-ACK onto the chain */
cookie_sz = 0;
- m_at = mret;
for (m_at = mret; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
cookie_sz += SCTP_BUF_LEN(m_at);
if (SCTP_BUF_NEXT(m_at) == NULL) {
@@ -3353,7 +3725,6 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
break;
}
}
-
for (m_at = copy_init; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
cookie_sz += SCTP_BUF_LEN(m_at);
if (SCTP_BUF_NEXT(m_at) == NULL) {
@@ -3361,7 +3732,6 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
break;
}
}
-
for (m_at = copy_initack; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
cookie_sz += SCTP_BUF_LEN(m_at);
if (SCTP_BUF_NEXT(m_at) == NULL) {
@@ -3388,60 +3758,62 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
static uint8_t
-sctp_get_ect(struct sctp_tcb *stcb,
- struct sctp_tmit_chunk *chk)
+sctp_get_ect(struct sctp_tcb *stcb)
{
- uint8_t this_random;
-
- /* Huh? */
- if (SCTP_BASE_SYSCTL(sctp_ecn_enable) == 0)
- return (0);
-
- if (SCTP_BASE_SYSCTL(sctp_ecn_nonce) == 0)
- /* no nonce, always return ECT0 */
- return (SCTP_ECT0_BIT);
-
- if (stcb->asoc.peer_supports_ecn_nonce == 0) {
- /* Peer does NOT support it, so we send a ECT0 only */
+ if ((stcb != NULL) && (stcb->asoc.ecn_allowed == 1)) {
return (SCTP_ECT0_BIT);
+ } else {
+ return (0);
}
- if (chk == NULL)
- return (SCTP_ECT0_BIT);
+}
- if ((stcb->asoc.hb_random_idx > 3) ||
- ((stcb->asoc.hb_random_idx == 3) &&
- (stcb->asoc.hb_ect_randombit > 7))) {
- uint32_t rndval;
-
-warp_drive_sa:
- rndval = sctp_select_initial_TSN(&stcb->sctp_ep->sctp_ep);
- memcpy(stcb->asoc.hb_random_values, &rndval,
- sizeof(stcb->asoc.hb_random_values));
- this_random = stcb->asoc.hb_random_values[0];
- stcb->asoc.hb_random_idx = 0;
- stcb->asoc.hb_ect_randombit = 0;
- } else {
- if (stcb->asoc.hb_ect_randombit > 7) {
- stcb->asoc.hb_ect_randombit = 0;
- stcb->asoc.hb_random_idx++;
- if (stcb->asoc.hb_random_idx > 3) {
- goto warp_drive_sa;
+#if defined(INET) || defined(INET6)
+static void
+sctp_handle_no_route(struct sctp_tcb *stcb,
+ struct sctp_nets *net,
+ int so_locked)
+{
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "dropped packet - no valid source addr\n");
+
+ if (net) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "Destination was ");
+ SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT1, &net->ro._l_addr.sa);
+ if (net->dest_state & SCTP_ADDR_CONFIRMED) {
+ if ((net->dest_state & SCTP_ADDR_REACHABLE) && stcb) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "no route takes interface %p down\n", (void *)net);
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
+ stcb, 0,
+ (void *)net,
+ so_locked);
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ }
+ if (stcb) {
+ if (net == stcb->asoc.primary_destination) {
+ /* need a new primary */
+ struct sctp_nets *alt;
+
+ alt = sctp_find_alternate_net(stcb, net, 0);
+ if (alt != net) {
+ if (stcb->asoc.alternate) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ }
+ stcb->asoc.alternate = alt;
+ atomic_add_int(&stcb->asoc.alternate->ref_count, 1);
+ if (net->ro._s_addr) {
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
+ }
+ net->src_addr_selected = 0;
+ }
}
}
- this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
- }
- if ((this_random >> stcb->asoc.hb_ect_randombit) & 0x01) {
- if (chk != NULL)
- /* ECN Nonce stuff */
- chk->rec.data.ect_nonce = SCTP_ECT1_BIT;
- stcb->asoc.hb_ect_randombit++;
- return (SCTP_ECT1_BIT);
- } else {
- stcb->asoc.hb_ect_randombit++;
- return (SCTP_ECT0_BIT);
}
}
+#endif
+
static int
sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
struct sctp_tcb *stcb, /* may be NULL */
@@ -3453,41 +3825,49 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
uint16_t auth_keyid,
int nofragment_flag,
int ecn_ok,
- struct sctp_tmit_chunk *chk,
int out_of_asoc_ok,
uint16_t src_port,
uint16_t dest_port,
uint32_t v_tag,
uint16_t port,
- int so_locked,
+ union sctp_sockstore *over_addr,
+ uint8_t use_mflowid, uint32_t mflowid,
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
- SCTP_UNUSED
+ int so_locked SCTP_UNUSED
+#else
+ int so_locked
#endif
- union sctp_sockstore *over_addr
)
/* nofragment_flag to tell if IP_DF should be set (IPv4 only) */
{
- /*
- * Given a mbuf chain (via SCTP_BUF_NEXT()) that holds a packet
- * header WITH an SCTPHDR but no IP header, endpoint inp and sa
- * structure: - fill in the HMAC digest of any AUTH chunk in the
- * packet. - calculate and fill in the SCTP checksum. - prepend an
- * IP address header. - if boundall use INADDR_ANY. - if
- * boundspecific do source address selection. - set fragmentation
- * option for ipV4. - On return from IP output, check/adjust mtu
- * size of output interface and smallest_mtu size as well.
+ /**
+ * Given a mbuf chain (via SCTP_BUF_NEXT()) that holds a packet header
+ * WITH an SCTPHDR but no IP header, endpoint inp and sa structure:
+ * - fill in the HMAC digest of any AUTH chunk in the packet.
+ * - calculate and fill in the SCTP checksum.
+ * - prepend an IP address header.
+ * - if boundall use INADDR_ANY.
+ * - if boundspecific do source address selection.
+ * - set fragmentation option for ipV4.
+ * - On return from IP output, check/adjust mtu size of output
+ * interface and smallest_mtu size as well.
*/
/* Will need ifdefs around this */
- struct mbuf *o_pak;
struct mbuf *newm;
struct sctphdr *sctphdr;
int packet_length;
int ret;
uint32_t vrf_id;
+
+#if defined(INET) || defined(INET6)
+ struct mbuf *o_pak;
sctp_route_t *ro = NULL;
struct udphdr *udp = NULL;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#endif
+ uint8_t tos_value;
+
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so = NULL;
#endif
@@ -3507,645 +3887,649 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if ((auth != NULL) && (stcb != NULL)) {
sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid);
}
- if (to->sa_family == AF_INET) {
- struct ip *ip = NULL;
- sctp_route_t iproute;
- uint8_t tos_value;
- int len;
-
- len = sizeof(struct ip) + sizeof(struct sctphdr);
- if (port) {
- len += sizeof(struct udphdr);
- }
- newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA);
- if (newm == NULL) {
- sctp_m_freem(m);
- SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
- return (ENOMEM);
- }
- SCTP_ALIGN_TO_END(newm, len);
- SCTP_BUF_LEN(newm) = len;
- SCTP_BUF_NEXT(newm) = m;
- m = newm;
- packet_length = sctp_calculate_len(m);
- ip = mtod(m, struct ip *);
- ip->ip_v = IPVERSION;
- ip->ip_hl = (sizeof(struct ip) >> 2);
- if (net) {
- tos_value = net->tos_flowlabel & 0x000000ff;
- } else {
- tos_value = inp->ip_inp.inp.inp_ip_tos;
- }
- if ((nofragment_flag) && (port == 0)) {
- ip->ip_off = IP_DF;
- } else
- ip->ip_off = 0;
+ if (net) {
+ tos_value = net->dscp;
+ } else if (stcb) {
+ tos_value = stcb->asoc.default_dscp;
+ } else {
+ tos_value = inp->sctp_ep.default_dscp;
+ }
- /* FreeBSD has a function for ip_id's */
- ip->ip_id = ip_newid();
+ switch (to->sa_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct ip *ip = NULL;
+ sctp_route_t iproute;
+ int len;
- ip->ip_ttl = inp->ip_inp.inp.inp_ip_ttl;
- ip->ip_len = packet_length;
- if (stcb) {
- if ((stcb->asoc.ecn_allowed) && ecn_ok) {
- /* Enable ECN */
- ip->ip_tos = ((u_char)(tos_value & 0xfc) | sctp_get_ect(stcb, chk));
- } else {
- /* No ECN */
- ip->ip_tos = (u_char)(tos_value & 0xfc);
+ len = sizeof(struct ip) + sizeof(struct sctphdr);
+ if (port) {
+ len += sizeof(struct udphdr);
}
- } else {
- /* no association at all */
- ip->ip_tos = (tos_value & 0xfc);
- }
- if (port) {
- ip->ip_p = IPPROTO_UDP;
- } else {
- ip->ip_p = IPPROTO_SCTP;
- }
- ip->ip_sum = 0;
- if (net == NULL) {
- ro = &iproute;
- memset(&iproute, 0, sizeof(iproute));
- memcpy(&ro->ro_dst, to, to->sa_len);
- } else {
- ro = (sctp_route_t *) & net->ro;
- }
- /* Now the address selection part */
- ip->ip_dst.s_addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
-
- /* call the routine to select the src address */
- if (net && out_of_asoc_ok == 0) {
- if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) {
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
- net->src_addr_selected = 0;
- if (ro->ro_rt) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = NULL;
+ newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA);
+ if (newm == NULL) {
+ sctp_m_freem(m);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ return (ENOMEM);
+ }
+ SCTP_ALIGN_TO_END(newm, len);
+ SCTP_BUF_LEN(newm) = len;
+ SCTP_BUF_NEXT(newm) = m;
+ m = newm;
+ if (net != NULL) {
+#ifdef INVARIANTS
+ if (net->flowidset == 0) {
+ panic("Flow ID not set");
+ }
+#endif
+ m->m_pkthdr.flowid = net->flowid;
+ m->m_flags |= M_FLOWID;
+ } else {
+ if (use_mflowid != 0) {
+ m->m_pkthdr.flowid = mflowid;
+ m->m_flags |= M_FLOWID;
}
}
- if (net->src_addr_selected == 0) {
- /* Cache the source address */
- net->ro._s_addr = sctp_source_address_selection(inp, stcb,
- ro, net, 0,
- vrf_id);
- net->src_addr_selected = 1;
+ packet_length = sctp_calculate_len(m);
+ ip = mtod(m, struct ip *);
+ ip->ip_v = IPVERSION;
+ ip->ip_hl = (sizeof(struct ip) >> 2);
+ if (tos_value == 0) {
+ /*
+ * This means especially, that it is not set
+ * at the SCTP layer. So use the value from
+ * the IP layer.
+ */
+ tos_value = inp->ip_inp.inp.inp_ip_tos;
}
- if (net->ro._s_addr == NULL) {
- /* No route to host */
- net->src_addr_selected = 0;
- goto no_route;
+ tos_value &= 0xfc;
+ if (ecn_ok) {
+ tos_value |= sctp_get_ect(stcb);
}
- ip->ip_src = net->ro._s_addr->address.sin.sin_addr;
- } else {
- if (over_addr == NULL) {
- struct sctp_ifa *_lsrc;
-
- _lsrc = sctp_source_address_selection(inp, stcb, ro,
- net,
- out_of_asoc_ok,
- vrf_id);
- if (_lsrc == NULL) {
- goto no_route;
- }
- ip->ip_src = _lsrc->address.sin.sin_addr;
- sctp_free_ifa(_lsrc);
+ if ((nofragment_flag) && (port == 0)) {
+ ip->ip_off = IP_DF;
} else {
- ip->ip_src = over_addr->sin.sin_addr;
- SCTP_RTALLOC(ro, vrf_id);
+ ip->ip_off = 0;
}
- }
- if (port) {
- udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip));
- udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
- udp->uh_dport = port;
- udp->uh_ulen = htons(packet_length - sizeof(struct ip));
- udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
- sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
- } else {
- sctphdr = (struct sctphdr *)((caddr_t)ip + sizeof(struct ip));
- }
+ /* FreeBSD has a function for ip_id's */
+ ip->ip_id = ip_newid();
- sctphdr->src_port = src_port;
- sctphdr->dest_port = dest_port;
- sctphdr->v_tag = v_tag;
- sctphdr->checksum = 0;
+ ip->ip_ttl = inp->ip_inp.inp.inp_ip_ttl;
+ ip->ip_len = packet_length;
+ ip->ip_tos = tos_value;
+ if (port) {
+ ip->ip_p = IPPROTO_UDP;
+ } else {
+ ip->ip_p = IPPROTO_SCTP;
+ }
+ ip->ip_sum = 0;
+ if (net == NULL) {
+ ro = &iproute;
+ memset(&iproute, 0, sizeof(iproute));
+ memcpy(&ro->ro_dst, to, to->sa_len);
+ } else {
+ ro = (sctp_route_t *) & net->ro;
+ }
+ /* Now the address selection part */
+ ip->ip_dst.s_addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
- /*
- * If source address selection fails and we find no route
- * then the ip_output should fail as well with a
- * NO_ROUTE_TO_HOST type error. We probably should catch
- * that somewhere and abort the association right away
- * (assuming this is an INIT being sent).
- */
- if ((ro->ro_rt == NULL)) {
- /*
- * src addr selection failed to find a route (or
- * valid source addr), so we can't get there from
- * here (yet)!
- */
- no_route:
- SCTPDBG(SCTP_DEBUG_OUTPUT1,
- "%s: dropped packet - no valid source addr\n",
- __FUNCTION__);
- if (net) {
- SCTPDBG(SCTP_DEBUG_OUTPUT1,
- "Destination was ");
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT1,
- &net->ro._l_addr.sa);
- if (net->dest_state & SCTP_ADDR_CONFIRMED) {
- if ((net->dest_state & SCTP_ADDR_REACHABLE) && stcb) {
- SCTPDBG(SCTP_DEBUG_OUTPUT1, "no route takes interface %p down\n", net);
- sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
- stcb,
- SCTP_FAILED_THRESHOLD,
- (void *)net,
- so_locked);
- net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
- /*
- * JRS 5/14/07 - If a
- * destination is
- * unreachable, the PF bit
- * is turned off. This
- * allows an unambiguous use
- * of the PF bit for
- * destinations that are
- * reachable but potentially
- * failed. If the
- * destination is set to the
- * unreachable state, also
- * set the destination to
- * the PF state.
- */
- /*
- * Add debug message here if
- * destination is not in PF
- * state.
- */
- /*
- * Stop any running T3
- * timers here?
- */
- if ((stcb->asoc.sctp_cmt_on_off == 1) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_OUTPUT1, "Destination %p moved from PF to unreachable.\n",
- net);
- }
+ /* call the routine to select the src address */
+ if (net && out_of_asoc_ok == 0) {
+ if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) {
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
+ net->src_addr_selected = 0;
+ if (ro->ro_rt) {
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = NULL;
}
}
- if (stcb) {
- if (net == stcb->asoc.primary_destination) {
- /* need a new primary */
- struct sctp_nets *alt;
-
- alt = sctp_find_alternate_net(stcb, net, 0);
- if (alt != net) {
- if (sctp_set_primary_addr(stcb,
- (struct sockaddr *)NULL,
- alt) == 0) {
- net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
- if (net->ro._s_addr) {
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
- }
- net->src_addr_selected = 0;
- }
- }
+ if (net->src_addr_selected == 0) {
+ /* Cache the source address */
+ net->ro._s_addr = sctp_source_address_selection(inp, stcb,
+ ro, net, 0,
+ vrf_id);
+ net->src_addr_selected = 1;
+ }
+ if (net->ro._s_addr == NULL) {
+ /* No route to host */
+ net->src_addr_selected = 0;
+ sctp_handle_no_route(stcb, net, so_locked);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
+ sctp_m_freem(m);
+ return (EHOSTUNREACH);
+ }
+ ip->ip_src = net->ro._s_addr->address.sin.sin_addr;
+ } else {
+ if (over_addr == NULL) {
+ struct sctp_ifa *_lsrc;
+
+ _lsrc = sctp_source_address_selection(inp, stcb, ro,
+ net,
+ out_of_asoc_ok,
+ vrf_id);
+ if (_lsrc == NULL) {
+ sctp_handle_no_route(stcb, net, so_locked);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
+ sctp_m_freem(m);
+ return (EHOSTUNREACH);
}
+ ip->ip_src = _lsrc->address.sin.sin_addr;
+ sctp_free_ifa(_lsrc);
+ } else {
+ ip->ip_src = over_addr->sin.sin_addr;
+ SCTP_RTALLOC(ro, vrf_id);
}
}
- SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
- sctp_m_freem(m);
- return (EHOSTUNREACH);
- }
- if (ro != &iproute) {
- memcpy(&iproute, ro, sizeof(*ro));
- }
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "Calling ipv4 output routine from low level src addr:%x\n",
- (uint32_t) (ntohl(ip->ip_src.s_addr)));
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "Destination is %x\n",
- (uint32_t) (ntohl(ip->ip_dst.s_addr)));
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "RTP route is %p through\n",
- ro->ro_rt);
+ if (port) {
+ if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
+ sctp_handle_no_route(stcb, net, so_locked);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
+ sctp_m_freem(m);
+ return (EHOSTUNREACH);
+ }
+ udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip));
+ udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
+ udp->uh_dport = port;
+ udp->uh_ulen = htons(packet_length - sizeof(struct ip));
+ if (V_udp_cksum) {
+ udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
+ } else {
+ udp->uh_sum = 0;
+ }
+ sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
+ } else {
+ sctphdr = (struct sctphdr *)((caddr_t)ip + sizeof(struct ip));
+ }
- if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
- /* failed to prepend data, give up */
- SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
- sctp_m_freem(m);
- return (ENOMEM);
- }
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(m, packet_length);
-#endif
- SCTP_ATTACH_CHAIN(o_pak, m, packet_length);
- if (port) {
+ sctphdr->src_port = src_port;
+ sctphdr->dest_port = dest_port;
+ sctphdr->v_tag = v_tag;
+ sctphdr->checksum = 0;
+
+ /*
+ * If source address selection fails and we find no
+ * route then the ip_output should fail as well with
+ * a NO_ROUTE_TO_HOST type error. We probably should
+ * catch that somewhere and abort the association
+ * right away (assuming this is an INIT being sent).
+ */
+ if (ro->ro_rt == NULL) {
+ /*
+ * src addr selection failed to find a route
+ * (or valid source addr), so we can't get
+ * there from here (yet)!
+ */
+ sctp_handle_no_route(stcb, net, so_locked);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
+ sctp_m_freem(m);
+ return (EHOSTUNREACH);
+ }
+ if (ro != &iproute) {
+ memcpy(&iproute, ro, sizeof(*ro));
+ }
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "Calling ipv4 output routine from low level src addr:%x\n",
+ (uint32_t) (ntohl(ip->ip_src.s_addr)));
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "Destination is %x\n",
+ (uint32_t) (ntohl(ip->ip_dst.s_addr)));
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "RTP route is %p through\n",
+ (void *)ro->ro_rt);
+
+ if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
+ /* failed to prepend data, give up */
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ sctp_m_freem(m);
+ return (ENOMEM);
+ }
+ SCTP_ATTACH_CHAIN(o_pak, m, packet_length);
+ if (port) {
#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
+ SCTP_STAT_INCR(sctps_sendnocrc);
#else
- if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
- (stcb) &&
- (stcb->asoc.loopback_scope))) {
sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr));
SCTP_STAT_INCR(sctps_sendswcrc);
+#endif
+ if (V_udp_cksum) {
+ SCTP_ENABLE_UDP_CSUM(o_pak);
+ }
} else {
+#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_sendnocrc);
+#else
+ m->m_pkthdr.csum_flags = CSUM_SCTP;
+ m->m_pkthdr.csum_data = 0;
+ SCTP_STAT_INCR(sctps_sendhwcrc);
+#endif
}
+#ifdef SCTP_PACKET_LOGGING
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
+ sctp_packet_log(o_pak);
#endif
- SCTP_ENABLE_UDP_CSUM(o_pak);
- } else {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- m->m_pkthdr.csum_flags = CSUM_SCTP;
- m->m_pkthdr.csum_data = 0;
- SCTP_STAT_INCR(sctps_sendhwcrc);
+ /* send it out. table id is taken from stcb */
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
+ so = SCTP_INP_SO(inp);
+ SCTP_SOCKET_UNLOCK(so, 0);
+ }
#endif
- }
- /* send it out. table id is taken from stcb */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
- so = SCTP_INP_SO(inp);
- SCTP_SOCKET_UNLOCK(so, 0);
- }
+ SCTP_IP_OUTPUT(ret, o_pak, ro, stcb, vrf_id);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_SOCKET_LOCK(so, 0);
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ }
#endif
- SCTP_IP_OUTPUT(ret, o_pak, ro, stcb, vrf_id);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- SCTP_SOCKET_LOCK(so, 0);
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ SCTP_STAT_INCR(sctps_sendpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
+ if (ret)
+ SCTP_STAT_INCR(sctps_senderrors);
+
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "IP output returns %d\n", ret);
+ if (net == NULL) {
+ /* free tempy routes */
+ if (ro->ro_rt) {
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = NULL;
+ }
+ } else {
+ /*
+ * PMTU check versus smallest asoc MTU goes
+ * here
+ */
+ if ((ro->ro_rt != NULL) &&
+ (net->ro._s_addr)) {
+ uint32_t mtu;
+
+ mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
+ if (net->port) {
+ mtu -= sizeof(struct udphdr);
+ }
+ if (mtu && (stcb->asoc.smallest_mtu > mtu)) {
+ sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ net->mtu = mtu;
+ }
+ } else if (ro->ro_rt == NULL) {
+ /* route was freed */
+ if (net->ro._s_addr &&
+ net->src_addr_selected) {
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
+ }
+ net->src_addr_selected = 0;
+ }
+ }
+ return (ret);
}
#endif
- SCTP_STAT_INCR(sctps_sendpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
- if (ret)
- SCTP_STAT_INCR(sctps_senderrors);
+#ifdef INET6
+ case AF_INET6:
+ {
+ uint32_t flowlabel, flowinfo;
+ struct ip6_hdr *ip6h;
+ struct route_in6 ip6route;
+ struct ifnet *ifp;
+ struct sockaddr_in6 *sin6, tmp, *lsa6, lsa6_tmp;
+ int prev_scope = 0;
+ struct sockaddr_in6 lsa6_storage;
+ int error;
+ u_short prev_port = 0;
+ int len;
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "IP output returns %d\n", ret);
- if (net == NULL) {
- /* free tempy routes */
- if (ro->ro_rt) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = NULL;
+ if (net) {
+ flowlabel = net->flowlabel;
+ } else if (stcb) {
+ flowlabel = stcb->asoc.default_flowlabel;
+ } else {
+ flowlabel = inp->sctp_ep.default_flowlabel;
}
- } else {
- /* PMTU check versus smallest asoc MTU goes here */
- if ((ro->ro_rt != NULL) &&
- (net->ro._s_addr)) {
- uint32_t mtu;
-
- mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
- if (net->port) {
- mtu -= sizeof(struct udphdr);
- }
- if (mtu && (stcb->asoc.smallest_mtu > mtu)) {
- sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
- net->mtu = mtu;
- }
- } else if (ro->ro_rt == NULL) {
- /* route was freed */
- if (net->ro._s_addr &&
- net->src_addr_selected) {
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
+ if (flowlabel == 0) {
+ /*
+ * This means especially, that it is not set
+ * at the SCTP layer. So use the value from
+ * the IP layer.
+ */
+ flowlabel = ntohl(((struct in6pcb *)inp)->in6p_flowinfo);
+ }
+ flowlabel &= 0x000fffff;
+ len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr);
+ if (port) {
+ len += sizeof(struct udphdr);
+ }
+ newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA);
+ if (newm == NULL) {
+ sctp_m_freem(m);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ return (ENOMEM);
+ }
+ SCTP_ALIGN_TO_END(newm, len);
+ SCTP_BUF_LEN(newm) = len;
+ SCTP_BUF_NEXT(newm) = m;
+ m = newm;
+ if (net != NULL) {
+#ifdef INVARIANTS
+ if (net->flowidset == 0) {
+ panic("Flow ID not set");
+ }
+#endif
+ m->m_pkthdr.flowid = net->flowid;
+ m->m_flags |= M_FLOWID;
+ } else {
+ if (use_mflowid != 0) {
+ m->m_pkthdr.flowid = mflowid;
+ m->m_flags |= M_FLOWID;
}
- net->src_addr_selected = 0;
}
- }
- return (ret);
- }
-#ifdef INET6
- else if (to->sa_family == AF_INET6) {
- uint32_t flowlabel;
- struct ip6_hdr *ip6h;
- struct route_in6 ip6route;
- struct ifnet *ifp;
- u_char flowTop;
- uint16_t flowBottom;
- u_char tosBottom, tosTop;
- struct sockaddr_in6 *sin6, tmp, *lsa6, lsa6_tmp;
- int prev_scope = 0;
- struct sockaddr_in6 lsa6_storage;
- int error;
- u_short prev_port = 0;
- int len;
-
- if (net != NULL) {
- flowlabel = net->tos_flowlabel;
- } else {
- flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo;
- }
+ packet_length = sctp_calculate_len(m);
- len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr);
- if (port) {
- len += sizeof(struct udphdr);
- }
- newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA);
- if (newm == NULL) {
- sctp_m_freem(m);
- SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
- return (ENOMEM);
- }
- SCTP_ALIGN_TO_END(newm, len);
- SCTP_BUF_LEN(newm) = len;
- SCTP_BUF_NEXT(newm) = m;
- m = newm;
- packet_length = sctp_calculate_len(m);
+ ip6h = mtod(m, struct ip6_hdr *);
+ /* protect *sin6 from overwrite */
+ sin6 = (struct sockaddr_in6 *)to;
+ tmp = *sin6;
+ sin6 = &tmp;
- ip6h = mtod(m, struct ip6_hdr *);
- /*
- * We assume here that inp_flow is in host byte order within
- * the TCB!
- */
- flowBottom = flowlabel & 0x0000ffff;
- flowTop = ((flowlabel & 0x000f0000) >> 16);
- tosTop = (((flowlabel & 0xf0) >> 4) | IPV6_VERSION);
- /* protect *sin6 from overwrite */
- sin6 = (struct sockaddr_in6 *)to;
- tmp = *sin6;
- sin6 = &tmp;
-
- /* KAME hack: embed scopeid */
- if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
- SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
- return (EINVAL);
- }
- if (net == NULL) {
- memset(&ip6route, 0, sizeof(ip6route));
- ro = (sctp_route_t *) & ip6route;
- memcpy(&ro->ro_dst, sin6, sin6->sin6_len);
- } else {
- ro = (sctp_route_t *) & net->ro;
- }
- if (stcb != NULL) {
- if ((stcb->asoc.ecn_allowed) && ecn_ok) {
- /* Enable ECN */
- tosBottom = (((((struct in6pcb *)inp)->in6p_flowinfo & 0x0c) | sctp_get_ect(stcb, chk)) << 4);
+ /* KAME hack: embed scopeid */
+ if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+ return (EINVAL);
+ }
+ if (net == NULL) {
+ memset(&ip6route, 0, sizeof(ip6route));
+ ro = (sctp_route_t *) & ip6route;
+ memcpy(&ro->ro_dst, sin6, sin6->sin6_len);
} else {
- /* No ECN */
- tosBottom = ((((struct in6pcb *)inp)->in6p_flowinfo & 0x0c) << 4);
+ ro = (sctp_route_t *) & net->ro;
}
- } else {
- /* we could get no asoc if it is a O-O-T-B packet */
- tosBottom = ((((struct in6pcb *)inp)->in6p_flowinfo & 0x0c) << 4);
- }
- ip6h->ip6_flow = htonl(((tosTop << 24) | ((tosBottom | flowTop) << 16) | flowBottom));
- if (port) {
- ip6h->ip6_nxt = IPPROTO_UDP;
- } else {
- ip6h->ip6_nxt = IPPROTO_SCTP;
- }
- ip6h->ip6_plen = (packet_length - sizeof(struct ip6_hdr));
- ip6h->ip6_dst = sin6->sin6_addr;
+ /*
+ * We assume here that inp_flow is in host byte
+ * order within the TCB!
+ */
+ if (tos_value == 0) {
+ /*
+ * This means especially, that it is not set
+ * at the SCTP layer. So use the value from
+ * the IP layer.
+ */
+ tos_value = (ntohl(((struct in6pcb *)inp)->in6p_flowinfo) >> 20) & 0xff;
+ }
+ tos_value &= 0xfc;
+ if (ecn_ok) {
+ tos_value |= sctp_get_ect(stcb);
+ }
+ flowinfo = 0x06;
+ flowinfo <<= 8;
+ flowinfo |= tos_value;
+ flowinfo <<= 20;
+ flowinfo |= flowlabel;
+ ip6h->ip6_flow = htonl(flowinfo);
+ if (port) {
+ ip6h->ip6_nxt = IPPROTO_UDP;
+ } else {
+ ip6h->ip6_nxt = IPPROTO_SCTP;
+ }
+ ip6h->ip6_plen = (packet_length - sizeof(struct ip6_hdr));
+ ip6h->ip6_dst = sin6->sin6_addr;
- /*
- * Add SRC address selection here: we can only reuse to a
- * limited degree the kame src-addr-sel, since we can try
- * their selection but it may not be bound.
- */
- bzero(&lsa6_tmp, sizeof(lsa6_tmp));
- lsa6_tmp.sin6_family = AF_INET6;
- lsa6_tmp.sin6_len = sizeof(lsa6_tmp);
- lsa6 = &lsa6_tmp;
- if (net && out_of_asoc_ok == 0) {
- if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) {
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
- net->src_addr_selected = 0;
- if (ro->ro_rt) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = NULL;
+ /*
+ * Add SRC address selection here: we can only reuse
+ * to a limited degree the kame src-addr-sel, since
+ * we can try their selection but it may not be
+ * bound.
+ */
+ bzero(&lsa6_tmp, sizeof(lsa6_tmp));
+ lsa6_tmp.sin6_family = AF_INET6;
+ lsa6_tmp.sin6_len = sizeof(lsa6_tmp);
+ lsa6 = &lsa6_tmp;
+ if (net && out_of_asoc_ok == 0) {
+ if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) {
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
+ net->src_addr_selected = 0;
+ if (ro->ro_rt) {
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = NULL;
+ }
}
- }
- if (net->src_addr_selected == 0) {
- sin6 = (struct sockaddr_in6 *)&net->ro._l_addr;
+ if (net->src_addr_selected == 0) {
+ sin6 = (struct sockaddr_in6 *)&net->ro._l_addr;
+ /* KAME hack: embed scopeid */
+ if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+ return (EINVAL);
+ }
+ /* Cache the source address */
+ net->ro._s_addr = sctp_source_address_selection(inp,
+ stcb,
+ ro,
+ net,
+ 0,
+ vrf_id);
+ (void)sa6_recoverscope(sin6);
+ net->src_addr_selected = 1;
+ }
+ if (net->ro._s_addr == NULL) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "V6:No route to host\n");
+ net->src_addr_selected = 0;
+ sctp_handle_no_route(stcb, net, so_locked);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
+ sctp_m_freem(m);
+ return (EHOSTUNREACH);
+ }
+ lsa6->sin6_addr = net->ro._s_addr->address.sin6.sin6_addr;
+ } else {
+ sin6 = (struct sockaddr_in6 *)&ro->ro_dst;
/* KAME hack: embed scopeid */
if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
- /* Cache the source address */
- net->ro._s_addr = sctp_source_address_selection(inp,
- stcb,
- ro,
- net,
- 0,
- vrf_id);
+ if (over_addr == NULL) {
+ struct sctp_ifa *_lsrc;
+
+ _lsrc = sctp_source_address_selection(inp, stcb, ro,
+ net,
+ out_of_asoc_ok,
+ vrf_id);
+ if (_lsrc == NULL) {
+ sctp_handle_no_route(stcb, net, so_locked);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
+ sctp_m_freem(m);
+ return (EHOSTUNREACH);
+ }
+ lsa6->sin6_addr = _lsrc->address.sin6.sin6_addr;
+ sctp_free_ifa(_lsrc);
+ } else {
+ lsa6->sin6_addr = over_addr->sin6.sin6_addr;
+ SCTP_RTALLOC(ro, vrf_id);
+ }
(void)sa6_recoverscope(sin6);
- net->src_addr_selected = 1;
}
- if (net->ro._s_addr == NULL) {
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "V6:No route to host\n");
- net->src_addr_selected = 0;
- goto no_route;
+ lsa6->sin6_port = inp->sctp_lport;
+
+ if (ro->ro_rt == NULL) {
+ /*
+ * src addr selection failed to find a route
+ * (or valid source addr), so we can't get
+ * there from here!
+ */
+ sctp_handle_no_route(stcb, net, so_locked);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
+ sctp_m_freem(m);
+ return (EHOSTUNREACH);
}
- lsa6->sin6_addr = net->ro._s_addr->address.sin6.sin6_addr;
- } else {
- sin6 = (struct sockaddr_in6 *)&ro->ro_dst;
- /* KAME hack: embed scopeid */
- if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
- SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
- return (EINVAL);
+ /*
+ * XXX: sa6 may not have a valid sin6_scope_id in
+ * the non-SCOPEDROUTING case.
+ */
+ bzero(&lsa6_storage, sizeof(lsa6_storage));
+ lsa6_storage.sin6_family = AF_INET6;
+ lsa6_storage.sin6_len = sizeof(lsa6_storage);
+ lsa6_storage.sin6_addr = lsa6->sin6_addr;
+ if ((error = sa6_recoverscope(&lsa6_storage)) != 0) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "recover scope fails error %d\n", error);
+ sctp_m_freem(m);
+ return (error);
}
- if (over_addr == NULL) {
- struct sctp_ifa *_lsrc;
-
- _lsrc = sctp_source_address_selection(inp, stcb, ro,
- net,
- out_of_asoc_ok,
- vrf_id);
- if (_lsrc == NULL) {
- goto no_route;
+ /* XXX */
+ lsa6_storage.sin6_addr = lsa6->sin6_addr;
+ lsa6_storage.sin6_port = inp->sctp_lport;
+ lsa6 = &lsa6_storage;
+ ip6h->ip6_src = lsa6->sin6_addr;
+
+ if (port) {
+ if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
+ sctp_handle_no_route(stcb, net, so_locked);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
+ sctp_m_freem(m);
+ return (EHOSTUNREACH);
}
- lsa6->sin6_addr = _lsrc->address.sin6.sin6_addr;
- sctp_free_ifa(_lsrc);
+ udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
+ udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
+ udp->uh_dport = port;
+ udp->uh_ulen = htons(packet_length - sizeof(struct ip6_hdr));
+ udp->uh_sum = 0;
+ sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
} else {
- lsa6->sin6_addr = over_addr->sin6.sin6_addr;
- SCTP_RTALLOC(ro, vrf_id);
+ sctphdr = (struct sctphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
}
- (void)sa6_recoverscope(sin6);
- }
- lsa6->sin6_port = inp->sctp_lport;
- if (ro->ro_rt == NULL) {
+ sctphdr->src_port = src_port;
+ sctphdr->dest_port = dest_port;
+ sctphdr->v_tag = v_tag;
+ sctphdr->checksum = 0;
+
/*
- * src addr selection failed to find a route (or
- * valid source addr), so we can't get there from
- * here!
+ * We set the hop limit now since there is a good
+ * chance that our ro pointer is now filled
*/
- goto no_route;
- }
- /*
- * XXX: sa6 may not have a valid sin6_scope_id in the
- * non-SCOPEDROUTING case.
- */
- bzero(&lsa6_storage, sizeof(lsa6_storage));
- lsa6_storage.sin6_family = AF_INET6;
- lsa6_storage.sin6_len = sizeof(lsa6_storage);
- lsa6_storage.sin6_addr = lsa6->sin6_addr;
- if ((error = sa6_recoverscope(&lsa6_storage)) != 0) {
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "recover scope fails error %d\n", error);
- sctp_m_freem(m);
- return (error);
- }
- /* XXX */
- lsa6_storage.sin6_addr = lsa6->sin6_addr;
- lsa6_storage.sin6_port = inp->sctp_lport;
- lsa6 = &lsa6_storage;
- ip6h->ip6_src = lsa6->sin6_addr;
-
- if (port) {
- udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
- udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
- udp->uh_dport = port;
- udp->uh_ulen = htons(packet_length - sizeof(struct ip6_hdr));
- udp->uh_sum = 0;
- sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
- } else {
- sctphdr = (struct sctphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
- }
-
- sctphdr->src_port = src_port;
- sctphdr->dest_port = dest_port;
- sctphdr->v_tag = v_tag;
- sctphdr->checksum = 0;
-
- /*
- * We set the hop limit now since there is a good chance
- * that our ro pointer is now filled
- */
- ip6h->ip6_hlim = SCTP_GET_HLIM(inp, ro);
- ifp = SCTP_GET_IFN_VOID_FROM_ROUTE(ro);
+ ip6h->ip6_hlim = SCTP_GET_HLIM(inp, ro);
+ ifp = SCTP_GET_IFN_VOID_FROM_ROUTE(ro);
#ifdef SCTP_DEBUG
- /* Copy to be sure something bad is not happening */
- sin6->sin6_addr = ip6h->ip6_dst;
- lsa6->sin6_addr = ip6h->ip6_src;
+ /* Copy to be sure something bad is not happening */
+ sin6->sin6_addr = ip6h->ip6_dst;
+ lsa6->sin6_addr = ip6h->ip6_src;
#endif
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "Calling ipv6 output routine from low level\n");
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "src: ");
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)lsa6);
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "dst: ");
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)sin6);
- if (net) {
- sin6 = (struct sockaddr_in6 *)&net->ro._l_addr;
- /* preserve the port and scope for link local send */
- prev_scope = sin6->sin6_scope_id;
- prev_port = sin6->sin6_port;
- }
- if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
- /* failed to prepend data, give up */
- sctp_m_freem(m);
- SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
- return (ENOMEM);
- }
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(m, packet_length);
-#endif
- SCTP_ATTACH_CHAIN(o_pak, m, packet_length);
- if (port) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "Calling ipv6 output routine from low level\n");
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "src: ");
+ SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)lsa6);
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "dst: ");
+ SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)sin6);
+ if (net) {
+ sin6 = (struct sockaddr_in6 *)&net->ro._l_addr;
+ /*
+ * preserve the port and scope for link
+ * local send
+ */
+ prev_scope = sin6->sin6_scope_id;
+ prev_port = sin6->sin6_port;
+ }
+ if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
+ /* failed to prepend data, give up */
+ sctp_m_freem(m);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ return (ENOMEM);
+ }
+ SCTP_ATTACH_CHAIN(o_pak, m, packet_length);
+ if (port) {
#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
+ SCTP_STAT_INCR(sctps_sendnocrc);
#else
- if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
- (stcb) &&
- (stcb->asoc.loopback_scope))) {
sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
SCTP_STAT_INCR(sctps_sendswcrc);
- } else {
- SCTP_STAT_INCR(sctps_sendnocrc);
- }
#endif
- if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), packet_length - sizeof(struct ip6_hdr))) == 0) {
- udp->uh_sum = 0xffff;
- }
- } else {
+ if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), packet_length - sizeof(struct ip6_hdr))) == 0) {
+ udp->uh_sum = 0xffff;
+ }
+ } else {
#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
+ SCTP_STAT_INCR(sctps_sendnocrc);
#else
- m->m_pkthdr.csum_flags = CSUM_SCTP;
- m->m_pkthdr.csum_data = 0;
- SCTP_STAT_INCR(sctps_sendhwcrc);
+ sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr));
+ SCTP_STAT_INCR(sctps_sendswcrc);
#endif
- }
- /* send it out. table id is taken from stcb */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
- so = SCTP_INP_SO(inp);
- SCTP_SOCKET_UNLOCK(so, 0);
- }
+ }
+ /* send it out. table id is taken from stcb */
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
+ so = SCTP_INP_SO(inp);
+ SCTP_SOCKET_UNLOCK(so, 0);
+ }
#endif
- SCTP_IP6_OUTPUT(ret, o_pak, (struct route_in6 *)ro, &ifp, stcb, vrf_id);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- SCTP_SOCKET_LOCK(so, 0);
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- }
+#ifdef SCTP_PACKET_LOGGING
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
+ sctp_packet_log(o_pak);
#endif
- if (net) {
- /* for link local this must be done */
- sin6->sin6_scope_id = prev_scope;
- sin6->sin6_port = prev_port;
- }
- SCTPDBG(SCTP_DEBUG_OUTPUT3, "return from send is %d\n", ret);
- SCTP_STAT_INCR(sctps_sendpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
- if (ret) {
- SCTP_STAT_INCR(sctps_senderrors);
- }
- if (net == NULL) {
- /* Now if we had a temp route free it */
- if (ro->ro_rt) {
- RTFREE(ro->ro_rt);
+ SCTP_IP6_OUTPUT(ret, o_pak, (struct route_in6 *)ro, &ifp, stcb, vrf_id);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_SOCKET_LOCK(so, 0);
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
}
- } else {
- /* PMTU check versus smallest asoc MTU goes here */
- if (ro->ro_rt == NULL) {
- /* Route was freed */
- if (net->ro._s_addr &&
- net->src_addr_selected) {
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
+#endif
+ if (net) {
+ /* for link local this must be done */
+ sin6->sin6_scope_id = prev_scope;
+ sin6->sin6_port = prev_port;
+ }
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "return from send is %d\n", ret);
+ SCTP_STAT_INCR(sctps_sendpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
+ if (ret) {
+ SCTP_STAT_INCR(sctps_senderrors);
+ }
+ if (net == NULL) {
+ /* Now if we had a temp route free it */
+ if (ro->ro_rt) {
+ RTFREE(ro->ro_rt);
}
- net->src_addr_selected = 0;
- }
- if ((ro->ro_rt != NULL) &&
- (net->ro._s_addr)) {
- uint32_t mtu;
-
- mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
- if (mtu &&
- (stcb->asoc.smallest_mtu > mtu)) {
- sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
- net->mtu = mtu;
- if (net->port) {
- net->mtu -= sizeof(struct udphdr);
+ } else {
+ /*
+ * PMTU check versus smallest asoc MTU goes
+ * here
+ */
+ if (ro->ro_rt == NULL) {
+ /* Route was freed */
+ if (net->ro._s_addr &&
+ net->src_addr_selected) {
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
}
+ net->src_addr_selected = 0;
}
- } else if (ifp) {
- if (ND_IFINFO(ifp)->linkmtu &&
- (stcb->asoc.smallest_mtu > ND_IFINFO(ifp)->linkmtu)) {
- sctp_mtu_size_reset(inp,
- &stcb->asoc,
- ND_IFINFO(ifp)->linkmtu);
+ if ((ro->ro_rt != NULL) &&
+ (net->ro._s_addr)) {
+ uint32_t mtu;
+
+ mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
+ if (mtu &&
+ (stcb->asoc.smallest_mtu > mtu)) {
+ sctp_mtu_size_reset(inp, &stcb->asoc, mtu);
+ net->mtu = mtu;
+ if (net->port) {
+ net->mtu -= sizeof(struct udphdr);
+ }
+ }
+ } else if (ifp) {
+ if (ND_IFINFO(ifp)->linkmtu &&
+ (stcb->asoc.smallest_mtu > ND_IFINFO(ifp)->linkmtu)) {
+ sctp_mtu_size_reset(inp,
+ &stcb->asoc,
+ ND_IFINFO(ifp)->linkmtu);
+ }
}
}
+ return (ret);
}
- return (ret);
- }
#endif
- else {
+ default:
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Unknown protocol (TSNH) type %d\n",
((struct sockaddr *)to)->sa_family);
sctp_m_freem(m);
@@ -4162,22 +4546,22 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
#endif
)
{
- struct mbuf *m, *m_at, *mp_last;
+ struct mbuf *m;
struct sctp_nets *net;
struct sctp_init_chunk *init;
+
+#if defined(INET) || defined(INET6)
struct sctp_supported_addr_param *sup_addr;
+
+#endif
struct sctp_adaptation_layer_indication *ali;
- struct sctp_ecn_supported_param *ecn;
- struct sctp_prsctp_supported_param *prsctp;
- struct sctp_ecn_nonce_supported_param *ecn_nonce;
struct sctp_supported_chunk_types_param *pr_supported;
+ struct sctp_paramhdr *ph;
int cnt_inits_to = 0;
- int padval, ret;
- int num_ext;
- int p_len;
+ int ret;
+ uint16_t num_ext, chunk_len, padding_len, parameter_len;
/* INIT's always go to the primary (and usually ONLY address) */
- mp_last = NULL;
net = stcb->asoc.primary_destination;
if (net == NULL) {
net = TAILQ_FIRST(&stcb->asoc.nets);
@@ -4194,15 +4578,12 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
}
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT\n");
#ifdef INET6
- if (((struct sockaddr *)&(net->ro._l_addr))->sa_family == AF_INET6) {
+ if (net->ro._l_addr.sa.sa_family == AF_INET6) {
/*
* special hook, if we are sending to link local it will not
* show up in our private address count.
*/
- struct sockaddr_in6 *sin6l;
-
- sin6l = &net->ro._l_addr.sin6;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6l->sin6_addr))
+ if (IN6_IS_ADDR_LINKLOCAL(&net->ro._l_addr.sin6.sin6_addr))
cnt_inits_to = 1;
}
#endif
@@ -4220,14 +4601,15 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - mbuf?\n");
return;
}
- SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
+ chunk_len = (uint16_t) sizeof(struct sctp_init_chunk);
+ padding_len = 0;
/*
* assume peer supports asconf in order to be able to queue local
* address changes while an INIT is in flight and before the assoc
* is established.
*/
stcb->asoc.peer_supports_asconf = 1;
- /* Now lets put the SCTP header in place */
+ /* Now lets put the chunk header in place */
init = mtod(m, struct sctp_init_chunk *);
/* now the chunk header */
init->ch.chunk_type = SCTP_INITIATION;
@@ -4239,76 +4621,104 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
/* set up some of the credits. */
init->init.a_rwnd = htonl(max(inp->sctp_socket ? SCTP_SB_LIMIT_RCV(inp->sctp_socket) : 0,
SCTP_MINIMAL_RWND));
-
init->init.num_outbound_streams = htons(stcb->asoc.pre_open_streams);
init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams);
init->init.initial_tsn = htonl(stcb->asoc.init_seq_number);
- /* now the address restriction */
- sup_addr = (struct sctp_supported_addr_param *)((caddr_t)init +
- sizeof(*init));
- sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE);
-#ifdef INET6
- /* we support 2 types: IPv6/IPv4 */
- sup_addr->ph.param_length = htons(sizeof(*sup_addr) + sizeof(uint16_t));
- sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS);
- sup_addr->addr_type[1] = htons(SCTP_IPV6_ADDRESS);
-#else
- /* we support 1 type: IPv4 */
- sup_addr->ph.param_length = htons(sizeof(*sup_addr) + sizeof(uint8_t));
- sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS);
- sup_addr->addr_type[1] = htons(0); /* this is the padding */
-#endif
- SCTP_BUF_LEN(m) += sizeof(*sup_addr) + sizeof(uint16_t);
- /* adaptation layer indication parameter */
- ali = (struct sctp_adaptation_layer_indication *)((caddr_t)sup_addr + sizeof(*sup_addr) + sizeof(uint16_t));
- ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
- ali->ph.param_length = htons(sizeof(*ali));
- ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
- SCTP_BUF_LEN(m) += sizeof(*ali);
- ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali));
- if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
- /* Add NAT friendly parameter */
- struct sctp_paramhdr *ph;
+ if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) {
+ uint8_t i;
- ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
+ parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+ if (stcb->asoc.scope.ipv4_addr_legal) {
+ parameter_len += (uint16_t) sizeof(uint16_t);
+ }
+ if (stcb->asoc.scope.ipv6_addr_legal) {
+ parameter_len += (uint16_t) sizeof(uint16_t);
+ }
+ sup_addr = (struct sctp_supported_addr_param *)(mtod(m, caddr_t)+chunk_len);
+ sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE);
+ sup_addr->ph.param_length = htons(parameter_len);
+ i = 0;
+ if (stcb->asoc.scope.ipv4_addr_legal) {
+ sup_addr->addr_type[i++] = htons(SCTP_IPV4_ADDRESS);
+ }
+ if (stcb->asoc.scope.ipv6_addr_legal) {
+ sup_addr->addr_type[i++] = htons(SCTP_IPV6_ADDRESS);
+ }
+ padding_len = 4 - 2 * i;
+ chunk_len += parameter_len;
+ }
+ /* Adaptation layer indication parameter */
+ if (inp->sctp_ep.adaptation_layer_indicator_provided) {
+ if (padding_len > 0) {
+ memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
+ chunk_len += padding_len;
+ padding_len = 0;
+ }
+ parameter_len = (uint16_t) sizeof(struct sctp_adaptation_layer_indication);
+ ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t)+chunk_len);
+ ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
+ ali->ph.param_length = htons(parameter_len);
+ ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
+ chunk_len += parameter_len;
+ }
+ if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
+ /* Add NAT friendly parameter. */
+ if (padding_len > 0) {
+ memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
+ chunk_len += padding_len;
+ padding_len = 0;
+ }
+ parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+ ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
- ph->param_length = htons(sizeof(struct sctp_paramhdr));
- SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr);
- ecn = (struct sctp_ecn_supported_param *)((caddr_t)ph + sizeof(*ph));
+ ph->param_length = htons(parameter_len);
+ chunk_len += parameter_len;
}
/* now any cookie time extensions */
if (stcb->asoc.cookie_preserve_req) {
struct sctp_cookie_perserve_param *cookie_preserve;
- cookie_preserve = (struct sctp_cookie_perserve_param *)(ecn);
+ if (padding_len > 0) {
+ memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
+ chunk_len += padding_len;
+ padding_len = 0;
+ }
+ parameter_len = (uint16_t) sizeof(struct sctp_cookie_perserve_param);
+ cookie_preserve = (struct sctp_cookie_perserve_param *)(mtod(m, caddr_t)+chunk_len);
cookie_preserve->ph.param_type = htons(SCTP_COOKIE_PRESERVE);
- cookie_preserve->ph.param_length = htons(
- sizeof(*cookie_preserve));
+ cookie_preserve->ph.param_length = htons(parameter_len);
cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req);
- SCTP_BUF_LEN(m) += sizeof(*cookie_preserve);
- ecn = (struct sctp_ecn_supported_param *)(
- (caddr_t)cookie_preserve + sizeof(*cookie_preserve));
stcb->asoc.cookie_preserve_req = 0;
+ chunk_len += parameter_len;
}
/* ECN parameter */
- if (SCTP_BASE_SYSCTL(sctp_ecn_enable) == 1) {
- ecn->ph.param_type = htons(SCTP_ECN_CAPABLE);
- ecn->ph.param_length = htons(sizeof(*ecn));
- SCTP_BUF_LEN(m) += sizeof(*ecn);
- prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn +
- sizeof(*ecn));
- } else {
- prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn);
- }
- /* And now tell the peer we do pr-sctp */
- prsctp->ph.param_type = htons(SCTP_PRSCTP_SUPPORTED);
- prsctp->ph.param_length = htons(sizeof(*prsctp));
- SCTP_BUF_LEN(m) += sizeof(*prsctp);
+ if (stcb->asoc.ecn_allowed == 1) {
+ if (padding_len > 0) {
+ memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
+ chunk_len += padding_len;
+ padding_len = 0;
+ }
+ parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+ ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
+ ph->param_type = htons(SCTP_ECN_CAPABLE);
+ ph->param_length = htons(parameter_len);
+ chunk_len += parameter_len;
+ }
+ /* And now tell the peer we do support PR-SCTP. */
+ if (padding_len > 0) {
+ memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
+ chunk_len += padding_len;
+ padding_len = 0;
+ }
+ parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+ ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
+ ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
+ ph->param_length = htons(parameter_len);
+ chunk_len += parameter_len;
/* And now tell the peer we do all the extensions */
- pr_supported = (struct sctp_supported_chunk_types_param *)
- ((caddr_t)prsctp + sizeof(*prsctp));
+ pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
num_ext = 0;
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
@@ -4322,118 +4732,100 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
if (stcb->asoc.sctp_nr_sack_on_off == 1) {
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
}
- p_len = sizeof(*pr_supported) + num_ext;
- pr_supported->ph.param_length = htons(p_len);
- bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len);
- SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
+ parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
+ pr_supported->ph.param_length = htons(parameter_len);
+ padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+ chunk_len += parameter_len;
-
- /* ECN nonce: And now tell the peer we support ECN nonce */
- if (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) {
- ecn_nonce = (struct sctp_ecn_nonce_supported_param *)
- ((caddr_t)pr_supported + SCTP_SIZE32(p_len));
- ecn_nonce->ph.param_type = htons(SCTP_ECN_NONCE_SUPPORTED);
- ecn_nonce->ph.param_length = htons(sizeof(*ecn_nonce));
- SCTP_BUF_LEN(m) += sizeof(*ecn_nonce);
- }
/* add authentication parameters */
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
- struct sctp_auth_random *randp;
- struct sctp_auth_hmac_algo *hmacs;
- struct sctp_auth_chunk_list *chunks;
-
/* attach RANDOM parameter, if available */
if (stcb->asoc.authinfo.random != NULL) {
- randp = (struct sctp_auth_random *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
- p_len = sizeof(*randp) + stcb->asoc.authinfo.random_len;
+ struct sctp_auth_random *randp;
+
+ if (padding_len > 0) {
+ memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
+ chunk_len += padding_len;
+ padding_len = 0;
+ }
+ randp = (struct sctp_auth_random *)(mtod(m, caddr_t)+chunk_len);
+ parameter_len = (uint16_t) sizeof(struct sctp_auth_random) + stcb->asoc.authinfo.random_len;
/* random key already contains the header */
- bcopy(stcb->asoc.authinfo.random->key, randp, p_len);
- /* zero out any padding required */
- bzero((caddr_t)randp + p_len, SCTP_SIZE32(p_len) - p_len);
- SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
+ memcpy(randp, stcb->asoc.authinfo.random->key, parameter_len);
+ padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+ chunk_len += parameter_len;
}
/* add HMAC_ALGO parameter */
- hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
- p_len = sctp_serialize_hmaclist(stcb->asoc.local_hmacs,
- (uint8_t *) hmacs->hmac_ids);
- if (p_len > 0) {
- p_len += sizeof(*hmacs);
+ if ((stcb->asoc.local_hmacs != NULL) &&
+ (stcb->asoc.local_hmacs->num_algo > 0)) {
+ struct sctp_auth_hmac_algo *hmacs;
+
+ if (padding_len > 0) {
+ memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
+ chunk_len += padding_len;
+ padding_len = 0;
+ }
+ hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t)+chunk_len);
+ parameter_len = (uint16_t) (sizeof(struct sctp_auth_hmac_algo) +
+ stcb->asoc.local_hmacs->num_algo * sizeof(uint16_t));
hmacs->ph.param_type = htons(SCTP_HMAC_LIST);
- hmacs->ph.param_length = htons(p_len);
- /* zero out any padding required */
- bzero((caddr_t)hmacs + p_len, SCTP_SIZE32(p_len) - p_len);
- SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
+ hmacs->ph.param_length = htons(parameter_len);
+ sctp_serialize_hmaclist(stcb->asoc.local_hmacs, (uint8_t *) hmacs->hmac_ids);
+ padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+ chunk_len += parameter_len;
}
/* add CHUNKS parameter */
- chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
- p_len = sctp_serialize_auth_chunks(stcb->asoc.local_auth_chunks,
- chunks->chunk_types);
- if (p_len > 0) {
- p_len += sizeof(*chunks);
+ if (sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks) > 0) {
+ struct sctp_auth_chunk_list *chunks;
+
+ if (padding_len > 0) {
+ memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
+ chunk_len += padding_len;
+ padding_len = 0;
+ }
+ chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t)+chunk_len);
+ parameter_len = (uint16_t) (sizeof(struct sctp_auth_chunk_list) +
+ sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks));
chunks->ph.param_type = htons(SCTP_CHUNK_LIST);
- chunks->ph.param_length = htons(p_len);
- /* zero out any padding required */
- bzero((caddr_t)chunks + p_len, SCTP_SIZE32(p_len) - p_len);
- SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
+ chunks->ph.param_length = htons(parameter_len);
+ sctp_serialize_auth_chunks(stcb->asoc.local_auth_chunks, chunks->chunk_types);
+ padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+ chunk_len += parameter_len;
}
}
- m_at = m;
- /* now the addresses */
- {
- struct sctp_scoping scp;
-
- /*
- * To optimize this we could put the scoping stuff into a
- * structure and remove the individual uint8's from the
- * assoc structure. Then we could just sifa in the address
- * within the stcb.. but for now this is a quick hack to get
- * the address stuff teased apart.
- */
- scp.ipv4_addr_legal = stcb->asoc.ipv4_addr_legal;
- scp.ipv6_addr_legal = stcb->asoc.ipv6_addr_legal;
- scp.loopback_scope = stcb->asoc.loopback_scope;
- scp.ipv4_local_scope = stcb->asoc.ipv4_local_scope;
- scp.local_scope = stcb->asoc.local_scope;
- scp.site_scope = stcb->asoc.site_scope;
-
- m_at = sctp_add_addresses_to_i_ia(inp, &scp, m_at, cnt_inits_to);
- }
+ SCTP_BUF_LEN(m) = chunk_len;
- /* calulate the size and update pkt header and chunk header */
- p_len = 0;
- for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
- if (SCTP_BUF_NEXT(m_at) == NULL)
- mp_last = m_at;
- p_len += SCTP_BUF_LEN(m_at);
- }
- init->ch.chunk_length = htons(p_len);
+ /* now the addresses */
/*
- * We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return
- * here since the timer will drive a retranmission.
+ * To optimize this we could put the scoping stuff into a structure
+ * and remove the individual uint8's from the assoc structure. Then
+ * we could just sifa in the address within the stcb. But for now
+ * this is a quick hack to get the address stuff teased apart.
*/
+ sctp_add_addresses_to_i_ia(inp, stcb, &stcb->asoc.scope, m, cnt_inits_to, &padding_len, &chunk_len);
- /* I don't expect this to execute but we will be safe here */
- padval = p_len % 4;
- if ((padval) && (mp_last)) {
- /*
- * The compiler worries that mp_last may not be set even
- * though I think it is impossible :-> however we add
- * mp_last here just in case.
- */
- ret = sctp_add_pad_tombuf(mp_last, (4 - padval));
- if (ret) {
- /* Houston we have a problem, no space */
+ init->ch.chunk_length = htons(chunk_len);
+ if (padding_len > 0) {
+ struct mbuf *m_at, *mp_last;
+
+ mp_last = NULL;
+ for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
+ if (SCTP_BUF_NEXT(m_at) == NULL)
+ mp_last = m_at;
+ }
+ if ((mp_last == NULL) || sctp_add_pad_tombuf(mp_last, padding_len)) {
sctp_m_freem(m);
return;
}
- p_len += padval;
}
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - calls lowlevel_output\n");
ret = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
- m, 0, NULL, 0, 0, 0, NULL, 0,
+ m, 0, NULL, 0, 0, 0, 0,
inp->sctp_lport, stcb->rport, htonl(0),
- net->port, so_locked, NULL);
+ net->port, NULL,
+ 0, 0,
+ so_locked);
SCTPDBG(SCTP_DEBUG_OUTPUT4, "lowlevel_output - %d\n", ret);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
(void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time);
@@ -4557,11 +4949,10 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
case SCTP_HAS_NAT_SUPPORT:
*nat_friendly = 1;
/* fall through */
- case SCTP_ECN_NONCE_SUPPORTED:
case SCTP_PRSCTP_SUPPORTED:
if (padded_size != sizeof(struct sctp_paramhdr)) {
- SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error ecnnonce/prsctp/nat support %d\n", plen);
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error prsctp/nat support %d\n", plen);
goto invalid_size;
}
at += padded_size;
@@ -4648,7 +5039,6 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
return (NULL);
}
m_copyback(op_err, err_at, plen, (caddr_t)phdr);
- err_at += plen;
}
return (op_err);
break;
@@ -4781,7 +5171,7 @@ invalid_size:
static int
sctp_are_there_new_addresses(struct sctp_association *asoc,
- struct mbuf *in_initpkt, int iphlen, int offset)
+ struct mbuf *in_initpkt, int offset, struct sockaddr *src)
{
/*
* Given a INIT packet, look through the packet to verify that there
@@ -4790,75 +5180,56 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
* must return (1) to drop the packet if we see a un-understood
* parameter that tells us to drop the chunk.
*/
- struct sockaddr_in sin4, *sa4;
-
-#ifdef INET6
- struct sockaddr_in6 sin6, *sa6;
-
-#endif
struct sockaddr *sa_touse;
struct sockaddr *sa;
struct sctp_paramhdr *phdr, params;
- struct ip *iph;
-
-#ifdef INET6
- struct ip6_hdr *ip6h;
-
-#endif
- struct mbuf *mat;
uint16_t ptype, plen;
- int err_at;
uint8_t fnd;
struct sctp_nets *net;
- memset(&sin4, 0, sizeof(sin4));
+#ifdef INET
+ struct sockaddr_in sin4, *sa4;
+
+#endif
#ifdef INET6
- memset(&sin6, 0, sizeof(sin6));
+ struct sockaddr_in6 sin6, *sa6;
+
#endif
+
+#ifdef INET
+ memset(&sin4, 0, sizeof(sin4));
sin4.sin_family = AF_INET;
sin4.sin_len = sizeof(sin4);
+#endif
#ifdef INET6
+ memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
#endif
- sa_touse = NULL;
/* First what about the src address of the pkt ? */
- iph = mtod(in_initpkt, struct ip *);
- switch (iph->ip_v) {
- case IPVERSION:
- /* source addr is IPv4 */
- sin4.sin_addr = iph->ip_src;
- sa_touse = (struct sockaddr *)&sin4;
- break;
-#ifdef INET6
- case IPV6_VERSION >> 4:
- /* source addr is IPv6 */
- ip6h = mtod(in_initpkt, struct ip6_hdr *);
- sin6.sin6_addr = ip6h->ip6_src;
- sa_touse = (struct sockaddr *)&sin6;
- break;
-#endif
- default:
- return (1);
- }
-
fnd = 0;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
sa = (struct sockaddr *)&net->ro._l_addr;
- if (sa->sa_family == sa_touse->sa_family) {
+ if (sa->sa_family == src->sa_family) {
+#ifdef INET
if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *src4;
+
sa4 = (struct sockaddr_in *)sa;
- if (sa4->sin_addr.s_addr ==
- sin4.sin_addr.s_addr) {
+ src4 = (struct sockaddr_in *)src;
+ if (sa4->sin_addr.s_addr == src4->sin_addr.s_addr) {
fnd = 1;
break;
}
}
+#endif
#ifdef INET6
if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *src6;
+
sa6 = (struct sockaddr_in6 *)sa;
- if (SCTP6_ARE_ADDR_EQUAL(sa6,
- &sin6)) {
+ src6 = (struct sockaddr_in6 *)src;
+ if (SCTP6_ARE_ADDR_EQUAL(sa6, src6)) {
fnd = 1;
break;
}
@@ -4871,41 +5242,51 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
return (1);
}
/* Ok so far lets munge through the rest of the packet */
- mat = in_initpkt;
- err_at = 0;
- sa_touse = NULL;
offset += sizeof(struct sctp_init_chunk);
- phdr = sctp_get_next_param(mat, offset, &params, sizeof(params));
+ phdr = sctp_get_next_param(in_initpkt, offset, &params, sizeof(params));
while (phdr) {
+ sa_touse = NULL;
ptype = ntohs(phdr->param_type);
plen = ntohs(phdr->param_length);
- if (ptype == SCTP_IPV4_ADDRESS) {
- struct sctp_ipv4addr_param *p4, p4_buf;
+ switch (ptype) {
+#ifdef INET
+ case SCTP_IPV4_ADDRESS:
+ {
+ struct sctp_ipv4addr_param *p4, p4_buf;
- phdr = sctp_get_next_param(mat, offset,
- (struct sctp_paramhdr *)&p4_buf, sizeof(p4_buf));
- if (plen != sizeof(struct sctp_ipv4addr_param) ||
- phdr == NULL) {
- return (1);
+ phdr = sctp_get_next_param(in_initpkt, offset,
+ (struct sctp_paramhdr *)&p4_buf, sizeof(p4_buf));
+ if (plen != sizeof(struct sctp_ipv4addr_param) ||
+ phdr == NULL) {
+ return (1);
+ }
+ p4 = (struct sctp_ipv4addr_param *)phdr;
+ sin4.sin_addr.s_addr = p4->addr;
+ sa_touse = (struct sockaddr *)&sin4;
+ break;
}
- p4 = (struct sctp_ipv4addr_param *)phdr;
- sin4.sin_addr.s_addr = p4->addr;
- sa_touse = (struct sockaddr *)&sin4;
- } else if (ptype == SCTP_IPV6_ADDRESS) {
- struct sctp_ipv6addr_param *p6, p6_buf;
+#endif
+#ifdef INET6
+ case SCTP_IPV6_ADDRESS:
+ {
+ struct sctp_ipv6addr_param *p6, p6_buf;
- phdr = sctp_get_next_param(mat, offset,
- (struct sctp_paramhdr *)&p6_buf, sizeof(p6_buf));
- if (plen != sizeof(struct sctp_ipv6addr_param) ||
- phdr == NULL) {
- return (1);
+ phdr = sctp_get_next_param(in_initpkt, offset,
+ (struct sctp_paramhdr *)&p6_buf, sizeof(p6_buf));
+ if (plen != sizeof(struct sctp_ipv6addr_param) ||
+ phdr == NULL) {
+ return (1);
+ }
+ p6 = (struct sctp_ipv6addr_param *)phdr;
+ memcpy((caddr_t)&sin6.sin6_addr, p6->addr,
+ sizeof(p6->addr));
+ sa_touse = (struct sockaddr *)&sin6;
+ break;
}
- p6 = (struct sctp_ipv6addr_param *)phdr;
-#ifdef INET6
- memcpy((caddr_t)&sin6.sin6_addr, p6->addr,
- sizeof(p6->addr));
#endif
- sa_touse = (struct sockaddr *)&sin4;
+ default:
+ sa_touse = NULL;
+ break;
}
if (sa_touse) {
/* ok, sa_touse points to one to check */
@@ -4915,6 +5296,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
if (sa->sa_family != sa_touse->sa_family) {
continue;
}
+#ifdef INET
if (sa->sa_family == AF_INET) {
sa4 = (struct sockaddr_in *)sa;
if (sa4->sin_addr.s_addr ==
@@ -4923,6 +5305,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
break;
}
}
+#endif
#ifdef INET6
if (sa->sa_family == AF_INET6) {
sa6 = (struct sockaddr_in6 *)sa;
@@ -4940,7 +5323,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
}
}
offset += SCTP_SIZE32(plen);
- phdr = sctp_get_next_param(mat, offset, &params, sizeof(params));
+ phdr = sctp_get_next_param(in_initpkt, offset, &params, sizeof(params));
}
return (0);
}
@@ -4953,8 +5336,11 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
*/
void
sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct mbuf *init_pkt, int iphlen, int offset, struct sctphdr *sh,
- struct sctp_init_chunk *init_chk, uint32_t vrf_id, uint16_t port, int hold_inp_lock)
+ struct mbuf *init_pkt, int iphlen, int offset,
+ struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh, struct sctp_init_chunk *init_chk,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port, int hold_inp_lock)
{
struct sctp_association *asoc;
struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last;
@@ -4962,19 +5348,19 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_adaptation_layer_indication *ali;
struct sctp_ecn_supported_param *ecn;
struct sctp_prsctp_supported_param *prsctp;
- struct sctp_ecn_nonce_supported_param *ecn_nonce;
struct sctp_supported_chunk_types_param *pr_supported;
- union sctp_sockstore store, store1, *over_addr;
- struct sockaddr_in *sin, *to_sin;
+ union sctp_sockstore *over_addr;
-#ifdef INET6
- struct sockaddr_in6 *sin6, *to_sin6;
+#ifdef INET
+ struct sockaddr_in *dst4 = (struct sockaddr_in *)dst;
+ struct sockaddr_in *src4 = (struct sockaddr_in *)src;
+ struct sockaddr_in *sin;
#endif
- struct ip *iph;
-
#ifdef INET6
- struct ip6_hdr *ip6;
+ struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
+ struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src;
+ struct sockaddr_in6 *sin6;
#endif
struct sockaddr *to;
@@ -4989,21 +5375,24 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
int nat_friendly = 0;
struct socket *so;
- if (stcb)
+ if (stcb) {
asoc = &stcb->asoc;
- else
+ } else {
asoc = NULL;
+ }
mp_last = NULL;
if ((asoc != NULL) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
- (sctp_are_there_new_addresses(asoc, init_pkt, iphlen, offset))) {
+ (sctp_are_there_new_addresses(asoc, init_pkt, offset, src))) {
/* new addresses, out of here in non-cookie-wait states */
/*
* Send a ABORT, we don't add the new address error clause
* though we even set the T bit and copy in the 0 tag.. this
* looks no different than if no listener was present.
*/
- sctp_send_abort(init_pkt, iphlen, sh, 0, NULL, vrf_id, port);
+ sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, NULL,
+ use_mflowid, mflowid,
+ vrf_id, port);
return;
}
abort_flag = 0;
@@ -5012,8 +5401,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
&abort_flag, (struct sctp_chunkhdr *)init_chk, &nat_friendly);
if (abort_flag) {
do_a_abort:
- sctp_send_abort(init_pkt, iphlen, sh,
- init_chk->init.initiate_tag, op_err, vrf_id, port);
+ sctp_send_abort(init_pkt, iphlen, src, dst, sh,
+ init_chk->init.initiate_tag, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
return;
}
m = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
@@ -5025,6 +5416,14 @@ do_a_abort:
}
SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
+ /*
+ * We might not overwrite the identification[] completely and on
+ * some platforms time_entered will contain some padding. Therefore
+ * zero out the cookie to avoid putting uninitialized memory on the
+ * wire.
+ */
+ memset(&stc, 0, sizeof(struct sctp_state_cookie));
+
/* the time I built cookie */
(void)SCTP_GETTIME_TIMEVAL(&stc.time_entered);
@@ -5052,79 +5451,35 @@ do_a_abort:
*/
stc.site_scope = stc.local_scope = stc.loopback_scope = 0;
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- struct inpcb *in_inp;
-
- /* Its a V6 socket */
- in_inp = (struct inpcb *)inp;
stc.ipv6_addr_legal = 1;
- /* Now look at the binding flag to see if V4 will be legal */
- if (SCTP_IPV6_V6ONLY(in_inp) == 0) {
- stc.ipv4_addr_legal = 1;
- } else {
- /* V4 addresses are NOT legal on the association */
+ if (SCTP_IPV6_V6ONLY(inp)) {
stc.ipv4_addr_legal = 0;
+ } else {
+ stc.ipv4_addr_legal = 1;
}
} else {
- /* Its a V4 socket, no - V6 */
- stc.ipv4_addr_legal = 1;
stc.ipv6_addr_legal = 0;
+ stc.ipv4_addr_legal = 1;
}
-
#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE
stc.ipv4_scope = 1;
#else
stc.ipv4_scope = 0;
#endif
- /* now for scope setup */
- memset((caddr_t)&store, 0, sizeof(store));
- memset((caddr_t)&store1, 0, sizeof(store1));
- sin = &store.sin;
- to_sin = &store1.sin;
-#ifdef INET6
- sin6 = &store.sin6;
- to_sin6 = &store1.sin6;
-#endif
- iph = mtod(init_pkt, struct ip *);
- /* establish the to_addr's */
- switch (iph->ip_v) {
- case IPVERSION:
- to_sin->sin_port = sh->dest_port;
- to_sin->sin_family = AF_INET;
- to_sin->sin_len = sizeof(struct sockaddr_in);
- to_sin->sin_addr = iph->ip_dst;
- break;
-#ifdef INET6
- case IPV6_VERSION >> 4:
- ip6 = mtod(init_pkt, struct ip6_hdr *);
- to_sin6->sin6_addr = ip6->ip6_dst;
- to_sin6->sin6_scope_id = 0;
- to_sin6->sin6_port = sh->dest_port;
- to_sin6->sin6_family = AF_INET6;
- to_sin6->sin6_len = sizeof(struct sockaddr_in6);
- break;
-#endif
- default:
- goto do_a_abort;
- break;
- };
-
if (net == NULL) {
- to = (struct sockaddr *)&store;
- switch (iph->ip_v) {
- case IPVERSION:
+ to = src;
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
{
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(struct sockaddr_in);
- sin->sin_port = sh->src_port;
- sin->sin_addr = iph->ip_src;
/* lookup address */
- stc.address[0] = sin->sin_addr.s_addr;
+ stc.address[0] = src4->sin_addr.s_addr;
stc.address[1] = 0;
stc.address[2] = 0;
stc.address[3] = 0;
stc.addr_type = SCTP_IPV4_ADDRESS;
/* local from address */
- stc.laddress[0] = to_sin->sin_addr.s_addr;
+ stc.laddress[0] = dst4->sin_addr.s_addr;
stc.laddress[1] = 0;
stc.laddress[2] = 0;
stc.laddress[3] = 0;
@@ -5132,14 +5487,14 @@ do_a_abort:
/* scope_id is only for v6 */
stc.scope_id = 0;
#ifndef SCTP_DONT_DO_PRIVADDR_SCOPE
- if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
+ if (IN4_ISPRIVATE_ADDRESS(&src4->sin_addr)) {
stc.ipv4_scope = 1;
}
#else
stc.ipv4_scope = 1;
#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */
/* Must use the address in this case */
- if (sctp_is_address_on_local_host((struct sockaddr *)sin, vrf_id)) {
+ if (sctp_is_address_on_local_host(src, vrf_id)) {
stc.loopback_scope = 1;
stc.ipv4_scope = 1;
stc.site_scope = 1;
@@ -5147,33 +5502,19 @@ do_a_abort:
}
break;
}
+#endif
#ifdef INET6
- case IPV6_VERSION >> 4:
+ case AF_INET6:
{
- ip6 = mtod(init_pkt, struct ip6_hdr *);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- sin6->sin6_port = sh->src_port;
- sin6->sin6_addr = ip6->ip6_src;
- /* lookup address */
- memcpy(&stc.address, &sin6->sin6_addr,
- sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
stc.addr_type = SCTP_IPV6_ADDRESS;
- stc.scope_id = 0;
- if (sctp_is_address_on_local_host((struct sockaddr *)sin6, vrf_id)) {
- /*
- * FIX ME: does this have scope from
- * rcvif?
- */
- (void)sa6_recoverscope(sin6);
- stc.scope_id = sin6->sin6_scope_id;
- sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone));
+ memcpy(&stc.address, &src6->sin6_addr, sizeof(struct in6_addr));
+ stc.scope_id = in6_getscope(&src6->sin6_addr);
+ if (sctp_is_address_on_local_host(src, vrf_id)) {
stc.loopback_scope = 1;
stc.local_scope = 0;
stc.site_scope = 1;
stc.ipv4_scope = 1;
- } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ } else if (IN6_IS_ADDR_LINKLOCAL(&src6->sin6_addr)) {
/*
* If the new destination is a
* LINK_LOCAL we must have common
@@ -5198,14 +5539,7 @@ do_a_abort:
* pull out the scope_id from
* incoming pkt
*/
- /*
- * FIX ME: does this have scope from
- * rcvif?
- */
- (void)sa6_recoverscope(sin6);
- stc.scope_id = sin6->sin6_scope_id;
- sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone));
- } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
+ } else if (IN6_IS_ADDR_SITELOCAL(&src6->sin6_addr)) {
/*
* If the new destination is
* SITE_LOCAL then we must have site
@@ -5213,7 +5547,7 @@ do_a_abort:
*/
stc.site_scope = 1;
}
- memcpy(&stc.laddress, &to_sin6->sin6_addr, sizeof(struct in6_addr));
+ memcpy(&stc.laddress, &dst6->sin6_addr, sizeof(struct in6_addr));
stc.laddr_type = SCTP_IPV6_ADDRESS;
break;
}
@@ -5231,10 +5565,10 @@ do_a_abort:
#endif
- stc.loopback_scope = asoc->loopback_scope;
- stc.ipv4_scope = asoc->ipv4_local_scope;
- stc.site_scope = asoc->site_scope;
- stc.local_scope = asoc->local_scope;
+ stc.loopback_scope = asoc->scope.loopback_scope;
+ stc.ipv4_scope = asoc->scope.ipv4_local_scope;
+ stc.site_scope = asoc->scope.site_scope;
+ stc.local_scope = asoc->scope.local_scope;
#ifdef INET6
/* Why do we not consider IPv4 LL addresses? */
TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) {
@@ -5252,6 +5586,7 @@ do_a_abort:
/* use the net pointer */
to = (struct sockaddr *)&net->ro._l_addr;
switch (to->sa_family) {
+#ifdef INET
case AF_INET:
sin = (struct sockaddr_in *)to;
stc.address[0] = sin->sin_addr.s_addr;
@@ -5278,17 +5613,21 @@ do_a_abort:
stc.laddress[2] = 0;
stc.laddress[3] = 0;
stc.laddr_type = SCTP_IPV4_ADDRESS;
+ /* scope_id is only for v6 */
+ stc.scope_id = 0;
break;
+#endif
#ifdef INET6
case AF_INET6:
sin6 = (struct sockaddr_in6 *)to;
memcpy(&stc.address, &sin6->sin6_addr,
sizeof(struct in6_addr));
stc.addr_type = SCTP_IPV6_ADDRESS;
+ stc.scope_id = sin6->sin6_scope_id;
if (net->src_addr_selected == 0) {
/*
* strange case here, the INIT should have
- * did the selection.
+ * done the selection.
*/
net->ro._s_addr = sctp_source_address_selection(inp,
stcb, (sctp_route_t *) & net->ro,
@@ -5312,6 +5651,7 @@ do_a_abort:
/* who are we */
memcpy(stc.identification, SCTP_VERSION_STRING,
min(strlen(SCTP_VERSION_STRING), sizeof(stc.identification)));
+ memset(stc.reserved, 0, SCTP_RESERVE_SPACE);
/* now the chunk header */
initack->ch.chunk_type = SCTP_INITIATION_ACK;
initack->ch.chunk_flags = 0;
@@ -5392,20 +5732,25 @@ do_a_abort:
/* I can have what I want :> */
initack->init.num_outbound_streams = htons(i_want);
}
- /* tell him his limt. */
+ /* tell him his limit. */
initack->init.num_inbound_streams =
htons(inp->sctp_ep.max_open_streams_intome);
/* adaptation layer indication parameter */
- ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initack + sizeof(*initack));
- ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
- ali->ph.param_length = htons(sizeof(*ali));
- ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
- SCTP_BUF_LEN(m) += sizeof(*ali);
- ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali));
+ if (inp->sctp_ep.adaptation_layer_indicator_provided) {
+ ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initack + sizeof(*initack));
+ ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
+ ali->ph.param_length = htons(sizeof(*ali));
+ ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
+ SCTP_BUF_LEN(m) += sizeof(*ali);
+ ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali));
+ } else {
+ ecn = (struct sctp_ecn_supported_param *)((caddr_t)initack + sizeof(*initack));
+ }
/* ECN parameter */
- if (SCTP_BASE_SYSCTL(sctp_ecn_enable) == 1) {
+ if (((asoc != NULL) && (asoc->ecn_allowed == 1)) ||
+ (inp->sctp_ecn_enable == 1)) {
ecn->ph.param_type = htons(SCTP_ECN_CAPABLE);
ecn->ph.param_length = htons(sizeof(*ecn));
SCTP_BUF_LEN(m) += sizeof(*ecn);
@@ -5446,14 +5791,6 @@ do_a_abort:
bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len);
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
- /* ECN nonce: And now tell the peer we support ECN nonce */
- if (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) {
- ecn_nonce = (struct sctp_ecn_nonce_supported_param *)
- ((caddr_t)pr_supported + SCTP_SIZE32(p_len));
- ecn_nonce->ph.param_type = htons(SCTP_ECN_NONCE_SUPPORTED);
- ecn_nonce->ph.param_length = htons(sizeof(*ecn_nonce));
- SCTP_BUF_LEN(m) += sizeof(*ecn_nonce);
- }
/* add authentication parameters */
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
struct sctp_auth_random *randp;
@@ -5515,7 +5852,7 @@ do_a_abort:
scp.ipv4_local_scope = stc.ipv4_scope;
scp.local_scope = stc.local_scope;
scp.site_scope = stc.site_scope;
- m_at = sctp_add_addresses_to_i_ia(inp, &scp, m_at, cnt_inits_to);
+ m_at = sctp_add_addresses_to_i_ia(inp, stcb, &scp, m_at, cnt_inits_to, NULL, NULL);
}
/* tack on the operational error if present */
@@ -5525,6 +5862,7 @@ do_a_abort:
llen = 0;
ol = op_err;
+
while (ol) {
llen += SCTP_BUF_LEN(ol);
ol = SCTP_BUF_NEXT(ol);
@@ -5556,7 +5894,7 @@ do_a_abort:
}
/* Now we must build a cookie */
- m_cookie = sctp_add_cookie(inp, init_pkt, offset, m, 0, &stc, &signature);
+ m_cookie = sctp_add_cookie(init_pkt, offset, m, 0, &stc, &signature);
if (m_cookie == NULL) {
/* memory problem */
sctp_m_freem(m);
@@ -5594,76 +5932,28 @@ do_a_abort:
padval = p_len % 4;
if ((padval) && (mp_last)) {
/* see my previous comments on mp_last */
- int ret;
-
- ret = sctp_add_pad_tombuf(mp_last, (4 - padval));
- if (ret) {
+ if (sctp_add_pad_tombuf(mp_last, (4 - padval))) {
/* Houston we have a problem, no space */
sctp_m_freem(m);
return;
}
- p_len += padval;
}
if (stc.loopback_scope) {
- over_addr = &store1;
+ over_addr = (union sctp_sockstore *)dst;
} else {
over_addr = NULL;
}
(void)sctp_lowlevel_chunk_output(inp, NULL, NULL, to, m, 0, NULL, 0, 0,
- 0, NULL, 0,
+ 0, 0,
inp->sctp_lport, sh->src_port, init_chk->init.initiate_tag,
- port, SCTP_SO_NOT_LOCKED, over_addr);
+ port, over_addr,
+ use_mflowid, mflowid,
+ SCTP_SO_NOT_LOCKED);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
}
-void
-sctp_insert_on_wheel(struct sctp_tcb *stcb,
- struct sctp_association *asoc,
- struct sctp_stream_out *strq, int holds_lock)
-{
- if (holds_lock == 0) {
- SCTP_TCB_SEND_LOCK(stcb);
- }
- if ((strq->next_spoke.tqe_next == NULL) &&
- (strq->next_spoke.tqe_prev == NULL)) {
- TAILQ_INSERT_TAIL(&asoc->out_wheel, strq, next_spoke);
- }
- if (holds_lock == 0) {
- SCTP_TCB_SEND_UNLOCK(stcb);
- }
-}
-
-void
-sctp_remove_from_wheel(struct sctp_tcb *stcb,
- struct sctp_association *asoc,
- struct sctp_stream_out *strq,
- int holds_lock)
-{
- /* take off and then setup so we know it is not on the wheel */
- if (holds_lock == 0) {
- SCTP_TCB_SEND_LOCK(stcb);
- }
- if (TAILQ_EMPTY(&strq->outqueue)) {
- if (asoc->last_out_stream == strq) {
- asoc->last_out_stream = TAILQ_PREV(asoc->last_out_stream, sctpwheel_listhead, next_spoke);
- if (asoc->last_out_stream == NULL) {
- asoc->last_out_stream = TAILQ_LAST(&asoc->out_wheel, sctpwheel_listhead);
- }
- if (asoc->last_out_stream == strq) {
- asoc->last_out_stream = NULL;
- }
- }
- TAILQ_REMOVE(&asoc->out_wheel, strq, next_spoke);
- strq->next_spoke.tqe_next = NULL;
- strq->next_spoke.tqe_prev = NULL;
- }
- if (holds_lock == 0) {
- SCTP_TCB_SEND_UNLOCK(stcb);
- }
-}
-
static void
sctp_prune_prsctp(struct sctp_tcb *stcb,
struct sctp_association *asoc,
@@ -5702,14 +5992,14 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
* if the mbuf is here
*/
int ret_spc;
- int cause;
+ uint8_t sent;
if (chk->sent > SCTP_DATAGRAM_UNSENT)
- cause = SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT;
+ sent = 1;
else
- cause = SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_UNSENT;
+ sent = 0;
ret_spc = sctp_release_pr_sctp_chunk(stcb, chk,
- cause,
+ sent,
SCTP_SO_LOCKED);
freed_spc += ret_spc;
if (freed_spc >= dataout) {
@@ -5720,9 +6010,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
} /* if chunk has enabled */
} /* tailqforeach */
- chk = TAILQ_FIRST(&asoc->send_queue);
- while (chk) {
- nchk = TAILQ_NEXT(chk, sctp_next);
+ TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
/* Here we must move to the sent queue and mark */
if (PR_SCTP_BUF_ENABLED(chk->flags)) {
if (chk->rec.data.timetodrop.tv_sec >= (long)srcv->sinfo_timetolive) {
@@ -5734,8 +6022,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
int ret_spc;
ret_spc = sctp_release_pr_sctp_chunk(stcb, chk,
- SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_UNSENT,
- SCTP_SO_LOCKED);
+ 0, SCTP_SO_LOCKED);
freed_spc += ret_spc;
if (freed_spc >= dataout) {
@@ -5744,8 +6031,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
} /* end if chk->data */
} /* end if right class */
} /* end if chk pr-sctp */
- chk = nchk;
- } /* end while (chk) */
+ } /* tailqforeachsafe (chk) */
} /* if enabled in asoc */
}
@@ -5850,7 +6136,7 @@ sctp_msg_append(struct sctp_tcb *stcb,
struct mbuf *m,
struct sctp_sndrcvinfo *srcv, int hold_stcb_lock)
{
- int error = 0, holds_lock;
+ int error = 0;
struct mbuf *at;
struct sctp_stream_queue_pending *sp = NULL;
struct sctp_stream_out *strm;
@@ -5859,7 +6145,6 @@ sctp_msg_append(struct sctp_tcb *stcb,
* Given an mbuf chain, put it into the association send queue and
* place it on the wheel
*/
- holds_lock = hold_stcb_lock;
if (srcv->sinfo_stream >= stcb->asoc.streamoutcnt) {
/* Invalid stream number */
SCTP_LTRACE_ERR_RET_PKT(m, NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
@@ -5893,7 +6178,6 @@ sctp_msg_append(struct sctp_tcb *stcb,
sp->timetolive = srcv->sinfo_timetolive;
sp->ppid = srcv->sinfo_ppid;
sp->context = srcv->sinfo_context;
- sp->strseq = 0;
if (sp->sinfo_flags & SCTP_ADDR_OVER) {
sp->net = net;
atomic_add_int(&sp->net->ref_count, 1);
@@ -5907,35 +6191,38 @@ sctp_msg_append(struct sctp_tcb *stcb,
sp->some_taken = 0;
sp->data = m;
sp->tail_mbuf = NULL;
- sp->length = 0;
- at = m;
sctp_set_prsctp_policy(sp);
/*
* We could in theory (for sendall) sifa the length in, but we would
* still have to hunt through the chain since we need to setup the
* tail_mbuf
*/
- while (at) {
+ sp->length = 0;
+ for (at = m; at; at = SCTP_BUF_NEXT(at)) {
if (SCTP_BUF_NEXT(at) == NULL)
sp->tail_mbuf = at;
sp->length += SCTP_BUF_LEN(at);
- at = SCTP_BUF_NEXT(at);
}
- SCTP_TCB_SEND_LOCK(stcb);
+ if (srcv->sinfo_keynumber_valid) {
+ sp->auth_keyid = srcv->sinfo_keynumber;
+ } else {
+ sp->auth_keyid = stcb->asoc.authinfo.active_keyid;
+ }
+ if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
+ sctp_auth_key_acquire(stcb, sp->auth_keyid);
+ sp->holds_key_ref = 1;
+ }
+ if (hold_stcb_lock == 0) {
+ SCTP_TCB_SEND_LOCK(stcb);
+ }
sctp_snd_sb_alloc(stcb, sp->length);
atomic_add_int(&stcb->asoc.stream_queue_cnt, 1);
TAILQ_INSERT_TAIL(&strm->outqueue, sp, next);
- if ((srcv->sinfo_flags & SCTP_UNORDERED) == 0) {
- sp->strseq = strm->next_sequence_sent;
- strm->next_sequence_sent++;
- }
- if ((strm->next_spoke.tqe_next == NULL) &&
- (strm->next_spoke.tqe_prev == NULL)) {
- /* Not on wheel, insert */
- sctp_insert_on_wheel(stcb, &stcb->asoc, strm, 1);
- }
+ stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, &stcb->asoc, strm, sp, 1);
m = NULL;
- SCTP_TCB_SEND_UNLOCK(stcb);
+ if (hold_stcb_lock == 0) {
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ }
out_now:
if (m) {
sctp_m_freem(m);
@@ -6049,12 +6336,10 @@ error_out:
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = appendchain;
- while (mat) {
+ for (mat = appendchain; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -6106,7 +6391,7 @@ error_out:
}
}
-int
+static int
sctp_med_chunk_output(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_association *asoc,
@@ -6121,7 +6406,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
static void
sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
- uint32_t val)
+ uint32_t val SCTP_UNUSED)
{
struct sctp_copy_all *ca;
struct mbuf *m;
@@ -6129,6 +6414,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
int added_control = 0;
int un_sent, do_chunk_output = 1;
struct sctp_association *asoc;
+ struct sctp_nets *net;
ca = (struct sctp_copy_all *)ptr;
if (ca->m == NULL) {
@@ -6149,12 +6435,10 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = m;
- while (mat) {
+ for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -6162,6 +6446,11 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
m = NULL;
}
SCTP_TCB_LOCK_ASSERT(stcb);
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
if (ca->sndrcv.sinfo_flags & SCTP_ABORT) {
/* Abort this assoc with m as the user defined reason */
if (m) {
@@ -6171,16 +6460,14 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
if (m) {
ph = mtod(m, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
- ph->param_length = htons(ca->sndlen);
+ ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen);
}
/*
* We add one here to keep the assoc from
* dis-appearing on us.
*/
atomic_add_int(&stcb->asoc.refcnt, 1);
- sctp_abort_an_association(inp, stcb,
- SCTP_RESPONSE_TO_USER_REQ,
- m, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED);
/*
* sctp_abort_an_association calls sctp_free_asoc()
* free association will NOT free it since we
@@ -6200,7 +6487,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
}
} else {
if (m) {
- ret = sctp_msg_append(stcb, stcb->asoc.primary_destination, m,
+ ret = sctp_msg_append(stcb, net, m,
&ca->sndrcv, 1);
}
asoc = &stcb->asoc;
@@ -6208,7 +6495,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
/* shutdown this assoc */
int cnt;
- cnt = sctp_is_there_unsent_data(stcb);
+ cnt = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED);
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
@@ -6227,14 +6514,15 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
* only send SHUTDOWN the first time
* through
*/
- sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(stcb);
+ sctp_send_shutdown(stcb, net);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ net);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
asoc->primary_destination);
added_control = 1;
@@ -6274,7 +6562,6 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
abort_anyway:
atomic_add_int(&stcb->asoc.refcnt, 1);
sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_RESPONSE_TO_USER_REQ,
NULL, SCTP_SO_NOT_LOCKED);
atomic_add_int(&stcb->asoc.refcnt, -1);
goto no_chunk_output;
@@ -6315,7 +6602,7 @@ no_chunk_output:
}
static void
-sctp_sendall_completes(void *ptr, uint32_t val)
+sctp_sendall_completes(void *ptr, uint32_t val SCTP_UNUSED)
{
struct sctp_copy_all *ca;
@@ -6400,7 +6687,9 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
memset(ca, 0, sizeof(struct sctp_copy_all));
ca->inp = inp;
- memcpy(&ca->sndrcv, srcv, sizeof(struct sctp_nonpad_sndrcvinfo));
+ if (srcv) {
+ memcpy(&ca->sndrcv, srcv, sizeof(struct sctp_nonpad_sndrcvinfo));
+ }
/*
* take off the sendall flag, it would be bad if we failed to do
* this :-0
@@ -6447,9 +6736,7 @@ sctp_toss_old_cookies(struct sctp_tcb *stcb, struct sctp_association *asoc)
{
struct sctp_tmit_chunk *chk, *nchk;
- chk = TAILQ_FIRST(&asoc->control_send_queue);
- while (chk) {
- nchk = TAILQ_NEXT(chk, sctp_next);
+ TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
if (chk->rec.chunk_id.id == SCTP_COOKIE_ECHO) {
TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
if (chk->data) {
@@ -6457,9 +6744,8 @@ sctp_toss_old_cookies(struct sctp_tcb *stcb, struct sctp_association *asoc)
chk->data = NULL;
}
asoc->ctrl_queue_cnt--;
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
}
- chk = nchk;
}
}
@@ -6467,19 +6753,16 @@ void
sctp_toss_old_asconf(struct sctp_tcb *stcb)
{
struct sctp_association *asoc;
- struct sctp_tmit_chunk *chk, *chk_tmp;
+ struct sctp_tmit_chunk *chk, *nchk;
struct sctp_asconf_chunk *acp;
asoc = &stcb->asoc;
- for (chk = TAILQ_FIRST(&asoc->asconf_send_queue); chk != NULL;
- chk = chk_tmp) {
- /* get next chk */
- chk_tmp = TAILQ_NEXT(chk, sctp_next);
+ TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) {
/* find SCTP_ASCONF chunk in queue */
if (chk->rec.chunk_id.id == SCTP_ASCONF) {
if (chk->data) {
acp = mtod(chk->data, struct sctp_asconf_chunk *);
- if (compare_with_wrap(ntohl(acp->serial_number), stcb->asoc.asconf_seq_out_acked, MAX_SEQ)) {
+ if (SCTP_TSN_GT(ntohl(acp->serial_number), asoc->asconf_seq_out_acked)) {
/* Not Acked yet */
break;
}
@@ -6490,7 +6773,7 @@ sctp_toss_old_asconf(struct sctp_tcb *stcb)
chk->data = NULL;
}
asoc->ctrl_queue_cnt--;
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
}
}
}
@@ -6520,6 +6803,7 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb,
}
/* record time */
data_list[i]->sent_rcv_time = net->last_sent_time;
+ data_list[i]->rec.data.cwnd_at_send = net->cwnd;
data_list[i]->rec.data.fast_retran_tsn = data_list[i]->rec.data.TSN_seq;
if (data_list[i]->whoTo == NULL) {
data_list[i]->whoTo = net;
@@ -6527,8 +6811,7 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb,
}
/* on to the sent queue */
tp1 = TAILQ_LAST(&asoc->sent_queue, sctpchunk_listhead);
- if ((tp1) && (compare_with_wrap(tp1->rec.data.TSN_seq,
- data_list[i]->rec.data.TSN_seq, MAX_TSN))) {
+ if ((tp1) && SCTP_TSN_GT(tp1->rec.data.TSN_seq, data_list[i]->rec.data.TSN_seq)) {
struct sctp_tmit_chunk *tpp;
/* need to move back */
@@ -6539,8 +6822,7 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb,
goto all_done;
}
tp1 = tpp;
- if (compare_with_wrap(tp1->rec.data.TSN_seq,
- data_list[i]->rec.data.TSN_seq, MAX_TSN)) {
+ if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, data_list[i]->rec.data.TSN_seq)) {
goto back_up_more;
}
TAILQ_INSERT_AFTER(&asoc->sent_queue, tp1, data_list[i], sctp_next);
@@ -6584,16 +6866,21 @@ all_done:
asoc->peers_rwnd = 0;
}
}
+ if (asoc->cc_functions.sctp_cwnd_update_packet_transmitted) {
+ (*asoc->cc_functions.sctp_cwnd_update_packet_transmitted) (stcb, net);
+ }
}
static void
-sctp_clean_up_ctl(struct sctp_tcb *stcb, struct sctp_association *asoc)
+sctp_clean_up_ctl(struct sctp_tcb *stcb, struct sctp_association *asoc, int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+ SCTP_UNUSED
+#endif
+)
{
struct sctp_tmit_chunk *chk, *nchk;
- for (chk = TAILQ_FIRST(&asoc->control_send_queue);
- chk; chk = nchk) {
- nchk = TAILQ_NEXT(chk, sctp_next);
+ TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
if ((chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) ||
(chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK) || /* EY */
(chk->rec.chunk_id.id == SCTP_HEARTBEAT_REQUEST) ||
@@ -6616,7 +6903,7 @@ sctp_clean_up_ctl(struct sctp_tcb *stcb, struct sctp_association *asoc)
asoc->ctrl_queue_cnt--;
if (chk->rec.chunk_id.id == SCTP_FORWARD_CUM_TSN)
asoc->fwd_tsn_cnt--;
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, so_locked);
} else if (chk->rec.chunk_id.id == SCTP_STREAM_RESET) {
/* special handling, we must look into the param */
if (chk != asoc->str_reset) {
@@ -6696,7 +6983,12 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
int *locked,
int *giveup,
int eeor_mode,
- int *bail)
+ int *bail,
+ int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+ SCTP_UNUSED
+#endif
+)
{
/* Move from the stream to the send_queue keeping track of the total */
struct sctp_association *asoc;
@@ -6758,6 +7050,7 @@ one_more_time:
}
atomic_subtract_int(&asoc->stream_queue_cnt, 1);
TAILQ_REMOVE(&strq->outqueue, sp, next);
+ stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up);
if (sp->net) {
sctp_free_remote_addr(sp->net);
sp->net = NULL;
@@ -6766,7 +7059,7 @@ one_more_time:
sctp_m_freem(sp->data);
sp->data = NULL;
}
- sctp_free_a_strmoq(stcb, sp);
+ sctp_free_a_strmoq(stcb, sp, so_locked);
/* we can't be locked to it */
*locked = 0;
stcb->asoc.locked_on_sending = NULL;
@@ -6932,7 +7225,7 @@ dont_do_it:
chk->last_mbuf = NULL;
if (chk->data == NULL) {
sp->some_taken = some_taken;
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, so_locked);
*bail = 1;
to_move = 0;
goto out_of;
@@ -6941,12 +7234,10 @@ dont_do_it:
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = chk->data;
- while (mat) {
+ for (mat = chk->data; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -7036,7 +7327,7 @@ dont_do_it:
atomic_add_int(&sp->length, to_move);
chk->data = NULL;
*bail = 1;
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, so_locked);
to_move = 0;
goto out_of;
} else {
@@ -7053,7 +7344,7 @@ dont_do_it:
panic("prepend failes HELP?");
#else
SCTP_PRINTF("prepend fails HELP?\n");
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, so_locked);
#endif
*bail = 1;
to_move = 0;
@@ -7068,12 +7359,14 @@ dont_do_it:
chk->asoc = &stcb->asoc;
chk->pad_inplace = 0;
chk->no_fr_allowed = 0;
- chk->rec.data.stream_seq = sp->strseq;
+ chk->rec.data.stream_seq = strq->next_sequence_send;
+ if (rcv_flags & SCTP_DATA_LAST_FRAG) {
+ strq->next_sequence_send++;
+ }
chk->rec.data.stream_number = sp->stream;
chk->rec.data.payloadtype = sp->ppid;
chk->rec.data.context = sp->context;
chk->rec.data.doing_fast_retransmit = 0;
- chk->rec.data.ect_nonce = 0; /* ECN Nonce */
chk->rec.data.timetodrop = sp->ts;
chk->flags = sp->act_flags;
@@ -7167,6 +7460,7 @@ dont_do_it:
send_lock_up = 1;
}
TAILQ_REMOVE(&strq->outqueue, sp, next);
+ stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up);
if (sp->net) {
sctp_free_remote_addr(sp->net);
sp->net = NULL;
@@ -7175,7 +7469,7 @@ dont_do_it:
sctp_m_freem(sp->data);
sp->data = NULL;
}
- sctp_free_a_strmoq(stcb, sp);
+ sctp_free_a_strmoq(stcb, sp, so_locked);
/* we can't be locked to it */
*locked = 0;
@@ -7185,57 +7479,48 @@ dont_do_it:
*locked = 1;
}
asoc->chunks_on_out_queue++;
+ strq->chunks_on_queues++;
TAILQ_INSERT_TAIL(&asoc->send_queue, chk, sctp_next);
asoc->send_queue_cnt++;
out_of:
if (send_lock_up) {
SCTP_TCB_SEND_UNLOCK(stcb);
- send_lock_up = 0;
}
return (to_move);
}
-static struct sctp_stream_out *
-sctp_select_a_stream(struct sctp_tcb *stcb, struct sctp_association *asoc)
-{
- struct sctp_stream_out *strq;
-
- /* Find the next stream to use */
- if (asoc->last_out_stream == NULL) {
- strq = TAILQ_FIRST(&asoc->out_wheel);
- } else {
- strq = TAILQ_NEXT(asoc->last_out_stream, next_spoke);
- if (strq == NULL) {
- strq = TAILQ_FIRST(&asoc->out_wheel);
- }
- }
- return (strq);
-}
-
-
static void
sctp_fill_outqueue(struct sctp_tcb *stcb,
- struct sctp_nets *net, int frag_point, int eeor_mode, int *quit_now)
+ struct sctp_nets *net, int frag_point, int eeor_mode, int *quit_now, int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+ SCTP_UNUSED
+#endif
+)
{
struct sctp_association *asoc;
- struct sctp_stream_out *strq, *strqn;
+ struct sctp_stream_out *strq;
int goal_mtu, moved_how_much, total_moved = 0, bail = 0;
int locked, giveup;
- struct sctp_stream_queue_pending *sp;
SCTP_TCB_LOCK_ASSERT(stcb);
asoc = &stcb->asoc;
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ goal_mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+ break;
+#endif
#ifdef INET6
- if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
+ case AF_INET6:
goal_mtu = net->mtu - SCTP_MIN_OVERHEAD;
- } else {
- /* ?? not sure what else to do */
- goal_mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
- }
-#else
- goal_mtu = net->mtu - SCTP_MIN_OVERHEAD;
+ break;
#endif
+ default:
+ /* TSNH */
+ goal_mtu = net->mtu;
+ break;
+ }
/* Need an allowance for the data chunk header too */
goal_mtu -= sizeof(struct sctp_data_chunk);
@@ -7246,46 +7531,16 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
strq = asoc->locked_on_sending;
locked = 1;
} else {
- strq = sctp_select_a_stream(stcb, asoc);
+ strq = stcb->asoc.ss_functions.sctp_ss_select_stream(stcb, net, asoc);
locked = 0;
}
- strqn = strq;
while ((goal_mtu > 0) && strq) {
- sp = TAILQ_FIRST(&strq->outqueue);
- if (sp == NULL) {
- break;
- }
- /**
- * Honor the users' choice if given. If not given,
- * pull it only to the primary path in case of not using
- * CMT.
- */
- if (((sp->net != NULL) &&
- (sp->net != net)) ||
- ((sp->net == NULL) &&
- (asoc->sctp_cmt_on_off == 0) &&
- (asoc->primary_destination != net))) {
- /* Do not pull to this network */
- if (locked) {
- break;
- } else {
- strq = sctp_select_a_stream(stcb, asoc);
- if (strq == NULL)
- /* none left */
- break;
- if (strqn == strq) {
- /* I have circled */
- break;
- }
- continue;
- }
- }
giveup = 0;
bail = 0;
moved_how_much = sctp_move_to_outqueue(stcb, strq, goal_mtu, frag_point, &locked,
- &giveup, eeor_mode, &bail);
+ &giveup, eeor_mode, &bail, so_locked);
if (moved_how_much)
- asoc->last_out_stream = strq;
+ stcb->asoc.ss_functions.sctp_ss_scheduled(stcb, net, asoc, strq, moved_how_much);
if (locked) {
asoc->locked_on_sending = strq;
@@ -7294,23 +7549,10 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
break;
} else {
asoc->locked_on_sending = NULL;
- if (TAILQ_EMPTY(&strq->outqueue)) {
- if (strq == strqn) {
- /* Must move start to next one */
- strqn = TAILQ_NEXT(strq, next_spoke);
- if (strqn == NULL) {
- strqn = TAILQ_FIRST(&asoc->out_wheel);
- if (strqn == NULL) {
- break;
- }
- }
- }
- sctp_remove_from_wheel(stcb, asoc, strq, 0);
- }
if ((giveup) || bail) {
break;
}
- strq = sctp_select_a_stream(stcb, asoc);
+ strq = stcb->asoc.ss_functions.sctp_ss_select_stream(stcb, net, asoc);
if (strq == NULL) {
break;
}
@@ -7322,12 +7564,14 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
if (bail)
*quit_now = 1;
+ stcb->asoc.ss_functions.sctp_ss_packet_done(stcb, net, asoc);
+
if (total_moved == 0) {
if ((stcb->asoc.sctp_cmt_on_off == 0) &&
(net == stcb->asoc.primary_destination)) {
/* ran dry for primary network net */
SCTP_STAT_INCR(sctps_primary_randry);
- } else if (stcb->asoc.sctp_cmt_on_off == 1) {
+ } else if (stcb->asoc.sctp_cmt_on_off > 0) {
/* ran dry with CMT on */
SCTP_STAT_INCR(sctps_cmt_randry);
}
@@ -7350,16 +7594,16 @@ void
sctp_move_chunks_from_net(struct sctp_tcb *stcb, struct sctp_nets *net)
{
struct sctp_association *asoc;
- struct sctp_stream_out *outs;
struct sctp_tmit_chunk *chk;
struct sctp_stream_queue_pending *sp;
+ unsigned int i;
if (net == NULL) {
return;
}
asoc = &stcb->asoc;
- TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
- TAILQ_FOREACH(sp, &outs->outqueue, next) {
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ TAILQ_FOREACH(sp, &stcb->asoc.strmout[i].outqueue, next) {
if (sp->net == net) {
sctp_free_remote_addr(sp->net);
sp->net = NULL;
@@ -7396,7 +7640,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
* fomulate and send the low level chunks. Making sure to combine
* any control in the control chunk queue also.
*/
- struct sctp_nets *net, *start_at, *old_start_at = NULL;
+ struct sctp_nets *net, *start_at, *sack_goes_to = NULL, *old_start_at = NULL;
struct mbuf *outchain, *endoutchain;
struct sctp_tmit_chunk *chk, *nchk;
@@ -7413,13 +7657,13 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
struct sctp_auth_chunk *auth = NULL;
uint16_t auth_keyid;
int override_ok = 1;
+ int skip_fill_up = 0;
int data_auth_reqd = 0;
/*
* JRS 5/14/07 - Add flag for whether a heartbeat is sent to the
* destination.
*/
- int pf_hbflag = 0;
int quit_now = 0;
*num_out = 0;
@@ -7449,10 +7693,12 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
no_data_chunks = 0;
/* Nothing to possible to send? */
- if (TAILQ_EMPTY(&asoc->control_send_queue) &&
+ if ((TAILQ_EMPTY(&asoc->control_send_queue) ||
+ (asoc->ctrl_queue_cnt == stcb->asoc.ecn_echo_cnt_onq)) &&
TAILQ_EMPTY(&asoc->asconf_send_queue) &&
TAILQ_EMPTY(&asoc->send_queue) &&
- TAILQ_EMPTY(&asoc->out_wheel)) {
+ stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
+nothing_to_send:
*reason_code = 9;
return (0);
}
@@ -7464,12 +7710,43 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
no_data_chunks = 1;
}
}
+ if (stcb->asoc.ecn_echo_cnt_onq) {
+ /* Record where a sack goes, if any */
+ if (no_data_chunks &&
+ (asoc->ctrl_queue_cnt == stcb->asoc.ecn_echo_cnt_onq)) {
+ /* Nothing but ECNe to send - we don't do that */
+ goto nothing_to_send;
+ }
+ TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
+ if ((chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) ||
+ (chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK)) {
+ sack_goes_to = chk->whoTo;
+ break;
+ }
+ }
+ }
max_rwnd_per_dest = ((asoc->peers_rwnd + asoc->total_flight) / asoc->numnets);
if (stcb->sctp_socket)
max_send_per_dest = SCTP_SB_LIMIT_SND(stcb->sctp_socket) / asoc->numnets;
else
max_send_per_dest = 0;
- if ((no_data_chunks == 0) && (!TAILQ_EMPTY(&asoc->out_wheel))) {
+ if (no_data_chunks == 0) {
+ /* How many non-directed chunks are there? */
+ TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
+ if (chk->whoTo == NULL) {
+ /*
+ * We already have non-directed chunks on
+ * the queue, no need to do a fill-up.
+ */
+ skip_fill_up = 1;
+ break;
+ }
+ }
+
+ }
+ if ((no_data_chunks == 0) &&
+ (skip_fill_up == 0) &&
+ (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc))) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
/*
* This for loop we are in takes in each net, if
@@ -7483,23 +7760,19 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
* copy by reference (we hope).
*/
net->window_probe = 0;
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ||
- (net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
+ if ((net != stcb->asoc.alternate) &&
+ ((net->dest_state & SCTP_ADDR_PF) ||
+ (!(net->dest_state & SCTP_ADDR_REACHABLE)) ||
+ (net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
sctp_log_cwnd(stcb, net, 1,
SCTP_CWND_LOG_FILL_OUTQ_CALLED);
}
continue;
}
- if ((asoc->sctp_cmt_on_off == 0) &&
- (asoc->primary_destination != net) &&
- (net->ref_count < 2)) {
- /* nothing can be in queue for this guy */
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
- sctp_log_cwnd(stcb, net, 2,
- SCTP_CWND_LOG_FILL_OUTQ_CALLED);
- }
- continue;
+ if ((stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) &&
+ (net->flight_size == 0)) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) (stcb, net);
}
if (net->flight_size >= net->cwnd) {
/* skip this network, no room - can't fill */
@@ -7512,7 +7785,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
sctp_log_cwnd(stcb, net, 4, SCTP_CWND_LOG_FILL_OUTQ_CALLED);
}
- sctp_fill_outqueue(stcb, net, frag_point, eeor_mode, &quit_now);
+ sctp_fill_outqueue(stcb, net, frag_point, eeor_mode, &quit_now, so_locked);
if (quit_now) {
/* memory alloc failure */
no_data_chunks = 1;
@@ -7528,7 +7801,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
*reason_code = 8;
return (0);
}
- if (asoc->sctp_cmt_on_off == 1) {
+ if (asoc->sctp_cmt_on_off > 0) {
/* get the last start point */
start_at = asoc->last_net_cmt_send_started;
if (start_at == NULL) {
@@ -7544,6 +7817,16 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
} else {
start_at = TAILQ_FIRST(&asoc->nets);
}
+ TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
+ if (chk->whoTo == NULL) {
+ if (asoc->alternate) {
+ chk->whoTo = asoc->alternate;
+ } else {
+ chk->whoTo = asoc->primary_destination;
+ }
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
+ }
old_start_at = NULL;
again_one_more_time:
for (net = start_at; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
@@ -7554,15 +7837,6 @@ again_one_more_time:
break;
}
tsns_sent = 0xa;
- if ((asoc->sctp_cmt_on_off == 0) &&
- (asoc->primary_destination != net) &&
- (net->ref_count < 2)) {
- /*
- * Ref-count of 1 so we cannot have data or control
- * queued to this address. Skip it (non-CMT).
- */
- continue;
- }
if (TAILQ_EMPTY(&asoc->control_send_queue) &&
TAILQ_EMPTY(&asoc->asconf_send_queue) &&
(net->flight_size >= net->cwnd)) {
@@ -7572,7 +7846,7 @@ again_one_more_time:
*/
continue;
}
- ctl_cnt = bundle_at = 0;
+ bundle_at = 0;
endoutchain = outchain = NULL;
no_fragmentflg = 1;
one_chunk = 0;
@@ -7598,9 +7872,11 @@ again_one_more_time:
}
}
switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
+#ifdef INET
case AF_INET:
mtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr));
break;
+#endif
#ifdef INET6
case AF_INET6:
mtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr));
@@ -7629,18 +7905,24 @@ again_one_more_time:
/* ASCONF transmission */
/************************/
/* Now first lets go through the asconf queue */
- for (chk = TAILQ_FIRST(&asoc->asconf_send_queue);
- chk; chk = nchk) {
- nchk = TAILQ_NEXT(chk, sctp_next);
+ TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) {
if (chk->rec.chunk_id.id != SCTP_ASCONF) {
continue;
}
- if (chk->whoTo != net) {
- /*
- * No, not sent to the network we are
- * looking at
- */
- break;
+ if (chk->whoTo == NULL) {
+ if (asoc->alternate == NULL) {
+ if (asoc->primary_destination != net) {
+ break;
+ }
+ } else {
+ if (asoc->alternate != net) {
+ break;
+ }
+ }
+ } else {
+ if (chk->whoTo != net) {
+ break;
+ }
}
if (chk->data == NULL) {
break;
@@ -7724,6 +8006,10 @@ again_one_more_time:
*/
no_data_chunks = 1;
chk->sent = SCTP_DATAGRAM_SENT;
+ if (chk->whoTo == NULL) {
+ chk->whoTo = net;
+ atomic_add_int(&net->ref_count, 1);
+ }
chk->snd_count++;
if (mtu == 0) {
/*
@@ -7742,10 +8028,12 @@ again_one_more_time:
(struct sockaddr *)&net->ro._l_addr,
outchain, auth_offset, auth,
stcb->asoc.authinfo.active_keyid,
- no_fragmentflg, 0, NULL, asconf,
+ no_fragmentflg, 0, asconf,
inp->sctp_lport, stcb->rport,
htonl(stcb->asoc.peer_vtag),
- net->port, so_locked, NULL))) {
+ net->port, NULL,
+ 0, 0,
+ so_locked))) {
if (error == ENOBUFS) {
asoc->ifp_had_enobuf = 1;
SCTP_STAT_INCR(sctps_lowlevelerr);
@@ -7793,10 +8081,21 @@ again_one_more_time:
if (!no_out_cnt)
*num_out += ctl_cnt;
/* recalc a clean slate and setup */
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- mtu = (net->mtu - SCTP_MIN_OVERHEAD);
- } else {
- mtu = (net->mtu - SCTP_MIN_V4_OVERHEAD);
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ mtu = net->mtu - SCTP_MIN_OVERHEAD;
+ break;
+#endif
+ default:
+ /* TSNH */
+ mtu = net->mtu;
+ break;
}
to_out = 0;
no_fragmentflg = 1;
@@ -7807,16 +8106,45 @@ again_one_more_time:
/* Control transmission */
/************************/
/* Now first lets go through the control queue */
- for (chk = TAILQ_FIRST(&asoc->control_send_queue);
- chk; chk = nchk) {
- nchk = TAILQ_NEXT(chk, sctp_next);
- if (chk->whoTo != net) {
+ TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
+ if ((sack_goes_to) &&
+ (chk->rec.chunk_id.id == SCTP_ECN_ECHO) &&
+ (chk->whoTo != sack_goes_to)) {
/*
- * No, not sent to the network we are
- * looking at
+ * if we have a sack in queue, and we are
+ * looking at an ecn echo that is NOT queued
+ * to where the sack is going..
*/
- continue;
+ if (chk->whoTo == net) {
+ /*
+ * Don't transmit it to where its
+ * going (current net)
+ */
+ continue;
+ } else if (sack_goes_to == net) {
+ /*
+ * But do transmit it to this
+ * address
+ */
+ goto skip_net_check;
+ }
+ }
+ if (chk->whoTo == NULL) {
+ if (asoc->alternate == NULL) {
+ if (asoc->primary_destination != net) {
+ continue;
+ }
+ } else {
+ if (asoc->alternate != net) {
+ continue;
+ }
+ }
+ } else {
+ if (chk->whoTo != net) {
+ continue;
+ }
}
+ skip_net_check:
if (chk->data == NULL) {
continue;
}
@@ -7903,15 +8231,8 @@ again_one_more_time:
(chk->rec.chunk_id.id == SCTP_ECN_CWR) ||
(chk->rec.chunk_id.id == SCTP_PACKET_DROPPED) ||
(chk->rec.chunk_id.id == SCTP_ASCONF_ACK)) {
-
if (chk->rec.chunk_id.id == SCTP_HEARTBEAT_REQUEST) {
hbflag = 1;
- /*
- * JRS 5/14/07 - Set the
- * flag to say a heartbeat
- * is being sent.
- */
- pf_hbflag = 1;
}
/* remove these chunks at the end */
if ((chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) ||
@@ -7934,8 +8255,26 @@ again_one_more_time:
if (chk->rec.chunk_id.id == SCTP_COOKIE_ECHO) {
cookie = 1;
no_out_cnt = 1;
+ } else if (chk->rec.chunk_id.id == SCTP_ECN_ECHO) {
+ /*
+ * Increment ecne send count
+ * here this means we may be
+ * over-zealous in our
+ * counting if the send
+ * fails, but its the best
+ * place to do it (we used
+ * to do it in the queue of
+ * the chunk, but that did
+ * not tell how many times
+ * it was sent.
+ */
+ SCTP_STAT_INCR(sctps_sendecne);
}
chk->sent = SCTP_DATAGRAM_SENT;
+ if (chk->whoTo == NULL) {
+ chk->whoTo = net;
+ atomic_add_int(&net->ref_count, 1);
+ }
chk->snd_count++;
}
if (mtu == 0) {
@@ -7963,10 +8302,12 @@ again_one_more_time:
outchain,
auth_offset, auth,
stcb->asoc.authinfo.active_keyid,
- no_fragmentflg, 0, NULL, asconf,
+ no_fragmentflg, 0, asconf,
inp->sctp_lport, stcb->rport,
htonl(stcb->asoc.peer_vtag),
- net->port, so_locked, NULL))) {
+ net->port, NULL,
+ 0, 0,
+ so_locked))) {
if (error == ENOBUFS) {
asoc->ifp_had_enobuf = 1;
SCTP_STAT_INCR(sctps_lowlevelerr);
@@ -8019,10 +8360,21 @@ again_one_more_time:
if (!no_out_cnt)
*num_out += ctl_cnt;
/* recalc a clean slate and setup */
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- mtu = (net->mtu - SCTP_MIN_OVERHEAD);
- } else {
- mtu = (net->mtu - SCTP_MIN_V4_OVERHEAD);
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ mtu = net->mtu - SCTP_MIN_OVERHEAD;
+ break;
+#endif
+ default:
+ /* TSNH */
+ mtu = net->mtu;
+ break;
}
to_out = 0;
no_fragmentflg = 1;
@@ -8030,15 +8382,15 @@ again_one_more_time:
}
}
/* JRI: if dest is in PF state, do not send data to it */
- if ((asoc->sctp_cmt_on_off == 1) &&
- (asoc->sctp_cmt_pf > 0) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
+ (net != stcb->asoc.alternate) &&
(net->dest_state & SCTP_ADDR_PF)) {
goto no_data_fill;
}
if (net->flight_size >= net->cwnd) {
goto no_data_fill;
}
- if ((asoc->sctp_cmt_on_off == 1) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
(SCTP_BASE_SYSCTL(sctp_buffer_splitting) & SCTP_RECV_BUFFER_SPLITTING) &&
(net->flight_size > max_rwnd_per_dest)) {
goto no_data_fill;
@@ -8049,7 +8401,7 @@ again_one_more_time:
* net. For now, this is better than nothing and it disabled
* by default...
*/
- if ((asoc->sctp_cmt_on_off == 1) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
(SCTP_BASE_SYSCTL(sctp_buffer_splitting) & SCTP_SEND_BUFFER_SPLITTING) &&
(max_send_per_dest > 0) &&
(net->flight_size > max_send_per_dest)) {
@@ -8071,12 +8423,14 @@ again_one_more_time:
}
/* now lets add any data within the MTU constraints */
switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
+#ifdef INET
case AF_INET:
if (net->mtu > (sizeof(struct ip) + sizeof(struct sctphdr)))
omtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr));
else
omtu = 0;
break;
+#endif
#ifdef INET6
case AF_INET6:
if (net->mtu > (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)))
@@ -8093,7 +8447,7 @@ again_one_more_time:
if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) &&
(skip_data_for_this_net == 0)) ||
(cookie)) {
- for (chk = TAILQ_FIRST(&asoc->send_queue); chk; chk = nchk) {
+ TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
if (no_data_chunks) {
/* let only control go out */
*reason_code = 1;
@@ -8104,12 +8458,22 @@ again_one_more_time:
*reason_code = 2;
break;
}
- nchk = TAILQ_NEXT(chk, sctp_next);
if ((chk->whoTo != NULL) &&
(chk->whoTo != net)) {
/* Don't send the chunk on this net */
continue;
}
+ if (asoc->sctp_cmt_on_off == 0) {
+ if ((asoc->alternate) &&
+ (asoc->alternate != net) &&
+ (chk->whoTo == NULL)) {
+ continue;
+ } else if ((net != asoc->primary_destination) &&
+ (asoc->alternate == NULL) &&
+ (chk->whoTo == NULL)) {
+ continue;
+ }
+ }
if ((chk->send_size > omtu) && ((chk->flags & CHUNK_FLAGS_FRAGMENT_OK) == 0)) {
/*-
* strange, we have a chunk that is
@@ -8208,7 +8572,6 @@ again_one_more_time:
chk->window_probe = 0;
data_list[bundle_at++] = chk;
if (bundle_at >= SCTP_MAX_DATA_BUNDLING) {
- mtu = 0;
break;
}
if (chk->sent == SCTP_DATAGRAM_UNSENT) {
@@ -8270,18 +8633,6 @@ no_data_fill:
* restart it.
*/
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
- } else if ((asoc->sctp_cmt_on_off == 1) &&
- (asoc->sctp_cmt_pf > 0) &&
- pf_hbflag &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF) &&
- (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer))) {
- /*
- * JRS 5/14/07 - If a HB has been sent to a
- * PF destination and no T3 timer is
- * currently running, start the T3 timer to
- * track the HBs that were sent.
- */
- sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
}
/* Now send it, if there is anything to send :> */
if ((error = sctp_lowlevel_chunk_output(inp,
@@ -8294,11 +8645,12 @@ no_data_fill:
auth_keyid,
no_fragmentflg,
bundle_at,
- data_list[0],
asconf,
inp->sctp_lport, stcb->rport,
htonl(stcb->asoc.peer_vtag),
- net->port, so_locked, NULL))) {
+ net->port, NULL,
+ 0, 0,
+ so_locked))) {
/* error, we could not output */
if (error == ENOBUFS) {
SCTP_STAT_INCR(sctps_lowlevelerr);
@@ -8338,7 +8690,7 @@ no_data_fill:
} else {
asoc->ifp_had_enobuf = 0;
}
- outchain = endoutchain = NULL;
+ endoutchain = NULL;
auth = NULL;
auth_offset = 0;
if (bundle_at || hbflag) {
@@ -8365,27 +8717,12 @@ no_data_fill:
} else {
asoc->time_last_sent = *now;
}
- data_list[0]->do_rtt = 1;
+ if (net->rto_needed) {
+ data_list[0]->do_rtt = 1;
+ net->rto_needed = 0;
+ }
SCTP_STAT_INCR_BY(sctps_senddata, bundle_at);
sctp_clean_up_datalist(stcb, asoc, data_list, bundle_at, net);
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (net->flight_size < net->cwnd) {
- /* start or restart it */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net,
- SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_2);
- }
- SCTP_STAT_INCR(sctps_earlyfrstrout);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net);
- } else {
- /* stop it if its running */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpout);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net,
- SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_3);
- }
- }
- }
}
if (one_chunk) {
break;
@@ -8413,7 +8750,7 @@ no_data_fill:
} else {
*reason_code = 5;
}
- sctp_clean_up_ctl(stcb, asoc);
+ sctp_clean_up_ctl(stcb, asoc, so_locked);
return (0);
}
@@ -8438,7 +8775,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
chk->copy_by_ref = 0;
SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_DONTWAIT);
if (op_err == NULL) {
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
return;
}
chk->send_size = 0;
@@ -8454,8 +8791,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->data = op_err;
- chk->whoTo = chk->asoc->primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
+ chk->whoTo = NULL;
hdr = mtod(op_err, struct sctp_chunkhdr *);
hdr->chunk_type = SCTP_OPERATION_ERROR;
hdr->chunk_flags = 0;
@@ -8511,12 +8847,10 @@ sctp_send_cookie_echo(struct mbuf *m,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = cookie;
- while (mat) {
+ for (mat = cookie; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -8550,7 +8884,7 @@ sctp_send_cookie_echo(struct mbuf *m,
chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
chk->asoc = &stcb->asoc;
chk->data = cookie;
- chk->whoTo = chk->asoc->primary_destination;
+ chk->whoTo = net;
atomic_add_int(&chk->whoTo->ref_count, 1);
TAILQ_INSERT_HEAD(&chk->asoc->control_send_queue, chk, sctp_next);
chk->asoc->ctrl_queue_cnt++;
@@ -8585,12 +8919,10 @@ sctp_send_heartbeat_ack(struct sctp_tcb *stcb,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = outchain;
- while (mat) {
+ for (mat = outchain; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -8660,10 +8992,10 @@ sctp_send_cookie_ack(struct sctp_tcb *stcb)
chk->data = cookie_ack;
if (chk->asoc->last_control_chunk_from != NULL) {
chk->whoTo = chk->asoc->last_control_chunk_from;
+ atomic_add_int(&chk->whoTo->ref_count, 1);
} else {
- chk->whoTo = chk->asoc->primary_destination;
+ chk->whoTo = NULL;
}
- atomic_add_int(&chk->whoTo->ref_count, 1);
hdr = mtod(cookie_ack, struct sctp_chunkhdr *);
hdr->chunk_type = SCTP_COOKIE_ACK;
hdr->chunk_flags = 0;
@@ -8705,8 +9037,9 @@ sctp_send_shutdown_ack(struct sctp_tcb *stcb, struct sctp_nets *net)
chk->asoc = &stcb->asoc;
chk->data = m_shutdown_ack;
chk->whoTo = net;
- atomic_add_int(&net->ref_count, 1);
-
+ if (chk->whoTo) {
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
ack_cp = mtod(m_shutdown_ack, struct sctp_shutdown_ack_chunk *);
ack_cp->ch.chunk_type = SCTP_SHUTDOWN_ACK;
ack_cp->ch.chunk_flags = 0;
@@ -8747,8 +9080,9 @@ sctp_send_shutdown(struct sctp_tcb *stcb, struct sctp_nets *net)
chk->asoc = &stcb->asoc;
chk->data = m_shutdown;
chk->whoTo = net;
- atomic_add_int(&net->ref_count, 1);
-
+ if (chk->whoTo) {
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
shutdown_cp = mtod(m_shutdown, struct sctp_shutdown_chunk *);
shutdown_cp->ch.chunk_type = SCTP_SHUTDOWN;
shutdown_cp->ch.chunk_flags = 0;
@@ -8799,7 +9133,9 @@ sctp_send_asconf(struct sctp_tcb *stcb, struct sctp_nets *net, int addr_locked)
chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
chk->asoc = &stcb->asoc;
chk->whoTo = net;
- atomic_add_int(&chk->whoTo->ref_count, 1);
+ if (chk->whoTo) {
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
TAILQ_INSERT_TAIL(&chk->asoc->asconf_send_queue, chk, sctp_next);
chk->asoc->ctrl_queue_cnt++;
return;
@@ -8814,7 +9150,7 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
*/
struct sctp_tmit_chunk *chk;
struct sctp_asconf_ack *ack, *latest_ack;
- struct mbuf *m_ack, *m;
+ struct mbuf *m_ack;
struct sctp_nets *net = NULL;
SCTP_TCB_LOCK_ASSERT(stcb);
@@ -8829,17 +9165,27 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
net = sctp_find_alternate_net(stcb, stcb->asoc.last_control_chunk_from, 0);
if (net == NULL) {
/* no alternate */
- if (stcb->asoc.last_control_chunk_from == NULL)
- net = stcb->asoc.primary_destination;
- else
+ if (stcb->asoc.last_control_chunk_from == NULL) {
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
+ } else {
net = stcb->asoc.last_control_chunk_from;
+ }
}
} else {
/* normal case */
- if (stcb->asoc.last_control_chunk_from == NULL)
- net = stcb->asoc.primary_destination;
- else
+ if (stcb->asoc.last_control_chunk_from == NULL) {
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
+ } else {
net = stcb->asoc.last_control_chunk_from;
+ }
}
latest_ack->last_sent_to = net;
@@ -8857,12 +9203,10 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
- mat = m_ack;
- while (mat) {
+ for (mat = m_ack; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
- mat = SCTP_BUF_NEXT(mat);
}
}
#endif
@@ -8877,10 +9221,12 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
chk->copy_by_ref = 0;
chk->whoTo = net;
+ if (chk->whoTo) {
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
chk->data = m_ack;
chk->send_size = 0;
/* Get size */
- m = m_ack;
chk->send_size = ack->len;
chk->rec.chunk_id.id = SCTP_ASCONF_ACK;
chk->rec.chunk_id.can_take_data = 1;
@@ -8888,7 +9234,6 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
chk->snd_count = 0;
chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; /* XXX */
chk->asoc = &stcb->asoc;
- atomic_add_int(&chk->whoTo->ref_count, 1);
TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next);
chk->asoc->ctrl_queue_cnt++;
@@ -8974,7 +9319,6 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
ctl_cnt++;
if (chk->rec.chunk_id.id == SCTP_FORWARD_CUM_TSN) {
fwd_tsn = 1;
- fwd = chk;
}
/*
* Add an AUTH chunk, if chunk requires it save the
@@ -9006,13 +9350,15 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
if ((error = sctp_lowlevel_chunk_output(inp, stcb, chk->whoTo,
(struct sockaddr *)&chk->whoTo->ro._l_addr, m,
auth_offset, auth, stcb->asoc.authinfo.active_keyid,
- no_fragmentflg, 0, NULL, 0,
+ no_fragmentflg, 0, 0,
inp->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag),
- chk->whoTo->port, so_locked, NULL))) {
+ chk->whoTo->port, NULL,
+ 0, 0,
+ so_locked))) {
SCTP_STAT_INCR(sctps_lowlevelerr);
return (error);
}
- m = endofchain = NULL;
+ endofchain = NULL;
auth = NULL;
auth_offset = 0;
/*
@@ -9027,7 +9373,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
return (0);
} else {
/* Clean up the fwd-tsn list */
- sctp_clean_up_ctl(stcb, asoc);
+ sctp_clean_up_ctl(stcb, asoc, so_locked);
return (0);
}
}
@@ -9053,7 +9399,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
continue;
}
if (chk->data == NULL) {
- printf("TSN:%x chk->snd_count:%d chk->sent:%d can't retran - no data\n",
+ SCTP_PRINTF("TSN:%x chk->snd_count:%d chk->sent:%d can't retran - no data\n",
chk->rec.data.TSN_seq, chk->snd_count, chk->sent);
continue;
}
@@ -9064,17 +9410,28 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
chk->snd_count,
SCTP_BASE_SYSCTL(sctp_max_retran_chunk));
atomic_add_int(&stcb->asoc.refcnt, 1);
- sctp_abort_an_association(stcb->sctp_ep, stcb, 0, NULL, so_locked);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, so_locked);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (SCTP_RETRAN_EXIT);
}
/* pick up the net */
net = chk->whoTo;
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- mtu = (net->mtu - SCTP_MIN_OVERHEAD);
- } else {
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ mtu = net->mtu - SCTP_MIN_OVERHEAD;
+ break;
+#endif
+ default:
+ /* TSNH */
+ mtu = net->mtu;
+ break;
}
if ((asoc->peers_rwnd < mtu) && (asoc->total_flight > 0)) {
@@ -9182,16 +9539,13 @@ one_chunk_around:
* now are there anymore forward from chk to pick
* up?
*/
- fwd = TAILQ_NEXT(chk, sctp_next);
- while (fwd) {
+ for (fwd = TAILQ_NEXT(chk, sctp_next); fwd != NULL; fwd = TAILQ_NEXT(fwd, sctp_next)) {
if (fwd->sent != SCTP_DATAGRAM_RESEND) {
/* Nope, not for retran */
- fwd = TAILQ_NEXT(fwd, sctp_next);
continue;
}
if (fwd->whoTo != net) {
/* Nope, not the net in question */
- fwd = TAILQ_NEXT(fwd, sctp_next);
continue;
}
if (data_auth_reqd && (auth == NULL)) {
@@ -9239,7 +9593,6 @@ one_chunk_around:
if (bundle_at >= SCTP_MAX_DATA_BUNDLING) {
break;
}
- fwd = TAILQ_NEXT(fwd, sctp_next);
} else {
/* can't fit so we are done */
break;
@@ -9264,14 +9617,16 @@ one_chunk_around:
if ((error = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr, m,
auth_offset, auth, auth_keyid,
- no_fragmentflg, 0, NULL, 0,
+ no_fragmentflg, 0, 0,
inp->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag),
- net->port, so_locked, NULL))) {
+ net->port, NULL,
+ 0, 0,
+ so_locked))) {
/* error, we could not output */
SCTP_STAT_INCR(sctps_lowlevelerr);
return (error);
}
- m = endofchain = NULL;
+ endofchain = NULL;
auth = NULL;
auth_offset = 0;
/* For HB's */
@@ -9399,12 +9754,10 @@ one_chunk_around:
return (0);
}
-
-static int
+static void
sctp_timer_validation(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
- struct sctp_association *asoc,
- int ret)
+ struct sctp_association *asoc)
{
struct sctp_nets *net;
@@ -9412,14 +9765,18 @@ sctp_timer_validation(struct sctp_inpcb *inp,
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
/* Here is a timer */
- return (ret);
+ return;
}
}
SCTP_TCB_LOCK_ASSERT(stcb);
/* Gak, we did not have a timer somewhere */
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Deadlock avoided starting timer on a dest at retran\n");
- sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->primary_destination);
- return (ret);
+ if (asoc->alternate) {
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->alternate);
+ } else {
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->primary_destination);
+ }
+ return;
}
void
@@ -9447,22 +9804,26 @@ sctp_chunk_output(struct sctp_inpcb *inp,
*/
struct sctp_association *asoc;
struct sctp_nets *net;
- int error = 0, num_out = 0, tot_out = 0, ret = 0, reason_code = 0,
- burst_cnt = 0, burst_limit = 0;
+ int error = 0, num_out = 0, tot_out = 0, ret = 0, reason_code = 0;
+ unsigned int burst_cnt = 0;
struct timeval now;
int now_filled = 0;
- int nagle_on = 0;
+ int nagle_on;
int frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
int un_sent = 0;
- int fr_done, tot_frs = 0;
+ int fr_done;
+ unsigned int tot_frs = 0;
asoc = &stcb->asoc;
+ /* The Nagle algorithm is only applied when handling a send call. */
if (from_where == SCTP_OUTPUT_FROM_USR_SEND) {
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY)) {
nagle_on = 0;
} else {
nagle_on = 1;
}
+ } else {
+ nagle_on = 0;
}
SCTP_TCB_LOCK_ASSERT(stcb);
@@ -9480,7 +9841,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
* running, if so piggy-back the sack.
*/
if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
- sctp_send_sack(stcb);
+ sctp_send_sack(stcb, so_locked);
(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
}
while (asoc->sent_queue_retran_cnt) {
@@ -9525,7 +9886,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(8, inp, stcb, NULL);
#endif
- (void)sctp_timer_validation(inp, stcb, asoc, ret);
+ sctp_timer_validation(inp, stcb, asoc);
return;
}
if (ret < 0) {
@@ -9551,12 +9912,11 @@ sctp_chunk_output(struct sctp_inpcb *inp,
&now, &now_filled, frag_point, so_locked);
return;
}
- if (tot_frs > asoc->max_burst) {
+ if ((asoc->fr_max_burst > 0) && (tot_frs >= asoc->fr_max_burst)) {
/* Hit FR burst limit */
return;
}
if ((num_out == 0) && (ret == 0)) {
-
/* No more retrans to send */
break;
}
@@ -9565,10 +9925,8 @@ sctp_chunk_output(struct sctp_inpcb *inp,
sctp_auditing(12, inp, stcb, NULL);
#endif
/* Check for bad destinations, if they exist move chunks around. */
- burst_limit = asoc->max_burst;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
- SCTP_ADDR_NOT_REACHABLE) {
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
/*-
* if possible move things off of this address we
* still may send below due to the dormant state but
@@ -9578,40 +9936,35 @@ sctp_chunk_output(struct sctp_inpcb *inp,
*/
if (net->ref_count > 1)
sctp_move_chunks_from_net(stcb, net);
- } else if ((asoc->sctp_cmt_on_off == 1) &&
- (asoc->sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- /*
- * JRS 5/14/07 - If CMT PF is on and the current
- * destination is in PF state, move all queued data
- * to an alternate desination.
- */
- if (net->ref_count > 1)
- sctp_move_chunks_from_net(stcb, net);
} else {
/*-
* if ((asoc->sat_network) || (net->addr_is_local))
* { burst_limit = asoc->max_burst *
* SCTP_SAT_NETWORK_BURST_INCR; }
*/
- if (SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst)) {
- if ((net->flight_size + (burst_limit * net->mtu)) < net->cwnd) {
- /*
- * JRS - Use the congestion control
- * given in the congestion control
- * module
- */
- asoc->cc_functions.sctp_cwnd_update_after_output(stcb, net, burst_limit);
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_MAXBURST_ENABLE) {
- sctp_log_maxburst(stcb, net, 0, burst_limit, SCTP_MAX_BURST_APPLIED);
+ if (asoc->max_burst > 0) {
+ if (SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst)) {
+ if ((net->flight_size + (asoc->max_burst * net->mtu)) < net->cwnd) {
+ /*
+ * JRS - Use the congestion
+ * control given in the
+ * congestion control module
+ */
+ asoc->cc_functions.sctp_cwnd_update_after_output(stcb, net, asoc->max_burst);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_MAXBURST_ENABLE) {
+ sctp_log_maxburst(stcb, net, 0, asoc->max_burst, SCTP_MAX_BURST_APPLIED);
+ }
+ SCTP_STAT_INCR(sctps_maxburstqueued);
+ }
+ net->fast_retran_ip = 0;
+ } else {
+ if (net->flight_size == 0) {
+ /*
+ * Should be decaying the
+ * cwnd here
+ */
+ ;
}
- SCTP_STAT_INCR(sctps_maxburstqueued);
- }
- net->fast_retran_ip = 0;
- } else {
- if (net->flight_size == 0) {
- /* Should be decaying the cwnd here */
- ;
}
}
}
@@ -9644,21 +9997,24 @@ sctp_chunk_output(struct sctp_inpcb *inp,
}
}
if (nagle_on) {
- /*-
- * When nagle is on, we look at how much is un_sent, then
- * if its smaller than an MTU and we have data in
- * flight we stop.
+ /*
+ * When the Nagle algorithm is used, look at how
+ * much is unsent, then if its smaller than an MTU
+ * and we have data in flight we stop, except if we
+ * are handling a fragmented user message.
*/
un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
(stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
if ((un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) &&
- (stcb->asoc.total_flight > 0)) {
+ (stcb->asoc.total_flight > 0) &&
+ ((stcb->asoc.locked_on_sending == NULL) ||
+ sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {
break;
}
}
if (TAILQ_EMPTY(&asoc->control_send_queue) &&
TAILQ_EMPTY(&asoc->send_queue) &&
- TAILQ_EMPTY(&asoc->out_wheel)) {
+ stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
/* Nothing left to send */
break;
}
@@ -9666,11 +10022,13 @@ sctp_chunk_output(struct sctp_inpcb *inp,
/* Nothing left to send */
break;
}
- } while (num_out && (SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) ||
- (burst_cnt < burst_limit)));
+ } while (num_out &&
+ ((asoc->max_burst == 0) ||
+ SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) ||
+ (burst_cnt < asoc->max_burst)));
if (SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) == 0) {
- if (burst_cnt >= burst_limit) {
+ if ((asoc->max_burst > 0) && (burst_cnt >= asoc->max_burst)) {
SCTP_STAT_INCR(sctps_maxburstqueued);
asoc->burst_limit_applied = 1;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_MAXBURST_ENABLE) {
@@ -9698,13 +10056,13 @@ sctp_chunk_output(struct sctp_inpcb *inp,
int
-sctp_output(inp, m, addr, control, p, flags)
- struct sctp_inpcb *inp;
- struct mbuf *m;
- struct sockaddr *addr;
- struct mbuf *control;
- struct thread *p;
- int flags;
+sctp_output(
+ struct sctp_inpcb *inp,
+ struct mbuf *m,
+ struct sockaddr *addr,
+ struct mbuf *control,
+ struct thread *p,
+ int flags)
{
if (inp == NULL) {
SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
@@ -9738,10 +10096,9 @@ send_forward_tsn(struct sctp_tcb *stcb,
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
/* Do we correct its output location? */
- if (chk->whoTo != asoc->primary_destination) {
+ if (chk->whoTo) {
sctp_free_remote_addr(chk->whoTo);
- chk->whoTo = asoc->primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
+ chk->whoTo = NULL;
}
goto sctp_fill_in_rest;
}
@@ -9759,14 +10116,12 @@ send_forward_tsn(struct sctp_tcb *stcb,
chk->whoTo = NULL;
chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
if (chk->data == NULL) {
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
return;
}
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->whoTo = asoc->primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
TAILQ_INSERT_TAIL(&asoc->control_send_queue, chk, sctp_next);
asoc->ctrl_queue_cnt++;
sctp_fill_in_rest:
@@ -9783,7 +10138,8 @@ sctp_fill_in_rest:
unsigned int cnt_of_skipped = 0;
TAILQ_FOREACH(at, &asoc->sent_queue, sctp_next) {
- if (at->sent != SCTP_FORWARD_TSN_SKIP) {
+ if ((at->sent != SCTP_FORWARD_TSN_SKIP) &&
+ (at->sent != SCTP_DATAGRAM_NR_ACKED)) {
/* no more to look at */
break;
}
@@ -9831,12 +10187,14 @@ sctp_fill_in_rest:
* we report.
*/
at = TAILQ_FIRST(&asoc->sent_queue);
- for (i = 0; i < cnt_of_skipped; i++) {
- tp1 = TAILQ_NEXT(at, sctp_next);
- if (tp1 == NULL) {
- break;
+ if (at != NULL) {
+ for (i = 0; i < cnt_of_skipped; i++) {
+ tp1 = TAILQ_NEXT(at, sctp_next);
+ if (tp1 == NULL) {
+ break;
+ }
+ at = tp1;
}
- at = tp1;
}
if (at && SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
sctp_misc_ints(SCTP_FWD_TSN_CHECK,
@@ -9900,11 +10258,14 @@ sctp_fill_in_rest:
}
}
return;
-
}
void
-sctp_send_sack(struct sctp_tcb *stcb)
+sctp_send_sack(struct sctp_tcb *stcb, int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+ SCTP_UNUSED
+#endif
+)
{
/*-
* Queue up a SACK or NR-SACK in the control queue.
@@ -9957,8 +10318,10 @@ sctp_send_sack(struct sctp_tcb *stcb)
sctp_m_freem(a_chk->data);
a_chk->data = NULL;
}
- sctp_free_remote_addr(a_chk->whoTo);
- a_chk->whoTo = NULL;
+ if (a_chk->whoTo) {
+ sctp_free_remote_addr(a_chk->whoTo);
+ a_chk->whoTo = NULL;
+ }
break;
}
}
@@ -9990,13 +10353,13 @@ sctp_send_sack(struct sctp_tcb *stcb)
a_chk->whoTo = NULL;
if ((asoc->numduptsns) ||
- (asoc->last_data_chunk_from->dest_state & SCTP_ADDR_NOT_REACHABLE)) {
+ (!(asoc->last_data_chunk_from->dest_state & SCTP_ADDR_REACHABLE))) {
/*-
* Ok, we have some duplicates or the destination for the
* sack is unreachable, lets see if we can select an
* alternate than asoc->last_data_chunk_from
*/
- if ((!(asoc->last_data_chunk_from->dest_state & SCTP_ADDR_NOT_REACHABLE)) &&
+ if ((asoc->last_data_chunk_from->dest_state & SCTP_ADDR_REACHABLE) &&
(asoc->used_alt_onsack > asoc->numnets)) {
/* We used an alt last time, don't this time */
a_chk->whoTo = NULL;
@@ -10020,7 +10383,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
if (a_chk->whoTo) {
atomic_add_int(&a_chk->whoTo->ref_count, 1);
}
- if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map)) {
highest_tsn = asoc->highest_tsn_inside_map;
} else {
highest_tsn = asoc->highest_tsn_inside_nr_map;
@@ -10046,7 +10409,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
sctp_m_freem(a_chk->data);
a_chk->data = NULL;
}
- sctp_free_a_chunk(stcb, a_chk);
+ sctp_free_a_chunk(stcb, a_chk, so_locked);
/* sa_ignore NO_NULL_CHK */
if (stcb->asoc.delayed_ack) {
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
@@ -10067,15 +10430,9 @@ sctp_send_sack(struct sctp_tcb *stcb)
limit = mtod(a_chk->data, caddr_t);
limit += space;
- /* 0x01 is used by nonce for ecn */
- if ((SCTP_BASE_SYSCTL(sctp_ecn_enable)) &&
- (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) &&
- (asoc->peer_supports_ecn_nonce))
- flags = (asoc->receiver_nonce_sum & SCTP_SACK_NONCE_SUM);
- else
- flags = 0;
+ flags = 0;
- if ((asoc->sctp_cmt_on_off == 1) &&
+ if ((asoc->sctp_cmt_on_off > 0) &&
SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
/*-
* CMT DAC algorithm: If 2 (i.e., 0x10) packets have been
@@ -10115,15 +10472,15 @@ sctp_send_sack(struct sctp_tcb *stcb)
}
}
- if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->mapping_array_base_tsn, asoc->cumulative_tsn)) {
offset = 1;
} else {
offset = asoc->mapping_array_base_tsn - asoc->cumulative_tsn;
}
if (((type == SCTP_SELECTIVE_ACK) &&
- compare_with_wrap(highest_tsn, asoc->cumulative_tsn, MAX_TSN)) ||
+ SCTP_TSN_GT(highest_tsn, asoc->cumulative_tsn)) ||
((type == SCTP_NR_SELECTIVE_ACK) &&
- compare_with_wrap(asoc->highest_tsn_inside_map, asoc->cumulative_tsn, MAX_TSN))) {
+ SCTP_TSN_GT(asoc->highest_tsn_inside_map, asoc->cumulative_tsn))) {
/* we have a gap .. maybe */
for (i = 0; i < siz; i++) {
tsn_map = asoc->mapping_array[i];
@@ -10195,12 +10552,12 @@ sctp_send_sack(struct sctp_tcb *stcb)
siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_nr_map + 7) / 8;
}
- if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->mapping_array_base_tsn, asoc->cumulative_tsn)) {
offset = 1;
} else {
offset = asoc->mapping_array_base_tsn - asoc->cumulative_tsn;
}
- if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, asoc->cumulative_tsn, MAX_TSN)) {
+ if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->cumulative_tsn)) {
/* we have a gap .. maybe */
for (i = 0; i < siz; i++) {
tsn_map = asoc->nr_mapping_array[i];
@@ -10321,44 +10678,50 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
#endif
)
{
- struct mbuf *m_abort;
- struct mbuf *m_out = NULL, *m_end = NULL;
- struct sctp_abort_chunk *abort = NULL;
- int sz;
- uint32_t auth_offset = 0;
+ struct mbuf *m_abort, *m, *m_last;
+ struct mbuf *m_out, *m_end = NULL;
+ struct sctp_abort_chunk *abort;
struct sctp_auth_chunk *auth = NULL;
+ struct sctp_nets *net;
+ uint32_t auth_offset = 0;
+ uint16_t cause_len, chunk_len, padding_len;
+ SCTP_TCB_LOCK_ASSERT(stcb);
/*-
* Add an AUTH chunk, if chunk requires it and save the offset into
* the chain for AUTH
*/
if (sctp_auth_is_required_chunk(SCTP_ABORT_ASSOCIATION,
stcb->asoc.peer_auth_chunks)) {
- m_out = sctp_add_auth_chunk(m_out, &m_end, &auth, &auth_offset,
+ m_out = sctp_add_auth_chunk(NULL, &m_end, &auth, &auth_offset,
stcb, SCTP_ABORT_ASSOCIATION);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
+ } else {
+ m_out = NULL;
}
- SCTP_TCB_LOCK_ASSERT(stcb);
m_abort = sctp_get_mbuf_for_msg(sizeof(struct sctp_abort_chunk), 0, M_DONTWAIT, 1, MT_HEADER);
if (m_abort == NULL) {
- /* no mbuf's */
- if (m_out)
+ if (m_out) {
sctp_m_freem(m_out);
+ }
+ if (operr) {
+ sctp_m_freem(operr);
+ }
return;
}
/* link in any error */
SCTP_BUF_NEXT(m_abort) = operr;
- sz = 0;
- if (operr) {
- struct mbuf *n;
-
- n = operr;
- while (n) {
- sz += SCTP_BUF_LEN(n);
- n = SCTP_BUF_NEXT(n);
+ cause_len = 0;
+ m_last = NULL;
+ for (m = operr; m; m = SCTP_BUF_NEXT(m)) {
+ cause_len += (uint16_t) SCTP_BUF_LEN(m);
+ if (SCTP_BUF_NEXT(m) == NULL) {
+ m_last = m;
}
}
- SCTP_BUF_LEN(m_abort) = sizeof(*abort);
+ SCTP_BUF_LEN(m_abort) = sizeof(struct sctp_abort_chunk);
+ chunk_len = (uint16_t) sizeof(struct sctp_abort_chunk) + cause_len;
+ padding_len = SCTP_SIZE32(chunk_len) - chunk_len;
if (m_out == NULL) {
/* NO Auth chunk prepended, so reserve space in front */
SCTP_BUF_RESV_UF(m_abort, SCTP_MIN_OVERHEAD);
@@ -10367,19 +10730,30 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
/* Put AUTH chunk at the front of the chain */
SCTP_BUF_NEXT(m_end) = m_abort;
}
-
- /* fill in the ABORT chunk */
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
+ /* Fill in the ABORT chunk header. */
abort = mtod(m_abort, struct sctp_abort_chunk *);
abort->ch.chunk_type = SCTP_ABORT_ASSOCIATION;
abort->ch.chunk_flags = 0;
- abort->ch.chunk_length = htons(sizeof(*abort) + sz);
-
- (void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb,
- stcb->asoc.primary_destination,
- (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr,
- m_out, auth_offset, auth, stcb->asoc.authinfo.active_keyid, 1, 0, NULL, 0,
+ abort->ch.chunk_length = htons(chunk_len);
+ /* Add padding, if necessary. */
+ if (padding_len > 0) {
+ if ((m_last == NULL) || sctp_add_pad_tombuf(m_last, padding_len)) {
+ sctp_m_freem(m_out);
+ return;
+ }
+ }
+ (void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net,
+ (struct sockaddr *)&net->ro._l_addr,
+ m_out, auth_offset, auth, stcb->asoc.authinfo.active_keyid, 1, 0, 0,
stcb->sctp_ep->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag),
- stcb->asoc.primary_destination->port, so_locked, NULL);
+ stcb->asoc.primary_destination->port, NULL,
+ 0, 0,
+ so_locked);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
}
@@ -10413,159 +10787,217 @@ sctp_send_shutdown_complete(struct sctp_tcb *stcb,
SCTP_BUF_LEN(m_shutdown_comp) = sizeof(struct sctp_shutdown_complete_chunk);
(void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
- m_shutdown_comp, 0, NULL, 0, 1, 0, NULL, 0,
+ m_shutdown_comp, 0, NULL, 0, 1, 0, 0,
stcb->sctp_ep->sctp_lport, stcb->rport,
htonl(vtag),
- net->port, SCTP_SO_NOT_LOCKED, NULL);
+ net->port, NULL,
+ 0, 0,
+ SCTP_SO_NOT_LOCKED);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
return;
}
-void
-sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
+static void
+sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh, uint32_t vtag,
+ uint8_t type, struct mbuf *cause,
+ uint8_t use_mflowid, uint32_t mflowid,
uint32_t vrf_id, uint16_t port)
{
- /* formulate and SEND a SHUTDOWN-COMPLETE */
struct mbuf *o_pak;
struct mbuf *mout;
- struct ip *iph, *iph_out;
- struct udphdr *udp = NULL;
+ struct sctphdr *shout;
+ struct sctp_chunkhdr *ch;
+ struct udphdr *udp;
+ int len, cause_len, padding_len, ret;
+#ifdef INET
+ struct sockaddr_in *src_sin, *dst_sin;
+ struct ip *ip;
+
+#endif
#ifdef INET6
- struct ip6_hdr *ip6, *ip6_out;
+ struct sockaddr_in6 *src_sin6, *dst_sin6;
+ struct ip6_hdr *ip6;
#endif
- int offset_out, len, mlen;
- struct sctp_shutdown_complete_msg *comp_cp;
- iph = mtod(m, struct ip *);
- switch (iph->ip_v) {
- case IPVERSION:
- len = (sizeof(struct ip) + sizeof(struct sctp_shutdown_complete_msg));
+ /* Compute the length of the cause and add final padding. */
+ cause_len = 0;
+ if (cause != NULL) {
+ struct mbuf *m_at, *m_last = NULL;
+
+ for (m_at = cause; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
+ if (SCTP_BUF_NEXT(m_at) == NULL)
+ m_last = m_at;
+ cause_len += SCTP_BUF_LEN(m_at);
+ }
+ padding_len = cause_len % 4;
+ if (padding_len != 0) {
+ padding_len = 4 - padding_len;
+ }
+ if (padding_len != 0) {
+ if (sctp_add_pad_tombuf(m_last, padding_len)) {
+ sctp_m_freem(cause);
+ return;
+ }
+ }
+ } else {
+ padding_len = 0;
+ }
+ /* Get an mbuf for the header. */
+ len = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ len += sizeof(struct ip);
break;
+#endif
#ifdef INET6
- case IPV6_VERSION >> 4:
- len = (sizeof(struct ip6_hdr) + sizeof(struct sctp_shutdown_complete_msg));
+ case AF_INET6:
+ len += sizeof(struct ip6_hdr);
break;
#endif
default:
- return;
+ break;
}
if (port) {
len += sizeof(struct udphdr);
}
mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, MT_DATA);
if (mout == NULL) {
+ if (cause) {
+ sctp_m_freem(cause);
+ }
return;
}
SCTP_BUF_RESV_UF(mout, max_linkhdr);
SCTP_BUF_LEN(mout) = len;
- SCTP_BUF_NEXT(mout) = NULL;
- iph_out = NULL;
+ SCTP_BUF_NEXT(mout) = cause;
+ if (use_mflowid != 0) {
+ mout->m_pkthdr.flowid = mflowid;
+ mout->m_flags |= M_FLOWID;
+ }
+#ifdef INET
+ ip = NULL;
+#endif
#ifdef INET6
- ip6_out = NULL;
+ ip6 = NULL;
#endif
- offset_out = 0;
-
- switch (iph->ip_v) {
- case IPVERSION:
- iph_out = mtod(mout, struct ip *);
-
- /* Fill in the IP header for the ABORT */
- iph_out->ip_v = IPVERSION;
- iph_out->ip_hl = (sizeof(struct ip) / 4);
- iph_out->ip_tos = (u_char)0;
- iph_out->ip_id = 0;
- iph_out->ip_off = 0;
- iph_out->ip_ttl = MAXTTL;
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ src_sin = (struct sockaddr_in *)src;
+ dst_sin = (struct sockaddr_in *)dst;
+ ip = mtod(mout, struct ip *);
+ ip->ip_v = IPVERSION;
+ ip->ip_hl = (sizeof(struct ip) >> 2);
+ ip->ip_tos = 0;
+ ip->ip_id = ip_newid();
+ ip->ip_off = 0;
+ ip->ip_ttl = MODULE_GLOBAL(ip_defttl);
if (port) {
- iph_out->ip_p = IPPROTO_UDP;
+ ip->ip_p = IPPROTO_UDP;
} else {
- iph_out->ip_p = IPPROTO_SCTP;
+ ip->ip_p = IPPROTO_SCTP;
}
- iph_out->ip_src.s_addr = iph->ip_dst.s_addr;
- iph_out->ip_dst.s_addr = iph->ip_src.s_addr;
-
- /* let IP layer calculate this */
- iph_out->ip_sum = 0;
- offset_out += sizeof(*iph_out);
- comp_cp = (struct sctp_shutdown_complete_msg *)(
- (caddr_t)iph_out + offset_out);
+ ip->ip_src.s_addr = dst_sin->sin_addr.s_addr;
+ ip->ip_dst.s_addr = src_sin->sin_addr.s_addr;
+ ip->ip_sum = 0;
+ len = sizeof(struct ip);
+ shout = (struct sctphdr *)((caddr_t)ip + len);
break;
+#endif
#ifdef INET6
- case IPV6_VERSION >> 4:
- ip6 = (struct ip6_hdr *)iph;
- ip6_out = mtod(mout, struct ip6_hdr *);
-
- /* Fill in the IPv6 header for the ABORT */
- ip6_out->ip6_flow = ip6->ip6_flow;
- ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim);
+ case AF_INET6:
+ src_sin6 = (struct sockaddr_in6 *)src;
+ dst_sin6 = (struct sockaddr_in6 *)dst;
+ ip6 = mtod(mout, struct ip6_hdr *);
+ ip6->ip6_flow = htonl(0x60000000);
+ if (V_ip6_auto_flowlabel) {
+ ip6->ip6_flow |= (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
+ }
+ ip6->ip6_hlim = MODULE_GLOBAL(ip6_defhlim);
if (port) {
- ip6_out->ip6_nxt = IPPROTO_UDP;
+ ip6->ip6_nxt = IPPROTO_UDP;
} else {
- ip6_out->ip6_nxt = IPPROTO_SCTP;
+ ip6->ip6_nxt = IPPROTO_SCTP;
}
- ip6_out->ip6_src = ip6->ip6_dst;
- ip6_out->ip6_dst = ip6->ip6_src;
- /*
- * ?? The old code had both the iph len + payload, I think
- * this is wrong and would never have worked
- */
- ip6_out->ip6_plen = sizeof(struct sctp_shutdown_complete_msg);
- offset_out += sizeof(*ip6_out);
- comp_cp = (struct sctp_shutdown_complete_msg *)(
- (caddr_t)ip6_out + offset_out);
+ ip6->ip6_src = dst_sin6->sin6_addr;
+ ip6->ip6_dst = src_sin6->sin6_addr;
+ len = sizeof(struct ip6_hdr);
+ shout = (struct sctphdr *)((caddr_t)ip6 + len);
break;
-#endif /* INET6 */
+#endif
default:
- /* Currently not supported. */
- sctp_m_freem(mout);
- return;
+ len = 0;
+ shout = mtod(mout, struct sctphdr *);
+ break;
}
if (port) {
- udp = (struct udphdr *)comp_cp;
+ if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
+ sctp_m_freem(mout);
+ return;
+ }
+ udp = (struct udphdr *)shout;
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
- udp->uh_ulen = htons(sizeof(struct sctp_shutdown_complete_msg) + sizeof(struct udphdr));
- if (iph_out)
- udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
- offset_out += sizeof(struct udphdr);
- comp_cp = (struct sctp_shutdown_complete_msg *)((caddr_t)comp_cp + sizeof(struct udphdr));
+ udp->uh_sum = 0;
+ udp->uh_ulen = htons(sizeof(struct udphdr) +
+ sizeof(struct sctphdr) +
+ sizeof(struct sctp_chunkhdr) +
+ cause_len + padding_len);
+ len += sizeof(struct udphdr);
+ shout = (struct sctphdr *)((caddr_t)shout + sizeof(struct udphdr));
+ } else {
+ udp = NULL;
}
+ shout->src_port = sh->dest_port;
+ shout->dest_port = sh->src_port;
+ shout->checksum = 0;
+ if (vtag) {
+ shout->v_tag = htonl(vtag);
+ } else {
+ shout->v_tag = sh->v_tag;
+ }
+ len += sizeof(struct sctphdr);
+ ch = (struct sctp_chunkhdr *)((caddr_t)shout + sizeof(struct sctphdr));
+ ch->chunk_type = type;
+ if (vtag) {
+ ch->chunk_flags = 0;
+ } else {
+ ch->chunk_flags = SCTP_HAD_NO_TCB;
+ }
+ ch->chunk_length = htons(sizeof(struct sctp_chunkhdr) + cause_len);
+ len += sizeof(struct sctp_chunkhdr);
+ len += cause_len + padding_len;
+
if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
- /* no mbuf's */
sctp_m_freem(mout);
return;
}
- /* Now copy in and fill in the ABORT tags etc. */
- comp_cp->sh.src_port = sh->dest_port;
- comp_cp->sh.dest_port = sh->src_port;
- comp_cp->sh.checksum = 0;
- comp_cp->sh.v_tag = sh->v_tag;
- comp_cp->shut_cmp.ch.chunk_flags = SCTP_HAD_NO_TCB;
- comp_cp->shut_cmp.ch.chunk_type = SCTP_SHUTDOWN_COMPLETE;
- comp_cp->shut_cmp.ch.chunk_length = htons(sizeof(struct sctp_shutdown_complete_chunk));
-
- if (iph_out != NULL) {
- sctp_route_t ro;
- int ret;
-
- mlen = SCTP_BUF_LEN(mout);
- bzero(&ro, sizeof ro);
- /* set IPv4 length */
- iph_out->ip_len = mlen;
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(mout, mlen);
-#endif
+ SCTP_ATTACH_CHAIN(o_pak, mout, len);
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (port) {
+ if (V_udp_cksum) {
+ udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
+ } else {
+ udp->uh_sum = 0;
+ }
+ }
+ ip->ip_len = len;
if (port) {
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_sendnocrc);
#else
- comp_cp->sh.checksum = sctp_calculate_cksum(mout, offset_out);
+ shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip) + sizeof(struct udphdr));
SCTP_STAT_INCR(sctps_sendswcrc);
#endif
- SCTP_ENABLE_UDP_CSUM(mout);
+ if (V_udp_cksum) {
+ SCTP_ENABLE_UDP_CSUM(o_pak);
+ }
} else {
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_sendnocrc);
@@ -10575,183 +11007,99 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
SCTP_STAT_INCR(sctps_sendhwcrc);
#endif
}
- SCTP_ATTACH_CHAIN(o_pak, mout, mlen);
- /* out it goes */
- SCTP_IP_OUTPUT(ret, o_pak, &ro, NULL, vrf_id);
-
- /* Free the route if we got one back */
- if (ro.ro_rt)
- RTFREE(ro.ro_rt);
- }
+#ifdef SCTP_PACKET_LOGGING
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
+ sctp_packet_log(o_pak);
+ }
+#endif
+ SCTP_IP_OUTPUT(ret, o_pak, NULL, NULL, vrf_id);
+ break;
+#endif
#ifdef INET6
- if (ip6_out != NULL) {
- struct route_in6 ro;
- int ret;
- struct ifnet *ifp = NULL;
-
- bzero(&ro, sizeof(ro));
- mlen = SCTP_BUF_LEN(mout);
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(mout, mlen);
-#endif
- SCTP_ATTACH_CHAIN(o_pak, mout, mlen);
+ case AF_INET6:
+ ip6->ip6_plen = len - sizeof(struct ip6_hdr);
if (port) {
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_sendnocrc);
#else
- comp_cp->sh.checksum = sctp_calculate_cksum(mout, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
+ shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
SCTP_STAT_INCR(sctps_sendswcrc);
#endif
- if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), mlen - sizeof(struct ip6_hdr))) == 0) {
+ if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
udp->uh_sum = 0xffff;
}
} else {
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_sendnocrc);
#else
- mout->m_pkthdr.csum_flags = CSUM_SCTP;
- mout->m_pkthdr.csum_data = 0;
- SCTP_STAT_INCR(sctps_sendhwcrc);
+ shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip6_hdr));
+ SCTP_STAT_INCR(sctps_sendswcrc);
#endif
}
- SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, NULL, vrf_id);
-
- /* Free the route if we got one back */
- if (ro.ro_rt)
- RTFREE(ro.ro_rt);
- }
+#ifdef SCTP_PACKET_LOGGING
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
+ sctp_packet_log(o_pak);
+ }
+#endif
+ SCTP_IP6_OUTPUT(ret, o_pak, NULL, NULL, NULL, vrf_id);
+ break;
#endif
+ default:
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "Unknown protocol (TSNH) type %d\n",
+ dst->sa_family);
+ sctp_m_freem(mout);
+ SCTP_LTRACE_ERR_RET_PKT(mout, NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT);
+ return;
+ }
SCTP_STAT_INCR(sctps_sendpackets);
SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
return;
-
}
-static struct sctp_nets *
-sctp_select_hb_destination(struct sctp_tcb *stcb, struct timeval *now)
+void
+sctp_send_shutdown_complete2(struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port)
{
- struct sctp_nets *net, *hnet;
- int ms_goneby, highest_ms, state_overide = 0;
-
- (void)SCTP_GETTIME_TIMEVAL(now);
- highest_ms = 0;
- hnet = NULL;
- SCTP_TCB_LOCK_ASSERT(stcb);
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if (
- ((net->dest_state & SCTP_ADDR_NOHB) && ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0)) ||
- (net->dest_state & SCTP_ADDR_OUT_OF_SCOPE)
- ) {
- /*
- * Skip this guy from consideration if HB is off AND
- * its confirmed
- */
- continue;
- }
- if (sctp_destination_is_reachable(stcb, (struct sockaddr *)&net->ro._l_addr) == 0) {
- /* skip this dest net from consideration */
- continue;
- }
- if (net->last_sent_time.tv_sec) {
- /* Sent to so we subtract */
- ms_goneby = (now->tv_sec - net->last_sent_time.tv_sec) * 1000;
- } else
- /* Never been sent to */
- ms_goneby = 0x7fffffff;
- /*-
- * When the address state is unconfirmed but still
- * considered reachable, we HB at a higher rate. Once it
- * goes confirmed OR reaches the "unreachable" state, thenw
- * we cut it back to HB at a more normal pace.
- */
- if ((net->dest_state & (SCTP_ADDR_UNCONFIRMED | SCTP_ADDR_NOT_REACHABLE)) == SCTP_ADDR_UNCONFIRMED) {
- state_overide = 1;
- } else {
- state_overide = 0;
- }
-
- if ((((unsigned int)ms_goneby >= net->RTO) || (state_overide)) &&
- (ms_goneby > highest_ms)) {
- highest_ms = ms_goneby;
- hnet = net;
- }
- }
- if (hnet &&
- ((hnet->dest_state & (SCTP_ADDR_UNCONFIRMED | SCTP_ADDR_NOT_REACHABLE)) == SCTP_ADDR_UNCONFIRMED)) {
- state_overide = 1;
- } else {
- state_overide = 0;
- }
-
- if (hnet && highest_ms && (((unsigned int)highest_ms >= hnet->RTO) || state_overide)) {
- /*-
- * Found the one with longest delay bounds OR it is
- * unconfirmed and still not marked unreachable.
- */
- SCTPDBG(SCTP_DEBUG_OUTPUT4, "net:%p is the hb winner -", hnet);
-#ifdef SCTP_DEBUG
- if (hnet) {
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT4,
- (struct sockaddr *)&hnet->ro._l_addr);
- } else {
- SCTPDBG(SCTP_DEBUG_OUTPUT4, " none\n");
- }
-#endif
- /* update the timer now */
- hnet->last_sent_time = *now;
- return (hnet);
- }
- /* Nothing to HB */
- return (NULL);
+ sctp_send_resp_msg(src, dst, sh, 0, SCTP_SHUTDOWN_COMPLETE, NULL,
+ use_mflowid, mflowid,
+ vrf_id, port);
}
-int
-sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net)
+void
+sctp_send_hb(struct sctp_tcb *stcb, struct sctp_nets *net, int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+ SCTP_UNUSED
+#endif
+)
{
struct sctp_tmit_chunk *chk;
- struct sctp_nets *net;
struct sctp_heartbeat_chunk *hb;
struct timeval now;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
SCTP_TCB_LOCK_ASSERT(stcb);
- if (user_req == 0) {
- net = sctp_select_hb_destination(stcb, &now);
- if (net == NULL) {
- /*-
- * All our busy none to send to, just start the
- * timer again.
- */
- if (stcb->asoc.state == 0) {
- return (0);
- }
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT,
- stcb->sctp_ep,
- stcb,
- net);
- return (0);
- }
- } else {
- net = u_net;
- if (net == NULL) {
- return (0);
- }
- (void)SCTP_GETTIME_TIMEVAL(&now);
+ if (net == NULL) {
+ return;
}
- sin = (struct sockaddr_in *)&net->ro._l_addr;
- if (sin->sin_family != AF_INET) {
- if (sin->sin_family != AF_INET6) {
- /* huh */
- return (0);
- }
+ (void)SCTP_GETTIME_TIMEVAL(&now);
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ break;
+#endif
+ default:
+ return;
}
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Gak, can't get a chunk for hb\n");
- return (0);
+ return;
}
chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_HEARTBEAT_REQUEST;
@@ -10761,8 +11109,8 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net)
chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_DONTWAIT, 1, MT_HEADER);
if (chk->data == NULL) {
- sctp_free_a_chunk(stcb, chk);
- return (0);
+ sctp_free_a_chunk(stcb, chk, so_locked);
+ return;
}
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
SCTP_BUF_LEN(chk->data) = chk->send_size;
@@ -10783,9 +11131,8 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net)
hb->heartbeat.hb_info.time_value_1 = now.tv_sec;
hb->heartbeat.hb_info.time_value_2 = now.tv_usec;
/* Did our user request this one, put it in */
- hb->heartbeat.hb_info.user_req = user_req;
- hb->heartbeat.hb_info.addr_family = sin->sin_family;
- hb->heartbeat.hb_info.addr_len = sin->sin_len;
+ hb->heartbeat.hb_info.addr_family = net->ro._l_addr.sa.sa_family;
+ hb->heartbeat.hb_info.addr_len = net->ro._l_addr.sa.sa_len;
if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
/*
* we only take from the entropy pool if the address is not
@@ -10797,64 +11144,30 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net)
net->heartbeat_random1 = hb->heartbeat.hb_info.random_value1 = 0;
net->heartbeat_random2 = hb->heartbeat.hb_info.random_value2 = 0;
}
- if (sin->sin_family == AF_INET) {
- memcpy(hb->heartbeat.hb_info.address, &sin->sin_addr, sizeof(sin->sin_addr));
- } else if (sin->sin_family == AF_INET6) {
- /* We leave the scope the way it is in our lookup table. */
- sin6 = (struct sockaddr_in6 *)&net->ro._l_addr;
- memcpy(hb->heartbeat.hb_info.address, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
- } else {
- /* huh compiler bug */
- return (0);
- }
-
- /*
- * JRS 5/14/07 - In CMT PF, the T3 timer is used to track
- * PF-heartbeats. Because of this, threshold management is done by
- * the t3 timer handler, and does not need to be done upon the send
- * of a PF-heartbeat. If CMT PF is on and the destination to which a
- * heartbeat is being sent is in PF state, do NOT do threshold
- * management.
- */
- if ((stcb->asoc.sctp_cmt_pf == 0) ||
- ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF)) {
- /* ok we have a destination that needs a beat */
- /* lets do the theshold management Qiaobing style */
- if (sctp_threshold_management(stcb->sctp_ep, stcb, net,
- stcb->asoc.max_send_times)) {
- /*-
- * we have lost the association, in a way this is
- * quite bad since we really are one less time since
- * we really did not send yet. This is the down side
- * to the Q's style as defined in the RFC and not my
- * alternate style defined in the RFC.
- */
- if (chk->data != NULL) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
- /*
- * Here we do NOT use the macro since the
- * association is now gone.
- */
- if (chk->whoTo) {
- sctp_free_remote_addr(chk->whoTo);
- chk->whoTo = NULL;
- }
- sctp_free_a_chunk((struct sctp_tcb *)NULL, chk);
- return (-1);
- }
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ memcpy(hb->heartbeat.hb_info.address,
+ &net->ro._l_addr.sin.sin_addr,
+ sizeof(net->ro._l_addr.sin.sin_addr));
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ memcpy(hb->heartbeat.hb_info.address,
+ &net->ro._l_addr.sin6.sin6_addr,
+ sizeof(net->ro._l_addr.sin6.sin6_addr));
+ break;
+#endif
+ default:
+ return;
+ break;
}
net->hb_responded = 0;
TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, chk, sctp_next);
stcb->asoc.ctrl_queue_cnt++;
SCTP_STAT_INCR(sctps_sendheartbeat);
- /*-
- * Call directly med level routine to put out the chunk. It will
- * always tumble out control chunks aka HB but it may even tumble
- * out data too.
- */
- return (1);
+ return;
}
void
@@ -10865,13 +11178,25 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
struct sctp_ecne_chunk *ecne;
struct sctp_tmit_chunk *chk;
+ if (net == NULL) {
+ return;
+ }
asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
- if (chk->rec.chunk_id.id == SCTP_ECN_ECHO) {
+ if ((chk->rec.chunk_id.id == SCTP_ECN_ECHO) && (net == chk->whoTo)) {
/* found a previous ECN_ECHO update it if needed */
+ uint32_t cnt, ctsn;
+
ecne = mtod(chk->data, struct sctp_ecne_chunk *);
- ecne->tsn = htonl(high_tsn);
+ ctsn = ntohl(ecne->tsn);
+ if (SCTP_TSN_GT(high_tsn, ctsn)) {
+ ecne->tsn = htonl(high_tsn);
+ SCTP_STAT_INCR(sctps_queue_upd_ecne);
+ }
+ cnt = ntohl(ecne->num_pkts_since_cwr);
+ cnt++;
+ ecne->num_pkts_since_cwr = htonl(cnt);
return;
}
}
@@ -10881,14 +11206,14 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
return;
}
chk->copy_by_ref = 0;
- SCTP_STAT_INCR(sctps_sendecne);
+ SCTP_STAT_INCR(sctps_queue_upd_ecne);
chk->rec.chunk_id.id = SCTP_ECN_ECHO;
chk->rec.chunk_id.can_take_data = 0;
chk->asoc = &stcb->asoc;
chk->send_size = sizeof(struct sctp_ecne_chunk);
chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_DONTWAIT, 1, MT_HEADER);
if (chk->data == NULL) {
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
return;
}
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
@@ -10897,33 +11222,28 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
chk->snd_count = 0;
chk->whoTo = net;
atomic_add_int(&chk->whoTo->ref_count, 1);
+
stcb->asoc.ecn_echo_cnt_onq++;
ecne = mtod(chk->data, struct sctp_ecne_chunk *);
ecne->ch.chunk_type = SCTP_ECN_ECHO;
ecne->ch.chunk_flags = 0;
ecne->ch.chunk_length = htons(sizeof(struct sctp_ecne_chunk));
ecne->tsn = htonl(high_tsn);
- TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, chk, sctp_next);
+ ecne->num_pkts_since_cwr = htonl(1);
+ TAILQ_INSERT_HEAD(&stcb->asoc.control_send_queue, chk, sctp_next);
asoc->ctrl_queue_cnt++;
}
void
sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
- struct mbuf *m, int iphlen, int bad_crc)
+ struct mbuf *m, int len, int iphlen, int bad_crc)
{
struct sctp_association *asoc;
struct sctp_pktdrop_chunk *drp;
struct sctp_tmit_chunk *chk;
uint8_t *datap;
- int len;
int was_trunc = 0;
- struct ip *iph;
-
-#ifdef INET6
- struct ip6_hdr *ip6h;
-
-#endif
- int fullsz = 0, extra = 0;
+ int fullsz = 0;
long spc;
int offset;
struct sctp_chunkhdr *ch, chunk_buf;
@@ -10948,26 +11268,8 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
return;
}
chk->copy_by_ref = 0;
- iph = mtod(m, struct ip *);
- if (iph == NULL) {
- sctp_free_a_chunk(stcb, chk);
- return;
- }
- switch (iph->ip_v) {
- case IPVERSION:
- /* IPv4 */
- len = chk->send_size = iph->ip_len;
- break;
-#ifdef INET6
- case IPV6_VERSION >> 4:
- /* IPv6 */
- ip6h = mtod(m, struct ip6_hdr *);
- len = chk->send_size = htons(ip6h->ip6_plen);
- break;
-#endif
- default:
- return;
- }
+ len -= iphlen;
+ chk->send_size = len;
/* Validate that we do not have an ABORT in here. */
offset = iphlen + sizeof(struct sctphdr);
ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
@@ -10988,7 +11290,7 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
* INIT-ACK, because we can't know if the initiation
* tag is correct or not.
*/
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
return;
default:
break;
@@ -11003,7 +11305,7 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
/*
* only send 1 mtu worth, trim off the excess on the end.
*/
- fullsz = len - extra;
+ fullsz = len;
len = min(stcb->asoc.smallest_mtu, MCLBYTES) - SCTP_MAX_OVERHEAD;
was_trunc = 1;
}
@@ -11011,7 +11313,7 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
if (chk->data == NULL) {
jump_out:
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
return;
}
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
@@ -11048,10 +11350,10 @@ jump_out:
if (net) {
/* we should hit here */
chk->whoTo = net;
+ atomic_add_int(&chk->whoTo->ref_count, 1);
} else {
- chk->whoTo = asoc->primary_destination;
+ chk->whoTo = NULL;
}
- atomic_add_int(&chk->whoTo->ref_count, 1);
chk->rec.chunk_id.id = SCTP_PACKET_DROPPED;
chk->rec.chunk_id.can_take_data = 1;
drp->ch.chunk_type = SCTP_PACKET_DROPPED;
@@ -11081,26 +11383,37 @@ jump_out:
}
void
-sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn)
+sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn, uint8_t override)
{
struct sctp_association *asoc;
struct sctp_cwr_chunk *cwr;
struct sctp_tmit_chunk *chk;
- asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
+ if (net == NULL) {
+ return;
+ }
+ asoc = &stcb->asoc;
TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
- if (chk->rec.chunk_id.id == SCTP_ECN_CWR) {
- /* found a previous ECN_CWR update it if needed */
+ if ((chk->rec.chunk_id.id == SCTP_ECN_CWR) && (net == chk->whoTo)) {
+ /*
+ * found a previous CWR queued to same destination
+ * update it if needed
+ */
+ uint32_t ctsn;
+
cwr = mtod(chk->data, struct sctp_cwr_chunk *);
- if (compare_with_wrap(high_tsn, ntohl(cwr->tsn),
- MAX_TSN)) {
+ ctsn = ntohl(cwr->tsn);
+ if (SCTP_TSN_GT(high_tsn, ctsn)) {
cwr->tsn = htonl(high_tsn);
}
+ if (override & SCTP_CWR_REDUCE_OVERRIDE) {
+ /* Make sure override is carried */
+ cwr->ch.chunk_flags |= SCTP_CWR_REDUCE_OVERRIDE;
+ }
return;
}
}
- /* nope could not find one to update so we must build one */
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
return;
@@ -11112,7 +11425,7 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn)
chk->send_size = sizeof(struct sctp_cwr_chunk);
chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_DONTWAIT, 1, MT_HEADER);
if (chk->data == NULL) {
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
return;
}
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
@@ -11123,7 +11436,7 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn)
atomic_add_int(&chk->whoTo->ref_count, 1);
cwr = mtod(chk->data, struct sctp_cwr_chunk *);
cwr->ch.chunk_type = SCTP_ECN_CWR;
- cwr->ch.chunk_flags = 0;
+ cwr->ch.chunk_flags = override;
cwr->ch.chunk_length = htons(sizeof(struct sctp_cwr_chunk));
cwr->tsn = htonl(high_tsn);
TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, chk, sctp_next);
@@ -11135,13 +11448,11 @@ sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk,
int number_entries, uint16_t * list,
uint32_t seq, uint32_t resp_seq, uint32_t last_sent)
{
- int len, old_len, i;
+ uint16_t len, old_len, i;
struct sctp_stream_reset_out_request *req_out;
struct sctp_chunkhdr *ch;
ch = mtod(chk->data, struct sctp_chunkhdr *);
-
-
old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length));
/* get to new offset for the param. */
@@ -11175,19 +11486,16 @@ sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk,
return;
}
-
-void
+static void
sctp_add_stream_reset_in(struct sctp_tmit_chunk *chk,
int number_entries, uint16_t * list,
uint32_t seq)
{
- int len, old_len, i;
+ uint16_t len, old_len, i;
struct sctp_stream_reset_in_request *req_in;
struct sctp_chunkhdr *ch;
ch = mtod(chk->data, struct sctp_chunkhdr *);
-
-
old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length));
/* get to new offset for the param. */
@@ -11219,18 +11527,15 @@ sctp_add_stream_reset_in(struct sctp_tmit_chunk *chk,
return;
}
-
-void
+static void
sctp_add_stream_reset_tsn(struct sctp_tmit_chunk *chk,
uint32_t seq)
{
- int len, old_len;
+ uint16_t len, old_len;
struct sctp_stream_reset_tsn_request *req_tsn;
struct sctp_chunkhdr *ch;
ch = mtod(chk->data, struct sctp_chunkhdr *);
-
-
old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length));
/* get to new offset for the param. */
@@ -11254,13 +11559,11 @@ void
sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk,
uint32_t resp_seq, uint32_t result)
{
- int len, old_len;
+ uint16_t len, old_len;
struct sctp_stream_reset_response *resp;
struct sctp_chunkhdr *ch;
ch = mtod(chk->data, struct sctp_chunkhdr *);
-
-
old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length));
/* get to new offset for the param. */
@@ -11279,22 +11582,18 @@ sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk,
chk->send_size = SCTP_SIZE32(chk->book_size);
SCTP_BUF_LEN(chk->data) = chk->send_size;
return;
-
}
-
void
sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk,
uint32_t resp_seq, uint32_t result,
uint32_t send_una, uint32_t recv_next)
{
- int len, old_len;
+ uint16_t len, old_len;
struct sctp_stream_reset_response_tsn *resp;
struct sctp_chunkhdr *ch;
ch = mtod(chk->data, struct sctp_chunkhdr *);
-
-
old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length));
/* get to new offset for the param. */
@@ -11318,11 +11617,11 @@ sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk,
}
static void
-sctp_add_a_stream(struct sctp_tmit_chunk *chk,
+sctp_add_an_out_stream(struct sctp_tmit_chunk *chk,
uint32_t seq,
uint16_t adding)
{
- int len, old_len;
+ uint16_t len, old_len;
struct sctp_chunkhdr *ch;
struct sctp_stream_reset_add_strm *addstr;
@@ -11335,7 +11634,39 @@ sctp_add_a_stream(struct sctp_tmit_chunk *chk,
len = sizeof(struct sctp_stream_reset_add_strm);
/* Fill it out. */
- addstr->ph.param_type = htons(SCTP_STR_RESET_ADD_STREAMS);
+ addstr->ph.param_type = htons(SCTP_STR_RESET_ADD_OUT_STREAMS);
+ addstr->ph.param_length = htons(len);
+ addstr->request_seq = htonl(seq);
+ addstr->number_of_streams = htons(adding);
+ addstr->reserved = 0;
+
+ /* now fix the chunk length */
+ ch->chunk_length = htons(len + old_len);
+ chk->send_size = len + old_len;
+ chk->book_size = SCTP_SIZE32(chk->send_size);
+ chk->book_size_scale = 0;
+ SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size);
+ return;
+}
+
+static void
+sctp_add_an_in_stream(struct sctp_tmit_chunk *chk,
+ uint32_t seq,
+ uint16_t adding)
+{
+ uint16_t len, old_len;
+ struct sctp_chunkhdr *ch;
+ struct sctp_stream_reset_add_strm *addstr;
+
+ ch = mtod(chk->data, struct sctp_chunkhdr *);
+ old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length));
+
+ /* get to new offset for the param. */
+ addstr = (struct sctp_stream_reset_add_strm *)((caddr_t)ch + len);
+ /* now how long will this param be? */
+ len = sizeof(struct sctp_stream_reset_add_strm);
+ /* Fill it out. */
+ addstr->ph.param_type = htons(SCTP_STR_RESET_ADD_IN_STREAMS);
addstr->ph.param_length = htons(len);
addstr->request_seq = htonl(seq);
addstr->number_of_streams = htons(adding);
@@ -11354,12 +11685,11 @@ int
sctp_send_str_reset_req(struct sctp_tcb *stcb,
int number_entries, uint16_t * list,
uint8_t send_out_req,
- uint32_t resp_seq,
uint8_t send_in_req,
uint8_t send_tsn_req,
uint8_t add_stream,
- uint16_t adding
-)
+ uint16_t adding_o,
+ uint16_t adding_i, uint8_t peer_asked)
{
struct sctp_association *asoc;
@@ -11401,7 +11731,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
if (chk->data == NULL) {
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_LOCKED);
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
@@ -11410,9 +11740,12 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
/* setup chunk parameters */
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->whoTo = asoc->primary_destination;
+ if (stcb->asoc.alternate) {
+ chk->whoTo = stcb->asoc.alternate;
+ } else {
+ chk->whoTo = stcb->asoc.primary_destination;
+ }
atomic_add_int(&chk->whoTo->ref_count, 1);
-
ch = mtod(chk->data, struct sctp_chunkhdr *);
ch->chunk_type = SCTP_STREAM_RESET;
ch->chunk_flags = 0;
@@ -11422,18 +11755,88 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
seq = stcb->asoc.str_reset_seq_out;
if (send_out_req) {
sctp_add_stream_reset_out(chk, number_entries, list,
- seq, resp_seq, (stcb->asoc.sending_seq - 1));
+ seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1));
asoc->stream_reset_out_is_outstanding = 1;
seq++;
asoc->stream_reset_outstanding++;
}
- if (add_stream) {
- sctp_add_a_stream(chk, seq, adding);
+ if ((add_stream & 1) &&
+ ((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < adding_o)) {
+ /* Need to allocate more */
+ struct sctp_stream_out *oldstream;
+ struct sctp_stream_queue_pending *sp, *nsp;
+ int i;
+
+ oldstream = stcb->asoc.strmout;
+ /* get some more */
+ SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *,
+ ((stcb->asoc.streamoutcnt + adding_o) * sizeof(struct sctp_stream_out)),
+ SCTP_M_STRMO);
+ if (stcb->asoc.strmout == NULL) {
+ uint8_t x;
+
+ stcb->asoc.strmout = oldstream;
+ /* Turn off the bit */
+ x = add_stream & 0xfe;
+ add_stream = x;
+ goto skip_stuff;
+ }
+ /*
+ * Ok now we proceed with copying the old out stuff and
+ * initializing the new stuff.
+ */
+ SCTP_TCB_SEND_LOCK(stcb);
+ stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 0, 1);
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
+ stcb->asoc.strmout[i].chunks_on_queues = oldstream[i].chunks_on_queues;
+ stcb->asoc.strmout[i].next_sequence_send = oldstream[i].next_sequence_send;
+ stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete;
+ stcb->asoc.strmout[i].stream_no = i;
+ stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], &oldstream[i]);
+ /* now anything on those queues? */
+ TAILQ_FOREACH_SAFE(sp, &oldstream[i].outqueue, next, nsp) {
+ TAILQ_REMOVE(&oldstream[i].outqueue, sp, next);
+ TAILQ_INSERT_TAIL(&stcb->asoc.strmout[i].outqueue, sp, next);
+ }
+ /* Now move assoc pointers too */
+ if (stcb->asoc.last_out_stream == &oldstream[i]) {
+ stcb->asoc.last_out_stream = &stcb->asoc.strmout[i];
+ }
+ if (stcb->asoc.locked_on_sending == &oldstream[i]) {
+ stcb->asoc.locked_on_sending = &stcb->asoc.strmout[i];
+ }
+ }
+ /* now the new streams */
+ stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
+ for (i = stcb->asoc.streamoutcnt; i < (stcb->asoc.streamoutcnt + adding_o); i++) {
+ TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
+ stcb->asoc.strmout[i].chunks_on_queues = 0;
+ stcb->asoc.strmout[i].next_sequence_send = 0x0;
+ stcb->asoc.strmout[i].stream_no = i;
+ stcb->asoc.strmout[i].last_msg_incomplete = 0;
+ stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
+ }
+ stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + adding_o;
+ SCTP_FREE(oldstream, SCTP_M_STRMO);
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ }
+skip_stuff:
+ if ((add_stream & 1) && (adding_o > 0)) {
+ asoc->strm_pending_add_size = adding_o;
+ asoc->peer_req_out = peer_asked;
+ sctp_add_an_out_stream(chk, seq, adding_o);
+ seq++;
+ asoc->stream_reset_outstanding++;
+ }
+ if ((add_stream & 2) && (adding_i > 0)) {
+ sctp_add_an_in_stream(chk, seq, adding_i);
seq++;
asoc->stream_reset_outstanding++;
}
if (send_in_req) {
sctp_add_stream_reset_in(chk, number_entries, list, seq);
+ seq++;
asoc->stream_reset_outstanding++;
}
if (send_tsn_req) {
@@ -11441,7 +11844,6 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
asoc->stream_reset_outstanding++;
}
asoc->str_reset = chk;
-
/* insert the chunk for sending */
TAILQ_INSERT_TAIL(&asoc->control_send_queue,
chk,
@@ -11452,499 +11854,37 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
}
void
-sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
- struct mbuf *err_cause, uint32_t vrf_id, uint16_t port)
+sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh, uint32_t vtag, struct mbuf *cause,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port)
{
- /*-
- * Formulate the abort message, and send it back down.
- */
- struct mbuf *o_pak;
- struct mbuf *mout;
- struct sctp_abort_msg *abm;
- struct ip *iph, *iph_out;
- struct udphdr *udp;
-
-#ifdef INET6
- struct ip6_hdr *ip6, *ip6_out;
-
-#endif
- int iphlen_out, len;
-
- /* don't respond to ABORT with ABORT */
+ /* Don't respond to an ABORT with an ABORT. */
if (sctp_is_there_an_abort_here(m, iphlen, &vtag)) {
- if (err_cause)
- sctp_m_freem(err_cause);
- return;
- }
- iph = mtod(m, struct ip *);
- switch (iph->ip_v) {
- case IPVERSION:
- len = (sizeof(struct ip) + sizeof(struct sctp_abort_msg));
- break;
-#ifdef INET6
- case IPV6_VERSION >> 4:
- len = (sizeof(struct ip6_hdr) + sizeof(struct sctp_abort_msg));
- break;
-#endif
- default:
- if (err_cause) {
- sctp_m_freem(err_cause);
- }
- return;
- }
- if (port) {
- len += sizeof(struct udphdr);
- }
- mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, MT_DATA);
- if (mout == NULL) {
- if (err_cause) {
- sctp_m_freem(err_cause);
- }
- return;
- }
- SCTP_BUF_RESV_UF(mout, max_linkhdr);
- SCTP_BUF_LEN(mout) = len;
- SCTP_BUF_NEXT(mout) = err_cause;
- iph_out = NULL;
-#ifdef INET6
- ip6_out = NULL;
-#endif
- switch (iph->ip_v) {
- case IPVERSION:
- iph_out = mtod(mout, struct ip *);
-
- /* Fill in the IP header for the ABORT */
- iph_out->ip_v = IPVERSION;
- iph_out->ip_hl = (sizeof(struct ip) / 4);
- iph_out->ip_tos = (u_char)0;
- iph_out->ip_id = 0;
- iph_out->ip_off = 0;
- iph_out->ip_ttl = MAXTTL;
- if (port) {
- iph_out->ip_p = IPPROTO_UDP;
- } else {
- iph_out->ip_p = IPPROTO_SCTP;
- }
- iph_out->ip_src.s_addr = iph->ip_dst.s_addr;
- iph_out->ip_dst.s_addr = iph->ip_src.s_addr;
- /* let IP layer calculate this */
- iph_out->ip_sum = 0;
-
- iphlen_out = sizeof(*iph_out);
- abm = (struct sctp_abort_msg *)((caddr_t)iph_out + iphlen_out);
- break;
-#ifdef INET6
- case IPV6_VERSION >> 4:
- ip6 = (struct ip6_hdr *)iph;
- ip6_out = mtod(mout, struct ip6_hdr *);
-
- /* Fill in the IP6 header for the ABORT */
- ip6_out->ip6_flow = ip6->ip6_flow;
- ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim);
- if (port) {
- ip6_out->ip6_nxt = IPPROTO_UDP;
- } else {
- ip6_out->ip6_nxt = IPPROTO_SCTP;
- }
- ip6_out->ip6_src = ip6->ip6_dst;
- ip6_out->ip6_dst = ip6->ip6_src;
-
- iphlen_out = sizeof(*ip6_out);
- abm = (struct sctp_abort_msg *)((caddr_t)ip6_out + iphlen_out);
- break;
-#endif /* INET6 */
- default:
- /* Currently not supported */
- sctp_m_freem(mout);
- return;
- }
-
- udp = (struct udphdr *)abm;
- if (port) {
- udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
- udp->uh_dport = port;
- /* set udp->uh_ulen later */
- udp->uh_sum = 0;
- iphlen_out += sizeof(struct udphdr);
- abm = (struct sctp_abort_msg *)((caddr_t)abm + sizeof(struct udphdr));
- }
- abm->sh.src_port = sh->dest_port;
- abm->sh.dest_port = sh->src_port;
- abm->sh.checksum = 0;
- if (vtag == 0) {
- abm->sh.v_tag = sh->v_tag;
- abm->msg.ch.chunk_flags = SCTP_HAD_NO_TCB;
- } else {
- abm->sh.v_tag = htonl(vtag);
- abm->msg.ch.chunk_flags = 0;
- }
- abm->msg.ch.chunk_type = SCTP_ABORT_ASSOCIATION;
-
- if (err_cause) {
- struct mbuf *m_tmp = err_cause;
- int err_len = 0;
-
- /* get length of the err_cause chain */
- while (m_tmp != NULL) {
- err_len += SCTP_BUF_LEN(m_tmp);
- m_tmp = SCTP_BUF_NEXT(m_tmp);
- }
- len = SCTP_BUF_LEN(mout) + err_len;
- if (err_len % 4) {
- /* need pad at end of chunk */
- uint32_t cpthis = 0;
- int padlen;
-
- padlen = 4 - (len % 4);
- m_copyback(mout, len, padlen, (caddr_t)&cpthis);
- len += padlen;
- }
- abm->msg.ch.chunk_length = htons(sizeof(abm->msg.ch) + err_len);
- } else {
- len = SCTP_BUF_LEN(mout);
- abm->msg.ch.chunk_length = htons(sizeof(abm->msg.ch));
- }
-
- if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
- /* no mbuf's */
- sctp_m_freem(mout);
+ if (cause)
+ sctp_m_freem(cause);
return;
}
- if (iph_out != NULL) {
- sctp_route_t ro;
- int ret;
-
- /* zap the stack pointer to the route */
- bzero(&ro, sizeof ro);
- if (port) {
- udp->uh_ulen = htons(len - sizeof(struct ip));
- udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
- }
- SCTPDBG(SCTP_DEBUG_OUTPUT2, "sctp_send_abort calling ip_output:\n");
- SCTPDBG_PKT(SCTP_DEBUG_OUTPUT2, iph_out, &abm->sh);
- /* set IPv4 length */
- iph_out->ip_len = len;
- /* out it goes */
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(mout, len);
-#endif
- SCTP_ATTACH_CHAIN(o_pak, mout, len);
- if (port) {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- abm->sh.checksum = sctp_calculate_cksum(mout, iphlen_out);
- SCTP_STAT_INCR(sctps_sendswcrc);
-#endif
- SCTP_ENABLE_UDP_CSUM(o_pak);
- } else {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- mout->m_pkthdr.csum_flags = CSUM_SCTP;
- mout->m_pkthdr.csum_data = 0;
- SCTP_STAT_INCR(sctps_sendhwcrc);
-#endif
- }
- SCTP_IP_OUTPUT(ret, o_pak, &ro, NULL, vrf_id);
-
- /* Free the route if we got one back */
- if (ro.ro_rt)
- RTFREE(ro.ro_rt);
- }
-#ifdef INET6
- if (ip6_out != NULL) {
- struct route_in6 ro;
- int ret;
- struct ifnet *ifp = NULL;
-
- /* zap the stack pointer to the route */
- bzero(&ro, sizeof(ro));
- if (port) {
- udp->uh_ulen = htons(len - sizeof(struct ip6_hdr));
- }
- SCTPDBG(SCTP_DEBUG_OUTPUT2, "sctp_send_abort calling ip6_output:\n");
- SCTPDBG_PKT(SCTP_DEBUG_OUTPUT2, (struct ip *)ip6_out, &abm->sh);
- ip6_out->ip6_plen = len - sizeof(*ip6_out);
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(mout, len);
-#endif
- SCTP_ATTACH_CHAIN(o_pak, mout, len);
- if (port) {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- abm->sh.checksum = sctp_calculate_cksum(mout, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
- SCTP_STAT_INCR(sctps_sendswcrc);
-#endif
- if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
- udp->uh_sum = 0xffff;
- }
- } else {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- mout->m_pkthdr.csum_flags = CSUM_SCTP;
- mout->m_pkthdr.csum_data = 0;
- SCTP_STAT_INCR(sctps_sendhwcrc);
-#endif
- }
- SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, NULL, vrf_id);
-
- /* Free the route if we got one back */
- if (ro.ro_rt)
- RTFREE(ro.ro_rt);
- }
-#endif
- SCTP_STAT_INCR(sctps_sendpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
+ sctp_send_resp_msg(src, dst, sh, vtag, SCTP_ABORT_ASSOCIATION, cause,
+ use_mflowid, mflowid,
+ vrf_id, port);
+ return;
}
void
-sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag,
+sctp_send_operr_to(struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh, uint32_t vtag, struct mbuf *cause,
+ uint8_t use_mflowid, uint32_t mflowid,
uint32_t vrf_id, uint16_t port)
{
- struct mbuf *o_pak;
- struct sctphdr *sh, *sh_out;
- struct sctp_chunkhdr *ch;
- struct ip *iph, *iph_out;
- struct udphdr *udp = NULL;
- struct mbuf *mout;
-
-#ifdef INET6
- struct ip6_hdr *ip6, *ip6_out;
-
-#endif
- int iphlen_out, len;
-
- iph = mtod(m, struct ip *);
- sh = (struct sctphdr *)((caddr_t)iph + iphlen);
- switch (iph->ip_v) {
- case IPVERSION:
- len = (sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr));
- break;
-#ifdef INET6
- case IPV6_VERSION >> 4:
- len = (sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr));
- break;
-#endif
- default:
- if (scm) {
- sctp_m_freem(scm);
- }
- return;
- }
- if (port) {
- len += sizeof(struct udphdr);
- }
- mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, MT_DATA);
- if (mout == NULL) {
- if (scm) {
- sctp_m_freem(scm);
- }
- return;
- }
- SCTP_BUF_RESV_UF(mout, max_linkhdr);
- SCTP_BUF_LEN(mout) = len;
- SCTP_BUF_NEXT(mout) = scm;
- iph_out = NULL;
-#ifdef INET6
- ip6_out = NULL;
-#endif
- switch (iph->ip_v) {
- case IPVERSION:
- iph_out = mtod(mout, struct ip *);
-
- /* Fill in the IP header for the ABORT */
- iph_out->ip_v = IPVERSION;
- iph_out->ip_hl = (sizeof(struct ip) / 4);
- iph_out->ip_tos = (u_char)0;
- iph_out->ip_id = 0;
- iph_out->ip_off = 0;
- iph_out->ip_ttl = MAXTTL;
- if (port) {
- iph_out->ip_p = IPPROTO_UDP;
- } else {
- iph_out->ip_p = IPPROTO_SCTP;
- }
- iph_out->ip_src.s_addr = iph->ip_dst.s_addr;
- iph_out->ip_dst.s_addr = iph->ip_src.s_addr;
- /* let IP layer calculate this */
- iph_out->ip_sum = 0;
-
- iphlen_out = sizeof(struct ip);
- sh_out = (struct sctphdr *)((caddr_t)iph_out + iphlen_out);
- break;
-#ifdef INET6
- case IPV6_VERSION >> 4:
- ip6 = (struct ip6_hdr *)iph;
- ip6_out = mtod(mout, struct ip6_hdr *);
-
- /* Fill in the IP6 header for the ABORT */
- ip6_out->ip6_flow = ip6->ip6_flow;
- ip6_out->ip6_hlim = MODULE_GLOBAL(ip6_defhlim);
- if (port) {
- ip6_out->ip6_nxt = IPPROTO_UDP;
- } else {
- ip6_out->ip6_nxt = IPPROTO_SCTP;
- }
- ip6_out->ip6_src = ip6->ip6_dst;
- ip6_out->ip6_dst = ip6->ip6_src;
-
- iphlen_out = sizeof(struct ip6_hdr);
- sh_out = (struct sctphdr *)((caddr_t)ip6_out + iphlen_out);
- break;
-#endif /* INET6 */
- default:
- /* Currently not supported */
- sctp_m_freem(mout);
- return;
- }
-
- udp = (struct udphdr *)sh_out;
- if (port) {
- udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
- udp->uh_dport = port;
- /* set udp->uh_ulen later */
- udp->uh_sum = 0;
- iphlen_out += sizeof(struct udphdr);
- sh_out = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
- }
- sh_out->src_port = sh->dest_port;
- sh_out->dest_port = sh->src_port;
- sh_out->v_tag = vtag;
- sh_out->checksum = 0;
-
- ch = (struct sctp_chunkhdr *)((caddr_t)sh_out + sizeof(struct sctphdr));
- ch->chunk_type = SCTP_OPERATION_ERROR;
- ch->chunk_flags = 0;
-
- if (scm) {
- struct mbuf *m_tmp = scm;
- int cause_len = 0;
-
- /* get length of the err_cause chain */
- while (m_tmp != NULL) {
- cause_len += SCTP_BUF_LEN(m_tmp);
- m_tmp = SCTP_BUF_NEXT(m_tmp);
- }
- len = SCTP_BUF_LEN(mout) + cause_len;
- if (cause_len % 4) {
- /* need pad at end of chunk */
- uint32_t cpthis = 0;
- int padlen;
-
- padlen = 4 - (len % 4);
- m_copyback(mout, len, padlen, (caddr_t)&cpthis);
- len += padlen;
- }
- ch->chunk_length = htons(sizeof(struct sctp_chunkhdr) + cause_len);
- } else {
- len = SCTP_BUF_LEN(mout);
- ch->chunk_length = htons(sizeof(struct sctp_chunkhdr));
- }
-
- if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
- /* no mbuf's */
- sctp_m_freem(mout);
- return;
- }
- if (iph_out != NULL) {
- sctp_route_t ro;
- int ret;
-
- /* zap the stack pointer to the route */
- bzero(&ro, sizeof ro);
- if (port) {
- udp->uh_ulen = htons(len - sizeof(struct ip));
- udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
- }
- /* set IPv4 length */
- iph_out->ip_len = len;
- /* out it goes */
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(mout, len);
-#endif
- SCTP_ATTACH_CHAIN(o_pak, mout, len);
- if (port) {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- sh_out->checksum = sctp_calculate_cksum(mout, iphlen_out);
- SCTP_STAT_INCR(sctps_sendswcrc);
-#endif
- SCTP_ENABLE_UDP_CSUM(o_pak);
- } else {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- mout->m_pkthdr.csum_flags = CSUM_SCTP;
- mout->m_pkthdr.csum_data = 0;
- SCTP_STAT_INCR(sctps_sendhwcrc);
-#endif
- }
- SCTP_IP_OUTPUT(ret, o_pak, &ro, NULL, vrf_id);
-
- /* Free the route if we got one back */
- if (ro.ro_rt)
- RTFREE(ro.ro_rt);
- }
-#ifdef INET6
- if (ip6_out != NULL) {
- struct route_in6 ro;
- int ret;
- struct ifnet *ifp = NULL;
-
- /* zap the stack pointer to the route */
- bzero(&ro, sizeof(ro));
- if (port) {
- udp->uh_ulen = htons(len - sizeof(struct ip6_hdr));
- }
- ip6_out->ip6_plen = len - sizeof(*ip6_out);
-#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(mout, len);
-#endif
- SCTP_ATTACH_CHAIN(o_pak, mout, len);
- if (port) {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- sh_out->checksum = sctp_calculate_cksum(mout, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
- SCTP_STAT_INCR(sctps_sendswcrc);
-#endif
- if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
- udp->uh_sum = 0xffff;
- }
- } else {
-#if defined(SCTP_WITH_NO_CSUM)
- SCTP_STAT_INCR(sctps_sendnocrc);
-#else
- mout->m_pkthdr.csum_flags = CSUM_SCTP;
- mout->m_pkthdr.csum_data = 0;
- SCTP_STAT_INCR(sctps_sendhwcrc);
-#endif
- }
- SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, NULL, vrf_id);
-
- /* Free the route if we got one back */
- if (ro.ro_rt)
- RTFREE(ro.ro_rt);
- }
-#endif
- SCTP_STAT_INCR(sctps_sendpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
+ sctp_send_resp_msg(src, dst, sh, vtag, SCTP_OPERATION_ERROR, cause,
+ use_mflowid, mflowid,
+ vrf_id, port);
+ return;
}
static struct mbuf *
-sctp_copy_resume(struct sctp_stream_queue_pending *sp,
- struct uio *uio,
- struct sctp_sndrcvinfo *srcv,
+sctp_copy_resume(struct uio *uio,
int max_send_len,
int user_marks_eor,
int *error,
@@ -11993,8 +11933,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
struct sctp_nets *net,
int max_send_len,
int user_marks_eor,
- int *error,
- int non_blocking)
+ int *error)
{
/*-
* This routine must be very careful in its work. Protocol
@@ -12029,7 +11968,6 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
sp->timetolive = srcv->sinfo_timetolive;
sp->ppid = srcv->sinfo_ppid;
sp->context = srcv->sinfo_context;
- sp->strseq = 0;
(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
sp->stream = srcv->sinfo_stream;
@@ -12051,15 +11989,19 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
*error = 0;
goto skip_copy;
}
- sp->auth_keyid = stcb->asoc.authinfo.active_keyid;
+ if (srcv->sinfo_keynumber_valid) {
+ sp->auth_keyid = srcv->sinfo_keynumber;
+ } else {
+ sp->auth_keyid = stcb->asoc.authinfo.active_keyid;
+ }
if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
- sctp_auth_key_acquire(stcb, stcb->asoc.authinfo.active_keyid);
+ sctp_auth_key_acquire(stcb, sp->auth_keyid);
sp->holds_key_ref = 1;
}
*error = sctp_copy_one(sp, uio, resv_in_first);
skip_copy:
if (*error) {
- sctp_free_a_strmoq(stcb, sp);
+ sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED);
sp = NULL;
} else {
if (sp->sinfo_flags & SCTP_ADDR_OVER) {
@@ -12085,8 +12027,8 @@ sctp_sosend(struct socket *so,
struct thread *p
)
{
- int error, use_rcvinfo = 0;
- struct sctp_sndrcvinfo srcv;
+ int error, use_sndinfo = 0;
+ struct sctp_sndrcvinfo sndrcvninfo;
struct sockaddr *addr_to_use;
#if defined(INET) && defined(INET6)
@@ -12096,10 +12038,10 @@ sctp_sosend(struct socket *so,
if (control) {
/* process cmsg snd/rcv info (maybe a assoc-id) */
- if (sctp_find_cmsg(SCTP_SNDRCV, (void *)&srcv, control,
- sizeof(srcv))) {
+ if (sctp_find_cmsg(SCTP_SNDRCV, (void *)&sndrcvninfo, control,
+ sizeof(sndrcvninfo))) {
/* got one */
- use_rcvinfo = 1;
+ use_sndinfo = 1;
}
}
addr_to_use = addr;
@@ -12117,7 +12059,7 @@ sctp_sosend(struct socket *so,
error = sctp_lower_sosend(so, addr_to_use, uio, top,
control,
flags,
- use_rcvinfo ? &srcv : NULL
+ use_sndinfo ? &sndrcvninfo : NULL
,p
);
return (error);
@@ -12194,7 +12136,7 @@ sctp_lower_sosend(struct socket *so,
sndlen = SCTP_HEADER_LEN(i_pak);
}
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %d\n",
- addr,
+ (void *)addr,
sndlen);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(inp->sctp_socket->so_qlimit)) {
@@ -12211,7 +12153,7 @@ sctp_lower_sosend(struct socket *so,
union sctp_sockstore *raddr = (union sctp_sockstore *)addr;
switch (raddr->sa.sa_family) {
-#if defined(INET)
+#ifdef INET
case AF_INET:
if (raddr->sin.sin_len != sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
@@ -12221,7 +12163,7 @@ sctp_lower_sosend(struct socket *so,
port = raddr->sin.sin_port;
break;
#endif
-#if defined(INET6)
+#ifdef INET6
case AF_INET6:
if (raddr->sin6.sin6_len != sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
@@ -12270,14 +12212,10 @@ sctp_lower_sosend(struct socket *so,
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb == NULL) {
- SCTP_INP_RUNLOCK(inp);
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
- error = ENOTCONN;
- goto out_unlocked;
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ hold_tcblock = 1;
}
- SCTP_TCB_LOCK(stcb);
- hold_tcblock = 1;
SCTP_INP_RUNLOCK(inp);
} else if (sinfo_assoc_id) {
stcb = sctp_findassociation_ep_asocid(inp, sinfo_assoc_id, 0);
@@ -12322,6 +12260,9 @@ sctp_lower_sosend(struct socket *so,
SCTP_INP_WUNLOCK(inp);
/* With the lock applied look again */
stcb = sctp_findassociation_ep_addr(&t_inp, addr, &net, NULL, NULL);
+ if ((stcb == NULL) && (control != NULL) && (port > 0)) {
+ stcb = sctp_findassociation_cmsgs(&t_inp, port, control, &net, &error);
+ }
if (stcb == NULL) {
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
@@ -12329,6 +12270,9 @@ sctp_lower_sosend(struct socket *so,
} else {
hold_tcblock = 1;
}
+ if (error) {
+ goto out_unlocked;
+ }
if (t_inp != inp) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
error = ENOTCONN;
@@ -12336,21 +12280,12 @@ sctp_lower_sosend(struct socket *so,
}
}
if (stcb == NULL) {
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
- (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
- error = ENOTCONN;
- goto out_unlocked;
- }
if (addr == NULL) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOENT);
error = ENOENT;
goto out_unlocked;
} else {
- /*
- * UDP style, we must go ahead and start the INIT
- * process
- */
+ /* We must go ahead and start the INIT process */
uint32_t vrf_id;
if ((sinfo_flags & SCTP_ABORT) ||
@@ -12377,6 +12312,15 @@ sctp_lower_sosend(struct socket *so,
/* Error is setup for us in the call */
goto out_unlocked;
}
+ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
+ stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
+ /*
+ * Set the connected flag so we can queue
+ * data
+ */
+ soisconnecting(so);
+ }
+ hold_tcblock = 1;
if (create_lock_applied) {
SCTP_ASOC_CREATE_UNLOCK(inp);
create_lock_applied = 0;
@@ -12396,85 +12340,13 @@ sctp_lower_sosend(struct socket *so,
sctp_initialize_auth_params(inp, stcb);
if (control) {
- /*
- * see if a init structure exists in cmsg
- * headers
- */
- struct sctp_initmsg initm;
- int i;
-
- if (sctp_find_cmsg(SCTP_INIT, (void *)&initm, control,
- sizeof(initm))) {
- /*
- * we have an INIT override of the
- * default
- */
- if (initm.sinit_max_attempts)
- asoc->max_init_times = initm.sinit_max_attempts;
- if (initm.sinit_num_ostreams)
- asoc->pre_open_streams = initm.sinit_num_ostreams;
- if (initm.sinit_max_instreams)
- asoc->max_inbound_streams = initm.sinit_max_instreams;
- if (initm.sinit_max_init_timeo)
- asoc->initial_init_rto_max = initm.sinit_max_init_timeo;
- if (asoc->streamoutcnt < asoc->pre_open_streams) {
- struct sctp_stream_out *tmp_str;
- int had_lock = 0;
-
- /* Default is NOT correct */
- SCTPDBG(SCTP_DEBUG_OUTPUT1, "Ok, defout:%d pre_open:%d\n",
- asoc->streamoutcnt, asoc->pre_open_streams);
- /*
- * What happens if this
- * fails? we panic ...
- */
-
- if (hold_tcblock) {
- had_lock = 1;
- SCTP_TCB_UNLOCK(stcb);
- }
- SCTP_MALLOC(tmp_str,
- struct sctp_stream_out *,
- (asoc->pre_open_streams *
- sizeof(struct sctp_stream_out)),
- SCTP_M_STRMO);
- if (had_lock) {
- SCTP_TCB_LOCK(stcb);
- }
- if (tmp_str != NULL) {
- SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
- asoc->strmout = tmp_str;
- asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams;
- } else {
- asoc->pre_open_streams = asoc->streamoutcnt;
- }
- for (i = 0; i < asoc->streamoutcnt; i++) {
- /*-
- * inbound side must be set
- * to 0xffff, also NOTE when
- * we get the INIT-ACK back
- * (for INIT sender) we MUST
- * reduce the count
- * (streamoutcnt) but first
- * check if we sent to any
- * of the upper streams that
- * were dropped (if some
- * were). Those that were
- * dropped must be notified
- * to the upper layer as
- * failed to send.
- */
- asoc->strmout[i].next_sequence_sent = 0x0;
- TAILQ_INIT(&asoc->strmout[i].outqueue);
- asoc->strmout[i].stream_no = i;
- asoc->strmout[i].last_msg_incomplete = 0;
- asoc->strmout[i].next_spoke.tqe_next = 0;
- asoc->strmout[i].next_spoke.tqe_prev = 0;
- }
- }
+ if (sctp_process_cmsgs_for_init(stcb, control, &error)) {
+ sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_7);
+ hold_tcblock = 0;
+ stcb = NULL;
+ goto out_unlocked;
}
}
- hold_tcblock = 1;
/* out with the INIT */
queue_only_for_init = 1;
/*-
@@ -12500,7 +12372,11 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
} else {
- net = stcb->asoc.primary_destination;
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
}
atomic_add_int(&stcb->total_sends, 1);
/* Keep the stcb from being freed under our feet */
@@ -12514,9 +12390,9 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
}
- if ((SCTP_SO_IS_NBIO(so)
+ if (SCTP_SO_IS_NBIO(so)
|| (flags & MSG_NBIO)
- )) {
+ ) {
non_blocking = 1;
}
/* would we block? */
@@ -12607,15 +12483,12 @@ sctp_lower_sosend(struct socket *so,
if (top) {
struct mbuf *cntm = NULL;
- mm = sctp_get_mbuf_for_msg(1, 0, M_WAIT, 1, MT_DATA);
+ mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_WAIT, 1, MT_DATA);
if (sndlen != 0) {
- cntm = top;
- while (cntm) {
+ for (cntm = top; cntm; cntm = SCTP_BUF_NEXT(cntm)) {
tot_out += SCTP_BUF_LEN(cntm);
- cntm = SCTP_BUF_NEXT(cntm);
}
}
- tot_demand = (tot_out + sizeof(struct sctp_paramhdr));
} else {
/* Must fit in a MTU */
tot_out = sndlen;
@@ -12644,7 +12517,7 @@ sctp_lower_sosend(struct socket *so,
/* now move forward the data pointer */
ph = mtod(mm, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
- ph->param_length = htons((sizeof(struct sctp_paramhdr) + tot_out));
+ ph->param_length = htons(sizeof(struct sctp_paramhdr) + tot_out);
ph++;
SCTP_BUF_LEN(mm) = tot_out + sizeof(struct sctp_paramhdr);
if (top == NULL) {
@@ -12666,14 +12539,11 @@ sctp_lower_sosend(struct socket *so,
}
if (hold_tcblock == 0) {
SCTP_TCB_LOCK(stcb);
- hold_tcblock = 1;
}
atomic_add_int(&stcb->asoc.refcnt, -1);
free_cnt_applied = 0;
/* release this lock, otherwise we hang on ourselves */
- sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_RESPONSE_TO_USER_REQ,
- mm, SCTP_SO_LOCKED);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, mm, SCTP_SO_LOCKED);
/* now relock the stcb so everything is sane */
hold_tcblock = 0;
stcb = NULL;
@@ -12763,7 +12633,7 @@ sctp_lower_sosend(struct socket *so,
stcb->asoc.chunks_on_out_queue,
SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue));
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
- sctp_log_block(SCTP_BLOCK_LOG_INTO_BLKA, so, asoc, sndlen);
+ sctp_log_block(SCTP_BLOCK_LOG_INTO_BLKA, asoc, sndlen);
}
be.error = 0;
stcb->block_entry = &be;
@@ -12782,7 +12652,7 @@ sctp_lower_sosend(struct socket *so,
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_OUTOF_BLK,
- so, asoc, stcb->asoc.total_output_queue_size);
+ asoc, stcb->asoc.total_output_queue_size);
}
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
goto out_unlocked;
@@ -12832,7 +12702,7 @@ skip_preblock:
strm = &stcb->asoc.strmout[srcv->sinfo_stream];
if (strm->last_msg_incomplete == 0) {
do_a_copy_in:
- sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error, non_blocking);
+ sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error);
if ((sp == NULL) || (error)) {
goto out;
}
@@ -12852,23 +12722,11 @@ skip_preblock:
}
sctp_snd_sb_alloc(stcb, sp->length);
atomic_add_int(&asoc->stream_queue_cnt, 1);
- if ((srcv->sinfo_flags & SCTP_UNORDERED) == 0) {
- sp->strseq = strm->next_sequence_sent;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_AT_SEND_2_SCTP) {
- sctp_misc_ints(SCTP_STRMOUT_LOG_ASSIGN,
- (uintptr_t) stcb, sp->length,
- (uint32_t) ((srcv->sinfo_stream << 16) | sp->strseq), 0);
- }
- strm->next_sequence_sent++;
- } else {
+ if (srcv->sinfo_flags & SCTP_UNORDERED) {
SCTP_STAT_INCR(sctps_sends_with_unord);
}
TAILQ_INSERT_TAIL(&strm->outqueue, sp, next);
- if ((strm->next_spoke.tqe_next == NULL) &&
- (strm->next_spoke.tqe_prev == NULL)) {
- /* Not on wheel, insert */
- sctp_insert_on_wheel(stcb, asoc, strm, 1);
- }
+ stcb->asoc.ss_functions.sctp_ss_add_to_stream(stcb, asoc, strm, sp, 1);
SCTP_TCB_SEND_UNLOCK(stcb);
} else {
SCTP_TCB_SEND_LOCK(stcb);
@@ -12904,7 +12762,7 @@ skip_preblock:
SCTP_TCB_UNLOCK(stcb);
hold_tcblock = 0;
}
- mm = sctp_copy_resume(sp, uio, srcv, max_len, user_marks_eor, &error, &sndout, &new_tail);
+ mm = sctp_copy_resume(uio, max_len, user_marks_eor, &error, &sndout, &new_tail);
if ((mm == NULL) || error) {
if (mm) {
sctp_m_freem(mm);
@@ -13086,7 +12944,7 @@ skip_preblock:
min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
- so, asoc, uio->uio_resid);
+ asoc, uio->uio_resid);
}
be.error = 0;
stcb->block_entry = &be;
@@ -13106,7 +12964,7 @@ skip_preblock:
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_OUTOF_BLK,
- so, asoc, stcb->asoc.total_output_queue_size);
+ asoc, stcb->asoc.total_output_queue_size);
}
}
SOCKBUF_UNLOCK(&so->so_snd);
@@ -13154,8 +13012,7 @@ skip_preblock:
dataless_eof:
/* EOF thing ? */
if ((srcv->sinfo_flags & SCTP_EOF) &&
- (got_all_of_the_send == 1) &&
- (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
+ (got_all_of_the_send == 1)) {
int cnt;
SCTP_STAT_INCR(sctps_sends_with_eof);
@@ -13164,7 +13021,7 @@ dataless_eof:
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
- cnt = sctp_is_there_unsent_data(stcb);
+ cnt = sctp_is_there_unsent_data(stcb, SCTP_SO_LOCKED);
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(cnt == 0)) {
@@ -13175,15 +13032,23 @@ dataless_eof:
if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ struct sctp_nets *netp;
+
/* only send SHUTDOWN the first time through */
- sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(stcb);
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
asoc->primary_destination);
}
@@ -13225,7 +13090,6 @@ dataless_eof:
free_cnt_applied = 0;
}
sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_RESPONSE_TO_USER_REQ,
NULL, SCTP_SO_LOCKED);
/*
* now relock the stcb so everything
@@ -13301,8 +13165,6 @@ skip_out_eof:
stcb->asoc.total_flight,
stcb->asoc.chunks_on_out_queue, stcb->asoc.total_flight_count);
}
- if (queue_only_for_init)
- queue_only_for_init = 0;
if ((queue_only == 0) && (nagle_applies == 0) && (stcb->asoc.peers_rwnd && un_sent)) {
/* we can attempt to send too. */
if (hold_tcblock == 0) {
@@ -13348,11 +13210,9 @@ out_unlocked:
if (local_soresv && stcb) {
atomic_subtract_int(&stcb->asoc.sb_send_resv, sndlen);
- local_soresv = 0;
}
if (create_lock_applied) {
SCTP_ASOC_CREATE_UNLOCK(inp);
- create_lock_applied = 0;
}
if ((stcb) && hold_tcblock) {
SCTP_TCB_UNLOCK(stcb);
@@ -13374,7 +13234,7 @@ out_unlocked:
if (inp) {
sctp_validate_no_locks(inp);
} else {
- printf("Warning - inp is NULL so cant validate locks\n");
+ SCTP_PRINTF("Warning - inp is NULL so cant validate locks\n");
}
#endif
if (top) {
@@ -13398,6 +13258,7 @@ sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end,
struct mbuf *m_auth;
struct sctp_auth_chunk *auth;
int chunk_len;
+ struct mbuf *cn;
if ((m_end == NULL) || (auth_ret == NULL) || (offset == NULL) ||
(stcb == NULL))
@@ -13435,17 +13296,10 @@ sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end,
/* key id and hmac digest will be computed and filled in upon send */
/* save the offset where the auth was inserted into the chain */
- if (m != NULL) {
- struct mbuf *cn;
-
- *offset = 0;
- cn = m;
- while (cn) {
- *offset += SCTP_BUF_LEN(cn);
- cn = SCTP_BUF_NEXT(cn);
- }
- } else
- *offset = 0;
+ *offset = 0;
+ for (cn = m; cn; cn = SCTP_BUF_NEXT(cn)) {
+ *offset += SCTP_BUF_LEN(cn);
+ }
/* update length and return pointer to the auth chunk */
SCTP_BUF_LEN(m_auth) = chunk_len;
@@ -13485,8 +13339,7 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro)
SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)src6);
/* search installed gateway from prefix entry */
- for (pfxrtr = pfx->ndpr_advrtrs.lh_first; pfxrtr; pfxrtr =
- pfxrtr->pfr_next) {
+ LIST_FOREACH(pfxrtr, &pfx->ndpr_advrtrs, pfr_entry) {
memset(&gw6, 0, sizeof(struct sockaddr_in6));
gw6.sin6_family = AF_INET6;
gw6.sin6_len = sizeof(struct sockaddr_in6);
@@ -13511,6 +13364,7 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro)
int
sctp_v4src_match_nexthop(struct sctp_ifa *sifa, sctp_route_t * ro)
{
+#ifdef INET
struct sockaddr_in *sin, *mask;
struct ifaddr *ifa;
struct in_addr srcnetaddr, gwnetaddr;
@@ -13535,5 +13389,6 @@ sctp_v4src_match_nexthop(struct sctp_ifa *sifa, sctp_route_t * ro)
if (srcnetaddr.s_addr == gwnetaddr.s_addr) {
return (1);
}
+#endif
return (0);
}
diff --git a/freebsd/sys/netinet/sctp_output.h b/freebsd/sys/netinet/sctp_output.h
index d655c3aa..59af5af2 100644
--- a/freebsd/sys/netinet/sctp_output.h
+++ b/freebsd/sys/netinet/sctp_output.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,13 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_output.h,v 1.14 2005/03/06 16:04:18 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_output_h__
-#define __sctp_output_h__
+#ifndef _NETINET_SCTP_OUTPUT_H_
+#define _NETINET_SCTP_OUTPUT_H_
#include <netinet/sctp_header.h>
@@ -43,9 +43,11 @@ __FBSDID("$FreeBSD$");
struct mbuf *
sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp,
+ struct sctp_tcb *stcb,
struct sctp_scoping *scope,
struct mbuf *m_at,
- int cnt_inits_to);
+ int cnt_inits_to,
+ uint16_t * padding_len, uint16_t * chunk_len);
int sctp_is_addr_restricted(struct sctp_tcb *, struct sctp_ifa *);
@@ -53,13 +55,9 @@ int sctp_is_addr_restricted(struct sctp_tcb *, struct sctp_ifa *);
int
sctp_is_address_in_scope(struct sctp_ifa *ifa,
- int ipv4_addr_legal,
- int ipv6_addr_legal,
- int loopback_scope,
- int ipv4_local_scope,
- int local_scope,
- int site_scope,
+ struct sctp_scoping *scope,
int do_update);
+
int
sctp_is_addr_in_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa);
@@ -82,8 +80,11 @@ sctp_send_initiate(struct sctp_inpcb *, struct sctp_tcb *, int
);
void
-sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *,
- struct mbuf *, int, int, struct sctphdr *, struct sctp_init_chunk *,
+sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *, struct mbuf *,
+ int, int,
+ struct sockaddr *, struct sockaddr *,
+ struct sctphdr *, struct sctp_init_chunk *,
+ uint8_t, uint32_t,
uint32_t, uint16_t, int);
struct mbuf *
@@ -114,7 +115,9 @@ void sctp_send_shutdown_ack(struct sctp_tcb *, struct sctp_nets *);
void sctp_send_shutdown_complete(struct sctp_tcb *, struct sctp_nets *, int);
void
-sctp_send_shutdown_complete2(struct mbuf *, int, struct sctphdr *,
+sctp_send_shutdown_complete2(struct sockaddr *, struct sockaddr *,
+ struct sctphdr *,
+ uint8_t, uint32_t,
uint32_t, uint16_t);
void sctp_send_asconf(struct sctp_tcb *, struct sctp_nets *, int addr_locked);
@@ -135,11 +138,6 @@ int
sctp_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct thread *, int);
-void
-sctp_insert_on_wheel(struct sctp_tcb *stcb,
- struct sctp_association *asoc,
- struct sctp_stream_out *strq, int holdslock);
-
void
sctp_chunk_output(struct sctp_inpcb *, struct sctp_tcb *, int, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
@@ -155,66 +153,52 @@ sctp_send_abort_tcb(struct sctp_tcb *, struct mbuf *, int
void send_forward_tsn(struct sctp_tcb *, struct sctp_association *);
-void sctp_send_sack(struct sctp_tcb *);
+void sctp_send_sack(struct sctp_tcb *, int);
-int sctp_send_hb(struct sctp_tcb *, int, struct sctp_nets *);
+void sctp_send_hb(struct sctp_tcb *, struct sctp_nets *, int);
void sctp_send_ecn_echo(struct sctp_tcb *, struct sctp_nets *, uint32_t);
void
sctp_send_packet_dropped(struct sctp_tcb *, struct sctp_nets *, struct mbuf *,
- int, int);
-
+ int, int, int);
-void sctp_send_cwr(struct sctp_tcb *, struct sctp_nets *, uint32_t);
+void sctp_send_cwr(struct sctp_tcb *, struct sctp_nets *, uint32_t, uint8_t);
-void
-sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk,
- int number_entries, uint16_t * list,
- uint32_t seq, uint32_t resp_seq, uint32_t last_sent);
-
-void
-sctp_add_stream_reset_in(struct sctp_tmit_chunk *chk,
- int number_entries, uint16_t * list,
- uint32_t seq);
void
-sctp_add_stream_reset_tsn(struct sctp_tmit_chunk *chk,
- uint32_t seq);
+sctp_add_stream_reset_out(struct sctp_tmit_chunk *,
+ int, uint16_t *, uint32_t, uint32_t, uint32_t);
void
-sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk,
- uint32_t resp_seq, uint32_t result);
+ sctp_add_stream_reset_result(struct sctp_tmit_chunk *, uint32_t, uint32_t);
void
-sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk,
- uint32_t resp_seq, uint32_t result,
- uint32_t send_una, uint32_t recv_next);
+sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *,
+ uint32_t, uint32_t, uint32_t, uint32_t);
int
-sctp_send_str_reset_req(struct sctp_tcb *stcb,
- int number_entries,
- uint16_t * list,
- uint8_t send_out_req,
- uint32_t resp_seq,
- uint8_t send_in_req,
- uint8_t send_tsn_req,
- uint8_t add_str,
- uint16_t adding);
-
+sctp_send_str_reset_req(struct sctp_tcb *, int, uint16_t *, uint8_t, uint8_t,
+ uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
void
-sctp_send_abort(struct mbuf *, int, struct sctphdr *, uint32_t,
- struct mbuf *, uint32_t, uint16_t);
+sctp_send_abort(struct mbuf *, int, struct sockaddr *, struct sockaddr *,
+ struct sctphdr *, uint32_t, struct mbuf *,
+ uint8_t, uint32_t,
+ uint32_t, uint16_t);
-void sctp_send_operr_to(struct mbuf *, int, struct mbuf *, uint32_t, uint32_t, uint16_t);
+void
+sctp_send_operr_to(struct sockaddr *, struct sockaddr *,
+ struct sctphdr *, uint32_t, struct mbuf *,
+ uint8_t, uint32_t,
+ uint32_t, uint16_t);
#endif /* _KERNEL || __Userspace__ */
-#if defined(_KERNEL) || defined (__Userspace__)
+#if defined(_KERNEL) || defined(__Userspace__)
int
sctp_sosend(struct socket *so,
struct sockaddr *addr,
diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c
index 98c5b707..8a0cdb42 100644
--- a/freebsd/sys/netinet/sctp_pcb.c
+++ b/freebsd/sys/netinet/sctp_pcb.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,8 +32,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_pcb.c,v 1.38 2005/03/06 16:04:18 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -47,7 +47,14 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_output.h>
#include <netinet/sctp_timer.h>
#include <netinet/sctp_bsd_addr.h>
+#include <netinet/sctp_dtrace_define.h>
#include <netinet/udp.h>
+#ifdef INET6
+#include <netinet6/ip6_var.h>
+#endif
+#include <sys/sched.h>
+#include <sys/smp.h>
+#include <rtems/bsd/sys/unistd.h>
VNET_DEFINE(struct sctp_base_info, system_base_info);
@@ -62,11 +69,11 @@ SCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b)
memcpy(&tmp_a, a, sizeof(struct sockaddr_in6));
if (sa6_embedscope(&tmp_a, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
- return 0;
+ return (0);
}
memcpy(&tmp_b, b, sizeof(struct sockaddr_in6));
if (sa6_embedscope(&tmp_b, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
- return 0;
+ return (0);
}
return (IN6_ARE_ADDR_EQUAL(&tmp_a.sin6_addr, &tmp_b.sin6_addr));
}
@@ -89,11 +96,10 @@ sctp_fill_pcbinfo(struct sctp_pcbinfo *spcb)
spcb->readq_count = SCTP_BASE_INFO(ipi_count_readq);
spcb->stream_oque = SCTP_BASE_INFO(ipi_count_strmoq);
spcb->free_chunks = SCTP_BASE_INFO(ipi_free_chunks);
-
SCTP_INP_INFO_RUNLOCK();
}
-/*
+/*-
* Addresses are added to VRF's (Virtual Router's). For BSD we
* have only the default VRF 0. We maintain a hash list of
* VRF's. Each VRF has its own list of sctp_ifn's. Each of
@@ -209,7 +215,6 @@ sctp_find_ifn(void *ifn, uint32_t ifn_index)
}
-
struct sctp_vrf *
sctp_find_vrf(uint32_t vrf_id)
{
@@ -225,6 +230,7 @@ sctp_find_vrf(uint32_t vrf_id)
return (NULL);
}
+
void
sctp_free_vrf(struct sctp_vrf *vrf)
{
@@ -240,6 +246,7 @@ sctp_free_vrf(struct sctp_vrf *vrf)
}
}
+
void
sctp_free_ifn(struct sctp_ifn *sctp_ifnp)
{
@@ -253,6 +260,7 @@ sctp_free_ifn(struct sctp_ifn *sctp_ifnp)
}
}
+
void
sctp_update_ifn_mtu(uint32_t ifn_index, uint32_t mtu)
{
@@ -278,6 +286,7 @@ sctp_free_ifa(struct sctp_ifa *sctp_ifap)
}
}
+
static void
sctp_delete_ifn(struct sctp_ifn *sctp_ifnp, int hold_addr_lock)
{
@@ -300,12 +309,13 @@ sctp_delete_ifn(struct sctp_ifn *sctp_ifnp, int hold_addr_lock)
sctp_free_ifn(sctp_ifnp);
}
+
void
sctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr,
const char *if_name, uint32_t ifn_index)
{
struct sctp_vrf *vrf;
- struct sctp_ifa *sctp_ifap = NULL;
+ struct sctp_ifa *sctp_ifap;
SCTP_IPI_ADDR_RLOCK();
vrf = sctp_find_vrf(vrf_id);
@@ -324,19 +334,9 @@ sctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr,
goto out;
}
if (if_name) {
- int len1, len2;
-
- len1 = strlen(if_name);
- len2 = strlen(sctp_ifap->ifn_p->ifn_name);
- if (len1 != len2) {
- SCTPDBG(SCTP_DEBUG_PCB4, "IFN of ifa names different length %d vs %d - ignored\n",
- len1, len2);
- goto out;
- }
- if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, len1) != 0) {
+ if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) != 0) {
SCTPDBG(SCTP_DEBUG_PCB4, "IFN %s of IFA not the same as %s\n",
- sctp_ifap->ifn_p->ifn_name,
- if_name);
+ sctp_ifap->ifn_p->ifn_name, if_name);
goto out;
}
} else {
@@ -353,12 +353,13 @@ out:
SCTP_IPI_ADDR_RUNLOCK();
}
+
void
sctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr,
const char *if_name, uint32_t ifn_index)
{
struct sctp_vrf *vrf;
- struct sctp_ifa *sctp_ifap = NULL;
+ struct sctp_ifa *sctp_ifap;
SCTP_IPI_ADDR_RLOCK();
vrf = sctp_find_vrf(vrf_id);
@@ -377,19 +378,9 @@ sctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr,
goto out;
}
if (if_name) {
- int len1, len2;
-
- len1 = strlen(if_name);
- len2 = strlen(sctp_ifap->ifn_p->ifn_name);
- if (len1 != len2) {
- SCTPDBG(SCTP_DEBUG_PCB4, "IFN of ifa names different length %d vs %d - ignored\n",
- len1, len2);
- goto out;
- }
- if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, len1) != 0) {
+ if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) != 0) {
SCTPDBG(SCTP_DEBUG_PCB4, "IFN %s of IFA not the same as %s\n",
- sctp_ifap->ifn_p->ifn_name,
- if_name);
+ sctp_ifap->ifn_p->ifn_name, if_name);
goto out;
}
} else {
@@ -406,6 +397,7 @@ out:
SCTP_IPI_ADDR_RUNLOCK();
}
+
/*-
* Add an ifa to an ifn.
* Register the interface as necessary.
@@ -422,10 +414,20 @@ sctp_add_ifa_to_ifn(struct sctp_ifn *sctp_ifnp, struct sctp_ifa *sctp_ifap)
/* update address counts */
sctp_ifnp->ifa_count++;
ifa_af = sctp_ifap->address.sa.sa_family;
- if (ifa_af == AF_INET)
+ switch (ifa_af) {
+#ifdef INET
+ case AF_INET:
sctp_ifnp->num_v4++;
- else
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
sctp_ifnp->num_v6++;
+ break;
+#endif
+ default:
+ break;
+ }
if (sctp_ifnp->ifa_count == 1) {
/* register the new interface */
SCTP_REGISTER_INTERFACE(sctp_ifnp->ifn_index, ifa_af);
@@ -433,6 +435,7 @@ sctp_add_ifa_to_ifn(struct sctp_ifn *sctp_ifnp, struct sctp_ifa *sctp_ifap)
}
}
+
/*-
* Remove an ifa from its ifn.
* If no more addresses exist, remove the ifn too. Otherwise, re-register
@@ -442,18 +445,25 @@ sctp_add_ifa_to_ifn(struct sctp_ifn *sctp_ifnp, struct sctp_ifa *sctp_ifap)
static void
sctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap)
{
- uint32_t ifn_index;
-
LIST_REMOVE(sctp_ifap, next_ifa);
if (sctp_ifap->ifn_p) {
/* update address counts */
sctp_ifap->ifn_p->ifa_count--;
- if (sctp_ifap->address.sa.sa_family == AF_INET6)
- sctp_ifap->ifn_p->num_v6--;
- else if (sctp_ifap->address.sa.sa_family == AF_INET)
+ switch (sctp_ifap->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
sctp_ifap->ifn_p->num_v4--;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ sctp_ifap->ifn_p->num_v6--;
+ break;
+#endif
+ default:
+ break;
+ }
- ifn_index = sctp_ifap->ifn_p->ifn_index;
if (LIST_EMPTY(&sctp_ifap->ifn_p->ifalist)) {
/* remove the ifn, possibly freeing it */
sctp_delete_ifn(sctp_ifap->ifn_p, SCTP_ADDR_LOCKED);
@@ -461,13 +471,13 @@ sctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap)
/* re-register address family type, if needed */
if ((sctp_ifap->ifn_p->num_v6 == 0) &&
(sctp_ifap->ifn_p->registered_af == AF_INET6)) {
- SCTP_DEREGISTER_INTERFACE(ifn_index, AF_INET6);
- SCTP_REGISTER_INTERFACE(ifn_index, AF_INET);
+ SCTP_DEREGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET6);
+ SCTP_REGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET);
sctp_ifap->ifn_p->registered_af = AF_INET;
} else if ((sctp_ifap->ifn_p->num_v4 == 0) &&
(sctp_ifap->ifn_p->registered_af == AF_INET)) {
- SCTP_DEREGISTER_INTERFACE(ifn_index, AF_INET);
- SCTP_REGISTER_INTERFACE(ifn_index, AF_INET6);
+ SCTP_DEREGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET);
+ SCTP_REGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET6);
sctp_ifap->ifn_p->registered_af = AF_INET6;
}
/* free the ifn refcount */
@@ -477,6 +487,7 @@ sctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap)
}
}
+
struct sctp_ifa *
sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
uint32_t ifn_type, const char *if_name, void *ifa,
@@ -532,9 +543,9 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
atomic_add_int(&vrf->refcount, 1);
sctp_ifnp->ifn_mtu = SCTP_GATHER_MTU_FROM_IFN_INFO(ifn, ifn_index, addr->sa_family);
if (if_name != NULL) {
- memcpy(sctp_ifnp->ifn_name, if_name, SCTP_IFNAMSIZ);
+ snprintf(sctp_ifnp->ifn_name, SCTP_IFNAMSIZ, "%s", if_name);
} else {
- memcpy(sctp_ifnp->ifn_name, "unknown", min(7, SCTP_IFNAMSIZ));
+ snprintf(sctp_ifnp->ifn_name, SCTP_IFNAMSIZ, "%s", "unknown");
}
hash_ifn_head = &SCTP_BASE_INFO(vrf_ifn_hash)[(ifn_index & SCTP_BASE_INFO(vrf_ifn_hashmark))];
LIST_INIT(&sctp_ifnp->ifalist);
@@ -551,7 +562,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
(sctp_ifap->ifn_p->ifn_index == ifn_index)) {
SCTPDBG(SCTP_DEBUG_PCB4, "Using existing ifn %s (0x%x) for ifa %p\n",
sctp_ifap->ifn_p->ifn_name, ifn_index,
- sctp_ifap);
+ (void *)sctp_ifap);
if (new_ifn_af) {
/* Remove the created one that we don't want */
sctp_delete_ifn(sctp_ifnp, SCTP_ADDR_LOCKED);
@@ -573,7 +584,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
* old one
*/
SCTPDBG(SCTP_DEBUG_PCB4, "Moving ifa %p from %s (0x%x) to %s (0x%x)\n",
- sctp_ifap, sctp_ifap->ifn_p->ifn_name,
+ (void *)sctp_ifap, sctp_ifap->ifn_p->ifn_name,
sctp_ifap->ifn_p->ifn_index, if_name,
ifn_index);
/* remove the address from the old ifn */
@@ -585,7 +596,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
/* repair ifnp which was NULL ? */
sctp_ifap->localifa_flags = SCTP_ADDR_VALID;
SCTPDBG(SCTP_DEBUG_PCB4, "Repairing ifn %p for ifa %p\n",
- sctp_ifnp, sctp_ifap);
+ (void *)sctp_ifnp, (void *)sctp_ifap);
sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap);
}
goto exit_stage_left;
@@ -609,6 +620,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
sctp_ifap->flags = ifa_flags;
/* Set scope */
switch (sctp_ifap->address.sa.sa_family) {
+#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin;
@@ -626,6 +638,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
new_ifn_af = AF_INET;
break;
}
+#endif
#ifdef INET6
case AF_INET6:
{
@@ -739,19 +752,9 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
* panda who might recycle indexes fast.
*/
if (if_name) {
- int len1, len2;
-
- len1 = min(SCTP_IFNAMSIZ, strlen(if_name));
- len2 = min(SCTP_IFNAMSIZ, strlen(sctp_ifap->ifn_p->ifn_name));
- if (len1 && len2 && (len1 == len2)) {
- /* we can compare them */
- if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, len1) == 0) {
- /*
- * They match its a correct
- * delete
- */
- valid = 1;
- }
+ if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) == 0) {
+ /* They match its a correct delete */
+ valid = 1;
}
}
if (!valid) {
@@ -769,7 +772,7 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
return;
}
}
- SCTPDBG(SCTP_DEBUG_PCB4, "Deleting ifa %p\n", sctp_ifap);
+ SCTPDBG(SCTP_DEBUG_PCB4, "Deleting ifa %p\n", (void *)sctp_ifap);
sctp_ifap->localifa_flags &= SCTP_ADDR_VALID;
sctp_ifap->localifa_flags |= SCTP_BEING_DELETED;
vrf->total_ifa_count--;
@@ -823,6 +826,160 @@ out_now:
}
+static int
+sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
+{
+ int loopback_scope, ipv4_local_scope, local_scope, site_scope;
+ int ipv4_addr_legal, ipv6_addr_legal;
+ struct sctp_vrf *vrf;
+ struct sctp_ifn *sctp_ifn;
+ struct sctp_ifa *sctp_ifa;
+
+ loopback_scope = stcb->asoc.scope.loopback_scope;
+ ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
+ local_scope = stcb->asoc.scope.local_scope;
+ site_scope = stcb->asoc.scope.site_scope;
+ ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
+ ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
+
+ SCTP_IPI_ADDR_RLOCK();
+ vrf = sctp_find_vrf(stcb->asoc.vrf_id);
+ if (vrf == NULL) {
+ /* no vrf, no addresses */
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (0);
+ }
+ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
+ LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
+ if ((loopback_scope == 0) &&
+ SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
+ continue;
+ }
+ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
+ if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
+ (!sctp_is_addr_pending(stcb, sctp_ifa))) {
+ /*
+ * We allow pending addresses, where
+ * we have sent an asconf-add to be
+ * considered valid.
+ */
+ continue;
+ }
+ switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (ipv4_addr_legal) {
+ struct sockaddr_in *sin,
+ *rsin;
+
+ sin = &sctp_ifa->address.sin;
+ rsin = (struct sockaddr_in *)to;
+ if ((ipv4_local_scope == 0) &&
+ IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
+ continue;
+ }
+ if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (1);
+ }
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (ipv6_addr_legal) {
+ struct sockaddr_in6 *sin6,
+ *rsin6;
+
+ sin6 = &sctp_ifa->address.sin6;
+ rsin6 = (struct sockaddr_in6 *)to;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ if (local_scope == 0)
+ continue;
+ if (sin6->sin6_scope_id == 0) {
+ if (sa6_recoverscope(sin6) != 0)
+ continue;
+ }
+ }
+ if ((site_scope == 0) &&
+ (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
+ continue;
+ }
+ if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (1);
+ }
+ }
+ break;
+#endif
+ default:
+ /* TSNH */
+ break;
+ }
+ }
+ }
+ } else {
+ struct sctp_laddr *laddr;
+
+ LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
+ if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
+ SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n");
+ continue;
+ }
+ if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
+ (!sctp_is_addr_pending(stcb, laddr->ifa))) {
+ /*
+ * We allow pending addresses, where we have
+ * sent an asconf-add to be considered
+ * valid.
+ */
+ continue;
+ }
+ if (laddr->ifa->address.sa.sa_family != to->sa_family) {
+ continue;
+ }
+ switch (to->sa_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin, *rsin;
+
+ sin = (struct sockaddr_in *)&laddr->ifa->address.sin;
+ rsin = (struct sockaddr_in *)to;
+ if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (1);
+ }
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6, *rsin6;
+
+ sin6 = (struct sockaddr_in6 *)&laddr->ifa->address.sin6;
+ rsin6 = (struct sockaddr_in6 *)to;
+ if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (1);
+ }
+ break;
+ }
+
+#endif
+ default:
+ /* TSNH */
+ break;
+ }
+
+ }
+ }
+ SCTP_IPI_ADDR_RUNLOCK();
+ return (0);
+}
+
+
static struct sctp_tcb *
sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
struct sockaddr *to, struct sctp_nets **netp, uint32_t vrf_id)
@@ -842,14 +999,29 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
if ((to == NULL) || (from == NULL)) {
return (NULL);
}
- if (to->sa_family == AF_INET && from->sa_family == AF_INET) {
- lport = ((struct sockaddr_in *)to)->sin_port;
- rport = ((struct sockaddr_in *)from)->sin_port;
- } else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) {
- lport = ((struct sockaddr_in6 *)to)->sin6_port;
- rport = ((struct sockaddr_in6 *)from)->sin6_port;
- } else {
- return NULL;
+ switch (to->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (from->sa_family == AF_INET) {
+ lport = ((struct sockaddr_in *)to)->sin_port;
+ rport = ((struct sockaddr_in *)from)->sin_port;
+ } else {
+ return (NULL);
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (from->sa_family == AF_INET6) {
+ lport = ((struct sockaddr_in6 *)to)->sin6_port;
+ rport = ((struct sockaddr_in6 *)from)->sin6_port;
+ } else {
+ return (NULL);
+ }
+ break;
+#endif
+ default:
+ return (NULL);
}
ephead = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))];
/*
@@ -890,17 +1062,20 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
if (laddr->ifa->address.sa.sa_family ==
to->sa_family) {
/* see if it matches */
- struct sockaddr_in *intf_addr, *sin;
-
- intf_addr = &laddr->ifa->address.sin;
- sin = (struct sockaddr_in *)to;
+#ifdef INET
if (from->sa_family == AF_INET) {
+ struct sockaddr_in *intf_addr,
+ *sin;
+
+ intf_addr = &laddr->ifa->address.sin;
+ sin = (struct sockaddr_in *)to;
if (sin->sin_addr.s_addr ==
intf_addr->sin_addr.s_addr) {
match = 1;
break;
}
}
+#endif
#ifdef INET6
if (from->sa_family == AF_INET6) {
struct sockaddr_in6 *intf_addr6;
@@ -929,13 +1104,18 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
* Ok if we hit here the ep has the address, does it hold
* the tcb?
*/
-
+ /* XXX: Why don't we TAILQ_FOREACH through sctp_asoc_list? */
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
SCTP_INP_RUNLOCK(inp);
continue;
}
SCTP_TCB_LOCK(stcb);
+ if (!sctp_does_stcb_own_this_addr(stcb, to)) {
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ continue;
+ }
if (stcb->rport != rport) {
/* remote port does not match. */
SCTP_TCB_UNLOCK(stcb);
@@ -947,6 +1127,11 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
SCTP_INP_RUNLOCK(inp);
continue;
}
+ if (!sctp_does_stcb_own_this_addr(stcb, to)) {
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ continue;
+ }
/* Does this TCB have a matching address? */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -955,6 +1140,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
continue;
}
switch (from->sa_family) {
+#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin, *rsin;
@@ -977,6 +1163,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
}
break;
}
+#endif
#ifdef INET6
case AF_INET6:
{
@@ -1012,148 +1199,6 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
return (NULL);
}
-static int
-sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
-{
- int loopback_scope, ipv4_local_scope, local_scope, site_scope;
- int ipv4_addr_legal, ipv6_addr_legal;
- struct sctp_vrf *vrf;
- struct sctp_ifn *sctp_ifn;
- struct sctp_ifa *sctp_ifa;
-
- loopback_scope = stcb->asoc.loopback_scope;
- ipv4_local_scope = stcb->asoc.ipv4_local_scope;
- local_scope = stcb->asoc.local_scope;
- site_scope = stcb->asoc.site_scope;
- ipv4_addr_legal = ipv6_addr_legal = 0;
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- ipv6_addr_legal = 1;
- if (SCTP_IPV6_V6ONLY(stcb->sctp_ep) == 0) {
- ipv4_addr_legal = 1;
- }
- } else {
- ipv4_addr_legal = 1;
- }
-
- SCTP_IPI_ADDR_RLOCK();
- vrf = sctp_find_vrf(stcb->asoc.vrf_id);
- if (vrf == NULL) {
- /* no vrf, no addresses */
- SCTP_IPI_ADDR_RUNLOCK();
- return (0);
- }
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
- LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
- if ((loopback_scope == 0) &&
- SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
- continue;
- }
- LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
- if (sctp_is_addr_restricted(stcb, sctp_ifa))
- continue;
- switch (sctp_ifa->address.sa.sa_family) {
-#ifdef INET
- case AF_INET:
- if (ipv4_addr_legal) {
- struct sockaddr_in *sin,
- *rsin;
-
- sin = &sctp_ifa->address.sin;
- rsin = (struct sockaddr_in *)to;
- if ((ipv4_local_scope == 0) &&
- IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
- continue;
- }
- if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
- SCTP_IPI_ADDR_RUNLOCK();
- return (1);
- }
- }
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- if (ipv6_addr_legal) {
- struct sockaddr_in6 *sin6,
- *rsin6;
-
- sin6 = &sctp_ifa->address.sin6;
- rsin6 = (struct sockaddr_in6 *)to;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- if (local_scope == 0)
- continue;
- if (sin6->sin6_scope_id == 0) {
- if (sa6_recoverscope(sin6) != 0)
- continue;
- }
- }
- if ((site_scope == 0) &&
- (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
- continue;
- }
- if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
- SCTP_IPI_ADDR_RUNLOCK();
- return (1);
- }
- }
- break;
-#endif
- default:
- /* TSNH */
- break;
- }
- }
- }
- } else {
- struct sctp_laddr *laddr;
-
- LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
- if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
- continue;
- }
- if (laddr->ifa->address.sa.sa_family != to->sa_family) {
- continue;
- }
- switch (to->sa_family) {
-#ifdef INET
- case AF_INET:
- {
- struct sockaddr_in *sin, *rsin;
-
- sin = (struct sockaddr_in *)&laddr->ifa->address.sin;
- rsin = (struct sockaddr_in *)to;
- if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
- SCTP_IPI_ADDR_RUNLOCK();
- return (1);
- }
- break;
- }
-#endif
-#ifdef INET6
- case AF_INET6:
- {
- struct sockaddr_in6 *sin6, *rsin6;
-
- sin6 = (struct sockaddr_in6 *)&laddr->ifa->address.sin6;
- rsin6 = (struct sockaddr_in6 *)to;
- if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
- SCTP_IPI_ADDR_RUNLOCK();
- return (1);
- }
- break;
- }
-
-#endif
- default:
- /* TSNH */
- break;
- }
-
- }
- }
- SCTP_IPI_ADDR_RUNLOCK();
- return (0);
-}
/*
* rules for use
@@ -1175,11 +1220,18 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
uint16_t rport;
inp = *inp_p;
- if (remote->sa_family == AF_INET) {
+ switch (remote->sa_family) {
+#ifdef INET
+ case AF_INET:
rport = (((struct sockaddr_in *)remote)->sin_port);
- } else if (remote->sa_family == AF_INET6) {
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
rport = (((struct sockaddr_in6 *)remote)->sin6_port);
- } else {
+ break;
+#endif
+ default:
return (NULL);
}
if (locked_tcb) {
@@ -1191,7 +1243,8 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
SCTP_TCB_UNLOCK(locked_tcb);
}
SCTP_INP_INFO_RLOCK();
- if (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
/*-
* Now either this guy is our listener or it's the
* connector. If it is the one that issued the connect, then
@@ -1252,6 +1305,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
continue;
}
switch (remote->sa_family) {
+#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin,
@@ -1280,6 +1334,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
}
break;
}
+#endif
#ifdef INET6
case AF_INET6:
{
@@ -1353,6 +1408,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
continue;
}
switch (remote->sa_family) {
+#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin,
@@ -1381,6 +1437,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
}
break;
}
+#endif
#ifdef INET6
case AF_INET6:
{
@@ -1431,11 +1488,11 @@ null_return:
return (NULL);
}
+
/*
* Find an association for a specific endpoint using the association id given
* out in the COMM_UP notification
*/
-
struct sctp_tcb *
sctp_findasoc_ep_asocid_locked(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int want_lock)
{
@@ -1496,37 +1553,39 @@ sctp_findassociation_ep_asocid(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int
}
+/*
+ * Endpoint probe expects that the INP_INFO is locked.
+ */
static struct sctp_inpcb *
sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
uint16_t lport, uint32_t vrf_id)
{
struct sctp_inpcb *inp;
- struct sockaddr_in *sin;
+ struct sctp_laddr *laddr;
-#ifdef INET6
- struct sockaddr_in6 *sin6;
+#ifdef INET
+ struct sockaddr_in *sin;
#endif
- struct sctp_laddr *laddr;
-
#ifdef INET6
+ struct sockaddr_in6 *sin6;
struct sockaddr_in6 *intf_addr6;
#endif
-
int fnd;
- /*
- * Endpoint probe expects that the INP_INFO is locked.
- */
+#ifdef INET
sin = NULL;
+#endif
#ifdef INET6
sin6 = NULL;
#endif
switch (nam->sa_family) {
+#ifdef INET
case AF_INET:
sin = (struct sockaddr_in *)nam;
break;
+#endif
#ifdef INET6
case AF_INET6:
sin6 = (struct sockaddr_in6 *)nam;
@@ -1549,6 +1608,7 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) &&
(inp->sctp_lport == lport)) {
/* got it */
+#ifdef INET
if ((nam->sa_family == AF_INET) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
SCTP_IPV6_V6ONLY(inp)) {
@@ -1556,12 +1616,15 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
SCTP_INP_RUNLOCK(inp);
continue;
}
+#endif
+#ifdef INET6
/* A V6 address and the endpoint is NOT bound V6 */
if (nam->sa_family == AF_INET6 &&
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
SCTP_INP_RUNLOCK(inp);
continue;
}
+#endif
/* does a VRF id match? */
fnd = 0;
if (inp->def_vrf_id == vrf_id)
@@ -1574,18 +1637,26 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
}
SCTP_INP_RUNLOCK(inp);
}
- if ((nam->sa_family == AF_INET) &&
- (sin->sin_addr.s_addr == INADDR_ANY)) {
- /* Can't hunt for one that has no address specified */
- return (NULL);
- }
+ switch (nam->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ /* Can't hunt for one that has no address specified */
+ return (NULL);
+ }
+ break;
+#endif
#ifdef INET6
- if ((nam->sa_family == AF_INET6) &&
- (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
- /* Can't hunt for one that has no address specified */
- return (NULL);
- }
+ case AF_INET6:
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ /* Can't hunt for one that has no address specified */
+ return (NULL);
+ }
+ break;
#endif
+ default:
+ break;
+ }
/*
* ok, not bound to all so see if we can find a EP bound to this
* address.
@@ -1624,24 +1695,23 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
continue;
}
SCTPDBG(SCTP_DEBUG_PCB1, "Ok laddr->ifa:%p is possible, ",
- laddr->ifa);
+ (void *)laddr->ifa);
if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
SCTPDBG(SCTP_DEBUG_PCB1, "Huh IFA being deleted\n");
continue;
}
if (laddr->ifa->address.sa.sa_family == nam->sa_family) {
/* possible, see if it matches */
- struct sockaddr_in *intf_addr;
-
- intf_addr = &laddr->ifa->address.sin;
switch (nam->sa_family) {
+#ifdef INET
case AF_INET:
if (sin->sin_addr.s_addr ==
- intf_addr->sin_addr.s_addr) {
+ laddr->ifa->address.sin.sin_addr.s_addr) {
SCTP_INP_RUNLOCK(inp);
return (inp);
}
break;
+#endif
#ifdef INET6
case AF_INET6:
intf_addr6 = &laddr->ifa->address.sin6;
@@ -1770,19 +1840,32 @@ sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock,
*/
struct sctp_inpcb *inp;
struct sctppcbhead *head;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
int lport;
unsigned int i;
- if (nam->sa_family == AF_INET) {
+#ifdef INET
+ struct sockaddr_in *sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+
+#endif
+
+ switch (nam->sa_family) {
+#ifdef INET
+ case AF_INET:
sin = (struct sockaddr_in *)nam;
- lport = ((struct sockaddr_in *)nam)->sin_port;
- } else if (nam->sa_family == AF_INET6) {
+ lport = sin->sin_port;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
sin6 = (struct sockaddr_in6 *)nam;
- lport = ((struct sockaddr_in6 *)nam)->sin6_port;
- } else {
- /* unsupported family */
+ lport = sin6->sin6_port;
+ break;
+#endif
+ default:
return (NULL);
}
/*
@@ -1826,31 +1909,32 @@ sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock,
return (inp);
}
+
/*
* Find an association for an endpoint with the pointer to whom you want to
* send to and the endpoint pointer. The address can be IPv4 or IPv6. We may
* need to change the *to to some other struct like a mbuf...
*/
struct sctp_tcb *
-sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from,
+sctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to,
struct sctp_inpcb **inp_p, struct sctp_nets **netp, int find_tcp_pool,
uint32_t vrf_id)
{
struct sctp_inpcb *inp = NULL;
- struct sctp_tcb *retval;
+ struct sctp_tcb *stcb;
SCTP_INP_INFO_RLOCK();
if (find_tcp_pool) {
if (inp_p != NULL) {
- retval = sctp_tcb_special_locate(inp_p, from, to, netp,
+ stcb = sctp_tcb_special_locate(inp_p, from, to, netp,
vrf_id);
} else {
- retval = sctp_tcb_special_locate(&inp, from, to, netp,
+ stcb = sctp_tcb_special_locate(&inp, from, to, netp,
vrf_id);
}
- if (retval != NULL) {
+ if (stcb != NULL) {
SCTP_INP_INFO_RUNLOCK();
- return (retval);
+ return (stcb);
}
}
inp = sctp_pcb_findep(to, 0, 1, vrf_id);
@@ -1858,7 +1942,6 @@ sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from,
*inp_p = inp;
}
SCTP_INP_INFO_RUNLOCK();
-
if (inp == NULL) {
return (NULL);
}
@@ -1869,13 +1952,13 @@ sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from,
* inbound packet side.
*/
if (inp_p != NULL) {
- retval = sctp_findassociation_ep_addr(inp_p, from, netp, to,
+ stcb = sctp_findassociation_ep_addr(inp_p, from, netp, to,
NULL);
} else {
- retval = sctp_findassociation_ep_addr(&inp, from, netp, to,
+ stcb = sctp_findassociation_ep_addr(&inp, from, netp, to,
NULL);
}
- return retval;
+ return (stcb);
}
@@ -1885,26 +1968,37 @@ sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from,
* address will be used to lookup the TCB and see if one exits.
*/
static struct sctp_tcb *
-sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset,
+sctp_findassociation_special_addr(struct mbuf *m, int offset,
struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp,
- struct sockaddr *dest)
+ struct sockaddr *dst)
{
- struct sockaddr_in sin4;
- struct sockaddr_in6 sin6;
struct sctp_paramhdr *phdr, parm_buf;
- struct sctp_tcb *retval;
+ struct sctp_tcb *stcb;
uint32_t ptype, plen;
+#ifdef INET
+ struct sockaddr_in sin4;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+
+#endif
+
+#ifdef INET
memset(&sin4, 0, sizeof(sin4));
- memset(&sin6, 0, sizeof(sin6));
sin4.sin_len = sizeof(sin4);
sin4.sin_family = AF_INET;
sin4.sin_port = sh->src_port;
+#endif
+#ifdef INET6
+ memset(&sin6, 0, sizeof(sin6));
sin6.sin6_len = sizeof(sin6);
sin6.sin6_family = AF_INET6;
sin6.sin6_port = sh->src_port;
+#endif
- retval = NULL;
+ stcb = NULL;
offset += sizeof(struct sctp_init_chunk);
phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
@@ -1915,6 +2009,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset,
if (plen == 0) {
break;
}
+#ifdef INET
if (ptype == SCTP_IPV4_ADDRESS &&
plen == sizeof(struct sctp_ipv4addr_param)) {
/* Get the rest of the address */
@@ -1928,12 +2023,15 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset,
p4 = (struct sctp_ipv4addr_param *)phdr;
memcpy(&sin4.sin_addr, &p4->addr, sizeof(p4->addr));
/* look it up */
- retval = sctp_findassociation_ep_addr(inp_p,
- (struct sockaddr *)&sin4, netp, dest, NULL);
- if (retval != NULL) {
- return (retval);
+ stcb = sctp_findassociation_ep_addr(inp_p,
+ (struct sockaddr *)&sin4, netp, dst, NULL);
+ if (stcb != NULL) {
+ return (stcb);
}
- } else if (ptype == SCTP_IPV6_ADDRESS &&
+ }
+#endif
+#ifdef INET6
+ if (ptype == SCTP_IPV6_ADDRESS &&
plen == sizeof(struct sctp_ipv6addr_param)) {
/* Get the rest of the address */
struct sctp_ipv6addr_param ip6_parm, *p6;
@@ -1946,12 +2044,13 @@ sctp_findassociation_special_addr(struct mbuf *m, int iphlen, int offset,
p6 = (struct sctp_ipv6addr_param *)phdr;
memcpy(&sin6.sin6_addr, &p6->addr, sizeof(p6->addr));
/* look it up */
- retval = sctp_findassociation_ep_addr(inp_p,
- (struct sockaddr *)&sin6, netp, dest, NULL);
- if (retval != NULL) {
- return (retval);
+ stcb = sctp_findassociation_ep_addr(inp_p,
+ (struct sockaddr *)&sin6, netp, dst, NULL);
+ if (stcb != NULL) {
+ return (stcb);
}
}
+#endif
offset += SCTP_SIZE32(plen);
phdr = sctp_get_next_param(m, offset, &parm_buf,
sizeof(parm_buf));
@@ -1973,8 +2072,6 @@ sctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag
struct sctp_nets *net;
struct sctp_tcb *stcb;
- *netp = NULL;
- *inp_p = NULL;
SCTP_INP_INFO_RLOCK();
head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(vtag,
SCTP_BASE_INFO(hashasocmark))];
@@ -1989,6 +2086,10 @@ sctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag
SCTP_INP_RUNLOCK(stcb->sctp_ep);
continue;
}
+ if (stcb->sctp_ep->def_vrf_id != vrf_id) {
+ SCTP_INP_RUNLOCK(stcb->sctp_ep);
+ continue;
+ }
SCTP_TCB_LOCK(stcb);
SCTP_INP_RUNLOCK(stcb->sctp_ep);
if (stcb->asoc.my_vtag == vtag) {
@@ -2028,7 +2129,7 @@ sctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag
if (skip_src_check) {
conclusive:
if (from) {
- net = sctp_findnet(stcb, from);
+ *netp = sctp_findnet(stcb, from);
} else {
*netp = NULL; /* unknown */
}
@@ -2059,110 +2160,27 @@ sctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag
return (NULL);
}
+
/*
* Find an association with the pointer to the inbound IP packet. This can be
* a IPv4 or IPv6 packet.
*/
struct sctp_tcb *
-sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
+sctp_findassociation_addr(struct mbuf *m, int offset,
+ struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_chunkhdr *ch,
struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
{
int find_tcp_pool;
- struct ip *iph;
- struct sctp_tcb *retval;
- struct sockaddr_storage to_store, from_store;
- struct sockaddr *to = (struct sockaddr *)&to_store;
- struct sockaddr *from = (struct sockaddr *)&from_store;
+ struct sctp_tcb *stcb;
struct sctp_inpcb *inp;
- iph = mtod(m, struct ip *);
- switch (iph->ip_v) {
- case IPVERSION:
- {
- /* its IPv4 */
- struct sockaddr_in *from4;
-
- from4 = (struct sockaddr_in *)&from_store;
- bzero(from4, sizeof(*from4));
- from4->sin_family = AF_INET;
- from4->sin_len = sizeof(struct sockaddr_in);
- from4->sin_addr.s_addr = iph->ip_src.s_addr;
- from4->sin_port = sh->src_port;
- break;
- }
-#ifdef INET6
- case IPV6_VERSION >> 4:
- {
- /* its IPv6 */
- struct ip6_hdr *ip6;
- struct sockaddr_in6 *from6;
-
- ip6 = mtod(m, struct ip6_hdr *);
- from6 = (struct sockaddr_in6 *)&from_store;
- bzero(from6, sizeof(*from6));
- from6->sin6_family = AF_INET6;
- from6->sin6_len = sizeof(struct sockaddr_in6);
- from6->sin6_addr = ip6->ip6_src;
- from6->sin6_port = sh->src_port;
- /* Get the scopes in properly to the sin6 addr's */
- /* we probably don't need these operations */
- (void)sa6_recoverscope(from6);
- sa6_embedscope(from6, MODULE_GLOBAL(ip6_use_defzone));
- break;
- }
-#endif
- default:
- /* Currently not supported. */
- return (NULL);
- }
-
-
- switch (iph->ip_v) {
- case IPVERSION:
- {
- /* its IPv4 */
- struct sockaddr_in *to4;
-
- to4 = (struct sockaddr_in *)&to_store;
- bzero(to4, sizeof(*to4));
- to4->sin_family = AF_INET;
- to4->sin_len = sizeof(struct sockaddr_in);
- to4->sin_addr.s_addr = iph->ip_dst.s_addr;
- to4->sin_port = sh->dest_port;
- break;
- }
-#ifdef INET6
- case IPV6_VERSION >> 4:
- {
- /* its IPv6 */
- struct ip6_hdr *ip6;
- struct sockaddr_in6 *to6;
-
- ip6 = mtod(m, struct ip6_hdr *);
- to6 = (struct sockaddr_in6 *)&to_store;
- bzero(to6, sizeof(*to6));
- to6->sin6_family = AF_INET6;
- to6->sin6_len = sizeof(struct sockaddr_in6);
- to6->sin6_addr = ip6->ip6_dst;
- to6->sin6_port = sh->dest_port;
- /* Get the scopes in properly to the sin6 addr's */
- /* we probably don't need these operations */
- (void)sa6_recoverscope(to6);
- sa6_embedscope(to6, MODULE_GLOBAL(ip6_use_defzone));
- break;
- }
-#endif
- default:
- /* TSNH */
- break;
- }
if (sh->v_tag) {
/* we only go down this path if vtag is non-zero */
- retval = sctp_findassoc_by_vtag(from, to, ntohl(sh->v_tag),
+ stcb = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag),
inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0);
- if (retval) {
- return (retval);
+ if (stcb) {
+ return (stcb);
}
}
find_tcp_pool = 0;
@@ -2174,15 +2192,15 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
find_tcp_pool = 1;
}
if (inp_p) {
- retval = sctp_findassociation_addr_sa(to, from, inp_p, netp,
+ stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp,
find_tcp_pool, vrf_id);
inp = *inp_p;
} else {
- retval = sctp_findassociation_addr_sa(to, from, &inp, netp,
+ stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp,
find_tcp_pool, vrf_id);
}
- SCTPDBG(SCTP_DEBUG_PCB1, "retval:%p inp:%p\n", retval, inp);
- if (retval == NULL && inp) {
+ SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp);
+ if (stcb == NULL && inp) {
/* Found a EP but not this address */
if ((ch->chunk_type == SCTP_INITIATION) ||
(ch->chunk_type == SCTP_INITIATION_ACK)) {
@@ -2200,15 +2218,15 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
}
return (NULL);
}
- retval = sctp_findassociation_special_addr(m, iphlen,
- offset, sh, &inp, netp, to);
+ stcb = sctp_findassociation_special_addr(m,
+ offset, sh, &inp, netp, dst);
if (inp_p != NULL) {
*inp_p = inp;
}
}
}
- SCTPDBG(SCTP_DEBUG_PCB1, "retval is %p\n", retval);
- return (retval);
+ SCTPDBG(SCTP_DEBUG_PCB1, "stcb is %p\n", (void *)stcb);
+ return (stcb);
}
/*
@@ -2216,58 +2234,26 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
* if the lookup address is 0.0.0.0 or ::0, use the vtag to do the lookup
*/
struct sctp_tcb *
-sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset,
- struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
+sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
+ struct sockaddr *dst, struct sctphdr *sh,
+ struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
{
struct sctp_tcb *stcb;
- struct sockaddr_in *sin;
-
-#ifdef INET6
- struct sockaddr_in6 *sin6;
-
-#endif
- struct sockaddr_storage local_store, remote_store;
- struct sockaddr *to;
- struct ip *iph;
-
-#ifdef INET6
- struct ip6_hdr *ip6;
-
-#endif
+ struct sockaddr_storage remote_store;
struct sctp_paramhdr parm_buf, *phdr;
int ptype;
int zero_address = 0;
+#ifdef INET
+ struct sockaddr_in *sin;
- memset(&local_store, 0, sizeof(local_store));
- memset(&remote_store, 0, sizeof(remote_store));
- to = (struct sockaddr *)&local_store;
- /* First get the destination address setup too. */
- iph = mtod(m, struct ip *);
- switch (iph->ip_v) {
- case IPVERSION:
- /* its IPv4 */
- sin = (struct sockaddr_in *)&local_store;
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(*sin);
- sin->sin_port = sh->dest_port;
- sin->sin_addr.s_addr = iph->ip_dst.s_addr;
- break;
+#endif
#ifdef INET6
- case IPV6_VERSION >> 4:
- /* its IPv6 */
- ip6 = mtod(m, struct ip6_hdr *);
- sin6 = (struct sockaddr_in6 *)&local_store;
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_port = sh->dest_port;
- sin6->sin6_addr = ip6->ip6_dst;
- break;
+ struct sockaddr_in6 *sin6;
+
#endif
- default:
- return NULL;
- }
+ memset(&remote_store, 0, sizeof(remote_store));
phdr = sctp_get_next_param(m, offset + sizeof(struct sctp_asconf_chunk),
&parm_buf, sizeof(struct sctp_paramhdr));
if (phdr == NULL) {
@@ -2305,6 +2291,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset,
break;
}
#endif
+#ifdef INET
case SCTP_IPV4_ADDRESS:
{
/* ipv4 address param */
@@ -2330,22 +2317,22 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset,
zero_address = 1;
break;
}
+#endif
default:
/* invalid address param type */
return NULL;
}
if (zero_address) {
- stcb = sctp_findassoc_by_vtag(NULL, to, ntohl(sh->v_tag), inp_p,
+ stcb = sctp_findassoc_by_vtag(NULL, dst, ntohl(sh->v_tag), inp_p,
netp, sh->src_port, sh->dest_port, 1, vrf_id, 0);
- /*
- * printf("findassociation_ep_asconf: zero lookup address
- * finds stcb 0x%x\n", (uint32_t)stcb);
- */
+ if (stcb != NULL) {
+ SCTP_INP_DECR_REF(*inp_p);
+ }
} else {
stcb = sctp_findassociation_ep_addr(inp_p,
(struct sockaddr *)&remote_store, netp,
- to, NULL);
+ dst, NULL);
}
return (stcb);
}
@@ -2390,10 +2377,16 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
/* setup socket pointers */
inp->sctp_socket = so;
inp->ip_inp.inp.inp_socket = so;
+#ifdef INET6
+ if (MODULE_GLOBAL(ip6_auto_flowlabel)) {
+ inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL;
+ }
+#endif
inp->sctp_associd_counter = 1;
inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT;
inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
+ inp->sctp_ecn_enable = SCTP_BASE_SYSCTL(sctp_ecn_enable);
/* init the small hash table we use to track asocid <-> tcb */
inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark);
if (inp->sctp_asocidhash == NULL) {
@@ -2422,8 +2415,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
so->so_pcb = (caddr_t)inp;
- if ((SCTP_SO_TYPE(so) == SOCK_DGRAM) ||
- (SCTP_SO_TYPE(so) == SOCK_SEQPACKET)) {
+ if (SCTP_SO_TYPE(so) == SOCK_SEQPACKET) {
/* UDP style socket */
inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
SCTP_PCB_FLAGS_UNBOUND);
@@ -2514,21 +2506,20 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
m->max_init_times = SCTP_BASE_SYSCTL(sctp_init_rtx_max_default);
m->max_send_times = SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default);
m->def_net_failure = SCTP_BASE_SYSCTL(sctp_path_rtx_max_default);
+ m->def_net_pf_threshold = SCTP_BASE_SYSCTL(sctp_path_pf_threshold);
m->sctp_sws_sender = SCTP_SWS_SENDER_DEF;
m->sctp_sws_receiver = SCTP_SWS_RECEIVER_DEF;
m->max_burst = SCTP_BASE_SYSCTL(sctp_max_burst_default);
- if ((SCTP_BASE_SYSCTL(sctp_default_cc_module) >= SCTP_CC_RFC2581) &&
- (SCTP_BASE_SYSCTL(sctp_default_cc_module) <= SCTP_CC_HTCP)) {
- m->sctp_default_cc_module = SCTP_BASE_SYSCTL(sctp_default_cc_module);
- } else {
- /* sysctl done with invalid value, set to 2581 */
- m->sctp_default_cc_module = SCTP_CC_RFC2581;
- }
+ m->fr_max_burst = SCTP_BASE_SYSCTL(sctp_fr_max_burst_default);
+
+ m->sctp_default_cc_module = SCTP_BASE_SYSCTL(sctp_default_cc_module);
+ m->sctp_default_ss_module = SCTP_BASE_SYSCTL(sctp_default_ss_module);
/* number of streams to pre-open on a association */
m->pre_open_stream_count = SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default);
/* Add adaptation cookie */
- m->adaptation_layer_indicator = 0x504C5253;
+ m->adaptation_layer_indicator = 0;
+ m->adaptation_layer_indicator_provided = 0;
/* seed random number generator */
m->random_counter = 1;
@@ -2557,6 +2548,11 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
*/
m->local_hmacs = sctp_default_supported_hmaclist();
m->local_auth_chunks = sctp_alloc_chunklist();
+ m->default_dscp = 0;
+#ifdef INET6
+ m->default_flowlabel = 0;
+#endif
+ m->port = 0; /* encapsulation disabled by default */
sctp_auth_set_default_chunks(m->local_auth_chunks);
LIST_INIT(&m->shared_keys);
/* add default NULL key as key id 0 */
@@ -2663,6 +2659,9 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
LIST_INSERT_HEAD(&new_inp->sctp_addr_list, laddr,
sctp_nxt_addr);
new_inp->laddr_count++;
+ if (oladdr == stcb->asoc.last_used_address) {
+ stcb->asoc.last_used_address = laddr;
+ }
}
}
/*
@@ -2671,7 +2670,6 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
* all of them.
*/
- stcb->asoc.hb_timer.ep = (void *)new_inp;
stcb->asoc.dack_timer.ep = (void *)new_inp;
stcb->asoc.asconf_timer.ep = (void *)new_inp;
stcb->asoc.strreset_timer.ep = (void *)new_inp;
@@ -2682,8 +2680,8 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
/* now what about the nets? */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
net->pmtu_timer.ep = (void *)new_inp;
+ net->hb_timer.ep = (void *)new_inp;
net->rxt_timer.ep = (void *)new_inp;
- net->fr_timer.ep = (void *)new_inp;
}
SCTP_INP_WUNLOCK(new_inp);
SCTP_INP_WUNLOCK(old_inp);
@@ -2714,9 +2712,9 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
ip_inp = (struct inpcb *)so->so_pcb;
#ifdef SCTP_DEBUG
if (addr) {
- SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port:%d\n",
+ SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port: %d\n",
ntohs(((struct sockaddr_in *)addr)->sin_port));
- SCTPDBG(SCTP_DEBUG_PCB1, "Addr :");
+ SCTPDBG(SCTP_DEBUG_PCB1, "Addr: ");
SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr);
}
#endif
@@ -2731,6 +2729,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
#endif
if (addr != NULL) {
switch (addr->sa_family) {
+#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin;
@@ -2760,6 +2759,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
}
break;
}
+#endif
#ifdef INET6
case AF_INET6:
{
@@ -2776,7 +2776,6 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
return (EINVAL);
}
lport = sin6->sin6_port;
-
/*
* For LOOPBACK the prison_local_ip6() call
* will transmute the ipv6 address to the
@@ -2814,7 +2813,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_INP_INCR_REF(inp);
if (lport) {
/*
- * Did the caller specify a port? if so we must see if a ep
+ * Did the caller specify a port? if so we must see if an ep
* already has this one bound.
*/
/* got to be root to get at low ports */
@@ -2895,8 +2894,7 @@ continue_anyway:
if (bindall) {
/* verify that no lport is not used by a singleton */
if ((port_reuse_active == 0) &&
- (inp_tmp = sctp_isport_inuse(inp, lport, vrf_id))
- ) {
+ (inp_tmp = sctp_isport_inuse(inp, lport, vrf_id))) {
/* Sorry someone already has this one bound */
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
(sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) {
@@ -3031,27 +3029,40 @@ continue_anyway:
struct sockaddr_storage store_sa;
memset(&store_sa, 0, sizeof(store_sa));
- if (addr->sa_family == AF_INET) {
- struct sockaddr_in *sin;
+ switch (addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
- sin = (struct sockaddr_in *)&store_sa;
- memcpy(sin, addr, sizeof(struct sockaddr_in));
- sin->sin_port = 0;
- } else if (addr->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6;
+ sin = (struct sockaddr_in *)&store_sa;
+ memcpy(sin, addr, sizeof(struct sockaddr_in));
+ sin->sin_port = 0;
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)&store_sa;
- memcpy(sin6, addr, sizeof(struct sockaddr_in6));
- sin6->sin6_port = 0;
+ sin6 = (struct sockaddr_in6 *)&store_sa;
+ memcpy(sin6, addr, sizeof(struct sockaddr_in6));
+ sin6->sin6_port = 0;
+ break;
+ }
+#endif
+ default:
+ break;
}
/*
* first find the interface with the bound address need to
* zero out the port to find the address! yuck! can't do
* this earlier since need port for sctp_pcb_findep()
*/
- if (sctp_ifap != NULL)
+ if (sctp_ifap != NULL) {
ifa = sctp_ifap;
- else {
+ } else {
/*
* Note for BSD we hit here always other O/S's will
* pass things in via the sctp_ifap argument
@@ -3067,6 +3078,7 @@ continue_anyway:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRNOTAVAIL);
return (EADDRNOTAVAIL);
}
+#ifdef INET6
if (addr->sa_family == AF_INET6) {
/* GAK, more FIXME IFA lock? */
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
@@ -3077,6 +3089,7 @@ continue_anyway:
return (EINVAL);
}
}
+#endif
/* we're not bound all */
inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUNDALL;
/* allow bindx() to send ASCONF's for binding changes */
@@ -3104,7 +3117,7 @@ continue_anyway:
/* put it in the bucket */
LIST_INSERT_HEAD(head, inp, sctp_hash);
SCTPDBG(SCTP_DEBUG_PCB1, "Main hash to bind at head:%p, bound port:%d - in tcp_pool=%d\n",
- head, ntohs(lport), port_reuse_active);
+ (void *)head, ntohs(lport), port_reuse_active);
/* set in the port */
inp->sctp_lport = lport;
@@ -3155,11 +3168,8 @@ sctp_iterator_inp_being_freed(struct sctp_inpcb *inp)
* may be still pending on the list
*/
SCTP_IPI_ITERATOR_WQ_LOCK();
- it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
- while (it) {
- nit = TAILQ_NEXT(it, sctp_nxt_itr);
+ TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
if (it->vn != curvnet) {
- it = nit;
continue;
}
if (it->inp == inp) {
@@ -3184,7 +3194,6 @@ sctp_iterator_inp_being_freed(struct sctp_inpcb *inp)
*/
SCTP_INP_DECR_REF(inp);
}
- it = nit;
}
SCTP_IPI_ITERATOR_WQ_UNLOCK();
}
@@ -3201,17 +3210,14 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* freeing. a) Any local lists. b) Any associations. c) The hash of
* all associations. d) finally the ep itself.
*/
- struct sctp_pcb *m;
struct sctp_tcb *asoc, *nasoc;
struct sctp_laddr *laddr, *nladdr;
struct inpcb *ip_pcb;
struct socket *so;
int being_refed = 0;
- struct sctp_queued_to_read *sq;
-
-
+ struct sctp_queued_to_read *sq, *nsq;
int cnt;
- sctp_sharedkey_t *shared_key;
+ sctp_sharedkey_t *shared_key, *nshared_key;
#ifdef SCTP_LOG_CLOSING
@@ -3254,7 +3260,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
sctp_m_freem(inp->pkt);
inp->pkt = NULL;
}
- m = &inp->sctp_ep;
ip_pcb = &inp->ip_inp.inp; /* we could just cast the main pointer
* here but I will be nice :> (i.e.
* ip_pcb = ep;) */
@@ -3262,10 +3267,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
int cnt_in_sd;
cnt_in_sd = 0;
- for ((asoc = LIST_FIRST(&inp->sctp_asoc_list)); asoc != NULL;
- asoc = nasoc) {
+ LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_list, sctp_tcblist, nasoc) {
SCTP_TCB_LOCK(asoc);
- nasoc = LIST_NEXT(asoc, sctp_tcblist);
if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
/* Skip guys being freed */
cnt_in_sd++;
@@ -3304,32 +3307,22 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
if ((asoc->asoc.size_on_reasm_queue > 0) ||
(asoc->asoc.control_pdapi) ||
(asoc->asoc.size_on_all_streams > 0) ||
- (so && (so->so_rcv.sb_cc > 0))
- ) {
+ (so && (so->so_rcv.sb_cc > 0))) {
/* Left with Data unread */
struct mbuf *op_err;
- op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_DONTWAIT, 1, MT_DATA);
if (op_err) {
/* Fill in the user initiated abort */
struct sctp_paramhdr *ph;
- uint32_t *ippp;
-
- SCTP_BUF_LEN(op_err) =
- sizeof(struct sctp_paramhdr) + sizeof(uint32_t);
- ph = mtod(op_err,
- struct sctp_paramhdr *);
- ph->param_type = htons(
- SCTP_CAUSE_USER_INITIATED_ABT);
+
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
+ ph = mtod(op_err, struct sctp_paramhdr *);
+ ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(op_err));
- ippp = (uint32_t *) (ph + 1);
- *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_3);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3;
-#if defined(SCTP_PANIC_ON_ABORT)
- panic("inpcb_free does an abort");
-#endif
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
@@ -3343,26 +3336,33 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
continue;
} else if (TAILQ_EMPTY(&asoc->asoc.send_queue) &&
TAILQ_EMPTY(&asoc->asoc.sent_queue) &&
- (asoc->asoc.stream_queue_cnt == 0)
- ) {
+ (asoc->asoc.stream_queue_cnt == 0)) {
if (asoc->asoc.locked_on_sending) {
goto abort_anyway;
}
if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
(SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ struct sctp_nets *netp;
+
/*
* there is nothing queued to send,
* so I send shutdown
*/
- sctp_send_shutdown(asoc, asoc->asoc.primary_destination);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_SET_STATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(asoc);
+ if (asoc->asoc.alternate) {
+ netp = asoc->asoc.alternate;
+ } else {
+ netp = asoc->asoc.primary_destination;
+ }
+ sctp_send_shutdown(asoc, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, asoc->sctp_ep, asoc,
- asoc->asoc.primary_destination);
+ netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc,
asoc->asoc.primary_destination);
sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_LOCKED);
@@ -3379,7 +3379,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
sctp_streamhead);
if (sp == NULL) {
SCTP_PRINTF("Error, sp is NULL, locked on sending is %p strm:%d\n",
- asoc->asoc.locked_on_sending,
+ (void *)asoc->asoc.locked_on_sending,
asoc->asoc.locked_on_sending->stream_no);
} else {
if ((sp->length == 0) && (sp->msg_is_complete == 0))
@@ -3392,7 +3392,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
struct mbuf *op_err;
abort_anyway:
- op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_DONTWAIT, 1, MT_DATA);
if (op_err) {
/*
@@ -3400,24 +3400,13 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* initiated abort
*/
struct sctp_paramhdr *ph;
- uint32_t *ippp;
-
- SCTP_BUF_LEN(op_err) =
- (sizeof(struct sctp_paramhdr) +
- sizeof(uint32_t));
- ph = mtod(op_err,
- struct sctp_paramhdr *);
- ph->param_type = htons(
- SCTP_CAUSE_USER_INITIATED_ABT);
+
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
+ ph = mtod(op_err, struct sctp_paramhdr *);
+ ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(op_err));
- ippp = (uint32_t *) (ph + 1);
- *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_5);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5;
-#if defined(SCTP_PANIC_ON_ABORT)
- panic("inpcb_free does an abort");
-#endif
-
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
@@ -3464,10 +3453,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* have a contest on the INP lock.. which would cause us to die ...
*/
cnt = 0;
- for ((asoc = LIST_FIRST(&inp->sctp_asoc_list)); asoc != NULL;
- asoc = nasoc) {
+ LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_list, sctp_tcblist, nasoc) {
SCTP_TCB_LOCK(asoc);
- nasoc = LIST_NEXT(asoc, sctp_tcblist);
if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) {
asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
@@ -3481,28 +3468,19 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_COOKIE_WAIT) &&
((asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) {
struct mbuf *op_err;
- uint32_t *ippp;
- op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_DONTWAIT, 1, MT_DATA);
if (op_err) {
/* Fill in the user initiated abort */
struct sctp_paramhdr *ph;
- SCTP_BUF_LEN(op_err) = (sizeof(struct sctp_paramhdr) +
- sizeof(uint32_t));
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
ph = mtod(op_err, struct sctp_paramhdr *);
- ph->param_type = htons(
- SCTP_CAUSE_USER_INITIATED_ABT);
+ ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(op_err));
- ippp = (uint32_t *) (ph + 1);
- *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_7);
-
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_7;
-#if defined(SCTP_PANIC_ON_ABORT)
- panic("inpcb_free does an abort");
-#endif
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
} else if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
@@ -3584,7 +3562,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
inp->sctp_asocidhash = NULL;
}
/* sa_ignore FREED_MEMORY */
- while ((sq = TAILQ_FIRST(&inp->read_queue)) != NULL) {
+ TAILQ_FOREACH_SAFE(sq, &inp->read_queue, next, nsq) {
/* Its only abandoned if it had data left */
if (sq->length)
SCTP_STAT_INCR(sctps_left_abandon);
@@ -3610,7 +3588,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* macro here since le_next will get freed as part of the
* sctp_free_assoc() call.
*/
- cnt = 0;
if (so) {
#ifdef IPSEC
ipsec_delete_pcbpolicy(ip_pcb);
@@ -3622,10 +3599,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
(void)sctp_m_free(ip_pcb->inp_options);
ip_pcb->inp_options = 0;
}
- if (ip_pcb->inp_moptions) {
- inp_freemoptions(ip_pcb->inp_moptions);
- ip_pcb->inp_moptions = 0;
- }
#ifdef INET6
if (ip_pcb->inp_vflag & INP_IPV6) {
struct in6pcb *in6p;
@@ -3641,12 +3614,10 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
if (inp->sctp_ep.local_hmacs != NULL)
sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
- shared_key = LIST_FIRST(&inp->sctp_ep.shared_keys);
- while (shared_key) {
+ LIST_FOREACH_SAFE(shared_key, &inp->sctp_ep.shared_keys, next, nshared_key) {
LIST_REMOVE(shared_key, next);
sctp_free_sharedkey(shared_key);
/* sa_ignore FREED_MEMORY */
- shared_key = LIST_FIRST(&inp->sctp_ep.shared_keys);
}
/*
@@ -3654,17 +3625,13 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* ifaddr's that are set into this ep. Again macro limitations here,
* since the LIST_FOREACH could be a bad idea.
*/
- for ((laddr = LIST_FIRST(&inp->sctp_addr_list)); laddr != NULL;
- laddr = nladdr) {
- nladdr = LIST_NEXT(laddr, sctp_nxt_addr);
+ LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
sctp_remove_laddr(laddr);
}
#ifdef SCTP_TRACK_FREED_ASOCS
/* TEMP CODE */
- for ((asoc = LIST_FIRST(&inp->sctp_asoc_free_list)); asoc != NULL;
- asoc = nasoc) {
- nasoc = LIST_NEXT(asoc, sctp_tcblist);
+ LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_free_list, sctp_tcblist, nasoc) {
LIST_REMOVE(asoc, sctp_tcblist);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), asoc);
SCTP_DECR_ASOC_COUNT();
@@ -3720,7 +3687,7 @@ sctp_is_address_on_local_host(struct sockaddr *addr, uint32_t vrf_id)
*/
int
sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
- int set_scope, int from)
+ struct sctp_nets **netp, int set_scope, int from)
{
/*
* The following is redundant to the same lines in the
@@ -3756,84 +3723,96 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
return (0);
}
addr_inscope = 1;
- if (newaddr->sa_family == AF_INET) {
- struct sockaddr_in *sin;
+ switch (newaddr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
- sin = (struct sockaddr_in *)newaddr;
- if (sin->sin_addr.s_addr == 0) {
- /* Invalid address */
- return (-1);
- }
- /* zero out the bzero area */
- memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
+ sin = (struct sockaddr_in *)newaddr;
+ if (sin->sin_addr.s_addr == 0) {
+ /* Invalid address */
+ return (-1);
+ }
+ /* zero out the bzero area */
+ memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
- /* assure len is set */
- sin->sin_len = sizeof(struct sockaddr_in);
- if (set_scope) {
+ /* assure len is set */
+ sin->sin_len = sizeof(struct sockaddr_in);
+ if (set_scope) {
#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE
- stcb->ipv4_local_scope = 1;
+ stcb->ipv4_local_scope = 1;
#else
- if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
- stcb->asoc.ipv4_local_scope = 1;
- }
+ if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
+ stcb->asoc.scope.ipv4_local_scope = 1;
+ }
#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */
- } else {
- /* Validate the address is in scope */
- if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) &&
- (stcb->asoc.ipv4_local_scope == 0)) {
- addr_inscope = 0;
+ } else {
+ /* Validate the address is in scope */
+ if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) &&
+ (stcb->asoc.scope.ipv4_local_scope == 0)) {
+ addr_inscope = 0;
+ }
}
+ break;
}
+#endif
#ifdef INET6
- } else if (newaddr->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)newaddr;
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
- /* Invalid address */
- return (-1);
- }
- /* assure len is set */
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- if (set_scope) {
- if (sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id)) {
- stcb->asoc.loopback_scope = 1;
- stcb->asoc.local_scope = 0;
- stcb->asoc.ipv4_local_scope = 1;
- stcb->asoc.site_scope = 1;
- } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- /*
- * If the new destination is a LINK_LOCAL we
- * must have common site scope. Don't set
- * the local scope since we may not share
- * all links, only loopback can do this.
- * Links on the local network would also be
- * on our private network for v4 too.
- */
- stcb->asoc.ipv4_local_scope = 1;
- stcb->asoc.site_scope = 1;
- } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
- /*
- * If the new destination is SITE_LOCAL then
- * we must have site scope in common.
- */
- stcb->asoc.site_scope = 1;
+ sin6 = (struct sockaddr_in6 *)newaddr;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ /* Invalid address */
+ return (-1);
}
- } else {
- /* Validate the address is in scope */
- if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
- (stcb->asoc.loopback_scope == 0)) {
- addr_inscope = 0;
- } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
- (stcb->asoc.local_scope == 0)) {
- addr_inscope = 0;
- } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
- (stcb->asoc.site_scope == 0)) {
- addr_inscope = 0;
+ /* assure len is set */
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+ if (set_scope) {
+ if (sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id)) {
+ stcb->asoc.scope.loopback_scope = 1;
+ stcb->asoc.scope.local_scope = 0;
+ stcb->asoc.scope.ipv4_local_scope = 1;
+ stcb->asoc.scope.site_scope = 1;
+ } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ /*
+ * If the new destination is a
+ * LINK_LOCAL we must have common
+ * site scope. Don't set the local
+ * scope since we may not share all
+ * links, only loopback can do this.
+ * Links on the local network would
+ * also be on our private network
+ * for v4 too.
+ */
+ stcb->asoc.scope.ipv4_local_scope = 1;
+ stcb->asoc.scope.site_scope = 1;
+ } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
+ /*
+ * If the new destination is
+ * SITE_LOCAL then we must have site
+ * scope in common.
+ */
+ stcb->asoc.scope.site_scope = 1;
+ }
+ } else {
+ /* Validate the address is in scope */
+ if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
+ (stcb->asoc.scope.loopback_scope == 0)) {
+ addr_inscope = 0;
+ } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
+ (stcb->asoc.scope.local_scope == 0)) {
+ addr_inscope = 0;
+ } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
+ (stcb->asoc.scope.site_scope == 0)) {
+ addr_inscope = 0;
+ }
}
+ break;
}
#endif
- } else {
+ default:
/* not supported family type */
return (-1);
}
@@ -3842,23 +3821,33 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
return (-1);
}
SCTP_INCR_RADDR_COUNT();
- bzero(net, sizeof(*net));
+ bzero(net, sizeof(struct sctp_nets));
(void)SCTP_GETTIME_TIMEVAL(&net->start_time);
memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len);
- if (newaddr->sa_family == AF_INET) {
+ switch (newaddr->sa_family) {
+#ifdef INET
+ case AF_INET:
((struct sockaddr_in *)&net->ro._l_addr)->sin_port = stcb->rport;
- } else if (newaddr->sa_family == AF_INET6) {
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
((struct sockaddr_in6 *)&net->ro._l_addr)->sin6_port = stcb->rport;
+ break;
+#endif
+ default:
+ break;
}
net->addr_is_local = sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id);
if (net->addr_is_local && ((set_scope || (from == SCTP_ADDR_IS_CONFIRMED)))) {
- stcb->asoc.loopback_scope = 1;
- stcb->asoc.ipv4_local_scope = 1;
- stcb->asoc.local_scope = 0;
- stcb->asoc.site_scope = 1;
+ stcb->asoc.scope.loopback_scope = 1;
+ stcb->asoc.scope.ipv4_local_scope = 1;
+ stcb->asoc.scope.local_scope = 0;
+ stcb->asoc.scope.site_scope = 1;
addr_inscope = 1;
}
net->failure_threshold = stcb->asoc.def_net_failure;
+ net->pf_threshold = stcb->asoc.def_net_pf_threshold;
if (addr_inscope == 0) {
net->dest_state = (SCTP_ADDR_REACHABLE |
SCTP_ADDR_OUT_OF_SCOPE);
@@ -3874,28 +3863,32 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
* We set this to 0, the timer code knows that this means its an
* initial value
*/
+ net->rto_needed = 1;
net->RTO = 0;
net->RTO_measured = 0;
stcb->asoc.numnets++;
- *(&net->ref_count) = 1;
- net->tos_flowlabel = 0;
- if (SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable)) {
- net->port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
- } else {
- net->port = 0;
- }
-#ifdef INET
- if (newaddr->sa_family == AF_INET)
- net->tos_flowlabel = stcb->asoc.default_tos;
-#endif
+ net->ref_count = 1;
+ net->cwr_window_tsn = net->last_cwr_tsn = stcb->asoc.sending_seq - 1;
+ net->port = stcb->asoc.port;
+ net->dscp = stcb->asoc.default_dscp;
#ifdef INET6
- if (newaddr->sa_family == AF_INET6)
- net->tos_flowlabel = stcb->asoc.default_flowlabel;
+ net->flowlabel = stcb->asoc.default_flowlabel;
#endif
+ if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
+ net->dest_state |= SCTP_ADDR_NOHB;
+ } else {
+ net->dest_state &= ~SCTP_ADDR_NOHB;
+ }
+ if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
+ net->dest_state |= SCTP_ADDR_NO_PMTUD;
+ } else {
+ net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
+ }
+ net->heart_beat_delay = stcb->asoc.heart_beat_delay;
/* Init the timer structure */
SCTP_OS_TIMER_INIT(&net->rxt_timer.timer);
- SCTP_OS_TIMER_INIT(&net->fr_timer.timer);
SCTP_OS_TIMER_INIT(&net->pmtu_timer.timer);
+ SCTP_OS_TIMER_INIT(&net->hb_timer.timer);
/* Now generate a route for this guy */
#ifdef INET6
@@ -3921,13 +3914,8 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
/* Now get the interface MTU */
if (net->ro._s_addr && net->ro._s_addr->ifn_p) {
net->mtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p);
- } else {
- net->mtu = 0;
}
- if (net->mtu == 0) {
- /* Huh ?? */
- net->mtu = SCTP_DEFAULT_MTU;
- } else {
+ if (net->mtu > 0) {
uint32_t rmtu;
rmtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, net->ro.ro_rt);
@@ -3947,11 +3935,31 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
net->mtu = rmtu;
}
}
- if (from == SCTP_ALLOC_ASOC) {
- stcb->asoc.smallest_mtu = net->mtu;
+ }
+ if (net->mtu == 0) {
+ switch (newaddr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ net->mtu = SCTP_DEFAULT_MTU;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ net->mtu = 1280;
+ break;
+#endif
+ default:
+ break;
}
- } else {
- net->mtu = stcb->asoc.smallest_mtu;
+ }
+ if (net->port) {
+ net->mtu -= (uint32_t) sizeof(struct udphdr);
+ }
+ if (from == SCTP_ALLOC_ASOC) {
+ stcb->asoc.smallest_mtu = net->mtu;
+ }
+ if (stcb->asoc.smallest_mtu > net->mtu) {
+ stcb->asoc.smallest_mtu = net->mtu;
}
#ifdef INET6
if (newaddr->sa_family == AF_INET6) {
@@ -3961,14 +3969,10 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
(void)sa6_recoverscope(sin6);
}
#endif
- if (net->port) {
- net->mtu -= sizeof(struct udphdr);
- }
- if (stcb->asoc.smallest_mtu > net->mtu) {
- stcb->asoc.smallest_mtu = net->mtu;
- }
+
/* JRS - Use the congestion control given in the CC module */
- stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
+ if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL)
+ (*stcb->asoc.cc_functions.sctp_set_initial_cc_param) (stcb, net);
/*
* CMT: CUC algo - set find_pseudo_cumack to TRUE (1) at beginning
@@ -3977,6 +3981,16 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
net->find_pseudo_cumack = 1;
net->find_rtx_pseudo_cumack = 1;
net->src_addr_selected = 0;
+ /* Choose an initial flowid. */
+ net->flowid = stcb->asoc.my_vtag ^
+ ntohs(stcb->rport) ^
+ ntohs(stcb->sctp_ep->sctp_lport);
+#ifdef INVARIANTS
+ net->flowidset = 1;
+#endif
+ if (netp) {
+ *netp = net;
+ }
netfirst = TAILQ_FIRST(&stcb->asoc.nets);
if (net->ro.ro_rt == NULL) {
/* Since we have no route put it at the back */
@@ -4034,8 +4048,6 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
/* No route to current primary adopt new primary */
stcb->asoc.primary_destination = net;
}
- sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb,
- net);
/* Validate primary is first */
net = TAILQ_FIRST(&stcb->asoc.nets);
if ((net != stcb->asoc.primary_destination) &&
@@ -4069,11 +4081,11 @@ try_again:
return (0);
}
/*
- * We don't allow assoc id to be 0, this is needed otherwise if the
- * id were to wrap we would have issues with some socket options.
+ * We don't allow assoc id to be one of SCTP_FUTURE_ASSOC,
+ * SCTP_CURRENT_ASSOC and SCTP_ALL_ASSOC.
*/
- if (inp->sctp_associd_counter == 0) {
- inp->sctp_associd_counter++;
+ if (inp->sctp_associd_counter <= SCTP_ALL_ASSOC) {
+ inp->sctp_associd_counter = SCTP_ALL_ASSOC + 1;
}
id = inp->sctp_associd_counter;
inp->sctp_associd_counter++;
@@ -4138,42 +4150,81 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
*error = EINVAL;
return (NULL);
}
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED)) {
+ SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
+ *error = EINVAL;
+ return (NULL);
+ }
+ }
SCTPDBG(SCTP_DEBUG_PCB3, "Allocate an association for peer:");
#ifdef SCTP_DEBUG
if (firstaddr) {
SCTPDBG_ADDR(SCTP_DEBUG_PCB3, firstaddr);
- SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n",
- ntohs(((struct sockaddr_in *)firstaddr)->sin_port));
+ switch (firstaddr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n",
+ ntohs(((struct sockaddr_in *)firstaddr)->sin_port));
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n",
+ ntohs(((struct sockaddr_in6 *)firstaddr)->sin6_port));
+ break;
+#endif
+ default:
+ break;
+ }
} else {
SCTPDBG(SCTP_DEBUG_PCB3, "None\n");
}
#endif /* SCTP_DEBUG */
- if (firstaddr->sa_family == AF_INET) {
- struct sockaddr_in *sin;
+ switch (firstaddr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
- sin = (struct sockaddr_in *)firstaddr;
- if ((sin->sin_port == 0) || (sin->sin_addr.s_addr == 0)) {
- /* Invalid address */
- SCTP_INP_RUNLOCK(inp);
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- *error = EINVAL;
- return (NULL);
+ sin = (struct sockaddr_in *)firstaddr;
+ if ((ntohs(sin->sin_port) == 0) ||
+ (sin->sin_addr.s_addr == INADDR_ANY) ||
+ (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
+ /* Invalid address */
+ SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
+ *error = EINVAL;
+ return (NULL);
+ }
+ rport = sin->sin_port;
+ break;
}
- rport = sin->sin_port;
- } else if (firstaddr->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)firstaddr;
- if ((sin6->sin6_port == 0) ||
- (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
- /* Invalid address */
- SCTP_INP_RUNLOCK(inp);
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- *error = EINVAL;
- return (NULL);
+ sin6 = (struct sockaddr_in6 *)firstaddr;
+ if ((ntohs(sin6->sin6_port) == 0) ||
+ IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+ /* Invalid address */
+ SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
+ *error = EINVAL;
+ return (NULL);
+ }
+ rport = sin6->sin6_port;
+ break;
}
- rport = sin6->sin6_port;
- } else {
+#endif
+ default:
/* not supported family type */
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
@@ -4249,7 +4300,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
SCTP_INP_INFO_WUNLOCK();
- if ((err = sctp_add_remote_addr(stcb, firstaddr, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) {
+ if ((err = sctp_add_remote_addr(stcb, firstaddr, NULL, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) {
/* failure.. memory error? */
if (asoc->strmout) {
SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
@@ -4274,7 +4325,6 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
return (NULL);
}
/* Init all the timers */
- SCTP_OS_TIMER_INIT(&asoc->hb_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->dack_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->strreset_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->asconf_timer.timer);
@@ -4291,7 +4341,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
LIST_INSERT_HEAD(head, stcb, sctp_tcbhash);
}
SCTP_INP_WUNLOCK(inp);
- SCTPDBG(SCTP_DEBUG_PCB1, "Association %p now allocated\n", stcb);
+ SCTPDBG(SCTP_DEBUG_PCB1, "Association %p now allocated\n", (void *)stcb);
return (stcb);
}
@@ -4344,6 +4394,10 @@ out:
/* Clear net */
asoc->last_control_chunk_from = NULL;
}
+ if (net == stcb->asoc.alternate) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
sctp_free_remote_addr(net);
}
@@ -4362,13 +4416,12 @@ sctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr)
* no other addresses.
*/
struct sctp_association *asoc;
- struct sctp_nets *net, *net_tmp;
+ struct sctp_nets *net, *nnet;
asoc = &stcb->asoc;
/* locate the address */
- for (net = TAILQ_FIRST(&asoc->nets); net != NULL; net = net_tmp) {
- net_tmp = TAILQ_NEXT(net, sctp_next);
+ TAILQ_FOREACH_SAFE(net, &asoc->nets, sctp_next, nnet) {
if (net->ro._l_addr.sa.sa_family != remaddr->sa_family) {
continue;
}
@@ -4533,18 +4586,16 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
{
int i;
struct sctp_association *asoc;
- struct sctp_nets *net, *prev;
- struct sctp_laddr *laddr;
- struct sctp_tmit_chunk *chk;
- struct sctp_asconf_addr *aparam;
- struct sctp_asconf_ack *aack;
- struct sctp_stream_reset_list *liste;
- struct sctp_queued_to_read *sq;
- struct sctp_stream_queue_pending *sp;
- sctp_sharedkey_t *shared_key;
+ struct sctp_nets *net, *nnet;
+ struct sctp_laddr *laddr, *naddr;
+ struct sctp_tmit_chunk *chk, *nchk;
+ struct sctp_asconf_addr *aparam, *naparam;
+ struct sctp_asconf_ack *aack, *naack;
+ struct sctp_stream_reset_list *strrst, *nstrrst;
+ struct sctp_queued_to_read *sq, *nsq;
+ struct sctp_stream_queue_pending *sp, *nsp;
+ sctp_sharedkey_t *shared_key, *nshared_key;
struct socket *so;
- int ccnt = 0;
- int cnt = 0;
/* first, lets purge the entry from the hash table. */
@@ -4558,6 +4609,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* there is no asoc, really TSNH :-0 */
return (1);
}
+ if (stcb->asoc.alternate) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
/* TEMP CODE */
if (stcb->freed_from_where == 0) {
/* Only record the first place free happened from */
@@ -4596,8 +4651,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
/* now clean up any other timers */
- (void)SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
- asoc->hb_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
asoc->dack_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
@@ -4621,15 +4674,14 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
(void)SCTP_OS_TIMER_STOP(&asoc->delete_prim_timer.timer);
asoc->delete_prim_timer.self = NULL;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- (void)SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
- net->fr_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
net->rxt_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
net->pmtu_timer.self = NULL;
+ (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
+ net->hb_timer.self = NULL;
}
/* Now the read queue needs to be cleaned up (only once) */
- cnt = 0;
if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) {
stcb->asoc.state |= SCTP_STATE_ABOUT_TO_BE_FREED;
SCTP_INP_READ_LOCK(inp);
@@ -4645,7 +4697,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* Held for PD-API clear that. */
sq->pdapi_aborted = 1;
sq->held_length = 0;
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT) && (so != NULL)) {
+ if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT) && (so != NULL)) {
/*
* Need to add a PD-API
* aborted indication.
@@ -4668,12 +4720,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* Add an end to wake them */
sq->end_added = 1;
- cnt++;
}
}
SCTP_INP_READ_UNLOCK(inp);
if (stcb->block_entry) {
- cnt++;
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PCB, ECONNRESET);
stcb->block_entry->error = ECONNRESET;
stcb->block_entry = NULL;
@@ -4797,7 +4847,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
* Now restop the timers to be sure this is paranoia at is finest!
*/
(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
- (void)SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
@@ -4805,13 +4854,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
(void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- (void)SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
(void)SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
(void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
+ (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
}
asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE;
- prev = NULL;
/*
* The chunk lists and such SHOULD be empty but we check them just
* in case.
@@ -4822,45 +4870,35 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
outs = &asoc->strmout[i];
/* now clean up any chunks here */
- sp = TAILQ_FIRST(&outs->outqueue);
- while (sp) {
+ TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
TAILQ_REMOVE(&outs->outqueue, sp, next);
+ sctp_free_spbufspace(stcb, asoc, sp);
if (sp->data) {
if (so) {
/* Still an open socket - report */
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_UNSENT,
- (void *)sp, SCTP_SO_LOCKED);
+ 0, (void *)sp, SCTP_SO_LOCKED);
}
if (sp->data) {
sctp_m_freem(sp->data);
sp->data = NULL;
sp->tail_mbuf = NULL;
+ sp->length = 0;
}
}
if (sp->net) {
sctp_free_remote_addr(sp->net);
sp->net = NULL;
}
- sctp_free_spbufspace(stcb, asoc, sp);
- if (sp->holds_key_ref)
- sctp_auth_key_release(stcb, sp->auth_keyid);
- /* Free the zone stuff */
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_strmoq), sp);
- SCTP_DECR_STRMOQ_COUNT();
- /* sa_ignore FREED_MEMORY */
- sp = TAILQ_FIRST(&outs->outqueue);
+ sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED);
}
}
-
/* sa_ignore FREED_MEMORY */
- while ((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) {
- TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
- SCTP_FREE(liste, SCTP_M_STRESET);
+ TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
+ TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
+ SCTP_FREE(strrst, SCTP_M_STRESET);
}
-
- sq = TAILQ_FIRST(&asoc->pending_reply_queue);
- while (sq) {
+ TAILQ_FOREACH_SAFE(sq, &asoc->pending_reply_queue, next, nsq) {
TAILQ_REMOVE(&asoc->pending_reply_queue, sq, next);
if (sq->data) {
sctp_m_freem(sq->data);
@@ -4873,168 +4911,131 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), sq);
SCTP_DECR_READQ_COUNT();
/* sa_ignore FREED_MEMORY */
- sq = TAILQ_FIRST(&asoc->pending_reply_queue);
}
-
- chk = TAILQ_FIRST(&asoc->free_chunks);
- while (chk) {
+ TAILQ_FOREACH_SAFE(chk, &asoc->free_chunks, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->free_chunks, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
- sctp_auth_key_release(stcb, chk->auth_keyid);
- ccnt++;
+ sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
atomic_subtract_int(&SCTP_BASE_INFO(ipi_free_chunks), 1);
asoc->free_chunk_cnt--;
/* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->free_chunks);
}
/* pending send queue SHOULD be empty */
- if (!TAILQ_EMPTY(&asoc->send_queue)) {
- chk = TAILQ_FIRST(&asoc->send_queue);
- while (chk) {
- TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
- if (chk->data) {
- if (so) {
- /* Still a socket? */
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_LOCKED);
- }
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
+ TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
+ if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
+#endif
+ }
+ TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
+ if (chk->data) {
+ if (so) {
+ /* Still a socket? */
+ sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb,
+ 0, chk, SCTP_SO_LOCKED);
}
- if (chk->holds_key_ref)
- sctp_auth_key_release(stcb, chk->auth_keyid);
- ccnt++;
- if (chk->whoTo) {
- sctp_free_remote_addr(chk->whoTo);
- chk->whoTo = NULL;
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
- SCTP_DECR_CHK_COUNT();
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->send_queue);
}
+ if (chk->holds_key_ref)
+ sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED);
+ if (chk->whoTo) {
+ sctp_free_remote_addr(chk->whoTo);
+ chk->whoTo = NULL;
+ }
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
+ SCTP_DECR_CHK_COUNT();
+ /* sa_ignore FREED_MEMORY */
}
-/*
- if (ccnt) {
- printf("Freed %d from send_queue\n", ccnt);
- ccnt = 0;
- }
-*/
/* sent queue SHOULD be empty */
- if (!TAILQ_EMPTY(&asoc->sent_queue)) {
- chk = TAILQ_FIRST(&asoc->sent_queue);
- while (chk) {
- TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
- if (chk->data) {
- if (so) {
- /* Still a socket? */
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_SENT, chk, SCTP_SO_LOCKED);
- }
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
+ TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
+ if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
+ if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
+#endif
}
- if (chk->holds_key_ref)
- sctp_auth_key_release(stcb, chk->auth_keyid);
- ccnt++;
- sctp_free_remote_addr(chk->whoTo);
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
- SCTP_DECR_CHK_COUNT();
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->sent_queue);
}
- }
-/*
- if (ccnt) {
- printf("Freed %d from sent_queue\n", ccnt);
- ccnt = 0;
- }
-*/
- /* control queue MAY not be empty */
- if (!TAILQ_EMPTY(&asoc->control_send_queue)) {
- chk = TAILQ_FIRST(&asoc->control_send_queue);
- while (chk) {
- TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
+ TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
+ if (chk->data) {
+ if (so) {
+ /* Still a socket? */
+ sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb,
+ 0, chk, SCTP_SO_LOCKED);
+ }
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
- if (chk->holds_key_ref)
- sctp_auth_key_release(stcb, chk->auth_keyid);
- ccnt++;
- sctp_free_remote_addr(chk->whoTo);
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
- SCTP_DECR_CHK_COUNT();
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->control_send_queue);
}
+ if (chk->holds_key_ref)
+ sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED);
+ sctp_free_remote_addr(chk->whoTo);
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
+ SCTP_DECR_CHK_COUNT();
+ /* sa_ignore FREED_MEMORY */
+ }
+#ifdef INVARIANTS
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ if (stcb->asoc.strmout[i].chunks_on_queues > 0) {
+ panic("%u chunks left for stream %u.", stcb->asoc.strmout[i].chunks_on_queues, i);
+ }
+ }
+#endif
+ /* control queue MAY not be empty */
+ TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
+ TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
+ }
+ if (chk->holds_key_ref)
+ sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED);
+ sctp_free_remote_addr(chk->whoTo);
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
+ SCTP_DECR_CHK_COUNT();
+ /* sa_ignore FREED_MEMORY */
}
-/*
- if (ccnt) {
- printf("Freed %d from ctrl_queue\n", ccnt);
- ccnt = 0;
- }
-*/
-
/* ASCONF queue MAY not be empty */
- if (!TAILQ_EMPTY(&asoc->asconf_send_queue)) {
- chk = TAILQ_FIRST(&asoc->asconf_send_queue);
- while (chk) {
- TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next);
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
- if (chk->holds_key_ref)
- sctp_auth_key_release(stcb, chk->auth_keyid);
- ccnt++;
- sctp_free_remote_addr(chk->whoTo);
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
- SCTP_DECR_CHK_COUNT();
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->asconf_send_queue);
+ TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) {
+ TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next);
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
+ if (chk->holds_key_ref)
+ sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED);
+ sctp_free_remote_addr(chk->whoTo);
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
+ SCTP_DECR_CHK_COUNT();
+ /* sa_ignore FREED_MEMORY */
}
-/*
- if (ccnt) {
- printf("Freed %d from asconf_queue\n", ccnt);
- ccnt = 0;
- }
-*/
- if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
- chk = TAILQ_FIRST(&asoc->reasmqueue);
- while (chk) {
- TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
- if (chk->holds_key_ref)
- sctp_auth_key_release(stcb, chk->auth_keyid);
- sctp_free_remote_addr(chk->whoTo);
- ccnt++;
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
- SCTP_DECR_CHK_COUNT();
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->reasmqueue);
+ TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
+ TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
+ if (chk->holds_key_ref)
+ sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED);
+ sctp_free_remote_addr(chk->whoTo);
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
+ SCTP_DECR_CHK_COUNT();
+ /* sa_ignore FREED_MEMORY */
}
-/*
- if (ccnt) {
- printf("Freed %d from reasm_queue\n", ccnt);
- ccnt = 0;
- }
-*/
+
if (asoc->mapping_array) {
SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
asoc->mapping_array = NULL;
@@ -5050,66 +5051,50 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
asoc->strm_realoutsize = asoc->streamoutcnt = 0;
if (asoc->strmin) {
- struct sctp_queued_to_read *ctl;
+ struct sctp_queued_to_read *ctl, *nctl;
for (i = 0; i < asoc->streamincnt; i++) {
- if (!TAILQ_EMPTY(&asoc->strmin[i].inqueue)) {
- /* We have somethings on the streamin queue */
- ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue);
- while (ctl) {
- TAILQ_REMOVE(&asoc->strmin[i].inqueue,
- ctl, next);
- sctp_free_remote_addr(ctl->whoFrom);
- if (ctl->data) {
- sctp_m_freem(ctl->data);
- ctl->data = NULL;
- }
- /*
- * We don't free the address here
- * since all the net's were freed
- * above.
- */
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl);
- SCTP_DECR_READQ_COUNT();
- ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue);
+ TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) {
+ TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next);
+ sctp_free_remote_addr(ctl->whoFrom);
+ if (ctl->data) {
+ sctp_m_freem(ctl->data);
+ ctl->data = NULL;
}
+ /*
+ * We don't free the address here since all
+ * the net's were freed above.
+ */
+ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl);
+ SCTP_DECR_READQ_COUNT();
}
}
SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
asoc->strmin = NULL;
}
asoc->streamincnt = 0;
- while (!TAILQ_EMPTY(&asoc->nets)) {
- /* sa_ignore FREED_MEMORY */
- net = TAILQ_FIRST(&asoc->nets);
- /* pull from list */
- if ((SCTP_BASE_INFO(ipi_count_raddr) == 0) || (prev == net)) {
+ TAILQ_FOREACH_SAFE(net, &asoc->nets, sctp_next, nnet) {
#ifdef INVARIANTS
+ if (SCTP_BASE_INFO(ipi_count_raddr) == 0) {
panic("no net's left alloc'ed, or list points to itself");
-#endif
- break;
}
- prev = net;
+#endif
TAILQ_REMOVE(&asoc->nets, net, sctp_next);
sctp_free_remote_addr(net);
}
-
- while (!LIST_EMPTY(&asoc->sctp_restricted_addrs)) {
+ LIST_FOREACH_SAFE(laddr, &asoc->sctp_restricted_addrs, sctp_nxt_addr, naddr) {
/* sa_ignore FREED_MEMORY */
- laddr = LIST_FIRST(&asoc->sctp_restricted_addrs);
sctp_remove_laddr(laddr);
}
/* pending asconf (address) parameters */
- while (!TAILQ_EMPTY(&asoc->asconf_queue)) {
+ TAILQ_FOREACH_SAFE(aparam, &asoc->asconf_queue, next, naparam) {
/* sa_ignore FREED_MEMORY */
- aparam = TAILQ_FIRST(&asoc->asconf_queue);
TAILQ_REMOVE(&asoc->asconf_queue, aparam, next);
SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
}
- while (!TAILQ_EMPTY(&asoc->asconf_ack_sent)) {
+ TAILQ_FOREACH_SAFE(aack, &asoc->asconf_ack_sent, next, naack) {
/* sa_ignore FREED_MEMORY */
- aack = TAILQ_FIRST(&asoc->asconf_ack_sent);
TAILQ_REMOVE(&asoc->asconf_ack_sent, aack, next);
if (aack->data != NULL) {
sctp_m_freem(aack->data);
@@ -5129,12 +5114,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_free_authinfo(&asoc->authinfo);
- shared_key = LIST_FIRST(&asoc->shared_keys);
- while (shared_key) {
+ LIST_FOREACH_SAFE(shared_key, &asoc->shared_keys, next, nshared_key) {
LIST_REMOVE(shared_key, next);
sctp_free_sharedkey(shared_key);
/* sa_ignore FREED_MEMORY */
- shared_key = LIST_FIRST(&asoc->shared_keys);
}
/* Insert new items here :> */
@@ -5231,13 +5214,21 @@ sctp_destination_is_reachable(struct sctp_tcb *stcb, struct sockaddr *destaddr)
return (1);
}
/* NOTE: all "scope" checks are done when local addresses are added */
- if (destaddr->sa_family == AF_INET6) {
+ switch (destaddr->sa_family) {
+#ifdef INET6
+ case AF_INET6:
answer = inp->ip_inp.inp.inp_vflag & INP_IPV6;
- } else if (destaddr->sa_family == AF_INET) {
+ break;
+#endif
+#ifdef INET
+ case AF_INET:
answer = inp->ip_inp.inp.inp_vflag & INP_IPV4;
- } else {
+ break;
+#endif
+ default:
/* invalid family, so it's unreachable */
answer = 0;
+ break;
}
return (answer);
}
@@ -5262,10 +5253,19 @@ sctp_update_ep_vflag(struct sctp_inpcb *inp)
if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
continue;
}
- if (laddr->ifa->address.sa.sa_family == AF_INET6) {
+ switch (laddr->ifa->address.sa.sa_family) {
+#ifdef INET6
+ case AF_INET6:
inp->ip_inp.inp.inp_vflag |= INP_IPV6;
- } else if (laddr->ifa->address.sa.sa_family == AF_INET) {
+ break;
+#endif
+#ifdef INET
+ case AF_INET:
inp->ip_inp.inp.inp_vflag |= INP_IPV4;
+ break;
+#endif
+ default:
+ break;
}
}
}
@@ -5286,12 +5286,14 @@ sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t ac
/* You are already bound to all. You have it already */
return;
}
+#ifdef INET6
if (ifa->address.sa.sa_family == AF_INET6) {
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
/* Can't bind a non-useable addr. */
return;
}
}
+#endif
/* first, is it already present? */
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (laddr->ifa == ifa) {
@@ -5307,10 +5309,19 @@ sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t ac
return;
inp->laddr_count++;
/* update inp_vflag flags */
- if (ifa->address.sa.sa_family == AF_INET6) {
+ switch (ifa->address.sa.sa_family) {
+#ifdef INET6
+ case AF_INET6:
inp->ip_inp.inp.inp_vflag |= INP_IPV6;
- } else if (ifa->address.sa.sa_family == AF_INET) {
+ break;
+#endif
+#ifdef INET
+ case AF_INET:
inp->ip_inp.inp.inp_vflag |= INP_IPV4;
+ break;
+#endif
+ default:
+ break;
}
}
return;
@@ -5428,7 +5439,6 @@ sctp_del_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa)
void
sctp_add_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa)
{
- struct sctp_inpcb *inp;
struct sctp_laddr *laddr;
struct sctpladdr *list;
@@ -5438,13 +5448,14 @@ sctp_add_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa)
*/
list = &stcb->asoc.sctp_restricted_addrs;
- inp = stcb->sctp_ep;
+#ifdef INET6
if (ifa->address.sa.sa_family == AF_INET6) {
if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
/* Can't bind a non-existent addr. */
return;
}
}
+#endif
/* does the address already exist? */
LIST_FOREACH(laddr, list, sctp_nxt_addr) {
if (laddr->ifa == ifa) {
@@ -5546,6 +5557,163 @@ sctp_del_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa)
static int sctp_max_number_of_assoc = SCTP_MAX_NUM_OF_ASOC;
static int sctp_scale_up_for_address = SCTP_SCALE_FOR_ADDR;
+
+
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+struct sctp_mcore_ctrl *sctp_mcore_workers = NULL;
+int *sctp_cpuarry = NULL;
+void
+sctp_queue_to_mcore(struct mbuf *m, int off, int cpu_to_use)
+{
+ /* Queue a packet to a processor for the specified core */
+ struct sctp_mcore_queue *qent;
+ struct sctp_mcore_ctrl *wkq;
+ int need_wake = 0;
+
+ if (sctp_mcore_workers == NULL) {
+ /* Something went way bad during setup */
+ sctp_input_with_port(m, off, 0);
+ return;
+ }
+ SCTP_MALLOC(qent, struct sctp_mcore_queue *,
+ (sizeof(struct sctp_mcore_queue)),
+ SCTP_M_MCORE);
+ if (qent == NULL) {
+ /* This is trouble */
+ sctp_input_with_port(m, off, 0);
+ return;
+ }
+ qent->vn = curvnet;
+ qent->m = m;
+ qent->off = off;
+ qent->v6 = 0;
+ wkq = &sctp_mcore_workers[cpu_to_use];
+ SCTP_MCORE_QLOCK(wkq);
+
+ TAILQ_INSERT_TAIL(&wkq->que, qent, next);
+ if (wkq->running == 0) {
+ need_wake = 1;
+ }
+ SCTP_MCORE_QUNLOCK(wkq);
+ if (need_wake) {
+ wakeup(&wkq->running);
+ }
+}
+
+static void
+sctp_mcore_thread(void *arg)
+{
+
+ struct sctp_mcore_ctrl *wkq;
+ struct sctp_mcore_queue *qent;
+
+ wkq = (struct sctp_mcore_ctrl *)arg;
+ struct mbuf *m;
+ int off, v6;
+
+ /* Wait for first tickle */
+ SCTP_MCORE_LOCK(wkq);
+ wkq->running = 0;
+ msleep(&wkq->running,
+ &wkq->core_mtx,
+ 0, "wait for pkt", 0);
+ SCTP_MCORE_UNLOCK(wkq);
+
+ /* Bind to our cpu */
+ thread_lock(curthread);
+ sched_bind(curthread, wkq->cpuid);
+ thread_unlock(curthread);
+
+ /* Now lets start working */
+ SCTP_MCORE_LOCK(wkq);
+ /* Now grab lock and go */
+ for (;;) {
+ SCTP_MCORE_QLOCK(wkq);
+skip_sleep:
+ wkq->running = 1;
+ qent = TAILQ_FIRST(&wkq->que);
+ if (qent) {
+ TAILQ_REMOVE(&wkq->que, qent, next);
+ SCTP_MCORE_QUNLOCK(wkq);
+ CURVNET_SET(qent->vn);
+ m = qent->m;
+ off = qent->off;
+ v6 = qent->v6;
+ SCTP_FREE(qent, SCTP_M_MCORE);
+ if (v6 == 0) {
+ sctp_input_with_port(m, off, 0);
+ } else {
+ SCTP_PRINTF("V6 not yet supported\n");
+ sctp_m_freem(m);
+ }
+ CURVNET_RESTORE();
+ SCTP_MCORE_QLOCK(wkq);
+ }
+ wkq->running = 0;
+ if (!TAILQ_EMPTY(&wkq->que)) {
+ goto skip_sleep;
+ }
+ SCTP_MCORE_QUNLOCK(wkq);
+ msleep(&wkq->running,
+ &wkq->core_mtx,
+ 0, "wait for pkt", 0);
+ }
+}
+
+static void
+sctp_startup_mcore_threads(void)
+{
+ int i, cpu;
+
+ if (mp_ncpus == 1)
+ return;
+
+ if (sctp_mcore_workers != NULL) {
+ /*
+ * Already been here in some previous vnet?
+ */
+ return;
+ }
+ SCTP_MALLOC(sctp_mcore_workers, struct sctp_mcore_ctrl *,
+ ((mp_maxid + 1) * sizeof(struct sctp_mcore_ctrl)),
+ SCTP_M_MCORE);
+ if (sctp_mcore_workers == NULL) {
+ /* TSNH I hope */
+ return;
+ }
+ memset(sctp_mcore_workers, 0, ((mp_maxid + 1) *
+ sizeof(struct sctp_mcore_ctrl)));
+ /* Init the structures */
+ for (i = 0; i <= mp_maxid; i++) {
+ TAILQ_INIT(&sctp_mcore_workers[i].que);
+ SCTP_MCORE_LOCK_INIT(&sctp_mcore_workers[i]);
+ SCTP_MCORE_QLOCK_INIT(&sctp_mcore_workers[i]);
+ sctp_mcore_workers[i].cpuid = i;
+ }
+ if (sctp_cpuarry == NULL) {
+ SCTP_MALLOC(sctp_cpuarry, int *,
+ (mp_ncpus * sizeof(int)),
+ SCTP_M_MCORE);
+ i = 0;
+ CPU_FOREACH(cpu) {
+ sctp_cpuarry[i] = cpu;
+ i++;
+ }
+ }
+ /* Now start them all */
+ CPU_FOREACH(cpu) {
+ (void)kproc_create(sctp_mcore_thread,
+ (void *)&sctp_mcore_workers[cpu],
+ &sctp_mcore_workers[cpu].thread_proc,
+ RFPROC,
+ SCTP_KTHREAD_PAGES,
+ SCTP_MCORE_NAME);
+
+ }
+}
+
+#endif
+
void
sctp_pcb_init()
{
@@ -5565,11 +5733,18 @@ sctp_pcb_init()
#if defined(SCTP_LOCAL_TRACE_BUF)
bzero(&SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log));
#endif
+#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
+ SCTP_MALLOC(SCTP_BASE_STATS, struct sctpstat *,
+ ((mp_maxid + 1) * sizeof(struct sctpstat)),
+ SCTP_M_MCORE);
+#endif
(void)SCTP_GETTIME_TIMEVAL(&tv);
#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
+ bzero(SCTP_BASE_STATS, (sizeof(struct sctpstat) * (mp_maxid + 1)));
SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_sec = (uint32_t) tv.tv_sec;
SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_usec = (uint32_t) tv.tv_usec;
#else
+ bzero(&SCTP_BASE_STATS, sizeof(struct sctpstat));
SCTP_BASE_STAT(sctps_discontinuitytime).tv_sec = (uint32_t) tv.tv_sec;
SCTP_BASE_STAT(sctps_discontinuitytime).tv_usec = (uint32_t) tv.tv_usec;
#endif
@@ -5676,13 +5851,16 @@ sctp_pcb_init()
sctp_startup_iterator();
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+ sctp_startup_mcore_threads();
+#endif
+
/*
* INIT the default VRF which for BSD is the only one, other O/S's
* may have more. But initially they must start with one and then
* add the VRF's as addresses are added.
*/
sctp_init_vrf_list(SCTP_DEFAULT_VRF);
-
}
/*
@@ -5692,12 +5870,12 @@ void
sctp_pcb_finish(void)
{
struct sctp_vrflist *vrf_bucket;
- struct sctp_vrf *vrf;
- struct sctp_ifn *ifn;
- struct sctp_ifa *ifa;
+ struct sctp_vrf *vrf, *nvrf;
+ struct sctp_ifn *ifn, *nifn;
+ struct sctp_ifa *ifa, *nifa;
struct sctpvtaghead *chain;
struct sctp_tagblock *twait_block, *prev_twait_block;
- struct sctp_laddr *wi;
+ struct sctp_laddr *wi, *nwi;
int i;
/*
@@ -5709,20 +5887,15 @@ sctp_pcb_finish(void)
struct sctp_iterator *it, *nit;
SCTP_IPI_ITERATOR_WQ_LOCK();
- it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
- while (it) {
- nit = TAILQ_NEXT(it, sctp_nxt_itr);
+ TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
if (it->vn != curvnet) {
- it = nit;
continue;
}
- TAILQ_REMOVE(&sctp_it_ctl.iteratorhead,
- it, sctp_nxt_itr);
+ TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
if (it->function_atend != NULL) {
(*it->function_atend) (it->pointer, it->val);
}
SCTP_FREE(it, SCTP_M_ITER);
- it = nit;
}
SCTP_IPI_ITERATOR_WQ_UNLOCK();
SCTP_ITERATOR_LOCK();
@@ -5735,7 +5908,7 @@ sctp_pcb_finish(void)
SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer));
SCTP_WQ_ADDR_LOCK();
- while ((wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq))) != NULL) {
+ LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
LIST_REMOVE(wi, sctp_nxt_addr);
SCTP_DECR_LADDR_COUNT();
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi);
@@ -5747,9 +5920,9 @@ sctp_pcb_finish(void)
* destroyed first).
*/
vrf_bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(SCTP_DEFAULT_VRFID & SCTP_BASE_INFO(hashvrfmark))];
- while ((vrf = LIST_FIRST(vrf_bucket)) != NULL) {
- while ((ifn = LIST_FIRST(&vrf->ifnlist)) != NULL) {
- while ((ifa = LIST_FIRST(&ifn->ifalist)) != NULL) {
+ LIST_FOREACH_SAFE(vrf, vrf_bucket, next_vrf, nvrf) {
+ LIST_FOREACH_SAFE(ifn, &vrf->ifnlist, next_ifn, nifn) {
+ LIST_FOREACH_SAFE(ifa, &ifn->ifalist, next_ifa, nifa) {
/* free the ifa */
LIST_REMOVE(ifa, next_bucket);
LIST_REMOVE(ifa, next_ifa);
@@ -5813,13 +5986,16 @@ sctp_pcb_finish(void)
SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_ephash), SCTP_BASE_INFO(hashmark));
if (SCTP_BASE_INFO(sctp_tcpephash) != NULL)
SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_tcpephash), SCTP_BASE_INFO(hashtcpmark));
-
+#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
+ SCTP_FREE(SCTP_BASE_STATS, SCTP_M_MCORE);
+#endif
}
int
sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
- int iphlen, int offset, int limit, struct sctphdr *sh,
+ int offset, int limit,
+ struct sockaddr *src, struct sockaddr *dst,
struct sockaddr *altsa)
{
/*
@@ -5829,17 +6005,12 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* with either INIT or INIT-ACK's as long as the m points to the IP
* packet and the offset points to the beginning of the parameters.
*/
- struct sctp_inpcb *inp, *l_inp;
- struct sctp_nets *net, *net_tmp;
- struct ip *iph;
+ struct sctp_inpcb *inp;
+ struct sctp_nets *net, *nnet, *net_tmp;
struct sctp_paramhdr *phdr, parm_buf;
struct sctp_tcb *stcb_tmp;
uint16_t ptype, plen;
struct sockaddr *sa;
- struct sockaddr_storage dest_store;
- struct sockaddr *local_sa = (struct sockaddr *)&dest_store;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
uint8_t random_store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_random *p_random = NULL;
uint16_t random_len = 0;
@@ -5854,91 +6025,71 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
sctp_key_t *new_key;
uint32_t keylen;
int got_random = 0, got_hmacs = 0, got_chklist = 0;
+ uint8_t ecn_allowed;
+
+#ifdef INET
+ struct sockaddr_in sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+
+#endif
/* First get the destination address setup too. */
+#ifdef INET
memset(&sin, 0, sizeof(sin));
- memset(&sin6, 0, sizeof(sin6));
-
sin.sin_family = AF_INET;
sin.sin_len = sizeof(sin);
sin.sin_port = stcb->rport;
-
+#endif
+#ifdef INET6
+ memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_port = stcb->rport;
- if (altsa == NULL) {
- iph = mtod(m, struct ip *);
- switch (iph->ip_v) {
- case IPVERSION:
- {
- /* its IPv4 */
- struct sockaddr_in *sin_2;
-
- sin_2 = (struct sockaddr_in *)(local_sa);
- memset(sin_2, 0, sizeof(sin));
- sin_2->sin_family = AF_INET;
- sin_2->sin_len = sizeof(sin);
- sin_2->sin_port = sh->dest_port;
- sin_2->sin_addr.s_addr = iph->ip_dst.s_addr;
- sin.sin_addr = iph->ip_src;
- sa = (struct sockaddr *)&sin;
- break;
- }
-#ifdef INET6
- case IPV6_VERSION >> 4:
- {
- /* its IPv6 */
- struct ip6_hdr *ip6;
- struct sockaddr_in6 *sin6_2;
-
- ip6 = mtod(m, struct ip6_hdr *);
- sin6_2 = (struct sockaddr_in6 *)(local_sa);
- memset(sin6_2, 0, sizeof(sin6));
- sin6_2->sin6_family = AF_INET6;
- sin6_2->sin6_len = sizeof(struct sockaddr_in6);
- sin6_2->sin6_port = sh->dest_port;
- sin6.sin6_addr = ip6->ip6_src;
- sa = (struct sockaddr *)&sin6;
- break;
- }
#endif
- default:
- return (-1);
- break;
- }
- } else {
- /*
- * For cookies we use the src address NOT from the packet
- * but from the original INIT
- */
+ if (altsa) {
sa = altsa;
+ } else {
+ sa = src;
}
/* Turn off ECN until we get through all params */
- stcb->asoc.ecn_allowed = 0;
+ ecn_allowed = 0;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
/* mark all addresses that we have currently on the list */
net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC;
}
/* does the source address already exist? if so skip it */
- l_inp = inp = stcb->sctp_ep;
-
+ inp = stcb->sctp_ep;
atomic_add_int(&stcb->asoc.refcnt, 1);
- stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net_tmp, local_sa, stcb);
+ stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net_tmp, dst, stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
if ((stcb_tmp == NULL && inp == stcb->sctp_ep) || inp == NULL) {
/* we must add the source address */
/* no scope set here since we have a tcb already. */
- if ((sa->sa_family == AF_INET) &&
- (stcb->asoc.ipv4_addr_legal)) {
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) {
- return (-1);
+ switch (sa->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (stcb->asoc.scope.ipv4_addr_legal) {
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) {
+ return (-1);
+ }
}
- } else if ((sa->sa_family == AF_INET6) &&
- (stcb->asoc.ipv6_addr_legal)) {
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) {
- return (-2);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (stcb->asoc.scope.ipv6_addr_legal) {
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) {
+ return (-2);
+ }
}
+ break;
+#endif
+ default:
+ break;
}
} else {
if (net_tmp != NULL && stcb_tmp == stcb) {
@@ -5966,8 +6117,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
ptype = ntohs(phdr->param_type);
plen = ntohs(phdr->param_length);
/*
- * printf("ptype => %0x, plen => %d\n", (uint32_t)ptype,
- * (int)plen);
+ * SCTP_PRINTF("ptype => %0x, plen => %d\n",
+ * (uint32_t)ptype, (int)plen);
*/
if (offset + plen > limit) {
break;
@@ -5975,8 +6126,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
if (plen == 0) {
break;
}
+#ifdef INET
if (ptype == SCTP_IPV4_ADDRESS) {
- if (stcb->asoc.ipv4_addr_legal) {
+ if (stcb->asoc.scope.ipv4_addr_legal) {
struct sctp_ipv4addr_param *p4, p4_buf;
/* ok get the v4 address and check/add */
@@ -6001,7 +6153,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
inp = stcb->sctp_ep;
atomic_add_int(&stcb->asoc.refcnt, 1);
stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net,
- local_sa, stcb);
+ dst, stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
if ((stcb_tmp == NULL && inp == stcb->sctp_ep) ||
@@ -6021,7 +6173,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
/* the assoc was freed? */
return (-7);
}
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_4)) {
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_4)) {
return (-8);
}
} else if (stcb_tmp == stcb) {
@@ -6046,7 +6198,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* abort this guy
*/
sctp_abort_an_association(stcb_tmp->sctp_ep,
- stcb_tmp, 1, NULL, 0);
+ stcb_tmp, NULL, SCTP_SO_NOT_LOCKED);
goto add_it_now;
}
SCTP_TCB_UNLOCK(stcb_tmp);
@@ -6058,8 +6210,11 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
return (-13);
}
}
- } else if (ptype == SCTP_IPV6_ADDRESS) {
- if (stcb->asoc.ipv6_addr_legal) {
+ } else
+#endif
+#ifdef INET6
+ if (ptype == SCTP_IPV6_ADDRESS) {
+ if (stcb->asoc.scope.ipv6_addr_legal) {
/* ok get the v6 address and check/add */
struct sctp_ipv6addr_param *p6, p6_buf;
@@ -6088,7 +6243,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
inp = stcb->sctp_ep;
atomic_add_int(&stcb->asoc.refcnt, 1);
stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net,
- local_sa, stcb);
+ dst, stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
if (stcb_tmp == NULL &&
(inp == stcb->sctp_ep || inp == NULL)) {
@@ -6105,7 +6260,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* we must add the address, no scope
* set
*/
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_5)) {
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_5)) {
return (-17);
}
} else if (stcb_tmp == stcb) {
@@ -6134,7 +6289,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* abort this guy
*/
sctp_abort_an_association(stcb_tmp->sctp_ep,
- stcb_tmp, 1, NULL, 0);
+ stcb_tmp, NULL, SCTP_SO_NOT_LOCKED);
goto add_it_now6;
}
SCTP_TCB_UNLOCK(stcb_tmp);
@@ -6146,8 +6301,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
return (-22);
}
}
- } else if (ptype == SCTP_ECN_CAPABLE) {
- stcb->asoc.ecn_allowed = 1;
+ } else
+#endif
+ if (ptype == SCTP_ECN_CAPABLE) {
+ ecn_allowed = 1;
} else if (ptype == SCTP_ULP_ADAPTATION) {
if (stcb->asoc.state != SCTP_STATE_OPEN) {
struct sctp_adaptation_layer_indication ai,
@@ -6163,10 +6320,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
} else if (ptype == SCTP_SET_PRIM_ADDR) {
struct sctp_asconf_addr_param lstore, *fee;
- struct sctp_asconf_addrv4_param *fii;
int lptype;
struct sockaddr *lsa = NULL;
+#ifdef INET
+ struct sctp_asconf_addrv4_param *fii;
+
+#endif
+
stcb->asoc.peer_supports_asconf = 1;
if (plen > sizeof(lstore)) {
return (-23);
@@ -6179,7 +6340,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
fee = (struct sctp_asconf_addr_param *)phdr;
lptype = ntohs(fee->addrp.ph.param_type);
- if (lptype == SCTP_IPV4_ADDRESS) {
+ switch (lptype) {
+#ifdef INET
+ case SCTP_IPV4_ADDRESS:
if (plen !=
sizeof(struct sctp_asconf_addrv4_param)) {
SCTP_PRINTF("Sizeof setprim in init/init ack not %d but %d - ignored\n",
@@ -6190,7 +6353,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
sin.sin_addr.s_addr = fii->addrp.addr;
lsa = (struct sockaddr *)&sin;
}
- } else if (lptype == SCTP_IPV6_ADDRESS) {
+ break;
+#endif
+#ifdef INET6
+ case SCTP_IPV6_ADDRESS:
if (plen !=
sizeof(struct sctp_asconf_addr_param)) {
SCTP_PRINTF("Sizeof setprim (v6) in init/init ack not %d but %d - ignored\n",
@@ -6202,6 +6368,10 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
sizeof(fee->addrp.addr));
lsa = (struct sockaddr *)&sin6;
}
+ break;
+#endif
+ default:
+ break;
}
if (lsa) {
(void)sctp_set_primary_addr(stcb, sa, NULL);
@@ -6257,10 +6427,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
}
- } else if (ptype == SCTP_ECN_NONCE_SUPPORTED) {
- /* Peer supports ECN-nonce */
- stcb->asoc.peer_supports_ecn_nonce = 1;
- stcb->asoc.ecn_nonce_allowed = 1;
} else if (ptype == SCTP_RANDOM) {
if (plen > sizeof(random_store))
break;
@@ -6376,8 +6542,7 @@ next_param:
sizeof(parm_buf));
}
/* Now check to see if we need to purge any addresses */
- for (net = TAILQ_FIRST(&stcb->asoc.nets); net != NULL; net = net_tmp) {
- net_tmp = TAILQ_NEXT(net, sctp_next);
+ TAILQ_FOREACH_SAFE(net, &stcb->asoc.nets, sctp_next, nnet) {
if ((net->dest_state & SCTP_ADDR_NOT_IN_ASSOC) ==
SCTP_ADDR_NOT_IN_ASSOC) {
/* This address has been removed from the asoc */
@@ -6391,6 +6556,9 @@ next_param:
}
}
}
+ if (ecn_allowed == 0) {
+ stcb->asoc.ecn_allowed = 0;
+ }
/* validate authentication required parameters */
if (got_random && got_hmacs) {
stcb->asoc.peer_supports_auth = 1;
@@ -6464,7 +6632,10 @@ sctp_set_primary_addr(struct sctp_tcb *stcb, struct sockaddr *sa,
return (0);
}
stcb->asoc.primary_destination = net;
- net->dest_state &= ~SCTP_ADDR_WAS_PRIMARY;
+ if (!(net->dest_state & SCTP_ADDR_PF) && (stcb->asoc.alternate)) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
net = TAILQ_FIRST(&stcb->asoc.nets);
if (net != stcb->asoc.primary_destination) {
/*
@@ -6480,7 +6651,7 @@ sctp_set_primary_addr(struct sctp_tcb *stcb, struct sockaddr *sa,
}
int
-sctp_is_vtag_good(struct sctp_inpcb *inp, uint32_t tag, uint16_t lport, uint16_t rport, struct timeval *now, int save_in_twait)
+sctp_is_vtag_good(uint32_t tag, uint16_t lport, uint16_t rport, struct timeval *now)
{
/*
* This function serves two purposes. It will see if a TAG can be
@@ -6559,13 +6730,8 @@ skip_vtag_check:
return (1);
}
-
-static sctp_assoc_t reneged_asoc_ids[256];
-static uint8_t reneged_at = 0;
-
-
static void
-sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
+sctp_drain_mbufs(struct sctp_tcb *stcb)
{
/*
* We must hunt this association for MBUF's past the cumack (i.e.
@@ -6590,12 +6756,8 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
cumulative_tsn_p1 = asoc->cumulative_tsn + 1;
cnt = 0;
/* First look in the re-assembly queue */
- chk = TAILQ_FIRST(&asoc->reasmqueue);
- while (chk) {
- /* Get the next one */
- nchk = TAILQ_NEXT(chk, sctp_next);
- if (compare_with_wrap(chk->rec.data.TSN_seq,
- cumulative_tsn_p1, MAX_TSN)) {
+ TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
+ if (SCTP_TSN_GT(chk->rec.data.TSN_seq, cumulative_tsn_p1)) {
/* Yep it is above cum-ack */
cnt++;
SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.TSN_seq, asoc->mapping_array_base_tsn);
@@ -6607,17 +6769,13 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
sctp_m_freem(chk->data);
chk->data = NULL;
}
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
}
- chk = nchk;
}
/* Ok that was fun, now we will drain all the inbound streams? */
for (strmat = 0; strmat < asoc->streamincnt; strmat++) {
- ctl = TAILQ_FIRST(&asoc->strmin[strmat].inqueue);
- while (ctl) {
- nctl = TAILQ_NEXT(ctl, next);
- if (compare_with_wrap(ctl->sinfo_tsn,
- cumulative_tsn_p1, MAX_TSN)) {
+ TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].inqueue, next, nctl) {
+ if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) {
/* Yep it is above cum-ack */
cnt++;
SCTP_CALC_TSN_TO_GAP(gap, ctl->sinfo_tsn, asoc->mapping_array_base_tsn);
@@ -6633,14 +6791,11 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl);
SCTP_DECR_READQ_COUNT();
}
- ctl = nctl;
}
}
if (cnt) {
/* We must back down to see what the new highest is */
- for (i = asoc->highest_tsn_inside_map;
- (compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN) || (i == asoc->mapping_array_base_tsn));
- i--) {
+ for (i = asoc->highest_tsn_inside_map; SCTP_TSN_GE(i, asoc->mapping_array_base_tsn); i--) {
SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn);
if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
asoc->highest_tsn_inside_map = i;
@@ -6677,10 +6832,8 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
asoc->last_revoke_count = cnt;
(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
/* sa_ignore NO_NULL_CHK */
- sctp_send_sack(stcb);
+ sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_DRAIN, SCTP_SO_NOT_LOCKED);
- reneged_asoc_ids[reneged_at] = sctp_get_associd(stcb);
- reneged_at++;
}
/*
* Another issue, in un-setting the TSN's in the mapping array we
@@ -6723,7 +6876,7 @@ sctp_drain()
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
/* For each association */
SCTP_TCB_LOCK(stcb);
- sctp_drain_mbufs(inp, stcb);
+ sctp_drain_mbufs(stcb);
SCTP_TCB_UNLOCK(stcb);
}
SCTP_INP_RUNLOCK(inp);
diff --git a/freebsd/sys/netinet/sctp_pcb.h b/freebsd/sys/netinet/sctp_pcb.h
index 23ebc4f1..91807c7c 100644
--- a/freebsd/sys/netinet/sctp_pcb.h
+++ b/freebsd/sys/netinet/sctp_pcb.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,13 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_pcb.h,v 1.21 2005/07/16 01:18:47 suz Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_pcb_h__
-#define __sctp_pcb_h__
+#ifndef _NETINET_SCTP_PCB_H_
+#define _NETINET_SCTP_PCB_H_
#include <netinet/sctp_os.h>
#include <netinet/sctp.h>
@@ -144,7 +144,12 @@ struct sctp_tagblock {
struct sctp_epinfo {
- struct socket *udp_tun_socket;
+#ifdef INET
+ struct socket *udp4_tun_socket;
+#endif
+#ifdef INET6
+ struct socket *udp6_tun_socket;
+#endif
struct sctpasochead *sctp_asochash;
u_long hashasocmark;
@@ -240,7 +245,7 @@ struct sctp_base_info {
*/
struct sctp_epinfo sctppcbinfo;
#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
- struct sctpstat sctpstat[MAXCPU];
+ struct sctpstat *sctpstat;
#else
struct sctpstat sctpstat;
#endif
@@ -276,6 +281,7 @@ struct sctp_pcb {
uint32_t sctp_sws_receiver;
uint32_t sctp_default_cc_module;
+ uint32_t sctp_default_ss_module;
/* authentication related fields */
struct sctp_keyhead shared_keys;
sctp_auth_chklist_t *local_auth_chunks;
@@ -291,6 +297,8 @@ struct sctp_pcb {
uint16_t def_net_failure;
+ uint16_t def_net_pf_threshold;
+
/* number of streams to pre-open on a association */
uint16_t pre_open_stream_count;
uint16_t max_open_streams_intome;
@@ -315,10 +323,17 @@ struct sctp_pcb {
int auto_close_time;
uint32_t initial_sequence_debug;
uint32_t adaptation_layer_indicator;
+ uint8_t adaptation_layer_indicator_provided;
uint32_t store_at;
- uint8_t max_burst;
+ uint32_t max_burst;
+ uint32_t fr_max_burst;
+#ifdef INET6
+ uint32_t default_flowlabel;
+#endif
+ uint8_t default_dscp;
char current_secret_number;
char last_secret_number;
+ uint16_t port; /* remote UDP encapsulation port */
};
#ifndef SCTP_ALIGNMENT
@@ -389,7 +404,9 @@ struct sctp_inpcb {
uint32_t sctp_frag_point;
uint32_t partial_delivery_point;
uint32_t sctp_context;
+ uint8_t local_strreset_support;
uint32_t sctp_cmt_on_off;
+ uint32_t sctp_ecn_enable;
struct sctp_nonpad_sndrcvinfo def_send;
/*-
* These three are here for the sosend_dgram
@@ -516,7 +533,8 @@ sctp_inpcb_bind(struct socket *, struct sockaddr *,
struct sctp_ifa *, struct thread *);
struct sctp_tcb *
-sctp_findassociation_addr(struct mbuf *, int, int,
+sctp_findassociation_addr(struct mbuf *, int,
+ struct sockaddr *, struct sockaddr *,
struct sctphdr *, struct sctp_chunkhdr *, struct sctp_inpcb **,
struct sctp_nets **, uint32_t vrf_id);
@@ -547,7 +565,7 @@ sctp_findassociation_ep_asocid(struct sctp_inpcb *,
sctp_assoc_t, int);
struct sctp_tcb *
-sctp_findassociation_ep_asconf(struct mbuf *, int, int,
+sctp_findassociation_ep_asconf(struct mbuf *, int, struct sockaddr *,
struct sctphdr *, struct sctp_inpcb **, struct sctp_nets **, uint32_t vrf_id);
int sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id);
@@ -578,7 +596,7 @@ void sctp_remove_laddr(struct sctp_laddr *);
void sctp_del_local_addr_ep(struct sctp_inpcb *, struct sctp_ifa *);
-int sctp_add_remote_addr(struct sctp_tcb *, struct sockaddr *, int, int);
+int sctp_add_remote_addr(struct sctp_tcb *, struct sockaddr *, struct sctp_nets **, int, int);
void sctp_remove_net(struct sctp_tcb *, struct sctp_nets *);
@@ -593,13 +611,13 @@ void sctp_del_local_addr_restricted(struct sctp_tcb *, struct sctp_ifa *);
int
sctp_load_addresses_from_init(struct sctp_tcb *, struct mbuf *, int, int,
- int, struct sctphdr *, struct sockaddr *);
+ struct sockaddr *, struct sockaddr *, struct sockaddr *);
int
sctp_set_primary_addr(struct sctp_tcb *, struct sockaddr *,
struct sctp_nets *);
-int sctp_is_vtag_good(struct sctp_inpcb *, uint32_t, uint16_t lport, uint16_t rport, struct timeval *, int);
+int sctp_is_vtag_good(uint32_t, uint16_t lport, uint16_t rport, struct timeval *);
/* void sctp_drain(void); */
@@ -622,6 +640,12 @@ sctp_initiate_iterator(inp_func inpf,
struct sctp_inpcb *,
uint8_t co_off);
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+void
+ sctp_queue_to_mcore(struct mbuf *m, int off, int cpu_to_use);
+
+#endif
+
#ifdef INVARIANTS
void
sctp_validate_no_locks(struct sctp_inpcb *inp);
diff --git a/freebsd/sys/netinet/sctp_peeloff.c b/freebsd/sys/netinet/sctp_peeloff.c
index bc5f8a4f..13b55be4 100644
--- a/freebsd/sys/netinet/sctp_peeloff.c
+++ b/freebsd/sys/netinet/sctp_peeloff.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,11 +32,9 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-/* $KAME: sctp_peeloff.c,v 1.13 2005/03/06 16:04:18 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+
#include <netinet/sctp_os.h>
#include <netinet/sctp_pcb.h>
#include <netinet/sctputil.h>
@@ -55,11 +55,20 @@ sctp_can_peel_off(struct socket *head, sctp_assoc_t assoc_id)
struct sctp_tcb *stcb;
uint32_t state;
+ if (head == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EBADF);
+ return (EBADF);
+ }
inp = (struct sctp_inpcb *)head->so_pcb;
if (inp == NULL) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
return (EFAULT);
}
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EOPNOTSUPP);
+ return (EOPNOTSUPP);
+ }
stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
if (stcb == NULL) {
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOENT);
@@ -67,9 +76,7 @@ sctp_can_peel_off(struct socket *head, sctp_assoc_t assoc_id)
}
state = SCTP_GET_STATE((&stcb->asoc));
if ((state == SCTP_STATE_EMPTY) ||
- (state == SCTP_STATE_INUSE) ||
- (state == SCTP_STATE_COOKIE_WAIT) ||
- (state == SCTP_STATE_COOKIE_ECHOED)) {
+ (state == SCTP_STATE_INUSE)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
@@ -98,9 +105,7 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
}
state = SCTP_GET_STATE((&stcb->asoc));
if ((state == SCTP_STATE_EMPTY) ||
- (state == SCTP_STATE_INUSE) ||
- (state == SCTP_STATE_COOKIE_WAIT) ||
- (state == SCTP_STATE_COOKIE_ECHOED)) {
+ (state == SCTP_STATE_INUSE)) {
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
@@ -115,8 +120,10 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
n_inp->sctp_mobility_features = inp->sctp_mobility_features;
n_inp->sctp_frag_point = inp->sctp_frag_point;
n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
+ n_inp->sctp_ecn_enable = inp->sctp_ecn_enable;
n_inp->partial_delivery_point = inp->partial_delivery_point;
n_inp->sctp_context = inp->sctp_context;
+ n_inp->local_strreset_support = inp->local_strreset_support;
n_inp->inp_starting_point_for_iterator = NULL;
/* copy in the authentication parameters from the original endpoint */
if (n_inp->sctp_ep.local_hmacs)
@@ -142,99 +149,3 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
return (0);
}
-
-
-struct socket *
-sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
-{
- struct socket *newso;
- struct sctp_inpcb *inp, *n_inp;
- struct sctp_tcb *stcb;
-
- SCTPDBG(SCTP_DEBUG_PEEL1, "SCTP peel-off called\n");
- inp = (struct sctp_inpcb *)head->so_pcb;
- if (inp == NULL) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
- *error = EFAULT;
- return (NULL);
- }
- stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
- if (stcb == NULL) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
- *error = ENOTCONN;
- return (NULL);
- }
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- newso = sonewconn(head, SS_ISCONNECTED
- );
- if (newso == NULL) {
- SCTPDBG(SCTP_DEBUG_PEEL1, "sctp_peeloff:sonewconn failed\n");
- SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOMEM);
- *error = ENOMEM;
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- return (NULL);
-
- }
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- n_inp = (struct sctp_inpcb *)newso->so_pcb;
- SOCK_LOCK(head);
- n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
- SCTP_PCB_FLAGS_CONNECTED |
- SCTP_PCB_FLAGS_IN_TCPPOOL | /* Turn on Blocking IO */
- (SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
- n_inp->sctp_features = inp->sctp_features;
- n_inp->sctp_frag_point = inp->sctp_frag_point;
- n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
- n_inp->partial_delivery_point = inp->partial_delivery_point;
- n_inp->sctp_context = inp->sctp_context;
- n_inp->inp_starting_point_for_iterator = NULL;
-
- /* copy in the authentication parameters from the original endpoint */
- if (n_inp->sctp_ep.local_hmacs)
- sctp_free_hmaclist(n_inp->sctp_ep.local_hmacs);
- n_inp->sctp_ep.local_hmacs =
- sctp_copy_hmaclist(inp->sctp_ep.local_hmacs);
- if (n_inp->sctp_ep.local_auth_chunks)
- sctp_free_chunklist(n_inp->sctp_ep.local_auth_chunks);
- n_inp->sctp_ep.local_auth_chunks =
- sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks);
- (void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys,
- &n_inp->sctp_ep.shared_keys);
-
- n_inp->sctp_socket = newso;
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
- sctp_feature_off(n_inp, SCTP_PCB_FLAGS_AUTOCLOSE);
- n_inp->sctp_ep.auto_close_time = 0;
- sctp_timer_stop(SCTP_TIMER_TYPE_AUTOCLOSE, n_inp, stcb, NULL,
- SCTP_FROM_SCTP_PEELOFF + SCTP_LOC_1);
- }
- /* Turn off any non-blocking semantic. */
- SCTP_CLEAR_SO_NBIO(newso);
- newso->so_state |= SS_ISCONNECTED;
- /* We remove it right away */
-
-#ifdef SCTP_LOCK_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
- sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
- }
-#endif
- TAILQ_REMOVE(&head->so_comp, newso, so_list);
- head->so_qlen--;
- SOCK_UNLOCK(head);
- /*
- * Now we must move it from one hash table to another and get the
- * stcb in the right place.
- */
- sctp_move_pcb_and_assoc(inp, n_inp, stcb);
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- /*
- * And now the final hack. We move data in the pending side i.e.
- * head to the new socket buffer. Let the GRUBBING begin :-0
- */
- sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- return (newso);
-}
diff --git a/freebsd/sys/netinet/sctp_peeloff.h b/freebsd/sys/netinet/sctp_peeloff.h
index db61db3b..dd905676 100644
--- a/freebsd/sys/netinet/sctp_peeloff.h
+++ b/freebsd/sys/netinet/sctp_peeloff.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,25 +30,14 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_peeloff.h,v 1.6 2005/03/06 16:04:18 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_peeloff_h__
-#define __sctp_peeloff_h__
-
-
-
-
+#ifndef _NETINET_SCTP_PEELOFF_H_
+#define _NETINET_SCTP_PEELOFF_H_
#if defined(_KERNEL)
-
int sctp_can_peel_off(struct socket *, sctp_assoc_t);
int sctp_do_peeloff(struct socket *, struct socket *, sctp_assoc_t);
-struct socket *sctp_get_peeloff(struct socket *, sctp_assoc_t, int *);
-
-
#endif /* _KERNEL */
-
-#endif
+#endif /* _NETINET_SCTP_PEELOFF_H_ */
diff --git a/freebsd/sys/netinet/sctp_structs.h b/freebsd/sys/netinet/sctp_structs.h
index 94d0395c..abecdabd 100644
--- a/freebsd/sys/netinet/sctp_structs.h
+++ b/freebsd/sys/netinet/sctp_structs.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,13 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_structs.h,v 1.13 2005/03/06 16:04:18 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_structs_h__
-#define __sctp_structs_h__
+#ifndef _NETINET_SCTP_STRUCTS_H_
+#define _NETINET_SCTP_STRUCTS_H_
#include <netinet/sctp_os.h>
#include <netinet/sctp_header.h>
@@ -77,8 +77,8 @@ TAILQ_HEAD(sctpnetlisthead, sctp_nets);
struct sctp_stream_reset_list {
TAILQ_ENTRY(sctp_stream_reset_list) next_resp;
uint32_t tsn;
- int number_entries;
- struct sctp_stream_reset_out_request req;
+ uint32_t number_entries;
+ uint16_t list_of_streams[];
};
TAILQ_HEAD(sctp_resethead, sctp_stream_reset_list);
@@ -106,6 +106,31 @@ typedef void (*asoc_func) (struct sctp_inpcb *, struct sctp_tcb *, void *ptr,
typedef int (*inp_func) (struct sctp_inpcb *, void *ptr, uint32_t val);
typedef void (*end_func) (void *ptr, uint32_t val);
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+/* whats on the mcore control struct */
+struct sctp_mcore_queue {
+ TAILQ_ENTRY(sctp_mcore_queue) next;
+ struct vnet *vn;
+ struct mbuf *m;
+ int off;
+ int v6;
+};
+
+TAILQ_HEAD(sctp_mcore_qhead, sctp_mcore_queue);
+
+struct sctp_mcore_ctrl {
+ SCTP_PROCESS_STRUCT thread_proc;
+ struct sctp_mcore_qhead que;
+ struct mtx core_mtx;
+ struct mtx que_mtx;
+ int running;
+ int cpuid;
+};
+
+
+#endif
+
+
struct sctp_iterator {
TAILQ_ENTRY(sctp_iterator) sctp_nxt_itr;
struct vnet *vn;
@@ -158,9 +183,8 @@ struct iterator_control {
uint32_t iterator_flags;
};
-#define SCTP_ITERATOR_MUST_EXIT 0x00000001
-#define SCTP_ITERATOR_STOP_CUR_IT 0x00000002
-#define SCTP_ITERATOR_STOP_CUR_INP 0x00000004
+#define SCTP_ITERATOR_STOP_CUR_IT 0x00000004
+#define SCTP_ITERATOR_STOP_CUR_INP 0x00000008
struct sctp_net_route {
sctp_rtentry_t *ro_rt;
@@ -192,6 +216,29 @@ struct htcp {
uint32_t lasttime;
};
+struct rtcc_cc {
+ struct timeval tls; /* The time we started the sending */
+ uint64_t lbw; /* Our last estimated bw */
+ uint64_t lbw_rtt; /* RTT at bw estimate */
+ uint64_t bw_bytes; /* The total bytes since this sending began */
+ uint64_t bw_tot_time; /* The total time since sending began */
+ uint64_t new_tot_time; /* temp holding the new value */
+ uint64_t bw_bytes_at_last_rttc; /* What bw_bytes was at last rtt calc */
+ uint32_t cwnd_at_bw_set;/* Cwnd at last bw saved - lbw */
+ uint32_t vol_reduce; /* cnt of voluntary reductions */
+ uint16_t steady_step; /* The number required to be in steady state */
+ uint16_t step_cnt; /* The current number */
+ uint8_t ret_from_eq; /* When all things are equal what do I return
+ * 0/1 - 1 no cc advance */
+ uint8_t use_dccc_ecn; /* Flag to enable DCCC ECN */
+ uint8_t tls_needs_set; /* Flag to indicate we need to set tls 0 or 1
+ * means set at send 2 not */
+ uint8_t last_step_state;/* Last state if steady state stepdown is on */
+ uint8_t rtt_set_this_sack; /* Flag saying this sack had RTT calc
+ * on it */
+ uint8_t last_inst_ind; /* Last saved inst indication */
+};
+
struct sctp_nets {
TAILQ_ENTRY(sctp_nets) sctp_next; /* next link */
@@ -201,6 +248,7 @@ struct sctp_nets {
* structure shared by all.
*/
struct sctp_timer pmtu_timer;
+ struct sctp_timer hb_timer;
/*
* The following two in combination equate to a route entry for v6
@@ -211,19 +259,25 @@ struct sctp_nets {
/* mtu discovered so far */
uint32_t mtu;
uint32_t ssthresh; /* not sure about this one for split */
-
+ uint32_t last_cwr_tsn;
+ uint32_t cwr_window_tsn;
+ uint32_t ecn_ce_pkt_cnt;
+ uint32_t lost_cnt;
/* smoothed average things for RTT and RTO itself */
int lastsa;
int lastsv;
- int rtt; /* last measured rtt value in ms */
+ uint64_t rtt; /* last measured rtt value in us */
unsigned int RTO;
/* This is used for SHUTDOWN/SHUTDOWN-ACK/SEND or INIT timers */
struct sctp_timer rxt_timer;
- struct sctp_timer fr_timer; /* for early fr */
/* last time in seconds I sent to it */
struct timeval last_sent_time;
+ union cc_control_data {
+ struct htcp htcp_ca; /* JRS - struct used in HTCP algorithm */
+ struct rtcc_cc rtcc; /* rtcc module cc stuff */
+ } cc_mod;
int ref_count;
/* Congestion stats per destination */
@@ -234,8 +288,9 @@ struct sctp_nets {
uint32_t flight_size;
uint32_t cwnd; /* actual cwnd */
uint32_t prev_cwnd; /* cwnd before any processing */
+ uint32_t ecn_prev_cwnd; /* ECN prev cwnd at first ecn_echo seen in new
+ * window */
uint32_t partial_bytes_acked; /* in CA tracks when to incr a MTU */
- uint32_t prev_rtt;
/* tracking variables to avoid the aloc/free in sack processing */
unsigned int net_ack;
unsigned int net_ack2;
@@ -263,19 +318,24 @@ struct sctp_nets {
uint32_t fast_recovery_tsn;
uint32_t heartbeat_random1;
uint32_t heartbeat_random2;
- uint32_t tos_flowlabel;
+#ifdef INET6
+ uint32_t flowlabel;
+#endif
+ uint8_t dscp;
struct timeval start_time; /* time when this net was created */
-
uint32_t marked_retrans;/* number or DATA chunks marked for timer
* based retransmissions */
uint32_t marked_fastretrans;
+ uint32_t heart_beat_delay; /* Heart Beat delay in ms */
/* if this guy is ok or not ... status */
uint16_t dest_state;
- /* number of transmit failures to down this guy */
+ /* number of timeouts to consider the destination unreachable */
uint16_t failure_threshold;
- /* error stats on destination */
+ /* number of timeouts to consider the destination potentially failed */
+ uint16_t pf_threshold;
+ /* error stats on the destination */
uint16_t error_count;
/* UDP port number in case of UDP tunneling */
uint16_t port;
@@ -315,8 +375,12 @@ struct sctp_nets {
uint8_t window_probe; /* Doing a window probe? */
uint8_t RTO_measured; /* Have we done the first measure */
uint8_t last_hs_used; /* index into the last HS table entry we used */
- /* JRS - struct used in HTCP algorithm */
- struct htcp htcp_ca;
+ uint8_t lan_type;
+ uint8_t rto_needed;
+ uint32_t flowid;
+#ifdef INVARIANTS
+ uint8_t flowidset;
+#endif
};
@@ -326,10 +390,7 @@ struct sctp_data_chunkrec {
uint16_t stream_number; /* the stream number of this guy */
uint32_t payloadtype;
uint32_t context; /* from send */
-
- /* ECN Nonce: Nonce Value for this chunk */
- uint8_t ect_nonce;
- uint8_t fwd_tsn_cnt;
+ uint32_t cwnd_at_send;
/*
* part of the Highest sacked algorithm to be able to stroke counts
* on ones that are FR'd.
@@ -341,6 +402,7 @@ struct sctp_data_chunkrec {
* outbound holds sending flags for PR-SCTP. */
uint8_t state_flags;
uint8_t chunk_was_revoked;
+ uint8_t fwd_tsn_cnt;
};
TAILQ_HEAD(sctpchunk_listhead, sctp_tmit_chunk);
@@ -350,7 +412,7 @@ TAILQ_HEAD(sctpchunk_listhead, sctp_tmit_chunk);
#define CHUNK_FLAGS_PR_SCTP_BUF SCTP_PR_SCTP_BUF
#define CHUNK_FLAGS_PR_SCTP_RTX SCTP_PR_SCTP_RTX
-/* The upper byte is used a a bit mask */
+/* The upper byte is used as a bit mask */
#define CHUNK_FLAGS_FRAGMENT_OK 0x0100
struct chk_id {
@@ -446,13 +508,13 @@ struct sctp_stream_queue_pending {
struct timeval ts;
struct sctp_nets *net;
TAILQ_ENTRY(sctp_stream_queue_pending) next;
+ TAILQ_ENTRY(sctp_stream_queue_pending) ss_next;
uint32_t length;
uint32_t timetolive;
uint32_t ppid;
uint32_t context;
uint16_t sinfo_flags;
uint16_t stream;
- uint16_t strseq;
uint16_t act_flags;
uint16_t auth_keyid;
uint8_t holds_key_ref;
@@ -476,13 +538,57 @@ struct sctp_stream_in {
uint8_t delivery_started;
};
-/* This struct is used to track the traffic on outbound streams */
TAILQ_HEAD(sctpwheel_listhead, sctp_stream_out);
+TAILQ_HEAD(sctplist_listhead, sctp_stream_queue_pending);
+
+/* Round-robin schedulers */
+struct ss_rr {
+ /* next link in wheel */
+ TAILQ_ENTRY(sctp_stream_out) next_spoke;
+};
+
+/* Priority scheduler */
+struct ss_prio {
+ /* next link in wheel */
+ TAILQ_ENTRY(sctp_stream_out) next_spoke;
+ /* priority id */
+ uint16_t priority;
+};
+
+/* Fair Bandwidth scheduler */
+struct ss_fb {
+ /* next link in wheel */
+ TAILQ_ENTRY(sctp_stream_out) next_spoke;
+ /* stores message size */
+ int32_t rounds;
+};
+
+/*
+ * This union holds all data necessary for
+ * different stream schedulers.
+ */
+union scheduling_data {
+ struct sctpwheel_listhead out_wheel;
+ struct sctplist_listhead out_list;
+};
+
+/*
+ * This union holds all parameters per stream
+ * necessary for different stream schedulers.
+ */
+union scheduling_parameters {
+ struct ss_rr rr;
+ struct ss_prio prio;
+ struct ss_fb fb;
+};
+
+/* This struct is used to track the traffic on outbound streams */
struct sctp_stream_out {
struct sctp_streamhead outqueue;
- TAILQ_ENTRY(sctp_stream_out) next_spoke; /* next link in wheel */
+ union scheduling_parameters ss_params;
+ uint32_t chunks_on_queues;
uint16_t stream_no;
- uint16_t next_sequence_sent; /* next one I expect to send out */
+ uint16_t next_sequence_send; /* next one I expect to send out */
uint8_t last_msg_incomplete;
};
@@ -544,6 +650,8 @@ struct sctp_nonpad_sndrcvinfo {
uint32_t sinfo_tsn;
uint32_t sinfo_cumtsn;
sctp_assoc_t sinfo_assoc_id;
+ uint16_t sinfo_keynumber;
+ uint16_t sinfo_keynumber_valid;
};
/*
@@ -556,19 +664,55 @@ struct sctp_cc_functions {
void (*sctp_cwnd_update_after_sack) (struct sctp_tcb *stcb,
struct sctp_association *asoc,
int accum_moved, int reneged_all, int will_exit);
+ void (*sctp_cwnd_update_exit_pf) (struct sctp_tcb *stcb, struct sctp_nets *net);
void (*sctp_cwnd_update_after_fr) (struct sctp_tcb *stcb,
struct sctp_association *asoc);
void (*sctp_cwnd_update_after_timeout) (struct sctp_tcb *stcb,
struct sctp_nets *net);
void (*sctp_cwnd_update_after_ecn_echo) (struct sctp_tcb *stcb,
- struct sctp_nets *net);
+ struct sctp_nets *net, int in_window, int num_pkt_lost);
void (*sctp_cwnd_update_after_packet_dropped) (struct sctp_tcb *stcb,
struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
uint32_t * bottle_bw, uint32_t * on_queue);
void (*sctp_cwnd_update_after_output) (struct sctp_tcb *stcb,
struct sctp_nets *net, int burst_limit);
- void (*sctp_cwnd_update_after_fr_timer) (struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, struct sctp_nets *net);
+ void (*sctp_cwnd_update_packet_transmitted) (struct sctp_tcb *stcb,
+ struct sctp_nets *net);
+ void (*sctp_cwnd_update_tsn_acknowledged) (struct sctp_nets *net,
+ struct sctp_tmit_chunk *);
+ void (*sctp_cwnd_new_transmission_begins) (struct sctp_tcb *stcb,
+ struct sctp_nets *net);
+ void (*sctp_cwnd_prepare_net_for_sack) (struct sctp_tcb *stcb,
+ struct sctp_nets *net);
+ int (*sctp_cwnd_socket_option) (struct sctp_tcb *stcb, int set, struct sctp_cc_option *);
+ void (*sctp_rtt_calculated) (struct sctp_tcb *, struct sctp_nets *, struct timeval *);
+};
+
+/*
+ * RS - Structure to hold function pointers to the functions responsible
+ * for stream scheduling.
+ */
+struct sctp_ss_functions {
+ void (*sctp_ss_init) (struct sctp_tcb *stcb, struct sctp_association *asoc,
+ int holds_lock);
+ void (*sctp_ss_clear) (struct sctp_tcb *stcb, struct sctp_association *asoc,
+ int clear_values, int holds_lock);
+ void (*sctp_ss_init_stream) (struct sctp_stream_out *strq, struct sctp_stream_out *with_strq);
+ void (*sctp_ss_add_to_stream) (struct sctp_tcb *stcb, struct sctp_association *asoc,
+ struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock);
+ int (*sctp_ss_is_empty) (struct sctp_tcb *stcb, struct sctp_association *asoc);
+ void (*sctp_ss_remove_from_stream) (struct sctp_tcb *stcb, struct sctp_association *asoc,
+ struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp, int holds_lock);
+ struct sctp_stream_out *(*sctp_ss_select_stream) (struct sctp_tcb *stcb,
+ struct sctp_nets *net, struct sctp_association *asoc);
+ void (*sctp_ss_scheduled) (struct sctp_tcb *stcb, struct sctp_nets *net,
+ struct sctp_association *asoc, struct sctp_stream_out *strq, int moved_how_much);
+ void (*sctp_ss_packet_done) (struct sctp_tcb *stcb, struct sctp_nets *net,
+ struct sctp_association *asoc);
+ int (*sctp_ss_get_value) (struct sctp_tcb *stcb, struct sctp_association *asoc,
+ struct sctp_stream_out *strq, uint16_t * value);
+ int (*sctp_ss_set_value) (struct sctp_tcb *stcb, struct sctp_association *asoc,
+ struct sctp_stream_out *strq, uint16_t value);
};
/* used to save ASCONF chunks for retransmission */
@@ -611,7 +755,6 @@ struct sctp_association {
struct sctp_nonpad_sndrcvinfo def_send;
/* timers and such */
- struct sctp_timer hb_timer; /* hb timer */
struct sctp_timer dack_timer; /* Delayed ack timer */
struct sctp_timer asconf_timer; /* asconf */
struct sctp_timer strreset_timer; /* stream reset */
@@ -652,13 +795,8 @@ struct sctp_association {
/* re-assembly queue for fragmented chunks on the inbound path */
struct sctpchunk_listhead reasmqueue;
- /*
- * this queue is used when we reach a condition that we can NOT put
- * data into the socket buffer. We track the size of this queue and
- * set our rwnd to the space in the socket minus also the
- * size_on_delivery_queue.
- */
- struct sctpwheel_listhead out_wheel;
+ /* Scheduling queues */
+ union scheduling_data ss_data;
/*
* This pointer will be set to NULL most of the time. But when we
@@ -691,6 +829,7 @@ struct sctp_association {
uint8_t *mapping_array;
/* primary destination to use */
struct sctp_nets *primary_destination;
+ struct sctp_nets *alternate; /* If primary is down or PF */
/* For CMT */
struct sctp_nets *last_net_cmt_send_started;
/* last place I got a data chunk from */
@@ -717,6 +856,10 @@ struct sctp_association {
* module
*/
uint32_t congestion_control_module;
+ /* RS - the stream scheduling functions are in this struct */
+ struct sctp_ss_functions ss_functions;
+ /* RS - value to store the currently loaded stream scheduling module */
+ uint32_t stream_scheduling_module;
uint32_t vrf_id;
@@ -789,8 +932,6 @@ struct sctp_association {
uint8_t *nr_mapping_array;
uint32_t highest_tsn_inside_nr_map;
- uint32_t last_echo_tsn;
- uint32_t last_cwr_tsn;
uint32_t fast_recovery_tsn;
uint32_t sat_t3_recovery_tsn;
uint32_t tsn_last_delivered;
@@ -845,12 +986,11 @@ struct sctp_association {
uint32_t sb_send_resv; /* amount reserved on a send */
uint32_t my_rwnd_control_len; /* shadow of sb_mbcnt used for rwnd
* control */
- /* 32 bit nonce stuff */
- uint32_t nonce_resync_tsn;
- uint32_t nonce_wait_tsn;
+#ifdef INET6
uint32_t default_flowlabel;
+#endif
uint32_t pr_sctp_cnt;
- int ctrl_queue_cnt; /* could be removed REM */
+ int ctrl_queue_cnt; /* could be removed REM - NO IT CAN'T!! RRS */
/*
* All outbound datagrams queue into this list from the individual
* stream queue. Here they get assigned a TSN and then await
@@ -887,8 +1027,8 @@ struct sctp_association {
unsigned int size_on_all_streams;
unsigned int cnt_on_all_streams;
- /* Heart Beat delay in ticks */
- unsigned int heart_beat_delay;
+ /* Heart Beat delay in ms */
+ uint32_t heart_beat_delay;
/* autoclose */
unsigned int sctp_autoclose_ticks;
@@ -951,6 +1091,7 @@ struct sctp_association {
uint16_t streamincnt;
uint16_t streamoutcnt;
uint16_t strm_realoutsize;
+ uint16_t strm_pending_add_size;
/* my maximum number of retrans of INIT and SEND */
/* copied from SCTP but should be individually setable */
uint16_t max_init_times;
@@ -958,6 +1099,8 @@ struct sctp_association {
uint16_t def_net_failure;
+ uint16_t def_net_pf_threshold;
+
/*
* lock flag: 0 is ok to send, 1+ (duals as a retran count) is
* awaiting ACK
@@ -974,7 +1117,6 @@ struct sctp_association {
uint16_t ecn_echo_cnt_onq;
uint16_t free_chunk_cnt;
-
uint8_t stream_locked;
uint8_t authenticated; /* packet authenticated ok */
/*
@@ -983,8 +1125,10 @@ struct sctp_association {
*/
uint8_t send_sack;
- /* max burst after fast retransmit completes */
- uint8_t max_burst;
+ /* max burst of new packets into the network */
+ uint32_t max_burst;
+ /* max burst of fast retransmit packets */
+ uint32_t fr_max_burst;
uint8_t sat_network; /* RTT is in range of sat net or greater */
uint8_t sat_network_lockout; /* lockout code */
@@ -996,27 +1140,22 @@ struct sctp_association {
uint8_t last_flags_delivered;
uint8_t hb_ect_randombit;
uint8_t hb_random_idx;
- uint8_t hb_is_disabled; /* is the hb disabled? */
- uint8_t default_tos;
+ uint8_t default_dscp;
uint8_t asconf_del_pending; /* asconf delete last addr pending */
- /* ECN Nonce stuff */
- uint8_t receiver_nonce_sum; /* nonce I sum and put in my sack */
- uint8_t ecn_nonce_allowed; /* Tells us if ECN nonce is on */
- uint8_t nonce_sum_check;/* On off switch used during re-sync */
- uint8_t nonce_wait_for_ecne; /* flag when we expect a ECN */
- uint8_t peer_supports_ecn_nonce;
-
/*
* This value, plus all other ack'd but above cum-ack is added
* together to cross check against the bit that we have yet to
* define (probably in the SACK). When the cum-ack is updated, this
* sum is updated as well.
*/
- uint8_t nonce_sum_expect_base;
+
/* Flag to tell if ECN is allowed */
uint8_t ecn_allowed;
+ /* Did the peer make the stream config (add out) request */
+ uint8_t peer_req_out;
+
/* flag to indicate if peer can do asconf */
uint8_t peer_supports_asconf;
/* EY - flag to indicate if peer can do nr_sack */
@@ -1027,6 +1166,7 @@ struct sctp_association {
uint8_t peer_supports_auth;
/* stream resets are supported by the peer */
uint8_t peer_supports_strreset;
+ uint8_t local_strreset_support;
uint8_t peer_supports_nat;
/*
@@ -1035,17 +1175,7 @@ struct sctp_association {
*/
uint8_t peer_supports_pktdrop;
- /* Do we allow V6/V4? */
- uint8_t ipv4_addr_legal;
- uint8_t ipv6_addr_legal;
- /* Address scoping flags */
- /* scope value for IPv4 */
- uint8_t ipv4_local_scope;
- /* scope values for IPv6 */
- uint8_t local_scope;
- uint8_t site_scope;
- /* loopback scope */
- uint8_t loopback_scope;
+ struct sctp_scoping scope;
/* flags to handle send alternate net tracking */
uint8_t used_alt_onsack;
uint8_t used_alt_asconfack;
@@ -1072,6 +1202,9 @@ struct sctp_association {
uint8_t sctp_nr_sack_on_off;
/* JRS 5/21/07 - CMT PF variable */
uint8_t sctp_cmt_pf;
+ uint8_t use_precise_time;
+ uint32_t sctp_features;
+ uint16_t port; /* remote UDP encapsulation port */
/*
* The mapping array is used to track out of order sequences above
* last_acked_seq. 0 indicates packet missing 1 indicates packet
diff --git a/freebsd/sys/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c
index 6fcf4964..b4ed49d4 100644
--- a/freebsd/sys/netinet/sctp_sysctl.c
+++ b/freebsd/sys/netinet/sctp_sysctl.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -54,14 +56,10 @@ sctp_init_sysctls()
SCTP_BASE_SYSCTL(sctp_auto_asconf) = SCTPCTL_AUTOASCONF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = SCTPCTL_MULTIPLEASCONFS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
- SCTP_BASE_SYSCTL(sctp_ecn_nonce) = SCTPCTL_ECN_NONCE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT;
-#if !defined(SCTP_WITH_NO_CSUM)
- SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) = SCTPCTL_LOOPBACK_NOCSUM_DEFAULT;
-#endif
- SCTP_BASE_SYSCTL(sctp_strict_init) = SCTPCTL_STRICT_INIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_peer_chunk_oh) = SCTPCTL_PEER_CHKOH_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_burst_default) = SCTPCTL_MAXBURST_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_fr_max_burst_default) = SCTPCTL_FRMAXBURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = SCTPCTL_MAXCHUNKS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_hashtblsize) = SCTPCTL_TCBHASHSIZE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pcbtblsize) = SCTPCTL_PCBHASHSIZE_DEFAULT;
@@ -83,16 +81,14 @@ sctp_init_sysctls()
SCTP_BASE_SYSCTL(sctp_init_rtx_max_default) = SCTPCTL_INIT_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default) = SCTPCTL_ASSOC_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_path_rtx_max_default) = SCTPCTL_PATH_RTX_MAX_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_path_pf_threshold) = SCTPCTL_PATH_PF_THRESHOLD_DEFAULT;
SCTP_BASE_SYSCTL(sctp_add_more_threshold) = SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default) = SCTPCTL_OUTGOING_STREAMS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT;
/* EY */
SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) = SCTPCTL_NR_SACK_ON_OFF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_use_dac) = SCTPCTL_CMT_USE_DAC_DEFAULT;
- SCTP_BASE_SYSCTL(sctp_cmt_pf) = SCTPCTL_CMT_PF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) = SCTPCTL_CWND_MAXBURST_DEFAULT;
- SCTP_BASE_SYSCTL(sctp_early_fr) = SCTPCTL_EARLY_FAST_RETRAN_DEFAULT;
- SCTP_BASE_SYSCTL(sctp_early_fr_msec) = SCTPCTL_EARLY_FAST_RETRAN_MSEC_DEFAULT;
SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) = SCTPCTL_ASCONF_AUTH_NOCHK_DEFAULT;
SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nat_friendly) = SCTPCTL_NAT_FRIENDLY_DEFAULT;
@@ -107,16 +103,24 @@ sctp_init_sysctls()
SCTP_BASE_SYSCTL(sctp_logging_level) = SCTPCTL_LOGGING_LEVEL_DEFAULT;
/* JRS - Variable for default congestion control module */
SCTP_BASE_SYSCTL(sctp_default_cc_module) = SCTPCTL_DEFAULT_CC_MODULE_DEFAULT;
+ /* RS - Variable for default stream scheduling module */
+ SCTP_BASE_SYSCTL(sctp_default_ss_module) = SCTPCTL_DEFAULT_SS_MODULE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_default_frag_interleave) = SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_mobility_base) = SCTPCTL_MOBILITY_BASE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff) = SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_vtag_time_wait) = SCTPCTL_TIME_WAIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_buffer_splitting) = SCTPCTL_BUFFER_SPLITTING_DEFAULT;
SCTP_BASE_SYSCTL(sctp_initial_cwnd) = SCTPCTL_INITIAL_CWND_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_rttvar_bw) = SCTPCTL_RTTVAR_BW_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_rttvar_rtt) = SCTPCTL_RTTVAR_RTT_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_rttvar_eqret) = SCTPCTL_RTTVAR_EQRET_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_steady_step) = SCTPCTL_RTTVAR_STEADYS_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_use_dccc_ecn) = SCTPCTL_RTTVAR_DCCCECN_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_blackhole) = SCTPCTL_BLACKHOLE_DEFAULT;
+
#if defined(SCTP_LOCAL_TRACE_BUF)
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
#endif
- SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable) = SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = SCTPCTL_UDP_TUNNELING_PORT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_enable_sack_immediately) = SCTPCTL_SACK_IMMEDIATELY_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly) = SCTPCTL_NAT_FRIENDLY_INITS_DEFAULT;
@@ -133,7 +137,7 @@ sctp_init_sysctls()
static unsigned int
number_of_addresses(struct sctp_inpcb *inp)
{
- int cnt;
+ unsigned int cnt;
struct sctp_vrf *vrf;
struct sctp_ifn *sctp_ifn;
struct sctp_ifa *sctp_ifa;
@@ -147,17 +151,33 @@ number_of_addresses(struct sctp_inpcb *inp)
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
- if ((sctp_ifa->address.sa.sa_family == AF_INET) ||
- (sctp_ifa->address.sa.sa_family == AF_INET6)) {
+ switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+#endif
+#ifdef INET6
+ case AF_INET6:
+#endif
cnt++;
+ break;
+ default:
+ break;
}
}
}
} else {
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
- if ((laddr->ifa->address.sa.sa_family == AF_INET) ||
- (laddr->ifa->address.sa.sa_family == AF_INET6)) {
+ switch (laddr->ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+#endif
+#ifdef INET6
+ case AF_INET6:
+#endif
cnt++;
+ break;
+ default:
+ break;
}
}
}
@@ -179,29 +199,29 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
/* Turn on all the appropriate scope */
if (stcb) {
/* use association specific values */
- loopback_scope = stcb->asoc.loopback_scope;
- ipv4_local_scope = stcb->asoc.ipv4_local_scope;
- local_scope = stcb->asoc.local_scope;
- site_scope = stcb->asoc.site_scope;
+ loopback_scope = stcb->asoc.scope.loopback_scope;
+ ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
+ local_scope = stcb->asoc.scope.local_scope;
+ site_scope = stcb->asoc.scope.site_scope;
+ ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
+ ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
} else {
- /* use generic values for endpoints */
+ /* Use generic values for endpoints. */
loopback_scope = 1;
ipv4_local_scope = 1;
local_scope = 1;
site_scope = 1;
- }
-
- /* use only address families of interest */
- if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- ipv6_addr_legal = 1;
- if (SCTP_IPV6_V6ONLY(inp)) {
- ipv4_addr_legal = 0;
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ ipv6_addr_legal = 1;
+ if (SCTP_IPV6_V6ONLY(inp)) {
+ ipv4_addr_legal = 0;
+ } else {
+ ipv4_addr_legal = 1;
+ }
} else {
+ ipv6_addr_legal = 0;
ipv4_addr_legal = 1;
}
- } else {
- ipv4_addr_legal = 1;
- ipv6_addr_legal = 0;
}
/* neither Mac OS X nor FreeBSD support mulitple routing functions */
@@ -225,6 +245,7 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
continue;
}
switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
case AF_INET:
if (ipv4_addr_legal) {
struct sockaddr_in *sin;
@@ -238,6 +259,7 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
continue;
}
break;
+#endif
#ifdef INET6
case AF_INET6:
if (ipv6_addr_legal) {
@@ -365,12 +387,12 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
/* request some more memory than needed */
req->oldidx = (n + n / 8);
- return 0;
+ return (0);
}
if (req->newptr != USER_ADDR_NULL) {
SCTP_INP_INFO_RUNLOCK();
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_SYSCTL, EPERM);
- return EPERM;
+ return (EPERM);
}
LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
SCTP_INP_RLOCK(inp);
@@ -401,14 +423,14 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
if (error) {
SCTP_INP_DECR_REF(inp);
- return error;
+ return (error);
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
error = copy_out_local_addresses(inp, NULL, req);
if (error) {
SCTP_INP_DECR_REF(inp);
- return error;
+ return (error);
}
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
SCTP_TCB_LOCK(stcb);
@@ -452,7 +474,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
- return error;
+ return (error);
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
@@ -460,7 +482,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
- return error;
+ return (error);
}
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
xraddr.last = 0;
@@ -468,6 +490,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.active = ((net->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE);
xraddr.confirmed = ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0);
xraddr.heartbeat_enabled = ((net->dest_state & SCTP_ADDR_NOHB) == 0);
+ xraddr.potentially_failed = ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF);
xraddr.rto = net->RTO;
xraddr.max_path_rtx = net->failure_threshold;
xraddr.rtx = net->marked_retrans;
@@ -475,7 +498,8 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.cwnd = net->cwnd;
xraddr.flight_size = net->flight_size;
xraddr.mtu = net->mtu;
- xraddr.rtt = net->rtt;
+ xraddr.rtt = net->rtt / 1000;
+ xraddr.heartbeat_interval = net->heart_beat_delay;
xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
@@ -484,7 +508,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
- return error;
+ return (error);
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
@@ -497,7 +521,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr));
if (error) {
SCTP_INP_DECR_REF(inp);
- return error;
+ return (error);
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
@@ -509,7 +533,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xstcb.last = 1;
error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb));
if (error) {
- return error;
+ return (error);
}
skip:
SCTP_INP_INFO_RLOCK();
@@ -519,7 +543,7 @@ skip:
memset((void *)&xinpcb, 0, sizeof(struct xsctp_inpcb));
xinpcb.last = 1;
error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
- return error;
+ return (error);
}
@@ -564,20 +588,20 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
{
int error;
+#ifdef VIMAGE
+ error = vnet_sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+#else
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+#endif
if (error == 0) {
RANGECHK(SCTP_BASE_SYSCTL(sctp_sendspace), SCTPCTL_MAXDGRAM_MIN, SCTPCTL_MAXDGRAM_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_recvspace), SCTPCTL_RECVSPACE_MIN, SCTPCTL_RECVSPACE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX);
- RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_nonce), SCTPCTL_ECN_NONCE_MIN, SCTPCTL_ECN_NONCE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX);
-#if !defined(SCTP_WITH_NO_CSUM)
- RANGECHK(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), SCTPCTL_LOOPBACK_NOCSUM_MIN, SCTPCTL_LOOPBACK_NOCSUM_MAX);
-#endif
- RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_init), SCTPCTL_STRICT_INIT_MIN, SCTPCTL_STRICT_INIT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_burst_default), SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), SCTPCTL_FRMAXBURST_MIN, SCTPCTL_FRMAXBURST_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), SCTPCTL_MAXCHUNKS_MIN, SCTPCTL_MAXCHUNKS_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_hashtblsize), SCTPCTL_TCBHASHSIZE_MIN, SCTPCTL_TCBHASHSIZE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_pcbtblsize), SCTPCTL_PCBHASHSIZE_MIN, SCTPCTL_PCBHASHSIZE_MAX);
@@ -599,16 +623,14 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), SCTPCTL_INIT_RTX_MAX_MIN, SCTPCTL_INIT_RTX_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), SCTPCTL_ASSOC_RTX_MAX_MIN, SCTPCTL_ASSOC_RTX_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), SCTPCTL_PATH_RTX_MAX_MIN, SCTPCTL_PATH_RTX_MAX_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_path_pf_threshold), SCTPCTL_PATH_PF_THRESHOLD_MIN, SCTPCTL_PATH_PF_THRESHOLD_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTPCTL_ADD_MORE_ON_OUTPUT_MIN, SCTPCTL_ADD_MORE_ON_OUTPUT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), SCTPCTL_OUTGOING_STREAMS_MIN, SCTPCTL_OUTGOING_STREAMS_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_on_off), SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX);
/* EY */
RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_sack_on_off), SCTPCTL_NR_SACK_ON_OFF_MIN, SCTPCTL_NR_SACK_ON_OFF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_use_dac), SCTPCTL_CMT_USE_DAC_MIN, SCTPCTL_CMT_USE_DAC_MAX);
- RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_pf), SCTPCTL_CMT_PF_MIN, SCTPCTL_CMT_PF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), SCTPCTL_CWND_MAXBURST_MIN, SCTPCTL_CWND_MAXBURST_MAX);
- RANGECHK(SCTP_BASE_SYSCTL(sctp_early_fr), SCTPCTL_EARLY_FAST_RETRAN_MIN, SCTPCTL_EARLY_FAST_RETRAN_MAX);
- RANGECHK(SCTP_BASE_SYSCTL(sctp_early_fr_msec), SCTPCTL_EARLY_FAST_RETRAN_MSEC_MIN, SCTPCTL_EARLY_FAST_RETRAN_MSEC_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), SCTPCTL_ASCONF_AUTH_NOCHK_MIN, SCTPCTL_ASCONF_AUTH_NOCHK_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_auth_disable), SCTPCTL_AUTH_DISABLE_MIN, SCTPCTL_AUTH_DISABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_nat_friendly), SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX);
@@ -622,20 +644,26 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_retran_chunk), SCTPCTL_MAX_RETRAN_CHUNK_MIN, SCTPCTL_MAX_RETRAN_CHUNK_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_logging_level), SCTPCTL_LOGGING_LEVEL_MIN, SCTPCTL_LOGGING_LEVEL_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_default_cc_module), SCTPCTL_DEFAULT_CC_MODULE_MIN, SCTPCTL_DEFAULT_CC_MODULE_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_default_ss_module), SCTPCTL_DEFAULT_SS_MODULE_MIN, SCTPCTL_DEFAULT_SS_MODULE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_default_frag_interleave), SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MIN, SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_vtag_time_wait), SCTPCTL_TIME_WAIT_MIN, SCTPCTL_TIME_WAIT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_buffer_splitting), SCTPCTL_BUFFER_SPLITTING_MIN, SCTPCTL_BUFFER_SPLITTING_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_initial_cwnd), SCTPCTL_INITIAL_CWND_MIN, SCTPCTL_INITIAL_CWND_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_bw), SCTPCTL_RTTVAR_BW_MIN, SCTPCTL_RTTVAR_BW_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_rtt), SCTPCTL_RTTVAR_RTT_MIN, SCTPCTL_RTTVAR_RTT_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_eqret), SCTPCTL_RTTVAR_EQRET_MIN, SCTPCTL_RTTVAR_EQRET_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_steady_step), SCTPCTL_RTTVAR_STEADYS_MIN, SCTPCTL_RTTVAR_STEADYS_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), SCTPCTL_RTTVAR_DCCCECN_MIN, SCTPCTL_RTTVAR_DCCCECN_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX);
- RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN, SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), SCTPCTL_SACK_IMMEDIATELY_ENABLE_MIN, SCTPCTL_SACK_IMMEDIATELY_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), SCTPCTL_NAT_FRIENDLY_INITS_MIN, SCTPCTL_NAT_FRIENDLY_INITS_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_blackhole), SCTPCTL_BLACKHOLE_MIN, SCTPCTL_BLACKHOLE_MAX);
#ifdef SCTP_DEBUG
RANGECHK(SCTP_BASE_SYSCTL(sctp_debug_on), SCTPCTL_DEBUG_MIN, SCTPCTL_DEBUG_MAX);
#endif
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
RANGECHK(SCTP_BASE_SYSCTL(sctp_output_unlocked), SCTPCTL_OUTPUT_UNLOCKED_MIN, SCTPCTL_OUTPUT_UNLOCKED_MAX);
#endif
}
@@ -647,10 +675,20 @@ static int
sysctl_stat_get(SYSCTL_HANDLER_ARGS)
{
int cpu, error;
- struct sctpstat sb, *sarry;
-
+ struct sctpstat sb, *sarry, *cpin = NULL;
+
+ if ((req->newptr) && (req->newlen == sizeof(struct sctpstat))) {
+ /*
+ * User wants us to clear or at least reset the counters to
+ * the specified values.
+ */
+ cpin = (struct sctpstat *)req->newptr;
+ } else if (req->newptr) {
+ /* Must be a stat structure */
+ return (EINVAL);
+ }
memset(&sb, 0, sizeof(sb));
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
+ for (cpu = 0; cpu < mp_maxid; cpu++) {
sarry = &SCTP_BASE_STATS[cpu];
if (sarry->sctps_discontinuitytime.tv_sec > sb.sctps_discontinuitytime.tv_sec) {
sb.sctps_discontinuitytime.tv_sec = sarry->sctps_discontinuitytime.tv_sec;
@@ -740,17 +778,6 @@ sysctl_stat_get(SYSCTL_HANDLER_ARGS)
sb.sctps_timoautoclose += sarry->sctps_timoautoclose;
sb.sctps_timoassockill += sarry->sctps_timoassockill;
sb.sctps_timoinpkill += sarry->sctps_timoinpkill;
- sb.sctps_earlyfrstart += sarry->sctps_earlyfrstart;
- sb.sctps_earlyfrstop += sarry->sctps_earlyfrstop;
- sb.sctps_earlyfrmrkretrans += sarry->sctps_earlyfrmrkretrans;
- sb.sctps_earlyfrstpout += sarry->sctps_earlyfrstpout;
- sb.sctps_earlyfrstpidsck1 += sarry->sctps_earlyfrstpidsck1;
- sb.sctps_earlyfrstpidsck2 += sarry->sctps_earlyfrstpidsck2;
- sb.sctps_earlyfrstpidsck3 += sarry->sctps_earlyfrstpidsck3;
- sb.sctps_earlyfrstpidsck4 += sarry->sctps_earlyfrstpidsck4;
- sb.sctps_earlyfrstrid += sarry->sctps_earlyfrstrid;
- sb.sctps_earlyfrstrout += sarry->sctps_earlyfrstrout;
- sb.sctps_earlyfrstrtmr += sarry->sctps_earlyfrstrtmr;
sb.sctps_hdrops += sarry->sctps_hdrops;
sb.sctps_badsum += sarry->sctps_badsum;
sb.sctps_noport += sarry->sctps_noport;
@@ -788,6 +815,9 @@ sysctl_stat_get(SYSCTL_HANDLER_ARGS)
sb.sctps_send_burst_avoid += sarry->sctps_send_burst_avoid;
sb.sctps_send_cwnd_avoid += sarry->sctps_send_cwnd_avoid;
sb.sctps_fwdtsn_map_over += sarry->sctps_fwdtsn_map_over;
+ if (cpin) {
+ memcpy(sarry, cpin, sizeof(struct sctpstat));
+ }
}
error = SYSCTL_OUT(req, &sb, sizeof(sb));
return (error);
@@ -812,297 +842,301 @@ sysctl_sctp_cleartrace(SYSCTL_HANDLER_ARGS)
* sysctl definitions
*/
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, sendspace, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sendspace, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_sendspace), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXDGRAM_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, recvspace, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, recvspace, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_recvspace), 0, sysctl_sctp_check, "IU",
SCTPCTL_RECVSPACE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auto_asconf, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auto_asconf, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_auto_asconf), 0, sysctl_sctp_check, "IU",
SCTPCTL_AUTOASCONF_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, ecn_enable, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, ecn_enable, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_ecn_enable), 0, sysctl_sctp_check, "IU",
SCTPCTL_ECN_ENABLE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, ecn_nonce, CTLTYPE_INT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_ecn_nonce), 0, sysctl_sctp_check, "IU",
- SCTPCTL_ECN_NONCE_DESC);
-
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_SACKS_DESC);
-#if !defined(SCTP_WITH_NO_CSUM)
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, loopback_nocsum, CTLTYPE_INT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), 0, sysctl_sctp_check, "IU",
- SCTPCTL_LOOPBACK_NOCSUM_DESC);
-#endif
-
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_init, CTLTYPE_INT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_strict_init), 0, sysctl_sctp_check, "IU",
- SCTPCTL_STRICT_INIT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, peer_chkoh, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, peer_chkoh, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), 0, sysctl_sctp_check, "IU",
SCTPCTL_PEER_CHKOH_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, maxburst, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, maxburst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_max_burst_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXBURST_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, maxchunks, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, fr_maxburst, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_FRMAXBURST_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, maxchunks, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXCHUNKS_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, tcbhashsize, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, tcbhashsize, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_hashtblsize), 0, sysctl_sctp_check, "IU",
SCTPCTL_TCBHASHSIZE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, pcbhashsize, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pcbhashsize, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_pcbtblsize), 0, sysctl_sctp_check, "IU",
SCTPCTL_PCBHASHSIZE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, min_split_point, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, min_split_point, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_min_split_point), 0, sysctl_sctp_check, "IU",
SCTPCTL_MIN_SPLIT_POINT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, chunkscale, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, chunkscale, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_chunkscale), 0, sysctl_sctp_check, "IU",
SCTPCTL_CHUNKSCALE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_DELAYED_SACK_TIME_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, sack_freq, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sack_freq, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_sack_freq_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_SACK_FREQ_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, sys_resource, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sys_resource, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_system_free_resc_limit), 0, sysctl_sctp_check, "IU",
SCTPCTL_SYS_RESOURCE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asoc_resource, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asoc_resource, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit), 0, sysctl_sctp_check, "IU",
SCTPCTL_ASOC_RESOURCE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_HEARTBEAT_INTERVAL_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, pmtu_raise_time, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pmtu_raise_time, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_PMTU_RAISE_TIME_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, shutdown_guard_time, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, shutdown_guard_time, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_SHUTDOWN_GUARD_TIME_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_secret_lifetime_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_SECRET_LIFETIME_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_max, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_rto_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_min, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_min, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_rto_min_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_MIN_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_initial, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_initial, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_rto_initial_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_INITIAL_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, init_rto_max, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, init_rto_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_init_rto_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_INIT_RTO_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_VALID_COOKIE_LIFE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_INIT_RTX_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoc_rtx_max, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, assoc_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_ASSOC_RTX_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_PATH_RTX_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, path_pf_threshold, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_path_pf_threshold), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_PATH_PF_THRESHOLD_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_add_more_threshold), 0, sysctl_sctp_check, "IU",
SCTPCTL_ADD_MORE_ON_OUTPUT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, outgoing_streams, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, outgoing_streams, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_OUTGOING_STREAMS_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_on_off, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_on_off, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_cmt_on_off), 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_ON_OFF_DESC);
-/* EY */
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, nr_sack_on_off, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nr_sack_on_off, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_nr_sack_on_off), 0, sysctl_sctp_check, "IU",
SCTPCTL_NR_SACK_ON_OFF_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_use_dac, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_use_dac, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_cmt_use_dac), 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_USE_DAC_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_pf, CTLTYPE_INT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_cmt_pf), 0, sysctl_sctp_check, "IU",
- SCTPCTL_CMT_PF_DESC);
-
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sysctl_sctp_check, "IU",
SCTPCTL_CWND_MAXBURST_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran, CTLTYPE_INT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_early_fr), 0, sysctl_sctp_check, "IU",
- SCTPCTL_EARLY_FAST_RETRAN_DESC);
-
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran_msec, CTLTYPE_INT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_early_fr_msec), 0, sysctl_sctp_check, "IU",
- SCTPCTL_EARLY_FAST_RETRAN_MSEC_DESC);
-
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asconf_auth_nochk, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asconf_auth_nochk, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), 0, sysctl_sctp_check, "IU",
SCTPCTL_ASCONF_AUTH_NOCHK_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_check, "IU",
SCTPCTL_AUTH_DISABLE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_nat_friendly), 0, sysctl_sctp_check, "IU",
SCTPCTL_NAT_FRIENDLY_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, abc_l_var, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, abc_l_var, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_L2_abc_variable), 0, sysctl_sctp_check, "IU",
SCTPCTL_ABC_L_VAR_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, max_chained_mbufs, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, max_chained_mbufs, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAX_CHAINED_MBUFS_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, do_sctp_drain, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, do_sctp_drain, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_do_drain), 0, sysctl_sctp_check, "IU",
SCTPCTL_DO_SCTP_DRAIN_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, hb_max_burst, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, hb_max_burst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_hb_maxburst), 0, sysctl_sctp_check, "IU",
SCTPCTL_HB_MAX_BURST_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, abort_at_limit, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, abort_at_limit, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit), 0, sysctl_sctp_check, "IU",
SCTPCTL_ABORT_AT_LIMIT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_data_order, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_data_order, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_strict_data_order), 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_DATA_ORDER_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, min_residual, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, min_residual, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_min_residual), 0, sysctl_sctp_check, "IU",
SCTPCTL_MIN_RESIDUAL_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_max_retran_chunk), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAX_RETRAN_CHUNK_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, log_level, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, log_level, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_logging_level), 0, sysctl_sctp_check, "IU",
SCTPCTL_LOGGING_LEVEL_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, default_cc_module, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_cc_module, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_default_cc_module), 0, sysctl_sctp_check, "IU",
SCTPCTL_DEFAULT_CC_MODULE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, default_frag_interleave, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_ss_module, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_default_ss_module), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_DEFAULT_SS_MODULE_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_frag_interleave, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_default_frag_interleave), 0, sysctl_sctp_check, "IU",
SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mobility_base, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, mobility_base, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_mobility_base), 0, sysctl_sctp_check, "IU",
SCTPCTL_MOBILITY_BASE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mobility_fasthandoff, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, mobility_fasthandoff, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), 0, sysctl_sctp_check, "IU",
SCTPCTL_MOBILITY_FASTHANDOFF_DESC);
#if defined(SCTP_LOCAL_TRACE_BUF)
-SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, log, CTLFLAG_RD,
+SYSCTL_VNET_STRUCT(_net_inet_sctp, OID_AUTO, log, CTLFLAG_RD,
&SCTP_BASE_SYSCTL(sctp_log), sctp_log,
"SCTP logging (struct sctp_log)");
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_OPAQUE | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_log), 0, sysctl_sctp_cleartrace, "IU",
"Clear SCTP Logging buffer");
-
-
-
#endif
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_for_client_enable, CTLTYPE_INT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), 0, sysctl_sctp_check, "IU",
- SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DESC);
-
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), 0, sysctl_sctp_udp_tunneling_check, "IU",
SCTPCTL_UDP_TUNNELING_PORT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, enable_sack_immediately, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, enable_sack_immediately, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), 0, sysctl_sctp_check, "IU",
SCTPCTL_SACK_IMMEDIATELY_ENABLE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, nat_friendly_init, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly_init, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), 0, sysctl_sctp_check, "IU",
SCTPCTL_NAT_FRIENDLY_INITS_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, vtag_time_wait, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, vtag_time_wait, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_vtag_time_wait), 0, sysctl_sctp_check, "IU",
SCTPCTL_TIME_WAIT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, buffer_splitting, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, buffer_splitting, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_buffer_splitting), 0, sysctl_sctp_check, "IU",
SCTPCTL_BUFFER_SPLITTING_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, initial_cwnd, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, initial_cwnd, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_initial_cwnd), 0, sysctl_sctp_check, "IU",
SCTPCTL_INITIAL_CWND_DESC);
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_bw, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_rttvar_bw), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_RTTVAR_BW_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_rtt, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_rttvar_rtt), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_RTTVAR_RTT_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_eqret, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_rttvar_eqret), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_RTTVAR_EQRET_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_steady_step, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_steady_step), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_RTTVAR_STEADYS_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, use_dcccecn, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_RTTVAR_DCCCECN_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, blackhole, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_blackhole), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_BLACKHOLE_DESC);
+
#ifdef SCTP_DEBUG
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_debug_on), 0, sysctl_sctp_check, "IU",
SCTPCTL_DEBUG_DESC);
-#endif /* SCTP_DEBUG */
+#endif
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, output_unlocked, CTLTYPE_INT | CTLFLAG_RW,
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, output_unlocked, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_output_unlocked), 0, sysctl_sctp_check, "IU",
SCTPCTL_OUTPUT_UNLOCKED_DESC);
#endif
+
#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, stats,
- CTLTYPE_STRUCT | CTLFLAG_RD,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, stats,
+ CTLTYPE_STRUCT | CTLFLAG_RW,
0, 0, sysctl_stat_get, "S,sctpstat",
"SCTP statistics (struct sctp_stat)");
#else
-SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW,
+SYSCTL_VNET_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW,
&SCTP_BASE_STATS_SYSCTL, sctpstat,
"SCTP statistics (struct sctp_stat)");
#endif
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLTYPE_OPAQUE | CTLFLAG_RD,
0, 0, sctp_assoclist,
"S,xassoc", "List of active SCTP associations");
diff --git a/freebsd/sys/netinet/sctp_sysctl.h b/freebsd/sys/netinet/sctp_sysctl.h
index 9dbc9ed2..4ec37157 100644
--- a/freebsd/sys/netinet/sctp_sysctl.h
+++ b/freebsd/sys/netinet/sctp_sysctl.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -31,8 +33,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_sysctl_h__
-#define __sctp_sysctl_h__
+#ifndef _NETINET_SCTP_SYSCTL_H_
+#define _NETINET_SCTP_SYSCTL_H_
#include <netinet/sctp_os.h>
#include <netinet/sctp_constants.h>
@@ -43,12 +45,8 @@ struct sctp_sysctl {
uint32_t sctp_auto_asconf;
uint32_t sctp_multiple_asconfs;
uint32_t sctp_ecn_enable;
- uint32_t sctp_ecn_nonce;
+ uint32_t sctp_fr_max_burst_default;
uint32_t sctp_strict_sacks;
-#if !defined(SCTP_WITH_NO_CSUM)
- uint32_t sctp_no_csum_on_loopback;
-#endif
- uint32_t sctp_strict_init;
uint32_t sctp_peer_chunk_oh;
uint32_t sctp_max_burst_default;
uint32_t sctp_max_chunks_on_queue;
@@ -72,16 +70,14 @@ struct sctp_sysctl {
uint32_t sctp_init_rtx_max_default;
uint32_t sctp_assoc_rtx_max_default;
uint32_t sctp_path_rtx_max_default;
+ uint32_t sctp_path_pf_threshold;
uint32_t sctp_add_more_threshold;
uint32_t sctp_nr_outgoing_streams_default;
uint32_t sctp_cmt_on_off;
uint32_t sctp_cmt_use_dac;
/* EY 5/5/08 - nr_sack flag variable */
uint32_t sctp_nr_sack_on_off;
- uint32_t sctp_cmt_pf;
uint32_t sctp_use_cwnd_based_maxburst;
- uint32_t sctp_early_fr;
- uint32_t sctp_early_fr_msec;
uint32_t sctp_asconf_auth_nochk;
uint32_t sctp_auth_disable;
uint32_t sctp_nat_friendly;
@@ -96,19 +92,26 @@ struct sctp_sysctl {
uint32_t sctp_logging_level;
/* JRS - Variable for default congestion control module */
uint32_t sctp_default_cc_module;
+ /* RS - Variable for default stream scheduling module */
+ uint32_t sctp_default_ss_module;
uint32_t sctp_default_frag_interleave;
uint32_t sctp_mobility_base;
uint32_t sctp_mobility_fasthandoff;
uint32_t sctp_inits_include_nat_friendly;
+ uint32_t sctp_rttvar_bw;
+ uint32_t sctp_rttvar_rtt;
+ uint32_t sctp_rttvar_eqret;
+ uint32_t sctp_steady_step;
+ uint32_t sctp_use_dccc_ecn;
#if defined(SCTP_LOCAL_TRACE_BUF)
struct sctp_log sctp_log;
#endif
- uint32_t sctp_udp_tunneling_for_client_enable;
uint32_t sctp_udp_tunneling_port;
uint32_t sctp_enable_sack_immediately;
uint32_t sctp_vtag_time_wait;
uint32_t sctp_buffer_splitting;
uint32_t sctp_initial_cwnd;
+ uint32_t sctp_blackhole;
#if defined(SCTP_DEBUG)
uint32_t sctp_debug_on;
#endif
@@ -150,12 +153,6 @@ struct sctp_sysctl {
#define SCTPCTL_ECN_ENABLE_MAX 1
#define SCTPCTL_ECN_ENABLE_DEFAULT 1
-/* ecn_nonce: Enable SCTP ECN Nonce */
-#define SCTPCTL_ECN_NONCE_DESC "Enable SCTP ECN Nonce"
-#define SCTPCTL_ECN_NONCE_MIN 0
-#define SCTPCTL_ECN_NONCE_MAX 1
-#define SCTPCTL_ECN_NONCE_DEFAULT 0
-
/* strict_sacks: Enable SCTP Strict SACK checking */
#define SCTPCTL_STRICT_SACKS_DESC "Enable SCTP Strict SACK checking"
#define SCTPCTL_STRICT_SACKS_MIN 0
@@ -168,12 +165,6 @@ struct sctp_sysctl {
#define SCTPCTL_LOOPBACK_NOCSUM_MAX 1
#define SCTPCTL_LOOPBACK_NOCSUM_DEFAULT 1
-/* strict_init: Enable strict INIT/INIT-ACK singleton enforcement */
-#define SCTPCTL_STRICT_INIT_DESC "Enable strict INIT/INIT-ACK singleton enforcement"
-#define SCTPCTL_STRICT_INIT_MIN 0
-#define SCTPCTL_STRICT_INIT_MAX 1
-#define SCTPCTL_STRICT_INIT_DEFAULT 1
-
/* peer_chkoh: Amount to debit peers rwnd per chunk sent */
#define SCTPCTL_PEER_CHKOH_DESC "Amount to debit peers rwnd per chunk sent"
#define SCTPCTL_PEER_CHKOH_MIN 0
@@ -182,23 +173,30 @@ struct sctp_sysctl {
/* maxburst: Default max burst for sctp endpoints */
#define SCTPCTL_MAXBURST_DESC "Default max burst for sctp endpoints"
-#define SCTPCTL_MAXBURST_MIN 1
+#define SCTPCTL_MAXBURST_MIN 0
#define SCTPCTL_MAXBURST_MAX 0xFFFFFFFF
#define SCTPCTL_MAXBURST_DEFAULT SCTP_DEF_MAX_BURST
+/* fr_maxburst: Default max burst for sctp endpoints when fast retransmitting */
+#define SCTPCTL_FRMAXBURST_DESC "Default fr max burst for sctp endpoints"
+#define SCTPCTL_FRMAXBURST_MIN 0
+#define SCTPCTL_FRMAXBURST_MAX 0xFFFFFFFF
+#define SCTPCTL_FRMAXBURST_DEFAULT SCTP_DEF_FRMAX_BURST
+
+
/* maxchunks: Default max chunks on queue per asoc */
#define SCTPCTL_MAXCHUNKS_DESC "Default max chunks on queue per asoc"
#define SCTPCTL_MAXCHUNKS_MIN 0
#define SCTPCTL_MAXCHUNKS_MAX 0xFFFFFFFF
#define SCTPCTL_MAXCHUNKS_DEFAULT SCTP_ASOC_MAX_CHUNKS_ON_QUEUE
-/* tcbhashsize: Tuneable for Hash table sizes */
+/* tcbhashsize: Tunable for Hash table sizes */
#define SCTPCTL_TCBHASHSIZE_DESC "Tunable for TCB hash table sizes"
#define SCTPCTL_TCBHASHSIZE_MIN 1
#define SCTPCTL_TCBHASHSIZE_MAX 0xFFFFFFFF
#define SCTPCTL_TCBHASHSIZE_DEFAULT SCTP_TCBHASHSIZE
-/* pcbhashsize: Tuneable for PCB Hash table sizes */
+/* pcbhashsize: Tunable for PCB Hash table sizes */
#define SCTPCTL_PCBHASHSIZE_DESC "Tunable for PCB hash table sizes"
#define SCTPCTL_PCBHASHSIZE_MIN 1
#define SCTPCTL_PCBHASHSIZE_MAX 0xFFFFFFFF
@@ -210,14 +208,14 @@ struct sctp_sysctl {
#define SCTPCTL_MIN_SPLIT_POINT_MAX 0xFFFFFFFF
#define SCTPCTL_MIN_SPLIT_POINT_DEFAULT SCTP_DEFAULT_SPLIT_POINT_MIN
-/* chunkscale: Tuneable for Scaling of number of chunks and messages */
-#define SCTPCTL_CHUNKSCALE_DESC "Tuneable for Scaling of number of chunks and messages"
+/* chunkscale: Tunable for Scaling of number of chunks and messages */
+#define SCTPCTL_CHUNKSCALE_DESC "Tunable for Scaling of number of chunks and messages"
#define SCTPCTL_CHUNKSCALE_MIN 1
#define SCTPCTL_CHUNKSCALE_MAX 0xFFFFFFFF
#define SCTPCTL_CHUNKSCALE_DEFAULT SCTP_CHUNKQUEUE_SCALE
-/* delayed_sack_time: Default delayed SACK timer in msec */
-#define SCTPCTL_DELAYED_SACK_TIME_DESC "Default delayed SACK timer in msec"
+/* delayed_sack_time: Default delayed SACK timer in ms */
+#define SCTPCTL_DELAYED_SACK_TIME_DESC "Default delayed SACK timer in ms"
#define SCTPCTL_DELAYED_SACK_TIME_MIN 0
#define SCTPCTL_DELAYED_SACK_TIME_MAX 0xFFFFFFFF
#define SCTPCTL_DELAYED_SACK_TIME_DEFAULT SCTP_RECV_MSEC
@@ -240,56 +238,56 @@ struct sctp_sysctl {
#define SCTPCTL_ASOC_RESOURCE_MAX 0xFFFFFFFF
#define SCTPCTL_ASOC_RESOURCE_DEFAULT SCTP_DEF_ASOC_RESC_LIMIT
-/* heartbeat_interval: Default heartbeat interval in msec */
-#define SCTPCTL_HEARTBEAT_INTERVAL_DESC "Default heartbeat interval in msec"
+/* heartbeat_interval: Default heartbeat interval in ms */
+#define SCTPCTL_HEARTBEAT_INTERVAL_DESC "Default heartbeat interval in ms"
#define SCTPCTL_HEARTBEAT_INTERVAL_MIN 0
#define SCTPCTL_HEARTBEAT_INTERVAL_MAX 0xFFFFFFFF
#define SCTPCTL_HEARTBEAT_INTERVAL_DEFAULT SCTP_HB_DEFAULT_MSEC
-/* pmtu_raise_time: Default PMTU raise timer in sec */
-#define SCTPCTL_PMTU_RAISE_TIME_DESC "Default PMTU raise timer in sec"
+/* pmtu_raise_time: Default PMTU raise timer in seconds */
+#define SCTPCTL_PMTU_RAISE_TIME_DESC "Default PMTU raise timer in seconds"
#define SCTPCTL_PMTU_RAISE_TIME_MIN 0
#define SCTPCTL_PMTU_RAISE_TIME_MAX 0xFFFFFFFF
#define SCTPCTL_PMTU_RAISE_TIME_DEFAULT SCTP_DEF_PMTU_RAISE_SEC
-/* shutdown_guard_time: Default shutdown guard timer in sec */
-#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Default shutdown guard timer in sec"
+/* shutdown_guard_time: Default shutdown guard timer in seconds */
+#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Default shutdown guard timer in seconds"
#define SCTPCTL_SHUTDOWN_GUARD_TIME_MIN 0
#define SCTPCTL_SHUTDOWN_GUARD_TIME_MAX 0xFFFFFFFF
#define SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT SCTP_DEF_MAX_SHUTDOWN_SEC
-/* secret_lifetime: Default secret lifetime in sec */
-#define SCTPCTL_SECRET_LIFETIME_DESC "Default secret lifetime in sec"
+/* secret_lifetime: Default secret lifetime in seconds */
+#define SCTPCTL_SECRET_LIFETIME_DESC "Default secret lifetime in seconds"
#define SCTPCTL_SECRET_LIFETIME_MIN 0
#define SCTPCTL_SECRET_LIFETIME_MAX 0xFFFFFFFF
#define SCTPCTL_SECRET_LIFETIME_DEFAULT SCTP_DEFAULT_SECRET_LIFE_SEC
-/* rto_max: Default maximum retransmission timeout in msec */
-#define SCTPCTL_RTO_MAX_DESC "Default maximum retransmission timeout in msec"
+/* rto_max: Default maximum retransmission timeout in ms */
+#define SCTPCTL_RTO_MAX_DESC "Default maximum retransmission timeout in ms"
#define SCTPCTL_RTO_MAX_MIN 0
#define SCTPCTL_RTO_MAX_MAX 0xFFFFFFFF
#define SCTPCTL_RTO_MAX_DEFAULT SCTP_RTO_UPPER_BOUND
-/* rto_min: Default minimum retransmission timeout in msec */
-#define SCTPCTL_RTO_MIN_DESC "Default minimum retransmission timeout in msec"
+/* rto_min: Default minimum retransmission timeout in ms */
+#define SCTPCTL_RTO_MIN_DESC "Default minimum retransmission timeout in ms"
#define SCTPCTL_RTO_MIN_MIN 0
#define SCTPCTL_RTO_MIN_MAX 0xFFFFFFFF
#define SCTPCTL_RTO_MIN_DEFAULT SCTP_RTO_LOWER_BOUND
-/* rto_initial: Default initial retransmission timeout in msec */
-#define SCTPCTL_RTO_INITIAL_DESC "Default initial retransmission timeout in msec"
+/* rto_initial: Default initial retransmission timeout in ms */
+#define SCTPCTL_RTO_INITIAL_DESC "Default initial retransmission timeout in ms"
#define SCTPCTL_RTO_INITIAL_MIN 0
#define SCTPCTL_RTO_INITIAL_MAX 0xFFFFFFFF
#define SCTPCTL_RTO_INITIAL_DEFAULT SCTP_RTO_INITIAL
-/* init_rto_max: Default maximum retransmission timeout during association setup in msec */
-#define SCTPCTL_INIT_RTO_MAX_DESC "Default maximum retransmission timeout during association setup in msec"
+/* init_rto_max: Default maximum retransmission timeout during association setup in ms */
+#define SCTPCTL_INIT_RTO_MAX_DESC "Default maximum retransmission timeout during association setup in ms"
#define SCTPCTL_INIT_RTO_MAX_MIN 0
#define SCTPCTL_INIT_RTO_MAX_MAX 0xFFFFFFFF
#define SCTPCTL_INIT_RTO_MAX_DEFAULT SCTP_RTO_UPPER_BOUND
/* valid_cookie_life: Default cookie lifetime in sec */
-#define SCTPCTL_VALID_COOKIE_LIFE_DESC "Default cookie lifetime in sec"
+#define SCTPCTL_VALID_COOKIE_LIFE_DESC "Default cookie lifetime in seconds"
#define SCTPCTL_VALID_COOKIE_LIFE_MIN 0
#define SCTPCTL_VALID_COOKIE_LIFE_MAX 0xFFFFFFFF
#define SCTPCTL_VALID_COOKIE_LIFE_DEFAULT SCTP_DEFAULT_COOKIE_LIFE
@@ -312,8 +310,14 @@ struct sctp_sysctl {
#define SCTPCTL_PATH_RTX_MAX_MAX 0xFFFFFFFF
#define SCTPCTL_PATH_RTX_MAX_DEFAULT SCTP_DEF_MAX_PATH_RTX
-/* add_more_on_output: When space wise is it worthwhile to try to add more to a socket send buffer */
-#define SCTPCTL_ADD_MORE_ON_OUTPUT_DESC "When space wise is it worthwhile to try to add more to a socket send buffer"
+/* path_pf_threshold: threshold for considering the path potentially failed */
+#define SCTPCTL_PATH_PF_THRESHOLD_DESC "Default potentially failed threshold"
+#define SCTPCTL_PATH_PF_THRESHOLD_MIN 0
+#define SCTPCTL_PATH_PF_THRESHOLD_MAX 0xFFFF
+#define SCTPCTL_PATH_PF_THRESHOLD_DEFAULT SCTPCTL_PATH_PF_THRESHOLD_MAX
+
+/* add_more_on_output: When space-wise is it worthwhile to try to add more to a socket send buffer */
+#define SCTPCTL_ADD_MORE_ON_OUTPUT_DESC "When space-wise is it worthwhile to try to add more to a socket send buffer"
#define SCTPCTL_ADD_MORE_ON_OUTPUT_MIN 0
#define SCTPCTL_ADD_MORE_ON_OUTPUT_MAX 0xFFFFFFFF
#define SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT SCTP_DEFAULT_ADD_MORE
@@ -325,10 +329,10 @@ struct sctp_sysctl {
#define SCTPCTL_OUTGOING_STREAMS_DEFAULT SCTP_OSTREAM_INITIAL
/* cmt_on_off: CMT on/off flag */
-#define SCTPCTL_CMT_ON_OFF_DESC "CMT on/off flag"
-#define SCTPCTL_CMT_ON_OFF_MIN 0
-#define SCTPCTL_CMT_ON_OFF_MAX 1
-#define SCTPCTL_CMT_ON_OFF_DEFAULT 0
+#define SCTPCTL_CMT_ON_OFF_DESC "CMT settings"
+#define SCTPCTL_CMT_ON_OFF_MIN SCTP_CMT_OFF
+#define SCTPCTL_CMT_ON_OFF_MAX SCTP_CMT_MAX
+#define SCTPCTL_CMT_ON_OFF_DEFAULT SCTP_CMT_OFF
/* EY - nr_sack_on_off: NR_SACK on/off flag */
#define SCTPCTL_NR_SACK_ON_OFF_DESC "NR_SACK on/off flag"
@@ -342,30 +346,12 @@ struct sctp_sysctl {
#define SCTPCTL_CMT_USE_DAC_MAX 1
#define SCTPCTL_CMT_USE_DAC_DEFAULT 0
-/* JRS 5/2107 - CMT PF type flag */
-#define SCTPCTL_CMT_PF_DESC "CMT PF type flag"
-#define SCTPCTL_CMT_PF_MIN 0
-#define SCTPCTL_CMT_PF_MAX 2
-#define SCTPCTL_CMT_PF_DEFAULT 0
-
/* cwnd_maxburst: Use a CWND adjusting maxburst */
#define SCTPCTL_CWND_MAXBURST_DESC "Use a CWND adjusting maxburst"
#define SCTPCTL_CWND_MAXBURST_MIN 0
#define SCTPCTL_CWND_MAXBURST_MAX 1
#define SCTPCTL_CWND_MAXBURST_DEFAULT 1
-/* early_fast_retran: Early Fast Retransmit with timer */
-#define SCTPCTL_EARLY_FAST_RETRAN_DESC "Early Fast Retransmit with timer"
-#define SCTPCTL_EARLY_FAST_RETRAN_MIN 0
-#define SCTPCTL_EARLY_FAST_RETRAN_MAX 0xFFFFFFFF
-#define SCTPCTL_EARLY_FAST_RETRAN_DEFAULT 0
-
-/* early_fast_retran_msec: Early Fast Retransmit minimum timer value */
-#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_DESC "Early Fast Retransmit minimum timer value"
-#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_MIN 0
-#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_MAX 0xFFFFFFFF
-#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_DEFAULT SCTP_MINFR_MSEC_TIMER
-
/* asconf_auth_nochk: Disable SCTP ASCONF AUTH requirement */
#define SCTPCTL_ASCONF_AUTH_NOCHK_DESC "Disable SCTP ASCONF AUTH requirement"
#define SCTPCTL_ASCONF_AUTH_NOCHK_MIN 0
@@ -388,7 +374,7 @@ struct sctp_sysctl {
#define SCTPCTL_ABC_L_VAR_DESC "SCTP ABC max increase per SACK (L)"
#define SCTPCTL_ABC_L_VAR_MIN 0
#define SCTPCTL_ABC_L_VAR_MAX 0xFFFFFFFF
-#define SCTPCTL_ABC_L_VAR_DEFAULT 1
+#define SCTPCTL_ABC_L_VAR_DEFAULT 2
/* max_chained_mbufs: Default max number of small mbufs on a chain */
#define SCTPCTL_MAX_CHAINED_MBUFS_DESC "Default max number of small mbufs on a chain"
@@ -406,7 +392,7 @@ struct sctp_sysctl {
#define SCTPCTL_HB_MAX_BURST_DESC "Confirmation Heartbeat max burst"
#define SCTPCTL_HB_MAX_BURST_MIN 1
#define SCTPCTL_HB_MAX_BURST_MAX 0xFFFFFFFF
-#define SCTPCTL_HB_MAX_BURST_DEFAULT SCTP_DEF_MAX_BURST
+#define SCTPCTL_HB_MAX_BURST_DEFAULT SCTP_DEF_HBMAX_BURST
/* abort_at_limit: When one-2-one hits qlimit abort */
#define SCTPCTL_ABORT_AT_LIMIT_DESC "When one-2-one hits qlimit abort"
@@ -444,6 +430,12 @@ struct sctp_sysctl {
#define SCTPCTL_DEFAULT_CC_MODULE_MAX 2
#define SCTPCTL_DEFAULT_CC_MODULE_DEFAULT 0
+/* RS - default stream scheduling module sysctl */
+#define SCTPCTL_DEFAULT_SS_MODULE_DESC "Default stream scheduling module"
+#define SCTPCTL_DEFAULT_SS_MODULE_MIN 0
+#define SCTPCTL_DEFAULT_SS_MODULE_MAX 5
+#define SCTPCTL_DEFAULT_SS_MODULE_DEFAULT 0
+
/* RRS - default fragment interleave */
#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC "Default fragment interleave level"
#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MIN 0
@@ -462,12 +454,6 @@ struct sctp_sysctl {
#define SCTPCTL_MOBILITY_FASTHANDOFF_MAX 1
#define SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT SCTP_DEFAULT_MOBILITY_FASTHANDOFF
-/* Enable SCTP/UDP tunneling for clients*/
-#define SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DESC "Enable SCTP/UDP tunneling for client"
-#define SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN 0
-#define SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MAX 1
-#define SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DEFAULT SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN
-
/* Enable SCTP/UDP tunneling port */
#define SCTPCTL_UDP_TUNNELING_PORT_DESC "Set the SCTP/UDP tunneling port"
#define SCTPCTL_UDP_TUNNELING_PORT_MIN 0
@@ -500,10 +486,42 @@ struct sctp_sysctl {
/* Initial congestion window in MTU */
#define SCTPCTL_INITIAL_CWND_DESC "Initial congestion window in MTUs"
-#define SCTPCTL_INITIAL_CWND_MIN 1
+#define SCTPCTL_INITIAL_CWND_MIN 0
#define SCTPCTL_INITIAL_CWND_MAX 0xffffffff
#define SCTPCTL_INITIAL_CWND_DEFAULT 3
+/* rttvar smooth avg for bw calc */
+#define SCTPCTL_RTTVAR_BW_DESC "Shift amount for bw smoothing on rtt calc"
+#define SCTPCTL_RTTVAR_BW_MIN 0
+#define SCTPCTL_RTTVAR_BW_MAX 32
+#define SCTPCTL_RTTVAR_BW_DEFAULT 4
+
+/* rttvar smooth avg for bw calc */
+#define SCTPCTL_RTTVAR_RTT_DESC "Shift amount for rtt smoothing on rtt calc"
+#define SCTPCTL_RTTVAR_RTT_MIN 0
+#define SCTPCTL_RTTVAR_RTT_MAX 32
+#define SCTPCTL_RTTVAR_RTT_DEFAULT 5
+
+#define SCTPCTL_RTTVAR_EQRET_DESC "What to return when rtt and bw are unchanged"
+#define SCTPCTL_RTTVAR_EQRET_MIN 0
+#define SCTPCTL_RTTVAR_EQRET_MAX 1
+#define SCTPCTL_RTTVAR_EQRET_DEFAULT 0
+
+#define SCTPCTL_RTTVAR_STEADYS_DESC "How many the sames it takes to try step down of cwnd"
+#define SCTPCTL_RTTVAR_STEADYS_MIN 0
+#define SCTPCTL_RTTVAR_STEADYS_MAX 0xFFFF
+#define SCTPCTL_RTTVAR_STEADYS_DEFAULT 20 /* 0 means disable feature */
+
+#define SCTPCTL_RTTVAR_DCCCECN_DESC "Enable for RTCC CC datacenter ECN"
+#define SCTPCTL_RTTVAR_DCCCECN_MIN 0
+#define SCTPCTL_RTTVAR_DCCCECN_MAX 1
+#define SCTPCTL_RTTVAR_DCCCECN_DEFAULT 1 /* 0 means disable feature */
+
+#define SCTPCTL_BLACKHOLE_DESC "Enable SCTP blackholing"
+#define SCTPCTL_BLACKHOLE_MIN 0
+#define SCTPCTL_BLACKHOLE_MAX 2
+#define SCTPCTL_BLACKHOLE_DEFAULT SCTPCTL_BLACKHOLE_MIN
+
#if defined(SCTP_DEBUG)
/* debug: Configure debug output */
#define SCTPCTL_DEBUG_DESC "Configure debug output"
@@ -513,7 +531,7 @@ struct sctp_sysctl {
#endif
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
#define SCTPCTL_OUTPUT_UNLOCKED_DESC "Unlock socket when sending packets down to IP."
#define SCTPCTL_OUTPUT_UNLOCKED_MIN 0
#define SCTPCTL_OUTPUT_UNLOCKED_MAX 1
diff --git a/freebsd/sys/netinet/sctp_timer.c b/freebsd/sys/netinet/sctp_timer.c
index 4fbded33..950d3f71 100644
--- a/freebsd/sys/netinet/sctp_timer.c
+++ b/freebsd/sys/netinet/sctp_timer.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,8 +32,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_timer.c,v 1.29 2005/03/06 16:04:18 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -55,105 +55,6 @@ __FBSDID("$FreeBSD$");
void
-sctp_early_fr_timer(struct sctp_inpcb *inp,
- struct sctp_tcb *stcb,
- struct sctp_nets *net)
-{
- struct sctp_tmit_chunk *chk, *tp2;
- struct timeval now, min_wait, tv;
- unsigned int cur_rtt, cnt = 0, cnt_resend = 0;
-
- /* an early FR is occuring. */
- (void)SCTP_GETTIME_TIMEVAL(&now);
- /* get cur rto in micro-seconds */
- if (net->lastsa == 0) {
- /* Hmm no rtt estimate yet? */
- cur_rtt = stcb->asoc.initial_rto >> 2;
- } else {
-
- cur_rtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
- }
- if (cur_rtt < SCTP_BASE_SYSCTL(sctp_early_fr_msec)) {
- cur_rtt = SCTP_BASE_SYSCTL(sctp_early_fr_msec);
- }
- cur_rtt *= 1000;
- tv.tv_sec = cur_rtt / 1000000;
- tv.tv_usec = cur_rtt % 1000000;
- min_wait = now;
- timevalsub(&min_wait, &tv);
- if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) {
- /*
- * if we hit here, we don't have enough seconds on the clock
- * to account for the RTO. We just let the lower seconds be
- * the bounds and don't worry about it. This may mean we
- * will mark a lot more than we should.
- */
- min_wait.tv_sec = min_wait.tv_usec = 0;
- }
- chk = TAILQ_LAST(&stcb->asoc.sent_queue, sctpchunk_listhead);
- for (; chk != NULL; chk = tp2) {
- tp2 = TAILQ_PREV(chk, sctpchunk_listhead, sctp_next);
- if (chk->whoTo != net) {
- continue;
- }
- if (chk->sent == SCTP_DATAGRAM_RESEND)
- cnt_resend++;
- else if ((chk->sent > SCTP_DATAGRAM_UNSENT) &&
- (chk->sent < SCTP_DATAGRAM_RESEND)) {
- /* pending, may need retran */
- if (chk->sent_rcv_time.tv_sec > min_wait.tv_sec) {
- /*
- * we have reached a chunk that was sent
- * some seconds past our min.. forget it we
- * will find no more to send.
- */
- continue;
- } else if (chk->sent_rcv_time.tv_sec == min_wait.tv_sec) {
- /*
- * we must look at the micro seconds to
- * know.
- */
- if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) {
- /*
- * ok it was sent after our boundary
- * time.
- */
- continue;
- }
- }
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_EARLYFR_LOGGING_ENABLE) {
- sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count,
- 4, SCTP_FR_MARKED_EARLY);
- }
- SCTP_STAT_INCR(sctps_earlyfrmrkretrans);
- chk->sent = SCTP_DATAGRAM_RESEND;
- sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
- /* double book size since we are doing an early FR */
- chk->book_size_scale++;
- cnt += chk->send_size;
- if ((cnt + net->flight_size) > net->cwnd) {
- /* Mark all we could possibly resend */
- break;
- }
- }
- }
- if (cnt) {
- /*
- * JRS - Use the congestion control given in the congestion
- * control module
- */
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer(inp, stcb, net);
- } else if (cnt_resend) {
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
- }
- /* Restart it? */
- if (net->flight_size < net->cwnd) {
- SCTP_STAT_INCR(sctps_earlyfrstrtmr);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
- }
-}
-
-void
sctp_audit_retranmission_queue(struct sctp_association *asoc)
{
struct sctp_tmit_chunk *chk;
@@ -191,50 +92,28 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (net) {
net->error_count++;
SCTPDBG(SCTP_DEBUG_TIMER4, "Error count for %p now %d thresh:%d\n",
- net, net->error_count,
+ (void *)net, net->error_count,
net->failure_threshold);
if (net->error_count > net->failure_threshold) {
/* We had a threshold failure */
if (net->dest_state & SCTP_ADDR_REACHABLE) {
net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY;
- if (net == stcb->asoc.primary_destination) {
- net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
- }
- /*
- * JRS 5/14/07 - If a destination is
- * unreachable, the PF bit is turned off.
- * This allows an unambiguous use of the PF
- * bit for destinations that are reachable
- * but potentially failed. If the
- * destination is set to the unreachable
- * state, also set the destination to the PF
- * state.
- */
- /*
- * Add debug message here if destination is
- * not in PF state.
- */
- /* Stop any running T3 timers here? */
- if ((stcb->asoc.sctp_cmt_on_off == 1) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
- net);
- }
+ net->dest_state &= ~SCTP_ADDR_PF;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
- stcb,
- SCTP_FAILED_THRESHOLD,
+ stcb, 0,
(void *)net, SCTP_SO_NOT_LOCKED);
}
+ } else if ((net->pf_threshold < net->failure_threshold) &&
+ (net->error_count > net->pf_threshold)) {
+ if (!(net->dest_state & SCTP_ADDR_PF)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ net->last_active = sctp_get_tick_count();
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
}
- /*********HOLD THIS COMMENT FOR PATCH OF ALTERNATE
- *********ROUTING CODE
- */
- /*********HOLD THIS COMMENT FOR END OF PATCH OF ALTERNATE
- *********ROUTING CODE
- */
}
if (stcb == NULL)
return (0);
@@ -261,7 +140,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
stcb->asoc.overall_error_count++;
}
SCTPDBG(SCTP_DEBUG_TIMER4, "Overall error count for %p now %d thresh:%u state:%x\n",
- &stcb->asoc, stcb->asoc.overall_error_count,
+ (void *)&stcb->asoc, stcb->asoc.overall_error_count,
(uint32_t) threshold,
((net == NULL) ? (uint32_t) 0 : (uint32_t) net->dest_state));
/*
@@ -287,7 +166,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
*ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_1);
}
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1;
- sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(inp, stcb, oper, SCTP_SO_NOT_LOCKED);
return (1);
}
return (0);
@@ -409,31 +288,10 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
}
}
}
- /*
- * JRS 5/14/07 - After all destination have been considered
- * as alternates, check to see if there was some active
- * destination (not in PF state). If not, check to see if
- * there was some PF destination with the minimum number of
- * errors. If not, return the original destination. If
- * there is a min_errors_net, remove the PF flag from that
- * destination, set the cwnd to one or two MTUs, and return
- * the destination as an alt. If there was some active
- * destination with a highest cwnd, return the destination
- * as an alt.
- */
if (max_cwnd_net == NULL) {
if (min_errors_net == NULL) {
return (net);
}
- min_errors_net->dest_state &= ~SCTP_ADDR_PF;
- min_errors_net->cwnd = min_errors_net->mtu * stcb->asoc.sctp_cmt_pf;
- if (SCTP_OS_TIMER_PENDING(&min_errors_net->rxt_timer.timer)) {
- sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
- stcb, min_errors_net,
- SCTP_FROM_SCTP_TIMER + SCTP_LOC_2);
- }
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to active with %d errors.\n",
- min_errors_net, min_errors_net->error_count);
return (min_errors_net);
} else {
return (max_cwnd_net);
@@ -576,20 +434,19 @@ sctp_backoff_on_timeout(struct sctp_tcb *stcb,
static void
sctp_recover_sent_list(struct sctp_tcb *stcb)
{
- struct sctp_tmit_chunk *chk, *tp2;
+ struct sctp_tmit_chunk *chk, *nchk;
struct sctp_association *asoc;
asoc = &stcb->asoc;
- chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
- for (; chk != NULL; chk = tp2) {
- tp2 = TAILQ_NEXT(chk, sctp_next);
- if ((compare_with_wrap(stcb->asoc.last_acked_seq,
- chk->rec.data.TSN_seq,
- MAX_TSN)) ||
- (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) {
-
+ TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
+ if (SCTP_TSN_GE(asoc->last_acked_seq, chk->rec.data.TSN_seq)) {
SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n",
- chk, chk->rec.data.TSN_seq, stcb->asoc.last_acked_seq);
+ (void *)chk, chk->rec.data.TSN_seq, asoc->last_acked_seq);
+ if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
+ if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
+ }
+ }
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
if (chk->pr_sctp_on) {
if (asoc->pr_sctp_cnt != 0)
@@ -599,20 +456,18 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
/* sa_ignore NO_NULL_CHK */
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_m_freem(chk->data);
+ chk->data = NULL;
if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) {
asoc->sent_queue_cnt_removeable--;
}
}
- chk->data = NULL;
asoc->sent_queue_cnt--;
- sctp_free_a_chunk(stcb, chk);
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
}
}
SCTP_PRINTF("after recover order is as follows\n");
- chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
- for (; chk != NULL; chk = tp2) {
- tp2 = TAILQ_NEXT(chk, sctp_next);
- SCTP_PRINTF("chk:%p TSN:%x\n", chk, chk->rec.data.TSN_seq);
+ TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
+ SCTP_PRINTF("chk:%p TSN:%x\n", (void *)chk, chk->rec.data.TSN_seq);
}
}
@@ -633,10 +488,10 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
* We only mark chunks that have been outstanding long enough to
* have received feed-back.
*/
- struct sctp_tmit_chunk *chk, *tp2;
+ struct sctp_tmit_chunk *chk, *nchk;
struct sctp_nets *lnets;
struct timeval now, min_wait, tv;
- int cur_rtt;
+ int cur_rto;
int cnt_abandoned;
int audit_tf, num_mk, fir;
unsigned int cnt_mk;
@@ -654,21 +509,18 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
*/
(void)SCTP_GETTIME_TIMEVAL(&now);
/* get cur rto in micro-seconds */
- cur_rtt = (((net->lastsa >> 2) + net->lastsv) >> 1);
- cur_rtt *= 1000;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
- sctp_log_fr(cur_rtt,
+ cur_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
+ cur_rto *= 1000;
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
+ sctp_log_fr(cur_rto,
stcb->asoc.peers_rwnd,
window_probe,
SCTP_FR_T3_MARK_TIME);
- sctp_log_fr(net->flight_size,
- SCTP_OS_TIMER_PENDING(&net->fr_timer.timer),
- SCTP_OS_TIMER_ACTIVE(&net->fr_timer.timer),
- SCTP_FR_CWND_REPORT);
+ sctp_log_fr(net->flight_size, 0, 0, SCTP_FR_CWND_REPORT);
sctp_log_fr(net->flight_size, net->cwnd, stcb->asoc.total_flight, SCTP_FR_CWND_REPORT);
}
- tv.tv_sec = cur_rtt / 1000000;
- tv.tv_usec = cur_rtt % 1000000;
+ tv.tv_sec = cur_rto / 1000000;
+ tv.tv_usec = cur_rto % 1000000;
min_wait = now;
timevalsub(&min_wait, &tv);
if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) {
@@ -680,8 +532,8 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
*/
min_wait.tv_sec = min_wait.tv_usec = 0;
}
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
- sctp_log_fr(cur_rtt, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
+ sctp_log_fr(cur_rto, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME);
sctp_log_fr(0, min_wait.tv_sec, min_wait.tv_usec, SCTP_FR_T3_MARK_TIME);
}
/*
@@ -699,13 +551,8 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
#ifndef INVARIANTS
start_again:
#endif
- chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
- for (; chk != NULL; chk = tp2) {
- tp2 = TAILQ_NEXT(chk, sctp_next);
- if ((compare_with_wrap(stcb->asoc.last_acked_seq,
- chk->rec.data.TSN_seq,
- MAX_TSN)) ||
- (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) {
+ TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) {
+ if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.TSN_seq)) {
/* Strange case our list got out of order? */
SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x",
(unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq);
@@ -732,7 +579,7 @@ start_again:
*/
/* validate its been outstanding long enough */
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(chk->rec.data.TSN_seq,
chk->sent_rcv_time.tv_sec,
chk->sent_rcv_time.tv_usec,
@@ -744,7 +591,7 @@ start_again:
* some seconds past our min.. forget it we
* will find no more to send.
*/
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(0,
chk->sent_rcv_time.tv_sec,
chk->sent_rcv_time.tv_usec,
@@ -762,12 +609,6 @@ start_again:
* ok it was sent after our boundary
* time.
*/
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
- sctp_log_fr(0,
- chk->sent_rcv_time.tv_sec,
- chk->sent_rcv_time.tv_usec,
- SCTP_FR_T3_STOPPED);
- }
continue;
}
}
@@ -778,7 +619,7 @@ start_again:
if (chk->data) {
(void)sctp_release_pr_sctp_chunk(stcb,
chk,
- (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
+ 1,
SCTP_SO_NOT_LOCKED);
cnt_abandoned++;
}
@@ -791,7 +632,7 @@ start_again:
if (chk->data) {
(void)sctp_release_pr_sctp_chunk(stcb,
chk,
- (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
+ 1,
SCTP_SO_NOT_LOCKED);
cnt_abandoned++;
}
@@ -806,7 +647,7 @@ start_again:
tsnfirst = chk->rec.data.TSN_seq;
}
tsnlast = chk->rec.data.TSN_seq;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count,
0, SCTP_FR_T3_MARKED);
}
@@ -835,6 +676,12 @@ start_again:
/* reset the TSN for striking and other FR stuff */
chk->rec.data.doing_fast_retransmit = 0;
/* Clear any time so NO RTT is being done */
+
+ if (chk->do_rtt) {
+ if (chk->whoTo->rto_needed == 0) {
+ chk->whoTo->rto_needed = 1;
+ }
+ }
chk->do_rtt = 0;
if (alt != net) {
sctp_free_remote_addr(chk->whoTo);
@@ -852,7 +699,7 @@ start_again:
/*
* CMT: Do not allow FRs on retransmitted TSNs.
*/
- if (stcb->asoc.sctp_cmt_on_off == 1) {
+ if (stcb->asoc.sctp_cmt_on_off > 0) {
chk->no_fr_allowed = 1;
}
#ifdef THIS_SHOULD_NOT_BE_DONE
@@ -869,7 +716,7 @@ start_again:
/* we did not subtract the same things? */
audit_tf = 1;
}
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT);
}
#ifdef SCTP_DEBUG
@@ -927,7 +774,7 @@ start_again:
if (audit_tf) {
SCTPDBG(SCTP_DEBUG_TIMER4,
"Audit total flight due to negative value net:%p\n",
- net);
+ (void *)net);
stcb->asoc.total_flight = 0;
stcb->asoc.total_flight_count = 0;
/* Clear all networks flight size */
@@ -935,7 +782,7 @@ start_again:
lnets->flight_size = 0;
SCTPDBG(SCTP_DEBUG_TIMER4,
"Net:%p c-f cwnd:%d ssthresh:%d\n",
- lnets, lnets->cwnd, lnets->ssthresh);
+ (void *)lnets, lnets->cwnd, lnets->ssthresh);
}
TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
if (chk->sent < SCTP_DATAGRAM_RESEND) {
@@ -951,19 +798,6 @@ start_again:
}
}
}
- /*
- * Setup the ecn nonce re-sync point. We do this since
- * retranmissions are NOT setup for ECN. This means that do to
- * Karn's rule, we don't know the total of the peers ecn bits.
- */
- chk = TAILQ_FIRST(&stcb->asoc.send_queue);
- if (chk == NULL) {
- stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq;
- } else {
- stcb->asoc.nonce_resync_tsn = chk->rec.data.TSN_seq;
- }
- stcb->asoc.nonce_wait_for_ecne = 0;
- stcb->asoc.nonce_sum_check = 0;
/* We return 1 if we only have a window probe outstanding */
return (0);
}
@@ -1000,58 +834,6 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
win_probe = 0;
}
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination if not already
- * in PF state, set the destination to PF state and store the
- * current time as the time that the destination was last active. In
- * addition, find an alternate destination with PF-based
- * find_alt_net().
- */
- if ((stcb->asoc.sctp_cmt_on_off == 1) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- if ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF) {
- net->dest_state |= SCTP_ADDR_PF;
- net->last_active = sctp_get_tick_count();
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from active to PF.\n",
- net);
- }
- alt = sctp_find_alternate_net(stcb, net, 2);
- } else if (stcb->asoc.sctp_cmt_on_off == 1) {
- /*
- * CMT: Using RTX_SSTHRESH policy for CMT. If CMT is being
- * used, then pick dest with largest ssthresh for any
- * retransmission.
- */
- alt = sctp_find_alternate_net(stcb, net, 1);
- /*
- * CUCv2: If a different dest is picked for the
- * retransmission, then new (rtx-)pseudo_cumack needs to be
- * tracked for orig dest. Let CUCv2 track new (rtx-)
- * pseudo-cumack always.
- */
- net->find_pseudo_cumack = 1;
- net->find_rtx_pseudo_cumack = 1;
- } else { /* CMT is OFF */
- alt = sctp_find_alternate_net(stcb, net, 0);
- }
- num_mk = 0;
- num_abandoned = 0;
- (void)sctp_mark_all_for_resend(stcb, net, alt, win_probe,
- &num_mk, &num_abandoned);
- /* FR Loss recovery just ended with the T3. */
- stcb->asoc.fast_retran_loss_recovery = 0;
-
- /* CMT FR loss recovery ended with the T3 */
- net->fast_retran_loss_recovery = 0;
-
- /*
- * setup the sat loss recovery that prevents satellite cwnd advance.
- */
- stcb->asoc.sat_t3_loss_recovery = 1;
- stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq;
-
- /* Backoff the timer and cwnd */
- sctp_backoff_on_timeout(stcb, net, win_probe, num_mk, num_abandoned);
if (win_probe == 0) {
/* We don't do normal threshold management on window probes */
if (sctp_threshold_management(inp, stcb, net,
@@ -1070,17 +852,15 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
} else {
ms_goneby = 0;
}
- if ((ms_goneby > net->RTO) || (net->RTO == 0)) {
- /*
- * no recent feed back in an RTO or
- * more, request a RTT update
- */
- if (sctp_send_hb(stcb, 1, net) < 0)
+ if ((net->dest_state & SCTP_ADDR_PF) == 0) {
+ if ((ms_goneby > net->RTO) || (net->RTO == 0)) {
/*
- * Less than 0 means we lost
- * the assoc
+ * no recent feed back in an
+ * RTO or more, request a
+ * RTT update
*/
- return (1);
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
+ }
}
}
}
@@ -1097,7 +877,52 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
return (1);
}
}
- if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
+ if (stcb->asoc.sctp_cmt_on_off > 0) {
+ if (net->pf_threshold < net->failure_threshold) {
+ alt = sctp_find_alternate_net(stcb, net, 2);
+ } else {
+ /*
+ * CMT: Using RTX_SSTHRESH policy for CMT. If CMT is
+ * being used, then pick dest with largest ssthresh
+ * for any retransmission.
+ */
+ alt = sctp_find_alternate_net(stcb, net, 1);
+ /*
+ * CUCv2: If a different dest is picked for the
+ * retransmission, then new (rtx-)pseudo_cumack
+ * needs to be tracked for orig dest. Let CUCv2
+ * track new (rtx-) pseudo-cumack always.
+ */
+ net->find_pseudo_cumack = 1;
+ net->find_rtx_pseudo_cumack = 1;
+ }
+ } else {
+ alt = sctp_find_alternate_net(stcb, net, 0);
+ }
+
+ num_mk = 0;
+ num_abandoned = 0;
+ (void)sctp_mark_all_for_resend(stcb, net, alt, win_probe,
+ &num_mk, &num_abandoned);
+ /* FR Loss recovery just ended with the T3. */
+ stcb->asoc.fast_retran_loss_recovery = 0;
+
+ /* CMT FR loss recovery ended with the T3 */
+ net->fast_retran_loss_recovery = 0;
+ if ((stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) &&
+ (net->flight_size == 0)) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) (stcb, net);
+ }
+ /*
+ * setup the sat loss recovery that prevents satellite cwnd advance.
+ */
+ stcb->asoc.sat_t3_loss_recovery = 1;
+ stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq;
+
+ /* Backoff the timer and cwnd */
+ sctp_backoff_on_timeout(stcb, net, win_probe, num_mk, num_abandoned);
+ if ((!(net->dest_state & SCTP_ADDR_REACHABLE)) ||
+ (net->dest_state & SCTP_ADDR_PF)) {
/* Move all pending over too */
sctp_move_chunks_from_net(stcb, net);
@@ -1125,23 +950,12 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
* change-primary then this flag must be cleared
* from any net structures.
*/
- if (sctp_set_primary_addr(stcb,
- (struct sockaddr *)NULL,
- alt) == 0) {
- net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
+ if (stcb->asoc.alternate) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
}
+ stcb->asoc.alternate = alt;
+ atomic_add_int(&stcb->asoc.alternate->ref_count, 1);
}
- } else if ((stcb->asoc.sctp_cmt_on_off == 1) &&
- (stcb->asoc.sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- /*
- * JRS 5/14/07 - If the destination hasn't failed completely
- * but is in PF state, a PF-heartbeat needs to be sent
- * manually.
- */
- if (sctp_send_hb(stcb, 1, net) < 0)
- /* Return less than 0 means we lost the association */
- return (1);
}
/*
* Special case for cookie-echo'ed case, we don't do output but must
@@ -1160,13 +974,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);
/* C3. See if we need to send a Fwd-TSN */
- if (compare_with_wrap(stcb->asoc.advanced_peer_ack_point,
- stcb->asoc.last_acked_seq, MAX_TSN)) {
- /*
- * ISSUE with ECN, see FWD-TSN processing for notes
- * on issues that will occur when the ECN NONCE
- * stuff is put into SCTP for cross checking.
- */
+ if (SCTP_TSN_GT(stcb->asoc.advanced_peer_ack_point, stcb->asoc.last_acked_seq)) {
send_forward_tsn(stcb, &stcb->asoc);
if (lchk) {
/* Assure a timer is up */
@@ -1231,7 +1039,7 @@ sctp_t1init_timer(struct sctp_inpcb *inp,
int
sctp_cookie_timer(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
- struct sctp_nets *net)
+ struct sctp_nets *net SCTP_UNUSED)
{
struct sctp_nets *alt;
struct sctp_tmit_chunk *cookie;
@@ -1262,8 +1070,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
*ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
}
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_4;
- sctp_abort_an_association(inp, stcb, SCTP_INTERNAL_ERROR,
- oper, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(inp, stcb, oper, SCTP_SO_NOT_LOCKED);
} else {
#ifdef INVARIANTS
panic("Cookie timer expires in wrong state?");
@@ -1349,7 +1156,7 @@ sctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
atomic_add_int(&alt->ref_count, 1);
}
}
- if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
/*
* If the address went un-reachable, we need to move to
* alternates for ALL chk's in queue
@@ -1371,7 +1178,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net)
{
struct sctp_nets *alt;
- struct sctp_tmit_chunk *asconf, *chk, *nchk;
+ struct sctp_tmit_chunk *asconf, *chk;
/* is this a first send, or a retransmission? */
if (TAILQ_EMPTY(&stcb->asoc.asconf_send_queue)) {
@@ -1429,8 +1236,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
atomic_add_int(&alt->ref_count, 1);
}
}
- for (chk = asconf; chk; chk = nchk) {
- nchk = TAILQ_NEXT(chk, sctp_next);
+ TAILQ_FOREACH(chk, &stcb->asoc.asconf_send_queue, sctp_next) {
if (chk->whoTo != alt) {
sctp_free_remote_addr(chk->whoTo);
chk->whoTo = alt;
@@ -1440,7 +1246,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
chk->sent = SCTP_DATAGRAM_RESEND;
}
- if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
/*
* If the address went un-reachable, we need to move
* to the alternate for ALL chunks in queue
@@ -1461,7 +1267,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* Mobility adaptation */
void
sctp_delete_prim_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net)
+ struct sctp_nets *net SCTP_UNUSED)
{
if (stcb->asoc.deleted_primary == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: deleted_primary is not stored...\n");
@@ -1532,9 +1338,8 @@ static void
sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
struct sctp_tcb *stcb)
{
- struct sctp_stream_out *outs;
struct sctp_stream_queue_pending *sp;
- unsigned int chks_in_queue = 0;
+ unsigned int i, chks_in_queue = 0;
int being_filled = 0;
/*
@@ -1548,32 +1353,21 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
stcb->asoc.sent_queue_retran_cnt);
stcb->asoc.sent_queue_retran_cnt = 0;
}
- SCTP_TCB_SEND_LOCK(stcb);
- if (TAILQ_EMPTY(&stcb->asoc.out_wheel)) {
- int i, cnt = 0;
-
- /* Check to see if a spoke fell off the wheel */
- for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
- if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
- sctp_insert_on_wheel(stcb, &stcb->asoc, &stcb->asoc.strmout[i], 1);
- cnt++;
- }
- }
- if (cnt) {
- /* yep, we lost a spoke or two */
- SCTP_PRINTF("Found an additional %d streams NOT on outwheel, corrected\n", cnt);
+ if (stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) {
+ /* No stream scheduler information, initialize scheduler */
+ stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 0);
+ if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, &stcb->asoc)) {
+ /* yep, we lost a stream or two */
+ SCTP_PRINTF("Found additional streams NOT managed by scheduler, corrected\n");
} else {
- /* no spokes lost, */
+ /* no streams lost */
stcb->asoc.total_output_queue_size = 0;
}
- SCTP_TCB_SEND_UNLOCK(stcb);
- return;
}
- SCTP_TCB_SEND_UNLOCK(stcb);
/* Check to see if some data queued, if so report it */
- TAILQ_FOREACH(outs, &stcb->asoc.out_wheel, next_spoke) {
- if (!TAILQ_EMPTY(&outs->outqueue)) {
- TAILQ_FOREACH(sp, &outs->outqueue, next) {
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
+ TAILQ_FOREACH(sp, &stcb->asoc.strmout[i].outqueue, next) {
if (sp->msg_is_complete)
being_filled++;
chks_in_queue++;
@@ -1607,66 +1401,62 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
int
sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net, int cnt_of_unconf)
+ struct sctp_nets *net)
{
- int ret;
+ uint8_t net_was_pf;
- if (net) {
- if (net->hb_responded == 0) {
- if (net->ro._s_addr) {
- /*
- * Invalidate the src address if we did not
- * get a response last time.
- */
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
- net->src_addr_selected = 0;
- }
- sctp_backoff_on_timeout(stcb, net, 1, 0, 0);
+ if (net->dest_state & SCTP_ADDR_PF) {
+ net_was_pf = 1;
+ } else {
+ net_was_pf = 0;
+ }
+ if (net->hb_responded == 0) {
+ if (net->ro._s_addr) {
+ /*
+ * Invalidate the src address if we did not get a
+ * response last time.
+ */
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
+ net->src_addr_selected = 0;
}
- /* Zero PBA, if it needs it */
- if (net->partial_bytes_acked) {
- net->partial_bytes_acked = 0;
+ sctp_backoff_on_timeout(stcb, net, 1, 0, 0);
+ if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
+ /* Assoc is over */
+ return (1);
}
}
+ /* Zero PBA, if it needs it */
+ if (net->partial_bytes_acked) {
+ net->partial_bytes_acked = 0;
+ }
if ((stcb->asoc.total_output_queue_size > 0) &&
(TAILQ_EMPTY(&stcb->asoc.send_queue)) &&
(TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
sctp_audit_stream_queues_for_size(inp, stcb);
}
- /* Send a new HB, this will do threshold managment, pick a new dest */
- if (cnt_of_unconf == 0) {
- if (sctp_send_hb(stcb, 0, NULL) < 0) {
- return (1);
- }
- } else {
+ if (!(net->dest_state & SCTP_ADDR_NOHB) &&
+ !((net_was_pf == 0) && (net->dest_state & SCTP_ADDR_PF))) {
/*
- * this will send out extra hb's up to maxburst if there are
- * any unconfirmed addresses.
+ * when move to PF during threshold mangement, a HB has been
+ * queued in that routine
*/
- uint32_t cnt_sent = 0;
-
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
- (net->dest_state & SCTP_ADDR_REACHABLE)) {
- cnt_sent++;
- if (net->hb_responded == 0) {
- /* Did we respond last time? */
- if (net->ro._s_addr) {
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
- net->src_addr_selected = 0;
- }
- }
- ret = sctp_send_hb(stcb, 1, net);
- if (ret < 0)
- return 1;
- else if (ret == 0) {
- break;
- }
- if (cnt_sent >= SCTP_BASE_SYSCTL(sctp_hb_maxburst))
- break;
- }
+ uint32_t ms_gone_by;
+
+ if ((net->last_sent_time.tv_sec > 0) ||
+ (net->last_sent_time.tv_usec > 0)) {
+ struct timeval diff;
+
+ SCTP_GETTIME_TIMEVAL(&diff);
+ timevalsub(&diff, &net->last_sent_time);
+ ms_gone_by = (uint32_t) (diff.tv_sec * 1000) +
+ (uint32_t) (diff.tv_usec / 1000);
+ } else {
+ ms_gone_by = 0xffffffff;
+ }
+ if ((ms_gone_by >= net->heart_beat_delay) ||
+ (net->dest_state & SCTP_ADDR_PF)) {
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
}
}
return (0);
@@ -1679,7 +1469,7 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp,
{
uint32_t next_mtu, mtu;
- next_mtu = sctp_get_next_mtu(inp, net->mtu);
+ next_mtu = sctp_get_next_mtu(net->mtu);
if ((next_mtu > net->mtu) && (net->port == 0)) {
if ((net->src_addr_selected == 0) ||
@@ -1770,19 +1560,27 @@ sctp_autoclose_timer(struct sctp_inpcb *inp,
*/
if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
/* only send SHUTDOWN 1st time thru */
- sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+ struct sctp_nets *netp;
+
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(stcb);
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
}
}
} else {
diff --git a/freebsd/sys/netinet/sctp_timer.h b/freebsd/sys/netinet/sctp_timer.h
index a26ad728..fd9df804 100644
--- a/freebsd/sys/netinet/sctp_timer.h
+++ b/freebsd/sys/netinet/sctp_timer.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,22 +30,17 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_timer.h,v 1.6 2005/03/06 16:04:18 itojun Exp $ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_timer_h__
-#define __sctp_timer_h__
+#ifndef _NETINET_SCTP_TIMER_H_
+#define _NETINET_SCTP_TIMER_H_
#if defined(_KERNEL) || defined(__Userspace__)
#define SCTP_RTT_SHIFT 3
#define SCTP_RTT_VAR_SHIFT 2
-void
-sctp_early_fr_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net);
-
struct sctp_nets *
sctp_find_alternate_net(struct sctp_tcb *,
struct sctp_nets *, int mode);
@@ -63,7 +60,7 @@ sctp_shutdown_timer(struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *);
int
sctp_heartbeat_timer(struct sctp_inpcb *, struct sctp_tcb *,
- struct sctp_nets *, int);
+ struct sctp_nets *);
int
sctp_cookie_timer(struct sctp_inpcb *, struct sctp_tcb *,
diff --git a/freebsd/sys/netinet/sctp_uio.h b/freebsd/sys/netinet/sctp_uio.h
index 4d72b1ca..d8e7da45 100644
--- a/freebsd/sys/netinet/sctp_uio.h
+++ b/freebsd/sys/netinet/sctp_uio.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,12 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_uio.h,v 1.11 2005/03/06 16:04:18 itojun Exp $ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctp_uio_h__
-#define __sctp_uio_h__
+#ifndef _NETINET_SCTP_UIO_H_
+#define _NETINET_SCTP_UIO_H_
#if ! defined(_KERNEL)
@@ -45,6 +46,16 @@ __FBSDID("$FreeBSD$");
typedef uint32_t sctp_assoc_t;
+#define SCTP_FUTURE_ASSOC 0
+#define SCTP_CURRENT_ASSOC 1
+#define SCTP_ALL_ASSOC 2
+
+struct sctp_event {
+ sctp_assoc_t se_assoc_id;
+ uint16_t se_type;
+ uint8_t se_on;
+};
+
/* Compatibility to previous define's */
#define sctp_stream_reset_events sctp_stream_reset_event
@@ -67,6 +78,14 @@ struct sctp_event_subscribe {
#define SCTP_INIT 0x0001
#define SCTP_SNDRCV 0x0002
#define SCTP_EXTRCV 0x0003
+#define SCTP_SNDINFO 0x0004
+#define SCTP_RCVINFO 0x0005
+#define SCTP_NXTINFO 0x0006
+#define SCTP_PRINFO 0x0007
+#define SCTP_AUTHINFO 0x0008
+#define SCTP_DSTADDRV4 0x0009
+#define SCTP_DSTADDRV6 0x000a
+
/*
* ancillary data structures
*/
@@ -91,8 +110,8 @@ struct sctp_initmsg {
*/
-#define SCTP_ALIGN_RESV_PAD 96
-#define SCTP_ALIGN_RESV_PAD_SHORT 80
+#define SCTP_ALIGN_RESV_PAD 92
+#define SCTP_ALIGN_RESV_PAD_SHORT 76
struct sctp_sndrcvinfo {
uint16_t sinfo_stream;
@@ -104,6 +123,8 @@ struct sctp_sndrcvinfo {
uint32_t sinfo_tsn;
uint32_t sinfo_cumtsn;
sctp_assoc_t sinfo_assoc_id;
+ uint16_t sinfo_keynumber;
+ uint16_t sinfo_keynumber_valid;
uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD];
};
@@ -111,7 +132,6 @@ struct sctp_extrcvinfo {
uint16_t sinfo_stream;
uint16_t sinfo_ssn;
uint16_t sinfo_flags;
- uint16_t sinfo_pr_policy;
uint32_t sinfo_ppid;
uint32_t sinfo_context;
uint32_t sinfo_timetolive;
@@ -123,15 +143,86 @@ struct sctp_extrcvinfo {
uint32_t sreinfo_next_aid;
uint32_t sreinfo_next_length;
uint32_t sreinfo_next_ppid;
+ uint16_t sinfo_keynumber;
+ uint16_t sinfo_keynumber_valid;
uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD_SHORT];
};
+struct sctp_sndinfo {
+ uint16_t snd_sid;
+ uint16_t snd_flags;
+ uint32_t snd_ppid;
+ uint32_t snd_context;
+ sctp_assoc_t snd_assoc_id;
+};
+
+struct sctp_prinfo {
+ uint16_t pr_policy;
+ uint32_t pr_value;
+};
+
+struct sctp_default_prinfo {
+ uint16_t pr_policy;
+ uint32_t pr_value;
+ sctp_assoc_t pr_assoc_id;
+};
+
+struct sctp_authinfo {
+ uint16_t auth_keynumber;
+};
+
+struct sctp_rcvinfo {
+ uint16_t rcv_sid;
+ uint16_t rcv_ssn;
+ uint16_t rcv_flags;
+ uint32_t rcv_ppid;
+ uint32_t rcv_tsn;
+ uint32_t rcv_cumtsn;
+ uint32_t rcv_context;
+ sctp_assoc_t rcv_assoc_id;
+};
+
+struct sctp_nxtinfo {
+ uint16_t nxt_sid;
+ uint16_t nxt_flags;
+ uint32_t nxt_ppid;
+ uint32_t nxt_length;
+ sctp_assoc_t nxt_assoc_id;
+};
+
#define SCTP_NO_NEXT_MSG 0x0000
#define SCTP_NEXT_MSG_AVAIL 0x0001
#define SCTP_NEXT_MSG_ISCOMPLETE 0x0002
#define SCTP_NEXT_MSG_IS_UNORDERED 0x0004
#define SCTP_NEXT_MSG_IS_NOTIFICATION 0x0008
+struct sctp_recvv_rn {
+ struct sctp_rcvinfo recvv_rcvinfo;
+ struct sctp_nxtinfo recvv_nxtinfo;
+};
+
+#define SCTP_RECVV_NOINFO 0
+#define SCTP_RECVV_RCVINFO 1
+#define SCTP_RECVV_NXTINFO 2
+#define SCTP_RECVV_RN 3
+
+#define SCTP_SENDV_NOINFO 0
+#define SCTP_SENDV_SNDINFO 1
+#define SCTP_SENDV_PRINFO 2
+#define SCTP_SENDV_AUTHINFO 3
+#define SCTP_SENDV_SPA 4
+
+struct sctp_sendv_spa {
+ uint32_t sendv_flags;
+ struct sctp_sndinfo sendv_sndinfo;
+ struct sctp_prinfo sendv_prinfo;
+ struct sctp_authinfo sendv_authinfo;
+};
+
+#define SCTP_SEND_SNDINFO_VALID 0x00000001
+#define SCTP_SEND_PRINFO_VALID 0x00000002
+#define SCTP_SEND_AUTHINFO_VALID 0x00000004
+
struct sctp_snd_all_completes {
uint16_t sall_stream;
uint16_t sall_flags;
@@ -142,6 +233,8 @@ struct sctp_snd_all_completes {
};
/* Flags that go into the sinfo->sinfo_flags field */
+#define SCTP_NOTIFICATION 0x0010 /* next message is a notification */
+#define SCTP_COMPLETE 0x0020 /* next message is complete */
#define SCTP_EOF 0x0100 /* Start shutdown procedures */
#define SCTP_ABORT 0x0200 /* Send an ABORT to peer */
#define SCTP_UNORDERED 0x0400 /* Message is un-ordered */
@@ -150,19 +243,20 @@ struct sctp_snd_all_completes {
#define SCTP_EOR 0x2000 /* end of message signal */
#define SCTP_SACK_IMMEDIATELY 0x4000 /* Set I-Bit */
-#define INVALID_SINFO_FLAG(x) (((x) & 0xffffff00 \
+#define INVALID_SINFO_FLAG(x) (((x) & 0xfffffff0 \
& ~(SCTP_EOF | SCTP_ABORT | SCTP_UNORDERED |\
SCTP_ADDR_OVER | SCTP_SENDALL | SCTP_EOR |\
SCTP_SACK_IMMEDIATELY)) != 0)
/* for the endpoint */
/* The lower byte is an enumeration of PR-SCTP policies */
+#define SCTP_PR_SCTP_NONE 0x0000/* Reliable transfer */
#define SCTP_PR_SCTP_TTL 0x0001/* Time based PR-SCTP */
#define SCTP_PR_SCTP_BUF 0x0002/* Buffer based PR-SCTP */
#define SCTP_PR_SCTP_RTX 0x0003/* Number of retransmissions based PR-SCTP */
-#define PR_SCTP_POLICY(x) ((x) & 0xff)
-#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != 0)
+#define PR_SCTP_POLICY(x) ((x) & 0x0f)
+#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE)
#define PR_SCTP_TTL_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL)
#define PR_SCTP_BUF_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF)
#define PR_SCTP_RTX_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX)
@@ -201,16 +295,23 @@ struct sctp_assoc_change {
uint16_t sac_outbound_streams;
uint16_t sac_inbound_streams;
sctp_assoc_t sac_assoc_id;
+ uint8_t sac_info[];
};
/* sac_state values */
-#define SCTP_COMM_UP 0x0001
-#define SCTP_COMM_LOST 0x0002
-#define SCTP_RESTART 0x0003
-#define SCTP_SHUTDOWN_COMP 0x0004
-#define SCTP_CANT_STR_ASSOC 0x0005
-
-
+#define SCTP_COMM_UP 0x0001
+#define SCTP_COMM_LOST 0x0002
+#define SCTP_RESTART 0x0003
+#define SCTP_SHUTDOWN_COMP 0x0004
+#define SCTP_CANT_STR_ASSOC 0x0005
+
+/* sac_info values */
+#define SCTP_ASSOC_SUPPORTS_PR 0x01
+#define SCTP_ASSOC_SUPPORTS_AUTH 0x02
+#define SCTP_ASSOC_SUPPORTS_ASCONF 0x03
+#define SCTP_ASSOC_SUPPORTS_MULTIBUF 0x04
+#define SCTP_ASSOC_SUPPORTS_RE_CONFIG 0x05
+#define SCTP_ASSOC_SUPPORTS_MAX 0x05
/*
* Address event
*/
@@ -233,31 +334,11 @@ struct sctp_paddr_change {
#define SCTP_ADDR_MADE_PRIM 0x0005
#define SCTP_ADDR_CONFIRMED 0x0006
-/*
- * CAUTION: these are user exposed SCTP addr reachability states must be
- * compatible with SCTP_ADDR states in sctp_constants.h
- */
-#ifdef SCTP_ACTIVE
-#undef SCTP_ACTIVE
-#endif
#define SCTP_ACTIVE 0x0001 /* SCTP_ADDR_REACHABLE */
-
-#ifdef SCTP_INACTIVE
-#undef SCTP_INACTIVE
-#endif
-#define SCTP_INACTIVE 0x0002 /* SCTP_ADDR_NOT_REACHABLE */
-
-#ifdef SCTP_UNCONFIRMED
-#undef SCTP_UNCONFIRMED
-#endif
+#define SCTP_INACTIVE 0x0002 /* neither SCTP_ADDR_REACHABLE nor
+ * SCTP_ADDR_UNCONFIRMED */
#define SCTP_UNCONFIRMED 0x0200 /* SCTP_ADDR_UNCONFIRMED */
-#ifdef SCTP_NOHEARTBEAT
-#undef SCTP_NOHEARTBEAT
-#endif
-#define SCTP_NOHEARTBEAT 0x0040 /* SCTP_ADDR_NOHB */
-
-
/* remote error events */
struct sctp_remote_error {
uint16_t sre_type;
@@ -268,7 +349,7 @@ struct sctp_remote_error {
uint8_t sre_data[4];
};
-/* data send failure event */
+/* data send failure event (deprecated) */
struct sctp_send_failed {
uint16_t ssf_type;
uint16_t ssf_flags;
@@ -279,6 +360,17 @@ struct sctp_send_failed {
uint8_t ssf_data[];
};
+/* data send failure event (not deprecated) */
+struct sctp_send_failed_event {
+ uint16_t ssfe_type;
+ uint16_t ssfe_flags;
+ uint32_t ssfe_length;
+ uint32_t ssfe_error;
+ struct sctp_sndinfo ssfe_info;
+ sctp_assoc_t ssfe_assoc_id;
+ uint8_t ssfe_data[];
+};
+
/* flag that indicates state of data */
#define SCTP_DATA_UNSENT 0x0001 /* inqueue never on wire */
#define SCTP_DATA_SENT 0x0002 /* on wire at failure */
@@ -349,7 +441,8 @@ struct sctp_authkey_event {
};
/* indication values */
-#define SCTP_AUTH_NEWKEY 0x0001
+#define SCTP_AUTH_NEW_KEY 0x0001
+#define SCTP_AUTH_NEWKEY SCTP_AUTH_NEW_KEY
#define SCTP_AUTH_NO_AUTH 0x0002
#define SCTP_AUTH_FREE_KEY 0x0003
@@ -363,23 +456,52 @@ struct sctp_sender_dry_event {
/*
- * stream reset event
+ * Stream reset event - subscribe to SCTP_STREAM_RESET_EVENT
*/
struct sctp_stream_reset_event {
uint16_t strreset_type;
uint16_t strreset_flags;
uint32_t strreset_length;
sctp_assoc_t strreset_assoc_id;
- uint16_t strreset_list[];
+ uint16_t strreset_stream_list[];
};
-/* flags in strreset_flags field */
-#define SCTP_STRRESET_INBOUND_STR 0x0001
-#define SCTP_STRRESET_OUTBOUND_STR 0x0002
-#define SCTP_STRRESET_ALL_STREAMS 0x0004
-#define SCTP_STRRESET_STREAM_LIST 0x0008
-#define SCTP_STRRESET_FAILED 0x0010
-#define SCTP_STRRESET_ADD_STREAM 0x0020
+/* flags in stream_reset_event (strreset_flags) */
+#define SCTP_STREAM_RESET_INCOMING_SSN 0x0001
+#define SCTP_STREAM_RESET_OUTGOING_SSN 0x0002
+#define SCTP_STREAM_RESET_DENIED 0x0004
+#define SCTP_STREAM_RESET_FAILED 0x0008
+
+/*
+ * Assoc reset event - subscribe to SCTP_ASSOC_RESET_EVENT
+ */
+struct sctp_assoc_reset_event {
+ uint16_t assocreset_type;
+ uint16_t assocreset_flags;
+ uint32_t assocreset_length;
+ sctp_assoc_t assocreset_assoc_id;
+ uint32_t assocreset_local_tsn;
+ uint32_t assocreset_remote_tsn;
+};
+
+#define SCTP_ASSOC_RESET_DENIED 0x0004
+#define SCTP_ASSOC_RESET_FAILED 0x0008
+
+/*
+ * Stream change event - subscribe to SCTP_STREAM_CHANGE_EVENT
+ */
+struct sctp_stream_change_event {
+ uint16_t strchange_type;
+ uint16_t strchange_flags;
+ uint32_t strchange_length;
+ sctp_assoc_t strchange_assoc_id;
+ uint16_t strchange_instrms;
+ uint16_t strchange_outstrms;
+};
+
+#define SCTP_STREAM_CHANGE_DENIED 0x0004
+#define SCTP_STREAM_CHANGE_FAILED 0x0008
+
/* SCTP notification event */
struct sctp_tlv {
@@ -401,23 +523,29 @@ union sctp_notification {
struct sctp_pdapi_event sn_pdapi_event;
struct sctp_authkey_event sn_auth_event;
struct sctp_sender_dry_event sn_sender_dry_event;
+ struct sctp_send_failed_event sn_send_failed_event;
struct sctp_stream_reset_event sn_strreset_event;
+ struct sctp_assoc_reset_event sn_assocreset_event;
+ struct sctp_stream_change_event sn_strchange_event;
};
/* notification types */
-#define SCTP_ASSOC_CHANGE 0x0001
-#define SCTP_PEER_ADDR_CHANGE 0x0002
-#define SCTP_REMOTE_ERROR 0x0003
-#define SCTP_SEND_FAILED 0x0004
-#define SCTP_SHUTDOWN_EVENT 0x0005
-#define SCTP_ADAPTATION_INDICATION 0x0006
+#define SCTP_ASSOC_CHANGE 0x0001
+#define SCTP_PEER_ADDR_CHANGE 0x0002
+#define SCTP_REMOTE_ERROR 0x0003
+#define SCTP_SEND_FAILED 0x0004
+#define SCTP_SHUTDOWN_EVENT 0x0005
+#define SCTP_ADAPTATION_INDICATION 0x0006
/* same as above */
-#define SCTP_ADAPTION_INDICATION 0x0006
-#define SCTP_PARTIAL_DELIVERY_EVENT 0x0007
-#define SCTP_AUTHENTICATION_EVENT 0x0008
-#define SCTP_STREAM_RESET_EVENT 0x0009
-#define SCTP_SENDER_DRY_EVENT 0x000a
-#define SCTP__NOTIFICATIONS_STOPPED_EVENT 0x000b /* we don't send this */
+#define SCTP_ADAPTION_INDICATION 0x0006
+#define SCTP_PARTIAL_DELIVERY_EVENT 0x0007
+#define SCTP_AUTHENTICATION_EVENT 0x0008
+#define SCTP_STREAM_RESET_EVENT 0x0009
+#define SCTP_SENDER_DRY_EVENT 0x000a
+#define SCTP_NOTIFICATIONS_STOPPED_EVENT 0x000b /* we don't send this */
+#define SCTP_ASSOC_RESET_EVENT 0x000c
+#define SCTP_STREAM_CHANGE_EVENT 0x000d
+#define SCTP_SEND_FAILED_EVENT 0x000e
/*
* socket option structs
*/
@@ -430,9 +558,11 @@ struct sctp_paddrparams {
uint32_t spp_flags;
uint32_t spp_ipv6_flowlabel;
uint16_t spp_pathmaxrxt;
- uint8_t spp_ipv4_tos;
+ uint8_t spp_dscp;
};
+#define spp_ipv4_tos spp_dscp
+
#define SPP_HB_ENABLE 0x00000001
#define SPP_HB_DISABLE 0x00000002
#define SPP_HB_DEMAND 0x00000004
@@ -440,7 +570,15 @@ struct sctp_paddrparams {
#define SPP_PMTUD_DISABLE 0x00000010
#define SPP_HB_TIME_IS_ZERO 0x00000080
#define SPP_IPV6_FLOWLABEL 0x00000100
-#define SPP_IPV4_TOS 0x00000200
+#define SPP_DSCP 0x00000200
+#define SPP_IPV4_TOS SPP_DSCP
+
+struct sctp_paddrthlds {
+ struct sockaddr_storage spt_address;
+ sctp_assoc_t spt_assoc_id;
+ uint16_t spt_pathmaxrxt;
+ uint16_t spt_pathpfthld;
+};
struct sctp_paddrinfo {
struct sockaddr_storage spinfo_address;
@@ -486,13 +624,6 @@ struct sctp_getaddresses {
struct sockaddr addr[1];
};
-struct sctp_setstrm_timeout {
- sctp_assoc_t ssto_assoc_id;
- uint32_t ssto_timeout;
- uint32_t ssto_streamid_start;
- uint32_t ssto_streamid_end;
-};
-
struct sctp_status {
sctp_assoc_t sstat_assoc_id;
int32_t sstat_state;
@@ -517,6 +648,7 @@ struct sctp_authchunk {
struct sctp_authkey {
sctp_assoc_t sca_assoc_id;
uint16_t sca_keynumber;
+ uint16_t sca_keylength;
uint8_t sca_key[];
};
@@ -544,6 +676,7 @@ struct sctp_authkeyid {
/* SCTP_PEER_AUTH_CHUNKS / SCTP_LOCAL_AUTH_CHUNKS */
struct sctp_authchunks {
sctp_assoc_t gauth_assoc_id;
+ uint32_t gauth_number_of_chunks;
uint8_t gauth_chunks[];
};
@@ -552,6 +685,17 @@ struct sctp_assoc_value {
uint32_t assoc_value;
};
+struct sctp_cc_option {
+ int option;
+ struct sctp_assoc_value aid_value;
+};
+
+struct sctp_stream_value {
+ sctp_assoc_t assoc_id;
+ uint16_t stream_id;
+ uint16_t stream_value;
+};
+
struct sctp_assoc_ids {
uint32_t gaids_number_of_ids;
sctp_assoc_t gaids_assoc_id[];
@@ -574,6 +718,12 @@ struct sctp_timeouts {
uint32_t stimo_shutdownack;
};
+struct sctp_udpencaps {
+ struct sockaddr_storage sue_address;
+ sctp_assoc_t sue_assoc_id;
+ uint16_t sue_port;
+};
+
struct sctp_cwnd_args {
struct sctp_nets *net; /* network to *//* FIXME: LP64 issue */
uint32_t cwnd_new_value;/* cwnd in k */
@@ -604,19 +754,18 @@ struct sctp_blk_args {
*/
#define SCTP_MAX_EXPLICT_STR_RESET 1000
-#define SCTP_RESET_LOCAL_RECV 0x0001
-#define SCTP_RESET_LOCAL_SEND 0x0002
-#define SCTP_RESET_BOTH 0x0003
-#define SCTP_RESET_TSN 0x0004
-#define SCTP_RESET_ADD_STREAMS 0x0005
-
-struct sctp_stream_reset {
- sctp_assoc_t strrst_assoc_id;
- uint16_t strrst_flags;
- uint16_t strrst_num_streams; /* 0 == ALL */
- uint16_t strrst_list[]; /* list if strrst_num_streams is not 0 */
+struct sctp_reset_streams {
+ sctp_assoc_t srs_assoc_id;
+ uint16_t srs_flags;
+ uint16_t srs_number_streams; /* 0 == ALL */
+ uint16_t srs_stream_list[]; /* list if strrst_num_streams is not 0 */
};
+struct sctp_add_streams {
+ sctp_assoc_t sas_assoc_id;
+ uint16_t sas_instrms;
+ uint16_t sas_outstrms;
+};
struct sctp_get_nonce_values {
sctp_assoc_t gn_assoc_id;
@@ -892,18 +1041,8 @@ struct sctpstat {
* fired */
uint32_t sctps_timoassockill; /* Number of asoc free timers expired */
uint32_t sctps_timoinpkill; /* Number of inp free timers expired */
- /* Early fast retransmission counters */
- uint32_t sctps_earlyfrstart;
- uint32_t sctps_earlyfrstop;
- uint32_t sctps_earlyfrmrkretrans;
- uint32_t sctps_earlyfrstpout;
- uint32_t sctps_earlyfrstpidsck1;
- uint32_t sctps_earlyfrstpidsck2;
- uint32_t sctps_earlyfrstpidsck3;
- uint32_t sctps_earlyfrstpidsck4;
- uint32_t sctps_earlyfrstrid;
- uint32_t sctps_earlyfrstrout;
- uint32_t sctps_earlyfrstrtmr;
+ /* former early FR counters */
+ uint32_t sctps_spare[11];
/* others */
uint32_t sctps_hdrops; /* packet shorter than header */
uint32_t sctps_badsum; /* checksum error */
@@ -942,7 +1081,7 @@ struct sctpstat {
uint32_t sctps_wu_sacks_sent; /* Window Update only sacks sent */
uint32_t sctps_sends_with_flags; /* number of sends with
* sinfo_flags !=0 */
- uint32_t sctps_sends_with_unord; /* number of unordered sends */
+ uint32_t sctps_sends_with_unord; /* number of unordered sends */
uint32_t sctps_sends_with_eof; /* number of sends with EOF flag set */
uint32_t sctps_sends_with_abort; /* number of sends with ABORT
* flag set */
@@ -961,8 +1100,9 @@ struct sctpstat {
* max burst inflight to net */
uint32_t sctps_fwdtsn_map_over; /* number of map array over-runs via
* fwd-tsn's */
-
- uint32_t sctps_reserved[32]; /* Future ABI compat - remove int's
+ uint32_t sctps_queue_upd_ecne; /* Number of times we queued or
+ * updated an ECN chunk on send queue */
+ uint32_t sctps_reserved[31]; /* Future ABI compat - remove int's
* from here when adding new */
};
@@ -984,12 +1124,8 @@ struct sctpstat {
#define SCTP_STAT_DECR_GAUGE32(_x) SCTP_STAT_DECR(_x)
union sctp_sockstore {
-#if defined(INET) || !defined(_KERNEL)
struct sockaddr_in sin;
-#endif
-#if defined(INET6) || !defined(_KERNEL)
struct sockaddr_in6 sin6;
-#endif
struct sockaddr sa;
};
@@ -1075,9 +1211,11 @@ struct xsctp_raddr {
uint8_t active; /* sctpAssocLocalRemEntry 3 */
uint8_t confirmed; /* */
uint8_t heartbeat_enabled; /* sctpAssocLocalRemEntry 4 */
+ uint8_t potentially_failed;
struct sctp_timeval start_time; /* sctpAssocLocalRemEntry 8 */
uint32_t rtt;
- uint32_t extra_padding[32]; /* future */
+ uint32_t heartbeat_interval;
+ uint32_t extra_padding[31]; /* future */
};
#define SCTP_MAX_LOGGING_SIZE 30000
@@ -1139,26 +1277,34 @@ int sctp_getladdrs __P((int, sctp_assoc_t, struct sockaddr **));
void sctp_freeladdrs __P((struct sockaddr *));
int sctp_opt_info __P((int, sctp_assoc_t, int, void *, socklen_t *));
+/* deprecated */
ssize_t sctp_sendmsg
-__P((int, const void *, size_t,
- const struct sockaddr *,
+__P((int, const void *, size_t, const struct sockaddr *,
socklen_t, uint32_t, uint32_t, uint16_t, uint32_t, uint32_t));
- ssize_t sctp_send __P((int sd, const void *msg, size_t len,
- const struct sctp_sndrcvinfo *sinfo, int flags));
+/* deprecated */
+ ssize_t sctp_send __P((int, const void *, size_t,
+ const struct sctp_sndrcvinfo *, int));
+
+/* deprecated */
+ ssize_t sctp_sendx __P((int, const void *, size_t, struct sockaddr *,
+ int, struct sctp_sndrcvinfo *, int));
+
+/* deprecated */
+ ssize_t sctp_sendmsgx __P((int sd, const void *, size_t, struct sockaddr *,
+ int, uint32_t, uint32_t, uint16_t, uint32_t, uint32_t));
- ssize_t sctp_sendx __P((int sd, const void *msg, size_t len,
- struct sockaddr *addrs, int addrcnt,
- struct sctp_sndrcvinfo *sinfo, int flags));
+ sctp_assoc_t sctp_getassocid __P((int, struct sockaddr *));
- ssize_t sctp_sendmsgx __P((int sd, const void *, size_t,
- struct sockaddr *, int,
- uint32_t, uint32_t, uint16_t, uint32_t, uint32_t));
+/* deprecated */
+ ssize_t sctp_recvmsg __P((int, void *, size_t, struct sockaddr *, socklen_t *,
+ struct sctp_sndrcvinfo *, int *));
- sctp_assoc_t sctp_getassocid __P((int sd, struct sockaddr *sa));
+ ssize_t sctp_sendv __P((int, const struct iovec *, int, struct sockaddr *,
+ int, void *, socklen_t, unsigned int, int));
- ssize_t sctp_recvmsg __P((int, void *, size_t, struct sockaddr *,
- socklen_t *, struct sctp_sndrcvinfo *, int *));
+ ssize_t sctp_recvv __P((int, const struct iovec *, int, struct sockaddr *,
+ socklen_t *, void *, socklen_t *, unsigned int *, int *));
__END_DECLS
diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c
index e901cf97..548ba9f3 100644
--- a/freebsd/sys/netinet/sctp_usrreq.c
+++ b/freebsd/sys/netinet/sctp_usrreq.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,16 +32,15 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_usrreq.c,v 1.48 2005/03/07 23:26:08 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+
#include <netinet/sctp_os.h>
#include <sys/proc.h>
#include <netinet/sctp_pcb.h>
#include <netinet/sctp_header.h>
#include <netinet/sctp_var.h>
-#if defined(INET6)
+#ifdef INET6
#endif
#include <netinet/sctp_sysctl.h>
#include <netinet/sctp_output.h>
@@ -50,19 +51,18 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_timer.h>
#include <netinet/sctp_auth.h>
#include <netinet/sctp_bsd_addr.h>
-#include <netinet/sctp_cc_functions.h>
#include <netinet/udp.h>
+extern struct sctp_cc_functions sctp_cc_functions[];
+extern struct sctp_ss_functions sctp_ss_functions[];
void
sctp_init(void)
{
u_long sb_max_adj;
- bzero(&SCTP_BASE_STATS, sizeof(struct sctpstat));
-
/* Initialize and modify the sysctled variables */
sctp_init_sysctls();
if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
@@ -80,7 +80,6 @@ sctp_init(void)
* now I will just copy.
*/
SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
-
SCTP_BASE_VAR(first_time) = 0;
SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
sctp_pcb_init();
@@ -89,8 +88,6 @@ sctp_init(void)
SCTP_BASE_VAR(packet_log_end) = 0;
bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
#endif
-
-
}
void
@@ -102,10 +99,7 @@ sctp_finish(void)
void
-sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
- struct sctp_tcb *stcb,
- struct sctp_nets *net,
- uint16_t nxtsz)
+sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
{
struct sctp_tmit_chunk *chk;
uint16_t overhead;
@@ -151,6 +145,7 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
}
}
+#ifdef INET
static void
sctp_notify_mbuf(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
@@ -213,7 +208,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp,
}
/* now what about the ep? */
if (stcb->asoc.smallest_mtu > nxtsz) {
- sctp_pathmtu_adjustment(inp, stcb, net, nxtsz);
+ sctp_pathmtu_adjustment(stcb, nxtsz);
}
if (tmr_stopped)
sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
@@ -221,6 +216,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp,
SCTP_TCB_UNLOCK(stcb);
}
+#endif
void
sctp_notify(struct sctp_inpcb *inp,
@@ -230,15 +226,13 @@ sctp_notify(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
- /* protection */
- int reason;
struct icmp *icmph;
-
+ /* protection */
if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
(sh == NULL) || (to == NULL)) {
if (stcb)
@@ -274,35 +268,10 @@ sctp_notify(struct sctp_inpcb *inp,
*/
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
- SCTP_PRINTF("ICMP (thresh %d/%d) takes interface %p down\n",
- net->error_count,
- net->failure_threshold,
- net);
-
net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
- /*
- * JRS 5/14/07 - If a destination is unreachable,
- * the PF bit is turned off. This allows an
- * unambiguous use of the PF bit for destinations
- * that are reachable but potentially failed. If the
- * destination is set to the unreachable state, also
- * set the destination to the PF state.
- */
- /*
- * Add debug message here if destination is not in
- * PF state.
- */
- /* Stop any running T3 timers here? */
- if ((stcb->asoc.sctp_cmt_on_off == 1) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
- net);
- }
- net->error_count = net->failure_threshold + 1;
+ net->dest_state &= ~SCTP_ADDR_PF;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
- stcb, SCTP_FAILED_THRESHOLD,
+ stcb, 0,
(void *)net, SCTP_SO_NOT_LOCKED);
}
SCTP_TCB_UNLOCK(stcb);
@@ -315,9 +284,8 @@ sctp_notify(struct sctp_inpcb *inp,
* now is dead. In either case treat it like a OOTB abort
* with no TCB
*/
- reason = SCTP_PEER_FAULTY;
- sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -326,7 +294,7 @@ sctp_notify(struct sctp_inpcb *inp,
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
#endif
@@ -336,6 +304,7 @@ sctp_notify(struct sctp_inpcb *inp,
}
}
+#ifdef INET
void
sctp_ctlinput(cmd, sa, vip)
int cmd;
@@ -378,8 +347,8 @@ sctp_ctlinput(cmd, sa, vip)
* 'from' holds our local endpoint address. Thus we reverse
* the to and the from in the lookup.
*/
- stcb = sctp_findassociation_addr_sa((struct sockaddr *)&from,
- (struct sockaddr *)&to,
+ stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
+ (struct sockaddr *)&from,
&inp, &net, 1, vrf_id);
if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
if (cmd != PRC_MSGSIZE) {
@@ -405,6 +374,8 @@ sctp_ctlinput(cmd, sa, vip)
return;
}
+#endif
+
static int
sctp_getcred(SYSCTL_HANDLER_ARGS)
{
@@ -428,8 +399,8 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
if (error)
return (error);
- stcb = sctp_findassociation_addr_sa(sintosa(&addrs[0]),
- sintosa(&addrs[1]),
+ stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
+ sintosa(&addrs[0]),
&inp, &net, 1, vrf_id);
if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
if ((inp != NULL) && (stcb == NULL)) {
@@ -467,6 +438,7 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
+#ifdef INET
static void
sctp_abort(struct socket *so)
{
@@ -474,7 +446,7 @@ sctp_abort(struct socket *so)
uint32_t flags;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
return;
}
sctp_must_try_again:
@@ -510,7 +482,7 @@ sctp_must_try_again:
}
static int
-sctp_attach(struct socket *so, int proto, struct thread *p)
+sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
{
struct sctp_inpcb *inp;
struct inpcb *ip_inp;
@@ -525,17 +497,17 @@ sctp_attach(struct socket *so, int proto, struct thread *p)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
if (error) {
- return error;
+ return (error);
}
}
error = sctp_inpcb_alloc(so, vrf_id);
if (error) {
- return error;
+ return (error);
}
inp = (struct sctp_inpcb *)so->so_pcb;
SCTP_INP_WLOCK(inp);
@@ -567,39 +539,34 @@ try_again:
SCTP_INP_WUNLOCK(inp);
}
}
- return error;
+ return (error);
}
#endif /* IPSEC */
SCTP_INP_WUNLOCK(inp);
- return 0;
+ return (0);
}
static int
sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
{
- struct sctp_inpcb *inp = NULL;
- int error;
+ struct sctp_inpcb *inp;
-#ifdef INET6
- if (addr && addr->sa_family != AF_INET) {
- /* must be a v4 address! */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return EINVAL;
- }
-#endif /* INET6 */
- if (addr && (addr->sa_len != sizeof(struct sockaddr_in))) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return EINVAL;
- }
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
- error = sctp_inpcb_bind(so, addr, NULL, p);
- return error;
+ if (addr != NULL) {
+ if ((addr->sa_family != AF_INET) ||
+ (addr->sa_len != sizeof(struct sockaddr_in))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ }
+ return (sctp_inpcb_bind(so, addr, NULL, p));
}
+#endif
void
sctp_close(struct socket *so)
{
@@ -607,7 +574,7 @@ sctp_close(struct socket *so)
uint32_t flags;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0)
+ if (inp == NULL)
return;
/*
@@ -672,20 +639,19 @@ sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
int error;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
if (control) {
sctp_m_freem(control);
control = NULL;
}
SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
sctp_m_freem(m);
- return EINVAL;
+ return (EINVAL);
}
/* Got to have an to address if we are NOT a connected socket */
if ((addr == NULL) &&
((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
- (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))
- ) {
+ (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
goto connected_type;
} else if (addr == NULL) {
SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
@@ -707,7 +673,7 @@ sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
control = NULL;
}
error = EDESTADDRREQ;
- return EDESTADDRREQ;
+ return (error);
}
#endif /* INET6 */
connected_type:
@@ -806,9 +772,6 @@ sctp_disconnect(struct socket *so)
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(err));
}
-#if defined(SCTP_PANIC_ON_ABORT)
- panic("disconnect does an abort");
-#endif
sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
}
@@ -831,22 +794,26 @@ sctp_disconnect(struct socket *so)
if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/* only send SHUTDOWN 1st time thru */
- sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown(stcb,
- stcb->asoc.primary_destination);
- sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
+ struct sctp_nets *netp;
+
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(stcb);
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
+ sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
}
} else {
/*
@@ -859,9 +826,17 @@ sctp_disconnect(struct socket *so)
* we will allow user data to be sent first
* and move to SHUTDOWN-PENDING
*/
+ struct sctp_nets *netp;
+
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+
asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
if (asoc->locked_on_sending) {
/* Locked to send out the data */
struct sctp_stream_queue_pending *sp;
@@ -881,7 +856,7 @@ sctp_disconnect(struct socket *so)
struct mbuf *op_err;
abort_anyway:
- op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_DONTWAIT, 1, MT_DATA);
if (op_err) {
/*
@@ -889,22 +864,12 @@ sctp_disconnect(struct socket *so)
* initiated abort
*/
struct sctp_paramhdr *ph;
- uint32_t *ippp;
-
- SCTP_BUF_LEN(op_err) =
- (sizeof(struct sctp_paramhdr) + sizeof(uint32_t));
- ph = mtod(op_err,
- struct sctp_paramhdr *);
- ph->param_type = htons(
- SCTP_CAUSE_USER_INITIATED_ABT);
+
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
+ ph = mtod(op_err, struct sctp_paramhdr *);
+ ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(op_err));
- ippp = (uint32_t *) (ph + 1);
- *ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4);
}
-#if defined(SCTP_PANIC_ON_ABORT)
- panic("disconnect does an abort");
-#endif
-
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
@@ -929,7 +894,7 @@ sctp_disconnect(struct socket *so)
/* UDP model does not support this */
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
- return EOPNOTSUPP;
+ return (EOPNOTSUPP);
}
}
@@ -947,7 +912,7 @@ sctp_flush(struct socket *so, int how)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
SCTP_INP_RLOCK(inp);
/* For the 1 to many model this does nothing */
@@ -989,13 +954,14 @@ sctp_shutdown(struct socket *so)
struct sctp_inpcb *inp;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
SCTP_INP_RLOCK(inp);
/* For UDP model this is a invalid call */
- if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
+ if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
/* Restore the flags that the soshutdown took away. */
SOCKBUF_LOCK(&so->so_rcv);
so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
@@ -1041,31 +1007,43 @@ sctp_shutdown(struct socket *so)
/* there is nothing queued to send, so I'm done... */
if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
/* only send SHUTDOWN the first time through */
- sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown(stcb,
- stcb->asoc.primary_destination);
- sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
+ struct sctp_nets *netp;
+
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(stcb);
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
+ sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
}
} else {
/*
* we still got (or just got) data to send, so set
* SHUTDOWN_PENDING
*/
+ struct sctp_nets *netp;
+
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+
asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
if (asoc->locked_on_sending) {
/* Locked to send out the data */
@@ -1087,29 +1065,19 @@ sctp_shutdown(struct socket *so)
struct mbuf *op_err;
abort_anyway:
- op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_DONTWAIT, 1, MT_DATA);
if (op_err) {
/* Fill in the user initiated abort */
struct sctp_paramhdr *ph;
- uint32_t *ippp;
-
- SCTP_BUF_LEN(op_err) =
- sizeof(struct sctp_paramhdr) + sizeof(uint32_t);
- ph = mtod(op_err,
- struct sctp_paramhdr *);
- ph->param_type = htons(
- SCTP_CAUSE_USER_INITIATED_ABT);
+
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
+ ph = mtod(op_err, struct sctp_paramhdr *);
+ ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(op_err));
- ippp = (uint32_t *) (ph + 1);
- *ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
}
-#if defined(SCTP_PANIC_ON_ABORT)
- panic("shutdown does an abort");
-#endif
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
sctp_abort_an_association(stcb->sctp_ep, stcb,
- SCTP_RESPONSE_TO_USER_REQ,
op_err, SCTP_SO_LOCKED);
goto skip_unlock;
} else {
@@ -1120,7 +1088,7 @@ sctp_shutdown(struct socket *so)
}
skip_unlock:
SCTP_INP_RUNLOCK(inp);
- return 0;
+ return (0);
}
/*
@@ -1165,23 +1133,29 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
if (stcb) {
/* Turn on all the appropriate scope */
- loopback_scope = stcb->asoc.loopback_scope;
- ipv4_local_scope = stcb->asoc.ipv4_local_scope;
- local_scope = stcb->asoc.local_scope;
- site_scope = stcb->asoc.site_scope;
+ loopback_scope = stcb->asoc.scope.loopback_scope;
+ ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
+ local_scope = stcb->asoc.scope.local_scope;
+ site_scope = stcb->asoc.scope.site_scope;
+ ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
+ ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
} else {
- /* Turn on ALL scope, since we look at the EP */
- loopback_scope = ipv4_local_scope = local_scope =
- site_scope = 1;
- }
- ipv4_addr_legal = ipv6_addr_legal = 0;
- if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- ipv6_addr_legal = 1;
- if (SCTP_IPV6_V6ONLY(inp) == 0) {
+ /* Use generic values for endpoints. */
+ loopback_scope = 1;
+ ipv4_local_scope = 1;
+ local_scope = 1;
+ site_scope = 1;
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ ipv6_addr_legal = 1;
+ if (SCTP_IPV6_V6ONLY(inp)) {
+ ipv4_addr_legal = 0;
+ } else {
+ ipv4_addr_legal = 1;
+ }
+ } else {
+ ipv6_addr_legal = 0;
ipv4_addr_legal = 1;
}
- } else {
- ipv4_addr_legal = 1;
}
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
@@ -1210,6 +1184,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
}
}
switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
case AF_INET:
if (ipv4_addr_legal) {
struct sockaddr_in *sin;
@@ -1249,6 +1224,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
continue;
}
break;
+#endif
#ifdef INET6
case AF_INET6:
if (ipv6_addr_legal) {
@@ -1318,8 +1294,21 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
}
if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
continue;
-
- ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
+ switch (laddr->ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
+ break;
+#endif
+ default:
+ /* TSNH */
+ break;
+ }
sas = (struct sockaddr_storage *)((caddr_t)sas +
laddr->ifa->address.sa.sa_len);
actual += laddr->ifa->address.sa.sa_len;
@@ -1374,28 +1363,46 @@ sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
/* Count them if they are the right type */
- if (sctp_ifa->address.sa.sa_family == AF_INET) {
+ switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
cnt += sizeof(struct sockaddr_in6);
else
cnt += sizeof(struct sockaddr_in);
-
- } else if (sctp_ifa->address.sa.sa_family == AF_INET6)
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
cnt += sizeof(struct sockaddr_in6);
+ break;
+#endif
+ default:
+ break;
+ }
}
}
} else {
struct sctp_laddr *laddr;
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
- if (laddr->ifa->address.sa.sa_family == AF_INET) {
+ switch (laddr->ifa->address.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
cnt += sizeof(struct sockaddr_in6);
else
cnt += sizeof(struct sockaddr_in);
-
- } else if (laddr->ifa->address.sa.sa_family == AF_INET6)
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
cnt += sizeof(struct sockaddr_in6);
+ break;
+#endif
+ default:
+ break;
+ }
}
}
return (cnt);
@@ -1422,7 +1429,6 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
struct sctp_tcb *stcb = NULL;
struct sockaddr *sa;
int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
- int added = 0;
uint32_t vrf_id;
int bad_addresses = 0;
sctp_assoc_t *a_id;
@@ -1516,15 +1522,30 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
/* Gak! no memory */
goto out_now;
}
+ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
+ stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
+ /* Set the connected flag so we can queue data */
+ soisconnecting(so);
+ }
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
/* move to second address */
- if (sa->sa_family == AF_INET)
+ switch (sa->sa_family) {
+#ifdef INET
+ case AF_INET:
sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
- else
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
+ break;
+#endif
+ default:
+ break;
+ }
error = 0;
- added = sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
+ sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
/* Fill in the return id */
if (error) {
(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
@@ -1555,7 +1576,7 @@ out_now:
SCTP_ASOC_CREATE_UNLOCK(inp);
}
SCTP_INP_DECR_REF(inp);
- return error;
+ return (error);
}
#define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
@@ -1567,7 +1588,7 @@ out_now:
SCTP_TCB_LOCK(stcb); \
} \
SCTP_INP_RUNLOCK(inp); \
- } else if (assoc_id != 0) { \
+ } else if (assoc_id > SCTP_ALL_ASSOC) { \
stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
if (stcb == NULL) { \
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
@@ -1580,7 +1601,7 @@ out_now:
}
-#define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
+#define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
if (size < sizeof(type)) { \
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
error = EINVAL; \
@@ -1603,7 +1624,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
return (EINVAL);
}
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
@@ -1655,10 +1676,6 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
} /* end switch (sopt->sopt_name) */
- if (optname != SCTP_AUTOCLOSE) {
- /* make it an "on/off" value */
- val = (val != 0);
- }
if (*optsize < sizeof(val)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
@@ -1698,8 +1715,8 @@ flags_out:
SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
*value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
*optsize = sizeof(uint32_t);
+ break;
}
- break;
case SCTP_PARTIAL_DELIVERY_POINT:
{
uint32_t *value;
@@ -1707,8 +1724,8 @@ flags_out:
SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
*value = inp->partial_delivery_point;
*optsize = sizeof(uint32_t);
+ break;
}
- break;
case SCTP_FRAGMENT_INTERLEAVE:
{
uint32_t *value;
@@ -1724,8 +1741,8 @@ flags_out:
*value = SCTP_FRAG_LEVEL_0;
}
*optsize = sizeof(uint32_t);
+ break;
}
- break;
case SCTP_CMT_ON_OFF:
{
struct sctp_assoc_value *av;
@@ -1736,14 +1753,22 @@ flags_out:
av->assoc_value = stcb->asoc.sctp_cmt_on_off;
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_RLOCK(inp);
- av->assoc_value = inp->sctp_cmt_on_off;
- SCTP_INP_RUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ av->assoc_value = inp->sctp_cmt_on_off;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_assoc_value);
}
- *optsize = sizeof(*av);
+ break;
}
- break;
- /* JRS - Get socket option for pluggable congestion control */
case SCTP_PLUGGABLE_CC:
{
struct sctp_assoc_value *av;
@@ -1754,11 +1779,92 @@ flags_out:
av->assoc_value = stcb->asoc.congestion_control_module;
SCTP_TCB_UNLOCK(stcb);
} else {
- av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_assoc_value);
}
- *optsize = sizeof(*av);
+ break;
+ }
+ case SCTP_CC_OPTION:
+ {
+ struct sctp_cc_option *cc_opt;
+
+ SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
+ SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
+ if (stcb == NULL) {
+ error = EINVAL;
+ } else {
+ if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
+ error = ENOTSUP;
+ } else {
+ error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 0, cc_opt);
+ *optsize = sizeof(struct sctp_cc_option);
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ break;
+ }
+ case SCTP_PLUGGABLE_SS:
+ {
+ struct sctp_assoc_value *av;
+
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+ if (stcb) {
+ av->assoc_value = stcb->asoc.stream_scheduling_module;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_assoc_value);
+ }
+ break;
+ }
+ case SCTP_SS_VALUE:
+ {
+ struct sctp_stream_value *av;
+
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+ if (stcb) {
+ if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
+ &av->stream_value) < 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ } else {
+ *optsize = sizeof(struct sctp_stream_value);
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ /*
+ * Can't get stream value without
+ * association
+ */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ break;
}
- break;
case SCTP_GET_ADDR_LEN:
{
struct sctp_assoc_value *av;
@@ -1779,10 +1885,11 @@ flags_out:
#endif
if (error) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ } else {
+ *optsize = sizeof(struct sctp_assoc_value);
}
- *optsize = sizeof(*av);
+ break;
}
- break;
case SCTP_GET_ASSOC_NUMBER:
{
uint32_t *value, cnt;
@@ -1796,9 +1903,8 @@ flags_out:
SCTP_INP_RUNLOCK(inp);
*value = cnt;
*optsize = sizeof(uint32_t);
+ break;
}
- break;
-
case SCTP_GET_ASSOC_ID_LIST:
{
struct sctp_assoc_ids *ids;
@@ -1818,10 +1924,12 @@ flags_out:
}
}
SCTP_INP_RUNLOCK(inp);
- ids->gaids_number_of_ids = at;
- *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
+ if (error == 0) {
+ ids->gaids_number_of_ids = at;
+ *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
+ }
+ break;
}
- break;
case SCTP_CONTEXT:
{
struct sctp_assoc_value *av;
@@ -1833,19 +1941,29 @@ flags_out:
av->assoc_value = stcb->asoc.context;
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_RLOCK(inp);
- av->assoc_value = inp->sctp_context;
- SCTP_INP_RUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ av->assoc_value = inp->sctp_context;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_assoc_value);
}
- *optsize = sizeof(*av);
+ break;
}
- break;
case SCTP_VRF_ID:
{
uint32_t *default_vrfid;
SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
*default_vrfid = inp->def_vrf_id;
+ *optsize = sizeof(uint32_t);
break;
}
case SCTP_GET_ASOC_VRF:
@@ -1857,9 +1975,10 @@ flags_out:
if (stcb == NULL) {
error = EINVAL;
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
- break;
+ } else {
+ id->assoc_value = stcb->asoc.vrf_id;
+ *optsize = sizeof(struct sctp_assoc_value);
}
- id->assoc_value = stcb->asoc.vrf_id;
break;
}
case SCTP_GET_VRF_IDS:
@@ -1879,13 +1998,13 @@ flags_out:
gnv->gn_peers_tag = stcb->asoc.peer_vtag;
gnv->gn_local_tag = stcb->asoc.my_vtag;
SCTP_TCB_UNLOCK(stcb);
+ *optsize = sizeof(struct sctp_get_nonce_values);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
- *optsize = sizeof(*gnv);
+ break;
}
- break;
case SCTP_DELAYED_SACK:
{
struct sctp_sack_info *sack;
@@ -1897,15 +2016,23 @@ flags_out:
sack->sack_freq = stcb->asoc.sack_freq;
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_RLOCK(inp);
- sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
- sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
- SCTP_INP_RUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
+ sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
}
- *optsize = sizeof(*sack);
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_sack_info);
+ }
+ break;
}
- break;
-
case SCTP_GET_SNDBUF_USE:
{
struct sctp_sockstat *ss;
@@ -1918,13 +2045,13 @@ flags_out:
ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
stcb->asoc.size_on_all_streams);
SCTP_TCB_UNLOCK(stcb);
+ *optsize = sizeof(struct sctp_sockstat);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
- *optsize = sizeof(struct sctp_sockstat);
+ break;
}
- break;
case SCTP_MAX_BURST:
{
uint8_t *value;
@@ -1932,11 +2059,15 @@ flags_out:
SCTP_CHECK_AND_CAST(value, optval, uint8_t, *optsize);
SCTP_INP_RLOCK(inp);
- *value = inp->sctp_ep.max_burst;
+ if (inp->sctp_ep.max_burst < 256) {
+ *value = inp->sctp_ep.max_burst;
+ } else {
+ *value = 255;
+ }
SCTP_INP_RUNLOCK(inp);
*optsize = sizeof(uint8_t);
+ break;
}
- break;
case SCTP_MAXSEG:
{
struct sctp_assoc_value *av;
@@ -1949,21 +2080,30 @@ flags_out:
av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_RLOCK(inp);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- ovh = SCTP_MED_OVERHEAD;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ ovh = SCTP_MED_OVERHEAD;
+ } else {
+ ovh = SCTP_MED_V4_OVERHEAD;
+ }
+ if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
+ av->assoc_value = 0;
+ else
+ av->assoc_value = inp->sctp_frag_point - ovh;
+ SCTP_INP_RUNLOCK(inp);
} else {
- ovh = SCTP_MED_V4_OVERHEAD;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
}
- if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
- av->assoc_value = 0;
- else
- av->assoc_value = inp->sctp_frag_point - ovh;
- SCTP_INP_RUNLOCK(inp);
}
- *optsize = sizeof(struct sctp_assoc_value);
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_assoc_value);
+ }
+ break;
}
- break;
case SCTP_GET_STAT_LOG:
error = sctp_fill_stat_log(optval, optsize);
break;
@@ -1972,7 +2112,7 @@ flags_out:
struct sctp_event_subscribe *events;
SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
- memset(events, 0, sizeof(*events));
+ memset(events, 0, sizeof(struct sctp_event_subscribe));
SCTP_INP_RLOCK(inp);
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
events->sctp_data_io_event = 1;
@@ -2008,9 +2148,8 @@ flags_out:
events->sctp_stream_reset_event = 1;
SCTP_INP_RUNLOCK(inp);
*optsize = sizeof(struct sctp_event_subscribe);
+ break;
}
- break;
-
case SCTP_ADAPTATION_LAYER:
{
uint32_t *value;
@@ -2021,8 +2160,8 @@ flags_out:
*value = inp->sctp_ep.adaptation_layer_indicator;
SCTP_INP_RUNLOCK(inp);
*optsize = sizeof(uint32_t);
+ break;
}
- break;
case SCTP_SET_INITIAL_DBG_SEQ:
{
uint32_t *value;
@@ -2032,8 +2171,8 @@ flags_out:
*value = inp->sctp_ep.initial_sequence_debug;
SCTP_INP_RUNLOCK(inp);
*optsize = sizeof(uint32_t);
+ break;
}
- break;
case SCTP_GET_LOCAL_ADDR_SIZE:
{
uint32_t *value;
@@ -2043,8 +2182,8 @@ flags_out:
*value = sctp_count_max_addresses(inp);
SCTP_INP_RUNLOCK(inp);
*optsize = sizeof(uint32_t);
+ break;
}
- break;
case SCTP_GET_REMOTE_ADDR_SIZE:
{
uint32_t *value;
@@ -2059,25 +2198,34 @@ flags_out:
size = 0;
/* Count the sizes */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) ||
- (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
size += sizeof(struct sockaddr_in6);
- } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
- size += sizeof(struct sockaddr_in);
} else {
- /* huh */
- break;
+ switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
+#ifdef INET
+ case AF_INET:
+ size += sizeof(struct sockaddr_in);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ size += sizeof(struct sockaddr_in6);
+ break;
+#endif
+ default:
+ break;
+ }
}
}
SCTP_TCB_UNLOCK(stcb);
*value = (uint32_t) size;
+ *optsize = sizeof(uint32_t);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
- *optsize = sizeof(uint32_t);
+ break;
}
- break;
case SCTP_GET_PEER_ADDRESSES:
/*
* Get the address information, an array is passed in to
@@ -2098,20 +2246,33 @@ flags_out:
sas = (struct sockaddr_storage *)&saddr->addr[0];
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) ||
- (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
cpsz = sizeof(struct sockaddr_in6);
- } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
- cpsz = sizeof(struct sockaddr_in);
} else {
- /* huh */
+ switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
+#ifdef INET
+ case AF_INET:
+ cpsz = sizeof(struct sockaddr_in);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ cpsz = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ default:
+ cpsz = 0;
+ break;
+ }
+ }
+ if (cpsz == 0) {
break;
}
if (left < cpsz) {
/* not enough room. */
break;
}
-#ifdef INET6
+#if defined(INET) && defined(INET6)
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
(((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
/* Must map the address */
@@ -2120,7 +2281,7 @@ flags_out:
} else {
#endif
memcpy(sas, &net->ro._l_addr, cpsz);
-#ifdef INET6
+#if defined(INET) && defined(INET6)
}
#endif
((struct sockaddr_in *)sas)->sin_port = stcb->rport;
@@ -2134,8 +2295,8 @@ flags_out:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
}
+ break;
}
- break;
case SCTP_GET_LOCAL_ADDRESSES:
{
size_t limit, actual;
@@ -2152,8 +2313,8 @@ flags_out:
SCTP_TCB_UNLOCK(stcb);
}
*optsize = sizeof(struct sockaddr_storage) + actual;
+ break;
}
- break;
case SCTP_PEER_ADDR_PARAMS:
{
struct sctp_paddrparams *paddrp;
@@ -2183,6 +2344,7 @@ flags_out:
struct sockaddr *sa;
sa = (struct sockaddr *)&paddrp->spp_address;
+#ifdef INET
if (sa->sa_family == AF_INET) {
struct sockaddr_in *sin;
@@ -2193,7 +2355,10 @@ flags_out:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
- } else if (sa->sa_family == AF_INET6) {
+ } else
+#endif
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)sa;
@@ -2203,7 +2368,9 @@ flags_out:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
- } else {
+ } else
+#endif
+ {
error = EAFNOSUPPORT;
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
@@ -2211,7 +2378,7 @@ flags_out:
}
}
if (stcb) {
- /* Applys to the specific association */
+ /* Applies to the specific association */
paddrp->spp_flags = 0;
if (net) {
int ovh;
@@ -2222,29 +2389,29 @@ flags_out:
ovh = SCTP_MED_V4_OVERHEAD;
}
-
+ paddrp->spp_hbinterval = net->heart_beat_delay;
paddrp->spp_pathmaxrxt = net->failure_threshold;
paddrp->spp_pathmtu = net->mtu - ovh;
/* get flags for HB */
- if (net->dest_state & SCTP_ADDR_NOHB)
+ if (net->dest_state & SCTP_ADDR_NOHB) {
paddrp->spp_flags |= SPP_HB_DISABLE;
- else
+ } else {
paddrp->spp_flags |= SPP_HB_ENABLE;
+ }
/* get flags for PMTU */
- if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
+ if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
paddrp->spp_flags |= SPP_PMTUD_ENABLE;
} else {
paddrp->spp_flags |= SPP_PMTUD_DISABLE;
}
-#ifdef INET
- if (net->ro._l_addr.sin.sin_family == AF_INET) {
- paddrp->spp_ipv4_tos = net->tos_flowlabel & 0x000000fc;
- paddrp->spp_flags |= SPP_IPV4_TOS;
+ if (net->dscp & 0x01) {
+ paddrp->spp_dscp = net->dscp & 0xfc;
+ paddrp->spp_flags |= SPP_DSCP;
}
-#endif
#ifdef INET6
- if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
- paddrp->spp_ipv6_flowlabel = net->tos_flowlabel;
+ if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
+ (net->flowlabel & 0x80000000)) {
+ paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
}
#endif
@@ -2253,69 +2420,78 @@ flags_out:
* No destination so return default
* value
*/
- int cnt = 0;
-
paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
-#ifdef INET
- paddrp->spp_ipv4_tos = stcb->asoc.default_tos & 0x000000fc;
- paddrp->spp_flags |= SPP_IPV4_TOS;
-#endif
+ if (stcb->asoc.default_dscp & 0x01) {
+ paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
+ paddrp->spp_flags |= SPP_DSCP;
+ }
#ifdef INET6
- paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel;
- paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
+ if (stcb->asoc.default_flowlabel & 0x80000000) {
+ paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
+ paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
+ }
#endif
/* default settings should be these */
- if (stcb->asoc.hb_is_disabled == 0) {
- paddrp->spp_flags |= SPP_HB_ENABLE;
- } else {
+ if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
paddrp->spp_flags |= SPP_HB_DISABLE;
+ } else {
+ paddrp->spp_flags |= SPP_HB_ENABLE;
}
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
- cnt++;
- }
- }
- if (cnt) {
+ if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
+ paddrp->spp_flags |= SPP_PMTUD_DISABLE;
+ } else {
paddrp->spp_flags |= SPP_PMTUD_ENABLE;
}
+ paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
}
- paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
paddrp->spp_assoc_id = sctp_get_associd(stcb);
SCTP_TCB_UNLOCK(stcb);
} else {
- /* Use endpoint defaults */
- SCTP_INP_RLOCK(inp);
- paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
- paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
- paddrp->spp_assoc_id = (sctp_assoc_t) 0;
- /* get inp's default */
-#ifdef INET
- paddrp->spp_ipv4_tos = inp->ip_inp.inp.inp_ip_tos;
- paddrp->spp_flags |= SPP_IPV4_TOS;
-#endif
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
+ /* Use endpoint defaults */
+ SCTP_INP_RLOCK(inp);
+ paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
+ paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
+ paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
+ /* get inp's default */
+ if (inp->sctp_ep.default_dscp & 0x01) {
+ paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
+ paddrp->spp_flags |= SPP_DSCP;
+ }
#ifdef INET6
- if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- paddrp->spp_ipv6_flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo;
- paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
- }
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
+ (inp->sctp_ep.default_flowlabel & 0x80000000)) {
+ paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
+ paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
+ }
#endif
- /* can't return this */
- paddrp->spp_pathmtu = 0;
+ /* can't return this */
+ paddrp->spp_pathmtu = 0;
- /* default behavior, no stcb */
- paddrp->spp_flags = SPP_PMTUD_ENABLE;
-
- if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
- paddrp->spp_flags |= SPP_HB_ENABLE;
+ if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
+ paddrp->spp_flags |= SPP_HB_ENABLE;
+ } else {
+ paddrp->spp_flags |= SPP_HB_DISABLE;
+ }
+ if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
+ paddrp->spp_flags |= SPP_PMTUD_ENABLE;
+ } else {
+ paddrp->spp_flags |= SPP_PMTUD_DISABLE;
+ }
+ SCTP_INP_RUNLOCK(inp);
} else {
- paddrp->spp_flags |= SPP_HB_DISABLE;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
}
- SCTP_INP_RUNLOCK(inp);
}
- *optsize = sizeof(struct sctp_paddrparams);
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_paddrparams);
+ }
+ break;
}
- break;
case SCTP_GET_PEER_ADDR_INFO:
{
struct sctp_paddrinfo *paddri;
@@ -2343,12 +2519,23 @@ flags_out:
}
if ((stcb) && (net)) {
- paddri->spinfo_state = net->dest_state & (SCTP_REACHABLE_MASK | SCTP_ADDR_NOHB);
+ if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
+ /* It's unconfirmed */
+ paddri->spinfo_state = SCTP_UNCONFIRMED;
+ } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ /* It's active */
+ paddri->spinfo_state = SCTP_ACTIVE;
+ } else {
+ /* It's inactive */
+ paddri->spinfo_state = SCTP_INACTIVE;
+ }
paddri->spinfo_cwnd = net->cwnd;
- paddri->spinfo_srtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
+ paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
paddri->spinfo_rto = net->RTO;
paddri->spinfo_assoc_id = sctp_get_associd(stcb);
+ paddri->spinfo_mtu = net->mtu;
SCTP_TCB_UNLOCK(stcb);
+ *optsize = sizeof(struct sctp_paddrinfo);
} else {
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
@@ -2356,9 +2543,8 @@ flags_out:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
}
- *optsize = sizeof(struct sctp_paddrinfo);
+ break;
}
- break;
case SCTP_PCB_STATUS:
{
struct sctp_pcbinfo *spcb;
@@ -2366,9 +2552,8 @@ flags_out:
SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
sctp_fill_pcbinfo(spcb);
*optsize = sizeof(struct sctp_pcbinfo);
+ break;
}
- break;
-
case SCTP_STATUS:
{
struct sctp_nets *net;
@@ -2378,7 +2563,7 @@ flags_out:
SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
if (stcb == NULL) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -2411,16 +2596,25 @@ flags_out:
* Again the user can get info from sctp_constants.h
* for what the state of the network is.
*/
- sstat->sstat_primary.spinfo_state = net->dest_state & SCTP_REACHABLE_MASK;
+ if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
+ /* It's unconfirmed */
+ sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
+ } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ /* It's active */
+ sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
+ } else {
+ /* It's inactive */
+ sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
+ }
sstat->sstat_primary.spinfo_cwnd = net->cwnd;
- sstat->sstat_primary.spinfo_srtt = net->lastsa;
+ sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
sstat->sstat_primary.spinfo_rto = net->RTO;
sstat->sstat_primary.spinfo_mtu = net->mtu;
sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
SCTP_TCB_UNLOCK(stcb);
- *optsize = sizeof(*sstat);
+ *optsize = sizeof(struct sctp_status);
+ break;
}
- break;
case SCTP_RTOINFO:
{
struct sctp_rtoinfo *srto;
@@ -2434,15 +2628,24 @@ flags_out:
srto->srto_min = stcb->asoc.minrto;
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_RLOCK(inp);
- srto->srto_initial = inp->sctp_ep.initial_rto;
- srto->srto_max = inp->sctp_ep.sctp_maxrto;
- srto->srto_min = inp->sctp_ep.sctp_minrto;
- SCTP_INP_RUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ srto->srto_initial = inp->sctp_ep.initial_rto;
+ srto->srto_max = inp->sctp_ep.sctp_maxrto;
+ srto->srto_min = inp->sctp_ep.sctp_minrto;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
}
- *optsize = sizeof(*srto);
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_rtoinfo);
+ }
+ break;
}
- break;
case SCTP_TIMEOUTS:
{
struct sctp_timeouts *stimo;
@@ -2459,23 +2662,21 @@ flags_out:
stimo->stimo_cookie = stcb->asoc.timocookie;
stimo->stimo_shutdownack = stcb->asoc.timoshutdownack;
SCTP_TCB_UNLOCK(stcb);
+ *optsize = sizeof(struct sctp_timeouts);
} else {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
- *optsize = sizeof(*stimo);
+ break;
}
- break;
case SCTP_ASSOCINFO:
{
struct sctp_assocparams *sasoc;
- uint32_t oldval;
SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
if (stcb) {
- oldval = sasoc->sasoc_cookie_life;
sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
@@ -2483,17 +2684,26 @@ flags_out:
sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_RLOCK(inp);
- sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
- sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
- sasoc->sasoc_number_peer_destinations = 0;
- sasoc->sasoc_peer_rwnd = 0;
- sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
- SCTP_INP_RUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
+ sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
+ sasoc->sasoc_number_peer_destinations = 0;
+ sasoc->sasoc_peer_rwnd = 0;
+ sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_assocparams);
}
- *optsize = sizeof(*sasoc);
+ break;
}
- break;
case SCTP_DEFAULT_SEND_PARAM:
{
struct sctp_sndrcvinfo *s_info;
@@ -2505,13 +2715,22 @@ flags_out:
memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_RLOCK(inp);
- memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
- SCTP_INP_RUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
}
- *optsize = sizeof(*s_info);
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_sndrcvinfo);
+ }
+ break;
}
- break;
case SCTP_INITMSG:
{
struct sctp_initmsg *sinit;
@@ -2523,9 +2742,9 @@ flags_out:
sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
SCTP_INP_RUNLOCK(inp);
- *optsize = sizeof(*sinit);
+ *optsize = sizeof(struct sctp_initmsg);
+ break;
}
- break;
case SCTP_PRIMARY_ADDR:
/* we allow a "get" operation on this */
{
@@ -2546,14 +2765,13 @@ flags_out:
&stcb->asoc.primary_destination->ro._l_addr,
len);
SCTP_TCB_UNLOCK(stcb);
+ *optsize = sizeof(struct sctp_setprim);
} else {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
- *optsize = sizeof(*ssp);
+ break;
}
- break;
-
case SCTP_HMAC_IDENT:
{
struct sctp_hmacalgo *shmac;
@@ -2575,7 +2793,7 @@ flags_out:
size = sizeof(*shmac) + (hmaclist->num_algo *
sizeof(shmac->shmac_idents[0]));
if ((size_t)(*optsize) < size) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
SCTP_INP_RUNLOCK(inp);
break;
@@ -2601,12 +2819,21 @@ flags_out:
scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
SCTP_TCB_UNLOCK(stcb);
} else {
- /* get the endpoint active key */
- SCTP_INP_RLOCK(inp);
- scact->scact_keynumber = inp->sctp_ep.default_keyid;
- SCTP_INP_RUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
+ /* get the endpoint active key */
+ SCTP_INP_RLOCK(inp);
+ scact->scact_keynumber = inp->sctp_ep.default_keyid;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_authkeyid);
}
- *optsize = sizeof(*scact);
break;
}
case SCTP_LOCAL_AUTH_CHUNKS:
@@ -2629,24 +2856,34 @@ flags_out:
} else {
/* copy in the chunks */
(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
+ sac->gauth_number_of_chunks = (uint32_t) size;
+ *optsize = sizeof(struct sctp_authchunks) + size;
}
SCTP_TCB_UNLOCK(stcb);
} else {
- /* get off the endpoint */
- SCTP_INP_RLOCK(inp);
- chklist = inp->sctp_ep.local_auth_chunks;
- /* is there enough space? */
- size = sctp_auth_get_chklist_size(chklist);
- if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
- error = EINVAL;
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
+ /* get off the endpoint */
+ SCTP_INP_RLOCK(inp);
+ chklist = inp->sctp_ep.local_auth_chunks;
+ /* is there enough space? */
+ size = sctp_auth_get_chklist_size(chklist);
+ if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ } else {
+ /* copy in the chunks */
+ (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
+ sac->gauth_number_of_chunks = (uint32_t) size;
+ *optsize = sizeof(struct sctp_authchunks) + size;
+ }
+ SCTP_INP_RUNLOCK(inp);
} else {
- /* copy in the chunks */
- (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
}
- SCTP_INP_RUNLOCK(inp);
}
- *optsize = sizeof(struct sctp_authchunks) + size;
break;
}
case SCTP_PEER_AUTH_CHUNKS:
@@ -2669,23 +2906,411 @@ flags_out:
} else {
/* copy in the chunks */
(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
+ sac->gauth_number_of_chunks = (uint32_t) size;
+ *optsize = sizeof(struct sctp_authchunks) + size;
}
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
}
- *optsize = sizeof(struct sctp_authchunks) + size;
break;
}
+ case SCTP_EVENT:
+ {
+ struct sctp_event *event;
+ uint32_t event_type;
+
+ SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
+ SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
+
+ switch (event->se_type) {
+ case SCTP_ASSOC_CHANGE:
+ event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
+ break;
+ case SCTP_PEER_ADDR_CHANGE:
+ event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
+ break;
+ case SCTP_REMOTE_ERROR:
+ event_type = SCTP_PCB_FLAGS_RECVPEERERR;
+ break;
+ case SCTP_SEND_FAILED:
+ event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
+ break;
+ case SCTP_SHUTDOWN_EVENT:
+ event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
+ break;
+ case SCTP_ADAPTATION_INDICATION:
+ event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
+ break;
+ case SCTP_PARTIAL_DELIVERY_EVENT:
+ event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
+ break;
+ case SCTP_AUTHENTICATION_EVENT:
+ event_type = SCTP_PCB_FLAGS_AUTHEVNT;
+ break;
+ case SCTP_STREAM_RESET_EVENT:
+ event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
+ break;
+ case SCTP_SENDER_DRY_EVENT:
+ event_type = SCTP_PCB_FLAGS_DRYEVNT;
+ break;
+ case SCTP_NOTIFICATIONS_STOPPED_EVENT:
+ event_type = 0;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
+ error = ENOTSUP;
+ break;
+ case SCTP_ASSOC_RESET_EVENT:
+ event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
+ break;
+ case SCTP_STREAM_CHANGE_EVENT:
+ event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
+ break;
+ case SCTP_SEND_FAILED_EVENT:
+ event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
+ break;
+ default:
+ event_type = 0;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ break;
+ }
+ if (event_type > 0) {
+ if (stcb) {
+ event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ event->se_on = sctp_is_feature_on(inp, event_type);
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_event);
+ }
+ break;
+ }
+ case SCTP_RECVRCVINFO:
+ {
+ int onoff;
+
+ if (*optsize < sizeof(int)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ } else {
+ SCTP_INP_RLOCK(inp);
+ onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
+ SCTP_INP_RUNLOCK(inp);
+ }
+ if (error == 0) {
+ /* return the option value */
+ *(int *)optval = onoff;
+ *optsize = sizeof(int);
+ }
+ break;
+ }
+ case SCTP_RECVNXTINFO:
+ {
+ int onoff;
+
+ if (*optsize < sizeof(int)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ } else {
+ SCTP_INP_RLOCK(inp);
+ onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
+ SCTP_INP_RUNLOCK(inp);
+ }
+ if (error == 0) {
+ /* return the option value */
+ *(int *)optval = onoff;
+ *optsize = sizeof(int);
+ }
+ break;
+ }
+ case SCTP_DEFAULT_SNDINFO:
+ {
+ struct sctp_sndinfo *info;
+
+ SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
+ SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
+
+ if (stcb) {
+ info->snd_sid = stcb->asoc.def_send.sinfo_stream;
+ info->snd_flags = stcb->asoc.def_send.sinfo_flags;
+ info->snd_flags &= 0xfff0;
+ info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
+ info->snd_context = stcb->asoc.def_send.sinfo_context;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ info->snd_sid = inp->def_send.sinfo_stream;
+ info->snd_flags = inp->def_send.sinfo_flags;
+ info->snd_flags &= 0xfff0;
+ info->snd_ppid = inp->def_send.sinfo_ppid;
+ info->snd_context = inp->def_send.sinfo_context;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_sndinfo);
+ }
+ break;
+ }
+ case SCTP_DEFAULT_PRINFO:
+ {
+ struct sctp_default_prinfo *info;
+
+ SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
+ SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
+
+ if (stcb) {
+ info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
+ info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
+ info->pr_value = inp->def_send.sinfo_timetolive;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_default_prinfo);
+ }
+ break;
+ }
+ case SCTP_PEER_ADDR_THLDS:
+ {
+ struct sctp_paddrthlds *thlds;
+ struct sctp_nets *net;
+
+ SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
+ SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
+
+ net = NULL;
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
+ if (stcb == NULL) {
+ SCTP_INP_DECR_REF(inp);
+ }
+ }
+ if (stcb && (net == NULL)) {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *)&thlds->spt_address;
+#ifdef INET
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ } else
+#endif
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ } else
+#endif
+ {
+ error = EAFNOSUPPORT;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ }
+ if (stcb) {
+ if (net) {
+ thlds->spt_pathmaxrxt = net->failure_threshold;
+ thlds->spt_pathpfthld = net->pf_threshold;
+ } else {
+ thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
+ thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
+ }
+ thlds->spt_assoc_id = sctp_get_associd(stcb);
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
+ /* Use endpoint defaults */
+ SCTP_INP_RLOCK(inp);
+ thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
+ thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_paddrthlds);
+ }
+ break;
+ }
+ case SCTP_REMOTE_UDP_ENCAPS_PORT:
+ {
+ struct sctp_udpencaps *encaps;
+ struct sctp_nets *net;
+
+ SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
+ SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
+
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ net = NULL;
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
+ if (stcb == NULL) {
+ SCTP_INP_DECR_REF(inp);
+ }
+ }
+ if (stcb && (net == NULL)) {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *)&encaps->sue_address;
+#ifdef INET
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ } else
+#endif
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ } else
+#endif
+ {
+ error = EAFNOSUPPORT;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ }
+ if (stcb) {
+ if (net) {
+ encaps->sue_port = net->port;
+ } else {
+ encaps->sue_port = stcb->asoc.port;
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ encaps->sue_port = inp->sctp_ep.port;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_paddrparams);
+ }
+ break;
+ }
+ case SCTP_ENABLE_STREAM_RESET:
+ {
+ struct sctp_assoc_value *av;
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+ if (stcb) {
+ av->assoc_value = (uint32_t) stcb->asoc.local_strreset_support;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ av->assoc_value = (uint32_t) inp->local_strreset_support;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_assoc_value);
+ }
+ break;
+ }
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
- *optsize = 0;
break;
} /* end switch (sopt->sopt_name) */
+ if (error) {
+ *optsize = 0;
+ }
return (error);
}
@@ -2705,10 +3330,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
return (EINVAL);
}
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_PRINTF("inp is NULL?\n");
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
vrf_id = inp->def_vrf_id;
@@ -2736,6 +3361,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
*/
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
/* only valid for bound all sockets */
+ if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
+ (*mopt != 0)) {
+ /* forbidden by admin */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
+ return (EPERM);
+ }
set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -2798,8 +3429,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
else
sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
+ break;
}
- break;
case SCTP_PARTIAL_DELIVERY_POINT:
{
uint32_t *value;
@@ -2811,8 +3442,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
break;
}
inp->partial_delivery_point = *value;
+ break;
}
- break;
case SCTP_FRAGMENT_INTERLEAVE:
/* not yet until we re-write sctp_recvmsg() */
{
@@ -2833,120 +3464,214 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
+ break;
}
- break;
case SCTP_CMT_ON_OFF:
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
struct sctp_assoc_value *av;
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+ if (av->assoc_value > SCTP_CMT_MAX) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ break;
+ }
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
- if (av->assoc_value != 0)
- stcb->asoc.sctp_cmt_on_off = 1;
- else
- stcb->asoc.sctp_cmt_on_off = 0;
+ stcb->asoc.sctp_cmt_on_off = av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- if (av->assoc_value != 0)
- inp->sctp_cmt_on_off = 1;
- else
- inp->sctp_cmt_on_off = 0;
- SCTP_INP_WUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->sctp_cmt_on_off = av->assoc_value;
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ stcb->asoc.sctp_cmt_on_off = av->assoc_value;
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
}
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
}
break;
- /* JRS - Set socket option for pluggable congestion control */
case SCTP_PLUGGABLE_CC:
{
struct sctp_assoc_value *av;
+ struct sctp_nets *net;
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+ if ((av->assoc_value != SCTP_CC_RFC2581) &&
+ (av->assoc_value != SCTP_CC_HSTCP) &&
+ (av->assoc_value != SCTP_CC_HTCP) &&
+ (av->assoc_value != SCTP_CC_RTCC)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ break;
+ }
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
- switch (av->assoc_value) {
- /*
- * JRS - Standard TCP congestion
- * control
- */
- case SCTP_CC_RFC2581:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_RFC2581;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer;
- SCTP_TCB_UNLOCK(stcb);
- break;
+ stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
+ stcb->asoc.congestion_control_module = av->assoc_value;
+ if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
}
- /*
- * JRS - High Speed TCP congestion
- * control (Floyd)
- */
- case SCTP_CC_HSTCP:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_HSTCP;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_hs_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_hs_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer;
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
+ stcb->asoc.congestion_control_module = av->assoc_value;
+ if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
+ }
+ }
SCTP_TCB_UNLOCK(stcb);
- break;
}
- /* JRS - HTCP congestion control */
- case SCTP_CC_HTCP:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_HTCP;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_htcp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_htcp_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_htcp_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_htcp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_htcp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_htcp_cwnd_update_after_fr_timer;
+ SCTP_INP_RUNLOCK(inp);
+ }
+ }
+ break;
+ }
+ case SCTP_CC_OPTION:
+ {
+ struct sctp_cc_option *cc_opt;
+
+ SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
+ SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
+ if (stcb == NULL) {
+ if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
+ }
SCTP_TCB_UNLOCK(stcb);
- break;
}
- /*
- * JRS - All other values are
- * invalid
- */
- default:
- {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- error = EINVAL;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ error = EINVAL;
+ }
+ } else {
+ if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
+ error = ENOTSUP;
+ } else {
+ error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
+ cc_opt);
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ break;
+ }
+ case SCTP_PLUGGABLE_SS:
+ {
+ struct sctp_assoc_value *av;
+
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+ if ((av->assoc_value != SCTP_SS_DEFAULT) &&
+ (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
+ (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
+ (av->assoc_value != SCTP_SS_PRIORITY) &&
+ (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
+ (av->assoc_value != SCTP_SS_FIRST_COME)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ break;
+ }
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+ if (stcb) {
+ stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
+ stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
+ stcb->asoc.stream_scheduling_module = av->assoc_value;
+ stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
+ stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
+ stcb->asoc.stream_scheduling_module = av->assoc_value;
+ stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
SCTP_TCB_UNLOCK(stcb);
- break;
}
+ SCTP_INP_RUNLOCK(inp);
+ }
+ }
+ break;
+ }
+ case SCTP_SS_VALUE:
+ {
+ struct sctp_stream_value *av;
+
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+ if (stcb) {
+ if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
+ av->stream_value) < 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
}
+ SCTP_TCB_UNLOCK(stcb);
} else {
- switch (av->assoc_value) {
- case SCTP_CC_RFC2581:
- case SCTP_CC_HSTCP:
- case SCTP_CC_HTCP:
- inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
- break;
- default:
+ if (av->assoc_id == SCTP_CURRENT_ASSOC) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
+ &stcb->asoc,
+ &stcb->asoc.strmout[av->stream_id],
+ av->stream_value);
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+
+ } else {
+ /*
+ * Can't set stream value without
+ * association
+ */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
- break;
- };
+ }
}
+ break;
}
- break;
case SCTP_CLR_STAT_LOG:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
error = EOPNOTSUPP;
@@ -2962,12 +3687,27 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
stcb->asoc.context = av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- inp->sctp_context = av->assoc_value;
- SCTP_INP_WUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->sctp_context = av->assoc_value;
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ stcb->asoc.context = av->assoc_value;
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
}
+ break;
}
- break;
case SCTP_VRF_ID:
{
uint32_t *default_vrfid;
@@ -3002,12 +3742,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (sack->sack_delay) {
if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
sack->sack_delay = SCTP_MAX_SACK_DELAY;
+ if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
+ sack->sack_delay = TICKS_TO_MSEC(1);
+ }
}
if (stcb) {
if (sack->sack_delay) {
- if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
- sack->sack_delay = TICKS_TO_MSEC(1);
- }
stcb->asoc.delayed_ack = sack->sack_delay;
}
if (sack->sack_freq) {
@@ -3015,17 +3755,34 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- if (sack->sack_delay) {
- if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
- sack->sack_delay = TICKS_TO_MSEC(1);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ if (sack->sack_delay) {
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
}
- inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
+ if (sack->sack_freq) {
+ inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
+ }
+ SCTP_INP_WUNLOCK(inp);
}
- if (sack->sack_freq) {
- inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
+ if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ if (sack->sack_delay) {
+ stcb->asoc.delayed_ack = sack->sack_delay;
+ }
+ if (sack->sack_freq) {
+ stcb->asoc.sack_freq = sack->sack_freq;
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
}
- SCTP_INP_WUNLOCK(inp);
}
break;
}
@@ -3052,11 +3809,20 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
size_t size;
SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
+ if (sca->sca_keylength == 0) {
+ size = optsize - sizeof(struct sctp_authkey);
+ } else {
+ if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
+ size = sca->sca_keylength;
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ break;
+ }
+ }
SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
- size = optsize - sizeof(*sca);
if (stcb) {
- /* set it on the assoc */
shared_keys = &stcb->asoc.shared_keys;
/* clear the cached keys for this key id */
sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
@@ -3086,39 +3852,78 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = sctp_insert_sharedkey(shared_keys, shared_key);
SCTP_TCB_UNLOCK(stcb);
} else {
- /* set it on the endpoint */
- SCTP_INP_WLOCK(inp);
- shared_keys = &inp->sctp_ep.shared_keys;
- /*
- * clear the cached keys on all assocs for
- * this key id
- */
- sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
- /*
- * create the new shared key and
- * insert/replace it
- */
- if (size > 0) {
- key = sctp_set_key(sca->sca_key, (uint32_t) size);
- if (key == NULL) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ shared_keys = &inp->sctp_ep.shared_keys;
+ /*
+ * clear the cached keys on all
+ * assocs for this key id
+ */
+ sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
+ /*
+ * create the new shared key and
+ * insert/replace it
+ */
+ if (size > 0) {
+ key = sctp_set_key(sca->sca_key, (uint32_t) size);
+ if (key == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
+ error = ENOMEM;
+ SCTP_INP_WUNLOCK(inp);
+ break;
+ }
+ }
+ shared_key = sctp_alloc_sharedkey();
+ if (shared_key == NULL) {
+ sctp_free_key(key);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
error = ENOMEM;
SCTP_INP_WUNLOCK(inp);
break;
}
- }
- shared_key = sctp_alloc_sharedkey();
- if (shared_key == NULL) {
- sctp_free_key(key);
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
- error = ENOMEM;
+ shared_key->key = key;
+ shared_key->keyid = sca->sca_keynumber;
+ error = sctp_insert_sharedkey(shared_keys, shared_key);
SCTP_INP_WUNLOCK(inp);
- break;
}
- shared_key->key = key;
- shared_key->keyid = sca->sca_keynumber;
- error = sctp_insert_sharedkey(shared_keys, shared_key);
- SCTP_INP_WUNLOCK(inp);
+ if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ shared_keys = &stcb->asoc.shared_keys;
+ /*
+ * clear the cached keys for
+ * this key id
+ */
+ sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
+ /*
+ * create the new shared key
+ * and insert/replace it
+ */
+ if (size > 0) {
+ key = sctp_set_key(sca->sca_key, (uint32_t) size);
+ if (key == NULL) {
+ SCTP_TCB_UNLOCK(stcb);
+ continue;
+ }
+ }
+ shared_key = sctp_alloc_sharedkey();
+ if (shared_key == NULL) {
+ sctp_free_key(key);
+ SCTP_TCB_UNLOCK(stcb);
+ continue;
+ }
+ shared_key->key = key;
+ shared_key->keyid = sca->sca_keynumber;
+ error = sctp_insert_sharedkey(shared_keys, shared_key);
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
}
break;
}
@@ -3128,7 +3933,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sctp_hmaclist_t *hmaclist;
uint16_t hmacid;
uint32_t i;
-
size_t found;
SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
@@ -3179,8 +3983,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
{
struct sctp_authkeyid *scact;
- SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid,
- optsize);
+ SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
/* set the active key on the right place */
@@ -3195,16 +3998,27 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- /* set the active key on the endpoint */
- SCTP_INP_WLOCK(inp);
- if (sctp_auth_setactivekey_ep(inp,
- scact->scact_keynumber)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
- SCTP_FROM_SCTP_USRREQ,
- EINVAL);
- error = EINVAL;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ sctp_auth_setactivekey(stcb, scact->scact_keynumber);
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
}
- SCTP_INP_WUNLOCK(inp);
}
break;
}
@@ -3212,30 +4026,38 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
{
struct sctp_authkeyid *scdel;
- SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid,
- optsize);
+ SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
/* delete the key from the right place */
if (stcb) {
- if (sctp_delete_sharedkey(stcb,
- scdel->scact_keynumber)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
- SCTP_FROM_SCTP_USRREQ,
- EINVAL);
+ if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- if (sctp_delete_sharedkey_ep(inp,
- scdel->scact_keynumber)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
- SCTP_FROM_SCTP_USRREQ,
- EINVAL);
- error = EINVAL;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
}
- SCTP_INP_WUNLOCK(inp);
}
break;
}
@@ -3243,45 +4065,85 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
{
struct sctp_authkeyid *keyid;
- SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid,
- optsize);
+ SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
/* deactivate the key from the right place */
if (stcb) {
- if (sctp_deact_sharedkey(stcb,
- keyid->scact_keynumber)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
- SCTP_FROM_SCTP_USRREQ,
- EINVAL);
+ if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- if (sctp_deact_sharedkey_ep(inp,
- keyid->scact_keynumber)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
- SCTP_FROM_SCTP_USRREQ,
- EINVAL);
- error = EINVAL;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
}
- SCTP_INP_WUNLOCK(inp);
}
break;
}
+ case SCTP_ENABLE_STREAM_RESET:
+ {
+ struct sctp_assoc_value *av;
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+ if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ break;
+ }
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+ if (stcb) {
+ stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->local_strreset_support = (uint8_t) av->assoc_value;
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
+ (av->assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
+ }
+ break;
+ }
case SCTP_RESET_STREAMS:
{
- struct sctp_stream_reset *strrst;
- uint8_t send_in = 0, send_tsn = 0, send_out = 0,
- addstream = 0;
- uint16_t addstrmcnt = 0;
- int i;
-
- SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_stream_reset, optsize);
- SCTP_FIND_STCB(inp, stcb, strrst->strrst_assoc_id);
+ struct sctp_reset_streams *strrst;
+ int i, send_out = 0;
+ int send_in = 0;
+ SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
+ SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
if (stcb == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
@@ -3289,13 +4151,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
if (stcb->asoc.peer_supports_strreset == 0) {
/*
- * Peer does not support it, we return
- * protocol not supported since this is true
- * for this feature and this peer, not the
- * socket request in general.
+ * Peer does not support the chunk type.
*/
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPROTONOSUPPORT);
- error = EPROTONOSUPPORT;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
+ error = EOPNOTSUPP;
SCTP_TCB_UNLOCK(stcb);
break;
}
@@ -3305,151 +4164,147 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_UNLOCK(stcb);
break;
}
- if (strrst->strrst_flags == SCTP_RESET_LOCAL_RECV) {
- send_in = 1;
- } else if (strrst->strrst_flags == SCTP_RESET_LOCAL_SEND) {
- send_out = 1;
- } else if (strrst->strrst_flags == SCTP_RESET_BOTH) {
+ if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
send_in = 1;
+ }
+ if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
send_out = 1;
- } else if (strrst->strrst_flags == SCTP_RESET_TSN) {
- send_tsn = 1;
- } else if (strrst->strrst_flags == SCTP_RESET_ADD_STREAMS) {
- if (send_tsn ||
- send_in ||
- send_out) {
- /* We can't do that and add streams */
- error = EINVAL;
- goto skip_stuff;
- }
- if (stcb->asoc.stream_reset_outstanding) {
- error = EBUSY;
- goto skip_stuff;
- }
- addstream = 1;
- /* We allocate here */
- addstrmcnt = strrst->strrst_num_streams;
- if ((int)(addstrmcnt + stcb->asoc.streamoutcnt) > 0xffff) {
- /* You can't have more than 64k */
- error = EINVAL;
- goto skip_stuff;
- }
- if ((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < addstrmcnt) {
- /* Need to allocate more */
- struct sctp_stream_out *oldstream;
- struct sctp_stream_queue_pending *sp;
- int removed;
-
- oldstream = stcb->asoc.strmout;
- /* get some more */
- SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *,
- ((stcb->asoc.streamoutcnt + addstrmcnt) * sizeof(struct sctp_stream_out)),
- SCTP_M_STRMO);
- if (stcb->asoc.strmout == NULL) {
- stcb->asoc.strmout = oldstream;
- error = ENOMEM;
- goto skip_stuff;
- }
- /*
- * Ok now we proceed with copying
- * the old out stuff and
- * initializing the new stuff.
- */
- SCTP_TCB_SEND_LOCK(stcb);
- for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
- TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
- stcb->asoc.strmout[i].next_sequence_sent = oldstream[i].next_sequence_sent;
- stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete;
- stcb->asoc.strmout[i].stream_no = i;
- if (oldstream[i].next_spoke.tqe_next) {
- sctp_remove_from_wheel(stcb, &stcb->asoc, &oldstream[i], 1);
- stcb->asoc.strmout[i].next_spoke.tqe_next = NULL;
- stcb->asoc.strmout[i].next_spoke.tqe_prev = NULL;
- removed = 1;
- } else {
- /* not on out wheel */
- stcb->asoc.strmout[i].next_spoke.tqe_next = NULL;
- stcb->asoc.strmout[i].next_spoke.tqe_prev = NULL;
- removed = 0;
- }
- /*
- * now anything on those
- * queues?
- */
- while (TAILQ_EMPTY(&oldstream[i].outqueue) == 0) {
- sp = TAILQ_FIRST(&oldstream[i].outqueue);
- TAILQ_REMOVE(&oldstream[i].outqueue, sp, next);
- TAILQ_INSERT_TAIL(&stcb->asoc.strmout[i].outqueue, sp, next);
- }
- /* Did we disrupt the wheel? */
- if (removed) {
- sctp_insert_on_wheel(stcb,
- &stcb->asoc,
- &stcb->asoc.strmout[i],
- 1);
- }
- /*
- * Now move assoc pointers
- * too
- */
- if (stcb->asoc.last_out_stream == &oldstream[i]) {
- stcb->asoc.last_out_stream = &stcb->asoc.strmout[i];
- }
- if (stcb->asoc.locked_on_sending == &oldstream[i]) {
- stcb->asoc.locked_on_sending = &stcb->asoc.strmout[i];
- }
- }
- /* now the new streams */
- for (i = stcb->asoc.streamoutcnt; i < (stcb->asoc.streamoutcnt + addstrmcnt); i++) {
- stcb->asoc.strmout[i].next_sequence_sent = 0x0;
- TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
- stcb->asoc.strmout[i].stream_no = i;
- stcb->asoc.strmout[i].last_msg_incomplete = 0;
- stcb->asoc.strmout[i].next_spoke.tqe_next = NULL;
- stcb->asoc.strmout[i].next_spoke.tqe_prev = NULL;
- }
- stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + addstrmcnt;
- SCTP_FREE(oldstream, SCTP_M_STRMO);
- }
- SCTP_TCB_SEND_UNLOCK(stcb);
- goto skip_stuff;
- } else {
+ }
+ if ((send_in == 0) && (send_out == 0)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
SCTP_TCB_UNLOCK(stcb);
break;
}
- for (i = 0; i < strrst->strrst_num_streams; i++) {
+ for (i = 0; i < strrst->srs_number_streams; i++) {
if ((send_in) &&
-
- (strrst->strrst_list[i] > stcb->asoc.streamincnt)) {
+ (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
- goto get_out;
+ break;
}
if ((send_out) &&
- (strrst->strrst_list[i] > stcb->asoc.streamoutcnt)) {
+ (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
- goto get_out;
+ break;
}
}
- skip_stuff:
if (error) {
- get_out:
SCTP_TCB_UNLOCK(stcb);
break;
}
- error = sctp_send_str_reset_req(stcb, strrst->strrst_num_streams,
- strrst->strrst_list,
- send_out, (stcb->asoc.str_reset_seq_in - 3),
- send_in, send_tsn, addstream, addstrmcnt);
+ error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
+ strrst->srs_stream_list,
+ send_out, send_in, 0, 0, 0, 0, 0);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
+ break;
}
- break;
+ case SCTP_ADD_STREAMS:
+ {
+ struct sctp_add_streams *stradd;
+ uint8_t addstream = 0;
+ uint16_t add_o_strmcnt = 0;
+ uint16_t add_i_strmcnt = 0;
+
+ SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
+ SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
+ if (stcb == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
+ error = ENOENT;
+ break;
+ }
+ if (stcb->asoc.peer_supports_strreset == 0) {
+ /*
+ * Peer does not support the chunk type.
+ */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
+ error = EOPNOTSUPP;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
+ if (stcb->asoc.stream_reset_outstanding) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
+ error = EALREADY;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
+ if ((stradd->sas_outstrms == 0) &&
+ (stradd->sas_instrms == 0)) {
+ error = EINVAL;
+ goto skip_stuff;
+ }
+ if (stradd->sas_outstrms) {
+ addstream = 1;
+ /* We allocate here */
+ add_o_strmcnt = stradd->sas_outstrms;
+ if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
+ /* You can't have more than 64k */
+ error = EINVAL;
+ goto skip_stuff;
+ }
+ }
+ if (stradd->sas_instrms) {
+ int cnt;
+
+ addstream |= 2;
+ /*
+ * We allocate inside
+ * sctp_send_str_reset_req()
+ */
+ add_i_strmcnt = stradd->sas_instrms;
+ cnt = add_i_strmcnt;
+ cnt += stcb->asoc.streamincnt;
+ if (cnt > 0x0000ffff) {
+ /* You can't have more than 64k */
+ error = EINVAL;
+ goto skip_stuff;
+ }
+ if (cnt > (int)stcb->asoc.max_inbound_streams) {
+ /* More than you are allowed */
+ error = EINVAL;
+ goto skip_stuff;
+ }
+ }
+ error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
+ skip_stuff:
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
+ case SCTP_RESET_ASSOC:
+ {
+ uint32_t *value;
+ SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
+ SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
+ if (stcb == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
+ error = ENOENT;
+ break;
+ }
+ if (stcb->asoc.peer_supports_strreset == 0) {
+ /*
+ * Peer does not support the chunk type.
+ */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
+ error = EOPNOTSUPP;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
+ if (stcb->asoc.stream_reset_outstanding) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
+ error = EALREADY;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
+ error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
case SCTP_CONNECT_X:
if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -3458,7 +4313,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
break;
-
case SCTP_CONNECT_X_DELAYED:
if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -3467,7 +4321,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
break;
-
case SCTP_CONNECT_X_COMPLETE:
{
struct sockaddr *sa;
@@ -3521,8 +4374,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EALREADY;
}
SCTP_TCB_UNLOCK(stcb);
+ break;
}
- break;
case SCTP_MAX_BURST:
{
uint8_t *burst;
@@ -3530,12 +4383,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_CHECK_AND_CAST(burst, optval, uint8_t, optsize);
SCTP_INP_WLOCK(inp);
- if (*burst) {
- inp->sctp_ep.max_burst = *burst;
- }
+ inp->sctp_ep.max_burst = *burst;
SCTP_INP_WUNLOCK(inp);
+ break;
}
- break;
case SCTP_MAXSEG:
{
struct sctp_assoc_value *av;
@@ -3557,20 +4408,27 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- /*
- * FIXME MT: I think this is not in tune
- * with the API ID
- */
- if (av->assoc_value) {
- inp->sctp_frag_point = (av->assoc_value + ovh);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ /*
+ * FIXME MT: I think this is not in
+ * tune with the API ID
+ */
+ if (av->assoc_value) {
+ inp->sctp_frag_point = (av->assoc_value + ovh);
+ } else {
+ inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
+ }
+ SCTP_INP_WUNLOCK(inp);
} else {
- inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
}
- SCTP_INP_WUNLOCK(inp);
}
+ break;
}
- break;
case SCTP_EVENTS:
{
struct sctp_event_subscribe *events;
@@ -3634,22 +4492,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (events->sctp_sender_dry_event) {
sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
- (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- }
- if (stcb &&
- TAILQ_EMPTY(&stcb->asoc.send_queue) &&
- TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
- (stcb->asoc.stream_queue_cnt == 0)) {
- sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
- }
- if (stcb) {
- SCTP_TCB_UNLOCK(stcb);
- }
- }
} else {
sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
}
@@ -3660,9 +4502,84 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
}
SCTP_INP_WUNLOCK(inp);
- }
- break;
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ if (events->sctp_association_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
+ }
+ if (events->sctp_address_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
+ }
+ if (events->sctp_send_failure_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
+ }
+ if (events->sctp_peer_error_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
+ }
+ if (events->sctp_shutdown_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
+ }
+ if (events->sctp_partial_delivery_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
+ }
+ if (events->sctp_adaptation_layer_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
+ }
+ if (events->sctp_authentication_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
+ }
+ if (events->sctp_sender_dry_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
+ }
+ if (events->sctp_stream_reset_event) {
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ /*
+ * Send up the sender dry event only for 1-to-1
+ * style sockets.
+ */
+ if (events->sctp_sender_dry_event) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ stcb = LIST_FIRST(&inp->sctp_asoc_list);
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
+ TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
+ (stcb->asoc.stream_queue_cnt == 0)) {
+ sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ }
+ }
+ SCTP_INP_RUNLOCK(inp);
+ break;
+ }
case SCTP_ADAPTATION_LAYER:
{
struct sctp_setadaptation *adap_bits;
@@ -3670,9 +4587,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
SCTP_INP_WLOCK(inp);
inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
+ inp->sctp_ep.adaptation_layer_indicator_provided = 1;
SCTP_INP_WUNLOCK(inp);
+ break;
}
- break;
#ifdef SCTP_DEBUG
case SCTP_SET_INITIAL_DBG_SEQ:
{
@@ -3682,8 +4600,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_INP_WLOCK(inp);
inp->sctp_ep.initial_sequence_debug = *vvv;
SCTP_INP_WUNLOCK(inp);
+ break;
}
- break;
#endif
case SCTP_DEFAULT_SEND_PARAM:
{
@@ -3693,7 +4611,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
if (stcb) {
- if (s_info->sinfo_stream <= stcb->asoc.streamoutcnt) {
+ if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -3701,14 +4619,30 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
- SCTP_INP_WUNLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
+ memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
}
+ break;
}
- break;
case SCTP_PEER_ADDR_PARAMS:
- /* Applys to the specific association */
{
struct sctp_paddrparams *paddrp;
struct sctp_nets *net;
@@ -3738,7 +4672,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
struct sockaddr *sa;
sa = (struct sockaddr *)&paddrp->spp_address;
+#ifdef INET
if (sa->sa_family == AF_INET) {
+
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)sa;
@@ -3748,7 +4684,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EINVAL;
break;
}
- } else if (sa->sa_family == AF_INET6) {
+ } else
+#endif
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)sa;
@@ -3758,7 +4697,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EINVAL;
break;
}
- } else {
+ } else
+#endif
+ {
error = EAFNOSUPPORT;
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
@@ -3792,71 +4733,156 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
ovh = SCTP_MED_V4_OVERHEAD;
}
- if (paddrp->spp_hbinterval)
- stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
- else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
- stcb->asoc.heart_beat_delay = 0;
-
/* network sets ? */
if (net) {
/************************NET SPECIFIC SET ******************/
- if (paddrp->spp_flags & SPP_HB_DEMAND) {
- /* on demand HB */
- if (sctp_send_hb(stcb, 1, net) < 0) {
- /* asoc destroyed */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- error = EINVAL;
- break;
- }
- }
if (paddrp->spp_flags & SPP_HB_DISABLE) {
+ if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
+ !(net->dest_state & SCTP_ADDR_NOHB)) {
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
+ SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
+ }
net->dest_state |= SCTP_ADDR_NOHB;
}
if (paddrp->spp_flags & SPP_HB_ENABLE) {
+ if (paddrp->spp_hbinterval) {
+ net->heart_beat_delay = paddrp->spp_hbinterval;
+ } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
+ net->heart_beat_delay = 0;
+ }
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
+ SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
net->dest_state &= ~SCTP_ADDR_NOHB;
}
+ if (paddrp->spp_flags & SPP_HB_DEMAND) {
+ /* on demand HB */
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ }
if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
}
+ net->dest_state |= SCTP_ADDR_NO_PMTUD;
if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
net->mtu = paddrp->spp_pathmtu + ovh;
if (net->mtu < stcb->asoc.smallest_mtu) {
- sctp_pathmtu_adjustment(inp, stcb, net, net->mtu);
+ sctp_pathmtu_adjustment(stcb, net->mtu);
}
}
}
if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
- if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
+ if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
}
+ net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
}
- if (paddrp->spp_pathmaxrxt)
- net->failure_threshold = paddrp->spp_pathmaxrxt;
-#ifdef INET
- if (paddrp->spp_flags & SPP_IPV4_TOS) {
- if (net->ro._l_addr.sin.sin_family == AF_INET) {
- net->tos_flowlabel = paddrp->spp_ipv4_tos & 0x000000fc;
+ if (paddrp->spp_pathmaxrxt) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ if (net->error_count > paddrp->spp_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ } else {
+ if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
+ (net->error_count > net->pf_threshold)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ if (net->error_count > paddrp->spp_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
+ }
+ } else {
+ if (net->error_count <= paddrp->spp_pathmaxrxt) {
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
+ }
}
+ net->failure_threshold = paddrp->spp_pathmaxrxt;
+ }
+ if (paddrp->spp_flags & SPP_DSCP) {
+ net->dscp = paddrp->spp_dscp & 0xfc;
+ net->dscp |= 0x01;
}
-#endif
#ifdef INET6
if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
- if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
- net->tos_flowlabel = paddrp->spp_ipv6_flowlabel;
+ if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
+ net->flowlabel |= 0x80000000;
}
}
#endif
} else {
/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
- if (paddrp->spp_pathmaxrxt)
+ if (paddrp->spp_pathmaxrxt) {
stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
-
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ if (net->error_count > paddrp->spp_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ } else {
+ if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
+ (net->error_count > net->pf_threshold)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ if (net->error_count > paddrp->spp_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
+ }
+ } else {
+ if (net->error_count <= paddrp->spp_pathmaxrxt) {
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
+ }
+ }
+ net->failure_threshold = paddrp->spp_pathmaxrxt;
+ }
+ }
if (paddrp->spp_flags & SPP_HB_ENABLE) {
+ if (paddrp->spp_hbinterval) {
+ stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
+ } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
+ stcb->asoc.heart_beat_delay = 0;
+ }
/* Turn back on the timer */
- stcb->asoc.hb_is_disabled = 0;
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (paddrp->spp_hbinterval) {
+ net->heart_beat_delay = paddrp->spp_hbinterval;
+ } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
+ net->heart_beat_delay = 0;
+ }
+ if (net->dest_state & SCTP_ADDR_NOHB) {
+ net->dest_state &= ~SCTP_ADDR_NOHB;
+ }
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
+ SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ }
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
+ }
+ if (paddrp->spp_flags & SPP_HB_DISABLE) {
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (!(net->dest_state & SCTP_ADDR_NOHB)) {
+ net->dest_state |= SCTP_ADDR_NOHB;
+ if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
+ }
+ }
+ }
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
}
if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -3864,87 +4890,103 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
}
+ net->dest_state |= SCTP_ADDR_NO_PMTUD;
if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
net->mtu = paddrp->spp_pathmtu + ovh;
if (net->mtu < stcb->asoc.smallest_mtu) {
- sctp_pathmtu_adjustment(inp, stcb, net, net->mtu);
+ sctp_pathmtu_adjustment(stcb, net->mtu);
}
}
}
+ sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
}
if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
+ if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
}
+ net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
}
+ sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
}
- if (paddrp->spp_flags & SPP_HB_DISABLE) {
- int cnt_of_unconf = 0;
- struct sctp_nets *lnet;
-
- stcb->asoc.hb_is_disabled = 1;
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- if (lnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
- cnt_of_unconf++;
- }
- }
- /*
- * stop the timer ONLY if we
- * have no unconfirmed
- * addresses
- */
- if (cnt_of_unconf == 0) {
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
- SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
- }
+ if (paddrp->spp_flags & SPP_DSCP) {
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ net->dscp = paddrp->spp_dscp & 0xfc;
+ net->dscp |= 0x01;
}
+ stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
+ stcb->asoc.default_dscp |= 0x01;
}
- if (paddrp->spp_flags & SPP_HB_ENABLE) {
- /* start up the timer. */
+#ifdef INET6
+ if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
+ net->flowlabel |= 0x80000000;
+ }
}
+ stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
+ stcb->asoc.default_flowlabel |= 0x80000000;
}
-#ifdef INET
- if (paddrp->spp_flags & SPP_IPV4_TOS)
- stcb->asoc.default_tos = paddrp->spp_ipv4_tos & 0x000000fc;
#endif
-#ifdef INET6
- if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL)
- stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel;
-#endif
-
}
SCTP_TCB_UNLOCK(stcb);
} else {
/************************NO TCB, SET TO default stuff ******************/
- SCTP_INP_WLOCK(inp);
- /*
- * For the TOS/FLOWLABEL stuff you set it
- * with the options on the socket
- */
- if (paddrp->spp_pathmaxrxt) {
- inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
- }
- if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
- inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
- else if (paddrp->spp_hbinterval) {
- if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
- paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
- inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
- }
- if (paddrp->spp_flags & SPP_HB_ENABLE) {
- sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
-
- } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
- sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ /*
+ * For the TOS/FLOWLABEL stuff you
+ * set it with the options on the
+ * socket
+ */
+ if (paddrp->spp_pathmaxrxt) {
+ inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
+ }
+ if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
+ else if (paddrp->spp_hbinterval) {
+ if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
+ paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
+ }
+ if (paddrp->spp_flags & SPP_HB_ENABLE) {
+ if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
+ } else if (paddrp->spp_hbinterval) {
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
+ }
+ sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
+ } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
+ }
+ if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
+ sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
+ } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
+ }
+ if (paddrp->spp_flags & SPP_DSCP) {
+ inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
+ inp->sctp_ep.default_dscp |= 0x01;
+ }
+#ifdef INET6
+ if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
+ inp->sctp_ep.default_flowlabel |= 0x80000000;
+ }
+ }
+#endif
+ SCTP_INP_WUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
}
- SCTP_INP_WUNLOCK(inp);
}
+ break;
}
- break;
case SCTP_RTOINFO:
{
struct sctp_rtoinfo *srto;
@@ -3976,31 +5018,38 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- if (srto->srto_initial)
- new_init = srto->srto_initial;
- else
- new_init = inp->sctp_ep.initial_rto;
- if (srto->srto_max)
- new_max = srto->srto_max;
- else
- new_max = inp->sctp_ep.sctp_maxrto;
- if (srto->srto_min)
- new_min = srto->srto_min;
- else
- new_min = inp->sctp_ep.sctp_minrto;
- if ((new_min <= new_init) && (new_init <= new_max)) {
- inp->sctp_ep.initial_rto = new_init;
- inp->sctp_ep.sctp_maxrto = new_max;
- inp->sctp_ep.sctp_minrto = new_min;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ if (srto->srto_initial)
+ new_init = srto->srto_initial;
+ else
+ new_init = inp->sctp_ep.initial_rto;
+ if (srto->srto_max)
+ new_max = srto->srto_max;
+ else
+ new_max = inp->sctp_ep.sctp_maxrto;
+ if (srto->srto_min)
+ new_min = srto->srto_min;
+ else
+ new_min = inp->sctp_ep.sctp_minrto;
+ if ((new_min <= new_init) && (new_init <= new_max)) {
+ inp->sctp_ep.initial_rto = new_init;
+ inp->sctp_ep.sctp_maxrto = new_max;
+ inp->sctp_ep.sctp_minrto = new_min;
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ SCTP_INP_WUNLOCK(inp);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
- SCTP_INP_WUNLOCK(inp);
}
+ break;
}
- break;
case SCTP_ASSOCINFO:
{
struct sctp_assocparams *sasoc;
@@ -4018,27 +5067,28 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (stcb) {
if (sasoc->sasoc_asocmaxrxt)
stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
- sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
- sasoc->sasoc_peer_rwnd = 0;
- sasoc->sasoc_local_rwnd = 0;
if (sasoc->sasoc_cookie_life) {
stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
}
SCTP_TCB_UNLOCK(stcb);
} else {
- SCTP_INP_WLOCK(inp);
- if (sasoc->sasoc_asocmaxrxt)
- inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
- sasoc->sasoc_number_peer_destinations = 0;
- sasoc->sasoc_peer_rwnd = 0;
- sasoc->sasoc_local_rwnd = 0;
- if (sasoc->sasoc_cookie_life) {
- inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ if (sasoc->sasoc_asocmaxrxt)
+ inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
+ if (sasoc->sasoc_cookie_life) {
+ inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
+ }
+ SCTP_INP_WUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
}
- SCTP_INP_WUNLOCK(inp);
}
+ break;
}
- break;
case SCTP_INITMSG:
{
struct sctp_initmsg *sinit;
@@ -4057,12 +5107,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (sinit->sinit_max_init_timeo)
inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
SCTP_INP_WUNLOCK(inp);
+ break;
}
- break;
case SCTP_PRIMARY_ADDR:
{
struct sctp_setprim *spa;
- struct sctp_nets *net, *lnet;
+ struct sctp_nets *net;
SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
@@ -4091,12 +5141,13 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if ((net != stcb->asoc.primary_destination) &&
(!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
/* Ok we need to set it */
- lnet = stcb->asoc.primary_destination;
if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
- if (net->dest_state & SCTP_ADDR_SWITCH_PRIMARY) {
- net->dest_state |= SCTP_ADDR_DOUBLE_SWITCH;
+ if ((stcb->asoc.alternate) &&
+ (!(net->dest_state & SCTP_ADDR_PF)) &&
+ (net->dest_state & SCTP_ADDR_REACHABLE)) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
}
- net->dest_state |= SCTP_ADDR_SWITCH_PRIMARY;
}
}
} else {
@@ -4106,8 +5157,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
+ break;
}
- break;
case SCTP_SET_DYNAMIC_PRIMARY:
{
union sctp_sockstore *ss;
@@ -4120,8 +5171,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
/* SUPER USER CHECK? */
error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
+ break;
}
- break;
case SCTP_SET_PEER_PRIMARY_ADDR:
{
struct sctp_setpeerprim *sspp;
@@ -4174,21 +5225,19 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
-
+ break;
}
- break;
case SCTP_BINDX_ADD_ADDR:
{
struct sctp_getaddresses *addrs;
- size_t sz;
struct thread *td;
td = (struct thread *)p;
SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
optsize);
+#ifdef INET
if (addrs->addr->sa_family == AF_INET) {
- sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
- if (optsize < sz) {
+ if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
@@ -4197,10 +5246,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
+ } else
+#endif
#ifdef INET6
- } else if (addrs->addr->sa_family == AF_INET6) {
- sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
- if (optsize < sz) {
+ if (addrs->addr->sa_family == AF_INET6) {
+ if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
@@ -4210,28 +5260,28 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
+ } else
#endif
- } else {
+ {
error = EAFNOSUPPORT;
break;
}
sctp_bindx_add_address(so, inp, addrs->addr,
addrs->sget_assoc_id, vrf_id,
&error, p);
+ break;
}
- break;
case SCTP_BINDX_REM_ADDR:
{
struct sctp_getaddresses *addrs;
- size_t sz;
struct thread *td;
td = (struct thread *)p;
SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
+#ifdef INET
if (addrs->addr->sa_family == AF_INET) {
- sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
- if (optsize < sz) {
+ if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
@@ -4240,29 +5290,502 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
+ } else
+#endif
#ifdef INET6
- } else if (addrs->addr->sa_family == AF_INET6) {
- sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
- if (optsize < sz) {
+ if (addrs->addr->sa_family == AF_INET6) {
+ if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
- if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
+ if (td != NULL &&
+ (error = prison_local_ip6(td->td_ucred,
+ &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
(SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
+ } else
#endif
- } else {
+ {
error = EAFNOSUPPORT;
break;
}
- sctp_bindx_delete_address(so, inp, addrs->addr,
+ sctp_bindx_delete_address(inp, addrs->addr,
addrs->sget_assoc_id, vrf_id,
&error);
+ break;
+ }
+ case SCTP_EVENT:
+ {
+ struct sctp_event *event;
+ uint32_t event_type;
+
+ SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
+ SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
+ switch (event->se_type) {
+ case SCTP_ASSOC_CHANGE:
+ event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
+ break;
+ case SCTP_PEER_ADDR_CHANGE:
+ event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
+ break;
+ case SCTP_REMOTE_ERROR:
+ event_type = SCTP_PCB_FLAGS_RECVPEERERR;
+ break;
+ case SCTP_SEND_FAILED:
+ event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
+ break;
+ case SCTP_SHUTDOWN_EVENT:
+ event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
+ break;
+ case SCTP_ADAPTATION_INDICATION:
+ event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
+ break;
+ case SCTP_PARTIAL_DELIVERY_EVENT:
+ event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
+ break;
+ case SCTP_AUTHENTICATION_EVENT:
+ event_type = SCTP_PCB_FLAGS_AUTHEVNT;
+ break;
+ case SCTP_STREAM_RESET_EVENT:
+ event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
+ break;
+ case SCTP_SENDER_DRY_EVENT:
+ event_type = SCTP_PCB_FLAGS_DRYEVNT;
+ break;
+ case SCTP_NOTIFICATIONS_STOPPED_EVENT:
+ event_type = 0;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
+ error = ENOTSUP;
+ break;
+ case SCTP_ASSOC_RESET_EVENT:
+ event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
+ break;
+ case SCTP_STREAM_CHANGE_EVENT:
+ event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
+ break;
+ case SCTP_SEND_FAILED_EVENT:
+ event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
+ break;
+ default:
+ event_type = 0;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ break;
+ }
+ if (event_type > 0) {
+ if (stcb) {
+ if (event->se_on) {
+ sctp_stcb_feature_on(inp, stcb, event_type);
+ if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
+ if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
+ TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
+ (stcb->asoc.stream_queue_cnt == 0)) {
+ sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
+ }
+ }
+ } else {
+ sctp_stcb_feature_off(inp, stcb, event_type);
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ /*
+ * We don't want to send up a storm
+ * of events, so return an error for
+ * sender dry events
+ */
+ if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
+ ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
+ (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
+ error = ENOTSUP;
+ break;
+ }
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (event->se_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ if (event->se_on) {
+ sctp_feature_on(inp, event_type);
+ } else {
+ sctp_feature_off(inp, event_type);
+ }
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (event->se_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ if (event->se_on) {
+ sctp_stcb_feature_on(inp, stcb, event_type);
+ } else {
+ sctp_stcb_feature_off(inp, stcb, event_type);
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
+ }
+ }
+ break;
+ }
+ case SCTP_RECVRCVINFO:
+ {
+ int *onoff;
+
+ SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
+ SCTP_INP_WLOCK(inp);
+ if (*onoff != 0) {
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
+ } else {
+ sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
+ }
+ SCTP_INP_WUNLOCK(inp);
+ break;
+ }
+ case SCTP_RECVNXTINFO:
+ {
+ int *onoff;
+
+ SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
+ SCTP_INP_WLOCK(inp);
+ if (*onoff != 0) {
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
+ } else {
+ sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
+ }
+ SCTP_INP_WUNLOCK(inp);
+ break;
+ }
+ case SCTP_DEFAULT_SNDINFO:
+ {
+ struct sctp_sndinfo *info;
+ uint16_t policy;
+
+ SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
+ SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
+
+ if (stcb) {
+ if (info->snd_sid < stcb->asoc.streamoutcnt) {
+ stcb->asoc.def_send.sinfo_stream = info->snd_sid;
+ policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
+ stcb->asoc.def_send.sinfo_flags = info->snd_flags;
+ stcb->asoc.def_send.sinfo_flags |= policy;
+ stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
+ stcb->asoc.def_send.sinfo_context = info->snd_context;
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->def_send.sinfo_stream = info->snd_sid;
+ policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
+ inp->def_send.sinfo_flags = info->snd_flags;
+ inp->def_send.sinfo_flags |= policy;
+ inp->def_send.sinfo_ppid = info->snd_ppid;
+ inp->def_send.sinfo_context = info->snd_context;
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ if (info->snd_sid < stcb->asoc.streamoutcnt) {
+ stcb->asoc.def_send.sinfo_stream = info->snd_sid;
+ policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
+ stcb->asoc.def_send.sinfo_flags = info->snd_flags;
+ stcb->asoc.def_send.sinfo_flags |= policy;
+ stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
+ stcb->asoc.def_send.sinfo_context = info->snd_context;
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
+ }
+ break;
+ }
+ case SCTP_DEFAULT_PRINFO:
+ {
+ struct sctp_default_prinfo *info;
+
+ SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
+ SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
+
+ if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ break;
+ }
+ if (stcb) {
+ stcb->asoc.def_send.sinfo_flags &= 0xfff0;
+ stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
+ stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
+ (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->def_send.sinfo_flags &= 0xfff0;
+ inp->def_send.sinfo_flags |= info->pr_policy;
+ inp->def_send.sinfo_timetolive = info->pr_value;
+ SCTP_INP_WUNLOCK(inp);
+ }
+ if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
+ (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ SCTP_TCB_LOCK(stcb);
+ stcb->asoc.def_send.sinfo_flags &= 0xfff0;
+ stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
+ stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
+ }
+ break;
+ }
+ case SCTP_PEER_ADDR_THLDS:
+ /* Applies to the specific association */
+ {
+ struct sctp_paddrthlds *thlds;
+ struct sctp_nets *net;
+
+ SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
+ SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
+ net = NULL;
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp,
+ (struct sockaddr *)&thlds->spt_assoc_id,
+ &net, NULL, NULL);
+ if (stcb == NULL) {
+ SCTP_INP_DECR_REF(inp);
+ }
+ }
+ if (stcb && (net == NULL)) {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *)&thlds->spt_assoc_id;
+#ifdef INET
+ if (sa->sa_family == AF_INET) {
+
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_TCB_UNLOCK(stcb);
+ error = EINVAL;
+ break;
+ }
+ } else
+#endif
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_TCB_UNLOCK(stcb);
+ error = EINVAL;
+ break;
+ }
+ } else
+#endif
+ {
+ error = EAFNOSUPPORT;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ }
+ if (stcb) {
+ if (net) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
+ (net->failure_threshold <= thlds->spt_pathpfthld)) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ } else {
+ if ((net->failure_threshold > thlds->spt_pathpfthld) &&
+ (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ if (net->failure_threshold > thlds->spt_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
+ }
+ } else {
+ if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
+ }
+ }
+ net->failure_threshold = thlds->spt_pathmaxrxt;
+ net->pf_threshold = thlds->spt_pathpfthld;
+ } else {
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
+ (net->failure_threshold <= thlds->spt_pathpfthld)) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ } else {
+ if ((net->failure_threshold > thlds->spt_pathpfthld) &&
+ (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ if (net->failure_threshold > thlds->spt_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
+ }
+ } else {
+ if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
+ }
+ }
+ net->failure_threshold = thlds->spt_pathmaxrxt;
+ net->pf_threshold = thlds->spt_pathpfthld;
+ }
+ stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
+ stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
+ }
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
+ inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
+ SCTP_INP_WUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ break;
+ }
+ case SCTP_REMOTE_UDP_ENCAPS_PORT:
+ {
+ struct sctp_udpencaps *encaps;
+ struct sctp_nets *net;
+
+ SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
+ SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ net = NULL;
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
+ if (stcb == NULL) {
+ SCTP_INP_DECR_REF(inp);
+ }
+ }
+ if (stcb && (net == NULL)) {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *)&encaps->sue_address;
+#ifdef INET
+ if (sa->sa_family == AF_INET) {
+
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_TCB_UNLOCK(stcb);
+ error = EINVAL;
+ break;
+ }
+ } else
+#endif
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_TCB_UNLOCK(stcb);
+ error = EINVAL;
+ break;
+ }
+ } else
+#endif
+ {
+ error = EAFNOSUPPORT;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ }
+ if (stcb) {
+ if (net) {
+ net->port = encaps->sue_port;
+ } else {
+ stcb->asoc.port = encaps->sue_port;
+ }
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->sctp_ep.port = encaps->sue_port;
+ SCTP_INP_WUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ break;
}
- break;
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
@@ -4276,31 +5799,28 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
{
void *optval = NULL;
size_t optsize = 0;
- struct sctp_inpcb *inp;
void *p;
int error = 0;
- inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
- /* I made the same as TCP since we are not setup? */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return (ECONNRESET);
- }
if (sopt->sopt_level != IPPROTO_SCTP) {
/* wrong proto level... send back up to IP */
#ifdef INET6
if (INP_CHECK_SOCKAF(so, AF_INET6))
error = ip6_ctloutput(so, sopt);
- else
#endif /* INET6 */
+#if defined(INET) && defined(INET6)
+ else
+#endif
+#ifdef INET
error = ip_ctloutput(so, sopt);
+#endif
return (error);
}
optsize = sopt->sopt_valsize;
if (optsize) {
SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
if (optval == NULL) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
+ SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
return (ENOBUFS);
}
error = sooptcopyin(sopt, optval, optsize, optsize);
@@ -4315,7 +5835,7 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
} else if (sopt->sopt_dir == SOPT_GET) {
error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
} else {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
if ((error == 0) && (optval != NULL)) {
@@ -4328,7 +5848,7 @@ out:
return (error);
}
-
+#ifdef INET
static int
sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
{
@@ -4339,7 +5859,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
struct sctp_tcb *stcb = NULL;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
/* I made the same as TCP since we are not setup? */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (ECONNRESET);
@@ -4348,34 +5868,42 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
+ switch (addr->sa_family) {
#ifdef INET6
- if (addr->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6p;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6p;
- if (addr->sa_len != sizeof(struct sockaddr_in6)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return (EINVAL);
- }
- sin6p = (struct sockaddr_in6 *)addr;
- if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
- return (error);
+ if (addr->sa_len != sizeof(struct sockaddr_in6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ sin6p = (struct sockaddr_in6 *)addr;
+ if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ return (error);
+ }
+ break;
}
- } else
#endif
- if (addr->sa_family == AF_INET) {
- struct sockaddr_in *sinp;
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sinp;
- if (addr->sa_len != sizeof(struct sockaddr_in)) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return (EINVAL);
- }
- sinp = (struct sockaddr_in *)addr;
- if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
- return (error);
+ if (addr->sa_len != sizeof(struct sockaddr_in)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ sinp = (struct sockaddr_in *)addr;
+ if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ return (error);
+ }
+ break;
}
- } else {
+#endif
+ default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
return (EAFNOSUPPORT);
}
@@ -4398,7 +5926,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
error = EINVAL;
goto out_now;
}
-#endif /* INET6 */
+#endif
if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
SCTP_PCB_FLAGS_UNBOUND) {
/* Bind a ephemeral port */
@@ -4455,15 +5983,6 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
/* Set the connected flag so we can queue data */
- SOCKBUF_LOCK(&so->so_rcv);
- so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
- SOCKBUF_UNLOCK(&so->so_rcv);
- SOCKBUF_LOCK(&so->so_snd);
- so->so_snd.sb_state &= ~SBS_CANTSENDMORE;
- SOCKBUF_UNLOCK(&so->so_snd);
- SOCK_LOCK(so);
- so->so_state &= ~SS_ISDISCONNECTING;
- SOCK_UNLOCK(so);
soisconnecting(so);
}
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
@@ -4479,9 +5998,11 @@ out_now:
SCTP_ASOC_CREATE_UNLOCK(inp);
}
SCTP_INP_DECR_REF(inp);
- return error;
+ return (error);
}
+#endif
+
int
sctp_listen(struct socket *so, int backlog, struct thread *p)
{
@@ -4498,7 +6019,7 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
struct sctp_inpcb *inp;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
/* I made the same as TCP since we are not setup? */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (ECONNRESET);
@@ -4515,7 +6036,20 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
memcpy(&store, &laddr->ifa->address, sizeof(store));
- sp->sin.sin_port = inp->sctp_lport;
+ switch (sp->sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ sp->sin.sin_port = inp->sctp_lport;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ sp->sin6.sin6_port = inp->sctp_lport;
+ break;
+#endif
+ default:
+ break;
+ }
tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
if (tinp && (tinp != inp) &&
((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
@@ -4534,17 +6068,32 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
} else {
/* Setup a local addr bound all */
memset(&store, 0, sizeof(store));
- store.sin.sin_port = inp->sctp_lport;
+ switch (sp->sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ store.sin.sin_port = inp->sctp_lport;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ sp->sin6.sin6_port = inp->sctp_lport;
+ break;
+#endif
+ default:
+ break;
+ }
#ifdef INET6
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
store.sa.sa_family = AF_INET6;
store.sa.sa_len = sizeof(struct sockaddr_in6);
}
#endif
+#ifdef INET
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
store.sa.sa_family = AF_INET;
store.sa.sa_len = sizeof(struct sockaddr_in);
}
+#endif
tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
if (tinp && (tinp != inp) &&
((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
@@ -4634,7 +6183,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
#endif
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (ECONNRESET);
}
@@ -4661,6 +6210,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
SCTP_TCB_UNLOCK(stcb);
switch (store.sa.sa_family) {
+#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin;
@@ -4670,11 +6220,12 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
return (ENOMEM);
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
- sin->sin_port = ((struct sockaddr_in *)&store)->sin_port;
- sin->sin_addr = ((struct sockaddr_in *)&store)->sin_addr;
+ sin->sin_port = store.sin.sin_port;
+ sin->sin_addr = store.sin.sin_addr;
*addr = (struct sockaddr *)sin;
break;
}
+#endif
#ifdef INET6
case AF_INET6:
{
@@ -4685,9 +6236,8 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
return (ENOMEM);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port;
-
- sin6->sin6_addr = ((struct sockaddr_in6 *)&store)->sin6_addr;
+ sin6->sin6_port = store.sin6.sin6_port;
+ sin6->sin6_addr = store.sin6.sin6_addr;
if ((error = sa6_recoverscope(sin6)) != 0) {
SCTP_FREE_SONAME(sin6);
return (error);
@@ -4736,6 +6286,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
return (0);
}
+#ifdef INET
int
sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
{
@@ -4756,7 +6307,7 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
if (!inp) {
SCTP_FREE_SONAME(sin);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return ECONNRESET;
+ return (ECONNRESET);
}
SCTP_INP_RLOCK(inp);
sin->sin_port = inp->sctp_lport;
@@ -4825,7 +6376,7 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
SCTP_FREE_SONAME(sin);
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
- return ENOENT;
+ return (ENOENT);
}
}
SCTP_INP_RUNLOCK(inp);
@@ -4836,7 +6387,7 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
int
sctp_peeraddr(struct socket *so, struct sockaddr **addr)
{
- struct sockaddr_in *sin = (struct sockaddr_in *)*addr;
+ struct sockaddr_in *sin;
int fnd;
struct sockaddr_in *sin_a;
struct sctp_inpcb *inp;
@@ -4844,25 +6395,19 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr)
struct sctp_nets *net;
/* Do the malloc first in case it blocks. */
- inp = (struct sctp_inpcb *)so->so_pcb;
- if ((inp == NULL) ||
- ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
- /* UDP type and listeners will drop out here */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
- return (ENOTCONN);
- }
SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
if (sin == NULL)
return (ENOMEM);
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
- /* We must recapture incase we blocked */
inp = (struct sctp_inpcb *)so->so_pcb;
- if (!inp) {
+ if ((inp == NULL) ||
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
+ /* UDP type and listeners will drop out here */
SCTP_FREE_SONAME(sin);
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return ECONNRESET;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
+ return (ENOTCONN);
}
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -4873,7 +6418,7 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr)
if (stcb == NULL) {
SCTP_FREE_SONAME(sin);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- return ECONNRESET;
+ return (ECONNRESET);
}
fnd = 0;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -4890,7 +6435,7 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr)
/* No IPv4 address */
SCTP_FREE_SONAME(sin);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
- return ENOENT;
+ return (ENOENT);
}
(*addr) = (struct sockaddr *)sin;
return (0);
@@ -4916,3 +6461,5 @@ struct pr_usrreqs sctp_usrreqs = {
.pru_sosend = sctp_sosend,
.pru_soreceive = sctp_soreceive
};
+
+#endif
diff --git a/freebsd/sys/netinet/sctp_var.h b/freebsd/sys/netinet/sctp_var.h
index bff7f5de..3862b90b 100644
--- a/freebsd/sys/netinet/sctp_var.h
+++ b/freebsd/sys/netinet/sctp_var.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,8 +30,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp_var.h,v 1.24 2005/03/06 16:04:19 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -48,6 +48,31 @@ extern struct pr_usrreqs sctp_usrreqs;
#define sctp_is_feature_on(inp, feature) ((inp->sctp_features & feature) == feature)
#define sctp_is_feature_off(inp, feature) ((inp->sctp_features & feature) == 0)
+#define sctp_stcb_feature_on(inp, stcb, feature) {\
+ if (stcb) { \
+ stcb->asoc.sctp_features |= feature; \
+ } else if (inp) { \
+ inp->sctp_features |= feature; \
+ } \
+}
+#define sctp_stcb_feature_off(inp, stcb, feature) {\
+ if (stcb) { \
+ stcb->asoc.sctp_features &= ~feature; \
+ } else if (inp) { \
+ inp->sctp_features &= ~feature; \
+ } \
+}
+#define sctp_stcb_is_feature_on(inp, stcb, feature) \
+ (((stcb != NULL) && \
+ ((stcb->asoc.sctp_features & feature) == feature)) || \
+ ((stcb == NULL) && (inp != NULL) && \
+ ((inp->sctp_features & feature) == feature)))
+#define sctp_stcb_is_feature_off(inp, stcb, feature) \
+ (((stcb != NULL) && \
+ ((stcb->asoc.sctp_features & feature) == 0)) || \
+ ((stcb == NULL) && (inp != NULL) && \
+ ((inp->sctp_features & feature) == 0)) || \
+ ((stcb == NULL) && (inp == NULL)))
/* managing mobility_feature in inpcb (by micchie) */
#define sctp_mobility_feature_on(inp, feature) (inp->sctp_mobility_features |= feature)
@@ -85,9 +110,9 @@ extern struct pr_usrreqs sctp_usrreqs;
} \
}
-#define sctp_free_a_strmoq(_stcb, _strmoq) { \
+#define sctp_free_a_strmoq(_stcb, _strmoq, _so_locked) { \
if ((_strmoq)->holds_key_ref) { \
- sctp_auth_key_release(stcb, sp->auth_keyid); \
+ sctp_auth_key_release(stcb, sp->auth_keyid, _so_locked); \
(_strmoq)->holds_key_ref = 0; \
} \
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_strmoq), (_strmoq)); \
@@ -103,9 +128,9 @@ extern struct pr_usrreqs sctp_usrreqs;
} \
}
-#define sctp_free_a_chunk(_stcb, _chk) { \
+#define sctp_free_a_chunk(_stcb, _chk, _so_locked) { \
if ((_chk)->holds_key_ref) {\
- sctp_auth_key_release((_stcb), (_chk)->auth_keyid); \
+ sctp_auth_key_release((_stcb), (_chk)->auth_keyid, _so_locked); \
(_chk)->holds_key_ref = 0; \
} \
if (_stcb) { \
@@ -130,7 +155,7 @@ extern struct pr_usrreqs sctp_usrreqs;
}
#define sctp_alloc_a_chunk(_stcb, _chk) { \
- if (TAILQ_EMPTY(&(_stcb)->asoc.free_chunks)) { \
+ if (TAILQ_EMPTY(&(_stcb)->asoc.free_chunks)) { \
(_chk) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_chunk), struct sctp_tmit_chunk); \
if ((_chk)) { \
SCTP_INCR_CHK_COUNT(); \
@@ -153,7 +178,6 @@ extern struct pr_usrreqs sctp_usrreqs;
if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \
(void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \
(void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \
- (void)SCTP_OS_TIMER_STOP(&(__net)->fr_timer.timer); \
if ((__net)->ro.ro_rt) { \
RTFREE((__net)->ro.ro_rt); \
(__net)->ro.ro_rt = NULL; \
@@ -163,7 +187,7 @@ extern struct pr_usrreqs sctp_usrreqs;
(__net)->ro._s_addr = NULL; \
} \
(__net)->src_addr_selected = 0; \
- (__net)->dest_state = SCTP_ADDR_NOT_REACHABLE; \
+ (__net)->dest_state &= ~SCTP_ADDR_REACHABLE; \
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \
SCTP_DECR_RADDR_COUNT(); \
} \
@@ -210,7 +234,7 @@ extern struct pr_usrreqs sctp_usrreqs;
#define sctp_mbuf_crush(data) do { \
struct mbuf *_m; \
_m = (data); \
- while(_m && (SCTP_BUF_LEN(_m) == 0)) { \
+ while (_m && (SCTP_BUF_LEN(_m) == 0)) { \
(data) = SCTP_BUF_NEXT(_m); \
SCTP_BUF_NEXT(_m) = NULL; \
sctp_m_free(_m); \
@@ -286,6 +310,8 @@ extern struct pr_usrreqs sctp_usrreqs;
#endif
+#define SCTP_PF_ENABLED(_net) (_net->pf_threshold < _net->failure_threshold)
+#define SCTP_NET_IS_PF(_net) (_net->pf_threshold < _net->error_count)
struct sctp_nets;
struct sctp_inpcb;
@@ -298,9 +324,16 @@ int sctp_disconnect(struct socket *so);
void sctp_ctlinput __P((int, struct sockaddr *, void *));
int sctp_ctloutput __P((struct socket *, struct sockopt *));
+
+#ifdef INET
void sctp_input_with_port __P((struct mbuf *, int, uint16_t));
+
+#endif
+#ifdef INET
void sctp_input __P((struct mbuf *, int));
-void sctp_pathmtu_adjustment __P((struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *, uint16_t));
+
+#endif
+void sctp_pathmtu_adjustment __P((struct sctp_tcb *, uint16_t));
void sctp_drain __P((void));
void sctp_init __P((void));
diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c
index e9a279c9..60888bef 100644
--- a/freebsd/sys/netinet/sctputil.c
+++ b/freebsd/sys/netinet/sctputil.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -30,8 +32,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctputil.c,v 1.37 2005/03/07 23:26:09 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_var.h>
#include <netinet/sctp_sysctl.h>
#ifdef INET6
+#include <netinet6/sctp6_var.h>
#endif
#include <netinet/sctp_header.h>
#include <netinet/sctp_output.h>
@@ -49,17 +50,21 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
#include <netinet/sctp_auth.h>
#include <netinet/sctp_asconf.h>
-#include <netinet/sctp_cc_functions.h>
#include <netinet/sctp_bsd_addr.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <sys/proc.h>
#ifndef KTR_SCTP
#define KTR_SCTP KTR_SUBSYS
#endif
+extern struct sctp_cc_functions sctp_cc_functions[];
+extern struct sctp_ss_functions sctp_ss_functions[];
+
void
-sctp_sblog(struct sockbuf *sb,
- struct sctp_tcb *stcb, int from, int incr)
+sctp_sblog(struct sockbuf *sb, struct sctp_tcb *stcb, int from, int incr)
{
struct sctp_cwnd_log sctp_clog;
@@ -103,7 +108,6 @@ sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc)
sctp_clog.x.misc.log4);
}
-
void
rto_logging(struct sctp_nets *net, int from)
{
@@ -111,7 +115,7 @@ rto_logging(struct sctp_nets *net, int from)
memset(&sctp_clog, 0, sizeof(sctp_clog));
sctp_clog.x.rto.net = (void *)net;
- sctp_clog.x.rto.rtt = net->prev_rtt;
+ sctp_clog.x.rto.rtt = net->rtt / 1000;
SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_RTT,
from,
@@ -119,7 +123,6 @@ rto_logging(struct sctp_nets *net, int from)
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
void
@@ -140,7 +143,6 @@ sctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t tsn, uint16_t sseq, uint16
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
void
@@ -162,7 +164,6 @@ sctp_log_nagle_event(struct sctp_tcb *stcb, int action)
sctp_clog.x.misc.log4);
}
-
void
sctp_log_sack(uint32_t old_cumack, uint32_t cumack, uint32_t tsn, uint16_t gaps, uint16_t dups, int from)
{
@@ -201,8 +202,7 @@ sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
}
void
-sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn,
- int from)
+sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn, int from)
{
struct sctp_cwnd_log sctp_clog;
@@ -217,10 +217,8 @@ sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn,
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
-
void
sctp_log_mb(struct mbuf *m, int from)
{
@@ -246,10 +244,8 @@ sctp_log_mb(struct mbuf *m, int from)
sctp_clog.x.misc.log4);
}
-
void
-sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk,
- int from)
+sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk, int from)
{
struct sctp_cwnd_log sctp_clog;
@@ -275,7 +271,6 @@ sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_rea
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
void
@@ -311,7 +306,6 @@ sctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
void
@@ -356,7 +350,6 @@ sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from)
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
void
@@ -384,7 +377,6 @@ sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int b
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
void
@@ -439,7 +431,6 @@ sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mb
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
void
@@ -452,7 +443,7 @@ sctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
}
void
-sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t cumtsn, uint32_t wake_cnt, int from)
+sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from)
{
struct sctp_cwnd_log sctp_clog;
@@ -495,11 +486,10 @@ sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t cumtsn, uint32_t wake_cnt, int f
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
void
-sctp_log_block(uint8_t from, struct socket *so, struct sctp_association *asoc, int sendlen)
+sctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
{
struct sctp_cwnd_log sctp_clog;
@@ -517,11 +507,10 @@ sctp_log_block(uint8_t from, struct socket *so, struct sctp_association *asoc, i
sctp_clog.x.misc.log2,
sctp_clog.x.misc.log3,
sctp_clog.x.misc.log4);
-
}
int
-sctp_fill_stat_log(void *optval, size_t *optsize)
+sctp_fill_stat_log(void *optval SCTP_UNUSED, size_t *optsize SCTP_UNUSED)
{
/* May need to fix this if ktrdump does not work */
return (0);
@@ -699,7 +688,7 @@ sctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
if (lnet->flight_size != tot_out) {
SCTP_PRINTF("net:%p flight was %d corrected to %d\n",
- lnet, lnet->flight_size,
+ (void *)lnet, lnet->flight_size,
tot_out);
lnet->flight_size = tot_out;
}
@@ -737,15 +726,14 @@ sctp_stop_timers_for_shutdown(struct sctp_tcb *stcb)
asoc = &stcb->asoc;
- (void)SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- (void)SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
(void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
+ (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
}
}
@@ -799,7 +787,7 @@ sctp_get_prev_mtu(uint32_t val)
* entry, just return val.
*/
uint32_t
-sctp_get_next_mtu(struct sctp_inpcb *inp, uint32_t val)
+sctp_get_next_mtu(uint32_t val)
{
/* select another MTU that is just bigger than this one */
uint32_t i;
@@ -870,28 +858,29 @@ retry:
}
uint32_t
-sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int save_in_twait)
+sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int check)
{
- uint32_t x, not_done;
+ uint32_t x;
struct timeval now;
- (void)SCTP_GETTIME_TIMEVAL(&now);
- not_done = 1;
- while (not_done) {
+ if (check) {
+ (void)SCTP_GETTIME_TIMEVAL(&now);
+ }
+ for (;;) {
x = sctp_select_initial_TSN(&inp->sctp_ep);
if (x == 0) {
/* we never use 0 */
continue;
}
- if (sctp_is_vtag_good(inp, x, lport, rport, &now, save_in_twait)) {
- not_done = 0;
+ if (!check || sctp_is_vtag_good(x, lport, rport, &now)) {
+ break;
}
}
return (x);
}
int
-sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
+sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
uint32_t override_tag, uint32_t vrf_id)
{
struct sctp_association *asoc;
@@ -912,40 +901,41 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc = &stcb->asoc;
/* init all variables to a known value. */
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
- asoc->max_burst = m->sctp_ep.max_burst;
- asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
- asoc->cookie_life = m->sctp_ep.def_cookie_life;
- asoc->sctp_cmt_on_off = m->sctp_cmt_on_off;
+ asoc->max_burst = inp->sctp_ep.max_burst;
+ asoc->fr_max_burst = inp->sctp_ep.fr_max_burst;
+ asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
+ asoc->cookie_life = inp->sctp_ep.def_cookie_life;
+ asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
+ asoc->ecn_allowed = inp->sctp_ecn_enable;
asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
- asoc->sctp_cmt_pf = (uint8_t) SCTP_BASE_SYSCTL(sctp_cmt_pf);
- asoc->sctp_frag_point = m->sctp_frag_point;
-#ifdef INET
- asoc->default_tos = m->ip_inp.inp.inp_ip_tos;
-#else
- asoc->default_tos = 0;
-#endif
-
+ asoc->sctp_cmt_pf = (uint8_t) 0;
+ asoc->sctp_frag_point = inp->sctp_frag_point;
+ asoc->sctp_features = inp->sctp_features;
+ asoc->default_dscp = inp->sctp_ep.default_dscp;
#ifdef INET6
- asoc->default_flowlabel = ((struct in6pcb *)m)->in6p_flowinfo;
-#else
- asoc->default_flowlabel = 0;
+ if (inp->sctp_ep.default_flowlabel) {
+ asoc->default_flowlabel = inp->sctp_ep.default_flowlabel;
+ } else {
+ if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) {
+ asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep);
+ asoc->default_flowlabel &= 0x000fffff;
+ asoc->default_flowlabel |= 0x80000000;
+ } else {
+ asoc->default_flowlabel = 0;
+ }
+ }
#endif
asoc->sb_send_resv = 0;
if (override_tag) {
asoc->my_vtag = override_tag;
} else {
- asoc->my_vtag = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
+ asoc->my_vtag = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
}
/* Get the nonce tags */
- asoc->my_vtag_nonce = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
- asoc->peer_vtag_nonce = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
+ asoc->my_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
+ asoc->peer_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
asoc->vrf_id = vrf_id;
- if (sctp_is_feature_on(m, SCTP_PCB_FLAGS_DONOT_HEARTBEAT))
- asoc->hb_is_disabled = 1;
- else
- asoc->hb_is_disabled = 0;
-
#ifdef SCTP_ASOCLOG_OF_TSNS
asoc->tsn_in_at = 0;
asoc->tsn_out_at = 0;
@@ -960,7 +950,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->refcnt = 0;
asoc->assoc_up_sent = 0;
asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
- sctp_select_initial_TSN(&m->sctp_ep);
+ sctp_select_initial_TSN(&inp->sctp_ep);
asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
/* we are optimisitic here */
asoc->peer_supports_pktdrop = 1;
@@ -971,7 +961,6 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->last_net_cmt_send_started = NULL;
/* This will need to be adjusted */
- asoc->last_cwr_tsn = asoc->init_seq_number - 1;
asoc->last_acked_seq = asoc->init_seq_number - 1;
asoc->advanced_peer_ack_point = asoc->last_acked_seq;
asoc->asconf_seq_in = asoc->last_acked_seq;
@@ -979,55 +968,42 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
/* here we are different, we hold the next one we expect */
asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
- asoc->initial_init_rto_max = m->sctp_ep.initial_init_rto_max;
- asoc->initial_rto = m->sctp_ep.initial_rto;
+ asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max;
+ asoc->initial_rto = inp->sctp_ep.initial_rto;
- asoc->max_init_times = m->sctp_ep.max_init_times;
- asoc->max_send_times = m->sctp_ep.max_send_times;
- asoc->def_net_failure = m->sctp_ep.def_net_failure;
+ asoc->max_init_times = inp->sctp_ep.max_init_times;
+ asoc->max_send_times = inp->sctp_ep.max_send_times;
+ asoc->def_net_failure = inp->sctp_ep.def_net_failure;
+ asoc->def_net_pf_threshold = inp->sctp_ep.def_net_pf_threshold;
asoc->free_chunk_cnt = 0;
asoc->iam_blocking = 0;
- /* ECN Nonce initialization */
- asoc->context = m->sctp_context;
- asoc->def_send = m->def_send;
- asoc->ecn_nonce_allowed = 0;
- asoc->receiver_nonce_sum = 1;
- asoc->nonce_sum_expect_base = 1;
- asoc->nonce_sum_check = 1;
- asoc->nonce_resync_tsn = 0;
- asoc->nonce_wait_for_ecne = 0;
- asoc->nonce_wait_tsn = 0;
- asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
- asoc->sack_freq = m->sctp_ep.sctp_sack_freq;
+ asoc->context = inp->sctp_context;
+ asoc->local_strreset_support = inp->local_strreset_support;
+ asoc->def_send = inp->def_send;
+ asoc->delayed_ack = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
+ asoc->sack_freq = inp->sctp_ep.sctp_sack_freq;
asoc->pr_sctp_cnt = 0;
asoc->total_output_queue_size = 0;
- if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- struct in6pcb *inp6;
-
- /* Its a V6 socket */
- inp6 = (struct in6pcb *)m;
- asoc->ipv6_addr_legal = 1;
- /* Now look at the binding flag to see if V4 will be legal */
- if (SCTP_IPV6_V6ONLY(inp6) == 0) {
- asoc->ipv4_addr_legal = 1;
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ asoc->scope.ipv6_addr_legal = 1;
+ if (SCTP_IPV6_V6ONLY(inp) == 0) {
+ asoc->scope.ipv4_addr_legal = 1;
} else {
- /* V4 addresses are NOT legal on the association */
- asoc->ipv4_addr_legal = 0;
+ asoc->scope.ipv4_addr_legal = 0;
}
} else {
- /* Its a V4 socket, no - V6 */
- asoc->ipv4_addr_legal = 1;
- asoc->ipv6_addr_legal = 0;
+ asoc->scope.ipv6_addr_legal = 0;
+ asoc->scope.ipv4_addr_legal = 1;
}
- asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(m->sctp_socket), SCTP_MINIMAL_RWND);
- asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(m->sctp_socket);
+ asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND);
+ asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(inp->sctp_socket);
- asoc->smallest_mtu = m->sctp_frag_point;
- asoc->minrto = m->sctp_ep.sctp_minrto;
- asoc->maxrto = m->sctp_ep.sctp_maxrto;
+ asoc->smallest_mtu = inp->sctp_frag_point;
+ asoc->minrto = inp->sctp_ep.sctp_minrto;
+ asoc->maxrto = inp->sctp_ep.sctp_maxrto;
asoc->locked_on_sending = NULL;
asoc->stream_locked_on = 0;
@@ -1044,77 +1020,20 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
/* Setup to fill the hb random cache at first HB */
asoc->hb_random_idx = 4;
- asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time;
+ asoc->sctp_autoclose_ticks = inp->sctp_ep.auto_close_time;
- /*
- * JRS - Pick the default congestion control module based on the
- * sysctl.
- */
- switch (m->sctp_ep.sctp_default_cc_module) {
- /* JRS - Standard TCP congestion control */
- case SCTP_CC_RFC2581:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_RFC2581;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer;
- break;
- }
- /* JRS - High Speed TCP congestion control (Floyd) */
- case SCTP_CC_HSTCP:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_HSTCP;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_hs_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_hs_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer;
- break;
- }
- /* JRS - HTCP congestion control */
- case SCTP_CC_HTCP:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_HTCP;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_htcp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_htcp_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_htcp_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_htcp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_htcp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_htcp_cwnd_update_after_fr_timer;
- break;
- }
- /* JRS - By default, use RFC2581 */
- default:
- {
- stcb->asoc.congestion_control_module = SCTP_CC_RFC2581;
- stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_cwnd_update_after_sack;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_cwnd_update_after_fr;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output;
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer;
- break;
- }
- }
+ stcb->asoc.congestion_control_module = inp->sctp_ep.sctp_default_cc_module;
+ stcb->asoc.cc_functions = sctp_cc_functions[inp->sctp_ep.sctp_default_cc_module];
+
+ stcb->asoc.stream_scheduling_module = inp->sctp_ep.sctp_default_ss_module;
+ stcb->asoc.ss_functions = sctp_ss_functions[inp->sctp_ep.sctp_default_ss_module];
/*
* Now the stream parameters, here we allocate space for all streams
* that we request by default.
*/
asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams =
- m->sctp_ep.pre_open_stream_count;
+ inp->sctp_ep.pre_open_stream_count;
SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *,
asoc->streamoutcnt * sizeof(struct sctp_stream_out),
SCTP_M_STRMO);
@@ -1132,13 +1051,15 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
* that were dropped must be notified to the upper layer as
* failed to send.
*/
- asoc->strmout[i].next_sequence_sent = 0x0;
+ asoc->strmout[i].next_sequence_send = 0x0;
TAILQ_INIT(&asoc->strmout[i].outqueue);
+ asoc->strmout[i].chunks_on_queues = 0;
asoc->strmout[i].stream_no = i;
asoc->strmout[i].last_msg_incomplete = 0;
- asoc->strmout[i].next_spoke.tqe_next = 0;
- asoc->strmout[i].next_spoke.tqe_prev = 0;
+ asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
}
+ asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
+
/* Now the mapping array */
asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size,
@@ -1161,14 +1082,13 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
/* Now the init of the other outqueues */
TAILQ_INIT(&asoc->free_chunks);
- TAILQ_INIT(&asoc->out_wheel);
TAILQ_INIT(&asoc->control_send_queue);
TAILQ_INIT(&asoc->asconf_send_queue);
TAILQ_INIT(&asoc->send_queue);
TAILQ_INIT(&asoc->sent_queue);
TAILQ_INIT(&asoc->reasmqueue);
TAILQ_INIT(&asoc->resetHead);
- asoc->max_inbound_streams = m->sctp_ep.max_open_streams_intome;
+ asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome;
TAILQ_INIT(&asoc->asconf_queue);
/* authentication fields */
asoc->authinfo.random = NULL;
@@ -1179,6 +1099,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->authinfo.recv_keyid = 0;
LIST_INIT(&asoc->shared_keys);
asoc->marked_retrans = 0;
+ asoc->port = inp->sctp_ep.port;
asoc->timoinit = 0;
asoc->timodata = 0;
asoc->timosack = 0;
@@ -1200,34 +1121,34 @@ sctp_print_mapping_array(struct sctp_association *asoc)
{
unsigned int i, limit;
- printf("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n",
+ SCTP_PRINTF("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n",
asoc->mapping_array_size,
asoc->mapping_array_base_tsn,
asoc->cumulative_tsn,
asoc->highest_tsn_inside_map,
asoc->highest_tsn_inside_nr_map);
for (limit = asoc->mapping_array_size; limit > 1; limit--) {
- if (asoc->mapping_array[limit - 1]) {
+ if (asoc->mapping_array[limit - 1] != 0) {
break;
}
}
- printf("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
+ SCTP_PRINTF("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
for (i = 0; i < limit; i++) {
- printf("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
+ SCTP_PRINTF("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
}
if (limit % 16)
- printf("\n");
+ SCTP_PRINTF("\n");
for (limit = asoc->mapping_array_size; limit > 1; limit--) {
if (asoc->nr_mapping_array[limit - 1]) {
break;
}
}
- printf("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
+ SCTP_PRINTF("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
for (i = 0; i < limit; i++) {
- printf("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
+ SCTP_PRINTF("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
}
if (limit % 16)
- printf("\n");
+ SCTP_PRINTF("\n");
}
int
@@ -1355,10 +1276,6 @@ select_a_new_ep:
SCTP_INP_DECR_REF(it->inp);
atomic_add_int(&it->stcb->asoc.refcnt, -1);
if (sctp_it_ctl.iterator_flags &
- SCTP_ITERATOR_MUST_EXIT) {
- goto done_with_iterator;
- }
- if (sctp_it_ctl.iterator_flags &
SCTP_ITERATOR_STOP_CUR_IT) {
sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT;
goto done_with_iterator;
@@ -1369,7 +1286,7 @@ select_a_new_ep:
goto no_stcb;
}
/* If we reach here huh? */
- printf("Unknown it ctl flag %x\n",
+ SCTP_PRINTF("Unknown it ctl flag %x\n",
sctp_it_ctl.iterator_flags);
sctp_it_ctl.iterator_flags = 0;
}
@@ -1419,27 +1336,22 @@ no_stcb:
void
sctp_iterator_worker(void)
{
- struct sctp_iterator *it = NULL;
+ struct sctp_iterator *it, *nit;
/* This function is called with the WQ lock in place */
sctp_it_ctl.iterator_running = 1;
- sctp_it_ctl.cur_it = it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
- while (it) {
+ TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
+ sctp_it_ctl.cur_it = it;
/* now lets work on this one */
TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
SCTP_IPI_ITERATOR_WQ_UNLOCK();
CURVNET_SET(it->vn);
sctp_iterator_work(it);
-
+ sctp_it_ctl.cur_it = NULL;
CURVNET_RESTORE();
SCTP_IPI_ITERATOR_WQ_LOCK();
- if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) {
- sctp_it_ctl.cur_it = NULL;
- break;
- }
/* sa_ignore FREED_MEMORY */
- sctp_it_ctl.cur_it = it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
}
sctp_it_ctl.iterator_running = 0;
return;
@@ -1450,7 +1362,7 @@ static void
sctp_handle_addr_wq(void)
{
/* deal with the ADDR wq from the rtsock calls */
- struct sctp_laddr *wi;
+ struct sctp_laddr *wi, *nwi;
struct sctp_asconf_iterator *asc;
SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
@@ -1467,12 +1379,10 @@ sctp_handle_addr_wq(void)
asc->cnt = 0;
SCTP_WQ_ADDR_LOCK();
- wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq));
- while (wi != NULL) {
+ LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
LIST_REMOVE(wi, sctp_nxt_addr);
LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
asc->cnt++;
- wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq));
}
SCTP_WQ_ADDR_UNLOCK();
@@ -1490,9 +1400,6 @@ sctp_handle_addr_wq(void)
}
}
-int retcode = 0;
-int cur_oerr = 0;
-
void
sctp_timeout_handler(void *t)
{
@@ -1501,7 +1408,7 @@ sctp_timeout_handler(void *t)
struct sctp_nets *net;
struct sctp_timer *tmr;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
@@ -1523,7 +1430,7 @@ sctp_timeout_handler(void *t)
if (tmr->self != (void *)tmr) {
/*
* SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n",
- * tmr);
+ * (void *)tmr);
*/
CURVNET_RESTORE();
return;
@@ -1547,7 +1454,7 @@ sctp_timeout_handler(void *t)
type = tmr->type;
if (inp) {
SCTP_INP_INCR_REF(inp);
- if ((inp->sctp_socket == 0) &&
+ if ((inp->sctp_socket == NULL) &&
((tmr->type != SCTP_TIMER_TYPE_INPKILL) &&
(tmr->type != SCTP_TIMER_TYPE_INIT) &&
(tmr->type != SCTP_TIMER_TYPE_SEND) &&
@@ -1653,9 +1560,7 @@ sctp_timeout_handler(void *t)
stcb->asoc.num_send_timers_up = 0;
}
SCTP_TCB_LOCK_ASSERT(stcb);
- cur_oerr = stcb->asoc.overall_error_count;
- retcode = sctp_t3rxt_timer(inp, stcb, net);
- if (retcode) {
+ if (sctp_t3rxt_timer(inp, stcb, net)) {
/* no need to unlock on tcb its gone */
goto out_decr;
@@ -1666,8 +1571,7 @@ sctp_timeout_handler(void *t)
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
if ((stcb->asoc.num_send_timers_up == 0) &&
- (stcb->asoc.sent_queue_cnt > 0)
- ) {
+ (stcb->asoc.sent_queue_cnt > 0)) {
struct sctp_tmit_chunk *chk;
/*
@@ -1697,11 +1601,10 @@ sctp_timeout_handler(void *t)
case SCTP_TIMER_TYPE_RECV:
if ((stcb == NULL) || (inp == NULL)) {
break;
- } {
- SCTP_STAT_INCR(sctps_timosack);
- stcb->asoc.timosack++;
- sctp_send_sack(stcb);
}
+ SCTP_STAT_INCR(sctps_timosack);
+ stcb->asoc.timosack++;
+ sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
@@ -1723,33 +1626,20 @@ sctp_timeout_handler(void *t)
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_HEARTBEAT:
- {
- struct sctp_nets *lnet;
- int cnt_of_unconf = 0;
-
- if ((stcb == NULL) || (inp == NULL)) {
- break;
- }
- SCTP_STAT_INCR(sctps_timoheartbeat);
- stcb->asoc.timoheartbeat++;
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
- (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
- cnt_of_unconf++;
- }
- }
- if (cnt_of_unconf == 0) {
- if (sctp_heartbeat_timer(inp, stcb, lnet,
- cnt_of_unconf)) {
- /* no need to unlock on tcb its gone */
- goto out_decr;
- }
- }
+ if ((stcb == NULL) || (inp == NULL) || (net == NULL)) {
+ break;
+ }
+ SCTP_STAT_INCR(sctps_timoheartbeat);
+ stcb->asoc.timoheartbeat++;
+ if (sctp_heartbeat_timer(inp, stcb, net)) {
+ /* no need to unlock on tcb its gone */
+ goto out_decr;
+ }
#ifdef SCTP_AUDITING_ENABLED
- sctp_auditing(4, inp, stcb, lnet);
+ sctp_auditing(4, inp, stcb, net);
#endif
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT,
- stcb->sctp_ep, stcb, lnet);
+ if (!(net->dest_state & SCTP_ADDR_NOHB)) {
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED);
}
break;
@@ -1829,8 +1719,7 @@ sctp_timeout_handler(void *t)
break;
}
SCTP_STAT_INCR(sctps_timoshutdownguard);
- sctp_abort_an_association(inp, stcb,
- SCTP_SHUTDOWN_GUARD_EXPIRES, NULL, SCTP_SO_NOT_LOCKED);
+ sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED);
/* no need to unlock on tcb its gone */
goto out_decr;
@@ -1845,14 +1734,6 @@ sctp_timeout_handler(void *t)
SCTP_STAT_INCR(sctps_timostrmrst);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED);
break;
- case SCTP_TIMER_TYPE_EARLYFR:
- /* Need to do FR of things for net */
- if ((stcb == NULL) || (inp == NULL)) {
- break;
- }
- SCTP_STAT_INCR(sctps_timoearlyfr);
- sctp_early_fr_timer(inp, stcb, net);
- break;
case SCTP_TIMER_TYPE_ASCONF:
if ((stcb == NULL) || (inp == NULL)) {
break;
@@ -1892,7 +1773,7 @@ sctp_timeout_handler(void *t)
/* Can we free it yet? */
SCTP_INP_DECR_REF(inp);
sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_1);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -1901,7 +1782,7 @@ sctp_timeout_handler(void *t)
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_2);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
/*
@@ -1929,7 +1810,7 @@ sctp_timeout_handler(void *t)
SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n",
tmr->type);
break;
- };
+ }
#ifdef SCTP_AUDITING_ENABLED
sctp_audit_log(0xF1, (uint8_t) tmr->type);
if (inp)
@@ -1963,14 +1844,12 @@ void
sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net)
{
- int to_ticks;
+ uint32_t to_ticks;
struct sctp_timer *tmr;
if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL))
return;
- to_ticks = 0;
-
tmr = NULL;
if (stcb) {
SCTP_TCB_LOCK_ASSERT(stcb);
@@ -2050,71 +1929,38 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* though we use a different timer. We also add the HB timer
* PLUS a random jitter.
*/
- if ((inp == NULL) || (stcb == NULL)) {
+ if ((inp == NULL) || (stcb == NULL) || (net == NULL)) {
return;
} else {
uint32_t rndval;
- uint8_t this_random;
- int cnt_of_unconf = 0;
- struct sctp_nets *lnet;
-
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
- (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
- cnt_of_unconf++;
- }
- }
- if (cnt_of_unconf) {
- net = lnet = NULL;
- (void)sctp_heartbeat_timer(inp, stcb, lnet, cnt_of_unconf);
- }
- if (stcb->asoc.hb_random_idx > 3) {
- rndval = sctp_select_initial_TSN(&inp->sctp_ep);
- memcpy(stcb->asoc.hb_random_values, &rndval,
- sizeof(stcb->asoc.hb_random_values));
- stcb->asoc.hb_random_idx = 0;
- }
- this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
- stcb->asoc.hb_random_idx++;
- stcb->asoc.hb_ect_randombit = 0;
- /*
- * this_random will be 0 - 256 ms RTO is in ms.
- */
- if ((stcb->asoc.hb_is_disabled) &&
- (cnt_of_unconf == 0)) {
+ uint32_t jitter;
+
+ if ((net->dest_state & SCTP_ADDR_NOHB) &&
+ !(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
return;
}
- if (net) {
- int delay;
-
- delay = stcb->asoc.heart_beat_delay;
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
- ((lnet->dest_state & SCTP_ADDR_OUT_OF_SCOPE) == 0) &&
- (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
- delay = 0;
- }
- }
- if (net->RTO == 0) {
- /* Never been checked */
- to_ticks = this_random + stcb->asoc.initial_rto + delay;
- } else {
- /* set rto_val to the ms */
- to_ticks = delay + net->RTO + this_random;
- }
+ if (net->RTO == 0) {
+ to_ticks = stcb->asoc.initial_rto;
} else {
- if (cnt_of_unconf) {
- to_ticks = this_random + stcb->asoc.initial_rto;
- } else {
- to_ticks = stcb->asoc.heart_beat_delay + this_random + stcb->asoc.initial_rto;
- }
+ to_ticks = net->RTO;
+ }
+ rndval = sctp_select_initial_TSN(&inp->sctp_ep);
+ jitter = rndval % to_ticks;
+ if (jitter >= (to_ticks >> 1)) {
+ to_ticks = to_ticks + (jitter - (to_ticks >> 1));
+ } else {
+ to_ticks = to_ticks - jitter;
+ }
+ if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
+ !(net->dest_state & SCTP_ADDR_PF)) {
+ to_ticks += net->heart_beat_delay;
}
/*
* Now we must convert the to_ticks that are now in
* ms to ticks.
*/
to_ticks = MSEC_TO_TICKS(to_ticks);
- tmr = &stcb->asoc.hb_timer;
+ tmr = &net->hb_timer;
}
break;
case SCTP_TIMER_TYPE_COOKIE:
@@ -2174,6 +2020,9 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (net == NULL) {
return;
}
+ if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
+ return;
+ }
to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
tmr = &net->pmtu_timer;
break;
@@ -2215,35 +2064,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
tmr = &stcb->asoc.strreset_timer;
break;
-
- case SCTP_TIMER_TYPE_EARLYFR:
- {
- unsigned int msec;
-
- if ((stcb == NULL) || (net == NULL)) {
- return;
- }
- if (net->flight_size > net->cwnd) {
- /* no need to start */
- return;
- }
- SCTP_STAT_INCR(sctps_earlyfrstart);
- if (net->lastsa == 0) {
- /* Hmm no rtt estimate yet? */
- msec = stcb->asoc.initial_rto >> 2;
- } else {
- msec = ((net->lastsa >> 2) + net->lastsv) >> 1;
- }
- if (msec < SCTP_BASE_SYSCTL(sctp_early_fr_msec)) {
- msec = SCTP_BASE_SYSCTL(sctp_early_fr_msec);
- if (msec < SCTP_MINFR_MSEC_FLOOR) {
- msec = SCTP_MINFR_MSEC_FLOOR;
- }
- }
- to_ticks = MSEC_TO_TICKS(msec);
- tmr = &net->fr_timer;
- }
- break;
case SCTP_TIMER_TYPE_ASCONF:
/*
* Here the timer comes from the stcb but its value is from
@@ -2285,10 +2105,10 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
__FUNCTION__, t_type);
return;
break;
- };
+ }
if ((to_ticks <= 0) || (tmr == NULL)) {
SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n",
- __FUNCTION__, t_type, to_ticks, tmr);
+ __FUNCTION__, t_type, to_ticks, (void *)tmr);
return;
}
if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
@@ -2338,13 +2158,6 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
case SCTP_TIMER_TYPE_ADDR_WQ:
tmr = &SCTP_BASE_INFO(addr_wq_timer);
break;
- case SCTP_TIMER_TYPE_EARLYFR:
- if ((stcb == NULL) || (net == NULL)) {
- return;
- }
- tmr = &net->fr_timer;
- SCTP_STAT_INCR(sctps_earlyfrstop);
- break;
case SCTP_TIMER_TYPE_SEND:
if ((stcb == NULL) || (net == NULL)) {
return;
@@ -2370,10 +2183,10 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
tmr = &net->rxt_timer;
break;
case SCTP_TIMER_TYPE_HEARTBEAT:
- if (stcb == NULL) {
+ if ((stcb == NULL) || (net == NULL)) {
return;
}
- tmr = &stcb->asoc.hb_timer;
+ tmr = &net->hb_timer;
break;
case SCTP_TIMER_TYPE_COOKIE:
if ((stcb == NULL) || (net == NULL)) {
@@ -2453,7 +2266,7 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
__FUNCTION__, t_type);
break;
- };
+ }
if (tmr == NULL) {
return;
}
@@ -2528,20 +2341,20 @@ sctp_mtu_size_reset(struct sctp_inpcb *inp,
* given an association and starting time of the current RTT period return
* RTO in number of msecs net should point to the current network
*/
+
uint32_t
sctp_calculate_rto(struct sctp_tcb *stcb,
struct sctp_association *asoc,
struct sctp_nets *net,
struct timeval *told,
- int safe)
+ int safe, int rtt_from_sack)
{
/*-
* given an association and the starting time of the current RTT
* period (in value1/value2) return RTO in number of msecs.
*/
- int calc_time = 0;
- int o_calctime;
- uint32_t new_rto = 0;
+ int32_t rtt; /* RTT in ms */
+ uint32_t new_rto;
int first_measure = 0;
struct timeval now, then, *old;
@@ -2560,81 +2373,72 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
/* 1. calculate new RTT */
/************************/
/* get the current time */
- (void)SCTP_GETTIME_TIMEVAL(&now);
- /* compute the RTT value */
- if ((u_long)now.tv_sec > (u_long)old->tv_sec) {
- calc_time = ((u_long)now.tv_sec - (u_long)old->tv_sec) * 1000;
- if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
- calc_time += (((u_long)now.tv_usec -
- (u_long)old->tv_usec) / 1000);
- } else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
- /* Borrow 1,000ms from current calculation */
- calc_time -= 1000;
- /* Add in the slop over */
- calc_time += ((int)now.tv_usec / 1000);
- /* Add in the pre-second ms's */
- calc_time += (((int)1000000 - (int)old->tv_usec) / 1000);
- }
- } else if ((u_long)now.tv_sec == (u_long)old->tv_sec) {
- if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
- calc_time = ((u_long)now.tv_usec -
- (u_long)old->tv_usec) / 1000;
- } else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
- /* impossible .. garbage in nothing out */
- goto calc_rto;
- } else if ((u_long)now.tv_usec == (u_long)old->tv_usec) {
- /*
- * We have to have 1 usec :-D this must be the
- * loopback.
- */
- calc_time = 1;
+ if (stcb->asoc.use_precise_time) {
+ (void)SCTP_GETPTIME_TIMEVAL(&now);
+ } else {
+ (void)SCTP_GETTIME_TIMEVAL(&now);
+ }
+ timevalsub(&now, old);
+ /* store the current RTT in us */
+ net->rtt = (uint64_t) 1000000 *(uint64_t) now.tv_sec +
+ (uint64_t) now.tv_usec;
+
+ /* computer rtt in ms */
+ rtt = net->rtt / 1000;
+ if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) {
+ /*
+ * Tell the CC module that a new update has just occurred
+ * from a sack
+ */
+ (*asoc->cc_functions.sctp_rtt_calculated) (stcb, net, &now);
+ }
+ /*
+ * Do we need to determine the lan? We do this only on sacks i.e.
+ * RTT being determined from data not non-data (HB/INIT->INITACK).
+ */
+ if ((rtt_from_sack == SCTP_RTT_FROM_DATA) &&
+ (net->lan_type == SCTP_LAN_UNKNOWN)) {
+ if (net->rtt > SCTP_LOCAL_LAN_RTT) {
+ net->lan_type = SCTP_LAN_INTERNET;
} else {
- /* impossible .. garbage in nothing out */
- goto calc_rto;
+ net->lan_type = SCTP_LAN_LOCAL;
}
- } else {
- /* Clock wrapped? */
- goto calc_rto;
}
/***************************/
/* 2. update RTTVAR & SRTT */
/***************************/
- net->rtt = o_calctime = calc_time;
- /* this is Van Jacobson's integer version */
+ /*-
+ * Compute the scaled average lastsa and the
+ * scaled variance lastsv as described in van Jacobson
+ * Paper "Congestion Avoidance and Control", Annex A.
+ *
+ * (net->lastsa >> SCTP_RTT_SHIFT) is the srtt
+ * (net->lastsa >> SCTP_RTT_VAR_SHIFT) is the rttvar
+ */
if (net->RTO_measured) {
- calc_time -= (net->lastsa >> SCTP_RTT_SHIFT); /* take away 1/8th when
- * shift=3 */
+ rtt -= (net->lastsa >> SCTP_RTT_SHIFT);
+ net->lastsa += rtt;
+ if (rtt < 0) {
+ rtt = -rtt;
+ }
+ rtt -= (net->lastsv >> SCTP_RTT_VAR_SHIFT);
+ net->lastsv += rtt;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) {
rto_logging(net, SCTP_LOG_RTTVAR);
}
- net->prev_rtt = o_calctime;
- net->lastsa += calc_time; /* add 7/8th into sa when
- * shift=3 */
- if (calc_time < 0) {
- calc_time = -calc_time;
- }
- calc_time -= (net->lastsv >> SCTP_RTT_VAR_SHIFT); /* take away 1/4 when
- * VAR shift=2 */
- net->lastsv += calc_time;
- if (net->lastsv == 0) {
- net->lastsv = SCTP_CLOCK_GRANULARITY;
- }
} else {
/* First RTO measurment */
net->RTO_measured = 1;
- net->lastsa = calc_time << SCTP_RTT_SHIFT; /* Multiply by 8 when
- * shift=3 */
- net->lastsv = calc_time;
- if (net->lastsv == 0) {
- net->lastsv = SCTP_CLOCK_GRANULARITY;
- }
first_measure = 1;
- net->prev_rtt = o_calctime;
+ net->lastsa = rtt << SCTP_RTT_SHIFT;
+ net->lastsv = (rtt / 2) << SCTP_RTT_VAR_SHIFT;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) {
rto_logging(net, SCTP_LOG_INITIAL_RTT);
}
}
-calc_rto:
+ if (net->lastsv == 0) {
+ net->lastsv = SCTP_CLOCK_GRANULARITY;
+ }
new_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
if ((new_rto > SCTP_SAT_NETWORK_MIN) &&
(stcb->asoc.sat_network_lockout == 0)) {
@@ -2742,8 +2546,8 @@ sctp_add_pad_tombuf(struct mbuf *m, int padlen)
tmp = sctp_get_mbuf_for_msg(padlen, 0, M_DONTWAIT, 1, MT_DATA);
if (tmp == NULL) {
/* Out of space GAK! we are in big trouble. */
- SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
- return (ENOSPC);
+ SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
+ return (ENOBUFS);
}
/* setup and insert in middle */
SCTP_BUF_LEN(tmp) = padlen;
@@ -2765,15 +2569,13 @@ sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
/* find the last mbuf in chain and pad it */
struct mbuf *m_at;
- m_at = m;
if (last_mbuf) {
return (sctp_add_pad_tombuf(last_mbuf, padval));
} else {
- while (m_at) {
+ for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
if (SCTP_BUF_NEXT(m_at) == NULL) {
return (sctp_add_pad_tombuf(m_at, padval));
}
- m_at = SCTP_BUF_NEXT(m_at);
}
}
SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
@@ -2781,8 +2583,8 @@ sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
}
static void
-sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
- uint32_t error, void *data, int so_locked
+sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
+ uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
@@ -2791,111 +2593,134 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
struct mbuf *m_notify;
struct sctp_assoc_change *sac;
struct sctp_queued_to_read *control;
+ size_t notif_len, abort_len;
+ unsigned int i;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
- /*
- * For TCP model AND UDP connected sockets we will send an error up
- * when an ABORT comes in.
- */
- if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
- (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
- ((event == SCTP_COMM_LOST) || (event == SCTP_CANT_STR_ASSOC))) {
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
- SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED);
- stcb->sctp_socket->so_error = ECONNREFUSED;
+ if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
+ notif_len = sizeof(struct sctp_assoc_change);
+ if (abort != NULL) {
+ abort_len = htons(abort->ch.chunk_length);
} else {
- SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
- stcb->sctp_socket->so_error = ECONNRESET;
+ abort_len = 0;
+ }
+ if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
+ notif_len += SCTP_ASSOC_SUPPORTS_MAX;
+ } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) {
+ notif_len += abort_len;
+ }
+ m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
+ if (m_notify == NULL) {
+ /* Retry with smaller value. */
+ notif_len = sizeof(struct sctp_assoc_change);
+ m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
+ if (m_notify == NULL) {
+ goto set_error;
+ }
}
- /* Wake ANY sleepers */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- so = SCTP_INP_SO(stcb->sctp_ep);
- if (!so_locked) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- SCTP_SOCKET_LOCK(so, 1);
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
- SCTP_SOCKET_UNLOCK(so, 1);
- return;
+ SCTP_BUF_NEXT(m_notify) = NULL;
+ sac = mtod(m_notify, struct sctp_assoc_change *);
+ sac->sac_type = SCTP_ASSOC_CHANGE;
+ sac->sac_flags = 0;
+ sac->sac_length = sizeof(struct sctp_assoc_change);
+ sac->sac_state = state;
+ sac->sac_error = error;
+ /* XXX verify these stream counts */
+ sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
+ sac->sac_inbound_streams = stcb->asoc.streamincnt;
+ sac->sac_assoc_id = sctp_get_associd(stcb);
+ if (notif_len > sizeof(struct sctp_assoc_change)) {
+ if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
+ i = 0;
+ if (stcb->asoc.peer_supports_prsctp) {
+ sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
+ }
+ if (stcb->asoc.peer_supports_auth) {
+ sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
+ }
+ if (stcb->asoc.peer_supports_asconf) {
+ sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
+ }
+ sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
+ if (stcb->asoc.peer_supports_strreset) {
+ sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
+ }
+ sac->sac_length += i;
+ } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) {
+ memcpy(sac->sac_info, abort, abort_len);
+ sac->sac_length += abort_len;
}
}
-#endif
- socantrcvmore(stcb->sctp_socket);
- sorwakeup(stcb->sctp_socket);
- sowwakeup(stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if (!so_locked) {
- SCTP_SOCKET_UNLOCK(so, 1);
+ SCTP_BUF_LEN(m_notify) = sac->sac_length;
+ control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
+ m_notify);
+ if (control != NULL) {
+ control->length = SCTP_BUF_LEN(m_notify);
+ /* not that we need this */
+ control->tail_mbuf = m_notify;
+ control->spec_flags = M_NOTIFICATION;
+ sctp_add_to_readq(stcb->sctp_ep, stcb,
+ control,
+ &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD,
+ so_locked);
+ } else {
+ sctp_m_freem(m_notify);
}
-#endif
- }
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
- /* event not enabled */
- return;
- }
- m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_change), 0, M_DONTWAIT, 1, MT_DATA);
- if (m_notify == NULL)
- /* no space left */
- return;
- SCTP_BUF_LEN(m_notify) = 0;
-
- sac = mtod(m_notify, struct sctp_assoc_change *);
- sac->sac_type = SCTP_ASSOC_CHANGE;
- sac->sac_flags = 0;
- sac->sac_length = sizeof(struct sctp_assoc_change);
- sac->sac_state = event;
- sac->sac_error = error;
- /* XXX verify these stream counts */
- sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
- sac->sac_inbound_streams = stcb->asoc.streamincnt;
- sac->sac_assoc_id = sctp_get_associd(stcb);
- SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_change);
- SCTP_BUF_NEXT(m_notify) = NULL;
- control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
- m_notify);
- if (control == NULL) {
- /* no memory */
- sctp_m_freem(m_notify);
- return;
}
- control->length = SCTP_BUF_LEN(m_notify);
- /* not that we need this */
- control->tail_mbuf = m_notify;
- control->spec_flags = M_NOTIFICATION;
- sctp_add_to_readq(stcb->sctp_ep, stcb,
- control,
- &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD,
- so_locked);
- if (event == SCTP_COMM_LOST) {
- /* Wake up any sleeper */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- so = SCTP_INP_SO(stcb->sctp_ep);
- if (!so_locked) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- SCTP_SOCKET_LOCK(so, 1);
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
- SCTP_SOCKET_UNLOCK(so, 1);
- return;
+ /*
+ * For 1-to-1 style sockets, we send up and error when an ABORT
+ * comes in.
+ */
+set_error:
+ if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
+ ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
+ SOCK_LOCK(stcb->sctp_socket);
+ if (from_peer) {
+ if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED);
+ stcb->sctp_socket->so_error = ECONNREFUSED;
+ } else {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
+ stcb->sctp_socket->so_error = ECONNRESET;
}
+ } else {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED);
+ stcb->sctp_socket->so_error = ECONNABORTED;
}
-#endif
- sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if (!so_locked) {
+ }
+ /* Wake ANY sleepers */
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ so = SCTP_INP_SO(stcb->sctp_ep);
+ if (!so_locked) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_SOCKET_LOCK(so, 1);
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
SCTP_SOCKET_UNLOCK(so, 1);
+ return;
}
+ }
#endif
+ if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
+ ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
+ socantrcvmore_locked(stcb->sctp_socket);
+ }
+ sorwakeup(stcb->sctp_socket);
+ sowwakeup(stcb->sctp_socket);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if (!so_locked) {
+ SCTP_SOCKET_UNLOCK(so, 1);
}
+#endif
}
static void
@@ -2906,7 +2731,8 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
struct sctp_paddr_change *spc;
struct sctp_queued_to_read *control;
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
+ if ((stcb == NULL) ||
+ sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
/* event not enabled */
return;
}
@@ -2919,9 +2745,11 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
spc->spc_flags = 0;
spc->spc_length = sizeof(struct sctp_paddr_change);
switch (sa->sa_family) {
+#ifdef INET
case AF_INET:
memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
break;
+#endif
#ifdef INET6
case AF_INET6:
{
@@ -2955,7 +2783,7 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
m_notify);
if (control == NULL) {
/* no memory */
@@ -2975,7 +2803,7 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
static void
-sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
+sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
struct sctp_tmit_chunk *chk, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -2984,38 +2812,68 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
{
struct mbuf *m_notify;
struct sctp_send_failed *ssf;
+ struct sctp_send_failed_event *ssfe;
struct sctp_queued_to_read *control;
int length;
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVSENDFAILEVNT)) {
+ if ((stcb == NULL) ||
+ (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
+ sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
/* event not enabled */
return;
}
- m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_send_failed), 0, M_DONTWAIT, 1, MT_DATA);
+ if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
+ length = sizeof(struct sctp_send_failed_event);
+ } else {
+ length = sizeof(struct sctp_send_failed);
+ }
+ m_notify = sctp_get_mbuf_for_msg(length, 0, M_DONTWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
return;
- length = sizeof(struct sctp_send_failed) + chk->send_size;
+ length += chk->send_size;
length -= sizeof(struct sctp_data_chunk);
SCTP_BUF_LEN(m_notify) = 0;
- ssf = mtod(m_notify, struct sctp_send_failed *);
- ssf->ssf_type = SCTP_SEND_FAILED;
- if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
- ssf->ssf_flags = SCTP_DATA_UNSENT;
- else
- ssf->ssf_flags = SCTP_DATA_SENT;
- ssf->ssf_length = length;
- ssf->ssf_error = error;
- /* not exactly what the user sent in, but should be close :) */
- bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
- ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
- ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
- ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
- ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
- ssf->ssf_info.sinfo_context = chk->rec.data.context;
- ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
- ssf->ssf_assoc_id = sctp_get_associd(stcb);
-
+ if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
+ ssfe = mtod(m_notify, struct sctp_send_failed_event *);
+ ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
+ if (sent) {
+ ssfe->ssfe_flags = SCTP_DATA_SENT;
+ } else {
+ ssfe->ssfe_flags = SCTP_DATA_UNSENT;
+ }
+ ssfe->ssfe_length = length;
+ ssfe->ssfe_error = error;
+ /* not exactly what the user sent in, but should be close :) */
+ bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info));
+ ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number;
+ ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags;
+ ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype;
+ ssfe->ssfe_info.snd_context = chk->rec.data.context;
+ ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
+ ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
+ SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
+ } else {
+ ssf = mtod(m_notify, struct sctp_send_failed *);
+ ssf->ssf_type = SCTP_SEND_FAILED;
+ if (sent) {
+ ssf->ssf_flags = SCTP_DATA_SENT;
+ } else {
+ ssf->ssf_flags = SCTP_DATA_UNSENT;
+ }
+ ssf->ssf_length = length;
+ ssf->ssf_error = error;
+ /* not exactly what the user sent in, but should be close :) */
+ bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
+ ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
+ ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
+ ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
+ ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
+ ssf->ssf_info.sinfo_context = chk->rec.data.context;
+ ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
+ ssf->ssf_assoc_id = sctp_get_associd(stcb);
+ SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
+ }
if (chk->data) {
/*
* trim off the sctp chunk header(it should be there)
@@ -3027,7 +2885,6 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
}
}
SCTP_BUF_NEXT(m_notify) = chk->data;
- SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
/* Steal off the mbuf */
chk->data = NULL;
/*
@@ -3041,7 +2898,7 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
}
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
m_notify);
if (control == NULL) {
/* no memory */
@@ -3067,42 +2924,69 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
{
struct mbuf *m_notify;
struct sctp_send_failed *ssf;
+ struct sctp_send_failed_event *ssfe;
struct sctp_queued_to_read *control;
int length;
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVSENDFAILEVNT)) {
+ if ((stcb == NULL) ||
+ (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
+ sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
/* event not enabled */
return;
}
- length = sizeof(struct sctp_send_failed) + sp->length;
- m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_send_failed), 0, M_DONTWAIT, 1, MT_DATA);
- if (m_notify == NULL)
+ if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
+ length = sizeof(struct sctp_send_failed_event);
+ } else {
+ length = sizeof(struct sctp_send_failed);
+ }
+ m_notify = sctp_get_mbuf_for_msg(length, 0, M_DONTWAIT, 1, MT_DATA);
+ if (m_notify == NULL) {
/* no space left */
return;
+ }
+ length += sp->length;
SCTP_BUF_LEN(m_notify) = 0;
- ssf = mtod(m_notify, struct sctp_send_failed *);
- ssf->ssf_type = SCTP_SEND_FAILED;
- if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
- ssf->ssf_flags = SCTP_DATA_UNSENT;
- else
- ssf->ssf_flags = SCTP_DATA_SENT;
- ssf->ssf_length = length;
- ssf->ssf_error = error;
- /* not exactly what the user sent in, but should be close :) */
- bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
- ssf->ssf_info.sinfo_stream = sp->stream;
- ssf->ssf_info.sinfo_ssn = sp->strseq;
- if (sp->some_taken) {
- ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG;
+ if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
+ ssfe = mtod(m_notify, struct sctp_send_failed_event *);
+ ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
+ ssfe->ssfe_flags = SCTP_DATA_UNSENT;
+ ssfe->ssfe_length = length;
+ ssfe->ssfe_error = error;
+ /* not exactly what the user sent in, but should be close :) */
+ bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info));
+ ssfe->ssfe_info.snd_sid = sp->stream;
+ if (sp->some_taken) {
+ ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG;
+ } else {
+ ssfe->ssfe_info.snd_flags = SCTP_DATA_NOT_FRAG;
+ }
+ ssfe->ssfe_info.snd_ppid = sp->ppid;
+ ssfe->ssfe_info.snd_context = sp->context;
+ ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
+ ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
+ SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
} else {
- ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG;
+ ssf = mtod(m_notify, struct sctp_send_failed *);
+ ssf->ssf_type = SCTP_SEND_FAILED;
+ ssf->ssf_flags = SCTP_DATA_UNSENT;
+ ssf->ssf_length = length;
+ ssf->ssf_error = error;
+ /* not exactly what the user sent in, but should be close :) */
+ bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
+ ssf->ssf_info.sinfo_stream = sp->stream;
+ ssf->ssf_info.sinfo_ssn = 0;
+ if (sp->some_taken) {
+ ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG;
+ } else {
+ ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG;
+ }
+ ssf->ssf_info.sinfo_ppid = sp->ppid;
+ ssf->ssf_info.sinfo_context = sp->context;
+ ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
+ ssf->ssf_assoc_id = sctp_get_associd(stcb);
+ SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
}
- ssf->ssf_info.sinfo_ppid = sp->ppid;
- ssf->ssf_info.sinfo_context = sp->context;
- ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
- ssf->ssf_assoc_id = sctp_get_associd(stcb);
SCTP_BUF_NEXT(m_notify) = sp->data;
- SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
/* Steal off the mbuf */
sp->data = NULL;
@@ -3117,7 +3001,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
}
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
m_notify);
if (control == NULL) {
/* no memory */
@@ -3133,14 +3017,14 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
static void
-sctp_notify_adaptation_layer(struct sctp_tcb *stcb,
- uint32_t error)
+sctp_notify_adaptation_layer(struct sctp_tcb *stcb)
{
struct mbuf *m_notify;
struct sctp_adaptation_event *sai;
struct sctp_queued_to_read *control;
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
+ if ((stcb == NULL) ||
+ sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
/* event not enabled */
return;
}
@@ -3161,7 +3045,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb,
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
m_notify);
if (control == NULL) {
/* no memory */
@@ -3191,7 +3075,8 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
struct sctp_queued_to_read *control;
struct sockbuf *sb;
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_PDAPIEVNT)) {
+ if ((stcb == NULL) ||
+ sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) {
/* event not enabled */
return;
}
@@ -3215,7 +3100,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event);
SCTP_BUF_NEXT(m_notify) = NULL;
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
m_notify);
if (control == NULL) {
/* no memory */
@@ -3246,7 +3131,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
}
if (stcb->sctp_ep && stcb->sctp_socket) {
/* This should always be the case */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
@@ -3263,7 +3148,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
}
#endif
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
@@ -3285,7 +3170,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
/* mark socket closed for read/write and wakeup! */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
@@ -3300,11 +3185,11 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
}
#endif
socantsendmore(stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) {
+ if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) {
/* event not enabled */
return;
}
@@ -3323,7 +3208,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
m_notify);
if (control == NULL) {
/* no memory */
@@ -3351,7 +3236,8 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb,
struct sctp_sender_dry_event *event;
struct sctp_queued_to_read *control;
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_DRYEVNT)) {
+ if ((stcb == NULL) ||
+ sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) {
/* event not enabled */
return;
}
@@ -3372,7 +3258,8 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb,
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0, m_notify);
+ 0, 0, stcb->asoc.context, 0, 0, 0,
+ m_notify);
if (control == NULL) {
/* no memory */
sctp_m_freem(m_notify);
@@ -3387,36 +3274,99 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb,
}
-static void
-sctp_notify_stream_reset_add(struct sctp_tcb *stcb, int number_entries, int flag)
+void
+sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t numberout, int flag)
{
struct mbuf *m_notify;
struct sctp_queued_to_read *control;
- struct sctp_stream_reset_event *strreset;
+ struct sctp_stream_change_event *stradd;
int len;
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_STREAM_RESETEVNT)) {
+ if ((stcb == NULL) ||
+ (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) {
/* event not enabled */
return;
}
+ if ((stcb->asoc.peer_req_out) && flag) {
+ /* Peer made the request, don't tell the local user */
+ stcb->asoc.peer_req_out = 0;
+ return;
+ }
+ stcb->asoc.peer_req_out = 0;
m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
return;
SCTP_BUF_LEN(m_notify) = 0;
- len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t));
+ len = sizeof(struct sctp_stream_change_event);
if (len > M_TRAILINGSPACE(m_notify)) {
/* never enough room */
sctp_m_freem(m_notify);
return;
}
- strreset = mtod(m_notify, struct sctp_stream_reset_event *);
- strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
- strreset->strreset_flags = SCTP_STRRESET_ADD_STREAM | flag;
- strreset->strreset_length = len;
- strreset->strreset_assoc_id = sctp_get_associd(stcb);
- strreset->strreset_list[0] = number_entries;
+ stradd = mtod(m_notify, struct sctp_stream_change_event *);
+ stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT;
+ stradd->strchange_flags = flag;
+ stradd->strchange_length = len;
+ stradd->strchange_assoc_id = sctp_get_associd(stcb);
+ stradd->strchange_instrms = numberin;
+ stradd->strchange_outstrms = numberout;
+ SCTP_BUF_LEN(m_notify) = len;
+ SCTP_BUF_NEXT(m_notify) = NULL;
+ if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
+ /* no space */
+ sctp_m_freem(m_notify);
+ return;
+ }
+ /* append to socket */
+ control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
+ m_notify);
+ if (control == NULL) {
+ /* no memory */
+ sctp_m_freem(m_notify);
+ return;
+ }
+ control->spec_flags = M_NOTIFICATION;
+ control->length = SCTP_BUF_LEN(m_notify);
+ /* not that we need this */
+ control->tail_mbuf = m_notify;
+ sctp_add_to_readq(stcb->sctp_ep, stcb,
+ control,
+ &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
+}
+void
+sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32_t recv_tsn, int flag)
+{
+ struct mbuf *m_notify;
+ struct sctp_queued_to_read *control;
+ struct sctp_assoc_reset_event *strasoc;
+ int len;
+
+ if ((stcb == NULL) ||
+ (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) {
+ /* event not enabled */
+ return;
+ }
+ m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
+ if (m_notify == NULL)
+ /* no space left */
+ return;
+ SCTP_BUF_LEN(m_notify) = 0;
+ len = sizeof(struct sctp_assoc_reset_event);
+ if (len > M_TRAILINGSPACE(m_notify)) {
+ /* never enough room */
+ sctp_m_freem(m_notify);
+ return;
+ }
+ strasoc = mtod(m_notify, struct sctp_assoc_reset_event *);
+ strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT;
+ strasoc->assocreset_flags = flag;
+ strasoc->assocreset_length = len;
+ strasoc->assocreset_assoc_id = sctp_get_associd(stcb);
+ strasoc->assocreset_local_tsn = sending_tsn;
+ strasoc->assocreset_remote_tsn = recv_tsn;
SCTP_BUF_LEN(m_notify) = len;
SCTP_BUF_NEXT(m_notify) = NULL;
if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
@@ -3426,7 +3376,7 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, int number_entries, int flag
}
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
m_notify);
if (control == NULL) {
/* no memory */
@@ -3443,6 +3393,7 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, int number_entries, int flag
}
+
static void
sctp_notify_stream_reset(struct sctp_tcb *stcb,
int number_entries, uint16_t * list, int flag)
@@ -3452,7 +3403,8 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
struct sctp_stream_reset_event *strreset;
int len;
- if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_STREAM_RESETEVNT)) {
+ if ((stcb == NULL) ||
+ (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT))) {
/* event not enabled */
return;
}
@@ -3469,18 +3421,14 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
}
strreset = mtod(m_notify, struct sctp_stream_reset_event *);
strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
- if (number_entries == 0) {
- strreset->strreset_flags = flag | SCTP_STRRESET_ALL_STREAMS;
- } else {
- strreset->strreset_flags = flag | SCTP_STRRESET_STREAM_LIST;
- }
+ strreset->strreset_flags = flag;
strreset->strreset_length = len;
strreset->strreset_assoc_id = sctp_get_associd(stcb);
if (number_entries) {
int i;
for (i = 0; i < number_entries; i++) {
- strreset->strreset_list[i] = ntohs(list[i]);
+ strreset->strreset_stream_list[i] = ntohs(list[i]);
}
}
SCTP_BUF_LEN(m_notify) = len;
@@ -3492,7 +3440,7 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
}
/* append to socket */
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
- 0, 0, 0, 0, 0, 0,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
m_notify);
if (control == NULL) {
/* no memory */
@@ -3509,6 +3457,63 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
}
+static void
+sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_error_chunk *chunk)
+{
+ struct mbuf *m_notify;
+ struct sctp_remote_error *sre;
+ struct sctp_queued_to_read *control;
+ size_t notif_len, chunk_len;
+
+ if ((stcb == NULL) ||
+ sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) {
+ return;
+ }
+ if (chunk != NULL) {
+ chunk_len = htons(chunk->ch.chunk_length);
+ } else {
+ chunk_len = 0;
+ }
+ notif_len = sizeof(struct sctp_remote_error) + chunk_len;
+ m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
+ if (m_notify == NULL) {
+ /* Retry with smaller value. */
+ notif_len = sizeof(struct sctp_remote_error);
+ m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
+ if (m_notify == NULL) {
+ return;
+ }
+ }
+ SCTP_BUF_NEXT(m_notify) = NULL;
+ sre = mtod(m_notify, struct sctp_remote_error *);
+ sre->sre_type = SCTP_REMOTE_ERROR;
+ sre->sre_flags = 0;
+ sre->sre_length = sizeof(struct sctp_remote_error);
+ sre->sre_error = error;
+ sre->sre_assoc_id = sctp_get_associd(stcb);
+ if (notif_len > sizeof(struct sctp_remote_error)) {
+ memcpy(sre->sre_data, chunk, chunk_len);
+ sre->sre_length += chunk_len;
+ }
+ SCTP_BUF_LEN(m_notify) = sre->sre_length;
+ control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
+ 0, 0, stcb->asoc.context, 0, 0, 0,
+ m_notify);
+ if (control != NULL) {
+ control->length = SCTP_BUF_LEN(m_notify);
+ /* not that we need this */
+ control->tail_mbuf = m_notify;
+ control->spec_flags = M_NOTIFICATION;
+ sctp_add_to_readq(stcb->sctp_ep, stcb,
+ control,
+ &stcb->sctp_socket->so_rcv, 1,
+ SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
+ } else {
+ sctp_m_freem(m_notify);
+ }
+}
+
+
void
sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
uint32_t error, void *data, int so_locked
@@ -3539,11 +3544,11 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
switch (notification) {
case SCTP_NOTIFY_ASSOC_UP:
if (stcb->asoc.assoc_up_sent == 0) {
- sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, so_locked);
+ sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, 0, so_locked);
stcb->asoc.assoc_up_sent = 1;
}
if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) {
- sctp_notify_adaptation_layer(stcb, error);
+ sctp_notify_adaptation_layer(stcb);
}
if (stcb->asoc.peer_supports_auth == 0) {
sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
@@ -3551,7 +3556,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
}
break;
case SCTP_NOTIFY_ASSOC_DOWN:
- sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, so_locked);
+ sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 0, so_locked);
break;
case SCTP_NOTIFY_INTERFACE_DOWN:
{
@@ -3584,8 +3589,12 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
sctp_notify_send_failed2(stcb, error,
(struct sctp_stream_queue_pending *)data, so_locked);
break;
- case SCTP_NOTIFY_DG_FAIL:
- sctp_notify_send_failed(stcb, error,
+ case SCTP_NOTIFY_SENT_DG_FAIL:
+ sctp_notify_send_failed(stcb, 1, error,
+ (struct sctp_tmit_chunk *)data, so_locked);
+ break;
+ case SCTP_NOTIFY_UNSENT_DG_FAIL:
+ sctp_notify_send_failed(stcb, 0, error,
(struct sctp_tmit_chunk *)data, so_locked);
break;
case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
@@ -3597,50 +3606,50 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
sctp_notify_partial_delivery_indication(stcb, error, val, so_locked);
break;
}
- case SCTP_NOTIFY_STRDATA_ERR:
- break;
- case SCTP_NOTIFY_ASSOC_ABORTED:
+ case SCTP_NOTIFY_ASSOC_LOC_ABORTED:
if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED))) {
- sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, NULL, so_locked);
+ sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked);
} else {
- sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, NULL, so_locked);
+ sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked);
}
break;
- case SCTP_NOTIFY_PEER_OPENED_STREAM:
- break;
- case SCTP_NOTIFY_STREAM_OPENED_OK:
+ case SCTP_NOTIFY_ASSOC_REM_ABORTED:
+ if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
+ ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED))) {
+ sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked);
+ } else {
+ sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked);
+ }
break;
case SCTP_NOTIFY_ASSOC_RESTART:
- sctp_notify_assoc_change(SCTP_RESTART, stcb, error, data, so_locked);
+ sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked);
if (stcb->asoc.peer_supports_auth == 0) {
sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
NULL, so_locked);
}
break;
- case SCTP_NOTIFY_HB_RESP:
- break;
- case SCTP_NOTIFY_STR_RESET_INSTREAM_ADD_OK:
- sctp_notify_stream_reset_add(stcb, error, SCTP_STRRESET_INBOUND_STR);
- break;
- case SCTP_NOTIFY_STR_RESET_ADD_OK:
- sctp_notify_stream_reset_add(stcb, error, SCTP_STRRESET_OUTBOUND_STR);
- break;
- case SCTP_NOTIFY_STR_RESET_ADD_FAIL:
- sctp_notify_stream_reset_add(stcb, error, (SCTP_STRRESET_FAILED | SCTP_STRRESET_OUTBOUND_STR));
- break;
-
case SCTP_NOTIFY_STR_RESET_SEND:
- sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STRRESET_OUTBOUND_STR);
+ sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_OUTGOING_SSN);
break;
case SCTP_NOTIFY_STR_RESET_RECV:
- sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STRRESET_INBOUND_STR);
+ sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_INCOMING);
break;
case SCTP_NOTIFY_STR_RESET_FAILED_OUT:
- sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), (SCTP_STRRESET_OUTBOUND_STR | SCTP_STRRESET_FAILED));
+ sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
+ (SCTP_STREAM_RESET_OUTGOING_SSN | SCTP_STREAM_RESET_FAILED));
+ break;
+ case SCTP_NOTIFY_STR_RESET_DENIED_OUT:
+ sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
+ (SCTP_STREAM_RESET_OUTGOING_SSN | SCTP_STREAM_RESET_DENIED));
break;
case SCTP_NOTIFY_STR_RESET_FAILED_IN:
- sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), (SCTP_STRRESET_INBOUND_STR | SCTP_STRRESET_FAILED));
+ sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
+ (SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_FAILED));
+ break;
+ case SCTP_NOTIFY_STR_RESET_DENIED_IN:
+ sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
+ (SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_DENIED));
break;
case SCTP_NOTIFY_ASCONF_ADD_IP:
sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
@@ -3654,15 +3663,11 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
error);
break;
- case SCTP_NOTIFY_ASCONF_SUCCESS:
- break;
- case SCTP_NOTIFY_ASCONF_FAILED:
- break;
case SCTP_NOTIFY_PEER_SHUTDOWN:
sctp_notify_shutdown_event(stcb);
break;
case SCTP_NOTIFY_AUTH_NEW_KEY:
- sctp_notify_authentication(stcb, SCTP_AUTH_NEWKEY, error,
+ sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error,
(uint16_t) (uintptr_t) data,
so_locked);
break;
@@ -3679,6 +3684,9 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
case SCTP_NOTIFY_SENDER_DRY:
sctp_notify_sender_dry_event(stcb, so_locked);
break;
+ case SCTP_NOTIFY_REMOTE_ERROR:
+ sctp_notify_remote_error(stcb, error, data);
+ break;
default:
SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n",
__FUNCTION__, notification, notification);
@@ -3687,7 +3695,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
}
void
-sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
+sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
@@ -3695,22 +3703,21 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
{
struct sctp_association *asoc;
struct sctp_stream_out *outs;
- struct sctp_tmit_chunk *chk;
- struct sctp_stream_queue_pending *sp;
+ struct sctp_tmit_chunk *chk, *nchk;
+ struct sctp_stream_queue_pending *sp, *nsp;
int i;
- asoc = &stcb->asoc;
-
if (stcb == NULL) {
return;
}
- if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ asoc = &stcb->asoc;
+ if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
/* already being freed */
return;
}
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
- (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
+ (asoc->state & SCTP_STATE_CLOSED_SOCKET)) {
return;
}
/* now through all the gunk freeing chunks */
@@ -3718,61 +3725,70 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
SCTP_TCB_SEND_LOCK(stcb);
}
/* sent queue SHOULD be empty */
- if (!TAILQ_EMPTY(&asoc->sent_queue)) {
- chk = TAILQ_FIRST(&asoc->sent_queue);
- while (chk) {
- TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
- asoc->sent_queue_cnt--;
- if (chk->data != NULL) {
- sctp_free_bufspace(stcb, asoc, chk, 1);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
+ TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
+ TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
+ asoc->sent_queue_cnt--;
+ if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
+ if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
+#endif
+ }
+ }
+ if (chk->data != NULL) {
+ sctp_free_bufspace(stcb, asoc, chk, 1);
+ sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb,
+ error, chk, so_locked);
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
- sctp_free_a_chunk(stcb, chk);
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->sent_queue);
}
+ sctp_free_a_chunk(stcb, chk, so_locked);
+ /* sa_ignore FREED_MEMORY */
}
/* pending send queue SHOULD be empty */
- if (!TAILQ_EMPTY(&asoc->send_queue)) {
- chk = TAILQ_FIRST(&asoc->send_queue);
- while (chk) {
- TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
- asoc->send_queue_cnt--;
- if (chk->data != NULL) {
- sctp_free_bufspace(stcb, asoc, chk, 1);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_UNSENT, chk, so_locked);
- if (chk->data) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
+ TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
+ TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
+ asoc->send_queue_cnt--;
+ if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
+ asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
+#ifdef INVARIANTS
+ } else {
+ panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
+#endif
+ }
+ if (chk->data != NULL) {
+ sctp_free_bufspace(stcb, asoc, chk, 1);
+ sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb,
+ error, chk, so_locked);
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
}
- sctp_free_a_chunk(stcb, chk);
- /* sa_ignore FREED_MEMORY */
- chk = TAILQ_FIRST(&asoc->send_queue);
}
+ sctp_free_a_chunk(stcb, chk, so_locked);
+ /* sa_ignore FREED_MEMORY */
}
- for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ for (i = 0; i < asoc->streamoutcnt; i++) {
/* For each stream */
- outs = &stcb->asoc.strmout[i];
+ outs = &asoc->strmout[i];
/* clean up any sends there */
- stcb->asoc.locked_on_sending = NULL;
- sp = TAILQ_FIRST(&outs->outqueue);
- while (sp) {
- stcb->asoc.stream_queue_cnt--;
+ asoc->locked_on_sending = NULL;
+ TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
+ asoc->stream_queue_cnt--;
TAILQ_REMOVE(&outs->outqueue, sp, next);
sctp_free_spbufspace(stcb, asoc, sp);
if (sp->data) {
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_UNSENT, (void *)sp, so_locked);
+ error, (void *)sp, so_locked);
if (sp->data) {
sctp_m_freem(sp->data);
sp->data = NULL;
+ sp->tail_mbuf = NULL;
+ sp->length = 0;
}
}
if (sp->net) {
@@ -3780,9 +3796,8 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
sp->net = NULL;
}
/* Free the chunk */
- sctp_free_a_strmoq(stcb, sp);
+ sctp_free_a_strmoq(stcb, sp, so_locked);
/* sa_ignore FREED_MEMORY */
- sp = TAILQ_FIRST(&outs->outqueue);
}
}
@@ -3792,39 +3807,46 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
}
void
-sctp_abort_notification(struct sctp_tcb *stcb, int error, int so_locked
+sctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error,
+ struct sctp_abort_chunk *abort, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
-
if (stcb == NULL) {
return;
}
+ if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
+ (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
+ stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
+ }
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
return;
}
/* Tell them we lost the asoc */
- sctp_report_all_outbound(stcb, 1, so_locked);
- if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
- ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
- (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
- stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
+ sctp_report_all_outbound(stcb, error, 1, so_locked);
+ if (from_peer) {
+ sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
+ } else {
+ sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, error, abort, so_locked);
}
- sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL, so_locked);
}
void
sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct mbuf *m, int iphlen, struct sctphdr *sh, struct mbuf *op_err,
+ struct mbuf *m, int iphlen,
+ struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh, struct mbuf *op_err,
+ uint8_t use_mflowid, uint32_t mflowid,
uint32_t vrf_id, uint16_t port)
{
uint32_t vtag;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
@@ -3833,15 +3855,17 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (stcb != NULL) {
/* We have a TCB to abort, send notification too */
vtag = stcb->asoc.peer_vtag;
- sctp_abort_notification(stcb, 0, SCTP_SO_NOT_LOCKED);
+ sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
/* get the assoc vrf id and table id */
vrf_id = stcb->asoc.vrf_id;
stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
}
- sctp_send_abort(m, iphlen, sh, vtag, op_err, vrf_id, port);
+ sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err,
+ use_mflowid, mflowid,
+ vrf_id, port);
if (stcb != NULL) {
/* Ok, now lets free it */
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -3855,7 +3879,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_4);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
@@ -3927,21 +3951,19 @@ none_in:
void
sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- int error, struct mbuf *op_err,
+ struct mbuf *op_err,
int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
- uint32_t vtag;
-
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
#endif
if (stcb == NULL) {
@@ -3956,14 +3978,11 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
} else {
stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
}
- vtag = stcb->asoc.peer_vtag;
/* notify the ulp */
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)
- sctp_abort_notification(stcb, error, so_locked);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
+ sctp_abort_notification(stcb, 0, 0, NULL, so_locked);
+ }
/* notify the peer */
-#if defined(SCTP_PANIC_ON_ABORT)
- panic("aborting an association");
-#endif
sctp_send_abort_tcb(stcb, op_err, so_locked);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
@@ -3974,7 +3993,7 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
#ifdef SCTP_ASOCLOG_OF_TSNS
sctp_print_out_track_log(stcb);
#endif
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -3984,7 +4003,7 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_5);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
@@ -3992,11 +4011,15 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
void
-sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
- struct sctp_inpcb *inp, struct mbuf *op_err, uint32_t vrf_id, uint16_t port)
+sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
+ struct sockaddr *src, struct sockaddr *dst,
+ struct sctphdr *sh, struct sctp_inpcb *inp,
+ uint8_t use_mflowid, uint32_t mflowid,
+ uint32_t vrf_id, uint16_t port)
{
struct sctp_chunkhdr *ch, chunk_buf;
unsigned int chk_length;
+ int contains_init_chunk;
SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue);
/* Generate a TO address for future reference */
@@ -4006,6 +4029,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
SCTP_CALLED_DIRECTLY_NOCMPSET);
}
}
+ contains_init_chunk = 0;
ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
sizeof(*ch), (uint8_t *) & chunk_buf);
while (ch != NULL) {
@@ -4015,6 +4039,9 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
break;
}
switch (ch->chunk_type) {
+ case SCTP_INIT:
+ contains_init_chunk = 1;
+ break;
case SCTP_COOKIE_ECHO:
/* We hit here only if the assoc is being freed */
return;
@@ -4031,7 +4058,9 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
*/
return;
case SCTP_SHUTDOWN_ACK:
- sctp_send_shutdown_complete2(m, iphlen, sh, vrf_id, port);
+ sctp_send_shutdown_complete2(src, dst, sh,
+ use_mflowid, mflowid,
+ vrf_id, port);
return;
default:
break;
@@ -4040,7 +4069,13 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
sizeof(*ch), (uint8_t *) & chunk_buf);
}
- sctp_send_abort(m, iphlen, sh, 0, op_err, vrf_id, port);
+ if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
+ ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
+ (contains_init_chunk == 0))) {
+ sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL,
+ use_mflowid, mflowid,
+ vrf_id, port);
+ }
}
/*
@@ -4170,6 +4205,7 @@ sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2)
sin6_2));
}
#endif
+#ifdef INET
case AF_INET:
{
/* IPv4 addresses */
@@ -4179,6 +4215,7 @@ sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2)
sin_2 = (struct sockaddr_in *)sa2;
return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
}
+#endif
default:
/* we don't do these... */
return (0);
@@ -4191,7 +4228,6 @@ sctp_print_address(struct sockaddr *sa)
#ifdef INET6
char ip6buf[INET6_ADDRSTRLEN];
- ip6buf[0] = 0;
#endif
switch (sa->sa_family) {
@@ -4208,6 +4244,7 @@ sctp_print_address(struct sockaddr *sa)
break;
}
#endif
+#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin;
@@ -4219,62 +4256,9 @@ sctp_print_address(struct sockaddr *sa)
p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
break;
}
- default:
- SCTP_PRINTF("?\n");
- break;
- }
-}
-
-void
-sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
-{
- switch (iph->ip_v) {
- case IPVERSION:
- {
- struct sockaddr_in lsa, fsa;
-
- bzero(&lsa, sizeof(lsa));
- lsa.sin_len = sizeof(lsa);
- lsa.sin_family = AF_INET;
- lsa.sin_addr = iph->ip_src;
- lsa.sin_port = sh->src_port;
- bzero(&fsa, sizeof(fsa));
- fsa.sin_len = sizeof(fsa);
- fsa.sin_family = AF_INET;
- fsa.sin_addr = iph->ip_dst;
- fsa.sin_port = sh->dest_port;
- SCTP_PRINTF("src: ");
- sctp_print_address((struct sockaddr *)&lsa);
- SCTP_PRINTF("dest: ");
- sctp_print_address((struct sockaddr *)&fsa);
- break;
- }
-#ifdef INET6
- case IPV6_VERSION >> 4:
- {
- struct ip6_hdr *ip6;
- struct sockaddr_in6 lsa6, fsa6;
-
- ip6 = (struct ip6_hdr *)iph;
- bzero(&lsa6, sizeof(lsa6));
- lsa6.sin6_len = sizeof(lsa6);
- lsa6.sin6_family = AF_INET6;
- lsa6.sin6_addr = ip6->ip6_src;
- lsa6.sin6_port = sh->src_port;
- bzero(&fsa6, sizeof(fsa6));
- fsa6.sin6_len = sizeof(fsa6);
- fsa6.sin6_family = AF_INET6;
- fsa6.sin6_addr = ip6->ip6_dst;
- fsa6.sin6_port = sh->dest_port;
- SCTP_PRINTF("src: ");
- sctp_print_address((struct sockaddr *)&lsa6);
- SCTP_PRINTF("dest: ");
- sctp_print_address((struct sockaddr *)&fsa6);
- break;
- }
#endif
default:
- /* TSNH */
+ SCTP_PRINTF("?\n");
break;
}
}
@@ -4313,10 +4297,8 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
}
/* lock the socket buffers */
SCTP_INP_READ_LOCK(old_inp);
- control = TAILQ_FIRST(&old_inp->read_queue);
- /* Pull off all for out target stcb */
- while (control) {
- nctl = TAILQ_NEXT(control, next);
+ TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) {
+ /* Pull off all for out target stcb */
if (control->stcb == stcb) {
/* remove it we want it */
TAILQ_REMOVE(&old_inp->read_queue, control, next);
@@ -4333,17 +4315,14 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
m = SCTP_BUF_NEXT(m);
}
}
- control = nctl;
}
SCTP_INP_READ_UNLOCK(old_inp);
/* Remove the sb-lock on the old socket */
sbunlock(&old_so->so_rcv);
/* Now we move them over to the new socket buffer */
- control = TAILQ_FIRST(&tmp_queue);
SCTP_INP_READ_LOCK(new_inp);
- while (control) {
- nctl = TAILQ_NEXT(control, next);
+ TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) {
TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next);
m = control->data;
while (m) {
@@ -4356,7 +4335,6 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
}
m = SCTP_BUF_NEXT(m);
}
- control = nctl;
}
SCTP_INP_READ_UNLOCK(new_inp);
}
@@ -4457,16 +4435,20 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
} else {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(inp);
if (!so_locked) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
+ if (stcb) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ }
SCTP_SOCKET_LOCK(so, 1);
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ }
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
SCTP_SOCKET_UNLOCK(so, 1);
return;
@@ -4474,7 +4456,7 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
}
#endif
sctp_sorwakeup(inp, inp->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
@@ -4517,7 +4499,7 @@ get_out:
}
if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) {
SCTP_INP_READ_UNLOCK(inp);
- return 0;
+ return (0);
}
if (control->end_added) {
/* huh this one is complete? */
@@ -4607,22 +4589,26 @@ get_out:
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
} else {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(inp);
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
+ if (stcb) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ }
SCTP_SOCKET_LOCK(so, 1);
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ }
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
SCTP_SOCKET_UNLOCK(so, 1);
return (0);
}
#endif
sctp_sorwakeup(inp, inp->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
@@ -4695,14 +4681,14 @@ sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
int
sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
- int reason, int so_locked
+ uint8_t sent, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
struct sctp_stream_out *strq;
- struct sctp_tmit_chunk *chk = NULL;
+ struct sctp_tmit_chunk *chk = NULL, *tp2;
struct sctp_stream_queue_pending *sp;
uint16_t stream = 0, seq = 0;
uint8_t foundeom = 0;
@@ -4722,7 +4708,11 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
stcb->asoc.peers_rwnd += tp1->send_size;
stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
+ if (sent) {
+ sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked);
+ } else {
+ sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked);
+ }
if (tp1->data) {
sctp_m_freem(tp1->data);
tp1->data = NULL;
@@ -4756,15 +4746,11 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
* The multi-part message was scattered across the send and
* sent queue.
*/
-next_on_sent:
- tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
- /*
- * recurse throught the send_queue too, starting at the
- * beginning.
- */
- if ((tp1) &&
- (tp1->rec.data.stream_number == stream) &&
- (tp1->rec.data.stream_seq == seq)) {
+ TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) {
+ if ((tp1->rec.data.stream_number != stream) ||
+ (tp1->rec.data.stream_seq != seq)) {
+ break;
+ }
/*
* save to chk in case we have some on stream out
* queue. If so and we have an un-transmitted one we
@@ -4773,7 +4759,11 @@ next_on_sent:
chk = tp1;
ret_sz += tp1->book_size;
sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
+ if (sent) {
+ sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked);
+ } else {
+ sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked);
+ }
if (tp1->data) {
sctp_m_freem(tp1->data);
tp1->data = NULL;
@@ -4794,7 +4784,6 @@ next_on_sent:
sctp_next);
stcb->asoc.send_queue_cnt--;
stcb->asoc.sent_queue_cnt++;
- goto next_on_sent;
}
}
if (foundeom == 0) {
@@ -4802,81 +4791,73 @@ next_on_sent:
* Still no eom found. That means there is stuff left on the
* stream out queue.. yuck.
*/
- strq = &stcb->asoc.strmout[stream];
SCTP_TCB_SEND_LOCK(stcb);
+ strq = &stcb->asoc.strmout[stream];
sp = TAILQ_FIRST(&strq->outqueue);
- while (sp->strseq <= seq) {
- /* Check if its our SEQ */
- if (sp->strseq == seq) {
- sp->discard_rest = 1;
- /*
- * We may need to put a chunk on the queue
- * that holds the TSN that would have been
- * sent with the LAST bit.
- */
+ if (sp != NULL) {
+ sp->discard_rest = 1;
+ /*
+ * We may need to put a chunk on the queue that
+ * holds the TSN that would have been sent with the
+ * LAST bit.
+ */
+ if (chk == NULL) {
+ /* Yep, we have to */
+ sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
- /* Yep, we have to */
- sctp_alloc_a_chunk(stcb, chk);
- if (chk == NULL) {
- /*
- * we are hosed. All we can
- * do is nothing.. which
- * will cause an abort if
- * the peer is paying
- * attention.
- */
- goto oh_well;
- }
- memset(chk, 0, sizeof(*chk));
- chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG;
- chk->sent = SCTP_FORWARD_TSN_SKIP;
- chk->asoc = &stcb->asoc;
- chk->rec.data.stream_seq = sp->strseq;
- chk->rec.data.stream_number = sp->stream;
- chk->rec.data.payloadtype = sp->ppid;
- chk->rec.data.context = sp->context;
- chk->flags = sp->act_flags;
- if (sp->net)
- chk->whoTo = sp->net;
- else
- chk->whoTo = stcb->asoc.primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
- chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1);
- stcb->asoc.pr_sctp_cnt++;
- chk->pr_sctp_on = 1;
- TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
- stcb->asoc.sent_queue_cnt++;
- stcb->asoc.pr_sctp_cnt++;
- } else {
- chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
- }
- oh_well:
- if (sp->data) {
/*
- * Pull any data to free up the SB
- * and allow sender to "add more"
- * whilc we will throw away :-)
+ * we are hosed. All we can do is
+ * nothing.. which will cause an
+ * abort if the peer is paying
+ * attention.
*/
- sctp_free_spbufspace(stcb, &stcb->asoc,
- sp);
- ret_sz += sp->length;
- do_wakeup_routine = 1;
- sp->some_taken = 1;
- sctp_m_freem(sp->data);
- sp->length = 0;
- sp->data = NULL;
- sp->tail_mbuf = NULL;
+ goto oh_well;
}
- break;
+ memset(chk, 0, sizeof(*chk));
+ chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG;
+ chk->sent = SCTP_FORWARD_TSN_SKIP;
+ chk->asoc = &stcb->asoc;
+ chk->rec.data.stream_seq = strq->next_sequence_send;
+ chk->rec.data.stream_number = sp->stream;
+ chk->rec.data.payloadtype = sp->ppid;
+ chk->rec.data.context = sp->context;
+ chk->flags = sp->act_flags;
+ if (sp->net)
+ chk->whoTo = sp->net;
+ else
+ chk->whoTo = stcb->asoc.primary_destination;
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1);
+ stcb->asoc.pr_sctp_cnt++;
+ chk->pr_sctp_on = 1;
+ TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
+ stcb->asoc.sent_queue_cnt++;
+ stcb->asoc.pr_sctp_cnt++;
} else {
- /* Next one please */
- sp = TAILQ_NEXT(sp, next);
+ chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
+ }
+ strq->next_sequence_send++;
+ oh_well:
+ if (sp->data) {
+ /*
+ * Pull any data to free up the SB and allow
+ * sender to "add more" while we will throw
+ * away :-)
+ */
+ sctp_free_spbufspace(stcb, &stcb->asoc, sp);
+ ret_sz += sp->length;
+ do_wakeup_routine = 1;
+ sp->some_taken = 1;
+ sctp_m_freem(sp->data);
+ sp->data = NULL;
+ sp->tail_mbuf = NULL;
+ sp->length = 0;
}
- } /* End while */
+ }
SCTP_TCB_SEND_UNLOCK(stcb);
}
if (do_wakeup_routine) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
@@ -4894,7 +4875,7 @@ next_on_sent:
}
#endif
sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
@@ -4923,6 +4904,7 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
continue;
if (addr->sa_family != laddr->ifa->address.sa.sa_family)
continue;
+#ifdef INET
if (addr->sa_family == AF_INET) {
if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
laddr->ifa->address.sin.sin_addr.s_addr) {
@@ -4934,6 +4916,7 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
break;
}
}
+#endif
#ifdef INET6
if (addr->sa_family == AF_INET6) {
if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
@@ -4957,22 +4940,33 @@ sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
uint32_t
sctp_get_ifa_hash_val(struct sockaddr *addr)
{
- if (addr->sa_family == AF_INET) {
- struct sockaddr_in *sin;
+ switch (addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
- sin = (struct sockaddr_in *)addr;
- return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16));
- } else if (addr->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6;
- uint32_t hash_of_addr;
+ sin = (struct sockaddr_in *)addr;
+ return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16));
+ }
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ uint32_t hash_of_addr;
- sin6 = (struct sockaddr_in6 *)addr;
- hash_of_addr = (sin6->sin6_addr.s6_addr32[0] +
- sin6->sin6_addr.s6_addr32[1] +
- sin6->sin6_addr.s6_addr32[2] +
- sin6->sin6_addr.s6_addr32[3]);
- hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16));
- return (hash_of_addr);
+ sin6 = (struct sockaddr_in6 *)addr;
+ hash_of_addr = (sin6->sin6_addr.s6_addr32[0] +
+ sin6->sin6_addr.s6_addr32[1] +
+ sin6->sin6_addr.s6_addr32[2] +
+ sin6->sin6_addr.s6_addr32[3]);
+ hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16));
+ return (hash_of_addr);
+ }
+#endif
+ default:
+ break;
}
return (0);
}
@@ -5021,6 +5015,7 @@ stage_right:
}
if (addr->sa_family != sctp_ifap->address.sa.sa_family)
continue;
+#ifdef INET
if (addr->sa_family == AF_INET) {
if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
sctp_ifap->address.sin.sin_addr.s_addr) {
@@ -5031,6 +5026,7 @@ stage_right:
break;
}
}
+#endif
#ifdef INET6
if (addr->sa_family == AF_INET6) {
if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
@@ -5110,7 +5106,7 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t * freed_so_far, int hold_rlock,
goto out;
}
SCTP_STAT_INCR(sctps_wu_sacks_sent);
- sctp_send_sack(stcb);
+ sctp_send_sack(stcb, SCTP_SO_LOCKED);
sctp_chunk_output(stcb->sctp_ep, stcb,
SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED);
@@ -5218,10 +5214,10 @@ sctp_sorecvmsg(struct socket *so,
rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
}
error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0));
- sockbuf_lock = 1;
if (error) {
goto release_unlocked;
}
+ sockbuf_lock = 1;
restart:
@@ -5234,7 +5230,7 @@ restart_nosblocks:
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
goto out;
}
- if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) {
if (so->so_error) {
error = so->so_error;
if ((in_flags & MSG_PEEK) == 0)
@@ -5242,7 +5238,6 @@ restart_nosblocks:
goto out;
} else {
if (so->so_rcv.sb_cc == 0) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
/* indicate EOF */
error = 0;
goto out;
@@ -5267,17 +5262,6 @@ restart_nosblocks:
*/
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
error = ECONNRESET;
- /*
- * You get this once if you are
- * active open side
- */
- if (!(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- /*
- * Remove flag if on the
- * active open side
- */
- inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_ABORTED;
- }
}
so->so_state &= ~(SS_ISCONNECTING |
SS_ISDISCONNECTING |
@@ -5287,8 +5271,6 @@ restart_nosblocks:
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
- } else {
- inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
}
}
goto out;
@@ -5321,18 +5303,6 @@ restart_nosblocks:
*/
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
error = ECONNRESET;
- /*
- * You get this once if you
- * are active open side
- */
- if (!(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- /*
- * Remove flag if on
- * the active open
- * side
- */
- inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_ABORTED;
- }
}
so->so_state &= ~(SS_ISCONNECTING |
SS_ISDISCONNECTING |
@@ -5342,8 +5312,6 @@ restart_nosblocks:
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
- } else {
- inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
}
}
goto out;
@@ -5369,7 +5337,6 @@ restart_nosblocks:
*/
if (hold_rlock == 0) {
SCTP_INP_READ_LOCK(inp);
- hold_rlock = 1;
}
control = TAILQ_FIRST(&inp->read_queue);
if ((control == NULL) && (so->so_rcv.sb_cc != 0)) {
@@ -5539,7 +5506,7 @@ found_one:
#ifdef INVARIANTS
panic("refcnt already incremented");
#else
- printf("refcnt already incremented?\n");
+ SCTP_PRINTF("refcnt already incremented?\n");
#endif
} else {
atomic_add_int(&stcb->asoc.refcnt, 1);
@@ -5567,7 +5534,8 @@ found_one:
if ((sinfo) && filling_sinfo) {
memcpy(sinfo, control, sizeof(struct sctp_nonpad_sndrcvinfo));
nxt = TAILQ_NEXT(control, next);
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
+ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
+ sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) {
struct sctp_extrcvinfo *s_extra;
s_extra = (struct sctp_extrcvinfo *)sinfo;
@@ -5639,28 +5607,31 @@ found_one:
}
#endif
if (fromlen && from) {
- struct sockaddr *to;
-
+ cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sa.sa_len);
+ switch (control->whoFrom->ro._l_addr.sa.sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
+ break;
+#endif
#ifdef INET
- cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sin.sin_len);
- memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
- ((struct sockaddr_in *)from)->sin_port = control->port_from;
-#else
- /* No AF_INET use AF_INET6 */
- cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sin6.sin6_len);
- memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
- ((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
+ case AF_INET:
+ ((struct sockaddr_in *)from)->sin_port = control->port_from;
+ break;
#endif
+ default:
+ break;
+ }
+ memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
- to = from;
#if defined(INET) && defined(INET6)
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
- (to->sa_family == AF_INET) &&
+ (from->sa_family == AF_INET) &&
((size_t)fromlen >= sizeof(struct sockaddr_in6))) {
struct sockaddr_in *sin;
struct sockaddr_in6 sin6;
- sin = (struct sockaddr_in *)to;
+ sin = (struct sockaddr_in *)from;
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
@@ -5669,15 +5640,15 @@ found_one:
&sin6.sin6_addr.s6_addr32[3],
sizeof(sin6.sin6_addr.s6_addr32[3]));
sin6.sin6_port = sin->sin_port;
- memcpy(from, (caddr_t)&sin6, sizeof(sin6));
+ memcpy(from, &sin6, sizeof(struct sockaddr_in6));
}
#endif
-#if defined(INET6)
+#ifdef INET6
{
- struct sockaddr_in6 lsa6, *to6;
+ struct sockaddr_in6 lsa6, *from6;
- to6 = (struct sockaddr_in6 *)to;
- sctp_recover_scope_mac(to6, (&lsa6));
+ from6 = (struct sockaddr_in6 *)from;
+ sctp_recover_scope_mac(from6, (&lsa6));
}
#endif
}
@@ -6014,7 +5985,9 @@ wait_some_more:
}
if (control->end_added) {
out_flags |= MSG_EOR;
- if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0))
+ if ((control->do_not_ref_stcb == 0) &&
+ (control->stcb != NULL) &&
+ ((control->spec_flags & M_NOTIFICATION) == 0))
control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
}
if (control->spec_flags & M_NOTIFICATION) {
@@ -6074,7 +6047,8 @@ out:
if (((out_flags & MSG_EOR) == 0) &&
((in_flags & MSG_PEEK) == 0) &&
(sinfo) &&
- (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO))) {
+ (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
+ sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) {
struct sctp_extrcvinfo *s_extra;
s_extra = (struct sctp_extrcvinfo *)sinfo;
@@ -6082,11 +6056,9 @@ out:
}
if (hold_rlock == 1) {
SCTP_INP_READ_UNLOCK(inp);
- hold_rlock = 0;
}
if (hold_sblock) {
SOCKBUF_UNLOCK(&so->so_rcv);
- hold_sblock = 0;
}
if (sockbuf_lock) {
sbunlock(&so->so_rcv);
@@ -6107,7 +6079,6 @@ out:
#endif
}
atomic_add_int(&stcb->asoc.refcnt, -1);
- freecnt_applied = 0;
/* Save the value back for next time */
stcb->freed_by_sorcv_sincelast = freed_so_far;
}
@@ -6224,8 +6195,9 @@ sctp_soreceive(struct socket *so,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
return (EINVAL);
}
- if ((sctp_is_feature_off(inp,
- SCTP_PCB_FLAGS_RECVDATAIOEVNT)) ||
+ if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) &&
+ sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
+ sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) ||
(controlp == NULL)) {
/* user does not want the sndrcv ctl */
filling_sinfo = 0;
@@ -6261,71 +6233,6 @@ sctp_soreceive(struct socket *so,
}
-int
-sctp_l_soreceive(struct socket *so,
- struct sockaddr **name,
- struct uio *uio,
- char **controlp,
- int *controllen,
- int *flag)
-{
- int error, fromlen;
- uint8_t sockbuf[256];
- struct sockaddr *from;
- struct sctp_extrcvinfo sinfo;
- int filling_sinfo = 1;
- struct sctp_inpcb *inp;
-
- inp = (struct sctp_inpcb *)so->so_pcb;
- /* pickup the assoc we are reading from */
- if (inp == NULL) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
- return (EINVAL);
- }
- if ((sctp_is_feature_off(inp,
- SCTP_PCB_FLAGS_RECVDATAIOEVNT)) ||
- (controlp == NULL)) {
- /* user does not want the sndrcv ctl */
- filling_sinfo = 0;
- }
- if (name) {
- from = (struct sockaddr *)sockbuf;
- fromlen = sizeof(sockbuf);
- from->sa_len = 0;
- } else {
- from = NULL;
- fromlen = 0;
- }
-
- error = sctp_sorecvmsg(so, uio,
- (struct mbuf **)NULL,
- from, fromlen, flag,
- (struct sctp_sndrcvinfo *)&sinfo,
- filling_sinfo);
- if ((controlp) && (filling_sinfo)) {
- /*
- * copy back the sinfo in a CMSG format note that the caller
- * has reponsibility for freeing the memory.
- */
- if (filling_sinfo)
- *controlp = sctp_build_ctl_cchunk(inp,
- controllen,
- (struct sctp_sndrcvinfo *)&sinfo);
- }
- if (name) {
- /* copy back the address info */
- if (from && from->sa_len) {
- *name = sodupsockaddr(from, M_WAIT);
- } else {
- *name = NULL;
- }
- }
- return (error);
-}
-
-
-
-
@@ -6339,13 +6246,33 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
struct sockaddr *sa;
size_t incr = 0;
+#ifdef INET
+ struct sockaddr_in *sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+
+#endif
+
sa = addr;
inp = stcb->sctp_ep;
*error = 0;
for (i = 0; i < totaddr; i++) {
- if (sa->sa_family == AF_INET) {
+ switch (sa->sa_family) {
+#ifdef INET
+ case AF_INET:
incr = sizeof(struct sockaddr_in);
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ sin = (struct sockaddr_in *)sa;
+ if ((sin->sin_addr.s_addr == INADDR_ANY) ||
+ (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
+ *error = EINVAL;
+ goto out_now;
+ }
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
/* assoc gone no un-lock */
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
@@ -6353,9 +6280,20 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
goto out_now;
}
added++;
- } else if (sa->sa_family == AF_INET6) {
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
incr = sizeof(struct sockaddr_in6);
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
+ *error = EINVAL;
+ goto out_now;
+ }
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
/* assoc gone no un-lock */
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
@@ -6363,6 +6301,10 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
goto out_now;
}
added++;
+ break;
+#endif
+ default:
+ break;
}
sa = (struct sockaddr *)((caddr_t)sa + incr);
}
@@ -6381,10 +6323,13 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
at = incr = 0;
sa = addr;
+
*error = *num_v6 = *num_v4 = 0;
/* account and validate addresses */
for (i = 0; i < (size_t)*totaddr; i++) {
- if (sa->sa_family == AF_INET) {
+ switch (sa->sa_family) {
+#ifdef INET
+ case AF_INET:
(*num_v4) += 1;
incr = sizeof(struct sockaddr_in);
if (sa->sa_len != incr) {
@@ -6393,30 +6338,40 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
*bad_addr = 1;
return (NULL);
}
- } else if (sa->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6;
-
- sin6 = (struct sockaddr_in6 *)sa;
- if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
- /* Must be non-mapped for connectx */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
- *error = EINVAL;
- *bad_addr = 1;
- return (NULL);
- }
- (*num_v6) += 1;
- incr = sizeof(struct sockaddr_in6);
- if (sa->sa_len != incr) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
- *error = EINVAL;
- *bad_addr = 1;
- return (NULL);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ /* Must be non-mapped for connectx */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
+ *error = EINVAL;
+ *bad_addr = 1;
+ return (NULL);
+ }
+ (*num_v6) += 1;
+ incr = sizeof(struct sockaddr_in6);
+ if (sa->sa_len != incr) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
+ *error = EINVAL;
+ *bad_addr = 1;
+ return (NULL);
+ }
+ break;
}
- } else {
+#endif
+ default:
*totaddr = i;
/* we are done */
break;
}
+ if (i == (size_t)*totaddr) {
+ break;
+ }
SCTP_INP_INCR_REF(inp);
stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
if (stcb != NULL) {
@@ -6457,7 +6412,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
return;
}
addr_touse = sa;
-#if defined(INET6) && !defined(__Userspace__) /* TODO port in6_sin6_2_sin */
+#ifdef INET6
if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
@@ -6486,6 +6441,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
}
}
#endif
+#ifdef INET
if (sa->sa_family == AF_INET) {
if (sa->sa_len != sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
@@ -6500,6 +6456,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
return;
}
}
+#endif
if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
if (p == NULL) {
/* Can't get proc for Net/Open BSD */
@@ -6565,7 +6522,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
* assumes all arguments are valid/checked by caller.
*/
void
-sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
+sctp_bindx_delete_address(struct sctp_inpcb *inp,
struct sockaddr *sa, sctp_assoc_t assoc_id,
uint32_t vrf_id, int *error)
{
@@ -6583,7 +6540,7 @@ sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
return;
}
addr_touse = sa;
-#if defined(INET6) && !defined(__Userspace__) /* TODO port in6_sin6_2_sin */
+#ifdef INET6
if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
@@ -6612,6 +6569,7 @@ sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
}
}
#endif
+#ifdef INET
if (sa->sa_family == AF_INET) {
if (sa->sa_len != sizeof(struct sockaddr_in)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
@@ -6626,6 +6584,7 @@ sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
return;
}
}
+#endif
/*
* No lock required mgmt_ep_sa does its own locking. If the FIX:
* below is ever changed we may need to lock before calling
@@ -6658,20 +6617,12 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
int count = 0;
/* Turn on all the appropriate scopes */
- loopback_scope = stcb->asoc.loopback_scope;
- ipv4_local_scope = stcb->asoc.ipv4_local_scope;
- local_scope = stcb->asoc.local_scope;
- site_scope = stcb->asoc.site_scope;
- ipv4_addr_legal = ipv6_addr_legal = 0;
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- ipv6_addr_legal = 1;
- if (SCTP_IPV6_V6ONLY(stcb->sctp_ep) == 0) {
- ipv4_addr_legal = 1;
- }
- } else {
- ipv4_addr_legal = 1;
- }
-
+ loopback_scope = stcb->asoc.scope.loopback_scope;
+ ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
+ local_scope = stcb->asoc.scope.local_scope;
+ site_scope = stcb->asoc.scope.site_scope;
+ ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
+ ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
SCTP_IPI_ADDR_RLOCK();
vrf = sctp_find_vrf(stcb->asoc.vrf_id);
if (vrf == NULL) {
@@ -6692,6 +6643,7 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
if (sctp_is_addr_restricted(stcb, sctp_ifa))
continue;
switch (sctp_ifa->address.sa.sa_family) {
+#ifdef INET
case AF_INET:
if (ipv4_addr_legal) {
struct sockaddr_in *sin;
@@ -6714,6 +6666,7 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
continue;
}
break;
+#endif
#ifdef INET6
case AF_INET6:
if (ipv6_addr_legal) {
@@ -6808,170 +6761,181 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_
}
#endif
-/* We will need to add support
- * to bind the ports and such here
- * so we can do UDP tunneling. In
- * the mean-time, we return error
- */
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-#include <sys/proc.h>
-#ifdef INET6
-#include <netinet6/sctp6_var.h>
-#endif
-
static void
sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
{
struct ip *iph;
+
+#ifdef INET6
+ struct ip6_hdr *ip6;
+
+#endif
struct mbuf *sp, *last;
struct udphdr *uhdr;
- uint16_t port = 0, len;
- int header_size = sizeof(struct udphdr) + sizeof(struct sctphdr);
+ uint16_t port;
- /*
- * Split out the mbuf chain. Leave the IP header in m, place the
- * rest in the sp.
- */
if ((m->m_flags & M_PKTHDR) == 0) {
/* Can't handle one that is not a pkt hdr */
goto out;
}
- /* pull the src port */
+ /* Pull the src port */
iph = mtod(m, struct ip *);
uhdr = (struct udphdr *)((caddr_t)iph + off);
-
port = uhdr->uh_sport;
+ /*
+ * Split out the mbuf chain. Leave the IP header in m, place the
+ * rest in the sp.
+ */
sp = m_split(m, off, M_DONTWAIT);
if (sp == NULL) {
/* Gak, drop packet, we can't do a split */
goto out;
}
- if (sp->m_pkthdr.len < header_size) {
- /* Gak, packet can't have an SCTP header in it - to small */
+ if (sp->m_pkthdr.len < sizeof(struct udphdr) + sizeof(struct sctphdr)) {
+ /* Gak, packet can't have an SCTP header in it - too small */
m_freem(sp);
goto out;
}
- /* ok now pull up the UDP header and SCTP header together */
- sp = m_pullup(sp, header_size);
+ /* Now pull up the UDP header and SCTP header together */
+ sp = m_pullup(sp, sizeof(struct udphdr) + sizeof(struct sctphdr));
if (sp == NULL) {
/* Gak pullup failed */
goto out;
}
- /* trim out the UDP header */
+ /* Trim out the UDP header */
m_adj(sp, sizeof(struct udphdr));
/* Now reconstruct the mbuf chain */
- /* 1) find last one */
- last = m;
- while (last->m_next != NULL) {
- last = last->m_next;
- }
+ for (last = m; last->m_next; last = last->m_next);
last->m_next = sp;
m->m_pkthdr.len += sp->m_pkthdr.len;
- last = m;
- while (last != NULL) {
- last = last->m_next;
- }
- /* Now its ready for sctp_input or sctp6_input */
iph = mtod(m, struct ip *);
switch (iph->ip_v) {
+#ifdef INET
case IPVERSION:
- {
- /* its IPv4 */
- len = SCTP_GET_IPV4_LENGTH(iph);
- len -= sizeof(struct udphdr);
- SCTP_GET_IPV4_LENGTH(iph) = len;
- sctp_input_with_port(m, off, port);
- break;
- }
+ iph->ip_len -= sizeof(struct udphdr);
+ sctp_input_with_port(m, off, port);
+ break;
+#endif
#ifdef INET6
case IPV6_VERSION >> 4:
- {
- /* its IPv6 - NOT supported */
- goto out;
- break;
-
- }
+ ip6 = mtod(m, struct ip6_hdr *);
+ ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - sizeof(struct udphdr));
+ sctp6_input_with_port(&m, &off, port);
+ break;
#endif
default:
- {
- m_freem(m);
- break;
- }
+ goto out;
+ break;
}
return;
out:
m_freem(m);
}
-void
+void
sctp_over_udp_stop(void)
{
- struct socket *sop;
-
/*
* This function assumes sysctl caller holds sctp_sysctl_info_lock()
* for writting!
*/
- if (SCTP_BASE_INFO(udp_tun_socket) == NULL) {
- /* Nothing to do */
- return;
+#ifdef INET
+ if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
+ soclose(SCTP_BASE_INFO(udp4_tun_socket));
+ SCTP_BASE_INFO(udp4_tun_socket) = NULL;
}
- sop = SCTP_BASE_INFO(udp_tun_socket);
- soclose(sop);
- SCTP_BASE_INFO(udp_tun_socket) = NULL;
+#endif
+#ifdef INET6
+ if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
+ soclose(SCTP_BASE_INFO(udp6_tun_socket));
+ SCTP_BASE_INFO(udp6_tun_socket) = NULL;
+ }
+#endif
}
-int
+
+int
sctp_over_udp_start(void)
{
uint16_t port;
int ret;
+
+#ifdef INET
struct sockaddr_in sin;
- struct socket *sop = NULL;
- struct thread *th;
- struct ucred *cred;
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+
+#endif
/*
* This function assumes sysctl caller holds sctp_sysctl_info_lock()
* for writting!
*/
port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
- if (port == 0) {
+ if (ntohs(port) == 0) {
/* Must have a port set */
return (EINVAL);
}
- if (SCTP_BASE_INFO(udp_tun_socket) != NULL) {
+#ifdef INET
+ if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
+ /* Already running -- must stop first */
+ return (EALREADY);
+ }
+#endif
+#ifdef INET6
+ if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
/* Already running -- must stop first */
return (EALREADY);
}
- th = curthread;
- cred = th->td_ucred;
- if ((ret = socreate(PF_INET, &sop,
- SOCK_DGRAM, IPPROTO_UDP, cred, th))) {
+#endif
+#ifdef INET
+ if ((ret = socreate(PF_INET, &SCTP_BASE_INFO(udp4_tun_socket),
+ SOCK_DGRAM, IPPROTO_UDP,
+ curthread->td_ucred, curthread))) {
+ sctp_over_udp_stop();
return (ret);
}
- SCTP_BASE_INFO(udp_tun_socket) = sop;
- /* call the special UDP hook */
- ret = udp_set_kernel_tunneling(sop, sctp_recv_udp_tunneled_packet);
- if (ret) {
- goto exit_stage_left;
+ /* Call the special UDP hook. */
+ if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket),
+ sctp_recv_udp_tunneled_packet))) {
+ sctp_over_udp_stop();
+ return (ret);
}
- /* Ok we have a socket, bind it to the port */
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(sin);
+ /* Ok, we have a socket, bind it to the port. */
+ memset(&sin, 0, sizeof(struct sockaddr_in));
+ sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
- ret = sobind(sop, (struct sockaddr *)&sin, th);
- if (ret) {
- /* Close up we cant get the port */
-exit_stage_left:
+ if ((ret = sobind(SCTP_BASE_INFO(udp4_tun_socket),
+ (struct sockaddr *)&sin, curthread))) {
sctp_over_udp_stop();
return (ret);
}
- /*
- * Ok we should now get UDP packets directly to our input routine
- * sctp_recv_upd_tunneled_packet().
- */
+#endif
+#ifdef INET6
+ if ((ret = socreate(PF_INET6, &SCTP_BASE_INFO(udp6_tun_socket),
+ SOCK_DGRAM, IPPROTO_UDP,
+ curthread->td_ucred, curthread))) {
+ sctp_over_udp_stop();
+ return (ret);
+ }
+ /* Call the special UDP hook. */
+ if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket),
+ sctp_recv_udp_tunneled_packet))) {
+ sctp_over_udp_stop();
+ return (ret);
+ }
+ /* Ok, we have a socket, bind it to the port. */
+ memset(&sin6, 0, sizeof(struct sockaddr_in6));
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_port = htons(port);
+ if ((ret = sobind(SCTP_BASE_INFO(udp6_tun_socket),
+ (struct sockaddr *)&sin6, curthread))) {
+ sctp_over_udp_stop();
+ return (ret);
+ }
+#endif
return (0);
}
diff --git a/freebsd/sys/netinet/sctputil.h b/freebsd/sys/netinet/sctputil.h
index d109ec23..411bfafc 100644
--- a/freebsd/sys/netinet/sctputil.h
+++ b/freebsd/sys/netinet/sctputil.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -28,14 +30,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-/* $KAME: sctputil.h,v 1.15 2005/03/06 16:04:19 itojun Exp $ */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef __sctputil_h__
-#define __sctputil_h__
+#ifndef _NETINET_SCTP_UTIL_H_
+#define _NETINET_SCTP_UTIL_H_
#if defined(_KERNEL) || defined(__Userspace__)
@@ -86,6 +85,12 @@ int sctp_init_asoc(struct sctp_inpcb *, struct sctp_tcb *, uint32_t, uint32_t);
void sctp_fill_random_store(struct sctp_pcb *);
void
+sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin,
+ uint16_t numberout, int flag);
+void
+ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32_t recv_tsn, int flag);
+
+void
sctp_timer_start(int, struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *);
@@ -125,14 +130,14 @@ sctp_append_to_readq(struct sctp_inpcb *inp,
void sctp_iterator_worker(void);
uint32_t sctp_get_prev_mtu(uint32_t);
-uint32_t sctp_get_next_mtu(struct sctp_inpcb *, uint32_t);
+uint32_t sctp_get_next_mtu(uint32_t);
void
sctp_timeout_handler(void *);
uint32_t
sctp_calculate_rto(struct sctp_tcb *, struct sctp_association *,
- struct sctp_nets *, struct timeval *, int);
+ struct sctp_nets *, struct timeval *, int, int);
uint32_t sctp_calculate_len(struct mbuf *);
@@ -162,7 +167,7 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
void sctp_stop_timers_for_shutdown(struct sctp_tcb *);
void
-sctp_report_all_outbound(struct sctp_tcb *, int, int
+sctp_report_all_outbound(struct sctp_tcb *, uint16_t, int, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
@@ -171,7 +176,8 @@ sctp_report_all_outbound(struct sctp_tcb *, int, int
int sctp_expand_mapping_array(struct sctp_association *, uint32_t);
void
-sctp_abort_notification(struct sctp_tcb *, int, int
+sctp_abort_notification(struct sctp_tcb *, uint8_t, uint16_t,
+ struct sctp_abort_chunk *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
@@ -179,13 +185,16 @@ sctp_abort_notification(struct sctp_tcb *, int, int
/* We abort responding to an IP packet for some reason */
void
-sctp_abort_association(struct sctp_inpcb *, struct sctp_tcb *,
- struct mbuf *, int, struct sctphdr *, struct mbuf *, uint32_t, uint16_t);
+sctp_abort_association(struct sctp_inpcb *, struct sctp_tcb *, struct mbuf *,
+ int, struct sockaddr *, struct sockaddr *,
+ struct sctphdr *, struct mbuf *,
+ uint8_t, uint32_t,
+ uint32_t, uint16_t);
/* We choose to abort via user input */
void
-sctp_abort_an_association(struct sctp_inpcb *, struct sctp_tcb *, int,
+sctp_abort_an_association(struct sctp_inpcb *, struct sctp_tcb *,
struct mbuf *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -193,8 +202,11 @@ sctp_abort_an_association(struct sctp_inpcb *, struct sctp_tcb *, int,
);
void
-sctp_handle_ootb(struct mbuf *, int, int, struct sctphdr *,
- struct sctp_inpcb *, struct mbuf *, uint32_t, uint16_t);
+sctp_handle_ootb(struct mbuf *, int, int,
+ struct sockaddr *, struct sockaddr *,
+ struct sctphdr *, struct sctp_inpcb *,
+ uint8_t, uint32_t,
+ uint32_t, uint16_t);
int
sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
@@ -231,11 +243,10 @@ struct sockaddr_in6 *
int sctp_cmpaddr(struct sockaddr *, struct sockaddr *);
void sctp_print_address(struct sockaddr *);
-void sctp_print_address_pkt(struct ip *, struct sctphdr *);
int
sctp_release_pr_sctp_chunk(struct sctp_tcb *, struct sctp_tmit_chunk *,
- int, int
+ uint8_t, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
@@ -248,7 +259,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
struct sockaddr *sa, sctp_assoc_t assoc_id,
uint32_t vrf_id, int *error, void *p);
void
-sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
+sctp_bindx_delete_address(struct sctp_inpcb *inp,
struct sockaddr *sa, sctp_assoc_t assoc_id,
uint32_t vrf_id, int *error);
@@ -311,7 +322,7 @@ do { \
} \
} while (0)
-/* new functions to start/stop udp tunneling */
+/* functions to start/stop udp tunneling */
void sctp_over_udp_stop(void);
int sctp_over_udp_start(void);
@@ -322,26 +333,11 @@ sctp_soreceive(struct socket *so, struct sockaddr **psa,
struct mbuf **controlp,
int *flagsp);
-
-/* For those not passing mbufs, this does the
- * translations for you. Caller owns memory
- * of size controllen returned in controlp.
- */
-int
-sctp_l_soreceive(struct socket *so,
- struct sockaddr **name,
- struct uio *uio,
- char **controlp,
- int *controllen,
- int *flag);
-
-
void
sctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d);
void
sctp_wakeup_log(struct sctp_tcb *stcb,
- uint32_t cumtsn,
uint32_t wake_cnt, int from);
void sctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t, uint16_t, uint16_t, int);
@@ -367,7 +363,7 @@ void sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc
void sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from);
void sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *, int, int, uint8_t);
-void sctp_log_block(uint8_t, struct socket *, struct sctp_association *, int);
+void sctp_log_block(uint8_t, struct sctp_association *, int);
void sctp_log_rwnd(uint8_t, uint32_t, uint32_t, uint32_t);
void sctp_log_mbcnt(uint8_t, uint32_t, uint32_t, uint32_t, uint32_t);
void sctp_log_rwnd_set(uint8_t, uint32_t, uint32_t, uint32_t, uint32_t);
@@ -386,7 +382,5 @@ sctp_auditing(int, struct sctp_inpcb *, struct sctp_tcb *,
void sctp_audit_log(uint8_t, uint8_t);
#endif
-
-
#endif /* _KERNEL */
#endif
diff --git a/freebsd/sys/netinet/tcp.h b/freebsd/sys/netinet/tcp.h
index 8779582a..affc4df0 100644
--- a/freebsd/sys/netinet/tcp.h
+++ b/freebsd/sys/netinet/tcp.h
@@ -140,16 +140,21 @@ struct tcphdr {
#endif /* __BSD_VISIBLE */
/*
- * User-settable options (used with setsockopt).
+ * User-settable options (used with setsockopt). These are discrete
+ * values and are not masked together. Some values appear to be
+ * bitmasks for historical reasons.
*/
-#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
+#define TCP_NODELAY 1 /* don't delay send to coalesce packets */
#if __BSD_VISIBLE
-#define TCP_MAXSEG 0x02 /* set maximum segment size */
-#define TCP_NOPUSH 0x04 /* don't push last block of write */
-#define TCP_NOOPT 0x08 /* don't use TCP options */
-#define TCP_MD5SIG 0x10 /* use MD5 digests (RFC2385) */
-#define TCP_INFO 0x20 /* retrieve tcp_info structure */
-#define TCP_CONGESTION 0x40 /* get/set congestion control algorithm */
+#define TCP_MAXSEG 2 /* set maximum segment size */
+#define TCP_NOPUSH 4 /* don't push last block of write */
+#define TCP_NOOPT 8 /* don't use TCP options */
+#define TCP_MD5SIG 16 /* use MD5 digests (RFC2385) */
+#define TCP_INFO 32 /* retrieve tcp_info structure */
+#define TCP_CONGESTION 64 /* get/set congestion control algorithm */
+
+/* Start of reserved space for third-party user-settable options. */
+#define TCP_VENDOR SO_VENDOR
#define TCP_CA_NAME_MAX 16 /* max congestion control name length */
@@ -217,9 +222,12 @@ struct tcp_info {
u_int32_t tcpi_snd_nxt; /* Next egress seqno */
u_int32_t tcpi_rcv_nxt; /* Next ingress seqno */
u_int32_t tcpi_toe_tid; /* HWTID for TOE endpoints */
+ u_int32_t tcpi_snd_rexmitpack; /* Retransmitted packets */
+ u_int32_t tcpi_rcv_ooopack; /* Out-of-order packets */
+ u_int32_t tcpi_snd_zerowin; /* Zero-sized windows sent */
/* Padding to grow without breaking ABI. */
- u_int32_t __tcpi_pad[29]; /* Padding. */
+ u_int32_t __tcpi_pad[26]; /* Padding. */
};
#endif
diff --git a/freebsd/sys/netinet/tcp_hostcache.c b/freebsd/sys/netinet/tcp_hostcache.c
index 352df1dd..69cb1a74 100644
--- a/freebsd/sys/netinet/tcp_hostcache.c
+++ b/freebsd/sys/netinet/tcp_hostcache.c
@@ -123,19 +123,19 @@ static void tcp_hc_purge(void *);
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, hostcache, CTLFLAG_RW, 0,
"TCP Host cache");
-SYSCTL_VNET_INT(_net_inet_tcp_hostcache, OID_AUTO, cachelimit, CTLFLAG_RDTUN,
+SYSCTL_VNET_UINT(_net_inet_tcp_hostcache, OID_AUTO, cachelimit, CTLFLAG_RDTUN,
&VNET_NAME(tcp_hostcache.cache_limit), 0,
"Overall entry limit for hostcache");
-SYSCTL_VNET_INT(_net_inet_tcp_hostcache, OID_AUTO, hashsize, CTLFLAG_RDTUN,
+SYSCTL_VNET_UINT(_net_inet_tcp_hostcache, OID_AUTO, hashsize, CTLFLAG_RDTUN,
&VNET_NAME(tcp_hostcache.hashsize), 0,
"Size of TCP hostcache hashtable");
-SYSCTL_VNET_INT(_net_inet_tcp_hostcache, OID_AUTO, bucketlimit,
+SYSCTL_VNET_UINT(_net_inet_tcp_hostcache, OID_AUTO, bucketlimit,
CTLFLAG_RDTUN, &VNET_NAME(tcp_hostcache.bucket_limit), 0,
"Per-bucket hash limit for hostcache");
-SYSCTL_VNET_INT(_net_inet_tcp_hostcache, OID_AUTO, count, CTLFLAG_RD,
+SYSCTL_VNET_UINT(_net_inet_tcp_hostcache, OID_AUTO, count, CTLFLAG_RD,
&VNET_NAME(tcp_hostcache.cache_count), 0,
"Current number of entries in hostcache");
@@ -176,6 +176,7 @@ static MALLOC_DEFINE(M_HOSTCACHE, "hostcache", "TCP hostcache");
void
tcp_hc_init(void)
{
+ u_int cache_limit;
int i;
/*
@@ -184,23 +185,27 @@ tcp_hc_init(void)
V_tcp_hostcache.cache_count = 0;
V_tcp_hostcache.hashsize = TCP_HOSTCACHE_HASHSIZE;
V_tcp_hostcache.bucket_limit = TCP_HOSTCACHE_BUCKETLIMIT;
- V_tcp_hostcache.cache_limit =
- V_tcp_hostcache.hashsize * V_tcp_hostcache.bucket_limit;
V_tcp_hostcache.expire = TCP_HOSTCACHE_EXPIRE;
V_tcp_hostcache.prune = TCP_HOSTCACHE_PRUNE;
TUNABLE_INT_FETCH("net.inet.tcp.hostcache.hashsize",
&V_tcp_hostcache.hashsize);
- TUNABLE_INT_FETCH("net.inet.tcp.hostcache.cachelimit",
- &V_tcp_hostcache.cache_limit);
- TUNABLE_INT_FETCH("net.inet.tcp.hostcache.bucketlimit",
- &V_tcp_hostcache.bucket_limit);
if (!powerof2(V_tcp_hostcache.hashsize)) {
printf("WARNING: hostcache hash size is not a power of 2.\n");
V_tcp_hostcache.hashsize = TCP_HOSTCACHE_HASHSIZE; /* default */
}
V_tcp_hostcache.hashmask = V_tcp_hostcache.hashsize - 1;
+ TUNABLE_INT_FETCH("net.inet.tcp.hostcache.bucketlimit",
+ &V_tcp_hostcache.bucket_limit);
+
+ cache_limit = V_tcp_hostcache.hashsize * V_tcp_hostcache.bucket_limit;
+ V_tcp_hostcache.cache_limit = cache_limit;
+ TUNABLE_INT_FETCH("net.inet.tcp.hostcache.cachelimit",
+ &V_tcp_hostcache.cache_limit);
+ if (V_tcp_hostcache.cache_limit > cache_limit)
+ V_tcp_hostcache.cache_limit = cache_limit;
+
/*
* Allocate the hash table.
*/
@@ -626,7 +631,7 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
msec(hc_entry->rmx_rtt *
(RTM_RTTUNIT / (hz * TCP_RTT_SCALE))),
msec(hc_entry->rmx_rttvar *
- (RTM_RTTUNIT / (hz * TCP_RTT_SCALE))),
+ (RTM_RTTUNIT / (hz * TCP_RTTVAR_SCALE))),
hc_entry->rmx_bandwidth * 8,
hc_entry->rmx_cwnd,
hc_entry->rmx_sendpipe,
diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c
index 8feb571f..508f6bf2 100644
--- a/freebsd/sys/netinet/tcp_input.c
+++ b/freebsd/sys/netinet/tcp_input.c
@@ -3,6 +3,20 @@
/*-
* Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2007-2008,2010
+ * Swinburne University of Technology, Melbourne, Australia.
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Lawrence Stewart,
+ * James Healy and David Hayes, made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/param.h>
#include <sys/kernel.h>
+#include <sys/hhook.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/proc.h> /* for proc0 declaration */
@@ -63,6 +78,7 @@ __FBSDID("$FreeBSD$");
#define TCPSTATES /* for logging */
+#include <netinet/cc.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_systm.h>
@@ -77,7 +93,6 @@ __FBSDID("$FreeBSD$");
#include <netinet6/in6_pcb.h>
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
-#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
@@ -98,7 +113,7 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-static const int tcprexmtthresh = 3;
+const int tcprexmtthresh = 3;
VNET_DEFINE(struct tcpstat, tcpstat);
SYSCTL_VNET_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, CTLFLAG_RW,
@@ -134,19 +149,16 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3042, CTLFLAG_RW,
"Enable RFC 3042 (Limited Transmit)");
VNET_DEFINE(int, tcp_do_rfc3390) = 1;
-#define V_tcp_do_rfc3390 VNET(tcp_do_rfc3390)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3390, CTLFLAG_RW,
&VNET_NAME(tcp_do_rfc3390), 0,
"Enable RFC 3390 (Increasing TCP's Initial Congestion Window)");
VNET_DEFINE(int, tcp_do_rfc3465) = 1;
-#define V_tcp_do_rfc3465 VNET(tcp_do_rfc3465)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3465, CTLFLAG_RW,
&VNET_NAME(tcp_do_rfc3465), 0,
"Enable RFC 3465 (Appropriate Byte Counting)");
VNET_DEFINE(int, tcp_abc_l_var) = 2;
-#define V_tcp_abc_l_var VNET(tcp_abc_l_var)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, abc_l_var, CTLFLAG_RW,
&VNET_NAME(tcp_abc_l_var), 2,
"Cap the max cwnd increment during slow-start to this number of segments");
@@ -205,8 +217,18 @@ static void tcp_pulloutofband(struct socket *,
struct tcphdr *, struct mbuf *, int);
static void tcp_xmit_timer(struct tcpcb *, int);
static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *);
-static void inline
- tcp_congestion_exp(struct tcpcb *);
+static void inline cc_ack_received(struct tcpcb *tp, struct tcphdr *th,
+ uint16_t type);
+static void inline cc_conn_init(struct tcpcb *tp);
+static void inline cc_post_recovery(struct tcpcb *tp, struct tcphdr *th);
+static void inline tcp_fields_to_host(struct tcphdr *);
+static void inline hhook_run_tcp_est_in(struct tcpcb *tp,
+ struct tcphdr *th, struct tcpopt *to);
+#ifdef TCP_SIGNATURE
+static void inline tcp_fields_to_net(struct tcphdr *);
+static int inline tcp_signature_verify_input(struct mbuf *, int, int,
+ int, struct tcpopt *, struct tcphdr *, u_int);
+#endif
/*
* Kernel module interface for updating tcpstat. The argument is an index
@@ -222,21 +244,244 @@ kmod_tcpstat_inc(int statnum)
(*((u_long *)&V_tcpstat + statnum))++;
}
+/*
+ * Wrapper for the TCP established input helper hook.
+ */
static void inline
-tcp_congestion_exp(struct tcpcb *tp)
+hhook_run_tcp_est_in(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to)
{
- u_int win;
-
- win = min(tp->snd_wnd, tp->snd_cwnd) /
- 2 / tp->t_maxseg;
- if (win < 2)
- win = 2;
- tp->snd_ssthresh = win * tp->t_maxseg;
- ENTER_FASTRECOVERY(tp);
- tp->snd_recover = tp->snd_max;
- if (tp->t_flags & TF_ECN_PERMIT)
- tp->t_flags |= TF_ECN_SND_CWR;
+ struct tcp_hhook_data hhook_data;
+
+ if (V_tcp_hhh[HHOOK_TCP_EST_IN]->hhh_nhooks > 0) {
+ hhook_data.tp = tp;
+ hhook_data.th = th;
+ hhook_data.to = to;
+
+ hhook_run_hooks(V_tcp_hhh[HHOOK_TCP_EST_IN], &hhook_data,
+ tp->osd);
+ }
+}
+
+/*
+ * CC wrapper hook functions
+ */
+static void inline
+cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th);
+ if (tp->snd_cwnd == min(tp->snd_cwnd, tp->snd_wnd))
+ tp->ccv->flags |= CCF_CWND_LIMITED;
+ else
+ tp->ccv->flags &= ~CCF_CWND_LIMITED;
+
+ if (type == CC_ACK) {
+ if (tp->snd_cwnd > tp->snd_ssthresh) {
+ tp->t_bytes_acked += min(tp->ccv->bytes_this_ack,
+ V_tcp_abc_l_var * tp->t_maxseg);
+ if (tp->t_bytes_acked >= tp->snd_cwnd) {
+ tp->t_bytes_acked -= tp->snd_cwnd;
+ tp->ccv->flags |= CCF_ABC_SENTAWND;
+ }
+ } else {
+ tp->ccv->flags &= ~CCF_ABC_SENTAWND;
+ tp->t_bytes_acked = 0;
+ }
+ }
+
+ if (CC_ALGO(tp)->ack_received != NULL) {
+ /* XXXLAS: Find a way to live without this */
+ tp->ccv->curack = th->th_ack;
+ CC_ALGO(tp)->ack_received(tp->ccv, type);
+ }
+}
+
+static void inline
+cc_conn_init(struct tcpcb *tp)
+{
+ struct hc_metrics_lite metrics;
+ struct inpcb *inp = tp->t_inpcb;
+ int rtt;
+#ifdef INET6
+ int isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0;
+#endif
+
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ tcp_hc_get(&inp->inp_inc, &metrics);
+
+ if (tp->t_srtt == 0 && (rtt = metrics.rmx_rtt)) {
+ tp->t_srtt = rtt;
+ tp->t_rttbest = tp->t_srtt + TCP_RTT_SCALE;
+ TCPSTAT_INC(tcps_usedrtt);
+ if (metrics.rmx_rttvar) {
+ tp->t_rttvar = metrics.rmx_rttvar;
+ TCPSTAT_INC(tcps_usedrttvar);
+ } else {
+ /* default variation is +- 1 rtt */
+ tp->t_rttvar =
+ tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE;
+ }
+ TCPT_RANGESET(tp->t_rxtcur,
+ ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1,
+ tp->t_rttmin, TCPTV_REXMTMAX);
+ }
+ if (metrics.rmx_ssthresh) {
+ /*
+ * There's some sort of gateway or interface
+ * buffer limit on the path. Use this to set
+ * the slow start threshhold, but set the
+ * threshold to no less than 2*mss.
+ */
+ tp->snd_ssthresh = max(2 * tp->t_maxseg, metrics.rmx_ssthresh);
+ TCPSTAT_INC(tcps_usedssthresh);
+ }
+
+ /*
+ * Set the slow-start flight size depending on whether this
+ * is a local network or not.
+ *
+ * Extend this so we cache the cwnd too and retrieve it here.
+ * Make cwnd even bigger than RFC3390 suggests but only if we
+ * have previous experience with the remote host. Be careful
+ * not make cwnd bigger than remote receive window or our own
+ * send socket buffer. Maybe put some additional upper bound
+ * on the retrieved cwnd. Should do incremental updates to
+ * hostcache when cwnd collapses so next connection doesn't
+ * overloads the path again.
+ *
+ * XXXAO: Initializing the CWND from the hostcache is broken
+ * and in its current form not RFC conformant. It is disabled
+ * until fixed or removed entirely.
+ *
+ * RFC3390 says only do this if SYN or SYN/ACK didn't got lost.
+ * We currently check only in syncache_socket for that.
+ */
+/* #define TCP_METRICS_CWND */
+#ifdef TCP_METRICS_CWND
+ if (metrics.rmx_cwnd)
+ tp->snd_cwnd = max(tp->t_maxseg, min(metrics.rmx_cwnd / 2,
+ min(tp->snd_wnd, so->so_snd.sb_hiwat)));
+ else
+#endif
+ if (V_tcp_do_rfc3390)
+ tp->snd_cwnd = min(4 * tp->t_maxseg,
+ max(2 * tp->t_maxseg, 4380));
+#ifdef INET6
+ else if ((isipv6 && in6_localaddr(&inp->in6p_faddr)) ||
+ (!isipv6 && in_localaddr(inp->inp_faddr)))
+#else
+ else if (in_localaddr(inp->inp_faddr))
+#endif
+ tp->snd_cwnd = tp->t_maxseg * V_ss_fltsz_local;
+ else
+ tp->snd_cwnd = tp->t_maxseg * V_ss_fltsz;
+
+ if (CC_ALGO(tp)->conn_init != NULL)
+ CC_ALGO(tp)->conn_init(tp->ccv);
+}
+
+void inline
+cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ switch(type) {
+ case CC_NDUPACK:
+ if (!IN_FASTRECOVERY(tp->t_flags)) {
+ tp->snd_recover = tp->snd_max;
+ if (tp->t_flags & TF_ECN_PERMIT)
+ tp->t_flags |= TF_ECN_SND_CWR;
+ }
+ break;
+ case CC_ECN:
+ if (!IN_CONGRECOVERY(tp->t_flags)) {
+ TCPSTAT_INC(tcps_ecn_rcwnd);
+ tp->snd_recover = tp->snd_max;
+ if (tp->t_flags & TF_ECN_PERMIT)
+ tp->t_flags |= TF_ECN_SND_CWR;
+ }
+ break;
+ case CC_RTO:
+ tp->t_dupacks = 0;
+ tp->t_bytes_acked = 0;
+ EXIT_RECOVERY(tp->t_flags);
+ tp->snd_ssthresh = max(2, min(tp->snd_wnd, tp->snd_cwnd) / 2 /
+ tp->t_maxseg) * tp->t_maxseg;
+ tp->snd_cwnd = tp->t_maxseg;
+ break;
+ case CC_RTO_ERR:
+ TCPSTAT_INC(tcps_sndrexmitbad);
+ /* RTO was unnecessary, so reset everything. */
+ tp->snd_cwnd = tp->snd_cwnd_prev;
+ tp->snd_ssthresh = tp->snd_ssthresh_prev;
+ tp->snd_recover = tp->snd_recover_prev;
+ if (tp->t_flags & TF_WASFRECOVERY)
+ ENTER_FASTRECOVERY(tp->t_flags);
+ if (tp->t_flags & TF_WASCRECOVERY)
+ ENTER_CONGRECOVERY(tp->t_flags);
+ tp->snd_nxt = tp->snd_max;
+ tp->t_flags &= ~TF_PREVVALID;
+ tp->t_badrxtwin = 0;
+ break;
+ }
+
+ if (CC_ALGO(tp)->cong_signal != NULL) {
+ if (th != NULL)
+ tp->ccv->curack = th->th_ack;
+ CC_ALGO(tp)->cong_signal(tp->ccv, type);
+ }
+}
+
+static void inline
+cc_post_recovery(struct tcpcb *tp, struct tcphdr *th)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ /* XXXLAS: KASSERT that we're in recovery? */
+
+ if (CC_ALGO(tp)->post_recovery != NULL) {
+ tp->ccv->curack = th->th_ack;
+ CC_ALGO(tp)->post_recovery(tp->ccv);
+ }
+ /* XXXLAS: EXIT_RECOVERY ? */
+ tp->t_bytes_acked = 0;
+}
+
+static inline void
+tcp_fields_to_host(struct tcphdr *th)
+{
+
+ th->th_seq = ntohl(th->th_seq);
+ th->th_ack = ntohl(th->th_ack);
+ th->th_win = ntohs(th->th_win);
+ th->th_urp = ntohs(th->th_urp);
+}
+
+#ifdef TCP_SIGNATURE
+static inline void
+tcp_fields_to_net(struct tcphdr *th)
+{
+
+ th->th_seq = htonl(th->th_seq);
+ th->th_ack = htonl(th->th_ack);
+ th->th_win = htons(th->th_win);
+ th->th_urp = htons(th->th_urp);
+}
+
+static inline int
+tcp_signature_verify_input(struct mbuf *m, int off0, int tlen, int optlen,
+ struct tcpopt *to, struct tcphdr *th, u_int tcpbflag)
+{
+ int ret;
+
+ tcp_fields_to_net(th);
+ ret = tcp_signature_verify(m, off0, tlen, optlen, to, th, tcpbflag);
+ tcp_fields_to_host(th);
+ return (ret);
}
+#endif
/* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */
#ifdef INET6
@@ -317,6 +562,9 @@ tcp_input(struct mbuf *m, int off0)
int thflags;
int rstreason = 0; /* For badport_bandlim accounting purposes */
uint8_t iptos;
+#ifdef TCP_SIGNATURE
+ uint8_t sig_checked = 0;
+#endif
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
@@ -474,10 +722,7 @@ tcp_input(struct mbuf *m, int off0)
/*
* Convert TCP protocol specific fields to host format.
*/
- th->th_seq = ntohl(th->th_seq);
- th->th_ack = ntohl(th->th_ack);
- th->th_win = ntohs(th->th_win);
- th->th_urp = ntohs(th->th_urp);
+ tcp_fields_to_host(th);
/*
* Delay dropping TCP, IP headers, IPv6 ext headers, and TCP options.
@@ -819,6 +1064,26 @@ relocked:
tp = intotcpcb(inp);
KASSERT(tp->t_state == TCPS_SYN_RECEIVED,
("%s: ", __func__));
+#ifdef TCP_SIGNATURE
+ if (sig_checked == 0) {
+ tcp_dooptions(&to, optp, optlen,
+ (thflags & TH_SYN) ? TO_SYN : 0);
+ if (!tcp_signature_verify_input(m, off0, tlen,
+ optlen, &to, th, tp->t_flags)) {
+
+ /*
+ * In SYN_SENT state if it receives an
+ * RST, it is allowed for further
+ * processing.
+ */
+ if ((thflags & TH_RST) == 0 ||
+ (tp->t_state == TCPS_SYN_SENT) == 0)
+ goto dropunlock;
+ }
+ sig_checked = 1;
+ }
+#endif
+
/*
* Process the segment and the data it
* contains. tcp_do_segment() consumes
@@ -1023,6 +1288,25 @@ relocked:
return;
}
+#ifdef TCP_SIGNATURE
+ if (sig_checked == 0) {
+ tcp_dooptions(&to, optp, optlen,
+ (thflags & TH_SYN) ? TO_SYN : 0);
+ if (!tcp_signature_verify_input(m, off0, tlen, optlen, &to,
+ th, tp->t_flags)) {
+
+ /*
+ * In SYN_SENT state if it receives an RST, it is
+ * allowed for further processing.
+ */
+ if ((thflags & TH_RST) == 0 ||
+ (tp->t_state == TCPS_SYN_SENT) == 0)
+ goto dropunlock;
+ }
+ sig_checked = 1;
+ }
+#endif
+
/*
* Segment belongs to a connection in SYN_SENT, ESTABLISHED or later
* state. tcp_do_segment() always consumes the mbuf chain, unlocks
@@ -1089,6 +1373,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
short ostate = 0;
#endif
thflags = th->th_flags;
+ tp->sackhint.last_sack_ack = 0;
/*
* If this is either a state-changing packet or current state isn't
@@ -1159,14 +1444,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
TCPSTAT_INC(tcps_ecn_ect1);
break;
}
- /*
- * Congestion experienced.
- * Ignore if we are already trying to recover.
- */
- if ((thflags & TH_ECE) &&
- SEQ_LEQ(th->th_ack, tp->snd_recover)) {
- TCPSTAT_INC(tcps_ecn_rcwnd);
- tcp_congestion_exp(tp);
+ /* Congestion experienced. */
+ if (thflags & TH_ECE) {
+ cc_cong_signal(tp, th, CC_ECN);
}
}
@@ -1185,7 +1465,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((to.to_flags & TOF_TS) && (to.to_tsecr != 0)) {
to.to_tsecr -= tp->ts_offset;
- if (TSTMP_GT(to.to_tsecr, ticks))
+ if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks()))
to.to_tsecr = 0;
}
@@ -1210,7 +1490,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
if (to.to_flags & TOF_TS) {
tp->t_flags |= TF_RCVD_TSTMP;
tp->ts_recent = to.to_tsval;
- tp->ts_recent_age = ticks;
+ tp->ts_recent_age = tcp_ts_getticks();
}
if (to.to_flags & TOF_MSS)
tcp_mss(tp, to.to_mss);
@@ -1254,22 +1534,16 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((to.to_flags & TOF_TS) != 0 &&
SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
- tp->ts_recent_age = ticks;
+ tp->ts_recent_age = tcp_ts_getticks();
tp->ts_recent = to.to_tsval;
}
if (tlen == 0) {
if (SEQ_GT(th->th_ack, tp->snd_una) &&
SEQ_LEQ(th->th_ack, tp->snd_max) &&
- tp->snd_cwnd >= tp->snd_wnd &&
- ((!V_tcp_do_newreno &&
- !(tp->t_flags & TF_SACK_PERMIT) &&
- tp->t_dupacks < tcprexmtthresh) ||
- ((V_tcp_do_newreno ||
- (tp->t_flags & TF_SACK_PERMIT)) &&
- !IN_FASTRECOVERY(tp) &&
- (to.to_flags & TOF_SACK) == 0 &&
- TAILQ_EMPTY(&tp->snd_holes)))) {
+ !IN_RECOVERY(tp->t_flags) &&
+ (to.to_flags & TOF_SACK) == 0 &&
+ TAILQ_EMPTY(&tp->snd_holes)) {
/*
* This is a pure ack for outstanding data.
*/
@@ -1288,16 +1562,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* "bad retransmit" recovery.
*/
if (tp->t_rxtshift == 1 &&
+ tp->t_flags & TF_PREVVALID &&
(int)(ticks - tp->t_badrxtwin) < 0) {
- TCPSTAT_INC(tcps_sndrexmitbad);
- tp->snd_cwnd = tp->snd_cwnd_prev;
- tp->snd_ssthresh =
- tp->snd_ssthresh_prev;
- tp->snd_recover = tp->snd_recover_prev;
- if (tp->t_flags & TF_WASFRECOVERY)
- ENTER_FASTRECOVERY(tp);
- tp->snd_nxt = tp->snd_max;
- tp->t_badrxtwin = 0;
+ cc_cong_signal(tp, th, CC_RTO_ERR);
}
/*
@@ -1310,11 +1577,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((to.to_flags & TOF_TS) != 0 &&
to.to_tsecr) {
- if (!tp->t_rttlow ||
- tp->t_rttlow > ticks - to.to_tsecr)
- tp->t_rttlow = ticks - to.to_tsecr;
+ u_int t;
+
+ t = tcp_ts_getticks() - to.to_tsecr;
+ if (!tp->t_rttlow || tp->t_rttlow > t)
+ tp->t_rttlow = t;
tcp_xmit_timer(tp,
- ticks - to.to_tsecr + 1);
+ TCP_TS_TO_TICKS(t) + 1);
} else if (tp->t_rtttime &&
SEQ_GT(th->th_ack, tp->t_rtseq)) {
if (!tp->t_rttlow ||
@@ -1324,13 +1593,26 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
ticks - tp->t_rtttime);
}
tcp_xmit_bandwidth_limit(tp, th->th_ack);
- acked = th->th_ack - tp->snd_una;
+ acked = BYTES_THIS_ACK(tp, th);
+
+ /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */
+ hhook_run_tcp_est_in(tp, th, &to);
+
TCPSTAT_INC(tcps_rcvackpack);
TCPSTAT_ADD(tcps_rcvackbyte, acked);
sbdrop(&so->so_snd, acked);
if (SEQ_GT(tp->snd_una, tp->snd_recover) &&
SEQ_LEQ(th->th_ack, tp->snd_recover))
tp->snd_recover = th->th_ack - 1;
+
+ /*
+ * Let the congestion control algorithm update
+ * congestion control related information. This
+ * typically means increasing the congestion
+ * window.
+ */
+ cc_ack_received(tp, th, CC_ACK);
+
tp->snd_una = th->th_ack;
/*
* Pull snd_wl2 up to prevent seq wrap relative
@@ -1560,7 +1842,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
tp->rcv_scale = tp->request_r_scale;
}
- tp->rcv_adv += tp->rcv_wnd;
+ tp->rcv_adv += imin(tp->rcv_wnd,
+ TCP_MAXWIN << tp->rcv_scale);
tp->snd_una++; /* SYN is acked */
/*
* If there's data, delay ACK; if there's also a FIN
@@ -1590,6 +1873,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
thflags &= ~TH_SYN;
} else {
tp->t_state = TCPS_ESTABLISHED;
+ cc_conn_init(tp);
tcp_timer_activate(tp, TT_KEEP, tcp_keepidle);
}
} else {
@@ -1770,7 +2054,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
TSTMP_LT(to.to_tsval, tp->ts_recent)) {
/* Check to see if ts_recent is over 24 days old. */
- if (ticks - tp->ts_recent_age > TCP_PAWS_IDLE) {
+ if (tcp_ts_getticks() - tp->ts_recent_age > TCP_PAWS_IDLE) {
/*
* Invalidate ts_recent. If this segment updates
* ts_recent, the age will be reset later and ts_recent
@@ -1929,7 +2213,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
SEQ_LEQ(th->th_seq, tp->last_ack_sent) &&
SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen +
((thflags & (TH_SYN|TH_FIN)) != 0))) {
- tp->ts_recent_age = ticks;
+ tp->ts_recent_age = tcp_ts_getticks();
tp->ts_recent = to.to_tsval;
}
@@ -1993,6 +2277,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->t_flags &= ~TF_NEEDFIN;
} else {
tp->t_state = TCPS_ESTABLISHED;
+ cc_conn_init(tp);
tcp_timer_activate(tp, TT_KEEP, tcp_keepidle);
}
/*
@@ -2027,6 +2312,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
((to.to_flags & TOF_SACK) ||
!TAILQ_EMPTY(&tp->snd_holes)))
tcp_sack_doack(tp, &to, th->th_ack);
+
+ /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */
+ hhook_run_tcp_est_in(tp, th, &to);
+
if (SEQ_LEQ(th->th_ack, tp->snd_una)) {
if (tlen == 0 && tiwin == tp->snd_wnd) {
TCPSTAT_INC(tcps_rcvdupack);
@@ -2061,11 +2350,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
th->th_ack != tp->snd_una)
tp->t_dupacks = 0;
else if (++tp->t_dupacks > tcprexmtthresh ||
- ((V_tcp_do_newreno ||
- (tp->t_flags & TF_SACK_PERMIT)) &&
- IN_FASTRECOVERY(tp))) {
+ IN_FASTRECOVERY(tp->t_flags)) {
+ cc_ack_received(tp, th, CC_DUPACK);
if ((tp->t_flags & TF_SACK_PERMIT) &&
- IN_FASTRECOVERY(tp)) {
+ IN_FASTRECOVERY(tp->t_flags)) {
int awnd;
/*
@@ -2083,6 +2371,16 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
}
} else
tp->snd_cwnd += tp->t_maxseg;
+ if ((thflags & TH_FIN) &&
+ (TCPS_HAVERCVDFIN(tp->t_state) == 0)) {
+ /*
+ * If its a fin we need to process
+ * it to avoid a race where both
+ * sides enter FIN-WAIT and send FIN|ACK
+ * at the same time.
+ */
+ break;
+ }
(void) tcp_output(tp);
goto drop;
} else if (tp->t_dupacks == tcprexmtthresh) {
@@ -2096,19 +2394,20 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* recovery.
*/
if (tp->t_flags & TF_SACK_PERMIT) {
- if (IN_FASTRECOVERY(tp)) {
+ if (IN_FASTRECOVERY(tp->t_flags)) {
tp->t_dupacks = 0;
break;
}
- } else if (V_tcp_do_newreno ||
- V_tcp_do_ecn) {
+ } else {
if (SEQ_LEQ(th->th_ack,
tp->snd_recover)) {
tp->t_dupacks = 0;
break;
}
}
- tcp_congestion_exp(tp);
+ /* Congestion signal before ack. */
+ cc_cong_signal(tp, th, CC_NDUPACK);
+ cc_ack_received(tp, th, CC_DUPACK);
tcp_timer_activate(tp, TT_REXMT, 0);
tp->t_rtttime = 0;
if (tp->t_flags & TF_SACK_PERMIT) {
@@ -2121,6 +2420,16 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
}
tp->snd_nxt = th->th_ack;
tp->snd_cwnd = tp->t_maxseg;
+ if ((thflags & TH_FIN) &&
+ (TCPS_HAVERCVDFIN(tp->t_state) == 0)) {
+ /*
+ * If its a fin we need to process
+ * it to avoid a race where both
+ * sides enter FIN-WAIT and send FIN|ACK
+ * at the same time.
+ */
+ break;
+ }
(void) tcp_output(tp);
KASSERT(tp->snd_limited <= 2,
("%s: tp->snd_limited too big",
@@ -2132,6 +2441,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->snd_nxt = onxt;
goto drop;
} else if (V_tcp_do_rfc3042) {
+ cc_ack_received(tp, th, CC_DUPACK);
u_long oldcwnd = tp->snd_cwnd;
tcp_seq oldsndmax = tp->snd_max;
u_int sent;
@@ -2146,6 +2456,16 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
(tp->snd_nxt - tp->snd_una) +
(tp->t_dupacks - tp->snd_limited) *
tp->t_maxseg;
+ if ((thflags & TH_FIN) &&
+ (TCPS_HAVERCVDFIN(tp->t_state) == 0)) {
+ /*
+ * If its a fin we need to process
+ * it to avoid a race where both
+ * sides enter FIN-WAIT and send FIN|ACK
+ * at the same time.
+ */
+ break;
+ }
(void) tcp_output(tp);
sent = tp->snd_max - oldsndmax;
if (sent > tp->t_maxseg) {
@@ -2173,37 +2493,14 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* If the congestion window was inflated to account
* for the other side's cached packets, retract it.
*/
- if (V_tcp_do_newreno || (tp->t_flags & TF_SACK_PERMIT)) {
- if (IN_FASTRECOVERY(tp)) {
- if (SEQ_LT(th->th_ack, tp->snd_recover)) {
- if (tp->t_flags & TF_SACK_PERMIT)
- tcp_sack_partialack(tp, th);
- else
- tcp_newreno_partial_ack(tp, th);
- } else {
- /*
- * Out of fast recovery.
- * Window inflation should have left us
- * with approximately snd_ssthresh
- * outstanding data.
- * But in case we would be inclined to
- * send a burst, better to do it via
- * the slow start mechanism.
- */
- if (SEQ_GT(th->th_ack +
- tp->snd_ssthresh,
- tp->snd_max))
- tp->snd_cwnd = tp->snd_max -
- th->th_ack +
- tp->t_maxseg;
- else
- tp->snd_cwnd = tp->snd_ssthresh;
- }
- }
- } else {
- if (tp->t_dupacks >= tcprexmtthresh &&
- tp->snd_cwnd > tp->snd_ssthresh)
- tp->snd_cwnd = tp->snd_ssthresh;
+ if (IN_FASTRECOVERY(tp->t_flags)) {
+ if (SEQ_LT(th->th_ack, tp->snd_recover)) {
+ if (tp->t_flags & TF_SACK_PERMIT)
+ tcp_sack_partialack(tp, th);
+ else
+ tcp_newreno_partial_ack(tp, th);
+ } else
+ cc_post_recovery(tp, th);
}
tp->t_dupacks = 0;
/*
@@ -2234,7 +2531,7 @@ process_ACK:
("tcp_input: process_ACK ti_locked %d", ti_locked));
INP_WLOCK_ASSERT(tp->t_inpcb);
- acked = th->th_ack - tp->snd_una;
+ acked = BYTES_THIS_ACK(tp, th);
TCPSTAT_INC(tcps_rcvackpack);
TCPSTAT_ADD(tcps_rcvackbyte, acked);
@@ -2245,16 +2542,9 @@ process_ACK:
* original cwnd and ssthresh, and proceed to transmit where
* we left off.
*/
- if (tp->t_rxtshift == 1 && (int)(ticks - tp->t_badrxtwin) < 0) {
- TCPSTAT_INC(tcps_sndrexmitbad);
- tp->snd_cwnd = tp->snd_cwnd_prev;
- tp->snd_ssthresh = tp->snd_ssthresh_prev;
- tp->snd_recover = tp->snd_recover_prev;
- if (tp->t_flags & TF_WASFRECOVERY)
- ENTER_FASTRECOVERY(tp);
- tp->snd_nxt = tp->snd_max;
- tp->t_badrxtwin = 0; /* XXX probably not required */
- }
+ if (tp->t_rxtshift == 1 && tp->t_flags & TF_PREVVALID &&
+ (int)(ticks - tp->t_badrxtwin) < 0)
+ cc_cong_signal(tp, th, CC_RTO_ERR);
/*
* If we have a timestamp reply, update smoothed
@@ -2270,11 +2560,13 @@ process_ACK:
* timestamps of 0 or we could calculate a
* huge RTT and blow up the retransmit timer.
*/
- if ((to.to_flags & TOF_TS) != 0 &&
- to.to_tsecr) {
- if (!tp->t_rttlow || tp->t_rttlow > ticks - to.to_tsecr)
- tp->t_rttlow = ticks - to.to_tsecr;
- tcp_xmit_timer(tp, ticks - to.to_tsecr + 1);
+ if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) {
+ u_int t;
+
+ t = tcp_ts_getticks() - to.to_tsecr;
+ if (!tp->t_rttlow || tp->t_rttlow > t)
+ tp->t_rttlow = t;
+ tcp_xmit_timer(tp, TCP_TS_TO_TICKS(t) + 1);
} else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) {
if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime)
tp->t_rttlow = ticks - tp->t_rtttime;
@@ -2302,61 +2594,12 @@ process_ACK:
goto step6;
/*
- * When new data is acked, open the congestion window.
- * Method depends on which congestion control state we're
- * in (slow start or cong avoid) and if ABC (RFC 3465) is
- * enabled.
- *
- * slow start: cwnd <= ssthresh
- * cong avoid: cwnd > ssthresh
- *
- * slow start and ABC (RFC 3465):
- * Grow cwnd exponentially by the amount of data
- * ACKed capping the max increment per ACK to
- * (abc_l_var * maxseg) bytes.
- *
- * slow start without ABC (RFC 2581):
- * Grow cwnd exponentially by maxseg per ACK.
- *
- * cong avoid and ABC (RFC 3465):
- * Grow cwnd linearly by maxseg per RTT for each
- * cwnd worth of ACKed data.
- *
- * cong avoid without ABC (RFC 2581):
- * Grow cwnd linearly by approximately maxseg per RTT using
- * maxseg^2 / cwnd per ACK as the increment.
- * If cwnd > maxseg^2, fix the cwnd increment at 1 byte to
- * avoid capping cwnd.
+ * Let the congestion control algorithm update congestion
+ * control related information. This typically means increasing
+ * the congestion window.
*/
- if ((!V_tcp_do_newreno && !(tp->t_flags & TF_SACK_PERMIT)) ||
- !IN_FASTRECOVERY(tp)) {
- u_int cw = tp->snd_cwnd;
- u_int incr = tp->t_maxseg;
- /* In congestion avoidance? */
- if (cw > tp->snd_ssthresh) {
- if (V_tcp_do_rfc3465) {
- tp->t_bytes_acked += acked;
- if (tp->t_bytes_acked >= tp->snd_cwnd)
- tp->t_bytes_acked -= cw;
- else
- incr = 0;
- }
- else
- incr = max((incr * incr / cw), 1);
- /*
- * In slow-start with ABC enabled and no RTO in sight?
- * (Must not use abc_l_var > 1 if slow starting after an
- * RTO. On RTO, snd_nxt = snd_una, so the snd_nxt ==
- * snd_max check is sufficient to handle this).
- */
- } else if (V_tcp_do_rfc3465 &&
- tp->snd_nxt == tp->snd_max)
- incr = min(acked,
- V_tcp_abc_l_var * tp->t_maxseg);
- /* ABC is on by default, so (incr == 0) frequently. */
- if (incr > 0)
- tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<<tp->snd_scale);
- }
+ cc_ack_received(tp, th, CC_ACK);
+
SOCKBUF_LOCK(&so->so_snd);
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
@@ -2370,16 +2613,14 @@ process_ACK:
/* NB: sowwakeup_locked() does an implicit unlock. */
sowwakeup_locked(so);
/* Detect una wraparound. */
- if ((V_tcp_do_newreno || (tp->t_flags & TF_SACK_PERMIT)) &&
- !IN_FASTRECOVERY(tp) &&
+ if (!IN_RECOVERY(tp->t_flags) &&
SEQ_GT(tp->snd_una, tp->snd_recover) &&
SEQ_LEQ(th->th_ack, tp->snd_recover))
tp->snd_recover = th->th_ack - 1;
- if ((V_tcp_do_newreno || (tp->t_flags & TF_SACK_PERMIT)) &&
- IN_FASTRECOVERY(tp) &&
+ /* XXXLAS: Can this be moved up into cc_post_recovery? */
+ if (IN_RECOVERY(tp->t_flags) &&
SEQ_GEQ(th->th_ack, tp->snd_recover)) {
- EXIT_FASTRECOVERY(tp);
- tp->t_bytes_acked = 0;
+ EXIT_RECOVERY(tp->t_flags);
}
tp->snd_una = th->th_ack;
if (tp->t_flags & TF_SACK_PERMIT) {
@@ -2609,7 +2850,10 @@ dodata: /* XXX */
* buffer size.
* XXX: Unused.
*/
- len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt);
+ if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt))
+ len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt);
+ else
+ len = so->so_rcv.sb_hiwat;
#endif
} else {
m_freem(m);
@@ -3078,22 +3322,19 @@ tcp_xmit_timer(struct tcpcb *tp, int rtt)
* are present. Store the upper limit of the length of options plus
* data in maxopd.
*
- * In case of T/TCP, we call this routine during implicit connection
- * setup as well (offer = -1), to initialize maxseg from the cached
- * MSS of our peer.
- *
* NOTE that this routine is only called when we process an incoming
- * segment. Outgoing SYN/ACK MSS settings are handled in tcp_mssopt().
+ * segment, or an ICMP need fragmentation datagram. Outgoing SYN/ACK MSS
+ * settings are handled in tcp_mssopt().
*/
void
-tcp_mss_update(struct tcpcb *tp, int offer,
+tcp_mss_update(struct tcpcb *tp, int offer, int mtuoffer,
struct hc_metrics_lite *metricptr, int *mtuflags)
{
int mss;
u_long maxmtu;
struct inpcb *inp = tp->t_inpcb;
struct hc_metrics_lite metrics;
- int origoffer = offer;
+ int origoffer;
#ifdef INET6
int isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0;
size_t min_protoh = isipv6 ?
@@ -3105,6 +3346,12 @@ tcp_mss_update(struct tcpcb *tp, int offer,
INP_WLOCK_ASSERT(tp->t_inpcb);
+ if (mtuoffer != -1) {
+ KASSERT(offer == -1, ("%s: conflict", __func__));
+ offer = mtuoffer - min_protoh;
+ }
+ origoffer = offer;
+
/* Initialize. */
#ifdef INET6
if (isipv6) {
@@ -3244,24 +3491,19 @@ tcp_mss_update(struct tcpcb *tp, int offer,
void
tcp_mss(struct tcpcb *tp, int offer)
{
- int rtt, mss;
+ int mss;
u_long bufsize;
struct inpcb *inp;
struct socket *so;
struct hc_metrics_lite metrics;
int mtuflags = 0;
-#ifdef INET6
- int isipv6;
-#endif
+
KASSERT(tp != NULL, ("%s: tp == NULL", __func__));
- tcp_mss_update(tp, offer, &metrics, &mtuflags);
+ tcp_mss_update(tp, offer, -1, &metrics, &mtuflags);
mss = tp->t_maxseg;
inp = tp->t_inpcb;
-#ifdef INET6
- isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0;
-#endif
/*
* If there's a pipesize, change the socket buffer to that size,
@@ -3301,77 +3543,6 @@ tcp_mss(struct tcpcb *tp, int offer)
(void)sbreserve_locked(&so->so_rcv, bufsize, so, NULL);
}
SOCKBUF_UNLOCK(&so->so_rcv);
- /*
- * While we're here, check the others too.
- */
- if (tp->t_srtt == 0 && (rtt = metrics.rmx_rtt)) {
- tp->t_srtt = rtt;
- tp->t_rttbest = tp->t_srtt + TCP_RTT_SCALE;
- TCPSTAT_INC(tcps_usedrtt);
- if (metrics.rmx_rttvar) {
- tp->t_rttvar = metrics.rmx_rttvar;
- TCPSTAT_INC(tcps_usedrttvar);
- } else {
- /* default variation is +- 1 rtt */
- tp->t_rttvar =
- tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE;
- }
- TCPT_RANGESET(tp->t_rxtcur,
- ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1,
- tp->t_rttmin, TCPTV_REXMTMAX);
- }
- if (metrics.rmx_ssthresh) {
- /*
- * There's some sort of gateway or interface
- * buffer limit on the path. Use this to set
- * the slow start threshhold, but set the
- * threshold to no less than 2*mss.
- */
- tp->snd_ssthresh = max(2 * mss, metrics.rmx_ssthresh);
- TCPSTAT_INC(tcps_usedssthresh);
- }
- if (metrics.rmx_bandwidth)
- tp->snd_bandwidth = metrics.rmx_bandwidth;
-
- /*
- * Set the slow-start flight size depending on whether this
- * is a local network or not.
- *
- * Extend this so we cache the cwnd too and retrieve it here.
- * Make cwnd even bigger than RFC3390 suggests but only if we
- * have previous experience with the remote host. Be careful
- * not make cwnd bigger than remote receive window or our own
- * send socket buffer. Maybe put some additional upper bound
- * on the retrieved cwnd. Should do incremental updates to
- * hostcache when cwnd collapses so next connection doesn't
- * overloads the path again.
- *
- * XXXAO: Initializing the CWND from the hostcache is broken
- * and in its current form not RFC conformant. It is disabled
- * until fixed or removed entirely.
- *
- * RFC3390 says only do this if SYN or SYN/ACK didn't got lost.
- * We currently check only in syncache_socket for that.
- */
-/* #define TCP_METRICS_CWND */
-#ifdef TCP_METRICS_CWND
- if (metrics.rmx_cwnd)
- tp->snd_cwnd = max(mss,
- min(metrics.rmx_cwnd / 2,
- min(tp->snd_wnd, so->so_snd.sb_hiwat)));
- else
-#endif
- if (V_tcp_do_rfc3390)
- tp->snd_cwnd = min(4 * mss, max(2 * mss, 4380));
-#ifdef INET6
- else if ((isipv6 && in6_localaddr(&inp->in6p_faddr)) ||
- (!isipv6 && in_localaddr(inp->inp_faddr)))
-#else
- else if (in_localaddr(inp->inp_faddr))
-#endif
- tp->snd_cwnd = mss * V_ss_fltsz_local;
- else
- tp->snd_cwnd = mss * V_ss_fltsz;
/* Check the interface for TSO capabilities. */
if (mtuflags & CSUM_TSO)
@@ -3435,7 +3606,7 @@ tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th)
* Set snd_cwnd to one segment beyond acknowledged offset.
* (tp->snd_una has not yet been updated when this function is called.)
*/
- tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una);
+ tp->snd_cwnd = tp->t_maxseg + BYTES_THIS_ACK(tp, th);
tp->t_flags |= TF_ACKNOW;
(void) tcp_output(tp);
tp->snd_cwnd = ocwnd;
@@ -3445,8 +3616,8 @@ tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th)
* Partial window deflation. Relies on fact that tp->snd_una
* not updated yet.
*/
- if (tp->snd_cwnd > th->th_ack - tp->snd_una)
- tp->snd_cwnd -= th->th_ack - tp->snd_una;
+ if (tp->snd_cwnd > BYTES_THIS_ACK(tp, th))
+ tp->snd_cwnd -= BYTES_THIS_ACK(tp, th);
else
tp->snd_cwnd = 0;
tp->snd_cwnd += tp->t_maxseg;
diff --git a/freebsd/sys/netinet/tcp_lro.c b/freebsd/sys/netinet/tcp_lro.c
index bbb98e60..f8f678e3 100644
--- a/freebsd/sys/netinet/tcp_lro.c
+++ b/freebsd/sys/netinet/tcp_lro.c
@@ -1,39 +1,33 @@
#include <machine/rtems-bsd-config.h>
-/******************************************************************************
-
-Copyright (c) 2007, Myricom Inc.
-Copyright (c) 2008, Intel Corporation.
-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. Neither the name of the Myricom Inc, nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
- 3. Neither the name of the Intel Corporation, nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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$
-***************************************************************************/
+/*-
+ * Copyright (c) 2007, Myricom Inc.
+ * Copyright (c) 2008, Intel Corporation.
+ * 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$
+ */
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
diff --git a/freebsd/sys/netinet/tcp_lro.h b/freebsd/sys/netinet/tcp_lro.h
index 08aac690..7e498871 100644
--- a/freebsd/sys/netinet/tcp_lro.h
+++ b/freebsd/sys/netinet/tcp_lro.h
@@ -1,39 +1,32 @@
-/*******************************************************************************
+/*-
+ * Copyright (c) 2006, Myricom Inc.
+ * Copyright (c) 2008, Intel Corporation.
+ * 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$
+ */
-Copyright (c) 2006, Myricom Inc.
-Copyright (c) 2008, Intel Corporation.
-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. Neither the name of the Myricom Inc, nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
- 2. Neither the name of the Intel Corporation, nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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$
-
-***************************************************************************/
#ifndef _TCP_LRO_H_
#define _TCP_LRO_H_
diff --git a/freebsd/sys/netinet/tcp_offload.h b/freebsd/sys/netinet/tcp_offload.h
index 48f35ff6..313185f6 100644
--- a/freebsd/sys/netinet/tcp_offload.h
+++ b/freebsd/sys/netinet/tcp_offload.h
@@ -56,7 +56,7 @@
*
* It is assumed that individuals deploying TOE will want connections
* to be offloaded without software changes so all connections on an
- * interface providing TOE are offloaded unless the the SO_NO_OFFLOAD
+ * interface providing TOE are offloaded unless the SO_NO_OFFLOAD
* flag is set on the socket.
*
*
diff --git a/freebsd/sys/netinet/tcp_output.c b/freebsd/sys/netinet/tcp_output.c
index 55a1f6e4..8d6881d1 100644
--- a/freebsd/sys/netinet/tcp_output.c
+++ b/freebsd/sys/netinet/tcp_output.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/domain.h>
+#include <sys/hhook.h>
#include <sys/kernel.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mbuf.h>
@@ -55,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <net/route.h>
#include <net/vnet.h>
+#include <netinet/cc.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@@ -66,7 +68,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#endif
-#include <netinet/tcp.h>
#define TCPOUTFLAGS
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
@@ -104,11 +105,6 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, local_slowstart_flightsize,
CTLFLAG_RW, &VNET_NAME(ss_fltsz_local), 1,
"Slow start flight size for local networks");
-VNET_DEFINE(int, tcp_do_newreno) = 1;
-SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, newreno, CTLFLAG_RW,
- &VNET_NAME(tcp_do_newreno), 0,
- "Enable NewReno Algorithms");
-
VNET_DEFINE(int, tcp_do_tso) = 1;
#define V_tcp_do_tso VNET(tcp_do_tso)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, tso, CTLFLAG_RW,
@@ -133,6 +129,43 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_max), 0,
"Max size of automatic send buffer");
+static void inline hhook_run_tcp_est_out(struct tcpcb *tp,
+ struct tcphdr *th, struct tcpopt *to,
+ long len, int tso);
+static void inline cc_after_idle(struct tcpcb *tp);
+
+/*
+ * Wrapper for the TCP established ouput helper hook.
+ */
+static void inline
+hhook_run_tcp_est_out(struct tcpcb *tp, struct tcphdr *th,
+ struct tcpopt *to, long len, int tso)
+{
+ struct tcp_hhook_data hhook_data;
+
+ if (V_tcp_hhh[HHOOK_TCP_EST_OUT]->hhh_nhooks > 0) {
+ hhook_data.tp = tp;
+ hhook_data.th = th;
+ hhook_data.to = to;
+ hhook_data.len = len;
+ hhook_data.tso = tso;
+
+ hhook_run_hooks(V_tcp_hhh[HHOOK_TCP_EST_OUT], &hhook_data,
+ tp->osd);
+ }
+}
+
+/*
+ * CC wrapper hook functions
+ */
+static void inline
+cc_after_idle(struct tcpcb *tp)
+{
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (CC_ALGO(tp)->after_idle != NULL)
+ CC_ALGO(tp)->after_idle(tp->ccv);
+}
/*
* Tcp output routine: figure out what should be sent and send it.
@@ -142,7 +175,7 @@ tcp_output(struct tcpcb *tp)
{
struct socket *so = tp->t_inpcb->inp_socket;
long len, recwin, sendwin;
- int off, flags, error, rw;
+ int off, flags, error;
struct mbuf *m;
struct ip *ip = NULL;
struct ipovly *ipov = NULL;
@@ -176,37 +209,8 @@ tcp_output(struct tcpcb *tp)
* to send, then transmit; otherwise, investigate further.
*/
idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una);
- if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur) {
- /*
- * If we've been idle for more than one retransmit
- * timeout the old congestion window is no longer
- * current and we have to reduce it to the restart
- * window before we can transmit again.
- *
- * The restart window is the initial window or the last
- * CWND, whichever is smaller.
- *
- * This is done to prevent us from flooding the path with
- * a full CWND at wirespeed, overloading router and switch
- * buffers along the way.
- *
- * See RFC5681 Section 4.1. "Restarting Idle Connections".
- */
- if (V_tcp_do_rfc3390)
- rw = min(4 * tp->t_maxseg,
- max(2 * tp->t_maxseg, 4380));
-#ifdef INET6
- else if ((isipv6 ? in6_localaddr(&tp->t_inpcb->in6p_faddr) :
- in_localaddr(tp->t_inpcb->inp_faddr)))
-#else
- else if (in_localaddr(tp->t_inpcb->inp_faddr))
-#endif
- rw = V_ss_fltsz_local * tp->t_maxseg;
- else
- rw = V_ss_fltsz * tp->t_maxseg;
-
- tp->snd_cwnd = min(rw, tp->snd_cwnd);
- }
+ if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur)
+ cc_after_idle(tp);
tp->t_flags &= ~TF_LASTIDLE;
if (idle) {
if (tp->t_flags & TF_MORETOCOME) {
@@ -244,7 +248,7 @@ again:
sack_bytes_rxmt = 0;
len = 0;
p = NULL;
- if ((tp->t_flags & TF_SACK_PERMIT) && IN_FASTRECOVERY(tp) &&
+ if ((tp->t_flags & TF_SACK_PERMIT) && IN_FASTRECOVERY(tp->t_flags) &&
(p = tcp_sack_output(tp, &sack_bytes_rxmt))) {
long cwin;
@@ -572,14 +576,28 @@ after_sack_rexmit:
* taking into account that we are limited by
* TCP_MAXWIN << tp->rcv_scale.
*/
- long adv = min(recwin, (long)TCP_MAXWIN << tp->rcv_scale) -
- (tp->rcv_adv - tp->rcv_nxt);
+ long adv;
+ int oldwin;
+
+ adv = min(recwin, (long)TCP_MAXWIN << tp->rcv_scale);
+ if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt)) {
+ oldwin = (tp->rcv_adv - tp->rcv_nxt);
+ adv -= oldwin;
+ } else
+ oldwin = 0;
+ /*
+ * If the new window size ends up being the same as the old
+ * size when it is scaled, then don't force a window update.
+ */
+ if (oldwin >> tp->rcv_scale == (adv + oldwin) >> tp->rcv_scale)
+ goto dontupdate;
if (adv >= (long) (2 * tp->t_maxseg))
goto send;
if (2 * adv >= (long) so->so_rcv.sb_hiwat)
goto send;
}
+dontupdate:
/*
* Send if we owe the peer an ACK, RST, SYN, or urgent data. ACKNOW
@@ -686,13 +704,13 @@ send:
/* Timestamps. */
if ((tp->t_flags & TF_RCVD_TSTMP) ||
((flags & TH_SYN) && (tp->t_flags & TF_REQ_TSTMP))) {
- to.to_tsval = ticks + tp->ts_offset;
+ to.to_tsval = tcp_ts_getticks() + tp->ts_offset;
to.to_tsecr = tp->ts_recent;
to.to_flags |= TOF_TS;
/* Set receive buffer autosizing timestamp. */
if (tp->rfbuf_ts == 0 &&
(so->so_rcv.sb_flags & SB_AUTOSIZE))
- tp->rfbuf_ts = ticks;
+ tp->rfbuf_ts = tcp_ts_getticks();
}
/* Selective ACK's. */
if (tp->t_flags & TF_SACK_PERMIT) {
@@ -785,6 +803,7 @@ send:
if ((tp->t_flags & TF_FORCEDATA) && len == 1)
TCPSTAT_INC(tcps_sndprobe);
else if (SEQ_LT(tp->snd_nxt, tp->snd_max) || sack_rxmit) {
+ tp->t_sndrexmitpack++;
TCPSTAT_INC(tcps_sndrexmitpack);
TCPSTAT_ADD(tcps_sndrexmitbyte, len);
} else {
@@ -985,7 +1004,8 @@ send:
if (recwin < (long)(so->so_rcv.sb_hiwat / 4) &&
recwin < (long)tp->t_maxseg)
recwin = 0;
- if (recwin < (long)(tp->rcv_adv - tp->rcv_nxt))
+ if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt) &&
+ recwin < (long)(tp->rcv_adv - tp->rcv_nxt))
recwin = (long)(tp->rcv_adv - tp->rcv_nxt);
if (recwin > (long)TCP_MAXWIN << tp->rcv_scale)
recwin = (long)TCP_MAXWIN << tp->rcv_scale;
@@ -1009,9 +1029,10 @@ send:
* to read more data than can be buffered prior to transmitting on
* the connection.
*/
- if (th->th_win == 0)
+ if (th->th_win == 0) {
+ tp->t_sndzerowin++;
tp->t_flags |= TF_RXWIN0SENT;
- else
+ } else
tp->t_flags &= ~TF_RXWIN0SENT;
if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
th->th_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
@@ -1140,6 +1161,9 @@ timer:
tp->snd_max = tp->snd_nxt + len;
}
+ /* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */
+ hhook_run_tcp_est_out(tp, th, &to, len, tso);
+
#ifdef TCPDEBUG
/*
* Trace.
@@ -1266,7 +1290,7 @@ out:
*/
if (tso)
tp->t_flags &= ~TF_TSO;
- tcp_mtudisc(tp->t_inpcb, 0);
+ tcp_mtudisc(tp->t_inpcb, -1);
return (0);
case EHOSTDOWN:
case EHOSTUNREACH:
@@ -1289,7 +1313,7 @@ out:
* then remember the size of the advertised window.
* Any pending ACK has now been sent.
*/
- if (recwin > 0 && SEQ_GT(tp->rcv_nxt + recwin, tp->rcv_adv))
+ if (recwin >= 0 && SEQ_GT(tp->rcv_nxt + recwin, tp->rcv_adv))
tp->rcv_adv = tp->rcv_nxt + recwin;
tp->last_ack_sent = tp->rcv_nxt;
tp->t_flags &= ~(TF_ACKNOW | TF_DELACK);
@@ -1302,7 +1326,7 @@ out:
* on the transmitter effectively destroys the TCP window, forcing
* it to four packets (1.5Kx4 = 6K window).
*/
- if (sendalot && (!V_tcp_do_newreno || --maxburst))
+ if (sendalot && --maxburst)
goto again;
#endif
if (sendalot)
@@ -1316,6 +1340,7 @@ tcp_setpersist(struct tcpcb *tp)
int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
int tt;
+ tp->t_flags &= ~TF_PREVVALID;
if (tcp_timer_active(tp, TT_REXMT))
panic("tcp_setpersist: retransmit pending");
/*
diff --git a/freebsd/sys/netinet/tcp_reass.c b/freebsd/sys/netinet/tcp_reass.c
index 64aeca84..432b6ba1 100644
--- a/freebsd/sys/netinet/tcp_reass.c
+++ b/freebsd/sys/netinet/tcp_reass.c
@@ -84,19 +84,22 @@ SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0,
static VNET_DEFINE(int, tcp_reass_maxseg) = 0;
#define V_tcp_reass_maxseg VNET(tcp_reass_maxseg)
-SYSCTL_VNET_PROC(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RDTUN,
+SYSCTL_VNET_PROC(_net_inet_tcp_reass, OID_AUTO, maxsegments,
+ CTLTYPE_INT | CTLFLAG_RDTUN,
&VNET_NAME(tcp_reass_maxseg), 0, &tcp_reass_sysctl_maxseg, "I",
"Global maximum number of TCP Segments in Reassembly Queue");
static VNET_DEFINE(int, tcp_reass_qsize) = 0;
#define V_tcp_reass_qsize VNET(tcp_reass_qsize)
-SYSCTL_VNET_PROC(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLFLAG_RD,
+SYSCTL_VNET_PROC(_net_inet_tcp_reass, OID_AUTO, cursegments,
+ CTLTYPE_INT | CTLFLAG_RD,
&VNET_NAME(tcp_reass_qsize), 0, &tcp_reass_sysctl_qsize, "I",
"Global number of TCP Segments currently in Reassembly Queue");
static VNET_DEFINE(int, tcp_reass_overflows) = 0;
#define V_tcp_reass_overflows VNET(tcp_reass_overflows)
-SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLFLAG_RD,
+SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, overflows,
+ CTLTYPE_INT | CTLFLAG_RD,
&VNET_NAME(tcp_reass_overflows), 0,
"Global number of TCP Segment Reassembly Queue Overflows");
@@ -176,7 +179,9 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
struct tseg_qent *nq;
struct tseg_qent *te = NULL;
struct socket *so = tp->t_inpcb->inp_socket;
+ char *s = NULL;
int flags;
+ struct tseg_qent tqs;
INP_WLOCK_ASSERT(tp->t_inpcb);
@@ -214,19 +219,45 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
TCPSTAT_INC(tcps_rcvmemdrop);
m_freem(m);
*tlenp = 0;
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: queue limit reached, "
+ "segment dropped\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
return (0);
}
/*
* Allocate a new queue entry. If we can't, or hit the zone limit
* just drop the pkt.
+ *
+ * Use a temporary structure on the stack for the missing segment
+ * when the zone is exhausted. Otherwise we may get stuck.
*/
te = uma_zalloc(V_tcp_reass_zone, M_NOWAIT);
if (te == NULL) {
- TCPSTAT_INC(tcps_rcvmemdrop);
- m_freem(m);
- *tlenp = 0;
- return (0);
+ if (th->th_seq != tp->rcv_nxt) {
+ TCPSTAT_INC(tcps_rcvmemdrop);
+ m_freem(m);
+ *tlenp = 0;
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+ NULL))) {
+ log(LOG_DEBUG, "%s; %s: global zone limit "
+ "reached, segment dropped\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ return (0);
+ } else {
+ bzero(&tqs, sizeof(struct tseg_qent));
+ te = &tqs;
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+ NULL))) {
+ log(LOG_DEBUG,
+ "%s; %s: global zone limit reached, using "
+ "stack for missing segment\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
}
tp->t_segqlen++;
@@ -268,6 +299,7 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
th->th_seq += i;
}
}
+ tp->t_rcvoopack++;
TCPSTAT_INC(tcps_rcvoopack);
TCPSTAT_ADD(tcps_rcvoobyte, *tlenp);
@@ -302,6 +334,8 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
if (p == NULL) {
LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q);
} else {
+ KASSERT(te != &tqs, ("%s: temporary stack based entry not "
+ "first element in queue", __func__));
LIST_INSERT_AFTER(p, te, tqe_q);
}
@@ -325,7 +359,8 @@ present:
m_freem(q->tqe_m);
else
sbappendstream_locked(&so->so_rcv, q->tqe_m);
- uma_zfree(V_tcp_reass_zone, q);
+ if (q != &tqs)
+ uma_zfree(V_tcp_reass_zone, q);
tp->t_segqlen--;
q = nq;
} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
diff --git a/freebsd/sys/netinet/tcp_sack.c b/freebsd/sys/netinet/tcp_sack.c
index 7a7df0bb..fc93be91 100644
--- a/freebsd/sys/netinet/tcp_sack.c
+++ b/freebsd/sys/netinet/tcp_sack.c
@@ -427,6 +427,7 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
* are received.
*/
sblkp = &sack_blocks[num_sack_blks - 1]; /* Last SACK block */
+ tp->sackhint.last_sack_ack = sblkp->end;
if (SEQ_LT(tp->snd_fack, sblkp->start)) {
/*
* The highest SACK block is beyond fack. Append new SACK
@@ -578,7 +579,7 @@ tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th)
tcp_timer_activate(tp, TT_REXMT, 0);
tp->t_rtttime = 0;
/* Send one or 2 segments based on how much new data was acked. */
- if (((th->th_ack - tp->snd_una) / tp->t_maxseg) > 2)
+ if ((BYTES_THIS_ACK(tp, th) / tp->t_maxseg) > 2)
num_segs = 2;
tp->snd_cwnd = (tp->sackhint.sack_bytes_rexmit +
(tp->snd_nxt - tp->sack_newdata) + num_segs * tp->t_maxseg);
diff --git a/freebsd/sys/netinet/tcp_seq.h b/freebsd/sys/netinet/tcp_seq.h
index f58b537c..51d971f2 100644
--- a/freebsd/sys/netinet/tcp_seq.h
+++ b/freebsd/sys/netinet/tcp_seq.h
@@ -62,7 +62,34 @@
(tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \
(tp)->snd_recover = (tp)->iss
-#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * hz)
- /* timestamp wrap-around time */
+#ifdef _KERNEL
+/*
+ * Clock macros for RFC 1323 timestamps.
+ */
+#define TCP_TS_TO_TICKS(_t) ((_t) * hz / 1000)
+
+/* Timestamp wrap-around time, 24 days. */
+#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * 1000)
+
+/*
+ * tcp_ts_getticks() in ms, should be 1ms < x < 1000ms according to RFC 1323.
+ * We always use 1ms granularity independent of hz.
+ */
+static __inline u_int
+tcp_ts_getticks(void)
+{
+ struct timeval tv;
+ u_long ms;
+
+ /*
+ * getmicrouptime() should be good enough for any 1-1000ms granularity.
+ * Do not use getmicrotime() here as it might break nfsroot/tcp.
+ */
+ getmicrouptime(&tv);
+ ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+
+ return (ms);
+}
+#endif /* _KERNEL */
#endif /* _NETINET_TCP_SEQ_H_ */
diff --git a/freebsd/sys/netinet/tcp_subr.c b/freebsd/sys/netinet/tcp_subr.c
index 027a2ad6..a42f2fa5 100644
--- a/freebsd/sys/netinet/tcp_subr.c
+++ b/freebsd/sys/netinet/tcp_subr.c
@@ -47,7 +47,9 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/callout.h>
+#include <sys/hhook.h>
#include <sys/kernel.h>
+#include <sys/khelp.h>
#include <sys/sysctl.h>
#include <sys/jail.h>
#include <sys/malloc.h>
@@ -68,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/vnet.h>
+#include <netinet/cc.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@@ -86,7 +89,6 @@ __FBSDID("$FreeBSD$");
#include <netinet6/nd6.h>
#endif
#include <netinet/ip_icmp.h>
-#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
@@ -204,7 +206,7 @@ static int do_tcpdrain = 1;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_tcpdrain, CTLFLAG_RW, &do_tcpdrain, 0,
"Enable tcp_drain routine for extra help when low on mbufs");
-SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD,
+SYSCTL_VNET_UINT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD,
&VNET_NAME(tcbinfo.ipi_count), 0, "Number of active PCBs");
static VNET_DEFINE(int, icmp_may_rst) = 1;
@@ -263,10 +265,19 @@ SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, stab, CTLFLAG_RW,
&VNET_NAME(tcp_inflight_stab), 0,
"Inflight Algorithm Stabilization 20 = 2 packets");
+#ifdef TCP_SIGNATURE
+static int tcp_sig_checksigs = 1;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, signature_verify_input, CTLFLAG_RW,
+ &tcp_sig_checksigs, 0, "Verify RFC2385 digests on inbound traffic");
+#endif
+
VNET_DEFINE(uma_zone_t, sack_hole_zone);
#define V_sack_hole_zone VNET(sack_hole_zone)
+VNET_DEFINE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST+1]);
+
static struct inpcb *tcp_notify(struct inpcb *, int);
+static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int);
static void tcp_isn_tick(void *);
static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th,
void *ip4hdr, const void *ip6hdr);
@@ -290,6 +301,8 @@ static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th,
struct tcpcb_mem {
struct tcpcb tcb;
struct tcp_timer tt;
+ struct cc_var ccv;
+ struct osd osd;
};
static VNET_DEFINE(uma_zone_t, tcpcb_zone);
@@ -335,6 +348,14 @@ tcp_init(void)
V_tcbinfo.ipi_vnet = curvnet;
#endif
V_tcbinfo.ipi_listhead = &V_tcb;
+
+ if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_IN,
+ &V_tcp_hhh[HHOOK_TCP_EST_IN], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0)
+ printf("%s: WARNING: unable to register helper hook\n", __func__);
+ if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT,
+ &V_tcp_hhh[HHOOK_TCP_EST_OUT], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0)
+ printf("%s: WARNING: unable to register helper hook\n", __func__);
+
hashsize = TCBHASHSIZE;
TUNABLE_INT_FETCH("net.inet.tcp.tcbhashsize", &hashsize);
if (!powerof2(hashsize)) {
@@ -705,6 +726,32 @@ tcp_newtcpcb(struct inpcb *inp)
if (tm == NULL)
return (NULL);
tp = &tm->tcb;
+
+ /* Initialise cc_var struct for this tcpcb. */
+ tp->ccv = &tm->ccv;
+ tp->ccv->type = IPPROTO_TCP;
+ tp->ccv->ccvc.tcp = tp;
+
+ /*
+ * Use the current system default CC algorithm.
+ */
+ CC_LIST_RLOCK();
+ KASSERT(!STAILQ_EMPTY(&cc_list), ("cc_list is empty!"));
+ CC_ALGO(tp) = CC_DEFAULT();
+ CC_LIST_RUNLOCK();
+
+ if (CC_ALGO(tp)->cb_init != NULL)
+ if (CC_ALGO(tp)->cb_init(tp->ccv) > 0) {
+ uma_zfree(V_tcpcb_zone, tm);
+ return (NULL);
+ }
+
+ tp->osd = &tm->osd;
+ if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) {
+ uma_zfree(V_tcpcb_zone, tm);
+ return (NULL);
+ }
+
#ifdef VIMAGE
tp->t_vnet = inp->inp_vnet;
#endif
@@ -754,6 +801,69 @@ tcp_newtcpcb(struct inpcb *inp)
}
/*
+ * Switch the congestion control algorithm back to NewReno for any active
+ * control blocks using an algorithm which is about to go away.
+ * This ensures the CC framework can allow the unload to proceed without leaving
+ * any dangling pointers which would trigger a panic.
+ * Returning non-zero would inform the CC framework that something went wrong
+ * and it would be unsafe to allow the unload to proceed. However, there is no
+ * way for this to occur with this implementation so we always return zero.
+ */
+int
+tcp_ccalgounload(struct cc_algo *unload_algo)
+{
+ struct cc_algo *tmpalgo;
+ struct inpcb *inp;
+ struct tcpcb *tp;
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ /*
+ * Check all active control blocks across all network stacks and change
+ * any that are using "unload_algo" back to NewReno. If "unload_algo"
+ * requires cleanup code to be run, call it.
+ */
+ VNET_LIST_RLOCK();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ INP_INFO_RLOCK(&V_tcbinfo);
+ /*
+ * New connections already part way through being initialised
+ * with the CC algo we're removing will not race with this code
+ * because the INP_INFO_WLOCK is held during initialisation. We
+ * therefore don't enter the loop below until the connection
+ * list has stabilised.
+ */
+ LIST_FOREACH(inp, &V_tcb, inp_list) {
+ INP_WLOCK(inp);
+ /* Important to skip tcptw structs. */
+ if (!(inp->inp_flags & INP_TIMEWAIT) &&
+ (tp = intotcpcb(inp)) != NULL) {
+ /*
+ * By holding INP_WLOCK here, we are assured
+ * that the connection is not currently
+ * executing inside the CC module's functions
+ * i.e. it is safe to make the switch back to
+ * NewReno.
+ */
+ if (CC_ALGO(tp) == unload_algo) {
+ tmpalgo = CC_ALGO(tp);
+ /* NewReno does not require any init. */
+ CC_ALGO(tp) = &newreno_cc_algo;
+ if (tmpalgo->cb_destroy != NULL)
+ tmpalgo->cb_destroy(tp->ccv);
+ }
+ }
+ INP_WUNLOCK(inp);
+ }
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK();
+
+ return (0);
+}
+
+/*
* Drop a TCP connection, reporting
* the specified error. If connection is synchronized,
* then send a RST to peer.
@@ -863,6 +973,14 @@ tcp_discardcb(struct tcpcb *tp)
tcp_offload_detach(tp);
tcp_free_sackholes(tp);
+
+ /* Allow the CC algorithm to clean up after itself. */
+ if (CC_ALGO(tp)->cb_destroy != NULL)
+ CC_ALGO(tp)->cb_destroy(tp->ccv);
+
+ khelp_destroy_osd(tp->osd);
+
+ CC_ALGO(tp) = NULL;
inp->inp_ppcb = NULL;
tp->t_inpcb = NULL;
uma_zfree(V_tcpcb_zone, tp);
@@ -1135,7 +1253,8 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
return (error);
}
-SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist,
+ CTLTYPE_OPAQUE | CTLFLAG_RD, NULL, 0,
tcp_pcblist, "S,xtcpcb", "List of active TCP connections");
static int
@@ -1260,7 +1379,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
return;
if (cmd == PRC_MSGSIZE)
- notify = tcp_mtudisc;
+ notify = tcp_mtudisc_notify;
else if (V_icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
notify = tcp_drop_syn_sent;
@@ -1327,16 +1446,17 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
mtu = V_tcp_minmss
+ sizeof(struct tcpiphdr);
/*
- * Only cache the the MTU if it
+ * Only cache the MTU if it
* is smaller than the interface
* or route MTU. tcp_mtudisc()
* will do right thing by itself.
*/
if (mtu <= tcp_maxmtu(&inc, NULL))
tcp_hc_updatemtu(&inc, mtu);
- }
-
- inp = (*notify)(inp, inetctlerrmap[cmd]);
+ tcp_mtudisc(inp, mtu);
+ } else
+ inp = (*notify)(inp,
+ inetctlerrmap[cmd]);
}
}
if (inp != NULL)
@@ -1375,7 +1495,7 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
return;
if (cmd == PRC_MSGSIZE)
- notify = tcp_mtudisc;
+ notify = tcp_mtudisc_notify;
else if (!PRC_IS_REDIRECT(cmd) &&
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
return;
@@ -1594,12 +1714,19 @@ tcp_drop_syn_sent(struct inpcb *inp, int errno)
/*
* When `need fragmentation' ICMP is received, update our idea of the MSS
- * based on the new value in the route. Also nudge TCP to send something,
- * since we know the packet we just sent was dropped.
+ * based on the new value. Also nudge TCP to send something, since we
+ * know the packet we just sent was dropped.
* This duplicates some code in the tcp_mss() function in tcp_input.c.
*/
+static struct inpcb *
+tcp_mtudisc_notify(struct inpcb *inp, int error)
+{
+
+ return (tcp_mtudisc(inp, -1));
+}
+
struct inpcb *
-tcp_mtudisc(struct inpcb *inp, int errno)
+tcp_mtudisc(struct inpcb *inp, int mtuoffer)
{
struct tcpcb *tp;
struct socket *so;
@@ -1612,7 +1739,7 @@ tcp_mtudisc(struct inpcb *inp, int errno)
tp = intotcpcb(inp);
KASSERT(tp != NULL, ("tcp_mtudisc: tp == NULL"));
- tcp_mss_update(tp, -1, NULL, NULL);
+ tcp_mss_update(tp, -1, mtuoffer, NULL, NULL);
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_snd);
@@ -1627,7 +1754,7 @@ tcp_mtudisc(struct inpcb *inp, int errno)
tcp_free_sackholes(tp);
tp->snd_recover = tp->snd_max;
if (tp->t_flags & TF_SACK_PERMIT)
- EXIT_FASTRECOVERY(tp);
+ EXIT_FASTRECOVERY(tp->t_flags);
tcp_output_send(tp);
return (inp);
}
@@ -1689,7 +1816,7 @@ tcp_maxmtu6(struct in_conninfo *inc, int *flags)
sro6.ro_dst.sin6_family = AF_INET6;
sro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
sro6.ro_dst.sin6_addr = inc->inc6_faddr;
- rtalloc_ign((struct route *)&sro6, 0);
+ in6_rtalloc_ign(&sro6, 0, inc->inc_fibnum);
}
if (sro6.ro_rt != NULL) {
ifp = sro6.ro_rt->rt_ifp;
@@ -2090,6 +2217,66 @@ tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
KEY_FREESAV(&sav);
return (0);
}
+
+/*
+ * Verify the TCP-MD5 hash of a TCP segment. (RFC2385)
+ *
+ * Parameters:
+ * m pointer to head of mbuf chain
+ * len length of TCP segment data, excluding options
+ * optlen length of TCP segment options
+ * buf pointer to storage for computed MD5 digest
+ * direction direction of flow (IPSEC_DIR_INBOUND or OUTBOUND)
+ *
+ * Return 1 if successful, otherwise return 0.
+ */
+int
+tcp_signature_verify(struct mbuf *m, int off0, int tlen, int optlen,
+ struct tcpopt *to, struct tcphdr *th, u_int tcpbflag)
+{
+ char tmpdigest[TCP_SIGLEN];
+
+ if (tcp_sig_checksigs == 0)
+ return (1);
+ if ((tcpbflag & TF_SIGNATURE) == 0) {
+ if ((to->to_flags & TOF_SIGNATURE) != 0) {
+
+ /*
+ * If this socket is not expecting signature but
+ * the segment contains signature just fail.
+ */
+ TCPSTAT_INC(tcps_sig_err_sigopt);
+ TCPSTAT_INC(tcps_sig_rcvbadsig);
+ return (0);
+ }
+
+ /* Signature is not expected, and not present in segment. */
+ return (1);
+ }
+
+ /*
+ * If this socket is expecting signature but the segment does not
+ * contain any just fail.
+ */
+ if ((to->to_flags & TOF_SIGNATURE) == 0) {
+ TCPSTAT_INC(tcps_sig_err_nosigopt);
+ TCPSTAT_INC(tcps_sig_rcvbadsig);
+ return (0);
+ }
+ if (tcp_signature_compute(m, off0, tlen, optlen, &tmpdigest[0],
+ IPSEC_DIR_INBOUND) == -1) {
+ TCPSTAT_INC(tcps_sig_err_buildsig);
+ TCPSTAT_INC(tcps_sig_rcvbadsig);
+ return (0);
+ }
+
+ if (bcmp(to->to_signature, &tmpdigest[0], TCP_SIGLEN) != 0) {
+ TCPSTAT_INC(tcps_sig_rcvbadsig);
+ return (0);
+ }
+ TCPSTAT_INC(tcps_sig_rcvgoodsig);
+ return (1);
+}
#endif /* TCP_SIGNATURE */
static int
diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c
index 4dc1208f..46b8414c 100644
--- a/freebsd/sys/netinet/tcp_syncache.c
+++ b/freebsd/sys/netinet/tcp_syncache.c
@@ -150,23 +150,23 @@ static VNET_DEFINE(struct tcp_syncache, tcp_syncache);
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, syncache, CTLFLAG_RW, 0, "TCP SYN cache");
-SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, bucketlimit, CTLFLAG_RDTUN,
+SYSCTL_VNET_UINT(_net_inet_tcp_syncache, OID_AUTO, bucketlimit, CTLFLAG_RDTUN,
&VNET_NAME(tcp_syncache.bucket_limit), 0,
"Per-bucket hash limit for syncache");
-SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, cachelimit, CTLFLAG_RDTUN,
+SYSCTL_VNET_UINT(_net_inet_tcp_syncache, OID_AUTO, cachelimit, CTLFLAG_RDTUN,
&VNET_NAME(tcp_syncache.cache_limit), 0,
"Overall entry limit for syncache");
-SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, count, CTLFLAG_RD,
+SYSCTL_VNET_UINT(_net_inet_tcp_syncache, OID_AUTO, count, CTLFLAG_RD,
&VNET_NAME(tcp_syncache.cache_count), 0,
"Current number of entries in syncache");
-SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, hashsize, CTLFLAG_RDTUN,
+SYSCTL_VNET_UINT(_net_inet_tcp_syncache, OID_AUTO, hashsize, CTLFLAG_RDTUN,
&VNET_NAME(tcp_syncache.hashsize), 0,
"Size of TCP syncache hashtable");
-SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, rexmtlimit, CTLFLAG_RW,
+SYSCTL_VNET_UINT(_net_inet_tcp_syncache, OID_AUTO, rexmtlimit, CTLFLAG_RW,
&VNET_NAME(tcp_syncache.rexmt_limit), 0,
"Limit on SYN/ACK retransmissions");
@@ -526,7 +526,7 @@ syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th)
* used, or we are under memory pressure, a valid RST
* may not find a syncache entry. In that case we're
* done and no SYN|ACK retransmissions will happen.
- * Otherwise the the RST was misdirected or spoofed.
+ * Otherwise the RST was misdirected or spoofed.
*/
if (sc == NULL) {
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
@@ -814,7 +814,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
if (sc->sc_flags & SCF_TIMESTAMP) {
tp->t_flags |= TF_REQ_TSTMP|TF_RCVD_TSTMP;
tp->ts_recent = sc->sc_tsreflect;
- tp->ts_recent_age = ticks;
+ tp->ts_recent_age = tcp_ts_getticks();
tp->ts_offset = sc->sc_tsoff;
}
#ifdef TCP_SIGNATURE
@@ -1023,7 +1023,8 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
struct syncache_head *sch;
struct mbuf *ipopts = NULL;
u_int32_t flowtmp;
- int win, sb_hiwat, ip_ttl, ip_tos, noopt;
+ u_int ltflags;
+ int win, sb_hiwat, ip_ttl, ip_tos;
char *s;
#ifdef INET6
int autoflowlabel = 0;
@@ -1056,7 +1057,7 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
ip_tos = inp->inp_ip_tos;
win = sbspace(&so->so_rcv);
sb_hiwat = so->so_rcv.sb_hiwat;
- noopt = (tp->t_flags & TF_NOOPT);
+ ltflags = (tp->t_flags & (TF_NOOPT | TF_SIGNATURE));
/* By the time we drop the lock these should no longer be used. */
so = NULL;
@@ -1208,7 +1209,7 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*/
if (to->to_flags & TOF_TS) {
sc->sc_tsreflect = to->to_tsval;
- sc->sc_ts = ticks;
+ sc->sc_ts = tcp_ts_getticks();
sc->sc_flags |= SCF_TIMESTAMP;
}
if (to->to_flags & TOF_SCALE) {
@@ -1251,14 +1252,14 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* XXX: Currently we always record the option by default and will
* attempt to use it in syncache_respond().
*/
- if (to->to_flags & TOF_SIGNATURE)
+ if (to->to_flags & TOF_SIGNATURE || ltflags & TF_SIGNATURE)
sc->sc_flags |= SCF_SIGNATURE;
#endif
if (to->to_flags & TOF_SACKPERM)
sc->sc_flags |= SCF_SACK;
if (to->to_flags & TOF_MSS)
sc->sc_peer_mss = to->to_mss; /* peer mss may be zero */
- if (noopt)
+ if (ltflags & TF_NOOPT)
sc->sc_flags |= SCF_NOOPT;
if ((th->th_flags & (TH_ECE|TH_CWR)) && V_tcp_do_ecn)
sc->sc_flags |= SCF_ECN;
@@ -1639,7 +1640,7 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc,
data |= md5_buffer[2] << 10; /* more digest bits */
data ^= md5_buffer[3];
sc->sc_ts = data;
- sc->sc_tsoff = data - ticks; /* after XOR */
+ sc->sc_tsoff = data - tcp_ts_getticks(); /* after XOR */
}
TCPSTAT_INC(tcps_sc_sendcookie);
@@ -1724,7 +1725,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
sc->sc_flags |= SCF_TIMESTAMP;
sc->sc_tsreflect = to->to_tsval;
sc->sc_ts = to->to_tsecr;
- sc->sc_tsoff = to->to_tsecr - ticks;
+ sc->sc_tsoff = to->to_tsecr - tcp_ts_getticks();
sc->sc_flags |= (data & 0x1) ? SCF_SIGNATURE : 0;
sc->sc_flags |= ((data >> 1) & 0x1) ? SCF_SACK : 0;
sc->sc_requested_s_scale = min((data >> 2) & 0xf,
diff --git a/freebsd/sys/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c
index cbf9206f..4fe0645a 100644
--- a/freebsd/sys/netinet/tcp_timer.c
+++ b/freebsd/sys/netinet/tcp_timer.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <net/route.h>
#include <net/vnet.h>
+#include <netinet/cc.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_systm.h>
@@ -59,7 +60,6 @@ __FBSDID("$FreeBSD$");
#include <netinet6/in6_pcb.h>
#endif
#include <netinet/ip_var.h>
-#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
@@ -119,6 +119,11 @@ int tcp_maxpersistidle;
/* max idle time in persist */
int tcp_maxidle;
+static int tcp_rexmit_drop_options = 1;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW,
+ &tcp_rexmit_drop_options, 0,
+ "Drop TCP options from 3rd and later retransmitted SYN");
+
/*
* Tcp protocol timeout routine called every 500 ms.
* Updates timestamps used for TCP
@@ -178,13 +183,18 @@ tcp_timer_delack(void *xtp)
return;
}
INP_WLOCK(inp);
- if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_delack)
- || !callout_active(&tp->t_timers->tt_delack)) {
+ if (callout_pending(&tp->t_timers->tt_delack) ||
+ !callout_active(&tp->t_timers->tt_delack)) {
INP_WUNLOCK(inp);
CURVNET_RESTORE();
return;
}
callout_deactivate(&tp->t_timers->tt_delack);
+ if ((inp->inp_flags & INP_DROPPED) != 0) {
+ INP_WUNLOCK(inp);
+ CURVNET_RESTORE();
+ return;
+ }
tp->t_flags |= TF_ACKNOW;
TCPSTAT_INC(tcps_delack);
@@ -224,7 +234,7 @@ tcp_timer_2msl(void *xtp)
}
INP_WLOCK(inp);
tcp_free_sackholes(tp);
- if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_2msl) ||
+ if (callout_pending(&tp->t_timers->tt_2msl) ||
!callout_active(&tp->t_timers->tt_2msl)) {
INP_WUNLOCK(tp->t_inpcb);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -232,6 +242,12 @@ tcp_timer_2msl(void *xtp)
return;
}
callout_deactivate(&tp->t_timers->tt_2msl);
+ if ((inp->inp_flags & INP_DROPPED) != 0) {
+ INP_WUNLOCK(inp);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+ CURVNET_RESTORE();
+ return;
+ }
/*
* 2 MSL timeout in shutdown went off. If we're closed but
* still waiting for peer to close and connection has been idle
@@ -295,14 +311,20 @@ tcp_timer_keep(void *xtp)
return;
}
INP_WLOCK(inp);
- if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_keep)
- || !callout_active(&tp->t_timers->tt_keep)) {
+ if (callout_pending(&tp->t_timers->tt_keep) ||
+ !callout_active(&tp->t_timers->tt_keep)) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
callout_deactivate(&tp->t_timers->tt_keep);
+ if ((inp->inp_flags & INP_DROPPED) != 0) {
+ INP_WUNLOCK(inp);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+ CURVNET_RESTORE();
+ return;
+ }
/*
* Keep-alive timer went off; send something
* or drop connection if idle for too long.
@@ -390,14 +412,20 @@ tcp_timer_persist(void *xtp)
return;
}
INP_WLOCK(inp);
- if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_persist)
- || !callout_active(&tp->t_timers->tt_persist)) {
+ if (callout_pending(&tp->t_timers->tt_persist) ||
+ !callout_active(&tp->t_timers->tt_persist)) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
callout_deactivate(&tp->t_timers->tt_persist);
+ if ((inp->inp_flags & INP_DROPPED) != 0) {
+ INP_WUNLOCK(inp);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+ CURVNET_RESTORE();
+ return;
+ }
/*
* Persistance timer into zero window.
* Force a byte to be output, if possible.
@@ -463,14 +491,20 @@ tcp_timer_rexmt(void * xtp)
return;
}
INP_WLOCK(inp);
- if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_rexmt)
- || !callout_active(&tp->t_timers->tt_rexmt)) {
+ if (callout_pending(&tp->t_timers->tt_rexmt) ||
+ !callout_active(&tp->t_timers->tt_rexmt)) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
callout_deactivate(&tp->t_timers->tt_rexmt);
+ if ((inp->inp_flags & INP_DROPPED) != 0) {
+ INP_WUNLOCK(inp);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+ CURVNET_RESTORE();
+ return;
+ }
tcp_free_sackholes(tp);
/*
* Retransmission timer went off. Message has not
@@ -499,12 +533,18 @@ tcp_timer_rexmt(void * xtp)
tp->snd_cwnd_prev = tp->snd_cwnd;
tp->snd_ssthresh_prev = tp->snd_ssthresh;
tp->snd_recover_prev = tp->snd_recover;
- if (IN_FASTRECOVERY(tp))
- tp->t_flags |= TF_WASFRECOVERY;
+ if (IN_FASTRECOVERY(tp->t_flags))
+ tp->t_flags |= TF_WASFRECOVERY;
else
- tp->t_flags &= ~TF_WASFRECOVERY;
+ tp->t_flags &= ~TF_WASFRECOVERY;
+ if (IN_CONGRECOVERY(tp->t_flags))
+ tp->t_flags |= TF_WASCRECOVERY;
+ else
+ tp->t_flags &= ~TF_WASCRECOVERY;
tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
- }
+ tp->t_flags |= TF_PREVVALID;
+ } else
+ tp->t_flags &= ~TF_PREVVALID;
TCPSTAT_INC(tcps_rexmttimeo);
if (tp->t_state == TCPS_SYN_SENT)
rexmt = TCP_REXMTVAL(tp) * tcp_syn_backoff[tp->t_rxtshift];
@@ -513,13 +553,14 @@ tcp_timer_rexmt(void * xtp)
TCPT_RANGESET(tp->t_rxtcur, rexmt,
tp->t_rttmin, TCPTV_REXMTMAX);
/*
- * Disable rfc1323 if we havn't got any response to
+ * Disable rfc1323 if we haven't got any response to
* our third SYN to work-around some broken terminal servers
* (most of which have hopefully been retired) that have bad VJ
* header compression code which trashes TCP segments containing
* unknown-to-them TCP options.
*/
- if ((tp->t_state == TCPS_SYN_SENT) && (tp->t_rxtshift == 3))
+ if (tcp_rexmit_drop_options && (tp->t_state == TCPS_SYN_SENT) &&
+ (tp->t_rxtshift == 3))
tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP);
/*
* If we backed off this far, our srtt estimate is probably bogus.
@@ -546,40 +587,9 @@ tcp_timer_rexmt(void * xtp)
* If timing a segment in this window, stop the timer.
*/
tp->t_rtttime = 0;
- /*
- * Close the congestion window down to one segment
- * (we'll open it by one segment for each ack we get).
- * Since we probably have a window's worth of unacked
- * data accumulated, this "slow start" keeps us from
- * dumping all that data as back-to-back packets (which
- * might overwhelm an intermediate gateway).
- *
- * There are two phases to the opening: Initially we
- * open by one mss on each ack. This makes the window
- * size increase exponentially with time. If the
- * window is larger than the path can handle, this
- * exponential growth results in dropped packet(s)
- * almost immediately. To get more time between
- * drops but still "push" the network to take advantage
- * of improving conditions, we switch from exponential
- * to linear window opening at some threshhold size.
- * For a threshhold, we use half the current window
- * size, truncated to a multiple of the mss.
- *
- * (the minimum cwnd that will give us exponential
- * growth is 2 mss. We don't allow the threshhold
- * to go below this.)
- */
- {
- u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
- if (win < 2)
- win = 2;
- tp->snd_cwnd = tp->t_maxseg;
- tp->snd_ssthresh = win * tp->t_maxseg;
- tp->t_dupacks = 0;
- }
- EXIT_FASTRECOVERY(tp);
- tp->t_bytes_acked = 0;
+
+ cc_cong_signal(tp, NULL, CC_RTO);
+
(void) tcp_output(tp);
out:
diff --git a/freebsd/sys/netinet/tcp_timewait.c b/freebsd/sys/netinet/tcp_timewait.c
index de321e3f..73f3cfc9 100644
--- a/freebsd/sys/netinet/tcp_timewait.c
+++ b/freebsd/sys/netinet/tcp_timewait.c
@@ -230,7 +230,10 @@ tcp_twstart(struct tcpcb *tp)
/*
* Recover last window size sent.
*/
- tw->last_win = (tp->rcv_adv - tp->rcv_nxt) >> tp->rcv_scale;
+ if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt))
+ tw->last_win = (tp->rcv_adv - tp->rcv_nxt) >> tp->rcv_scale;
+ else
+ tw->last_win = 0;
/*
* Set t_recent if timestamps are used on the connection.
@@ -399,7 +402,7 @@ tcp_twcheck(struct inpcb *inp, struct tcpopt *to, struct tcphdr *th,
}
/*
- * Drop the the segment if it does not contain an ACK.
+ * Drop the segment if it does not contain an ACK.
*/
if ((thflags & TH_ACK) == 0)
goto drop;
@@ -534,7 +537,7 @@ tcp_twrespond(struct tcptw *tw, int flags)
*/
if (tw->t_recent && flags == TH_ACK) {
to.to_flags |= TOF_TS;
- to.to_tsval = ticks + tw->ts_offset;
+ to.to_tsval = tcp_ts_getticks() + tw->ts_offset;
to.to_tsecr = tw->t_recent;
}
optlen = tcp_addoptions(&to, (u_char *)(th + 1));
diff --git a/freebsd/sys/netinet/tcp_usrreq.c b/freebsd/sys/netinet/tcp_usrreq.c
index 3d803987..4b0e08e9 100644
--- a/freebsd/sys/netinet/tcp_usrreq.c
+++ b/freebsd/sys/netinet/tcp_usrreq.c
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
#include <net/route.h>
#include <net/vnet.h>
+#include <netinet/cc.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#ifdef INET6
@@ -79,7 +80,6 @@ __FBSDID("$FreeBSD$");
#include <netinet6/ip6_var.h>
#include <netinet6/scope6_var.h>
#endif
-#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
@@ -204,8 +204,10 @@ tcp_detach(struct socket *so, struct inpcb *inp)
tcp_discardcb(tp);
in_pcbdetach(inp);
in_pcbfree(inp);
- } else
+ } else {
in_pcbdetach(inp);
+ INP_WUNLOCK(inp);
+ }
}
}
@@ -1228,6 +1230,9 @@ tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti)
ti->tcpi_rcv_mss = tp->t_maxseg;
if (tp->t_flags & TF_TOE)
ti->tcpi_options |= TCPI_OPT_TOE;
+ ti->tcpi_snd_rexmitpack = tp->t_sndrexmitpack;
+ ti->tcpi_rcv_ooopack = tp->t_rcvoopack;
+ ti->tcpi_snd_zerowin = tp->t_sndzerowin;
}
/*
@@ -1252,6 +1257,8 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
struct inpcb *inp;
struct tcpcb *tp;
struct tcp_info ti;
+ char buf[TCP_CA_NAME_MAX];
+ struct cc_algo *algo;
error = 0;
inp = sotoinpcb(so);
@@ -1362,6 +1369,54 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
error = EINVAL;
break;
+ case TCP_CONGESTION:
+ INP_WUNLOCK(inp);
+ bzero(buf, sizeof(buf));
+ error = sooptcopyin(sopt, &buf, sizeof(buf), 1);
+ if (error)
+ break;
+ INP_WLOCK_RECHECK(inp);
+ /*
+ * Return EINVAL if we can't find the requested cc algo.
+ */
+ error = EINVAL;
+ CC_LIST_RLOCK();
+ STAILQ_FOREACH(algo, &cc_list, entries) {
+ if (strncmp(buf, algo->name, TCP_CA_NAME_MAX)
+ == 0) {
+ /* We've found the requested algo. */
+ error = 0;
+ /*
+ * We hold a write lock over the tcb
+ * so it's safe to do these things
+ * without ordering concerns.
+ */
+ if (CC_ALGO(tp)->cb_destroy != NULL)
+ CC_ALGO(tp)->cb_destroy(tp->ccv);
+ CC_ALGO(tp) = algo;
+ /*
+ * If something goes pear shaped
+ * initialising the new algo,
+ * fall back to newreno (which
+ * does not require initialisation).
+ */
+ if (algo->cb_init != NULL)
+ if (algo->cb_init(tp->ccv) > 0) {
+ CC_ALGO(tp) = &newreno_cc_algo;
+ /*
+ * The only reason init
+ * should fail is
+ * because of malloc.
+ */
+ error = ENOMEM;
+ }
+ break; /* Break the STAILQ_FOREACH. */
+ }
+ }
+ CC_LIST_RUNLOCK();
+ INP_WUNLOCK(inp);
+ break;
+
default:
INP_WUNLOCK(inp);
error = ENOPROTOOPT;
@@ -1405,6 +1460,12 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
INP_WUNLOCK(inp);
error = sooptcopyout(sopt, &ti, sizeof ti);
break;
+ case TCP_CONGESTION:
+ bzero(buf, sizeof(buf));
+ strlcpy(buf, CC_ALGO(tp)->name, TCP_CA_NAME_MAX);
+ INP_WUNLOCK(inp);
+ error = sooptcopyout(sopt, buf, TCP_CA_NAME_MAX);
+ break;
default:
INP_WUNLOCK(inp);
error = ENOPROTOOPT;
@@ -1694,10 +1755,6 @@ db_print_tflags(u_int t_flags)
db_printf("%sTF_NOPUSH", comma ? ", " : "");
comma = 1;
}
- if (t_flags & TF_NOPUSH) {
- db_printf("%sTF_NOPUSH", comma ? ", " : "");
- comma = 1;
- }
if (t_flags & TF_MORETOCOME) {
db_printf("%sTF_MORETOCOME", comma ? ", " : "");
comma = 1;
@@ -1718,6 +1775,10 @@ db_print_tflags(u_int t_flags)
db_printf("%sTF_FASTRECOVERY", comma ? ", " : "");
comma = 1;
}
+ if (t_flags & TF_CONGRECOVERY) {
+ db_printf("%sTF_CONGRECOVERY", comma ? ", " : "");
+ comma = 1;
+ }
if (t_flags & TF_WASFRECOVERY) {
db_printf("%sTF_WASFRECOVERY", comma ? ", " : "");
comma = 1;
diff --git a/freebsd/sys/netinet/tcp_var.h b/freebsd/sys/netinet/tcp_var.h
index 7e186bcd..618250cd 100644
--- a/freebsd/sys/netinet/tcp_var.h
+++ b/freebsd/sys/netinet/tcp_var.h
@@ -70,8 +70,8 @@ struct sackhole {
struct sackhint {
struct sackhole *nexthole;
int sack_bytes_rexmit;
+ tcp_seq last_sack_ack; /* Most recent/largest sacked ack */
- int ispare; /* explicit pad for 64bit alignment */
uint64_t _pad[2]; /* 1 sacked_bytes, 1 TBD */
};
@@ -196,9 +196,17 @@ struct tcpcb {
void *t_toe; /* TOE pcb pointer */
int t_bytes_acked; /* # bytes acked during current RTT */
- int t_ispare; /* explicit pad for 64bit alignment */
- void *t_pspare2[6]; /* 2 CC / 4 TBD */
- uint64_t _pad[12]; /* 7 UTO, 5 TBD (1-2 CC/RTT?) */
+ int t_sndzerowin; /* zero-window updates sent */
+
+ struct cc_algo *cc_algo; /* congestion control algorithm */
+ struct cc_var *ccv; /* congestion control specific vars */
+ struct osd *osd; /* storage for Khelp module data */
+
+ void *t_pspare2[3]; /* 3 TBD */
+ uint64_t _pad[10]; /* 7 UTO, 3 TBD (1-2 CC/RTT?) */
+
+ uint64_t t_sndrexmitpack;/* retransmit packets sent */
+ uint64_t t_rcvoopack; /* out-of-order packets received */
};
/*
@@ -217,6 +225,7 @@ struct tcpcb {
#define TF_NEEDSYN 0x000400 /* send SYN (implicit state) */
#define TF_NEEDFIN 0x000800 /* send FIN (implicit state) */
#define TF_NOPUSH 0x001000 /* don't push */
+#define TF_PREVVALID 0x002000 /* saved values for bad rxmit valid */
#define TF_MORETOCOME 0x010000 /* More data to be appended to sock */
#define TF_LQ_OVERFLOW 0x020000 /* listen queue overflow */
#define TF_LASTIDLE 0x040000 /* connection was previously idle */
@@ -230,10 +239,22 @@ struct tcpcb {
#define TF_ECN_PERMIT 0x4000000 /* connection ECN-ready */
#define TF_ECN_SND_CWR 0x8000000 /* ECN CWR in queue */
#define TF_ECN_SND_ECE 0x10000000 /* ECN ECE in queue */
+#define TF_CONGRECOVERY 0x20000000 /* congestion recovery mode */
+#define TF_WASCRECOVERY 0x40000000 /* was in congestion recovery */
+
+#define IN_FASTRECOVERY(t_flags) (t_flags & TF_FASTRECOVERY)
+#define ENTER_FASTRECOVERY(t_flags) t_flags |= TF_FASTRECOVERY
+#define EXIT_FASTRECOVERY(t_flags) t_flags &= ~TF_FASTRECOVERY
-#define IN_FASTRECOVERY(tp) (tp->t_flags & TF_FASTRECOVERY)
-#define ENTER_FASTRECOVERY(tp) tp->t_flags |= TF_FASTRECOVERY
-#define EXIT_FASTRECOVERY(tp) tp->t_flags &= ~TF_FASTRECOVERY
+#define IN_CONGRECOVERY(t_flags) (t_flags & TF_CONGRECOVERY)
+#define ENTER_CONGRECOVERY(t_flags) t_flags |= TF_CONGRECOVERY
+#define EXIT_CONGRECOVERY(t_flags) t_flags &= ~TF_CONGRECOVERY
+
+#define IN_RECOVERY(t_flags) (t_flags & (TF_CONGRECOVERY | TF_FASTRECOVERY))
+#define ENTER_RECOVERY(t_flags) t_flags |= (TF_CONGRECOVERY | TF_FASTRECOVERY)
+#define EXIT_RECOVERY(t_flags) t_flags &= ~(TF_CONGRECOVERY | TF_FASTRECOVERY)
+
+#define BYTES_THIS_ACK(tp, th) (th->th_ack - tp->snd_una)
/*
* Flags for the t_oobflags field.
@@ -466,7 +487,14 @@ struct tcpstat {
u_long tcps_ecn_shs; /* ECN successful handshakes */
u_long tcps_ecn_rcwnd; /* # times ECN reduced the cwnd */
- u_long _pad[12]; /* 6 UTO, 6 TBD */
+ /* TCP_SIGNATURE related stats */
+ u_long tcps_sig_rcvgoodsig; /* Total matching signature received */
+ u_long tcps_sig_rcvbadsig; /* Total bad signature received */
+ u_long tcps_sig_err_buildsig; /* Mismatching signature received */
+ u_long tcps_sig_err_sigopt; /* No signature expected by socket */
+ u_long tcps_sig_err_nosigopt; /* No signature provided by segment */
+
+ u_long _pad[7]; /* 6 UTO, 1 TBD */
};
#ifdef _KERNEL
@@ -483,6 +511,22 @@ struct tcpstat {
void kmod_tcpstat_inc(int statnum);
#define KMOD_TCPSTAT_INC(name) \
kmod_tcpstat_inc(offsetof(struct tcpstat, name) / sizeof(u_long))
+
+/*
+ * TCP specific helper hook point identifiers.
+ */
+#define HHOOK_TCP_EST_IN 0
+#define HHOOK_TCP_EST_OUT 1
+#define HHOOK_TCP_LAST HHOOK_TCP_EST_OUT
+
+struct tcp_hhook_data {
+ struct tcpcb *tp;
+ struct tcphdr *th;
+ struct tcpopt *to;
+ long len;
+ int tso;
+ tcp_seq curack;
+};
#endif
/*
@@ -553,10 +597,11 @@ VNET_DECLARE(int, tcp_mssdflt); /* XXX */
VNET_DECLARE(int, tcp_minmss);
VNET_DECLARE(int, tcp_delack_enabled);
VNET_DECLARE(int, tcp_do_rfc3390);
-VNET_DECLARE(int, tcp_do_newreno);
VNET_DECLARE(int, path_mtu_discovery);
VNET_DECLARE(int, ss_fltsz);
VNET_DECLARE(int, ss_fltsz_local);
+VNET_DECLARE(int, tcp_do_rfc3465);
+VNET_DECLARE(int, tcp_abc_l_var);
#define V_tcb VNET(tcb)
#define V_tcbinfo VNET(tcbinfo)
#define V_tcpstat VNET(tcpstat)
@@ -564,10 +609,11 @@ VNET_DECLARE(int, ss_fltsz_local);
#define V_tcp_minmss VNET(tcp_minmss)
#define V_tcp_delack_enabled VNET(tcp_delack_enabled)
#define V_tcp_do_rfc3390 VNET(tcp_do_rfc3390)
-#define V_tcp_do_newreno VNET(tcp_do_newreno)
#define V_path_mtu_discovery VNET(path_mtu_discovery)
#define V_ss_fltsz VNET(ss_fltsz)
#define V_ss_fltsz_local VNET(ss_fltsz_local)
+#define V_tcp_do_rfc3465 VNET(tcp_do_rfc3465)
+#define V_tcp_abc_l_var VNET(tcp_abc_l_var)
VNET_DECLARE(int, tcp_do_sack); /* SACK enabled/disabled */
VNET_DECLARE(int, tcp_sc_rst_sock_fail); /* RST on sock alloc failure */
@@ -579,7 +625,11 @@ VNET_DECLARE(int, tcp_ecn_maxretries);
#define V_tcp_do_ecn VNET(tcp_do_ecn)
#define V_tcp_ecn_maxretries VNET(tcp_ecn_maxretries)
+VNET_DECLARE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST + 1]);
+#define V_tcp_hhh VNET(tcp_hhh)
+
int tcp_addoptions(struct tcpopt *, u_char *);
+int tcp_ccalgounload(struct cc_algo *unload_algo);
struct tcpcb *
tcp_close(struct tcpcb *);
void tcp_discardcb(struct tcpcb *);
@@ -611,7 +661,8 @@ void tcp_reass_destroy(void);
void tcp_input(struct mbuf *, int);
u_long tcp_maxmtu(struct in_conninfo *, int *);
u_long tcp_maxmtu6(struct in_conninfo *, int *);
-void tcp_mss_update(struct tcpcb *, int, struct hc_metrics_lite *, int *);
+void tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *,
+ int *);
void tcp_mss(struct tcpcb *, int);
int tcp_mssopt(struct in_conninfo *);
struct inpcb *
@@ -634,6 +685,8 @@ int tcp_twrespond(struct tcptw *, int);
void tcp_setpersist(struct tcpcb *);
#ifdef TCP_SIGNATURE
int tcp_signature_compute(struct mbuf *, int, int, int, u_char *, u_int);
+int tcp_signature_verify(struct mbuf *, int, int, int, struct tcpopt *,
+ struct tcphdr *, u_int);
#endif
void tcp_slowtimo(void);
struct tcptemp *
@@ -670,6 +723,8 @@ void tcp_free_sackholes(struct tcpcb *tp);
int tcp_newreno(struct tcpcb *, struct tcphdr *);
u_long tcp_seq_subtract(u_long, u_long );
+void cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type);
+
#endif /* _KERNEL */
#endif /* _NETINET_TCP_VAR_H_ */
diff --git a/freebsd/sys/netinet/udp.h b/freebsd/sys/netinet/udp.h
index 6841683f..5ec55970 100644
--- a/freebsd/sys/netinet/udp.h
+++ b/freebsd/sys/netinet/udp.h
@@ -48,8 +48,10 @@ struct udphdr {
/*
* User-settable options (used with setsockopt).
*/
-#define UDP_ENCAP 0x01
+#define UDP_ENCAP 1
+/* Start of reserved space for third-party user-settable options. */
+#define UDP_VENDOR SO_VENDOR
/*
* UDP Encapsulation of IPsec Packets options.
diff --git a/freebsd/sys/netinet/udp_usrreq.c b/freebsd/sys/netinet/udp_usrreq.c
index d47ffdaf..87cb13fc 100644
--- a/freebsd/sys/netinet/udp_usrreq.c
+++ b/freebsd/sys/netinet/udp_usrreq.c
@@ -106,9 +106,9 @@ __FBSDID("$FreeBSD$");
* packets that would otherwise be discarded due to bad checksums, and may
* cause problems (especially for NFS data blocks).
*/
-static int udp_cksum = 1;
-SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW, &udp_cksum,
- 0, "compute udp checksum");
+VNET_DEFINE(int, udp_cksum) = 1;
+SYSCTL_VNET_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
+ &VNET_NAME(udp_cksum), 0, "compute udp checksum");
int udp_log_in_vain = 0;
SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
@@ -501,6 +501,15 @@ udp_input(struct mbuf *m, int off)
INP_RLOCK(inp);
/*
+ * Detached PCBs can linger in the list if someone
+ * holds a reference. (e.g. udp_pcblist)
+ */
+ if (inp->inp_socket == NULL) {
+ INP_RUNLOCK(inp);
+ continue;
+ }
+
+ /*
* Handle socket delivery policy for any-source
* and source-specific multicast. [RFC3678]
*/
@@ -626,6 +635,15 @@ udp_input(struct mbuf *m, int off)
*/
INP_RLOCK(inp);
INP_INFO_RUNLOCK(&V_udbinfo);
+
+ /*
+ * Detached PCBs can linger in the hash table if someone holds a
+ * reference. (e.g. udp_pcblist)
+ */
+ if (inp->inp_socket == NULL) {
+ INP_RUNLOCK(inp);
+ goto badunlocked;
+ }
if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) {
INP_RUNLOCK(inp);
goto badunlocked;
@@ -826,7 +844,8 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
return (error);
}
-SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
+SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist,
+ CTLTYPE_OPAQUE | CTLFLAG_RD, NULL, 0,
udp_pcblist, "S,xinpcb", "List of active UDP sockets");
static int
@@ -975,6 +994,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
int ipflags;
u_short fport, lport;
int unlock_udbinfo;
+ u_char tos;
/*
* udp_output() may need to temporarily bind or connect the current
@@ -990,6 +1010,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
}
src.sin_family = 0;
+ tos = inp->inp_ip_tos;
if (control != NULL) {
/*
* XXX: Currently, we assume all the optional information is
@@ -1027,6 +1048,14 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
*(struct in_addr *)CMSG_DATA(cm);
break;
+ case IP_TOS:
+ if (cm->cmsg_len != CMSG_LEN(sizeof(u_char))) {
+ error = EINVAL;
+ break;
+ }
+ tos = *(u_char *)CMSG_DATA(cm);
+ break;
+
default:
error = ENOPROTOOPT;
break;
@@ -1233,7 +1262,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
/*
* Set up checksum and output datagram.
*/
- if (udp_cksum) {
+ if (V_udp_cksum) {
if (inp->inp_flags & INP_ONESBCAST)
faddr.s_addr = INADDR_BROADCAST;
ui->ui_sum = in_pseudo(ui->ui_src.s_addr, faddr.s_addr,
@@ -1244,7 +1273,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
ui->ui_sum = 0;
((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
- ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
+ ((struct ip *)ui)->ip_tos = tos; /* XXX */
UDPSTAT_INC(udps_opackets);
if (unlock_udbinfo == 2)
diff --git a/freebsd/sys/netinet/udp_var.h b/freebsd/sys/netinet/udp_var.h
index 947400b1..5cf7dc9f 100644
--- a/freebsd/sys/netinet/udp_var.h
+++ b/freebsd/sys/netinet/udp_var.h
@@ -140,8 +140,10 @@ VNET_DECLARE(struct inpcbinfo, udbinfo);
extern u_long udp_sendspace;
extern u_long udp_recvspace;
+VNET_DECLARE(int, udp_cksum);
VNET_DECLARE(struct udpstat, udpstat);
VNET_DECLARE(int, udp_blackhole);
+#define V_udp_cksum VNET(udp_cksum)
#define V_udpstat VNET(udpstat)
#define V_udp_blackhole VNET(udp_blackhole)
extern int udp_log_in_vain;
diff --git a/freebsd/sys/netinet6/frag6.c b/freebsd/sys/netinet6/frag6.c
index 391f2a78..f176ffb6 100644
--- a/freebsd/sys/netinet6/frag6.c
+++ b/freebsd/sys/netinet6/frag6.c
@@ -223,6 +223,19 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
/* offset now points to data portion */
offset += sizeof(struct ip6_frag);
+ /*
+ * XXX-BZ RFC XXXX (draft-gont-6man-ipv6-atomic-fragments)
+ * Handle "atomic" fragments (offset and m bit set to 0) upfront,
+ * unrelated to any reassembly. Just skip the fragment header.
+ */
+ if ((ip6f->ip6f_offlg & ~IP6F_RESERVED_MASK) == 0) {
+ /* XXX-BZ we want dedicated counters for this. */
+ V_ip6stat.ip6s_reassembled++;
+ in6_ifstat_inc(dstifp, ifs6_reass_ok);
+ *offp = offset;
+ return (ip6f->ip6f_nxt);
+ }
+
IP6Q_LOCK();
/*
diff --git a/freebsd/sys/netinet6/icmp6.c b/freebsd/sys/netinet6/icmp6.c
index 54758cd4..f73dee04 100644
--- a/freebsd/sys/netinet6/icmp6.c
+++ b/freebsd/sys/netinet6/icmp6.c
@@ -361,7 +361,7 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
- M_PREPEND(m, preplen, M_DONTWAIT);
+ M_PREPEND(m, preplen, M_DONTWAIT); /* FIB is also copied over. */
if (m && m->m_len < preplen)
m = m_pullup(m, preplen);
if (m == NULL) {
@@ -583,7 +583,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
MGETHDR(n, M_DONTWAIT, n0->m_type);
n0len = n0->m_pkthdr.len; /* save for use below */
if (n)
- M_MOVE_PKTHDR(n, n0);
+ M_MOVE_PKTHDR(n, n0); /* FIB copied. */
if (n && maxlen >= MHLEN) {
MCLGET(n, M_DONTWAIT);
if ((n->m_flags & M_EXT) == 0) {
@@ -1429,7 +1429,7 @@ ni6_input(struct mbuf *m, int off)
m_freem(m);
return (NULL);
}
- M_MOVE_PKTHDR(n, m); /* just for recvif */
+ M_MOVE_PKTHDR(n, m); /* just for recvif and FIB */
if (replylen > MHLEN) {
if (replylen > MCLBYTES) {
/*
@@ -1711,9 +1711,9 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
}
IFNET_RLOCK_NOSLEEP();
- for (ifp = TAILQ_FIRST(&V_ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
+ TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
addrsofif = 0;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -1764,7 +1764,7 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
}
addrsofif++; /* count the address */
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (iffound) {
*ifpp = ifp;
IFNET_RUNLOCK_NOSLEEP();
@@ -1782,7 +1782,7 @@ static int
ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
struct ifnet *ifp0, int resid)
{
- struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&V_ifnet);
+ struct ifnet *ifp;
struct in6_ifaddr *ifa6;
struct ifaddr *ifa;
struct ifnet *ifp_dep = NULL;
@@ -1795,10 +1795,11 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
return (0); /* needless to copy */
IFNET_RLOCK_NOSLEEP();
+ ifp = ifp0 ? ifp0 : TAILQ_FIRST(&V_ifnet);
again:
for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -1853,7 +1854,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
/* now we can copy the address */
if (resid < sizeof(struct in6_addr) +
sizeof(u_int32_t)) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/*
* We give up much more copy.
* Set the truncate flag and return.
@@ -1900,7 +1901,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
copied += (sizeof(struct in6_addr) + sizeof(u_int32_t));
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (ifp0) /* we need search only on the specified IF */
break;
}
@@ -2175,10 +2176,6 @@ icmp6_reflect(struct mbuf *m, size_t off)
}
}
- if ((srcp != NULL) &&
- (in6_addrscope(srcp) != in6_addrscope(&ip6->ip6_src)))
- srcp = NULL;
-
if (srcp == NULL) {
int e;
struct sockaddr_in6 sin6;
@@ -2284,8 +2281,6 @@ icmp6_redirect_input(struct mbuf *m, int off)
int icmp6len = ntohs(ip6->ip6_plen);
char *lladdr = NULL;
int lladdrlen = 0;
- u_char *redirhdr = NULL;
- int redirhdrlen = 0;
struct rtentry *rt = NULL;
int is_router;
int is_onlink;
@@ -2351,7 +2346,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
- rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
+ rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL, RT_DEFAULT_FIB);
if (rt) {
if (rt->rt_gateway == NULL ||
rt->rt_gateway->sa_family != AF_INET6) {
@@ -2421,11 +2416,6 @@ icmp6_redirect_input(struct mbuf *m, int off)
lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
}
- if (ndopts.nd_opts_rh) {
- redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
- redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
- }
-
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
nd6log((LOG_INFO,
"icmp6_redirect_input: lladdrlen mismatch for %s "
@@ -2445,6 +2435,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
struct sockaddr_in6 sdst;
struct sockaddr_in6 sgw;
struct sockaddr_in6 ssrc;
+ u_int fibnum;
bzero(&sdst, sizeof(sdst));
bzero(&sgw, sizeof(sgw));
@@ -2455,9 +2446,11 @@ icmp6_redirect_input(struct mbuf *m, int off)
bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
- rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw,
- (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST,
- (struct sockaddr *)&ssrc);
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++)
+ in6_rtredirect((struct sockaddr *)&sdst,
+ (struct sockaddr *)&sgw, (struct sockaddr *)NULL,
+ RTF_GATEWAY | RTF_HOST, (struct sockaddr *)&ssrc,
+ fibnum);
}
/* finally update cached route in each socket via pfctlinput */
{
@@ -2541,6 +2534,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
MCLGET(m, M_DONTWAIT);
if (!m)
goto fail;
+ M_SETFIB(m, rt->rt_fibnum);
m->m_pkthdr.rcvif = NULL;
m->m_len = 0;
maxlen = M_TRAILINGSPACE(m);
@@ -2620,9 +2614,9 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
struct nd_opt_hdr *nd_opt;
char *lladdr;
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_RLOCK(ifp);
ln = nd6_lookup(router_ll6, 0, ifp);
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
if (ln == NULL)
goto nolladdropt;
diff --git a/freebsd/sys/netinet6/in6.c b/freebsd/sys/netinet6/in6.c
index 5d9f85ba..a57f3975 100644
--- a/freebsd/sys/netinet6/in6.c
+++ b/freebsd/sys/netinet6/in6.c
@@ -200,6 +200,11 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
switch (cmd) {
case SIOCGETSGCNT_IN6:
case SIOCGETMIFCNT_IN6:
+ /*
+ * XXX mrt_ioctl has a 3rd, unused, FIB argument in route.c.
+ * We cannot see how that would be needed, so do not adjust the
+ * KPI blindly; more likely should clean up the IPv4 variant.
+ */
return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP);
}
@@ -341,6 +346,18 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
case SIOCGIFSTAT_ICMP6:
sa6 = &ifr->ifr_addr;
break;
+ case SIOCSIFADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFNETMASK:
+ /*
+ * Although we should pass any non-INET6 ioctl requests
+ * down to driver, we filter some legacy INET requests.
+ * Drivers trust SIOCSIFADDR et al to come from an already
+ * privileged layer, and do not perform any credentials
+ * checks or input validation.
+ */
+ return (EINVAL);
default:
sa6 = NULL;
break;
@@ -698,6 +715,169 @@ out:
}
/*
+ * Join necessary multicast groups. Factored out from in6_update_ifa().
+ * This entire work should only be done once, for the default FIB.
+ */
+static int
+in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra,
+ struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol)
+{
+ char ip6buf[INET6_ADDRSTRLEN];
+ struct sockaddr_in6 mltaddr, mltmask;
+ struct in6_addr llsol;
+ struct in6_multi_mship *imm;
+ struct rtentry *rt;
+ int delay, error;
+
+ KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__));
+
+ /* Join solicited multicast addr for new host id. */
+ bzero(&llsol, sizeof(struct in6_addr));
+ llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
+ llsol.s6_addr32[1] = 0;
+ llsol.s6_addr32[2] = htonl(1);
+ llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
+ llsol.s6_addr8[12] = 0xff;
+ if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
+ /* XXX: should not happen */
+ log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
+ goto cleanup;
+ }
+ delay = 0;
+ if ((flags & IN6_IFAUPDATE_DADDELAY)) {
+ /*
+ * We need a random delay for DAD on the address being
+ * configured. It also means delaying transmission of the
+ * corresponding MLD report to avoid report collision.
+ * [RFC 4861, Section 6.3.7]
+ */
+ delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
+ }
+ imm = in6_joingroup(ifp, &llsol, &error, delay);
+ if (imm == NULL) {
+ nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
+ "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &llsol),
+ if_name(ifp), error));
+ goto cleanup;
+ }
+ LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+ *in6m_sol = imm->i6mm_maddr;
+
+ bzero(&mltmask, sizeof(mltmask));
+ mltmask.sin6_len = sizeof(struct sockaddr_in6);
+ mltmask.sin6_family = AF_INET6;
+ mltmask.sin6_addr = in6mask32;
+#define MLTMASK_LEN 4 /* mltmask's masklen (=32bit=4octet) */
+
+ /*
+ * Join link-local all-nodes address.
+ */
+ bzero(&mltaddr, sizeof(mltaddr));
+ mltaddr.sin6_len = sizeof(struct sockaddr_in6);
+ mltaddr.sin6_family = AF_INET6;
+ mltaddr.sin6_addr = in6addr_linklocal_allnodes;
+ if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
+ goto cleanup; /* XXX: should not fail */
+
+ /*
+ * XXX: do we really need this automatic routes? We should probably
+ * reconsider this stuff. Most applications actually do not need the
+ * routes, since they usually specify the outgoing interface.
+ */
+ rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
+ if (rt != NULL) {
+ /* XXX: only works in !SCOPEDROUTING case. */
+ if (memcmp(&mltaddr.sin6_addr,
+ &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
+ MLTMASK_LEN)) {
+ RTFREE_LOCKED(rt);
+ rt = NULL;
+ }
+ }
+ if (rt == NULL) {
+ error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
+ (struct sockaddr *)&ia->ia_addr,
+ (struct sockaddr *)&mltmask, RTF_UP,
+ (struct rtentry **)0, RT_DEFAULT_FIB);
+ if (error)
+ goto cleanup;
+ } else
+ RTFREE_LOCKED(rt);
+
+ imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
+ if (imm == NULL) {
+ nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
+ "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
+ &mltaddr.sin6_addr), if_name(ifp), error));
+ goto cleanup;
+ }
+ LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+
+ /*
+ * Join node information group address.
+ */
+ delay = 0;
+ if ((flags & IN6_IFAUPDATE_DADDELAY)) {
+ /*
+ * The spec does not say anything about delay for this group,
+ * but the same logic should apply.
+ */
+ delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
+ }
+ if (in6_nigroup(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) {
+ /* XXX jinmei */
+ imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay);
+ if (imm == NULL)
+ nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
+ "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
+ &mltaddr.sin6_addr), if_name(ifp), error));
+ /* XXX not very fatal, go on... */
+ else
+ LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+ }
+
+ /*
+ * Join interface-local all-nodes address.
+ * (ff01::1%ifN, and ff01::%ifN/32)
+ */
+ mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
+ if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
+ goto cleanup; /* XXX: should not fail */
+ /* XXX: again, do we really need the route? */
+ rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
+ if (rt != NULL) {
+ if (memcmp(&mltaddr.sin6_addr,
+ &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
+ MLTMASK_LEN)) {
+ RTFREE_LOCKED(rt);
+ rt = NULL;
+ }
+ }
+ if (rt == NULL) {
+ error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
+ (struct sockaddr *)&ia->ia_addr,
+ (struct sockaddr *)&mltmask, RTF_UP,
+ (struct rtentry **)0, RT_DEFAULT_FIB);
+ if (error)
+ goto cleanup;
+ } else
+ RTFREE_LOCKED(rt);
+
+ imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
+ if (imm == NULL) {
+ nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
+ "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
+ &mltaddr.sin6_addr), if_name(ifp), error));
+ goto cleanup;
+ }
+ LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+#undef MLTMASK_LEN
+
+cleanup:
+ return (error);
+}
+
+/*
* Update parameters of an IPv6 interface address.
* If necessary, a new entry is created and linked into address chains.
* This function is separated from in6_control().
@@ -710,9 +890,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
int error = 0, hostIsNew = 0, plen = -1;
struct sockaddr_in6 dst6;
struct in6_addrlifetime *lt;
- struct in6_multi_mship *imm;
struct in6_multi *in6m_sol;
- struct rtentry *rt;
int delay;
char ip6buf[INET6_ADDRSTRLEN];
@@ -851,9 +1029,9 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
ia->ia_ifp = ifp;
ifa_ref(&ia->ia_ifa); /* if_addrhead */
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
ifa_ref(&ia->ia_ifa); /* in6_ifaddrhead */
IN6_IFADDR_WLOCK();
@@ -956,178 +1134,17 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
* not just go to unlink.
*/
- /* Join necessary multicast groups */
+ /* Join necessary multicast groups. */
in6m_sol = NULL;
if ((ifp->if_flags & IFF_MULTICAST) != 0) {
- struct sockaddr_in6 mltaddr, mltmask;
- struct in6_addr llsol;
-
- /* join solicited multicast addr for new host id */
- bzero(&llsol, sizeof(struct in6_addr));
- llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
- llsol.s6_addr32[1] = 0;
- llsol.s6_addr32[2] = htonl(1);
- llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
- llsol.s6_addr8[12] = 0xff;
- if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
- /* XXX: should not happen */
- log(LOG_ERR, "in6_update_ifa: "
- "in6_setscope failed\n");
+ error = in6_update_ifa_join_mc(ifp, ifra, ia, flags, &in6m_sol);
+ if (error)
goto cleanup;
- }
- delay = 0;
- if ((flags & IN6_IFAUPDATE_DADDELAY)) {
- /*
- * We need a random delay for DAD on the address
- * being configured. It also means delaying
- * transmission of the corresponding MLD report to
- * avoid report collision.
- * [draft-ietf-ipv6-rfc2462bis-02.txt]
- */
- delay = arc4random() %
- (MAX_RTR_SOLICITATION_DELAY * hz);
- }
- imm = in6_joingroup(ifp, &llsol, &error, delay);
- if (imm == NULL) {
- nd6log((LOG_WARNING,
- "in6_update_ifa: addmulti failed for "
- "%s on %s (errno=%d)\n",
- ip6_sprintf(ip6buf, &llsol), if_name(ifp),
- error));
- goto cleanup;
- }
- LIST_INSERT_HEAD(&ia->ia6_memberships,
- imm, i6mm_chain);
- in6m_sol = imm->i6mm_maddr;
-
- bzero(&mltmask, sizeof(mltmask));
- mltmask.sin6_len = sizeof(struct sockaddr_in6);
- mltmask.sin6_family = AF_INET6;
- mltmask.sin6_addr = in6mask32;
-#define MLTMASK_LEN 4 /* mltmask's masklen (=32bit=4octet) */
-
- /*
- * join link-local all-nodes address
- */
- bzero(&mltaddr, sizeof(mltaddr));
- mltaddr.sin6_len = sizeof(struct sockaddr_in6);
- mltaddr.sin6_family = AF_INET6;
- mltaddr.sin6_addr = in6addr_linklocal_allnodes;
- if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) !=
- 0)
- goto cleanup; /* XXX: should not fail */
-
- /*
- * XXX: do we really need this automatic routes?
- * We should probably reconsider this stuff. Most applications
- * actually do not need the routes, since they usually specify
- * the outgoing interface.
- */
- rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
- if (rt) {
- /* XXX: only works in !SCOPEDROUTING case. */
- if (memcmp(&mltaddr.sin6_addr,
- &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
- MLTMASK_LEN)) {
- RTFREE_LOCKED(rt);
- rt = NULL;
- }
- }
- if (!rt) {
- error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
- (struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&mltmask, RTF_UP,
- (struct rtentry **)0);
- if (error)
- goto cleanup;
- } else {
- RTFREE_LOCKED(rt);
- }
-
- imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
- if (!imm) {
- nd6log((LOG_WARNING,
- "in6_update_ifa: addmulti failed for "
- "%s on %s (errno=%d)\n",
- ip6_sprintf(ip6buf, &mltaddr.sin6_addr),
- if_name(ifp), error));
- goto cleanup;
- }
- LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
-
- /*
- * join node information group address
- */
- delay = 0;
- if ((flags & IN6_IFAUPDATE_DADDELAY)) {
- /*
- * The spec doesn't say anything about delay for this
- * group, but the same logic should apply.
- */
- delay = arc4random() %
- (MAX_RTR_SOLICITATION_DELAY * hz);
- }
- if (in6_nigroup(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) {
- imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error,
- delay); /* XXX jinmei */
- if (!imm) {
- nd6log((LOG_WARNING, "in6_update_ifa: "
- "addmulti failed for %s on %s "
- "(errno=%d)\n",
- ip6_sprintf(ip6buf, &mltaddr.sin6_addr),
- if_name(ifp), error));
- /* XXX not very fatal, go on... */
- } else {
- LIST_INSERT_HEAD(&ia->ia6_memberships,
- imm, i6mm_chain);
- }
- }
-
- /*
- * join interface-local all-nodes address.
- * (ff01::1%ifN, and ff01::%ifN/32)
- */
- mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
- if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL))
- != 0)
- goto cleanup; /* XXX: should not fail */
- /* XXX: again, do we really need the route? */
- rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
- if (rt) {
- if (memcmp(&mltaddr.sin6_addr,
- &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
- MLTMASK_LEN)) {
- RTFREE_LOCKED(rt);
- rt = NULL;
- }
- }
- if (!rt) {
- error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
- (struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&mltmask, RTF_UP,
- (struct rtentry **)0);
- if (error)
- goto cleanup;
- } else
- RTFREE_LOCKED(rt);
-
- imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
- if (!imm) {
- nd6log((LOG_WARNING, "in6_update_ifa: "
- "addmulti failed for %s on %s "
- "(errno=%d)\n",
- ip6_sprintf(ip6buf, &mltaddr.sin6_addr),
- if_name(ifp), error));
- goto cleanup;
- }
- LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
-#undef MLTMASK_LEN
}
/*
* Perform DAD, if needed.
- * XXX It may be of use, if we can administratively
- * disable DAD.
+ * XXX It may be of use, if we can administratively disable DAD.
*/
if (in6if_do_dad(ifp) && ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
(ia->ia6_flags & IN6_IFF_TENTATIVE))
@@ -1185,87 +1202,29 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
return error;
}
-void
-in6_purgeaddr(struct ifaddr *ifa)
+/*
+ * Leave multicast groups. Factored out from in6_purgeaddr().
+ * This entire work should only be done once, for the default FIB.
+ */
+static int
+in6_purgeaddr_mc(struct ifnet *ifp, struct in6_ifaddr *ia, struct ifaddr *ifa0)
{
- struct ifnet *ifp = ifa->ifa_ifp;
- struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
- struct in6_multi_mship *imm;
struct sockaddr_in6 mltaddr, mltmask;
- struct rtentry rt0;
- struct sockaddr_dl gateway;
- struct sockaddr_in6 mask, addr;
- int plen, error;
+ struct in6_multi_mship *imm;
struct rtentry *rt;
- struct ifaddr *ifa0, *nifa;
-
- /*
- * find another IPv6 address as the gateway for the
- * link-local and node-local all-nodes multicast
- * address routes
- */
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH_SAFE(ifa0, &ifp->if_addrhead, ifa_link, nifa) {
- if ((ifa0->ifa_addr->sa_family != AF_INET6) ||
- memcmp(&satosin6(ifa0->ifa_addr)->sin6_addr,
- &ia->ia_addr.sin6_addr,
- sizeof(struct in6_addr)) == 0)
- continue;
- else
- break;
- }
- if (ifa0 != NULL)
- ifa_ref(ifa0);
- IF_ADDR_UNLOCK(ifp);
-
- /*
- * Remove the loopback route to the interface address.
- * The check for the current setting of "nd6_useloopback"
- * is not needed.
- */
- if (ia->ia_flags & IFA_RTSELF) {
- error = ifa_del_loopback_route((struct ifaddr *)ia,
- (struct sockaddr *)&ia->ia_addr);
- if (error == 0)
- ia->ia_flags &= ~IFA_RTSELF;
- }
-
- /* stop DAD processing */
- nd6_dad_stop(ifa);
-
- IF_AFDATA_LOCK(ifp);
- lla_lookup(LLTABLE6(ifp), (LLE_DELETE | LLE_IFADDR),
- (struct sockaddr *)&ia->ia_addr);
- IF_AFDATA_UNLOCK(ifp);
-
- /*
- * initialize for rtmsg generation
- */
- bzero(&gateway, sizeof(gateway));
- gateway.sdl_len = sizeof(gateway);
- gateway.sdl_family = AF_LINK;
- gateway.sdl_nlen = 0;
- gateway.sdl_alen = ifp->if_addrlen;
- /* */
- bzero(&rt0, sizeof(rt0));
- rt0.rt_gateway = (struct sockaddr *)&gateway;
- memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
- memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
- rt_mask(&rt0) = (struct sockaddr *)&mask;
- rt_key(&rt0) = (struct sockaddr *)&addr;
- rt0.rt_flags = RTF_HOST | RTF_STATIC;
- rt_newaddrmsg(RTM_DELETE, ifa, 0, &rt0);
+ struct sockaddr_in6 sin6;
+ int error;
/*
- * leave from multicast groups we have joined for the interface
+ * Leave from multicast groups we have joined for the interface.
*/
- while ((imm = ia->ia6_memberships.lh_first) != NULL) {
+ while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
LIST_REMOVE(imm, i6mm_chain);
in6_leavegroup(imm);
}
/*
- * remove the link-local all-nodes address
+ * Remove the link-local all-nodes address.
*/
bzero(&mltmask, sizeof(mltmask));
mltmask.sin6_len = sizeof(struct sockaddr_in6);
@@ -1277,43 +1236,51 @@ in6_purgeaddr(struct ifaddr *ifa)
mltaddr.sin6_family = AF_INET6;
mltaddr.sin6_addr = in6addr_linklocal_allnodes;
- if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) !=
- 0)
- goto cleanup;
+ if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
+ return (error);
- rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
+ /*
+ * As for the mltaddr above, proactively prepare the sin6 to avoid
+ * rtentry un- and re-locking.
+ */
+ if (ifa0 != NULL) {
+ bzero(&sin6, sizeof(sin6));
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+ memcpy(&sin6.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
+ sizeof(sin6.sin6_addr));
+ error = in6_setscope(&sin6.sin6_addr, ifa0->ifa_ifp, NULL);
+ if (error != 0)
+ return (error);
+ }
+
+ rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
if (rt != NULL && rt->rt_gateway != NULL &&
(memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
&ia->ia_addr.sin6_addr,
sizeof(ia->ia_addr.sin6_addr)) == 0)) {
/*
- * if no more IPv6 address exists on this interface
- * then remove the multicast address route
+ * If no more IPv6 address exists on this interface then
+ * remove the multicast address route.
*/
if (ifa0 == NULL) {
memcpy(&mltaddr.sin6_addr, &satosin6(rt_key(rt))->sin6_addr,
sizeof(mltaddr.sin6_addr));
RTFREE_LOCKED(rt);
- error = rtrequest(RTM_DELETE, (struct sockaddr *)&mltaddr,
- (struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&mltmask, RTF_UP,
- (struct rtentry **)0);
+ error = in6_rtrequest(RTM_DELETE,
+ (struct sockaddr *)&mltaddr,
+ (struct sockaddr *)&ia->ia_addr,
+ (struct sockaddr *)&mltmask, RTF_UP,
+ (struct rtentry **)0, RT_DEFAULT_FIB);
if (error)
- log(LOG_INFO, "in6_purgeaddr: link-local all-nodes"
- "multicast address deletion error\n");
+ log(LOG_INFO, "%s: link-local all-nodes "
+ "multicast address deletion error\n",
+ __func__);
} else {
/*
- * replace the gateway of the route
+ * Replace the gateway of the route.
*/
- struct sockaddr_in6 sa;
-
- bzero(&sa, sizeof(sa));
- sa.sin6_len = sizeof(struct sockaddr_in6);
- sa.sin6_family = AF_INET6;
- memcpy(&sa.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
- sizeof(sa.sin6_addr));
- in6_setscope(&sa.sin6_addr, ifa0->ifa_ifp, NULL);
- memcpy(rt->rt_gateway, &sa, sizeof(sa));
+ memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
RTFREE_LOCKED(rt);
}
} else {
@@ -1322,48 +1289,40 @@ in6_purgeaddr(struct ifaddr *ifa)
}
/*
- * remove the node-local all-nodes address
+ * Remove the node-local all-nodes address.
*/
mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
- if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) !=
- 0)
- goto cleanup;
+ if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
+ return (error);
- rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
+ rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
if (rt != NULL && rt->rt_gateway != NULL &&
(memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
&ia->ia_addr.sin6_addr,
sizeof(ia->ia_addr.sin6_addr)) == 0)) {
/*
- * if no more IPv6 address exists on this interface
- * then remove the multicast address route
+ * If no more IPv6 address exists on this interface then
+ * remove the multicast address route.
*/
if (ifa0 == NULL) {
memcpy(&mltaddr.sin6_addr, &satosin6(rt_key(rt))->sin6_addr,
sizeof(mltaddr.sin6_addr));
RTFREE_LOCKED(rt);
- error = rtrequest(RTM_DELETE, (struct sockaddr *)&mltaddr,
- (struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&mltmask, RTF_UP,
- (struct rtentry **)0);
-
+ error = in6_rtrequest(RTM_DELETE,
+ (struct sockaddr *)&mltaddr,
+ (struct sockaddr *)&ia->ia_addr,
+ (struct sockaddr *)&mltmask, RTF_UP,
+ (struct rtentry **)0, RT_DEFAULT_FIB);
if (error)
- log(LOG_INFO, "in6_purgeaddr: node-local all-nodes"
- "multicast address deletion error\n");
+ log(LOG_INFO, "%s: node-local all-nodes"
+ "multicast address deletion error\n",
+ __func__);
} else {
/*
- * replace the gateway of the route
+ * Replace the gateway of the route.
*/
- struct sockaddr_in6 sa;
-
- bzero(&sa, sizeof(sa));
- sa.sin6_len = sizeof(struct sockaddr_in6);
- sa.sin6_family = AF_INET6;
- memcpy(&sa.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
- sizeof(sa.sin6_addr));
- in6_setscope(&sa.sin6_addr, ifa0->ifa_ifp, NULL);
- memcpy(rt->rt_gateway, &sa, sizeof(sa));
+ memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
RTFREE_LOCKED(rt);
}
} else {
@@ -1371,31 +1330,91 @@ in6_purgeaddr(struct ifaddr *ifa)
RTFREE_LOCKED(rt);
}
-cleanup:
+ return (0);
+}
+
+void
+in6_purgeaddr(struct ifaddr *ifa)
+{
+ struct ifnet *ifp = ifa->ifa_ifp;
+ struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
+ struct sockaddr_dl gateway;
+ struct sockaddr_in6 mask, addr;
+ struct rtentry rt0;
+ int plen, error;
+ struct ifaddr *ifa0;
+
+ /*
+ * find another IPv6 address as the gateway for the
+ * link-local and node-local all-nodes multicast
+ * address routes
+ */
+ IF_ADDR_RLOCK(ifp);
+ TAILQ_FOREACH(ifa0, &ifp->if_addrhead, ifa_link) {
+ if ((ifa0->ifa_addr->sa_family != AF_INET6) ||
+ memcmp(&satosin6(ifa0->ifa_addr)->sin6_addr,
+ &ia->ia_addr.sin6_addr,
+ sizeof(struct in6_addr)) == 0)
+ continue;
+ else
+ break;
+ }
+ if (ifa0 != NULL)
+ ifa_ref(ifa0);
+ IF_ADDR_RUNLOCK(ifp);
+
+ /*
+ * Remove the loopback route to the interface address.
+ * The check for the current setting of "nd6_useloopback"
+ * is not needed.
+ */
+ if (ia->ia_flags & IFA_RTSELF) {
+ error = ifa_del_loopback_route((struct ifaddr *)ia,
+ (struct sockaddr *)&ia->ia_addr);
+ if (error == 0)
+ ia->ia_flags &= ~IFA_RTSELF;
+ }
+
+ /* stop DAD processing */
+ nd6_dad_stop(ifa);
+
+ /* Remove local address entry from lltable. */
+ IF_AFDATA_LOCK(ifp);
+ lla_lookup(LLTABLE6(ifp), (LLE_DELETE | LLE_IFADDR),
+ (struct sockaddr *)&ia->ia_addr);
+ IF_AFDATA_UNLOCK(ifp);
+
+ /*
+ * initialize for rtmsg generation
+ */
+ bzero(&gateway, sizeof(gateway));
+ gateway.sdl_len = sizeof(gateway);
+ gateway.sdl_family = AF_LINK;
+ gateway.sdl_nlen = 0;
+ gateway.sdl_alen = ifp->if_addrlen;
+ /* */
+ bzero(&rt0, sizeof(rt0));
+ rt0.rt_gateway = (struct sockaddr *)&gateway;
+ memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
+ memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
+ rt_mask(&rt0) = (struct sockaddr *)&mask;
+ rt_key(&rt0) = (struct sockaddr *)&addr;
+ rt0.rt_flags = RTF_HOST | RTF_STATIC;
+ rt_newaddrmsg(RTM_DELETE, ifa, 0, &rt0);
+
+ /* Leave multicast groups. */
+ error = in6_purgeaddr_mc(ifp, ia, ifa0);
+
if (ifa0 != NULL)
ifa_free(ifa0);
plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
if ((ia->ia_flags & IFA_ROUTE) && plen == 128) {
- int error;
- struct sockaddr *dstaddr;
-
- /*
- * use the interface address if configuring an
- * interface address with a /128 prefix len
- */
- if (ia->ia_dstaddr.sin6_family == AF_INET6)
- dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
- else
- dstaddr = (struct sockaddr *)&ia->ia_addr;
-
- error = rtrequest(RTM_DELETE,
- (struct sockaddr *)dstaddr,
- (struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&ia->ia_prefixmask,
- ia->ia_flags | RTF_HOST, NULL);
+ error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags |
+ (ia->ia_dstaddr.sin6_family == AF_INET6) ? RTF_HOST : 0);
if (error != 0)
- return;
+ log(LOG_INFO, "%s: err=%d, destination address delete "
+ "failed\n", __func__, error);
ia->ia_flags &= ~IFA_ROUTE;
}
@@ -1407,9 +1426,9 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
{
int s = splnet();
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
ifa_free(&ia->ia_ifa); /* if_addrhead */
/*
@@ -1641,7 +1660,7 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
}
}
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -1662,7 +1681,9 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
break;
}
- IF_ADDR_UNLOCK(ifp);
+ if (ifa != NULL)
+ ifa_ref(ifa);
+ IF_ADDR_RUNLOCK(ifp);
if (!ifa)
return EADDRNOTAVAIL;
ia = ifa2ia6(ifa);
@@ -1674,16 +1695,20 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
error = sa6_recoverscope(
(struct sockaddr_in6 *)&iflr->addr);
- if (error != 0)
+ if (error != 0) {
+ ifa_free(ifa);
return (error);
+ }
if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
ia->ia_dstaddr.sin6_len);
error = sa6_recoverscope(
(struct sockaddr_in6 *)&iflr->dstaddr);
- if (error != 0)
+ if (error != 0) {
+ ifa_free(ifa);
return (error);
+ }
} else
bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
@@ -1691,6 +1716,7 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
iflr->flags = ia->ia6_flags; /* XXX */
+ ifa_free(ifa);
return 0;
} else {
@@ -1714,6 +1740,7 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
ia->ia_prefixmask.sin6_len);
ifra.ifra_flags = ia->ia6_flags;
+ ifa_free(ifa);
return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
ifp, td);
}
@@ -1724,8 +1751,7 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
}
/*
- * Initialize an interface's intetnet6 address
- * and routing table entry.
+ * Initialize an interface's IPv6 address and routing table entry.
*/
static int
in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
@@ -1740,13 +1766,13 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
* if this is its first address,
* and to validate the address if necessary.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
ifacount++;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
ia->ia_addr = *sin6;
@@ -1775,30 +1801,28 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
ia->ia_dstaddr.sin6_family == AF_INET6) {
int rtflags = RTF_UP | RTF_HOST;
-
- error = rtrequest(RTM_ADD,
- (struct sockaddr *)&ia->ia_dstaddr,
- (struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&ia->ia_prefixmask,
- ia->ia_flags | rtflags, NULL);
- if (error != 0)
+ error = rtinit(&ia->ia_ifa, RTM_ADD, ia->ia_flags | rtflags);
+ if (error)
return (error);
ia->ia_flags |= IFA_ROUTE;
+ /*
+ * Handle the case for ::1 .
+ */
+ if (ifp->if_flags & IFF_LOOPBACK)
+ ia->ia_flags |= IFA_RTSELF;
}
/*
* add a loopback route to self
*/
- if (!(ia->ia_flags & IFA_ROUTE)
- && (V_nd6_useloopback
- || (ifp->if_flags & IFF_LOOPBACK))) {
+ if (!(ia->ia_flags & IFA_RTSELF) && V_nd6_useloopback) {
error = ifa_add_loopback_route((struct ifaddr *)ia,
(struct sockaddr *)&ia->ia_addr);
if (error == 0)
ia->ia_flags |= IFA_RTSELF;
}
- /* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
+ /* Add local address to lltable, if necessary (ex. on p2p link). */
if (newhost) {
struct llentry *ln;
struct rtentry rt;
@@ -1806,11 +1830,7 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
struct sockaddr_in6 mask, addr;
IF_AFDATA_LOCK(ifp);
- ia->ia_ifa.ifa_rtrequest = NULL;
-
- /* XXX QL
- * we need to report rt_newaddrmsg
- */
+ ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR | LLE_EXCLUSIVE),
(struct sockaddr *)&ia->ia_addr);
IF_AFDATA_UNLOCK(ifp);
@@ -1837,6 +1857,7 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
rt_mask(&rt) = (struct sockaddr *)&mask;
rt_key(&rt) = (struct sockaddr *)&addr;
rt.rt_flags = RTF_UP | RTF_HOST | RTF_STATIC;
+ /* Announce arrival of local address to all FIBs. */
rt_newaddrmsg(RTM_ADD, &ia->ia_ifa, 0, &rt);
}
@@ -1852,7 +1873,7 @@ in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
{
struct ifaddr *ifa;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -1864,7 +1885,7 @@ in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return ((struct in6_ifaddr *)ifa);
}
@@ -1879,7 +1900,7 @@ in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
{
struct ifaddr *ifa;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -1888,7 +1909,7 @@ in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return ((struct in6_ifaddr *)ifa);
}
@@ -2091,7 +2112,7 @@ in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
* If two or more, return one which matches the dst longest.
* If none, return one of global addresses assigned other ifs.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -2125,12 +2146,10 @@ in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
}
if (besta) {
ifa_ref(&besta->ia_ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return (besta);
}
- IF_ADDR_UNLOCK(ifp);
- IN6_IFADDR_RLOCK();
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -2148,23 +2167,23 @@ in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
if (ifa != NULL)
ifa_ref(ifa);
- IN6_IFADDR_RUNLOCK();
+ IF_ADDR_RUNLOCK(ifp);
return (struct in6_ifaddr *)ifa;
}
/* use the last-resort values, that are, deprecated addresses */
if (dep[0]) {
ifa_ref((struct ifaddr *)dep[0]);
- IN6_IFADDR_RUNLOCK();
+ IF_ADDR_RUNLOCK(ifp);
return dep[0];
}
if (dep[1]) {
ifa_ref((struct ifaddr *)dep[1]);
- IN6_IFADDR_RUNLOCK();
+ IF_ADDR_RUNLOCK(ifp);
return dep[1];
}
- IN6_IFADDR_RUNLOCK();
+ IF_ADDR_RUNLOCK(ifp);
return NULL;
}
@@ -2177,7 +2196,7 @@ in6_if_up(struct ifnet *ifp)
struct ifaddr *ifa;
struct in6_ifaddr *ia;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -2193,7 +2212,7 @@ in6_if_up(struct ifnet *ifp)
arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/*
* special cases, like 6to4, are handled in in6_ifattach
@@ -2248,8 +2267,7 @@ in6_setmaxmtu(void)
struct ifnet *ifp;
IFNET_RLOCK_NOSLEEP();
- for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
- ifp = TAILQ_NEXT(ifp, if_list)) {
+ TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
/* this function can be called during ifnet initialization */
if (!ifp->if_afdata[AF_INET6])
continue;
@@ -2364,19 +2382,25 @@ in6_lltable_free(struct lltable *llt, struct llentry *lle)
static void
in6_lltable_prefix_free(struct lltable *llt,
const struct sockaddr *prefix,
- const struct sockaddr *mask)
+ const struct sockaddr *mask,
+ u_int flags)
{
const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix;
const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask;
struct llentry *lle, *next;
register int i;
+ /*
+ * (flags & LLE_STATIC) means deleting all entries
+ * including static ND6 entries
+ */
for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
if (IN6_ARE_MASKED_ADDR_EQUAL(
&((struct sockaddr_in6 *)L3_ADDR(lle))->sin6_addr,
&pfx->sin6_addr,
- &msk->sin6_addr)) {
+ &msk->sin6_addr) &&
+ ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC))) {
int canceled;
canceled = callout_drain(&lle->la_timer);
@@ -2400,8 +2424,10 @@ in6_lltable_rtcheck(struct ifnet *ifp,
KASSERT(l3addr->sa_family == AF_INET6,
("sin_family %d", l3addr->sa_family));
+ /* Our local addresses are always only installed on the default FIB. */
/* XXX rtalloc1 should take a const param */
- rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
+ rt = in6_rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0,
+ RT_DEFAULT_FIB);
if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
struct ifaddr *ifa;
/*
@@ -2594,10 +2620,8 @@ in6_domifattach(struct ifnet *ifp)
ext->scope6_id = scope6_ifattach(ifp);
ext->lltable = lltable_init(ifp, AF_INET6);
if (ext->lltable != NULL) {
- ext->lltable->llt_new = in6_lltable_new;
ext->lltable->llt_free = in6_lltable_free;
ext->lltable->llt_prefix_free = in6_lltable_prefix_free;
- ext->lltable->llt_rtcheck = in6_lltable_rtcheck;
ext->lltable->llt_lookup = in6_lltable_lookup;
ext->lltable->llt_dump = in6_lltable_dump;
}
diff --git a/freebsd/sys/netinet6/in6.h b/freebsd/sys/netinet6/in6.h
index eadfc090..7abbfa40 100644
--- a/freebsd/sys/netinet6/in6.h
+++ b/freebsd/sys/netinet6/in6.h
@@ -78,7 +78,7 @@
/*
* IPv6 port allocation rules should mirror the IPv4 rules and are controlled
- * by the the net.inet.ip.portrange sysctl tree. The following defines exist
+ * by the net.inet.ip.portrange sysctl tree. The following defines exist
* for compatibility with userland applications that need them.
*/
#if __BSD_VISIBLE
diff --git a/freebsd/sys/netinet6/in6_gif.c b/freebsd/sys/netinet6/in6_gif.c
index be915827..488a0106 100644
--- a/freebsd/sys/netinet6/in6_gif.c
+++ b/freebsd/sys/netinet6/in6_gif.c
@@ -230,6 +230,8 @@ in6_gif_output(struct ifnet *ifp,
ip6->ip6_flow &= ~htonl(0xff << 20);
ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
+ M_SETFIB(m, sc->gif_fibnum);
+
if (dst->sin6_family != sin6_dst->sin6_family ||
!IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr)) {
/* cache route doesn't match */
@@ -247,7 +249,7 @@ in6_gif_output(struct ifnet *ifp,
}
if (sc->gif_ro6.ro_rt == NULL) {
- rtalloc((struct route *)&sc->gif_ro6);
+ in6_rtalloc(&sc->gif_ro6, sc->gif_fibnum);
if (sc->gif_ro6.ro_rt == NULL) {
m_freem(m);
return ENETUNREACH;
@@ -404,7 +406,8 @@ gif_validate6(const struct ip6_hdr *ip6, struct gif_softc *sc,
sin6.sin6_addr = ip6->ip6_src;
sin6.sin6_scope_id = 0; /* XXX */
- rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
+ rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL,
+ sc->gif_fibnum);
if (!rt || rt->rt_ifp != ifp) {
#if 0
char ip6buf[INET6_ADDRSTRLEN];
diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c
index c2134c6f..bb150eb1 100644
--- a/freebsd/sys/netinet6/in6_ifattach.c
+++ b/freebsd/sys/netinet6/in6_ifattach.c
@@ -249,7 +249,7 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
static u_int8_t allone[8] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_LINK)
continue;
@@ -261,7 +261,7 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
goto found;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
@@ -273,6 +273,7 @@ found:
/* get EUI64 */
switch (ifp->if_type) {
case IFT_ETHER:
+ case IFT_L2VLAN:
case IFT_FDDI:
case IFT_ISO88025:
case IFT_ATM:
@@ -287,7 +288,7 @@ found:
/* look at IEEE802/EUI64 only */
if (addrlen != 8 && addrlen != 6) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
}
@@ -297,11 +298,11 @@ found:
* card insertion.
*/
if (bcmp(addr, allzero, addrlen) == 0) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
}
if (bcmp(addr, allone, addrlen) == 0) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
}
@@ -322,11 +323,11 @@ found:
case IFT_ARCNET:
if (addrlen != 1) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
}
if (!addr[0]) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
}
@@ -350,17 +351,17 @@ found:
* identifier source (can be renumbered).
* we don't do this.
*/
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
default:
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
}
/* sanity check: g bit must not indicate "group" */
if (EUI64_GROUP(in6)) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
}
@@ -373,11 +374,11 @@ found:
*/
if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return -1;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return 0;
}
@@ -410,7 +411,7 @@ get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
/* next, try to get it from some other hardware interface */
IFNET_RLOCK_NOSLEEP();
- for (ifp = V_ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
+ TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
if (ifp == ifp0)
continue;
if (in6_get_hw_ifid(ifp, in6) != 0)
@@ -518,12 +519,8 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
}
ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
-#ifdef DIAGNOSTIC
- if (!ia) {
- panic("ia == NULL in in6_ifattach_linklocal");
- /* NOTREACHED */
- }
-#endif
+ KASSERT(ia != NULL, ("%s: ia == NULL, ifp=%p", __func__, ifp));
+
ifa_free(&ia->ia_ifa);
/*
@@ -798,7 +795,6 @@ in6_ifdetach(struct ifnet *ifp)
struct ifaddr *ifa, *next;
struct radix_node_head *rnh;
struct rtentry *rt;
- short rtflags;
struct sockaddr_in6 sin6;
struct in6_multi_mship *imm;
@@ -824,26 +820,19 @@ in6_ifdetach(struct ifnet *ifp)
/*
* leave from multicast groups we have joined for the interface
*/
- while ((imm = ia->ia6_memberships.lh_first) != NULL) {
+ while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
LIST_REMOVE(imm, i6mm_chain);
in6_leavegroup(imm);
}
- /* remove from the routing table */
- if ((ia->ia_flags & IFA_ROUTE) &&
- (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
- rtflags = rt->rt_flags;
- RTFREE_LOCKED(rt);
- rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&ia->ia_prefixmask,
- rtflags, (struct rtentry **)0);
- }
+ /* Remove link-local from the routing table. */
+ if (ia->ia_flags & IFA_ROUTE)
+ (void)rtinit(&ia->ia_ifa, RTM_DELETE, ia->ia_flags);
/* remove from the linked list */
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
ifa_free(ifa); /* if_addrhead */
IN6_IFADDR_WLOCK();
@@ -867,7 +856,10 @@ in6_ifdetach(struct ifnet *ifp)
*/
nd6_purge(ifp);
- /* remove route to link-local allnodes multicast (ff02::1) */
+ /*
+ * Remove route to link-local allnodes multicast (ff02::1).
+ * These only get automatically installed for the default FIB.
+ */
bzero(&sin6, sizeof(sin6));
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_family = AF_INET6;
@@ -876,10 +868,11 @@ in6_ifdetach(struct ifnet *ifp)
/* XXX: should not fail */
return;
/* XXX grab lock first to avoid LOR */
- rnh = rt_tables_get_rnh(0, AF_INET6);
+ rnh = rt_tables_get_rnh(RT_DEFAULT_FIB, AF_INET6);
if (rnh != NULL) {
RADIX_NODE_HEAD_LOCK(rnh);
- rt = rtalloc1((struct sockaddr *)&sin6, 0, RTF_RNH_LOCKED);
+ rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, RTF_RNH_LOCKED,
+ RT_DEFAULT_FIB);
if (rt) {
if (rt->rt_ifp == ifp)
rtexpunge(rt);
@@ -927,8 +920,7 @@ in6_tmpaddrtimer(void *arg)
V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet);
bzero(nullbuf, sizeof(nullbuf));
- for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
- ifp = TAILQ_NEXT(ifp, if_list)) {
+ TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
ndi = ND_IFINFO(ifp);
if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
/*
@@ -959,7 +951,7 @@ in6_purgemaddrs(struct ifnet *ifp)
* We need to do this as IF_ADDR_LOCK() may be re-acquired
* by code further down.
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET6 ||
ifma->ifma_protospec == NULL)
@@ -967,7 +959,7 @@ in6_purgemaddrs(struct ifnet *ifp)
inm = (struct in6_multi *)ifma->ifma_protospec;
LIST_INSERT_HEAD(&purgeinms, inm, in6m_entry);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
LIST_FOREACH_SAFE(inm, &purgeinms, in6m_entry, tinm) {
LIST_REMOVE(inm, in6m_entry);
diff --git a/freebsd/sys/netinet6/in6_mcast.c b/freebsd/sys/netinet6/in6_mcast.c
index 4d0637aa..86162cf8 100644
--- a/freebsd/sys/netinet6/in6_mcast.c
+++ b/freebsd/sys/netinet6/in6_mcast.c
@@ -401,7 +401,7 @@ in6_mc_get(struct ifnet *ifp, const struct in6_addr *group,
* re-acquire around the call.
*/
IN6_MULTI_LOCK_ASSERT();
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
inm = in6m_lookup_locked(ifp, group);
if (inm != NULL) {
@@ -425,11 +425,11 @@ in6_mc_get(struct ifnet *ifp, const struct in6_addr *group,
* Check if a link-layer group is already associated
* with this network-layer group on the given ifnet.
*/
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
error = if_addmulti(ifp, (struct sockaddr *)&gsin6, &ifma);
if (error != 0)
return (error);
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_WLOCK(ifp);
/*
* If something other than netinet6 is occupying the link-layer
@@ -456,7 +456,7 @@ in6_mc_get(struct ifnet *ifp, const struct in6_addr *group,
goto out_locked;
}
- IF_ADDR_LOCK_ASSERT(ifp);
+ IF_ADDR_WLOCK_ASSERT(ifp);
/*
* A new in6_multi record is needed; allocate and initialize it.
@@ -488,7 +488,7 @@ in6_mc_get(struct ifnet *ifp, const struct in6_addr *group,
*pinm = inm;
out_locked:
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_WUNLOCK(ifp);
return (error);
}
@@ -1626,6 +1626,8 @@ in6p_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
* has asked for, but we always tell userland how big the
* buffer really needs to be.
*/
+ if (msfr.msfr_nsrcs > in6_mcast_maxsocksrc)
+ msfr.msfr_nsrcs = in6_mcast_maxsocksrc;
tss = NULL;
if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) {
tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs,
@@ -1715,7 +1717,7 @@ ip6_getmoptions(struct inpcb *inp, struct sockopt *sopt)
if (im6o == NULL)
optval = V_ip6_defmcasthlim;
else
- optval = im6o->im6o_multicast_loop;
+ optval = im6o->im6o_multicast_hlim;
INP_WUNLOCK(inp);
error = sooptcopyout(sopt, &optval, sizeof(u_int));
break;
@@ -1765,7 +1767,7 @@ ip6_getmoptions(struct inpcb *inp, struct sockopt *sopt)
* Returns NULL if no ifp could be found.
*/
static struct ifnet *
-in6p_lookup_mcast_ifp(const struct inpcb *in6p __unused,
+in6p_lookup_mcast_ifp(const struct inpcb *in6p,
const struct sockaddr_in6 *gsin6)
{
struct route_in6 ro6;
@@ -1781,11 +1783,8 @@ in6p_lookup_mcast_ifp(const struct inpcb *in6p __unused,
ifp = NULL;
memset(&ro6, 0, sizeof(struct route_in6));
memcpy(&ro6.ro_dst, gsin6, sizeof(struct sockaddr_in6));
-#ifdef notyet
- rtalloc_ign_fib(&ro6, 0, inp ? inp->inp_inc.inc_fibnum : 0);
-#else
- rtalloc_ign((struct route *)&ro6, 0);
-#endif
+ rtalloc_ign_fib((struct route *)&ro6, 0,
+ in6p ? in6p->inp_inc.inc_fibnum : RT_DEFAULT_FIB);
if (ro6.ro_rt != NULL) {
ifp = ro6.ro_rt->rt_ifp;
KASSERT(ifp != NULL, ("%s: null ifp", __func__));
@@ -2720,7 +2719,7 @@ sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS)
IN6_MULTI_LOCK();
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET6 ||
ifma->ifma_protospec == NULL)
@@ -2749,7 +2748,7 @@ sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
IN6_MULTI_UNLOCK();
diff --git a/freebsd/sys/netinet6/in6_pcb.c b/freebsd/sys/netinet6/in6_pcb.c
index 4a1f65c5..44783f3c 100644
--- a/freebsd/sys/netinet6/in6_pcb.c
+++ b/freebsd/sys/netinet6/in6_pcb.c
@@ -272,8 +272,11 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
inp->in6p_laddr = sin6->sin6_addr;
}
if (lport == 0) {
- if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0)
+ if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) {
+ /* Undo an address bind that may have occurred. */
+ inp->in6p_laddr = in6addr_any;
return (error);
+ }
} else {
inp->inp_lport = lport;
if (in_pcbinshash(inp) != 0) {
diff --git a/freebsd/sys/netinet6/in6_proto.c b/freebsd/sys/netinet6/in6_proto.c
index 39611537..1139c7d9 100644
--- a/freebsd/sys/netinet6/in6_proto.c
+++ b/freebsd/sys/netinet6/in6_proto.c
@@ -130,6 +130,7 @@ __FBSDID("$FreeBSD$");
/*
* TCP/IP protocol family: IP6, ICMP6, UDP, TCP.
*/
+FEATURE(inet6, "Internet Protocol version 6");
extern struct domain inet6domain;
static struct pr_usrreqs nousrreqs;
@@ -185,38 +186,29 @@ struct ip6protosw inet6sw[] = {
},
#ifdef SCTP
{
- .pr_type = SOCK_DGRAM,
- .pr_domain = &inet6domain,
- .pr_protocol = IPPROTO_SCTP,
- .pr_flags = PR_WANTRCVD,
- .pr_input = sctp6_input,
- .pr_ctlinput = sctp6_ctlinput,
- .pr_ctloutput = sctp_ctloutput,
- .pr_drain = sctp_drain,
- .pr_usrreqs = &sctp6_usrreqs
+ .pr_type = SOCK_SEQPACKET,
+ .pr_domain = &inet6domain,
+ .pr_protocol = IPPROTO_SCTP,
+ .pr_flags = PR_WANTRCVD,
+ .pr_input = sctp6_input,
+ .pr_ctlinput = sctp6_ctlinput,
+ .pr_ctloutput = sctp_ctloutput,
+ .pr_drain = sctp_drain,
+#ifndef INET /* Do not call initialization twice. */
+ .pr_init = sctp_init,
+#endif
+ .pr_usrreqs = &sctp6_usrreqs
},
{
- .pr_type = SOCK_SEQPACKET,
- .pr_domain = &inet6domain,
- .pr_protocol = IPPROTO_SCTP,
- .pr_flags = PR_WANTRCVD,
- .pr_input = sctp6_input,
- .pr_ctlinput = sctp6_ctlinput,
- .pr_ctloutput = sctp_ctloutput,
- .pr_drain = sctp_drain,
- .pr_usrreqs = &sctp6_usrreqs
-},
-
-{
- .pr_type = SOCK_STREAM,
- .pr_domain = &inet6domain,
- .pr_protocol = IPPROTO_SCTP,
- .pr_flags = PR_WANTRCVD,
- .pr_input = sctp6_input,
- .pr_ctlinput = sctp6_ctlinput,
- .pr_ctloutput = sctp_ctloutput,
- .pr_drain = sctp_drain,
- .pr_usrreqs = &sctp6_usrreqs
+ .pr_type = SOCK_STREAM,
+ .pr_domain = &inet6domain,
+ .pr_protocol = IPPROTO_SCTP,
+ .pr_flags = PR_WANTRCVD,
+ .pr_input = sctp6_input,
+ .pr_ctlinput = sctp6_ctlinput,
+ .pr_ctloutput = sctp_ctloutput,
+ .pr_drain = sctp_drain,
+ .pr_usrreqs = &sctp6_usrreqs
},
#endif /* SCTP */
{
diff --git a/freebsd/sys/netinet6/in6_rmx.c b/freebsd/sys/netinet6/in6_rmx.c
index fee58221..a4bdb3af 100644
--- a/freebsd/sys/netinet6/in6_rmx.c
+++ b/freebsd/sys/netinet6/in6_rmx.c
@@ -61,19 +61,6 @@
*
*/
-/*
- * This code does two things necessary for the enhanced TCP metrics to
- * function in a useful manner:
- * 1) It marks all non-host routes as `cloning', thus ensuring that
- * every actual reference to such a route actually gets turned
- * into a reference to a host route to the specific destination
- * requested.
- * 2) When such routes lose all their references, it arranges for them
- * to be deleted in some random collection of circumstances, so that
- * a large quantity of stale routing data is not kept in kernel memory
- * indefinitely. See in6_rtqtimo() below for the exact mechanism.
- */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -113,8 +100,6 @@ extern int in6_inithead(void **head, int off);
extern int in6_detachhead(void **head, int off);
#endif
-#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */
-
/*
* Do what we need to do when inserting a route.
*/
@@ -170,7 +155,8 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
* net route entry, 3ffe:0501:: -> if0.
* This case should not raise an error.
*/
- rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED);
+ rt2 = in6_rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED,
+ rt->rt_fibnum);
if (rt2) {
if (((rt2->rt_flags & (RTF_HOST|RTF_GATEWAY)) == 0)
&& rt2->rt_gateway
@@ -184,42 +170,8 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
return (ret);
}
-/*
- * This code is the inverse of in6_clsroute: on first reference, if we
- * were managing the route, stop doing so and set the expiration timer
- * back off again.
- */
-static struct radix_node *
-in6_matroute(void *v_arg, struct radix_node_head *head)
-{
- struct radix_node *rn = rn_match(v_arg, head);
- struct rtentry *rt = (struct rtentry *)rn;
-
- if (rt) {
- RT_LOCK(rt);
- if (rt->rt_flags & RTPRF_OURS) {
- rt->rt_flags &= ~RTPRF_OURS;
- rt->rt_rmx.rmx_expire = 0;
- }
- RT_UNLOCK(rt);
- }
- return rn;
-}
-
SYSCTL_DECL(_net_inet6_ip6);
-static VNET_DEFINE(int, rtq_reallyold6) = 60*60;
- /* one hour is ``really old'' */
-#define V_rtq_reallyold6 VNET(rtq_reallyold6)
-SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTEXPIRE, rtexpire, CTLFLAG_RW,
- &VNET_NAME(rtq_reallyold6) , 0, "");
-
-static VNET_DEFINE(int, rtq_minreallyold6) = 10;
- /* never automatically crank down to less */
-#define V_rtq_minreallyold6 VNET(rtq_minreallyold6)
-SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW,
- &VNET_NAME(rtq_minreallyold6) , 0, "");
-
static VNET_DEFINE(int, rtq_toomany6) = 128;
/* 128 cached routes is ``too many'' */
#define V_rtq_toomany6 VNET(rtq_toomany6)
@@ -237,114 +189,6 @@ struct rtqk_arg {
};
/*
- * Get rid of old routes. When draining, this deletes everything, even when
- * the timeout is not expired yet. When updating, this makes sure that
- * nothing has a timeout longer than the current value of rtq_reallyold6.
- */
-static int
-in6_rtqkill(struct radix_node *rn, void *rock)
-{
- struct rtqk_arg *ap = rock;
- struct rtentry *rt = (struct rtentry *)rn;
- int err;
-
- RADIX_NODE_HEAD_WLOCK_ASSERT(ap->rnh);
-
- if (rt->rt_flags & RTPRF_OURS) {
- ap->found++;
-
- if (ap->draining || rt->rt_rmx.rmx_expire <= time_uptime) {
- if (rt->rt_refcnt > 0)
- panic("rtqkill route really not free");
-
- err = rtrequest(RTM_DELETE,
- (struct sockaddr *)rt_key(rt),
- rt->rt_gateway, rt_mask(rt),
- rt->rt_flags|RTF_RNH_LOCKED, 0);
- if (err) {
- log(LOG_WARNING, "in6_rtqkill: error %d", err);
- } else {
- ap->killed++;
- }
- } else {
- if (ap->updating
- && (rt->rt_rmx.rmx_expire - time_uptime
- > V_rtq_reallyold6)) {
- rt->rt_rmx.rmx_expire = time_uptime
- + V_rtq_reallyold6;
- }
- ap->nextstop = lmin(ap->nextstop,
- rt->rt_rmx.rmx_expire);
- }
- }
-
- return 0;
-}
-
-#define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */
-static VNET_DEFINE(int, rtq_timeout6) = RTQ_TIMEOUT;
-static VNET_DEFINE(struct callout, rtq_timer6);
-
-#define V_rtq_timeout6 VNET(rtq_timeout6)
-#define V_rtq_timer6 VNET(rtq_timer6)
-
-static void
-in6_rtqtimo(void *rock)
-{
- CURVNET_SET_QUIET((struct vnet *) rock);
- struct radix_node_head *rnh;
- struct rtqk_arg arg;
- struct timeval atv;
- static time_t last_adjusted_timeout = 0;
-
- rnh = rt_tables_get_rnh(0, AF_INET6);
- if (rnh == NULL) {
- CURVNET_RESTORE();
- return;
- }
- arg.found = arg.killed = 0;
- arg.rnh = rnh;
- arg.nextstop = time_uptime + V_rtq_timeout6;
- arg.draining = arg.updating = 0;
- RADIX_NODE_HEAD_LOCK(rnh);
- rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
- RADIX_NODE_HEAD_UNLOCK(rnh);
-
- /*
- * Attempt to be somewhat dynamic about this:
- * If there are ``too many'' routes sitting around taking up space,
- * then crank down the timeout, and see if we can't make some more
- * go away. However, we make sure that we will never adjust more
- * than once in rtq_timeout6 seconds, to keep from cranking down too
- * hard.
- */
- if ((arg.found - arg.killed > V_rtq_toomany6)
- && (time_uptime - last_adjusted_timeout >= V_rtq_timeout6)
- && V_rtq_reallyold6 > V_rtq_minreallyold6) {
- V_rtq_reallyold6 = 2*V_rtq_reallyold6 / 3;
- if (V_rtq_reallyold6 < V_rtq_minreallyold6) {
- V_rtq_reallyold6 = V_rtq_minreallyold6;
- }
-
- last_adjusted_timeout = time_uptime;
-#ifdef DIAGNOSTIC
- log(LOG_DEBUG, "in6_rtqtimo: adjusted rtq_reallyold6 to %d",
- V_rtq_reallyold6);
-#endif
- arg.found = arg.killed = 0;
- arg.updating = 1;
- RADIX_NODE_HEAD_LOCK(rnh);
- rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
- RADIX_NODE_HEAD_UNLOCK(rnh);
- }
-
- atv.tv_usec = 0;
- atv.tv_sec = arg.nextstop - time_uptime;
- callout_reset(&V_rtq_timer6, tvtohz(&atv), in6_rtqtimo, rock);
- CURVNET_RESTORE();
-}
-
-/*
* Age old PMTUs.
*/
struct mtuex_arg {
@@ -379,31 +223,33 @@ in6_mtuexpire(struct radix_node *rn, void *rock)
#define MTUTIMO_DEFAULT (60*1)
static void
-in6_mtutimo(void *rock)
+in6_mtutimo_one(struct radix_node_head *rnh)
{
- CURVNET_SET_QUIET((struct vnet *) rock);
- struct radix_node_head *rnh;
struct mtuex_arg arg;
- struct timeval atv;
- rnh = rt_tables_get_rnh(0, AF_INET6);
- if (rnh == NULL) {
- CURVNET_RESTORE();
- return;
- }
arg.rnh = rnh;
arg.nextstop = time_uptime + MTUTIMO_DEFAULT;
RADIX_NODE_HEAD_LOCK(rnh);
rnh->rnh_walktree(rnh, in6_mtuexpire, &arg);
RADIX_NODE_HEAD_UNLOCK(rnh);
+}
- atv.tv_usec = 0;
- atv.tv_sec = arg.nextstop - time_uptime;
- if (atv.tv_sec < 0) {
- printf("invalid mtu expiration time on routing table\n");
- arg.nextstop = time_uptime + 30; /* last resort */
- atv.tv_sec = 30;
+static void
+in6_mtutimo(void *rock)
+{
+ CURVNET_SET_QUIET((struct vnet *) rock);
+ struct radix_node_head *rnh;
+ struct timeval atv;
+ u_int fibnum;
+
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
+ rnh = rt_tables_get_rnh(fibnum, AF_INET6);
+ if (rnh != NULL)
+ in6_mtutimo_one(rnh);
}
+
+ atv.tv_sec = MTUTIMO_DEFAULT;
+ atv.tv_usec = 0;
callout_reset(&V_rtq_mtutimer, tvtohz(&atv), in6_mtutimo, rock);
CURVNET_RESTORE();
}
@@ -415,6 +261,9 @@ in6_mtutimo(void *rock)
* value should be so just use that).. FIX AFTER RELENG_7 is MFC'd
* see also comments in in_inithead() vfs_export.c and domain.h
*/
+static VNET_DEFINE(int, _in6_rt_was_here);
+#define V__in6_rt_was_here VNET(_in6_rt_was_here)
+
int
in6_inithead(void **head, int off)
{
@@ -427,13 +276,14 @@ in6_inithead(void **head, int off)
return 1; /* only do the rest for the real thing */
rnh = *head;
- KASSERT(rnh == rt_tables_get_rnh(0, AF_INET6), ("rnh?"));
rnh->rnh_addaddr = in6_addroute;
- rnh->rnh_matchaddr = in6_matroute;
- callout_init(&V_rtq_timer6, CALLOUT_MPSAFE);
- callout_init(&V_rtq_mtutimer, CALLOUT_MPSAFE);
- in6_rtqtimo(curvnet); /* kick off timeout first time */
- in6_mtutimo(curvnet); /* kick off timeout first time */
+
+ if (V__in6_rt_was_here == 0) {
+ callout_init(&V_rtq_mtutimer, CALLOUT_MPSAFE);
+ in6_mtutimo(curvnet); /* kick off timeout first time */
+ V__in6_rt_was_here = 1;
+ }
+
return 1;
}
@@ -442,8 +292,47 @@ int
in6_detachhead(void **head, int off)
{
- callout_drain(&V_rtq_timer6);
callout_drain(&V_rtq_mtutimer);
return (1);
}
#endif
+
+/*
+ * Extended API for IPv6 FIB support.
+ */
+void
+in6_rtredirect(struct sockaddr *dst, struct sockaddr *gw, struct sockaddr *nm,
+ int flags, struct sockaddr *src, u_int fibnum)
+{
+
+ rtredirect_fib(dst, gw, nm, flags, src, fibnum);
+}
+
+int
+in6_rtrequest(int req, struct sockaddr *dst, struct sockaddr *gw,
+ struct sockaddr *mask, int flags, struct rtentry **ret_nrt, u_int fibnum)
+{
+
+ return (rtrequest_fib(req, dst, gw, mask, flags, ret_nrt, fibnum));
+}
+
+void
+in6_rtalloc(struct route_in6 *ro, u_int fibnum)
+{
+
+ rtalloc_ign_fib((struct route *)ro, 0ul, fibnum);
+}
+
+void
+in6_rtalloc_ign(struct route_in6 *ro, u_long ignflags, u_int fibnum)
+{
+
+ rtalloc_ign_fib((struct route *)ro, ignflags, fibnum);
+}
+
+struct rtentry *
+in6_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum)
+{
+
+ return (rtalloc1_fib(dst, report, ignflags, fibnum));
+}
diff --git a/freebsd/sys/netinet6/in6_src.c b/freebsd/sys/netinet6/in6_src.c
index f7cd642e..4f20ee54 100644
--- a/freebsd/sys/netinet6/in6_src.c
+++ b/freebsd/sys/netinet6/in6_src.c
@@ -131,9 +131,10 @@ VNET_DEFINE(int, ip6_prefer_tempaddr) = 0;
static int selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, int));
+ struct rtentry **, int, u_int));
static int in6_selectif __P((struct sockaddr_in6 *, struct ip6_pktopts *,
- struct ip6_moptions *, struct route_in6 *ro, struct ifnet **));
+ struct ip6_moptions *, struct route_in6 *ro, struct ifnet **,
+ struct ifnet *, u_int));
static struct in6_addrpolicy *lookup_addrsel_policy(struct sockaddr_in6 *);
@@ -184,7 +185,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ifnet **ifpp, struct in6_addr *srcp)
{
struct in6_addr dst, tmp;
- struct ifnet *ifp = NULL;
+ struct ifnet *ifp = NULL, *oifp = NULL;
struct in6_ifaddr *ia = NULL, *ia_best = NULL;
struct in6_pktinfo *pi = NULL;
int dst_scope = -1, best_scope = -1, best_matchlen = -1;
@@ -197,8 +198,18 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__));
dst = dstsock->sin6_addr; /* make a copy for local operation */
- if (ifpp)
+ if (ifpp) {
+ /*
+ * Save a possibly passed in ifp for in6_selectsrc. Only
+ * neighbor discovery code should use this feature, where
+ * we may know the interface but not the FIB number holding
+ * the connected subnet in case someone deleted it from the
+ * default FIB and we need to check the interface.
+ */
+ if (*ifpp != NULL)
+ oifp = *ifpp;
*ifpp = NULL;
+ }
if (inp != NULL) {
INP_LOCK_ASSERT(inp);
@@ -219,7 +230,9 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct in6_ifaddr *ia6;
/* get the outgoing interface */
- if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp)) != 0)
+ if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp, oifp,
+ (inp != NULL) ? inp->inp_inc.inc_fibnum : RT_DEFAULT_FIB))
+ != 0)
return (error);
/*
@@ -283,7 +296,8 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
* the outgoing interface and the destination address.
*/
/* get the outgoing interface */
- if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp)) != 0)
+ if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp, oifp,
+ (inp != NULL) ? inp->inp_inc.inc_fibnum : RT_DEFAULT_FIB)) != 0)
return (error);
#ifdef DIAGNOSTIC
@@ -506,7 +520,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
static int
selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, int norouteok)
+ struct ifnet **retifp, struct rtentry **retrt, int norouteok, u_int fibnum)
{
int error = 0;
struct ifnet *ifp = NULL;
@@ -583,7 +597,7 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
if (ron->ro_rt == NULL) {
- rtalloc((struct route *)ron); /* multi path case? */
+ in6_rtalloc(ron, fibnum); /* multi path case? */
if (ron->ro_rt == NULL) {
if (ron->ro_rt) {
RTFREE(ron->ro_rt);
@@ -596,9 +610,9 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
rt = ron->ro_rt;
ifp = rt->rt_ifp;
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_RLOCK(ifp);
la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6_next->sin6_addr);
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
if (la != NULL)
LLE_RUNLOCK(la);
else {
@@ -618,7 +632,7 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*satosin6(&ron->ro_dst) = *sin6_next;
}
if (ron->ro_rt == NULL) {
- rtalloc((struct route *)ron); /* multi path case? */
+ in6_rtalloc(ron, fibnum); /* multi path case? */
if (ron->ro_rt == NULL ||
!(ron->ro_rt->rt_flags & RTF_LLINFO)) {
if (ron->ro_rt) {
@@ -663,11 +677,11 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
sa6->sin6_scope_id = 0;
#ifdef RADIX_MPATH
- rtalloc_mpath((struct route *)ro,
- ntohl(sa6->sin6_addr.s6_addr32[3]));
+ rtalloc_mpath_fib((struct route *)ro,
+ ntohl(sa6->sin6_addr.s6_addr32[3]), fibnum);
#else
- ro->ro_rt = rtalloc1(&((struct route *)ro)
- ->ro_dst, 0, 0UL);
+ ro->ro_rt = in6_rtalloc1((struct sockaddr *)
+ &ro->ro_dst, 0, 0UL, fibnum);
if (ro->ro_rt)
RT_UNLOCK(ro->ro_rt);
#endif
@@ -748,21 +762,29 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
static int
in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
- struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp)
+ struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp,
+ struct ifnet *oifp, u_int fibnum)
{
int error;
struct route_in6 sro;
struct rtentry *rt = NULL;
+ KASSERT(retifp != NULL, ("%s: retifp is NULL", __func__));
+
if (ro == NULL) {
bzero(&sro, sizeof(sro));
ro = &sro;
}
if ((error = selectroute(dstsock, opts, mopts, ro, retifp,
- &rt, 1)) != 0) {
+ &rt, 1, fibnum)) != 0) {
if (ro == &sro && rt && rt == sro.ro_rt)
RTFREE(rt);
+ /* Help ND. See oifp comment in in6_selectsrc(). */
+ if (oifp != NULL && fibnum == RT_DEFAULT_FIB) {
+ *retifp = oifp;
+ error = 0;
+ }
return (error);
}
@@ -797,7 +819,10 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
}
/*
- * clone - meaningful only for bsdi and freebsd
+ * Public wrapper function to selectroute().
+ *
+ * XXX-BZ in6_selectroute() should and will grow the FIB argument. The
+ * in6_selectroute_fib() function is only there for backward compat on stable.
*/
int
in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
@@ -806,9 +831,21 @@ in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
{
return (selectroute(dstsock, opts, mopts, ro, retifp,
- retrt, 0));
+ retrt, 0, RT_DEFAULT_FIB));
}
+#ifndef BURN_BRIDGES
+int
+in6_selectroute_fib(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
+ struct ip6_moptions *mopts, struct route_in6 *ro,
+ struct ifnet **retifp, struct rtentry **retrt, u_int fibnum)
+{
+
+ return (selectroute(dstsock, opts, mopts, ro, retifp,
+ retrt, 0, fibnum));
+}
+#endif
+
/*
* Default hop limit selection. The precedence is as follows:
* 1. Hoplimit value specified via ioctl.
@@ -832,7 +869,7 @@ in6_selecthlim(struct inpcb *in6p, struct ifnet *ifp)
ro6.ro_dst.sin6_family = AF_INET6;
ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
ro6.ro_dst.sin6_addr = in6p->in6p_faddr;
- rtalloc((struct route *)&ro6);
+ in6_rtalloc(&ro6, in6p->inp_inc.inc_fibnum);
if (ro6.ro_rt) {
lifp = ro6.ro_rt->rt_ifp;
RTFREE(ro6.ro_rt);
@@ -852,9 +889,11 @@ int
in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
{
struct socket *so = inp->inp_socket;
- u_int16_t lport = 0, first, last, *lastport;
- int count, error, wild = 0, dorandom;
+ u_int16_t lport = 0;
+ int error, wild = 0;
+#ifdef INVARIANTS
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
+#endif
INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_WLOCK_ASSERT(inp);
@@ -870,74 +909,9 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
inp->inp_flags |= INP_ANONPORT;
- if (inp->inp_flags & INP_HIGHPORT) {
- first = V_ipport_hifirstauto; /* sysctl */
- last = V_ipport_hilastauto;
- lastport = &pcbinfo->ipi_lasthi;
- } else if (inp->inp_flags & INP_LOWPORT) {
- error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0);
- if (error)
- return error;
- first = V_ipport_lowfirstauto; /* 1023 */
- last = V_ipport_lowlastauto; /* 600 */
- lastport = &pcbinfo->ipi_lastlow;
- } else {
- first = V_ipport_firstauto; /* sysctl */
- last = V_ipport_lastauto;
- lastport = &pcbinfo->ipi_lastport;
- }
-
- /*
- * For UDP, use random port allocation as long as the user
- * allows it. For TCP (and as of yet unknown) connections,
- * use random port allocation only if the user allows it AND
- * ipport_tick() allows it.
- */
- if (V_ipport_randomized &&
- (!V_ipport_stoprandom || pcbinfo == &V_udbinfo))
- dorandom = 1;
- else
- dorandom = 0;
- /*
- * It makes no sense to do random port allocation if
- * we have the only port available.
- */
- if (first == last)
- dorandom = 0;
- /* Make sure to not include UDP packets in the count. */
- if (pcbinfo != &V_udbinfo)
- V_ipport_tcpallocs++;
-
- /*
- * Instead of having two loops further down counting up or down
- * make sure that first is always <= last and go with only one
- * code path implementing all logic.
- */
- if (first > last) {
- u_int16_t aux;
-
- aux = first;
- first = last;
- last = aux;
- }
-
- if (dorandom)
- *lastport = first + (arc4random() % (last - first));
-
- count = last - first;
-
- do {
- if (count-- < 0) { /* completely used? */
- /* Undo an address bind that may have occurred. */
- inp->in6p_laddr = in6addr_any;
- return (EADDRNOTAVAIL);
- }
- ++*lastport;
- if (*lastport < first || *lastport > last)
- *lastport = first;
- lport = htons(*lastport);
- } while (in6_pcblookup_local(pcbinfo, &inp->in6p_laddr,
- lport, wild, cred));
+ error = in_pcb_lport(inp, NULL, &lport, cred, wild);
+ if (error != 0)
+ return (error);
inp->inp_lport = lport;
if (in_pcbinshash(inp) != 0) {
diff --git a/freebsd/sys/netinet6/in6_var.h b/freebsd/sys/netinet6/in6_var.h
index 00342fde..793eb540 100644
--- a/freebsd/sys/netinet6/in6_var.h
+++ b/freebsd/sys/netinet6/in6_var.h
@@ -704,9 +704,9 @@ in6m_lookup(struct ifnet *ifp, const struct in6_addr *mcaddr)
struct in6_multi *inm;
IN6_MULTI_LOCK();
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
inm = in6m_lookup_locked(ifp, mcaddr);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
IN6_MULTI_UNLOCK();
return (inm);
@@ -779,8 +779,18 @@ void in6_ifremloop(struct ifaddr *);
void in6_ifaddloop(struct ifaddr *);
int in6_is_addr_deprecated __P((struct sockaddr_in6 *));
-struct inpcb;
-int in6_src_ioctl __P((u_long, caddr_t));
+int in6_src_ioctl __P((u_long, caddr_t));
+
+/*
+ * Extended API for IPv6 FIB support.
+ */
+void in6_rtredirect(struct sockaddr *, struct sockaddr *, struct sockaddr *,
+ int, struct sockaddr *, u_int);
+int in6_rtrequest(int, struct sockaddr *, struct sockaddr *,
+ struct sockaddr *, int, struct rtentry **, u_int);
+void in6_rtalloc(struct route_in6 *, u_int);
+void in6_rtalloc_ign(struct route_in6 *, u_long, u_int);
+struct rtentry *in6_rtalloc1(struct sockaddr *, int, u_long, u_int);
#endif /* _KERNEL */
#endif /* _NETINET6_IN6_VAR_H_ */
diff --git a/freebsd/sys/netinet6/ip6_forward.c b/freebsd/sys/netinet6/ip6_forward.c
index 2f9073c8..a3d3d8f4 100644
--- a/freebsd/sys/netinet6/ip6_forward.c
+++ b/freebsd/sys/netinet6/ip6_forward.c
@@ -354,7 +354,7 @@ skip_ipsec:
dst->sin6_family = AF_INET6;
dst->sin6_addr = ip6->ip6_dst;
- rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
+ rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m));
if (rin6.ro_rt != NULL)
RT_UNLOCK(rin6.ro_rt);
else {
diff --git a/freebsd/sys/netinet6/ip6_input.c b/freebsd/sys/netinet6/ip6_input.c
index 568ec167..47d9e690 100644
--- a/freebsd/sys/netinet6/ip6_input.c
+++ b/freebsd/sys/netinet6/ip6_input.c
@@ -544,10 +544,10 @@ passin:
dst6.sin6_len = sizeof(struct sockaddr_in6);
dst6.sin6_addr = ip6->ip6_dst;
ifp = m->m_pkthdr.rcvif;
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_RLOCK(ifp);
lle = lla_lookup(LLTABLE6(ifp), 0,
(struct sockaddr *)&dst6);
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) {
struct ifaddr *ifa;
struct in6_ifaddr *ia6;
@@ -556,7 +556,7 @@ passin:
bad = 1;
#define sa_equal(a1, a2) \
(bcmp((a1), (a2), ((a1))->sin6_len) == 0)
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != dst6.sin6_family)
continue;
@@ -588,7 +588,7 @@ passin:
ip6_sprintf(ip6bufs, &ip6->ip6_src),
ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
LLE_RUNLOCK(lle);
if (bad)
goto bad;
@@ -605,7 +605,7 @@ passin:
dst->sin6_len = sizeof(struct sockaddr_in6);
dst->sin6_family = AF_INET6;
dst->sin6_addr = ip6->ip6_dst;
- rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
+ rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m));
if (rin6.ro_rt)
RT_UNLOCK(rin6.ro_rt);
@@ -1238,19 +1238,28 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp,
}
#endif
- if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
- if (v4only != NULL)
- *v4only = 1;
- return (mp);
- }
-
#define IS2292(inp, x, y) (((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y))
/* RFC 2292 sec. 5 */
if ((inp->inp_flags & IN6P_PKTINFO) != 0) {
struct in6_pktinfo pi6;
- bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
- in6_clearscope(&pi6.ipi6_addr); /* XXX */
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+#ifdef INET
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ pi6.ipi6_addr.s6_addr32[0] = 0;
+ pi6.ipi6_addr.s6_addr32[1] = 0;
+ pi6.ipi6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
+ pi6.ipi6_addr.s6_addr32[3] = ip->ip_dst.s_addr;
+#else
+ /* We won't hit this code */
+ bzero(&pi6.ipi6_addr, sizeof(struct in6_addr));
+#endif
+ } else {
+ bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
+ in6_clearscope(&pi6.ipi6_addr); /* XXX */
+ }
pi6.ipi6_ifindex =
(m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0;
@@ -1262,8 +1271,21 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp,
}
if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) {
- int hlim = ip6->ip6_hlim & 0xff;
+ int hlim;
+
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+#ifdef INET
+ struct ip *ip;
+ ip = mtod(m, struct ip *);
+ hlim = ip->ip_ttl;
+#else
+ /* We won't hit this code */
+ hlim = 0;
+#endif
+ } else {
+ hlim = ip6->ip6_hlim & 0xff;
+ }
*mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int),
IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT),
IPPROTO_IPV6);
@@ -1271,8 +1293,40 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp,
mp = &(*mp)->m_next;
}
- if (v4only != NULL)
- *v4only = 0;
+ if ((inp->inp_flags & IN6P_TCLASS) != 0) {
+ int tclass;
+
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+#ifdef INET
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ tclass = ip->ip_tos;
+#else
+ /* We won't hit this code */
+ tclass = 0;
+#endif
+ } else {
+ u_int32_t flowinfo;
+
+ flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
+ flowinfo >>= 20;
+ tclass = flowinfo & 0xff;
+ }
+ *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(int),
+ IPV6_TCLASS, IPPROTO_IPV6);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+
+ if (v4only != NULL) {
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+ *v4only = 1;
+ } else {
+ *v4only = 0;
+ }
+ }
+
return (mp);
}
@@ -1286,20 +1340,6 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
if (v4only)
return;
- if ((in6p->inp_flags & IN6P_TCLASS) != 0) {
- u_int32_t flowinfo;
- int tclass;
-
- flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
- flowinfo >>= 20;
-
- tclass = flowinfo & 0xff;
- *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(tclass),
- IPV6_TCLASS, IPPROTO_IPV6);
- if (*mp)
- mp = &(*mp)->m_next;
- }
-
/*
* IPV6_HOPOPTS socket option. Recall that we required super-user
* privilege for the option (see ip6_ctloutput), but it might be too
diff --git a/freebsd/sys/netinet6/ip6_ipsec.c b/freebsd/sys/netinet6/ip6_ipsec.c
index e1477123..8ed4eec2 100644
--- a/freebsd/sys/netinet6/ip6_ipsec.c
+++ b/freebsd/sys/netinet6/ip6_ipsec.c
@@ -97,7 +97,7 @@ SYSCTL_VNET_INT(_net_inet6_ipsec6, OID_AUTO,
/*
* Check if we have to jump over firewall processing for this packet.
- * Called from ip_input().
+ * Called from ip6_input().
* 1 = jump over firewall, 0 = packet goes through firewall.
*/
int
@@ -106,7 +106,7 @@ ip6_ipsec_filtertunnel(struct mbuf *m)
#if defined(IPSEC)
/*
- * Bypass packet filtering for packets from a tunnel.
+ * Bypass packet filtering for packets previously handled by IPsec.
*/
if (!V_ip6_ipsec6_filtertunnel &&
m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
@@ -118,7 +118,7 @@ ip6_ipsec_filtertunnel(struct mbuf *m)
/*
* Check if this packet has an active SA and needs to be dropped instead
* of forwarded.
- * Called from ip_input().
+ * Called from ip6_input().
* 1 = drop packet, 0 = forward packet.
*/
int
@@ -141,7 +141,7 @@ ip6_ipsec_fwd(struct mbuf *m)
if (sp == NULL) { /* NB: can happen if error */
splx(s);
/*XXX error stat???*/
- DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/
+ DPRINTF(("%s: no SP for forwarding\n", __func__)); /*XXX*/
return 1;
}
@@ -163,7 +163,7 @@ ip6_ipsec_fwd(struct mbuf *m)
* Check if protocol type doesn't have a further header and do IPSEC
* decryption or reject right now. Protocols with further headers get
* their IPSEC treatment within the protocol specific processing.
- * Called from ip_input().
+ * Called from ip6_input().
* 1 = drop packet, 0 = continue processing packet.
*/
int
@@ -206,7 +206,7 @@ ip6_ipsec_input(struct mbuf *m, int nxt)
} else {
/* XXX error stat??? */
error = EINVAL;
- DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
+ DPRINTF(("%s: no SP, packet discarded\n", __func__));/*XXX*/
return 1;
}
splx(s);
@@ -263,7 +263,7 @@ ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error,
mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
continue;
/*
- * Check if policy has an SA associated with it.
+ * Check if policy has no SA associated with it.
* This can happen when an SP has yet to acquire
* an SA; e.g. on first reference. If it occurs,
* then we let ipsec4_process_packet do its thing.
diff --git a/freebsd/sys/netinet6/ip6_mroute.c b/freebsd/sys/netinet6/ip6_mroute.c
index 3be1d480..44a96cb5 100644
--- a/freebsd/sys/netinet6/ip6_mroute.c
+++ b/freebsd/sys/netinet6/ip6_mroute.c
@@ -83,7 +83,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <rtems/bsd/local/opt_inet.h>
#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/sys/param.h>
diff --git a/freebsd/sys/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c
index d6d7eb6e..19c430a6 100644
--- a/freebsd/sys/netinet6/ip6_output.c
+++ b/freebsd/sys/netinet6/ip6_output.c
@@ -137,7 +137,7 @@ static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int,
static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t);
static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
static int ip6_getpmtu __P((struct route_in6 *, struct route_in6 *,
- struct ifnet *, struct in6_addr *, u_long *, int *));
+ struct ifnet *, struct in6_addr *, u_long *, int *, u_int));
static int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
@@ -232,6 +232,9 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
goto bad;
}
+ if (inp != NULL)
+ M_SETFIB(m, inp->inp_inc.inc_fibnum);
+
finaldst = ip6->ip6_dst;
bzero(&exthdrs, sizeof(exthdrs));
@@ -259,11 +262,11 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
}
+#ifdef IPSEC
/*
* IPSec checking which handles several cases.
* FAST IPSEC: We re-injected the packet.
*/
-#ifdef IPSEC
switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp, &sp))
{
case 1: /* Bad packet */
@@ -578,8 +581,8 @@ again:
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = ip6->ip6_dst;
- if ((error = in6_selectroute(&dst_sa, opt, im6o, ro,
- &ifp, &rt)) != 0) {
+ if ((error = in6_selectroute_fib(&dst_sa, opt, im6o, ro,
+ &ifp, &rt, inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m))) != 0) {
switch (error) {
case EHOSTUNREACH:
V_ip6stat.ip6s_noroute++;
@@ -747,7 +750,7 @@ again:
/* Determine path MTU. */
if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu,
- &alwaysfrag)) != 0)
+ &alwaysfrag, inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m))) != 0)
goto bad;
/*
@@ -1011,7 +1014,7 @@ passout:
goto sendorfree;
}
m->m_pkthdr.rcvif = NULL;
- m->m_flags = m0->m_flags & M_COPYFLAGS;
+ m->m_flags = m0->m_flags & M_COPYFLAGS; /* incl. FIB */
*mnext = m;
mnext = &m->m_nextpkt;
m->m_data += max_linkhdr;
@@ -1266,7 +1269,7 @@ ip6_insertfraghdr(struct mbuf *m0, struct mbuf *m, int hlen,
static int
ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
struct ifnet *ifp, struct in6_addr *dst, u_long *mtup,
- int *alwaysfragp)
+ int *alwaysfragp, u_int fibnum)
{
u_int32_t mtu = 0;
int alwaysfrag = 0;
@@ -1288,7 +1291,7 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
sa6_dst->sin6_addr = *dst;
- rtalloc((struct route *)ro_pmtu);
+ in6_rtalloc(ro_pmtu, fibnum);
}
}
if (ro_pmtu->ro_rt) {
@@ -1366,7 +1369,23 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
optval = 0;
uproto = (int)so->so_proto->pr_protocol;
- if (level == IPPROTO_IPV6) {
+ if (level != IPPROTO_IPV6) {
+ error = EINVAL;
+
+ if (sopt->sopt_level == SOL_SOCKET &&
+ sopt->sopt_dir == SOPT_SET) {
+ switch (sopt->sopt_name) {
+ case SO_SETFIB:
+ INP_WLOCK(in6p);
+ in6p->inp_inc.inc_fibnum = so->so_fibnum;
+ INP_WUNLOCK(in6p);
+ error = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
switch (op) {
case SOPT_SET:
@@ -1455,18 +1474,22 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
break;
#define OPTSET(bit) \
do { \
+ INP_WLOCK(in6p); \
if (optval) \
in6p->inp_flags |= (bit); \
else \
in6p->inp_flags &= ~(bit); \
+ INP_WUNLOCK(in6p); \
} while (/*CONSTCOND*/ 0)
#define OPTSET2292(bit) \
do { \
+ INP_WLOCK(in6p); \
in6p->inp_flags |= IN6P_RFC2292; \
if (optval) \
in6p->inp_flags |= (bit); \
else \
in6p->inp_flags &= ~(bit); \
+ INP_WUNLOCK(in6p); \
} while (/*CONSTCOND*/ 0)
#define OPTBIT(bit) (in6p->inp_flags & (bit) ? 1 : 0)
@@ -1720,6 +1743,7 @@ do { \
if (error)
break;
+ INP_WLOCK(in6p);
switch (optval) {
case IPV6_PORTRANGE_DEFAULT:
in6p->inp_flags &= ~(INP_LOWPORT);
@@ -1740,6 +1764,7 @@ do { \
error = EINVAL;
break;
}
+ INP_WUNLOCK(in6p);
break;
#ifdef IPSEC
@@ -1889,7 +1914,8 @@ do { \
* the outgoing interface.
*/
error = ip6_getpmtu(&sro, NULL, NULL,
- &in6p->in6p_faddr, &pmtu, NULL);
+ &in6p->in6p_faddr, &pmtu, NULL,
+ so->so_fibnum);
if (sro.ro_rt)
RTFREE(sro.ro_rt);
if (error)
@@ -1989,8 +2015,6 @@ do { \
}
break;
}
- } else { /* level != IPPROTO_IPV6 */
- error = EINVAL;
}
return (error);
}
@@ -2312,6 +2336,8 @@ copypktopts(struct ip6_pktopts *dst, struct ip6_pktopts *src, int canwait)
dst->ip6po_hlim = src->ip6po_hlim;
dst->ip6po_tclass = src->ip6po_tclass;
dst->ip6po_flags = src->ip6po_flags;
+ dst->ip6po_minmtu = src->ip6po_minmtu;
+ dst->ip6po_prefer_tempaddr = src->ip6po_prefer_tempaddr;
if (src->ip6po_pktinfo) {
dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo),
M_IP6OPT, canwait);
diff --git a/freebsd/sys/netinet6/ip6_var.h b/freebsd/sys/netinet6/ip6_var.h
index 51ae1f74..9e210e2d 100644
--- a/freebsd/sys/netinet6/ip6_var.h
+++ b/freebsd/sys/netinet6/ip6_var.h
@@ -437,6 +437,9 @@ int in6_selectsrc(struct sockaddr_in6 *, struct ip6_pktopts *,
int in6_selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
struct rtentry **));
+int in6_selectroute_fib(struct sockaddr_in6 *, struct ip6_pktopts *,
+ struct ip6_moptions *, struct route_in6 *, struct ifnet **,
+ struct rtentry **, u_int);
u_int32_t ip6_randomid __P((void));
u_int32_t ip6_randomflowlabel __P((void));
#endif /* _KERNEL */
diff --git a/freebsd/sys/netinet6/mld6.c b/freebsd/sys/netinet6/mld6.c
index b1133d69..5f9b4ffa 100644
--- a/freebsd/sys/netinet6/mld6.c
+++ b/freebsd/sys/netinet6/mld6.c
@@ -123,7 +123,8 @@ static int mld_v1_input_query(struct ifnet *, const struct ip6_hdr *,
/*const*/ struct mld_hdr *);
static int mld_v1_input_report(struct ifnet *, const struct ip6_hdr *,
/*const*/ struct mld_hdr *);
-static void mld_v1_process_group_timer(struct in6_multi *, const int);
+static void mld_v1_process_group_timer(struct mld_ifinfo *,
+ struct in6_multi *);
static void mld_v1_process_querier_timers(struct mld_ifinfo *);
static int mld_v1_transmit_report(struct in6_multi *, const int);
static void mld_v1_update_group(struct in6_multi *, const int);
@@ -543,7 +544,7 @@ mld_ifdetach(struct ifnet *ifp)
mli = MLD_IFINFO(ifp);
if (mli->mli_version == MLD_VERSION_2) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET6 ||
ifma->ifma_protospec == NULL)
@@ -555,7 +556,7 @@ mld_ifdetach(struct ifnet *ifp)
}
in6m_clear_recorded(inm);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele,
tinm) {
SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
@@ -682,7 +683,6 @@ mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
IN6_MULTI_LOCK();
MLD_LOCK();
- IF_ADDR_LOCK(ifp);
/*
* Switch to MLDv1 host compatibility mode.
@@ -695,6 +695,7 @@ mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
if (timer == 0)
timer = 1;
+ IF_ADDR_RLOCK(ifp);
if (is_general_query) {
/*
* For each reporting group joined on this
@@ -726,7 +727,7 @@ mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
in6_clearscope(&mld->mld_addr);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
MLD_UNLOCK();
IN6_MULTI_UNLOCK();
@@ -890,7 +891,6 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
IN6_MULTI_LOCK();
MLD_LOCK();
- IF_ADDR_LOCK(ifp);
mli = MLD_IFINFO(ifp);
KASSERT(mli != NULL, ("%s: no mld_ifinfo for ifp %p", __func__, ifp));
@@ -938,14 +938,18 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
* Queries for groups we are not a member of on this
* link are simply ignored.
*/
+ IF_ADDR_RLOCK(ifp);
inm = in6m_lookup_locked(ifp, &mld->mld_addr);
- if (inm == NULL)
+ if (inm == NULL) {
+ IF_ADDR_RUNLOCK(ifp);
goto out_locked;
+ }
if (nsrc > 0) {
if (!ratecheck(&inm->in6m_lastgsrtv,
&V_mld_gsrdelay)) {
CTR1(KTR_MLD, "%s: GS query throttled.",
__func__);
+ IF_ADDR_RUNLOCK(ifp);
goto out_locked;
}
}
@@ -963,10 +967,10 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
/* XXX Clear embedded scope ID as userland won't expect it. */
in6_clearscope(&mld->mld_addr);
+ IF_ADDR_RUNLOCK(ifp);
}
out_locked:
- IF_ADDR_UNLOCK(ifp);
MLD_UNLOCK();
IN6_MULTI_UNLOCK();
@@ -1173,7 +1177,7 @@ mld_v1_input_report(struct ifnet *ifp, const struct ip6_hdr *ip6,
IN6_MULTI_LOCK();
MLD_LOCK();
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
/*
* MLDv1 report suppression.
@@ -1221,8 +1225,8 @@ mld_v1_input_report(struct ifnet *ifp, const struct ip6_hdr *ip6,
}
out_locked:
+ IF_ADDR_RUNLOCK(ifp);
MLD_UNLOCK();
- IF_ADDR_UNLOCK(ifp);
IN6_MULTI_UNLOCK();
/* XXX Clear embedded scope ID as userland won't expect it. */
@@ -1334,8 +1338,8 @@ mld_fasttimo_vnet(void)
struct ifqueue qrq; /* Query response packets */
struct ifnet *ifp;
struct mld_ifinfo *mli;
- struct ifmultiaddr *ifma, *tifma;
- struct in6_multi *inm;
+ struct ifmultiaddr *ifma;
+ struct in6_multi *inm, *tinm;
int uri_fasthz;
uri_fasthz = 0;
@@ -1398,25 +1402,15 @@ mld_fasttimo_vnet(void)
IFQ_SET_MAXLEN(&scq, MLD_MAX_STATE_CHANGE_PACKETS);
}
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link,
- tifma) {
+ IF_ADDR_RLOCK(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET6 ||
ifma->ifma_protospec == NULL)
continue;
inm = (struct in6_multi *)ifma->ifma_protospec;
switch (mli->mli_version) {
case MLD_VERSION_1:
- /*
- * XXX Drop IF_ADDR lock temporarily to
- * avoid recursion caused by a potential
- * call by in6ifa_ifpforlinklocal().
- * rwlock candidate?
- */
- IF_ADDR_UNLOCK(ifp);
- mld_v1_process_group_timer(inm,
- mli->mli_version);
- IF_ADDR_LOCK(ifp);
+ mld_v1_process_group_timer(mli, inm);
break;
case MLD_VERSION_2:
mld_v2_process_group_timers(mli, &qrq,
@@ -1424,11 +1418,27 @@ mld_fasttimo_vnet(void)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
-
- if (mli->mli_version == MLD_VERSION_2) {
- struct in6_multi *tinm;
+ IF_ADDR_RUNLOCK(ifp);
+ switch (mli->mli_version) {
+ case MLD_VERSION_1:
+ /*
+ * Transmit reports for this lifecycle. This
+ * is done while not holding IF_ADDR_LOCK
+ * since this can call
+ * in6ifa_ifpforlinklocal() which locks
+ * IF_ADDR_LOCK internally as well as
+ * ip6_output() to transmit a packet.
+ */
+ SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead,
+ in6m_nrele, tinm) {
+ SLIST_REMOVE_HEAD(&mli->mli_relinmhead,
+ in6m_nrele);
+ (void)mld_v1_transmit_report(inm,
+ MLD_LISTENER_REPORT);
+ }
+ break;
+ case MLD_VERSION_2:
mld_dispatch_queue(&qrq, 0);
mld_dispatch_queue(&scq, 0);
@@ -1442,6 +1452,7 @@ mld_fasttimo_vnet(void)
in6m_nrele);
in6m_release_locked(inm);
}
+ break;
}
}
@@ -1455,7 +1466,7 @@ out_locked:
* Will update the global pending timer flags.
*/
static void
-mld_v1_process_group_timer(struct in6_multi *inm, const int version)
+mld_v1_process_group_timer(struct mld_ifinfo *mli, struct in6_multi *inm)
{
int report_timer_expired;
@@ -1482,8 +1493,8 @@ mld_v1_process_group_timer(struct in6_multi *inm, const int version)
case MLD_REPORTING_MEMBER:
if (report_timer_expired) {
inm->in6m_state = MLD_IDLE_MEMBER;
- (void)mld_v1_transmit_report(inm,
- MLD_LISTENER_REPORT);
+ SLIST_INSERT_HEAD(&mli->mli_relinmhead, inm,
+ in6m_nrele);
}
break;
case MLD_G_QUERY_PENDING_MEMBER:
@@ -1654,7 +1665,7 @@ mld_v2_cancel_link_timers(struct mld_ifinfo *mli)
{
struct ifmultiaddr *ifma;
struct ifnet *ifp;
- struct in6_multi *inm;
+ struct in6_multi *inm, *tinm;
CTR3(KTR_MLD, "%s: cancel v2 timers on ifp %p(%s)", __func__,
mli->mli_ifp, mli->mli_ifp->if_xname);
@@ -1675,7 +1686,7 @@ mld_v2_cancel_link_timers(struct mld_ifinfo *mli)
ifp = mli->mli_ifp;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET6)
continue;
@@ -1693,14 +1704,9 @@ mld_v2_cancel_link_timers(struct mld_ifinfo *mli)
* If we are leaving the group and switching
* version, we need to release the final
* reference held for issuing the INCLUDE {}.
- *
- * SMPNG: Must drop and re-acquire IF_ADDR_LOCK
- * around in6m_release_locked(), as it is not
- * a recursive mutex.
*/
- IF_ADDR_UNLOCK(ifp);
- in6m_release_locked(inm);
- IF_ADDR_LOCK(ifp);
+ SLIST_INSERT_HEAD(&mli->mli_relinmhead, inm,
+ in6m_nrele);
/* FALLTHROUGH */
case MLD_G_QUERY_PENDING_MEMBER:
case MLD_SG_QUERY_PENDING_MEMBER:
@@ -1717,7 +1723,11 @@ mld_v2_cancel_link_timers(struct mld_ifinfo *mli)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
+ SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele, tinm) {
+ SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
+ in6m_release_locked(inm);
+ }
}
/*
@@ -2974,7 +2984,7 @@ mld_v2_merge_state_changes(struct in6_multi *inm, struct ifqueue *ifscq)
static void
mld_v2_dispatch_general_query(struct mld_ifinfo *mli)
{
- struct ifmultiaddr *ifma, *tifma;
+ struct ifmultiaddr *ifma;
struct ifnet *ifp;
struct in6_multi *inm;
int retval;
@@ -2987,8 +2997,8 @@ mld_v2_dispatch_general_query(struct mld_ifinfo *mli)
ifp = mli->mli_ifp;
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, tifma) {
+ IF_ADDR_RLOCK(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET6 ||
ifma->ifma_protospec == NULL)
continue;
@@ -3018,7 +3028,7 @@ mld_v2_dispatch_general_query(struct mld_ifinfo *mli)
break;
}
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
mld_dispatch_queue(&mli->mli_gq, MLD_MAX_RESPONSE_BURST);
diff --git a/freebsd/sys/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c
index 999855ca..89b15e56 100644
--- a/freebsd/sys/netinet6/nd6.c
+++ b/freebsd/sys/netinet6/nd6.c
@@ -372,6 +372,14 @@ nd6_options(union nd_opts *ndopts)
ndopts->nd_opts_pi_end =
(struct nd_opt_prefix_info *)nd_opt;
break;
+ /* What about ND_OPT_ROUTE_INFO? RFC 4191 */
+ case ND_OPT_RDNSS: /* RFC 6106 */
+ case ND_OPT_DNSSL: /* RFC 6106 */
+ /*
+ * Silently ignore options we know and do not care about
+ * in the kernel.
+ */
+ break;
default:
/*
* Unknown options must be silently ignored,
@@ -564,26 +572,18 @@ nd6_timer(void *arg)
{
CURVNET_SET((struct vnet *) arg);
int s;
- struct nd_defrouter *dr;
- struct nd_prefix *pr;
+ struct nd_defrouter *dr, *ndr;
+ struct nd_prefix *pr, *npr;
struct in6_ifaddr *ia6, *nia6;
- struct in6_addrlifetime *lt6;
callout_reset(&V_nd6_timer_ch, V_nd6_prune * hz,
nd6_timer, curvnet);
/* expire default router list */
s = splnet();
- dr = TAILQ_FIRST(&V_nd_defrouter);
- while (dr) {
- if (dr->expire && dr->expire < time_second) {
- struct nd_defrouter *t;
- t = TAILQ_NEXT(dr, dr_entry);
+ TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) {
+ if (dr->expire && dr->expire < time_second)
defrtrlist_del(dr);
- dr = t;
- } else {
- dr = TAILQ_NEXT(dr, dr_entry);
- }
}
/*
@@ -597,7 +597,6 @@ nd6_timer(void *arg)
addrloop:
TAILQ_FOREACH_SAFE(ia6, &V_in6_ifaddrhead, ia_link, nia6) {
/* check address lifetime */
- lt6 = &ia6->ia6_lifetime;
if (IFA6_IS_INVALID(ia6)) {
int regen = 0;
@@ -660,8 +659,7 @@ nd6_timer(void *arg)
}
/* expire prefix list */
- pr = V_nd_prefix.lh_first;
- while (pr) {
+ LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) {
/*
* check prefix lifetime.
* since pltime is just for autoconf, pltime processing for
@@ -669,18 +667,13 @@ nd6_timer(void *arg)
*/
if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
time_second - pr->ndpr_lastupdate > pr->ndpr_vltime) {
- struct nd_prefix *t;
- t = pr->ndpr_next;
/*
* address expiration and prefix expiration are
* separate. NEVER perform in6_purgeaddr here.
*/
-
prelist_remove(pr);
- pr = t;
- } else
- pr = pr->ndpr_next;
+ }
}
splx(s);
CURVNET_RESTORE();
@@ -697,7 +690,7 @@ regen_tmpaddr(struct in6_ifaddr *ia6)
struct in6_ifaddr *public_ifa6 = NULL;
ifp = ia6->ia_ifa.ifa_ifp;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct in6_ifaddr *it6;
@@ -739,7 +732,7 @@ regen_tmpaddr(struct in6_ifaddr *ia6)
if (public_ifa6 != NULL)
ifa_ref(&public_ifa6->ia_ifa);
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (public_ifa6 != NULL) {
int e;
@@ -773,8 +766,7 @@ nd6_purge(struct ifnet *ifp)
* in the routing table, in order to keep additional side effects as
* small as possible.
*/
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr; dr = ndr) {
- ndr = TAILQ_NEXT(dr, dr_entry);
+ TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) {
if (dr->installed)
continue;
@@ -782,8 +774,7 @@ nd6_purge(struct ifnet *ifp)
defrtrlist_del(dr);
}
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr; dr = ndr) {
- ndr = TAILQ_NEXT(dr, dr_entry);
+ TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) {
if (!dr->installed)
continue;
@@ -792,8 +783,7 @@ nd6_purge(struct ifnet *ifp)
}
/* Nuke prefix list entries toward ifp */
- for (pr = V_nd_prefix.lh_first; pr; pr = npr) {
- npr = pr->ndpr_next;
+ LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) {
if (pr->ndpr_ifp == ifp) {
/*
* Because if_detach() does *not* release prefixes
@@ -908,13 +898,16 @@ nd6_is_new_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
* If the address matches one of our on-link prefixes, it should be a
* neighbor.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
if (pr->ndpr_ifp != ifp)
continue;
if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) {
struct rtentry *rt;
- rt = rtalloc1((struct sockaddr *)&pr->ndpr_prefix, 0, 0);
+
+ /* Always use the default FIB here. */
+ rt = in6_rtalloc1((struct sockaddr *)&pr->ndpr_prefix,
+ 0, 0, RT_DEFAULT_FIB);
if (rt == NULL)
continue;
/*
@@ -959,7 +952,7 @@ nd6_is_new_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
* XXX: we restrict the condition to hosts, because routers usually do
* not have the "default router list".
*/
- if (!V_ip6_forwarding && TAILQ_FIRST(&V_nd_defrouter) == NULL &&
+ if (!V_ip6_forwarding && TAILQ_EMPTY(&V_nd_defrouter) &&
V_nd6_defifindex == ifp->if_index) {
return (1);
}
@@ -986,12 +979,12 @@ nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
* Even if the address matches none of our addresses, it might be
* in the neighbor cache.
*/
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_RLOCK(ifp);
if ((lle = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL) {
LLE_RUNLOCK(lle);
rc = 1;
}
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
return (rc);
}
@@ -1172,6 +1165,46 @@ done:
}
+/*
+ * Rejuvenate this function for routing operations related
+ * processing.
+ */
+void
+nd6_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
+{
+ struct sockaddr_in6 *gateway = (struct sockaddr_in6 *)rt->rt_gateway;
+ struct nd_defrouter *dr;
+ struct ifnet *ifp = rt->rt_ifp;
+
+ RT_LOCK_ASSERT(rt);
+
+ switch (req) {
+ case RTM_ADD:
+ break;
+
+ case RTM_DELETE:
+ if (!ifp)
+ return;
+ /*
+ * Only indirect routes are interesting.
+ */
+ if ((rt->rt_flags & RTF_GATEWAY) == 0)
+ return;
+ /*
+ * check for default route
+ */
+ if (IN6_ARE_ADDR_EQUAL(&in6addr_any,
+ &SIN6(rt_key(rt))->sin6_addr)) {
+
+ dr = defrouter_lookup(&gateway->sin6_addr, ifp);
+ if (dr != NULL)
+ dr->installed = 0;
+ }
+ break;
+ }
+}
+
+
int
nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
{
@@ -1192,8 +1225,9 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
*/
bzero(drl, sizeof(*drl));
s = splnet();
- dr = TAILQ_FIRST(&V_nd_defrouter);
- while (dr && i < DRLSTSIZ) {
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
+ if (i >= DRLSTSIZ)
+ break;
drl->defrouter[i].rtaddr = dr->rtaddr;
in6_clearscope(&drl->defrouter[i].rtaddr);
@@ -1202,7 +1236,6 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
drl->defrouter[i].expire = dr->expire;
drl->defrouter[i].if_index = dr->ifp->if_index;
i++;
- dr = TAILQ_NEXT(dr, dr_entry);
}
splx(s);
break;
@@ -1221,11 +1254,12 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
*/
bzero(oprl, sizeof(*oprl));
s = splnet();
- pr = V_nd_prefix.lh_first;
- while (pr && i < PRLSTSIZ) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
struct nd_pfxrouter *pfr;
int j;
+ if (i >= PRLSTSIZ)
+ break;
oprl->prefix[i].prefix = pr->ndpr_prefix.sin6_addr;
oprl->prefix[i].raflags = pr->ndpr_raf;
oprl->prefix[i].prefixlen = pr->ndpr_plen;
@@ -1250,9 +1284,8 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
oprl->prefix[i].expire = maxexpire;
}
- pfr = pr->ndpr_advrtrs.lh_first;
j = 0;
- while (pfr) {
+ LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
if (j < DRLSTSIZ) {
#define RTRADDR oprl->prefix[i].advrtr[j]
RTRADDR = pfr->router->rtaddr;
@@ -1260,13 +1293,11 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
#undef RTRADDR
}
j++;
- pfr = pfr->pfr_next;
}
oprl->prefix[i].advrtrs = j;
oprl->prefix[i].origin = PR_ORIG_RA;
i++;
- pr = pr->ndpr_next;
}
splx(s);
@@ -1330,11 +1361,9 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
struct nd_prefix *pr, *next;
s = splnet();
- for (pr = V_nd_prefix.lh_first; pr; pr = next) {
+ LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, next) {
struct in6_ifaddr *ia, *ia_next;
- next = pr->ndpr_next;
-
if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
continue; /* XXX */
@@ -1360,8 +1389,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
s = splnet();
defrouter_reset();
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr; dr = next) {
- next = TAILQ_NEXT(dr, dr_entry);
+ TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, next) {
defrtrlist_del(dr);
}
defrouter_select();
@@ -1376,9 +1404,9 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0)
return (error);
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_RLOCK(ifp);
ln = nd6_lookup(&nb_addr, 0, ifp);
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
if (ln == NULL) {
error = EINVAL;
@@ -1683,8 +1711,7 @@ nd6_slowtimo(void *arg)
callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
nd6_slowtimo, curvnet);
IFNET_RLOCK_NOSLEEP();
- for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
- ifp = TAILQ_NEXT(ifp, if_list)) {
+ TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
nd6if = ND_IFINFO(ifp);
if (nd6if->basereachable && /* already initialized */
(nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
@@ -1919,14 +1946,15 @@ nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
if (*chain == NULL)
*chain = m;
else {
- struct mbuf *m = *chain;
+ struct mbuf *mb;
/*
* append mbuf to end of deferred chain
*/
- while (m->m_nextpkt != NULL)
- m = m->m_nextpkt;
- m->m_nextpkt = m;
+ mb = *chain;
+ while (mb->m_nextpkt != NULL)
+ mb = mb->m_nextpkt;
+ mb->m_nextpkt = m;
}
return (error);
}
@@ -2070,9 +2098,9 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
/*
* the entry should have been created in nd6_store_lladdr
*/
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_RLOCK(ifp);
ln = lla_lookup(LLTABLE6(ifp), 0, dst);
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
if (ln != NULL)
LLE_RUNLOCK(ln);
@@ -2120,130 +2148,101 @@ SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd6_maxqueuelen,
static int
nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS)
{
- int error;
- char buf[1024] __aligned(4);
- struct in6_defrouter *d, *de;
+ struct in6_defrouter d;
struct nd_defrouter *dr;
+ int error;
if (req->newptr)
- return EPERM;
- error = 0;
-
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
- d = (struct in6_defrouter *)buf;
- de = (struct in6_defrouter *)(buf + sizeof(buf));
-
- if (d + 1 <= de) {
- bzero(d, sizeof(*d));
- d->rtaddr.sin6_family = AF_INET6;
- d->rtaddr.sin6_len = sizeof(d->rtaddr);
- d->rtaddr.sin6_addr = dr->rtaddr;
- error = sa6_recoverscope(&d->rtaddr);
- if (error != 0)
- return (error);
- d->flags = dr->flags;
- d->rtlifetime = dr->rtlifetime;
- d->expire = dr->expire;
- d->if_index = dr->ifp->if_index;
- } else
- panic("buffer too short");
-
- error = SYSCTL_OUT(req, buf, sizeof(*d));
- if (error)
- break;
- }
+ return (EPERM);
- return (error);
+ bzero(&d, sizeof(d));
+ d.rtaddr.sin6_family = AF_INET6;
+ d.rtaddr.sin6_len = sizeof(d.rtaddr);
+
+ /*
+ * XXX locking
+ */
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
+ d.rtaddr.sin6_addr = dr->rtaddr;
+ error = sa6_recoverscope(&d.rtaddr);
+ if (error != 0)
+ return (error);
+ d.flags = dr->flags;
+ d.rtlifetime = dr->rtlifetime;
+ d.expire = dr->expire;
+ d.if_index = dr->ifp->if_index;
+ error = SYSCTL_OUT(req, &d, sizeof(d));
+ if (error != 0)
+ return (error);
+ }
+ return (0);
}
static int
nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS)
{
- int error;
- char buf[1024] __aligned(4);
- struct in6_prefix *p, *pe;
+ struct in6_prefix p;
+ struct sockaddr_in6 s6;
struct nd_prefix *pr;
+ struct nd_pfxrouter *pfr;
+ time_t maxexpire;
+ int error;
char ip6buf[INET6_ADDRSTRLEN];
if (req->newptr)
- return EPERM;
- error = 0;
-
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
- u_short advrtrs;
- size_t advance;
- struct sockaddr_in6 *sin6, *s6;
- struct nd_pfxrouter *pfr;
+ return (EPERM);
- p = (struct in6_prefix *)buf;
- pe = (struct in6_prefix *)(buf + sizeof(buf));
+ bzero(&p, sizeof(p));
+ p.origin = PR_ORIG_RA;
+ bzero(&s6, sizeof(s6));
+ s6.sin6_family = AF_INET6;
+ s6.sin6_len = sizeof(s6);
- if (p + 1 <= pe) {
- bzero(p, sizeof(*p));
- sin6 = (struct sockaddr_in6 *)(p + 1);
-
- p->prefix = pr->ndpr_prefix;
- if (sa6_recoverscope(&p->prefix)) {
+ /*
+ * XXX locking
+ */
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
+ p.prefix = pr->ndpr_prefix;
+ if (sa6_recoverscope(&p.prefix)) {
+ log(LOG_ERR, "scope error in prefix list (%s)\n",
+ ip6_sprintf(ip6buf, &p.prefix.sin6_addr));
+ /* XXX: press on... */
+ }
+ p.raflags = pr->ndpr_raf;
+ p.prefixlen = pr->ndpr_plen;
+ p.vltime = pr->ndpr_vltime;
+ p.pltime = pr->ndpr_pltime;
+ p.if_index = pr->ndpr_ifp->if_index;
+ if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
+ p.expire = 0;
+ else {
+ /* XXX: we assume time_t is signed. */
+ maxexpire = (-1) &
+ ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
+ if (pr->ndpr_vltime < maxexpire - pr->ndpr_lastupdate)
+ p.expire = pr->ndpr_lastupdate +
+ pr->ndpr_vltime;
+ else
+ p.expire = maxexpire;
+ }
+ p.refcnt = pr->ndpr_refcnt;
+ p.flags = pr->ndpr_stateflags;
+ p.advrtrs = 0;
+ LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry)
+ p.advrtrs++;
+ error = SYSCTL_OUT(req, &p, sizeof(p));
+ if (error != 0)
+ return (error);
+ LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
+ s6.sin6_addr = pfr->router->rtaddr;
+ if (sa6_recoverscope(&s6))
log(LOG_ERR,
"scope error in prefix list (%s)\n",
- ip6_sprintf(ip6buf, &p->prefix.sin6_addr));
- /* XXX: press on... */
- }
- p->raflags = pr->ndpr_raf;
- p->prefixlen = pr->ndpr_plen;
- p->vltime = pr->ndpr_vltime;
- p->pltime = pr->ndpr_pltime;
- p->if_index = pr->ndpr_ifp->if_index;
- if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
- p->expire = 0;
- else {
- time_t maxexpire;
-
- /* XXX: we assume time_t is signed. */
- maxexpire = (-1) &
- ~((time_t)1 <<
- ((sizeof(maxexpire) * 8) - 1));
- if (pr->ndpr_vltime <
- maxexpire - pr->ndpr_lastupdate) {
- p->expire = pr->ndpr_lastupdate +
- pr->ndpr_vltime;
- } else
- p->expire = maxexpire;
- }
- p->refcnt = pr->ndpr_refcnt;
- p->flags = pr->ndpr_stateflags;
- p->origin = PR_ORIG_RA;
- advrtrs = 0;
- for (pfr = pr->ndpr_advrtrs.lh_first; pfr;
- pfr = pfr->pfr_next) {
- if ((void *)&sin6[advrtrs + 1] > (void *)pe) {
- advrtrs++;
- continue;
- }
- s6 = &sin6[advrtrs];
- bzero(s6, sizeof(*s6));
- s6->sin6_family = AF_INET6;
- s6->sin6_len = sizeof(*sin6);
- s6->sin6_addr = pfr->router->rtaddr;
- if (sa6_recoverscope(s6)) {
- log(LOG_ERR,
- "scope error in "
- "prefix list (%s)\n",
- ip6_sprintf(ip6buf,
- &pfr->router->rtaddr));
- }
- advrtrs++;
- }
- p->advrtrs = advrtrs;
- } else
- panic("buffer too short");
-
- advance = sizeof(*p) + sizeof(*sin6) * advrtrs;
- error = SYSCTL_OUT(req, buf, advance);
- if (error)
- break;
+ ip6_sprintf(ip6buf, &pfr->router->rtaddr));
+ error = SYSCTL_OUT(req, &s6, sizeof(s6));
+ if (error != 0)
+ return (error);
+ }
}
-
- return (error);
+ return (0);
}
diff --git a/freebsd/sys/netinet6/nd6.h b/freebsd/sys/netinet6/nd6.h
index 9874f6ad..0893065e 100644
--- a/freebsd/sys/netinet6/nd6.h
+++ b/freebsd/sys/netinet6/nd6.h
@@ -276,8 +276,6 @@ struct nd_prefix {
int ndpr_refcnt; /* reference couter from addresses */
};
-#define ndpr_next ndpr_entry.le_next
-
#define ndpr_raf ndpr_flags
#define ndpr_raf_onlink ndpr_flags.onlink
#define ndpr_raf_auto ndpr_flags.autonomous
@@ -311,7 +309,6 @@ struct inet6_ndpr_msghdr {
struct nd_pfxrouter {
LIST_ENTRY(nd_pfxrouter) pfr_entry;
-#define pfr_next pfr_entry.le_next
struct nd_defrouter *router;
};
@@ -404,6 +401,7 @@ void nd6_purge __P((struct ifnet *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
int nd6_resolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *));
+void nd6_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
@@ -434,15 +432,12 @@ void nd6_dad_duplicated __P((struct ifaddr *));
void nd6_rs_input __P((struct mbuf *, int, int));
void nd6_ra_input __P((struct mbuf *, int, int));
void prelist_del __P((struct nd_prefix *));
-void defrouter_addreq __P((struct nd_defrouter *));
void defrouter_reset __P((void));
void defrouter_select __P((void));
void defrtrlist_del __P((struct nd_defrouter *));
void prelist_remove __P((struct nd_prefix *));
int nd6_prelist_add __P((struct nd_prefixctl *, struct nd_defrouter *,
struct nd_prefix **));
-int nd6_prefix_onlink __P((struct nd_prefix *));
-int nd6_prefix_offlink __P((struct nd_prefix *));
void pfxlist_onlink_check __P((void));
struct nd_defrouter *defrouter_lookup __P((struct in6_addr *, struct ifnet *));
struct nd_prefix *nd6_prefix_lookup __P((struct nd_prefixctl *));
diff --git a/freebsd/sys/netinet6/nd6_nbr.c b/freebsd/sys/netinet6/nd6_nbr.c
index 599c133f..63fb25c8 100644
--- a/freebsd/sys/netinet6/nd6_nbr.c
+++ b/freebsd/sys/netinet6/nd6_nbr.c
@@ -86,6 +86,8 @@ static void nd6_dad_timer(struct dadq *);
static void nd6_dad_ns_output(struct dadq *, struct ifaddr *);
static void nd6_dad_ns_input(struct ifaddr *);
static void nd6_dad_na_input(struct ifaddr *);
+static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *,
+ const struct in6_addr *, u_long, int, struct sockaddr *, u_int);
VNET_DEFINE(int, dad_ignore_ns) = 0; /* ignore NS in DAD - specwise incorrect*/
VNET_DEFINE(int, dad_maxtry) = 15; /* max # of *tries* to transmit DAD packet */
@@ -114,7 +116,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
int anycast = 0, proxy = 0, tentative = 0;
int tlladdr;
union nd_opts ndopts;
- struct sockaddr_dl *proxydl = NULL;
+ struct sockaddr_dl proxydl;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
#ifndef PULLDOWN_TEST
@@ -239,28 +241,38 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
tsin6.sin6_family = AF_INET6;
tsin6.sin6_addr = taddr6;
+ /* Always use the default FIB. */
#ifdef RADIX_MPATH
bzero(&ro, sizeof(ro));
ro.ro_dst = tsin6;
- rtalloc_mpath((struct route *)&ro, RTF_ANNOUNCE);
+ rtalloc_mpath_fib((struct route *)&ro, RTF_ANNOUNCE,
+ RT_DEFAULT_FIB);
rt = ro.ro_rt;
#else
- rt = rtalloc1((struct sockaddr *)&tsin6, 0, 0);
+ rt = in6_rtalloc1((struct sockaddr *)&tsin6, 0, 0,
+ RT_DEFAULT_FIB);
#endif
need_proxy = (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
rt->rt_gateway->sa_family == AF_LINK);
- if (rt)
+ if (rt != NULL) {
+ /*
+ * Make a copy while we can be sure that rt_gateway
+ * is still stable before unlocking to avoid lock
+ * order problems. proxydl will only be used if
+ * proxy will be set in the next block.
+ */
+ if (need_proxy)
+ proxydl = *SDL(rt->rt_gateway);
RTFREE_LOCKED(rt);
+ }
if (need_proxy) {
/*
* proxy NDP for single entry
*/
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
- if (ifa) {
+ if (ifa)
proxy = 1;
- proxydl = SDL(rt->rt_gateway);
- }
}
}
if (ifa == NULL) {
@@ -331,20 +343,21 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
in6_all = in6addr_linklocal_allnodes;
if (in6_setscope(&in6_all, ifp, NULL) != 0)
goto bad;
- nd6_na_output(ifp, &in6_all, &taddr6,
+ nd6_na_output_fib(ifp, &in6_all, &taddr6,
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
(V_ip6_forwarding ? ND_NA_FLAG_ROUTER : 0),
- tlladdr, (struct sockaddr *)proxydl);
+ tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL,
+ M_GETFIB(m));
goto freeit;
}
nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen,
ND_NEIGHBOR_SOLICIT, 0);
- nd6_na_output(ifp, &saddr6, &taddr6,
+ nd6_na_output_fib(ifp, &saddr6, &taddr6,
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
(V_ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
- tlladdr, (struct sockaddr *)proxydl);
+ tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m));
freeit:
if (ifa != NULL)
ifa_free(ifa);
@@ -495,14 +508,16 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
int error;
struct sockaddr_in6 dst_sa;
struct in6_addr src_in;
+ struct ifnet *oifp;
bzero(&dst_sa, sizeof(dst_sa));
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = ip6->ip6_dst;
+ oifp = ifp;
error = in6_selectsrc(&dst_sa, NULL,
- NULL, &ro, NULL, NULL, &src_in);
+ NULL, &ro, NULL, &oifp, &src_in);
if (error) {
char ip6buf[INET6_ADDRSTRLEN];
nd6log((LOG_DEBUG,
@@ -917,12 +932,13 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* tlladdr - 1 if include target link-layer address
* sdl0 - sockaddr_dl (= proxy NA) or NULL
*/
-void
-nd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
+static void
+nd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
const struct in6_addr *taddr6, u_long flags, int tlladdr,
- struct sockaddr *sdl0)
+ struct sockaddr *sdl0, u_int fibnum)
{
struct mbuf *m;
+ struct ifnet *oifp;
struct ip6_hdr *ip6;
struct nd_neighbor_advert *nd_na;
struct ip6_moptions im6o;
@@ -958,6 +974,7 @@ nd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
if (m == NULL)
return;
m->m_pkthdr.rcvif = NULL;
+ M_SETFIB(m, fibnum);
if (IN6_IS_ADDR_MULTICAST(&daddr6)) {
m->m_flags |= M_MCAST;
@@ -999,7 +1016,8 @@ nd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
* Select a source whose scope is the same as that of the dest.
*/
bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
- error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, NULL, &src);
+ oifp = ifp;
+ error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &oifp, &src);
if (error) {
char ip6buf[INET6_ADDRSTRLEN];
nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
@@ -1079,6 +1097,18 @@ nd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
return;
}
+#ifndef BURN_BRIDGES
+void
+nd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
+ const struct in6_addr *taddr6, u_long flags, int tlladdr,
+ struct sockaddr *sdl0)
+{
+
+ nd6_na_output_fib(ifp, daddr6_0, taddr6, flags, tlladdr, sdl0,
+ RT_DEFAULT_FIB);
+}
+#endif
+
caddr_t
nd6_ifptomac(struct ifnet *ifp)
{
@@ -1126,11 +1156,11 @@ nd6_dad_find(struct ifaddr *ifa)
{
struct dadq *dp;
- for (dp = V_dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) {
+ TAILQ_FOREACH(dp, &V_dadq, dad_list)
if (dp->dad_ifa == ifa)
- return dp;
- }
- return NULL;
+ return (dp);
+
+ return (NULL);
}
static void
diff --git a/freebsd/sys/netinet6/nd6_rtr.c b/freebsd/sys/netinet6/nd6_rtr.c
index f2a07d96..4da54fa6 100644
--- a/freebsd/sys/netinet6/nd6_rtr.c
+++ b/freebsd/sys/netinet6/nd6_rtr.c
@@ -86,6 +86,9 @@ static int in6_init_prefix_ltimes(struct nd_prefix *);
static void in6_init_address_ltimes __P((struct nd_prefix *,
struct in6_addrlifetime *));
+static int nd6_prefix_onlink(struct nd_prefix *);
+static int nd6_prefix_offlink(struct nd_prefix *);
+
static int rt6_deleteroute(struct radix_node *, void *);
VNET_DECLARE(int, nd6_recalc_reachtm_interval);
@@ -443,21 +446,21 @@ nd6_rtmsg(int cmd, struct rtentry *rt)
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
ifp = rt->rt_ifp;
if (ifp != NULL) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
ifa = TAILQ_FIRST(&ifp->if_addrhead);
info.rti_info[RTAX_IFP] = ifa->ifa_addr;
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
} else
ifa = NULL;
- rt_missmsg(cmd, &info, rt->rt_flags, 0);
+ rt_missmsg_fib(cmd, &info, rt->rt_flags, 0, rt->rt_fibnum);
if (ifa != NULL)
ifa_free(ifa);
}
-void
+static void
defrouter_addreq(struct nd_defrouter *new)
{
struct sockaddr_in6 def, mask, gate;
@@ -475,9 +478,9 @@ defrouter_addreq(struct nd_defrouter *new)
gate.sin6_addr = new->rtaddr;
s = splnet();
- error = rtrequest(RTM_ADD, (struct sockaddr *)&def,
+ error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&def,
(struct sockaddr *)&gate, (struct sockaddr *)&mask,
- RTF_GATEWAY, &newrt);
+ RTF_GATEWAY, &newrt, RT_DEFAULT_FIB);
if (newrt) {
nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
RTFREE(newrt);
@@ -493,8 +496,7 @@ defrouter_lookup(struct in6_addr *addr, struct ifnet *ifp)
{
struct nd_defrouter *dr;
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
return (dr);
}
@@ -522,9 +524,9 @@ defrouter_delreq(struct nd_defrouter *dr)
def.sin6_family = gate.sin6_family = AF_INET6;
gate.sin6_addr = dr->rtaddr;
- rtrequest(RTM_DELETE, (struct sockaddr *)&def,
+ in6_rtrequest(RTM_DELETE, (struct sockaddr *)&def,
(struct sockaddr *)&gate,
- (struct sockaddr *)&mask, RTF_GATEWAY, &oldrt);
+ (struct sockaddr *)&mask, RTF_GATEWAY, &oldrt, RT_DEFAULT_FIB);
if (oldrt) {
nd6_rtmsg(RTM_DELETE, oldrt);
RTFREE(oldrt);
@@ -541,8 +543,7 @@ defrouter_reset(void)
{
struct nd_defrouter *dr;
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry))
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry)
defrouter_delreq(dr);
/*
@@ -573,7 +574,7 @@ defrtrlist_del(struct nd_defrouter *dr)
/*
* Also delete all the pointers to the router in each prefix lists.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
struct nd_pfxrouter *pfxrtr;
if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
pfxrtr_del(pfxrtr);
@@ -637,7 +638,7 @@ defrouter_select(void)
* Let's handle easy case (3) first:
* If default router list is empty, there's nothing to be done.
*/
- if (!TAILQ_FIRST(&V_nd_defrouter)) {
+ if (TAILQ_EMPTY(&V_nd_defrouter)) {
splx(s);
return;
}
@@ -647,15 +648,14 @@ defrouter_select(void)
* We just pick up the first reachable one (if any), assuming that
* the ordering rule of the list described in defrtrlist_update().
*/
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
- IF_AFDATA_LOCK(dr->ifp);
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
+ IF_AFDATA_RLOCK(dr->ifp);
if (selected_dr == NULL &&
(ln = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
ND6_IS_LLINFO_PROBREACH(ln)) {
selected_dr = dr;
}
- IF_AFDATA_UNLOCK(dr->ifp);
+ IF_AFDATA_RUNLOCK(dr->ifp);
if (ln != NULL) {
LLE_RUNLOCK(ln);
ln = NULL;
@@ -683,13 +683,13 @@ defrouter_select(void)
else
selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
} else if (installed_dr) {
- IF_AFDATA_LOCK(installed_dr->ifp);
+ IF_AFDATA_RLOCK(installed_dr->ifp);
if ((ln = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
ND6_IS_LLINFO_PROBREACH(ln) &&
rtpref(selected_dr) <= rtpref(installed_dr)) {
selected_dr = installed_dr;
}
- IF_AFDATA_UNLOCK(installed_dr->ifp);
+ IF_AFDATA_RUNLOCK(installed_dr->ifp);
if (ln != NULL)
LLE_RUNLOCK(ln);
}
@@ -757,9 +757,10 @@ defrtrlist_update(struct nd_defrouter *new)
/*
* If the preference does not change, there's no need
- * to sort the entries.
+ * to sort the entries. Also make sure the selected
+ * router is still installed in the kernel.
*/
- if (rtpref(new) == oldpref) {
+ if (dr->installed && rtpref(new) == oldpref) {
splx(s);
return (dr);
}
@@ -804,8 +805,7 @@ insert:
*/
/* insert at the end of the group */
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
if (rtpref(n) > rtpref(dr))
break;
}
@@ -826,7 +826,7 @@ pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
{
struct nd_pfxrouter *search;
- for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) {
+ LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) {
if (search->router == dr)
break;
}
@@ -862,8 +862,7 @@ nd6_prefix_lookup(struct nd_prefixctl *key)
{
struct nd_prefix *search;
- for (search = V_nd_prefix.lh_first;
- search; search = search->ndpr_next) {
+ LIST_FOREACH(search, &V_nd_prefix, ndpr_entry) {
if (key->ndpr_ifp == search->ndpr_ifp &&
key->ndpr_plen == search->ndpr_plen &&
in6_are_prefix_equal(&key->ndpr_prefix.sin6_addr,
@@ -969,9 +968,7 @@ prelist_remove(struct nd_prefix *pr)
LIST_REMOVE(pr, ndpr_entry);
/* free list of routers that adversed the prefix */
- for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
- next = pfr->pfr_next;
-
+ LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next) {
free(pfr, M_IP6NDP);
}
splx(s);
@@ -1119,7 +1116,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
* consider autoconfigured addresses while RFC2462 simply said
* "address".
*/
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct in6_ifaddr *ifa6;
u_int32_t remaininglifetime;
@@ -1242,7 +1239,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
ifa6->ia6_lifetime = lt6_tmp;
ifa6->ia6_updatetime = time_second;
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (ia6_match == NULL && new->ndpr_vltime) {
int ifidlen;
@@ -1334,11 +1331,10 @@ find_pfxlist_reachable_router(struct nd_prefix *pr)
struct llentry *ln;
int canreach;
- for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr != NULL;
- pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
- IF_AFDATA_LOCK(pfxrtr->router->ifp);
+ LIST_FOREACH(pfxrtr, &pr->ndpr_advrtrs, pfr_entry) {
+ IF_AFDATA_RLOCK(pfxrtr->router->ifp);
ln = nd6_lookup(&pfxrtr->router->rtaddr, 0, pfxrtr->router->ifp);
- IF_AFDATA_UNLOCK(pfxrtr->router->ifp);
+ IF_AFDATA_RUNLOCK(pfxrtr->router->ifp);
if (ln == NULL)
continue;
canreach = ND6_IS_LLINFO_PROBREACH(ln);
@@ -1374,7 +1370,7 @@ pfxlist_onlink_check()
* Check if there is a prefix that has a reachable advertising
* router.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr))
break;
}
@@ -1384,12 +1380,10 @@ pfxlist_onlink_check()
* that does not advertise any prefixes.
*/
if (pr == NULL) {
- for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
- dr = TAILQ_NEXT(dr, dr_entry)) {
+ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
struct nd_prefix *pr0;
- for (pr0 = V_nd_prefix.lh_first; pr0;
- pr0 = pr0->ndpr_next) {
+ LIST_FOREACH(pr0, &V_nd_prefix, ndpr_entry) {
if ((pfxrtr = pfxrtr_lookup(pr0, dr)) != NULL)
break;
}
@@ -1397,7 +1391,7 @@ pfxlist_onlink_check()
break;
}
}
- if (pr != NULL || (TAILQ_FIRST(&V_nd_defrouter) && pfxrtr == NULL)) {
+ if (pr != NULL || (!TAILQ_EMPTY(&V_nd_defrouter) && pfxrtr == NULL)) {
/*
* There is at least one prefix that has a reachable router,
* or at least a router which probably does not advertise
@@ -1407,7 +1401,7 @@ pfxlist_onlink_check()
* Detach prefixes which have no reachable advertising
* router, and attach other prefixes.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
/* XXX: a link-local prefix should never be detached */
if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
continue;
@@ -1431,7 +1425,7 @@ pfxlist_onlink_check()
}
} else {
/* there is no prefix that has a reachable router */
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
continue;
@@ -1454,7 +1448,7 @@ pfxlist_onlink_check()
* interfaces. Such cases will be handled in nd6_prefix_onlink,
* so we don't have to care about them.
*/
- for (pr = V_nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
+ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
int e;
char ip6buf[INET6_ADDRSTRLEN];
@@ -1552,19 +1546,92 @@ pfxlist_onlink_check()
}
}
-int
+static int
+nd6_prefix_onlink_rtrequest(struct nd_prefix *pr, struct ifaddr *ifa)
+{
+ static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
+ struct radix_node_head *rnh;
+ struct rtentry *rt;
+ struct sockaddr_in6 mask6;
+ u_long rtflags;
+ int error, a_failure, fibnum;
+
+ /*
+ * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
+ * ifa->ifa_rtrequest = nd6_rtrequest;
+ */
+ bzero(&mask6, sizeof(mask6));
+ mask6.sin6_len = sizeof(mask6);
+ mask6.sin6_addr = pr->ndpr_mask;
+ rtflags = (ifa->ifa_flags & ~IFA_RTSELF) | RTF_UP;
+
+ a_failure = 0;
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
+
+ rt = NULL;
+ error = in6_rtrequest(RTM_ADD,
+ (struct sockaddr *)&pr->ndpr_prefix, ifa->ifa_addr,
+ (struct sockaddr *)&mask6, rtflags, &rt, fibnum);
+ if (error == 0) {
+ KASSERT(rt != NULL, ("%s: in6_rtrequest return no "
+ "error(%d) but rt is NULL, pr=%p, ifa=%p", __func__,
+ error, pr, ifa));
+
+ rnh = rt_tables_get_rnh(rt->rt_fibnum, AF_INET6);
+ /* XXX what if rhn == NULL? */
+ RADIX_NODE_HEAD_LOCK(rnh);
+ RT_LOCK(rt);
+ if (rt_setgate(rt, rt_key(rt),
+ (struct sockaddr *)&null_sdl) == 0) {
+ struct sockaddr_dl *dl;
+
+ dl = (struct sockaddr_dl *)rt->rt_gateway;
+ dl->sdl_type = rt->rt_ifp->if_type;
+ dl->sdl_index = rt->rt_ifp->if_index;
+ }
+ RADIX_NODE_HEAD_UNLOCK(rnh);
+ nd6_rtmsg(RTM_ADD, rt);
+ RT_UNLOCK(rt);
+ pr->ndpr_stateflags |= NDPRF_ONLINK;
+ } else {
+ char ip6buf[INET6_ADDRSTRLEN];
+ char ip6bufg[INET6_ADDRSTRLEN];
+ char ip6bufm[INET6_ADDRSTRLEN];
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+ nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add "
+ "route for a prefix (%s/%d) on %s, gw=%s, mask=%s, "
+ "flags=%lx errno = %d\n",
+ ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
+ pr->ndpr_plen, if_name(pr->ndpr_ifp),
+ ip6_sprintf(ip6bufg, &sin6->sin6_addr),
+ ip6_sprintf(ip6bufm, &mask6.sin6_addr),
+ rtflags, error));
+
+ /* Save last error to return, see rtinit(). */
+ a_failure = error;
+ }
+
+ if (rt != NULL) {
+ RT_LOCK(rt);
+ RT_REMREF(rt);
+ RT_UNLOCK(rt);
+ }
+ }
+
+ /* Return the last error we got. */
+ return (a_failure);
+}
+
+static int
nd6_prefix_onlink(struct nd_prefix *pr)
{
struct ifaddr *ifa;
struct ifnet *ifp = pr->ndpr_ifp;
- struct sockaddr_in6 mask6;
struct nd_prefix *opr;
- u_long rtflags;
int error = 0;
- struct radix_node_head *rnh;
- struct rtentry *rt = NULL;
char ip6buf[INET6_ADDRSTRLEN];
- struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
/* sanity check */
if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
@@ -1582,7 +1649,7 @@ nd6_prefix_onlink(struct nd_prefix *pr)
* Although such a configuration is expected to be rare, we explicitly
* allow it.
*/
- for (opr = V_nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
+ LIST_FOREACH(opr, &V_nd_prefix, ndpr_entry) {
if (opr == pr)
continue;
@@ -1603,14 +1670,14 @@ nd6_prefix_onlink(struct nd_prefix *pr)
IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
if (ifa == NULL) {
/* XXX: freebsd does not have ifa_ifwithaf */
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family == AF_INET6)
break;
}
if (ifa != NULL)
ifa_ref(ifa);
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/* should we care about ia6_flags? */
}
if (ifa == NULL) {
@@ -1628,64 +1695,24 @@ nd6_prefix_onlink(struct nd_prefix *pr)
return (0);
}
- /*
- * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
- * ifa->ifa_rtrequest = nd6_rtrequest;
- */
- bzero(&mask6, sizeof(mask6));
- mask6.sin6_len = sizeof(mask6);
- mask6.sin6_addr = pr->ndpr_mask;
- rtflags = (ifa->ifa_flags & ~IFA_RTSELF) | RTF_UP;
- error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
- ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
- if (error == 0) {
- if (rt != NULL) /* this should be non NULL, though */ {
- rnh = rt_tables_get_rnh(rt->rt_fibnum, AF_INET6);
- /* XXX what if rhn == NULL? */
- RADIX_NODE_HEAD_LOCK(rnh);
- RT_LOCK(rt);
- if (!rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl)) {
- ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
- rt->rt_ifp->if_type;
- ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
- rt->rt_ifp->if_index;
- }
- RADIX_NODE_HEAD_UNLOCK(rnh);
- nd6_rtmsg(RTM_ADD, rt);
- RT_UNLOCK(rt);
- }
- pr->ndpr_stateflags |= NDPRF_ONLINK;
- } else {
- char ip6bufg[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
- nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
- " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
- "errno = %d\n",
- ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
- pr->ndpr_plen, if_name(ifp),
- ip6_sprintf(ip6bufg, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
- ip6_sprintf(ip6bufm, &mask6.sin6_addr), rtflags, error));
- }
+ error = nd6_prefix_onlink_rtrequest(pr, ifa);
- if (rt != NULL) {
- RT_LOCK(rt);
- RT_REMREF(rt);
- RT_UNLOCK(rt);
- }
if (ifa != NULL)
ifa_free(ifa);
return (error);
}
-int
+static int
nd6_prefix_offlink(struct nd_prefix *pr)
{
int error = 0;
struct ifnet *ifp = pr->ndpr_ifp;
struct nd_prefix *opr;
struct sockaddr_in6 sa6, mask6;
- struct rtentry *rt = NULL;
+ struct rtentry *rt;
char ip6buf[INET6_ADDRSTRLEN];
+ int fibnum, a_failure;
/* sanity check */
if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
@@ -1705,15 +1732,28 @@ nd6_prefix_offlink(struct nd_prefix *pr)
mask6.sin6_family = AF_INET6;
mask6.sin6_len = sizeof(sa6);
bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
- error = rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL,
- (struct sockaddr *)&mask6, 0, &rt);
+
+ a_failure = 0;
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
+ rt = NULL;
+ error = in6_rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL,
+ (struct sockaddr *)&mask6, 0, &rt, fibnum);
+ if (error == 0) {
+ /* report the route deletion to the routing socket. */
+ if (rt != NULL)
+ nd6_rtmsg(RTM_DELETE, rt);
+ } else {
+ /* Save last error to return, see rtinit(). */
+ a_failure = error;
+ }
+ if (rt != NULL) {
+ RTFREE(rt);
+ }
+ }
+ error = a_failure;
if (error == 0) {
pr->ndpr_stateflags &= ~NDPRF_ONLINK;
- /* report the route deletion to the routing socket. */
- if (rt != NULL)
- nd6_rtmsg(RTM_DELETE, rt);
-
/*
* There might be the same prefix on another interface,
* the prefix which could not be on-link just because we have
@@ -1721,7 +1761,7 @@ nd6_prefix_offlink(struct nd_prefix *pr)
* If there's one, try to make the prefix on-link on the
* interface.
*/
- for (opr = V_nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
+ LIST_FOREACH(opr, &V_nd_prefix, ndpr_entry) {
if (opr == pr)
continue;
@@ -1761,10 +1801,6 @@ nd6_prefix_offlink(struct nd_prefix *pr)
if_name(ifp), error));
}
- if (rt != NULL) {
- RTFREE(rt);
- }
-
return (error);
}
@@ -2081,6 +2117,7 @@ void
rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
{
struct radix_node_head *rnh;
+ u_int fibnum;
int s = splnet();
/* We'll care only link-local addresses */
@@ -2089,13 +2126,16 @@ rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
return;
}
- rnh = rt_tables_get_rnh(0, AF_INET6);
- if (rnh == NULL)
- return;
+ /* XXX Do we really need to walk any but the default FIB? */
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
+ rnh = rt_tables_get_rnh(fibnum, AF_INET6);
+ if (rnh == NULL)
+ continue;
- RADIX_NODE_HEAD_LOCK(rnh);
- rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
- RADIX_NODE_HEAD_UNLOCK(rnh);
+ RADIX_NODE_HEAD_LOCK(rnh);
+ rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
+ RADIX_NODE_HEAD_UNLOCK(rnh);
+ }
splx(s);
}
@@ -2128,8 +2168,8 @@ rt6_deleteroute(struct radix_node *rn, void *arg)
if ((rt->rt_flags & RTF_HOST) == 0)
return (0);
- return (rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
- rt_mask(rt), rt->rt_flags, 0));
+ return (in6_rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
+ rt_mask(rt), rt->rt_flags, NULL, rt->rt_fibnum));
#undef SIN6
}
diff --git a/freebsd/sys/netinet6/raw_ip6.c b/freebsd/sys/netinet6/raw_ip6.c
index 9ea1895d..45645e29 100644
--- a/freebsd/sys/netinet6/raw_ip6.c
+++ b/freebsd/sys/netinet6/raw_ip6.c
@@ -197,6 +197,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
&ip6->ip6_dst) != 0)
continue;
}
+ INP_RLOCK(in6p);
if (in6p->in6p_cksum != -1) {
V_rip6stat.rip6s_isum++;
if (in6_cksum(m, proto, *offp,
@@ -206,7 +207,6 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
continue;
}
}
- INP_RLOCK(in6p);
/*
* If this raw socket has multicast state, and we
* have received a multicast, check if this socket
@@ -564,6 +564,7 @@ rip6_output(m, va_alist)
int
rip6_ctloutput(struct socket *so, struct sockopt *sopt)
{
+ struct inpcb *inp;
int error;
if (sopt->sopt_level == IPPROTO_ICMPV6)
@@ -572,8 +573,17 @@ rip6_ctloutput(struct socket *so, struct sockopt *sopt)
* from protosw?
*/
return (icmp6_ctloutput(so, sopt));
- else if (sopt->sopt_level != IPPROTO_IPV6)
+ else if (sopt->sopt_level != IPPROTO_IPV6) {
+ if (sopt->sopt_level == SOL_SOCKET &&
+ sopt->sopt_name == SO_SETFIB) {
+ inp = sotoinpcb(so);
+ INP_WLOCK(inp);
+ inp->inp_inc.inc_fibnum = so->so_fibnum;
+ INP_WUNLOCK(inp);
+ return (0);
+ }
return (EINVAL);
+ }
error = 0;
diff --git a/freebsd/sys/netinet6/scope6.c b/freebsd/sys/netinet6/scope6.c
index 655022d6..a5c7d7b1 100644
--- a/freebsd/sys/netinet6/scope6.c
+++ b/freebsd/sys/netinet6/scope6.c
@@ -123,11 +123,11 @@ scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
int error = 0;
struct scope6_id *sid = NULL;
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_WLOCK(ifp);
sid = SID(ifp);
if (!sid) { /* paranoid? */
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_WUNLOCK(ifp);
return (EINVAL);
}
@@ -141,7 +141,6 @@ scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
* interface addresses, routing table entries, PCB entries...
*/
- SCOPE6_LOCK();
for (i = 0; i < 16; i++) {
if (idlist->s6id_list[i] &&
idlist->s6id_list[i] != sid->s6id_list[i]) {
@@ -151,8 +150,7 @@ scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
*/
if (i == IPV6_ADDR_SCOPE_INTFACELOCAL &&
idlist->s6id_list[i] != ifp->if_index) {
- IF_AFDATA_UNLOCK(ifp);
- SCOPE6_UNLOCK();
+ IF_AFDATA_WUNLOCK(ifp);
return (EINVAL);
}
@@ -164,8 +162,7 @@ scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
* IDs, but we check the consistency for
* safety in later use.
*/
- IF_AFDATA_UNLOCK(ifp);
- SCOPE6_UNLOCK();
+ IF_AFDATA_WUNLOCK(ifp);
return (EINVAL);
}
@@ -177,8 +174,7 @@ scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
sid->s6id_list[i] = idlist->s6id_list[i];
}
}
- SCOPE6_UNLOCK();
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_WUNLOCK(ifp);
return (error);
}
@@ -186,20 +182,19 @@ scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
int
scope6_get(struct ifnet *ifp, struct scope6_id *idlist)
{
- /* We only need to lock the interface's afdata for SID() to work. */
- IF_AFDATA_LOCK(ifp);
- struct scope6_id *sid = SID(ifp);
+ struct scope6_id *sid;
+ /* We only need to lock the interface's afdata for SID() to work. */
+ IF_AFDATA_RLOCK(ifp);
+ sid = SID(ifp);
if (sid == NULL) { /* paranoid? */
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
return (EINVAL);
}
- SCOPE6_LOCK();
*idlist = *sid;
- SCOPE6_UNLOCK();
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
return (0);
}
@@ -390,7 +385,7 @@ sa6_recoverscope(struct sockaddr_in6 *sin6)
zoneid = ntohs(sin6->sin6_addr.s6_addr16[1]);
if (zoneid) {
/* sanity check */
- if (zoneid < 0 || V_if_index < zoneid)
+ if (V_if_index < zoneid)
return (ENXIO);
if (!ifnet_byindex(zoneid))
return (ENXIO);
@@ -416,7 +411,7 @@ in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
u_int32_t zoneid = 0;
struct scope6_id *sid;
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_RLOCK(ifp);
sid = SID(ifp);
@@ -433,19 +428,17 @@ in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
*/
if (IN6_IS_ADDR_LOOPBACK(in6)) {
if (!(ifp->if_flags & IFF_LOOPBACK)) {
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
return (EINVAL);
} else {
if (ret_id != NULL)
*ret_id = 0; /* there's no ambiguity */
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
return (0);
}
}
scope = in6_addrscope(in6);
-
- SCOPE6_LOCK();
switch (scope) {
case IPV6_ADDR_SCOPE_INTFACELOCAL: /* should be interface index */
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL];
@@ -467,8 +460,7 @@ in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
zoneid = 0; /* XXX: treat as global. */
break;
}
- SCOPE6_UNLOCK();
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
if (ret_id != NULL)
*ret_id = zoneid;
@@ -496,3 +488,16 @@ in6_clearscope(struct in6_addr *in6)
return (modified);
}
+
+/*
+ * Return the scope identifier or zero.
+ */
+uint16_t
+in6_getscope(struct in6_addr *in6)
+{
+
+ if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6))
+ return (in6->s6_addr16[1]);
+
+ return (0);
+}
diff --git a/freebsd/sys/netinet6/scope6_var.h b/freebsd/sys/netinet6/scope6_var.h
index 55e0c8ed..2248037f 100644
--- a/freebsd/sys/netinet6/scope6_var.h
+++ b/freebsd/sys/netinet6/scope6_var.h
@@ -49,12 +49,12 @@ int scope6_set __P((struct ifnet *, struct scope6_id *));
int scope6_get __P((struct ifnet *, struct scope6_id *));
void scope6_setdefault __P((struct ifnet *));
int scope6_get_default __P((struct scope6_id *));
-u_int32_t scope6_in6_addrscope __P((struct in6_addr *));
u_int32_t scope6_addr2default __P((struct in6_addr *));
int sa6_embedscope __P((struct sockaddr_in6 *, int));
int sa6_recoverscope __P((struct sockaddr_in6 *));
int in6_setscope __P((struct in6_addr *, struct ifnet *, u_int32_t *));
int in6_clearscope __P((struct in6_addr *));
+uint16_t in6_getscope(struct in6_addr *);
#endif /* _KERNEL */
#endif /* _NETINET6_SCOPE6_VAR_H_ */
diff --git a/freebsd/sys/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c
index 16b9e4fd..0551d48b 100644
--- a/freebsd/sys/netinet6/sctp6_usrreq.c
+++ b/freebsd/sys/netinet6/sctp6_usrreq.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -29,17 +31,17 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp6_usrreq.c,v 1.38 2005/08/24 08:08:56 suz Exp $ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <netinet/sctp_os.h>
+#ifdef INET6
#include <sys/proc.h>
#include <netinet/sctp_pcb.h>
#include <netinet/sctp_header.h>
#include <netinet/sctp_var.h>
-#if defined(INET6)
+#ifdef INET6
#include <netinet6/sctp6_var.h>
#endif
#include <netinet/sctp_sysctl.h>
@@ -58,7 +60,7 @@ __FBSDID("$FreeBSD$");
#ifdef IPSEC
#include <netipsec/ipsec.h>
-#if defined(INET6)
+#ifdef INET6
#include <netipsec/ipsec6.h>
#endif /* INET6 */
#endif /* IPSEC */
@@ -66,222 +68,140 @@ __FBSDID("$FreeBSD$");
extern struct protosw inetsw[];
int
-sctp6_input(struct mbuf **i_pak, int *offp, int proto)
+sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
{
struct mbuf *m;
+ int iphlen;
+ uint32_t vrf_id;
+ uint8_t ecn_bits;
+ struct sockaddr_in6 src, dst;
struct ip6_hdr *ip6;
struct sctphdr *sh;
- struct sctp_inpcb *in6p = NULL;
- struct sctp_nets *net;
- int refcount_up = 0;
- uint32_t vrf_id = 0;
-
-#ifdef IPSEC
- struct inpcb *in6p_ip;
-
-#endif
struct sctp_chunkhdr *ch;
- int length, offset, iphlen;
- uint8_t ecn_bits;
- struct sctp_tcb *stcb = NULL;
- int pkt_len = 0;
+ int length, offset;
#if !defined(SCTP_WITH_NO_CSUM)
- uint32_t check, calc_check;
+ uint8_t compute_crc;
#endif
- int off = *offp;
- uint16_t port = 0;
+ uint32_t mflowid;
+ uint8_t use_mflowid;
- /* get the VRF and table id's */
+ iphlen = *offp;
if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
SCTP_RELEASE_PKT(*i_pak);
- return (-1);
+ return (IPPROTO_DONE);
}
m = SCTP_HEADER_TO_CHAIN(*i_pak);
- pkt_len = SCTP_HEADER_LEN((*i_pak));
-
-#ifdef SCTP_PACKET_LOGGING
- sctp_packet_log(m, pkt_len);
+#ifdef SCTP_MBUF_LOGGING
+ /* Log in any input mbufs */
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
+ struct mbuf *mat;
+
+ for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
+ if (SCTP_BUF_IS_EXTENDED(mat)) {
+ sctp_log_mb(mat, SCTP_MBUF_INPUT);
+ }
+ }
+ }
#endif
+#ifdef SCTP_PACKET_LOGGING
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
+ sctp_packet_log(m);
+ }
+#endif
+ SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
+ "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
+ m->m_pkthdr.len,
+ if_name(m->m_pkthdr.rcvif),
+ m->m_pkthdr.csum_flags);
+ if (m->m_flags & M_FLOWID) {
+ mflowid = m->m_pkthdr.flowid;
+ use_mflowid = 1;
+ } else {
+ mflowid = 0;
+ use_mflowid = 0;
+ }
+ SCTP_STAT_INCR(sctps_recvpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
+ /* Get IP, SCTP, and first chunk header together in the first mbuf. */
+ offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
ip6 = mtod(m, struct ip6_hdr *);
- /* Ensure that (sctphdr + sctp_chunkhdr) in a row. */
- IP6_EXTHDR_GET(sh, struct sctphdr *, m, off,
- (int)(sizeof(*sh) + sizeof(*ch)));
+ IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen,
+ (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
if (sh == NULL) {
SCTP_STAT_INCR(sctps_hdrops);
- return IPPROTO_DONE;
+ return (IPPROTO_DONE);
}
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
- iphlen = off;
- offset = iphlen + sizeof(*sh) + sizeof(*ch);
- SCTPDBG(SCTP_DEBUG_INPUT1,
- "sctp6_input() length:%d iphlen:%d\n", pkt_len, iphlen);
-
-
-#if defined(NFAITH) && NFAITH > 0
-
- if (faithprefix_p != NULL && (*faithprefix_p) (&ip6->ip6_dst)) {
+ offset -= sizeof(struct sctp_chunkhdr);
+ memset(&src, 0, sizeof(struct sockaddr_in6));
+ src.sin6_family = AF_INET6;
+ src.sin6_len = sizeof(struct sockaddr_in6);
+ src.sin6_port = sh->src_port;
+ src.sin6_addr = ip6->ip6_src;
+ if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
+ goto out;
+ }
+ memset(&dst, 0, sizeof(struct sockaddr_in6));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_len = sizeof(struct sockaddr_in6);
+ dst.sin6_port = sh->dest_port;
+ dst.sin6_addr = ip6->ip6_dst;
+ if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
+ goto out;
+ }
+ if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) {
/* XXX send icmp6 host/port unreach? */
- goto bad;
+ goto out;
+ }
+ length = ntohs(ip6->ip6_plen) + iphlen;
+ /* Validate mbuf chain length with IP payload length. */
+ if (SCTP_HEADER_LEN(m) != length) {
+ SCTPDBG(SCTP_DEBUG_INPUT1,
+ "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
+ SCTP_STAT_INCR(sctps_hdrops);
+ goto out;
}
-#endif /* NFAITH defined and > 0 */
- SCTP_STAT_INCR(sctps_recvpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
- SCTPDBG(SCTP_DEBUG_INPUT1, "V6 input gets a packet iphlen:%d pktlen:%d\n",
- iphlen, pkt_len);
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
- /* No multi-cast support in SCTP */
- goto bad;
+ goto out;
}
- /* destination port of 0 is illegal, based on RFC2960. */
- if (sh->dest_port == 0)
- goto bad;
-
- SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
- "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
- m->m_pkthdr.len,
- if_name(m->m_pkthdr.rcvif),
- m->m_pkthdr.csum_flags);
+ ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_recvnocrc);
#else
if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
SCTP_STAT_INCR(sctps_recvhwcrc);
- goto sctp_skip_csum;
- }
- check = sh->checksum; /* save incoming checksum */
- if ((check == 0) && (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback)) &&
- (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &ip6->ip6_dst))) {
- SCTP_STAT_INCR(sctps_recvnocrc);
- goto sctp_skip_csum;
- }
- sh->checksum = 0; /* prepare for calc */
- calc_check = sctp_calculate_cksum(m, iphlen);
- SCTP_STAT_INCR(sctps_recvswcrc);
- if (calc_check != check) {
- SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p phlen:%d\n",
- calc_check, check, m, iphlen);
- stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
- sh, ch, &in6p, &net, vrf_id);
- if ((net) && (port)) {
- if (net->port == 0) {
- sctp_pathmtu_adjustment(in6p, stcb, net, net->mtu - sizeof(struct udphdr));
- }
- net->port = port;
- }
- /* in6p's ref-count increased && stcb locked */
- if ((in6p) && (stcb)) {
- sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
- sctp_chunk_output((struct sctp_inpcb *)in6p, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
- } else if ((in6p != NULL) && (stcb == NULL)) {
- refcount_up = 1;
- }
- SCTP_STAT_INCR(sctps_badsum);
- SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
- goto bad;
+ compute_crc = 0;
+ } else {
+ SCTP_STAT_INCR(sctps_recvswcrc);
+ compute_crc = 1;
}
- sh->checksum = calc_check;
-
-sctp_skip_csum:
#endif
- net = NULL;
- /*
- * Locate pcb and tcb for datagram sctp_findassociation_addr() wants
- * IP/SCTP/first chunk header...
- */
- stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
- sh, ch, &in6p, &net, vrf_id);
- if ((net) && (port)) {
- if (net->port == 0) {
- sctp_pathmtu_adjustment(in6p, stcb, net, net->mtu - sizeof(struct udphdr));
- }
- net->port = port;
- }
- /* in6p's ref-count increased */
- if (in6p == NULL) {
- struct sctp_init_chunk *init_chk, chunk_buf;
-
- SCTP_STAT_INCR(sctps_noport);
- if (ch->chunk_type == SCTP_INITIATION) {
- /*
- * we do a trick here to get the INIT tag, dig in
- * and get the tag from the INIT and put it in the
- * common header.
- */
- init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
- iphlen + sizeof(*sh), sizeof(*init_chk),
- (uint8_t *) & chunk_buf);
- if (init_chk)
- sh->v_tag = init_chk->init.initiate_tag;
- else
- sh->v_tag = 0;
- }
- if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
- sctp_send_shutdown_complete2(m, iphlen, sh, vrf_id, port);
- goto bad;
- }
- if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
- goto bad;
- }
- if (ch->chunk_type != SCTP_ABORT_ASSOCIATION)
- sctp_send_abort(m, iphlen, sh, 0, NULL, vrf_id, port);
- goto bad;
- } else if (stcb == NULL) {
- refcount_up = 1;
- }
-#ifdef IPSEC
- /*
- * Check AH/ESP integrity.
- */
- in6p_ip = (struct inpcb *)in6p;
- if (in6p_ip && (ipsec6_in_reject(m, in6p_ip))) {
-/* XXX */
- MODULE_GLOBAL(ipsec6stat).in_polvio++;
- goto bad;
- }
-#endif /* IPSEC */
-
- /*
- * CONTROL chunk processing
- */
- offset -= sizeof(*ch);
- ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
-
- /* Length now holds the total packet length payload + iphlen */
- length = ntohs(ip6->ip6_plen) + iphlen;
-
- /* sa_ignore NO_NULL_CHK */
- sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
- in6p, stcb, net, ecn_bits, vrf_id, port);
- /* inp's ref-count reduced && stcb unlocked */
- /* XXX this stuff below gets moved to appropriate parts later... */
- if (m)
+ sctp_common_input_processing(&m, iphlen, offset, length,
+ (struct sockaddr *)&src,
+ (struct sockaddr *)&dst,
+ sh, ch,
+#if !defined(SCTP_WITH_NO_CSUM)
+ compute_crc,
+#endif
+ ecn_bits,
+ use_mflowid, mflowid,
+ vrf_id, port);
+out:
+ if (m) {
sctp_m_freem(m);
- if ((in6p) && refcount_up) {
- /* reduce ref-count */
- SCTP_INP_WLOCK(in6p);
- SCTP_INP_DECR_REF(in6p);
- SCTP_INP_WUNLOCK(in6p);
- }
- return IPPROTO_DONE;
-
-bad:
- if (stcb) {
- SCTP_TCB_UNLOCK(stcb);
}
- if ((in6p) && refcount_up) {
- /* reduce ref-count */
- SCTP_INP_WLOCK(in6p);
- SCTP_INP_DECR_REF(in6p);
- SCTP_INP_WUNLOCK(in6p);
- }
- if (m)
- sctp_m_freem(m);
- return IPPROTO_DONE;
+ return (IPPROTO_DONE);
}
+int
+sctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
+{
+ return (sctp6_input_with_port(i_pak, offp, 0));
+}
+
static void
sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6,
struct sctphdr *sh, struct sctp_tcb *stcb, struct sctp_nets *net)
@@ -367,14 +287,12 @@ sctp6_notify(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
- /* protection */
- int reason;
-
+ /* protection */
if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
(sh == NULL) || (to == NULL)) {
if (stcb)
@@ -408,36 +326,10 @@ sctp6_notify(struct sctp_inpcb *inp,
*/
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
- SCTP_PRINTF("ICMP (thresh %d/%d) takes interface %p down\n",
- net->error_count,
- net->failure_threshold,
- net);
-
net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
- /*
- * JRS 5/14/07 - If a destination is unreachable,
- * the PF bit is turned off. This allows an
- * unambiguous use of the PF bit for destinations
- * that are reachable but potentially failed. If the
- * destination is set to the unreachable state, also
- * set the destination to the PF state.
- */
- /*
- * Add debug message here if destination is not in
- * PF state.
- */
- /* Stop any running T3 timers here? */
- if ((stcb->asoc.sctp_cmt_on_off == 1) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
- net);
- }
- net->error_count = net->failure_threshold + 1;
+ net->dest_state &= ~SCTP_ADDR_PF;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
- stcb, SCTP_FAILED_THRESHOLD,
- (void *)net, SCTP_SO_NOT_LOCKED);
+ stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED);
}
SCTP_TCB_UNLOCK(stcb);
} else if ((icmph->icmp6_code == ICMP_UNREACH_PROTOCOL) ||
@@ -449,9 +341,8 @@ sctp6_notify(struct sctp_inpcb *inp,
* now is dead. In either case treat it like a OOTB abort
* with no TCB
*/
- reason = SCTP_PEER_FAULTY;
- sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -460,7 +351,7 @@ sctp6_notify(struct sctp_inpcb *inp,
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
#endif
@@ -524,8 +415,8 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
final.sin6_family = AF_INET6;
final.sin6_addr = ((struct sockaddr_in6 *)pktdst)->sin6_addr;
final.sin6_port = sh.dest_port;
- stcb = sctp_findassociation_addr_sa((struct sockaddr *)ip6cp->ip6c_src,
- (struct sockaddr *)&final,
+ stcb = sctp_findassociation_addr_sa((struct sockaddr *)&final,
+ (struct sockaddr *)ip6cp->ip6c_src,
&inp, &net, 1, vrf_id);
/* inp's ref-count increased && stcb locked */
if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
@@ -593,8 +484,8 @@ sctp6_getcred(SYSCTL_HANDLER_ARGS)
if (error)
return (error);
- stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[0]),
- sin6tosa(&addrs[1]),
+ stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
+ sin6tosa(&addrs[0]),
&inp, &net, 1, vrf_id);
if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
if ((inp != NULL) && (stcb == NULL)) {
@@ -642,7 +533,7 @@ sctp6_abort(struct socket *so)
uint32_t flags;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return;
}
@@ -678,7 +569,7 @@ sctp_must_try_again:
}
static int
-sctp6_attach(struct socket *so, int proto, struct thread *p)
+sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
{
struct in6pcb *inp6;
int error;
@@ -688,16 +579,16 @@ sctp6_attach(struct socket *so, int proto, struct thread *p)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp != NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
if (error)
- return error;
+ return (error);
}
error = sctp_inpcb_alloc(so, vrf_id);
if (error)
- return error;
+ return (error);
inp = (struct sctp_inpcb *)so->so_pcb;
SCTP_INP_WLOCK(inp);
inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6; /* I'm v6! */
@@ -719,7 +610,7 @@ sctp6_attach(struct socket *so, int proto, struct thread *p)
* sctp_attach()?
*/
SCTP_INP_WUNLOCK(inp);
- return 0;
+ return (0);
}
static int
@@ -730,68 +621,94 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
int error;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (addr) {
- if ((addr->sa_family == AF_INET6) &&
- (addr->sa_len != sizeof(struct sockaddr_in6))) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
- }
- if ((addr->sa_family == AF_INET) &&
- (addr->sa_len != sizeof(struct sockaddr_in))) {
+ switch (addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (addr->sa_len != sizeof(struct sockaddr_in)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (addr->sa_len != sizeof(struct sockaddr_in6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ break;
+#endif
+ default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
}
inp6 = (struct in6pcb *)inp;
inp6->inp_vflag &= ~INP_IPV4;
inp6->inp_vflag |= INP_IPV6;
if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) {
- if (addr->sa_family == AF_INET) {
+ switch (addr->sa_family) {
+#ifdef INET
+ case AF_INET:
/* binding v4 addr to v6 socket, so reset flags */
inp6->inp_vflag |= INP_IPV4;
inp6->inp_vflag &= ~INP_IPV6;
- } else {
- struct sockaddr_in6 *sin6_p;
-
- sin6_p = (struct sockaddr_in6 *)addr;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6_p;
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
- inp6->inp_vflag |= INP_IPV4;
- } else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
- struct sockaddr_in sin;
+ sin6_p = (struct sockaddr_in6 *)addr;
- in6_sin6_2_sin(&sin, sin6_p);
- inp6->inp_vflag |= INP_IPV4;
- inp6->inp_vflag &= ~INP_IPV6;
- error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
- return error;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
+ inp6->inp_vflag |= INP_IPV4;
+ }
+#ifdef INET
+ if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
+ struct sockaddr_in sin;
+
+ in6_sin6_2_sin(&sin, sin6_p);
+ inp6->inp_vflag |= INP_IPV4;
+ inp6->inp_vflag &= ~INP_IPV6;
+ error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
+ return (error);
+ }
+#endif
+ break;
}
+#endif
+ default:
+ break;
}
} else if (addr != NULL) {
+ struct sockaddr_in6 *sin6_p;
+
/* IPV6_V6ONLY socket */
+#ifdef INET
if (addr->sa_family == AF_INET) {
/* can't bind v4 addr to v6 only socket! */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
- } else {
- struct sockaddr_in6 *sin6_p;
-
- sin6_p = (struct sockaddr_in6 *)addr;
+ return (EINVAL);
+ }
+#endif
+ sin6_p = (struct sockaddr_in6 *)addr;
- if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
- /* can't bind v4-mapped addrs either! */
- /* NOTE: we don't support SIIT */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
- }
+ if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
+ /* can't bind v4-mapped addrs either! */
+ /* NOTE: we don't support SIIT */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
}
}
error = sctp_inpcb_bind(so, addr, NULL, p);
- return error;
+ return (error);
}
@@ -837,7 +754,7 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
}
SCTP_RELEASE_PKT(m);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
inp6 = (struct in6pcb *)inp;
/*
@@ -866,11 +783,11 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
*/
if (addr->sa_family == AF_INET) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
@@ -879,12 +796,12 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
/* convert v4-mapped into v4 addr and send */
in6_sin6_2_sin(&sin, sin6);
- return sctp_sendm(so, flags, m, (struct sockaddr *)&sin,
- control, p);
+ return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin,
+ control, p));
} else {
/* mapped addresses aren't enabled */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
}
#endif /* INET */
@@ -940,11 +857,11 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
struct sockaddr_in6 *sin6;
struct sockaddr_storage ss;
-#endif /* INET */
+#endif
inp6 = (struct in6pcb *)so->so_pcb;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
return (ECONNRESET); /* I made the same as TCP since we are
* not setup? */
@@ -953,14 +870,28 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
- if ((addr->sa_family == AF_INET6) && (addr->sa_len != sizeof(struct sockaddr_in6))) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return (EINVAL);
- }
- if ((addr->sa_family == AF_INET) && (addr->sa_len != sizeof(struct sockaddr_in))) {
+ switch (addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (addr->sa_len != sizeof(struct sockaddr_in)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (addr->sa_len != sizeof(struct sockaddr_in6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ break;
+#endif
+ default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
+
vrf_id = inp->def_vrf_id;
SCTP_ASOC_CREATE_LOCK(inp);
SCTP_INP_RLOCK(inp);
@@ -995,13 +926,13 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
@@ -1014,12 +945,10 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
- } else
+ }
#endif /* INET */
- addr = addr; /* for true v6 address case */
-
/* Now do we connect? */
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -1067,7 +996,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
- return error;
+ return (error);
}
static int
@@ -1083,9 +1012,9 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
/*
* Do the malloc first in case it blocks.
*/
- SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
+ SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
if (sin6 == NULL)
- return ENOMEM;
+ return (ENOMEM);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
@@ -1093,7 +1022,7 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
if (inp == NULL) {
SCTP_FREE_SONAME(sin6);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
- return ECONNRESET;
+ return (ECONNRESET);
}
SCTP_INP_RLOCK(inp);
sin6->sin6_port = inp->sctp_lport;
@@ -1155,7 +1084,7 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
SCTP_FREE_SONAME(sin6);
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
- return ENOENT;
+ return (ENOENT);
}
}
SCTP_INP_RUNLOCK(inp);
@@ -1171,36 +1100,28 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
static int
sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)*addr;
+ struct sockaddr_in6 *sin6;
int fnd;
struct sockaddr_in6 *sin_a6;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
-
int error;
- /*
- * Do the malloc first in case it blocks.
- */
- inp = (struct sctp_inpcb *)so->so_pcb;
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
- /* UDP type and listeners will drop out here */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
- return (ENOTCONN);
- }
+ /* Do the malloc first in case it blocks. */
SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
if (sin6 == NULL)
return (ENOMEM);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
- /* We must recapture incase we blocked */
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == NULL) {
+ if ((inp == NULL) ||
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
+ /* UDP type and listeners will drop out here */
SCTP_FREE_SONAME(sin6);
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
- return ECONNRESET;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
+ return (ENOTCONN);
}
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -1211,7 +1132,7 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
if (stcb == NULL) {
SCTP_FREE_SONAME(sin6);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
- return ECONNRESET;
+ return (ECONNRESET);
}
fnd = 0;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -1228,7 +1149,7 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
/* No IPv4 address */
SCTP_FREE_SONAME(sin6);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
- return ENOENT;
+ return (ENOENT);
}
if ((error = sa6_recoverscope(sin6)) != 0)
return (error);
@@ -1239,16 +1160,20 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
static int
sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
{
+#ifdef INET
struct sockaddr *addr;
+
+#endif
struct in6pcb *inp6 = sotoin6pcb(so);
int error;
if (inp6 == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
/* allow v6 addresses precedence */
error = sctp6_getaddr(so, nam);
+#ifdef INET
if (error) {
/* try v4 next if v6 failed */
error = sctp_ingetaddr(so, nam);
@@ -1262,9 +1187,9 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
-
}
}
+#endif
return (error);
}
@@ -1272,22 +1197,27 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
static int
sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
{
- struct sockaddr *addr = *nam;
+#ifdef INET
+ struct sockaddr *addr;
+
+#endif
struct in6pcb *inp6 = sotoin6pcb(so);
int error;
if (inp6 == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
/* allow v6 addresses precedence */
error = sctp6_peeraddr(so, nam);
+#ifdef INET
if (error) {
/* try v4 next if v6 failed */
error = sctp_peeraddr(so, nam);
if (error) {
return (error);
}
+ addr = *nam;
/* if I'm V6ONLY, convert it to v4-mapped */
if (SCTP_IPV6_V6ONLY(inp6)) {
struct sockaddr_in6 sin6;
@@ -1296,7 +1226,8 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
}
}
- return error;
+#endif
+ return (error);
}
struct pr_usrreqs sctp6_usrreqs = {
@@ -1319,3 +1250,5 @@ struct pr_usrreqs sctp6_usrreqs = {
.pru_sosend = sctp_sosend,
.pru_soreceive = sctp_soreceive
};
+
+#endif
diff --git a/freebsd/sys/netinet6/sctp6_var.h b/freebsd/sys/netinet6/sctp6_var.h
index a05f6b03..53d1d4c5 100644
--- a/freebsd/sys/netinet6/sctp6_var.h
+++ b/freebsd/sys/netinet6/sctp6_var.h
@@ -1,15 +1,17 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -27,15 +29,13 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp6_var.h,v 1.7 2004/08/17 04:06:22 itojun Exp $ */
-
-#ifndef _NETINET6_SCTP6_VAR_H_
-#define _NETINET6_SCTP6_VAR_H_
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-/* TODO __Userspace__ IPv6 stuff... */
+#ifndef _NETINET6_SCTP6_VAR_H_
+#define _NETINET6_SCTP6_VAR_H_
+
#if defined(_KERNEL)
SYSCTL_DECL(_net_inet6_sctp6);
@@ -43,6 +43,7 @@ extern struct pr_usrreqs sctp6_usrreqs;
int sctp6_input __P((struct mbuf **, int *, int));
+int sctp6_input_with_port __P((struct mbuf **, int *, uint16_t));
int sctp6_output
__P((struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct proc *));
diff --git a/freebsd/sys/netinet6/udp6_usrreq.c b/freebsd/sys/netinet6/udp6_usrreq.c
index 941b3950..2c2559fb 100644
--- a/freebsd/sys/netinet6/udp6_usrreq.c
+++ b/freebsd/sys/netinet6/udp6_usrreq.c
@@ -275,6 +275,13 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
}
/*
+ * Detached PCBs can linger in the list if someone
+ * holds a reference. (e.g. udp_pcblist)
+ */
+ if (inp->inp_socket == NULL)
+ continue;
+
+ /*
* Handle socket delivery policy for any-source
* and source-specific multicast. [RFC3678]
*/
@@ -398,6 +405,15 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
}
INP_RLOCK(inp);
INP_INFO_RUNLOCK(&V_udbinfo);
+
+ /*
+ * Detached PCBs can linger in the hash table if someone holds a
+ * reference. (e.g. udp_pcblist)
+ */
+ if (inp->inp_socket == NULL) {
+ INP_RUNLOCK(inp);
+ goto badunlocked;
+ }
up = intoudpcb(inp);
if (up->u_tun_func == NULL) {
udp6_append(inp, m, off, &fromsa);
@@ -658,8 +674,11 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
goto release;
}
if (inp->inp_lport == 0 &&
- (error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0)
+ (error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0) {
+ /* Undo an address bind that may have occurred. */
+ inp->in6p_laddr = in6addr_any;
goto release;
+ }
} else {
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
error = ENOTCONN;
@@ -908,43 +927,41 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
- if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
- IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
struct sockaddr_in sin;
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) {
+ error = EINVAL;
+ goto out;
+ }
if (inp->inp_faddr.s_addr != INADDR_ANY) {
error = EISCONN;
goto out;
}
in6_sin6_2_sin(&sin, sin6);
+ inp->inp_vflag |= INP_IPV4;
+ inp->inp_vflag &= ~INP_IPV6;
error = prison_remote_ip4(td->td_ucred, &sin.sin_addr);
if (error != 0)
goto out;
error = in_pcbconnect(inp, (struct sockaddr *)&sin,
td->td_ucred);
- if (error == 0) {
- inp->inp_vflag |= INP_IPV4;
- inp->inp_vflag &= ~INP_IPV6;
+ if (error == 0)
soisconnected(so);
- }
goto out;
}
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
error = EISCONN;
goto out;
}
+ inp->inp_vflag &= ~INP_IPV4;
+ inp->inp_vflag |= INP_IPV6;
error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr);
if (error != 0)
goto out;
error = in6_pcbconnect(inp, nam, td->td_ucred);
- if (error == 0) {
- if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
- /* should be non mapped addr */
- inp->inp_vflag &= ~INP_IPV4;
- inp->inp_vflag |= INP_IPV6;
- }
+ if (error == 0)
soisconnected(so);
- }
out:
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_udbinfo);
@@ -1046,18 +1063,6 @@ udp6_send(struct socket *so, int flags, struct mbuf *m,
if (hasv4addr) {
struct pr_usrreqs *pru;
- if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
- !IN6_IS_ADDR_V4MAPPED(&inp->in6p_laddr)) {
- /*
- * When remote addr is IPv4-mapped address,
- * local addr should not be an IPv6 address;
- * since you cannot determine how to map IPv6
- * source address to IPv4.
- */
- error = EINVAL;
- goto out;
- }
-
/*
* XXXRW: We release UDP-layer locks before calling
* udp_send() in order to avoid recursion. However,
@@ -1081,7 +1086,6 @@ udp6_send(struct socket *so, int flags, struct mbuf *m,
mac_inpcb_create_mbuf(inp, m);
#endif
error = udp6_output(inp, m, addr, control, td);
-out:
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_udbinfo);
return (error);
diff --git a/freebsd/sys/netipsec/ipsec.h b/freebsd/sys/netipsec/ipsec.h
index d54e7cff..fb987ad2 100644
--- a/freebsd/sys/netipsec/ipsec.h
+++ b/freebsd/sys/netipsec/ipsec.h
@@ -123,7 +123,7 @@ struct ipsecrequest {
struct secasvar *sav; /* place holder of SA for use */
struct secpolicy *sp; /* back pointer to SP */
- struct mtx lock; /* to interlock updates */
+ struct rwlock lock; /* to interlock updates */
};
/*
@@ -132,11 +132,15 @@ struct ipsecrequest {
* hard it is to remove this...
*/
#define IPSECREQUEST_LOCK_INIT(_isr) \
- mtx_init(&(_isr)->lock, "ipsec request", NULL, MTX_DEF | MTX_RECURSE)
-#define IPSECREQUEST_LOCK(_isr) mtx_lock(&(_isr)->lock)
-#define IPSECREQUEST_UNLOCK(_isr) mtx_unlock(&(_isr)->lock)
-#define IPSECREQUEST_LOCK_DESTROY(_isr) mtx_destroy(&(_isr)->lock)
-#define IPSECREQUEST_LOCK_ASSERT(_isr) mtx_assert(&(_isr)->lock, MA_OWNED)
+ rw_init_flags(&(_isr)->lock, "ipsec request", RW_RECURSE)
+#define IPSECREQUEST_LOCK(_isr) rw_rlock(&(_isr)->lock)
+#define IPSECREQUEST_UNLOCK(_isr) rw_runlock(&(_isr)->lock)
+#define IPSECREQUEST_WLOCK(_isr) rw_wlock(&(_isr)->lock)
+#define IPSECREQUEST_WUNLOCK(_isr) rw_wunlock(&(_isr)->lock)
+#define IPSECREQUEST_UPGRADE(_isr) rw_try_upgrade(&(_isr)->lock)
+#define IPSECREQUEST_DOWNGRADE(_isr) rw_downgrade(&(_isr)->lock)
+#define IPSECREQUEST_LOCK_DESTROY(_isr) rw_destroy(&(_isr)->lock)
+#define IPSECREQUEST_LOCK_ASSERT(_isr) rw_assert(&(_isr)->lock, RA_LOCKED)
/* security policy in PCB */
struct inpcbpolicy {
diff --git a/freebsd/sys/netipsec/ipsec_output.c b/freebsd/sys/netipsec/ipsec_output.c
index d477b5f4..9f7051f7 100644
--- a/freebsd/sys/netipsec/ipsec_output.c
+++ b/freebsd/sys/netipsec/ipsec_output.c
@@ -249,7 +249,6 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
panic("ipsec_process_done");
bad:
m_freem(m);
- KEY_FREESAV(&sav);
return (error);
}
@@ -846,7 +845,7 @@ ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int
dst6->sin6_family = AF_INET6;
dst6->sin6_len = sizeof(*dst6);
dst6->sin6_addr = ip6->ip6_dst;
- rtalloc(state->ro);
+ rtalloc_ign_fib(state->ro, 0UL, M_GETFIB(m));
}
if (state->ro->ro_rt == NULL) {
V_ip6stat.ip6s_noroute++;
diff --git a/freebsd/sys/netipsec/key.c b/freebsd/sys/netipsec/key.c
index b6fb97a0..0252730f 100644
--- a/freebsd/sys/netipsec/key.c
+++ b/freebsd/sys/netipsec/key.c
@@ -811,6 +811,7 @@ key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx)
{
u_int level;
int error;
+ struct secasvar *sav;
IPSEC_ASSERT(isr != NULL, ("null isr"));
IPSEC_ASSERT(saidx != NULL, ("null saidx"));
@@ -828,45 +829,31 @@ key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx)
/* get current level */
level = ipsec_get_reqlevel(isr);
-#if 0
- /*
- * We do allocate new SA only if the state of SA in the holder is
- * SADB_SASTATE_DEAD. The SA for outbound must be the oldest.
- */
- if (isr->sav != NULL) {
- if (isr->sav->sah == NULL)
- panic("%s: sah is null.\n", __func__);
- if (isr->sav == (struct secasvar *)LIST_FIRST(
- &isr->sav->sah->savtree[SADB_SASTATE_DEAD])) {
- KEY_FREESAV(&isr->sav);
- isr->sav = NULL;
- }
- }
-#else
+
/*
- * we free any SA stashed in the IPsec request because a different
+ * We check new SA in the IPsec request because a different
* SA may be involved each time this request is checked, either
* because new SAs are being configured, or this request is
* associated with an unconnected datagram socket, or this request
* is associated with a system default policy.
*
- * The operation may have negative impact to performance. We may
- * want to check cached SA carefully, rather than picking new SA
- * every time.
- */
- if (isr->sav != NULL) {
- KEY_FREESAV(&isr->sav);
- isr->sav = NULL;
- }
-#endif
-
- /*
- * new SA allocation if no SA found.
* key_allocsa_policy should allocate the oldest SA available.
* See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt.
*/
- if (isr->sav == NULL)
- isr->sav = key_allocsa_policy(saidx);
+ sav = key_allocsa_policy(saidx);
+ if (sav != isr->sav) {
+ /* SA need to be updated. */
+ if (!IPSECREQUEST_UPGRADE(isr)) {
+ /* Kick everyone off. */
+ IPSECREQUEST_UNLOCK(isr);
+ IPSECREQUEST_WLOCK(isr);
+ }
+ if (isr->sav != NULL)
+ KEY_FREESAV(&isr->sav);
+ isr->sav = sav;
+ IPSECREQUEST_DOWNGRADE(isr);
+ } else if (sav != NULL)
+ KEY_FREESAV(&sav);
/* When there is SA. */
if (isr->sav != NULL) {
@@ -1241,6 +1228,16 @@ key_freesp_so(struct secpolicy **sp)
KEY_FREESP(sp);
}
+void
+key_addrefsa(struct secasvar *sav, const char* where, int tag)
+{
+
+ IPSEC_ASSERT(sav != NULL, ("null sav"));
+ IPSEC_ASSERT(sav->refcnt > 0, ("refcount must exist"));
+
+ sa_addref(sav);
+}
+
/*
* Must be called after calling key_allocsa().
* This function is called by key_freesp() to free some SA allocated
@@ -1768,6 +1765,7 @@ key_gather_mbuf(m, mhp, ndeep, nitem, va_alist)
fail:
m_freem(result);
+ va_end(ap);
return NULL;
}
@@ -2297,6 +2295,7 @@ key_spdget(so, m, mhp)
}
n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid);
+ KEY_FREESP(&sp);
if (n != NULL) {
m_freem(m);
return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
@@ -2870,9 +2869,10 @@ key_newsav(m, mhp, sah, errp, where, tag)
sa_initref(newsav);
newsav->state = SADB_SASTATE_LARVAL;
- /* XXX locking??? */
+ SAHTREE_LOCK();
LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav,
secasvar, chain);
+ SAHTREE_UNLOCK();
done:
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s from %s:%u return SP:%p\n", __func__,
@@ -5716,8 +5716,8 @@ key_delete(so, m, mhp)
}
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
- SAHTREE_UNLOCK();
KEY_FREESAV(&sav);
+ SAHTREE_UNLOCK();
{
struct mbuf *n;
@@ -6105,6 +6105,9 @@ key_getsizes_ah(
case SADB_X_AALG_MD5: *min = *max = 16; break;
case SADB_X_AALG_SHA: *min = *max = 20; break;
case SADB_X_AALG_NULL: *min = 1; *max = 256; break;
+ case SADB_X_AALG_SHA2_256: *min = *max = 32; break;
+ case SADB_X_AALG_SHA2_384: *min = *max = 48; break;
+ case SADB_X_AALG_SHA2_512: *min = *max = 64; break;
default:
DPRINTF(("%s: unknown AH algorithm %u\n",
__func__, alg));
@@ -6130,7 +6133,11 @@ key_getcomb_ah()
for (i = 1; i <= SADB_AALG_MAX; i++) {
#if 1
/* we prefer HMAC algorithms, not old algorithms */
- if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC)
+ if (i != SADB_AALG_SHA1HMAC &&
+ i != SADB_AALG_MD5HMAC &&
+ i != SADB_X_AALG_SHA2_256 &&
+ i != SADB_X_AALG_SHA2_384 &&
+ i != SADB_X_AALG_SHA2_512)
continue;
#endif
algo = ah_algorithm_lookup(i);
diff --git a/freebsd/sys/netipsec/key.h b/freebsd/sys/netipsec/key.h
index e85acd1e..f246dbcf 100644
--- a/freebsd/sys/netipsec/key.h
+++ b/freebsd/sys/netipsec/key.h
@@ -76,10 +76,13 @@ extern void _key_freesp(struct secpolicy **, const char*, int);
extern struct secasvar *key_allocsa(union sockaddr_union *, u_int, u_int32_t,
const char*, int);
+extern void key_addrefsa(struct secasvar *, const char*, int);
extern void key_freesav(struct secasvar **, const char*, int);
#define KEY_ALLOCSA(dst, proto, spi) \
key_allocsa(dst, proto, spi, __FILE__, __LINE__)
+#define KEY_ADDREFSA(sav) \
+ key_addrefsa(sav, __FILE__, __LINE__)
#define KEY_FREESAV(psav) \
key_freesav(psav, __FILE__, __LINE__)
diff --git a/freebsd/sys/netipsec/xform.h b/freebsd/sys/netipsec/xform.h
index fc259c91..77b93af3 100644
--- a/freebsd/sys/netipsec/xform.h
+++ b/freebsd/sys/netipsec/xform.h
@@ -46,6 +46,7 @@
#include <opencrypto/xform.h>
#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */
+#define AH_HMAC_MAXHASHLEN (SHA2_512_HASH_LEN/2) /* Keep this updated */
#define AH_HMAC_INITIAL_RPL 1 /* replay counter initial value */
/*
@@ -74,6 +75,7 @@ struct tdb_crypto {
int tc_protoff; /* current protocol offset */
int tc_skip; /* data offset */
caddr_t tc_ptr; /* associated crypto data */
+ struct secasvar *tc_sav; /* related SA */
};
struct secasvar;
diff --git a/freebsd/sys/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c
index f5c0929b..98d319ce 100644
--- a/freebsd/sys/netipsec/xform_ah.c
+++ b/freebsd/sys/netipsec/xform_ah.c
@@ -87,8 +87,7 @@
* to use a fixed 16-byte authenticator. The new algorithm use 12-byte
* authenticator.
*/
-#define AUTHSIZE(sav) \
- ((sav->flags & SADB_X_EXT_OLD) ? 16 : AH_HMAC_HASHLEN)
+#define AUTHSIZE(sav) ah_authsize(sav)
VNET_DEFINE(int, ah_enable) = 1; /* control flow of packets with AH */
VNET_DEFINE(int, ah_cleartos) = 1; /* clear ip_tos when doing AH calc */
@@ -107,6 +106,27 @@ static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */
static int ah_input_cb(struct cryptop*);
static int ah_output_cb(struct cryptop*);
+static int
+ah_authsize(struct secasvar *sav)
+{
+
+ IPSEC_ASSERT(sav != NULL, ("%s: sav == NULL", __func__));
+
+ if (sav->flags & SADB_X_EXT_OLD)
+ return 16;
+
+ switch (sav->alg_auth) {
+ case SADB_X_AALG_SHA2_256:
+ return 16;
+ case SADB_X_AALG_SHA2_384:
+ return 24;
+ case SADB_X_AALG_SHA2_512:
+ return 32;
+ default:
+ return AH_HMAC_HASHLEN;
+ }
+ /* NOTREACHED */
+}
/*
* NB: this is public for use by the PF_KEY support.
*/
@@ -697,6 +717,8 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
tc->tc_protoff = protoff;
tc->tc_skip = skip;
tc->tc_ptr = (caddr_t) mtag; /* Save the mtag we've identified. */
+ KEY_ADDREFSA(sav);
+ tc->tc_sav = sav;
if (mtag == NULL)
return crypto_dispatch(crp);
@@ -746,13 +768,8 @@ ah_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
- if (sav == NULL) {
- V_ahstat.ahs_notdb++;
- DPRINTF(("%s: SA expired while in crypto\n", __func__));
- error = ENOBUFS; /*XXX*/
- goto bad;
- }
+ sav = tc->tc_sav;
+ IPSEC_ASSERT(sav != NULL, ("null SA!"));
saidx = &sav->sah->saidx;
IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
@@ -1092,6 +1109,8 @@ ah_output(
/* These are passed as-is to the callback. */
tc->tc_isr = isr;
+ KEY_ADDREFSA(sav);
+ tc->tc_sav = sav;
tc->tc_spi = sav->spi;
tc->tc_dst = sav->sah->saidx.dst;
tc->tc_proto = sav->sah->saidx.proto;
@@ -1128,14 +1147,14 @@ ah_output_cb(struct cryptop *crp)
isr = tc->tc_isr;
IPSECREQUEST_LOCK(isr);
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
- if (sav == NULL) {
+ sav = tc->tc_sav;
+ /* With the isr lock released SA pointer can be updated. */
+ if (sav != isr->sav) {
V_ahstat.ahs_notdb++;
DPRINTF(("%s: SA expired while in crypto\n", __func__));
error = ENOBUFS; /*XXX*/
goto bad;
}
- IPSEC_ASSERT(isr->sav == sav, ("SA changed\n"));
/* Check for crypto errors. */
if (crp->crp_etype) {
@@ -1143,7 +1162,6 @@ ah_output_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
- KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
error = crypto_dispatch(crp);
return error;
diff --git a/freebsd/sys/netipsec/xform_esp.c b/freebsd/sys/netipsec/xform_esp.c
index 04d7bd51..4e52cde1 100644
--- a/freebsd/sys/netipsec/xform_esp.c
+++ b/freebsd/sys/netipsec/xform_esp.c
@@ -299,7 +299,19 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
else
hlen = sizeof (struct newesp) + sav->ivlen;
/* Authenticator hash size */
- alen = esph ? AH_HMAC_HASHLEN : 0;
+ if (esph != NULL) {
+ switch (esph->type) {
+ case CRYPTO_SHA2_256_HMAC:
+ case CRYPTO_SHA2_384_HMAC:
+ case CRYPTO_SHA2_512_HMAC:
+ alen = esph->hashsize/2;
+ break;
+ default:
+ alen = AH_HMAC_HASHLEN;
+ break;
+ }
+ }else
+ alen = 0;
/*
* Verify payload length is multiple of encryption algorithm
@@ -413,6 +425,8 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
tc->tc_proto = sav->sah->saidx.proto;
tc->tc_protoff = protoff;
tc->tc_skip = skip;
+ KEY_ADDREFSA(sav);
+ tc->tc_sav = sav;
/* Decryption descriptor */
if (espx) {
@@ -452,8 +466,8 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
static int
esp_input_cb(struct cryptop *crp)
{
- u_int8_t lastthree[3], aalg[AH_HMAC_HASHLEN];
- int hlen, skip, protoff, error;
+ u_int8_t lastthree[3], aalg[AH_HMAC_MAXHASHLEN];
+ int hlen, skip, protoff, error, alen;
struct mbuf *m;
struct cryptodesc *crd;
struct auth_hash *esph;
@@ -474,15 +488,8 @@ esp_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
- if (sav == NULL) {
- V_espstat.esps_notdb++;
- DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n",
- __func__, ipsec_address(&tc->tc_dst),
- (u_long) ntohl(tc->tc_spi), tc->tc_proto));
- error = ENOBUFS; /*XXX*/
- goto bad;
- }
+ sav = tc->tc_sav;
+ IPSEC_ASSERT(sav != NULL, ("null SA!"));
saidx = &sav->sah->saidx;
IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
@@ -499,7 +506,6 @@ esp_input_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
- KEY_FREESAV(&sav);
error = crypto_dispatch(crp);
return error;
}
@@ -521,6 +527,16 @@ esp_input_cb(struct cryptop *crp)
/* If authentication was performed, check now. */
if (esph != NULL) {
+ switch (esph->type) {
+ case CRYPTO_SHA2_256_HMAC:
+ case CRYPTO_SHA2_384_HMAC:
+ case CRYPTO_SHA2_512_HMAC:
+ alen = esph->hashsize/2;
+ break;
+ default:
+ alen = AH_HMAC_HASHLEN;
+ break;
+ }
/*
* If we have a tag, it means an IPsec-aware NIC did
* the verification for us. Otherwise we need to
@@ -529,13 +545,13 @@ esp_input_cb(struct cryptop *crp)
V_ahstat.ahs_hist[sav->alg_auth]++;
if (mtag == NULL) {
/* Copy the authenticator from the packet */
- m_copydata(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
- AH_HMAC_HASHLEN, aalg);
+ m_copydata(m, m->m_pkthdr.len - alen,
+ alen, aalg);
ptr = (caddr_t) (tc + 1);
/* Verify authenticator */
- if (bcmp(ptr, aalg, AH_HMAC_HASHLEN) != 0) {
+ if (bcmp(ptr, aalg, alen) != 0) {
DPRINTF(("%s: "
"authentication hash mismatch for packet in SA %s/%08lx\n",
__func__,
@@ -548,7 +564,7 @@ esp_input_cb(struct cryptop *crp)
}
/* Remove trailing authenticator */
- m_adj(m, -AH_HMAC_HASHLEN);
+ m_adj(m, -alen);
}
/* Release the crypto descriptors */
@@ -692,7 +708,16 @@ esp_output(
plen = rlen + padding; /* Padded payload length. */
if (esph)
+ switch (esph->type) {
+ case CRYPTO_SHA2_256_HMAC:
+ case CRYPTO_SHA2_384_HMAC:
+ case CRYPTO_SHA2_512_HMAC:
+ alen = esph->hashsize/2;
+ break;
+ default:
alen = AH_HMAC_HASHLEN;
+ break;
+ }
else
alen = 0;
@@ -848,6 +873,8 @@ esp_output(
/* Callback parameters */
tc->tc_isr = isr;
+ KEY_ADDREFSA(sav);
+ tc->tc_sav = sav;
tc->tc_spi = sav->spi;
tc->tc_dst = saidx->dst;
tc->tc_proto = saidx->proto;
@@ -897,8 +924,9 @@ esp_output_cb(struct cryptop *crp)
isr = tc->tc_isr;
IPSECREQUEST_LOCK(isr);
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
- if (sav == NULL) {
+ sav = tc->tc_sav;
+ /* With the isr lock released SA pointer can be updated. */
+ if (sav != isr->sav) {
V_espstat.esps_notdb++;
DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n",
__func__, ipsec_address(&tc->tc_dst),
@@ -906,8 +934,6 @@ esp_output_cb(struct cryptop *crp)
error = ENOBUFS; /*XXX*/
goto bad;
}
- IPSEC_ASSERT(isr->sav == sav,
- ("SA changed was %p now %p\n", isr->sav, sav));
/* Check for crypto errors. */
if (crp->crp_etype) {
@@ -916,7 +942,6 @@ esp_output_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
- KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
error = crypto_dispatch(crp);
return error;
@@ -946,7 +971,7 @@ esp_output_cb(struct cryptop *crp)
#ifdef REGRESSION
/* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */
if (V_ipsec_integrity) {
- static unsigned char ipseczeroes[AH_HMAC_HASHLEN];
+ static unsigned char ipseczeroes[AH_HMAC_MAXHASHLEN];
struct auth_hash *esph;
/*
@@ -955,8 +980,20 @@ esp_output_cb(struct cryptop *crp)
*/
esph = sav->tdb_authalgxform;
if (esph != NULL) {
- m_copyback(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
- AH_HMAC_HASHLEN, ipseczeroes);
+ int alen;
+
+ switch (esph->type) {
+ case CRYPTO_SHA2_256_HMAC:
+ case CRYPTO_SHA2_384_HMAC:
+ case CRYPTO_SHA2_512_HMAC:
+ alen = esph->hashsize/2;
+ break;
+ default:
+ alen = AH_HMAC_HASHLEN;
+ break;
+ }
+ m_copyback(m, m->m_pkthdr.len - alen,
+ alen, ipseczeroes);
}
}
#endif
diff --git a/freebsd/sys/netipsec/xform_ipcomp.c b/freebsd/sys/netipsec/xform_ipcomp.c
index 2c0f961f..c4048cc9 100644
--- a/freebsd/sys/netipsec/xform_ipcomp.c
+++ b/freebsd/sys/netipsec/xform_ipcomp.c
@@ -39,6 +39,7 @@
#include <sys/mbuf.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
+#include <sys/rwlock.h>
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/protosw.h>
@@ -143,8 +144,29 @@ ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
struct tdb_crypto *tc;
struct cryptodesc *crdc;
struct cryptop *crp;
+ struct ipcomp *ipcomp;
+ caddr_t addr;
int hlen = IPCOMP_HLENGTH;
+ /*
+ * Check that the next header of the IPComp is not IPComp again, before
+ * doing any real work. Given it is not possible to do double
+ * compression it means someone is playing tricks on us.
+ */
+ if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) {
+ V_ipcompstat.ipcomps_hdrops++; /*XXX*/
+ DPRINTF(("%s: m_pullup failed\n", __func__));
+ return (ENOBUFS);
+ }
+ addr = (caddr_t) mtod(m, struct ip *) + skip;
+ ipcomp = (struct ipcomp *)addr;
+ if (ipcomp->comp_nxt == IPPROTO_IPCOMP) {
+ m_freem(m);
+ V_ipcompstat.ipcomps_pdrops++; /* XXX have our own stats? */
+ DPRINTF(("%s: recursive compression detected\n", __func__));
+ return (EINVAL);
+ }
+
/* Get crypto descriptors */
crp = crypto_getreq(1);
if (crp == NULL) {
@@ -187,6 +209,8 @@ ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
tc->tc_proto = sav->sah->saidx.proto;
tc->tc_protoff = protoff;
tc->tc_skip = skip;
+ KEY_ADDREFSA(sav);
+ tc->tc_sav = sav;
return crypto_dispatch(crp);
}
@@ -230,13 +254,8 @@ ipcomp_input_cb(struct cryptop *crp)
mtag = (struct mtag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
- if (sav == NULL) {
- V_ipcompstat.ipcomps_notdb++;
- DPRINTF(("%s: SA expired while in crypto\n", __func__));
- error = ENOBUFS; /*XXX*/
- goto bad;
- }
+ sav = tc->tc_sav;
+ IPSEC_ASSERT(sav != NULL, ("null SA!"));
saidx = &sav->sah->saidx;
IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
@@ -250,7 +269,6 @@ ipcomp_input_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
- KEY_FREESAV(&sav);
return crypto_dispatch(crp);
}
V_ipcompstat.ipcomps_noxform++;
@@ -433,6 +451,8 @@ ipcomp_output(
}
tc->tc_isr = isr;
+ KEY_ADDREFSA(sav);
+ tc->tc_sav = sav;
tc->tc_spi = sav->spi;
tc->tc_dst = sav->sah->saidx.dst;
tc->tc_proto = sav->sah->saidx.proto;
@@ -473,14 +493,14 @@ ipcomp_output_cb(struct cryptop *crp)
isr = tc->tc_isr;
IPSECREQUEST_LOCK(isr);
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
- if (sav == NULL) {
+ sav = tc->tc_sav;
+ /* With the isr lock released SA pointer can be updated. */
+ if (sav != isr->sav) {
V_ipcompstat.ipcomps_notdb++;
DPRINTF(("%s: SA expired while in crypto\n", __func__));
error = ENOBUFS; /*XXX*/
goto bad;
}
- IPSEC_ASSERT(isr->sav == sav, ("SA changed\n"));
/* Check for crypto errors */
if (crp->crp_etype) {
@@ -489,7 +509,6 @@ ipcomp_output_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
- KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
return crypto_dispatch(crp);
}
diff --git a/freebsd/sys/nios2/include/machine/legacyvar.h b/freebsd/sys/nios2/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/nios2/include/machine/legacyvar.h
+++ b/freebsd/sys/nios2/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/nios2/nios2/legacy.c b/freebsd/sys/nios2/nios2/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/nios2/nios2/legacy.c
+++ b/freebsd/sys/nios2/nios2/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/nios2/pci/pci_bus.c b/freebsd/sys/nios2/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/nios2/pci/pci_bus.c
+++ b/freebsd/sys/nios2/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/opencrypto/deflate.c b/freebsd/sys/opencrypto/deflate.c
index 5806d33e..cc38f600 100644
--- a/freebsd/sys/opencrypto/deflate.c
+++ b/freebsd/sys/opencrypto/deflate.c
@@ -52,13 +52,13 @@ __FBSDID("$FreeBSD$");
#include <opencrypto/deflate.h>
SDT_PROVIDER_DECLARE(opencrypto);
-SDT_PROBE_DEFINE2(opencrypto, deflate, deflate_global, entry,
+SDT_PROBE_DEFINE2(opencrypto, deflate, deflate_global, entry, entry,
"int", "u_int32_t");
-SDT_PROBE_DEFINE5(opencrypto, deflate, deflate_global, bad,
+SDT_PROBE_DEFINE5(opencrypto, deflate, deflate_global, bad, bad,
"int", "int", "int", "int", "int");
-SDT_PROBE_DEFINE5(opencrypto, deflate, deflate_global, iter,
+SDT_PROBE_DEFINE5(opencrypto, deflate, deflate_global, iter, iter,
"int", "int", "int", "int", "int");
-SDT_PROBE_DEFINE2(opencrypto, deflate, deflate_global, return,
+SDT_PROBE_DEFINE2(opencrypto, deflate, deflate_global, return, return,
"int", "u_int32_t");
int window_inflate = -1 * MAX_WBITS;
diff --git a/freebsd/sys/opencrypto/xform.h b/freebsd/sys/opencrypto/xform.h
index 0a7f981d..8df7b07e 100644
--- a/freebsd/sys/opencrypto/xform.h
+++ b/freebsd/sys/opencrypto/xform.h
@@ -43,7 +43,8 @@ struct auth_hash {
void (*Final) (u_int8_t *, void *);
};
-#define AH_ALEN_MAX 20 /* max authenticator hash length */
+/* XXX use a define common with other hash stuff ! */
+#define AH_ALEN_MAX 64 /* max authenticator hash length */
struct enc_xform {
int type;
diff --git a/freebsd/sys/pci/if_rlreg.h b/freebsd/sys/pci/if_rlreg.h
index 9de72170..be89c4f5 100644
--- a/freebsd/sys/pci/if_rlreg.h
+++ b/freebsd/sys/pci/if_rlreg.h
@@ -74,6 +74,14 @@
#define RL_TIMERCNT 0x0048 /* timer count register */
#define RL_MISSEDPKT 0x004C /* missed packet counter */
#define RL_EECMD 0x0050 /* EEPROM command register */
+
+/* RTL8139/RTL8139C+ only */
+#define RL_8139_CFG0 0x0051 /* config register #0 */
+#define RL_8139_CFG1 0x0052 /* config register #1 */
+#define RL_8139_CFG3 0x0059 /* config register #3 */
+#define RL_8139_CFG4 0x005A /* config register #4 */
+#define RL_8139_CFG5 0x00D8 /* config register #5 */
+
#define RL_CFG0 0x0051 /* config register #0 */
#define RL_CFG1 0x0052 /* config register #1 */
#define RL_CFG2 0x0053 /* config register #2 */
@@ -143,6 +151,7 @@
*/
#define RL_TXCFG_CLRABRT 0x00000001 /* retransmit aborted pkt */
#define RL_TXCFG_MAXDMA 0x00000700 /* max DMA burst size */
+#define RL_TXCFG_QUEUE_EMPTY 0x00000800 /* 8168E-VL or higher */
#define RL_TXCFG_CRCAPPEND 0x00010000 /* CRC append (0 = yes) */
#define RL_TXCFG_LOOPBKTST 0x00060000 /* loopback test */
#define RL_TXCFG_IFG2 0x00080000 /* 8169 only */
@@ -160,21 +169,28 @@
#define RL_HWREV_8110S 0x04000000
#define RL_HWREV_8169_8110SB 0x10000000
#define RL_HWREV_8169_8110SC 0x18000000
+#define RL_HWREV_8401E 0x24000000
#define RL_HWREV_8102EL 0x24800000
#define RL_HWREV_8102EL_SPIN1 0x24C00000
#define RL_HWREV_8168D 0x28000000
#define RL_HWREV_8168DP 0x28800000
#define RL_HWREV_8168E 0x2C000000
-#define RL_HWREV_8168_SPIN1 0x30000000
+#define RL_HWREV_8168E_VL 0x2C800000
+#define RL_HWREV_8168B_SPIN1 0x30000000
#define RL_HWREV_8100E 0x30800000
#define RL_HWREV_8101E 0x34000000
#define RL_HWREV_8102E 0x34800000
#define RL_HWREV_8103E 0x34C00000
-#define RL_HWREV_8168_SPIN2 0x38000000
-#define RL_HWREV_8168_SPIN3 0x38400000
+#define RL_HWREV_8168B_SPIN2 0x38000000
+#define RL_HWREV_8168B_SPIN3 0x38400000
#define RL_HWREV_8168C 0x3C000000
#define RL_HWREV_8168C_SPIN2 0x3C400000
#define RL_HWREV_8168CP 0x3C800000
+#define RL_HWREV_8105E 0x40800000
+#define RL_HWREV_8105E_SPIN1 0x40C00000
+#define RL_HWREV_8402 0x44000000
+#define RL_HWREV_8168F 0x48000000
+#define RL_HWREV_8411 0x48800000
#define RL_HWREV_8139 0x60000000
#define RL_HWREV_8139A 0x70000000
#define RL_HWREV_8139AG 0x70800000
@@ -428,6 +444,7 @@
#define RL_CFG3_GRANTSEL 0x80
#define RL_CFG3_WOL_MAGIC 0x20
#define RL_CFG3_WOL_LINK 0x10
+#define RL_CFG3_JUMBO_EN0 0x04 /* RTL8168C or later. */
#define RL_CFG3_FAST_B2B 0x01
/*
@@ -435,6 +452,7 @@
*/
#define RL_CFG4_LWPTN 0x04
#define RL_CFG4_LWPME 0x10
+#define RL_CFG4_JUMBO_EN1 0x02 /* RTL8168C or later. */
/*
* Config 5 register
@@ -494,6 +512,14 @@
#define RL_EARLYTXTHRESH_CNT 0x003F /* byte count times 8 */
+/* Timer interrupt register */
+#define RL_TIMERINT_8169_VAL 0x00001FFF
+#define RL_TIMER_MIN 0
+#define RL_TIMER_MAX 65 /* 65.528us */
+#define RL_TIMER_DEFAULT RL_TIMER_MAX
+#define RL_TIMER_PCIE_CLK 125 /* 125MHZ */
+#define RL_USECS(x) ((x) * RL_TIMER_PCIE_CLK)
+
/*
* Gigabit PHY access register (8169 only)
*/
@@ -584,32 +610,16 @@ struct rl_type {
uint16_t rl_vid;
uint16_t rl_did;
int rl_basetype;
- char *rl_name;
+ const char *rl_name;
};
struct rl_hwrev {
uint32_t rl_rev;
int rl_type;
- char *rl_desc;
+ const char *rl_desc;
+ int rl_max_mtu;
};
-struct rl_mii_frame {
- uint8_t mii_stdelim;
- uint8_t mii_opcode;
- uint8_t mii_phyaddr;
- uint8_t mii_regaddr;
- uint8_t mii_turnaround;
- uint16_t mii_data;
-};
-
-/*
- * MII constants
- */
-#define RL_MII_STARTDELIM 0x01
-#define RL_MII_READOP 0x02
-#define RL_MII_WRITEOP 0x01
-#define RL_MII_TURNAROUND 0x02
-
#define RL_8129 1
#define RL_8139 2
#define RL_8139CPLUS 3
@@ -657,6 +667,8 @@ struct rl_desc {
#define RL_TDESC_CMD_UDPCSUMV2 0x80000000
#define RL_TDESC_CMD_TCPCSUMV2 0x40000000
#define RL_TDESC_CMD_IPCSUMV2 0x20000000
+#define RL_TDESC_CMD_MSSVALV2 0x1FFC0000
+#define RL_TDESC_CMD_MSSVALV2_SHIFT 18
/*
* Error bits are valid only on the last descriptor of a frame
@@ -764,6 +776,7 @@ struct rl_stats {
#define RL_8139_RX_DESC_CNT 64
#define RL_TX_DESC_CNT RL_8169_TX_DESC_CNT
#define RL_RX_DESC_CNT RL_8169_RX_DESC_CNT
+#define RL_RX_JUMBO_DESC_CNT RL_RX_DESC_CNT
#define RL_NTXSEGS 32
#define RL_RING_ALIGN 256
@@ -798,8 +811,13 @@ struct rl_stats {
/* see comment in dev/re/if_re.c */
#define RL_JUMBO_FRAMELEN 7440
-#define RL_JUMBO_MTU (RL_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
-#define RL_MAX_FRAMELEN \
+#define RL_JUMBO_MTU \
+ (RL_JUMBO_FRAMELEN-ETHER_VLAN_ENCAP_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
+#define RL_JUMBO_MTU_6K \
+ ((6 * 1024) - ETHER_VLAN_ENCAP_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
+#define RL_JUMBO_MTU_9K \
+ ((9 * 1024) - ETHER_VLAN_ENCAP_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
+#define RL_MTU \
(ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
struct rl_txdesc {
@@ -816,6 +834,7 @@ struct rl_rxdesc {
struct rl_list_data {
struct rl_txdesc rl_tx_desc[RL_TX_DESC_CNT];
struct rl_rxdesc rl_rx_desc[RL_RX_DESC_CNT];
+ struct rl_rxdesc rl_jrx_desc[RL_RX_JUMBO_DESC_CNT];
int rl_tx_desc_cnt;
int rl_rx_desc_cnt;
int rl_tx_prodidx;
@@ -824,7 +843,9 @@ struct rl_list_data {
int rl_tx_free;
bus_dma_tag_t rl_tx_mtag; /* mbuf TX mapping tag */
bus_dma_tag_t rl_rx_mtag; /* mbuf RX mapping tag */
+ bus_dma_tag_t rl_jrx_mtag; /* mbuf RX mapping tag */
bus_dmamap_t rl_rx_sparemap;
+ bus_dmamap_t rl_jrx_sparemap;
bus_dma_tag_t rl_stag; /* stats mapping tag */
bus_dmamap_t rl_smap; /* stats map */
struct rl_stats *rl_stats;
@@ -849,15 +870,23 @@ struct rl_softc {
struct resource *rl_res;
int rl_res_id;
int rl_res_type;
+ struct resource *rl_res_pba;
struct resource *rl_irq[RL_MSI_MESSAGES];
void *rl_intrhand[RL_MSI_MESSAGES];
device_t rl_miibus;
bus_dma_tag_t rl_parent_tag;
uint8_t rl_type;
+ const struct rl_hwrev *rl_hwrev;
int rl_eecmd_read;
int rl_eewidth;
- uint8_t rl_stats_no_timeout;
+ int rl_expcap;
int rl_txthresh;
+ bus_size_t rl_cfg0;
+ bus_size_t rl_cfg1;
+ bus_size_t rl_cfg2;
+ bus_size_t rl_cfg3;
+ bus_size_t rl_cfg4;
+ bus_size_t rl_cfg5;
struct rl_chain_data rl_cdata;
struct rl_list_data rl_ldata;
struct callout rl_stat_callout;
@@ -865,7 +894,6 @@ struct rl_softc {
struct mtx rl_mtx;
struct mbuf *rl_head;
struct mbuf *rl_tail;
- uint32_t rl_hwrev;
uint32_t rl_rxlenmask;
int rl_testmode;
int rl_if_flags;
@@ -878,26 +906,31 @@ struct rl_softc {
int rxcycles;
#endif
- struct task rl_txtask;
struct task rl_inttask;
int rl_txstart;
+ int rl_int_rx_act;
+ int rl_int_rx_mod;
uint32_t rl_flags;
-#define RL_FLAG_MSI 0x0001
-#define RL_FLAG_AUTOPAD 0x0002
-#define RL_FLAG_PHYWAKE_PM 0x0004
-#define RL_FLAG_PHYWAKE 0x0008
-#define RL_FLAG_NOJUMBO 0x0010
-#define RL_FLAG_PAR 0x0020
-#define RL_FLAG_DESCV2 0x0040
-#define RL_FLAG_MACSTAT 0x0080
-#define RL_FLAG_FASTETHER 0x0100
-#define RL_FLAG_CMDSTOP 0x0200
-#define RL_FLAG_MACRESET 0x0400
-#define RL_FLAG_WOLRXENB 0x1000
-#define RL_FLAG_MACSLEEP 0x2000
-#define RL_FLAG_PCIE 0x4000
-#define RL_FLAG_LINK 0x8000
+#define RL_FLAG_MSI 0x00000001
+#define RL_FLAG_AUTOPAD 0x00000002
+#define RL_FLAG_PHYWAKE_PM 0x00000004
+#define RL_FLAG_PHYWAKE 0x00000008
+#define RL_FLAG_JUMBOV2 0x00000010
+#define RL_FLAG_PAR 0x00000020
+#define RL_FLAG_DESCV2 0x00000040
+#define RL_FLAG_MACSTAT 0x00000080
+#define RL_FLAG_FASTETHER 0x00000100
+#define RL_FLAG_CMDSTOP 0x00000200
+#define RL_FLAG_MACRESET 0x00000400
+#define RL_FLAG_MSIX 0x00000800
+#define RL_FLAG_WOLRXENB 0x00001000
+#define RL_FLAG_MACSLEEP 0x00002000
+#define RL_FLAG_WAIT_TXPOLL 0x00004000
+#define RL_FLAG_CMDSTOP_WAIT_TXQ 0x00008000
+#define RL_FLAG_WOL_MANLINK 0x00010000
+#define RL_FLAG_PCIE 0x40000000
+#define RL_FLAG_LINK 0x80000000
};
#define RL_LOCK(_sc) mtx_lock(&(_sc)->rl_mtx)
@@ -923,6 +956,9 @@ struct rl_softc {
#define CSR_READ_1(sc, reg) \
bus_space_read_1(sc->rl_btag, sc->rl_bhandle, reg)
+#define CSR_BARRIER(sc, reg, length, flags) \
+ bus_space_barrier(sc->rl_btag, sc->rl_bhandle, reg, length, flags)
+
#define CSR_SETBIT_1(sc, offset, val) \
CSR_WRITE_1(sc, offset, CSR_READ_1(sc, offset) | (val))
@@ -1012,9 +1048,15 @@ struct rl_softc {
#define DLINK_DEVICEID_530TXPLUS 0x1300
/*
+ * D-Link DFE-520TX rev. C1 device ID
+ */
+#define DLINK_DEVICEID_520TX_REVC1 0x4200
+
+/*
* D-Link DFE-5280T device ID
*/
#define DLINK_DEVICEID_528T 0x4300
+#define DLINK_DEVICEID_530T_REVC 0x4302
/*
* D-Link DFE-690TXD device ID
diff --git a/freebsd/sys/powerpc/include/machine/legacyvar.h b/freebsd/sys/powerpc/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/powerpc/include/machine/legacyvar.h
+++ b/freebsd/sys/powerpc/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/powerpc/pci/pci_bus.c b/freebsd/sys/powerpc/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/powerpc/pci/pci_bus.c
+++ b/freebsd/sys/powerpc/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/powerpc/powerpc/legacy.c b/freebsd/sys/powerpc/powerpc/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/powerpc/powerpc/legacy.c
+++ b/freebsd/sys/powerpc/powerpc/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/sh/include/machine/legacyvar.h b/freebsd/sys/sh/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/sh/include/machine/legacyvar.h
+++ b/freebsd/sys/sh/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/sh/pci/pci_bus.c b/freebsd/sys/sh/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/sh/pci/pci_bus.c
+++ b/freebsd/sys/sh/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/sh/sh/legacy.c b/freebsd/sys/sh/sh/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/sh/sh/legacy.c
+++ b/freebsd/sys/sh/sh/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/sparc/include/machine/legacyvar.h b/freebsd/sys/sparc/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/sparc/include/machine/legacyvar.h
+++ b/freebsd/sys/sparc/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/sparc/pci/pci_bus.c b/freebsd/sys/sparc/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/sparc/pci/pci_bus.c
+++ b/freebsd/sys/sparc/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/sparc/sparc/legacy.c b/freebsd/sys/sparc/sparc/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/sparc/sparc/legacy.c
+++ b/freebsd/sys/sparc/sparc/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/sparc64/include/machine/cpufunc.h b/freebsd/sys/sparc64/include/machine/cpufunc.h
index 60533f83..abfbd1fd 100644
--- a/freebsd/sys/sparc64/include/machine/cpufunc.h
+++ b/freebsd/sys/sparc64/include/machine/cpufunc.h
@@ -157,9 +157,9 @@ int fasword32(u_long asi, void *addr, uint32_t *val);
__sr; \
})
-#define wr(name, val, xor) do { \
+#define wr(name, val, xorval) do { \
__asm __volatile("wr %0, %1, %%" #name \
- : : "r" (val), "rI" (xor)); \
+ : : "r" (val), "rI" (xorval)); \
} while (0)
#define rdpr(name) ({ \
@@ -168,37 +168,39 @@ int fasword32(u_long asi, void *addr, uint32_t *val);
__pr; \
})
-#define wrpr(name, val, xor) do { \
+#define wrpr(name, val, xorval) do { \
__asm __volatile("wrpr %0, %1, %%" #name \
- : : "r" (val), "rI" (xor)); \
+ : : "r" (val), "rI" (xorval)); \
} while (0)
/*
- * Trick GAS/GCC into compiling access to STICK/STICK_COMPARE independently
+ * Trick GAS/GCC into compiling access to TICK/(S)TICK_COMPARE independently
* of the selected instruction set.
*/
-#define rdstick() rd(asr24)
-#define rdstickcmpr() rd(asr25)
-#define wrstick(val, xor) wr(asr24, (val), (xor))
-#define wrstickcmpr(val, xor) wr(asr25, (val), (xor))
+#define rdtickcmpr() rd(asr23)
+#define rdstick() rd(asr24)
+#define rdstickcmpr() rd(asr25)
+#define wrtickcmpr(val, xorval) wr(asr23, (val), (xorval))
+#define wrstick(val, xorval) wr(asr24, (val), (xorval))
+#define wrstickcmpr(val, xorval) wr(asr25, (val), (xorval))
/*
- * Macro intended to be used instead of wr(asr23, val, xor) for writing to
+ * Macro intended to be used instead of wr(asr23, val, xorval) for writing to
* the TICK_COMPARE register in order to avoid a bug in BlackBird CPUs that
- * can cause these writes to fail under certain condidtions which in turn
+ * can cause these writes to fail under certain conditions which in turn
* causes the hardclock to stop. The workaround is to read the TICK_COMPARE
* register back immediately after writing to it with these two instructions
* aligned to a quadword boundary in order to ensure that I$ misses won't
* split them up.
*/
-#define wrtickcmpr(val, xor) ({ \
+#define wrtickcmpr_bbwar(val, xorval) ({ \
__asm __volatile( \
" ba,pt %%xcc, 1f ; " \
" nop ; " \
" .align 128 ; " \
"1: wr %0, %1, %%asr23 ; " \
" rd %%asr23, %%g0 ; " \
- : : "r" (val), "rI" (xor)); \
+ : : "r" (val), "rI" (xorval)); \
})
static __inline void
diff --git a/freebsd/sys/sparc64/include/machine/legacyvar.h b/freebsd/sys/sparc64/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/sparc64/include/machine/legacyvar.h
+++ b/freebsd/sys/sparc64/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/sparc64/pci/pci_bus.c b/freebsd/sys/sparc64/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/sparc64/pci/pci_bus.c
+++ b/freebsd/sys/sparc64/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/sparc64/sparc64/legacy.c b/freebsd/sys/sparc64/sparc64/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/sparc64/sparc64/legacy.c
+++ b/freebsd/sys/sparc64/sparc64/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/sys/ata.h b/freebsd/sys/sys/ata.h
index cacb1ea0..efa5b246 100644
--- a/freebsd/sys/sys/ata.h
+++ b/freebsd/sys/sys/ata.h
@@ -135,6 +135,7 @@ struct ata_params {
#define ATA_SUPPORT_AUTOACTIVATE 0x0004
#define ATA_SUPPORT_IFPWRMNGT 0x0008
#define ATA_SUPPORT_INORDERDATA 0x0010
+#define ATA_SUPPORT_ASYNCNOTIF 0x0020
#define ATA_SUPPORT_SOFTSETPRESERVE 0x0040
/*79*/ u_int16_t sataenabled;
#define ATA_ENABLED_DAPST 0x0080
@@ -260,6 +261,20 @@ struct ata_params {
/*255*/ u_int16_t integrity;
} __packed;
+/*
+ * ATA Device Register
+ *
+ * bit 7 Obsolete (was 1 in early ATA specs)
+ * bit 6 Sets LBA/CHS mode. 1=LBA, 0=CHS
+ * bit 5 Obsolete (was 1 in early ATA specs)
+ * bit 4 1 = Slave Drive, 0 = Master Drive
+ * bit 3-0 In LBA mode, 27-24 of address. In CHS mode, head number
+*/
+
+#define ATA_DEV_MASTER 0x00
+#define ATA_DEV_SLAVE 0x10
+#define ATA_DEV_LBA 0x40
+
/* ATA transfer modes */
#define ATA_MODE_MASK 0x0f
diff --git a/freebsd/sys/sys/buf.h b/freebsd/sys/sys/buf.h
index 6cc68ee9..e182c7cc 100644
--- a/freebsd/sys/sys/buf.h
+++ b/freebsd/sys/sys/buf.h
@@ -311,6 +311,12 @@ extern const char *buf_wmesg; /* Default buffer lock message */
lockdestroy(&(bp)->b_lock)
/*
+ * Print informations on a buffer lock.
+ */
+#define BUF_LOCKPRINTINFO(bp) \
+ lockmgr_printinfo(&(bp)->b_lock)
+
+/*
* Buffer lock assertions.
*/
#if defined(INVARIANTS) && defined(INVARIANT_SUPPORT)
diff --git a/freebsd/sys/sys/bus.h b/freebsd/sys/sys/bus.h
index 6c1128e3..7259981e 100644
--- a/freebsd/sys/sys/bus.h
+++ b/freebsd/sys/sys/bus.h
@@ -52,6 +52,7 @@ struct u_businfo {
typedef enum device_state {
DS_NOTPRESENT = 10, /**< @brief not probed or probe failed */
DS_ALIVE = 20, /**< @brief probe succeeded */
+ DS_ATTACHING = 25, /**< @brief currently attaching */
DS_ATTACHED = 30, /**< @brief attach method called */
DS_BUSY = 40 /**< @brief device is open */
} device_state_t;
@@ -194,7 +195,11 @@ enum intr_type {
INTR_FAST = 128,
INTR_EXCL = 256, /* exclusive interrupt */
INTR_MPSAFE = 512, /* this interrupt is SMP safe */
- INTR_ENTROPY = 1024 /* this interrupt provides entropy */
+ INTR_ENTROPY = 1024, /* this interrupt provides entropy */
+ INTR_MD1 = 4096, /* flag reserved for MD use */
+ INTR_MD2 = 8192, /* flag reserved for MD use */
+ INTR_MD3 = 16384, /* flag reserved for MD use */
+ INTR_MD4 = 32768 /* flag reserved for MD use */
};
enum intr_trigger {
@@ -285,6 +290,9 @@ int bus_generic_activate_resource(device_t dev, device_t child, int type,
device_t
bus_generic_add_child(device_t dev, u_int order, const char *name,
int unit);
+int bus_generic_adjust_resource(device_t bus, device_t child, int type,
+ struct resource *r, u_long start,
+ u_long end);
struct resource *
bus_generic_alloc_resource(device_t bus, device_t child, int type,
int *rid, u_long start, u_long end,
@@ -353,6 +361,8 @@ struct resource_spec {
int bus_alloc_resources(device_t dev, struct resource_spec *rs, struct resource **res);
void bus_release_resources(device_t dev, const struct resource_spec *rs, struct resource **res);
+int bus_adjust_resource(device_t child, int type, struct resource *r,
+ u_long start, u_long end);
struct resource *bus_alloc_resource(device_t dev, int type, int *rid,
u_long start, u_long end, u_long count,
u_int flags);
@@ -397,6 +407,7 @@ device_t device_add_child_ordered(device_t dev, u_int order,
const char *name, int unit);
void device_busy(device_t dev);
int device_delete_child(device_t dev, device_t child);
+int device_delete_children(device_t dev);
int device_attach(device_t dev);
int device_detach(device_t dev);
void device_disable(device_t dev);
@@ -540,9 +551,10 @@ extern int bus_current_pass;
void bus_set_pass(int pass);
/**
- * Shorthand for constructing method tables.
+ * Shorthands for constructing method tables.
*/
#define DEVMETHOD KOBJMETHOD
+#define DEVMETHOD_END KOBJMETHOD_END
/*
* Some common device interfaces.
@@ -566,7 +578,8 @@ struct driver_module_data {
int dmd_pass;
};
-#define EARLY_DRIVER_MODULE(name, busname, driver, devclass, evh, arg, pass) \
+#define EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, devclass, \
+ evh, arg, order, pass) \
\
static struct driver_module_data name##_##busname##_driver_mod = { \
evh, arg, \
@@ -582,7 +595,16 @@ static moduledata_t name##_##busname##_mod = { \
&name##_##busname##_driver_mod \
}; \
DECLARE_MODULE(name##_##busname, name##_##busname##_mod, \
- SI_SUB_DRIVERS, SI_ORDER_MIDDLE)
+ SI_SUB_DRIVERS, order)
+
+#define EARLY_DRIVER_MODULE(name, busname, driver, devclass, evh, arg, pass) \
+ EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, devclass, \
+ evh, arg, SI_ORDER_MIDDLE, pass)
+
+#define DRIVER_MODULE_ORDERED(name, busname, driver, devclass, evh, arg,\
+ order) \
+ EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, devclass, \
+ evh, arg, order, BUS_PASS_DEFAULT)
#define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \
EARLY_DRIVER_MODULE(name, busname, driver, devclass, evh, arg, \
diff --git a/freebsd/sys/sys/callout.h b/freebsd/sys/sys/callout.h
index 2d43d149..370cec7a 100644
--- a/freebsd/sys/sys/callout.h
+++ b/freebsd/sys/sys/callout.h
@@ -64,6 +64,7 @@ struct callout {
#define CALLOUT_MPSAFE 0x0008 /* callout handler is mp safe */
#define CALLOUT_RETURNUNLOCKED 0x0010 /* handler returns with mtx unlocked */
#define CALLOUT_SHAREDLOCK 0x0020 /* callout lock held in shared mode */
+#define CALLOUT_DFRMIGRATION 0x0040 /* callout in deferred migration mode */
struct callout_handle {
struct callout *callout;
diff --git a/freebsd/sys/sys/eventhandler.h b/freebsd/sys/sys/eventhandler.h
index 0da999d0..61d05bff 100644
--- a/freebsd/sys/sys/eventhandler.h
+++ b/freebsd/sys/sys/eventhandler.h
@@ -178,6 +178,11 @@ EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */
EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */
EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn);
+/* Power state change events */
+typedef void (*power_change_fn)(void *);
+EVENTHANDLER_DECLARE(power_resume, power_change_fn);
+EVENTHANDLER_DECLARE(power_suspend, power_change_fn);
+
/* Low memory event */
typedef void (*vm_lowmem_handler_t)(void *, int);
#define LOWMEM_PRI_DEFAULT EVENTHANDLER_PRI_FIRST
@@ -237,6 +242,4 @@ typedef void (*uma_zone_chfn)(void *);
EVENTHANDLER_DECLARE(nmbclusters_change, uma_zone_chfn);
EVENTHANDLER_DECLARE(maxsockets_change, uma_zone_chfn);
-typedef void(*schedtail_fn)(void *, struct proc *);
-EVENTHANDLER_DECLARE(schedtail, schedtail_fn);
#endif /* SYS_EVENTHANDLER_H */
diff --git a/freebsd/sys/sys/file.h b/freebsd/sys/sys/file.h
index 60339b81..f563f75c 100644
--- a/freebsd/sys/sys/file.h
+++ b/freebsd/sys/sys/file.h
@@ -117,6 +117,14 @@ struct fileops {
* none not locked
*/
+struct fadvise_info {
+ int fa_advice; /* (f) FADV_* type. */
+ off_t fa_start; /* (f) Region start. */
+ off_t fa_end; /* (f) Region end. */
+ off_t fa_prevstart; /* (f) Previous NOREUSE start. */
+ off_t fa_prevend; /* (f) Previous NOREUSE end. */
+};
+
struct file {
#ifndef __rtems__
void *f_data; /* file descriptor specific data */
@@ -132,7 +140,11 @@ struct file {
*/
int f_seqcount; /* Count of sequential accesses. */
off_t f_nextoff; /* next expected read/write offset. */
- struct cdev_privdata *f_cdevpriv; /* (d) Private data for the cdev. */
+ union {
+ struct cdev_privdata *fvn_cdevpriv;
+ /* (d) Private data for the cdev. */
+ struct fadvise_info *fvn_advice;
+ } f_vnun;
/*
* DFLAG_SEEKABLE specific fields
*/
@@ -223,6 +235,9 @@ rtems_bsd_error_to_status_and_errno(int error)
}
#endif /* __rtems__ */
+#define f_cdevpriv f_vnun.fvn_cdevpriv
+#define f_advice f_vnun.fvn_advice
+
#define FOFFSET_LOCKED 0x1
#define FOFFSET_LOCK_WAITING 0x2
diff --git a/freebsd/sys/sys/filedesc.h b/freebsd/sys/sys/filedesc.h
index 62bbc6f2..0b48d849 100644
--- a/freebsd/sys/sys/filedesc.h
+++ b/freebsd/sys/sys/filedesc.h
@@ -153,6 +153,8 @@ falloc(struct thread *td, struct file **resultfp, int *resultfd)
}
}
#endif /* __rtems__ */
+int fallocf(struct thread *td, struct file **resultfp, int *resultfd,
+ int flags);
int fdalloc(struct thread *td, int minfd, int *result);
int fdavail(struct thread *td, int n);
int fdcheckstd(struct thread *td);
diff --git a/freebsd/sys/sys/hhook.h b/freebsd/sys/sys/hhook.h
new file mode 100644
index 00000000..51eda1fd
--- /dev/null
+++ b/freebsd/sys/sys/hhook.h
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Lawrence Stewart while studying at the Centre
+ * for Advanced Internet Architectures, Swinburne University of Technology, made
+ * possible in part by grants from the FreeBSD Foundation and Cisco University
+ * Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by Lawrence Stewart under sponsorship from the FreeBSD Foundation.
+ *
+ * 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$
+ */
+
+/*
+ * A KPI modelled on the pfil framework for instantiating helper hook points
+ * within the kernel for use by Khelp modules. Originally released as part of
+ * the NewTCP research project at Swinburne University of Technology's Centre
+ * for Advanced Internet Architectures, Melbourne, Australia, which was made
+ * possible in part by a grant from the Cisco University Research Program Fund
+ * at Community Foundation Silicon Valley. More details are available at:
+ * http://caia.swin.edu.au/urp/newtcp/
+ */
+
+#ifndef _SYS_HHOOK_H_
+#define _SYS_HHOOK_H_
+
+/* XXXLAS: Is there a way around this? */
+#include <rtems/bsd/sys/lock.h>
+#include <sys/rmlock.h>
+
+/* hhook_head flags. */
+#define HHH_ISINVNET 0x00000001 /* Is the hook point in a vnet? */
+
+/* Flags common to all register functions. */
+#define HHOOK_WAITOK 0x00000001 /* Sleeping allowed. */
+#define HHOOK_NOWAIT 0x00000002 /* Sleeping disallowed. */
+/* Flags only relevant to hhook_head_register() and hhook_head_is_virtual(). */
+#define HHOOK_HEADISINVNET 0x00000100 /* Public proxy for HHH_ISINVNET. */
+
+/* Helper hook types. */
+#define HHOOK_TYPE_TCP 1
+
+struct helper;
+struct osd;
+
+/* Signature for helper hook functions. */
+typedef int (*hhook_func_t)(int32_t hhook_type, int32_t hhook_id, void *udata,
+ void *ctx_data, void *hdata, struct osd *hosd);
+
+/*
+ * Information required to add/remove a helper hook function to/from a helper
+ * hook point.
+ */
+struct hookinfo {
+ hhook_func_t hook_func;
+ struct helper *hook_helper;
+ void *hook_udata;
+ int32_t hook_id;
+ int32_t hook_type;
+};
+
+/*
+ * Ideally this would be private but we need access to the hhh_nhooks member
+ * variable in order to make the HHOOKS_RUN_IF() macro low impact.
+ */
+struct hhook_head {
+ STAILQ_HEAD(hhook_list, hhook) hhh_hooks;
+ struct rmlock hhh_lock;
+ int32_t hhh_id;
+ int32_t hhh_nhooks;
+ int32_t hhh_type;
+ uint32_t hhh_flags;
+ volatile uint32_t hhh_refcount;
+ LIST_ENTRY(hhook_head) hhh_next;
+};
+
+/* Public KPI functions. */
+void hhook_run_hooks(struct hhook_head *hhh, void *ctx_data, struct osd *hosd);
+
+int hhook_add_hook(struct hhook_head *hhh, struct hookinfo *hki,
+ uint32_t flags);
+
+int hhook_add_hook_lookup(struct hookinfo *hki, uint32_t flags);
+
+int hhook_remove_hook(struct hhook_head *hhh, struct hookinfo *hki);
+
+int hhook_remove_hook_lookup(struct hookinfo *hki);
+
+int hhook_head_register(int32_t hhook_type, int32_t hhook_id,
+ struct hhook_head **hhh, uint32_t flags);
+
+int hhook_head_deregister(struct hhook_head *hhh);
+
+int hhook_head_deregister_lookup(int32_t hhook_type, int32_t hhook_id);
+
+struct hhook_head * hhook_head_get(int32_t hhook_type, int32_t hhook_id);
+
+void hhook_head_release(struct hhook_head *hhh);
+
+uint32_t hhook_head_is_virtualised(struct hhook_head *hhh);
+
+uint32_t hhook_head_is_virtualised_lookup(int32_t hook_type, int32_t hook_id);
+
+/*
+ * A wrapper around hhook_run_hooks() that only calls the function if at least
+ * one helper hook function is registered for the specified helper hook point.
+ */
+#define HHOOKS_RUN_IF(hhh, ctx_data, hosd) do { \
+ if (hhh != NULL && hhh->hhh_nhooks > 0) \
+ hhook_run_hooks(hhh, ctx_data, hosd); \
+} while (0)
+
+/*
+ * WARNING: This macro should only be used in code paths that execute
+ * infrequently, otherwise the refcounting overhead would be excessive.
+ *
+ * A similar wrapper to HHOOKS_RUN_IF() for situations where the caller prefers
+ * not to lookup and store the appropriate hhook_head pointer themselves.
+ */
+#define HHOOKS_RUN_LOOKUP_IF(hhook_type, hhook_id, ctx_data, hosd) do { \
+ struct hhook_head *_hhh; \
+ \
+ _hhh = hhook_head_get(hhook_type, hhook_id); \
+ if (_hhh != NULL) { \
+ if (_hhh->hhh_nhooks > 0) \
+ hhook_run_hooks(_hhh, ctx_data, hosd); \
+ hhook_head_release(_hhh); \
+ } \
+} while (0)
+
+#endif /* _SYS_HHOOK_H_ */
diff --git a/freebsd/sys/sys/kernel.h b/freebsd/sys/sys/kernel.h
index 9b5aa856..83122c99 100644
--- a/freebsd/sys/sys/kernel.h
+++ b/freebsd/sys/sys/kernel.h
@@ -66,7 +66,7 @@ extern int stathz; /* statistics clock's frequency */
extern int profhz; /* profiling clock's frequency */
extern int profprocs; /* number of process's profiling */
#ifndef __rtems__
-extern int ticks;
+extern volatile int ticks;
#else /* __rtems__ */
#include <rtems/score/watchdogimpl.h>
#define ticks _Watchdog_Ticks_since_boot
diff --git a/freebsd/sys/sys/khelp.h b/freebsd/sys/sys/khelp.h
new file mode 100644
index 00000000..db12d6bb
--- /dev/null
+++ b/freebsd/sys/sys/khelp.h
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Lawrence Stewart while studying at the Centre
+ * for Advanced Internet Architectures, Swinburne University of Technology, made
+ * possible in part by grants from the FreeBSD Foundation and Cisco University
+ * Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by Lawrence Stewart under sponsorship from the FreeBSD Foundation.
+ *
+ * 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$
+ */
+
+/*
+ * A KPI for managing kernel helper modules which perform useful functionality
+ * within the kernel. Originally released as part of the NewTCP research project
+ * at Swinburne University of Technology's Centre for Advanced Internet
+ * Architectures, Melbourne, Australia, which was made possible in part by a
+ * grant from the Cisco University Research Program Fund at Community Foundation
+ * Silicon Valley. More details are available at:
+ * http://caia.swin.edu.au/urp/newtcp/
+ */
+
+#ifndef _SYS_KHELP_H_
+#define _SYS_KHELP_H_
+
+struct helper;
+struct hookinfo;
+struct osd;
+
+/* Helper classes. */
+#define HELPER_CLASS_TCP 0x00000001
+
+/* Public KPI functions. */
+int khelp_register_helper(struct helper *h);
+
+int khelp_deregister_helper(struct helper *h);
+
+int khelp_init_osd(uint32_t classes, struct osd *hosd);
+
+int khelp_destroy_osd(struct osd *hosd);
+
+void * khelp_get_osd(struct osd *hosd, int32_t id);
+
+int32_t khelp_get_id(char *hname);
+
+int khelp_add_hhook(struct hookinfo *hki, uint32_t flags);
+
+int khelp_remove_hhook(struct hookinfo *hki);
+
+#endif /* _SYS_KHELP_H_ */
diff --git a/freebsd/sys/sys/kobj.h b/freebsd/sys/sys/kobj.h
index 3143bea4..5df5dccc 100644
--- a/freebsd/sys/sys/kobj.h
+++ b/freebsd/sys/sys/kobj.h
@@ -201,6 +201,7 @@ kobj_t kobj_create(kobj_class_t cls,
* Initialise a pre-allocated object.
*/
void kobj_init(kobj_t obj, kobj_class_t cls);
+void kobj_init_static(kobj_t obj, kobj_class_t cls);
/*
* Delete an object. If mtype is non-zero, free the memory.
diff --git a/freebsd/sys/sys/libkern.h b/freebsd/sys/sys/libkern.h
index a09517cc..942c21f5 100644
--- a/freebsd/sys/sys/libkern.h
+++ b/freebsd/sys/sys/libkern.h
@@ -127,6 +127,7 @@ size_t strlen(const char *);
int strncasecmp(const char *, const char *, size_t);
int strncmp(const char *, const char *, size_t);
char *strncpy(char * __restrict, const char * __restrict, size_t);
+size_t strnlen(const char *, size_t);
char *strsep(char **, const char *delim);
size_t strspn(const char *, const char *);
char *strstr(const char *, const char *);
diff --git a/freebsd/sys/sys/limits.h b/freebsd/sys/sys/limits.h
index 633a7f70..edb21d8d 100644
--- a/freebsd/sys/sys/limits.h
+++ b/freebsd/sys/sys/limits.h
@@ -91,7 +91,7 @@
#endif
#ifndef __rtems__
-#if __XSI_VISIBLE
+#if __XSI_VISIBLE || __POSIX_VISIBLE >= 200809
#define LONG_BIT __LONG_BIT
#define WORD_BIT __WORD_BIT
#endif
diff --git a/freebsd/sys/sys/mman.h b/freebsd/sys/sys/mman.h
index 4872d631..5ed9cdd6 100644
--- a/freebsd/sys/sys/mman.h
+++ b/freebsd/sys/sys/mman.h
@@ -82,11 +82,15 @@
*/
#define MAP_FILE 0x0000 /* map from file (default) */
#define MAP_ANON 0x1000 /* allocated from memory, swap space */
+#ifndef _KERNEL
+#define MAP_ANONYMOUS MAP_ANON /* For compatibility. */
+#endif /* !_KERNEL */
/*
* Extended flags
*/
#define MAP_NOCORE 0x00020000 /* dont include these pages in a coredump */
+#define MAP_PREFAULT_READ 0x00040000 /* prefault mapping for reading */
#endif /* __BSD_VISIBLE */
#if __POSIX_VISIBLE >= 199309
@@ -174,9 +178,11 @@ typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_WANT_FILE)
#include <vm/vm.h>
+struct file;
+
struct shmfd {
size_t shm_size;
vm_object_t shm_object;
@@ -184,6 +190,7 @@ struct shmfd {
uid_t shm_uid;
gid_t shm_gid;
mode_t shm_mode;
+ int shm_kmappings;
/*
* Values maintained solely to make this a better-behaved file
@@ -195,10 +202,16 @@ struct shmfd {
struct timespec shm_birthtime;
struct label *shm_label; /* MAC label */
+ const char *shm_path;
};
+#endif
+#ifdef _KERNEL
int shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_ooffset_t foff,
vm_object_t *obj);
+int shm_map(struct file *fp, size_t size, off_t offset, void **memp);
+int shm_unmap(struct file *fp, void *mem, size_t size);
+void shm_path(struct shmfd *shmfd, char *path, size_t size);
#else /* !_KERNEL */
diff --git a/freebsd/sys/sys/module_khelp.h b/freebsd/sys/sys/module_khelp.h
new file mode 100644
index 00000000..9a7f507d
--- /dev/null
+++ b/freebsd/sys/sys/module_khelp.h
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Lawrence Stewart while studying at the Centre
+ * for Advanced Internet Architectures, Swinburne University of Technology, made
+ * possible in part by grants from the FreeBSD Foundation and Cisco University
+ * Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by Lawrence Stewart under sponsorship from the FreeBSD Foundation.
+ *
+ * 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$
+ */
+
+#ifndef _SYS_MODULE_KHELP_H_
+#define _SYS_MODULE_KHELP_H_
+
+/* XXXLAS: Needed for uma related typedefs. */
+#include <vm/uma.h>
+
+/* Helper flags. */
+#define HELPER_NEEDS_OSD 0x0001
+
+struct helper {
+ int (*mod_init) (void);
+ int (*mod_destroy) (void);
+#define HELPER_NAME_MAXLEN 16
+ char h_name[HELPER_NAME_MAXLEN];
+ uma_zone_t h_zone;
+ struct hookinfo *h_hooks;
+ uint32_t h_nhooks;
+ uint32_t h_classes;
+ int32_t h_id;
+ volatile uint32_t h_refcount;
+ uint16_t h_flags;
+ TAILQ_ENTRY(helper) h_next;
+};
+
+struct khelp_modevent_data {
+ char name[HELPER_NAME_MAXLEN];
+ struct helper *helper;
+ struct hookinfo *hooks;
+ int nhooks;
+ int uma_zsize;
+ uma_ctor umactor;
+ uma_dtor umadtor;
+};
+
+#define KHELP_DECLARE_MOD(hname, hdata, hhooks, version) \
+ static struct khelp_modevent_data kmd_##hname = { \
+ .name = #hname, \
+ .helper = hdata \
+ .hooks = hhooks, \
+ .nhooks = sizeof(hhooks) / sizeof(hhooks[0]), \
+ }; \
+ static moduledata_t h_##hname = { \
+ .name = #hname, \
+ .evhand = khelp_modevent, \
+ .priv = &kmd_##hname \
+ }; \
+ DECLARE_MODULE(hname, h_##hname, SI_SUB_PROTO_IFATTACHDOMAIN, \
+ SI_ORDER_ANY); \
+ MODULE_VERSION(hname, version)
+
+#define KHELP_DECLARE_MOD_UMA(hname, hdata, hhooks, version, size, ctor, dtor) \
+ static struct khelp_modevent_data kmd_##hname = { \
+ .name = #hname, \
+ .helper = hdata, \
+ .hooks = hhooks, \
+ .nhooks = sizeof(hhooks) / sizeof(hhooks[0]), \
+ .uma_zsize = size, \
+ .umactor = ctor, \
+ .umadtor = dtor \
+ }; \
+ static moduledata_t h_##hname = { \
+ .name = #hname, \
+ .evhand = khelp_modevent, \
+ .priv = &kmd_##hname \
+ }; \
+ DECLARE_MODULE(hname, h_##hname, SI_SUB_PROTO_IFATTACHDOMAIN, \
+ SI_ORDER_ANY); \
+ MODULE_VERSION(hname, version)
+
+int khelp_modevent(module_t mod, int type, void *data);
+
+#endif /* _SYS_MODULE_KHELP_H_ */
diff --git a/freebsd/sys/sys/mount.h b/freebsd/sys/sys/mount.h
index fcf80bd5..efa17492 100644
--- a/freebsd/sys/sys/mount.h
+++ b/freebsd/sys/sys/mount.h
@@ -201,10 +201,10 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
__mnt_vnode_markerfree(&(mvp), (mp))
#define MNT_VNODE_FOREACH_ABORT(mp, mvp) \
- do { \
- MNT_ILOCK(mp); \
- MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); \
- MNT_IUNLOCK(mp); \
+ do { \
+ MNT_ILOCK(mp); \
+ MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); \
+ MNT_IUNLOCK(mp); \
} while (0)
#define MNT_ILOCK(mp) mtx_lock(&(mp)->mnt_mtx)
@@ -213,7 +213,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
#define MNT_MTX(mp) (&(mp)->mnt_mtx)
#define MNT_REF(mp) (mp)->mnt_ref++
#define MNT_REL(mp) do { \
- KASSERT((mp)->mnt_ref > 0, ("negative mnt_ref")); \
+ KASSERT((mp)->mnt_ref > 0, ("negative mnt_ref")); \
(mp)->mnt_ref--; \
if ((mp)->mnt_ref == 0) \
wakeup((mp)); \
diff --git a/freebsd/sys/sys/mutex.h b/freebsd/sys/sys/mutex.h
index 3e4a1701..e7649d8f 100644
--- a/freebsd/sys/sys/mutex.h
+++ b/freebsd/sys/sys/mutex.h
@@ -399,7 +399,8 @@ do { \
\
if (mtx_owned(&Giant)) { \
WITNESS_SAVE(&Giant.lock_object, Giant); \
- for (_giantcnt = 0; mtx_owned(&Giant); _giantcnt++) \
+ for (_giantcnt = 0; mtx_owned(&Giant) && \
+ !SCHEDULER_STOPPED(); _giantcnt++) \
mtx_unlock(&Giant); \
}
diff --git a/freebsd/sys/sys/osd.h b/freebsd/sys/sys/osd.h
index 63d536fa..14316ae3 100644
--- a/freebsd/sys/sys/osd.h
+++ b/freebsd/sys/sys/osd.h
@@ -46,9 +46,10 @@ struct osd {
#define OSD_THREAD 0
#define OSD_JAIL 1
+#define OSD_KHELP 2
#define OSD_FIRST OSD_THREAD
-#define OSD_LAST OSD_JAIL
+#define OSD_LAST OSD_KHELP
typedef void (*osd_destructor_t)(void *value);
typedef int (*osd_method_t)(void *obj, void *data);
diff --git a/freebsd/sys/sys/priority.h b/freebsd/sys/sys/priority.h
index 9bbd2de8..a3493715 100644
--- a/freebsd/sys/sys/priority.h
+++ b/freebsd/sys/sys/priority.h
@@ -85,14 +85,12 @@
#define PI_REALTIME (PRI_MIN_ITHD + 0)
#define PI_AV (PRI_MIN_ITHD + 4)
-#define PI_TTYHIGH (PRI_MIN_ITHD + 8)
-#define PI_TAPE (PRI_MIN_ITHD + 12)
#define PI_NET (PRI_MIN_ITHD + 16)
#define PI_DISK (PRI_MIN_ITHD + 20)
-#define PI_TTYLOW (PRI_MIN_ITHD + 24)
-#define PI_DISKLOW (PRI_MIN_ITHD + 28)
+#define PI_TTY (PRI_MIN_ITHD + 24)
#define PI_DULL (PRI_MIN_ITHD + 32)
#define PI_SOFT (PRI_MIN_ITHD + 36)
+#define PI_SWI(x) (PI_SOFT + (x) * RQ_PPQ)
#define PRI_MIN_KERN (64)
#define PRI_MAX_KERN (PRI_MIN_REALTIME - 1)
@@ -105,7 +103,6 @@
#define PZERO (PRI_MIN_KERN + 20)
#define PSOCK (PRI_MIN_KERN + 24)
#define PWAIT (PRI_MIN_KERN + 28)
-#define PCONFIG (PRI_MIN_KERN + 32)
#define PLOCK (PRI_MIN_KERN + 36)
#define PPAUSE (PRI_MIN_KERN + 40)
@@ -120,6 +117,12 @@
#define PRI_MIN_IDLE (224)
#define PRI_MAX_IDLE (PRI_MAX)
+#ifdef _KERNEL
+/* Other arguments for kern_yield(9). */
+#define PRI_USER -2 /* Change to current user priority. */
+#define PRI_UNCHANGED -1 /* Do not change priority. */
+#endif
+
struct priority {
u_char pri_class; /* Scheduling class. */
u_char pri_level; /* Normal priority level. */
diff --git a/freebsd/sys/sys/priv.h b/freebsd/sys/sys/priv.h
index 6939e144..a9b9bdb6 100644
--- a/freebsd/sys/sys/priv.h
+++ b/freebsd/sys/sys/priv.h
@@ -336,6 +336,7 @@
#define PRIV_NET_GIF 416 /* Administer gif interface. */
#define PRIV_NET_SETIFVNET 417 /* Move interface to vnet. */
#define PRIV_NET_SETIFDESCR 418 /* Set interface description. */
+#define PRIV_NET_SETIFFIB 419 /* Set interface fib. */
/*
* 802.11-related privileges.
@@ -497,7 +498,7 @@
#ifdef _KERNEL
/*
- * Privilege check interfaces, modeled after historic suser() interfacs, but
+ * Privilege check interfaces, modeled after historic suser() interfaces, but
* with the addition of a specific privilege name. No flags are currently
* defined for the API. Historically, flags specified using the real uid
* instead of the effective uid, and whether or not the check should be
diff --git a/freebsd/sys/sys/proc.h b/freebsd/sys/sys/proc.h
index ba40e259..d75dd7de 100644
--- a/freebsd/sys/sys/proc.h
+++ b/freebsd/sys/sys/proc.h
@@ -238,6 +238,7 @@ struct thread {
short td_locks; /* (k) Count of non-spin locks. */
short td_rw_rlocks; /* (k) Count of rwlock read locks. */
short td_lk_slocks; /* (k) Count of lockmgr shared locks. */
+ short td_stopsched; /* (k) Scheduler stopped. */
struct turnstile *td_blocked; /* (t) Lock thread is blocked on. */
const char *td_lockname; /* (t) Name of lock blocked on. */
LIST_HEAD(, turnstile) td_contested; /* (q) Contested locks. */
@@ -250,6 +251,7 @@ struct thread {
u_int td_estcpu; /* (t) estimated cpu utilization */
int td_slptick; /* (t) Time at sleep. */
int td_blktick; /* (t) Time spent blocked. */
+ u_int td_cow; /* (*) Number of copy-on-write faults */
struct rusage td_ru; /* (t) rusage information. */
uint64_t td_incruntime; /* (t) Cpu ticks to transfer to proc. */
uint64_t td_runtime; /* (t) How many cpu ticks we've run. */
@@ -271,7 +273,7 @@ struct thread {
struct ksiginfo td_dbgksi; /* (c) ksi reflected to debugger. */
int td_ng_outbound; /* (k) Thread entered ng from above. */
struct osd td_osd; /* (k) Object specific data. */
-#define td_endzero td_base_pri
+#define td_endzero td_rqindex
/* Copied during fork1() or thread_sched_upcall(). */
#define td_startcopy td_endzero
@@ -318,6 +320,8 @@ struct thread {
const char *td_vnet_lpush; /* (k) Debugging vnet push / pop. */
struct rusage_ext td_rux; /* (t) Internal rusage information. */
struct vm_map_entry *td_map_def_user; /* (k) Deferred entries. */
+ pid_t td_dbg_forked; /* (c) Child pid for debugger. */
+ u_int td_vp_reserv; /* (k) Count of reserved vnodes. */
#endif /* __rtems__ */
};
@@ -367,7 +371,7 @@ do { \
#define TDF_NEEDSUSPCHK 0x00008000 /* Thread may need to suspend. */
#define TDF_NEEDRESCHED 0x00010000 /* Thread needs to yield. */
#define TDF_NEEDSIGCHK 0x00020000 /* Thread may need signal delivery. */
-#define TDF_UNUSED18 0x00040000 /* --available-- */
+#define TDF_NOLOAD 0x00040000 /* Ignore during load avg calculations. */
#define TDF_UNUSED19 0x00080000 /* Thread is sleeping on a umtx. */
#define TDF_THRWAKEUP 0x00100000 /* Libthr thread must not suspend itself. */
#define TDF_UNUSED21 0x00200000 /* --available-- */
@@ -388,6 +392,10 @@ do { \
#define TDB_SCE 0x00000008 /* Thread performs syscall enter */
#define TDB_SCX 0x00000010 /* Thread performs syscall exit */
#define TDB_EXEC 0x00000020 /* TDB_SCX from exec(2) family */
+#define TDB_FORK 0x00000040 /* TDB_SCX from fork(2) that created new
+ process */
+#define TDB_STOPATFORK 0x00000080 /* Stop at the return from fork (child
+ only) */
/*
* "Private" flags kept in td_pflags:
@@ -400,11 +408,11 @@ do { \
#define TDP_COWINPROGRESS 0x00000010 /* Snapshot copy-on-write in progress. */
#define TDP_ALTSTACK 0x00000020 /* Have alternate signal stack. */
#define TDP_DEADLKTREAT 0x00000040 /* Lock aquisition - deadlock treatment. */
-#define TDP_UNUSED80 0x00000080 /* available. */
+#define TDP_NOFAULTING 0x00000080 /* Do not handle page faults. */
#define TDP_NOSLEEPING 0x00000100 /* Thread is not allowed to sleep on a sq. */
#define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */
#define TDP_ITHREAD 0x00000400 /* Thread is an interrupt thread. */
-#define TDP_UNUSED800 0x00000800 /* available. */
+#define TDP_SYNCIO 0x00000800 /* Local override, disable async i/o. */
#define TDP_SCHED1 0x00001000 /* Reserved for scheduler private use */
#define TDP_SCHED2 0x00002000 /* Reserved for scheduler private use */
#define TDP_SCHED3 0x00004000 /* Reserved for scheduler private use */
@@ -418,6 +426,8 @@ do { \
#define TDP_CALLCHAIN 0x00400000 /* Capture thread's callchain */
#define TDP_IGNSUSP 0x00800000 /* Permission to ignore the MNTK_SUSPEND* */
#define TDP_AUDITREC 0x01000000 /* Audit record pending on thread */
+#define TDP_RESETSPUR 0x04000000 /* Reset spurious page fault history. */
+#define TDP_NERRNO 0x08000000 /* Last errno is already in td_errno */
/*
* Reasons that the current thread can not be run yet.
@@ -537,7 +547,7 @@ struct proc {
struct thread *p_singlethread;/* (c + j) If single threading this is it */
int p_suspcount; /* (j) Num threads in suspended mode. */
struct thread *p_xthread; /* (c) Trap thread */
- int p_boundary_count;/* (c) Num threads at user boundary */
+ int p_boundary_count;/* (j) Num threads at user boundary */
int p_pendingcnt; /* how many signals are pending */
struct itimers *p_itimers; /* (c) POSIX interval timers. */
/* End area that is zeroed on creation. */
@@ -572,7 +582,9 @@ struct proc {
STAILQ_HEAD(, ktr_request) p_ktr; /* (o) KTR event queue. */
LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/
struct kdtrace_proc *p_dtrace; /* (*) DTrace-specific data. */
- struct cv p_pwait; /* (*) wait cv for exit/exec */
+ struct cv p_pwait; /* (*) wait cv for exit/exec. */
+ struct cv p_dbgwait; /* (*) wait cv for debugger attach
+ after fork. */
#endif /* __rtems__ */
};
@@ -589,7 +601,7 @@ struct proc {
#define P_ADVLOCK 0x00001 /* Process may hold a POSIX advisory lock. */
#define P_CONTROLT 0x00002 /* Has a controlling terminal. */
#define P_KTHREAD 0x00004 /* Kernel thread (*). */
-#define P_NOLOAD 0x00008 /* Ignore during load avg calculations. */
+#define P_FOLLOWFORK 0x00008 /* Attach parent debugger to children. */
#define P_PPWAIT 0x00010 /* Parent is waiting for child to exec/exit. */
#define P_PROFIL 0x00020 /* Has started profiling. */
#define P_STOPPROF 0x00040 /* Has thread requesting to stop profiling. */
@@ -610,7 +622,6 @@ struct proc {
#define P_SIGEVENT 0x200000 /* Process pending signals changed. */
#define P_SINGLE_BOUNDARY 0x400000 /* Threads should suspend at user boundary. */
#define P_HWPMC 0x800000 /* Process is using HWPMCs */
-
#define P_JAILED 0x1000000 /* Process is in jail. */
#define P_INEXEC 0x4000000 /* Process is in execve(). */
#define P_STATCHILD 0x8000000 /* Child process stopped or exited. */
@@ -669,7 +680,6 @@ MALLOC_DECLARE(M_PARGS);
MALLOC_DECLARE(M_PGRP);
MALLOC_DECLARE(M_SESSION);
MALLOC_DECLARE(M_SUBPROC);
-MALLOC_DECLARE(M_ZOMBIE);
#endif
#define FOREACH_PROC_IN_SYSTEM(p) \
@@ -757,6 +767,7 @@ MALLOC_DECLARE(M_ZOMBIE);
} while (0)
#define _PRELE(p) do { \
PROC_LOCK_ASSERT((p), MA_OWNED); \
+ PROC_ASSERT_HELD(p); \
(--(p)->p_lock); \
if (((p)->p_flag & P_WEXIT) && (p)->p_lock == 0) \
wakeup(&(p)->p_lock); \
@@ -814,6 +825,21 @@ struct proc *pfind(pid_t); /* Find process by id. */
struct pgrp *pgfind(pid_t); /* Find process group by id. */
struct proc *zpfind(pid_t); /* Find zombie process by id. */
+/*
+ * pget() flags.
+ */
+#define PGET_HOLD 0x00001 /* Hold the process. */
+#define PGET_CANSEE 0x00002 /* Check against p_cansee(). */
+#define PGET_CANDEBUG 0x00004 /* Check against p_candebug(). */
+#define PGET_ISCURRENT 0x00008 /* Check that the found process is current. */
+#define PGET_NOTWEXIT 0x00010 /* Check that the process is not in P_WEXIT. */
+#define PGET_NOTINEXEC 0x00020 /* Check that the process is not in P_INEXEC. */
+#define PGET_NOTID 0x00040 /* Do not assume tid if pid > PID_MAX. */
+
+#define PGET_WANTREAD (PGET_HOLD | PGET_CANDEBUG | PGET_NOTWEXIT)
+
+int pget(pid_t pid, int flags, struct proc **pp);
+
void ast(struct trapframe *framep);
struct thread *choosethread(void);
int cr_cansignal(struct ucred *cred, struct proc *proc, int signum);
@@ -827,9 +853,11 @@ void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);
void fork_return(struct thread *, struct trapframe *);
int inferior(struct proc *p);
+void kern_yield(int);
void kick_proc0(void);
int leavepgrp(struct proc *p);
int maybe_preempt(struct thread *td);
+void maybe_yield(void);
void mi_switch(int flags, struct thread *newtd);
int p_candebug(struct thread *td, struct proc *p);
int p_cansee(struct thread *td, struct proc *p);
@@ -852,6 +880,7 @@ void sess_hold(struct session *);
void sess_release(struct session *);
int setrunnable(struct thread *);
void setsugid(struct proc *p);
+int should_yield(void);
int sigonstack(size_t sp);
void sleepinit(void);
void stopevent(struct proc *, u_int, u_int);
@@ -863,9 +892,6 @@ void cpu_switch(struct thread *, struct thread *, struct mtx *);
void cpu_throw(struct thread *, struct thread *) __dead2;
void unsleep(struct thread *);
void userret(struct thread *, struct trapframe *);
-struct syscall_args;
-int syscallenter(struct thread *, struct syscall_args *);
-void syscallret(struct thread *, int, struct syscall_args *);
void cpu_exit(struct thread *);
void exit1(struct thread *, int) __dead2;
@@ -908,7 +934,27 @@ int thread_unsuspend_one(struct thread *td);
void thread_unthread(struct thread *td);
void thread_wait(struct proc *p);
struct thread *thread_find(struct proc *p, lwpid_t tid);
-void thr_exit1(void);
+
+#ifndef __rtems__
+static __inline int
+curthread_pflags_set(int flags)
+{
+ struct thread *td;
+ int save;
+
+ td = curthread;
+ save = ~flags | (td->td_pflags & flags);
+ td->td_pflags |= flags;
+ return (save);
+}
+
+static __inline void
+curthread_pflags_restore(int save)
+{
+
+ curthread->td_pflags &= save;
+}
+#endif /* __rtems__ */
#endif /* _KERNEL */
diff --git a/freebsd/sys/sys/queue.h b/freebsd/sys/sys/queue.h
index f0bae8d9..274e636c 100644
--- a/freebsd/sys/sys/queue.h
+++ b/freebsd/sys/sys/queue.h
@@ -99,6 +99,7 @@
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
* _REMOVE + + + +
+ * _SWAP + + + +
*
*/
#ifdef QUEUE_MACRO_DEBUG
@@ -307,18 +308,18 @@ struct { \
TRASHIT(*oldnext); \
} while (0)
-#define STAILQ_REMOVE_HEAD(head, field) do { \
- if ((STAILQ_FIRST((head)) = \
- STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
#define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \
diff --git a/freebsd/sys/sys/refcount.h b/freebsd/sys/sys/refcount.h
index 7cf4d47b..572a64e1 100644
--- a/freebsd/sys/sys/refcount.h
+++ b/freebsd/sys/sys/refcount.h
@@ -29,8 +29,8 @@
* $FreeBSD$
*/
-#ifndef __SYS_REFCOUNT_HH__
-#define __SYS_REFCOUNT_HH__
+#ifndef __SYS_REFCOUNT_H__
+#define __SYS_REFCOUNT_H__
#include <machine/atomic.h>
@@ -73,4 +73,4 @@ refcount_release(volatile u_int *count)
return (old == 1);
}
-#endif /* ! __SYS_REFCOUNT_HH__ */
+#endif /* ! __SYS_REFCOUNT_H__ */
diff --git a/freebsd/sys/sys/rman.h b/freebsd/sys/sys/rman.h
index ba06cc04..b34ef37d 100644
--- a/freebsd/sys/sys/rman.h
+++ b/freebsd/sys/sys/rman.h
@@ -116,7 +116,9 @@ struct rman {
TAILQ_HEAD(rman_head, rman);
int rman_activate_resource(struct resource *r);
+int rman_adjust_resource(struct resource *r, u_long start, u_long end);
int rman_await_resource(struct resource *r, int pri, int timo);
+int rman_first_free_region(struct rman *rm, u_long *start, u_long *end);
bus_space_handle_t rman_get_bushandle(struct resource *);
bus_space_tag_t rman_get_bustag(struct resource *);
u_long rman_get_end(struct resource *);
@@ -130,6 +132,7 @@ int rman_deactivate_resource(struct resource *r);
int rman_fini(struct rman *rm);
int rman_init(struct rman *rm);
int rman_init_from_resource(struct rman *rm, struct resource *r);
+int rman_last_free_region(struct rman *rm, u_long *start, u_long *end);
uint32_t rman_make_alignment_flags(uint32_t size);
int rman_manage_region(struct rman *rm, u_long start, u_long end);
int rman_is_region_manager(struct resource *r, struct rman *rm);
diff --git a/freebsd/sys/sys/sbuf.h b/freebsd/sys/sys/sbuf.h
index ee74ce5b..6f923378 100644
--- a/freebsd/sys/sys/sbuf.h
+++ b/freebsd/sys/sys/sbuf.h
@@ -33,12 +33,16 @@
#include <rtems/bsd/sys/_types.h>
+struct sbuf;
+struct sbuf_drain_data;
+typedef int (sbuf_drain_func)(void *, const char *, int);
+
/*
* Structure definition
*/
struct sbuf {
char *s_buf; /* storage buffer */
- void *s_unused; /* binary compatibility. */
+ struct sbuf_drain *s_drain; /* drain function and data */
int s_size; /* size of storage buffer */
int s_len; /* current length of string */
#define SBUF_FIXEDLEN 0x00000000 /* fixed length buffer (default) */
@@ -69,9 +73,10 @@ int sbuf_printf(struct sbuf *, const char *, ...)
int sbuf_vprintf(struct sbuf *, const char *, __va_list)
__printflike(2, 0);
int sbuf_putc(struct sbuf *, int);
+void sbuf_set_drain(struct sbuf *, sbuf_drain_func *, void *);
int sbuf_trim(struct sbuf *);
int sbuf_overflowed(struct sbuf *);
-void sbuf_finish(struct sbuf *);
+int sbuf_finish(struct sbuf *);
char *sbuf_data(struct sbuf *);
int sbuf_len(struct sbuf *);
int sbuf_done(struct sbuf *);
diff --git a/freebsd/sys/sys/sdt.h b/freebsd/sys/sys/sdt.h
index eeae665c..7d1286b8 100644
--- a/freebsd/sys/sys/sdt.h
+++ b/freebsd/sys/sys/sdt.h
@@ -31,34 +31,68 @@
#ifndef _SYS_SDT_H
#define _SYS_SDT_H
-/* Stub these for the time being. */
-#define DTRACE_PROBE(name)
-#define DTRACE_PROBE1(name, type1, arg1)
-#define DTRACE_PROBE2(name, type1, arg1, type2, arg2)
-#define DTRACE_PROBE3(name, type1, arg1, type2, arg2, type3, arg3)
-#define DTRACE_PROBE4(name, type1, arg1, type2, arg2, type3, arg3, type4, arg4)
-
#ifndef _KERNEL
-/* The promise of things to come. Worlds to explore. People to meet. Things to do. */
-
-#else
+#define _DTRACE_VERSION 1
+
+#define DTRACE_PROBE(prov, name) { \
+ extern void __dtrace_##prov##___##name(void); \
+ __dtrace_##prov##___##name(); \
+}
+
+#define DTRACE_PROBE1(prov, name, arg1) { \
+ extern void __dtrace_##prov##___##name(unsigned long); \
+ __dtrace_##prov##___##name((unsigned long)arg1); \
+}
+
+#define DTRACE_PROBE2(prov, name, arg1, arg2) { \
+ extern void __dtrace_##prov##___##name(unsigned long, \
+ unsigned long); \
+ __dtrace_##prov##___##name((unsigned long)arg1, \
+ (unsigned long)arg2); \
+}
+
+#define DTRACE_PROBE3(prov, name, arg1, arg2, arg3) { \
+ extern void __dtrace_##prov##___##name(unsigned long, \
+ unsigned long, unsigned long); \
+ __dtrace_##prov##___##name((unsigned long)arg1, \
+ (unsigned long)arg2, (unsigned long)arg3); \
+}
+
+#define DTRACE_PROBE4(prov, name, arg1, arg2, arg3, arg4) { \
+ extern void __dtrace_##prov##___##name(unsigned long, \
+ unsigned long, unsigned long, unsigned long); \
+ __dtrace_##prov##___##name((unsigned long)arg1, \
+ (unsigned long)arg2, (unsigned long)arg3, \
+ (unsigned long)arg4); \
+}
+
+#define DTRACE_PROBE5(prov, name, arg1, arg2, arg3, arg4, arg5) { \
+ extern void __dtrace_##prov##___##name(unsigned long, \
+ unsigned long, unsigned long, unsigned long, unsigned long);\
+ __dtrace_##prov##___##name((unsigned long)arg1, \
+ (unsigned long)arg2, (unsigned long)arg3, \
+ (unsigned long)arg4, (unsigned long)arg5); \
+}
+
+#else /* _KERNEL */
#ifndef KDTRACE_HOOKS
#define SDT_PROVIDER_DEFINE(prov)
#define SDT_PROVIDER_DECLARE(prov)
-#define SDT_PROBE_DEFINE(prov, mod, func, name)
+#define SDT_PROBE_DEFINE(prov, mod, func, name, sname)
#define SDT_PROBE_DECLARE(prov, mod, func, name)
#define SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4)
#define SDT_PROBE_ARGTYPE(prov, mod, func, name, num, type)
-#define SDT_PROBE_DEFINE1(prov, mod, func, name, arg0)
-#define SDT_PROBE_DEFINE2(prov, mod, func, name, arg0, arg1)
-#define SDT_PROBE_DEFINE3(prov, mod, func, name, arg0, arg1, arg2)
-#define SDT_PROBE_DEFINE4(prov, mod, func, name, arg0, arg1, arg2, arg3)
-#define SDT_PROBE_DEFINE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4)
+#define SDT_PROBE_DEFINE1(prov, mod, func, name, sname, arg0)
+#define SDT_PROBE_DEFINE2(prov, mod, func, name, sname, arg0, arg1)
+#define SDT_PROBE_DEFINE3(prov, mod, func, name, sname, arg0, arg1, arg2)
+#define SDT_PROBE_DEFINE4(prov, mod, func, name, sname, arg0, arg1, arg2, arg3)
+#define SDT_PROBE_DEFINE5(prov, mod, func, name, sname, arg0, arg1, arg2, arg3, arg4)
+#define SDT_PROBE0(prov, mod, func, name)
#define SDT_PROBE1(prov, mod, func, name, arg0)
#define SDT_PROBE2(prov, mod, func, name, arg0, arg1)
#define SDT_PROBE3(prov, mod, func, name, arg0, arg1, arg2)
@@ -135,10 +169,10 @@ struct sdt_provider {
#define SDT_PROVIDER_DECLARE(prov) \
extern struct sdt_provider sdt_provider_##prov[1]
-#define SDT_PROBE_DEFINE(prov, mod, func, name) \
+#define SDT_PROBE_DEFINE(prov, mod, func, name, sname) \
struct sdt_probe sdt_##prov##_##mod##_##func##_##name[1] = { \
{ sizeof(struct sdt_probe), 0, sdt_provider_##prov, \
- { NULL, NULL }, { NULL, NULL }, #mod, #func, #name, 0, 0 } \
+ { NULL, NULL }, { NULL, NULL }, #mod, #func, #sname, 0, 0 } \
}; \
SYSINIT(sdt_##prov##_##mod##_##func##_##name##_init, SI_SUB_KDTRACE, \
SI_ORDER_SECOND + 1, sdt_probe_register, \
@@ -168,36 +202,38 @@ struct sdt_provider {
SI_SUB_KDTRACE, SI_ORDER_SECOND + 2, sdt_argtype_deregister, \
sdt_##prov##_##mod##_##func##_##name##num )
-#define SDT_PROBE_DEFINE1(prov, mod, func, name, arg0) \
- SDT_PROBE_DEFINE(prov, mod, func, name); \
+#define SDT_PROBE_DEFINE1(prov, mod, func, name, sname, arg0) \
+ SDT_PROBE_DEFINE(prov, mod, func, name, sname); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0)
-#define SDT_PROBE_DEFINE2(prov, mod, func, name, arg0, arg1) \
- SDT_PROBE_DEFINE(prov, mod, func, name); \
+#define SDT_PROBE_DEFINE2(prov, mod, func, name, sname, arg0, arg1) \
+ SDT_PROBE_DEFINE(prov, mod, func, name, sname); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1)
-#define SDT_PROBE_DEFINE3(prov, mod, func, name, arg0, arg1, arg2) \
- SDT_PROBE_DEFINE(prov, mod, func, name); \
+#define SDT_PROBE_DEFINE3(prov, mod, func, name, sname, arg0, arg1, arg2)\
+ SDT_PROBE_DEFINE(prov, mod, func, name, sname); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2)
-#define SDT_PROBE_DEFINE4(prov, mod, func, name, arg0, arg1, arg2, arg3) \
- SDT_PROBE_DEFINE(prov, mod, func, name); \
+#define SDT_PROBE_DEFINE4(prov, mod, func, name, sname, arg0, arg1, arg2, arg3) \
+ SDT_PROBE_DEFINE(prov, mod, func, name, sname); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3)
-#define SDT_PROBE_DEFINE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) \
- SDT_PROBE_DEFINE(prov, mod, func, name); \
+#define SDT_PROBE_DEFINE5(prov, mod, func, name, sname, arg0, arg1, arg2, arg3, arg4) \
+ SDT_PROBE_DEFINE(prov, mod, func, name, sname); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3); \
SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4)
+#define SDT_PROBE0(prov, mod, func, name) \
+ SDT_PROBE(prov, mod, func, name, 0, 0, 0, 0, 0)
#define SDT_PROBE1(prov, mod, func, name, arg0) \
SDT_PROBE(prov, mod, func, name, arg0, 0, 0, 0, 0)
#define SDT_PROBE2(prov, mod, func, name, arg0, arg1) \
@@ -225,6 +261,10 @@ int sdt_argtype_listall(struct sdt_probe *, sdt_argtype_listall_func_t, void *);
int sdt_probe_listall(struct sdt_provider *, sdt_probe_listall_func_t, void *);
int sdt_provider_listall(sdt_provider_listall_func_t,void *);
+void sdt_register_callbacks(sdt_provider_listall_func_t, void *,
+ sdt_provider_listall_func_t, void *, sdt_probe_listall_func_t, void *);
+void sdt_deregister_callbacks(void);
+
#endif /* KDTRACE_HOOKS */
#endif /* _KERNEL */
diff --git a/freebsd/sys/sys/selinfo.h b/freebsd/sys/sys/selinfo.h
index 39e540f7..bfa445c6 100644
--- a/freebsd/sys/sys/selinfo.h
+++ b/freebsd/sys/sys/selinfo.h
@@ -55,6 +55,7 @@ struct selinfo {
#define SEL_WAITING(si) (!TAILQ_EMPTY(&(si)->si_tdlist))
#ifdef _KERNEL
+void seldrain(struct selinfo *sip);
void selrecord(struct thread *selector, struct selinfo *sip);
void selwakeup(struct selinfo *sip);
void selwakeuppri(struct selinfo *sip, int pri);
diff --git a/freebsd/sys/sys/socket.h b/freebsd/sys/sys/socket.h
index 9481e5c4..2f016b27 100644
--- a/freebsd/sys/sys/socket.h
+++ b/freebsd/sys/sys/socket.h
@@ -139,6 +139,17 @@ typedef __uid_t uid_t;
#define SO_LISTENQLEN 0x1012 /* socket's complete queue length */
#define SO_LISTENINCQLEN 0x1013 /* socket's incomplete queue length */
#define SO_SETFIB 0x1014 /* use this FIB to route */
+#define SO_PROTOCOL 0x1016 /* get socket protocol (Linux name) */
+#define SO_PROTOTYPE SO_PROTOCOL /* alias for SO_PROTOCOL (SunOS name) */
+#endif
+
+/*
+ * Space reserved for new socket options added by third-party vendors.
+ * This range applies to all socket option levels. New socket options
+ * in FreeBSD should always use an option value less than SO_VENDOR.
+ */
+#if __BSD_VISIBLE
+#define SO_VENDOR 0x80000000
#endif
/*
@@ -416,7 +427,9 @@ struct sockaddr_storage {
#define NET_RT_FLAGS 2 /* by flags, e.g. RESOLVING */
#define NET_RT_IFLIST 3 /* survey interface list */
#define NET_RT_IFMALIST 4 /* return multicast address list */
-#define NET_RT_MAXID 5
+#define NET_RT_IFLISTL 5 /* Survey interface list, using 'l'en
+ * versions of msghdr structs. */
+#define NET_RT_MAXID 6
#define CTL_NET_RT_NAMES { \
{ 0, 0 }, \
@@ -424,6 +437,7 @@ struct sockaddr_storage {
{ "flags", CTLTYPE_STRUCT }, \
{ "iflist", CTLTYPE_STRUCT }, \
{ "ifmalist", CTLTYPE_STRUCT }, \
+ { "iflistl", CTLTYPE_STRUCT }, \
}
#endif /* __BSD_VISIBLE */
diff --git a/freebsd/sys/sys/sockio.h b/freebsd/sys/sys/sockio.h
index 4c1c4839..89226990 100644
--- a/freebsd/sys/sys/sockio.h
+++ b/freebsd/sys/sys/sockio.h
@@ -110,6 +110,9 @@
#define SIOCSIFVNET _IOWR('i', 90, struct ifreq) /* move IF jail/vnet */
#define SIOCSIFRVNET _IOWR('i', 91, struct ifreq) /* reclaim vnet IF */
+#define SIOCGIFFIB _IOWR('i', 92, struct ifreq) /* get IF fib */
+#define SIOCSIFFIB _IOW('i', 93, struct ifreq) /* set IF fib */
+
#define SIOCSDRVSPEC _IOW('i', 123, struct ifdrv) /* set driver-specific
parameters */
#define SIOCGDRVSPEC _IOWR('i', 123, struct ifdrv) /* get driver-specific
diff --git a/freebsd/sys/sys/sysctl.h b/freebsd/sys/sys/sysctl.h
index 16d4d2db..d4f44e64 100644
--- a/freebsd/sys/sys/sysctl.h
+++ b/freebsd/sys/sys/sysctl.h
@@ -87,6 +87,7 @@ struct ctlname {
#define CTLFLAG_MPSAFE 0x00040000 /* Handler is MP safe */
#define CTLFLAG_VNET 0x00020000 /* Prisons with vnet can fiddle */
#define CTLFLAG_RDTUN (CTLFLAG_RD|CTLFLAG_TUN)
+#define CTLFLAG_DYING 0x00010000 /* oid is being removed */
/*
* Secure level. Note that CTLFLAG_SECURE == CTLFLAG_SECURE1.
@@ -114,6 +115,8 @@ struct ctlname {
#define CTL_AUTO_START 0x100
#ifdef _KERNEL
+#include <sys/linker_set.h>
+
#define SYSCTL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1, int arg2, \
struct sysctl_req *req
@@ -166,7 +169,8 @@ struct sysctl_oid {
const char *oid_name;
int (*oid_handler)(SYSCTL_HANDLER_ARGS);
const char *oid_fmt;
- int oid_refcnt;
+ int16_t oid_refcnt;
+ uint16_t oid_running;
const char *oid_descr;
};
@@ -242,13 +246,13 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
#define SYSCTL_OID(parent, nbr, name, kind, a1, a2, handler, fmt, descr) \
static struct sysctl_oid sysctl__##parent##_##name = { \
&sysctl_##parent##_children, { NULL }, nbr, kind, \
- a1, a2, #name, handler, fmt, 0, __DESCR(descr) }; \
+ a1, a2, #name, handler, fmt, 0, 0, __DESCR(descr) }; \
DATA_SET(sysctl_set, sysctl__##parent##_##name)
#else /* __rtems__ */
#define SYSCTL_OID(parent, nbr, name, kind, a1, a2, handler, fmt, descr) \
static struct sysctl_oid sysctl__##parent##_##name = { \
&_bsd_sysctl_##parent##_children, { NULL }, nbr, kind, \
- a1, a2, #name, handler, fmt, 0, __DESCR(descr) }; \
+ a1, a2, #name, handler, fmt, 0, 0, __DESCR(descr) }; \
DATA_SET(sysctl_set, sysctl__##parent##_##name)
#endif /* __rtems__ */
@@ -516,6 +520,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
#define KERN_PROC_VMMAP 32 /* VM map entries for process */
#define KERN_PROC_FILEDESC 33 /* File descriptors for process */
#define KERN_PROC_GROUPS 34 /* process groups */
+#define KERN_PROC_OSREL 40 /* osreldate for process binary */
/*
* KERN_IPC identifiers
@@ -747,6 +752,9 @@ void sysctl_lock(void);
void sysctl_unlock(void);
int sysctl_wire_old_buffer(struct sysctl_req *req, size_t len);
+struct sbuf;
+struct sbuf *sbuf_new_for_sysctl(struct sbuf *, char *, int,
+ struct sysctl_req *);
#else /* !_KERNEL */
#include <sys/cdefs.h>
diff --git a/freebsd/sys/sys/sysproto.h b/freebsd/sys/sys/sysproto.h
index a3d54238..c94df43d 100644
--- a/freebsd/sys/sys/sysproto.h
+++ b/freebsd/sys/sys/sysproto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: stable/8/sys/kern/syscalls.master 212545 2010-09-13 08:49:08Z kib
+ * created from FreeBSD: stable/8/sys/kern/syscalls.master 229725 2012-01-06 19:32:39Z jhb
*/
#ifndef _SYS_SYSPROTO_H_
@@ -1711,6 +1711,17 @@ struct pselect_args {
char ts_l_[PADL_(const struct timespec *)]; const struct timespec * ts; char ts_r_[PADR_(const struct timespec *)];
char sm_l_[PADL_(const sigset_t *)]; const sigset_t * sm; char sm_r_[PADR_(const sigset_t *)];
};
+struct posix_fallocate_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)];
+ char len_l_[PADL_(off_t)]; off_t len; char len_r_[PADR_(off_t)];
+};
+struct posix_fadvise_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char offset_l_[PADL_(off_t)]; off_t offset; char offset_r_[PADR_(off_t)];
+ char len_l_[PADL_(off_t)]; off_t len; char len_r_[PADR_(off_t)];
+ char advice_l_[PADL_(int)]; int advice; char advice_r_[PADR_(int)];
+};
int nosys(struct thread *, struct nosys_args *);
void sys_exit(struct thread *, struct sys_exit_args *);
int fork(struct thread *, struct fork_args *);
@@ -2072,6 +2083,8 @@ int msgctl(struct thread *, struct msgctl_args *);
int shmctl(struct thread *, struct shmctl_args *);
int lpathconf(struct thread *, struct lpathconf_args *);
int pselect(struct thread *, struct pselect_args *);
+int posix_fallocate(struct thread *, struct posix_fallocate_args *);
+int posix_fadvise(struct thread *, struct posix_fadvise_args *);
#ifdef COMPAT_43
@@ -2747,6 +2760,8 @@ int freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *);
#define SYS_AUE_shmctl AUE_SHMCTL
#define SYS_AUE_lpathconf AUE_LPATHCONF
#define SYS_AUE_pselect AUE_SELECT
+#define SYS_AUE_posix_fallocate AUE_NULL
+#define SYS_AUE_posix_fadvise AUE_NULL
#endif /* __rtems__ */
#undef PAD_
diff --git a/freebsd/sys/sys/systm.h b/freebsd/sys/sys/systm.h
index 4d922392..b689998c 100644
--- a/freebsd/sys/sys/systm.h
+++ b/freebsd/sys/sys/systm.h
@@ -54,6 +54,7 @@ extern int cold; /* nonzero if we are doing a cold boot */
extern int rebooting; /* boot() has been called. */
extern const char *panicstr; /* panic message */
extern char version[]; /* system version */
+extern char compiler_version[]; /* compiler version */
extern char copyright[]; /* system copyright */
extern int kstack_pages; /* number of kernel stack pages */
@@ -125,6 +126,18 @@ enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN };
((uintptr_t)&(var) & (sizeof(void *) - 1)) == 0, msg)
/*
+ * If we have already panic'd and this is the thread that called
+ * panic(), then don't block on any mutexes but silently succeed.
+ * Otherwise, the kernel will deadlock since the scheduler isn't
+ * going to run the thread that holds any lock we need.
+ */
+#ifndef __rtems__
+#define SCHEDULER_STOPPED() __predict_false(curthread->td_stopsched)
+#else /* __rtems__ */
+#define SCHEDULER_STOPPED() 0
+#endif /* __rtems__ */
+
+/*
* XXX the hints declarations are even more misplaced than most declarations
* in this file, since they are needed in one file (per arch) and only used
* in two files.
@@ -166,7 +179,7 @@ int nullop(void);
int eopnotsupp(void);
int ureadc(int, struct uio *);
void hashdestroy(void *, struct malloc_type *, u_long);
-void *hashinit(int count, struct malloc_type *type, u_long *hashmark);
+void *hashinit(int count, struct malloc_type *type, u_long *hashmask);
void *hashinit_flags(int count, struct malloc_type *type,
u_long *hashmask, int flags);
#define HASH_NOWAIT 0x00000001
@@ -233,8 +246,12 @@ int copyinstr(const void * __restrict udaddr, void * __restrict kaddr,
__nonnull(1) __nonnull(2);
int copyin(const void * __restrict udaddr, void * __restrict kaddr,
size_t len) __nonnull(1) __nonnull(2);
+int copyin_nofault(const void * __restrict udaddr, void * __restrict kaddr,
+ size_t len) __nonnull(1) __nonnull(2);
int copyout(const void * __restrict kaddr, void * __restrict udaddr,
size_t len) __nonnull(1) __nonnull(2);
+int copyout_nofault(const void * __restrict kaddr, void * __restrict udaddr,
+ size_t len) __nonnull(1) __nonnull(2);
#else /* __rtems__ */
static inline int __nonnull(1) __nonnull(2)
copyinstr(const void * __restrict udaddr, void * __restrict kaddr,
@@ -259,6 +276,13 @@ copyin(const void * __restrict udaddr, void * __restrict kaddr,
}
static inline int __nonnull(1) __nonnull(2)
+copyin_nofault(const void * __restrict udaddr, void * __restrict kaddr,
+ size_t len)
+{
+ return copyin(udaddr, kaddr, len);
+}
+
+static inline int __nonnull(1) __nonnull(2)
copyout(const void * __restrict kaddr, void * __restrict udaddr,
size_t len)
{
@@ -266,9 +290,26 @@ copyout(const void * __restrict kaddr, void * __restrict udaddr,
return (0);
}
+
+static inline int __nonnull(1) __nonnull(2)
+copyout_nofault(const void * __restrict kaddr, void * __restrict udaddr,
+ size_t len)
+{
+ return copyout(kaddr, udaddr, len);
+}
#endif /* __rtems__ */
+#ifndef __rtems__
int fubyte(const void *base);
+#else /* __rtems__ */
+static inline int
+fubyte(const void *base)
+{
+ const unsigned char *byte_base = base;
+
+ return byte_base[0];
+}
+#endif /* __rtems__ */
long fuword(const void *base);
int fuword16(void *base);
int32_t fuword32(const void *base);
@@ -426,48 +467,13 @@ void delete_unrhdr(struct unrhdr *uh);
void clean_unrhdr(struct unrhdr *uh);
void clean_unrhdrl(struct unrhdr *uh);
int alloc_unr(struct unrhdr *uh);
+int alloc_unr_specific(struct unrhdr *uh, u_int item);
int alloc_unrl(struct unrhdr *uh);
void free_unr(struct unrhdr *uh, u_int item);
/*
- * This is about as magic as it gets. fortune(1) has got similar code
- * for reversing bits in a word. Who thinks up this stuff??
- *
- * Yes, it does appear to be consistently faster than:
- * while (i = ffs(m)) {
- * m >>= i;
- * bits++;
- * }
- * and
- * while (lsb = (m & -m)) { // This is magic too
- * m &= ~lsb; // or: m ^= lsb
- * bits++;
- * }
- * Both of these latter forms do some very strange things on gcc-3.1 with
- * -mcpu=pentiumpro and/or -march=pentiumpro and/or -O or -O2.
- * There is probably an SSE or MMX popcnt instruction.
- *
- * I wonder if this should be in libkern?
- *
- * XXX Stop the presses! Another one:
- * static __inline u_int32_t
- * popcnt1(u_int32_t v)
- * {
- * v -= ((v >> 1) & 0x55555555);
- * v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
- * v = (v + (v >> 4)) & 0x0F0F0F0F;
- * return (v * 0x01010101) >> 24;
- * }
- * The downside is that it has a multiply. With a pentium3 with
- * -mcpu=pentiumpro and -march=pentiumpro then gcc-3.1 will use
- * an imull, and in that case it is faster. In most other cases
- * it appears slightly slower.
- *
- * Another variant (also from fortune):
- * #define BITCOUNT(x) (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255)
- * #define BX_(x) ((x) - (((x)>>1)&0x77777777) \
- * - (((x)>>2)&0x33333333) \
- * - (((x)>>3)&0x11111111))
+ * Population count algorithm using SWAR approach
+ * - "SIMD Within A Register".
*/
static __inline uint32_t
bitcount32(uint32_t x)
@@ -481,4 +487,15 @@ bitcount32(uint32_t x)
return (x);
}
+static __inline uint16_t
+bitcount16(uint32_t x)
+{
+
+ x = (x & 0x5555) + ((x & 0xaaaa) >> 1);
+ x = (x & 0x3333) + ((x & 0xcccc) >> 2);
+ x = (x + (x >> 4)) & 0x0f0f;
+ x = (x + (x >> 8)) & 0x00ff;
+ return (x);
+}
+
#endif /* !_SYS_SYSTM_H_ */
diff --git a/freebsd/sys/sys/taskqueue.h b/freebsd/sys/sys/taskqueue.h
index bf2e4ee3..6ac22e06 100644
--- a/freebsd/sys/sys/taskqueue.h
+++ b/freebsd/sys/sys/taskqueue.h
@@ -61,6 +61,12 @@ void taskqueue_block(struct taskqueue *queue);
void taskqueue_unblock(struct taskqueue *queue);
int taskqueue_member(struct taskqueue *queue, struct thread *td);
+#define TASK_INITIALIZER(priority, func, context) \
+ { .ta_pending = 0, \
+ .ta_priority = (priority), \
+ .ta_func = (func), \
+ .ta_context = (context) }
+
/*
* Functions for dedicated thread taskqueues
*/
@@ -94,7 +100,7 @@ static void \
taskqueue_define_##name(void *arg) \
{ \
taskqueue_##name = \
- taskqueue_create(#name, M_NOWAIT, (enqueue), (context)); \
+ taskqueue_create(#name, M_WAITOK, (enqueue), (context)); \
init; \
} \
\
@@ -118,7 +124,7 @@ static void \
taskqueue_define_##name(void *arg) \
{ \
taskqueue_##name = \
- taskqueue_create_fast(#name, M_NOWAIT, (enqueue), \
+ taskqueue_create_fast(#name, M_WAITOK, (enqueue), \
(context)); \
init; \
} \
diff --git a/freebsd/sys/sys/un.h b/freebsd/sys/sys/un.h
index a858abf4..9db3c6d9 100644
--- a/freebsd/sys/sys/un.h
+++ b/freebsd/sys/sys/un.h
@@ -53,9 +53,12 @@ struct sockaddr_un {
#if __BSD_VISIBLE
/* Socket options. */
-#define LOCAL_PEERCRED 0x001 /* retrieve peer credentials */
-#define LOCAL_CREDS 0x002 /* pass credentials to receiver */
-#define LOCAL_CONNWAIT 0x004 /* connects block until accepted */
+#define LOCAL_PEERCRED 1 /* retrieve peer credentials */
+#define LOCAL_CREDS 2 /* pass credentials to receiver */
+#define LOCAL_CONNWAIT 4 /* connects block until accepted */
+
+/* Start of reserved space for third-party socket options. */
+#define LOCAL_VENDOR SO_VENDOR
#ifndef _KERNEL
diff --git a/freebsd/sys/sys/user.h b/freebsd/sys/sys/user.h
index 7ca16ad0..01a8e73a 100644
--- a/freebsd/sys/sys/user.h
+++ b/freebsd/sys/sys/user.h
@@ -151,7 +151,7 @@ struct kinfo_proc {
u_int ki_estcpu; /* Time averaged value of ki_cpticks */
u_int ki_slptime; /* Time since last blocked */
u_int ki_swtime; /* Time swapped in or out */
- int ki_spareint1; /* unused (just here for alignment) */
+ u_int ki_cow; /* number of copy-on-write faults */
u_int64_t ki_runtime; /* Real time in microsec */
struct timeval ki_start; /* starting time */
struct timeval ki_childtime; /* time used by process children */
@@ -338,6 +338,7 @@ struct kinfo_file {
#define KVME_FLAG_COW 0x00000001
#define KVME_FLAG_NEEDS_COPY 0x00000002
#define KVME_FLAG_NOCOREDUMP 0x00000004
+#define KVME_FLAG_SUPER 0x00000008
#if defined(__amd64__)
#define KINFO_OVMENTRY_SIZE 1168
diff --git a/freebsd/sys/v850/include/machine/legacyvar.h b/freebsd/sys/v850/include/machine/legacyvar.h
index 0b0fa433..14dd9e03 100644
--- a/freebsd/sys/v850/include/machine/legacyvar.h
+++ b/freebsd/sys/v850/include/machine/legacyvar.h
@@ -31,7 +31,9 @@
enum legacy_device_ivars {
LEGACY_IVAR_PCIDOMAIN,
- LEGACY_IVAR_PCIBUS
+ LEGACY_IVAR_PCIBUS,
+ LEGACY_IVAR_PCISLOT,
+ LEGACY_IVAR_PCIFUNC
};
#define LEGACY_ACCESSOR(var, ivar, type) \
@@ -39,6 +41,8 @@ enum legacy_device_ivars {
LEGACY_ACCESSOR(pcidomain, PCIDOMAIN, uint32_t)
LEGACY_ACCESSOR(pcibus, PCIBUS, uint32_t)
+LEGACY_ACCESSOR(pcislot, PCISLOT, int)
+LEGACY_ACCESSOR(pcifunc, PCIFUNC, int)
#undef LEGACY_ACCESSOR
@@ -53,5 +57,7 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
+int legacy_pcib_map_msi(device_t pcib, device_t dev, int irq,
+ uint64_t *addr, uint32_t *data);
#endif /* !_MACHINE_LEGACYVAR_H_ */
diff --git a/freebsd/sys/v850/pci/pci_bus.c b/freebsd/sys/v850/pci/pci_bus.c
index 6627db98..75b169eb 100644
--- a/freebsd/sys/v850/pci/pci_bus.c
+++ b/freebsd/sys/v850/pci/pci_bus.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
@@ -112,14 +113,28 @@ legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
}
-static int
+int
legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
- device_t bus;
+ device_t bus, hostb;
+ int error, func, slot;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ slot = legacy_get_pcislot(pcib);
+ func = legacy_get_pcifunc(pcib);
+ if (slot == -1 || func == -1)
+ return (0);
+ hostb = pci_find_bsf(0, slot, func);
+ KASSERT(hostb != NULL, ("%s: missing hostb for 0:%d:%d", __func__,
+ slot, func));
+ pci_ht_map_msi(hostb, *addr);
+ return (0);
+
}
static const char *
@@ -444,6 +459,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent)
"pcib", busnum);
device_set_desc(child, s);
legacy_set_pcibus(child, busnum);
+ legacy_set_pcislot(child, slot);
+ legacy_set_pcifunc(child, func);
found = 1;
if (id == 0x12258086)
@@ -577,10 +594,10 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -598,7 +615,7 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t hostb_devclass;
@@ -673,7 +690,6 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
@@ -694,7 +710,7 @@ static device_method_t pcibios_pcib_pci_methods[] = {
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/freebsd/sys/v850/v850/legacy.c b/freebsd/sys/v850/v850/legacy.c
index 2547990c..70bdcebc 100644
--- a/freebsd/sys/v850/v850/legacy.c
+++ b/freebsd/sys/v850/v850/legacy.c
@@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
struct legacy_device {
- int lg_pcibus;
+ int lg_pcibus;
+ int lg_pcislot;
+ int lg_pcifunc;
};
#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev))
@@ -89,6 +91,7 @@ static device_method_t legacy_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
@@ -184,6 +187,8 @@ legacy_add_child(device_t bus, u_int order, const char *name, int unit)
if (atdev == NULL)
return(NULL);
atdev->lg_pcibus = -1;
+ atdev->lg_pcislot = -1;
+ atdev->lg_pcifunc = -1;
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL)
@@ -207,6 +212,12 @@ legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case LEGACY_IVAR_PCIBUS:
*result = atdev->lg_pcibus;
break;
+ case LEGACY_IVAR_PCISLOT:
+ *result = atdev->lg_pcislot;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ *result = atdev->lg_pcifunc;
+ break;
default:
return ENOENT;
}
@@ -225,6 +236,12 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
case LEGACY_IVAR_PCIBUS:
atdev->lg_pcibus = value;
break;
+ case LEGACY_IVAR_PCISLOT:
+ atdev->lg_pcislot = value;
+ break;
+ case LEGACY_IVAR_PCIFUNC:
+ atdev->lg_pcifunc = value;
+ break;
default:
return ENOENT;
}
@@ -260,19 +277,17 @@ static device_method_t cpu_methods[] = {
/* Bus interface */
DEVMETHOD(bus_add_child, cpu_add_child),
DEVMETHOD(bus_read_ivar, cpu_read_ivar),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t cpu_driver = {
@@ -294,12 +309,11 @@ cpu_identify(driver_t *driver, device_t parent)
* so that these devices are attached after the Host-PCI
* bridges (which are added at order 100).
*/
- for (i = 0; i <= mp_maxid; i++)
- if (!CPU_ABSENT(i)) {
- child = BUS_ADD_CHILD(parent, 150, "cpu", i);
- if (child == NULL)
- panic("legacy_attach cpu");
- }
+ CPU_FOREACH(i) {
+ child = BUS_ADD_CHILD(parent, 150, "cpu", i);
+ if (child == NULL)
+ panic("legacy_attach cpu");
+ }
}
static device_t
diff --git a/freebsd/sys/vm/uma.h b/freebsd/sys/vm/uma.h
index 62a0ca79..138d087f 100644
--- a/freebsd/sys/vm/uma.h
+++ b/freebsd/sys/vm/uma.h
@@ -165,9 +165,9 @@ typedef void (*uma_fini)(void *mem, int size);
* A pointer to a structure which is intended to be opaque to users of
* the interface. The value may be null if the wait flag is not set.
*/
-uma_zone_t uma_zcreate(char *name, size_t size, uma_ctor ctor, uma_dtor dtor,
- uma_init uminit, uma_fini fini, int align,
- u_int32_t flags);
+uma_zone_t uma_zcreate(const char *name, size_t size, uma_ctor ctor,
+ uma_dtor dtor, uma_init uminit, uma_fini fini,
+ int align, u_int32_t flags);
/*
* Create a secondary uma zone
diff --git a/freebsd/sys/vm/uma_core.c b/freebsd/sys/vm/uma_core.c
index 733aa8be..c30d516b 100644
--- a/freebsd/sys/vm/uma_core.c
+++ b/freebsd/sys/vm/uma_core.c
@@ -162,7 +162,7 @@ static struct callout uma_callout;
* a special allocation function just for zones.
*/
struct uma_zctor_args {
- char *name;
+ const char *name;
size_t size;
uma_ctor ctor;
uma_dtor dtor;
@@ -216,6 +216,7 @@ enum zfreeskip { SKIP_NONE, SKIP_DTOR, SKIP_FINI };
#define ZFREE_STATFREE 0x00000002 /* Update zone free statistic. */
/* Prototypes.. */
+
#ifndef __rtems__
static void *obj_alloc(uma_zone_t, int, u_int8_t *, int);
#endif /* __rtems__ */
@@ -286,10 +287,7 @@ static void
bucket_enable(void)
{
#ifndef __rtems__
- if (cnt.v_free_count < cnt.v_free_min)
- bucketdisable = 1;
- else
- bucketdisable = 0;
+ bucketdisable = vm_page_count_min();
#endif /* __rtems__ */
}
@@ -642,9 +640,7 @@ cache_drain(uma_zone_t zone)
* it is used elsewhere. Should the tear-down path be made special
* there in some form?
*/
- for (cpu = 0; cpu <= mp_maxid; cpu++) {
- if (CPU_ABSENT(cpu))
- continue;
+ CPU_FOREACH(cpu) {
cache = &zone->uz_cpu[cpu];
bucket_drain(zone, cache->uc_allocbucket);
bucket_drain(zone, cache->uc_freebucket);
@@ -1022,16 +1018,16 @@ startup_alloc(uma_zone_t zone, int bytes, u_int8_t *pflag, int wait)
static void *
page_alloc(uma_zone_t zone, int bytes, u_int8_t *pflag, int wait)
{
- void *p; /* Returned page */
+ void *p; /* Returned page */
- *pflag = UMA_SLAB_KMEM;
+ *pflag = UMA_SLAB_KMEM;
#ifndef __rtems__
- p = (void *) kmem_malloc(kmem_map, bytes, wait);
+ p = (void *) kmem_malloc(kmem_map, bytes, wait);
#else /* __rtems__ */
- p = rtems_bsd_chunk_alloc(&rtems_bsd_uma_chunks, bytes);
+ p = rtems_bsd_chunk_alloc(&rtems_bsd_uma_chunks, bytes);
#endif /* __rtems__ */
- return (p);
+ return (p);
}
#ifndef __rtems__
@@ -1429,7 +1425,7 @@ keg_ctor(void *mem, int size, void *udata, int flags)
hash_alloc(&keg->uk_hash);
#ifdef UMA_DEBUG
- printf("UMA: %s(%p) size %d(%d) flags %d ipers %d ppera %d out %d free %d\n",
+ printf("UMA: %s(%p) size %d(%d) flags %#x ipers %d ppera %d out %d free %d\n",
zone->uz_name, zone, keg->uk_size, keg->uk_rsize, keg->uk_flags,
keg->uk_ipers, keg->uk_ppera,
(keg->uk_ipers * keg->uk_pages) - keg->uk_free, keg->uk_free);
@@ -1902,7 +1898,7 @@ uma_set_align(int align)
/* See uma.h */
uma_zone_t
-uma_zcreate(char *name, size_t size, uma_ctor ctor, uma_dtor dtor,
+uma_zcreate(const char *name, size_t size, uma_ctor ctor, uma_dtor dtor,
uma_init uminit, uma_fini fini, int align, u_int32_t flags)
{
@@ -3211,7 +3207,7 @@ uma_print_keg(uma_keg_t keg)
{
uma_slab_t slab;
- printf("keg: %s(%p) size %d(%d) flags %d ipers %d ppera %d "
+ printf("keg: %s(%p) size %d(%d) flags %#x ipers %d ppera %d "
"out %d free %d limit %d\n",
keg->uk_name, keg, keg->uk_size, keg->uk_rsize, keg->uk_flags,
keg->uk_ipers, keg->uk_ppera,
@@ -3235,13 +3231,11 @@ uma_print_zone(uma_zone_t zone)
uma_klink_t kl;
int i;
- printf("zone: %s(%p) size %d flags %d\n",
+ printf("zone: %s(%p) size %d flags %#x\n",
zone->uz_name, zone, zone->uz_size, zone->uz_flags);
LIST_FOREACH(kl, &zone->uz_kegs, kl_link)
uma_print_keg(kl->kl_keg);
- for (i = 0; i <= mp_maxid; i++) {
- if (CPU_ABSENT(i))
- continue;
+ CPU_FOREACH(i) {
cache = &zone->uz_cpu[i];
printf("CPU %d Cache:\n", i);
cache_print(cache);
@@ -3271,9 +3265,7 @@ uma_zone_sumstat(uma_zone_t z, int *cachefreep, u_int64_t *allocsp,
allocs = frees = 0;
cachefree = 0;
- for (cpu = 0; cpu <= mp_maxid; cpu++) {
- if (CPU_ABSENT(cpu))
- continue;
+ CPU_FOREACH(cpu) {
cache = &z->uz_cpu[cpu];
if (cache->uc_allocbucket != NULL)
cachefree += cache->uc_allocbucket->ub_cnt;
@@ -3474,6 +3466,8 @@ DB_SHOW_COMMAND(uma, db_show_uma)
(uintmax_t)kz->uk_size,
(intmax_t)(allocs - frees), cachefree,
(uintmax_t)allocs);
+ if (db_pager_quit)
+ return;
}
}
}
diff --git a/freebsd/sys/vm/uma_int.h b/freebsd/sys/vm/uma_int.h
index 62cf0452..b92681c1 100644
--- a/freebsd/sys/vm/uma_int.h
+++ b/freebsd/sys/vm/uma_int.h
@@ -193,7 +193,7 @@ struct uma_keg {
struct mtx uk_lock; /* Lock for the keg */
struct uma_hash uk_hash;
- char *uk_name; /* Name of creating zone. */
+ const char *uk_name; /* Name of creating zone. */
LIST_HEAD(,uma_zone) uk_zones; /* Keg's zones */
LIST_HEAD(,uma_slab) uk_part_slab; /* partially allocated slabs */
LIST_HEAD(,uma_slab) uk_free_slab; /* empty slab list */
@@ -296,7 +296,7 @@ typedef struct uma_klink *uma_klink_t;
*
*/
struct uma_zone {
- char *uz_name; /* Text name of the zone */
+ const char *uz_name; /* Text name of the zone */
struct mtx *uz_lock; /* Lock for the zone (keg's lock) */
LIST_ENTRY(uma_zone) uz_link; /* List of all zones in keg */
diff --git a/freebsd/sys/vm/vm_extern.h b/freebsd/sys/vm/vm_extern.h
index 76f53802..7782f2a0 100644
--- a/freebsd/sys/vm/vm_extern.h
+++ b/freebsd/sys/vm/vm_extern.h
@@ -61,11 +61,14 @@ int useracc(void *, int, int);
int vm_fault(vm_map_t, vm_offset_t, vm_prot_t, int);
void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t,
vm_ooffset_t *);
+int vm_fault_disable_pagefaults(void);
+void vm_fault_enable_pagefaults(int save);
void vm_fault_unwire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t);
int vm_fault_wire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t, boolean_t);
int vm_forkproc(struct thread *, struct proc *, struct thread *, struct vmspace *, int);
void vm_waitproc(struct proc *);
int vm_mmap(vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, objtype_t, void *, vm_ooffset_t);
+int vm_mmap_to_errno(int rv);
void vm_set_page_size(void);
void vm_sync_icache(vm_map_t, vm_offset_t, vm_size_t);
struct vmspace *vmspace_alloc(vm_offset_t, vm_offset_t);
diff --git a/freebsd/usr.bin/netstat/if.c b/freebsd/usr.bin/netstat/if.c
index aaf1fd88..73f74967 100644
--- a/freebsd/usr.bin/netstat/if.c
+++ b/freebsd/usr.bin/netstat/if.c
@@ -68,6 +68,9 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <libutil.h>
+#ifdef INET6
+#include <netdb.h>
+#endif
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
@@ -84,7 +87,7 @@ static void sidewaysintpr(int, u_long);
static void catchalarm(int);
#ifdef INET6
-static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
+static char addr_buf[NI_MAXHOST]; /* for getnameinfo() */
#endif
/*
@@ -196,7 +199,6 @@ intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
} ifaddr;
u_long ifaddraddr;
u_long ifaddrfound;
- u_long ifnetfound;
u_long opackets;
u_long ipackets;
u_long obytes;
@@ -260,7 +262,6 @@ intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
link_layer = 0;
if (ifaddraddr == 0) {
- ifnetfound = ifnetaddr;
if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
return;
strlcpy(name, ifnet.if_xname, sizeof(name));
@@ -354,13 +355,14 @@ intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
#ifdef INET6
case AF_INET6:
sockin6 = (struct sockaddr_in6 *)sa;
+ in6_fillscopeid(&ifaddr.in6.ia_addr);
printf("%-13.13s ",
netname6(&ifaddr.in6.ia_addr,
&ifaddr.in6.ia_prefixmask.sin6_addr));
- printf("%-17.17s ",
- inet_ntop(AF_INET6,
- &sockin6->sin6_addr,
- ntop_buf, sizeof(ntop_buf)));
+ in6_fillscopeid(sockin6);
+ getnameinfo(sa, sa->sa_len, addr_buf,
+ sizeof(addr_buf), 0, 0, NI_NUMERICHOST);
+ printf("%-17.17s ", addr_buf);
network_layer = 1;
break;
@@ -409,7 +411,7 @@ intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
n = cp - sa->sa_data + 1;
cp = sa->sa_data;
hexprint:
- while (--n >= 0)
+ while ((--n >= 0) && (m < 30))
m += printf("%02x%c", *cp++ & 0xff,
n > 0 ? ':' : ' ');
m = 32 - m;
@@ -486,13 +488,13 @@ intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
break;
#ifdef INET6
case AF_INET6:
+ in6_fillscopeid(&msa.in6);
+ getnameinfo(&msa.sa, msa.sa.sa_len,
+ addr_buf, sizeof(addr_buf), 0, 0,
+ NI_NUMERICHOST);
printf("%*s %-19.19s(refs: %d)\n",
Wflag ? 27 : 25, "",
- inet_ntop(AF_INET6,
- &msa.in6.sin6_addr,
- ntop_buf,
- sizeof(ntop_buf)),
- ifma.ifma_refcount);
+ addr_buf, ifma.ifma_refcount);
break;
#endif /* INET6 */
case AF_LINK:
diff --git a/freebsd/usr.bin/netstat/inet.c b/freebsd/usr.bin/netstat/inet.c
index 4915a4dd..00b9e27a 100644
--- a/freebsd/usr.bin/netstat/inet.c
+++ b/freebsd/usr.bin/netstat/inet.c
@@ -403,35 +403,44 @@ protopr(u_long off, const char *name, int af1, int proto)
"Current listen queue sizes (qlen/incqlen/maxqlen)");
putchar('\n');
if (Aflag)
- printf("%-8.8s ", "Tcpcb");
+ printf("%-*s ", 2 * (int)sizeof(void *), "Tcpcb");
if (Lflag)
- printf("%-5.5s %-14.14s %-22.22s\n",
+ printf((Aflag && !Wflag) ?
+ "%-5.5s %-14.14s %-18.18s" :
+ "%-5.5s %-14.14s %-22.22s",
"Proto", "Listen", "Local Address");
+ else if (Tflag)
+ printf((Aflag && !Wflag) ?
+ "%-5.5s %-6.6s %-6.6s %-6.6s %-18.18s %s" :
+ "%-5.5s %-6.6s %-6.6s %-6.6s %-22.22s %s",
+ "Proto", "Rexmit", "OOORcv", "0-win",
+ "Local Address", "Foreign Address");
else {
printf((Aflag && !Wflag) ?
- "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s" :
- "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s",
+ "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s" :
+ "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s",
"Proto", "Recv-Q", "Send-Q",
"Local Address", "Foreign Address");
- if (xflag)
- printf("%-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %s\n",
- "R-MBUF", "S-MBUF", "R-CLUS",
- "S-CLUS", "R-HIWA", "S-HIWA",
- "R-LOWA", "S-LOWA", "R-BCNT",
- "S-BCNT", "R-BMAX", "S-BMAX",
- "(state)");
- else
- printf("(state)\n");
+ if (!xflag)
+ printf(" (state)");
}
+ if (xflag) {
+ printf(" %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s",
+ "R-MBUF", "S-MBUF", "R-CLUS",
+ "S-CLUS", "R-HIWA", "S-HIWA",
+ "R-LOWA", "S-LOWA", "R-BCNT",
+ "S-BCNT", "R-BMAX", "S-BMAX");
+ }
+ putchar('\n');
protopr_initialized = 1;
}
if (Lflag && so->so_qlimit == 0)
continue;
if (Aflag) {
if (istcp)
- printf("%8lx ", (u_long)inp->inp_ppcb);
+ printf("%*lx ", 2 * (int)sizeof(void *), (u_long)inp->inp_ppcb);
else
- printf("%8lx ", (u_long)so->so_pcb);
+ printf("%*lx ", 2 * (int)sizeof(void *), (u_long)so->so_pcb);
}
#ifdef INET6
if ((inp->inp_vflag & INP_IPV6) != 0)
@@ -448,6 +457,12 @@ protopr(u_long off, const char *name, int af1, int proto)
snprintf(buf1, 15, "%d/%d/%d", so->so_qlen,
so->so_incqlen, so->so_qlimit);
printf("%-14.14s ", buf1);
+ } else if (Tflag) {
+ if (istcp)
+ printf("%6ju %6ju %6u ",
+ (uintmax_t)tp->t_sndrexmitpack,
+ (uintmax_t)tp->t_rcvoopack,
+ tp->t_sndzerowin);
} else {
printf("%6u %6u ", so->so_rcv.sb_cc, so->so_snd.sb_cc);
}
@@ -506,25 +521,15 @@ protopr(u_long off, const char *name, int af1, int proto)
#endif /* INET6 */
}
if (xflag) {
- if (Lflag)
- printf("%21s %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ",
- " ",
- so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt,
- so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt,
- so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat,
- so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
- so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
- so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax);
- else
- printf("%6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ",
- so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt,
- so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt,
- so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat,
- so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
- so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
- so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax);
+ printf("%6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u",
+ so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt,
+ so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt,
+ so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat,
+ so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
+ so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
+ so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax);
}
- if (istcp && !Lflag) {
+ if (istcp && !Lflag && !xflag && !Tflag) {
if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
printf("%d", tp->t_state);
else {
@@ -674,6 +679,9 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n");
p(tcps_sc_recvcookie, "\t%lu cookie%s received\n");
+ p(tcps_hc_added, "\t%lu hostcache entrie%s added\n");
+ p1a(tcps_hc_bucketoverflow, "\t\t%lu bucket overflow\n");
+
p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n");
p(tcps_sack_rexmits,
"\t%lu segment rexmit%s in SACK recovery episodes\n");
@@ -1043,7 +1051,7 @@ icmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
* Dump IGMP statistics structure (pre 8.x kernel).
*/
static void
-igmp_stats_live_old(u_long off, const char *name)
+igmp_stats_live_old(const char *name)
{
struct oigmpstat oigmpstat, zerostat;
size_t len = sizeof(oigmpstat);
@@ -1103,7 +1111,7 @@ igmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
return;
}
if (len < sizeof(igmpstat)) {
- igmp_stats_live_old(off, name);
+ igmp_stats_live_old(name);
return;
}
}
diff --git a/freebsd/usr.bin/netstat/main.c b/freebsd/usr.bin/netstat/main.c
index acb256d5..e4e7dce1 100644
--- a/freebsd/usr.bin/netstat/main.c
+++ b/freebsd/usr.bin/netstat/main.c
@@ -348,10 +348,14 @@ int noutputs = 0; /* how much outputs before we exit */
int numeric_addr; /* show addresses numerically */
int numeric_port; /* show ports numerically */
static int pflag; /* show given protocol */
+#ifndef __rtems__
+int Qflag; /* show netisr information */
+#endif /* __rtems__ */
int rflag; /* show routing tables (or routing stats) */
int sflag; /* show protocol statistics */
int tflag; /* show i/f watchdog timers */
int Wflag; /* wide display */
+int Tflag; /* TCP Information */
int xflag; /* extra information, includes all socket buffer info */
int zflag; /* zero stats */
@@ -431,7 +435,8 @@ main(int argc, char *argv[])
af = AF_UNSPEC;
- while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz")) != -1)
+ while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:Qq:rSTstuWw:xz"))
+ != -1)
switch(ch) {
case 'A':
Aflag = 1;
@@ -517,6 +522,11 @@ main(int argc, char *argv[])
}
pflag = 1;
break;
+#ifndef __rtems__
+ case 'Q':
+ Qflag = 1;
+ break;
+#endif /* __rtems__ */
case 'q':
noutputs = atoi(optarg);
if (noutputs != 0)
@@ -545,6 +555,9 @@ main(int argc, char *argv[])
interval = atoi(optarg);
iflag = 1;
break;
+ case 'T':
+ Tflag = 1;
+ break;
case 'x':
xflag = 1;
break;
@@ -584,6 +597,9 @@ main(int argc, char *argv[])
if (!live)
setgid(getgid());
+ if (xflag && Tflag)
+ errx(1, "-x and -T are incompatible, pick one.");
+
if (Bflag) {
if (!live)
usage();
@@ -598,6 +614,16 @@ main(int argc, char *argv[])
mbpr(NULL, 0);
exit(0);
}
+#ifndef __rtems__
+ if (Qflag) {
+ if (!live) {
+ if (kread(0, NULL, 0) == 0)
+ netisr_stats(kvmd);
+ } else
+ netisr_stats(NULL);
+ exit(0);
+ }
+#endif /* __rtems__ */
#if 0
/*
* Keep file descriptors open to avoid overhead
@@ -864,8 +890,8 @@ name2protox(const char *name)
static void
usage(void)
{
- (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
-"usage: netstat [-AaLnSWx] [-f protocol_family | -p protocol]\n"
+ (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+"usage: netstat [-AaLnSTWx] [-f protocol_family | -p protocol]\n"
" [-M core] [-N system]",
" netstat -i | -I interface [-abdhntW] [-f address_family]\n"
" [-M core] [-N system]",
@@ -879,6 +905,7 @@ usage(void)
" netstat -r [-AanW] [-f address_family] [-M core] [-N system]",
" netstat -rs [-s] [-M core] [-N system]",
" netstat -g [-W] [-f address_family] [-M core] [-N system]",
-" netstat -gs [-s] [-f address_family] [-M core] [-N system]");
+" netstat -gs [-s] [-f address_family] [-M core] [-N system]",
+" netstat -Q");
exit(1);
}
diff --git a/freebsd/usr.bin/netstat/netstat.h b/freebsd/usr.bin/netstat/netstat.h
index 9b2db595..69465cf8 100644
--- a/freebsd/usr.bin/netstat/netstat.h
+++ b/freebsd/usr.bin/netstat/netstat.h
@@ -57,6 +57,7 @@ extern int numeric_port; /* show ports numerically */
extern int rflag; /* show routing tables (or routing stats) */
extern int sflag; /* show protocol statistics */
extern int tflag; /* show i/f watchdog timers */
+extern int Tflag; /* show TCP control block info */
extern int Wflag; /* wide display */
extern int xflag; /* extended display, includes all socket buffer info */
extern int zflag; /* zero stats */
@@ -79,6 +80,9 @@ const char *plural(uintmax_t);
const char *plurales(uintmax_t);
const char *pluralies(uintmax_t);
+struct sockaddr;
+struct socket;
+struct xsocket;
int sotoxsocket(struct socket *, struct xsocket *);
void protopr(u_long, const char *, int, int);
void tcp_stats(u_long, const char *, int, int);
@@ -113,6 +117,7 @@ void mrt6_stats(u_long);
struct sockaddr_in6;
struct in6_addr;
+void in6_fillscopeid(struct sockaddr_in6 *);
char *routename6(struct sockaddr_in6 *);
const char *netname6(struct sockaddr_in6 *, struct in6_addr *);
void inet6print(struct in6_addr *, int, const char *, int);
@@ -124,6 +129,8 @@ void pfkey_stats(u_long, const char *, int, int);
void mbpr(void *, u_long);
+void netisr_stats(void *);
+
void hostpr(u_long, u_long);
void impstats(u_long, u_long);
diff --git a/freebsd/usr.bin/netstat/route.c b/freebsd/usr.bin/netstat/route.c
index 584ce132..1725c78d 100644
--- a/freebsd/usr.bin/netstat/route.c
+++ b/freebsd/usr.bin/netstat/route.c
@@ -126,7 +126,6 @@ typedef union {
static sa_u pt_u;
-static int fibnum;
static struct rtentry rtentry;
static struct radix_node rnode;
static struct radix_mask rmask;
@@ -159,8 +158,7 @@ routepr(u_long rtree)
{
struct radix_node_head **rnhp, *rnh, head;
size_t intsize;
- int i;
- int numfibs;
+ int fam, fibnum, numfibs;
intsize = sizeof(int);
if (sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1)
@@ -198,15 +196,20 @@ routepr(u_long rtree)
if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs *
(AF_MAX+1) * sizeof(struct radix_node_head *))) != 0)
return;
- for (i = 0; i <= AF_MAX; i++) {
+ for (fam = 0; fam <= AF_MAX; fam++) {
int tmpfib;
- if (i != AF_INET)
- tmpfib = 0;
- else
+
+ switch (fam) {
+ case AF_INET6:
+ case AF_INET:
tmpfib = fibnum;
+ break;
+ default:
+ tmpfib = 0;
+ }
rnhp = (struct radix_node_head **)*rt_tables;
/* Calculate the in-kernel address. */
- rnhp += tmpfib * (AF_MAX+1) + i;
+ rnhp += tmpfib * (AF_MAX+1) + fam;
/* Read the in kernel rhn pointer. */
if (kget(rnhp, rnh) != 0)
continue;
@@ -219,16 +222,16 @@ routepr(u_long rtree)
/* Read the rnh data. */
if (kget(rnh, head) != 0)
continue;
- if (i == AF_UNSPEC) {
+ if (fam == AF_UNSPEC) {
if (Aflag && af == 0) {
printf("Netmasks:\n");
p_tree(head.rnh_treetop);
}
- } else if (af == AF_UNSPEC || af == i) {
- size_cols(i, head.rnh_treetop);
- pr_family(i);
+ } else if (af == AF_UNSPEC || af == fam) {
+ size_cols(fam, head.rnh_treetop);
+ pr_family(fam);
do_rtent = 1;
- pr_rthdr(i);
+ pr_rthdr(fam);
p_tree(head.rnh_treetop);
}
}
@@ -654,18 +657,8 @@ fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags)
case AF_INET6:
{
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
- struct in6_addr *in6 = &sa6->sin6_addr;
-
- /*
- * XXX: This is a special workaround for KAME kernels.
- * sin6_scope_id field of SA should be set in the future.
- */
- if (IN6_IS_ADDR_LINKLOCAL(in6) ||
- IN6_IS_ADDR_MC_LINKLOCAL(in6)) {
- /* XXX: override is ok? */
- sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]);
- *(u_short *)&in6->s6_addr[2] = 0;
- }
+
+ in6_fillscopeid(sa6);
if (flags & RTF_HOST)
cp = routename6(sa6);
@@ -923,6 +916,25 @@ netname(in_addr_t in, u_long mask)
#undef NSHIFT
#ifdef INET6
+void
+in6_fillscopeid(struct sockaddr_in6 *sa6)
+{
+#if defined(__KAME__)
+ /*
+ * XXX: This is a special workaround for KAME kernels.
+ * sin6_scope_id field of SA should be set in the future.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sa6->sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) {
+ /* XXX: override is ok? */
+ sa6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sa6->sin6_addr.s6_addr[2]);
+ sa6->sin6_addr.s6_addr[2] = sa6->sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+}
+
const char *
netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask)
{
@@ -1121,10 +1133,8 @@ ipx_phost(struct sockaddr *sa)
struct sockaddr_ipx work;
static union ipx_net ipx_zeronet;
char *p;
- struct ipx_addr in;
work = *sipx;
- in = work.sipx_addr;
work.sipx_addr.x_port = 0;
work.sipx_addr.x_net = ipx_zeronet;
diff --git a/freebsd/usr.bin/netstat/sctp.c b/freebsd/usr.bin/netstat/sctp.c
index d32d28d1..9feca576 100644
--- a/freebsd/usr.bin/netstat/sctp.c
+++ b/freebsd/usr.bin/netstat/sctp.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2001-2007, by Weongyo Jeong. All rights reserved.
+ * Copyright (c) 2011, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -63,7 +64,6 @@ __FBSDID("$FreeBSD$");
#ifdef SCTP
-void inetprint(struct in_addr *, int, const char *, int);
static void sctp_statesprint(uint32_t state);
#define NETSTAT_SCTP_STATES_CLOSED 0x0
@@ -102,6 +102,128 @@ struct xraddr_entry {
LIST_ENTRY(xraddr_entry) xraddr_entries;
};
+/*
+ * Construct an Internet address representation.
+ * If numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+#ifdef INET
+static char *
+inetname(struct in_addr *inp)
+{
+ char *cp;
+ static char line[MAXHOSTNAMELEN];
+ struct hostent *hp;
+ struct netent *np;
+
+ cp = 0;
+ if (!numeric_addr && inp->s_addr != INADDR_ANY) {
+ int net = inet_netof(*inp);
+ int lna = inet_lnaof(*inp);
+
+ if (lna == INADDR_ANY) {
+ np = getnetbyaddr(net, AF_INET);
+ if (np)
+ cp = np->n_name;
+ }
+ if (cp == 0) {
+ hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
+ if (hp) {
+ cp = hp->h_name;
+ trimdomain(cp, strlen(cp));
+ }
+ }
+ }
+ if (inp->s_addr == INADDR_ANY)
+ strcpy(line, "*");
+ else if (cp) {
+ strlcpy(line, cp, sizeof(line));
+ } else {
+ inp->s_addr = ntohl(inp->s_addr);
+#define C(x) ((u_int)((x) & 0xff))
+ sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
+ C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
+ inp->s_addr = htonl(inp->s_addr);
+ }
+ return (line);
+}
+#endif
+
+#ifdef INET6
+static char ntop_buf[INET6_ADDRSTRLEN];
+
+static char *
+inet6name(struct in6_addr *in6p)
+{
+ char *cp;
+ static char line[50];
+ struct hostent *hp;
+ static char domain[MAXHOSTNAMELEN];
+ static int first = 1;
+
+ if (first && !numeric_addr) {
+ first = 0;
+ if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+ (cp = index(domain, '.')))
+ (void) strcpy(domain, cp + 1);
+ else
+ domain[0] = 0;
+ }
+ cp = 0;
+ if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
+ hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
+ if (hp) {
+ if ((cp = index(hp->h_name, '.')) &&
+ !strcmp(cp + 1, domain))
+ *cp = 0;
+ cp = hp->h_name;
+ }
+ }
+ if (IN6_IS_ADDR_UNSPECIFIED(in6p))
+ strcpy(line, "*");
+ else if (cp)
+ strcpy(line, cp);
+ else
+ sprintf(line, "%s",
+ inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
+ sizeof(ntop_buf)));
+ return (line);
+}
+#endif
+
+static void
+sctp_print_address(union sctp_sockstore *address, int port, int num_port)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int width;
+
+ switch (address->sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ sprintf(line, "%.*s.", Wflag ? 39 : 16, inetname(&address->sin.sin_addr));
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ sprintf(line, "%.*s.", Wflag ? 39 : 16, inet6name(&address->sin6.sin6_addr));
+ break;
+#endif
+ default:
+ sprintf(line, "%.*s.", Wflag ? 39 : 16, "");
+ break;
+ }
+ cp = index(line, '\0');
+ if (!num_port && port)
+ sp = getservbyport((int)port, "sctp");
+ if (sp || port == 0)
+ sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
+ else
+ sprintf(cp, "%d ", ntohs((u_short)port));
+ width = Wflag ? 45 : 22;
+ printf("%-*.*s ", width, width, line);
+}
+
static int
sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
{
@@ -150,18 +272,14 @@ sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
}
static void
-sctp_process_tcb(struct xsctp_tcb *xstcb, const char *name,
+sctp_process_tcb(struct xsctp_tcb *xstcb,
char *buf, const size_t buflen, size_t *offset, int *indent)
{
int i, xl_total = 0, xr_total = 0, x_max;
- struct sockaddr *sa;
struct xsctp_raddr *xraddr;
struct xsctp_laddr *xladdr;
struct xladdr_entry *prev_xl = NULL, *xl = NULL, *xl_tmp;
struct xraddr_entry *prev_xr = NULL, *xr = NULL, *xr_tmp;
-#ifdef INET6
- struct sockaddr_in6 *in6;
-#endif
LIST_INIT(&xladdr_head);
LIST_INIT(&xraddr_head);
@@ -220,38 +338,22 @@ sctp_process_tcb(struct xsctp_tcb *xstcb, const char *name,
x_max = (xl_total > xr_total) ? xl_total : xr_total;
for (i = 0; i < x_max; i++) {
if (((*indent == 0) && i > 0) || *indent > 0)
- printf("%-11s ", " ");
+ printf("%-12s ", " ");
if (xl != NULL) {
- sa = &(xl->xladdr->address.sa);
- if ((sa->sa_family) == AF_INET)
- inetprint(&((struct sockaddr_in *)sa)->sin_addr,
- htons(xstcb->local_port),
- name, numeric_port);
-#ifdef INET6
- else {
- in6 = (struct sockaddr_in6 *)sa;
- inet6print(&in6->sin6_addr,
- htons(xstcb->local_port),
- name, numeric_port);
+ sctp_print_address(&(xl->xladdr->address),
+ htons(xstcb->local_port), numeric_port);
+ } else {
+ if (Wflag) {
+ printf("%-45s ", " ");
+ } else {
+ printf("%-22s ", " ");
}
-#endif
}
if (xr != NULL && !Lflag) {
- sa = &(xr->xraddr->address.sa);
- if ((sa->sa_family) == AF_INET)
- inetprint(&((struct sockaddr_in *)sa)->sin_addr,
- htons(xstcb->remote_port),
- name, numeric_port);
-#ifdef INET6
- else {
- in6 = (struct sockaddr_in6 *)sa;
- inet6print(&in6->sin6_addr,
- htons(xstcb->remote_port),
- name, numeric_port);
- }
-#endif
+ sctp_print_address(&(xr->xraddr->address),
+ htons(xstcb->remote_port), numeric_port);
}
if (xl != NULL)
@@ -285,53 +387,21 @@ out:
}
}
-#ifdef SCTP_DEBUG
-uint32_t sctp_pdup[64];
-int sctp_pcnt = 0;
-#endif
-
static void
-sctp_process_inpcb(struct xsctp_inpcb *xinpcb, const char *name,
+sctp_process_inpcb(struct xsctp_inpcb *xinpcb,
char *buf, const size_t buflen, size_t *offset)
{
- int offset_backup, indent = 0, xladdr_total = 0, is_listening = 0;
+ int indent = 0, xladdr_total = 0, is_listening = 0;
static int first = 1;
- char *tname;
+ char *tname, *pname;
struct xsctp_tcb *xstcb;
struct xsctp_laddr *xladdr;
- struct sockaddr *sa;
-#ifdef INET6
- struct sockaddr_in6 *in6;
-#endif
+ size_t offset_laddr;
+ int process_closed;
- if ((xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE) ==
- SCTP_PCB_FLAGS_TCPTYPE && xinpcb->maxqlen > 0)
+ if (xinpcb->maxqlen > 0)
is_listening = 1;
- if (!Lflag && !is_listening &&
- !(xinpcb->flags & SCTP_PCB_FLAGS_CONNECTED)) {
-#ifdef SCTP_DEBUG
- int i, found = 0;
-
- for (i = 0; i < sctp_pcnt; i++) {
- if (sctp_pdup[i] == xinpcb->flags) {
- found = 1;
- break;
- }
- }
- if (!found) {
- sctp_pdup[sctp_pcnt++] = xinpcb->flags;
- if (sctp_pcnt >= 64)
- sctp_pcnt = 0;
- printf("[0x%08x]", xinpcb->flags);
- }
-#endif
- offset_backup = *offset;
- if (!sctp_skip_xinpcb_ifneed(buf, buflen, offset))
- return;
- *offset = offset_backup;
- }
-
if (first) {
if (!Lflag) {
printf("Active SCTP associations");
@@ -340,90 +410,115 @@ sctp_process_inpcb(struct xsctp_inpcb *xinpcb, const char *name,
} else
printf("Current listen queue sizes (qlen/maxqlen)");
putchar('\n');
- if (Aflag)
- printf("%-8.8s ", "Socket");
if (Lflag)
- printf("%-5.5s %-5.5s %-8.8s %-22.22s\n",
+ printf("%-6.6s %-5.5s %-8.8s %-22.22s\n",
"Proto", "Type", "Listen", "Local Address");
else
- printf((Aflag && !Wflag) ?
- "%-5.5s %-5.5s %-18.18s %-18.18s %s\n" :
- "%-5.5s %-5.5s %-22.22s %-22.22s %s\n",
- "Proto", "Type",
- "Local Address", "Foreign Address",
- "(state)");
+ if (Wflag)
+ printf("%-6.6s %-5.5s %-45.45s %-45.45s %s\n",
+ "Proto", "Type",
+ "Local Address", "Foreign Address",
+ "(state)");
+ else
+ printf("%-6.6s %-5.5s %-22.22s %-22.22s %s\n",
+ "Proto", "Type",
+ "Local Address", "Foreign Address",
+ "(state)");
first = 0;
}
- if (Lflag && xinpcb->maxqlen == 0) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ if (Lflag && !is_listening) {
(int)sctp_skip_xinpcb_ifneed(buf, buflen, offset);
return;
}
- if (Aflag)
- printf("%8lx ", (u_long)xinpcb);
- printf("%-5.5s ", name);
+ if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ /* Can't distinguish between sctp46 and sctp6 */
+ pname = "sctp46";
+ } else {
+ pname = "sctp4";
+ }
if (xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE)
tname = "1to1";
else if (xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE)
tname = "1toN";
else
- return;
-
- printf("%-5.5s ", tname);
+ tname = "????";
if (Lflag) {
char buf1[9];
snprintf(buf1, 9, "%hu/%hu", xinpcb->qlen, xinpcb->maxqlen);
+ printf("%-6.6s %-5.5s ", pname, tname);
printf("%-8.8s ", buf1);
}
- /*
- * process the local address. This routine are used for Lflag.
- */
+
+ offset_laddr = *offset;
+ process_closed = 0;
+retry:
while (*offset < buflen) {
xladdr = (struct xsctp_laddr *)(buf + *offset);
*offset += sizeof(struct xsctp_laddr);
- if (xladdr->last == 1)
+ if (xladdr->last) {
+ if (aflag && !Lflag && (xladdr_total == 0) && process_closed) {
+ printf("%-6.6s %-5.5s ", pname, tname);
+ if (Wflag) {
+ printf("%-91.91s CLOSED", " ");
+ } else {
+ printf("%-45.45s CLOSED", " ");
+ }
+ }
+ if (process_closed || is_listening) {
+ putchar('\n');
+ }
break;
+ }
- if (!Lflag && !is_listening)
+ if (!Lflag && !is_listening && !process_closed)
continue;
- if (xladdr_total != 0)
+ if (xladdr_total == 0) {
+ printf("%-6.6s %-5.5s ", pname, tname);
+ } else {
putchar('\n');
- if (xladdr_total > 0)
printf((Lflag) ?
- "%-20.20s " : "%-11.11s ", " ");
-
- sa = &(xladdr->address.sa);
- if ((sa->sa_family) == AF_INET)
- inetprint(&((struct sockaddr_in *)sa)->sin_addr,
- htons(xinpcb->local_port), name, numeric_port);
-#ifdef INET6
- else {
- in6 = (struct sockaddr_in6 *)sa;
- inet6print(&in6->sin6_addr,
- htons(xinpcb->local_port), name, numeric_port);
+ "%-21.21s " : "%-12.12s ", " ");
+ }
+ sctp_print_address(&(xladdr->address),
+ htons(xinpcb->local_port), numeric_port);
+ if (aflag && !Lflag && xladdr_total == 0) {
+ if (Wflag) {
+ if (process_closed) {
+ printf("%-45.45s CLOSED", " ");
+ } else {
+ printf("%-45.45s LISTEN", " ");
+ }
+ } else {
+ if (process_closed) {
+ printf("%-22.22s CLOSED", " ");
+ } else {
+ printf("%-22.22s LISTEN", " ");
+ }
+ }
}
-#endif
-
- if (!Lflag && xladdr_total == 0 && is_listening == 1)
- printf("%-22.22s LISTEN", " ");
-
xladdr_total++;
}
xstcb = (struct xsctp_tcb *)(buf + *offset);
*offset += sizeof(struct xsctp_tcb);
+ if (aflag && (xladdr_total == 0) && xstcb->last && !process_closed) {
+ process_closed = 1;
+ *offset = offset_laddr;
+ goto retry;
+ }
while (xstcb->last == 0 && *offset < buflen) {
- sctp_process_tcb(xstcb, name, buf, buflen, offset, &indent);
+ printf("%-6.6s %-5.5s ", pname, tname);
+ sctp_process_tcb(xstcb, buf, buflen, offset, &indent);
indent++;
xstcb = (struct xsctp_tcb *)(buf + *offset);
*offset += sizeof(struct xsctp_tcb);
}
-
- putchar('\n');
}
/*
@@ -461,7 +556,7 @@ sctp_protopr(u_long off __unused,
xinpcb = (struct xsctp_inpcb *)(buf + offset);
offset += sizeof(struct xsctp_inpcb);
while (xinpcb->last == 0 && offset < len) {
- sctp_process_inpcb(xinpcb, name, buf, (const size_t)len,
+ sctp_process_inpcb(xinpcb, buf, (const size_t)len,
&offset);
xinpcb = (struct xsctp_inpcb *)(buf + offset);
@@ -520,7 +615,8 @@ sctp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
memset(&zerostat, 0, len);
if (sysctlbyname("net.inet.sctp.stats", &sctpstat, &len,
zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
- warn("sysctl: net.inet.sctp.stats");
+ if (errno != ENOENT)
+ warn("sysctl: net.inet.sctp.stats");
return;
}
} else
@@ -563,7 +659,7 @@ sctp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
p(sctps_sendfastretrans, "\t\t%ju fast retransmitted DATA chunk%s\n");
p(sctps_sendmultfastretrans, "\t\t%ju FR'%s that happened more "
"than once to same chunk\n");
- p(sctps_sendheartbeat, "\t\t%ju intput HB chunk%s\n");
+ p(sctps_sendheartbeat, "\t\t%ju output HB chunk%s\n");
p(sctps_sendecne, "\t\t%ju output ECNE chunk%s\n");
p(sctps_sendauth, "\t\t%ju output AUTH chunk%s\n");
p1a(sctps_senderrors, "\t\t%ju ip_output error counter\n");
diff --git a/rtemsbsd/include/rtems/bsd/local/bus_if.h b/rtemsbsd/include/rtems/bsd/local/bus_if.h
index 6a54d605..a0204db3 100644
--- a/rtemsbsd/include/rtems/bsd/local/bus_if.h
+++ b/rtemsbsd/include/rtems/bsd/local/bus_if.h
@@ -3,7 +3,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * kern/bus_if.m
+ * freebsd-org/sys/kern/bus_if.m
* with
* makeobjops.awk
*
@@ -319,6 +319,37 @@ static __inline int BUS_DEACTIVATE_RESOURCE(device_t _dev, device_t _child,
return ((bus_deactivate_resource_t *) _m)(_dev, _child, _type, _rid, _r);
}
+/** @brief Unique descriptor for the BUS_ADJUST_RESOURCE() method */
+extern struct kobjop_desc bus_adjust_resource_desc;
+/** @brief A function implementing the BUS_ADJUST_RESOURCE() method */
+typedef int bus_adjust_resource_t(device_t _dev, device_t _child, int _type,
+ struct resource *_res, u_long _start,
+ u_long _end);
+/**
+ * @brief Adjust a resource
+ *
+ * Adjust the start and/or end of a resource allocated by
+ * BUS_ALLOC_RESOURCE. At least part of the new address range must overlap
+ * with the existing address range. If the successful, the resource's range
+ * will be adjusted to [start, end] on return.
+ *
+ * @param _dev the parent device of @p _child
+ * @param _child the device which allocated the resource
+ * @param _type the type of resource
+ * @param _res the resource to adjust
+ * @param _start the new starting address of the resource range
+ * @param _end the new ending address of the resource range
+ */
+
+static __inline int BUS_ADJUST_RESOURCE(device_t _dev, device_t _child,
+ int _type, struct resource *_res,
+ u_long _start, u_long _end)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_adjust_resource);
+ return ((bus_adjust_resource_t *) _m)(_dev, _child, _type, _res, _start, _end);
+}
+
/** @brief Unique descriptor for the BUS_RELEASE_RESOURCE() method */
extern struct kobjop_desc bus_release_resource_desc;
/** @brief A function implementing the BUS_RELEASE_RESOURCE() method */
diff --git a/rtemsbsd/include/rtems/bsd/local/device_if.h b/rtemsbsd/include/rtems/bsd/local/device_if.h
index 47339eb3..7a2cbc72 100644
--- a/rtemsbsd/include/rtems/bsd/local/device_if.h
+++ b/rtemsbsd/include/rtems/bsd/local/device_if.h
@@ -3,7 +3,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * kern/device_if.m
+ * freebsd-org/sys/kern/device_if.m
* with
* makeobjops.awk
*
diff --git a/rtemsbsd/include/rtems/bsd/local/miidevs.h b/rtemsbsd/include/rtems/bsd/local/miidevs.h
index ee8f4327..f0f42d41 100644
--- a/rtemsbsd/include/rtems/bsd/local/miidevs.h
+++ b/rtemsbsd/include/rtems/bsd/local/miidevs.h
@@ -66,6 +66,7 @@
#define MII_OUI_LEVEL1 0x00207b /* Level 1 */
#define MII_OUI_NATSEMI 0x080017 /* National Semiconductor */
#define MII_OUI_QUALSEMI 0x006051 /* Quality Semiconductor */
+#define MII_OUI_RDC 0x000bb4 /* RDC Semiconductor */
#define MII_OUI_REALTEK 0x000020 /* RealTek Semicondctor */
#define MII_OUI_SEEQ 0x00a07d /* Seeq */
#define MII_OUI_SIS 0x00e006 /* Silicon Integrated Systems */
@@ -205,9 +206,17 @@
#define MII_MODEL_xxBROADCOM_ALT1_BCM5761 0x003d
#define MII_STR_xxBROADCOM_ALT1_BCM5761 "BCM5761 10/100/1000baseTX PHY"
#define MII_MODEL_xxBROADCOM_ALT1_BCM5709S 0x003f
-#define MII_STR_xxBROADCOM_ALT1_BCM5709S "BCM5709S 1000/2500baseSX PHY"
+#define MII_STR_xxBROADCOM_ALT1_BCM5709S "BCM5709S/5720S 1000/2500baseSX PHY"
+#define MII_MODEL_xxBROADCOM_ALT2_BCM57780 0x0019
+#define MII_STR_xxBROADCOM_ALT2_BCM57780 "BCM57780 1000BASE-T media interface"
#define MII_MODEL_xxBROADCOM_ALT2_BCM5717C 0x0020
#define MII_STR_xxBROADCOM_ALT2_BCM5717C "BCM5717C 10/100/1000baseTX PHY"
+#define MII_MODEL_xxBROADCOM_ALT2_BCM5719C 0x0022
+#define MII_STR_xxBROADCOM_ALT2_BCM5719C "BCM5719C 10/100/1000baseTX PHY"
+#define MII_MODEL_xxBROADCOM_ALT2_BCM57765 0x0024
+#define MII_STR_xxBROADCOM_ALT2_BCM57765 "BCM57765 10/100/1000baseTX PHY"
+#define MII_MODEL_xxBROADCOM_ALT2_BCM5720C 0x0036
+#define MII_STR_xxBROADCOM_ALT2_BCM5720C "BCM5720C 10/100/1000baseTX PHY"
#define MII_MODEL_BROADCOM2_BCM5906 0x0004
#define MII_STR_BROADCOM2_BCM5906 "BCM5906 10/100baseTX PHY"
@@ -292,11 +301,17 @@
#define MII_STR_NATSEMI_DP83861 "DP83861 10/100/1000 media interface"
#define MII_MODEL_NATSEMI_DP83865 0x0007
#define MII_STR_NATSEMI_DP83865 "DP83865 10/100/1000 media interface"
+#define MII_MODEL_NATSEMI_DP83849 0x000a
+#define MII_STR_NATSEMI_DP83849 "DP83849 10/100 media interface"
/* Quality Semiconductor PHYs */
#define MII_MODEL_QUALSEMI_QS6612 0x0000
#define MII_STR_QUALSEMI_QS6612 "QS6612 10/100 media interface"
+/* RDC Semiconductor PHYs */
+#define MII_MODEL_RDC_R6040 0x0003
+#define MII_STR_RDC_R6040 "R6040 10/100 media interface"
+
/* RealTek Semiconductor PHYs */
#define MII_MODEL_REALTEK_RTL8201L 0x0020
#define MII_STR_REALTEK_RTL8201L "RTL8201L 10/100 media interface"
@@ -360,6 +375,8 @@
#define MII_STR_MARVELL_E1116R "Marvell 88E1116R Gigabit PHY"
#define MII_MODEL_MARVELL_E1118 0x0022
#define MII_STR_MARVELL_E1118 "Marvell 88E1118 Gigabit PHY"
+#define MII_MODEL_MARVELL_E1149R 0x0025
+#define MII_STR_MARVELL_E1149R "Marvell 88E1149R Quad Gigabit PHY"
#define MII_MODEL_MARVELL_E3016 0x0026
#define MII_STR_MARVELL_E3016 "Marvell 88E3016 10/100 Fast Ethernet PHY"
#define MII_MODEL_MARVELL_PHYG65G 0x0027
diff --git a/rtemsbsd/include/rtems/bsd/local/pci_if.h b/rtemsbsd/include/rtems/bsd/local/pci_if.h
index c2028bf8..d4152556 100644
--- a/rtemsbsd/include/rtems/bsd/local/pci_if.h
+++ b/rtemsbsd/include/rtems/bsd/local/pci_if.h
@@ -3,7 +3,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * dev/pci/pci_if.m
+ * freebsd-org/sys/dev/pci/pci_if.m
* with
* makeobjops.awk
*
diff --git a/rtemsbsd/include/rtems/bsd/local/pcib_if.h b/rtemsbsd/include/rtems/bsd/local/pcib_if.h
index ad659176..22c387e9 100644
--- a/rtemsbsd/include/rtems/bsd/local/pcib_if.h
+++ b/rtemsbsd/include/rtems/bsd/local/pcib_if.h
@@ -3,7 +3,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * dev/pci/pcib_if.m
+ * freebsd-org/sys/dev/pci/pcib_if.m
* with
* makeobjops.awk
*
diff --git a/rtemsbsd/include/rtems/bsd/local/usb_if.h b/rtemsbsd/include/rtems/bsd/local/usb_if.h
index 6f4a15a3..1c5b9199 100644
--- a/rtemsbsd/include/rtems/bsd/local/usb_if.h
+++ b/rtemsbsd/include/rtems/bsd/local/usb_if.h
@@ -3,7 +3,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * dev/usb/usb_if.m
+ * freebsd-org/sys/dev/usb/usb_if.m
* with
* makeobjops.awk
*
@@ -28,4 +28,16 @@ static __inline int USB_HANDLE_REQUEST(device_t dev, const void *req,
return ((usb_handle_request_t *) _m)(dev, req, pptr, plen, offset, pstate);
}
+/** @brief Unique descriptor for the USB_TAKE_CONTROLLER() method */
+extern struct kobjop_desc usb_take_controller_desc;
+/** @brief A function implementing the USB_TAKE_CONTROLLER() method */
+typedef int usb_take_controller_t(device_t dev);
+
+static __inline int USB_TAKE_CONTROLLER(device_t dev)
+{
+ kobjop_t _m;
+ KOBJOPLOOKUP(((kobj_t)dev)->ops,usb_take_controller);
+ return ((usb_take_controller_t *) _m)(dev);
+}
+
#endif /* _usb_if_h_ */
diff --git a/rtemsbsd/include/rtems/bsd/local/usbdevs.h b/rtemsbsd/include/rtems/bsd/local/usbdevs.h
index 79bee891..63f285c3 100644
--- a/rtemsbsd/include/rtems/bsd/local/usbdevs.h
+++ b/rtemsbsd/include/rtems/bsd/local/usbdevs.h
@@ -24,13 +24,6 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -331,10 +324,12 @@
#define USB_VENDOR_ALARIS 0x0620 /* Alaris */
#define USB_VENDOR_APEX 0x0624 /* Apex */
#define USB_VENDOR_CREATIVE3 0x062a /* Creative Labs */
+#define USB_VENDOR_MICRON 0x0634 /* Micron Technology */
#define USB_VENDOR_VIVITAR 0x0636 /* Vivitar */
#define USB_VENDOR_GUNZE 0x0637 /* Gunze Electronics USA */
#define USB_VENDOR_AVISION 0x0638 /* Avision */
#define USB_VENDOR_TEAC 0x0644 /* TEAC */
+#define USB_VENDOR_ACTON 0x0647 /* Acton Research Corp. */
#define USB_VENDOR_SGI 0x065e /* Silicon Graphics */
#define USB_VENDOR_SANWASUPPLY 0x0663 /* Sanwa Supply */
#define USB_VENDOR_MEGATEC 0x0665 /* Megatec */
@@ -359,6 +354,7 @@
#define USB_VENDOR_ASIAMD 0x06be /* Asia Microelectronic Development */
#define USB_VENDOR_BIZLINK 0x06c4 /* Bizlink International */
#define USB_VENDOR_KEYSPAN 0x06cd /* Keyspan / InnoSys Inc. */
+#define USB_VENDOR_CONTEC 0x06ce /* Contec products */
#define USB_VENDOR_AASHIMA 0x06d6 /* Aashima Technology */
#define USB_VENDOR_LIEBERT 0x06da /* Liebert */
#define USB_VENDOR_MULTITECH 0x06e0 /* MultiTech */
@@ -377,7 +373,7 @@
#define USB_VENDOR_SYNTECH 0x0745 /* Syntech Information */
#define USB_VENDOR_DIGITALSTREAM 0x074e /* Digital Stream */
#define USB_VENDOR_AUREAL 0x0755 /* Aureal Semiconductor */
-#define USB_VENDOR_MIDIMAN 0x0763 /* Midiman */
+#define USB_VENDOR_MAUDIO 0x0763 /* M-Audio */
#define USB_VENDOR_CYBERPOWER 0x0764 /* Cyber Power Systems, Inc. */
#define USB_VENDOR_SURECOM 0x0769 /* Surecom Technology */
#define USB_VENDOR_HIDGLOBAL 0x076b /* HID Global */
@@ -418,6 +414,7 @@
#define USB_VENDOR_STSN 0x07ef /* STSN */
#define USB_VENDOR_CENTURY 0x07f7 /* Century Corp */
#define USB_VENDOR_NEWLINK 0x07ff /* NEWlink */
+#define USB_VENDOR_MAGTEK 0x0801 /* Mag-Tek */
#define USB_VENDOR_ZOOM 0x0803 /* Zoom Telephonics */
#define USB_VENDOR_PCS 0x0810 /* Personal Communication Systems */
#define USB_VENDOR_ALPHASMART 0x081e /* AlphaSmart, Inc. */
@@ -498,8 +495,11 @@
#define USB_VENDOR_MEDIAGEAR 0x0a48 /* MediaGear */
#define USB_VENDOR_BROADCOM 0x0a5c /* Broadcom */
#define USB_VENDOR_GREENHOUSE 0x0a6b /* GREENHOUSE */
+#define USB_VENDOR_MEDELI 0x0a67 /* Medeli */
#define USB_VENDOR_GEOCAST 0x0a79 /* Geocast Network Systems */
-#define USB_VENDOR_IDQUANTIQUE 0x0aba /* id Quantique */
+#define USB_VENDOR_EGO 0x0a92 /* EGO systems */
+#define USB_VENDOR_IDQUANTIQUE 0x0aba /* ID Quantique */
+#define USB_VENDOR_IDTECH 0x0acd /* ID TECH */
#define USB_VENDOR_ZYDAS 0x0ace /* Zydas Technology Corporation */
#define USB_VENDOR_NEODIO 0x0aec /* Neodio */
#define USB_VENDOR_OPTION 0x0af0 /* Option N.V. */
@@ -526,14 +526,20 @@
#define USB_VENDOR_FSC 0x0bf8 /* Fujitsu Siemens Computers */
#define USB_VENDOR_AGATE 0x0c08 /* Agate Technologies */
#define USB_VENDOR_DMI 0x0c0b /* DMI */
+#define USB_VENDOR_ICOM 0x0c26 /* Icom Inc. */
+#define USB_VENDOR_GNOTOMETRICS 0x0c33 /* GN Otometrics */
#define USB_VENDOR_CHICONY2 0x0c45 /* Chicony */
#define USB_VENDOR_REINERSCT 0x0c4b /* Reiner-SCT */
#define USB_VENDOR_SEALEVEL 0x0c52 /* Sealevel System */
+#define USB_VENDOR_JETI 0x0c6c /* Jeti */
#define USB_VENDOR_LUWEN 0x0c76 /* Luwen */
+#define USB_VENDOR_ELEKTOR 0x0c7d /* ELEKTOR Electronics */
#define USB_VENDOR_KYOCERA2 0x0c88 /* Kyocera Wireless Corp. */
#define USB_VENDOR_ZCOM 0x0cde /* Z-Com */
#define USB_VENDOR_ATHEROS2 0x0cf3 /* Atheros Communications */
+#define USB_VENDOR_POSIFLEX 0x0d3a /* POSIFLEX */
#define USB_VENDOR_TANGTOP 0x0d3d /* Tangtop */
+#define USB_VENDOR_KOBIL 0x0d46 /* KOBIL */
#define USB_VENDOR_SMC3 0x0d5c /* Standard Microsystems */
#define USB_VENDOR_ADDON 0x0d7d /* Add-on Technology */
#define USB_VENDOR_ACDC 0x0d7e /* American Computer & Digital Components */
@@ -542,6 +548,7 @@
#define USB_VENDOR_SKANHEX 0x0d96 /* Skanhex Technology, Inc. */
#define USB_VENDOR_MSI 0x0db0 /* Micro Star International */
#define USB_VENDOR_ELCON 0x0db7 /* ELCON Systemtechnik */
+#define USB_VENDOR_UNKNOWN4 0x0dcd /* Unknown vendor */
#define USB_VENDOR_NETAC 0x0dd8 /* Netac */
#define USB_VENDOR_SITECOMEU 0x0df6 /* Sitecom Europe */
#define USB_VENDOR_MOBILEACTION 0x0df7 /* Mobile Action */
@@ -550,6 +557,7 @@
#define USB_VENDOR_HAWKING 0x0e66 /* Hawking */
#define USB_VENDOR_FOSSIL 0x0e67 /* Fossil, Inc */
#define USB_VENDOR_GMATE 0x0e7e /* G.Mate, Inc */
+#define USB_VENDOR_MEDIATEK 0x0e8d /* MediaTek, Inc. */
#define USB_VENDOR_OTI 0x0ea0 /* Ours Technology */
#define USB_VENDOR_YISO 0x0eab /* Yiso Wireless Co. */
#define USB_VENDOR_PILOTECH 0x0eaf /* Pilotech */
@@ -564,11 +572,15 @@
#define USB_VENDOR_FALCOM 0x0f94 /* Falcom Wireless Communications GmbH */
#define USB_VENDOR_RIM 0x0fca /* Research In Motion */
#define USB_VENDOR_DYNASTREAM 0x0fcf /* Dynastream Innovations */
+#define USB_VENDOR_LARSENBRUSGAARD 0x0fd8 /* Larsen and Brusgaard */
+#define USB_VENDOR_KONTRON 0x0fe6 /* Kontron AG */
#define USB_VENDOR_QUALCOMM 0x1004 /* Qualcomm */
#define USB_VENDOR_APACER 0x1005 /* Apacer */
#define USB_VENDOR_MOTOROLA4 0x100d /* Motorola */
#define USB_VENDOR_AIRPLUS 0x1011 /* Airplus */
#define USB_VENDOR_DESKNOTE 0x1019 /* Desknote */
+#define USB_VENDOR_NEC3 0x1033 /* NEC */
+#define USB_VENDOR_TTI 0x103e /* Thurlby Thandar Instruments */
#define USB_VENDOR_GIGABYTE 0x1044 /* GIGABYTE */
#define USB_VENDOR_WESTERN 0x1058 /* Western Digital */
#define USB_VENDOR_MOTOROLA 0x1063 /* Motorola */
@@ -597,12 +609,14 @@
#define USB_VENDOR_SIEMENS3 0x11f5 /* Siemens */
#define USB_VENDOR_NETINDEX 0x11f6 /* NetIndex */
#define USB_VENDOR_ALCATEL 0x11f7 /* Alcatel */
+#define USB_VENDOR_INTERBIOMETRICS 0x1209 /* Interbiometrics */
#define USB_VENDOR_UNKNOWN3 0x1233 /* Unknown vendor */
#define USB_VENDOR_TSUNAMI 0x1241 /* Tsunami */
#define USB_VENDOR_PHEENET 0x124a /* Pheenet */
#define USB_VENDOR_TARGUS 0x1267 /* Targus */
#define USB_VENDOR_TWINMOS 0x126f /* TwinMOS */
#define USB_VENDOR_TENDA 0x1286 /* Tenda */
+#define USB_VENDOR_TESTO 0x128d /* Testo products */
#define USB_VENDOR_CREATIVE2 0x1292 /* Creative Labs */
#define USB_VENDOR_BELKIN2 0x1293 /* Belkin Components */
#define USB_VENDOR_CYBERTAN 0x129b /* CyberTAN Technology */
@@ -617,11 +631,14 @@
#define USB_VENDOR_CISCOLINKSYS 0x13b1 /* Cisco-Linksys */
#define USB_VENDOR_SHARK 0x13d2 /* Shark */
#define USB_VENDOR_AZUREWAVE 0x13d3 /* AsureWave */
+#define USB_VENDOR_INITIO 0x13fd /* Initio Corporation */
#define USB_VENDOR_EMTEC 0x13fe /* Emtec */
#define USB_VENDOR_NOVATEL 0x1410 /* Novatel Wireless */
#define USB_VENDOR_MERLIN 0x1416 /* Merlin */
+#define USB_VENDOR_REDOCTANE 0x1430 /* RedOctane */
#define USB_VENDOR_WISTRONNEWEB 0x1435 /* Wistron NeWeb */
#define USB_VENDOR_RADIOSHACK 0x1453 /* Radio Shack */
+#define USB_VENDOR_FIC 0x1457 /* FIC / OpenMoko */
#define USB_VENDOR_HUAWEI3COM 0x1472 /* Huawei-3Com */
#define USB_VENDOR_ABOCOM2 0x1482 /* AboCom Systems */
#define USB_VENDOR_SILICOM 0x1485 /* Silicom */
@@ -640,7 +657,10 @@
#define USB_VENDOR_UMEDIA 0x157e /* U-MEDIA Communications */
#define USB_VENDOR_FIBERLINE 0x1582 /* Fiberline */
#define USB_VENDOR_SPARKLAN 0x15a9 /* SparkLAN */
+#define USB_VENDOR_OLIMEX 0x15ba /* Olimex */
+#define USB_VENDOR_SOUNDGRAPH 0x15c2 /* Soundgraph, Inc. */
#define USB_VENDOR_AMIT2 0x15c5 /* AMIT */
+#define USB_VENDOR_TEXTECH 0x15ca /* Textech International Ltd. */
#define USB_VENDOR_SOHOWARE 0x15e8 /* SOHOware */
#define USB_VENDOR_UMAX 0x1606 /* UMAX Data Systems */
#define USB_VENDOR_INSIDEOUT 0x1608 /* Inside Out Networks */
@@ -656,12 +676,14 @@
#define USB_VENDOR_ANYDATA 0x16d5 /* AnyDATA Corporation */
#define USB_VENDOR_JABLOTRON 0x16d6 /* Jablotron */
#define USB_VENDOR_CMOTECH 0x16d8 /* C-motech */
+#define USB_VENDOR_WIENERPLEINBAUS 0x16dc /* WIENER Plein & Baus GmbH. */
#define USB_VENDOR_AXESSTEL 0x1726 /* Axesstel Co., Ltd. */
#define USB_VENDOR_LINKSYS4 0x1737 /* Linksys */
#define USB_VENDOR_SENAO 0x1740 /* Senao */
#define USB_VENDOR_ASUS2 0x1761 /* ASUS */
#define USB_VENDOR_SWEEX2 0x177f /* Sweex */
#define USB_VENDOR_METAGEEK 0x1781 /* MetaGeek */
+#define USB_VENDOR_KAMSTRUP 0x17a8 /* Kamstrup A/S */
#define USB_VENDOR_WAVESENSE 0x17f4 /* WaveSense */
#define USB_VENDOR_VAISALA 0x1843 /* Vaisala */
#define USB_VENDOR_AMIT 0x18c5 /* AMIT */
@@ -670,12 +692,19 @@
#define USB_VENDOR_ELV 0x18ef /* ELV */
#define USB_VENDOR_LINKSYS3 0x1915 /* Linksys */
#define USB_VENDOR_QUALCOMMINC 0x19d2 /* Qualcomm, Incorporated */
+#define USB_VENDOR_BAYER 0x1a79 /* Bayer */
#define USB_VENDOR_WCH2 0x1a86 /* QinHeng Electronics */
#define USB_VENDOR_STELERA 0x1a8d /* Stelera Wireless */
+#define USB_VENDOR_CORSAIR 0x1b1c /* Corsair */
#define USB_VENDOR_MATRIXORBITAL 0x1b3d /* Matrix Orbital */
#define USB_VENDOR_OVISLINK 0x1b75 /* OvisLink */
+#define USB_VENDOR_TML 0x1b91 /* The Mobility Lab */
#define USB_VENDOR_TCTMOBILE 0x1bbb /* TCT Mobile */
+#define USB_VENDOR_ALTI2 0x1bc9 /* Alti-2 products */
+#define USB_VENDOR_SUNPLUS 0x1bcf /* Sunplus Innovation Technology Inc. */
+#define USB_VENDOR_WAGO 0x1be3 /* WAGO Kontakttechnik GmbH. */
#define USB_VENDOR_TELIT 0x1bc7 /* Telit */
+#define USB_VENDOR_IONICS 0x1c0c /* Ionics PlugComputer */
#define USB_VENDOR_LONGCHEER 0x1c9e /* Longcheer Holdings, Ltd. */
#define USB_VENDOR_MPMAN 0x1cae /* MpMan */
#define USB_VENDOR_DRESDENELEKTRONIK 0x1cf1 /* dresden elektronik */
@@ -685,19 +714,27 @@
#define USB_VENDOR_METAGEEK2 0x1dd5 /* MetaGeek */
#define USB_VENDOR_ALINK 0x1e0e /* Alink */
#define USB_VENDOR_AIRTIES 0x1eda /* AirTies */
+#define USB_VENDOR_FESTO 0x1e29 /* Festo */
+#define USB_VENDOR_VERTEX 0x1fe7 /* Vertex Wireless Co., Ltd. */
#define USB_VENDOR_DLINK 0x2001 /* D-Link */
#define USB_VENDOR_PLANEX2 0x2019 /* Planex Communications */
#define USB_VENDOR_HAUPPAUGE2 0x2040 /* Hauppauge Computer Works */
#define USB_VENDOR_TLAYTECH 0x20b9 /* Tlay Tech */
#define USB_VENDOR_ENCORE 0x203d /* Encore */
+#define USB_VENDOR_QIHARDWARE 0x20b7 /* QI-hardware */
#define USB_VENDOR_PARA 0x20b8 /* PARA Industrial */
+#define USB_VENDOR_SIMTEC 0x20df /* Simtec Electronics */
+#define USB_VENDOR_RTSYSTEMS 0x2100 /* RTSYSTEMS */
+#define USB_VENDOR_VIALABS 0x2109 /* VIA Labs */
#define USB_VENDOR_ERICSSON 0x2282 /* Ericsson */
#define USB_VENDOR_MOTOROLA2 0x22b8 /* Motorola */
+#define USB_VENDOR_WETELECOM 0x22de /* WeTelecom */
#define USB_VENDOR_TRIPPLITE 0x2478 /* Tripp-Lite */
#define USB_VENDOR_HIROSE 0x2631 /* Hirose Electric */
#define USB_VENDOR_NHJ 0x2770 /* NHJ */
#define USB_VENDOR_PLANEX 0x2c02 /* Planex Communications */
#define USB_VENDOR_VIDZMEDIA 0x3275 /* VidzMedia Pte Ltd */
+#define USB_VENDOR_LINKINSTRUMENTS 0x3195 /* Link Instruments Inc. */
#define USB_VENDOR_AEI 0x3334 /* AEI */
#define USB_VENDOR_HANK 0x3353 /* Hank Connection */
#define USB_VENDOR_PQI 0x3538 /* PQI */
@@ -709,6 +746,7 @@
#define USB_VENDOR_DELL 0x413c /* Dell */
#define USB_VENDOR_WCH 0x4348 /* QinHeng Electronics */
#define USB_VENDOR_ACEECA 0x4766 /* Aceeca */
+#define USB_VENDOR_PAPOUCH 0x5050 /* Papouch products */
#define USB_VENDOR_AVERATEC 0x50c2 /* Averatec */
#define USB_VENDOR_SWEEX 0x5173 /* Sweex */
#define USB_VENDOR_PROLIFIC2 0x5372 /* Prolific Technologies */
@@ -725,8 +763,10 @@
#define USB_VENDOR_MOSCHIP 0x9710 /* MosChip Semiconductor */
#define USB_VENDOR_MARVELL 0x9e88 /* Marvell Technology Group Ltd. */
#define USB_VENDOR_3COM3 0xa727 /* 3Com */
+#define USB_VENDOR_EVOLUTION 0xdeee /* Evolution Robotics products */
#define USB_VENDOR_DATAAPEX 0xdaae /* DataApex */
#define USB_VENDOR_HP2 0xf003 /* Hewlett Packard */
+#define USB_VENDOR_LOGILINK 0xfc08 /* LogiLink */
#define USB_VENDOR_USRP 0xfffe /* GNU Radio USRP */
/*
@@ -780,6 +820,9 @@
#define USB_PRODUCT_ABOCOM_RT2573_4 0xb21e /* RT2573 */
#define USB_PRODUCT_ABOCOM_WUG2700 0xb21f /* WUG2700 */
+/* Acton Research Corp. */
+#define USB_PRODUCT_ACTON_SPECTRAPRO 0x0100 /* FTDI compatible adapter */
+
/* Accton products */
#define USB_PRODUCT_ACCTON_USB320_EC 0x1046 /* USB320-EC Ethernet Adapter */
#define USB_PRODUCT_ACCTON_2664W 0x3501 /* 2664W */
@@ -907,6 +950,8 @@
/* AirPrime products */
#define USB_PRODUCT_AIRPRIME_PC5220 0x0112 /* CDMA Wireless PC Card */
+#define USB_PRODUCT_AIRPRIME_USB308 0x68A3 /* USB308 HSPA+ USB Modem */
+#define USB_PRODUCT_AIRPRIME_AC313U 0x68aa /* Sierra Wireless AirCard 313U */
/* AirTies products */
#define USB_PRODUCT_AIRTIES_RT3070 0x2310 /* RT3070 */
@@ -920,8 +965,10 @@
/* Alcor Micro, Inc. products */
#define USB_PRODUCT_ALCOR2_KBD_HUB 0x2802 /* Kbd Hub */
+#define USB_PRODUCT_ALCOR_DUMMY 0x0000 /* Dummy product */
#define USB_PRODUCT_ALCOR_SDCR_6335 0x6335 /* SD/MMC Card Reader */
#define USB_PRODUCT_ALCOR_SDCR_6362 0x6362 /* SD/MMC Card Reader */
+#define USB_PRODUCT_ALCOR_SDCR_6366 0x6366 /* SD/MMC Card Reader */
#define USB_PRODUCT_ALCOR_TRANSCEND 0x6387 /* Transcend JetFlash Drive */
#define USB_PRODUCT_ALCOR_MA_KBD_HUB 0x9213 /* MacAlly Kbd Hub */
#define USB_PRODUCT_ALCOR_AU9814 0x9215 /* AU9814 Hub */
@@ -940,6 +987,9 @@
#define USB_PRODUCT_ALTEC_ADA70 0x0070 /* ADA70 Speakers */
#define USB_PRODUCT_ALTEC_ASC495 0xff05 /* ASC495 Speakers */
+/* Alti-2 products */
+#define USB_PRODUCT_ALTI2_N3 0x6001 /* FTDI compatible adapter */
+
/* Allied Telesyn International products */
#define USB_PRODUCT_ALLIEDTELESYN_ATUSB100 0xb100 /* AT-USB100 */
@@ -986,6 +1036,10 @@
/* AMIT(2) products */
#define USB_PRODUCT_AMIT2_RT2870 0x0008 /* RT2870 */
+/* Analog Devices products */
+#define USB_PRODUCT_ANALOGDEVICES_GNICE 0xf000 /* FTDI compatible adapter */
+#define USB_PRODUCT_ANALOGDEVICES_GNICEPLUS 0xf001 /* FTDI compatible adapter */
+
/* Anchor products */
#define USB_PRODUCT_ANCHOR_SERIAL 0x2008 /* Serial */
#define USB_PRODUCT_ANCHOR_EZUSB 0x2131 /* EZUSB */
@@ -1003,6 +1057,7 @@
#define USB_PRODUCT_APC_UPS 0x0002 /* Uninterruptible Power Supply */
/* Apple Computer products */
+#define USB_PRODUCT_APPLE_DUMMY 0x0000 /* Dummy product */
#define USB_PRODUCT_APPLE_IMAC_KBD 0x0201 /* USB iMac Keyboard */
#define USB_PRODUCT_APPLE_KBD 0x0202 /* USB Keyboard M2452 */
#define USB_PRODUCT_APPLE_EXT_KBD 0x020c /* Apple Extended USB Keyboard */
@@ -1033,6 +1088,7 @@
#define USB_PRODUCT_APPLE_IPHONE_3G 0x1292 /* iPhone 3G */
#define USB_PRODUCT_APPLE_IPHONE_3GS 0x1294 /* iPhone 3GS */
#define USB_PRODUCT_APPLE_IPHONE_4 0x1297 /* iPhone 4 */
+#define USB_PRODUCT_APPLE_IPHONE_5 0x12a8 /* iPhone 5 */
#define USB_PRODUCT_APPLE_IPAD 0x129a /* iPad */
#define USB_PRODUCT_APPLE_ETHERNET 0x1402 /* Ethernet A1277 */
@@ -1051,6 +1107,8 @@
#define USB_PRODUCT_ASIX_AX88178 0x1780 /* AX88178 */
#define USB_PRODUCT_ASIX_AX88772 0x7720 /* AX88772 */
#define USB_PRODUCT_ASIX_AX88772A 0x772a /* AX88772A USB 2.0 10/100 Ethernet */
+#define USB_PRODUCT_ASIX_AX88772B 0x772b /* AX88772B USB 2.0 10/100 Ethernet */
+#define USB_PRODUCT_ASIX_AX88772B_1 0x7e2b /* AX88772B USB 2.0 10/100 Ethernet */
/* ASUS products */
#define USB_PRODUCT_ASUS2_USBN11 0x0b05 /* USB-N11 */
@@ -1072,6 +1130,7 @@
#define USB_PRODUCT_ASUS_P535 0x420f /* ASUS P535 PDA */
#define USB_PRODUCT_ASUS_GMSC 0x422f /* ASUS Generic Mass Storage */
#define USB_PRODUCT_ASUS_RT2570 0x1706 /* RT2500USB Wireless Adapter */
+#define USB_PRODUCT_ASUS_USB_N53 0x179d /* ASUS Black Diamond Dual Band USB-N53 */
/* ATen products */
#define USB_PRODUCT_ATEN_UC1284 0x2001 /* Parallel printer */
@@ -1118,8 +1177,27 @@
/* Baltech products */
#define USB_PRODUCT_BALTECH_CARDREADER 0x9999 /* Card reader */
+/* Bayer products */
+#define USB_PRODUCT_BAYER_CONTOUR_CABLE 0x6001 /* FTDI compatible adapter */
+
/* B&B Electronics products */
#define USB_PRODUCT_BBELECTRONICS_USOTL4 0xAC01 /* RS-422/485 */
+#define USB_PRODUCT_BBELECTRONICS_232USB9M 0xac27 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_485USB9F_2W 0xac25 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_485USB9F_4W 0xac26 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_485USBTB_2W 0xac33 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_485USBTB_4W 0xac34 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_TTL3USB9M 0xac50 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_TTL5USB9M 0xac49 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_USO9ML2 0xac03 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_USO9ML2DR 0xac17 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_USO9ML2DR_2 0xac16 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_USOPTL4 0xac11 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_USOPTL4DR 0xac19 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_USOPTL4DR2 0xac18 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_USPTL4 0xac12 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_USTL4 0xac02 /* FTDI compatible adapter */
+#define USB_PRODUCT_BBELECTRONICS_ZZ_PROG1_USB 0xba02 /* FTDI compatible adapter */
/* Belkin products */
/*product BELKIN F5U111 0x???? F5U111 Ethernet*/
@@ -1149,6 +1227,7 @@
#define USB_PRODUCT_BELKIN_RT2870_2 0x805c /* RT2870 */
#define USB_PRODUCT_BELKIN_F5D8053V3 0x815c /* F5D8053 v3 */
#define USB_PRODUCT_BELKIN_F5D8055 0x825a /* F5D8055 */
+#define USB_PRODUCT_BELKIN_F5D8055V2 0x825b /* F5D8055 v2 */
#define USB_PRODUCT_BELKIN_F5D9050V3 0x905b /* F5D9050 ver 3 Wireless Adapter */
#define USB_PRODUCT_BELKIN2_F5U002 0x0002 /* F5U002 Parallel printer */
#define USB_PRODUCT_BELKIN_F6D4050V1 0x935a /* F6D4050 v1 */
@@ -1232,11 +1311,18 @@
#define USB_PRODUCT_CISCOLINKSYS_WUSB54GC 0x0020 /* WUSB54GC */
#define USB_PRODUCT_CISCOLINKSYS_WUSB54GR 0x0023 /* WUSB54GR */
#define USB_PRODUCT_CISCOLINKSYS_WUSBF54G 0x0024 /* WUSBF54G */
+#define USB_PRODUCT_CISCOLINKSYS_AE1000 0x002f /* AE1000 */
#define USB_PRODUCT_CISCOLINKSYS2_RT3070 0x4001 /* RT3070 */
#define USB_PRODUCT_CISCOLINKSYS3_RT3070 0x0101 /* RT3070 */
/* Clipsal products */
-#define USB_PRODUCT_CLIPSAL_5500PCU 0x0303 /* 5500PCU C-Bus */
+#define USB_PRODUCT_CLIPSAL_560884 0x0101 /* 560884 C-Bus Audio Matrix Switch */
+#define USB_PRODUCT_CLIPSAL_5500PACA 0x0201 /* 5500PACA C-Bus Pascal Automation Controller */
+#define USB_PRODUCT_CLIPSAL_5800PC 0x0301 /* 5800PC C-Bus Wireless Interface */
+#define USB_PRODUCT_CLIPSAL_5500PCU 0x0303 /* 5500PCU C-Bus Interface */
+#define USB_PRODUCT_CLIPSAL_5000CT2 0x0304 /* 5000CT2 C-Bus Touch Screen */
+#define USB_PRODUCT_CLIPSAL_C5000CT2 0x0305 /* C5000CT2 C-Bus Touch Screen */
+#define USB_PRODUCT_CLIPSAL_L51xx 0x0401 /* L51xx C-Bus Dimmer */
/* CMOTECH products */
#define USB_PRODUCT_CMOTECH_CNU510 0x5141 /* CDMA Technologies USB modem */
@@ -1278,6 +1364,9 @@
/* Connectix products */
#define USB_PRODUCT_CONNECTIX_QUICKCAM 0x0001 /* QuickCam */
+/* Conect products */
+#define USB_PRODUCT_CONTEC_COM1USBH 0x8311 /* FTDI compatible adapter */
+
/* Corega products */
#define USB_PRODUCT_COREGA_ETHER_USB_T 0x0001 /* Ether USB-T */
#define USB_PRODUCT_COREGA_FETHER_USB_TX 0x0004 /* FEther USB-TX */
@@ -1298,6 +1387,9 @@
#define USB_PRODUCT_COREGA_WLUSB_11_STICK 0x7613 /* WLAN USB Stick 11 */
#define USB_PRODUCT_COREGA_FETHER_USB_TXC 0x9601 /* FEther USB-TXC */
+/* Corsair products */
+#define USB_PRODUCT_CORSAIR_K60 0x0a60 /* Corsair Vengeance K60 keyboard */
+
/* Creative products */
#define USB_PRODUCT_CREATIVE_NOMAD_II 0x1002 /* Nomad II MP3 player */
#define USB_PRODUCT_CREATIVE_NOMAD_IIMG 0x4004 /* Nomad II MG */
@@ -1320,6 +1412,7 @@
#define USB_PRODUCT_CURITEL_HX550C 0x1101 /* CDMA 2000 1xRTT USB modem (HX-550C) */
#define USB_PRODUCT_CURITEL_HX57XB 0x2101 /* CDMA 2000 1xRTT USB modem (HX-570/575B/PR-600) */
#define USB_PRODUCT_CURITEL_PC5740 0x3701 /* Broadband Wireless modem */
+#define USB_PRODUCT_CURITEL_UM150 0x3711 /* EVDO modem */
#define USB_PRODUCT_CURITEL_UM175 0x3714 /* EVDO modem */
/* CyberPower products */
@@ -1400,6 +1493,7 @@
/* D-Link products */
/*product DLINK DSBS25 0x0100 DSB-S25 serial*/
#define USB_PRODUCT_DLINK_DUBE100 0x1a00 /* 10/100 Ethernet */
+#define USB_PRODUCT_DLINK_DUBE100C1 0x1a02 /* DUB-E100 rev C1 */
#define USB_PRODUCT_DLINK_DSB650TX4 0x200c /* 10/100 Ethernet */
#define USB_PRODUCT_DLINK_DWL120E 0x3200 /* DWL-120 rev E */
#define USB_PRODUCT_DLINK_DWL122 0x3700 /* DWL-122 */
@@ -1462,12 +1556,17 @@
#define USB_PRODUCT_EDIMAX_RT2870_1 0x7711 /* RT2870 */
#define USB_PRODUCT_EDIMAX_EW7717 0x7717 /* EW-7717 */
#define USB_PRODUCT_EDIMAX_EW7718 0x7718 /* EW-7718 */
+#define USB_PRODUCT_EDIMAX_EW7811UN 0x7811 /* EW-7811Un */
/* eGalax Products */
#define USB_PRODUCT_EGALAX_TPANEL 0x0001 /* Touch Panel */
#define USB_PRODUCT_EGALAX_TPANEL2 0x0002 /* Touch Panel */
#define USB_PRODUCT_EGALAX2_TPANEL 0x0001 /* Touch Panel */
+/* EGO Products */
+#define USB_PRODUCT_EGO_DUMMY 0x0000 /* Dummy Product */
+#define USB_PRODUCT_EGO_M4U 0x1020 /* ESI M4U */
+
/* Eicon Networks */
#define USB_PRODUCT_EICON_DIVA852 0x4905 /* Diva 852 ISDN TA */
@@ -1489,6 +1588,9 @@
#define USB_PRODUCT_ELECOM_UCSGT0 0x5004 /* UC-SGT */
#define USB_PRODUCT_ELECOM_LDUSBTX3 0xabc1 /* LD-USB/TX */
+/* Elektor products */
+#define USB_PRODUCT_ELEKTOR_FT323R 0x0005 /* FTDI compatible adapter */
+
/* Elsa products */
#define USB_PRODUCT_ELSA_MODEM1 0x2265 /* ELSA Modem Board */
#define USB_PRODUCT_ELSA_USB2ETHERNET 0x3000 /* Microlink USB2Ethernet */
@@ -1499,6 +1601,9 @@
/* EMS products */
#define USB_PRODUCT_EMS_DUAL_SHOOTER 0x0003 /* PSX gun controller converter */
+/* Emtec products */
+#define USB_PRODUCT_EMTEC_RUF2PS 0x2240 /* Flash Drive */
+
/* Encore products */
#define USB_PRODUCT_ENCORE_RT3070_1 0x1480 /* RT3070 */
#define USB_PRODUCT_ENCORE_RT3070_2 0x14a1 /* RT3070 */
@@ -1544,6 +1649,7 @@
#define USB_PRODUCT_EPSON_3590 0x0122 /* Perfection 3590 scanner */
#define USB_PRODUCT_EPSON_4990 0x012a /* Perfection 4990 Photo scanner */
#define USB_PRODUCT_EPSON_CRESSI_EDY 0x0521 /* Cressi Edy diving computer */
+#define USB_PRODUCT_EPSON_N2ITION3 0x0522 /* Zeagle N2iTion3 diving computer */
#define USB_PRODUCT_EPSON_STYLUS_875DC 0x0601 /* Stylus Photo 875DC Card Reader */
#define USB_PRODUCT_EPSON_STYLUS_895 0x0602 /* Stylus Photo 895 Card Reader */
#define USB_PRODUCT_EPSON_CX5400 0x0808 /* CX5400 scanner */
@@ -1565,20 +1671,40 @@
/* e-TEK Labs products */
#define USB_PRODUCT_ETEK_1COM 0x8007 /* Serial */
+/* Evolution products */
+#define USB_PRODUCT_EVOLUTION_ER1 0x0300 /* FTDI compatible adapter */
+#define USB_PRODUCT_EVOLUTION_HYBRID 0x0302 /* FTDI compatible adapter */
+#define USB_PRODUCT_EVOLUTION_RCM4 0x0303 /* FTDI compatible adapter */
+
/* Extended Systems products */
#define USB_PRODUCT_EXTENDED_XTNDACCESS 0x0100 /* XTNDAccess IrDA */
+/* Falcom products */
+#define USB_PRODUCT_FALCOM_TWIST 0x0001 /* USB GSM/GPRS Modem */
+#define USB_PRODUCT_FALCOM_SAMBA 0x0005 /* FTDI compatible adapter */
+
/* FEIYA products */
+#define USB_PRODUCT_FEIYA_DUMMY 0x0000 /* Dummy product */
#define USB_PRODUCT_FEIYA_5IN1 0x1132 /* 5-in-1 Card Reader */
+#define USB_PRODUCT_FEIYA_ELANGO 0x6200 /* MicroSDHC Card Reader */
+#define USB_PRODUCT_FEIYA_AC110 0x6300 /* AC-110 Card Reader */
+
+/* Festo */
+#define USB_PRODUCT_FESTO_CPX_USB 0x0102 /* CPX-USB */
+#define USB_PRODUCT_FESTO_CMSP 0x0501 /* CMSP */
/* Fiberline */
#define USB_PRODUCT_FIBERLINE_WL430U 0x6003 /* WL-430U */
+/* FIC / OpenMoko */
+#define USB_PRODUCT_FIC_NEO1973_DEBUG 0x5118 /* FTDI compatible adapter */
+
/* Fossil, Inc products */
#define USB_PRODUCT_FOSSIL_WRISTPDA 0x0002 /* Wrist PDA */
/* Foxconn products */
-#define USB_PRODUCT_FOXCONN_PIRELLI_DP_L10 0xe000 /* Pirelli DP-L10 */
+#define USB_PRODUCT_FOXCONN_TCOM_TC_300 0xe000 /* T-Com TC 300 */
+#define USB_PRODUCT_FOXCONN_PIRELLI_DP_L10 0xe003 /* Pirelli DP-L10 */
/* Freecom products */
#define USB_PRODUCT_FREECOM_DVD 0xfc01 /* DVD drive */
@@ -1591,9 +1717,13 @@
#define USB_PRODUCT_FTDI_SERIAL_8U100AX 0x8372 /* 8U100AX Serial */
#define USB_PRODUCT_FTDI_SERIAL_8U232AM 0x6001 /* 8U232AM Serial */
#define USB_PRODUCT_FTDI_SERIAL_8U232AM4 0x6004 /* 8U232AM Serial */
+#define USB_PRODUCT_FTDI_SERIAL_232RL 0x6006 /* FT232RL Serial */
#define USB_PRODUCT_FTDI_SERIAL_2232C 0x6010 /* FT2232C Dual port Serial */
+#define USB_PRODUCT_FTDI_232H 0x6014 /* FTDI compatible adapter */
#define USB_PRODUCT_FTDI_SERIAL_2232D 0x9e90 /* FT2232D Dual port Serial */
#define USB_PRODUCT_FTDI_SERIAL_4232H 0x6011 /* FT4232H Quad port Serial */
+#define USB_PRODUCT_FTDI_BEAGLEBONE 0xa6d0 /* BeagleBone */
+#define USB_PRODUCT_FTDI_TURTELIZER2 0xbdc8 /* egnite Turtelizer 2 JTAG/RS232 Adapter */
/* Gude Analog- und Digitalsysteme products also uses FTDI's id: */
#define USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13M 0xcc48 /* OpenPort 1.3 Mitsubishi */
#define USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13S 0xcc49 /* OpenPort 1.3 Subaru */
@@ -1621,6 +1751,204 @@
/* Commerzielle und Technische Informationssysteme GmbH products */
#define USB_PRODUCT_FTDI_CTI_USB_NANO_485 0xf60b /* CTI USB-Nano 485 */
#define USB_PRODUCT_FTDI_CTI_USB_MINI_485 0xf608 /* CTI USB-Mini 485 */
+/* Other products */
+#define USB_PRODUCT_FTDI_232RL 0xfbfa /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_4N_GALAXY_DE_1 0xf3c0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_4N_GALAXY_DE_2 0xf3c1 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_4N_GALAXY_DE_3 0xf3c2 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_8U232AM_ALT 0x6006 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ACCESSO 0xfad0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ACG_HFDUAL 0xdd20 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ACTIVE_ROBOTS 0xe548 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ACTZWAVE 0xf2d0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_AMC232 0xff00 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ARTEMIS 0xdf28 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ASK_RDR400 0xc991 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ATIK_ATK16 0xdf30 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ATIK_ATK16C 0xdf32 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ATIK_ATK16HR 0xdf31 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ATIK_ATK16HRC 0xdf33 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ATIK_ATK16IC 0xdf35 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_BCS_SE923 0xfb99 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CANDAPTER 0x9f80 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CANUSB 0xffa8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CCSICDU20_0 0xf9d0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CCSICDU40_1 0xf9d1 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CCSICDU64_4 0xf9d4 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CCSLOAD_N_GO_3 0xf9d3 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CCSMACHX_2 0xf9d2 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CCSPRIME8_5 0xf9d5 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CHAMSYS_24_MASTER_WING 0xdaf8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CHAMSYS_MAXI_WING 0xdafd /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CHAMSYS_MEDIA_WING 0xdafe /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CHAMSYS_MIDI_TIMECODE 0xdafb /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CHAMSYS_MINI_WING 0xdafc /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CHAMSYS_PC_WING 0xdaf9 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CHAMSYS_USB_DMX 0xdafa /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CHAMSYS_WING 0xdaff /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_COM4SM 0xd578 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CONVERTER_0 0xd388 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CONVERTER_1 0xd389 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CONVERTER_2 0xd38a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CONVERTER_3 0xd38b /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CONVERTER_4 0xd38c /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CONVERTER_5 0xd38d /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CONVERTER_6 0xd38e /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_CONVERTER_7 0xd38f /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_DMX4ALL 0xc850 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_DOMINTELL_DGQG 0xef50 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_DOMINTELL_DUSB 0xef51 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_DOTEC 0x9868 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ECLO_COM_1WIRE 0xea90 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ECO_PRO_CDS 0xe520 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELSTER_UNICOM 0xe700 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_ALC8500 0xf06e /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_CLI7000 0xfb59 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_CSI8 0xe0f0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_EC3000 0xe006 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_EM1000DL 0xe0f1 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_EM1010PC 0xe0ef /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_FEM 0xe00a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_FHZ1000PC 0xf06f /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_FHZ1300PC 0xe0e8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_FM3RX 0xe0ed /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_FS20SIG 0xe0f4 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_HS485 0xe0ea /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_KL100 0xe002 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_MSM1 0xe001 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_PCD200 0xf06c /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_PCK100 0xe0f2 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_PPS7330 0xfb5c /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_RFP500 0xe0f3 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_T1100 0xf06b /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_TFD128 0xe0ec /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_TFM100 0xfb5d /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_TWS550 0xe009 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UAD8 0xf068 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UDA7 0xf069 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UDF77 0xfb5e /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UIO88 0xfb5f /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_ULA200 0xf06d /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UM100 0xfb5a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UMS100 0xe0eb /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UO100 0xfb5b /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UR100 0xfb58 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_USI2 0xf06a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_USR 0xe000 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_UTP8 0xe0f5 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_WS300PC 0xe0f6 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_WS444PC 0xe0f7 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_WS500 0xe0e9 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_WS550 0xe004 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_WS777 0xe0ee /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_ELV_WS888 0xe008 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_FUTURE_0 0xf44a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_FUTURE_1 0xf44b /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_FUTURE_2 0xf44c /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GENERIC 0x9378 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E808 0xe808 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E809 0xe809 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E80A 0xe80a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E80B 0xe80b /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E80C 0xe80c /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E80D 0xe80d /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E80E 0xe80e /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E80F 0xe80f /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E88D 0xe88d /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E88E 0xe88e /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_GUDEADS_E88F 0xe88f /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_HD_RADIO 0x937c /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_HO720 0xed72 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_HO730 0xed73 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_HO820 0xed74 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_HO870 0xed71 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IBS_APP70 0xff3d /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IBS_PCMCIA 0xff3a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IBS_PEDO 0xff3e /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IBS_PICPRO 0xff39 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IBS_PK1 0xff3b /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IBS_PROD 0xff3f /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IBS_RS232MON 0xff3c /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IBS_US485 0xff38 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IPLUS 0xd070 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IPLUS2 0xd071 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_IRTRANS 0xfc60 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_LENZ_LIUSB 0xd780 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_LM3S_DEVEL_BOARD 0xbcd8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_LM3S_EVAL_BOARD 0xbcd9 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MASTERDEVEL2 0xf449 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MHAM_DB9 0xeeed /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MHAM_IC 0xeeec /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MHAM_KW 0xeee8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MHAM_RS232 0xeeee /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MHAM_Y6 0xeeea /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MHAM_Y8 0xeeeb /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MHAM_Y9 0xeeef /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MHAM_YS 0xeee9 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MICRO_CHAMELEON 0xcaa0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MTXORB_5 0xfa05 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_MTXORB_6 0xfa06 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_NXTCAM 0xabb8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_OCEANIC 0xf460 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_OOCDLINK 0xbaf8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_OPENDCC 0xbfd8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_OPENDCC_GATEWAY 0xbfdb /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_OPENDCC_GBM 0xbfdc /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_OPENDCC_SNIFFER 0xbfd9 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_OPENDCC_THROTTLE 0xbfda /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_PCDJ_DAC2 0xfa88 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_PERLE_ULTRAPORT 0xf0c0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_PHI_FISCO 0xe40b /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_PIEGROUP 0xf208 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_PROPOX_JTAGCABLEII 0xd738 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_R2000KU_TRUE_RNG 0xfb80 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_R2X0 0xfc71 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_RELAIS 0xfa10 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_REU_TINY 0xed22 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_RMP200 0xe729 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_RM_CANVIEW 0xfd60 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_RRCIRKITS_LOCOBUFFER 0xc7d0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCIENCESCOPE_HS_LOGBOOK 0xff1d /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCIENCESCOPE_LOGBOOKML 0xff18 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCIENCESCOPE_LS_LOGBOOK 0xff1c /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCS_DEVICE_0 0xd010 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCS_DEVICE_1 0xd011 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCS_DEVICE_2 0xd012 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCS_DEVICE_3 0xd013 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCS_DEVICE_4 0xd014 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCS_DEVICE_5 0xd015 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCS_DEVICE_6 0xd016 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SCS_DEVICE_7 0xd017 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SDMUSBQSS 0xf448 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SIGNALYZER_SH2 0xbca2 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SIGNALYZER_SH4 0xbca4 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SIGNALYZER_SLITE 0xbca1 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SIGNALYZER_ST 0xbca0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SPECIAL_1 0xfc70 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SPECIAL_3 0xfc72 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SPECIAL_4 0xfc73 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SPROG_II 0xf0c8 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SR_RADIO 0x9379 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_SUUNTO_SPORTS 0xf680 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_TAVIR_STK500 0xfa33 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_TERATRONIK_D2XX 0xec89 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_TERATRONIK_VCP 0xec88 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_THORLABS 0xfaf0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_TNC_X 0xebe0 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_TTUSB 0xff20 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_USBX_707 0xf857 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_USINT_CAT 0xb810 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_USINT_RS232 0xb812 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_USINT_WKEY 0xb811 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_VARDAAN 0xf070 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_VNHCPCUSB_D 0xfe38 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_WESTREX_MODEL_777 0xdc00 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_WESTREX_MODEL_8900F 0xdc01 /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_XF_547 0xfc0a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_XF_640 0xfc0e /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_XF_642 0xfc0f /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_XM_RADIO 0x937a /* FTDI compatible adapter */
+#define USB_PRODUCT_FTDI_YEI_SERVOCENTER31 0xe050 /* FTDI compatible adapter */
/* Fuji photo products */
#define USB_PRODUCT_FUJIPHOTO_MASS0100 0x0100 /* Mass Storage */
@@ -1635,7 +1963,7 @@
#define USB_PRODUCT_GARMIN_IQUE_3600 0x0004 /* iQue 3600 */
/* Gemalto products */
-#define USB_PRODUCT_GEMALTO_PROXPU 0x5501 /* Prox-PU/CU */
+#define USB_PRODUCT_GEMALTO_PROXPU 0x5501 /* Prox-PU/CU RFID Card Reader */
/* General Instruments (Motorola) products */
#define USB_PRODUCT_GENERALINSTMNTS_SB5100 0x5100 /* SURFboard SB5100 Cable modem */
@@ -1683,6 +2011,9 @@
/* G.Mate, Inc products */
#define USB_PRODUCT_GMATE_YP3X00 0x1001 /* YP3X00 PDA */
+/* GN Otometrics */
+#define USB_PRODUCT_GNOTOMETRICS_USB 0x0010 /* FTDI compatible adapter */
+
/* GoHubs products */
#define USB_PRODUCT_GOHUBS_GOCOM232 0x1001 /* GoCOM232 Serial */
@@ -1869,9 +2200,19 @@
#define USB_PRODUCT_HUAWEI_E143E 0x143e /* 3G modem */
#define USB_PRODUCT_HUAWEI_E143F 0x143f /* 3G modem */
#define USB_PRODUCT_HUAWEI_E1752 0x1446 /* 3G modem */
+#define USB_PRODUCT_HUAWEI_K4505 0x1464 /* 3G modem */
#define USB_PRODUCT_HUAWEI_K3765 0x1465 /* 3G modem */
#define USB_PRODUCT_HUAWEI_E1820 0x14ac /* E1820 HSPA+ USB Slider */
+#define USB_PRODUCT_HUAWEI_K3770 0x14c9 /* 3G modem */
+#define USB_PRODUCT_HUAWEI_K3770_INIT 0x14d1 /* K3770 Initial */
+#define USB_PRODUCT_HUAWEI_E3131_INIT 0x14fe /* 3G modem initial */
+#define USB_PRODUCT_HUAWEI_E392 0x1505 /* LTE modem */
+#define USB_PRODUCT_HUAWEI_E3131 0x1506 /* 3G modem */
#define USB_PRODUCT_HUAWEI_K3765_INIT 0x1520 /* K3765 Initial */
+#define USB_PRODUCT_HUAWEI_K4505_INIT 0x1521 /* K4505 Initial */
+#define USB_PRODUCT_HUAWEI_ETS2055 0x1803 /* CDMA modem */
+#define USB_PRODUCT_HUAWEI_E173 0x1c05 /* 3G modem */
+#define USB_PRODUCT_HUAWEI_E173_INIT 0x1c0b /* 3G modem initial */
/* HUAWEI 3com products */
#define USB_PRODUCT_HUAWEI3COM_WUB320G 0x0009 /* Aolynk WUB320g */
@@ -1879,9 +2220,29 @@
/* IBM Corporation */
#define USB_PRODUCT_IBM_USBCDROMDRIVE 0x4427 /* USB CD-ROM Drive */
+/* Icom products */
+#define USB_PRODUCT_ICOM_SP1 0x0004 /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_OPC_U_UC 0x0018 /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP2C1 0x0009 /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP2C2 0x000a /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP2D 0x000b /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP2KVR 0x0013 /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP2KVT 0x0012 /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP2VR 0x000d /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP2VT 0x000c /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP4KVR 0x0011 /* FTDI compatible adapter */
+#define USB_PRODUCT_ICOM_RP4KVT 0x0010 /* FTDI compatible adapter */
+
+/* ID-tech products */
+#define USB_PRODUCT_IDTECH_IDT1221U 0x0300 /* FTDI compatible adapter */
+
/* Imagination Technologies products */
#define USB_PRODUCT_IMAGINATION_DBX1 0x2107 /* DBX1 DSP core */
+/* Initio Corporation products */
+#define USB_PRODUCT_INITIO_DUMMY 0x0000 /* Dummy product */
+#define USB_PRODUCT_INITIO_INIC_1610P 0x1e40 /* USB to SATA Bridge */
+
/* Inside Out Networks products */
#define USB_PRODUCT_INSIDEOUT_EDGEPORT4 0x0001 /* EdgePort/4 serial ports */
@@ -1897,6 +2258,11 @@
#define USB_PRODUCT_INTEL_EASYPC_CAMERA 0x0110 /* Easy PC Camera */
#define USB_PRODUCT_INTEL_TESTBOARD 0x9890 /* 82930 test board */
#define USB_PRODUCT_INTEL2_IRMH 0x0020 /* Integrated Rate Matching Hub */
+#define USB_PRODUCT_INTEL2_IRMH2 0x0024 /* Integrated Rate Matching Hub */
+
+/* Interbiometric products */
+#define USB_PRODUCT_INTERBIOMETRICS_IOBOARD 0x1002 /* FTDI compatible adapter */
+#define USB_PRODUCT_INTERBIOMETRICS_MINI_IOBOARD 0x1006 /* FTDI compatible adapter */
/* Intersil products */
#define USB_PRODUCT_INTERSIL_PRISM_GT 0x1000 /* PrismGT USB 2.0 WLAN */
@@ -1929,6 +2295,9 @@
#define USB_PRODUCT_IOMEGA_ZIP100 0x0001 /* Zip 100 */
#define USB_PRODUCT_IOMEGA_ZIP250 0x0030 /* Zip 250 */
+/* Ionic products */
+#define USB_PRODUCT_IONICS_PLUGCOMPUTER 0x0102 /* FTDI compatible adapter */
+
/* Integrated System Solution Corp. products */
#define USB_PRODUCT_ISSC_ISSCBTA 0x1001 /* Bluetooth USB Adapter */
@@ -1946,6 +2315,9 @@
/* Jaton products */
#define USB_PRODUCT_JATON_EDA 0x5704 /* Ethernet */
+/* Jeti products */
+#define USB_PRODUCT_JETI_SPC1201 0x04b2 /* FTDI compatible adapter */
+
/* JMicron products */
#define USB_PRODUCT_JMICRON_JM20336 0x2336 /* USB to SATA Bridge */
#define USB_PRODUCT_JMICRON_JM20337 0x2338 /* USB to ATA/ATAPI Bridge */
@@ -1957,6 +2329,10 @@
/* JRC products */
#define USB_PRODUCT_JRC_AH_J3001V_J3002V 0x0001 /* AirH PHONE AH-J3001V/J3002V */
+/* Kamstrrup products */
+#define USB_PRODUCT_KAMSTRUP_OPTICALEYE 0x0001 /* Optical Eye/3-wire */
+#define USB_PRODUCT_KAMSTRUP_MBUS_250D 0x0005 /* M-Bus Master MultiPort 250D */
+
/* Kawatsu products */
#define USB_PRODUCT_KAWATSU_MH4000P 0x0003 /* MiniHub 4000P */
@@ -2005,6 +2381,10 @@
#define USB_PRODUCT_KLSI_DUH3E10BT 0x0008 /* USB Ethernet */
#define USB_PRODUCT_KLSI_DUH3E10BTN 0x0009 /* USB Ethernet */
+/* Kobil products */
+#define USB_PRODUCT_KOBIL_CONV_B1 0x2020 /* FTDI compatible adapter */
+#define USB_PRODUCT_KOBIL_CONV_KAAN 0x2021 /* FTDI compatible adapter */
+
/* Kodak products */
#define USB_PRODUCT_KODAK_DC220 0x0100 /* Digital Science DC220 */
#define USB_PRODUCT_KODAK_DC260 0x0110 /* Digital Science DC260 */
@@ -2013,6 +2393,10 @@
#define USB_PRODUCT_KODAK_DC240 0x0120 /* Digital Science DC240 */
#define USB_PRODUCT_KODAK_DC280 0x0130 /* Digital Science DC280 */
+/* Kontron AG products */
+#define USB_PRODUCT_KONTRON_DM9601 0x8101 /* USB Ethernet */
+#define USB_PRODUCT_KONTRON_JP1082 0x9700 /* USB Ethernet */
+
/* Konica Corp. Products */
#define USB_PRODUCT_KONICA_CAMERA 0x0720 /* Digital Color Camera */
@@ -2035,6 +2419,9 @@
#define USB_PRODUCT_LACIE_HD 0xa601 /* Hard Disk */
#define USB_PRODUCT_LACIE_CDRW 0xa602 /* CD R/W */
+/* Larsen and Brusgaard products */
+#define USB_PRODUCT_LARSENBRUSGAARD_ALTITRACK 0x0001 /* FTDI compatible adapter */
+
/* Leadtek products */
#define USB_PRODUCT_LEADTEK_9531 0x2101 /* 9531 GPS */
@@ -2048,6 +2435,11 @@
/* Liebert products */
#define USB_PRODUCT_LIEBERT_POWERSURE_PXT 0xffff /* PowerSure Personal XT */
+/* Link Instruments Inc. products */
+#define USB_PRODUCT_LINKINSTRUMENTS_MSO19 0xf190 /* Link Instruments MSO-19 */
+#define USB_PRODUCT_LINKINSTRUMENTS_MSO28 0xf280 /* Link Instruments MSO-28 */
+#define USB_PRODUCT_LINKINSTRUMENTS_MSO28_2 0xf281 /* Link Instruments MSO-28 */
+
/* Linksys products */
#define USB_PRODUCT_LINKSYS_MAUSB2 0x0105 /* Camedia MAUSB-2 */
#define USB_PRODUCT_LINKSYS_USB10TX1 0x200c /* USB10TX */
@@ -2067,12 +2459,17 @@
#define USB_PRODUCT_LINKSYS4_RT3070 0x0078 /* RT3070 */
#define USB_PRODUCT_LINKSYS4_WUSB600NV2 0x0079 /* WUSB600N v2 */
+/* Logilink products */
+#define USB_PRODUCT_LOGILINK_DUMMY 0x0000 /* Dummy product */
+#define USB_PRODUCT_LOGILINK_U2M 0x0101 /* LogiLink USB MIDI Cable */
+
/* Logitech products */
#define USB_PRODUCT_LOGITECH_M2452 0x0203 /* M2452 keyboard */
#define USB_PRODUCT_LOGITECH_M4848 0x0301 /* M4848 mouse */
#define USB_PRODUCT_LOGITECH_PAGESCAN 0x040f /* PageScan */
#define USB_PRODUCT_LOGITECH_QUICKCAMWEB 0x0801 /* QuickCam Web */
#define USB_PRODUCT_LOGITECH_QUICKCAMPRO 0x0810 /* QuickCam Pro */
+#define USB_PRODUCT_LOGITECH_WEBCAMC100 0X0817 /* Webcam C100 */
#define USB_PRODUCT_LOGITECH_QUICKCAMEXP 0x0840 /* QuickCam Express */
#define USB_PRODUCT_LOGITECH_QUICKCAM 0x0850 /* QuickCam */
#define USB_PRODUCT_LOGITECH_QUICKCAMPRO3 0x0990 /* QuickCam Pro 9000 */
@@ -2099,11 +2496,14 @@
#define USB_PRODUCT_LOGITEC_RT2870_1 0x0162 /* RT2870 */
#define USB_PRODUCT_LOGITEC_RT2870_2 0x0163 /* RT2870 */
#define USB_PRODUCT_LOGITEC_RT2870_3 0x0164 /* RT2870 */
+#define USB_PRODUCT_LOGITEC_LANW300NU2 0x0166 /* LAN-W300N/U2 */
+#define USB_PRODUCT_LOGITEC_LANW150NU2 0x0168 /* LAN-W150N/U2 */
/* Longcheer Holdings, Ltd. products */
#define USB_PRODUCT_LONGCHEER_WM66 0x6061 /* Longcheer WM66 HSDPA */
#define USB_PRODUCT_LONGCHEER_W14 0x9603 /* Mobilcom W14 */
#define USB_PRODUCT_LONGCHEER_DISK 0xf000 /* Driver disk */
+#define USB_PRODUCT_LONGCHEER_XSSTICK 0x9605 /* 4G Systems XSStick P14 */
/* Lucent products */
@@ -2115,11 +2515,262 @@
/* Macally products */
#define USB_PRODUCT_MACALLY_MOUSE1 0x0101 /* mouse */
+/* Mag-Tek products */
+#define USB_PRODUCT_MAGTEK_USBSWIPE 0x0002 /* USB Mag Stripe Swipe Reader */
+
/* Marvell Technology Group, Ltd. products */
#define USB_PRODUCT_MARVELL_SHEEVAPLUG 0x9e8f /* SheevaPlug serial interface */
-
+
/* Matrix Orbital products */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0100 0x0100 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0101 0x0101 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0102 0x0102 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0103 0x0103 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0104 0x0104 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0105 0x0105 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0106 0x0106 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0107 0x0107 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0108 0x0108 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0109 0x0109 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010A 0x010a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010B 0x010b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010C 0x010c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010D 0x010d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010E 0x010e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010F 0x010f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0110 0x0110 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0111 0x0111 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0112 0x0112 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0113 0x0113 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0114 0x0114 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0115 0x0115 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0116 0x0116 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0117 0x0117 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0118 0x0118 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0119 0x0119 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011A 0x011a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011B 0x011b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011C 0x011c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011D 0x011d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011E 0x011e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011F 0x011f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0120 0x0120 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0121 0x0121 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0122 0x0122 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0123 0x0123 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0124 0x0124 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0125 0x0125 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0126 0x0126 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0128 0x0128 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0129 0x0129 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012A 0x012a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012B 0x012b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012D 0x012d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012E 0x012e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012F 0x012f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0130 0x0130 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0131 0x0131 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0132 0x0132 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0133 0x0133 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0134 0x0134 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0135 0x0135 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0136 0x0136 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0137 0x0137 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0138 0x0138 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0139 0x0139 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013A 0x013a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013B 0x013b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013C 0x013c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013D 0x013d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013E 0x013e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013F 0x013f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0140 0x0140 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0141 0x0141 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0142 0x0142 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0143 0x0143 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0144 0x0144 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0145 0x0145 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0146 0x0146 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0147 0x0147 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0148 0x0148 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0149 0x0149 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014A 0x014a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014B 0x014b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014C 0x014c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014D 0x014d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014E 0x014e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014F 0x014f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0150 0x0150 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0151 0x0151 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0152 0x0152 /* FTDI compatible adapter */
#define USB_PRODUCT_MATRIXORBITAL_MOUA 0x0153 /* Martrix Orbital MOU-Axxxx LCD displays */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0159 0x0159 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015A 0x015a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015B 0x015b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015C 0x015c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015D 0x015d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015E 0x015e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015F 0x015f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0160 0x0160 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0161 0x0161 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0162 0x0162 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0163 0x0163 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0164 0x0164 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0165 0x0165 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0166 0x0166 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0167 0x0167 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0168 0x0168 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0169 0x0169 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016A 0x016a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016B 0x016b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016C 0x016c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016D 0x016d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016E 0x016e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016F 0x016f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0170 0x0170 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0171 0x0171 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0172 0x0172 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0173 0x0173 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0174 0x0174 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0175 0x0175 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0176 0x0176 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0177 0x0177 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0178 0x0178 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0179 0x0179 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017A 0x017a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017B 0x017b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017C 0x017c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017D 0x017d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017E 0x017e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017F 0x017f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0180 0x0180 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0181 0x0181 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0182 0x0182 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0183 0x0183 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0184 0x0184 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0185 0x0185 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0186 0x0186 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0187 0x0187 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0188 0x0188 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0189 0x0189 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018A 0x018a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018B 0x018b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018C 0x018c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018D 0x018d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018E 0x018e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018F 0x018f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0190 0x0190 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0191 0x0191 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0192 0x0192 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0193 0x0193 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0194 0x0194 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0195 0x0195 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0196 0x0196 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0197 0x0197 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0198 0x0198 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0199 0x0199 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019A 0x019a /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019B 0x019b /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019C 0x019c /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019D 0x019d /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019E 0x019e /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019F 0x019f /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A0 0x01a0 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A1 0x01a1 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A2 0x01a2 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A3 0x01a3 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A4 0x01a4 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A5 0x01a5 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A6 0x01a6 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A7 0x01a7 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A8 0x01a8 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A9 0x01a9 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AA 0x01aa /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AB 0x01ab /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AC 0x01ac /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AD 0x01ad /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AE 0x01ae /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AF 0x01af /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B0 0x01b0 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B1 0x01b1 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B2 0x01b2 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B3 0x01b3 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B4 0x01b4 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B5 0x01b5 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B6 0x01b6 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B7 0x01b7 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B8 0x01b8 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B9 0x01b9 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BA 0x01ba /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BB 0x01bb /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BC 0x01bc /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BD 0x01bd /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BE 0x01be /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BF 0x01bf /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C0 0x01c0 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C1 0x01c1 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C2 0x01c2 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C3 0x01c3 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C4 0x01c4 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C5 0x01c5 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C6 0x01c6 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C7 0x01c7 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C8 0x01c8 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C9 0x01c9 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CA 0x01ca /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CB 0x01cb /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CC 0x01cc /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CD 0x01cd /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CE 0x01ce /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CF 0x01cf /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D0 0x01d0 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D1 0x01d1 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D2 0x01d2 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D3 0x01d3 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D4 0x01d4 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D5 0x01d5 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D6 0x01d6 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D7 0x01d7 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D8 0x01d8 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D9 0x01d9 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DA 0x01da /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DB 0x01db /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DC 0x01dc /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DD 0x01dd /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DE 0x01de /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DF 0x01df /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E0 0x01e0 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E1 0x01e1 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E2 0x01e2 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E3 0x01e3 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E4 0x01e4 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E5 0x01e5 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E6 0x01e6 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E7 0x01e7 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E8 0x01e8 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E9 0x01e9 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EA 0x01ea /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EB 0x01eb /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EC 0x01ec /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01ED 0x01ed /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EE 0x01ee /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EF 0x01ef /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F0 0x01f0 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F1 0x01f1 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F2 0x01f2 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F3 0x01f3 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F4 0x01f4 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F5 0x01f5 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F6 0x01f6 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F7 0x01f7 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F8 0x01f8 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F9 0x01f9 /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FA 0x01fa /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FB 0x01fb /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FC 0x01fc /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FD 0x01fd /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FE 0x01fe /* FTDI compatible adapter */
+#define USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FF 0x01ff /* FTDI compatible adapter */
/* MCT Corp. */
#define USB_PRODUCT_MCT_HUB0100 0x0100 /* Hub */
@@ -2127,6 +2778,12 @@
#define USB_PRODUCT_MCT_USB232 0x0210 /* USB-232 Interface */
#define USB_PRODUCT_MCT_SITECOM_USB232 0x0230 /* Sitecom USB-232 Products */
+/* Medeli */
+#define USB_PRODUCT_MEDELI_DD305 0x5011 /* DD305 Digital Drum Set */
+
+/* MediaTek, Inc. */
+#define USB_PRODUCT_MEDIATEK_MTK3329 0x3329 /* MTK II GPS Receiver */
+
/* Meizu Electronics */
#define USB_PRODUCT_MEIZU_M6_SL 0x0140 /* MiniPlayer M6 (SL) */
@@ -2151,14 +2808,19 @@
#define USB_PRODUCT_MELCO_WLRUCG 0x0116 /* WLR-UC-G */
#define USB_PRODUCT_MELCO_WLRUCGAOSS 0x0119 /* WLR-UC-G-AOSS */
#define USB_PRODUCT_MELCO_WLIUCAG300N 0x012e /* WLI-UC-AG300N */
+#define USB_PRODUCT_MELCO_WLIUCG 0x0137 /* WLI-UC-G */
#define USB_PRODUCT_MELCO_RT2870_1 0x0148 /* RT2870 */
#define USB_PRODUCT_MELCO_RT2870_2 0x0150 /* RT2870 */
#define USB_PRODUCT_MELCO_WLIUCGN 0x015d /* WLI-UC-GN */
+#define USB_PRODUCT_MELCO_WLIUCG301N 0x016f /* WLI-UC-G301N */
+#define USB_PRODUCT_MELCO_WLIUCGNM 0x01a2 /* WLI-UC-GNM */
+#define USB_PRODUCT_MELCO_WLIUCGNM2 0x01ee /* WLI-UC-GNM2 */
/* Merlin products */
#define USB_PRODUCT_MERLIN_V620 0x1110 /* Merlin V620 */
/* MetaGeek products */
+#define USB_PRODUCT_METAGEEK_TELLSTICK 0x0c30 /* FTDI compatible adapter */
#define USB_PRODUCT_METAGEEK_WISPY1B 0x083e /* MetaGeek Wi-Spy */
#define USB_PRODUCT_METAGEEK_WISPY24X 0x083f /* MetaGeek Wi-Spy 2.4x */
#define USB_PRODUCT_METAGEEK2_WISPYDBX 0x5000 /* MetaGeek Wi-Spy DBx */
@@ -2172,7 +2834,7 @@
/* MEI products */
#define USB_PRODUCT_MEI_CASHFLOW_SC 0x1100 /* Cashflow-SC Cash Acceptor */
-#define USB_PRODUCT_MEI_S2000 0x1101 /* Seies 2000 Combo Acceptor */
+#define USB_PRODUCT_MEI_S2000 0x1101 /* Series 2000 Combo Acceptor */
/* Micro Star International products */
#define USB_PRODUCT_MSI_BT_DONGLE 0x1967 /* Bluetooth USB dongle */
@@ -2196,6 +2858,9 @@
#define USB_PRODUCT_MSI_RT2573_3 0xa861 /* RT2573 */
#define USB_PRODUCT_MSI_RT2573_4 0xa874 /* RT2573 */
+/* Micron products */
+#define USB_PRODUCT_MICRON_REALSSD 0x0655 /* Real SSD eUSB */
+
/* Microsoft products */
#define USB_PRODUCT_MICROSOFT_SIDEPREC 0x0008 /* SideWinder Precision Pro */
#define USB_PRODUCT_MICROSOFT_INTELLIMOUSE 0x0009 /* IntelliMouse */
@@ -2238,7 +2903,9 @@
#define USB_PRODUCT_MICROTUNE_BT_DONGLE 0x1000 /* Bluetooth USB dongle */
/* Midiman products */
-#define USB_PRODUCT_MIDIMAN_MIDISPORT2X2 0x1001 /* Midisport 2x2 */
+#define USB_PRODUCT_MAUDIO_MIDISPORT2X2 0x1001 /* Midisport 2x2 */
+#define USB_PRODUCT_MAUDIO_FASTTRACKULTRA 0x2080 /* Fast Track Ultra */
+#define USB_PRODUCT_MAUDIO_FASTTRACKULTRA8R 0x2081 /* Fast Track Ultra 8R */
/* MindsAtWork products */
#define USB_PRODUCT_MINDSATWORK_WALLET 0x0001 /* Digital Wallet */
@@ -2260,12 +2927,17 @@
#define USB_PRODUCT_MOBILEACTION_MA620 0x0620 /* MA-620 Infrared Adapter */
/* Mobility products */
+#define USB_PRODUCT_MOBILITY_USB_SERIAL 0x0202 /* FTDI compatible adapter */
#define USB_PRODUCT_MOBILITY_EA 0x0204 /* Ethernet */
#define USB_PRODUCT_MOBILITY_EASIDOCK 0x0304 /* EasiDock Ethernet */
/* MosChip products */
#define USB_PRODUCT_MOSCHIP_MCS7703 0x7703 /* MCS7703 Serial Port Adapter */
+#define USB_PRODUCT_MOSCHIP_MCS7730 0x7730 /* MCS7730 Ethernet */
+#define USB_PRODUCT_MOSCHIP_MCS7820 0x7820 /* MCS7820 Serial Port Adapter */
#define USB_PRODUCT_MOSCHIP_MCS7830 0x7830 /* MCS7830 Ethernet */
+#define USB_PRODUCT_MOSCHIP_MCS7832 0x7832 /* MCS7832 Ethernet */
+#define USB_PRODUCT_MOSCHIP_MCS7840 0x7840 /* MCS7840 Serial Port Adapter */
/* Motorola products */
#define USB_PRODUCT_MOTOROLA_MC141555 0x1555 /* MC141555 hub controller */
@@ -2278,6 +2950,10 @@
#define USB_PRODUCT_MOTOROLA4_RT2770 0x9031 /* RT2770 */
#define USB_PRODUCT_MOTOROLA4_RT3070 0x9032 /* RT3070 */
+/* MpMan products */
+#define USB_PRODUCT_MPMAN_MPF400_2 0x25a8 /* MPF400 Music Player 2Go */
+#define USB_PRODUCT_MPMAN_MPF400_1 0x36d0 /* MPF400 Music Player 1Go */
+
/* MultiTech products */
#define USB_PRODUCT_MULTITECH_ATLAS 0xf101 /* MT5634ZBA-USB modem */
@@ -2393,6 +3069,7 @@
#define USB_PRODUCT_NOVATEL_U727_2 0x5100 /* Merlin U727 CDMA */
#define USB_PRODUCT_NOVATEL_U760 0x6000 /* Novatel U760 */
#define USB_PRODUCT_NOVATEL_MC760 0x6002 /* Novatel MC760 */
+#define USB_PRODUCT_NOVATEL_MC547 0x7042 /* Novatel MC547 */
#define USB_PRODUCT_NOVATEL2_FLEXPACKGPS 0x0100 /* NovAtel FlexPack GPS receiver */
/* Merlin products */
@@ -2402,6 +3079,10 @@
#define USB_PRODUCT_O2MICRO_OZ776_HUB 0x7761 /* OZ776 hub */
#define USB_PRODUCT_O2MICRO_OZ776_CCID_SC 0x7772 /* OZ776 CCID SC Reader */
+/* Olimex products */
+#define USB_PRODUCT_OLIMEX_ARM_USB_OCD 0x0003 /* FTDI compatible adapter */
+#define USB_PRODUCT_OLIMEX_ARM_USB_OCD_H 0x002b /* FTDI compatible adapter */
+
/* Olympus products */
#define USB_PRODUCT_OLYMPUS_C1 0x0102 /* C-1 Digital Camera */
#define USB_PRODUCT_OLYMPUS_C700 0x0105 /* C-700 Ultra Zoom */
@@ -2429,6 +3110,7 @@
#define USB_PRODUCT_OPTION_GT3GPLUS 0x6600 /* GlobeTrotter 3G+ datacard */
#define USB_PRODUCT_OPTION_GTICON322 0xd033 /* GlobeTrotter Icon322 storage */
#define USB_PRODUCT_OPTION_GTMAX36 0x6701 /* GlobeTrotter Max 3.6 Modem */
+#define USB_PRODUCT_OPTION_GTMAX72 0x6711 /* GlobeTrotter Max 7.2 HSDPA */
#define USB_PRODUCT_OPTION_GTHSDPA 0x6971 /* GlobeTrotter HSDPA */
#define USB_PRODUCT_OPTION_GTMAXHSUPA 0x7001 /* GlobeTrotter HSUPA */
#define USB_PRODUCT_OPTION_GTMAXHSUPAE 0x6901 /* GlobeTrotter HSUPA PCIe */
@@ -2503,9 +3185,42 @@
#define USB_PRODUCT_PANASONIC_SDCAAE 0x1b00 /* MultiMediaCard */
#define USB_PRODUCT_PANASONIC_TYTP50P6S 0x3900 /* TY-TP50P6-S 50in Touch Panel */
+/* Papouch products */
+#define USB_PRODUCT_PAPOUCH_AD4USB 0x8003 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_AP485 0x0101 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_AP485_2 0x0104 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_DRAK5 0x0700 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_DRAK6 0x1000 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_GMSR 0x8005 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_GMUX 0x8004 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_IRAMP 0x0500 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_LEC 0x0300 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_MU 0x8001 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_QUIDO10X1 0x0b00 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_QUIDO2X16 0x0e00 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_QUIDO2X2 0x0a00 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_QUIDO30X3 0x0c00 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_QUIDO3X32 0x0f00 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_QUIDO4X4 0x0900 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_QUIDO60X3 0x0d00 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_QUIDO8X8 0x0800 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_SB232 0x0301 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_SB422 0x0102 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_SB422_2 0x0105 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_SB485 0x0100 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_SB485C 0x0107 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_SB485S 0x0106 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_SB485_2 0x0103 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_SIMUKEY 0x8002 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_TMU 0x0400 /* FTDI compatible adapter */
+#define USB_PRODUCT_PAPOUCH_UPSUSB 0x8000 /* FTDI compatible adapter */
+
/* PARA Industrial products */
#define USB_PRODUCT_PARA_RT3070 0x8888 /* RT3070 */
+/* Simtec Electronics products */
+#define USB_PRODUCT_SIMTEC_ENTROPYKEY 0x0001 /* Entropy Key */
+
/* Pegatron products */
#define USB_PRODUCT_PEGATRON_RT2870 0x0002 /* RT2870 */
#define USB_PRODUCT_PEGATRON_RT3070 0x000c /* RT3070 */
@@ -2555,6 +3270,7 @@
#define USB_PRODUCT_PLANEX2_GWUSMM 0xed02 /* GW-USMM */
#define USB_PRODUCT_PLANEX2_RT2870 0xed06 /* RT2870 */
#define USB_PRODUCT_PLANEX2_GWUSMICRON 0xed14 /* GW-USMicroN */
+#define USB_PRODUCT_PLANEX2_GWUSVALUEEZ 0xed17 /* GW-USValue-EZ */
#define USB_PRODUCT_PLANEX3_GWUS54GZ 0xab10 /* GW-US54GZ */
#define USB_PRODUCT_PLANEX3_GU1000T 0xab11 /* GU-1000T */
#define USB_PRODUCT_PLANEX3_GWUS54MINI 0xab13 /* GW-US54Mini */
@@ -2576,6 +3292,9 @@
/* Portsmith products */
#define USB_PRODUCT_PORTSMITH_EEA 0x3003 /* Express Ethernet */
+/* Posiflex products */
+#define USB_PRODUCT_POSIFLEX_PP7000 0x0300 /* FTDI compatible adapter */
+
/* Primax products */
#define USB_PRODUCT_PRIMAX_G2X300 0x0300 /* G2-200 scanner */
#define USB_PRODUCT_PRIMAX_G2E300 0x0301 /* G2E-300 scanner */
@@ -2598,11 +3317,13 @@
/* Prolific products */
#define USB_PRODUCT_PROLIFIC_PL2301 0x0000 /* PL2301 Host-Host interface */
#define USB_PRODUCT_PROLIFIC_PL2302 0x0001 /* PL2302 Host-Host interface */
+#define USB_PRODUCT_PROLIFIC_MOTOROLA 0x0307 /* Motorola Cable */
#define USB_PRODUCT_PROLIFIC_RSAQ2 0x04bb /* PL2303 Serial (IODATA USB-RSAQ2) */
#define USB_PRODUCT_PROLIFIC_ALLTRONIX_GPRS 0x0609 /* Alltronix ACM003U00 modem */
#define USB_PRODUCT_PROLIFIC_ALDIGA_AL11U 0x0611 /* AlDiga AL-11U modem */
#define USB_PRODUCT_PROLIFIC_MICROMAX_610U 0x0612 /* Micromax 610U */
#define USB_PRODUCT_PROLIFIC_DCU11 0x1234 /* DCU-11 Phone Cable */
+#define USB_PRODUCT_PROLIFIC_UIC_MSR206 0x206a /* UIC MSR206 Card Reader */
#define USB_PRODUCT_PROLIFIC_PL2303 0x2303 /* PL2303 Serial (ATEN/IOGEAR UC232A) */
#define USB_PRODUCT_PROLIFIC_PL2305 0x2305 /* Parallel printer */
#define USB_PRODUCT_PROLIFIC_ATAPI4 0x2307 /* ATAPI-4 Controller */
@@ -2622,6 +3343,9 @@
#define USB_PRODUCT_QCOM_RT2573_3 0x6238 /* RT2573 */
#define USB_PRODUCT_QCOM_RT2870 0x6259 /* RT2870 */
+/* QI-hardware */
+#define USB_PRODUCT_QIHARDWARE_JTAGSERIAL 0x0713 /* FTDI compatible adapter */
+
/* Qisda products */
#define USB_PRODUCT_QISDA_H21_1 0x4512 /* 3G modem */
#define USB_PRODUCT_QISDA_H21_2 0x4523 /* 3G modem */
@@ -2634,6 +3358,10 @@
#define USB_PRODUCT_QUALCOMM2_RWT_FCT 0x3100 /* RWT FCT-CDMA 2000 1xRTT modem */
#define USB_PRODUCT_QUALCOMM2_CDMA_MSM 0x3196 /* CDMA Technologies MSM modem */
#define USB_PRODUCT_QUALCOMM2_AC8700 0x6000 /* AC8700 */
+#define USB_PRODUCT_QUALCOMM2_VW110L 0x1000 /* Vertex Wireless 110L modem */
+#define USB_PRODUCT_QUALCOMM2_SIM5218 0x9000 /* SIM5218 */
+#define USB_PRODUCT_QUALCOMM2_GOBI2000_QDL 0x9204 /* Qualcomm Gobi 2000 QDL */
+#define USB_PRODUCT_QUALCOMM2_GOBI2000 0x9205 /* Qualcomm Gobi 2000 modem */
#define USB_PRODUCT_QUALCOMMINC_CDMA_MSM 0x0001 /* CDMA Technologies MSM modem */
#define USB_PRODUCT_QUALCOMMINC_E0002 0x0002 /* 3G modem */
#define USB_PRODUCT_QUALCOMMINC_E0003 0x0003 /* 3G modem */
@@ -2700,6 +3428,8 @@
#define USB_PRODUCT_QUALCOMMINC_E0078 0x0078 /* 3G modem */
#define USB_PRODUCT_QUALCOMMINC_E0082 0x0082 /* 3G modem */
#define USB_PRODUCT_QUALCOMMINC_E0086 0x0086 /* 3G modem */
+#define USB_PRODUCT_QUALCOMMINC_SURFSTICK 0x0117 /* 1&1 Surf Stick */
+#define USB_PRODUCT_QUALCOMMINC_K3772_Z 0x1179 /* 3G modem */
#define USB_PRODUCT_QUALCOMMINC_ZTE_STOR 0x2000 /* USB ZTE Storage */
#define USB_PRODUCT_QUALCOMMINC_E2002 0x2002 /* 3G modem */
#define USB_PRODUCT_QUALCOMMINC_E2003 0x2003 /* 3G modem */
@@ -2743,6 +3473,7 @@
#define USB_PRODUCT_RALINK_RT3072 0x3072 /* RT3072 */
#define USB_PRODUCT_RALINK_RT3370 0x3370 /* RT3370 */
#define USB_PRODUCT_RALINK_RT3572 0x3572 /* RT3572 */
+#define USB_PRODUCT_RALINK_RT5370 0x5370 /* RT5370 */
#define USB_PRODUCT_RALINK_RT8070 0x8070 /* RT8070 */
#define USB_PRODUCT_RALINK_RT2570_3 0x9020 /* RT2500USB Wireless Adapter */
#define USB_PRODUCT_RALINK_RT2573_2 0x9021 /* RT2501USB Wireless Adapter */
@@ -2753,6 +3484,7 @@
/* ReakTek products */
/* Green House and CompUSA OEM this part */
+#define USB_PRODUCT_REALTEK_DUMMY 0x0000 /* Dummy product */
#define USB_PRODUCT_REALTEK_USB20CRW 0x0158 /* USB20CRW Card Reader */
#define USB_PRODUCT_REALTEK_USBKR100 0x8150 /* USBKR100 USB Ethernet */
#define USB_PRODUCT_REALTEK_RTL8187 0x8187 /* RTL8187 Wireless Adapter */
@@ -2760,6 +3492,13 @@
#define USB_PRODUCT_REALTEK_RTL8187B_1 0x8197 /* RTL8187B Wireless Adapter */
#define USB_PRODUCT_REALTEK_RTL8187B_2 0x8198 /* RTL8187B Wireless Adapter */
+/* RedOctane products */
+#define USB_PRODUCT_REDOCTANE_DUMMY 0x0000 /* Dummy product */
+#define USB_PRODUCT_REDOCTANE_GHMIDI 0x474b /* GH MIDI INTERFACE */
+
+/* Renesas products */
+#define USB_PRODUCT_RENESAS_RX610 0x0053 /* RX610 RX-Stick */
+
/* Ricoh products */
#define USB_PRODUCT_RICOH_VGPVCC2 0x1830 /* VGP-VCC2 Camera */
#define USB_PRODUCT_RICOH_VGPVCC3 0x1832 /* VGP-VCC3 Camera */
@@ -2772,9 +3511,23 @@
#define USB_PRODUCT_REINERSCT_CYBERJACK_ECOM 0x0100 /* e-com cyberJack */
/* Roland products */
+#define USB_PRODUCT_ROLAND_UA100 0x0000 /* UA-100 Audio I/F */
+#define USB_PRODUCT_ROLAND_UM4 0x0002 /* UM-4 MIDI I/F */
+#define USB_PRODUCT_ROLAND_SC8850 0x0003 /* SC-8850 MIDI Synth */
+#define USB_PRODUCT_ROLAND_U8 0x0004 /* U-8 Audio I/F */
+#define USB_PRODUCT_ROLAND_UM2 0x0005 /* UM-2 MIDI I/F */
+#define USB_PRODUCT_ROLAND_SC8820 0x0007 /* SC-8820 MIDI Synth */
+#define USB_PRODUCT_ROLAND_PC300 0x0008 /* PC-300 MIDI Keyboard */
#define USB_PRODUCT_ROLAND_UM1 0x0009 /* UM-1 MIDI I/F */
+#define USB_PRODUCT_ROLAND_SK500 0x000b /* SK-500 MIDI Keyboard */
+#define USB_PRODUCT_ROLAND_SCD70 0x000c /* SC-D70 MIDI Synth */
#define USB_PRODUCT_ROLAND_UM880N 0x0014 /* EDIROL UM-880 MIDI I/F (native) */
#define USB_PRODUCT_ROLAND_UM880G 0x0015 /* EDIROL UM-880 MIDI I/F (generic) */
+#define USB_PRODUCT_ROLAND_SD90 0x0016 /* SD-90 MIDI Synth */
+#define USB_PRODUCT_ROLAND_UM550 0x0023 /* UM-550 MIDI I/F */
+#define USB_PRODUCT_ROLAND_SD20 0x0027 /* SD-20 MIDI Synth */
+#define USB_PRODUCT_ROLAND_SD80 0x0029 /* SD-80 MIDI Synth */
+#define USB_PRODUCT_ROLAND_UA700 0x002b /* UA-700 Audio I/F */
/* Rockfire products */
#define USB_PRODUCT_ROCKFIRE_GAMEPAD 0x2033 /* gamepad 203USB */
@@ -2783,12 +3536,17 @@
#define USB_PRODUCT_RATOC_REXUSB60 0xb000 /* REX-USB60 */
#define USB_PRODUCT_RATOC_REXUSB60F 0xb020 /* REX-USB60F */
+/* RT system products */
+#define USB_PRODUCT_RTSYSTEMS_CT29B 0x9e54 /* FTDI compatible adapter */
+#define USB_PRODUCT_RTSYSTEMS_SERIAL_VX7 0x9e52 /* FTDI compatible adapter */
+
/* Sagem products */
#define USB_PRODUCT_SAGEM_USBSERIAL 0x0027 /* USB-Serial Controller */
#define USB_PRODUCT_SAGEM_XG760A 0x004a /* XG-760A */
#define USB_PRODUCT_SAGEM_XG76NA 0x0062 /* XG-76NA */
/* Samsung products */
+#define USB_PRODUCT_SAMSUNG_WIS09ABGN 0x2018 /* WIS09ABGN Wireless LAN adapter */
#define USB_PRODUCT_SAMSUNG_ML6060 0x3008 /* ML-6060 laser printer */
#define USB_PRODUCT_SAMSUNG_YP_U2 0x5050 /* YP-U2 MP3 Player */
#define USB_PRODUCT_SAMSUNG_YP_U4 0x5092 /* YP-U4 MP3 Player */
@@ -2809,6 +3567,7 @@
#define USB_PRODUCT_SANDISK_SDCZ2_256 0x7104 /* Cruzer Mini 256MB */
#define USB_PRODUCT_SANDISK_SDCZ4_128 0x7112 /* Cruzer Micro 128MB */
#define USB_PRODUCT_SANDISK_SDCZ4_256 0x7113 /* Cruzer Micro 256MB */
+#define USB_PRODUCT_SANDISK_IMAGEMATE_SDDR289 0xb6ba /* ImageMate SDDR-289 */
/* Sanwa Electric Instrument Co., Ltd. products */
#define USB_PRODUCT_SANWA_KB_USB2 0x0701 /* KB-USB2 multimeter cable */
@@ -2820,6 +3579,55 @@
#define USB_PRODUCT_SCANLOGIC_SL11R 0x0002 /* SL11R IDE Adapter */
#define USB_PRODUCT_SCANLOGIC_336CX 0x0300 /* Phantom 336CX - C3 scanner */
+/* Sealevel products */
+#define USB_PRODUCT_SEALEVEL_2101 0x2101 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2102 0x2102 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2103 0x2103 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2104 0x2104 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2106 0x9020 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2201_1 0x2211 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2201_2 0x2221 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2202_1 0x2212 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2202_2 0x2222 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2203_1 0x2213 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2203_2 0x2223 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2401_1 0x2411 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2401_2 0x2421 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2401_3 0x2431 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2401_4 0x2441 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2402_1 0x2412 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2402_2 0x2422 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2402_3 0x2432 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2402_4 0x2442 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2403_1 0x2413 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2403_2 0x2423 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2403_3 0x2433 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2403_4 0x2443 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2801_1 0x2811 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2801_2 0x2821 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2801_3 0x2831 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2801_4 0x2841 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2801_5 0x2851 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2801_6 0x2861 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2801_7 0x2871 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2801_8 0x2881 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2802_1 0x2812 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2802_2 0x2822 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2802_3 0x2832 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2802_4 0x2842 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2802_5 0x2852 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2802_6 0x2862 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2802_7 0x2872 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2802_8 0x2882 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2803_1 0x2813 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2803_2 0x2823 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2803_3 0x2833 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2803_4 0x2843 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2803_5 0x2853 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2803_6 0x2863 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2803_7 0x2873 /* FTDI compatible adapter */
+#define USB_PRODUCT_SEALEVEL_2803_8 0x2883 /* FTDI compatible adapter */
+
/* Senao products */
#define USB_PRODUCT_SENAO_RT2870_3 0x0605 /* RT2870 */
#define USB_PRODUCT_SENAO_RT2870_4 0x0615 /* RT2870 */
@@ -2837,6 +3645,7 @@
/* ShanTou products */
#define USB_PRODUCT_SHANTOU_ST268 0x0268 /* ST268 */
#define USB_PRODUCT_SHANTOU_DM9601 0x9601 /* DM 9601 */
+#define USB_PRODUCT_SHANTOU_ADM8515 0x8515 /* ADM8515 */
/* Shark products */
#define USB_PRODUCT_SHARK_PA 0x0400 /* Pocket Adapter */
@@ -2936,6 +3745,7 @@
#define USB_PRODUCT_SIERRA_E6893 0x6893 /* E6893 */
#define USB_PRODUCT_SIERRA_MC8700 0x68A3 /* MC8700 */
#define USB_PRODUCT_SIERRA_AIRCARD875 0x6820 /* Aircard 875 HSDPA */
+#define USB_PRODUCT_SIERRA_AC313U 0x68aa /* Sierra Wireless AirCard 313U */
#define USB_PRODUCT_SIERRA_TRUINSTALL 0x0fff /* Aircard Tru Installer */
/* Sigmatel products */
@@ -2946,6 +3756,7 @@
/* Also: Omnidirectional Control Technology products */
#define USB_PRODUCT_SIIG_DIGIFILMREADER 0x0004 /* DigiFilm-Combo Reader */
#define USB_PRODUCT_SIIG_WINTERREADER 0x0330 /* WINTERREADER Reader */
+#define USB_PRODUCT_SIIG2_DK201 0x0103 /* FTDI compatible adapter */
#define USB_PRODUCT_SIIG2_USBTOETHER 0x0109 /* USB TO Ethernet */
#define USB_PRODUCT_SIIG2_US2308 0x0421 /* Serial */
@@ -2954,10 +3765,10 @@
#define USB_PRODUCT_SILICOM_GPE 0x0002 /* Psion Gold Port Ethernet */
/* SI Labs */
-#define USB_PRODUCT_SILABS_VSTABI 0x0f91 /* Vstabi */
+#define USB_PRODUCT_SILABS_VSTABI 0x0f91 /* VStabi Controller */
#define USB_PRODUCT_SILABS_ARKHAM_DS101_M 0x1101 /* Arkham DS101 Monitor */
#define USB_PRODUCT_SILABS_ARKHAM_DS101_A 0x1601 /* Arkham DS101 Adapter */
-#define USB_PRODUCT_SILABS_BSM7DUSB 0x800a /* BSM7-D-USB */
+#define USB_PRODUCT_SILABS_BSM7DUSB 0x800a /* SPORTident BSM7-D USB */
#define USB_PRODUCT_SILABS_POLOLU 0x803b /* Pololu Serial */
#define USB_PRODUCT_SILABS_CYGNAL_DEBUG 0x8044 /* Cygnal Debug Adapter */
#define USB_PRODUCT_SILABS_SB_PARAMOUNT_ME 0x8043 /* Software Bisque Paramount ME */
@@ -2966,6 +3777,7 @@
#define USB_PRODUCT_SILABS_ARGUSISP 0x8066 /* Argussoft ISP */
#define USB_PRODUCT_SILABS_IMS_USB_RS422 0x806f /* IMS USB-RS422 */
#define USB_PRODUCT_SILABS_CRUMB128 0x807a /* Crumb128 board */
+#define USB_PRODUCT_SILABS_OPTRIS_MSPRO 0x80c4 /* Optris MSpro LT Thermometer */
#define USB_PRODUCT_SILABS_DEGREE 0x80ca /* Degree Controls Inc */
#define USB_PRODUCT_SILABS_TRACIENT 0x80dd /* Tracient RFID */
#define USB_PRODUCT_SILABS_TRAQMATE 0x80ed /* Track Systems Traqmate */
@@ -2976,10 +3788,13 @@
#define USB_PRODUCT_SILABS_WMRBATT 0x814a /* WMR RIGblaster Plug&Play */
#define USB_PRODUCT_SILABS_WMRRIGBLASTER 0x814a /* WMR RIGblaster Plug&Play */
#define USB_PRODUCT_SILABS_WMRRIGTALK 0x814b /* WMR RIGtalk RT1 */
+#define USB_PRODUCT_SILABS_B_G_H3000 0x8156 /* B&G H3000 Data Cable */
#define USB_PRODUCT_SILABS_HELICOM 0x815e /* Helicomm IP-Link 1220-DVM */
+#define USB_PRODUCT_SILABS_HAMLINKUSB 0x815f /* Timewave HamLinkUSB */
#define USB_PRODUCT_SILABS_AVIT_USB_TTL 0x818b /* AVIT Research USB-TTL */
-#define USB_PRODUCT_SILABS_MJS_TOSLINK 0x819f /* MJS USB-TOSLINk */
+#define USB_PRODUCT_SILABS_MJS_TOSLINK 0x819f /* MJS USB-TOSLINK */
#define USB_PRODUCT_SILABS_WAVIT 0x81a6 /* ThinkOptics WavIt */
+#define USB_PRODUCT_SILABS_MULTIPLEX_RC 0x81a9 /* Multiplex RC adapter */
#define USB_PRODUCT_SILABS_MSD_DASHHAWK 0x81ac /* MSD DashHawk */
#define USB_PRODUCT_SILABS_INSYS_MODEM 0x81ad /* INSYS Modem */
#define USB_PRODUCT_SILABS_LIPOWSKY_JTAG 0x81c8 /* Lipowsky Baby-JTAG */
@@ -2990,15 +3805,24 @@
#define USB_PRODUCT_SILABS_LIPOWSKY_HARP 0x8218 /* Lipowsky HARP-1 */
#define USB_PRODUCT_SILABS_C2_EDGE_MODEM 0x822b /* Commander 2 EDGE(GSM) Modem */
#define USB_PRODUCT_SILABS_CYGNAL_GPS 0x826b /* Cygnal Fasttrax GPS */
-#define USB_PRODUCT_SILABS_TELEGESYS_ETRX2 0x8293 /* Telegesys ETRX2USB */
+#define USB_PRODUCT_SILABS_TELEGESIS_ETRX2 0x8293 /* Telegesis ETRX2USB */
#define USB_PRODUCT_SILABS_PROCYON_AVS 0x82f9 /* Procyon AVS */
#define USB_PRODUCT_SILABS_MC35PU 0x8341 /* MC35pu */
#define USB_PRODUCT_SILABS_CYGNAL 0x8382 /* Cygnal */
#define USB_PRODUCT_SILABS_AMBER_AMB2560 0x83a8 /* Amber Wireless AMB2560 */
+#define USB_PRODUCT_SILABS_DEKTEK_DTAPLUS 0x83d8 /* DekTec DTA Plus VHF/UHF Booster */
#define USB_PRODUCT_SILABS_KYOCERA_GPS 0x8411 /* Kyocera GPS */
+#define USB_PRODUCT_SILABS_IRZ_SG10 0x8418 /* IRZ SG-10 GSM/GPRS Modem */
#define USB_PRODUCT_SILABS_BEI_VCP 0x846e /* BEI USB Sensor (VCP) */
+#define USB_PRODUCT_SILABS_BALLUFF_RFID 0x8477 /* Balluff RFID reader */
+#define USB_PRODUCT_SILABS_AC_SERV_IBUS 0x85ea /* AC-Services IBUS Interface */
+#define USB_PRODUCT_SILABS_AC_SERV_CIS 0x85eb /* AC-Services CIS-IBUS */
+#define USB_PRODUCT_SILABS_AC_SERV_CAN 0x8664 /* AC-Services CAN Interface */
+#define USB_PRODUCT_SILABS_AC_SERV_OBD 0x8665 /* AC-Services OBD Interface */
#define USB_PRODUCT_SILABS_CP2102 0xea60 /* SILABS USB UART */
#define USB_PRODUCT_SILABS_CP210X_2 0xea61 /* CP210x Serial */
+#define USB_PRODUCT_SILABS_CP210X_3 0xea70 /* CP210x Serial */
+#define USB_PRODUCT_SILABS_CP210X_4 0xea80 /* CP210x Serial */
#define USB_PRODUCT_SILABS_INFINITY_MIC 0xea71 /* Infinity GPS-MIC-1 Radio Monophone */
#define USB_PRODUCT_SILABS_USBSCOPE50 0xf001 /* USBscope50 */
#define USB_PRODUCT_SILABS_USBWAVE12 0xf002 /* USBwave12 */
@@ -3023,6 +3847,7 @@
/* Sitecom Europe products */
#define USB_PRODUCT_SITECOMEU_RT2870_1 0x0017 /* RT2870 */
#define USB_PRODUCT_SITECOMEU_WL168V1 0x000d /* WL-168 v1 */
+#define USB_PRODUCT_SITECOMEU_LN030 0x0021 /* MCS7830 */
#define USB_PRODUCT_SITECOMEU_WL168V4 0x0028 /* WL-168 v4 */
#define USB_PRODUCT_SITECOMEU_RT2870_2 0x002b /* RT2870 */
#define USB_PRODUCT_SITECOMEU_RT2870_3 0x002c /* RT2870 */
@@ -3065,6 +3890,7 @@
#define USB_PRODUCT_SMC2_2020HUB 0x2020 /* USB Hub */
#define USB_PRODUCT_SMC2_2514HUB 0x2514 /* USB Hub */
#define USB_PRODUCT_SMC3_2662WUSB 0xa002 /* 2662W-AR Wireless */
+#define USB_PRODUCT_SMC2_LAN9514_ETH 0xec00 /* USB/Ethernet */
/* SOHOware products */
#define USB_PRODUCT_SOHOWARE_NUB100 0x9100 /* 10/100 USB Ethernet */
@@ -3107,6 +3933,10 @@
#define USB_PRODUCT_SPARKLAN_RT2870_1 0x0006 /* RT2870 */
#define USB_PRODUCT_SPARKLAN_RT3070 0x0010 /* RT3070 */
+/* Soundgraph products */
+#define USB_PRODUCT_SOUNDGRAPH_IMON_VFD 0x0044 /* Antec Veris Elite VFD Panel, Knob, and Remote */
+#define USB_PRODUCT_SOUNDGRAPH_SSTONE_LC16 0xffdc /* Silverstone LC16 VFD Panel, Knob, and Remote */
+
/* Speed Dragon Multimedia products */
#define USB_PRODUCT_SPEEDDRAGON_MS3303H 0x110b /* MS3303H Serial */
@@ -3133,13 +3963,10 @@
#define USB_PRODUCT_STELERA_E1011 0x1011 /* 3G modem */
#define USB_PRODUCT_STELERA_E1012 0x1012 /* 3G modem */
-/* MpMan products */
-#define USB_PRODUCT_MPMAN_MPF400_1 0x36d0 /* MPF400 Music Player 1Go */
-#define USB_PRODUCT_MPMAN_MPF400_2 0x25a8 /* MPF400 Music Player 2Go */
-
/* STMicroelectronics products */
#define USB_PRODUCT_STMICRO_BIOCPU 0x2016 /* Biometric Coprocessor */
#define USB_PRODUCT_STMICRO_COMMUNICATOR 0x7554 /* USB Communicator */
+#define USB_PRODUCT_STMICRO_ST72682 0xfada /* USB 2.0 Flash drive controller */
/* STSN products */
#define USB_PRODUCT_STSN_STSN0001 0x0001 /* Internet Access Device */
@@ -3159,8 +3986,12 @@
#define USB_PRODUCT_SUN_MOUSE 0x0100 /* Type 6 USB mouse */
#define USB_PRODUCT_SUN_KBD_HUB 0x100e /* Kbd Hub */
+/* Sunplus Innovation Technology Inc. products */
+#define USB_PRODUCT_SUNPLUS_USBMOUSE 0x0007 /* USB Optical Mouse */
+
/* Super Top products */
#define USB_PRODUCT_SUPERTOP_IDE 0x6600 /* USB-IDE */
+#define USB_PRODUCT_SUPERTOP_FLASHDRIVE 0x121c /* extrememory Snippy */
/* Syntech products */
#define USB_PRODUCT_SYNTECH_CPT8001C 0x0001 /* CPT-8001C Barcode scanner */
@@ -3169,6 +4000,20 @@
/* Teclast products */
#define USB_PRODUCT_TECLAST_TLC300 0x3203 /* USB Media Player */
+/* Testo products */
+#define USB_PRODUCT_TESTO_USB_INTERFACE 0x0001 /* FTDI compatible adapter */
+
+/* TexTech products */
+#define USB_PRODUCT_TEXTECH_DUMMY 0x0000 /* Dummy product */
+#define USB_PRODUCT_TEXTECH_U2M_1 0x0101 /* Textech USB MIDI cable */
+#define USB_PRODUCT_TEXTECH_U2M_2 0x1806 /* Textech USB MIDI cable */
+
+/* The Mobility Lab products */
+#define USB_PRODUCT_TML_USB_SERIAL 0x0064 /* FTDI compatible adapter */
+
+/* Thurlby Thandar Instrument products */
+#define USB_PRODUCT_TTI_QL355P 0x03e8 /* FTDI compatible adapter */
+
/* Supra products */
#define USB_PRODUCT_DIAMOND2_SUPRAEXPRESS56K 0x07da /* Supra Express 56K modem */
#define USB_PRODUCT_DIAMOND2_SUPRA2890 0x0b4a /* SupraMax 2890 56K Modem */
@@ -3242,6 +4087,7 @@
#define USB_PRODUCT_TOSHIBA_RT3070 0x0a07 /* RT3070 */
#define USB_PRODUCT_TOSHIBA_G450 0x0d45 /* G450 modem */
#define USB_PRODUCT_TOSHIBA_HSDPA 0x1302 /* G450 modem */
+#define USB_PRODUCT_TOSHIBA_TRANSMEMORY 0x6545 /* USB ThumbDrive */
/* Trek Technology products */
#define USB_PRODUCT_TREK_THUMBDRIVE 0x1111 /* ThumbDrive */
@@ -3288,6 +4134,9 @@
/* Universal Access products */
#define USB_PRODUCT_UNIACCESS_PANACHE 0x0101 /* Panache Surf USB ISDN Adapter */
+/* Unknown products */
+#define USB_PRODUCT_UNKNOWN4_NF_RIC 0x0001 /* FTDI compatible adapter */
+
/* USI products */
#define USB_PRODUCT_USI_MC60 0x10c5 /* MC60 Serial */
@@ -3298,9 +4147,15 @@
/* VIA Technologies products */
#define USB_PRODUCT_VIA_USB2IDEBRIDGE 0x6204 /* USB 2.0 IDE Bridge */
+/* VIA Labs */
+#define USB_PRODUCT_VIALABS_USB30SATABRIDGE 0x0700 /* USB 3.0 SATA Bridge */
+
/* Vaisala products */
#define USB_PRODUCT_VAISALA_CABLE 0x0200 /* USB Interface cable */
+/* Vertex products */
+#define USB_PRODUCT_VERTEX_VW110L 0x0100 /* Vertex VW110L modem */
+
/* VidzMedia products */
#define USB_PRODUCT_VIDZMEDIA_MONSTERTV 0x4fb1 /* MonsterTV P2H */
@@ -3330,12 +4185,18 @@
#define USB_PRODUCT_WACOM_INTUOSA5 0x0021 /* Intuos A5 */
#define USB_PRODUCT_WACOM_GD0912U 0x0022 /* Intuos 9x12 Graphics Tablet */
+/* WAGO Kontakttechnik GmbH products */
+#define USB_PRODUCT_WAGO_SERVICECABLE 0x07a6 /* USB Service Cable 750-923 */
+
/* WaveSense products */
#define USB_PRODUCT_WAVESENSE_JAZZ 0xaaaa /* Jazz blood glucose meter */
/* WCH products */
#define USB_PRODUCT_WCH_CH341SER 0x5523 /* CH341/CH340 USB-Serial Bridge */
+#define USB_PRODUCT_WCH2_DUMMY 0x0000 /* Dummy product */
+#define USB_PRODUCT_WCH2_CH341SER_2 0x5523 /* CH341/CH340 USB-Serial Bridge */
#define USB_PRODUCT_WCH2_CH341SER 0x7523 /* CH341/CH340 USB-Serial Bridge */
+#define USB_PRODUCT_WCH2_U2M 0X752d /* CH345 USB2.0-MIDI */
/* Western Digital products */
#define USB_PRODUCT_WESTERN_COMBO 0x0200 /* Firewire USB Combo */
@@ -3344,6 +4205,15 @@
#define USB_PRODUCT_WESTERN_MYBOOK 0x0901 /* MyBook External HDD */
#define USB_PRODUCT_WESTERN_MYPASSWORD 0x0704 /* MyPassword External HDD */
+/* WeTelecom products */
+#define USB_PRODUCT_WETELECOM_WM_D200 0x6801 /* WM-D200 */
+
+/* WIENER Plein & Baus GmbH products */
+#define USB_PRODUCT_WIENERPLEINBAUS_PL512 0x0010 /* PL512 PSU */
+#define USB_PRODUCT_WIENERPLEINBAUS_RCM 0x0011 /* RCM Remote Control */
+#define USB_PRODUCT_WIENERPLEINBAUS_MPOD 0x0012 /* MPOD PSU */
+#define USB_PRODUCT_WIENERPLEINBAUS_CML 0x0015 /* CML Data Logger */
+
/* Windbond Electronics */
#define USB_PRODUCT_WINBOND_UH104 0x5518 /* 4-port USB Hub */
@@ -3371,10 +4241,11 @@
/* Yamaha products */
#define USB_PRODUCT_YAMAHA_UX256 0x1000 /* UX256 MIDI I/F */
#define USB_PRODUCT_YAMAHA_UX96 0x1008 /* UX96 MIDI I/F */
+#define USB_PRODUCT_YAMAHA_RPU200 0x3104 /* RP-U200 */
#define USB_PRODUCT_YAMAHA_RTA54I 0x4000 /* NetVolante RTA54i Broadband&ISDN Router */
-#define USB_PRODUCT_YAMAHA_RTA55I 0x4004 /* NetVolante RTA55i Broadband VoIP Router */
#define USB_PRODUCT_YAMAHA_RTW65B 0x4001 /* NetVolante RTW65b Broadband Wireless Router */
#define USB_PRODUCT_YAMAHA_RTW65I 0x4002 /* NetVolante RTW65i Broadband&ISDN Wireless Router */
+#define USB_PRODUCT_YAMAHA_RTA55I 0x4004 /* NetVolante RTA55i Broadband VoIP Router */
/* Yano products */
#define USB_PRODUCT_YANO_U640MO 0x0101 /* U640MO-03 */
diff --git a/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h b/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
index 6bd20f55..4a0c6b94 100644
--- a/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
+++ b/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h
@@ -24,13 +24,6 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -299,6 +292,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"WUG2700",
},
{
+ USB_VENDOR_ACTON, USB_PRODUCT_ACTON_SPECTRAPRO,
+ 0,
+ "Acton Research Corp.",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_USB320_EC,
0,
"Accton Technology",
@@ -773,6 +772,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"CDMA Wireless PC Card",
},
{
+ USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_USB308,
+ 0,
+ "AirPrime, Inc.",
+ "USB308 HSPA+ USB Modem",
+ },
+ {
+ USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_AC313U,
+ 0,
+ "AirPrime, Inc.",
+ "Sierra Wireless AirCard 313U",
+ },
+ {
USB_VENDOR_AIRTIES, USB_PRODUCT_AIRTIES_RT3070,
0,
"AirTies",
@@ -797,6 +808,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Kbd Hub",
},
{
+ USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_DUMMY,
+ 0,
+ "Alcor Micro",
+ "Dummy product",
+ },
+ {
USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_SDCR_6335,
0,
"Alcor Micro",
@@ -809,6 +826,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"SD/MMC Card Reader",
},
{
+ USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_SDCR_6366,
+ 0,
+ "Alcor Micro",
+ "SD/MMC Card Reader",
+ },
+ {
USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_TRANSCEND,
0,
"Alcor Micro",
@@ -887,6 +910,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"ASC495 Speakers",
},
{
+ USB_VENDOR_ALTI2, USB_PRODUCT_ALTI2_N3,
+ 0,
+ "Alti-2 products",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_ALLIEDTELESYN, USB_PRODUCT_ALLIEDTELESYN_ATUSB100,
0,
"Allied Telesyn International",
@@ -1031,6 +1060,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT2870",
},
{
+ USB_VENDOR_ANALOGDEVICES, USB_PRODUCT_ANALOGDEVICES_GNICE,
+ 0,
+ "Analog Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ANALOGDEVICES, USB_PRODUCT_ANALOGDEVICES_GNICEPLUS,
+ 0,
+ "Analog Devices",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_SERIAL,
0,
"Anchor Chips",
@@ -1079,6 +1120,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Uninterruptible Power Supply",
},
{
+ USB_VENDOR_APPLE, USB_PRODUCT_APPLE_DUMMY,
+ 0,
+ "Apple Computer",
+ "Dummy product",
+ },
+ {
USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IMAC_KBD,
0,
"Apple Computer",
@@ -1259,6 +1306,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"iPhone 4",
},
{
+ USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_5,
+ 0,
+ "Apple Computer",
+ "iPhone 5",
+ },
+ {
USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPAD,
0,
"Apple Computer",
@@ -1319,6 +1372,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"AX88772A USB 2.0 10/100 Ethernet",
},
{
+ USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772B,
+ 0,
+ "ASIX Electronics",
+ "AX88772B USB 2.0 10/100 Ethernet",
+ },
+ {
+ USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772B_1,
+ 0,
+ "ASIX Electronics",
+ "AX88772B USB 2.0 10/100 Ethernet",
+ },
+ {
USB_VENDOR_ASUS2, USB_PRODUCT_ASUS2_USBN11,
0,
"ASUS",
@@ -1433,6 +1498,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT2500USB Wireless Adapter",
},
{
+ USB_VENDOR_ASUS, USB_PRODUCT_ASUS_USB_N53,
+ 0,
+ "ASUSTeK Computer",
+ "ASUS Black Diamond Dual Band USB-N53",
+ },
+ {
USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC1284,
0,
"ATEN International",
@@ -1607,12 +1678,114 @@ const struct usb_knowndev usb_knowndevs[] = {
"Card reader",
},
{
+ USB_VENDOR_BAYER, USB_PRODUCT_BAYER_CONTOUR_CABLE,
+ 0,
+ "Bayer",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USOTL4,
0,
"B&B Electronics",
"RS-422/485",
},
{
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_232USB9M,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_485USB9F_2W,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_485USB9F_4W,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_485USBTB_2W,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_485USBTB_4W,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_TTL3USB9M,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_TTL5USB9M,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USO9ML2,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USO9ML2DR,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USO9ML2DR_2,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USOPTL4,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USOPTL4DR,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USOPTL4DR2,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USPTL4,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USTL4,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_ZZ_PROG1_USB,
+ 0,
+ "B&B Electronics",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D6050,
0,
"Belkin Components",
@@ -1763,6 +1936,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"F5D8055",
},
{
+ USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D8055V2,
+ 0,
+ "Belkin Components",
+ "F5D8055 v2",
+ },
+ {
USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3,
0,
"Belkin Components",
@@ -2093,6 +2272,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"WUSBF54G",
},
{
+ USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_AE1000,
+ 0,
+ "Cisco-Linksys",
+ "AE1000",
+ },
+ {
USB_VENDOR_CISCOLINKSYS2, USB_PRODUCT_CISCOLINKSYS2_RT3070,
0,
"Cisco-Linksys",
@@ -2105,10 +2290,46 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT3070",
},
{
+ USB_VENDOR_CLIPSAL, USB_PRODUCT_CLIPSAL_560884,
+ 0,
+ "Clipsal",
+ "560884 C-Bus Audio Matrix Switch",
+ },
+ {
+ USB_VENDOR_CLIPSAL, USB_PRODUCT_CLIPSAL_5500PACA,
+ 0,
+ "Clipsal",
+ "5500PACA C-Bus Pascal Automation Controller",
+ },
+ {
+ USB_VENDOR_CLIPSAL, USB_PRODUCT_CLIPSAL_5800PC,
+ 0,
+ "Clipsal",
+ "5800PC C-Bus Wireless Interface",
+ },
+ {
USB_VENDOR_CLIPSAL, USB_PRODUCT_CLIPSAL_5500PCU,
0,
"Clipsal",
- "5500PCU C-Bus",
+ "5500PCU C-Bus Interface",
+ },
+ {
+ USB_VENDOR_CLIPSAL, USB_PRODUCT_CLIPSAL_5000CT2,
+ 0,
+ "Clipsal",
+ "5000CT2 C-Bus Touch Screen",
+ },
+ {
+ USB_VENDOR_CLIPSAL, USB_PRODUCT_CLIPSAL_C5000CT2,
+ 0,
+ "Clipsal",
+ "C5000CT2 C-Bus Touch Screen",
+ },
+ {
+ USB_VENDOR_CLIPSAL, USB_PRODUCT_CLIPSAL_L51xx,
+ 0,
+ "Clipsal",
+ "L51xx C-Bus Dimmer",
},
{
USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CNU510,
@@ -2291,6 +2512,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"QuickCam",
},
{
+ USB_VENDOR_CONTEC, USB_PRODUCT_CONTEC_COM1USBH,
+ 0,
+ "Contec products",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_COREGA, USB_PRODUCT_COREGA_ETHER_USB_T,
0,
"Corega",
@@ -2393,6 +2620,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"FEther USB-TXC",
},
{
+ USB_VENDOR_CORSAIR, USB_PRODUCT_CORSAIR_K60,
+ 0,
+ "Corsair",
+ "Corsair Vengeance K60 keyboard",
+ },
+ {
USB_VENDOR_CREATIVE, USB_PRODUCT_CREATIVE_NOMAD_II,
0,
"Creative Labs",
@@ -2471,6 +2704,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Broadband Wireless modem",
},
{
+ USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_UM150,
+ 0,
+ "Curitel Communications Inc",
+ "EVDO modem",
+ },
+ {
USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_UM175,
0,
"Curitel Communications Inc",
@@ -2771,6 +3010,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"10/100 Ethernet",
},
{
+ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100C1,
+ 0,
+ "D-Link",
+ "DUB-E100 rev C1",
+ },
+ {
USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX4,
0,
"D-Link",
@@ -3083,6 +3328,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"EW-7718",
},
{
+ USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_EW7811UN,
+ 0,
+ "Edimax",
+ "EW-7811Un",
+ },
+ {
USB_VENDOR_EGALAX, USB_PRODUCT_EGALAX_TPANEL,
0,
"eGalax, Inc.",
@@ -3101,6 +3352,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"Touch Panel",
},
{
+ USB_VENDOR_EGO, USB_PRODUCT_EGO_DUMMY,
+ 0,
+ "EGO systems",
+ "Dummy Product",
+ },
+ {
+ USB_VENDOR_EGO, USB_PRODUCT_EGO_M4U,
+ 0,
+ "EGO systems",
+ "ESI M4U",
+ },
+ {
USB_VENDOR_EICON, USB_PRODUCT_EICON_DIVA852,
0,
"Eicon Networks",
@@ -3179,6 +3442,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"LD-USB/TX",
},
{
+ USB_VENDOR_ELEKTOR, USB_PRODUCT_ELEKTOR_FT323R,
+ 0,
+ "ELEKTOR Electronics",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_ELSA, USB_PRODUCT_ELSA_MODEM1,
0,
"ELSA",
@@ -3203,6 +3472,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"PSX gun controller converter",
},
{
+ USB_VENDOR_EMTEC, USB_PRODUCT_EMTEC_RUF2PS,
+ 0,
+ "Emtec",
+ "Flash Drive",
+ },
+ {
USB_VENDOR_ENCORE, USB_PRODUCT_ENCORE_RT3070_1,
0,
"Encore",
@@ -3431,6 +3706,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Cressi Edy diving computer",
},
{
+ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_N2ITION3,
+ 0,
+ "Seiko Epson",
+ "Zeagle N2iTion3 diving computer",
+ },
+ {
USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_875DC,
0,
"Seiko Epson",
@@ -3539,30 +3820,102 @@ const struct usb_knowndev usb_knowndevs[] = {
"Serial",
},
{
+ USB_VENDOR_EVOLUTION, USB_PRODUCT_EVOLUTION_ER1,
+ 0,
+ "Evolution Robotics products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_EVOLUTION, USB_PRODUCT_EVOLUTION_HYBRID,
+ 0,
+ "Evolution Robotics products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_EVOLUTION, USB_PRODUCT_EVOLUTION_RCM4,
+ 0,
+ "Evolution Robotics products",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_EXTENDED, USB_PRODUCT_EXTENDED_XTNDACCESS,
0,
"Extended Systems",
"XTNDAccess IrDA",
},
{
+ USB_VENDOR_FALCOM, USB_PRODUCT_FALCOM_TWIST,
+ 0,
+ "Falcom Wireless Communications GmbH",
+ "USB GSM/GPRS Modem",
+ },
+ {
+ USB_VENDOR_FALCOM, USB_PRODUCT_FALCOM_SAMBA,
+ 0,
+ "Falcom Wireless Communications GmbH",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_DUMMY,
+ 0,
+ "Feiya",
+ "Dummy product",
+ },
+ {
USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_5IN1,
0,
"Feiya",
"5-in-1 Card Reader",
},
{
+ USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_ELANGO,
+ 0,
+ "Feiya",
+ "MicroSDHC Card Reader",
+ },
+ {
+ USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_AC110,
+ 0,
+ "Feiya",
+ "AC-110 Card Reader",
+ },
+ {
+ USB_VENDOR_FESTO, USB_PRODUCT_FESTO_CPX_USB,
+ 0,
+ "Festo",
+ "CPX-USB",
+ },
+ {
+ USB_VENDOR_FESTO, USB_PRODUCT_FESTO_CMSP,
+ 0,
+ "Festo",
+ "CMSP",
+ },
+ {
USB_VENDOR_FIBERLINE, USB_PRODUCT_FIBERLINE_WL430U,
0,
"Fiberline",
"WL-430U",
},
{
+ USB_VENDOR_FIC, USB_PRODUCT_FIC_NEO1973_DEBUG,
+ 0,
+ "FIC / OpenMoko",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_FOSSIL, USB_PRODUCT_FOSSIL_WRISTPDA,
0,
"Fossil, Inc",
"Wrist PDA",
},
{
+ USB_VENDOR_FOXCONN, USB_PRODUCT_FOXCONN_TCOM_TC_300,
+ 0,
+ "Foxconn",
+ "T-Com TC 300",
+ },
+ {
USB_VENDOR_FOXCONN, USB_PRODUCT_FOXCONN_PIRELLI_DP_L10,
0,
"Foxconn",
@@ -3605,12 +3958,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"8U232AM Serial",
},
{
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_232RL,
+ 0,
+ "Future Technology Devices",
+ "FT232RL Serial",
+ },
+ {
USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_2232C,
0,
"Future Technology Devices",
"FT2232C Dual port Serial",
},
{
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_232H,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_2232D,
0,
"Future Technology Devices",
@@ -3623,6 +3988,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"FT4232H Quad port Serial",
},
{
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_BEAGLEBONE,
+ 0,
+ "Future Technology Devices",
+ "BeagleBone",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TURTELIZER2,
+ 0,
+ "Future Technology Devices",
+ "egnite Turtelizer 2 JTAG/RS232 Adapter",
+ },
+ {
USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13M,
0,
"Future Technology Devices",
@@ -3773,6 +4150,1188 @@ const struct usb_knowndev usb_knowndevs[] = {
"CTI USB-Mini 485",
},
{
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_232RL,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_4N_GALAXY_DE_1,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_4N_GALAXY_DE_2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_4N_GALAXY_DE_3,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_8U232AM_ALT,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ACCESSO,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ACG_HFDUAL,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ACTIVE_ROBOTS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ACTZWAVE,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_AMC232,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ARTEMIS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ASK_RDR400,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ATIK_ATK16,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ATIK_ATK16C,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ATIK_ATK16HR,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ATIK_ATK16HRC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ATIK_ATK16IC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_BCS_SE923,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CANDAPTER,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CANUSB,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CCSICDU20_0,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CCSICDU40_1,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CCSICDU64_4,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CCSLOAD_N_GO_3,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CCSMACHX_2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CCSPRIME8_5,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CHAMSYS_24_MASTER_WING,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CHAMSYS_MAXI_WING,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CHAMSYS_MEDIA_WING,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CHAMSYS_MIDI_TIMECODE,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CHAMSYS_MINI_WING,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CHAMSYS_PC_WING,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CHAMSYS_USB_DMX,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CHAMSYS_WING,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_COM4SM,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CONVERTER_0,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CONVERTER_1,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CONVERTER_2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CONVERTER_3,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CONVERTER_4,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CONVERTER_5,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CONVERTER_6,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CONVERTER_7,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_DMX4ALL,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_DOMINTELL_DGQG,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_DOMINTELL_DUSB,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_DOTEC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ECLO_COM_1WIRE,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ECO_PRO_CDS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELSTER_UNICOM,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_ALC8500,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_CLI7000,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_CSI8,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_EC3000,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_EM1000DL,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_EM1010PC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_FEM,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_FHZ1000PC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_FHZ1300PC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_FM3RX,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_FS20SIG,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_HS485,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_KL100,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_MSM1,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_PCD200,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_PCK100,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_PPS7330,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_RFP500,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_T1100,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_TFD128,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_TFM100,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_TWS550,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UAD8,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UDA7,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UDF77,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UIO88,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_ULA200,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UM100,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UMS100,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UO100,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UR100,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_USI2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_USR,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_UTP8,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_WS300PC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_WS444PC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_WS500,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_WS550,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_WS777,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_ELV_WS888,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_FUTURE_0,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_FUTURE_1,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_FUTURE_2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GENERIC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E808,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E809,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E80A,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E80B,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E80C,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E80D,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E80E,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E80F,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E88D,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E88E,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GUDEADS_E88F,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_HD_RADIO,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_HO720,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_HO730,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_HO820,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_HO870,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IBS_APP70,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IBS_PCMCIA,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IBS_PEDO,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IBS_PICPRO,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IBS_PK1,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IBS_PROD,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IBS_RS232MON,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IBS_US485,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IPLUS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IPLUS2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_IRTRANS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_LENZ_LIUSB,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_LM3S_DEVEL_BOARD,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_LM3S_EVAL_BOARD,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MASTERDEVEL2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MHAM_DB9,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MHAM_IC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MHAM_KW,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MHAM_RS232,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MHAM_Y6,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MHAM_Y8,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MHAM_Y9,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MHAM_YS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MICRO_CHAMELEON,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MTXORB_5,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MTXORB_6,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_NXTCAM,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_OCEANIC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_OOCDLINK,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_OPENDCC,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_OPENDCC_GATEWAY,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_OPENDCC_GBM,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_OPENDCC_SNIFFER,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_OPENDCC_THROTTLE,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_PCDJ_DAC2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_PERLE_ULTRAPORT,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_PHI_FISCO,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_PIEGROUP,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_PROPOX_JTAGCABLEII,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_R2000KU_TRUE_RNG,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_R2X0,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_RELAIS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_REU_TINY,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_RMP200,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_RM_CANVIEW,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_RRCIRKITS_LOCOBUFFER,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCIENCESCOPE_HS_LOGBOOK,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCIENCESCOPE_LOGBOOKML,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCIENCESCOPE_LS_LOGBOOK,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCS_DEVICE_0,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCS_DEVICE_1,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCS_DEVICE_2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCS_DEVICE_3,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCS_DEVICE_4,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCS_DEVICE_5,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCS_DEVICE_6,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SCS_DEVICE_7,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SDMUSBQSS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SIGNALYZER_SH2,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SIGNALYZER_SH4,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SIGNALYZER_SLITE,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SIGNALYZER_ST,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SPECIAL_1,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SPECIAL_3,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SPECIAL_4,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SPROG_II,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SR_RADIO,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SUUNTO_SPORTS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TAVIR_STK500,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TERATRONIK_D2XX,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TERATRONIK_VCP,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_THORLABS,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TNC_X,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TTUSB,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_USBX_707,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_USINT_CAT,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_USINT_RS232,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_USINT_WKEY,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_VARDAAN,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_VNHCPCUSB_D,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_WESTREX_MODEL_777,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_WESTREX_MODEL_8900F,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_XF_547,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_XF_640,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_XF_642,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_XM_RADIO,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_FTDI, USB_PRODUCT_FTDI_YEI_SERVOCENTER31,
+ 0,
+ "Future Technology Devices",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100,
0,
"Fuji Photo Film",
@@ -3800,7 +5359,7 @@ const struct usb_knowndev usb_knowndevs[] = {
USB_VENDOR_GEMALTO, USB_PRODUCT_GEMALTO_PROXPU,
0,
"Gemalto SA",
- "Prox-PU/CU",
+ "Prox-PU/CU RFID Card Reader",
},
{
USB_VENDOR_GENERALINSTMNTS, USB_PRODUCT_GENERALINSTMNTS_SB5100,
@@ -3995,6 +5554,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"YP3X00 PDA",
},
{
+ USB_VENDOR_GNOTOMETRICS, USB_PRODUCT_GNOTOMETRICS_USB,
+ 0,
+ "GN Otometrics",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_GOHUBS, USB_PRODUCT_GOHUBS_GOCOM232,
0,
"GoHubs",
@@ -4913,6 +6478,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"3G modem",
},
{
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K4505,
+ 0,
+ "Huawei Technologies",
+ "3G modem",
+ },
+ {
USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K3765,
0,
"Huawei Technologies",
@@ -4925,12 +6496,66 @@ const struct usb_knowndev usb_knowndevs[] = {
"E1820 HSPA+ USB Slider",
},
{
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K3770,
+ 0,
+ "Huawei Technologies",
+ "3G modem",
+ },
+ {
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K3770_INIT,
+ 0,
+ "Huawei Technologies",
+ "K3770 Initial",
+ },
+ {
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E3131_INIT,
+ 0,
+ "Huawei Technologies",
+ "3G modem initial",
+ },
+ {
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E392,
+ 0,
+ "Huawei Technologies",
+ "LTE modem",
+ },
+ {
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E3131,
+ 0,
+ "Huawei Technologies",
+ "3G modem",
+ },
+ {
USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K3765_INIT,
0,
"Huawei Technologies",
"K3765 Initial",
},
{
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K4505_INIT,
+ 0,
+ "Huawei Technologies",
+ "K4505 Initial",
+ },
+ {
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_ETS2055,
+ 0,
+ "Huawei Technologies",
+ "CDMA modem",
+ },
+ {
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E173,
+ 0,
+ "Huawei Technologies",
+ "3G modem",
+ },
+ {
+ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E173_INIT,
+ 0,
+ "Huawei Technologies",
+ "3G modem initial",
+ },
+ {
USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_WUB320G,
0,
"Huawei-3Com",
@@ -4943,12 +6568,96 @@ const struct usb_knowndev usb_knowndevs[] = {
"USB CD-ROM Drive",
},
{
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_SP1,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_OPC_U_UC,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP2C1,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP2C2,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP2D,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP2KVR,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP2KVT,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP2VR,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP2VT,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP4KVR,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_ICOM, USB_PRODUCT_ICOM_RP4KVT,
+ 0,
+ "Icom Inc.",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_IDTECH, USB_PRODUCT_IDTECH_IDT1221U,
+ 0,
+ "ID TECH",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_IMAGINATION, USB_PRODUCT_IMAGINATION_DBX1,
0,
"Imagination Technologies",
"DBX1 DSP core",
},
{
+ USB_VENDOR_INITIO, USB_PRODUCT_INITIO_DUMMY,
+ 0,
+ "Initio Corporation",
+ "Dummy product",
+ },
+ {
+ USB_VENDOR_INITIO, USB_PRODUCT_INITIO_INIC_1610P,
+ 0,
+ "Initio Corporation",
+ "USB to SATA Bridge",
+ },
+ {
USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4,
0,
"Inside Out Networks",
@@ -5009,6 +6718,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"Integrated Rate Matching Hub",
},
{
+ USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_IRMH2,
+ 0,
+ "Intel",
+ "Integrated Rate Matching Hub",
+ },
+ {
+ USB_VENDOR_INTERBIOMETRICS, USB_PRODUCT_INTERBIOMETRICS_IOBOARD,
+ 0,
+ "Interbiometrics",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_INTERBIOMETRICS, USB_PRODUCT_INTERBIOMETRICS_MINI_IOBOARD,
+ 0,
+ "Interbiometrics",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_INTERSIL, USB_PRODUCT_INTERSIL_PRISM_GT,
0,
"Intersil",
@@ -5147,6 +6874,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Zip 250",
},
{
+ USB_VENDOR_IONICS, USB_PRODUCT_IONICS_PLUGCOMPUTER,
+ 0,
+ "Ionics PlugComputer",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_ISSC, USB_PRODUCT_ISSC_ISSCBTA,
0,
"Integrated System Solution Corp.",
@@ -5189,6 +6922,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Ethernet",
},
{
+ USB_VENDOR_JETI, USB_PRODUCT_JETI_SPC1201,
+ 0,
+ "Jeti",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_JMICRON, USB_PRODUCT_JMICRON_JM20336,
0,
"JMicron",
@@ -5219,6 +6958,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"AirH PHONE AH-J3001V/J3002V",
},
{
+ USB_VENDOR_KAMSTRUP, USB_PRODUCT_KAMSTRUP_OPTICALEYE,
+ 0,
+ "Kamstrup A/S",
+ "Optical Eye/3-wire",
+ },
+ {
+ USB_VENDOR_KAMSTRUP, USB_PRODUCT_KAMSTRUP_MBUS_250D,
+ 0,
+ "Kamstrup A/S",
+ "M-Bus Master MultiPort 250D",
+ },
+ {
USB_VENDOR_KAWATSU, USB_PRODUCT_KAWATSU_MH4000P,
0,
"Kawatsu Semiconductor",
@@ -5435,6 +7186,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"USB Ethernet",
},
{
+ USB_VENDOR_KOBIL, USB_PRODUCT_KOBIL_CONV_B1,
+ 0,
+ "KOBIL",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_KOBIL, USB_PRODUCT_KOBIL_CONV_KAAN,
+ 0,
+ "KOBIL",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_KODAK, USB_PRODUCT_KODAK_DC220,
0,
"Eastman Kodak",
@@ -5471,6 +7234,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"Digital Science DC280",
},
{
+ USB_VENDOR_KONTRON, USB_PRODUCT_KONTRON_DM9601,
+ 0,
+ "Kontron AG",
+ "USB Ethernet",
+ },
+ {
+ USB_VENDOR_KONTRON, USB_PRODUCT_KONTRON_JP1082,
+ 0,
+ "Kontron AG",
+ "USB Ethernet",
+ },
+ {
USB_VENDOR_KONICA, USB_PRODUCT_KONICA_CAMERA,
0,
"Konica",
@@ -5555,6 +7330,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"CD R/W",
},
{
+ USB_VENDOR_LARSENBRUSGAARD, USB_PRODUCT_LARSENBRUSGAARD_ALTITRACK,
+ 0,
+ "Larsen and Brusgaard",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_LEADTEK, USB_PRODUCT_LEADTEK_9531,
0,
"Leadtek",
@@ -5585,6 +7366,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"PowerSure Personal XT",
},
{
+ USB_VENDOR_LINKINSTRUMENTS, USB_PRODUCT_LINKINSTRUMENTS_MSO19,
+ 0,
+ "Link Instruments Inc.",
+ "Link Instruments MSO-19",
+ },
+ {
+ USB_VENDOR_LINKINSTRUMENTS, USB_PRODUCT_LINKINSTRUMENTS_MSO28,
+ 0,
+ "Link Instruments Inc.",
+ "Link Instruments MSO-28",
+ },
+ {
+ USB_VENDOR_LINKINSTRUMENTS, USB_PRODUCT_LINKINSTRUMENTS_MSO28_2,
+ 0,
+ "Link Instruments Inc.",
+ "Link Instruments MSO-28",
+ },
+ {
USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_MAUSB2,
0,
"Linksys",
@@ -5687,6 +7486,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"WUSB600N v2",
},
{
+ USB_VENDOR_LOGILINK, USB_PRODUCT_LOGILINK_DUMMY,
+ 0,
+ "LogiLink",
+ "Dummy product",
+ },
+ {
+ USB_VENDOR_LOGILINK, USB_PRODUCT_LOGILINK_U2M,
+ 0,
+ "LogiLink",
+ "LogiLink USB MIDI Cable",
+ },
+ {
USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_M2452,
0,
"Logitech",
@@ -5717,6 +7528,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"QuickCam Pro",
},
{
+ USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WEBCAMC100,
+ 0,
+ "Logitech",
+ "Webcam C100",
+ },
+ {
USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMEXP,
0,
"Logitech",
@@ -5861,6 +7678,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT2870",
},
{
+ USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LANW300NU2,
+ 0,
+ "Logitec",
+ "LAN-W300N/U2",
+ },
+ {
+ USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LANW150NU2,
+ 0,
+ "Logitec",
+ "LAN-W150N/U2",
+ },
+ {
USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_WM66,
0,
"Longcheer Holdings, Ltd.",
@@ -5879,6 +7708,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Driver disk",
},
{
+ USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_XSSTICK,
+ 0,
+ "Longcheer Holdings, Ltd.",
+ "4G Systems XSStick P14",
+ },
+ {
USB_VENDOR_LUCENT, USB_PRODUCT_LUCENT_EVALKIT,
0,
"Lucent",
@@ -5897,18 +7732,1512 @@ const struct usb_knowndev usb_knowndevs[] = {
"mouse",
},
{
+ USB_VENDOR_MAGTEK, USB_PRODUCT_MAGTEK_USBSWIPE,
+ 0,
+ "Mag-Tek",
+ "USB Mag Stripe Swipe Reader",
+ },
+ {
USB_VENDOR_MARVELL, USB_PRODUCT_MARVELL_SHEEVAPLUG,
0,
"Marvell Technology Group Ltd.",
"SheevaPlug serial interface",
},
{
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0100,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0101,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0102,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0103,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0104,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0105,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0106,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0107,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0108,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0109,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_010F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0110,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0111,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0112,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0113,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0114,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0115,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0116,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0117,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0118,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0119,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_011F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0120,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0121,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0122,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0123,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0124,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0125,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0126,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0128,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0129,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_012F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0130,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0131,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0132,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0133,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0134,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0135,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0136,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0137,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0138,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0139,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_013F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0140,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0141,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0142,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0143,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0144,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0145,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0146,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0147,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0148,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0149,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_014F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0150,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0151,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0152,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_MOUA,
0,
"Matrix Orbital",
"Martrix Orbital MOU-Axxxx LCD displays",
},
{
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0159,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_015F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0160,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0161,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0162,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0163,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0164,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0165,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0166,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0167,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0168,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0169,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_016F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0170,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0171,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0172,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0173,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0174,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0175,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0176,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0177,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0178,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0179,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_017F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0180,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0181,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0182,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0183,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0184,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0185,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0186,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0187,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0188,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0189,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_018F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0190,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0191,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0192,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0193,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0194,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0195,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0196,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0197,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0198,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_0199,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019A,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019B,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019C,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019D,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019E,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_019F,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A0,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A1,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A2,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A3,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A4,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A5,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A6,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A7,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A8,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01A9,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AA,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AB,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AC,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AD,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AE,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01AF,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B0,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B1,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B2,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B3,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B4,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B5,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B6,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B7,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B8,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01B9,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BA,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BB,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BC,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BD,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BE,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01BF,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C0,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C1,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C2,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C3,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C4,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C5,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C6,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C7,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C8,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01C9,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CA,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CB,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CC,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CD,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CE,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01CF,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D0,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D1,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D2,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D3,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D4,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D5,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D6,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D7,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D8,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01D9,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DA,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DB,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DC,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DD,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DE,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01DF,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E0,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E1,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E2,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E3,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E4,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E5,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E6,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E7,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E8,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01E9,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EA,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EB,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EC,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01ED,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EE,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01EF,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F0,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F1,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F2,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F3,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F4,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F5,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F6,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F7,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F8,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01F9,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FA,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FB,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FC,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FD,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FE,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_FTDI_RANGE_01FF,
+ 0,
+ "Matrix Orbital",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100,
0,
"MCT",
@@ -5933,6 +9262,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"Sitecom USB-232 Products",
},
{
+ USB_VENDOR_MEDELI, USB_PRODUCT_MEDELI_DD305,
+ 0,
+ "Medeli",
+ "DD305 Digital Drum Set",
+ },
+ {
+ USB_VENDOR_MEDIATEK, USB_PRODUCT_MEDIATEK_MTK3329,
+ 0,
+ "MediaTek, Inc.",
+ "MTK II GPS Receiver",
+ },
+ {
USB_VENDOR_MEIZU, USB_PRODUCT_MEIZU_M6_SL,
0,
"Meizu Electronics",
@@ -6059,6 +9400,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"WLI-UC-AG300N",
},
{
+ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLIUCG,
+ 0,
+ "Melco",
+ "WLI-UC-G",
+ },
+ {
USB_VENDOR_MELCO, USB_PRODUCT_MELCO_RT2870_1,
0,
"Melco",
@@ -6077,12 +9424,36 @@ const struct usb_knowndev usb_knowndevs[] = {
"WLI-UC-GN",
},
{
+ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLIUCG301N,
+ 0,
+ "Melco",
+ "WLI-UC-G301N",
+ },
+ {
+ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLIUCGNM,
+ 0,
+ "Melco",
+ "WLI-UC-GNM",
+ },
+ {
+ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLIUCGNM2,
+ 0,
+ "Melco",
+ "WLI-UC-GNM2",
+ },
+ {
USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620,
0,
"Merlin",
"Merlin V620",
},
{
+ USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_TELLSTICK,
+ 0,
+ "MetaGeek",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B,
0,
"MetaGeek",
@@ -6128,7 +9499,7 @@ const struct usb_knowndev usb_knowndevs[] = {
USB_VENDOR_MEI, USB_PRODUCT_MEI_S2000,
0,
"MEI",
- "Seies 2000 Combo Acceptor",
+ "Series 2000 Combo Acceptor",
},
{
USB_VENDOR_MSI, USB_PRODUCT_MSI_BT_DONGLE,
@@ -6251,6 +9622,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT2573",
},
{
+ USB_VENDOR_MICRON, USB_PRODUCT_MICRON_REALSSD,
+ 0,
+ "Micron Technology",
+ "Real SSD eUSB",
+ },
+ {
USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_SIDEPREC,
0,
"Microsoft",
@@ -6449,12 +9826,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"Bluetooth USB dongle",
},
{
- USB_VENDOR_MIDIMAN, USB_PRODUCT_MIDIMAN_MIDISPORT2X2,
+ USB_VENDOR_MAUDIO, USB_PRODUCT_MAUDIO_MIDISPORT2X2,
0,
- "Midiman",
+ "M-Audio",
"Midisport 2x2",
},
{
+ USB_VENDOR_MAUDIO, USB_PRODUCT_MAUDIO_FASTTRACKULTRA,
+ 0,
+ "M-Audio",
+ "Fast Track Ultra",
+ },
+ {
+ USB_VENDOR_MAUDIO, USB_PRODUCT_MAUDIO_FASTTRACKULTRA8R,
+ 0,
+ "M-Audio",
+ "Fast Track Ultra 8R",
+ },
+ {
USB_VENDOR_MINDSATWORK, USB_PRODUCT_MINDSATWORK_WALLET,
0,
"Minds At Work",
@@ -6521,6 +9910,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"MA-620 Infrared Adapter",
},
{
+ USB_VENDOR_MOBILITY, USB_PRODUCT_MOBILITY_USB_SERIAL,
+ 0,
+ "Mobility",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_MOBILITY, USB_PRODUCT_MOBILITY_EA,
0,
"Mobility",
@@ -6539,12 +9934,36 @@ const struct usb_knowndev usb_knowndevs[] = {
"MCS7703 Serial Port Adapter",
},
{
+ USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7730,
+ 0,
+ "MosChip Semiconductor",
+ "MCS7730 Ethernet",
+ },
+ {
+ USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7820,
+ 0,
+ "MosChip Semiconductor",
+ "MCS7820 Serial Port Adapter",
+ },
+ {
USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830,
0,
"MosChip Semiconductor",
"MCS7830 Ethernet",
},
{
+ USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7832,
+ 0,
+ "MosChip Semiconductor",
+ "MCS7832 Ethernet",
+ },
+ {
+ USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7840,
+ 0,
+ "MosChip Semiconductor",
+ "MCS7840 Serial Port Adapter",
+ },
+ {
USB_VENDOR_MOTOROLA, USB_PRODUCT_MOTOROLA_MC141555,
0,
"Motorola",
@@ -6599,6 +10018,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT3070",
},
{
+ USB_VENDOR_MPMAN, USB_PRODUCT_MPMAN_MPF400_2,
+ 0,
+ "MpMan",
+ "MPF400 Music Player 2Go",
+ },
+ {
+ USB_VENDOR_MPMAN, USB_PRODUCT_MPMAN_MPF400_1,
+ 0,
+ "MpMan",
+ "MPF400 Music Player 1Go",
+ },
+ {
USB_VENDOR_MULTITECH, USB_PRODUCT_MULTITECH_ATLAS,
0,
"MultiTech",
@@ -7091,6 +10522,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Novatel MC760",
},
{
+ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC547,
+ 0,
+ "Novatel Wireless",
+ "Novatel MC547",
+ },
+ {
USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_FLEXPACKGPS,
0,
"Novatel Wireless",
@@ -7115,6 +10552,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"OZ776 CCID SC Reader",
},
{
+ USB_VENDOR_OLIMEX, USB_PRODUCT_OLIMEX_ARM_USB_OCD,
+ 0,
+ "Olimex",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_OLIMEX, USB_PRODUCT_OLIMEX_ARM_USB_OCD_H,
+ 0,
+ "Olimex",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1,
0,
"Olympus",
@@ -7235,6 +10684,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"GlobeTrotter Max 3.6 Modem",
},
{
+ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX72,
+ 0,
+ "Option N.V.",
+ "GlobeTrotter Max 7.2 HSDPA",
+ },
+ {
USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTHSDPA,
0,
"Option N.V.",
@@ -7601,12 +11056,186 @@ const struct usb_knowndev usb_knowndevs[] = {
"TY-TP50P6-S 50in Touch Panel",
},
{
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_AD4USB,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_AP485,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_AP485_2,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_DRAK5,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_DRAK6,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_GMSR,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_GMUX,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_IRAMP,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_LEC,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_MU,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_QUIDO10X1,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_QUIDO2X16,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_QUIDO2X2,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_QUIDO30X3,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_QUIDO3X32,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_QUIDO4X4,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_QUIDO60X3,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_QUIDO8X8,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_SB232,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_SB422,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_SB422_2,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_SB485,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_SB485C,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_SB485S,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_SB485_2,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_SIMUKEY,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_TMU,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_PAPOUCH, USB_PRODUCT_PAPOUCH_UPSUSB,
+ 0,
+ "Papouch products",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_PARA, USB_PRODUCT_PARA_RT3070,
0,
"PARA Industrial",
"RT3070",
},
{
+ USB_VENDOR_SIMTEC, USB_PRODUCT_SIMTEC_ENTROPYKEY,
+ 0,
+ "Simtec Electronics",
+ "Entropy Key",
+ },
+ {
USB_VENDOR_PEGATRON, USB_PRODUCT_PEGATRON_RT2870,
0,
"Pegatron",
@@ -7823,6 +11452,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"GW-USMicroN",
},
{
+ USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSVALUEEZ,
+ 0,
+ "Planex Communications",
+ "GW-USValue-EZ",
+ },
+ {
USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54GZ,
0,
"Planex Communications",
@@ -7883,6 +11518,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Express Ethernet",
},
{
+ USB_VENDOR_POSIFLEX, USB_PRODUCT_POSIFLEX_PP7000,
+ 0,
+ "POSIFLEX",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2X300,
0,
"Primax Electronics",
@@ -7997,6 +11638,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"PL2302 Host-Host interface",
},
{
+ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_MOTOROLA,
+ 0,
+ "Prolific Technology",
+ "Motorola Cable",
+ },
+ {
USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2,
0,
"Prolific Technology",
@@ -8027,6 +11674,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"DCU-11 Phone Cable",
},
{
+ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_UIC_MSR206,
+ 0,
+ "Prolific Technology",
+ "UIC MSR206 Card Reader",
+ },
+ {
USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303,
0,
"Prolific Technology",
@@ -8111,6 +11764,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT2870",
},
{
+ USB_VENDOR_QIHARDWARE, USB_PRODUCT_QIHARDWARE_JTAGSERIAL,
+ 0,
+ "QI-hardware",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_QISDA, USB_PRODUCT_QISDA_H21_1,
0,
"Qisda",
@@ -8165,6 +11824,30 @@ const struct usb_knowndev usb_knowndevs[] = {
"AC8700",
},
{
+ USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_VW110L,
+ 0,
+ "Qualcomm",
+ "Vertex Wireless 110L modem",
+ },
+ {
+ USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_SIM5218,
+ 0,
+ "Qualcomm",
+ "SIM5218",
+ },
+ {
+ USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_GOBI2000_QDL,
+ 0,
+ "Qualcomm",
+ "Qualcomm Gobi 2000 QDL",
+ },
+ {
+ USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_GOBI2000,
+ 0,
+ "Qualcomm",
+ "Qualcomm Gobi 2000 modem",
+ },
+ {
USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM,
0,
"Qualcomm, Incorporated",
@@ -8561,6 +12244,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"3G modem",
},
{
+ USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_SURFSTICK,
+ 0,
+ "Qualcomm, Incorporated",
+ "1&1 Surf Stick",
+ },
+ {
+ USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_K3772_Z,
+ 0,
+ "Qualcomm, Incorporated",
+ "3G modem",
+ },
+ {
USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_STOR,
0,
"Qualcomm, Incorporated",
@@ -8747,6 +12442,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT3572",
},
{
+ USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT5370,
+ 0,
+ "Ralink Technology",
+ "RT5370",
+ },
+ {
USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT8070,
0,
"Ralink Technology",
@@ -8777,6 +12478,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"USB serial adapter REX-USB60F",
},
{
+ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_DUMMY,
+ 0,
+ "Realtek",
+ "Dummy product",
+ },
+ {
USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_USB20CRW,
0,
"Realtek",
@@ -8813,6 +12520,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"RTL8187B Wireless Adapter",
},
{
+ USB_VENDOR_REDOCTANE, USB_PRODUCT_REDOCTANE_DUMMY,
+ 0,
+ "RedOctane",
+ "Dummy product",
+ },
+ {
+ USB_VENDOR_REDOCTANE, USB_PRODUCT_REDOCTANE_GHMIDI,
+ 0,
+ "RedOctane",
+ "GH MIDI INTERFACE",
+ },
+ {
+ USB_VENDOR_RENESAS, USB_PRODUCT_RENESAS_RX610,
+ 0,
+ "Renesas",
+ "RX610 RX-Stick",
+ },
+ {
USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC2,
0,
"Ricoh",
@@ -8855,12 +12580,66 @@ const struct usb_knowndev usb_knowndevs[] = {
"e-com cyberJack",
},
{
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UA100,
+ 0,
+ "Roland",
+ "UA-100 Audio I/F",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UM4,
+ 0,
+ "Roland",
+ "UM-4 MIDI I/F",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_SC8850,
+ 0,
+ "Roland",
+ "SC-8850 MIDI Synth",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_U8,
+ 0,
+ "Roland",
+ "U-8 Audio I/F",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UM2,
+ 0,
+ "Roland",
+ "UM-2 MIDI I/F",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_SC8820,
+ 0,
+ "Roland",
+ "SC-8820 MIDI Synth",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_PC300,
+ 0,
+ "Roland",
+ "PC-300 MIDI Keyboard",
+ },
+ {
USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UM1,
0,
"Roland",
"UM-1 MIDI I/F",
},
{
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_SK500,
+ 0,
+ "Roland",
+ "SK-500 MIDI Keyboard",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_SCD70,
+ 0,
+ "Roland",
+ "SC-D70 MIDI Synth",
+ },
+ {
USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UM880N,
0,
"Roland",
@@ -8873,6 +12652,36 @@ const struct usb_knowndev usb_knowndevs[] = {
"EDIROL UM-880 MIDI I/F (generic)",
},
{
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_SD90,
+ 0,
+ "Roland",
+ "SD-90 MIDI Synth",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UM550,
+ 0,
+ "Roland",
+ "UM-550 MIDI I/F",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_SD20,
+ 0,
+ "Roland",
+ "SD-20 MIDI Synth",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_SD80,
+ 0,
+ "Roland",
+ "SD-80 MIDI Synth",
+ },
+ {
+ USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UA700,
+ 0,
+ "Roland",
+ "UA-700 Audio I/F",
+ },
+ {
USB_VENDOR_ROCKFIRE, USB_PRODUCT_ROCKFIRE_GAMEPAD,
0,
"Rockfire",
@@ -8891,6 +12700,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"REX-USB60F",
},
{
+ USB_VENDOR_RTSYSTEMS, USB_PRODUCT_RTSYSTEMS_CT29B,
+ 0,
+ "RTSYSTEMS",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_RTSYSTEMS, USB_PRODUCT_RTSYSTEMS_SERIAL_VX7,
+ 0,
+ "RTSYSTEMS",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_USBSERIAL,
0,
"Sagem",
@@ -8909,6 +12730,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"XG-76NA",
},
{
+ USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_WIS09ABGN,
+ 0,
+ "Samsung Electronics",
+ "WIS09ABGN Wireless LAN adapter",
+ },
+ {
USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ML6060,
0,
"Samsung Electronics",
@@ -9005,6 +12832,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Cruzer Micro 256MB",
},
{
+ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_IMAGEMATE_SDDR289,
+ 0,
+ "SanDisk",
+ "ImageMate SDDR-289",
+ },
+ {
USB_VENDOR_SANWA, USB_PRODUCT_SANWA_KB_USB2,
0,
"Sanwa Electric Instrument Co., Ltd.",
@@ -9029,6 +12862,288 @@ const struct usb_knowndev usb_knowndevs[] = {
"Phantom 336CX - C3 scanner",
},
{
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2101,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2102,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2103,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2104,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2106,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2201_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2201_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2202_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2202_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2203_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2203_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2401_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2401_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2401_3,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2401_4,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2402_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2402_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2402_3,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2402_4,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2403_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2403_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2403_3,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2403_4,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2801_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2801_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2801_3,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2801_4,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2801_5,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2801_6,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2801_7,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2801_8,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2802_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2802_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2802_3,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2802_4,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2802_5,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2802_6,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2802_7,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2802_8,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2803_1,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2803_2,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2803_3,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2803_4,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2803_5,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2803_6,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2803_7,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_SEALEVEL, USB_PRODUCT_SEALEVEL_2803_8,
+ 0,
+ "Sealevel System",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT2870_3,
0,
"Senao",
@@ -9113,6 +13228,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"DM 9601",
},
{
+ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ADM8515,
+ 0,
+ "ShanTou",
+ "ADM8515",
+ },
+ {
USB_VENDOR_SHARK, USB_PRODUCT_SHARK_PA,
0,
"Shark",
@@ -9647,6 +13768,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Aircard 875 HSDPA",
},
{
+ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC313U,
+ 0,
+ "Sierra Wireless",
+ "Sierra Wireless AirCard 313U",
+ },
+ {
USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL,
0,
"Sierra Wireless",
@@ -9677,6 +13804,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"WINTERREADER Reader",
},
{
+ USB_VENDOR_SIIG2, USB_PRODUCT_SIIG2_DK201,
+ 0,
+ "SIIG",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_SIIG2, USB_PRODUCT_SIIG2_USBTOETHER,
0,
"SIIG",
@@ -9704,7 +13837,7 @@ const struct usb_knowndev usb_knowndevs[] = {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_VSTABI,
0,
"Silicon Labs",
- "Vstabi",
+ "VStabi Controller",
},
{
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARKHAM_DS101_M,
@@ -9722,7 +13855,7 @@ const struct usb_knowndev usb_knowndevs[] = {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_BSM7DUSB,
0,
"Silicon Labs",
- "BSM7-D-USB",
+ "SPORTident BSM7-D USB",
},
{
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_POLOLU,
@@ -9773,6 +13906,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Crumb128 board",
},
{
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_OPTRIS_MSPRO,
+ 0,
+ "Silicon Labs",
+ "Optris MSpro LT Thermometer",
+ },
+ {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DEGREE,
0,
"Silicon Labs",
@@ -9833,12 +13972,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"WMR RIGtalk RT1",
},
{
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_B_G_H3000,
+ 0,
+ "Silicon Labs",
+ "B&G H3000 Data Cable",
+ },
+ {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_HELICOM,
0,
"Silicon Labs",
"Helicomm IP-Link 1220-DVM",
},
{
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_HAMLINKUSB,
+ 0,
+ "Silicon Labs",
+ "Timewave HamLinkUSB",
+ },
+ {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_AVIT_USB_TTL,
0,
"Silicon Labs",
@@ -9848,7 +13999,7 @@ const struct usb_knowndev usb_knowndevs[] = {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_MJS_TOSLINK,
0,
"Silicon Labs",
- "MJS USB-TOSLINk",
+ "MJS USB-TOSLINK",
},
{
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_WAVIT,
@@ -9857,6 +14008,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"ThinkOptics WavIt",
},
{
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_MULTIPLEX_RC,
+ 0,
+ "Silicon Labs",
+ "Multiplex RC adapter",
+ },
+ {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_MSD_DASHHAWK,
0,
"Silicon Labs",
@@ -9917,10 +14074,10 @@ const struct usb_knowndev usb_knowndevs[] = {
"Cygnal Fasttrax GPS",
},
{
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_TELEGESYS_ETRX2,
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_TELEGESIS_ETRX2,
0,
"Silicon Labs",
- "Telegesys ETRX2USB",
+ "Telegesis ETRX2USB",
},
{
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_PROCYON_AVS,
@@ -9947,18 +14104,60 @@ const struct usb_knowndev usb_knowndevs[] = {
"Amber Wireless AMB2560",
},
{
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DEKTEK_DTAPLUS,
+ 0,
+ "Silicon Labs",
+ "DekTec DTA Plus VHF/UHF Booster",
+ },
+ {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_KYOCERA_GPS,
0,
"Silicon Labs",
"Kyocera GPS",
},
{
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_IRZ_SG10,
+ 0,
+ "Silicon Labs",
+ "IRZ SG-10 GSM/GPRS Modem",
+ },
+ {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_BEI_VCP,
0,
"Silicon Labs",
"BEI USB Sensor (VCP)",
},
{
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_BALLUFF_RFID,
+ 0,
+ "Silicon Labs",
+ "Balluff RFID reader",
+ },
+ {
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_AC_SERV_IBUS,
+ 0,
+ "Silicon Labs",
+ "AC-Services IBUS Interface",
+ },
+ {
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_AC_SERV_CIS,
+ 0,
+ "Silicon Labs",
+ "AC-Services CIS-IBUS",
+ },
+ {
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_AC_SERV_CAN,
+ 0,
+ "Silicon Labs",
+ "AC-Services CAN Interface",
+ },
+ {
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_AC_SERV_OBD,
+ 0,
+ "Silicon Labs",
+ "AC-Services OBD Interface",
+ },
+ {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP2102,
0,
"Silicon Labs",
@@ -9971,6 +14170,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"CP210x Serial",
},
{
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_3,
+ 0,
+ "Silicon Labs",
+ "CP210x Serial",
+ },
+ {
+ USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_4,
+ 0,
+ "Silicon Labs",
+ "CP210x Serial",
+ },
+ {
USB_VENDOR_SILABS, USB_PRODUCT_SILABS_INFINITY_MIC,
0,
"Silicon Labs",
@@ -10067,6 +14278,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"WL-168 v1",
},
{
+ USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN030,
+ 0,
+ "Sitecom Europe",
+ "MCS7830",
+ },
+ {
USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL168V4,
0,
"Sitecom Europe",
@@ -10271,6 +14488,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"2662W-AR Wireless",
},
{
+ USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN9514_ETH,
+ 0,
+ "Standard Microsystems",
+ "USB/Ethernet",
+ },
+ {
USB_VENDOR_SOHOWARE, USB_PRODUCT_SOHOWARE_NUB100,
0,
"SOHOware",
@@ -10445,6 +14668,18 @@ const struct usb_knowndev usb_knowndevs[] = {
"RT3070",
},
{
+ USB_VENDOR_SOUNDGRAPH, USB_PRODUCT_SOUNDGRAPH_IMON_VFD,
+ 0,
+ "Soundgraph, Inc.",
+ "Antec Veris Elite VFD Panel, Knob, and Remote",
+ },
+ {
+ USB_VENDOR_SOUNDGRAPH, USB_PRODUCT_SOUNDGRAPH_SSTONE_LC16,
+ 0,
+ "Soundgraph, Inc.",
+ "Silverstone LC16 VFD Panel, Knob, and Remote",
+ },
+ {
USB_VENDOR_SPEEDDRAGON, USB_PRODUCT_SPEEDDRAGON_MS3303H,
0,
"Speed Dragon Multimedia",
@@ -10565,18 +14800,6 @@ const struct usb_knowndev usb_knowndevs[] = {
"3G modem",
},
{
- USB_VENDOR_MPMAN, USB_PRODUCT_MPMAN_MPF400_1,
- 0,
- "MpMan",
- "MPF400 Music Player 1Go",
- },
- {
- USB_VENDOR_MPMAN, USB_PRODUCT_MPMAN_MPF400_2,
- 0,
- "MpMan",
- "MPF400 Music Player 2Go",
- },
- {
USB_VENDOR_STMICRO, USB_PRODUCT_STMICRO_BIOCPU,
0,
"STMicroelectronics",
@@ -10589,6 +14812,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"USB Communicator",
},
{
+ USB_VENDOR_STMICRO, USB_PRODUCT_STMICRO_ST72682,
+ 0,
+ "STMicroelectronics",
+ "USB 2.0 Flash drive controller",
+ },
+ {
USB_VENDOR_STSN, USB_PRODUCT_STSN_STSN0001,
0,
"STSN",
@@ -10655,12 +14884,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"Kbd Hub",
},
{
+ USB_VENDOR_SUNPLUS, USB_PRODUCT_SUNPLUS_USBMOUSE,
+ 0,
+ "Sunplus Innovation Technology Inc.",
+ "USB Optical Mouse",
+ },
+ {
USB_VENDOR_SUPERTOP, USB_PRODUCT_SUPERTOP_IDE,
0,
"Super Top",
"USB-IDE",
},
{
+ USB_VENDOR_SUPERTOP, USB_PRODUCT_SUPERTOP_FLASHDRIVE,
+ 0,
+ "Super Top",
+ "extrememory Snippy",
+ },
+ {
USB_VENDOR_SYNTECH, USB_PRODUCT_SYNTECH_CPT8001C,
0,
"Syntech Information",
@@ -10679,6 +14920,42 @@ const struct usb_knowndev usb_knowndevs[] = {
"USB Media Player",
},
{
+ USB_VENDOR_TESTO, USB_PRODUCT_TESTO_USB_INTERFACE,
+ 0,
+ "Testo products",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_TEXTECH, USB_PRODUCT_TEXTECH_DUMMY,
+ 0,
+ "Textech International Ltd.",
+ "Dummy product",
+ },
+ {
+ USB_VENDOR_TEXTECH, USB_PRODUCT_TEXTECH_U2M_1,
+ 0,
+ "Textech International Ltd.",
+ "Textech USB MIDI cable",
+ },
+ {
+ USB_VENDOR_TEXTECH, USB_PRODUCT_TEXTECH_U2M_2,
+ 0,
+ "Textech International Ltd.",
+ "Textech USB MIDI cable",
+ },
+ {
+ USB_VENDOR_TML, USB_PRODUCT_TML_USB_SERIAL,
+ 0,
+ "The Mobility Lab",
+ "FTDI compatible adapter",
+ },
+ {
+ USB_VENDOR_TTI, USB_PRODUCT_TTI_QL355P,
+ 0,
+ "Thurlby Thandar Instruments",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_SUPRAEXPRESS56K,
0,
"Diamond (Supra)",
@@ -10907,6 +15184,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"G450 modem",
},
{
+ USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_TRANSMEMORY,
+ 0,
+ "Toshiba",
+ "USB ThumbDrive",
+ },
+ {
USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE,
0,
"Trek Technology",
@@ -11069,6 +15352,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Panache Surf USB ISDN Adapter",
},
{
+ USB_VENDOR_UNKNOWN4, USB_PRODUCT_UNKNOWN4_NF_RIC,
+ 0,
+ "Unknown vendor",
+ "FTDI compatible adapter",
+ },
+ {
USB_VENDOR_USI, USB_PRODUCT_USI_MC60,
0,
"USI",
@@ -11093,12 +15382,24 @@ const struct usb_knowndev usb_knowndevs[] = {
"USB 2.0 IDE Bridge",
},
{
+ USB_VENDOR_VIALABS, USB_PRODUCT_VIALABS_USB30SATABRIDGE,
+ 0,
+ "VIA Labs",
+ "USB 3.0 SATA Bridge",
+ },
+ {
USB_VENDOR_VAISALA, USB_PRODUCT_VAISALA_CABLE,
0,
"Vaisala",
"USB Interface cable",
},
{
+ USB_VENDOR_VERTEX, USB_PRODUCT_VERTEX_VW110L,
+ 0,
+ "Vertex Wireless Co., Ltd.",
+ "Vertex VW110L modem",
+ },
+ {
USB_VENDOR_VIDZMEDIA, USB_PRODUCT_VIDZMEDIA_MONSTERTV,
0,
"VidzMedia Pte Ltd",
@@ -11201,6 +15502,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"Intuos 9x12 Graphics Tablet",
},
{
+ USB_VENDOR_WAGO, USB_PRODUCT_WAGO_SERVICECABLE,
+ 0,
+ "WAGO Kontakttechnik GmbH.",
+ "USB Service Cable 750-923",
+ },
+ {
USB_VENDOR_WAVESENSE, USB_PRODUCT_WAVESENSE_JAZZ,
0,
"WaveSense",
@@ -11213,12 +15520,30 @@ const struct usb_knowndev usb_knowndevs[] = {
"CH341/CH340 USB-Serial Bridge",
},
{
+ USB_VENDOR_WCH2, USB_PRODUCT_WCH2_DUMMY,
+ 0,
+ "QinHeng Electronics",
+ "Dummy product",
+ },
+ {
+ USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH341SER_2,
+ 0,
+ "QinHeng Electronics",
+ "CH341/CH340 USB-Serial Bridge",
+ },
+ {
USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH341SER,
0,
"QinHeng Electronics",
"CH341/CH340 USB-Serial Bridge",
},
{
+ USB_VENDOR_WCH2, USB_PRODUCT_WCH2_U2M,
+ 0,
+ "QinHeng Electronics",
+ "CH345 USB2.0-MIDI",
+ },
+ {
USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_COMBO,
0,
"Western Digital",
@@ -11249,6 +15574,36 @@ const struct usb_knowndev usb_knowndevs[] = {
"MyPassword External HDD",
},
{
+ USB_VENDOR_WETELECOM, USB_PRODUCT_WETELECOM_WM_D200,
+ 0,
+ "WeTelecom",
+ "WM-D200",
+ },
+ {
+ USB_VENDOR_WIENERPLEINBAUS, USB_PRODUCT_WIENERPLEINBAUS_PL512,
+ 0,
+ "WIENER Plein & Baus GmbH.",
+ "PL512 PSU",
+ },
+ {
+ USB_VENDOR_WIENERPLEINBAUS, USB_PRODUCT_WIENERPLEINBAUS_RCM,
+ 0,
+ "WIENER Plein & Baus GmbH.",
+ "RCM Remote Control",
+ },
+ {
+ USB_VENDOR_WIENERPLEINBAUS, USB_PRODUCT_WIENERPLEINBAUS_MPOD,
+ 0,
+ "WIENER Plein & Baus GmbH.",
+ "MPOD PSU",
+ },
+ {
+ USB_VENDOR_WIENERPLEINBAUS, USB_PRODUCT_WIENERPLEINBAUS_CML,
+ 0,
+ "WIENER Plein & Baus GmbH.",
+ "CML Data Logger",
+ },
+ {
USB_VENDOR_WINBOND, USB_PRODUCT_WINBOND_UH104,
0,
"Winbond",
@@ -11333,16 +15688,16 @@ const struct usb_knowndev usb_knowndevs[] = {
"UX96 MIDI I/F",
},
{
- USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTA54I,
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RPU200,
0,
"YAMAHA",
- "NetVolante RTA54i Broadband&ISDN Router",
+ "RP-U200",
},
{
- USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTA55I,
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTA54I,
0,
"YAMAHA",
- "NetVolante RTA55i Broadband VoIP Router",
+ "NetVolante RTA54i Broadband&ISDN Router",
},
{
USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTW65B,
@@ -11357,6 +15712,12 @@ const struct usb_knowndev usb_knowndevs[] = {
"NetVolante RTW65i Broadband&ISDN Wireless Router",
},
{
+ USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTA55I,
+ 0,
+ "YAMAHA",
+ "NetVolante RTA55i Broadband VoIP Router",
+ },
+ {
USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO,
0,
"Yano",
@@ -13145,6 +17506,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_MICRON, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Micron Technology",
+ NULL,
+ },
+ {
USB_VENDOR_VIVITAR, 0,
USB_KNOWNDEV_NOPROD,
"Vivitar",
@@ -13169,6 +17536,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_ACTON, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Acton Research Corp.",
+ NULL,
+ },
+ {
USB_VENDOR_SGI, 0,
USB_KNOWNDEV_NOPROD,
"Silicon Graphics",
@@ -13313,6 +17686,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_CONTEC, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Contec products",
+ NULL,
+ },
+ {
USB_VENDOR_AASHIMA, 0,
USB_KNOWNDEV_NOPROD,
"Aashima Technology",
@@ -13421,9 +17800,9 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
- USB_VENDOR_MIDIMAN, 0,
+ USB_VENDOR_MAUDIO, 0,
USB_KNOWNDEV_NOPROD,
- "Midiman",
+ "M-Audio",
NULL,
},
{
@@ -13667,6 +18046,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_MAGTEK, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Mag-Tek",
+ NULL,
+ },
+ {
USB_VENDOR_ZOOM, 0,
USB_KNOWNDEV_NOPROD,
"Zoom Telephonics",
@@ -14147,15 +18532,33 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_MEDELI, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Medeli",
+ NULL,
+ },
+ {
USB_VENDOR_GEOCAST, 0,
USB_KNOWNDEV_NOPROD,
"Geocast Network Systems",
NULL,
},
{
+ USB_VENDOR_EGO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "EGO systems",
+ NULL,
+ },
+ {
USB_VENDOR_IDQUANTIQUE, 0,
USB_KNOWNDEV_NOPROD,
- "id Quantique",
+ "ID Quantique",
+ NULL,
+ },
+ {
+ USB_VENDOR_IDTECH, 0,
+ USB_KNOWNDEV_NOPROD,
+ "ID TECH",
NULL,
},
{
@@ -14315,6 +18718,18 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_ICOM, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Icom Inc.",
+ NULL,
+ },
+ {
+ USB_VENDOR_GNOTOMETRICS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "GN Otometrics",
+ NULL,
+ },
+ {
USB_VENDOR_CHICONY2, 0,
USB_KNOWNDEV_NOPROD,
"Chicony",
@@ -14333,12 +18748,24 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_JETI, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Jeti",
+ NULL,
+ },
+ {
USB_VENDOR_LUWEN, 0,
USB_KNOWNDEV_NOPROD,
"Luwen",
NULL,
},
{
+ USB_VENDOR_ELEKTOR, 0,
+ USB_KNOWNDEV_NOPROD,
+ "ELEKTOR Electronics",
+ NULL,
+ },
+ {
USB_VENDOR_KYOCERA2, 0,
USB_KNOWNDEV_NOPROD,
"Kyocera Wireless Corp.",
@@ -14357,12 +18784,24 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_POSIFLEX, 0,
+ USB_KNOWNDEV_NOPROD,
+ "POSIFLEX",
+ NULL,
+ },
+ {
USB_VENDOR_TANGTOP, 0,
USB_KNOWNDEV_NOPROD,
"Tangtop",
NULL,
},
{
+ USB_VENDOR_KOBIL, 0,
+ USB_KNOWNDEV_NOPROD,
+ "KOBIL",
+ NULL,
+ },
+ {
USB_VENDOR_SMC3, 0,
USB_KNOWNDEV_NOPROD,
"Standard Microsystems",
@@ -14411,6 +18850,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_UNKNOWN4, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Unknown vendor",
+ NULL,
+ },
+ {
USB_VENDOR_NETAC, 0,
USB_KNOWNDEV_NOPROD,
"Netac",
@@ -14459,6 +18904,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_MEDIATEK, 0,
+ USB_KNOWNDEV_NOPROD,
+ "MediaTek, Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_OTI, 0,
USB_KNOWNDEV_NOPROD,
"Ours Technology",
@@ -14543,6 +18994,18 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_LARSENBRUSGAARD, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Larsen and Brusgaard",
+ NULL,
+ },
+ {
+ USB_VENDOR_KONTRON, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Kontron AG",
+ NULL,
+ },
+ {
USB_VENDOR_QUALCOMM, 0,
USB_KNOWNDEV_NOPROD,
"Qualcomm",
@@ -14573,6 +19036,18 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_NEC3, 0,
+ USB_KNOWNDEV_NOPROD,
+ "NEC",
+ NULL,
+ },
+ {
+ USB_VENDOR_TTI, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Thurlby Thandar Instruments",
+ NULL,
+ },
+ {
USB_VENDOR_GIGABYTE, 0,
USB_KNOWNDEV_NOPROD,
"GIGABYTE",
@@ -14741,6 +19216,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_INTERBIOMETRICS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Interbiometrics",
+ NULL,
+ },
+ {
USB_VENDOR_UNKNOWN3, 0,
USB_KNOWNDEV_NOPROD,
"Unknown vendor",
@@ -14777,6 +19258,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_TESTO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Testo products",
+ NULL,
+ },
+ {
USB_VENDOR_CREATIVE2, 0,
USB_KNOWNDEV_NOPROD,
"Creative Labs",
@@ -14861,6 +19348,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_INITIO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Initio Corporation",
+ NULL,
+ },
+ {
USB_VENDOR_EMTEC, 0,
USB_KNOWNDEV_NOPROD,
"Emtec",
@@ -14879,6 +19372,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_REDOCTANE, 0,
+ USB_KNOWNDEV_NOPROD,
+ "RedOctane",
+ NULL,
+ },
+ {
USB_VENDOR_WISTRONNEWEB, 0,
USB_KNOWNDEV_NOPROD,
"Wistron NeWeb",
@@ -14891,6 +19390,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_FIC, 0,
+ USB_KNOWNDEV_NOPROD,
+ "FIC / OpenMoko",
+ NULL,
+ },
+ {
USB_VENDOR_HUAWEI3COM, 0,
USB_KNOWNDEV_NOPROD,
"Huawei-3Com",
@@ -14999,12 +19504,30 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_OLIMEX, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Olimex",
+ NULL,
+ },
+ {
+ USB_VENDOR_SOUNDGRAPH, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Soundgraph, Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_AMIT2, 0,
USB_KNOWNDEV_NOPROD,
"AMIT",
NULL,
},
{
+ USB_VENDOR_TEXTECH, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Textech International Ltd.",
+ NULL,
+ },
+ {
USB_VENDOR_SOHOWARE, 0,
USB_KNOWNDEV_NOPROD,
"SOHOware",
@@ -15095,6 +19618,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_WIENERPLEINBAUS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "WIENER Plein & Baus GmbH.",
+ NULL,
+ },
+ {
USB_VENDOR_AXESSTEL, 0,
USB_KNOWNDEV_NOPROD,
"Axesstel Co., Ltd.",
@@ -15131,6 +19660,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_KAMSTRUP, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Kamstrup A/S",
+ NULL,
+ },
+ {
USB_VENDOR_WAVESENSE, 0,
USB_KNOWNDEV_NOPROD,
"WaveSense",
@@ -15179,6 +19714,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_BAYER, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Bayer",
+ NULL,
+ },
+ {
USB_VENDOR_WCH2, 0,
USB_KNOWNDEV_NOPROD,
"QinHeng Electronics",
@@ -15191,6 +19732,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_CORSAIR, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Corsair",
+ NULL,
+ },
+ {
USB_VENDOR_MATRIXORBITAL, 0,
USB_KNOWNDEV_NOPROD,
"Matrix Orbital",
@@ -15203,18 +19750,48 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_TML, 0,
+ USB_KNOWNDEV_NOPROD,
+ "The Mobility Lab",
+ NULL,
+ },
+ {
USB_VENDOR_TCTMOBILE, 0,
USB_KNOWNDEV_NOPROD,
"TCT Mobile",
NULL,
},
{
+ USB_VENDOR_ALTI2, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Alti-2 products",
+ NULL,
+ },
+ {
+ USB_VENDOR_SUNPLUS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Sunplus Innovation Technology Inc.",
+ NULL,
+ },
+ {
+ USB_VENDOR_WAGO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "WAGO Kontakttechnik GmbH.",
+ NULL,
+ },
+ {
USB_VENDOR_TELIT, 0,
USB_KNOWNDEV_NOPROD,
"Telit",
NULL,
},
{
+ USB_VENDOR_IONICS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Ionics PlugComputer",
+ NULL,
+ },
+ {
USB_VENDOR_LONGCHEER, 0,
USB_KNOWNDEV_NOPROD,
"Longcheer Holdings, Ltd.",
@@ -15269,6 +19846,18 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_FESTO, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Festo",
+ NULL,
+ },
+ {
+ USB_VENDOR_VERTEX, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Vertex Wireless Co., Ltd.",
+ NULL,
+ },
+ {
USB_VENDOR_DLINK, 0,
USB_KNOWNDEV_NOPROD,
"D-Link",
@@ -15299,12 +19888,36 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_QIHARDWARE, 0,
+ USB_KNOWNDEV_NOPROD,
+ "QI-hardware",
+ NULL,
+ },
+ {
USB_VENDOR_PARA, 0,
USB_KNOWNDEV_NOPROD,
"PARA Industrial",
NULL,
},
{
+ USB_VENDOR_SIMTEC, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Simtec Electronics",
+ NULL,
+ },
+ {
+ USB_VENDOR_RTSYSTEMS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "RTSYSTEMS",
+ NULL,
+ },
+ {
+ USB_VENDOR_VIALABS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "VIA Labs",
+ NULL,
+ },
+ {
USB_VENDOR_ERICSSON, 0,
USB_KNOWNDEV_NOPROD,
"Ericsson",
@@ -15317,6 +19930,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_WETELECOM, 0,
+ USB_KNOWNDEV_NOPROD,
+ "WeTelecom",
+ NULL,
+ },
+ {
USB_VENDOR_TRIPPLITE, 0,
USB_KNOWNDEV_NOPROD,
"Tripp-Lite",
@@ -15347,6 +19966,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_LINKINSTRUMENTS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Link Instruments Inc.",
+ NULL,
+ },
+ {
USB_VENDOR_AEI, 0,
USB_KNOWNDEV_NOPROD,
"AEI",
@@ -15413,6 +20038,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_PAPOUCH, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Papouch products",
+ NULL,
+ },
+ {
USB_VENDOR_AVERATEC, 0,
USB_KNOWNDEV_NOPROD,
"Averatec",
@@ -15509,6 +20140,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_EVOLUTION, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Evolution Robotics products",
+ NULL,
+ },
+ {
USB_VENDOR_DATAAPEX, 0,
USB_KNOWNDEV_NOPROD,
"DataApex",
@@ -15521,6 +20158,12 @@ const struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_LOGILINK, 0,
+ USB_KNOWNDEV_NOPROD,
+ "LogiLink",
+ NULL,
+ },
+ {
USB_VENDOR_USRP, 0,
USB_KNOWNDEV_NOPROD,
"GNU Radio USRP",
diff --git a/rtemsbsd/include/rtems/bsd/local/vnode_if.h b/rtemsbsd/include/rtems/bsd/local/vnode_if.h
deleted file mode 100644
index 367a8db7..00000000
--- a/rtemsbsd/include/rtems/bsd/local/vnode_if.h
+++ /dev/null
@@ -1,1546 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from $FreeBSD$
- */
-
-extern struct vnodeop_desc vop_default_desc;
-#include <rtems/bsd/local/vnode_if_typedef.h>
-#include <rtems/bsd/local/vnode_if_newproto.h>
-struct vop_islocked_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
-};
-
-extern struct vnodeop_desc vop_islocked_desc;
-
-int VOP_ISLOCKED_AP(struct vop_islocked_args *);
-int VOP_ISLOCKED_APV(struct vop_vector *vop, struct vop_islocked_args *);
-
-static __inline int VOP_ISLOCKED(
- struct vnode *vp)
-{
- struct vop_islocked_args a;
-
- a.a_gen.a_desc = &vop_islocked_desc;
- a.a_vp = vp;
- return (VOP_ISLOCKED_APV(vp->v_op, &a));
-}
-
-struct vop_lookup_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_lookup_desc;
-
-int VOP_LOOKUP_AP(struct vop_lookup_args *);
-int VOP_LOOKUP_APV(struct vop_vector *vop, struct vop_lookup_args *);
-
-static __inline int VOP_LOOKUP(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp)
-{
- struct vop_lookup_args a;
-
- a.a_gen.a_desc = &vop_lookup_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- return (VOP_LOOKUP_APV(dvp->v_op, &a));
-}
-
-struct vop_cachedlookup_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_cachedlookup_desc;
-
-int VOP_CACHEDLOOKUP_AP(struct vop_cachedlookup_args *);
-int VOP_CACHEDLOOKUP_APV(struct vop_vector *vop, struct vop_cachedlookup_args *);
-
-static __inline int VOP_CACHEDLOOKUP(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp)
-{
- struct vop_cachedlookup_args a;
-
- a.a_gen.a_desc = &vop_cachedlookup_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- return (VOP_CACHEDLOOKUP_APV(dvp->v_op, &a));
-}
-
-struct vop_create_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-
-extern struct vnodeop_desc vop_create_desc;
-
-int VOP_CREATE_AP(struct vop_create_args *);
-int VOP_CREATE_APV(struct vop_vector *vop, struct vop_create_args *);
-
-static __inline int VOP_CREATE(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap)
-{
- struct vop_create_args a;
-
- a.a_gen.a_desc = &vop_create_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- return (VOP_CREATE_APV(dvp->v_op, &a));
-}
-
-struct vop_whiteout_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct componentname *a_cnp;
- int a_flags;
-};
-
-extern struct vnodeop_desc vop_whiteout_desc;
-
-int VOP_WHITEOUT_AP(struct vop_whiteout_args *);
-int VOP_WHITEOUT_APV(struct vop_vector *vop, struct vop_whiteout_args *);
-
-static __inline int VOP_WHITEOUT(
- struct vnode *dvp,
- struct componentname *cnp,
- int flags)
-{
- struct vop_whiteout_args a;
-
- a.a_gen.a_desc = &vop_whiteout_desc;
- a.a_dvp = dvp;
- a.a_cnp = cnp;
- a.a_flags = flags;
- return (VOP_WHITEOUT_APV(dvp->v_op, &a));
-}
-
-struct vop_mknod_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-
-extern struct vnodeop_desc vop_mknod_desc;
-
-int VOP_MKNOD_AP(struct vop_mknod_args *);
-int VOP_MKNOD_APV(struct vop_vector *vop, struct vop_mknod_args *);
-
-static __inline int VOP_MKNOD(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap)
-{
- struct vop_mknod_args a;
-
- a.a_gen.a_desc = &vop_mknod_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- return (VOP_MKNOD_APV(dvp->v_op, &a));
-}
-
-struct vop_open_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- struct file *a_fp;
-};
-
-extern struct vnodeop_desc vop_open_desc;
-
-int VOP_OPEN_AP(struct vop_open_args *);
-int VOP_OPEN_APV(struct vop_vector *vop, struct vop_open_args *);
-
-static __inline int VOP_OPEN(
- struct vnode *vp,
- int mode,
- struct ucred *cred,
- struct thread *td,
- struct file *fp)
-{
- struct vop_open_args a;
-
- a.a_gen.a_desc = &vop_open_desc;
- a.a_vp = vp;
- a.a_mode = mode;
- a.a_cred = cred;
- a.a_td = td;
- a.a_fp = fp;
- return (VOP_OPEN_APV(vp->v_op, &a));
-}
-
-struct vop_close_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_close_desc;
-
-int VOP_CLOSE_AP(struct vop_close_args *);
-int VOP_CLOSE_APV(struct vop_vector *vop, struct vop_close_args *);
-
-static __inline int VOP_CLOSE(
- struct vnode *vp,
- int fflag,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_close_args a;
-
- a.a_gen.a_desc = &vop_close_desc;
- a.a_vp = vp;
- a.a_fflag = fflag;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_CLOSE_APV(vp->v_op, &a));
-}
-
-struct vop_access_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- accmode_t a_accmode;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_access_desc;
-
-int VOP_ACCESS_AP(struct vop_access_args *);
-int VOP_ACCESS_APV(struct vop_vector *vop, struct vop_access_args *);
-
-static __inline int VOP_ACCESS(
- struct vnode *vp,
- accmode_t accmode,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_access_args a;
-
- a.a_gen.a_desc = &vop_access_desc;
- a.a_vp = vp;
- a.a_accmode = accmode;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_ACCESS_APV(vp->v_op, &a));
-}
-
-struct vop_accessx_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- accmode_t a_accmode;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_accessx_desc;
-
-int VOP_ACCESSX_AP(struct vop_accessx_args *);
-int VOP_ACCESSX_APV(struct vop_vector *vop, struct vop_accessx_args *);
-
-static __inline int VOP_ACCESSX(
- struct vnode *vp,
- accmode_t accmode,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_accessx_args a;
-
- a.a_gen.a_desc = &vop_accessx_desc;
- a.a_vp = vp;
- a.a_accmode = accmode;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_ACCESSX_APV(vp->v_op, &a));
-}
-
-struct vop_getattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_getattr_desc;
-
-int VOP_GETATTR_AP(struct vop_getattr_args *);
-int VOP_GETATTR_APV(struct vop_vector *vop, struct vop_getattr_args *);
-
-static __inline int VOP_GETATTR(
- struct vnode *vp,
- struct vattr *vap,
- struct ucred *cred)
-{
- struct vop_getattr_args a;
-
- a.a_gen.a_desc = &vop_getattr_desc;
- a.a_vp = vp;
- a.a_vap = vap;
- a.a_cred = cred;
- return (VOP_GETATTR_APV(vp->v_op, &a));
-}
-
-struct vop_setattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_setattr_desc;
-
-int VOP_SETATTR_AP(struct vop_setattr_args *);
-int VOP_SETATTR_APV(struct vop_vector *vop, struct vop_setattr_args *);
-
-static __inline int VOP_SETATTR(
- struct vnode *vp,
- struct vattr *vap,
- struct ucred *cred)
-{
- struct vop_setattr_args a;
-
- a.a_gen.a_desc = &vop_setattr_desc;
- a.a_vp = vp;
- a.a_vap = vap;
- a.a_cred = cred;
- return (VOP_SETATTR_APV(vp->v_op, &a));
-}
-
-struct vop_markatime_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
-};
-
-extern struct vnodeop_desc vop_markatime_desc;
-
-int VOP_MARKATIME_AP(struct vop_markatime_args *);
-int VOP_MARKATIME_APV(struct vop_vector *vop, struct vop_markatime_args *);
-
-static __inline int VOP_MARKATIME(
- struct vnode *vp)
-{
- struct vop_markatime_args a;
-
- a.a_gen.a_desc = &vop_markatime_desc;
- a.a_vp = vp;
- return (VOP_MARKATIME_APV(vp->v_op, &a));
-}
-
-struct vop_read_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_read_desc;
-
-int VOP_READ_AP(struct vop_read_args *);
-int VOP_READ_APV(struct vop_vector *vop, struct vop_read_args *);
-
-static __inline int VOP_READ(
- struct vnode *vp,
- struct uio *uio,
- int ioflag,
- struct ucred *cred)
-{
- struct vop_read_args a;
-
- a.a_gen.a_desc = &vop_read_desc;
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_ioflag = ioflag;
- a.a_cred = cred;
- return (VOP_READ_APV(vp->v_op, &a));
-}
-
-struct vop_write_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_write_desc;
-
-int VOP_WRITE_AP(struct vop_write_args *);
-int VOP_WRITE_APV(struct vop_vector *vop, struct vop_write_args *);
-
-static __inline int VOP_WRITE(
- struct vnode *vp,
- struct uio *uio,
- int ioflag,
- struct ucred *cred)
-{
- struct vop_write_args a;
-
- a.a_gen.a_desc = &vop_write_desc;
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_ioflag = ioflag;
- a.a_cred = cred;
- return (VOP_WRITE_APV(vp->v_op, &a));
-}
-
-struct vop_ioctl_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- u_long a_command;
- void *a_data;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_ioctl_desc;
-
-int VOP_IOCTL_AP(struct vop_ioctl_args *);
-int VOP_IOCTL_APV(struct vop_vector *vop, struct vop_ioctl_args *);
-
-static __inline int VOP_IOCTL(
- struct vnode *vp,
- u_long command,
- void *data,
- int fflag,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_ioctl_args a;
-
- a.a_gen.a_desc = &vop_ioctl_desc;
- a.a_vp = vp;
- a.a_command = command;
- a.a_data = data;
- a.a_fflag = fflag;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_IOCTL_APV(vp->v_op, &a));
-}
-
-struct vop_poll_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_events;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_poll_desc;
-
-int VOP_POLL_AP(struct vop_poll_args *);
-int VOP_POLL_APV(struct vop_vector *vop, struct vop_poll_args *);
-
-static __inline int VOP_POLL(
- struct vnode *vp,
- int events,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_poll_args a;
-
- a.a_gen.a_desc = &vop_poll_desc;
- a.a_vp = vp;
- a.a_events = events;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_POLL_APV(vp->v_op, &a));
-}
-
-struct vop_kqfilter_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct knote *a_kn;
-};
-
-extern struct vnodeop_desc vop_kqfilter_desc;
-
-int VOP_KQFILTER_AP(struct vop_kqfilter_args *);
-int VOP_KQFILTER_APV(struct vop_vector *vop, struct vop_kqfilter_args *);
-
-static __inline int VOP_KQFILTER(
- struct vnode *vp,
- struct knote *kn)
-{
- struct vop_kqfilter_args a;
-
- a.a_gen.a_desc = &vop_kqfilter_desc;
- a.a_vp = vp;
- a.a_kn = kn;
- return (VOP_KQFILTER_APV(vp->v_op, &a));
-}
-
-struct vop_revoke_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_flags;
-};
-
-extern struct vnodeop_desc vop_revoke_desc;
-
-int VOP_REVOKE_AP(struct vop_revoke_args *);
-int VOP_REVOKE_APV(struct vop_vector *vop, struct vop_revoke_args *);
-
-static __inline int VOP_REVOKE(
- struct vnode *vp,
- int flags)
-{
- struct vop_revoke_args a;
-
- a.a_gen.a_desc = &vop_revoke_desc;
- a.a_vp = vp;
- a.a_flags = flags;
- return (VOP_REVOKE_APV(vp->v_op, &a));
-}
-
-struct vop_fsync_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_waitfor;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_fsync_desc;
-
-int VOP_FSYNC_AP(struct vop_fsync_args *);
-int VOP_FSYNC_APV(struct vop_vector *vop, struct vop_fsync_args *);
-
-static __inline int VOP_FSYNC(
- struct vnode *vp,
- int waitfor,
- struct thread *td)
-{
- struct vop_fsync_args a;
-
- a.a_gen.a_desc = &vop_fsync_desc;
- a.a_vp = vp;
- a.a_waitfor = waitfor;
- a.a_td = td;
- return (VOP_FSYNC_APV(vp->v_op, &a));
-}
-
-struct vop_remove_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_remove_desc;
-
-int VOP_REMOVE_AP(struct vop_remove_args *);
-int VOP_REMOVE_APV(struct vop_vector *vop, struct vop_remove_args *);
-
-static __inline int VOP_REMOVE(
- struct vnode *dvp,
- struct vnode *vp,
- struct componentname *cnp)
-{
- struct vop_remove_args a;
-
- a.a_gen.a_desc = &vop_remove_desc;
- a.a_dvp = dvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- return (VOP_REMOVE_APV(dvp->v_op, &a));
-}
-
-struct vop_link_args {
- struct vop_generic_args a_gen;
- struct vnode *a_tdvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_link_desc;
-
-int VOP_LINK_AP(struct vop_link_args *);
-int VOP_LINK_APV(struct vop_vector *vop, struct vop_link_args *);
-
-static __inline int VOP_LINK(
- struct vnode *tdvp,
- struct vnode *vp,
- struct componentname *cnp)
-{
- struct vop_link_args a;
-
- a.a_gen.a_desc = &vop_link_desc;
- a.a_tdvp = tdvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- return (VOP_LINK_APV(tdvp->v_op, &a));
-}
-
-struct vop_rename_args {
- struct vop_generic_args a_gen;
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
-};
-
-extern struct vnodeop_desc vop_rename_desc;
-
-int VOP_RENAME_AP(struct vop_rename_args *);
-int VOP_RENAME_APV(struct vop_vector *vop, struct vop_rename_args *);
-
-static __inline int VOP_RENAME(
- struct vnode *fdvp,
- struct vnode *fvp,
- struct componentname *fcnp,
- struct vnode *tdvp,
- struct vnode *tvp,
- struct componentname *tcnp)
-{
- struct vop_rename_args a;
-
- a.a_gen.a_desc = &vop_rename_desc;
- a.a_fdvp = fdvp;
- a.a_fvp = fvp;
- a.a_fcnp = fcnp;
- a.a_tdvp = tdvp;
- a.a_tvp = tvp;
- a.a_tcnp = tcnp;
- return (VOP_RENAME_APV(fdvp->v_op, &a));
-}
-
-struct vop_mkdir_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-
-extern struct vnodeop_desc vop_mkdir_desc;
-
-int VOP_MKDIR_AP(struct vop_mkdir_args *);
-int VOP_MKDIR_APV(struct vop_vector *vop, struct vop_mkdir_args *);
-
-static __inline int VOP_MKDIR(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap)
-{
- struct vop_mkdir_args a;
-
- a.a_gen.a_desc = &vop_mkdir_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- return (VOP_MKDIR_APV(dvp->v_op, &a));
-}
-
-struct vop_rmdir_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_rmdir_desc;
-
-int VOP_RMDIR_AP(struct vop_rmdir_args *);
-int VOP_RMDIR_APV(struct vop_vector *vop, struct vop_rmdir_args *);
-
-static __inline int VOP_RMDIR(
- struct vnode *dvp,
- struct vnode *vp,
- struct componentname *cnp)
-{
- struct vop_rmdir_args a;
-
- a.a_gen.a_desc = &vop_rmdir_desc;
- a.a_dvp = dvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- return (VOP_RMDIR_APV(dvp->v_op, &a));
-}
-
-struct vop_symlink_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
-};
-
-extern struct vnodeop_desc vop_symlink_desc;
-
-int VOP_SYMLINK_AP(struct vop_symlink_args *);
-int VOP_SYMLINK_APV(struct vop_vector *vop, struct vop_symlink_args *);
-
-static __inline int VOP_SYMLINK(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap,
- char *target)
-{
- struct vop_symlink_args a;
-
- a.a_gen.a_desc = &vop_symlink_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- a.a_target = target;
- return (VOP_SYMLINK_APV(dvp->v_op, &a));
-}
-
-struct vop_readdir_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- int *a_eofflag;
- int *a_ncookies;
- u_long **a_cookies;
-};
-
-extern struct vnodeop_desc vop_readdir_desc;
-
-int VOP_READDIR_AP(struct vop_readdir_args *);
-int VOP_READDIR_APV(struct vop_vector *vop, struct vop_readdir_args *);
-
-static __inline int VOP_READDIR(
- struct vnode *vp,
- struct uio *uio,
- struct ucred *cred,
- int *eofflag,
- int *ncookies,
- u_long **cookies)
-{
- struct vop_readdir_args a;
-
- a.a_gen.a_desc = &vop_readdir_desc;
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_cred = cred;
- a.a_eofflag = eofflag;
- a.a_ncookies = ncookies;
- a.a_cookies = cookies;
- return (VOP_READDIR_APV(vp->v_op, &a));
-}
-
-struct vop_readlink_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_readlink_desc;
-
-int VOP_READLINK_AP(struct vop_readlink_args *);
-int VOP_READLINK_APV(struct vop_vector *vop, struct vop_readlink_args *);
-
-static __inline int VOP_READLINK(
- struct vnode *vp,
- struct uio *uio,
- struct ucred *cred)
-{
- struct vop_readlink_args a;
-
- a.a_gen.a_desc = &vop_readlink_desc;
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_cred = cred;
- return (VOP_READLINK_APV(vp->v_op, &a));
-}
-
-struct vop_inactive_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_inactive_desc;
-
-int VOP_INACTIVE_AP(struct vop_inactive_args *);
-int VOP_INACTIVE_APV(struct vop_vector *vop, struct vop_inactive_args *);
-
-static __inline int VOP_INACTIVE(
- struct vnode *vp,
- struct thread *td)
-{
- struct vop_inactive_args a;
-
- a.a_gen.a_desc = &vop_inactive_desc;
- a.a_vp = vp;
- a.a_td = td;
- return (VOP_INACTIVE_APV(vp->v_op, &a));
-}
-
-struct vop_reclaim_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_reclaim_desc;
-
-int VOP_RECLAIM_AP(struct vop_reclaim_args *);
-int VOP_RECLAIM_APV(struct vop_vector *vop, struct vop_reclaim_args *);
-
-static __inline int VOP_RECLAIM(
- struct vnode *vp,
- struct thread *td)
-{
- struct vop_reclaim_args a;
-
- a.a_gen.a_desc = &vop_reclaim_desc;
- a.a_vp = vp;
- a.a_td = td;
- return (VOP_RECLAIM_APV(vp->v_op, &a));
-}
-
-struct vop_lock1_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_flags;
- char *a_file;
- int a_line;
-};
-
-extern struct vnodeop_desc vop_lock1_desc;
-
-int VOP_LOCK1_AP(struct vop_lock1_args *);
-int VOP_LOCK1_APV(struct vop_vector *vop, struct vop_lock1_args *);
-
-static __inline int VOP_LOCK1(
- struct vnode *vp,
- int flags,
- char *file,
- int line)
-{
- struct vop_lock1_args a;
-
- a.a_gen.a_desc = &vop_lock1_desc;
- a.a_vp = vp;
- a.a_flags = flags;
- a.a_file = file;
- a.a_line = line;
- return (VOP_LOCK1_APV(vp->v_op, &a));
-}
-
-struct vop_unlock_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_flags;
-};
-
-extern struct vnodeop_desc vop_unlock_desc;
-
-int VOP_UNLOCK_AP(struct vop_unlock_args *);
-int VOP_UNLOCK_APV(struct vop_vector *vop, struct vop_unlock_args *);
-
-static __inline int VOP_UNLOCK(
- struct vnode *vp,
- int flags)
-{
- struct vop_unlock_args a;
-
- a.a_gen.a_desc = &vop_unlock_desc;
- a.a_vp = vp;
- a.a_flags = flags;
- return (VOP_UNLOCK_APV(vp->v_op, &a));
-}
-
-struct vop_bmap_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- daddr_t a_bn;
- struct bufobj **a_bop;
- daddr_t *a_bnp;
- int *a_runp;
- int *a_runb;
-};
-
-extern struct vnodeop_desc vop_bmap_desc;
-
-int VOP_BMAP_AP(struct vop_bmap_args *);
-int VOP_BMAP_APV(struct vop_vector *vop, struct vop_bmap_args *);
-
-static __inline int VOP_BMAP(
- struct vnode *vp,
- daddr_t bn,
- struct bufobj **bop,
- daddr_t *bnp,
- int *runp,
- int *runb)
-{
- struct vop_bmap_args a;
-
- a.a_gen.a_desc = &vop_bmap_desc;
- a.a_vp = vp;
- a.a_bn = bn;
- a.a_bop = bop;
- a.a_bnp = bnp;
- a.a_runp = runp;
- a.a_runb = runb;
- return (VOP_BMAP_APV(vp->v_op, &a));
-}
-
-struct vop_strategy_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct buf *a_bp;
-};
-
-extern struct vnodeop_desc vop_strategy_desc;
-
-int VOP_STRATEGY_AP(struct vop_strategy_args *);
-int VOP_STRATEGY_APV(struct vop_vector *vop, struct vop_strategy_args *);
-
-static __inline int VOP_STRATEGY(
- struct vnode *vp,
- struct buf *bp)
-{
- struct vop_strategy_args a;
-
- a.a_gen.a_desc = &vop_strategy_desc;
- a.a_vp = vp;
- a.a_bp = bp;
- return (VOP_STRATEGY_APV(vp->v_op, &a));
-}
-
-struct vop_getwritemount_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct mount **a_mpp;
-};
-
-extern struct vnodeop_desc vop_getwritemount_desc;
-
-int VOP_GETWRITEMOUNT_AP(struct vop_getwritemount_args *);
-int VOP_GETWRITEMOUNT_APV(struct vop_vector *vop, struct vop_getwritemount_args *);
-
-static __inline int VOP_GETWRITEMOUNT(
- struct vnode *vp,
- struct mount **mpp)
-{
- struct vop_getwritemount_args a;
-
- a.a_gen.a_desc = &vop_getwritemount_desc;
- a.a_vp = vp;
- a.a_mpp = mpp;
- return (VOP_GETWRITEMOUNT_APV(vp->v_op, &a));
-}
-
-struct vop_print_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
-};
-
-extern struct vnodeop_desc vop_print_desc;
-
-int VOP_PRINT_AP(struct vop_print_args *);
-int VOP_PRINT_APV(struct vop_vector *vop, struct vop_print_args *);
-
-static __inline int VOP_PRINT(
- struct vnode *vp)
-{
- struct vop_print_args a;
-
- a.a_gen.a_desc = &vop_print_desc;
- a.a_vp = vp;
- return (VOP_PRINT_APV(vp->v_op, &a));
-}
-
-struct vop_pathconf_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_name;
- register_t *a_retval;
-};
-
-extern struct vnodeop_desc vop_pathconf_desc;
-
-int VOP_PATHCONF_AP(struct vop_pathconf_args *);
-int VOP_PATHCONF_APV(struct vop_vector *vop, struct vop_pathconf_args *);
-
-static __inline int VOP_PATHCONF(
- struct vnode *vp,
- int name,
- register_t *retval)
-{
- struct vop_pathconf_args a;
-
- a.a_gen.a_desc = &vop_pathconf_desc;
- a.a_vp = vp;
- a.a_name = name;
- a.a_retval = retval;
- return (VOP_PATHCONF_APV(vp->v_op, &a));
-}
-
-struct vop_advlock_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- void *a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
-};
-
-extern struct vnodeop_desc vop_advlock_desc;
-
-int VOP_ADVLOCK_AP(struct vop_advlock_args *);
-int VOP_ADVLOCK_APV(struct vop_vector *vop, struct vop_advlock_args *);
-
-static __inline int VOP_ADVLOCK(
- struct vnode *vp,
- void *id,
- int op,
- struct flock *fl,
- int flags)
-{
- struct vop_advlock_args a;
-
- a.a_gen.a_desc = &vop_advlock_desc;
- a.a_vp = vp;
- a.a_id = id;
- a.a_op = op;
- a.a_fl = fl;
- a.a_flags = flags;
- return (VOP_ADVLOCK_APV(vp->v_op, &a));
-}
-
-struct vop_advlockasync_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- void *a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- struct task *a_task;
- void **a_cookiep;
-};
-
-extern struct vnodeop_desc vop_advlockasync_desc;
-
-int VOP_ADVLOCKASYNC_AP(struct vop_advlockasync_args *);
-int VOP_ADVLOCKASYNC_APV(struct vop_vector *vop, struct vop_advlockasync_args *);
-
-static __inline int VOP_ADVLOCKASYNC(
- struct vnode *vp,
- void *id,
- int op,
- struct flock *fl,
- int flags,
- struct task *task,
- void **cookiep)
-{
- struct vop_advlockasync_args a;
-
- a.a_gen.a_desc = &vop_advlockasync_desc;
- a.a_vp = vp;
- a.a_id = id;
- a.a_op = op;
- a.a_fl = fl;
- a.a_flags = flags;
- a.a_task = task;
- a.a_cookiep = cookiep;
- return (VOP_ADVLOCKASYNC_APV(vp->v_op, &a));
-}
-
-struct vop_reallocblks_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct cluster_save *a_buflist;
-};
-
-extern struct vnodeop_desc vop_reallocblks_desc;
-
-int VOP_REALLOCBLKS_AP(struct vop_reallocblks_args *);
-int VOP_REALLOCBLKS_APV(struct vop_vector *vop, struct vop_reallocblks_args *);
-
-static __inline int VOP_REALLOCBLKS(
- struct vnode *vp,
- struct cluster_save *buflist)
-{
- struct vop_reallocblks_args a;
-
- a.a_gen.a_desc = &vop_reallocblks_desc;
- a.a_vp = vp;
- a.a_buflist = buflist;
- return (VOP_REALLOCBLKS_APV(vp->v_op, &a));
-}
-
-struct vop_getpages_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_reqpage;
- vm_ooffset_t a_offset;
-};
-
-extern struct vnodeop_desc vop_getpages_desc;
-
-int VOP_GETPAGES_AP(struct vop_getpages_args *);
-int VOP_GETPAGES_APV(struct vop_vector *vop, struct vop_getpages_args *);
-
-static __inline int VOP_GETPAGES(
- struct vnode *vp,
- vm_page_t *m,
- int count,
- int reqpage,
- vm_ooffset_t offset)
-{
- struct vop_getpages_args a;
-
- a.a_gen.a_desc = &vop_getpages_desc;
- a.a_vp = vp;
- a.a_m = m;
- a.a_count = count;
- a.a_reqpage = reqpage;
- a.a_offset = offset;
- return (VOP_GETPAGES_APV(vp->v_op, &a));
-}
-
-struct vop_putpages_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_sync;
- int *a_rtvals;
- vm_ooffset_t a_offset;
-};
-
-extern struct vnodeop_desc vop_putpages_desc;
-
-int VOP_PUTPAGES_AP(struct vop_putpages_args *);
-int VOP_PUTPAGES_APV(struct vop_vector *vop, struct vop_putpages_args *);
-
-static __inline int VOP_PUTPAGES(
- struct vnode *vp,
- vm_page_t *m,
- int count,
- int sync,
- int *rtvals,
- vm_ooffset_t offset)
-{
- struct vop_putpages_args a;
-
- a.a_gen.a_desc = &vop_putpages_desc;
- a.a_vp = vp;
- a.a_m = m;
- a.a_count = count;
- a.a_sync = sync;
- a.a_rtvals = rtvals;
- a.a_offset = offset;
- return (VOP_PUTPAGES_APV(vp->v_op, &a));
-}
-
-struct vop_getacl_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_getacl_desc;
-
-int VOP_GETACL_AP(struct vop_getacl_args *);
-int VOP_GETACL_APV(struct vop_vector *vop, struct vop_getacl_args *);
-
-static __inline int VOP_GETACL(
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_getacl_args a;
-
- a.a_gen.a_desc = &vop_getacl_desc;
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_GETACL_APV(vp->v_op, &a));
-}
-
-struct vop_setacl_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_setacl_desc;
-
-int VOP_SETACL_AP(struct vop_setacl_args *);
-int VOP_SETACL_APV(struct vop_vector *vop, struct vop_setacl_args *);
-
-static __inline int VOP_SETACL(
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_setacl_args a;
-
- a.a_gen.a_desc = &vop_setacl_desc;
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_SETACL_APV(vp->v_op, &a));
-}
-
-struct vop_aclcheck_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_aclcheck_desc;
-
-int VOP_ACLCHECK_AP(struct vop_aclcheck_args *);
-int VOP_ACLCHECK_APV(struct vop_vector *vop, struct vop_aclcheck_args *);
-
-static __inline int VOP_ACLCHECK(
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_aclcheck_args a;
-
- a.a_gen.a_desc = &vop_aclcheck_desc;
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_ACLCHECK_APV(vp->v_op, &a));
-}
-
-struct vop_closeextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_commit;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_closeextattr_desc;
-
-int VOP_CLOSEEXTATTR_AP(struct vop_closeextattr_args *);
-int VOP_CLOSEEXTATTR_APV(struct vop_vector *vop, struct vop_closeextattr_args *);
-
-static __inline int VOP_CLOSEEXTATTR(
- struct vnode *vp,
- int commit,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_closeextattr_args a;
-
- a.a_gen.a_desc = &vop_closeextattr_desc;
- a.a_vp = vp;
- a.a_commit = commit;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_CLOSEEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_getextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_attrnamespace;
- const char *a_name;
- struct uio *a_uio;
- size_t *a_size;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_getextattr_desc;
-
-int VOP_GETEXTATTR_AP(struct vop_getextattr_args *);
-int VOP_GETEXTATTR_APV(struct vop_vector *vop, struct vop_getextattr_args *);
-
-static __inline int VOP_GETEXTATTR(
- struct vnode *vp,
- int attrnamespace,
- const char *name,
- struct uio *uio,
- size_t *size,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_getextattr_args a;
-
- a.a_gen.a_desc = &vop_getextattr_desc;
- a.a_vp = vp;
- a.a_attrnamespace = attrnamespace;
- a.a_name = name;
- a.a_uio = uio;
- a.a_size = size;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_GETEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_listextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_attrnamespace;
- struct uio *a_uio;
- size_t *a_size;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_listextattr_desc;
-
-int VOP_LISTEXTATTR_AP(struct vop_listextattr_args *);
-int VOP_LISTEXTATTR_APV(struct vop_vector *vop, struct vop_listextattr_args *);
-
-static __inline int VOP_LISTEXTATTR(
- struct vnode *vp,
- int attrnamespace,
- struct uio *uio,
- size_t *size,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_listextattr_args a;
-
- a.a_gen.a_desc = &vop_listextattr_desc;
- a.a_vp = vp;
- a.a_attrnamespace = attrnamespace;
- a.a_uio = uio;
- a.a_size = size;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_LISTEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_openextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_openextattr_desc;
-
-int VOP_OPENEXTATTR_AP(struct vop_openextattr_args *);
-int VOP_OPENEXTATTR_APV(struct vop_vector *vop, struct vop_openextattr_args *);
-
-static __inline int VOP_OPENEXTATTR(
- struct vnode *vp,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_openextattr_args a;
-
- a.a_gen.a_desc = &vop_openextattr_desc;
- a.a_vp = vp;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_OPENEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_deleteextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_attrnamespace;
- const char *a_name;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_deleteextattr_desc;
-
-int VOP_DELETEEXTATTR_AP(struct vop_deleteextattr_args *);
-int VOP_DELETEEXTATTR_APV(struct vop_vector *vop, struct vop_deleteextattr_args *);
-
-static __inline int VOP_DELETEEXTATTR(
- struct vnode *vp,
- int attrnamespace,
- const char *name,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_deleteextattr_args a;
-
- a.a_gen.a_desc = &vop_deleteextattr_desc;
- a.a_vp = vp;
- a.a_attrnamespace = attrnamespace;
- a.a_name = name;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_DELETEEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_setextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_attrnamespace;
- const char *a_name;
- struct uio *a_uio;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_setextattr_desc;
-
-int VOP_SETEXTATTR_AP(struct vop_setextattr_args *);
-int VOP_SETEXTATTR_APV(struct vop_vector *vop, struct vop_setextattr_args *);
-
-static __inline int VOP_SETEXTATTR(
- struct vnode *vp,
- int attrnamespace,
- const char *name,
- struct uio *uio,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_setextattr_args a;
-
- a.a_gen.a_desc = &vop_setextattr_desc;
- a.a_vp = vp;
- a.a_attrnamespace = attrnamespace;
- a.a_name = name;
- a.a_uio = uio;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_SETEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_setlabel_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct label *a_label;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_setlabel_desc;
-
-int VOP_SETLABEL_AP(struct vop_setlabel_args *);
-int VOP_SETLABEL_APV(struct vop_vector *vop, struct vop_setlabel_args *);
-
-static __inline int VOP_SETLABEL(
- struct vnode *vp,
- struct label *label,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_setlabel_args a;
-
- a.a_gen.a_desc = &vop_setlabel_desc;
- a.a_vp = vp;
- a.a_label = label;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_SETLABEL_APV(vp->v_op, &a));
-}
-
-struct vop_vptofh_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct fid *a_fhp;
-};
-
-extern struct vnodeop_desc vop_vptofh_desc;
-
-int VOP_VPTOFH_AP(struct vop_vptofh_args *);
-int VOP_VPTOFH_APV(struct vop_vector *vop, struct vop_vptofh_args *);
-
-static __inline int VOP_VPTOFH(
- struct vnode *vp,
- struct fid *fhp)
-{
- struct vop_vptofh_args a;
-
- a.a_gen.a_desc = &vop_vptofh_desc;
- a.a_vp = vp;
- a.a_fhp = fhp;
- return (VOP_VPTOFH_APV(vp->v_op, &a));
-}
-
-struct vop_vptocnp_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct vnode **a_vpp;
- struct ucred *a_cred;
- char *a_buf;
- int *a_buflen;
-};
-
-extern struct vnodeop_desc vop_vptocnp_desc;
-
-int VOP_VPTOCNP_AP(struct vop_vptocnp_args *);
-int VOP_VPTOCNP_APV(struct vop_vector *vop, struct vop_vptocnp_args *);
-
-static __inline int VOP_VPTOCNP(
- struct vnode *vp,
- struct vnode **vpp,
- struct ucred *cred,
- char *buf,
- int *buflen)
-{
- struct vop_vptocnp_args a;
-
- a.a_gen.a_desc = &vop_vptocnp_desc;
- a.a_vp = vp;
- a.a_vpp = vpp;
- a.a_cred = cred;
- a.a_buf = buf;
- a.a_buflen = buflen;
- return (VOP_VPTOCNP_APV(vp->v_op, &a));
-}
-
diff --git a/rtemsbsd/include/rtems/bsd/local/vnode_if_newproto.h b/rtemsbsd/include/rtems/bsd/local/vnode_if_newproto.h
deleted file mode 100644
index 4b888acd..00000000
--- a/rtemsbsd/include/rtems/bsd/local/vnode_if_newproto.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from $FreeBSD$
- */
-
-
-struct vop_vector {
- struct vop_vector *vop_default;
- vop_bypass_t *vop_bypass;
- vop_islocked_t *vop_islocked;
- vop_lookup_t *vop_lookup;
- vop_cachedlookup_t *vop_cachedlookup;
- vop_create_t *vop_create;
- vop_whiteout_t *vop_whiteout;
- vop_mknod_t *vop_mknod;
- vop_open_t *vop_open;
- vop_close_t *vop_close;
- vop_access_t *vop_access;
- vop_accessx_t *vop_accessx;
- vop_getattr_t *vop_getattr;
- vop_setattr_t *vop_setattr;
- vop_markatime_t *vop_markatime;
- vop_read_t *vop_read;
- vop_write_t *vop_write;
- vop_ioctl_t *vop_ioctl;
- vop_poll_t *vop_poll;
- vop_kqfilter_t *vop_kqfilter;
- vop_revoke_t *vop_revoke;
- vop_fsync_t *vop_fsync;
- vop_remove_t *vop_remove;
- vop_link_t *vop_link;
- vop_rename_t *vop_rename;
- vop_mkdir_t *vop_mkdir;
- vop_rmdir_t *vop_rmdir;
- vop_symlink_t *vop_symlink;
- vop_readdir_t *vop_readdir;
- vop_readlink_t *vop_readlink;
- vop_inactive_t *vop_inactive;
- vop_reclaim_t *vop_reclaim;
- vop_lock1_t *vop_lock1;
- vop_unlock_t *vop_unlock;
- vop_bmap_t *vop_bmap;
- vop_strategy_t *vop_strategy;
- vop_getwritemount_t *vop_getwritemount;
- vop_print_t *vop_print;
- vop_pathconf_t *vop_pathconf;
- vop_advlock_t *vop_advlock;
- vop_advlockasync_t *vop_advlockasync;
- vop_reallocblks_t *vop_reallocblks;
- vop_getpages_t *vop_getpages;
- vop_putpages_t *vop_putpages;
- vop_getacl_t *vop_getacl;
- vop_setacl_t *vop_setacl;
- vop_aclcheck_t *vop_aclcheck;
- vop_closeextattr_t *vop_closeextattr;
- vop_getextattr_t *vop_getextattr;
- vop_listextattr_t *vop_listextattr;
- vop_openextattr_t *vop_openextattr;
- vop_deleteextattr_t *vop_deleteextattr;
- vop_setextattr_t *vop_setextattr;
- vop_setlabel_t *vop_setlabel;
- vop_vptofh_t *vop_vptofh;
- vop_vptocnp_t *vop_vptocnp;
-};
diff --git a/rtemsbsd/include/rtems/bsd/local/vnode_if_typedef.h b/rtemsbsd/include/rtems/bsd/local/vnode_if_typedef.h
deleted file mode 100644
index b7157011..00000000
--- a/rtemsbsd/include/rtems/bsd/local/vnode_if_typedef.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from $FreeBSD$
- */
-
-
-struct vop_islocked_args;
-typedef int vop_islocked_t(struct vop_islocked_args *);
-
-struct vop_lookup_args;
-typedef int vop_lookup_t(struct vop_lookup_args *);
-
-struct vop_cachedlookup_args;
-typedef int vop_cachedlookup_t(struct vop_cachedlookup_args *);
-
-struct vop_create_args;
-typedef int vop_create_t(struct vop_create_args *);
-
-struct vop_whiteout_args;
-typedef int vop_whiteout_t(struct vop_whiteout_args *);
-
-struct vop_mknod_args;
-typedef int vop_mknod_t(struct vop_mknod_args *);
-
-struct vop_open_args;
-typedef int vop_open_t(struct vop_open_args *);
-
-struct vop_close_args;
-typedef int vop_close_t(struct vop_close_args *);
-
-struct vop_access_args;
-typedef int vop_access_t(struct vop_access_args *);
-
-struct vop_accessx_args;
-typedef int vop_accessx_t(struct vop_accessx_args *);
-
-struct vop_getattr_args;
-typedef int vop_getattr_t(struct vop_getattr_args *);
-
-struct vop_setattr_args;
-typedef int vop_setattr_t(struct vop_setattr_args *);
-
-struct vop_markatime_args;
-typedef int vop_markatime_t(struct vop_markatime_args *);
-
-struct vop_read_args;
-typedef int vop_read_t(struct vop_read_args *);
-
-struct vop_write_args;
-typedef int vop_write_t(struct vop_write_args *);
-
-struct vop_ioctl_args;
-typedef int vop_ioctl_t(struct vop_ioctl_args *);
-
-struct vop_poll_args;
-typedef int vop_poll_t(struct vop_poll_args *);
-
-struct vop_kqfilter_args;
-typedef int vop_kqfilter_t(struct vop_kqfilter_args *);
-
-struct vop_revoke_args;
-typedef int vop_revoke_t(struct vop_revoke_args *);
-
-struct vop_fsync_args;
-typedef int vop_fsync_t(struct vop_fsync_args *);
-
-struct vop_remove_args;
-typedef int vop_remove_t(struct vop_remove_args *);
-
-struct vop_link_args;
-typedef int vop_link_t(struct vop_link_args *);
-
-struct vop_rename_args;
-typedef int vop_rename_t(struct vop_rename_args *);
-
-struct vop_mkdir_args;
-typedef int vop_mkdir_t(struct vop_mkdir_args *);
-
-struct vop_rmdir_args;
-typedef int vop_rmdir_t(struct vop_rmdir_args *);
-
-struct vop_symlink_args;
-typedef int vop_symlink_t(struct vop_symlink_args *);
-
-struct vop_readdir_args;
-typedef int vop_readdir_t(struct vop_readdir_args *);
-
-struct vop_readlink_args;
-typedef int vop_readlink_t(struct vop_readlink_args *);
-
-struct vop_inactive_args;
-typedef int vop_inactive_t(struct vop_inactive_args *);
-
-struct vop_reclaim_args;
-typedef int vop_reclaim_t(struct vop_reclaim_args *);
-
-struct vop_lock1_args;
-typedef int vop_lock1_t(struct vop_lock1_args *);
-
-struct vop_unlock_args;
-typedef int vop_unlock_t(struct vop_unlock_args *);
-
-struct vop_bmap_args;
-typedef int vop_bmap_t(struct vop_bmap_args *);
-
-struct vop_strategy_args;
-typedef int vop_strategy_t(struct vop_strategy_args *);
-
-struct vop_getwritemount_args;
-typedef int vop_getwritemount_t(struct vop_getwritemount_args *);
-
-struct vop_print_args;
-typedef int vop_print_t(struct vop_print_args *);
-
-struct vop_pathconf_args;
-typedef int vop_pathconf_t(struct vop_pathconf_args *);
-
-struct vop_advlock_args;
-typedef int vop_advlock_t(struct vop_advlock_args *);
-
-struct vop_advlockasync_args;
-typedef int vop_advlockasync_t(struct vop_advlockasync_args *);
-
-struct vop_reallocblks_args;
-typedef int vop_reallocblks_t(struct vop_reallocblks_args *);
-
-struct vop_getpages_args;
-typedef int vop_getpages_t(struct vop_getpages_args *);
-
-struct vop_putpages_args;
-typedef int vop_putpages_t(struct vop_putpages_args *);
-
-struct vop_getacl_args;
-typedef int vop_getacl_t(struct vop_getacl_args *);
-
-struct vop_setacl_args;
-typedef int vop_setacl_t(struct vop_setacl_args *);
-
-struct vop_aclcheck_args;
-typedef int vop_aclcheck_t(struct vop_aclcheck_args *);
-
-struct vop_closeextattr_args;
-typedef int vop_closeextattr_t(struct vop_closeextattr_args *);
-
-struct vop_getextattr_args;
-typedef int vop_getextattr_t(struct vop_getextattr_args *);
-
-struct vop_listextattr_args;
-typedef int vop_listextattr_t(struct vop_listextattr_args *);
-
-struct vop_openextattr_args;
-typedef int vop_openextattr_t(struct vop_openextattr_args *);
-
-struct vop_deleteextattr_args;
-typedef int vop_deleteextattr_t(struct vop_deleteextattr_args *);
-
-struct vop_setextattr_args;
-typedef int vop_setextattr_t(struct vop_setextattr_args *);
-
-struct vop_setlabel_args;
-typedef int vop_setlabel_t(struct vop_setlabel_args *);
-
-struct vop_vptofh_args;
-typedef int vop_vptofh_t(struct vop_vptofh_args *);
-
-struct vop_vptocnp_args;
-typedef int vop_vptocnp_t(struct vop_vptocnp_args *);
-
diff --git a/rtemsbsd/local/bus_if.c b/rtemsbsd/local/bus_if.c
index 77a982b8..f758bf4d 100644
--- a/rtemsbsd/local/bus_if.c
+++ b/rtemsbsd/local/bus_if.c
@@ -5,7 +5,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * kern/bus_if.m
+ * freebsd-org/sys/kern/bus_if.m
* with
* makeobjops.awk
*
@@ -127,6 +127,14 @@ struct kobjop_desc bus_deactivate_resource_desc = {
0, &bus_deactivate_resource_method_default
};
+struct kobj_method bus_adjust_resource_method_default = {
+ &bus_adjust_resource_desc, (kobjop_t) kobj_error_method
+};
+
+struct kobjop_desc bus_adjust_resource_desc = {
+ 0, &bus_adjust_resource_method_default
+};
+
struct kobj_method bus_release_resource_method_default = {
&bus_release_resource_desc, (kobjop_t) kobj_error_method
};
diff --git a/rtemsbsd/local/device_if.c b/rtemsbsd/local/device_if.c
index ba29ef4a..3bdedbc5 100644
--- a/rtemsbsd/local/device_if.c
+++ b/rtemsbsd/local/device_if.c
@@ -5,7 +5,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * kern/device_if.m
+ * freebsd-org/sys/kern/device_if.m
* with
* makeobjops.awk
*
diff --git a/rtemsbsd/local/pci_if.c b/rtemsbsd/local/pci_if.c
index 7a939f6a..fddebdca 100644
--- a/rtemsbsd/local/pci_if.c
+++ b/rtemsbsd/local/pci_if.c
@@ -5,7 +5,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * dev/pci/pci_if.m
+ * freebsd-org/sys/dev/pci/pci_if.m
* with
* makeobjops.awk
*
diff --git a/rtemsbsd/local/pcib_if.c b/rtemsbsd/local/pcib_if.c
index bdb60e44..82a5965c 100644
--- a/rtemsbsd/local/pcib_if.c
+++ b/rtemsbsd/local/pcib_if.c
@@ -5,7 +5,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * dev/pci/pcib_if.m
+ * freebsd-org/sys/dev/pci/pcib_if.m
* with
* makeobjops.awk
*
diff --git a/rtemsbsd/local/usb_if.c b/rtemsbsd/local/usb_if.c
index 766b1243..5277e529 100644
--- a/rtemsbsd/local/usb_if.c
+++ b/rtemsbsd/local/usb_if.c
@@ -5,7 +5,7 @@
* Do not modify anything in here by hand.
*
* Created from source file
- * dev/usb/usb_if.m
+ * freebsd-org/sys/dev/usb/usb_if.m
* with
* makeobjops.awk
*
@@ -27,3 +27,11 @@ struct kobjop_desc usb_handle_request_desc = {
0, &usb_handle_request_method_default
};
+struct kobj_method usb_take_controller_method_default = {
+ &usb_take_controller_desc, (kobjop_t) kobj_error_method
+};
+
+struct kobjop_desc usb_take_controller_desc = {
+ 0, &usb_take_controller_method_default
+};
+
diff --git a/rtemsbsd/rtems/rtems-bsd-pci_bus.c b/rtemsbsd/rtems/rtems-bsd-pci_bus.c
index 4ceddfce..51ae99c1 100644
--- a/rtemsbsd/rtems/rtems-bsd-pci_bus.c
+++ b/rtemsbsd/rtems/rtems-bsd-pci_bus.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <rtems/bsd/local/pcib_if.h>
+#define pci_find_device rtems_pci_find_device
#include <rtems/pci.h>
#include <machine/bus.h>
diff --git a/rtemsbsd/rtems/rtems-bsd-pci_cfgreg.c b/rtemsbsd/rtems/rtems-bsd-pci_cfgreg.c
index 14c9edd0..15c56b8b 100644
--- a/rtemsbsd/rtems/rtems-bsd-pci_cfgreg.c
+++ b/rtemsbsd/rtems/rtems-bsd-pci_cfgreg.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
+#define pci_find_device rtems_pci_find_device
#include <rtems/pci.h>