/***********************************************************************************
 *                                                                      
 *                  I N T E L   P R O P R I E T A R Y                   
 *                                                                      
 *     COPYRIGHT (c)  2001 BY  INTEL  CORPORATION.  ALL RIGHTS          
 *     RESERVED.   NO  PART  OF THIS PROGRAM  OR  PUBLICATION  MAY      
 *     BE  REPRODUCED,   TRANSMITTED,   TRANSCRIBED,   STORED  IN  A    
 *     RETRIEVAL SYSTEM, OR TRANSLATED INTO ANY LANGUAGE OR COMPUTER    
 *     LANGUAGE IN ANY FORM OR BY ANY MEANS, ELECTRONIC, MECHANICAL,    
 *     MAGNETIC,  OPTICAL,  CHEMICAL, MANUAL, OR OTHERWISE,  WITHOUT    
 *     THE PRIOR WRITTEN PERMISSION OF :                                
 *                                                                      
 *                        INTEL  CORPORATION                            
 *                                                                     
 *                     2200 MISSION COLLEGE BLVD                        
 *                                                                      
 *               SANTA  CLARA,  CALIFORNIA  95052-8119                  
 *                                                                      
 ************************************************************************************
 *
 * 		File Name: scheduler_packet.h
 * 
 * 		Purpose: Header file with data structures for IXP2800 DRR scheduler 
 *
 ************************************************************************************
 *
 * 		History:
 *
 * 		Date			Comment										By
 *		---------------------------------------------------------------------------
 *
 *		Dec 26/02		Created										urn/kt
 *
 *************************************************************************************/


#ifndef __SCHEDULER_PACKET_H__
#define __SCHEDULER_PACKET_H__

#include "dl_system.h"

//Signal used for inter-ME waking up 
.sig volatile system_init_sig
.addr system_init_sig ME_INIT_SIGNAL

/*************************************************************************************
 *
 * Constants 
 *
 ************************************************************************************/
/*Bit field number for SAME_ME_SIGNAL CSR */
#define	NEXT_CONTEXT_BIT		7
#define SIGNAL_NUMBER_FIELD		3
/*definition for normal cam state*/
#define NORMAL_CAM_STATE		1

#define NUM_PORTS				16
#define NUM_QUEUE_PER_PORTS		256
/*initial round is 1 because Queue Manager used 0x0 to indicate no enqueue/dequeue */
#define	INIT_ENQ_ROUND			0x1
		
/* Maximum number of rounds needed to update dequeue counter.
   When dequeue counter == enqueue counter, the queue is empty
   and CLASS SCHEDULER ME needs to reinitialize queue structure 
   information. When dequeue counter not equal to enqueue counter.
   the queue is really not empty or it's empty but the write to update 
   dequeue counter is pending. The following constant is a mximum number
   of rounds can happen during the write to update the dequeue counter.
   If current round has advanced within this number of round from the last
   scheduled round, pending dequeue update is possible. Proceed as if 
   the queue is empty */

   #define		MAX_ROUNDS_FOR_PENDING_COUNTER_UPDATE	16
    
/* Start location of port bits in equeue/dequeue message*/

#define 		PORT_BITS_START              16

/* Number of bits used to specify a DRR round */

#define			TOTAL_ROUNDS				(1 << NUMBER_OF_BITS_FOR_ROUNDS)

/* Value to mask roll-over bits in port and round - this value is depended
   on NUMBER_OF_BITS_FOR_ROUNDS */
#define		ROUND_ONLY_MASK_VAL		0x00000fff

/* Value to mask roll-over bits in port and round - this value is depended
   on NUMBER_OF_BITS_FOR_PORTS and PORT_BITS_START */
#define		PORT_ONLY_MASK_VAL		0x000f0000


/* Value to mask roll-over bits in port and round  */
#define			PORT_ROUND_MASK_VAL		(PORT_ONLY_MASK_VAL | ROUND_ONLY_MASK_VAL)
	

#define 		NUMBER_OF_QUEUES_PER_PORT_SHIFT		8

/* Size of each queue data structure in bytes. Must be a power of 2*/

