home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / NETWORK / TEL23SRC.ZIP / NET / ENET / NOV3COM.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-05-15  |  25.0 KB  |  946 lines

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