다음 이전 차례

8. 부록

8.1 어드레스

어드레스에는 3 개의 타입, 즉 메인 메모리 어드레스, I/O 어드레스, 설정 어드레스가 있다. PCI 버스에서, 설정 어드레스는 I/O 어드레스와 닮은 다른 어드레스 공간을 구성 한다. 어려운 ISA의 설정 어드레스의 경우를 제외하고, 버스상의 어드레스가 메모리 어드레스, I/O 어드레스, 설정 어드레 스로 있는지는, 버스의 다른 선(traces)의 전압에 의해서만 결정된다.

ISA 버스의 설정 어드레스 (Read-Port등)

ISA 버스의 경우, 기술적으로 설정 어드레스 공간은 없지만, CPU 가 PnP 카드의 PnP 설정 레지스터에 억세스하기 위한 특별한 방법이 있다. 의 목적을 위해서, 3 개의 @ I/O 어드레스가 할당되어 있다. 그러나, 각각의 카드에 3개씩 어드레스가 할당되었다는 것이 아니라, 모든 카드에서 3 개의 어드레스를 공유 한다.

3 개의 어드레스 이름은, 각각 read-port, write-port, address-port 이다. 각 포트의 사이즈는 정확히 1 바이트이다. PnP 카드는 제각기 레지스터를 많이 가지고 있기 때문에, 이 3 개의 어드레스에서는 카드 1 매분의 레지스터에 대한 것도 충분하지 않다. 특정의 카드와 통신 하기 위해서는, 특별히 할당되어진 카드의 번호(핸들)을 write-port 어드레스를 사용해 모든 카드에 보낸다. 그러면, 이 핸들을 가진 카드만이 감시 상태가 된다. 다음으로(이 카드의)설정 레지스터의 어드레스 포트에 보낸다(어드레스 포트는 모든 카드가 공유되어 있지만, 현재 포트의 감시를 하고 있는 것은 1 개뿐이다). 그런 다음, 통신은 그 카드의 설정 레지스터 중의 하나에서 일어난다. 이것은 read-port로부터 읽어 내거나, write-port에서의 쓰기에 의해 행해진다.

write-port의 어드레스는 반드시 A79로, 어드레스 포트의 어드레스는 반드시 279이다(16 진수). 그러나, read-port 포트의 어드레스는 고정이 아니며, 그 외 의 ISA 카드와 겹치지 않다고 생각되는 어드레스에 설정 프로그램이 설정한다. 어드레스가 겹친 경우는 변경된다. read-port의 어드레스를 사용해, 모든 PnP 카드를 「프로그램한다」는것이 가능하다. 그렇지만 , isapnp 등을 사용해 데이터의 설정과 체크를 하는 경우에는, 이 read-port 어드레스를 정하지 않으면 안 된다.

어드레스의 범위

본문서에서는 「어드레스」라는 단어에서 어드레스에 인접하고 있는 범위를 가리키는 것으로 가끔 사용되었다. 어드레스는 바이트 단위로 주어지므로, 1 개의 어드레스 는 1 바이트의 용량밖에 없다. 그러나, I/O(와 메인 메모리)어드레스 에는 이것보다 큰 사이즈가 필요하다. 따라서, I/O 어드레스에는 예를 들면, 8 바이트의 범위가 사용되는 것이 많고, 디바이스에 할당되어진 메인 메모리 어드레스의 범위는 이것보다도 좀 더 커야한다. 시리얼 포트 (I/O 디바이스)의 경우에는, 디바이스 최초의 I/O 어드레스(3F8 등)을 부여하는 것으로 충분하다. 왜냐하면, 이 디바이스에 대한 어드레스의 범위는 8 바이트 밖에 없는 것으로 상식화 되어 있기 때문이다. 이 범위 중 최초의 어드레스는 「베이스어드레스(base address)」라고 불리운다.

어드레스 공간

