Rozdział 2
CENTRALNA PROCEDURA I/O
Centralna procedura wejścia/wyjścia (CIO) umożliwia
komunikację ze wszystkimi urządzeniami zewnętrznymi, które są
przyłączone do systemu komputerowego. Jest ona dostępna
bezpośrednio z poziomu języka maszynowego oraz z poziomu
języków programowania poprzez instrukcje wejścia/wyjścia (np. w
Atari Basic: OPEN, CLOSE, PRINT, GET itd.). Przez urządzenia
zewnętrzne należy rozumieć wszystkie urządzenia do komunikacji
komputera z otoczeniem w tym również klawiaturę, która
fizycznie jest wbudowana do komputera. Dodatkowym, oddzielnym
urządzeniem zewnętrznym Atari jest tzw. edytor, który stanowi
połączenie klawiatury (wejście) i ekranu w trybie 0 (wyjście).
Przed wywołaniem procedury CIO program użytkownika musi
umieścić w odpowiednim IOCB kod operacji do wykonania oraz
parametry potrzebne dla żądanej operacji (np. adres bufora
danych). Ponadto numer wybranego IOCB pomnożony przez 16
umieszczany jest w rejestrze indeksowym X procesora.
2.1. Główna procedura CIO
Zadaniem głównej procedury CIO jest sprawdzenie poprawności
podanego kodu operacji i numeru IOCB. Następnie według
odczytanego kodu wywoływana jest podrzędna procedura CIO
wykonująca żądaną operację.
< CIOMAIN >
|
v
/--------\
/ poprawny \ nie +-------+
< numer >------>| Y=$86 |
\ IOCB ? / +-------+
\--------/ |
| tak v
v +--------+
+---------------+ | CIORET |
| przepisanie | +--------+
| IOCB do ZIOCB |
+---------------+
|
|
v
/----------\ tak /---------\ tak
< ICHIDZ=$7F >---->--------< ICCOM=$0C >----------+
\----------/ \---------/ |
| nie | nie |
v v |
+<---------------+ /--------\ tak |
| | < HNDLOD=0 >--->-+ |
v | \--------/ | |
+-------+ | nie | | |
| Y=$84 | | v v |
+-------+ | ++--------++ +-------+ |
| | || PRPLNK || | Y=$82 | |
v | ++--------++ +-------+ |
/---------\ tak | | | |
< ICCOM<$03 >---->-+ | v | |
\---------/ | | nie /------\ | |
| | +-<---< błąd ? > | |
v | \------/ | |
+-------------------+ | | tak | |
| odczyt indeksu | | v | |
| adresu sterownika | | ++--------++ | |
+-------------------+ +------->|| CIORET ||<---+ |
| ++--------++ |
v |
/--------\ tak ++--------++ |
< indeks=0 >------->|| OPEN || |
\--------/ ++--------++ |
nie | |
v |
/--------\ tak ++--------++ |
< indeks=2 >------->|| CLOSE ||<-----------------+
\--------/ ++--------++
nie |
v
/---------\ tak ++--------++
< indeks>=8 >------>|| STATUS ||
\---------/ ++--------++
nie |
v
/--------\ tak ++--------++
< indeks=4 >------->|| READ ||
\--------/ ++--------++
nie |
v
++-------++
|| WRITE ||
++-------++
Rys.3. Struktura głównej procedury CIO.
Na początku procedury zawartości rejestru X i akumulatora
są zapisywane w pomocniczych rejestrach ICAX5Z i ICAX6Z.
Następnie sprawdzane jest, czy numer IOCB jest pełną
wielokrotnością liczby 16 i czy jest mniejszy od $80. Negatywny
wynik powoduje umieszczenie w rejestrze Y wartości $86 (kod
błędu BAD IOCB NUMBER - błędny numer IOCB) i przejście do
procedury CIORET kończącej operację CIO.
0100 ;CIO MAIN routine
0110 ;
0120 CIOCLS = $E57C
0130 CIOOPN = $E53F
0140 CIOREAD = $E5B2
0150 CIORET = $E670
0160 CIOSTSP = $E597
0170 CIOWRT = $E61E
0180 COMTAB = $E72D
0190 HNDLOD = $02E9
0200 ICAX5Z = $2E
0210 ICAX6Z = $2F
0220 ICCHID = $0340
0230 ICCOMT = $17
0240 ICCOMZ = $22
0250 ICHIDZ = $20
0260 PRPLNK = $CA29
0270 ;
0280 *= $E4DF
0290 ;
0300 STA ICAX6Z
0310 STX ICAX5Z
0320 TXA
0330 AND #$0F
0340 BNE BNAM
0350 CPX #$80
0360 BCC MOVE
0370 BNAM LDY #$86
0380 JMP CIORET
0390 MOVE LDY #$00
0400 NEXT LDA ICCHID,X
0410 STA ICHIDZ,Y
0420 INX
0430 INY
0440 CPY #$0C
0450 BCC NEXT
0460 LDA ICHIDZ
0470 CMP #$7F
0480 BNE PCMD
0490 LDA ICCOMZ
0500 CMP #$0C
0510 BEQ CIOCLS
0520 LDA HNDLOD
0530 BNE LDH
0540 ;NonEXistent Device ERror
0550 NEXDER LDY #$82
0560 EXIT JMP CIORET
0570 LDH JSR PRPLNK
0580 BMI EXIT
0590 PCMD LDY #$84
0600 LDA ICCOMZ
0610 CMP #$03
0620 BCC EXIT
0630 TAY
0640 CPY #$0E
0650 BCC CMD
0660 LDY #$0E
0670 CMD STY ICCOMT
0680 LDA COMTAB-3,Y
0690 BEQ CIOOPN
0700 CMP #$02
0710 BEQ CIOCLS
0720 CMP #$08
0730 BCS CIOSTSP
0740 CMP #$04
0750 BEQ CIOREAD
0760 JMP CIOWRT
Jeżeli numer IOCB jest poprawny, to jego zawartość jest
przepisywana na stronę zerową do ZIOCB. Nie ją jedynie
przenoszone dwa ostatnie bajty IOCB, gdyż w odpowiadających im
rejestrach ZIOCB przechowywane są już wartości z akumulatora i
rejestru X.
W następnej kolejności sprawdzany jest indeks wpisu w
tabeli HATABS - ICHIDZ (IOCB CHannel IDentification). Jego
wartość równa $7F oznacza, że operacja dotyczy "nowego
urządzenia". W takim przypadku, jeśli kod operacji jest równy
$0C (CLOSE), następuje skok do procedury CIOCLS. W przeciwnym
razie kontrolowany jest znacznik HNDLOD. Gdy jest on równy
zero, to do rejestru Y wpisywana jest wartość $82 (NON EXISTENT
DEVICE - urządzenie nie istnieje) i procedura CIOMAIN kończy
się skokiem do CIORET. Po stwierdzeniu obecności urządzenia
wywoływana jest procedura PRPLNK, która obsługuje nowe
urządzenia (zob. rozdział 6.2.).
Wartość ICHIDZ różna od $7F oznacza, że komunikacja z
urządzeniem będzie wykonywana przez standardowe procedury CIO.
Teraz do rejestru Y wpisywany jest kod błędu INVALID COMMAND
($84 - błędny rozkaz) i sprawdzana jest zawartość rejestru
ICCOMZ. Gdy jest ona mniejsza od $03, następuje skok do CIORET.
Poprawny kod operacji powoduje (po zapisaniu go do rejestru
ICCOMT) pobranie z tabeli COMTAB wartości indeksu wskazującego
położenie adresu procedury wykonującej tą operację w tabeli
adresowej sterowników. Bliższe informacje na ten temat są
zawarte w rozdziale 2.2.
0100 ;COMmand TABle
0110 ;
0120 *= $E72D
0130 ;
0140 .BYTE $00,$04,$04,$04
0150 .BYTE $04,$06,$06,$06
0160 .BYTE $06,$02,$08,$0A
Teraz przeprowadzane jest rozpoznanie operacji do wykonania
poprzez sprawdzanie wartości odczytanego indeksu. Wartość zero
oznacza operację otwarcia kanału IOCB (OPEN) i powoduje
przejście do procedury CIOOPN. Wartość dwa oznacza zamknięcie
kanału (CLOSE) - wywołuje skok do CIOCLS. Indeks większy od $07
oznacza operację odczytu statusu (STATUS) lub operację
specjalną (SPECIAL), specyficzną dla danego urządzenia. W tym
przypadku wykonywany jest skok do CIOSTSP. Na końcu sprawdzany
jest indeks operacji odczytu ($04 - READ) - skok do CIOREAD.
Jeśli żadna z wyżej wymienionych operacji nie została
rozpoznana, to znaczy, że chodzi o zapis (WRITE) i następuje
skok do CIOWRT.
2.1.1. Zakończenie procedury CIO
Zarówno główna, jak i wszystkie szczegółowe procedury CIO
kończą się skokiem do procedury CIORET. Ma ona dwa punkty
początkowe: CIORET i CPLCIO. Rozpoczęcie procedury od
etykiety CIORET powoduje zapisanie aktualnej zawartości
rejestru Y procesora do rejestru statusu ZIOCB (ICSTZ - IOCB
STatus, Zeropage). Operacja ta jest omijana przy rozpoczęciu od
etykiety CPLCIO.
0100 ;CIO RETurn routine
0110 ;
0120 HNDLOD = $02E9
0130 ICAX5Z = $2E
0140 ICAX6Z = $2F
0150 ICBAZ = $24
0160 ICBUFA = $0344
0170 ICCHID = $0340
0180 ICHIDZ = $20
0190 ICSTZ = $23
0200 ;
0210 *= $E670
0220 ;
0230 STY ICSTZ
0240 ;ComPLete CIO operation
0250 CPLCIO LDY ICAX5Z
0260 LDA ICBUFA,Y
0270 STA ICBAZ
0280 LDA ICBUFA+1,Y
0290 STA ICBAZ+1
0300 LDX #$00
0310 STX HNDLOD
0320 NEXT LDA ICHIDZ,X
0330 STA ICCHID,Y
0340 INX
0350 INY
0360 CPX #$0C
0370 BCC NEXT
0380 LDA ICAX6Z
0390 LDX ICAX5Z
0400 LDY ICSTZ
0410 RTS
Zadaniem CIORET jest przekazanie zawartości ZIOCB do
odpowiedniego IOCB. W tym celu najpierw z rejestru ICAX5Z jest
pobierany numer właściwego IOCB. Następnie adres bufora w ZIOCB
jest odtwarzany według zawartości IOCB i zerowany jest rejestr
HNDLOD. Teraz kolejno zawartości rejestrów ZIOCB są przenoszone
do IOCB (oprócz dwóch ostatnich bajtów).
Na początku procedury CIOMAIN w rejestrach ICAX5Z i ICAX6Z
zostały zapamiętane zawartości rejestru X i akumulatora. Przed
zakończeniem CIO są one odtwarzane i dodatkowo do rejestru Y
pobierany jest status wykonanej operacji I/O. Ponieważ jest to
ostatnie polecenie przed końcem procedury, to w przypadku błędu
(status większy od $7F) po powrocie do miejsca wywołania CIO
bit N (negative) w rejestrze statusu procesora jest ustawiony.
Pozwala to na bardzo proste wykrycie błędu i przejście do
dalszej części programu (np. procedury obsługi błędu) przy
użyciu rozkazów BPL (Branch if PLus) lub BMI (Branch if MInus).
2.2. Tabele adresowe sterowników
Kilkakrotnie już wspominane były tabele adresów procedur
obsługi urządzeń zewnętrznych. Według umieszczonych w nich
adresów CIO rozpoznaje procedury dotyczące poszczególnych
urządzeń. W systemie operacyjnym Atari występują dwa rodzaje
tabel adresowych: HATABS i tabele wektorów sterowników
(procedur obsługi).
Tabela HATABS (Handler Address TABleS) znajduje się na
trzeciej stronie pamięci i zawiera nazwy wszystkich urządzeń i
adresy ich tabel wektorów. Każdy wpis w tabeli HATABS składa
się z trzech bajtów: nazwa urządzenia, młodszy bajt adresu i
starszy bajt adresu:
+-------------------+ -+
1 bajt | nazwa urządzenia | |
+-------------------+ |
2 bajt | LSB adresu tabeli | +- jeden wpis
+-------------------+ |
3 bajt | MSB adresu tabeli | |
+-------------------+ -+
| |
| dalsze wpisy |
| |
+-------------------+
Rys.4. Struktura tabeli HATABS
Nazwa urządzenia w HATABS jest zapisaną w kodzie ASCII
pierwszą literą nazwy symbolicznej, np. Cassette, Editor,
Keyboard, Printer itd. Są to te same nazwy, które występują w
Atari Basic w instrukcji OPEN. Początkowo tabela HATABS zawiera
pięć wpisów urządzeń (P, C, E, S i K) przeniesionych tu z
tabeli INIT31A podczas inicjowania systemu:
0100 ;Handler Address TABleS
0110 ;
0120 CASVEC = $E440
0130 EDTVEC = $E400
0140 KBDVEC = $E420
0150 PRTVEC = $E430
0160 SCRVEC = $E410
0170 ;
0180 *= $031A
0190 ;
0200 .BYTE 'P
0210 .WORD PRTVEC
0220 .BYTE 'C
0230 .WORD CASVEC
0240 .BYTE 'E
0250 .WORD EDTVEC
0260 .BYTE 'S
0270 .WORD SCRVEC
0280 .BYTE 'K
0290 .WORD KBDVEC
Dalsze miejsca w HATABS są przeznaczone do zainstalowania
innych urządzeń zewnętrznych. Wszystkie niewykorzystywane wpisy
mają wartość zero. Razem z wpisami już istniejącymi w tabeli
HATABS można umieścić 11 różnych urządzeń zewnętrznych.
Dwa bajty adresowe wpisu w HATABS wskazują na tabelę
adresów procedur obsługi poszczególnych operacji wykonywanych
przez urządzenie. Należy zwrócić uwagę, że wszystkie adresy są
zmniejszone o jeden. Ostatnie cztery bajty zawierają rozkaz
skoku do procedury inicjowania oraz bajt zerowy.
+-----------+
+$00 | OPEN-1 |
+-----------+
+$02 | CLOSE-1 |
+-----------+
+$04 | GET-1 |
+-----------+
+$06 | PUT-1 |
+-----------+
+$08 | STATUS-1 |
+-----------+
+$0A | SPECIAL-1 |
+-----------+
+$0C | JMP INIT |
+-----------+
+$0F | $00 |
+-----------+
Rys.5. Tabela adresowa sterownika
Urządzenia zainstalowane na stałe posiadają tabele adresów
zapisaną w pamięci ROM. Można jednak napisać dla nich własne
procedury obsługi i po umieszczeniu w dowolnym miejscu RAM
tabeli adresów zmienić wektor w HATABS tak, aby wskazywał na
nową tabelę adresową. Standardowa tabela zapisana w ROM-ie jest
następująca:
0100 ;DEVice HAndler Table
0110 ;
0120 CASCLS = $FDCF
0130 CASINIT = $FCDB
0140 CASOPN = $FCE6
0150 CASRDBT = $FD7A
0160 CASSP = $FCE5
0170 CASST = $FDCC
0180 CASWRT = $FDB4
0190 DRAW = $F9AF
0200 EDOPN = $EF94
0210 EDSP = $F22D
0220 EGETCH = $F24A
0230 EOUTCH = $F2B0
0240 GETCH = $F180
0250 KBGBYT = $F2FD
0260 KBOPN = $F21E
0270 OUTCH = $F1A4
0280 POWERON = $EF6E
0290 PRCLS = $FF07
0300 PRINIT = $FE99
0310 PROPN = $FEC2
0320 PRRDSP = $FEC1
0330 PRSTAT = $FEA3
0340 PRWRT = $FECB
0350 SCOPN = $EF8E
0360 SCRFIN = $F22E
0370 ;
0380 *= $E400
0390 ;
0400 EDTVEC .WORD EDOPN-1
0410 .WORD SCRFIN-1
0420 .WORD EGETCH-1
0430 .WORD EOUTCH-1
0440 .WORD KBOPN-1
0450 .WORD EDSP-1
0460 JMP POWERON
0470 .BYTE $00
0480 SCRVEC .WORD SCOPN-1
0490 .WORD SCRFIN-1
0500 .WORD GETCH-1
0510 .WORD OUTCH-1
0520 .WORD KBOPN-1
0530 .WORD DRAW-1
0540 JMP POWERON
0550 .BYTE $00
0560 KBDVEC .WORD KBOPN-1
0570 .WORD KBOPN-1
0580 .WORD KBGBYT-1
0590 .WORD EDSP-1
0600 .WORD KBOPN-1
0610 .WORD EDSP-1
0620 JMP POWERON
0630 .BYTE $00
0640 PRTVEC .WORD PROPN-1
0650 .WORD PRCLS-1
0660 .WORD PRRDSP-1
0670 .WORD PRWRT-1
0680 .WORD PRSTAT-1
0690 .WORD PRRDSP-1
0700 JMP PRINIT
0710 .BYTE $00
0720 CASVEC .WORD CASOPN-1
0730 .WORD CASCLS-1
0740 .WORD CASDRBT-1
0750 .WORD CASWRT-1
0760 .WORD CASST-1
0770 .WORD CASSP-1
0780 JMP CASINIT
0790 .BYTE $00
Z tabeli tej pobierane są przez procedurę CIO adresy
procedur obsługi poszczególnych operacji dla konkretnych
urządzeń. Sposób wykorzystania tej tabeli przez procedury
systemu operacyjnego jest opisany w następnych rozdziałach.
Dodanie nowego urządzenia do tabeli HATABS nie wymaga nawet
pisania specjalnej procedury. Do tego celu służy znajdująca się
2już w systemie operacyjnym procedura NEWDEV. Przed jej
wywołaniem trzeba jedynie umieścić w rejestrze X nazwę
urządzenia, a w rejestrze Y i w akumulatorze odpowiednio
młodszy i starszy bajt adresu tabeli adresowej procedur
obsługi.
0100 ;NEW DEVice
0110 ;
0120 HATABS = $031A
0130 ;
0140 *= $EEBC
0150 ;
0160 PHA
0170 TYA
0180 PHA
0190 TXA
0200 LDX #$00
0210 NEXT1 CMP HATABS,X
0220 BEQ FOUND
0230 INX
0240 INX
0250 INX
0260 CPX #$22
0270 BMI NEXT1
0280 LDX #$00
0290 TAY
0300 LDA #$00
0310 NEXT2 CMP HATABS,X
0320 BEQ EMPTY
0330 INX
0340 INX
0350 INX
0360 CPX #$22
0370 BMI NEXT2
0380 PLA
0390 PLA
0400 LDY #$FF
0410 SEC
0420 RTS
0430 FOUND PLA
0440 TAY
0450 PLA
0460 INX
0470 SEC
0480 RTS
0490 EMPTY TYA
0500 STA HATABS,X
0510 PLA
0520 STA HATABS+1,X
0530 PLA
0540 STA HATABS+2,X
0550 CLC
0560 RTS
Na początku procedury zawartości akumulatora i rejestru X
są umieszczane na stosie, a rejestr X (nazwa urządzenia)
przepisywany jest do akumulatora. Następnie wykonywane są dwie
pętle przeszukujące HATABS.
Pierwsza pętla sprawdza, czy urządzenie o podanej nazwie
znajduje się już w HATABS. Jeśli tak, to po odtworzeniu ze
stosu zawartości rejestru Y i akumulatora procedura kończy się
z ustawionym bitem Carry statusu procesora. Rejestr X zawiera
wtedy indeks młodszego bajtu wektora w HATABS, co pozwala na
bezpośrednią zmianę tego wektora poprzez sekwencję rozkazów
STY HATABS,X, INX, STA HATABS,X.
Gdy poszukiwane urządzenie nie zostało znalezione,
wykonywana jest druga pętla. Jej zadaniem jest wykrycie
pierwszego wolnego miejsca na wpis w HATABS. Jeżeli tabela
HATABS jest całkowicie zapełniona, to ustawiany jest bit Carry,
w rejestrze Y umieszczana jest wartość $FF i procedura się
kończy.
Po wykryciu wolnego miejsca w HATABS umieszczana jest w
tabeli nazwa urządzenia, a następnie pobrany ze stosu adres
tabeli jego procedur obsługi. W tym przypadku przed
zakończeniem procedury bit Carry jest kasowany w celu wskazania
pomyślnego przebiegu procedury.
2.2.1. Procedury korzystające z HATABS
Z tabelami adresowymi sterowników jest związanych jeszcze
kilka procedur pomocniczych wykorzystywanych przez procedury
operacji CIO. Są to procedury DEVNUM, CMPENT i GOHAND oraz
pośrednio procedura CIOJMP.
Zadaniem procedury DEVNUM jest ustalenie numeru urządzenia,
którego dotyczy operacja I/O; a w drugiej części
rozpoczynającej się od etykiety DVSRCH - odnalezienie wpisu
urządzenia w HATABS.
0100 ;DEVice NUMber
0110 ;
0120 HATABS = $031A
0130 ICBAZ = $24
0140 ICHIDZ = $20
0150 ICDNOZ = $21
0160 ;
0170 *= $E6FF
0180 ;
0190 SEC
0200 LDY #$01
0210 LDA (ICBAZ),Y
0220 SBC #'1
0230 BMI SET0
0240 CMP #$09
0250 BCC STDN
0260 SET0 LDA #$00
0270 STDN STA ICDNOZ
0280 INC ICDNOZ
0290 ;DeVice SeaRCH
0300 DVSRCH LDY #$00
0310 LDA (ICBAZ),Y
0320 ;Find DeVice HaNDler
0330 FDVHND BEQ ERR
0340 LDY #$21
0350 NEXT CMP HATABS,Y
0360 BEQ SUC
0370 DEY
0380 DEY
0390 DEY
0400 BPL NEXT
0410 ERR LDY #$82
0420 SEC
0430 RTS
0440 SUC TYA
0450 STA ICHIDZ
0460 CLC
0470 RTS
Procedura DEVNUM w celu ustalenia numeru urządzenia pobiera
najpierw drugi bajt z bufora wskazywanego przez rejestr ICBAZ
(bufor musi zawierać nazwę urządzenia). Następnie sprawdza, czy
jego wartość mieści się w dozwolonym zakresie (dopuszczalne są
numery urządzeń od 1 do 9). Poprawny numer urządzenia jest
umieszczany w rejestrze ICDNOZ, a gdy jest nieprawidłowy, to do
ICDNOZ wpisywane jest 1.
Teraz odczytywany jest z bufora pierwszy bajt, który
określa nazwę urządzenia i tabela HATABS jest przeszukiwana w
celu odnalezienia wpisu tego urządzenia. Po napotkaniu wpisu
jego indeks w HATABS jest umieszczany w rejestrze ICHIDZ i bit
Carry jest kasowany. Gdy tabela nie zawiera poszukiwanego
wpisu, to w rejestrze Y umieszczany jest kod błędu $82 (NON
EXISTENT DEVICE) i bit Carry jest ustawiany.
Warto przy tym zauważyć, że tabela HATABS jest
przeszukiwana od końca. Jeżeli więc zostanie umieszczony w niej
drugi wpis tego samego urządzenia (np. nowa procedura obsługi
drukarki), to zostanie on odnaleziony wcześniej niż wpis
oryginalny. Umożliwia to wprowadzenie nowego wpisu bez
kasowania starego.
Procedura CMPENT służy do ustalenia adresu początkowego
procedury obsługi wykonującej żądaną operację I/O. Na początku
odczytywany jest z rejestru ICHIDZ indeks urządzenia w HATABS.
Jeśli jest on większy od $21, to w rejestrze Y umieszczany jest
kod błędu $85 (IOCB NOT OPEN - IOCB nie otwarty) i po
ustawieniu bitu Carry procedura się kończy.
Jeśli wartość indeksu jest prawidłowa, to według niej
wektor tabeli adresowej odczytywany jest z HATABS i umieszczany
w rejestrach ICAX3Z oraz ICAX4Z. Następnie według kodu operacji
pobranego z ICCOMT określany jest (przy pomocy tabeli COMTAB)
indeks adresu procedury, która wykonuje żądaną operację.
Znaleziony adres jest przepisywany z tabeli adresowej do
rejestrów ICAX3Z i ICAX4Z. W celu zasygnalizowania poprawnego
przebiegu procedury, przed jej zakończeniem kasowany jest
jeszcze bit Carry.
0100 ;CoMPute ENTry
0110 ;
0120 COMTAB = $E72D
0130 HATABS = $031A
0140 ICAX3Z = $2C
0150 ICAX4Z = $2D
0160 ICCOMT = $17
0170 ICCOMZ = $22
0180 ICHIDZ = $20
0190 ;
0200 *= $E695
0210 ;
0220 LDY ICHIDZ
0230 CPY #$22
0240 BCC LAD
0250 LDY #$85
0260 BCS END
0270 LAD LDA HATABS+1,Y
0280 STA ICAX3Z
0290 LDA HATABS+2,Y
0300 STA ICAX4Z
0310 LDY ICCOMT
0320 LDA COMTAB+3,Y
0330 TAY
0340 LDA (ICAX3Z),Y
0350 TAX
0360 INY
0370 LDA (ICAX3Z),Y
0380 STA ICAX4Z
0390 STX ICAX3Z
0400 CLC
0410 END RTS
Wywołanie wybranej procedury obsługi urządzenia jest
wykonywane przez procedurę GOHAND.
0100 ;GO to HANDler
0110 ;
0120 CIOJMP = $E6F4
0130 ICSTZ = $23
0140 ;
0150 *= $E6EA
0160 ;
0170 LDY #$92
0180 JSR CIOJMP
0190 STY ICSTZ
0200 CPY #$00
0210 RTS
Umieszcza ona najpierw w rejestrze Y kod błędu $92
(FUNCTION NOT IMPLEMENTED - operacja niedozwolona), a następnie
poprzez procedurę CIOJMP wywołuje sterownik urządzenia
zewnętrznego. Po zakończeniu operacji i powrocie do GOHAND
zawartość rejestru Y jest przepisywana do ICSTZ, a poprzez
rozkaz CPY bit Negative rejestru statusu otrzymuje wartość
sygnalizującą powodzenie (lub nie) operacji. Umieszczenie w
rejestrze Y kodu błędu $92 przed wywołaniem procedury obsługi
żądanej operacji znakomicie upraszcza projektowanie procedur
operacji niedozwolonych - wystarczy jako adres takiej operacji
podać adres rozkazu RTS. Rozwiązanie to jest często stosowane w
OS Atari oraz w sterownikach urządzeń instalowanych po
zainicjowaniu systemu.
Procedura CIOJMP służy wyłącznie do wykonania skoku do
procedury obsługi urządzenia, której adres jest zawarty w
rejestrach ICAX3Z i ICAX4Z. Bardzo interesujący jest natomiast
sposób wykonania tego skoku.
0100 ;CIO JuMP routine
0110 ;
0120 ICAX3Z = $2C
0130 ICAX4Z = $2D
0140 ICAX5Z = $2E
0150 ;
0160 *= $E6F4
0170 ;
0180 TAX
0190 LDA ICAX4Z
0200 PHA
0210 LDA ICAX3Z
0220 PHA
0230 TXA
0240 LDX ICAX5Z
0250 RTS
Zastosowana sztuczka polega na tym, że bajty adresu
procedury pobrane z rejestrów ICAX3/4Z są umieszczane na
stosie. Wykonanie teraz rozkazu RTS powoduje zdjęcie ze stosu
dwóch znajdujących się tam bajtów, które normalnie oznaczają
stan licznika rozkazów w chwili wykonania rozkazu JSR,
zwiększenie ich o jeden i umieszczenie w liczniku rozkazów
procesora. W ten sposób dalsze wykonywanie programu odbywa się
od początku odpowiedniej procedury obsługi urządzenia. Kończący
tą procedurę rozkaz RTS spowoduje powrót do miejsca wywołania
CIOJMP, a więc bezpośrednio do procedury GOHAND. Oczywiste jest
już także umieszczenie w tabeli adresowej adresów procedur
zmniejszonych o jeden.
2.3. Procedura otwarcia IOCB
Rozpoznanie przez CIOMAIN kodu operacji OPEN ($03) powoduje
wywołanie procedury CIOOPN. Dla jej poprawnego wykonania
rejestr ICBUFA musi zawierać adres nazwy urządzenia, dla
którego otwierany jest kanał IOCB (np. S: lub D:NAZWA.EXT).
Ponadto w ICAX1 muszą znajdować się informacje o sposobie
dostępu do urządzenia (zapis czy odczyt) i ewentualnie inne
informacje zależne od rodzaju urządzenia. Niektóre urządzenia
wymagają jeszcze dodatkowych danych w rejestrze ICAX2.
0100 ;CIO OPeN routine
0110 ;
0120 CIORET = $E670
0130 CMPENT = $E695
0140 CPLCIO = $E672
0150 DEVNUM = $E6FF
0160 DVSTAT = $02EA
0170 GOHAND = $E6EA
0180 HNDLOD = $02E9
0190 ICAX3Z = $2C
0200 ICAX4Z = $2D
0210 ICCOMT = $17
0220 ICHIDZ = $20
0230 ICPTZ = $26
0240 SPCHND = $EEF9
0250 ;
0260 *= $E53F
0270 ;
0280 LDA ICHIDZ
0290 CMP #$FF
0300 BEQ OPN
0310 LDY #$81
0320 EXIT JMP CIORET
0330 OPN LDA HNDLOD
0340 BNE END
0350 JSR DEVNUM
0360 BCS END
0370 LDA #$00
0380 STA DVSTAT
0390 STA DVSTAT+1
0400 ;INItialize for OPeN
0410 INIOPN JSR CMPENT
0420 BCS EXIT
0430 JSR GOHAND
0440 LDA #$0B
0450 STA ICCOMT
0460 JSR CMPENT
0470 LDA ICAX3Z
0480 STA ICPTZ
0490 LDA ICAX4Z
0500 STA ICPTZ+1
0510 JMP CPLCIO
0520 END JSR SPCHND
0530 JMP CIORET
Przede wszystkim na początku procedury sprawdzany jest
indeks wpisu w HATABS. Gdy jest on różny od $FF, to w rejestrze
Y umieszczany jest kod błędu $81 (PREVIOUS OPEN - uprzednio
otwarty) i następuje skok do CIORET. Ma to na celu
zabezpieczenie przed jednoczesnym otwarciem tego samego kanału
IOCB dla dwóch różnych urządzeń.
Następnie kontrolowany jest rejestr HNDLOD, który wskazuje
użycie nowego urządzenia i wywoływana jest procedura DEVNUM w
celu odszukania wpisu urządzenia w HATABS. Negatywny wynik
którejkolwiek z tych operacji powoduje wywołanie specjalnej
procedury obsługi SPCHND, a następnie skok do CIORET.
Jeśli wpis urządzenia w HATABS został odnaleziony, to
procedura CMPENT odczytuje z tabeli adresowej urządzenia adres
procedury otwierającej kanał dla tego urządzenia. Następujące
po tym sprawdzenie pozytywnego wyniku jest konieczne ze względu
na to, że niektóre procedury komunikacji z urządzeniami
zewnętrznymi korzystają z CIOOPN od miejsca oznaczonego
etykietą INIOPN.
Teraz poprzez GOHAND jest wywoływana właściwa procedura
otwarcia urządzenia. Po jej zakończeniu w rejestrze ICSTZ
znajduje się status wykonanej operacji informujący o jej
pomyślnym (lub nie) przebiegu.
W ostatniej fazie procedury do rejestru ICCOMT wpisywany
jest kod rozkazu PUT BYTE i ponownie wywoływana jest procedura
CMPENT. Odnaleziony przez nią adres procedury PUT BYTE
urządzenia jest przepisywany do rejestru ICPTZ. Procedura
CIOOPN kończy się skokiem do CPLCIO.
Po zakończeniu procedury CIOOPN odpowiedni IOCB zawiera: w
rejestrze ICCHID - indeks wpisu urządzenia w HATABS, w
rejestrze ICDNO - numer urządzenia oraz w rejestrze ICSTAT -
wynik (status) operacji OPEN.
2.4. Procedura zamknięcia IOCB
Kod operacji CIO równy $0C powoduje wywołanie procedury
CIOCLS, której zadaniem jest zamknięcie odpowiedniego kanału
IOCB. Operacja CLOSE nie wymaga żadnych dodatkowych informacji
w rejestrach IOCB.
0100 ;CIO CLoSe routine
0110 ;
0120 CIONOPN = $E4DC
0130 CPLCIO = $E672
0140 CMPENT = $E695
0150 GOHAND = $E6EA
0160 ICHIDZ = $20
0170 ICPTZ = $26
0180 ICSTZ = $23
0190 ;
0200 *= $E57C
0210 ;
0220 LDY #$01
0230 STY ICSTZ
0240 JSR CMPENT
0250 BCS CLS
0260 JSR GOHAND
0270 CLS LDA #$FF
0280 STA ICHIDZ
0290 LDA # >[CIONOPN-1]
0300 STA ICPTZ+1
0310 LDA # <[CIONOPN-1]
0320 STA ICPTZ
0330 JMP CPLCIO
Od razu na początku procedury status operacji jest
ustawiany na $01 (SUCCESS). Następnie przez procedurę CMPENT
wyszukiwany jest adres procedury zamykającej komunikację z
urządzeniem i procedura ta jest wywoływana poprzez GOHAND.
Zarówno w przypadku nieodnalezienia przez CMPENT
odpowiedniego wpisu w HATABS, jak i po zakończeniu procedury
GOHAND (ewentualny błąd jest przez nią sygnalizowany w
rejestrze ICSTZ) dalsze postępowanie jest identyczne. Indeks
wpisu urządzenia w HATABS jest ustawiany na wartość $FF, a
wektor procedury obsługi w rejestrze ICPTZ wskazuje na
procedurę CIONOPN. Procedura ta umieszcza jedynie w rejestrze Y
kod błędu $85 (NOT OPEN).
0100 ;CIO Not OPeN
0110 ;
0120 *= $E4DC
0130 ;
0140 LDY #$85
0150 RTS
Po zakończeniu operacji CLOSE rejestr ICCHID ma więc
wartość $FF, a w rejestrze ICSTAT znajduje się wynik operacji.
2.5. Procedura odczytu z urządzenia
Procedura odczytu CIO jest wywoływana po rozpoznaniu kodu
$07 (GET BYTE) lub $05 (GET RECORD). Obie operacje są
wykonywane przez tą samą procedurę, która rozpoznaje różnicę
według bitu 1 kodu operacji (ustawiony = BYTE, skasowany =
RECORD). Przed wywołaniem CIOMAIN konieczne jest jeszcze
umieszczenie w rejestrze ICBUFA adresu bufora i w rejestrze
ICBUFL jego długości. Jeżeli długość bufora jest równa zero, to
odczytany znak umieszczany jest w akumulatorze. Zamieszczony
poniżej schemat ukazuje przybliżoną strukturę operacji odczytu.
< CIOREAD >
|
v
/-------\
/ czy \ nie
< dozwolony >---->----+
\ odczyt? / |
\-------/ v
| tak +-------+
v | Y=$83 |
++--------++ +-------+
|| CMPENT || |
++--------++ |
| |
v |
/-----\ tak |
< błąd? >---->---+ |
\-----/ | |
| nie v v
v +--------+
+------------>+ | CIORET |
| | +--------+
| v
| +--------+
| | odczyt |
| | bajtu |
| +--------+
| |
| v
| /-----\ tak
| < błąd? >---->---+
| \-----/ |
| | nie |
| v |
| nie /-------\ tak v
+---<----< koniec? >------>+
\-------/ |
v
+--------+
| CPLCIO |
+--------+
Rys.6. Struktura operacji READ
Przed rozpoczęciem operacji odczytu kontrolowany jest bit 2
rejestru ICAX1, który sygnalizuje możliwość odczytu z
urządzenia. Jeśli jest on skasowany, to do rejestru Y wpisywany
jest kod błędu $83 (WRITE ONLY - dozwolony tylko zapis) i
operacja kończy się skokiem do CIORET. Następnie procedura
CMPENT odszukuje adres procedury odczytu z urządzenia, a w
przypadku niepowodzenia także przechodzi się do CIORET (w takim
razie rejestr Y zawiera kod $85 - NOT OPEN).
0100 ;CIO READ routine
0110 ;
0120 CIORET = $E670
0130 CPLCIO = $E672
0140 DECBUFL = $E6BB
0150 DECBUFP = $E6C8
0160 CMPENT = $E695
0170 GOHAND = $E6EA
0180 ICAX1Z = $2A
0190 ICAX6Z = $2F
0200 ICBAZ = $24
0210 ICBLZ = $28
0220 ICCOMZ = $22
0230 ICSTZ = $23
0240 INCBUFP = $E6D1
0250 SUBBUFL = $E6D8
0260 ;
0270 *= $E5B2
0280 ;
0290 LDA ICCOMZ
0300 AND ICAX1Z
0310 BNE PRFM
0320 LDY #$83
0330 EXIT JMP CIORET
0340 PRFM JSR CMPENT
0350 BCS EXIT
0360 LDA ICBLZ
0370 ORA ICBLZ+1
0380 BNE GET1
0390 JSR GOHAND
0400 STA ICAX6Z
0410 JMP CPLCIO
0420 GET1 JSR GOHAND
0430 STA ICAX6Z
0440 BMI END
0450 LDY #$00
0460 STA (ICBAZ),Y
0470 JSR INCBUFP
0480 LDA ICCOMZ
0490 AND #$02
0500 BNE NEXT
0510 LDA ICAX6Z
0520 CMP #$9B
0530 BNE NEXT
0540 JSR DECBUFL
0550 JMP END
0560 NEXT JSR DECBUFL
0570 BNE GET1
0580 LDA ICCOMZ
0590 AND #$02
0600 BNE END
0610 GET2 JSR GOHAND
0620 STA ICAX6Z
0630 BMI ZBF
0640 LDA ICAX6Z
0650 CMP #$9B
0660 BNE GET2
0670 LDA #$89
0680 STA ICSTZ
0690 ZBF JSR DECBUFP
0700 LDY #$00
0710 LDA #$9B
0720 STA (ICBAZ),Y
0730 JSR INCBUFP
0740 END JSR SUBBUFL
0750 JMP CPLCIO
Właściwy odczyt rozpoczyna się od sprawdzenia długości
bufora. Gdy jest ona równa zero, to poprzez wywołanie GOHAND
odczytywany jest do akumulatora bajt z urządzenia. Po jego
przepisaniu do rejestru ICAX6Z procedura kończy się skokiem do
CPLCIO.
Przy niezerowej długości bufora postępowanie jest podobne,
lecz zamiast zakończenia odczytu następuje sprawdzenie statusu
operacji. Ewentualne wystąpienie błędu przerywa odczyt (przed
opuszczeniem CIOREAD korygowana jest jeszcze długość bufora).
Prawidłowo odczytany bajt jest przepisywany z akumulatora w
miejsce określone zawartością rejestru ICBAZ. Aby następny znak
został wpisany w kolejne miejsce pamięci, to zawartość ICBAZ
jest zwiększane przez procedurę INCBUFP.
0100 ;INCrement BUFfer Pointer
0110 ;
0120 ICBAZ = $24
0130 ;
0140 *= $E6D1
0150 ;
0160 INC ICBAZ
0170 BNE END
0180 INC ICBAZ+1
0190 END RTS
Teraz kontrolowany jest bit 1 kodu operacji, który określa
jej rodzaj (zob. wyżej). Gdy odczytywany jest bajt, to CIOREAD
kończy się po zmniejszeniu rejestru określającego długość
bufora (poprzez procedurę DECBUFL). Dla wybrania odpowiedniego
wariantu procedury bit 1 jest kontrolowany potem jeszcze raz.
Przy odczytywaniu rekordu trzeba sprawdzić, czy odczytany znak
jest kodem końca linii ($9B - RETURN). Jeżeli tak, to po
zmniejszeniu długości bufora odczyt również się kończy.
W przeciwnym razie także zmniejszana jest długość bufora i
gdy jest większa od zera, to procedura odczytu bajtu jest
powtarzana. W celu zmniejszenia wskaźnika długości bufora
(ICBLZ) wywoływana jest specjalna procedura DECBUFL. Zwraca ona
w akumulatorze wartość zero, jeśli długość bufora jest równa
zero lub wartość niezerową w przeciwnym wypadku, co ułatwia
wybór wariantu procedury.
0100 ;DECrement BUFfer Length
0110 ;
0120 ICBLZ = $28
0130 ;
0140 *= $E6BB
0150 ;
0160 LDA ICBLZ
0170 BNE SKIP
0180 DEC ICBLZ+1
0190 SKIP DEC ICBLZ
0200 LDA ICBLZ
0210 ORA ICBLZ+1
0220 RTS
Jeżeli cały bufor został już zapełniony (długość bufora
równa zero), to procedura GOHAND jest wywoływana w pętli w celu
2odczytania pozostałej części rekordu. Odczytane bajty nie są
nigdzie przechowywane i zostają stracone. Pętla jest przerywana
po wystąpieniu błędu lub po napotkaniu kodu RETURN ($9B). W tym
ostatnim przypadku w rejestrze Y umieszczany jest kod błędu $89
(TRUNCATED RECORD - część rekordu utracona). Ponieważ bufor
jest już pełny, to procedura DECBUFP zmniejsza jego adres o
jeden.
0100 ;DECrement BUFfer Pointer
0110 ;
0120 ICBAZ = $24
0130 ;
0140 *= $E6C8
0150 ;
0160 LDA ICBAZ
0170 BNE END
0180 DEC ICBAZ+1
0190 DEC ICBAZ
0200 END RTS
W uzyskane w ten sposób miejsce wpisywany jest znak RETURN
i adres bufora jest ponownie zwiększany przez procedurę
INCBUFP.
Po wszystkich opisanych wyżej wariantach zakończenia
odczytu, przed opuszczeniem CIOREAD jest jeszcze wywoływana
procedura SUBBUFL, której zadaniem jest uaktualnienie długości
bufora dla operacji CIO. Wykorzystuje ona do rozpoznania
właściwego IOCB jego numer zapisany w rejestrze ICAX5Z.
0100 ;SUBtract BUFfer Length
0110 ;
0120 ICAX5Z = $2E
0130 ICBLZ = $28
0140 ICBUFL = $0348
0150 ;
0160 *= $E6D8
0170 ;
0180 LDX ICAX5Z
0190 SEC
0200 LDA ICBUFL,X
0210 SBC ICBLZ
0220 STA ICBLZ
0230 LDA ICBUFL+1,X
0240 SBC ICBLZ+1
0250 STA ICBLZ+1
0260 RTS
Procedura odejmuje od początkowej długości bufora wpisanej
w ICBUFL długość jego części zajętej przez odczytane dane
(zawiera ją rejestr ICBLZ). W wyniku otrzymujemy długość
pozostałej jeszcze (pustej) części bufora.
Po zapoznaniu się z przebiegiem CIOREAD można łatwo
określić różnicę pomiędzy operacjami GET BYTE i GET RECORD.
Przy odczycie rekordu znak RETURN ($9B) przerywa odczyt, a jego
brak powoduje przepełnienie bufora i utratę części informacji.
Operacja GET BYTE kończy się natomiast po zapełnieniu bufora, a
znak o kodzie $9B jest traktowany tak, jak wszystkie pozostałe.
2.6. Procedura zapisu na urządzenie.
Kody operacji $09 (PUT RECORD) i $0B (PUT BYTE) powodują
wywołanie z CIOMAIN procedury CIOWRT. Przebiega ona w sposób
bardzo zbliżony do procedury CIOREAD, a wymagane dla niej
parametry są identyczne (ICBUFA i ICBUFL). Struktura procedury
CIOWRT jest pokazana na rysunku 7.
< CIOWRT >
|
v
/-------\
/ czy \ nie
< dozwolony >---->----+
\ zapis ? / |
\-------/ v
| tak +-------+
v | Y=$87 |
++--------++ +-------+
|| CMPENT || |
++--------++ |
| |
v |
/-----\ tak |
< błąd? >---->---+ |
\-----/ | |
| nie v v
v +--------+
+------------>+ | CIORET |
| | +--------+
| v
| +-------+
| | zapis |
| | bajtu |
| +-------+
| |
| v
| /-----\ tak
| < błąd? >---->---+
| \-----/ |
| | nie |
| v |
| nie /-------\ tak v
+---<----< koniec? >------>+
\-------/ |
v
+--------+
| CPLCIO |
+--------+
Rys.7. Struktura operacji WRITE
Podobnie jak przy odczycie na początku kontrolowany jest
bit 3 rejestru ICAX1, który sygnalizuje możliwość zapisu na
urządzenie. Jeśli jest on skasowany, to do rejestru Y wpisywany
0100 ;CIO WRiTe routine
0110 ;
0120 CIORET = $E670
0130 CPLCIO = $E672
0140 CMPENT = $E695
0150 DECBUFL = $E6BB
0160 GOHAND = $E6EA
0170 ICAX1Z = $2A
0180 ICAX6Z = $2F
0190 ICBAZ = $24
0200 ICBLZ = $28
0210 ICCOMZ = $22
0220 INCBUFP = $E6D1
0230 SUBBUFL = $E6D8
0240 ;
0250 *= $E61E
0260 ;
0270 LDA ICCOMZ
0280 AND ICAX1Z
0290 BNE PRFM
0300 LDY #$87
0310 EXIT JMP CIORET
0320 PRFM JSR CMPENT
0330 BCS EXIT
0340 LDA ICBLZ
0350 ORA ICBLZ+1
0360 BNE LBF
0370 LDA ICAX6Z
0380 INC ICBLZ
0390 BNE PUT
0400 LBF LDY #$00
0410 LDA (ICBAZ),Y
0420 STA ICAX6Z
0430 PUT JSR GOHAND
0440 PHP
0450 JSR INCBUFP
0460 JSR DECBUFL
0470 PLP
0480 BMI END
0490 LDA ICCOMZ
0500 AND #$02
0510 BNE NEXT
0520 LDA ICAX6Z
0530 CMP #$9B
0540 BEQ END
0550 NEXT LDA ICBLZ
0560 ORA ICBLZ+1
0570 BNE LBF
0580 LDA ICCOMZ
0590 AND #$02
0600 BNE END
0610 LDA #$9B
0620 JSR GOHAND
0630 END JSR SUBBUFL
0640 JMP CPLCIO
jest kod błędu $87 (READ ONLY - dozwolony tylko odczyt) i
operacja kończy się skokiem do CIORET. Następnie przez CMPENT
wyszukiwany jest adres procedury zapisu (w przypadku
niepowodzenia skok do CIORET z kodem $85 w rejestrze Y).
Poprzez sprawdzenie długości bufora określane jest miejsce
pobrania znaku do wysłania. Jeżeli bufor ma zerową długość, to
znak pobierany jest z akumulatora, w przeciwnym razie wysyłany
jest pierwszy znak z bufora. Samo wysłanie bajtu, który zostaje
przepisany do ICAX6Z, jest wykonywane przez wywołanie procedury
obsługi urządzenia poprzez GOHAND. Następnie przez wywołanie
INCBUFP i DECBUFL zwiększany jest adres bufora i zmniejszana
jego długość.
Teraz wykonywana jest seria sprawdzeń różnych warunków.
Procedura zapisu jest przerywana, jeśli wystąpił błąd przy
zapisie, jeśli zapisywany był bajt (PUT BYTE) i długość bufora
jest równa zero lub jeśli przy zapisywaniu rekordu został
wysłany znak RETURN. Jeżeli przy zapisie bajtów długość bufora
jest różna od zera, to następny bajt z bufora jest przepisywany
do ICAX6Z i zapis jest powtarzany. Zerowa długość bufora w
przypadku zapisu rekordu powoduje jeszcze przed zakończeniem
operacji zapisanie bajtu $9B (RETURN).
We wszystkich wymienionych przypadkach zakończenia operacji
zapisu, przed opuszczeniem CIOWRT jest jeszcze uaktualniana
długość bufora (przy pomocy SUBBUFL). Cała operacja zapisu
kończy się skokiem do CPLCIO.
Dokładniejsze informacje o procedurach DECBUFL, INCBUFP i
SUBBUFL znajdują się w rozdziale 2.5. (Procedura odczytu z
urządzenia).
2.7. Odczyt statusu i procedury specjalne
Wszystkie kody operacji o wartości równej lub większej od
$0D powodują wywołanie procedury CIOSTSP. Kod $0D oznacza
operację odczytu statusu urządzenia, zaś wyższe kody są
rozkazami operacji specjalnych, których przebieg zależy od
rodzaju urządzenia.
Procedura ta, jako jedyna z procedur CIO, umożliwia
wykonanie operacji BEZ uprzedniego otwierania urządzenia
operacją OPEN. Najpierw sprawdzany jest bowiem indeks wpisu w
HATABS (zawarty w rejestrze ICHIDZ). Jeżeli ma on wartość $FF,
to wywoływana jest procedura DEVNUM, która wyszukuje prawidłowy
indeks (wystąpienie przy tym błędu przerywa operację skokiem do
CIORET).
0100 ;CIO STatus/SPecial routine
0110 ;
0120 CPLCIO = $E672
0130 CMPENT = $E695
0140 DEVNUM = $E6FF
0150 GOHAND = $E6EA
0160 ICAX5Z = $2E
0170 ICCHID = $0340
0180 ICHIDZ = $20
0190 ;
0200 *= $E597
0210 ;
0220 LDA ICHIDZ
0230 CMP #$FF
0240 BNE PRFM
0250 JSR DEVNUM
0260 BCS $E547 ;do JMP CIORET
0270 PRFM JSR CMPENT
0280 JSR GOHAND
0290 LDX ICAX5Z
0300 LDA ICCHID,X
0310 STA ICHIDZ
0320 JMP CPLCIO
Dalszy przebieg procedury CIOSTSP jest podobny do opisanych
wcześniej. Adres sterownika jest odszukiwany przez wywołanie
CMPENT, a sama procedura obsługi wywoływana jest poprzez
GOHAND. Ponieważ podczas procedury CIOMAIN zmieniane są kody
operacji większe od $0D, to przed zakończeniem CIOSTSP
prawidłowy kod jest odtwarzany według zawartości właściwego
IOCB. Procedura kończy się skokiem do CPLCIO.
|