diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c')
-rw-r--r-- | drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c | 664 |
1 files changed, 662 insertions, 2 deletions
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c index bfa05c5..4949b79 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c @@ -45,12 +45,13 @@ #include "fman_common.h" #include "fm_port.h" - +#include "fm_port_dsar.h" #include "common/general.h" /****************************************/ /* static functions */ /****************************************/ +static t_Error FmPortConfigAutoResForDeepSleepSupport1(t_FmPort *p_FmPort); static t_Error CheckInitParameters(t_FmPort *p_FmPort) { @@ -2252,6 +2253,9 @@ t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams) return p_FmPort; } +t_FmPort *rx_port = 0; +t_FmPort *tx_port = 0; + /**************************************************************************//** @Function FM_PORT_Init @@ -2443,7 +2447,10 @@ t_Error FM_PORT_Init(t_Handle h_FmPort) #endif /* FM_ERROR_VSP_NO_MATCH_SW006 */ } #endif /* (DPAA_VERSION >= 11) */ - + + if (p_FmPort->deepSleepVars.autoResMaxSizes) + FmPortConfigAutoResForDeepSleepSupport1(p_FmPort); + return E_OK; } @@ -5183,3 +5190,656 @@ t_Error FM_PORT_GetIPv4OptionsCount(t_Handle h_FmPort, uint32_t *p_Ipv4OptionsCo } #endif /* (DPAA_VERSION >= 11) */ +t_Error FM_PORT_ConfigDsarSupport(t_Handle h_FmPortRx, t_FmPortDsarTablesSizes *params) +{ + t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx; + p_FmPort->deepSleepVars.autoResMaxSizes = XX_Malloc(sizeof(struct t_FmPortDsarTablesSizes)); + memcpy(p_FmPort->deepSleepVars.autoResMaxSizes, params, sizeof(struct t_FmPortDsarTablesSizes)); + return E_OK; +} + +static t_Error FmPortConfigAutoResForDeepSleepSupport1(t_FmPort *p_FmPort) +{ + uint32_t *param_page; + t_FmPortDsarTablesSizes *params = p_FmPort->deepSleepVars.autoResMaxSizes; + t_ArCommonDesc *ArCommonDescPtr; + uint32_t size = sizeof(t_ArCommonDesc); + // ARP + // should put here if (params->max_num_of_arp_entries)? + size = ROUND_UP(size,4); + size += sizeof(t_DsarArpDescriptor); + size += sizeof(t_DsarArpBindingEntry) * params->maxNumOfArpEntries; + size += sizeof(t_DsarArpStatistics); + //ICMPV4 + size = ROUND_UP(size,4); + size += sizeof(t_DsarIcmpV4Descriptor); + size += sizeof(t_DsarIcmpV4BindingEntry) * params->maxNumOfEchoIpv4Entries; + size += sizeof(t_DsarIcmpV4Statistics); + //ICMPV6 + size = ROUND_UP(size,4); + size += sizeof(t_DsarIcmpV6Descriptor); + size += sizeof(t_DsarIcmpV6BindingEntry) * params->maxNumOfEchoIpv6Entries; + size += sizeof(t_DsarIcmpV6Statistics); + //ND + size = ROUND_UP(size,4); + size += sizeof(t_DsarNdDescriptor); + size += sizeof(t_DsarIcmpV6BindingEntry) * params->maxNumOfNdpEntries; + size += sizeof(t_DsarIcmpV6Statistics); + //SNMP + size = ROUND_UP(size,4); + size += sizeof(t_DsarSnmpDescriptor); + size += sizeof(t_DsarSnmpIpv4AddrTblEntry) * params->maxNumOfSnmpIPV4Entries; + size += sizeof(t_DsarSnmpIpv6AddrTblEntry) * params->maxNumOfSnmpIPV6Entries; + size += sizeof(t_OidsTblEntry) * params->maxNumOfSnmpOidEntries; + size += params->maxNumOfSnmpOidChar; + size += sizeof(t_DsarIcmpV6Statistics); + //filters + size = ROUND_UP(size,4); + size += params->maxNumOfIpProtFiltering; + size = ROUND_UP(size,4); + size += params->maxNumOfUdpPortFiltering * sizeof(t_PortTblEntry); + size = ROUND_UP(size,4); + size += params->maxNumOfTcpPortFiltering * sizeof(t_PortTblEntry); + + // add here for more protocols + + // statistics + size = ROUND_UP(size,4); + size += sizeof(t_ArStatistics); + + ArCommonDescPtr = FM_MURAM_AllocMem(p_FmPort->h_FmMuram, size, 0x10); + + param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); + WRITE_UINT32(*param_page, + (uint32_t)(XX_VirtToPhys(ArCommonDescPtr) - p_FmPort->fmMuramPhysBaseAddr)); + return E_OK; +} + +t_FmPortDsarTablesSizes* FM_PORT_GetDsarTablesMaxSizes(t_Handle h_FmPortRx) +{ + t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx; + return p_FmPort->deepSleepVars.autoResMaxSizes; +} + +struct arOffsets +{ + uint32_t arp; + uint32_t nd; + uint32_t icmpv4; + uint32_t icmpv6; + uint32_t snmp; + uint32_t stats; + uint32_t filtIp; + uint32_t filtUdp; + uint32_t filtTcp; +}; + +static uint32_t AR_ComputeOffsets(struct arOffsets* of, struct t_FmPortDsarParams *params, t_FmPort *p_FmPort) +{ + uint32_t size = sizeof(t_ArCommonDesc); + // ARP + if (params->p_AutoResArpInfo) + { + size = ROUND_UP(size,4); + of->arp = size; + size += sizeof(t_DsarArpDescriptor); + size += sizeof(t_DsarArpBindingEntry) * params->p_AutoResArpInfo->tableSize; + size += sizeof(t_DsarArpStatistics); + } + // ICMPV4 + if (params->p_AutoResEchoIpv4Info) + { + size = ROUND_UP(size,4); + of->icmpv4 = size; + size += sizeof(t_DsarIcmpV4Descriptor); + size += sizeof(t_DsarIcmpV4BindingEntry) * params->p_AutoResEchoIpv4Info->tableSize; + size += sizeof(t_DsarIcmpV4Statistics); + } + // ICMPV6 + if (params->p_AutoResEchoIpv6Info) + { + size = ROUND_UP(size,4); + of->icmpv6 = size; + size += sizeof(t_DsarIcmpV6Descriptor); + size += sizeof(t_DsarIcmpV6BindingEntry) * params->p_AutoResEchoIpv6Info->tableSize; + size += sizeof(t_DsarIcmpV6Statistics); + } + // ND + if (params->p_AutoResNdpInfo) + { + size = ROUND_UP(size,4); + of->nd = size; + size += sizeof(t_DsarNdDescriptor); + size += sizeof(t_DsarIcmpV6BindingEntry) * + (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp); + size += sizeof(t_DsarIcmpV6Statistics); + } + // SNMP + if (params->p_AutoResSnmpInfo) + { + size = ROUND_UP(size,4); + of->snmp = size; + size += sizeof(t_DsarSnmpDescriptor); + size += sizeof(t_DsarSnmpIpv4AddrTblEntry) * params->p_AutoResSnmpInfo->numOfIpv4Addresses; + size += sizeof(t_DsarSnmpIpv6AddrTblEntry) * params->p_AutoResSnmpInfo->numOfIpv6Addresses; + size += sizeof(t_OidsTblEntry) * params->p_AutoResSnmpInfo->oidsTblSize; + size += p_FmPort->deepSleepVars.autoResMaxSizes->maxNumOfSnmpOidChar; + size += sizeof(t_DsarIcmpV6Statistics); + } + //filters + size = ROUND_UP(size,4); + if (params->p_AutoResFilteringInfo) + { + of->filtIp = size; + size += params->p_AutoResFilteringInfo->ipProtTableSize; + size = ROUND_UP(size,4); + of->filtUdp = size; + size += params->p_AutoResFilteringInfo->udpPortsTableSize * sizeof(t_PortTblEntry); + size = ROUND_UP(size,4); + of->filtTcp = size; + size += params->p_AutoResFilteringInfo->tcpPortsTableSize * sizeof(t_PortTblEntry); + } + // add here for more protocols + // statistics + size = ROUND_UP(size,4); + of->stats = size; + size += sizeof(t_ArStatistics); + return size; +} + +uint32_t* ARDesc; +void PrsEnable(t_Handle p_FmPcd); +void PrsDisable(t_Handle p_FmPcd); +int PrsIsEnabled(t_Handle p_FmPcd); + +static t_Error DsarCheckParams(t_FmPortDsarParams *params, t_FmPortDsarTablesSizes *sizes) +{ + bool macInit = FALSE; + uint8_t mac[6]; + int i; + + // check table sizes + if (params->p_AutoResArpInfo && sizes->maxNumOfArpEntries < params->p_AutoResArpInfo->tableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Arp table size exceeds the configured maximum size.")); + if (params->p_AutoResEchoIpv4Info && sizes->maxNumOfEchoIpv4Entries < params->p_AutoResEchoIpv4Info->tableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: EchoIpv4 table size exceeds the configured maximum size.")); + if (params->p_AutoResNdpInfo && sizes->maxNumOfNdpEntries < params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: NDP table size exceeds the configured maximum size.")); + if (params->p_AutoResEchoIpv6Info && sizes->maxNumOfEchoIpv6Entries < params->p_AutoResEchoIpv6Info->tableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: EchoIpv6 table size exceeds the configured maximum size.")); + if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpOidEntries < params->p_AutoResSnmpInfo->oidsTblSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp Oid table size exceeds the configured maximum size.")); + if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpIPV4Entries < params->p_AutoResSnmpInfo->numOfIpv4Addresses) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp ipv4 table size exceeds the configured maximum size.")); + if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpIPV6Entries < params->p_AutoResSnmpInfo->numOfIpv6Addresses) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp ipv6 table size exceeds the configured maximum size.")); + if (params->p_AutoResFilteringInfo) + { + if (sizes->maxNumOfIpProtFiltering < params->p_AutoResFilteringInfo->ipProtTableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: ip filter table size exceeds the configured maximum size.")); + if (sizes->maxNumOfTcpPortFiltering < params->p_AutoResFilteringInfo->udpPortsTableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: udp filter table size exceeds the configured maximum size.")); + if (sizes->maxNumOfUdpPortFiltering < params->p_AutoResFilteringInfo->tcpPortsTableSize) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: tcp filter table size exceeds the configured maximum size.")); + } + // check only 1 MAC address is configured (this is what ucode currently supports) + if (params->p_AutoResArpInfo && params->p_AutoResArpInfo->tableSize) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResArpInfo->p_AutoResTable[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResArpInfo->tableSize; i++) + if (memcmp(mac, params->p_AutoResArpInfo->p_AutoResTable[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + if (params->p_AutoResEchoIpv4Info && params->p_AutoResEchoIpv4Info->tableSize) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResEchoIpv4Info->p_AutoResTable[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResEchoIpv4Info->tableSize; i++) + if (memcmp(mac, params->p_AutoResEchoIpv4Info->p_AutoResTable[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + if (params->p_AutoResEchoIpv6Info && params->p_AutoResEchoIpv6Info->tableSize) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResEchoIpv6Info->p_AutoResTable[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResEchoIpv6Info->tableSize; i++) + if (memcmp(mac, params->p_AutoResEchoIpv6Info->p_AutoResTable[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + if (params->p_AutoResNdpInfo && params->p_AutoResNdpInfo->tableSizeAssigned) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResNdpInfo->p_AutoResTableAssigned[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResNdpInfo->tableSizeAssigned; i++) + if (memcmp(mac, params->p_AutoResNdpInfo->p_AutoResTableAssigned[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + if (params->p_AutoResNdpInfo && params->p_AutoResNdpInfo->tableSizeTmp) + { + i = 0; + if (!macInit) + { + memcpy(mac, params->p_AutoResNdpInfo->p_AutoResTableTmp[0].mac, 6); + i = 1; + macInit = TRUE; + } + for (; i < params->p_AutoResNdpInfo->tableSizeTmp; i++) + if (memcmp(mac, params->p_AutoResNdpInfo->p_AutoResTableTmp[i].mac, 6)) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported.")); + } + return E_OK; +} + +static int GetBERLen(uint8_t* buf) +{ + if (*buf & 0x80) + { + if ((*buf & 0x7F) == 1) + return buf[1]; + else + return *(uint16_t*)&buf[1]; // assuming max len is 2 + } + else + return buf[0]; +} +#define TOTAL_BER_LEN(len) (len < 128) ? len + 2 : len + 3 + +t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) +{ + int i,j; + t_Error err; + uint32_t nia; + t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx; + t_FmPort *p_FmPortTx = (t_FmPort *)params->h_FmPortTx; + t_DsarArpDescriptor *ArpDescriptor; + t_DsarIcmpV4Descriptor* ICMPV4Descriptor; + t_DsarIcmpV6Descriptor* ICMPV6Descriptor; + t_DsarNdDescriptor* NDDescriptor; + uint64_t fmMuramVirtBaseAddr = (uint64_t)XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr); + uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); + t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page))); + struct arOffsets* of; + uint8_t tmp = 0; + t_Handle *h_FmPcd; + + err = DsarCheckParams(params, p_FmPort->deepSleepVars.autoResMaxSizes); + if (err != E_OK) + return err; + + p_FmPort->deepSleepVars.autoResOffsets = XX_Malloc(sizeof(struct arOffsets)); + of = (struct arOffsets *)p_FmPort->deepSleepVars.autoResOffsets; + IOMemSet32(ArCommonDescPtr, 0, AR_ComputeOffsets(of, params, p_FmPort)); + + // common + WRITE_UINT8(ArCommonDescPtr->arTxPort, p_FmPortTx->hardwarePortId); + nia = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); // bmi nia + if ((nia & 0x007C0000) == 0x00440000) // bmi nia is parser + WRITE_UINT32(ArCommonDescPtr->activeHPNIA, GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne)); + else + WRITE_UINT32(ArCommonDescPtr->activeHPNIA, nia); + WRITE_UINT16(ArCommonDescPtr->snmpPort, 161); + + // ARP + if (params->p_AutoResArpInfo) + { + t_DsarArpBindingEntry* arp_bindings; + ArpDescriptor = (t_DsarArpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->arp); + WRITE_UINT32(ArCommonDescPtr->p_ArpDescriptor, PTR_TO_UINT(ArpDescriptor) - fmMuramVirtBaseAddr); + arp_bindings = (t_DsarArpBindingEntry*)(PTR_TO_UINT(ArpDescriptor) + sizeof(t_DsarArpDescriptor)); + WRITE_UINT16(ArpDescriptor->control, 0); + if (params->p_AutoResArpInfo->tableSize) + { + t_FmPortDsarArpEntry* arp_entry = params->p_AutoResArpInfo->p_AutoResTable; + WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&arp_entry[0].mac[0]); + WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&arp_entry[0].mac[2]); + WRITE_UINT16(ArpDescriptor->numOfBindings, params->p_AutoResArpInfo->tableSize); + + for (i = 0; i < params->p_AutoResArpInfo->tableSize; i++) + { + WRITE_UINT32(arp_bindings[i].ipv4Addr, arp_entry[i].ipAddress); + if (arp_entry[i].isVlan) + WRITE_UINT16(arp_bindings[i].vlanId, arp_entry[i].vid & 0xFFF); + } + WRITE_UINT32(ArpDescriptor->p_Bindings, PTR_TO_UINT(arp_bindings) - fmMuramVirtBaseAddr); + } + WRITE_UINT32(ArpDescriptor->p_Statistics, PTR_TO_UINT(arp_bindings) + + sizeof(t_DsarArpBindingEntry) * params->p_AutoResArpInfo->tableSize - fmMuramVirtBaseAddr); + } + + // ICMPV4 + if (params->p_AutoResEchoIpv4Info) + { + t_DsarIcmpV4BindingEntry* icmpv4_bindings; + ICMPV4Descriptor = (t_DsarIcmpV4Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv4); + WRITE_UINT32(ArCommonDescPtr->p_IcmpV4Descriptor, PTR_TO_UINT(ICMPV4Descriptor) - fmMuramVirtBaseAddr); + icmpv4_bindings = (t_DsarIcmpV4BindingEntry*)(PTR_TO_UINT(ICMPV4Descriptor) + sizeof(t_DsarIcmpV4Descriptor)); + WRITE_UINT16(ICMPV4Descriptor->control, 0); + if (params->p_AutoResEchoIpv4Info->tableSize) + { + t_FmPortDsarArpEntry* arp_entry = params->p_AutoResEchoIpv4Info->p_AutoResTable; + WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&arp_entry[0].mac[0]); + WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&arp_entry[0].mac[2]); + WRITE_UINT16(ICMPV4Descriptor->numOfBindings, params->p_AutoResEchoIpv4Info->tableSize); + + for (i = 0; i < params->p_AutoResEchoIpv4Info->tableSize; i++) + { + WRITE_UINT32(icmpv4_bindings[i].ipv4Addr, arp_entry[i].ipAddress); + if (arp_entry[i].isVlan) + WRITE_UINT16(icmpv4_bindings[i].vlanId, arp_entry[i].vid & 0xFFF); + } + WRITE_UINT32(ICMPV4Descriptor->p_Bindings, PTR_TO_UINT(icmpv4_bindings) - fmMuramVirtBaseAddr); + } + WRITE_UINT32(ICMPV4Descriptor->p_Statistics, PTR_TO_UINT(icmpv4_bindings) + + sizeof(t_DsarIcmpV4BindingEntry) * params->p_AutoResEchoIpv4Info->tableSize - fmMuramVirtBaseAddr); + } + + // ICMPV6 + if (params->p_AutoResEchoIpv6Info) + { + t_DsarIcmpV6BindingEntry* icmpv6_bindings; + ICMPV6Descriptor = (t_DsarIcmpV6Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv6); + WRITE_UINT32(ArCommonDescPtr->p_IcmpV6Descriptor, PTR_TO_UINT(ICMPV6Descriptor) - fmMuramVirtBaseAddr); + icmpv6_bindings = (t_DsarIcmpV6BindingEntry*)(PTR_TO_UINT(ICMPV6Descriptor) + sizeof(t_DsarIcmpV6Descriptor)); + WRITE_UINT16(ICMPV6Descriptor->control, 0); + if (params->p_AutoResEchoIpv6Info->tableSize) + { + t_FmPortDsarNdpEntry* ndp_entry = params->p_AutoResEchoIpv6Info->p_AutoResTable; + WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&ndp_entry[0].mac[0]); + WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&ndp_entry[0].mac[2]); + WRITE_UINT16(ICMPV6Descriptor->numOfBindings, params->p_AutoResEchoIpv6Info->tableSize); + + for (i = 0; i < params->p_AutoResEchoIpv6Info->tableSize; i++) + { + for (j = 0; j < 4; j++) + WRITE_UINT32(icmpv6_bindings[i].ipv6Addr[j], ndp_entry[i].ipAddress[j]); + if (ndp_entry[i].isVlan) + WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan + } + WRITE_UINT32(ICMPV6Descriptor->p_Bindings, PTR_TO_UINT(icmpv6_bindings) - fmMuramVirtBaseAddr); + } + WRITE_UINT32(ICMPV6Descriptor->p_Statistics, PTR_TO_UINT(icmpv6_bindings) + + sizeof(t_DsarIcmpV6BindingEntry) * params->p_AutoResEchoIpv6Info->tableSize - fmMuramVirtBaseAddr); + } + + // ND + if (params->p_AutoResNdpInfo) + { + t_DsarIcmpV6BindingEntry* icmpv6_bindings; + NDDescriptor = (t_DsarNdDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->nd); + WRITE_UINT32(ArCommonDescPtr->p_NdDescriptor, PTR_TO_UINT(NDDescriptor) - fmMuramVirtBaseAddr); + icmpv6_bindings = (t_DsarIcmpV6BindingEntry*)(PTR_TO_UINT(NDDescriptor) + sizeof(t_DsarNdDescriptor)); + WRITE_UINT16(NDDescriptor->control, 0); + if (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp) + { + t_FmPortDsarNdpEntry* ndp_entry = params->p_AutoResNdpInfo->p_AutoResTableAssigned; + WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&ndp_entry[0].mac[0]); + WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&ndp_entry[0].mac[2]); + WRITE_UINT16(NDDescriptor->numOfBindings, params->p_AutoResNdpInfo->tableSizeAssigned + + params->p_AutoResNdpInfo->tableSizeTmp); + + for (i = 0; i < params->p_AutoResNdpInfo->tableSizeAssigned; i++) + { + for (j = 0; j < 4; j++) + WRITE_UINT32(icmpv6_bindings[i].ipv6Addr[j], ndp_entry[i].ipAddress[j]); + if (ndp_entry[i].isVlan) + WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan + } + ndp_entry = params->p_AutoResNdpInfo->p_AutoResTableTmp; + for (i = 0; i < params->p_AutoResNdpInfo->tableSizeTmp; i++) + { + for (j = 0; j < 4; j++) + WRITE_UINT32(icmpv6_bindings[i + params->p_AutoResNdpInfo->tableSizeAssigned].ipv6Addr[j], ndp_entry[i].ipAddress[j]); + if (ndp_entry[i].isVlan) + WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i + params->p_AutoResNdpInfo->tableSizeAssigned].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan + } + WRITE_UINT32(NDDescriptor->p_Bindings, PTR_TO_UINT(icmpv6_bindings) - fmMuramVirtBaseAddr); + } + WRITE_UINT32(NDDescriptor->p_Statistics, PTR_TO_UINT(icmpv6_bindings) + sizeof(t_DsarIcmpV6BindingEntry) + * (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp) + - fmMuramVirtBaseAddr); + WRITE_UINT32(NDDescriptor->solicitedAddr, 0xFFFFFFFF); + } + + // SNMP + if (params->p_AutoResSnmpInfo) + { + t_FmPortDsarSnmpInfo *snmpSrc = params->p_AutoResSnmpInfo; + t_DsarSnmpIpv4AddrTblEntry* snmpIpv4Addr; + t_DsarSnmpIpv6AddrTblEntry* snmpIpv6Addr; + t_OidsTblEntry* snmpOid; + uint8_t *charPointer; + int len; + t_DsarSnmpDescriptor* SnmpDescriptor = (t_DsarSnmpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->snmp); + WRITE_UINT32(ArCommonDescPtr->p_SnmpDescriptor, PTR_TO_UINT(SnmpDescriptor) - fmMuramVirtBaseAddr); + WRITE_UINT16(SnmpDescriptor->control, snmpSrc->control); + WRITE_UINT16(SnmpDescriptor->maxSnmpMsgLength, snmpSrc->maxSnmpMsgLength); + snmpIpv4Addr = (t_DsarSnmpIpv4AddrTblEntry*)(PTR_TO_UINT(SnmpDescriptor) + sizeof(t_DsarSnmpDescriptor)); + if (snmpSrc->numOfIpv4Addresses) + { + t_FmPortDsarSnmpIpv4AddrTblEntry* snmpIpv4AddrSrc = snmpSrc->p_Ipv4AddrTbl; + WRITE_UINT16(SnmpDescriptor->numOfIpv4Addresses, snmpSrc->numOfIpv4Addresses); + for (i = 0; i < snmpSrc->numOfIpv4Addresses; i++) + { + WRITE_UINT32(snmpIpv4Addr[i].ipv4Addr, snmpIpv4AddrSrc[i].ipv4Addr); + if (snmpIpv4AddrSrc[i].isVlan) + WRITE_UINT16(snmpIpv4Addr[i].vlanId, snmpIpv4AddrSrc[i].vid & 0xFFF); + } + WRITE_UINT32(SnmpDescriptor->p_Ipv4AddrTbl, PTR_TO_UINT(snmpIpv4Addr) - fmMuramVirtBaseAddr); + } + snmpIpv6Addr = (t_DsarSnmpIpv6AddrTblEntry*)(PTR_TO_UINT(snmpIpv4Addr) + + sizeof(t_DsarSnmpIpv4AddrTblEntry) * snmpSrc->numOfIpv4Addresses); + if (snmpSrc->numOfIpv6Addresses) + { + t_FmPortDsarSnmpIpv6AddrTblEntry* snmpIpv6AddrSrc = snmpSrc->p_Ipv6AddrTbl; + WRITE_UINT16(SnmpDescriptor->numOfIpv6Addresses, snmpSrc->numOfIpv6Addresses); + for (i = 0; i < snmpSrc->numOfIpv6Addresses; i++) + { + for (j = 0; j < 4; j++) + WRITE_UINT32(snmpIpv6Addr[i].ipv6Addr[j], snmpIpv6AddrSrc[i].ipv6Addr[j]); + if (snmpIpv6AddrSrc[i].isVlan) + WRITE_UINT16(snmpIpv6Addr[i].vlanId, snmpIpv6AddrSrc[i].vid & 0xFFF); + } + WRITE_UINT32(SnmpDescriptor->p_Ipv6AddrTbl, PTR_TO_UINT(snmpIpv6Addr) - fmMuramVirtBaseAddr); + } + snmpOid = (t_OidsTblEntry*)(PTR_TO_UINT(snmpIpv6Addr) + + sizeof(t_DsarSnmpIpv6AddrTblEntry) * snmpSrc->numOfIpv6Addresses); + charPointer = (uint8_t*)(PTR_TO_UINT(snmpOid) + + sizeof(t_OidsTblEntry) * snmpSrc->oidsTblSize); + len = TOTAL_BER_LEN(GetBERLen(&snmpSrc->p_RdOnlyCommunityStr[1])); + Mem2IOCpy32(charPointer, snmpSrc->p_RdOnlyCommunityStr, len); + WRITE_UINT32(SnmpDescriptor->p_RdOnlyCommunityStr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + charPointer += len; + len = TOTAL_BER_LEN(GetBERLen(&snmpSrc->p_RdWrCommunityStr[1])); + Mem2IOCpy32(charPointer, snmpSrc->p_RdWrCommunityStr, len); + WRITE_UINT32(SnmpDescriptor->p_RdWrCommunityStr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + charPointer += len; + WRITE_UINT32(SnmpDescriptor->oidsTblSize, snmpSrc->oidsTblSize); + WRITE_UINT32(SnmpDescriptor->p_OidsTbl, PTR_TO_UINT(snmpOid) - fmMuramVirtBaseAddr); + for (i = 0; i < snmpSrc->oidsTblSize; i++) + { + WRITE_UINT16(snmpOid->oidSize, snmpSrc->p_OidsTbl[i].oidSize); + WRITE_UINT16(snmpOid->resSize, snmpSrc->p_OidsTbl[i].resSize); + Mem2IOCpy32(charPointer, snmpSrc->p_OidsTbl[i].p_Oid, snmpSrc->p_OidsTbl[i].oidSize); + WRITE_UINT32(snmpOid->p_Oid, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + charPointer += snmpSrc->p_OidsTbl[i].oidSize; + if (snmpSrc->p_OidsTbl[i].resSize <= 4) + WRITE_UINT32(snmpOid->resValOrPtr, snmpSrc->p_OidsTbl[i].resValOrPtr); + else + { + Mem2IOCpy32(charPointer, UINT_TO_PTR(snmpSrc->p_OidsTbl[i].resValOrPtr), snmpSrc->p_OidsTbl[i].resSize); + WRITE_UINT32(snmpOid->resValOrPtr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + charPointer += snmpSrc->p_OidsTbl[i].resSize; + } + snmpOid++; + } + charPointer = UINT_TO_PTR(ROUND_UP(PTR_TO_UINT(charPointer),4)); + WRITE_UINT32(SnmpDescriptor->p_Statistics, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); + } + + // filtering + if (params->p_AutoResFilteringInfo) + { + if (params->p_AutoResFilteringInfo->ipProtDropOnHit) + tmp |= IP_PROT_TBL_PASS_MASK; + if (params->p_AutoResFilteringInfo->udpPortDropOnHit) + tmp |= UDP_PORT_TBL_PASS_MASK; + if (params->p_AutoResFilteringInfo->tcpPortDropOnHit) + tmp |= TCP_PORT_TBL_PASS_MASK; + WRITE_UINT8(ArCommonDescPtr->filterControl, tmp); + + // ip filtering + if (params->p_AutoResFilteringInfo->ipProtTableSize) + { + uint8_t* ip_tbl = (uint8_t*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtIp); + WRITE_UINT8(ArCommonDescPtr->ipProtocolTblSize, params->p_AutoResFilteringInfo->ipProtTableSize); + for (i = 0; i < params->p_AutoResFilteringInfo->ipProtTableSize; i++) + WRITE_UINT8(ip_tbl[i], params->p_AutoResFilteringInfo->p_IpProtTablePtr[i]); + WRITE_UINT32(ArCommonDescPtr->p_IpProtocolFiltTbl, PTR_TO_UINT(ip_tbl) - fmMuramVirtBaseAddr); + } + + // udp filtering + if (params->p_AutoResFilteringInfo->udpPortsTableSize) + { + t_PortTblEntry* udp_tbl = (t_PortTblEntry*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtUdp); + WRITE_UINT8(ArCommonDescPtr->udpPortTblSize, params->p_AutoResFilteringInfo->udpPortsTableSize); + for (i = 0; i < params->p_AutoResFilteringInfo->udpPortsTableSize; i++) + { + WRITE_UINT32(udp_tbl[i].Ports, + (params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].srcPort << 16) + + params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].dstPort); + WRITE_UINT32(udp_tbl[i].PortsMask, + (params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].srcPortMask << 16) + + params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].dstPortMask); + } + WRITE_UINT32(ArCommonDescPtr->p_UdpPortFiltTbl, PTR_TO_UINT(udp_tbl) - fmMuramVirtBaseAddr); + } + + // tcp filtering + if (params->p_AutoResFilteringInfo->tcpPortsTableSize) + { + t_PortTblEntry* tcp_tbl = (t_PortTblEntry*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtTcp); + WRITE_UINT8(ArCommonDescPtr->tcpPortTblSize, params->p_AutoResFilteringInfo->tcpPortsTableSize); + for (i = 0; i < params->p_AutoResFilteringInfo->tcpPortsTableSize; i++) + { + WRITE_UINT32(tcp_tbl[i].Ports, + (params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].srcPort << 16) + + params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].dstPort); + WRITE_UINT32(tcp_tbl[i].PortsMask, + (params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].srcPortMask << 16) + + params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].dstPortMask); + } + WRITE_UINT32(ArCommonDescPtr->p_TcpPortFiltTbl, PTR_TO_UINT(tcp_tbl) - fmMuramVirtBaseAddr); + } + } + // common stats + WRITE_UINT32(ArCommonDescPtr->p_ArStats, PTR_TO_UINT(ArCommonDescPtr) + of->stats - fmMuramVirtBaseAddr); + + // get into Deep Sleep sequence: + // Stage 6: configure tx port to im + p_FmPort->deepSleepVars.fmbm_tcfg = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg); + WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg) | BMI_PORT_CFG_IM); + // ???? + p_FmPort->deepSleepVars.fmbm_tcmne = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne); + WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, 0xE); + // Stage 7:echo + p_FmPort->deepSleepVars.fmbm_rfne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, 0x440000); + p_FmPort->deepSleepVars.fmbm_rfpne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne); + h_FmPcd = FmGetPcd(p_FmPort->h_Fm); + if (!PrsIsEnabled(h_FmPcd)) + { + p_FmPort->deepSleepVars.dsarEnabledParser = TRUE; + PrsEnable(h_FmPcd); + } + else + p_FmPort->deepSleepVars.dsarEnabledParser = FALSE; + + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, 0x2E); + // Stage 8: We don't support magic packet for now. + // Stage 9: Accumulate mode +// WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg, GET_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg) | BMI_PORT_CFG_AM); + ARDesc = UINT_TO_PTR(XX_VirtToPhys(ArCommonDescPtr)); + return E_OK; +} + +void FM_PORT_Dsar_DumpRegs() +{ + uint32_t* hh = XX_PhysToVirt(PTR_TO_UINT(ARDesc)); + DUMP_MEMORY(hh, 0x180); +} + +void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx) +{ + t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; + t_FmPort *p_FmPortTx = (t_FmPort *)h_FmPortTx; + if (p_FmPort->deepSleepVars.autoResOffsets) + { + XX_Free(p_FmPort->deepSleepVars.autoResOffsets); + p_FmPort->deepSleepVars.autoResOffsets = 0; + } + if (p_FmPort->deepSleepVars.autoResMaxSizes) + { + XX_Free(p_FmPort->deepSleepVars.autoResMaxSizes); + p_FmPort->deepSleepVars.autoResMaxSizes = 0; + } + + if (p_FmPort->deepSleepVars.dsarEnabledParser) + PrsDisable(FmGetPcd(p_FmPort->h_Fm)); + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, p_FmPort->deepSleepVars.fmbm_rfpne); + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, p_FmPort->deepSleepVars.fmbm_rfne); + WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, p_FmPort->deepSleepVars.fmbm_tcmne); + WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, p_FmPort->deepSleepVars.fmbm_tcfg); +} + +bool FM_PORT_IsInDsar(t_Handle h_FmPort) +{ + t_FmPort *p_FmPort = (t_FmPort *)h_FmPort; + return PTR_TO_UINT(p_FmPort->deepSleepVars.autoResOffsets); +} + +t_Error FM_PORT_GetDsarStats(t_Handle h_FmPortRx, t_FmPortDsarStats *stats) +{ + t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; + struct arOffsets *of = (struct arOffsets*)p_FmPort->deepSleepVars.autoResOffsets; + uint8_t* fmMuramVirtBaseAddr = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr); + uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); + t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page))); + t_DsarArpDescriptor *ArpDescriptor = (t_DsarArpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->arp); + t_DsarArpStatistics* arp_stats = (t_DsarArpStatistics*)(PTR_TO_UINT(ArpDescriptor->p_Statistics) + fmMuramVirtBaseAddr); + t_DsarIcmpV4Descriptor* ICMPV4Descriptor = (t_DsarIcmpV4Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv4); + t_DsarIcmpV4Statistics* icmpv4_stats = (t_DsarIcmpV4Statistics*)(PTR_TO_UINT(ICMPV4Descriptor->p_Statistics) + fmMuramVirtBaseAddr); + t_DsarNdDescriptor* NDDescriptor = (t_DsarNdDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->nd); + t_NdStatistics* nd_stats = (t_NdStatistics*)(PTR_TO_UINT(NDDescriptor->p_Statistics) + fmMuramVirtBaseAddr); + t_DsarIcmpV6Descriptor* ICMPV6Descriptor = (t_DsarIcmpV6Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv6); + t_DsarIcmpV6Statistics* icmpv6_stats = (t_DsarIcmpV6Statistics*)(PTR_TO_UINT(ICMPV6Descriptor->p_Statistics) + fmMuramVirtBaseAddr); + t_DsarSnmpDescriptor* SnmpDescriptor = (t_DsarSnmpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->snmp); + t_DsarSnmpStatistics* snmp_stats = (t_DsarSnmpStatistics*)(PTR_TO_UINT(SnmpDescriptor->p_Statistics) + fmMuramVirtBaseAddr); + stats->arpArCnt = arp_stats->arCnt; + stats->echoIcmpv4ArCnt = icmpv4_stats->arCnt; + stats->ndpArCnt = nd_stats->arCnt; + stats->echoIcmpv6ArCnt = icmpv6_stats->arCnt; + stats->snmpGetCnt = snmp_stats->snmpGetReqCnt; + stats->snmpGetNextCnt = snmp_stats->snmpGetNextReqCnt; + return E_OK; +} |