ISA 버스의 경우, I/O 어드레스와 (메인)메모리 어드레스의 「공간」에 접근할 때에는, 같은 어드레스 버스가 사용된다.(어드레스에 사용되는 배선이 공 유된다). 그러면, 디바이스는 어드레스 버스에 나타나는 어드레스가 메모리 어드레스인지, I/O 어드레스인지를 어떻게 알수 있을까? 사실는 버스상에는 4 개의 전용 선이 있어, 이러한 정보를 전하는 것이다. 4개의 선 중의 특정한 것에 신호가 흐른 경우, 이것은 CPU가 I/O 어드레스 로부터 데이터를 읽으려하고 있는 것과, 메인 메모리는 버스 상의 어드레스를 무시하는 것을 의미 한다. 나머지의 3 개의 선도 비슷한 목적으로 사용된다. 간단하게 설명하면, 읽기와 쓰기의 선이 메인 메모리와 I/O 어드레스 의 양쪽을 위해서 존재한다(선은 전부 4 개이다).

PCI 버스의 경우도 기본적인 사고방식은 같이 4 개의 선을 사용하지만, 그 사용 방법은 조금 다르다. 즉, 4 개 중의 1개에 신호를 흘리는 것이 아니고, 4 개의 선을 전부사용해 2 진수를 흘린다.(16 가지로 조합가능하다 ). 이렇게 하는 것에 의해, 보다 많은 정보를 보낼 수 있다. 16개 중 4 개는 앞 에서 말한 I/O 공간과 메모리 공간을 위해서 사용한다. 추가로, 설정 어드레스 공간이 2 개를 더 사용한다. 나머지의 10 개는 다른 목적으로 사용할 수 있도록 남겨진다.

어드레스 범위 체크 (ISA에 있어서 I/O 어드레스의 충돌 검사)

ISA 버스의 경우, 같은 어드레스를 사용하는 다른 카드가 없는 지를 체크하기 위한 방법이 각 PnP카드에 구축 되어있다 . 복수의 카드가 같은 I/O 어드레 스를 사용하고 있으면, 어느 쪽의 카드도 바르게 동작하지 않을 것이다. 효과적인 PnP 설정 프로그램은 이러한 충돌이 일어나지 않도록 버스 자원을 할당하지만, 이 경우도 숨어 있는 legacy 카드가 중복되는 어드레스 를 가고 있을지도 모른다.

이 테스트는, 카드가 자신의 I/O 레지스터에 테스트 번호를 설정하는 것에 의해 행해진다. 다음으로 PnP 설정 프로그램은 이것을 읽고, 같은 테스트 번호가 읽는 것을 검사 한다. 이것은 다른 경우에는 무엇인가 문제가 있다. (예를 들면, 다른 카드가 같은 어드레스를 사용하고 있다). 이것은 다른 테스트 번호로 같은 테스트를 반복한다. 이 테스트는 실제로는 카드에 할당된 I/O 어드레스의 범위를 체크 하는 것으로 「범위 체크」라고 불리운다. 이것은 어드레스 충돌 테스트라고 부르는 편이 좋을지도 모른다. 어드레스 충돌이 있으면 사용자에게 에러 메세지가 보내므로, 사용자는 스스로 이것을 해결하지 않으면 안 된다.

메모리를 통한 직접 통신

전통적으로, 대부분의 I/O 디바이스는 CPU 와 통신할 때에 I/O 메모리 만을 사용하였다다. 예를 들면, 시리얼 포트가 이것에 해당 한다. CPU 상에서 동작하고 있는 디바이스 드라이버는, I/O 어드레스 공간과 메인 메모리에 대해 읽기 와 쓰기를 한다. 보다 빠른 방법으로서, 디바이스가 직접 메인 메모리 에 데이터를 쓰는 방법이 있다. 이것을 할수 있느 방법의 하나가, ``DMA 채널" 혹은 bus mastering의 이용이다. 또, 메인 메모리 공간의 일부를 디바이스에 할당하는 방법도 있다. 이와 같이 해서, 디바이스는 일부러 DMA 와 bus mastering을 사용하지 않아도 직접 메인 메모리에 데이터 쓰기를 할 수 있다. 이러한 디바이스는 보통, I/O 어드레스도 사용할 수 있다.

8.2 인터럽트 --상세

