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

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