home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / NOVELL / PKTDRV7.ZIP / ARCNET.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-07-27  |  13.6 KB  |  598 lines

  1. ;History:591,12
  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    word 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. int_num    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    as_send_pkt
  153. ; The Asynchronous Transmit Packet routine.
  154. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  155. ;   interrupts possibly enabled.
  156. ; Exit with nc if ok, or else cy if error, dh set to error number.
  157. ;   es:di and interrupt enable flag preserved on exit.
  158. as_send_pkt:
  159.     ret
  160.  
  161.     public    drop_pkt
  162. ; Drop a packet from the queue.
  163. ; Enter with es:di -> iocb.
  164. drop_pkt:
  165.     assume    ds:nothing
  166.     ret
  167.  
  168.     public    xmit
  169. ; Process a transmit interrupt with the least possible latency to achieve
  170. ;   back-to-back packet transmissions.
  171. ; May only use ax and dx.
  172. xmit:
  173.     assume    ds:nothing
  174.     ret
  175.  
  176.  
  177.     public    send_pkt
  178. send_pkt:
  179. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  180. ;  (only if the high-performance bit is set in driver_function)
  181. ;enter with ds:si -> packet, cx = packet length.
  182. ;exit with nc if ok, or else cy if error, dh set to error number.
  183.     assume    ds:nothing
  184.  
  185. ;Wait for transmitter ready.
  186.     loadport
  187.     setport    STATUS
  188.  
  189.     mov    ax,SEND_IVAL        ;only wait this long for it.
  190.     call    set_timeout        ;  otherwise we can't send.
  191. send_pkt_3:
  192.     in    al,dx            ;if not busy, exit.
  193.     and    al,ST_TA
  194.     jne    send_pkt_2
  195.     call    do_timeout        ;did we time out yet?
  196.     jne    send_pkt_3        ;no, not yet.
  197.  
  198.     setport    COMMAND            ;stop the transmit.
  199.     mov    al,DSBL_XMT
  200.     out    dx,al
  201.     mov    dh,CANT_SEND        ;timed out, can't send.
  202.     stc
  203.     ret
  204.  
  205. send_pkt_2:
  206. ;store the packet on the board.
  207.     mov    es,mem_base
  208.     mov    di,XMTPAGE * 512
  209.     movsw                ;move the SID and DID to the board.
  210.     sub    cx,2            ;leave them out of the count.
  211.  
  212.     cmp    cx,ARC_XMTU        ;is this one too big?
  213.     ja    send_pkt_toobig        ;yes, can't store it.
  214.     cmp    cx,ARC_MTU        ;is this one small enough
  215.     jbe    send_pkt_1        ;yes, just move it in.
  216.     cmp    cx,ARC_MnTU        ;is it *too* large AND *too* small?
  217.     jae    send_pkt_5        ;no.
  218.     mov    cx,ARC_MnTU        ;yes - use the larger size.
  219. send_pkt_5:
  220.     xor    al,al            ;use a zero cp to indicate xcp.
  221.     mov    ah,cl            ;store the length in xcp.
  222.     neg    ah
  223.     stosw
  224.     jmp    short send_pkt_4
  225. send_pkt_1:
  226.     mov    al,cl            ;store the length in cp.
  227.     neg    al
  228.     stosb
  229. send_pkt_4:
  230.     mov    ax,di            ;continue the put.
  231.     mov    al,cl            ;  advance the cp to its proper place.
  232.     neg    al
  233.     mov    di,ax
  234.     call    movemem
  235.  
  236. ;start the transmit.
  237.     mov    al,ENBL_XMT or (XMTPAGE shl 3)
  238.     loadport
  239.     setport    COMMAND
  240.     out    dx,al
  241.  
  242.     clc
  243.     ret
  244. send_pkt_toobig:
  245.     mov    dh,NO_SPACE
  246.     stc
  247.     ret
  248.  
  249.     include    movemem.asm
  250.  
  251.     public    get_address
  252. get_address:
  253. ;get the address of the interface.
  254. ;enter with es:di -> place to get the address, cx = size of address buffer.
  255. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  256.     assume    ds:code
  257.     cmp    cx,ARCADDR_LEN        ;make sure that we have enough room.
  258.     mov    dh,NO_SPACE
  259.     jb    get_address_2
  260.  
  261.     mov    al,my_arcnet_id        ;store our address.
  262.     stosb
  263.  
  264.     mov    cx,ARCADDR_LEN
  265.     clc
  266.     ret
  267. get_address_2:
  268.     stc
  269.     ret
  270.  
  271.  
  272. ;Set address on controller
  273.     public    set_address
  274. set_address:
  275.     assume    ds:nothing
  276. ;enter with ds:si -> address, CX = length of address.
  277. ;exit with nc if okay, or cy, dh=error if any errors.
  278.     mov    dh,CANT_SET
  279.     stc
  280.     ret
  281.  
  282.  
  283. rcv_mode_3:
  284. ;receive mode 3 is the only one we support, so we don't have to do anything.
  285.     ret
  286.  
  287.  
  288.     public    set_multicast_list
  289. set_multicast_list:
  290. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  291. ;return nc if we set all of them, or cy,dh=error if we didn't.
  292.     mov    dh,NO_MULTICAST
  293.     stc
  294.     ret
  295.  
  296.  
  297.     public    terminate
  298. terminate:
  299.     assume    ds:code
  300.     loadport
  301.     setport    IMASK
  302.     mov    al,0
  303.     out    dx,al
  304.  
  305.     setport COMMAND
  306.     mov    al,DSBL_RCV
  307.     out    dx,al
  308.     mov    al,DSBL_XMT
  309.     out    dx,al
  310.  
  311.     setport    STATUS            ;do we need to do this [rnn]?
  312.     in    al,dx
  313.  
  314.     ret
  315.  
  316.  
  317.     public    reset_interface
  318. reset_interface:
  319. ;reset the interface.
  320. ;we don't do anything.
  321.     ret
  322.  
  323.  
  324.     include    timeout.asm
  325.  
  326. ;called when we want to determine what to do with a received packet.
  327. ;enter with cx = packet length, es:di -> packet type.
  328.     extrn    recv_find: near
  329.  
  330. ;called after we have copied the packet into the buffer.
  331. ;enter with ds:si ->the packet, cx = length of the packet.
  332.     extrn    recv_copy: near
  333.  
  334.     extrn    count_in_err: near
  335.     extrn    count_out_err: near
  336.  
  337.     public    recv
  338. recv:
  339. ;called from the recv isr.  All registers have been saved, and ds=cs.
  340. ;Upon exit, the interrupt will be acknowledged.
  341.     assume    ds:code
  342.  
  343. recv_1:
  344.     loadport            ;get the status to see if we got
  345.     setport    STATUS            ;  a false alarm.
  346.     in    al,dx
  347.     test    al,ST_RI
  348.     je    recv_2            ;yup, exit now.
  349.  
  350.     mov    es,mem_base
  351.     mov    bx,RCVPAGE * 512
  352.  
  353. ;decode data size.
  354.  
  355.     mov    cx,256            ;compute the actual length.
  356.     mov    al,es:[bx].arc_cp
  357.     or    al,al            ;is this a normal or continuation pkt?
  358.     jne    recv_3            ;go if normal.
  359.     mov    cx,512            ;extended packets have 512 max.
  360.     mov    al,es:[bx].arc_xcp
  361. recv_3:
  362.     xor    ah,ah
  363.     sub    cx,ax
  364.     add    cx,2            ;add in SID and DID.
  365.     mov    bl,al            ;use al as the low byte of the address.
  366.     mov    di,bx
  367.     call    recv_find        ;look up our type.
  368.  
  369.     mov    ax,es            ;is this pointer null?
  370.     or    ax,di
  371.     je    recv_isr_9        ;yes - just free the frame.
  372.  
  373.     push    es            ;remember where the buffer pointer is.
  374.     push    di
  375.  
  376.     mov    ds,mem_base        ;copy the packet into their buffer.
  377.     assume    ds:nothing
  378.     mov    si,RCVPAGE * 512    ;  (don't worry about ds.
  379.     movsw                ;move SID and DID.
  380.     mov    ax,si
  381.     lodsb                ;get arc_cp.
  382.     or    al,al            ;extended?
  383.     jne    recv_5            ;no.
  384.     lodsb                ;yes - get arc_xcp.
  385. recv_5:
  386.     mov    si,ax            ;set the new pointer.
  387.     push    cx            ;move the data part of the packet.
  388.     sub    cx,2            ;don't move the two we've already
  389.     call    movemem            ;  moved.
  390.     pop    cx
  391.  
  392.     pop    si
  393.     pop    ds
  394.     assume    ds:nothing
  395.     call    recv_copy        ;tell them that we copied it.
  396.  
  397.     mov    ax,cs            ;restore our ds.
  398.     mov    ds,ax
  399.     assume    ds:code
  400.  
  401. recv_isr_9:
  402.  
  403.     loadport            ;enable reception again.
  404.     setport    COMMAND
  405.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST
  406.     out    dx,al
  407.  
  408.     jmp    recv_1
  409. recv_2:
  410.     ret
  411.  
  412.  
  413.     public    recv_exiting
  414. recv_exiting:
  415. ;called from the recv isr after interrupts have been acknowledged.
  416. ;Only ds and ax have been saved.
  417.     assume    ds:nothing
  418.     ret
  419.  
  420.  
  421. end_resident    label    byte
  422.  
  423.     public    usage_msg
  424. usage_msg    db    "usage: arcnet [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr> <mem_base>",CR,LF,'$'
  425.  
  426.     public    copyright_msg
  427. copyright_msg    db    "Packet driver for the DataPoint RIM (ARCnet), version ",'0'+majver,".",'0'+version,CR,LF
  428.         db    "Portions Copyright 1988 Philip Prindeville",CR,LF,'$'
  429.  
  430. no_arcnet_msg    db    "No ARCnet found at that address.",CR,LF,'$'
  431. failed_test_msg    db    "Failed self test.",CR,LF,'$'
  432.  
  433. int_no_name    db    "Interrupt number ",'$'
  434. io_addr_name    db    "I/O port ",'$'
  435. mem_base_name    db    "Memory address ",'$'
  436.  
  437.     extrn    set_recv_isr: near
  438.  
  439. ;enter with si -> argument string, di -> word to store.
  440. ;if there is no number, don't change the number.
  441.     extrn    get_number: near
  442.  
  443. ;enter with dx -> name of word, di -> dword to print.
  444.     extrn    print_number: near
  445.  
  446.     public    parse_args
  447. parse_args:
  448. ;exit with nc if all went well, cy otherwise.
  449.     mov    di,offset int_no
  450.     call    get_number
  451.     mov    di,offset io_addr
  452.     call    get_number
  453.     mov    di,offset mem_base
  454.     call    get_number
  455.     clc
  456.     ret
  457.  
  458.  
  459. no_arcnet_error:
  460.     mov    dx,offset no_arcnet_msg
  461.     mov    ah,9
  462.     int    21h
  463.     jmp    short error
  464. failed_test_error:
  465.     mov    dx,offset failed_test_msg
  466.     mov    ah,9
  467.     int    21h
  468. error:
  469.     stc
  470.     ret
  471.  
  472.  
  473.     public    etopen
  474. etopen:
  475. ;reset the board via the I/O reset port, then wait for it to become sane again.
  476.  
  477.     mov    ax,mem_base        ;test the memory first.
  478.     mov    cx,2048
  479.     call    memory_test
  480.     jne    no_arcnet_error
  481.  
  482.     mov    es,mem_base
  483.  
  484.     loadport
  485.     setport SW_RST
  486.     in    al,dx
  487.  
  488.     mov    ax,RST_IVAL
  489.     call    set_timeout
  490. etopen_1:
  491.     call    do_timeout
  492.     jne    etopen_1
  493.  
  494.     setport    STATUS
  495.     in    al,dx
  496.  
  497. ;since we've just reset:
  498. ;    reset the POR flag,
  499. ;    check the diagnostic byte in the buffer,
  500. ;    grab the node ID, and assign it to the host number.
  501.  
  502.     test    al,ST_POR
  503.     je    etopen_2
  504.  
  505.     setport    COMMAND
  506.     mov    al,CLR_FLGS or FL_POR or FL_RECON
  507.     out    dx,al
  508.  
  509.     mov    al,es:[0]
  510.     cmp    byte ptr es:[0],TSTWRD
  511.     je    etopen_3
  512.     jmp    failed_test_error    ;failed power on self-test.
  513. etopen_3:
  514.     mov    al,es:[1]
  515.     mov    my_arcnet_id,al
  516. etopen_2:
  517.  
  518. ;another simple diagnostic:
  519. ;    force test flag on in RIM,
  520. ;    check to see that it is set,
  521. ;    reset it.
  522.  
  523.     loadport
  524.     setport    COMMAND
  525.     mov    al,LD_TST_FLG or FL_TST
  526.     out    dx,al
  527.  
  528.     setport STATUS
  529.     in    al,dx
  530.  
  531.     test    al,FL_TST
  532.     jne    etopen_4
  533.     jmp    failed_test_error    ;failed forced self-test.
  534. etopen_4:
  535.     setport    COMMAND
  536.     mov    al,LD_TST_FLG
  537.     out    dx,al
  538.     setport STATUS
  539.     in    al,dx
  540.  
  541.     pushf
  542.     cli
  543.  
  544.     call    set_recv_isr
  545.  
  546. ;now we enable the board to interrupt
  547. ;us on packet received.  Not transmiter available
  548. ;(i.e. transmission complete).  We don't have
  549. ;any control over POR, since it is NMI...
  550. ;RECON seems useless.
  551.  
  552.     loadport
  553.     setport    IMASK
  554.     mov    al,ST_RI
  555.     out    dx,al
  556.  
  557.     ; we should allow extended packets
  558.     setport    COMMAND
  559.     mov    al,DFN_CONF or CONF_XTND
  560.     out    dx,al
  561.  
  562.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST;
  563.     out    dx,al
  564.  
  565.     popf
  566.  
  567.     mov    al, int_no        ; Get board's interrupt vector
  568.     add    al, 8
  569.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  570.     jb    set_int_num        ; No.
  571.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  572. set_int_num:
  573.     xor    ah, ah            ; Clear high byte
  574.     mov    int_num, ax        ; Set parameter_list int num.
  575.  
  576.     mov    dx,offset end_resident
  577.     clc
  578.     ret
  579.  
  580.     public    print_parameters
  581. print_parameters:
  582.     mov    di,offset int_no
  583.     mov    dx,offset int_no_name
  584.     call    print_number
  585.     mov    di,offset io_addr
  586.     mov    dx,offset io_addr_name
  587.     call    print_number
  588.     mov    di,offset mem_base
  589.     mov    dx,offset mem_base_name
  590.     call    print_number
  591.     ret
  592.  
  593.     include    memtest.asm
  594.  
  595. code    ends
  596.  
  597.     end
  598.