Clarion code for DeviceIoControl SMART_RCV_DRIVE_DATA control code

I wrote once Clarion code to get some Harddisk properties with DeviceIoControl with using SMART (if the device supports it)

Ask me for more info on overlapped for example, as it needs a signal event etc, and the device must be incl the overlapped attribute with the createfile call etc
As it took me a while to make it work, I thought I post it so it saves time for others :slight_smile:


https://docs.microsoft.com/en-us/previous-versions/windows/hardware/drivers/ff566204(v%3Dvs.85)

Up here the code:

IO_DFP_RECEIVE_DRIVE_DATA ROUTINE

Clear(LBUFFER16K,-1)
Clear(SendCmdInParams)
SndIn:BufferSize         	= Size(LBUFFER16K)
SndIn:irSectorCountReg      = 1
SndIn:irSectorNumberReg     = 1
SndIn:irCylLowReg           = 04Fh
SndIn:irCylHighReg          = 0C2h
SndIn:irDriveHeadReg       	= BXOR(0A0h, BSHIFT(1,-4))
SndIn:irCommandReg         	= ID_CMD
Clear(DeviceInfo)

OverlappedBytesReturned = 0
OverlappedCall = 0
WaitForEvent = 0
ReturnLong = DeviceIoControl(LDeviceHandle, DFP_RECEIVE_DRIVE_DATA, Address(SendCmdInParams), Size(SendCmdInParams), Address(LBUFFER16K), Size(LBUFFER16K), Address(OverlappedBytesReturned),0)
Do PROCESS_DATA_IO_DFP_RECEIVE_DRIVE_DATA

PROCESS_DATA_IO_DFP_RECEIVE_DRIVE_DATA ROUTINE

DATA

Pos long

LGRPSmartRcvDriveData GROUP,PRE(LGSmrtRcvDrvDat)
Id LONG
YourId LONG
DriveGuid STRING(450)
DriveGuidA STRING(450)
GeneralConfiguration LONG
NumCylinders LONG
NumHeads LONG
TracksPerCylinder LONG
TrackBytes LONG
SectorBytes LONG
NumSectorsPerTrack REAL
VendorUnique1A LONG
VendorUnique1B LONG
VendorUnique1C LONG
SerialNumber STRING(450)
SerialNumberA STRING(450)
BufferType LONG
BufferTypeString STRING(450)
BufferTypeStringA STRING(450)
BufferSize LONG
ECCBytes LONG
FirmwareRevision STRING(450)
FirmwareRevisionA STRING(450)
ModelNumber STRING(450)
ModelNumberA STRING(450)
MaximumBlockTransfer LONG
VendorUnique2 LONG
DoubleWordIO LONG
Capabilities BYTE
DmaSupported BYTE
LbaSupported BYTE
IordyDisable BYTE
IordySupported BYTE
SoftReset BYTE
StandbyOverlap BYTE
SupportQTag BYTE
SupportIDma BYTE
DeviceStandbyMin LONG
PioCycleTimingMode LONG
PioModeString STRING(450)
PioModeStringA STRING(450)
DmaCycleTimingMode LONG
DmaModeString STRING(450)
DmaModeStringA STRING(450)
TranslationFieldsValid LONG
NumberOfCurrentCylinders LONG
NumberOfCurrentHeads LONG
CurrentSectorsPerTrack LONG
CurrentSectorCapacity LONG
CurrentMultiSectorSetting LONG
MultiSectorSettingValid BYTE
UserAddressableSectors LONG
MultiWordDMASupport LONG
MultiWordDMAActive LONG
AdvancedPIOModes LONG
MinimumMWXferCycleTime LONG
RecommendedMWXferCycleTime LONG
MinimumPIOCycleTime LONG
MinimumPIOCycleTimeIOrdy LONG
QueueDepth LONG
MajorRevision LONG
MinorRevision LONG
Rotation LONG
WorkerId LONG
WorkerDevice STRING(450)
WorkerDeviceA STRING(450)
TaskName STRING(450)
TaskNameA STRING(450)
ResultCall LONG
ResultRawData STRING(450)
ResultRawDataA STRING(450)
ResultRawDataDBLen LONG
ResultRawDataOriginalLen LONG
ResultRawDateFormat STRING(450)
ResultRawDateFormatA STRING(450)
ResultBytesReturned LONG
ResultStructureVersion LONG
ResultStructureSize LONG
ResultIsCorrupt BYTE
TimeOutSpan LONG
ResultMMSecondsCompleted LONG
ResultIsSuccess BYTE
ResultIsError BYTE
ResultIsCritical BYTE
ResultIsBufferToSmall BYTE
ResultIsTimeOut BYTE
ResultLastErrorcode BYTE
ResultToSave BYTE
DeviceClassName STRING(450)
DeviceClassNameA STRING(450)
IsAdapter BYTE
IsDiskDrive BYTE
NameDevice STRING(450)
NameDeviceA STRING(450)
END
IsSmartEnabled byte

