home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / NCSATELN / TEL23SRC.ZIP / NET / ENET / NET523.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-05-15  |  25.0 KB  |  1,035 lines

  1. ;  3COM 3C523 driver code
  2. ;  Tim Krauskopf
  3. ;****************************************************************************
  4. ;*                                                                          *
  5. ;*                                                                          *
  6. ;*      part of NCSA Telnet                                                 *
  7. ;*      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  8. ;*                                                                          *
  9. ;*      National Center for Supercomputing Applications                     *
  10. ;*      152 Computing Applications Building                                 *
  11. ;*      605 E. Springfield Ave.                                             *
  12. ;*      Champaign, IL  61820                                                *
  13. ;*                                                                          *
  14. ;*                                                                          *
  15. ;****************************************************************************
  16. ;
  17.  
  18.     TITLE    NETSUPPORT -- LOW LEVEL DRIVERS FOR ETHERNET
  19. ;
  20. ;  Assembler support for Ethernet I/O on the PC
  21. ;
  22. ;  Tim Krauskopf
  23. ;  9/1/87  Ungermann-Bass driver started, PC bus
  24. ;  9/14/87 MICOM NI5210 driver started, PC bus
  25. ;  4/22/88 3COM 3C523 driver adapted from MICOM 82586 driver, MCA bus
  26. ;
  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.     NAME    MNET
  43. ifdef Microsoft
  44. X    EQU    6
  45.     DOSSEG
  46.     .MODEL    LARGE
  47. else
  48.     INCLUDE    DOS.MAC
  49.     SETX
  50. endif
  51.  
  52. ;
  53. ;  CA macro
  54. ;
  55. DOCA    MACRO    FLGS
  56.     mov    dx,IOADDR
  57.     add    dx,IOC
  58.     mov    al,FLGS+CA
  59.     out    dx,al
  60.     mov    al,FLGS
  61.     jmp    $+2
  62.     jmp    $+2
  63.     jmp    $+2
  64.     out    dx,al
  65.     ENDM
  66. ;
  67. ;  Equates for controlling the 3c523 board
  68. ;
  69. ;  I/O addresses, seventh address controls everything
  70. ;
  71. ;  First six addresses are the EPROM board Ether address (read)
  72. ;
  73. IOC    EQU    6
  74. ;
  75. ;  Register bits
  76. ;
  77. GO    EQU    83h        ; no reset plus bank select
  78. CA    EQU    40h        ; CA bit
  79. LBK    EQU    20h        ; loopback bit
  80. ZRAM    EQU    03h        ; memory bank enable
  81. ;
  82. ;  other bits are interrupts, not needed
  83. ;
  84.  
  85. ;
  86. ;  Structure elements specific to the Intel 82586 chip
  87. ;
  88. BDBASE    EQU    1874+0c000h        ; base address for 30 buffer descriptors
  89. BUFBASE    EQU    2174+0c000h        ; base address for 30 200 byte buffers
  90. BDSTAT    EQU    0        ; status word in BD
  91. BDLINK    EQU    2        ; 16pointer to next BD
  92. BDPTR    EQU    4        ; 24pointer to actual buffer
  93. BDSIZE    EQU    8        ; size of the buffer
  94. ;
  95. SCB    EQU    10+0c000h        ; system control block base
  96. SSTAT    EQU    0        ; status word for SCB
  97. SCOM    EQU    2        ; command word in SCB
  98. SCBL    EQU    4        ; 16pointer to command block list
  99. SRFA    EQU    6        ; 16pointer to receive frame list
  100. SERRS    EQU    8        ; 4 words of error counts
  101. ;
  102. FDBASE    EQU    1214+0c000h        ; base addr for 30 frame descriptors
  103. FDSTAT    EQU    0        ; status word for frame
  104. FDEOL    EQU    2        ; end of FD list flag
  105. FDLINK    EQU    4        ; 16pointer to next FD
  106. FDPTR    EQU    6        ; 16pointer to list of BD's
  107. ;
  108. TSTAT    EQU    0        ; status word for xmit
  109. TCOM    EQU    2        ; command to transmit
  110. TLINK    EQU    4        ; 16pointer to next command (always ffff)
  111. TPTR    EQU    6        ; 16pointer to xmit TBD
  112. TTRIES    EQU    8        ; number of transmit retries
  113. ;
  114. SCPTR    EQU    03ff6h+0c000h        ; hardwired address for SCP
  115. ISCPTR    EQU    03feeh+0c000h        ; my address for ISCP, points to SCB
  116. CCBPTR    EQU    26+0c000h        ; offset of configure command block
  117. TCBPTR    EQU    44+0c000h        ; xmit CB offset
  118. TBDPTR    EQU    60+0c000h        ; xmit BD offset
  119. TBUFPTR    EQU    68+0c000h        ; xmit buffer offset
  120. ;
  121. ;  Data segment
  122. ;
  123. ifdef Microsoft
  124. ;DGROUP    group    _DATA
  125. ;_DATA    segment    public 'DATA'
  126. ;    assume    DS:DGROUP
  127.     .data
  128. else
  129.     DSEG
  130. endif
  131. ;
  132. ;  The pointers below are actually DWORDs but we access them two
  133. ;  bytes at a time.
  134. ;
  135. ; STAT change to RSTAT because of name clash with MSC library routine
  136. ifdef Microsoft
  137.     EXTRN    _RSTAT:BYTE    ; last status from read
  138.     EXTRN    _BUFPT:WORD    ; current buffer pointer
  139.     EXTRN    _BUFORG:WORD    ; pointer to beginning of buffer
  140.     EXTRN    _BUFEND:WORD    ; pointer to end of buffer
  141.     EXTRN    _BUFREAD:WORD    ; pointer to where program is reading
  142.     EXTRN    _BUFBIG:WORD    ; integer, how many bytes we have
  143.     EXTRN    _BUFLIM:WORD    ; integer, max bytes we can have
  144. else
  145.     EXTRN    RSTAT:BYTE    ; last status from read
  146.     EXTRN    BUFPT:WORD    ; current buffer pointer
  147.     EXTRN    BUFORG:WORD    ; pointer to beginning of buffer
  148.     EXTRN    BUFEND:WORD    ; pointer to end of buffer
  149.     EXTRN    BUFREAD:WORD    ; pointer to where program is reading
  150.     EXTRN    BUFBIG:WORD    ; integer, how many bytes we have
  151.     EXTRN    BUFLIM:WORD    ; integer, max bytes we can have
  152. endif
  153.  
  154.  
  155. ICNT    DB    00h
  156.  
  157. SAVECS    DW    00H        ; where to save the old interrupt ptr
  158. SAVEIP    DW    00H
  159. LFPP    DB    00h        ; Full Page pointer
  160. DEAF    DB    00H        ; when we can't handle any more packets
  161. OFFS    DW    00H        ; how many times the handler was turned off
  162. FIRSTFD    dw    FDBASE        ; start of FD queue
  163. LASTFD    DW    0        ; end of the FD chain
  164. LASTBD    DW    0        ; end of the BD chain
  165. IOADDR    DW    02300h        ; I/O address for card (POS set)
  166. UBASE    DW      0bc00h        ; base segment for board (POS set)
  167. ;
  168. ;  data for configuring and setting up the MICOM board
  169. ;
  170. ;  chip always looks at SCP for config info which points to ISCP for the
  171. ;  pointer to the CONTROL BLOCK which handles everything from there.
  172. ;  Kind of indirect, but it works.
  173. ;
  174. SCP    DB    0        ; bus use flag
  175.     DB    5 DUP(0)    ; unused
  176.     DW    ISCPTR        ; 24pointer to ISCP offset
  177.     DW    0        ; high part
  178. ;
  179. ; Intermediate SCP
  180. ;
  181. ISCP    DW    1        ; busy flag
  182.     DW    SCB        ; 16pointer to SCB
  183.     DW    0,0        ; base for all 16 pointers, lo, hi
  184.                 ; board is hardwired to 0 for these values
  185. ;
  186. ; Configuration block for 82586, this comprises one config command
  187. ;  Parameters taken from MICOM driver
  188. ;
  189. CBCONF    DW    0        ; status word
  190.     DW    8002H        ; end of command list + configure command
  191.     DW    0ffffh        ; link to next command (not used)
  192.     DW    080CH        ; fifo=8, byte count=C
  193.     DW    2E00H        ; important! Addr (AL) not inserted on the fly!
  194.     DW    6000H        ; IFS = 60h
  195.     DW    0F200H        ; retry=F, slot time=200h
  196.     DW    0        ; flags, set to 1 for promiscuous
  197.     DW    40H        ; min frame length=40h
  198. ;
  199. ; CB for xmit, followed by BD for xmit, copied together
  200. ;
  201. TCB    DW    0        ; status word
  202.     DW    08004H        ; command word for xmit + EL
  203.     DW    0ffffh        ; no command link
  204.     DW    TBDPTR        ; 16pointer to xmit BD
  205.     DW    0,0,0,0        ; no addressing used here
  206. ;
  207. ; BD template for xmit
  208. TBD    DW    0
  209.     DW    0        ; next BD pointer, unused
  210.     DW    TBUFPTR        ; 24pointer to xmit buffer
  211.     DW    0        ; high part of pointer
  212.  
  213. ifdef Microsoft
  214. ;_DATA    ends
  215. else
  216.     ENDDS
  217. endif
  218. ;
  219. ;
  220. ;
  221. ;   The subroutines to call from C
  222. ;
  223. ifdef Microsoft
  224. ;_TEXT    segment    public    'CODE'
  225. ;    assume CS:_TEXT
  226.     .code
  227.     PUBLIC    _E2RECV,_E2ETOPEN,_E2ETCLOSE,_E2GETADDR
  228.     PUBLIC    _E2XMIT,_E2ETUPDATE
  229. else
  230.     PSEG
  231.     PUBLIC    E2RECV,E2ETOPEN,E2ETCLOSE,E2GETADDR
  232.     PUBLIC    E2XMIT,E2ETUPDATE
  233. endif
  234.  
  235. ;******************************************************************
  236. ;  ETOPEN
  237. ;     Initialize the Ethernet board, set receive type.
  238. ;
  239. ;  usage:  etopen(s,irq,address,ioaddr)
  240. ;           char s[6];       ethernet address
  241. ;           int irq;         (unused, we don't use no interrupts)
  242. ;           int address         base mem address
  243. ;           int ioaddr       io base address
  244. ;
  245. ifdef Microsoft
  246. _E2ETOPEN    PROC    FAR
  247. else
  248. E2ETOPEN    PROC    FAR
  249. endif
  250.     PUSH    BP
  251.     MOV    BP,SP
  252.     PUSH    SI
  253.     PUSH    DI
  254.     push    es
  255.     mov    ax,[bp+X+6]    ; second parameter
  256.     sub    ax,0c00h    ; set back to match 82586 addressing
  257.     mov    UBASE,ax    ; base address
  258. ;    mov    ax,UBASE    ; get a copy (temporary)
  259.     mov    es,ax        ; set to base address
  260.     mov    ax,[bp+X+8]    ; get I/O address
  261.     mov    IOADDR,ax    ; save a copy
  262. ;    mov    ax,IOADDR    ; get a copy (temporary)
  263. ;
  264. ;  Set the POS bit for card enable?
  265. ;  The section which hasn't been written here should query the POS,
  266. ;  set the card enable bit, and look up the base and ioaddrs so that
  267. ;  the user won't have to install them in the configuration file.
  268. ;  That's why we have PS/2s - but I got lazy (tk)
  269. ;
  270.  
  271. ;
  272. ;  Bank select, so that the memory will be available
  273. ;  Bit settings also leave interrupts off, don't need them
  274. ;
  275.     mov    dx,ax        ; IO reg base
  276.     add    dx,IOC        ; control register
  277.     mov    al,23h        ; reset, plus enable bank 3, plus LBK
  278.     out    dx,al
  279.  
  280. ;
  281. ;  Initialize 82586
  282. ;
  283.     DOCA    ZRAM+LBK    ; hit the board with a reset
  284. ;
  285. ;  Install 16K SCP
  286. ;
  287. nop
  288. nop
  289. nop
  290.     mov    si,offset SCP    ; get pre-set values
  291.     mov    di,SCPTR        ; offset for 16K board
  292.     mov    cx,5        ; 5 words
  293.     rep    movsw        ; install SCP
  294. ;
  295. ;  Intermediate SCP
  296. ;
  297.     mov    si,offset ISCP    ; addr of pre-set values
  298.     mov    di,ISCPTR
  299.     mov    cx,4        ; 4 words
  300.     rep    movsw        ; install ISCP
  301.  
  302. ;
  303. ;  configure 82586
  304. ;
  305.     mov    si,offset CBCONF    ; configure command
  306.     mov    di,CCBPTR        ; where command will reside
  307.     mov    cx,9
  308.     rep    movsw            ; copy to board
  309. ;
  310. ;  issue the configure command
  311. ;
  312.     mov    ax,word ptr es:[SCB+SSTAT]    ; get old status
  313.     and    ax,0f000h
  314.     or    ax,0100h
  315.     mov    word ptr es:[SCB+SCOM],ax    ; do-command command
  316.     mov    word ptr es:[SCB+SSTAT],0    ; status word
  317.     mov    word ptr es:[CCBPTR],0        ; status word
  318.     mov    word ptr es:[SCB+SCBL],CCBPTR    ; where conf command is
  319.     mov    word ptr es:[SCB+SERRS],0    ; zero errs field
  320.     mov    word ptr es:[SCB+SERRS+2],0    ; zero errs field
  321.     mov    word ptr es:[SCB+SERRS+4],0    ; zero errs field
  322.     mov    word ptr es:[SCB+SERRS+6],0    ; zero errs field
  323.  
  324.     DOCA    LBK+GO            ; kick CA
  325.     DOCA    LBK+GO            ; kick CA
  326.  
  327.     xor    cx,cx            ; timeout
  328. waitconf:
  329.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  330.     test    ax,08000h
  331.     loopz    waitconf
  332.     jnz    confok
  333.     mov    ax,-1            ; timeout problem
  334.     pop    es
  335.     POP    DI
  336.     POP    SI
  337.     pop    bp
  338.     ret
  339. ;
  340. confok:
  341.     and    ax,0f000h        ; ack flags
  342.     mov    word ptr es:[SCB+SCOM],ax    ; ack bits
  343.  
  344.     DOCA    LBK+GO
  345.  
  346.     xor    cx,cx            ; timeout
  347. waitcack:
  348.     mov    ax,word ptr es:[SCB+SCOM]    ; get command word
  349.     or    ax,ax
  350.     loopnz    waitcack
  351.     jz    cackok
  352.     mov    ax,-1            ; timeout problem
  353.     pop    es
  354.     POP    DI
  355.     POP    SI
  356.     pop    bp
  357.     ret
  358. ;
  359. cackok:
  360.     
  361. ;
  362. ;  Next step, load our address into the board
  363. ;     reuses the space that the configure command used, with different command 
  364. ;
  365.     mov    di,CCBPTR        ; start of config command block
  366.     xor    ax,ax
  367.     stosw                ; zero status word for commmand
  368.     mov    ax,8001h        ; IA setup command + EL
  369.     stosw
  370.     xor    ax,ax
  371.     dec    ax
  372.     stosw                ; set link value to -1 (unused)
  373.  
  374. ;  move my addr onto board location inside IA command
  375. ;  es:di is already set
  376. ;
  377.     PUSH     DS        ; save my DS
  378.     MOV    AX,[BP+X+2]    ; get new one
  379.     MOV    DS,AX           ; set new one
  380.     MOV    SI,[BP+X]    ; get pointer, ds:si is ready
  381.     ;
  382.     movsw
  383.     movsw
  384.     movsw
  385.     POP    DS        ; get back DS of local data
  386. ;
  387. ;  start the IA setup command, 
  388. ;
  389.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  390.     mov    word ptr es:[SCB+SSTAT],0    ; clear status
  391.  
  392.     DOCA    LBK+GO            ; kick CA, with loopback
  393.  
  394.     xor    cx,cx            ; timeout
  395. waitia:
  396.     mov    ax,word ptr es:[SCB+SSTAT]    ; get status word
  397.     or    ax,ax
  398.     loopz    waitia
  399.     jnz    iaok
  400.     mov    ax,-2            ; timeout problem
  401.     pop    es
  402.     POP    DI
  403.     POP    SI
  404.     pop    bp
  405.     ret
  406. ;
  407. iaok:
  408.     and    ax,0f000h        ; ack flags
  409.     mov    word ptr es:[SCB+SCOM],ax    ; ack bits
  410.  
  411.     DOCA    LBK+GO
  412.  
  413.     xor    cx,cx            ; timeout
  414. waitiack:
  415.     mov    ax,word ptr es:[SCB+SCOM]    ; get command word
  416.     or    ax,ax
  417.     loopnz    waitiack
  418.     jz    iackok
  419.     mov    ax,-1            ; timeout problem
  420.     pop    es
  421.     POP    DI
  422.     POP    SI
  423.     pop    bp
  424.     ret
  425. ;
  426. iackok:
  427. ;
  428. ;  IA sent, setup all of the other data structures on the board
  429. ;  start with xmit command descriptors
  430. ;
  431.     mov    si,offset TCB        ; template for xmit
  432.     mov    di,TCBPTR        ; where it goes on board
  433.     mov    cx,12            ; copies CB and BD for xmit
  434.     rep    movsw
  435. ;
  436. ;  Set up frame and buffer descriptors, 30 each
  437. ;
  438.     mov    cx,30            ; # of FDs
  439.     mov    di,FDBASE        ; base addr for FDs
  440. fdloop:
  441.     xor    ax,ax
  442.     mov    bx,di            ; save pointer
  443.     stosw                ; clear status wd
  444.     stosw                ; clear EL field
  445.     add    bx,22            ; points to next one
  446.     mov    es:[di],bx        ; put in link ptr
  447.     inc    di
  448.     inc    di
  449.     dec    ax
  450.     stosw                ; clear BD ptr to -1
  451.     add    di,14
  452.     loop    fdloop
  453. ;
  454.     sub    di,20            ; point back to last EL field
  455.     mov    ax,08000h        ; end of list
  456.     stosw                ; put into last FD
  457.     sub    di,4            ; back to beginning of last FD
  458.     mov    LASTFD,di        ; save the pointer
  459.     mov    word ptr es:[di+FDLINK],FDBASE    ; make list circular, from last to first
  460.     
  461. ;
  462.     mov    ax,BDBASE        ; first BD
  463.     mov    word ptr es:[FDBASE+FDPTR],ax    ; put it in the first FD frame
  464. ;
  465. ;  now BDs
  466.     mov    cx,30
  467.     mov    di,BDBASE        ; start of BD area
  468.     mov    dx,BUFBASE        ; start of buffer area
  469. bdloop:
  470.     xor    ax,ax
  471.     mov    bx,di            ; save pointer
  472.     stosw                ; zero status field
  473.     add    bx,10            ; point to next record
  474.     mov    es:[di],bx        ; put in link ptr
  475.     inc    di
  476.     inc    di
  477.     mov    es:[di],dx        ; address of buffer, lo part
  478.     inc    di
  479.     inc    di
  480.     stosw                ; zero out high part
  481.     mov    ax,200
  482.     stosw                ; store length field    
  483.     add    dx,ax            ; add in length of buffer, updates ptr
  484.     loop    bdloop
  485. ;
  486.     sub    di,2            ; back to last BD size field
  487.     mov    ax,08000h+200        ; end of list + 200
  488.     stosw                ; mark end of list
  489.     sub    di,8            ; back to last BDLINK field
  490.     mov    ax,BDBASE
  491.     stosw                ; put link to beginning of list here
  492.     sub    di,4            ; back to beginning of last BD
  493.     mov    LASTBD,di        ; save pointer to end of list
  494. ;
  495. ;  minor detail, but important
  496. ;  Change SCB command block pointer to setup for xmit commands
  497. ;      = only commands needed when operational
  498. ;
  499.     mov    word ptr es:[SCB+SCBL],TCBPTR    ; where xmit command is
  500. ;
  501. ;  configure to connect to network
  502. ;
  503. ;    mov    dx,IOADDR
  504. ;    add    dx,IOC            ; enable network
  505. ;    mov    al,GO            ; network setting
  506. ;    out    dx,al            ;
  507. ;
  508. ;  Start the RU, doesn't need CB, only SCB parms.
  509. ;   command, to start receiving
  510. ;
  511.     mov    word ptr es:[SCB],0        ; clear status word
  512.     mov    word ptr es:[SCB+SRFA],FDBASE    ; set to frame descriptors
  513.     mov    word ptr es:[SCB+SCOM],010h    ; start RU
  514.  
  515.     DOCA    GO            ; kick CA
  516. ;
  517. ;  don't wait for response, we are done
  518. ;
  519.     xor    ax,ax
  520.     POP    ES
  521.     POP    DI
  522.     POP    SI
  523.     POP    BP
  524.     RET
  525. ifdef Microsoft
  526. _E2ETOPEN    ENDP
  527. else
  528. E2ETOPEN    ENDP
  529. endif
  530. ;
  531. ;
  532. ;*******************************************************************
  533. ;  GETADDR
  534. ;     get the Ethernet address off of the board
  535. ;
  536. ;   usage:  getaddr(s,address,ioaddr);
  537. ;    char s[6];           will get six bytes from the PROM
  538. ;
  539. ifdef Microsoft
  540. _E2GETADDR    PROC    FAR
  541. else
  542. E2GETADDR    PROC    FAR
  543. endif
  544.     PUSH    BP
  545.     MOV    BP,SP
  546.     PUSH    DI
  547.  
  548.     mov    dx,[BP+X+6]    ; get board's base io addr
  549.     PUSH     ES        ; save mine
  550.     MOV    AX,[BP+X+2]    ; get new one
  551.     MOV    ES,AX           ; set new one
  552.     MOV    DI,[BP+X]    ; get pointer, es:di is ready
  553.     ;
  554.     mov    cx,6
  555.     CLD
  556. getonee:
  557.     in    al,dx        ; get a byte of the EPROM address
  558.     STOSB            ; put it away
  559.     inc    dx        ; next register
  560.     loop getonee        ; go back for rest
  561.  
  562.     xor    ax,ax
  563.     POP     ES
  564.     POP    DI
  565.     POP    BP        
  566.     RET
  567. ifdef Microsoft
  568. _E2GETADDR    ENDP
  569. else
  570. E2GETADDR    ENDP
  571. endif
  572. ;
  573. ;***********************************************************************
  574. ;  ETCLOSE
  575. ;        shut it down if necessary
  576. ;        MICOM board never interrupts, so we can leave it running.
  577. ;        Who cares, right?
  578. ;
  579. ifdef Microsoft
  580. _E2ETCLOSE    PROC    FAR
  581.     RET
  582. _E2ETCLOSE    ENDP
  583. else
  584. E2ETCLOSE    PROC    FAR
  585.     RET
  586. E2ETCLOSE    ENDP
  587. endif
  588. ;
  589. ;
  590. ;************************************************************************
  591. ;  XMIT         
  592. ;     send a packet to Ethernet
  593. ;     Is not interrupt driven, just call it when you need it.
  594. ;
  595. ;  usage:   xmit(packet,count)
  596. ;        char *packet;
  597. ;        int count;
  598. ;
  599. ;   Takes a packet raw, Ethernet packets start with destination address,
  600. ;   and puts it out onto the wire.  Count is the length of packet < 2048
  601. ;
  602. ;   checks for packets under the Ethernet size limit of 60 and handles them
  603. ;
  604. ifdef Microsoft
  605. _E2XMIT    PROC    FAR
  606. else
  607. E2XMIT    PROC    FAR
  608. endif
  609.     PUSH    BP
  610.     MOV    BP,SP
  611.     PUSH    SI
  612.     PUSH    DI
  613.     push    es
  614.     mov    ax,ubase
  615.     mov    es,ax        ; base for board
  616.     PUSH    DS        ; set up proper ds for the buffer
  617.     MOV    AX,[BP+X+2]
  618.     MOV    DS,AX
  619.     MOV    SI,[BP+X]    ; offset for buffer
  620.  
  621.     MOV    DX,[BP+X+4]    ; count of bytes
  622.     MOV    CX,DX        ; save a copy, might be less than 60, ok
  623.  
  624.     CMP    DX,60        ; minimum length for Ether
  625.     JNB    OKLEN
  626.     MOV    DX,60        ; make sure size at least 60
  627. OKLEN:
  628.     mov    di,TBUFPTR    ; start of xmit buffer
  629.  
  630. ;
  631. ;  check for previous xmit
  632. xwait:
  633.     mov    bx,word ptr es:[SCB+SCOM]    ; is command zeroed yet?
  634.     or    bx,bx
  635.     jnz    xwait        ; not there yet, wait for it
  636. ;
  637. ;  move the data
  638.     rep    movsb        ; copy into buffer
  639. ;
  640. ;  put the correct size into the TDB
  641. ;
  642.     or    dx,08000h    ; end of frame bit flag
  643.     mov    word ptr es:[TBDPTR],dx        ; store it
  644.     mov    word ptr es:[TCBPTR],0        ; zero status wd
  645.     mov    word ptr es:[TCBPTR+TCOM],08004h; xmit command in TCB
  646.     mov    word ptr es:[SCB+SCOM],0100h    ; execute command
  647. ;    test    bx,0100h            ; suspended?
  648. ;    jz    nosus
  649. ;    mov    word ptr es:[SCB+SCOM],0400h    ; stop command
  650. ;nosus:
  651.     pop    ds            ; get back my ds
  652.  
  653.     DOCA    GO            ; kick CA
  654.  
  655.     xor     ax,ax
  656.     pop    es
  657.     POP    DI
  658.     POP    SI
  659.     POP    BP
  660.     RET
  661. ifdef Microsoft
  662. _E2XMIT    ENDP
  663. else
  664. E2XMIT    ENDP
  665. endif
  666. ;
  667. ;
  668. ;***********************************************************************
  669. ;   Receive
  670. ;   This is a CPU hook for boards that must be polled before we can
  671. ;   deliver packets into the receive buffer.  (i.e. no interrupts used)
  672. ;
  673. ;   The 3COM 3C501 version uses interrupts, so this routine is a NOP
  674. ;   for this board.
  675. ;
  676. ;    usage:  recv();
  677. ;
  678. ;
  679. ifdef Microsoft
  680. _E2RECV    proc    far
  681. else
  682. E2RECV    proc    far
  683. endif
  684.     push    bp
  685.     PUSH    SI
  686.     PUSH    DI
  687.     push    es
  688.  
  689. ifdef Microsoft
  690.     MOV    AX,word ptr [_BUFPT+2]    ; buffer's ds
  691.     MOV    DI,_BUFPT    ; where buffer is
  692. else
  693.     MOV    AX,word ptr [BUFPT+2]    ; buffer's ds
  694.     MOV    DI,BUFPT    ; where buffer is
  695. endif
  696.     MOV    ES,AX
  697.  
  698. ;
  699. ;  check for buffer overrun or catching up with reader
  700. ;
  701. ;  implicit 64K max buffer, should stop before 64K anyway
  702. ;
  703. ifdef Microsoft
  704.     MOV    AX,_BUFBIG    ; how much stuff is in buffer
  705.     MOV    BX,_BUFLIM    ; what is our size limit?
  706. else
  707.     MOV    AX,BUFBIG    ; how much stuff is in buffer
  708.     MOV    BX,BUFLIM    ; what is our size limit?
  709. endif
  710.     CMP    AX,BX
  711.     JNA    ISROOM        ; we are ok
  712. ;
  713. ;  no room at the Inn. 
  714. ;
  715.     JMP    ENDINT        ; can't do much, we lose packets until restarted
  716.  
  717. ;
  718. ;  wrap pointer around at end, we know that we have room
  719. ;
  720. ISROOM:
  721. ifdef Microsoft
  722.     MOV    DX,_BUFEND    ; right before 2K safety area
  723. else
  724.     MOV    DX,BUFEND    ; right before 2K safety area
  725. endif
  726.     CMP    DX,DI        ; see if pointer is over limit
  727.     JA    OKAYREAD    ; we are not at wrap-around
  728.  
  729. ifdef Microsoft
  730.     MOV    AX,_BUFORG    ; wrap to here
  731.     MOV    _BUFPT,AX    ; wrap-around
  732. else
  733.     MOV    AX,BUFORG    ; wrap to here
  734.     MOV    BUFPT,AX    ; wrap-around
  735. endif
  736.     MOV    DI,AX        ; di also
  737. ;
  738. ;  here, DI contains where we want to put the packet.
  739. ;  Add 2 to allow for space to put the size value
  740. ;
  741. OKAYREAD:
  742.     inc    di
  743.     inc    di        ; room for size word
  744.     mov    bx,FIRSTFD    ; get addr of first FD in list
  745.     mov    dx,ubase    ; base for board
  746.     push    ds
  747.     mov    ds,dx
  748. ;
  749. ;  
  750. CKFRAME:
  751.     mov    ax,[bx]        ; status word of frame
  752.     test    ax,08000h    ; frame written?
  753.     jnz    IREADONE    ; yes, read it in
  754.     pop    ds
  755.     call    rust        ; restore receiver if necessary
  756.     jmp    STOPINT
  757. ;
  758. ;  we have a frame, read it in
  759. ;
  760. IREADONE:
  761.     test    ax,02000h    ; check frame OK bit
  762.     jnz    frameok        ; ok, read it
  763.     mov    cx,ds
  764.     pop    ds
  765.     call    rust        ; preserves cx, restart RU if necessary
  766.     jmp SHORT freespace   ; not OK, just free the frame
  767.  
  768. frameok:
  769.     mov    si,[bx+FDPTR]    ; get pointer to buffer descriptor
  770.  
  771. copybuf:            ; es:di is already set to receive packet
  772.     mov    dx,si        ; save a copy of current BD ptr
  773.     mov    ax,[si]        ; get status and count word for BD
  774.     push    ax        ; save for EOF bit
  775.     test    ax,04000h    ; is count field there?
  776.     jnz    okcount
  777.     pop    ax    
  778.     mov    cx,ds
  779.     pop    ds
  780.     jmp SHORT freespace   ; free the frame, etc
  781. okcount:
  782.     xor    cx,cx
  783.     mov    cl,al        ; 200 bytes is largest this can be
  784.     mov    si,[si+BDPTR]    ; get offset of data
  785.     rep    movsb        ; copy the bytes from this packet segment
  786.     mov    si,dx        ; get back current BD ptr
  787.     pop    ax        ; get back EOF bit
  788.     test    ax,08000h    ; check bit
  789.     jnz    ptrupdate    ; free the frame, no more data here
  790.     mov    si,[si+BDLINK]    ; go to next BD in list
  791.     jmp    copybuf        ; copy the next buffer
  792. ;
  793. ;
  794. ptrupdate:
  795. ;
  796. ;  DI now contains updated value for BUFPT
  797. ;
  798.     mov    cx,ds        ; save board segment
  799.     pop    ds
  800. ifdef Microsoft
  801.     mov    bx,_BUFPT    ; get where size field for this packet goes
  802. else
  803.     mov    bx,BUFPT    ; get where size field for this packet goes
  804. endif
  805.     mov    ax,di        ; where pointer is now
  806.     sub    ax,bx        ; where is was then, difference is size
  807. ifdef Microsoft
  808.     MOV    DX,_BUFBIG    ; total amount of stuff in buffer
  809. else
  810.     MOV    DX,BUFBIG    ; total amount of stuff in buffer
  811. endif
  812.     ADD    DX,AX        ; add in size of this packet
  813. ifdef Microsoft
  814.     MOV    _BUFBIG,DX    ; after adding in current packet size
  815. else
  816.     MOV    BUFBIG,DX    ; after adding in current packet size
  817. endif
  818.  
  819.     dec    ax
  820.     dec    ax        ; account for length field
  821.     mov    ES:[bx],ax        ; put the accumulated size there
  822.  
  823. ifdef Microsoft
  824.     MOV    _BUFPT,DI    ; it is here, now
  825. else
  826.     MOV    BUFPT,DI    ; it is here, now
  827. endif
  828.  
  829. ;
  830. freespace:
  831. ;
  832. ;  we are done with the frame, do the list management
  833. ;    cx=DS for board  DS=DGROUP
  834. ;
  835.     mov    bx,FIRSTFD    ; the frame we are working with
  836.     mov    di,LASTBD    ; where end of BD list is now
  837.     mov    es,cx        ; reload board segment
  838.  
  839.     mov    si,es:[bx+FDPTR]    ; first BD in frame list
  840. nextbd:
  841.     mov    cx,es:[si]    ; count word for BD, EOF bit
  842.     test    cx,08000h    ; EOF bit, if set, save si in lastbd
  843.     jnz    dolastbd
  844.     mov    word ptr es:[si],0    ; clear status word, EOF bit
  845.     cmp    si,LASTBD        ; see if we are wrapping
  846.     jz    dolastbd        ; yes, just undo it
  847.     mov    si,es:[si+BDLINK]    ; follow link
  848.     jmp    nextbd
  849. dolastbd:
  850.     mov    LASTBD,si    ; store last known BD
  851.     mov    word ptr es:[si+BDSIZE],08000h+200    ; end of list here
  852.     mov    word ptr es:[si],0    ; clear status word, EOF bit
  853. ; size field for not end of list
  854.     mov    word ptr es:[di+BDSIZE],200    ; remove old end-of-list
  855.  
  856. ;
  857. ;  update the FD list flags, new end-of-list
  858. ;
  859.     mov    di,LASTFD    ; get old end-of-list
  860.     mov    word ptr es:[bx+FDEOL],08000h    ; store new EOL
  861.     mov    word ptr es:[bx],0        ; clear status word for frame
  862.     mov    word ptr es:[di+FDEOL],0    ; zero old one
  863.     mov    LASTFD,bx    ; update stored pointer
  864.     mov    si,es:[bx+FDLINK]        ; where next fd is
  865.     mov    FIRSTFD,si    ; store that info for next time
  866. ;    mov    bx,LASTBD    ; last of the BD list
  867. ;    mov    ax,es:[bx+BDLINK]        ; get link field from lastBD
  868. ;    mov    es:[si+FDPTR],ax        ; store into next frame
  869. ;
  870. ;  signs that something is actually happening - for debugging
  871. ;
  872. ;    MOV    AX,0B800H       ; screen
  873. ;    MOV    ES,AX
  874. ;    MOV    DI,3998        ; lower right corner
  875. ;    INC    ICNT
  876. ;    MOV    al,ICNT        ; character
  877. ;    STOSB
  878. ;
  879. ;
  880. ;  set up to read the next packet from the net
  881. ;
  882. STOPINT:
  883.  
  884. ENDINT:
  885.     pop    es
  886.     POP    DI
  887.     POP    SI
  888.     POP    BP
  889.     RET
  890. ifdef Microsoft
  891. _E2RECV    ENDP
  892. else
  893. E2RECV    ENDP
  894. endif
  895.  
  896. rust    proc    near        ; re-start receiver
  897. ;
  898. ;  check to see if the receiver went off because of no resources
  899. ;  and restart receiver if necessary
  900. ;  ds=dgroup, no other requirements
  901. ;
  902.     push    es
  903.     mov    ax,ubase
  904.     mov    es,ax
  905.     mov    ax,es:[SCB]    ; status word for SCB
  906.     and    ax,070h        ; receiver status
  907.     cmp    al,020h        ; receiver has no resources
  908.     jnz    hasres
  909. ;
  910. ;  setup lists for starting the RU on the chip
  911. ;  we know that there isn't anything in the buffer that we want
  912. ;
  913.     mov    bx,FIRSTFD    ; get first FD on free list (assume free)
  914.     mov    word ptr es:[SCB+SRFA],bx    ; put into SCB
  915.     mov    si,LASTBD    ; pointer to a BD, end of chain
  916.     mov    ax,word ptr es:[si+BDLINK]    ; pointer to next BD
  917.     mov    word ptr es:[bx+FDPTR],ax    ; set to start of BDs
  918. ;
  919. ;
  920. ;  Start the RU, doesn't need CB, only SCB parms.
  921. ;   command, to start receiving again
  922. ;
  923.     mov    word ptr es:[SCB],0        ; clear status word
  924.     mov    word ptr es:[SCB+SCOM],010h    ; start RU
  925.  
  926.     DOCA    GO
  927. hasres:
  928.     pop    es
  929.     ret    
  930. rust    endp
  931. ;
  932. ;*************************************************************************
  933. ;  ETUPDATE
  934. ;      update pointers and/or restart receiver when read routine has
  935. ;      already removed the current packet
  936. ;
  937. ifdef Microsoft
  938. _E2ETUPDATE    PROC    FAR
  939. else
  940. E2ETUPDATE    PROC    FAR
  941. endif
  942.     PUSH     ES
  943. ifdef Microsoft
  944.     MOV    AX,word ptr [_BUFPT+2]    ; establish data segment to buffer
  945. else
  946.     MOV    AX,word ptr [BUFPT+2]    ; establish data segment to buffer
  947. endif
  948.     MOV    ES,AX        ; put that in es
  949. ;
  950. ifdef Microsoft
  951.     MOV    BX,_BUFREAD    ; where read pointer is now
  952. else
  953.     MOV    BX,BUFREAD    ; where read pointer is now
  954. endif
  955.     MOV    DX,ES:[BX]    ; get size of this packet
  956.     INC    DX
  957.     INC    DX        ; TWO MORE FOR LENGTH VALUE
  958.  
  959.     ADD    BX,DX        ; increment bufread by size of packet
  960.  
  961. ifdef Microsoft
  962.     MOV    CX,_BUFEND    ; right before 2K safety area
  963. else
  964.     MOV    CX,BUFEND    ; right before 2K safety area
  965. endif
  966.     CMP    BX,CX        ; see if pointer is over limit
  967.     JB    NOWRAPRD    ; we are not at wrap-around
  968.     
  969. ifdef Microsoft
  970.     MOV    BX,_BUFORG    ; wrap to here
  971. else
  972.     MOV    BX,BUFORG    ; wrap to here
  973. endif
  974. NOWRAPRD:
  975. ifdef Microsoft
  976.     MOV    _BUFREAD,BX    ; buffer pointer has been updated
  977. else
  978.     MOV    BUFREAD,BX    ; buffer pointer has been updated
  979. endif
  980.  
  981. ;
  982. ;  DECREMENT TOTAL BUFFER SIZE
  983. ;
  984.     CLI            ; keep interrupt handler from bothering dec
  985. ifdef Microsoft
  986.     MOV    CX,_BUFBIG    ; size before removing packet
  987. else
  988.     MOV    CX,BUFBIG    ; size before removing packet
  989. endif
  990.     SUB    CX,DX        ; remove size of current packet
  991. ifdef Microsoft
  992.     MOV    _BUFBIG,CX    ; put it back
  993. else
  994.     MOV    BUFBIG,CX    ; put it back
  995. endif
  996.     STI
  997. ;
  998. ;  IF RECEIVER IS ON, THEN CHECKING BUFLIM IS UNNECESSARY.
  999. ;
  1000.     MOV    AL,DEAF        ; is the receiver turned off?
  1001.     OR    AL,AL        ; 0 = reading, 1 = deaf
  1002.     JZ    ALIVE
  1003. ;
  1004. ;  CHECK FOR ROOM IN THE BUFFER, IF THERE IS, TURN ON RECEIVER
  1005. ;
  1006. ifdef Microsoft
  1007.     MOV    AX,_BUFLIM    ; what is our limit?
  1008. else
  1009.     MOV    AX,BUFLIM    ; what is our limit?
  1010. endif
  1011.     CMP    CX,AX        ; compare to limit
  1012.     JA    ALIVE        ; not really alive, but can't turn on yet
  1013.  
  1014.     XOR    AL,AL
  1015.     MOV    DEAF,AL        ; reset flag
  1016.  
  1017.     INC    OFFS        ; keep count how many times this happened
  1018.  
  1019. ALIVE:
  1020.     POP    ES
  1021.     RET    
  1022. ifdef Microsoft
  1023. _E2ETUPDATE    ENDP
  1024. else
  1025. E2ETUPDATE    ENDP
  1026. endif
  1027.  
  1028.  
  1029. ifdef Microsoft
  1030. ;_TEXT    ends
  1031. else
  1032.     ENDPS
  1033. endif
  1034.     END
  1035.