인터럽트는 많은 정보를 전달 할 수 있지만, 간접적이다. 인터럽트 신호(배선상의 전압)는, 어떤 디바이스가 처리를 필요 로 하고 있는 것을 인터럽트 콘트롤러라고 불리우는 칩에 전달한다. 그러면 인터럽트 콘트롤러는 CPU에 신호를 보낸다. CPU는 이 디바이스의 드라 이버를 찾아내어, 「인터럽트 서비스 루틴」(또는 「인터럽트 핸들러 」)라고 불리우는 드라이버의 일부분을 실행 한다. 이 「루틴」은 무언가 동작 하는지를 조사하고, 디바이스와의 데이터 전송등의 문제를 처리하려고 한다. 이 프로그램(루틴)에서, 무엇이 일어난지에 대해서 간단하게 조사 할 수 있다. 왜냐하면, 드라이버는 자신이 알고 있는 어드레스 내에, 조사하기 위한 레지스터를 가지고 있기 때문이다.(디바이스의 IRQ 번호와 I/O 어드레스가 바르게 설정되어 있는 경우에는) 이들 레지스터에는 디바이스에 관한 상태 정보가 저장 되어 있다. 드라이버는 이 레지스터의 내용을 읽고, 이것을 조사해서, 무엇이 발생했는가를 찾아 적합한 동작을 한다.

따라서, 각 디바이스 드라이버는 감시하는 인터럽트 번호(IRQ)를 알고 있을 필요가 있다. PCI 버스(또 커넬 2.2 이후에서는 ISA 버스상의 시리얼 포트) 의 경우에는, 복수의 디바이스가 같은 IRQ 번호를 공유하는 것이 가능 하다. 이러한 인터럽트가 발생되면, CPU는 그 인터럽트를 사용하고 있는 모든 디바이스 인터럽트 서비스 루틴을 전부 실행한다. 최초의 서비스 루틴이 먼저 하는 일은, 인터럽트가 정말로 그 디바이스에 대해 실행되는지를 확인하는 것이다. 인터럽트가 없으면(false alarm) 이 루틴은 종료하고, 다음 서비스 루틴을 개시 한다. 이후도 같은 형태이다.

8.3 PCI 의 인터럽트

PCI 의 인터럽트는 ISA의 인터럽트와는 다른 것이지만, 보통은 IRQ에 mapping되기 때문에, 동작은 대부분 같다. 주요한 차이는 PCI 에서는 인터럽트 를 공유할 수 있는 점이다. 이 공유는 자동적으로 행해진다. 따라서, 특별한 하드웨어와 소프트웨어는 필요 없다. 이전에는 인터럽트의 공유가 제대로 동작하지 않다는 보고도 있었지만, 이것은 대부분 디바이스 드라이버 소프트웨어의 문제 이다. PCI 용 디바이스 드라이버는 모든 인터럽트 공유 의 기능을 가지고 있는 것으로 되어있다. 단, 같은 인터럽트를 PCI 버스 와 ISA 버스에서 공유하는 것은 할 수 없는 점에 주의 하시오. 그러나, 인터럽트가 중복되는 디바이스를 동시에 사용하는 것이 없으면, 부적절하게 인터럽트를 공유하고 있어도 가끔 동작할 수 있다. 여기서 「사용한다」라는 것은, 동작하고 있는 프로그램이(C 언어 프로그램의 의미로)디바이스를 오픈하는 것이다.

BIOS의 CMOS를 설정하거나, 낡은 PCI 카드의 점퍼를 설정 하려면, 어쩌면 PCI의 인터럽트 시스템에 대해서 자세한 지식이 필요할 것이다. 각 PCI 카드는 INTA# 로부터 INTD# (A, B, C, D)까지의 4 개의 인터럽트를 사용할 수 있다. 따라서, 슬롯이 7 개있는 시스템에서는 7 x 4 = 28 개의 인터럽트 선을 별개로 가지는 것이 된다.그렇지만, 사양에서는 인터럽트 선의 수는 이것보다 적어도 좋다고 되어 있다 . 또한, 인터럽트는 공유할 수 있으므로, 이것은 그다지 제한하지 않는다. 여기서, 이것들 의 선(배선과 traces)을 W, X, Y, Z 라고 부른다. 또, 슬롯 3 으로부터의 인터럽트 B를 인터럽트 3B라고 한다. 그러면, 선 W 를 사용해 인터럽트 1A, 2B, 3C, 4D, 5A, 6B, 7C를 공유할 수 있다. 공유는, 선 W 를 물 리적으로 1A, 2B 등에 접속하는 것으로서 실현 한다. 같이, 선 X 를 사용해 인터럽트 1B, 2C, 3D, 4A, 5B, 6C, 7D를 공유할 수 있다. 그리고, 시작시에 BIOS가 W, X, Y, Z를 IRQ 에 map 한다. 그 후 BIOS는, 각각 의 디바이스가 map된 IRQ를 각각의 디바이스의 하드웨어 레지스터에 쓴 후에, 디바이스 문의를 하는 모든 것은 디바이스가 사용하는 IRQ 를 알 수 있다.

