/*++

Copyright (C) Microsoft Corporation, 1992 - 1999

Module Name:

    classkd.c

Abstract:

    Debugger Extension Api for interpretting scsiport structures

Author:

    ervinp

Environment:

    User Mode.

Revision History:

--*/

#include "pch.h"

#include "classpnp.h" // #defines ALLOCATE_SRB_FROM_POOL as needed
#include "classp.h"   // Classpnp's private definitions
#include "cdrom.h"

#include "classkd.h"  // routines that are useful for all class drivers



char *DbgGetIoctlStr(ULONG ioctl)
{
    char *ioctlStr = "?";
    
    switch (ioctl){
        
        #undef MAKE_CASE             
        #define MAKE_CASE(ioctlCode) case ioctlCode: ioctlStr = #ioctlCode; break;

        MAKE_CASE(IOCTL_STORAGE_CHECK_VERIFY)
        MAKE_CASE(IOCTL_STORAGE_CHECK_VERIFY2)
        MAKE_CASE(IOCTL_STORAGE_MEDIA_REMOVAL)
        MAKE_CASE(IOCTL_STORAGE_EJECT_MEDIA)
        MAKE_CASE(IOCTL_STORAGE_LOAD_MEDIA)
        MAKE_CASE(IOCTL_STORAGE_LOAD_MEDIA2)
        MAKE_CASE(IOCTL_STORAGE_RESERVE)
        MAKE_CASE(IOCTL_STORAGE_RELEASE)
        MAKE_CASE(IOCTL_STORAGE_FIND_NEW_DEVICES)
        MAKE_CASE(IOCTL_STORAGE_EJECTION_CONTROL)
        MAKE_CASE(IOCTL_STORAGE_MCN_CONTROL)
        MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_TYPES)
        MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_TYPES_EX)
        MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
        MAKE_CASE(IOCTL_STORAGE_GET_HOTPLUG_INFO)
        MAKE_CASE(IOCTL_STORAGE_RESET_BUS)
        MAKE_CASE(IOCTL_STORAGE_RESET_DEVICE)
        MAKE_CASE(IOCTL_STORAGE_GET_DEVICE_NUMBER)
        MAKE_CASE(IOCTL_STORAGE_PREDICT_FAILURE)
        MAKE_CASE(IOCTL_STORAGE_QUERY_PROPERTY)
        MAKE_CASE(OBSOLETE_IOCTL_STORAGE_RESET_BUS)
        MAKE_CASE(OBSOLETE_IOCTL_STORAGE_RESET_DEVICE)
    }
  
    return ioctlStr;
}


