Пишу KWDF-драйвер для PCIe-устройства.
Руководствуюсь примером src\general\PLX9x5x из WinDDK.
На данный момент мой драйвер компилируется и устанавливается через диспетчер устройств без ошибок. Информация о нём появляется в реестре, простенькие программа c++ видит моё устройство (точнее class interface моего устройства). Теперь стоит задача организации чтения/записи.
Помогите разобраться вот с чем.
Есть у меня обработчик, который называется XXxPrepareHardware. В этом обработчике я смотрю список всех ресурсов и сохраняю их в переменные драйвера.
В частности, я вижу три ресурса:
* Memory (F9F00000 — FA000000)
* DevicePrivate
* Interrupt
Из этих трёх ресурсов для меня самый интересный — memory. Именно этот ресурс я вижу на вкладке "Ресурсы" моего устройства в диспетчере задач.
Кроме того, у меня есть приложение PCITree (скачал из инета), которое показывает список PCI-устройств и для каждого из них отображает Config Space Dump. В этом дампе для моего устройства помимо прочего есть некий BAR0 mem 32 bit размером 1 Мб. Действительно при прошивке устройства я инициализировал этот BAR0 именно таким, какой он отображается в PCITree. И получается, что этот BAR0 совпадает с ресурсом memory моего устройтсва.
В примере для PLX9x5x в обработчике XXxPrepareHardware выполняется поиск нескольких ресурсов типа memory (запоминаются их базовые адресы и размеры). Они обозначаются, как:
BAR0 — Regs (т.е. видимо регистры)
BAR2 — SRAM
BAR3 — SRAM2
Вопрос такой: что такое, найденный в моём случае, ресурс — BAR0? SRAM или Regs?
Что вообще такое SRAM и Regs? Особенно Regs..
В примере для PLX9x5x в файле Reg9656.h описана структура вида
typedef struct _PCI9656_REGS_ {
unsigned int Space0_Range ; // 0x000 unsigned int Space0_Remap ; // 0x004
...
unsigned int Arbiter_Cntl ; // 0x100unsigned int Abort_Address ; // 0x104
} PCI9656_REGS, * PPCI9656_REGS;
Как я понимаю, это структура регистров для устройства в рассматриваемом примере. Как мне сделать что-то подобное для моего устройства?
Честно говоря, в голове уже каша и очень надеюсь на помощь.
Здравствуйте, chaika_sv,
_>Есть у меня обработчик, который называется XXxPrepareHardware. В этом обработчике я смотрю список всех ресурсов и сохраняю их в переменные драйвера. _>В частности, я вижу три ресурса: _> * Memory (F9F00000 — FA000000) _> * DevicePrivate _> * Interrupt
_>Из этих трёх ресурсов для меня самый интересный — memory. Именно этот ресурс я вижу на вкладке "Ресурсы" моего устройства в диспетчере задач.
_>В примере для PLX9x5x в обработчике XXxPrepareHardware выполняется поиск нескольких ресурсов типа memory (запоминаются их базовые адресы и размеры). Они обозначаются, как: _>BAR0 — Regs (т.е. видимо регистры) _>BAR2 — SRAM _>BAR3 — SRAM2
_>Вопрос такой: что такое, найденный в моём случае, ресурс — BAR0? SRAM или Regs?
---
Каждое PCI/PCIe устройство имеет свою собственную структуру регистров I/O и/или памяти процессора, через которую с ними можно общаться. Они уникальны для каждого PCI устройства и информацию о них можно получить в описании конфигурационного пространства PCIe конкретной микросхемы.
BARx — это регистры в конфигурационном пространстве PCI устройства, с помощью которых система может узнать, сколько и какого размера требуется для PCI устройства памяти и/или регистров I/O, и затем задать базовый адрес для этих участков в своем пространстве памяти и регистров I/O. В некотором смысле BARx определяет "окно" (тип окна — память или регистры I/O, его размер и т.п.), через которое можно общаться с PCI устройством.
В современных устройствая PCI/PCIe стараются не использовать "окна", которые представляют собой регистры I/O.
В Вашем случае микросхема имеет одно "окно", которое система считает участком памяти. Размер этого окна — 1 MB.
_>Что вообще такое SRAM и Regs? Особенно Regs..
---
К регистрам (Regs) PCI/PICe можно добраться с помощью специальных команд ввода/вывода (например, in и out для 80x86). К памяти (SRAM) PCI/PCIe можно добраться куда более изощренными способами, и это, на мой взгляд, одна из причин тенденции использования только памяти в PCI/PCIe устройствах.
_>В примере для PLX9x5x в файле Reg9656.h описана структура вида _>Как я понимаю, это структура регистров для устройства в рассматриваемом примере. Как мне сделать что-то подобное для моего устройства?
---
Я бы назвал ее не структурой регистров, а описанием того, каким образом можно обращаться к микросхеме (описание "окон"). Я ее обычно составляю сам, исходя из описания конфигурационного пространства устройства.
Обратите внимание, что каждое окно конкретного PCI устройства в свою очередь может иметь относительное разбиение на участки и там тоже обычно используется термин "регистры". Эти регистры представляют собой реализацию (т.е. кишочки, внутренности) микросхемы и их не следует путать с регистрами I/O процессора. Для них, например, в нашей лавке разработчики микросхем автоматически генерируют макросы (defines) исходя из реализации кокретных регистров. Далее, с их помошью, программист может уже задать относительный адрес регистра в "окне" и распределение бит в этом регистре.
Геннадий, спасибо огромное! Кажется, теперь всё встаёт на свои места.
Т.е. помимо всего прочего у меня есть в конфигурационном пространстве:
— регистр BAR0, который для окна памяти (SRAM) задаёт размер 1 MB и его начальный адрес xF9F00000
— само окно памяти (SRAM) размером 1 MB
Всё так?
Вы писали про изощрённые способы работы с памятью (SRAM). Подскажите, пожалуйста, в общих чертах, что это за способы?
ГМ>Я бы назвал ее не структурой регистров, а описанием того, каким образом можно обращаться к микросхеме (описание "окон"). Я ее обычно составляю сам, исходя из описания конфигурационного пространства устройства.
Т.е. изначально у меня есть "пустое" окно памяти размером в 1 MB, и я как бы "накладываю" на него такую структуру. Об этой структуре "знают" драйвер и прошивка микросхемы. Правильно ли я понимаю, что это нужно для того, чтобы не возиться с адресами внутри окна, а работать с именованными полями структуры, потому что так просто удобнее?
Здравствуйте, chaika_sv,
_>Т.е. помимо всего прочего у меня есть в конфигурационном пространстве: _> — регистр BAR0, который для окна памяти (SRAM) задаёт размер 1 MB и его начальный адрес xF9F00000 _> — само окно памяти (SRAM) размером 1 MB _>Всё так?
--
Да, правильно.
В конфигурационном пространстве нет явной информации о размере окна, она получается (генерируется микросхемой) при определенной манипуляции с регистрами BAR. Система записывает в него все 1 и снова читает. В ответ на это чтение PCI устройство сообшает размер окна и кое-какую другую информацию, в частности, тип окна, соответствуюшего этому BAR. Далее система резервирует в своем адресном пространстве необходимыый кусок памяти или регистров и вновь записывает уже начальный адрес этого участка в этот BAR. (Я по памяти эту пишу, могу в детялях ошибиться...)
_>Вы писали про изощрённые способы работы с памятью (SRAM). Подскажите, пожалуйста, в общих чертах, что это за способы?
--
Ну например, косвенная и/или индексная адресация, выполнение математических действий, строковые операции. Посмотрите, например, систему команд процессора x86. Для программиста — все, что можно сделать с выделенным участком памяти. Только выделила этот участок памяти система и сообшила Вам его адрес и длину как значение параметров при вызове XXxPrepareHardware.
ГМ>>Я бы назвал ее не структурой регистров, а описанием того, каким образом можно обращаться к микросхеме (описание "окон"). Я ее обычно составляю сам, исходя из описания конфигурационного пространства устройства.
_>Т.е. изначально у меня есть "пустое" окно памяти размером в 1 MB, и я как бы "накладываю" на него такую структуру. Об этой структуре "знают" драйвер и прошивка микросхемы. Правильно ли я понимаю, что это нужно для того, чтобы не возиться с адресами внутри окна, а работать с именованными полями структуры, потому что так просто удобнее?
--
Нет, не совсем так так.
Приведенная в первом письме структура описывает расположения окон в системе. Она описывает "позицию" PCI устойства в системе как совокупность окон.
Да, эта информация нужна системе (Windows), прошивке микросхемы и драйверу.
Нет, для упрощения работы с окнами микросхемы она не годится. Для этого нужна или другая структура, или defines, последние, на мой взгляд, удобнее. Эта другая структура (или defines) уже описывает структуру окна.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Приведенная в первом письме структура описывает расположения окон в системе. Она описывает "позицию" PCI устойства в системе как совокупность окон.
К сожалению, не очень понял Вас
В примере в обработчике XXxPrepareHardware есть такой код:
//
// Map in the Registers Memory resource: BAR0
//
DevExt->RegsBase = (PUCHAR) MmMapIoSpace( regsBasePA, // Базовый адрес BAR0
regsLength, // Длина BAR0
MmNonCached );
.......
DevExt->RegsLength = regsLength;
//
// Set seperated pointer to PCI9656_REGS structure.
//
DevExt->Regs = (PPCI9656_REGS) DevExt->RegsBase;
Получается под эту структуру PPCI9656_REGS они выделяют отдельную область памяти (которую BAR0 описывает)?
Ну и по назначению этой структуры ещё не совсем всё понятно.. Как её использует система? (как её могут использовать драйвер и прошивка микросхемы вроде понятно)
Здравствуйте, chaika_sv,
ГМ>>Приведенная в первом письме структура описывает расположения окон в системе. Она описывает "позицию" PCI устойства в системе как совокупность окон.
_>К сожалению, не очень понял Вас
--
Mea culpa
Я счас еще раз взглянул на структуру
typedef struct _PCI9656_REGS_ {
unsigned int Space0_Range ; // 0x000 unsigned int Space0_Remap ; // 0x004
...
unsigned int Arbiter_Cntl ; // 0x100unsigned int Abort_Address ; // 0x104
} PCI9656_REGS, * PPCI9656_REGS;
и я тут не прав. Она действительно описывает структуру окна. Вы правы, если ее "наложить" на окно, начинаюшееся с адреса DevExt->RegsBase, то Вы получите удобный способ доступа к внутренним регистрам микросхемы.
Виноват, приношу свои извинения .
_>В примере в обработчике XXxPrepareHardware есть такой код: _>
_> //
_> // Map in the Registers Memory resource: BAR0
_> //
_> DevExt->RegsBase = (PUCHAR) MmMapIoSpace( regsBasePA, // Базовый адрес BAR0
_> regsLength, // Длина BAR0
_> MmNonCached );
_> .......
_> DevExt->RegsLength = regsLength;
_> //
_> // Set seperated pointer to PCI9656_REGS structure.
_> //
_> DevExt->Regs = (PPCI9656_REGS) DevExt->RegsBase;
_>
_>Получается под эту структуру PPCI9656_REGS они выделяют отдельную область памяти (которую BAR0 описывает)?
--
Да, система выделили отдельную область памяти, которая может "выглядить" как эта структура.
_>Ну и по назначению этой структуры ещё не совсем всё понятно.. Как её использует система? (как её могут использовать драйвер и прошивка микросхемы вроде понятно)
--
Здесь опять моя неточность в прошлом письме. Система о ней в принципе ничего не знает, за исключением начала области памяти и ее длины. Она нужна в драйвере для обеспечения функциональной работы с микросхемой. Если Вы найдете описание этой микросхемы, то там наверняка будет написано назначение каждого регистра (Space0_Range, Space0_Remap, ...,Arbiter_Cntl, Abort_Address) и каждого бита в них.
У меня вопросов всё меньше..
ГМ>если ее "наложить" на окно, начинаюшееся с адреса DevExt->RegsBase, то Вы получите удобный способ доступа к внутренним регистрам микросхемы.
А что это за внутренние регисты микросхемы? Может и у моей такие есть?
Случайно не те, которые описаны в конфигурационном пространтсве и имеют пометку в PCITree "device specific"? Там всего 64 регистра (первые 16 — это типа VID, DID, BARx (они одинаковы для всех устройств), а оставшиеся 17..64 как раз имеют пометку "device specific").
ГМ>Виноват, приношу свои извинения .
Геннадий, Вам не за что извиняться, Вы мне очень сильно помогли!
Здравствуйте, chaika_sv,
ГМ>>если ее "наложить" на окно, начинаюшееся с адреса DevExt->RegsBase, то Вы получите удобный способ доступа к внутренним регистрам микросхемы. _>А что это за внутренние регисты микросхемы? Может и у моей такие есть?
--
Скорее всего есть.
В Вашем случае это можно найти, скорее всего, в описании той "прошивки" FPGA, которую Вы используете.
_>Случайно не те, которые описаны в конфигурационном пространтсве и имеют пометку в PCITree "device specific"? Там всего 64 регистра (первые 16 — это типа VID, DID, BARx (они одинаковы для всех устройств), а оставшиеся 17..64 как раз имеют пометку "device specific").
--
Увы, нет. Это не они.
ГМ>>Виноват, приношу свои извинения . _>Геннадий, Вам не за что извиняться, Вы мне очень сильно помогли!
--
Наш с Вами диалог могут прочесть и другие коллеги, так что это относится и к ним тоже...