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

  1. ;*****************************************************************************;
  2. ;*                                                                           *;
  3. ;*     File:   IBMTOKEN.ASM                                                  *;
  4. ;*     Auth:   Brian Fisher                                                  *;
  5. ;*             Queens University                                             *;
  6. ;*             Computing and Communications Services                         *;
  7. ;*             Rm 2-50 Dupuis Hall                                           *;
  8. ;*             Kingston Ontario                                              *;
  9. ;*                                                                           *;
  10. ;*     Date:   September 3 1989                                              *;
  11. ;*                                                                           *;
  12. ;*     Purp:   Ethernet (3C501) packet driver for IBM Token Ring.  This      *;
  13. ;*             driver uses the IBM LAN support program DIR interface.        *;
  14. ;*             The current implementation supports IP and ARP.               *;
  15. ;*                                                                           *;
  16. ;*             (C) 1989 Queens University                                    *;
  17. ;*             Computing and Communications Services.  This portion of       *;
  18. ;*             the program remains the property of Queens University.        *;
  19. ;*                                                                           *;
  20. ;*===========================================================================*;
  21. ;*     Program Logic:                                                        *;
  22. ;*                                                                           *;
  23. ;*     IBMTOKEN extracts IP and ARP data from ethernet datagrams passed to   *;
  24. ;*     it by the ULP, makes any adjustments required, then builds a token    *;
  25. ;*     ring datagram and sends it out over the network.  The process is      *;
  26. ;*     reversed when packets are received.  IBMTOKEN supports token ring     *;
  27. ;*     source routing and functions in a bridged environment.                *;
  28. ;*                                                                           *;
  29. ;*     The ULP uses Ethernet 'Blue Book' encapsulation.  IBMTOKEN uses       *;
  30. ;*     802.2 LLC format for transmission on token ring.  The IBM (tm)        *;
  31. ;*     LAN Support Program is required.  IBMTOKEN uses the DIR interface     *;
  32. ;*     to send/receive packets on token ring.                                *;
  33. ;*                                                                           *;
  34. ;*     IP packets do not require any modifications, and are sent 'as is.'    *;
  35. ;*     ARP packets have an 'hwr' field that must be changed fro 1h to 6h     *;
  36. ;*     during send_pkt, and changed back to 1h from 6h during _receive.      *;
  37. ;*                                                                           *;
  38. ;*     The minimum size of an ethernet packet is 60 bytes (minus the 4 byte  *;
  39. ;*     ethernet checksum).  Token ring has no lower limit.  The ULP will     *;
  40. ;*     reject 'short' packets, so IBMTOKEN lies and tells it there are 60    *;
  41. ;*     bytes.                                                                *;
  42. ;*                                                                           *;
  43. ;*     ARP packets are 28 bytes in length.  The ULP rounds the size of a     *;
  44. ;*     packet up to 60 bytes, so there is extra data on the end of the ARP   *;
  45. ;*     packet.  IBMTOKEN trims this off, because token ring hosts reject     *;
  46. ;*     'too long' ARP packets.                                               *;
  47. ;*                                                                           *;
  48. ;*     The minimum size of an ethernet packet is 60 bytes.  The maximum      *;
  49. ;*     is 1514 bytes.  The buffer sizes for token ring send/receive are      *;
  50. ;*     set to accomodate this.                                               *;
  51. ;*                                                                           *;
  52. ;*     Source Routing:                                                       *;
  53. ;*                                                                           *;
  54. ;*     The ethernet entrenched logic of the ULP does not accomodate source   *;
  55. ;*     routing.  IBMTOKEN provides a mechanism for source routing that is    *;
  56. ;*     transparent to the ULP.  The RIF information associated with token    *;
  57. ;*     ring source addresses are placed in a cache.  When the ULP sends to   *;
  58. ;*     that address, the RIF information is extracted from the cache and     *;
  59. ;*     used to route the packet to the target host.                          *;
  60. ;*                                                                           *;
  61. ;*     RIF Cache Logic:                                                      *;
  62. ;*                                                                           *;
  63. ;*        The cache logic uses an LRU algorithm.  Each entry is time         *;
  64. ;*        stamped.  If all the slots in the cache are being used, the oldest *;
  65. ;*        entry (assumed to be the LRU) is replaced (bumped from the cache). *;
  66. ;*                                                                           *;
  67. ;*        If the ULP uses an address whose RIF has been bumped from the      *;
  68. ;*        cache, a mechanism exists to rediscover the source route.          *;
  69. ;*        IBMTOKEN attaches a phony RIF, with the broadcast bit set and      *;
  70. ;*        and empty route table.  This packet travels to all rings.  When    *;
  71. ;*        the foreign host responds, the RIF info is placed back in the      *;
  72. ;*        cache.  Subsequent transmissions will use the rediscovered RIF.    *;
  73. ;*                                                                           *;
  74. ;*        The size of the RIF cache should be set to handle the maximum      *;
  75. ;*        number of concurrent hosts.  This will minimize the bumping        *;
  76. ;*        effect and minimize all rings broadcasts.                          *;
  77. ;*                                                                           *;
  78. ;*        I chose this algorithm so the ULP would not require any special    *;
  79. ;*        coding to work.  It eliminates the need for special syncronization *;
  80. ;*        of the ARP and RIF cache's.                                        *;
  81. ;*                                                                           *;
  82. ;*===========================================================================*;
  83. ;*                                                                           *;
  84. ;*      Revs:  Sep 29 1989     Successful tests with TN3270, FTP, and FTPBIN.*;
  85. ;*             B. Fisher       Some fine tuning required.                    *;
  86. ;*                                                                           *;
  87. ;*             Oct 1  1989     Cleaning up code.  Found bug that prevented   *;
  88. ;*                             buffer1/buffer2..n copies from working.       *;
  89. ;*                                                                           *;
  90. ;*             Oct 15 1989     Rearranged buffer sizes to accomodate Adapt I *;
  91. ;*                                                                           *;
  92. ;*             Nov 15 1989     Added missing popf at end of recv_complt      *;
  93. ;*                             Fixed missing popf at end of recv_complt      *;
  94. ;*                                                                           *;
  95. ;*             Nov 19 1989     Added marker to show interrupt activity       *;
  96. ;*                             for debugging.                                *;
  97. ;*                                                                           *;
  98. ;*             Nov 20 1989     Add changes for Release 5 compatibility       *;
  99. ;*                                                                           *;
  100. ;*             Nov 21 1989     Fix es/bx reversal at get_size                *;
  101. ;*                                                                           *;
  102. ;*             Nov 22 1989     RIF not working because of confusion with     *;
  103. ;*                             SA bit acquired via ARP and SA bit acquired   *;
  104. ;*                             through Token Receive.  Send_Pkt now looks    *;
  105. ;*                             up all dest addresses in RIF table.           *;
  106. ;*                                                                           *;
  107. ;*             Nov 23 1989     Have DEBUG mode report RIF table address when *;
  108. ;*                             get_multicast_ call made.                     *;
  109. ;*                                                                           *;
  110. ;*             Nov 28 1989     Add phony RIF to 'local' addresses so the     *;
  111. ;*                             bridge will pass them on.  ARP acquired HW    *;
  112. ;*                             addresses need RIF to cross bridge.  This is  *;
  113. ;*                             done in send_pkt.                             *;
  114. ;*                                                                           *;
  115. ;*             Nov 29 1989     Fixed REPT macro in SA_blk so size of SA info *;
  116. ;*                             is correct.  Didn't hurt function, however.   *;
  117. ;*                                                                           *;
  118. ;*             Nov 29 1989     Clear broadcast bit in RIF before entry in    *;
  119. ;*                             table.  This prevents bridges from altering   *;
  120. ;*                             existing route.  FF,FF,FF,FF,FF,FF address    *;
  121. ;*                             uses broadcast bit so ARP will work.          *;
  122. ;*                                                                           *;
  123. ;*             Nov 29 1989     Predefined broadcast RIF entry direction bit  *;
  124. ;*                             polarity reversal prevented broadcast from    *;
  125. ;*                             going over the bridge.                        *;
  126. ;*                                                                           *;
  127. ;*             Version 1.A -   Production Version released at Queens         *;
  128. ;*                                                                           *;
  129. ;*             Jan 02 1990     Fix missing CLD in _receiver, shows up when   *;
  130. ;*                             TOKREUI is used instead of Lan Support Pgm... *;
  131. ;*                                                                           *;
  132. ;*             Version 1.B                                                   *;
  133. ;*             Jan 15 1990     Begin modifications for LRU algorithm in the  *;
  134. ;*             (alpha 0)       RIF cache.  3rd parm on cmd line sets number  *;
  135. ;*                             of entries in the cache, which is allocated   *;
  136. ;*                             using INT 21, Function 48h.  The cache        *;
  137. ;*                             routines are modified to handle the new addr  *;
  138. ;*                             mode for accessing the table.                 *;
  139. ;*                                                                           *;
  140. ;*             Jan 16 1990     Adding time mark info to SA_table structure.  *;
  141. ;*             (alpha 1)       add_entry initializes t_mark                  *;
  142. ;*                             loc_entry refreshes t_mark when match found   *;
  143. ;*                             add_entry uses LRU slot in table when slots   *;
  144. ;*                             are all in use.                               *;
  145. ;*                                                                           *;
  146. ;*             Jan 18 1990     Updated the program documentation to reflect  *;
  147. ;*                             the operation of the RIF cache.               *;
  148. ;*                                                                           *;
  149. ;*             Version 1.C     Add code for compatibility with Release 6 of  *;
  150. ;*             Mar 18 1990     Clarkson drivers, including TERMINATE call.   *;
  151. ;*                                                                           *;
  152. ;*             Version 1.D     Fix bug that prevents get_address from        *;
  153. ;*                             returning adapter 1's hardware address.       *;
  154. ;*                                                                           *;
  155. ;*                                         *;
  156. ;*           Version 1.E     Modified to coexist with other LAN software   *;
  157. ;*           25.06.1991      (MS LAN Manager, IBM LAN Support ....) by     *;
  158. ;*                             Antero Koskinen, Nokia Data Systems Oy,       *;
  159. ;*                             Finland (anterok@xerver.icl.fi)               *;
  160. ;*****************************************************************************;
  161.  
  162. version        equ    16h        ; Version E = 15h
  163.  
  164.     include    defs.asm
  165.  
  166. debug        =    0        ; set 1 for IRM marks on RX
  167.  
  168. alpha        =    0        ; ALPHA Test Version = 0
  169. alpha_ver    =    1        ; Which ALPHA Version...
  170.  
  171. hrs24        =    1573040        ; ticks in 24 hour day
  172.  
  173. toke_vect    =    5Ch        ; LAN Support Pgm Vector
  174. toke_wait    =    0FFh        ; completion code wait status
  175. pool_size    =    512        ; 8K space for buffer pool area
  176.  
  177. num_rcv_buff    =    2        ; <2 defaults to 8
  178. recv_size    =    1536        ; max size of card recieve buffer
  179. tran_size    =    1536        ; max size of transmit buffer
  180.  
  181. STATION_ID    =    0        ;                            ; talk using direct station
  182.  
  183. RECV_OPTIONS    =    0C0h        ; contiguous mac/data in bufs
  184.  
  185. open_cmd    =    3h        ; LAN Support OpCodes
  186. interrupt_cmd    =    0h
  187. initialize_cmd    =    20h
  188. close_cmd    =    4h
  189. modify_cmd    =    1h
  190. restore_cmd    =    2h
  191. trans_dir_cmd    =    0Ah
  192. free_ccb_cmd    =    27h
  193. recv_can_cmd    =    29h
  194. open_recv_cmd    =    28h
  195. get_status_cmd    =    21h
  196.  
  197. SA_table_size    =    32        ; default size of the RIF cache
  198. SA_min_size    =    2        ; minimum size
  199. SA_max_size    =    1024        ; maximum size
  200.  
  201. LLC_AC        =    10h        ; access control LLC
  202. LLC_FC        =    40h        ; frame control  LLC
  203. LLC_SSAP_DSAP    =    0AAAAh        ; reversed for network <grin>
  204. LLC_CON        =    03h
  205.  
  206. MAC_hdr_size    =    22        ; MAC+LLC+SNAP header length
  207.  
  208. not_SA_mask    =    7Fh
  209. SA_mask        =    80h
  210. RIF_size_mask    =    1Fh
  211. RIF_dir_bit    =    80h
  212.  
  213. broadcast_byte    =    0FFh        ; broadcast is FF,FF,FF,FF,FF,FF
  214.  
  215. ARP_type    =    0608h        ; reversed for network order
  216. ARP_Eth_hwr    =    0100h        ; reversed for network order
  217. ARP_Tok_hwr    =    0600h        ; reversed for network order
  218.     ARP_packet_size=    28    ; fixes Ethernet assumption...
  219. phony_RIF    =    2082h        ; used for bridges...
  220.  
  221.  
  222.  
  223. LLC_info_size    =    8        ; LLC (3) + SNAP(5) = 8
  224.  
  225. ;-> the assigned Ethernet address of the card.
  226.     extrn    rom_address: byte
  227.  
  228. ;-> current address
  229.     extrn    my_address: byte
  230.  
  231. mark        =    0F90h        ; marker debug pos on screen 25
  232.  
  233. marker    macro   st,nd
  234.  
  235.     IF    debug NE 0        ; do marker if debug <> 0
  236.  
  237.     pushf                ; show 2 char marker on
  238.     push    es            ; 25th line, 1st column
  239.     push    ax
  240.     mov    ax,0B800h
  241.     mov    es,ax
  242.     mov    al,'&st&'
  243.     mov    byte ptr es:[mark],al
  244.     mov    al,byte ptr es:[mark+1]    ; get color value
  245.     inc    al
  246.     and    al,0Fh
  247.     or    al,1
  248.     mov    byte ptr es:[mark+1],al    ; advance it to show activity
  249.     mov    al,'&nd'
  250.     mov    byte ptr es:[mark+2],al
  251.     mov    al,byte ptr es:[mark+3]
  252.     inc    al
  253.     and    al,0Fh
  254.     or    al,1
  255.     mov    byte ptr es:[mark+3],al
  256.     pop    ax
  257.     pop    es
  258.     popf
  259.  
  260.     ENDIF
  261.  
  262.     endm
  263.  
  264. call_token    macro   ccb
  265. ;--------------------------------------;
  266. ; loads address of CCB in ES:BX, then  ;
  267. ; calls the Token Ring Interface.      ;
  268. ;--------------------------------------;
  269.     mov    ax,cs
  270.     mov    es,ax
  271.     mov    bx,offset &ccb&
  272.     int    toke_vect
  273.     endm
  274.  
  275.  
  276. call_wait    macro
  277.     local    wait_loop
  278. ;---------------------------------------;
  279. ; assumes ES:BX points to a CCB.  Waits ;
  280. ; for a pending command to terminate.   ;
  281. ;---------------------------------------;
  282. wait_loop:
  283.     mov    al,es:[bx+2]
  284.     cmp    al,toke_wait
  285.     je    wait_loop
  286.     endm
  287.  
  288.  
  289. ticks    macro
  290. ;---------------------------------------;
  291. ; get system timer ticks in CX:DX       ;
  292. ;---------------------------------------;
  293.     mov    ah,0
  294.     int    1Ah
  295.     endm
  296.  
  297.  
  298. set_ptr    macro   dest,addr
  299. ;---------------------------------------;
  300. ; loads a far pointer with a near       ;
  301. ; address offset and CS:                ;
  302. ;---------------------------------------;
  303.     mov    ax,offset &addr&
  304.     mov    word ptr [&dest&],ax
  305.     mov    ax,cs
  306.     mov    word ptr [&dest&+2],ax
  307.     endm
  308.  
  309.  
  310. print$    macro   string
  311. ;---------------------------------------;
  312. ;  sends $ terminated string to screen  ;
  313. ;---------------------------------------;
  314.     mov    ah,9
  315.     mov    dx,offset &string&    ; print $ terminated string
  316.     int    21h
  317.     endm
  318.  
  319.  
  320. clr_struc    macro   name
  321. ;---------------------------------------;
  322. ;  clear all bytes of the named struc   ;
  323. ;  to zero.  Useful for Token calls.    ;
  324. ;---------------------------------------;
  325.     mov    cx,SIZE &name&        ; uses ax, es:di, cx
  326.     mov    ax,ds
  327.     mov    es,ax
  328.     mov    di,offset &name&
  329.     xor    al,al
  330.     cld
  331.     rep    stosb            ; set all elements to 0
  332.     endm
  333.  
  334.  
  335. rdupb    macro   l,n
  336. &l&        db    ?
  337.     rept    &n&-1
  338.     db    ?
  339.     endm
  340.     endm
  341.  
  342. ccb_blk    struc                ; CCB used for local token ring calls.
  343. adapter        db    ?        ; adapter 0 or 1
  344. command        db    ?        ; command code
  345. returncode    db    ?        ; command completion code
  346. work        db    ?        ; scratch
  347. pointer        dd    ?        ; queue pointer
  348. complt        dd    ?        ; command complete appendage
  349. parms        dd    ?        ; pointer to CCB parameter table
  350. ccb_blk    ends
  351.  
  352.  
  353. init_parms    struc            ; parameters for DIR_INITIALIZE
  354. bring_ups    dw    ?        ; result of bring up tests
  355. sram_addr    dw    ?        ; shared ram address
  356. reserved    dd    ?        ; not used...
  357. chk_exit    dd    ?        ; adapter check exit
  358. status        dd    ?        ; ring status exit
  359. error        dd    ?        ; PC error exit
  360. init_parms    ends
  361.  
  362.  
  363. o_parms    struc                ; ccb parms for DIR_OPEN
  364. adapt        dd    ?        ; ptr to adapter parms
  365. direct        dd    ?        ; ptr to direct parms
  366. dlc        dd    ?        ; ptr to dlc parms
  367. msg        dd    ?        ; ptr to msg parms
  368. o_parms    ends
  369.  
  370.  
  371. ada_blk    struc                ; adapter open parms table format
  372. err_code    dw    ?        ; open errors detected
  373. options        dw    ?        ; various options
  374. node_addr    dd    ?        ; node address ( 4 bytes here +  )
  375.     dw    ?            ; rest of node address ( 2 here  )
  376. group_add    dd    ?        ; group address
  377. func_add    dd    ?        ; functional address
  378. rcv_buff    dw    ?        ; number of receive buffers
  379. rcv_len        dw    ?        ; receive buffer length
  380. dhb_len        dw    ?        ; length of transmit buffers
  381. hold_buf    db    ?        ; number of tx buffers
  382.     db    ?            ; reserved
  383. lock_code    dw    ?        ; lock code
  384. id_addr        dd    ?        ; address of id code
  385. ada_blk    ends
  386.  
  387.  
  388. dir_blk    struc                ; dir interfce open parms table format
  389. buf_size    dw    ?        ; size of direct station buffer
  390. pool_blks    dw    ?        ; number of 16 byte blocks in buff pool
  391. pool_addr    dd    ?        ; address of direct station buffer pool
  392. chk_exit    dd    ?        ; the rest can be 0 (defaults) for now
  393. stat_exit    dd    ?        ; ring status appendage pointer
  394. err_exit    dd    ?        ; PC error exit
  395. work_addr    dd    ?        ; work area segment value
  396. len_req        dw    ?        ; work area length requested
  397. len_act        dw    ?        ; actual length obtained
  398. dir_blk    ends
  399.  
  400.  
  401. dlc_blk    struc                ; dlc interface open parms table format
  402. max_sap        db    ?        ; max number of saps
  403. max_sta        db    ?        ; max number of stations
  404. max_gsap    db    ?        ; max group saps
  405. max_gmem    db    ?        ; max members per group
  406. t1_tick1    db    ?        ; DLC timer t1 interval
  407. t2_tick1    db    ?        ; DLC timer t2 interval
  408. TI_tick1    db    ?        ; DLC timer TI interval
  409. t1_tick2    db    ?        ; DLC timer t1 group 2
  410. t2_tick2    db    ?        ; DLC timer t2 group 2
  411. TI_tick2    db    ?        ; DLC timer TI group 2
  412. dlc_blk    ends
  413.  
  414.  
  415. mod_blk    struc                ; modify open parms parameter block
  416. buf_size    dw    ?        ; size of SAP buffers
  417. pool_blks    dw    ?        ; length in 16-byte, of buffer pool
  418. pool_adrs    dd    ?        ; address of direct interface buf pool
  419. chkt_exit    dd    ?        ; appendage, adapter check
  420. stat_exit    dd    ?        ; appendage, ring status
  421. err_exit    dd    ?        ; appendage, PC error exit
  422. new_opts    dw    ?        ; new options (wrap is ignored)
  423. mod_blk    ends
  424.  
  425.  
  426. tx_blk    struc                ; transmit.dir.frame parameter block
  427. station        dw    ?        ; defines station sending data
  428. trans_fs    db    ?        ; * stripped FS field (returned)
  429. rsap        db    ?        ; RSAP (remote sap value)
  430. queue_1        dd    ?        ; address of TX queue 1
  431. queue_2        dd    ?        ; address of TX queue 2
  432. buf_len_1    dw    ?        ; length of buffer 1
  433. buf_len_2    dw    ?        ; length of buffer 2
  434. buffer_1    dd    ?        ; address of the first transmit buffer
  435. buffer_2    dd    ?        ; address of the second transmit buffer
  436. tx_blk    ends
  437.  
  438.  
  439. free_blk    struc            ; buffer.free parameters
  440. st_id        dw    ?        ; station id
  441. buf_left    dw    ?        ; returns number of buffers left
  442. resrvd        dd    ?        ;
  443. first_buf    dd    ?        ; address of 1st buffer to free
  444. free_blk    ends
  445.  
  446.  
  447. get_blk    struc                ; buffer.get parameters
  448. stn_id        dw    ?        ; station id
  449. buffr_lef    dw    ?        ; buffers left
  450. buff_get    db    ?        ; number of buffers to get
  451. resrv1        db    ?        ; 3 bytes not used
  452. resrv2        db    ?
  453. resrv3        db    ?
  454. frst_buff    dd    ?        ; address of buffer obtained
  455. get_blk    ends
  456.  
  457.  
  458. rx_blk    struc                ; receive parms
  459. id        dw    ?        ; station id
  460. user_len    dw    ?        ; size of user space in buffer
  461. receiver    dd    ?        ; appendage for received data
  462. first_bf    dd    ?        ; pointer to 1st buffer
  463. opts        db    ?        ; receive options
  464. rx_blk    ends
  465.  
  466.  
  467. status_blk    struc            ; parameter table for dir.status
  468. encoded_addr    dw    ?        ; adapters permanent ring address
  469.     dd    ?
  470. node_adrs    dw    ?        ; ring address set by open
  471.     dd    ?
  472. group_adrs    dd    ?
  473. func_adrs    dd    ?
  474.     REPT    16
  475.     db    ?
  476.     ENDM
  477.     REPT    3
  478.     dd    ?
  479.     ENDM
  480.     dw    ?
  481. status_blk    ends
  482.  
  483.  
  484.  
  485.  
  486.  
  487. mac_header    struc            ; token ring mac header format
  488. AC        db    ?        ; access control byte
  489. FC        db    ?        ; frame control byte
  490. dest        db    EADDR_LEN dup(?)
  491. source        db    EADDR_LEN dup(?)
  492. dsap        db    ?        ; LLC dsap
  493. ssap        db    ?        ; LLC ssap
  494. control        db    ?        ; control byte
  495. ptype        db    ?
  496.     db    ?            ; SNAP header
  497.     db    ?
  498. ethtype        dw    ?        ; EtherType
  499. rif        dw    ?        ; optional RIF information
  500.     REPT    8            ; segment information
  501.     dw    ?            ; this is not its real position.
  502.     ENDM                ; this is a variable length field...
  503. mac_header    ends
  504.  
  505.  
  506. SA_blk    struc
  507.     rdupb    s_addr,EADDR_LEN
  508. RCF        db    ?
  509.     db    ?
  510. route        dw    ?
  511.     REPT    7
  512.     dw    ?
  513.     ENDM    ?
  514. t_mark        dd    ?        ; LRU time marker...
  515. SA_blk    ends
  516.  
  517.  
  518. ether_hdr    struc            ; ethernet header format
  519.     rdupb    ether_dest,EADDR_LEN
  520.     rdupb    ether_src,EADDR_LEN
  521. ether_type    dw    ?
  522. ether_hdr    ends
  523.  
  524.  
  525. first_buffer    struc            ; Token receive 1st buffer
  526. next_buffer    dd    ?        ; ptr to next buffer
  527. xx1        dw    ?
  528. data_size    dw    ?        ; size of user data
  529.     REPT    12
  530.     db    ?
  531.     ENDM
  532. user_data    db    ?
  533. first_buffer    ends
  534.  
  535. user_data2    =    12        ; 2nd buffer slightly different
  536.  
  537.  
  538.  
  539. ;=============================================================================;
  540. ;======================= START OF PROGRAM CODE ===============================;
  541. ;=============================================================================;
  542.  
  543. code    segment word public
  544.     assume    cs:code, ds:code
  545.  
  546. ccb        ccb_blk <>        ; scratch CCB
  547. free_ccb    ccb_blk <>
  548. tx_parms    tx_blk  <>        ; transmit.dir.frame parms
  549. iparms        init_parms <>        ; init parms
  550. pool_buff    db    (pool_size+1)*16 dup (?); buffer pool
  551. free_parms    free_blk <>        ; buffer.free parameters
  552. get_parms    get_blk  <>        ; buffer.get parameters
  553.  
  554. rx_ccb        ccb_blk <>        ; receive CCB
  555. rx_parms    rx_blk  <>        ; receive parms
  556.  
  557.  
  558. id_code        db    18 dup (0)    ; phony product id code
  559.                     ; (a real space saver...)
  560.  
  561. my_open        db    0        ; set to 1 if we opened the adapter
  562.  
  563. ada_parm    ada_blk <0,0,0,0,0,0,num_rcv_buff,recv_size,tran_size,1,0,0,0>
  564.  
  565. dir_parm    dir_blk <0,pool_size,0,0,0,0,0,0,0>
  566. dlc_parm    dlc_blk <0,0,0,0,0,0,0,0,0,0>
  567. init_parm    o_parms <0,0,0,0>
  568. initccb        ccb_blk <0,0,0,0,0,0,0>
  569. toke_status    status_blk <>
  570.  
  571. modparms    mod_blk <0,pool_size,0,0,0,0,0>
  572. modccb        ccb_blk < 0,modify_cmd,0,0,0,0,0>
  573.  
  574. lan_header    mac_header  <LLC_AC,LLC_FC>
  575.  
  576.  
  577. ;      SA RIF table has 1 entry in it by default, for the broadcast address.
  578. ;
  579. SA_index    dw    1
  580. SA_size        dw    SA_table_size    ; size of table
  581.         dw    0        ; parsed from cmd line
  582.  
  583. SA_delta    dw    0        ; delta t for LRU find
  584.         dw    0
  585. SA_ord        dw    0        ; ordinal for LRU entry
  586.  
  587. RIF_cache_ptr    dw    ?
  588.  
  589. dir_interrupt    proc
  590. ;---------------------------------------;
  591. ; Entry: token_card (0 or 1)            ;
  592. ;  Exit: AX = CCB return code           ;
  593. ;---------------------------------------;
  594.     clr_struc    ccb        ; initialize CCB
  595.     mov    ax,token_card
  596.     mov    [ccb.adapter],al
  597.     mov    al,interrupt_cmd
  598.     mov    [ccb.command],al
  599.     call_token    ccb        ; call the interface
  600.     call_wait    ccb        ; wait for completion
  601.     xor    ah,ah
  602.     mov    al,[ccb.returncode]    ; return the result in AX
  603.     ret
  604. dir_interrupt    endp
  605.  
  606.  
  607. dir_initialize    proc
  608. ;---------------------------------------;
  609. ; Entry: token_card (0 or 1)            ;
  610. ;  Exit:                                ;
  611. ;       Ah = bring up return code       ;
  612. ;       Al = ccb return code            ;
  613. ;---------------------------------------;
  614.     clr_struc    ccb        ; clear ccb
  615.     clr_struc    iparms        ; clear init parms (defaults)
  616.  
  617.     mov    ax,token_card        ; assign parameters
  618.     mov    [ccb.adapter],al
  619.     mov    al,initialize_cmd    ; command....
  620.     mov    [ccb.command],al
  621.  
  622.     set_ptr    ccb.parms,iparms    ; link to init parms
  623.  
  624.     call_token    ccb        ; call the interface
  625.     call_wait    ccb        ; wait for completion
  626.  
  627.     mov    ah,byte ptr iparms.bring_ups
  628.     mov    al,[ccb.returncode]
  629.  
  630.     ret
  631. dir_initialize    endp
  632.  
  633.  
  634. dir_open_adapter    proc
  635. ;---------------------------------------;
  636. ; Entry: token_card (0 or 1)            ;
  637. ;  Exit: AX = CCB return code           ;
  638. ;---------------------------------------;
  639.     mov    ax,token_card        ; get adapter number
  640.     mov    [initccb.adapter],al
  641.  
  642.     mov    al,open_cmd
  643.     mov    [initccb.command],al    ; 03h open_adapter command
  644.  
  645.     set_ptr    ada_parm.id_addr,id_code
  646.     set_ptr    dir_parm.pool_addr,pool_buff
  647.     set_ptr    init_parm.adapt,ada_parm
  648.     set_ptr    init_parm.direct,dir_parm
  649.     set_ptr    init_parm.dlc,dlc_parm
  650.     set_ptr    initccb.parms,init_parm
  651.  
  652.     xor    al,al
  653.     mov    [initccb.returncode],al
  654.  
  655.     call_token    initccb        ; call the interface
  656. ;    call_wait    initccb        ; wait for completion
  657. doa_1:
  658.     print$    msg_opening        ; wait for completion
  659.     mov    al,es:[bx]+2
  660.     cmp    al,toke_wait
  661.     je    doa_1
  662.  
  663.     print$    msg_lf
  664.  
  665.     xor    ah,ah
  666.     mov    al,[initccb.returncode]
  667.  
  668.     ret
  669. dir_open_adapter    endp
  670.  
  671.  
  672. dir_close_adapter    proc
  673. ;---------------------------------------;
  674. ; Entry: token_card (0 or 1)            ;
  675. ;  Exit: AX = CCB return code           ;
  676. ;---------------------------------------;
  677.     clr_struc    ccb        ; clear CCB
  678.  
  679.     mov    ax,token_card        ; initialize local CCB
  680.     mov    [ccb.adapter],al
  681.     mov    al,close_cmd        ; close command
  682.     mov    [ccb.command],al
  683.  
  684.     call_token    ccb        ; call the interface
  685.     call_wait    ccb        ; wait for completion
  686.  
  687.     xor    ah,ah
  688.     mov    al,[ccb.returncode]    ; return the result
  689.     ret
  690. dir_close_adapter    endp
  691.  
  692.  
  693. dir_modify_open    proc
  694. ;---------------------------------------;
  695. ; Entry: token_card (0 or 1)            ;
  696. ;  Exit: AX = CCB return code           ;
  697. ;---------------------------------------;
  698.     mov    ax,token_card        ; get adapter number
  699.     mov    [modccb.adapter],al    ; command is a constant in ccb
  700.  
  701.     set_ptr    modparms.pool_adrs,pool_buff
  702.     set_ptr    modccb.parms,modparms
  703.  
  704.     xor    al,al
  705.     mov    [modccb.returncode],al
  706.  
  707.     call_token    modccb        ; call the interface
  708.     call_wait    modccb        ; wait for completion
  709.  
  710.     xor    ah,ah
  711.     mov    al,[modccb.returncode]
  712.     ret
  713. dir_modify_open    endp
  714.  
  715.  
  716. dir_restore_open    proc
  717. ;---------------------------------------;
  718. ; Entry: token_card (0 or 1)            ;
  719. ;  Exit: AX = CCB return code           ;
  720. ;---------------------------------------;
  721.     clr_struc    ccb        ; initialize CCB
  722.  
  723.     mov    ax,token_card
  724.     mov    [ccb.adapter],al
  725.     mov    al,restore_cmd        ; dir.restore.open.parms
  726.     mov    [ccb.command],al
  727.  
  728.     call_token    ccb        ; call the interface
  729.     call_wait    ccb        ; wait for completion
  730.  
  731.     xor    ah,ah
  732.     mov    al,[ccb.returncode]    ; return the result in AX
  733.     ret
  734. dir_restore_open    endp
  735.  
  736.  
  737. transmit_dir_frame    proc
  738. ;---------------------------------------;
  739. ; Entry: token_card (0 or 1)            ;
  740. ;                                       ;
  741. ; Stack:                                ;
  742. ;       sp+14  dw [usr seg]             ;
  743. ;       sp+12  dw [usr ofs]             ;
  744. ;       sp+10  dw [usrsize]             ;
  745. ;       sp+8   dw [hdr seg]             ;
  746. ;       sp+6   dw [hdr ofs]             ;
  747. ;       sp+4   dw [hdrsize]             ;
  748. ;       sp+2   dw [ret ofs]             ;
  749. ;       sp+0   dw [  bp   ]             ;
  750. ;                                       ;
  751. ;  Exit:                                ;
  752. ;       Ah = stripped FS field          ;
  753. ;       al = CCB return code            ;
  754. ;---------------------------------------;
  755.  
  756. trans_frame    struc            ; transmit_dir_frame parms
  757. _x_bp        dw    ?        ; old bp register
  758. _x_ret_ofs    dw    ?        ; near return address
  759. header_size    dw    ?        ; MAC header size
  760. llc_header    dd    ?        ; address of header
  761. user_dsize    dw    ?        ; user data size
  762. user_daddress    dd    ?        ; user data address
  763. trans_frame    ends
  764.  
  765.     push    bp
  766.     mov    bp,sp
  767.  
  768.     mov    ax,cs
  769.     mov    ds,ax
  770.  
  771.     clr_struc    ccb        ; zero the CCB
  772.     clr_struc    tx_parms    ; zero parameters
  773.  
  774.     mov    ax,token_card        ; initialize local CCB
  775.     mov    [ccb.adapter],al
  776.     mov    al,trans_dir_cmd    ; transmit.dir.frame
  777.     mov    [ccb.command],al
  778. ;
  779. ;      Set up transmit parameters, and link them to
  780. ;      the CCB...
  781. ;
  782.     mov    ax,offset tx_parms
  783.     mov    word ptr [ccb.parms],ax
  784.  
  785.     mov    ax,cs
  786.     mov    word ptr [ccb.parms+2],ax
  787. ;
  788.     mov    ax,STATION_ID
  789.  
  790.     mov    word ptr [tx_parms.station],ax
  791.  
  792.     mov    ax,[bp][user_dsize]
  793.     mov    word ptr [tx_parms.buf_len_2],ax
  794.  
  795.     mov    ax,word ptr [bp][user_daddress]
  796.     mov    word ptr [tx_parms.buffer_2],ax
  797.     mov    ax,word ptr [bp][user_daddress+2]
  798.     mov    word ptr [tx_parms.buffer_2+2],ax
  799.  
  800.     mov    ax,[bp][header_size]
  801.     mov    word ptr [tx_parms.buf_len_1],ax
  802.  
  803.     mov    ax,word ptr [bp][llc_header]
  804.     mov    word ptr [tx_parms.buffer_1],ax
  805.     mov    ax,word ptr [bp][llc_header+2]
  806.     mov    word ptr [tx_parms.buffer_1+2],ax
  807.  
  808.     call_token    ccb        ; call the interface
  809.     call_wait    ccb        ; wait for completion
  810.  
  811.     mov    ah,[tx_parms.trans_fs]
  812.     mov    al,[ccb.returncode]
  813.  
  814.     pop    bp
  815.  
  816.     ret    (SIZE trans_frame)-4    ; (forget bp and ret address)
  817. transmit_dir_frame    endp
  818.  
  819.  
  820. buffer_free    proc
  821. ;---------------------------------------;
  822. ; Entry:                                ;
  823. ;      sp+4    [ seg 1st buffer ]       ;
  824. ;      sp+2    [ ofs 1st buffer ]       ;
  825. ;      sp+0    [ bp             ]       ;
  826. ;                                       ;
  827. ;  Exit: AX = CCB return code           ;
  828. ;---------------------------------------;
  829.     mov    ax,cs
  830.     mov    ds,ax
  831.  
  832.     push    bp
  833.     mov    bp,sp
  834.  
  835.     clr_struc    free_ccb
  836.     clr_struc    free_parms
  837.  
  838.     mov    ax,token_card        ; initialize local CCB
  839.     mov    [free_ccb.adapter],al
  840.  
  841.     mov    al,free_ccb_cmd        ; buffer.free
  842.     mov    [free_ccb.command],al
  843.  
  844.     mov    ax,offset free_parms
  845.     mov    word ptr [free_ccb.parms],ax
  846.  
  847.     mov    ax,cs
  848.     mov    word ptr [free_ccb.parms+2],ax
  849. ;
  850. ;      Load free_parms to release buffer
  851. ;
  852.     mov    ax,STATION_ID
  853.     mov    word ptr [free_parms.st_id],ax
  854.  
  855.     mov    ax,[bp][4]
  856.     mov    free_parms.first_buf.offs,ax
  857.     mov    ax,[bp][6]
  858.     mov    free_parms.first_buf.segm,ax
  859.  
  860.     call_token    free_ccb    ; call the interface
  861.  
  862.     xor    ah,ah
  863.     mov    al,[free_ccb.returncode]; return the result in AX
  864.  
  865.     pop    bp
  866.  
  867.     ret    4
  868. buffer_free    endp
  869.  
  870.  
  871. recv_cancel    proc
  872. ;---------------------------------------;
  873. ; Entry: token_card (0 or 1)            ;
  874. ;                                       ;
  875. ;  Exit:                                ;
  876. ;       AX = CCB return code            ;
  877. ;                                       ;
  878. ;---------------------------------------;
  879.     mov    ax,token_card        ; initialize local CCB
  880.     mov    [ccb.adapter],al
  881.  
  882.     mov    al,recv_can_cmd        ; receive.cancel
  883.     mov    [ccb.command],al
  884.  
  885.     xor    ax,ax            ; word/bytes set to 0
  886.     mov    [ccb.returncode],al
  887.     mov    [ccb.work],al
  888.     mov    word ptr [ccb.pointer],ax
  889.     mov    word ptr [ccb.pointer+2],ax
  890.     mov    word ptr [ccb.complt],ax
  891.     mov    word ptr [ccb.complt+2],ax
  892.     mov    word ptr [ccb.parms+2],ax
  893.  
  894.     mov    ax,STATION_ID
  895.     mov    word ptr [ccb.parms],ax
  896.  
  897.     call_token    ccb        ; call the interface
  898.     call_wait    ccb        ; wait for completion
  899.  
  900.     xor    ah,ah
  901.     mov    al,[ccb.returncode]    ; return the result in AX
  902.     ret
  903.  
  904. recv_cancel    endp
  905.  
  906.  
  907. open_receive    proc
  908. ;---------------------------------------;
  909. ; Entry: token_card (0 or 1)            ;
  910. ;                                       ;
  911. ; Stack:                                ;
  912. ;       sp+6   dw [ret ofs]             ;
  913. ;       sp+4   dw [  bp   ]             ;
  914. ;       sp+2   dw [  ds   ]             ;
  915. ;       sp+0   dw [  es   ]             ;
  916. ;                                       ;
  917. ;  Exit:                                ;
  918. ;       AX = CCB return code            ;
  919. ;---------------------------------------;
  920.     mov    ax,cs
  921.     mov    ds,ax
  922.  
  923.     clr_struc    rx_ccb
  924.     clr_struc    rx_parms    ;
  925.  
  926.     mov    ax,token_card        ; initialize local CCB
  927.     mov    [rx_ccb.adapter],al
  928.  
  929.     mov    al,open_recv_cmd    ; receive
  930.     mov    [rx_ccb.command],al
  931.  
  932.     mov    ax,offset recv_complt
  933.     mov    word ptr [rx_ccb.complt],ax
  934.     mov    ax,cs
  935.     mov    word ptr [rx_ccb.complt+2],ax
  936. ;
  937. ;      Link receive parameters table
  938. ;
  939.     mov    ax,offset rx_parms
  940.     mov    word ptr [rx_ccb.parms],ax
  941.     mov    ax,cs
  942.     mov    word ptr [rx_ccb.parms+2],ax
  943.  
  944.     mov    ax,STATION_ID
  945.     mov    word ptr [rx_parms.id],ax
  946.  
  947.     mov    al,RECV_OPTIONS
  948.     mov    rx_parms.opts,al
  949.  
  950.     mov    ax,offset _receiver
  951.     mov    word ptr [rx_parms.receiver],ax
  952.     mov    ax,cs
  953.     mov    word ptr [rx_parms.receiver+2],ax
  954. ;
  955. ;       Note: The receive request is submitted, but it doesn't 'complete'
  956. ;             here.  So DON'T wait for a completion code!
  957. ;
  958.     call_token    rx_ccb        ; call the interface
  959.  
  960.     xor    ah,ah
  961.     mov    al,[rx_ccb.returncode]    ; return the result
  962.     ret
  963. open_receive    endp
  964.  
  965.  
  966. recv_complt    proc
  967. ;
  968. ;      This procedure is an interrupt routine called by the Token Card
  969. ;      when receive completion occurs after an error.  All it should have
  970. ;      to do is resubmit the receive request, then exit.
  971. ;
  972.     pushf
  973.     push    ax
  974.     push    bx
  975.     push    cx
  976.     push    dx
  977.     push    si
  978.     push    di
  979.     push    ds
  980.     push    es
  981.     push    bp
  982.     sti
  983.  
  984.     marker    E,R
  985.     call    open_receive        ; restart communications
  986.  
  987.     pop    bp
  988.     pop    es
  989.     pop    ds
  990.     pop    di
  991.     pop    si
  992.     pop    dx
  993.     pop    cx
  994.     pop    bx
  995.     pop    ax
  996.     popf
  997.     iret
  998. recv_complt    endp
  999.  
  1000.  
  1001. recv_frame    struc            ; stack frame for receiver
  1002. RIF_size    dw    ?        ; size of RIF in packet.
  1003. user_buff    dd    ?        ; pointer to users buffer
  1004. user_size    dw    ?        ; size of buffer needed/used
  1005. _BP        dw    ?        ; register set on stack
  1006. _ES        dw    ?
  1007. _DS        dw    ?
  1008. _DI        dw    ?
  1009. _SI        dw    ?
  1010. _DX        dw    ?
  1011. _CX        dw    ?
  1012. _BX        dw    ?
  1013. _AX        dw    ?
  1014. recv_frame    ends
  1015.  
  1016.  
  1017. _receiver    proc
  1018. ;
  1019. ;      This interrupt procedure is called when the Token Ring
  1020. ;      card has data.
  1021. ;
  1022. ;      On entry, ds:si points to the CCB
  1023. ;                es:bx points to the receive first_buffer in the chain.
  1024. ;
  1025. ;
  1026.     pushf                ; save CPU environment
  1027.     push    ax
  1028.     push    bx
  1029.     push    cx
  1030.     push    dx
  1031.     push    si
  1032.     push    di
  1033.     push    ds
  1034.     push    es
  1035.     push    bp
  1036.  
  1037.     push    ax            ; local variables: size of receive data
  1038.     push    ax            ; segment of user supplied buffer
  1039.     push    ax            ; offset of user supplied buffer
  1040.     push    ax
  1041.  
  1042.     mov    bp,sp            ; set stack frame reference
  1043.  
  1044.     cld
  1045.     sti                ; enable further int activity
  1046.  
  1047.     marker    R,X
  1048. ;
  1049. ;      If the source address is mine, ignore the transmission!
  1050. ;
  1051.     mov    ax,cs
  1052.     mov    ds,ax
  1053.     mov    si,offset my_address
  1054.     lea    di,[bx].user_data+source; ds:si -> token address
  1055.                     ; es:di -> pkt
  1056.     mov    cx,EADDR_LEN
  1057.     push    word ptr es:[di]    ; save msb of address
  1058.  
  1059.     mov    al,es:[di]
  1060.     and    al,not_SA_mask        ; drop SA indicator
  1061.     mov    es:[di],al        ; fix the bit during compare
  1062.     repe    cmpsb            ; do string compare now
  1063.     jne    not_mine
  1064.  
  1065.     lea    di,[bx].user_data+source
  1066.     pop    word ptr es:[di]    ; restore token address
  1067.  
  1068.     jmp    drop_buffer        ; from me, ignore it!
  1069.  
  1070. ;      es:bx -> 1st receive buffer
  1071. not_mine:
  1072.     lea    di,[bx].user_data+source
  1073.     pop    word ptr es:[di]    ; save MSB of source address
  1074.  
  1075.     xor    ax,ax
  1076.     mov    cx,ax
  1077.     mov    word ptr [bp][RIF_size],ax; zero RIF size value
  1078.  
  1079. get_size:
  1080.     mov    ax,es
  1081.     or    ax,bx
  1082.     je    got_size
  1083.     add    cx,es:[bx].data_size
  1084.     les    bx,es:[bx].next_buffer
  1085.     jmp    get_size
  1086.  
  1087. got_size:
  1088.     sub    cx,LLC_info_size    ; adjust size for Token
  1089.  
  1090.     mov    es,[bp][_ES]
  1091.     mov    bx,[bp][_BX]        ; get buffer address
  1092.     mov    al,es:[bx][user_data+source]
  1093.     and    al,SA_mask        ; if SA, adjust total
  1094.     je    got_no_fix
  1095.  
  1096. ;
  1097. ;      How big is the RIF?
  1098. ;
  1099.     mov    ax,word ptr es:[bx][user_data+source+EADDR_LEN]
  1100.     and    ax,RIF_size_mask
  1101.     mov    [bp][RIF_size],ax
  1102. ;
  1103. ;      Take away size of RIF.  Upper level doesn't get it.
  1104. ;
  1105.     sub    cx,ax            ; subtract RIF size
  1106.  
  1107. got_no_fix:
  1108. ;
  1109. ;      Min Ethersize is RUNT, so check it first, round up if necessary
  1110. ;
  1111.     cmp    cx,RUNT
  1112.     jge    no_adjust_cx
  1113.     mov    cx,RUNT
  1114.  
  1115. no_adjust_cx:
  1116.     mov    [bp].user_size,cx    ; save size of receive data
  1117. ;
  1118. ;      Call recv_find to determine if the receiver wants the data,
  1119. ;      and where it should be stored.
  1120. ;
  1121.     mov    es,_ES[bp]        ; reload segment/offset
  1122.     mov    di,_BX[bp]        ; points to E-type in Token
  1123.     add    di,40            ; assumes Buffer 1 format,
  1124.     add    di,[bp][RIF_size]    ; RIF size added now...
  1125. ;
  1126. ;      if ARP type, convert hardware address space value back to Ethernet...
  1127. ;
  1128.     mov    ax,word ptr es:[di]    ;  -> EtherType in SNAP
  1129.     cmp    ax,ARP_type        ; ARP packet?
  1130.     jne    not_rx_arp
  1131.     mov    ax,ARP_Eth_hwr
  1132.     mov    word ptr es:[di][2],ax    ; fix 1st field of data
  1133.  
  1134. not_rx_arp:
  1135.     mov    dl,BLUEBOOK
  1136.     call    recv_find        ; es:di -> Snap E-Type, CX = data size
  1137.  
  1138.     mov    [bp].user_buff.offs,di
  1139.     mov    [bp].user_buff.segm,es
  1140.  
  1141.     mov    ax,es
  1142.     or    ax,di
  1143.     jne    do_copy
  1144.     jmp    drop_buffer        ; if ptr is 0, doesn't want it!
  1145. ;
  1146. ;      Copy Token Ring data to users Ethernet format receive buffer.
  1147. ;
  1148. do_copy:
  1149. ;
  1150. ;      Since the upper level wants it, better keep the RIF info in case we
  1151. ;      want to send a return message.
  1152. ;
  1153.     mov    ds,_ES[bp]
  1154.     mov    si,_BX[bp]
  1155.     add    si,user_data+source    ; 1st byte of source address
  1156.     call    add_entry        ; do table maintenance
  1157. ;
  1158. ;      Copy data to the users buffer
  1159. ;
  1160.     les    di,[bp].user_buff    ; Ethernet destination buffer
  1161.  
  1162.     mov    bx,_BX[bp]        ; Token Ring Source buffer
  1163.     mov    ds,_ES[bp]
  1164.     lea    si,[bx].user_data    ; offset to user data
  1165. ;
  1166. ;      ds:si points to 1st token buffer
  1167. ;      es:di points to ethernet format buffer
  1168.  
  1169. ;      1. Copy Token/Ether  dest/source field to users buffer
  1170. ;         after stripping off the SA bit in the source address.
  1171.  
  1172.     and    ds:[si].source,7fh
  1173.  
  1174.     mov    cx,EADDR_LEN*2        ; 2 address fields
  1175.     add    si,2            ; offset to dest field
  1176.     rep    movsb
  1177.  
  1178.     add    si,LLC_info_size-2    ; assume no RIF,
  1179.     add    si,word ptr [bp][RIF_size]; compensate for RIF
  1180.  
  1181.     movsw                ; get ethertype
  1182.  
  1183.     mov    cx,[bx].data_size    ; get length of data
  1184.     sub    cx,MAC_hdr_size        ; drop MAC header stuff
  1185.     sub    cx,[bp][RIF_size]    ; compensate for RIF
  1186.  
  1187. copy_buffer:
  1188.     rep    movsb            ; copy rest of data to Ether..
  1189.     lds    bx,[bx].next_buffer    ; bx is base of buffer
  1190.     lea    si,[bx].user_data2    ; si offsets to user data
  1191.     mov    cx,[bx].data_size    ; length of user data
  1192.     mov    ax,ds
  1193.     or    ax,bx            ; NULL pointer?
  1194.     jne    copy_buffer        ; no, keep copying...
  1195. ;
  1196. ;      Tell Upper layer I copied the data into his buffer...
  1197. ;
  1198.     lds    si,[bp].user_buff
  1199.     mov    cx,[bp].user_size
  1200.  
  1201.     call    recv_copy
  1202. ;
  1203. ;      _ES:_BX points to 1st receive buffer, drop it, then exit
  1204. ;
  1205. drop_buffer:
  1206.     push    _ES[bp]            ; tell Token, drop buffer
  1207.     push    _BX[bp]
  1208.     call    buffer_free        ; seg:offs of 1st buff on stack
  1209.  
  1210.     add    sp,4*2            ; vacuum local variables off the stack
  1211.  
  1212.     pop    bp
  1213.     pop    es
  1214.     pop    ds
  1215.     pop    di
  1216.     pop    si
  1217.     pop    dx
  1218.     pop    cx
  1219.     pop    bx
  1220.     pop    ax
  1221.     popf
  1222.  
  1223.     marker    r,x
  1224.  
  1225.     iret
  1226.  
  1227. _receiver    endp
  1228.  
  1229.  
  1230. comp_adr    proc
  1231. ;
  1232. ;      Compare two token address values, set flags without affecting any
  1233. ;      other registers.  JE or JNE to test result.
  1234. ;
  1235.     push    si
  1236.     push    di
  1237.     push    cx
  1238.     mov    cx,EADDR_LEN
  1239.     repe    cmpsb
  1240.     pop    cx
  1241.     pop    di
  1242.     pop    si
  1243.     ret
  1244. comp_adr    endp
  1245.  
  1246.  
  1247. make_adr    proc
  1248. ;
  1249. ;      Given CX as an ordinal (1..n) into the RIF_cache, build the address
  1250. ;      in ES:DI
  1251. ;
  1252.     push    ax
  1253.     push    cx
  1254.     dec    cx
  1255.     xor    di,di
  1256.     cmp    cx,0
  1257.     je    make_adr1
  1258. make_adr0:
  1259.     add    di,SIZE SA_blk        ; build index into SA_table
  1260.     loop    make_adr0
  1261.  
  1262. make_adr1:
  1263.     mov    ax,cs            ; segment of table
  1264.     mov    es,ax
  1265.     add    di,RIF_cache_ptr    ; + offset to base of table
  1266.     pop    cx
  1267.     pop    ax
  1268.     ret
  1269. make_adr    endp
  1270.  
  1271.  
  1272.  
  1273. add_entry    proc
  1274. ;
  1275. ;      DS:SI -> Token Address, make an entry in the SA routing table
  1276. ;
  1277.     mov    cx,EADDR_LEN        ; don't add broadcasts to table
  1278.     push    si            ; leave the default intact
  1279.  
  1280. add_entry0:
  1281.     lodsb                ; Broadcast?
  1282.     cmp    al,broadcast_byte
  1283.     loope    add_entry0
  1284.     pop    si
  1285.     je    add_done        ; yes...
  1286.  
  1287.     mov    al,ds:[si]        ; is it a source route address?
  1288.     and    al,SA_mask
  1289.     je    add_done
  1290. ;
  1291. ;      Is it in the table?
  1292.  
  1293.     call    loc_entry
  1294.     jc    add_done        ; c = 1, its in the table.
  1295. ;
  1296. ;      if its not in the table, try to put it in a 'new' slot...
  1297. ;
  1298.     mov    cx,word ptr cs:[SA_index]
  1299.     cmp    cx,word ptr cs:[SA_size]
  1300.     jne    lotsa_room        ; room in table, make flat entry
  1301. ;
  1302. ;      If no new slots available, determine LRU entry and overwrite it...
  1303. ;
  1304.     push    ds            ; save initial pointer
  1305.     push    si
  1306.     call    find_lru        ; returns cx ordinal into table
  1307.     pop    si            ; restore initial pointer
  1308.     pop    ds
  1309.     jmp    do_entry
  1310. ;
  1311. ;      Update entry pointer, overwrite a new slot in the table...
  1312. ;
  1313. lotsa_room:
  1314.     inc    cx
  1315.     mov    word ptr cs:[SA_index],cx; advance the table index
  1316.  
  1317. ;      before entry is made, the broadcast bit must be cleared so bridges
  1318. ;      will leave the segment values alone.
  1319.  
  1320. do_entry:
  1321.     mov    al,byte ptr ds:[si+EADDR_LEN]
  1322.     and    al,07Fh            ; clear broadcast bit
  1323.     mov    byte ptr ds:[si+EADDR_LEN],al
  1324.  
  1325.     call    make_adr        ; build destination address
  1326.     push    si
  1327.     push    di
  1328.     push    es
  1329.     mov    cx,SIZE SA_blk
  1330.     rep    movsb            ; copy RIF into table
  1331.     pop    es
  1332.     pop    di
  1333.     pop    si
  1334. ;
  1335. ;      Put time stamp on the new entry for LRU algorithm
  1336. ;
  1337.     ticks                ; cx:dx = ticks count
  1338.     mov    word ptr es:[di+t_mark],dx
  1339.     mov    word ptr es:[di+t_mark+2],cx
  1340.  
  1341. add_done:
  1342.     ret
  1343. add_entry    endp
  1344.  
  1345.  
  1346. find_lru    proc
  1347. ;
  1348. ;      locates oldest entry in the RIF_cache, returns the ordinal number in
  1349. ;      CX.  The first entry is NEVER chosen because it contains the broadcast
  1350. ;      route predefined in the table!
  1351. ;
  1352. ;      CX = 2 .. cs:[SA_size]  ( range to be searched )
  1353. ;
  1354. ;      SA_delta  dword contains time difference for last one checked
  1355. ;      SA_ord    word  contains the ordinal of the least recently used
  1356. ;
  1357.     xor    ax,ax            ; zero search variables
  1358.     mov    word ptr cs:[SA_delta],ax
  1359.     mov    word ptr cs:[SA_delta+2],ax
  1360.     mov    word ptr cs:[SA_ord],ax
  1361.  
  1362.     mov    cx,2            ; 1st entry is NEVER touched!
  1363.  
  1364. find_loop:
  1365.     call    make_adr        ; es:di -> current entry
  1366.     push    cx            ; save index
  1367.     ticks                ; cx:dx = current ticks
  1368.     sub    cx,word ptr es:[di+t_mark+2]; ticks = mark
  1369.     sbb    dx,word ptr es:[di+t_mark]
  1370. ;
  1371. ;      if the result < 0, then ticks went past midnight.  Add 24 hrs in
  1372. ;      ticks to get the real delta t.
  1373. ;
  1374.     jge    _no_fix
  1375.     add    cx,((hrs24 shr 16) and 0ffffh); longint to fix delta t
  1376.     adc    dx,(hrs24 and 0ffffh)    ; add 24 hours in ticks to
  1377.  
  1378. _no_fix:
  1379. ;
  1380. ;      If the result is greater than the stored SA_delta, replace it with
  1381. ;      this entry, then continue the loop...
  1382. ;
  1383.     push    cx            ; save hi/low delta t result
  1384.     push    dx
  1385.     sub    cx,word ptr cs:[SA_delta+2]
  1386.     sbb    dx,word ptr cs:[SA_delta]
  1387.     jl    _no_replace
  1388.  
  1389. ;
  1390. ;      replace SA_ord and SA_delta with entry that has been around longer
  1391. ;
  1392.     pop    cs:[SA_delta]        ; pull lo/hi delta t result
  1393.     pop    cs:[SA_delta+2]
  1394.     pop    cx            ; get ordinal...
  1395.     mov    word ptr cs:[SA_ord],cx    ; replace SA_ord...
  1396.     jmp    _next_find
  1397.  
  1398. _no_replace:
  1399.     pop    cx
  1400.     pop    cx
  1401.     pop    cx
  1402.  
  1403. _next_find:
  1404.     inc    cx
  1405.     cmp    cx,word ptr cs:[SA_size]
  1406.     jle    find_loop
  1407.     jmp    _find_exit
  1408.  
  1409. _find_exit:
  1410.     mov    cx,SA_ord        ; return ordinal of LRU
  1411.     ret
  1412.  
  1413. find_lru    endp
  1414.  
  1415.  
  1416.  
  1417. loc_entry    proc
  1418. ;
  1419. ;      DS:SI -> Token Address, locate entry in the SA routing table
  1420. ;      ES:DI -> SA information in table, if carry is set.
  1421. ;
  1422.     mov    cx,word ptr cs:[SA_index]; any entries in table?
  1423.     cmp    cx,0
  1424.     je    loc_done
  1425.  
  1426.  
  1427. loc_entry0:
  1428.     call    make_adr        ; build address into table
  1429.     call    comp_adr        ; compare Token Addresses
  1430.     je    loc_found        ; if matches, in table
  1431.     loop    loc_entry0
  1432.  
  1433. loc_done:
  1434.     clc
  1435.     ret
  1436.  
  1437. loc_found:
  1438.                     ;    ES:DI points to matching entry
  1439.     ticks                ; cx:dx = ticks value for
  1440.     mov    word ptr es:[di+t_mark],dx; refresh of existing
  1441.     mov    word ptr es:[di+t_mark+2],cx; entry...
  1442.  
  1443.     stc
  1444.     ret
  1445.  
  1446. loc_entry    endp
  1447.  
  1448.  
  1449. ;==============================================================================
  1450. ;
  1451. ;=================== DRIVER CODE  =============================================
  1452. ;
  1453. ;==============================================================================
  1454. ;
  1455. ;
  1456. ;      Token Ring Card number, parsed from command line
  1457. ;
  1458. token_card    dw    0        ; default adapter number 0
  1459.     dw    0            ; this prevents type error.
  1460.  
  1461. toke_ad_name    db    "Adapter (0 or 1) ",'$'
  1462. toke_sa_name    db    " RIF Cache Size: ",'$'
  1463.  
  1464. dir_open_mode    db    0        ; set <> 0 if modify_open used
  1465. msg_initialize    db    " INIT: Initializing the adapter...",CR,LF,'$'
  1466. msg_opening    db    "       Opening the adapter...",CR,'$'
  1467. msg_lf        db    LF,'$'
  1468. msg_complete    db    "       IBMTOKEN - Initialization complete.",CR,LF,'$'
  1469. msg_modifying    db    "       Creating direct buffer pool...",CR,LF,'$'
  1470. msg_bad_adapter    db    "ERROR: adapter must be 0 or 1.",CR,LF,'$'
  1471. no_mem_cache    db    "ERROR: RIF_cache value out of range!",CR,LF
  1472. msg_bad_init    db    "ERROR: Initialization Failed.",CR,LF
  1473.     db    "       Installation aborted!",CR,LF,'$'
  1474. msg_receiving    db    "       Starting receiver process...",CR,LF,'$'
  1475.  
  1476.     public    int_no
  1477. int_no        db    0,0,0,0        ;must be four bytes long for get_number.
  1478.  
  1479.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  1480. driver_class    db    BLUEBOOK,0    ;from the packet spec
  1481. driver_type    db    92        ;from the packet spec
  1482. driver_name    db    'IBMTokenR',0    ;name of the driver.
  1483. driver_function    db    2
  1484.  
  1485. parameter_list    label   byte
  1486.     db    1            ;major rev of packet driver
  1487.     db    9            ;minor rev of packet driver
  1488.     db    14            ;length of parameter list
  1489.     db    EADDR_LEN        ;length of MAC-layer address
  1490.     dw    GIANT            ;MTU, including MAC headers
  1491.     dw    MAX_MULTICAST * EADDR_LEN;buffer size of multicast addrs
  1492.     dw    0            ;(# of back-to-back MTU rcvs) - 1
  1493.     dw    0            ;(# of successive xmits) - 1
  1494.     dw    0            ;Interrupt # to hook for post-EOI
  1495.                     ;processing, 0 == none,
  1496.  
  1497.     public    rcv_modes
  1498. rcv_modes    dw    4        ;number of receive modes in our table.
  1499.     dw    0,0,0,rcv_mode_3
  1500.  
  1501.  
  1502. sp_frame    struc
  1503. __bp        dw    ?
  1504. u_size        dw    ?
  1505. u_data        dd    ?
  1506. u_snap        dw    ?
  1507. sp_frame    ends
  1508.  
  1509.  
  1510.     public bad_command_intercept
  1511. bad_command_intercept:
  1512. ;called with ah=command, unknown to the skeleton.
  1513. ;exit with nc if okay, cy, dh=error if not.
  1514.     mov    dh,BAD_COMMAND
  1515.     stc
  1516.     ret
  1517.  
  1518.     public    as_send_pkt
  1519. ; The Asynchronous Transmit Packet routine.
  1520. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  1521. ;   interrupts possibly enabled.
  1522. ; Exit with nc if ok, or else cy if error, dh set to error number.
  1523. ;   es:di and interrupt enable flag preserved on exit.
  1524. as_send_pkt:
  1525.     ret
  1526.  
  1527.     public    drop_pkt
  1528. ; Drop a packet from the queue.
  1529. ; Enter with es:di -> iocb.
  1530. drop_pkt:
  1531.     assume    ds:nothing
  1532.     ret
  1533.  
  1534.     public    xmit
  1535. ; Process a transmit interrupt with the least possible latency to achieve
  1536. ;   back-to-back packet transmissions.
  1537. ; May only use ax and dx.
  1538. xmit:
  1539.     assume    ds:nothing
  1540.     ret
  1541.  
  1542.  
  1543.     public    send_pkt
  1544. send_pkt:
  1545. ;enter with ds:si -> packet, cx = packet length.
  1546. ;exit with nc if ok, or else cy if error, dh set to error number.
  1547.     assume    ds:nothing
  1548.  
  1549.     cmp    cx,GIANT        ; Is this packet too large?
  1550.     ja    send_pkt_toobig
  1551.  
  1552.     sti
  1553.     marker    T,X
  1554.  
  1555. ;
  1556. ;      construct local stack frame
  1557. ;
  1558.     push    ds:[si].ether_type
  1559.     push    ds            ; pointer to user data packet
  1560.     lea    ax,[si]+SIZE ether_hdr
  1561.     push    ax            ; adjusted userdata pointer
  1562.     sub    cx,SIZE ether_hdr    ; adjust size for send
  1563.     push    cx
  1564.     push    bp
  1565.     mov    bp,sp            ; use sp_frame for reference
  1566.  
  1567.  
  1568.     mov    ax,cs            ; set dest pointer to LLC header
  1569.     mov    es,ax
  1570.  
  1571.     mov    di,offset lan_header.dest
  1572.     mov    cx,EADDR_LEN*2        ; copy dest|source fields
  1573.     rep    movsb
  1574. ;
  1575. ;      ds:si -> dest address, locate it in the SA RIF table
  1576. ;
  1577.     mov    ax,cs
  1578.     mov    ds,ax
  1579.     mov    si,offset lan_header.dest; building LAN header info here
  1580.  
  1581. ; Set bit 7 of address, force lookup in table.  If it is found, add RIF,
  1582. ; otherwise, assume the local net.
  1583.  
  1584.     or    byte ptr ds:[si],80h
  1585.  
  1586.     call    loc_entry
  1587.     jc    send_pkt1        ; yes, copy out RIF information
  1588. ;
  1589. ;      add the rest of the fields to the LLC header, and set the size
  1590. ;      for the transmit call.
  1591. ;
  1592.     and    byte ptr ds:[si],not_SA_mask    ; dest address 1st byte,
  1593.                     ;lop off SA bit
  1594.  
  1595.     or    byte ptr ds:[si][EADDR_LEN],80h    ; force U bit high
  1596.  
  1597.     add    si,EADDR_LEN*2        ; point after dest/source addrs.
  1598.     mov    ax,es
  1599.     mov    bx,ds
  1600.     mov    ds,ax
  1601.     mov    es,bx
  1602.     xchg    si,di
  1603.  
  1604. ;      addresses acquired from ARP default to broadcast mode, using phony
  1605. ;      RIF info so the bridge will pass the packet along.
  1606. ;
  1607.     mov    ax,phony_RIF        ; copy phony RIF to LLC buffer,
  1608.     stosw                ; so 'local' can cross bridge..
  1609.     jmp    send_pkt2
  1610.  
  1611. send_pkt_toobig:
  1612.     mov    dh,NO_SPACE
  1613.     stc
  1614.     ret
  1615.  
  1616. send_pkt1:
  1617. ;
  1618. ;      source/dest address need to be adjusted for routing.
  1619. ;
  1620.     mov    cx,EADDR_LEN
  1621.     push    si
  1622.  
  1623. send_pkt3:
  1624.     mov    al,byte ptr ds:[si]
  1625.     inc    si
  1626.     cmp    al,broadcast_byte
  1627.     loope    send_pkt3
  1628.     pop    si
  1629.     je    send_pkt4        ; broadcast address?
  1630.  
  1631.  
  1632.     and    byte ptr ds:[si],not_SA_mask    ; dest, lop off SA bit
  1633.  
  1634. send_pkt4:
  1635.     or    byte ptr ds:[si][EADDR_LEN],SA_mask    ; set SA bit for RIF
  1636.  
  1637.     add    si,EADDR_LEN*2        ; ds:si -> dest for RIF info.
  1638.     add    di,EADDR_LEN        ; es:di -> RIF info, addr fld
  1639.  
  1640.     mov    bx,si            ; keep RIF pos in LLC header
  1641.  
  1642.     mov    ax,word ptr es:[di]    ; get rif info
  1643.     and    ax,RIF_size_mask    ; get length of RIF
  1644.     mov    cx,ax
  1645.     mov    ax,es
  1646.     mov    dx,ds
  1647.     mov    ds,ax
  1648.     mov    es,dx
  1649.     xchg    si,di
  1650.     rep    movsb
  1651.  
  1652. ;
  1653. ;      Got RIF, fix direction bit.
  1654. ;
  1655.     mov    al,es:[bx][1]        ; RIF+1 = dir bit location
  1656.     xor    al,RIF_dir_bit        ; change direction
  1657.     mov    es:[bx][1],al
  1658.  
  1659. send_pkt2:
  1660. ;
  1661. ;      es:di -> target in LLC for the rest of the header,
  1662. ;      add LLC and SNAP information.
  1663. ;
  1664.     mov    ax,LLC_SSAP_DSAP    ; build LLC portion
  1665.     stosw
  1666.     mov    al,LLC_CON
  1667.     stosb
  1668.     xor    ax,ax            ; 3 bytes for Ptype in SNAP
  1669.     stosw
  1670.     stosb
  1671.     mov    ax,word ptr [bp][u_snap]
  1672.     stosw
  1673. ;
  1674. ;      header is complete.
  1675. ;
  1676.     sub    di,offset lan_header    ; calculate size of LLC header
  1677. ;
  1678. ;      stack parameters for Transmit
  1679. ;
  1680.     pop    bp
  1681.  
  1682.     mov    ax,cs
  1683.     mov    ds,ax            ; set ds for transmit entry
  1684.     push    ax
  1685.     mov    ax,offset lan_header
  1686.     push    ax
  1687.     push    di
  1688.  
  1689. ;--------------------------------------------------------------------
  1690. ;       If Users data is an ARP packet, 0806 type, then the 1st field
  1691. ;       must be changed from 0001 to 0006 for Token Ring broadcast, or
  1692. ;       no one will respond.  Funny, eh?  Another thing.  Since an ARP
  1693. ;       packet is smaller than the min size for Ethernet, the caller rounds
  1694. ;       up the size.  I have to change it back, or some Token hosts won't
  1695. ;       ARP for me.  The nerve!
  1696. ;
  1697.     push    bp
  1698.     mov    bp,sp
  1699.     mov    ax,word ptr [bp][14]    ; offset to ARP type on stack...
  1700.     pop    bp
  1701.  
  1702.     cmp    ax,ARP_type        ; network byte order is backwards
  1703.     jne    not_tx_arp
  1704. ;
  1705. ;      The first field of the ARP data has to be changed from 0001 to 0006
  1706. ;
  1707.     push    bp            ; use trans_frame
  1708.     push    bp            ; dummy entry on stack...
  1709.     mov    bp,sp
  1710.     les    di,[bp].user_daddress    ; addr of user data
  1711.  
  1712.     mov    ax,ARP_Tok_hwr
  1713.     mov    word ptr es:[di],ax    ; change ARP type to 0006
  1714.  
  1715.     mov    ax,ARP_packet_size    ; 28  bytes in an ARP packet
  1716.     mov    word ptr [bp][user_dsize],ax; reset users data size
  1717.  
  1718.     pop    bp            ; pop fake return address
  1719.     pop    bp            ; pop real bp
  1720.  
  1721. not_tx_arp:
  1722.     call    transmit_dir_frame    ; send the packet
  1723.  
  1724.     pop    ax            ; vacuum
  1725.     clc
  1726.     ret
  1727.  
  1728.  
  1729.     public    set_address
  1730. set_address:
  1731. ;enter with ds:si -> Ethernet address, CX = length of address.
  1732. ;exit with nc if okay, or cy, dh=error if any errors.
  1733.     assume    ds:nothing
  1734.     mov    dh,CANT_SET
  1735.     stc
  1736.     ret
  1737.  
  1738.  
  1739. rcv_mode_3:
  1740. ;receive mode 3 is the only one we support, so we don't have to do anything.
  1741.     ret
  1742.  
  1743.  
  1744.     public    set_multicast_list
  1745. set_multicast_list:
  1746. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  1747. ;  cx = number of bytes.
  1748. ;return nc if we set all of them, or cy,dh=error if we didn't.
  1749.     mov    dh,NO_MULTICAST
  1750.     stc
  1751.     ret
  1752.  
  1753.  
  1754.     public    reset_interface
  1755. reset_interface:
  1756. ;reset the interface.
  1757.     assume    ds:code
  1758.     ret
  1759.  
  1760.  
  1761. ;called when we want to determine what to do with a received packet.
  1762. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  1763.     extrn    recv_find: near
  1764.  
  1765. ;called after we have copied the packet into the buffer.
  1766. ;enter with ds:si ->the packet, cx = length of the packet.
  1767.     extrn    recv_copy: near
  1768.  
  1769. ;call this routine to schedule a subroutine that gets run after the
  1770. ;recv_isr.  This is done by stuffing routine's address in place
  1771. ;of the recv_isr iret's address.  This routine should push the flags when it
  1772. ;is entered, and should jump to recv_exiting_exit to leave.
  1773. ;enter with ax = address of routine to run.
  1774.     extrn    schedule_exiting: near
  1775.  
  1776. ;recv_exiting jumps here to exit, after pushing the flags.
  1777.     extrn    recv_exiting_exit: near
  1778.  
  1779. ;enter with dx = amount of memory desired.
  1780. ;exit with nc, dx -> that memory, or cy if there isn't enough memory.
  1781.     extrn    malloc: near
  1782.  
  1783.     extrn    count_in_err: near
  1784.     extrn    count_out_err: near
  1785.  
  1786.     public    recv
  1787. recv:
  1788. ;called from the recv isr.  All registers have been saved, and ds=cs.
  1789. ;Upon exit, the interrupt will be acknowledged.
  1790.     assume    ds:code
  1791.     ret
  1792.  
  1793.     public    terminate
  1794. terminate:
  1795.     sti
  1796.     call    recv_cancel        ; shut down call-backs
  1797.     cmp    my_open, word ptr 1
  1798.     jne    restore_parms
  1799.     call    dir_close_adapter    ; close out the adapter
  1800. final_exit:
  1801.     ret
  1802.  
  1803. restore_parms:
  1804.     call    dir_restore_open
  1805.     jmp    short final_exit
  1806.  
  1807.     include    popf.asm
  1808.  
  1809.     public    timer_isr
  1810. timer_isr:
  1811. ;if the first instruction is an iret, then the timer is not hooked
  1812.     iret
  1813.  
  1814. ;any code after this will not be kept.  Buffers used by the program, if any,
  1815. ;are allocated from the memory between end_resident and end_free_mem.
  1816.     public end_resident,end_free_mem
  1817. end_resident    label    byte
  1818.     db    SA_table_size * (size SA_blk) dup(0)
  1819. end_free_mem    label    byte
  1820.  
  1821. ;=======================================================================;
  1822. ;============================== RIF Cache ==============================;
  1823. ;=======================================================================;
  1824. ;      The first entry in the cache is for the broadcast address.  This ;
  1825. ;      entry is NEVER bumped from the cache!                            ;
  1826. ;=======================================================================;
  1827.  
  1828. RIF_cache_initial    SA_blk    <0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,82h,0A0h,0>
  1829.  
  1830.     public    usage_msg
  1831. usage_msg    db    CR,LF
  1832.     db    "usage: IBMTOKEN <packet_int_no> <adapter> <RIF_cache>",CR,LF,LF
  1833.     db    "where: entry_point     is the interrupt vector",CR,LF
  1834.     db    "       adapter           is adapter 0 or 1",CR,LF
  1835.     db    "       RIF_cache         is number of hosts in RIF cache",CR,LF,CR,LF
  1836.     db    " note: IBM (tm) LAN Support Program or similar DLC",CR,LF
  1837.     db    "       interface for other TR adapters required.",CR,LF,'$'
  1838.  
  1839.     public    copyright_msg
  1840. copyright_msg    db    CR,LF,"Token Ring Driver (3C501 emulation) Version "
  1841.     db    '0'+(majver / 10),'0'+(majver mod 10),"."
  1842.     db    '0'+(version / 10),'0'+(version mod 10),CR,LF
  1843.     IF    alpha NE 0
  1844.     db    "ALPHA TEST VERSION ",'0'+alpha_ver,CR,LF
  1845.     ENDIF
  1846.     db    "portions -",CR,LF
  1847.     db    "Copyright 1989, Queens University",CR,LF
  1848.     db    "Computing and Communications Services",CR,LF
  1849.     db    "Written by Brian Fisher",CR,LF
  1850.     db    "Modified to run with MS LAN Manager/IBM LAN",CR,LF
  1851.     db    "Support Program by Antero Koskinen",CR,LF
  1852.     db    "Portions copyright 1992, Crynwr Software",CR,LF
  1853.     IF    debug NE 0
  1854.     db    "*** DEBUG VERSION ***",CR,LF
  1855.     ENDIF
  1856.     db    LF,LF
  1857.     db    '$'
  1858.  
  1859.     extrn    set_recv_isr: near
  1860.  
  1861. ;enter with si -> argument string, di -> wword to store.
  1862. ;if there is no number, don't change the number.
  1863.     extrn    get_number: near
  1864.  
  1865.     public    parse_args
  1866. parse_args:
  1867. ;
  1868. ;      si points to next argument of command line...
  1869. ;
  1870.     mov    di,offset token_card    ; next argument is card number
  1871.     call    get_number
  1872.     jc    _parse_exit
  1873.     mov    di,offset SA_size    ; see if cache size ok...
  1874.     call    get_number
  1875. _parse_exit:
  1876.     clc
  1877.     ret
  1878.  
  1879. et_error:
  1880.                     ;    token adapter number out of range
  1881. ;if we got an error,
  1882.     mov    dx,offset msg_bad_adapter
  1883.     stc
  1884.     ret
  1885.  
  1886. sa_error:
  1887.                     ;    RIF cache allocation problem
  1888. ; if no memory for SA table,
  1889.     mov    dx,offset no_mem_cache
  1890.     stc
  1891.     ret
  1892.  
  1893. et_init_error:
  1894.     call    dir_close_adapter    ; make sure adapter is closed
  1895.     mov    dx,offset msg_bad_init
  1896.     stc
  1897.     ret
  1898.  
  1899.     public    etopen
  1900. ;
  1901. ;      Initialize the IBM Token Ring Adapter, determine memory requirements
  1902. ;      for the RIF_cache.
  1903. ;
  1904. etopen:
  1905.     mov    ax,cs
  1906.     mov    ds,ax
  1907.     assume    cs:code, ds:code
  1908.  
  1909.     mov    ax,token_card        ; check card parm for range
  1910.     cmp    ax,1
  1911.     jg    et_error
  1912.     cmp    ax,0
  1913.     jl    et_error        ; less than zero?
  1914.  
  1915.     mov    ax,SA_size        ; is the requested RIF cache
  1916.     cmp    ax,SA_min_size        ; size in range?
  1917.     jl    SA_error
  1918.     cmp    ax,SA_max_size
  1919.     jg    SA_error
  1920.  
  1921.     mov    bx,SIZE SA_blk        ; multiply to get bytes needed
  1922.     imul    bx
  1923.     or    dx,dx
  1924.     jne    SA_error        ; dx <> 0, way out of range!
  1925.     mov    dx,ax            ;malloc needs it in dx.
  1926.     call    malloc            ; bytes needed for code+RIF
  1927.     jc    SA_error
  1928.     mov    RIF_cache_ptr,dx    ;save pointer to our RIF_cache.
  1929.  
  1930.     movseg    es,cs
  1931.     mov    di,dx
  1932.     mov    si,offset RIF_cache_initial
  1933.     mov    cx,(size SA_blk)
  1934.     rep    movsb
  1935.  
  1936.     call    dir_interrupt        ; check if adapter open
  1937.     cmp    ax, 0            ; adapter open if retcode 0
  1938.     je    modify
  1939.  
  1940.     print$    msg_initialize        ; initialize the adapter
  1941.     call    dir_initialize
  1942.     cmp    ax,0
  1943.     jne    et_init_error
  1944.  
  1945.     call    dir_open_adapter
  1946.     cmp    ax,0
  1947.     jne    et_init_error
  1948.     mov    my_open, word ptr 1
  1949.     jmp    short no_init
  1950.  
  1951. modify:
  1952.     print$    msg_modifying        ; modify adapter open params
  1953.     call    dir_modify_open
  1954.     cmp    ax, 0
  1955.     je    no_init
  1956.     jmp    et_init_error
  1957.  
  1958. no_init:
  1959.     print$    msg_receiving        ; set up receive routines
  1960.     call    open_receive
  1961.     cmp    ax,0ffh
  1962.     je    init_ok
  1963.     jmp    et_init_error        ; no receive open...
  1964. init_ok:
  1965.  
  1966.     print$    msg_complete        ; card ready to go
  1967.  
  1968.     mov    ax,cs
  1969.     mov    ds,ax
  1970.  
  1971.     clr_struc    ccb
  1972.     clr_struc    toke_status
  1973.  
  1974.     mov    ax,token_card        ; set adapter number
  1975.     mov    [ccb.adapter],al
  1976.     mov    al,get_status_cmd    ; get status returns address
  1977.     mov    ccb.command,al
  1978.     mov    ax,offset toke_status
  1979.     mov    word ptr [ccb.parms],ax
  1980.     mov    ax,ds
  1981.     mov    word ptr [ccb.parms+2],ax
  1982.  
  1983.     call_token    ccb
  1984.     call_wait    ccb
  1985.  
  1986.     mov    si,offset toke_status.node_adrs
  1987.  
  1988.     mov    ax,cs
  1989.       mov    es,ax            ; get Token Address for _receiver
  1990.     mov    di,offset rom_address
  1991.       mov    ds,ax
  1992.  
  1993.     mov    cx,EADDR_LEN
  1994.     rep    movsb
  1995.  
  1996.     clc
  1997.     ret
  1998.  
  1999.     public    print_parameters
  2000. print_parameters:
  2001.     ret
  2002.  
  2003. code    ends
  2004.     end
  2005.  
  2006. ;******************************************************************************
  2007. ;
  2008. ;*     End of file: IBMTOKEN.ASM                                              *
  2009. ;
  2010. ;******************************************************************************
  2011.