PCI 구성 공간

**[[PCI 버스|PCI]], [[PCI-X]] 및 [[PCI 익스프레스]] 구성 공간**(PCI configuration space)은 버스에 삽입된 카드의 자동 구성을 수행하는 기본 방법이다.

## 개요
PCI 장치에는 구성 공간으로 알려진 레지스터 세트가 있으며, PCI 익스프레스는 장치에 대한 확장 구성 공간을 도입한다. 구성 공간 레지스터는 메모리 위치에 매핑된다. 장치 드라이버 및 진단 소프트웨어는 구성 공간에 접근해야 하며, 운영체제는 일반적으로 API를 사용하여 장치 구성 공간에 접근하도록 허용한다. 운영체제에 메모리 맵 구성 공간 요청에 대해 정의된 접근 방식 또는 API가 없는 경우, 드라이버 또는 진단 소프트웨어는 운영체제의 기본 접근 규칙과 호환되는 방식으로 구성 공간에 접근해야 하는 부담을 안는다. 모든 시스템에서 장치 드라이버는 장치의 구성 공간에 접근하기 위해 운영체제에서 제공하는 API를 사용하는 것이 권장된다.

## 기술 정보 <span class="anchor" id="DEVICE-FUNCTIONS"></span><span class="anchor" id="BDF"></span>

PCI 로컬 버스가 다른 I/O 아키텍처보다 크게 개선된 점 중 하나는 구성 메커니즘이었다. 일반적인 메모리 맵 및 I/O 포트 공간 외에도 버스의 각 장치 기능에는 256바이트 길이의 구성 공간이 있으며, 장치에 대한 8비트 PCI 버스, 5비트 장치, 3비트 기능 번호(일반적으로 버스/장치/기능을 줄여 BDF 또는 B/D/F로 지칭됨)를 알면 주소를 지정할 수 있다. 이를 통해 최대 256개의 버스를 지원하며, 각 버스는 최대 32개의 장치를 지원하고 각 장치는 8개의 기능을 지원할 수 있다. 단일 PCI 확장 카드는 장치로 응답할 수 있으며 최소한 기능 번호 0을 구현해야 한다. 구성 공간의 처음 64바이트는 표준화되어 있으며, 나머지는 공급업체 정의 목적으로 사용할 수 있다. 일부 고급 컴퓨터는 하나 이상의 PCI 도메인(또는 PCI 세그먼트)을 지원하며, 각 PCI 세그먼트는 최대 256개의 버스를 지원한다. PCI 세그먼트는 PCI 루트 브릿지로 참조될 수 있다.

기존 사용과 충돌하지 않고 구성 공간의 더 많은 부분을 표준화하기 위해 나머지 192바이트의 PCI 구성 공간 내에 정의된 기능 목록이 있을 수 있다. 각 기능에는 어떤 기능인지 설명하는 1바이트와 다음 기능을 가리키는 1바이트가 있다. 추가 바이트 수는 기능 ID에 따라 다르다. 기능이 사용되는 경우 상태 레지스터의 비트가 설정되고, 표준화된 레지스터에 정의된 Cap. 포인터 레지스터에 링크된 기능 목록의 첫 번째 항목을 가리키는 포인터가 제공된다.

PCI-X 2.0 및 PCI 익스프레스는 최대 4096바이트의 확장 구성 공간을 도입했다. 확장 구성 공간의 유일한 표준화된 부분은 확장 기능 목록의 시작인 에 있는 처음 4바이트이다. 확장 기능은 일반 기능과 매우 유사하지만 확장 구성 공간의 어떤 바이트도 참조할 수 있고(8비트 대신 12비트 사용), 4비트 버전 번호와 16비트 기능 ID를 갖는다. 확장 기능 ID는 일반 기능 ID와 중복되지만 별도의 목록에 있으므로 혼동될 가능성은 없다.

## 표준화된 레지스터
섬네일|300px|오른쪽|PCI 유형 0 (비 브릿지) 구성 공간 헤더의 표준 레지스터

장치 ID(DID) 및 공급업체 ID(VID) 레지스터는 장치(IC 등)를 식별하며 일반적으로 PCI ID라고 한다. 16비트 공급업체 ID는 PCI-SIG에서 할당한다. 16비트 장치 ID는 공급업체에서 할당한다. 알려진 모든 공급업체 및 장치 ID를 수집하는 비활성 프로젝트가 있다. (아래 외부 링크 참조)

