Linux 6.18 driver API · 각 장치 규격과 binding 확인 필요

I²C·SPI·USB·PCIe: 연결과 전송을 구분해서 읽습니다

버스마다 다른 주소·전송·완료의 의미를 비교하고 driver가 지켜야 할 수명을 살펴봅니다.

서로 다른 버스의 주소를 같은 숫자로 생각하지 않습니다

버스주소·선택의 대표 의미주의할 점
I²Cadapter와 slave address로 장치를 선택합니다.7비트 주소와 R/W bit까지 합친 8비트 전송 값을 구분합니다.
SPIcontroller의 chip select로 대상을 고릅니다.slave address가 I²C처럼 표준 packet에 포함된다고 가정하지 않습니다.
USBhost가 device·configuration·interface·endpoint를 관리합니다.device address와 endpoint 번호, interface 번호는 다른 값입니다.
PCIebus/device/function과 BAR·DMA 주소 등을 사용합니다.BAR의 CPU MMIO 주소와 장치가 RAM에 접근하는 DMA 주소를 구분합니다.

버스가 발견됐다는 것은 통신 경로의 한 조건입니다. 장치가 필요한 전원·clock·reset 상태인지, driver가 맞는 protocol을 쓰는지까지 확인해야 합니다. I²C 사용자 인터페이스 SPI 사용자 인터페이스 PCI driver의 자원 처리

I²C register 읽기는 장치의 protocol을 따릅니다

register 주소를 먼저 쓰고 데이터를 읽는 장치의 예
  1. 메시지 1

    slave에 읽을 register 번호를 전송합니다.

    필요한 경우 repeated START로 다음 메시지를 이어 갑니다.

  2. 메시지 2

    같은 slave에서 지정 길이의 데이터를 읽습니다.

    전송 결과와 길이를 확인합니다.

  3. 호출자

    endianness와 bit field 규칙에 맞춰 값을 해석합니다.

화살표는 버스 메시지의 순서입니다. 모든 I²C 장치가 register 주소 쓰기+읽기 형태를 사용하는 것은 아닙니다.

별도의 write()와 read()는 중간에 STOP을 만들 수 있어 combined transaction과 다를 수 있습니다. 사용자 공간에서 여러 메시지를 한 묶음으로 요청할 때는 I2C_RDWR와 adapter가 지원하는 기능을 확인합니다. SPI 역시 read와 write를 따로 호출할지 SPI_IOC_MESSAGE로 chip select 유지가 필요한 전송을 묶을지 장치 규약에 따라 정합니다.

URB 제출 성공과 전송 완료는 다릅니다

비동기 USB 전송의 수명

1. 준비

driver가 endpoint, buffer, 길이, completion callback과 context를 준비합니다. callback이 사용할 driver 객체도 살아 있어야 합니다.

2. 제출

usb_submit_urb()가 성공하면 전송이 접수된 것입니다. 요청한 모든 바이트가 장치에 도착했다는 뜻은 아닙니다. 제출 실패 경로도 따로 처리해야 합니다.

3. 완료 callback

상태와 실제 전송 길이를 확인합니다. 취소·disconnect·오류 완료를 정상 데이터와 구분합니다. USB completion callback에서는 잠들 수 없습니다. 오래 걸리거나 sleep이 필요한 처리는 적절한 별도 문맥으로 넘겨야 합니다.

4. 재사용 또는 종료

사용 중인 URB·buffer를 무조건 해제하지 않습니다. disconnect에서 진행 중 전송과 callback을 정리한 뒤 마지막 참조를 반환해야 합니다.

단계는 요청 객체의 수명입니다. USB host가 URB라는 C 구조체 자체를 장치 firmware에 그대로 전송하는 것은 아닙니다.

USB driver의 제출·완료·disconnect 현재 USB host API의 규칙

MMIO·DMA·MSI는 다른 통로입니다

CPU는 BAR를 통해 장치 register에 접근하고, 장치는 DMA 주소를 사용해 RAM의 buffer에 접근할 수 있습니다. MSI/MSI-X는 장치가 interrupt를 알리는 방식입니다. MMIO register에 값을 썼다고 DMA가 끝났거나 해당 interrupt의 처리가 완료된 것은 아닙니다.

행동필요한 확인
BAR 접근자원 예약·mapping·접근 폭·endianness·ordering을 맞춥니다.
DMA 시작DMA mask·mapping·descriptor·완료·unmap 수명을 맞춥니다.
interrupt 처리할당한 vector와 장치 상태를 맞추고 mask·ack 규칙을 지킵니다.
장치 제거새 요청을 막고 진행 중 DMA·IRQ·work를 정리한 뒤 자원을 반환합니다.