openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

sw_an.c (31769B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  * SW AN thread is an optional feature to support 
      7  * consortium AN mode on devices using PM4x25 D0. THis module is responsible for 
      8  * driving the Page exchange An state machine as recomennded by IEEE802.3by/MSA spec
      9  * Once the page exchange is completed and speed is resolved HW will take over and complete
     10  * the Autoneg.  
     11  */
     12 
     13 #include <shared/bsl.h>
     14 #ifdef SW_AUTONEG_SUPPORT 
     15 
     16 #include <sal/types.h>
     17 #include <shared/alloc.h>
     18 #include <sal/core/spl.h>
     19 #include <soc/drv.h>
     20 
     21 #include <bcm/error.h>
     22 #include <bcm/port.h>
     23 #include <bcm_int/esw/port.h>
     24 #include <bcm_int/common/sw_an.h>
     25 
     26 #include <soc/phy/phymod_ctrl.h>
     27 #include <soc/phy/phyctrl.h>
     28 
     29 #include <sal/appl/io.h>
     30 
     31 #ifdef PORTMOD_SUPPORT
     32 #include <soc/portmod/portmod.h>
     33 #include <soc/portmod/portmod_common.h>
     34 #include <soc/esw/portctrl.h>
     35 #include <bcm_int/esw/portctrl.h>
     36 
     37 #define PORT_MAX_PHY_ACCESS_STRUCTURES (6)
     38 #endif
     39 
     40 /*
     41  * SW AN Port context
     42  */
     43 
     44 typedef struct _sw_an_port_ctxt_s {
     45     bcm_port_sw_an_event_t    an_event;
     46     phymod_sw_an_ctxt_t       phymod_sw_an_ctxt;
     47     int                       an_retry;
     48     uint32_t                  an_state;
     49 #ifdef PORTMOD_SUPPORT
     50     phymod_phy_access_t       phy_access[PORT_MAX_PHY_ACCESS_STRUCTURES];
     51 #endif
     52 } _sw_an_port_ctxt_t;
     53 
     54 /*
     55  * AW AN module context structure
     56  */
     57 typedef struct _sw_autoneg_ctxt_s {
     58 	int                     enable; /* enable SW AN Thread */ 
     59     sal_mutex_t	  		    lock; /* lock to access the port bitmap */
     60 	sal_sem_t       		signal_event; /* semaphore to signal new event to AN thread */
     61 	sal_thread_t	  		thread_id; /* Therad id */
     62 	char                    thread_name[SAL_THREAD_NAME_MAX_LEN]; 
     63 	pbmp_t          		add_ports; /* bitmap of ports that are part of the SW AN */
     64 	pbmp_t                  process_ports; /* list of ports currently serviced by SW AN */
     65 	_sw_an_port_ctxt_t      port_sw_an_ctxt[SOC_MAX_NUM_PORTS]; /* per port SW AN context */
     66 	uint32_t                polling_interval; /* AN thread polling intervakl in msec */
     67 } _sw_autoneg_ctxt_t;
     68 
     69 /* static alocation of SW AN CTXT for all units */
     70 _sw_autoneg_ctxt_t    *_sw_autoneg_ctxt[BCM_LOCAL_UNITS_MAX];
     71 
     72 #define SW_AN_CTXT(unit)    (_sw_autoneg_ctxt[unit])
     73 
     74 typedef enum _sw_an_page_exchange_sm_cmd_e {
     75 	SW_AN_PAGE_EXCHANGE_SM_CMD_STOP = 0,
     76 	SW_AN_PAGE_EXCHANGE_SM_CMD_START,
     77 	SW_AN_PAGE_EXCHANGE_SM_CMD_MAX
     78 } _sw_an_page_exchange_sm_cmd_t;
     79 
     80 /*
     81  * Define:
     82  *     SW_AN_LOCK/SW_AN_UNLOCK
     83  * Purpose:
     84  *     Serialization Macros for access to _sw_autoneg_ctxt_t structure.
     85  */
     86 
     87 #define SW_AN_LOCK(unit) \
     88         sal_mutex_take(_sw_autoneg_ctxt[unit]->lock, sal_mutex_FOREVER)
     89 
     90 #define SW_AN_UNLOCK(unit) \
     91         sal_mutex_give(_sw_autoneg_ctxt[unit]->lock)
     92 
     93 #define SW_AN_WAIT_FOR_EVENT(unit) \
     94 		sal_sem_take(_sw_autoneg_ctxt[unit]->signal_event, sal_sem_FOREVER)
     95 
     96 #define SW_AN_POST_EVENT(unit) \
     97 		sal_sem_give(_sw_autoneg_ctxt[unit]->signal_event)		        
     98 
     99 #define UNIT_VALID_CHECK(unit) \
    100     if (((unit) < 0) || ((unit) >= BCM_LOCAL_UNITS_MAX)) { return BCM_E_UNIT; }
    101 
    102 #define UNIT_INIT_CHECK(unit) \
    103     do { \
    104         UNIT_VALID_CHECK(unit); \
    105         if (_sw_autoneg_ctxt[unit] == NULL) { return BCM_E_INIT; } \
    106     } while (0)
    107 
    108 
    109 #define SW_AN_THREAD_PRIORITY 50 /* 0 the highest and 255 the lowest*/
    110 #define SW_AN_NUM_PAGES_TO_TX 0x3 
    111 
    112 #define SW_AN_POLLING_INTERVAL 50
    113 
    114 static int _bcm_sw_an_page_exchange_sm(int unit, bcm_port_t port, bcm_sw_an_fsm_event_t event);
    115 int _bcm_sw_an_event_get(int unit, bcm_port_t port, bcm_sw_an_fsm_event_t *event);
    116 phymod_phy_access_t * _bcm_sw_an_phy_access_get(int unit, bcm_port_t port);
    117 
    118 int 
    119 bcm_sw_an_module_deinit(int unit) 
    120 {
    121     _sw_autoneg_ctxt_t    *sw_an_ctxt;
    122 
    123 	UNIT_VALID_CHECK(unit);
    124 
    125 	sw_an_ctxt = SW_AN_CTXT(unit);
    126 
    127 	if (sw_an_ctxt == NULL) {
    128 		return BCM_E_NONE;
    129 	}
    130 
    131 	if (sw_an_ctxt->signal_event != NULL) {
    132 		sal_sem_destroy(sw_an_ctxt->signal_event);
    133 		sw_an_ctxt->signal_event = NULL;
    134 	}
    135 
    136 	if (sw_an_ctxt->lock != NULL) {
    137 		sal_mutex_destroy(sw_an_ctxt->lock);
    138 	}
    139 
    140     /* sal_thread_destroy is supported only with netbsd
    141      * thread is should be NULL once we reach this 
    142      * function. Incase if we delete a thread while its holding lock
    143      * we may have unpredicatble behaviour in non linux machines  
    144      */
    145     if (sw_an_ctxt->thread_id != NULL) {
    146     	sal_thread_destroy(sw_an_ctxt->thread_id);
    147     }
    148 	sal_free(sw_an_ctxt);
    149 
    150 	SW_AN_CTXT(unit) = NULL;
    151 
    152 	return BCM_E_NONE;
    153 }
    154 
    155 int 
    156 bcm_sw_an_module_init(int unit) 
    157 {
    158 	_sw_autoneg_ctxt_t    *sw_an_ctxt;
    159 	uint32                size;
    160 	uint32                polling_interval;
    161 	int                   rv = BCM_E_NONE;
    162 
    163 
    164 	UNIT_VALID_CHECK(unit);
    165 
    166 	if (SW_AN_CTXT(unit) != NULL) {
    167 		/* free the allocated resource */
    168 		rv = bcm_sw_an_module_deinit(unit);
    169 		if (rv < BCM_E_NONE) {
    170 			return rv;
    171 		}
    172 	}
    173 
    174 	size = sizeof(_sw_autoneg_ctxt_t);
    175 	if ((sw_an_ctxt = sal_alloc(size, "sw_an_module")) == NULL) {
    176 		return BCM_E_MEMORY;
    177 	}
    178 	sal_memset(sw_an_ctxt, 0, size);
    179 
    180 	/* initalize the mutex and semaphore */
    181 	sw_an_ctxt->lock = sal_mutex_create("SW_AN_LOCK");
    182 	if (sw_an_ctxt->lock == NULL) {
    183 		rv = BCM_E_MEMORY;
    184 	}
    185 
    186 	if (BCM_SUCCESS(rv)) {
    187 		sw_an_ctxt->signal_event = sal_sem_create("SW_AN_signal_event",
    188 												  sal_sem_BINARY,
    189 											      0);
    190 		if (sw_an_ctxt->signal_event == NULL) {
    191 			sal_mutex_destroy(sw_an_ctxt->lock);
    192 			rv = BCM_E_MEMORY;
    193 		}
    194 	}
    195 
    196 	if (BCM_FAILURE(rv)) {
    197 		sal_free(sw_an_ctxt);
    198 	}
    199 
    200 	/* initialize the port bitmap */
    201 	BCM_PBMP_CLEAR(sw_an_ctxt->add_ports);
    202 	BCM_PBMP_CLEAR(sw_an_ctxt->process_ports);
    203 
    204 	sw_an_ctxt->thread_id = NULL;
    205 
    206 	polling_interval = SW_AN_POLLING_INTERVAL;
    207 	polling_interval = soc_property_get(unit, spn_SW_AUTONEG_POLLING_INTERVAL, 
    208 						polling_interval);
    209 
    210 	sw_an_ctxt->polling_interval = polling_interval;
    211 
    212     _sw_autoneg_ctxt[unit] = sw_an_ctxt;
    213 
    214     return BCM_E_NONE;
    215 }
    216 
    217 /* Run the through each port in the bit map and if they are
    218  * scheduled to run service that port 
    219  */
    220 STATIC void
    221 _bcm_sw_an_thread(int unit) 
    222 {
    223 	_sw_autoneg_ctxt_t    *sw_an_ctxt;
    224 	_sw_an_port_ctxt_t    *port_an_ctxt;
    225 	bcm_sw_an_fsm_event_t event; 
    226     bcm_port_t     		  port;
    227     int                   rv = BCM_E_NONE;
    228     int                   is_process = 0;
    229 
    230     sw_an_ctxt = SW_AN_CTXT(unit);
    231     if (sw_an_ctxt == NULL) {
    232   	    sal_thread_exit(0);
    233   	    return;
    234     }
    235 
    236     sw_an_ctxt->thread_id = sal_thread_self();
    237 
    238     while(sw_an_ctxt->enable) {
    239     	SW_AN_LOCK(unit);
    240     	SOC_PBMP_ASSIGN(sw_an_ctxt->process_ports,
    241     					sw_an_ctxt->add_ports);
    242     	SW_AN_UNLOCK(unit);
    243     	/* run through the port bitmap */
    244     	do 
    245     	{
    246     		is_process = 0;
    247 	    	PBMP_ITER(sw_an_ctxt->process_ports, port) {
    248 	    		/* check if the port needs to be serviced */
    249 	    		port_an_ctxt = &(sw_an_ctxt->port_sw_an_ctxt[port]);
    250 	    		if (port_an_ctxt->an_event != BCM_PORT_SW_AN_EVENT_AN_STOP) {
    251 	    			is_process = 1;
    252 		    		switch(port_an_ctxt->an_event) {
    253 		    			case BCM_PORT_SW_AN_EVENT_AN_START:
    254 		  				    PORT_LOCK(unit);
    255 		    				rv = _bcm_sw_an_page_exchange_sm(unit, port, BCM_FSM_SW_AN_EVT_START);
    256 		   				    PORT_UNLOCK(unit);
    257 		    				if (rv < BCM_E_NONE) {
    258 		    					SW_AN_LOCK(unit);
    259 		    					port_an_ctxt->an_event = BCM_PORT_SW_AN_EVENT_AN_DOWN;
    260 		    					SW_AN_UNLOCK(unit);
    261 		    					/* log error */
    262 		    				}
    263 		    				break;
    264 						case BCM_PORT_SW_AN_EVENT_AN_RESTART:
    265 						case BCM_PORT_SW_AN_EVENT_AN_LINK_DOWN: 
    266 							/* update the an retry count */
    267 							port_an_ctxt->an_retry++;
    268 							PORT_LOCK(unit);
    269 							rv = _bcm_sw_an_page_exchange_sm(unit, port, BCM_FSM_SW_AN_EVT_SEND_RESTART);
    270 		   				    PORT_UNLOCK(unit);
    271 							if (rv < BCM_E_NONE) {
    272 								SW_AN_LOCK(unit);
    273 		    					port_an_ctxt->an_event = BCM_PORT_SW_AN_EVENT_AN_DOWN;
    274 		    					SW_AN_UNLOCK(unit);
    275 								/* log error */
    276 							}
    277 							break;
    278 						case BCM_PORT_SW_AN_EVENT_AN_IN_PROCESS:
    279 							PORT_LOCK(unit);
    280 							_bcm_sw_an_event_get(unit, port, &event);
    281 							rv = _bcm_sw_an_page_exchange_sm(unit, port, event);
    282 		   				    PORT_UNLOCK(unit);
    283 							if (rv < BCM_E_NONE) {
    284 								SW_AN_LOCK(unit);
    285 		    					port_an_ctxt->an_event = BCM_PORT_SW_AN_EVENT_AN_DOWN;
    286 		    					SW_AN_UNLOCK(unit);
    287 								/* log error */
    288 							}
    289 							break;
    290 						case BCM_PORT_SW_AN_EVENT_AN_STOP:
    291 							break;
    292 						default:
    293 							break;		    				
    294 		    		}
    295 	    		}
    296     		}
    297     		sal_msleep(sw_an_ctxt->polling_interval); 
    298     		SW_AN_LOCK(unit);
    299     		SOC_PBMP_ASSIGN(sw_an_ctxt->process_ports,
    300     					sw_an_ctxt->add_ports);
    301     		SW_AN_UNLOCK(unit);
    302     	} while(is_process);
    303 
    304     	/* wait on a semaphore */
    305     	SW_AN_WAIT_FOR_EVENT(unit);
    306     }
    307 
    308     sw_an_ctxt->thread_id = NULL;
    309     sal_thread_exit(0);
    310     return;
    311 }
    312 
    313 
    314 
    315 int 
    316 bcm_sw_an_enable_set(int unit, int enable) 
    317 {
    318 	_sw_autoneg_ctxt_t   *sw_an_ctxt = NULL;
    319 	int 				 rv          = BCM_E_NONE;
    320 	soc_timeout_t   	 to;
    321 	sal_usecs_t          wait_usec;
    322 
    323 	/* Time to wait for thread to start/end (longer for BCMSIM) */
    324     wait_usec = (SAL_BOOT_BCMSIM || SAL_BOOT_QUICKTURN) ? 30000000 : 10000000;
    325 
    326     UNIT_INIT_CHECK(unit);
    327 
    328     sw_an_ctxt = SW_AN_CTXT(unit);
    329 
    330     if (enable) {
    331 
    332     	if (sw_an_ctxt->thread_id != NULL) {
    333     		/* wakeup the SW AN thread */
    334     		SW_AN_POST_EVENT(unit);
    335     		return BCM_E_NONE;
    336     	}
    337 
    338     	sw_an_ctxt->enable = enable;
    339 
    340 		sal_snprintf(sw_an_ctxt->thread_name,
    341 	                 sizeof (sw_an_ctxt->thread_name),
    342 	                 "SW_AN.%0x",
    343 	                 unit);
    344 
    345 		if (sal_thread_create(sw_an_ctxt->thread_name,
    346                               SAL_THREAD_STKSZ,
    347                               SW_AN_THREAD_PRIORITY,
    348                               (void (*)(void*))_bcm_sw_an_thread,
    349                               INT_TO_PTR(unit)) == SAL_THREAD_ERROR) {
    350 			rv = BCM_E_MEMORY;
    351 		} else {
    352 			/* wait for the timeout period to expire to 
    353 			 * check if the thread creation is successful
    354 			 */
    355 			soc_timeout_init(&to, wait_usec, 0);
    356 
    357 			while(sw_an_ctxt->thread_id == NULL) {
    358 				if ((soc_timeout_check(&to))) {
    359 					LOG_ERROR(BSL_LS_BCM_PORT,
    360                               (BSL_META_U(unit,
    361                                           "%s: Thread did not start\n"),
    362                                			  sw_an_ctxt->thread_name));
    363                     rv = BCM_E_INTERNAL;
    364                     break;
    365 				}
    366 			}
    367 
    368 		}
    369     } else {
    370     	/* set the enable flag to 0 and wait for the 
    371     	 * the thread to exit
    372     	 */
    373     	sw_an_ctxt->enable = enable; 
    374 
    375     }   
    376     return rv;
    377 }
    378 
    379 int 
    380 bcm_sw_an_enable_get(int unit, int *enable) 
    381 {
    382 	_sw_autoneg_ctxt_t   *sw_an_ctxt = NULL;
    383 
    384 	UNIT_INIT_CHECK(unit);
    385 
    386     sw_an_ctxt = SW_AN_CTXT(unit);
    387 
    388     *enable = sw_an_ctxt->enable;
    389 
    390     return BCM_E_NONE;
    391 }
    392 
    393 int 
    394 bcm_sw_an_post_event(int unit, bcm_port_t port, bcm_port_sw_an_event_t event) 
    395 {
    396 	_sw_autoneg_ctxt_t    *sw_an_ctxt;
    397 	_sw_an_port_ctxt_t    *port_an_ctxt;
    398 
    399     UNIT_INIT_CHECK(unit);
    400 
    401     if (event <= BCM_PORT_SW_AN_EVENT_NONE ||
    402     	event >= BCM_PORT_SW_AN_EVENT_AN_MAX)  {
    403     	/* nothing to notify the thread */
    404     	return BCM_E_NONE;
    405     }
    406 
    407     sw_an_ctxt = SW_AN_CTXT(unit);
    408 
    409     if (!SOC_PBMP_MEMBER(sw_an_ctxt->add_ports, port)) {
    410     	/* given port is not part of SW AN process thread 
    411     	 * nothing to notify
    412     	 */
    413     	return BCM_E_NONE; 
    414     }
    415 
    416     port_an_ctxt = &(sw_an_ctxt->port_sw_an_ctxt[port]);
    417 
    418     SW_AN_LOCK(unit);
    419     port_an_ctxt->an_event = event;
    420     SW_AN_UNLOCK(unit);
    421 
    422     /* notify the SW AN thread */
    423     SW_AN_POST_EVENT(unit);
    424 
    425     return BCM_E_NONE;
    426 }
    427 
    428 int
    429 bcm_sw_an_port_register(int unit, bcm_port_t port) 
    430 {
    431 	_sw_autoneg_ctxt_t    *sw_an_ctxt;
    432     int                   enable = 0;
    433     int                   rv = BCM_E_NONE;
    434 
    435 	UNIT_INIT_CHECK(unit);
    436 
    437 	sw_an_ctxt = SW_AN_CTXT(unit);
    438 
    439     if (!SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port) || 
    440     	!SOC_PORT_VALID(unit, port) || !IS_PORT(unit, port)) {
    441     	return BCM_E_PORT;
    442 	}
    443 
    444 	 /* if AN Thread is not enabled enable the AN thread */
    445     rv = bcm_sw_an_enable_get(unit, &enable);
    446     if (rv != BCM_E_NONE) {
    447     	return rv;
    448     }
    449 
    450     if (!enable) {
    451     	rv = bcm_sw_an_enable_set(unit, 1);	
    452     	if (rv != BCM_E_NONE) {
    453     		return rv;
    454     	}
    455     }
    456 
    457     if (!SOC_PBMP_MEMBER(sw_an_ctxt->add_ports, port)) {
    458 		SW_AN_LOCK(unit);
    459 		BCM_PBMP_PORT_ADD(sw_an_ctxt->add_ports, port);
    460 		SW_AN_UNLOCK(unit);
    461 
    462 	    rv = bcm_sw_an_post_event(unit, port, BCM_PORT_SW_AN_EVENT_AN_START);
    463 	    return rv;
    464 	} else {
    465 		/* SW AN is already enabled for this port  restart SW AN */
    466 		rv = bcm_sw_an_post_event(unit, port, BCM_PORT_SW_AN_EVENT_AN_RESTART);
    467 	}
    468 
    469 	return BCM_E_NONE;	
    470 }
    471 
    472 int
    473 bcm_sw_an_port_unregister(int unit, bcm_port_t port) 
    474 {
    475 	_sw_autoneg_ctxt_t    *sw_an_ctxt;
    476 	phymod_phy_access_t   *phy = NULL;
    477 
    478 	UNIT_INIT_CHECK(unit);
    479 
    480 	sw_an_ctxt = SW_AN_CTXT(unit);
    481 
    482     if (!SOC_PBMP_MEMBER(sw_an_ctxt->add_ports, port) || 
    483     	!SOC_PORT_VALID(unit, port) || !IS_PORT(unit, port)) {
    484     	return BCM_E_PORT;
    485 	}
    486 	
    487 	SW_AN_LOCK(unit);
    488 	BCM_PBMP_PORT_REMOVE(sw_an_ctxt->add_ports, port);
    489 	SW_AN_UNLOCK(unit);
    490 
    491 	phy = _bcm_sw_an_phy_access_get(unit, port);
    492 	if (NULL == phy) {
    493 		return BCM_E_INTERNAL;
    494 	}
    495 
    496 	PHYMOD_IF_ERR_RETURN
    497 		(phymod_phy_sw_autoneg_enable(phy, 0));
    498 
    499 	return BCM_E_NONE;	
    500 }
    501 
    502 #ifdef PORTMOD_SUPPORT
    503 phymod_phy_access_t *
    504 _bcm_sw_an_portmod_phy_access_get(int unit, bcm_port_t port) {
    505     _sw_autoneg_ctxt_t    *sw_an_ctxt;
    506     pm_info_t pm_info;
    507     int chain_length = 0;
    508     portmod_dispatch_type_t __type__;
    509     int rv = 0;
    510 
    511 
    512     sw_an_ctxt = SW_AN_CTXT(unit);
    513 
    514     rv = portmod_port_pm_type_get(unit, port, &port, &__type__);
    515     if (rv != BCM_E_NONE) {
    516         return NULL;
    517     }
    518 
    519     rv = portmod_pm_info_get(unit, port, &pm_info);
    520     if (rv != BCM_E_NONE) {
    521         return NULL;
    522     }
    523 
    524     rv = portmod_port_chain_phy_access_get(unit, port, pm_info, sw_an_ctxt->port_sw_an_ctxt[port].phy_access,
    525                                            PORT_MAX_PHY_ACCESS_STRUCTURES,
    526                                            &chain_length);
    527 
    528     if (rv != BCM_E_NONE) {
    529         return NULL;
    530     }
    531 
    532     return &(sw_an_ctxt->port_sw_an_ctxt[port].phy_access[0]);
    533 }
    534 #endif
    535 
    536 phymod_phy_access_t *
    537 _bcm_sw_an_phy_access_get(int unit, bcm_port_t port) 
    538 {
    539 	phy_ctrl_t                *pc;
    540     soc_phymod_ctrl_t         *pmc;
    541     soc_phymod_phy_t          *phy;
    542 
    543 
    544     if (SOC_USE_PORTCTRL(unit)) {
    545         return _bcm_sw_an_portmod_phy_access_get(unit, port);
    546     }
    547 
    548     /* locate phy control */
    549     pc = INT_PHY_SW_STATE(unit, port);
    550     if (pc == NULL) {
    551         return NULL;
    552     }
    553 
    554     pmc = &pc->phymod_ctrl;
    555 
    556     /* only request autoneg on the first core */
    557     phy = pmc->phy[0];
    558     if (phy == NULL) {
    559         return NULL;
    560     }
    561 
    562     return (&phy->pm_phy);
    563 }
    564 
    565 int
    566 _bcm_sw_an_event_get(int unit, bcm_port_t port, bcm_sw_an_fsm_event_t *event) 
    567 {
    568 	phymod_sw_an_ctrl_status_t		an_ctrl_status;
    569 	phymod_phy_access_t             *phy = NULL;
    570 
    571 	phymod_sw_an_ctrl_status_t_init(&an_ctrl_status);
    572 	phy = _bcm_sw_an_phy_access_get(unit, port);
    573 	if (NULL == phy) {
    574 		return BCM_E_INTERNAL;
    575 	}
    576 	/* call the phymod API to get the event*/
    577 	PHYMOD_IF_ERR_RETURN
    578 		(phymod_phy_sw_an_control_status_get(phy, &an_ctrl_status));
    579 
    580 	*event = BCM_FSM_SW_AN_EVT_WAIT;
    581 
    582 	if (an_ctrl_status.seq_restart) {
    583 		/* not handled */
    584 	} else if (an_ctrl_status.page_req) {
    585 		/* handled as part of lp_page_rdy*/
    586 	} else if (an_ctrl_status.lp_page_rdy) {
    587 		*event = BCM_FSM_SW_AN_EVT_LP_PAGE_RDY;
    588 	} else if (an_ctrl_status.an_completed) {
    589 		*event = BCM_FSM_SW_AN_EVT_PAGE_EX_COMPLETE;
    590 	} else {
    591 		/* do nothing */
    592 	}
    593 	return BCM_E_NONE;
    594 }
    595 
    596 int
    597 _bcm_sw_an_page_exchange_sm(int unit, bcm_port_t port, bcm_sw_an_fsm_event_t event) 
    598 {
    599 	_sw_autoneg_ctxt_t    			 *sw_an_ctxt;
    600 	_sw_an_port_ctxt_t               *port_an_ctxt;
    601 	phymod_sw_an_ctxt_t              *phymod_an_ctxt;
    602 	phymod_phy_access_t              *phy;
    603 	int                              rv; 
    604 
    605 	UNIT_INIT_CHECK(unit);
    606 
    607 	sw_an_ctxt = SW_AN_CTXT(unit);
    608 	rv    = BCM_E_NONE;
    609 
    610 	phy = _bcm_sw_an_phy_access_get(unit, port);
    611     if (NULL == phy) {
    612     	return BCM_E_INTERNAL;
    613     }
    614 
    615     port_an_ctxt = &(sw_an_ctxt->port_sw_an_ctxt[port]);
    616     phymod_an_ctxt = &port_an_ctxt->phymod_sw_an_ctxt;
    617 
    618     port_an_ctxt->an_state |= 0x1 << event;
    619 
    620 	switch(event) {
    621 		case BCM_FSM_SW_AN_EVT_START:
    622 		    phymod_an_ctxt->tx_pages_cnt = 0;
    623 			phymod_an_ctxt->rx_pages_cnt = 0;
    624 			phymod_an_ctxt->no_pages_to_be_txed = SW_AN_NUM_PAGES_TO_TX;
    625 			PHYMOD_IF_ERR_RETURN
    626 				(phymod_phy_sw_an_base_page_exchange_handler(phy, phymod_an_ctxt));
    627 			bcm_sw_an_post_event(unit, port, BCM_PORT_SW_AN_EVENT_AN_IN_PROCESS);	
    628 			break;
    629 		case BCM_FSM_SW_AN_EVT_SEND_RESTART:
    630 			phymod_an_ctxt->tx_pages_cnt = 0;
    631 			phymod_an_ctxt->rx_pages_cnt = 0;
    632 			phymod_an_ctxt->no_pages_to_be_txed = SW_AN_NUM_PAGES_TO_TX;
    633 			/* Diable the SW AN to toggle SW AN bit */
    634 			PHYMOD_IF_ERR_RETURN
    635 				(phymod_phy_sw_autoneg_enable(phy, 0));
    636 			PHYMOD_IF_ERR_RETURN
    637 				(phymod_phy_sw_an_base_page_exchange_handler(phy, phymod_an_ctxt));
    638 			bcm_sw_an_post_event(unit, port, BCM_PORT_SW_AN_EVENT_AN_IN_PROCESS);
    639 			break;
    640 		case BCM_FSM_SW_AN_EVT_LP_PAGE_RDY:
    641 			PHYMOD_IF_ERR_RETURN
    642 				(phymod_phy_sw_an_lp_page_rdy_handler(phy, phymod_an_ctxt));
    643 			bcm_sw_an_post_event(unit, port, BCM_PORT_SW_AN_EVENT_AN_IN_PROCESS);	
    644 			break;
    645 		case BCM_FSM_SW_AN_EVT_LD_PAGE:
    646 			/* do nothing */
    647 			break;
    648 		case BCM_FSM_SW_AN_EVT_PAGE_EX_COMPLETE:
    649 				bcm_sw_an_post_event(unit, port, BCM_PORT_SW_AN_EVENT_AN_STOP);
    650 			break;
    651 		case BCM_FSM_SW_AN_EVT_WAIT:
    652 			bcm_sw_an_post_event(unit, port, BCM_PORT_SW_AN_EVENT_AN_IN_PROCESS);
    653 			break;	
    654 		default:
    655 			break;					
    656 	}
    657     return rv;
    658 }
    659 
    660 int
    661 bcm_sw_an_ability_advert_set(int unit, soc_port_t port,
    662                                  soc_port_ability_t *ability)
    663 {
    664     int                       port_num_lanes;
    665     bcm_port_if_t             line_interface;
    666     uint32_t                  an_tech_ability;
    667     uint32_t                  an_bam37_ability;
    668     uint32_t                  an_bam73_ability;
    669     _shr_port_mode_t          speed_full_duplex;
    670     phymod_autoneg_ability_t  phymod_autoneg_ability;
    671     int                       rv = BCM_E_NONE;
    672     uint8_t                   sw_an_mode = 0;
    673 
    674     port_num_lanes = SOC_INFO(unit).port_num_lanes[port];
    675     rv = bcmi_esw_portctrl_interface_get(unit, port, &line_interface);
    676     if (rv != BCM_E_NONE) {
    677         return rv;
    678     }
    679 
    680     an_tech_ability  = 0;
    681     an_bam37_ability = 0;
    682     an_bam73_ability = 0;
    683     speed_full_duplex = ability->speed_full_duplex;
    684 
    685     PHYMOD_IF_ERR_RETURN
    686         (phymod_autoneg_ability_t_init(&phymod_autoneg_ability));
    687 
    688     sw_an_mode = soc_property_port_get(unit, port,
    689                       spn_PHY_AN_C73, sw_an_mode);
    690 
    691     if (port_num_lanes == 4) {
    692         if (speed_full_duplex & SOC_PA_SPEED_100GB) {
    693             if (ability->medium & SOC_PA_MEDIUM_BACKPLANE) {
    694                 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability);
    695             } else if (ability->medium & SOC_PA_MEDIUM_COPPER) {
    696                 PHYMOD_AN_CAP_100G_CR4_SET(an_tech_ability);
    697             } else {
    698                 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability);
    699             }
    700         }
    701         if (speed_full_duplex & SOC_PA_SPEED_40GB) {
    702             if (ability->medium & SOC_PA_MEDIUM_BACKPLANE) {
    703                 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability);
    704             } else if (ability->medium & SOC_PA_MEDIUM_COPPER) {
    705                 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability);
    706             } else {
    707                 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability);
    708             }
    709         }
    710     } else if (port_num_lanes == 2) {
    711         /* Supports only 50G in SW AN */
    712         if(speed_full_duplex & SOC_PA_SPEED_50GB) {
    713             /* need to fix CR2 bit shift issue */
    714             if (ability->medium & SOC_PA_MEDIUM_BACKPLANE) {
    715                 PHYMOD_BAM_CL73_CAP_50G_KR2_SET(an_bam73_ability);
    716             } else if (ability->medium & SOC_PA_MEDIUM_COPPER) {
    717                 PHYMOD_BAM_CL73_CAP_50G_CR2_SET(an_bam73_ability);
    718             } else {
    719                 PHYMOD_BAM_CL73_CAP_50G_KR2_SET(an_bam73_ability);
    720             }
    721         }
    722     } else {
    723         if(speed_full_duplex & SOC_PA_SPEED_25GB) {
    724             if (ability->medium & SOC_PA_MEDIUM_BACKPLANE) {
    725                 if (sw_an_mode != SW_AN_MODE_MSA_ONLY) {
    726                       if (ability->channel & SOC_PA_CHANNEL_SHORT) {
    727                          PHYMOD_AN_CAP_25G_KRS1_SET(an_tech_ability);
    728                       } else {
    729                            PHYMOD_AN_CAP_25G_KR1_SET(an_tech_ability);
    730                       }
    731                 }
    732                 PHYMOD_BAM_CL73_CAP_25G_KR1_SET(an_bam73_ability);
    733             } else if (ability->medium & SOC_PA_MEDIUM_COPPER) {
    734                 if (sw_an_mode != SW_AN_MODE_MSA_ONLY) {
    735                         if (ability->channel & SOC_PA_CHANNEL_SHORT) {
    736                             PHYMOD_AN_CAP_25G_CRS1_SET(an_tech_ability);
    737                         } else {
    738                             PHYMOD_AN_CAP_25G_CR1_SET(an_tech_ability);
    739                         }
    740                 }
    741                 PHYMOD_BAM_CL73_CAP_25G_CR1_SET(an_bam73_ability);
    742             } else {
    743                 if (sw_an_mode != SW_AN_MODE_MSA_ONLY) {
    744                       if (ability->channel & SOC_PA_CHANNEL_SHORT) {
    745                          PHYMOD_AN_CAP_25G_KRS1_SET(an_tech_ability);
    746                       } else {
    747                            PHYMOD_AN_CAP_25G_KR1_SET(an_tech_ability);
    748                       }
    749                 }
    750                 PHYMOD_BAM_CL73_CAP_25G_KR1_SET(an_bam73_ability);
    751             }
    752         }
    753         if (speed_full_duplex & SOC_PA_SPEED_10GB) {
    754             PHYMOD_AN_CAP_10G_KR_SET(an_tech_ability);
    755         }
    756     }
    757 
    758     phymod_autoneg_ability.an_cap = an_tech_ability;
    759     phymod_autoneg_ability.cl73bam_cap = an_bam73_ability;
    760     phymod_autoneg_ability.cl37bam_cap = an_bam37_ability;
    761     phymod_autoneg_ability.sgmii_speed = 0;
    762 
    763     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
    764     case SOC_PA_PAUSE_TX:
    765         PHYMOD_AN_CAP_ASYM_PAUSE_SET(&phymod_autoneg_ability);
    766         break;
    767     case SOC_PA_PAUSE_RX:
    768         /* an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; */
    769         PHYMOD_AN_CAP_ASYM_PAUSE_SET(&phymod_autoneg_ability);
    770         PHYMOD_AN_CAP_SYMM_PAUSE_SET(&phymod_autoneg_ability);
    771         break;
    772     case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
    773         PHYMOD_AN_CAP_SYMM_PAUSE_SET(&phymod_autoneg_ability);
    774         break;
    775     }
    776 
    777     phymod_autoneg_ability.an_cl72 = 1;
    778 
    779 
    780     /*next need to check FEC ability */
    781     if (ability->fec == SOC_PA_FEC_NONE) {
    782         PHYMOD_AN_FEC_OFF_SET(phymod_autoneg_ability.an_fec);
    783     } else {
    784         if (ability->fec & SOC_PA_FEC_CL74)
    785             PHYMOD_AN_FEC_CL74_SET(phymod_autoneg_ability.an_fec);
    786         if (ability->fec & SOC_PA_FEC_CL91)
    787             PHYMOD_AN_FEC_CL91_SET(phymod_autoneg_ability.an_fec);
    788     }
    789 
    790     rv = bcm_sw_an_advert_set(unit, port, &phymod_autoneg_ability);
    791 
    792     return rv;
    793 
    794 }
    795 
    796 int 
    797 bcm_sw_an_advert_set(int unit, bcm_port_t port, phymod_autoneg_ability_t *ability) 
    798 {
    799 	_sw_autoneg_ctxt_t    			 *sw_an_ctxt;
    800 	phymod_sw_an_ctxt_t              *phymod_an_ctxt;
    801 	phymod_phy_access_t              *phy;
    802 	uint8_t                          sw_an_mode = 0;
    803 
    804 	UNIT_INIT_CHECK(unit);
    805 
    806 	phy = _bcm_sw_an_phy_access_get(unit, port);
    807     if (NULL == phy) {
    808     	return BCM_E_INTERNAL;
    809     }
    810 
    811 	sw_an_ctxt = SW_AN_CTXT(unit);
    812 	phymod_an_ctxt = &(sw_an_ctxt->port_sw_an_ctxt[port].phymod_sw_an_ctxt);
    813 
    814 	sw_an_mode = soc_property_port_get(unit, port,
    815                        spn_PHY_AN_C73, sw_an_mode);
    816 
    817 	switch(sw_an_mode) {
    818 		case SW_AN_MODE_CL73_MSA:
    819 			SW_AN_LOCK(unit);
    820 			phymod_an_ctxt->an_mode = phymod_AN_MODE_CL73_MSA;
    821 			SW_AN_UNLOCK(unit);
    822 			break;
    823 		case SW_AN_MODE_MSA_ONLY:
    824 			SW_AN_LOCK(unit);
    825 			phymod_an_ctxt->an_mode = phymod_AN_MODE_MSA;
    826 			SW_AN_UNLOCK(unit);
    827 			break;
    828 		default:
    829 			/* Ideally we should not hit this case*/
    830 			SW_AN_LOCK(unit);
    831 			phymod_an_ctxt->an_mode = phymod_AN_MODE_CL73_MSA;
    832 			SW_AN_UNLOCK(unit);
    833 			break;
    834 	}
    835 
    836 	PHYMOD_IF_ERR_RETURN
    837 		(phymod_phy_sw_an_advert_set(phy, ability, phymod_an_ctxt));
    838 
    839 	return BCM_E_NONE;	
    840 }
    841 
    842 int
    843 _bcm_sw_an_ability_get(const phymod_an_pages_t *an_pages, soc_port_ability_t *portAbility)
    844 {
    845     uint16_t            ability = 0, pause_cap = 0;
    846     _shr_port_mode_t    spd_fd = 0;
    847     uint32_t            msa_code_13_23 = 0, msa_code_2_12 = 0, msa_code_0_1 =0;
    848     uint16_t            msa_mode = 0;
    849 
    850     portAbility->channel = SOC_PA_CHANNEL_LONG;
    851     portAbility->medium = SOC_PA_MEDIUM_BACKPLANE;
    852     portAbility->fec = 0;
    853     portAbility->pause = 0;
    854 
    855     /* Get PAUSE ability */
    856     ability = an_pages->base_page.page_0;
    857     pause_cap = (ability >>  SW_AN_BASE0_PAGE_CAP_OFFSET) & SW_AN_BASE0_PAGE_CAP_MASK;
    858     if (pause_cap == 3) {
    859         portAbility->pause = SOC_PA_PAUSE_RX;
    860     } else if (pause_cap == 2) {
    861         portAbility->pause = SOC_PA_PAUSE_TX;
    862     } else if (pause_cap == 1) {
    863         portAbility->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
    864     }
    865 
    866     /* Get CL73 speed ability */
    867     ability = an_pages->base_page.page_1;
    868     if ((ability >> SW_AN_BASE_TECH_ABILITY_25GKR_OFFSET) & SW_AN_BASE_TECH_ABILITY_25GKR_MASK) {
    869         spd_fd|= SOC_PA_SPEED_25GB;
    870     }
    871     if ((ability >> SW_AN_BASE_TECH_ABILITY_25GKRS_OFFSET) & SW_AN_BASE_TECH_ABILITY_25GKRS_MASK) {
    872         spd_fd|= SOC_PA_SPEED_25GB;
    873         portAbility->channel = SOC_PA_CHANNEL_SHORT;
    874     }
    875     if ((ability >> SW_AN_BASE_TECH_ABILITY_10GKR_OFFSET) & SW_AN_BASE_TECH_ABILITY_10GKR_MASK) {
    876         spd_fd|= SOC_PA_SPEED_10GB;
    877     }
    878 
    879     /* Get CL73 FEC ability */
    880     ability = an_pages->base_page.page_2;
    881     if ((ability >> SW_AN_BASE_CL91_ABILITY_REQ_OFFSET) & SW_AN_BASE_CL91_ABILITY_REQ_MASK) {
    882         portAbility->fec |= SOC_PA_FEC_CL91;
    883     }
    884     if ((ability >> SW_AN_BASE_CL74_25GKRS_REQ_OFFSET) & SW_AN_BASE_CL74_25GKRS_REQ_MASK) {
    885         portAbility->fec |= SOC_PA_FEC_CL74;
    886     }
    887     if ((ability >> SW_AN_BASE_CL74_ABILITY_REQ_OFFSET) & SW_AN_BASE_CL74_ABILITY_REQ_MASK) {
    888         portAbility->fec |= SOC_PA_FEC_CL74;
    889     }
    890 
    891     msa_code_13_23 = ((an_pages->msg_page.page_1 >> SW_AN_MSG_PAGE1_OUI_13to23_OFFSET) &
    892                       SW_AN_MSG_PAGE1_OUI_13to23_MASK);
    893     msa_code_2_12 = ((an_pages->msg_page.page_2 >> SW_AN_MSG_PAGE2_OUI_2to12_OFFSET) &
    894                       SW_AN_MSG_PAGE2_OUI_2to12_MASK);
    895     msa_code_0_1  = ((an_pages->ufmt_page.page_0 >> SW_AN_UF_PAGE0_OUI_OFFSET) &
    896                       SW_AN_UF_PAGE0_OUI_MASK);
    897     msa_mode = ((an_pages->base_page.page_0 >> SW_AN_BASE0_PAGE_NP_OFFSET) & SW_AN_BASE0_PAGE_NP_MASK);
    898 
    899     /* Check MSA ability if applicable */
    900     if ((msa_mode) && (msa_code_0_1 == SW_AN_MSA_OUI_0to1) &&
    901         (msa_code_13_23 == SW_AN_MSA_OUI_13to23) && (msa_code_2_12  == SW_AN_MSA_OUI_2to12)) {
    902         ability = an_pages->ufmt_page.page_1;
    903         if ((ability >> SW_AN_UF_PAGE1_50G_KR2_ABILITY_OFFSET) & SW_AN_UF_PAGE1_50G_KR2_ABILITY_MASK) {
    904             spd_fd|= SOC_PA_SPEED_50GB;
    905         }
    906         if ((ability >> SW_AN_UF_PAGE1_50G_CR2_ABILITY_OFFSET) & SW_AN_UF_PAGE1_50G_CR2_ABILITY_MASK) {
    907             spd_fd|= SOC_PA_SPEED_50GB;
    908             portAbility->medium = SOC_PA_MEDIUM_COPPER;
    909         }
    910         if ((ability >> SW_AN_UF_PAGE1_25G_KR1_ABILITY_OFFSET) & SW_AN_UF_PAGE1_25G_KR1_ABILITY_MASK) {
    911             spd_fd|= SOC_PA_SPEED_25GB;
    912         }
    913         if ((ability >> SW_AN_UF_PAGE1_25G_CR1_ABILITY_OFFSET) & SW_AN_UF_PAGE1_25G_CR1_ABILITY_MASK) {
    914             spd_fd|= SOC_PA_SPEED_25GB;
    915             portAbility->medium = SOC_PA_MEDIUM_COPPER;
    916         }
    917         ability = an_pages->ufmt_page.page_2;
    918         if ((ability >> SW_AN_UF_PAGE2_CL91_REQ_OFFSET) & SW_AN_UF_PAGE2_CL91_REQ_MASK) {
    919             portAbility->fec |= SOC_PA_FEC_CL91;
    920         }
    921         if ((ability >> SW_AN_UF_PAGE2_CL74_REQ_OFFSET) & SW_AN_UF_PAGE2_CL74_REQ_MASK) {
    922             portAbility->fec |= SOC_PA_FEC_CL74;
    923         }
    924     }
    925     portAbility->speed_full_duplex = spd_fd;
    926 
    927     /* If there's no FEC ability, set FEC_NONE */
    928     if (portAbility->fec == 0) {
    929         portAbility->fec = SOC_PA_FEC_NONE;
    930     }
    931 
    932     return BCM_E_NONE;
    933 }
    934 
    935 
    936 int
    937 bcm_sw_an_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *portAbility)
    938 {
    939     _sw_autoneg_ctxt_t        *sw_an_ctxt;
    940     phymod_sw_an_ctxt_t       *phymod_an_ctxt;
    941     phymod_an_pages_t         *an_pages;
    942     int                       rv = 0;
    943 
    944     UNIT_INIT_CHECK(unit);
    945 
    946     sw_an_ctxt = SW_AN_CTXT(unit);
    947     phymod_an_ctxt = &(sw_an_ctxt->port_sw_an_ctxt[port].phymod_sw_an_ctxt);
    948     an_pages = &phymod_an_ctxt->tx_pages;
    949 
    950     rv = _bcm_sw_an_ability_get(an_pages, portAbility);
    951 
    952     return rv;
    953 }
    954 
    955 int
    956 bcm_sw_an_ability_remote_get(int unit, soc_port_t port, soc_port_ability_t *portAbility)
    957 {
    958     _sw_autoneg_ctxt_t        *sw_an_ctxt;
    959     phymod_sw_an_ctxt_t       *phymod_an_ctxt;
    960     phymod_an_pages_t         *an_pages;
    961     int                       rv = 0;
    962 
    963     UNIT_INIT_CHECK(unit);
    964 
    965     sw_an_ctxt = SW_AN_CTXT(unit);
    966     phymod_an_ctxt = &(sw_an_ctxt->port_sw_an_ctxt[port].phymod_sw_an_ctxt);
    967     an_pages = &phymod_an_ctxt->rx_pages;
    968 
    969     rv = _bcm_sw_an_ability_get(an_pages, portAbility);
    970 
    971     return rv;
    972 }
    973 
    974 int
    975 bcm_sw_an_port_diag(int unit, int port) 
    976 {
    977 	_sw_autoneg_ctxt_t    			 *sw_an_ctxt;
    978 	phymod_sw_an_ctxt_t              *phymod_an_ctxt;
    979 	_sw_an_port_ctxt_t               *port_an_ctxt;
    980 
    981 	UNIT_INIT_CHECK(unit);
    982 
    983 	sw_an_ctxt = SW_AN_CTXT(unit);
    984 	phymod_an_ctxt = &(sw_an_ctxt->port_sw_an_ctxt[port].phymod_sw_an_ctxt);
    985 	port_an_ctxt = &(sw_an_ctxt->port_sw_an_ctxt[port]);
    986 
    987     sal_printf("********** SW AN CONTEXT INFORMATION FOR THE UNIT:%0x PORT:%0x **********\n", unit, port);
    988     sal_printf("PORT SW AN STATE:        \t %0x\n", port_an_ctxt->an_state);
    989     sal_printf("PORT SW AN TX PAGES:     \t %0x\n", phymod_an_ctxt->tx_pages_cnt);
    990     sal_printf("PORT SW AN RX PAGES:     \t %0x\n", phymod_an_ctxt->rx_pages_cnt);
    991     
    992     sal_printf("PORT SW AN TX BASE PAGE: \t (48-32):%0x (31-16):%0x (15-0):%0x\n", 
    993     	phymod_an_ctxt->tx_pages.base_page.page_2, phymod_an_ctxt->tx_pages.base_page.page_1, 
    994     	phymod_an_ctxt->tx_pages.base_page.page_0);
    995         sal_printf("PORT SW AN TX MSG PAGE:  \t (48-32):%0x (31-16):%0x (15-0):%0x\n", 
    996     	phymod_an_ctxt->tx_pages.msg_page.page_2, phymod_an_ctxt->tx_pages.msg_page.page_1, 
    997     	phymod_an_ctxt->tx_pages.msg_page.page_0);
    998     sal_printf("PORT SW AN TX UP PAGE:   \t (48-32):%0x (31-16):%0x (15-0):%0x\n", 
    999     	phymod_an_ctxt->tx_pages.ufmt_page.page_2, phymod_an_ctxt->tx_pages.ufmt_page.page_1, 
   1000     	phymod_an_ctxt->tx_pages.ufmt_page.page_0);
   1001 
   1002     sal_printf("PORT SW AN RX BASE PAGE: \t (48-32):%0x (31-16):%0x (15-0):%0x\n", 
   1003     	phymod_an_ctxt->rx_pages.base_page.page_2, phymod_an_ctxt->rx_pages.base_page.page_1, 
   1004     	phymod_an_ctxt->rx_pages.base_page.page_0);
   1005     sal_printf("PORT SW AN RX MSG PAGE:  \t (48-32):%0x (31-16):%0x (15-0):%0x\n", 
   1006     	phymod_an_ctxt->rx_pages.msg_page.page_2, phymod_an_ctxt->rx_pages.msg_page.page_1, 
   1007     	phymod_an_ctxt->rx_pages.msg_page.page_0);
   1008     sal_printf("PORT SW AN RX UP PAGE:   \t (48-32):%0x (31-16):%0x (15-0):%0x\n", 
   1009     	phymod_an_ctxt->rx_pages.ufmt_page.page_2, phymod_an_ctxt->rx_pages.ufmt_page.page_1, 
   1010     	phymod_an_ctxt->rx_pages.ufmt_page.page_0);
   1011 
   1012     sal_printf("PORT SW AN  EXT PAGE:    \t (48-32):%0x (31-16):%0x (15-0):%0x\n", 
   1013     	phymod_an_ctxt->tx_pages.null_page.page_2, phymod_an_ctxt->tx_pages.null_page.page_1, 
   1014     	phymod_an_ctxt->tx_pages.null_page.page_0);
   1015     sal_printf("PORT SW AN  EXT PAGE:    \t (48-32):%0x (31-16):%0x (15-0):%0x\n", 
   1016     	phymod_an_ctxt->rx_pages.null_page.page_2, phymod_an_ctxt->rx_pages.null_page.page_1, 
   1017     	phymod_an_ctxt->rx_pages.null_page.page_0);
   1018 
   1019     return BCM_E_NONE;
   1020 }
   1021 #endif /* SW_AUTONEG_SUPPORT */
   1022