1093454e2SDmitry Fleytman /* 2093454e2SDmitry Fleytman * QEMU e1000(e) emulation - shared code 3093454e2SDmitry Fleytman * 4093454e2SDmitry Fleytman * Copyright (c) 2008 Qumranet 5093454e2SDmitry Fleytman * 6093454e2SDmitry Fleytman * Based on work done by: 7093454e2SDmitry Fleytman * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. 8093454e2SDmitry Fleytman * Copyright (c) 2007 Dan Aloni 9093454e2SDmitry Fleytman * Copyright (c) 2004 Antony T Curtis 10093454e2SDmitry Fleytman * 11093454e2SDmitry Fleytman * This library is free software; you can redistribute it and/or 12093454e2SDmitry Fleytman * modify it under the terms of the GNU Lesser General Public 13093454e2SDmitry Fleytman * License as published by the Free Software Foundation; either 14093454e2SDmitry Fleytman * version 2 of the License, or (at your option) any later version. 15093454e2SDmitry Fleytman * 16093454e2SDmitry Fleytman * This library is distributed in the hope that it will be useful, 17093454e2SDmitry Fleytman * but WITHOUT ANY WARRANTY; without even the implied warranty of 18093454e2SDmitry Fleytman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19093454e2SDmitry Fleytman * Lesser General Public License for more details. 20093454e2SDmitry Fleytman * 21093454e2SDmitry Fleytman * You should have received a copy of the GNU Lesser General Public 22093454e2SDmitry Fleytman * License along with this library; if not, see <http://www.gnu.org/licenses/>. 23093454e2SDmitry Fleytman */ 24093454e2SDmitry Fleytman 25093454e2SDmitry Fleytman #include "e1000_regs.h" 26093454e2SDmitry Fleytman 27093454e2SDmitry Fleytman #define defreg(x) x = (E1000_##x >> 2) 28093454e2SDmitry Fleytman enum { 29093454e2SDmitry Fleytman defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC), 30093454e2SDmitry Fleytman defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC), 31093454e2SDmitry Fleytman defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC), 32093454e2SDmitry Fleytman defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH0), 33093454e2SDmitry Fleytman defreg(RDBAL0), defreg(RDH0), defreg(RDLEN0), defreg(RDT0), 34093454e2SDmitry Fleytman defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH), 35093454e2SDmitry Fleytman defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT), 36093454e2SDmitry Fleytman defreg(TDLEN1), defreg(TDBAL1), defreg(TDBAH1), defreg(TDH1), 37093454e2SDmitry Fleytman defreg(TDT1), defreg(TORH), defreg(TORL), defreg(TOTH), 38093454e2SDmitry Fleytman defreg(TOTL), defreg(TPR), defreg(TPT), defreg(TXDCTL), 39093454e2SDmitry Fleytman defreg(WUFC), defreg(RA), defreg(MTA), defreg(CRCERRS), 40093454e2SDmitry Fleytman defreg(VFTA), defreg(VET), defreg(RDTR), defreg(RADV), 41093454e2SDmitry Fleytman defreg(TADV), defreg(ITR), defreg(SCC), defreg(ECOL), 42093454e2SDmitry Fleytman defreg(MCC), defreg(LATECOL), defreg(COLC), defreg(DC), 43*757704f1SKamil Rytarowski defreg(TNCRS), defreg(SEQEC), defreg(CEXTERR), defreg(RLEC), 44093454e2SDmitry Fleytman defreg(XONRXC), defreg(XONTXC), defreg(XOFFRXC), defreg(XOFFTXC), 45093454e2SDmitry Fleytman defreg(FCRUC), defreg(AIT), defreg(TDFH), defreg(TDFT), 46093454e2SDmitry Fleytman defreg(TDFHS), defreg(TDFTS), defreg(TDFPC), defreg(WUC), 47093454e2SDmitry Fleytman defreg(WUS), defreg(POEMB), defreg(PBS), defreg(RDFH), 48093454e2SDmitry Fleytman defreg(RDFT), defreg(RDFHS), defreg(RDFTS), defreg(RDFPC), 49093454e2SDmitry Fleytman defreg(PBM), defreg(IPAV), defreg(IP4AT), defreg(IP6AT), 50093454e2SDmitry Fleytman defreg(WUPM), defreg(FFLT), defreg(FFMT), defreg(FFVT), 51093454e2SDmitry Fleytman defreg(TARC0), defreg(TARC1), defreg(IAM), defreg(EXTCNF_CTRL), 52093454e2SDmitry Fleytman defreg(GCR), defreg(TIMINCA), defreg(EIAC), defreg(CTRL_EXT), 53093454e2SDmitry Fleytman defreg(IVAR), defreg(MFUTP01), defreg(MFUTP23), defreg(MANC2H), 54093454e2SDmitry Fleytman defreg(MFVAL), defreg(MDEF), defreg(FACTPS), defreg(FTFT), 55093454e2SDmitry Fleytman defreg(RUC), defreg(ROC), defreg(RFC), defreg(RJC), 56093454e2SDmitry Fleytman defreg(PRC64), defreg(PRC127), defreg(PRC255), defreg(PRC511), 57093454e2SDmitry Fleytman defreg(PRC1023), defreg(PRC1522), defreg(PTC64), defreg(PTC127), 58093454e2SDmitry Fleytman defreg(PTC255), defreg(PTC511), defreg(PTC1023), defreg(PTC1522), 59093454e2SDmitry Fleytman defreg(GORCL), defreg(GORCH), defreg(GOTCL), defreg(GOTCH), 60093454e2SDmitry Fleytman defreg(RNBC), defreg(BPRC), defreg(MPRC), defreg(RFCTL), 61093454e2SDmitry Fleytman defreg(PSRCTL), defreg(MPTC), defreg(BPTC), defreg(TSCTFC), 62093454e2SDmitry Fleytman defreg(IAC), defreg(MGTPRC), defreg(MGTPDC), defreg(MGTPTC), 63093454e2SDmitry Fleytman defreg(TSCTC), defreg(RXCSUM), defreg(FUNCTAG), defreg(GSCL_1), 64093454e2SDmitry Fleytman defreg(GSCL_2), defreg(GSCL_3), defreg(GSCL_4), defreg(GSCN_0), 65093454e2SDmitry Fleytman defreg(GSCN_1), defreg(GSCN_2), defreg(GSCN_3), defreg(GCR2), 66093454e2SDmitry Fleytman defreg(RAID), defreg(RSRPD), defreg(TIDV), defreg(EITR), 67093454e2SDmitry Fleytman defreg(MRQC), defreg(RETA), defreg(RSSRK), defreg(RDBAH1), 68093454e2SDmitry Fleytman defreg(RDBAL1), defreg(RDLEN1), defreg(RDH1), defreg(RDT1), 69093454e2SDmitry Fleytman defreg(PBACLR), defreg(FCAL), defreg(FCAH), defreg(FCT), 70093454e2SDmitry Fleytman defreg(FCRTH), defreg(FCRTL), defreg(FCTTV), defreg(FCRTV), 71093454e2SDmitry Fleytman defreg(FLA), defreg(EEWR), defreg(FLOP), defreg(FLOL), 72093454e2SDmitry Fleytman defreg(FLSWCTL), defreg(FLSWCNT), defreg(RXDCTL), defreg(RXDCTL1), 73093454e2SDmitry Fleytman defreg(MAVTV0), defreg(MAVTV1), defreg(MAVTV2), defreg(MAVTV3), 74093454e2SDmitry Fleytman defreg(TXSTMPL), defreg(TXSTMPH), defreg(SYSTIML), defreg(SYSTIMH), 75093454e2SDmitry Fleytman defreg(RXCFGL), defreg(RXUDP), defreg(TIMADJL), defreg(TIMADJH), 76093454e2SDmitry Fleytman defreg(RXSTMPH), defreg(RXSTMPL), defreg(RXSATRL), defreg(RXSATRH), 77093454e2SDmitry Fleytman defreg(FLASHT), defreg(TIPG), defreg(RDH), defreg(RDT), 78093454e2SDmitry Fleytman defreg(RDLEN), defreg(RDBAH), defreg(RDBAL), 79093454e2SDmitry Fleytman defreg(TXDCTL1), 80093454e2SDmitry Fleytman defreg(FLSWDATA), 81093454e2SDmitry Fleytman defreg(CTRL_DUP), 82093454e2SDmitry Fleytman defreg(EXTCNF_SIZE), 83093454e2SDmitry Fleytman defreg(EEMNGCTL), 84093454e2SDmitry Fleytman defreg(EEMNGDATA), 85093454e2SDmitry Fleytman defreg(FLMNGCTL), 86093454e2SDmitry Fleytman defreg(FLMNGDATA), 87093454e2SDmitry Fleytman defreg(FLMNGCNT), 88093454e2SDmitry Fleytman defreg(TSYNCRXCTL), 89093454e2SDmitry Fleytman defreg(TSYNCTXCTL), 90093454e2SDmitry Fleytman 91093454e2SDmitry Fleytman /* Aliases */ 92093454e2SDmitry Fleytman defreg(RDH0_A), defreg(RDT0_A), defreg(RDTR_A), defreg(RDFH_A), 93093454e2SDmitry Fleytman defreg(RDFT_A), defreg(TDH_A), defreg(TDT_A), defreg(TIDV_A), 94093454e2SDmitry Fleytman defreg(TDFH_A), defreg(TDFT_A), defreg(RA_A), defreg(RDBAL0_A), 95093454e2SDmitry Fleytman defreg(TDBAL_A), defreg(TDLEN_A), defreg(VFTA_A), defreg(RDLEN0_A), 96093454e2SDmitry Fleytman defreg(FCRTL_A), defreg(FCRTH_A) 97093454e2SDmitry Fleytman }; 98093454e2SDmitry Fleytman 99093454e2SDmitry Fleytman static inline void 100093454e2SDmitry Fleytman e1000x_inc_reg_if_not_full(uint32_t *mac, int index) 101093454e2SDmitry Fleytman { 102093454e2SDmitry Fleytman if (mac[index] != 0xffffffff) { 103093454e2SDmitry Fleytman mac[index]++; 104093454e2SDmitry Fleytman } 105093454e2SDmitry Fleytman } 106093454e2SDmitry Fleytman 107093454e2SDmitry Fleytman static inline void 108093454e2SDmitry Fleytman e1000x_grow_8reg_if_not_full(uint32_t *mac, int index, int size) 109093454e2SDmitry Fleytman { 110093454e2SDmitry Fleytman uint64_t sum = mac[index] | (uint64_t)mac[index + 1] << 32; 111093454e2SDmitry Fleytman 112093454e2SDmitry Fleytman if (sum + size < sum) { 113093454e2SDmitry Fleytman sum = ~0ULL; 114093454e2SDmitry Fleytman } else { 115093454e2SDmitry Fleytman sum += size; 116093454e2SDmitry Fleytman } 117093454e2SDmitry Fleytman mac[index] = sum; 118093454e2SDmitry Fleytman mac[index + 1] = sum >> 32; 119093454e2SDmitry Fleytman } 120093454e2SDmitry Fleytman 121093454e2SDmitry Fleytman static inline int 122093454e2SDmitry Fleytman e1000x_vlan_enabled(uint32_t *mac) 123093454e2SDmitry Fleytman { 124093454e2SDmitry Fleytman return ((mac[CTRL] & E1000_CTRL_VME) != 0); 125093454e2SDmitry Fleytman } 126093454e2SDmitry Fleytman 127093454e2SDmitry Fleytman static inline int 128093454e2SDmitry Fleytman e1000x_is_vlan_txd(uint32_t txd_lower) 129093454e2SDmitry Fleytman { 130093454e2SDmitry Fleytman return ((txd_lower & E1000_TXD_CMD_VLE) != 0); 131093454e2SDmitry Fleytman } 132093454e2SDmitry Fleytman 133093454e2SDmitry Fleytman static inline int 134093454e2SDmitry Fleytman e1000x_vlan_rx_filter_enabled(uint32_t *mac) 135093454e2SDmitry Fleytman { 136093454e2SDmitry Fleytman return ((mac[RCTL] & E1000_RCTL_VFE) != 0); 137093454e2SDmitry Fleytman } 138093454e2SDmitry Fleytman 139093454e2SDmitry Fleytman static inline int 140093454e2SDmitry Fleytman e1000x_fcs_len(uint32_t *mac) 141093454e2SDmitry Fleytman { 142093454e2SDmitry Fleytman /* FCS aka Ethernet CRC-32. We don't get it from backends and can't 143093454e2SDmitry Fleytman * fill it in, just pad descriptor length by 4 bytes unless guest 144093454e2SDmitry Fleytman * told us to strip it off the packet. */ 145093454e2SDmitry Fleytman return (mac[RCTL] & E1000_RCTL_SECRC) ? 0 : 4; 146093454e2SDmitry Fleytman } 147093454e2SDmitry Fleytman 148093454e2SDmitry Fleytman static inline void 149093454e2SDmitry Fleytman e1000x_update_regs_on_link_down(uint32_t *mac, uint16_t *phy) 150093454e2SDmitry Fleytman { 151093454e2SDmitry Fleytman mac[STATUS] &= ~E1000_STATUS_LU; 152093454e2SDmitry Fleytman phy[PHY_STATUS] &= ~MII_SR_LINK_STATUS; 153093454e2SDmitry Fleytman phy[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE; 154093454e2SDmitry Fleytman phy[PHY_LP_ABILITY] &= ~MII_LPAR_LPACK; 155093454e2SDmitry Fleytman } 156093454e2SDmitry Fleytman 157093454e2SDmitry Fleytman static inline void 158093454e2SDmitry Fleytman e1000x_update_regs_on_link_up(uint32_t *mac, uint16_t *phy) 159093454e2SDmitry Fleytman { 160093454e2SDmitry Fleytman mac[STATUS] |= E1000_STATUS_LU; 161093454e2SDmitry Fleytman phy[PHY_STATUS] |= MII_SR_LINK_STATUS; 162093454e2SDmitry Fleytman } 163093454e2SDmitry Fleytman 164093454e2SDmitry Fleytman void e1000x_update_rx_total_stats(uint32_t *mac, 165093454e2SDmitry Fleytman size_t data_size, 166093454e2SDmitry Fleytman size_t data_fcs_size); 167093454e2SDmitry Fleytman 168093454e2SDmitry Fleytman void e1000x_core_prepare_eeprom(uint16_t *eeprom, 169093454e2SDmitry Fleytman const uint16_t *templ, 170093454e2SDmitry Fleytman uint32_t templ_size, 171093454e2SDmitry Fleytman uint16_t dev_id, 172093454e2SDmitry Fleytman const uint8_t *macaddr); 173093454e2SDmitry Fleytman 174093454e2SDmitry Fleytman uint32_t e1000x_rxbufsize(uint32_t rctl); 175093454e2SDmitry Fleytman 176093454e2SDmitry Fleytman bool e1000x_rx_ready(PCIDevice *d, uint32_t *mac); 177093454e2SDmitry Fleytman 178093454e2SDmitry Fleytman bool e1000x_is_vlan_packet(const uint8_t *buf, uint16_t vet); 179093454e2SDmitry Fleytman 180093454e2SDmitry Fleytman bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf); 181093454e2SDmitry Fleytman 182093454e2SDmitry Fleytman bool e1000x_hw_rx_enabled(uint32_t *mac); 183093454e2SDmitry Fleytman 184093454e2SDmitry Fleytman bool e1000x_is_oversized(uint32_t *mac, size_t size); 185093454e2SDmitry Fleytman 186093454e2SDmitry Fleytman void e1000x_restart_autoneg(uint32_t *mac, uint16_t *phy, QEMUTimer *timer); 187093454e2SDmitry Fleytman 188093454e2SDmitry Fleytman void e1000x_reset_mac_addr(NICState *nic, uint32_t *mac_regs, 189093454e2SDmitry Fleytman uint8_t *mac_addr); 190093454e2SDmitry Fleytman 191093454e2SDmitry Fleytman void e1000x_update_regs_on_autoneg_done(uint32_t *mac, uint16_t *phy); 192093454e2SDmitry Fleytman 193093454e2SDmitry Fleytman void e1000x_increase_size_stats(uint32_t *mac, const int *size_regs, int size); 194093454e2SDmitry Fleytman 195093454e2SDmitry Fleytman typedef struct e1000x_txd_props { 196093454e2SDmitry Fleytman unsigned char sum_needed; 197093454e2SDmitry Fleytman uint8_t ipcss; 198093454e2SDmitry Fleytman uint8_t ipcso; 199093454e2SDmitry Fleytman uint16_t ipcse; 200093454e2SDmitry Fleytman uint8_t tucss; 201093454e2SDmitry Fleytman uint8_t tucso; 202093454e2SDmitry Fleytman uint16_t tucse; 203093454e2SDmitry Fleytman uint32_t paylen; 204093454e2SDmitry Fleytman uint8_t hdr_len; 205093454e2SDmitry Fleytman uint16_t mss; 206093454e2SDmitry Fleytman int8_t ip; 207093454e2SDmitry Fleytman int8_t tcp; 208093454e2SDmitry Fleytman bool tse; 209093454e2SDmitry Fleytman bool cptse; 210093454e2SDmitry Fleytman } e1000x_txd_props; 211093454e2SDmitry Fleytman 212093454e2SDmitry Fleytman void e1000x_read_tx_ctx_descr(struct e1000_context_desc *d, 213093454e2SDmitry Fleytman e1000x_txd_props *props); 214