home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / packetdrivers.tar.gz / pd.tar / src / 3c501.asm < prev    next >
Assembly Source File  |  1995-06-25  |  15KB  |  685 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.     extrn    is_186: byte        ;=0 if 808[68], =1 if 80[123]86.
  113. our_type    dw    ?,?
  114.  
  115.     include    io8.asm
  116.  
  117.     public bad_command_intercept
  118. bad_command_intercept:
  119. ;called with ah=command, unknown to the skeleton.
  120. ;exit with nc if okay, cy, dh=error if not.
  121.     mov    dh,BAD_COMMAND
  122.     stc
  123.     ret
  124.  
  125.     public    as_send_pkt
  126. ; The Asynchronous Transmit Packet routine.
  127. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  128. ;   interrupts possibly enabled.
  129. ; Exit with nc if ok, or else cy if error, dh set to error number.
  130. ;   es:di and interrupt enable flag preserved on exit.
  131. as_send_pkt:
  132.     ret
  133.  
  134.     public    drop_pkt
  135. ; Drop a packet from the queue.
  136. ; Enter with es:di -> iocb.
  137. drop_pkt:
  138.     assume    ds:nothing
  139.     ret
  140.  
  141.     public    xmit
  142. ; Process a transmit interrupt with the least possible latency to achieve
  143. ;   back-to-back packet transmissions.
  144. ; May only use ax and dx.
  145. xmit:
  146.     assume    ds:nothing
  147.     ret
  148.  
  149.  
  150.     public    send_pkt
  151. send_pkt:
  152. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  153. ;  (only if the high-performance bit is set in driver_function)
  154. ;enter with ds:si -> packet, cx = packet length.
  155. ;exit with nc if ok, or else cy if error, dh set to error number.
  156.     assume    ds:nothing
  157.     cmp    cx,GIANT        ; Is this packet too large?
  158.     ja    send_pkt_toobig
  159.  
  160.     cmp    cx,RUNT        ; minimum length for Ether
  161.     jae    oklen
  162.     mov    cx,RUNT        ; make sure size at least RUNT
  163. oklen:
  164.     inc    cx            ;round size up to next even number.
  165.     and    cx,not 1
  166.  
  167. ;Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  168. ;only in the transmit mode, hence the initial check.
  169.  
  170.     loadport
  171.     setport    IE_CSR
  172.     in    al,dx
  173.     and    al,IE_BUFCTL
  174.     cmp    al,IE_XMTEDLC
  175.     jne    send_pkt_2
  176.  
  177.     mov    bx,20000        ;try this many times.
  178. send_pkt_3:
  179.     in    al,dx            ;if not busy, exit.
  180.     and    al,IE_XMTBSY
  181.     je    send_pkt_2
  182.     dec    bx
  183.     jne    send_pkt_3
  184.     mov    dh,CANT_SEND        ;timed out, can't send.
  185.     stc
  186.     ret
  187. send_pkt_toobig:
  188.     mov    dh,NO_SPACE
  189.     stc
  190.     ret
  191. send_pkt_2:
  192.  
  193. ;Get control of the board buffer and disable receiver
  194.     mov    al,IE_RIDE or IE_SYSBFR
  195.     setport    IE_CSR
  196.     out    dx,al
  197.  
  198. ;Point GP at beginning of packet
  199.     mov    ax,BFRSIZ
  200.     sub    ax,cx
  201.     setport    IE_GP
  202.     out    dx,ax
  203.  
  204.     setport    IE_BFR
  205.  
  206.     mov    opkt_size,cx    ; opkt_size = cx;
  207.     call    repoutsb
  208.  
  209. ;Start transmitter
  210. ;Point GP at beginning of packet
  211.     mov    ax,BFRSIZ
  212.     sub    ax,opkt_size
  213.     setport    IE_GP
  214.     out    dx,ax
  215.  
  216.     mov    al,IE_RIDE or IE_XMTEDLC
  217.     setport    IE_CSR
  218.     out    dx,al
  219.  
  220.   if 1
  221.     mov    bx,20000        ;try this many times.
  222. send_pkt_4:
  223.     in    al,dx            ;if not busy, exit.
  224.     and    al,IE_XMTBSY
  225.     je    send_pkt_5
  226.     dec    bx
  227.     jne    send_pkt_4
  228.     mov    dh,CANT_SEND        ;timed out, can't send.
  229.     stc
  230.     ret
  231. send_pkt_5:
  232.  
  233.   endif
  234.  
  235.     clc
  236.     ret
  237.  
  238.  
  239. ;Set Ethernet address on controller
  240.     public    set_address
  241. set_address:
  242.     assume    ds:nothing
  243. ;enter with ds:si -> Ethernet address, CX = length of address.
  244. ;exit with nc if okay, or cy, dh=error if any errors.
  245. ;
  246.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  247.     je    set_address_4
  248.     mov    dh,BAD_ADDRESS
  249.     stc
  250.     jmp    short set_address_done
  251. set_address_4:
  252.  
  253.     loadport
  254.     setport    EDLC_ADDR
  255. set_address_1:
  256.     lodsb
  257.     out    dx,al
  258.     inc    dx
  259.     loop    set_address_1
  260. set_address_okay:
  261.     mov    cx,EADDR_LEN        ;return their address length.
  262.     clc
  263. set_address_done:
  264.     movseg    ds,cs
  265.     assume    ds:code
  266.     ret
  267.  
  268.  
  269. rcv_mode_1:
  270. ;Set up the receiver interrupts and flush status
  271.     mov    al,EDLC_NONE
  272.     loadport
  273.     setport    EDLC_RCV
  274.     out    dx,al
  275.     in    al,dx            ;flush status.
  276.  
  277.     ret
  278.  
  279.  
  280. rcv_mode_3:
  281. ;Set up the receiver interrupts and flush status
  282.     mov    al,EDLC_BROAD or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  283.     loadport
  284.     setport    EDLC_RCV
  285.     out    dx,al
  286.     in    al,dx            ;flush status.
  287.  
  288.     ret
  289.  
  290.  
  291. rcv_mode_5:
  292. ;Set up the receiver interrupts and flush status
  293.     mov    al,EDLC_MULTI or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  294.     loadport
  295.     setport    EDLC_RCV
  296.     out    dx,al
  297.     in    al,dx            ;flush status.
  298.  
  299.     ret
  300.  
  301.  
  302. rcv_mode_6:
  303. ;Set up the receiver interrupts and flush status
  304.     mov    al,EDLC_ALL or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  305.     loadport
  306.     setport    EDLC_RCV
  307.     out    dx,al
  308.     in    al,dx            ;flush status.
  309.  
  310.     ret
  311.  
  312.  
  313.     public    set_multicast_list
  314. set_multicast_list:
  315. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  316. ;  cx = number of bytes.
  317. ;return nc if we set all of them, or cy,dh=error if we didn't.
  318.     mov    dh,NO_MULTICAST
  319.     stc
  320.     ret
  321.  
  322.  
  323.     public    terminate
  324. terminate:
  325. ;Pulse IE_RESET
  326.     mov    al,IE_RESET
  327.     loadport
  328.     setport    IE_CSR
  329.     out    dx,al
  330.     mov    al,0
  331.     out    dx,al
  332.  
  333.     ret
  334.  
  335.     public    reset_interface
  336. reset_interface:
  337. ;reset the interface.
  338. ;we don't do anything.
  339.     ret
  340.  
  341.  
  342. ;called when we want to determine what to do with a received packet.
  343. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  344.     extrn    recv_find: near
  345.  
  346. ;called after we have copied the packet into the buffer.
  347. ;enter with ds:si ->the packet, cx = length of the packet.
  348.     extrn    recv_copy: near
  349.  
  350. ;call this routine to schedule a subroutine that gets run after the
  351. ;recv_isr.  This is done by stuffing routine's address in place
  352. ;of the recv_isr iret's address.  This routine should push the flags when it
  353. ;is entered, and should jump to recv_exiting_exit to leave.
  354. ;enter with ax = address of routine to run.
  355.     extrn    schedule_exiting: near
  356.  
  357. ;recv_exiting jumps here to exit, after pushing the flags.
  358.     extrn    recv_exiting_exit: near
  359.  
  360.     extrn    count_in_err: near
  361.     extrn    count_out_err: near
  362.  
  363.     public    recv
  364. recv:
  365. ;called from the recv isr.  All registers have been saved, and ds=cs.
  366. ;Upon exit, the interrupt will be acknowledged.
  367.     assume    ds:code
  368.  
  369. ;Check for transmit jam
  370.  
  371.     loadport
  372.     setport    IE_CSR
  373.     in    al,dx
  374.     and    al,IE_XMTBSY
  375.     jne    recv_isr_1
  376.  
  377.     setport    EDLC_XMT
  378.     in    al,dx
  379.     test    al,EDLC_16
  380.     je    recv_isr_2
  381. ;ecp->estats.jam16++;
  382.     call    rcv_fixup
  383.     jmp    short     recv_isr_3
  384. recv_isr_2:
  385.     test    al,EDLC_JAM
  386.     je    recv_isr_3
  387. ;Crank counter back to beginning and restart transmit
  388. ;ecp->estats.jam++;
  389.     mov    al,IE_RIDE or IE_SYSBFR
  390.     setport    IE_CSR
  391.     out    dx,al
  392.  
  393.     mov    ax,BFRSIZ
  394.     sub    ax,opkt_size
  395.     setport    IE_GP
  396.     out    dx,ax
  397.  
  398.     mov    al,IE_RIDE or IE_XMTEDLC
  399.     setport    IE_CSR
  400.     out    dx,al
  401.  
  402. recv_isr_3:
  403.  
  404. recv_isr_1:
  405.     loadport
  406.     setport    EDLC_RCV
  407.     in    al,dx
  408.     test    al,EDLC_STALE
  409.     jne    recv_isr_4_j_1
  410.     test    al,EDLC_OVER
  411.     je    recv_isr_5
  412. ;ecp->estats.over++;
  413.     call    rcv_fixup
  414.     jmp    recv_isr_1
  415. recv_isr_5:
  416.     test    al,EDLC_SHORT or EDLC_FCS or EDLC_DRIBBLE
  417.     je    recv_isr_6
  418. ;ecp->estats.bad++;
  419.     call    rcv_fixup
  420.     jmp    recv_isr_1
  421. recv_isr_4_j_1:
  422.     jmp    recv_isr_4
  423. recv_isr_6:
  424.     test    al,EDLC_ANY
  425.     je    recv_isr_4_j_1
  426. ;Get control of the buffer
  427.     mov    al,IE_RIDE or IE_SYSBFR
  428.     setport    IE_CSR
  429.     out    dx,al
  430.  
  431.     setport    IE_RP
  432.     in    ax,dx            ;get the size.
  433.     mov    ipkt_size,ax
  434.     cmp    ax,RUNT            ;less than RUNT?
  435.     jb    recv_isr_7        ;yes.
  436.     cmp    ax,GIANT        ;greater than GIANT?
  437.     jbe    recv_isr_8        ;no.
  438. recv_isr_7:
  439.     call    count_in_err
  440. ;ecp->estats.bad++;
  441.     jmp    recv_isr_9
  442. recv_isr_8:
  443. ;Put it on the receive queue
  444.  
  445.     mov    ax,EADDR_LEN+EADDR_LEN    ;seek to the type word.
  446.     setport    IE_GP
  447.     out    dx,ax
  448.  
  449.     setport    IE_BFR
  450.     in    al,dx            ;read the type word out of the board.
  451.     mov    ah,al
  452.     in    al,dx
  453.     xchg    al,ah            ;should be in network byte order.
  454.     mov    our_type,ax
  455.     in    al,dx            ;read the type word out of the board.
  456.     mov    ah,al
  457.     in    al,dx
  458.     xchg    al,ah            ;should be in network byte order.
  459.     mov    our_type+2,ax
  460.  
  461.     movseg    es,ds            ;look up our type.
  462.     mov    di,offset our_type
  463.  
  464.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  465.     mov    ax, es:[di]
  466.     xchg    ah, al
  467.     cmp     ax, 1500
  468.     ja    BlueBookPacket
  469.     inc    di            ;set di to 802.2 header
  470.     inc    di
  471.     mov    dl, IEEE8023
  472. BlueBookPacket:
  473.  
  474.     mov    cx,ipkt_size
  475.     call    recv_find
  476.  
  477.     mov    ax,es            ;is this pointer null?
  478.     or    ax,di
  479.     je    recv_isr_9        ;yes - just free the frame.
  480.  
  481.     push    es            ;remember where the buffer pointer is.
  482.     push    di
  483.  
  484.     xor    ax,ax            ;seek to the beginning again.
  485.     loadport
  486.     setport    IE_GP
  487.     out    dx,ax
  488.  
  489.     mov    cx,ipkt_size
  490.     setport    IE_BFR
  491.  
  492.     call    repinsb
  493.  
  494.     pop    si
  495.     pop    ds
  496.     assume    ds:nothing
  497.     mov    cx,ipkt_size
  498.     call    recv_copy        ;tell them that we copied it.
  499.  
  500.     movseg    ds,cs
  501.     assume    ds:code
  502.  
  503. recv_isr_9:
  504.     mov    al,IE_RIDE or IE_RCVEDLC
  505.     loadport
  506.     setport    IE_CSR
  507.     out    dx,al
  508.     xor    al,al
  509.     setport    IE_RP
  510.     out    dx,al
  511. recv_isr_4:
  512. ;Clear any spurious interrupts
  513.     loadport
  514.     setport    EDLC_RCV
  515.     in    al,dx
  516.  
  517.     setport    EDLC_XMT
  518.     in    al,dx
  519.  
  520.     ret
  521.  
  522.  
  523. rcv_fixup:
  524.     call    count_out_err
  525.  
  526.     mov    al,IE_RIDE or IE_SYSBFR
  527.     loadport
  528.     setport    IE_CSR
  529.     out    dx,al
  530.  
  531.     mov    al,IE_RIDE or IE_RCVEDLC
  532.     setport    IE_CSR
  533.     out    dx,al
  534.  
  535.     mov    al,0
  536.     setport    IE_RP
  537.     out    dx,al
  538.  
  539.     ret
  540.  
  541.  
  542.     public    timer_isr
  543. timer_isr:
  544. ;if the first instruction is an iret, then the timer is not hooked
  545.     iret
  546.  
  547. ;any code after this will not be kept.  Buffers used by the program, if any,
  548. ;are allocated from the memory between end_resident and end_free_mem.
  549.     public end_resident,end_free_mem
  550. end_resident    label    byte
  551. end_free_mem    label    byte
  552.  
  553.     public    usage_msg
  554. usage_msg    db    "usage: 3C501 [options] <packet_int_no> <hardware_irq> <io_addr>",CR,LF,'$'
  555.  
  556.     public    copyright_msg
  557. copyright_msg    db    "Packet driver for the 3COM 3C501, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  558.         db    "Portions Copyright 1988 Phil Karn",CR,LF,'$'
  559.  
  560. no_3c501_msg    db    "No 3C501 found at that address.",CR,LF,'$'
  561. ether_bdcst    db    6 dup(-1)    ;ethernet broadcast address.
  562.  
  563. int_no_name    db    "Interrupt number ",'$'
  564. io_addr_name    db    "I/O port ",'$'
  565.  
  566.     extrn    set_recv_isr: near
  567.  
  568. ;enter with si -> argument string, di -> word to store.
  569. ;if there is no number, don't change the number.
  570.     extrn    get_number: near
  571.  
  572. ;enter with dx -> name of word, di -> dword to print.
  573.     extrn    print_number: near
  574.  
  575. ;-> the assigned Ethernet address of the card.
  576.     extrn    rom_address: byte
  577.  
  578.     public    parse_args
  579. parse_args:
  580. ;exit with nc if all went well, cy otherwise.
  581.     mov    di,offset int_no
  582.     call    get_number
  583.     mov    di,offset io_addr
  584.     call    get_number
  585.     clc
  586.     ret
  587.  
  588.  
  589.     public    etopen
  590. etopen:
  591. ;  Initialize the Ethernet board, set receive type.
  592. ;
  593. ;  check for correct EPROM location
  594. ;
  595. ;Pulse IE_RESET
  596.     mov    al,IE_RESET
  597.     loadport
  598.     setport    IE_CSR
  599.     out    dx,al
  600.  
  601.     call    set_recv_isr
  602.  
  603.     movseg    es,ds
  604.     mov    di,offset rom_address
  605.     mov    cx,EADDR_LEN
  606.     xor    bx,bx
  607. get_address_1:
  608.     mov    ax,bx
  609.     loadport
  610.     setport    IE_GP
  611.     out    dx,ax
  612.  
  613.     setport    IE_SAPROM
  614.     in    al,dx
  615.     stosb
  616.     inc    bx
  617.     loop    get_address_1
  618.  
  619. ;See if there really is a 3c501 there.
  620.     mov    cx,EADDR_LEN
  621.     mov    si,offset rom_address
  622.     mov    di,offset ether_bdcst
  623.     repe    cmpsb
  624.     jne    have_3c501        ;not broadcast address -- must be real.
  625.     mov    dx,offset no_3c501_msg
  626.     stc
  627.     ret
  628. have_3c501:
  629.  
  630.     mov    si,offset rom_address
  631.     mov    cx,EADDR_LEN
  632.     call    set_address
  633.  
  634. ;Enable DMA/interrupt request, gain control of buffer
  635.     mov    al,IE_RIDE or IE_SYSBFR
  636.     loadport
  637.     setport    IE_CSR
  638.     out    dx,al
  639.  
  640. ;Enable transmit interrupts
  641.     mov    al,EDLC_16 or EDLC_JAM
  642.     setport    EDLC_XMT
  643.     out    dx,al
  644.  
  645. ;Set up the receiver interrupts and flush status
  646.     mov    al,EDLC_MULTI or EDLC_GOOD or EDLC_ANY or EDLC_SHORT or EDLC_DRIBBLE or EDLC_FCS or EDLC_OVER
  647.     setport    EDLC_RCV
  648.     out    dx,al
  649.     in    al,dx            ;flush status.
  650.  
  651. ;Start receiver
  652.     mov    ax,0            ;Reset read pointer
  653.     setport    IE_RP
  654.     out    dx,ax
  655.     mov    al,IE_RIDE or IE_RCVEDLC
  656.     setport    IE_CSR
  657.     out    dx,al
  658.  
  659.     mov    al, int_no        ; Get board's interrupt vector
  660.     add    al, 8
  661.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  662.     jb    set_int_num        ; No.
  663.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  664. set_int_num:
  665.     xor    ah, ah            ; Clear high byte
  666.     mov    int_num, ax        ; Set parameter_list int num.
  667.  
  668.     clc
  669.     ret
  670.  
  671.     public    print_parameters
  672. print_parameters:
  673.     mov    di,offset int_no
  674.     mov    dx,offset int_no_name
  675.     call    print_number
  676.     mov    di,offset io_addr
  677.     mov    dx,offset io_addr_name
  678.     call    print_number
  679.     ret
  680.  
  681.  
  682. code    ends
  683.  
  684.     end
  685.