home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / driver6s / arcnet.asm < prev    next >
Assembly Source File  |  1990-03-26  |  14KB  |  582 lines

  1. ;History:557,1
  2. ;Tue Feb 27 10:56:15 1990 send_pkt wasn't timing out properly.
  3. version    equ    0
  4.  
  5.     include    defs.asm
  6.  
  7. ;Ported from Philip Prindeville's arcnet driver for PCIP
  8. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  9.  
  10. ;  Copyright, 1988, 1989, Russell Nelson
  11.  
  12. ;   This program is free software; you can redistribute it and/or modify
  13. ;   it under the terms of the GNU General Public License as published by
  14. ;   the Free Software Foundation, version 1.
  15. ;
  16. ;   This program is distributed in the hope that it will be useful,
  17. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. ;   GNU General Public License for more details.
  20. ;
  21. ;   You should have received a copy of the GNU General Public License
  22. ;   along with this program; if not, write to the Free Software
  23. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25. code    segment    byte public
  26.     assume    cs:code, ds:code
  27.  
  28.  
  29. ;Registers:
  30.  
  31. ;the following I/O addresses are mapped to the COM 9026
  32. IMASK        equ    0        ; writeable
  33. STATUS        equ    0        ; readable
  34. COMMAND        equ    1
  35. ;the following I/O addresses are mapped to the 8253 counter/timer
  36. CNTR0        equ    4
  37. CNTR1        equ    5
  38. CNTR2        equ    6
  39. MODE        equ    7
  40. ;reading the following I/O addresse performs a software reset.
  41. SW_RST        equ    8
  42.  
  43. ; time needed to do various things (in clock ticks)
  44. RST_IVAL    equ    4        ;reset
  45. SEND_IVAL    equ    4        ;send
  46.  
  47. ; ARP type for ARCnet
  48. ARP_ARC        equ    007h
  49.  
  50. ; broadcast address is nid 0
  51. ARC_BCAST    equ    0
  52.  
  53. ; packet sizes
  54. ARC_MTU        equ    253
  55. ARC_MnTU    equ    257
  56. ARC_XMTU    equ    508
  57. ;
  58. ;status/interrupt mask bit fields
  59. ;
  60. ST_TA        equ    001h        ; transmitter available
  61. ST_TMA        equ    002h        ; transmitted msg. ackd
  62. ST_RECON    equ    004h        ; system reconfigured
  63. ST_TEST        equ    008h        ; test flag
  64. ST_POR        equ    010h        ; power-on-reset
  65. ST_ETS1        equ    020h        ; unused
  66. ST_ETS2        equ    040h        ; unused
  67. ST_RI        equ    080h        ; receiver inhibited
  68.  
  69. ;
  70. ;in the command register, the following bits have these meanings:
  71. ;        0-2    command
  72. ;        3-4    page number (enable rvc/xmt)
  73. ;         7    rcv b'casts
  74.  
  75.  
  76. DSBL_XMT    equ    001h        ; disable transmitter
  77. DSBL_RCV    equ    002h        ; disable receiver
  78. ENBL_XMT    equ    003h        ; enable transmitter
  79. ENBL_RCV    equ    004h        ; enable receiver
  80. DFN_CONF    equ    005h        ; define configuration
  81. CLR_FLGS    equ    006h        ; clear flags
  82. LD_TST_FLG    equ    007h        ; load test flags
  83.  
  84. ; flags for clear flags operation
  85.  
  86. FL_POR        equ    008h        ; power-on-reset
  87. FL_RECON    equ    010h        ; system reconfigured
  88.  
  89. ; flags for load test flags operation
  90.  
  91. FL_TST        equ    008h        ; test flag (diagnostic)
  92.  
  93. ; byte deposited into first address of buffers when POR
  94. TSTWRD        equ    0321Q
  95.  
  96. ; handy macros for enable receiver/transmitter
  97.  
  98. BCAST        equ    080h        ; receiver only
  99. ;PAGE        equ(nn)    ((nn)<<3)
  100.  
  101. ; flags for define configuration
  102.  
  103. CONF_NORM    equ    000h        ; 1-253 byte packets
  104. CONF_XTND    equ    008h        ; 256-508 byte packets
  105.  
  106. ; macros to access buffers
  107. ;BUF    equ(page)    (((custom.c_basemem) + 512 * (page)))
  108.  
  109. ; ARCnet pseudo header -- note that syscode must occupy last byte...
  110.  
  111. arc_hdr    struc
  112. arc_sid        db    ?        ; source, valid on rcv
  113. arc_did        db    ?        ; destination, 0 = b'cast
  114. arc_cp        db    ?        ; continuation pointer. zero
  115.                     ; for extended packets
  116. arc_xcp        db    ?        ; extended cp, see above
  117. arc_syscode    db    ?        ; system code/pkt type
  118. arc_hdr    ends
  119.  
  120. ; designations for receiver/transmitter buffers.  sorry, no cleverness here
  121. RCVPAGE        equ    2
  122. XMTPAGE        equ    3
  123.  
  124. my_arcnet_id    db    0            ;my arcnet ID.
  125.  
  126.     public    int_no
  127. int_no        db    5,0,0,0        ; interrupt number.
  128. io_addr        dw    02e0h,0        ; I/O address for card (jumpers)
  129. mem_base    dw    0d800h,0
  130.  
  131.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  132. driver_class    db    8        ;ARCnet (from the packet spec)
  133. driver_type    db    1        ;Datapoint RIM (from the packet spec)
  134. driver_name    db    'ARCnet',0    ;name of the driver.
  135. driver_function    db    2
  136. parameter_list    label    byte
  137.     db    1    ;major rev of packet driver
  138.     db    9    ;minor rev of packet driver
  139.     db    14    ;length of parameter list
  140.     db    1    ;length of MAC-layer address
  141.     dw    507    ;MTU, including MAC headers
  142.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  143.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  144.     dw    0    ;(# of successive xmits) - 1
  145.     dw    0    ;Interrupt # to hook for post-EOI
  146.             ;processing, 0 == none,
  147.  
  148.     public    rcv_modes
  149. rcv_modes    dw    4        ;number of receive modes in our table.
  150.         dw    0,0,0,rcv_mode_3
  151.  
  152.     public    send_pkt
  153. send_pkt:
  154. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  155. ;  (only if the high-performance bit is set in driver_function)
  156. ;enter with ds:si -> packet, cx = packet length.
  157. ;exit with nc if ok, or else cy if error, dh set to error number.
  158.     assume    ds:nothing
  159.  
  160. ;Wait for transmitter ready.
  161.     loadport
  162.     setport    STATUS
  163.  
  164.     mov    ax,SEND_IVAL        ;only wait this long for it.
  165.     call    set_timeout        ;  otherwise we can't send.
  166. send_pkt_3:
  167.     in    al,dx            ;if not busy, exit.
  168.     and    al,ST_TA
  169.     jne    send_pkt_2
  170.     call    do_timeout        ;did we time out yet?
  171.     jne    send_pkt_3        ;no, not yet.
  172.  
  173.     setport    COMMAND            ;stop the transmit.
  174.     mov    al,DSBL_XMT
  175.     out    dx,al
  176.     mov    dh,CANT_SEND        ;timed out, can't send.
  177.     stc
  178.     ret
  179.  
  180. send_pkt_2:
  181. ;store the packet on the board.
  182.     mov    es,mem_base
  183.     mov    di,XMTPAGE * 512
  184.     movsw                ;move the SID and DID to the board.
  185.     sub    cx,2            ;leave them out of the count.
  186.  
  187.     cmp    cx,ARC_XMTU        ;is this one too big?
  188.     ja    send_pkt_toobig        ;yes, can't store it.
  189.     cmp    cx,ARC_MTU        ;is this one small enough
  190.     jbe    send_pkt_1        ;yes, just move it in.
  191.     cmp    cx,ARC_MnTU        ;is it *too* large AND *too* small?
  192.     jae    send_pkt_5        ;no.
  193.     mov    cx,ARC_MnTU        ;yes - use the larger size.
  194. send_pkt_5:
  195.     xor    al,al            ;use a zero cp to indicate xcp.
  196.     mov    ah,cl            ;store the length in xcp.
  197.     neg    ah
  198.     stosw
  199.     jmp    short send_pkt_4
  200. send_pkt_1:
  201.     mov    al,cl            ;store the length in cp.
  202.     neg    al
  203.     stosb
  204. send_pkt_4:
  205.     mov    ax,di            ;continue the put.
  206.     mov    al,cl            ;  advance the cp to its proper place.
  207.     neg    al
  208.     mov    di,ax
  209.     call    movemem
  210.  
  211. ;start the transmit.
  212.     mov    al,ENBL_XMT or (XMTPAGE shl 3)
  213.     loadport
  214.     setport    COMMAND
  215.     out    dx,al
  216.  
  217.     clc
  218.     ret
  219. send_pkt_toobig:
  220.     mov    dh,NO_SPACE
  221.     stc
  222.     ret
  223.  
  224. movemem:
  225. ;does the same thing as "rep movsb", only 50% faster.
  226. ;moves words instead of bytes, and handles the case of both addresses odd
  227. ;efficiently.  There is no way to handle one address odd efficiently.
  228. ;This routine always aligns the source address in the hopes that the
  229. ;destination address will also get aligned.  This is from Phil Karn's
  230. ;code from ec.c, a part of his NET package.  I bummed a few instructions
  231. ;out.
  232.     jcxz    movemem_cnte        ; If zero, we're done already.
  233.     test    si,1            ; Does source start on odd byte?
  234.     jz    movemem_adre        ; Go if not
  235.     movsb                ; Yes, move the first byte
  236.     dec    cx            ; Count that byte
  237. movemem_adre:
  238.     shr    cx,1            ; convert to word count
  239.     rep    movsw            ; Move the bulk as words
  240.     jnc    movemem_cnte        ; Go if the count was even
  241.     movsb                ; Move leftover last byte
  242. movemem_cnte:
  243.     ret
  244.  
  245.  
  246.     public    get_address
  247. get_address:
  248. ;get the address of the interface.
  249. ;enter with es:di -> place to get the address, cx = size of address buffer.
  250. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  251.     assume    ds:code
  252.     cmp    cx,ARCADDR_LEN        ;make sure that we have enough room.
  253.     mov    dh,NO_SPACE
  254.     jb    get_address_2
  255.  
  256.     mov    al,my_arcnet_id        ;store our address.
  257.     stosb
  258.  
  259.     mov    cx,ARCADDR_LEN
  260.     clc
  261.     ret
  262. get_address_2:
  263.     stc
  264.     ret
  265.  
  266.  
  267. ;Set address on controller
  268.     public    set_address
  269. set_address:
  270.     assume    ds:nothing
  271. ;enter with ds:si -> address, CX = length of address.
  272. ;exit with nc if okay, or cy, dh=error if any errors.
  273.     mov    dh,CANT_SET
  274.     stc
  275.     ret
  276.  
  277.  
  278. rcv_mode_3:
  279. ;receive mode 3 is the only one we support, so we don't have to do anything.
  280.     ret
  281.  
  282.  
  283.     public    set_multicast_list
  284. set_multicast_list:
  285. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  286. ;return nc if we set all of them, or cy,dh=error if we didn't.
  287.     mov    dh,NO_MULTICAST
  288.     stc
  289.     ret
  290.  
  291.  
  292.     public    terminate
  293. terminate:
  294.     assume    ds:code
  295.     loadport
  296.     setport    IMASK
  297.     mov    al,0
  298.     out    dx,al
  299.  
  300.     setport COMMAND
  301.     mov    al,DSBL_RCV
  302.     out    dx,al
  303.     mov    al,DSBL_XMT
  304.     out    dx,al
  305.  
  306.     setport    STATUS            ;do we need to do this [rnn]?
  307.     in    al,dx
  308.  
  309.     ret
  310.  
  311.  
  312.     public    reset_interface
  313. reset_interface:
  314. ;reset the interface.
  315. ;we don't do anything.
  316.     ret
  317.  
  318.  
  319.     include    timeout.asm
  320.  
  321. ;called when we want to determine what to do with a received packet.
  322. ;enter with cx = packet length, es:di -> packet type.
  323.     extrn    recv_find: near
  324.  
  325. ;called after we have copied the packet into the buffer.
  326. ;enter with ds:si ->the packet, cx = length of the packet.
  327.     extrn    recv_copy: near
  328.  
  329.     extrn    count_in_err: near
  330.     extrn    count_out_err: near
  331.  
  332.     public    recv
  333. recv:
  334. ;called from the recv isr.  All registers have been saved, and ds=cs.
  335. ;Upon exit, the interrupt will be acknowledged.
  336.     assume    ds:code
  337.  
  338. recv_1:
  339.     loadport            ;get the status to see if we got
  340.     setport    STATUS            ;  a false alarm.
  341.     in    al,dx
  342.     test    al,ST_RI
  343.     je    recv_2            ;yup, exit now.
  344.  
  345.     mov    es,mem_base
  346.     mov    bx,RCVPAGE * 512
  347.  
  348. ;decode data size.
  349.  
  350.     mov    cx,256            ;compute the actual length.
  351.     mov    al,es:[bx].arc_cp
  352.     or    al,al            ;is this a normal or continuation pkt?
  353.     jne    recv_3            ;go if normal.
  354.     mov    cx,512            ;extended packets have 512 max.
  355.     mov    al,es:[bx].arc_xcp
  356. recv_3:
  357.     xor    ah,ah
  358.     sub    cx,ax
  359.     add    cx,2            ;add in SID and DID.
  360.     mov    bl,al            ;use al as the low byte of the address.
  361.     mov    di,bx
  362.     call    recv_find        ;look up our type.
  363.  
  364.     mov    ax,es            ;is this pointer null?
  365.     or    ax,di
  366.     je    recv_isr_9        ;yes - just free the frame.
  367.  
  368.     push    es            ;remember where the buffer pointer is.
  369.     push    di
  370.  
  371.     mov    ds,mem_base        ;copy the packet into their buffer.
  372.     assume    ds:nothing
  373.     mov    si,RCVPAGE * 512    ;  (don't worry about ds.
  374.     movsw                ;move SID and DID.
  375.     mov    ax,si
  376.     lodsb                ;get arc_cp.
  377.     or    al,al            ;extended?
  378.     jne    recv_5            ;no.
  379.     lodsb                ;yes - get arc_xcp.
  380. recv_5:
  381.     mov    si,ax            ;set the new pointer.
  382.     push    cx            ;move the data part of the packet.
  383.     sub    cx,2            ;don't move the two we've already
  384.     call    movemem            ;  moved.
  385.     pop    cx
  386.  
  387.     pop    si
  388.     pop    ds
  389.     assume    ds:nothing
  390.     call    recv_copy        ;tell them that we copied it.
  391.  
  392.     mov    ax,cs            ;restore our ds.
  393.     mov    ds,ax
  394.     assume    ds:code
  395.  
  396. recv_isr_9:
  397.  
  398.     loadport            ;enable reception again.
  399.     setport    COMMAND
  400.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST
  401.     out    dx,al
  402.  
  403.     jmp    recv_1
  404. recv_2:
  405.     ret
  406.  
  407.  
  408.     public    recv_exiting
  409. recv_exiting:
  410. ;called from the recv isr after interrupts have been acknowledged.
  411. ;Only ds and ax have been saved.
  412.     assume    ds:nothing
  413.     ret
  414.  
  415.  
  416. end_resident    label    byte
  417.  
  418.     public    usage_msg
  419. usage_msg    db    "usage: arcnet <packet_int_no> <int_no> <io_addr> <mem_base>",CR,LF,'$'
  420.  
  421.     public    copyright_msg
  422. copyright_msg    db    "Packet driver for the DataPoint RIM (ARCnet), version ",'0'+majver,".",'0'+version,CR,LF
  423.         db    "Portions Copyright 1988 Philip Prindeville",CR,LF,'$'
  424.  
  425. no_arcnet_msg    db    "No ARCnet found at that address.",CR,LF,'$'
  426. failed_test_msg    db    "Failed self test.",CR,LF,'$'
  427.  
  428. int_no_name    db    "Interrupt number ",'$'
  429. io_addr_name    db    "I/O port ",'$'
  430. mem_base_name    db    "Memory address ",'$'
  431.  
  432.     extrn    set_recv_isr: near
  433.  
  434. ;enter with si -> argument string, di -> word to store.
  435. ;if there is no number, don't change the number.
  436.     extrn    get_number: near
  437.  
  438. ;enter with dx -> name of word, di -> dword to print.
  439.     extrn    print_number: near
  440.  
  441.     public    parse_args
  442. parse_args:
  443. ;exit with nc if all went well, cy otherwise.
  444.     mov    di,offset int_no
  445.     call    get_number
  446.     mov    di,offset io_addr
  447.     call    get_number
  448.     mov    di,offset mem_base
  449.     call    get_number
  450.     clc
  451.     ret
  452.  
  453.  
  454. no_arcnet_error:
  455.     mov    dx,offset no_arcnet_msg
  456.     mov    ah,9
  457.     int    21h
  458.     jmp    short error
  459. failed_test_error:
  460.     mov    dx,offset failed_test_msg
  461.     mov    ah,9
  462.     int    21h
  463. error:
  464.     stc
  465.     ret
  466.  
  467.  
  468.     public    etopen
  469. etopen:
  470. ;reset the board via the I/O reset port, then wait for it to become sane again.
  471.  
  472.     mov    ax,mem_base        ;test the memory first.
  473.     mov    cx,2048
  474.     call    memory_test
  475.     jne    no_arcnet_error
  476.  
  477.     mov    es,mem_base
  478.  
  479.     loadport
  480.     setport SW_RST
  481.     in    al,dx
  482.  
  483.     mov    ax,RST_IVAL
  484.     call    set_timeout
  485. etopen_1:
  486.     call    do_timeout
  487.     jne    etopen_1
  488.  
  489.     setport    STATUS
  490.     in    al,dx
  491.  
  492. ;since we've just reset:
  493. ;    reset the POR flag,
  494. ;    check the diagnostic byte in the buffer,
  495. ;    grab the node ID, and assign it to the host number.
  496.  
  497.     test    al,ST_POR
  498.     je    etopen_2
  499.  
  500.     setport    COMMAND
  501.     mov    al,CLR_FLGS or FL_POR or FL_RECON
  502.     out    dx,al
  503.  
  504.     mov    al,es:[0]
  505.     cmp    byte ptr es:[0],TSTWRD
  506.     je    etopen_3
  507.     jmp    failed_test_error    ;failed power on self-test.
  508. etopen_3:
  509.     mov    al,es:[1]
  510.     mov    my_arcnet_id,al
  511. etopen_2:
  512.  
  513. ;another simple diagnostic:
  514. ;    force test flag on in RIM,
  515. ;    check to see that it is set,
  516. ;    reset it.
  517.  
  518.     loadport
  519.     setport    COMMAND
  520.     mov    al,LD_TST_FLG or FL_TST
  521.     out    dx,al
  522.  
  523.     setport STATUS
  524.     in    al,dx
  525.  
  526.     test    al,FL_TST
  527.     jne    etopen_4
  528.     jmp    failed_test_error    ;failed forced self-test.
  529. etopen_4:
  530.     setport    COMMAND
  531.     mov    al,LD_TST_FLG
  532.     out    dx,al
  533.     setport STATUS
  534.     in    al,dx
  535.  
  536.     pushf
  537.     cli
  538.  
  539.     call    set_recv_isr
  540.  
  541. ;now we enable the board to interrupt
  542. ;us on packet received.  Not transmiter available
  543. ;(i.e. transmission complete).  We don't have
  544. ;any control over POR, since it is NMI...
  545. ;RECON seems useless.
  546.  
  547.     loadport
  548.     setport    IMASK
  549.     mov    al,ST_RI
  550.     out    dx,al
  551.  
  552.     ; we should allow extended packets
  553.     setport    COMMAND
  554.     mov    al,DFN_CONF or CONF_XTND
  555.     out    dx,al
  556.  
  557.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST;
  558.     out    dx,al
  559.  
  560.     popf
  561.  
  562.     mov    di,offset int_no
  563.     mov    dx,offset int_no_name
  564.     call    print_number
  565.     mov    di,offset io_addr
  566.     mov    dx,offset io_addr_name
  567.     call    print_number
  568.     mov    di,offset mem_base
  569.     mov    dx,offset mem_base_name
  570.     call    print_number
  571.  
  572.     mov    dx,offset end_resident
  573.     clc
  574.     ret
  575.  
  576.  
  577.     include    memtest.asm
  578.  
  579. code    ends
  580.  
  581.     end
  582.