⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi2.c

📁 Windows CE 5.0下的U盘驱动源代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
    UCHAR             bCDB[MAX_CDB] = {0};
    #define           MAX_LIST_LENGTH 512
    UCHAR             bDataBlock[MAX_LIST_LENGTH] = {0};
    USHORT            usPageLength = 0;
    DWORD             dwErr = ERROR_SUCCESS;

    DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6!ScsiModeSense10: Enter\r\n")));

    dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL);
    if (ERROR_SUCCESS != dwErr) {
        return dwErr;
    }

    ASSERT(SCSI_DEVICE_DIRECT_ACCESS == pDevice->DeviceType || SCSI_DEVICE_CDROM == pDevice->DeviceType);
    ASSERT(Lun <= 0x7);

    tCommand.Flags   = DATA_IN;
    tCommand.Timeout = pDevice->Timeouts.ScsiCommandTimeout;
    tCommand.Length  = USBMSC_SUBCLASS_SCSI == pDevice->DiskSubClass ? SCSI_CDB_10 : UFI_CDB;
    tCommand.CommandBlock = bCDB;
    tCommand.dwLun = Lun;

    bCDB[0] = SCSI_MODE_SENSE10;
    bCDB[1] = ((Lun & 0x7) << 5);
    // Set disable block descriptors (DBD) bit to 1.
    //bCDB[1] |= 0x8;
    // Set page control (PC) and page code to 0; i.e., return current, vendor-
    // specific values.
    bCDB[2] = 0;
    bCDB[7] = 0;
    bCDB[8] = 8;
    usPageLength = 8;

    /*
    switch (pDevice->DeviceType) {
        case SCSI_DEVICE_DIRECT_ACCESS:
            if (pDevice->DiskSubClass == USBMSC_SUBCLASS_UFI || pDevice->DiskSubClass == USBMSC_SUBCLASS_SFF8070i) {
                bCDB[2] = MODE_PAGE_FLEXIBLE_DISK;
            }
            break;
        case SCSI_DEVICE_CDROM:
            bCDB[2] = MODE_PAGE_CDROM;
            break;
        default:
            DEBUGMSG(ZONE_ERR, (TEXT("USBDISK6!ScsiModeSense10: Unknown device type (0x%x)\r\n"), pDevice->DeviceType));
            break;
    }
    */

    memset(bDataBlock, 0, sizeof(bDataBlock));
    ASSERT(usPageLength <= sizeof(bDataBlock));

    tData.TransferLength = 0;
    tData.RequestLength = usPageLength;
    tData.DataBlock = bDataBlock;

    dwErr = UsbsDataTransfer(pDevice->hUsbTransport, &tCommand, &tData);

    if ((ERROR_SUCCESS != dwErr) || (tData.TransferLength < 4)) {
        dwErr = ScsiGetSenseData(pDevice, Lun);
        SetLastError(dwErr);
        DEBUGMSG(ZONE_ERR,(TEXT("USBDISK6!ScsiModeSense10: Failed to issue MODE SENSE (10) (%d) \r\n"), dwErr));
    }
    else {
        EnterCriticalSection(&pDevice->Lock);
        DEBUGMSG(ZONE_SCSI, (TEXT("USBDISK6!ScsiModeSense10: Device reported medium type of 0x%x\r\n"), bDataBlock[2]));
        pDevice->MediumType = bDataBlock[2];
        DEBUGMSG(ZONE_SCSI, (TEXT("USBDISK6!ScsiModeSense10: %s \r\n"), (bDataBlock[3] & 0x80) ? TEXT("Write-protected") : TEXT("Not write-protected")));
        pDevice->Flags.WriteProtect = bDataBlock[3] & 0x80;
        LeaveCriticalSection(&pDevice->Lock);
    }

    ReleaseRemoveLock(&pDevice->RemoveLock, NULL);

    DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6!ScsiModeSense10: Exit (%d)\r\n"), dwErr));

    return dwErr;
}

