home *** CD-ROM | disk | FTP | other *** search
/ Netware Super Library / Netware Super Library.iso / drivers / nics / pktdrv7 / isolan.asm < prev    next >
Encoding:
Assembly Source File  |  1990-07-27  |  13.2 KB  |  626 lines

  1. version    equ    1
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ; Packet driver for BICC Data Networks' ISOLAN 4110 ethernet
  6. ; controller, written by
  7. ;    Rainer Toebbicke
  8. ;    European Organisation of Nuclear Research (CERN)
  9. ;    Geneva, Switzerland
  10. ; based on the "generic" packet driver by Russell Nelson.
  11.  
  12.  
  13.  
  14. ; BICC ISOLAN card constants
  15.  
  16. IS_SAP    struc            ;Service Access Point channel
  17. IS_S_Data    db    ?    ;data semaphore
  18. IS_S_Taken    db    ?    ;taken semaphore
  19.         dw    ?
  20.  
  21. IS_S_Event    db    ?
  22.  
  23. IS_S_SrcEaddr    db    6 dup(?)    ;source Ethernet address
  24. IS_S_SrcLsap    db    ?
  25. IS_S_DstEaddr    db    6 dup(?)
  26. IS_S_DstLsap    db    ?
  27.         db    ?
  28. IS_S_Status    dw    ?
  29.         db    ?
  30. IS_S_SDUptr    dw    ?
  31. IS_SAP        ends
  32.  
  33. ; Bits defined in IS_S_Event
  34. IS_M_Init    equ    0ch
  35. IS_M_DataRq    equ    09h
  36. IS_M_DataInd    equ    0ah
  37. IS_Board_Init    equ    0dh
  38.  
  39.  
  40. IS        segment    at 0
  41.         org    8000h
  42. IS_Sign        db    ?        ;test for card presence
  43. IS_Reset    db    ?
  44. IS_Diagok    db    ?
  45. IS_Error    db    ?
  46. IS_ErrCode    db    ?
  47.         org    800eh
  48. IS_PgmStart    dw    ?
  49.  
  50. IS_IER        db    ?        ;interrupt enable register
  51. IS_I_Tx        equ    01h        ;transmit interrupt
  52. IS_I_Rx        equ    02h        ;receive interrupt
  53.  
  54. IS_ISR        db    ?        ;interrupt status reg
  55.         org    8014h
  56. IS_BlueBook    db    ?
  57. IS_LLC1        db    ?
  58. IS_Precv    db    ?        ;promiscuous receive flag
  59. IS_LanceRev    db    ?
  60. IS_MacReflSup    db    ?        ;MAC reflection suppression
  61.         org    8020h
  62. IS_Xmit        IS_SAP    <>        ;Transmit channel
  63.         org    8040h
  64. IS_Rcv        IS_SAP    <>        ;Receive channel
  65.         org    8060h
  66. IS_Eaddr    db    6 dup(?)    ;This card's Ethernet address
  67.  
  68. IS        ends
  69.  
  70.  
  71. IS_SDU        struc
  72. IS_SDU_DataOff    db    ?        ;offset to data
  73. IS_SDU_L    dw    ?        ;length of packet
  74. IS_SDU        ends
  75.  
  76.  
  77. ENET_HDR    equ    EADDR_LEN*2+2    ;length of ethernet header
  78.  
  79.  
  80.  
  81. code    segment    word public
  82.     assume    cs:code, ds:code
  83.  
  84.     public    int_no,    MemBase
  85. int_no    db    2,0,0,0            ;must be four bytes long for get_number.
  86. MemBase    dw    0b800h,0
  87.  
  88.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  89. driver_class    db    1        ;from the packet spec
  90. driver_type    db    4+128        ;from the packet spec
  91. driver_name    db    'ISOLAN',0    ;name of the driver.
  92. driver_function    db    2
  93. parameter_list    label    byte
  94.     db    1    ;major rev of packet driver
  95.     db    9    ;minor rev of packet driver
  96.     db    14    ;length of parameter list
  97.     db    EADDR_LEN    ;length of MAC-layer address
  98.     dw    GIANT    ;MTU, including MAC headers
  99.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  100.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  101.     dw    0    ;(# of successive xmits) - 1
  102. int_num    dw    0    ;Interrupt # to hook for post-EOI
  103.             ;processing, 0 == none,
  104.  
  105.     public    rcv_modes
  106. rcv_modes    dw    4        ;number of receive modes in our table.
  107.         dw    0,0,0,rcv_mode_3
  108.  
  109.     public    as_send_pkt
  110. ; The Asynchronous Transmit Packet routine.
  111. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  112. ;   interrupts possibly enabled.
  113. ; Exit with nc if ok, or else cy if error, dh set to error number.
  114. ;   es:di and interrupt enable flag preserved on exit.
  115. as_send_pkt:
  116.     ret
  117.  
  118.     public    drop_pkt
  119. ; Drop a packet from the queue.
  120. ; Enter with es:di -> iocb.
  121. drop_pkt:
  122.     assume    ds:nothing
  123.     ret
  124.  
  125.     public    xmit
  126. ; Process a transmit interrupt with the least possible latency to achieve
  127. ;   back-to-back packet transmissions.
  128. ; May only use ax and dx.
  129. xmit:
  130.     assume    ds:nothing
  131.     ret
  132.  
  133.  
  134.     public    send_pkt
  135. send_pkt:
  136. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  137. ;  (only if the high-performance bit is set in driver_function)
  138. ;enter with ds:si -> packet, cx = packet length.
  139. ;exit with nc if ok, or else cy if error, dh set to error number.
  140.     assume    ds:nothing
  141.  
  142.     cld                ;moves go forward
  143.     mov    ax,MemBase
  144.     mov    es,ax            ;address the card
  145.     assume    es:IS
  146.     push    cx            ;save length
  147.  
  148. ; Wait for the transmit channel to become free
  149.     mov    cx,0ffffh        ;avoid infinite loop
  150. tx_wait:
  151.     test    IS_Xmit.IS_S_Data,0ffh
  152.     jnz    tx_idle
  153.     loop    tx_wait
  154.     pop    cx            ;remove from stack
  155.     mov    dh,CANT_SEND        ;transmit error
  156.     stc
  157.     ret
  158.  
  159. tx_idle:
  160.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  161.     mov    IS_Xmit.IS_S_Event,IS_M_DataRq    ;sending Data
  162.  
  163. ; copy destination ethernet addr
  164.     mov    cx,EADDR_LEN/2
  165.     lea    di,IS_Xmit.IS_S_DstEaddr
  166.     rep    movsw
  167.  
  168. ; copy source ethernet addr
  169.     mov    cx,EADDR_LEN/2
  170.     lea    di,IS_Xmit.IS_S_SrcEaddr
  171.     rep    movsw
  172.  
  173. ; copy type field
  174.     lodsw
  175.     xchg    ah,al                ;8086 order
  176.     mov    IS_Xmit.IS_S_Status,ax
  177.  
  178.     pop    cx                ;restore count
  179.     sub    cx,ENET_HDR            ;minus header
  180.  
  181.     mov    di,IS_Xmit.IS_S_SDUptr        ;point to SDU
  182.     mov    es:IS_SDU_L[di],cx        ;set count
  183.     xor    ah,ah
  184.     mov    al,es:IS_SDU_DataOff[di]
  185.     add    di,ax                ;point to data
  186.  
  187.     call    movemem                ; now copy the buffer
  188.  
  189.     mov    IS_Xmit.IS_S_Taken,1        ;release channel
  190.     clc                    ;no error occurred
  191.     ret
  192.     assume    es:nothing
  193.  
  194.  
  195.     include    movemem.asm
  196.  
  197.  
  198.     public    get_address
  199. get_address:
  200. ;get the address of the interface.
  201. ;enter with es:di -> place to get the address, cx = size of address buffer.
  202. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  203.     assume    ds:code
  204.     cmp    cx,EADDR_LEN
  205.     jnb    get_addr_ok        ;buffer ok
  206.     stc
  207.     ret
  208.  
  209. get_addr_ok:
  210.     push    ds
  211.     push    si
  212.     mov    ax,MemBase        ;point to interface
  213.     mov    ds,ax
  214.     assume    ds:IS
  215.  
  216.     mov    si,offset IS_Eaddr    ;point to our E-net addr
  217.     mov    cx,EADDR_LEN/2
  218.     rep    movsw
  219.     pop    si
  220.     pop    ds
  221.     mov    cl,EADDR_LEN
  222.     clc
  223.     ret
  224.  
  225.  
  226.  
  227.     public    set_address
  228. set_address:
  229. ;enter with ds:si -> Ethernet address, CX = length of address.
  230. ;exit with nc if okay, or cy, dh=error if any errors.
  231.     assume    ds:nothing
  232.     cmp    cx,EADDR_LEN
  233.     jnb    set_addr_ok        ;buffer ok
  234.     mov    dh,BAD_ADDRESS
  235.     stc
  236.     ret
  237.  
  238. set_addr_ok:
  239.     push    es
  240.     push    di
  241.     mov    ax,MemBase        ;point to interface
  242.     mov    es,ax
  243.     assume    es:IS
  244.  
  245.     mov    di,offset IS_Eaddr    ;point to our E-net addr
  246.     mov    cx,EADDR_LEN/2
  247.     rep    movsw
  248.  
  249. ; reset the board's software, don't really know if this is needed
  250.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  251.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  252.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  253.  
  254. ; wait for request to complete
  255.     mov    cx,0ffffh        ;avoid infinite loop
  256. set_wait_2:
  257.     test    IS_Xmit.IS_S_Data,0ffh
  258.     jnz    set_done
  259.     loop    set_wait_2
  260.  
  261. set_done:
  262.     mov    cx,EADDR_LEN        ;return their address length.
  263.     pop    di
  264.     pop    es
  265.     assume    es:nothing
  266.     clc
  267.     ret
  268.  
  269.  
  270.  
  271. rcv_mode_3:
  272. ;receive mode 3 is the only one we support, so we don't have to do anything.
  273.     ret
  274.  
  275.  
  276.     public    set_multicast_list
  277. set_multicast_list:
  278. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  279. ;return nc if we set all of them, or cy,dh=error if we didn't.
  280.     mov    dh,NO_MULTICAST
  281.     stc
  282.     ret
  283.  
  284.  
  285.     public    terminate
  286. terminate:
  287.     ret
  288.  
  289.     public    reset_interface
  290. reset_interface:
  291. ;reset the interface.
  292.     assume    ds:code
  293.     push    ds
  294.     mov    ax,MemBase
  295.     mov    ds,ax
  296.     assume    ds:IS
  297.     mov    IS_IER,0
  298.     pop    ds
  299.     ret
  300.  
  301.  
  302. ;called when we want to determine what to do with a received packet.
  303. ;enter with cx = packet length, es:di -> packet type.
  304.     extrn    recv_find: near
  305.  
  306. ;called after we have copied the packet into the buffer.
  307. ;enter with ds:si ->the packet, cx = length of the packet.
  308.     extrn    recv_copy: near
  309.  
  310.     extrn    count_in_err: near
  311.     extrn    count_out_err: near
  312.  
  313.     public    recv
  314. recv:
  315. ;called from the recv isr.  All registers have been saved, and ds=cs.
  316. ;Upon exit, the interrupt will be acknowledged.
  317.     assume    ds:code
  318.     mov    ax,MemBase
  319.     mov    ds,ax
  320.     assume    ds:IS
  321.  
  322.     mov    al,IS_ISR        ;get interrupt status
  323.     test    al,IS_I_RX        ;receive interrupt?
  324.     jnz    rcv_test_errors        ;yes...
  325.     jmp    rcv_done
  326.  
  327. rcv_test_errors:
  328.  
  329. ; some thorough testing missing here
  330. ; anyway, don't know what to test
  331.  
  332.  
  333. rcv_no_errors:
  334.     mov    IS_Rcv.IS_S_Data,0    ;block channel
  335.     mov    di,IS_Rcv.IS_S_SDUptr    ;point to SDU
  336.     mov    cx,IS_SDU_L[di]        ;get length
  337.     add    cx,ENET_HDR        ;plus ethernet header
  338.  
  339.  
  340. ; These following lines correctly point to the type field.
  341. ; However, addressability to the whole buffer on the 'receiver' call
  342. ; would be lost, a feature useful to some applications
  343.  
  344. ;    mov     ax,IS_Rcv.IS_S_Status ;get type field
  345. ;    xchg    ah,al         ;in network byte order
  346. ;    push    ax         ;have to place it somewhere
  347. ;    mov    di,sp
  348. ;    push    ss
  349. ;    pop    es            ;es:di at type field
  350.  
  351. ; The following 'hack' keeps addressability to the packet
  352. ; on the 'receiver' call but stays compatible with the
  353. ; packet driver skeleton.
  354. ; This feature is indicated by a bit in the type number (ugly)
  355. ; which the application can examine
  356.  
  357.     mov    al,IS_SDU_DataOff[di]    ;offset to to data
  358.     sub    al,2            ;offset to type field
  359.     cbw
  360.     add    di,ax            ;point to type field
  361.     push    ds
  362.     pop    es            ;es:di->type field
  363.  
  364.     push    cs
  365.     pop    ds            ;don't confuse recv_find
  366.     assume    ds:code
  367.     call    recv_find        ;do we want this packet?
  368. ;    add    sp,2               ;remove type field
  369.  
  370.     mov    ax,es
  371.     or    ax,di
  372.     jz    rcv_done_0        ;pointer zero, give up
  373.  
  374.     push    es
  375.     push    di            ;save pointer
  376.  
  377.     mov    ax,MemBase
  378.     mov    ds,ax
  379.     assume    ds:IS
  380.  
  381. ; set up ethernet header
  382.     mov    cx,EADDR_LEN/2
  383.     mov    si,offset IS_Rcv.IS_S_DstEaddr
  384.     rep    movsw
  385.     mov    cx,EADDR_LEN/2
  386.     mov    si,offset IS_Rcv.IS_S_SrcEaddr
  387.     rep    movsw
  388.     mov    ax,IS_Rcv.IS_S_Status        ;type field
  389.     xchg    ah,al                ;in network byte order
  390.     stosw
  391.  
  392.     mov    si,IS_Rcv.IS_S_SDUptr        ;point to SDU
  393.     mov    cx,IS_SDU_L[si]            ;get length
  394.     push    cx                ;save for later
  395.     mov    al,IS_SDU_DataOff[si]
  396.     xor    ah,ah
  397.     add    si,ax                ;point to data
  398.  
  399.     call    movemem
  400.  
  401.     pop    cx            ;restore count
  402.     pop    si            ;restore pointer
  403.     pop    ds            ;restore pointer
  404.     assume    ds:nothing
  405.  
  406.     add    cx,ENET_HDR        ;adjust length
  407.     call    recv_copy        ;wake up client
  408.  
  409. rcv_done_0:
  410.     mov    ax,MemBase        ;point to interface
  411.     mov    ds,ax
  412.     assume    ds:IS
  413.  
  414. rcv_done:
  415.     mov    IS_Rcv.IS_S_Taken,1    ;release channel
  416.     mov    IS_ISR,0        ;clear interrupt
  417.     push    cs
  418.     pop    ds
  419.     assume    ds:code
  420.     ret
  421.  
  422.  
  423.     public    recv_exiting
  424. recv_exiting:
  425. ;called from the recv isr after interrupts have been acknowledged.
  426. ;Only ds and ax have been saved.
  427.     assume    ds:nothing
  428.     ret
  429.  
  430.  
  431. ;any code after this will not be kept after initialization.
  432. end_resident    label    byte
  433.  
  434.  
  435.     public    usage_msg
  436. usage_msg db "usage: ISOLAN [-n] [-d] [-w] <packet_int_no> <int_level>    <mem_addr>",CR,LF,'$'
  437.  
  438.     public    copyright_msg
  439. copyright_msg    db    "Packet    driver for BICC    ISOLAN device, version ",'0'+version,CR,LF
  440.         db    "Portions Copyright 1989, R.Toebbicke, CERN, Switzerland",CR,LF
  441.         db    '$'
  442.  
  443. errmsg1    db    "No BICC Isolan    board found at this address.",CR,LF,'$'
  444. diag_errmsg    db    "Error - ISOLAN    Diagnostics failed.$"
  445.  
  446. diag_start_msg    db    "ISOLAN    Diagnostics running... $"
  447. diag_end_msg    db    " done.$"
  448.  
  449. int_no_name    db    "Interrupt number $"
  450. MemBaseName    db    "Shared    Memory address $"
  451. MemPrt    dw    0c000h,0
  452.  
  453.  
  454.  
  455.     extrn    set_recv_isr: near
  456.  
  457. ;enter with si -> argument string, di -> word to store.
  458. ;if there is no number, don't change the number.
  459.     extrn    get_number: near
  460.  
  461. ;enter with dx -> name of word, di -> dword to print.
  462.     extrn    print_number: near
  463.  
  464.     public    parse_args
  465. parse_args:
  466. ;exit with nc if all went well, cy otherwise.
  467.     mov    di,offset int_no
  468.     call    get_number
  469.     mov    di,offset MemPrt
  470.     call    get_number
  471.     mov    di,MemPrt
  472.     sub    di,800h            ;BICC standard notation
  473.     mov    MemBase,di
  474.     clc
  475.     ret
  476.  
  477.  
  478. bad_board:
  479.     mov    dx,offset errmsg1
  480. err_msg:
  481.     assume    ds:nothing
  482.     push    cs
  483.     pop    ds
  484.     mov    ah,9
  485.     int    21h
  486.     stc
  487.     ret
  488.  
  489.  
  490.     public    etopen
  491. etopen:
  492.     mov    ax,MemBase
  493.     mov    ds,ax
  494.     assume    ds:IS
  495.  
  496. ; test if board exists
  497.     mov    IS_Sign,42
  498.     cmp    IS_Sign,42
  499.     jne    bad_board
  500.  
  501.     mov    IS_Sign,0ffh-42
  502.     cmp    IS_Sign,0ffh-42
  503.     jne    bad_board
  504.  
  505.     cmp    IS_Reset,01h        ;already running?
  506.     je    diag_ok            ;yes, let it run
  507.  
  508.     mov    IS_Reset,0
  509.     mov    cx,0ffffh        ;avoid infinite loop
  510. diag_w_0:
  511.     cmp    IS_Reset,0fah
  512.     je    diag_1
  513.     loop    diag_w_0
  514.  
  515. diag_1:
  516.     mov    IS_Reset,0ffh
  517.     mov    cx,0ffffh        ;avoid infinite loop
  518. diag_w_1:
  519.     cmp    IS_Reset,0fah
  520.     je    diag_2
  521.     loop    diag_w_1
  522.  
  523. diag_2:
  524.     mov    IS_Reset,0e5h
  525.     mov    cx,0ffffh        ;avoid infinite loop
  526. diag_w_2:
  527.     cmp    IS_Reset,0fah
  528.     je    diag_3
  529.     loop    diag_w_2
  530.  
  531. diag_3:
  532.     mov    IS_Reset,09dh        ;start diagnostics
  533.  
  534.     push    ds
  535.     push    cs
  536.     pop    ds
  537.     mov    dx,offset diag_start_msg
  538.     mov    ah,9
  539.     int    21h
  540.     pop    ds
  541.  
  542.     mov    bx,050h            ;double loop, takes some time
  543. diag_w_3_0:
  544.     mov    cx,0ffffh        ;avoid infinite loop
  545. diag_w_3:
  546.     cmp    IS_Diagok,01h
  547.     je    diag_4
  548.     loop    diag_w_3
  549.     dec    bx
  550.     jnz    diag_w_3_0
  551.     mov    dx,offset diag_errmsg
  552.  
  553. diag_4:
  554.     push    ds
  555.     push    cs
  556.     pop    ds
  557.     mov    dx,offset diag_end_msg
  558.     mov    ah,9
  559.     int    21h
  560.     pop    ds
  561.  
  562.     mov    ax,0800h
  563.     mov    IS_PgmStart,ax
  564.     mov    IS_Reset,01h        ;run the program
  565.  
  566.  
  567. ; enable the board's interrupts
  568. diag_ok:
  569.     push    ds
  570.     push    cs
  571.     pop    ds            ;set cs=ds
  572.     call    set_recv_isr
  573.     pop    ds
  574.  
  575.     mov    IS_BlueBook,1        ;enable Blue Book MAC
  576.     mov    IS_LLC1,1        ;disable LLC1 service
  577.     mov    IS_MacReflSup,1        ;suppress MAC reflection
  578.     mov    IS_IER,IS_I_RX        ;enable for receive
  579.     mov    IS_ISR,0        ;clear previous
  580.  
  581. ; reset the board's software, just in case...
  582.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  583.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  584.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  585.  
  586. ; again wait for request to complete
  587.     mov    cx,0ffffh        ;avoid infinite loop
  588. in_wait_2:
  589.     test    IS_Xmit.IS_S_Data,0ffh
  590.     jnz    in_done
  591.     loop    in_wait_2
  592.  
  593. in_done:
  594.  
  595.     mov    al, int_no        ; Get board's interrupt vector
  596.     add    al, 8
  597.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  598.     jb    set_int_num        ; No.
  599.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  600. set_int_num:
  601.     xor    ah, ah            ; Clear high byte
  602.     mov    int_num, ax        ; Set parameter_list int num.
  603.  
  604. ;if all is okay,
  605.     mov    dx,offset end_resident
  606.     push    cs
  607.     pop    ds
  608.     clc
  609.     ret
  610.  
  611.     public    print_parameters
  612. print_parameters:
  613. ;echo our command-line parameters
  614.     mov    di,offset int_no
  615.     mov    dx,offset int_no_name
  616.     call    print_number
  617.     mov    di,offset MemPrt
  618.     mov    dx,offset MemBaseName
  619.     call    print_number
  620.     ret
  621.  
  622.  
  623. code    ends
  624.  
  625.     end
  626.