⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asmpkt4.asm

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 ASM
字号:
ifdef DOSX and DOS4GW

PAGE 60,132

; PKT_DEBUG = 1       ; uncomment to enable debug

.386
ASMPKT4_TEXT segment dword public use16 'CODE'
assume cs:ASMPKT4_TEXT, ds:nothing, es:nothing

;
; Packet-driver receiver upcall handler.  This module is only
; used for Watcom 32-bit targets using DOS4GW/CauseWay etc., but
; not WDOSX which luckily supports callbacks.
;
; Because most Watcom DOS-extenders doesn't support "Real Mode Callback"
; (rmcb), this module must handle the buffer+enqueue operations here.
; Other targets call pkt_enqueue() in pcpkt.c.
;
; This module cannot contain relocatable variables because this
; module will be copied to allocated DOS-memory at run-time.
; This code is tiny-model with run-time offsets starting at 0.
;
; The `asmpkt_inf' variable is initialised from pcpkt.c before this
; module is copied to DOS-memory.
;
; The `*_save' variables are for saving stuff between 1st (AL = 0)
; and 2nd (AL != 0) packet-driver upcall.
;

PUBLIC pkt_receiver4_start, pkt_receiver4_start_
PUBLIC pkt_receiver4_rm,    pkt_receiver4_rm_
PUBLIC pkt_receiver4_end,   pkt_receiver4_end_
PUBLIC asmpkt_inf,         _asmpkt_inf
PUBLIC asmpkt_size_chk,    _asmpkt_size_chk

;
; These structures must match 'struct pkt_ringbuf' in pcqueue.h
; and 'struct pkt_info' in pcpkt.h
;
PKT_RINGBUF struc
         in_index   dd  ?      ; queue index head
         out_index  dd  ?      ; queue index tail
         buf_size   dd  ?      ; size of each buffer
         num_buf    dd  ?      ; number of buffers
         num_drop   dd  ?      ; number of dropped pkts
         buf_start  dd  ?      ; start of buffer pool (not used)
         dos_ofs    dw  ?      ; DOS offset of buffer pool
PKT_RINGBUF ends

PKT_INFO struc
         ip_handle         dw  ?
         arp_handle        dw  ?
         rarp_handle       dw  ?
         pppoe_disc_handle dw  ?
         pppoe_sess_handle dw  ?
         is_serial         dw  ?
         max_pkt_size      dw  ?
         ip_queue          PKT_RINGBUF <>
         arp_queue         PKT_RINGBUF <>
         ip_buf            db (20*1524) dup (?)   ; IP_BUFS * IP_SIZE
         arp_buf           db  (4*72)   dup (?)   ; ARP_BUFS * ARP_SIZE
PKT_INFO ends

ETH_MAX = 1514           ; max Ethernet size


pkt_receiver4_start:
pkt_receiver4_start_:
 _asmpkt_inf  label dword
  asmpkt_inf  dd 0       ; CS:0
  head_save   dd 0       ; CS:4
  queue_save  dd 0       ; CS:8
  index_save  dw 0       ; CS:12

ifdef PKT_DEBUG
  xy_pos dw 160*13
  temp   dw (14) dup (0)
endif

;
; Location of variables at run-time.
;
PKT_INF = cs:[0]         ; asmpkt_inf
HEAD    = cs:[4]         ; head_save
QUEUE   = cs:[8]         ; queue_save
INDEX   = cs:[12]        ; index_save

ifdef PKT_DEBUG
  XY_POS  = cs:[14]
  VAR_1   = cs:[16]
  VAR_2   = cs:[18]
  VAR_3   = cs:[20]
  VAR_4   = cs:[22]
  VAR_5   = cs:[24]
  VAR_6   = cs:[26]
  VAR_7   = cs:[28]
  VAR_8   = cs:[30]
  VAR_9   = cs:[32]
  VAR_10  = cs:[34]
  VAR_11  = cs:[36]
  VAR_12  = cs:[38]
  VAR_13  = cs:[40]
  VAR_14  = cs:[42]
endif

;-----------------------------------------------------
;
PUTCH  MACRO char
ifdef PKT_DEBUG
       push es
       push di
       push ax
       mov  ax, 0B800h
       mov  es, ax
       mov  di, XY_POS
       mov  al, char
       mov  ah, 15+16           ; white on blue
       stosw
       add  word ptr XY_POS, 2  ; increment X-pos
       pop  ax
       pop  di
       pop  es