상태 레지스터는 지원되는 기능과 특정 종류의 오류 발생 여부를 보고하는 데 사용된다. 명령어 레지스터에는 개별적으로 활성화 및 비활성화할 수 있는 기능의 비트마스크가 포함되어 있다. 헤더 유형 레지스터 값은 장치 기능에 따라 나머지 48바이트(64-16) 헤더의 다른 레이아웃을 결정한다. 즉, 루트 컴플렉스, 스위치 및 브릿지의 경우 유형 1 헤더를 사용한다. 그런 다음 엔드포인트의 경우 유형 0을 사용한다. Cache Line Size 레지스터는 장치가 메모리 쓰기 및 무효화 트랜잭션을 사용할 수 있도록 알려주기 전에 프로그래밍되어야 한다. 이것은 일반적으로 CPU 캐시 라인 크기와 일치해야 하지만 정확한 설정은 시스템에 따라 다르다. 이 레지스터는 PCI 익스프레스에 적용되지 않는다.

서브시스템 ID(SSID) 및 서브시스템 공급업체 ID(SVID)는 특정 모델(애드인 카드 등)을 구별한다. 공급업체 ID는 칩셋 제조업체의 것이고 서브시스템 공급업체 ID는 카드 제조업체의 것이다. 서브시스템 ID는 서브시스템 공급업체에서 할당하고 장치 ID는 칩셋 제조업체에서 할당한다. 예를 들어, 무선 네트워크 카드의 경우 칩 제조업체는 인텔 또는 브로드컴 또는 아테로스일 수 있으며, 카드 제조업체는 넷기어 또는 휴렛 팩커드일 수 있다. 일반적으로 공급업체 ID–장치 ID 조합은 호스트가 장치를 처리하기 위해 로드해야 하는 드라이버를 지정한다. 이는 동일한 VID:DID 조합을 가진 모든 카드가 동일한 드라이버로 처리될 수 있기 때문이다. 서브시스템 공급업체 ID–서브시스템 ID 조합은 카드를 식별하며, 이는 드라이버가 작동에 사소한 카드 특정 변경 사항을 적용하는 데 사용할 수 있는 정보이다.

## 버스 열거 <span class="anchor" id="BUS-ENUM"></span><span class="anchor" id="IDSEL"></span>
PCI 장치에 주소를 지정하려면 시스템의 I/O 포트 주소 공간 또는 메모리 맵 주소 공간에 매핑되어 활성화되어야 한다. 시스템의 펌웨어(바이오스 등) 또는 운영체제는 PCI 컨트롤러에 구성 명령어를 작성하여 장치에 리소스 구성을 알리기 위해 기본 주소 레지스터(일반적으로 BAR라고 함)를 프로그래밍한다. 시스템 재설정 시 모든 PCI 장치는 비활성 상태이므로 운영체제 또는 장치 드라이버가 통신할 수 있는 주소가 할당되지 않는다. 바이오스 또는 운영체제는 PCI 컨트롤러를 통해 슬롯별 또는 장치별 IDSEL(초기화 장치 선택) 신호를 사용하여 PCI 장치의 위치를 지리적으로 지정한다(예: 첫 번째 PCI 슬롯, 두 번째 PCI 슬롯, 세 번째 PCI 슬롯, 또는 메인보드에 통합된 PCI 장치 등).

컴퓨터 전원이 켜지면 바이오스 또는 운영체제에 의해 PCI 버스 및 장치가 열거되어야 한다. 버스 열거는 각 버스, 장치 및 기능에 대한 PCI 구성 공간 레지스터에 접근하여 수행된다. VID 및 DID와 다른 장치 번호는 해당 버스의 장치 순차 번호일 뿐이다. 또한 새 브릿지가 감지되면 새 버스 번호가 정의되고 장치 열거는 장치 번호 0에서 다시 시작된다.

장치의 기능 #0에서 응답이 수신되지 않으면 버스 마스터는 어보트를 수행하고 모든 비트가 설정된 값( 16진수)을 반환하는데, 이는 유효하지 않은 VID/DID 값이며, 따라서 바이오스 또는 운영체제는 지정된 버스/장치 번호/기능(B/D/F) 조합이 존재하지 않음을 알 수 있다. 따라서 특정 버스/장치에 대한 기능 ID 0에 대한 읽기가 마스터(개시자)를 어보트시키면, 장치가 기능 번호 0을 구현해야 하므로 해당 버스에 작동하는 장치가 없다고 가정해야 한다. 이 경우 나머지 기능 번호(1-7)에 대한 읽기는 존재하지 않으므로 필요하지 않다.