DWORD
ScsiModeSense6(
    PSCSI_DEVICE pDevice,
    UCHAR        Lun
    )
{
    TRANSPORT_DATA    tData;
    TRANSPORT_COMMAND tCommand;
    UCHAR             bCDB[SCSI_CDB_6];
    UCHAR             bDataBlock[MAX_LIST_LENGTH] = {0};
    USHORT            usPageLength = 0;
    DWORD             dwErr = ERROR_SUCCESS;

    DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6!ScsiModeSense6: Enter\r\n")));

    dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL);
    if (ERROR_SUCCESS != dwErr) {
        return dwErr;
    }

    ASSERT(SCSI_DEVICE_DIRECT_ACCESS == pDevice->DeviceType || SCSI_DEVICE_CDROM == pDevice->DeviceType);

    memset(bCDB, 0, sizeof(bCDB));
    tCommand.Flags = DATA_IN;
    tCommand.Timeout = pDevice->Timeouts.ScsiCommandTimeout;
    tCommand.Length = USBMSC_SUBCLASS_SCSI == pDevice->DiskSubClass ? SCSI_CDB_6 : UFI_CDB;
    tCommand.CommandBlock = bCDB;
    tCommand.dwLun = Lun;
    DEBUGCHK(Lun <= 0x7);

    bCDB[0] = SCSI_MODE_SENSE6;
    bCDB[1] = ((Lun & 0x7) << 5);
    bCDB[2] = 0;
    usPageLength = 4;

    /*
    switch (pDevice->DeviceType) {
        case SCSI_DEVICE_DIRECT_ACCESS:
            if (pDevice->DiskSubClass == USBMSC_SUBCLASS_UFI || pDevice->DiskSubClass == USBMSC_SUBCLASS_SFF8070i) {
                bCDB[2] = MODE_PAGE_FLEXIBLE_DISK;
            }
            break;
        case SCSI_DEVICE_CDROM:
            bCDB[2] = MODE_PAGE_CDROM;
            break;
    }
    */

    DEBUGCHK(usPageLength <= sizeof(bDataBlock));
    memset(bDataBlock, 0, sizeof(bDataBlock));

    tData.TransferLength = 0;
    tData.RequestLength = usPageLength;
    tData.DataBlock = bDataBlock;

    dwErr = UsbsDataTransfer(pDevice->hUsbTransport, &tCommand, &tData);

    if ((ERROR_SUCCESS != dwErr) || (tData.TransferLength < 4)) {
        dwErr = ScsiGetSenseData(pDevice, Lun);
        SetLastError(dwErr);
        DEBUGMSG(ZONE_ERR,(TEXT("USBDISK6!ScsiModeSense6: Failed to issue MODE SENSE (6) (%d) \r\n"), dwErr));
    }
    else {
        EnterCriticalSection(&pDevice->Lock);
        DEBUGMSG(ZONE_SCSI, (TEXT("USBDISK6!ScsiModeSense6: Device reported medium type of 0x%x\r\n"), bDataBlock[2]));
        pDevice->MediumType = bDataBlock[2];
        DEBUGMSG(ZONE_SCSI, (TEXT("USBDISK6!ScsiModeSense6: %s \r\n"), (bDataBlock[3] & 0x80) ? TEXT("Write-protected") : TEXT("Not write-protected")));
        pDevice->Flags.WriteProtect = bDataBlock[3] & 0x80;
        LeaveCriticalSection(&pDevice->Lock);
    }

    ReleaseRemoveLock(&pDevice->RemoveLock, NULL);

    DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6!ScsiModeSense6: Exit (%d)\r\n"), dwErr));

    return dwErr;
}