endif
ENDM

;-----------------------------------------------------
;
STORE_VARS MACRO
ifdef PKT_DEBUG 
       push ds
       push si
       push ax
       lds  si, PKT_INF
       mov  ax, [si].ip_handle
       mov  VAR_1, ax
       mov  ax, [si].arp_handle
       mov  VAR_2, ax
       mov  ax, [si].rarp_handle
       mov  VAR_3, ax
       mov  ax, [si].is_serial
       mov  VAR_4, ax

       add  si, offset ip_queue
       mov  ax, word ptr [si].in_index
       mov  VAR_5, ax
       mov  ax, word ptr [si].out_index
       mov  VAR_6, ax
       mov  ax, word ptr [si].buf_size
       mov  VAR_7, ax
       mov  ax, word ptr [si].num_buf
       mov  VAR_8, ax
       mov  ax, word ptr [si].dos_ofs
       mov  VAR_9, ax

       add  si, offset arp_queue - offset ip_queue
       mov  ax, word ptr [si].in_index
       mov  VAR_10, ax
       mov  ax, word ptr [si].out_index
       mov  VAR_11, ax
       mov  ax, word ptr [si].buf_size
       mov  VAR_12, ax
       mov  ax, word ptr [si].num_buf
       mov  VAR_13, ax
       mov  ax, word ptr [si].dos_ofs
       mov  VAR_14, ax
       pop  ax
       pop  si
       pop  ds
endif
ENDM

;
; The packet-driver calls this routine to ask for a receive buffer (AL=0)
; And to tell when the buffer has been copied (AL != 0).
;
; Entry AL = 0; driver requests a buffer. We return ES:DI of next
;               available ring-buffer (or ES:DI = 0:0 if no room)
;       CX = length of packet
;       BX = handle (IP or ARP/RARP)
; Entry AL != 0; driver has put the data in buffer, we then update
;                the ring-buffer head index (INDEX).
;       BX = handle (IP or ARP/RARP)
;

pkt_receiver4_rm:
pkt_receiver4_rm_:
        pushf
        cli                    ; no interruptions now
        or   al, al
        jnz  @enque            ; AL != 0, branch and enqueue packet

        PUTCH ' '
        PUTCH '0'

        ;
        ; AL = 0: buffer request
        ;
        call pkt_get_buffer    ; get a buffer, return ES:DI (may be 0:0)
        popf
        retf

        ;
        ; AL != 0: enqueue packet
        ;
@enque:
        PUTCH '1'

        or   si, si            ; NULL-ptr is not valid
        jz   @no_enque
        call pkt_enqueue       ; copy packet at DS:SI to queue-head

        STORE_VARS

@no_enque:
        popf
        retf