공급업체 ID 레지스터에 대한 특정 B/D/F 조합에 대한 읽기가 성공하면 시스템 펌웨어 또는 운영체제는 해당 장치가 존재함을 알게 된다. BAR에 모든 1을 쓰고 인코딩된 형태로 장치가 요청한 메모리 크기를 다시 읽는다. 이 설계는 모든 주소 공간 크기가 2의 거듭제곱이며 자연스럽게 정렬됨을 의미한다.

이 시점에서 바이오스 또는 운영체제는 장치의 BAR 구성 레지스터에 메모리 맵 주소와 I/O 포트 주소를 프로그래밍한다. 이 주소는 시스템 전원이 켜져 있는 동안 유효하다. 전원 차단 시 이 설정은 손실되고 다음 시스템 전원 켜짐 시 절차가 반복된다. 바이오스 또는 운영체제는 각 PCI 장치에 대한 PCI 구성 공간의 다른 레지스터(예: 인터럽트 요청)도 프로그래밍한다. 이 전체 프로세스는 완전히 자동화되어 있으므로 사용자는 카드 자체의 DIP 스위치를 변경하여 새로 추가된 하드웨어를 수동으로 구성하는 작업에서 벗어날 수 있다. 이러한 자동 장치 검색 및 주소 공간 할당이 바로 플러그 앤 플레이가 구현되는 방식이다.

PCI-to-PCI 브릿지가 발견되면 시스템은 브릿지 너머의 보조 PCI 버스에 0이 아닌 버스 번호를 할당한 다음 해당 보조 버스의 장치를 열거해야 한다. 더 많은 PCI 브릿지가 발견되면 가능한 모든 도메인/버스/장치 조합이 스캔될 때까지 검색이 재귀적으로 계속된다.

각 비브릿지 PCI 장치 기능은 최대 6개의 BAR를 구현할 수 있으며, 각 BAR는 I/O 포트 및 메모리 맵 주소 공간에서 다른 주소에 응답할 수 있다. 각 BAR는 4기가바이트 주소 공간 제한 아래에 있는 16바이트에서 2기가바이트 사이의 크기의 영역을 설명한다. 플랫폼이 시스템 펌웨어에서 "Above 4G" 옵션을 지원하는 경우 64비트 BAR를 사용할 수 있다. **Resizable BAR** (Re-Size BAR, AMD Smart Access Memory (SAM), 또는 애즈락 Clever Access Memory (CAM))로도 알려진 기능은 PCIe 장치가 더 큰 BAR 크기를 협상하는 데 사용할 수 있는 기능이다. 전통적으로 BAR는 256MB 크기로 제한되었지만, 최신 그래픽 카드에는 이보다 훨씬 큰 프레임버퍼가 있다. 이러한 불일치는 CPU가 프레임버퍼에 접근할 때 비효율성을 야기했다. Resizable BAR는 CPU가 전체 프레임버퍼에 한 번에 접근할 수 있도록 하여 성능을 향상시킨다.

PCI 장치에는 옵션 ROM이 있을 수도 있다.

## 하드웨어 구현
구성 공간 접근을 수행할 때 PCI 장치는 주소를 디코딩하여 응답해야 하는지 여부를 결정하는 대신 IDSEL(Initialization Device Select) 신호를 확인한다. 각 IDSEL 신호에 대한 시스템 전체의 고유한 활성화 방법이 있다. PCI 장치는 주소/데이터 신호의 하위 11비트(AD[10] ~ AD[0])만 디코딩해야 하며, 21개의 상위 A/D 신호(AD[31] ~ AD[11])는 디코딩을 무시할 수 있다. 이는 구성 공간 접근 구현이 각 슬롯의 IDSEL 핀을 다른 상위 주소/데이터 라인 AD[11]에서 AD[31]까지 연결하기 때문이다. IDSEL 신호는 각 PCI 장치/어댑터/슬롯에 대해 다른 핀이다.

슬롯 n에 있는 카드를 구성하려면 PCI 버스 브릿지는 AD[7:2] 라인에 주소를 지정할 PCI 장치의 레지스터를 사용하여 구성 공간 접근 사이클을 수행하며(레지스터는 이중 단어(32비트)이므로 AD[1:0]은 항상 0), AD[10:8] 비트에 지정된 PCI 기능 번호를 사용하고 AD[n+11]을 제외한 모든 상위 비트는 지정된 슬롯/장치에서 IDSEL 신호로 사용된다.

