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