#define 		QUEUE_STRUCTURE_SIZE		 16
#define_eval	NUM_LWS						(QUEUE_STRUCTURE_SIZE / 4)

/* Log 2 of QUEUE_STRUCTURE_SIZE */
#define 		QUEUE_STRUCTURE_SHIFT		 4

/* Dequeue counter is always the last long word in queue structure */
#define_eval	DEQ_COUNTER_INDEX	(NUM_LWS - 1)
	
/* Number of bits to left shift the port number to get the
   queue structure offset for that port
   Log 2 of (NUMBER_OF_QUEUES_PER_PORT * QUEUE_STRUCTURE_SIZE) 
 */

#define_eval 	QUEUE_STRUCTURES_PER_PORT_SHIFT (NUMBER_OF_QUEUES_PER_PORT_SHIFT + QUEUE_STRUCTURE_SHIFT) 
 

/* Quantum shift start bit in long word 2 of queue structure*/
#define 		QUANTUM_SHIFT_BITS_START       24
/* Number of bits used to specify the port */

/* Out of 8-longword queue structure, only 3 need to be written back on LRU evict.
   Longword 3 is constant, longwords 5, 6 are reserved, lw 7 is dequeued pkts counter.
   NOTE: IF MORE DATA IS ADDED TO QUEUE STRUCTURES, THE VALUE BELOW MAY NEED CHANGE*/

#define 		QUEUE_STRUCTURE_LWS_TO_WRITE_BACK		 3

/* Log 2 of the size of the enqueue base round data (one per port) in SRAM */

#define 		ENQ_BASE_ROUND_SHIFT		 	2

/* Log 2 of the size of the packets counter per round */

#define 		PACKETS_CTR_SHIFT		 	2


/* Number of bits to right-shift the next dequeue round response to get
   packets counter offset. Each port has 1 counter, port number 
   is in bits 19..16, and each counter is 4 bytes 
*/
   #define 		ROUND_PKTS_COUNTER_SHIFT (NUMBER_OF_BITS_FOR_ROUNDS + PACKETS_CTR_SHIFT)	 

/* Inverted of the mask to mask out any bits that may belong to
   round number. Message: Port[19:16] round[16:0]. So, after shifting message right by
   PORT_STRUCTURE_SHIFT	(11), we need to mask out the last 5 bits
 */

#define			INVERTED_PORT_STRUCTURE_MASK	0x1F

/* Number of bits to right-shift the enqueue message to extract port structure offset 
   in Port Scheduler - port is in [19..16], each structure is 32 bytes (shift left 5) 
*/
   #define 		PORT_STRUCTURE_SHIFT		 	7
/*n where 2^n = port structure size) */
   #define		PORT_STRUCTURE_SIZE				5
/*the number of bit shift right to convert port offset to T_INDEX value.
  This value is equal to PORT_STRUCTURE_SIZE - 2 since T_Index is in bits [8:2]
*/
  #define_eval  PORT_OFFSET_TO_T_INDEX			(PORT_STRUCTURE_SIZE - 2)

/* Low water mark: If packet count for a round falls below this mark in the
   scheduler, then it requests a new round from the class scheduler microengine
*/
#define 		ROUND_LOW_WATER_MARK		 	32

/* Maximum number of packets in flight per port - packets scheduled but 
   not transmitted 
 */
#if ( (TX_PHY_MODE ==  SPI_4_10PORTS) || (TX_PHY_MODE	== SPI_4_16PORTS) )
#define 		MAX_IN_FLIGHT				 	16
#else
#define 		MAX_IN_FLIGHT				 	192
#endif	// #if ((TX_PHY_MODE is  SPI_4_10PORTS) or	== SPI_4_16PORTS))


/*
 * Ring id for scratch ring between Scheduler and class scheduler (from dl_system.h)
 */
#define_eval 	RING_ID							CLASS_COUNT_PORT_SCHEDULER_SCR_RING
#define_eval 	RING_ADDR						(CLASS_COUNT_PORT_SCHEDULER_SCR_RING << 2)
/*
 * Ring full value for testing branch state. This depends on which ring you are using
 * Eventhough 0-15 rings are possible, the "ring full"input state can be used
 * only on rings 0-11. i.e SCR_Ring#_Full is valid only for # = 0-11.
 */

