// scheduling algorithm for split periodic 

#ifndef   __SCHED_H__
#define   __SCHED_H__

#define MAXCEPS 30

// all times are in units of bytes
#define	FS_BYTES_PER_MICROFRAME 188
#define MICROFRAMES_PER_FRAME	8
#define FS_SOF 6  // number of byte times allocated to an SOF packet at the beginning of a frame
//#define	MAXFRAMES	8	// scheduling window for budget tracking, periods longer than
#define	MAXFRAMES	32	// scheduling window for budget tracking, periods longer than
				// this are reduced to this.  Also impacts space required for
				// tracking data structures.  Otherwise fairly arbitrary.

#define	MAXMICROFRAMES	(MAXFRAMES * 8)	

// 4 byte sync, 4 byte split token, 1 byte EOP, 11 byte ipg, plus
// 4 byte sync, 3 byte regular token, 1 byte EOP, 11 byte ipg
#define HS_SPLIT_SAME_OVERHEAD 39
// 4 byte sync, 4 byte split token, 1 byte EOP, 11 byte ipg, plus
// 4 byte sync, 3 byte regular token, 1 byte EOP, 1 byte bus turn
#define HS_SPLIT_TURN_OVERHEAD 29
// 4 byte sync, 1 byte PID, 2 bytes CRC16, 1 byte EOP, 11 byte ipg
#define HS_DATA_SAME_OVERHEAD 19
// 4 byte sync, 1 byte PID, 2 bytes CRC16, 1 byte EOP, 1 byte bus turn
#define HS_DATA_TURN_OVERHEAD 9
// 4 byte sync, 1 byte PID, 1 byte EOP, 1 byte bus turn
#define HS_HANDSHAKE_OVERHEAD 7
//#define HS_MAX_PERIODIC_ALLOCATION	6000	// floor(0.8*7500)
#define HS_MAX_PERIODIC_ALLOCATION	7000	// floor(0.8*7500)

// This could actually be a variable based on an HC implementation
// some measurements have shown 3?us between transactions or about 3% of a microframe
// which is about 200+ byte times.  We'll use about half that for budgeting purposes.
#define HS_HC_THINK_TIME 100

// 4 byte sync, 3 byte regular token, 1 byte EOP, 11 byte ipg
#define HS_TOKEN_SAME_OVERHEAD 19
// 4 byte sync, 3 byte regular token, 1 byte EOP, 1 byte bus turn
#define HS_TOKEN_TURN_OVERHEAD 9

// TOKEN: 1 byte sync, 3 byte token, 3 bit EOP, 1 byte ipg
// DATA: 1 byte sync, 1 byte PID, 2 bytes CRC16, 3 bit EOP, 1 byte ipg
// HANDSHAKE: 1 byte sync, 1 byte PID, 3 bit EOP, 1 byte ipg
#define	FS_ISOCH_OVERHEAD 9
#define FS_INT_OVERHEAD 13
//#define LS_INT_OVERHEAD (19*8)
#define LS_INT_OVERHEAD ((14 *8) + 5)
#define HUB_FS_ADJ 30 // periodic allocation at beginning of frame for use by hubs, maximum allowable is 60 bytes
#define FS_MAX_PERIODIC_ALLOCATION	(1157)	// floor(0.9*1500/1.16)
#define FS_BS_MAX_PERIODIC_ALLOCATION 1350 // floor(0.9*1500), includes bitstuffing allowance (for HC classic allocation)

// byte time to qualify as a large FS isoch transaction
//   673 = 1023/1.16 (i.e. 881) - 1microframe (188) - adj (30) or
//   1/2 of max allocation in this case 
// #define LARGEXACT (881-FS_BYTES_PER_MICROFRAME)
#define LARGEXACT (579)

typedef struct _Endpoint *PEndpoint;

typedef struct _frame_rec
{
	unsigned  time_used:16;		// The number of bytes that are budgeted for all endpoints in this frame
	PEndpoint allocated_large;	// endpoint if xact over LARGEXACT bytes is allocated in this frame
	PEndpoint isoch_ehead;		// many frames can point to the same endpoint. endpoints are linked
	PEndpoint int_ehead;		// in longest to shortest period.
		//
		// NOTE: always start with a "dummy" endpoint for SOF on the lists to avoid empty list corner condition
		//
} frame_rec;

typedef struct _HC *PHC;
typedef struct _TT *PTT;

typedef enum {bulk, control, interrupt, isoch} eptype;