CODE

! DFP_RECEIVE_DRIVE_DATA_RETURNLEN = OverlappedBytesReturned
! DFP_RECEIVE_DRIVE_DATA_RETURN = ReturnLong
!
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘***DeviceIoControl’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘int’
QLDevPropExt:ValueA = OverlappedBytesReturned
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
!
! Clear(QLDevicePropExt)
! QLDevicePropExtSeed = QLDevicePropExtSeed + 1
! QLDevPropExt:Id = QLDevicePropExtSeed
! QLDevPropExt:MachineId = ThisMachineId
! QLDevPropExt:WinWorker = LWinWorkerIndex
! QLDevPropExt:DeviceId = LQDeviceId
! QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
! QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
! QLDevPropExt:NameA = ‘BytesReturned’
! QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
! QLDevPropExt:DataType = 1
! QLDevPropExt:DataTypeString = ‘int’
! QLDevPropExt:ValueA = OverlappedBytesReturned
! QLDevPropExt:ValueLen = 1
! Add(QLDevicePropExt)

Clear(LGRPSmartRcvDriveData)

!LAllMyDrivesGUID = 'tralasdfsdfsdfsdfsdflala'
!IsSmartEnabled = 1

!IdDataString = LBUFFER16K[17 : 528]

! if len(clip(IdDataString)) > 50
! CrcA = crc32c_append(0,Address(IdDataString),512)
! CrcB = crc32c_append(1,Address(IdDataString),512)
! CrcC = crc32c_append(2,Address(IdDataString),512)
! CrcD = crc32c_append(3,Address(IdDataString),512)
! CrcAHex = UPPER(ST.LongToHex(CrcA))
! CrcBHex = UPPER(ST.LongToHex(CrcB))
! CrcCHex = UPPER(ST.LongToHex(CrcC))
! CrcDHex = UPPER(ST.LongToHex(CrcC))
! LAllMyDrivesGUID = CrcAHex[1 : 4] & CrcAHex[5 : 8] & ‘-’ & CrcBHex[1 : 4] & ‘-’ & CrcBHex[5 : 8] & ‘-’ & CrcCHex[1 : 4] & ‘-’ & CrcCHex[5 : 8] & CrcDHex[1 : 4] & CrcDHex[5 : 6]
! !LAllMyDrivesGUID = CrcAHex[1 : 4] & CrcAHex[5 : 8] & ‘-’ & CrcBHex[1 : 4] & ‘-’ & CrcBHex[5 : 8] & ‘-’ & CrcCHex[1 : 4]
! ELSE
! LAllMyDrivesGUID = ‘ASDFSFSDFSDFSFSFSFSFSWEREWRWER’ & CLOCK()
! End
!

Pos = 16
If OverlappedBytesReturned > 20
	IsSmartEnabled = 1
    Clear(QLDevicePropExt)
    QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
    QLDevPropExt:Id                 = QLDevicePropExtSeed
    QLDevPropExt:MachineId          = ThisMachineId
    QLDevPropExt:WinWorker          = LWinWorkerIndex
    QLDevPropExt:DeviceId           = LQDeviceId
    QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
    QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
    QLDevPropExt:NameA              = 'IsSmartEnabled'
    QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
    !QLDevPropExt:DataType           = 0
    QLDevPropExt:DataTypeString     = 'byte'
    QLDevPropExt:ValueA             = '1'
    QLDevPropExt:ValueLen           = 1
    Add(QLDevicePropExt)                    
End

Loop 900 Times

