;******************************************************************************* ;* * ;* K o m u n i k a č n í o v l a d a č p r o a d a p t é r Z N E T * ;* * ;******************************************************************************* czech equ 1 ; česky =1 eng equ 0 ; anglick = 1 video equ 0B000H ; hercules 0B000H debug equ 0 dbg equ 0 if card12 c_max equ 10 else c_max equ 5 endif include com.asm p59 equ 20H ; adresa 8259 p591 equ 21H p59at equ 0A0H ; adresa 8259 slave p591at equ 0A1H int_irq2 equ 0AH int_irq2at equ 71H ; společná oblast ZNET a PC RAM z_rom1 equ 0CC00H ; adresní prostor pro ZNET z_ram1 equ 0CD00H z_rom2 equ 0CE00H z_ram2 equ 0CF00H rt_area struc ; oblasti ZNET pro vysílání a příjem z_sem db ? ; semafor - stav oblasti z_len dw ? ; délka zprávy z_to1 db ? ; adresát - zprostředkovatel z_ack db ? ; žádost o potvrzení z_from1 db ? ; odesilatel - zprostředkovatel z_to dw ? ; síťová adresa skutečného adresáta (koncového) z_from dw ? ; síťová adresa koncového odesilatele z_in dw ? ; pro kontrolu délka zprávy vysilané z_msg db 591 dup (?) ; vlastní text zprávy rt_area ends msg_hdr equ 9 eoi equ 20H z_ramseg segment at z_ram1 and 0FFFFH swtch db ? ; stav přepínačů adaptéru swtch2 db ? ; moje adresa převzatá z přepínačů tx_cnt db ? ; čítač kolizí při vysílání rx_cnt db ? ; čítač chybně přijatých paketů tx_area rt_area <> ; vysílací oblast rx1_area rt_area <> ; první přijímací oblast dw ? ; rezerva pro CRC rx2_area rt_area <> ; druhá přijímací oblast post dw ? ; výsledek autotestu adaptéru z_ramseg ends z_romseg segment at z_rom1 and 0FFFFH sign dw ? epsize db ? z_romseg ends resident segment assume cs:resident,ds:resident tx_wait db 0 ; po vysílacím timeoutu čekej ; ****** vysílání ****** ; SI ukazuje na c_blok to_card1: mov ax,z_ram1 mov es,ax mov dl,[si].c_near ; komu ve větvi mov es:tx_area.z_to1,dl push ds lds di,[si].c_scb mov al,[di].s_ack pop ds cmp dl,255 jnz tz1_11 mov al,0 tz1_11: mov es:tx_area.z_ack,al ; potvrzení mov ax,[si].c_from mov es:tx_area.z_from,ax ; původní odesilatel lds si,[si].c_scb mov ax,[si].s_to mov es:tx_area.z_to,ax ; koncový adresát mov cx,[si].s_len mov ax,cx ; délka add ax,msg_hdr mov es:tx_area.z_len,ax mov es:tx_area.z_in,ax lds si,[si].s_buf ; přesun textu zprávy do ZNET cmp byte ptr [si],1 ; odpověď na Boot ? jnz tz1_2 ; !!! možná do společné části mov es:tx_area.z_from,0 mov es:tx_area.z_to,0 tz1_2: mov di,offset tx_area.z_msg cld rep movsb push cs pop ds mov es:tx_area.z_sem,1 ; vysílej mov tx1_busy,1 ; stav - vysílá se ret if card2 to_card2: mov ax,z_ram2 mov es,ax mov dl,[si].c_near ; komu ve větvi mov es:tx_area.z_to1,dl push ds lds di,[si].c_scb mov al,[di].s_ack pop ds cmp dl,255 jnz tz2_11 mov al,0 tz2_11: mov es:tx_area.z_ack,al ; potvrzení mov ax,[si].c_from mov es:tx_area.z_from,ax ; původní odesilatel lds si,[si].c_scb mov ax,[si].s_to mov es:tx_area.z_to,ax ; koncový adresát mov cx,[si].s_len mov ax,cx ; délka add ax,msg_hdr mov es:tx_area.z_len,ax mov es:tx_area.z_in,ax lds si,[si].s_buf ; přesun textu zprávy do ZNET cmp byte ptr [si],1 ; odpověď na Boot ? jnz tz2_2 ; !!! možná do společné části mov es:tx_area.z_from,0 mov es:tx_area.z_to,0 tz2_2: mov di,offset tx_area.z_msg cld rep movsb push cs pop ds mov es:tx_area.z_sem,1 ; vysílej mov tx2_busy,1 ; stav - vysílá se ret endif ; ***************************************************************************** ; Proces pro obsluhu ZNET. Aktivuje se v přerušovací rutině IRQ2 nastavením ; příznaku číslo nula. Nejprve se kontroluje příjem, pak vysílání. ; ****************************************************************************** znet_flg db ? db 500 dup (?) znet_st dw ? ; BP dw ? ; DI dw ? ; SI dw ? ; DX dw ? ; CX dw ? ; ES dw resident ; DS dw ? ; BX dw ? ; AX dw offset card_loop ; IP dw resident ; CS dw 0200H ; flags - STI card_loop: if debug push es mov ax,video mov es,ax inc byte ptr es:0 pop es endif if card1 mov ax,z_ram1 mov es,ax cmp es:rx1_area.z_sem,0 jz zs1_1 mov ah,byte ptr my_addr mov bx,offset rx1_area ; obsluha příjmu - 1. oblast call znet_rcv zs1_1: cmp es:rx2_area.z_sem,0 jz zs1_2 mov ah,byte ptr my_addr mov bx,offset rx2_area ; 2. oblast call znet_rcv zs1_2: cmp tx1_busy,1 ; vysílá se ? je zs1_21 jmp zs1_9 zs1_21: mov al,es:tx_area.z_sem ; v jakém stavu je vysílání ? or al,al jz zs1_4 ; vysláno OK cmp al,80H ; chybné parametry jz zs1_4 ; jako by se vyslalo správně inc al jz zs1_22 jmp zs1_9 ; ZNET čeká na potvrzení zs1_22: mov bx,tx1_act ; nepřišlo dec [bx].c_rpt ; nepřišlo potvrzení jnz zs1_3 ; zkus později znovu vyslat mov al,er_noack ; již neopakuj a ohlaš chybu jmp short zs1_4 zs1_3: mov [bx].c_next,0 cli ; dej na konec fronty mov di,tx1_q9 or di,di jnz zs1_33 ; připoj na konec mov tx1_q1,bx ; jediný ve frontě mov tx1_q9,bx sti call send_end11 jmp short zs1_9 zs1_33: mov [di].c_next,bx ; připojení na konec mov tx1_q9,bx sti call send_end11 ; zkus znovu vysílat jmp short zs1_9 zs1_4: and al,7FH call send_end1 zs1_9: endif if card2 mov ax,z_ram2 mov es,ax cmp es:rx1_area.z_sem,0 jz zs2_1 mov ah,byte ptr my_addr2 mov bx,offset rx1_area ; obsluha příjmu - 1. oblast call znet_rcv zs2_1: cmp es:rx2_area.z_sem,0 jz zs2_2 mov ah,byte ptr my_addr2 mov bx,offset rx2_area ; 2. oblast call znet_rcv zs2_2: cmp tx2_busy,1 ; vysílá se ? je zs2_21 jmp zs2_9 zs2_21: mov al,es:tx_area.z_sem ; v jakém stavu je vysílání ? or al,al jz zs2_4 ; vysláno OK cmp al,80H ; chybné parametry jz zs2_4 ; jako by se vyslalo správně inc al jz zs2_22 jmp zs2_9 ; ZNET čeká na potvrzení zs2_22: mov bx,tx2_act ; nepřišlo dec [bx].c_rpt ; nepřišlo potvrzení jnz zs2_3 ; zkus později znovu vyslat mov al,er_noack ; již neopakuj a ohlaš chybu jmp short zs2_4 zs2_3: mov [bx].c_next,0 cli ; dej na konec fronty mov di,tx2_q9 or di,di jnz zs2_33 ; připoj na konec mov tx2_q1,bx ; jediný ve frontě mov tx2_q9,bx sti call send_end21 jmp short zs2_9 zs2_33: mov [di].c_next,bx ; připojení na konec mov tx2_q9,bx sti call send_end21 ; zkus znovu vysílat jmp short zs2_9 zs2_4: and al,7FH call send_end2 zs2_9: endif zs9_9: mov ah,k_wait ; konec - čekej na příznak mov al,znet_flg int int_ker jmp card_loop fz_boot: if dbg push es push ax mov ax,video mov es,ax mov al,'3' mov byte ptr es:0,al pop ax pop es endif mov es:[bx].z_to,dx ; žádost o boot mov al,es:[bx].z_from1 mov byte ptr es:[bx].z_from+1,al fz_loc: cli ; zpráva je pro mne, alokuj buffer DI ; mov dx,my_addr ; mov byte ptr es:[bx].z_from,dl mov di,b_free or di,di jz fz0 ; buffery vyčerpány mov ax,[di].b_next mov b_free,ax sti mov [di].b_next,0 lea si,[bx].z_to ; přesun i s řídicími informacemi push es push bx sub cx,msg_hdr mov es:[bx].z_in,cx add cx,6 mov ax,ds ; xchg es,ds mov dx,es mov ds,dx mov es,ax mov ax,di lea di,[di].b_to cld rep movsb push cs pop ds mov si,ax call inqueue ; do přijímací fronty pop bx pop es mov es:[bx].z_sem,0 ret ;******************************************************************************* ; ES:BX ukazuje na přijímací oblast ZNET, kde je přijatá zpráva ; AH číslo větve pro obsluhovanou ZNET. ; V případě žádosti o Boot Block se vyplní úplné adresy odesilatele ; i adresáta. Je-li zpráva určena pro mne, přidělí se buffer a zařadí ; do přijímací fronty pomocí INQUEUE. Jinak se přidělí c blok, buffer ; a vše se řeší komplexně pomocí SEND. ; ES se zachová. ;******************************************************************************* znet_rcv: if dbg push es push ax mov ax,video mov es,ax mov al,'1' mov byte ptr es:0,al pop ax pop es endif mov cx,es:[bx].z_len ; očekávaná a přijatá délka cmp cx,es:[bx].z_in je fz2 ; při chybě zprávu zahoď fz0: sti mov es:[bx].z_sem,0 ; a znovu přijímej fz1: ret fz2: if dbg push es push ax mov ax,video mov es,ax mov al,'2' mov byte ptr es:0,al pop ax pop es endif mov dx,my_addr cmp byte ptr es:[bx].z_from,0 jne fz20 mov byte ptr es:[bx].z_from,ah ; větev odesilatele fz20: mov al,byte ptr es:[bx].z_msg or al,al je fz_boot ; v žádosti o boot vyplň úplné adresy cmp dx,es:[bx].z_to je fz_loc ; adresováno pro mne mov dl,0 cmp dx,es:[bx].z_to jne fz21 jmp fz_loc fz21: cmp es:[bx].z_to1,255 jne fz25 mov dx,my_addr mov es:[bx].z_to,dx jmp fz_loc fz25:; cmp byte ptr es:[bx].z_to,255 ; jne fz26 ; mov byte ptr es:[bx].z_to,0 fz26: cli mov di,b_free ; zprávu je třeba přesměrovat or di,di ; alokace bufferu do DI jz fz0 ; buffer není volný, zprávu zahoď mov ax,[di].b_next mov b_free,ax mov si,c_free ; dále alokuj řidicí blok do SI or si,si jnz fz3 mov [di].b_next,ax ; řidicí bloky vyčerpány, vrať buffer mov b_free,di ; a zprávu zahoď sti mov es:[bx].z_sem,0 ret fz3: mov ax,[si].c_next mov c_free,ax sti mov [si].c_next,0 ; SI - řídicí blok mov [di].b_next,0 ; DI - buffer mov [si].c_mybuf,1 mov word ptr [si].c_scb+2,ds; ES:BX - zpráva ve ZNET mov word ptr [si].c_buf+2,ds lea ax,[si].c_reply ; adresa SCB mov word ptr [si].c_scb,ax mov ax,es:[bx].z_from ; odesilatel mov [si].c_from,ax mov [si].c_sem,0 ; příznak mov al,es:[bx].z_ack mov [si].c_ack,al ; potvrzování mov ax,es:[bx].z_to mov [si].c_to,ax ; adresát sub cx,msg_hdr mov [si].c_len,cx ; délka mov word ptr [si].c_buf,di; adresa bufferu push es push bx xchg bx,si add si,z_msg mov bp,es mov dx,ds mov es,dx mov ds,bp cld rep movsb pop si mov [si].z_sem,0 ; už zas můžeš přijímat mov ds,dx mov [bx].c_timcnt,10 mov si,bx call send pop es ret ; ***************************************************************************** ; Proces pro obsluhu ZNET volanou prostřednictvím časovače. ; ****************************************************************************** refresh db 10 ; XT 10, AT 2 ztim_tim dw 3 ztim_flg db ? db 500 dup (?) ztim_st dw ? ; BP dw ? ; DI dw ? ; SI dw ? ; DX dw ? ; CX dw resident ; ES dw resident ; DS dw offset ztim_tim ; BX dw ? ; AX dw offset ztim_serve ; IP dw resident ; CS dw 0200H ; flags - STI ztim_serve: if 0; debug push es mov ax,video mov es,ax inc byte ptr es:80 pop es endif sti mov ah,k_set ; aktivace znet mov al,znet_flg int int_ker mov al,refresh mov byte ptr ztim_tim,al ; znovu do časové fronty mov ah,k_inq mov al,ztim_flg int int_ker mov al,ztim_flg ; a čekej na příznak mov ah,k_wait int int_ker jmp short ztim_serve ; ****************************************************************************** ; Přerušení od ZNET. Nastaví se příznak pro aktivaci obsluhy ; ZNETu - a to je vlastně všechno. ; ****************************************************************************** irq2at: push ax if debug push es mov ax,video mov es,ax inc byte ptr es:160 pop es endif mov al,eoi ; JK 9.12.90 out p59,al ; JK 9.12.90 out p59at,al mov ah,k_set ; nastavením příznaku aktivuj proces obsluhy mov al,cs:znet_flg ; JK 9.12.90 int int_ker mov ah,k_iret int int_ker irq2xt: push ax if debug push es mov ax,video mov es,ax inc byte ptr es:160 pop es endif mov al,eoi out p59,al mov ah,k_set ; nastavením příznaku aktivuj proces obsluhy mov al,cs:znet_flg ; JK 9.12.90 int int_ker mov ah,k_iret int int_ker ; ****************************************************************************** ; časovač se volá z multi-jádra. Ošetřují se time-outy pro zprávy ve vysílací ; frontě. Běží se zakázaným přerušením ! ; ****************************************************************************** lin_timer proc far cli push ax ; push bx push si push ds push es push cs pop ds if debug mov ax,video mov es,ax inc byte ptr es:2 mov si,z_ram1 mov ds,si assume ds:z_ramseg mov al,ds:tx_area.z_sem or al,'0' mov byte ptr es:4,al mov al,ds:rx1_area.z_sem or al,'0' mov byte ptr es:6,al mov al,ds:rx2_area.z_sem or al,'0' mov byte ptr es:8,al mov si,z_ram2 mov ds,si mov al,ds:tx_area.z_sem or al,'0' mov byte ptr es:10,al mov al,ds:rx1_area.z_sem or al,'0' mov byte ptr es:12,al mov al,ds:rx2_area.z_sem or al,'0' mov byte ptr es:14,al push cs pop ds mov al,tx1_busy or al,'0' mov byte ptr es:164,al mov al,tx2_busy or al,'0' mov byte ptr es:170,al assume ds:resident endif if card1 cmp tx1_busy,1 jne tim1_9 mov si,tx1_act dec [si].c_timcnt jnz tim1_9 mov ax,z_ram1 mov es,ax mov es:tx_area.z_sem,0 mov tx_wait,0FFH tim1_9: endif if card2 cmp tx2_busy,1 jne tim2_9 mov si,tx2_act dec [si].c_timcnt jnz tim2_9 mov ax,z_ram2 mov es,ax mov es:tx_area.z_sem,0 mov tx_wait,0FFH tim2_9: endif pop es pop ds pop si ; pop bx pop ax ret lin_timer endp comment \ mov bx,tx1_q1 ; *** time-outy vysílací fronty *** tim1_l: or bx,bx ; konec fronty ? jz tim1_9 mov al,[bx].c_tmout or al,al ; hlídat timeout ? jz tim1_8 ; ne dec al mov [bx].c_tmout,al jnz tim1_8 ; dosud nevypršel cmp bx,tx1_q1 ; vypršel, vyhodit z fronty mov ax,[bx].c_next ; první ve frontě push ax ; následník jne tim1_text mov tx1_q1,ax cmp ax,0 ; fronta se vyprázdnila ? jnz tim1_3 mov tx1_q9,ax ; ano tim1_3: ; BX prvek, zásobník další les si,dword ptr [bx].c_scb mov es:[si].s_reply,er_tmout; uživateli dej time-out mov al,es:[si].c_sem ; nastavit příznak ? or al,al jz tim1_4 mov ah,k_set int int_ker ; a uvolnit muj buffer !!!! tim1_4: mov si,c_free ; prvek dej do volných mov c_free,bx mov [bx].c_next,si pop bx jmp short tim1_l tim1_text: ; vyhodit z prostředka (konce) fronty mov [si].c_next,ax or ax,ax ; poslední ? jnz tim1_3 mov tx1_q9,si jmp short tim1_3 tim1_8: mov si,bx ; uschovej předchůdce mov bx,[bx].c_next ; a přesun na další prvek jmp short tim1_l tim1_9: endif if card2 mov bx,tx2_q1 ; *** time-outy vysílací fronty *** tim2_l: or bx,bx ; konec fronty ? jz tim2_9 mov al,[bx].c_tmout or al,al ; hlídat timeout ? jz tim2_8 ; ne dec al mov [bx].c_tmout,al jnz tim2_8 ; dosud nevypršel cmp bx,tx2_q1 ; vypršel, vyhodit z fronty mov ax,[bx].c_next ; první ve frontě push ax ; následník jne tim2_text mov tx2_q1,ax cmp ax,0 ; fronta se vyprázdnila ? jnz tim2_3 mov tx2_q9,ax ; ano tim2_3: ; BX prvek, zásobník další les si,dword ptr [bx].c_scb mov es:[si].s_reply,er_tmout; uživateli dej time-out mov al,es:[si].c_sem ; nastavit příznak ? or al,al jz tim2_4 mov ah,k_set int int_ker ; a uvolnit muj buffer !!!! tim2_4: mov si,c_free ; prvek dej do volných mov c_free,bx mov [bx].c_next,si pop bx jmp short tim2_l tim2_text: ; vyhodit z prostředka (konce) fronty mov [si].c_next,ax or ax,ax ; poslední ? jnz tim2_3 mov tx2_q9,si jmp short tim2_3 tim2_8: mov si,bx ; uschovej předchůdce mov bx,[bx].c_next ; a přesun na další prvek jmp short tim2_l tim2_9: endif \ resident ends init segment assume cs:init,ds:init znet_test: ; AX na ZNET, DX na chybovou zprávu mov ds,ax ; v BL zůstane uloženo číslo adaptéru assume ds:z_ramseg mov bl,swtch ; je to RAM ? mov bh,bl xor bl,0FFH mov swtch,bl xor swtch,0FFH cmp bh,swtch jne zneter and bh,3FH ; vypadá to jako ZNET ? cmp bh,swtch2 jne zneter sub ax,100H mov ds,ax assume ds:z_romseg ; cmp sign,0AA55H ; ve verzi FEL to tak neni ; jne zneter cmp epsize,8 jne zneter ret zneter: push cs pop ds assume ds:init mov ah,wrstr int dos mov ax,4C00H int dos banner2: db ' NETDRIVER 2.22',0dh,0ah,'$' banner1:db 0dh,0ah,0dh,0ah if czech db ' Komunikační ovladač pro ' if card12 db 'dva adaptéry' endif if not card12 and card1 db 'jeden adaptér' endif if not card12 and card2 db 'druhý adaptér' endif db ' ZNET',cr,lf,cr,lf,'$' if card1 noznet1: db cr,lf,'Adaptér ZNET nepracuje nebo není přítomen !',cr,lf,'$' endif if card2 noznet2: db cr,lf,'Druhý adaptér ZNET nepracuje nebo není přítomen !',cr,lf,'$' endif endif if eng db ' Network driver for ' if card12 db 'two adapters' endif if not card12 and card1 db 'one adapter' endif if not card12 and card2 db 'second adapter' endif db ' ZNET',cr,lf,cr,lf,'$' if card1 noznet1: db cr,lf,'Adapter ZNET is wrong or not present !',cr,lf,'$' endif if card2 noznet2: db cr,lf,'Second adapter ZNET is wrong or not present !',cr,lf,'$' endif endif er_comline db 0dh,0ah,'Chybný zápis parametrů !$' er_int db 0dh,0ah,'Umím jen IRQ0 až IRQ7 !$' er_buf db 0dh,0ah,'Chybný počet komunikačních bufferů !$' oddelovac: cmp al,' ' je odd_ret cmp al,',' je odd_ret cmp al,9 ; TAB je odd_ret cmp al,0AH ; LF odd_ret:ret dalsi_znak: jcxz err_par dec cx lodsb ret err_par: lea dx,er_comline err_par2: mov ax,seg init mov ds,ax assume ds:init mov ah,9 int 21H mov ah,4CH int 21H err_int: lea dx,er_int jmp short err_par2 ;******************************************************************************* ;HW_TEST: Kontrola přítomnosti a případně i funkčnosti adaptéru (adaptérů) ; v AL vrátí síťovou adresu základního adaptéru. ;******************************************************************************* hw_test: mov ah,62H ; zpracuj príkazový řádek int 21H ; get PSP mov ds,bx mov ax,seg resident mov es,ax mov si,80H ; DS:SI na řádek, ES resident cld lodsb mov cl,al ; počet znaků xor ch,ch jedu_dal: jcxz konec_param lodsb call oddelovac loopz jedu_dal ; přeskoč mezery jcxz konec_param cmp al,'/' jne err_par call dalsi_znak or al,' ' zkus_B: cmp al,'b' ; /B počet komunikačních bufferů jne err_par3 call dalsi_znak cmp al,':' jne err_par3 mov dx,0 call dalsi_znak b_loop: cmp al,'0' jb b_dal cmp al,'9' ja b_dal sub al,'0' mov ah,0 add dx,dx ; * 10 mov bx,dx add dx,dx add dx,dx add dx,bx add dx,ax jcxz b_dal dec cx lodsb jmp short b_loop b_dal: dec si ; smyluplný počet inc cx cmp dx,4 jb b_err cmp dx,b_max ja b_err mov es:b_num,dx jmp jedu_dal b_err: lea dx,er_buf jmp err_par2 err_par3: jmp err_par konec_param: if card2 lea dx,noznet2 mov ax,z_ram2 call znet_test endif if card1 lea dx,noznet1 mov ax,z_ram1 call znet_test endif mov al,bh ; moje adresa ret ;******************************************************************************* ; HW_INIT: Inicializace všeho, co je závislé na konkrétním adaptéru ; ;******************************************************************************* i_b_1: mov cx,seg resident mov ds,cx assume ds:resident mov refresh,al ; tvorba procesu ZNET mov bx,seg resident mov es,bx mov bx,offset znet_st mov ax,256*k_crea+200 int int_ker call alocflg ; tvorba časovacího procesu mov bx,seg resident mov ds,bx mov ztim_flg,al ; pro aktivaci obsluhy ZNET mov bx,seg ztim_st mov es,bx mov bx,offset ztim_st mov ax,256*k_crea+21 int int_ker ret i_b_2: int dos cli if card1 mov ax,z_ram1 mov es,ax mov es:tx_area.z_sem,0 mov es:rx1_area.z_sem,0 ; vyprázdnění přijímacích bufferů mov es:rx2_area.z_sem,0 endif if card2 mov ax,z_ram2 mov es,ax mov es:tx_area.z_sem,0 mov es:rx1_area.z_sem,0 ; vyprázdnění přijímacích bufferů mov es:rx2_area.z_sem,0 endif ret hw_init: call alocflg ; příznak pro obsluhu ZNET mov bx,resident mov ds,bx mov cx,0F000H mov es,cx mov ah,byte ptr es:0FFFEH ; XT/AT ? mov es,bx assume ds:resident mov znet_flg,al cmp ah,0FBH je hw_init_XT cmp ah,0FEH je hw_init_XT cmp ah,0FFH ; !!! nektery Honza je hw_init_XT hw_init_AT: mov bx,offset irq2at push bx mov al,2 call i_b_1 in al,p591 ; odmaskování IRQ 2 and al,11111011B mov ah,al in al,p591at and al,11111101B pop dx push ax mov ax,256*set_int+int_irq2at call i_b_2 pop ax xchg ah,al out p591,al mov al,62H ; Specific EOI out p59,al mov al,ah out p591at,al mov al,61H ; S EOI ? out p59at,al sti jmp short hw_init_both hw_init_XT: mov bx,offset irq2xt push bx mov al,3 ;!!!!!!!!!!!!!!!!!!!!!! 10 call i_b_1 in al,p591 ; odmaskování IRQ 2 and al,11111011B pop dx push ax mov ax,256*set_int+int_irq2 call i_b_2 pop ax out p591,al mov al,62H ; Specific EOI out p59,al sti hw_init_both: push es ; zavěšení na časovač push bx mov ax,seg lin_timer mov es,ax mov bx,offset lin_timer mov ah,20 int int_ker pop bx pop es ret init ends