SPB I/O 요청

I/O 컨트롤 코드 정의에 설명된 시스템 제공 CTL_CODE 매크로는 Spb.h에서 IOCTL_SPB_* 컨트롤 코드를 정의하는 데 사용됩니다.

IOCTL_SPB_EXECUTE_SEQUENCE 제어 코드

IOCTL_SPB_EXECUTE_SEQUENCE I/O 제어 코드를 사용하면 SPB 컨트롤러 드라이버의 클라이언트(주변 드라이버)가 하나의 I/O 요청을 사용하여 단일 원자성 작업으로 전송 시퀀스(읽기 및 쓰기)를 수행할 수 있습니다. 버스의 지정된 디바이스는 시퀀스의 모든 전송 대상입니다.

고정 길이 전송 시퀀스를 단일 원자성 작업으로 지정하면 IOCTL_SPB_EXECUTE_SEQUENCE I/O 제어 요청을 통해 컨트롤러 드라이버가 I/O 전송을 최적화하고 성능을 향상시킬 수 있습니다.

클라이언트는 대상 디바이스의 파일 개체에 이 I/O 컨트롤 요청을 보냅니다.

SPB 컨트롤러 드라이버는 I/O 전송 시퀀스에 대한 버스 전송을 수행하기 위해 EvtSpbControllerIoSequence 콜백 함수를 등록합니다. SPB 프레임워크 확장(SpbCx)은 이 함수를 호출하여 처리를 위해 spB 컨트롤러 드라이버에 IOCTL_SPB_EXECUTE_SEQUENCE 요청을 전달합니다.

입력 버퍼 IOCTL_SPB_EXECUTE_SEQUENCE

입력 버퍼는 클라이언트의 데이터 버퍼에 대한 포인터 목록을 포함하는 SPB_TRANSFER_LIST 구조체입니다. 이 목록에는 I/O 전송 시퀀스의 각 전송(읽기 또는 쓰기)에 대한 데이터 버퍼가 포함되어 있습니다.

입력 버퍼 길이 IOCTL_SPB_EXECUTE_SEQUENCE

SPB_TRANSFER_LIST 구조체의 크기입니다.

IOCTL_SPB_EXECUTE_SEQUENCE 상태 블록

작업이 성공하면 컨트롤러 드라이버는 상태 멤버를 STATUS_SUCCESS 설정하고 정보 멤버를 시퀀스 중에 전송된 총 바이트 수로 설정합니다.

이 작업은 리소스 부족, 잘못된 클라이언트 입력 및 디바이스 오작동을 포함할 수 있는 다양한 이유로 인해 실패할 수 있습니다.

컨트롤러 드라이버가 I/O 요청을 처리하기 시작하지만 시퀀스의 전송 중 하나에서 오류가 발생하는 경우(예: 대상 디바이스가 NACK에 전송 거부 신호를 표시함) 컨트롤러 드라이버는 시퀀스의 나머지 전송을 중단합니다. 그런 다음 드라이버는 완료 상태 STATUS_SUCCESS 설정하고, 정보 멤버를 오류가 발생하기 전에 성공적으로 전송된 바이트 수로 설정하고, 요청을 완료합니다.

IOCTL_SPB_FULL_DUPLEX 제어 코드

IOCTL_SPB_FULL_DUPLEX 제어 코드는 클라이언트(주변 드라이버)에서 전체 이중 I/O 작업을 요청하는 데 사용됩니다. 전체 이중 I/O 작업은 데이터를 동시에 읽고 쓸 수 있는 SPI와 같은 버스용 컨트롤러에서 지원됩니다. I/O 컨트롤 코드 정의에 설명된 시스템 제공 CTL_CODE 매크로는 다음과 같이 IOCTL_SPB_FULL_DUPLEX 정의하는 데 사용됩니다.

버스의 디바이스에 대한 사용자 모드 드라이버 또는 커널 모드 드라이버는 이 I/O 컨트롤 요청을 대상 디바이스의 파일 개체로 보냅니다.