DWORD
ScsiStartStopUnit(
    PSCSI_DEVICE    pDevice,
    BOOL            Start,  // TRUE = START, else STOP
    BOOL            LoEj,
    UCHAR           Lun
    )
{
    TRANSPORT_COMMAND tCommand;
    UCHAR             bCDB[MAX_CDB];
    
    DWORD dwErr;
    
    DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6>ScsiStartStopUnit\n")));

    dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL);
    if ( ERROR_SUCCESS != dwErr) {
        return dwErr;
    }

    tCommand.Flags   = DATA_OUT;
    tCommand.Timeout = pDevice->Timeouts.ScsiCommandTimeout;
    tCommand.Length  = USBMSC_SUBCLASS_SCSI == pDevice->DiskSubClass ?
                       SCSI_CDB_6 : UFI_CDB;
    tCommand.CommandBlock = bCDB;
    tCommand.dwLun=Lun;

    memset( bCDB, 0, sizeof(bCDB));
    bCDB[0] = SCSI_START_STOP;

    ASSERT(Lun <= 0x7);
    bCDB[1] = ((Lun & 0x7) << 5);

    bCDB[4] = (LoEj & 0x1) << 1;
    bCDB[4] |= Start & 0x1;

    dwErr = UsbsDataTransfer(pDevice->hUsbTransport,
                             &tCommand,
                             NULL );

    if ( dwErr != ERROR_SUCCESS ) {

        dwErr = ScsiGetSenseData( pDevice, Lun );

        DEBUGMSG(ZONE_ERR,(TEXT("ScsiStartStopUnit ERROR:%d\n"), dwErr));

        SetLastError(dwErr);

    }

    ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
    
    DEBUGMSG(ZONE_SCSI,(TEXT("USBDISK6<ScsiStartStopUnit:%d\n"), dwErr));

    return dwErr;
}


//
// Checks the users SG to see if we can use it.
// Since we basically do a prescan then return flag saying
// if we need to use double buffering.
//
DWORD
CheckSegments(
    IN PSCSI_DEVICE    pDevice,
    IN PSG_REQ         pSgReq,
    IN OUT PDWORD      pTransferLength,
    IN OUT PDWORD      pFlags
    )
{
    DWORD dwErr = ERROR_SUCCESS;
    DWORD sg;

    DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC>CheckSegments\n")));


    if ( !pDevice || 0 == pDevice->DiskInfo.di_bytes_per_sect || 
         0 == pDevice->DiskInfo.di_total_sectors ) 
    {
        dwErr = ERROR_FLOPPY_UNKNOWN_ERROR;
        DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:1: di_bytes_per_sect:%d di_total_sectors:%d\n"),
            pDevice?pDevice->DiskInfo.di_bytes_per_sect:-1, pDevice?pDevice->DiskInfo.di_total_sectors:-1));
        
        TEST_TRAP();

    } else if ( !pSgReq || !pTransferLength || !pFlags) {

        dwErr=ERROR_INVALID_PARAMETER;
        DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:2: %d\n"), dwErr ));
    
    } else if (pSgReq->sr_num_sg > MAX_SG_BUF ||
               pSgReq->sr_start + pSgReq->sr_num_sec > pDevice->DiskInfo.di_total_sectors)
    {
            dwErr=ERROR_INVALID_PARAMETER;
            DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:3: sg:%d sr_start:%d, sr_num_sec:%d, di_total_sectors:%d di_bytes_per_sect:%d\n"),
                pSgReq->sr_num_sg, pSgReq->sr_start, pSgReq->sr_num_sec, pDevice->DiskInfo.di_total_sectors, pDevice->DiskInfo.di_bytes_per_sect));
    
    } else {
        //
        // ensure all the buffers in the SG list are OK
        //
        ASSERT(pFlags);
        ASSERT(pTransferLength);
	    EnterCriticalSection(&pDevice->Lock);

        for (sg = 0, *pTransferLength = 0, *pFlags = 0; sg < pSgReq->sr_num_sg; sg++) 
        {
            if ( !pSgReq->sr_sglist[sg].sb_buf )
            {
                dwErr = ERROR_INVALID_PARAMETER;
                DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:4:%d\n"), dwErr));
                break;
            }

            // do we need double buffering?
            if ((pSgReq->sr_sglist[sg].sb_len % pDevice->DiskInfo.di_bytes_per_sect) != 0)
            {
                *pFlags |= 0x1;
                DEBUGMSG(ZONE_READ,(TEXT("CheckSegments: Double Buffered\n")));
            }

            // sum all the buffer lengths to make sure they match 
            // the requested number of sectors
            *pTransferLength += pSgReq->sr_sglist[sg].sb_len;
        }

        if (dwErr == ERROR_SUCCESS && 
            *pTransferLength > (pSgReq->sr_num_sec * pDevice->DiskInfo.di_bytes_per_sect)) 
        {
            dwErr = ERROR_INVALID_PARAMETER;
            DEBUGMSG(ZONE_ERR,(TEXT("CheckSegments ERROR:5: invalid user SG buffers (%u > %u)\n"),
            *pTransferLength, (pSgReq->sr_num_sg * pDevice->DiskInfo.di_bytes_per_sect)));
        }
               
	    LeaveCriticalSection(&pDevice->Lock);
    }

    DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC<CheckSegments:%d\n"), dwErr));

    return dwErr;
}

