Сетевые драйверы
Семёнов Ю.А. (ГНЦ ИТЭФ), book.itep.ru
Читатели, знакомые с телекоммуникационными протоколами, могут заинтересоваться тем, как писать прикладные программы для работы с пакетами. Прикладная программа взаимодействует с драйвером сетевого интерфейса. Ethernet-интерфейс, как и всякий другой, содержит несколько статусных управляющих регистров (CSR) и один или несколько регистров данных. Запись (чтение) в эти регистры выполняется в IBM/PC с помощью команд IN (OUT). Каждому регистру ставится в соответствие определенный номер порта. Блок номеров портов задается с помощью переключателей на интерфейсе или в процессе постановки пакетного драйвера. В последнем случае в AUTOEXEC-файле должна присутствовать строка, например (для DOS):
NE2000 0x60 0x5 0x300, (если ваша ЭВМ снабжена интерфейсом типа NE2000).
Здесь предполагается, что интерфейс будет использовать номер прерывания 0x60, аппаратное прерывание 0x5 и блок портов, начиная с шестнадцатеричного адреса 0x300 (io_addr). Следует иметь в виду, что разные интерфейсы могут иметь разное число CSR-регистров и отличные от приведенных ниже функции (NE2100). Интерфейс характеризуется тремя целыми числами: класс (8 бит), тип (16 бит) и номер. Класс говорит о том, для какой из сетевых сред предназначен данный прибор (PPP, DIX Ethernet, IEEE 802.3, IEEE 802.5, Pronet-10, Appletalk и т.д.). Тип описывает конкретную реализацию интерфейса (NE2000, NI5210, 3C501 и т.д.). Тип 0xffff соответствует всем интерфейсам данного класса. В случае, когда ЭВМ оснащена более чем одним интерфейсом идентичного типа, для их идентификации используется номер. На рис. 7.2.1 показана структура управляющего (CSR) регистра сетевого интерфейса. В таблице 7.2.1 приведен перечень основных классов с примерами определенных типов интерфейсов.
Рис. 7.2.1.А Структура CSR-регистра интерфейса (CSR0)
Init | инициализация (initialize); |
Strt | старт; |
Stop | стоп; |
Tdnd | запрос передачи (transmit demand); |
Txon | включение передачи; |
Rxon | включение приема; |
Inea | разрешение прерываний (interrupt enable); |
Intr | прерывание; |
Idon | инициализация выполнена (стирание записью 1); |
Tint | прерывание при передаче (стирание записью 1); |
Rint | прерывание при чтении (стирание записью 1); |
Merr | ошибка при тайм-ауте на шине (стирание записью 1); |
Miss | нет буфера для приема (стирание записью 1); |
Cerr | ошибка из-за столкновения (стирание записью 1); |
Labl | тайм-аут при передаче (стирание записью 1); |
Err | ошибка типа Babl, Cerr, Miss, Merr (только для чтения). |
CSR1 (доступ разрешен при CSR0[stop] = 1)
Рис. 7.2.1.Б. CSR1
CSR2 (доступ разрешен при CSR0[stop] = 1)
Рис. 7.2.1В. CSR2
Bcon | 0 = <0:7> перестановка байтов адресов |
Acon | 0 = ale, 1 = /as |
Bswp | 0 = /bm1, bm0, /hold; |
csr3 (доступ разрешен при CSR0[stop] = 1)
Рис. 7.2.1.Г. CSR3
Таблица 7.2.1.
Сетевая среда | Класс | Фирма, интерфейс | Тип интерфейса |
dec/intel/Xerox | 1 | 3com 3C500/3C501 | 1 |
"Bluebook" ethernet | 3com 3C505 | 2 | |
Interlan NI5010 | 3 | ||
Micom-Interlan NP600 | 6 | ||
Ungermann-bass PC-nic | 8 | ||
Univation NC-516 | 9 | ||
TRW PC-2000 | 10 | ||
Interlan NI5210 | 11 | ||
3com 3C503 | 12 | ||
3com 3C523 | 13 | ||
Western digital WD8003 | 14 | ||
Spider systems S4 | 15 | ||
Torus frame level | 16 | ||
10net communications | 17 | ||
Gateway PC-bus | 18 | ||
Gateway at-bus | 19 | ||
Gateway MCA-bus | 20 | ||
IMC PCnic | 21 | ||
1 | IMC PCnic II | 22 | |
Micromatic research | 25 | ||
Clarkson "multiplexor" | 26 | ||
D-link 16-bit | 28 | ||
D-link ps/2 | 29 | ||
Research machines 16 | 31 | ||
Research machines MCA | 32 | ||
Interlan NI9210 | 34 | ||
Interlan NI6510 | 35 | ||
Novell NE2000 | 36 | ||
Allied telesis pc/xt/at | 38 | ||
Allied telesis NEC PC-98 | 39 | ||
Ungermann-bass NIC/PS2 | 41 | ||
Tiara lancard/E AT | 42 | ||
Tiara Lancard/E MC | 43 | ||
Tiara Lancard/E TP | 44 | ||
AT&T Starlan NAU | 47 | ||
AT&T Starlan-10 NAU | 48 | ||
AT&T Ethernet NAU | 49 | ||
Pronet-10 | 2 | Proteon P1300 | 1 |
Proteon P1800 | 2 | ||
IEEE 802.5/pronet-4 IBM Token Ring интерфейс | 3 | Proteon P1340 | 2 |
Proteon P1344 | 3 | ||
Gateway PC-bus | 4 | ||
Gateway AT-bus | 5 | ||
Gateway MCA-bus | 6 | ||
Omninet | 4 | ||
Appletalk | 5 | ||
Последовательный интерфейс | 6 | Clarkson 8250-slip | 1 |
Clarkson "multiplexor" | 2 | ||
Starlan | 7 | ||
Arcnet | 8 | Datapoint RIM | 1 |
AX.25 | 9 | ||
KISS | 10 | ||
IEEE 802.3 w/802.2 HDRS | 11 | ||
FDDI W/802.2 HDRS | 12 | ||
Internet X.25 | 13 | Western Digital | 1 |
N.T. Lanstar (encap. dix) | 14 | NT Lanstar/8 | 1 |
NT Lanstar/mc | 2 | ||
SLFP | 15 | ||
Netrom | 16 | ||
Nclass | 17 |
EADDR_LEN | equ 6 | ; длина физического адреса | |
init_block | struc | ||
init_mode | dw | 0 | |
init_addr | db | eaddr_len dup(?) | ; ethernet-адрес |
init_filter | db | 8 dup(0) | ; Логический адресный фильтр (multicast filter). |
init_receive | dw | ?,? | ; Указатель входного кольцевого буфера |
init_transmit | dw | ?,? | ; Указатель выходного кольцевого буфера. |
init_block | ends |
Структура переменных init_mode (смещение = 0) имеет вид
Рис. 7.2.2. Структура переменных init_mode
Drx | запрет приема; |
Dtx | запрет передачи; |
Loop | цикл; |
Dtcr | запрет передачи crc; |
Coll | столкновение; |
Drty | запрет повторов; |
Intl | внутренний цикл; |
Prom | режим приема всех пакетов (promiscuous mode). |
rcv_msg_dscp | struc | |
rd_addr | dw ? | ; Младшая часть адреса входного буфера |
rd_stat | dw ? | ; Статусная часть + старшая часть адреса |
rd_bcnt | dw ? | ; Размер буфера в байтах |
rd_mcnt | dw ? | ; Длина сообщения в байтах |
rcv_msg_dscp | ends |
Рис. 7.2.3. Структура переменных rd_stat
Enp | конец пакета; |
Stp | начало пакета; |
Buff | ошибка в буфере; |
CRC | CRC-ошибка; |
Oflo | переполнение буфера; |
Fram | ошибка при записи в буфер; |
Err | наличие ошибки; |
Own | 0 = полное заполнение. |
Я не буду описывать здесь то, как следует писать системные драйверы (Исчерпывающую информацию по написанию таких драйверов читатель может найти в книге "Написание драйверов для MS-DOS" Р.Лея и "Уэйт Груп", Москва "Мир", 1995), тем более что существует достаточное их количество в депозитариях общего доступа (Например, анонимное FTP по адресам ftp.funet.fi, ftp.switch.ch или oak.oakland.edu, депозитарий SimTel ). Приведенное выше описание регистров интерфейса не является единственно возможным (см. также руководство по сетевому контроллеру 8390 и файл NE2.ASM из ссылки ftp.funet.fi. Структура драйверов варьируется для разных операционных систем. Для системных программистов полезно иметь возможность настраивать драйвер или непосредственно интерфейс на определенный режим, например, на прием всех пакетов, проходящих по кабельному сегменту. Последнее может представлять интерес в диагностических целях, так как вслед за пакетным драйвером загружается Etherdrv, Winsock или winpkt и т.д., блокирующие режим приема всех пакетов (mode=6). Ниже приведен пример описания основных параметров драйвера:
BLUEBOOK | equ | 1 | |
IEEE8023 | equ | 11 | |
ADDR_LEN | equ | 6 | ; размер Ethernet-адреса |
MAX_M_CAST | equ | 8 | ; максимальное число мультикаст-адресов. |
Public | int_no, | io_addr | |
int_no | db | 2,0,0,0 | ; должно иметь 4 байта для get_number. |
io_addr | dw | 0300h,0 | ; I/O адрес карты (переключатели) |
public | driver_class | driver_type, | driver_name, | driver_function, | parameter_list | ||
driver_class | db | BLUEBOOK, IEEE8023, 0 | ; из спецификации интерфейса | ||||
driver_type | dw | 54 | ; из спецификации интерфейса | ||||
driver_name | db | 'NE2000',0 | ; имя драйвера. | ||||
driver_function | db | 2 | |||||
parameter_list | label | byte | |||||
db | 1 | ; | |||||
db | 9 | ; | |||||
db | 14 | ; длина списка параметров в байтах | |||||
db | ADDR_LEN | ; длина адреса MAC-уровня в байтах | |||||
dw | GIANT | ; MTU, включая MAC-заголовок | |||||
dw | MAX_M_CAST * ADDR_LEN |
dw | 0 | ;(# принимаемых подряд пакетов с; размером MTU) - 1 | |
dw | 0 | ; (# посылаемых подряд пакетов) - 1 | |
int_num | dw | 0 | ; Номер прерывания |
Существует множество пакетных драйверов. Можно обнаружить несколько модификаций для одного и того же типа интерфейса. Эти драйверы могут быть ориентированы на работу в разных программных средах (Novell, UNIX, MS-DOS и т.д.) и иметь разные возможности. Для MS-DOS сложился неофициальный стандарт, который позволяет использовать драйвер для самых разных приложений. Драйвер может использовать минимум возможностей интерфейса (базовый уровень), реализовать более широкий набор функций (мультикастинг, сбор статистики и т.д.) или поддерживать практически все, на что способен данный прибор. В последнем случае он занимает больше места в памяти. Описания операций с пакетными драйверами, приведенные ниже, выполнены в нотации ассемблера IBM/PC. При написании программы следует помнить, что порядок байтов в Ethernet противоположен тому, который используется в вашей IBM/PC.
Пакетные драйверы используют программные прерывания в интервале 0x60 - 0x80. Следует сразу заметить, что не все прерывания из этого списка свободны и при конфигурировании системы следует проявлять осмотрительность. Для того чтобы избежать конфликтов с другими внешними устройствами, предусматривается возможность реконфигурации прерываний.
Предполагается, что программа обработки прерываний начинается с команды безусловной передачи управления (JMP), за которой следует текстовая строка "PKT DRVR". Именно эта строка служит указателем при поиске адреса пакетного прерывания. Практически все драйверы могут работать с различными протоколами (TCP/IP, OSI и др.). Решить задачу мультиплексирования на связном уровне помогает процедура access_type, которая обеспечивает доступ для пакетов определенного типа.
Все функции реализуются с помощью обращения к драйверу с набором определенных параметров. При этом значение регистра AH определяет тип запроса. Каждому типу используемого сетевого протокола, с которым работает интерфейс, ставится в соответствие целочисленный указатель (handle), получаемый с помощью процедуры access_type. Выполнимость драйвером тех или иных операций может быть выяснена с помощью запроса driver_info.
При работе с драйвером следует проявлять осторожность и спасать нужные вам регистры. Следует также помнить, что порядок байтов в PC и в некоторых сетях, включая Ethernet, не совпадает. Описание основных запросов, посылаемых пакетному драйверу: