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