home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / driver6s / ibmtoken.asm < prev    next >
Assembly Source File  |  1990-03-15  |  68KB  |  1,791 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.                call_wait  initccb              ; wait for completion
  590.  
  591.                xor  ah,ah
  592.                mov  al,[initccb.retcode]
  593.  
  594.                ret
  595. dir_open_adapter endp
  596.  
  597.  
  598. dir_close_adapter proc
  599. ;---------------------------------------;
  600. ; Entry: token_card (0 or 1)            ;
  601. ;  Exit: AX = CCB return code           ;
  602. ;---------------------------------------;
  603.                clr_struc ccb                   ; clear CCB
  604.  
  605.                mov     ax,token_card           ; initialize local CCB
  606.                mov     [ccb.adapter],al
  607.                mov     al,close_cmd            ; close command
  608.                mov     [ccb.command],al
  609.  
  610.                call_token ccb                  ; call the interface
  611.                call_wait  ccb                  ; wait for completion
  612.  
  613.                xor     ah,ah
  614.                mov     al,[ccb.retcode]        ; return the result
  615.                ret
  616. dir_close_adapter endp
  617.  
  618.  
  619. dir_modify_open proc
  620. ;---------------------------------------;
  621. ; Entry: token_card (0 or 1)            ;
  622. ;  Exit: AX = CCB return code           ;
  623. ;---------------------------------------;
  624.                mov     ax,token_card           ; get adapter number
  625.                mov     [modccb.adapter],al     ; command is a constant in ccb
  626.  
  627.                set_ptr modparms.pool_adrs,pool_buff
  628.                set_ptr modccb.parms,modparms
  629.  
  630.                xor     al,al
  631.                mov     [modccb.retcode],al
  632.  
  633.                call_token modccb       ; call the interface
  634.                call_wait  modccb       ; wait for completion
  635.  
  636.                xor     ah,ah
  637.                mov     al,[modccb.retcode]
  638.                ret
  639. dir_modify_open endp
  640.  
  641.  
  642. dir_restore_open proc
  643. ;---------------------------------------;
  644. ; Entry: token_card (0 or 1)            ;
  645. ;  Exit: AX = CCB return code           ;
  646. ;---------------------------------------;
  647.                clr_struc ccb                   ; initialize CCB
  648.  
  649.                mov     ax,token_card
  650.                mov     [ccb.adapter],al
  651.                mov     al,restore_cmd          ; dir.restore.open.parms
  652.                mov     [ccb.command],al
  653.  
  654.                call_token ccb                  ; call the interface
  655.                call_wait  ccb                  ; wait for completion
  656.  
  657.                xor     ah,ah
  658.                mov     al,[ccb.retcode]        ; return the result in AX
  659.                ret
  660. dir_restore_open endp
  661.  
  662.  
  663. transmit_dir_frame proc
  664. ;---------------------------------------;
  665. ; Entry: token_card (0 or 1)            ;
  666. ;                                       ;
  667. ; Stack:                                ;
  668. ;       sp+14  dw [usr seg]             ;
  669. ;       sp+12  dw [usr ofs]             ;
  670. ;       sp+10  dw [usrsize]             ;
  671. ;       sp+8   dw [hdr seg]             ;
  672. ;       sp+6   dw [hdr ofs]             ;
  673. ;       sp+4   dw [hdrsize]             ;
  674. ;       sp+2   dw [ret ofs]             ;
  675. ;       sp+0   dw [  bp   ]             ;
  676. ;                                       ;
  677. ;  Exit:                                ;
  678. ;       Ah = stripped FS field          ;
  679. ;       al = CCB return code            ;
  680. ;---------------------------------------;
  681.  
  682. trans_frame    struc                           ; transmit_dir_frame parms
  683. _x_bp          dw      ?                       ; old bp register
  684. _x_ret_ofs     dw      ?                       ; near return address
  685. header_size    dw      ?                       ; MAC header size
  686. llc_header     dd      ?                       ; address of header
  687. user_dsize     dw      ?                       ; user data size
  688. user_daddress  dd      ?                       ; user data address
  689. trans_frame    ends
  690.  
  691.                push    bp
  692.                mov     bp,sp
  693.  
  694.                mov     ax,cs
  695.                mov     ds,ax
  696.  
  697.                clr_struc ccb                   ; zero the CCB
  698.                clr_struc tx_parms              ; zero parameters
  699.  
  700.                mov     ax,token_card           ; initialize local CCB
  701.                mov     [ccb.adapter],al
  702.                mov     al,trans_dir_cmd        ; transmit.dir.frame
  703.                mov     [ccb.command],al
  704. ;
  705. ;      Set up transmit parameters, and link them to
  706. ;      the CCB...
  707. ;
  708.                mov     ax,offset tx_parms
  709.                mov     word ptr [ccb.parms],ax
  710.  
  711.                mov     ax,cs
  712.                mov     word ptr [ccb.parms+2],ax
  713. ;
  714.                mov     ax,STATION_ID
  715.  
  716.                mov     word ptr [tx_parms.station],ax
  717.  
  718.                mov     ax,[bp][user_dsize]
  719.                mov     word ptr [tx_parms.buf_len_2],ax
  720.  
  721.                mov     ax,word ptr [bp][user_daddress]
  722.                mov     word ptr [tx_parms.buffer_2],ax
  723.                mov     ax,word ptr [bp][user_daddress+2]
  724.                mov     word ptr [tx_parms.buffer_2+2],ax
  725.  
  726.                mov     ax,[bp][header_size]
  727.                mov     word ptr [tx_parms.buf_len_1],ax
  728.  
  729.                mov     ax,word ptr [bp][llc_header]
  730.                mov     word ptr [tx_parms.buffer_1],ax
  731.                mov     ax,word ptr [bp][llc_header+2]
  732.                mov     word ptr [tx_parms.buffer_1+2],ax
  733.  
  734.                call_token ccb                  ; call the interface
  735.                call_wait  ccb                  ; wait for completion
  736.  
  737.                mov     ah,[tx_parms.trans_fs]
  738.                mov     al,[ccb.retcode]
  739.  
  740.                pop     bp
  741.  
  742.                ret     (SIZE trans_frame)-4    ; (forget bp and ret address)
  743. transmit_dir_frame endp
  744.  
  745.  
  746. buffer_free    proc
  747. ;---------------------------------------;
  748. ; Entry:                                ;
  749. ;      sp+4    [ seg 1st buffer ]       ;
  750. ;      sp+2    [ ofs 1st buffer ]       ;
  751. ;      sp+0    [ bp             ]       ;
  752. ;                                       ;
  753. ;  Exit: AX = CCB return code           ;
  754. ;---------------------------------------;
  755.                mov     ax,cs
  756.                mov     ds,ax
  757.  
  758.                push    bp
  759.                mov     bp,sp
  760.  
  761.                clr_struc free_ccb
  762.                clr_struc free_parms
  763.  
  764.                mov     ax,token_card           ; initialize local CCB
  765.                mov     [free_ccb.adapter],al
  766.  
  767.                mov     al,free_ccb_cmd         ; buffer.free
  768.                mov     [free_ccb.command],al
  769.  
  770.                mov     ax,offset free_parms
  771.                mov     word ptr [free_ccb.parms],ax
  772.  
  773.                mov     ax,cs
  774.                mov     word ptr [free_ccb.parms+2],ax
  775. ;
  776. ;      Load free_parms to release buffer
  777. ;
  778.                mov     ax,STATION_ID
  779.                mov     word ptr [free_parms.st_id],ax
  780.  
  781.                mov     ax,word ptr [bp][4]
  782.                mov     word ptr [free_parms.first_buf],ax
  783.                mov     ax,word ptr [bp][6]
  784.                mov     word ptr [free_parms.first_buf+2],ax
  785.  
  786.                call_token free_ccb             ; call the interface
  787.  
  788.                xor     ah,ah
  789.                mov     al,[free_ccb.retcode]   ; return the result in AX
  790.  
  791.                pop     bp
  792.  
  793.                ret     4
  794. buffer_free    endp
  795.  
  796.  
  797. recv_cancel    proc
  798. ;---------------------------------------;
  799. ; Entry: token_card (0 or 1)            ;
  800. ;                                       ;
  801. ;  Exit:                                ;
  802. ;       AX = CCB return code            ;
  803. ;                                       ;
  804. ;---------------------------------------;
  805.                mov     ax,token_card           ; initialize local CCB
  806.                mov     [ccb.adapter],al
  807.  
  808.                mov     al,recv_can_cmd         ; receive.cancel
  809.                mov     [ccb.command],al
  810.  
  811.                xor     ax,ax                   ; word/bytes set to 0
  812.                mov     [ccb.retcode],al
  813.                mov     [ccb.work],al
  814.                mov     word ptr [ccb.pointer],ax
  815.                mov     word ptr [ccb.pointer+2],ax
  816.                mov     word ptr [ccb.complt],ax
  817.                mov     word ptr [ccb.complt+2],ax
  818.                mov     word ptr [ccb.parms+2],ax
  819.  
  820.                mov     ax,STATION_ID
  821.                mov     word ptr [ccb.parms],ax
  822.  
  823.                call_token ccb                  ; call the interface
  824.                call_wait  ccb                  ; wait for completion
  825.  
  826.                xor     ah,ah
  827.                mov     al,[ccb.retcode]        ; return the result in AX
  828.                ret
  829.  
  830. recv_cancel    endp
  831.  
  832.  
  833. open_receive proc
  834. ;---------------------------------------;
  835. ; Entry: token_card (0 or 1)            ;
  836. ;                                       ;
  837. ; Stack:                                ;
  838. ;       sp+6   dw [ret ofs]             ;
  839. ;       sp+4   dw [  bp   ]             ;
  840. ;       sp+2   dw [  ds   ]             ;
  841. ;       sp+0   dw [  es   ]             ;
  842. ;                                       ;
  843. ;  Exit:                                ;
  844. ;       AX = CCB return code            ;
  845. ;---------------------------------------;
  846.                mov     ax,cs
  847.                mov     ds,ax
  848.  
  849.                clr_struc rx_ccb
  850.                clr_struc rx_parms;
  851.  
  852.                mov     ax,token_card           ; initialize local CCB
  853.                mov     [rx_ccb.adapter],al
  854.  
  855.                mov     al,open_recv_cmd        ; receive
  856.                mov     [rx_ccb.command],al
  857.  
  858.                mov     ax,offset recv_complt
  859.                mov     word ptr [rx_ccb.complt],ax
  860.                mov     ax,cs
  861.                mov     word ptr [rx_ccb.complt+2],ax
  862. ;
  863. ;      Link receive parameters table
  864. ;
  865.                mov     ax,offset rx_parms
  866.                mov     word ptr [rx_ccb.parms],ax
  867.                mov     ax,cs
  868.                mov     word ptr [rx_ccb.parms+2],ax
  869.  
  870.                mov     ax,STATION_ID
  871.                mov     word ptr [rx_parms.id],ax
  872.  
  873.                mov     al,RECV_OPTIONS
  874.                mov     rx_parms.opts,al
  875.  
  876.                mov     ax,offset _receiver
  877.                mov     word ptr [rx_parms.receiver],ax
  878.                mov     ax,cs
  879.                mov     word ptr [rx_parms.receiver+2],ax
  880. ;
  881. ;       Note: The receive request is submitted, but it doesn't 'complete'
  882. ;             here.  So DON'T wait for a completion code!
  883. ;
  884.                call_token rx_ccb               ; call the interface
  885.  
  886.                xor     ah,ah
  887.                mov     al,[rx_ccb.retcode]     ; return the result
  888.                ret
  889. open_receive endp
  890.  
  891.  
  892. recv_complt proc
  893. ;
  894. ;      This procedure is an interrupt routine called by the Token Card
  895. ;      when receive completion occurs after an error.  All it should have
  896. ;      to do is resubmit the receive request, then exit.
  897. ;
  898.                pushf
  899.                push ax
  900.                push bx
  901.                push cx
  902.                push dx
  903.                push si
  904.                push di
  905.                push ds
  906.                push es
  907.                push bp
  908.                sti
  909.  
  910.                marker E,R
  911.                call open_receive               ; restart communications
  912.  
  913.                pop  bp
  914.                pop  es
  915.                pop  ds
  916.                pop  di
  917.                pop  si
  918.                pop  dx
  919.                pop  cx
  920.                pop  bx
  921.                pop  ax
  922.                popf
  923.                iret
  924. recv_complt    endp
  925.  
  926.  
  927. recv_frame     struc                           ; stack frame for receiver
  928.                RIF_size dw     ?               ; size of RIF in packet.
  929.                user_buff dd    ?               ; pointer to users buffer
  930.                user_size dw    ?               ; size of buffer needed/used
  931.                _BP     dw      ?               ; register set on stack
  932.                _ES     dw      ?
  933.                _DS     dw      ?
  934.                _DI     dw      ?
  935.                _SI     dw      ?
  936.                _DX     dw      ?
  937.                _CX     dw      ?
  938.                _BX     dw      ?
  939.                _AX     dw      ?
  940. recv_frame     ends
  941.  
  942.  
  943. _receiver      proc
  944. ;
  945. ;      This interrupt procedure is called when the Token Ring
  946. ;      card has data.
  947. ;
  948. ;      On entry, ds:si points to the CCB
  949. ;                es:bx points to the receive first_buffer in the chain.
  950. ;
  951. ;
  952.                 pushf                          ; save CPU environment
  953.                 push   ax
  954.                 push   bx
  955.                 push   cx
  956.                 push   dx
  957.                 push   si
  958.                 push   di
  959.                 push   ds
  960.                 push   es
  961.                 push   bp
  962.  
  963.                 push   ax                      ; local variables: size of receive data
  964.                 push   ax                      ; segment of user supplied buffer
  965.                 push   ax                      ; offset of user supplied buffer
  966.                 push   ax
  967.  
  968.                 mov    bp,sp                   ; set stack frame reference
  969.  
  970.                 sti                            ; enable further int activity
  971.  
  972.                 marker R,X
  973. ;
  974. ;      If the source address is mine, ignore the transmission!
  975. ;
  976.                mov     ax,cs
  977.                mov     ds,ax
  978.                mov     si,offset Token_address
  979.                mov     di,bx
  980.                add     di,user_data+source     ; ds:si -> token address
  981.                                                ; es:di -> pkt
  982.                mov     cx,EADDR_LEN
  983.                push    word ptr es:[di]        ; save msb of address
  984.  
  985.                mov     al,es:[di]
  986.                and     al,not_SA_mask          ; drop SA indicator
  987.                mov     es:[di],al              ; fix the bit during compare
  988.  
  989.                repe    cmpsb                   ; do string compare now
  990.                jne     not_mine
  991.  
  992.                mov     di,bx
  993.                add     di,user_data+source
  994.                pop     word ptr es:[di]        ; restore token address
  995.  
  996.                jmp     drop_buffer             ; from me, ignore it!
  997.  
  998. ;      es:bx -> 1st receive buffer
  999. not_mine:
  1000.                mov     di,bx
  1001.                add     di,user_data+source
  1002.                pop     word ptr es:[di]        ; save MSB of source address
  1003.  
  1004.                xor     ax,ax
  1005.                mov     cx,ax
  1006.                mov     word ptr [bp][RIF_size],ax ; zero RIF size value
  1007.  
  1008. get_size:
  1009.                mov     ax,es
  1010.                or      ax,bx
  1011.                je      got_size
  1012.                add     cx,word ptr es:[bx][data_size]
  1013.                push    word ptr es:[bx][next_buffer]
  1014.                push    word ptr es:[bx][next_buffer+2]
  1015.                pop     es                      ; ************************
  1016.                pop     bx                      ; ************************
  1017.                jmp     get_size
  1018.  
  1019. got_size:
  1020.                sub     cx,LLC_info_size        ; adjust size for Token
  1021.  
  1022.                mov     ax,word ptr [bp][_ES]
  1023.                mov     es,ax
  1024.                mov     bx,word ptr [bp][_BX]   ; get buffer address
  1025.                mov     al,es:[bx][user_data+source]
  1026.                and     al,SA_mask              ; if SA, adjust total
  1027.                je      got_no_fix
  1028.  
  1029. ;
  1030. ;      How big is the RIF?
  1031. ;
  1032.                mov     ax,word ptr es:[bx][user_data+source+EADDR_LEN]
  1033.                and     ax,RIF_size_mask
  1034.                mov     word ptr [bp][RIF_size],ax
  1035. ;
  1036. ;      Take away size of RIF.  Upper level doesn't get it.
  1037. ;
  1038.                sub     cx,ax                   ; subtract RIF size
  1039.  
  1040. got_no_fix:
  1041. ;
  1042. ;      Min Ethersize is RUNT, so check it first, round up if necessary
  1043. ;
  1044.                cmp     cx,RUNT
  1045.                jge     no_adjust_cx
  1046.                mov     cx,RUNT
  1047.  
  1048. no_adjust_cx:
  1049.                mov     word ptr [bp][user_size],cx ; save size of receive data
  1050. ;
  1051. ;      Call recv_find to determine if the receiver wants the data,
  1052. ;      and where it should be stored.
  1053. ;
  1054.                mov     ax,word ptr [bp][_ES]   ; reload segment/offset
  1055.                mov     es,ax
  1056.                mov     di,word ptr [bp][_BX]   ; points to E-type in Token
  1057.                add     di,40                   ; assumes Buffer 1 format,
  1058.                add     di,word ptr [bp][RIF_size] ; RIF size added now...
  1059. ;
  1060. ;      if ARP type, convert hardware address space value back to Ethernet...
  1061. ;
  1062.                mov     ax,word ptr es:[di]     ;  -> EtherType in SNAP
  1063.                cmp     ax,ARP_type             ; ARP packet?
  1064.                jne     not_rx_arp
  1065.                mov     ax,ARP_Eth_hwr
  1066.                mov     word ptr es:[di][2],ax  ; fix 1st field of data
  1067.  
  1068. not_rx_arp:
  1069.                call    recv_find               ; es:di -> Snap E-Type, CX = data size
  1070.  
  1071.                mov     word ptr [bp][user_buff],di
  1072.                mov     ax,es
  1073.                mov     word ptr [bp][user_buff+2],ax
  1074.  
  1075.                or      ax,di
  1076.                jne     do_copy
  1077.                jmp     drop_buffer             ; if ptr is 0, doesn't want it!
  1078. ;
  1079. ;      Copy Token Ring data to users Ethernet format receive buffer.
  1080. ;
  1081. do_copy:
  1082. ;
  1083. ;      Since the upper level wants it, better keep the RIF info in case we
  1084. ;      want to send a return message.
  1085. ;
  1086.                mov     ax,word ptr [bp][_ES]
  1087.                mov     ds,ax
  1088.                mov     si,word ptr [bp][_BX]
  1089.                add     si,user_data+source     ; 1st byte of source address
  1090.                call    add_entry               ; do table maintenance
  1091. ;
  1092. ;      Copy data to the users buffer
  1093. ;
  1094.                mov     di,word ptr [bp][user_buff] ; Ethernet destination buffer
  1095.                mov     ax,word ptr [bp][user_buff+2]
  1096.                mov     es,ax
  1097.  
  1098.                mov     si,word ptr [bp][_BX]   ; Token Ring Source buffer
  1099.                mov     bx,si
  1100.                mov     ax,word ptr [bp][_ES]
  1101.                mov     ds,ax
  1102.                add     si,user_data            ; offset to user data
  1103. ;
  1104. ;      ds:si points to 1st token buffer
  1105. ;      es:di points to ethernet format buffer
  1106.  
  1107. ;      1. Copy Token/Ether  dest/source field to users buffer
  1108. ;         after stripping off the SA bit in the source address.
  1109.  
  1110.                mov    al,byte ptr ds:[si+6]    ;****************
  1111.                and    al,07Fh                  ;***** NEW ******
  1112.                mov    byte ptr ds:[si+6],al    ;****************
  1113.  
  1114.                mov    cx,EADDR_LEN*2           ; 2 address fields
  1115.                add    si,2                     ; offset to dest field
  1116.                cld
  1117.                rep     movsb
  1118.  
  1119.                add     si,LLC_info_size-2      ; assume no RIF,
  1120.                add     si,word ptr [bp][RIF_size] ; compensate for RIF
  1121.  
  1122.                movsw                           ; get ethertype
  1123.  
  1124.                mov     cx,[bx][data_size]      ; get length of data
  1125.                sub     cx,MAC_hdr_size         ; drop MAC header stuff
  1126.                sub     cx,[bp][RIF_size]       ; compensate for RIF
  1127.  
  1128. copy_buffer:
  1129.                cld
  1130.                rep     movsb                   ; copy rest of data to Ether..
  1131.                push    word ptr [bx][next_buffer]
  1132.                push    word ptr [bx][next_buffer+2]
  1133.                pop     ds
  1134.                pop     si
  1135.                mov     bx,si                   ; bx is base of buffer
  1136.                add     si,user_data2           ; si offsets to user data
  1137.                mov     cx,[bx][data_size]      ; length of user data
  1138.                mov     ax,ds
  1139.                or      ax,bx                   ; NULL pointer?
  1140.                jne     copy_buffer             ; no, keep copying...
  1141. ;
  1142. ;      Tell Upper layer I copied the data into his buffer...
  1143. ;
  1144.                mov     si,word ptr [bp][user_buff]
  1145.                mov     ax,word ptr [bp][user_buff+2]
  1146.                mov     ds,ax
  1147.                mov     cx,word ptr [bp][user_size]
  1148.  
  1149.                call    recv_copy
  1150. ;
  1151. ;      _ES:_BX points to 1st receive buffer, drop it, then exit
  1152. ;
  1153. drop_buffer:
  1154.                mov     ax,word ptr [bp][_ES]   ; tell Token, drop buffer
  1155.                mov     bx,word ptr [bp][_BX]
  1156.                push    ax
  1157.                push    bx
  1158.                call    buffer_free             ; seg:offs of 1st buff on stack
  1159.  
  1160.                pop     ax                      ; vacuum local variables off
  1161.                pop     ax                      ; the stack
  1162.                pop     ax
  1163.                pop     ax
  1164.  
  1165.                pop     bp
  1166.                pop     es
  1167.                pop     ds
  1168.                pop     di
  1169.                pop     si
  1170.                pop     dx
  1171.                pop     cx
  1172.                pop     bx
  1173.                pop     ax
  1174.                popf
  1175.  
  1176.                marker  r,x
  1177.  
  1178.                iret
  1179.  
  1180. _receiver      endp
  1181.  
  1182.  
  1183. comp_adr       proc
  1184. ;
  1185. ;      Compare two token address values, set flags without affecting any
  1186. ;      other registers.  JE or JNE to test result.
  1187. ;
  1188.                push    si
  1189.                push    di
  1190.                push    cx
  1191.                cld
  1192.                mov     cx,EADDR_LEN
  1193.                repe    cmpsb
  1194.                pop     cx
  1195.                pop     di
  1196.                pop     si
  1197.                ret
  1198. comp_adr       endp
  1199.  
  1200.  
  1201. make_adr       proc
  1202. ;
  1203. ;      Given CX as an index into the SA_table (1..n), build the resulting
  1204. ;      address, in ES:DI.
  1205. ;
  1206.                push    ax
  1207.                push    cx
  1208.                dec     cx
  1209.                xor     di,di
  1210.                cmp     cx,0
  1211.                je      make_adr1
  1212.  
  1213. make_adr0:
  1214.                add     di,SIZE SA_blk          ; build index into SA_table
  1215.                loop    make_adr0
  1216.  
  1217. make_adr1:
  1218.                add     di,offset SA_table      ; complete the address
  1219.                mov     ax,cs
  1220.                mov     es,ax
  1221.                pop     cx
  1222.                pop     ax
  1223.                ret
  1224. make_adr       endp
  1225.  
  1226.  
  1227.  
  1228. add_entry      proc
  1229. ;
  1230. ;      DS:SI -> Token Address, make an entry in the SA routing table
  1231. ;
  1232.                mov     cx,EADDR_LEN            ; don't add broadcasts to table
  1233.                push    si                      ; leave the default intact
  1234.                cld
  1235.  
  1236. add_entry0:
  1237.                lodsb                           ; Broadcast?
  1238.                cmp     al,broadcast_byte
  1239.                loope   add_entry0
  1240.                pop     si
  1241.                je      add_done                ; yes...
  1242.  
  1243.                mov     al,ds:[si]              ; is it a source route address?
  1244.                and     al,SA_mask
  1245.                je      add_done
  1246. ;
  1247. ;      Is it in the table?
  1248.  
  1249.                call    loc_entry
  1250.                jc      add_done                ; c = 1, its in the table.
  1251. ;
  1252. ;      if its not in the table, lets add it, if there is room.
  1253. ;
  1254.                mov     cx,word ptr cs:[SA_index]
  1255.                cmp     cx,SA_table_size
  1256.                je      add_done                ; table full, ignore new entries...
  1257.  
  1258.                inc     cx
  1259.                mov     word ptr cs:[SA_index],cx ; advance the table index
  1260.  
  1261. ;      before entry is made, the broadcast bit must be cleared so bridges
  1262. ;      will leave the segment values alone.
  1263.  
  1264.                mov     al,byte ptr ds:[si+EADDR_LEN]
  1265.                and     al,07Fh                 ; clear broadcast bit
  1266.                mov     byte ptr ds:[si+EADDR_LEN],al
  1267.  
  1268.                call    make_adr                ; build destination address
  1269.                push    si
  1270.                mov     cx,SIZE SA_blk
  1271.                cld
  1272.                rep     movsb                   ; copy RIF into table
  1273.                pop     si
  1274.  
  1275. add_done:
  1276.                ret
  1277. add_entry      endp
  1278.  
  1279.  
  1280.  
  1281.  
  1282. loc_entry      proc
  1283. ;
  1284. ;      DS:SI -> Token Address, locate entry in the SA routing table
  1285. ;      ES:DI -> SA information in table, if carry is set.
  1286. ;
  1287.                mov     cx,word ptr cs:[SA_index]  ; any entries in table?
  1288.                cmp     cx,0
  1289.                je      loc_done
  1290.  
  1291.  
  1292. loc_entry0:
  1293.                call    make_adr                ; build address into table
  1294.                call    comp_adr                ; compare Token Addresses
  1295.                je      loc_found               ; if matches, in table
  1296.                loop    loc_entry0
  1297.  
  1298. loc_done:
  1299.                clc
  1300.                ret
  1301.  
  1302. loc_found:                                     ; ES:DI points to matching entry
  1303.                stc
  1304.                ret
  1305.  
  1306. loc_entry endp
  1307.  
  1308.  
  1309. ;==============================================================================;
  1310. ;=================== DRIVER CODE  =============================================;
  1311. ;==============================================================================;
  1312. ;
  1313. ;      Token Ring Card number, parsed from command line
  1314. ;
  1315. token_card     dw      0                       ; default adapter number 0
  1316.                dw      0                       ; this prevents type error.
  1317.  
  1318. toke_ad_name   db      "Adapter (0 or 1) ",'$'
  1319.  
  1320. dir_open_mode  db      0                       ; set <> 0 if modify_open used
  1321. msg_modify     db      "  ERROR:  Card Already in Use.",CR,LF
  1322.                db      "          REBOOT and try again.",CR,LF
  1323.                db      '$'
  1324. msg_initialize db      "INSTALL: initializing the adapter...",CR,LF,'$'
  1325. msg_opening    db      "         opening the adapter...",CR,LF,'$'
  1326. msg_complete   db      "         Adapter initialization is complete.",CR,LF,'$'
  1327. msg_bad_adapter db     "ERROR: adapter must be 0 or 1.",CR,LF,'$'
  1328. msg_bad_init   db      "  ERROR: Initialization Failed.",CR,LF
  1329.                db      "         Installation aborted.",CR,LF,'$'
  1330. msg_receiving  db      "         setting up receive process...",CR,LF,'$'
  1331.  
  1332.        public  int_no
  1333. int_no db      0,0,0,0                 ;must be four bytes long for get_number.
  1334.  
  1335.        public  driver_class, driver_type, driver_name, driver_function, parameter_list
  1336. driver_class   db      1               ;from the packet spec
  1337. driver_type    db      1               ;from the packet spec
  1338. driver_name    db      'IBMTokenR',0   ;name of the driver.
  1339. driver_function    db    2
  1340. parameter_list    label    byte
  1341.     db    1    ;major rev of packet driver
  1342.     db    9    ;minor rev of packet driver
  1343.     db    14    ;length of parameter list
  1344.     db    EADDR_LEN    ;length of MAC-layer address
  1345.     dw    GIANT    ;MTU, including MAC headers
  1346.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  1347.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  1348.     dw    0    ;(# of successive xmits) - 1
  1349.     dw    0    ;Interrupt # to hook for post-EOI
  1350.             ;processing, 0 == none,
  1351.  
  1352.        public  rcv_modes
  1353. rcv_modes      dw      4               ;number of receive modes in our table.
  1354.                dw      0,0,0,rcv_mode_3
  1355.  
  1356.  
  1357. sp_frame       struc
  1358. __bp           dw      ?
  1359. u_size         dw      ?
  1360. u_data         dd      ?
  1361. u_snap         dw      ?
  1362. sp_frame       ends
  1363.  
  1364.  
  1365.                public  send_pkt
  1366. send_pkt:
  1367. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  1368. ;  (only if the high-performance bit is set in driver_function)
  1369. ;enter with ds:si -> packet, cx = packet length.
  1370. ;exit with nc if ok, or else cy if error, dh set to error number.
  1371.                assume  ds:nothing
  1372.                sti
  1373.                marker  T,X
  1374.  
  1375. ;
  1376. ;      construct local stack frame
  1377. ;
  1378.                mov     ax,word ptr ds:[si][ether_type]
  1379.                push    ax
  1380.                push    ds                      ; pointer to user data packet
  1381.                mov     ax,si
  1382.                add     ax,SIZE ether_hdr
  1383.                push    ax                      ; adjusted userdata pointer
  1384.                sub     cx,SIZE ether_hdr       ; adjust size for send
  1385.                push    cx
  1386.                push    bp
  1387.                mov     bp,sp                   ; use sp_frame for reference
  1388.  
  1389.  
  1390.                mov     ax,cs                   ; set dest pointer to LLC header
  1391.                mov     es,ax
  1392.  
  1393.                mov     di,offset lan_header.dest
  1394.                mov     cx,EADDR_LEN*2          ; copy dest|source fields
  1395.                cld
  1396.                rep  movsb
  1397. ;
  1398. ;      ds:si -> dest address, locate it in the SA RIF table
  1399. ;
  1400.                mov     ax,cs
  1401.                mov     ds,ax
  1402.                mov     si,offset lan_header.dest ; building LAN header info here
  1403.  
  1404. ; Set bit 7 of address, force lookup in table.  If it is found, add RIF,
  1405. ; otherwise, assume the local net.
  1406.  
  1407.                mov     al,byte ptr ds:[si]       ; ********************
  1408.                or      al,080h                   ; ****** NEW *********
  1409.                mov     byte ptr ds:[si],al       ;*********************
  1410.  
  1411.                call loc_entry
  1412.                jc   send_pkt1                  ; yes, copy out RIF information
  1413. ;
  1414. ;      add the rest of the fields to the LLC header, and set the size
  1415. ;      for the transmit call.
  1416. ;
  1417.                mov     al,byte ptr ds:[si]     ; dest address 1st byte,
  1418.                                                ; lop off SA bit
  1419.                and     al,not_SA_mask
  1420.                mov     byte ptr ds:[si],al
  1421.  
  1422.                mov     al,byte ptr ds:[si][EADDR_LEN]  ; force U bit high
  1423.                or      al,080h
  1424.                mov     byte ptr ds:[si][EADDR_LEN],al
  1425.  
  1426.                add     si,EADDR_LEN*2          ; point after dest/source addrs.
  1427.                mov     ax,es
  1428.                mov     bx,ds
  1429.                mov     ds,ax
  1430.                mov     es,bx
  1431.                xchg    si,di
  1432.  
  1433. ;      addresses acquired from ARP default to broadcast mode, using phony
  1434. ;      RIF info so the bridge will pass the packet along.
  1435. ;
  1436.                mov     ax,phony_RIF            ; copy phony RIF to LLC buffer,
  1437.                cld                             ; so 'local' can cross bridge..
  1438.                stosw
  1439.                jmp     send_pkt2
  1440.  
  1441. send_pkt1:
  1442. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  1443. ;  (only if the high-performance bit is set in driver_function)
  1444. ;
  1445. ;      source/dest address need to be adjusted for routing.
  1446. ;
  1447.                mov     cx,EADDR_LEN
  1448.                push    si
  1449.  
  1450. send_pkt3:
  1451. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  1452. ;  (only if the high-performance bit is set in driver_function)
  1453.                mov     al,byte ptr ds:[si]
  1454.                inc     si
  1455.                cmp     al,broadcast_byte
  1456.                loope   send_pkt3
  1457.                pop     si
  1458.                je      send_pkt4               ; broadcast address?
  1459.  
  1460.  
  1461.                mov     al,byte ptr ds:[si]     ; dest, lop off SA bit
  1462.                and     al,not_SA_mask
  1463.                mov     byte ptr ds:[si],al
  1464.  
  1465. send_pkt4:
  1466. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  1467. ;  (only if the high-performance bit is set in driver_function)
  1468.                mov     al,byte ptr ds:[si][EADDR_LEN]
  1469.                or      al,SA_mask              ; set SA bit for RIF
  1470.                mov     byte ptr ds:[si][EADDR_LEN],al
  1471.  
  1472.                add     si,EADDR_LEN*2          ; ds:si -> dest for RIF info.
  1473.                add     di,EADDR_LEN            ; es:di -> RIF info, addr fld
  1474.  
  1475.                mov     bx,si                   ; keep RIF pos in LLC header
  1476.  
  1477.                mov     ax,word ptr es:[di]     ; get rif info
  1478.                and     ax,RIF_size_mask        ; get length of RIF
  1479.                mov     cx,ax
  1480.                mov     ax,es
  1481.                mov     dx,ds
  1482.                mov     ds,ax
  1483.                mov     es,dx
  1484.                xchg    si,di
  1485.                cld
  1486.                rep     movsb
  1487.  
  1488. ;
  1489. ;      Got RIF, fix direction bit.
  1490. ;
  1491.                mov     al,es:[bx][1]           ; RIF+1 = dir bit location
  1492.                xor     al,RIF_dir_bit          ; change direction
  1493.                mov     es:[bx][1],al
  1494.  
  1495. send_pkt2:
  1496. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  1497. ;  (only if the high-performance bit is set in driver_function)
  1498. ;
  1499. ;      es:di -> target in LLC for the rest of the header,
  1500. ;      add LLC and SNAP information.
  1501. ;
  1502.                mov     ax,LLC_SSAP_DSAP        ; build LLC portion
  1503.                stosw
  1504.                mov     al,LLC_CON
  1505.                stosb
  1506.                xor     ax,ax                   ; 3 bytes for Ptype in SNAP
  1507.                stosw
  1508.                stosb
  1509.                mov     ax,word ptr [bp][u_snap]
  1510.                stosw
  1511. ;
  1512. ;      header is complete.
  1513. ;
  1514.                sub     di,offset lan_header    ; calculate size of LLC header
  1515. ;
  1516. ;      stack parameters for Transmit
  1517. ;
  1518.                pop     bp
  1519.  
  1520.                mov     ax,cs
  1521.                mov     ds,ax                   ; set ds for transmit entry
  1522.                push    ax
  1523.                mov     ax,offset lan_header
  1524.                push    ax
  1525.                push    di
  1526.  
  1527. ;--------------------------------------------------------------------
  1528. ;       If Users data is an ARP packet, 0806 type, then the 1st field
  1529. ;       must be changed from 0001 to 0006 for Token Ring broadcast, or
  1530. ;       no one will respond.  Funny, eh?  Another thing.  Since an ARP
  1531. ;       packet is smaller than the min size for Ethernet, the caller rounds
  1532. ;       up the size.  I have to change it back, or some Token hosts won't
  1533. ;       ARP for me.  The nerve!
  1534. ;
  1535.                push    bp
  1536.                mov     bp,sp
  1537.                mov     ax,word ptr [bp][14]    ; offset to ARP type on stack...
  1538.                pop     bp
  1539.  
  1540.                cmp     ax,ARP_type             ; network byte order is backwards
  1541.                jne     not_tx_arp
  1542. ;
  1543. ;      The first field of the ARP data has to be changed from 0001 to 0006
  1544. ;
  1545.                push    bp                      ; use trans_frame
  1546.                push    bp                      ; dummy entry on stack...
  1547.                mov     bp,sp
  1548.                mov     ax,word ptr [bp][user_daddress+2] ; addr of user data
  1549.                mov     es,ax
  1550.                mov     di,word ptr [bp][user_daddress]
  1551.  
  1552.                mov     ax,ARP_Tok_hwr
  1553.                mov     word ptr es:[di],ax     ; change ARP type to 0006
  1554.  
  1555.                mov     ax,ARP_packet_size      ; 28  bytes in an ARP packet
  1556.                mov     word ptr [bp][user_dsize],ax ; reset users data size
  1557.  
  1558.                pop     bp                      ; pop fake return address
  1559.                pop     bp                      ; pop real bp
  1560.  
  1561. not_tx_arp:
  1562.                call    transmit_dir_frame      ; send the packet
  1563.  
  1564.                pop     ax                      ; vacuum
  1565.                clc
  1566.                ret
  1567.  
  1568.  
  1569.                public  get_address
  1570. get_address:
  1571. ;get the address of the interface.
  1572. ;enter with es:di -> place to get the address, cx = size of address buffer.
  1573. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  1574.                assume  ds:code
  1575. ;
  1576.                push    di
  1577.                push    es
  1578.                push    cx
  1579.  
  1580.                mov     ax,cs
  1581.                mov     ds,ax
  1582.                clr_struc ccb
  1583.                clr_struc toke_status
  1584.  
  1585.                mov     al,get_status_cmd       ; get status returns address
  1586.                mov     ccb.command,al
  1587.                mov     ax,offset toke_status
  1588.                mov     word ptr [ccb.parms],ax
  1589.                mov     ax,ds
  1590.                mov     word ptr [ccb.parms+2],ax
  1591.  
  1592.                call_token ccb
  1593.                call_wait  ccb
  1594.  
  1595.                mov     si,offset toke_status.encoded_addr
  1596.                pop     cx
  1597.                pop     es
  1598.                pop     di
  1599.                cmp     cx,EADDR_LEN            ; got the room for it?
  1600.                jb      get_address_fail
  1601.  
  1602.                cld
  1603.                mov     cx,EADDR_LEN
  1604.                rep     movsb
  1605.                mov     cx,EADDR_LEN
  1606.                clc
  1607.                ret
  1608.  
  1609. get_address_fail:
  1610.                stc
  1611.                ret
  1612.  
  1613.  
  1614.                public  set_address
  1615. set_address:
  1616. ;enter with ds:si -> Ethernet address, CX = length of address.
  1617. ;exit with nc if okay, or cy, dh=error if any errors.
  1618.                assume  ds:nothing
  1619.                clc
  1620.                ret
  1621.  
  1622.  
  1623. rcv_mode_3:
  1624. ;receive mode 3 is the only one we support, so we don't have to do anything.
  1625.        ret
  1626.  
  1627.  
  1628.        public  set_multicast_list
  1629. set_multicast_list:
  1630. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  1631. ;return nc if we set all of them, or cy,dh=error if we didn't.
  1632.        mov     dh,NO_MULTICAST
  1633.        stc
  1634.        ret
  1635.  
  1636.  
  1637.     public    terminate
  1638. terminate:
  1639.     ret
  1640.  
  1641.                public  reset_interface
  1642. reset_interface:
  1643. ;reset the interface.
  1644.                assume  ds:code
  1645.                ret
  1646.  
  1647.  
  1648. ;called when we want to determine what to do with a received packet.
  1649. ;enter with cx = packet length, es:di -> packet type.
  1650.                extrn   recv_find: near
  1651.  
  1652. ;called after we have copied the packet into the buffer.
  1653. ;enter with ds:si ->the packet, cx = length of the packet.
  1654.                extrn   recv_copy: near
  1655.  
  1656.                extrn   count_in_err: near
  1657.                extrn   count_out_err: near
  1658.  
  1659.                public  recv
  1660. recv:
  1661. ;called from the recv isr.  All registers have been saved, and ds=cs.
  1662. ;Upon exit, the interrupt will be acknowledged.
  1663.                assume  ds:code
  1664.                ret
  1665.  
  1666.  
  1667.        public  recv_exiting
  1668. recv_exiting:
  1669. ;called from the recv isr after interrupts have been acknowledged.
  1670. ;Only ds and ax have been saved.
  1671.        assume  ds:nothing
  1672.        ret
  1673.  
  1674.  
  1675.  
  1676.  
  1677. ;any code after this will not be kept after initialization.
  1678. end_resident   label   byte
  1679.  
  1680.  
  1681.                public  usage_msg
  1682. usage_msg      db      CR,LF
  1683.                db      "usage: IBMTOKEN <packet_int_no> <adapter>",CR,LF,LF
  1684.                db      "where: packet_int_no     is the interrupt vector",CR,LF
  1685.                db      "       adapter           is adapter 0 or 1",CR,LF,CR,LF
  1686.                db      " note: IBM LAN Support Program required.",CR,LF,'$'
  1687.  
  1688.                public  copyright_msg
  1689. copyright_msg  db      "*************************************************",CR,LF
  1690.                db      "*   Ethernet Packet Driver for IBM Token Ring   *",CR,LF
  1691.                db      "*                                               *",CR,LF
  1692.                db      "*   3C501 Emulation Mode, Version 1.",'0'+version
  1693.                db      "           *",CR,LF
  1694.                db      "*   portions -                                  *",CR,LF
  1695.                db      "*   Copyright 1989, Queens University           *",CR,LF
  1696.                db      "*   Computing and Communications Services       *",CR,LF
  1697.                db      "*   Written by Brian Fisher                     *",CR,LF
  1698.                IF  debug NE 0
  1699.                db      "*   DEBUG VERSION                               *",CR,LF
  1700.                ENDIF
  1701.                db      "*************************************************",CR,LF
  1702.                db      LF,LF
  1703.                db      '$'
  1704.  
  1705.                extrn   set_recv_isr: near
  1706.  
  1707. ;enter with si -> argument string, di -> wword to store.
  1708. ;if there is no number, don't change the number.
  1709.                extrn   get_number: near
  1710.  
  1711.                public  parse_args
  1712. parse_args:
  1713. ;
  1714. ;      si points to next argument of command line...
  1715. ;
  1716.                mov     bx,offset toke_ad_name  ; next argument is card number
  1717.                mov     di,offset token_card    ; default is zero
  1718.                call    get_number
  1719.                ret
  1720.  
  1721.  
  1722.                public  etopen
  1723. ;
  1724. ;      Initialize the IBM Token Ring Adapter, or use
  1725. ;      Modify Open if its already in use.
  1726. ;
  1727. etopen:
  1728.                mov     ax,cs
  1729.                mov     ds,ax
  1730.  
  1731.                mov     ax,token_card           ; check token card for range
  1732.                cmp     ax,1
  1733.                jg      et_error
  1734.  
  1735.                call    dir_modify_open
  1736.                cmp     ax,9
  1737.                jne     et_modify_error         ; can't modify open adapter!
  1738.  
  1739. do_init:
  1740.                print$  msg_initialize          ; initialize the adapter
  1741.                call    dir_initialize
  1742.                cmp     ax,0
  1743.                jne     et_init_error
  1744.  
  1745.                print$  msg_opening             ; open the adapter
  1746.                call    dir_open_adapter
  1747.                cmp     ax,0
  1748.                jne     et_init_error
  1749.  
  1750. no_init:
  1751.                print$  msg_receiving           ; set up receive routines
  1752.                call    open_receive
  1753.                cmp     ax,0ffh
  1754.                jne     et_init_error           ; no receive open...
  1755.  
  1756.                print$  msg_complete            ; card ready to go
  1757.  
  1758.  
  1759.                mov     ax,cs
  1760.                mov     es,ax                   ; get Token Address for _receiver
  1761.                mov     di,offset Token_address
  1762.                mov     ds,ax
  1763.                mov     cx,6
  1764.                call    get_address
  1765.  
  1766. all_ok:
  1767. ;if all is okay,
  1768.                mov     dx,offset end_resident
  1769.                clc
  1770.                ret
  1771.  
  1772. et_error:
  1773. ;if we got an error,
  1774.                print$  msg_bad_adapter
  1775.                stc
  1776.                ret
  1777.  
  1778. et_init_error:
  1779.                call    dir_close_adapter       ; make sure adapter is closed
  1780.                print$  msg_bad_init
  1781.                stc
  1782.                ret
  1783.  
  1784. et_modify_error:
  1785.                print$  msg_modify
  1786.                stc
  1787.                ret
  1788.  
  1789. code           ends
  1790.                end
  1791.