char *DbgGetScsiOpStr(UCHAR ScsiOp)
{
    char *scsiOpStr = "?";
    
    switch (ScsiOp){

        #undef MAKE_CASE             
        #define MAKE_CASE(scsiOpCode) case scsiOpCode: scsiOpStr = #scsiOpCode; break;
        
        MAKE_CASE(SCSIOP_TEST_UNIT_READY)
        MAKE_CASE(SCSIOP_REWIND)    // aka SCSIOP_REZERO_UNIT
        MAKE_CASE(SCSIOP_REQUEST_BLOCK_ADDR)
        MAKE_CASE(SCSIOP_REQUEST_SENSE)
        MAKE_CASE(SCSIOP_FORMAT_UNIT)
        MAKE_CASE(SCSIOP_READ_BLOCK_LIMITS)
        MAKE_CASE(SCSIOP_INIT_ELEMENT_STATUS)   // aka SCSIOP_REASSIGN_BLOCKS
        MAKE_CASE(SCSIOP_RECEIVE)       // aka SCSIOP_READ6
        MAKE_CASE(SCSIOP_SEND)  // aka SCSIOP_WRITE6, SCSIOP_PRINT
        MAKE_CASE(SCSIOP_SLEW_PRINT)    // aka SCSIOP_SEEK6, SCSIOP_TRACK_SELECT
        MAKE_CASE(SCSIOP_SEEK_BLOCK)
        MAKE_CASE(SCSIOP_PARTITION)
        MAKE_CASE(SCSIOP_READ_REVERSE)
        MAKE_CASE(SCSIOP_FLUSH_BUFFER)      // aka SCSIOP_WRITE_FILEMARKS
        MAKE_CASE(SCSIOP_SPACE)
        MAKE_CASE(SCSIOP_INQUIRY)
        MAKE_CASE(SCSIOP_VERIFY6)
        MAKE_CASE(SCSIOP_RECOVER_BUF_DATA)
        MAKE_CASE(SCSIOP_MODE_SELECT)
        MAKE_CASE(SCSIOP_RESERVE_UNIT)
        MAKE_CASE(SCSIOP_RELEASE_UNIT)
        MAKE_CASE(SCSIOP_COPY)
        MAKE_CASE(SCSIOP_ERASE)
        MAKE_CASE(SCSIOP_MODE_SENSE)
        MAKE_CASE(SCSIOP_START_STOP_UNIT)   // aka SCSIOP_STOP_PRINT, SCSIOP_LOAD_UNLOAD
        MAKE_CASE(SCSIOP_RECEIVE_DIAGNOSTIC)
        MAKE_CASE(SCSIOP_SEND_DIAGNOSTIC)
        MAKE_CASE(SCSIOP_MEDIUM_REMOVAL)
        MAKE_CASE(SCSIOP_READ_FORMATTED_CAPACITY)
        MAKE_CASE(SCSIOP_READ_CAPACITY)
        MAKE_CASE(SCSIOP_READ)
        MAKE_CASE(SCSIOP_WRITE)
        MAKE_CASE(SCSIOP_SEEK)  // aka SCSIOP_LOCATE, SCSIOP_POSITION_TO_ELEMENT
        MAKE_CASE(SCSIOP_WRITE_VERIFY)
        MAKE_CASE(SCSIOP_VERIFY)
        MAKE_CASE(SCSIOP_SEARCH_DATA_HIGH)
        MAKE_CASE(SCSIOP_SEARCH_DATA_EQUAL)
        MAKE_CASE(SCSIOP_SEARCH_DATA_LOW)
        MAKE_CASE(SCSIOP_SET_LIMITS)
        MAKE_CASE(SCSIOP_READ_POSITION)
        MAKE_CASE(SCSIOP_SYNCHRONIZE_CACHE)
        MAKE_CASE(SCSIOP_COMPARE)
        MAKE_CASE(SCSIOP_COPY_COMPARE)
        MAKE_CASE(SCSIOP_WRITE_DATA_BUFF)
        MAKE_CASE(SCSIOP_READ_DATA_BUFF)
        MAKE_CASE(SCSIOP_CHANGE_DEFINITION)
        MAKE_CASE(SCSIOP_READ_SUB_CHANNEL)
        MAKE_CASE(SCSIOP_READ_TOC)
        MAKE_CASE(SCSIOP_READ_HEADER)
        MAKE_CASE(SCSIOP_PLAY_AUDIO)
        MAKE_CASE(SCSIOP_GET_CONFIGURATION)
        MAKE_CASE(SCSIOP_PLAY_AUDIO_MSF)
        MAKE_CASE(SCSIOP_PLAY_TRACK_INDEX)
        MAKE_CASE(SCSIOP_PLAY_TRACK_RELATIVE)
        MAKE_CASE(SCSIOP_GET_EVENT_STATUS)
        MAKE_CASE(SCSIOP_PAUSE_RESUME)
        MAKE_CASE(SCSIOP_LOG_SELECT)
        MAKE_CASE(SCSIOP_LOG_SENSE)
        MAKE_CASE(SCSIOP_STOP_PLAY_SCAN)
        MAKE_CASE(SCSIOP_READ_DISK_INFORMATION)
        MAKE_CASE(SCSIOP_READ_TRACK_INFORMATION)
        MAKE_CASE(SCSIOP_RESERVE_TRACK_RZONE)
        MAKE_CASE(SCSIOP_SEND_OPC_INFORMATION)
        MAKE_CASE(SCSIOP_MODE_SELECT10)
        MAKE_CASE(SCSIOP_MODE_SENSE10)
        MAKE_CASE(SCSIOP_CLOSE_TRACK_SESSION)
        MAKE_CASE(SCSIOP_READ_BUFFER_CAPACITY)
        MAKE_CASE(SCSIOP_SEND_CUE_SHEET)
        MAKE_CASE(SCSIOP_PERSISTENT_RESERVE_IN)
        MAKE_CASE(SCSIOP_PERSISTENT_RESERVE_OUT)
        MAKE_CASE(SCSIOP_REPORT_LUNS)
        MAKE_CASE(SCSIOP_BLANK)
        MAKE_CASE(SCSIOP_SEND_KEY)
        MAKE_CASE(SCSIOP_REPORT_KEY)
        MAKE_CASE(SCSIOP_MOVE_MEDIUM)
        MAKE_CASE(SCSIOP_LOAD_UNLOAD_SLOT)  // aka SCSIOP_EXCHANGE_MEDIUM
        MAKE_CASE(SCSIOP_SET_READ_AHEAD)
        MAKE_CASE(SCSIOP_READ_DVD_STRUCTURE)
        MAKE_CASE(SCSIOP_REQUEST_VOL_ELEMENT)
        MAKE_CASE(SCSIOP_SEND_VOLUME_TAG)
        MAKE_CASE(SCSIOP_READ_ELEMENT_STATUS)
        MAKE_CASE(SCSIOP_READ_CD_MSF)
        MAKE_CASE(SCSIOP_SCAN_CD)
        MAKE_CASE(SCSIOP_SET_CD_SPEED)
        MAKE_CASE(SCSIOP_PLAY_CD)
        MAKE_CASE(SCSIOP_MECHANISM_STATUS)
        MAKE_CASE(SCSIOP_READ_CD)
        MAKE_CASE(SCSIOP_SEND_DVD_STRUCTURE)
        MAKE_CASE(SCSIOP_INIT_ELEMENT_RANGE)
    }

    return scsiOpStr;
}


