home *** CD-ROM | disk | FTP | other *** search
- ;;******************************************************************************
- ;; packet.inc packet.inc
- ;;******************************************************************************
- ;;
- ;; Copyright (C) 1989 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.
- ;;
- ;;******************************************************************************
- ;; packet.inc contains the interface driver for the the packet driver
- ;; (a la FTP software, drivers and info available from sun.soe.clarson.edu)
- ;;
- ;; Note that this interface driver is VERY inefficient. basically packets
- ;; are copyied once on read and once again on write. Thus this driver will
- ;; be at best 1/3 the speed of a native driver. Nevertheless, this speed
- ;; may be acceptable, (and besides it gets all those people who want 3Com
- ;; support off my back). There are other inefficiencies as well (saving
- ;; and restoring registers, waiting for packets to be sent etc), but even
- ;; so it will be usefull for low performance applications.
- ;;
- ;; Note that this these routines do not use any extended or high performance
- ;; packet driver calls. Only the basic calls are used
- ;;
- ;; The functions provided by this file are
- ;;
- ;; PKT_DECLARE name, driver_int, driver_class, prom
- ;; PKT_DEFINE name, fail
- ;; PKT_IF_R_ACCESS_out_BX_CX_ES name, no_packet
- ;; PKT_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES name, ok
- ;; PKT_IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
- ;; PKT_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP name, no_buffer
- ;; PKT_IF_W_WRITE_in_CX_const_BX_BP_ES name
- ;; PKT_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES name
- ;; PKT_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
- ;;
- ;; Variables set by this module
- ;;
- ;; pkt_&name&_declared ;; one if this interface exists
- ;; if_&name&_address ;; the hardware address
- ;; if_&name&_mtu ;; the maximum trans unit
- ;;
- ;;******************************************************************************
-
- ;;******************************************************************************
- ;; data storage needed by this module
-
- pkt_r_q_entry STRUC
- pkt_q_rstart DW ?
- pkt_q_rend DW ?
- pkt_r_q_entry ENDS
-
- pkt_data STRUC
- pkt_handle DW ?
- pkt_bend DW ?
- pkt_bstart DW ?
- pkt_data ENDS
-
-
- ;;******************************************************************************
- ;; IF_DECLARE name, driver_int driver_class, promiscuous
- ;; declares an interface object. driver_int is the interupt number
- ;; to use to access the packet driver (60H-80H). driver_class is
- ;; the packet driver class of the card (Ethernet = 1)
- ;;
- PKT_DECLARE MACRO name, driver_int, driver_class, promiscuous
- .errb <name>
- .errb <driver_int>
-
- .DATA
- pkt_&name&_declared = 1
- pkt_&name&_drv_int = driver_int
- pkt_&name&_drv_class = driver_class
-
- pkt_&name&_rbuff = name*100+1
- pkt_&name&_rqueue = name*100+2
-
- pkt_&name&_promiscuous = 0
- ifnb <promiscuous>
- pkt_&name&_promiscuous = 0&promiscuous
- endif
-
- if_&name&_mtu = 1514
- global pkt_&name&_wbuffer:byte
- global pkt_&name&_rbuffer:byte
- global pkt_&name&_data:pkt_data
- global if_&name&_address:word
-
- .CODE
- global pkt_&name&_data_seg:word
- global pkt_&name&_real_define:near
- BUFF_DECLARE %pkt_&name&_rbuff, 10240, pkt_&name&_rbuffer
- QUEUE_DECLARE %pkt_&name&_rqueue, 16, %(size pkt_r_q_entry)
- ENDM
-
-
- ;;******************************************************************************
- ;; IF_DEFINE name, fail
- ;; sets asside memory an name object and initializes it. This
- ;; routine is a no-op if 'name' was not declared. It jumps to 'fail'
- ;; if there was an error in setup.
- ;;
- PKT_DEFINE MACRO name, fail
- ifdef pkt_&name&_declared
- BUFF_DEFINE %pkt_&name&_rbuff
- QUEUE_DEFINE %pkt_&name&_rqueue
- call pkt_&name&_real_define
- or AX, AX
- jnz fail
- endif
- ENDM
-
-
- PKT_REAL_DEFINE MACRO name
- local pkt_read_task, got_driver, got_address, size_check, no_room, done
- local set_prom
- .errb <name>
-
- ifdef pkt_&name&_declared
- .DATA
- if_&name&_address DW 3 DUP (0)
- pkt_&name&_rbuffer DB 10240 dup (0)
- pkt_&name&_wbuffer DB 1536 dup (0)
- pkt_&name&_data pkt_data <> ;; create storage needed
-
- .CODE
- ;;*****************************************************************
- pkt_&name&_real_define:
- mov word ptr cs:pkt_&name&_data_seg, DS
-
- mov AH, 2 ;; access_type driver call
- mov AL, pkt_&name&_drv_class ;; driver class
- mov DL, 0 ;; wildcard number
- mov BX, 0FFFFH ;; wildcard Type
- xor CX, CX ;; get any packet type
- mov DI, CS ;; point to my packet reciever
- mov ES, DI
- mov DI, offset pkt_read_task
- stc
- PKT_CALL_DRIVER name
- jnc got_driver
- mov DL, DH
- xor DH, DH
- mov AX, DX
- ret
- got_driver:
- mov pkt_&name&_data.pkt_handle, AX
-
- mov BX, AX
- mov AH, 6 ;; get ethernet address
- mov DX, DS
- mov ES, DX
- mov DI, offset if_&name&_address
- mov CX, 6 ;; length of address buffer
- stc
- PKT_CALL_DRIVER name
- jnc got_address
- mov DL, DH
- xor DH, DH
- mov AX, DX
- ret
- got_address:
-
- if pkt_&name&_promiscuous eq 1
- mov BX, pkt_&name&_data.pkt_handle
- mov AH, 20 ;; set recieve mode
- mov CX, 6 ;; to recieve all packets
- stc
- PKT_CALL_DRIVER name
- jnc set_prom
- mov DL, DH
- xor DH, DH
- mov AX, DX
- ret
- set_prom:
- endif
-
- xor AX, AX
- sti ;; turn on interupts if they are not already on
- ret
-
- ;;*********************************************************************
- ;; 'interupt' routine
- pkt_&name&_data_seg: DW 0
-
- pkt_read_task:
- push DS
- segcs
- mov DS, word ptr pkt_&name&_data_seg
- or AX, AX
- jz size_check
- QUEUE_ENQUEUE_out_DI_const_BX_CX_DX_BP_SI_ES %pkt_&name&_rqueue, done
- mov AX, pkt_&name&_data.pkt_bstart
- mov [DI+pkt_q_rstart], AX
- mov AX, pkt_&name&_data.pkt_bend
- mov [DI+pkt_q_rend], AX
- done:
- pop DS
- retf
- size_check:
- BUFF_CHECK_in_CX_out_SI_DI_const_BX_CX_DX_BP_ES %pkt_&name&_rbuff,no_room
- BUFF_GET_in_DI_const_AX_BX_CX_DX_BP_SI_DI_ES %pkt_&name&_rbuff
- mov pkt_&name&_data.pkt_bstart, SI
- mov pkt_&name&_data.pkt_bend, DI
- mov DI, SI
- mov AX, DS
- mov ES, AX
- pop DS
- retf
- no_room:
- xor DI, DI
- mov ES, DI
- pop DS
- retf
-
- endif
- ENDM
-
-
- ;;******************************************************************************
- ;; PKT_CLOSE
- ;; closes the packet driver gracefully
- ;;
- PKT_CLOSE MACRO name
- mov AH, 3 ;; CLOSE command
- mov BX, pkt_&name&_data.pkt_handle
- PKT_CALL_DRIVER name
- 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
- ;;
- PKT_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 %pkt_&name&_rqueue, no_packet
- mov BX, [SI+pkt_q_rstart]
- mov CX, [SI+pkt_q_rend]
- sub CX, BX
- 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.
- ;;
- PKT_IF_R_FREE_const_BX_CX_BP_SI_DI_ES MACRO name
- local done
- .errb <name>
-
- cli
- QUEUE_HEAD_out_SI_const_AX_BX_CX_DX_BP_DI_ES %pkt_&name&_rqueue, done
- mov DI, [SI+pkt_q_rend]
- BUFF_FREE_in_DI_const_AX_BX_CX_DX_BP_SI_DI_ES %pkt_&name&_rbuff
- QUEUE_DEQUEUE_in_SI_const_AX_BX_CX_DX_BP_DI_ES %pkt_&name&_rqueue
- done:
- sti
- ENDM
-
-
- ;;******************************************************************************
- ;; PKT_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
- ;;
- PKT_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_buffer'. The output buffer min(CX, 1536)
- ;; bytes long
- ;;
- PKT_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP MACRO name, no_buffer
- .errb <no_buffer>
-
- mov DI, offset pkt_&name&_wbuffer
- mov AX, DS
- mov ES, AX
- 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.
- ;;
- PKT_IF_W_WRITE_in_CX_const_BX_BP_ES MACRO name
- .errb <name>
-
- push BX
- push BP
- push ES
-
- mov AH, 4 ;; set_pkt command
- mov SI, offset pkt_&name&_wbuffer ;; the packet to send
- ;; DS is OK as it stands
- ;; CX is also fine as is
- PKT_CALL_DRIVER name
- pop ES
- pop BP
- pop BX
- 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)
- ;;
-
- PKT_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES MACRO name
- .err ;; we don't support setting ethernet addresses (yet)
- 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)
- ;;
- PKT_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
-
- ;;******************************************************************************
- ;; PKT_CALL_DRIVER calls the drivers, but it also makes sure that the
- ;; segment registers are preserved.
-
- PKT_CALL_DRIVER MACRO name
- .errb <name>
-
- push DS
- push SS
- int pkt_&name&_drv_int
- pop SS
- pop DS
- ENDM
-
-