⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2o.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 3 页
字号:

/**********************************************************************
 * function: I2ODBPost
 *
 * description: local processor writes to a outbound doorbell register,
 *              PCI master writes to the inbound doorbell register of device
 *
 * note:
 * If it is not local, pcsrbar must be passed to the function.
 * Otherwise eumbbar is passed.
 *
 * If it is remote, in doorbell register on the device is written.
 * Otherwise local out doorbell is written
 *********************************************************************/
void I2ODBPost( LOCATION loc,             /*  REMOTE/LOCAL   */
                unsigned int base,        /* pcsrbar/eumbbar */
                unsigned int msg )        /*   in   / out    */
{
    if ( loc == REMOTE )
    {
	/* write to inbound doorbell register of device, pcsrbar is the base */
	store_runtime_reg( base, I2O_IDBR, msg );
    }
    else
    {
	/* write to local outbound doorbell register, eumbbar is the base */
	store_runtime_reg( base, I2O_ODBR, msg & 0x1fffffff );
    }

}

/********************************************************************
 * function: I2O_ISR_host
 *
 * This function is a very simple interrupt service routine to be
 * installed in the host.  It must poll the Kahlua agent to
 * determine the cause of the interrupt, without knowing anything
 * about the nature.  Note that the agent's ISR is already aware 
 * that the interrupt is for the Message unit.  At first, this ISR
 * only looks at the message unit, but it must be extended in the
 * future to examine any part of the Kahlua's status registers for
 * any kind of expected interrupt.  If it doesn't find a cause, it
 * reports that an unexpected interrupt occurred.
 *
 ********************************************************************/
/*extern int dink_printff( unsigned char *, ... );
#define printf dink_printff*/

void I2O_ISR_host ()
{
/*  unsigned int kahlua_pcsrbar = get_kahlua_pcsrbar();
  unsigned int found_cause = 0;

  I2OOMSTAT i2o_status;*/
  /*unsigned int db_reg_content;*/

  /* Try the Message Unit status */
 /* if (I2OOutMsgStatGet(kahlua_pcsrbar, &i2o_status) != I2OSUCCESS)
    logMsg("Unable to read Kahlua's Message Unit status.\n",0,0,0,0,0,0);*/
/*  else
  {*/
    /* check the doorbell status */
/*    if (i2o_status.odi)
    {*/
      /*logMsg("Doorbell interrupt detected:\n",0,0,0,0,0,0);*/
      	 store_runtime_reg(0x84000060, 0, (0x1<<31));

      	if(runled12%2)	
	led12(0);
	else
	led12(1);
	runled12++;
       store_runtime_reg( 0x84000060, 0, (0x1<<1) );
	logMsg("\n come to net 1200 interrupt",0,0,0,0,0,0);
      /*db_reg_content =*/ /*I2ODBGet(REMOTE,0x84000060);*/
      /*logMsg("Agent's outbound doorbell register: 0x%x\n",db_reg_content,0,0,0,0,0);*/
     /* found_cause++;*/
   /* }*/
    /* check for Outbound Message 0/1 and Outbound Post Queue interrupts here */
/*  }*/

  /* can't find the cause */
  /*if (found_cause == 0)
    logMsg("A non-Message Unit external interrupt has been detected.\n",0,0,0,0,0,0);*/
  return;
}


/********************************************************************
 * function: I2O_ISR_agent
 *
 * This function is a very simple interrupt service routine to be
 * installed in the Kahlua agent.  It knows that it is servicing
 * Message Unit interrupts only.  Initially, it only reports doorbell
 * interrupts, but should be extended to handle message 0/1 and
 * the inbound FIFO.
 * If it doesn't find a cause, it reports that an unexpected message
 * unit interrupt occurred.
 *
 ********************************************************************/
