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