home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / asm / driver6s / 82586.asm < prev    next >
Encoding:
Assembly Source File  |  1990-04-13  |  23.1 KB  |  923 lines

  1. i82586_version    equ    1
  2. DAN    equ    1
  3.  
  4. ;
  5. ; Code that is common between 82586 implementations.
  6. ;
  7.  
  8. ; Ported from Tim Krauskopf's micnet.asm, an assembly language
  9. ; driver for the MICOM-Interlan NI5210, by Russell Nelson.  Any bugs
  10. ; are due to Russell Nelson.
  11. ; Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  12. ; Updated to support 1500 byte MTU April 27, 1989 By Brad Clements.
  13.  
  14. ; Copyright, 1988, 1989, Russell Nelson
  15.  
  16. ;   This program is free software; you can redistribute it and/or modify
  17. ;   it under the terms of the GNU General Public License as published by
  18. ;   the Free Software Foundation, version 1.
  19. ;
  20. ;   This program is distributed in the hope that it will be useful,
  21. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23. ;   GNU General Public License for more details.
  24. ;
  25. ;   You should have received a copy of the GNU General Public License
  26. ;   along with this program; if not, write to the Free Software
  27. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  28.  
  29. ;
  30. ;  Structure elements specific to the Intel 82586 chip
  31. ;
  32. BUF_COUNT EQU    28            ; number of buffers
  33. XMIT_MTU EQU    1500+14            ; size of xmit buffer (1500 MTU +
  34.                     ;   14 bytes for Ethernet headers
  35.  
  36. SCB    EQU    BASE_OFFSET + 10    ; system control block base
  37. CCBPTR    EQU    BASE_OFFSET + 26    ; offset of configure command block
  38. TCBPTR    EQU    BASE_OFFSET + 44    ; xmit CB offset
  39. TBDPTR    EQU    BASE_OFFSET + 60    ; xmit BD offset
  40. TBUFPTR    EQU    BASE_OFFSET + 68    ; xmit buffer offset
  41. FDBASE    EQU    TBUFPTR+XMIT_MTU    ; base addr for 30 frame descriptors
  42. FDSIZE  EQU     BUF_COUNT * 22
  43. BDBASE    EQU    FDBASE+FDSIZE        ; base address for 30 buffer descriptors
  44. BDASIZE    EQU     BUF_COUNT * 10
  45. BUFBASE    EQU    BDBASE+BDASIZE        ; base address for 30 200 byte buffers
  46. BUFFTOP EQU     BUFBASE+BUF_COUNT*200
  47. ISCPTR    EQU    BASE_OFFSET + 01feeh    ; my address for ISCP, points to SCB
  48. SCPTR    EQU    BASE_OFFSET + 01ff6h    ; hardwired address for SCP
  49.  
  50. if2
  51.         %out Buffer top is BUFFTOP
  52. if BUFFTOP gt ISCPTR
  53.         %out Warning, buffers extend beyond ISCPTR, reduce BUF_COUNT.
  54. endif
  55. endif
  56. BDSTAT    EQU    0            ; status word in BD
  57. BDLINK    EQU    2            ; 16pointer to next BD
  58. BDPTR    EQU    4            ; 24pointer to actual buffer
  59. BDSIZE    EQU    8            ; size of the buffer
  60. ;
  61. SSTAT    EQU    0            ; status word for SCB
  62. SCOM    EQU    2            ; command word in SCB
  63. SCBL    EQU    4            ; 16pointer to command block list
  64. SRFA    EQU    6            ; 16pointer to receive frame list
  65. SERRS    EQU    8            ; 4 words of error counts
  66. ;
  67. FDSTAT    EQU    0            ; status word for frame
  68. FDEOL    EQU    2            ; end of FD list flag
  69. FDLINK    EQU    4            ; 16pointer to next FD
  70. FDPTR    EQU    6            ; 16pointer to list of BD's
  71. ;
  72. TSTAT    EQU    0            ; status word for xmit
  73. TCOM    EQU    2            ; command to transmit
  74. TLINK    EQU    4            ; 16pointer to next command (always ffff)
  75. TPTR    EQU    6            ; 16pointer to xmit TBD
  76. TTRIES    EQU    8            ; number of transmit retries
  77. ;
  78. MCSTAT    equ    0            ; status word for multicast
  79. MCCOM    equ    2            ; command to setup multicast
  80. MCLINK    equ    4            ; 16pointer to next command (always ffff)
  81. MCCNT    equ    6            ; number of multicast addresses.
  82.  
  83.     public    rcv_modes
  84. rcv_modes    dw    7        ;number of receive modes in our table.
  85.         dw    0               ;There is no mode zero
  86.         dw    0
  87.         dw    rcv_mode_2
  88.         dw    rcv_mode_3
  89.         dw    rcv_mode_4    ;haven't set up perfect filtering yet.
  90.         dw    0
  91.         dw    rcv_mode_6
  92.  
  93. firstfd        dw    FDBASE        ; start of FD queue
  94. lastfd        dw    0        ; end of the FD chain
  95. lastbd        dw    0        ; end of the BD chain
  96. flag        dw    0
  97.  
  98.  
  99. ;
  100. ; Configuration block for 82586, this comprises one config command
  101. ;  Parameters taken from MICOM driver
  102. ;
  103. CBCONF    DW    0        ; status word
  104.     DW    8002H        ; end of command list + configure command
  105.     DW    0ffffh        ; link to next command (not used)
  106.     DW    080CH        ; fifo=8, byte count=C
  107.     DW    2E00H        ; important! Addr (AL) not inserted on the fly!
  108.     DW    6000H        ; IFS = 60h
  109.     DW    0F200H        ; retry=F, slot time=200h
  110. CBCONF_FLAGS    label    byte
  111.     DW    0        ; flags, set to 1 for promiscuous
  112.     DW    40H        ; min frame length=40h
  113.  
  114.  
  115.     include    timeout.asm
  116.  
  117.     public    send_pkt
  118. send_pkt:
  119. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  120. ;  (only if the high-performance bit is set in driver_function)
  121. ;enter with ds:si -> packet, cx = packet length.
  122. ;exit with nc if ok, or else cy if error, dh set to error number.
  123.     assume    ds:nothing
  124.     mov    es,base_addr        ; base for board
  125.  
  126.     mov    word ptr es:[SCB+SCBL],TCBPTR; say where xmit command is
  127.  
  128.     cmp    cx,XMIT_MTU        ; Is this packet too large?
  129.     ja    send_pkt_toobig
  130.  
  131.     mov    dx,cx            ; save a copy, might be less than 60, ok
  132.  
  133.     cmp    dx,RUNT            ; minimum length for Ether
  134.     jnb    oklen
  135.     mov    dx,RUNT            ; make sure size at least RUNT
  136. oklen:
  137.     mov    di,TBUFPTR        ; start of xmit buffer
  138.  
  139. ;
  140. ;  check for previous xmit
  141. ;
  142. xwait:
  143.     mov    bx,word ptr es:[SCB+SCOM]    ; is command zeroed yet?
  144.     or    bx,bx
  145.     jnz    xwait                ; not there yet, wait for it
  146. ;
  147. ;  move the data using word moves.
  148. ;
  149.     call    movemem
  150. ;
  151. ;  put the correct size into the TBD
  152. ;
  153.     or    dx,08000h            ; end of frame bit flag
  154.     mov    word ptr es:[TBDPTR],dx        ; store it
  155.     mov    word ptr es:[TCBPTR],0        ; zero status wd
  156.     mov    word ptr es:[TCBPTR+TCOM],08004h; xmit command in TCB
  157.     mov    word ptr es:[SCB+SCOM],0100h    ; execute command
  158.  
  159.     call    doca
  160.  
  161.     clc
  162.     ret
  163. send_pkt_toobig:
  164.     mov    dh,NO_SPACE
  165.     stc
  166.     ret
  167.  
  168.  
  169. movemem:
  170. ;does the same thing as "rep movsb", only 50% faster.
  171. ;moves words instead of bytes, and handles the case of both addresses odd
  172. ;efficiently.  There is no way to handle one address odd efficiently.
  173. ;This routine always aligns the source address in the hopes that the
  174. ;destination address will also get aligned.  This is from Phil Karn's
  175. ;code from ec.c, a part of his NET package.  I bummed a few instructions
  176. ;out.
  177.     jcxz    movemem_cnte        ; If zero, we're done already.
  178.     test    si,1            ; Does source start on odd byte?
  179.     jz    movemem_adre        ; Go if not
  180.     movsb                ; Yes, move the first byte
  181.     dec    cx            ; Count that byte
  182. movemem_adre:
  183.     shr    cx,1            ; convert to word count
  184.     rep    movsw            ; Move the bulk as words
  185.     jnc    movemem_cnte        ; Go if the count was even
  186.     movsb                ; Move leftover last byte
  187. movemem_cnte:
  188.     ret
  189.  
  190.  
  191.     public    get_address
  192. get_address:
  193. ;get the address of the interface.
  194. ;enter with es:di -> place to get the address, cx = size of address buffer.
  195. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  196.     assume    ds:code
  197.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  198.     jb    get_address_2
  199.     mov    cx,EADDR_LEN
  200.     mov    dx,io_addr        ; Get our IO base address.
  201.     cld
  202. get_address_1:
  203.     in    al,dx            ; get a byte of the eprom address
  204.     stosb                ; put it away
  205.     add    dx,GET_ADDR_INC        ; next register
  206.     loop    get_address_1        ; go back for rest
  207.     mov    cx,EADDR_LEN
  208.     clc
  209.     ret
  210. get_address_2:
  211.     stc
  212.     ret
  213.  
  214.  
  215. rcv_mode_2:
  216.     and    CBCONF_FLAGS,not 3
  217.     or    CBCONF_FLAGS,2        ;disable broadcasts.
  218.     jmp    short reconfigure
  219. rcv_mode_4:
  220. rcv_mode_3:
  221.     and    CBCONF_FLAGS,not 3    ;clear promiscuous mode.
  222.     jmp    short reconfigure
  223. rcv_mode_6:
  224.     and    CBCONF_FLAGS,not 3
  225.     or    CBCONF_FLAGS,1        ;set promiscuous mode.
  226. reconfigure:
  227.     mov    es,base_addr        ;get the base address for the board.
  228.     mov    si,offset CBCONF    ; configure command
  229.     mov    di,CCBPTR        ; where command will reside
  230.     mov    cx,9
  231.     rep    movsw            ; copy to board
  232. ;
  233. ;  issue the configure command
  234. ;
  235.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  236.     mov    word ptr es:[SCB+SCBL],CCBPTR    ; where conf command is
  237.     mov    word ptr es:[SCB+SERRS],0    ; zero errs field
  238.     mov    word ptr es:[SCB+SERRS+2],0    ; zero errs field
  239.     mov    word ptr es:[SCB+SERRS+4],0    ; zero errs field
  240.     mov    word ptr es:[SCB+SERRS+6],0    ; zero errs field
  241.     call    doca
  242.     mov    ax,18
  243.     call    set_timeout
  244. reconfigure_1:
  245.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  246.     test    ax,08000h        ; is command complete?
  247.     jnz    reconfigure_2        ; we're okay.
  248.     call    do_timeout        ;did we time out yet?
  249.     jne    reconfigure_1        ;not yet.
  250.     stc                ;timeout -- uh-oh.
  251.     ret
  252. reconfigure_2:
  253.     clc
  254.     ret
  255.  
  256.  
  257.     public    set_multicast_list
  258. set_multicast_list:
  259. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  260. ;return nc if we set all of them, or cy,dh=error if we didn't.
  261.     assume    ds:code
  262.     mov    es,base_addr
  263.     mov    word ptr es:[SCB+SCBL],TBUFPTR    ;use the transmit buffer.
  264.  
  265.     mov    es:[TBUFPTR+MCSTAT],word ptr 0    ;status word
  266.     mov    es:[TBUFPTR+MCCOM],word ptr 08003h    ;command word for mc-setup + EL
  267.     mov    es:[TBUFPTR+MCLINK],word ptr -1        ;no command link.
  268.     mov    di,TBUFPTR+MCCNT
  269.     mov    ax,cx            ;store the count.
  270.     stosw
  271.     rep    movsb
  272.  
  273.     call    doca
  274.     mov    ax,18
  275.     call    set_timeout
  276. set_multicast_1:
  277.     mov    ax,word ptr es:[TBUFPTR+MCSTAT]    ; get status word
  278.     test    ax,08000h        ; is command complete?
  279.     jnz    set_multicast_2        ; we're okay.
  280.     call    do_timeout        ;did we time out yet?
  281.     jne    set_multicast_1        ;not yet.
  282.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  283.     stc
  284.     ret
  285. set_multicast_2:
  286.     clc
  287.     ret
  288.  
  289.  
  290.     public    terminate
  291. terminate:
  292.     assume    ds:code
  293.     ret
  294.  
  295.     public    reset_interface
  296. reset_interface:
  297. ;reset the interface.
  298. ;we don't do anything.
  299.     assume    ds:nothing
  300.     ret
  301.  
  302.  
  303. ;called when we want to determine what to do with a received packet.
  304. ;enter with cx = packet length, es:di -> packet type.
  305.     extrn    recv_find: near
  306.  
  307. ;called after we have copied the packet into the buffer.
  308. ;enter with ds:si ->the packet, cx = length of the packet.
  309.     extrn    recv_copy: near
  310.  
  311.     extrn    count_in_err: near
  312.     extrn    count_out_err: near
  313.  
  314.     public    recv
  315. recv:
  316.     mov    flag, 1
  317. ;called from the recv isr.  All registers have been saved, and ds=cs.
  318. ;Upon exit, the interrupt will be acknowledged.
  319. recv1:
  320.     mov    ds,base_addr    ; base for board
  321.     assume    ds:nothing
  322.  
  323.     mov    ax,ds:[SCB+SSTAT]    ;get the status.
  324. recv_isr_1:
  325.     cmp    word ptr ds:[SCB+SCOM],0 ;are we done yet?
  326.     jne    recv_isr_1        ;no -- keep waiting.
  327.  
  328.     and    ax,0f000h        ;isolate the ACK bits.
  329.   if DAN
  330.     jz    recv_isr_2
  331.   endif
  332.     mov    ds:[SCB+SCOM],ax    ;make a command to
  333.                     ;acknowledge the interrupt.
  334.     call    doca
  335. recv_isr_2:
  336.     cmp    word ptr ds:[SCB+SCOM],0 ;are we done yet?
  337.     jne    recv_isr_2        ;no -- keep waiting.
  338.  
  339. ;  Get whatever packets are on the board
  340. ;
  341.     mov    bx,firstfd    ; get addr of first FD in list
  342.     mov    ax,[bx+FDSTAT]    ; status word of frame
  343.     test    ax,08000h    ; frame written?
  344.     jnz    okframe
  345.  
  346.     jmp    ru_start    ; no, restore receiver if necessary
  347. frame_bad:
  348.     call    count_in_err
  349. ptrupdate_j_1:
  350.     jmp    ptrupdate
  351.  
  352. ;  we have a frame, read it in
  353. ;
  354. okframe:
  355.     test    ax,02000h        ;check frame OK bit
  356.     jz    frame_bad        ;bad, fix it.
  357.     mov    si,[bx+FDPTR]        ;get pointer to buffer descriptor
  358.     xor    cx,cx            ;start with zero bytes.
  359. countbuf:                ;es:di is already set to receive packet
  360.     mov    dx,si            ;save a copy of current BD ptr
  361.     mov    ax,[si+BDSTAT]        ;get status and count word for BD
  362.     test    ax,04000h        ;is count field there?
  363.     jz    ptrupdate_j_1        ;no - we give up here.
  364.     add    cl,al            ;add the count into cx.
  365.     adc    ch,0
  366.     mov    si,[si+BDLINK]        ;go to next BD in list
  367.     test    ax,8000h        ;is this the last frame?
  368.     je    countbuf        ;no - keep counting.
  369.  
  370.     push    bx
  371.     push    cx
  372.  
  373.     mov    ax,cs            ;we need ds = code.
  374.     mov    ds,ax
  375.     assume    ds:code
  376.  
  377.     mov    es,base_addr        ;get a pointer to their type.
  378.     mov    di,es:[bx+FDPTR]    ;get pointer to buffer descriptor
  379.     mov    di,es:[di+BDPTR]    ;get offset of data
  380.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  381.                     ;  point to the packet type.
  382.  
  383.     call    recv_find        ;look up our type.
  384.  
  385.     pop    cx
  386.     pop    bx
  387.     mov    ds,base_addr        ;restore ds to the board.
  388.     assume    ds:nothing
  389.  
  390.     mov    ax,es            ;is this pointer null?
  391.     or    ax,di
  392.     je    ptrupdate        ;yes - just free the frame.
  393.  
  394.     push    cx
  395.     push    es            ;remember where the buffer pointer is.
  396.     push    di
  397.   if DAN
  398.     push    cx
  399.   endif
  400.  
  401.     mov    si,[bx+FDPTR]        ;get pointer to buffer descriptor
  402. copybuf:
  403.     mov    dx,si            ;save a copy of current BD ptr
  404.     xor    ch,ch            ;200 bytes is largest this can be
  405.     mov    cl,[si+BDSTAT]        ;get count word for BD
  406.     mov    si,[si+BDPTR]        ;get offset of data
  407.   if DAN
  408.     pop    ax
  409.     sub    ax, cx
  410.     jc    copydone
  411.     push    ax
  412.   ENDIf
  413.     call    movemem
  414.     mov    si,dx            ;get back current BD ptr
  415.     test    [si+BDSTAT],8000h    ;check EOF bit
  416.     mov    si,[si+BDLINK]        ;go to next BD in list
  417.     jz    copybuf            ;not done, keep copying it.
  418.  
  419.   if DAN
  420.     pop    cx
  421. copydone:
  422.   endif
  423.     pop    si            ;now give the frame to the client.
  424.     pop    ds
  425.     pop    cx
  426.     assume    ds:nothing
  427.  
  428.     call    recv_copy
  429. ;
  430. ;  we are done with the frame, do the list management
  431. ;
  432. ptrupdate:
  433.     push    cs
  434.     pop    ds
  435.     assume    ds:code
  436.     mov    es,base_addr        ; reload board segment
  437.  
  438.     mov    si,es:[bx+FDPTR]    ; first BD in frame list
  439. nextbd:
  440.     mov    cx,es:[si+BDSTAT]    ; count word for BD, EOF bit
  441.     test    cx,08000h        ; EOF bit, if set, save si in lastbd
  442.     jnz    dolastbd
  443.     mov    word ptr es:[si+BDSTAT],0 ; clear status word, EOF bit
  444.     cmp    si,lastbd        ; see if we are wrapping
  445.     jz    dolastbd        ; yes, just undo it
  446.     mov    si,es:[si+BDLINK]    ; follow link
  447.     jmp    nextbd
  448. dolastbd:
  449.     mov    di,lastbd        ; where end of BD list is now
  450.     mov    lastbd,si        ; store last known BD
  451.     mov    word ptr es:[si+BDSIZE],08000h+200    ; end of list here
  452.     mov    word ptr es:[si+BDSTAT],0 ; clear status word, EOF bit
  453. ; size field for not end of list
  454.     mov    word ptr es:[di+BDSIZE],200    ; remove old end-of-list
  455.  
  456. ;
  457. ;  update the FD list flags, new end-of-list
  458. ;
  459.     mov    word ptr es:[bx+FDEOL],08000h    ; store new EOL
  460.     mov    word ptr es:[bx+FDSTAT],0    ; clear status word for frame
  461.     mov    di,lastfd        ; get old end-of-list
  462.     mov    word ptr es:[di+FDEOL],0 ; zero old one
  463.     mov    lastfd,bx        ; update stored pointer
  464.     mov    si,es:[bx+FDLINK]    ; where next fd is
  465.     mov    firstfd,si        ; store that info for next time
  466.   if DAN
  467.     jmp    recv1
  468.   endif
  469.  
  470. ru_start:
  471. ; re-start receive unit
  472. ;
  473. ;  check to see if the receiver went off because of no resources
  474. ;  and restart receiver if necessary
  475. ;
  476.     push    cs
  477.     pop    ds
  478.     mov    es,base_addr
  479.     mov    ax,es:[SCB+SSTAT]    ; status word for SCB
  480.     and    ax,070h        ; receiver status
  481.     cmp    al,020h        ; receiver has no resources
  482.     jnz    hasres
  483.   if DAN
  484.     cmp    flag, 1
  485.     jnz    ru_start1
  486.     mov    flag, 0
  487.     jmp    recv1
  488.   endif
  489.  
  490. ru_start1:
  491.     call    count_out_err
  492. ;
  493. ;  setup lists for starting the RU on the chip
  494. ;  we know that there isn't anything in the buffer that we want
  495. ;
  496.  
  497.     mov    bx,firstfd    ; get first FD on free list (assume free)
  498.     mov    word ptr es:[SCB+SRFA],bx    ; put into SCB
  499.     mov    si,lastbd    ; pointer to a BD, end of chain
  500.     mov    ax,word ptr es:[si+BDLINK]    ; pointer to next BD
  501.     mov    word ptr es:[bx+FDPTR],ax    ; set to start of BDs
  502. ;
  503. ;
  504. ;  Start the RU, doesn't need CB, only SCB parms.
  505. ;   command, to start receiving again
  506. ;
  507.     mov    word ptr es:[SCB+SSTAT],0    ; clear status word
  508.     mov    word ptr es:[SCB+SCOM],010h    ; start RU
  509.     call    doca
  510. hasres:
  511. recv_isr_end:
  512.     cmp    word ptr es:[SCB+SCOM],0 ;are we done yet?
  513.     jne    recv_isr_end        ;no -- keep waiting.
  514.     ret
  515.  
  516.  
  517.     public    recv_exiting
  518. recv_exiting:
  519. ;called from the recv isr after interrupts have been acknowledged.
  520. ;Only ds and ax have been saved.
  521.     assume    ds:nothing
  522.     ret
  523.  
  524.  
  525.     public    set_address
  526. set_address:
  527.     assume    ds:nothing
  528. ;enter with ds:si -> Ethernet address, CX = length of address.
  529. ;exit with nc if okay, or cy, dh=error if any errors.
  530.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  531.     je    set_address_4
  532.     mov    dh,BAD_ADDRESS
  533.     stc
  534.     jmp    short set_address_done
  535. set_address_4:
  536.  
  537. ;  Next step, load our address into the board
  538. ;     reuses the space that the configure command used, with different command
  539. ;
  540.     mov    es,base_addr        ; set to base address
  541.     mov    word ptr es:[SCB+SCBL],CCBPTR    ; say where conf command is
  542.  
  543.     mov    di,CCBPTR        ; start of config command block
  544.     xor    ax,ax
  545.     stosw                ; zero status word for commmand
  546.     mov    ax,8001h        ; IA setup command + EL
  547.     stosw
  548.     xor    ax,ax
  549.     dec    ax
  550.     stosw                ; set link value to -1 (unused)
  551.  
  552.     rep    movsb            ; move their ethernet address in.
  553. ;
  554. ;  start the IA setup command
  555. ;
  556.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  557.     call    doca
  558.     xor    cx,cx            ; timeout
  559. set_address_1:
  560.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  561.     test    ax,08000h        ; is command complete?
  562.     loopz    set_address_1
  563.     jnz    set_address_okay
  564.     stc
  565.     mov    dh,-1            ; no error in the list applies.
  566.     jmp    short set_address_done
  567. set_address_okay:
  568.     mov    cx,EADDR_LEN        ;return their address length.
  569.     clc
  570. set_address_done:
  571.     push    cs
  572.     pop    ds
  573.     assume    ds:code
  574.     ret
  575.  
  576.  
  577. end_resident    label    byte
  578.  
  579. timeout_msg    db    "Timed out while initializing the board.",CR,LF,'$'
  580. int_no_name    db    "Interrupt number ",'$'
  581. io_addr_name    db    "I/O port ",'$'
  582. base_addr_name    db    "Memory address ",'$'
  583. our_address    db    6 dup(?)    ;temporarily hold our address
  584.  
  585. tdr_ok_msg    db    "TDR Ok",CR,LF,'$'
  586. tdr_none_msg    db    "Your Ethernet card doesn't seem to be plugged in.",CR,LF,'$'
  587. tdr_open_msg    db    " clocks away is an OPEN",CR,LF,'$'
  588. tdr_short_msg    db    " clocks away is a SHORT",CR,LF,'$'
  589.  
  590. mem8_16        db    2        ; 1 for 16k, 2 for 8k
  591.  
  592.     extrn    set_recv_isr: near
  593.     extrn    maskint: near
  594.  
  595. ;enter with si -> argument string, di -> word to store.
  596. ;if there is no number, don't change the number.
  597.     extrn    get_number: near
  598.  
  599. ;enter with dx -> name of word, di -> dword to print.
  600.     extrn    print_number: near
  601.  
  602. ;enter with ax = number to print.
  603.     extrn    decout: near
  604.  
  605.     public    parse_args
  606. parse_args:
  607.     mov    di,offset int_no
  608.     call    get_number
  609.     mov    di,offset io_addr
  610.     call    get_number
  611.     mov    di,offset base_addr
  612.     call    get_number
  613.     sub    base_addr,BASE_OFFSET shr 4
  614.     clc
  615.     ret
  616.  
  617.  
  618. timeout_error:
  619.     mov    dx,offset timeout_msg
  620.     jmp    short error
  621. error:
  622.     mov    ah,9
  623.     int    21h
  624.     stc
  625.     ret
  626.  
  627. ;
  628. ;  data for configuring and setting up the board
  629. ;
  630. ;  chip always looks at SCP for config info which points to ISCP for the
  631. ;  pointer to the CONTROL BLOCK which handles everything from there.
  632. ;  Kind of indirect, but it works.
  633. ;
  634. SCP    DB    0            ; bus use flag (0=16 bit, 1=8 bit).
  635.     DB    5 DUP(0)        ; unused
  636.     DW    ISCPTR            ; 24pointer to ISCP offset
  637.     DW    0            ; high part
  638. ;
  639. ; Intermediate SCP
  640. ;
  641. ISCP    DW    1        ; busy flag
  642.     DW    SCB        ; 16pointer to SCB
  643.     DW    0,0        ; base for all 16 pointers, lo, hi
  644.                 ; board is hardwired to 0 for these values
  645. ;
  646. ; CB for xmit, followed by BD for xmit, copied together
  647. ;
  648. TCB    DW    0        ; status word
  649.     DW    08004H        ; command word for xmit + EL
  650.     DW    0ffffh        ; no command link
  651.     DW    TBDPTR        ; 16pointer to xmit BD
  652.     DW    0,0,0,0        ; no addressing used here
  653. ;
  654. ; BD template for xmit
  655. TBD    DW    0
  656.     DW    0        ; next BD pointer, unused
  657.     DW    TBUFPTR        ; 24pointer to xmit buffer
  658.     DW    0        ; high part of pointer
  659.  
  660.     public    etopen
  661. etopen:
  662.     mov    al,int_no
  663.     call    maskint            ;disable these interrupts.
  664.  
  665. ;  Initialize the Ethernet board, set receive type.
  666. ;
  667. ;  check for correct EPROM location
  668. ;
  669.     call    check_board
  670.  
  671. ;
  672. ;  Turn off interrupts, I don't want them
  673. ;
  674.   ifdef IOINTOF
  675.     loadport
  676.     setport IOINTOF
  677.     out    dx,al
  678.   endif
  679. ;
  680. ;  Disconnect from network
  681. ;
  682.   ifdef IODIS
  683.     loadport
  684.     setport    IODIS
  685.     out    dx,al
  686.   endif
  687.  
  688. ;
  689. ;  Initialize the Ethernet board.
  690. ;
  691.     mov    es,base_addr    ; set to base address
  692.  
  693. ;
  694. ;  Intermediate SCP
  695. ;
  696.     mov    si,offset ISCP    ; addr of pre-set values
  697.     mov    di,ISCPTR
  698.     mov    cx,4        ; 4 words
  699.     rep    movsw        ; install ISCP
  700.  
  701. ;
  702. ;  Now discern the end of memory by repeatedly re-initializing the board
  703. ;  until the BUSY flag in the ISCP gets reset.
  704. ;
  705.     mov    di,SCPTR
  706.  
  707. re_discern:
  708.     push    di
  709.     mov    si,offset SCP    ; get pre-set values
  710.     mov    cx,5        ; 5 words
  711.     rep    movsw        ; install SCP
  712.     pop    di
  713.  
  714.   ifdef IORESET
  715. ;
  716. ;  Reset the chip
  717. ;
  718.     loadport
  719.     setport    IORESET
  720.     out    dx,al
  721.   endif
  722. ;
  723. ;  Issue a CA to initialize the chip after reset
  724. ;
  725.     call    lbca
  726.  
  727.     mov    ax,2            ;don't wait too long.
  728.     call    set_timeout
  729. confwait:
  730.     cmp    byte ptr es:[ISCPTR],0    ;did it clear the busy flag?
  731.     je    confok            ;yes.
  732.     call    do_timeout
  733.     jne    confwait
  734.  
  735.     add    di,2000h        ;go up another 8K.
  736.     jnc    re_discern        ;try this next higher address.
  737. confbad:
  738.     sti
  739.     jmp    timeout_error
  740.  
  741. confok:
  742.     call    reconfigure
  743.     jc    confbad
  744.  
  745. ;
  746. ;  Ask the board for the Ethernet address, and then use set_address to set it.
  747. ;
  748.     push    ds
  749.     pop    es
  750.     mov    di,offset our_address
  751.     mov    cx,EADDR_LEN
  752.     call    get_address
  753.  
  754.     mov    si,offset our_address
  755.     mov    cx,EADDR_LEN
  756.     call    set_address
  757.     jnc    store_address_2
  758.     sti
  759.     jmp    timeout_error
  760. store_address_2:
  761. ;
  762. ;  IA sent, setup all of the other data structures on the board
  763. ;  start with xmit command descriptors
  764. ;
  765.     mov    si,offset TCB        ; template for xmit
  766.     mov    di,TCBPTR        ; where it goes on board
  767.     mov    cx,12            ; copies CB and BD for xmit
  768.     rep    movsw
  769. ;
  770. ;  Set up frame and buffer descriptors, 30 each
  771. ;
  772.     mov    cx,BUF_COUNT        ; # of FDs
  773.     mov    di,FDBASE        ; base addr for FDs
  774. fdloop:
  775.     xor    ax,ax
  776.     mov    bx,di            ; save pointer
  777.     stosw                ; clear status wd
  778.     stosw                ; clear EL field
  779.     add    bx,22            ; points to next one
  780.     mov    es:[di],bx        ; put in link ptr
  781.     inc    di
  782.     inc    di
  783.     dec    ax
  784.     stosw                ; clear BD ptr to -1
  785.     add    di,14
  786.     loop    fdloop
  787.  
  788.     sub    di,20            ; point back to last EL field
  789.     mov    ax,08000h        ; end of list
  790.     stosw                ; put into last FD
  791.     sub    di,4            ; back to beginning of last FD
  792.     mov    lastfd,di        ; save the pointer
  793.     mov    word ptr es:[di+FDLINK],FDBASE    ; make list circular,
  794.                         ; from last to first
  795.  
  796.     mov    ax,BDBASE        ; first BD
  797.     mov    word ptr es:[FDBASE+FDPTR],ax    ; put it in the first FD frame
  798. ;
  799. ;  now BDs
  800.     mov    cx,BUF_COUNT
  801.     mov    di,BDBASE        ; start of BD area
  802.     mov    dx,BUFBASE        ; start of buffer area
  803. bdloop:
  804.     xor    ax,ax
  805.     mov    bx,di            ; save pointer
  806.     stosw                ; zero status field
  807.     add    bx,10            ; point to next record
  808.     mov    es:[di],bx        ; put in link ptr
  809.     inc    di
  810.     inc    di
  811.     mov    es:[di],dx        ; address of buffer, lo part
  812.     inc    di
  813.     inc    di
  814.     stosw                ; zero out high part
  815.     mov    ax,200
  816.     stosw                ; store length field
  817.     add    dx,ax            ; add in length of buffer, updates ptr
  818.     loop    bdloop
  819.  
  820.     sub    di,2            ; back to last BD size field
  821.     mov    ax,08000h+200        ; end of list + 200
  822.     stosw                ; mark end of list
  823.     sub    di,8            ; back to last BDLINK field
  824.     mov    ax,BDBASE
  825.     stosw                ; put link to beginning of list here
  826.     sub    di,4            ; back to beginning of last BD
  827.     mov    lastbd,di        ; save pointer to end of list
  828.   ifdef IOENA
  829. ;
  830. ;  configure to connect to network
  831. ;
  832.     loadport
  833.     setport    IOENA            ; enable network
  834.     out    dx,al            ; any al value
  835.   endif
  836. ;
  837. ; Test to see if the network is okay.
  838. ;
  839.     mov    di,CCBPTR        ; start of config command block
  840.     xor    ax,ax            ; zero status word for commmand
  841.     stosw
  842.     mov    ax,8005h        ; TDR command + EL
  843.     stosw
  844.     xor    ax,ax
  845.     dec    ax
  846.     stosw                ; set link value to -1 (unused)
  847.     inc    ax
  848.     stosw                ; zero time result.
  849.  
  850.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  851.  
  852.     call    lbca
  853.  
  854.     xor    cx,cx            ; timeout
  855. do_tdr_1:
  856.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  857.     test    ax,08000h        ; is command complete?
  858.     loopz    do_tdr_1
  859.     mov    ax,word ptr es:[CCBPTR+6]
  860.     jnz    do_tdr_2
  861.     mov    ax,2000h        ; treat a timeout as an open
  862. do_tdr_2:
  863.     test    ax,8000h
  864.     mov    dx,offset tdr_ok_msg
  865.     jne    do_tdr_3
  866.     mov    dx,offset tdr_short_msg
  867.     test    ax,2000h
  868.     je    do_tdr_4
  869.     mov    dx,offset tdr_none_msg
  870.     cmp    ax,2000h
  871.     je    do_tdr_3
  872.     mov    dx,offset tdr_open_msg
  873. do_tdr_4:
  874.     push    dx
  875.     and    ax,2048-1
  876.     xor    dx,dx
  877.     call    decout
  878.     pop    dx
  879. do_tdr_3:
  880.     mov    ah,9
  881.     int    21h
  882.  
  883. ;
  884. ;  Start the RU, doesn't need CB, only SCB parms.
  885. ;   command, to start receiving
  886. ;
  887.     mov    word ptr es:[SCB+SSTAT],0        ; clear status word
  888.     mov    word ptr es:[SCB+SRFA],FDBASE    ; set to frame descriptors
  889.     mov    word ptr es:[SCB+SCOM],010h    ; start RU
  890.     call    lbca
  891. ;
  892. ; Now reset CX, FR, CNA, and RNR so that we don't get a spurious interrupt.
  893. ;
  894. store_ack_1:
  895.     cmp    word ptr es:[SCB+SCOM],0 ;are we done yet?
  896.     jne    store_ack_1        ;no -- keep waiting.
  897.  
  898.     mov    ax,es:[SCB+SSTAT]    ;get the status.
  899.     and    ax,0f000h        ;isolate the ACK bits.
  900.     mov    es:[SCB+SCOM],ax    ;make a command to
  901.                     ;acknowledge the interrupt.
  902.     call    doca
  903. ;
  904. ; Now hook in our interrupt
  905. ;
  906.     call    set_recv_isr
  907.  
  908.     sti
  909.  
  910.     mov    di,offset int_no
  911.     mov    dx,offset int_no_name
  912.     call    print_number
  913.     mov    di,offset io_addr
  914.     mov    dx,offset io_addr_name
  915.     call    print_number
  916.     mov    di,offset base_addr
  917.     mov    dx,offset base_addr_name
  918.     call    print_number
  919.  
  920.     mov    dx,offset end_resident
  921.     clc
  922.     ret
  923.