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

  1. version        equ     2
  2. ;******************************************************************************;
  3. ;*    File:    EN301.ASM
  4. ;*        Packet Driver for Multi-Tech Systems EN301xx series
  5. ;*        ETHERNET adapters.
  6. ;*      Auth:    Chris Elmquist    N0JCF
  7. ;*    Date:    April 1, 1991
  8. ;*        Removed Microchannel support and added code to
  9. ;*        support serial EEPROM on Multi-Tech card.
  10. ;*
  11. ;*   Copyright (C) 1991  Chris Elmquist
  12. ;*
  13. ;*   This program is free software; you can redistribute it and/or modify
  14. ;*   it under the terms of the GNU General Public License as published by
  15. ;*   the Free Software Foundation; either version 1, or (at your option)
  16. ;*   any later version.
  17. ;*
  18. ;*   This program is distributed in the hope that it will be useful,
  19. ;*   but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. ;*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. ;*   GNU General Public License for more details.
  22. ;*
  23. ;*   You should have received a copy of the GNU General Public License
  24. ;*   along with this program; if not, write to the Free Software
  25. ;*   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26. ;*
  27. ;******************************************************************************;
  28. ;*        Original work from:                          *;
  29. ;*                        File: TiaraFTP.ASM                          *;
  30. ;*                 Auth: Brian Fisher                          *;
  31. ;*                       Queens University                             *;
  32. ;*                       Computing and Communications Services         *;
  33. ;*                       Rm 2-50 Dupuis Hall                           *;
  34. ;*                       Kingston Ontario                              *;
  35. ;*                Date: January 24 1990                         *;
  36. ;*============================================================================*;
  37. ;*     Revs: January 25 1990   V 1.6.0 Clean up code and document.            *;
  38. ;*           Feb     24 1991   V 1.8.2 Gets IRQ and I/O info from MCH POS regs*;
  39. ;*                                                                            *;
  40. ;*============================================================================*;
  41. ;*                                                                            *;
  42. ;*     Thanks, Mehdi Safipour, of Tiara Computer Systems, who supplied the    *;
  43. ;*     programming manual and examples.                                       *;
  44. ;*                                                                            *;
  45. ;*============================================================================*;
  46. ;*                                                                            *;
  47. ;*     Logic -                                                                *;
  48. ;*                                                                            *;
  49. ;*     Initialization - classic, by-the-book initialization, with one         *;
  50. ;*     exception:  The manual didn't mention the fact that receive            *;
  51. ;*     interrupts will not always work unless the receive buffer is           *;
  52. ;*     vacuumed.                                                              *;
  53. ;*                                                                            *;
  54. ;*     Byte/Word I/O mode was determined by code ruthlessly copied from       *;
  55. ;*     NI5010.ASM, auth: Russ Nelson.                                         *;
  56. ;*                                                                            *;
  57. ;*     Transmit-no surprises, data goes whoosh!                               *;
  58. ;*                                                                            *;
  59. ;*     Receive-interrupt driven receive makes upcalls to inform the ULP of    *;
  60. ;*     its status.  The 14 byte ethernet header is copied from the card to    *;
  61. ;*     a temporary buffer, to determine the ether-type.  Recv_find is called  *;
  62. ;*     to acquire a buffer from the ULP.  If no buffer, the packet is dropped.*;
  63. ;*     If a buffer is acquired, the packet is copied into it, and recv_copy   *;
  64. ;*     informs the ULP that the data is there.                                *;
  65. ;*                                                                            *;
  66. ;******************************************************************************;
  67. ;
  68.  
  69. DLCR_XMIT_STAT EQU     0               ; EtherStar I/O Register offsets
  70. DLCR_XMIT_MASK EQU     1
  71. DLCR_RECV_STAT EQU     2
  72. DLCR_RECV_MASK EQU     3
  73. DLCR_XMIT_MODE EQU     4
  74. DLCR_RECV_MODE EQU     5
  75. DLCR_ENABLE    EQU     6
  76. DLCR_TDR_LOW   EQU     7
  77. DLCR_NODE_ID   EQU     8
  78. DLCR_TDR_HIGH  EQU     0FH
  79. BMPR_MEM_PORT  EQU     10H
  80. BMPR_PKT_LEN   EQU     12H
  81. BMPR_DMA_ENABLE EQU    14H
  82. EECS_PORT    EQU    18H
  83. EECLK_PORT    EQU    19H
  84. EEDI_PORT    EQU    1AH
  85. EEDO_PORT    EQU    1AH
  86. TMST           EQU     80h
  87. TMT_OK         EQU     80h
  88. BUF_EMPTY      EQU     40h
  89. card_disable   equ     80h             ; written to DLCR_ENABLE to disable card
  90. card_enable    equ     0h              ; written to DLCR_ENABLE to enable card
  91. clear_status   equ     00001111B       ; used to clear status info
  92. ;
  93. ;                      !!!!!!!!--------
  94. ;                      !!!!!!!+--------CLEAR BUS WRITE ERROR
  95. ;                      !!!!!!+---------CLEAR 16 COLLISION
  96. ;                      !!!!!+----------CLEAR COLLISION
  97. ;                      !!!!+-----------CLEAR UNDERFLOW
  98. ;                      !!!+------------NC
  99. ;                      !!+-------------NC
  100. ;                      !+--------------NC
  101. ;                      +---------------NC
  102. ;
  103. no_tx_irqs      equ     0              ; written to clear transmit IRQs
  104. clr_rcv_status  equ     0CFh           ; clears receive status
  105. en_rcv_irqs     equ     10000000B      ; enable receive interrupts
  106. ;
  107. ;                      !!!!!!!!--------
  108. ;                      !!!!!!!+--------ENABLE OVERFLOW
  109. ;                      !!!!!!+---------ENABLE CRC
  110. ;                      !!!!!+----------ENABLE ALIGN
  111. ;                      !!!!+-----------ENABLE SHORT PKT
  112. ;                      !!!+------------DISABLE REMOTE RESET
  113. ;                      !!+-------------RESERVED
  114. ;                      !+--------------RESERVED
  115. ;                      +---------------ENABLE PKT READY
  116. ;
  117. xmit_mode       equ     00000010B
  118. ;                       !!!!!!!!---------ENABLE CARRIER DETECT
  119. ;                       !!!!!!!+---------DISABLE LOOPBACK
  120. ;
  121. ;
  122. recv_mode       equ     00000010B                 ; set receive mode
  123. ;
  124. ;                       !!!!!!!!---------ACCEPT ALL PACKETS
  125. ;                       !!!!!!!+---------ACCEPT PHYSICAL, MULTICAST, AND
  126. ;                       !!!!!!+----------BROADCAST PACKETS
  127. ;                       !!!!!+-----------DISABLE REMOTE RESET
  128. ;                       !!!!+------------DISABLE SHORT PACKETS
  129. ;                       !!!+-------------USE 6 BYTE ADDRESS
  130. ;                       !!+--------------NC
  131. ;                       !+---------------NC
  132. ;                       +----------------DISABLE CRC TEST MODE
  133.  
  134. debug    = 0
  135.  
  136.     include defs.asm
  137.  
  138. code segment word public
  139.     assume  cs:code, ds:code
  140.  
  141.     public  int_no
  142. int_no    db      3,0,0,0            ;must be four bytes long for get_number
  143. io_adr    dw    300h,0            ; default I/O address
  144.     extrn    is_186: byte        ;=0 if 808[68], =1 if 80[123]86.
  145.  
  146.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  147. driver_class    db      BLUEBOOK,IEEE8023,0    ;from the packet spec
  148. driver_type    db      1        ;from the packet spec
  149. driver_name    db      'EN301FTP',0    ;name of the driver.
  150. driver_function    db    2
  151. parameter_list    label    byte
  152.     db    1    ;major rev of packet driver
  153.     db    9    ;minor rev of packet driver
  154.     db    14    ;length of parameter list
  155.     db    EADDR_LEN    ;length of MAC-layer address
  156.     dw    GIANT    ;MTU, including MAC headers
  157.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  158.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  159.     dw    0    ;(# of successive xmits) - 1
  160. int_num    dw    0    ;Interrupt # to hook for post-EOI
  161.             ;processing, 0 == none,
  162.  
  163.     public  rcv_modes
  164. rcv_modes    dw    7        ;number of receive modes in our table.
  165.         dw    0               ;There is no mode zero
  166.         dw    rcv_mode_1
  167.         dw    0
  168.         dw    rcv_mode_3
  169.         dw    0        ;haven't set up perfect filtering yet.
  170.         dw    0
  171.         dw    rcv_mode_6
  172.  
  173.  
  174. ;
  175. ;      Receive Packet Header Buffer: Required because addresses and e-type
  176. ;      must be read from Tiara card before upcall to find a buffer can be
  177. ;      made.  Need the number of bytes, and the e-type for the call...
  178. ;
  179. ether_buff    db    EADDR_LEN  dup(?)
  180.         db    EADDR_LEN  dup(?)
  181. ether_type    db    4 dup(?)
  182. usr_ptr        dd    ?                 ; temp storage or recv_buff ptr
  183.  
  184. writebport  macro   from_base,value
  185.     mov    dx,cs:[io_adr]        ; write byte value to port
  186.     add    dx,from_base
  187.     mov    al,value
  188.     out    dx,al
  189.     endm
  190.  
  191. readbport  macro  from_base
  192.     mov    dx,cs:[io_adr]
  193.     add    dx,from_base
  194.     in    al,dx
  195.     endm
  196.  
  197. port    macro    from_base
  198.     mov    dx,cs:[io_adr]
  199.     add    dx,from_base
  200.     endm
  201.  
  202. mark           = 0F90h                 ; marker debug pos on screen 25
  203.  
  204. marker  macro   st,nd
  205.   IF  debug NE 0                       ; do marker if debug <> 0
  206.       pushf                            ; show 2 char marker on
  207.       push es                          ; 25th line, 1st column
  208.       push ax
  209.       mov  ax,0B800h
  210.       mov  es,ax
  211.       mov  al,'&st&'
  212.       mov  byte ptr es:[mark],al
  213.       mov  al,byte ptr es:[mark+1]     ; get color value
  214.       inc  al
  215.       and  al,0Fh
  216.       or   al,1
  217.       mov  byte ptr es:[mark+1],al     ; advance it to show activity
  218.       mov  al,'&nd'
  219.       mov  byte ptr es:[mark+2],al
  220.       mov  al,byte ptr es:[mark+3]
  221.       inc  al
  222.       and  al,0Fh
  223.       or   al,1
  224.       mov  byte ptr es:[mark+3],al
  225.       pop  ax
  226.       pop  es
  227.       popf
  228.     ENDIF
  229.   endm
  230.  
  231.     public bad_command_intercept
  232. bad_command_intercept:
  233. ;called with ah=command, unknown to the skeleton.
  234. ;exit with nc if okay, cy, dh=error if not.
  235.     mov    dh,BAD_COMMAND
  236.     stc
  237.     ret
  238.  
  239.     public    as_send_pkt
  240. ; The Asynchronous Transmit Packet routine.
  241. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  242. ;   interrupts possibly enabled.
  243. ; Exit with nc if ok, or else cy if error, dh set to error number.
  244. ;   es:di and interrupt enable flag preserved on exit.
  245. as_send_pkt:
  246.     ret
  247.  
  248.     public    drop_pkt
  249. ; Drop a packet from the queue.
  250. ; Enter with es:di -> iocb.
  251. drop_pkt:
  252.     assume    ds:nothing
  253.     ret
  254.  
  255.     public    xmit
  256. ; Process a transmit interrupt with the least possible latency to achieve
  257. ;   back-to-back packet transmissions.
  258. ; May only use ax and dx.
  259. xmit:
  260.     assume    ds:nothing
  261.     ret
  262.  
  263.  
  264.     public    send_pkt
  265. send_pkt:
  266. ;enter with ds:si -> packet, cx = packet length.
  267. ;exit with nc if ok, pr else cy if error, dh set to error number.
  268.  
  269.               assume  ds:nothing
  270.               marker  T,X
  271.               inc     cx
  272.               and     cx,not 1                ; round to nearest even number
  273.               cmp     cx,RUNT                 ; big enough?
  274.               jae     send_runt_ok
  275.               mov     cx,RUNT                 ; at least runt!
  276. send_runt_ok:
  277.               cmp     cx,GIANT                ; small enough?
  278.               jbe     send_size_ok
  279.               mov     dh,NO_SPACE
  280.               stc                             ; Error
  281.               ret
  282. send_size_ok:
  283.               push    cx
  284.               shr     cx,1                    ; words to send
  285. ;
  286. ;      8086/8088 byte mode send
  287. ;
  288.               mov     dx,cs:[io_adr]
  289.               add     dx,BMPR_MEM_PORT
  290.               cmp     cs:is_186,0  ; use BYTE or WORD mode?
  291.               jne     send_w_mode
  292.  xb:
  293.               lodsw                           ; load word, ind ds:si
  294.               out     dx,al
  295.               xchg    ah,al
  296.               out     dx,al
  297.               loop    xb                      ; set packet length (byte mode)
  298.               pop     ax
  299.               or      ah,TMST
  300.               mov     dx,cs:[io_adr]
  301.               add     dx,BMPR_PKT_LEN
  302.               out     dx,al                   ; write BMPR2, then BMPR3 to
  303.               xchg    al,ah                   ; initiate byte mode transmit
  304.               inc     dx
  305.               out     dx,al
  306.               jmp     wait_tmt_ok
  307. send_w_mode:
  308.               .286
  309.               rep    outsw
  310.               .8086
  311.               pop     ax
  312.               or      ah,TMST
  313.               mov     dx,cs:[io_adr]
  314.               add     dx,BMPR_PKT_LEN
  315.               out     dx,ax
  316. wait_tmt_ok:
  317.               xor     cx,cx
  318.               mov     dx,cs:[io_adr]
  319.               IF DLCR_XMIT_STAT NE 0
  320.                  add     dx,DLCR_XMIT_STAT
  321.               ENDIF
  322. wait_tmt:
  323.               in      al,dx            ; read status register until timeout...
  324.               test    al,TMT_OK
  325.               jnz     send_ok
  326.               loop    wait_tmt
  327.               stc
  328.               ret
  329. send_ok:
  330.               clc
  331.               ret
  332.  
  333.     public  set_address
  334. set_address:
  335. ;enter with ds:si -> Ethernet address,CX = length of address.
  336. ;exit with nc if okay, or cy, dh=error if any errors.
  337.     assume    ds:nothing
  338.     ret
  339.  
  340.  
  341. rcv_mode_1:
  342.     writebport    DLCR_RECV_MODE,0    ; don't receive any packets
  343.     ret
  344.  
  345.  
  346. rcv_mode_3:
  347.     writebport    DLCR_RECV_MODE,2    ; receive mine, broads, and multis.
  348.     ret
  349.  
  350.  
  351. rcv_mode_6:
  352.     writebport    DLCR_RECV_MODE,3    ; receive all packets.
  353.     ret
  354.  
  355.  
  356.     public  set_multicast_list
  357. set_multicast_list:
  358. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  359. ;  cx = number of bytes.
  360. ;return nc if we set all of them, or cy,dh=error if we didn't.
  361.  
  362.     mov     dh,NO_MULTICAST
  363.     stc
  364.     ret
  365.  
  366.     public    terminate
  367. terminate:
  368.     writebport    DLCR_RECV_MODE,0    ; don't receive any packets
  369.     ret
  370.  
  371.     public  reset_interface
  372. reset_interface:                       ;reset the interface.
  373.     assume  ds:code
  374.     ret
  375.  
  376. ;called when we want to determine what to do with a received packet.
  377. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  378.     extrn   recv_find: near
  379.  
  380. ;called after we've copied the packet into the buffer.
  381. ;enter with ds:si ->the packet, cx = length of the packet.
  382.     extrn   recv_copy: near
  383.  
  384.     extrn   count_in_err: near
  385.     extrn   count_out_err: near
  386.  
  387.     public  recv
  388. recv:
  389. ;called from the recv isr.  All registers have been saved, and ds=cs.
  390. ;Upon exit, the interrupt will be acknowledged.
  391.  
  392.     assume  ds:code
  393.     marker  R,X
  394.  
  395. ;clear receive masks to prevent further IRQs
  396.  
  397.     writebport    DLCR_RECV_MASK,0
  398. recv_0:
  399.     mov     ax,cs
  400.     mov     ds,ax
  401.     writebport      DLCR_RECV_STAT,clr_rcv_status
  402.  
  403. ;are there any packets to read?
  404.  
  405.     mov     dx,cs:[io_adr]
  406.     add     dx,DLCR_RECV_MODE
  407.     in      al,dx
  408.     test    al,BUF_EMPTY
  409.     jz      recv_1                    ; 0 if at least one valid pkt..
  410.     jmp     recv_99
  411.  
  412. ;yes, read out a receive packet...
  413.  
  414. recv_1:
  415.               cmp     cs:is_186,0
  416.               jne     recv11
  417.               jmp     read_b_mode
  418. ;
  419. ;        read packet out in word mode
  420. ;
  421. recv11:
  422.     mov    dx,cs:[io_adr]    ; get status and reserved byte
  423.     add    dx,BMPR_MEM_PORT
  424.     in    ax,dx
  425.     in    ax,dx                           ; get packet size
  426.     inc    ax                              ; convert to words
  427.     and    ax,not 1                        ; save it for copy out...
  428.     push    ax
  429.                     ;read first 14 bytes from receive buffer into ether_buff
  430.     mov    ax,cs
  431.     mov    es, ax
  432.     mov    di,offset ether_buff
  433.     mov    cx,16/2                            ; word mode, remember...
  434.     .286
  435.     rep    insw            ; read words into ether_buff
  436.     .8086
  437.  
  438. ;
  439. ;      If the sender is myself, ignore the packet.  This allows async
  440. ;      send/receive without messing up...
  441. ;
  442.     mov    si,offset ether_buff+EADDR_LEN       ; we want the SOURCE
  443.     mov    di,offset my_address
  444.     mov    cx,EADDR_LEN/2
  445.     repe    cmpsw
  446.     jne    not_mine
  447.     jmp    word_flush                      ; mine, so flush it
  448. ;
  449. ;      cx = length, es:di = pointer to ethertype
  450. ;
  451. not_mine:
  452.     pop    cx
  453.     push    cx
  454.     mov    di,offset ether_type
  455.     mov    ax,cs
  456.     mov    es,ax            ; es:di -> ether type, cx = size# bytes
  457.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  458.     mov    ax, es:[di]
  459.     xchg    ah, al
  460.     cmp     ax, 1500
  461.     ja    BlueBookPacket
  462.     inc    di            ;set di to 802.2 header
  463.     inc    di
  464.     mov    dl, IEEE8023
  465. BlueBookPacket:
  466.     call    recv_find        ; got a buffer?
  467.     mov    ax,es
  468.     or    ax,di            ; pointer zero?
  469.     je    word_flush        ; no pointer, discard data
  470. ;
  471. ;      es:di -> users buffer, do copy...
  472. ;      ds:si -> source of copy
  473. ;
  474.     mov    cs:[usr_ptr.segm],es; save ULP pointer
  475.     mov    cs:[usr_ptr.offs],di
  476.     mov    ax,cs
  477.     mov    ds,ax
  478.     mov    si,offset ether_buff    ; copy header to users buffer
  479.     mov    cx,16/2            ; 8 words to copy
  480.     rep    movsw
  481.     mov    dx,cs:[io_adr]        ;copy rest of data to user
  482.     add    dx,BMPR_MEM_PORT    ; buffer in es:di ->
  483.     pop    cx
  484.     push    cx
  485.     sub    cx,16
  486.     shr    cx,1
  487.     .286
  488.     rep    insw            ; read word, store at es:di ->
  489.     .8086
  490.     pop    cx            ;call recv_copy to say copy done
  491.     lds    si,cs:[usr_ptr]
  492.     call    recv_copy
  493.     jmp    recv_0            ; go get another packet
  494. word_flush:
  495.     mov    dx,cs:[io_adr]
  496.     add    dx,BMPR_MEM_PORT
  497.     pop    cx
  498.     sub    cx,16            ; adjust word count
  499.     shr    cx,1
  500. word_f:
  501.     in    ax,dx
  502.     loop    word_f
  503.     jmp    recv_0
  504. ;
  505. ;             go see of any more packets comming....
  506. ;
  507. ;             READ in BYTE MODE
  508. ;
  509. read_b_mode:
  510.     mov    dx,cs:[io_adr]    ;get status and reserved byte
  511.     add    dx,BMPR_MEM_PORT
  512.     in    al,dx        ; vacuum status and reserved
  513.     in    al,dx
  514.     in    al,dx        ; get packet size
  515.     xchg    al,ah        ; low byte in ah
  516.     in    al,dx        ; get packet size
  517.     xchg    al,ah        ; fix size ah/al order
  518.     push    ax        ; keep number of bytes
  519.     ;      read first 16 bytes from receive buffer into ether_buff
  520.     mov    ax,cs
  521.     mov    es,ax
  522.     mov    di,offset ether_buff
  523.     mov    cx,16            ; byte mode, 16 byte header
  524. rdb:
  525.     in    al,dx            ; read 16 bytes into ether_buff
  526.     stosb
  527.     loop    rdb
  528. ;
  529. ;      If the sender is myself, ignore the packet.
  530. ;
  531.     mov    si,offset ether_buff+EADDR_LEN       ; we want the SOURCE
  532.     mov    di,offset my_address
  533.     mov    cx,EADDR_LEN/2
  534.     repe    cmpsw
  535.     jne    not_mineb
  536.     jmp    byte_flush                  ; mine, so flush it
  537. ;
  538. ;      cx = length, es:di = pointer to ethertype
  539. ;
  540. not_mineb:
  541.     pop    cx
  542.     push    cx
  543.     mov    di,offset ether_type
  544.     mov    ax,cs
  545.     mov    es,ax             ; es:di -> ether type, cx = size#bytes
  546.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  547.     mov    ax, es:[di]
  548.     xchg    ah, al
  549.     cmp     ax, 1500
  550.     ja    BlueBookPacket1
  551.     inc    di            ;set di to 802.2 header
  552.     inc    di
  553.     mov    dl, IEEE8023
  554. BlueBookPacket1:
  555.     call    recv_find                   ; got a buffer?
  556.     mov    ax,es
  557.     or    ax,di                       ; pointer zero?
  558.     je    byte_flush                  ; no pointer, discard data
  559. ;
  560. ;      es:di -> users buffer, do copy...
  561. ;      ds:si -> source of copy
  562. ;
  563.     mov    cs:[usr_ptr.segm],es    ; save ULP pointer
  564.     mov    cs:[usr_ptr.offs],di
  565.     mov    ax,cs
  566.     mov    ds,ax
  567.     mov    si,offset ether_buff        ; copy header to users buffer
  568.     mov    cx,16/2            ; 16 bytes in header to copy
  569.     rep    movsw
  570.     mov    dx,cs:io_adr     ; copy rest of data to users
  571.     add    dx,BMPR_MEM_PORT            ; buffer in es:di ->
  572.     pop    cx
  573.     push    cx
  574.     sub    cx,14
  575. cpyb:
  576.     in    al,dx            ; read byte
  577.     stosb                ; store at es:di ->
  578.     loop    cpyb
  579.     pop    cx            ; call recv_copy to say copy done
  580.     lds    si,cs:[usr_ptr]
  581.     call    recv_copy
  582.     jmp    recv_0            ; go get another packet...
  583. byte_flush:
  584.     mov    dx,cs:io_adr
  585.     add    dx,BMPR_MEM_PORT
  586.     pop    cx
  587.     sub    cx,16            ; adjust byte count header
  588. byte_f:
  589.     in    al,dx
  590.     loop    byte_f
  591.     jmp    recv_0            ; go to see if any more packets comming...
  592. recv_99:
  593. ;      receive ok, restore recive mask and exit
  594. ;
  595.     writebport    DLCR_RECV_MASK,en_rcv_irqs
  596.     ret
  597.  
  598.  
  599.     public    timer_isr
  600. timer_isr:
  601. ;if the first instruction is an iret, then the timer is not hooked
  602.     iret
  603.  
  604. ;any code after this will not be kept.  Buffers used by the program, if any,
  605. ;are allocated from the memory between end_resident and end_free_mem.
  606.     public end_resident,end_free_mem
  607. end_resident    label    byte
  608. end_free_mem    label    byte
  609.  
  610. io_adr_msg    db    "I/O Base Address: ",'$'
  611. int_no_msg    db    " Interrupt Level: ",'$'
  612.  
  613.     public  usage_msg
  614. usage_msg   db  "usage: EN301 [options] <packet_int_no> <hardware_irq> <io_addr>",CR,LF,'$'
  615.  
  616.     public  copyright_msg
  617. copyright_msg    label    byte
  618.  db CR,LF
  619.  db "EN301:   FTP Driver for Multi-Tech EN301, Version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version, CR,LF
  620.  db "         - for PC and PC-AT",CR,LF
  621.  db "portions - Copyright 1991 by Chris Elmquist and",CR,LF
  622.  db "           Copyright 1990, 1991 Queens University by Brian Fisher",CR,LF
  623.  db CR,LF,'$'
  624.  
  625.     extrn   set_recv_isr: near
  626. ;enter with si-> argument string,di->wword to store.
  627. ;if there is no number, don't change  the number.
  628.  
  629. ;enter with si -> argument string, di -> word to store.
  630. ;if there is no number, don't change the number.
  631.     extrn   get_number: near
  632.  
  633. ;enter with dx -> name of word, di -> dword to print.
  634.     extrn    print_number: near
  635.  
  636. ;-> the assigned Ethernet address of the card.
  637.     extrn    rom_address: byte
  638.  
  639. ;-> the current Ethernet address of the card.
  640.     extrn    my_address: byte
  641.  
  642.     public  parse_args
  643. parse_args:
  644.  
  645. ;      parse I/O base address and hardware interrupt number from the
  646. ;      command line.
  647. ;
  648.     mov    bx,offset int_no_msg    ; first comes the interrupt level
  649.     mov    di,offset int_no
  650.     call    get_number
  651.     jc    _parse_exit
  652.     mov    bx,offset io_adr_msg    ; then the I/O base address
  653.     mov    di,offset io_adr
  654.     call    get_number
  655. _parse_exit:
  656.     clc
  657.     ret
  658.  
  659. ; Clock the LSB of AX into the EEPROM (DI is inverted by the hardware)
  660. clkbit:
  661.     push    ax
  662.     port    EEDI_PORT
  663.     not    ax        ; invert data because of hardware
  664.     out    dx,al
  665.     mov    al,1        ; clock high
  666.     port    EECLK_PORT
  667.     out    dx,al
  668.     mov    al,0        ; clock low
  669.     out    dx,al
  670.     pop    ax
  671.     ret
  672.  
  673.     public etopen
  674. etopen:
  675.     assume    ds:code
  676. ;
  677. ;      Set Node ID:
  678. ;
  679.     writebport    EECS_PORT,1    ; CS high on 9346
  680.     mov    al,0
  681.     call    clkbit
  682.  
  683. ; clock the 6 byte (3 words) Ethernet address out of the EEPROM
  684.     mov    cx,3
  685.     mov    bx,0
  686. eegetadr1:
  687.     mov    al,1        ; READ opcode is '110'
  688.     call    clkbit
  689.     call    clkbit
  690.     mov    al,0
  691.     call    clkbit
  692.     mov    ax,bx
  693.     shr    ax,1
  694.  
  695. ; send the address in AX to EEPROM
  696.     push    cx
  697.     mov    cx,5
  698.     ror    ax,cl        ; move A5 to LSB
  699.     call    clkbit
  700. saddr1:    rol    ax,1        ; A4 to LSB, then A3, etc...
  701.     call    clkbit        ; LSB of AX gets clocked in
  702.     loop    saddr1
  703.  
  704. ; read the data from the currently addressed EEPROM cell
  705.     push    bx
  706.     mov    cx,16        ; set counter to read 16 bits of data
  707.     mov    bx,0
  708. rdd:    shl    bx,1
  709.     call    clkbit
  710.     readbport    EEDO_PORT
  711.     and    ax,1
  712.     or    bx,ax
  713.     loop    rdd
  714.     mov    al,bh
  715.     mov    ah,bl
  716.     pop    bx
  717.     pop    cx
  718.  
  719.     mov    word ptr rom_address[bx],ax
  720.     inc    bx
  721.     inc    bx
  722.  
  723. ; perform a standby operation after each read
  724.     writebport    EECS_PORT,0
  725.     call    clkbit
  726.     call    clkbit
  727.     writebport    EECS_PORT,1
  728.     loop    eegetadr1
  729.  
  730.     writebport    EECS_PORT,0    ; deselect the EEPROM and de-reset
  731.                     ; the Fujitsu
  732.  
  733.     writebport    DLCR_ENABLE,card_disable    ; disable etherstar
  734.     writebport    DLCR_XMIT_STAT,clear_status    ; clr xmit status
  735.     writebport    DLCR_XMIT_MASK,no_tx_irqs    ; disable xmit IRQ's
  736.     writebport    DLCR_RECV_STAT,clr_rcv_status    ; clear rcv status
  737.     writebport    DLCR_RECV_MASK,en_rcv_irqs    ; enable rcv IRQ's
  738.     writebport    DLCR_XMIT_MODE,xmit_mode    ; set xmit mode
  739.     writebport    DLCR_RECV_MODE,recv_mode    ; set receive mode
  740.  
  741.     mov    si,offset rom_address    ; write the node address
  742.     mov    cx,6            ; into the 86950 registers
  743.     port    DLCR_NODE_ID
  744. etopen1:
  745.     lodsb
  746.     out    dx,al
  747.     inc    dx
  748.     loop    etopen1
  749.  
  750.                                         ; repeat until BUF_EMPTY vacuum data port
  751.     mov    dx,cs:io_adr
  752.     mov    bx,dx
  753.     add    bx,DLCR_RECV_MODE
  754.     add    dx,BMPR_MEM_PORT
  755.     cmp    cs:is_186,0
  756.     je    vac_88
  757. vac_86:
  758.         in      ax,dx
  759.         xchg    dx,bx
  760.         in      ax,dx
  761.         xchg    dx,bx
  762.         test    al,BUF_EMPTY
  763.         jz      vac_86
  764.         jmp     short all_done
  765. vac_88:
  766.     in    al,dx
  767.         xchg    dx,bx
  768.         in      al,dx
  769.         xchg    dx,bx
  770.         test    al,BUF_EMPTY
  771.         jz      vac_88
  772. all_done:
  773.         writebport      DLCR_RECV_STAT,clr_rcv_status; clear possible underflow
  774.     writebport    DLCR_ENABLE,card_enable
  775.     call    set_recv_isr                ; install receive IRQ routine
  776.  
  777.     mov    al, int_no        ; Get board's interrupt vector
  778.     add    al, 8
  779.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  780.     jb    set_int_num        ; No.
  781.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  782. set_int_num:
  783.     xor    ah, ah            ; Clear high byte
  784.     mov    int_num, ax        ; Set parameter_list int num.
  785.  
  786.     clc                ; if all is okay,
  787.     ret
  788.  
  789.     public    print_parameters
  790. print_parameters:
  791. ;echo our command-line parameters
  792.     mov    di,offset int_no    ; interrupt level.
  793.     mov    dx,offset int_no_msg
  794.     call    print_number
  795.     mov    di,offset io_adr    ; now comes the I/O base address
  796.     mov    dx,offset io_adr_msg
  797.     call    print_number
  798.     ret
  799.  
  800. code    ends
  801.  
  802.     end
  803.