/*
	 Copyright 2001 (c) by Authors,
	 Swiss Federal Institute of Technology,
	 Computer Engineering and Networks Laboratory.
 
	 TOPSY -- A Teachable Operating System.
	 Implementation of a tiny and simple
	 micro kernel for teaching purposes.
 
	 For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
	 This software is provided under the terms of the GNU General Public 
	 Licence. A full copy of the GNU GPL is provided in the file COPYING 
	 found in the development root of Topsy.
*/
/*
 
	File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/IO/sa1100/Drivers/Attic/IXPBusInit.c,v $
	Affiliation:           ETH Zuerich, TIK
	Version:               $Revision: 2922 $
	Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/

// this code is based upon parts of vera from Princeton

//
// Utilities for the Intel IXP1200
// Princeton University
// Scott Karlin and Tammo Spalink
//
// Copyright Princeton University Board of Trustees
// All rights reserved
//
//  $Id: IXPBusInit.c 2922 2007-03-19 16:48:52Z baderma $
//


#include "IXPBusInit.h"
#include "IXPMemAccess.h"
#include "IXP_Defines.h"
#include "IXPUtil.h"
#include "Support.h"


//
// ---------- Private Hardware Access Definitions ----------
//

static uint32 RDYBUS_TEMPLATE_PROG[] = {
                                         0xB0040184, 0xB0040188, 0xB004018C
                                       };

typedef enum {
  RDYBUS_TEMPLATE_CTL_EI = 1 << 5,  // Big [Little] Endian FBE# Signals
  RDYBUS_TEMPLATE_CTL_ST = 1 << 6,  // MACs do [do not] Return Status on EOP
  RDYBUS_TEMPLATE_CTL_ML = 1 << 7,  // Multiple [Single] IXPs Share the Bus
  RDYBUS_TEMPLATE_CTL_MS = 1 << 8,  // Ready Bus Master [Slave]
  RDYBUS_TEMPLATE_CTL_FM = 1 << 9,  // 64 [32] bit Bus Width/Mode
  RDYBUS_TEMPLATE_CTL_TM = 1 << 10, // 1-2 [3-7] MACs
  RDYBUS_TEMPLATE_CTL_ER = 1 << 11  // Enable [Disable] Ready Bus Sequencer
} RDYBUS_TEMPLATE_CTL_fields;

// Actual size of the counter is (RDBUS_TIMER + 1)
#define RDYBUS_SYNCH_COUNT_DEFAULT_RDBUS_TIMER(value) (putBits((value), 0, 16))

typedef enum {
  RCV_RDY_CTL_clear    = 0x00000000,
  RCV_RDY_CTL_FPTM_ETM = 2 << 13
} RCV_RDY_CTL_fields;

typedef enum {
  XMIT_RDY_CTL_clear = 0x00000000
} XMIT_RDY_CTL_fields;

typedef enum {
  FLOWCTL_MASK_MAC0 = 7 << 8
} FLOWCTL_MASK_fields;

//
// ---------- Exported Functions ----------
//

/*****************************************************************************/
/*                                                                           */
/* Function Name: IXBus_Init                                                 */
/* Parameters: <none>                                                        */
/* Returns: <none>                                                           */
/* Effects: Initialize the IXBus by writing the RDY_BUS control program and  */
/*          setting initial values in the registers.                         */
/*****************************************************************************/

void
IXBus_Init(void)
{
  led(0x40);

  // Write RDBus Controller Instructions
  memWrite32(RDYBUS_TEMPLATE_PROG[0], 0xFB1FF71F);
  memWrite32(RDYBUS_TEMPLATE_PROG[1], 0xFB1FF71F);
  memWrite32(RDYBUS_TEMPLATE_PROG[2], 0xFB1FF71F);
  //     memWrite32(RDYBUS_TEMPLATE_PROG[0], 0x00FB00F7);
  //     memWrite32(RDYBUS_TEMPLATE_PROG[1], 0);
  //     memWrite32(RDYBUS_TEMPLATE_PROG[2], 0);

  led(0x41);

  /* Set the ready bus synchronizer counter to default to 0. pg. 4-32 */
  memWrite32(IXP1200_RDYBUS_SYNCH_COUNT_DEFAULT,
             RDYBUS_SYNCH_COUNT_DEFAULT_RDBUS_TIMER(0));

  /* Set the state machine to explicitly signal the thread making the
   * request. pg. 4-18 */
  memWrite32(IXP1200_RCV_RDY_CTL, RCV_RDY_CTL_FPTM_ETM);
  /* Send flow control information out on MAC0. pg 4-27. This is to work
   * around the ready bus controller. */
  memWrite32(IXP1200_FLOWCTL_MASK, FLOWCTL_MASK_MAC0);
  /* Clear the transmit ready control. pg 4-41 */
  memWrite32(IXP1200_XMIT_RDY_CTL, XMIT_RDY_CTL_clear);

  memWrite32(IXP1200_THREAD_DONE_REG0, 0xFFFFFFFF);     // Clear
  memWrite32(IXP1200_THREAD_DONE_REG1, 0xFFFFFFFF);     // Clear

  memRead32(IXP1200_SELF_DESTRUCT);                     // Clear

  /* See definitions above. pg 4-28 */
  memWrite32(IXP1200_RDYBUS_TEMPLATE_CTL,
             RDYBUS_TEMPLATE_CTL_MS | RDYBUS_TEMPLATE_CTL_TM |
             RDYBUS_TEMPLATE_CTL_ER | RDYBUS_TEMPLATE_CTL_FM
             /* | XXX RDYBUS_TEMPLATE_CTL_EI */ );

  led(0x43);
}


//
// ---------- Exported Diagnostic Functions ----------
//

/*****************************************************************************/
/*                                                                           */
/* Function Name: IXBus_PrintCSRs                                            */
/* Parameters: <none>                                                        */
/* Returns: <none>                                                           */
/* Effects: Prints IXBus related Control Status registers to standard output.*/
/*                                                                           */
/*****************************************************************************/

void
IXBus_PrintCSRs(void)
{
  uint32 RCV_RDY_LO_value        = memRead32(IXP1200_RCV_RDY_LO);
  uint32 RCV_RDY_CNT_value       = memRead32(IXP1200_RCV_RDY_CNT);
  uint32 XMIT_RDY_LO_value       = memRead32(IXP1200_XMIT_RDY_LO);
  uint32 XMIT_PTR_value          = memRead32(IXP1200_XMIT_PTR);
  uint32 XMIT_RDY_CTL_value      = memRead32(IXP1200_XMIT_RDY_CTL);

  printf("IXBus\n"
         "  %-16s : %x\n""  %-16s : %d\n""  %-16s : %d\n"
         "  %-16s : %x\n""  %-16s : %d\n""  %-16s : %x\n",
         "RCV_RDY Flags",  getBits(RCV_RDY_LO_value, 0, 8),
         "RCV_RDY Count",  getBits(RCV_RDY_CNT_value, 0, 8),
         "RCV_REQ Count",  getBits(RCV_RDY_CNT_value, 8, 8),
         "XMIT_RDY Flags", getBits(XMIT_RDY_LO_value, 0, 8),
         "XMIT_PTR",       getBits(XMIT_PTR_value, 0, 4),
         "TFIFO Valid Flags", getBits(XMIT_RDY_CTL_value, 16, 16));
}

inline void IXBus_SignalThread(int tid)
{
  memWrite32(IXP1200_INTER_THD_SIG, putBits(tid, 0, 5));
}
