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

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