void I2O_ISR_agent ()
{
  unsigned int eumbbar = get_eumbbar();
  unsigned int found_cause = 0;

  I2OIMSTAT i2o_status;
  unsigned int db_reg_content;

  /* Get the Inbound Message Unit status */
  if (I2OInMsgStatGet(eumbbar, &i2o_status) != I2OSUCCESS)
    logMsg("Unable to read Inbound Message Unit status.\n",0,0,0,0,0,0);
  else
  {
    #ifdef I2O_DBG
    union{
      I2OIMSTAT status;
      unsigned int raw;
    } s;
    s.status = i2o_status;
    logMsg("inbound message status register, masked: 0x%x\n",s.raw,0,0,0,0,0,0);
    #endif
    /* check the doorbell status */
    if (i2o_status.idi)
    {
      logMsg("Doorbell interrupt detected:\n",0,0,0,0,0,0);
      db_reg_content = I2ODBGet(LOCALA,eumbbar);
      logMsg("Agent's inbound doorbell register: 0x%x\n",db_reg_content,0,0,0,0,0);
      found_cause++;
    }
    /* handle Inbound Message 0/1 and Outbound Post Queue interrupts here */
  }

  /* can't find the cause */
  if (found_cause == 0)
    logMsg("Unable to determine cause of Inbound Message Unit interrupt.\n",0,0,0,0,0,0);
  return;
}

/********************************************************************
 * function: I2OOutMsgStatGet
 *
 * description: PCI master reads device's outbound msg unit interrupt status.
 *              Reading an interrupt status register,
 *              the register will be cleared.
 * Only the two outbound message interrupt bits (OM1I and OM0I) are cleared,
 * the other bits are reserved (so leave them alone), or are read only and
 * are cleared by reading all MFA's or by the host writing 1's to the outbound
 * doorbell bits.
 *
 *              The value of the status register is AND with the outbound
 *              interrupt mask and result is returned.
 * The outbound message interrupt mask register has a 1 to mask an interrupt
 * and a 0 to allow an interrupt, so the mask has to be complemented prior
 * to the AND operation.  Also note that the OPQI bit may be set irrespective
 * of the OPQIM bit setting.  I don't see why there is a  OPQIM bit in the
 * OMIMR, but this is what book IV says.  Since the OPQI status cannot be masked,
 * do not use the OPQIM bit from the OMIMR.
 *
 * note:
 * pcsrbar must be passed to the function.
 ********************************************************************/
I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT *val )
{
    union {
      unsigned int raw_value;
      I2OOMSTAT status;
    } s;
      
    unsigned int mask;

    if ( val == 0 )
    {
	    return I2OINVALID;
    }
    
    /* read device's outbound status */
    s.raw_value = load_runtime_reg( pcsrbar, I2O_OMISR );
    mask = load_runtime_reg( pcsrbar, I2O_OMIMR );

    /* Use only the ODIM and OM1IM and OM0IM bits, OPQIM doesn't do 
     * anything, others are reserved.
     */
    mask &= 0xb;

    /* only clear the OM1I and OM0I status bits */
    store_runtime_reg( pcsrbar, I2O_OMISR, s.raw_value & 0x3);
    
    /* complement the mask, a 0 means the interrupt is NOT masked */
    s.raw_value &= ~mask;

    /* use status register mapping part of the union */
    *val = s.status;

    return I2OSUCCESS;   
}

/********************************************************************
 * function: I2OInMsgStatGet
 *
 * description: Local processor reads its inbound msg unit interrupt status.
 *              Reading an interrupt status register,
 *              the register will be cleared.
 * Only the defined bits in the register are cleared.
 *
 *              The inbound msg interrupt status is AND with the inbound
 *              msg interrupt mask and result is returned.
 * As in the outbound, the mask register has a 0 to NOT mask the status,
 * so the mask register is complemented prior to the AND operation.
 *
 * note:
 * eumbbar must be passed to the function.
 ********************************************************************/
I2OSTATUS I2OInMsgStatGet(unsigned int eumbbar, I2OIMSTAT *val)
{
    union {
      unsigned int raw_value;
      I2OIMSTAT status;
    } s;

    unsigned int mask;

    if ( val == 0 )
    {
	    return I2OINVALID;
    }
    
    /* read device's inbound status */
    s.raw_value = load_runtime_reg( eumbbar, I2O_IMISR );
    #ifdef I2O_DBG
    printf("inbound message status register, not masked: 0x%x\n",s.raw_value);
    #endif
    mask = load_runtime_reg( eumbbar, I2O_IMIMR );

    /* only use defined parts of the mask register, ignore reserved parts */
    mask &= 0x1bb;

    /* When resetting, leave the reserved parts alone and do not write to
     * the MCI and IDI bits which are cleared by writing to the doorbell
     * register, not the status bits.
     */
    store_runtime_reg( eumbbar, I2O_IMISR, s.raw_value & 0x1a3 );

    /* use the complement of the mask, a 0 means NOT mask the status bit */
    s.raw_value &= ~mask;

    /* use the status register mapping part of the union */
    *val = s.status;
    
    return I2OSUCCESS;
	   
}

