На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
Страницы: (51) « Первая ... 45 46 [47] 48 49 ... Последняя »  ( Перейти к последнему сообщению )  
> Желающим USB под ДОС , Welcome!!!
    Ну, вот наконец разобрался я с текущими делами на работе, с 32-битным расширителем ДОС, и даже с 64-битным режимом.. Можно спокойно приступить к исследованию xHCI, то бишь контроллера USB 3.0. Есть у меня отдельная плата PCI-express от фирмы ST Lab, и есть мамка со встроенным контроллером от Intel. Найти контроллер на шине труда не составило, прочитать его регистры - тоже. Пока есть некоторые странности, например, ST Lab говорит, что у него 0 портов, хотя их на самом деле 2. Ну, надеюсь, разберусь. Постараюсь рапортовать здесь о ходе работы.
      Нашел у себя ошибку. Странно, она тянулась уже несколько лет, а я ее не замечал. Читая BAR0 из PCI configuration space, я не обнулял его младшие биты. А там же флажки всякие. Когда я работал с UHCI, то обнулял самый младший бит, поскольку там идет указание на то, что в BAR0 записан адрес порта. А в OHCI и EHCI не обнулял. И до сих пор везло - они и так были нулями. Сейчас же столкнулся с тем, что бит 2 установлен в 1 ("any 64-bit") и, соответственно, я читал совсем не те адреса, которые были нужны. В общем, сейчас вижу нормальные значения во всех регистрах, и уже прошел ресет контроллера. Запустить в полном объеме пока не могу, поскольку не заполнены никакие структуры данных.
        При подключении флешки к любому порту загорается лампочка на флешке, горит секунды две и гаснет. Это если ничего не делать с контроллером.
        Сделал опрос портов, увидел подключенное устройство. Сделал ресет порта. Получил установленный бит Port Enabled. Лампочка на флешке загорелась и не гаснет. В регистре статуса порта увидел идентификатор скорости устройства. Он разный при подключении флешки (2.0 High Speed), мыши (1.1 Low Speed) и матричного сканера штрих-кодов (1.1 Full Speed). К сожалению, оставил дома винчестер с USB 3.0 (SuperSpeed), а здесь в доступной близости таких устройств нет..
        У платы от ST Lab всего два порта, но они имеют номера 3 и 4. Поэтому я не видел подключенных устройств, пока пробовал опрашивать только порты 1 и 2.. Пока не сделал полный цикл, ничего не получалось.
        Сообщение отредактировано: zakharo -
          Дома проверил подключение винчестера 3.0. Устройства, работающие по протоколу USB 3.0 (SuperSpeed), не требуют ресета порта. Все делается автоматически. Контроллер сам определяет подключение такого устройства и выставляет бит Port Enabled. Ну, и идентификатор скорости соответствующий.
          На сегодня работу закончил, завтра займусь транзакциями.
          Сообщение отредактировано: zakharo -
            Запутался во всех этих новых делах.. Command Ring, Event Ring, Transfer Ring.. В спецификации постоянно идут отсылки к другим разделам.. Начинаешь читать про одно, тебя для "более детальной информации" отсылают к другому, оттуда - к третьему и т.д.
            В конце концов нашел в Инете такую интересную страничку http://www.cs.usfca.edu/~cruse/cs698s10/, на которой есть демонстрационная программка xhcidemo.cpp. Она изначально написана для Линукса, но легко правится для Watcom C с 32-битным расширителем. Рассчитана на работу с неким USB-индикатором, который как-то мигает лампочками. Там проводится вся нужная инициализация контроллера и устройства, вплоть до присвоения адреса и установки конфигурации. Попутно на экран выводится состояние регистров контроллера и всех этих рингов.. Выкинув все, что связано с неизвестным мне индикатором, я получил вполне работающий вариант. Теперь разбираюсь по шагам, что же реально делает эта программа.. :-)
              Цитата zakharo @
              У платы от ST Lab всего два порта, но они имеют номера 3 и 4.

              Оказалось, что такие номера порты имеют при подключении флешки USB2.0. При подключении же винчестера USB3.0 порты имеют номера 1 и 2.
              Весь день разбирался с демонстрационной программой. Слишком уж она демонстрационная. Хотя инициализация делается, и какие-то команды посылаются, но ответы контроллера никак не проверяются. Когда я наконец, разобрался, как же проверять код завершения выполненной команды, выяснилось, что Address Device (есть такая команда у контроллера) не проходит. Возвращается код 17 - ошибка в параметрах контекста. Пытаюсь понять, в чем именно ошибка..
                Жесть.. Много раз проверял все структуры.. Все вроде соответствует описанию. А команда Address Device по-прежнему возвращает код 17. Попытка запустить эту программу на домашнем компьютере привела к немедленному зависанию сразу после старта контроллера - видимо, по причине того, что тому контроллеру нужны scratchpad buffers, которых требуется аж 16. Плата от ST Lab этих буферов не требует, а потому и программа не выделяет (так было и в той изначальной демке). Я уже сделал было предположение, что плата ST Lab не полностью выполняет спецификацию и требует каких-то дополнительный инициализаций.. Взял демо-программку от George Potthast (он уже сделал поддержку 3.0) - она прекрасно видит флешку, подключенную к порту ST Lab. Значит, это все же я чего-то недопонимаю. Будем искать..
                Жаль, линуксовые исходники не сильно помогают - очень уж там все запутано.
                Сообщение отредактировано: zakharo -
                  Нашел еще исходники для xHCI. http://review.coreboot.org/gitweb?p=corebo...ers/usb;hb=HEAD Посмотрел на тексты - опять они как-то сильно урезаны..
                  В общем, заказал себе книгу http://www.barnesandnoble.com/w/usb-benjam...lunt/1111346446 . Предполагается, что она придет недели через 3. А пока займусь другими делами, коих множество.
                    Терпение и труд все перетрут..
                    В отчаянии я зашел на сайт STLab, глянуть на описание этой моей платы, и что же я увидел?? Новую прошивку для нее, датированную летом 2012 года! Перешил - и вуаля!! Моя программа заработала! По крайней мере, команда Address Device проходит с нормальным кодом завершения, и контроллер заполняет контекст устройства. Вот оно как.. Видно, плата эта была сделана по какой-нибудь пререлизной спецификации. Когда я ее купил-то, уж и не помню.. Кажется, в 2010-м, что ли.. Она просто не могла быть сделана по релизной версии. Не очень понятно, правда, почему работала программа Поттхаста. Могу предположить, что он знал какие-то особенности той спецификации. Ну, в общем, дальше остались мелочи - сделать транзакции. Все остальное у меня уже есть.
                    Сообщение отредактировано: zakharo -
                      Ну, все, пошло дело! Пронумеровал устройство (флешку), получил дескриптор устройства (8 байтов), узнал из него длину пакета EP0, поправил ее в контексте устройства, получил дескриптор конфигурации (8 байтов), узнал его реальную длину (wTotalLength) и получил весь дескриптор конфигурации. То есть транзакции типа SETUP пошли в полном объеме. Теперь надо сделать конфигурацию остальных EP - и дело в шляпе. Можно будет уже на понятном языке пересказать всем, как же работает этот контроллер.
                      Сообщение отредактировано: zakharo -
                        Ну, все. Пошли bulk-транзакции, прошли SCSI-команды TEST UNIT READY и INQUIRY. А значит, пройдут и все другие. Можно считать исследование интерфейса xHCI законченным. Теперь могу популярно изложить алгоритм работы с этим новым зверем. Если, конечно, это кому-то надо. Ибо просто так "в воздух" мне писать неинтересно..
                          Надо надо, пиши :)
                          Ну не то чтоб прям надо, но интересно.
                          Хоть будет какой-то результат у этого "блога" ;)
                            Ок. Подготовлю текстик и размещу здесь.
                              Начинаю описание. Здесь я изложу основные положения, которые лично для меня были новыми, но без конкретики. Вся конкретика (состав структур, значение полей и т.д.) есть в спецификации xHCI.

                              Контроллер xHCI рассчитан на работу с огромными скоростями, поэтому его архитектура существенно отличается от всех предыдущих.
                              Главное тут - понять и усвоить новые концепции.

                              Начну с конца. С того момента, когда контроллер уже проинициализирован. Иначе не будет понятно, зачем нужны те или иные действия.

                              Весь процесс обмена информацией с устройствами (после всех инициализаций, о которых речь пойдет дальше) в самых общих чертах выглядит так: у нас есть набор конечных точек (EP - Endpoint), и у каждой EP есть своя очередь "запросов на транзакции" (Transfer Request Block - TRB). TRB - это основная структура для работы с контроллером, имеет размер 16 байтов (4 32-битных слова). В зависимости от области применения поля TRB могут использоваться по-разному.

                              Когда мне нужно что-то отправить или получить, я заполняю TRB в соответствующей очереди и "звоню" в нужный "звонок" (ring the doorbell). Контроллер исполняет запрос и выдает мне ответ (как именно - объясню чуть позже).

                              Все очереди для xHCI организуются в виде кольцевых буферов (ring). Я в дальнейшем для простоты буду просто называть их кольцами. Кольцо - это массив из нужного количества TRB (какого именно, определяется программистом). У каждого кольца есть два указателя - куда класть (enqueue) и откуда брать (dequeue). Если enqueue==dequeue, очередь пуста. При инициализации EP контроллеру сообщается адрес начала соответствующего кольца (enqueue). Указатель dequeue контроллер организует сам.
                              У колец для xCHI есть одна особенность. Поскольку в очередь можно положить не один TRB, а сразу несколько, то должен быть какой-то признак, по которому контроллер поймет, где ему надо остановиться. Иначе он может просто зациклиться. Таким признаком является самый младший бит в TRB, он называется "бит C". Он изменяется при каждом проходе по кольцу. То есть, изначально вся память кольца обнулена, а у всех новых TRB бит "C" устанавливается в 1. Когда мы кладем нужное количество TRB в буфер и "звоним в звонок", контроллер исполняет все TRB с единичным битом С и останавливается. Когда мы доходим до конца кольца и возвращаемся в начало, значение бита C для всех новых TRB уже будет нулевым. И все новые TRB будут отличаться этим битом от тех, которые были в буфере раньше.

                              Размер кольца мы определяем сами. Чтобы зациклить буфер, последним TRB в кольце должен быть TRB специального типа "link", который имеет в своем составе поле адреса, указывающего на начало кольца.

                              Все общение с контроллером в процессе работы происходит через эти кольца и "звонки". Через кольца типа Transfer Ring мы выдаем ему запросы на транзакции. Таких колец должно быть столько, сколько существует активных EP. Есть еще одно кольцо для подачи команд контроллеру, оно называется Command Ring (кольцо команд). О системе команд самого контроллера - чуть позже.

                              Для ответов контроллера есть свои кольца - Event Ring (кольцо событий). Их может быть несколько. Их заполняет контроллер, а читает - наша программа. И тут уже контроллеру приходится задавать не только начало кольца, но и его размер (при инициализации), а также после каждой выборки TRB из очереди сообщать ему наш указатель dequeue, чтобы он знал, сколько свободного места есть в кольце.

                              Продолжение следует...

                              Добавлено
                              Теперь поговорим о полях памяти, с которыми работает контроллер. Начнем с описателей EP.

                              Каждая EP описывается контекстом (Endpoint Context) - это структура из 8 32-битных слов (32 байта). В контексте EP содержится информация о типе EP (bulk-in, bulk-out и т.д), ее maxPacketSize и адрес начала соответствующего кольца.

                              Все контексты EP, принадлежащие одному устройству, объединяются в единый контекст устройства (Device context). В регистре HCSPARAM1 есть байт, в котором записано максимальное количество контекстов устройств, с которыми может работать контроллер (Max Device Slots). При инициализации мы можем задать контроллеру максимальное количество контекстов, с которыми хотим работать мы (регистр CONFIG).

                              Контекст устройства - довольно специфическая структура. Она состоит из контекста слота (Slot context) и набора контекстов EP.
                              В контексте слота (структура из 8 32-битовых слов) содержится информация о скорости устройства, номере порта RootHub (корневого хаба, или просто порта контроллера), к которому оно подключено, и, если устройство подключено к хабу (цепочке хабов), то там же содержится "маршрут" (это уже понятие из спецификации USB 3.0), в котором записаны адреса и номера портов всех промежуточных хабов. Там же есть поле, описывающее состояние слота.
                              Набор контекстов EP - всегда постоянный. Согласно спецификации USB устройство может иметь до 16 EP (одна типа Control с номером 0 и до 15 разных других). В контексте устройства предусмотрено место для 31 контекста EP. Один контекст - для EP0, остальные - для всех остальных. Для всех EP, чей номер больше 0, предусмотрена пара контекстов - один для OUT, второй - для IN.
                              Например, EP номер 1h (тип OUT) будет описана контекстом со смещением 2*1 относительно начала контекста устройства (мы помним, что по смещению 0 находится контекст слота, а по смещению 1 - контекст EP0), EP номер 3h (тип OUT) - со смещением 2*3. А EP номер 85h (тип IN) - (2*5)+1. Можно сказать, что смещение контекста EP относительно начала контекста устройства вычисляется путем циклического сдвига влево (на 1 бит) ее номера.
                              В спецификации xHCI вводится термин "Device context Index" (DCI), который и указывает на контекст внутри контекста устройства. Контекст слота (Slot Context) будет иметь DCI=0, а DCI для контекстов EP будут начинаться с 1 (DCI=1 соответствует EP0).

                              Теперь расскажу, как мы "звоним в дверной звонок". У контроллера есть набор регистров, которые так и называются "doorbells" (DB). Адрес начала массива этих регистров записан в регистре DBOFF. Регистр DB с индексом 0 соответствует кольцу команд контроллера (Command Ring), остальные - контекстам устройств. Когда мы хотим сообщить, что в каком-то кольце произошли изменения, мы записываем что-то в соответствующий регистр.

                              Когда мы работаем с Command Ring (даем команду контроллеру), мы записываем 0 в регистр DB0.
                              Когда мы хотим выполнить TRB для какой-нибудь EP, мы записываем DCI этой EP в регистр DB, соответствующий номеру контекста устройства. Номера контекстов устройств (еще они называются номера слотов) начинаются с 1, так что никакой путаницы возникнуть не может.
                              Сообщение отредактировано: zakharo -
                                Теперь опишу действия при обнаружении нового подключенного устройства. Как обнаружить устройство - напишу позже.

                                Первое, что мы должны сделать, - это запросить номер свободного слота у контроллера. Для этого мы формируем в кольце Command Ring TRB с командой Enable Slot (структура описана в спецификации) и "звоним" в DB0. Контроллер отвечает в Event Ring, куда помещает TRB типа Command Completion Event с кодом завершения (Completion Code) и индексом слота (Slot ID). Этот индекс слота мы будем использовать в дальнейшем при всех операциях с устройством.
                                Мы должны выделить память под контекст устройства, обнулить ее и поместить адрес этой памяти в таблицу адресов контекстов устройств (DCBAA - о ней я расскажу чуть позже), в ячейку, соответствующую Slot ID.

                                Далее нужно проинициализировать контекст устройства. Для инициализации служит команда Address Device. Но перед тем, как выдать эту команду, мы должны выполнить еще некоторые действия. Результатом выполнения команды будет инициализированный контекст слота и контекст EP0. И мы должны дать контроллеру информацию для этих инициализаций.

                                Мы должны указать скорость устройства и порт, к которому оно подключено, а также адрес Transfer Ring (кольца TRB, которое мы тоже тут же должны инициализировать) для EP0. Чтобы дать эту информацию контроллеру, мы должны заполнить новую структуру, которая называется Input Context (входной контекст). Формат Input Context следующий - в самом начале идет структура под названием Input Control Context (входной управляющий контекст - 8 32-битных слов, из которых используются только первые 2), а после нее - полное повторение структуры Device Context. Первые два слова Input Control Context используются как битовая маска. Слово номер 0 указывает, какие контексты из реального Device Context надо сбросить (DROP), слово номер 1 - какие контексты из Input Context добавить (ADD). Номера битов в этих словах соответствуют DCI. Структура Input Context - универсальная для всех операций по изменению контекста устройства, и мы ее еще попользуем пару раз. В данном конкретном случае (при выдаче команды Address Device) мы должны заполнить Slot Context и контекст для EP0. В Slot Context пишем номер порта, скорость устройства, маршрут и максимальный номер контекста EP (DCI=1). В контекст EP0 пишем тип (Control), maxPacketSize (8 - мы же пока ничего не знаем о реальном maxPacketSize), количество перезапросов транзакций (рекомендуют 3), адрес Transfer Ring и начальное значение бита C для него (1). В слове ADD из Input Control Context устанавливаем в 1 биты 0 (Slot Context) и 1 (EP0). Выбираем очередной TRB в Command Ring и пишем туда команду Address Device, номер слота = Slot ID, в первые 8 байтов этого TRB пишем адрес Input Context, ставим бит C в 1 и звоним в DB0.

                                Кстати, про maxPacketSize. Как написано в этой же спецификации, для устройств LS, HS и SS существуют раз и навсегда заданные единственно разрешенные размеры пакетов для EP0. Для LS это 8 байт, для HS - 64, для SS - 512. Выяснять этот размер путем чтения 8 байтов дескриптора нужно только для устройств FS. У меня команда Address Device с maxPacketSize=8 для SS устройства возвращала код ошибки 17 (неверный контекст).

                                Контроллер сам пошлет устройству USB Request типа SET_ADDRESS. Кстати, это единственный способ присвоить адрес устройству. Если мы попытаемся самостоятельно отправить SET_ADDRESS на устройство, контроллер его заблокирует. В TRB для этой команды есть бит BSR (Block Set Address Request). Если его взвести, команда присвоения адреса не будет выдана на устройство, а слот перейдет в состояние Default. В этом состоянии можно запросить 8 байтов дескриптора устройства - как пишут, это сделано для возможности работы со старыми устройствами, которые требовали именно такой последовательности действий. Но все равно потом придется присваивать адрес устройству этой же командой (Address Device), уже с обнуленным битом BSR.

                                Ответ контроллер пришлет в Event Ring. Мы его анализируем, и если Completion Code = 1, то это означает, что слот инициализирован. То есть устройство уже адресовано (контроллер сам выбирает адрес устройства), и EP0 доступна. В Device Context запишется информация из Input Context. Состояние слота установится в Addressed, состояние EP0 - в Running. Где-то там в Slot Context появится адрес устройства, присвоенный ему контроллером.


                                После этого мы должны выяснить реальный maxPacketSize для EP0 и поправить его в Device Context. Для этого запрашиваем 8 байтов дескриптора устройства (если, конечно, не сделали это раньше).
                                Делаем TRB типа Setup в Transfer Ring для EP0. То есть на самом деле будет три TRB - первый это Setup, второй - Data Stage и третий - Status Stage. TRB типа Setup могут быть двух видов - с непосредственной информацией внутри TRB и с адресом, указывающим на внешнюю информацию. Нам нужно передать стандартный USB Request длиной всего 8 байтов, поэтому можно использовать формат с непосредственными данными. В первые 8 байт TRB записываем собственно USB Request (с полем wLength=8), устанавливаем тип TRB (TRB Type) = Setup Stage (2), устанавливаем бит IDT (Immediate Data) в 1, ставим TRB Transfer Length=8 и бит C=1. Следующий TRB - типа Data Stage, там мы пишем адрес, куда хотим принять информацию, опять же бит C=1, TRB Transfer Length=8, DIR=1 (направление передачи данных = IN), TRB Type = DataStage (3). Третий TRB - типа Status Stage - TRB Type = Status Stage (4), бит C=1, DIR = 0, IOC (Interrupt on Completion) =1 (это для того, чтобы контроллер вернул нам статус транзакции). И "звоним в звонок", то есть записываем в DB[Slot ID] 1 (для EP0 DCI всегда 1).

                                Контроллер выкинет в Event Ring TRB типа Transfer Event c кодом завершения. Если Completion Code =1, то все прошло нормально. Байт 7 (считая от 0) из полученных 8 (ну, то бишь, последний) будет содержать maxPacketSize для EP0.

                                Теперь мы должны подправить maxPacketSize для EP0 в Device Context. Используем команду Evaluate Context. Заполняем Input Context (можно взять тот, который мы подавали на Address Device, и поправить в нем maxPacketSize), его адрес записываем в TRB с командой Evaluate Context и звоним в DB0.

                                Контроллер подправит Device Context. Теперь EP0 полностью функциональна. Можно продолжать конфигурировать устройство.

                                Запрашиваем все необходимые дескрипторы, определяем класс устройства. Если устройство принадлежит к интересующему нас классу (меня, например, интересовал класс Mass Storage), то надо инициализировать bulk-endpoint'ы. Используем команду Configure Endoint, для которой опять же надо заполнять Input Context.
                                Получаем дескрипторы EP от устройства. По номерам EP вычисляем DCI. Берем Input Context и заполняем в нем контексты EP, соответствующие DCI. В Slot Context этого Input Context записываем DCI максимальной EP. Понятное дело, тут же инициализируем Transfer Ring для каждой EP. В поле ADD из Input Control Context выставляем биты, соответствующие нашим DCI, плюс бит 0 для изменения Slot Context. Формируем TRB с командой Configure Endpoint и адресом нашего Input Context и звоним в DB0.

                                При успешном завершении команды все нужные нам EP в контексте устройства будут инициализированы, а слот перейдет в состояние Configured. Я долго бился над тем, чтобы в контекстах EP появились биты Running, но так и не добился.. Может быть, потому, что моя плата работает по версии 0.96. Но все EP при этом оказались работоспособны.

                                После всего этого я выдал на устройство команду SET_CONFIGURATION, и на этом инициализация полностью закончилась. Можно передавать SCSI-команды.

                                Добавлено
                                Как обнаружить новое устройство.
                                Есть два пути. Первый - опрашивать все регистры PortSC на предмет появления в них битов CCS (Current Connect Status) или PED (Port Enabled).
                                Второй - ловить в Event Ring TRB типа Port Status Change Event.
                                Я пользовался первым. Мне не нужен hotplug, мне нужно определить, какие устройства подключены в момент инициализации. Читаем из регистра HSPARAM1 старший байт - Max Ports, при необходимости подаем питание на все порты (бит PP в PortSC), и опрашиваем все порты. Если к порту подключено не SuperSpeed устройство, то он выставит бит Connected. Надо выставить бит PR (Port Reset) и дождаться, когда он сбросится. При этом должен взвестись бит PED(Port Enabled), а в поле Port Speed появится индекс скорости устройства.
                                Дальше действуем по описанной схеме. Для команды Address Device используем номер текущего порта (номера портов начинаются с 1) и индекс скорости из поля Port Speed.
                                Если к порту подключено устройство SuperSpeed, то в PortSC сразу появится бит PED. Ресет порта делать не надо. И тогда, кажется, при инициализации еще надо делать кое-какие манипуляции со скоростью (устройства SuperSpeed работают на переменной скорости), я пока не разбирался..

                                Про прерывания.
                                Контроллер xHCI является PCI-express устройством и умеет посылать Message Signaled Interrupts (MSI-X). Я ими не пользовался.

                                Про начальную инициализацию.
                                Собственно в начале мы должны найти контроллер на шине по коду класса 0C0330h, вытащить BAR0 и BAR1 (контроллер может работать в 64-битном адресном пространстве).
                                Посмотреть, не владеет ли им BIOS и, если надо, отнять его у BIOS, сделать Reset.
                                В регистр CONFIG записать максимальное количество слотов (MaxSlots), с которыми мы хотим работать.
                                Инициализировать Command Ring и записать его адрес в CRCR (Command Ring Control Regicter).
                                Инициализировать таблицу контекстов устройств DCBAA - это таблица из (MaxSlots+1) 64-битных адресов и записать ее адрес в регистр DCBAAP.
                                Мы говорили, что нумерация слотов у контроллера начинается с 1. Нулевая ячейка DCBAA должна указывать на таблицу Scratchpad Buffers - это буферы для работы контроллера (каждый размером PAGESIZE), количество которых указывается в поле Max Scratchpad bufs регистра HCSPARAMS2. Если Max Scratchpad bufs = 0, то и DCBAA[0] = 0.
                                Инициализировать Event Ring. Как я говорил, их может быть несколько. Но можно обойтись и одним. У контроллера есть понятие Interrupter, то есть, как я понял, обработчик событий. Максимальное их количество указано в регистре HCSPARAMS1. У каждого обработчика есть свое Event Ring. Каждое это кольцо может состоять из нескольких сегментов, поэтому для того, чтобы указать контроллеру все необходимое, используется таблица сегментов... Я обошелся одним. Но все равно таблица нужна.
                                А потом можно и запустить контроллер..

                                Да, вот еще что.. Все перечисленные выше структуры должны быть выровнены в памяти по разным границам. Некоторые - на 16 байт, некоторые - на 64 и т.д. И не должны пересекать границы физических страниц памяти.. В общем, при программировании надо постоянно смотреть в спецификацию.

                                Вот, собственно, и все, что я хотел тут рассказать. Я не ставил задачей написание учебника типа Кулакова или Агурова. Просто даю общее представление о том, как устроен xHCI. Будут вопросы - отвечу, если смогу. :D
                                Сообщение отредактировано: zakharo -
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1238 ]   [ 14 queries used ]   [ Generated: 19.07.25, 03:43 GMT ]