! If IsSmartEnabled = 0
! BREAK
! End
Pos = Pos + 1
If Pos >= OverlappedBytesReturned
BREAK
End
Case (Pos - 16)
Of 1
!110001011010
LGSmrtRcvDrvDat:GeneralConfiguration = GetU16(LBUFFER16K[Pos : Pos + 1])
Of 3
LGSmrtRcvDrvDat:NumCylinders = GetU16(LBUFFER16K[Pos : Pos + 1])
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘NumCylinders’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 0
QLDevPropExt:DataTypeString = ‘ushort’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:NumCylinders
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
Of 5 ! /* specific configuration /
!LGSmrtRcvDrvDat:ReservedWord2 = Get32(LBUFFER16K[Pos : Pos + 1])
Of 7 ! /
number of logical heads /
LGSmrtRcvDrvDat:NumHeads = GetU16(LBUFFER16K[Pos : Pos + 1])
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘NumHeads’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 0
QLDevPropExt:DataTypeString = ‘ushort’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:NumHeads
QLDevPropExt:ValueLen = 2
Add(QLDevicePropExt)
Of 9 ! /
number of bytes/track (ATA-1) /
LGSmrtRcvDrvDat:TrackBytes = GetU16(LBUFFER16K[Pos : Pos + 1])
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘TrackBytes’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘ushort’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:TrackBytes
QLDevPropExt:ValueLen = 2
Add(QLDevicePropExt)
Of 11 ! /
number of bytes/sector (ATA-1) /
LGSmrtRcvDrvDat:SectorBytes = GetU16(LBUFFER16K[Pos : Pos + 1])
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘SectorBytes’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘ushort’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:SectorBytes
QLDevPropExt:ValueLen = 2
Add(QLDevicePropExt)
Of 13 ! /
number of logical sectors/track */
LGSmrtRcvDrvDat:NumSectorsPerTrack = GetU16(LBUFFER16K[Pos : Pos + 1])
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘NumSectorsPerTrack’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘ushort’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:NumSectorsPerTrack
QLDevPropExt:ValueLen = 2
Add(QLDevicePropExt)
! Of 15 !
! !LGSmrtRcvDrvDa = Get32(LBUFFER16K[Pos : Pos + 1])
! Of 17
! LGSmrtRcvDrvDat:VendorUnique1B = Get32(LBUFFER16K[Pos : Pos + 1])
! Of 19
! LGSmrtRcvDrvDat:VendorUnique1C = Get32(LBUFFER16K[Pos : Pos + 1])
Of 21
LGSmrtRcvDrvDat:SerialNumber = LBUFFER16K[Pos+1] & LBUFFER16K[Pos] & |
LBUFFER16K[Pos+3] & LBUFFER16K[Pos+2] & |
LBUFFER16K[Pos+5] & LBUFFER16K[Pos+4] & |
LBUFFER16K[Pos+7] & LBUFFER16K[Pos+6] & |
LBUFFER16K[Pos+9] & LBUFFER16K[Pos+8] & |
LBUFFER16K[Pos+11] & LBUFFER16K[Pos+10] & |
LBUFFER16K[Pos+13] & LBUFFER16K[Pos+12] & |
LBUFFER16K[Pos+15] & LBUFFER16K[Pos+14] & |
LBUFFER16K[Pos+17] & LBUFFER16K[Pos+16] & |
LBUFFER16K[Pos+19] & LBUFFER16K[Pos+18]

        LGSmrtRcvDrvDat:SerialNumber = Clip(Left(LGSmrtRcvDrvDat:SerialNumber))
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'SerialNumber'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'string'
        QLDevPropExt:ValueA             = Left(LGSmrtRcvDrvDat:SerialNumber)
        QLDevPropExt:ValueLen           = Len(Clip(QLDevPropExt:ValueA))*2
        Add(QLDevicePropExt)                  