타이밍에 민감하고 따라서 전기적 부하에 민감한 AD[] 버스의 전기적 부하를 줄이기 위해 PCI 슬롯 커넥터의 IDSEL 신호는 일반적으로 저항을 통해 지정된 AD[n+11] 핀에 연결된다. 이로 인해 PCI의 IDSEL 신호는 다른 PCI 버스 신호보다 더 느리게 활성 상태에 도달한다(저항과 IDSEL 핀의 입력 정전 용량 모두의 RC 시정수 때문). 따라서 IDSEL 신호가 유효한 수준에 도달할 시간을 허용하기 위해 구성 공간 접근이 더 느리게 수행된다.

버스 스캔은 인텔 플랫폼에서 두 가지 정의된 표준화된 포트에 접근하여 수행된다. 이 포트는 구성 공간 주소() I/O 포트와 구성 공간 데이터() I/O 포트이다. 구성 공간 주소 I/O 포트에 기록된 값은 B/D/F 값과 레지스터 주소 값을 32비트 워드로 결합하여 생성된다.

## 소프트웨어 구현
구성 읽기 및 쓰기는 두 가지 방법으로 CPU에서 시작될 수 있다. 하나는 I/O 주소  및 를 통한 레거시 방법이고, 다른 하나는 메모리 맵 구성이다.

레거시 방법은 원래 PCI에 존재했으며 구성 접근 메커니즘(CAM)이라고 한다. 이는 PCI CONFIG_ADDRESS 및 PCI CONFIG_DATA라는 두 개의 32비트 레지스터를 통해 장치의 주소 공간 256바이트에 간접적으로 도달할 수 있도록 한다. 이 레지스터는 x86 I/O 주소 공간의  및  주소에 있다. 예를 들어, 소프트웨어 드라이버(펌웨어, OS 커널 또는 커널 드라이버)는 이러한 레지스터를 사용하여 장치의 레지스터 주소를 CONFIG_ADDRESS에 쓰고 장치에 기록되어야 하는 데이터를 CONFIG_DATA에 넣어 PCI 장치를 구성할 수 있다. 이 프로세스는 장치의 레지스터를 기록하기 위해 레지스터에 기록해야 하므로 "간접"이라고 한다.

CONFIG_ADDRESS의 형식은 다음과 같다.


```c
0x80000000 | bus << 16 | device << 11 | function <<  8 | offset
```


앞서 설명한 것처럼 버스, 장치 및 기능(BDF)을 통해 장치에 주소를 지정하는 것을 "장치 지리적 주소 지정"이라고도 한다. 지리적 주소 지정을 사용하는 코드의 예는 리눅스 커널 코드의 `arch/x86/pci/early.c`를 참조하십시오.

일부 AMD CPU에서 확장 구성 공간이 사용되는 경우, 오프셋의 추가 비트 11:8은 CONFIG_ADDRESS 레지스터의 비트 27:24에 기록된다.


```c
0x80000000 | (offset & 0xf00) << 16 | bus << 16 | device << 11 | function <<  8 | (offset & 0xff)
```


두 번째 방법은 PCI 익스프레스를 위해 만들어졌다. 이는 강화된 구성 접근 메커니즘(ECAM)이라고 한다. 장치의 구성 공간을 4&nbsp;KB로 확장하며, 하위 256바이트는 PCI의 원래(레거시) 구성 공간과 중첩된다. 주소 지정 가능한 공간의 섹션은 "도용"되어 CPU의 접근이 메모리로 이동하지 않고 PCI 익스프레스 패브릭의 특정 장치에 도달한다. 시스템 초기화 중에 바이오스는 이 "도용된" 주소 영역의 기본 주소를 결정하고 루트 컴플렉스 및 운영체제에 통신한다.

각 장치에는 자체 4&nbsp;KB 공간이 있으며, 각 장치의 정보는 간단한 배열 `dev[bus][device][function]`을 통해 접근 가능하므로 256&nbsp;MB의 물리적으로 연속된 공간이 이 용도로 "도용"된다(256 버스 × 32 장치 × 8 기능 × 4&nbsp;KB = 256&nbsp;MB). 이 배열의 기본 물리적 주소는 지정되지 않는다. 예를 들어, 최신 x86 시스템에서는 ACPI 테이블에 필요한 정보가 포함되어 있다.

## 같이 보기
* PC 카드
* 루트 컴플렉스

## 각주

## 외부 링크
* PCI 공급업체 및 장치 목록
* PCI ID 저장소, 알려진 모든 ID를 수집하는 프로젝트
* PCI 구성에 대한 I/O 포트 사용 설명
* 구성 공간 레지스터 정의가 있는 리눅스 커널 헤더 파일

분류:컴퓨터 버스
분류:PCI 버스