이 IOCTL은 데이터를 동시에 읽고 쓸 수 있는 SPI와 같은 버스용 SPB 컨트롤러 드라이버에서만 지원됩니다.

전체 이중 전송에 대한 쓰기 및 읽기 버퍼는 SPB_TRANSFER_LIST 구조로 설명됩니다. 이 구조체는 다음 형식을 사용해야 합니다.

  • SPB_TRANSFER_LIST_ENTRY 구조체의 배열에는 정확히 두 개의 요소가 포함됩니다. 첫 번째 요소는 쓰기 버퍼(Direction = SpbTransferDirectionToDevice)를 설명합니다. 두 번째 요소는 읽기 버퍼(Direction = SpbTransferDirectionFromDevice)를 설명합니다.

  • 두 SPB_TRANSFER_LIST_ENTRY 구조체의 DelayInUs 멤버는 0이어야 합니다. 쓰기 버퍼 및 읽기 버퍼에 대한 버퍼 형식은 다음 중 한 가지일 수 있습니다.

    • SpbTransferBufferFormatSimple
    • SpbTransferBufferFormatList
    • SpbTransferBufferFormatSimpleNonPaged
    • SpbTransferBufferFormatMdl

    이전 목록의 마지막 두 형식은 커널 모드 클라이언트에서만 사용할 수 있습니다. 쓰기 및 읽기 버퍼의 형식은 동일할 필요가 없습니다. 이러한 버퍼 형식에 대한 자세한 내용은 SPB_TRANSFER_BUFFER_FORMAT 참조하세요.

작업이 성공하면 정보 멤버가 쓰기 버퍼 및 읽기 버퍼 크기의 합계보다 작은 값으로 설정될 수 있습니다. 이 값은 요청이 취소되거나 작업이 디바이스에 쓰기 버퍼의 전체 내용을 쓸 수 없거나 디바이스에서 읽은 데이터로 읽기 버퍼를 완전히 채울 수 있는 경우에 발생할 수 있습니다.

쓰기 및 읽기 버퍼 크기는 동일할 필요가 없습니다. 쓰기 버퍼가 읽기 버퍼보다 큰 경우 읽기 버퍼가 가득 찬 후에도 작업은 쓰기 버퍼에서 데이터를 계속 씁니다. 읽기 버퍼가 쓰기 버퍼보다 크면 쓰기 버퍼가 비워진 후에도 작업이 읽기 버퍼를 계속 채웁니다.

SPB 컨트롤러 드라이버가 EvtSpbControllerIoOther 콜백 함수를 등록하는 경우 SPB 프레임워크 확장(SpbCx)은 이 함수를 호출하여 처리를 위해 SPB 컨트롤러 드라이버에 IOCTL_SPB_FULL_DUPLEX 요청을 전달합니다. SpbCx는 IOCTL_SPB_FULL_DUPLEX 요청에 대한 매개 변수 검사, 전송 목록 유효성 검사 또는 기타 처리를 수행하지 않습니다.

SPB 컨트롤러 드라이버가 이 IOCTL에 대한 지원을 구현하는 방법에 대한 자세한 내용은 IOCTL_SPB_FULL_DUPLEX 요청 처리를 참조하세요.

입력 버퍼 IOCTL_SPB_FULL_DUPLEX

클라이언트의 입력 및 출력 데이터 버퍼에 대한 포인터를 포함하는 SPB_TRANSFER_LIST 구조체에 대한 포인터입니다. 이 구조체에는 정확히 두 개의 요소로 구성된 Transfers 배열이 포함되어 있습니다. 첫 번째 요소는 디바이스에 쓸 데이터가 포함된 버퍼를 설명합니다. 두 번째 요소는 디바이스에서 읽은 데이터를 보관하는 데 사용되는 버퍼를 설명합니다. SPB 컨트롤러 드라이버가 SPB_TRANSFER_LIST 구조를 사용하여 버퍼를 설명하는 IOCTL(사용자 지정 I/O 컨트롤) 요청을 구현하는 방법에 대한 자세한 내용은 사용자 지정 IOCTL에 SPB_TRANSFER_LIST 구조 사용을 참조하세요.