! If len(clip(GDiskDrive[GDiskDriveIndex].Device_SerialNumber)) = 0
! GDiskDrive[GDiskDriveIndex].Device_SerialNumber = LGSmrtRcvDrvDat:SerialNumber
!! End

	Of 41 ! /* buffer type (ATA-1) */
        LGSmrtRcvDrvDat:BufferType  = GetU16(LBUFFER16K[Pos : Pos + 1])
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'BufferType'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'ushort'
        QLDevPropExt:ValueA             = LGSmrtRcvDrvDat:BufferType
        QLDevPropExt:ValueLen           = 2
        Add(QLDevicePropExt)                  
        !If BAND(LGSmrtRcvDrvDat:BufferType,
	Of 43 ! /* buffer size (ATA-1) */
        LGSmrtRcvDrvDat:BufferSize  = GetU16(LBUFFER16K[Pos : Pos + 1])
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'BufferSize'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'ushort'
        QLDevPropExt:ValueA             = LGSmrtRcvDrvDat:BufferSize
        QLDevPropExt:ValueLen           = 2
        Add(QLDevicePropExt)                  
	Of 45 ! /* extra bytes in R/W LONG cmd ( < ATA-4)*/
        LGSmrtRcvDrvDat:ECCBytes  = GetU16(LBUFFER16K[Pos : Pos + 1])
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'ECCBytes'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'ushort'
        QLDevPropExt:ValueA             = LGSmrtRcvDrvDat:ECCBytes
        QLDevPropExt:ValueLen           = 2
        Add(QLDevicePropExt)                  
	Of 47 ! /* ASCII firmware revision */
		LGSmrtRcvDrvDat:FirmwareRevision  = LBUFFER16K[Pos+1] & LBUFFER16K[Pos] & |
			LBUFFER16K[Pos+3] & LBUFFER16K[Pos+2] & |
			LBUFFER16K[Pos+5] & LBUFFER16K[Pos+4] & |
			LBUFFER16K[Pos+7] & LBUFFER16K[Pos+6] 
        LGSmrtRcvDrvDat:FirmwareRevision = Clip(Left(LGSmrtRcvDrvDat:FirmwareRevision))
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'FirmwareRevision'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'string'
        QLDevPropExt:ValueA             = LGSmrtRcvDrvDat:FirmwareRevision
        QLDevPropExt:ValueLen           = Len(Clip(QLDevPropExt:ValueA)) * 2
        Add(QLDevicePropExt)                  
	Of 55 ! /* ASCII model number */
		LGSmrtRcvDrvDat:ModelNumber  = LBUFFER16K[Pos+1] & LBUFFER16K[Pos] & |
			LBUFFER16K[Pos+3] & LBUFFER16K[Pos+2] & |
			LBUFFER16K[Pos+5] & LBUFFER16K[Pos+4] & |
			LBUFFER16K[Pos+7] & LBUFFER16K[Pos+6] & |
			LBUFFER16K[Pos+9] & LBUFFER16K[Pos+8] & |
			LBUFFER16K[Pos+11] & LBUFFER16K[Pos+10] & |
			LBUFFER16K[Pos+13] & LBUFFER16K[Pos+12] & |
			LBUFFER16K[Pos+15] & LBUFFER16K[Pos+14] & |
			LBUFFER16K[Pos+17] & LBUFFER16K[Pos+16] & |
			LBUFFER16K[Pos+19] & LBUFFER16K[Pos+18] & |
			LBUFFER16K[Pos+21] & LBUFFER16K[Pos+20] & |
			LBUFFER16K[Pos+23] & LBUFFER16K[Pos+22] & |
			LBUFFER16K[Pos+25] & LBUFFER16K[Pos+24] & |
			LBUFFER16K[Pos+27] & LBUFFER16K[Pos+26] & |
			LBUFFER16K[Pos+29] & LBUFFER16K[Pos+28] & |
			LBUFFER16K[Pos+31] & LBUFFER16K[Pos+30] & |
			LBUFFER16K[Pos+33] & LBUFFER16K[Pos+32] & |
			LBUFFER16K[Pos+34] & LBUFFER16K[Pos+34] & |
			LBUFFER16K[Pos+37] & LBUFFER16K[Pos+36] & |                        
			LBUFFER16K[Pos+39] & LBUFFER16K[Pos+38]      
        LGSmrtRcvDrvDat:ModelNumber = Clip(Left(LGSmrtRcvDrvDat:ModelNumber))
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'ModelNumber'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'string'
        QLDevPropExt:ValueA             = LGSmrtRcvDrvDat:ModelNumber
        QLDevPropExt:ValueLen           = Len(Clip(QLDevPropExt:ValueA)) * 2
        Add(QLDevicePropExt)                  
	Of 95 ! /* r/w multiple: max sectors xfered */
        LGSmrtRcvDrvDat:MaximumBlockTransfer  = Val(LBUFFER16K[Pos]) 
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'MaximumBlockTransferv'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'byte'
        QLDevPropExt:ValueA             = LGSmrtRcvDrvDat:MaximumBlockTransfer
        QLDevPropExt:ValueLen           = 1
        Add(QLDevicePropExt)                  
	Of 96 ! 
        LGSmrtRcvDrvDat:VendorUnique2  = Val(LBUFFER16K[Pos]) 
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'VendorUnique2'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'string'
        QLDevPropExt:ValueA             = LGSmrtRcvDrvDat:VendorUnique2
        QLDevPropExt:ValueLen           = Len(Clip(QLDevPropExt:ValueA)) * 2
        Add(QLDevicePropExt)                  
	Of 97 ! /* can do double-word IO (ATA-1 only) */
        LGSmrtRcvDrvDat:DoubleWordIO  = Val(LBUFFER16K[Pos]) 
        Clear(QLDevicePropExt)
        QLDevicePropExtSeed             = QLDevicePropExtSeed + 1
        QLDevPropExt:Id                 = QLDevicePropExtSeed
        QLDevPropExt:MachineId          = ThisMachineId
        QLDevPropExt:WinWorker          = LWinWorkerIndex
        QLDevPropExt:DeviceId           = LQDeviceId
        QLDevPropExt:TagNameA           = 'DFP_RECEIVE_DRIVE_DATA'
        QLDevPropExt:TagNameLen         = Len(Clip(QLDevPropExt:TagNameA)) * 2
        QLDevPropExt:NameA              = 'DoubleWordIO'
        QLDevPropExt:NameLen            = Len(Clip(QLDevPropExt:NameA)) * 2
        !QLDevPropExt:DataType           = 1
        QLDevPropExt:DataTypeString     = 'bool'
        QLDevPropExt:ValueA             = LGSmrtRcvDrvDat:DoubleWordIO
        QLDevPropExt:ValueLen           = 1
        Add(QLDevicePropExt)                  
	Of 99 ! /* can do double-word IO (ATA-1 only) */
        LGSmrtRcvDrvDat:DoubleWordIO  = Val(LBUFFER16K[Pos]) 

! Clear(QLDevicePropExt)
! QLDevicePropExtSeed = QLDevicePropExtSeed + 1
! QLDevPropExt:Id = QLDevicePropExtSeed
! QLDevPropExt:MachineId = ThisMachineId
! QLDevPropExt:WinWorker = LWinWorkerIndex
! QLDevPropExt:DeviceId = LQDeviceId
! QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
! QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
! QLDevPropExt:NameA = ‘NumCylinders’
! QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
! !QLDevPropExt:DataType = 1
! QLDevPropExt:DataTypeString = ‘bool’
! QLDevPropExt:ValueA = ‘1’
! QLDevPropExt:ValueLen = 1
! Add(QLDevicePropExt)
Of 100
LGSmrtRcvDrvDat:Capabilities = Val(LBUFFER16K[Pos])
If Band(LGSmrtRcvDrvDat:Capabilities,1)
LGSmrtRcvDrvDat:DmaSupported = 1
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘DmaSupported’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:DmaSupported
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
End
If Band(LGSmrtRcvDrvDat:Capabilities,2)
LGSmrtRcvDrvDat:LbaSupported = 1
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘LbaSupported’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:LbaSupported
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
End
If Band(LGSmrtRcvDrvDat:Capabilities,4)
LGSmrtRcvDrvDat:IordyDisable = 1
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘IordyDisable’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:IordyDisable
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
End
If Band(LGSmrtRcvDrvDat:Capabilities,8)
LGSmrtRcvDrvDat:IordySupported = 1
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘IordySupported’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:IordySupported
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
End
If Band(LGSmrtRcvDrvDat:Capabilities,16)
LGSmrtRcvDrvDat:SoftReset = 1
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘SoftReset’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:SoftReset
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
End
If Band(LGSmrtRcvDrvDat:Capabilities,32)
LGSmrtRcvDrvDat:StandbyOverlap = 1
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘StandbyOverlap’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:StandbyOverlap
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
End
If Band(LGSmrtRcvDrvDat:Capabilities,64)
LGSmrtRcvDrvDat:SupportQTag = 1
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘SupportQTag’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:SupportQTag
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
End
If Band(LGSmrtRcvDrvDat:Capabilities,128)
LGSmrtRcvDrvDat:SupportIDma = 1
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘SupportIDma’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:SupportIDma
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
End

! If Band(LGSmrtRcvDrvDat:Capabilities,00000100b)
! LGSmrtRcvDrvDat:StandybyTimerSupport = 1
! End
!! * 3: IORDYsup
!! * 2: IORDYsw
!! * 1: LBA
!! * 0: DMA
Of 102
LGSmrtRcvDrvDat:DeviceStandbyMin = GetU16(LBUFFER16K[Pos : Pos + 1])
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘DeviceStandbyMin’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘ushort’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:DeviceStandbyMin
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
! Of 103 !
! ! vendor5
Of 104 ! /* max PIO mode supported (obsolete)/
LGSmrtRcvDrvDat:PioCycleTimingMode = Val(LBUFFER16K[Pos]) ! TODO PIOMODE STRING
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘PioCycleTimingMode’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:PioCycleTimingMode
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
! Of 105 !
! ! vendor6
Of 106 ! /
max Singleword DMA mode supported (obs)/
LGSmrtRcvDrvDat:DmaCycleTimingMode = Val(LBUFFER16K[Pos]) ! TODO DMAMODE STRING
Clear(QLDevicePropExt)
QLDevicePropExtSeed = QLDevicePropExtSeed + 1
QLDevPropExt:Id = QLDevicePropExtSeed
QLDevPropExt:MachineId = ThisMachineId
QLDevPropExt:WinWorker = LWinWorkerIndex
QLDevPropExt:DeviceId = LQDeviceId
QLDevPropExt:TagNameA = ‘DFP_RECEIVE_DRIVE_DATA’
QLDevPropExt:TagNameLen = Len(Clip(QLDevPropExt:TagNameA)) * 2
QLDevPropExt:NameA = ‘DmaCycleTimingMode’
QLDevPropExt:NameLen = Len(Clip(QLDevPropExt:NameA)) * 2
!QLDevPropExt:DataType = 1
QLDevPropExt:DataTypeString = ‘bool’
QLDevPropExt:ValueA = LGSmrtRcvDrvDat:DmaCycleTimingMode
QLDevPropExt:ValueLen = 1
Add(QLDevicePropExt)
! Of 107 ! /
what fields are valid /
! LGSmrtRcvDrvDat:TranslationFieldsValid = Get32(LBUFFER16K[Pos : Pos + 1])
! Of 109 ! /
current logical cylinders /
! LGSmrtRcvDrvDat:NumberOfCurrentCylinders = Get32(LBUFFER16K[Pos : Pos + 1])
! Of 111 ! /
current logical heads /
! LGSmrtRcvDrvDat:NumberOfCurrentHeads = Get32(LBUFFER16K[Pos : Pos + 1])
! Of 113 ! /
current logical sectors/track /
! LGSmrtRcvDrvDat:CurrentSectorsPerTrack = Get32(LBUFFER16K[Pos : Pos + 1])
! Of 115 ! /
current capacity in sectors /
! LGSmrtRcvDrvDat:CurrentSectorCapacity = Get32(LBUFFER16K[Pos : Pos + 3])
! Of 119 ! /
r/w multiple: current sectors xfered /
! LGSmrtRcvDrvDat:CurrentMultiSectorSetting = Val(LBUFFER16K[Pos])
! Of 120 ! /
LBA: total number of user */
! LGSmrtRcvDrvDat:MultiSectorSettingValid = Val(LBUFFER16K[Pos])
! Of 121
! LGSmrtRcvDrvDat:UserAddressableSectors = Get32(LBUFFER16K[Pos : Pos + 3])
! Of 125 !
! !LGSmrtRcvDrvDat:ObsoleteWord62 = Get32(LBUFFER16K[Pos : Pos + 1])
! Of 127 !
! LGSmrtRcvDrvDat:MultiWordDMASupport = Get32(LBUFFER16K[Pos : Pos + 1])
End
End