home *** CD-ROM | disk | FTP | other *** search
- ; PARnet interrupt handler
- ; 03-JUN-93 <S.A.Pechler@bdk.tue.nl>
-
- .MODEL MEMMOD,C
- %MACS
-
- if @Datasize NE 0
- extrn parint:far,maskoff:far,maskon:far
- else
- extrn parint:near,maskoff:near,maskon:near
- endif
-
- .DATA
- Isat dw 0
- int_no dw 7 ; IRQ level used (=printer IRQ)
- savess dw ? ; saved SS during the stack swap.
- savesp dw ? ; saved SP
- Intstk dw 512 dup(?) ; Interrupt working stack
- Stktop equ $ ; SP set here when entering interrupt
-
- .CODE
- dbase dw @Data ;to get the right DS
-
- eoi PROC
- cmp Isat,1
- jne @@1 ; Only one 8259, so skip this stuff
- mov al,0bh ; read in-service register from
- out 0a0h,al ; secondary 8259
- nop ; settling delay
- nop
- nop
- in al,0a0h ; get it
- or al,al ; Any bits set?
- jz @@1 ; nope, not a secondary interrupt
- mov al,20h ; Get EOI instruction
- out 0a0h,al ; Secondary 8259 (PC/AT only)
- @@1: mov al,20h ; 8259 end-of-interrupt command
- out 20h,al ; Primary 8259
- ret
- eoi ENDP
-
- public parisr
- if @Datasize NE 0
- label parisr far
- else
- label parisr near
- endif
-
- push ds
- ; Now switch stacks, push remaining registers, and do remaining interrupt work.
- mov ds,cs:dbase ; establish interrupt data segment
-
- mov savesp,sp
- mov savess,ss
-
- mov ss,cs:dbase ; stack segment = data segment
- mov sp,offset Stktop; initalize stacktop
- cld
-
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push es
-
- ; The following comment is wrong in that we now do a specific EOI command,
- ; and because we don't enable interrupts (even though we should).
-
- ; Chips & Technologies 8259 clone chip seems to be very broken. If you
- ; send it a Non Specific EOI command, it clears all In Service Register
- ; bits instead of just the one with the highest priority (as the Intel
- ; chip does and clones should do). This bug causes our interrupt
- ; routine to be reentered if: 1. we reenable processor interrupts;
- ; 2. we reenable device interrupts; 3. a timer or other higher priority
- ; device interrupt now comes in; 4. the new interrupting device uses
- ; a Non Specific EOI; 5. our device interrupts again. Because of
- ; this bug, we now completely mask our interrupts around the call
- ; to "parint", the real device interrupt handler. This allows us
- ; to send an EOI instruction to the 8259 early, before we actually
- ; reenable device interrupts. Since the interrupt is masked, we
- ; are still guaranteed not to get another interrupt from our device
- ; until the interrupt handler returns. This has another benefit:
- ; we now no longer prevent other devices from interrupting while our
- ; interrupt handler is running. This is especially useful if we have
- ; other (multiple) packet drivers trying to do low-latency transmits.
- mov ax,int_no ; Disable further device interrupts
- push ax
- call maskoff
- inc sp
- inc sp
-
- call eoi
-
- sti ; Interrupts are now completely safe
- mov ax,0
- push ax
- call parint ; user interrupt routine
- inc sp
- inc sp
-
- cli ;interrupts *must* be off between
- ;here and the stack restore, because
- ;if we have one of our interrupts
- ;pending, we would trash our stack.
- mov ax,int_no ; Now reenable device interrupts
- push ax
- call maskon
- inc sp
- inc sp
-
- pop es
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
-
- mov ss,savess
- mov sp,savesp
-
- pop ds
- iret
-
- ; Convert 32-bit int in network order to host order (dh, dl, ah, al)
- ; Called from C as
- ; int32 get32(char *cp);
-
- public get32
- get32 proc
- arg cp:ptr
- if @Datasize NE 0
- uses ds,si
- lds si,cp ; ds:si = cp
- else
- uses si
- mov si,cp ; ds:si = cp (ds already set)
- endif
-
- cld
- lodsw
- mov dh,al ; high word to dx, a-swapping as we go
- mov dl,ah
- lodsw
- xchg al,ah ; low word stays in ax, just swap
- ret
- get32 endp
-
- ; Convert 16-bit int in network order to host order (ah, al)
- ; Called from C as
- ; int16 get16(char *cp);
-
- public get16
- get16 proc
- arg cp:ptr
- if @Datasize NE 0
- uses ds,si
- lds si,cp ; ds:si = cp
- else
- uses si
- mov si,cp ; ds:si = cp (ds already set)
- endif
-
- lodsw ; note: direction flag is don't-care
- xchg al,ah ; word stays in ax, just swap
- ret
- get16 endp
-
- ; Convert 32-bit int to network order, returning new pointer
- ; Called from C as
- ; char *put32(char *cp,int32 x);
-
- public put32
- put32 proc
- arg cp:ptr,x:dword
- if @Datasize NE 0
- uses ds,di
- les di,cp ; es:di = cp
- mov ax,ss ; our parameter is on the stack, and ds might not
- mov ds,ax ; be pointing to ss.
- else
- uses di
- mov di,cp ; es:di = cp
- mov ax,ds ; point es at data segment
- mov es,ax
- endif
-
- cld
- mov ax,word ptr (x+2) ; read high word of machine version
- xchg ah,al ; swap bytes
- stosw ; output in network order
- mov ax,word ptr x ; read low word of machine version
- xchg ah,al ; swap bytes
- stosw ; put in network order
-
- mov ax,di ; return incremented output pointer
- if @Datasize NE 0
- mov dx,es ; upper half of pointer
- endif
- ret
- put32 endp
-
- ; Convert 16-bit int to network order, returning new pointer
- ; Called from C as
- ; char *put16(char *cp,int16 x);
-
- public put16
- put16 proc
- arg cp:ptr,x:word
- uses di
- if @Datasize NE 0
- les di,cp ;es:di = cp
- else
- mov di,cp ; es:di = cp
- mov ax,ds
- mov es,ax
- endif
- cld
- mov ax,x ; fetch source word in machine order
- xchg ah,al ; swap bytes
- stosw ; save in network order
- mov ax,di ; return new output pointer to user
- if @Datasize NE 0
- mov dx,es ; upper half of pointer
- endif
- ret
- put16 endp
-
-
- end
-