home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / driver6s / isolan.asm < prev    next >
Assembly Source File  |  1990-03-15  |  13KB  |  608 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    byte 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.     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    send_pkt
  110. send_pkt:
  111. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  112. ;  (only if the high-performance bit is set in driver_function)
  113. ;enter with ds:si -> packet, cx = packet length.
  114. ;exit with nc if ok, or else cy if error, dh set to error number.
  115.     assume    ds:nothing
  116.  
  117.     cld                ;moves go forward
  118.     mov    ax,MemBase
  119.     mov    es,ax            ;address the card
  120.     assume    es:IS
  121.     push    cx            ;save length
  122.  
  123. ; Wait for the transmit channel to become free
  124.     mov    cx,0ffffh        ;avoid infinite loop
  125. tx_wait:
  126.     test    IS_Xmit.IS_S_Data,0ffh
  127.     jnz    tx_idle
  128.     loop    tx_wait
  129.     pop    cx            ;remove from stack
  130.     mov    dh,CANT_SEND        ;transmit error
  131.     stc
  132.     ret
  133.  
  134. tx_idle:
  135.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  136.     mov    IS_Xmit.IS_S_Event,IS_M_DataRq    ;sending Data
  137.  
  138. ; copy destination ethernet addr
  139.     mov    cx,EADDR_LEN/2
  140.     lea    di,IS_Xmit.IS_S_DstEaddr
  141.     rep    movsw
  142.  
  143. ; copy source ethernet addr
  144.     mov    cx,EADDR_LEN/2
  145.     lea    di,IS_Xmit.IS_S_SrcEaddr
  146.     rep    movsw
  147.  
  148. ; copy type field
  149.     lodsw
  150.     xchg    ah,al                ;8086 order
  151.     mov    IS_Xmit.IS_S_Status,ax
  152.  
  153.     pop    cx                ;restore count
  154.     sub    cx,ENET_HDR            ;minus header
  155.  
  156.     mov    di,IS_Xmit.IS_S_SDUptr        ;point to SDU
  157.     mov    es:IS_SDU_L[di],cx        ;set count
  158.     xor    ah,ah
  159.     mov    al,es:IS_SDU_DataOff[di]
  160.     add    di,ax                ;point to data
  161.  
  162.     call    movemem                ; now copy the buffer
  163.  
  164.     mov    IS_Xmit.IS_S_Taken,1        ;release channel
  165.     clc                    ;no error occurred
  166.     ret
  167.     assume    es:nothing
  168.  
  169.  
  170. movemem:
  171. ;does the same thing as "rep movsb", only 50% faster.
  172. ;moves words instead of bytes, and handles the case of both addresses odd
  173. ;efficiently.  There is no way to handle one address odd efficiently.
  174. ;This routine always aligns the source address in the hopes that the
  175. ;destination address will also get aligned.  This is from Phil Karn's
  176. ;code from ec.c, a part of his NET package.  I bummed a few instructions
  177. ;out.
  178.     jcxz    movemem_cnte        ; If zero, we're done already.
  179.     test    si,1            ; Does source start on odd byte?
  180.     jz    movemem_adre        ; Go if not
  181.     movsb                ; Yes, move the first byte
  182.     dec    cx            ; Count that byte
  183. movemem_adre:
  184.     shr    cx,1            ; convert to word count
  185.     rep    movsw            ; Move the bulk as words
  186.     jnc    movemem_cnte        ; Go if the count was even
  187.     movsb                ; Move leftover last byte
  188. movemem_cnte:
  189.     ret
  190.  
  191.  
  192.     public    get_address
  193. get_address:
  194. ;get the address of the interface.
  195. ;enter with es:di -> place to get the address, cx = size of address buffer.
  196. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  197.     assume    ds:code
  198.     cmp    cx,EADDR_LEN
  199.     jnb    get_addr_ok        ;buffer ok
  200.     stc
  201.     ret
  202.  
  203. get_addr_ok:
  204.     push    ds
  205.     push    si
  206.     mov    ax,MemBase        ;point to interface
  207.     mov    ds,ax
  208.     assume    ds:IS
  209.  
  210.     mov    si,offset IS_Eaddr    ;point to our E-net addr
  211.     mov    cx,EADDR_LEN/2
  212.     rep    movsw
  213.     pop    si
  214.     pop    ds
  215.     mov    cl,EADDR_LEN
  216.     clc
  217.     ret
  218.  
  219.  
  220.  
  221.     public    set_address
  222. set_address:
  223. ;enter with ds:si -> Ethernet address, CX = length of address.
  224. ;exit with nc if okay, or cy, dh=error if any errors.
  225.     assume    ds:nothing
  226.     cmp    cx,EADDR_LEN
  227.     jnb    set_addr_ok        ;buffer ok
  228.     mov    dh,BAD_ADDRESS
  229.     stc
  230.     ret
  231.  
  232. set_addr_ok:
  233.     push    es
  234.     push    di
  235.     mov    ax,MemBase        ;point to interface
  236.     mov    es,ax
  237.     assume    es:IS
  238.  
  239.     mov    di,offset IS_Eaddr    ;point to our E-net addr
  240.     mov    cx,EADDR_LEN/2
  241.     rep    movsw
  242.  
  243. ; reset the board's software, don't really know if this is needed
  244.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  245.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  246.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  247.  
  248. ; wait for request to complete
  249.     mov    cx,0ffffh        ;avoid infinite loop
  250. set_wait_2:
  251.     test    IS_Xmit.IS_S_Data,0ffh
  252.     jnz    set_done
  253.     loop    set_wait_2
  254.  
  255. set_done:
  256.     mov    cx,EADDR_LEN        ;return their address length.
  257.     pop    di
  258.     pop    es
  259.     assume    es:nothing
  260.     clc
  261.     ret
  262.  
  263.  
  264.  
  265. rcv_mode_3:
  266. ;receive mode 3 is the only one we support, so we don't have to do anything.
  267.     ret
  268.  
  269.  
  270.     public    set_multicast_list
  271. set_multicast_list:
  272. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  273. ;return nc if we set all of them, or cy,dh=error if we didn't.
  274.     mov    dh,NO_MULTICAST
  275.     stc
  276.     ret
  277.  
  278.  
  279.     public    terminate
  280. terminate:
  281.     ret
  282.  
  283.     public    reset_interface
  284. reset_interface:
  285. ;reset the interface.
  286.     assume    ds:code
  287.     push    ds
  288.     mov    ax,MemBase
  289.     mov    ds,ax
  290.     assume    ds:IS
  291.     mov    IS_IER,0
  292.     pop    ds
  293.     ret
  294.  
  295.  
  296. ;called when we want to determine what to do with a received packet.
  297. ;enter with cx = packet length, es:di -> packet type.
  298.     extrn    recv_find: near
  299.  
  300. ;called after we have copied the packet into the buffer.
  301. ;enter with ds:si ->the packet, cx = length of the packet.
  302.     extrn    recv_copy: near
  303.  
  304.     extrn    count_in_err: near
  305.     extrn    count_out_err: near
  306.  
  307.     public    recv
  308. recv:
  309. ;called from the recv isr.  All registers have been saved, and ds=cs.
  310. ;Upon exit, the interrupt will be acknowledged.
  311.     assume    ds:code
  312.     mov    ax,MemBase
  313.     mov    ds,ax
  314.     assume    ds:IS
  315.  
  316.     mov    al,IS_ISR        ;get interrupt status
  317.     test    al,IS_I_RX        ;receive interrupt?
  318.     jnz    rcv_test_errors        ;yes...
  319.     jmp    rcv_done
  320.  
  321. rcv_test_errors:
  322.  
  323. ; some thorough testing missing here
  324. ; anyway, don't know what to test
  325.  
  326.  
  327. rcv_no_errors:
  328.     mov    IS_Rcv.IS_S_Data,0    ;block channel
  329.     mov    di,IS_Rcv.IS_S_SDUptr    ;point to SDU
  330.     mov    cx,IS_SDU_L[di]        ;get length
  331.     add    cx,ENET_HDR        ;plus ethernet header
  332.  
  333.  
  334. ; These following lines correctly point to the type field.
  335. ; However, addressability to the whole buffer on the 'receiver' call
  336. ; would be lost, a feature useful to some applications
  337.  
  338. ;    mov     ax,IS_Rcv.IS_S_Status ;get type field
  339. ;    xchg    ah,al         ;in network byte order
  340. ;    push    ax         ;have to place it somewhere
  341. ;    mov    di,sp
  342. ;    push    ss
  343. ;    pop    es            ;es:di at type field
  344.  
  345. ; The following 'hack' keeps addressability to the packet
  346. ; on the 'receiver' call but stays compatible with the
  347. ; packet driver skeleton.
  348. ; This feature is indicated by a bit in the type number (ugly)
  349. ; which the application can examine
  350.  
  351.     mov    al,IS_SDU_DataOff[di]    ;offset to to data
  352.     sub    al,2            ;offset to type field
  353.     cbw
  354.     add    di,ax            ;point to type field
  355.     push    ds
  356.     pop    es            ;es:di->type field
  357.  
  358.     push    cs
  359.     pop    ds            ;don't confuse recv_find
  360.     assume    ds:code
  361.     call    recv_find        ;do we want this packet?
  362. ;    add    sp,2               ;remove type field
  363.  
  364.     mov    ax,es
  365.     or    ax,di
  366.     jz    rcv_done_0        ;pointer zero, give up
  367.  
  368.     push    es
  369.     push    di            ;save pointer
  370.  
  371.     mov    ax,MemBase
  372.     mov    ds,ax
  373.     assume    ds:IS
  374.  
  375. ; set up ethernet header
  376.     mov    cx,EADDR_LEN/2
  377.     mov    si,offset IS_Rcv.IS_S_DstEaddr
  378.     rep    movsw
  379.     mov    cx,EADDR_LEN/2
  380.     mov    si,offset IS_Rcv.IS_S_SrcEaddr
  381.     rep    movsw
  382.     mov    ax,IS_Rcv.IS_S_Status        ;type field
  383.     xchg    ah,al                ;in network byte order
  384.     stosw
  385.  
  386.     mov    si,IS_Rcv.IS_S_SDUptr        ;point to SDU
  387.     mov    cx,IS_SDU_L[si]            ;get length
  388.     push    cx                ;save for later
  389.     mov    al,IS_SDU_DataOff[si]
  390.     xor    ah,ah
  391.     add    si,ax                ;point to data
  392.  
  393.     call    movemem
  394.  
  395.     pop    cx            ;restore count
  396.     pop    si            ;restore pointer
  397.     pop    ds            ;restore pointer
  398.     assume    ds:nothing
  399.  
  400.     add    cx,ENET_HDR        ;adjust length
  401.     call    recv_copy        ;wake up client
  402.  
  403. rcv_done_0:
  404.     mov    ax,MemBase        ;point to interface
  405.     mov    ds,ax
  406.     assume    ds:IS
  407.  
  408. rcv_done:
  409.     mov    IS_Rcv.IS_S_Taken,1    ;release channel
  410.     mov    IS_ISR,0        ;clear interrupt
  411.     push    cs
  412.     pop    ds
  413.     assume    ds:code
  414.     ret
  415.  
  416.  
  417.     public    recv_exiting
  418. recv_exiting:
  419. ;called from the recv isr after interrupts have been acknowledged.
  420. ;Only ds and ax have been saved.
  421.     assume    ds:nothing
  422.     ret
  423.  
  424.  
  425. ;any code after this will not be kept after initialization.
  426. end_resident    label    byte
  427.  
  428.  
  429.     public    usage_msg
  430. usage_msg db "usage: ISOLAN <packet_int_no> <int_level>    <mem_addr>",CR,LF,'$'
  431.  
  432.     public    copyright_msg
  433. copyright_msg    db    "Packet    driver for BICC    ISOLAN device, version ",'0'+version,CR,LF
  434.         db    "Portions Copyright 1989, R.Toebbicke, CERN, Switzerland",CR,LF
  435.  
  436.  
  437. errmsg1    db    "No BICC Isolan    board found at this address.",CR,LF,'$'
  438. diag_errmsg    db    "Error - ISOLAN    Diagnostics failed.$"
  439.  
  440. diag_start_msg    db    "ISOLAN    Diagnostics running... $"
  441. diag_end_msg    db    " done.$"
  442.  
  443. int_no_name    db    "Interrupt number $"
  444. MemBaseName    db    "Shared    Memory address $"
  445. MemPrt    dw    0c000h,0
  446.  
  447.  
  448.  
  449.     extrn    set_recv_isr: near
  450.  
  451. ;enter with si -> argument string, di -> word to store.
  452. ;if there is no number, don't change the number.
  453.     extrn    get_number: near
  454.  
  455. ;enter with dx -> name of word, di -> dword to print.
  456.     extrn    print_number: near
  457.  
  458.     public    parse_args
  459. parse_args:
  460. ;exit with nc if all went well, cy otherwise.
  461.     mov    di,offset int_no
  462.     call    get_number
  463.     mov    di,offset MemPrt
  464.     call    get_number
  465.     mov    di,MemPrt
  466.     sub    di,800h            ;BICC standard notation
  467.     mov    MemBase,di
  468.     clc
  469.     ret
  470.  
  471.  
  472. bad_board:
  473.     mov    dx,offset errmsg1
  474. err_msg:
  475.     assume    ds:nothing
  476.     push    cs
  477.     pop    ds
  478.     mov    ah,9
  479.     int    21h
  480.     stc
  481.     ret
  482.  
  483.  
  484.     public    etopen
  485. etopen:
  486.     mov    ax,MemBase
  487.     mov    ds,ax
  488.     assume    ds:IS
  489.  
  490. ; test if board exists
  491.     mov    IS_Sign,42
  492.     cmp    IS_Sign,42
  493.     jne    bad_board
  494.  
  495.     mov    IS_Sign,0ffh-42
  496.     cmp    IS_Sign,0ffh-42
  497.     jne    bad_board
  498.  
  499.     cmp    IS_Reset,01h        ;already running?
  500.     je    diag_ok            ;yes, let it run
  501.  
  502.     mov    IS_Reset,0
  503.     mov    cx,0ffffh        ;avoid infinite loop
  504. diag_w_0:
  505.     cmp    IS_Reset,0fah
  506.     je    diag_1
  507.     loop    diag_w_0
  508.  
  509. diag_1:
  510.     mov    IS_Reset,0ffh
  511.     mov    cx,0ffffh        ;avoid infinite loop
  512. diag_w_1:
  513.     cmp    IS_Reset,0fah
  514.     je    diag_2
  515.     loop    diag_w_1
  516.  
  517. diag_2:
  518.     mov    IS_Reset,0e5h
  519.     mov    cx,0ffffh        ;avoid infinite loop
  520. diag_w_2:
  521.     cmp    IS_Reset,0fah
  522.     je    diag_3
  523.     loop    diag_w_2
  524.  
  525. diag_3:
  526.     mov    IS_Reset,09dh        ;start diagnostics
  527.  
  528.     push    ds
  529.     push    cs
  530.     pop    ds
  531.     mov    dx,offset diag_start_msg
  532.     mov    ah,9
  533.     int    21h
  534.     pop    ds
  535.  
  536.     mov    bx,050h            ;double loop, takes some time
  537. diag_w_3_0:
  538.     mov    cx,0ffffh        ;avoid infinite loop
  539. diag_w_3:
  540.     cmp    IS_Diagok,01h
  541.     je    diag_4
  542.     loop    diag_w_3
  543.     dec    bx
  544.     jnz    diag_w_3_0
  545.     mov    dx,offset diag_errmsg
  546.  
  547. diag_4:
  548.     push    ds
  549.     push    cs
  550.     pop    ds
  551.     mov    dx,offset diag_end_msg
  552.     mov    ah,9
  553.     int    21h
  554.     pop    ds
  555.  
  556.     mov    ax,0800h
  557.     mov    IS_PgmStart,ax
  558.     mov    IS_Reset,01h        ;run the program
  559.  
  560.  
  561. ; enable the board's interrupts
  562. diag_ok:
  563.     push    ds
  564.     push    cs
  565.     pop    ds            ;set cs=ds
  566.     call    set_recv_isr
  567.     pop    ds
  568.  
  569.     mov    IS_BlueBook,1        ;enable Blue Book MAC
  570.     mov    IS_LLC1,1        ;disable LLC1 service
  571.     mov    IS_MacReflSup,1        ;suppress MAC reflection
  572.     mov    IS_IER,IS_I_RX        ;enable for receive
  573.     mov    IS_ISR,0        ;clear previous
  574.  
  575. ; reset the board's software, just in case...
  576.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  577.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  578.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  579.  
  580. ; again wait for request to complete
  581.     mov    cx,0ffffh        ;avoid infinite loop
  582. in_wait_2:
  583.     test    IS_Xmit.IS_S_Data,0ffh
  584.     jnz    in_done
  585.     loop    in_wait_2
  586.  
  587. in_done:
  588.  
  589.     mov    di,offset int_no
  590.     mov    dx,offset int_no_name
  591.     call    print_number
  592.     mov    di,offset MemPrt
  593.     mov    dx,offset MemBaseName
  594.     call    print_number
  595.  
  596. ;if all is okay,
  597.     mov    dx,offset end_resident
  598.     push    cs
  599.     pop    ds
  600.     clc
  601.     ret
  602.  
  603.  
  604.  
  605. code    ends
  606.  
  607.     end
  608.