void SCSIBusScan ( void ) { // PHASE 1: determine how many host adapters are installed and the // name and version of the ASPI manager // initialize the SRB for the first inquiry SRB_HAInquiry srbHAInquiry; memset ( &srbHAInquiry, 0, sizeof ( SRB_HAInquiry ) ); srbHAInquiry . SRB_Cmd = SC_HA_INQUIRY; srbHAInquiry . SRB_HaId = 0; // get the number of host adapters installed pfnSendASPI32Command ( ( LPSRB ) &srbHAInquiry ); if ( srbHAInquiry . SRB_Status != SS_COMP ) { MessageBox ( NULL, "Host adapter inquiry failed.", "Error FS 006:", MB_ICONSTOP ); return; } BYTE HA_Count = srbHAInquiry . HA_Count; // display ASPI manager information srbHAInquiry . HA_ManagerId [ 16 ] = 0; MessageBox ( NULL, srbHAInquiry . HA_ManagerId, "Installed ASPI manager: ", MB_OK ); // PHASE 2: describe each host adapter and any attached device // for each host adapter... for ( BYTE HA_num = 0; HA_num < HA_Count; HA_num++ ) { char szHA_num [ 10 ]; itoa ( ( int ) HA_num, szHA_num, 10 ); memset ( &srbHAInquiry, 0, sizeof ( SRB_HAInquiry ) ); srbHAInquiry . SRB_Cmd = SC_HA_INQUIRY; srbHAInquiry . SRB_HaId = HA_num; pfnSendASPI32Command ( ( LPSRB ) &srbHAInquiry ); if ( srbHAInquiry . SRB_Status != SS_COMP ) { char szMsg [ 60 ] = "Host adapter number "; strcat ( szMsg, szHA_num ); strcat ( szMsg, ": inquiry failed." ); MessageBox ( NULL, szMsg, "Error FS 007:", MB_ICONSTOP ); } else { char szMsg [ 60 ] = "Host adapter n. "; strcat ( szMsg, szHA_num ); strcat ( szMsg, ":" ); srbHAInquiry.HA_Identifier [ 16 ] = 0; MessageBox ( NULL, srbHAInquiry.HA_Identifier, szMsg, MB_OK ); // for each SCSI id... for ( BYTE SCSI_Id = 0; SCSI_Id < 8; SCSI_Id++ ) { char szSCSI_Id [ 10 ]; itoa ( ( int ) SCSI_Id, szSCSI_Id, 10 ); char szDescription [ 32 ]; char* szResult; // for each logical unit... for ( BYTE SCSI_Lun = 0; SCSI_Lun < 8; SCSI_Lun++ ) { char szSCSI_Lun [ 10 ]; itoa ( ( int ) SCSI_Lun, szSCSI_Lun, 10 ); char szDevice [ 60 ] = "Unknown device type."; char szMsg [ 60 ] = "SCSI id "; strcat ( szMsg, szSCSI_Id ); strcat ( szMsg, " lun " ); strcat ( szMsg, szSCSI_Lun ); SRB_GDEVBlock srbGDEVBlock; memset ( &srbGDEVBlock, 0, sizeof ( srbGDEVBlock ) ); srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; srbGDEVBlock.SRB_HaId = HA_num; srbGDEVBlock.SRB_Target = SCSI_Id; srbGDEVBlock.SRB_Lun = SCSI_Lun; pfnSendASPI32Command ( ( LPSRB ) &srbGDEVBlock ); if ( srbGDEVBlock.SRB_Status != SS_COMP ) continue; if ( srbGDEVBlock.SRB_DeviceType == DTYPE_DASD ) strcpy ( szDevice, "Direct access storage device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_SEQD ) strcpy ( szDevice, "Sequntial access storage device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_PRNT ) strcpy ( szDevice, "Printer device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_PROC ) strcpy ( szDevice, "Processor device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_WORM ) strcpy ( szDevice, "WORM device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM ) strcpy ( szDevice, "CD-ROM device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_SCAN ) strcpy ( szDevice, "Scanner device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_OPTI ) strcpy ( szDevice, "Optical memory device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_JUKE ) strcpy ( szDevice, "Medium changer device" ); if ( srbGDEVBlock.SRB_DeviceType == DTYPE_COMM ) strcpy ( szDevice, "Communication device" ); strcat ( szMsg, " - " ); strcat ( szMsg, szDevice ); szResult = ScsiInquiry ( HA_num, SCSI_Id, SCSI_Lun ); strcpy ( szDescription, szResult ); MessageBox ( NULL, szDescription, szMsg, MB_OK ); } } } } // end of function return; } // sept 11, 2001 - Hans R. from Germany reminded me to define ScsiInquiry function. // Here it follows: //-------------------------------------------------------------------------- // August 2nd, 2002: Pierre Leveille makes me observe that this function has a // little bug: szReturnString is defined within the function, and is removed // from the memory when the function exits. But the function returns a pointer // to that string !!! The final result is that the returned char* sometimes is // valid and sometime is not (it is valid until some other program does not // overwrite che szReturnString memory area). A better code would have received // a char* in the parameter list and used it to return the string. Now you have // been warned, and you can change the code accordingly (if you have troubles). // Thanks to Pierre. // char* ScsiInquiry ( BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun ) { char szReturnString [ 30 ]; char szBuffer [ 36 ]; strcpy ( szBuffer, "" ); SRB_ExecSCSICmd srbExec; memset ( &srbExec, 0, sizeof ( SRB_ExecSCSICmd ) ); srbExec.SRB_Cmd = SC_EXEC_SCSI_CMD; srbExec.SRB_HaId = HA_num; srbExec.SRB_Flags = SRB_DIR_IN; srbExec.SRB_Target = SCSI_Id; srbExec.SRB_Lun = SCSI_Lun; srbExec.SRB_BufLen = 36; srbExec.SRB_BufPointer = szBuffer; srbExec.SRB_SenseLen = SENSE_LEN; srbExec.SRB_CDBLen = 6; srbExec.CDBByte [ 0 ] = SCSI_INQUIRY; srbExec.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ] pfnSendASPI32Command ( ( LPSRB ) &srbExec ); while ( srbExec.SRB_Status == SS_PENDING ); if ( srbExec.SRB_Status != SS_COMP ) strcpy ( szReturnString, "Inquiry error." ); else strsub ( szBuffer, szReturnString, 9, 35 ); return szReturnString; } //-------------------------------------------------------------------------- Please note that "strsub" is a function that retrieves a substring from a string: //-------------------------------------------------------------------------- void strsub ( char* src, char* dest, int from, int to ) { from = from - 1; int y = 0; char x; while ( from < to ) { x = src [ from ]; dest [ y ] = x; from = from + 1; y = y + 1; } dest [ y ] = 0; return; } //--------------------------------------------------------------------------