//------------------------------------------------------------------- // idnumber.cpp // // This program directly accesses the IDE Hard Disk Controller. // It issues the 'IDENTIFY DRIVE' command to obtain information // about the hard-disk's geometry and its unique serial number. // (NOTE: The 'iopl()' system-call requires 'root' privileges.) // // programmer: ALLAN CRUSE // written on: 29 AUG 2004 //------------------------------------------------------------------- #include // for iopl(), inb(), outb() #include // for printf(), perror() #include // for exit() #include // for strncpy() #define IDE_DATA_REG 0x1F0 #define IDE_ERR_REG 0x1F1 #define IDE_DRV_HEAD 0x1F6 #define IDE_STATUS 0x1F7 #define IDE_COMMAND 0x1F7 #define IDE_CONTROL 0x3F6 #define IDE_ALT_STAT 0x3F6 #define IDE_DEV_ADDR 0x3F7 #define IDENTIFY_DRIVE 0xEC unsigned short buffer[ 256 ]; char serial_number[ 21 ]; int main( void ) { //--------------------------------------------------- // ask Linux to allow programmed i/o from user-space //--------------------------------------------------- if ( iopl( 3 ) < 0 ) { perror( "iopl" ); exit(1); } //-------------------------------------------------------- // select which drive will be accessed (0=master/1=slave) //-------------------------------------------------------- // port 0x1F6 bits: 1 LBA 1 DRV HS3 HS2 HS1 HS0 outb( 0xA0, IDE_DRV_HEAD ); // drive 0 selected //-------------------------------------- // wait for 'device-not-busy' indicator //-------------------------------------- // port 0x1F7 bits: BSY DRDY DF DSC DRQ CORR IDX ERR int status, timeout = 1000; while ( --timeout ) { status = inb( IDE_STATUS ); if ( ( status & 0x80 ) == 0x00 ) break; } if ( timeout == 0 ) { printf( "Timeout -- Device is busy\n" ); exit(1); } //--------------------------------------------------- // COMMAND PHASE: issue command (if drive is ready ) //--------------------------------------------------- asm(" cli "); // disable interrupts status = inb( IDE_STATUS ); if ( ( status & 0xC0 ) == 0x40 ) { outb( IDENTIFY_DRIVE, IDE_COMMAND ); } else { asm(" sti "); // reenable interrupts printf( "Device not ready for command\n" ); exit(1); } //--------------------------------------------- // DATA-TRANSFER PHASE: wait for DRQ indicator //--------------------------------------------- timeout = 1000000; while ( --timeout ) { status = inb( IDE_STATUS ); if ( ( status & 0x88 ) == 0x08 ) break; } if ( timeout == 0 ) { asm(" sti "); // reenable interrupts printf( "Timeout! Data-Transfer unsuccessful\n" ); exit(1); } //------------------------------------------------------------ // RESULT PHASE: transfer data from the drive's sector-buffer //------------------------------------------------------------ for (int i = 0; i < 256; i++) buffer[ i ] = inw( IDE_DATA_REG ); status = inb( IDE_STATUS ); if ( ( status & 0x89 ) == 0x00 ) asm( "sti " ); // reenable interrupts else { int error = inb( IDE_ERR_REG ); asm(" sti " ); // reenable interrupts printf( "Error during result-phase " ); printf( "(status=%02X, error=%02X)\n", status, error ); exit(1); } //-------------------------------------------- // now we display some of the IDE information //-------------------------------------------- strncpy( serial_number, (char*)&buffer[ 10 ], 20 ); printf( "\n\tDisk-Drive Serial Number: %s \n\n", serial_number ); }