home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / NCSA / TEL2307S.ZIP / NET / ENET / NET503.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-10-20  |  22.5 KB  |  1,100 lines

  1. ;  3C503 Driver
  2. ;
  3. ;    Kurt Mahan ( based on WD8003 by Tim Krauskopf )
  4. ;
  5. ;****************************************************************************
  6. ;*                                                                          *
  7. ;*                                                                          *
  8. ;*      part of NCSA Telnet                                                 *
  9. ;*      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  10. ;*        neat other things by Kurt Mahan
  11. ;*                                                                          *
  12. ;*      National Center for Supercomputing Applications                     *
  13. ;*      152 Computing Applications Building                                 *
  14. ;*      605 E. Springfield Ave.                                             *
  15. ;*      Champaign, IL  61820                                                *
  16. ;*                                                                          *
  17. ;*                                                                          *
  18. ;****************************************************************************
  19. ;
  20.  
  21.     TITLE    NETSUPPORT -- LOW LEVEL DRIVERS FOR ETHERNET
  22. ;
  23. ;  Assembler support for interrupt-driven Ethernet I/O on the PC
  24. ;
  25. ;  Reads and writes from the 8K buffer on the WD card.
  26. ;  Started 4/11/88
  27. ;
  28. ;Microsoft EQU 1
  29. ;Lattice EQU 1
  30. ifndef Microsoft
  31.     ifndef Lattice
  32.         if2
  33.             %out
  34.             %out ERROR: You have to specify "/DMicrosoft" OR "/DLattice" on the
  35.             %out        MASM command line to determine the type of assembly.
  36.             %out
  37.         endif
  38.         end
  39.     endif
  40. endif
  41.  
  42. ifdef Microsoft
  43. X    EQU    6
  44.     DOSSEG
  45.     .MODEL    LARGE
  46. else
  47.         NAME    NET503
  48.       INCLUDE    DOS.MAC
  49.       SETX
  50. endif
  51.  
  52. ;
  53. ;    EQUATES for the 3C503 board
  54. ;
  55.  
  56. CMDR    equ    00h              ; ports on the 8390 ( page 0 )
  57. PSTART    equ    01h
  58. PSTOP    equ    02h
  59. BNRY    equ    03h
  60. TPSR    equ    04h
  61. TBCR0    equ    05h
  62. TBCR1    equ    06h
  63. ISR    equ    07h
  64. RSAR0    equ    08h
  65. RSAR1    equ    09h
  66. RBCR0    equ    0ah
  67. RBCR1    equ    0bh
  68. XRCR    equ    0ch
  69. TCR    equ    0dh
  70. DCR    equ    0eh
  71. IMR    equ    0fh
  72.  
  73. PAR0    equ    01h              ; ports on the 8390 ( page 1 )
  74. PAR1    equ    02h
  75. PAR2    equ    03h
  76. PAR3    equ    04h
  77. PAR4    equ    05h
  78. PAR5    equ    06h
  79. CURR    equ    07h
  80. MAR0    equ    08h
  81. MAR1    equ    09h
  82. MAR2    equ    0ah
  83. MAR3    equ    0bh
  84. MAR4    equ    0ch
  85. MAR5    equ    0dh
  86. MAR6    equ    0eh
  87. MAR7    equ    0fh
  88.  
  89. PSTR    equ    400h              ; ports on the gate array
  90. PSPR    equ    401h
  91. DQTR    equ    402h
  92. BCFR    equ    403h
  93. PCFR    equ    404h
  94. GACFR    equ    405h
  95. CTRL    equ    406h
  96. STREG    equ    407h
  97. IDCFR    equ    408h
  98. DAMSB    equ    409h
  99. DALSM    equ    40ah
  100. VPTR2    equ    40bh
  101. VPTR1    equ    40ch
  102. VPTR0    equ    40dh
  103. RFMSB    equ    40eh
  104. RFLSB    equ    40fh
  105.  
  106. STRT_PG    equ    26h              ; start at page 6
  107. STOP_PG    equ    40h              ; end at page 31
  108. TSTRT_PG equ    20h              ; transmit start page
  109.  
  110. ;
  111. ;  macros for writing to NET503 board
  112. ;
  113. ;***********************************************************************
  114. ;
  115. ;    Macros, from example driver
  116. ;
  117. ;***********************************************************************
  118.  
  119. ;
  120. ; MACRO rd_wd8
  121. ;   Reads port specified on macro call. Leaves byte in AL.
  122. ;
  123.  
  124. rd_wd8    MACRO    port
  125.     push    dx
  126.     mov    DX, WDBASE
  127.     add    DX, port        ; DX contains address of port
  128.     in    AL, DX            ; AL contains data read from port
  129.     pop    dx
  130.     ENDM
  131.  
  132. ;
  133. ; MACRO wr_wd8
  134. ;   Writes byte in AL to port specified on macro call.
  135. ;
  136.  
  137. wr_wd8    MACRO    port
  138.     push    dx
  139.     mov    DX, WDBASE
  140.     add    DX, port        ; DX contains address of port
  141.     out    DX, AL            ; AL contains data to be written to port
  142.     pop    dx
  143.     ENDM
  144.  
  145. ;
  146. ifdef Microsoft
  147. ;DGROUP    group    _DATA
  148. ;_DATA    segment    public 'DATA'
  149. ;    assume    DS:DGROUP
  150.     .data
  151. else
  152.     DSEG
  153. endif
  154. ;    PUBLIC    STAT,BUFPT,BUFORG,BUFEND,BUFREAD,BUFBIG,BUFLIM,OFFS
  155. ;
  156. ;  The pointers below are actually DWORDs but we access them two
  157. ;  bytes at a time.
  158. ;
  159. ; STAT change to RSTAT because of name clash with MSC library routine
  160. ifdef Microsoft
  161.     EXTRN    _RSTAT:BYTE    ; last status from read
  162.     EXTRN    _BUFPT:WORD    ; current buffer pointer
  163.     EXTRN    _BUFORG:WORD    ; pointer to beginning of buffer
  164.     EXTRN    _BUFEND:WORD    ; pointer to end of buffer
  165.     EXTRN    _BUFREAD:WORD    ; pointer to where program is reading
  166.     EXTRN    _BUFBIG:WORD    ; integer, how many bytes we have
  167.     EXTRN    _BUFLIM:WORD    ; integer, max bytes we can have
  168. else
  169.     EXTRN    RSTAT:BYTE    ; last status from read
  170.     EXTRN    BUFPT:WORD    ; current buffer pointer
  171.     EXTRN    BUFORG:WORD    ; pointer to beginning of buffer
  172.     EXTRN    BUFEND:WORD    ; pointer to end of buffer
  173.     EXTRN    BUFREAD:WORD    ; pointer to where program is reading
  174.     EXTRN    BUFBIG:WORD    ; integer, how many bytes we have
  175.     EXTRN    BUFLIM:WORD    ; integer, max bytes we can have
  176. endif
  177.  
  178. WDBASE    DW    00h        ; base ioaddr
  179. WDADD    DW    00h        ; base shared mem addr
  180. DEAF    DB    00H        ; when we can't handle any more packets
  181. OFFS    DW    00H        ; how many times the handler was turned off
  182. WIRE    DB    02h        ; thin as the default
  183. ;
  184. ifdef Microsoft
  185. ;_DATA    ends
  186. else
  187.     ENDDS
  188. endif
  189. ;
  190. ;   The subroutines to call from C
  191. ;
  192. ifdef Microsoft
  193. ;_TEXT    segment    public    'CODE'
  194. ;    assume CS:_TEXT
  195.     .code
  196.     PUBLIC    _E4RECV,_E4ETOPEN,_E4ETCLOSE,_E4GETADDR
  197. ifdef NOT_USED
  198.     PUBLIC  _E4SETADDR
  199. endif
  200.     PUBLIC  _E4XMIT,_E4ETUPDATE
  201.     PUBLIC _E4SETWIRE
  202. else
  203.     PSEG
  204.     PUBLIC    E4RECV,E4ETOPEN,E4ETCLOSE,E4GETADDR
  205. ifdef NOT_USED
  206.     PUBLIC  E4SETADDR
  207. endif
  208.     PUBLIC  E4XMIT,E4ETUPDATE, E4SETWIRE
  209. endif
  210.  
  211.  
  212. ;*****************************************************************
  213. ;
  214. ; E4SETWIRE
  215. ;
  216. ; WHAT TYPE OF WIRE ARE WE USING?  THIN OR THICK
  217. ;
  218. ; USAGE: E4SETWIRE(INT WIRE)
  219. ;
  220.  
  221. ifdef Microsoft
  222. _E4SETWIRE    PROC FAR
  223. else
  224. E4SETWIRE    PROC FAR
  225. endif
  226.  
  227.     PUSH BP
  228.     MOV  BP,SP
  229.     push ds
  230.     mov  ax,seg WIRE
  231.     mov  ds,ax
  232.     XOR  AX,AX
  233.     MOV  AL,[BP+X]        ; GET WIRE TYPE
  234.     MOV  WIRE,AL         ; STORE IT!
  235.     pop  ds
  236.     POP  BP
  237.     RET
  238.  
  239. ifdef    Microsoft
  240. _E4SETWIRE    ENDP
  241. else
  242. E4SETWIRE    ENDP
  243. endif
  244.  
  245.  
  246. ;******************************************************************
  247. ;  ETOPEN
  248. ;     Initialize the Ethernet board, set receive type.
  249. ;
  250. ;  usage:  etopen(s,irq,addr,ioaddr)
  251. ;           char s[6];       ethernet address
  252. ;           int irq,addr,ioaddr;     
  253. ;                interrupt number (unused), base mem address and
  254. ;                i/o address to use
  255. ;
  256. ifdef    Microsoft
  257. _E4ETOPEN    PROC    FAR
  258. else
  259. E4ETOPEN    PROC    FAR
  260. endif
  261. ;
  262. ;    init addresses and things
  263. ;
  264.  
  265.     PUSH    BP
  266.     MOV    BP,SP
  267.  
  268.     mov    AX,[BP+X+8]        ; install ioaddr
  269.     mov    WDBASE,AX
  270.     mov    AX,[BP+X+6]        ; install shared mem addr
  271.     mov    WDADD,AX
  272. ;
  273. ;    initialize the gate array
  274. ;
  275.     push    ds
  276.     mov    ax,seg WIRE
  277.     mov    ds,ax
  278.     mov    al,1            ; reset the board -- onboard xcvr
  279.     or     al,WIRE
  280.     wr_wd8    CTRL
  281.     mov    al,0            ; done with reset -- still onboard xcvr
  282.     or    al,WIRE
  283.     wr_wd8    CTRL
  284.     wr_wd8    CTRL
  285.     pop    ds
  286. ;
  287. ;    set the vector pointers ( VPTR0 - VPTR2 ) so that the shared memory
  288. ;    won't go byebye on us accidentally ( point to ffff00h )
  289. ;
  290.     mov    al,0ffh
  291.     wr_wd8    VPTR2
  292.     wr_wd8    VPTR1
  293.     xor    al,al
  294.     wr_wd8    VPTR0
  295. ;
  296. ;    lookup the shared memory address ( such a neat card, huh -- we can
  297. ;    actually read it up from the gate array )
  298. ;
  299. ;    PCFR : high bits = ( 7 .. 0 )
  300. ;                bit 7 = dc00
  301. ;                bit 6 = d800
  302. ;                bit 5 = cc00
  303. ;                bit 4 = c800
  304. ;
  305. ;
  306.     rd_wd8    PCFR            ; read prom config register
  307.     test    al,80h            ; dc00?
  308.     jz    eto100
  309.     mov    WDADD,0da00h
  310.     jmp SHORT etok
  311. eto100:    test    al,40h            ; d800?
  312.     jz    eto200
  313.     mov    WDADD,0d600h
  314.     jmp SHORT etok
  315. eto200:    test    al,20h            ; cc00?
  316.     jz    eto300
  317.     mov    WDADD,0ca00h
  318.     jmp SHORT etok
  319. eto300:    test    al,10h            ; c800?
  320.     jz    eto400
  321.     mov    WDADD,0c600h
  322.     jmp SHORT etok
  323. ;
  324. eto400:    mov    ax,-1            ; mem not enabled
  325.     pop    bp
  326.     ret
  327. ;
  328. ;    ok, WDBASE is setup as the base memory address
  329. ;
  330. etok :    mov    al,0c9h            ; dis ints, ram sel, bank 0
  331.     wr_wd8    GACFR
  332. ;
  333. ;    setup the start/stop pages 
  334. ;
  335.     mov    al,STRT_PG        ; starting page
  336.     wr_wd8    PSTR
  337.     mov    al,STOP_PG        ; ending page
  338.     wr_wd8    PSPR
  339. ;
  340. ;    setup the interrupt and dma request stuff
  341. ;
  342.     xor    al,10h            ; no ints, no dma channels
  343.     wr_wd8    IDCFR            ; interrupt/dma channel ctrl
  344. ;
  345. ;    set DRQ timer to 8
  346. ;
  347.     mov    al,8
  348.     wr_wd8    DQTR
  349. ;
  350. ;    set dma msb to 20h
  351. ;
  352.     mov    al,TSTRT_PG        ; transmit start page
  353.     wr_wd8    DAMSB
  354.     xor    al,al            ; 0
  355.     wr_wd8    DALSM
  356. ;
  357.     cld
  358. ;
  359. ; initialize the LAN Controller register
  360. ;                    
  361.     push    ds
  362.     mov    ax,seg WIRE
  363.     mov    ds,ax
  364.     mov    al,0
  365.     or    al,WIRE
  366.     wr_wd8    CTRL            ; make sure its switched in
  367.     pop    ds
  368. ;
  369. ; program for page 0
  370. ;
  371.     mov    AL, 21h              ; page 0, abort any pending dma
  372.     wr_wd8    CMDR
  373. ;
  374. ;    clear interrupt regs
  375. ;
  376.     mov    al, 0ffh
  377.     wr_wd8    ISR
  378. ;
  379. ; initial DCR data configuration
  380. ;
  381.     mov    AL, 48h               ; burst dma, fifo thresh = 8 bytes
  382.     wr_wd8    DCR
  383. ;
  384. ; initial TCR
  385. ;
  386.     xor    AL, AL            
  387.     wr_wd8    TCR            ; normal operation
  388. ;
  389. ; initial RCR to monitor mode
  390. ;
  391.     mov    AL, 20h                ; monitor mode
  392.     wr_wd8    XRCR
  393. ;
  394. ; set page start/page stop/ boundary
  395. ;
  396.     mov    AL,STRT_PG
  397.     wr_wd8    PSTART
  398.     mov    al,STOP_PG
  399.     wr_wd8    PSTOP
  400.     mov    al,STRT_PG        ; go with the WD style of things
  401.     wr_wd8    BNRY
  402. ;
  403. ; program for page 1
  404. ;
  405.     mov    AL, 60h               ; page 1, abort any pending dma
  406.     wr_wd8    CMDR
  407. ;
  408. ; initial physical addr
  409. ;
  410.     mov    DX, WDBASE        ; get board io base
  411.     push    DS
  412.     mov    ax,[bp+X+2]        ; get seg from parms
  413.     mov    ds,ax
  414.  
  415.     mov    CX, 6            ; should be 6 for Ethernet
  416.     mov    BX, [BP+X]        ; ptr to adr in BX
  417.     add    DX, PAR0        ; i/o address of PAR0 in DX
  418. lopa:
  419.     mov    AL, [BX]        ; get 1 byte into AL
  420.     out    DX, AL            ; write to PAR
  421.     inc    BX
  422.     inc    DX
  423.     loop    lopa
  424.     pop    DS
  425. ;
  426. ; initial multicast filter,  write all 0's  into MAR0 - MAR7
  427. ;
  428.     mov    CX, 8
  429.     mov    DX, WDBASE
  430.     add    DX, MAR0        ; i/o address of MAR0 in DX
  431.     xor    AL, AL            
  432. lopb:
  433.     out    DX, AL
  434.     inc    DX
  435.     loop    lopb                    
  436. ;
  437. ;    set CURR page
  438. ;
  439.     mov    al,STRT_PG+1
  440.     wr_wd8    CURR
  441. ;
  442. ; program for page 0
  443. ;
  444.     mov    al,21h            ; page 0, stop any dma stuff
  445.     wr_wd8    CMDR
  446. ;
  447. ; initial IMR
  448. ;
  449.     xor    al,al            ; ***NCSA Telnet does not need interrupts
  450.     wr_wd8    IMR            ; enable interrupt
  451.     mov    al,0ffh
  452.     wr_wd8    ISR
  453. ;
  454. ;    clear byte counts
  455. ;
  456.     xor    AL, AL
  457.     wr_wd8    RBCR0
  458.     wr_wd8    RBCR1
  459. ;    
  460. ; put 8390 on line
  461. ;
  462.     mov    al,22h            ; start up the 8390
  463.     wr_wd8    CMDR
  464. ;
  465. ; program RCR to normal operation (MSK_AB, no MSK_AM)
  466. ;
  467.     mov    al,4                ; accept broadcast packets
  468.     wr_wd8    XRCR
  469. ;
  470.     mov    al,0c9h
  471.     wr_wd8    GACFR
  472. ;
  473. ;    I'm happy to keep GACFR at c9 ( no interrupts )
  474. ;
  475. ;    return NO ERROR
  476. ;
  477.     XOR    AX,AX
  478.     POP    BP
  479.     RET
  480. ;
  481. ifdef    Microsoft
  482. _E4ETOPEN    ENDP
  483. else
  484. E4ETOPEN    ENDP
  485. endif
  486.  
  487. ifdef NOT_USED
  488. ;
  489. ;******************************************************************
  490. ;  SETADDR
  491. ;    set the Ethernet address on the board to 6 byte ID code
  492. ;
  493. ;   usage:   setaddr(s,basea,ioa);
  494. ;             char s[6];           ethernet address to use
  495. ;             int basea;           shared memory base address 
  496. ;             int ioa;             io address for board
  497. ;
  498. ifdef    Microsoft
  499. _E4SETADDR    PROC    FAR
  500. else
  501. E4SETADDR    PROC    FAR
  502. endif
  503.  
  504.     PUSH    BP
  505.     MOV    BP,SP
  506. ;
  507. ;  not used for this board, set during etopen
  508. ;
  509.     POP    BP
  510.     RET
  511. ifdef    Microsoft
  512. _E4SETADDR    ENDP
  513. else
  514. E4SETADDR    ENDP
  515. endif
  516. endif       ; NOT_USED
  517. ;
  518. ;*******************************************************************
  519. ;  GETADDR
  520. ;     get the Ethernet address off of the board
  521. ;
  522. ;   usage:  getaddr(s,address,ioaddr);
  523. ;    char s[6];           will get six bytes from the PROM
  524. ;       int address;
  525. ;       int ioaddr;      mem address and ioaddress to use
  526. ;
  527. ifdef    Microsoft
  528. _E4GETADDR    PROC    FAR
  529. else
  530. E4GETADDR    PROC    FAR
  531. endif
  532.  
  533.     PUSH    BP
  534.     MOV    BP,SP
  535.     PUSH    DS
  536.     MOV    AX,[BP+X+2]    ; SEG of where to put info
  537.     MOV    DS,AX
  538.     MOV    BX,[BP+X]    ; address of where to put info
  539.     mov    cx,6
  540.     mov    dx,[BP+X+6]    ; ioaddr for board
  541. ;
  542. ;    set the gate array to look at the lower 16 bytes of the prom
  543. ;
  544.     push    ds
  545.     mov    ax,seg WIRE
  546.     mov    ds,ax
  547.     mov    al,1
  548.     or    al,WIRE
  549.     pop    ds
  550.     push    dx
  551.     add    dx,CTRL
  552.     out    dx,al
  553.     mov    al,2
  554.     out    dx,al
  555.     mov    al,6
  556.     out    dx,al
  557.     
  558.     pop    dx
  559.     push    dx
  560. ;
  561. getloop:
  562.     in    al,dx
  563.     mov    [bx],al        ; store where we want
  564.     inc    dx
  565.     inc    bx
  566.     loop    getloop
  567. ;
  568. ;    reset the gate array to normal mapping
  569. ;
  570.     pop    dx
  571.     push    ds
  572.     mov    ax,seg WIRE
  573.     mov    ds,ax
  574.     mov    al,0        ; still onboard xcvr 
  575.     or    al,WIRE
  576.     pop    ds
  577.     add    dx,CTRL
  578.     out    dx,al
  579.     POP    DS
  580.     POP    BP        
  581.     RET
  582. ifdef    Microsoft
  583. _E4GETADDR    ENDP
  584. else
  585. E4GETADDR    ENDP
  586. endif
  587.  
  588. ;
  589. ;***********************************************************************
  590. ;  ETCLOSE
  591. ;        shut it down, remove the interrupt handler
  592. ;
  593. ;  usage:  etclose();
  594. ;
  595. ;
  596. ifdef    Microsoft
  597. _E4ETCLOSE    PROC    FAR
  598. else
  599. E4ETCLOSE    PROC    FAR
  600. endif
  601.  
  602.     RET
  603. ifdef    Microsoft
  604. _E4ETCLOSE    ENDP
  605. else
  606. E4ETCLOSE    ENDP
  607. endif
  608. ;
  609. ;************************************************************************
  610. ;   Receive
  611. ;   This is a CPU hook for boards that must be polled before we can
  612. ;   deliver packets into the receive buffer.  (i.e. no interrupts used)
  613. ;
  614. ;    usage:  recv();
  615. ;
  616. ifdef    Microsoft
  617. _E4RECV    PROC    FAR
  618. else
  619. E4RECV    PROC    FAR
  620. endif
  621.  
  622.     push    bp
  623.     push    es
  624. ;
  625. ;  check for data which can be read
  626. ;
  627.     rd_wd8    XRCR            ; read the Rx Status Register
  628.     and    al,01h            ; check for a packet
  629.     jnz    snore            ; none -- go onto something else
  630.     jmp    end_rx
  631. snore:
  632. ;
  633. ;    ok, the chip thinks we have a packet to read
  634. ;
  635.     mov    AL, 61h            ; page 1
  636.     wr_wd8    CMDR
  637.     rd_wd8    CURR
  638.     mov    BL, AL            ; CURR in BL 
  639. ;
  640.     mov    AL, 20h            ; page 0
  641.     wr_wd8  CMDR
  642.     rd_wd8    BNRY            ; BNRY in AL
  643. ;
  644.     add    AL, 1            ; start page of frm in AL
  645.     cmp    AL, STOP_PG        ; check boundary
  646.     jne    go_cmp
  647.     mov    AL, STRT_PG        
  648. go_cmp:
  649.     cmp    AL, BL            
  650.     jne    gotone
  651.     jmp     end_rx            ; buff ring empty
  652. gotone:
  653. ;
  654. ; ring not empty
  655. ;
  656.     mov    BH, AL
  657.     xor    BL, BL            ; BX has the rx_frm pointer
  658.     push    BX            ; save the frm ptr
  659.         mov    AX, WDADD        ; shared mem base
  660.     mov     ES, AX            ; ES has the shr seg paragraph
  661.     mov    AL, ES:[BX]        ; AL has the status byte
  662. ;    test    AL, SMK_PRX        ; if rx good
  663.     test    al,1
  664.     jnz    readit
  665.     jmp    fd_bnry            ; rx error, drop frm by forward bnry
  666. readit:
  667. ;
  668. ;  set up to read the next packet from the net
  669. ;
  670. ;
  671. ;  get ready for next packet
  672. ;
  673.     cld            ; moves in fwd dir
  674. ;
  675. ;  check for buffer overrun or catching up with reader
  676. ;
  677. ;  implicit 64K max buffer, should stop before 64K anyway
  678. ;
  679. ifdef    Microsoft
  680.     MOV    AX,_BUFBIG    ; how much stuff is in buffer
  681.     MOV    BX,_BUFLIM    ; what is our size limit?
  682. else
  683.     MOV    AX,BUFBIG    ; how much stuff is in buffer
  684.     MOV    BX,BUFLIM    ; what is our size limit?
  685. endif
  686.     CMP    AX,BX
  687.     JNA    ISROOM        ; we are ok
  688. ;
  689. ;  no room at the Inn. 
  690. ;
  691.     JMP SHORT fd_bnry     ; can't do much, we lose packets until restarted
  692.  
  693. ;
  694. ;  wrap pointer around at end, we know that we have room
  695. ;
  696. ISROOM:
  697. ifdef    Microsoft
  698.     MOV    DI,word ptr [_BUFPT]     ; where buffer is
  699.     MOV    DX,word ptr [_BUFEND]    ; right before 2K safety area
  700. else
  701.     MOV    DI,word ptr [BUFPT]     ; where buffer is
  702.     MOV    DX,word ptr [BUFEND]    ; right before 2K safety area
  703. endif
  704.  
  705.     CMP    DX,DI            ; see if pointer is over limit
  706.     JA    OKAYREAD        ; we are not at wrap-around
  707.  
  708. ifdef    Microsoft
  709.     MOV    AX,word ptr [_BUFORG]    ; wrap to here
  710.     MOV    word ptr [_BUFPT],AX    ; wrap-around
  711. else
  712.     MOV    AX,word ptr [BUFORG]    ; wrap to here
  713.     MOV    word ptr [BUFPT],AX    ; wrap-around
  714. endif
  715.     MOV    DI,AX            ; di also
  716.  
  717. OKAYREAD:
  718. ;
  719. ;
  720. ;  start the copy of the new packet
  721. ;  pointer to the shared memory offset is in BX
  722. ;  At this offset, you will find:
  723. ;    1 byte - read status, usually 21h
  724. ;    1 byte - pointer, page # of next packet
  725. ;    2 bytes - length of data in packet, swapped for you already
  726. ;    n bytes - that many bytes of Ethernet packet spread
  727. ;       over n div 256 pages (allowing four lost bytes in first packet)
  728. ;
  729. ;
  730.     pop    si        ; get packet pointer back into si
  731.     push    si        ; restore for fd_bnry to read
  732. ;
  733. ;  save regs while moving packet to buffer
  734. ;  set up ds for buffer, even though we switch it later
  735. ;
  736.     push    es
  737.     push    ds
  738. ifdef    Microsoft
  739.     MOV    AX,word ptr [_BUFPT+2]    ; buffer's ds
  740. else
  741.     MOV    AX,word ptr [BUFPT+2]    ; buffer's ds
  742. endif
  743.     mov    ds,ax
  744. ;
  745. ;  here, DS:DI contains where we want to put the packet.
  746. ;
  747. newpkt:
  748.     add    si,2        ; offset for length field
  749.     mov    dx,es:[si]    ; value of length of recd packet
  750.  
  751.     mov    [di],dx        ; put the accumulated size there
  752.     inc    si
  753.     inc    si
  754.     inc    di
  755.     inc    di        ; now it is the data pointer
  756. ;
  757. ;
  758. ;  Actually move the data
  759. ;    DX has packet size in bytes
  760. ;    ES:SI has the source pointer  } need to switch
  761. ;    DS:DI has the dest pointer    } es and ds
  762. ;    Remember, 256 byte pages wrap around at STOP_PG and there
  763. ;    are max 252 bytes in the first page
  764. ;
  765.     mov    cx,dx
  766.     cmp    cx,252
  767.     jng    shrt
  768.     mov    cx,252        ; first page len
  769. shrt:
  770.     mov    ax,ds
  771.     mov    bx,es
  772.     mov    ds,bx
  773.     mov    es,ax        ; swap them
  774.  
  775.     mov    bx,dx        ; save a copy of data length
  776.  
  777. mvpg:                ; start of page move loop
  778.     sub    dx,cx
  779.     shr    cx,1        ; convert to words
  780.     jnc    iseven
  781.     movsb            ; move odd one if needed
  782. iseven:
  783.     rep    movsw        ; move all words in one page
  784.  
  785.     cmp    dx,0        ; how many left to move?
  786.     jng    donepg
  787.     mov    cx,dx
  788.     cmp    cx,256
  789.     jng    shrtr
  790.     mov    cx,256        ; one more page
  791. shrtr:
  792.     mov    ax,si        ; look at source page
  793.     cmp    ah,STOP_PG
  794.     jl    mvpg
  795.     mov    ah,STRT_PG    ; wrap around at this page boundary
  796.     mov    si,ax        ; put back in si for rest of packet
  797.     jmp    mvpg
  798.  
  799. donepg:
  800.  
  801.     pop    ds
  802.     pop    es        ; put regs back so ES is shared mem
  803.  
  804. ;
  805. ; update the pointer and length in the buffer
  806. ;  DI already points just past end of data just placed there
  807. ;
  808. ifdef    Microsoft
  809.     MOV    word ptr [_BUFPT],di    ; it is here, now
  810.     MOV    AX,word ptr [_BUFBIG]    ; total amount of stuff in buffer
  811. else
  812.     MOV    word ptr [BUFPT],di    ; it is here, now
  813.     MOV    AX,word ptr [BUFBIG]    ; total amount of stuff in buffer
  814. endif
  815.     ADD    AX,BX        ; add in size of this packet
  816.     INC    AX
  817.     INC    AX        ; to cover the length value
  818. ifdef    Microsoft
  819.     MOV    word ptr [_BUFBIG],AX    ; after adding in current packet size
  820. else
  821.     MOV    word ptr [BUFBIG],AX    ; after adding in current packet size
  822. endif
  823. ;
  824. ;
  825. ;  signs that something is actually happening
  826. ;
  827. ;    push    es
  828. ;    MOV    AX,0B000H       ; screen
  829. ;    MOV    ES,AX
  830. ;    MOV    DI,3998        ; lower right corner
  831. ;    INC    cs:ICNT
  832. ;    MOV    al,cs:ICNT    ; character
  833. ;    STOSB
  834. ;    pop    es
  835. ;
  836.  
  837.  
  838. ; drop bad frame by forwarding the BNRY register
  839. ;  or just normal BNRY update after frame read
  840. ;
  841. fd_bnry:                ; drop frm by forward BNRY
  842.     pop    BX            ; restore frm ptr in BX
  843.     add    BX, 1
  844.     mov    AL, ES:[BX]        ; next frm start page in AL
  845.     sub    AL, 1            ; new BNRY in AL
  846.     cmp    AL, STRT_PG        ; check boundary
  847.     jge    wrbnry
  848.     mov    AL, STOP_PG - 1
  849. wrbnry:
  850.     wr_wd8    BNRY
  851.  
  852. end_rx:
  853.     pop    es
  854.     POP    BP
  855.  
  856.     RET            ; for compatibility with other drivers
  857. ICNT    db    0
  858. ifdef    Microsoft
  859. _E4RECV    ENDP
  860. else
  861. E4RECV    ENDP
  862. endif
  863.  
  864. ;
  865. ;************************************************************************
  866. ;  XMIT         
  867. ;     send a packet to Ethernet
  868. ;     Is not interrupt driven, just call it when you need it.
  869. ;
  870. ;  usage:   xmit(packet,count)
  871. ;        char *packet;
  872. ;        int count;
  873. ;
  874. ;   Takes a packet raw, Ethernet packets start with destination address,
  875. ;   and puts it out onto the wire.  Count is the length of packet < 2048
  876. ;
  877. ;   checks for packets under the Ethernet size limit of 60 and handles them
  878. ;
  879. ifdef    Microsoft
  880. _E4XMIT    PROC    FAR
  881. else
  882. E4XMIT    PROC    FAR
  883. endif
  884.  
  885.     PUSH    BP
  886.     MOV    BP,SP
  887.     push    es
  888.     PUSH    DS        ; set up proper ds for the buffer
  889. ;
  890. ;    ok, let's hangout here waiting for the transmitter
  891. ;
  892.     mov    bx,8000h    ; adequate timeout
  893. twait:    rd_wd8    CMDR        ; read up the command reg
  894.     and    al,04h        ; xmit flag
  895.     jz        tfree
  896.     dec    bx
  897.     jnz    twait        ; keep going till timeout
  898.     mov    ax,-1        ; bummer, it hates me
  899.     pop    ds
  900.     pop    es
  901.     pop    bp
  902.     ret
  903. tfree:
  904.     cld
  905. ;
  906.     mov    al,0c9h
  907.     wr_wd8    GACFR
  908. ;
  909.     mov    ax,WDADD    ; shared memory address in ax
  910.     mov    es,ax        ; use es for this
  911. ;
  912. ;  move packet into position, set up regs
  913. ;
  914.     MOV    AX,[BP+X+2]    ; get data ds
  915.     MOV    DS,AX
  916.     MOV    SI,[BP+X]    ; DS:SI points to data buffer
  917.  
  918.     MOV        CX,[BP+X+4]    ; count of bytes
  919.     CMP    CX,60        ; minimum length for Ether
  920.     JNB    OKLEN
  921.     MOV    CX,60        ; make sure size at least 60
  922. OKLEN:
  923. ;
  924. ;  Copy Packet : 
  925. ;
  926. ;    DS:SI = real data
  927. ;    ES    = shared memory address
  928. ;    CX    = number of bytes
  929. ;
  930.     mov    al,0c9h        ; reset the gate array
  931.     wr_wd8    GACFR
  932. ;
  933.     push    cx        ; save xmit length
  934.     xor    ax,ax
  935.     mov    ah,TSTRT_PG    ; starting page number
  936.     mov    di,ax        ; ES:DI = shared mem buff start
  937.     shr    cx,1        ; gonna do 16 bits
  938.     jnc    evenx
  939.     movsb            ; pick up odd byte
  940. evenx:
  941.     rep    movsw        ; copy all data into xmit buf
  942. ;
  943.     mov    al,0
  944.     wr_wd8    TCR
  945. ;
  946. ;  set up xmit length registers
  947. ;
  948.     pop    cx        ; len restored in cx
  949.     pop    ds
  950.     mov    al,cl        ; length
  951.     wr_wd8    TBCR0            ; lower byte to TBCR0
  952.     mov    al,ch
  953.     wr_wd8    TBCR1            ; higher byte to TBCR1
  954. ;
  955. ; set page number
  956. ;
  957.     mov    al,TSTRT_PG
  958.     wr_wd8    TPSR            ; write start page into TPSR
  959. ;
  960. ; issue tx command
  961. ;
  962.     mov    al,24h
  963.     wr_wd8    CMDR            ; start xmit
  964. ;
  965. ;  check to see if the last packet xmitted ok
  966. ;
  967.     xor    cx,cx            ; set a timeout
  968. ;
  969. waitxmit:
  970. ;
  971.     rd_wd8    CMDR        ; command register
  972.     and    al,4        ; xmit bit
  973.     jz    oktogo        ; xmit is finished
  974.     loop    waitxmit    ; waiting for xmit to complete
  975.     mov    ax,-1
  976.     jmp SHORT getout
  977. oktogo:
  978.     xor    ax,ax
  979. ;
  980. ; go back for more
  981. ;
  982. getout:
  983.     pop    es
  984.     POP    BP
  985.     RET
  986. ifdef    Microsoft
  987. _E4XMIT    ENDP
  988. else
  989. E4XMIT    ENDP
  990. endif
  991.  
  992. ;
  993. ;
  994. ;*************************************************************************
  995. ;  ETUPDATE
  996. ;      update pointers and/or restart receiver when read routine has
  997. ;      already removed the current packet
  998. ;
  999. ;   usage:  etupdate();
  1000. ;
  1001. ifdef    Microsoft
  1002. _E4ETUPDATE    PROC    FAR
  1003. else
  1004. E4ETUPDATE    PROC    FAR
  1005. endif
  1006.  
  1007.     PUSH     ES
  1008. ifdef    Microsoft
  1009.     MOV    AX,word ptr [_BUFPT+2]    ; establish data segment to buffer
  1010. else
  1011.     MOV    AX,word ptr [BUFPT+2]    ; establish data segment to buffer
  1012. endif
  1013.     MOV    ES,AX        ; put that in es
  1014. ;
  1015. ifdef    Microsoft
  1016.     MOV    BX,_BUFREAD    ; where read pointer is now
  1017. else
  1018.     MOV    BX,BUFREAD    ; where read pointer is now
  1019. endif
  1020.     MOV    DX,ES:[BX]    ; get size of this packet
  1021.     INC    DX
  1022.     INC    DX        ; two more for length value
  1023.  
  1024.     ADD    BX,DX        ; increment bufread by size of packet
  1025.  
  1026. ifdef    Microsoft
  1027.     MOV    CX,_BUFEND    ; right before 2K safety area
  1028. else
  1029.     MOV    CX,BUFEND    ; right before 2K safety area
  1030. endif
  1031.     CMP    BX,CX        ; see if pointer is over limit
  1032.     JB    NOWRAPRD    ; we are not at wrap-around
  1033.  
  1034. ifdef    Microsoft    
  1035.     MOV    BX,_BUFORG    ; wrap to here
  1036. NOWRAPRD:
  1037.     MOV    _BUFREAD,BX    ; buffer pointer has been updated
  1038. else
  1039.     MOV    BX,BUFORG    ; wrap to here
  1040. NOWRAPRD:
  1041.     MOV    BUFREAD,BX    ; buffer pointer has been updated
  1042. endif
  1043.  
  1044. ;
  1045. ;  DECREMENT TOTAL BUFFER SIZE
  1046. ;
  1047.     CLI            ; keep interrupt handler from bothering dec
  1048. ifdef    Microsoft
  1049.     MOV    CX,_BUFBIG    ; size before removing packet
  1050.     SUB    CX,DX        ; remove size of current packet
  1051.     MOV    _BUFBIG,CX    ; put it back
  1052. else
  1053.     MOV    CX,BUFBIG    ; size before removing packet
  1054.     SUB    CX,DX        ; remove size of current packet
  1055.     MOV    BUFBIG,CX    ; put it back
  1056. endif
  1057.     STI
  1058. ;
  1059. ;  IF RECEIVER IS ON, THEN CHECKING BUFLIM IS UNNECESSARY.
  1060. ;
  1061.     MOV    AL,DEAF        ; is the receiver turned off?
  1062.     OR    AL,AL        ; 0 = reading, 1 = deaf
  1063.     JZ    ALIVE
  1064. ;
  1065. ;  CHECK FOR ROOM IN THE BUFFER, IF THERE IS, TURN ON RECEIVER
  1066. ;
  1067. ifdef    Microsoft
  1068.     MOV    AX,_BUFLIM    ; what is our limit?
  1069. else
  1070.     MOV    AX,BUFLIM    ; what is our limit?
  1071. endif
  1072.     CMP    CX,AX        ; compare to limit
  1073.     JA    ALIVE        ; not really alive, but can't turn on yet
  1074.  
  1075.     XOR    AL,AL
  1076.     MOV    DEAF,AL        ; reset flag
  1077.  
  1078.     INC    OFFS        ; keep count how many times this happened
  1079.  
  1080. ;
  1081. ;  turn receiver back on
  1082. ;
  1083.  
  1084. ALIVE:
  1085.     POP    ES
  1086.     RET    
  1087.  
  1088. ifdef    Microsoft
  1089. _E4ETUPDATE    ENDP
  1090. else
  1091. E4ETUPDATE    ENDP
  1092. endif
  1093.  
  1094. ifdef Microsoft
  1095. ;_TEXT    ends
  1096. else
  1097.     ENDPS
  1098. endif
  1099.     END
  1100.