Linux драйвера сетевых карт для

🏷 Как найти имя и версию драйвера сетевой карты в Linux

Вопрос: Сетевая карта Ethernet подключена к моей Linux-системе, и я хотел бы узнать, какой драйвер сетевого адаптера установлен для оборудования NIC. Есть ли способ узнать имя и версию драйвера сетевой карты для моей сетевой карты?

Для правильной работы аппаратного обеспечения сетевой интерфейсной платы (NIC) необходим соответствующий драйвер устройства для аппаратного обеспечения NIC.

Драйвер устройства NIC реализует аппаратно-независимый общий интерфейс между ядром Linux и NIC, так что пакеты могут перемещаться между ядром и NIC.

Хотя некоторые драйверы могут быть статически встроены в ядро, большинство драйверов для современных сетевых адаптеров динамически загружаются как модули ядра.

Когда вы устраняете неполадки аппаратного обеспечения сетевого адаптера, вы можете проверить, правильно ли установлен драйвер сетевого адаптера.

В этом случае вам нужно знать, какой модуль ядра является вашим драйвером NIC.

Способ первый

Первый способ заключается в проверке сообщений dmesg.

Поскольку ядро загружает необходимые аппаратные драйверы во время загрузки, вывод dmesg должен сообщить, установлен ли драйвер карты Ethernet.

Приведенный выше вывод показывает, что драйвер с именем r8169 загружен в ядро.

Если вы хотите узнать более подробно об этом драйвере (например, о версии драйвера), вы можете использовать команду modinfo.

Источник

Установка драйвера сетевой карты Debian

Доброго времени суток! Решил поставить Debian 7. В процессе установки потребовались драйвера для сетевой карты, так как под рукой не было, то пропустил. Материнская плата: foxconn h67a-s После в консоли ввожу

Последние строки dmesg-а

Драйвер качал с оф сайта realtec, по поиску r8169 Прошу помощи.

А подробнее можно? Что ты там качал?

З.Ы. А что, готового уже модуля ядерного нет такого чтоль? Зачем качать откуда-то?

лучше использовать ядреный драйвер, это раз.

Нужно установить пакет с прошивками для карт от realtek, это два.

По умолчанию в Debian нет прошивок. Подключите.

lspci |grep -i net 03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 06)

всё работает, не надо вот тут.

Верни назад aptitude install firmware-realtek

И просто в /etc/network/interfaces пропиши

Прочитал, что лучше установить драйвер вручную.

Нагло врут. Твоя проблема решается не сменой драйвера, а

верни наместо ядерный модуль и:
apt-get install firmware-realtek

Там, где скачивал образы, есть каталог non-free, в котором есть образ с включёнными прошивками.

Т.е помимо основного образа с системой надо всегда еще выкачивать образ с прошивками?из non-free ветки? и как вернуть ядерный модуль? этот rmmod-ом удалить, а старый вернуть как?

А где почитать про это? Я читал много статей по установке debian, но ничего подобного не нашел. Где вы находите эту информацию?!)

Т.е помимо основного образа с системой надо всегда еще выкачивать образ с прошивками?из non-free ветки?

Просто ставьте систему с образа, в котором содержатся non-free компоненты, в том числе и прошивки.

Переустновить пакет с ядром.

Ну и просто надо знать, что в стандартной поставке Debian (установочных образах) нет прошивок.

я просто качал с оф сайта debian dvd-amd64, там я не заметил нигде разные виды образов,как мне найти нужный?

Пакет с ядром, это мне надо переустановить kernel-package? Простым apt-get?

Еще же можно скачать пакет firmware-realtek и поставить dpkg -i его, вручную, да?

я просто качал с оф сайта debian dvd-amd64, там я не заметил нигде разные виды образов,как мне найти нужный?

Читаем внимательно вот этот текст: и скачиваем предложенные образы net-install, включающие в себя несвободные прошивки, при установке с такого образа не забываем в списке пакетов выбрать пакет с прошивками под ваше оборудование.

Пакет с ядром, это мне надо переустановить kernel-package? Простым apt-get?

Еще же можно скачать пакет firmware-realtek и поставить dpkg -i его, вручную, да?

