#Start Contents
Pisanie plikow .SYS
Sterowniki w postaci plikow .SYS dziela sie na 2 rodzaje:
* Nie-DOS-owe pliki .SYS (ladowane z config.sys poleceniem
DEVICE=...) zazwyczaj zawieraja sterowniki takich urzadzen
zewnetrznych jak np. CD-ROM.
* Pliki .SYS systemu DOS - np. MSDOS.SYS czy IO.SYS. Te pliki
zawieraja sterowniki urzadzen standardowych, jak konsola CON czy
drukarka PRN.
Wszystkie te pliki laczy wspolna struktura, ktora postaram sie tutaj
przedstawic. Informacje podane przeze mnie sa wycinkiem z dokumentu
"Programmer's Technical Reference for MSDOS and the IBM PC", ktorego
kopie mozna znalezc na stronach systemu O3one (720 kB).
Pliki .SYS zaczynaja sie od adresu 0 (org 0), a naglowek takiego
pliku sklada sie z pieciu elementow:
(przeskocz elementy naglowka)
* DWORD - pelny adres (najpierw offset, potem segment) do
nastepnego takiego naglowka jak ten, jesli nasz plik .SYS
obsluguje wiecej niz jedno urzadzenie. Jesli mamy tylko jeden
sterownik w naszym pliku, wpisujemy tutaj wartosc -1, czyli
FFFF:FFFF.
* WORD - atrybut urzadzenia (opisany dalej)
* WORD - offset "procedury strategii" danego sterownika (opisane
dalej)
* WORD - offset "procedury przerwania" danego sterownika (opisane
dalej)
* 8 bajtow - nazwa (urzadzenie znakowe) dopelniana w razie potrzeby
spacjami do osmiu znakow lub ilosc jednostek (urzadzenie blokowe)
Urzadzenie znakowe to takie, ktore moze wysylac/odbierac pojedyncze
bajty, np. CON, PRN, AUX. Mozna je otwierac jak normalne pliki.
Urzadzenie blokowe to takie, ktore operuja na blokach danych i sa to
zazwyczaj dyski.
(przeskocz tabele atrybutow urzadzenia)
CAPTION: Bity atrybutu i ich znaczenie
Numer bitu Znaczenie
0 =0 - to urzadzenie nie jest standardowym urzadzeniem wejscia
=1 - to urzadzenie jest standardowym urzadzeniem wejscia
1 =0 - to urzadzenie nie jest standardowym urzadzeniem wyjscia
=1 - to urzadzenie jest standardowym urzadzeniem wyjscia
2 =0 - to urzadzenie nie jest urzadzeniem NUL
=1 - to urzadzenie jest urzadzeniem NUL
3 =0 - to urzadzenie nie jest urzadzeniem CLOCK
=1 - to urzadzenie jest urzadzeniem CLOCK
4 =0 - nalezy uzywac standardowych procedur we/wy CON
=1 - nalezy uzywac szybkich procedur we/wy ekranu (int 29h)
5-10 zarezerwowane, musza byc rowne 0
11 =0 - to urzadzenie nie obsluguje wymiennych nosnikow (domyslne dla
DOS 2.x)
=1 - to urzadzenie obsluguje wymienne nosniki (tylko dla DOS 3.0+)
12 zarezerwowane, musi byc rowny 0
13 =0 - format IBM (urzadzenia blokowe)
=1 - format nie-IBM (urzadzenia blokowe)
=1 - obsluguje funkcje zapisywania danych az do stanu zajetosci
("output till busy", urzadzenia znakowe)
14 =0 - nie obsluguje IOCTL
=1 - obsluguje IOCTL
15 =0 - urzadzenie blokowe
=1 - urzadzenie znakowe
Ostatnie pole w naglowku to nazwa urzadzenia (w przypadku urzadzen
znakowych) lub ilosc jednostek/dyskow obslugiwanych przez ten
sterownik (urzadzenia blokowe).
________________________________________________________________
"Procedura strategii" (strategy routine).
(przeskocz procedure strategii)
Za kazdym razem, jak DOS chce cos od naszego sterownika, uruchamia
procedure strategii, podajac w parze rejestrow ES:BX adres naglowka
zadania (request header). Zawiera on informacje o tym, co mamy
zrobic.
Jedynym obowiazkowym zadaniem tej procedury jest zachowanie adresu z
ES:BX w zmiennej lokalnej, aby mozna bylo potem odczytywac zadania w
procedurze przerwania, ktora uruchamiana jest zaraz po procedurze
strategii. Jesli chcemy zrobic cos wiecej, musimy zachowac wszystkie
rejestry (lacznie z flagami), ktore zmieniamy.
Procedura konczy sie wywolaniem RETF, gdyz DOS uruchamia nasz
sterownik wykonujac CALL FAR.
Tak wiec najprostszy przyklad sprowadza sie do:
mov word cs:[nagl_zad], bx ; NASM : [cs:nagl_zad]
mov word cs:[nagl_zad+2], es ; NASM : [cs:nagl_zad+2]
retf
________________________________________________________________
"Procedura przerwania" (interrupt routine).
(przeskocz procedure przerwania)
Ta procedura jest odpowiedzialna za wykonywanie polecen od systemu.
Polecenia te sa zawarte w naglowku zadania, ktory teraz omowie.
W procedurze przerwania rowniez nalezy zachowac wszystkie
modyfikowane rejestry i wrocic do DOSa poleceniem RETF. Procedura
przerwania jest uruchamiana przez DOS tuz po powrocie z procedury
strategii, ktora musi zachowac biezacy adres naglowka zadania.
(przeskocz opis naglowka zadania)
CAPTION: Naglowek zadania
Odleglosc od poczatku Dlugosc Zawartosc
0 1 bajt Dlugosc w bajtach calego naglowka i ewentualnych danych
1 1 Kod podjednostki w urzadzeniach blokowych. Nieistotne dla
urzadzen znakowych
2 1 Kod rozkazu
3 2 Status wykonania
5 8 zarezerwowane dla DOSa
0Ch rozna Dane odpowiednie dla operacji
Kod podjednostki w urzadzeniach blokowych jest istotny, gdy nasz
sterownik obsluguje wiecej niz 1 urzadzenie.
(przeskocz liste rozkazow)
CAPTION: Kod rozkazu
Kod Nazwa Funkcja
0 - INIT - Inicjalizacja sterownika. Uzywane tylko raz.
1 - MEDIA CHECK - Sprawdzanie, czy zmieniono dysk od ostatniego
sprawdzenia. Uzywane tylko w urzadzeniach blokowych. Urzadzenia
znakowe nic nie robia.
2 - BUILD BPB - Stworzenie nowego BIOS Parameter Block (BPB). Uzywane
tylko w urzadzeniach blokowych. Urzadzenia znakowe nic nie robia.
3 - IOCTL INPUT - Odczyt IOCTL. Uruchamiane tylko wtedy, gdy
urzadzenie ma ustawiony bit IOCTL.
4 - INPUT - Odczyt danych.
5 - NONDESTRUCTIVE INPUT NO WAIT - Odczyt danych.
6 - INPUT STATUS - Stan odczytu
7 - INPUT FLUSH - Oproznienie kolejki wejsciowej
8 - OUTPUT - Zapis danych.
9 - OUTPUT - Zapis danych z weryfikacja.
10 - OUTPUT STATUS - Stan zapisu
11 - OUTPUT FLUSH - Oproznienie kolejki wyjsciowej
12 - IOCTL OUTPUT - Zapis IOCTL. Uruchamiane tylko wtedy, gdy
urzadzenie ma ustawiony bit IOCTL.
13 - DEVICE OPEN - Uruchamiane tylko wtedy, gdy urzadzenie ma
ustawiony bit OPEN/CLOSE/RM.
14 - DEVICE CLOSE - Uruchamiane tylko wtedy, gdy urzadzenie ma
ustawiony bit OPEN/CLOSE/RM.
15 - REMOVEABLE MEDIA - Uruchamiane tylko wtedy, gdy urzadzenie
blokowe ma ustawiony bit OPEN/CLOSE/RM.
16 - OUTPUT UNTIL BUSY - Uruchamiane tylko wtedy, gdy urzadzenie
znakowe ma ustawiony bit 13.
Najwazniejsze rozkazy sa opisane dalej.
(przeskocz liste wynikow dzialania)
CAPTION: Status wykonania zadania
bit Znaczenie
0-7 Kod bledu, gdy bit15 = 1
8 =1 oznacza "Operacja zakonczona"
9 =1 oznacza "Urzadzenie zajete"
10-14 Zarezerwowane dla DOSa
15 =1 oznacza "blad"
(przeskocz liste bledow sterownika)
CAPTION: Znaczenie numerow bledow
numer Typ bledu
0 naruszenie ochrony przed zapisem
1 nieznana jednostka
2 urzadzenie nie jest gotowe
3 nieznana komenda
4 blad CRC
5 nieprawidlowa dlugosc struktury zadania dostepu do dysku
6 blad wyszukania (seek error)
7 nieznany nosnik
8 sektor nie znaleziony
9 koniec papieru w drukarce
10 blad zapisu
11 blad odczytu
12 blad ogolny
13 zarezerwowane
14 zarezerwowane
15 nieprawidlowa zmiana dysku
________________________________________________________________
Rozkazy
(przeskocz liste rozkazow sterownika)
* INIT.
(przeskocz rozkaz init)
ES:BX -> struktura zawierajaca naglowek zadania i dane. Ta
struktura wyglada tak:
CAPTION: Naglowek zadania
Odleglosc od poczatku Dlugosc Zawartosc
0 13 bajtow Naglowek zadania
0Dh 1 Liczba jednostek w urzadzeniach blokowych. Nieistotne dla
urzadzen znakowych
0Eh? 4 Offset i segment konca kodu naszego sterownika. Mowi DOSowi,
ile pamieci mozna zwolnic (wymieniony wczesniej dokument podaje tutaj
offset 11h, ktory nie jest prawidlowy).
12h? 4 Wskaznik na tablice BPB (nieistotne dla urzadzen znakowych) /
wskaznik na reszte argumentow (wymieniony wczesniej dokument podaje
tutaj offset 15h).
16h? 1 numer dysku (DOS 3.0+) (wymieniony wczesniej dokument podaje
tutaj offset 19h).
W czasie inicjalizacji nalezy:
1. ustawic liczbe jednostek (tylko w urzadzeniach blokowych).
Wpisac 0, jesli nie mozna uruchomic urzadzenia.
2. ustawic wskaznik na tablice BPB (tylko w urzadzeniach
blokowych)
3. wykonac czynnosci inicjalizacyjne (np. modemow, drukarek)
4. ustawic adres konca rezydentnego kodu. Wstawic CS:0, jesli
nie mozna uruchomic urzadzenia.
5. ustawic odpowiedni status w naglowku zadania
* Odczyt/Zapis (funkcje: 3, 4, 8, 9, 12, 16).
(przeskocz rozkazy odczytu i zapisu)
ES:BX -> struktura zawierajaca naglowek zadania i dane. Ta
struktura wyglada tak:
CAPTION: Naglowek zadania
Odleglosc od poczatku Dlugosc Zawartosc
0 13 bajtow Naglowek zadania
0Dh 1 Bajt deskryptora nosnika z BPB (Media Descriptor Byte)
0Eh 4 Offset i segment bufora, z ktorego dane beda odczytywane/ do
ktorego dane beda zapisywane.
12h 2 Ilosc bajtow/sektorow do zapisania/odczytania.
14h 1 Poczatkowy numer sektora (tylko urzadzenia blokowe). Nie ma
znaczenia dla urzadzen znakowych.
16h 4 Offset i segment identyfikatora napedu (volume ID), gdy
zwrocono kod bledu 0Fh.
W czasie tej operacji nalezy:
1. ustawic odpowiedni status w naglowku zadania
2. wykonac zadanie
3. ustawic rzeczywista liczbe przeniesionych bajtow/sektorow
* NONDESTRUCTIVE INPUT NO WAIT.
(przeskocz rozkaz NONDESTRUCTIVE INPUT NO WAIT)
Ten odczyt rozni sie od innych tym, ze nie usuwa odczytanych
danych z bufora.
ES:BX -> struktura zawierajaca naglowek zadania i dane. Ta
struktura wyglada tak:
CAPTION: Naglowek zadania
Odleglosc od poczatku Dlugosc Zawartosc
0 13 bajtow Naglowek zadania
0Dh 1 Bajt odczytany z urzadzenia
W czasie tej operacji nalezy:
1. zwrocic bajt odczytany z urzadzenia
2. ustawic odpowiedni status w naglowku zadania
* INPUT FLUSH
(przeskocz rozkaz INPUT FLUSH)
Wymuszenie wykonania wszystkich operacji odczytu, o ktorych wie
sterownik.
ES:BX -> naglowek zadania.
W czasie tej operacji nalezy:
1. ustawic odpowiedni status w naglowku zadania
* OUTPUT FLUSH
(przeskocz rozkaz OUTPUT FLUSH)
Wymuszenie wykonania wszystkich operacji zapisu, o ktorych wie
sterownik.
ES:BX -> naglowek zadania.
W czasie tej operacji nalezy:
1. ustawic odpowiedni status w naglowku zadania
________________________________________________________________
Przyklad
Skladajac razem powyzsze informacje, napisalem taki oto przykladowy
plik .SYS.
Jest to sterownik wymyslonego urzadzenia znakowego "MYSZKA1", ktory
obsluguje tylko funkcje INIT (oczywiscie) i "pobieranie danych" z
urzadzenia, ktore sprowadza sie do zwrocenia starego znacznika EOF
(1Ah).
Aby bylo widac, ze moj sterownik sie laduje (dzieki linii DEVICE=...
w config.sys), dorobilem kod wyswietlajacy na ekranie informacje o
ladowaniu.
Reszte zobaczcie sami:
(przeskocz przykladowy kod)
; Przyklad sterownika typu .SYS
; Autor: Bogdan D.
; kontakt: bogdandr (malpka) op (kropka) pl
;
; kompilacja:
; nasm -O999 -w+orphan-labels -o protosys.sys -f bin protosys.asm
dd 0FFFFFFFFh ; wskaznik na nastepny sterownik
; -1, bo mamy tylko 1 urzadzenie
dw 08000h ; atrybuty (urz. znakowe), output till busy (A
000)
dw strategia ; adres procedury strategii
dw przerwanie ; adres procedury przerwania
db "MYSZKA1 " ; nazwa urzadzenia (8 znakow, dopelniane spacjami)
przerwanie:
pushf
push es
push bx
push ax
les bx, [cs:request_header] ; ES:BX -> naglowek zadania
mov al, [es:bx + 2] ; kod rozkazu
test al, al ; 0 = INIT
jz .init
cmp al, 4 ; czy ktos chce czytac dane?
je .czytanie
cmp al, 5
je .czytanie2
; innych zadan nie obslugujemy
.koniec_przer:
; slowo wyniku w [es:bx+3]
mov word [es:bx + 3], 100h ; mowimy, ze wszystko zrobione
pop ax
pop bx
pop es
popf
retf
.init:
; podajemy adres konca kodu, ktory ma
; zostac w pamieci
; mozna usunac niepotrzebny juz kod
mov word [es:bx + 0eh], koniec
mov [es:bx + 10h], cs
pusha
push es
mov ah, 3 ; pobranie aktualnej pozycji kursora
xor bx, bx
int 10h ; DH, DL - wiersz, kolumna kursora
inc dh
xor dl, dl ; idziemy o 1 wiersz nizej,
; od lewej krawedzi
push cs
mov ax, 1301h ; AH=funkcja pisania na ekran.
; AL=przesuwaj kursor
mov bx, 7 ; normalne znaki (szary na czarnym)
mov cx, init1_dl ; dlugosc napisu
mov bp, init1 ; adres napisu
pop es ; segment napisu = CS
int 10h ; napis na ekran.
; DH, DL wskazuja pozycje.
pop es
popa
jmp short .koniec_przer
.czytanie: ; jak ktos chce czytac, zwracamy mu EOF
push es
push ax
push cx
push di
mov cx, [es:bx + 12h] ; liczba zadanych bajtow
les di, [es:bx + 0Eh] ; adres czytania/zapisywania
mov al, 1Ah ; 1ah = EOF
rep stosb ; zapisujemy
pop di
pop cx
pop ax
pop es
jmp short .koniec_przer
.czytanie2: ; jak ktos chce czytac, zwracamy mu EOF
mov byte [es:bx+0Dh], 1Ah
jmp short .koniec_przer
request_header dd 0 ; wskaznik na naglowek zadania
strategia:
pushf
mov [cs:request_header], bx ; zapisujemy adres naglowka zadania
mov [cs:request_header+2], es
cmp byte [cs:pierwsze], 1
jne .nie_pisz
mov byte [cs:pierwsze], 0
pusha
push es
mov ah, 3 ; pobranie aktualnej pozycji kursora
xor bx, bx
int 10h ; DH, DL - wiersz, kolumna kursora
inc dh
xor dl, dl ; idziemy o 1 wiersz nizej,
; od lewej krawedzi
push cs
mov ax, 1301h ; AH=funkcja pisania na ekran.
; AL=przesuwaj kursor
mov bx, 7 ; normalne znaki (szary na czarnym)
mov cx, info1_dl ; dlugosc napisu
mov bp, info1 ; adres napisu
pop es ; segment napisu = CS
int 10h ; napis na ekran.
; DH, DL wskazuja pozycje.
pop es
popa
.nie_pisz:
popf
retf
info1 db "*** Uruchamianie sterownika MYSZKA1...",10,13,10,13
info1_dl equ $ - info1
init1 db "*** INIT", 13, 10, 13, 10
init1_dl equ $ - init1
pierwsze db 1
; wszystko od tego miejsca zostanie wyrzucone z pamieci
koniec:
Jak widac, bylo tu o wiele wiecej opisu niz samej roboty i wcale nie
okazalo sie to takie straszne.
Aby zobaczyc, czy nasz sterownik rzeczywiscie zostal zaladowany i ile
zajmuje miejsca w pamieci, nalezy wydac polecenie mem /c/p.
Milej zabawy.
Spis tresci off-line (Alt+1)
Spis tresci on-line (Alt+2)
Ulatwienia dla niepelnosprawnych (Alt+0)
Wyszukiwarka
Podobne podstrony:
SYS TUTDOS SYS TUTSYS TUTART121 tut 2sys akw?nych dodatek aphys tut 08SYSUłamki z sys binsys i sieciphys tut 12DOS DIOD TUTdet systhe jeff dunham show 103 hdtv xvid sysART121 tut 3SYS SKR1MYSZ TUTwięcej podobnych podstron