I/O 전송 시퀀스

SPB 프레임워크 확장(SpbCx)은 I/O 전송 시퀀스를 지원합니다. I/O 전송 시퀀스는 단일 원자 버스 작업으로 수행되는 버스 전송(읽기 및 쓰기 작업)의 순서가 지정된 집합입니다. I/O 전송 시퀀스의 모든 전송은 버스의 동일한 대상 디바이스에 액세스합니다. 시퀀스가 수행되는 동안 SPB 컨트롤러 드라이버가 I/O 전송 시퀀스가 완료되기 전에 다른 디바이스에 대한 I/O 요청을 받을 수 있더라도 버스의 다른 디바이스에 액세스할 수 없습니다.

I/O 전송 시퀀스의 예로는 버스 쓰기 작업과 버스 읽기 작업이 뒤따르는 쓰기 읽기 작업이 있습니다. 클라이언트 주변 장치 드라이버는 이러한 유형의 시퀀스를 사용하여 SPB 연결 주변 디바이스의 함수 선택 레지스터에 쓴 다음 선택한 디바이스 함수의 값을 읽을 수 있습니다. 이 두 전송은 길이가 다를 수 있습니다. 예를 들어 쓰기 작업은 1바이트의 데이터를 전송할 수 있으며 읽기 작업은 많은 바이트의 데이터를 전송할 수 있습니다.

I/O 전송 시퀀스 유형

클라이언트는 다음 방법 중 하나로 I/O 전송 시퀀스를 시작할 수 있습니다.

  1. 클라이언트는 IOCTL_SPB_EXECUTE_SEQUENCE I/O 컨트롤 요청에서 전체 시퀀스를 지정할 수 있습니다. 이 요청을 통해 SPB 컨트롤러 드라이버는 전송 시퀀스를 수행하는 데 사용할 수 있는 하드웨어별 성능 최적화를 사용할 수 있습니다. 자세한 내용은 단일 요청 시퀀스를 참조하세요.

  2. 클라이언트는 IOCTL_SPB_LOCK_CONTROLLER I/O 컨트롤 요청을 보내 시퀀스의 시작 부분에 컨트롤러를 잠그고 시퀀스가 완료되면 IOCTL_SPB_UNLOCK_CONTROLLER 보낼 수 있습니다. 컨트롤러가 잠겨 있는 동안 클라이언트는 시퀀스의 각 읽기 또는 쓰기 작업에 대해 별도의 I /O 요청( IRP_MJ_READ 또는 IRP_MJ_WRITE)을 보냅니다. 자세한 내용은 클라이언트 구현 시퀀스를 참조하세요.

가능하면 클라이언트는 IOCTL_SPB_EXECUTE_SEQUENCE 요청을 사용해야 합니다. 이 요청은 오류가 발생하기 쉽기 쉽고 다른 클라이언트가 버스에서 잠기는 시간을 크게 줄입니다. 그러나 시퀀스에서 이후 전송을 시작하기 전에 시퀀스의 전송 중 하나에서 읽은 값을 확인해야 하는 경우 클라이언트는 IOCTL_SPB_LOCK_CONTROLLER 사용하여 요청을 IOCTL_SPB_UNLOCK_CONTROLLER 수 있습니다. 이 경우 필요한 것보다 더 오랫동안 버스에서 다른 클라이언트를 잠그지 않도록 주의 깊게 설계해야 하며, 잘못 설계된 주변 장치 드라이버는 전체 시스템 성능을 저하시킬 수 있습니다.

Single-Request 시퀀스

성능을 향상시키려면 SPB 컨트롤러 드라이버가 EvtSpbControllerIoSequence 콜백 함수를 구현하여 IOCTL_SPB_EXECUTE_SEQUENCE 요청을 처리해야 합니다. 이 방법은 SPB 컨트롤러 드라이버에 복잡성을 더하지만 다른 클라이언트가 버스에서 잠겨 있는 동안 클라이언트가 일련의 개별 읽기 및 쓰기 작업으로 I/O 전송 시퀀스를 수행하도록 요구하지 않습니다.

참고

EvtSpbControllerIoSequence 함수를 구현하는 것이 좋으며 Windows 8 요구 사항이 될 수 있습니다.

전송 시퀀스의 구현은 간단한 읽기 또는 쓰기 작업의 구현과 유사하지만 시퀀스의 개별 전송 간에 시퀀스 작업의 저장된 상태에 대한 업데이트가 추가로 필요합니다. 첫 번째 전송이 완료되면 SPB 컨트롤러 드라이버는 시퀀스 상태를 업데이트하여 시퀀스에서 다음 전송을 선택합니다. 시퀀스 상태는 디바이스 컨텍스트에 저장되며 EvtSpbControllerIoSequence 콜백에 전달되는 SPBREQUEST 핸들을 포함합니다. SPB 컨트롤러 드라이버는 이 핸들을 사용하여 시퀀스의 개별 전송에 대한 버퍼, 길이, 방향 및 위치 매개 변수를 가져옵니다. 이러한 매개 변수를 가져오는 방법에 대한 자세한 내용은 SpbRequestGetTransferParameters를 참조하세요.