#define	HSSPEED 2
#define FSSPEED 1
#define LSSPEED 0
#define INDIR 0
#define OUTDIR 1
typedef struct _Endpoint
{
	unsigned	type;

	// These fields have static information that is valid/constant as long as an
	// endpoint is configured
	unsigned 	max_packet:16;	// maximum number of data bytes allowed for this
                        		// endpoint. 0-8 for LS_int, 0-64 for FS_int,
                        		// 0-1023 for FS_isoch.
	unsigned 	period:16;       // desired period of transactions, assumed to be a power of 2
	eptype		ep_type:4;
	unsigned	direction:1;
	unsigned	speed:2;
	unsigned	moved_this_req:1;	// 1 when this endpoint has been changed during this allocation request
	PTT			mytt;			// the TT that roots this classic device.

	// These fields hold dynamically calculated information that changes as (other)
	// endpoints are added/removed.

	unsigned calc_bus_time:16;	// bytes of FS/LS bus time this endpoint requires
                        		// including overhead. This can be calculated once.

	unsigned start_time:16;		// classic bus time at which this endpoint is budgeted to occupy the classic bus

	unsigned actual_period:16;	// requested period can be modified:
								// 1. when period is greater than scheduling window (MAXFRAMES)
								// 2. if period is reduced (not currently done by algorithm)

	unsigned start_frame:8;		// first bus frame that is allocated to this endpoint.
	int	start_microframe:8;		// first bus microframe (in a frame) that can have a
                        		// start-split for this ep.
                        		// Complete-splits always start 2 microframes after a
                        		// start-split.
	unsigned num_starts:4;		// the number of start splits.
	unsigned num_completes:4;	// the number of complete splits.
	/* The numbers above could be (better?) represented as bitmasks. */

	/* corner conditions above: coder beware!!
	   patterns can have the last CS in the "next" frame
	     This is indicated in this design when:
		(start_microframe + num_completes + 1) > 7
	   patterns can have the first SS in the previous frame
             This is indicated in this design when:
                start_microframe = -1
	*/

	PEndpoint next_ep;			// pointer to next (faster/equal period) endpoint in budget

	int	id:16;						// not needed for real budgeter
	unsigned saved_period:16;	// used during period promotion to hold original period
	unsigned promoted_this_time:1;

} Endpoint;

typedef	struct _TT
{
	unsigned	HS_split_data_time[MAXFRAMES][MICROFRAMES_PER_FRAME]; // HS data bytes used for split completes
	// the above time tracks the data time for all devices rooted in this TT.
	// when the time is below 188 in a microframe, that time is allocated in the
	// HS microframe (in the HS HC budget).  When the time is greater than 188
	// only 188 byte times (bit stuffed) is allocated on the HS microframe budget.

	unsigned	num_starts[MAXFRAMES][MICROFRAMES_PER_FRAME];

	frame_rec frame_budget[MAXFRAMES];

	PHC	myHC;

	unsigned	think_time;	// TT reports it inter transaction "think" time.  Keep it here.
	unsigned	allocation_limit;	// maximum allocation allowed for this TT's classic bus

	struct _Endpoint isoch_head[MAXFRAMES];
	struct _Endpoint int_head[MAXFRAMES];
} TT;

typedef struct _microframe_rec
{
	unsigned	time_used;
	
} microframe_rec;

typedef struct _HC
{
	microframe_rec HS_microframe_info[MAXFRAMES][MICROFRAMES_PER_FRAME];	// HS bus time allocated to
								//this host controller
	PTT tthead;					// head of list of TTs attached to this HC
	unsigned thinktime;
	unsigned allocation_limit;	// maximum allocation allowed for this HC
	int	speed;					// HS or FS

} HC;

#if 0
typedef struct _command {
    char cmd_code;
    int  endpoint_number;
} Cmd_t;
#endif


/* protoypes */
void init_hc(PHC myHC);

Set_endpoint(
    PEndpoint	ep,
    eptype		t,
    unsigned	d,
    unsigned	s,
	unsigned	p,
	unsigned	m,
	TT			*thistt
	);

int Allocate_time_for_endpoint(
	PEndpoint ep,					
	PEndpoint changed_ep_list[],	
									
	int	*max_changed_eps			
									
	);

void
init_tt(PHC myHC, PTT myTT);	

void
Deallocate_time_for_endpoint(
	PEndpoint ep,					// endpoint that needs to be removed (bus time deallocated)
	PEndpoint changed_ep_list[],	// pointer to array to set (on return) with list of
									// changed endpoints
	int	*max_changed_eps			// input: maximum size of (returned) list
									// on return: number of changed endpoints
	);

#endif //   __SCHED_H__