summaryrefslogtreecommitdiff
path: root/storage/class/classpnp/src/history.c
blob: c8505774af6baf9358e0d6712f4e7cbb63203be0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*++


Copyright (C) Microsoft Corporation, 1991 - 1999

Module Name:

    history.c

Abstract:

    Packet history routines for CLASSPNP

Environment:

    kernel mode only

Notes:


Revision History:

--*/

#include "classp.h"
#include "debug.h"

#ifdef DEBUG_USE_WPP
#include "history.tmh"
#endif

//#ifdef ALLOC_PRAGMA
//    #pragma alloc_text(PAGE, InitializeTransferPackets)
//#endif

VOID HistoryInitializeRetryLogs(_Out_ PSRB_HISTORY History, ULONG HistoryCount) {
    ULONG tmpSize = HistoryCount * sizeof(SRB_HISTORY_ITEM);
    tmpSize += sizeof(SRB_HISTORY) - sizeof(SRB_HISTORY_ITEM);
    RtlZeroMemory(History, tmpSize);
    History->TotalHistoryCount = HistoryCount;
    return;
}


VOID HistoryLogSendPacket(TRANSFER_PACKET * Pkt) {

    PSRB_HISTORY history;
    PSRB_HISTORY_ITEM item;

    NT_ASSERT( Pkt->RetryHistory != NULL );
    history = Pkt->RetryHistory;
    // sending a packet implies a new history unit is to be used.
    NT_ASSERT( history->UsedHistoryCount <= history->TotalHistoryCount );

    // if already all used up, request class driver to remove at least one history unit
    if (history->UsedHistoryCount == history->TotalHistoryCount )
    {
        PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Pkt->Fdo->DeviceExtension;
        PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
        NT_ASSERT( fdoData->InterpretSenseInfo != NULL );
        NT_ASSERT( fdoData->InterpretSenseInfo->Compress != NULL );
        fdoData->InterpretSenseInfo->Compress( fdoExtension->DeviceObject, history );
        NT_ASSERT( history->UsedHistoryCount < history->TotalHistoryCount );
    }

    // thus, since we are about to increment the count, it must now be less...
    NT_ASSERT( history->UsedHistoryCount < history->TotalHistoryCount );

    // increment the number of history units in use
    history->UsedHistoryCount++;

    // determine index to use
    item = &( history->History[ history->UsedHistoryCount-1 ] );

    // zero out the history item
    RtlZeroMemory(item, sizeof(SRB_HISTORY_ITEM));

    // Query the tick count and store in the history
    KeQueryTickCount(&item->TickCountSent);
    return;
}

VOID HistoryLogReturnedPacket(TRANSFER_PACKET *Pkt) {

    PSRB_HISTORY history;
    PSRB_HISTORY_ITEM item;
    UCHAR senseSize;
    PVOID senseInfoBuffer;
    UCHAR senseInfoBufferLength;
    SENSE_DATA convertedSenseBuffer = {0};
    BOOLEAN validSense = TRUE;

    NT_ASSERT( Pkt->RetryHistory != NULL );
    history = Pkt->RetryHistory;
    NT_ASSERT( history->UsedHistoryCount <= history->TotalHistoryCount );
    item = &( history->History[ history->UsedHistoryCount-1 ] );

    // Query the tick count and store in the history
    KeQueryTickCount(&item->TickCountCompleted);

    // Copy the SRB Status...
    item->SrbStatus = Pkt->Srb->SrbStatus;

    //
    // Process sense data
    //

    senseInfoBuffer = ClasspTransferPacketGetSenseInfoBuffer(Pkt);
    senseInfoBufferLength = ClasspTransferPacketGetSenseInfoBufferLength(Pkt);

    if (IsDescriptorSenseDataFormat(senseInfoBuffer)) {

        validSense = ScsiConvertToFixedSenseFormat(senseInfoBuffer,
                                                   senseInfoBufferLength,
                                                   (PVOID)&convertedSenseBuffer,
                                                   sizeof(convertedSenseBuffer));

        if (validSense) {
            senseInfoBuffer = (PVOID)&convertedSenseBuffer;
            senseInfoBufferLength = sizeof(convertedSenseBuffer);
        }
    }

    RtlZeroMemory(&(item->NormalizedSenseData), sizeof(item->NormalizedSenseData));
    
    if (validSense) {

        // Determine the amount of valid sense data

        if (!ScsiGetTotalSenseByteCountIndicated(senseInfoBuffer, 
                                                 senseInfoBufferLength,
                                                 &senseSize)) {
            senseSize = senseInfoBufferLength;
        }

        // Normalize the sense data copy in the history
        senseSize = min(senseSize, sizeof(item->NormalizedSenseData));
        RtlCopyMemory(&(item->NormalizedSenseData),
                      senseInfoBuffer,
                      senseSize
                      );
    }

    return;
}