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

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