입력 버퍼 길이 IOCTL_SPB_FULL_DUPLEX

SPB_TRANSFER_LIST 구조체의 크기입니다.

IOCTL_SPB_FULL_DUPLEX 상태 블록

작업이 성공하면 컨트롤러 드라이버는 Status 멤버를 STATUS_SUCCESS 설정하고 정보 멤버를 전체 이중 작업 중에 전송된 총 바이트 수(읽은 바이트 및 쓴 바이트)로 설정합니다.

이 작업은 리소스 부족, 잘못된 클라이언트 입력 및 디바이스 오작동을 포함할 수 있는 다양한 이유로 인해 실패할 수 있습니다.

IOCTL_SPB_LOCK_CONNECTION 제어 코드

IOCTL_SPB_LOCK_CONNECTION 제어 코드는 클라이언트(주변 드라이버)에서 다른 클라이언트와 공유되는 SPB 연결 대상 디바이스에서 연결 잠금을 획득하는 데 사용됩니다. 클라이언트가 연결 잠금을 보유하는 동안 이 클라이언트는 디바이스에 독점적으로 액세스할 수 있습니다. I/O 제어 코드 정의에 설명된 시스템 제공 CTL_CODE 매크로는 다음과 같이 IOCTL_SPB_LOCK_CONNECTION 정의하는 데 사용됩니다.

IOCTL_SPB_LOCK_CONNECTION 및 IOCTL_SPB_UNLOCK_CONNECTION 요청은 간단한 주변 버스에 연결된 대상 디바이스에서 연결 잠금을 획득하고 해제합니다. 대부분의 클라이언트는 이러한 I/O 제어 요청을 사용하지 않습니다. 이러한 요청은 두 클라이언트가 동일한 대상 디바이스에 대한 액세스를 공유하는 경우에만 사용됩니다. 자세한 내용은 SPB 연결 잠금을 참조하세요.

두 클라이언트는 동일한 대상 디바이스에 대한 별도의 논리적 연결을 열고 두 클라이언트가 디바이스에 대한 단독 액세스가 필요한 경우 연결 잠금을 사용할 수 있습니다. 한 클라이언트가 잠금을 보유하면 첫 번째 클라이언트가 잠금을 해제할 때까지 두 번째 클라이언트에서 디바이스에 대한 I/O 요청이 자동으로 지연됩니다.

클라이언트는 대상 디바이스에 대한 연결 잠금과 SPB 컨트롤러의 컨트롤러 잠금을 동시에 보유할 수 있습니다. IOCTL_SPB_LOCK_CONTROLLER 및 IOCTL_SPB_UNLOCK_CONTROLLER 요청은 컨트롤러 잠금을 획득하고 해제합니다. 클라이언트는 컨트롤러 잠금을 획득하기 전에 연결 잠금을 획득해야 하며 연결 잠금을 해제하기 전에 컨트롤러 잠금을 해제해야 합니다. 클라이언트는 컨트롤러 잠금을 사용하여 단일 원자 버스 작업으로 순서가 지정된 버스 전송 집합(읽기 및 쓰기 작업)을 수행합니다. 자세한 내용은 I/O 전송 시퀀스를 참조하세요.

디바이스에서 연결이 잠겨 있는 동안 IRP_MJ_CLEANUP 요청이 대상 디바이스로 전송되면 연결 잠금이 자동으로 종료됩니다. 클라이언트가 디바이스에 대한 파일 핸들을 닫으면 정리 요청이 대상 디바이스로 전송됩니다.

IOCTL_SPB_LOCK_CONNECTION 상태 블록

작업이 성공하면 Status 멤버가 STATUS_SUCCESS 설정됩니다.

작업이 실패하면 Status 멤버가 코드에 상태 적절한 오류로 설정됩니다.

클라이언트가 대상 디바이스의 연결 잠금 또는 SPB 컨트롤러의 컨트롤러 잠금을 이미 보유하고 있는 경우 상태 = STATUS_INVALID_DEVICE_REQUEST 이 작업이 실패합니다. 이 작업은 리소스 부족, 잘못된 클라이언트 입력 및 디바이스 오작동을 포함할 수 있는 다른 이유로 인해 실패할 수 있습니다.