#if (RING_ID > 11)

#error			"For Ring > 11, we cannot use the SCR_Ring#_Full input state"

#else
/*assume that the CSR SCR_RING#_BASE is set to indicate ring full*/
#define_eval	RING_FULL			SCR_Ring/**/RING_ID/***/_Status
	
#endif

/*************************************************************************************
 *
 * Per Queue Structure maintained in SRAM
 * 16 strcutures are cached in class scheduler microengine local memory
 *
 * For each queue there are 4 long words in local memory. Information for 16 queues
 * is cached in local memory (16 * 4 = 128 words)
 *
 *
 * q_credit_used: 					current_credit_used: A value between 0 and 
 *								    (2 * max_packet_size) that reflects how much 
 *								    credit of the current round has been used
 *
 
 *
 * q_last_enq_round_and_quantum_shift: [19:16] port [11:0] round.	 The last round
 *									number in which packet(s) from this queue was
 *								  	scheduled. When a new packet from this queue comes, 
 *									the round in which the new packet will be scheduled 
 *									will be calculated starting from this last round.
 *
 *									[31:24] n where 2^n is credit quantum per round
 *
 * q_enqueued_packets_count	:	  	number of packets from the queue that has been enqueued
 *									to the Round FIFO
 *
 *
 *************************************************************************************/	
 //the first 3 longwords are changed for each packet enqueued
 #define lm_q_current_credit_used				*l$index0[0] 
														 
 #define lm_q_last_enq_round_and_quantum_shift *l$index0[1] //[31:24] quantum_shift
 																//[19:16] port [11:0] round
 #define lm_q_enqueued_packets_count			*l$index0[2]

 /*In queue structures, it's the dequeue packets counter. This counter is in part of 
   the queue structures in SRAM but it will not be cached in local memory. See more
   details about dequeue counter below
 */
 #define lm_q_reserved 							*l$index0[4]
 
/*************************************************************************************
 *
 * For each queue, there's a 1 long word counter to keep track of dequeued packets.
 * This longword is maintained in SRAM and ALWAYS read/written from SRAM each time it's
 * accessed because these counters are updated (written) by Transmit ME and used (read) 
 * by Class Scheduler ME.
 *
 * Since the queue structures are cached in local memory at 64-byte offsets, there is 
 * room for the dequeue counter of each queue to be right at the bottom of each queue 
 * structure. 
 * This way, only one SRAM read can bring in both queue structure data and
 * dequeue counter (note that even all 64 bytes blocked are cached in local memory of
 * Class Scehduler ME, the dequeue counter is always read from SRAM )
 ************************************************************************************/
 
 /***********************************************************************************
 * Per Port Current Round structure maintained in class scheduler microengine local memory
 *
 * For each port there are 1 long word to keep track of the base enqueue round which 
 * is the first round where new packets can be enqueued. 
 * By design, packets can only be dequeued from the previous rounds of this base
 * enqueue round
 *
 ************************************************************************************/
 #define		lm_enq_base_round			*l$index1[0]//[19:16] port number [11:0] round number	

