?? i2o1.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 ) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -