1/*******************************************************************************
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright 2014 QLogic Corporation
22 * The contents of this file are subject to the terms of the
23 * QLogic End User License (the "License").
24 * You may not use this file except in compliance with the License.
25 *
26 * You can obtain a copy of the License at
27 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
28 * QLogic_End_User_Software_License.txt
29 * See the License for the specific language governing permissions
30 * and limitations under the License.
31 *
32 *
33 * Module Description:
34 *      This file contains functions having to do with Device info, licensing
35 *      and Bandwidth Allocation
36 *
37 ******************************************************************************/
38
39#include "lm5710.h"
40
41unsigned long log2_align(unsigned long n);
42
43u64_t lm_get_timestamp_of_recent_cid_recycling(struct _lm_device_t *pdev)
44{
45    return pdev->vars.last_recycling_timestamp;
46}
47
48u32_t lm_get_max_supported_toe_cons(struct _lm_device_t *pdev)
49{
50    if ( CHK_NULL(pdev) )
51    {
52        return 0;
53    }
54    return pdev->params.max_supported_toe_cons;
55}
56
57u8_t lm_get_toe_rss_possibility(struct _lm_device_t *pdev)
58{
59    if ( CHK_NULL(pdev) )
60    {
61        return 0;
62    }
63    return (pdev->params.l4_rss_is_possible != L4_RSS_DISABLED);
64}
65
66/*******************************************************************************
67 * Description:
68 *     reads iscsi_boot info block from shmem
69 * Return:
70 *     lm_status
71 ******************************************************************************/
72lm_status_t lm_get_iscsi_boot_info_block( struct _lm_device_t *pdev, struct _iscsi_info_block_hdr_t* iscsi_info_block_hdr_ptr )
73{
74    u32_t           val                = 0;
75    u32_t           offset             = 0;
76    const u8_t      func_mb_id         = FUNC_MAILBOX_ID(pdev);
77
78    // dummy variables so we have convenience way to know the shmem offsets
79                                               // This is a pointer so it doesn't load the stack.
80    // If we delete these lines we won't have shmem_region_t symbols
81    shmem_region_t*    shmem_region_dummy    = NULL;
82    shmem2_region_t*   shmem2_region_dummy   = NULL;
83    shared_hw_cfg_t*   shared_hw_cfg_dummy   = NULL;
84    port_hw_cfg_t*     port_hw_cfg_dummy     = NULL;
85    shared_feat_cfg_t* shared_feat_cfg_dummy = NULL;
86    port_feat_cfg_t*   port_feat_cfg_dummy   = NULL;
87    mf_cfg_t*          mf_cfg_dummy          = NULL;
88
89    UNREFERENCED_PARAMETER_(shmem_region_dummy);
90    UNREFERENCED_PARAMETER_(shmem2_region_dummy);
91    UNREFERENCED_PARAMETER_(shared_hw_cfg_dummy);
92    UNREFERENCED_PARAMETER_(port_hw_cfg_dummy);
93    UNREFERENCED_PARAMETER_(shared_feat_cfg_dummy);
94    UNREFERENCED_PARAMETER_(port_feat_cfg_dummy);
95    UNREFERENCED_PARAMETER_(mf_cfg_dummy);
96
97    if ( CHK_NULL( iscsi_info_block_hdr_ptr ) )
98    {
99        return LM_STATUS_INVALID_PARAMETER ;
100    }
101
102    if (pdev->hw_info.mcp_detected == 1)
103    {
104        offset = OFFSETOF(shmem_region_t,func_mb[func_mb_id].iscsi_boot_signature);
105        LM_SHMEM_READ(pdev, offset, &val );
106        iscsi_info_block_hdr_ptr->signature = val ;
107        // only for debugging
108        offset = OFFSETOF(shmem_region_t,func_mb[func_mb_id].iscsi_boot_block_offset);
109        LM_SHMEM_READ(pdev, offset, &val );
110        if (val == UEFI_BOOT_SIGNATURE)
111        {
112            SET_FLAGS(iscsi_info_block_hdr_ptr->boot_flags, BOOT_INFO_FLAGS_UEFI_BOOT );
113        }
114        else
115        {
116            RESET_FLAGS(iscsi_info_block_hdr_ptr->boot_flags, BOOT_INFO_FLAGS_UEFI_BOOT );
117        }
118    }
119    else
120    {
121        // If mcp is detected the shmenm is not initialized and
122        iscsi_info_block_hdr_ptr->signature = 0;
123    }
124    return LM_STATUS_SUCCESS ;
125}
126
127lm_status_t
128lm_get_ibft_physical_addr_for_efi(
129    struct _lm_device_t *pdev, u32_t *phy_hi, u32_t *phy_lo
130    )
131{
132    u32_t           offset             = 0;
133    u32_t           val                = 0;
134    const u8_t      func_mb_id         = FUNC_MAILBOX_ID(pdev);
135
136    if (pdev->hw_info.mcp_detected == 1)
137    {
138        offset = OFFSETOF(shmem_region_t,func_mb[func_mb_id].iscsi_boot_signature);
139        LM_SHMEM_READ(pdev, offset, &val );
140        //iscsi_info_block_hdr_ptr->signature = val ;
141        // only for debugging
142        offset = OFFSETOF(shmem_region_t,func_mb[func_mb_id].iscsi_boot_block_offset);
143        LM_SHMEM_READ(pdev, offset, &val );
144        if (val == UEFI_BOOT_SIGNATURE)
145        {
146            offset = OFFSETOF(shmem2_region_t,ibft_host_addr);
147            LM_SHMEM2_READ(pdev, offset , &val);
148            *phy_lo = val;
149            *phy_hi = 0;
150
151            return LM_STATUS_SUCCESS;
152        }
153    }
154    return LM_STATUS_FAILURE;
155}
156lm_status_t
157lm_get_sriov_info(lm_device_t *pdev)
158{
159    lm_status_t rc = LM_STATUS_SUCCESS;
160    u32_t val;
161    if (!CHIP_IS_E1x(pdev)) {
162        /* get bars... */
163#ifdef VF_INVOLVED
164        rc = mm_get_sriov_info(pdev, &pdev->hw_info.sriov_info);
165        if (rc != LM_STATUS_SUCCESS) {
166            return rc;
167        }
168#endif
169
170#ifdef __LINUX
171        lm_set_virt_mode(pdev, DEVICE_TYPE_PF, (pdev->hw_info.sriov_info.total_vfs? VT_BASIC_VF : VT_NONE));
172#elif defined(_VBD_CMD_)
173        lm_set_virt_mode(pdev, DEVICE_TYPE_PF, (pdev->hw_info.sriov_info.total_vfs? VT_CHANNEL_VF : VT_NONE));
174#endif
175        /* Since registers from 0x000-0x7ff are spilt across functions, each PF will have  the same location for the same 4 bits*/
176        val = REG_RD(pdev, PCICFG_OFFSET + GRC_CONFIG_REG_PF_INIT_VF);
177        pdev->hw_info.sriov_info.first_vf_in_pf = ((val & GRC_CR_PF_INIT_VF_PF_FIRST_VF_NUM_MASK) * 8) - E2_MAX_NUM_OF_VFS*PATH_ID(pdev);
178        DbgMessage(pdev, WARN, "First VF in PF = %d\n", pdev->hw_info.sriov_info.first_vf_in_pf);
179    }
180    return rc;
181}
182
183
184static void lm_print_func_info(lm_device_t *pdev)
185{
186    DbgMessage(pdev, WARN, "lm_get_shmem_info: FUNC_ID: %d\n", FUNC_ID(pdev));
187    DbgMessage(pdev, WARN, "lm_get_shmem_info: PCI_FUNC_ID: %d\n", ABS_FUNC_ID(pdev));
188    DbgMessage(pdev, WARN, "lm_get_shmem_info: PORT_ID: %d\n", PORT_ID(pdev));
189
190    if (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_4)
191    {
192        DbgMessage(pdev, WARN, "lm_get_shmem_info: ETH_PORT_ID: %d\n", PATH_ID(pdev) + 2*PORT_ID(pdev));
193    }
194    else
195    {
196        DbgMessage(pdev, WARN, "lm_get_shmem_info: ETH_PORT_ID: %d\n", PATH_ID(pdev) + PORT_ID(pdev));
197    }
198
199    DbgMessage(pdev, WARN, "lm_get_shmem_info: PATH_ID: %d\n", PATH_ID(pdev));
200    DbgMessage(pdev, WARN, "lm_get_shmem_info: VNIC_ID: %d\n", VNIC_ID(pdev));
201    DbgMessage(pdev, WARN, "lm_get_shmem_info: FUNC_MAILBOX_ID: %d\n", FUNC_MAILBOX_ID(pdev));
202
203}
204
205
206/*******************************************************************************
207 * Description:
208 *
209 * Return:
210 ******************************************************************************/
211lm_status_t
212lm_get_function_num(lm_device_t *pdev)
213{
214    u32_t val = 0;
215    /* read the me register to get function number. */
216    /* Me register: holds the relative-function num + absolute-function num,
217     * absolute-function-num appears only from E2 and above. Before that these bits
218     * always contained zero, therefore we can't take as is. */
219    val = REG_RD(pdev, BAR_ME_REGISTER);
220    pdev->params.pfunc_rel = (u8_t)((val & ME_REG_PF_NUM) >> ME_REG_PF_NUM_SHIFT);
221    pdev->params.path_id = (u8_t)((val & ME_REG_ABS_PF_NUM) >> ME_REG_ABS_PF_NUM_SHIFT) & 1;
222
223    if (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_4)
224    {
225        pdev->params.pfunc_abs = (pdev->params.pfunc_rel << 1) | pdev->params.path_id;
226    }
227    else
228    {
229        pdev->params.pfunc_abs = pdev->params.pfunc_rel | pdev->params.path_id;
230    }
231    pdev->params.pfunc_mb_id = FUNC_MAILBOX_ID(pdev);
232
233    DbgMessage(pdev, INFORM , "relative function %d absolute function %d\n", pdev->params.pfunc_rel, pdev->params.pfunc_abs);
234
235    lm_print_func_info(pdev);
236    return LM_STATUS_SUCCESS;
237}
238
239
240// reads max_payload_size & max_read_req_size from pci config space
241lm_status_t lm_get_pcicfg_mps_mrrs(lm_device_t * pdev)
242{
243    lm_status_t lm_status = LM_STATUS_SUCCESS;
244    u32_t       val       = 0;
245
246    /* get max payload size and max read size we need it for pxp configuration
247    in the real chip it should be done by the MCP.*/
248    lm_status = mm_read_pci(pdev, PCICFG_DEVICE_CONTROL, &val);
249    if (lm_status != LM_STATUS_SUCCESS)
250    {
251        return lm_status;
252    }
253    // bit 5-7
254    pdev->hw_info.max_payload_size = (val & 0xe0)>>5;
255    // bit 12-14
256    pdev->hw_info.max_read_req_size = (val & 0x7000)>>12;
257    DbgMessage(pdev, INFORMi, "reg 0xd8 0x%x \n max_payload %d max_read_req %d \n",
258                val,pdev->hw_info.max_payload_size,pdev->hw_info.max_read_req_size);
259
260    return lm_status ;
261}
262
263lm_status_t lm_get_pcicfg_info(lm_device_t *pdev)
264{
265    lm_status_t lm_status;
266    u32_t val;
267    /* Get PCI device and vendor id. (need to be read from parent */
268    if (IS_PFDEV(pdev) || IS_CHANNEL_VFDEV(pdev))
269    {
270        lm_status = mm_read_pci(pdev, PCICFG_VENDOR_ID_OFFSET, &val);
271        if (lm_status != LM_STATUS_SUCCESS)
272        {
273            return lm_status;
274        }
275        if (val != 0xFFFFFFFF)
276        {
277            pdev->hw_info.vid = (u16_t) val;
278            pdev->hw_info.did = (u16_t) (val >> 16);
279        }
280        else if (IS_SW_CHANNEL_VIRT_MODE(pdev))
281        {
282            pdev->hw_info.vid = 0x14E4;
283            pdev->hw_info.did = 0x166F;
284        }
285        DbgMessage(pdev, INFORMi, "vid 0x%x\n", pdev->hw_info.vid);
286        DbgMessage(pdev, INFORMi, "did 0x%x\n", pdev->hw_info.did);
287    }
288    else
289    {
290        DbgMessage(pdev, WARN, "vid&did for VBD VF will be known later\n"); /*Must be known earlier*/
291    }
292    /* Get subsystem and subvendor id. */
293    lm_status = mm_read_pci(pdev, PCICFG_SUBSYSTEM_VENDOR_ID_OFFSET, &val);
294    if (lm_status != LM_STATUS_SUCCESS)
295    {
296        return lm_status;
297    }
298
299    pdev->hw_info.svid = (u16_t) val;
300    DbgMessage(pdev, INFORMi, "svid 0x%x\n", pdev->hw_info.svid);
301    pdev->hw_info.ssid = (u16_t) (val >> 16);
302    DbgMessage(pdev, INFORMi, "ssid 0x%x\n", pdev->hw_info.ssid);
303
304    /* Get IRQ, and interrupt pin. */
305    lm_status = mm_read_pci(pdev, PCICFG_INT_LINE, &val);
306    if (lm_status != LM_STATUS_SUCCESS)
307    {
308        return lm_status;
309    }
310    pdev->hw_info.irq = (u8_t) val;
311    DbgMessage(pdev, INFORMi, "IRQ 0x%x\n", pdev->hw_info.irq);
312    pdev->hw_info.int_pin = (u8_t) (val >> 8);
313    DbgMessage(pdev, INFORMi, "Int pin 0x%x\n", pdev->hw_info.int_pin);
314
315    /* Get cache line size. */
316    lm_status = mm_read_pci(pdev, PCICFG_CACHE_LINE_SIZE, &val);
317    if (lm_status != LM_STATUS_SUCCESS)
318    {
319        return lm_status;
320    }
321
322    pdev->hw_info.cache_line_size = (u8_t) val;
323    DbgMessage(pdev, INFORMi, "Cache line size 0x%x\n", (u8_t) val);
324    pdev->hw_info.latency_timer = (u8_t) (val >> 8);
325    DbgMessage(pdev, INFORMi, "Latency timer 0x%x\n", (u8_t) (val >> 8));
326
327    /* Get PCI revision id. */
328    lm_status = mm_read_pci(pdev, PCICFG_REVISION_ID_OFFSET, &val);
329    if (lm_status != LM_STATUS_SUCCESS)
330    {
331        return lm_status;
332    }
333    pdev->hw_info.rev_id = (u8_t) val;
334    DbgMessage(pdev, INFORMi, "Revision id 0x%x\n", pdev->hw_info.rev_id);
335
336    /* Get PCI-E speed*/
337    /* only for PF */
338    if (IS_PFDEV(pdev))
339    {
340        lm_status = mm_read_pci(pdev, PCICFG_LINK_CONTROL, &val);
341        if (lm_status != LM_STATUS_SUCCESS)
342        {
343            return lm_status;
344        }
345
346        /* bit 20-25 */
347        pdev->hw_info.pcie_lane_width = (val & 0x3f00000) >> 20;
348        DbgMessage(pdev, INFORMi, "pcie_lane_width 0x%x\n", pdev->hw_info.pcie_lane_width);
349        /* bit 16 - 19 */
350        pdev->hw_info.pcie_lane_speed = (val & 0xf0000) >> 16;
351        DbgMessage(pdev, INFORMi, "pcie_lane_speed 0x%x\n", pdev->hw_info.pcie_lane_speed);
352
353        lm_status = lm_get_pcicfg_mps_mrrs(pdev);
354    }
355
356    // CQ61532 - Fan Failure test fails when stop the fan for more than 10 seconds and reboot.
357    // Actually most chances we won't get until here if the value is error = we might read other registers before that will hang the machine in Windows
358    // Hopefully this read will help with other LM drivers
359    // anyway, we'll fail the bind for that...
360    if (GET_FLAGS(pdev->hw_info.rev_id,PCICFG_REVESION_ID_MASK) == PCICFG_REVESION_ID_ERROR_VAL)
361    {
362        return LM_STATUS_FAILURE;
363    }
364
365    return lm_status;
366}
367/**
368 * This function reads bar offset from PCI configuration
369 * header.
370 *
371 * @param _pdev
372 * @param bar_num Bar index: BAR_0 or BAR_1 or BAR_2
373 * @param bar_addr Output value (bar offset).
374 *
375 * @return LM_STATUS_SUCCESS if bar offset has been read
376 *         successfully.
377 */
378static __inline lm_status_t lm_get_bar_offset_direct(
379    IN   struct _lm_device_t * pdev,
380    IN   u8_t                  bar_num,   /* Bar index: BAR_0 or BAR_1 or BAR_2 */
381    OUT lm_address_t         * bar_addr )
382{
383    u32_t pci_reg, val;
384    lm_status_t lm_status;
385    /* Get BARs addresses. */
386    switch (bar_num) {
387    case BAR_0:
388        pci_reg = PCICFG_BAR_1_LOW;
389        break;
390    case BAR_1:
391        pci_reg = PCICFG_BAR_1_LOW + 8;
392        break;
393    case BAR_2:
394        pci_reg = PCICFG_BAR_1_LOW + 16;
395        break;
396    default:
397        DbgMessage(pdev, FATAL, "Unsupported bar index: %d\n", bar_num);
398        DbgBreakIfAll(1);
399        return LM_STATUS_INVALID_PARAMETER;
400    }
401    lm_status = mm_read_pci(pdev, pci_reg, &val);
402    if(lm_status != LM_STATUS_SUCCESS) {
403        return lm_status;
404    }
405    bar_addr->as_u32.low = val & 0xfffffff0;;
406    DbgMessage(pdev, INFORMi, "BAR %d low 0x%x\n", bar_num,
407                bar_addr->as_u32.low);
408    pci_reg += 4; /* sizeof configuration space bar address register */
409    lm_status = mm_read_pci(pdev, pci_reg, &val);
410    if(lm_status != LM_STATUS_SUCCESS) {
411        return lm_status;
412    }
413    bar_addr->as_u32.high = val;
414    DbgMessage(pdev, INFORMi, "BAR %d high 0x%x\n", bar_num,
415                bar_addr->as_u32.high);
416    return LM_STATUS_SUCCESS;
417}
418
419static __inline lm_status_t lm_get_bar_size_direct (
420    IN  lm_device_t *pdev,
421    IN  u8_t bar_num,
422    OUT  u32_t * val_p)
423{
424    u32_t bar_address = 0;
425    u32_t bar_size;
426    switch (bar_num) {
427    case BAR_0:
428        bar_address = GRC_CONFIG_2_SIZE_REG;
429        break;
430    case BAR_1:
431        bar_address = GRC_BAR2_CONFIG;
432        break;
433    case BAR_2:
434        bar_address = GRC_BAR3_CONFIG;
435        break;
436    default:
437        DbgMessage(pdev, FATAL, "Invalid Bar Num\n");
438        return LM_STATUS_INVALID_PARAMETER;
439    }
440    lm_reg_rd_ind(pdev,PCICFG_OFFSET + bar_address,&bar_size);
441    /*extract only bar size*/
442    ASSERT_STATIC(PCI_CONFIG_2_BAR1_SIZE == PCI_CONFIG_2_BAR2_SIZE);
443    ASSERT_STATIC(PCI_CONFIG_2_BAR2_SIZE == PCI_CONFIG_2_BAR3_SIZE);
444
445    bar_size = (bar_size & PCI_CONFIG_2_BAR1_SIZE);
446    if (bar_size == 0)
447    {
448        /*bar size disabled*/
449        return LM_STATUS_FAILURE;
450    }
451    else
452    {
453        /*bit 1 stand for 64K each bit multiply it by two */
454        *val_p = (0x40 << ((bar_size - 1)))*0x400;
455    }
456
457    return LM_STATUS_SUCCESS;
458}
459/* init pdev->hw_info with data from pcicfg */
460lm_status_t lm_get_bars_info(lm_device_t *pdev)
461{
462    lm_status_t lm_status;
463    u32_t bar_map_size = 0;
464    u8_t i;
465
466    /* Get BARs addresses. */
467    for (i = 0; i < ARRSIZE(pdev->hw_info.mem_base); i++)
468    {
469        lm_status = mm_get_bar_offset(pdev, i, &pdev->hw_info.mem_base[i]);
470        DbgMessage(pdev, INFORMi, "Bar_Offset=0x%x\n", pdev->hw_info.mem_base[i]);
471
472        if(lm_status != LM_STATUS_SUCCESS)
473        {
474            return lm_status;
475        }
476        if(pdev->hw_info.mem_base[i].as_u64 == 0)
477        {
478            DbgMessage(pdev, WARNi, "BAR %d IS NOT PRESENT\n", i);
479            if(i==0)
480            {
481                DbgBreakMsg("BAR 0 must be present\n");
482            }
483        }
484    }
485    /* TBA: review two intializations done in Teton here (are they needed? are they part of "get_bars_info"):
486    - Enable PCI bus master....
487    - Configure byte swap and enable write to the reg_window registers
488    */
489    for (i = 0; i < MAX_NUM_BAR; i++)
490    {
491        if(pdev->hw_info.mem_base[i].as_u64 == 0)
492        {
493            continue;
494        }
495
496        /* get bar i size*/
497        lm_status = mm_get_bar_size(pdev, i, &(pdev->hw_info.bar_size[i]));
498
499        if ( lm_status != LM_STATUS_SUCCESS )
500        {
501            return lm_status;
502        }
503        DbgMessage(pdev, INFORMi, "bar %d size 0x%x\n", i, pdev->hw_info.bar_size[i]);
504        /* Change in BAR1
505         * The function will map in case of BAR1 only the ETH cid doorbell space to a virtual address.
506         * (Map from BAR1 base address, to BAR1 base address plus MAX_ETH_CONS* LM_PAGE_SIZE).
507        */
508        if (BAR_1 == i )
509        {
510            if (IS_PFDEV(pdev))
511            { //TODO Revise it
512#ifdef VF_INVOLVED
513                bar_map_size = pdev->hw_info.bar_size[i];
514#else
515                bar_map_size = LM_DQ_CID_SIZE * MAX_ETH_CONS;
516#endif
517            }
518            else
519            {
520                bar_map_size = LM_DQ_CID_SIZE;
521            }
522#ifndef VF_INVOLVED
523            DbgBreakIf(bar_map_size >= pdev->hw_info.bar_size[i]);
524#endif
525        }
526        else
527        {
528            bar_map_size = pdev->hw_info.bar_size[i];
529        }
530        /* Map bar i to system address space. If not mapped already. */
531        if(lm_is_function_after_flr(pdev) ||
532#ifdef VF_INVOLVED
533           lm_is_function_after_flr(PFDEV(pdev)) ||
534#endif
535           (pdev->vars.mapped_bar_addr[i] == NULL))
536        {
537                pdev->vars.mapped_bar_addr[i] = NULL;
538                pdev->vars.mapped_bar_addr[i] = mm_map_io_base(
539                        pdev,
540                        pdev->hw_info.mem_base[i],
541                        bar_map_size,
542                        i);
543                if(pdev->vars.mapped_bar_addr[i] == NULL)
544                {
545                    DbgMessage(pdev, FATAL, "bar %d map io failed\n", i);
546                    return LM_STATUS_FAILURE;
547                }
548                else
549                {
550                    DbgMessage(pdev, INFORMi, "mem_base[%d]=%p size=0x%x\n", i, pdev->vars.mapped_bar_addr[i], pdev->hw_info.bar_size[i]);
551                }
552        }
553    }
554    /* Now that the bars are mapped, we need to enable target read + write and master-enable,
555     * we can't do this before bars are mapped, but we need to do this before we start any chip
556     * initializations... */
557#if defined(__LINUX) || defined(_VBD_)
558    if (IS_PFDEV(pdev))
559    {
560        pdev->hw_info.pcie_caps_offset = mm_get_cap_offset(pdev, PCI_CAP_PCIE);
561        if (pdev->hw_info.pcie_caps_offset != 0 && pdev->hw_info.pcie_caps_offset != 0xFFFFFFFF)
562        {
563            mm_read_pci(pdev, pdev->hw_info.pcie_caps_offset + PCIE_DEV_CAPS, &pdev->hw_info.pcie_dev_capabilities);
564
565            DbgMessage(pdev, WARN,"Device Capability of PCIe caps is %x\n",pdev->hw_info.pcie_dev_capabilities);
566
567            if (pdev->hw_info.pcie_dev_capabilities)
568            {
569                if (pdev->hw_info.pcie_dev_capabilities & PCIE_DEV_CAPS_FLR_CAPABILITY)
570                {
571                    pdev->hw_info.flr_capable = TRUE;
572                }
573                else
574                {
575                    pdev->hw_info.flr_capable = FALSE; /*Not trusted for PCI_CFG accesible via hypervisor*/
576                }
577            }
578            else
579            {
580                pdev->hw_info.pci_cfg_trust = PCI_CFG_NOT_TRUSTED;
581            }
582        }
583        else
584        {
585            pdev->hw_info.pci_cfg_trust = PCI_CFG_NOT_TRUSTED;
586        }
587
588        if (!lm_is_function_after_flr(pdev))
589        {
590            pdev->hw_info.grc_didvid = REG_RD(pdev, (PCICFG_OFFSET + PCICFG_VENDOR_ID_OFFSET));
591            lm_status = mm_read_pci(pdev, PCICFG_VENDOR_ID_OFFSET, &pdev->hw_info.pci_cfg_didvid);
592            if (lm_status == LM_STATUS_SUCCESS)
593            {
594                if (pdev->hw_info.grc_didvid != pdev->hw_info.pci_cfg_didvid)
595                {
596                    pdev->hw_info.flr_capable = TRUE;
597                    pdev->params.is_flr = TRUE;
598                }
599            }
600        }
601    }
602#endif
603    if (lm_is_function_after_flr(pdev))
604    {
605        u32_t m_e,tr_e,tw_e;
606        u32_t i_cycles;
607        REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
608        for (i_cycles = 0; i_cycles < 1000; i_cycles++)
609        {
610            mm_wait(pdev,999);
611        }
612        tr_e = REG_RD(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ);
613        tw_e = REG_RD(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_WRITE);
614        m_e = REG_RD(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER);
615        DbgMessage(pdev, INFORM, "M:0x%x, TR:0x%x, TW:0x%x\n",m_e,tr_e,tw_e);
616        if (tw_e != 0x1)
617        {
618            DbgBreakMsg("BAR 0 must be present\n");
619            return LM_STATUS_FAILURE;
620        }
621    }
622    return LM_STATUS_SUCCESS;
623}
624
625lm_status_t lm_get_chip_id_and_mode(lm_device_t *pdev)
626{
627    u32_t val;
628    u32_t chip_rev;
629
630    /* Get the chip revision id and number. */
631    /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
632    val=REG_RD(PFDEV(pdev),MISC_REG_CHIP_NUM);
633    CHIP_NUM_SET(pdev->hw_info.chip_id,val);
634
635    /* If OTP process was done on the device, change chip number to 57811 */
636    val=REG_RD(PFDEV(pdev),MISC_REG_CHIP_TYPE);
637    if (val & CHIP_OPT_MISC_DO_BIT)
638    {
639         switch (pdev->hw_info.chip_id)
640         {
641            case CHIP_NUM_57810:
642                pdev->hw_info.chip_id = CHIP_NUM_57811;
643                break;
644            case CHIP_NUM_57810_MF:
645               pdev->hw_info.chip_id = CHIP_NUM_57811_MF;
646                break;
647            default:
648                DbgMessage(pdev, FATAL, "Un-supported chip id for OTP: %d\n", pdev->hw_info.chip_id);
649                DbgBreakIfAll(1);
650                return LM_STATUS_FAILURE;
651         }
652    }
653
654    val=REG_RD(PFDEV(pdev),MISC_REG_CHIP_REV);
655    // the chip rev is realy ASIC when it < 5
656    // when it > 5 odd mean FPGA even EMUL.
657    chip_rev = (val & 0xF)<<CHIP_REV_SHIFT;
658    pdev->hw_info.chip_id |= chip_rev;
659
660    if(chip_rev <= CHIP_REV_ASIC_MAX)
661    {
662        pdev->vars.clk_factor = 1;
663    }
664    else if(chip_rev & CHIP_REV_SIM_IS_FPGA)
665    {
666        pdev->vars.clk_factor = LM_FPGA_FACTOR;
667        DbgMessage(pdev, INFORMi, "FPGA: forcing MPS from %d to 0.\n", pdev->hw_info.max_payload_size);
668        pdev->hw_info.max_payload_size = 0;
669    }
670    else
671    {
672        pdev->vars.clk_factor = LM_EMUL_FACTOR;
673    }
674
675    val=REG_RD(PFDEV(pdev),MISC_REG_CHIP_METAL);
676    pdev->hw_info.chip_id |= (val & 0xff) << 4;
677    val=REG_RD(PFDEV(pdev),MISC_REG_BOND_ID);
678    pdev->hw_info.chip_id |= (val & 0xf);
679    DbgMessage(pdev, INFORMi , "chip id 0x%x\n", pdev->hw_info.chip_id);
680    /* Read silent revision */
681    val=REG_RD(PFDEV(pdev),MISC_REG_CHIP_TEST_REG);
682    pdev->hw_info.silent_chip_rev = (val & 0xff);
683    DbgMessage(pdev, INFORMi , "silent chip rev 0x%x\n", pdev->hw_info.silent_chip_rev);
684    if (!CHIP_IS_E1x(pdev))
685    {
686        /* Determine whether we are 2 port or 4 port mode */
687        /* read port4mode_en_ovwr[0];
688         * b)     if 0  read port4mode_en (0  2-port; 1  4-port);
689         * c)     if 1  read port4mode_en_ovwr[1] (0  2-port; 1  4-port);
690         */
691        val = REG_RD(PFDEV(pdev), MISC_REG_PORT4MODE_EN_OVWR);
692        DbgMessage(pdev, WARN, "MISC_REG_PORT4MODE_EN_OVWR = %d\n", val);
693        if ((val & 1) == 0)
694        {
695            val = REG_RD(PFDEV(pdev), MISC_REG_PORT4MODE_EN);
696        }
697        else
698        {
699            val = (val >> 1) & 1;
700        }
701        pdev->hw_info.chip_port_mode = val? LM_CHIP_PORT_MODE_4 : LM_CHIP_PORT_MODE_2;
702        DbgMessage(pdev, WARN, "chip_port_mode %s\n", (pdev->hw_info.chip_port_mode == LM_CHIP_PORT_MODE_4 )? "4_PORT" : "2_PORT");
703    }
704    else
705    {
706        pdev->hw_info.chip_port_mode = LM_CHIP_PORT_MODE_NONE; /* N/A */
707        DbgMessage(pdev, WARN, "chip_port_mode NONE\n");
708    }
709    return LM_STATUS_SUCCESS;
710}
711static void lm_get_igu_cam_info(lm_device_t *pdev)
712{
713    lm_intr_blk_info_t *blk_info = &pdev->hw_info.intr_blk_info;
714    u8_t igu_test_vectors = FALSE;
715    #define IGU_CAM_VFID_MATCH(pdev, igu_fid) (!(igu_fid & IGU_FID_ENCODE_IS_PF) && ((igu_fid & IGU_FID_VF_NUM_MASK) == ABS_VFID(pdev)))
716    #define IGU_CAM_PFID_MATCH(pdev, igu_fid) ((igu_fid & IGU_FID_ENCODE_IS_PF) && ((igu_fid & IGU_FID_PF_NUM_MASK) == FUNC_ID(pdev)))
717    if (INTR_BLK_MODE(pdev) == INTR_BLK_MODE_BC)
718    {
719        blk_info->igu_info.igu_sb_cnt       = MAX_RSS_CHAINS;
720        blk_info->igu_info.igu_u_sb_offset  = 0;
721        if (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_2)
722        {
723            blk_info->igu_info.igu_base_sb      = VNIC_ID(pdev) * MAX_RSS_CHAINS;
724            blk_info->igu_info.igu_dsb_id       = MAX_VNIC_NUM * MAX_RSS_CHAINS + VNIC_ID(pdev);
725        }
726        else
727        {
728            blk_info->igu_info.igu_base_sb      = FUNC_ID(pdev) * MAX_RSS_CHAINS;
729            blk_info->igu_info.igu_dsb_id       = MAX_VNIC_NUM * MAX_RSS_CHAINS + FUNC_ID(pdev);
730        }
731    }
732    else
733    {
734        u8_t igu_sb_id;
735        u8_t fid;
736        u8_t vec;
737        u8_t vf_id;
738        u32_t val;
739        u8_t current_pf_id = 0;
740        u8_t recent_vf_id = 0xFF;
741        blk_info->igu_info.igu_sb_cnt = 0;
742        blk_info->igu_info.igu_test_sb_cnt = 0;
743        blk_info->igu_info.igu_base_sb = 0xff;
744        for (vf_id = 0; vf_id < E2_MAX_NUM_OF_VFS; vf_id++)
745        {
746            blk_info->igu_info.vf_igu_info[vf_id].igu_base_sb = 0xFF;
747            blk_info->igu_info.vf_igu_info[vf_id].igu_sb_cnt = 0;
748            blk_info->igu_info.vf_igu_info[vf_id].igu_test_sb_cnt = 0;
749            blk_info->igu_info.vf_igu_info[vf_id].igu_test_mode = FALSE;
750        }
751        for (igu_sb_id = 0; igu_sb_id < IGU_REG_MAPPING_MEMORY_SIZE; igu_sb_id++ )
752        {
753            // mapping CAM; relevant for E2 operating mode only.
754            // [0] - valid.
755            // [6:1] - vector number;
756            // [13:7] - FID (if VF - [13] = 0; [12:7] = VF number; if PF - [13] = 1; [12:9] = 0; [8:7] = PF number);
757            lm_igu_block_t * lm_igu_sb = &IGU_SB(pdev,igu_sb_id);
758            lm_igu_sb->block_dump = val = REG_RD(PFDEV(pdev), IGU_REG_MAPPING_MEMORY + 4*igu_sb_id);
759            DbgMessage(pdev, WARN, "addr:0x%x IGU_CAM[%d]=%x\n",IGU_REG_MAPPING_MEMORY + 4*igu_sb_id, igu_sb_id, val);
760            if (!(val & IGU_REG_MAPPING_MEMORY_VALID))
761            {
762                if (!IS_MULTI_VNIC(pdev) && (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_2))
763                {
764                    lm_igu_sb->status = LM_IGU_STATUS_AVAILABLE;
765                }
766                else if (current_pf_id == FUNC_ID(pdev))
767                {
768                    lm_igu_sb->status = LM_IGU_STATUS_AVAILABLE;
769                }
770                else
771                {
772                    lm_igu_sb->status = 0;
773                }
774                continue;
775            }
776            else
777            {
778                lm_igu_sb->status = LM_IGU_STATUS_VALID;
779            }
780            fid = (val & IGU_REG_MAPPING_MEMORY_FID_MASK) >> IGU_REG_MAPPING_MEMORY_FID_SHIFT;
781            if (fid & IGU_FID_ENCODE_IS_PF)
782            {
783                current_pf_id = lm_igu_sb->pf_number = fid & IGU_FID_PF_NUM_MASK;
784                if (lm_igu_sb->pf_number == FUNC_ID(pdev))
785                {
786                    lm_igu_sb->status |= (LM_IGU_STATUS_AVAILABLE | LM_IGU_STATUS_PF);
787                }
788                else
789                {
790                    lm_igu_sb->status |= LM_IGU_STATUS_PF;
791                }
792            }
793            else
794            {
795                lm_igu_sb->vf_number = fid & IGU_FID_VF_NUM_MASK;
796                if ((lm_igu_sb->vf_number >= pdev->hw_info.sriov_info.first_vf_in_pf)
797                    && (lm_igu_sb->vf_number < (pdev->hw_info.sriov_info.first_vf_in_pf + pdev->hw_info.sriov_info.total_vfs)))
798                {
799                    lm_igu_sb->status |= LM_IGU_STATUS_AVAILABLE;
800                }
801            }
802            lm_igu_sb->vector_number = (val & IGU_REG_MAPPING_MEMORY_VECTOR_MASK) >> IGU_REG_MAPPING_MEMORY_VECTOR_SHIFT;
803            DbgMessage(pdev, VERBOSEi, "FID[%d]=%d\n", igu_sb_id, fid);
804            if ((IS_PFDEV(pdev) && IGU_CAM_PFID_MATCH(pdev, fid)) ||
805                (IS_VFDEV(pdev) && IGU_CAM_VFID_MATCH(pdev, fid)))
806            {
807                vec = (val & IGU_REG_MAPPING_MEMORY_VECTOR_MASK) >> IGU_REG_MAPPING_MEMORY_VECTOR_SHIFT;
808                DbgMessage(pdev, INFORMi, "VEC[%d]=%d\n", igu_sb_id, vec);
809                if (igu_test_vectors)
810                {
811                    blk_info->igu_info.igu_test_sb_cnt++;
812                }
813                else
814                {
815                    if (vec == 0 && IS_PFDEV(pdev))
816                    {
817                        /* default status block for default segment + attn segment */
818                        blk_info->igu_info.igu_dsb_id = igu_sb_id;
819                    }
820                    else
821                    {
822                        if (blk_info->igu_info.igu_base_sb == 0xff)
823                        {
824                            blk_info->igu_info.igu_base_sb = igu_sb_id;
825                        }
826                        /* we don't count the default */
827                        blk_info->igu_info.igu_sb_cnt++;
828                    }
829                }
830                if (recent_vf_id != 0xFF)
831                {
832                    if (!blk_info->igu_info.vf_igu_info[recent_vf_id].igu_test_mode)
833                    {
834                        DbgMessage(pdev, WARN, "Consecutiveness of IGU for VF%d is broken. My be it's IGU test mode\n",recent_vf_id);
835                    }
836                    blk_info->igu_info.vf_igu_info[recent_vf_id].igu_test_mode = TRUE;
837                }
838            }
839            else if (IS_CHANNEL_VIRT_MODE_MASTER_PFDEV(pdev))
840            {
841                if (!(fid & IGU_FID_ENCODE_IS_PF))
842                {
843                     vf_id = fid & IGU_FID_VF_NUM_MASK;
844                     if (blk_info->igu_info.vf_igu_info[vf_id].igu_base_sb == 0xff)
845                     {
846                         blk_info->igu_info.vf_igu_info[vf_id].igu_base_sb = igu_sb_id;
847                     }
848                     /* we don't count the default */
849                     if (recent_vf_id != vf_id)
850                     {
851                         if (recent_vf_id != 0xFF)
852                         {
853                             if (!blk_info->igu_info.vf_igu_info[recent_vf_id].igu_test_mode)
854                             {
855                                 DbgMessage(pdev, WARN, "Consecutiveness of IGU for VF%d is broken. My be it's IGU test mode\n",recent_vf_id);
856                             }
857                             blk_info->igu_info.vf_igu_info[recent_vf_id].igu_test_mode = TRUE;
858                         }
859                     }
860                     recent_vf_id = vf_id;
861                     if (blk_info->igu_info.vf_igu_info[vf_id].igu_test_mode)
862                     {
863                         blk_info->igu_info.vf_igu_info[vf_id].igu_test_sb_cnt++;
864                     }
865                     else
866                     {
867                         blk_info->igu_info.vf_igu_info[vf_id].igu_sb_cnt++;
868                     }
869                }
870                else
871                {
872                    if (recent_vf_id != 0xFF)
873                    {
874                        if (!blk_info->igu_info.vf_igu_info[recent_vf_id].igu_test_mode)
875                        {
876                                DbgMessage(pdev, WARN, "Consecutiveness of IGU for VF%d is broken. My be it's IGU test mode\n",recent_vf_id);
877                        }
878                        blk_info->igu_info.vf_igu_info[recent_vf_id].igu_test_mode = TRUE;
879                    }
880                }
881                if (blk_info->igu_info.igu_base_sb != 0xff)
882                {
883                    /* We've already found our base... but now we don't match... these are now igu-test-vectors */
884                    if (!igu_test_vectors)
885                    {
886                            DbgMessage(pdev, WARN, "Consecutiveness of IGU is broken. My be it's IGU test mode\n");
887                    }
888                    igu_test_vectors = TRUE; //TODO Michals: take care of this!!!e2 igu_test will fail.
889                }
890            }
891            else
892            {
893                /* No Match - belongs to someone else, check if breaks consecutiveness, if so, break at this point
894                 * driver doesn't support non-consecutive vectors (EXCEPT Def sb...) */
895                if (blk_info->igu_info.igu_base_sb != 0xff)
896                {
897                    /* We've already found our base... but now we don't match... these are now igu-test-vectors */
898                    if (!igu_test_vectors) {
899                        DbgMessage(pdev, WARN, "Consecutiveness of IGU is broken. My be it's IGU test mode\n");
900                    }
901                    igu_test_vectors = TRUE; //TODO Michals: take care of this!!!e2 igu_test will fail.
902                }
903            }
904        }
905        // TODO check cam is valid...
906#ifndef _VBD_
907        blk_info->igu_info.igu_sb_cnt = min(blk_info->igu_info.igu_sb_cnt, (u8_t)16);
908#endif
909        /* E2 TODO: if we don't want to separate u/c/ producers in IGU, this line needs to
910         * be removed, and igu_u_offset needs to be set to 'zero'
911        blk_info->igu_info.igu_u_sb_offset = blk_info->igu_info.igu_sb_cnt / 2;*/
912        DbgMessage(pdev, WARN, "igu_sb_cnt=%d igu_dsb_id=%d igu_base_sb = %d igu_us_sb_offset = %d igu_test_cnt=%d\n",
913                    blk_info->igu_info.igu_sb_cnt, blk_info->igu_info.igu_dsb_id, blk_info->igu_info.igu_base_sb, blk_info->igu_info.igu_u_sb_offset,
914                    blk_info->igu_info.igu_test_sb_cnt);
915
916        /* CQ61438 - do not show this error message in case of mf mode changed to SF and func >= 2*/
917        if ((FUNC_ID(pdev) < 2) && (pdev->hw_info.mf_info.mf_mode != SINGLE_FUNCTION))
918        {
919            if (blk_info->igu_info.igu_sb_cnt < 1)
920            {
921                DbgMessage(pdev, FATAL, "Igu sb cnt is not valid value=%d\n", blk_info->igu_info.igu_sb_cnt);
922            }
923            if (blk_info->igu_info.igu_base_sb == 0xff)
924            {
925                DbgMessage(pdev, FATAL, "Igu base sb is not valid value=%d\n", blk_info->igu_info.igu_base_sb);
926            }
927        }
928
929#define IGU_MAX_INTA_SB_CNT 31
930
931        /* CQ72933/CQ72546
932           In case we are in INTA mode, we limit the igu count to 31 as we can't handle more than that */
933        if (pdev->params.b_inta_mode_prvided_by_os && (blk_info->igu_info.igu_sb_cnt > IGU_MAX_INTA_SB_CNT ))
934        {
935            blk_info->igu_info.igu_sb_cnt = IGU_MAX_INTA_SB_CNT ;
936        }
937    }
938
939    DbgMessage(pdev, WARN, "IGU CAM INFO: BASE_SB: %d DSB: %d IGU_SB_CNT: %d\n", blk_info->igu_info.igu_base_sb, blk_info->igu_info.igu_dsb_id, blk_info->igu_info.igu_sb_cnt);
940}
941/*
942 * Assumptions:
943 *  - the following are initialized before call to this function:
944 *    chip-id, func-rel,
945 */
946lm_status_t lm_get_intr_blk_info(lm_device_t *pdev)
947{
948    lm_intr_blk_info_t *blk_info = &pdev->hw_info.intr_blk_info;
949    u32_t bar_base;
950    u8_t igu_func_id = 0;
951
952    if (CHIP_IS_E1x(pdev))
953    {
954        blk_info->blk_type         = INTR_BLK_HC;
955        blk_info->access_type      = INTR_BLK_ACCESS_GRC;
956        blk_info->blk_mode         = INTR_BLK_MODE_NORM;
957        blk_info->simd_addr_womask = HC_REG_COMMAND_REG + PORT_ID(pdev)*32 + COMMAND_REG_SIMD_NOMASK;
958        /* The next part is tricky... and has to do with an emulation work-around for handling interrupts, in which
959         * we want to read without mask - always... so we take care of it here, instead of changing different ums to
960         * call approriate function */
961        if (CHIP_REV_IS_EMUL(pdev))
962        {
963            blk_info->simd_addr_wmask = HC_REG_COMMAND_REG + PORT_ID(pdev)*32 + COMMAND_REG_SIMD_NOMASK;
964        }
965        else
966        {
967            blk_info->simd_addr_wmask = HC_REG_COMMAND_REG + PORT_ID(pdev)*32 + COMMAND_REG_SIMD_MASK;
968        }
969    }
970    else
971    {
972        /* If we have more than 32 status blocks we'll need to read from IGU_REG_SISR_MDPC_WMASK_UPPER */
973        ASSERT_STATIC(MAX_RSS_CHAINS <= 32);
974        pdev->hw_info.intr_blk_info.blk_type = INTR_BLK_IGU;
975        if (REG_RD(PFDEV(pdev), IGU_REG_BLOCK_CONFIGURATION) & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN)
976        {
977            DbgMessage(pdev, FATAL, "IGU Backward Compatible Mode\n");
978            blk_info->blk_mode = INTR_BLK_MODE_BC;
979        }
980        else
981        {
982            DbgMessage(pdev, WARN, "IGU Normal Mode\n");
983            blk_info->blk_mode = INTR_BLK_MODE_NORM;
984        }
985        /* read CAM to get igu info (must be called after we know if we're in backward compatible mode or not )*/
986        lm_get_igu_cam_info(pdev);
987
988        igu_func_id = (1 << IGU_FID_ENCODE_IS_PF_SHIFT) | FUNC_ID(pdev);
989        blk_info->igu_info.igu_func_id = igu_func_id;
990        if (pdev->params.igu_access_mode == INTR_BLK_ACCESS_GRC)
991        {
992            DbgMessage(pdev, FATAL, "IGU -  GRC\n");
993            if (IS_VFDEV(pdev))
994            {
995                DbgBreakMsg("VF Can't work in GRC Access mode!\n");
996                return LM_STATUS_FAILURE;
997            }
998            blk_info->access_type = INTR_BLK_ACCESS_GRC;
999            /* [18:12] - FID (if VF - [18] = 0; [17:12] = VF number; if PF - [18] = 1; [17:14] = 0; [13:12] = PF number) */
1000            blk_info->cmd_ctrl_rd_womask =
1001            ((IGU_REG_SISR_MDPC_WOMASK_UPPER << IGU_CTRL_REG_ADDRESS_SHIFT) |
1002             (igu_func_id << IGU_CTRL_REG_FID_SHIFT) |
1003             (IGU_CTRL_CMD_TYPE_RD << IGU_CTRL_REG_TYPE_SHIFT));
1004            blk_info->simd_addr_womask = IGU_REG_COMMAND_REG_32LSB_DATA; /* this is where data will be after writing ctrol reg... */
1005            /* The next part is tricky... and has to do with an emulation work-around for handling interrupts, in which
1006             * we want to read without mask - always... so we take care of it here, instead of changing different ums to
1007             * call approriate function */
1008            if (CHIP_REV_IS_EMUL(pdev))
1009            {
1010                blk_info->cmd_ctrl_rd_wmask =
1011                ((IGU_REG_SISR_MDPC_WOMASK_UPPER << IGU_CTRL_REG_ADDRESS_SHIFT) |
1012                 (igu_func_id << IGU_CTRL_REG_FID_SHIFT) |
1013                 (IGU_CTRL_CMD_TYPE_RD << IGU_CTRL_REG_TYPE_SHIFT));
1014            }
1015            else
1016            {
1017                blk_info->cmd_ctrl_rd_wmask =
1018                ((IGU_REG_SISR_MDPC_WMASK_LSB_UPPER << IGU_CTRL_REG_ADDRESS_SHIFT) |
1019                 (igu_func_id << IGU_CTRL_REG_FID_SHIFT) |
1020                 (IGU_CTRL_CMD_TYPE_RD << IGU_CTRL_REG_TYPE_SHIFT));
1021            }
1022            blk_info->simd_addr_wmask = IGU_REG_COMMAND_REG_32LSB_DATA; /* this is where data will be after writing ctrol reg... */
1023        }
1024        else
1025        {
1026            DbgMessage(pdev, WARN, "IGU  - IGUMEM\n");
1027            blk_info->access_type = INTR_BLK_ACCESS_IGUMEM;
1028            bar_base = IS_PFDEV(pdev)? BAR_IGU_INTMEM : VF_BAR0_IGU_OFFSET;
1029            blk_info->simd_addr_womask = bar_base + IGU_REG_SISR_MDPC_WOMASK_UPPER*8;
1030            /* The next part is tricky... and has to do with an emulation work-around for handling interrupts, in which
1031             * we want to read without mask - always... so we take care of it here, instead of changing different ums to
1032             * call approriate function */
1033            if (CHIP_REV_IS_EMUL(pdev))
1034            {
1035                blk_info->simd_addr_wmask = bar_base + IGU_REG_SISR_MDPC_WOMASK_UPPER*8;
1036            }
1037            else
1038            {
1039                blk_info->simd_addr_wmask = bar_base + IGU_REG_SISR_MDPC_WMASK_LSB_UPPER*8;
1040            }
1041        }
1042    }
1043    return LM_STATUS_SUCCESS;
1044}
1045
1046lm_status_t lm_get_nvm_info(lm_device_t *pdev)
1047{
1048    u32_t val = REG_RD(pdev,MCP_REG_MCPR_NVM_CFG4);
1049
1050    pdev->hw_info.flash_spec.total_size = NVRAM_1MB_SIZE << (val & MCPR_NVM_CFG4_FLASH_SIZE);
1051    pdev->hw_info.flash_spec.page_size  = NVRAM_PAGE_SIZE;
1052
1053    return LM_STATUS_SUCCESS;
1054}
1055#if defined(DOS) || defined(__LINUX)
1056/* for ediag + lediat we don't really care about licensing!... */
1057#define DEFAULT_CONNECTIONS_TOE 1880
1058#define MAX_CONNECTIONS         2048  /* Max 32K Connections per port / vnic-per-port (rounded  to power2)*/
1059#define MAX_CONNECTIONS_ISCSI    128
1060#define MAX_CONNECTIONS_RDMA      10
1061#define MAX_CONNECTIONS_TOE     1880
1062#define MAX_CONNECTIONS_FCOE       0
1063#define MAX_CONNECTIONS_VF       128
1064
1065#else
1066
1067#define MAX_CONNECTIONS (min(16384,(32768 / (log2_align(pdev->hw_info.mf_info.vnics_per_port)))))  /* Max 32K Connections per port / vnic-per-port (rounded  to power2)
1068                                                                                                   but no more 16K to limit ilt client page size by 64KB*/
1069
1070#define DEFAULT_CONNECTIONS_TOE 1880
1071#define MAX_CONNECTIONS_ISCSI    128
1072#define MAX_CONNECTIONS_RDMA      10
1073#define MAX_CONNECTIONS_FCOE    1024
1074#define MAX_CONNECTIONS_VF      (1 << (LM_VF_MAX_RVFID_SIZE + LM_MAX_VF_CID_WND_SIZE + 1))
1075#define MAX_CONNECTIONS_TOE     (min(8192,MAX_CONNECTIONS - MAX_CONNECTIONS_ISCSI - MAX_CONNECTIONS_RDMA - MAX_CONNECTIONS_FCOE - MAX_ETH_CONS - MAX_CONNECTIONS_VF))
1076
1077#endif
1078
1079
1080#define MAX_CONNECTIONS_TOE_NO_LICENSE   0
1081#define MAX_CONNECTIONS_ISCSI_NO_LICENSE 0
1082#define MAX_CONNECTIONS_RDMA_NO_LICENSE  0
1083#define MAX_CONNECTIONS_FCOE_NO_LICENSE  0
1084
1085#define MAX_CONNECTIONS_FCOE_NO_MCP      128
1086
1087static u32_t lm_parse_license_info(u32 val, u8_t is_high)
1088{
1089    if (is_high)
1090    {
1091        val &=0xFFFF0000;
1092        if(val)
1093        {
1094            val ^= FW_ENCODE_32BIT_PATTERN;
1095        }
1096        val >>= 16;
1097    }
1098    else
1099    {
1100        val &= 0xffff;
1101        if(val)
1102        {
1103            val ^= FW_ENCODE_16BIT_PATTERN;
1104        }
1105    }
1106    return val;
1107}
1108
1109static u32_t lm_parse_license_info_bounded(u32 val, u32_t max_cons, u8_t is_high)
1110{
1111    u32_t license_from_shmem =0;
1112    license_from_shmem = lm_parse_license_info(val, is_high);
1113
1114    val = min(license_from_shmem, max_cons);
1115    return val;
1116}
1117/* No special MCP handling for a specific E1H configuration */
1118/* WARNING: Do Not Change these defines!!! They are used in an external tcl script that assumes their values!!! */
1119#define NO_MCP_WA_CFG_SET_ADDR            (0xA0000)
1120#define NO_MCP_WA_CFG_SET_MAGIC           (0x88AA55FF)
1121#define NO_MCP_WA_MULTI_VNIC_MODE         (0xA0004)
1122#define NO_MCP_WA_VNICS_PER_PORT(port)    (0xA0008 + 4*(port))
1123#define NO_MCP_WA_OVLAN(func)             (0xA0010 + 4*(func)) // --> 0xA0030
1124#define NO_MCP_WA_FORCE_5710              (0xA0030)
1125#define NO_MCP_WA_VALID_LIC_ADDR          (0xA0040)
1126#define NO_MCP_WA_VALID_LIC_MAGIC         (0xCCAAFFEE)
1127#define NO_MCP_WA_TOE_LIC                 (0xA0048)
1128#define NO_MCP_WA_ISCSI_LIC               (0xA0050)
1129#define NO_MCP_WA_RDMA_LIC                (0xA0058)
1130#define NO_MCP_WA_CLC_SHMEM               (0xAF900)
1131
1132static lm_status_t lm_get_shmem_license_info(lm_device_t *pdev)
1133{
1134    u32_t max_toe_cons[PORT_MAX]           = {0,0};
1135    u32_t max_rdma_cons[PORT_MAX]          = {0,0};
1136    u32_t max_iscsi_cons[PORT_MAX]         = {0,0};
1137    u32_t max_fcoe_cons[PORT_MAX]          = {0,0};
1138    u32_t max_eth_cons[PORT_MAX]           = {0,0}; /* Includes VF connections */
1139    u32_t max_bar_supported_cons[PORT_MAX] = {0};
1140    u32_t max_supported_cons[PORT_MAX]     = {0};
1141    u32_t val                              = 0;
1142    u8_t  port                             = 0;
1143    u32_t offset                           = 0;
1144
1145    /* Even though only one port actually does the initialization, ALL functions need to know the maximum number of connections
1146     * because that's how they know what the page-size-is, and based on that do per-function initializations as well. */
1147    pdev->hw_info.max_common_conns = 0;
1148
1149    /* get values for relevant ports. */
1150    for (port = 0; port < PORT_MAX; port++)
1151    {
1152        if (pdev->hw_info.mcp_detected == 1)
1153        {
1154            LM_SHMEM_READ(pdev, OFFSETOF(shmem_region_t, validity_map[port]),&val);
1155
1156            // check that licensing is enabled
1157            if(GET_FLAGS(val, SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT | SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT))
1158            {
1159                // align to 32 bit
1160                offset = OFFSETOF(shmem_region_t, drv_lic_key[port].max_toe_conn) & 0xfffffffc;
1161                LM_SHMEM_READ(pdev, offset, &val);
1162                max_toe_cons[port] = lm_parse_license_info_bounded(val, MAX_CONNECTIONS_TOE,FALSE);
1163                DbgMessage(pdev, INFORMi, "max_toe_conn from shmem %d for port %d\n",val, port);
1164                /* RDMA */
1165                offset = OFFSETOF(shmem_region_t, drv_lic_key[port].max_um_rdma_conn) & 0xfffffffc;
1166                LM_SHMEM_READ(pdev, offset, &val);
1167                max_rdma_cons[port] = lm_parse_license_info_bounded(val, MAX_CONNECTIONS_RDMA,FALSE);
1168                DbgMessage(pdev, INFORMi, "max_rdma_conn from shmem %d for port %d\n",val, port);
1169                /* ISCSI */
1170                offset = OFFSETOF(shmem_region_t, drv_lic_key[port].max_iscsi_trgt_conn) & 0xfffffffc;
1171                LM_SHMEM_READ(pdev, offset, &val);
1172                max_iscsi_cons[port] = lm_parse_license_info_bounded(val, MAX_CONNECTIONS_ISCSI,TRUE);
1173                DbgMessage(pdev, INFORMi, "max_iscsi_conn from shmem %d for port %d\n",val, port);
1174                /* FCOE */
1175                offset = OFFSETOF(shmem_region_t, drv_lic_key[port].max_fcoe_init_conn) & 0xfffffffc;
1176                LM_SHMEM_READ(pdev, offset, &val);
1177                if(0 == lm_parse_license_info(val,TRUE))
1178                {
1179                    max_fcoe_cons[port] = 0;
1180                }
1181                else
1182                {
1183                    max_fcoe_cons[port] = MAX_CONNECTIONS_FCOE;
1184                }
1185                DbgMessage(pdev, INFORMi, "max_fcoe_conn from shmem %d for port %d\n",val, port);
1186
1187            }
1188            else
1189            {
1190                // In case MCP is enabled and there is no licence => there should be no offload connection.
1191                max_toe_cons[port]      = MAX_CONNECTIONS_TOE_NO_LICENSE;
1192                max_rdma_cons[port]     = MAX_CONNECTIONS_ISCSI_NO_LICENSE;
1193                max_iscsi_cons[port]    = MAX_CONNECTIONS_RDMA_NO_LICENSE;
1194                max_fcoe_cons[port]     = MAX_CONNECTIONS_FCOE_NO_LICENSE;
1195            }
1196            if (CHIP_IS_E1x(pdev))
1197            {
1198                max_eth_cons[port] = MAX_ETH_REG_CONS;
1199            }
1200            else
1201            {
1202                max_eth_cons[port] = MAX_CONNECTIONS_VF;
1203            }
1204
1205            /* get the bar size... unless it's current port and then we have it. otherwise, read from shmem W.C which
1206             * is what the other ports asked for, they could have gotten less, but we're looking into the worst case. */
1207            if (PORT_ID(pdev) == port)
1208            {
1209                max_bar_supported_cons[port] = pdev->hw_info.bar_size[BAR_1] / LM_DQ_CID_SIZE;
1210            }
1211            else
1212            {
1213                LM_SHMEM_READ(pdev, OFFSETOF(shmem_region_t, dev_info.port_feature_config[port].config), &val);
1214                val = (val & PORT_FEAT_CFG_BAR2_SIZE_MASK) >> PORT_FEAT_CFG_BAR2_SIZE_SHIFT;
1215                if (val != 0)
1216                 {
1217                    /* bit 1 stand for 64K each bit multiply it by two */
1218                    val = (0x40 << ((val - 1)))*0x400;
1219                }
1220                max_bar_supported_cons[port] = val / LM_DQ_CID_SIZE;
1221            }
1222        }
1223        else
1224        {
1225            // MCP_WA
1226            LM_SHMEM_READ(pdev, NO_MCP_WA_VALID_LIC_ADDR+4*port, &val);
1227
1228            if (val == NO_MCP_WA_VALID_LIC_MAGIC)
1229            {
1230                LM_SHMEM_READ(pdev, NO_MCP_WA_TOE_LIC+4*port, &val);
1231                max_toe_cons[port] = val;
1232                LM_SHMEM_READ(pdev, NO_MCP_WA_ISCSI_LIC+4*port, &val);
1233                max_iscsi_cons[port] = val;
1234                LM_SHMEM_READ(pdev, NO_MCP_WA_RDMA_LIC+4*port, &val);
1235                max_rdma_cons[port] = val;
1236
1237                /* FCOE */
1238                // For backward compatibility, same value if it will be required we can add NO_MCP_WA_FCOE_LIC
1239                max_fcoe_cons[port] = MAX_CONNECTIONS_FCOE_NO_MCP;
1240                // Fcoe licencing isn't supported.
1241                /*
1242                LM_SHMEM_READ(pdev, NO_MCP_WA_FCOE_LIC+4*port, &val);
1243                max_fcoe_cons[port] = val;
1244                */
1245            }
1246            else
1247            {
1248                #ifdef VF_INVOLVED
1249                max_toe_cons[port] = DEFAULT_CONNECTIONS_TOE - 100;
1250                #else
1251                max_toe_cons[port] = DEFAULT_CONNECTIONS_TOE;
1252                #endif
1253                max_iscsi_cons[port] = MAX_CONNECTIONS_ISCSI;
1254                max_rdma_cons[port]  = MAX_CONNECTIONS_RDMA;
1255                // Need to review this value seems like we take in this case the max value
1256                max_fcoe_cons[port] = MAX_CONNECTIONS_FCOE_NO_MCP;
1257            }
1258            if (CHIP_IS_E1x(pdev))
1259            {
1260                max_eth_cons[port] = MAX_ETH_REG_CONS;
1261            }
1262            else
1263            {
1264                max_eth_cons[port] = MAX_CONNECTIONS_VF;
1265            }
1266            /* For MCP - WA, we always assume the same bar size for all ports: makes life simpler... */
1267            max_bar_supported_cons[port] = pdev->hw_info.bar_size[BAR_1] / LM_DQ_CID_SIZE;
1268        }
1269        /* so after all this - what is the maximum number of connections supported for this port? */
1270        max_supported_cons[port] = log2_align(max_toe_cons[port] + max_rdma_cons[port] + max_iscsi_cons[port] + max_fcoe_cons[port] + max_eth_cons[port]);
1271        max_supported_cons[port] = min(max_supported_cons[port], max_bar_supported_cons[port]);
1272
1273        /* And after all this... in lediag  / ediag... we assume a maximum of 1024 connections */
1274        #if defined(DOS) || defined(__LINUX)
1275        max_supported_cons[port] = min(max_supported_cons[port], (u32_t)1024);
1276        #endif
1277
1278        if (max_supported_cons[port] > pdev->hw_info.max_common_conns)
1279        {
1280            pdev->hw_info.max_common_conns = max_supported_cons[port];
1281        }
1282
1283
1284    }
1285    /* Now, port specific... */
1286    port = PORT_ID(pdev);
1287    /* now, there could be a problem where the bar limited us, and the max-connections is smaller than the total above, in this case we need to decrease the
1288     * numbers relatively... can't touch MAX_ETH_CONS... */
1289    if (ERR_IF(max_supported_cons[port] < max_eth_cons[port]))
1290    {
1291        return LM_STATUS_INVALID_PARAMETER;
1292    }
1293    if ((max_iscsi_cons[port]  + max_rdma_cons[port] +  max_toe_cons[port] + max_fcoe_cons[port] + max_eth_cons[port]) > max_supported_cons[port])
1294    {
1295        /* we first try giving iscsi + rdma what they asked for... */
1296        if ((max_iscsi_cons[port] + max_rdma_cons[port] + max_fcoe_cons[port] + max_eth_cons[port]) > max_supported_cons[port])
1297        {
1298            u32_t s = max_iscsi_cons[port] + max_rdma_cons[port] +  max_toe_cons[port] + max_fcoe_cons[port]; /* eth out of the game... */
1299            u32_t t = max_supported_cons[port] - pdev->params.max_eth_including_vfs_conns; /* what we want to reach... */
1300            /* relatively decrease all... (x+y+z=s, actual = t: xt/s+yt/s+zt/s = t) */
1301            max_iscsi_cons[port] *=t;
1302            max_iscsi_cons[port] /=s;
1303            max_rdma_cons[port]  *=t;
1304            max_rdma_cons[port]  /=s;
1305            max_toe_cons[port]   *=t;
1306            max_toe_cons[port]   /=s;
1307            max_fcoe_cons[port]  *=t;
1308            max_fcoe_cons[port]  /=s;
1309        }
1310        else
1311         {
1312            /* just give toe what's left... */
1313            max_toe_cons[port] = max_supported_cons[port] - (max_iscsi_cons[port] + max_rdma_cons[port]  + max_fcoe_cons[port] + max_eth_cons[port]);
1314        }
1315    }
1316    if (ERR_IF((max_iscsi_cons[port]  + max_rdma_cons[port] + max_fcoe_cons[port] + max_toe_cons[port] + max_eth_cons[port]) > max_supported_cons[port]))
1317    {
1318        return LM_STATUS_INVALID_PARAMETER;
1319    }
1320
1321    /* Now lets save our port-specific variables. By this stage we have the maximum supported connections for our port. */
1322    pdev->hw_info.max_port_toe_conn = max_toe_cons[port];
1323    DbgMessage(pdev, INFORMi, "max_toe_conn from shmem %d\n",pdev->hw_info.max_port_toe_conn);
1324    /* RDMA */
1325    pdev->hw_info.max_port_rdma_conn = max_rdma_cons[port];
1326    DbgMessage(pdev, INFORMi, "max_rdma_conn from shmem %d\n",pdev->hw_info.max_port_rdma_conn);
1327    /* ISCSI */
1328    pdev->hw_info.max_port_iscsi_conn = max_iscsi_cons[port];
1329    DbgMessage(pdev, INFORMi, "max_iscsi_conn from shmem %d\n",pdev->hw_info.max_port_iscsi_conn);
1330    /* FCOE */
1331    pdev->hw_info.max_port_fcoe_conn = max_fcoe_cons[port];
1332    DbgMessage(pdev, INFORMi, "max_fcoe_conn from shmem %d\n",pdev->hw_info.max_port_fcoe_conn);
1333
1334    pdev->hw_info.max_port_conns = log2_align(pdev->hw_info.max_port_toe_conn +
1335                                              pdev->hw_info.max_port_rdma_conn + pdev->hw_info.max_port_iscsi_conn
1336                                              + pdev->hw_info.max_port_fcoe_conn + pdev->params.max_eth_including_vfs_conns);
1337
1338    if (ERR_IF(pdev->hw_info.max_port_conns > max_bar_supported_cons[port]))
1339    {
1340        /* this would mean an error in the calculations above. */
1341        return LM_STATUS_INVALID_PARAMETER;
1342    }
1343
1344    return LM_STATUS_SUCCESS;
1345}
1346static lm_status_t lm_check_valid_mf_cfg(lm_device_t *pdev)
1347{
1348    lm_hardware_mf_info_t *mf_info    = &pdev->hw_info.mf_info;
1349    lm_status_t           lm_status   = LM_STATUS_SUCCESS;
1350    const u8_t            func_id     = FUNC_ID(pdev);
1351    u8_t                  i           = 0;
1352    u8_t                  j           = 0;
1353    u32_t                 mf_cfg1     = 0;
1354    u32_t                 mf_cfg2     = 0;
1355    u32_t                 ovlan1      = 0;
1356    u32_t                 ovlan2      = 0;
1357    u32_t                 dynamic_cfg = 0;
1358
1359    /* hard coded offsets in vnic_cfg.tcl. if assertion here fails,
1360     * need to fix vnic_cfg.tcl script as well. */
1361//    ASSERT_STATIC(OFFSETOF(shmem_region_t,mf_cfg)            == 0x7e4);
1362    ASSERT_STATIC(OFFSETOF(mf_cfg_t,shared_mf_config.clp_mb) == 0);
1363  //ASSERT_STATIC(MCP_CLP_MB_NO_CLP                          == 0x80000000); not yet defined
1364    ASSERT_STATIC(OFFSETOF(mf_cfg_t,func_mf_config)          == 36);
1365    ASSERT_STATIC(OFFSETOF(func_mf_cfg_t,config)             == 0);
1366    ASSERT_STATIC(FUNC_MF_CFG_FUNC_HIDE                      == 0x1);
1367    ASSERT_STATIC(FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA    == 0x4);
1368    ASSERT_STATIC(FUNC_MF_CFG_FUNC_DISABLED                  == 0x8);
1369    ASSERT_STATIC(OFFSETOF(func_mf_cfg_t,mac_upper)          == 4);
1370    ASSERT_STATIC(OFFSETOF(func_mf_cfg_t,mac_lower)          == 8);
1371    ASSERT_STATIC(FUNC_MF_CFG_UPPERMAC_DEFAULT               == 0x0000ffff);
1372    ASSERT_STATIC(FUNC_MF_CFG_LOWERMAC_DEFAULT               == 0xffffffff);
1373    ASSERT_STATIC(OFFSETOF(func_mf_cfg_t,e1hov_tag)          == 12);
1374    ASSERT_STATIC(FUNC_MF_CFG_E1HOV_TAG_DEFAULT              == 0x0000ffff);
1375    ASSERT_STATIC(sizeof(func_mf_cfg_t)                      == 24);
1376
1377    /* trace mf cfg parameters */
1378    DbgMessage(pdev, INFORMi, "MF cfg parameters for function %d:\n", func_id);
1379    DbgMessage(pdev, INFORMi, "\t func_mf_cfg=0x%x\n\t multi_vnics_mode=%d\n\t vnics_per_port=%d\n\t ovlan/vifid=%d\n\t min_bw=%d\n\t max_bw=%d\n",
1380                mf_info->func_mf_cfg,
1381                mf_info->vnics_per_port,
1382                mf_info->multi_vnics_mode,
1383                mf_info->ext_id,
1384                mf_info->min_bw,
1385                mf_info->max_bw);
1386    DbgMessage(pdev, INFORMi, "\t mac addr (overiding main and iscsi): %02x %02x %02x %02x %02x %02x\n",
1387            pdev->hw_info.mac_addr[0],
1388            pdev->hw_info.mac_addr[1],
1389            pdev->hw_info.mac_addr[2],
1390            pdev->hw_info.mac_addr[3],
1391            pdev->hw_info.mac_addr[4],
1392            pdev->hw_info.mac_addr[5]);
1393
1394    /* verify that function is not hidden */
1395    if (GET_FLAGS(mf_info->func_mf_cfg, FUNC_MF_CFG_FUNC_HIDE))
1396    {
1397        DbgMessage(pdev, FATAL, "Enumerated function %d, is marked as hidden\n", func_id);
1398        lm_status = LM_STATUS_FAILURE;
1399        goto _end;
1400    }
1401
1402    if (mf_info->vnics_per_port > 1 && !mf_info->multi_vnics_mode)
1403    {
1404        DbgMessage(pdev, FATAL, "invalid mf mode configuration: vnics_per_port=%d, multi_vnics_mode=%d\n",
1405                    mf_info->vnics_per_port,
1406                    mf_info->multi_vnics_mode);
1407        lm_status = LM_STATUS_FAILURE;
1408        //DbgBreakIf(1);
1409        goto _end;
1410    }
1411
1412    /* Sanity checks on outer-vlan for switch_dependent_mode... */
1413    if (mf_info->mf_mode == MULTI_FUNCTION_SD)
1414    {
1415        /* enumerated vnic id > 0 must have valid ovlan if we're in switch-dependet mode */
1416        if ((VNIC_ID(pdev) > 0) && !VALID_OVLAN(OVLAN(pdev)))
1417        {
1418            DbgMessage(pdev, WARNi, "invalid mf mode configuration: VNICID=%d, Function is enumerated, ovlan (%d) is invalid\n",
1419                        VNIC_ID(pdev), OVLAN(pdev));
1420#ifdef EDIAG
1421            // Allow OVLAN 0xFFFF in ediag UFP mode
1422            if (mf_info->sd_mode != SD_UFP_MODE)
1423            {
1424                lm_status = LM_STATUS_FAILURE;
1425            }
1426#else
1427            lm_status = LM_STATUS_FAILURE;
1428#endif
1429            goto _end;
1430        }
1431
1432        /* additional sanity checks */
1433        if (!VALID_OVLAN(OVLAN(pdev)) && mf_info->multi_vnics_mode)
1434        {
1435            DbgMessage(pdev, FATAL, "invalid mf mode configuration: multi_vnics_mode=%d, ovlan=%d\n",
1436                        mf_info->multi_vnics_mode,
1437                        OVLAN(pdev));
1438#ifdef EDIAG
1439            // Allow OVLAN 0xFFFF in ediag UFP mode
1440            if (mf_info->sd_mode != SD_UFP_MODE)
1441            {
1442                lm_status = LM_STATUS_FAILURE;
1443            }
1444#else
1445            lm_status = LM_STATUS_FAILURE;
1446#endif
1447            goto _end;
1448        }
1449        /* verify all functions are either mf mode or sf mode:
1450         * if we set mode to mf, make sure that all non hidden functions have valid ovlan
1451         * if we set mode to sf, make sure that all non hidden functions have invalid ovlan */
1452        LM_FOREACH_ABS_FUNC_IN_PORT(pdev, i)
1453        {
1454            LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[i].config),&mf_cfg1);
1455            LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[i].e1hov_tag), &ovlan1);
1456            if (!GET_FLAGS(mf_cfg1, FUNC_MF_CFG_FUNC_HIDE) &&
1457                (((mf_info->multi_vnics_mode) && !VALID_OVLAN(ovlan1)) ||
1458                 ((!mf_info->multi_vnics_mode) && VALID_OVLAN(ovlan1))))
1459            {
1460#ifdef EDIAG
1461				// Allow OVLAN 0xFFFF in eDiag UFP mode
1462                if (mf_info->sd_mode != SD_UFP_MODE)
1463                {
1464	                lm_status = LM_STATUS_FAILURE;
1465                }
1466#else
1467		lm_status= LM_STATUS_FAILURE;
1468#endif
1469                goto _end;
1470            }
1471        }
1472        /* verify different ovlan between funcs on same port */
1473        LM_FOREACH_ABS_FUNC_IN_PORT(pdev, i)
1474        {
1475            LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[i].config),&mf_cfg1);
1476            LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[i].e1hov_tag), &ovlan1);
1477            /* iterate from the next function in the port till max func */
1478            for (j = i + 2; j < E1H_FUNC_MAX; j += 2)
1479            {
1480                LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[j].config),&mf_cfg2);
1481                LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[j].e1hov_tag), &ovlan2);
1482                if (!GET_FLAGS(mf_cfg1, FUNC_MF_CFG_FUNC_HIDE) && VALID_OVLAN(ovlan1) &&
1483                    !GET_FLAGS(mf_cfg2, FUNC_MF_CFG_FUNC_HIDE) && VALID_OVLAN(ovlan2) &&
1484                    (ovlan1 == ovlan2) )
1485                {
1486                    lm_status = LM_STATUS_FAILURE;
1487                    DbgBreakIf(1);
1488                    goto _end;
1489                }
1490            }
1491        }
1492        // Check if DCC is active (Debugging only)
1493        LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, port_mf_config[PATH_ID(pdev)][PORT_ID(pdev)].dynamic_cfg),&dynamic_cfg );
1494        if( PORT_MF_CFG_E1HOV_TAG_DEFAULT == ( dynamic_cfg & PORT_MF_CFG_E1HOV_TAG_MASK ) )
1495        {
1496            pdev->hw_info.is_dcc_active = FALSE;
1497        }
1498        else
1499        {
1500            pdev->hw_info.is_dcc_active = TRUE;
1501        }
1502    } // MULTI_FUNCTION_SD
1503_end:
1504    return lm_status;
1505}
1506
1507void lm_cmng_get_shmem_info( lm_device_t* pdev )
1508{
1509    u32_t                  val     = 0;
1510    u8_t                   i       = 0;
1511    u8_t                   vnic    = 0;
1512    lm_hardware_mf_info_t *mf_info = &pdev->hw_info.mf_info;;
1513
1514    if( !IS_MF_MODE_CAPABLE(pdev) )
1515    {
1516        DbgBreakIf(1) ;
1517        return;
1518    }
1519
1520    LM_FOREACH_ABS_FUNC_IN_PORT(pdev, i)
1521    {
1522        LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[i].config),&val);
1523        /* get min/max bw */
1524        mf_info->min_bw[vnic] = (GET_FLAGS(val, FUNC_MF_CFG_MIN_BW_MASK) >> FUNC_MF_CFG_MIN_BW_SHIFT);
1525        mf_info->max_bw[vnic] = (GET_FLAGS(val, FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT);
1526        vnic++;
1527    }
1528}
1529
1530/**lm_get_vnics_per_port
1531 * Get the value of vnics_per_port according to the MF mode and
1532 * port mode.
1533 *
1534 * Note: This function assumes that multi_vnics_mode and
1535 * chip_port_mode are initialized in hw_info.
1536 *
1537 * @param pdev
1538 *
1539 * @return u8_t the value of vnics_per_port for this pdev's port
1540 *         mode and MF mode. This value does not consider hidden
1541 *         PFs.
1542 */
1543static u8_t lm_get_vnics_per_port(lm_device_t* pdev)
1544{
1545    if (pdev->hw_info.mf_info.multi_vnics_mode)
1546    {
1547        return LM_PFS_PER_PORT(pdev);
1548    }
1549    else
1550    {
1551        return 1;
1552    }
1553}
1554
1555/* Get shmem multi function config info for switch dependent mode */
1556static lm_status_t lm_get_shmem_mf_cfg_info_sd(lm_device_t *pdev)
1557{
1558    lm_hardware_mf_info_t *mf_info = &pdev->hw_info.mf_info;
1559    u32_t                  val     = 0;
1560
1561    /* get ovlan if we're in switch-dependent mode... */
1562    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].e1hov_tag),&val);
1563    mf_info->ext_id = (u16_t)val;
1564
1565    mf_info->multi_vnics_mode = 1;
1566    if(!VALID_OVLAN(OVLAN(pdev)))
1567    {
1568        /* Unexpected at this time */
1569        DbgMessage(pdev, FATAL, "Invalid mf mode configuration: VNICID=%d, Function is enumerated, ovlan (%d) is invalid\n",
1570                   VNIC_ID(pdev), OVLAN(pdev));
1571#ifdef EDIAG
1572     	// Allow OVLAN 0xFFFF in ediag UFP mode
1573     	if (mf_info->sd_mode != SD_UFP_MODE)
1574     	{
1575          	return LM_STATUS_FAILURE;
1576     	}
1577#else
1578        return LM_STATUS_FAILURE;
1579#endif
1580    }
1581
1582    /* Get capabilities */
1583    if (GET_FLAGS(mf_info->func_mf_cfg, FUNC_MF_CFG_PROTOCOL_MASK) == FUNC_MF_CFG_PROTOCOL_ISCSI)
1584    {
1585        pdev->params.mf_proto_support_flags |= LM_PROTO_SUPPORT_ISCSI;
1586    }
1587    else if (GET_FLAGS(mf_info->func_mf_cfg, FUNC_MF_CFG_PROTOCOL_MASK) == FUNC_MF_CFG_PROTOCOL_FCOE)
1588    {
1589        pdev->params.mf_proto_support_flags |= LM_PROTO_SUPPORT_FCOE;
1590    }
1591    else
1592    {
1593        pdev->params.mf_proto_support_flags |= LM_PROTO_SUPPORT_ETHERNET;
1594    }
1595
1596    mf_info->vnics_per_port = lm_get_vnics_per_port(pdev);
1597
1598    return LM_STATUS_SUCCESS;
1599}
1600
1601
1602/* Get shmem multi function config info for switch dependent mode */
1603static lm_status_t lm_get_shmem_mf_cfg_info_sd_bd(lm_device_t *pdev)
1604{
1605    lm_status_t lm_status = lm_get_shmem_mf_cfg_info_sd(pdev);
1606
1607    return lm_status;
1608}
1609
1610
1611/* Get shmem multi function config info for switch dependent mode */
1612static lm_status_t lm_get_shmem_mf_cfg_info_sd_ufp(lm_device_t *pdev)
1613{
1614    lm_status_t lm_status = lm_get_shmem_mf_cfg_info_sd(pdev);
1615
1616    return lm_status;
1617}
1618
1619static void _copy_mac_upper_lower_to_arr(IN u32_t mac_upper, IN u32_t mac_lower, OUT u8_t* mac_addr)
1620{
1621    if(mac_addr)
1622    {
1623        mac_addr[0] = (u8_t) (mac_upper >> 8);
1624        mac_addr[1] = (u8_t) mac_upper;
1625        mac_addr[2] = (u8_t) (mac_lower >> 24);
1626        mac_addr[3] = (u8_t) (mac_lower >> 16);
1627        mac_addr[4] = (u8_t) (mac_lower >> 8);
1628        mac_addr[5] = (u8_t) mac_lower;
1629    }
1630}
1631
1632static void lm_get_shmem_ext_mac_addresses(lm_device_t *pdev)
1633{
1634    u32_t      mac_upper   = 0;
1635    u32_t      mac_lower   = 0;
1636    u32_t      offset      = 0;
1637    const u8_t abs_func_id = ABS_FUNC_ID(pdev);
1638
1639    /* We have a different mac address per iscsi / fcoe - we'll set it from extended multi function info, but only if it's valid, otherwise
1640     * we'll leave the same mac as for L2
1641     */
1642    offset = OFFSETOF(mf_cfg_t, func_ext_config[abs_func_id].iscsi_mac_addr_upper);
1643    LM_MFCFG_READ(pdev, offset, &mac_upper);
1644
1645    offset = OFFSETOF(mf_cfg_t, func_ext_config[abs_func_id].iscsi_mac_addr_lower);
1646    LM_MFCFG_READ(pdev, offset, &mac_lower);
1647
1648    _copy_mac_upper_lower_to_arr(mac_upper, mac_lower, pdev->hw_info.iscsi_mac_addr);
1649
1650    offset = OFFSETOF(mf_cfg_t, func_ext_config[abs_func_id].fcoe_mac_addr_upper);
1651    LM_MFCFG_READ(pdev, offset, &mac_upper);
1652
1653    offset = OFFSETOF(mf_cfg_t, func_ext_config[abs_func_id].fcoe_mac_addr_lower);
1654    LM_MFCFG_READ(pdev, offset, &mac_lower);
1655
1656    _copy_mac_upper_lower_to_arr(mac_upper, mac_lower, pdev->hw_info.fcoe_mac_addr);
1657
1658    offset = OFFSETOF(mf_cfg_t, func_ext_config[abs_func_id].fcoe_wwn_port_name_upper);
1659    LM_MFCFG_READ(pdev, offset, &mac_upper);
1660
1661    offset = OFFSETOF(mf_cfg_t, func_ext_config[abs_func_id].fcoe_wwn_port_name_lower);
1662    LM_MFCFG_READ(pdev, offset, &mac_lower);
1663
1664    _copy_mac_upper_lower_to_arr(mac_upper, mac_lower, &(pdev->hw_info.fcoe_wwn_port_name[2]));
1665    pdev->hw_info.fcoe_wwn_port_name[0] = (u8_t) (mac_upper >> 24);
1666    pdev->hw_info.fcoe_wwn_port_name[1] = (u8_t) (mac_upper >> 16);
1667
1668    offset = OFFSETOF(mf_cfg_t, func_ext_config[abs_func_id].fcoe_wwn_node_name_upper);
1669    LM_MFCFG_READ(pdev, offset, &mac_upper);
1670
1671    offset = OFFSETOF(mf_cfg_t, func_ext_config[abs_func_id].fcoe_wwn_node_name_lower);
1672    LM_MFCFG_READ(pdev, offset, &mac_lower);
1673
1674    _copy_mac_upper_lower_to_arr(mac_upper, mac_lower, &(pdev->hw_info.fcoe_wwn_node_name[2]));
1675    pdev->hw_info.fcoe_wwn_node_name[0] = (u8_t) (mac_upper >> 24);
1676    pdev->hw_info.fcoe_wwn_node_name[1] = (u8_t) (mac_upper >> 16);
1677}
1678
1679static u32_t
1680lm_get_shmem_ext_proto_support_flags(lm_device_t *pdev)
1681{
1682    u32_t   func_ext_cfg        = 0;
1683    u32_t   proto_support_flags = 0;
1684
1685    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_ext_config[ABS_FUNC_ID(pdev)].func_cfg),&func_ext_cfg);
1686
1687    if (GET_FLAGS(func_ext_cfg, MACP_FUNC_CFG_FLAGS_ENABLED ))
1688    {
1689        if (GET_FLAGS(func_ext_cfg, MACP_FUNC_CFG_FLAGS_ETHERNET))
1690        {
1691            proto_support_flags |= LM_PROTO_SUPPORT_ETHERNET;
1692        }
1693        if (GET_FLAGS(func_ext_cfg, MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD))
1694        {
1695            proto_support_flags |= LM_PROTO_SUPPORT_ISCSI;
1696        }
1697        if (GET_FLAGS(func_ext_cfg, MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD))
1698        {
1699            proto_support_flags |= LM_PROTO_SUPPORT_FCOE;
1700        }
1701    }
1702
1703    return proto_support_flags;
1704}
1705
1706/* Get shmem multi function config info for switch independent mode */
1707static lm_status_t lm_get_shmem_mf_cfg_info_si(lm_device_t *pdev)
1708{
1709    lm_hardware_mf_info_t *mf_info = &pdev->hw_info.mf_info;
1710    u32_t val       = 0;
1711
1712    /* No outer-vlan... we're in switch-independent mode, so if the mac is valid - assume multi-function */
1713    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_ext_config[ABS_FUNC_ID(pdev)].func_cfg),&val);
1714    val = val & MACP_FUNC_CFG_FLAGS_MASK;
1715    mf_info->multi_vnics_mode = (val != 0);
1716    mf_info->path_has_ovlan = FALSE;
1717
1718    pdev->params.mf_proto_support_flags = lm_get_shmem_ext_proto_support_flags(pdev);
1719
1720    mf_info->vnics_per_port = lm_get_vnics_per_port(pdev);
1721
1722    return LM_STATUS_SUCCESS;
1723
1724}
1725
1726lm_status_t lm_get_shmem_mf_cfg_info_niv(lm_device_t *pdev)
1727{
1728    lm_hardware_mf_info_t   *mf_info     = &pdev->hw_info.mf_info;
1729    u32_t                   func_config  = 0;
1730    u32_t                   niv_config   = 0;
1731    u32_t                   e1hov_tag    = 0;
1732
1733    mf_info->multi_vnics_mode = TRUE;
1734
1735    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].e1hov_tag),&e1hov_tag);
1736    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].config), &func_config);
1737    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].afex_config), &niv_config);
1738
1739    mf_info->ext_id = (u16_t)(GET_FLAGS(e1hov_tag, FUNC_MF_CFG_E1HOV_TAG_MASK)>>FUNC_MF_CFG_E1HOV_TAG_SHIFT);
1740    mf_info->default_vlan = (u16_t)(GET_FLAGS(e1hov_tag, FUNC_MF_CFG_AFEX_VLAN_MASK)>>FUNC_MF_CFG_AFEX_VLAN_SHIFT);
1741
1742    mf_info->niv_allowed_priorities = (u8_t)(GET_FLAGS(niv_config, FUNC_MF_CFG_AFEX_COS_FILTER_MASK)>>FUNC_MF_CFG_AFEX_COS_FILTER_SHIFT);
1743    mf_info->niv_default_cos = (u8_t)(GET_FLAGS(func_config, FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK)>>FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT);
1744    mf_info->afex_vlan_mode = GET_FLAGS(niv_config, FUNC_MF_CFG_AFEX_VLAN_MODE_MASK)>>FUNC_MF_CFG_AFEX_VLAN_MODE_SHIFT;
1745    mf_info->niv_mba_enabled = GET_FLAGS(niv_config, FUNC_MF_CFG_AFEX_MBA_ENABLED_MASK)>>FUNC_MF_CFG_AFEX_MBA_ENABLED_SHIFT;
1746
1747
1748    pdev->params.mf_proto_support_flags = lm_get_shmem_ext_proto_support_flags(pdev);
1749
1750    mf_info->vnics_per_port = lm_get_vnics_per_port(pdev);
1751
1752    return LM_STATUS_SUCCESS;
1753}
1754
1755static lm_status_t lm_shmem_set_default(lm_device_t *pdev)
1756{
1757    lm_hardware_mf_info_t *mf_info   = &pdev->hw_info.mf_info;
1758    u8_t i;
1759
1760    /* set defaults: */
1761    mf_info->multi_vnics_mode = 0;
1762    mf_info->vnics_per_port   = 1;
1763    mf_info->ext_id           = 0xffff; /* invalid ovlan */ /* TBD - E1H: - what is the right value for Cisco? */
1764
1765    ASSERT_STATIC( ARRSIZE(mf_info->min_bw) == ARRSIZE(mf_info->max_bw) )
1766
1767    for (i = 0; i < ARRSIZE(mf_info->min_bw); i++)
1768    {
1769        mf_info->min_bw[i] = 0;
1770        mf_info->max_bw[i] = 200;
1771    }
1772    pdev->hw_info.shmem_base          = 0;
1773    pdev->hw_info.max_port_toe_conn   = MAX_CONNECTIONS_TOE;
1774    pdev->hw_info.max_port_rdma_conn  = MAX_CONNECTIONS_RDMA;
1775    pdev->hw_info.max_port_iscsi_conn = MAX_CONNECTIONS_ISCSI;
1776    pdev->hw_info.max_port_fcoe_conn  = MAX_CONNECTIONS_FCOE;
1777    pdev->hw_info.max_port_conns      = MAX_CONNECTIONS;
1778    pdev->hw_info.max_common_conns    = MAX_CONNECTIONS;
1779
1780    return LM_STATUS_SUCCESS;
1781}
1782
1783static u32_t lm_get_shmem_base_addr(lm_device_t *pdev)
1784{
1785    u32_t val            = 0;
1786    u32_t min_shmem_addr = 0;
1787    u32_t max_shmem_addr = 0;
1788
1789    val = REG_RD(pdev,MISC_REG_SHARED_MEM_ADDR);
1790    if (CHIP_IS_E1(pdev))
1791    {
1792        min_shmem_addr = 0xa0000;
1793        max_shmem_addr = 0xb0000;
1794    }
1795    else if (CHIP_IS_E1H(pdev))
1796    {
1797       min_shmem_addr = 0xa0000;
1798       max_shmem_addr = 0xc0000;
1799    }
1800    else if (CHIP_IS_E2E3(pdev))
1801    {
1802        min_shmem_addr = 0x3a0000;
1803        max_shmem_addr = 0x3c8000;
1804    }
1805    else
1806    {
1807        u32 pcicfg_chip;
1808        mm_read_pci(pdev, 0, &pcicfg_chip);
1809        DbgMessage(pdev, FATAL , "Unknown chip 0x%x, pcicfg[0]=0x%x, GRC[0x2000]=0x%x\n",
1810                    CHIP_NUM(pdev), pcicfg_chip, REG_RD(pdev, 0x2000));
1811        DbgBreakMsg("Unknown chip version");
1812    }
1813
1814    if (val < min_shmem_addr || val >= max_shmem_addr)
1815    {
1816        /* Invalid shmem base address return '0' */
1817        val = 0;
1818    }
1819
1820    return val;
1821}
1822
1823/**
1824 * @Description
1825 *     This function is called when MCP is not detected. It
1826 *     initializes lmdevice parameters that are required for
1827 *     functional running with default values or values read
1828 *     from vnic_cfg.tcl script.
1829 *
1830 * @param pdev
1831 *
1832 * @return lm_status_t
1833 */
1834static lm_status_t lm_get_shmem_info_no_mcp_bypass(lm_device_t *pdev)
1835{
1836    lm_hardware_mf_info_t *mf_info = &pdev->hw_info.mf_info;
1837    lm_status_t lm_status          = LM_STATUS_SUCCESS;
1838    u32_t val                      = 0;
1839
1840
1841    DbgMessage(pdev, WARN, "MCP Down Detected\n");
1842#ifndef _VBD_CMD_
1843    val = REG_RD(pdev,MISC_REG_SHARED_MEM_ADDR);
1844    DbgMessage(pdev, FATAL, "FW ShMem addr: 0x%x\n", val);
1845#endif // _VBD_CMD_
1846
1847    pdev->hw_info.mcp_detected = 0;
1848    /* should have a magic number written if configuration was set otherwise, use default above */
1849    LM_SHMEM_READ(pdev, NO_MCP_WA_CFG_SET_ADDR, &val);
1850    if (val == NO_MCP_WA_CFG_SET_MAGIC)
1851    {
1852        LM_SHMEM_READ(pdev, NO_MCP_WA_FORCE_5710, &val);
1853        LM_SHMEM_READ(pdev, NO_MCP_WA_MULTI_VNIC_MODE, &val);
1854        mf_info->multi_vnics_mode = (u8_t)val;
1855        if (mf_info->multi_vnics_mode)
1856        {
1857            LM_SHMEM_READ(pdev, NO_MCP_WA_OVLAN(ABS_FUNC_ID(pdev)), &val);
1858            mf_info->ext_id = (u16_t)val;
1859
1860            mf_info->multi_vnics_mode = VALID_OVLAN(mf_info->ext_id)? 1 : 0;
1861            mf_info->path_has_ovlan = mf_info->multi_vnics_mode;
1862
1863            /* decide on path multi vnics mode - incase we're not in mf mode...and in 4-port-mode good enough to check vnic-0 of the other port, on the same path */
1864            if ((CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_4) &&  !mf_info->multi_vnics_mode)
1865            {
1866                u8_t other_port = !PORT_ID(pdev);
1867                u8_t abs_func_on_other_port = PATH_ID(pdev) + 2*other_port;
1868                LM_SHMEM_READ(pdev, NO_MCP_WA_OVLAN(abs_func_on_other_port), &val);
1869
1870                mf_info->path_has_ovlan = VALID_OVLAN((u16_t)val) ? 1 : 0;
1871            }
1872
1873            /* For simplicity, we leave vnics_per_port to be 2, for resource splitting issues... */
1874            if (mf_info->path_has_ovlan)
1875            {
1876                if (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_4)
1877                {
1878                    mf_info->vnics_per_port = 2;
1879                }
1880                else
1881                {
1882                    mf_info->vnics_per_port = 4;
1883                }
1884            }
1885
1886            /* If we're multi-vnic, we'll set a default mf_mode of switch-dependent, this could be overriden
1887             * later on by registry */
1888            mf_info->mf_mode = MULTI_FUNCTION_SD;
1889
1890        }
1891        lm_status = lm_get_shmem_license_info(pdev);
1892        if (lm_status != LM_STATUS_SUCCESS)
1893        {
1894            return lm_status;
1895        }
1896    }
1897    /* sanity checks on vnic params */
1898    if (mf_info->multi_vnics_mode)
1899    {
1900        if (!VALID_OVLAN(mf_info->ext_id))
1901        {
1902            DbgMessage(pdev, FATAL, "Invalid ovlan (0x%x) configured for Func %d. Can't load the function.\n",
1903                        mf_info->ext_id, ABS_FUNC_ID(pdev));
1904            lm_status = LM_STATUS_FAILURE;
1905        }
1906    }
1907    if ((mf_info->vnics_per_port - 1 < VNIC_ID(pdev)) || ( !mf_info->multi_vnics_mode && (VNIC_ID(pdev) > 0)))
1908    {
1909        DbgMessage(pdev, FATAL, "Invalid vnics_per_port (%d) configured for Func %d. Can't load the function.\n",
1910                    mf_info->vnics_per_port, ABS_FUNC_ID(pdev));
1911        lm_status = LM_STATUS_FAILURE;
1912    }
1913    return lm_status;
1914}
1915
1916
1917
1918static lm_status_t lm_get_shmem_shared_hw_config(lm_device_t *pdev)
1919{
1920    u32_t val = 0;
1921    u8_t  i   = 0;
1922
1923    /* Get the hw config words. */
1924    LM_SHMEM_READ(pdev, OFFSETOF(shmem_region_t, dev_info.shared_hw_config.config),&val);
1925    pdev->hw_info.nvm_hw_config = val;
1926    pdev->params.link.hw_led_mode = ((pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_LED_MODE_MASK) >> SHARED_HW_CFG_LED_MODE_SHIFT);
1927    DbgMessage(pdev, INFORMi, "nvm_hw_config %d\n",val);
1928
1929    LM_SHMEM_READ(pdev,
1930        OFFSETOF(shmem_region_t, dev_info.shared_hw_config.config2),&val);
1931    pdev->hw_info.nvm_hw_config2 = val;
1932    DbgMessage(pdev, INFORMi, "nvm_hw_configs %d\n",val);
1933
1934    //board_sn;
1935    LM_SHMEM_READ(pdev,
1936        OFFSETOF(shmem_region_t, dev_info.shared_hw_config.part_num),&val);
1937    pdev->hw_info.board_num[0] = (u8_t) val;
1938    pdev->hw_info.board_num[1] = (u8_t) (val >> 8);
1939    pdev->hw_info.board_num[2] = (u8_t) (val >> 16);
1940    pdev->hw_info.board_num[3] = (u8_t) (val >> 24);
1941
1942    LM_SHMEM_READ(pdev,
1943        OFFSETOF(shmem_region_t, dev_info.shared_hw_config.part_num)+4,&val);
1944    pdev->hw_info.board_num[4] = (u8_t) val;
1945    pdev->hw_info.board_num[5] = (u8_t) (val >> 8);
1946    pdev->hw_info.board_num[6] = (u8_t) (val >> 16);
1947    pdev->hw_info.board_num[7] = (u8_t) (val >> 24);
1948
1949    LM_SHMEM_READ(pdev,
1950        OFFSETOF(shmem_region_t, dev_info.shared_hw_config.part_num)+8,&val);
1951    pdev->hw_info.board_num[8] = (u8_t) val;
1952    pdev->hw_info.board_num[9] = (u8_t) (val >> 8);
1953    pdev->hw_info.board_num[10] =(u8_t) (val >> 16);
1954    pdev->hw_info.board_num[11] =(u8_t) (val >> 24);
1955
1956    LM_SHMEM_READ(pdev,
1957        OFFSETOF(shmem_region_t, dev_info.shared_hw_config.part_num)+12,&val);
1958    pdev->hw_info.board_num[12] = (u8_t) val;
1959    pdev->hw_info.board_num[13] = (u8_t) (val >> 8);
1960    pdev->hw_info.board_num[14] = (u8_t) (val >> 16);
1961    pdev->hw_info.board_num[15] = (u8_t) (val >> 24);
1962    DbgMessage(pdev, INFORMi, "board_sn: ");
1963    for (i = 0 ; i < 16 ; i++ )
1964    {
1965        DbgMessage(pdev, INFORMi, "%02x",pdev->hw_info.board_num[i]);
1966    }
1967    DbgMessage(pdev, INFORMi, "\n");
1968
1969    /* Get the override preemphasis flag */
1970    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.shared_feature_config.config),&val);
1971    if GET_FLAGS(val, SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED)
1972    {
1973        SET_FLAGS( pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED);
1974    }
1975    else
1976    {
1977        RESET_FLAGS(pdev->params.link.feature_config_flags,ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED);
1978    }
1979#ifdef EDIAG
1980    /* Diag doesn't support remote fault detection */
1981    SET_FLAGS( pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET);
1982    /* Only Diag supports IEEE PHY testing */
1983    SET_FLAGS( pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_IEEE_PHY_TEST);
1984#endif
1985    return LM_STATUS_SUCCESS;
1986}
1987
1988static u32_t lm_get_shmem_mf_cfg_base(lm_device_t *pdev)
1989{
1990    u32_t shmem2_size;
1991    u32_t offset;
1992    u32_t mf_cfg_offset_value;
1993
1994    offset = pdev->hw_info.shmem_base + OFFSETOF(shmem_region_t, func_mb) + E1H_FUNC_MAX * sizeof(struct drv_func_mb);
1995    if (pdev->hw_info.shmem_base2 != 0)
1996    {
1997        LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t,size), &shmem2_size);
1998        if (shmem2_size > OFFSETOF(shmem2_region_t,mf_cfg_addr))
1999        {
2000            LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t,mf_cfg_addr), &mf_cfg_offset_value);
2001            if (SHMEM_MF_CFG_ADDR_NONE != mf_cfg_offset_value)
2002            {
2003                offset = mf_cfg_offset_value;
2004            }
2005        }
2006    }
2007    return offset;
2008}
2009
2010static lm_status_t lm_get_shmem_port_hw_config(lm_device_t *pdev)
2011{
2012    u32_t val;
2013    const u8_t port = PORT_ID(pdev);
2014
2015    /* mba features*/
2016    LM_SHMEM_READ(pdev,
2017        OFFSETOF(shmem_region_t,dev_info.port_feature_config[port].mba_config),
2018        &val);
2019    pdev->hw_info.mba_features = (val & PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK);
2020    DbgMessage(pdev, INFORMi, "mba_features %d\n",pdev->hw_info.mba_features);
2021    /* mba_vlan_cfg */
2022    LM_SHMEM_READ(pdev,
2023        OFFSETOF(shmem_region_t,dev_info.port_feature_config[port].mba_vlan_cfg),
2024        &val);
2025    pdev->hw_info.mba_vlan_cfg = val ;
2026    DbgMessage(pdev, INFORMi, "mba_vlan_cfg 0x%x\n",pdev->hw_info.mba_vlan_cfg);
2027
2028    // port_feature_config bits
2029    LM_SHMEM_READ(pdev,
2030        OFFSETOF(shmem_region_t,dev_info.port_feature_config[port].config),
2031        &val);
2032    pdev->hw_info.port_feature_config = val;
2033    DbgMessage(pdev, INFORMi, "port_feature_config 0x%x\n",pdev->hw_info.port_feature_config);
2034
2035#ifndef DOS
2036    /* AutogrEEEn settings */
2037    if(val & PORT_FEAT_CFG_AUTOGREEEN_ENABLED) {
2038        SET_FLAGS( pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_AUTOGREEEN_ENABLED);
2039    } else {
2040        RESET_FLAGS( pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_AUTOGREEEN_ENABLED);
2041    }
2042#endif
2043    /* clc params*/
2044    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_hw_config[port].speed_capability_mask),&val);
2045    pdev->params.link.speed_cap_mask[0] = val & PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK;
2046    DbgMessage(pdev, INFORMi, "speed_cap_mask1 %d\n",val);
2047
2048    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_hw_config[port].speed_capability_mask2),&val);
2049    pdev->params.link.speed_cap_mask[1] = val & PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK;
2050    DbgMessage(pdev, INFORMi, "speed_cap_mask2 %d\n",val);
2051
2052    /* Get lane swap*/
2053    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_hw_config[port].lane_config),&val);
2054    pdev->params.link.lane_config = val;
2055    DbgMessage(pdev, INFORMi, "lane_config %d\n",val);
2056
2057    /*link config  */
2058    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_feature_config[port].link_config),&val);
2059    pdev->hw_info.link_config[ELINK_INT_PHY] = val;
2060    pdev->params.link.switch_cfg = val & PORT_FEATURE_CONNECTED_SWITCH_MASK;
2061    DbgMessage(pdev, INFORMi, "link config %d\n",val);
2062
2063    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_feature_config[port].link_config2),&val);
2064    pdev->hw_info.link_config[ELINK_EXT_PHY1] = val;
2065
2066    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_hw_config[port].multi_phy_config),&val);
2067    /* set the initial value to the link params */
2068    pdev->params.link.multi_phy_config = val;
2069    /* save the initial value if we'll want to restore it later */
2070    pdev->hw_info.multi_phy_config = val;
2071    /* check if 10g KR is blocked on this session */
2072    pdev->hw_info.no_10g_kr = FALSE ;
2073
2074    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_hw_config[port].default_cfg),&val);
2075    pdev->hw_info.phy_force_kr_enabler = (val & PORT_HW_CFG_FORCE_KR_ENABLER_MASK) ;
2076
2077    /* If the force KR enabler is on, 10G/20G should have been enabled in the
2078     * nvram as well. If 10G/20G capbility is not set, it means that the MFW
2079     * disabled it and we should set the no_10g_kr flag */
2080    if(( PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED != pdev->hw_info.phy_force_kr_enabler ) &&
2081        ( FALSE == ( pdev->params.link.speed_cap_mask[0] & (PORT_HW_CFG_SPEED_CAPABILITY_D0_10G | PORT_HW_CFG_SPEED_CAPABILITY_D0_20G))) )
2082    {
2083        pdev->hw_info.no_10g_kr = TRUE ;
2084    }
2085
2086    /* read EEE mode from shmem (original source is NVRAM) */
2087    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_feature_config[port].eee_power_mode),&val);
2088    pdev->params.link.eee_mode = val & PORT_FEAT_CFG_EEE_POWER_MODE_MASK;
2089    DbgMessage(pdev, INFORMi, "eee_power_mode 0x%x\n", pdev->params.link.eee_mode);
2090
2091    if ((pdev->params.link.eee_mode & PORT_FEAT_CFG_EEE_POWER_MODE_MASK) != PORT_FEAT_CFG_EEE_POWER_MODE_DISABLED)
2092    {
2093        SET_FLAGS(pdev->params.link.eee_mode,
2094                              ELINK_EEE_MODE_ENABLE_LPI |
2095                              ELINK_EEE_MODE_ADV_LPI);
2096    }
2097
2098    return LM_STATUS_SUCCESS;
2099}
2100
2101/* Check if other path is in multi_function_mode */
2102static void lm_set_path_has_ovlan(lm_device_t *pdev)
2103{
2104    lm_hardware_mf_info_t *mf_info = &pdev->hw_info.mf_info;
2105    u32_t                  val     = 0;
2106
2107    mf_info->path_has_ovlan = FALSE;
2108
2109    if (mf_info->mf_mode == MULTI_FUNCTION_SD)
2110    {
2111        mf_info->path_has_ovlan = TRUE;
2112    }
2113    else if (mf_info->mf_mode == SINGLE_FUNCTION)
2114    {
2115        /* decide on path multi vnics mode - incase we're not in mf mode...and in 4-port-mode good enough to check vnic-0 of the other port, on the same path */
2116        if (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_4)
2117        {
2118            u8_t other_port = !PORT_ID(pdev);
2119            u8_t abs_func_on_other_port = PATH_ID(pdev) + 2*other_port;
2120            LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[abs_func_on_other_port].e1hov_tag),&val);
2121
2122            mf_info->path_has_ovlan = VALID_OVLAN((u16_t)val) ? 1 : 0;
2123        }
2124    }
2125}
2126
2127/**
2128 * @Description
2129 *    Initializes mf mode and data, checks that mf info is valid
2130 *  by checking that MAC address must be legal (check only upper
2131 *    bytes) for  Switch-Independent mode;
2132 *    OVLAN must be legal for Switch-Dependent mode
2133 *
2134 * @param pdev
2135 *
2136 * @return lm_status_t
2137 */
2138lm_status_t lm_get_shmem_mf_cfg_info(lm_device_t *pdev)
2139{
2140    lm_hardware_mf_info_t *mf_info = &pdev->hw_info.mf_info;
2141    u32_t val                      = 0;
2142    u32_t val2                     = 0;
2143    u32_t mac_upper                = 0;
2144    lm_status_t status = LM_STATUS_SUCCESS;
2145
2146    /* Set some mf_info defaults */
2147    mf_info->vnics_per_port   = 1;
2148    mf_info->multi_vnics_mode = FALSE;
2149    mf_info->path_has_ovlan   = FALSE;
2150    mf_info->mf_mode          = SINGLE_FUNCTION;
2151    pdev->params.mf_proto_support_flags = 0;
2152
2153
2154    /* Get the multi-function-mode value (switch dependent / independent / single-function )  */
2155    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.shared_feature_config.config),&val);
2156    val &= SHARED_FEAT_CFG_FORCE_SF_MODE_MASK;
2157
2158    switch (val)
2159    {
2160    case SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT:
2161        LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].mac_upper),&mac_upper);
2162        /* check for legal mac (upper bytes)*/
2163        if (mac_upper != FUNC_MF_CFG_UPPERMAC_DEFAULT)
2164        {
2165            mf_info->mf_mode = MULTI_FUNCTION_SI;
2166        }
2167        else
2168        {
2169            DbgMessage(pdev, WARNi, "Illegal configuration for switch independent mode\n");
2170        }
2171        DbgBreakIf(CHIP_IS_E1x(pdev));
2172        break;
2173    case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED:
2174    case SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4:
2175        /* get OV configuration */
2176        LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].e1hov_tag),&val);
2177        val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
2178
2179        if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
2180        {
2181            mf_info->mf_mode = MULTI_FUNCTION_SD;
2182            mf_info->sd_mode = SD_REGULAR_MODE;
2183        }
2184        else
2185        {
2186            DbgMessage(pdev, WARNi, "Illegal configuration for switch dependent mode\n");
2187        }
2188        break;
2189    case SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF:
2190        /* We're not in multi-function mode - return with vnics_per_port=1 & multi_vnics_mode = FALSE*/
2191        return LM_STATUS_SUCCESS;
2192    case SHARED_FEAT_CFG_FORCE_SF_MODE_AFEX_MODE:
2193        /* mark mf mode as NIV if MCP version includes NPAR-SD support
2194           and the MAC address is valid.
2195         */
2196        LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].mac_upper),&mac_upper);
2197        if ((LM_SHMEM2_HAS(pdev, afex_driver_support)) &&
2198            (mac_upper != FUNC_MF_CFG_UPPERMAC_DEFAULT) )
2199        {
2200            mf_info->mf_mode = MULTI_FUNCTION_AFEX;
2201        }
2202        else
2203        {
2204            DbgMessage(pdev, WARNi, "Illegal configuration for NPAR-SD mode\n");
2205        }
2206        DbgBreakIf(CHIP_IS_E1x(pdev));
2207        break;
2208    case SHARED_FEAT_CFG_FORCE_SF_MODE_BD_MODE:
2209        mf_info->mf_mode = MULTI_FUNCTION_SD;
2210        mf_info->sd_mode = SD_BD_MODE;
2211        DbgMessage(pdev, WARN, "lm_get_shmem_info: SF_MODE_BD_MODE is detected.\n");
2212        break;
2213
2214    case SHARED_FEAT_CFG_FORCE_SF_MODE_UFP_MODE:
2215        mf_info->mf_mode = MULTI_FUNCTION_SD;
2216        mf_info->sd_mode = SD_UFP_MODE;
2217        DbgMessage(pdev, WARN, "lm_get_shmem_info: SF_MODE_UFP_MODE is detected.\n");
2218        break;
2219
2220    case SHARED_FEAT_CFG_FORCE_SF_MODE_EXTENDED_MODE:
2221        /* Get extended mf mode value */
2222        LM_SHMEM_READ(pdev, OFFSETOF(shmem_region_t, dev_info.shared_hw_config.config_3),&val);
2223        val2 &= SHARED_HW_CFG_EXTENDED_MF_MODE_MASK;
2224        switch (val2)
2225        {
2226        case SHARED_HW_CFG_EXTENDED_MF_MODE_NPAR1_DOT_5:
2227            mf_info->mf_mode = MULTI_FUNCTION_SI;
2228            break;
2229
2230        default:
2231            DbgBreakMsg(" Unknown extended mf mode\n");
2232            return LM_STATUS_FAILURE;
2233        }
2234        break;
2235
2236    default:
2237        DbgBreakMsg(" Unknown mf mode\n");
2238        return LM_STATUS_FAILURE;
2239    }
2240
2241    /* Set path mf_mode (which could be different than function mf_mode)  */
2242    lm_set_path_has_ovlan(pdev);
2243
2244    /* Invalid Multi function configuration: */
2245    if (mf_info->mf_mode == SINGLE_FUNCTION)
2246    {
2247        if (VNIC_ID(pdev) >= 1)
2248        {
2249            return LM_STATUS_FAILURE;
2250        }
2251        return LM_STATUS_SUCCESS;
2252    }
2253
2254    /* Get the multi-function configuration */
2255    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].config),&val);
2256    mf_info->func_mf_cfg = val;
2257
2258    switch(mf_info->mf_mode)
2259    {
2260        case MULTI_FUNCTION_SD:
2261        {
2262            switch (mf_info->sd_mode)
2263            {
2264                case SD_REGULAR_MODE:
2265                    status = lm_get_shmem_mf_cfg_info_sd(pdev);
2266                    break;
2267                case SD_UFP_MODE:
2268                    status = lm_get_shmem_mf_cfg_info_sd_ufp(pdev);
2269                    break;
2270                case SD_BD_MODE:
2271                    status = lm_get_shmem_mf_cfg_info_sd_bd(pdev);
2272                    break;
2273                default:
2274                    DbgBreak();
2275            }
2276
2277            if(status != LM_STATUS_SUCCESS)
2278                return status;
2279        }
2280        break;
2281        case MULTI_FUNCTION_SI:
2282        {
2283            lm_get_shmem_mf_cfg_info_si(pdev);
2284        }
2285        break;
2286        case MULTI_FUNCTION_AFEX:
2287        {
2288            lm_get_shmem_mf_cfg_info_niv(pdev);
2289        }
2290        break;
2291        default:
2292        {
2293            DbgBreakIfAll(TRUE);
2294            return LM_STATUS_FAILURE;
2295        }
2296    }
2297
2298    lm_cmng_get_shmem_info(pdev);
2299
2300    return lm_check_valid_mf_cfg(pdev);
2301}
2302
2303static void lm_fcoe_set_default_wwns(lm_device_t *pdev)
2304{
2305    /* create default wwns from fcoe mac adress */
2306    mm_memcpy(&(pdev->hw_info.fcoe_wwn_port_name[2]), pdev->hw_info.fcoe_mac_addr, 6);
2307    pdev->hw_info.fcoe_wwn_port_name[0] = 0x20;
2308    pdev->hw_info.fcoe_wwn_port_name[1] = 0;
2309    mm_memcpy(&(pdev->hw_info.fcoe_wwn_node_name[2]), pdev->hw_info.fcoe_mac_addr, 6);
2310    pdev->hw_info.fcoe_wwn_node_name[0] = 0x10;
2311    pdev->hw_info.fcoe_wwn_node_name[1] = 0;
2312}
2313
2314static lm_status_t lm_get_shmem_mf_mac_info(lm_device_t *pdev)
2315{
2316    lm_hardware_mf_info_t *mf_info   = &pdev->hw_info.mf_info;
2317    u32_t                  mac_upper = 0;
2318    u32_t                  mac_lower = 0;
2319
2320    if (mf_info->mf_mode == SINGLE_FUNCTION)
2321    {
2322        return LM_STATUS_FAILURE;
2323    }
2324
2325    /* Get the permanent L2 MAC address. */
2326    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].mac_upper),&mac_upper);
2327    LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_mf_config[ABS_FUNC_ID(pdev)].mac_lower),&mac_lower);
2328
2329
2330    /* Mac validity is assumed since we already checked it to determine mf_mode. And we assume mf_mode
2331     * is configured correctly when we enter this function. */
2332    SET_FLAGS(mf_info->flags,MF_INFO_VALID_MAC);
2333    _copy_mac_upper_lower_to_arr(mac_upper, mac_lower, pdev->hw_info.mac_addr);
2334
2335    /* Set iSCSI / FCOE Mac addresses */
2336    switch (mf_info->mf_mode)
2337    {
2338    case MULTI_FUNCTION_SD:
2339        {
2340            // in E1x the ext mac doesn't exists and will cause MCP parity error CQ67469
2341            if ( CHIP_IS_E1x(pdev) || IS_SD_UFP_MODE(pdev) || IS_SD_BD_MODE(pdev))
2342            {
2343                /* Set all iscsi and fcoe mac addresses the same as network. */
2344                mm_memcpy(pdev->hw_info.iscsi_mac_addr, pdev->hw_info.mac_addr, 6);
2345                mm_memcpy(pdev->hw_info.fcoe_mac_addr,  pdev->hw_info.mac_addr, 6);
2346                break;
2347            }
2348        }
2349	/* FALLTHROUGH */
2350    case MULTI_FUNCTION_SI:
2351    case MULTI_FUNCTION_AFEX:
2352        lm_get_shmem_ext_mac_addresses(pdev);
2353        break;
2354    }
2355
2356    return LM_STATUS_SUCCESS;
2357}
2358
2359static lm_status_t lm_get_shmem_sf_mac_info(lm_device_t *pdev)
2360{
2361    u32_t val  = 0;
2362    u32_t val2 = 0;
2363
2364    LM_SHMEM_READ(pdev,
2365                  OFFSETOF(shmem_region_t, dev_info.port_hw_config[PORT_ID(pdev)].mac_upper),&val);
2366    LM_SHMEM_READ(pdev,
2367                  OFFSETOF(shmem_region_t, dev_info.port_hw_config[PORT_ID(pdev)].mac_lower),&val2);
2368    _copy_mac_upper_lower_to_arr(val, val2, pdev->hw_info.mac_addr);
2369
2370    /* Get iSCSI MAC address. */
2371    LM_SHMEM_READ(pdev,
2372                  OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].iscsi_mac_upper),&val);
2373    LM_SHMEM_READ(pdev,
2374                  OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].iscsi_mac_lower),&val2);
2375    _copy_mac_upper_lower_to_arr(val, val2, pdev->hw_info.iscsi_mac_addr);
2376
2377     /* Get FCoE MAC addresses. */
2378    LM_SHMEM_READ(pdev,
2379                  OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].fcoe_fip_mac_upper),&val);
2380    LM_SHMEM_READ(pdev,
2381                  OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].fcoe_fip_mac_lower),&val2);
2382    _copy_mac_upper_lower_to_arr(val, val2, pdev->hw_info.fcoe_mac_addr);
2383
2384    LM_SHMEM_READ(pdev,
2385                  OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].fcoe_wwn_port_name_upper),&val);
2386    LM_SHMEM_READ(pdev,
2387                  OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].fcoe_wwn_port_name_lower),&val2);
2388    _copy_mac_upper_lower_to_arr(val, val2, &(pdev->hw_info.fcoe_wwn_port_name[2]));
2389    pdev->hw_info.fcoe_wwn_port_name[0] = (u8_t) (val >> 24);
2390    pdev->hw_info.fcoe_wwn_port_name[1] = (u8_t) (val >> 16);
2391
2392    LM_SHMEM_READ(pdev,
2393                  OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].fcoe_wwn_node_name_upper),&val);
2394    LM_SHMEM_READ(pdev,
2395                  OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].fcoe_wwn_node_name_lower),&val2);
2396    _copy_mac_upper_lower_to_arr(val, val2, &(pdev->hw_info.fcoe_wwn_node_name[2]));
2397    pdev->hw_info.fcoe_wwn_node_name[0] = (u8_t) (val >> 24);
2398    pdev->hw_info.fcoe_wwn_node_name[1] = (u8_t) (val >> 16);
2399
2400    DbgMessage(pdev, INFORMi, "main mac addr: %02x %02x %02x %02x %02x %02x\n",
2401        pdev->hw_info.mac_addr[0],
2402        pdev->hw_info.mac_addr[1],
2403        pdev->hw_info.mac_addr[2],
2404        pdev->hw_info.mac_addr[3],
2405        pdev->hw_info.mac_addr[4],
2406        pdev->hw_info.mac_addr[5]);
2407    DbgMessage(pdev, INFORMi, "iSCSI mac addr: %02x %02x %02x %02x %02x %02x\n",
2408        pdev->hw_info.iscsi_mac_addr[0],
2409        pdev->hw_info.iscsi_mac_addr[1],
2410        pdev->hw_info.iscsi_mac_addr[2],
2411        pdev->hw_info.iscsi_mac_addr[3],
2412        pdev->hw_info.iscsi_mac_addr[4],
2413        pdev->hw_info.iscsi_mac_addr[5]);
2414
2415    return LM_STATUS_SUCCESS;
2416}
2417
2418/* Gets the sriov info from shmem of ALL functions and marks if configuration is assymetric */
2419static void lm_get_shmem_sf_sriov_info(lm_device_t *pdev)
2420{
2421    const lm_chip_port_mode_t port_mode         = CHIP_PORT_MODE(pdev);
2422    u32_t                     offset            = 0;
2423    u32_t                     val               = 0;
2424    u8_t                      port_max          = (port_mode == LM_CHIP_PORT_MODE_2)? 1 : PORT_MAX;
2425    const u8_t                port              = PORT_ID(pdev);
2426    u8_t                      port_idx          = 0;
2427    u8_t                      sriov_enabled     = 0xff;
2428    u8_t                      sriov_disabled    = 0xff;
2429
2430    ASSERT_STATIC((FIELD_SIZE(struct shm_dev_info, port_hw_config)/FIELD_SIZE(struct shm_dev_info, port_hw_config[0])) >= max(PORT_MAX,1));
2431
2432    if (CHIP_IS_E1x(pdev))
2433    {
2434        pdev->hw_info.sriov_info.shmem_num_vfs_in_pf = 0;
2435        pdev->hw_info.sriov_info.b_pf_asymetric_configuration = FALSE;
2436
2437        return;
2438    }
2439
2440    for (port_idx = 0; port_idx < port_max; port_idx++)
2441    {
2442        offset = OFFSETOF(shmem_region_t,dev_info.port_hw_config[port_idx].pf_allocation);
2443        LM_SHMEM_READ(pdev, offset, &val);
2444
2445        val = (val & PORT_HW_CFG_NUMBER_OF_VFS_MASK) >> PORT_HW_CFG_NUMBER_OF_VFS_SHIFT;
2446
2447        if (0 == val)
2448        {
2449            sriov_disabled = 1;
2450        }
2451        else
2452        {
2453            sriov_enabled = 1;
2454        }
2455
2456        if (port_idx == port)
2457        {
2458            pdev->hw_info.sriov_info.shmem_num_vfs_in_pf = val;
2459        }
2460    }
2461
2462
2463    /* check if assymteric configuration...basically we initialize both params to 0xff, so the only way they can both be
2464     * the same is if one of the ports was enabled and one was disabled... */
2465    if (sriov_disabled == sriov_enabled)
2466    {
2467        pdev->hw_info.sriov_info.b_pf_asymetric_configuration = TRUE;
2468    }
2469    else
2470    {
2471        pdev->hw_info.sriov_info.b_pf_asymetric_configuration = FALSE;
2472    }
2473
2474}
2475
2476static void lm_get_shmem_mf_sriov_info(lm_device_t *pdev)
2477{
2478    u32_t                     offset               = 0;
2479    u32_t                     val                  = 0;
2480    u8_t                      func                 = 0;
2481    const u8_t                abs_func             = ABS_FUNC_ID(pdev);
2482    u8_t                      abs_func_idx         = 0;
2483    u8_t                      sriov_enabled        = 0xff;
2484    u8_t                      sriov_disabled       = 0xff;
2485
2486    ASSERT_STATIC((FIELD_SIZE(struct mf_cfg, func_mf_config) / FIELD_SIZE(struct mf_cfg, func_mf_config[0])) == E2_FUNC_MAX*2);
2487
2488    if (CHIP_IS_E1x(pdev))
2489    {
2490        pdev->hw_info.sriov_info.shmem_num_vfs_in_pf = 0;
2491        pdev->hw_info.sriov_info.b_pf_asymetric_configuration = FALSE;
2492
2493        return;
2494    }
2495
2496    for (func = 0; func < E2_FUNC_MAX; func++)
2497    {
2498        abs_func_idx = PATH_ID(pdev) + func*2;
2499
2500        offset = OFFSETOF(mf_cfg_t, func_mf_config[abs_func_idx].pf_allocation);
2501        LM_MFCFG_READ(pdev, offset,&val);
2502        val = (val & FUNC_MF_CFG_NUMBER_OF_VFS_MASK) >> FUNC_MF_CFG_NUMBER_OF_VFS_SHIFT;
2503
2504        if (0 == val)
2505        {
2506            sriov_disabled = 1;
2507        }
2508        else
2509        {
2510            sriov_enabled = 1;
2511        }
2512
2513        if (abs_func_idx == abs_func)
2514        {
2515            pdev->hw_info.sriov_info.shmem_num_vfs_in_pf = val;
2516        }
2517    }
2518
2519
2520    /* check if assymteric configuration...basically we initialize both params to 0xff, so the only way they can both be
2521     * the same is if one of the ports was enabled and one was disabled... */
2522    if (sriov_disabled == sriov_enabled)
2523    {
2524        pdev->hw_info.sriov_info.b_pf_asymetric_configuration = TRUE;
2525    }
2526    else
2527    {
2528        pdev->hw_info.sriov_info.b_pf_asymetric_configuration = FALSE;
2529    }
2530
2531}
2532
2533
2534static lm_status_t lm_get_shmem_mac_info(lm_device_t *pdev)
2535{
2536    lm_status_t lm_status = LM_STATUS_SUCCESS;
2537
2538    if (pdev->hw_info.mf_info.mf_mode == SINGLE_FUNCTION)
2539    {
2540        lm_status = lm_get_shmem_sf_mac_info(pdev);
2541    }
2542    else
2543    {
2544        lm_status = lm_get_shmem_mf_mac_info(pdev);
2545    }
2546
2547    return lm_status;
2548}
2549
2550static void lm_get_shmem_sriov_info(lm_device_t *pdev)
2551{
2552    const u32_t bc_rev    = LM_GET_BC_REV_MAJOR(pdev);
2553
2554    if (CHIP_IS_E1x(pdev) || (bc_rev < BC_REV_IE_SRIOV_SUPPORTED))
2555    {
2556        return;
2557    }
2558
2559    if (pdev->hw_info.mf_info.mf_mode == SINGLE_FUNCTION)
2560    {
2561        lm_get_shmem_sf_sriov_info(pdev);
2562    }
2563    else
2564    {
2565        lm_get_shmem_mf_sriov_info(pdev);
2566    }
2567}
2568
2569static void lm_get_shmem_fw_flow_control(lm_device_t *pdev)
2570{
2571    u32_t func_ext_cfg = 0;
2572
2573    // cq57766
2574    // if this static assert fails consider adding the new mode to the if
2575    // and read the l2_fw_flow_ctrl from the shmem in the new mode also
2576    ASSERT_STATIC(MAX_MF_MODE == 4);
2577    // l2_fw_flow_ctrl is read from the shmem in multi-function mode in E2 and above.
2578    // In all other cases this parameter is read from the registry.
2579    // We read this parameter from the registry in E1.5 multi-function since 57711 boot code does not have the struct func_ext_cfg
2580    if (((pdev->hw_info.mf_info.mf_mode == MULTI_FUNCTION_SI)   ||
2581         (pdev->hw_info.mf_info.mf_mode == MULTI_FUNCTION_AFEX)) &&
2582        (!CHIP_IS_E1x(pdev)))
2583    {
2584        LM_MFCFG_READ(pdev, OFFSETOF(mf_cfg_t, func_ext_config[ABS_FUNC_ID(pdev)].func_cfg), &func_ext_cfg);
2585        if (GET_FLAGS(func_ext_cfg, MACP_FUNC_CFG_PAUSE_ON_HOST_RING))
2586        {
2587            pdev->params.l2_fw_flow_ctrl = 1;
2588        }
2589        else
2590        {
2591            pdev->params.l2_fw_flow_ctrl = 0;
2592        }
2593    }
2594}
2595
2596/**
2597 * @Description
2598 *     This function is responsible for reading all the data
2599 *     that the driver needs before loading from the shmem.
2600 *
2601 * @param pdev
2602 *
2603 * @return lm_status_t
2604 */
2605lm_status_t lm_get_shmem_info(lm_device_t *pdev)
2606{
2607    lm_status_t lm_status = LM_STATUS_SUCCESS;
2608    u32_t       val       = 0;
2609
2610    lm_shmem_set_default(pdev);
2611
2612    val = lm_get_shmem_base_addr(pdev);
2613    if (!val)
2614    {
2615        DbgMessage(pdev, WARNi, "NO MCP\n");
2616        return lm_get_shmem_info_no_mcp_bypass(pdev);
2617    }
2618
2619    pdev->hw_info.mcp_detected = 1;
2620    pdev->hw_info.shmem_base   = val;
2621
2622    pdev->hw_info.shmem_base2 = REG_RD(pdev, PATH_ID(pdev) ? MISC_REG_GENERIC_CR_1 : MISC_REG_GENERIC_CR_0);
2623    pdev->hw_info.mf_cfg_base = lm_get_shmem_mf_cfg_base(pdev);
2624
2625    DbgMessage(pdev, WARNi, "MCP Up Detected. shmem_base=0x%x shmem_base2=0x%x mf_cfg_offset=0x%x\n",
2626                pdev->hw_info.shmem_base, pdev->hw_info.shmem_base2, pdev->hw_info.mf_cfg_base);
2627
2628    lm_status = lm_verify_validity_map( pdev );
2629    if(LM_STATUS_SUCCESS != lm_status )
2630    {
2631        DbgMessage(pdev, FATAL, "lm_get_shmem_info: Shmem signature not present.\n");
2632        pdev->hw_info.mcp_detected = 0;
2633        return LM_STATUS_SUCCESS;
2634     }
2635
2636    /* bc rev */
2637    LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.bc_rev),&val);
2638    pdev->hw_info.bc_rev = val;
2639    DbgMessage(pdev, INFORMi, "bc_rev %d\n",val);
2640
2641    lm_status = lm_get_shmem_shared_hw_config(pdev);
2642    if (lm_status != LM_STATUS_SUCCESS)
2643    {
2644        DbgMessage(pdev, WARNi, "lm_get_shmem_shared_hw_config returned lm_status=%d\n", lm_status);
2645        return lm_status;
2646    }
2647
2648    lm_status = lm_get_shmem_port_hw_config(pdev);
2649    if (lm_status != LM_STATUS_SUCCESS)
2650    {
2651        DbgMessage(pdev, WARNi, "lm_get_shmem_port_hw_config returned lm_status=%d\n", lm_status);
2652        return lm_status;
2653    }
2654
2655    /* Check License for toe/rdma/iscsi */
2656#ifdef _LICENSE_H
2657    lm_status = lm_get_shmem_license_info(pdev);
2658    if (lm_status != LM_STATUS_SUCCESS)
2659    {
2660        DbgMessage(pdev, WARNi, "lm_get_shmem_license_info returned lm_status=%d\n", lm_status);
2661        return lm_status;
2662    }
2663#endif
2664    /* get mf config parameters */
2665    if (IS_MF_MODE_CAPABLE(pdev) && (pdev->hw_info.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE))
2666    {
2667        lm_status = lm_get_shmem_mf_cfg_info(pdev);
2668        if (lm_status != LM_STATUS_SUCCESS)
2669        {
2670            DbgMessage(pdev, WARNi, "lm_get_shmem_mf_cfg_info returned lm_status=%d\n", lm_status);
2671            return lm_status;
2672        }
2673    }
2674    else if (FUNC_ID(pdev) != PORT_ID(pdev))
2675    {
2676        DbgMessage(pdev, WARNi, "Illegal to load func %d of port %d on non MF mode capable device\n");
2677        return LM_STATUS_FAILURE;
2678    }
2679
2680    lm_get_shmem_sriov_info(pdev);
2681
2682    lm_status = lm_get_shmem_mac_info(pdev);
2683
2684    lm_get_shmem_fw_flow_control(pdev);
2685
2686    return lm_status;
2687}
2688
2689void init_link_params(lm_device_t *pdev)
2690{
2691    u32_t val              = 0;
2692    u32_t feat_val         = 0;
2693    const u8_t port     = PORT_ID(pdev);
2694
2695    pdev->params.link.port        = port;
2696    pdev->params.link.lfa_base = 0;
2697    pdev->params.link.shmem_base = NO_MCP_WA_CLC_SHMEM;
2698    pdev->params.link.shmem2_base= NO_MCP_WA_CLC_SHMEM;
2699
2700    if (pdev->hw_info.mcp_detected)
2701    {
2702        pdev->params.link.shmem_base = pdev->hw_info.shmem_base;
2703        pdev->params.link.shmem2_base= pdev->hw_info.shmem_base2;
2704
2705        // Only if LFA is supported in MFW
2706        if (LM_SHMEM2_HAS(pdev,lfa_host_addr[port]))
2707        {
2708            LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t, lfa_host_addr[port]), &pdev->params.link.lfa_base);
2709        }
2710   }
2711
2712    pdev->params.link.chip_id = pdev->hw_info.chip_id;
2713    pdev->params.link.cb      = pdev;
2714
2715    ///TODO remove - the initialization in lm_mcp_cmd_init should be enough, but BC versions are still in flux.
2716    if(pdev->hw_info.mf_info.mf_mode == MULTI_FUNCTION_AFEX) //we can't use IS_MF_NIV_MODE because params.mf_mode is not initalized yet.
2717    {
2718        SET_FLAGS( pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_BC_SUPPORTS_AFEX );
2719    }
2720
2721    if (CHIP_REV_IS_SLOW(pdev))
2722    {
2723        val = CHIP_BONDING(pdev);
2724        DbgMessage(pdev, WARN, "init_link_params: chip bond id is 0x%x\n",val);
2725
2726        if (pdev->hw_info.chip_port_mode == LM_CHIP_PORT_MODE_4)
2727        {
2728            feat_val |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC;
2729        }
2730        else if (val & 0x4)
2731        {
2732            // force to work with emac
2733            if (CHIP_IS_E3(pdev))
2734            {
2735                pdev->params.link.req_line_speed[0] = ELINK_SPEED_1000;
2736                feat_val |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC;
2737            }
2738            else
2739            {
2740                feat_val |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC;
2741            }
2742        }
2743        else if (val & 0x8)
2744        {
2745            if (CHIP_IS_E3(pdev))
2746            {
2747                feat_val |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_UMAC;
2748            }
2749            else
2750            {
2751                feat_val |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC;
2752            }
2753        }
2754        /* Disable EMAC for E3 and above */
2755        if (val & 2)
2756        {
2757            feat_val |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC;
2758        }
2759
2760        SET_FLAGS(pdev->params.link.feature_config_flags, feat_val);
2761    }
2762}
2763
2764/** lm_init_cam_params
2765 *  set cam/mac parameters
2766 *
2767 *  cam mapping is dynamic, we only set sizes...
2768 *
2769 */
2770static void lm_init_cam_params(lm_device_t *pdev)
2771{
2772    /* FIXME: remove once constants are in hsi file */
2773    #define LM_CAM_SIZE_EMUL                    (5)                                /*5 per vnic also in single function mode (real cam size on emulation is 20 per port) */
2774    #define LM_MC_TABLE_SIZE_EMUL               (1)
2775    #define LM_CAM_SIZE_EMUL_E2                 (40)
2776
2777    u16_t mc_credit;
2778    u16_t uc_credit;
2779    u8_t b_is_asic = CHIP_REV_IS_ASIC(pdev);
2780    u8_t num_ports = 2;
2781    u8_t num_funcs;
2782
2783    /* set CAM parameters according to EMUL/FPGA or ASIC + Chip*/
2784    mm_mem_zero(pdev->params.uc_table_size, sizeof(pdev->params.uc_table_size));
2785    mm_mem_zero(pdev->params.mc_table_size, sizeof(pdev->params.mc_table_size));
2786
2787    if (CHIP_IS_E1(pdev))
2788    {
2789        pdev->params.cam_size = b_is_asic? MAX_MAC_CREDIT_E1 / num_ports : LM_CAM_SIZE_EMUL;
2790
2791        mc_credit = b_is_asic? LM_MC_NDIS_TABLE_SIZE : LM_MC_TABLE_SIZE_EMUL;
2792        uc_credit = pdev->params.cam_size - mc_credit; /* E1 multicast is in CAM */
2793
2794    /* init unicast table entires */
2795    pdev->params.uc_table_size[LM_CLI_IDX_ISCSI]    = 1;
2796        pdev->params.uc_table_size[LM_CLI_IDX_NDIS]  = uc_credit - 1; /* - one for iscsi... */
2797
2798    /* init multicast table entires */
2799        pdev->params.mc_table_size[LM_CLI_IDX_NDIS] = mc_credit;
2800
2801        DbgMessage(pdev, INFORMi, "uc_table_size[ndis]=%d, uc_table_size[ndis]=%d, mc_table_size[ndis]=%d\n",
2802                   pdev->params.uc_table_size[LM_CLI_IDX_NDIS], pdev->params.uc_table_size[LM_CLI_IDX_ISCSI],
2803                   pdev->params.mc_table_size[LM_CLI_IDX_NDIS]);
2804
2805    }
2806    else if (CHIP_IS_E1H(pdev))
2807    {
2808        pdev->params.cam_size = b_is_asic? MAX_MAC_CREDIT_E1H / num_ports: LM_CAM_SIZE_EMUL;
2809        pdev->params.cam_size = pdev->params.cam_size / pdev->params.vnics_per_port;
2810        uc_credit = pdev->params.cam_size;
2811
2812        /* init unicast table entires */
2813        pdev->params.uc_table_size[LM_CLI_IDX_ISCSI] = 1;
2814        pdev->params.uc_table_size[LM_CLI_IDX_NDIS]  = uc_credit - 1; /* - one for iscsi... */
2815
2816        /* init multicast table entires */
2817        pdev->params.mc_table_size[LM_CLI_IDX_NDIS] = LM_MC_NDIS_TABLE_SIZE;
2818
2819        DbgMessage(pdev, INFORMi, "uc_table_size[ndis]=%d, uc_table_size[ndis]=%d, mc_table_size[ndis]=%d\n",
2820                   pdev->params.uc_table_size[LM_CLI_IDX_NDIS], pdev->params.uc_table_size[LM_CLI_IDX_ISCSI],
2821                   pdev->params.mc_table_size[LM_CLI_IDX_NDIS]);
2822    }
2823    else if (CHIP_IS_E2E3(pdev))
2824    {
2825        num_ports = (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_4)? 2 : 1;
2826    num_funcs = VNICS_PER_PATH(pdev);
2827    if (num_funcs > 1)
2828    {
2829        pdev->params.cam_size = b_is_asic? ((MAX_MAC_CREDIT_E2 - GET_NUM_VFS_PER_PATH(pdev))/ num_funcs + GET_NUM_VFS_PER_PF(pdev)): LM_CAM_SIZE_EMUL_E2;
2830    }
2831    else
2832    {
2833        pdev->params.cam_size = b_is_asic? MAX_MAC_CREDIT_E2 : LM_CAM_SIZE_EMUL_E2;
2834    }
2835        uc_credit = pdev->params.cam_size;
2836
2837        /* init unicast table entires */
2838        pdev->params.uc_table_size[LM_CLI_IDX_ISCSI] = 1;
2839        pdev->params.uc_table_size[LM_CLI_IDX_FCOE]  = 1;
2840        pdev->params.uc_table_size[LM_CLI_IDX_NDIS]  = uc_credit - 2; /* - the two above... */
2841
2842        /* init multicast table entires */
2843        pdev->params.mc_table_size[LM_CLI_IDX_NDIS] = LM_MC_NDIS_TABLE_SIZE;
2844        pdev->params.mc_table_size[LM_CLI_IDX_FCOE] = LM_MC_FCOE_TABLE_SIZE;
2845
2846        DbgMessage(pdev, INFORMi, "uc_table_size[ndis]=%d, uc_table_size[ndis]=%d, uc_table_size[fcoe]=%d, mc_table_size[ndis]=%d, mc_table_size[fcoe]=%d\n",
2847                    pdev->params.uc_table_size[LM_CLI_IDX_NDIS], pdev->params.uc_table_size[LM_CLI_IDX_ISCSI],
2848                    pdev->params.uc_table_size[LM_CLI_IDX_FCOE],
2849                    pdev->params.mc_table_size[LM_CLI_IDX_NDIS], pdev->params.mc_table_size[LM_CLI_IDX_FCOE]);
2850    }
2851    else
2852    {
2853        DbgBreakIfAll("New Chip?? initialize cam params!\n");
2854    }
2855
2856    /* override CAM parameters for chips later than E1 */
2857    if (IS_PFDEV(pdev))
2858    {
2859        pdev->params.base_offset_in_cam_table = ((num_ports == 2)? FUNC_ID(pdev) : VNIC_ID(pdev)) * LM_CAM_SIZE(pdev);
2860    }
2861    else if (IS_CHANNEL_VFDEV(pdev))
2862    {
2863        pdev->params.base_offset_in_cam_table = 0;
2864        pdev->params.mc_table_size[LM_CLI_IDX_NDIS] = 0; /* Will be filled later on acquire response (HW_CHANNEL)*/
2865    }
2866}
2867
2868/*
2869 * \brief Initialize pdev->params members
2870 *
2871 * This function initializes the various pdev->params members, depending
2872 * on chip technology/implementation: fpga, emul or asic (default).
2873 *
2874 * The function may also be used to validate these parameters.
2875 *
2876 * \param[in,out]   pdev
2877 * \param[in]       validate        flag to indicate desired operation.
2878 *
2879 * \return success/failure indication
2880 */
2881
2882static lm_status_t lm_init_params(lm_device_t *pdev, u8_t validate)
2883{
2884    typedef struct _param_entry_t
2885    {
2886        /* Ideally, we want to save the address of the parameter here.
2887        * However, some compiler will not allow us to dynamically
2888        * initialize the pointer to a parameter in the table below.
2889        * As an alternative, we will save the offset to the parameter
2890        * from pdev device structure. */
2891        u32_t offset;
2892        /* Parameter default value. */
2893        u32_t asic_default;
2894        u32_t fpga_default;
2895        u32_t emulation_default;
2896        /* Limit checking is diabled if min and max are zeros. */
2897        u32_t min;
2898        u32_t max;
2899    } param_entry_t;
2900    #define _OFFSET(_name)          (OFFSETOF(lm_device_t, params._name))
2901    #define PARAM_VAL(_pdev, _entry) \
2902        (*((u32_t *) ((u8_t *) (_pdev) + (_entry)->offset)))
2903    #define SET_PARAM_VAL(_pdev, _entry, _val) \
2904        *((u32_t *) ((u8_t *) (_pdev) + (_entry)->offset)) = (_val)
2905    static param_entry_t param_list[] =
2906    {
2907        /*                                 asic     fpga     emul
2908        offset                          default  default  default min     max */
2909        { _OFFSET(mtu[LM_CLI_IDX_NDIS]),  9216,    9216,    9216,   1500,   9216 },
2910        { _OFFSET(mtu[LM_CLI_IDX_ISCSI]),  9216,    9216,    9216,   1500,   9216 },
2911        { _OFFSET(mtu[LM_CLI_IDX_FCOE]),  9216,    9216,    9216,   1500,   9216 },
2912//        { _OFFSET(mtu[LM_CLI_IDX_RDMA]),  LM_MTU_INVALID_VALUE,    LM_MTU_INVALID_VALUE,    LM_MTU_INVALID_VALUE,   LM_MTU_INVALID_VALUE,   LM_MTU_INVALID_VALUE },
2913        { _OFFSET(mtu[LM_CLI_IDX_OOO]),  9216,    9216,    9216,   1500,   9216 },
2914        { _OFFSET(mtu[LM_CLI_IDX_FWD]),  9216,    9216,    9216,   1500,   9216 },
2915        { _OFFSET(mtu_max),  9216,    9216,    9216,   1500,   9216 },
2916        { _OFFSET(rcv_buffer_offset),      0,       0,       0,      0,   9000 },
2917        { _OFFSET(l2_rx_desc_cnt[LM_CLI_IDX_NDIS]),      200,     200,     200,    0,      32767 },
2918        { _OFFSET(l2_rx_desc_cnt[LM_CLI_IDX_FCOE]),      200,     200,     200,    0,      32767 },
2919        { _OFFSET(l2_rx_desc_cnt[LM_CLI_IDX_OOO]),       500,     500,     500,    0,      32767 },
2920        /* The maximum page count is chosen to prevent us from having
2921        * more than 32767 pending entries at any one time. */
2922        { _OFFSET(l2_tx_bd_page_cnt[LM_CLI_IDX_NDIS]),   2,       2,       2,      1,      127 },
2923        { _OFFSET(l2_tx_bd_page_cnt[LM_CLI_IDX_FCOE]),   2,       2,       2,      1,      127 },
2924        { _OFFSET(l2_tx_coal_buf_cnt[LM_CLI_IDX_NDIS]),  0,       0,       0,      0,      20 },
2925        { _OFFSET(l2_tx_coal_buf_cnt[LM_CLI_IDX_FCOE]),  0,       0,       0,      0,      20 },
2926        { _OFFSET(l2_tx_bd_page_cnt[LM_CLI_IDX_FWD]) ,   2,       2,       2,      1,      127 },
2927        /* NirV: still not supported in ediag, being set in the windows mm */
2928//        { _OFFSET(l2_rx_desc_cnt[LM_CLI_IDX_ISCSI]),      200,     200,     200,    0,      32767 },
2929//
2930//        /* The maximum page count is chosen to prevent us from having
2931//        * more than 32767 pending entries at any one time. */
2932//        { _OFFSET(l2_tx_bd_page_cnt[LM_CLI_IDX_ISCSI]),   2,       2,       2,      1,      127 },
2933//        { _OFFSET(l2_tx_coal_buf_cnt[LM_CLI_IDX_ISCSI]),  0,       0,       0,      0,      20 },
2934//        { _OFFSET(l2_rx_bd_page_cnt[LM_CLI_IDX_ISCSI]),   1,       1,       1,      1,      127 },
2935        { _OFFSET(test_mode),              0,       0,       0,      0,      0 },
2936        { _OFFSET(ofld_cap),               0,       0,       0,      0,      0 },
2937        { _OFFSET(wol_cap),                0,       0,       0,      0,      0 },
2938        { _OFFSET(i2c_interval_sec),       0,       0,       0,      0,      1000 },
2939        { _OFFSET(flow_ctrl_cap),          0,       0,       0,      0,      0x80000000 },
2940        { _OFFSET(eee_policy),             LM_EEE_CONTROL_NVRAM, LM_EEE_CONTROL_NVRAM, LM_EEE_CONTROL_NVRAM, LM_EEE_CONTROL_HIGH, LM_EEE_CONTROL_NVRAM }, // registry values are 0-5 for this
2941        { _OFFSET(req_medium),             0xff00,  0x00ff,  0x00ff, 0,   0xfffff },
2942        { _OFFSET(interrupt_mode),         LM_INT_MODE_INTA, LM_INT_MODE_INTA, LM_INT_MODE_INTA, LM_INT_MODE_INTA, LM_INT_MODE_MIMD},
2943        { _OFFSET(igu_access_mode),        INTR_BLK_ACCESS_IGUMEM, INTR_BLK_ACCESS_IGUMEM, INTR_BLK_ACCESS_IGUMEM, INTR_BLK_ACCESS_GRC, INTR_BLK_ACCESS_IGUMEM},
2944        { _OFFSET(sw_config),              4,       4,       4,      0,      4},
2945        { _OFFSET(selective_autoneg),      0,       0,       0,      0,      0 },
2946        { _OFFSET(autogreeen),             LM_AUTOGREEEN_NVRAM,       LM_AUTOGREEEN_NVRAM,       LM_AUTOGREEEN_NVRAM,      LM_AUTOGREEEN_DISABLED,      LM_AUTOGREEEN_NVRAM },
2947        { _OFFSET(wire_speed),             1,       0,       0,      0,      0 },
2948        { _OFFSET(phy_int_mode),           2,       2,       2,      0,      0 },
2949        { _OFFSET(link_chng_mode),         2,       2,       2,      0,      0 },
2950        // TODO add correct values here
2951        { _OFFSET(max_func_connections),   1024,    1024,    1024,   0,      500000},
2952#ifdef VF_INVOLVED
2953        { _OFFSET(max_func_toe_cons),      310,     310,     310,    0,      500000},
2954#else
2955        { _OFFSET(max_func_toe_cons),      750,     750,     750,    0,      500000},
2956#endif
2957        { _OFFSET(max_func_rdma_cons),     10,       10,      10,    0,      500000},
2958        { _OFFSET(max_func_iscsi_cons),    128,     128,     128,    0,      500000},
2959        { _OFFSET(max_func_fcoe_cons),     64,      64,      20,     0,      500000},
2960        { _OFFSET(context_line_size),      LM_CONTEXT_SIZE,    LM_CONTEXT_SIZE,    LM_CONTEXT_SIZE,   0,      LM_CONTEXT_SIZE },
2961        { _OFFSET(context_waste_size),     0,       0,       0,      0,      1024 },
2962        { _OFFSET(num_context_in_page),    4,       4,       4,      0,       128},
2963        { _OFFSET(client_page_size),       0x1000, 0x1000, 0x1000,0x1000, 0x20000 },
2964        { _OFFSET(elt_page_size),          0x1000, 0x1000, 0x1000,0x1000, 0x20000 },
2965        { _OFFSET(ilt_client_page_size),   0x1000, 0x1000, 0x1000,0x1000, 0x20000 },
2966        { _OFFSET(cfc_last_lcid),          0xff,   0xff,   0xff,    0x1,     0xff },
2967        { _OFFSET(override_rss_chain_cnt), 0,      0,      0,       0,       16 },
2968        // network type and max cwnd
2969        { _OFFSET(network_type),   LM_NETOWRK_TYPE_WAN, LM_NETOWRK_TYPE_WAN, LM_NETOWRK_TYPE_WAN,LM_NETOWRK_TYPE_LAN, LM_NETOWRK_TYPE_WAN },
2970        { _OFFSET(max_cwnd_wan),   12500000, 12500000, 12500000,12500000, 12500000 },
2971        { _OFFSET(max_cwnd_lan),   1250000 , 1250000,  1250000, 1250000,  1250000 },
2972        // cid allocation mode
2973        { _OFFSET(cid_allocation_mode),     LM_CID_ALLOC_DELAY , LM_CID_ALLOC_DELAY, LM_CID_ALLOC_DELAY,LM_CID_ALLOC_DELAY, LM_CID_ALLOC_NUM_MODES},
2974        // interrupt coalesing configuration
2975        { _OFFSET(int_coalesing_mode),      LM_INT_COAL_PERIODIC_SYNC, LM_INT_COAL_NONE, LM_INT_COAL_NONE, 1, LM_INT_COAL_NUM_MODES },
2976        { _OFFSET(int_per_sec_rx[0]),          5000,    5000,    5000,  1,      200000 },
2977        { _OFFSET(int_per_sec_rx[1]),          5000,    5000,    5000,  1,      200000 },
2978        { _OFFSET(int_per_sec_rx[2]),          5000,    5000,    5000,  1,      200000 },
2979        { _OFFSET(int_per_sec_rx[3]),          5000,    5000,    5000,  1,      200000 },
2980        { _OFFSET(int_per_sec_tx[0]),          7500,    7500,    7500,  1,      200000 },
2981        { _OFFSET(int_per_sec_tx[1]),          3800,    3800,    3800,  1,      200000 },
2982        { _OFFSET(int_per_sec_tx[2]),          3800,    3800,    3800,  1,      200000 },
2983        { _OFFSET(int_per_sec_tx[3]),          3800,    3800,    3800,  1,      200000 },
2984        // VF interrupt coalesing configuration
2985        { _OFFSET(vf_int_per_sec_rx[LM_VF_INT_LOW_IDX]),    5000,    5000,    5000,  1,      200000 },
2986        { _OFFSET(vf_int_per_sec_rx[LM_VF_INT_MEDIUM_IDX]), 10000,    5000,    5000,  1,      200000 },
2987        { _OFFSET(vf_int_per_sec_rx[LM_VF_INT_HIGH_IDX]),   20000,    5000,    5000,  1,      200000 },
2988        { _OFFSET(vf_int_per_sec_tx[LM_VF_INT_LOW_IDX]),    3800,    3800,    3800,  1,      200000 },
2989        { _OFFSET(vf_int_per_sec_tx[LM_VF_INT_MEDIUM_IDX]), 8000,    3800,    3800,  1,      200000 },
2990        { _OFFSET(vf_int_per_sec_tx[LM_VF_INT_HIGH_IDX]),   16000,    3800,    3800,  1,      200000 },
2991
2992        { _OFFSET(enable_dynamic_hc[0]),    1,       1,       1,     0,      1 },
2993        { _OFFSET(enable_dynamic_hc[1]),    1,       1,       1,     0,      1 },
2994        { _OFFSET(enable_dynamic_hc[2]),    1,       1,       1,     0,      1 },
2995        { _OFFSET(enable_dynamic_hc[3]),    0,       0,       0,     0,      1 },
2996        { _OFFSET(hc_timeout0[SM_RX_ID][0]),       12,      12,      12,    1,      0xff },   /* (20K int/sec assuming no more btr) */
2997        { _OFFSET(hc_timeout1[SM_RX_ID][0]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
2998        { _OFFSET(hc_timeout2[SM_RX_ID][0]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
2999        { _OFFSET(hc_timeout3[SM_RX_ID][0]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3000        { _OFFSET(hc_timeout0[SM_RX_ID][1]),       6,       6,       6,     1,      0xff },   /* (40K int/sec assuming no more btr) */
3001        { _OFFSET(hc_timeout1[SM_RX_ID][1]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3002        { _OFFSET(hc_timeout2[SM_RX_ID][1]),       120,    120,     120,    1,      0xff },   /* (2K int/sec assuming no more btr) */
3003        { _OFFSET(hc_timeout3[SM_RX_ID][1]),       240,    240,     240,    1,      0xff },   /* (1K int/sec assuming no more btr) */
3004        { _OFFSET(hc_timeout0[SM_RX_ID][2]),       6,       6,       6,     1,      0xff },   /* (40K int/sec assuming no more btr) */
3005        { _OFFSET(hc_timeout1[SM_RX_ID][2]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3006        { _OFFSET(hc_timeout2[SM_RX_ID][2]),       120,    120,     120,    1,      0xff },   /* (2K int/sec assuming no more btr) */
3007        { _OFFSET(hc_timeout3[SM_RX_ID][2]),       240,    240,     240,    1,      0xff },   /* (1K int/sec assuming no more btr) */
3008        { _OFFSET(hc_timeout0[SM_RX_ID][3]),       6,       6,       6,     1,      0xff },   /* (40K int/sec assuming no more btr) */
3009        { _OFFSET(hc_timeout1[SM_RX_ID][3]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3010        { _OFFSET(hc_timeout2[SM_RX_ID][3]),       120,    120,     120,    1,      0xff },   /* (2K int/sec assuming no more btr) */
3011        { _OFFSET(hc_timeout3[SM_RX_ID][3]),       240,    240,     240,    1,      0xff },   /* (1K int/sec assuming no more btr) */
3012
3013        { _OFFSET(hc_timeout0[SM_TX_ID][0]),       12,      12,      12,    1,      0xff },   /* (20K int/sec assuming no more btr) */
3014        { _OFFSET(hc_timeout1[SM_TX_ID][0]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3015        { _OFFSET(hc_timeout2[SM_TX_ID][0]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3016        { _OFFSET(hc_timeout3[SM_TX_ID][0]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3017        { _OFFSET(hc_timeout0[SM_TX_ID][1]),       6,       6,       6,     1,      0xff },   /* (40K int/sec assuming no more btr) */
3018        { _OFFSET(hc_timeout1[SM_TX_ID][1]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3019        { _OFFSET(hc_timeout2[SM_TX_ID][1]),       120,    120,     120,    1,      0xff },   /* (2K int/sec assuming no more btr) */
3020        { _OFFSET(hc_timeout3[SM_TX_ID][1]),       240,    240,     240,    1,      0xff },   /* (1K int/sec assuming no more btr) */
3021        { _OFFSET(hc_timeout0[SM_TX_ID][2]),        6,       6,       6,    1,      0xff },   /* (40K int/sec assuming no more btr) */
3022        { _OFFSET(hc_timeout1[SM_TX_ID][2]),       12,      12,      12,    1,      0xff },   /* (20K int/sec assuming no more btr) */
3023        { _OFFSET(hc_timeout2[SM_TX_ID][2]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3024        { _OFFSET(hc_timeout3[SM_TX_ID][2]),       64,      64,      64,    1,      0xff },   /* (3.75K int/sec assuming no more btr) */
3025        { _OFFSET(hc_timeout0[SM_TX_ID][3]),       6,       6,       6,     1,      0xff },   /* (40K int/sec assuming no more btr) */
3026        { _OFFSET(hc_timeout1[SM_TX_ID][3]),       48,      48,      48,    1,      0xff },   /* (5K int/sec assuming no more btr) */
3027        { _OFFSET(hc_timeout2[SM_TX_ID][3]),       120,    120,     120,    1,      0xff },   /* (2K int/sec assuming no more btr) */
3028        { _OFFSET(hc_timeout3[SM_TX_ID][3]),       240,    240,     240,    1,      0xff },   /* (1K int/sec assuming no more btr) */
3029
3030        { _OFFSET(hc_threshold0[SM_RX_ID]),        0x2000,  0x2000,  0x2000,1,     0xffffffff },
3031        { _OFFSET(hc_threshold1[SM_RX_ID]),        0x10000, 0x10000, 0x10000,1,     0xffffffff },
3032        { _OFFSET(hc_threshold2[SM_RX_ID]),        0x50000, 0x50000, 0x50000,1,     0xffffffff },
3033
3034        { _OFFSET(hc_threshold0[SM_TX_ID]),        0x2000,  0x2000,  0x2000,1,     0xffffffff },
3035        { _OFFSET(hc_threshold1[SM_TX_ID]),        0x10000, 0x10000, 0x10000,1,     0xffffffff },
3036        { _OFFSET(hc_threshold2[SM_TX_ID]),        0x20000, 0x20000, 0x20000,1,     0xffffffff },
3037
3038        { _OFFSET(l2_dynamic_hc_min_bytes_per_packet),        0,      0,        0,        0,     0xffff },
3039//        { _OFFSET(l4_hc_scaling_factor),     12,      12,        12,      0,    16 },
3040        { _OFFSET(l4_hc_ustorm_thresh),     12,     12,       12,     12,     0xffffffff },  /* 128K */
3041        // l4 params
3042        { _OFFSET(l4_scq_page_cnt),         2,       2,       2,     2,      127 }, /* 321 BDs are reserved to FW threshold :-( */
3043        { _OFFSET(l4_rcq_page_cnt),         3,       3,       3,     3,      127 }, /* 398 BDs are reserved to FW threshold :-(  CQ_XOFF_TH = ((65*6) +  8) = ((maximum pending incoming msgs) * (maximum completions) + (maximum ramrods)) */
3044        { _OFFSET(l4_grq_page_cnt),         2,       2,       2,     2,      127 }, /* 65  BDs are reserved to FW threshold :-( */
3045        { _OFFSET(l4_tx_chain_page_cnt),    2,       2,       2,     2,      127 },
3046        { _OFFSET(l4_rx_chain_page_cnt),    2,       2,       2,     2,      127 },
3047        { _OFFSET(l4_gen_buf_size),         LM_PAGE_SIZE,LM_PAGE_SIZE,LM_PAGE_SIZE,LM_PAGE_SIZE,16*LM_PAGE_SIZE },
3048        { _OFFSET(l4_history_cqe_cnt),      20,      20,      20,    1,      20   },
3049        { _OFFSET(l4_ignore_grq_push_enabled), 0,       0,       0,     0,      1   },
3050        { _OFFSET(l4cli_flags),             0,       0,       0,     0,      1 },
3051        { _OFFSET(l4cli_ticks_per_second),  1000,    1000,    1000,  500,    10000 },
3052        { _OFFSET(l4cli_ack_frequency),     2,       2,       2,     1,      255 }, /* default 2 segments */
3053        { _OFFSET(l4cli_delayed_ack_ticks), 200,     200,     200,   1,      255 }, /* default 200ms */
3054        { _OFFSET(l4cli_max_retx),          6,       6,       6,     1,      255 },
3055        { _OFFSET(l4cli_doubt_reachability_retx),3,  3,       3,     1,      255 },
3056        { _OFFSET(l4cli_sws_prevention_ticks), 1000, 1000,    1000,  200,    0xffffffff }, /* default 1s */
3057        { _OFFSET(l4cli_dup_ack_threshold), 3,       3,       3,     1,      255 },
3058        { _OFFSET(l4cli_push_ticks),        100,     100,     100,   1,      0xffffffff }, /* default 100ms */
3059        { _OFFSET(l4cli_nce_stale_ticks),   0xffffff,0xffffff,0xffffff, 1,   0xffffffff },
3060        { _OFFSET(l4cli_starting_ip_id),    0,       0,       0,     0,      0xffff },
3061        { _OFFSET(keep_vlan_tag),           1 ,      1,       1,     0,      1 },
3062        //congestion managment parameters
3063        { _OFFSET(cmng_enable),             0,       0,       0,     0,      1},
3064        { _OFFSET(cmng_rate_shaping_enable),1,       1,       1,     0,      1},
3065        { _OFFSET(cmng_fairness_enable),    1,       1,       1,     0,      1},
3066        // safc
3067        { _OFFSET(cmng_safc_rate_thresh),   3,       3,       3,     0,      10},
3068        { _OFFSET(cmng_activate_safc),      0,       0,       0,     0,      1},
3069        // fairness
3070        { _OFFSET(cmng_fair_port0_rate),    10,      10,      10,    1,      10},
3071        { _OFFSET(cmng_eth_weight),         8,       8,       8,     0,      10},
3072        { _OFFSET(cmng_toe_weight),         8,       8,       8,     0,      10},
3073        { _OFFSET(cmng_rdma_weight),        8,       8,       8,     0,      10},
3074        { _OFFSET(cmng_iscsi_weight),       8,       8,       8,     0,      10},
3075        // rate shaping
3076        { _OFFSET(cmng_eth_rate),           10,      10,      10,    0,      10},
3077        { _OFFSET(cmng_toe_rate),           10,      10,      10,    0,      10},
3078        { _OFFSET(cmng_rdma_rate),          2,       2,       2,     0,      10},
3079        { _OFFSET(cmng_iscsi_rate),         4,       2,       2,     0,      10},
3080        // Demo will be removed later
3081        { _OFFSET(cmng_toe_con_number),     20,      20,      20,    0,      1024},
3082        { _OFFSET(cmng_rdma_con_number),    2,       2,       2,     0,      1024},
3083        { _OFFSET(cmng_iscsi_con_number),   40,      40,      40,    0,      1024},
3084        // iscsi
3085        { _OFFSET(l5sc_max_pending_tasks),      64,          64,      64,    64,     2048},
3086        // fcoe
3087        { _OFFSET(max_fcoe_task),           64,      64,      64,    0,     4096},
3088#if 0
3089        { _OFFSET(disable_patent_using),        1,       1,       1,     0,      1},
3090#else
3091        { _OFFSET(disable_patent_using),        0,       0,       0,     0,      1},
3092#endif
3093        { _OFFSET(l4_grq_filling_threshold_divider),    64,       64,       64,     2,      2048},
3094        { _OFFSET(l4_free_cid_delay_time),  2000,   10000,      10000,  0,  10000},
3095        { _OFFSET(preemphasis_enable),      0,       0,       0,     0,      1},
3096        { _OFFSET(preemphasis_rx_0),        0,       0,       0,     0,      0xffff},
3097        { _OFFSET(preemphasis_rx_1),        0,       0,       0,     0,      0xffff},
3098        { _OFFSET(preemphasis_rx_2),        0,       0,       0,     0,      0xffff},
3099        { _OFFSET(preemphasis_rx_3),        0,       0,       0,     0,      0xffff},
3100        { _OFFSET(preemphasis_tx_0),        0,       0,       0,     0,      0xffff},
3101        { _OFFSET(preemphasis_tx_1),        0,       0,       0,     0,      0xffff},
3102        { _OFFSET(preemphasis_tx_2),        0,       0,       0,     0,      0xffff},
3103        { _OFFSET(preemphasis_tx_3),        0,       0,       0,     0,      0xffff},
3104        { _OFFSET(disable_pcie_nfr),        0,       0,       0,     0,      1},
3105        { _OFFSET(debug_cap_flags),  0xffffffff,       0xffffffff,       0xffffffff,     0,      0xffffffff},
3106        { _OFFSET(try_not_align_page_multiplied_memory),     1,       1,       1,     0,      1},
3107        { _OFFSET(l4_limit_isles),          0,       0,       0,     0,      1},
3108        { _OFFSET(l4_max_rcv_wnd_size),     0x100000,0x100000,0x100000, 0,      0x1000000},
3109        { _OFFSET(ndsb_type),               1,       1,       1,     0,      2},
3110        { _OFFSET(l4_dominance_threshold),  10,      10,      10,     0,      0xFF},
3111        { _OFFSET(l4_max_dominance_value),  20,     20,      20,     0,      0xFF},
3112        { _OFFSET(l4_data_integrity),       0x0,     0x0,     0x0,   0x0,      0x3},
3113        { _OFFSET(l4_start_port),           5001,  5001,      5001,  0,      0xFFFFFFFF},
3114        { _OFFSET(l4_num_of_ports),         50,      50,      50,     0,      0xFFFF},
3115        { _OFFSET(l4_skip_start_bytes),     4,       4,       4,     0,      0xFFFFFFFF},
3116        { _OFFSET(phy_priority_mode),       PHY_PRIORITY_MODE_HW_DEF, PHY_PRIORITY_MODE_HW_DEF, PHY_PRIORITY_MODE_HW_DEF, PHY_PRIORITY_MODE_HW_DEF, PHY_PRIORITY_MODE_HW_PIN},
3117        { _OFFSET(grc_timeout_max_ignore),  0,       0,       0,     0,      0xFFFFFFFF},
3118        { _OFFSET(enable_error_recovery),   0,       0,       0,     0,      1},
3119        { _OFFSET(validate_sq_complete),    0,       0,       0,     0,      1},
3120        { _OFFSET(npar_vm_switching_enable),0,       0,       0,     0,      1},
3121        { _OFFSET(flow_control_reporting_mode),LM_FLOW_CONTROL_REPORTING_MODE_DISABLED,LM_FLOW_CONTROL_REPORTING_MODE_DISABLED,LM_FLOW_CONTROL_REPORTING_MODE_DISABLED,LM_FLOW_CONTROL_REPORTING_MODE_DISABLED,LM_FLOW_CONTROL_REPORTING_MODE_ENABLED},
3122        { _OFFSET(tpa_desc_cnt_per_chain),  0,       0,       0,     0,      0x10000},
3123        { _OFFSET(sriov_inc_mac),           0,       0,       0,     0,      64},
3124        { _OFFSET(e3_cos_modes),            0,       0,       0,     0,      1},
3125        { _OFFSET(e3_network_cos_mode),     0,       0,       0,     0,      1},
3126        { _OFFSET(fw_valid_mask),           0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0, 0xFFFFFFFF},
3127        { _OFFSET(record_sp),               0x0,     0x0,     0x0,   0,      0xf},
3128        { 0,                                0,       0,       0,     0,      0}
3129    }; // param_list
3130
3131    param_entry_t  *param               = NULL;
3132    size_t          csize               = 0;
3133    u32_t           flow_control        = 0;
3134    u8_t            i                   = 0;
3135    u8_t            port_base_aux_qzone = 0;
3136    u8_t            base_fw_qzone_id = 0;
3137    DbgMessage(pdev, INFORMi , "### lm_init_param\n");
3138    if (!validate)
3139    {
3140        /* Initialize the default parameters. */
3141        param = param_list;
3142        while(param->offset)
3143        {
3144            if(CHIP_REV_IS_FPGA(pdev))
3145            {
3146                SET_PARAM_VAL(pdev, param, param->fpga_default);
3147            }
3148            else if(CHIP_REV_IS_EMUL(pdev))
3149            {
3150                SET_PARAM_VAL(pdev, param, param->emulation_default);
3151            }
3152            else
3153            {
3154                SET_PARAM_VAL(pdev, param, param->asic_default);
3155            }
3156            param++;
3157        }
3158        pdev->params.rss_caps = (LM_RSS_CAP_IPV4 | LM_RSS_CAP_IPV6);
3159        pdev->params.rss_chain_cnt = 1;
3160        pdev->params.tss_chain_cnt = 1;
3161        if (IS_PFDEV(pdev))
3162        {
3163            pdev->params.sb_cnt = MAX_RSS_CHAINS / pdev->params.vnics_per_port;
3164            /* base non-default status block idx - 0 in E1. 0, 4, 8 or 12 in E1H */
3165            if (CHIP_IS_E1x(pdev))
3166            {
3167                pdev->params.max_pf_sb_cnt = pdev->params.fw_sb_cnt = HC_SB_MAX_SB_E1X / 2 / pdev->params.vnics_per_port;
3168                pdev->params.base_fw_ndsb = FUNC_ID(pdev) * pdev->params.fw_sb_cnt;
3169                if (CHIP_IS_E1(pdev)) {
3170                    pdev->params.fw_client_cnt = pdev->params.max_pf_fw_client_cnt = ETH_MAX_RX_CLIENTS_E1;
3171                } else {
3172                    pdev->params.fw_client_cnt = pdev->params.max_pf_fw_client_cnt = ETH_MAX_RX_CLIENTS_E1H / pdev->params.vnics_per_port;
3173                }
3174                pdev->params.base_fw_client_id = VNIC_ID(pdev) * pdev->params.fw_client_cnt;
3175            }
3176            else
3177            {
3178#ifdef _VBD_
3179//      pdev->params.sb_cnt = min(LM_IGU_SB_CNT(pdev), MAX_RSS_CHAINS);
3180        pdev->params.sb_cnt = LM_IGU_SB_CNT(pdev);
3181#endif
3182                if (pdev->params.sb_cnt > LM_IGU_SB_CNT(pdev)) {
3183                    pdev->params.sb_cnt = LM_IGU_SB_CNT(pdev);
3184                }
3185// Asymmetric resource division
3186#ifndef LM_NUM_DSBS
3187#define LM_NUM_DSBS 1
3188#endif
3189                if (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_4)
3190                {
3191                    pdev->params.base_fw_ndsb = IGU_BASE_NDSB(pdev) - (FUNC_ID(pdev) + 1)* LM_NUM_DSBS;
3192                    pdev->params.fw_aux_qzone_cnt = (ETH_MAX_RX_CLIENTS_E2 - PXP_REG_HST_ZONE_PERMISSION_TABLE_SIZE) / pdev->params.vnics_per_port / 2;
3193                    port_base_aux_qzone = PORT_ID(pdev)* ((ETH_MAX_RX_CLIENTS_E2 - PXP_REG_HST_ZONE_PERMISSION_TABLE_SIZE)/PORT_MAX);
3194                    pdev->params.aux_fw_qzone_id = PXP_REG_HST_ZONE_PERMISSION_TABLE_SIZE + port_base_aux_qzone + VNIC_ID(pdev) * pdev->params.fw_aux_qzone_cnt;
3195                    pdev->params.base_fw_client_id = pdev->params.base_fw_ndsb + FUNC_ID(pdev) * MAX_NON_RSS_FW_CLIENTS;
3196                }
3197                else
3198                {
3199                    pdev->params.base_fw_ndsb = IGU_BASE_NDSB(pdev) - (VNIC_ID(pdev) + 1) * LM_NUM_DSBS;
3200                    pdev->params.fw_aux_qzone_cnt = (ETH_MAX_RX_CLIENTS_E2 - PXP_REG_HST_ZONE_PERMISSION_TABLE_SIZE) / pdev->params.vnics_per_port;
3201                    pdev->params.aux_fw_qzone_id = PXP_REG_HST_ZONE_PERMISSION_TABLE_SIZE + VNIC_ID(pdev) * pdev->params.fw_aux_qzone_cnt;
3202                    pdev->params.base_fw_client_id = pdev->params.base_fw_ndsb + VNIC_ID(pdev) * MAX_NON_RSS_FW_CLIENTS;
3203                }
3204                pdev->params.fw_sb_cnt = LM_IGU_SB_CNT(pdev);
3205#ifdef VF_INVOLVED
3206                pdev->params.fw_sb_cnt = pdev->params.fw_sb_cnt + lm_pf_get_vf_available_igu_blocks(pdev);
3207                if ((VNICS_PER_PORT(pdev) == 1) && (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_2))
3208                {
3209                    pdev->params.fw_client_cnt = ETH_MAX_RX_CLIENTS_E2;
3210                }
3211                else
3212                {
3213                    pdev->params.fw_client_cnt = pdev->params.fw_sb_cnt + MAX_NON_RSS_FW_CLIENTS;
3214                }
3215#else
3216                pdev->params.fw_client_cnt = pdev->params.fw_sb_cnt + MAX_NON_RSS_FW_CLIENTS;
3217#endif
3218                pdev->params.fw_base_qzone_cnt = pdev->params.fw_sb_cnt;
3219                base_fw_qzone_id = pdev->params.base_fw_ndsb;
3220                pdev->params.max_pf_sb_cnt = LM_IGU_SB_CNT(pdev);
3221                pdev->params.max_pf_fw_client_cnt = pdev->params.max_pf_sb_cnt + MAX_NON_RSS_FW_CLIENTS;
3222            }
3223            DbgMessage(pdev, WARN, "SB counts(from %d): %d rss, %d max(pf), %d fw ndsbs accessible\n",
3224                        pdev->params.base_fw_ndsb, pdev->params.sb_cnt, pdev->params.max_pf_sb_cnt, pdev->params.fw_sb_cnt);
3225            DbgBreakIf(pdev->params.sb_cnt > pdev->params.max_pf_sb_cnt);
3226            DbgBreakIf(pdev->params.max_pf_sb_cnt > pdev->params.fw_sb_cnt);
3227
3228//            pdev->params.base_fw_client_id = VNIC_ID(pdev) * pdev->params.fw_client_cnt;
3229            DbgMessage(pdev, WARN, "FW clients (from %d): %d max(pf), %d fw cliens accessible\n",
3230                        pdev->params.base_fw_client_id, pdev->params.max_pf_fw_client_cnt, pdev->params.fw_client_cnt);
3231            if (CHIP_IS_E2E3(pdev)) {
3232                u8_t qz_idx;
3233                for (qz_idx = 0; qz_idx < pdev->params.fw_base_qzone_cnt; qz_idx++)
3234                {
3235                    pdev->params.fw_qzone_id[qz_idx] = base_fw_qzone_id + qz_idx;
3236
3237                }
3238                DbgMessage(pdev, WARN, "%d base FW Q zone IDs from %d\n", pdev->params.fw_base_qzone_cnt, base_fw_qzone_id);
3239                DbgMessage(pdev, WARN, "%d aux FW Q zone IDs from %d\n", pdev->params.fw_aux_qzone_cnt, pdev->params.aux_fw_qzone_id);
3240            }
3241//            pdev->params.base_fw_client_id = VNIC_ID(pdev) * (pdev->params.sb_cnt + MAX_NON_RSS_FW_CLIENTS);
3242            /* For now, base_fw_qzone_id == base_fw_client_id, but this doesn't have to be the case... */
3243            /* qzone-id is relevant only for E2 and therefore it is ok that we use a */
3244            /* Todo - change once E2 client is added. */
3245//            pdev->params.base_fw_qzone_id = pdev->params.base_fw_client_id + ETH_MAX_RX_CLIENTS_E1H*PORT_ID(pdev);
3246            /* E2 TODO: read how many sb each pf has...?? */
3247        } else if (IS_CHANNEL_VFDEV(pdev)) {
3248            pdev->params.sb_cnt = 16;
3249        } else {
3250            pdev->params.sb_cnt = 1;
3251        }
3252
3253        pdev->params.max_rss_chains = ((IS_PFDEV(pdev) && IGU_U_NDSB_OFFSET(pdev)) ? min(IGU_U_NDSB_OFFSET(pdev),LM_SB_CNT(pdev)) : LM_SB_CNT(pdev));
3254        if (pdev->params.max_rss_chains > MAX_RSS_CHAINS)
3255        {
3256        pdev->params.max_rss_chains = MAX_RSS_CHAINS;
3257        }
3258#ifndef EDIAG
3259        if(0 == pdev->params.max_rss_chains)
3260        {
3261            DbgBreakMsg("Zero isn't a valid value for pdev->params.max_rss_chains  ");
3262            return LM_STATUS_FAILURE;
3263        }
3264#endif
3265        pdev->params.base_cam_offset = 0;
3266        /* set the clients cids that will be used by the driver */
3267        pdev->params.map_client_to_cid[LM_CLI_IDX_NDIS]  = 0;
3268        pdev->params.map_client_to_cid[LM_CLI_IDX_ISCSI] = i = LM_MAX_RSS_CHAINS(pdev);
3269        pdev->params.map_client_to_cid[LM_CLI_IDX_OOO]   = ++i;
3270        pdev->params.map_client_to_cid[LM_CLI_IDX_FCOE]  = ++i;
3271        pdev->params.map_client_to_cid[LM_CLI_IDX_FWD]   = ++i;
3272    pdev->params.start_mp_chain = ++i;
3273
3274//        pdev->params.map_client_to_cid[LM_CLI_IDX_RDMA]  = ++i;
3275        // FCoE is not supported in E1 and we have only 18 clients in E1
3276        // so we OOO client gets 'priority' over FCoE
3277        DbgBreakIf(pdev->params.map_client_to_cid[LM_CLI_IDX_OOO] > pdev->params.map_client_to_cid[LM_CLI_IDX_FCOE]);
3278
3279        /* L4 RSS */
3280        pdev->params.l4_rss_chain_cnt = 1;
3281        pdev->params.l4_tss_chain_cnt = 1;
3282        /* set l4_rss base chain index to be the first one after l2 */
3283        pdev->params.l4_rss_base_chain_idx = 0;
3284        if (CHIP_IS_E1x(pdev))
3285        {
3286            pdev->params.l4_base_fw_rss_id = VNIC_ID(pdev) * pdev->params.sb_cnt;
3287   }
3288   else
3289        {
3290            pdev->params.l4_base_fw_rss_id = VNIC_ID(pdev);
3291        }
3292        /* master-pfdev needs to keep resources for its vfs, resource allocation is done first between
3293         * pfs and then each pf leaves itself 1 sb_cnt for enabling vfs. */
3294        pdev->params.eth_align_enable = 0;
3295        lm_init_cam_params(pdev);
3296
3297        if((CHIP_REV_IS_SLOW(pdev)
3298#ifdef DUMMY_MAC_FOR_VF
3299                || IS_VFDEV(pdev)
3300#endif
3301                )
3302                &&
3303                (!(GET_FLAGS(pdev->hw_info.mf_info.flags,MF_INFO_VALID_MAC))))
3304        {
3305            pdev->params.mac_addr[0] = pdev->hw_info.mac_addr[0] = 0x00;
3306            pdev->params.mac_addr[1] = pdev->hw_info.mac_addr[1] = 0x50;
3307            pdev->params.mac_addr[2] = pdev->hw_info.mac_addr[2] = 0xc2;
3308            pdev->params.mac_addr[3] = pdev->hw_info.mac_addr[3] = 0x2c;
3309            pdev->params.mac_addr[4] = pdev->hw_info.mac_addr[4] = 0x70 + (IS_PFDEV(pdev) ? 0 : (1 + 64*PATH_ID(pdev) + ABS_VFID(pdev)));
3310            if (CHIP_IS_E1x(pdev))
3311            {
3312                pdev->params.mac_addr[5] = pdev->hw_info.mac_addr[5] = 0x9a + 2 * FUNC_ID(pdev);
3313            }
3314            else
3315            {
3316                pdev->params.mac_addr[5] = pdev->hw_info.mac_addr[5] = 0x9a + PATH_ID(pdev)*8 + PORT_ID(pdev)*4 + VNIC_ID(pdev)*2;
3317            }
3318
3319            mm_memcpy(pdev->hw_info.iscsi_mac_addr, pdev->hw_info.mac_addr, 6);
3320            pdev->hw_info.iscsi_mac_addr[5]++;
3321            mm_memcpy(pdev->hw_info.fcoe_mac_addr, pdev->hw_info.iscsi_mac_addr, 6);
3322            pdev->hw_info.fcoe_mac_addr[5]++;
3323            lm_fcoe_set_default_wwns(pdev);
3324        }
3325        else
3326        {
3327            pdev->params.mac_addr[0] = pdev->hw_info.mac_addr[0];
3328            pdev->params.mac_addr[1] = pdev->hw_info.mac_addr[1];
3329            pdev->params.mac_addr[2] = pdev->hw_info.mac_addr[2];
3330            pdev->params.mac_addr[3] = pdev->hw_info.mac_addr[3];
3331            pdev->params.mac_addr[4] = pdev->hw_info.mac_addr[4];
3332            pdev->params.mac_addr[5] = pdev->hw_info.mac_addr[5];
3333        }
3334        if(CHIP_REV_IS_EMUL(pdev))
3335        {
3336            DbgMessage(pdev, INFORMi, "Emulation is detected.\n");
3337            pdev->params.test_mode |= TEST_MODE_IGNORE_SHMEM_SIGNATURE;
3338            pdev->params.test_mode |= TEST_MODE_LOG_REG_ACCESS;
3339            //pdev->params.test_mode |= TEST_MODE_NO_MCP;
3340            DbgMessage(pdev, INFORMi , "test mode is 0x%x \n",pdev->params.test_mode);
3341        }
3342        else
3343        {
3344            DbgMessage(pdev, INFORMi, "ASIC is detected.\n");
3345        }
3346        if (!pdev->hw_info.mcp_detected)
3347        {
3348            pdev->params.test_mode |= TEST_MODE_NO_MCP;
3349        }
3350        flow_control = (pdev->hw_info.link_config[ELINK_INT_PHY] & PORT_FEATURE_FLOW_CONTROL_MASK);
3351
3352        switch (flow_control)
3353        {
3354        case PORT_FEATURE_FLOW_CONTROL_AUTO:
3355            pdev->params.flow_ctrl_cap = LM_FLOW_CONTROL_AUTO_PAUSE;
3356        break;
3357        case PORT_FEATURE_FLOW_CONTROL_TX:
3358            pdev->params.flow_ctrl_cap = LM_FLOW_CONTROL_TRANSMIT_PAUSE;
3359        break;
3360        case PORT_FEATURE_FLOW_CONTROL_RX:
3361            pdev->params.flow_ctrl_cap = LM_FLOW_CONTROL_RECEIVE_PAUSE;
3362        break;
3363        case PORT_FEATURE_FLOW_CONTROL_BOTH:
3364            pdev->params.flow_ctrl_cap = LM_FLOW_CONTROL_TRANSMIT_PAUSE | LM_FLOW_CONTROL_RECEIVE_PAUSE;
3365        break;
3366        case PORT_FEATURE_FLOW_CONTROL_NONE:
3367            pdev->params.flow_ctrl_cap = LM_FLOW_CONTROL_NONE;
3368        break;
3369        default:
3370            pdev->params.flow_ctrl_cap = LM_FLOW_CONTROL_NONE;
3371        break;
3372        }
3373
3374        /*
3375         * We don't know (yet...) if the PHY supportes EEE - so we cannot set params
3376         * to reflect this info.
3377         */
3378
3379        /* L2 FW Flow control */
3380        // cq57766
3381        // if this static assert fails consider adding the new mode to the if
3382        // and read the l2_fw_flow_ctrl from the shmem in the new mode also
3383        ASSERT_STATIC(MAX_MF_MODE == 4);
3384        if ((pdev->hw_info.mf_info.mf_mode == SINGLE_FUNCTION) ||
3385            (pdev->hw_info.mf_info.mf_mode == MULTI_FUNCTION_SD) ||
3386            (CHIP_IS_E1x(pdev)))
3387        {
3388            // l2_fw_flow_ctrl is read from the shmem in multi-function mode in E2 and above.
3389            // In all other cases this parameter is read from the registry.
3390            // We read this parameter from the registry in E1.5 multi-function since 57711 boot code does not have the struct func_ext_cfg
3391            pdev->params.l2_fw_flow_ctrl = 0;
3392        }
3393        pdev->params.l4_fw_flow_ctrl = 0;
3394        pdev->params.fw_stats_init_value = TRUE;
3395
3396        pdev->params.mf_mode = pdev->hw_info.mf_info.mf_mode;
3397        if (pdev->params.mf_mode == MULTI_FUNCTION_SD)
3398        {
3399            pdev->params.sd_mode = pdev->hw_info.mf_info.sd_mode;
3400        }
3401
3402    }
3403    else
3404    {
3405        /* Make sure the parameter values are within range. */
3406        param = param_list;
3407        while(param->offset)
3408        {
3409            if(param->min != 0 || param->max != 0)
3410            {
3411                if(PARAM_VAL(pdev, param) < param->min ||
3412                    PARAM_VAL(pdev, param) > param->max)
3413                {
3414                    if(CHIP_REV_IS_FPGA(pdev))
3415                    {
3416                        SET_PARAM_VAL(pdev, param, param->fpga_default);
3417                    }
3418                    else if(CHIP_REV_IS_EMUL(pdev))
3419                    {
3420                        SET_PARAM_VAL(pdev, param, param->emulation_default);
3421                    }
3422                    else
3423                    {
3424                        SET_PARAM_VAL(pdev, param, param->asic_default);
3425                    }
3426                }
3427            }
3428            param++;
3429        }
3430        /* calculate context_line_size context_waste_size */
3431        // TODO calculate number of context lines in alocation page.
3432            csize = max(sizeof(struct eth_context),sizeof(struct toe_context));
3433            //csize = max(sizeof(struct rdma_context),csize);
3434            csize = max(sizeof(struct iscsi_context),csize);
3435            DbgBreakIf(csize>1024);
3436        /* Check for a valid mac address. */
3437        if((pdev->params.mac_addr[0] == 0 &&
3438            pdev->params.mac_addr[1] == 0 &&
3439            pdev->params.mac_addr[2] == 0 &&
3440            pdev->params.mac_addr[3] == 0 &&
3441            pdev->params.mac_addr[4] == 0 &&
3442            pdev->params.mac_addr[5] == 0) || (pdev->params.mac_addr[0] & 1))
3443        {
3444            DbgMessage(pdev, WARNi, "invalid MAC number.\n");
3445            pdev->params.mac_addr[0] = pdev->hw_info.mac_addr[0];
3446            pdev->params.mac_addr[1] = pdev->hw_info.mac_addr[1];
3447            pdev->params.mac_addr[2] = pdev->hw_info.mac_addr[2];
3448            pdev->params.mac_addr[3] = pdev->hw_info.mac_addr[3];
3449            pdev->params.mac_addr[4] = pdev->hw_info.mac_addr[4];
3450            pdev->params.mac_addr[5] = pdev->hw_info.mac_addr[5];
3451        }
3452        if (CHIP_IS_E1(pdev))
3453        {
3454            if ((pdev->params.l2_fw_flow_ctrl == 1) || (pdev->params.l4_fw_flow_ctrl == 1))
3455            {
3456                DbgMessage(pdev, WARNi, "L2 FW Flow control not supported on E1\n");
3457                pdev->params.l2_fw_flow_ctrl = 0;
3458                pdev->params.l4_fw_flow_ctrl = 0;
3459            }
3460        }
3461    }
3462
3463    /* init l2 client conn param with default mtu values */
3464    for (i = 0; i < ARRSIZE(pdev->params.l2_cli_con_params); i++)
3465    {
3466        lm_cli_idx_t lm_cli_idx = LM_CHAIN_IDX_CLI(pdev, i);
3467        ASSERT_STATIC( ARRSIZE(pdev->params.l2_rx_desc_cnt) == ARRSIZE(pdev->params.mtu));
3468        if(  lm_cli_idx >= ARRSIZE(pdev->params.l2_rx_desc_cnt))
3469        {
3470            // in case lm_cli_idx is above boundries
3471            // it means that is should not be used (currently expected in MF mode)
3472            // we skip the iteration
3473            continue;
3474        }
3475        pdev->params.l2_cli_con_params[i].mtu         = pdev->params.mtu[lm_cli_idx];
3476
3477        if(i < (LM_SB_CNT(pdev) + MAX_NON_RSS_CHAINS))
3478        {
3479            pdev->params.l2_cli_con_params[i].num_rx_desc = pdev->params.l2_rx_desc_cnt[lm_cli_idx];
3480            pdev->params.l2_cli_con_params[i].attributes  = LM_CLIENT_ATTRIBUTES_RX | LM_CLIENT_ATTRIBUTES_TX | LM_CLIENT_ATTRIBUTES_REG_CLI;
3481        }
3482        else
3483        {
3484            pdev->params.l2_cli_con_params[i].attributes  = LM_CLIENT_ATTRIBUTES_TX;
3485        }
3486    }
3487    return LM_STATUS_SUCCESS;
3488} /* lm_init_params */
3489
3490/*******************************************************************************
3491 * Description:
3492 *
3493 * Return:
3494 ******************************************************************************/
3495lm_status_t
3496lm_get_dev_info(
3497    lm_device_t *pdev)
3498{
3499    lm_status_t lm_status = LM_STATUS_SUCCESS;
3500
3501    DbgMessage(pdev, INFORMi , "### lm_get_dev_info\n");
3502
3503    // initialize "product_version" to 0xffffffff so all platforms will have invalid values (but Windows that will update it later)
3504    mm_memset( pdev->product_version, 0xff, sizeof(pdev->product_version) );
3505
3506    lm_status = lm_get_pcicfg_info(pdev);
3507    if(lm_status != LM_STATUS_SUCCESS)
3508    {
3509        return lm_status;
3510    }
3511
3512    lm_status = lm_get_bars_info(pdev);
3513    if(lm_status != LM_STATUS_SUCCESS)
3514    {
3515        return lm_status;
3516    }
3517    if (!IS_CHANNEL_VFDEV(pdev)) {
3518        lm_status = lm_get_chip_id_and_mode(pdev);
3519        if(lm_status != LM_STATUS_SUCCESS)
3520        {
3521            return lm_status;
3522        }
3523    }
3524    if (IS_PFDEV(pdev)) {
3525        // Get function num using me register
3526        lm_status = lm_get_function_num(pdev);
3527        if (lm_status != LM_STATUS_SUCCESS) {
3528            return lm_status;
3529        }
3530        // initialize pointers to init arrays (can only do this after we know which chip we are...)
3531        // We want to do this here to enable IRO access before driver load (ediag/lediag) this is only done
3532        // for PFs, VFs use PFDEV to access IRO
3533        if ( lm_set_init_arrs(pdev) != 0 ) {
3534            DbgMessage(pdev, FATAL, "Unknown chip revision\n");
3535            return LM_STATUS_UNKNOWN_ADAPTER;
3536        }
3537    } else {
3538            /* For VF, we also get the vf-id here... since we need it from configuration space */
3539#ifdef VF_INVOLVED
3540        if (IS_VFDEV(pdev))
3541        {
3542            lm_vf_get_vf_id(pdev);
3543        }
3544#endif
3545    }
3546
3547#ifdef __LINUX
3548    if (lm_is_function_after_flr(pdev))
3549    {
3550        if (IS_PFDEV(pdev)) {
3551            lm_status = lm_cleanup_after_flr(pdev);
3552            if(lm_status != LM_STATUS_SUCCESS)
3553            {
3554                return lm_status;
3555            }
3556        } else {
3557        /*  8.  Verify that the transaction-pending bit of each of the function in the Device Status Register in the PCIe is cleared. */
3558
3559#ifdef __LINUX
3560            u32_t pcie_caps_offset = mm_get_cap_offset(pdev, PCI_CAP_PCIE);
3561            if (pcie_caps_offset != 0 && pcie_caps_offset != 0xFFFFFFFF) {
3562                u32_t dev_control_and_status = 0xFFFFFFFF;
3563                mm_read_pci(pdev, pcie_caps_offset + PCIE_DEV_CTRL, &dev_control_and_status);
3564                DbgMessage(pdev, FATAL,"Device Control&Status of PCIe caps is %x\n",dev_control_and_status);
3565                if (dev_control_and_status & (PCIE_DEV_STATUS_PENDING_TRANSACTION << 16)) {
3566                    DbgBreak();
3567                }
3568            }
3569#else
3570            DbgMessage(pdev, FATAL, "Function mm_get_cap_offset is not implemented yet\n");
3571            DbgBreak();
3572#endif
3573            lm_fl_reset_clear_inprogress(pdev);
3574        }
3575    }
3576#endif
3577
3578    if (IS_CHANNEL_VIRT_MODE_MASTER_PFDEV(pdev)) {
3579        pdev->params.max_eth_including_vfs_conns = 1 << (LM_VF_MAX_RVFID_SIZE + LM_VF_CID_WND_SIZE(pdev) + 1);
3580    } else if (IS_PFDEV(pdev)) {
3581        pdev->params.max_eth_including_vfs_conns = MAX_VF_ETH_CONS;
3582        // Registry parameters are read in this stage.
3583        // As a result pdev->params.is_dcb_ndis_mp_en isn't valid yet.
3584        if(IS_DCB_SUPPORTED_BY_CHIP(pdev))
3585        {
3586            // Add DCB multiple connections
3587#ifdef _VBD_
3588            pdev->params.max_eth_including_vfs_conns += 3 * MAX_HW_CHAINS + MAX_NON_RSS_CHAINS;
3589#else
3590            pdev->params.max_eth_including_vfs_conns += MAX_ETH_CONS;
3591#endif
3592        }
3593        else
3594        {
3595#ifdef _VBD_
3596            pdev->params.max_eth_including_vfs_conns += MAX_ETH_REG_CHAINS;
3597#else
3598            pdev->params.max_eth_including_vfs_conns += MAX_ETH_REG_CONS;
3599#endif
3600        }
3601    }
3602    else
3603    {
3604        pdev->params.max_eth_including_vfs_conns = MAX_RSS_CHAINS;
3605    }
3606    if (IS_PFDEV(pdev)) {
3607        lm_status = lm_get_sriov_info(pdev);
3608        if (lm_status != LM_STATUS_SUCCESS) {
3609            return lm_status;
3610        }
3611        lm_status = lm_get_nvm_info(pdev);
3612        if (lm_status != LM_STATUS_SUCCESS) {
3613            return lm_status;
3614        }
3615        lm_status = lm_get_shmem_info(pdev);
3616        if (lm_status != LM_STATUS_SUCCESS) {
3617            return lm_status;
3618        }
3619
3620    } else if (IS_CHANNEL_VFDEV(pdev)) { //TODO check for basic vf
3621        pdev->hw_info.mf_info.multi_vnics_mode = 0;
3622        pdev->hw_info.mf_info.vnics_per_port   = 1;
3623        pdev->hw_info.mf_info.ext_id            = 0xffff; /* invalid ovlan */ /* TBD - E1H: - what is the right value for Cisco? */
3624        pdev->hw_info.mcp_detected = FALSE;
3625        pdev->hw_info.chip_id = CHIP_NUM_5712E;
3626        pdev->hw_info.max_port_conns =  log2_align(MAX_ETH_CONS);
3627        pdev->debug_info.ack_en[0] = 1;
3628    }
3629
3630#ifdef VF_INVOLVED
3631    if (IS_VFDEV(pdev)) {
3632        lm_vf_enable_vf(pdev);
3633    }
3634#endif
3635    pdev->ver_num =
3636        (LM_DRIVER_MAJOR_VER << 24) |
3637        (LM_DRIVER_MINOR_VER << 16) |
3638        (LM_DRIVER_FIX_NUM   << 8)  |
3639         LM_DRIVER_ENG_NUM ;
3640    mm_build_ver_string(pdev);
3641    // for debugging only (no other use)
3642    pdev->ver_num_fw = (BCM_5710_FW_MAJOR_VERSION << 24) |
3643                       (BCM_5710_FW_MINOR_VERSION << 16) |
3644                       (BCM_5710_FW_REVISION_VERSION<<8) |
3645                       (BCM_5710_FW_ENGINEERING_VERSION) ;
3646    /* get vnic parameters */
3647    pdev->params.vnics_per_port = pdev->hw_info.mf_info.vnics_per_port;
3648    pdev->params.ovlan = VALID_OVLAN(OVLAN(pdev)) ? OVLAN(pdev) : 0; // TBD: verify it's the right value (with OfirH)
3649    pdev->params.multi_vnics_mode = pdev->hw_info.mf_info.multi_vnics_mode;
3650    pdev->params.path_has_ovlan = pdev->hw_info.mf_info.path_has_ovlan;
3651
3652    if IS_MULTI_VNIC(pdev)
3653    {
3654        lm_cmng_calc_params(pdev);
3655    }
3656
3657    if (IS_PFDEV(pdev))
3658    {
3659        // clc params
3660        init_link_params(pdev);
3661    }
3662
3663    if (IS_CHANNEL_VFDEV(pdev))
3664    {
3665        pdev->hw_info.intr_blk_info.blk_type = INTR_BLK_IGU;
3666        pdev->hw_info.intr_blk_info.blk_mode = INTR_BLK_MODE_NORM;
3667        pdev->hw_info.intr_blk_info.access_type = INTR_BLK_ACCESS_IGUMEM;
3668    }
3669    else
3670    {
3671        lm_status = lm_get_intr_blk_info(pdev);
3672        if(lm_status != LM_STATUS_SUCCESS)
3673        {
3674            return lm_status;
3675        }
3676    }
3677
3678    lm_status = lm_init_params(pdev, 0);
3679    if(lm_status != LM_STATUS_SUCCESS)
3680    {
3681        return lm_status;
3682    }
3683
3684    lm_status = lm_mcp_cmd_init(pdev);
3685    if( LM_STATUS_SUCCESS != lm_status )
3686    {
3687        // Ediag may want to update the BC version. Don't fail lm_get_dev_info because of lm_mcp_cmd_init
3688        // in no condition.
3689        DbgMessage(pdev, FATAL, "lm_get_shmem_info: mcp_cmd_init failed. lm_status=0x%x\n", lm_status);
3690    }
3691
3692    if (CHIP_PORT_MODE(pdev) == LM_CHIP_PORT_MODE_4)
3693    {
3694        /* We're a single-function port on a mult-function path in a 4-port-mode environment... we need to support 1G */
3695        if (pdev->params.path_has_ovlan && !pdev->params.multi_vnics_mode)
3696        {
3697            DbgMessage(pdev, WARN, "func_id = %d Setting link speed to 1000MBPS\n", ABS_FUNC_ID(pdev));
3698            SET_MEDIUM_SPEED(pdev->params.req_medium, LM_MEDIUM_SPEED_1000MBPS);
3699        }
3700    }
3701
3702    /* Override the defaults with user configurations. */
3703    lm_status = mm_get_user_config(pdev);
3704    if(lm_status != LM_STATUS_SUCCESS)
3705    {
3706        return lm_status;
3707    }
3708    lm_status = lm_init_params(pdev, 1);
3709    if(lm_status != LM_STATUS_SUCCESS)
3710    {
3711        return lm_status;
3712    }
3713    DbgMessage(pdev, INFORMi , "### lm_get_dev_info exit\n");
3714    return LM_STATUS_SUCCESS;
3715} /* lm_get_dev_info */
3716
3717/*
3718 *Function Name: lm_get_port_id_from_func_abs
3719 *
3720 *Parameters:
3721 *
3722 *Description:
3723 *  returns the port ID according to the func_abs_id
3724 * E1/E1.5:
3725 * Port0: 0,2,4,6
3726 * Port1: 1,3,5,7
3727 *
3728 * E2/E32P
3729 * Port0: 0,1,2,3,4,5,6,7
3730 *
3731 * E34P
3732 * Port0: 0,1,4,5
3733 * Port1: 2,3,6,7
3734 *
3735 *Returns: u8_t port_id
3736 *
3737 */
3738u8_t lm_get_port_id_from_func_abs( const u32_t chip_num,  const lm_chip_port_mode_t lm_chip_port_mode, const u8_t abs_func )
3739{
3740    u8_t port_id     = 0xff;
3741    u8_t modulus_res = 0;
3742
3743    do
3744    {
3745        if( CHIP_IS_E1x_PARAM( chip_num ) )
3746        {
3747            port_id = abs_func % PORT_MAX;
3748            break;
3749        }
3750
3751        switch( lm_chip_port_mode )
3752        {
3753        case LM_CHIP_PORT_MODE_2:
3754            {
3755                // we expect here only E2 or E3
3756                DbgBreakIf( CHIP_IS_E1x_PARAM( chip_num ) );
3757                port_id = 0;
3758            }
3759            break;
3760
3761        case LM_CHIP_PORT_MODE_4:
3762            {
3763                modulus_res = abs_func % 4;
3764                switch (modulus_res)
3765                {
3766                case 0:
3767                case 1:
3768                    port_id = 0;
3769                    break;
3770                case 2:
3771                case 3:
3772                    port_id = 1;
3773                    break;
3774                default:
3775                    break;
3776                }
3777            }
3778            break;
3779
3780        default:
3781            DbgBreakIf(TRUE);
3782            break;
3783        } // switch lm_chip_port_mode
3784
3785    }while(0);
3786
3787    return port_id;
3788} /* lm_get_port_id_from_func_abs */
3789
3790/*
3791 *Function Name: lm_get_abs_func_vector
3792 *
3793 *Parameters:
3794 *
3795 *Description:
3796 *  returns vector of abs_func id's upon parameters
3797 *
3798 *Returns: u32_t abs_func_vector
3799 *
3800 */
3801u8_t lm_get_abs_func_vector( const u32_t chip_num,  const lm_chip_port_mode_t chip_port_mode, const u8_t b_multi_vnics_mode, const u8_t path_id )
3802{
3803    u8_t abs_func_vector = 0;
3804
3805    // TODO VF for T7.0
3806
3807/*
3808    The following table is mapping between abs func, ports and paths
3809
3810    |-----------------------------------------------|
3811    |[#]| CHIP & Mode | PATH(s) | Port(s) | Func(s) |
3812    |---|-------------|---------|---------|---------|
3813    |[1]| E1.0 (SF)   |   (0)   |   0,1   |  (0,1)  |
3814    |   | E1.5  SF    |         |   0,1   |  (0,1)  | (port is same as func)
3815    |---|-------------|---------|---------|---------|
3816    |[2]| E1.5 MF     |   (0)   |   0,1   |   0-7   | 0,1,2,3,4,5,6,7 (port is %2 of func)
3817    |---|-------------|---------|---------|---------|
3818    |[3]| E2/E32P SF  |   0,1   |   0     |   --->  | (Path 0) 0        | (Path 1) 1
3819    |---|-------------|---------|---------|---------|
3820    |[4]| E2/E32P MF  |   0,1   |   0     |   --->  | (Path 0) 0,2,4,6  | (Path 1) 1,3,5,7
3821    |---|-------------|---------|---------|---------|
3822    |[5]| E34P SF     |   0,1   |   0,1   |   --->  | (Path 0) 0:port0 2:port1     | (Path 1) 1:port0 3:port1
3823    |---|-------------|---------|---------|---------|
3824    |[6]| E34P MF     |   0,1   |   0,1   |   --->  | (Path 0) 0,4:port0 2,6:port1 | (Path 1) 1,5:port0 3,7:port1 (57840)
3825    |---|-------------|---------|---------|---------|
3826    |[7]| E34P MF/SF  |   0,1   |   0,1   |   --->  | (Path 0) 0,4:port0 2:port1   | (Path 1) 1,5:port0 3:port1 (57800)
3827    |---|-------------|---------|---------|---------|
3828*/
3829    do
3830    {
3831        // [1]
3832        if( CHIP_IS_E1x_PARAM(chip_num) && !b_multi_vnics_mode )
3833        {
3834            SET_BIT( abs_func_vector, 0 );
3835            SET_BIT( abs_func_vector, 1 );
3836            break;
3837        }
3838
3839        // [2]
3840        if( CHIP_IS_E1H_PARAM(chip_num) && b_multi_vnics_mode )
3841        {
3842            SET_BIT( abs_func_vector, 0 );
3843            SET_BIT( abs_func_vector, 1 );
3844            SET_BIT( abs_func_vector, 2 );
3845            SET_BIT( abs_func_vector, 3 );
3846            SET_BIT( abs_func_vector, 4 );
3847            SET_BIT( abs_func_vector, 5 );
3848            SET_BIT( abs_func_vector, 6 );
3849            SET_BIT( abs_func_vector, 7 );
3850            break;
3851        }
3852
3853        // If we got here chip should not be ealier than E2
3854        DbgBreakIf( CHIP_IS_E1x_PARAM(chip_num) );
3855
3856        // [3] [4] [5] [6]
3857        switch ( chip_port_mode )
3858        {
3859        case LM_CHIP_PORT_MODE_2:
3860            {
3861                // we expect here only E2 or E3
3862                DbgBreakIf( !CHIP_IS_E2_PARAM(chip_num) && !CHIP_IS_E3_PARAM(chip_num) );
3863
3864                if( b_multi_vnics_mode )
3865                {
3866                    // [4]
3867                    SET_BIT( abs_func_vector, (0 + path_id) );
3868                    SET_BIT( abs_func_vector, (2 + path_id) );
3869                    SET_BIT( abs_func_vector, (4 + path_id) );
3870                    SET_BIT( abs_func_vector, (6 + path_id) );
3871                    break;
3872                }
3873                else
3874                {
3875                    // [3]
3876                    SET_BIT( abs_func_vector, path_id );
3877                    break;
3878                }
3879            } // LM_CHIP_PORT_MODE_2
3880            break;
3881
3882
3883        case LM_CHIP_PORT_MODE_4:
3884            {
3885                if( b_multi_vnics_mode )
3886                {
3887                    // [6]
3888                    if (chip_num != CHIP_NUM_57800)
3889                    {
3890                        SET_BIT( abs_func_vector, (0 + path_id) );
3891                        SET_BIT( abs_func_vector, (2 + path_id) );
3892                        SET_BIT( abs_func_vector, (4 + path_id) );
3893                        SET_BIT( abs_func_vector, (6 + path_id) );
3894
3895                    }
3896                    // [7] In 57800 if we are multi function the other port can only be single function
3897                    else
3898                    {
3899                        SET_BIT( abs_func_vector, (0 + path_id) );
3900                        SET_BIT( abs_func_vector, (2 + path_id) );
3901                        SET_BIT( abs_func_vector, (4 + path_id) );
3902                    }
3903                    break;
3904                }
3905                else
3906                {
3907                    // [5]
3908                    if (chip_num != CHIP_NUM_57800)
3909                    {
3910                        SET_BIT( abs_func_vector, (0 + path_id) );
3911                        SET_BIT( abs_func_vector, (2 + path_id) );
3912                    }
3913                    // [7] We can't really know what's on the other port, so for this case where we are
3914                    //     in 57800 single function, we assume multi-function and access all the functions
3915                    //     so this might be case [5] but we can't know this.
3916                    else
3917                    {
3918                        SET_BIT( abs_func_vector, (0 + path_id) );
3919                        SET_BIT( abs_func_vector, (2 + path_id) );
3920                        SET_BIT( abs_func_vector, (4 + path_id) );
3921                    }
3922                    break;
3923                }
3924            } // LM_CHIP_PORT_MODE_4
3925            break;
3926
3927        default:
3928            {
3929                DbgBreakIf(TRUE);
3930                break;
3931            }
3932        } // CHIP_PORT_MODE
3933
3934    }while(0);
3935
3936    return abs_func_vector;
3937} /* lm_get_abs_func_vector */
3938
3939lm_status_t lm_verify_validity_map(lm_device_t *pdev)
3940{
3941    u64_t        wait_cnt       = 0 ;
3942    u64_t        wait_cnt_limit = 200000; // 4 seconds (ASIC)
3943    u32_t        val            = 0;
3944    lm_status_t  lm_status      = LM_STATUS_FAILURE ;
3945    if ( CHK_NULL(pdev) )
3946    {
3947        return LM_STATUS_INVALID_PARAMETER ;
3948    }
3949    wait_cnt_limit*= (u64_t)(pdev->vars.clk_factor) ;
3950    for(wait_cnt = 0; wait_cnt < wait_cnt_limit; wait_cnt++)
3951    {
3952        LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t, validity_map[PORT_ID(pdev)]),&val);
3953        // check that shared memory is valid.
3954        if((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) == (SHR_MEM_VALIDITY_DEV_INFO|SHR_MEM_VALIDITY_MB))
3955        {
3956            lm_status = LM_STATUS_SUCCESS ;
3957            break;
3958        }
3959        mm_wait(pdev, 20);
3960    }
3961    DbgMessage(pdev, INFORMi, "lm_verify_validity_map: shmem signature %d\n",val);
3962    return lm_status ;
3963}
3964
3965
3966lm_status_t
3967lm_set_cam_params(struct _lm_device_t * pdev,
3968                  u32_t mac_requestors_mask,
3969                  u32_t base_offset_in_cam_table,
3970                  u32_t cam_size,
3971                  u32_t mma_size,
3972                  u32_t mc_size)
3973{
3974    lm_status_t lm_status =  LM_STATUS_SUCCESS;
3975    if (IS_VFDEV(pdev)) {
3976        return LM_STATUS_FAILURE;
3977    }
3978    if (base_offset_in_cam_table != LM_KEEP_CURRENT_CAM_VALUE) {
3979        pdev->params.base_offset_in_cam_table = (u8_t)base_offset_in_cam_table;
3980    }
3981    if (cam_size != LM_KEEP_CURRENT_CAM_VALUE) {
3982        pdev->params.cam_size = (u8_t)cam_size;
3983    }
3984    if (mc_size != LM_KEEP_CURRENT_CAM_VALUE) {
3985        if (CHIP_IS_E1(pdev)) {
3986            pdev->params.mc_table_size[LM_CLI_IDX_NDIS]  =(u8_t) mc_size;
3987        } else {
3988            pdev->params.mc_table_size[LM_CLI_IDX_FCOE]  = (u8_t)mc_size;
3989        }
3990    }
3991
3992    return lm_status;
3993} /* lm_set_cam_params */
3994
3995/*******************************************************************************
3996 * Description:
3997 *
3998 * Return:
3999 ******************************************************************************/
4000void lm_cmng_calc_params(lm_device_t* pdev )
4001{
4002    u8_t vnic = 0;
4003    DbgBreakIf(!IS_MULTI_VNIC(pdev));
4004    for (vnic = 0; vnic < MAX_VNIC_NUM; vnic++)
4005    {
4006        if (GET_FLAGS(pdev->hw_info.mf_info.func_mf_cfg , FUNC_MF_CFG_FUNC_HIDE))
4007        {
4008            pdev->params.min_bw[vnic] = 0;
4009            pdev->params.max_bw[vnic] = 0;
4010        }
4011        else
4012        {
4013            pdev->params.min_bw[vnic] = pdev->hw_info.mf_info.min_bw[vnic];
4014            pdev->params.max_bw[vnic] = pdev->hw_info.mf_info.max_bw[vnic];
4015        }
4016    }
4017} /* lm_cmng_calc_params */
4018
4019/**
4020 * @description
4021 * Calculates BW according to current linespeed and MF
4022 * configuration  of the function in Mbps.
4023 * @param pdev
4024 * @param link_speed - Port rate in Mbps.
4025 * @param vnic
4026 *
4027 * @return u16
4028 * Return the max BW of the function in Mbps.
4029 */
4030u16_t
4031lm_get_max_bw(IN const lm_device_t  *pdev,
4032              IN const u32_t        link_speed,
4033              IN const u8_t         vnic)
4034{
4035    u16_t  max_bw   = 0;
4036
4037    DbgBreakIf(0 == IS_MULTI_VNIC(pdev));
4038
4039    //global vnic counter
4040    if(IS_MF_SD_MODE(pdev) || IS_MF_AFEX_MODE(pdev))
4041    {
4042        // SD max BW in 100Mbps
4043        max_bw = pdev->params.max_bw[vnic]*100;
4044    }
4045    else
4046    {
4047        // SI max BW in percentage from the link speed.
4048        DbgBreakIf(FALSE == IS_MF_SI_MODE(pdev));
4049        max_bw = (link_speed * pdev->params.max_bw[vnic])/100;
4050    }
4051    return max_bw;
4052}
4053
4054u8_t lm_check_if_pf_assigned_to_vm(struct _lm_device_t *pdev)
4055{
4056    u8_t b_assigned_to_vm = FALSE;
4057
4058    switch (pdev->hw_info.pci_cfg_trust)
4059    {
4060        case PCI_CFG_NOT_TESTED_FOR_TRUST:
4061            break;
4062        case PCI_CFG_NOT_TRUSTED:
4063            b_assigned_to_vm = TRUE;
4064            break;
4065        case PCI_CFG_TRUSTED:
4066            b_assigned_to_vm = FALSE;
4067            break;
4068    }
4069    return b_assigned_to_vm;
4070}
4071
4072u8_t lm_is_fw_version_valid(struct _lm_device_t *pdev)
4073{
4074    u8_t is_fw_valid = FALSE;
4075    u32_t drv_fw_ver = (BCM_5710_FW_MAJOR_VERSION) |
4076                       (BCM_5710_FW_MINOR_VERSION << 8) |
4077                       (BCM_5710_FW_REVISION_VERSION << 16) |
4078                       (BCM_5710_FW_ENGINEERING_VERSION  << 24) ;
4079    u32_t real_fw_ver = REG_RD(pdev,0x2c0000); /* Read acitve FW version from 1st DWORD of XSTORM params*/
4080    u32_t fw_valid_mask;
4081
4082    fw_valid_mask = SWAP_BYTES32(pdev->params.fw_valid_mask);
4083    is_fw_valid = (((drv_fw_ver ^ real_fw_ver) & fw_valid_mask) == 0);
4084    return (is_fw_valid);
4085}
4086
4087/*
4088 * Support for NSCI get OS driver version CQ70040
4089 */
4090
4091/*Descripion: Write the client driver version
4092*              to the shmem2 region
4093*/
4094lm_status_t
4095lm_set_cli_drv_ver_to_shmem(struct _lm_device_t *pdev)
4096{
4097    u32_t               drv_ver_offset      = OFFSETOF(shmem2_region_t,func_os_drv_ver);
4098    u32_t               offset              = 0;
4099    lm_status_t         lm_status           = LM_STATUS_SUCCESS; //  Status is always SUCCESS now
4100    u32_t               shmem2_size         = 0;
4101    u32_t               index               = 0;
4102
4103    if (IS_VFDEV(pdev))
4104    {
4105        return LM_STATUS_SUCCESS;
4106    }
4107
4108    ASSERT_STATIC( sizeof(pdev->lm_cli_drv_ver_to_shmem.cli_drv_ver) == sizeof(struct os_drv_ver) );
4109
4110    offset = drv_ver_offset + (pdev->params.pfunc_mb_id * sizeof(pdev->lm_cli_drv_ver_to_shmem.cli_drv_ver));
4111
4112    DbgMessage(pdev, WARN,"offset= %d \n", offset);
4113
4114    if (pdev->hw_info.shmem_base2 != 0)
4115    {
4116        LM_SHMEM2_READ (pdev, OFFSETOF(shmem2_region_t,size), &shmem2_size);
4117        if (shmem2_size > offset)
4118        {
4119            for (index = 0; index < ARRSIZE(pdev->lm_cli_drv_ver_to_shmem.cli_drv_ver.versions); index++)
4120            {
4121                LM_SHMEM2_WRITE(pdev, offset, pdev->lm_cli_drv_ver_to_shmem.cli_drv_ver.versions[index]);
4122                offset+= sizeof( pdev->lm_cli_drv_ver_to_shmem.cli_drv_ver.versions[index] );
4123            }
4124        }
4125    }
4126
4127   return lm_status;
4128}
4129
4130u8_t lm_is_mac_locally_administrated(struct _lm_device_t    *pdev, u8_t * mac)
4131{
4132    u8_t res = FALSE;
4133    if (mac != NULL)
4134    {
4135        res = (mac[0] != pdev->params.mac_addr[0]) ||
4136              (mac[1] != pdev->params.mac_addr[1]) ||
4137              (mac[2] != pdev->params.mac_addr[2]) ||
4138              (mac[3] != pdev->params.mac_addr[3]) ||
4139              (mac[4] != pdev->params.mac_addr[4]) ||
4140              (mac[5] != pdev->params.mac_addr[5]);
4141    }
4142    return res;
4143}
4144