/***********************************************************
 * function: I2OFIFOInit
 *
 * description: Configure the I2O FIFO, including QBAR,
 *              IFHPR/IFTPR, IPHPR/IPTPR, OFHPR/OFTPR,
 *              OPHPR/OPTPR, MUCR.
 *
 *              return I2OSUCCESS if no error,
 *              otherwise return I2OQUEINVALID
 *
 * note: It is NOT this driver's responsibility of initializing
 *       MFA blocks, i.e., FIFO queue itself. The MFA blocks
 *       must be initialized before I2O unit can be used.
 ***********************************************************/
I2OSTATUS I2OFIFOInit( unsigned int eumbbar,
		       QUEUE_SIZE   sz,      /* value of CQS of MUCR */
		       unsigned int qba)     /* queue base address that must be aligned at 1M */
{
    
    if ( ( qba & 0xfffff ) != 0 )
    {
	/* QBA must be aligned at 1Mbyte boundary */
	return I2OQUEINVALID;
    }

    store_runtime_reg( eumbbar, I2O_QBAR, qba );
    store_runtime_reg( eumbbar, I2O_MUCR, (unsigned int)sz );
    store_runtime_reg( eumbbar, I2O_IFHPR, qba );
    store_runtime_reg( eumbbar, I2O_IFTPR, qba );
    store_runtime_reg( eumbbar, I2O_IPHPR, qba + 1 * ( sz << 11 ));
    store_runtime_reg( eumbbar, I2O_IPTPR, qba + 1 * ( sz << 11 ));
    store_runtime_reg( eumbbar, I2O_OFHPR, qba + 2 * ( sz << 11 ));
    store_runtime_reg( eumbbar, I2O_OFTPR, qba + 2 * ( sz << 11 ));    
    store_runtime_reg( eumbbar, I2O_OPHPR, qba + 3 * ( sz << 11 ));
    store_runtime_reg( eumbbar, I2O_OPTPR, qba + 3 * ( sz << 11 ));

    fifo_stat.qsz = sz;
    fifo_stat.qba = qba;

    return I2OSUCCESS;
}

/**************************************************
 * function: I2OFIFOEnable
 *
 * description: Enable the circular queue
 *              return I2OSUCCESS if no error.
 *              Otherwise I2OQUEINVALID is returned.
 *
 * note:
 *************************************************/
I2OSTATUS I2OFIFOEnable( unsigned int eumbbar )
{
    unsigned int val;

    if ( fifo_stat.qba == 0xfffffff )
    {
	return I2OQUEINVALID;
    }
	    
    val = load_runtime_reg( eumbbar, I2O_MUCR );
    store_runtime_reg( eumbbar, I2O_MUCR, val | 0x1 );

    return I2OSUCCESS;
}

/**************************************************
 * function: I2OFIFODisable
 *
 * description: Disable the circular queue
 *
 * note:
 *************************************************/
void I2OFIFODisable( unsigned int eumbbar )
{
    unsigned int val = load_runtime_reg( eumbbar, I2O_MUCR );
    if ( fifo_stat.qba == 0xffffffff )
    {
	/* not enabled */
	return;
    }
    
    store_runtime_reg( eumbbar, I2O_MUCR, val & 0xfffffffe );
}

/****************************************************
 * function: I2OFIFOAlloc
 *
 * description: Allocate a free MFA from free FIFO.
 *              return I2OSUCCESS if no error.
 *              return I2OQUEEMPTY if no more free MFA.
 *              return I2OINVALID on other errors.
 *
 *              A free MFA must be allocated before a
 *              message can be posted.
 *
 * note:
 * PCI Master allocates a free MFA from inbound queue of device
 * (pcsrbar is the base,) through the inbound queue port of device
 * while local processor allocates a free MFA from its outbound
 * queue (eumbbar is the base.)
 *
 ****************************************************/
I2OSTATUS I2OFIFOAlloc( LOCATION loc,
		        unsigned int base,
		        void         **pMsg )
{
    I2OSTATUS stat = I2OSUCCESS;
    void *pHdr, *pTil;
    
    if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff )
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -