Запись драйвера для устройства PCI
Драйвер устройства PCI управляет устройством, присоединенным к шине PCI. Соответствия драйвера и присоединения к объекту куска IOPCIDevice или IOAGPDevice класс, конфигурирует устройство через пространство конфигурации PCI и устанавливает регистры с отображенной памятью или пространство I/O, чтобы позволить управлять устройством. Мало еще необходимо кроме кода для управления самим устройством.
Соответствие
Драйвер, который способен к управлению устройством на шине PCI, объявляет об этом факте включением индивидуальности в ее списке свойств. Эта индивидуальность включает ключ IOProviderClass со значением IOPCIDevice.
Поскольку IOAGPDevice подкласс IOPCIDevice, не необходимо соответствовать на IOAGPDevice для Вашего драйвера для присоединения к устройствам AGP. Таким образом необходимо обычно только соответствовать на IOPCIDevice.
IOPCIDevice и IOAGPDevice оба определяют два набора ключей, которые драйвер может использовать для соответствия, одного на основе стандартных регистров PCI, и другой на основе Открывает Firmware. Драйвер устройства PCI может использовать любой тип ключа. Это может даже использовать комбинацию двух, пока они находятся в отдельных лицах.
Соответствие PCI
Драйверы устройств PCI могут базировать свое свойство, соответствующее на регистрах пространства конфигурации PCI для поставщика, и устройство ID (смещает 0x00, и 0x02), поставщик подсистемы и устройство ID (смещает 0x2C, и 0x2E), и код класса (сместите 0x09). Другие регистры, такие как версия ID и тип заголовка, не доступны в соответствии свойства и должны быть исследованы probe метод. PCI, соответствующий ключи словаря:
Ключ | Поведение при сравнении |
|---|---|
| Соответствия против основного поставщика/устройства ID регистрируются или поставщик/устройство подсистемы регистры ID. Основной IDs проверяется сначала; если любой из них не соответствует тогда подсистему, IDs проверяется. |
| Соответствия только против основного поставщика/устройства регистры ID. |
| Соответствия только против поставщика/устройства подсистемы регистры ID. |
| Соответствия против кодового регистра класса. |
Значение для ключа может быть единственным значением регистра или списком значений регистра, разделенных пробелами. Значения регистра даны как шестнадцатеричные строки с прямым порядком байтов с устройством ID сначала и второй идентификатор поставщика. Посмотрите Порядок байтов и Адресующийся для получения дополнительной информации о порядке байтов.
В дополнение к самому значению каждое значение ключа может включать маску, указывающую, что только должна быть сравнена часть значения.
Вот некоторые примеры соответствия словарных статей. Первый пример соответствует устройство PCI основному идентификатору поставщика 0x8086 и основного устройства ID 0x1229, или с подсистемой IDs тех значений.
<key>IOPCIMatch</key> |
<string>0x12298086</string> |
Второй пример соответствует устройство PCI основному идентификатору поставщика 0x8086 и основного устройства ID 0x1229 или 0x1227, или с подсистемой IDs тех значений.
<key>IOPCIMatch</key> |
<string>0x12298086 0x12278086</string> |
Третий пример соответствует устройство PCI основному идентификатору поставщика 0x8086 и основного устройства ID 0x1229. Подсистема IDs не проверяется.
<key>IOPCIMatch</key> |
<string>0x12298086</string> |
Четвертый пример использует маску для соответствия устройства PCI основному идентификатору поставщика 0x8086 и любого основного устройства ID, чей сначала две цифры являются 0x12. Подсистема IDs не проверяется.
<key>IOPCIPrimaryMatch</key> |
<string>0x12008086&0xFF00FFFF</string> |
Маска присоединена к значению регистра с помощью символа амперсанда, который должен быть закодирован как & в XML, если Вы редактируете его непосредственно. Если Вы используете Редактора XCode или Списка свойств, & Escape представлен просто как амперсанд (и).
Эта запись соответствует устройство PCI основному идентификатору поставщика 0x8086 и кода класса, начинающегося 0x0200, кода класса для контроллеров Ethernet.
<key>IOPCIMatch</key> |
<string>0x00008086&0x0000FFFF</string> |
<key>IOPCIClassMatch</key> |
<string>0x02000000&0xFFFFFF00</string> |
Откройте Firmware Matching
Драйвер устройства PCI может использовать, Открывать Firmware, соответствующий в индивидуальности путем указания значения для IONameMatch ключ. Значение является или единственной строкой или массивом строк, сравненных со значениями для Открыть свойств устройства Firmware name, compatible, device_type, или model.
Если любое из значений для IONameMatch ключевое соответствие любое из свойств Open Firmware, соответствие считают успехом, и экземпляр драйвера создается для индивидуальности. Имя, приведшее к соответствию, сохранено как свойство в водительском Ключе реестра I/O в IONameMatched ключ (kIONameMatchedKey).
Для получения дополнительной информации о соответствии имени необходимо консультироваться с документацией для IOService класс.
Проверка устройства PCI и конфигурация
Прежде чем драйвер начинает взаимодействовать с устройством PCI, ли в probe метод или start метод, это обычно исследует значения в регистрах пространства конфигурации PCI и устанавливает некоторых из них как требуется. Класс IOPCIDevice определяет несколько методов и масок регистра для создания выполнения настолько простого.
Наиболее общие методы configRead32, configWrite32, и setConfigBits. Первый метод читает, полное 32-разрядное значение от 4 байтов выровняло адрес в пространстве конфигурации PCI. Драйвер может тогда извлечь определенное значение регистра. Драйвер мог бы использовать этот метод во время зондирования для исследования значения версии регистр ID, например. IOPCIDevice определяет много констант для различных смещений регистра.
Метод configWrite32 пишет, что полное 32-разрядное значение в 4 байта выровняло адрес в пространстве конфигурации PCI. Более гибкий метод setConfigBits может записать отдельные биты в пространство конфигурации, не тревожа других. Это принимает 32-разрядное значение для записи вместе с 32-разрядной маской, указывающей который биты установить или очиститься. Это обычно используется для записи в регистр команды. Этот фрагмент кода, например, включает запись памяти, и лишите законной силы транзакцию (MWI) на шине:
UInt32 configMask = 0; |
UInt32 configBits = 0; |
configMask = configBits = kIOPCICommandMemWrInvalidate; |
// provider is the PCI nub object |
provider->setConfigBits(kIOPCIConfigCommand, |
configMask, configBits); |
Для обычно используемых параметров конфигурации IOPCIDevice определяет удобные методы, берущие a bool параметр за включение и отключение настроек. Эти методы setMemoryEnable для управления с отображенной памятью устройства PCI и setIOEnable для управления I/O-mapped.
Некоторые устройства требуют, чтобы шинное управление работало должным образом. Для большинства карт Откройте, Firmware должен установить это автоматически на основе информации в объявлении карты ROM, прежде чем OS X даже начнет загружаться. Однако эта автоматическая установка не всегда происходит, в зависимости от специфических особенностей определенной карты и на решениях, принятых поставщиком карты при заполнении карты с ROMs. Если карта не сконфигурирована правильно в этом отношении, можно использовать setBusMasterEnable вручную включать или выключать шинное управление для устройства.
Другие методы для проверки устройства PCI включают findPCICapability, getBusNumber, getDeviceNumber, и getFunctionNumber. Для получения дополнительной информации на них и всех других методах, см. справочную документацию в /System/Developer/Documentation.
Доступ к устройствам
start метод то, где наборы драйверов его аппаратные средства для работы. Для устройств PCI это включает конфигурирование аппаратных средств, как описано выше, установка канал передачи между CPU и устройством и затем выполнением независимо от того, что требуется специфичная для устройства инициализация. Можно получить доступ к устройству PCI путем отображения регистров устройства (его пространство памяти) в адресное пространство ядра, или путем чтения и записи в пространстве I/O устройства с помощью объекта куска.
Отображение регистров устройства является наиболее удобным способом установить управление устройствами. Как только это сделано, драйвер имеет очень мало дальнейшего взаимодействия с IOPCIDevice кусок. Вместо этого это взаимодействует с аппаратными средствами, как будто это была обычная память, хотя некэшируемая память, с помощью или методов доступа устройства для свопинга байта или путем прямого разыменования указателей в пространство памяти карты.
Доступ пространства I/O обеспечивает единственный интерфейс программирования для использования пространства I/O. На процессорах с отдельной шиной памяти I/O методы пространства I/O фактически используют эту шину. На процессорах без отдельной шины памяти I/O методы просто используют пространство с отображенной памятью и обрабатывают требуемую синхронизацию автоматически.
Доступ к устройствам с отображенной памятью
Установка управления устройствами с отображенной памятью является двухступенчатым процессом. Драйвер должен сначала добраться IOMemoryMap объект для одного из индексных регистров устройства, с помощью mapDeviceMemoryWithRegister метод. Константы доступны для смещений индексного регистра. Драйвер тогда вызывает карту распределения памяти getVirtualAddress метод для получения указателя на регистр с отображенной памятью блокирует в виртуальном адресном пространстве ядра. Вот пример стандартной идиомы для установки регистров с отображенной памятью, который обычно делается в водительскомstart метод:
IOMemoryMap *map; |
map = provider->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0); |
if (!map) { |
// Handle error |
} |
deviceRegisterPointer = (deviceStruct *)map->getVirtualAddress(); |
Оба map и deviceRegisterPointer переменные экземпляра драйвера. Поскольку драйвер создал объект карты путем вызова mapDeviceMemoryWithRegister, это должно кэшировать указатель и более поздний выпуск объект карты в stop метод. deviceRegisterPointer указатель на структуру, определенную драйвером, соответствующим расположению специфичных для устройства регистров.
Необходимо отметить две вещи при использовании управления с отображенной памятью устройства PCI. Во-первых, PCI соединяет шиной обращение байта использования стандарта с прямым порядком байтов. Порядок байтов шины обычно оказывает минимальное влияние на писателей драйвера устройства. Однако порядок байтов также мотивирует связанную модель расположения регистра, непосредственно влияющего на большинство писателей драйвера. Для получения дополнительной информации посмотрите Порядок байтов и Обращение.
Во-вторых, в то время как доступы в пространство PCI явно не кэшируются, чтобы не гарантируется выполнение этих доступов. Когда порядок выполнения важен, барьеры I/O могут использоваться.
Барьеры I/O часто используются по следующим причинам:
Гарантировать, что операнды команды, отправленной в устройство, записаны в регистры устройства прежде, чем утвердить команду.
Гарантировать, что команда начала выполняться прежде, чем опросить относительно ее состояния завершения.
Гарантировать, что линия прерывания очищена прежде, чем ожидать того прерывания снова.
Барьер I/O общего назначения в OS X предоставлен libkern функция OSSynchronizeIO. На архитектуре PowerPC, например, это выходит eieio инструкция для осуществления, чтобы выполнение операции записи. Из-за влияния производительности необходимо только использовать барьер I/O когда, чтобы выполнение требуется для корректной работы.
Синхронизация требуется только при записи непосредственно в аппаратные регистры; при установке буферов и структур, используемых аппаратными средствами, это не необходимо. Посмотрите пример драйвер PCI от набора Apple с открытым исходным кодом для примеров того, как использовать OSSynchronizeIO.
При необычных обстоятельствах Вы могли бы счесть желательным позволить кэшироваться на частях пространства I/O. Если Вы сделаете это, то записи к той части пространства PCI, как больше гарантируют, не будут записаны обратно к пространству памяти устройства. Дополнительная синхронизация необходима в этих случаях. Включение кэширующегося и выполнение I/O к кэшируемым пробелам I/O выходят за рамки этой книги. При необходимости в такой поддержке, необходимо связаться с Технической поддержкой Разработчика Apple для получения дополнительной информации.
I/O Располагает Доступ к устройствам с интервалами
Установка доступа пространства I/O требуется только для устройств с перемещаемыми пробелами I/O. В этом случае драйвер должен получить объект IOMemoryMap, так же, как для доступа с отображенной памятью. Кроме этого, однако, доступ пространства I/O выполняется с помощью ряда шести методов для чтения и записи 32-разрядных, 16-разрядных, и 8-разрядных значений. ioWrite16 метод, например, берет байтовое смещение в пространство памяти, значение для записи, и карта распределения памяти для пространства I/O. Для устройств с неперемещаемыми пробелами I/O опущен параметр карты распределения памяти. Методы пространства I/O выполняют весь необходимый свопинг байта и синхронизацию. Для получения дополнительной информации об этих методах см. справочную документацию IOPCIDevice в /System/Developer/Documentation/Kernel/IOKit/IOPCIDevice.