PCI 사양에서는, 먼저 언급된 배선 W, X, Y, Z 에 INTA#, INTB#, INTC#, INTD# 라는 라벨이 붙어 있다. 그렇지만, 이 정식 기법은 혼동하기 쉽다. 왜냐하면, 슬롯과 PCI 버스의 어느 쪽에 주목하고 있는지에 대한 INTA# 의 의미가 두가지로 바뀌기 때문이다. 예를 들면 3C가 X 에 맵되고 있는 경우, 슬롯 3의 INTC# 가 PCI 버스의 INTA# (X) 에 배선되고 있다고 말하는 것이다. 혼동하기 쉬운 기법이다.

필요 사항은 다른것도 있다. PCI 슬롯에서는, 하위 문자의 인터럽트로부터 사용해야 한다. 따라서, 슬롯이 1개밖에 인터럽트를 사용하지 않는다면, 인터럽트 INTA# 이어야만 한다. 인터럽트를 2 개사용한다면 , INTA# 와 INTB# 이어야 한다. 이후도 같다. 슬롯내의 카드는 디바이스를 8 개까지 가질 수 있지만, PCI 인터럽트의 할당 은 4 개밖에 없다. 인터럽트는 공유할 수 있기 때문에, 이것으로 문제는 없어지고, 8 개 의 디바이스는 각자 인터럽트를 가질 수 있다. 디바이스의 PCI 인터럽트 문자는, 고정값으로서 디바이스에 하드웨어적으로 결선되고 있는 것도 자주 있다.

BIOS 는 ISA 버스에 설정되어 있는 IRQ(인터럽트)와 충돌하지 않도록, PCI 의 IRQ 를 할당한다. CMOS의 BIOS 메뉴에서 사용자가 IRQ를 PCI 버스에 할당하는 것도 가끔 있다. (그러나, 이것이 간단하지 않다는 것은 이미 기술되었다.) IRQ의 mapping를 설정한 후에는, Windows가 PCI 카드 의 IRQ를 모두 0 으로 만들어 버리는 경우도 있다. 따라서, Windows 를 사용하고 있는 사람이 Windows에서 Linux를 시작한 경우, Linux 에서는 IRQ가 0 라는 틀린 결과만을 얻는 경우도 있다.

독자의 여러분은 PCI가 IRQ(ISA 버스)를 사용하고 있기 때문에 늦는 이유를 생각 할지도 모른다. 그렇지만, 그것은 바른것이 아니다. ISA의 인터럽트 제어칩은 CPU 에 직결하고 있는 배선을 가지고 있으므로, 곧바로 CPU 에 신호를 보낼 수 있다. ISA 어드레스와 데이터 버스상의 신호는 PCI 버스 경유로 CPU 에 닿게 되지만, IRQ의 인터럽트 신호는 대부분 직접 CPU 까지 보낸다.

8.4 Isolation

Isolation은 ISA 버스에서만 사용할 수 있다. 이것은 ISA 버스상의 각 PnP 디바이스에 일시적인 핸들(ID 번호또는 카드 선택 번호(Card Select Number, CSN))를 할당하기 위한 복잡한 방법이다. 이것보다도 효율적인 방법 (그러나, 한층 복잡하다)이 있으므로, 그것이 단순한 방법이라고 말해질 수도 있다. Isolation에서는, 감시를 하고 있는 모든 PnP 디바이스에게 PnP 쓰기 대해서, 쓰기 어드레스 1개만이 사용된다. 이 쓰기 어드레스는, 각각의 PnP 디바이스에 고유의 핸들을 보내기 위해(할당한다. ) 사용된다. 이 핸들의 할당은, 핸들이 공통의 어드레스에 보내진(쓰여졌다)때에 디바이스 1개만이 대기하고 있는 것 이 필요하다. 모든 PnP 디바이스는 Isolation의 처리로 사용하는 고유의 시리얼 번호를 가지고 있다 . Isolation의 동작은 게임과 비슷하다. 이것은, 모든 PnP 디바이스가 연결되어 있는 오직 1개의 공통 버스 배선과 Isolation 프로그램이 가지고 있는 값을 동등한 것으로 수행한다.

