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

  1. version    equ    1
  2.  
  3. ;History:525,47 0
  4.  
  5. ; Copyright, 1990-1992, Russell Nelson, Crynwr Software
  6.  
  7. ;   This program is free software; you can redistribute it and/or modify
  8. ;   it under the terms of the GNU General Public License as published by
  9. ;   the Free Software Foundation, version 1.
  10. ;
  11. ;   This program is distributed in the hope that it will be useful,
  12. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;   GNU General Public License for more details.
  15. ;
  16. ;   You should have received a copy of the GNU General Public License
  17. ;   along with this program; if not, write to the Free Software
  18. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.  
  21.     include    defs.asm
  22.  
  23. ;some generic information about buffer lengths, etc
  24. XMITBUF_LEN    equ    800h        ;Transmit buffer length
  25. RPAGE_LEN    equ    128        ;receive page is 128 bytes
  26. NUM_RPAGES    equ    96        ;There are 96 receive pages
  27. NUM_XBUFS    equ    2        ;Number of xmit buffers
  28. NUM_XBUFS_MASK    equ    1
  29.  
  30. ub_seg    segment at 0
  31.  
  32.     org    10h
  33. eaddr_rom    db    6 dup(?)    ;Has serial # in 3 & 4th bytes
  34.  
  35.     org    2080h
  36. tsa_msb        db    ?    ;transmitter start address, high order 4
  37.                 ;bits on write, start send on read
  38. tsa_lsb        db    ?    ;Transmitter start address, least
  39.                 ;significant byte on write, clear PAV
  40.                 ;on read
  41.  
  42. ;Control / status register (CSR)
  43.  
  44. csr        db    ?    ;Control on write, status on read port
  45.  
  46. ;Command bits
  47. TxRdyIntEn    equ    080h        ;allow TxRdy interrupts
  48. PAVIntEn    equ    040h        ;Allow PAV to gen. intr.
  49. SFTInt        equ    020h        ;generate an interrupt reg.
  50. TimIntEn    equ    010h        ;allow Time interrupt req.
  51. ;status bits
  52. NTxRdyInt    equ    080h        ;Not req. TxRdy inter.
  53. NPAVInt        equ    040h        ;Not req. Pav intr.
  54. NSFTInt        equ    020h        ;Not req. SFTInt inter.
  55. NTimInt        equ    010h        ;Not req. timer inter.
  56. NRINT        equ    008h        ;Not req. recv inter.
  57. NTINT        equ    004h        ;Not req. xmit inter.
  58. TPOK        equ    002h        ;Packet okay of some type
  59. TXDONE        equ    001h        ;Transmit done
  60.  
  61. ;Page pointer register definitions
  62.  
  63. ffp        label    byte        ;ffp - first free page register
  64. epp        label    byte        ;epp - empty page pointer register
  65. pp        db    ?        ;ffp on write/epp on read
  66.  
  67.  
  68. ;ffp bits
  69. NIC_IE        equ    080h        ;NIC interrupts enable
  70.  
  71. ;epp bits
  72. PAV        equ    080h        ;Page available
  73. RPAGE_BITS    equ    07fh
  74.  
  75.  
  76.     org    2100h
  77. page_ram    db    NUM_RPAGES dup(?);Receiver buffer pages
  78.  
  79.     org    2180h
  80. tstatus        db    ?        ;Transmitter status 80
  81.  
  82. ;Transmit status bits - EDLC
  83. TX_READY    equ    080h        ;
  84. TX_BUSY        equ    040h        ;Carrier detect
  85. TX_TPR        equ    020h        ;Self received packet sent
  86. TX_SHORTED    equ    010h        ;Carrier lost
  87. TX_UF        equ    008h        ;Underflow
  88. TX_COL        equ    004h        ;Collision
  89. TX_C16        equ    002h        ;16 collisions
  90. TX_PE        equ    001h        ;Parity error
  91.  
  92. TXERRMASK    equ    TX_PE or TX_C16 or TX_COL or TX_UF or TX_SHORTED or TX_BUSY
  93.  
  94. tmask        db    ?        ;Transmitter mask 81
  95. rstatus        db    ?        ;Receiver status
  96. rmask        db    ?        ;Receiver mask 83
  97. tmode        db    ?        ;Transmitter mode 84
  98. rmode        db    ?        ;Receiver mode 85
  99. reset        db    ?        ;Reset line - high on bit 7, 86
  100. tdrlsb        db    ?        ;TDR lsb  87
  101. eaddr_ram    db    6 dup(?)    ;current Ethernet address.
  102.         db    ?        ;Reserved 8e
  103. tdrmsb        db    ?        ;TDR msb 8f
  104.  
  105.     org    4000h
  106. receive_buf    label    byte
  107.  
  108.     org    7000h
  109. transmit_buf_1    label    byte
  110.  
  111.     org    7800h
  112. transmit_buf_2    label    byte
  113.  
  114. ub_seg    ends
  115.  
  116. code    segment    word public
  117.     assume    cs:code, ds:code
  118.  
  119.     public    int_no
  120. int_no        db    3,0,0,0        ;must be four bytes long for get_number.
  121. base_addr    dw    0d000h,0
  122.  
  123.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  124. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  125. driver_type    db    8        ;from the packet spec
  126. driver_name    db    'PC-NIC',0    ;name of the driver.
  127. driver_function    db    2
  128. parameter_list    label    byte
  129.     db    1    ;major rev of packet driver
  130.     db    9    ;minor rev of packet driver
  131.     db    14    ;length of parameter list
  132.     db    EADDR_LEN    ;length of MAC-layer address
  133.     dw    GIANT    ;MTU, including MAC headers
  134.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  135.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  136.     dw    0    ;(# of successive xmits) - 1
  137. int_num    dw    0    ;Interrupt # to hook for post-EOI
  138.             ;processing, 0 == none,
  139.  
  140.     public    rcv_modes
  141. rcv_modes    dw    7        ;number of receive modes in our table.
  142.         dw    0               ;There is no mode zero
  143.         dw    rcv_mode_1
  144.         dw    0        ;don't want to bother.
  145.         dw    rcv_mode_3
  146.         dw    0        ;haven't set up perfect filtering yet.
  147.         dw    rcv_mode_5
  148.         dw    rcv_mode_6
  149.  
  150. current_page    db    0        ;current receiver page
  151.  
  152. active_buffer    dw    transmit_buf_1
  153. inactive_buffer    dw    transmit_buf_2
  154.  
  155.     include    movemem.asm
  156.  
  157.     public bad_command_intercept
  158. bad_command_intercept:
  159. ;called with ah=command, unknown to the skeleton.
  160. ;exit with nc if okay, cy, dh=error if not.
  161.     mov    dh,BAD_COMMAND
  162.     stc
  163.     ret
  164.  
  165.     public    as_send_pkt
  166. ; The Asynchronous Transmit Packet routine.
  167. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  168. ;   interrupts possibly enabled.
  169. ; Exit with nc if ok, or else cy if error, dh set to error number.
  170. ;   es:di and interrupt enable flag preserved on exit.
  171. as_send_pkt:
  172.     ret
  173.  
  174.     public    drop_pkt
  175. ; Drop a packet from the queue.
  176. ; Enter with es:di -> iocb.
  177. drop_pkt:
  178.     assume    ds:nothing
  179.     ret
  180.  
  181.     public    xmit
  182. ; Process a transmit interrupt with the least possible latency to achieve
  183. ;   back-to-back packet transmissions.
  184. ; May only use ax and dx.
  185. xmit:
  186.     assume    ds:nothing
  187.     ret
  188.  
  189.  
  190.     public    send_pkt
  191. send_pkt:
  192. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  193. ;  (only if the high-performance bit is set in driver_function)
  194. ;enter with ds:si -> packet, cx = packet length.
  195. ;if we're a high-performance driver, es:di -> upcall.
  196. ;exit with nc if ok, or else cy if error, dh set to error number.
  197.     assume    ds:nothing
  198.  
  199.     mov    es,base_addr
  200.     assume    es:ub_seg
  201.  
  202.     cmp    cx,GIANT        ; Is this packet too large?
  203.     ja    send_pkt_toobig
  204.  
  205.     cmp    cx,RUNT            ; minimum length for Ether
  206.     jnb    oklen
  207.     mov    cx,RUNT            ; make sure size at least RUNT
  208. oklen:
  209.  
  210.     mov    di,XMITBUF_LEN        ;compute where we're going to
  211.     sub    di,cx            ;  be putting the packet.
  212.  
  213. ;games above ensure that the last byte of data to go out is at the
  214. ;end of the ub xmit buffer, pos is really the offset from the
  215. ;start of that buffer
  216.  
  217.     mov    ax,active_buffer    ;swap the buffer pointers.
  218.     xchg    ax,inactive_buffer
  219.     mov    active_buffer,ax
  220.     add    di,ax
  221.     push    di
  222.     call    movemem
  223.     pop    di
  224.  
  225. ;Wait for previous packet to finish first
  226. ;could do this with interrupts, etc, but with only 2 xmit buffers
  227. ;doesn't seem worth the effort
  228.  
  229. send_pkt_1:
  230.     mov    al,csr
  231.     and    al,TPOK or TXDONE
  232.     cmp    al,TPOK or TXDONE
  233.     jne    send_pkt_1
  234.  
  235.     mov    al,tstatus        ;get xmiter status ...
  236.     mov    tstatus,0fh        ;... and clear status bits
  237.  
  238.     test    al,TXERRMASK        ;any errors?
  239.     je    send_pkt_2
  240.     call    count_out_err        ;yes, count them.
  241. send_pkt_2:
  242.  
  243. ;all done above, we can play with TSA now!
  244. ;give offset
  245.  
  246.     mov    ax,di
  247.     mov    tsa_lsb,al
  248.     mov    tsa_msb,ah
  249.  
  250.     cmp    al,tsa_msb        ;Start the send in action (SIDEEFFECT)
  251.  
  252.     clc
  253.     ret
  254. send_pkt_toobig:
  255.     mov    dh,NO_SPACE
  256.     stc
  257.     ret
  258.  
  259.     public    set_address
  260. set_address:
  261. ;enter with ds:si -> Ethernet address, CX = length of address.
  262. ;exit with nc if okay, or cy, dh=error if any errors.
  263.     assume    ds:code
  264.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  265.     je    set_address_4
  266.     mov    dh,BAD_ADDRESS
  267.     stc
  268.     jmp    short set_address_done
  269. set_address_4:
  270.  
  271.     mov    es,base_addr
  272.     mov    di,offset eaddr_ram
  273.     rep    movsb
  274. ;    call    initialize        ;initialize with our new address.
  275.  
  276. set_address_okay:
  277.     mov    cx,EADDR_LEN        ;return their address length.
  278.     clc
  279. set_address_done:
  280.     ret
  281.  
  282.  
  283. ;    0 - accept no packets
  284. rcv_mode_1:
  285.     mov    es,base_addr
  286.     assume    es:ub_seg
  287.  
  288.     mov    rmode,0
  289.     ret
  290.  
  291. rcv_mode_3:
  292. ;    1 - accept node id packets, multicasts which match first three
  293. ;        bytes of node id, and broadcasts
  294.     mov    es,base_addr
  295.     assume    es:ub_seg
  296.  
  297.     mov    rmode,1
  298.     ret
  299.  
  300. ;    2 - accept node id packets, all multicasts and broadcasts
  301. rcv_mode_5:
  302.     mov    es,base_addr
  303.     assume    es:ub_seg
  304.  
  305.     mov    rmode,2
  306.     ret
  307.  
  308. ;    3 - take all, promiscous
  309. rcv_mode_6:
  310.     mov    es,base_addr
  311.     assume    es:ub_seg
  312.  
  313.     mov    rmode,3
  314.     ret
  315.  
  316.     public    set_multicast_list
  317. set_multicast_list:
  318. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  319. ;return nc if we set all of them, or cy,dh=error if we didn't.
  320.     mov    dh,NO_MULTICAST
  321.     stc
  322.     ret
  323.  
  324.  
  325.     public    terminate
  326. terminate:
  327.     mov    es,base_addr
  328.     assume    es:ub_seg
  329.  
  330.     mov    ffp,0            ;set ffp to zero - disabling PAV
  331.     mov    csr,0            ;Turn off interrupt masks here and ...
  332.     mov    tmask,0            ;reset edlc interrupt masks
  333.     mov    rmask,0
  334.     mov    reset,80h        ;Turn on reset line
  335.  
  336.     ret
  337.  
  338.     public    reset_interface
  339. reset_interface:
  340. ;reset the interface.
  341.     assume    ds:code
  342.     ret
  343.  
  344.  
  345. ;called when we want to determine what to do with a received packet.
  346. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  347.     extrn    recv_find: near
  348.  
  349. ;called after we have copied the packet into the buffer.
  350. ;enter with ds:si ->the packet, cx = length of the packet.
  351.     extrn    recv_copy: near
  352.  
  353.     extrn    count_in_err: near
  354.     extrn    count_out_err: near
  355.  
  356.  
  357.     public    recv
  358. recv:
  359. ;called from the recv isr.  All registers have been saved, and ds=cs.
  360. ;Upon exit, the interrupt will be acknowledged.
  361.     assume    ds:code
  362.  
  363.     mov    es,base_addr
  364.     assume    es:ub_seg
  365.  
  366. recv_3:
  367.     test    epp,PAV
  368.     jne    recv_4
  369.     jmp    recv_2            ;yes.
  370. recv_4:
  371.  
  372. ;checking against epp is a pain actually...
  373.     xor    cx,cx            ;start with zero length
  374.     mov    bl,current_page        ;get the first page.
  375.     xor    bh,bh
  376.     mov    dx,bx            ;remember the first page.
  377. count_pages_1:
  378.     mov    al,page_ram[bx]        ;Get page descriptor
  379.     and    al,RPAGE_BITS        ;Only page offset bits PLEASE
  380.     inc    al            ;Add 1 to offset to make length
  381.     xor    ah,ah
  382.     add    cx,ax            ;Add in current page length
  383.  
  384.     mov    al,page_ram[bx]        ;Get page descriptor
  385.     inc    bx            ;go to the next page
  386.     cmp    bx,NUM_RPAGES        ;wrap around if necessary.
  387.     jb    count_pages_2
  388.     xor    bx,bx
  389. count_pages_2:
  390.  
  391.     test    al,80h            ;End page?
  392.     je    count_pages_1        ;yes, go add this one's length.
  393.  
  394.     mov    current_page,bl
  395.  
  396.     mov    ax,dx            ;multiply dx by RPAGE_LEN.
  397.     xchg    ah,al
  398.     ror    ax,1
  399.     mov    di,ax
  400.     add    di,offset receive_buf    ;get the starting address.
  401.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  402.                     ;  point to the packet type.
  403.     push    bx
  404.     push    cx
  405.     push    dx
  406.  
  407.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  408.     mov    ax, es:[di]
  409.     xchg    ah, al
  410.     cmp     ax, 1500
  411.     ja    BlueBookPacket
  412.     inc    di            ;set di to 802.2 header
  413.     inc    di
  414.     mov    dl, IEEE8023
  415. BlueBookPacket:
  416.  
  417.     call    recv_find        ;look up our type.
  418.     assume    es:nothing
  419.     pop    dx
  420.     pop    cx
  421.     pop    bx
  422.  
  423.     mov    ax,es            ;is this pointer null?
  424.     or    ax,di
  425.     je    just_discard        ;yes - just free the frame.
  426.  
  427.     push    cx
  428.     push    di
  429.     push    es
  430.  
  431.     cmp    dx,bx            ;did we wrap around (first >last?)
  432.     jbe    no_wrap            ;no, just do one move.
  433.  
  434. ;we wrapped around the buffer, so we have to move in two halves.
  435. ;move the first part.
  436.     mov    ax,dx            ;multiply dx by RPAGE_LEN.
  437.     xchg    ah,al
  438.     ror    ax,1
  439.     mov    si,ax
  440.     add    si,offset receive_buf    ;get the starting address.
  441.  
  442.     mov    ax,NUM_RPAGES        ;Compute the number of pages to move.
  443.     sub    ax,dx
  444.     xchg    ah,al            ;convert to pages (*RPAGE_LEN).
  445.     ror    ax,1
  446.     cmp    cx,ax            ;are we moving less than that?
  447.     jbe    no_wrap            ;yes, just move it.
  448.     sub    cx,ax            ;reduce the total count by this count.
  449.     push    cx            ;preserve the second part's count
  450.     mov    cx,ax            ;get the first part's count.
  451.  
  452.     push    ds
  453.     mov    ds,base_addr
  454.     assume    ds:nothing
  455.     call    movemem
  456.     assume    ds:code
  457.     pop    ds
  458.  
  459.     pop    cx            ;get back the count
  460.  
  461.     xor    dx,dx
  462.  
  463. no_wrap:
  464.     mov    ax,dx            ;multiply dx by 128.
  465.     xchg    ah,al
  466.     ror    ax,1
  467.     mov    si,ax
  468.     add    si,offset receive_buf
  469.     mov    ds,base_addr
  470.     assume    ds:nothing
  471.     call    movemem
  472.     assume    ds:code
  473.  
  474.     pop    ds
  475.     pop    si
  476.     pop    cx
  477.     call    recv_copy
  478.     push    cs
  479.     pop    ds
  480.  
  481. just_discard:
  482.     mov    es,base_addr
  483.     assume    es:ub_seg
  484.     mov    al,epp            ;Any more packets left?
  485.     and    al,RPAGE_BITS
  486.     cmp    al,current_page
  487.     je    recv_5
  488.     jmp    recv_3
  489. recv_5:
  490.  
  491.     cmp    al,tsa_lsb        ;Clearing pav bit (SIDEEFFECT)
  492.  
  493. recv_2:
  494.  
  495. ;Ack the interrupt by turning bit on and off
  496.     mov    al,current_page        ;Set first free page pointer
  497.     mov    ffp,al
  498.     or    al,NIC_IE        ;set interrupt bit, was off
  499.     mov    ffp,al
  500. recv_1:
  501.     ret
  502.  
  503.  
  504.     public    recv_exiting
  505. recv_exiting:
  506. ;called from the recv isr after interrupts have been acknowledged.
  507. ;Only ds and ax have been saved.
  508.     assume    ds:nothing
  509.     ret
  510.  
  511.  
  512.     public    timer_isr
  513. timer_isr:
  514. ;if the first instruction is an iret, then the timer is not hooked
  515.     iret
  516.  
  517. ;any code after this will not be kept.  Buffers used by the program, if any,
  518. ;are allocated from the memory between end_resident and end_free_mem.
  519.     public end_resident,end_free_mem
  520. end_resident    label    byte
  521. end_free_mem    label    byte
  522.  
  523.  
  524.     public    usage_msg
  525. usage_msg    db    "usage: ubnic [options] <packet_int_no> <int_no> <base_addr>",CR,LF,'$'
  526.  
  527.     public    copyright_msg
  528. copyright_msg    db    "Packet driver for the UB PC/NIC, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  529.         db    '$'
  530.  
  531. int_no_name    db    "Interrupt number ",'$'
  532. base_addr_name    db    "Memory address ",'$'
  533.  
  534.     extrn    set_recv_isr: near
  535.  
  536. ;enter with si -> argument string, di -> wword to store.
  537. ;if there is no number, don't change the number.
  538.     extrn    get_number: near
  539.  
  540. ;enter with si -> argument string, di -> wword to print.
  541.     extrn    print_number: near
  542.  
  543. ;-> the assigned Ethernet address of the card.
  544.     extrn    rom_address: byte
  545.  
  546.     public    parse_args
  547. parse_args:
  548. ;exit with nc if all went well, cy otherwise.
  549.     mov    di,offset int_no
  550.     call    get_number
  551.     mov    di,offset base_addr
  552.     call    get_number
  553.     clc
  554.     ret
  555.  
  556.  
  557.     public    etopen
  558. etopen:
  559.     cli
  560.  
  561.     cmp    base_addr,-1        ;did they ask for auto-configure?
  562.     jne    no_auto_config
  563.  
  564.     mov    bx,8000h        ;yes, they *could* address it there.
  565. auto_config_1:
  566.     mov    es,bx
  567.     assume    es:ub_seg
  568.     cmp    word ptr es:eaddr_rom[0],00h + 0ddh * 256
  569.     jne    auto_config_2
  570.     cmp    byte ptr es:eaddr_rom[2],01h
  571.     je    auto_config_3
  572. auto_config_2:
  573.     add    bx,800h            ;move up by 32K
  574.     jnc    auto_config_1        ;go if we didn't overflow.
  575.     sti
  576.     stc                ;say that we couldn't init.
  577.     ret
  578.  
  579. auto_config_3:
  580.     mov    base_addr,bx        ;remember where we found it.
  581.     mov    base_addr+2,0        ;and nuke the rest of the -1.
  582.  
  583. no_auto_config:
  584.     mov    es,base_addr
  585.     assume    es:ub_seg
  586.  
  587.     mov    reset,80h        ;Turn on reset line to tie down NIC
  588.     mov    rmode,0            ;no packets for now
  589.     mov    tmode,0            ;Turn on loopback
  590.  
  591.     mov    al,epp            ;start ffp at epp - eliminates bogus ....
  592.     and    al,07fh
  593.     mov    current_page,al        ;... packets if we've been started before
  594.     mov    ffp,al            ;Make sure interrupt enable is dead
  595.  
  596.     cmp    al,tsa_lsb        ;Clearing pav bit (SIDEEFFECT)
  597.  
  598.     mov    tstatus, 0fh        ;Clear xmit status bits
  599.     mov    tmask,0            ;No xmit intrs
  600.     mov    rmask,0            ;'Packet okay' only?
  601.     mov    rstatus,0ffh        ;Clear receiver status bits
  602.  
  603.     movseg    ds,es
  604.     mov    di,offset rom_address
  605.     push    ds
  606.     mov    ds,base_addr
  607.     mov    si,offset eaddr_rom
  608.     repmov    EADDR_LEN
  609.     pop    ds
  610.  
  611.     mov    si,offset rom_address
  612.     mov    cx,EADDR_LEN
  613.     call    set_address
  614.  
  615. ;Since first packet will get sent no matter what we do, let's make it
  616. ;something everyone (include me) will ignore
  617. ;set length to zero
  618.  
  619.     mov    tsa_lsb,0ffh        ;Get last 8 bits
  620.     mov    tsa_msb,0fh        ;and top 4 bits
  621.  
  622.     mov    reset,0            ;Clear reset - expect packet to go
  623. ;Wait for packet to go!
  624. etopen_1:
  625.     mov    al,csr
  626.     and    al,TPOK or TXDONE
  627.     cmp    al,TPOK or TXDONE
  628.     jne    etopen_1
  629.  
  630.     mov    tstatus,0fh        ;clear xmiter status
  631.     mov    tmode,0ah        ;Clear loopbk, set parity enable
  632.  
  633.     mov    csr,0            ;make sure this interrupt was off first
  634.     mov    csr,PAVIntEn        ;Page frame available interrupt only
  635.     mov    al,current_page        ;Set first free page register ...
  636.     or    al,NIC_IE
  637.     mov    ffp,al            ;... and make sure interrupts enabled
  638.  
  639.     mov    al,epp            ;get epp again
  640.     test    al,PAV
  641.     je    etopen_2
  642.     cmp    al,tsa_lsb        ;Try clearing pav bit (SIDEEFFECT)
  643. etopen_2:
  644.  
  645. ;enable receiving now
  646. ;    1 - accept node id packets, multicasts which match first three
  647. ;        bytes of node id, and broadcasts
  648.     mov    rmode,1
  649.  
  650. ;
  651. ; Now hook in our interrupt
  652. ;
  653.     call    set_recv_isr
  654.  
  655.     sti
  656.  
  657.     mov    al, int_no        ; Get board's interrupt vector
  658.     add    al, 8
  659.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  660.     jb    set_int_num        ; No.
  661.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  662. set_int_num:
  663.     xor    ah, ah            ; Clear high byte
  664.     mov    int_num, ax        ; Set parameter_list int num.
  665.  
  666. ;if all is okay,
  667.     mov    dx,offset end_resident
  668.     clc
  669.     ret
  670. ;if we got an error,
  671.     stc
  672.     ret
  673.  
  674.     public    print_parameters
  675. print_parameters:
  676. ;echo our command-line parameters
  677.     mov    di,offset int_no
  678.     mov    dx,offset int_no_name
  679.     call    print_number
  680.     mov    di,offset base_addr
  681.     mov    dx,offset base_addr_name
  682.     call    print_number
  683.     ret
  684.  
  685. code    ends
  686.  
  687.     end
  688.