u-boot/cpu/mpc824x/drivers/i2o/i2o1.c
wdenk 8bde7f776c * Code cleanup:
- remove trailing white space, trailing empty lines, C++ comments, etc.
  - split cmd_boot.c (separate cmd_bdinfo.c and cmd_load.c)

* Patches by Kenneth Johansson, 25 Jun 2003:
  - major rework of command structure
    (work done mostly by Michal Cendrowski and Joakim Kristiansen)
2003-06-27 21:31:46 +00:00

890 lines
26 KiB
C

/*********************************************************
* $Id
*
* copyright @ Motorola, 1999
*********************************************************/
#include "i2o.h"
extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
#pragma Alias( load_runtime_reg, "load_runtime_reg" );
extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
#pragma Alias( store_runtime_reg, "store_runtime_reg" );
typedef struct _fifo_stat
{
QUEUE_SIZE qsz;
unsigned int qba;
} FIFOSTAT;
FIFOSTAT fifo_stat = { QSIZE_4K, 0xffffffff };
/**********************************************************************************
* function: I2OMsgEnable
*
* description: Enable the interrupt associated with in/out bound msg
* return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
*
* All previously enabled interrupts are preserved.
* note:
* Inbound message interrupt generated by PCI master and serviced by local processor
* Outbound message interrupt generated by local processor and serviced by PCI master
*
* local processor needs to enable its inbound interrupts it wants to handle(LOCAL)
* PCI master needs to enable the outbound interrupts of devices it wants to handle(REMOTE)
************************************************************************************/
I2OSTATUS I2OMsgEnable ( LOCATION loc, /* REMOTE/LOCAL */
unsigned int base, /* pcsrbar/eumbbar */
unsigned char n ) /* b'1' - msg 0
* b'10'- msg 1
* b'11'- both
*/
{
unsigned int reg, val;
if ( ( n & 0x3 ) == 0 )
{
/* neither msg 0, nor msg 1 */
return I2OMSGINVALID;
}
n = (~n) & 0x3;
/* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base
* LOCAL : enable local inbound message, eumbbar as base
*/
reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
val = load_runtime_reg( base, reg );
val &= 0xfffffffc; /* masked out the msg interrupt bits */
val |= n; /* LSB are the one we want */
store_runtime_reg( base, reg, val );
return I2OSUCCESS;
}
/*********************************************************************************
* function: I2OMsgDisable
*
* description: Disable the interrupt associated with in/out bound msg
* Other previously enabled interrupts are preserved.
* return I2OSUCCESS if no error otherwise return I2OMSGINVALID
*
* note:
* local processor needs to disable its inbound interrupts it is not interested(LOCAL)
* PCI master needs to disable outbound interrupts of devices it is not interested(REMOTE)
*********************************************************************************/
I2OSTATUS I2OMsgDisable( LOCATION loc, /* REMOTE/LOCAL */
unsigned int base, /* pcsrbar/eumbbar */
unsigned char n ) /* b'1' - msg 0
* b'10'- msg 1
* b'11'- both
*/
{
unsigned int reg, val;
if ( ( n & 0x3 ) == 0 )
{
/* neither msg 0, nor msg 1 */
return I2OMSGINVALID;
}
/* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base
* LOCAL : disable local inbound message interrupt, eumbbar as base
*/
reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
val = load_runtime_reg( base, reg );
val &= 0xfffffffc; /* masked out the msg interrupt bits */
val |= ( n & 0x3 );
store_runtime_reg( base, reg, val );
return I2OSUCCESS;
}
/**************************************************************************
* function: I2OMsgGet
*
* description: Local processor reads the nth Msg register from its inbound msg,
* or a PCI Master reads nth outbound msg from device
*
* return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
*
* note:
* If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed.
* If it is remote, outbound msg on the device is read; otherwise local inbound msg is read
*************************************************************************/
I2OSTATUS I2OMsgGet ( LOCATION loc, /* REMOTE/LOCAL */
unsigned int base, /*pcsrbar/eumbbar */
unsigned int n, /* 0 or 1 */
unsigned int *msg )
{
if ( n >= I2O_NUM_MSG || msg == 0 )
{
return I2OMSGINVALID;
}
if ( loc == REMOTE )
{
/* read the outbound msg of the device, pcsrbar as base */
*msg = load_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET );
}
else
{
/* read the inbound msg sent by PCI master, eumbbar as base */
*msg = load_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET );
}
return I2OSUCCESS;
}
/***************************************************************
* function: I2OMsgPost
*
* description: Kahlua writes to its nth outbound msg register
* PCI master writes to nth inbound msg register of device
*
* return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
*
* note:
* If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed.
*
* If it is remote, inbound msg on the device is written; otherwise local outbound msg is written
***************************************************************/
I2OSTATUS I2OMsgPost( LOCATION loc, /* REMOTE/LOCAL */
unsigned int base, /*pcsrbar/eumbbar */
unsigned int n, /* 0 or 1 */
unsigned int msg )
{
if ( n >= I2O_NUM_MSG )
{
return I2OMSGINVALID;
}
if ( loc == REMOTE )
{
/* write to the inbound msg register of the device, pcsrbar as base */
store_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET, msg );
}
else
{
/* write to the outbound msg register for PCI master to read, eumbbar as base */
store_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET, msg );
}
return I2OSUCCESS;
}
/***********************************************************************
* function: I2ODBEnable
*
* description: Local processor enables it's inbound doorbell interrupt
* PCI master enables outbound doorbell interrupt of devices
* Other previously enabled interrupts are preserved.
* Return I2OSUCCESS if no error otherwise return I2ODBINVALID
*
* note:
* In DoorBell interrupt is generated by PCI master and serviced by local processor
* Out Doorbell interrupt is generated by local processor and serviced by PCI master
*
* Out Doorbell interrupt is generated by local processor and serviced by PCI master
* PCI master needs to enable the outbound doorbell interrupts of device it wants to handle
**********************************************************************/
I2OSTATUS I2ODBEnable( LOCATION loc, /* REMOTE/LOCAL */
unsigned int base, /* pcsrbar/eumbbar */
unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
{
/* LOCATION - REMOTE : PCI master initializes outbound doorbell message of device
* LOCAL : Kahlua initializes its inbound doorbell message
*/
unsigned int val;
if ( loc == LOCAL && ( in_db & 0x3 ) == 0 )
{
return I2ODBINVALID;
}
if ( loc == REMOTE )
{
/* pcsrbar is base */
val = load_runtime_reg( base, I2O_OMIMR );
val &= 0xfffffff7;
store_runtime_reg( base, I2O_OMIMR , val );
}
else
{
/* eumbbar is base */
val = load_runtime_reg( base, I2O_IMIMR);
in_db = ( (~in_db) & 0x3 ) << 3;
val = ( val & 0xffffffe7) | in_db;
store_runtime_reg( base, I2O_IMIMR, val );
}
return I2OSUCCESS;
}
/**********************************************************************************
* function: I2ODBDisable
*
* description: local processor disables its inbound DoorBell Interrupt
* PCI master disables outbound DoorBell interrupt of device
* Other previously enabled interrupts are preserved.
* return I2OSUCCESS if no error.Otherwise return I2ODBINVALID
*
* note:
* local processor needs to disable its inbound doorbell interrupts it is not interested
*
* PCI master needs to disable outbound doorbell interrupts of device it is not interested
************************************************************************************/
I2OSTATUS I2ODBDisable( LOCATION loc, /* REMOTE/LOCAL */
unsigned int base, /* pcsrbar/eumbbar */
unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
{
/* LOCATION - REMOTE : handle device's out bound message initialization
* LOCAL : handle local in bound message initialization
*/
unsigned int val;
if ( loc == LOCAL && ( in_db & 0x3 ) == 0 )
{
return I2ODBINVALID;
}
if ( loc == REMOTE )
{
/* pcsrbar is the base */
val = load_runtime_reg( base, I2O_OMIMR );
val |= 0x8;
store_runtime_reg( base, I2O_OMIMR, val );
}
else
{
val = load_runtime_reg( base, I2O_IMIMR);
in_db = ( in_db & 0x3 ) << 3;
val |= in_db;
store_runtime_reg( base, I2O_IMIMR, val );
}
return I2OSUCCESS;
}
/**********************************************************************************
* function: I2ODBGet
*
* description: Local processor reads its in doorbell register,
* PCI master reads the outdoorbell register of device.
* After a doorbell register is read, the whole register will be cleared.
* Otherwise, HW keeps generating interrupt.
*
* note:
* If it is not local, pcsrbar must be passed to the function.
* Otherwise eumbbar is passed.
*
* If it is remote, out doorbell register on the device is read.
* Otherwise local in doorbell is read
*
* If the register is not cleared by write to it, any remaining bit of b'1's
* will cause interrupt pending.
*********************************************************************************/
unsigned int I2ODBGet( LOCATION loc, /* REMOTE/LOCAL */
unsigned int base) /* pcsrbar/eumbbar */
{
unsigned int msg, val;
if ( loc == REMOTE )
{
/* read outbound doorbell register of device, pcsrbar is the base */
val = load_runtime_reg( base, I2O_ODBR );
msg = val & 0xe0000000;
store_runtime_reg( base, I2O_ODBR, val ); /* clear the register */
}
else
{
/* read the inbound doorbell register, eumbbar is the base */
val = load_runtime_reg( base, I2O_IDBR );
store_runtime_reg( base, I2O_IDBR, val ); /* clear the register */
msg = val;
}
return msg;
}
/**********************************************************************
* 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: I2OOutMsgStatGet
*
* description: PCI master reads device's outbound msg unit interrupt status.
* Reading an interrupt status register,
* the register will be cleared.
*
* The value of the status register is AND with the outbound
* interrupt mask and result is returned.
*
* note:
* pcsrbar must be passed to the function.
********************************************************************/
I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT *val )
{
unsigned int stat;
unsigned int mask;
if ( val == 0 )
{
return I2OINVALID;
}
/* read device's outbound status */
stat = load_runtime_reg( pcsrbar, I2O_OMISR );
mask = load_runtime_reg( pcsrbar, I2O_OMIMR );
store_runtime_reg( pcsrbar, I2O_OMISR, stat & 0xffffffd7);
stat &= mask;
val->rsvd0 = ( stat & 0xffffffc0 ) >> 6;
val->opqi = ( stat & 0x00000020 ) >> 5;
val->rsvd1 = ( stat & 0x00000010 ) >> 4;
val->odi = ( stat & 0x00000008 ) >> 3;
val->rsvd2 = ( stat & 0x00000004 ) >> 2;
val->om1i = ( stat & 0x00000002 ) >> 1;
val->om0i = ( stat & 0x00000001 );
return I2OSUCCESS;
}
/********************************************************************
* function: I2OInMsgStatGet
*
* description: Local processor reads its inbound msg unit interrupt status.
* Reading an interrupt status register,
* the register will be cleared.
*
* The inbound msg interrupt status is AND with the inbound
* msg interrupt mask and result is returned.
*
* note:
* eumbbar must be passed to the function.
********************************************************************/
I2OSTATUS I2OInMsgStatGet(unsigned int eumbbar, I2OIMSTAT *val)
{
unsigned int stat;
unsigned int mask;
if ( val == 0 )
{
return I2OINVALID;
}
/* read device's outbound status */
stat = load_runtime_reg( eumbbar, I2O_OMISR );
mask = load_runtime_reg( eumbbar, I2O_OMIMR );
store_runtime_reg( eumbbar, I2O_OMISR, stat & 0xffffffe7 );
stat &= mask;
val->rsvd0 = ( stat & 0xfffffe00 ) >> 9;
val->ofoi = ( stat & 0x00000100 ) >> 8;
val->ipoi = ( stat & 0x00000080 ) >> 7;
val->rsvd1 = ( stat & 0x00000040 ) >> 6;
val->ipqi = ( stat & 0x00000020 ) >> 5;
val->mci = ( stat & 0x00000010 ) >> 4;
val->idi = ( stat & 0x00000008 ) >> 3;
val->rsvd2 = ( stat & 0x00000004 ) >> 2;
val->im1i = ( stat & 0x00000002 ) >> 1;
val->im0i = ( stat & 0x00000001 );
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 )
{
if ( fifo_stat.qba == 0xffffffff )
{
/* not enabled */
return;
}
unsigned int val = load_runtime_reg( eumbbar, I2O_MUCR );
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 )
{
/* not configured */
return I2OQUEINVALID;
}
if ( loc == REMOTE )
{
/* pcsrbar is the base and read the inbound free tail ptr */
pTil = (void *)load_runtime_reg( base, I2O_IFQPR );
if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF )
{
stat = I2OQUEEMPTY;
}
else
{
*pMsg = pTil;
}
}
else
{
/* eumbbar is the base and read the outbound free tail ptr */
pHdr = (void *)load_runtime_reg( base, I2O_OFHPR ); /* queue head */
pTil = (void *)load_runtime_reg( base, I2O_OFTPR ); /* queue tail */
/* check underflow */
if ( pHdr == pTil )
{
/* hdr and til point to the same fifo item, no free MFA */
stat = I2OQUEEMPTY;
}
else
{
/* update OFTPR */
*pMsg = (void *)(*(unsigned char *)pTil);
pTil = (void *)((unsigned int)pTil + 4);
if ( (unsigned int)pTil == fifo_stat.qba + ( 4 * ( fifo_stat.qsz << 11 ) ) )
{
/* reach the upper limit */
pTil = (void *)(fifo_stat.qba + ( 3 * (fifo_stat.qsz << 11) ));
}
store_runtime_reg( base, I2O_OFTPR, (unsigned int)pTil );
}
}
return stat;
}
/******************************************************
* function: I2OFIFOFree
*
* description: Free a used MFA back to free queue after
* use.
* return I2OSUCCESS if no error.
* return I2OQUEFULL if inbound free queue
* overflow
*
* note: PCI Master frees a MFA into device's outbound queue
* (OFQPR) while local processor frees a MFA into its
* inbound queue (IFHPR).
*****************************************************/
I2OSTATUS I2OFIFOFree( LOCATION loc,
unsigned int base,
void *pMsg )
{
void **pHdr, **pTil;
I2OSTATUS stat = I2OSUCCESS;
if ( fifo_stat.qba == 0xffffffff || pMsg == 0 )
{
return I2OQUEINVALID;
}
if ( loc == REMOTE )
{
/* pcsrbar is the base */
store_runtime_reg( base, I2O_OFQPR, (unsigned int)pMsg );
}
else
{
/* eumbbar is the base */
pHdr = (void **)load_runtime_reg( base, I2O_IFHPR );
pTil = (void **)load_runtime_reg( base, I2O_IFTPR );
/* store MFA */
*pHdr = pMsg;
/* update IFHPR */
pHdr += 4;
if ( (unsigned int)pHdr == fifo_stat.qba + ( fifo_stat.qsz << 11 ) )
{
/* reach the upper limit */
pHdr = (void **)fifo_stat.qba;
}
/* check inbound free queue overflow */
if ( pHdr != pTil )
{
store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr);
}
else
{
stat = I2OQUEFULL;
}
}
return stat;
}
/*********************************************
* function: I2OFIFOPost
*
* description: Post a msg into FIFO post queue
* the value of msg must be the one
* returned by I2OFIFOAlloc
*
* note: PCI Master posts a msg into device's inbound queue
* (IFQPR) while local processor post a msg into device's
* outbound queue (OPHPR)
*********************************************/
I2OSTATUS I2OFIFOPost( LOCATION loc,
unsigned int base,
void *pMsg )
{
void **pHdr, **pTil;
I2OSTATUS stat = I2OSUCCESS;
if ( fifo_stat.qba == 0xffffffff || pMsg == 0 )
{
return I2OQUEINVALID;
}
if ( loc == REMOTE )
{
/* pcsrbar is the base */
store_runtime_reg( base, I2O_IFQPR, (unsigned int)pMsg );
}
else
{
/* eumbbar is the base */
pHdr = (void **)load_runtime_reg( base, I2O_OPHPR );
pTil = (void **)load_runtime_reg( base, I2O_OPTPR );
/* store MFA */
*pHdr = pMsg;
/* update IFHPR */
pHdr += 4;
if ( (unsigned int)pHdr == fifo_stat.qba + 3 * ( fifo_stat.qsz << 11 ) )
{
/* reach the upper limit */
pHdr = (void **)(fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) );
}
/* check post queue overflow */
if ( pHdr != pTil )
{
store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr);
}
else
{
stat = I2OQUEFULL;
}
}
return stat;
}
/************************************************
* function: I2OFIFOGet
*
* description: Read a msg from FIFO
* This function should be called
* only when there is a corresponding
* msg interrupt.
*
* note: PCI Master reads a msg from device's outbound queue
* (OFQPR) while local processor reads a msg from device's
* inbound queue (IPTPR)
************************************************/
I2OSTATUS I2OFIFOGet( LOCATION loc,
unsigned int base,
void **pMsg )
{
I2OSTATUS stat = I2OSUCCESS;
void *pHdr, *pTil;
if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff )
{
/* not configured */
return I2OQUEINVALID;
}
if ( loc == REMOTE )
{
/* pcsrbar is the base */
pTil = (void *)load_runtime_reg( base, I2O_OFQPR );
if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF )
{
stat = I2OQUEEMPTY;
}
else
{
*pMsg = pTil;
}
}
else
{
/* eumbbar is the base and read the outbound free tail ptr */
pHdr = (void *)load_runtime_reg( base, I2O_IPHPR ); /* queue head */
pTil = (void *)load_runtime_reg( base, I2O_IPTPR ); /* queue tail */
/* check underflow */
if ( pHdr == pTil )
{
/* no free MFA */
stat = I2OQUEEMPTY;
}
else
{
/* update OFTPR */
*pMsg = (void *)(*(unsigned char *)pTil);
pTil = (void *)((unsigned int)pTil + 4);
if ( (unsigned int)pTil == fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) )
{
/* reach the upper limit */
pTil = (void *)(fifo_stat.qba + 1 * (fifo_stat.qsz << 11) );
}
store_runtime_reg( base, I2O_IPTPR, (unsigned int)pTil );
}
}
return stat;
}
/********************************************************
* function: I2OIOP
*
* description: Get the I2O PCI configuration identification
* register.
*
* note: PCI master should pass pcsrbar while local processor
* should pass eumbbar.
*********************************************************/
I2OSTATUS I2OPCIConfigGet( LOCATION loc,
unsigned int base,
I2OIOP * val)
{
unsigned int tmp;
if ( val == 0 )
{
return I2OINVALID;
}
tmp = load_runtime_reg( base, PCI_CFG_CLA );
val->base_class = ( tmp & 0xFF) << 16;
tmp = load_runtime_reg( base, PCI_CFG_SCL );
val->sub_class= ( (tmp & 0xFF) << 8 );
tmp = load_runtime_reg( base, PCI_CFG_PIC );
val->prg_code = (tmp & 0xFF);
return I2OSUCCESS;
}
/*********************************************************
* function: I2OFIFOIntEnable
*
* description: Enable the circular post queue interrupt
*
* note:
* PCI master enables outbound FIFO interrupt of device
* pscrbar is the base
* Device enables its inbound FIFO interrupt
* eumbbar is the base
*******************************************************/
void I2OFIFOIntEnable( LOCATION loc, unsigned int base )
{
unsigned int reg, val;
/* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base
* LOCAL : enable local inbound message, eumbbar as base
*/
reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
val = load_runtime_reg( base, reg );
val &= 0xffffffdf; /* clear the msg interrupt bits */
store_runtime_reg( base, reg, val );
}
/****************************************************
* function: I2OFIFOIntDisable
*
* description: Disable the circular post queue interrupt
*
* note:
* PCI master disables outbound FIFO interrupt of device
* (pscrbar is the base)
* Device disables its inbound FIFO interrupt
* (eumbbar is the base)
*****************************************************/
void I2OFIFOIntDisable( LOCATION loc, unsigned int base )
{
/* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base
* LOCAL : disable local inbound message interrupt, eumbbar as base
*/
unsigned int reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
unsigned int val = load_runtime_reg( base, reg );
val |= 0x00000020; /* masked out the msg interrupt bits */
store_runtime_reg( base, reg, val );
}
/*********************************************************
* function: I2OFIFOOverflowIntEnable
*
* description: Enable the circular queue overflow interrupt
*
* note:
* Device enables its inbound FIFO post overflow interrupt
* and outbound free overflow interrupt.
* eumbbar is the base
*******************************************************/
void I2OFIFOOverflowIntEnable( unsigned int eumbbar )
{
unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR );
val &= 0xfffffe7f; /* clear the two overflow interrupt bits */
store_runtime_reg( eumbbar, I2O_IMIMR, val );
}
/****************************************************
* function: I2OFIFOOverflowIntDisable
*
* description: Disable the circular queue overflow interrupt
*
* note:
* Device disables its inbound post FIFO overflow interrupt
* and outbound free FIFO overflow interrupt
* (eumbbar is the base)
*****************************************************/
void I2OFIFOOverflowIntDisable( unsigned int eumbbar )
{
unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR );
val |= 0x00000180; /* masked out the msg overflow interrupt bits */
store_runtime_reg( eumbbar, I2O_IMIMR, val );
}