/*++

    Validate a Scatter/Gather request object.

    Returns: If fail, Win32 error.
             If pass, ERROR_SUCCESS.
--*/
static DWORD
InspectSgReq(
    PSG_REQ pSgReq,
    UINT uiBytesPerSector
    )
{
    UINT uiSgIndex;         // Index into Scatter/Gather buffer array.
	UINT uiBytesToTransfer; // Running count of the number of bytes requested to transfer.
	
	DEBUGMSG(ZONE_SCSI, (TEXT("USBMSC>InspectSgReq\n")));

	if (pSgReq == NULL) {
		DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: pSqReq: NULL\n")));
		return ERROR_BAD_ARGUMENTS;
    }    
    if (pSgReq->sr_num_sec == 0) {
		DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: ->sr_num_sec: 0\n")));
		return ERROR_BAD_ARGUMENTS;
	}
	if (pSgReq->sr_num_sg == 0) {
		DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: ->sr_num_sg: 0\n")));
		return ERROR_BAD_ARGUMENTS;
	}
	DEBUGMSG(ZONE_SCSI, (TEXT("USBMSC>InspectSgReq: ->sr_num_sec: %d, ->sr_num_sg: %d, bytes/sec: %d\n"), pSgReq->sr_num_sec, pSgReq->sr_num_sg, uiBytesPerSector));
	for (uiSgIndex = 0, uiBytesToTransfer = 0; uiSgIndex < pSgReq->sr_num_sg; uiSgIndex += 1) {
		if (pSgReq->sr_sglist[uiSgIndex].sb_buf == NULL) {
			DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: ->sr_sglist[%d].sb_buf: NULL\n"), uiSgIndex));
			return ERROR_BAD_ARGUMENTS;
		}
		if (pSgReq->sr_sglist[uiSgIndex].sb_len == 0) {
			DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: ->sr_sglist[%d].sb_len: 0\n"), uiSgIndex));
			return ERROR_BAD_ARGUMENTS;
		}
		DEBUGMSG(ZONE_SCSI, (TEXT("USBMSC>InspectSgReq: ->sr_sglist[%d].sb_len: %d\n"), uiSgIndex, pSgReq->sr_sglist[uiSgIndex].sb_len));
		uiBytesToTransfer += pSgReq->sr_sglist[uiSgIndex].sb_len;
    }
	if (uiBytesPerSector==0 || ((uiBytesToTransfer / uiBytesPerSector) != pSgReq->sr_num_sec)) {
		DEBUGMSG(ZONE_ERR, (TEXT("USBMSC>InspectSgReq: Error: [(tot bytes = %d)*(bytes/sec = %d)] != (->sr_num_sec = %d)\n"), uiBytesToTransfer, uiBytesPerSector, pSgReq->sr_num_sec));
		return ERROR_BAD_ARGUMENTS;
	}
	DEBUGMSG(ZONE_SCSI,(TEXT("USBMSC<InspectSgReq\n")));	
	return ERROR_SUCCESS;
}

/*++

    Complete a Scatter/Gather request on a SCSI device.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -