Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Тема:Розробка драйверів ЗП ЕОМ



НЕ 1.6 (Лекція)

Тема: Розробка драйверів ЗП ЕОМ

Створення драйвера пристрою

 

Драйвер пристрою – це спеціальна програма, яка керує обміном з периферійними пристроєм, таким як принтер чи дисковий накопичувач. Оскільки параметри цих периферійних пристроїв змінюються від виробника до виробника, то різним користувачам може знадобитися декілька різних драйверів щоб він міг працювати на наявному у нього обладнанні.

 

Існує 4 способи включення драйвера пристрою в програму:

1. Можна помістити код всіх драйверів прямо в програму.

Наприклад, щоб підтримувати різні принтери, можна створити таблицю керуючих послідовностей та шукати в ній потрібний код кожного разу коли він знадобиться. Цей підхід витрачає багато пам'яті і може бути достатньо повільним.

2. Створити ряд драйверів пристроїв і вимагати, щоб програма завантажувала необхідний драйвер в якості оверлея (тобто поміщати його в область програми, спеціально залишену для цієї цілі).

3. Створити драйвер пристрою як окрему програму, котра вказується в командному файлі, виконуваному при завантажені системи. Програма завантажується та встановлює драйвер пристрою як програму обробки переривань. Після цього програма завершується, але залишається в резидентній пам'яті. Наша програма викорчовує цей драйвер через вектор переривання.

4. Створити повноцінний драйвер пристрою, який буде завантажуватися при старті за допомогою файлу CONFIG.SYS. MS DOS підтримує такий тип драйверів пристрої і одноразово завантажений він може використовувати всі можливості команд DOS, включаючи перевірку помилок. Спеціальна команда IOCTL (Контроль вводу/виводу) дозволяє програмі дізнатися про статус драйверу та посилати йому керуючу стрічку окрім звичайного потоку даних.

 

Перші три стратегії відносно легко реалізуються. Але взагалі-то драйвери є відносно складними. В четвертому підході система буде працювати з пристроєм настільки ж тісно, як з клавіатурою або дисковим накопичувачем. Пристрою може бути присвоєно ім'я, наприклад, SERIALPR для послідовного принтера, і потім цей пристрій може бути відкритим для доступу з будь-якої мови програмування. У мову Бейсік оператор OPEN "SERIALPR" FOR OUTPUT AS #2 підготує послідовний принтер для виводу. У мові асемблера Ви зможете отримати доступ до принтера як за допомогою методу керуючого блоку файлу, так і за допомогою методу дескриптора файлу, включаючи дуже потужну функцію IOCTL. При цьому користувач має можливість доступу до пристрою на рівні операційної системи і може просто ввести команду COPY: MYFILE SERIALPR:, щоб скопіювати вміст файлу на принтер.



Встановлювані драйвери пристроїв можуть бути написані тільки на мові асемблера. Вони можуть обслуговувати два типи пристроїв: символьні та блочні. Ці імена описують одиниці, якими пристрій обробляє дані. Зазвичай драйвери блокових пристроїв обслуговують дискові накопичувачі, а драйвери символьних - все решта, починаючи від послідовних принтерів і закінчуючи роботами. Блокові пристрої обмінюються блоками даних, тому вони займаються накопиченням даних. Символьні пристрої обмінюються даними побайтно, тому вони краще підходять для керуючих пристроїв, а також для пристроїв, які не можуть забезпечити високу швидкість обміну даними. Драйвери блокових пристроїв дуже складні і тут немає достатньо місця, щоб пояснити їх структуру. Дуже рідко кому потрібно написати такий драйвер. Технічний посібник з MS DOS надає всю необхідну інформацію і містить повний приклад драйвера віртуального диску в оперативній пам'яті.

Встановлювані драйвери пристроїв нещадні до програмістських помилок. Оскільки драйвери автоматично завантажуються системою при завантаженні, то неможливо використовувати налагоджувачі для виявлення причин неполадок. Тому будьте гранично уважні при їх написанні.

Програма драйвера пристрою розбивається на три частини, кожну з яких опишемо далі окремо. Це заголовок драйвера, який іменує пристрій і містить інформацію про інші частини драйверу, стратегія драйвера, яка зберігає інформацію про область даних, що створюється MS DOS, яка називається заголовком запиту, і процесор переривання пристрою, який і містить код, що керує пристроєм.

 

 

Створення заголовку драйвера

 

 

Драйвери пристроїв повинні створюватися у вигляді COM файлів. Однак вони не є справжніми програмами, оскільки у них відсутній префікс програмного сегменту. Щоб домогтися цього не треба включати оператор ORG 100H на початку програми, як це робиться для COM файлів. Або запишіть ORG 0, або взагалі нічого не пишіть. Драйвер повинен бути описаний як далека процедура, як і в будь-якій програмі. У нижчеподаному прикладі наведено початковий код для драйвера пристрою з ім'ям DEVICE12. Він замінює стандартний пристрій AUX, використовуваний MS DOS, беручи вивід функції 4 переривання 21H.

Драйвер пристрою повинен починатися з заголовка драйвера. Він має довжину 18 байтів, розділених на 5 полів. Перше поле (DD) завжди містить значення -1 (FFFFFFFFH), і коли MS DOS завантажує драйвер, то воно замінюється на стартову адресу наступного драйверу. Таким чином, система може шукати наступний драйвер по ланцюжку. У останнього завантаженого драйвера в цьому полі залишається значення -1.

Друге поле – це байт атрибутів драйвера. Мають значення тільки 7 бітів цього слова:

 

Біт

Опис

 

1=символьний пристрій, 0= блоковий пристрій

 

1=підтримує IOCTL, 0=не підтримує IOCTL

 

1=фориат блоку IBM, 0=інший формат блоку

 

1=годинник, 0=не годинник

 

1=нульовий пристрій, 0=не нульовий пристрій

 

1=пристрій стандартного виводу, 0=ні

 

1=пристрій стандартного вводу, 0=ні

 

 

Зазвичай встановлений тільки біт 15, або біти 15 і 14, якщо пристрій підтримує IOCTL. Біт 13 встановлюється тільки для блокових пристроїв. Решта бітів використовуються для заміни пристроїв, що використовуються MS DOS за замовчуванням (пристроєм стандартного вводу і виводу є клавіатура й відеодисплей; пристрій годинник об'єднує годинник реального часу з годинником часу доби BIOS; а нульовий пристрій (NULL) – це псевдоприлад, що використовується для тестових цілей).

Третє і четверте поля містять зміщення для процедур стратегії та обробки переривання. Нарешті, останнє поле містить ім'я пристрою. Ім'я може містити до 8 символів і воно має бути вирівняне по лівому краю з завершальними пробілами. Для заміни існуючих в DOS пристроїв, таких як LPT1 або COM1, використовуйте те ж ім'я пристрою, як в наступному прикладі.

 

Низький рівень.

 

В цьому прикладі створюється драйвер для послідовного пристрою. "DEVICE12" – ім'я файлу, який повинен бути зазначений у файлі конфігурації системи, щоб цей драйвер був завантажений. У байті атрибутів встановлений тільки біт 15, вказуючи що цей символьний пристрій і що він не підтримує IOCTL. DEV_STRATEGY і DEV_INTERRUPT – імена процедур. Пристрій названо AUX, з тим, щоб замінити звичайний пристрій MS DOS з цим ім'ям. Це дозволяє дуже просто звертатися до цього пристрою, оскільки система має передумовлений номер файлу для звернення до пристрою AUX (послідовному). У приклад включений початковий код для драйвера, що визначає його як COM програму.

 

 

CSEG SEGMENT PUBLIC 'CODE' ' встановлюємо кодовий сегмент

ORG 0 ' ця стрічка не обов’язкова

ASSUME CS:CSEG,DS:CSEG,ES:CSEG

DEVICE12 PROC FAR ' драйвер це далека процедура

DD 0FFFFFFFFH ' адреса наступного драйвера

DW 8000H ' байт атрибутів

DW DEV_STATEGY ' адреса процедури стратегії

DW DEV_INTERRUPT ' адреса процедури переривання

DB 'AUX ' ' ім’я пристрою (доповнене пробілами)

 

Створення стратегії пристрою

 

Процедура стратегії пристрою вимагає тільки п'яти рядків. Коли система завантажує пристрій, то вона створює блок даних, названий заголовком запиту. Він має дві функції. По-перше він служить областю даних для внутрішніх операцій системи. Більш важливо те, що заголовок запиту служить областю, через яку відбувається обмін інформацією між драйвером і викликаючою його програмою. Наприклад, коли драйвер виводить дані, то йому дається адреса даних через заголовок запиту. Коли ж драйвер завершує свою роботу, то він встановлює в заголовку запиту байт статусу, який доступний викликаючій програмі, тим самим даючи можливість їй дізнатися про помилку.

MS DOS створює заголовок запиту при установці драйвера пристрою (коли система завантажується). Процедура стратегії пристрою виконується тільки один раз в цей момент. При цьому ES: BX вказують на новостворений заголовок запиту та процедурі потрібно просто скопіювати їх, щоб згодом він міг бути виявлений при зверненні до драйвера. Адреси зсуву і сегмента заголовка поміщаються у дві змінні. При зверненні до драйвера, перше що він робить – відновлює значення ES: BX, щоб можна було отримати інформацію із заголовка запиту.

Розмір заголовка запиту може змінюватися, залежно від типу зробленого запиту до драйвера (напр. ініціалізація, вивід даних або повернення статусу). Проте перші 13 байт заголовка завжди одні і ті ж. Їх формат такий:

 

1. Довжина заголовка запиту (DB).

2. Код пристрою (DB). Визначає номер для блокових пристроїв.

3. Код команди (DB). Тут зберігається номер останньої надісланої драйверу команди.

4. Статус (DW). Статус встановлюється кожен раз при виклику драйвера. Якщо встановлено біт 15, то в молодших восьми бітах знаходиться код помилки.

5. Резервна область (8 байтів). Використовується MS DOS.

6. Дані необхідні для роботи драйвера (змінної довжини).

 

Низький рівень.

 

Ось 5 рядків процедури стратегії пристрою. Відзначимо, що дві DW змінні, що зберігають значення ES і BX, слідують за інструкцією RET, як і належить у форматі COM.

 

DEV_STRATEGY: MOV CS: KEEP_ES, ES

MOV CS: KEEP_BX, BX

RET

KEEP_CS DW?

KEEP_BX DW?

 

 

Створення обробника переривань пристрою

 

Драйвер пристрою починається з двох частин коду, наведених у попередніх розділах. За ними повинна слідувати відповідна процедура обробки переривання. Насправді, це невірно, називати цю процедуру процедурою обробки переривання, так як вона зовсім не обслуговує переривання і завершується звичайної інструкцією RET.

Є 13 типів функцій, які може виконувати встановлений драйвер пристрою. Коли драйвер викликається функцією DOS (скажімо функцією 3Fh переривання 21H, яка читає дані з файлу або пристрою), то функція поміщає кодовий номер від 1 до 13 у однобайтне поле по зміщенню 2 в заголовку запиту (для вводу – кодовий номер 5). Потім управління передається процедурі обробки переривання драйвера, адреса якої визначається при перегляді заголовку драйвера. Ця процедура в першу чергу відновлює ES: BX, з тим щоб вони вказували на заголовок запиту, а потім читає кодовий номер команди. З цього коду процедура обробки переривання викликає потрібну процедуру, яка виконає потрібну функцію. Процедура шукається за допомогою 13-слівної таблиці, яка містить зміщення для 13 типів функцій.

Опції завжди перераховуються у такому порядку:

 

1. Ініціалізації (ініціалізація)

2. CHECK_MEDIA (перевірка носія)

3. MAKE_BPB

4. IOCTL_IN

5. INPUT_DATA (ввід даних)

6. NONDESTRUCT_IN

7. INPUT_STATUS (статус вводу)

8. CLEAR_INPUT (очищення вводу)

9. OUTPUT_DATA (вивід даних)

10. OUTPUT_VERIFY (перевірка виводу)

 

 

11. OUTPUT_STATUS (статус виводу)

12. CLEAR_OUTPUT (очищення виводу)

13. IOCTL_OUT

 

Після завершення процедури, процедура обробки переривання завершується інструкцією RET і управління повертається в викликаючу програму. Драйвер пристрою може включати код для обробки тільки деяких функцій, в залежності від пристрою і ступеня контролю помилок який вимагається і управління пристроєм. Номери функцій, для яких не написані процедури, повинні завершуватися виходом з драйвера без виконання чого-небудь. У цьому випадку треба тільки перед виходом встановити біти 15, 8, 1 і 0 в заголовку запиту, щоб інформувати викликаючу задачу, що була затребувана неіснуюча функція (біт 15 відображає помилку, біт 8 показує, що драйвер працює нормально, а біти 0 і 1 дають код3 помилки, що відповідає "невідомій команді").

Але одна функція повинна бути присутня у всіх драйверах пристроїв, і це функція номер 1 – ініціалізація. Ця функція автоматично виконується при завантаженні драйвера. Одна з важливих задач, виконувана цією процедурою, складається в встановленні адреси кінця драйвера в чотирьох байтах, що починаються зі зміщення 14 в заголовку запиту. У нижчеподаному прикладі кінець програми відзначений міткою eop:. Крім цієї задачі, процедура ініціалізації повинна також виконати всю необхідну для цього пристрою ініціалізацію.

Які з решти 12-ти функцій будуть включені в драйвер пристрою залежить від того, що драйвер повинен робити. Деякі, такі як CHECK_MEDIA і MAKE_BPB, відносяться тільки до блокових пристроїв (вони встановлюють тип диска, розмір секторів і т.д.). Для символьних пристроїв найбільш важливими є дві функції: INPUT_DATA і OUTPUT_DATA (відзначимо, що ці імена неважливі – важлива позиція в таблиці функцій, яка незмінна).

В обох випадках заголовок запиту має наступну структуру:

 

13 байтів стандартний формат заголовка запиту

1 байт – байт опису середовища (тільки для блокових пристроїв)

4 байти зміщення / сегмент буфера обміну даних

2 байти число байтів, яке треба передати

2 байти стартовий номер сектора (тільки для блокових)

 

У нижчеподаному прикладі використовується функція виводу. Процедура, що виконує вивід, отримує із заголовка запиту адресу буфера, в якому знаходяться дані що виводяться (зміщення 14). Вона також зчитує число байтів, яке треба вивести (зміщення 18). Коли процедура завершить виведення даних, то вона встановить слово статусу в заголовку запиту (зміщення 3) і поверне керування. Якщо операція успішна, то треба встановити біт 8 слова статусу.

Низький рівень.

 

В даному прикладі наведена загальна форма процедури обробки переривання, не включаючи реального коду, керуючого пристроєм.

 

DEV_INTERRUPT: PUSH ES;зберігаємо регістри

PUSH DS

PUSH AX

PUSH BX

PUSH CX

PUSH DX

PUSH SI

PUSH DI

PUSH BP

MOV AX,CS:KEEP_ES;ES:BX вказують на заголовок запиту

MOV ES,AX;

MOV BX,CS:KEEP_BX;

MOV AL,ES:[BX]+2;отримуємо код команди з заголовку

SHL AL,1;множимо на 2

SUB AH,AH;занулюємо AH

LEA DI,FUNCTIONS;DI вказує на зміщення до таблиці

ADD DI,AX;додаємо зміщення в таблиці

JMP WORD PTR [DI];переходимо на адресу з таблиці

 

FUNCTIONS LABEL WORD;це таблиця функцій

DW INITIALIZE

DW CHECK_MEDIA

DW MAKE_BPB

DW IOCTL_IN

DW INPUT_DATA

DW NONDESTRUCT_IN

DW INPUT_STATUS

DW CLEAR_INPUT

DW OUTPUT_DATA

DW OUTPUT_VERIFY

 

DW OUTPUT_STATUS

DW CLEAR_OUTPUT

DW IOCTL_OUT

 

;--вихід з драйверу, якщо функція не підтримується

CHECK_MEDIA:

MAKE_BPB:

IOCTL_IN:

INPUT_DATA:

NONDESTRUCT_IN:

INPUT_STATUS:

CLEAR_INPUT:

OUTPUT_VERIFY:

OUTPUT_STATUS:

CLEAR_OUTPUT:

IOCTL_OUT:

OR ES:WORD PTR [BX]+3,8103H;модифікуємо статус

JMP QUIT

 

;--процедури для двох підтримуваних кодів

INITIALIZE: LEA AX,E_O_P;зміщення кінця програми в AX

MOV ES:WORD PTR [BX]+14,AX;поміщуємо його в заголовок

MOV ES:WORD PTR [BX]+16,CS;

.

(тут йде ініціалізація пристрою)

.

JMP QUIT

 

OUTPUT_DATA: MOV CL,ES:[BX]+18;отримуємо число символів

CBW CX;CX використовуємо як лічильник

MOV AX,ES:[BX]+16;отримуємо адресу буферу даних

MOV DS,AX;

MOV DX,ES:[BX]+14;

.

(тут йдуть операції по виводу)

.

JMP QUIT

 

;--виходимо, модифікуючи байт статусу в заголовку запиту

QUIT: OR ES:WORD PTR [BX]+3,100H;встановлюємо біт 8

POP BP;відновлюємо регістри

POP DI;

POP SI;

POP DX;

POP CX;

POP BX;

POP AX;

POP DS;

POP ES;

RET

E_O_P:;мітка кінця програми

DEVICE12 ENDP

CSEG ENDS

END DEVICE12

 

Перед поверненням драйвер встановлює слово статусу в заголовку запиту. У даному прикладі це робиться в двох місцях, в залежності від того чи викликалася забезпечувана драйвером функція чи ні. Ці рядки виглядають так: OR ES: WORD PTR [BX] +3, XXXXH. Значення бітів XXXX наступне:

 

біти 0-7 код помилки (якщо біт 15 = 1)

8 біт встановлюється в 1, коли функція завершена

9 біт встановлюється в 1, коли драйвер зайнятий

біти 10-14 зарезервовані MS DOS

15 біт встановлюється в разі виникнення помилки

 

Молодший байт цього слова містить наступні коди помилок, якщо встановлений біт 15, ідентифікуючий помилку:

 

0 спроба запису на захищений від запису пристрій

1 невідомий пристрій

2 пристрій не готовий

3 невідома команда

4 помилка перевірки за контрольною сумою

5 невірна довжина запиту до пристрою

6 помилка пошуку

7 невідомий носій

8 сектор не знайдений

9 нема паперу в принтері

А помилка запису

B помилка читання

C загальна помилка

 


Дата добавления: 2015-08-27; просмотров: 44 | Нарушение авторских прав




<== предыдущая лекция | следующая лекция ==>
Тема:Робота з драйвером маніпулятора «миша» | Не осуждайте нас://ficbook.net/readfic/1668977 1 страница

mybiblioteka.su - 2015-2024 год. (0.035 сек.)