Сделал все как вы сказали.Не помогло. Для сравнения скачал non-free netinstall образ, поставил с него — результат тот же.

Смотреть вывод dmesg на предмет сообщений от драйвер r8169 на примере тех, что вы привели в шапке темы.

Тут проблема не в модуле, а в прошивке, Debian по умолчанию не содержит в себе никаких несвободных прошивок и ПО, решается установкой пакета firmware-realtek.

Вот логи Сразу после загрузки системы

Попробуйте принудительно запустить dhcp клиент:

И проверьте получает или нет интерфейс параметры сети.

В общем итог. Пробовал все, что написано. Ничего не помогало, тогда взял и напрямую соединил два компьютера, на одном задал адрес 192.168.0.1, на другом(проблемном) 192.168.0.2 с маской /24, т.е решил проверить работает ли вообще железо, со статикой. О чудо, все заработало!(пинг прошел) Тогда я взял и соединился с сетью провайдера не через свитч, и все сработало! Оказывается был виноват свитч. Пробовал тогда в разные порты свитча втыкать, снова не работало ничего, на второй системе(win7) все работало и со свитчем. Другой комп с дебианом тоже через свитч нормально работает. Магия.

Возможно стоит обновить ядро в Debian или использовать другой DHCP клиент. У меня при использовании классического ISC DHCP Client`а в сети провайдера не параметры сети не получаются, поэтому я использую dhcp клиент из состава busybox.

Есть еще вероятность, что у тебя в биосе не включены какие-нибудь настройки. Я так-же парился с Ethernet на маме GA-970-UD3p (такой-же адаптер). Смотрю в сислог, а там чехорда. Флешку включаешь, езернет валится. Мышь, то работает, то — нет. На чипсет матершина какая-то. Я сделал вывод, что ядро отстает от производителей железа. И начал искать дрова от AMD и прочих для линукс. Наткнулся на статью про IOMMO controller. Зашел в биос поставил Enableb на нем и еще EHCI Hand-off и Port 60/64 Emulation, И, ооо, чууудо. Пошел пинг. Раздался IP.

Читайте также:  Windows root system32 ntoskrnl exe что это такое

Ты хоть дату создания темы (12.02.2014) или последнего коментария (14.02.2014) смотрел? Рано ты отписался, пожождал бы хотя бы до 12 февраля, было бы как раз два года с даты создания, можно было бы праздник устроить. А так, эх .

Источник

Пишем драйвер сетевого устройства для Linux

Введение

Настоящая статья была написана для тех, кто только начинает изучение ядра Linux и хочет знать о драйверах сетевых устройств. Предполагается, что читатель в должной мере знаком с языком C и средой Linux.

В настоящей статье описывается сетевой драйвер для сетевой платы RealTek 8139. Я выбрал чипсет RealTek по следующим двум причинам: Во-первых, компания RealTek бесплатно предоставляет технические спецификации на этот чипсет (спасибо, RealTek!). Во-вторых, он сравнительно дешев. В Индии его можно приобрести менее, чем за 300 рупий (приблизительно 7 долларов США).

Драйвер, представленный в статье, имеет минимум функций; он просто посылает и принимает пакеты и собирает некоторую статистику. Для ознакомления с полноценным драйвером, написанном на профессиональном уровне, пожалуйста, смотрите исходные тексты Linux.

Подготовка к разработке драйвера

Прежде, чем начать разработку драйвера, нам нужно для этого подготовить систему. Настоящая статья была написана и проверена для ядра Linux 2.4.18, в котором содержится исходный код драйвера чипсета RealTek8139. Может быть в ядре, с которым Вы работаете, драйвер включен в состав ядра, либо скомпилирован как модуль. Для того, чтобы избавиться от каких-либо сюрпризов, желательно собрать ядро, в котором не будет драйвера RealTek8139 ни в каком из вариантов. Если Вы не знаете, как откомпилировать ядро, я рекомендую обратиться по следующей ссылке.

С этого момента обсуждения предполагается, что у вас есть рабочее ядро, в котором нет драйвера RealTek8139. Вам также нужны технические спецификации на чипсет, которые Вы можете загрузить с http://www.realtek.com.tw/ . Последнее, что вам нужно сделать при подготовке, это – правильно вставить сетевую плату в PCI разъем и теперь мы готовы идти дальше.

Настоятельно рекомендуется иметь книгу Rubini Linux Device Drivers в качестве справочника по API. В настоящий момент это лучший известный мне источник сведений для разработки драйверов устройств под Linux.

Начинаем разработку драйвера

Рассмотрим разработку драйвера поэтапно по следующим пунктам:

  1. Обнаружение устройства
  2. Включение устройства
  3. Что такое сетевые устройства
  4. Доступ к устройству не через шину
  5. Что такое конфигурационное адресное пространство PCI
  6. Инициализация net_device
  7. Какой механизм передачи используется в RealTek8139
  8. Какой механизм приема используется в RealTek8139
  9. Делаем устройство готовым к передаче пакетов
  10. Делаем устройство готовым к приему пакетов

Обнаружение устройства

Каждый разработчик имеет уникальный, назначенный только ему идентификатор ID и назначает уникальный идентификатор ID каждому конкретному виду устройств. Макросы REALTEK_VENDER_ID и REALTEK_DEVICE_ID определяют эти идентификаторы ID. Вы можете найти эти значения в «PCI Configuration Space Table» в спецификациях RealTek8139.

Включение устройства

Давайте на время приостановим процесс изучения кода драйвера; вместо этого мы рассмотрим несколько важных тем, чтобы понять, чем с точки зрения Linux является сетевое устройство. Мы рассмотрим сетевые устройства и разницу между вводом-выводом с отображением в память (memory-mapped I/O), вводом-выводом с отображением по портам (port-mapped I/O) и конфигурационным адресным пространством PCI (PCI configuration space).

Что такое сетевые устройства

Хотя полей в этой структуре значительно больше, для нашего минимального драйвера вполне достаточно перечисленных. Рассмотрим их подробнее:

  • name – имя устройства. Если первый символ устройства равен null, то register_netdev назначает ему имя «ethn», где n – подходящий номер, Например, если в вашей системе уже есть eth0 и eth1, то ваше устройство будет поименовано как eth2.
  • base_addr – базовый адрес ввода/вывода. Мы обсудим адресацию ввода/вывода далее в настоящей статье.
  • addr_len – длина адреса платы (MAC адреса). Для Ethernet-интерфейсов она равна 6.
  • dev_addr – адрес платы (Ethernet-адрес или MAC-адрес).
  • broadcast – аппаратный адрес широковещательной передачи. Для Ethernet-интерфейсов – это FF:FF:FF:FF:FF:FF.
  • hard_header_len — «hardware header length» – количество восьмеричных символов, которые предваряют передаваемый пакет и идут перед заголовком IP или другой информацией протокола. Для Ethernet-интерфейсов длина hard_header_len равна 14.
  • irq – номер назначенного прерывания.
  • open – указатель на функцию, которая открывает устройство. Эта функция вызывается всякий раз, когда ifconfig активирует устройство (например, «ifconfig eth0 up»). Метод open должен регистрировать все необходимые системные ресурсы (порты ввода/вывода, IRQ, DMA и т.п.), включать устройство и увеличивать на единицу счетчик использования модуля.
  • stop – указатель на функцию, которая останавливает интерфейс. Эта функция вызывается всякий раз, когда ifconfig деактивирует устройство (например, «ifconfig eth0 down»). Метод stop освобождает все ресурсы, запрошенные функцией open.
  • hard_start_xmit – с помощью этой функции заданный пакет передается в сеть. Первым аргументом функции является указатель на структуру sk_buff. Структура sk_buff используется для хранения пакетов в сетевых стеках Linux. Хотя в этой статье не требуется детальное знание структуры sk_buff’s, подробности можно найти по ссылке http://www.tldp.org/LDP/khg/HyperNews/get/net/net-intro.html .
  • get_stats – эта функция предоставляет статистику интерфейса. В выходных данных команды «ifconfig eth0» большая часть полей содержит данные из get_stats.
  • priv – приватные данные драйвера. Это личное поле драйвера и он может использовать его по своему усмотрению. Далее мы увидим, как наш драйвер будет использовать это поле для хранения данных, относящихся к PCI устройствам.

Хотя мы не упомянули все поля структуры net_device, пожалуйста, обратите внимание на то, что нет никаких ссылок на функцию, принимающую пакеты. Это делается обработчиком прерываний устройства, что мы также рассмотрим далее в настоящей статье.

Доступ к устройству не через шину

Замечание: Этот раздел был взят из книги Алана Кокса (Alan Cox) «Bus-Independent Device Accesses», которая доступна по ссылке http://tali.admingilde.org/linux-docbook/deviceiobook.pdf

Ввод-вывод с отображением в память (Memory-Mapped I/O)

Наиболее широко используемый способ ввода/вывода – ввод/вывод с отображением в память (memory-mapped I/O). Т.е. часть адресного пространства CPU интерпретируется не как адреса памяти, а используется для доступа к устройству. В некоторых системах с определенной архитектурой требуется, чтобы устройства имели фиксированные адреса, но в большинстве систем имеется некоторый способ обнаружения устройств. Хорошим примером такой схемы является обход шины PCI. В настоящей статье не рассматривается, как получить такой адрес, но предполагается, что изначально он у вас есть.

Физический адрес является беззнаковым числом типа long. Эти адреса не используются напрямую. Вместо этого для того, чтобы получить адрес, который можно было передать в функцию так, как это описано ниже, вам следует вызвать ioremap. В ответ Вы получите адрес, который можно использовать для доступа к устройству.

Читайте также:  Виджет для рабочего стола windows 10 записки

После того, как Вы закончите использовать устройство (скажем, в вашей подпрограмме выхода из модуля), вызовите iounmap для того, чтобы вернуть ядру адресное пространство. Архитектура большинства систем позволяет выделять новое адресное пространство каждый раз, когда Вы вызываете ioremap, и использовать его до тех пор, пока Вы не вызовете iounmap.

Доступ к устройству

Часть интерфейса, наиболее используемая драйверами, это чтение из регистров устройства, отображаемых в память, и запись в них. Linux предоставляет интерфейс для чтения и записи блоков размером 8, 16, 32 или 64 бита. Исторически сложилось так, что они называются доступом к байту (byte), к слову (word), к длинному числу (long) и к двойному слову или четверке слов (quad). Названия функций следующие — readb, readw, readl, readq, writeb, writew, writel и writeq.

Для некоторых устройств (работающих, например, с буферами кадров) было бы удобнее за один раз передавать блоки, значительно большие чем 8 байтов. Для этих устройств предлагается использовать функции memcpy_toio, memcpy_fromio и memset_io. Не используйте memset или memcpy для работы с адресами ввода/вывода; они не гарантируют копирование данных в правильном порядке.

Работа функций чтения и записи должна происходить в определенном порядке. Т.е. компилятору не разрешается выполнять переупорядочивание последовательностей ввода-вывода. Если компилятору разрешается оптимизировать порядок, то Вы можете использовать функцию __readb и ей подобные с тем, чтобы не требовать строгого сохранения порядка выполнения операций. Пользуйтесь этим с осторожностью. Операция rmb блокирует чтение памяти. Операция wmb блокирует запись в память.

Хотя, по определению, основные функции синхронны относительно друг друга, устройства, которые установлены в шинах, сами по себе асинхронны. В частности многим авторам драйверов неудобно, что запись в PCI шину осуществляется асинхронно. Они должны выполнить операцию чтения из устройства с тем, чтобы удостовериться, что запись была сделана так, как хотел автор. Эта особенность скрыта от авторов драйверов в API.

Доступ к пространству портов

Еще один широко применяемый вариант ввода-вывода, это — пространство портов. Это диапазон адресов, отличающихся от адресного пространства обычной памяти. Доступ к этим адресам обычно не столь быстр, поскольку эти адреса отображаются в адреса памяти, к тому же пространство портов потенциально меньше адресного пространства.

В отличие от ввода-вывода с отображением в память, для доступа к пространству портов подготовка не требуется.

Доступ к пространству портов или устройства с отображением ввода-вывода

Доступ к этому пространству обеспечивается с помощью набора функций, в которых допускается доступ к 8, 16 и 32 битам, известных как байт (byte), слово (word ) и длинное слово (long). Это следующие функции — inb, inw, inl, outb, outw и outl.

Эти функции имеют несколько вариантов. Для некоторых устройств требуется, чтобы доступ к их портам происходил со сниженной скоростью. Эта функциональность обеспечивается при помощи добавления _p в конце команды. Имеются также эквиваленты команды memcpy. Функции ins и out копируют байты, слова и длинные слова в заданный порт и из него.

Что такое конфигурационноеадресное пространство PCI (PCI Configuration Space)

В этом разделе мы рассмотрим конфигурационное адресное пространство PCI. Устройства PCI имеют 256 байтное адресное пространство. Первые 64 байта используются стандартным образом, тогда как использование оставшихся байтов зависит от устройства. На рис.1. показано стандартное конфигурационное адресное пространство PCI

(Прим. пер.: В оригинале статьи Рис. 1 пропущен. Краткое описание конфигурационного адресного пространства PCI на русском языке можно найти в Википедии http://ru.wikipedia.org/wiki/PCI_configuration_space . Недостающий рисунок был взят по ссылке http://en.wikipedia.org/wiki/File:Pci-config-space.svg .)

Рис.1: Конфигурационное адресное пространство

Поля «Vendor ID» и «Device ID» содержат уникальные идентификаторы, присвоенные разработчику устройств и устройству соответственно. Мы уже обсуждали их в разделе «Обнаружение устройства». Отметим еще поле — «Base Address Registers» (базовые адресные регистры), известное еще как BAR. Мы кратко расскажем, как использовать регистры BAR.

Инициализация net_device

Таблица 4: Структура rtl8139_private

Таблица 5: Инициализация net_device

Теперь давайте объясним, что мы сделали в таблице 5. Функцию probe_for_realtek8139 мы уже рассматривали. Функция rtl8139_init распределяет память для локального указателя rtl8139_dev, который мы должны использовать как net_device. Вдобавок эта функция заполняет компоненту pci_dev of rtl8139_private для обнаруженного устройства.

Наша следующая цель – получить поле base_addr для net_device. Это начало памяти регистров устройства. Мы напишем драйвер только для ввода-вывода с отображением в память. Чтобы получить базовый адрес для ввода-вывода с отображением в память, мы используем PCI API такие как pci_resource_start, pci_resource_end, pci_resource_len, pci_resource_flags и т.п. Эти API позволяют нам читать конфигурационное пространство PCI, не зная о деталях его реализации. Второй аргумент в этих API – номер BAR. Если Вы видели спецификации RealTek8139, то знаете, что первый BAR (нумеруемый как 0) — I/OAR, тогда как второй BAR (нумеруемый как 1) — MEMAR. Поскольку в этом драйвере используется ввод-вывод с отбражением в память, то в качестве второго аргумента мы передаем 1. Прежде, чем получить доступ к адресам, возвращаемыми указанными выше API, мы должны сделать две вещи. Во-первых, зарезервировать в драйвере указанные выше ресурсы (пространство памяти); это делается с помощью вызова функции pci_request_regions. Во-вторых, отобразить адреса ввода-вывода, описанные в этом разделе ранее, так, чтобы они использовались при вводе-выводе с отображением в память. Адрес io_addr назначается компоненте base_addr в структуре net_device, и это то место, откуда мы можем начинать читать регистры устройства или писать в них.

В оставшейся части кода, приведенного в таблице 5, выполняется обычная инициализация структуры net_device. Заметьте, что теперь мы читаем аппаратный адрес из устройства и записываем его в dev_addr. Если Вы смотрели раздел «Описания регистров» в спецификации RealTek8139, то знаете, что первые 6 байтов являются аппаратным адресом устройства. Также мы должны иметь проинициализированные компоненты указателя на функцию, но не должны определять какую-либо соответствующую функцию. Теперь для компиляции модуля мы добавим фиктивные функции.

Таблица 6: Фиктивные функции

Обратите внимание, что в init_module пропущена часть, обрабатывающая ошибки. Вы можете написать эту обработку, заглянув для этого в модуль cleanup_module, приведенный ниже:

Таблица 7: Функция cleanup_module

Теперь мы имеем готовый фиктивный драйвер или драйвер-шаблон. Откомпилируйте модуль и вставьте его в ядро так, как показано в таблице 8 (предполагается, что исходный код ядра — /usr/src/linux-2.4.18 ).

Таблица 8: Компиляция драйвера

Теперь выполним последовательность команд «ifconfig», «ifconfig — a», «ifconfig rtl8139 up», «ifconfig» и «ifconfig rtl8139 down» и посмотрим на результат. Эти команды покажут, когда каждая функция вызывается. Если все в порядке, то когда вы выполняете команду «ifconfig — a», вы должны обнаружить устройство rtl8139 и должны получить сообщение «function rtl8139_get_stat called «. Когда выполняете команду «ifconfig rtl8139 up», Вы должны получить сообщение «function rtl8139_open called». Аналогичным образом, когда Вы выполняете команду «ifconfig rtl8139 down», Вы должны получить сообщение «function rtl8139_stop called».

Читайте также:  Astra linux windows server

Снова остановим разработку драйвера и попытаемся лучше понять, какой механизм передачи и приема данных используется в устройстве.

Какой механизм передачи используется в RealTek 8139

В этом разделе описывается механизм передачи данных в устройстве RealTek8139; однако рекомендуется загрузить руководство по программированию «RTL8139 (A/B) Programming Guide», в котором приведены все подробности. В RealTek8139 имеется 4 дескриптора передачи, каждый дескриптор имеет фиксированное смещение адреса ввода-вывода. Четыре дескриптора используются циклически. Это означает, что для передачи четырех пакетов драйвер будет использовать в циклическом порядке дескриптор 0, дескриптор 1, дескриптор 2 и дескриптор 3. Для передачи следующего пакета драйвер снова будет использовать дескриптор 0 (при условии, что он свободен). В спецификациях RealTek8139 в разделе «Описание регистров» указывается, что регистры TSAD0, TSAD1, TSAD2 и TSAD3 имеют смещения 0x20, 0x24, 0x28, 0x2C, соответственно. В этих регистрах хранится «начальный адрес дескрипторов передачи «, т.е. в них хранится стартовый адрес (в памяти) пакетов, которые должны быть переданы. Позже устройство считает содержимое пакетов из этих адресов DMA, перепишет их в свой собственный стек FIFO, а затем выполнит передачу данных в сеть.

Мы скоро увидим, что этот драйвер выделяет память прямого доступа (доступ DMA), где будут храниться пакеты, и записывает адрес этой памяти в регистры TSAD.

Какой механизм приема используется в RealTek 8139

Приемная часть RTL8139 спроектирована как кольцевой буфер (линейная память, управление которой осуществляется как кольцевой памятью). Всякий раз, когда устройство принимает пакет, содержимое пакета запоминается в память кольцевого буфера и изменяется место, куда будет записываться содержимое следующего пакета (начальный адрес первого пакета + длина первого пакета). Устройство продолжает так запоминать пакеты до тех пор, пока не исчерпается линейная память. В этом случае устройство снова начинает запись с начального адреса линейной памяти, реализуя, таким образом, кольцевой буфер.

Делаем устройство готовым к передаче пакетов

Таблица 10: Определения регистров RTL 8139

Таблица 11: Пишем функцию открытия устройства

Таблица 12: Пишем функцию start_xmit

Функция rtl8139_start_xmit, показанная в таблице 12, исключительно тривиальная. Сначала она ищет имеющийся дескриптор передачи, а затем проверяет, чтобы размер пакета был, по меньшей мере, 60 байтов (поскольку размер пакетов Ethernet не может быть меньше 60 байтов). Как только это будет сделано, будет вызвана функция skb_copy_and_csum_dev, которая скопирует содержимое пакетов в имеющуюся память DMA. Следующей функцией writel мы информируем устройство о длине пакета. После этого пакеты передаются в сеть. Затем мы определяем имеющиеся в наличии следующие дескрипторы передачи и, если так случится, что он будет равен дескриптору, для которого передача еще не завершена, то мы остановим устройство; в противном случае мы просто выйдем из функции.

Теперь наше устройство готово отсылать пакеты (помните, что мы еще не можем принимать пакеты). Откомпилируйте драйвер и попытайтесь послать пакеты ping. На другом конце Вы должны увидеть несколько пакетов ARP. Даже если удаленные хосты будут отвечать на пакеты ARP, они для нас будут бесполезными, поскольку мы не готовы их принимать.

Делаем устройство готовым к приему пакетов

Таблица 13: Расширяем структуру rtl8139_private

Компонента stats должна хранить статистику с устройства (большая часть статистики, выдаваемой ifconfig, берется из этой структуры). Следующая компонента, rx_ring, является адресом памяти в ядре, где запоминаются принятые пакеты, а rx_ring_dma – физический адрес этой памяти. Как мы скоро увидим, компонент cur_rx используется для отслеживания места, куда будет записываться следующий пакет.

Таблица 14: Расширяем функцию rtl8139_open

Код в таблице 14 вычисляет размер памяти, нужный для кольцевого буфера. Вычисление RX_BUF_TOT_LEN зависит от некоторых конфигурационных параметров устройства. Как мы скоро увидим, в функции rtl8139_hw_start устанавливаются значения битов 12 – 11 регистра RCR в 10, что задает длину приемного буфера равной 32K+16. Таким образом, мы выделяем этот объем памяти для приемного буфера. Также мы устанавливаем значение бита с 7 в 1, что означает, что RTL8139 переместит остальные пакетные данные в память, которая идет сразу после конца приемного буфера. Поэтому мы дополнительно выделяем 2048 байтов с тем, чтобы справиться с такими ситуациями.

Таблица 15: Расширяем функцию rtl8139_hw_start

Как видно в таблице 15, первое изменение в функции rtl8139_hw_start — мы записываем в регистр CR значения CmdTxEnb | CmdRxEnb, что означает, что устройство будет передавать и принимать пакеты. Следующее изменение – конфигурирование приемной части устройства. Я не использовал в коде макросы, но, если вы смотрели спецификации rtl8139, они понятны. В этом месте используются следующие биты:

  • Бит 1 – Принимаются пакеты с проверкой физического адреса (адреса MAC – прим.пер.).
  • Бит 2 – Принимаются многоадресные пакеты (посылаемые на несколько адресов – прим.пер.)
  • Бит 3 – Принимаются широковещательные пакеты (посылаемые на все адреса – прим.пер.)
  • Бит 7 — WRAP. Когда установлен в 1, то RTL8139 будет перемещать оставшуюся часть пакетных данных в память, которая следует непосредственно за концом премного буфера.
  • Биты 8-10 — Максимальный размер буфера DMA для каждого сохраняемого в DMA пакета. Мы устанавливаем это значение равным 111, что означает – неограниченный.
  • Биты 11-12 – Длина буфера приема. Мы устанавливаем это значение равным 10, что означает 32K+16 байтов.

Следующее крупное изменение – конфигурирование регистра RBSTART. В этом регистре содержится стартовый адрес приемного буфера. Далее мы обнуляем регистр MPC (Missed Packet Counter – счетчик ошибочных пакетов) и конфигурируем устройство так, чтобы не генерировались ранние прерывания.

Последняя большая функция, которую мы хотим обсудить – обработчик прерываний устройства. Этот обработчик прерываний ответственен за прием пакетов, а также за обновление необходимой статистики. Ниже приведен исходный код обработчика прерываний.

Таблица 16: Обработчик прерываний

Последняя функция, которую мы хотим добавить — rtl8139_get_stats, она просто возвращает tp->stats.

Таблица 17: Функция rtl8139_get_stats

Этим завершается разработка нашего драйвера. Откомпилируйте его, снова вставьте его в ядро (Вы должны с помощью команды rmmod выгрузить предыдущий модуль) и пропингуйте другой хост. Вы должны получить ответ на пинги.

Хотя драйвер профессионального уровня содержит гораздо больше возможностей, чем имеется в нашем драйвере, последний даст вам хорошее представление о сетевых драйверах и поможет понять процесс разработки драйверов.

Источник

Оцените статью