IOCTL_SPB_LOCK_CONTROLLER 제어 코드

IOCTL_SPB_LOCK_CONTROLLER 제어 코드는 클라이언트(주변 드라이버)에서 SPB 컨트롤러를 잠그는 데 사용됩니다. 컨트롤러가 잠겨 있는 동안 클라이언트는 잠금에 대해 지정된 대상 디바이스에 액세스하기 위해 버스를 단독으로 사용합니다. I/O 컨트롤 코드 정의에 설명된 시스템 제공 CTL_CODE 매크로는 다음과 같이 IOCTL_SPB_LOCK_CONTROLLER 정의하는 데 사용됩니다.

대상 디바이스에 액세스하기 위해 버스를 단독으로 사용하기 위해 클라이언트(주변 드라이버)는 이 IOCTL을 대상의 파일 개체로 보냅니다. 이 IOCTL이 완료되면 컨트롤러가 잠기고 버스의 모든 I/O 전송(읽기 또는 쓰기)이 지정된 대상에 액세스합니다. 전송 사이에 컨트롤러는 대상 디바이스를 선택된 상태를 유지하지만 클록을 중지합니다.

클라이언트가 컨트롤러의 잠금을 해제하기 위해 IOCTL_SPB_UNLOCK_CONTROLLER 요청을 보낼 때까지 컨트롤러는 잠긴 상태로 유지됩니다. 대상 디바이스에 대한 클라이언트의 전송 시퀀스가 완료되면 컨트롤러가 버스의 다른 대상에 대한 I/O 요청을 처리할 수 있도록 클라이언트가 컨트롤러의 잠금을 해제해야 합니다.

컨트롤러가 대상에 잠겨 있는 동안 IRP_MJ_CLEANUP 요청이 대상 디바이스로 전송되면 잠금이 자동으로 종료됩니다. 정리 요청은 클라이언트가 대상에 대한 핸들을 닫을 때 대상으로 전송됩니다.

SPB 컨트롤러는 IOCTL_SPB_LOCK_CONTROLLER 및 IOCTL_SPB_UNLOCK_CONTROLLER 요청을 지원할 필요가 없으며 주변 장치 드라이버는 지원된다고 가정해서는 안 됩니다.

SPB 컨트롤러 드라이버가 EvtSpbControllerLock 콜백 함수를 등록하는 경우 SPB 프레임워크 확장(SpbCx)은 이 함수를 호출하여 처리를 위해 SPB 컨트롤러 드라이버에 IOCTL_SPB_LOCK_CONTROLLER 요청을 전달합니다.

IOCTL_SPB_LOCK_CONTROLLER 상태 블록

작업이 성공하면 Status 멤버가 STATUS_SUCCESS 설정됩니다. 이 IOCTL은 단독 액세스 모드에서 작동하도록 컨트롤러를 구성하지 못하는 등 여러 가지 이유로 오류 상태 반환할 수 있습니다. 이 모드에서 컨트롤러는 버스의 모든 I/O 전송에 대한 전용 대상이 되도록 대상 디바이스를 선택된 상태로 유지합니다. 컨트롤러는 잠금 해제될 때까지 이 모드로 유지됩니다.

IOCTL_SPB_UNLOCK_CONNECTION 제어 코드

IOCTL_SPB_UNLOCK_CONNECTION I/O 제어 코드는 클라이언트(주변 드라이버)에서 다른 클라이언트와 공유되는 SPB 연결 대상 디바이스에서 연결 잠금을 해제하는 데 사용됩니다. 클라이언트는 이전에 디바이스에 대한 단독 액세스를 획득하기 위해 IOCTL_SPB_LOCK_CONNECTION 요청을 보냈습니다.

