home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / packetdrivers.tar.gz / pd.tar / src / isolink.asm < prev    next >
Assembly Source File  |  1995-06-25  |  22KB  |  927 lines

  1. version    equ    3
  2. ;History:1,1
  3.  
  4. ; Copyright, 1990-1992, Russell Nelson, Crynwr Software
  5.  
  6. ;   This program is free software; you can redistribute it and/or modify
  7. ;   it under the terms of the GNU General Public License as published by
  8. ;   the Free Software Foundation, version 1.
  9. ;
  10. ;   This program is distributed in the hope that it will be useful,
  11. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ;   GNU General Public License for more details.
  14. ;
  15. ;   You should have received a copy of the GNU General Public License
  16. ;   along with this program; if not, write to the Free Software
  17. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     .286                ;the 6510 requires a 286.
  20.  
  21.     include    defs.asm
  22.  
  23. DATA_REG    equ    0ch
  24. ADDR_REG    equ    0eh
  25.     CSR0        equ    0
  26.     CSR1        equ    1
  27.     CSR2        equ    2
  28.     CSR3        equ    3
  29. RESET        equ    4
  30. CONFIG        equ    5
  31. EBASE        equ    0
  32.  
  33. DMA_8MASK_REG    equ    0Ah
  34. DMA_16MASK_REG    equ    0D4h
  35.  
  36. DMA_8MODE_REG    equ    0Bh
  37. DMA_16MODE_REG    equ    0D6h
  38.  
  39. CASCADE_MODE      equ    0C0h
  40. SET_DMA_MASK      equ    4
  41. DMA_CHANNEL_FIELD equ    3
  42.  
  43.  
  44. outport    macro    reg
  45.     push    ax
  46.     setport    ADDR_REG
  47.     mov    ax,reg
  48.     out    dx,ax
  49.     in    ax,dx            ;delay a little bit
  50.  
  51.     setport    DATA_REG
  52.     pop    ax
  53.     out    dx,ax
  54.     in    ax,dx            ;delay a little bit
  55.  
  56.     endm
  57.  
  58.  
  59. ;
  60. ;     Control and Status Register 0 (CSR0) bit definitions
  61. ;
  62. CSR0_ERR    equ     8000h    ; Error summary
  63. CSR0_BABL    equ     4000h    ; Babble transmitter timeout error
  64. CSR0_CERR    equ    2000h    ; Collision Error
  65. CSR0_MISS    equ    1000h    ; Missed packet
  66. CSR0_MERR    equ    0800h    ; Memory Error
  67. CSR0_RINT    equ    0400h    ; Reciever Interrupt
  68. CSR0_TINT       equ    0200h    ; Transmit Interrupt
  69. CSR0_IDON    equ    0100h    ; Initialization Done
  70. CSR0_INTR    equ    0080h    ; Interrupt Flag
  71. CSR0_INEA    equ    0040h    ; Interrupt Enable
  72. CSR0_RXON    equ    0020h    ; Receiver on
  73. CSR0_TXON    equ    0010h   ; Transmitter on
  74. CSR0_TDMD    equ    0008h    ; Transmit Demand
  75. CSR0_STOP    equ    0004h     ; Stop
  76. CSR0_STRT    equ    0002h    ; Start
  77. CSR0_INIT    equ    0001h    ; Initialize
  78.  
  79. ;
  80. ;     Initialization Block  Mode operation Bit Definitions.
  81. ;
  82. M_PROM        equ    8000h    ; Promiscuous Mode
  83. M_INTL        equ    0040h   ; Internal Loopback
  84. M_DRTY        equ    0020h   ; Disable Retry
  85. M_COLL        equ    0010h    ; Force Collision
  86. M_DTCR        equ    0008h    ; Disable Transmit CRC)
  87. M_LOOP        equ    0004h    ; Loopback
  88. M_DTX        equ    0002h    ; Disable the Transmitter
  89. M_DRX        equ    0001h   ; Disable the Reciever
  90.  
  91.  
  92. ;
  93. ;     Receive message descriptor bit definitions.
  94. ;
  95. RCV_OWN        equ    8000h    ; owner bit 0 = host, 1 = lance
  96. RCV_ERR        equ    4000h    ; Error Summary
  97. RCV_FRAM    equ     2000h    ; Framing Error
  98. RCV_OFLO    equ    1000h    ; Overflow Error
  99. RCV_CRC        equ    0800h    ; CRC Error
  100. RCV_BUF_ERR    equ     0400h    ; Buffer Error
  101. RCV_START    equ    0200h    ; Start of Packet
  102. RCV_END        equ    0100h    ; End of Packet
  103.  
  104.  
  105. ;
  106. ;    Transmit  message descriptor bit definitions.
  107. ;
  108. XMIT_OWN    equ    8000h    ; owner bit 0 = host, 1 = lance
  109. XMIT_ERR    equ    4000h   ; Error Summary
  110. XMIT_RETRY    equ    1000h   ; more the 1 retry needed to Xmit
  111. XMIT_1_RETRY    equ    0800h    ; one retry needed to Xmit
  112. XMIT_DEF    equ    0400h    ; Deferred
  113. XMIT_START    equ    0200h    ; Start of Packet
  114. XMIT_END    equ    0100h    ; End of Packet
  115.  
  116. ;
  117. ;    Miscellaneous Equates
  118. ;
  119.  
  120. TRANSMIT_BUF_COUNT    equ    1
  121. RECEIVE_BUF_COUNT    equ    8
  122. TRANSMIT_BUF_SIZE    equ    GIANT+2        ;dword-align.
  123. RECEIVE_BUF_SIZE    equ    GIANT+4+2    ;LANCE copies in 4 bytes of checksum, plus dword-align.
  124.  
  125. ;
  126. ;    Receive Message Descriptor
  127. ;
  128. rcv_msg_dscp struc
  129.     rmd0    dw    ?    ; Rec. Buffer Lo-Address
  130.     rmd1    dw    ?    ; Status bits / Hi-Address
  131.     rmd2    dw    ?    ; Buff Byte-length (2's Comp)
  132.     rmd3    dw    ?    ; Receive message length
  133. rcv_msg_dscp ends
  134.  
  135.  
  136. ;
  137. ;    Transmit Message Descriptor
  138. ;
  139. xmit_msg_dscp struc
  140.     tmd0    dw    ?    ; Xmit Buffer Lo-Address
  141.     tmd1    dw    ?    ; Status bits / Hi-Address
  142.     tmd2     dw    ?    ; Buff Byte-length (2's Comp)
  143.     tmd3    dw    ?    ; Buffer Status bits & TDR value
  144. xmit_msg_dscp ends
  145.  
  146. code    segment    para public
  147.     assume    cs:code, ds:code
  148.  
  149.     public    int_no
  150. int_no    db    10,0,0,0        ;must be four bytes long for get_number.
  151. io_addr    dw    -1,-1
  152. dma_no    db    0,0,0,0            ;default is zero.
  153.  
  154.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  155. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  156. driver_type     db      5               ;from the packet spec
  157. driver_name     db      'ISOLINK',0     ;name of the driver.
  158. driver_function    db    2        ;basic, extended
  159. parameter_list    label    byte
  160.     db    1    ;major rev of packet driver
  161.     db    9    ;minor rev of packet driver
  162.     db    14    ;length of parameter list
  163.     db    EADDR_LEN    ;length of MAC-layer address
  164.     dw    GIANT    ;MTU, including MAC headers
  165.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  166.     dw    RECEIVE_BUF_COUNT-1    ;(# of back-to-back MTU rcvs) - 1
  167.     dw    TRANSMIT_BUF_COUNT-1    ;(# of successive xmits) - 1
  168. int_num    dw    0    ;Interrupt # to hook for post-EOI
  169.             ;processing, 0 == none,
  170.  
  171.     extrn    sys_features: byte
  172.  
  173.     public    rcv_modes
  174. rcv_modes    dw    7        ;number of receive modes in our table.
  175.         dw    0               ;There is no mode zero
  176.         dw    rcv_mode_1
  177.         dw    0        ;only ours.
  178.         dw    rcv_mode_3    ;ours plus broadcast
  179.         dw    0        ;some multicasts
  180.         dw    rcv_mode_5    ;all multicasts
  181.         dw    rcv_mode_6    ;all packets
  182.  
  183. ;
  184. ;the LANCE requires that the descriptor pointers be on a qword boundary.
  185. ;
  186.     align    8
  187.  
  188. transmit_dscps    xmit_msg_dscp    TRANSMIT_BUF_COUNT dup(<>)
  189. receive_dscps    rcv_msg_dscp    RECEIVE_BUF_COUNT dup(<>)
  190.  
  191. save_csr1    dw    ?
  192. save_csr2    dw    ?
  193.  
  194. transmit_head    dw    transmit_dscps    ;->next packet to be filled by host.
  195. receive_head    dw    receive_dscps    ;->next packet to be filled by LANCE.
  196.  
  197. ;
  198. ;      LANCE Initialization Block
  199. ;
  200.     align    2
  201. init_block        label    byte
  202. init_mode        dw    0
  203. init_addr        db    EADDR_LEN dup(?)    ; Our Ethernet address
  204. init_filter        db    8 dup(0)    ;Multicast filter.
  205. init_receive        dw    ?,?        ;Receive Ring Pointer.
  206. init_transmit          dw    ?,?          ;Transmit Ring Pointer.
  207.  
  208.     public bad_command_intercept
  209. bad_command_intercept:
  210. ;called with ah=command, unknown to the skeleton.
  211. ;exit with nc if okay, cy, dh=error if not.
  212.     mov    dh,BAD_COMMAND
  213.     stc
  214.     ret
  215.  
  216.     public    as_send_pkt
  217. ; The Asynchronous Transmit Packet routine.
  218. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  219. ;   interrupts possibly enabled.
  220. ; Exit with nc if ok, or else cy if error, dh set to error number.
  221. ;   es:di and interrupt enable flag preserved on exit.
  222. as_send_pkt:
  223.     ret
  224.  
  225.     public    drop_pkt
  226. ; Drop a packet from the queue.
  227. ; Enter with es:di -> iocb.
  228. drop_pkt:
  229.     assume    ds:nothing
  230.     ret
  231.  
  232.     public    xmit
  233. ; Process a transmit interrupt with the least possible latency to achieve
  234. ;   back-to-back packet transmissions.
  235. ; May only use ax and dx.
  236. xmit:
  237.     assume    ds:nothing
  238.     ret
  239.  
  240.  
  241.     public    send_pkt
  242. send_pkt:
  243. ;enter with ds:si -> packet, cx = packet length.
  244. ;exit with nc if ok, or else cy if error, dh set to error number.
  245.     assume    ds:nothing
  246.  
  247.     cmp    cx,GIANT
  248.     ja    send_err
  249.     xor    bx,bx
  250.  
  251.     mov    ax,18
  252.     call    set_timeout
  253. send_pkt_1:
  254.     test    transmit_dscps[bx].tmd1,XMIT_OWN    ;Did the lance chip give it back?
  255.     je    send_pkt_2
  256.     call    do_timeout
  257.     jne    send_pkt_1
  258.     mov    dh,CANT_SEND
  259.     stc
  260.     ret
  261. send_err:
  262.     mov    dh,NO_SPACE
  263.     stc
  264.     ret
  265. send_pkt_2:
  266. ;reset error indications.
  267.     and    transmit_dscps[bx].tmd1,not (XMIT_ERR or XMIT_DEF or XMIT_1_RETRY or XMIT_RETRY)    ;Did the lance chip give it back?
  268.     mov    transmit_dscps[bx].tmd3,0    ;reset all error bits.
  269.  
  270.     mov    ax,cx            ;store the count.
  271.     cmp    ax,RUNT            ; minimum length for Ether
  272.     ja    oklen
  273.     mov    ax,RUNT            ; make sure size at least RUNT
  274. oklen:
  275.     neg    ax
  276.     mov    transmit_dscps[bx].tmd2,ax
  277.  
  278.     mov    ax,transmit_dscps[bx].tmd0    ;store the packet.
  279.     mov    dx,transmit_dscps[bx].tmd1
  280.     call    phys_to_segmoffs
  281.     shr    cx,1
  282.     rep    movsw
  283.     jnc    send_pkt_3
  284.     movsb
  285. send_pkt_3:
  286.  
  287.     or    transmit_dscps[bx].tmd1,XMIT_OWN    ;give it to the lance chip.
  288.  
  289. ;Inform LANCE that it should poll for a packet.
  290.     loadport
  291.     mov    ax,CSR0_INEA or CSR0_TDMD
  292.     outport    CSR0
  293.     clc
  294.     ret
  295.  
  296.  
  297.     public    set_address
  298. set_address:
  299. ;enter with ds:si -> Ethernet address, CX = length of address.
  300. ;exit with nc if okay, or cy, dh=error if any errors.
  301.     assume    ds:nothing
  302.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  303.     je    set_address_4
  304.     mov    dh,BAD_ADDRESS
  305.     stc
  306.     jmp    short set_address_done
  307. set_address_4:
  308.  
  309.     movseg    es,cs
  310.     mov    di,offset init_addr
  311.     rep    movsb
  312.     call    initialize        ;initialize with our new address.
  313.  
  314. set_address_okay:
  315.     mov    cx,EADDR_LEN        ;return their address length.
  316.     clc
  317. set_address_done:
  318.     movseg    ds,cs
  319.     assume    ds:code
  320.     ret
  321.  
  322.  
  323. rcv_mode_1:
  324.     mov    ax,M_DRX        ;disable the receiver
  325.     jmp    initialize_nomulti
  326. rcv_mode_3:
  327.     xor    ax,ax            ;don't accept any multicast frames.    
  328.     call    initialize_multi
  329.     mov    ax,0            ;non-promiscuous mode
  330.     jmp    short initialize_nomulti
  331. rcv_mode_5:
  332.     mov    ax,-1            ;accept any multicast frames.
  333.     call    initialize_multi
  334.     mov    ax,0            ;non-promiscuous mode
  335.     jmp    short initialize_nomulti
  336. rcv_mode_6:
  337.     mov    ax,M_PROM        ;promiscuous mode
  338. initialize_nomulti:
  339.     mov    init_mode,ax
  340.  
  341. initialize:
  342.     loadport
  343.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  344.     outport    CSR0
  345.  
  346.     mov    ax,0            ;write the bus config register.
  347.     outport    CSR3
  348.  
  349.     mov    ax,save_csr1        ;write the low word.
  350.     outport    CSR1
  351.  
  352.     mov    ax,save_csr2        ;write the high word.
  353.     outport    CSR2
  354.  
  355.     mov    ax,CSR0_INEA or CSR0_STRT or CSR0_INIT    ;reinit and restart.
  356.     outport    CSR0
  357.  
  358.     setport    DATA_REG
  359.  
  360.     mov    ax,36            ;wait one second for the board
  361.     call    set_timeout        ;  to timeout.
  362. initialize_1:
  363.     in    ax,dx
  364.     test    ax,CSR0_IDON
  365.     jne    initialize_2
  366.     call    do_timeout
  367.     jne    initialize_1
  368.     stc
  369.     ret
  370. initialize_2:
  371.     clc
  372.     ret
  373.  
  374.  
  375. initialize_multi:
  376. ;enter with ax = value for all multicast hash bits.
  377.     movseg    es,cs
  378.     mov    di,offset init_filter
  379.     mov    cx,8/2
  380.     rep    stosw
  381.     ret
  382.  
  383.  
  384.     public    set_multicast_list
  385. set_multicast_list:
  386. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  387. ;  cx = number of bytes.
  388. ;return nc if we set all of them, or cy,dh=error if we didn't.
  389.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  390.     stc
  391.     ret
  392.  
  393.  
  394.     public    terminate
  395. terminate:
  396.     call    rcv_mode_1        ;don't receive any apckets.
  397.  
  398. ;This routine will remove the (host) DMA controller from
  399. ;cascade mode of operation.
  400.     mov    al,dma_no
  401.     or    al,SET_DMA_MASK
  402.     cmp    dma_no,4        ;If channel 5 or 6,
  403.     ja    terminate_16        ;  use sixteen bit dma.
  404. terminate_8:
  405.     out    DMA_8MASK_REG,al
  406.     jmp    short terminate_done
  407. terminate_16:
  408.     out    DMA_16MASK_REG,al
  409. terminate_done:
  410.     ret
  411.  
  412.     public    reset_interface
  413. reset_interface:
  414. ;reset the interface.
  415.     assume    ds:code
  416.     ret
  417.  
  418.  
  419. ;called when we want to determine what to do with a received packet.
  420. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  421.     extrn    recv_find: near
  422.  
  423. ;called after we have copied the packet into the buffer.
  424. ;enter with ds:si ->the packet, cx = length of the packet.
  425.     extrn    recv_copy: near
  426.  
  427. ;call this routine to schedule a subroutine that gets run after the
  428. ;recv_isr.  This is done by stuffing routine's address in place
  429. ;of the recv_isr iret's address.  This routine should push the flags when it
  430. ;is entered, and should jump to recv_exiting_exit to leave.
  431. ;enter with ax = address of routine to run.
  432.     extrn    schedule_exiting: near
  433.  
  434. ;recv_exiting jumps here to exit, after pushing the flags.
  435.     extrn    recv_exiting_exit: near
  436.  
  437. ;enter with dx = amount of memory desired.
  438. ;exit with nc, dx -> that memory, or cy if there isn't enough memory.
  439.     extrn    malloc: near
  440.  
  441.     extrn    count_in_err: near
  442.     extrn    count_out_err: near
  443.  
  444. LANCE_ISR_ACKNOWLEDGE equ (CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  445.  
  446.     public    recv
  447. recv:
  448. ;called from the recv isr.  All registers have been saved, and ds=cs.
  449. ;Upon exit, the interrupt will be acknowledged.
  450.     assume    ds:code
  451.  
  452.     loadport
  453.     setport    ADDR_REG
  454.     mov    ax,CSR0
  455.     out    dx,ax
  456.     in    ax,dx
  457.     setport    DATA_REG
  458.     in    ax,dx
  459.     mov    bx,ax            ;make a copy.
  460.  
  461. ; Acknowledge the Interrupt from the controller, but disable further
  462. ; controller Interrupts until we service the current interrupt.
  463. ;
  464. ;(CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  465. ;
  466.     and    ax,not LANCE_ISR_ACKNOWLEDGE
  467.     out    dx,ax
  468.     in    ax,dx        ; follow all writes by a read
  469.  
  470.     test    bx,CSR0_RINT        ;receive interrupt?
  471.     je    recv_done_1        ;no, we're done.
  472.  
  473.     mov    bx,receive_head
  474.  
  475. recv_search:
  476.     test    code:[bx].rmd1,RCV_OWN    ;do we own this buffer?
  477.     je    recv_own        ;yes - process it.
  478.     call    inc_recv_ring        ;go to the next one.
  479.     cmp    bx,receive_head        ;did we get back to the beginning?
  480.     jne    recv_search        ;not yet.
  481. recv_done_1:
  482.     jmp    short recv_done        ;yes -- spurious interrupt!
  483. recv_own:
  484.     test    code:[bx].rmd1,RCV_ERR    ;Any errors in this buffer?
  485.     jne    recv_err        ;yes -- ignore this packet.
  486.  
  487.     mov    ax,code:[bx].rmd0    ;fetch the packet.
  488.     mov    dx,code:[bx].rmd1
  489.     call    phys_to_segmoffs
  490.  
  491.     push    es
  492.     push    di
  493.     push    bx
  494.  
  495.     mov    cx,code:[bx].rmd3
  496.     and    cx,0fffh        ;strip off the reserved bits
  497.     sub    cx,4            ;leave the CRC behind.
  498.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  499.                     ;  point to the packet type.
  500.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  501.     mov    ax, es:[di]
  502.     xchg    ah, al
  503.     cmp     ax, 1500
  504.     ja    BlueBookPacket
  505.     inc    di            ;set di to 802.2 header
  506.     inc    di
  507.     mov    dl, IEEE8023
  508. BlueBookPacket:
  509.     push    cx
  510.     call    recv_find
  511.     pop    cx
  512.  
  513.     pop    bx
  514.     pop    si
  515.     pop    ds
  516.     assume    ds:nothing
  517.  
  518.     mov    ax,es            ;is this pointer null?
  519.     or    ax,di
  520.     je    recv_free        ;yes - just free the frame.
  521.  
  522.     push    es
  523.     push    di
  524.     push    cx
  525.     shr    cx,1
  526.     rep    movsw
  527.     jnc    rec_pkt_3
  528.     movsb
  529. rec_pkt_3:
  530.     pop    cx
  531.     pop    si
  532.     pop    ds
  533.     assume    ds:nothing
  534.  
  535.     call    recv_copy
  536.  
  537.     jmp    short recv_free
  538.  
  539. recv_err:
  540.     call    count_in_err
  541. recv_free:
  542.     movseg    ds,cs
  543.     assume    ds:code
  544.  
  545. ;clear any error bits.
  546.     and    code:[bx].rmd1,not (RCV_ERR or RCV_FRAM or RCV_OFLO or RCV_CRC or RCV_BUF_ERR)
  547.     or    code:[bx].rmd1,RCV_OWN    ;give it back to the lance.
  548.     call    inc_recv_ring        ;go to the next one.
  549.     test    code:[bx].rmd1,RCV_OWN    ;Do we own this one?
  550.     je    recv_own
  551.     mov    receive_head,bx        ;remember where the next one starts.
  552. recv_done:
  553.     loadport            ;enable interrupts again.
  554.     setport    DATA_REG
  555.     mov    ax,CSR0_INEA
  556.     out    dx,ax
  557.     ret
  558.  
  559.  
  560. inc_recv_ring:
  561. ;advance bx to the next receive ring descriptor.
  562.     assume    ds:nothing
  563.     add    bx,(size rcv_msg_dscp)
  564.     cmp    bx,offset receive_dscps + RECEIVE_BUF_COUNT * (size rcv_msg_dscp)
  565.     jb    inc_recv_ring_1
  566.     mov    bx,offset receive_dscps
  567. inc_recv_ring_1:
  568.     ret
  569.  
  570.  
  571. phys_to_segmoffs:
  572. ;enter with dx:ax as the physical address of the buffer,
  573. ;exit with es:di -> buffer.
  574.     shl    dx,16-4            ;move the upper four bits into position.
  575.     mov    di,ax            ;now get the low 12 bits of the segment.
  576.     shr    di,4
  577.     or    dx,di            ;combine them.
  578.     mov    es,dx
  579.     mov    di,ax
  580.     and    di,0fh            ;now compute the offset.
  581.     ret
  582.  
  583.     include    timeout.asm
  584.  
  585.     public    timer_isr
  586. timer_isr:
  587. ;if the first instruction is an iret, then the timer is not hooked
  588.     iret
  589.  
  590. ;any code after this will not be kept.  Buffers used by the program, if any,
  591. ;are allocated from the memory between end_resident and end_free_mem.
  592.     public end_resident,end_free_mem
  593.     align    4            ;just for efficiency's sake.
  594. end_resident    label    byte
  595.     db    (RECEIVE_BUF_COUNT*RECEIVE_BUF_SIZE) + (TRANSMIT_BUF_COUNT*TRANSMIT_BUF_SIZE) dup(?)
  596. end_free_mem    label    byte
  597.  
  598.     public    usage_msg
  599. usage_msg    db    "usage: isolink [options] <packet_int_no> <hardware_irq> <dma_no> <io_addr>",CR,LF,'$'
  600. no_board_msg    db    "No isolink detected.",CR,LF,'$'
  601. io_addr_funny_msg    label    byte
  602.         db    "No isolink detected, continuing anyway.",CR,LF,'$'
  603. bad_reset_msg    db    "Unable to reset the isolink.",CR,LF,'$'
  604. bad_init_msg    db    "Unable to initialize the isolink.",CR,LF,'$'
  605. no_memory_msg    db    "Unable to allocate enough memory, look at end_resident in isolink.ASM",CR,LF,'$'
  606.  
  607.     public    copyright_msg
  608. copyright_msg    db    "Packet driver for a BICC Isolink, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  609.         db    '$'
  610.  
  611. int_no_name    db    "Interrupt number ",'$'
  612. dma_no_name    db    "DMA number ",'$'
  613. io_addr_name    db    "I/O port ",'$'
  614.  
  615.     extrn    set_recv_isr: near
  616.     extrn    maskint: near
  617.  
  618. ;enter with si -> argument string, di -> dword to store.
  619. ;if there is no number, don't change the number.
  620.     extrn    get_number: near
  621.  
  622. ;enter with dx -> name of word, di -> dword to print.
  623.     extrn    print_number: near
  624.  
  625. ;-> the assigned Ethernet address of the card.
  626.     extrn    rom_address: byte
  627.  
  628. PS2IO           dw      08280h, 09250h, 0a390h, 0b1d0h
  629. PS2INT          db      9, 10, 11, 15, 3, 4, 5, 0
  630.  
  631.     public    parse_args
  632. parse_args:
  633. ;exit with nc if all went well, cy otherwise.
  634.     assume    ds:code
  635. ; If we run on a PS/2, read the default configuration from the POS regs
  636.  
  637.     test    sys_features,SYS_MCA
  638.     jnz    do_mc_defaults
  639.     jmp    parse_args_l
  640. do_mc_defaults:
  641.  
  642.                 mov     bx,08h                  ;1st slot
  643. pa_slot_l:
  644.                 mov     dx,96h
  645.                 mov     ax,bx
  646.                 out     dx,al                   ;put in setup mode
  647.                 mov     dx,101h
  648.                 in      al,dx
  649.                 xchg    al,ah                   ;high id byte
  650.                 dec     dx
  651.                 in      al,dx                   ;low id byte
  652.                 cmp     ax,0808h                ;ISOLINK card?
  653.                 je      pa_found_iso            ;yes...
  654.                 inc     bx                      ;next slot
  655.                 cmp     bx,0fh                  ;too far?
  656.                 jna     pa_slot_l               ;no, try next
  657.                 mov     dx,96h
  658.                 xor     al,al
  659.                 out     dx,al                   ;exit setup mode
  660.                 jmp     parse_args_l
  661.  
  662. pa_found_iso:
  663.                 mov     dx,102h
  664.                 in      al,dx                   ;get I/O address code
  665.                 xor     ah,ah
  666.                 and     al,6
  667.                 mov     bx,ax
  668.                 mov     ax,PS2IO[bx]            ;I/O port address
  669.                 mov     io_addr,ax
  670.  
  671.                 mov     dx,104h
  672.                 in      al,dx
  673.                 xor     ah,ah
  674.                 shr     al,5                    ;isolate interrupt bits
  675.                 mov     bx,ax
  676.                 mov     al,PS2INT[bx]           ;interrupt number
  677.                 mov     int_no,al
  678.  
  679.  
  680. parse_args_l:
  681.     mov    di,offset int_no
  682.     call    get_number
  683.     mov    di,offset dma_no
  684.     call    get_number
  685.     mov    di,offset io_addr
  686.     call    get_number
  687.     clc
  688.     ret
  689.  
  690.  
  691.     public    etopen
  692. etopen:
  693.     assume    ds:code
  694.  
  695.     cmp    io_addr,-1        ;Did they ask for auto-detect?
  696.     je    find_board
  697.  
  698.     call    detect_board        ;no, just verify its existance.
  699.     je    find_board_found
  700.  
  701.     mov    dx,offset io_addr_funny_msg
  702.     mov    ah,9
  703.     int    21h
  704.  
  705.     jmp    find_board_found
  706.  
  707. find_board:
  708.     mov    io_addr,200h        ;Search for the Ethernet address.
  709.     mov    io_addr+2,0
  710. find_board_0:
  711.     call    detect_board
  712.     je    find_board_found
  713. find_board_again:
  714.     add    io_addr,10h        ;not at this port, try another.
  715.     cmp    io_addr,3f0h
  716.     jbe    find_board_0
  717.  
  718.     mov    dx,offset no_board_msg    ;Tell them that we can't find it.
  719.     stc
  720.     ret
  721. no_memory:
  722.     mov    dx,offset no_memory_msg
  723.     stc
  724.     ret
  725.  
  726. find_board_found:
  727.  
  728. ;This routine will put the (host) DMA controller into
  729. ;cascade mode of operation.
  730.  
  731.     mov    al,dma_no
  732.     and    al,DMA_CHANNEL_FIELD
  733.     cmp    al,4            ;If channel 5, 6 or 7
  734.     ja    dma_16            ;  use sixteen bit dma.
  735. dma_8:
  736.     or    al,CASCADE_MODE
  737.     out    DMA_8MODE_REG,al
  738.     and    al,DMA_CHANNEL_FIELD
  739.     out    DMA_8MASK_REG,al
  740.     jmp    short dma_done
  741. dma_16:
  742.     and    al,DMA_CHANNEL_FIELD
  743.     out    DMA_16MASK_REG,al
  744.     or    al,CASCADE_MODE
  745.     out    DMA_16MODE_REG,al
  746. dma_done:
  747.  
  748.     mov    al, int_no        ; Get board's interrupt vector
  749.     add    al, 8
  750.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  751.     jb    set_int_num        ; No.
  752.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  753. set_int_num:
  754.     xor    ah, ah            ; Clear high byte
  755.     mov    int_num, ax        ; Set parameter_list int num.
  756.  
  757.     mov    al,int_no
  758.     call    maskint            ;disable these interrupts.
  759.  
  760. ;set up transmit descriptor ring.
  761.     movseg    es,ds
  762.     mov    cx,TRANSMIT_BUF_COUNT
  763.     mov    bx,offset transmit_dscps
  764. setup_transmit:
  765.     mov    dx,TRANSMIT_BUF_SIZE
  766.     call    malloc
  767.     jc    no_memory
  768.  
  769.     mov    di,dx
  770.     call    segmoffs_to_phys
  771.  
  772.     or    dx,XMIT_START or XMIT_END
  773.     mov    [bx].tmd0,ax        ;points to the buffer.
  774.     mov    [bx].tmd1,dx
  775.  
  776.     add    bx,(size xmit_msg_dscp)
  777.     loop    setup_transmit
  778.  
  779. ;set up receive descriptor ring.
  780.     mov    cx,RECEIVE_BUF_COUNT
  781.     mov    bx,offset receive_dscps
  782. setup_receive:
  783.     mov    dx,RECEIVE_BUF_SIZE
  784.     call    malloc
  785.     jc    no_memory
  786.  
  787.     mov    di,dx
  788.     call    segmoffs_to_phys
  789.  
  790.     or    dx,RCV_OWN
  791.     mov    [bx].rmd0,ax        ;points to the buffer.
  792.     mov    [bx].rmd1,dx
  793.  
  794.     mov    [bx].rmd2,-RECEIVE_BUF_SIZE
  795.     mov    [bx].rmd3,0
  796.  
  797.   if 0
  798.     push    di            ;initialize the buffers to 55aa.
  799.     push    cx
  800.     mov    cx,RECEIVE_BUF_SIZE/2
  801.     mov    ax,55aah
  802.     rep    stosw
  803.     pop    cx
  804.     pop    di
  805.   endif
  806.  
  807.     add    bx,(size rcv_msg_dscp)
  808.     loop    setup_receive
  809.  
  810. ;initialize the board.
  811.     mov    cx,EADDR_LEN        ;get our address.
  812.     mov    di,offset rom_address
  813.     loadport            ; Get our Ethernet address base.
  814.     setport    EBASE
  815. get_address_1:
  816.     insb                ; get a byte of the eprom address
  817.     add    dx,2            ; next register
  818.     loop    get_address_1        ; go back for rest
  819.  
  820.     mov    si,offset rom_address    ; copy it to the init table.
  821.     mov    di,offset init_addr
  822.     mov    cx,EADDR_LEN
  823.     rep    movsb
  824.  
  825.     mov    cx,RECEIVE_BUF_COUNT
  826.     call    compute_log2
  827.  
  828.     mov    di,offset receive_dscps
  829.     call    segmoffs_to_phys
  830.     or    dx,cx            ;include the buffer size bits.
  831.     mov    init_receive[0],ax
  832.     mov    init_receive[2],dx
  833.  
  834.     mov    cx,TRANSMIT_BUF_COUNT
  835.     call    compute_log2
  836.  
  837.     mov    di,offset transmit_dscps
  838.     call    segmoffs_to_phys
  839.     or    dx,cx            ;include the buffer size bits.
  840.     mov    init_transmit[0],ax
  841.     mov    init_transmit[2],dx
  842.  
  843.     mov    di,offset init_block    ;now tell the board where the init
  844.     call    segmoffs_to_phys    ;  block is.
  845.     mov    save_csr1,ax
  846.     mov    save_csr2,dx
  847.  
  848.     call    rcv_mode_3
  849.     jnc    init_ok
  850.  
  851.     mov    dx,offset bad_init_msg
  852.     stc
  853.     ret
  854.  
  855. init_ok:
  856. ;
  857. ; Now hook in our interrupt
  858. ;
  859.     call    set_recv_isr
  860.  
  861.     clc
  862.     ret
  863.  
  864.     public    print_parameters
  865. print_parameters:
  866. ;echo our command-line parameters
  867.     mov    di,offset int_no
  868.     mov    dx,offset int_no_name
  869.     call    print_number
  870.     mov    di,offset dma_no
  871.     mov    dx,offset dma_no_name
  872.     call    print_number
  873.     mov    di,offset io_addr
  874.     mov    dx,offset io_addr_name
  875.     call    print_number
  876.     ret
  877.  
  878. compute_log2:
  879. ;enter with cx = number of buffers.
  880. ;exit with cx = log2(number of buffers) << 13.
  881.     mov    ax,-1
  882. compute_log2_1:
  883.     inc    ax
  884.     shr    cx,1
  885.     jne    compute_log2_1
  886.     shl    ax,13
  887.     mov    cx,ax
  888.     ret
  889.  
  890.  
  891. segmoffs_to_phys:
  892. ;enter with es:di -> buffer.
  893. ;exit with dx:ax as the physical address of the buffer,
  894.  
  895.     mov    dx,es            ;get the high 4 bits of the segment,
  896.     shr    dx,16-4
  897.     mov    ax,es            ;and the low 12 bits of the segment.
  898.     shl    ax,4
  899.     add    ax,di            ;add in the offset.
  900.     adc    dx,0
  901.     ret
  902.  
  903.  
  904. detect_board:
  905. ;test to see if a board is located at io_addr.
  906. ;return nz if not.
  907.     loadport
  908.     setport    EBASE
  909.     in    al,dx            ;Check for BICC's prefix word.
  910.     cmp    al,8
  911.     jne    detect_board_exit
  912.  
  913.     setport    EBASE+2
  914.     in    al,dx
  915.     cmp    al,00
  916.     jne    detect_board_exit
  917.  
  918.     setport    EBASE+4
  919.     in    al,dx
  920.     cmp    al,4eh
  921. detect_board_exit:
  922.     ret
  923.  
  924. code    ends
  925.  
  926.     end
  927.