Beispiel #1
0
/*******************************************************************************
* qdLoadDriver
*
* DESCRIPTION:
*       QuarterDeck Driver Initialization Routine. 
*       This is the first routine that needs be called by system software. 
*       It takes *cfg from system software, and retures a pointer (*dev) 
*       to a data structure which includes infomation related to this QuarterDeck
*       device. This pointer (*dev) is then used for all the API functions. 
*
* INPUTS:
*       cfg  - Holds device configuration parameters provided by system software.
*
* OUTPUTS:
*       dev  - Holds device information to be used for each API call.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_ALREADY_EXIST    - if device already started
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS:
*     qdUnloadDriver is also provided to do driver cleanup.
*
*******************************************************************************/
GT_STATUS qdLoadDriver
(
    IN  GT_SYS_CONFIG   *cfg,
    OUT GT_QD_DEV    *dev
)
{
    GT_STATUS   retVal;
    GT_LPORT    port;

    DBG_INFO(("qdLoadDriver Called.\n"));

    /* Check for parameters validity        */
    if(dev == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    /* Check for parameters validity        */
    if(cfg == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    /* The initialization was already done. */
    if(dev->devEnabled)
    {
        DBG_INFO(("QuarterDeck already started.\n"));
        return GT_ALREADY_EXIST;
    }

#ifdef GT_PORT_MAP_IN_DEV
    /* Modified to add port mapping functions into device ssystem configuration. */

    if (dev->lport2port == NULL) {
      dev->lport2port = lport2port;
    }

    if (dev->port2lport == NULL) {
      dev->port2lport = port2lport;
    }

    if (dev->lportvec2portvec == NULL) {
      dev->lportvec2portvec = lportvec2portvec;
    }

    if (dev->portvec2lportvec == NULL) {
      dev->portvec2lportvec = portvec2lportvec;
    }
#endif
  
    if(gtRegister(dev,&(cfg->BSPFunctions)) != GT_TRUE)
    {
       DBG_INFO(("gtRegister Failed.\n"));
       return GT_FAIL;
    }
    dev->accessMode = (GT_U8)cfg->mode.scanMode;
    if (dev->accessMode == SMI_MULTI_ADDR_MODE)
    {
        dev->baseRegAddr = 0;
        dev->phyAddr = (GT_U8)cfg->mode.baseAddr;
    }
    else
    {
        dev->baseRegAddr = (GT_U8)cfg->mode.baseAddr;
        dev->phyAddr = 0;
    }


    /* Initialize the driver    */
    retVal = driverConfig(dev);
    if(retVal != GT_OK)
    {
        DBG_INFO(("driverConfig Failed.\n"));
        return retVal;
    }

    /* Initialize dev fields.         */
    dev->cpuPortNum = cfg->cpuPortNum;
    dev->maxPhyNum = 5;
    dev->devGroup = 0;
    dev->devStorage = 0;
    /* Assign Device Name */
    dev->devName = 0;
    dev->devName1 = 0;

    dev->validSerdesVec = 0;

    if((dev->deviceId&0xfff8)==GT_88EC000) /* device id 0xc00 - 0xc07 are GT_88EC0XX */
      dev->deviceId=GT_88EC000;

    switch(dev->deviceId)
    {
        case GT_88E6021:
                dev->numOfPorts = 3;
                dev->maxPorts = 3;
                dev->maxPhyNum = 2;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6021;
                break;

        case GT_88E6051:
                dev->numOfPorts = 5;
                dev->maxPorts = 5;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6051;
                break;

        case GT_88E6052:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6052;
                break;

        case GT_88E6060:
                if((dev->cpuPortNum != 4)&&(dev->cpuPortNum != 5))
                {
                    return GT_FAIL;
                }
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6060;
                break;

        case GT_88E6031:
                dev->numOfPorts = 3;
                dev->maxPorts = 6;
                dev->maxPhyNum = 3;
                dev->validPortVec = 0x31;    /* port 0, 4, and 5 */
                dev->validPhyVec = 0x31;    /* port 0, 4, and 5 */
                dev->devName = DEV_88E6061;
                break;

        case GT_88E6061:
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 6;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6061;
                break;

        case GT_88E6035:
                dev->numOfPorts = 3;
                dev->maxPorts = 6;
                dev->maxPhyNum = 3;
                dev->validPortVec = 0x31;    /* port 0, 4, and 5 */
                dev->validPhyVec = 0x31;    /* port 0, 4, and 5 */
                dev->devName = DEV_88E6065;
                break;

        case GT_88E6065:
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 6;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6065;
                break;

        case GT_88E6063:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6063;
                break;

        case GT_FH_VPN:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_FH_VPN;
                break;

        case GT_FF_EG:
                if(dev->cpuPortNum != 5)
                {
                    return GT_FAIL;
                }
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_FF_EG;
                break;

        case GT_FF_HG:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_FF_HG;
                break;

        case GT_88E6083:
                dev->numOfPorts = 10;
                dev->maxPorts = 10;
                dev->maxPhyNum = 8;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6083;
                break;

        case GT_88E6153:
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 6;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6183;
                break;

        case GT_88E6181:
                dev->numOfPorts = 8;
                dev->maxPorts = 8;
                dev->maxPhyNum = 8;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6181;
                break;

        case GT_88E6183:
                dev->numOfPorts = 10;
                dev->maxPorts = 10;
                dev->maxPhyNum = 10;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6183;
                break;

        case GT_88E6093:
                dev->numOfPorts = 11;
                dev->maxPorts = 11;
                dev->maxPhyNum = 11;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6093;
                break;

        case GT_88E6092:
                dev->numOfPorts = 11;
                dev->maxPorts = 11;
                dev->maxPhyNum = 11;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6092;
                break;

        case GT_88E6095:
                dev->numOfPorts = 11;
                dev->maxPorts = 11;
                dev->maxPhyNum = 11;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6095;
                break;

        case GT_88E6097:
                dev->numOfPorts = 11;
                dev->maxPorts = 11;
                dev->maxPhyNum = 11;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6097;
                break;

        case GT_88E6096:
                dev->numOfPorts = 11;
                dev->maxPorts = 11;
                dev->maxPhyNum = 11;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6096;
                break;

        case GT_88E6046:
                dev->numOfPorts = 6;
                dev->maxPorts = 11;
                dev->maxPhyNum = 11;
                dev->validPortVec = 0x60F;
                dev->validPhyVec = 0x60F;
                dev->devName = DEV_88E6096;
                break;

        case GT_88E6085:
                dev->numOfPorts = 10;
                dev->maxPorts = 11;
                dev->maxPhyNum = 11;
                dev->validPortVec = 0x6FF;
                dev->validPhyVec = 0x6FF;
                dev->devName = DEV_88E6096;
                break;

        case GT_88E6152:
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 6;
                dev->validPortVec = 0x28F;
                dev->validPhyVec = 0x28F;
                dev->devName = DEV_88E6182;
                break;

        case GT_88E6155:
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 6;
                dev->validPortVec = 0x28F;
                dev->validPhyVec = 0x28F;
                dev->devName = DEV_88E6185;
                break;

        case GT_88E6182:
                dev->numOfPorts = 10;
                dev->maxPorts = 10;
                dev->maxPhyNum = 10;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6182;
                break;

        case GT_88E6185:
                dev->numOfPorts = 10;
                dev->maxPorts = 10;
                dev->maxPhyNum = 10;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->devName = DEV_88E6185;
                break;

        case GT_88E6121:
                dev->numOfPorts = 3;
                dev->maxPorts = 8;
                dev->maxPhyNum = 3;
                dev->validPortVec = 0xE;    /* port 1, 2, and 3 */
                dev->validPhyVec = 0xE;        /* port 1, 2, and 3 */
                dev->devName = DEV_88E6108;
                break;

        case GT_88E6122:
                dev->numOfPorts = 6;
                dev->maxPorts = 8;
                dev->maxPhyNum = 16;
                dev->validPortVec = 0x7E;    /* port 1 ~ 6 */
                dev->validPhyVec = 0xF07E;    /* port 1 ~ 6, 12 ~ 15 (serdes) */
                dev->validSerdesVec = 0xF000;
                dev->devName = DEV_88E6108;
                break;

        case GT_88E6131:
        case GT_88E6108:
                dev->numOfPorts = 8;
                dev->maxPorts = 8;
                dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
                dev->validSerdesVec = 0xF000;
                dev->devName = DEV_88E6108;
                break;

        case GT_88E6123:
                dev->numOfPorts = 3;
                dev->maxPorts = 6;
                dev->maxPhyNum = 14;
                dev->validPortVec = 0x23;
                dev->validPhyVec = 0x303F;
                dev->validSerdesVec = 0x3000;
                dev->devName = DEV_88E6161;
                break;

        case GT_88E6161:
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 14;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x303F;
                dev->validSerdesVec = 0x3000;
                dev->devName = DEV_88E6161;
                break;

        case GT_88E6165:
                dev->numOfPorts = 6;
                dev->maxPorts = 6;
                dev->maxPhyNum = 14;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x303F;
                dev->validSerdesVec = 0x3000;
                dev->devName = DEV_88E6165;
                break;

        case GT_88E6351:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName = DEV_88E6351;
                break;

        case GT_88E6175:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName1 = DEV_88E6175; /* test device group 1 */
                break;

        case GT_88E6171 :
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName = DEV_88E6171;
                break;

        case GT_88E6350 :
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName = DEV_88E6371;
                break;

        case GT_88EC000 :
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName1 = DEV_88EC000;
                break;
        case GT_88E6020:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName1 = DEV_88E3020;
                break;
        case GT_88E6070:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName1 = DEV_88E3020;
                break;
        case GT_88E6071:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName1 = DEV_88E3020;
                break;
        case GT_88E6220:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName1 = DEV_88E3020;
                break;
        case GT_88E6250:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 5;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->devName1 = DEV_88E3020;
                break;
        case GT_88E6172:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x1F;
                dev->validSerdesVec = 0x8000;
                dev->devName = DEV_88E6172;
                break;

        case GT_88E6176:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x7F;
                dev->validSerdesVec = 0x8000;
                dev->devName = DEV_88E6176;
                break;

        case GT_88E6240:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x7F;
                dev->validSerdesVec = 0x8000;
                dev->devName = DEV_88E6240;
                break;

        case GT_88E6352:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x7F;
                dev->validSerdesVec = 0x8000;
                dev->devName = DEV_88E6352;
                break;

        case GT_88E6320:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x18;
                dev->validSerdesVec = 0x3000;
                dev->devName1 = DEV_88E6320;
                break;

        case GT_88E6321:
                dev->numOfPorts = 7;
                dev->maxPorts = 7;
                dev->maxPhyNum = 12;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x18;
                dev->validSerdesVec = 0x3000;
                dev->devName1 = DEV_88E6321;
                break;

        case GT_88E6999:  /* Opus */
                dev->numOfPorts = 11;
                dev->maxPorts = 11;
                dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x0;
                dev->validSerdesVec = 0x0000;
                dev->devName1 = DEV_88E6999;
                break;

		case GT_88E6390:  /* Peridot Full Featured Device */
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0;
                dev->validSerdesVec = 0x0000;
                dev->devName1 = DEV_88E6390;
				break;

		case GT_88E6360:  /* Peridot 5 GE PHY version */
				dev->numOfPorts = 5;
				dev->maxPorts = 5;
				dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x0;
                dev->validSerdesVec = 0x0000;
                dev->devName1 = DEV_88E6390;
				break;

		case GT_88E6290:  /* Peridot FE PHY version */
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x0;
                dev->validSerdesVec = 0x0000;
                dev->devName1 = DEV_88E6290;
				break;

		case GT_88E6290A:  /* Peridot Forced FE PHY (no AutoNeg) for Automotive */
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x0;
                dev->validSerdesVec = 0x0000;
                dev->devName1 = DEV_88E6290A;
				break;

		case GT_88E6191:  /* Peridot No AVB */
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x0;
                dev->validSerdesVec = 0x0000;
                dev->devName1 = DEV_88E6190;
				break;

		case GT_88E6190:  /* Peridot  No AVB, Z80 NIC, TCAM nor Cut Through */
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 16;
                dev->validPortVec = (1 << dev->numOfPorts) - 1;
                dev->validPhyVec = 0x0;
                dev->validSerdesVec = 0x0000;
                dev->devName1 = DEV_88E6191;
				break;

        default:
                DBG_INFO(("Unknown Device. Initialization failed\n"));
                return GT_FAIL;
    }

    dev->cpuPortNum = GT_PORT_2_LPORT(cfg->cpuPortNum);

    if(dev->cpuPortNum == GT_INVALID_PORT)
    {
        if(GT_LPORT_2_PORT((GT_LPORT)cfg->cpuPortNum) != GT_INVALID_PORT)
        {
            dev->cpuPortNum = cfg->cpuPortNum;
        }
        else
        {
            return GT_BAD_CPU_PORT;
        }
    }
    /* Initialize the MultiAddress Register Access semaphore.    */
    if((dev->multiAddrSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the ATU semaphore.    */
    if((dev->atuRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the VTU semaphore.    */
    if((dev->vtuRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the STATS semaphore.    */
    if((dev->statsRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the PIRL semaphore.    */
    if((dev->pirlRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the PTP semaphore.    */
    if((dev->ptpRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the Table semaphore.    */
    if((dev->tblRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the EEPROM Configuration semaphore.    */
    if((dev->eepromRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the PHY Device Register Access semaphore.    */
    if((dev->phyRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the Remote management Register Access semaphore.    */
    if((dev->hwAccessRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the ports states to forwarding mode. */
    if(cfg->initPorts == GT_TRUE)
    {
        for (port=0; port<dev->numOfPorts; port++)
        {
            if((retVal = gstpSetPortState(dev,port,GT_PORT_FORWARDING)) != GT_OK)
               {
                DBG_INFO(("Failed.\n"));
                qdUnloadDriver(dev);
                   return retVal;
            }
        }
    }

    dev->use_mad = GT_FALSE;
#ifdef GT_USE_MAD  
	{
	  int portPhyAddr=0;
	  unsigned int validPhyVec = dev->validPhyVec;
	  while((validPhyVec&1)==0)
	  {
        validPhyVec >>= 1;
	    portPhyAddr++;
	  }
      DBG_INFO(("@@@@@@@@@@ qd_madInit\n"));
      if((retVal = qd_madInit(dev, portPhyAddr)) != GT_OK)
      {
        DBG_INFO(("Initialize MAD failed.\n"));
        qdUnloadDriver(dev);
        return retVal;
      }
	}
#endif

    if(cfg->skipInitSetup == GT_SKIP_INIT_SETUP)
    {
        dev->devEnabled = 1;
        dev->devNum = cfg->devNum;

        DBG_INFO(("OK.\n"));
        return GT_OK;
    }

    if(IS_IN_DEV_GROUP(dev,DEV_ENHANCED_CPU_PORT))
    {
        if((retVal = gsysSetRsvd2CpuEnables(dev,0)) != GT_OK)
        {
            DBG_INFO(("gsysGetRsvd2CpuEnables failed.\n"));
            qdUnloadDriver(dev);
            return retVal;
        }

        if((retVal = gsysSetRsvd2Cpu(dev,GT_FALSE)) != GT_OK)
        {
            DBG_INFO(("gsysSetRsvd2Cpu failed.\n"));
            qdUnloadDriver(dev);
            return retVal;
        }
    }

    if (IS_IN_DEV_GROUP(dev,DEV_CPU_DEST_PER_PORT))
    {
        for (port=0; port<dev->numOfPorts; port++)
        {
            retVal = gprtSetCPUPort(dev,port,dev->cpuPortNum);
            if(retVal != GT_OK)
            {
                DBG_INFO(("Failed.\n"));
                qdUnloadDriver(dev);
                   return retVal;
            }
        }
    }

    if(IS_IN_DEV_GROUP(dev,DEV_CPU_PORT))
    {
        retVal = gsysSetCPUPort(dev,dev->cpuPortNum);
        if(retVal != GT_OK)
           {
            DBG_INFO(("Failed.\n"));
            qdUnloadDriver(dev);
               return retVal;
        }
    }

    if(IS_IN_DEV_GROUP(dev,DEV_CPU_DEST))
    {
        retVal = gsysSetCPUDest(dev,dev->cpuPortNum);
        if(retVal != GT_OK)
           {
            DBG_INFO(("Failed.\n"));
            qdUnloadDriver(dev);
               return retVal;
        }
    }

    if(IS_IN_DEV_GROUP(dev,DEV_MULTICAST))
    {
        if((retVal = gsysSetRsvd2Cpu(dev,GT_FALSE)) != GT_OK)
        {
            DBG_INFO(("gsysSetRsvd2Cpu failed.\n"));
            qdUnloadDriver(dev);
            return retVal;
        }
    }

    if (IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
    {
        retVal = gpirlInitialize(dev);
        if(retVal != GT_OK)
           {
            DBG_INFO(("Failed.\n"));
            qdUnloadDriver(dev);
               return retVal;
        }
    }

    if (IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
    {
        retVal = gpirl2Initialize(dev);
        if(retVal != GT_OK)
           {
            DBG_INFO(("Failed.\n"));
            qdUnloadDriver(dev);
               return retVal;
        }
    }
    else if (IS_IN_DEV_GROUP(dev,DEV_PIRL3_RESOURCE))
    {
        retVal = gpirl3Initialize(dev);
        if(retVal != GT_OK)
           {
            DBG_INFO(("Failed.\n"));
            qdUnloadDriver(dev);
               return retVal;
        }
    }

    if(IS_IN_DEV_GROUP(dev,DEV_CPU_PORT_NEED_INIT))
    {
        retVal = gsysInitCPUPort(dev,dev->cpuPortNum);
        if(retVal != GT_OK)
           {
            DBG_INFO(("Failed.\n"));
            qdUnloadDriver(dev);
               return retVal;
        }
    }

    dev->devEnabled = 1;
    dev->devNum = cfg->devNum;

    DBG_INFO(("OK.\n"));
    return GT_OK;
}
/*******************************************************************************
* qdLoadDriver
*
* DESCRIPTION:
*       QuarterDeck Driver Initialization Routine. 
*       This is the first routine that needs be called by system software. 
*       It takes *cfg from system software, and retures a pointer (*dev) 
*       to a data structure which includes infomation related to this QuarterDeck
*       device. This pointer (*dev) is then used for all the API functions. 
*
* INPUTS:
*       cfg  - Holds device configuration parameters provided by system software.
*
* OUTPUTS:
*       dev  - Holds device information to be used for each API call.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_ALREADY_EXIST    - if device already started
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS:
* 	qdUnloadDriver is also provided to do driver cleanup.
*
*******************************************************************************/
GT_STATUS qdLoadDriver
(
    IN  GT_SYS_CONFIG   *cfg,
    OUT GT_QD_DEV	*dev
)
{
    GT_STATUS   retVal;
	GT_LPORT	port;

    DBG_INFO(("qdLoadDriver Called.\n"));

    /* Check for parameters validity        */
    if(dev == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    /* Check for parameters validity        */
    if(cfg == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    /* The initialization was already done. */
    if(dev->devEnabled)
    {
        DBG_INFO(("QuarterDeck already started.\n"));
        return GT_ALREADY_EXIST;
    }

    if(gtRegister(dev,&(cfg->BSPFunctions)) != GT_TRUE)
    {
       DBG_INFO(("gtRegister Failed.\n"));
       return GT_FAIL;
    }
	dev->accessMode = (GT_U8)cfg->mode.scanMode;
	if (dev->accessMode == SMI_MULTI_ADDR_MODE)
	{
		dev->baseRegAddr = 0;
		dev->phyAddr = (GT_U8)cfg->mode.baseAddr;
	}
	else
	{
		dev->baseRegAddr = (GT_U8)cfg->mode.baseAddr;
		dev->phyAddr = 0;
	}

    /* Initialize the driver    */
    retVal = driverConfig(dev);
    if(retVal != GT_OK)
    {
        DBG_INFO(("driverConfig Failed.\n"));
        return retVal;
    }

    /* Initialize dev fields.         */
    dev->cpuPortNum = cfg->cpuPortNum;
    dev->maxPhyNum = 5;
    dev->devGroup = 0;
    dev->devStorage = 0;

    /* Assign Device Name */
    switch(dev->deviceId)
    {
		case GT_88E6021:
				dev->numOfPorts = 3;
				dev->maxPorts = 3;
				dev->maxPhyNum = 2;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6021;
				break;

		case GT_88E6051:
				dev->numOfPorts = 5;
				dev->maxPorts = 5;
				dev->maxPhyNum = 5;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6051;
				break;

		case GT_88E6052:
				dev->numOfPorts = 7;
				dev->maxPorts = 7;
				dev->maxPhyNum = 5;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6052;
				break;

		case GT_88E6060:
				if((dev->cpuPortNum != 4)&&(dev->cpuPortNum != 5))
				{
					return GT_FAIL;
				}
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 5;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6060;
				break;

		case GT_88E6031:
				dev->numOfPorts = 3;
				dev->maxPorts = 6;
				dev->maxPhyNum = 3;
				dev->validPortVec = 0x31;	/* port 0, 4, and 5 */
				dev->validPhyVec = 0x31;	/* port 0, 4, and 5 */
				dev->devName = DEV_88E6061;
				break;

		case GT_88E6061:
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 6;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6061;
				break;

		case GT_88E6035:
				dev->numOfPorts = 3;
				dev->maxPorts = 6;
				dev->maxPhyNum = 3;
				dev->validPortVec = 0x31;	/* port 0, 4, and 5 */
				dev->validPhyVec = 0x31;	/* port 0, 4, and 5 */
				dev->devName = DEV_88E6065;
				break;

		case GT_88E6055:
				dev->numOfPorts = 5;
				dev->maxPorts = 6;
				dev->maxPhyNum = 5;
				dev->validPortVec = 0x2F;	/* port 0,1,2,3, and 5 */
				dev->validPhyVec = 0x2F;	/* port 0,1,2,3, and 5 */
				dev->devName = DEV_88E6065;
				break;

		case GT_88E6065:
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 6;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6065;
				break;

		case GT_88E6063:
				dev->numOfPorts = 7;
				dev->maxPorts = 7;
				dev->maxPhyNum = 5;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6063;
				break;

		case GT_FH_VPN:
				dev->numOfPorts = 7;
				dev->maxPorts = 7;
				dev->maxPhyNum = 5;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_FH_VPN;
				break;

		case GT_FF_EG:
				if(dev->cpuPortNum != 5)
				{
					return GT_FAIL;
				}
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 5;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_FF_EG;
				break;

		case GT_FF_HG:
				dev->numOfPorts = 7;
				dev->maxPorts = 7;
				dev->maxPhyNum = 5;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_FF_HG;
				break;

		case GT_88E6083:
				dev->numOfPorts = 10;
				dev->maxPorts = 10;
				dev->maxPhyNum = 8;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6083;
				break;

		case GT_88E6153:
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 6;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6183;
				break;

		case GT_88E6181:
				dev->numOfPorts = 8;
				dev->maxPorts = 8;
				dev->maxPhyNum = 8;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6181;
				break;

		case GT_88E6183:
				dev->numOfPorts = 10;
				dev->maxPorts = 10;
				dev->maxPhyNum = 10;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6183;
				break;

		case GT_88E6093:
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6093;
				break;

		case GT_88E6092:
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6092;
				break;

		case GT_88E6095:
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6095;
				break;

		case GT_88E6045:
				dev->numOfPorts = 6;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = 0x60F;
				dev->validPhyVec = 0x60F;
				dev->devName = DEV_88E6095;
				break;

		case GT_88E6097:
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6097;
				break;

		case GT_88E6096:
				dev->numOfPorts = 11;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6096;
				break;

		case GT_88E6047:
				dev->numOfPorts = 6;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = 0x60F;
				dev->validPhyVec = 0x60F;
				dev->devName = DEV_88E6097;
				break;

		case GT_88E6046:
				dev->numOfPorts = 6;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = 0x60F;
				dev->validPhyVec = 0x60F;
				dev->devName = DEV_88E6096;
				break;

		case GT_88E6085:
				dev->numOfPorts = 10;
				dev->maxPorts = 11;
				dev->maxPhyNum = 11;
				dev->validPortVec = 0x6FF;
				dev->validPhyVec = 0x6FF;
				dev->devName = DEV_88E6096;
				break;

		case GT_88E6152:
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 6;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6182;
				break;

		case GT_88E6155:
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 6;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6185;
				break;

		case GT_88E6182:
				dev->numOfPorts = 10;
				dev->maxPorts = 10;
				dev->maxPhyNum = 10;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6182;
				break;

		case GT_88E6185:
				dev->numOfPorts = 10;
				dev->maxPorts = 10;
				dev->maxPhyNum = 10;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->devName = DEV_88E6185;
				break;

		case GT_88E6121:
				dev->numOfPorts = 3;
				dev->maxPorts = 8;
				dev->maxPhyNum = 3;
				dev->validPortVec = 0xE;	/* port 1, 2, and 3 */
				dev->validPhyVec = 0xE;		/* port 1, 2, and 3 */
				dev->devName = DEV_88E6108;
				break;

		case GT_88E6122:
				dev->numOfPorts = 6;
				dev->maxPorts = 8;
				dev->maxPhyNum = 16;
				dev->validPortVec = 0x7E;	/* port 1 ~ 6 */
				dev->validPhyVec = 0xF07E;	/* port 1 ~ 6, 12 ~ 15 (serdes) */
				dev->validSerdesVec = 0xF000;
				dev->devName = DEV_88E6108;
				break;

		case GT_88E6131:
		case GT_88E6108:
				dev->numOfPorts = 8;
				dev->maxPorts = 8;
				dev->maxPhyNum = 16;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = (1 << dev->maxPhyNum) - 1;
				dev->validSerdesVec = 0xF000;
				dev->devName = DEV_88E6108;
				break;

		case GT_88E6123:
				dev->numOfPorts = 3;
				dev->maxPorts = 6;
				dev->maxPhyNum = 14;
				dev->validPortVec = 0x23;
				dev->validPhyVec = 0x303F;
				dev->validSerdesVec = 0x3000;
				dev->devName = DEV_88E6161;
				break;

		case GT_88E6140:
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 14;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = 0x303F;
				dev->validSerdesVec = 0x3000;
				dev->devName = DEV_88E6165;
				break;

		case GT_88E6161:
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 14;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = 0x303F;
				dev->validSerdesVec = 0x3000;
				dev->devName = DEV_88E6161;
				break;

		case GT_88E6165:
				dev->numOfPorts = 6;
				dev->maxPorts = 6;
				dev->maxPhyNum = 14;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = 0x303F;
				dev->validSerdesVec = 0x3000;
				dev->devName = DEV_88E6165;
				break;

		case GT_KW2_INT :
				dev->deviceId = GT_88E6351;
				/* fall through */
		case GT_88E6351:
				dev->numOfPorts = 7;
				dev->maxPorts = 7;
				dev->maxPhyNum = 7;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = 0x7F;
				dev->devName = DEV_88E6351;
				break;

		case GT_88E6175:
				dev->numOfPorts = 7;
				dev->maxPorts = 7;
				dev->maxPhyNum = 7;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = 0x7F;
				dev->devName = DEV_88E6175;
				break;

		case GT_88E6125 :
				dev->numOfPorts = 4;
				dev->maxPorts = 7;
				dev->maxPhyNum = 7;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPortVec &= ~(0x7);
				dev->validPhyVec = 0x78;
				dev->devName = DEV_88E6171;
				break;

		case GT_88E6171 :
				dev->numOfPorts = 7;
				dev->maxPorts = 7;
				dev->maxPhyNum = 7;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = 0x7F;
				dev->devName = DEV_88E6171;
				break;

		case GT_88E6321 :
				dev->numOfPorts = 4;
				dev->maxPorts = 7;
				dev->maxPhyNum = 7;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPortVec &= ~(0x7);
				dev->validPhyVec = 0x78;
				dev->devName = DEV_88E6371;
				break;

		case GT_88E6350 :
				dev->numOfPorts = 7;
				dev->maxPorts = 7;
				dev->maxPhyNum = 7;
				dev->validPortVec = (1 << dev->numOfPorts) - 1;
				dev->validPhyVec = 0x7F;
				dev->devName = DEV_88E6371;
				break;

		default:
				DBG_INFO(("Unknown Device. Initialization failed\n"));
				return GT_FAIL;
    }

    dev->cpuPortNum = GT_PORT_2_LPORT(cfg->cpuPortNum);

    if(dev->cpuPortNum == GT_INVALID_PORT)
	{
    	if(GT_LPORT_2_PORT((GT_LPORT)cfg->cpuPortNum) != GT_INVALID_PORT)
		{
		    dev->cpuPortNum = cfg->cpuPortNum;
		}
		else
		{
			return GT_BAD_CPU_PORT;
		}
	}

    /* Initialize the MultiAddress Register Access semaphore.    */
    if((dev->multiAddrSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the ATU semaphore.    */
    if((dev->atuRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the VTU semaphore.    */
    if((dev->vtuRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
		qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the STATS semaphore.    */
    if((dev->statsRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
		qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the PIRL semaphore.    */
    if((dev->pirlRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
		qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the PTP semaphore.    */
    if((dev->ptpRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
		qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the Table semaphore.    */
    if((dev->tblRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
		DBG_INFO(("semCreate Failed.\n"));
		qdUnloadDriver(dev);
		return GT_FAIL;
    }

    /* Initialize the EEPROM Configuration semaphore.    */
    if((dev->eepromRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
		DBG_INFO(("semCreate Failed.\n"));
		qdUnloadDriver(dev);
		return GT_FAIL;
    }

    /* Initialize the PHY Device Register Access semaphore.    */
    if((dev->phyRegsSem = gtSemCreate(dev,GT_SEM_FULL)) == 0)
    {
        DBG_INFO(("semCreate Failed.\n"));
        qdUnloadDriver(dev);
        return GT_FAIL;
    }

    /* Initialize the ports states to forwarding mode. */
    if(cfg->initPorts == GT_TRUE)
    {
		for (port=0; port<dev->numOfPorts; port++)
		{
			if((retVal = gstpSetPortState(dev,port,GT_PORT_FORWARDING)) != GT_OK)
   			{
	    	    DBG_INFO(("Failed.\n"));
				qdUnloadDriver(dev);
   		    	return retVal;
	    	}
		}
    }

    if(cfg->skipInitSetup == GT_SKIP_INIT_SETUP)
	{
	    dev->devEnabled = 1;
    	dev->devNum = cfg->devNum;

	    DBG_INFO(("OK.\n"));
    	return GT_OK;
	}

	if(IS_IN_DEV_GROUP(dev,DEV_ENHANCED_CPU_PORT))
	{
		if((retVal = gsysSetRsvd2CpuEnables(dev,0)) != GT_OK)
		{
	        DBG_INFO(("gsysGetRsvd2CpuEnables failed.\n"));
			qdUnloadDriver(dev);
			return retVal;
		}

		if((retVal = gsysSetRsvd2Cpu(dev,GT_FALSE)) != GT_OK)
		{
	        DBG_INFO(("gsysSetRsvd2Cpu failed.\n"));
			qdUnloadDriver(dev);
			return retVal;
		}
	}

	if (IS_IN_DEV_GROUP(dev,DEV_CPU_DEST_PER_PORT))
	{
		for (port=0; port<dev->numOfPorts; port++)
		{
			retVal = gprtSetCPUPort(dev,port,dev->cpuPortNum);
		    if(retVal != GT_OK)
    		{
	    	    DBG_INFO(("Failed.\n"));
				qdUnloadDriver(dev);
	   	    	return retVal;
		    }
		}
	}

	if(IS_IN_DEV_GROUP(dev,DEV_CPU_PORT))
	{
		retVal = gsysSetCPUPort(dev,dev->cpuPortNum);
	    if(retVal != GT_OK)
   		{
    	    DBG_INFO(("Failed.\n"));
			qdUnloadDriver(dev);
   	    	return retVal;
	    }
	}

	if(IS_IN_DEV_GROUP(dev,DEV_CPU_DEST))
	{
		retVal = gsysSetCPUDest(dev,dev->cpuPortNum);
	    if(retVal != GT_OK)
   		{
    	    DBG_INFO(("Failed.\n"));
			qdUnloadDriver(dev);
   	    	return retVal;
	    }
	}

	if(IS_IN_DEV_GROUP(dev,DEV_MULTICAST))
	{
		if((retVal = gsysSetRsvd2Cpu(dev,GT_FALSE)) != GT_OK)
		{
	        DBG_INFO(("gsysSetRsvd2Cpu failed.\n"));
			qdUnloadDriver(dev);
			return retVal;
		}
	}

	if (IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE))
	{
		retVal = gpirlInitialize(dev);
	    if(retVal != GT_OK)
   		{
    	    DBG_INFO(("Failed.\n"));
			qdUnloadDriver(dev);
   	    	return retVal;
	    }
	}

	if (IS_IN_DEV_GROUP(dev,DEV_PIRL2_RESOURCE))
	{
		retVal = gpirl2Initialize(dev);
	    if(retVal != GT_OK)
   		{
    	    DBG_INFO(("Failed.\n"));
			qdUnloadDriver(dev);
   	    	return retVal;
	    }
	}

    dev->devEnabled = 1;
    dev->devNum = cfg->devNum;

    DBG_INFO(("OK.\n"));
    return GT_OK;
}