char *DbgGetSrbStatusStr(UCHAR SrbStat)
{
    char *srbStatStr = "?";
    
    switch (SrbStat){

        #undef MAKE_CASE
        #define MAKE_CASE(srbStat) \
                    case srbStat: \
                        srbStatStr = #srbStat; \
                        break; \
                    case srbStat|SRB_STATUS_QUEUE_FROZEN: \
                        srbStatStr = #srbStat "|SRB_STATUS_QUEUE_FROZEN"; \
                        break; \
                    case srbStat|SRB_STATUS_AUTOSENSE_VALID: \
                        srbStatStr = #srbStat "|SRB_STATUS_AUTOSENSE_VALID"; \
                        break; \
                    case srbStat|SRB_STATUS_QUEUE_FROZEN|SRB_STATUS_AUTOSENSE_VALID: \
                        srbStatStr = #srbStat "|SRB_STATUS_QUEUE_FROZEN|SRB_STATUS_AUTOSENSE_VALID"; \
                        break; 

        MAKE_CASE(SRB_STATUS_PENDING)
        MAKE_CASE(SRB_STATUS_SUCCESS)
        MAKE_CASE(SRB_STATUS_ABORTED)
        MAKE_CASE(SRB_STATUS_ABORT_FAILED)
        MAKE_CASE(SRB_STATUS_ERROR)
        MAKE_CASE(SRB_STATUS_BUSY)
        MAKE_CASE(SRB_STATUS_INVALID_REQUEST)
        MAKE_CASE(SRB_STATUS_INVALID_PATH_ID)
        MAKE_CASE(SRB_STATUS_NO_DEVICE)
        MAKE_CASE(SRB_STATUS_TIMEOUT)
        MAKE_CASE(SRB_STATUS_SELECTION_TIMEOUT)
        MAKE_CASE(SRB_STATUS_COMMAND_TIMEOUT)
        MAKE_CASE(SRB_STATUS_MESSAGE_REJECTED)
        MAKE_CASE(SRB_STATUS_BUS_RESET)
        MAKE_CASE(SRB_STATUS_PARITY_ERROR)
        MAKE_CASE(SRB_STATUS_REQUEST_SENSE_FAILED)
        MAKE_CASE(SRB_STATUS_NO_HBA)
        MAKE_CASE(SRB_STATUS_DATA_OVERRUN)
        MAKE_CASE(SRB_STATUS_UNEXPECTED_BUS_FREE)
        MAKE_CASE(SRB_STATUS_PHASE_SEQUENCE_FAILURE)
        MAKE_CASE(SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
        MAKE_CASE(SRB_STATUS_REQUEST_FLUSHED)
        MAKE_CASE(SRB_STATUS_INVALID_LUN)
        MAKE_CASE(SRB_STATUS_INVALID_TARGET_ID)
        MAKE_CASE(SRB_STATUS_BAD_FUNCTION)
        MAKE_CASE(SRB_STATUS_ERROR_RECOVERY)
        MAKE_CASE(SRB_STATUS_NOT_POWERED)
        MAKE_CASE(SRB_STATUS_INTERNAL_ERROR)
    }

    return srbStatStr;
}



char *DbgGetSenseCodeStr(UCHAR SrbStat, ULONG64 SenseDataAddr)
{
    char *senseCodeStr = "?";

    if (SrbStat & SRB_STATUS_AUTOSENSE_VALID){
        UCHAR senseCode;

        senseCode = GetUCHARField(SenseDataAddr, "classpnp!_SENSE_DATA", "SenseKey");
        if (senseCode != BAD_VALUE){
            
            senseCode &= 0x0f;
                         
            switch (senseCode){

                #undef MAKE_CASE             
                #define MAKE_CASE(snsCod) case snsCod: senseCodeStr = #snsCod; break;
            
                MAKE_CASE(SCSI_SENSE_NO_SENSE)
                MAKE_CASE(SCSI_SENSE_RECOVERED_ERROR)
                MAKE_CASE(SCSI_SENSE_NOT_READY)
                MAKE_CASE(SCSI_SENSE_MEDIUM_ERROR)
                MAKE_CASE(SCSI_SENSE_HARDWARE_ERROR)
                MAKE_CASE(SCSI_SENSE_ILLEGAL_REQUEST)
                MAKE_CASE(SCSI_SENSE_UNIT_ATTENTION)
                MAKE_CASE(SCSI_SENSE_DATA_PROTECT)
                MAKE_CASE(SCSI_SENSE_BLANK_CHECK)
                MAKE_CASE(SCSI_SENSE_UNIQUE)
                MAKE_CASE(SCSI_SENSE_COPY_ABORTED)
                MAKE_CASE(SCSI_SENSE_ABORTED_COMMAND)
                MAKE_CASE(SCSI_SENSE_EQUAL)
                MAKE_CASE(SCSI_SENSE_VOL_OVERFLOW)
                MAKE_CASE(SCSI_SENSE_MISCOMPARE)
                MAKE_CASE(SCSI_SENSE_RESERVED)               
            }
        }                
    }

    return senseCodeStr;
}


char *DbgGetAdditionalSenseCodeStr(UCHAR SrbStat, ULONG64 SenseDataAddr)
{
    char *adSenseCodeStr = "?";

    if (SrbStat & SRB_STATUS_AUTOSENSE_VALID){
        UCHAR adSenseCode;

        adSenseCode = GetUCHARField(SenseDataAddr, "classpnp!_SENSE_DATA", "AdditionalSenseCode");
        if (adSenseCode != BAD_VALUE){
            
            switch (adSenseCode){

                #undef MAKE_CASE             
                #define MAKE_CASE(adSnsCod) case adSnsCod: adSenseCodeStr = #adSnsCod; break;

                MAKE_CASE(SCSI_ADSENSE_NO_SENSE)
                MAKE_CASE(SCSI_ADSENSE_LUN_NOT_READY)
                MAKE_CASE(SCSI_ADSENSE_TRACK_ERROR)
                MAKE_CASE(SCSI_ADSENSE_SEEK_ERROR)
                MAKE_CASE(SCSI_ADSENSE_REC_DATA_NOECC)
                MAKE_CASE(SCSI_ADSENSE_REC_DATA_ECC)
                MAKE_CASE(SCSI_ADSENSE_ILLEGAL_COMMAND)
                MAKE_CASE(SCSI_ADSENSE_ILLEGAL_BLOCK)
                MAKE_CASE(SCSI_ADSENSE_INVALID_CDB)
                MAKE_CASE(SCSI_ADSENSE_INVALID_LUN)
                MAKE_CASE(SCSI_ADSENSE_WRITE_PROTECT)   // aka SCSI_ADWRITE_PROTECT
                MAKE_CASE(SCSI_ADSENSE_MEDIUM_CHANGED)
                MAKE_CASE(SCSI_ADSENSE_BUS_RESET)
                MAKE_CASE(SCSI_ADSENSE_INVALID_MEDIA)
                MAKE_CASE(SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)
                MAKE_CASE(SCSI_ADSENSE_POSITION_ERROR)
                MAKE_CASE(SCSI_ADSENSE_OPERATOR_REQUEST)
                MAKE_CASE(SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED)
                MAKE_CASE(SCSI_ADSENSE_COPY_PROTECTION_FAILURE)
                MAKE_CASE(SCSI_ADSENSE_VENDOR_UNIQUE)
                MAKE_CASE(SCSI_ADSENSE_MUSIC_AREA)
                MAKE_CASE(SCSI_ADSENSE_DATA_AREA)
                MAKE_CASE(SCSI_ADSENSE_VOLUME_OVERFLOW)
            }
        }
    }

    return adSenseCodeStr;
}


char *DbgGetAdditionalSenseCodeQualifierStr(UCHAR SrbStat, ULONG64 SenseDataAddr)
{
    char *adSenseCodeQualStr = "?";
    
    if (SrbStat & SRB_STATUS_AUTOSENSE_VALID){
        UCHAR adSenseCode, adSenseCodeQual;

        adSenseCode = GetUCHARField(SenseDataAddr, "classpnp!_SENSE_DATA", "AdditionalSenseCode");
        adSenseCodeQual = GetUCHARField(SenseDataAddr, "classpnp!_SENSE_DATA", "AdditionalSenseCodeQualifier");
        
        if ((adSenseCode != BAD_VALUE) && (adSenseCodeQual != BAD_VALUE)){
    
            switch (adSenseCode){

                #undef MAKE_CASE             
                #define MAKE_CASE(adSnsCodQual) case adSnsCodQual: adSenseCodeQualStr = #adSnsCodQual; break;

                case SCSI_ADSENSE_LUN_NOT_READY:
                    switch (adSenseCodeQual){
                        MAKE_CASE(SCSI_SENSEQ_CAUSE_NOT_REPORTABLE)
                        MAKE_CASE(SCSI_SENSEQ_BECOMING_READY)
                        MAKE_CASE(SCSI_SENSEQ_INIT_COMMAND_REQUIRED)
                        MAKE_CASE(SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED)
                        MAKE_CASE(SCSI_SENSEQ_FORMAT_IN_PROGRESS)
                        MAKE_CASE(SCSI_SENSEQ_REBUILD_IN_PROGRESS)
                        MAKE_CASE(SCSI_SENSEQ_RECALCULATION_IN_PROGRESS)
                        MAKE_CASE(SCSI_SENSEQ_OPERATION_IN_PROGRESS)
                        MAKE_CASE(SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS)                        
                    }
                    break;
                case SCSI_ADSENSE_NO_SENSE:
                    switch (adSenseCodeQual){
                        MAKE_CASE(SCSI_SENSEQ_FILEMARK_DETECTED)
                        MAKE_CASE(SCSI_SENSEQ_END_OF_MEDIA_DETECTED)
                        MAKE_CASE(SCSI_SENSEQ_SETMARK_DETECTED)
                        MAKE_CASE(SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED)
                    }
                    break;
                case SCSI_ADSENSE_ILLEGAL_BLOCK:
                    switch (adSenseCodeQual){
                        MAKE_CASE(SCSI_SENSEQ_ILLEGAL_ELEMENT_ADDR)
                    }
                    break;
                case SCSI_ADSENSE_POSITION_ERROR:
                    switch (adSenseCodeQual){
                        MAKE_CASE(SCSI_SENSEQ_DESTINATION_FULL)
                        MAKE_CASE(SCSI_SENSEQ_SOURCE_EMPTY)
                    }
                    break;
                case SCSI_ADSENSE_INVALID_MEDIA:
                    switch (adSenseCodeQual){
                        MAKE_CASE(SCSI_SENSEQ_INCOMPATIBLE_MEDIA_INSTALLED)
                        MAKE_CASE(SCSI_SENSEQ_UNKNOWN_FORMAT)
                        MAKE_CASE(SCSI_SENSEQ_INCOMPATIBLE_FORMAT)
                        MAKE_CASE(SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED)
                    }
                    break;
                case SCSI_ADSENSE_OPERATOR_REQUEST:
                    switch (adSenseCodeQual){
                        MAKE_CASE(SCSI_SENSEQ_STATE_CHANGE_INPUT)
                        MAKE_CASE(SCSI_SENSEQ_MEDIUM_REMOVAL)
                        MAKE_CASE(SCSI_SENSEQ_WRITE_PROTECT_ENABLE)
                        MAKE_CASE(SCSI_SENSEQ_WRITE_PROTECT_DISABLE)
                    }
                    break;
                case SCSI_ADSENSE_COPY_PROTECTION_FAILURE:
                    switch (adSenseCodeQual){
                        MAKE_CASE(SCSI_SENSEQ_AUTHENTICATION_FAILURE)
                        MAKE_CASE(SCSI_SENSEQ_KEY_NOT_PRESENT)
                        MAKE_CASE(SCSI_SENSEQ_KEY_NOT_ESTABLISHED)
                        MAKE_CASE(SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION)
                        MAKE_CASE(SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT)
                        MAKE_CASE(SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR)
                    }
                    break;
            }
        }
    }

    return adSenseCodeQualStr;
}


/*
 *  DbgGetMediaTypeStr
 *
 *      Convert MEDIA_TYPE (defined in ntdddisk.h) to a string.
 */
char *DbgGetMediaTypeStr(ULONG MediaType)
{
    char *mediaTypeStr = "?";
    
    switch (MediaType){

        #undef MAKE_CASE             
        #define MAKE_CASE(mtype) case mtype: mediaTypeStr = #mtype; break;

        MAKE_CASE(Unknown)
        MAKE_CASE(F5_1Pt2_512)
        MAKE_CASE(F3_1Pt44_512)
        MAKE_CASE(F3_2Pt88_512)
        MAKE_CASE(F3_20Pt8_512)
        MAKE_CASE(F3_720_512)
        MAKE_CASE(F5_360_512)
        MAKE_CASE(F5_320_512)
        MAKE_CASE(F5_320_1024)
        MAKE_CASE(F5_180_512)
        MAKE_CASE(F5_160_512)
        MAKE_CASE(RemovableMedia)
        MAKE_CASE(FixedMedia)
        MAKE_CASE(F3_120M_512)
        MAKE_CASE(F3_640_512)
        MAKE_CASE(F5_640_512)
        MAKE_CASE(F5_720_512)
        MAKE_CASE(F3_1Pt2_512)
        MAKE_CASE(F3_1Pt23_1024)
        MAKE_CASE(F5_1Pt23_1024)
        MAKE_CASE(F3_128Mb_512)
        MAKE_CASE(F3_230Mb_512)
        MAKE_CASE(F8_256_128)
        MAKE_CASE(F3_200Mb_512)
        MAKE_CASE(F3_240M_512)
        MAKE_CASE(F3_32M_512)
    }

    return mediaTypeStr;
}