Blog:Ovládač pre komunikáciu s PMD 32

Z PMD 85 Infoserver

(Rozdiel medzi revíziami)
Rombor (Diskusia | príspevky)
D (Opravený preklep; pridaný download link)
Aktuálna verzia (10:02, 22. október 2023) (upraviť) (vrátiť)
Rombor (Diskusia | príspevky)
(Opravené preklepy a doplnená diakritika)
 
Riadok 3: Riadok 3:
[[PMD 85#PMD 85-3|PMD 85-3]] obsahuje vo svojej EPROM, na rozdiel od predošlých verzií PMD 85, ovládač pre disketovú jednotku [[PMD 32]]. Keďže sa ukázalo, že [[Blog:Postavte_si_PMD_32-SD|PMD 32-SD]], teda náhradu za PMD 32, by si chceli niektorí pripojiť aj k iným počítačom (SAPI, IQ-151), uvediem tu výpis tohto ovládača, aby si ho záujemci mohli prispôsobiť pre svoj počítač. Ovládač nie je úplnou kópiou z PMD 85-3, ale je naopak optimalizovaný a skrátený. Zároveň ale neobsahuje implementáciu všetkých povelov, ktoré PMD 32, či PMD 32-SD poskytujú, pretože to ani nie je účelné. Verím, že prípadný záujemca si ďalšie povely bez problémov doplní sám.
[[PMD 85#PMD 85-3|PMD 85-3]] obsahuje vo svojej EPROM, na rozdiel od predošlých verzií PMD 85, ovládač pre disketovú jednotku [[PMD 32]]. Keďže sa ukázalo, že [[Blog:Postavte_si_PMD_32-SD|PMD 32-SD]], teda náhradu za PMD 32, by si chceli niektorí pripojiť aj k iným počítačom (SAPI, IQ-151), uvediem tu výpis tohto ovládača, aby si ho záujemci mohli prispôsobiť pre svoj počítač. Ovládač nie je úplnou kópiou z PMD 85-3, ale je naopak optimalizovaný a skrátený. Zároveň ale neobsahuje implementáciu všetkých povelov, ktoré PMD 32, či PMD 32-SD poskytujú, pretože to ani nie je účelné. Verím, že prípadný záujemca si ďalšie povely bez problémov doplní sám.
-
PMD 32, resp. PMD 32-SD komunikuje s nadradeným počítačom prostredníctvom obojsmerného paraleného kanála, ktorý je na strane počítača tvorený interfejsovým obvodom PPI 8255.
+
PMD 32, resp. PMD 32-SD komunikuje s nadradeným počítačom prostredníctvom obojsmerného paralelného kanála, ktorý je na strane počítača tvorený interfejsovým obvodom PPI 8255.
Z 8255 sa využíva iba port PA v móde 2 ako 8 bitová obojsmerná dátová zbernica a 4 riadiace bity hornej polovice portu PC pre handshake. Stav zbernice sa ale testuje 3. bitom portu PC (INTRA), ktorý podľa zvoleného smeru prenosu indikuje, či je na zbernici platný byte (vstup dát), alebo bol byte perifériou prečítaný (výstup dát). Smer prenosu dát sa volí povolením alebo zakázaním prerušenia (signál INTRA) pre vstup alebo výstup dát.
Z 8255 sa využíva iba port PA v móde 2 ako 8 bitová obojsmerná dátová zbernica a 4 riadiace bity hornej polovice portu PC pre handshake. Stav zbernice sa ale testuje 3. bitom portu PC (INTRA), ktorý podľa zvoleného smeru prenosu indikuje, či je na zbernici platný byte (vstup dát), alebo bol byte perifériou prečítaný (výstup dát). Smer prenosu dát sa volí povolením alebo zakázaním prerušenia (signál INTRA) pre vstup alebo výstup dát.
Riadok 9: Riadok 9:
Ovládač potrebuje niekde v RAM 4 premenné:
Ovládač potrebuje niekde v RAM 4 premenné:
-
Drive: DS 1 ; cislo disku 0 = A:, 1 = B:, 2 = C:, 3 = D:
+
Drive: DS 1 ; číslo disku 0 = A:, 1 = B:, 2 = C:, 3 = D:
-
Sector: DS 1 ; cislo sektora 0 az N (N je max. 63)
+
Sector: DS 1 ; číslo sektora 0 N (N je max. 63)
-
Track: DS 1 ; cislo stopy 0 az N (N je max. 255)
+
Track: DS 1 ; číslo stopy 0 N (N je max. 255)
-
Dma: DS 2 ; cielova/zdrojova adresa pre citanie/zapis sektora
+
Dma: DS 2 ; cieľová/zdrojová adresa pre čítanie/zápis sektora
Základná komunikácia na najnižšej úrovni zahŕňa niekoľko elementárnych rutín:
Základná komunikácia na najnižšej úrovni zahŕňa niekoľko elementárnych rutín:
* '''Nastavenie smeru prenosu a test, či je na vstupe platný byte, alebo či bol perifériou byte prečítaný'''
* '''Nastavenie smeru prenosu a test, či je na vstupe platný byte, alebo či bol perifériou byte prečítaný'''
-
Tieto rutiny sú volané ostanými rutinami, pre čítanie a zápis bytu atď., takže pri vytváraní rutín vyšších úrovní ich zrejme nebude treba volať.
+
Tieto rutiny sú volané ostatnými rutinami, pre čítanie a zápis bytu atď., takže pri vytváraní rutín vyšších úrovní ich zrejme nebude treba volať.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Povoli prerusenie pre vstup na porte A
+
; Povolí prerušenie pre vstup bytu na porte A
; I: -
; I: -
-
; O: povolene prerusenie pre vstup bytu
+
; O: povolené prerušenie pre vstup bytu
; M: A
; M: A
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
EnaByteIn:
EnaByteIn:
-
MVI A,09h ; 1->C4 povolenie prerusovacieho signalu INTRA
+
MVI A,09h ; 1->C4 povolenie prerušovacieho signálu INTRA
-
OUT PIO_CW ; pre vstup na porte A
+
OUT PIO_CW ; pre vstup bytu na porte A
-
MVI A,0Ch ; 0->C6 zakazanie prerusovacieho signalu INTRA
+
MVI A,0Ch ; 0->C6 zakázanie prerušovacieho signálu INTRA
-
OUT PIO_CW ; pre vystup porte A
+
OUT PIO_CW ; pre výstup bytu na port A
RET
RET
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Povoli prerusenie pre vystup portu A
+
; Povolí prerušenie pre výstup bytu na porte A
; I: -
; I: -
-
; O: povolene prerusenie pre vystup bytu
+
; O: povolené prerušenie pre výstup bytu
; M: A
; M: A
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
EnaByteOut:
EnaByteOut:
-
MVI A,08h ; 0->C4 zakazanie prerusovacieho signalu INTRA
+
MVI A,08h ; 0->C4 zakázanie prerušovacieho signálu INTRA
-
OUT PIO_CW ; pre vstup na porte A
+
OUT PIO_CW ; pre vstup bytu na porte A
-
MVI A,0Dh ; 1->C6 povolenie prerusovacieho signalu INTRA
+
MVI A,0Dh ; 1->C6 povolenie prerušovacieho signálu INTRA
-
OUT PIO_CW ; pre vystup na porteA
+
OUT PIO_CW ; pre výstup bytu na port A
RET
RET
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Zisti, ci je nastavene INTRA. Na INTRA sa caka zvoleny cas.
+
; Zistí, či je nastavené INTRA. Na INTRA sa čaká zvolený čas.
-
; INTRA=1, ak je platny byte na vstupe, alebo bol precitany byte z vystupu.
+
; INTRA=1, ak je platný byte na vstupe, alebo bol prečítaný byte z výstupu.
-
; I: Pri volani od IsIntraD DE=timeout
+
; I: Pri volaní od IsIntraD DE=timeout
; O: CY=1 - timeout
; O: CY=1 - timeout
; CY=0 - OK
; CY=0 - OK
Riadok 56: Riadok 56:
LXI D,205 ; timeout asi 5ms
LXI D,205 ; timeout asi 5ms
IsIntraD:
IsIntraD:
-
PUSH PSW ; uloz AF
+
PUSH PSW ; ulož AF
IsIntra2:
IsIntra2:
IN PIO_C ; zisti stav INTRA
IN PIO_C ; zisti stav INTRA
ANI 8
ANI 8
-
JNZ IsIntra3 ; ak je INTRA=1, skoc dopredu
+
JNZ IsIntra3 ; ak je INTRA=1, skoč dopredu
DCX D
DCX D
MOV A,D
MOV A,D
ORA E
ORA E
-
JNZ IsIntra2 ; a ak nie je nulove, vrat sa do slucky
+
JNZ IsIntra2 ; a ak nie je nulové, vráť sa do slučky
-
POP PSW ; doslo k timeoutu, obnov AF
+
POP PSW ; došlo k timeoutu, obnov AF
-
STC ; nastav CY ako priznak chyby
+
STC ; nastav CY ako príznak chyby
RET
RET
IsIntra3:
IsIntra3:
-
POP PSW
+
POP PSW ; obnov AF
ORA A ; vynuluj CY
ORA A ; vynuluj CY
RET
RET
* '''Čítanie bytu'''
* '''Čítanie bytu'''
-
Pred volaním tejto rutiny musí byť povolený vstup bytu volaním rutiny <tt>EnaByteIn</tt>. Rutina priebežne modifikuje CRC, ktoré sa prenáša v registri B.
+
Pred volaním tejto rutiny musí byť povolený vstup bytu volaním rutiny {{Kbd|EnaByteIn}}. Rutina priebežne modifikuje CRC, ktoré sa prenáša v registri B.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Precita byte z PMD 32 a zaroven modifikuje CRC.
+
; Prečíta byte z PMD 32 a zároveň modifikuje CRC.
; I: B=priebežné CRC
; I: B=priebežné CRC
; O: CY=1 - chyba
; O: CY=1 - chyba
-
; CY=0 - A=C=precitany byte, B=modifikovane CRC
+
; CY=0 - A=C=prečítaný byte, B=modifikované CRC
; M: AF, BC
; M: AF, BC
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
ReadByte:
ReadByte:
-
PUSH D ; DE na zasobnik
+
PUSH D ; DE na zásobník
-
CALL IsIntra ; je platny byte na vstupe?
+
CALL IsIntra ; je platný byte na vstupe?
POP D ; obnov DE
POP D ; obnov DE
-
RC ; nie, vrat sa s chybou
+
RC ; nie, vráť sa s chybou
-
IN PIO_A ; precitaj byte
+
IN PIO_A ; prečítaj byte
-
MOV C,A ; odloz si ho do C
+
MOV C,A ; odlož si ho do C
XRA B ; modifikuj CRC
XRA B ; modifikuj CRC
-
MOV B,A ; a uloz ho naspat do B
+
MOV B,A ; a ulož ho naspäť do B
-
MOV A,C ; vrat nacitany byte do A
+
MOV A,C ; vráť načítaný byte do A
RET
RET
* '''Odoslanie bytu a povelu'''
* '''Odoslanie bytu a povelu'''
-
Pred volaním rutiny <tt>SendByte</tt> musí byť povolený výstup bytu volaním rutiny <tt>EnaByteOut</tt>. Rutina priebežne modifikuje CRC, ktoré sa prenáša v registri B.
+
Pred volaním rutiny {{Kbd|SendByte}} musí byť povolený výstup bytu volaním rutiny {{Kbd|EnaByteOut}}. Rutina priebežne modifikuje CRC, ktoré sa prenáša v registri B.
-
Rutina <tt>SendCommand</tt> slúži pre odoslanie povelu. Táto rutina najprv volaním rutiny <tt>IsPresent</tt> preveruje, či náhodou nie je na zbernici prezentačný byte, ktorý posiela PMD 32, keď je "v kľude". Pokiaľ na zbernici prezentačný byte nie je, povolí sa výstup bytu a povel sa odošle. Inak sa najprv napsäť odošle prezentačný byte a následne samotný povel. Rutina pred odoslaním povelu inicializuje CRC.
+
Rutina {{Kbd|SendCommand}} slúži pre odoslanie povelu. Táto rutina najprv volaním rutiny {{Kbd|IsPresent}} preveruje, či náhodou nie je na zbernici prezentačný byte, ktorý posiela PMD 32, keď je "v kľude". Pokiaľ na zbernici prezentačný byte nie je, povolí sa výstup bytu a povel sa odošle. Inak sa najprv naspäť odošle prezentačný byte a následne samotný povel. Rutina pred odoslaním povelu inicializuje CRC.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Posle povel do PMD 32. Pred poslanim povelu sa najprv preveri, ci na zbernici
+
; Pošle povel do PMD 32. Pred poslaním povelu sa najprv preverí, či na zbernici
-
; nahodou nie je prezentacny byte.
+
; náhodou nie je prezentačný byte.
; I: A=povel
; I: A=povel
; O: CY=1 - chyba
; O: CY=1 - chyba
-
; CY=0 - OK, B=A=modifikovane CRC
+
; CY=0 - OK, B=A=modifikované CRC
; M: AF, B
; M: AF, B
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
SendCommand:
SendCommand:
-
MOV B,A ; uloz posielany byte do B
+
MOV B,A ; ulož posielaný povelový byte do B
-
PUSH B ; BC, DE na zasobnik
+
PUSH B ; BC, DE na zásobník
PUSH D
PUSH D
-
CALL IsPresent ; zisti, ci je na zbernici prezentacny byte 0AAh
+
CALL IsPresent ; zisti, či je na zbernici prezentačný byte 0AAh
-
; ak ano, odosli naspat prezentacny byte
+
; ak áno, odošli naspäť prezentačný byte
POP D
POP D
POP B ; obnov DE, BC
POP B ; obnov DE, BC
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
-
MOV A,B ; vrat posielany byte do A
+
MOV A,B ; vráť posielaný povelový byte do A
MVI B,0 ; vynuluj CRC
MVI B,0 ; vynuluj CRC
-
; pokracuj dalej
+
; pokračuj ďalej
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Posle byte do PMD 32 a modifikuje priebezne CRC.
+
; Pošle byte do PMD 32 a modifikuje priebežné CRC.
-
; I: A=posielany byte, B=priebezne CRC
+
; I: A=posielaný byte, B=priebežné CRC
; O: CY=1 - chyba
; O: CY=1 - chyba
-
; CY=0 - OK, B=A=modifikovane CRC
+
; CY=0 - OK, B=A=modifikované CRC
; M: AF, B
; M: AF, B
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
SendByte:
SendByte:
-
PUSH D ; DE na zasobnik
+
PUSH D ; DE na zásobník
-
CALL IsIntra ; zisti, ci je volny vystup
+
CALL IsIntra ; zisti, či je voľný výstup
POP D ; obnov DE
POP D ; obnov DE
-
RC ; vrat sa, ak doslo ku timeoutu
+
RC ; vráť sa, ak došlo ku timeoutu
-
OUT PIO_A ; posli byte na vystup
+
OUT PIO_A ; pošli byte na výstup
-
XRA B ; modofikuj CRC
+
XRA B ; modifikuj CRC
-
MOV B,A ; a uloz ho naspat do B
+
MOV B,A ; a ulož ho naspäť do B
RET
RET
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Zisti, ci na zbernici nie je nahodou prezentacny byte 0AAh, ktory poslala
+
; Zisti, či na zbernici nie je náhodou prezentačný byte 0AAh, ktorý poslala
-
; disketova jednotka po navrate do "idle" stavu, kedy cakala na povel.
+
; disketová jednotka po návrate do "idle" stavu, kedy čakala na povel.
; I: -
; I: -
; O: CY=1 - chyba
; O: CY=1 - chyba
Riadok 147: Riadok 147:
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
IsPresent:
IsPresent:
-
CALL EnaByteIn ; povol prerusenie pre vstup
+
CALL EnaByteIn ; povoľ prerušenie pre vstup
-
CALL WaitQ ; male zdrzanie asi 90 us
+
CALL WaitQ ; malé zdržanie asi 90 µs
IN PIO_C
IN PIO_C
-
ANI 8 ; je platny byte na vstupe?
+
ANI 8 ; je platný byte na vstupe?
-
JZ EnaByteOut ; ak nie, vrat sa cez povolenie prerusenia pre vystup
+
JZ EnaByteOut ; ak nie, vráť sa cez povolenie prerušenia pre výstup
IsPresent5:
IsPresent5:
-
CALL EnaByteIn ; povol prerusenie pre vstup
+
CALL EnaByteIn ; povoľ prerušenie pre vstup
IsPresent4:
IsPresent4:
-
IN PIO_A ; precitaj byte zo vstupu
+
IN PIO_A ; prečítaj byte zo vstupu
-
CPI 0AAh ; ak je to prezentacny byte 0AAh
+
CPI 0AAh ; ak je to prezentačný byte 0AAh
-
JZ IsPresent2 ; skoc poslat prezentacny byte 0AAh na vystup
+
JZ IsPresent2 ; skoč poslať prezentačný byte 0AAh na výstup
LXI D,5000 ; timeout asi 125 ms
LXI D,5000 ; timeout asi 125 ms
-
CALL IsIntraD ; cakaj na byte
+
CALL IsIntraD ; čakaj na byte
-
RC ; timeout, vrat sa
+
RC ; vráť sa s chybou, ak čas vypršal
-
JMP IsPresent4 ; ano, skoc precitat byte zo vstupu
+
JMP IsPresent4 ; inak, skoč prečítať byte zo vstupu
 
 
IsPresent2:
IsPresent2:
-
CALL WaitQ ; male zdrzanie asi 90 us
+
CALL WaitQ ; malé zdržanie asi 90 µs
-
CALL EnaByteOut ; povol prerusenie pre vystup
+
CALL EnaByteOut ; povoľ prerušenie pre výstup
-
MVI A,0AAh ; posli na vystup prezentacny byte 0AAh
+
MVI A,0AAh ; pošli na výstup prezentačný byte 0AAh
OUT PIO_A
OUT PIO_A
LXI D,5000 ; timeout asi 125 ms
LXI D,5000 ; timeout asi 125 ms
-
CALL IsIntraD ; cakaj na byte
+
CALL IsIntraD ; čakaj na byte
-
JC IsPresent5 ; ak nebol prezentacny byte prijaty, skoc otestovat vstup
+
JC IsPresent5 ; ak nebol prezentačný byte prijatý, skoč otestovať vstup
-
RET ; bol prijaty prezentacny byte, vrat sa s vynulovanym CY
+
RET ; bol prijatý prezentačný byte, vráť sa s vynulovaným CY
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Kratke zdrzanie
+
; Krátke zdržanie
; I: -
; I: -
-
; O: kratke zdrzanie asi 90 us
+
; O: krátke zdržanie asi 90 µs
; M: AF
; M: AF
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
Riadok 190: Riadok 190:
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Zisti, ci je pripojena PMD 32 a ci odpoveda prezentacnym bytom.
+
; Zistí, či je pripojená PMD 32 a či odpovedá prezentačným bytom.
; I: -
; I: -
-
; O: CY=1 - chyba, timeout, PMD 32 neodpoveda prezentacnym bytom
+
; O: CY=1 - chyba, timeout, PMD 32 neodpovedá prezentačným bytom
 +
; CY=0 - OK
; M: AF, DE, B
; M: AF, DE, B
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
Riadok 198: Riadok 199:
MVI A,0C4h ; inicializuj GPIO 8255
MVI A,0C4h ; inicializuj GPIO 8255
OUT PIO_CW ; SK A: MOD 2, A-IN/OUT, SK B: MOD 1, B-OUT
OUT PIO_CW ; SK A: MOD 2, A-IN/OUT, SK B: MOD 1, B-OUT
-
CALL EnaByteIn ; povol prerusenie pre vstup
+
CALL EnaByteIn ; povoľ prerušenie pre vstup
LXI D,10000 ; timeout asi 250 ms
LXI D,10000 ; timeout asi 250 ms
-
CALL IsIntraD ; cakaj na byte
+
CALL IsIntraD ; čakaj na byte
-
RC ; timeout, vrat sa
+
RC ; timeout, vráť sa
-
IN PIO_A ; precitaj prijaty byte
+
IN PIO_A ; prečítaj prijatý byte
-
CPI 0AAh ; je to prezentacny byte 0AAh ?
+
CPI 0AAh ; je to prezentačný byte 0AAh ?
-
STC ; nastav CY ako priznak chyby
+
STC ; nastav CY ako príznak chyby
-
RNZ ; nie je to prezentacny byte 0AAh, vrat sa s CY
+
RNZ ; nie je to prezentačný byte 0AAh, vráť sa s CY
-
CALL EnaByteOut ; povol prerusenie pre vystup
+
CALL EnaByteOut ; povoľ prerušenie pre výstup
-
MVI A,0AAh ; posli ako odpoved prezentacny byte 0AAh
+
MVI A,0AAh ; pošli ako odpoveď prezentačný byte 0AAh
JMP SendByte
JMP SendByte
* '''Rutiny pre ukončenie povelu'''
* '''Rutiny pre ukončenie povelu'''
-
Rutina <tt>SndCrcRdAckErr</tt> slúži pre odoslanie CRC, ktoré sa priebežne počíta v registri B. Po odoslaní sa počká na potvrdzovací byte ACK a na chybový kód.
+
Rutina {{Kbd|SndCrcRdAckErr}} slúži pre odoslanie CRC, ktoré sa priebežne počíta v registri B. Po odoslaní sa počká na potvrdzovací byte ACK a na chybový kód.
-
Rutina <tt>SndCrcRdAck</tt> je rovnaká ako predošlá, ale chybový kód sa testuje na nulu.
+
Rutina {{Kbd|SndCrcRdAck}} je rovnaká ako predošlá, ale chybový kód sa ihneď testuje na nulu.
-
Rutina <tt>ReadCheckCrc</tt> precita CRC z PMD 32 a porovná ho s priebežne počítaným CRC v registri B.
+
Rutina {{Kbd|ReadCheckCrc}} prečíta CRC z PMD 32 a porovná ho s priebežne počítaným CRC v registri B.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Posle CRC na vystup a pocka na ACK a vysledok povelu.
+
; Pošle CRC na výstup a počká na ACK a výsledok povelu.
-
; I: B=aktualne CRC
+
; I: B=aktuálne CRC
; O: CY=1 - chyba
; O: CY=1 - chyba
-
; CY=0 - OK, A=vysledok povelu
+
; CY=0 - OK, A=výsledok povelu
; M: AF, BC, DE
; M: AF, BC, DE
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
SndCrcRdAckErr:
SndCrcRdAckErr:
-
MOV A,B ; posielane CRC do A
+
MOV A,B ; posielané CRC do A
-
CALL SendByte ; posli na vystup
+
CALL SendByte ; pošli na výstup
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
ReadAckErr:
ReadAckErr:
-
CALL EnaByteIn ; povol prerusenie na vstupe
+
CALL EnaByteIn ; povoľ prerušenie na vstupe
-
CALL ReadByte ; precitaj byte zo vstupu
+
CALL ReadByte ; prečítaj byte zo vstupu
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
CPI 33h ; bolo prijate byte ACK?
CPI 33h ; bolo prijate byte ACK?
-
STC ; nastav chybovy priznak
+
STC ; nastav chybový príznak
-
RNZ ; vrat sa s chybou, ak to nebolo ACK
+
RNZ ; vráť sa s chybou, ak to nebolo ACK
WaitErrT15:
WaitErrT15:
LXI D,3000 ; timeout asi 15,5 sec
LXI D,3000 ; timeout asi 15,5 sec
WaitErrT:
WaitErrT:
-
PUSH D ; DE na zasobnik
+
PUSH D ; DE na zásobník
-
CALL IsIntra ; je platny byte na vstupe?
+
CALL IsIntra ; je platný byte na vstupe?
POP D ; obnov DE
POP D ; obnov DE
-
JNC ReadByte ; ak ano, skoc ho precitat
+
JNC ReadByte ; ak áno, skoč ho prečítať
-
DCX D ; zniz pocitadlo timeoutu
+
DCX D ; zníž počítadlo timeoutu
MOV A,D ; a testuj ho na nulu
MOV A,D ; a testuj ho na nulu
ORA E
ORA E
-
JNZ WaitErrT ; ak nie je nulovy, skoc do slucky
+
JNZ WaitErrT ; ak nie je nulové, skoč do slučky
-
STC ; nastav priznak chyby
+
STC ; nastav príznak chyby
RET
RET
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Odosle CRC a caka na potvrdenie. Otestuje chybovy kod na nulu.
+
; Odošle CRC a čaká na potvrdenie. Otestuje chybový kód na nulu.
-
; I: B=posielane CRC
+
; I: B=posielané CRC
; O: CY=1 - chyba
; O: CY=1 - chyba
; CY=0 - OK
; CY=0 - OK
Riadok 257: Riadok 258:
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
SndCrcRdAck:
SndCrcRdAck:
-
CALL SndCrcRdAckErr ; posli CRC a cakaj ACK a vysledok povelu
+
CALL SndCrcRdAckErr ; pošli CRC a čakaj ACK a výsledok povelu
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
-
JMP ReadCheckCrc2 ; ak bol druhy byte skutocne 0, je to OK
+
JMP ReadCheckCrc2 ; ak bol druhy byte skutočne 0, je to OK
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Precita byte zo vstupu, predstavujuci CRC
+
; Prečíta byte zo vstupu, predstavujúci CRC
; I: -
; I: -
; O: CY=1 - chyba CRC alebo timeout
; O: CY=1 - chyba CRC alebo timeout
Riadok 269: Riadok 270:
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
ReadCheckCrc:
ReadCheckCrc:
-
CALL ReadByte ; precitaj CRC zo vstupu
+
CALL ReadByte ; prečítaj CRC zo vstupu
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
MOV A,B ; skontroluj CRC
MOV A,B ; skontroluj CRC
ReadCheckCrc2:
ReadCheckCrc2:
ORA A
ORA A
RZ ; OK
RZ ; OK
-
STC ; nastav priznak chyby
+
STC ; nastav príznak chyby
RET
RET
* '''Rutiny pre čítanie a zápis sektora'''
* '''Rutiny pre čítanie a zápis sektora'''
-
Jedná sa o povely B, Q a T. Povely Q a T používajú rutinu <tt>SendSectorTrack</tt>, ktorá odošle sektor a disk ako prvý byte a následne stopu ako druhý byte. Aj keď má zvyčajne prvý sektor na disku fyzické číslo 1, PMD 32 vo svojich poveloch čísluje sektory od 0. Číslo disku od 0 do 3 sa posiela v horných dvoch bitoch prvého bytu. Aby sa zachovala spätná kompatibilita s pôvodnou PMD 32, kde sú iba dva disky a disk B je označený siedmym bitom, bity označujúce disk sú zamenené. Keďže žiadna komunikácia nie je bez chýb, (tieto) povely je vhodné vložiť do slučky niekoľkých pokusov pri chybe. BIOS PMD 85 napr. používa 4 pokusy.
+
Jedná sa o povely B, Q a T. Povely Q a T používajú rutinu {{Kbd|SendSectorTrack}}, ktorá odošle sektor a disk ako prvý byte a následne stopu ako druhý byte. Aj keď má zvyčajne prvý sektor na disku fyzické číslo 1, PMD 32 vo svojich poveloch čísluje sektory od 0. Číslo disku od 0 do 3 sa posiela v horných dvoch bitoch prvého bytu. Aby sa zachovala spätná kompatibilita s pôvodnou PMD 32, kde sú iba dva disky a disk B je označený siedmym bitom, bity označujúce disk sú zamenené. Keďže žiadna komunikácia nie je bez chýb, (tieto) povely je vhodné vložiť do slučky niekoľkých pokusov pri chybe. BIOS PMD 85 napr. používa 4 pokusy.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Posle do PMD 32 cislo sektoru vratane cisla disku a cislo stopy.
+
; Pošle do PMD 32 číslo sektora vrátane čísla disku a čísla stopy.
-
; vstup: cislo sektoru, disku a stopy na adresach Drive, Sector, Track
+
; I: číslo sektora, disku a stopy na adresách {{Kbd|Drive}}, {{Kbd|Sector}} a {{Kbd|Track}}
-
; B=priebezne CRC
+
; B=priebežné CRC
-
; vystup: CY = 1 - chyba
+
; O: CY=1 - chyba
-
; CY = 0 - OK, B = A = modifikovane CRC
+
; CY=0 - OK, B=A=modifikovane CRC
-
; meni: AF, BC
+
; M: AF, BC
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
SendSectorTrack:
SendSectorTrack:
-
LDA Drive ; cislo disku transformuj do 7. a 6. bitu
+
LDA Drive ; číslo disku transformuj do 7. a 6. bitu
ORA A ; disk A: ?
ORA A ; disk A: ?
-
JZ SendSectorTrack2 ; ano, skoc
+
JZ SendSectorTrack2 ; áno, skoč
-
MVI C,0C0H ; transformovana hodnota pre disk D:
+
MVI C,0C0H ; transformovaná hodnota pre disk D:
-
XRI 3 ; invertuj (prehod) bity cisla disku
+
XRI 3 ; invertuj (prehoď) bity čísla disku
-
JZ SendSectorTrack3 ; je to disk D: ? ano, skoc
+
JZ SendSectorTrack3 ; je to disk D: ? áno, skoč
-
RRC ; pre disky B: a C: posun cislo do hornych bitov
+
RRC ; pre disky B: a C: posuň číslo do horných bitov
RRC
RRC
-
SendSectorTrack2: ; C bude obsahovat transformovanu hodnotu cisla disku
+
SendSectorTrack2: ; C bude obsahovať transformovanú hodnotu čísla disku
MOV C,A ; C -> 00h=A: 80h=B: 40h=C: 0C0h=D:
MOV C,A ; C -> 00h=A: 80h=B: 40h=C: 0C0h=D:
SendSectorTrack3:
SendSectorTrack3:
-
LDA Sector ; vezmi cislo sektora 0 az N (N je max. 63)
+
LDA Sector ; vezmi číslo sektora 0 N (N je max. 63)
-
ANI 03FH ; -> nemusi byt, ak sa zabezpeci povoleny rozsah
+
ANI 03FH ; -> nemusí byť, ak sa zabezpečí povolený rozsah
-
ORA C ; do hornych bitov pridaj cislo disku
+
ORA C ; do horných bitov pridaj číslo disku
-
CALL SendByte ; posli cislo disku a sektora
+
CALL SendByte ; pošli číslo disku a sektora
-
RC ; navrat s CY=1 pri chybe
+
RC ; návrat s CY=1 pri chybe
-
LDA Track ; cislo stopy 0 az N (N je max. 255)
+
LDA Track ; číslo stopy 0 N (N je max. 255)
-
JMP SendByte ; posli stopu
+
JMP SendByte ; pošli stopu
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Posle povel "B" a precita BOOT - sektor 0 a 0. stope.
+
; Pošle povel "B" a prečíta BOOT - sektor 0 na 0. stope.
-
; Vzdy je to z jednotky A:
+
; Vždy je to z jednotky A:
-
; vstup: cielova adresa na adrese Dma
+
; I: cieľová adresa na adrese {{Kbd|Dma}}
-
; vystup: CY = 1 - chyba timeout, CRC
+
; O: CY=1 - chyba timeout, CRC
-
; CY = 0 - OK
+
; CY=0 - OK
-
; meni: vsetky
+
; M: všetky
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
ReadBoot:
ReadBoot:
-
MVI A,'B' ; povel "B" - precitaj BOOT
+
MVI A,'B' ; povel "B" - prečítaj BOOT
-
CALL SendCommand ; odosli na vystup
+
CALL SendCommand ; odošli na výstup
JMP ReadSectorB
JMP ReadSectorB
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Povel "Q" - precitanie sektora z disku.
+
; Povel "Q" - prečítanie sektora z disku.
-
; vstup: cislo sektoru, disku a stopy na adresach Drive, Sector, Track
+
; I: číslo sektora, disku a stopy na adresách {{Kbd|Drive}}, {{Kbd|Sector}}, {{Kbd|Track}}
-
; cielova adresa na adrese Dma
+
; cieľová adresa na adrese {{Kbd|Dma}}
-
; vystup: CY = 1 - chyba timeout, CRC
+
; O: CY=1 - chyba timeout, CRC
-
; CY = 0 - OK
+
; CY=0 - OK
-
; meni: vsetky
+
; M: všetky
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
ReadSector:
ReadSector:
-
MVI A,'Q' ; povel "Q" - precitaj sektor
+
MVI A,'Q' ; povel "Q" - prečítaj sektor
-
CALL SendCommand ; odosli na vystup
+
CALL SendCommand ; odošli na výstup
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
-
CALL SendSectorTrack ; posli stopu a sektor
+
CALL SendSectorTrack ; pošli stopu a sektor
ReadSectorB:
ReadSectorB:
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
-
CALL SndCrcRdAck ; posli CRC a pockaj na potvrdenie
+
CALL SndCrcRdAck ; pošli CRC a počkaj na potvrdenie
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
MVI B,0 ; vynuluj CRC
MVI B,0 ; vynuluj CRC
-
MVI D,128 ; nastav pocitadlo
+
MVI D,128 ; nastav počítadlo
-
LHLD Dma ; do HL adresa pamati
+
LHLD Dma ; do HL cieľovú adresu
ReadSector2:
ReadSector2:
-
CALL ReadByte ; precitaj byte
+
CALL ReadByte ; prečítaj byte
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
-
MOV M,A ; uloz byte do pamati
+
MOV M,A ; ulož byte do pamäte
-
INX H ; posun ukazatel
+
INX H ; posuň ukazateľ
-
DCR D ; zniz pocitadlo prijimanych bytov
+
DCR D ; zníž počítadlo prijímaných bytov
-
JNZ ReadSector2 ; ak neboli prijate vsetky, vrat sa do slucky
+
JNZ ReadSector2 ; ak neboli prijaté všetky, vráť sa do slučky
-
JMP ReadCheckCrc ; skoc precitat CRC
+
JMP ReadCheckCrc ; skoč prečítať CRC
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
-
; Povel "T" - zapise sektor na disk.
+
; Povel "T" - zapíše sektor na disk.
-
; vstup: cislo sektoru, disku a stopy na adresach Drive, Sector, Track
+
; I: číslo sektora, disku a stopy na adresách {{Kbd|Drive}}, {{Kbd|Sector}}, {{Kbd|Track}}
-
; zdrojova adresa na adrese Dma
+
; zdrojová adresa na adrese {{Kbd|Dma}}
-
; vystup: CY = 1 - chyba timeout, CRC
+
; O: CY=1 - chyba timeout, CRC
-
; CY = 0 - OK
+
; CY=0 - OK
-
; meni: vsetky
+
; M: vsetky
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
WriteSector:
WriteSector:
-
MVI A,'T' ; povel "T" - zapis sektor
+
MVI A,'T' ; povel "T" - zapíš sektor
-
CALL SendCommand ; odosli na vystup
+
CALL SendCommand ; odošli na výstup
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
-
CALL SendSectorTrack ; posli stopu a sektor
+
CALL SendSectorTrack ; pošli stopu a sektor
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
-
MVI D,128 ; nastav pocitadlo
+
MVI D,128 ; nastav počítadlo
-
LHLD Dma ; do HL adresa pamati
+
LHLD Dma ; do HL zdrojová adresa
WriteSector2:
WriteSector2:
-
MOV A,M ; byte z pamati
+
MOV A,M ; byte z pamäte
-
CALL SendByte ; odosli
+
CALL SendByte ; odošli
-
RC ; vrat sa, ak doslo ku chybe
+
RC ; vráť sa, ak došlo ku chybe
-
INX H ; posun ukazatel
+
INX H ; posuň ukazateľ
-
DCR D ; zniz pocitadlo bytov
+
DCR D ; zníž počítadlo bytov
-
JNZ WriteSector2 ; opakuj pre vsetkych 128 bytov
+
JNZ WriteSector2 ; opakuj pre všetkých 128 bytov sektora
-
JMP SndCrcRdAck ; odosli CRC a cakaj na potvrdenie
+
JMP SndCrcRdAck ; odošli CRC a čakaj na potvrdenie
=== Download ===
=== Download ===
-
Zdroják je pripravený na kompiláciu v ASe. Ale pochopiteľne je ho možné upraviť a kompilovať "v čomkoľvek".
+
Zdroják je pripravený na kompiláciu v ASe. Ale, pochopiteľne, je ho možné upraviť a kompilovať "v čomkoľvek".
* [[download:59|zdrojový súbor]] tohto ovládača
* [[download:59|zdrojový súbor]] tohto ovládača
* [[download:16|komunikačný protokol]] [[PMD 32]]/[[PMD 32-SD]]
* [[download:16|komunikačný protokol]] [[PMD 32]]/[[PMD 32-SD]]
[[Kategória:Blog| 006]]
[[Kategória:Blog| 006]]

Aktuálna verzia

Ovládač pre komunikáciu s PMD 32

PMD 85-3 obsahuje vo svojej EPROM, na rozdiel od predošlých verzií PMD 85, ovládač pre disketovú jednotku PMD 32. Keďže sa ukázalo, že PMD 32-SD, teda náhradu za PMD 32, by si chceli niektorí pripojiť aj k iným počítačom (SAPI, IQ-151), uvediem tu výpis tohto ovládača, aby si ho záujemci mohli prispôsobiť pre svoj počítač. Ovládač nie je úplnou kópiou z PMD 85-3, ale je naopak optimalizovaný a skrátený. Zároveň ale neobsahuje implementáciu všetkých povelov, ktoré PMD 32, či PMD 32-SD poskytujú, pretože to ani nie je účelné. Verím, že prípadný záujemca si ďalšie povely bez problémov doplní sám.

PMD 32, resp. PMD 32-SD komunikuje s nadradeným počítačom prostredníctvom obojsmerného paralelného kanála, ktorý je na strane počítača tvorený interfejsovým obvodom PPI 8255.

Z 8255 sa využíva iba port PA v móde 2 ako 8 bitová obojsmerná dátová zbernica a 4 riadiace bity hornej polovice portu PC pre handshake. Stav zbernice sa ale testuje 3. bitom portu PC (INTRA), ktorý podľa zvoleného smeru prenosu indikuje, či je na zbernici platný byte (vstup dát), alebo bol byte perifériou prečítaný (výstup dát). Smer prenosu dát sa volí povolením alebo zakázaním prerušenia (signál INTRA) pre vstup alebo výstup dát.

Ovládač potrebuje niekde v RAM 4 premenné:

Drive:  DS     1            ; číslo disku 0 = A:, 1 = B:, 2 = C:, 3 = D:
Sector: DS     1            ; číslo sektora 0 až N (N je max. 63)
Track:  DS     1            ; číslo stopy 0 až N (N je max. 255)
Dma:    DS     2            ; cieľová/zdrojová adresa pre čítanie/zápis sektora

Základná komunikácia na najnižšej úrovni zahŕňa niekoľko elementárnych rutín:

  • Nastavenie smeru prenosu a test, či je na vstupe platný byte, alebo či bol perifériou byte prečítaný

Tieto rutiny sú volané ostatnými rutinami, pre čítanie a zápis bytu atď., takže pri vytváraní rutín vyšších úrovní ich zrejme nebude treba volať.

;------------------------------------------------------------------------------
; Povolí prerušenie pre vstup bytu na porte A
; I: -
; O: povolené prerušenie pre vstup bytu
; M: A
;------------------------------------------------------------------------------
EnaByteIn:
        MVI    A,09h        ; 1->C4 povolenie prerušovacieho signálu INTRA
        OUT    PIO_CW       ; pre vstup bytu na porte A
        MVI    A,0Ch        ; 0->C6 zakázanie prerušovacieho signálu INTRA
        OUT    PIO_CW       ; pre výstup bytu na port A
        RET
 
;------------------------------------------------------------------------------
; Povolí prerušenie pre výstup bytu na porte A
; I: -
; O: povolené prerušenie pre výstup bytu
; M: A
;------------------------------------------------------------------------------
EnaByteOut:
        MVI    A,08h        ; 0->C4 zakázanie prerušovacieho signálu INTRA
        OUT    PIO_CW       ; pre vstup bytu na porte A
        MVI    A,0Dh        ; 1->C6 povolenie prerušovacieho signálu INTRA
        OUT    PIO_CW       ; pre výstup bytu na port A
        RET
 
;------------------------------------------------------------------------------
; Zistí, či je nastavené INTRA. Na INTRA sa čaká zvolený čas.
; INTRA=1, ak je platný byte na vstupe, alebo bol prečítaný byte z výstupu.
; I: Pri volaní od IsIntraD DE=timeout
; O: CY=1 - timeout
;    CY=0 - OK
; M: CY, DE
;------------------------------------------------------------------------------
IsIntra:
        LXI    D,205        ; timeout asi 5ms
IsIntraD:
        PUSH   PSW          ; ulož AF
IsIntra2:
        IN     PIO_C        ; zisti stav INTRA
        ANI    8
        JNZ    IsIntra3     ; ak je INTRA=1, skoč dopredu
        DCX    D
        MOV    A,D
        ORA    E
        JNZ    IsIntra2     ; a ak nie je nulové, vráť sa do slučky
        POP    PSW          ; došlo k timeoutu, obnov AF
        STC                 ; nastav CY ako príznak chyby
        RET
IsIntra3:
        POP    PSW          ; obnov AF
        ORA    A            ; vynuluj CY
        RET
  • Čítanie bytu

Pred volaním tejto rutiny musí byť povolený vstup bytu volaním rutiny EnaByteIn. Rutina priebežne modifikuje CRC, ktoré sa prenáša v registri B.

;------------------------------------------------------------------------------
; Prečíta byte z PMD 32 a zároveň modifikuje CRC.
; I: B=priebežné CRC
; O: CY=1 - chyba
;    CY=0 - A=C=prečítaný byte, B=modifikované CRC
; M: AF, BC
;------------------------------------------------------------------------------
ReadByte:
        PUSH   D            ; DE na zásobník
        CALL   IsIntra      ; je platný byte na vstupe?
        POP    D            ; obnov DE
        RC                  ; nie, vráť sa s chybou
        IN     PIO_A        ; prečítaj byte
        MOV    C,A          ; odlož si ho do C
        XRA    B            ; modifikuj CRC
        MOV    B,A          ; a ulož ho naspäť do B
        MOV    A,C          ; vráť načítaný byte do A
        RET
  • Odoslanie bytu a povelu

Pred volaním rutiny SendByte musí byť povolený výstup bytu volaním rutiny EnaByteOut. Rutina priebežne modifikuje CRC, ktoré sa prenáša v registri B.

Rutina SendCommand slúži pre odoslanie povelu. Táto rutina najprv volaním rutiny IsPresent preveruje, či náhodou nie je na zbernici prezentačný byte, ktorý posiela PMD 32, keď je "v kľude". Pokiaľ na zbernici prezentačný byte nie je, povolí sa výstup bytu a povel sa odošle. Inak sa najprv naspäť odošle prezentačný byte a následne samotný povel. Rutina pred odoslaním povelu inicializuje CRC.

;------------------------------------------------------------------------------
; Pošle povel do PMD 32. Pred poslaním povelu sa najprv preverí, či na zbernici
; náhodou nie je prezentačný byte.
; I: A=povel
; O: CY=1 - chyba
;    CY=0 - OK, B=A=modifikované CRC
; M: AF, B
;------------------------------------------------------------------------------
SendCommand:
       MOV     B,A          ; ulož posielaný povelový byte do B
       PUSH    B            ; BC, DE na zásobník
       PUSH    D
       CALL    IsPresent    ; zisti, či je na zbernici prezentačný byte 0AAh
                            ; ak áno, odošli naspäť prezentačný byte
       POP     D
       POP     B            ; obnov DE, BC
       RC                   ; vráť sa, ak došlo ku chybe
       MOV     A,B          ; vráť posielaný povelový byte do A
       MVI     B,0          ; vynuluj CRC
; pokračuj ďalej
 
;------------------------------------------------------------------------------
; Pošle byte do PMD 32 a modifikuje priebežné CRC.
; I: A=posielaný byte, B=priebežné CRC
; O: CY=1 - chyba
;    CY=0 - OK, B=A=modifikované CRC
; M: AF, B
;------------------------------------------------------------------------------
SendByte:
       PUSH    D            ; DE na zásobník
       CALL    IsIntra      ; zisti, či je voľný výstup
       POP     D            ; obnov DE
       RC                   ; vráť sa, ak došlo ku timeoutu
       OUT     PIO_A        ; pošli byte na výstup
       XRA     B            ; modifikuj CRC
       MOV     B,A          ; a ulož ho naspäť do B
       RET
 
;------------------------------------------------------------------------------
; Zisti, či na zbernici nie je náhodou prezentačný byte 0AAh, ktorý poslala
; disketová jednotka po návrate do "idle" stavu, kedy čakala na povel.
; I: -
; O: CY=1 - chyba
;    CY=0 - OK
; M: AF, DE
;------------------------------------------------------------------------------
IsPresent:
       CALL    EnaByteIn    ; povoľ prerušenie pre vstup
       CALL    WaitQ        ; malé zdržanie asi 90 µs
       IN      PIO_C
       ANI     8            ; je platný byte na vstupe?
       JZ      EnaByteOut   ; ak nie, vráť sa cez povolenie prerušenia pre výstup
IsPresent5:
       CALL    EnaByteIn    ; povoľ prerušenie pre vstup
IsPresent4:
       IN      PIO_A        ; prečítaj byte zo vstupu
       CPI     0AAh         ; ak je to prezentačný byte 0AAh
       JZ      IsPresent2   ; skoč poslať prezentačný byte 0AAh na výstup
       LXI     D,5000       ; timeout asi 125 ms
       CALL    IsIntraD     ; čakaj na byte
       RC                   ; vráť sa s chybou, ak čas vypršal
       JMP     IsPresent4   ; inak, skoč prečítať byte zo vstupu
 
IsPresent2:
       CALL    WaitQ        ; malé zdržanie asi 90 µs
       CALL    EnaByteOut   ; povoľ prerušenie pre výstup
       MVI     A,0AAh       ; pošli na výstup prezentačný byte 0AAh
       OUT     PIO_A
       LXI     D,5000       ; timeout asi 125 ms
       CALL    IsIntraD     ; čakaj na byte
       JC      IsPresent5   ; ak nebol prezentačný byte prijatý, skoč otestovať vstup
       RET                  ; bol prijatý prezentačný byte, vráť sa s vynulovaným CY
 
;------------------------------------------------------------------------------
; Krátke zdržanie
; I: -
; O: krátke zdržanie asi 90 µs
; M: AF
;------------------------------------------------------------------------------
WaitQ:
       MVI     A,20
WaitQ1:
       DCR     A
       JNZ     WaitQ1
       RET
  • Zistenie, či je PMD 32 pripojená
  • Táto rutina musí byť volaná ako prvá, pretože inicializuje 8255 a preveruje, či je PMD 32 pripojená.
;------------------------------------------------------------------------------
; Zistí, či je pripojená PMD 32 a či odpovedá prezentačným bytom.
; I: -
; O: CY=1 - chyba, timeout, PMD 32 neodpovedá prezentačným bytom
;    CY=0 - OK
; M: AF, DE, B
;------------------------------------------------------------------------------
CheckDevice:
       MVI     A,0C4h       ; inicializuj GPIO 8255
       OUT     PIO_CW       ; SK A: MOD 2, A-IN/OUT,  SK B: MOD 1, B-OUT
       CALL    EnaByteIn    ; povoľ prerušenie pre vstup
       LXI     D,10000      ; timeout asi 250 ms
       CALL    IsIntraD     ; čakaj na byte
       RC                   ; timeout, vráť sa
       IN      PIO_A        ; prečítaj prijatý byte
       CPI     0AAh         ; je to prezentačný byte 0AAh ?
       STC                  ; nastav CY ako príznak chyby
       RNZ                  ; nie je to prezentačný byte 0AAh, vráť sa s CY
       CALL    EnaByteOut   ; povoľ prerušenie pre výstup
       MVI     A,0AAh       ; pošli ako odpoveď prezentačný byte 0AAh
       JMP     SendByte
  • Rutiny pre ukončenie povelu

Rutina SndCrcRdAckErr slúži pre odoslanie CRC, ktoré sa priebežne počíta v registri B. Po odoslaní sa počká na potvrdzovací byte ACK a na chybový kód.

Rutina SndCrcRdAck je rovnaká ako predošlá, ale chybový kód sa ihneď testuje na nulu.

Rutina ReadCheckCrc prečíta CRC z PMD 32 a porovná ho s priebežne počítaným CRC v registri B.

;------------------------------------------------------------------------------
; Pošle CRC na výstup a počká na ACK a výsledok povelu.
; I: B=aktuálne CRC
; O: CY=1 - chyba
;    CY=0 - OK, A=výsledok povelu
; M: AF, BC, DE
;------------------------------------------------------------------------------
SndCrcRdAckErr:
       MOV     A,B          ; posielané CRC do A
       CALL    SendByte     ; pošli na výstup
       RC                   ; vráť sa, ak došlo ku chybe
ReadAckErr:
       CALL    EnaByteIn    ; povoľ prerušenie na vstupe
       CALL    ReadByte     ; prečítaj byte zo vstupu
       RC                   ; vráť sa, ak došlo ku chybe
       CPI     33h          ; bolo prijate byte ACK?
       STC                  ; nastav chybový príznak
       RNZ                  ; vráť sa s chybou, ak to nebolo ACK
WaitErrT15:
       LXI     D,3000       ; timeout asi 15,5 sec
WaitErrT:
       PUSH    D            ; DE na zásobník
       CALL    IsIntra      ; je platný byte na vstupe?
       POP     D            ; obnov DE
       JNC     ReadByte     ; ak áno, skoč ho prečítať
       DCX     D            ; zníž počítadlo timeoutu
       MOV     A,D          ; a testuj ho na nulu
       ORA     E
       JNZ     WaitErrT     ; ak nie je nulové, skoč do slučky
       STC                  ; nastav príznak chyby
       RET
 
;------------------------------------------------------------------------------
; Odošle CRC a čaká na potvrdenie. Otestuje chybový kód na nulu.
; I: B=posielané CRC
; O: CY=1 - chyba
;    CY=0 - OK
; M: AF, BC, DE
;------------------------------------------------------------------------------
SndCrcRdAck:
       CALL    SndCrcRdAckErr ; pošli CRC a čakaj ACK a výsledok povelu
       RC                     ; vráť sa, ak došlo ku chybe
       JMP     ReadCheckCrc2  ; ak bol druhy byte skutočne 0, je to OK
 
;------------------------------------------------------------------------------
; Prečíta byte zo vstupu, predstavujúci CRC
; I: -
; O: CY=1 - chyba CRC alebo timeout
;    CY=0 - CRC OK
; M: AF, BC
;------------------------------------------------------------------------------
ReadCheckCrc:
       CALL    ReadByte     ; prečítaj CRC zo vstupu
       RC                   ; vráť sa, ak došlo ku chybe
       MOV     A,B          ; skontroluj CRC
ReadCheckCrc2:
       ORA     A
       RZ                   ; OK
       STC                  ; nastav príznak chyby
       RET
  • Rutiny pre čítanie a zápis sektora

Jedná sa o povely B, Q a T. Povely Q a T používajú rutinu SendSectorTrack, ktorá odošle sektor a disk ako prvý byte a následne stopu ako druhý byte. Aj keď má zvyčajne prvý sektor na disku fyzické číslo 1, PMD 32 vo svojich poveloch čísluje sektory od 0. Číslo disku od 0 do 3 sa posiela v horných dvoch bitoch prvého bytu. Aby sa zachovala spätná kompatibilita s pôvodnou PMD 32, kde sú iba dva disky a disk B je označený siedmym bitom, bity označujúce disk sú zamenené. Keďže žiadna komunikácia nie je bez chýb, (tieto) povely je vhodné vložiť do slučky niekoľkých pokusov pri chybe. BIOS PMD 85 napr. používa 4 pokusy.

;------------------------------------------------------------------------------
; Pošle do PMD 32 číslo sektora vrátane čísla disku a čísla stopy.
; I: číslo sektora, disku a stopy na adresách Drive, Sector a Track
;    B=priebežné CRC
; O: CY=1 - chyba
;    CY=0 - OK, B=A=modifikovane CRC
; M: AF, BC
;------------------------------------------------------------------------------
SendSectorTrack:
       LDA     Drive        ; číslo disku transformuj do 7. a 6. bitu
       ORA     A            ; disk A: ?
       JZ      SendSectorTrack2 ; áno, skoč
       MVI     C,0C0H       ; transformovaná hodnota pre disk D:
       XRI     3            ; invertuj (prehoď) bity čísla disku
       JZ      SendSectorTrack3 ; je to disk D: ? áno, skoč
       RRC                  ; pre disky B: a C: posuň číslo do horných bitov
       RRC
SendSectorTrack2:           ; C bude obsahovať transformovanú hodnotu čísla disku
       MOV     C,A          ; C -> 00h=A: 80h=B: 40h=C: 0C0h=D:
SendSectorTrack3:
       LDA     Sector       ; vezmi číslo sektora 0 až N (N je max. 63)
       ANI     03FH         ;  -> nemusí byť, ak sa zabezpečí povolený rozsah
       ORA     C            ; do horných bitov pridaj číslo disku
       CALL    SendByte     ; pošli číslo disku a sektora
       RC                   ; návrat s CY=1 pri chybe
       LDA     Track        ; číslo stopy 0 až N (N je max. 255)
       JMP     SendByte     ; pošli stopu
 
;------------------------------------------------------------------------------
; Pošle povel "B" a prečíta BOOT - sektor 0 na 0. stope.
; Vždy je to z jednotky A:
; I: cieľová adresa na adrese Dma
; O: CY=1 - chyba timeout, CRC
;    CY=0 - OK
; M: všetky
;------------------------------------------------------------------------------
ReadBoot:
       MVI     A,'B'        ; povel "B" - prečítaj BOOT
       CALL    SendCommand  ; odošli na výstup
       JMP     ReadSectorB
 
;------------------------------------------------------------------------------
; Povel "Q" - prečítanie sektora z disku.
; I: číslo sektora, disku a stopy na adresách Drive, Sector, Track
;    cieľová adresa na adrese Dma
; O: CY=1 - chyba timeout, CRC
;    CY=0 - OK
; M: všetky
;------------------------------------------------------------------------------
ReadSector:
       MVI     A,'Q'        ; povel "Q" - prečítaj sektor
       CALL    SendCommand  ; odošli na výstup
       RC                   ; vráť sa, ak došlo ku chybe
       CALL    SendSectorTrack ; pošli stopu a sektor
ReadSectorB:
       RC                   ; vráť sa, ak došlo ku chybe
       CALL    SndCrcRdAck  ; pošli CRC a počkaj na potvrdenie
       RC                   ; vráť sa, ak došlo ku chybe
       MVI     B,0          ; vynuluj CRC
       MVI     D,128        ; nastav počítadlo
       LHLD    Dma          ; do HL cieľovú adresu
ReadSector2:
       CALL    ReadByte     ; prečítaj byte
       RC                   ; vráť sa, ak došlo ku chybe
       MOV     M,A          ; ulož byte do pamäte
       INX     H            ; posuň ukazateľ
       DCR     D            ; zníž počítadlo prijímaných bytov
       JNZ     ReadSector2  ; ak neboli prijaté všetky, vráť sa do slučky
       JMP     ReadCheckCrc ; skoč prečítať CRC
 
;------------------------------------------------------------------------------
; Povel "T" - zapíše sektor na disk.
; I: číslo sektora, disku a stopy na adresách Drive, Sector, Track
;    zdrojová adresa na adrese Dma
; O: CY=1 - chyba timeout, CRC
;    CY=0 - OK
; M: vsetky
;------------------------------------------------------------------------------
WriteSector:
       MVI     A,'T'        ; povel "T" - zapíš sektor
       CALL    SendCommand  ; odošli na výstup
       RC                   ; vráť sa, ak došlo ku chybe
       CALL    SendSectorTrack ; pošli stopu a sektor
       RC                   ; vráť sa, ak došlo ku chybe
       MVI     D,128        ; nastav počítadlo
       LHLD    Dma          ; do HL zdrojová adresa
WriteSector2:
       MOV     A,M          ; byte z pamäte
       CALL    SendByte     ; odošli
       RC                   ; vráť sa, ak došlo ku chybe
       INX     H            ; posuň ukazateľ
       DCR     D            ; zníž počítadlo bytov
       JNZ     WriteSector2 ; opakuj pre všetkých 128 bytov sektora
       JMP     SndCrcRdAck  ; odošli CRC a čakaj na potvrdenie

Download

Zdroják je pripravený na kompiláciu v ASe. Ale, pochopiteľne, je ho možné upraviť a kompilovať "v čomkoľvek".