Пример #1
0
BOOL
NDAS_Unbind(UNIT_DISK_LOCATION *pUnitDisk)
{
	// AING_TO_DO : complex check routine

	BOOL bReturn = FALSE;
	IDE_COMMAND_IO cmd, *cmd_chk = NULL;
	DISK_INFORMATION_BLOCK	*pDiskInfoV1;
	DISK_INFORMATION_BLOCK_V2 *pDiskInfoV2;
	UINT i, j;
	UINT nDIB;

	DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : Start\n"));

	// Check V2
	cmd.command = WIN_READ;
	cmd.iSector = -2;

	DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : Reading V2\n"));
	if(!NDAS_IdeIO(pUnitDisk, 1, &cmd, NULL))
		goto out;
	
	pDiskInfoV2 = (PDISK_INFORMATION_BLOCK_V2)cmd.data;

	if(DISK_INFORMATION_SIGNATURE_V2 != pDiskInfoV2->Signature) // V2 information exists
		goto chk_v1;
	
	DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : V2\n"));

	if(IS_NDAS_DIB_V2_VERSION_HIGH(*pDiskInfoV2))
		goto out;

	// AING_TO_DO :version check routine needed here

	if(pDiskInfoV2->nDiskCount <= 1)
	{
		// nothing to do
		bReturn = TRUE;
		goto out;
	}

	DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : Disk count >= 2\n"));

	if(NMT_VDVD == pDiskInfoV2->iMediaType)
		goto out;

	DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : not VDVD\n"));
	// AING_TO_DO : if nr of disks is more than NDAS_MAX_UNITS_IN_V2, read more sectors...
	nDIB = 1 + /* DISK_INFORMATION_BLOCK */ + 1 /* DISK_INFORMATION_BLOCK_V2 */ + GET_TRAIL_SECTOR_COUNT_V2(pDiskInfoV2->nDiskCount);
	cmd_chk = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDE_COMMAND_IO) * nDIB);

	DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : nDIB = %d\n", nDIB));
	for(i = 0; i < nDIB; i++)
	{
		cmd_chk[i].command = WIN_READ;
		cmd_chk[i].iSector = -1 * ((signed _int64)i);
	}
	
	DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : nDiskCount = %d\n", pDiskInfoV2->nDiskCount));
	for(i = 0; i < pDiskInfoV2->nDiskCount; i++) // for each netdisks
	{
		DISK_INFORMATION_BLOCK	*pDIV1;
		DISK_INFORMATION_BLOCK_V2 *pDIV2;

		// verify that the disk is bound correctly
		if(!NDAS_IdeIO(&pUnitDisk[i], nDIB, cmd_chk, NULL))
			continue;

		pDIV1 = (PDISK_INFORMATION_BLOCK)cmd_chk[0].data;
		pDIV2 = (PDISK_INFORMATION_BLOCK_V2)cmd_chk[1].data;

		// check V1 data
		if(DISK_INFORMATION_SIGNATURE != pDIV1->Signature ||
			IS_WRONG_VERSION(*pDIV1))
			continue;

		// check V2 data
		if(DISK_INFORMATION_SIGNATURE_V2 != pDIV2->Signature)
			continue;

		// higher version check code
		if(IS_NDAS_DIB_V2_VERSION_HIGH(*pDIV2))
			continue;

		if(pDIV2->nDiskCount != pDiskInfoV2->nDiskCount ||
			pDIV2->iSequence != i ||
			pDIV2->iMediaType != pDiskInfoV2->iMediaType)
			continue;

		// compare unit disk informations
		if(memcmp(pDIV2->UnitDisks, pDiskInfoV2->UnitDisks, min(pDiskInfoV2->nDiskCount, NDAS_MAX_UNITS_IN_V2) * sizeof(UNIT_DISK_LOCATION)))
			continue;

		if(pDiskInfoV2->nDiskCount > NDAS_MAX_UNITS_IN_V2)
		{
			for(j = NDAS_MAX_UNITS_IN_V2; j < pDiskInfoV2->nDiskCount; j++)
			{
				if(memcmp(&cmd_chk[2 + (j - NDAS_MAX_UNITS_IN_V2) / NDAS_MAX_UNITS_IN_SECTOR].data[(j - NDAS_MAX_UNITS_IN_V2) % NDAS_MAX_UNITS_IN_SECTOR], &pUnitDisk[j], sizeof(UNIT_DISK_LOCATION)))
					continue;
			}
		}

		DebugPrint(1, ("[NDASOpLib] NDAS_Unbind : Clear %d\n", i));

		// ok it is safe to clear
		if(!NDAS_ClearInfo(&(pDiskInfoV2->UnitDisks[i])))
			continue;
	}

