/**************************************************************************** * * * Copyright 2004-2011 NetApp Inc. All rights reserved. This file is * * confidential and a trade secret of NetApp Inc. The receipt or * * possession of this file does not convey any rights to reproduce or * * disclose its contents or to manufacture, use, or sell anything it may * * describe, in whole, or in part, without the specific written consent of * * NetApp Inc. * * * ****************************************************************************/ /**************************************************************************** * * * NAME hddMgr.c * * SUMMARY * * VERSION %version: % * * UPDATE DATE %date_modified: % * * PROGRAMMER %created_by: Merck Hung % * * * * Copyright 2002-2011 NetApp Inc. All Rights Reserved. * * * * DESCRIPTION: * * * ****************************************************************************/ #include #include #include #include #include #include #include #include #include "hddMgr.h" static int verbose = 0, silent = 0; //int createHddNodes( int sas0, int sas1, int sas2 ) { int createHddNodes( int phy0_3, int phy4_7, int phy8_11 ) { char path[ MAX_BUF_SIZE ]; DIR *top, *second, *third, *fourth, *add; struct dirent *dir, *dir1, *dir2, *dir3, *adddir; int ch1, id1, ch2, id2, ch3, id3, ch4, id4; int tgt, tgt1, tgt2, eport, phyid; int major, minor, ret, slot, swp, encl, drv, ioc; int cnt = 0; // Obtain info of Ctl slot slot = findCtlSlot(); encl = findEnclosure(); //Bernie slot = CTL_SLOT_A; encl = ENCLOSURE_CAMDEN; if( slot != CTL_SLOT_A && slot != CTL_SLOT_B ) { if( !silent || verbose ) fprintf( stderr, "Internal error: slot = %d\n", slot ); return -1; } if( encl != ENCLOSURE_EBBETS && encl != ENCLOSURE_CAMDEN && encl != ENCLOSURE_WSAS ) { if( !silent || verbose ) fprintf( stderr, "Internal error: enclosure = %d\n", encl ); return -1; } // Open the top directory top = opendir( EXPANDER_PATH ); if( !top ) return -1; for( dir = readdir( top ) ; dir ; dir = readdir( top ) ) { // Skip "." & ".." if( !strcmp( dir->d_name, "." ) || !strcmp( dir->d_name, ".." ) ) continue; // Get CH & ID sscanf( dir->d_name, EXPANDER_PREFIX "%d:%d", &ch1, &id1 ); cnt = getOrderNumOfExp( EXPANDER_PATH, ch1, id1 ); // Walk through all PHYs for( phyid = 0 ; phyid < MAX_PHY_NUM ; phyid++ ) { snprintf( path, MAX_BUF_SIZE, EXPANDER_PATH "/%s/device/%s%d:%d:%d/port", dir->d_name, PHY_PREFIX, ch1, id1, phyid ); // // Second Layer // second = opendir( path ); if( !second ) continue; // Find out tgt id for( dir1 = readdir( second ) ; dir1 ; dir1 = readdir( second ) ) { if( strncmp( dir1->d_name, ENDDEV_PREFIX, strlen( ENDDEV_PREFIX ) ) ) continue; // Only allow ENDDEV_PREFIX sscanf( dir1->d_name, ENDDEV_PREFIX "%d:%d:%d", &ch2, &id2, &tgt ); snprintf( path, MAX_BUF_SIZE, EXPANDER_PATH "/%s/device/%s%d:%d:%d/port/%s%d:%d:%d", dir->d_name, PHY_PREFIX, ch1, id1, phyid, ENDDEV_PREFIX, ch2, id2, tgt ); add = opendir( path ); if( !add ) continue; // Find out tgt1 id for( adddir = readdir( add ) ; adddir ; adddir = readdir( add ) ) { // Only allow target device if( strncmp( adddir->d_name, TARGET_PREFIX, strlen( TARGET_PREFIX ) ) ) continue; // Only allow ENDDEV_PREFIX sscanf( adddir->d_name, TARGET_PREFIX "%d:%d:%d", &ch3, &id3, &tgt1 ); snprintf( path, MAX_BUF_SIZE, EXPANDER_PATH "/%s/device/%s%d:%d:%d/port/%s%d:%d:%d/%s%d:%d:%d", dir->d_name, PHY_PREFIX, ch1, id1, phyid, ENDDEV_PREFIX, ch2, id2, tgt, TARGET_PREFIX, ch3, id3, tgt1 ); // // Third Layer // third = opendir( path ); if( !third ) continue; // Find out HDD name for( dir2 = readdir( third ) ; dir2 ; dir2 = readdir( third ) ) { // Skip "." & ".." if( !strcmp( dir2->d_name, "." ) || !strcmp( dir2->d_name, ".." ) || !strcmp( dir2->d_name, "subsystem" ) || !strcmp( dir2->d_name, "uevent" ) ) continue; sscanf( dir2->d_name, "%d:%d:%d:%d", &ch4, &id4, &tgt2, &eport ); snprintf( path, MAX_BUF_SIZE, EXPANDER_PATH "/%s/device/%s%d:%d:%d/port/%s%d:%d:%d/%s%d:%d:%d/%d:%d:%d:%d/block", dir->d_name, PHY_PREFIX, ch1, id1, phyid, ENDDEV_PREFIX, ch2, id2, tgt, TARGET_PREFIX, ch3, id3, tgt1, ch4, id4, tgt2, eport ); // // Fourth Layer // fourth = opendir( path ); if( !fourth ) continue; for( dir3 = readdir( fourth ) ; dir3 ; dir3 = readdir( fourth ) ) { // Skip "." & ".." if( !strcmp( dir3->d_name, "." ) || !strcmp( dir3->d_name, ".." ) ) continue; snprintf( path, MAX_BUF_SIZE, EXPANDER_PATH "/%s/device/%s%d:%d:%d/port/%s%d:%d:%d/%s%d:%d:%d/%d:%d:%d:%d/block/%s/dev", dir->d_name, PHY_PREFIX, ch1, id1, phyid, ENDDEV_PREFIX, ch2, id2, tgt, TARGET_PREFIX, ch3, id3, tgt1, ch4, id4, tgt2, eport, dir3->d_name ); // Define system drive number if( obtainMajorMinorNo( path, &major, &minor ) ) continue; // Find out IOC number ioc = findSasIocNo( dir3->d_name ); if( ioc < 0 ) continue; // Handle SAS0 remote path #if defined(CTRLER_SOYUZ) swp = slot; if( ioc == 0 ) { if( swp == CTL_SLOT_A ) swp = CTL_SLOT_B; else swp = CTL_SLOT_A; } #else swp = slot; if( phy4_7 == 1 ) { if( swp == CTL_SLOT_A ) swp = CTL_SLOT_B; else swp = CTL_SLOT_A; } #endif // Find System Defined Drive NO & Ioc NO if( encl == ENCLOSURE_WSAS ) drv = findWsasDrvByExpAndPhy( swp, cnt - 1, phyid ); else drv = findSasDrvByPhy( encl, swp, phyid ); // Check DRV value if( drv < 0 ) continue; #if defined(CTRLER_SOYUZ) // Avoid miscreate nodes if( (ioc == 0 && phy4_7 != 1) || (ioc == 1 && phy8_11 != 1) || (ioc == 2 && phy0_3 != 1) ) continue; #endif if( !silent || verbose ) printf( "HDD Present: " HDD_PREFIX_SAS "%d" HDD_SUFFIX_SYS "%d\t(%d:%d)\n", ioc, drv, major, minor ); // Create Device Node snprintf( path, MAX_BUF_SIZE, DEV_BASE_PATH "/" HDD_PREFIX_SAS "%d" HDD_SUFFIX_SYS "%d", ioc, drv ); // Make device node unlink( path ); ret = mknod( path, S_IFBLK | 0660, makedev( major, minor ) ); if( ret ) { if( !silent || verbose ) fprintf( stderr, "Failed to create device: %s (%d)\n", path, ret ); } } closedir( fourth ); } closedir( third ); } closedir( add ); } closedir( second ); } } closedir( top ); return 0; } void usage( void ) { fprintf( stderr, "\nNetApp Inc.\n" ); fprintf( stderr, "Diagnostic Firmware Hard Drive Manager " HDD_MGR_VER "\n\n" ); fprintf( stderr, "Usage: \n " HDD_MGR_NAME " PARAM1, PARM2, ...\n\n" ); fprintf( stderr, " SAS1P0 - Enable SAS1 Port 0 (On-Board Fury 3008) to Expander\n" ); fprintf( stderr, " SAS1P1 - Enable SAS1 Port 1 (On-Board Fury 3008) to Expander\n" ); fprintf( stderr, " SAS0Loc - Enable Local SAS0 (3108) to Expander\n" ); fprintf( stderr, " SAS0Rem - Enable Remote SAS0 (3108) to Expander\n" ); fprintf( stderr, " HDD - Enable All HDDs to Expander\n" ); fprintf( stderr, " DISABLE - Disable All Paths to Expander\n" ); fprintf( stderr, " VERBOSE - Display more messages\n" ); fprintf( stderr, " SILENT - Don't display anything\n" ); fprintf( stderr, " NODEV - Don't create device node\n\n" ); } int main( int argc, char **argv ) { int i; int sas0_local = 0, sas0_remote= 0, sas1_port0 = 0, sas1_port1 = 0; int hdd = 0, disall = 0, nodev = 0; int exp_phy8_11 = 0; // Connect to remote Invander ROC int exp_phy20_23 = 0; // Connetc to local Invander ROC int exp_phy12_15 = 0; // Cobra expansion port 0, corresponding to SAS1's port 0 int exp_phy16_19 = 0; // Cobra expansion port 1, corresponding to SAS1's port 1 // No argument if( argc <= 1 ) { usage(); return 0; } // Check for DISBALE if( argc == 2 && !strcasecmp( argv[ 1 ], ARGU_PATH_DIS ) ) { disall = 1; goto goAhead; } // Check for ENABLE for( i = 1 ; i < argc ; i++ ) { if( !strcasecmp( argv[ i ], ARGU_SAS_PREFIX "1P0" ) ) { sas1_port0 = 1; exp_phy12_15 = 1; } else if( !strcasecmp( argv[ i ], ARGU_SAS_PREFIX "1P1" ) ) { sas1_port1 = 1; exp_phy16_19 = 1; } else if( !strcasecmp( argv[ i ], ARGU_SAS_PREFIX "0Loc" ) ) { sas0_local = 1; exp_phy20_23 = 1; } else if( !strcasecmp( argv[ i ], ARGU_SAS_PREFIX "0Rem" ) ) { sas0_remote = 1; exp_phy8_11 = 1; } else if( !strcasecmp( argv[ i ], ARGU_HDD ) ) { hdd = 1; } else if( !strcasecmp( argv[ i ], ARGU_VERBOSE ) ) { verbose = 1; } else if( !strcasecmp( argv[ i ], ARGU_SILENT ) ) { silent = 1; } else if( !strcasecmp( argv[ i ], ARGU_NODEV ) ) { nodev = 1; } else if( !strcasecmp( argv[ i ], ARGU_PATH_DIS ) ) { fprintf( stderr, "\nCannot combine DISABLE with others\n" ); usage(); return -1; } else { fprintf( stderr, "\nInvalid argument(%s)\n", argv[ i ] ); usage(); return -1; } } goAhead: // Print logo if( !silent || verbose ) printf( "\nDiagnostic Firmware Hard Drive Manager, " HDD_MGR_VER "\n" ); if( disall ) { if( verbose ) printf( "All SAS and HDD PATHS are being Disabled.\n" ); goto updateNodes; } if( sas1_port0 ) { if( verbose ) printf( "SAS1 (On-board Fury) Port 0 PATH is being Enabled\n" ); } else { if( verbose ) printf( "SAS1 (On-board Fury) Port 0 PATH is being Disabled\n" ); } if( sas1_port1 ) { if( verbose ) printf( "SAS1 (On-board Fury) Port 1 PATH is being Enabled\n" ); } else { if( verbose ) printf( "SAS1 (On-board Fury) Port 1 PATH is being Disabled\n" ); } if( sas0_local ) { if( verbose ) printf( "(Local) SAS0 PATH is being Enabled\n" ); } else { if( verbose ) printf( "(Local) SAS0 PATH is being Disabled\n" ); } if( sas0_remote ) { if( verbose ) printf( "(Remote) SAS0 PATH is being Enabled\n" ); } else { if( verbose ) printf( "(Remote) SAS0 PATH is being Disabled\n" ); } updateNodes: // Toggle SAS Ctl Map writeSasCtlMap( exp_phy8_11, exp_phy12_15, exp_phy16_19, exp_phy20_23 ); if( hdd ) { if( verbose ) printf( "All HDD PATHs are being Enabled\n" ); // Enable HDD writeDriveMap( 0x00FFFFFF ); } else { if( verbose ) printf( "All HDD PATHs are being Disabled\n" ); // Disable HDD writeDriveMap( 0 ); } // Remove old device nodes removeOldHddNodesByIoc(sas0_local, sas0_remote, sas1_port0, sas1_port1); // Create Ramdisk nodes createRamdiskNodes(); createSataNodes(); createUsbNodes(); // Wait for 5 seconds if( !nodev && !disall ) { // D0elay for all HDDs being presented i = delayForAllHddPresent( findEnclosure(), sas0_local, sas0_remote, sas1_port0, sas1_port1); if( i ) if( !silent || verbose ) fprintf( stderr, "Time out to wait for all HDDs being presented\n" ); // Set the umask umask( 0 ); // Print start bar if( !silent || verbose ) printf( "==============================================\n" ); // Create all device nodes //createHddNodes( phy0_3, phy4_7, phy8_11 ); //newCreateHddNodes( sas0, sas1, sas2 ); if (sas0_local) system("sh createHddNodes.sh 1 0 0 0"); if (sas0_remote) system("sh createHddNodes.sh 0 1 0 0"); if (sas1_port0) system("sh createHddNodes.sh 0 0 1 0"); if (sas1_port1) system("sh createHddNodes.sh 0 0 0 1"); // Print end bar if( !silent || verbose ) printf( "==============================================\n" ); } return 0; }