/*************************************************************************************
 *
 * Per port structure maintained in Port Scheduler microengine local memory
 *
 *		  port_packets_enqueued
 *		  port_credit_quantum_and_current
 *		  port_pkts_scheduled
 *		  port_req_status_link_next
 *		  port_next_and_curr_rnd_pkts_cnt
 *		  port_next_and_curr_deq_rounds
 *
 * For each queue there are 8 long words in local memory. Information for 16 queues
 * is cached in local memory (16 * 8 = 128 words)
 *
 * port_pkts_enqueued		 : 		total number of pkts have been enqueued for the port.
 * 
 * port_credit_quantum_and_current:	WRR credit quantum for the port and current credit the
 *									port has
 *									[31:16] credit quantum
 *									[15:0] current credit
 *
 * port_pkts_scheduled		 : number of packets scheduled to be dequeued for the port
 *
 * port_req_status_link_next: [31]: round_request_pending bit. 
 *										When the packets count in dequeue round is 
 *        								less than LOW_WATER_MARK, Port Scheduler send 
 *										a new round request to class scheduler ME  
 *										and set the round_request_pending bit
 *
 * 										[23]: got_request_response bit. The response 
 *										for the new round request is the packet count  
 *										of that round. When the response comes back,
 *										the packets count will be saved in [31:16] of 
 *										lm0_port_next_and_curr_rnd_pkts_cnt.
 *										The got_request_response bit is set and the 
 *										request_pending bit will be cleared.
 *
 *										[0:16]: link to the structure of the next port 
 *										that has packets
 *
 *
 * port_next_and_curr_deq_rounds : 		[31:16] current round number and port
 *										[15:0]  next round number and port
 *
 * port_next_and_curr_rnd_pkts_cnt:     [31:16] packets in the current round that is 
 *										currently being dequeued 
 *										[15:0] packets in the next round that is 
 *										will be dequeued
 ************************************************************************************/
 #define PORT_CREDIT_QUANTUM				0x100
 #define REQ_PENDING_BIT					31
 #define GOT_RESPONSE_BIT					30
 #define PORT_ACTIVE_BIT					29	
 #define_eval PORT_ACTIVE_VAL				(1 << (PORT_ACTIVE_BIT % 8))	
 
 //LM0
 /*packets enqueued for the port*/
 #define lm0_port_pkts_enqueued						*l$index0[0]	
 
 #define lm0_port_credit_quantum_and_current		*l$index0[1]
 
  /*packets scheduled for dequeue*/
 #define lm0_port_pkts_scheduled					*l$index0[2]
 
 /*[31]: REQ_PENDING bit. 
 		 When the packets count in dequeue round is 
         less than LOW_WATER_MARK, Port Scheduler send a next dequeue round 
		 request to Class Scheduler ME and set the round_request_pending bit
		 to signal that the request has been sent.

   [30]: GOT_RESPONSE bit. 
   		 Count ME responses to the next dequeue round request 
    	 with the port/round number and the packet count of the round available
		 for dequeueing. The port/round number in long word 4 of the port structure, 
		 and packets count will be saved in long word 5.
		 The GOT_RESPONSE bit is set to signal that request response has come back
		 and the REQ_PENDING bit will be cleared.
   
   [23]: PORT_ACTIVE bit. 
   		 A port is enlisted to the port_with_packets list when the Port Scheduler
		  gets the FIRST response to the next dequeue round request for it.
		 In order to get the 1st response, an intial request must be sent. This
		 intial request is sent only when port is not in port_with_packets list.
		 PORT_ACTIVE bit = 0 --> port not in list

   [0:16]: link to the structure of the next port that has packets*/
 #define lm0_port_req_status_link_next	*l$index0[3] 

 #define lm0_port_next_and_curr_deq_rounds	*l$index0[4] /*[31:16] next, [15:0] current*/
 

 #define lm0_port_next_and_curr_rnd_pkts_cnt *l$index0[5] /* [15:0] packet available */ 
 														  /* in the current dequeue round */
														  /* [31:16] packet available*/ 
 														  /* in the next dequeue round */
 #define lm0_port_resvd_1					 *l$index0[6]
 #define lm0_port_resvd_2					 *l$index0[7]
 

 //LM1
 #define lm1_port_pkts_enqueued					*l$index1[0]	
 
 #define lm1_port_credit_quantum_and_current		*l$index1[1]

 #define lm1_port_pkts_scheduled					*l$index1[2]

 #define lm1_port_req_status_link_next	*l$index1[3] 

 #define lm1_port_next_and_curr_deq_rounds	*l$index1[4] /*[31:16] next, [15:0] current*/						 							

 #define lm1_port_next_and_curr_rnd_pkts_cnt *l$index1[5] /* [15:0] packet available */ 
 														  /* in the current dequeue round */
														  /* [31:16] packet available*/ 
 														  /* in the next dequeue round */
 #define lm1_port_resvd_1					 *l$index1[6]
 #define lm1_port_resvd_2					 *l$index1[7]

	
