home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / drivrs30 / wd8003e.asm < prev    next >
Assembly Source File  |  1989-06-08  |  25KB  |  767 lines

  1. version    equ    2
  2.  
  3.     include    defs.asm
  4.  
  5. ;   PC/FTP Packet Driver source, conforming to version 1.05 of the spec
  6. ;   Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  7. ;   Robert C Clements, K1BC,  August 19, 1988
  8. ;   Portions (C) Copyright 1988 Robert C Clements
  9.  
  10. ;   This program is free software; you can redistribute it and/or modify
  11. ;   it under the terms of the GNU General Public License as published by
  12. ;   the Free Software Foundation, version 1.
  13. ;
  14. ;   This program is distributed in the hope that it will be useful,
  15. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. ;   GNU General Public License for more details.
  18. ;
  19. ;   You should have received a copy of the GNU General Public License
  20. ;   along with this program; if not, write to the Free Software
  21. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  
  23. code    segment    byte public
  24.     assume    cs:code, ds:code
  25.  
  26. HT    equ    09h
  27. CR    equ    0dh
  28. LF    equ    0ah
  29.  
  30. ;
  31. ;  Packet Driver Error numbers
  32. BAD_HANDLE    equ    1        ;invalid handle number
  33. NO_CLASS    equ    2        ;no interfaces of specified class found
  34. NO_TYPE        equ    3        ;no interfaces of specified type found
  35. NO_NUMBER    equ    4        ;no interfaces of specified number found
  36. BAD_TYPE    equ    5        ;bad packet type specified
  37. NO_MULTICAST    equ    6        ;this interface does not support
  38. CANT_TERMINATE    equ    7        ;this packet driver cannot terminate
  39. BAD_MODE    equ    8        ;an invalid receiver mode was specified
  40. NO_SPACE    equ    9        ;operation failed because of insufficient
  41. TYPE_INUSE    equ    10        ;the type had previously been accessed,
  42. BAD_COMMAND    equ    11        ;the command was out of range, or not
  43. CANT_SEND    equ    12        ;the packet couldn't be sent (usually
  44.  
  45. ; Stuff specific to the Western Digital WD003E Ethernet controller board
  46. ; C version by Bob Clements, K1BC, May 1988 for the KA9Q TCP/IP package
  47. ; Symbol prefix "EW" is for Ethernet, Western-digital card
  48.  
  49. ; The EW registers - First, the board registers */
  50.  
  51. EW_CMD        equ    000h    ; Board's command register
  52. EW_SAPROM    equ    008h    ; Window on station addr prom
  53.  
  54. ; The EW registers - Next, the DS8390 chip registers */
  55. ; There are two (really 3) pages of registers in the chip. You select
  56. ; which page you want, then address them at offsets 10-1F from base.
  57. ; The chip command register (EW_CCMD) appears in both pages.
  58.  
  59. EW_CCMD        equ    010h    ; Chip's command register
  60.  
  61. ; Page 0
  62.  
  63. EW0_STARTPG    equ    011h    ; Starting page of ring bfr
  64. EW0_STOPPG    equ    012h    ; Ending page +1 of ring bfr
  65. EW0_BOUNDARY    equ    013h    ; Boundary page of ring bfr
  66. EW0_TSR        equ    014h    ; Transmit status reg
  67. EW0_TPSR    equ    014h    ; Transmit starting page
  68. EW0_TCNTLO    equ    015h    ; Low  byte of tx byte count
  69. EW0_TCNTHI    equ    016h    ; High byte of tx byte count
  70. EW0_ISR        equ    017h    ; Interrupt status reg
  71. EW0_RCNTLO    equ    01ah    ; Remote byte count reg
  72. EW0_RCNTHI    equ    01bh    ; Remote byte count reg
  73. EW0_RXCR    equ    01ch    ; RX control reg
  74. EW0_TXCR    equ    01dh    ; TX control reg
  75. EW0_COUNTER0    equ    01dh    ; Rcv alignment error counter
  76. EW0_DCFG    equ    01eh    ; Data configuration reg
  77. EW0_COUNTER1    equ    01eh    ; Rcv CRC error counter
  78. EW0_IMR        equ    01fh    ; Interrupt mask reg
  79. EW0_COUNTER2    equ    01fh    ; Rcv missed frame error counter
  80.  
  81. ; Page 1
  82.  
  83. EW1_PHYS    equ    011h    ; This board's physical enet addr
  84. EW1_CURPAG    equ    017h    ; Current memory page
  85. EW1_MULT    equ    018h    ; Desired multicast addr
  86.  
  87.  
  88. ; Board commands in EW_CMD
  89. EW_RESET    equ    080h    ; Reset the board
  90. EW_MEMEN    equ    040h    ; Enable the shared memory
  91. EW_MEM_MASK    equ    03fh    ; B18-B13 of address of the shared memory
  92.  
  93. ; Chip commands in EW_CCMD
  94. EWC_STOP    equ    001h    ; Stop the chip
  95. EWC_START    equ    002h    ; Start the chip
  96. EWC_TRANS    equ    004h    ; Transmit a frame
  97. EWC_NODMA    equ    020h    ; No remote DMA used on this card
  98. EWC_PAGE0    equ    000h    ; Select page 0 of chip registers
  99. EWC_PAGE1    equ    040h    ; Select page 1 of chip registers
  100.  
  101. ; Commands for RX control reg
  102. EWRXCR_MON    equ    020h    ; Monitor mode
  103. EWRXCR_BCST    equ    004h    ; Accept broadcasts
  104.  
  105. ; Commands for TX control reg
  106. EWTXCR_LOOP    equ    002h    ; Set loopback mode
  107.  
  108. ; Bits in EW0_DCFG - Data config register
  109. EWDCFG_BM8    equ    048h    ; Set burst mode, 8 deep FIFO
  110.  
  111. ; Bits in EW0_ISR - Interrupt status register
  112. EWISR_RX    equ    001h    ; Receiver, no error
  113. EWISR_TX    equ    002h    ; Transmitter, no error
  114. EWISR_RX_ERR    equ    004h    ; Receiver, with error
  115. EWISR_TX_ERR    equ    008h    ;    Transmitter, with error
  116. EWISR_OVER    equ    010h    ; Receiver overwrote the ring
  117. EWISR_COUNTERS    equ    020h    ; Counters need emptying
  118. EWISR_RESET    equ    080h    ; Reset completed
  119. EWISR_ALL    equ    03fh    ; Interrupts we will enable
  120.  
  121. ; Bits in received packet status byte and EW0_RSR
  122. EWPS_RXOK    equ    001h    ; Received a good packet
  123.  
  124. ; Bits in TX status reg
  125.  
  126. EWTSR_COLL    equ    004h    ; Collided at least once
  127. EWTSR_COLL16    equ    008h    ; Collided 16 times and was dropped
  128. EWTSR_FU    equ    020h    ; TX FIFO Underrun
  129.  
  130. ; Shared memory management parameters
  131.  
  132. XMIT_MTU    equ    600h    ; Largest packet we have room for.
  133. SM_TSTART_PG    equ    0    ; First page of TX buffer
  134. SM_RSTART_PG    equ    6    ; Starting page of ring
  135. SM_RSTOP_PG    equ    32    ; Last page +1 of ring
  136. SM_BASE        equ    0C400h    ; Default para where shared memory starts
  137.                 ; Real value set at attach time.
  138.  
  139. ; Description of header of each packet in receive area of shared memory
  140.  
  141. EW_RBUF_STAT    equ    0    ; Received frame status
  142. EW_RBUF_NXT_PG    equ    1    ; Page after this frame
  143. EW_RBUF_SIZE_LO    equ    2    ; Length of this frame
  144. EW_RBUF_SIZE_HI    equ    3    ; Length of this frame
  145. EW_RBUF_NHDR    equ    4    ; Length of above header area
  146.  
  147. ; End of WD8003E parameter definitions
  148.  
  149. ; The following three values may be overridden from the command line.
  150. ; If they are omitted from the command line, these defaults are used.
  151.  
  152.     public    int_no, io_addr, mem_base
  153. int_no        db    2,0,0,0        ; Interrupt level
  154. io_addr        dw    0280h,0        ; I/O address for card (jumpers)
  155. mem_base    dw    0c400h,0    ; Shared memory addr (software)
  156.  
  157.     public    driver_class, driver_type, driver_name
  158. driver_class    db    1        ;from the packet spec
  159. driver_type    db    14        ;from the packet spec
  160. driver_name    db    'WD8003E',0    ;name of the driver.
  161.  
  162.  
  163. ; send_pkt: - The Transmit Frame routine
  164.  
  165.     public    send_pkt
  166. send_pkt:
  167. ;enter with ds:si -> packet, cx = packet length.
  168. ;exit with nc if ok, or else cy if error, dh set to error number.
  169.     assume    ds:nothing
  170.     loadport        ; Point at chip command register
  171.     setport EW_CCMD        ; ..
  172. tx_wait:
  173.     mov bx,    8000h        ; Avoid infinite loop
  174.     in al,    dx        ; Get chip command state
  175.     test al,EWC_TRANS    ; Is transmitter still running?
  176.     jz    tx_idle        ; Go if free
  177.     dec    bx        ; Count the timeout
  178.     jnz    tx_wait        ; Fall thru if TX is stuck
  179.                 ; Should count these error timeouts
  180.                 ; Maybe need to add recovery logic here
  181. tx_idle:
  182.     cmp    cx,XMIT_MTU    ; Is this packet too large?
  183.     ja    send_pkt_toobig
  184.  
  185.     cmp cx,    RUNT        ; Is the frame long enough?
  186.     jnb    tx_oklen    ; Go if OK
  187.     mov cx,    RUNT        ; Stretch frame to minimum allowed
  188. tx_oklen:
  189.     push    cx        ; Hold count for later
  190.                 ; Now compute destination of move in es:di
  191.     mov ax,    mem_base    ; Compute base of transmit buffer
  192. ;    add ax,    SM_TSTART_PG*16    ; The right page in mem (currently zero)
  193.     mov es,    ax        ; Paragraph of the TX buffer
  194.     xor di,    di        ; Fill starting at beginning of paragraph
  195.  
  196.     call    movemem
  197.  
  198.     pop    cx        ; Get back count to give to board
  199.     loadport        ; Base of I/O regs
  200.     setport    EW0_TCNTLO    ; Low byte of TX count
  201.     mov al,    cl        ; Get the count
  202.     out dx,    al        ; Tell card the count
  203.     setport    EW0_TCNTHI    ; High byte of TX count
  204.     mov al,    ch        ; Get the count
  205.     out dx,    al        ; Tell card the count
  206.     setport    EW0_TPSR    ; Transmit Page Start Register
  207.     mov al,    SM_TSTART_PG
  208.     out dx,    al        ; Start the transmitter
  209.     setport    EW_CCMD        ; Chip command reg
  210.     mov al,    EWC_TRANS+EWC_NODMA
  211.     out dx,    al        ; Start the transmitter
  212.  
  213.     clc
  214.     ret            ; End of transmit-start routine
  215. send_pkt_toobig:
  216.     mov    dh,NO_SPACE
  217.     stc
  218.     ret
  219.  
  220.  
  221. movemem:
  222. ;does the same thing as "rep movsb", only 50% faster.
  223. ;moves words instead of bytes, and handles the case of both addresses odd
  224. ;efficiently.  There is no way to handle one address odd efficiently.
  225. ;This routine always aligns the source address in the hopes that the
  226. ;destination address will also get aligned.  This is from Phil Karn's
  227. ;code from ec.c, a part of his NET package.  I bummed a few instructions
  228. ;out.
  229.     jcxz    movemem_cnte        ; If zero, we're done already.
  230.     test    si,1            ; Does source start on odd byte?
  231.     jz    movemem_adre        ; Go if not
  232.     movsb                ; Yes, move the first byte
  233.     dec    cx            ; Count that byte
  234. movemem_adre:
  235.     shr    cx,1            ; convert to word count
  236.     rep    movsw            ; Move the bulk as words
  237.     jnc    movemem_cnte        ; Go if the count was even
  238.     movsb                ; Move leftover last byte
  239. movemem_cnte:
  240.     ret
  241.  
  242.  
  243.     public    get_address
  244. get_address:
  245. ;get the address of the interface.
  246. ;enter with es:di -> place to get the address, cx = size of address buffer.
  247. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  248.     assume ds:code
  249.     cmp cx,    EADDR_LEN    ; Caller wants a reasonable length?
  250.     jb    get_addr_x    ; No, fail.
  251.     mov cx,    EADDR_LEN    ; Yes. Set count for loop
  252.     loadport        ; Base of device
  253.     setport    EW_SAPROM    ; Where the address prom is
  254.     cld            ; Make sure string mode is right
  255. get_addr_loop:
  256.     in al,    dx        ; Get a byte of address
  257.     stosb            ; Feed it to caller
  258.     inc    dx        ; Next byte at next I/O port
  259.     loop    get_addr_loop    ; Loop over six bytes
  260.     mov cx,    EADDR_LEN    ; Tell caller how many bytes we fed him
  261.     clc            ; Carry off says success
  262.     ret
  263. get_addr_x:
  264.     stc            ; Tell caller our addr is too big for him
  265.     ret
  266.  
  267.  
  268.     public    set_address
  269. set_address:
  270.     assume    ds:nothing
  271. ;enter with ds:si -> Ethernet address, CX = length of address.
  272. ;exit with nc if okay, or cy, dh=error if any errors.
  273. ;
  274.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  275.     je    set_address_4
  276.     mov    dh,BAD_ADDRESS
  277.     stc
  278.     jmp    short set_address_done
  279. set_address_4:
  280.  
  281.     loadport
  282.     setport    EW1_PHYS
  283. set_address_1:
  284.     lodsb
  285.     out    dx,al
  286.     inc    dx
  287.     loop    set_address_1
  288.  
  289. set_address_okay:
  290.     clc
  291. set_address_done:
  292.     push    cs
  293.     pop    ds
  294.     assume    ds:code
  295.     ret
  296.  
  297.  
  298.     public    reset_interface
  299. reset_interface:
  300.     assume ds:code
  301.     loadport        ; Base of I/O regs
  302.     setport    EW_CCMD        ; Chip command reg
  303.     mov al,    EWC_STOP+EWC_NODMA
  304.     out dx,    al        ; Stop the DS8390
  305.     setport    EW0_ISR        ; Interrupt status reg
  306.     mov al,    0ffh        ; Clear all pending interrupts
  307.     out dx,    al        ; ..
  308.     setport    EW0_IMR        ; Interrupt mask reg
  309.     xor al,    al        ; Turn off all enables
  310.     out dx,    al        ; ..
  311.     ret
  312.  
  313.  
  314. ;called when we want to determine what to do with a received packet.
  315. ;enter with cx = packet length, es:di -> packet type.
  316. ;It returns with es:di = 0 if don't want this type or if no buffer available.
  317.     extrn    recv_find: near
  318.  
  319. ;called after we have copied the packet into the buffer.
  320. ;enter with ds:si ->the packet, cx = length of the packet.
  321.     extrn    recv_copy: near
  322.  
  323.     extrn    count_in_err: near
  324.     extrn    count_out_err: near
  325.  
  326.     public    recv
  327. recv:
  328. ;called from the recv isr.  All registers have been saved, and ds=cs.
  329. ;Actually, not just receive, but all interrupts come here.
  330. ;Upon exit, the interrupt will be acknowledged.
  331.  
  332.     assume    ds:code
  333. check_isr:            ; Was there an interrupt from this card?
  334.     loadport        ; Point at interrupt status register
  335.     setport    EW0_ISR        ; ..
  336.     in al,    dx        ; Get pending interrupts
  337.     and al,    EWISR_ALL    ; Any?
  338.     jnz    isr_test_overrun
  339.     jmp    interrupt_done    ; Go if none
  340. ; First, a messy procedure for handling the case where the rcvr
  341. ; over-runs its ring buffer.  This is spec'ed by National for the chip.
  342. isr_test_overrun: 
  343.     test al,EWISR_OVER    ; Was there an overrun?
  344.     jnz    recv_overrun    ; Go if so.
  345.     jmp    recv_no_overrun    ; Go if not.
  346. recv_overrun:
  347.     setport    EW_CCMD        ; Stop the card
  348.     mov al,    EWC_STOP+EWC_NODMA
  349.     out dx,    al        ; Write "stop" to command register
  350.  
  351. ; Remove one frame from the ring
  352.     setport    EW0_BOUNDARY    ; Find end of this frame
  353.     in al,    dx        ; Get memory page number
  354.     inc    al        ; Page plus 1
  355.     cmp al,    SM_RSTOP_PG    ; Wrapped around ring?
  356.     jnz    rcv_ovr_nwrap    ; Go if not
  357.     mov al,    SM_RSTART_PG    ; Yes, wrap the page pointer
  358. rcv_ovr_nwrap:
  359.     xor ah,    ah        ; Convert page to segment
  360.     mov cl,    4
  361.     mov bl,    al        ; Page number as arg to rcv_frm
  362.     shl ax,    cl        ; ..
  363.     add ax,    mem_base    ; Page in this memory
  364.     mov es,    ax        ; Segment pointer to the frame header
  365.     push    es        ; Hold this frame pointer for later
  366.     mov al,    es:[EW_RBUF_STAT]    ; Get the buffer status byte
  367.     test al,EWPS_RXOK    ; Is this frame any good?
  368.     jz    rcv_ovr_ng    ; Skip if not
  369.      call    rcv_frm        ; Yes, go accept it
  370. rcv_ovr_ng:
  371.     pop    es        ; Back to start of this frame
  372.     mov al,    es:[EW_RBUF_NXT_PG]    ; Get pointer to next frame
  373.     dec    al        ; Back up one page
  374.     cmp al,    SM_RSTART_PG    ; Did it wrap?
  375.     jge    rcv_ovr_nwr2
  376.     mov al,    SM_RSTOP_PG-1    ; Yes, back to end of ring
  377. rcv_ovr_nwr2:
  378.     loadport        ; Point at boundary reg
  379.     setport    EW0_BOUNDARY    ; ..
  380.     out dx,    al        ; Set the boundary
  381.     setport    EW0_RCNTLO    ; Point at byte count regs
  382.     xor al,    al        ; Clear them
  383.     out dx,    al        ; ..
  384.     setport    EW0_RCNTHI
  385.     out dx,    al
  386.     setport    EW0_ISR        ; Point at status reg
  387.     mov cx,    8000h        ; Timeout counter
  388. rcv_ovr_rst_loop:
  389.     in al,    dx        ; Is it finished resetting?
  390.     test al,EWISR_RESET    ; ..
  391.     jnz    rcv_ovr_rst    ; Go if so
  392.     dec    cx        ; Loop til reset, or til timeout
  393.     jnz    rcv_ovr_rst_loop
  394. rcv_ovr_rst:
  395.     loadport        ; Point at Transmit control reg
  396.      setport    EW0_TXCR    ; ..
  397.     mov al,    EWTXCR_LOOP    ; Put transmitter in loopback mode
  398.     out dx,    al        ; ..
  399.     setport    EW_CCMD        ; Point at Chip command reg
  400.     mov al,    EWC_START+EWC_NODMA
  401.     out dx,    al        ; Start the chip running again
  402.     setport    EW0_TXCR    ; Back to TX control reg
  403.     xor al,    al        ; Clear the loopback bit
  404.     out dx,    al        ; ..
  405.     setport    EW0_ISR        ; Point at Interrupt status register
  406.     mov al,    EWISR_OVER    ; Clear the overrun interrupt bit
  407.     out dx,    al        ; ..
  408.     call    count_in_err    ; Count the anomaly
  409.      jmp    check_isr    ; Done with the overrun case
  410.  
  411. recv_no_overrun:
  412. ; Handle receive flags, normal and with error (but not overrun).
  413.     test al,EWISR_RX+EWISR_RX_ERR    ; Frame received without overrun?
  414.     jnz    recv_frame    ; Go if so.
  415.     jmp    recv_no_frame    ; Go if not.
  416. recv_frame:
  417.     loadport        ; Point at Chip's Command Reg
  418.      setport    EW_CCMD        ; ..
  419.     mov al,    EWC_NODMA+EWC_PAGE1
  420.     out dx,    al        ; Switch to page 1 registers
  421.     setport    EW1_CURPAG    ;Get current page of rcv ring
  422.     in al,    dx        ; ..
  423.     mov ah,    al        ; Hold current page in AH
  424.      setport    EW_CCMD        ; Back to page zero registers
  425.     mov al,    EWC_NODMA+EWC_PAGE0
  426.     out dx,    al        ; Switch back to page 0 registers
  427.     setport    EW0_BOUNDARY    ;Get boundary page
  428.     in al,    dx        ; ..
  429.     inc    al        ; Step boundary from last used page
  430.     cmp al,    SM_RSTOP_PG    ; Wrap if needed
  431.     jne    rx_nwrap3    ; Go if not
  432.     mov al,    SM_RSTART_PG    ; Wrap to first RX page
  433. rx_nwrap3:
  434.     cmp al,    ah        ; Read all the frames?
  435.     je    recv_frame_break    ; Finished them all
  436.     mov bl,    al        ; Page number as arg to rcv_frm
  437.     xor ah,    ah        ; Make segment pointer to this frame
  438.     mov cl,    4        ; 16 * pages = paragraphs
  439.     shl ax,    cl        ; ..
  440.     add ax,    mem_base    ; That far into shared memory
  441.     mov es,    ax        ; Segment part of pointer
  442.     push    es        ; Hold on to this pointer for later
  443.     mov al,    es:[EW_RBUF_STAT]    ; Get the buffer status byte
  444.     test al,EWPS_RXOK    ; Good frame?
  445.     jz    recv_no_rcv
  446.     call    rcv_frm        ; Yes, go accept it
  447. recv_no_rcv:
  448.     pop    es        ; Back to base of frame
  449.     mov al,    es:[EW_RBUF_NXT_PG]    ; Start of next frame
  450.     dec    al        ; Make previous page for new boundary
  451.     cmp al,    SM_RSTART_PG    ; Wrap around the bottom?
  452.     jge    rcv_nwrap4
  453.     mov al,    SM_RSTOP_PG-1    ; Yes
  454. rcv_nwrap4:
  455.     loadport        ; Point at the Boundary Reg again
  456.      setport    EW0_BOUNDARY    ; ..
  457.     out dx,    al        ; Set new boundary
  458.     jmp    recv_frame    ; See if any more frames
  459.  
  460. recv_frame_break:
  461.     loadport        ; Point at Interrupt Status Reg
  462.      setport    EW0_ISR        ; ..
  463.     mov al,    EWISR_RX+EWISR_RX_ERR+EWISR_OVER
  464.     out dx,    al        ; Clear those requests
  465.     jmp    check_isr    ; See if any other interrupts pending
  466.  
  467. recv_no_frame:                ; Handle transmit flags.
  468.     test al,EWISR_TX+EWISR_TX_ERR    ; Frame transmitted?
  469.     jnz    isr_tx        ; Go if so.
  470.     jmp    isr_no_tx    ; Go if not.
  471. isr_tx:
  472.     mov ah,    al        ; Hold interrupt status bits
  473.     loadport        ; Point at Transmit Status Reg
  474.      setport    EW0_TSR        ; ..
  475.     in al,    dx        ; ..
  476.     test ah,EWISR_TX    ; Non-error TX?
  477.     jz    isr_tx_err    ; No, do TX error completion
  478.     test al,EWTSR_COLL16    ; Jammed for 16 transmit tries?
  479.     jz    isr_tx_njam    ; Go if not
  480.     call    count_out_err    ; Yes, count those
  481. isr_tx_njam:
  482.     setport    EW0_ISR        ; Clear the TX complete flag
  483.     mov al,    EWISR_TX    ; ..
  484.     out dx,    al        ; ..    
  485.     jmp    isr_tx_done
  486. isr_tx_err:
  487.     test al,EWTSR_FU    ; FIFO Underrun?
  488.     jz    isr_txerr_nfu
  489.     call    count_out_err    ; Yes, count those
  490. isr_txerr_nfu:
  491.     loadport        ; Clear the TX error completion flag
  492.     setport    EW0_ISR        ; ..
  493.     mov al,    EWISR_TX_ERR    ; ..
  494.     out dx,    al        ; ..    
  495. isr_tx_done:
  496. ; If TX queue and/or TX shared memory ring buffer were being
  497. ; used, logic to step through them would go here.  However,
  498. ; in this version, we just clear the flags for background to notice.
  499.  
  500.      jmp    check_isr    ; See if any other interrupts on
  501.  
  502. isr_no_tx:
  503. ; Now check to see if any counters are getting full
  504.     test al,EWISR_COUNTERS    ; Interrupt to handle counters?
  505.     jnz    isr_stat    ; Go if so.
  506.     jmp    isr_no_stat    ; Go if not.
  507. isr_stat:
  508. ; We have to read the counters to clear them and to clear the interrupt.
  509. ; The structure of the PC/FTP driver system doesn't give us
  510. ; anything useful to do with the data, though.
  511.     loadport        ; Point at first counter
  512.      setport    EW0_COUNTER0    ; ..
  513.     in al,    dx        ; Read the count, ignore it.
  514.     setport    EW0_COUNTER1
  515.     in al,    dx        ; Read the count, ignore it.
  516.     setport    EW0_COUNTER2
  517.     in al,    dx        ; Read the count, ignore it.
  518.     setport    EW0_ISR        ; Clear the statistics completion flag
  519.     mov al,    EWISR_COUNTERS    ; ..
  520.     out dx,    al        ; ..
  521. isr_no_stat:
  522.      jmp    check_isr    ; Anything else to do?
  523.  
  524. interrupt_done:
  525.     ret
  526.  
  527. ; Do the work of copying out a receive frame.
  528. ; Called with bl/ the page number of the frame header in shared memory/
  529. ; Also, es/ the paragraph number of that page.
  530.  
  531. rcv_frm:
  532. ; Old version checked size, memory space, queue length here. Now done
  533. ; in higher level code.
  534. ; Set cx to length of this frame.
  535.     mov ch,    es:[EW_RBUF_SIZE_HI]    ; Extract size of frame
  536.     mov cl,    es:[EW_RBUF_SIZE_LO]    ; Extract size of frame
  537.     sub cx,    EW_RBUF_NHDR        ; Less the header stuff
  538. ; Set es:di to point to Ethernet type field.  es is already at base of
  539. ; page where this frame starts.  Set di after the header and two addresses.
  540.     mov di,    EW_RBUF_NHDR+EADDR_LEN+EADDR_LEN
  541.     push    bx            ; Save page number in bl
  542.     push    cx            ; Save frame size
  543.     push    es
  544.     mov ax,    cs            ; Set ds = code
  545.     mov ds,    ax
  546.     assume    ds:code
  547.     call    recv_find        ; See if type and size are wanted
  548.     pop    ds            ; RX page pointer in ds now
  549.     assume    ds:nothing
  550.     pop    cx
  551.     pop    bx
  552.     cld            ; Copies below are forward, please
  553.     mov ax,    es        ; Did recv_find give us a null pointer?
  554.     or ax,    di        ; ..
  555.     je    rcv_no_copy    ; If null, don't copy the data    
  556.  
  557.     push    cx        ; We will want the count and pointer
  558.     push    es        ;  to hand to client after copying,
  559.     push    di        ;  so save them at this point
  560.  
  561. ;; if ( (((size + 255 + EW_RBUF_NHDR) >> 8) + pg) > SM_RSTOP_PG){
  562.     mov ax,    cx        ; Length of frame
  563.     add ax,    EW_RBUF_NHDR+255 ; Including the overhead bytes, rounded up
  564.     add ah,    bl        ; Compute page with last byte of data in ah
  565.     cmp ah,    SM_RSTOP_PG    ; Over the top of the ring?
  566.     jg    rcopy_wrap    ; Yes, move in two pieces
  567.     mov si,    EW_RBUF_NHDR    ; One piece, starts here in first page (in ds)
  568.     jmp    rcopy_one_piece    ; Go move it
  569.  
  570. rcopy_wrap:
  571. ;; Copy in two pieces due to buffer wraparound. */
  572. ;; n = ((SM_RSTOP_PG - pg) << 8) - EW_RBUF_NHDR;    /* To top of mem */
  573.     mov ah,    SM_RSTOP_PG    ; Compute length of first part
  574.     sub ah,    bl        ;  as all of the pages up to wrap point
  575.     xor al,    al        ; 16-bit count
  576.     sub ax,    EW_RBUF_NHDR    ; Less the four overhead bytes
  577.     sub cx,    ax        ; Move the rest in second part
  578.     push    cx        ; Save count of second part
  579.     mov cx,    ax        ; Count for first move
  580.     mov si,    EW_RBUF_NHDR    ; ds:si points at first byte to move
  581.     shr cx,    1        ; All above are even numbers, do words.
  582.     rep    movsw        ; Move first part of frame
  583.     mov ax,    mem_base    ; Paragraph of base of shared memory
  584.     mov ds,    ax        ; ..
  585.     mov si,    SM_RSTART_PG*256  ; Offset to start of first receive page
  586.     pop    cx        ; Bytes left to move
  587. rcopy_one_piece:
  588.     call    movemem
  589.     pop    si        ; Recover pointer to destination
  590.     pop    ds        ; Tell client it's his source
  591.     pop    cx        ; And it's this long
  592.     assume    ds:nothing
  593.     call    recv_copy    ; Give it to him
  594. rcv_no_copy:
  595.     push    cs        ; Put ds back in code space
  596.     pop    ds        ; ..
  597.     assume    ds:code
  598.     ret            ; That's it for rcv_frm
  599.  
  600.  
  601. ;any code after this will not be kept after initialization.
  602. end_resident    label    byte
  603.  
  604.  
  605.     public    usage_msg
  606. usage_msg    db    "usage: WD8003E <packet_int_no> <int_level> <io_addr> <mem_base>",CR,LF,'$'
  607.  
  608.     public    copyright_msg
  609. copyright_msg    db    "Packet driver for Western Digital WD8003E, version ",'0'+majver,".",'0'+version,CR,LF
  610.         db    "Portions Copyright 1988, Robert C. Clements, K1BC",CR,LF,'$'
  611.  
  612. no_board_msg:
  613.     db    "WD8003E apparently not present at this address.",CR,LF,'$'
  614. int_no_name    db    "Interrupt number ",'$'
  615. io_addr_name    db    "I/O port ",'$'
  616. mem_base_name    db    "Memory address ",'$'
  617.  
  618.     extrn    set_recv_isr: near
  619.  
  620. ;enter with si -> argument string, di -> word to store.
  621. ;if there is no number, don't change the number.
  622.     extrn    get_number: near
  623.  
  624.     public    parse_args
  625. parse_args:
  626.     mov    di,offset int_no
  627.     mov    bx,offset int_no_name
  628.     call    get_number
  629.     mov    di,offset io_addr
  630.     mov    bx,offset io_addr_name
  631.     call    get_number
  632.     mov    di,offset mem_base
  633.     mov    bx,offset mem_base_name
  634.     call    get_number
  635.     ret
  636.  
  637.  
  638. bad_cksum:
  639.     mov    dx,offset no_board_msg
  640.     mov    ah,9
  641.     int    21h
  642.     stc
  643.     ret
  644.  
  645.  
  646.     public    etopen
  647. etopen:                ; Initialize interface
  648.     loadport        ; First, pulse the board reset
  649.     setport    EW_CMD
  650.     mov al,    EW_RESET
  651.     out dx,    al        ; Turn on board reset bit
  652.     xor al,    al
  653.     out dx,    al        ; Turn off board reset bit
  654.     setport    EW_CCMD        ; DS8390 chip's command register
  655.     mov al,    EWC_NODMA+EWC_PAGE0    
  656.     out dx,    al        ; Switch to page zero
  657.     setport    EW0_ISR        ; Clear all interrupt flags
  658.     mov al,    0ffh        ; ..
  659.     out dx,    al        ; ..
  660. ; Copy our Ethernet address from PROM into the DS8390
  661. ; (No provision in driver spec for setting a false address.)
  662.     setport    EW_CCMD        ; Chip command register
  663.     mov al,    EWC_NODMA+EWC_PAGE1
  664.     out dx,    al        ; Switch to page one for writing eaddr
  665.     mov cl,    EADDR_LEN    ; Loop for six bytes
  666.     xor ch,    ch        ; Clear the index of bytes
  667.     xor bx,    bx        ; Clear the addr ROM checksum
  668. cpy_adr_loop:
  669.     loadport        ; Base of registers
  670.     setport    EW_SAPROM    ; Prom address
  671.     add dl,    ch        ; Plus which byte this is
  672.     in al,    dx        ; Get a byte of address
  673.     add    bl,al        ; Compute the checksum
  674.     add dl,    EW1_PHYS-EW_SAPROM ; Point at reg in chip
  675.     out dx,    al        ; Copy that byte
  676.     inc    ch        ; Step the index
  677.     dec    cl        ; Count bytes
  678.     jnz    cpy_adr_loop    ; Loop for six
  679.     loadport        ; Get last two bytes into cksum
  680.     setport    EW_SAPROM+EADDR_LEN
  681.     in al,    dx        ; Get seventh byte
  682.     add bl,    al        ; Add it in
  683.     inc    dx        ; Step to eighth byte
  684.     in al,    dx        ; Get last byte
  685.     add bl,    al        ; Final checksum
  686.     cmp bl, 0ffh        ; Correct?
  687.     jnz    bad_cksum    ; No, board is not happy
  688. ; Clear the multicast filter enables, we don't want any of them.
  689.     mov cl,    8        ; Eight bytes of multicast filter
  690.     xor al,    al        ; Zeros for filter
  691.     loadport        ; Base of multicast filter locations
  692.     setport    EW1_MULT    ; ..
  693. clr_mcast_l:
  694.     out dx,    al        ; Clear a byte
  695.     inc    dl        ; Step to next one
  696.     dec    cl        ; Count 8 filter locs
  697.     jnz    clr_mcast_l    ; ..    
  698.     loadport        ; Base of I/O regs
  699.     setport    EW_CCMD        ; Chip command register
  700.     mov al,    EWC_NODMA+EWC_PAGE0
  701.     out dx,    al        ; Back to page zero
  702.     setport    EW0_DCFG    ; Configure the fifo organization
  703.     mov al,    EWDCFG_BM8    ; Fifo threshold = 8 bytes
  704.     out dx,    al
  705.     setport    EW0_RCNTLO    ; Clear the byte count registers
  706.     xor al,    al        ; ..
  707.     out dx,    al
  708.     setport    EW0_RCNTHI
  709.     out dx,    al        ; Clear high byte, too
  710.     setport    EW0_RXCR    ; Set receiver to monitor mode
  711.     mov al,    EWRXCR_MON
  712.     out dx,    al
  713.     setport    EW0_TXCR    ; Set transmitter mode to normal
  714.     xor al,    al
  715.     out dx,    al
  716. ; Turn on the shared memory block
  717.     setport    EW_CMD        ; Point at board command register
  718.     mov ax,    mem_base    ; Find where shared memory will be mapped
  719.     mov al,    ah        ; Shift to right location
  720.     sar al,    1        ;  in the map control word
  721.     and al,    EW_MEM_MASK    ; Just these bits
  722.     or al,    EW_MEMEN    ; Command to turn on map
  723.     out dx,    al        ; Create that memory
  724. ; Set up control of shared memory, buffer ring, etc.
  725.     setport    EW0_STARTPG    ; Set receiver's first buffer page
  726.     mov al,    SM_RSTART_PG
  727.     out dx,    al
  728.     setport    EW0_STOPPG    ;  and receiver's last buffer page + 1
  729.     mov al,    SM_RSTOP_PG
  730.     out dx,    al
  731.     setport    EW0_BOUNDARY    ; Set initial "last page we have emptied"
  732.     mov al,    SM_RSTART_PG
  733.     out dx,    al
  734.     setport    EW_CCMD        ; Switch to page one registers
  735.     mov al,    EWC_NODMA+EWC_PAGE1
  736.     out dx,    al
  737.     setport    EW1_CURPAG    ; Set current shared page for RX to work on
  738.     mov al,    SM_RSTART_PG+1
  739.     out dx,    al
  740.     setport    EW_CCMD        ; Switch back to page zero registers
  741.     mov al,    EWC_NODMA+EWC_PAGE0
  742.     out dx,    al
  743.     setport    EW0_IMR        ; Clear all interrupt enable flags
  744.     xor al,    al
  745.     out dx,    al
  746.     setport    EW0_ISR        ; Clear all interrupt assertion flags
  747.     mov al,    0ffh        ; again for safety before making the
  748.     out dx,    al        ; interrupt be enabled
  749.     call    set_recv_isr    ; Put ourselves in interrupt chain
  750.     loadport
  751.     setport    EW_CCMD        ; Now start the DS8390
  752.     mov al,    EWC_START+EWC_NODMA
  753.     out dx,    al        ; interrupt be enabled
  754.     setport    EW0_RXCR    ; Tell it to accept broadcasts
  755.     mov al,    EWRXCR_BCST
  756.     out dx,    al
  757.     setport    EW0_IMR        ; Tell card it can cause these interrupts
  758.     mov al,    EWISR_ALL
  759.     out dx,    al
  760.     mov    dx,offset end_resident
  761.     clc
  762.     ret
  763.  
  764. code    ends
  765.  
  766.     end
  767.