home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / packetdrivers.tar.gz / pd.tar / src / arcether.asm < prev    next >
Assembly Source File  |  1995-06-25  |  34KB  |  1,103 lines

  1. ;History:180,18
  2. ;Sun Jan 05 22:13:57 1992 increased RST_IVAL from 4 to 7.
  3. ;Tue Feb 27 10:56:15 1990 send_pkt wasn't timing out properly.
  4. version    equ    1
  5.  
  6.     include    defs.asm
  7.  
  8. ;Ported from Philip Prindeville's arcnet driver for PCIP
  9. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  10.  
  11. ;Ported from Philip Prindevilles's and Russell Nelson's ARCNET
  12. ;driver to RFC1201 and class Ethernet by Martin Wilmes (Q91@DHDURZ1.BITNET).
  13. ;So any bugs are now due to Martin Wilmes.
  14.  
  15. ;  Parts Copyright, 1988-1992, Russell Nelson, Crynwr Software
  16. ;  Copyright 1991 Martin Wilmes
  17.  
  18. ;   This program is free software; you can redistribute it and/or modify
  19. ;   it under the terms of the GNU General Public License as published by
  20. ;   the Free Software Foundation, version 1.
  21. ;
  22. ;   This program is distributed in the hope that it will be useful,
  23. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25. ;   GNU General Public License for more details.
  26. ;
  27. ;   You should have received a copy of the GNU General Public License
  28. ;   along with this program; if not, write to the Free Software
  29. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  30.  
  31. code    segment    word public
  32.     assume    cs:code, ds:code
  33.  
  34. ;Registers:
  35.  
  36. ;the following I/O addresses are mapped to the COM 9026
  37. IMASK        equ    0        ; writeable
  38. STATUS        equ    0        ; readable
  39. COMMAND        equ    1
  40. ;the following I/O addresses are mapped to the 8253 counter/timer
  41. CNTR0        equ    4
  42. CNTR1        equ    5
  43. CNTR2        equ    6
  44. MODE        equ    7
  45. ;reading the following I/O addresse performs a software reset.
  46. SW_RST        equ    8
  47.  
  48. ; time needed to do various things (in clock ticks)
  49. RST_IVAL    equ    7        ;reset
  50. SEND_IVAL    equ    4        ;send
  51. ACK_IVAL        equ     4               ;acknowledge
  52.  
  53. ; Maximum number of replays of an unacknowledged packet
  54. SEND_REPLAY     equ     5               ;times a packet should be replayed
  55.                                         ;when we get no acknowledge, not
  56.                                         ;yet used
  57.  
  58. ; ARP type for ARCnet
  59. ARP_ARC        equ    001h           ; We are ARCnet but show up as EtherNet
  60.  
  61. ; broadcast address is nid 0
  62. ARC_BCAST    equ    0              ;ARCnet Broadcast address
  63.  
  64. ; packet sizes
  65. ARC_MTU        equ    249            ;These are the length of client data!
  66. ARC_MnTU    equ    252            ;
  67. ARC_XMTU    equ    504            ;
  68. ;
  69. ;status/interrupt mask bit fields
  70. ;
  71. ST_TA        equ    001h        ; transmitter available
  72. ST_TMA        equ    002h        ; transmitted msg. ackd
  73. ST_RECON    equ    004h        ; system reconfigured
  74. ST_TEST        equ    008h        ; test flag
  75. ST_POR        equ    010h        ; power-on-reset
  76. ST_ETS1        equ    020h        ; unused
  77. ST_ETS2        equ    040h        ; unused
  78. ST_RI        equ    080h        ; receiver inhibited
  79.  
  80. ;
  81. ;in the command register, the following bits have these meanings:
  82. ;        0-2    command
  83. ;        3-4    page number (enable rvc/xmt)
  84. ;         7    rcv b'casts
  85.  
  86.  
  87. DSBL_XMT    equ    001h        ; disable transmitter
  88. DSBL_RCV    equ    002h        ; disable receiver
  89. ENBL_XMT    equ    003h        ; enable transmitter
  90. ENBL_RCV    equ    004h        ; enable receiver
  91. DFN_CONF    equ    005h        ; define configuration
  92. CLR_FLGS    equ    006h        ; clear flags
  93. LD_TST_FLG    equ    007h        ; load test flags
  94.  
  95. ; flags for clear flags operation
  96.  
  97. FL_POR        equ    008h        ; power-on-reset
  98. FL_RECON    equ    010h        ; system reconfigured
  99.  
  100. ; flags for load test flags operation
  101.  
  102. FL_TST        equ    008h        ; test flag (diagnostic)
  103.  
  104. ; byte deposited into first address of buffers when POR
  105. TSTWRD        equ    0321Q
  106.  
  107. ; handy macros for enable receiver/transmitter
  108.  
  109. BCAST        equ    080h        ; receiver only
  110.  
  111. ; flags for define configuration
  112.  
  113. CONF_NORM    equ    000h        ; 1-249 byte packets
  114. CONF_XTND    equ    008h        ; 250-504 byte packets
  115.  
  116.  
  117.          public    no_confident
  118. NO_CONFIDENT    db      1
  119.  
  120. ; designations for receiver/transmitter buffers.  sorry, no cleverness here
  121. RCVPAGE        equ    0
  122. XMTPAGE        equ    3
  123.  
  124. ; Flag which indicates that we should build and expect 802.3 framed Novell
  125. ; IPX packets from the IPX-Shell, set to N_OPTION in this case
  126. OPTION_8023     db      0
  127.  
  128. ; Maximum number of fragments we can store in our receive-buffer
  129. MAX_FRAGMENTS   equ     3
  130.  
  131. ; Data for sending splitted packets
  132.  
  133. send_did        db      0                   ;Destination ID
  134. send_sid        db      0                   ;Source ID
  135. Stored_CX       dw      0                   ;Rest of packet not send yet
  136. Protocol_ID     db      0                   ;The ARCnet protocol ID
  137. Split_Number    db      0                   ;Number of fragments we have to send
  138. Pkt_Number      db      0                   ;Number of the current packet
  139. Sequence_Number dw      0                   ;Sequence number, start with zero
  140. send_times      db      0                   ;times a packet has been replayed
  141.  
  142. ; Data for receiving splitted packets
  143.  
  144. last_expected      db      0feh             ;Splitflag of last Packet in a
  145.                                             ;sequence - 1
  146. expected_packet    db      0                ;Used to test a sequence
  147. expected_sequence  dw      0
  148. recv_protocol      dw      0                ;Ethernet protocol
  149. recv_num_frags     db      0                ;Number of fragments we received
  150. recv_protocolbyte  db      0                ;ARCnet protocol
  151. recv_offset        dw      0
  152. recv_packet        dw      0
  153. last_length        dw      0
  154.  
  155. ; We store all but the last fragments of incomplete sequences in our own
  156. ; buffer. This is not necessary since the ARCnet card has 4 pages and we
  157. ; should receive a maximum of 3 fragments in a sequence. Using our own
  158. ; buffer has two advantages: Our driver becomes faster because it uses
  159. ; idle times when the packet not complete to test the sequence and
  160. ; reassemble the client data and our own buffer makes it easier to
  161. ; change the driver to receive more than 3 fragments if required.
  162. recv_buffer        db      (MAX_FRAGMENTS-1)*504 dup (0feh)
  163.  
  164.     public    int_no
  165. int_no        db    5,0,0,0        ; interrupt number.
  166. io_addr        dw    02e0h,0        ; I/O address for card (jumpers)
  167. mem_base    dw    0d800h,0
  168.  
  169.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  170. driver_class    db    1,0,0           ;We show as Ethernet driver, class 1.
  171.                                         ;when the OPTION_8023 flag is set, we
  172.                                         ;don not refuse calls for a class 11
  173.                                         ;driver since the PDIPX-shell asks for
  174.                                         ;a class 11 driver
  175. driver_type    db    14           ;Datapoint RIM (from the packet spec)
  176. driver_name    db    'ARCEther',0    ;name of the driver.
  177. driver_function    db    2
  178. parameter_list    label    byte
  179.     db    1    ;major rev of packet driver
  180.     db    9    ;minor rev of packet driver
  181.     db    14    ;length of parameter list
  182.     db    6    ;length of MAC-layer address
  183.     dw    1514    ;MTU, including MAC headers
  184.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  185.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  186.     dw    0    ;(# of successive xmits) - 1
  187. int_num    dw    0    ;Interrupt # to hook for post-EOI
  188.             ;processing, 0 == none,
  189.  
  190.     public    rcv_modes
  191. rcv_modes    dw    4        ;number of receive modes in our table.
  192.         dw    0,0,0,rcv_mode_3
  193.  
  194.     include    popf.asm
  195.     include    movemem.asm
  196.  
  197.     public bad_command_intercept
  198. bad_command_intercept:
  199. ;called with ah=command, unknown to the skeleton.
  200. ;exit with nc if okay, cy, dh=error if not.
  201.     mov    dh,BAD_COMMAND
  202.     stc
  203.     ret
  204.  
  205.     public    as_send_pkt
  206. ; The Asynchronous Transmit Packet routine.
  207. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  208. ;   interrupts possibly enabled.
  209. ; Exit with nc if ok, or else cy if error, dh set to error number.
  210. ;   es:di and interrupt enable flag preserved on exit.
  211. as_send_pkt:
  212.     ret
  213.  
  214.     public    drop_pkt
  215. ; Drop a packet from the queue.
  216. ; Enter with es:di -> iocb.
  217. drop_pkt:
  218.     assume    ds:nothing
  219.     ret
  220.  
  221.     public    xmit
  222. ; Process a transmit interrupt with the least possible latency to achieve
  223. ;   back-to-back packet transmissions.
  224. ; May only use ax and dx.
  225. xmit:
  226.     assume    ds:nothing
  227.     ret
  228.  
  229.  
  230.     public    send_pkt
  231. send_pkt:
  232. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  233. ;  (only if the high-performance bit is set in driver_function)
  234. ;enter with ds:si -> packet, cx = packet length.
  235. ;exit with nc if ok, or else cy if error, dh set to error number.
  236.     assume    ds:nothing
  237.  
  238.     cmp    cx,GIANT        ; Is this packet too large?
  239.     ja    send_pkt_toobig
  240.  
  241.         push    ds
  242.         push    si
  243.         push    cx
  244.  
  245.         mov     send_did,0        ;Assume that destination is broadcast
  246.         mov     cx,3
  247.         mov     ax,ds:[si+4]
  248.         cmp     ax,0ffffh        ;A first fast check for non-Broadcast
  249.         jne     send_non_broadcast
  250. send_adress_loop:
  251.         lodsw
  252.         cmp     ax,0ffffh
  253.         jne     send_after_loop
  254.         loop    send_adress_loop
  255.         jmp     nr_3            ;destination is indeed broadcast
  256.  
  257. send_pkt_toobig:
  258.     mov    dh,NO_SPACE
  259.     stc
  260.     ret
  261.  
  262. send_after_loop:
  263.         dec     cx                      ;read the rest of the ethernet adress
  264.         rep     lodsw
  265. send_non_broadcast:
  266.         mov     cs:send_did,ah          ;arcnet address is highest byte of
  267.                                         ;the ethernet address
  268. nr_3:
  269.         pop     cx
  270.         pop     di
  271.         pop     es                     ;We change ds:si to to es:di because we
  272.                                        ;we want to access our own data more easily.
  273.         mov     ax,cs
  274.         mov     ds,ax
  275.         assume  ds:code
  276.  
  277.         mov     al,es:[di+11]        ;source ID
  278.         mov     send_sid,ah
  279.         mov     ax,es:[di+12]        ;Ethernet Protocol
  280.         cmp     ax,0008h        ;IP Packet
  281.         jne     nr_5
  282.         mov     protocol_ID,212        ;IP on ARCnet
  283.         jmp     nr_10
  284. nr_5:
  285.         cmp     ax,0608h        ;ARP packet
  286.         jne     nr_6
  287.         mov     protocol_ID,213        ;ARP on ARCnet
  288.         mov     cx,18+14        ;18Bytes is ARP and RARP on Arcnet
  289.                     ;14 Byte for EtherNet Header and Protocol
  290.                     ;which we forget later
  291.         jmp     nr_10
  292. nr_6:
  293.         cmp     ax,3580h        ;RARP packet
  294.         jne     nr_7
  295.         mov     protocol_ID,214        ;RARP on ARCnet
  296.         mov     cx,18+14
  297.         jmp     nr_10
  298. nr_7:
  299.         test    OPTION_8023,N_OPTION    ;do we expect 802.3 packets?
  300.         jnz     nr_7a
  301.         cmp     ax,3781h        ;No: check for Bluebox IPX protocol
  302.         jne     nr_8
  303.         mov     protocol_id,250        ;IPX on ARCnet
  304.         jmp     nr_10
  305. nr_7a:
  306.         mov     ax,es:[di+14]        ;Every IPX packet begins with ffff.
  307.         cmp     ax,0ffffh        ;so we check the begin of the client
  308.                     ;data for this signature
  309.         jne     nr_8
  310.         mov     protocol_ID,250
  311.         jmp     nr_10
  312.  
  313. nr_8:
  314.         mov     ax,es:[di+12]        ;Ethernet Protocol
  315.         cmp     ax,0CAACh        ;LANSoft
  316.         jne     nr_5
  317.         mov     protocol_ID,251        ;LANSoft on ARCnet
  318.         jmp     nr_10
  319. nr_error:                ;We do not now this protocol and
  320.         assume  ds:nothing        ;cannot send
  321.         mov     dh,CANT_SEND
  322.         stc
  323.         ret
  324.  
  325. nr_10:
  326.         sub     cx,14            ;Forget EtherNet-Header
  327.         add     di,14
  328.         inc     sequence_number
  329.                     ;
  330.                     ;Look if we can send it as one packet or have to split the packet
  331.                     ;
  332.         xor     al,al
  333.         mov     Split_Number,0        ;Number of splits is zero in case of one packet
  334.         mov     pkt_number,0        ;Fragment number is zero for the first packet
  335.     cmp    cx,ARC_XMTU        ;length of client data longer than long frame?
  336.     jbe    new_send        ;no, we can send it as one packet
  337.         mov     split_number,1        ;division takes so long, so we just
  338.         cmp     cx,1008            ;compare
  339.         jbe     new_send
  340.         mov     split_number,3
  341.                     ;
  342. ;Wait for transmitter ready.
  343.         ;
  344. New_send:
  345.         push    es            ;save current position of paket
  346.         push    di
  347. New_send_2:
  348.     loadport
  349.     setport    STATUS
  350.  
  351.     mov    ax,SEND_IVAL        ;only wait this long for it.
  352.     call    set_timeout        ;otherwise we can't send.
  353. send_pkt_3:
  354.     in    al,dx            ;if not busy, exit.
  355.     and    al,ST_TA
  356.     jne    send_pkt_2
  357.     call    do_timeout        ;did we time out yet?
  358.     jne    send_pkt_3        ;no, not yet.
  359.  
  360.         loadport
  361.     setport    COMMAND            ;stop the transmit.
  362.     mov    al,DSBL_XMT
  363.     out    dx,al
  364.     mov    dh,CANT_SEND        ;timed out, can't send.
  365.         pop     si
  366.         pop     ds
  367.         assume  ds:nothing
  368.         stc
  369.     ret
  370.  
  371. send_pkt_2:
  372. ;store the packet on the board.
  373.     mov    es,mem_base
  374.     mov    di,XMTPAGE * 512
  375.  
  376.         mov     al,send_sid
  377.         mov     ah,send_did
  378.     stosw                ;move the SID and DID to the board.
  379.         mov     Stored_CX,cx            ;remeber the packet length
  380.  
  381.         cmp     cx,ARC_MTU              ;Decide which frame we use
  382.         jbe     Send_normal_1           ;normal frame
  383.         cmp     cx,ARC_MNTU
  384.         jbe     send_pkt_5a             ;exceptional frame
  385.         ;                               ;build header for long frame
  386.         xor    ax,ax
  387.         cmp    cx,ARC_XMTU              ;length less than long Frame ?
  388.         jbe    send_Long_1              ;yes, send it
  389.         mov    cx,ARC_XMTU              ;No: send 504 bytes
  390. send_Long_1:
  391.         mov    ax,508                   ;number of bytes - 4 Byte header
  392.         sub    ax,cx                    ;Offset is 508 - clientData
  393.         mov    ah,al                    ;length in ah for stosw and long frame
  394.         xor    al,al                    ;al=0 indicates non-normal frame
  395.         stosw                           ;
  396.         mov     al,ah                   ;Move offset to back to al
  397.         xor     ah,ah                   ;
  398.         sub     al,4                    ; -4 Byte for long frame
  399.         add     di,ax                   ;jump over unused bytes
  400.         jmp     send_splits
  401. send_pkt_5a:                            ; build header for exceptional frame
  402.         ;
  403.         mov     ax,504                  ;Octet-Zahl - 8 Byte (long frame - 4 padding bytes)
  404.         sub     ax,cx                   ;Offset is 504 - clientData
  405.         mov     ah,al                   ;
  406.         xor     al,al                   ;
  407.         stosw                           ;
  408.         mov     al,ah                   ;
  409.         xor     ah,ah                   ;
  410.         sub     al,4                    ;
  411.         add     di,ax                   ;
  412.         mov     al,Protocol_ID          ;First padding byte
  413.         mov     ah,0ffh                 ;indicates exceptional frame
  414.         stosw                           ;
  415.         mov     ax,0ffffh               ;Another two padding bytes
  416.         stosw                           ;
  417.         jmp     send_splits
  418.  
  419.         ;                               header for normal frame
  420. send_normal_1:
  421.         mov     ax,252                  ;
  422.         sub     ax,cx                   ;Offset is 252 - clientData
  423.         xor     ah,ah
  424.         stosb                           ;store offset
  425.         sub     al,3                    ;
  426.         add     di,ax                   ;jump over unused bytes
  427.  
  428. Send_Splits:
  429.         mov    al,Protocol_ID
  430.         xor    ah,ah                    ;We hope it was only one packet
  431.         cmp    Split_number,0
  432.         je     Send_Transmit_split      ;Ok, it was only one
  433.         cmp    Pkt_number,0             ;A sequence: is it the first fragment
  434.         jne    Send_Splits_2            ;
  435.         mov    ah,Split_Number          ;yes: Splitflag is (T-2)*2+1
  436.         jmp    send_Transmit_split      ;and send it
  437. Send_Splits_2:
  438.         mov    ah,Pkt_number            ;
  439.  
  440. Send_Transmit_split:
  441.         stosw                           ;
  442.         mov    ax,Sequence_Number       ;
  443.         stosw
  444.         cmp    protocol_ID,213          ;ARP and RARP packets differ between
  445.         je     send_arp                 ;ARCnet and Ethernet, because the hardware
  446.         cmp    protocol_ID,214          ;type is 7 for ARCnet and 1 for Ethernet and
  447.         je     send_ARP                 ;address length are 1 for ARCnet and 6 for Ethernet
  448.         cld
  449.         pop    si                       ;its and IP or IPX packet: just send it
  450.         pop    ds                       ;ds:si for movsw
  451.         assume ds:nothing
  452.         push   cx
  453.         call   movemem                  ;und nun noch cx bytes clientdata übertragen   ****
  454.         pop    cx
  455.         push   ds                       ;the next fragment
  456.         push   si
  457.         mov    ax,cs
  458.         mov    ds,ax
  459.         assume ds:code
  460.         jmp    send_transmit
  461. Send_ARP:
  462.         pop    si
  463.         pop    ds
  464.         assume ds:nothing
  465.         mov    ax,0700h                 ;HardwareType ARCnet
  466.         stosw
  467.         mov    ax,0008h                 ;Protocol is IP
  468.         stosw
  469.         mov    ax,0401h                 ;Hardware and IP-Length
  470.         stosw
  471.         add    si,6
  472.         movsw                           ;move opcode
  473.         add    si,5
  474.         movsb                           ;sender hardware adress
  475.         movsw                           ;sender IP Adress
  476.         movsw
  477.         push   cx
  478.         mov    cx,3
  479. Send_ARP_loop:                          ;check ARP destination for broadcast
  480.         lodsw
  481.         cmp    ax,0ffffh
  482.         je     Send_ARP_1
  483.         loop   Send_ARP_loop
  484.         xor    al,al
  485.         jmp    Send_ARP_2
  486. send_ARP_1:
  487.         dec    cx
  488.         rep    lodsw
  489.         mov    al,ah
  490. send_ARP_2:
  491.         stosb
  492.  
  493.         movsw                   ;destination IP address
  494.         movsw
  495.         pop    cx               ;cx was on the stack
  496.         push   ds
  497.         push   si
  498.         mov    ax,cs
  499.         mov    ds,ax
  500.         assume ds:code
  501. send_transmit:                  ;now send the packet
  502.  
  503.     mov    al,ENBL_XMT or (XMTPAGE shl 3)
  504.     loadport
  505.     setport    COMMAND
  506.     out    dx,al
  507.         mov     al,pkt_number
  508.         cmp     al,split_number                   ;was it the last fragment
  509.         jae     send_ende                         ;yes: sending is done
  510.         add     pkt_number,2
  511.         mov     cx,Stored_CX
  512.         sub     cx,ARC_XMTU                       ;No: we did send a long packet
  513.         jmp     New_Send_2
  514. send_ende:
  515.         pop     si
  516.         pop     ds
  517.         assume  ds:nothing
  518.     clc
  519.     ret
  520.  
  521.  
  522. ;Set address on controller
  523.     public    set_address
  524. set_address:
  525.     assume    ds:nothing
  526. ;enter with ds:si -> address, CX = length of address.
  527. ;exit with nc if okay, or cy, dh=error if any errors.
  528.     mov    dh,CANT_SET
  529.     stc
  530.     ret
  531.  
  532.  
  533. rcv_mode_3:
  534. ;receive mode 3 is the only one we support, so we don't have to do anything.
  535.     ret
  536.  
  537.  
  538.     public    set_multicast_list
  539. set_multicast_list:
  540. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  541. ;  cx = number of bytes.
  542. ;return nc if we set all of them, or cy,dh=error if we didn't.
  543.     mov    dh,NO_MULTICAST
  544.     stc
  545.     ret
  546.  
  547.  
  548.     public    terminate
  549. terminate:
  550.     assume    ds:code
  551.     loadport
  552.     setport    IMASK
  553.     mov    al,0
  554.     out    dx,al
  555.  
  556.         loadport
  557.     setport COMMAND
  558.     mov    al,DSBL_RCV
  559.     out    dx,al
  560.     mov    al,DSBL_XMT
  561.     out    dx,al
  562.  
  563.         loadport
  564.     setport    STATUS            ;do we need to do this [rnn]?
  565.     in    al,dx
  566.  
  567.     ret
  568.  
  569.  
  570.     public    reset_interface
  571. reset_interface:
  572. ;reset the interface.
  573. ;we don't do anything.
  574.     ret
  575.  
  576.  
  577.     include    timeout.asm
  578.  
  579. ;called when we want to determine what to do with a received packet.
  580. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  581.     extrn    recv_find: near
  582.  
  583. ;called after we have copied the packet into the buffer.
  584. ;enter with ds:si ->the packet, cx = length of the packet.
  585.     extrn    recv_copy: near
  586.  
  587. ;call this routine to schedule a subroutine that gets run after the
  588. ;recv_isr.  This is done by stuffing routine's address in place
  589. ;of the recv_isr iret's address.  This routine should push the flags when it
  590. ;is entered, and should jump to recv_exiting_exit to leave.
  591. ;enter with ax = address of routine to run.
  592.     extrn    schedule_exiting: near
  593.  
  594. ;recv_exiting jumps here to exit, after pushing the flags.
  595.     extrn    recv_exiting_exit: near
  596.  
  597.     extrn    count_in_err: near
  598.     extrn    count_out_err: near
  599.  
  600.     public    recv
  601. recv:
  602. ;called from the recv isr.  All registers have been saved, and ds=cs.
  603. ;Upon exit, the interrupt will be acknowledged.
  604.     assume    ds:code
  605.  
  606. recv_1:
  607.         loadport            ;get the status to see if we got
  608.     setport    STATUS            ;a false alarm.
  609.     in    al,dx
  610.         test    al,ST_RI
  611.         jnz     recv_1a                 ;its a packet, don't exit
  612.         ret
  613. recv_1a:
  614.         mov     es,mem_base             ;access the card via es:bx
  615.     mov    bx,RCVPAGE * 512
  616.  
  617. ;get packet length and splitflag
  618.         mov     ax,es:[bx+2]            ;look for offset
  619.         mov     cx,252                  ;-4 for client data
  620.         cmp     al,0                    ;test for non-normal frame
  621.         jne     short recv_my_1
  622.         mov     cx,508
  623.         mov     al,ah
  624. recv_my_1:
  625.         xor     ah,ah
  626.         add     bx,ax                 ;jump to packet
  627.         sub     cx,ax
  628.         mov     ax,es:[bx]
  629.         cmp     ah,0ffh               ;test for exceptional frame
  630.         jne     short recv_my_2
  631.         add     bx,4
  632.         sub     cx,4
  633.         mov     ax,es:[bx]            ;get the real splitflag
  634. recv_my_2:
  635.         test    ah,1
  636.         jz      recv_more             ;with the first fragment of a packet we
  637.                                       ;must be very fast because Novell
  638.                                       ;transmits fast, so we don't jump
  639.         cmp     ah,(MAX_FRAGMENTS - 2)*2+1
  640.         ja      recv_reset
  641. recv_new:
  642.         mov     last_expected,ah      ;in a new sequence the splitflag is
  643.                                       ;last splitflag -1 or zero for one packet
  644.         mov     recv_protocolbyte,al  ;protocol for tests
  645.         mov     di,es:[bx+2]
  646.         mov     expected_sequence,di
  647.         mov     recv_offset,offset recv_buffer
  648.         xor     ah,ah                 ;zero it because otherwise we would
  649.                                       ;think the sequence is complete with the
  650.                                       ;first packet
  651. recv_my_5:
  652.         cmp    ah,last_expected       ;was it the last fragment?
  653.         jae    recv_to_application    ;Never store the last fragment
  654.         push   ax
  655.         mov    ds,mem_base            ;move packet to the buffer
  656.         assume ds:nothing
  657.         mov    si,bx
  658.         add    si,4
  659.         mov    bx,cs
  660.         mov    es,bx
  661.         mov    di,cs:recv_offset
  662.  
  663.         cld
  664.         call   movemem
  665.         mov    ax,cs
  666.         mov    ds,ax
  667.         assume ds:code
  668.         pop    ax
  669.         mov    recv_offset,di
  670.         mov    expected_packet,ah
  671.         add    expected_packet,2        ;the next packet to expect
  672. recv_isr_9:
  673.  
  674.     loadport            ;enable reception again.
  675.     setport    COMMAND
  676.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST
  677.     out    dx,al
  678.  
  679.     jmp    recv_1
  680. recv_reset:
  681.         mov     last_expected,0feh      ;If a in-sequenve packet tests not ok
  682.         jmp     recv_isr_9
  683.  
  684. recv_more:
  685.         cmp     ah,0
  686.         je      recv_new                 ;splitflag zero is a new packet
  687.         cmp     last_expected,0feh       ;Are we in a sequence?
  688.         je      recv_isr_9               ;No
  689.         cmp     ah,expected_packet       ;Test splitflag,protocolbyte and sequence number
  690.         jb      recv_isr_9               ;Its a replayed (or wrong) packet
  691.         ja      recv_reset               ;Packet out of order
  692.         cmp     recv_protocolbyte,al
  693.         jne     recv_reset
  694.         mov     di,es:[bx+2]
  695.         cmp     di,expected_sequence
  696.         jne     recv_reset
  697.         cmp     ah,(MAX_FRAGMENTS - 1)*2    ;we can only store MAX_FRAGMENT
  698.         jbe     recv_My_5
  699.         jmp     recv_reset
  700.  
  701. recv_to_application:                          ;we gathered the whole sequence
  702.                                               ;and have now (hopefully) enough
  703.                                               ;time to build the EtherNet Packet
  704.         add     bx,4
  705.         mov     recv_packet,bx                ;offset of client data for the last fragment
  706.         mov     last_length,cx                ;length of client data of the last fragment
  707.         mov     ax,ds
  708.         mov     es,ax
  709.         mov     cx,recv_offset
  710.         sub     cx,offset recv_buffer         ;length of reassembled part
  711.  
  712.         mov     last_expected,0feh            ;the sequence is complete
  713.         add     cx,14                         ;for the EtherNet-Header
  714.         add     cx,last_length                ;and the last fragment
  715.  
  716.         mov     al,recv_protocolbyte
  717.         mov     dl,driver_class
  718.         cmp     al,250                  ;is it IPX
  719.         jne     recv_new_4              ;No
  720.         mov     recv_protocol,3781h
  721.         test    OPTION_8023,N_OPTION    ;Is 802.3-Option set ?
  722.         jz      recv_new_10             ;No, proceed as normal
  723.         mov     dl,11                   ;Yes, now we are driver class 11
  724.         mov     recv_protocol,0ffffh    ;and use novell protocol ffffh
  725.         jmp     recv_new_10
  726.  
  727. recv_isr_9a:
  728.         jmp     recv_isr_9
  729.  
  730. recv_new_4:
  731.         cmp     al,212
  732.         jne     recv_new_5
  733.         mov     recv_protocol,0008h     ;IP packet
  734.         jmp     recv_new_10
  735. recv_new_5:
  736.         cmp     al,213
  737.         jne     recv_new_6
  738.         mov     recv_protocol,0608h     ;ARP Packet
  739.         mov     cx,42
  740.         jmp     recv_new_10
  741. recv_new_6:
  742.         cmp     al,214
  743.         jne     recv_new_7
  744.         mov     recv_protocol,3580h     ;RARP Packet
  745.         mov     cx,42
  746.         jmp     recv_new_10
  747.  
  748. recv_new_7:
  749.     cmp    al,251
  750.     jne    recv_new_8
  751.         mov     recv_protocol,0CAACh     ;LANSoft
  752.         jmp     recv_new_10
  753.  
  754. recv_new_8:
  755.         ;mov     ah,al
  756.         ;mov     recv_protocol,ax        ;We dont know the frame and
  757.                                          ;double te protocol ID for inspection of
  758.                                          ;these packets by a watch client
  759.         jmp      recv_isr_9              ;to be comaptible with other drivers,
  760.                                          ;we just free the frame
  761. recv_new_10:
  762.         push    cx
  763.         mov     ax,ds
  764.         mov     es,ax
  765.         mov     di,offset recv_protocol
  766.         call    recv_find                ;find a client who wants this packet
  767.         pop     cx
  768.  
  769.         mov     ax,es                        ;is this pointer null?
  770.         or      ax,di
  771.  
  772.         je      recv_isr_9a                  ;Yes, forget the packet
  773.  
  774.         push    cx                           ;remember length and buffer address
  775.         push    es
  776.         push    di
  777.  
  778.         mov     si,RCVPAGE*512               ;sid and did of the last fragment
  779.         mov     ds,mem_base
  780.         assume  ds:nothing
  781.         lodsw
  782.         push    cx
  783.         push    ax
  784.         mov     bx,cs
  785.         mov     ds,bx
  786.         assume  ds:code
  787.  
  788.         cmp     ah,0                            ;receiving broadcast
  789.         jne     recv_directed
  790.         mov     cx,3
  791.         mov     ax,0ffffh
  792.         rep     stosw
  793.         jmp     short recv_source
  794. recv_directed:                                  ;directed packets
  795.         xor     ax,ax
  796.         mov     cx,2
  797.         rep     stosw
  798.         pop     ax
  799.         push    ax
  800.         xor     al,al
  801.         stosw
  802. recv_source:                                    ;source address
  803.         xor     ax,ax
  804.         mov     cx,2
  805.         rep     stosw
  806.         pop     ax
  807.         mov     ah,al
  808.         xor     al,al
  809.         stosw
  810.         mov     ax,recv_protocol                ;Ethernet protocol
  811.         stosw
  812.  
  813.         mov     si,offset recv_buffer           ;with ARP and RARP its
  814.         cmp     recv_protocol,0608h             ;its just the opposite as in
  815.         je      recv_arp                        ;case of sending packets
  816.         cmp     recv_protocol,3580h
  817.         je      recv_arp
  818.         pop     cx
  819.         sub     cx,14
  820.         sub     cx,last_length
  821.         cld
  822.         jcxz    recv_move_last
  823.         call    movemem                        ;The first fragments
  824. recv_move_last:
  825.         mov     cx,last_length
  826.         mov     si,recv_packet
  827.         mov     ds,mem_base
  828.         assume  ds:nothing
  829.         cld
  830.         call    movemem                        ;And the last fragment
  831.         jmp     recv_copied
  832. recv_arp:
  833.         pop     cx
  834.         mov     si,recv_packet
  835.         mov     ds,mem_base
  836.         assume  ds:nothing
  837.         cld
  838.         xor     al,al
  839.         mov     ah,1
  840.         stosw                         ;Put Hardware-Type EtherNet at ist place
  841.         mov     ax,0008h
  842.         stosw                         ;Protocol used is IP
  843.         mov     ax,0406h              ;Length of Ethernet and IP-Adress
  844.         stosw
  845.                                       ;now we transfer ARCnet-Client-Data to Ethernet-Client-Data
  846.         add     si,6
  847.         movsw                         ;move opcode
  848.         mov     cx,5
  849.         xor     al,al                 ;Padd first five byte of source address with zero
  850.         rep     stosb
  851.         movsb                         ;Move ARCNet-Hardware Adress
  852.         movsw                         ;Sender IP-Adress
  853.         movsw
  854.         lodsb                         ;now we check destination for Broadcast
  855.         cmp     al,0
  856.         je      recv_hw_bcast
  857.         mov     ah,al                 ;directed ARP
  858.         xor     al,al
  859.         mov     cx,5
  860.         rep     stosb
  861.         mov     al,ah
  862.         stosb
  863.         jmp     recv_client_2
  864. recv_hw_bcast:
  865.         mov    ax,0ffffh              ;Target was Broadcast
  866.         mov    cx,3
  867.         rep    stosw
  868. recv_client_2:
  869.         movsw                         ;Target IP-Address
  870.         movsw
  871. recv_copied:
  872.         cmp     cs:recv_protocol,0ffffh  ;Novell 802.3 packet ?
  873.         jne     recv_copied_2
  874.  
  875.         pop     di                    ;Yes: put length in prot field
  876.         push    di
  877.     mov    ax,es:[di+16]       ; get len
  878.     xchg    ah,al
  879.     inc    ax            ; make even (rounding up)
  880.     and    al,0feh
  881.     xchg    ah,al
  882.     mov    es:[di+12],ax       ; save in prot field
  883.  
  884. recv_copied_2:
  885.  
  886.         pop     si
  887.         pop     ds
  888.         pop     cx
  889.         assume  ds:nothing
  890.         call    recv_copy               ;tell the client that we
  891.         mov     ax,cs                   ;copied the packet
  892.         mov     ds,ax
  893.         assume  ds:code
  894.         jmp     recv_isr_9
  895.  
  896.     public    timer_isr
  897. timer_isr:
  898. ;if the first instruction is an iret, then the timer is not hooked
  899.     iret
  900.  
  901. ;any code after this will not be kept.  Buffers used by the program, if any,
  902. ;are allocated from the memory between end_resident and end_free_mem.
  903.     public end_resident,end_free_mem
  904. end_resident    label    byte
  905. end_free_mem    label    byte
  906.  
  907.     public    usage_msg
  908. usage_msg    db    "usage: arcether [options] <packet_int_no> <hardware_irq> <io_addr> <mem_base>",CR,LF,'$'
  909.  
  910.     public    copyright_msg
  911. copyright_msg    db    "Packet driver for Novell ARCnet TCP/IP and IPX version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  912.         db    "Portions Copyright 1988 Philip Prindeville",CR,LF
  913.                 db      "Copyright 1991 Martin Wilmes",CR,LF,'$'
  914.  
  915. no_arcnet_msg    db    "No ARCnet found at that address.",CR,LF,'$'
  916. failed_test_msg    db    "Failed self test.",CR,LF,'$'
  917.  
  918. int_no_name    db    "Interrupt number ",'$'
  919. io_addr_name    db    "I/O port ",'$'
  920. mem_base_name    db    "Memory address ",'$'
  921.  
  922.     extrn    set_recv_isr: near
  923.  
  924. ;enter with si -> argument string, di -> word to store.
  925. ;if there is no number, don't change the number.
  926.     extrn    get_number: near
  927.  
  928. ;enter with dx -> name of word, di -> dword to print.
  929.     extrn    print_number: near
  930.         extrn   flagbyte
  931.  
  932. ;=length of our address.
  933.     extrn    address_len: word
  934.  
  935. ;-> the assigned address of the card.
  936.     extrn    rom_address: byte
  937.  
  938.     public    parse_args
  939. parse_args:
  940. ;exit with nc if all went well, cy otherwise.
  941.         test    cs:flagbyte,N_OPTION            ;Check if -n Option was used
  942.         jz      next_arg
  943.         xor     cs:flagbyte,N_OPTION            ;if yes: clear this flag and
  944.         or      OPTION_8023,N_OPTION            ;set our own flag, because
  945.         mov     cs:[driver_class+1],11          ;standard N_OPTION does not
  946.                                                 ;work with a ARCnet-Driver
  947.                                                 ;and has another meaning for us
  948. next_arg:
  949.     mov    di,offset int_no
  950.                                                 
  951.                                                 
  952.     call    get_number
  953.     mov    di,offset io_addr
  954.     call    get_number
  955.     mov    di,offset mem_base
  956.     call    get_number
  957.     clc
  958.     ret
  959.  
  960.  
  961. no_arcnet_error:
  962.     mov    dx,offset no_arcnet_msg
  963.     stc
  964.     ret
  965. failed_test_error:
  966.     mov    dx,offset failed_test_msg
  967. error:
  968.     stc
  969.     ret
  970.  
  971.  
  972.     public    etopen
  973. etopen:
  974. ;reset the board via the I/O reset port, then wait for it to become sane again.
  975.  
  976.     mov    ax,mem_base        ;test the memory first.
  977.     mov    cx,2048
  978.     call    memory_test
  979.     jne    no_arcnet_error
  980.  
  981.     mov    es,mem_base
  982.  
  983.     loadport
  984.     setport SW_RST
  985.     in    al,dx
  986.  
  987.     mov    ax,RST_IVAL
  988.     call    set_timeout
  989. etopen_1:
  990.     call    do_timeout
  991.     jne    etopen_1
  992.  
  993.         loadport
  994.     setport    STATUS
  995.     in    al,dx
  996.  
  997. ;since we've just reset:
  998. ;    reset the POR flag,
  999. ;    check the diagnostic byte in the buffer,
  1000. ;    grab the node ID, and assign it to the host number.
  1001.  
  1002.     test    al,ST_POR
  1003.     je    etopen_2
  1004.  
  1005.         loadport
  1006.     setport    COMMAND
  1007.     mov    al,CLR_FLGS or FL_POR or FL_RECON
  1008.     out    dx,al
  1009.  
  1010.     mov    al,es:[0]
  1011.     cmp    byte ptr es:[0],TSTWRD
  1012.     je    etopen_3
  1013.     jmp    failed_test_error    ;failed power on self-test.
  1014. etopen_3:
  1015.     mov    al,es:[1]
  1016.     mov    rom_address[5],al
  1017.     mov    address_len,ARCADDR_LEN
  1018. etopen_2:
  1019.  
  1020. ;another simple diagnostic:
  1021. ;    force test flag on in RIM,
  1022. ;    check to see that it is set,
  1023. ;    reset it.
  1024.  
  1025.     loadport
  1026.     setport    COMMAND
  1027.     mov    al,LD_TST_FLG or FL_TST
  1028.     out    dx,al
  1029.  
  1030.         loadport
  1031.     setport STATUS
  1032.     in    al,dx
  1033.  
  1034.     test    al,FL_TST
  1035.     jne    etopen_4
  1036.     jmp    failed_test_error    ;failed forced self-test.
  1037. etopen_4:
  1038.         loadport
  1039.     setport    COMMAND
  1040.     mov    al,LD_TST_FLG
  1041.     out    dx,al
  1042.         loadport
  1043.     setport STATUS
  1044.     in    al,dx
  1045.  
  1046.     pushf
  1047.     cli
  1048.  
  1049.     call    set_recv_isr
  1050.  
  1051. ;now we enable the board to interrupt
  1052. ;us on packet received.  Not transmiter available
  1053. ;(i.e. transmission complete).  We don't have
  1054. ;any control over POR, since it is NMI...
  1055. ;RECON seems useless.
  1056.  
  1057.     loadport
  1058.     setport    IMASK
  1059.     mov    al,ST_RI
  1060.     out    dx,al
  1061.  
  1062.     ; we should allow extended packets
  1063.         loadport
  1064.     setport    COMMAND
  1065.     mov    al,DFN_CONF or CONF_XTND
  1066.     out    dx,al
  1067.  
  1068.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST;
  1069.     out    dx,al
  1070.  
  1071.     popf
  1072.  
  1073.     mov    al, int_no        ; Get board's interrupt vector
  1074.     add    al, 8
  1075.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1076.     jb    set_int_num        ; No.
  1077.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1078. set_int_num:
  1079.     xor    ah, ah            ; Clear high byte
  1080.     mov    int_num, ax        ; Set parameter_list int num.
  1081.  
  1082.     clc
  1083.     ret
  1084.  
  1085.     public    print_parameters
  1086. print_parameters:
  1087.     mov    di,offset int_no
  1088.     mov    dx,offset int_no_name
  1089.     call    print_number
  1090.     mov    di,offset io_addr
  1091.     mov    dx,offset io_addr_name
  1092.     call    print_number
  1093.     mov    di,offset mem_base
  1094.     mov    dx,offset mem_base_name
  1095.     call    print_number
  1096.     ret
  1097.  
  1098.     include    memtest.asm
  1099.  
  1100. code    ends
  1101.  
  1102.     end
  1103.