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

  1. version    equ    2
  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    BLUEBOOK, IEEE8023, 0        ;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.     include    movemem.asm
  110.     include    timeout.asm
  111.  
  112.     public bad_command_intercept
  113. bad_command_intercept:
  114. ;called with ah=command, unknown to the skeleton.
  115. ;exit with nc if okay, cy, dh=error if not.
  116.     mov    dh,BAD_COMMAND
  117.     stc
  118.     ret
  119.  
  120.     public    as_send_pkt
  121. ; The Asynchronous Transmit Packet routine.
  122. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  123. ;   interrupts possibly enabled.
  124. ; Exit with nc if ok, or else cy if error, dh set to error number.
  125. ;   es:di and interrupt enable flag preserved on exit.
  126. as_send_pkt:
  127.     ret
  128.  
  129.     public    drop_pkt
  130. ; Drop a packet from the queue.
  131. ; Enter with es:di -> iocb.
  132. drop_pkt:
  133.     assume    ds:nothing
  134.     ret
  135.  
  136.     public    xmit
  137. ; Process a transmit interrupt with the least possible latency to achieve
  138. ;   back-to-back packet transmissions.
  139. ; May only use ax and dx.
  140. xmit:
  141.     assume    ds:nothing
  142.     ret
  143.  
  144.  
  145.     public    send_pkt
  146. send_pkt:
  147. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  148. ;  (only if the high-performance bit is set in driver_function)
  149. ;enter with ds:si -> packet, cx = packet length.
  150. ;exit with nc if ok, or else cy if error, dh set to error number.
  151.     assume    ds:nothing
  152.  
  153.     cmp    cx,GIANT        ; Is this packet too large?
  154.     ja    send_pkt_toobig
  155.  
  156.     cld                ;moves go forward
  157.     mov    ax,MemBase
  158.     mov    es,ax            ;address the card
  159.     assume    es:IS
  160.     push    cx            ;save length
  161.  
  162. ; Wait for the transmit channel to become free
  163.     mov    cx,10            ;wait 10 36ths of a second.
  164.     call    set_timeout
  165. tx_wait:
  166.     test    IS_Xmit.IS_S_Data,0ffh
  167.     jnz    tx_idle
  168.     call    do_timeout
  169.     jnz    tx_wait
  170.     pop    cx            ;remove from stack
  171.     mov    dh,CANT_SEND        ;transmit error
  172.     stc
  173.     ret
  174.  
  175. send_pkt_toobig:
  176.     mov    dh,NO_SPACE
  177.     stc
  178.     ret
  179.  
  180. tx_idle:
  181.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  182.     mov    IS_Xmit.IS_S_Event,IS_M_DataRq    ;sending Data
  183.  
  184. ; copy destination ethernet addr
  185.     mov    cx,EADDR_LEN/2
  186.     lea    di,IS_Xmit.IS_S_DstEaddr
  187.     rep    movsw
  188.  
  189. ; copy source ethernet addr
  190.     mov    cx,EADDR_LEN/2
  191.     lea    di,IS_Xmit.IS_S_SrcEaddr
  192.     rep    movsw
  193.  
  194. ; copy type field
  195.     lodsw
  196.     xchg    ah,al                ;8086 order
  197.     mov    IS_Xmit.IS_S_Status,ax
  198.  
  199.     pop    cx                ;restore count
  200.     sub    cx,ENET_HDR            ;minus header
  201.  
  202.     mov    di,IS_Xmit.IS_S_SDUptr        ;point to SDU
  203.     mov    es:IS_SDU_L[di],cx        ;set count
  204.     xor    ah,ah
  205.     mov    al,es:IS_SDU_DataOff[di]
  206.     add    di,ax                ;point to data
  207.  
  208.     call    movemem                ; now copy the buffer
  209.  
  210.     mov    IS_Xmit.IS_S_Taken,1        ;release channel
  211.     clc                    ;no error occurred
  212.     ret
  213.     assume    es:nothing
  214.  
  215.  
  216.     public    set_address
  217. set_address:
  218. ;enter with ds:si -> Ethernet address, CX = length of address.
  219. ;exit with nc if okay, or cy, dh=error if any errors.
  220.     assume    ds:nothing
  221.     cmp    cx,EADDR_LEN
  222.     jnb    set_addr_ok        ;buffer ok
  223.     mov    dh,BAD_ADDRESS
  224.     stc
  225.     ret
  226.  
  227. set_addr_ok:
  228.     push    es
  229.     push    di
  230.     mov    ax,MemBase        ;point to interface
  231.     mov    es,ax
  232.     assume    es:IS
  233.  
  234.     mov    di,offset IS_Eaddr    ;point to our E-net addr
  235.     mov    cx,EADDR_LEN/2
  236.     rep    movsw
  237.  
  238. ; reset the board's software, don't really know if this is needed
  239.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  240.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;reboot
  241.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  242.  
  243. ; wait for request to complete
  244.     mov    cx,10            ;wait 10 36ths of a second.
  245.     call    set_timeout
  246. set_wait_2:
  247.     test    IS_Xmit.IS_S_Data,0ffh
  248.     jnz    set_done
  249.     call    do_timeout
  250.     jnz    set_wait_2
  251.  
  252. set_done:
  253.     mov    cx,EADDR_LEN        ;return their address length.
  254.     pop    di
  255.     pop    es
  256.     assume    es:nothing
  257.     clc
  258.     ret
  259.  
  260.  
  261.  
  262. rcv_mode_3:
  263. ;receive mode 3 is the only one we support, so we don't have to do anything.
  264.     ret
  265.  
  266.  
  267.     public    set_multicast_list
  268. set_multicast_list:
  269. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  270. ;  cx = number of bytes.
  271. ;return nc if we set all of them, or cy,dh=error if we didn't.
  272.     mov    dh,NO_MULTICAST
  273.     stc
  274.     ret
  275.  
  276.  
  277.     public    terminate
  278. terminate:
  279.     ret
  280.  
  281.     public    reset_interface
  282. reset_interface:
  283. ;reset the interface.
  284.     assume    ds:code
  285.     push    ds
  286.     mov    ax,MemBase
  287.     mov    ds,ax
  288.     assume    ds:IS
  289.     mov    IS_IER,0
  290.     pop    ds
  291.     ret
  292.  
  293.  
  294. ;called when we want to determine what to do with a received packet.
  295. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  296.     extrn    recv_find: near
  297.  
  298. ;called after we have copied the packet into the buffer.
  299. ;enter with ds:si ->the packet, cx = length of the packet.
  300.     extrn    recv_copy: near
  301.  
  302. ;call this routine to schedule a subroutine that gets run after the
  303. ;recv_isr.  This is done by stuffing routine's address in place
  304. ;of the recv_isr iret's address.  This routine should push the flags when it
  305. ;is entered, and should jump to recv_exiting_exit to leave.
  306. ;enter with ax = address of routine to run.
  307.     extrn    schedule_exiting: near
  308.  
  309. ;recv_exiting jumps here to exit, after pushing the flags.
  310.     extrn    recv_exiting_exit: near
  311.  
  312.     extrn    count_in_err: near
  313.     extrn    count_out_err: near
  314.  
  315.     public    recv
  316. recv:
  317. ;called from the recv isr.  All registers have been saved, and ds=cs.
  318. ;Upon exit, the interrupt will be acknowledged.
  319.     assume    ds:code
  320.     mov    ax,MemBase
  321.     mov    ds,ax
  322.     assume    ds:IS
  323.  
  324.     mov    al,IS_ISR        ;get interrupt status
  325.     test    al,IS_I_RX        ;receive interrupt?
  326.     jnz    rcv_test_errors        ;yes...
  327.     jmp    rcv_done
  328.  
  329. rcv_test_errors:
  330.  
  331. ; some thorough testing missing here
  332. ; anyway, don't know what to test
  333.  
  334.  
  335. rcv_no_errors:
  336.     mov    IS_Rcv.IS_S_Data,0    ;block channel
  337.     mov    di,IS_Rcv.IS_S_SDUptr    ;point to SDU
  338.     mov    cx,IS_SDU_L[di]        ;get length
  339.     add    cx,ENET_HDR        ;plus ethernet header
  340.  
  341.  
  342. ; These following lines correctly point to the type field.
  343. ; Addressability to the whole buffer on the 'receiver' call
  344. ; would be lost, a feature useful to some applications
  345.  
  346. ;    mov     ax,IS_Rcv.IS_S_Status ;get type field
  347. ;    xchg    ah,al         ;in network byte order
  348. ;    push    ax         ;have to place it somewhere
  349. ;    mov    di,sp
  350. ;    push    ss
  351. ;    pop    es            ;es:di at type field
  352.  
  353. ; The following 'hack' keeps addressability to the packet
  354. ; on the 'receiver' call but stays compatible with the
  355. ; packet driver skeleton.
  356. ; This feature is indicated by a bit in the type number (ugly)
  357. ; which the application can examine
  358.  
  359.     mov    al,IS_SDU_DataOff[di]    ;offset to to data
  360.     sub    al,2            ;offset to type field
  361.     cbw
  362.     add    di,ax            ;point to type field
  363.     movseg    es,ds
  364.  
  365.     movseg    ds,cs
  366.     assume    ds:code
  367.  
  368.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  369.     mov    ax, es:[di]
  370.     xchg    ah, al
  371.     cmp     ax, 1500
  372.     ja    BlueBookPacket
  373.     inc    di            ;set di to 802.2 header
  374.     inc    di
  375.     mov    dl, IEEE8023
  376. BlueBookPacket:
  377.     call    recv_find        ;do we want this packet?
  378. ;    add    sp,2               ;remove type field
  379.  
  380.     mov    ax,es
  381.     or    ax,di
  382.     jz    rcv_done_0        ;pointer zero, give up
  383.  
  384.     push    es
  385.     push    di            ;save pointer
  386.  
  387.     mov    ax,MemBase
  388.     mov    ds,ax
  389.     assume    ds:IS
  390.  
  391. ; set up ethernet header
  392.     mov    cx,EADDR_LEN/2
  393.     mov    si,offset IS_Rcv.IS_S_DstEaddr
  394.     rep    movsw
  395.     mov    cx,EADDR_LEN/2
  396.     mov    si,offset IS_Rcv.IS_S_SrcEaddr
  397.     rep    movsw
  398.     mov    ax,IS_Rcv.IS_S_Status        ;type field
  399.     xchg    ah,al                ;in network byte order
  400.     stosw
  401.  
  402.     mov    si,IS_Rcv.IS_S_SDUptr        ;point to SDU
  403.     mov    cx,IS_SDU_L[si]            ;get length
  404.     push    cx                ;save for later
  405.     mov    al,IS_SDU_DataOff[si]
  406.     xor    ah,ah
  407.     add    si,ax                ;point to data
  408.  
  409.     call    movemem
  410.  
  411.     pop    cx            ;restore count
  412.     pop    si            ;restore pointer
  413.     pop    ds            ;restore pointer
  414.     assume    ds:nothing
  415.  
  416.     add    cx,ENET_HDR        ;adjust length
  417.     call    recv_copy        ;wake up client
  418.  
  419. rcv_done_0:
  420.     mov    ax,MemBase        ;point to interface
  421.     mov    ds,ax
  422.     assume    ds:IS
  423.  
  424. rcv_done:
  425.     mov    IS_Rcv.IS_S_Taken,1    ;release channel
  426.     mov    IS_ISR,0        ;clear interrupt
  427.     movseg    ds,cs
  428.     assume    ds:code
  429.     ret
  430.  
  431.  
  432.     public    timer_isr
  433. timer_isr:
  434. ;if the first instruction is an iret, then the timer is not hooked
  435.     iret
  436.  
  437. ;any code after this will not be kept after initialization. Buffers
  438. ;used by the program, if any, are allocated from the memory between
  439. ;end_resident and end_free_mem.
  440.     public end_resident,end_free_mem
  441. end_resident    label    byte
  442. end_free_mem    label    byte
  443.  
  444.  
  445.     public    usage_msg
  446. usage_msg db "usage: ISOLAN [options] <packet_int_no> <int_level>    <mem_addr>",CR,LF,'$'
  447.  
  448.     public    copyright_msg
  449. copyright_msg    db    "Packet    driver for BICC    ISOLAN device, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  450.         db    "Portions Copyright 1989, R.Toebbicke, CERN, Switzerland",CR,LF
  451.         db    '$'
  452.  
  453. errmsg1    db    "No BICC Isolan    board found at this address.",CR,LF,'$'
  454. diag_errmsg    db    "Error - ISOLAN    Diagnostics failed.",CR,LF,'$'
  455.  
  456. diag_start_msg    db    "ISOLAN    Diagnostics running... $"
  457. diag_end_msg    db    " done.",CR,LF,'$'
  458.  
  459. int_no_name    db    "Interrupt number $"
  460. MemBaseName    db    "Shared    Memory address $"
  461. MemPrt    dw    0c000h,0
  462.  
  463.  
  464.  
  465.     extrn    set_recv_isr: near
  466.  
  467. ;enter with si -> argument string, di -> word to store.
  468. ;if there is no number, don't change the number.
  469.     extrn    get_number: near
  470.  
  471. ;enter with dx -> name of word, di -> dword to print.
  472.     extrn    print_number: near
  473.  
  474. ;-> the assigned Ethernet address of the card.
  475.     extrn    rom_address: byte
  476.  
  477.     public    parse_args
  478. parse_args:
  479. ;exit with nc if all went well, cy otherwise.
  480.     mov    di,offset int_no
  481.     call    get_number
  482.     mov    di,offset MemPrt
  483.     call    get_number
  484.     mov    di,MemPrt
  485.     sub    di,800h            ;BICC standard notation
  486.     mov    MemBase,di
  487.     clc
  488.     ret
  489.  
  490.  
  491. bad_board:
  492.     mov    dx,offset errmsg1
  493.     assume    ds:nothing
  494.     movseg    ds,cs
  495.     stc
  496.     ret
  497.  
  498.  
  499.     public    etopen
  500. etopen:
  501.     mov    ax,MemBase
  502.     mov    ds,ax
  503.     assume    ds:IS
  504.  
  505. ; test if board exists
  506.     mov    IS_Sign,42
  507.     cmp    IS_Sign,42
  508.     jne    bad_board
  509.  
  510.     mov    IS_Sign,0ffh-42
  511.     cmp    IS_Sign,0ffh-42
  512.     jne    bad_board
  513.  
  514.     cmp    IS_Reset,01h        ;already running?
  515.     jne    diag_not_ok
  516.     jmp    diag_ok            ;yes, let it run
  517. diag_not_ok:
  518.  
  519.     mov    IS_Reset,0
  520.     mov    cx,10            ;wait 10 36ths of a second.
  521.     call    set_timeout
  522. diag_w_0:
  523.     cmp    IS_Reset,0fah
  524.     je    diag_1
  525.     call    do_timeout
  526.     jne    diag_w_0
  527.  
  528. diag_1:
  529.     mov    IS_Reset,0ffh
  530.     mov    cx,10            ;wait 10 36ths of a second.
  531.     call    set_timeout
  532. diag_w_1:
  533.     cmp    IS_Reset,0fah
  534.     je    diag_2
  535.     call    do_timeout
  536.     jne    diag_w_1
  537.  
  538. diag_2:
  539.     mov    IS_Reset,0e5h
  540.     mov    cx,10            ;wait 10 36ths of a second.
  541.     call    set_timeout
  542. diag_w_2:
  543.     cmp    IS_Reset,0fah
  544.     je    diag_3
  545.     call    do_timeout
  546.     jne    diag_w_2
  547.  
  548. diag_3:
  549.     mov    IS_Reset,09dh        ;start diagnostics
  550.  
  551.     push    ds
  552.     push    cs
  553.     pop    ds
  554.     mov    dx,offset diag_start_msg
  555.     mov    ah,9
  556.     int    21h
  557.     pop    ds
  558.  
  559.     mov    bx,72            ;double loop, takes some time
  560. diag_w_3_0:
  561.     mov    cx,10            ;wait 10 36ths of a second.
  562.     call    set_timeout
  563. diag_w_3:
  564.     cmp    IS_Diagok,01h
  565.     je    diag_4
  566.     call    do_timeout
  567.     jne    diag_w_3
  568.     dec    bx
  569.     jnz    diag_w_3_0
  570.     mov    dx,offset diag_errmsg
  571.     stc
  572.     ret
  573.  
  574. diag_4:
  575.     push    ds
  576.     push    cs
  577.     pop    ds
  578.     mov    dx,offset diag_end_msg
  579.     mov    ah,9
  580.     int    21h
  581.     pop    ds
  582.  
  583.     mov    ax,0800h
  584.     mov    IS_PgmStart,ax
  585.     mov    IS_Reset,01h        ;run the program
  586.  
  587.  
  588. ; enable the board's interrupts
  589. diag_ok:
  590.  
  591. ; get the board's Ethernet address.
  592.       push    cs
  593.     pop    es
  594.     mov    si,offset IS_Eaddr    ;point to our E-net addr
  595.     mov    di,offset rom_address
  596.     mov    cx,EADDR_LEN/2
  597.     rep    movsw
  598.  
  599. ; enable the board's interrupts
  600.     push    ds
  601.     mov    ax,cs
  602.     mov    ds,ax            ;set ds=cs
  603.     call    set_recv_isr
  604.     pop    ds
  605.  
  606.     mov    IS_BlueBook,1        ;enable Blue Book MAC
  607.     mov    IS_LLC1,1        ;disable LLC1 service
  608.     mov    IS_MacReflSup,1        ;suppress MAC reflection
  609.     mov    IS_IER,IS_I_RX        ;enable for receive
  610.     mov    IS_ISR,0        ;clear previous
  611.  
  612. ; reset the board's software, just in case...
  613.     mov    IS_Xmit.IS_S_Data,0        ;our channel now
  614.     mov    IS_Xmit.IS_S_Event,IS_Board_Init ;init MAC layer
  615.     mov    IS_Xmit.IS_S_Taken,1        ;issue the command
  616.  
  617. ; again wait for request to complete
  618.     mov    cx,10            ;wait 10 36ths of a second.
  619.     call    set_timeout
  620. in_wait_2:
  621.     test    IS_Xmit.IS_S_Data,0ffh
  622.     jnz    in_done
  623.     call    do_timeout
  624.     jne    in_wait_2
  625.  
  626. in_done:
  627.  
  628.     mov    al, int_no        ; Get board's interrupt vector
  629.     add    al, 8
  630.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  631.     jb    set_int_num        ; No.
  632.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  633. set_int_num:
  634.     xor    ah, ah            ; Clear high byte
  635.     mov    int_num, ax        ; Set parameter_list int num.
  636.  
  637. ;if all is okay,
  638.     movseg    ds,cs
  639.     clc
  640.     ret
  641.  
  642.     public    print_parameters
  643. print_parameters:
  644. ;echo our command-line parameters
  645.     mov    di,offset int_no
  646.     mov    dx,offset int_no_name
  647.     call    print_number
  648.     mov    di,offset MemPrt
  649.     mov    dx,offset MemBaseName
  650.     call    print_number
  651.     ret
  652.  
  653.  
  654. code    ends
  655.  
  656.     end
  657.