home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / asm / drivers1 / 3c501.asm next >
Assembly Source File  |  1992-01-23  |  17KB  |  748 lines

  1. version    equ    2
  2.  
  3.     include    defs.asm
  4.  
  5. ;Ported from Phil Karn's ec.c, a C-language driver for the 3COM 3C501
  6. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  7. ;*  Updated to version 1.08 Feb. 17, 1989.
  8.  
  9. ;  Copyright, 1988-1992, Russell Nelson, Crynwr Software
  10.  
  11. ;   This program is free software; you can redistribute it and/or modify
  12. ;   it under the terms of the GNU General Public License as published by
  13. ;   the Free Software Foundation, version 1.
  14. ;
  15. ;   This program is distributed in the hope that it will be useful,
  16. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. ;   GNU General Public License for more details.
  19. ;
  20. ;   You should have received a copy of the GNU General Public License
  21. ;   along with this program; if not, write to the Free Software
  22. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24. code    segment    word public
  25.     assume    cs:code, ds:code
  26.  
  27. ;The various IE command registers
  28. EDLC_ADDR    equ    00h    ;EDLC station address, 6 bytes
  29. EDLC_RCV    equ    06h    ;EDLC receive csr
  30. EDLC_XMT    equ    07h    ;EDLC transmit csr
  31. IE_GP        equ    08h    ;GP pointer
  32. IE_RP        equ    0ah    ;Receive buffer pointer
  33. IE_SAPROM    equ    0ch    ;window on station addr prom
  34. IE_CSR        equ    0eh    ;IE command/status
  35. IE_BFR        equ    0fh    ;window on packet buffer
  36.  
  37. ;Bits in EDLC_RCV, interrupt enable on write, status when read
  38. EDLC_NONE    equ    000h    ;match mode in bits 5-6, write only
  39. EDLC_ALL    equ    040h    ;promiscuous receive, write only
  40. EDLC_BROAD    equ    080h    ;station address plus broadcast
  41. EDLC_MULTI    equ    0c0h    ;station address plus multicast
  42.  
  43. EDLC_STALE    equ    80h    ;receive CSR status previously read
  44. EDLC_GOOD    equ    20h    ;well formed packets only
  45. EDLC_ANY    equ    10h    ;any packet, even those with errors
  46. EDLC_SHORT    equ    08h    ;short frame
  47. EDLC_DRIBBLE    equ    04h    ;dribble error
  48. EDLC_FCS    equ    02h    ;CRC error
  49. EDLC_OVER    equ    01h    ;data overflow
  50.  
  51. EDLC_RERROR    equ    EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  52. EDLC_RMASK    equ    EDLC_GOOD or EDLC_ANY or EDLC_RERROR
  53.  
  54. ;bits in EDLC_XMT, interrupt enable on write, status when read
  55. EDLC_IDLE    equ    08h    ;transmit idle
  56. EDLC_16        equ    04h    ;packet experienced 16 collisions
  57. EDLC_JAM    equ    02h    ;packet experienced a collision
  58. EDLC_UNDER    equ    01h    ;data underflow
  59.  
  60. ;bits in IE_CSR
  61. IE_RESET    equ    80h    ;reset the controller (wo)
  62. IE_XMTBSY    equ    80h    ;Transmitter busy (ro)
  63. IE_RIDE        equ    40h    ;request interrupt/DMA enable (rw)
  64. IE_DMA        equ    20h    ;DMA request (rw)
  65. IE_EDMA        equ    10h    ;DMA done (ro)
  66.  
  67. IE_BUFCTL    equ    0ch    ;mask for buffer control field (rw)
  68. IE_LOOP        equ    0ch    ;2 bit field in bits 2,3, loopback
  69. IE_RCVEDLC    equ    08h    ;gives buffer to receiver
  70. IE_XMTEDLC    equ    04h    ;gives buffer to transmit
  71. IE_SYSBFR    equ    00h    ;gives buffer to processor
  72.  
  73. IE_CRC        equ    01h    ;causes CRC error on transmit (wo)
  74. IE_RCVBSY    equ    01h    ;receive in progress (ro)
  75.  
  76. BFRSIZ        equ    2048    ;number of bytes in a buffer
  77.  
  78.     public    int_no
  79. int_no        db    3,0,0,0        ; interrupt number.
  80. io_addr        dw    0300h,0        ; I/O address for card (jumpers)
  81.  
  82.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  83. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  84. driver_type    db    1        ;from the packet spec
  85. driver_name    db    '3C501',0    ;name of the driver.
  86. driver_function    db    2
  87. parameter_list    label    byte
  88.     db    1    ;major rev of packet driver
  89.     db    9    ;minor rev of packet driver
  90.     db    14    ;length of parameter list
  91.     db    EADDR_LEN    ;length of MAC-layer address
  92.     dw    GIANT    ;MTU, including MAC headers
  93.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  94.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  95.     dw    0    ;(# of successive xmits) - 1
  96. int_num    dw    0    ;Interrupt # to hook for post-EOI
  97.             ;processing, 0 == none,
  98.  
  99.     public    rcv_modes
  100. rcv_modes    dw    7        ;number of receive modes in our table.
  101.         dw    0               ;There is no mode zero
  102.         dw    rcv_mode_1
  103.         dw    0        ;don't want to bother.
  104.         dw    rcv_mode_3
  105.         dw    0        ;haven't set up perfect filtering yet.
  106.         dw    rcv_mode_5
  107.         dw    rcv_mode_6
  108.  
  109. ipkt_size    dw    ?
  110. opkt_size    dw    ?
  111.  
  112. is_186        db    0        ;=0 if 808[68], =1 if 80[123]86.
  113. our_type    dw    ?,?
  114.  
  115.     public    as_send_pkt
  116. ; The Asynchronous Transmit Packet routine.
  117. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  118. ;   interrupts possibly enabled.
  119. ; Exit with nc if ok, or else cy if error, dh set to error number.
  120. ;   es:di and interrupt enable flag preserved on exit.
  121. as_send_pkt:
  122.     ret
  123.  
  124.     public    drop_pkt
  125. ; Drop a packet from the queue.
  126. ; Enter with es:di -> iocb.
  127. drop_pkt:
  128.     assume    ds:nothing
  129.     ret
  130.  
  131.     public    xmit
  132. ; Process a transmit interrupt with the least possible latency to achieve
  133. ;   back-to-back packet transmissions.
  134. ; May only use ax and dx.
  135. xmit:
  136.     assume    ds:nothing
  137.     ret
  138.  
  139.  
  140.     public    send_pkt
  141. send_pkt:
  142. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  143. ;  (only if the high-performance bit is set in driver_function)
  144. ;enter with ds:si -> packet, cx = packet length.
  145. ;exit with nc if ok, or else cy if error, dh set to error number.
  146.     assume    ds:nothing
  147.     cmp    cx,RUNT        ; minimum length for Ether
  148.     jae    oklen
  149.     mov    cx,RUNT        ; make sure size at least RUNT
  150. oklen:
  151.     inc    cx            ;round size up to next even number.
  152.     and    cx,not 1
  153.  
  154. ;Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  155. ;only in the transmit mode, hence the initial check.
  156.  
  157.     loadport
  158.     setport    IE_CSR
  159.     in    al,dx
  160.     and    al,IE_BUFCTL
  161.     cmp    al,IE_XMTEDLC
  162.     jne    send_pkt_2
  163.  
  164.     mov    bx,20000        ;try this many times.
  165. send_pkt_3:
  166.     in    al,dx            ;if not busy, exit.
  167.     and    al,IE_XMTBSY
  168.     je    send_pkt_2
  169.     dec    bx
  170.     jne    send_pkt_3
  171.     mov    dh,CANT_SEND        ;timed out, can't send.
  172.     stc
  173.     ret
  174. send_pkt_2:
  175.  
  176. ;Get control of the board buffer and disable receiver
  177.     mov    al,IE_RIDE or IE_SYSBFR
  178.     setport    IE_CSR
  179.     out    dx,al
  180.  
  181. ;Point GP at beginning of packet
  182.     mov    ax,BFRSIZ
  183.     sub    ax,cx
  184.     setport    IE_GP
  185.     out    dx,ax
  186.  
  187.     setport    IE_BFR
  188.  
  189.     mov    opkt_size,cx    ; opkt_size = cx;
  190.     cmp    is_186,0    ; Can we use rep outsb?
  191.     je    out86        ; no - have to do it slowly.
  192.     db    0f3h, 06eh    ;masm 4.0 doesn't grok "rep outsb"
  193.     jmp    short ocnteven
  194. out86:
  195.     test    si,1        ; (buf & 1) ?
  196.     jz    obufeven    ; no
  197.     lodsb            ; al = *si++;
  198.     out    dx,al        ; out(dx,al);
  199.     dec    cx        ; cx--;
  200. obufeven:
  201.     mov    di,cx        ; save for later test
  202.     shr    cx,1        ; cx = cnt >> 1; (convert to word count)
  203. ; Do the bulk of the buffer, a word at a time
  204.     jcxz    onobuf        ; if(cx != 0){
  205. xb:    lodsw            ; do { ax = *si++; (si is word pointer)
  206.     out    dx,al        ; out(dx,lowbyte(ax));
  207.     mov    al,ah
  208.     out    dx,al        ; out(dx,hibyte(ax));
  209.     loop    xb        ; } while(--cx != 0); }
  210. ; now check for odd trailing byte
  211. onobuf:    shr    di,1        ; if (di & 1)
  212.     jnc    ocnteven
  213.     lodsb            ;   out(dx,*si++);
  214.     out    dx,al
  215. ocnteven:
  216.  
  217. ;Start transmitter
  218. ;Point GP at beginning of packet
  219.     mov    ax,BFRSIZ
  220.     sub    ax,opkt_size
  221.     setport    IE_GP
  222.     out    dx,ax
  223.  
  224.     mov    al,IE_RIDE or IE_XMTEDLC
  225.     setport    IE_CSR
  226.     out    dx,al
  227.  
  228.   if 1
  229.     mov    bx,20000        ;try this many times.
  230. send_pkt_4:
  231.     in    al,dx            ;if not busy, exit.
  232.     and    al,IE_XMTBSY
  233.     je    send_pkt_5
  234.     dec    bx
  235.     jne    send_pkt_4
  236.     mov    dh,CANT_SEND        ;timed out, can't send.
  237.     stc
  238.     ret
  239. send_pkt_5:
  240.  
  241.   endif
  242.  
  243.     clc
  244.     ret
  245.  
  246.  
  247.     public    get_address
  248. get_address:
  249. ;get the address of the interface.
  250. ;enter with es:di -> place to get the address, cx = size of address buffer.
  251. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  252.     assume    ds:code
  253.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  254.     jb    get_address_2
  255.     mov    cx,EADDR_LEN
  256.     xor    bx,bx
  257. get_address_1:
  258.     mov    ax,bx
  259.     loadport
  260.     setport    IE_GP
  261.     out    dx,ax
  262.  
  263.     setport    IE_SAPROM
  264.     in    al,dx
  265.     stosb
  266.     inc    bx
  267.     loop    get_address_1
  268.  
  269.     mov    cx,EADDR_LEN
  270.     clc
  271.     ret
  272. get_address_2:
  273.     stc
  274.     ret
  275.  
  276.  
  277. ;Set Ethernet address on controller
  278.     public    set_address
  279. set_address:
  280.     assume    ds:nothing
  281. ;enter with ds:si -> Ethernet address, CX = length of address.
  282. ;exit with nc if okay, or cy, dh=error if any errors.
  283. ;
  284.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  285.     je    set_address_4
  286.     mov    dh,BAD_ADDRESS
  287.     stc
  288.     jmp    short set_address_done
  289. set_address_4:
  290.  
  291.     loadport
  292.     setport    EDLC_ADDR
  293. set_address_1:
  294.     lodsb
  295.     out    dx,al
  296.     inc    dx
  297.     loop    set_address_1
  298. set_address_okay:
  299.     mov    cx,EADDR_LEN        ;return their address length.
  300.     clc
  301. set_address_done:
  302.     push    cs
  303.     pop    ds
  304.     assume    ds:code
  305.     ret
  306.  
  307.  
  308. rcv_mode_1:
  309. ;Set up the receiver interrupts and flush status
  310.     mov    al,EDLC_NONE
  311.     loadport
  312.     setport    EDLC_RCV
  313.     out    dx,al
  314.     in    al,dx            ;flush status.
  315.  
  316.     ret
  317.  
  318.  
  319. rcv_mode_3:
  320. ;Set up the receiver interrupts and flush status
  321.     mov    al,EDLC_BROAD or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  322.     loadport
  323.     setport    EDLC_RCV
  324.     out    dx,al
  325.     in    al,dx            ;flush status.
  326.  
  327.     ret
  328.  
  329.  
  330. rcv_mode_5:
  331. ;Set up the receiver interrupts and flush status
  332.     mov    al,EDLC_MULTI or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  333.     loadport
  334.     setport    EDLC_RCV
  335.     out    dx,al
  336.     in    al,dx            ;flush status.
  337.  
  338.     ret
  339.  
  340.  
  341. rcv_mode_6:
  342. ;Set up the receiver interrupts and flush status
  343.     mov    al,EDLC_ALL or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  344.     loadport
  345.     setport    EDLC_RCV
  346.     out    dx,al
  347.     in    al,dx            ;flush status.
  348.  
  349.     ret
  350.  
  351.  
  352.     public    set_multicast_list
  353. set_multicast_list:
  354. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  355. ;return nc if we set all of them, or cy,dh=error if we didn't.
  356.     mov    dh,NO_MULTICAST
  357.     stc
  358.     ret
  359.  
  360.  
  361.     public    terminate
  362. terminate:
  363. ;Pulse IE_RESET
  364.     mov    al,IE_RESET
  365.     loadport
  366.     setport    IE_CSR
  367.     out    dx,al
  368.     mov    al,0
  369.     out    dx,al
  370.  
  371.     ret
  372.  
  373.     public    reset_interface
  374. reset_interface:
  375. ;reset the interface.
  376. ;we don't do anything.
  377.     ret
  378.  
  379.  
  380. ;called when we want to determine what to do with a received packet.
  381. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  382.     extrn    recv_find: near
  383.  
  384. ;called after we have copied the packet into the buffer.
  385. ;enter with ds:si ->the packet, cx = length of the packet.
  386.     extrn    recv_copy: near
  387.  
  388.     extrn    count_in_err: near
  389.     extrn    count_out_err: near
  390.  
  391.     public    recv
  392. recv:
  393. ;called from the recv isr.  All registers have been saved, and ds=cs.
  394. ;Upon exit, the interrupt will be acknowledged.
  395.     assume    ds:code
  396.  
  397. ;Check for transmit jam
  398.  
  399.     loadport
  400.     setport    IE_CSR
  401.     in    al,dx
  402.     and    al,IE_XMTBSY
  403.     jne    recv_isr_1
  404.  
  405.     setport    EDLC_XMT
  406.     in    al,dx
  407.     test    al,EDLC_16
  408.     je    recv_isr_2
  409. ;ecp->estats.jam16++;
  410.     call    rcv_fixup
  411.     jmp    short     recv_isr_3
  412. recv_isr_2:
  413.     test    al,EDLC_JAM
  414.     je    recv_isr_3
  415. ;Crank counter back to beginning and restart transmit
  416. ;ecp->estats.jam++;
  417.     mov    al,IE_RIDE or IE_SYSBFR
  418.     setport    IE_CSR
  419.     out    dx,al
  420.  
  421.     mov    ax,BFRSIZ
  422.     sub    ax,opkt_size
  423.     setport    IE_GP
  424.     out    dx,ax
  425.  
  426.     mov    al,IE_RIDE or IE_XMTEDLC
  427.     setport    IE_CSR
  428.     out    dx,al
  429.  
  430. recv_isr_3:
  431.  
  432. recv_isr_1:
  433.     loadport
  434.     setport    EDLC_RCV
  435.     in    al,dx
  436.     test    al,EDLC_STALE
  437.     jne    recv_isr_4_j_1
  438.     test    al,EDLC_OVER
  439.     je    recv_isr_5
  440. ;ecp->estats.over++;
  441.     call    rcv_fixup
  442.     jmp    recv_isr_1
  443. recv_isr_5:
  444.     test    al,EDLC_SHORT or EDLC_FCS or EDLC_DRIBBLE
  445.     je    recv_isr_6
  446. ;ecp->estats.bad++;
  447.     call    rcv_fixup
  448.     jmp    recv_isr_1
  449. recv_isr_4_j_1:
  450.     jmp    recv_isr_4
  451. recv_isr_6:
  452.     test    al,EDLC_ANY
  453.     je    recv_isr_4_j_1
  454. ;Get control of the buffer
  455.     mov    al,IE_RIDE or IE_SYSBFR
  456.     setport    IE_CSR
  457.     out    dx,al
  458.  
  459.     setport    IE_RP
  460.     in    ax,dx            ;get the size.
  461.     mov    ipkt_size,ax
  462.     cmp    ax,RUNT            ;less than RUNT?
  463.     jb    recv_isr_7        ;yes.
  464.     cmp    ax,GIANT        ;greater than GIANT?
  465.     jbe    recv_isr_8        ;no.
  466. recv_isr_7:
  467.     call    count_in_err
  468. ;ecp->estats.bad++;
  469.     jmp    recv_isr_9
  470. recv_isr_8:
  471. ;Put it on the receive queue
  472.  
  473.     mov    ax,EADDR_LEN+EADDR_LEN    ;seek to the type word.
  474.     setport    IE_GP
  475.     out    dx,ax
  476.  
  477.     setport    IE_BFR
  478.     in    al,dx            ;read the type word out of the board.
  479.     mov    ah,al
  480.     in    al,dx
  481.     xchg    al,ah            ;should be in network byte order.
  482.     mov    our_type,ax
  483.     in    al,dx            ;read the type word out of the board.
  484.     mov    ah,al
  485.     in    al,dx
  486.     xchg    al,ah            ;should be in network byte order.
  487.     mov    our_type+2,ax
  488.  
  489.     mov    ax,ds            ;look up our type.
  490.     mov    es,ax
  491.     mov    di,offset our_type
  492.  
  493.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  494.     mov    ax, es:[di]
  495.     xchg    ah, al
  496.     cmp     ax, 1500
  497.     ja    BlueBookPacket
  498.     inc    di            ;set di to 802.2 header
  499.     inc    di
  500.     mov    dl, IEEE8023
  501. BlueBookPacket:
  502.  
  503.     mov    cx,ipkt_size
  504.     call    recv_find
  505.  
  506.     mov    ax,es            ;is this pointer null?
  507.     or    ax,di
  508.     je    recv_isr_9        ;yes - just free the frame.
  509.  
  510.     push    es            ;remember where the buffer pointer is.
  511.     push    di
  512.  
  513.     xor    ax,ax            ;seek to the beginning again.
  514.     loadport
  515.     setport    IE_GP
  516.     out    dx,ax
  517.  
  518.     mov    cx,ipkt_size
  519.     setport    IE_BFR
  520.  
  521.     cmp    is_186,0    ; Can we use rep insb?
  522.     je    in86        ; no - have to do it slowly.
  523.     db    0f3h, 06ch    ;masm 4.0 doesn't grok "rep insb"
  524.     jmp    short icnteven
  525. in86:
  526. ; If buffer doesn't begin on a word boundary, get the first byte
  527.     test    di,1    ; if(buf & 1){
  528.     jz    ibufeven ;
  529.     in    al,dx    ; al = in(dx);
  530.     stosb        ; *di++ = al
  531.     dec    cx    ; cx--;
  532. ibufeven:
  533.     mov    si,cx    ; size = cx;
  534.     shr    cx,1    ; cx = cnt >> 1; (convert to word count)
  535. ; Do the bulk of the buffer, a word at a time
  536.     jcxz    inobuf    ; if(cx != 0){
  537. rb:    in    al,dx    ; do { al = in(dx);
  538.     mov    ah,al
  539.     in    al,dx    ; ah = in(dx);
  540.     xchg    al,ah
  541.     stosw        ; *si++ = ax; (di is word pointer)
  542.     loop    rb    ; } while(--cx != 0);
  543. ; now check for odd trailing byte
  544. inobuf:    shr    si,1
  545.     jnc    icnteven
  546.     in    al,dx
  547.     stosb        ; *di++ = al
  548. icnteven:
  549.  
  550.     pop    si
  551.     pop    ds
  552.     assume    ds:nothing
  553.     mov    cx,ipkt_size
  554.     call    recv_copy        ;tell them that we copied it.
  555.  
  556.     mov    ax,cs            ;restore our ds.
  557.     mov    ds,ax
  558.     assume    ds:code
  559.  
  560. recv_isr_9:
  561.     mov    al,IE_RIDE or IE_RCVEDLC
  562.     loadport
  563.     setport    IE_CSR
  564.     out    dx,al
  565.     xor    al,al
  566.     setport    IE_RP
  567.     out    dx,al
  568. recv_isr_4:
  569. ;Clear any spurious interrupts
  570.     loadport
  571.     setport    EDLC_RCV
  572.     in    al,dx
  573.  
  574.     setport    EDLC_XMT
  575.     in    al,dx
  576.  
  577.     ret
  578.  
  579.  
  580. rcv_fixup:
  581.     call    count_out_err
  582.  
  583.     mov    al,IE_RIDE or IE_SYSBFR
  584.     loadport
  585.     setport    IE_CSR
  586.     out    dx,al
  587.  
  588.     mov    al,IE_RIDE or IE_RCVEDLC
  589.     setport    IE_CSR
  590.     out    dx,al
  591.  
  592.     mov    al,0
  593.     setport    IE_RP
  594.     out    dx,al
  595.  
  596.     ret
  597.  
  598.  
  599.     public    recv_exiting
  600. recv_exiting:
  601. ;called from the recv isr after interrupts have been acknowledged.
  602. ;Only ds and ax have been saved.
  603.     assume    ds:nothing
  604.     ret
  605.  
  606.  
  607. end_resident    label    byte
  608.  
  609.     public    usage_msg
  610. usage_msg    db    "usage: 3C501 [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr>",CR,LF,'$'
  611.  
  612.     public    copyright_msg
  613. copyright_msg    db    "Packet driver for the 3COM 3C501, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  614.         db    "Portions Copyright 1988 Phil Karn",CR,LF,'$'
  615.  
  616. using_186_msg    db    "Using 80[123]86 I/O instructions.",CR,LF,'$'
  617. no_3c501_msg    db    "No 3C501 found at that address.",CR,LF,'$'
  618. ether_bdcst    db    6 dup(-1)    ;ethernet broadcast address.
  619. our_address    db    6 dup(?)    ;temporarily hold our address
  620.  
  621. int_no_name    db    "Interrupt number ",'$'
  622. io_addr_name    db    "I/O port ",'$'
  623.  
  624.     extrn    set_recv_isr: near
  625.  
  626. ;enter with si -> argument string, di -> word to store.
  627. ;if there is no number, don't change the number.
  628.     extrn    get_number: near
  629.  
  630. ;enter with dx -> name of word, di -> dword to print.
  631.     extrn    print_number: near
  632.  
  633.     public    parse_args
  634. parse_args:
  635. ;exit with nc if all went well, cy otherwise.
  636.     mov    di,offset int_no
  637.     call    get_number
  638.     mov    di,offset io_addr
  639.     call    get_number
  640.     clc
  641.     ret
  642.  
  643.  
  644. no_3c501_error:
  645.     mov    dx,offset no_3c501_msg
  646.     mov    ah,9
  647.     int    21h
  648.     stc
  649.     ret
  650.  
  651.  
  652.     public    etopen
  653. etopen:
  654. ;  Initialize the Ethernet board, set receive type.
  655. ;
  656. ;  check for correct EPROM location
  657. ;
  658. ;Pulse IE_RESET
  659.     mov    al,IE_RESET
  660.     loadport
  661.     setport    IE_CSR
  662.     out    dx,al
  663.  
  664. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  665. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  666.     mov    cl,33
  667.     mov    ax,0ffffh
  668.     shl    ax,cl
  669.     jz    not_186
  670.     mov    is_186,1
  671.     mov    dx,offset using_186_msg
  672.     mov    ah,9
  673.     int    21h
  674. not_186:
  675.  
  676.     call    set_recv_isr
  677.  
  678.     push    ds
  679.     pop    es
  680.     mov    di,offset our_address
  681.     mov    cx,EADDR_LEN
  682.     call    get_address
  683.     mov    si,offset our_address
  684.     mov    cx,EADDR_LEN
  685.     call    set_address
  686.  
  687. ;See if there really is a 3c501 there.
  688.     mov    cx,EADDR_LEN
  689.     mov    si,offset our_address
  690.     mov    di,offset ether_bdcst
  691.     repe    cmpsb
  692.     jne    have_3c501        ;not broadcast address -- must be real.
  693.     jmp    no_3c501_error        ;not there -- no 3c501.
  694. have_3c501:
  695.  
  696. ;Enable DMA/interrupt request, gain control of buffer
  697.     mov    al,IE_RIDE or IE_SYSBFR
  698.     loadport
  699.     setport    IE_CSR
  700.     out    dx,al
  701.  
  702. ;Enable transmit interrupts
  703.     mov    al,EDLC_16 or EDLC_JAM
  704.     setport    EDLC_XMT
  705.     out    dx,al
  706.  
  707. ;Set up the receiver interrupts and flush status
  708.     mov    al,EDLC_MULTI or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  709.     setport    EDLC_RCV
  710.     out    dx,al
  711.     in    al,dx            ;flush status.
  712.  
  713. ;Start receiver
  714.     mov    ax,0            ;Reset read pointer
  715.     setport    IE_RP
  716.     out    dx,ax
  717.     mov    al,IE_RIDE or IE_RCVEDLC
  718.     setport    IE_CSR
  719.     out    dx,al
  720.  
  721.     mov    al, int_no        ; Get board's interrupt vector
  722.     add    al, 8
  723.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  724.     jb    set_int_num        ; No.
  725.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  726. set_int_num:
  727.     xor    ah, ah            ; Clear high byte
  728.     mov    int_num, ax        ; Set parameter_list int num.
  729.  
  730.     mov    dx,offset end_resident
  731.     clc
  732.     ret
  733.  
  734.     public    print_parameters
  735. print_parameters:
  736.     mov    di,offset int_no
  737.     mov    dx,offset int_no_name
  738.     call    print_number
  739.     mov    di,offset io_addr
  740.     mov    dx,offset io_addr_name
  741.     call    print_number
  742.     ret
  743.  
  744.  
  745. code    ends
  746.  
  747.     end
  748.