//	if(!NDAS_Unbind(pAddress, iTargetID);

	bReturn = TRUE;
	goto out;

chk_v1:
	// Check V1
	cmd.command = WIN_READ;
	cmd.iSector = -1;

	if(!NDAS_IdeIO(pUnitDisk, 1, &cmd, NULL))
		goto out;
	
	pDiskInfoV1 = (PDISK_INFORMATION_BLOCK)cmd.data;

	if(DISK_INFORMATION_SIGNATURE != pDiskInfoV1->Signature)
	{
		// already single
		bReturn = TRUE;
		goto out;
	}

	// only 2 disks bound
	if(
		UNITDISK_TYPE_DVD == pDiskInfoV1->DiskType ||
		UNITDISK_TYPE_VDVD == pDiskInfoV1->DiskType ||
		UNITDISK_TYPE_MO == pDiskInfoV1->DiskType
		)
	{
		goto out;
	}

	if(UNITDISK_TYPE_SINGLE == pDiskInfoV1->DiskType)
	{
		if(!NDAS_ClearInfo(pUnitDisk))
			goto out;
	}
	else
	{
		UNIT_DISK_LOCATION UnitPeer;
		CopyMemory(UnitPeer.MACAddr, pDiskInfoV1->PeerAddress, 6);
		UnitPeer.SlotNumber = pDiskInfoV1->PeerUnitNumber;

		if(!NDAS_ClearInfo(pUnitDisk))
			goto out;

		cmd_chk = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDE_COMMAND_IO));
		cmd_chk->command = WIN_READ;
		cmd_chk->iSector = -1;

		if(
			NDAS_IdeIO(&UnitPeer, 1, cmd_chk, NULL) &&
			0 == memcmp(UnitPeer.MACAddr, ((PDISK_INFORMATION_BLOCK)cmd_chk->data)->PeerAddress, 6) &&
			UnitPeer.SlotNumber == ((PDISK_INFORMATION_BLOCK)cmd_chk->data)->PeerUnitNumber
			)
		{

			if(!NDAS_ClearInfo(&UnitPeer))
				goto out;
		}
	}

	bReturn = TRUE;
out:	

	if(NULL != cmd_chk)
	{
		HeapFree(GetProcessHeap(), 0, cmd_chk);
		cmd_chk = NULL;
	}
	return bReturn;
}
Пример #2
0
BOOL
CNdasUnitDeviceCreator::ReadDIB(NDAS_DIB_V2** ppDIBv2)
{
    //
    // ppDIBv2 will be set only if this function succeed.
    //

    PNDAS_DIB_V2 pDIBv2 = reinterpret_cast<PNDAS_DIB_V2>(
                              HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 512));

    if (NULL == pDIBv2)
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "ReadDiskBlock failed, error=0x%X\n",
                  GetLastError());

        return FALSE;
    }

    BOOL fSuccess = m_devComm.ReadDiskBlock(
                        reinterpret_cast<PBYTE>(pDIBv2),
                        NDAS_BLOCK_LOCATION_DIB_V2);

    //
    // Regardless of the existence,
    // Disk Block should be read.
    // Failure means communication error or disk error
    //
    if (!fSuccess)
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "ReadDiskBlock failed, error=0x%X\n",
                  GetLastError());

        XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );

        return FALSE;
    }

    //
    // check signature
    //

    if(NDAS_DIB_V2_SIGNATURE != pDIBv2->Signature ||
            pDIBv2->crc32 != crc32_calc((unsigned char *)pDIBv2,
                                        sizeof(pDIBv2->bytes_248)) ||
            pDIBv2->crc32_unitdisks != crc32_calc((unsigned char *)pDIBv2->UnitDisks,
                    sizeof(pDIBv2->UnitDisks)))
    {
        //
        // Read DIBv1
        //

        fSuccess = ReadDIBv1AndConvert(pDIBv2);

        if (!fSuccess)
        {
            XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );
            return FALSE;
        }

        if ( ! IsConsistentDIB(pDIBv2) )
        {
            // Inconsistent DIB will be reported as single
            InitializeDIBv2AsSingle(pDIBv2);
        }

        *ppDIBv2 = pDIBv2;
        return TRUE;
    }

    //
    // check version
    //
    if(IS_HIGHER_VERSION_V2(*pDIBv2))
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "Unsupported version V2.\n");

        XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );
        return FALSE;
    }

    //
    // TODO: Lower version process (future code) ???
    //
    if(0)
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "lower version V2 detected\n");
    }

    //
    // read additional locations if needed
    //
    if (pDIBv2->nDiskCount + pDIBv2->nSpareCount > NDAS_MAX_UNITS_IN_V2)
    {

        UINT32 nTrailSectorCount =
            GET_TRAIL_SECTOR_COUNT_V2(pDIBv2->nDiskCount + pDIBv2->nSpareCount);

        SIZE_T dwBytes = sizeof(NDAS_DIB_V2) + 512 * nTrailSectorCount;

        LPVOID ptr = HeapReAlloc(
                         GetProcessHeap(),
                         HEAP_ZERO_MEMORY,
                         pDIBv2,
                         dwBytes);

        if (NULL == ptr)
        {
            XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                      "HeapReAlloc failed, bytes=%d\n", dwBytes);

            // When HeapReAlloc fails, pDIBv2 should be freed
            XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );

            return FALSE;
        }

        pDIBv2 = reinterpret_cast<PNDAS_DIB_V2>(ptr);

        for(DWORD i = 0; i < nTrailSectorCount; i++) {

            fSuccess = m_devComm.ReadDiskBlock(
                           reinterpret_cast<PBYTE>(pDIBv2) + sizeof(NDAS_DIB_V2) + 512 * i,
                           NDAS_BLOCK_LOCATION_ADD_BIND + i);

            if(!fSuccess)
            {
                XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                          "Reading additional block failed, block=%d, error=0x%X\n",
                          NDAS_BLOCK_LOCATION_ADD_BIND + i, GetLastError());

                XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );

                return FALSE;
            }
        }
    }

    // Virtual DVD check. Not supported ATM.

    //
    // DIB Consistency Check
    //
    if ( ! IsConsistentDIB(pDIBv2) )
    {
        // Inconsistent DIB will be reported as single
        InitializeDIBv2AsSingle(pDIBv2);
    }

    *ppDIBv2 = pDIBv2;

    return TRUE;
}
Пример #3
0
/*
	iMirrorLevel
	0 : do not mirror
	1 : mirror, full dirty
	2 : mirror, clean
*/
BOOL
NDAS_Bind(UINT nDiskCount, UNIT_DISK_LOCATION *aUnitDisks, int iMirrorLevel)
{
	IDE_COMMAND_IO *cmd = NULL;
	unsigned int i, j;
	_int64 nDiskSize;
	LANSCSI_PATH path;
	DISK_INFORMATION_BLOCK *pDiskInfoV1;
	DISK_INFORMATION_BLOCK_V2 *pDiskInfoV2;
	unsigned _int64 nBitmapSize, sizeUserSpace, sizeXArea;
	BOOL bReturn = FALSE;
	unsigned int nDIB;

	if(nDiskCount <= 1)
		goto out;

	if(iMirrorLevel && 0 != nDiskCount %2)
		goto out;

	// mirror : 0 - 1 group
	// 128 * n sectors devide
	// absolute 2 mega
	// 0x80 for V1 disk type
	// all single !
	for(i = 0; i < nDiskCount; i++)
	{
//		if(!NDAS_IsBindable(&aUnitDisks[i], &bResult) || FALSE == bResult)
//			return FALSE;		
	}

	nDIB = 1 /* DISK_INFORMATION_BLOCK */ + 1 /* DISK_INFORMATION_BLOCK_V2 */ + GET_TRAIL_SECTOR_COUNT_V2(nDiskCount);
	cmd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDE_COMMAND_IO) * nDIB);

	// build cmd
	// V1
	cmd[0].command = WIN_WRITE;
	cmd[0].iSector = -1;
	pDiskInfoV1 = (PDISK_INFORMATION_BLOCK)cmd[0].data;
	pDiskInfoV1->Signature = DISK_INFORMATION_SIGNATURE;
	pDiskInfoV1->MajorVersion = 1;
	pDiskInfoV1->MinorVersion = 0;
	pDiskInfoV1->DiskType = UNITDISK_TYPE_INVALID; // intentional wrong value

	// V2
	for(i = 1; i < nDIB; i++)
	{
		cmd[i].command = WIN_WRITE;
		cmd[i].iSector = -2 - ((signed _int64)i - 1);
	}
	pDiskInfoV2 = (PDISK_INFORMATION_BLOCK_V2)cmd[1].data;
	pDiskInfoV2->Signature = DISK_INFORMATION_SIGNATURE_V2;
	pDiskInfoV2->MajorVersion = CURRENT_MAJOR_VERSION_V2;
	pDiskInfoV2->MinorVersion = CURRENT_MINOR_VERSION_V2;
	pDiskInfoV2->iSectorsPerBit = 128;
	pDiskInfoV2->iMediaType = (iMirrorLevel) ? NMT_RAID1 : NMT_AGGREGATE;
	pDiskInfoV2->nDiskCount = nDiskCount;
	
	// if nDiskCount > NDAS_MAX_UNITS_IN_V2, aUnitDisks will be copied into cmd[2], cmd[3]...
	CopyMemory(pDiskInfoV2->UnitDisks, aUnitDisks, min(nDiskCount, NDAS_MAX_UNITS_IN_V2) * sizeof(UNIT_DISK_LOCATION));

	if(nDiskCount > NDAS_MAX_UNITS_IN_V2) // fill trailing sectors
	{
		int nCopyPoint;
		for(i = 2; i < nDIB; i++)
		{
			nCopyPoint = NDAS_MAX_UNITS_IN_SECTOR * (i - 2) + NDAS_MAX_UNITS_IN_V2;
			CopyMemory(cmd[i].data, &aUnitDisks[nCopyPoint], min(nDiskCount - nCopyPoint, NDAS_MAX_UNITS_IN_SECTOR) * sizeof(UNIT_DISK_LOCATION));
		}
			
	}

	// size checker

	for(i = 0; i < nDiskCount; i++)
	{

#ifdef _DEBUG
		char szTemp[100];
		sprintf(szTemp, "[NDASOpLib]NDAS_Bind: %d\n", i);
		OutputDebugString(szTemp);
#endif
		
		// V1
		CopyMemory(pDiskInfoV1->EtherAddress, aUnitDisks[i].MACAddr, 6);
		pDiskInfoV1->UnitNumber = aUnitDisks[i].SlotNumber;

		// V2
		NDAS_IdeIO(&aUnitDisks[i], 0, NULL, &path);
		nDiskSize = path.PerTarget[aUnitDisks[i].SlotNumber].SectorCount;

		// start to calc sizeUserSpace, sizeXArea
		sizeUserSpace = nDiskSize;
		
		if(iMirrorLevel)
		{
			// choose smaller size
			NDAS_IdeIO(&aUnitDisks[i ^1], 0, NULL, &path);			
			sizeUserSpace = min(sizeUserSpace, path.PerTarget[aUnitDisks[i ^1].SlotNumber].SectorCount);
		}

		nBitmapSize = (sizeUserSpace / pDiskInfoV2->iSectorsPerBit /* bits needed */) / 8 /* bytes needed */ / 512 /* sectors needed */ +1 /* last sector */; // backup bitmap size

		sizeXArea = nBitmapSize;
		sizeXArea *= 2; // double bitmap
		sizeXArea += 1 + 1 + 10; // S0, S1 and trails
		sizeXArea = max(2 * 1024 * 2, sizeXArea); // at least 2mega

		// reduce X Area size
		sizeUserSpace -= sizeXArea;
		sizeUserSpace -= sizeUserSpace % 128; // multiples of 128

		// AING_TO_DO : reduce sizeUserSpace so that bound disk size won't be over 2TB limit
//		sizeUserSpace = 160 * 128; // 10MB


		pDiskInfoV2->sizeXArea = sizeXArea;
		pDiskInfoV2->sizeUserSpace = sizeUserSpace;
		// end to calc sizeUserSpace, sizeXArea

		pDiskInfoV2->iSequence = i;

		// dirt or clean
		if(1 == iMirrorLevel)
		{
			pDiskInfoV2->FlagDirty = TRUE;
		}
		else
		{
			pDiskInfoV2->FlagDirty = FALSE;
		}

		// write S0, S1
		NDAS_IdeIO(&aUnitDisks[i], nDIB, cmd, NULL);

		// dirt or clean bitmap
		if(iMirrorLevel)
		{
			IDE_COMMAND_IO *aCmds;
			aCmds = HeapAlloc(GetProcessHeap(), 0, sizeof(IDE_COMMAND_IO) * (unsigned _int32)nBitmapSize);
			for(j = 0; j < nBitmapSize; j++)
			{
				aCmds[j].command = WIN_WRITE;
				aCmds[j].iSector = (-1 * sizeXArea) + (signed _int64)j;
				FillMemory(aCmds[j].data, 512, (iMirrorLevel == 1) ? 0xff : 0x00);
			}
			
			NDAS_IdeIO(&aUnitDisks[i], (unsigned _int32)nBitmapSize, aCmds, NULL);
			HeapFree(GetProcessHeap(), 0, aCmds);
		}
	}

	bReturn = TRUE;
out:

	if(NULL != cmd)
	{
		HeapFree(GetProcessHeap(), 0, cmd);
		cmd = NULL;
	}

	return bReturn;
}