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

  1. ;  3COM 3C501 driver code
  2. ;  Tim Krauskopf
  3. ;
  4. ;  This version is virtually unused, replaced by the driver version 
  5. ;  which handles all of the different ioaddrs and interrupts.
  6. ;
  7. ;****************************************************************************
  8. ;*                                                                          *
  9. ;*                                                                          *
  10. ;*      part of NCSA Telnet                                                 *
  11. ;*      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  12. ;*                                                                          *
  13. ;*      National Center for Supercomputing Applications                     *
  14. ;*      152 Computing Applications Building                                 *
  15. ;*      605 E. Springfield Ave.                                             *
  16. ;*      Champaign, IL  61820                                                *
  17. ;*                                                                          *
  18. ;*                                                                          *
  19. ;****************************************************************************
  20. ;
  21.  
  22.     TITLE    NETSUPPORT -- LOW LEVEL DRIVERS FOR ETHERNET
  23. ;
  24. ;  Assembler support for interrupt-driven Ethernet I/O on the PC
  25. ;
  26. ;  Will read and write packets from the 2K packet buffer on the
  27. ;  Etherlink card.  Provides hooks for higher layer protocols.
  28. ;
  29. ;Microsoft EQU 1
  30. ;Lattice EQU 1
  31. ifndef Microsoft
  32.     ifndef Lattice
  33.         if2
  34.             %out
  35.             %out ERROR: You have to specify "/DMicrosoft" OR "/DLattice" on the
  36.             %out        MASM command line to determine the type of assembly.
  37.             %out
  38.         endif
  39.         end
  40.     endif
  41. endif
  42.  
  43. ifdef Microsoft
  44. X    EQU    6
  45.     DOSSEG
  46.     .MODEL    LARGE
  47. else
  48.     INCLUDE    DOS.MAC
  49.     SETX
  50. endif
  51.     NAME    NET
  52. ;
  53. ;  Equates for controlling the 3COM board
  54. ;
  55. ICTRL    EQU    020H        ; 8259 interrupt control register
  56. IMASK    EQU    021H        ; 8259 interrupt mask register
  57. BASEA    EQU    300H        ; Base I/O address on PC I/O bus
  58. ENDOFI    EQU    020H        ; end-of-interrupt
  59. ;
  60. ;  Controller registers
  61. ;
  62. EADDR    EQU    BASEA+0H    ; Network address for hardware checking
  63. ;   takes six bytes, this is the address that the Ethernet board will
  64. ;   match to find packets on the net.  (0-5h)
  65. ;
  66. EREC    EQU    BASEA+6H    ; Receive status (read)
  67.                 ; Receive command (write)
  68. ESEND    EQU    BASEA+7H    ; Transmit status (read)
  69.                 ; Transmit command (write)
  70. EGLOW    EQU    BASEA+8H    ; General purpose pointer for R/W to 
  71.                 ; packet buffer, low byte
  72. EGHI    EQU    BASEA+9H    ; high byte, total of 11 bits for 2K buffer
  73. ERLOW    EQU    BASEA+0AH    ; Receive pointer, set by board (read) low byte
  74.                 ; Receive buffer pointer clear (write)
  75. ERHI    EQU    BASEA+0BH    ; high byte of Receive pointer
  76. EPROM    EQU    BASEA+0CH    ; PROM window address
  77.         ;     DH ??
  78. EAUX    EQU    BASEA+0EH    ; Auxiliary Status (read)
  79.                 ; Aux Command (write)
  80. EBUF    EQU    BASEA+0FH    ; Buffer window (where to I/O to net)
  81. ;
  82. ;  Transmit command options
  83. ;     what conditions we wish to be interrupted on after transmit
  84. ;
  85. EDTUNDER  EQU    01H        ; Detect underflow (bad CRC), not used
  86. EDTCOLL    EQU    02H        ; Detect collision on xmit
  87. EDTC16    EQU    04H        ; Detect 16 consecutive collisions (net down)
  88. EDTOK    EQU    08H        ; Detect successful transmission
  89.                 ; other 4 bits unused in this reg
  90. EXMITNORM  EQU    00H        ; Normal use for interrupt-driven XMIT
  91. ;
  92. ;  Transmit status results
  93. ;
  94. ;  Use same values as commands, 08h means OK to xmit again
  95. ;
  96. ;*****************************
  97. ;  Receive Command Options
  98. ;
  99. ;    If something is not detected for, the receiver automatically discards
  100. ;        those packets.
  101. ;
  102. EDTOVER    EQU    01H        ; Detect Overflow condition
  103. EDTFCS    EQU    02H        ; Detect FCS error, bad CRC on packet
  104. EDTDRB    EQU    04H        ; Detect dribble errors and accept them
  105. EDTSHORT EQU    08H        ; Detect short frames (< 60 bytes)
  106. EDTEOF    EQU    10H        ; Detect no overflow (end-of-frame found)
  107. EGOOD    EQU    20H        ; Accept good frames 
  108. ; four values legal for the last two bits:
  109. ECLOSE    EQU    00H        ; Turn off receiver
  110. EGETALL    EQU    40H        ; Get all packets, no matter what address
  111. EBROAD    EQU    80H        ; get those for me or for broadcast
  112. EMULTI    EQU    0C0H        ; get those for me or for multicast
  113. EWANT    EQU    0A0h        ; EGOOD OR EBROAD
  114.                 ; which packets we will look for on net
  115. ;
  116. ;  Receive Status results
  117. ;
  118. ;  errors are not detected unless asked for...otherwise the board just
  119. ;  won't take bad packets off of the net.
  120. ;
  121. ERROVER    EQU    01H        ; overflow error
  122. ERRFCS    EQU    02H        ; FCS (checksum) error
  123. ERRDRB    EQU    04H        ; Dribble error
  124. ERRSHORT  EQU    08H        ; Short frame error
  125. ENOOVER    EQU    10H        ; Received without overflow error 
  126.                 ; means that we didn't miss any by being slow
  127. ;EGOOD    EQU    20H        ; as above, we received a valid frame
  128. ; undefined 40h
  129. ESTALE    EQU    80H        ; stale receive condition, already read me
  130. ;
  131. ;  Aux command register
  132. ;
  133. EIRE    EQU    01H        ; interrupt request enable (no DMA) new boards
  134. EBADFCS    EQU    02H        ; create bad checksum for testing only
  135. ;
  136. ;  Next two bits tell who has access to packet buffer
  137. ;
  138. EBUS    EQU    00H        ; System bus has control of buffer
  139. EXMIT    EQU    04H        ; Transmit packet in buffer, auto kick
  140.                 ; back to recieve status
  141. EGETEM    EQU    08H        ; Receive state, look for packets
  142. ELOOP    EQU    0CH        ; Transmit and loopback into xmit buffer
  143. ;  10H  unused
  144. EDMA    EQU    20H        ; Starts a DMA xfer
  145. ERIDE    EQU    40H        ; Interrupt and DMA enable
  146. ERESET    EQU    80H        ; Reset the Ethernet board
  147. ;
  148. ;  Aux status register
  149. ;
  150. ERBUSY    EQU    01H        ; Receive busy, receiver looking for packets
  151. ;               02H        ; echos command status EBADFCS
  152. ;               04,08h        ; echos command status for EXMIT,EGETEM,EBUS
  153. EDMADONE  EQU    10H        ; goes to one when DMA finishes
  154. ;               20H        ; echos DMA request bit
  155. ;               40h        ; echos RIDE bit
  156. EXBUSY    EQU    80H        ; for polled xmit, goes to 0 when xmit is done
  157. ;
  158. ;
  159. ;  Macros for in and out
  160. ;
  161. MOUT    MACRO    REG,STUFF       ; one byte to the given I/O register
  162.     MOV    DX,REG
  163.     MOV    AL,STUFF
  164.     OUT    DX,AL
  165.     ENDM
  166. ;
  167. MOUTW    MACRO    REG,LO,HI      ; two bytes to the I/O double port
  168.     MOV    DX,REG
  169.     MOV    AL,LO
  170.     OUT    DX,AL
  171.     INC    DX
  172.     MOV    AL,HI
  173.     OUT    DX,AL
  174.     ENDM
  175. ;
  176. MIN    MACRO    REG             ; get one byte to al
  177.     MOV    DX,REG
  178.     IN    AL,DX
  179.     ENDM
  180.  
  181. ifdef Microsoft
  182. ;DGROUP    group    _DATA
  183. ;_DATA    segment    public 'DATA'
  184. ;    assume    DS:DGROUP
  185.     .data
  186. else
  187.     DSEG
  188. endif
  189. ;
  190. ;  The pointers below are actually DWORDs but we access them two
  191. ;  bytes at a time.
  192. ;
  193. ifdef Microsoft
  194. ;    EXTRN    _RSTAT:BYTE    ; last status from read
  195. ;    EXTRN    _BUFPT:WORD    ; current buffer pointer
  196. ;    EXTRN    _BUFORG:WORD    ; pointer to beginning of buffer
  197. ;    EXTRN    _BUFEND:WORD    ; pointer to end of buffer
  198. ;    EXTRN    _BUFREAD:WORD    ; pointer to where program is reading
  199. ;    EXTRN    _BUFBIG:WORD    ; integer, how many bytes we have
  200. ;    EXTRN    _BUFLIM:WORD    ; integer, max bytes we can have
  201. ;
  202. ; Seems to work only this way //jkp
  203.     PUBLIC    _RSTAT,_BUFPT,_BUFORG,_BUFEND,_BUFREAD,_BUFBIG,_BUFLIM,OFFS
  204. _RSTAT    DB    00H         ; last status from read
  205. _BUFBIG    DW    00H        ; buffer space used
  206. _BUFLIM    DW    05000H        ; buffer space limit
  207. _BUFPT    DW    00000H        ; where buffer pointer is, initialized safely
  208. _BUFDS    DW    0a000H        ; where buffer is, ds
  209. _BUFORG    DW    00000H        ; start of buffer space
  210. _BUFDS2    DW    0a000H        ; another ds
  211. _BUFEND    DW    06000H        ; end limit of allowable buffer space
  212. _BUFDS3    DW    0a000H
  213. _BUFREAD    DW    00000H        ; where the read pointer is
  214. _BUFDS4    DW    0a000H
  215. else
  216.     EXTRN    RSTAT:BYTE    ; last status from read
  217.     EXTRN    BUFPT:WORD    ; current buffer pointer
  218.     EXTRN    BUFORG:WORD    ; pointer to beginning of buffer
  219.     EXTRN    BUFEND:WORD    ; pointer to end of buffer
  220.     EXTRN    BUFREAD:WORD    ; pointer to where program is reading
  221.     EXTRN    BUFBIG:WORD    ; integer, how many bytes we have
  222.     EXTRN    BUFLIM:WORD    ; integer, max bytes we can have
  223. endif
  224.  
  225. SAVECS    DW    00H        ; where to save the old interrupt ptr
  226. SAVEIP    DW    00H
  227. OLDMASK    DB    00H        ; save interrupt controller mask
  228. DEAF    DB    00H        ; when we can't handle any more packets
  229. OFFS    DW    00H        ; how many times the handler was turned off
  230. ;
  231. ;  use variables to access IRQ3 or IRQ5
  232. ;  3 is COM2, 5 is LPT2
  233. ;
  234. ;WHICHINT  EQU    4*0Bh        ; Interrupt for interrupt I/O on IRQ3
  235. ;WHICHINT  EQU    4*0Dh        ; Interrupt for interrupt I/O on IRQ5
  236. ;TURNOFF  EQU      08H          ; IRQ3 bit mask for 8259 controller (1<<3)
  237. ;TURNOFF  EQU      020H            ; IRQ5 bit mask for 8259 controller (1<<5)
  238. ;TURNON    EQU    0F7H        ; IRQ3 enable bit mask for 8259 controller
  239. ;TURNON    EQU    0DFH        ; IRQ5 enable bit mask for 8259 controller
  240. INTNUM    DB    0BH        ; Defaults to IRQ3, interrupt handler 0bh
  241. WHICHINT  DW    4*0BH        ; ETOPEN can change these values
  242. TURNOFF    DB    08H
  243. TURNON    DB    0F7H
  244. ifdef Microsoft
  245. ;_DATA    ends
  246. else
  247.     ENDDS
  248. endif
  249. ;
  250. ;
  251. ;
  252. ;   The subroutines to call from C
  253. ;
  254. ifdef Microsoft
  255. ;_TEXT    segment    public    'CODE'
  256. ;    assume CS:_TEXT
  257.     .code
  258.     PUBLIC    _E3RECV,_E3ETOPEN,_E3ETCLOSE,_E3GETADDR,_E3SETADDR,_E3XMIT,_E3ETUPDATE
  259. else
  260.     PSEG
  261.     PUBLIC    E3RECV,E3ETOPEN,E3ETCLOSE,E3GETADDR
  262.     PUBLIC    E3SETADDR,E3XMIT,E3ETUPDATE
  263. endif
  264.  
  265. ;******************************************************************
  266. ;  ETOPEN
  267. ;     Initialize the Ethernet board, set receive type.
  268. ;
  269. ;  usage:  etopen(s,irq,addr,ioaddr)
  270. ;           char s[6];       ethernet address
  271. ;           int irq,addr,ioaddr;     
  272. ;                interrupt number, base mem address (unused) and
  273. ;                i/o address to use (currently unused)
  274. ;
  275. ;
  276. ifdef Microsoft
  277. _E3ETOPEN    PROC    FAR
  278. else
  279. E3ETOPEN    PROC    FAR
  280. endif
  281.     PUSH    BP
  282.     MOV    BP,SP
  283.     PUSH    SI
  284.     MOUT    EAUX,ERESET    ; reset the board
  285.     MOUT    EAUX,0          ; Clear the reset bit, otherwise keeps resetting
  286. ;
  287. ;  check the parameters for interrupt and dma
  288. ;
  289.     MOV    AX,[BP+X+4]    ; interrupt number
  290.     CMP    AL,5        ; If not 5, then use 3
  291.     JNZ    USE3
  292.     MOV    INTNUM,0DH    ; Interrupt # for handler for IRQ5
  293.     MOV    WHICHINT,4*0DH    ; Interrupt handler location in vector table
  294.     MOV    TURNOFF,020H    ; mask for interrupt controller for IRQ5
  295.     MOV    TURNON,0DFH    ; opposite mask, for interrupt controller
  296. USE3:
  297.     MOV    AX,[BP+X+6]    ; dma channel to use
  298.     CMP    AL,3        ; if not 3, then use 1
  299.     JNZ    USE1
  300. ;
  301. ; Add DMA values for channel 3 here later
  302. ;  probably never going to use DMA for this board - unreliable so far
  303. ;
  304. USE1:
  305. ;
  306. ;  install the interrupt handler
  307. ;
  308.     CALL    IINST        ; do the patching of the interrupt table
  309. ;
  310. ;  set up the net address
  311. ;
  312.     PUSH     DS        ; save mine
  313.     MOV    AX,[BP+X+2]    ; get new one
  314.     MOV    DS,AX           ; set new one
  315.     MOV    SI,[BP+X]    ; get pointer, ds:si is ready
  316.     ;
  317.     MOV    CX,6
  318.     MOV    DX,EADDR    ; get base i/o reg for setting address
  319.     CLD
  320. SADDR:
  321.     LODSB            ; get next one
  322.     OUT    DX,AL        ; send it
  323.     INC    DX        ; next position
  324.     LOOP    SADDR        ; do 6 times
  325.  
  326.     POP    DS        ; get back DS of local data
  327. ;
  328. ;  enable interrupts here with interrupt handler 
  329. ;  already set up.
  330. ;
  331.     MOUT    ESEND,0        ; xmit command = 0 for no interrupts
  332.     IN    AL,DX
  333.  
  334.     MOUT    EREC,EWANT    ; Set receiver for which packets we want
  335.     IN    AL,DX        ; reset 'stale'
  336.  
  337.     MOUT    ERLOW,0        ; Clear the receive buffer pointer
  338.  
  339.     CLI
  340.     MOUT    EAUX,EGETEM+ERIDE    ; Set for receive, interrupts
  341.  
  342.     MIN    IMASK        ; get current int enable mask
  343.     MOV    BL,AL        ; save a copy
  344.     AND    AL,TURNON    ; force bit for etherlink board off
  345.     OUT    DX,AL        ; put back the byte, IRQ enabled
  346.  
  347.     STI
  348.     AND    BL,TURNOFF    ; isolate this bit only from oldmask
  349.     MOV    OLDMASK,BL    ; save it
  350. ;
  351.     POP    SI
  352.     POP    BP
  353.     XOR    AX,AX
  354.     RET
  355. ifdef Microsoft
  356. _E3ETOPEN    ENDP
  357. else
  358. E3ETOPEN    ENDP
  359. endif
  360. ;
  361. ;******************************************************************
  362. ;  SETADDR
  363. ;    set the Ethernet address on the board to 6 byte ID code
  364. ;
  365. ;   usage:   setaddr(s,basea,ioa);
  366. ;             char s[6];           ethernet address to use
  367. ;             int basea;           shared memory base address (unused)
  368. ;             int ioa;             io address for board (unused)
  369. ;
  370. ifdef Microsoft
  371. _E3SETADDR    PROC    FAR
  372. else
  373. E3SETADDR    PROC    FAR
  374. endif
  375.     PUSH    BP
  376.     MOV    BP,SP
  377.     PUSH    DS
  378.     PUSH    SI
  379.     MOV    AX,[BP+X+2]
  380.     MOV    DS,AX
  381.     MOV    SI,[BP+X]    ; address of buffer to read
  382. ;
  383.     MOV    CX,6
  384.     MOV    DX,EADDR    ; get base i/o reg for setting address
  385.     CLD
  386. SADDR2:
  387.     LODSB            ; get next one
  388.     OUT    DX,AL        ; send it
  389.     INC    DX        ; next position
  390.     LOOP    SADDR2        ; do 6 times
  391.  
  392.     POP    SI
  393.     POP    DS
  394.     POP    BP
  395.     RET
  396. ifdef Microsoft
  397. _E3SETADDR    ENDP
  398. else
  399. E3SETADDR    ENDP
  400. endif
  401. ;
  402. ;*******************************************************************
  403. ;  GETADDR
  404. ;     get the Ethernet address off of the board
  405. ;
  406. ;   usage:  getaddr(s,address,ioaddr);
  407. ;    char s[6];           will get six bytes from the PROM
  408. ;       int address;
  409. ;       int ioaddr;     (unused here) mem address and ioaddress to use
  410. ;
  411. ifdef Microsoft
  412. _E3GETADDR    PROC    FAR
  413. else
  414. E3GETADDR    PROC    FAR
  415. endif
  416.     PUSH    BP
  417.     MOV    BP,SP
  418.     PUSH    DI
  419.     PUSH     ES        ; save mine
  420.     MOV    AX,[BP+X+2]    ; get new one
  421.     MOV    ES,AX           ; set new one
  422.     MOV    DI,[BP+X]    ; get pointer, es:di is ready
  423.     ;
  424.     MOV    BX,0            ; start location 
  425.     MOV    CX,EPROM    ; address window
  426. GADDR:
  427.     CLD
  428.     MOUTW    EGLOW,BL,BH      ; set gp to the right value
  429.     MIN    CX        ; get value from prom address window
  430.     STOSB                   ; put into given buffer
  431.     INC    BX        ; next position
  432.     CMP    BX,6
  433.     JNZ     GADDR          ; do 6 times
  434.     POP     ES
  435.     POP    DI
  436.     POP    BP        
  437.     RET
  438. ifdef Microsoft
  439. _E3GETADDR    ENDP
  440. else
  441. E3GETADDR    ENDP
  442. endif
  443. ;
  444. ;***********************************************************************
  445. ;  ETCLOSE
  446. ;        shut it down, remove the interrupt handler
  447. ;
  448. ;  usage:  etclose();
  449. ;
  450. ;
  451. ifdef Microsoft
  452. _E3ETCLOSE    PROC    FAR
  453. else
  454. E3ETCLOSE    PROC    FAR
  455. endif
  456.     CLI
  457.     MOUT    EAUX,ERESET    ; Turn off all pendings, cause reset
  458.     MOUT    EAUX,0          ; Turn off reset
  459. ;
  460. ;
  461. ;  mask out IRQ on interrupt controller
  462. ;
  463.     MIN    IMASK        ; get current mask
  464.     OR    AL,TURNOFF    ; force that bit on
  465.     OUT    DX,AL        ; send it back to controller
  466.     STI
  467.  
  468.     CALL    DEINST        ; restore old interrupt handler
  469.  
  470.     MOV    BL,OLDMASK    ; get back saved setting of irq
  471.     NOT    BL        ; flip it
  472.     CLI
  473.     MIN    IMASK
  474.     AND    AL,BL        ; restore setting of that bit
  475.     OUT    DX,AL
  476.     STI    
  477.     RET
  478. ifdef Microsoft
  479. _E3ETCLOSE    ENDP
  480. else
  481. E3ETCLOSE    ENDP
  482. endif
  483. ;
  484. ;************************************************************************
  485. ;   Receive
  486. ;   This is a CPU hook for boards that must be polled before we can
  487. ;   deliver packets into the receive buffer.  (i.e. no interrupts used)
  488. ;
  489. ;   The 3COM 3C501 version uses interrupts, so this routine is a NOP
  490. ;   for this board.
  491. ;
  492. ;    usage:  recv();
  493. ;
  494. ifdef Microsoft
  495. _E3RECV    PROC    FAR
  496. else
  497. E3RECV    PROC    FAR
  498. endif
  499.     RET            ; for compatibility with other drivers
  500. ifdef Microsoft
  501. _E3RECV    ENDP
  502. else
  503. E3RECV    ENDP
  504. endif
  505. ifdef unused_code
  506. ;      This version is unused.  It is a polled receive which is nearly
  507. ;      useless with this board.  It hasn't been debugged yet, either.
  508. ;             char *where;      at least 2048 bytes of room
  509. ;             returns # bytes in packet, -1 if no packet available
  510.     PUSH    BP
  511.     MOV    BP,SP
  512.     PUSH    ES
  513.     MOV    AX,[BP+X+2]    ; get new es value
  514.     MOV    ES,AX
  515.     MOV    DI,[BP+X]    ; set di for later movement
  516.     ;
  517.     MOV    CX,10        ; give it a few tries
  518.  
  519. FINDONE:
  520.     MIN    EAUX        ; get status to al
  521.     MOV    STAT,AL
  522.     AND    AL,ERBUSY    ; is it still in receive state or done?
  523.     JZ    READONE        ; done, can read it
  524.     LOOP    FINDONE
  525.  
  526.     MOV    AX,-1        ; no packet yet, return
  527.     POP    ES
  528.     POP    BP
  529.     RET
  530. ;
  531. READONE:
  532.     MOUT    EAUX,EBUS    ; turn off receive, give buffer to bus
  533.     MOUTW    EGLOW,0,0    ; clear general purpose pointer for read
  534.  
  535.     MOV    DX,ERLOW    ; receive buffer pointer
  536.     IN    AL,DX
  537.     MOV    CL,AL        ; save low byte
  538.     INC    DX
  539.     IN    AL,DX
  540.     MOV    CH,AL        ; save high byte
  541.  
  542.     MOV    BX,CX           ; save another copy of the length
  543.  
  544.     MOV    DX,EBUF        ; window to the data
  545.  
  546. DOBYTES:
  547.     IN    AL,DX        ; get a byte
  548.     STOSB            ; save it to es:di
  549.     LOOP     DOBYTES
  550.  
  551.     MIN    EREC        ; get status to al, clears read
  552.     MOV    STAT,AL        ; KEEP LAST STATUS BYTE
  553. ;
  554. ;  set up to read the next packet from the net
  555. ;
  556.     MOUT    ERLOW,0        ; clear receive buffer pointer
  557.     MOUT    EAUX,EGETEM+ERIDE    ; set receive bit in aux
  558.  
  559.     MOV    AX,BX        ; return value is # of bytes
  560.     POP    ES
  561.     POP    BP
  562.     RET
  563. ifdef Microsoft
  564. _E3RECV    ENDP
  565. else
  566. E3RECV    ENDP
  567. endif
  568. endif
  569. ;
  570. ;************************************************************************
  571. ;  XMIT         
  572. ;     send a packet to Ethernet
  573. ;     Is not interrupt driven, just call it when you need it.
  574. ;
  575. ;  usage:   xmit(packet,count)
  576. ;        char *packet;
  577. ;        int count;
  578. ;
  579. ;   Takes a packet raw, Ethernet packets start with destination address,
  580. ;   and puts it out onto the wire.  Count is the length of packet < 2048
  581. ;
  582. ;   checks for packets under the Ethernet size limit of 60 and handles them
  583. ;
  584. ifdef Microsoft
  585. _E3XMIT    PROC    FAR
  586. else
  587. E3XMIT    PROC    FAR
  588. endif
  589.     PUSH    BP
  590.     MOV    BP,SP
  591.     PUSH    SI
  592.     PUSH    DI
  593.     PUSH    DS        ; set up proper ds for the buffer
  594.     MOV    AX,[BP+X+2]
  595.     MOV    DS,AX
  596.     MOV    SI,[BP+X]    ; offset for buffer
  597.  
  598.     MOV    AX,[BP+X+4]    ; count of bytes
  599.     MOV    CX,AX        ; save a copy, might be less than 60, ok
  600.  
  601.     CMP    AX,60        ; minimum length for Ether
  602.     JNB    OKLEN
  603.     MOV    AX,60        ; make sure size at least 60
  604. OKLEN:
  605.     MOV    BX,2048        ; total length of buffer
  606.     SUB    BX,AX        ; offset of for buffer pointer to start
  607.     MOV    DI,BX        ; save a copy of the buffer pointer
  608. ;
  609. ;  TAKE CONTROL OF THE INPUT BUFFER
  610. ;
  611.     MOUT    EAUX,EBUS+ERIDE    ; take buffer away from receiver
  612.     MOUT    ERLOW,0        ; clear receive pointer for next read
  613.     MOUTW    EGLOW,BL,BH    ; set the general purpose pointer
  614.  
  615.     MOV    DX,EBUF        ; window to packet buffer
  616.     CLD
  617. FILLBUF:
  618.     LODSB            ; get value to go into buffer
  619.     OUT    DX,AL        ; put it into buffer (autoincrement)
  620.     LOOP    FILLBUF        ; do whole count
  621.  
  622.     POP    DS
  623. ;
  624. ;  packet is in buffer, ready to be sent
  625. ;
  626. TRYAGAIN:
  627.     MOV    BX,DI        ; retrieve copy of offset pointer
  628.     MOUTW    EGLOW,BL,BH    ; set the general purpose pointer (again)
  629. ;
  630.     MOUT    EAUX,EXMIT+ERIDE    ; tell the board to send it and start receiving
  631.     
  632. NOTDONEX:
  633.     MIN    EAUX        ; waiting for transmit to finish
  634.     AND    AL,EXBUSY    ; is it done yet?
  635.     JNZ    NOTDONEX    ; no, wait some more
  636.  
  637.     MOV    CX,0        ; return value, ok
  638.     MIN    ESEND        ; get xmit status
  639.     MOV    BL,AL        ; save status
  640.     AND    AL,EDTOK    ; was it ok?
  641.     JNZ    DONEX        ; yes, successful xmit
  642. ;
  643. ;  handle the possible errors, return 1 on coll16
  644. ;     coll16 generally means that the network has failed
  645. ;
  646.     MOV    AL,BL        ; get copy of status back
  647.     AND    AL,EDTC16    ; check collision 16
  648.     JNZ    RET16        ; yes, network probably down
  649.     MOV    AL,BL        ; get copy back again
  650.     AND    AL,EDTCOLL    ; check for collision status
  651.     JZ    UNK        ; no, unknown problem
  652.     MOUT    EAUX,EBUS+ERIDE        ; collision, reset buffer control
  653.     JMP    TRYAGAIN    ; go for it
  654. UNK:
  655.     MOV    CX,2        ; unknown problem return code
  656.     JMP SHORT DONEX
  657. RET16:
  658.     MOV    CX,1        ; failure return
  659. DONEX:
  660.     MOUT    EREC,EWANT    ; reset receive register filter necessary
  661.     MIN    EAUX    
  662.     AND    AL,ERBUSY    ; is it still in receive state or done?
  663.     JNZ    DONEMIT        ; not ready now, return instead
  664.  
  665.     MOV    AL,INTNUM
  666.     CMP    AL,0BH        ; two choices of int to call
  667.     JNZ    TRYNINT
  668.     INT    0BH        ; we do have a packet, read it
  669.     JMP SHORT DONEMIT
  670. TRYNINT:
  671.     CMP    AL,0DH
  672.     JNZ    DONEMIT
  673.     INT    0DH
  674.  
  675. DONEMIT:
  676.     MOV    AX,CX        ; put return in ax
  677.     POP    DI
  678.     POP    SI
  679.     POP    BP
  680.     RET
  681. ifdef Microsoft
  682. _E3XMIT    ENDP
  683. else
  684. E3XMIT    ENDP
  685. endif
  686. ;
  687. ;*************************************************************************
  688. ;  Interrupt Handler
  689. ;  installation and deinstallation
  690. ;
  691. ;     the handler takes the receive packet out of the input buffer
  692. ;
  693. DEINST    PROC    NEAR
  694.     MOV    CX,SAVEIP    ; get old ip from save spot
  695.     MOV    DX,SAVECS    ; get old cs from save spot
  696.     MOV    BX,WHICHINT    ; interrupt in table for 3com board
  697.     PUSH    DS
  698.     XOR    AX,AX        ; system interrupt table
  699.     MOV    DS,AX        
  700.     CLI
  701.     MOV    [BX],CX        ; store old ip into the table
  702.     INC    BX
  703.     INC    BX        ; move pointer in interrupt table
  704.     MOV    [BX],DX        ; store old cs into the table
  705.     STI
  706.     POP    DS
  707.     RET
  708. DEINST    ENDP
  709. ;
  710. IINST    PROC    NEAR
  711.     MOV    CS:MYDS,DS    ; store for use by handler
  712.     MOV    BX,WHICHINT    ; interrupt in table for 3com board
  713.     PUSH    DS
  714.     XOR    AX,AX        ; system interrupt table
  715.     MOV    DS,AX        
  716.     MOV    AX,OFFSET IHAND    ; where the handler is
  717.     CLI
  718.     MOV    DX,[BX]        ; keep copy of the ip
  719.     MOV    [BX],AX        ; store ip into the table
  720.     INC    BX
  721.     INC    BX        ; move pointer in interrupt table
  722.     MOV    CX,[BX]        ; keep copy of the cs, too
  723.     MOV    AX,CS
  724.     MOV    [BX],AX        ; store new cs into the table
  725.     STI
  726.     POP    DS
  727.     MOV    SAVEIP,DX    ; store them away
  728.     MOV    SAVECS,CX
  729.     RET
  730. MYDS    DW    00H        ; the data segment for this assembly code
  731. ICNT    DB      00H
  732. IHAND:                       ; not a public name, only handles ints
  733.     STI
  734.     PUSH    DS
  735.     PUSH     ES
  736.     PUSH    AX
  737.     PUSH    BX
  738.     PUSH    CX
  739.     PUSH    DX
  740.     PUSH    DI
  741.     CLD            ; all moves will be forward
  742. ;
  743. ;  SET UP CORRECT DS
  744. ;
  745.     MOV    DS,CS:MYDS        ; get correct ds
  746. ifdef Microsoft
  747.     MOV    AX,word ptr [_BUFPT+2]    ; buffer's ds
  748.     MOV DI,_BUFPT       ; where buffer is
  749. else
  750.     MOV    AX,word ptr [BUFPT+2]    ; buffer's ds
  751.     MOV DI,BUFPT        ; where buffer is
  752. endif
  753.     MOV    ES,AX
  754. ;
  755. ;  check for buffer overrun or catching up with reader
  756. ;
  757. ;  implicit 64K max buffer, should stop before 64K anyway
  758. ;
  759. ifdef Microsoft
  760.     MOV    AX,_BUFBIG    ; how much stuff is in buffer
  761. else
  762.     MOV    AX,BUFBIG    ; how much stuff is in buffer
  763. endif
  764. ifdef Microsoft
  765.     MOV    BX,_BUFLIM    ; what is our size limit?
  766. else
  767.     MOV    BX,BUFLIM    ; what is our size limit?
  768. endif
  769.     CMP    AX,BX
  770.     JNA    ISROOM        ; we are ok
  771. ;
  772. ;  no room at the Inn.  turn off receiver
  773. ;
  774.     MOUT    EAUX,EBUS+ERIDE    ; refuse to read more packets until restarted
  775.  
  776.     MIN    EREC        ; must clear interrupt
  777.  
  778.     MOV    AL,1        ; set flag
  779.     MOV    DEAF,AL        ; we are now deaf, read routine must restart
  780.  
  781.     JMP SHORT ENDINT      ; can't do much, we lose packets until restarted
  782.  
  783. ;
  784. ;  wrap pointer around at end, we know that we have room
  785. ;
  786. ISROOM:
  787. ifdef Microsoft
  788.     MOV    DX,_BUFEND    ; right before 2K safety area
  789. else
  790.     MOV    DX,BUFEND    ; right before 2K safety area
  791. endif
  792.     CMP    DX,DI        ; see if pointer is over limit
  793.     JA    OKAYREAD    ; we are not at wrap-around
  794.  
  795. ifdef Microsoft
  796.     MOV    AX,_BUFORG    ; wrap to here
  797. else
  798.     MOV    AX,BUFORG    ; wrap to here
  799. endif
  800. ifdef Microsoft
  801.     MOV    _BUFPT,AX    ; wrap-around
  802. else
  803.     MOV    BUFPT,AX    ; wrap-around
  804. endif
  805.     MOV    DI,AX        ; di also
  806. ;
  807. ;  here, DI contains where we want to put the packet.
  808. ;
  809. OKAYREAD:
  810.  
  811. ;    MOV    CX,10        ; give it a few tries
  812.  
  813. IFINDONE:
  814. ;    MIN    EAUX        ; get status to al
  815. ;    AND    AL,ERBUSY    ; is it still in receive state or done?
  816. ;    JZ    IREADONE    ; done, can read it
  817. ;    LOOP    IFINDONE
  818. ;    MIN    EREC
  819. ;    AND    AL,ESTALE
  820. ;    JZ    IREADONE
  821. ;    jmp    ireadone
  822.  
  823. ;    MOV    AX,0        ; no packet yet, spurious int, return
  824. ;    STOSB
  825.  
  826. ;    MIN    EREC        ; clear interrupt condition
  827. ;    MIN    ESEND        ; in case it was an xmit spurious int
  828. ;    JMP    STOPINT
  829. ;
  830. IREADONE:
  831.     MOUT    EAUX,EBUS+ERIDE    ; turn off receive, give buffer to bus
  832.     MOUTW    EGLOW,0,0    ; clear general purpose pointer for read
  833.     MIN    EREC        ; get status to al, clears read
  834.  
  835.     MOV    DX,ERLOW    ; receive buffer pointer
  836.     IN    AL,DX
  837.     MOV    CL,AL        ; save low byte
  838.     INC    DX
  839.     IN    AL,DX
  840.     MOV    CH,AL        ; save high byte
  841.  
  842.     MOV    BX,CX           ; save another copy of the length
  843.     OR    BX,BX        ; check for non-zero
  844.     JZ    STOPINT        ; no packet
  845.     
  846.     MOV    AX,BX        ; save length in buffer, before packet
  847.     STOSW
  848.  
  849.     MOV    DX,EBUF        ; window to the data
  850.  
  851. IDOBYTES:
  852.     IN    AL,DX        ; get a byte
  853.     STOSB            ; save it to es:di
  854.     LOOP     IDOBYTES
  855. ;
  856. ;
  857. ;  DI now contains updated value for BUFPT, BX contains size of packet
  858. ;
  859. ifdef Microsoft
  860.     MOV    _BUFPT,DI    ; it is here, now
  861. else
  862.     MOV    BUFPT,DI    ; it is here, now
  863. endif
  864.  
  865. ifdef Microsoft
  866.     MOV    AX,_BUFBIG    ; total amount of stuff in buffer
  867. else
  868.     MOV    AX,BUFBIG    ; total amount of stuff in buffer
  869. endif
  870.     ADD    AX,BX
  871.     INC    AX
  872.     INC    AX        ; to cover the length value
  873. ifdef Microsoft
  874.     MOV    _BUFBIG,AX    ; after adding in current packet size
  875. else
  876.     MOV    BUFBIG,AX    ; after adding in current packet size
  877. endif
  878. ;
  879. ;  signs that something is actually happening - used for debugging
  880. ;
  881. ;    MOV    AX,0B000H       ; screen
  882. ;    MOV    ES,AX
  883. ;    MOV    DI,3998        ; lower right corner
  884. ;    INC    CS:ICNT
  885. ;    MOV    Al,CS:ICNT    ; character
  886. ;    STOSB
  887.  
  888. ;
  889. ;  set up to read the next packet from the net
  890. ;
  891. STOPINT:
  892.     MOUT    ERLOW,0        ; clear receive buffer pointer
  893.     MOUT    EAUX,EGETEM+ERIDE    ; set receive bit in aux
  894.  
  895. ENDINT:
  896.  
  897.     MOUT    ICTRL,ENDOFI    ; signal end of interrupt
  898.     POP    DI
  899.     POP    DX
  900.     POP    CX
  901.     POP    BX
  902.     POP    AX
  903.     POP    ES
  904.     POP    DS
  905.     IRET
  906. IINST    ENDP
  907.  
  908. ;
  909. ;*************************************************************************
  910. ;  ETUPDATE
  911. ;      update pointers and/or restart receiver when read routine has
  912. ;      already removed the current packet
  913. ;
  914. ;   usage:  etupdate();
  915. ;
  916. ifdef Microsoft
  917. _E3ETUPDATE    PROC    FAR
  918. else
  919. E3ETUPDATE    PROC    FAR
  920. endif
  921.     PUSH     ES
  922. ifdef Microsoft
  923.     MOV    AX,word ptr [_BUFPT+2]    ; establish data segment to buffer
  924. else
  925.     MOV    AX,word ptr [BUFPT+2]    ; establish data segment to buffer
  926. endif
  927.     MOV    ES,AX        ; put that in es
  928. ;
  929. ifdef Microsoft
  930.     MOV    BX,_BUFREAD    ; where read pointer is now
  931. else
  932.     MOV    BX,BUFREAD    ; where read pointer is now
  933. endif
  934.     MOV    DX,ES:[BX]    ; get size of this packet
  935.     INC    DX
  936.     INC    DX        ; two more for length value
  937.  
  938.     ADD    BX,DX        ; increment bufread by size of packet
  939.  
  940. ifdef Microsoft
  941.     MOV    CX,_BUFEND    ; right before 2K safety area
  942. else
  943.     MOV    CX,BUFEND    ; right before 2K safety area
  944. endif
  945.     CMP    BX,CX        ; see if pointer is over limit
  946.     JB    NOWRAPRD    ; we are not at wrap-around
  947.     
  948. ifdef Microsoft
  949.     MOV    BX,_BUFORG    ; wrap to here
  950. else
  951.     MOV    BX,BUFORG    ; wrap to here
  952. endif
  953. NOWRAPRD:
  954. ifdef Microsoft
  955.     MOV    _BUFREAD,BX    ; buffer pointer has been updated
  956. else
  957.     MOV    BUFREAD,BX    ; buffer pointer has been updated
  958. endif
  959.  
  960. ;
  961. ;  DECREMENT TOTAL BUFFER SIZE
  962. ;
  963.     CLI            ; keep interrupt handler from bothering dec
  964. ifdef Microsoft
  965.     MOV    CX,_BUFBIG    ; size before removing packet
  966. else
  967.     MOV    CX,BUFBIG    ; size before removing packet
  968. endif
  969.     SUB    CX,DX        ; remove size of current packet
  970. ifdef Microsoft
  971.     MOV    _BUFBIG,CX    ; put it back
  972. else
  973.     MOV    BUFBIG,CX    ; put it back
  974. endif
  975.     STI
  976. ;
  977. ;  IF RECEIVER IS ON, THEN CHECKING BUFLIM IS UNNECESSARY.
  978. ;
  979.     MOV    AL,DEAF        ; is the receiver turned off?
  980.     OR    AL,AL        ; 0 = reading, 1 = deaf
  981.     JZ    ALIVE
  982. ;
  983. ;  CHECK FOR ROOM IN THE BUFFER, IF THERE IS, TURN ON RECEIVER
  984. ;
  985. ifdef Microsoft
  986.     MOV    AX,_BUFLIM    ; what is our limit?
  987. else
  988.     MOV    AX,BUFLIM    ; what is our limit?
  989. endif
  990.     CMP    CX,AX        ; compare to limit
  991.     JA    ALIVE        ; not really alive, but can't turn on yet
  992.  
  993.     XOR    AL,AL
  994.     MOV    DEAF,AL        ; reset flag
  995.  
  996.     INC    OFFS        ; keep count how many times this happened
  997.  
  998.     MOUT    ERLOW,0        ; reset receive buffer ptr
  999.     MOUT    EAUX,EGETEM+ERIDE    ; turn on receiver
  1000.  
  1001. ALIVE:
  1002.     POP    ES
  1003.     RET    
  1004. ifdef Microsoft
  1005. _E3ETUPDATE    ENDP
  1006. else
  1007. E3ETUPDATE    ENDP
  1008. endif
  1009.  
  1010. ifdef Microsoft
  1011. ;_TEXT    ends
  1012. else
  1013.     ENDPS
  1014. endif
  1015.     END
  1016.