「게임」 최초의 라운드에서는, 모든 PnP 디바이스는 이 선을 감시하고, 여기로 비트열을 동시에 보낸다. 허용되는 비트값은 1 (positive voltage)또는 전압 없음의 "open 0" (open circuit or tri-state)의 어느 것이다. 계속해서, 각각 의 PnP 디바이스는 이 선으로 시리얼 번호를 비트마다 상위 비트로부터 전송을 시작한다. 어떤 디바이스가 1를 보내면, 접속되어 있는 다른 디바이스는 모두 1을 받는다. 모든 디바이스가 "open 0" 을 보내면, 접속 되어있는 디바이스는 아무것도 받지 않는다. 이 목적은, (최초의 라운드가 종료될때 까지)가장 높은 시리얼 번호를 가지는 것 이외의 것을 제거하는 것이다. 「제거한다」라는 것은, 이 디바이스는 쓰기 어드레스의 감시를 그만두지만, 게임에 이겨 남아 있는 모든 디바이스는 이 어드레스의 감시를 계속한다는 것이다. 이것은 "dropping out" 라고도 말한다. (시리얼 번호의 길이는 모든 같다는 점에 주의해 주시오. )

먼저, 아직 핸들을 받고 있지 않은 디바이스 모두가 처음으로 배선에 놓인 시리얼번호의 가장 상위 비트에 대해서만 생각 보자. 어떤 PnP 디바이스가 0 (open 0)를 보냈는데 1 을 받은 경우, 이것은 다른 PnP 디바이스가 보다 높은 시리얼 번호를 가지고 있다는 것이다. 즉, 이 디바이스는 이 라운드로부터 일시적으로 탈락하고, 이 라운드가 끝날 때까지는 비트열을 읽을 수 없게 된다. (라운드가 끝난 시점에서 승자, 즉 가장 큰 시리얼 번호를 가지고 있는 디바이스에 핸들이 할당되어진다.) 이 때, 게임에 남아 있는 디바이스는 모두 같은 선두 비트(1)을 가지고 있다. 그런데, 이 라운드의 연속되는 자리수를 제거하고 요구한 "stripped serial number" 만을 생각하면 좋을 것이다. 그 후에는 이 단락 의 선두로 돌아오고, 시리얼 번호 전체를 조사할 때까지 반복한다(모든 것이 0 의 경우에 대해서는 아래를 참조해 주시오).

가장 높은 시리얼 번호가 게임으로부터 제거되지 않는 것은 분명하다. 그러나, (손상된 것도 포함해)시리얼 번호의 선두의 자리수가 모두 0 이었던 경우 는 어떻게 될 것인가 ? 이 경우에는 「open 0」이 배선에 보내지고, 모든 디바이스는 게임에 참가했던 그대로 된다. 모든 디바이스의 선두의 자리수가 0 이라면 무승부가 되고, 앞의 단락에서 1을 제거한 것과 같게 0를 제거한다. 그리고 게임은 계속되고, (시리얼 번호의)다음 자리수가 보내진다.

라운드가 끝나면(참가 디바이스가 남아 있는 시리얼 번호의 하위 비트를 계속 보낸 후에 ), 가장 높은 시리얼 번호를 가진 PnP 디바이스가 1개 만 남는다. 이 디바이스에는 핸들이 할당되어지고, 그 이후는 게임 에 참가할 수 없다. 그리고, 전의 라운드 도중에서 탈락한(아직 핸들을 할당되어지지 않은)모든 디바이스는 게임에 다시 참가하고, 1개 적은 디바이스의 참가로 새로운 라운드를 시작한다. 이와 같이 해 모든 PnP 디바이스에 핸들을 할당한다. 이 알고리즘이 바르게 동작하는 것 은 간단하게 증명할 수 있다.

한 번 할당되어진 핸들은 각 PnP 디바이스를 가리키기 위해서 사용되고, PnP 와 의 디바이스 설정 정보의 교환에 사용된다. 이 핸들은 PnP 설정 으로만 사용하는 것이고, PnP 디바이스와의 통상적인 통신에는 사용되지 않는 점에 주의 하시오. 컴퓨터 시작시에는 핸들은 모두 상실되므로, PC를 시작할 때에 PnP BIOS는 isolation 처리를 한다.

이상


다음 이전 차례