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

  1. ;   Copyright (C) 1993, RF Nets, Cupertino, CA 
  2. ;   All Rights Reserved
  3. ;   Author:kevinr@Solaris.com
  4. ;
  5. ;   ecoupler -
  6. ;   TSR compatible with the FTP Software, inc packet driver interface
  7. ;   specification for any card using the Fujitsu MB86965 EtherCoupler.
  8. ;
  9. version    equ    1
  10.  
  11. ;   $Id: ecoupler.s%v 1.3 1993/02/10 06:30:26 N6RCE Rel $
  12. ;
  13.     .286
  14.     
  15.     include    defs.asm
  16.     include f965.inc        ;Fujitsu 86965 definitions
  17.  
  18. code    segment    word public
  19.     assume    cs:code, ds:code
  20.  
  21.     public    int_no
  22. int_no    db    0,0,0,0            ;must be four bytes long for get_number.
  23. io_addr    dw    -1,-1            ;selected I/O base address
  24.  
  25.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  26.                 ;supported classes from pkt drv spec
  27. driver_class    db    BLUEBOOK,IEEE8023,0  
  28. driver_type    db    DR_TYPE        ;per the spec.
  29. driver_name    db    DR_NAME,0    ;name of the driver.
  30. driver_function    db    2        ;basic and extended only
  31. parameter_list    label    byte
  32.     db    1    ;major rev of packet driver
  33.     db    9    ;minor rev of packet driver
  34.     db    14    ;length of parameter list
  35.     db    EADDR_LEN    ;length of MAC-layer address
  36.     dw    GIANT    ;MTU, including MAC headers
  37.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  38.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  39.     dw    0    ;(# of successive xmits) - 1
  40. int_num    dw    0    ;Interrupt # to hook for post-EOI
  41.             ;processing, 0 == none,
  42.  
  43.     public  rcv_modes
  44. rcv_modes    dw    7        ;number of receive modes in our table.
  45.         dw    0               ;There is no mode zero
  46.         dw    rcv_mode_1
  47.         dw    0
  48.         dw    rcv_mode_3
  49.         dw    rcv_mode_4
  50.         dw    rcv_mode_5
  51.         dw    rcv_mode_6
  52.  
  53. WEC_reg    Macro    reg,val        ;write to an ethercoupler register
  54.     Mov    DX,io_addr
  55.     Add    DX,reg
  56.   IFNB <val>
  57.     Mov    AL,val
  58.   ENDIF
  59.     Out    DX,AL
  60.     endm
  61.  
  62. REC_reg    Macro    reg        ;read a designated ethercoupler register
  63.                 ;result into AL
  64.     Mov    DX,io_addr
  65.     Add    DX,reg
  66.     In    AL,DX
  67.     endm
  68.  
  69. ;
  70. ;-------------------------------------------------------------------------
  71. ;   Misc. data variables needed by driver
  72. ;-------------------------------------------------------------------------
  73. ;
  74.  
  75. mcast_list_bits db      0,0,0,0,0,0,0,0 ;Bit mask from last set_multicast_list
  76. mcast_none    db    8 dup(0)
  77. mcast_all    db    8 dup(0ffh)
  78.  
  79. ;------------------------------------------------------------------
  80. ; keep the following together
  81. recv_pkt_hdr Equ pkt_status    ;
  82. pkt_status Db    0        ;etherCoupler status byte
  83. pkt_rsvd1  Db    0        ;reserved byte
  84. pkt_count  Dw    0        ;actual bytes received
  85. pkt_dst_MAC Db    EADDR_LEN dup(0)    ;destination MAC addr
  86. pkt_src_MAC Db    EADDR_LEN dup(0)    ;source MAC addr
  87. pkt_type   Db    MAX_P_LEN dup(?) ;ethernet type field -or- 802.3 length field
  88. ; keep the above together
  89. ;------------------------------------------------------------------
  90.  
  91.     public bad_command_intercept
  92. bad_command_intercept:
  93. ;called with ah=command, unknown to the skeleton.
  94. ;exit with nc if okay, cy, dh=error if not.
  95.     mov    dh,BAD_COMMAND
  96.     stc
  97.     ret
  98.  
  99.     public    as_send_pkt
  100. ; The Asynchronous Transmit Packet routine.
  101. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  102. ;   interrupts possibly enabled.
  103. ; Exit with nc if ok, or else cy if error, dh set to error number.
  104. ;   es:di and interrupt enable flag preserved on exit.
  105. as_send_pkt:
  106.     ret
  107.  
  108.     public    drop_pkt
  109. ; Drop a packet from the queue.
  110. ; Enter with es:di -> iocb.
  111. drop_pkt:
  112.     assume    ds:nothing
  113.     ret
  114.  
  115.     public    xmit
  116. ; Process a transmit interrupt with the least possible latency to achieve
  117. ;   back-to-back packet transmissions.
  118. ; May only use ax and dx.
  119. xmit:
  120.     ret
  121.  
  122.     public    send_pkt
  123. send_pkt:
  124. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  125. ;  (only if the high-performance bit is set in driver_function)
  126. ;enter with ds:si -> packet, cx = packet length.
  127. ;if we're a high-performance driver, es:di -> upcall.
  128. ;exit with nc if ok, or else cy if error, dh set to error number.
  129.     assume    ds:nothing
  130.     cmp    cx,RUNT        ; minimum length for Ether
  131.     jae    oklen
  132.     mov    cx,RUNT        ; make sure size at least RUNT
  133. oklen:
  134.     Mov    AX,CX
  135.     Mov    DX,io_addr
  136.     Add    DX,BMPR8        ;output buffer reg addr
  137.     Out    DX,AX            ;write count into xmit buffer reg
  138.     inc    cx            ;round up.
  139.     shr    CX,1            ;bytes to words
  140.     rep OutSW            ;copy pkt buffer to EC xmit buffer
  141.  
  142.     mov    ax,18
  143.     call    set_timeout
  144. send_buffer_1:
  145.     REC_reg    DLCR0            ;get the transmit status
  146.     test    al,TX_DONE        ;is it done?
  147.     jne    send_buffer_2        ;yes.
  148.     call    do_timeout
  149.     jne    send_buffer_1
  150. ;send the packet anyway -- we *can't* be waiting to send a packet *this* long.
  151. send_buffer_2:
  152.  
  153.     WEC_reg    DLCR0,TX_DONE        ;clear TX status
  154.     mov    Al,TX_START + 1        ;start command + packet_count
  155.     WEC_reg    BMPR10            ;and we're off
  156.     Clc
  157.     ret
  158.  
  159.     public    set_address
  160. set_address:
  161. ;enter with ds:si -> Ethernet address, CX = length of address.
  162. ;exit with nc if okay, or cy, dh=error if any errors.
  163. ;
  164. ;   NOTE: this routine alters (and restores on exit) the 
  165. ;   DLCR8-15 register set.  It also disables DLC then enables it on exit.
  166. ;
  167. ;-----------------------------------------------------------------
  168.     assume    ds:code
  169.  
  170.     cmp    cx,6            ;chk for correct length
  171.     je    sa_01            ;if okay, jmp to continue
  172.     mov    dl,BAD_ADDRESS
  173.     stc
  174.     ret
  175. sa_01:                    ;come here to continue with setting new MAC address
  176.     mov    bl,RBS_DLCRH
  177.     call    set_reg_block
  178.     mov    cx,6            ;restore length
  179.     clc
  180.     ret
  181.  
  182.     assume    ds:code
  183. rcv_mode_1:
  184.     mov    al,0            ;disable the receiver and transmitter.
  185.     jmp    initialize_nomulti
  186. rcv_mode_6:
  187.     mov    al,3            ;promiscuous mode
  188.     jmp    short initialize_nomulti
  189. rcv_mode_3:
  190.     mov    si,offset mcast_none    ;don't accept any multicast frames.
  191.     jmp    short initialize_multi
  192. rcv_mode_4:
  193.     mov    si,offset mcast_list_bits    ;accept our multicast frames.
  194.     jmp    short initialize_multi
  195. rcv_mode_5:
  196.     mov    si,offset mcast_all    ;accept any multicast frames.
  197. initialize_multi:
  198.     call    set_hw_multi
  199.     mov    al,AF1            ; receive mine, broads, and multis.
  200. initialize_nomulti:
  201.     WEC_reg    DLCR5            ;set the address match list.
  202.     ret
  203.  
  204.  
  205. set_hw_multi:
  206.     mov    bl,RBS_HT
  207.     mov    cx,8
  208. ;
  209. ;
  210. set_reg_block:
  211. ;enter with si -> block of register values to set, bl = register set selection,
  212. ;  cx = count of registers to set (up to 8).
  213.     loadport
  214.     setport    DLCR6            ;get register contents
  215.     in    al,dx
  216.     mov    ah,al            ;save a copy.
  217.     or    al,DLC_EN        ;set DLC high (disable)
  218.     out    dx,al            ;disable EtherCoupler
  219.  
  220.     setport    DLCR7            ;get config register 1
  221.     in    al,dx
  222.     push    ax            ;save 6 and 7.
  223.  
  224.     and    al,not RBS        ;clear current register setting
  225.     or    al,bl            ;include the one they want to select.
  226.     out    dx,al
  227.  
  228.     setport    DLCR8
  229. srb_01:
  230.     lodsb
  231.     out    dx,al            ;output to Node ID register
  232.     inc    dx
  233.     loop    srb_01
  234.  
  235.     loadport
  236.     setport    DLCR7            ;restore config reg 1
  237.     pop    ax
  238.     out    dx,al
  239.  
  240.     setport    DLCR6            ;restore it.
  241.     mov    al,ah
  242.     out    dx,al
  243.     ret
  244.  
  245.  
  246.     public    terminate
  247. terminate:
  248.  
  249. ;time to get out of Dodge
  250. ; maks interrupts from the hardware, and disable DLC
  251.     WEC_reg    DLCR6,DLC_EN
  252.     WEC_reg    DLCR2,0        ;disable all Tx src's of inteerupts
  253.     WEC_reg    DLCR3,0        ;ditto for Rx
  254.  
  255.     Mov    DX,io_addr
  256.     Add    DX,24        ;IDRB0
  257.     Out    DX,AL        ;claims to reset the EC device
  258.  
  259.     ret
  260.  
  261.     public    reset_interface
  262. reset_interface:
  263. ;reset the interface.
  264.     assume    ds:code
  265.     ret
  266.  
  267.  
  268. ;called when we want to determine what to do with a received packet.
  269. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  270.     extrn    recv_find: near
  271.  
  272. ;called after we have copied the packet into the buffer.
  273. ;enter with ds:si ->the packet, cx = length of the packet.
  274.     extrn    recv_copy: near
  275.  
  276.     extrn    count_in_err: near
  277.     extrn    count_out_err: near
  278.  
  279.     public    recv
  280. recv:
  281. ;called from the recv isr.  All registers have been saved, and ds=cs.
  282. ;a specific EOI has already been issued to the 8259. The IRQ line in the
  283. ;8259 is also masked.
  284.  
  285.     assume    ds:code
  286.  
  287. ;technique:  read the status register, and write that back to register,
  288. ; thereby clearing it.
  289. ;Then, check for RX Buffer Overflow, if so, increment a counter.
  290. ;Next, loop on RX BUF not empty (DLCR5).
  291. ;
  292.     REC_reg    DLCR1        ;Rx Status register
  293.     WEC_reg    DLCR1        ;reset for next occurrance
  294.         ;we shouldn't ever loose an interrupt 'cause:
  295.         ;the PIC is already cleared, it's edge triggered
  296.         ;and we've now armed the EC to hit us again, after the
  297.         ;processor interrupt mask is turned off.
  298.     Test    AL,RX_BUF_OVFL    ;RX Buffer overflow?
  299.     Jz    rcv_buf_chk    ;jump if not buffer overflow
  300.     Call    count_in_err
  301.         ;we don't test for pkt arrive interrupt, we'll figure it
  302.         ;out from the RX buffer empty status bit in DLCR5
  303.         
  304. rcv_buf_chk:        ;check for packets in buffer
  305.     REC_reg    DLCR5            ;recv mode register
  306.     Test    AX,RX_BUF_EMPTY        ;any more pkts in buffer?
  307.     Jz    rcv_not_empty            ;jmp if so (RX_BUF_EMPTY off)
  308. ; no pkts in buffer..all done
  309. ;***    Jmp    rcv_empty            ;
  310.     
  311. rcv_empty:        ;come here after pkt buffer goes empty.
  312.  
  313.     Ret                ;back to main ISR
  314.     
  315.     
  316. rcv_not_empty:
  317.         ;We'll read 9 words from the EC.  The first two
  318.         ;contain the recv status and the count, the next
  319.         ;fourteen bytes contain the ethernet header.
  320.         ;we're interested in the type field in bytes at
  321.         ;offset 12 and 13.
  322.     Mov    DX,io_addr
  323.     Add    DX,BMPR8
  324.     Mov    CX,(4+EADDR_LEN+EADDR_LEN+MAX_P_LEN)/2    ;status, count, E hdr, all in words
  325.     Push    DS
  326.     Pop    ES
  327.     Mov    DI,offset recv_pkt_hdr    ;where to load
  328.     rep Insw
  329.     Cmp    pkt_status,20h        ;good status
  330.     Je    rcv_good_pkt         ;jump if good recv status
  331. ;  bad recv status...skip the packet, increment some counter
  332.  
  333.     jmp    rcv_skip_pkt        ;go to dump packet routine
  334. rcv_good_pkt:
  335. ;come here when good packet recv'ed
  336. ;prep and call recv_find to see if handler owner wants
  337. ;the blasted thing!
  338. ;DL = type (BLUEBOOK or IEEE8023)
  339. ;CX = length including MAC header
  340. ;ES:DI = ethernet type field
  341.     mov    cx,pkt_count
  342.     mov    di,offset pkt_type
  343.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  344.     mov    ax, es:[di]
  345.     xchg    ah, al
  346.     cmp     ax, 1500
  347.     ja    BlueBookPacket
  348.     inc    di            ;set di to 802.2 header
  349.     inc    di
  350.     mov    dl, IEEE8023
  351. BlueBookPacket:
  352.  
  353.     call    recv_find        ;ES:DI points to buffer on rtn
  354.                     ;or 0:0 if don't want packet
  355.     mov    ax,es
  356.     or    ax,di            ;check for any bits on
  357.     je    rcv_skip_pkt        ;jump if don't want the packet
  358.  
  359.     push    es
  360.     push    di
  361.  
  362.     mov    cx,(EADDR_LEN+EADDR_LEN+MAX_P_LEN)/2 ;header length (in words)
  363.     mov    si,offset pkt_dst_mac
  364.     rep    movsw
  365.     mov    dx,io_addr
  366.     add    dx,BMPR8
  367.     mov    cx,pkt_count        ;orig pkt length
  368.     sub    cx,(EADDR_LEN+EADDR_LEN+MAX_P_LEN) ;hdr already taken
  369.     shr    cx,1            ;make it into words
  370.     rep    insw            ;copy remainder of pkt to callers buf
  371.     jnc    rcv_not_odd_cnt
  372.     in    ax,dx            ;allow for odd length packets
  373.     stosb
  374. rcv_not_odd_cnt:
  375.  
  376. ; notify handle owner the copy is finished
  377.     pop    si
  378.     pop    ds
  379.     assume    ds:nothing
  380.     mov    cx,pkt_count
  381.     Call    recv_copy        ;let caller know data loaded into his
  382.                     ;buffer. 
  383.                     ;DS:SI->his buffer
  384.                     ;CX = packet length
  385.     Push    CS
  386.     Pop    DS            ;data back to our segment
  387.     assume    DS:code
  388.  
  389.     Jmp    rcv_buf_chk        ;go check for more pkts in buffer
  390.     
  391. rcv_skip_pkt:        ;come here to skip a packet
  392.             ;** need to increment some counter **
  393.     REC_reg    BMPR14            ;get skip pkt reg contents
  394.     Or    AL,SKIP_PKT        ;tell EC to skip this packet
  395.     WEC_reg    BMPR14            ;do it. Note: chip spec says
  396.                     ;this could take up to 300ns
  397.                     ;to complete.
  398.     Jmp    rcv_buf_chk        ;go check for more pkts in buffer
  399.  
  400.     public    recv_exiting
  401. recv_exiting:
  402. ;called from the recv isr after interrupts have been acknowledged.
  403. ;Only ds and ax have been saved.
  404.     assume    ds:nothing
  405.     ret
  406.  
  407.     include    timeout.asm
  408.     include    multicrc.asm
  409.  
  410.     public    timer_isr
  411. timer_isr:
  412. ;if the first instruction is an iret, then the timer is not hooked
  413.     iret
  414.  
  415. ;any code after this will not be kept.  Buffers used by the program, if any,
  416. ;are allocated from the memory between end_resident and end_free_mem.
  417.     public end_resident,end_free_mem
  418. end_resident    label    byte
  419. end_free_mem    label    byte
  420.  
  421.  
  422. int_no_name    db    "Interrupt number ",'$'
  423. io_addr_name    db    "I/O port ",'$'
  424.  
  425. bmpr13_val    db    0
  426.  
  427.     extrn    set_recv_isr: near
  428.  
  429. ;enter with si -> argument string, di -> wword to store.
  430. ;if there is no number, don't change the number.
  431.     extrn    get_number: near
  432.  
  433. ;enter with dx -> argument string, di -> wword to print.
  434.     extrn    print_number: near
  435.  
  436. ;-> the assigned Ethernet address of the card.
  437.     extrn    rom_address: byte
  438.  
  439. ;----------------------------------------------------------------------
  440. ;   initialize ethercoupler and prepare driver for operation
  441. ;----------------------------------------------------------------------
  442.     public    etopen
  443. etopen:
  444.     call    get_board_parameters
  445.  
  446.     WEC_reg    DLCR6,DLC_EN    ;disable data link ctrler prior to init
  447. ; DLC shut off, we can now safely init all reg values.
  448. ; DLCR6 is also config reg 0, so don't need to reload it
  449.     Or    AL,SRAM_CYCLE_CLK + BUFFER_BUSW
  450.             ; 100NS SRAM cycle, 8 bit system bus width, 8 bit
  451.             ; buffer bus width
  452.     Or    AL,TBS_2_2    ;2 2K Tx Buffer
  453.     Or    AL,BS_32    ;total buffer size of 32K bytes
  454.     Out    DX,AL
  455.  
  456.     WEC_reg    DLCR0,TX_DONE+TX_PKT_RCD+JABBER+COL+COL16
  457.         ;clear Tx status'es and the associated interrupts
  458.     WEC_reg    DLCR1,0ffh    ;rcv status reg - clear all condx
  459.     WEC_reg    DLCR2,0        ;disable all Tx src's of interrupts
  460.     WEC_reg    DLCR3,RX_PKT_IE+RX_BUF_OVFL
  461.     WEC_reg    DLCR4,LBC    ;not loopback, Tx defer to carrier sense
  462.                 ;no aloha here!
  463.     WEC_reg    DLCR5,0        ;receive mode 1, for now.
  464.     WEC_reg    DLCR7,PWRON+RDYPNSEL+RBS_BMPR
  465.     WEC_reg    BMPR11,0    ;clear collison controls
  466.     WEC_reg    BMPR12,0    ;clear DMA enables
  467.     mov    al,bmpr13_val
  468.     WEC_reg    BMPR13
  469.     WEC_reg    BMPR14,FILTER_SELF_RX
  470. ;
  471. ; registers are all set, now setup the station MAC address
  472. ;
  473.     mov    di,io_addr
  474.     mov    si,offset rom_address
  475.     call    read_mac_addr
  476.  
  477.     mov    si,offset rom_address
  478.     mov    cx,EADDR_LEN
  479.     call    set_address        ;turns on the DLC
  480.  
  481.     Call    set_recv_isr    ;hook ourselves in
  482.  
  483.     REC_reg    DLCR6            ;get register contents
  484.     and    al,not DLC_EN        ;set DLC low (Enable)
  485.     WEC_reg    DLCR6            ;enable EtherCoupler
  486.  
  487. ;if all is okay,
  488.     mov    dx,offset end_resident
  489.     clc
  490.     ret
  491. ;if we got an error,
  492. EC_problem:
  493. noEC:
  494.     stc
  495.     ret
  496.  
  497.     public    print_parameters
  498. print_parameters:
  499. ;echo our command-line parameters
  500.     mov    di,offset int_no
  501.     mov    dx,offset int_no_name
  502.     call    print_number
  503.     mov    di,offset io_addr
  504.     mov    dx,offset io_addr_name
  505.     call    print_number
  506.     ret
  507.  
  508.