;
; Check handle, check correct ring-buffer (ip_queue or arp_queue) in
; '_pkt_inf'. If room in buffer, return next head buffer, else NULL.
;
; static struct _far pkt_ringbuf *QUEUE;
; static char   _far             *HEAD;
; static int                      INDEX;
;
; char * pkt_get_buffer (int handle, int rx_len)
; {
;   if (!PKT_INF)     /* should never happen */
;      return (NULL);
;
;   if (handle == PKT_INF->arp_handle && !PKT_INF->is_serial)
;        QUEUE = &PKT_INF->arp_queue;
;   else QUEUE = &PKT_INF->ip_queue;
;
;   if (rx_len > QUEUE->buf_size - 4)
;   {
;     QUEUE->num_drop++;
;     return (NULL);
;   }
;
;   INDEX = QUEUE->in_index + 1;
;   if (INDEX >= QUEUE->num_buf)
;       INDEX = 0;
;
;   if (INDEX == QUEUE->out_index)
;   {
;     QUEUE->num_drop++;
;     return (NULL);
;   }
;   HEAD = MK_FP (_ES, QUEUE->dos_ofs + (QUEUE->buf_size * QUEUE->in_index);
;   return (HEAD);
; }
;
; BX = IP or ARP/RARP handle
; CX = buffer size
;
; return ES:DI, AX,BX,DX changed

pkt_get_buffer:
        les  di, PKT_INF
        mov  ax, es
        cmp  ax, 0                        ; seg(_pkt_inf) == 0 ?
        je   @ret_null                    ; yes, discard it

        push ds                           ; save DS
        mov  ds, ax                       ; DS = ES
        mov  ax, offset ip_queue          ; assume it's IP
        cmp  bx, [di].arp_handle
        jne  @is_ip

        test [di].is_serial, 0FFFFh       ; using serial driver
        jnz  @is_ip                       ; yes, cannot be ARP/RARP/PPPoE
        mov  ax, offset arp_queue

        PUTCH 'a'

@is_ip:
        add  di, ax                       ; ES:DI = ip_queue or arp_queue
        mov  ax, word ptr [di].buf_size
        sub  ax, 4
        cmp  cx, ax                       ; if (rx_len > QUEUE->buf_size - 4)
        ja   @too_big                     ;   drop it

        mov  QUEUE[0], di
        mov  QUEUE[2], es

        mov  ax, word ptr [di].in_index
        inc  ax
        cmp  ax, word ptr [di].num_buf    ; (index >= queue->num_buf)
        jb   @no_wrap                     ; no, don't wrap
        xor  ax, ax                       ; yes, index wrapped
        PUTCH 'w'

@no_wrap:
        mov  INDEX, ax                    ; store INDEX
        cmp  ax, word ptr [di].out_index
        je   @drop                        ; if (INDEX == QUEUE->out_index)
                                          ;   drop packet (queue full)
        mov  ax, word ptr [di].buf_size
        mul  word ptr [di].in_index       ; AX = (QUEUE->buf_size * QUEUE->in_index)
        add  ax, word ptr [di].dos_ofs    ; AX += QUEUE->dos_ofs
        mov  di, ax                       ;
        mov  ax, es

        mov  HEAD[0], di
        mov  HEAD[2], ax                  ; save HEAD = ES:DI
        pop  ds
        PUTCH '!'
        ret                               ; return ES:DI

@too_big:
        PUTCH 't'
@drop:
        PUTCH 'd'
        inc  word ptr [di].num_drop
        adc  word ptr [di+2].num_drop, 0
        pop  ds

@ret_null:
        PUTCH 'D'
        xor  di, di
        mov  es, di                       ; return (NULL)
        ret

;
; Enqueue a packet to the head of queue.
; No need to copy data, only zero-pad buffer.
;
; void pkt_enqueue (int rx_len)
; {
;   int pad_len = QUEUE->buf_size - 4 - rx_len; /* 4 = size of PKTQ_MARKER */
;
;   memset (HEAD + rx_len, 0, pad_len); /* zero-fill rest of buffer */
;   QUEUE->in_index = INDEX;
; }
;
; DS:SI = receiver buffer to enqueue (=HEAD)
; CX = rx_len
;
pkt_enqueue:
        les  di, QUEUE
        mov  bx, word ptr es:[di].buf_size
        sub  bx, 4
        sub  bx, cx

        cld
        add  si, cx
        xchg di, si            ; DI = SI+rx_len, ES = DS already
        xchg cx, bx
        shr  cx, 2             ; CX = pad_len/4
        rep  stosd             ; fill rest of buffer

        PUTCH '*'

        mov  si, word ptr QUEUE[0]
        mov  ax, INDEX
        mov  word ptr [si].in_index, ax
        ret

        nop
        nop          ; incase ptr-arithmetic is wrong !

;
; Label to calculate the size to copy to DOS-memory
;

pkt_receiver4_end:   ; TX-buffer and scratch-area (PKT_TMP) starts here
pkt_receiver4_end_:

;
; PKT_TMP db (30)      dup (?)  ; these gets overlayed buffer below
; TX_BUF db  (IP_SIZE) dup (?)
;
; Use 'asmpkt_size_chk' to compared with 'sizeof(*_pkt_inf)' in pcpkt.c
; WASM's SIZE operator doesn't seem to handle structure defs (only data).
;
ifdef ??version    ; Turbo Assembler
 _asmpkt_size_chk label word
  asmpkt_size_chk dw SIZE PKT_INFO
else
  dummy_pkt_start = $
  dummy_pkt_info  PKT_INFO <>            ; won't be used or copied to DOS-mem
 _asmpkt_size_chk label word             ; doesn't use space in .exe-image ?
  asmpkt_size_chk dw $ - dummy_pkt_start
endif

ASMPKT4_TEXT ends

endif   ; ifdef DOSX and DOS4GW

END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -