#include "archinc.h"
#include "cli.h"
#include "strutil.h"
#include "zarlink.h"
#include "frame.h"

#include <stdio.h>
#include <stdlib.h>

// frame descriptor pool
static frameDescriptor_t fdPool[CONFIG_NUM_FRAME_DESCRIPTORS];

// frame data
static char f128[CONFIG_FRAME_POOL_128][128];
static char f512[CONFIG_FRAME_POOL_512][512];
static char f1518[CONFIG_FRAME_POOL_1518][1518];

/*
 * Frame Manager
 * 
 * This module is meant to provide a pool of buffers for incoming packets
 */

static int addToPool(char * pBuffer, int bufSize)
{
  int retVal = -1;
  int i;

  for (i=0;i<CONFIG_NUM_FRAME_DESCRIPTORS;i++) {
    if (fdPool[i].attrib == 0) {
      fdPool[i].payload = pBuffer;
      fdPool[i].maxLength = bufSize;
      fdPool[i].attrib = FRAME_ATTRIB_VALID;
      retVal = 0;
      break;
      }
    }

  return retVal;
}

int frameInit(void)
{
  int i;

  // first, zero out all the frame descriptors
  for (i=0;i<CONFIG_NUM_FRAME_DESCRIPTORS;i++) {
    fdPool[i].payload = NULL;
    fdPool[i].length = 0;
    fdPool[i].maxLength = 0;
    fdPool[i].attrib = 0;
    }
  
  // add frames to frame pool list
  for (i=0;i<CONFIG_FRAME_POOL_128;i++)
    addToPool(&(f128[i][0]), 128);

  for (i=0;i<CONFIG_FRAME_POOL_512;i++)
    addToPool(&(f512[i][0]), 512);

  for (i=0;i<CONFIG_FRAME_POOL_1518;i++)
    addToPool(&(f1518[i][0]), 1518);

  // cliRegisterCommand("frame", frameHandler, "frame - get frame manager info");
  return 0;
} 


pFrameDescriptor_t frameRequest(int reqLength)
{
  int i;
  pFrameDescriptor_t pRetFrame = NULL;

  for (i=0;i<CONFIG_NUM_FRAME_DESCRIPTORS;i++) {
    if ( ((fdPool[i].attrib & FRAME_ATTRIB_VALID) != 0) &&
         ((fdPool[i].attrib & FRAME_ATTRIB_INUSE) == 0) &&
          (fdPool[i].maxLength >= reqLength) ) 
      {
      fdPool[i].attrib |= FRAME_ATTRIB_INUSE;
      pRetFrame = (pFrameDescriptor_t)&fdPool[i];
      break;
      }
    }

  return pRetFrame;
}

int frameReturn(pFrameDescriptor_t pRetFrame)
{
  if (pRetFrame == NULL)
    return -1;

  pRetFrame->attrib &= ~FRAME_ATTRIB_INUSE;
  return 0;
}

