home *** CD-ROM | disk | FTP | other *** search
- ;;******************************************************************************
- ;; 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
-
-