home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
network
/
pcb121.zip
/
QIF.INC
< prev
next >
Wrap
Text File
|
1992-01-23
|
8KB
|
248 lines
;;******************************************************************************
;; qif.inc qif.inc
;;******************************************************************************
;;
;; Copyright (C) 1990 Vance Morrison
;;
;;
;; Permission to view, compile, and modify for LOCAL (intra-organization)
;; USE ONLY is hereby granted, provided that this copyright and permission
;; notice appear on all copies. Any other use by permission only.
;;
;; Vance Morrison makes no representations about the suitability
;; of this software for any purpose. It is provided "as is" without expressed
;; or implied warranty. See the copywrite notice file for complete details.
;;
;;******************************************************************************
;; qif.inc contains the interface driver for a QIF interface. This
;; software is responcible for packetizing/depacketizing the data for the
;; serial line and providing data transparency (byte stuffing)
;;
;; The functions provided by this file are
;;
;; Q_IF_DECLARE name, rbuff, rqueue, wbuff, wqueue, prefix, port
;; Q_IF_DEFINE name
;; Q_IF_R_ACCESS_out_BX_CX_ES name, no_packet
;; Q_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES name, ok
;; Q_IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
;; Q_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP name, no_buffer
;; Q_IF_W_WRITE_in_CX_const_BX_BP_ES name
;; Q_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES name
;; Q_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
;;
;; Variables set by this module
;;
;; qif_&name&_declared ;; one if this interface exists
;;
;; Variables used by this module
;;
;; if_&name&_mtu ;; the MTU of this interface
;;
;;******************************************************************************
;;******************************************************************************
;; data storage needed by this module
qif_entry STRUC
qif_q_start DW ?
qif_q_end DW ?
qif_q_len DW ?
qif_entry ENDS
qif_data STRUC
qif_wpkt_start DW 0
qif_wpkt_end DW 0
qif_data ENDS
;;******************************************************************************
;; IF_DECLARE name, rbuff, rqueue, wbuff, wqueue, prefix, port
;; rbuff and wbuff are the buffer sizes (in bytes for the read
;; and write buffers, and rqueue and wqueue are the number length
;; of the queue in packets. Whenever a high level write is performed
;; the routine <prefix>_WRITE_const_BX_BP_ES <port> is called.
;;
Q_IF_DECLARE MACRO name, rbuff, rqueue, wbuff, wqueue, prefix, port
.errb <name>
.errb <irq>
.DATA
qif_&name&_declared = 1
qif_&name&_rbuff = rbuff
qif_&name&_rqueue = rqueue
qif_&name&_wbuff = wbuff
qif_&name&_wqueue = wqueue
qif_&name&_prefix equ <prefix>
qif_&name&_port = port
global qif_&name&_data:qif_data
.CODE
ENDM
;;******************************************************************************
;; IF_DEFINE name
;; sets asside memory an name object and initializes it. This
;; routine is a no-op if 'name' was not declared.
;;
Q_IF_DEFINE MACRO name
ifdef qif_&name&_declared
.DATA
qif_&name&_data qif_data <>
.CODE
endif
ENDM
;;******************************************************************************
;; IF_R_ACCESS_out_BX_ES name, no_packet
;; IF_R_ACCESS checks for the next packet to come from the the board
;; associated with 'name' and returns a pointer to the begining of
;; an ethernet packet in BX:ES. CX holds the length of the packet
;; R_ACCESS jumps to 'no_packet' if there are no packets waiting to
;; be read in
;;
Q_IF_R_ACCESS_out_BX_CX_ES MACRO name, no_packet
.errb <no_packet>
QUEUE_HEAD_out_SI_const_AX_BX_CX_DX_BP_DI_ES %qif_&name&_rqueue, no_packet
mov BX, [SI+qif_q_start]
mov CX, [SI+qif_q_len]
mov AX, DS
mov ES, AX
ENDM
;;******************************************************************************
;; IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
;; After the client is through processing the packet returned by
;; IF_R_ACCESS, IF_R_FREE must be called to inform 'name' that the
;; memory that the packet was in can be reused for future packets.
;;
Q_IF_R_FREE_const_BX_CX_BP_SI_DI_ES MACRO name
local done
.errb <name>
cli
mov AX, SI ;; save SI DI
mov DX, DI
QUEUE_HEAD_out_SI_const_AX_BX_CX_DX_BP_DI_ES %qif_&name&_rqueue, done
mov DI, [SI+qif_q_end]
BUFF_FREE_in_DI_const_AX_BX_CX_DX_BP_SI_DI_ES %qif_&name&_rbuff
QUEUE_DEQUEUE_in_SI_const_AX_BX_CX_DX_BP_DI_ES %qif_&name&_rqueue
done:
mov SI, AX ;; restore SI DI
mov DI, DX
sti
ENDM
;;******************************************************************************
;; Q_IF_R_CONT_in_BX_CX_ES name, ok
;; IF_R_CONT determines if the packet returned by R_READ in BX:ES
;; of length CX is continuous. If it is it jumps to 'ok' otherwise
;; it just returns
;;
Q_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES MACRO name, ok
.errb <ok>
jmp ok ;; is it always continuous
ENDM
;;******************************************************************************
;; IF_W_ACCESS_in_CX_out_DI_ES name, no_buffer
;; IF_W_ACCESS returns a pointer to an output buffer for a packet. The
;; pointer is returned in DI:ES. If the ouptut buffer is busy, this
;; routine will jump to 'no_buff'. The output buffer min(CX, mtu)
;; bytes long
;;
Q_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP MACRO name, no_buff
local lenOK, done, my_no_buff
.errb <no_buffer>
cmp CX, if_&name&_mtu
jbe lenOK
mov CX, if_&name&_mtu
lenOK:
cli
BUFF_CHECK_in_CX_out_SI_DI_const_BX_CX_DX_BP_ES %qif_&name&_wbuff,my_no_buff
BUFF_GET_in_DI_const_AX_BX_CX_DX_BP_SI_DI_ES %qif_&name&_wbuff
sti
mov word ptr qif_&name&_data.qif_wpkt_start, SI
mov word ptr qif_&name&_data.qif_wpkt_end, DI
mov DI, SI
mov AX, DS
mov ES, AX
jmp done
my_no_buff:
sti
jmp no_buff
done:
ENDM
;;******************************************************************************
;; IF_W_WRITE_in_CX name
;; IF_W_WRITE actually signals the ethernet board to write a packet to
;; the ethernet. The packet is assumed to be in the buffer returned by
;; IF_W_ACCESS. CX is the length of the packet to send.
;;
Q_IF_W_WRITE_in_CX_const_BX_BP_ES MACRO name
local done
.errb <name>
cli
QUEUE_ENQUEUE_out_DI_const_BX_CX_DX_BP_SI_ES %qif_&name&_wqueue, done
mov AX, word ptr qif_&name&_data.qif_wpkt_start
mov [DI+qif_q_start], AX
mov AX, word ptr qif_&name&_data.qif_wpkt_end
mov [DI+qif_q_end], AX
mov [DI+qif_q_len], CX
;start the low level processing, if necessary.
done:
CALL_WRITE_const_BX_BP_ES %qif_&name&_prefix, %qif_&name&_port
sti
ENDM
CALL_WRITE_const_BX_BP_ES MACRO prefix, port
prefix&_WRITE_const_BX_BP_ES port
ENDM
;;******************************************************************************
;; IF_SET_ADDRESS_in_SI name
;; IF_SET_ADDRESS_in_SI sets the hardware address to be the value
;; pointed to by SI. Note this function may be a no-op if the
;; hardware address cannot be set (ETHERNET for example)
;;
Q_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES MACRO name
.err ;; we don't support setting ethernet addresses
ENDM
;;******************************************************************************
;; IF_COPY_in_CX_SI_DI_ES_out_SI_DI name
;; IF_COPY_in_CX_SI_DI_ES copys a packet from the input buffer (pointed
;; to by SI and the segement register given in IF_DECLARE) to an output
;; buffer (pointed to by DI and ES) of length CX. It assumes the
;; output buffer is contiguous. (and the caller shouln't care if the
;; input buffer is contiguous)
;;
Q_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES MACRO name
.errb <name>
;; since DS points to the data segment, we are ready to go!!
inc CX
shr CX,1
rep movsw
ENDM