/*************************************************************************************
 * Packets Transmitted array in Port Scheduler microengine
 *
 * An array of 16 transfer registers that hold the packets transmitted for a port
 * This array will be written by Transmit microengine via reflector write
 *
 * packets_transmitted[16]
 * 
 ************************************************************************************/

/*************************************************************************************
 *
 * Per Round packets counter maintained in SRAM
 *
 * For each round there is one word in SRAM which keeps the 
 * count of packets in the round. 
 * Total number of counters = number of ports * number of rounds
 *
 * In addition there are 16 cached Round counters in local memory of COUNT ME. They 
 * are read in/written out using the CAM
 *
 * round_counters[NUMBER_OF_ROUNDS_PER_PORT * NUMBER_OF_PORTS]
 *
 ************************************************************************************/

/*************************************************************************************
 *
 * Enqueue request from Statistics microengine to class scheduler microengine
 *
 * NN ring interface 
 * 

 * packet_length				 : 32 bits
 * sop_handle					 : 32 bits 
 * port_number					 : 16 bits
 * queue_number					 : 16 bits
 *
 ************************************************************************************/

/*************************************************************************************
 *
 * Enqueue request and new round response from class scheduler microengine to Count microengine
 *
 * NN ring interface 
 *
 * sop_handle					 : bits 31:0		for enqueue request
 *													
 * port_round_number			 : bits 31:0		for enqueue request
 *													[19:16] port number [11:0] round number
 *
 * port_next_dequeue_round		 : bits 31:0		for response to Next Dequeue Round
 *													Request from Port Scheduler microengine
 *													[19:16] port number [11:0] round number										[19:16] port number [11:0] round number   
 *													[31] invalid bit: 1 = invalid response
 *																	0 = valid response 
 *													[30:20] reserved (must be 0)
 *
 * If enqueue request or new round response is not valid then 
 * round number will be 0 (0 is INVALID_ROUND_NUM)
 *
 ************************************************************************************/
 
/*************************************************************************************
 *
 * Enqueue request and new round response from Count to Port Scheduler microengine
 *
 * NN ring interface  
 *
 * sop_handle					 : bits 31..0		for enqueue request
 *		
 * enqueue_port_round_number	 : bits 31..0 		for enqueue request
 *													[31] invalid bit (1=invalid,0=valid)
 *													[19:16] port number, [11:0] round number
 *
 * new_dequeue_port_round		 : bits 31..0		for response to next dequeue round
 *													request from Port Scheduler.
 *													[31] invalid bit (1=invalid,0=valid)
 *													[19:16] port number, [11:0] round number
 *
 * new_dequeue_round_pkts_count	 : bits 31..0		number of packets in the new dequeue round
 * 
 * If enqueue request or new round response is not valid then 
 * round number will be INVALID_ROUND_NUM and INVALID_BIT = 1
 *
 ************************************************************************************/

/*************************************************************************************
 *
 * Enqueue and Dequeue requests from Port Scheduler to QM 
 *
 * NN ring interface for enqueue/dequeue request 
 *
 * sop_handle					 : bits 31..0  
 * enqueue_queue_number			 : [31] invalid bit, [19:16] port number, [11:0] round number							
 * dequeue_queue_number			 : [31] invalid bit, [19:16] port number, [11:0] round number   
 *
 * If enqueue request or new round response is not valid then 
 * round number will be INVALID_ROUND_NUM and INVALID_BIT = 1
 *				
 ************************************************************************************/

/*************************************************************************************
 *
 * New round requests from Port Scheduler to class scheduler microengine
 *
 * To request the next round to dequeue from for the port
 *
 * Scratch ring interface for enqueue/dequeue request 
 *
 * port_number					:  bits [3:0], reserved [4:30], 
 *								   valid bit [31] (1 = valid, 0 = invalid) 
 *
 ************************************************************************************/



/************************************************************************************/

#endif 		/* __PACKET_SCHEDULER_H__ */

/************************************************************************************/