SPB 컨트롤러 드라이버가 요청된 IOCTL_SPB_EXECUTE_SEQUENCE 작업을 수행할 수 없는 경우 실패 코드로 요청을 완료합니다. 이러한 오류가 발생하는 경우 클라이언트는 옵션으로 버스를 잠그고 일련의 간단한 I/O 요청으로 I/O 전송 시퀀스를 명시적으로 수행한 다음 버스의 잠금을 해제할 수 있습니다. 자세한 내용은 클라이언트 구현 시퀀스를 참조하세요.

SpbCx는 주변 장치 드라이버에서 수신하는 IOCTL_SPB_XXX 요청에 대해 매개 변수 검사를 수행합니다. IOCTL_SPB_EXECUTE_SEQUENCE 요청의 경우 SpbCx는 NULL 버퍼 포인터 또는 길이가 0인 버퍼를 포함하는 빈 시퀀스와 시퀀스를 모두 거부합니다.

SPB 컨트롤러 드라이버는 시퀀스의 각 전송 길이가 드라이버 지정 제한을 초과하지 않는지 확인해야 합니다. 예를 들어 WDK(Windows 드라이버 키트)의 SkeletonI2C 샘플 드라이버는 4K 바이트를 초과하는 전송을 지정하고 이 요청에 대한 상태 코드를 STATUS_INVALID_PARAMETER 설정하는 IOCTL_SPB_EXECUTE_SEQUENCE 요청에 실패합니다. IOCTL_SPB_EXECUTE_SEQUENCE 요청에 대한 시퀀스 작업을 시작하기 전에 드라이버는 시퀀스의 모든 전송에 대한 매개 변수의 유효성을 검사하여 작업이 성공적으로 완료될 수 있는지 확인해야 합니다.

SpbCx는 EvtSpbControllerLock 콜백이 있는 EvtSpbControllerIoSequence 콜백보다 우선하지 않으며 EvtSpbControllerUnlock 콜백이 있는 EvtSpbControllerIoSequence 콜백을 따르지 않습니다.

Client-Implemented 시퀀스

SPB 컨트롤러 드라이버의 클라이언트는 일련의 간단한 읽기 및 쓰기로 I/O 전송 시퀀스를 명시적으로 수행할 수 있습니다. 클라이언트는 커널 모드 드라이버 또는 버스에 연결된 주변 장치를 제어하는 사용자 모드 드라이버일 수 있습니다. 시퀀스의 첫 번째 전송 전에 클라이언트는 대상 디바이스에 IOCTL_SPB_LOCK_CONTROLLER 요청을 전송하여 관련 없는 다른 버스 액세스가 시퀀스의 전송 간에 발생하지 않도록 합니다. 다음으로, 클라이언트는 IRP_MJ_READIRP_MJ_WRITE 요청을 전송하여 시퀀스에서 전송을 수행합니다. 마지막으로 클라이언트는 잠금을 해제하는 IOCTL_SPB_UNLOCK_CONTROLLER 요청을 보냅니다.

이후 시퀀스의 전송이 이전 전송에 종속된 경우 클라이언트는 이러한 유형의 I/O 전송 시퀀스를 구현해야 할 수 있습니다. 예를 들어 첫 번째 읽기는 이후에 읽거나 쓸 바이트 수를 나타낼 수 있습니다. 그러나 이러한 종속성이 없는 경우 클라이언트는 시퀀스를 보다 효율적으로 수행할 수 있는 SPB 컨트롤러 드라이버에 IOCTL_SPB_EXECUTE_SEQUENCE 요청을 보내야 합니다.

클라이언트 구현 시퀀스를 시작하는 IOCTL_SPB_LOCK_CONTROLLER 요청과 시퀀스를 종료하는 IOCTL_SPB_UNLOCK_CONTROLLER 요청 간에 클라이언트가 대상 디바이스에 보낼 수 있는 유일한 I/O 요청은 IRP_MJ_READIRP_MJ_WRITE 요청 입니다. 이 규칙을 위반하는 것은 오류입니다.

SPB 잠금은 읽기 및 쓰기 시퀀스가 원자 버스 작업으로 수행되도록 보장하는 데만 사용되며 해당 용도로만 사용해야 합니다.

자세한 내용은 Client-Implemented 시퀀스 처리를 참조하세요.