IOCTL_SPB_LOCK_CONNECTION 및 IOCTL_SPB_UNLOCK_CONNECTION 요청은 간단한 주변 버스에 연결된 대상 디바이스에서 연결 잠금을 획득하고 해제합니다. 대부분의 클라이언트는 이러한 I/O 제어 요청을 사용하지 않습니다. 이러한 요청은 두 클라이언트가 동일한 대상 디바이스에 대한 액세스를 공유하는 경우에만 사용됩니다. 자세한 내용은 SPB 연결 잠금을 참조하세요.

클라이언트(주변 장치 드라이버)가 버스의 대상 디바이스에 IOCTL_SPB_LOCK_CONNECTION 요청을 보내고 요청이 성공적으로 완료되면 클라이언트가 연결 잠금을 해제하기 위해 IOCTL_SPB_UNLOCK_CONNECTION 요청을 보낼 때까지 연결이 잠깁니다.

클라이언트는 클라이언트가 더 이상 디바이스에 대한 단독 액세스가 필요하지 않은 경우 대상 디바이스에 대한 연결 잠금을 해제하는 IOCTL_SPB_UNLOCK_CONNECTION 요청을 보냅니다. 다른 클라이언트가 디바이스에 액세스할 수 있도록 연결을 잠금 해제해야 합니다.

IOCTL_SPB_UNLOCK_CONNECTION 상태 블록

작업이 성공하면 Status 멤버가 STATUS_SUCCESS 설정됩니다.

작업이 실패하면 Status 멤버가 코드에 상태 적절한 오류로 설정됩니다. 클라이언트가 대상 디바이스에서 연결 잠금을 유지하지 않거나 클라이언트가 SPB 컨트롤러에 대한 연결 잠금을 계속 유지하는 경우 이 작업이 실패하고 상태 = STATUS_INVALID_DEVICE_REQUEST. 이 작업은 리소스 부족, 잘못된 클라이언트 입력 및 디바이스 오작동을 포함할 수 있는 다른 이유로 인해 실패할 수 있습니다.

IOCTL_SPB_UNLOCK_CONTROLLER 제어 코드

IOCTL_SPB_UNLOCK_CONTROLLER I/O 제어 코드는 클라이언트(주변 드라이버)에서 SPB 컨트롤러의 잠금을 해제하는 데 사용됩니다. 클라이언트는 이전에 버스의 대상 디바이스에 액세스하기 위해 버스를 독점적으로 사용하기 위해 컨트롤러를 잠갔습니다.

클라이언트(주변 장치 드라이버)가 버스의 대상 디바이스에 IOCTL_SPB_LOCK_CONTROLLER I/O 제어 요청을 보낸 후에는 클라이언트가 컨트롤러 잠금을 해제하기 위해 IOCTL_SPB_UNLOCK_CONTROLLER I/O 제어 요청을 보낼 때까지 컨트롤러가 잠긴 상태로 유지됩니다. 클라이언트는 이러한 I/O 컨트롤 요청을 대상 디바이스의 파일 개체로 보냅니다.

클라이언트는 버스에서 일련의 전송을 완료하고 대상 디바이스를 해제하려고 할 때 IOCTL_SPB_UNLOCK_CONTROLLER 요청을 보냅니다. 버스의 다른 대상에 대한 I/O 요청을 처리할 수 있도록 컨트롤러의 잠금을 해제해야 합니다.

SPB 컨트롤러는 IOCTL_SPB_LOCK_CONTROLLER 및 IOCTL_SPB_UNLOCK_CONTROLLER 요청을 지원할 필요가 없으며 주변 장치 드라이버는 지원된다고 가정해서는 안 됩니다.

SPB 프레임워크 확장(SpbCx)은 SPB 컨트롤러 드라이버의 선택적 EvtSpbControllerUnlock 콜백 함수를 호출하여 처리를 위해 spB 컨트롤러 드라이버에 IOCTL_SPB_LOCK_CONTROLLER 요청을 전달합니다.

IOCTL_SPB_UNLOCK_CONTROLLER 상태 블록

작업이 성공하면 Status 멤버가 STATUS_SUCCESS 설정됩니다.

이 IOCTL은 지정된 대상에 대한 단독 액세스를 위해 컨트롤러가 잠겨 있지 않은 클라이언트에서 보낸 경우에만 실패할 수 있습니다.