/*++ Copyright (c) 2003 Aleksandrov O.E. All rights Reserved Copyright (c) 2003 Ђ«ҐЄc ­¤а®ў Ћ.…. All rights Reserved Module Name: FuncMi1201.h Abstract: Дополнительные функции для MI1201-AGM Port I/O Driver ******************************************************** --*/ #include "Funcmi1201.h" //-------------------------------------------------------- // Разрешение ВЫГРУЗКИ СТРАНИЦ на диск (paging) #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, InitTranslatedPortInfo) #endif void InitTranslatedPortInfo( // Инициализирует структуру tTransPortInfo начальными значениями IN OUT tTransPortInfo *PortInfo, IN ULONG ulRangeCount // количество инициализируемых диапазонов ) { ULONG i; PAGED_CODE(); PortInfo->RangeCount = ulRangeCount; PortInfo->UsedRangeCount = 0; for( i=0; i < ulRangeCount; i++) { PortInfo->Range[i].PortFirst = 0; PortInfo->Range[i].PortCount = 0; PortInfo->Range[i].PortMemoryType = CmResourceTypePort; PortInfo->Range[i].PortWasMapped = FALSE; } } //-------------------------------------------------------- // Разрешение ВЫГРУЗКИ СТРАНИЦ на диск (paging) #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, InitInitialPortInfo) #endif void InitInitialPortInfo( // Инициализирует структуру tInitialPortInfo начальными значениями IN OUT tInitialPortInfo *PortInfo, IN ULONG ulRangeCount // количество инициализируемых диапазонов ) { ULONG i; PAGED_CODE(); PortInfo->RangeCount = ulRangeCount; PortInfo->UsedRangeCount = 0; for( i=0; i < ulRangeCount; i++) { PortInfo->Range[i].PortFirst = 0; PortInfo->Range[i].PortLast = 0; PortInfo->Range[i].TranslatedRangeNumber = 0; } } //-------------------------------------------------------- #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, AddTranslatedPortInfo) #endif LONG AddTranslatedPortInfo( // Добавление диапазона в структуру tTransPortInfo IN OUT tTransPortInfo *PortInfo, IN PVOID PortFirst, // адрес первого порта диапазона (PVOID, потому что MmMapIoSpace возвращает PVOID) IN ULONG PortCount, // число портов в диапазоне. IN ULONG PortMemoryType, // HalTranslateBusAddress MemoryType IN BOOLEAN PortWasMapped // If TRUE, we have to unmap on unload ) // возвращает: // Номер добавленного элемента; // 0 - если места нет; // -1 - если неверные значения параметров; { ULONG i; PAGED_CODE(); if(PortCount <= 0) { return -1; } else if(PortInfo->UsedRangeCount >= PortInfo->RangeCount) { return 0; } else { i = PortInfo->UsedRangeCount; PortInfo->UsedRangeCount = PortInfo->UsedRangeCount+1; PortInfo->Range[i].PortFirst = PortFirst; PortInfo->Range[i].PortCount = PortCount; PortInfo->Range[i].PortMemoryType = PortMemoryType; PortInfo->Range[i].PortWasMapped = PortWasMapped; return i; } } //-------------------------------------------------------- LONG AddInitialPortInfo( // Добавление диапазона в структуру tInitialPortInfo IN OUT tInitialPortInfo *PortInfo, IN ULONG PortFirst, // адрес первого порта диапазона IN ULONG PortCount // число портов в диапазоне. ); #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, AddInitialPortInfo) #endif LONG AddInitialPortInfo( // Добавление диапазона в структуру tInitialPortInfo IN OUT tInitialPortInfo *PortInfo, IN ULONG PortFirst, // адрес первого порта диапазона IN ULONG PortCount // число портов в диапазоне. ) // возвращает: // Номер добавленного элемента; // 0 - если места нет; // -1 - если неверные значения параметров; { ULONG i; PAGED_CODE(); if(PortCount <= 0) { return -1; } else if(PortInfo->UsedRangeCount >= PortInfo->RangeCount) { return 0; } else { i = PortInfo->UsedRangeCount; PortInfo->UsedRangeCount = PortInfo->UsedRangeCount+1; PortInfo->Range[i].PortFirst = PortFirst; PortInfo->Range[i].PortLast = PortInfo->Range[i].PortFirst+PortCount-1; PortInfo->Range[i].TranslatedRangeNumber= i; return i; } } //-------------------------------------------------------- int CompareInitialRangeAndPort( // Проверка принадлежности порта диапазону IN tInitialPortRange *PortRange, // диапазон IN ULONG Port // адрес порта ); #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, CompareInitialRangeAndPort) #endif int CompareInitialRangeAndPort( // Проверка принадлежности порта диапазону IN tInitialPortRange *PortRange, // диапазон IN ULONG Port // адрес порта ) // возвращает: // -1 - Порт до диапазона (перед нижней границей); // 0 - Порт в диапазоне; // 1 - Порт после диапазона (за верхней границей); { if(Port < PortRange->PortFirst) { return -1; } else if(PortRange->PortLast < Port ) { return 1; } else { return 0; } } //-------------------------------------------------------- #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, CompareInitialPortInfoAndPort) #endif LONG CompareInitialPortInfoAndPort( // Проверка принадлежности порта списку диапазонов IN tInitialPortInfo *PortInfo, // УПОРЯДОЧЕННЫЙ ПО ВОЗРАСТАНИЮ список диапазонов IN ULONG Port // адрес порта ) // возвращает: // -2 - В списке нет диапазонов; // -1 - Порт не попадает ни в один диапазон из списока портов; // n - Порт в диапазоне n; { LONG IndexFirst; LONG IndexLast; ULONG IndexMiddle; LONG CmpResult; if (PortInfo->UsedRangeCount <= 0){ // нельзя искать в пустом списке return -2; }; // поиск методом деляния отрезка пополам IndexFirst = 0; // левая граница IndexLast = PortInfo->UsedRangeCount-1; // правая граница while(IndexFirst<=IndexLast){ IndexMiddle = (IndexFirst+IndexLast) >> 1; CmpResult = CompareInitialRangeAndPort(&PortInfo->Range[IndexMiddle], Port); if (CmpResult == 0) { // нашли диапазон return IndexMiddle; } else if (CmpResult > 0) { // порт за диапазоном IndexFirst = IndexMiddle+1; } else { // порт перед диапазоном IndexLast = IndexMiddle-1; } } return -1; } //-------------------------------------------------------- int CompareInitialRanges( // Сравнение диапазонов IN tInitialPortRange *PortRange1, IN tInitialPortRange *PortRange2 ); #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, CompareInitialRanges) #endif // возвращает: // 1 - PortRange1>PortRange2; // 0 - PortRange1=PortRange2; // -1 - PortRange1PortFirst < PortRange2->PortFirst) { return -1; } else if(PortRange1->PortFirst > PortRange2->PortFirst) { return 1; } else if(PortRange1->PortLast < PortRange2->PortLast) { return -1; } else if(PortRange1->PortLast > PortRange2->PortLast) { return 1; } else { return 0; } } //-------------------------------------------------------- ULONG FindRangePlace( // поиск места для вновь добавленного диапазона в списке. IN OUT tInitialPortInfo *PortInfo ); #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, FindRangePlace) #endif ULONG FindRangePlace( // поиск места для вновь добавленного диапазона в списке. IN OUT tInitialPortInfo *PortInfo ) { ULONG IndexFirst; ULONG IndexLast; ULONG IndexMiddle; ptInitialPortRange PtrNewRange; PAGED_CODE(); if (PortInfo->UsedRangeCount <= 1){ // нельзя сортировать список из 1 диапазона return 0; } // поиск методом деления отрезка пополам IndexFirst = 0; // левая граница IndexLast = PortInfo->UsedRangeCount-1; // правая граница PtrNewRange = &PortInfo->Range[IndexLast]; // добавленный диапазон while(IndexFirst> 1; if (CompareInitialRanges(&PortInfo->Range[IndexMiddle], PtrNewRange)>0) { IndexLast = IndexMiddle; } else { IndexFirst = IndexMiddle+1; } } return IndexLast; } //-------------------------------------------------------- #ifdef ALLOC_PRAGMA // насколько я понял при запуске BUILD это ОПРЕДЕЛЕНО #pragma alloc_text (PAGE, AddInitialPortInfoAscending) #endif LONG AddInitialPortInfoAscending( // Добавление диапазона в структуру tPortInfo с упорядочением по возрастанию IN OUT tInitialPortInfo *PortInfo, IN ULONG PortFirst, // адрес первого порта диапазона IN ULONG PortCount // число портов в диапазоне. ) // возвращает: // Номер добавленного элемента (после упорядочения); // 0 - если места нет; // -1 - если неверные значения параметров; { LONG j; PAGED_CODE(); // добавляем диапазон j = AddInitialPortInfo(PortInfo, PortFirst, PortCount); // если больше 1 диапазона в списке if(j > 0) { tInitialPortRange tmp; ULONG k,i,n; // ищем место нового диапазона в упорядоченном списке i = FindRangePlace(PortInfo); n = PortInfo->UsedRangeCount - 1; // если место нового диапазона в упорядоченном списке не совпадает с текущим if (i != n) { // перемещаем новый диапазон на место tmp = PortInfo->Range[n]; // запомнили диапазон // переместили остальные диапазоны к концу списка for (k=n; k>i; k--){ PortInfo->Range[k] = PortInfo->Range[k-1]; } // переместили новый диапазон на место PortInfo->Range[i] = tmp; } return i; } else { return j; } } //--------------------------------------------------------