home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / NCSA / TEL2307S.ZIP / NET / ENET / NET505.ASM < prev    next >
Encoding:
Assembly Source File  |  1992-02-22  |  64.8 KB  |  1,789 lines

  1.           page       55,132
  2.           title     Driver routines for 3C505 Ethernet board
  3. ;
  4. ; Driver routines for 3C505 Ethernet board
  5. ;
  6. ; Bruce Orchard
  7. ; Waisman Center on Mental Retardation and Human Development
  8. ; University of Wisconsin-Madison
  9. ;
  10. ; April 7, 1988
  11. ;  2/9/89      Changed to make compatible with Telnet 2.2 - Warren Van Houten
  12. ;  3/17/89     Changed to make compatible with msc 5.0
  13. ;  7/14/89     Fixed getting ether address (far/near mismatch) - krus@diku.dk
  14. ;
  15. ;Microsoft EQU 1
  16. ;Lattice EQU 1
  17. ifndef Microsoft
  18.     ifndef Lattice
  19.         if2
  20.             %out
  21.             %out ERROR: You have to specify "/DMicrosoft" OR "/DLattice" on the
  22.             %out        MASM command line to determine the type of assembly.
  23.             %out
  24.         endif
  25.         end
  26.     endif
  27. endif
  28.  
  29. ifdef Microsoft
  30. x          equ     6              ; Offset to parameters (skip bp, ip, cs)
  31. else
  32.         NAME    NET
  33.       INCLUDE    DOS.MAC
  34.       SETX
  35. endif
  36.  
  37. ;  3C505 control register bit definitions
  38.  
  39. EC_ATTENTION             equ     0200q     ; Attention
  40. EC_FLUSH_DATA            equ     0100q     ; Flush data register
  41. EC_DMA_ENABLE            equ     0040q     ; DMA enable
  42. EC_TO_HOST               equ     0020q     ; Direction:  To host
  43. EC_TERMINAL_COUNT_ENABLE equ     0010q     ; Terminal count interrupt enable
  44. EC_COMMAND_ENABLE        equ     0004q     ; Command intterupt enable
  45. EC_FLAG2                 equ     0002q     ; Host status flag 2
  46. EC_FLAG1                 equ     0001q     ; Host status flag 1
  47.  
  48. ;  3C505 status register bit definitions
  49.  
  50. ES_DATA_READY            equ     0200q     ; Data register ready
  51. ES_HOST_COMMAND_EMPTY    equ     0100q     ; Host command register empty
  52. ES_ADAPTER_COMMAND_FULL  equ     0040q     ; Adapter command register full
  53. ES_TO_HOST               equ     0020q     ; Direction:  To host
  54. ES_DMA_DONE              equ     0010q     ; DMA done
  55. ES_FLAG3                 equ     0004q     ; Adapter status flag 3
  56. ES_FLAG2                 equ     0002q     ; Adapter status flag 2
  57. ES_FLAG1                 equ     0001q     ; Adapter status flag 1
  58.  
  59. ;  3C505 aux DMA control register bit definitions
  60.  
  61. EA_BURST                 equ     0001q     ; Burst mode DMA
  62.  
  63. ; 8259 equates
  64.  
  65. IOCWR1        equ     20h          ; Command register address 1
  66. IMR1          equ     21h          ; Interrupt mask register address 1
  67. VEC1          equ     8            ; First vector for 8259 1
  68. IOCWR2        equ     0a0h         ; Command register address 2
  69. IMR2          equ     0a1h         ; Interrupt mask register address 2
  70. VEC2          equ     70h          ; First vector for 8259 2
  71. EOI           equ     60h          ; End of interrupt command
  72.  
  73. ; Time out values (1/18 second ticks)
  74.  
  75. SECOND          EQU     18          ; Ticks in 1 second
  76. RESDEL          EQU     3           ; Delay before checking reset status
  77. RESTO           EQU     15*SECOND   ; Time out for reset completion
  78. CMDBTO          EQU     3           ; Time out for command byte to be accepted
  79. CMDCTO          EQU     3           ; Time out for command to be accepted
  80. RETRYDELAY      EQU     3           ; Command retry delay
  81. RCMDTO          EQU     3           ; Incoming command time out
  82. RESPTO          EQU     3           ; Response time out
  83.  
  84.  
  85.  
  86. ; BIOS data area
  87.  
  88. bios_data      segment     at 40h
  89. org 06Ch
  90. timer_low        dw        ?         ; BIOS timer counter
  91. timer_high       dw        ?
  92. timer_ofl        dw        ?
  93. bios_data       ends
  94.  
  95. ifdef Microsoft
  96. DGROUP    group    _DATA
  97. _DATA    segment    public 'DATA'
  98.  
  99. ;    PUBLIC    STAT,BUFPT,BUFORG,BUFEND,BUFREAD,BUFBIG,BUFLIM,OFFS
  100. ;
  101. ;  The pointers below are actually DWORDs but we access them two
  102. ;  bytes at a time.
  103. ;
  104. ; STAT change to RSTAT because of name clash with MSC library routine
  105. ;   EXTRN   _RSTAT:BYTE       ; last status from read
  106.     EXTRN   _BUFPT:WORD       ; current buffer pointer
  107.     EXTRN   _BUFORG:WORD      ; pointer to beginning of buffer
  108.     EXTRN   _BUFEND:WORD      ; pointer to end of buffer
  109.     EXTRN   _BUFREAD:WORD     ; pointer to where program is reading
  110.     EXTRN   _BUFBIG:WORD      ; integer, how many bytes we have
  111.     EXTRN   _BUFLIM:WORD      ; integer, max bytes we can have
  112.  
  113.           public     _c5_droptot
  114.           public     _c5_wrapct
  115.           public     _c5_nocmd     
  116.           public     _c5_cmdito
  117.  
  118. _c5_droptot    dw     0          ; total buffers dropped
  119. _c5_wrapct     dw     0          ; buffer wraparounds
  120. _c5_nocmd      dw     0          ; interrupt with command register empty
  121. _c5_cmdito     dw     0          ; incoming command timeout
  122.     assume    DS:seg _c5_droptot
  123.  
  124. else
  125.     DSEG
  126.  
  127. ;   EXTRN   RSTAT:BYTE    ; last status from read
  128.     EXTRN   BUFPT:WORD    ; current buffer pointer
  129.     EXTRN   BUFORG:WORD    ; pointer to beginning of buffer
  130.     EXTRN   BUFEND:WORD    ; pointer to end of buffer
  131.     EXTRN   BUFREAD:WORD    ; pointer to where program is reading
  132.     EXTRN   BUFBIG:WORD    ; integer, how many bytes we have
  133.     EXTRN   BUFLIM:WORD    ; integer, max bytes we can have
  134.  
  135.           public     c5_droptot
  136.           public     c5_wrapct
  137.           public     c5_nocmd     
  138.           public     c5_cmdito
  139.  
  140. c5_droptot    dw     0          ; total buffers dropped
  141. c5_wrapct     dw     0          ; buffer wraparounds
  142. c5_nocmd      dw     0          ; interrupt with command register empty
  143. c5_cmdito     dw     0          ; incoming command timeout
  144.     assume    DS:seg c5_droptot
  145.  
  146. endif
  147.  
  148. ksegbios     dw     ?          ; bios data segment
  149. ksegdata     dw     ?          ; DATA segment - might be different
  150.                                ; from seg c5_drop
  151. kseghere     dw     ?          ; segment for the begining of this data
  152.                                ; group.
  153. irq          dw     ?          ; Interrupt request level
  154. ioadr        dw     ?          ; IO address
  155. dma          dw     ?          ; DMA request level
  156.  
  157. ecommand     dw     ?          ; 3C505 command address
  158. estatus      dw     ?          ; 3C505 status address
  159. edata        dw     ?          ; 3C505 data address
  160. econtrol     dw     ?          ; 3C505 control address
  161. eauxdma      dw     ?          ; 3C505 aux DMA control address
  162.  
  163. eoi1         dw     ?          ; End of interrupt command for 8259 1
  164. eoi2         dw     ?          ; End of interrupt command for 8259 2
  165.  
  166. imr          dw     ?          ; Interrupt mask register address
  167. vec          dw     ?          ; Vector number
  168. oldioff      dw     ?          ; Original interrupt offset
  169. oldiseg      dw     ?          ; Original interrupt segment
  170.  
  171. pcblen       dw     ?          ; PCB length
  172. pcbad        dw     ?          ; PCB address
  173.  
  174. cmdlen       dw     ?          ; Incoming command length
  175.  
  176. rbufct       dw     ?          ; receive buffer counter
  177. rdropnew     dw     ?          ; receive buffers just dropped
  178. newstart     dw     ?          ; number of receives to start
  179.  
  180. savemask     db     ?          ; Original interrupt mask
  181. maskbit      db     ?          ; Interrupt mask bit
  182. lastcon      db     ?          ; Last control to board
  183.  
  184. CBSH         equ     50        ; half of incoming command buffer
  185. CBS          equ     CBSH*2    ; incoming command buffer size
  186.  
  187. icmdb        db     CBS dup (?)    ; Incoming command buffer
  188. icmd         db     CBSH dup (?)   ; incoming command
  189.  
  190. fconc        db     0          ; Flag:  Configure 82586
  191. fgeth        db     0          ; Flag:  Get Ethernet address
  192. fseth        db     0          ; Flag:  Set Ethernet address
  193. fxmit        db     0          ; Flag:  Transmit packet
  194. fadin        db     0          ; Flag:  Adapter info
  195. fstat        db     0          ; Flag:  Statistics
  196.  
  197.           even
  198.  
  199. cconc          db     02h        ; Command:  Configure 82586
  200.                db     2          ; -- 2 more bytes
  201.                dw     1          ; -- receive broadcasts
  202.  
  203. rconc          db  2 dup (?)     ; Response:  Configure 82586
  204. rconc_st       dw     ?          ; -- status
  205.  
  206.  
  207. cgeth          db     03h        ; Command:  Get Ethernet address
  208.                db     00         ; 0 more bytes
  209.  
  210. rgeth          db  2 dup (?)     ; Response:  Get Ethernet address
  211. rgeth_ad       db  6 dup (?)     ; -- address
  212.  
  213.  
  214. cseth          db     10h        ; Command:  Set Ethernet address
  215.                db     06         ; 6 more bytes
  216. cseth_ad       db  6 dup (?)     ; -- address
  217. rseth          db  2 dup (?)     ; Response:  Set Ethernet address
  218. rseth_status   dw     ?          ; -- status
  219.  
  220. cxmit          db     09h        ; Command:  Transmit packet
  221.                db     06         ; 6 more bytes
  222. cx_offset      dw     ?          ; -- buffer offset
  223. cx_segment     dw     ?          ; -- buffer segment
  224. cx_length      dw     ?          ; -- buffer length
  225.  
  226. rxmit          db  2 dup (?)     ; Response:  Transmit packet
  227. rx_offset      dw     ?          ; -- buffer offset
  228. rx_segment     dw     ?          ; -- buffer segment
  229. rx_status      dw     ?          ; -- completion status
  230. rx_cstatus     dw     ?          ; -- 82586 status
  231.  
  232. cr             db     08h        ; Command:  Receive
  233.                db     08         ; 8 more bytes
  234. cr_offset      dw     ?          ; -- buffer offset
  235. cr_segment     dw     ?          ; -- buffer segment
  236. cr_length      dw     ?          ; -- buffer length
  237. cr_timeout     dw     ?          ; -- timeout
  238.  
  239. rr             db  2 dup (?)     ; Response:  Receive
  240. rr_offset      dw     ?          ; -- buffer offset
  241. rr_segment     dw     ?          ; -- buffer segment
  242. rr_dmalen      dw     ?          ; -- bytes to dma
  243. rr_length      dw     ?          ; -- actual length
  244. rr_status      dw     ?          ; -- completion status
  245. rr_rstatus     dw     ?          ; -- 82586 receive status
  246. rr_time        dd     ?          ; -- time tag
  247.  
  248. cadin          db     11h        ; Command:  Adapter info
  249.                db     0          ; 0 more bytes
  250. radin          db  2 dup (?)     ; Response:  Adapter info
  251.  
  252. ra_rom         dw     ?          ; -- ROM version
  253. ra_cs          dw     ?          ; -- ROM checksum
  254. ra_mem         dw     ?          ; -- RAM memory size
  255. ra_freeoff     dw     ?          ; -- Free memory offset
  256. ra_freeseg     dw     ?          ; -- Free memory segment
  257.  
  258. cstat          db     0ah        ; Command:  Network statistics
  259.                db     0          ; 0 more bytes
  260.  
  261. rstat          db  2 dup (?)     ; Response:  Network statistics
  262. rs_rec         dd     ?          ; -- Packets received
  263. rs_tran        dd     ?          ; -- Packets sent
  264. rs_crc         dw     ?          ; -- CRC error counter
  265. rs_align       dw     ?          ; -- Alignment error counter
  266. rs_nors        dw     ?          ; -- No resources error counter
  267. rs_or          dw     ?          ; -- Overrun error counter
  268.  
  269. TURNOFF        db     08h
  270. TURNON         db     0F7h
  271. ifdef Microsoft
  272. _DATA    ends
  273. else
  274.     ENDDS
  275. endif
  276. ;
  277. ;
  278. ;  Macros for in and out
  279. ;
  280. MOUT     MACRO     REG,STUFF       ; one byte to the given I/O register
  281.      MOV  DX, REG
  282.      MOV  AL, STUFF
  283.      OUT  DX, AL
  284.      ENDM
  285. ;
  286. MOUTW     MACRO     REG, LO, HI     ; two bytes to the I/O double port
  287.      MOV  DX, REG
  288.      MOV  AL, LO
  289.      OUT  DX, AL
  290.      INC  DX
  291.      MOV  AL, HI
  292.      OUT  DX, AL
  293.      ENDM
  294. ;
  295. MIN MACRO  REG              ; get one byte to al
  296.     MOV DX, REG
  297.     IN  AL, DX
  298.     ENDM
  299.  
  300.  
  301. ;
  302. ;
  303. ;
  304. ;   The subroutines to call from C
  305. ;
  306. ifdef Microsoft
  307. NET505_TEXT  segment  public  'CODE'
  308.     
  309.     assume CS:NET505_TEXT, ES:bios_data
  310.     
  311.     PUBLIC    _E5RECV, _E5ETOPEN, _E5ETCLOSE, _E5GETADDR
  312. ifdef LOCAL_DEF
  313.     PUBLIC  _E5SETADDR
  314. endif
  315.     PUBLIC  _E5XMIT, _E5ETUPDATE, _E5ETDMA
  316.     public  _c5_get_adapter_info, _c5_get_statistics
  317. else
  318.     PSEG
  319.     PUBLIC    E5RECV, E5ETOPEN, E5ETCLOS, E5GETADD
  320. ifdef LOCAL_DEF
  321.     PUBLIC  E5SETADD
  322. endif
  323.     PUBLIC  E5XMIT, E5ETUPDA, E5ETDMA
  324.     public  c5getada, c5getsta
  325. endif
  326.  
  327.  
  328.  
  329.           subttl     _E5etopen:  Initialize board
  330.           page     +
  331. ;******************************************************************
  332. ;  ETOPEN
  333. ;     Initialize the Ethernet board, set receive type.
  334. ;
  335. ;  usage:  etopen(s,irq,addr,ioaddr)
  336. ;           char s[6];       ethernet address
  337. ;           int irq,addr,ioaddr;     
  338. ;                interrupt number, base mem address (unused) and
  339. ;                i/o address to use
  340. ;
  341. ;  _c5_init
  342. ;    Initialize the board, etc.
  343. ;
  344. ;  Arguments:
  345. a_ethadr   equ     x             ; ethernet address
  346. a_irq      equ     a_ethadr+4    ; Interrupt request level (int)
  347. a_seg      equ     a_irq+2       ; Shared segment address (int)
  348. a_ioadr    equ     a_seg+2       ; IO address (int)
  349. ;
  350. ifdef Microsoft
  351. _E5etopen  proc   far
  352. else
  353. E5ETOPEN    PROC    FAR
  354. endif
  355.           push     bp          ; save bp
  356.           mov     bp,sp          ; bp -> return, parameters
  357.           push     ds          ; save ds
  358.           push     es          ; save es
  359.           push     si          ; save si
  360.           push     di          ; save di
  361. ifdef Microsoft
  362.           mov     ax, seg _c5_droptot     ; ax -> data segment
  363. else
  364.           mov     ax, seg c5_droptot      ; ax -> data segment
  365. endif
  366.           mov     ds, ax                  ; ds -> data segment
  367.           mov     kseghere, ax
  368.           
  369.           mov     ax, seg _DATA
  370.           mov     ksegdata, ax
  371.           
  372.           mov     ax, seg bios_data
  373.           mov     ksegbios, ax
  374.           
  375.           mov     es, ksegbios            ; es -> bios data segment
  376.  
  377.           mov     ax, [bp+a_irq]          ; interrupt level -> ax
  378.           mov     irq, ax                 ; save interrupt level
  379.  
  380.           mov     ax, [bp+a_ioadr]        ; IO address -> ax
  381.           mov     ioadr, ax               ; save IO address
  382.           mov     ax, ioadr               ; 3C505 IO address -> ax
  383.           mov     ecommand, ax            ; save command address
  384.  
  385.           add     ax, 2                   ; status address -> ax
  386.           mov     estatus, ax             ; save status address
  387.  
  388.           mov     eauxdma, ax             ; save aux dma address
  389.           
  390.           add     ax, 2                   ; data address -> ax
  391.           mov     edata, ax               ; save data address
  392.  
  393.           add     ax, 2                   ; control address -> ax
  394.           mov     econtrol, ax            ; save control address
  395.  
  396.           cli                             ; disable interrupts
  397.  
  398. ; Set up the 8259 interrupt controller chip to what the 3c505 board is 
  399. ; set at.
  400.  
  401.           
  402.           mov     ax, irq                 ; interrupt level -> ax
  403.           cmp     ax, 8                   ; which 8259?
  404.           jge     o_1                     ; 8259 2
  405.           
  406.           mov     bx, ax                  ; irq -> bx
  407.           or      ax, EOI                 ; 8259 1: make first EOI command
  408.           mov     eoi1, ax                ; save first EOI command
  409.           mov     eoi2, 0                 ; no second EOI command
  410.           mov     imr, IMR1               ; mask is in IMR1
  411.           add     bx, VEC1                ; interrupt vector number -> bx
  412.           mov     vec, bx                 ; save vector number
  413.           jmp     SHORT o_2                     ; skip 8259 2 case
  414.  
  415.        ; 8259 2: just keep low 8 bits of interrupt number
  416. o_1:
  417.           and     ax, 07Q
  418.           mov     bx, ax                  ; interrupt on 8259 -> bx
  419.           or      ax, EOI                 ; put in EOI command
  420.           mov     eoi2, ax                ; save second EOI command
  421.           mov     eoi1, EOI+2             ; first EOI releases second
  422.           mov     imr, IMR2               ; mask is in IMR2
  423.           add     bx, VEC2                ; interrupt vector number -> bx
  424.           mov     vec, bx                 ; save vector number
  425.           mov     dx, IOCWR2              ; dx -> command register 2
  426.           out     dx, al                  ; do EOI 2 just in case
  427.  
  428. o_2:
  429.           mov     ax, eoi1                ; EOI 1 command -> ax
  430.           mov     dx, IOCWR1              ; dx -> command register 1
  431.           out     dx, al                  ; do EOI 1 just in case
  432.           mov     ax, vec                 ; vector number -> ax
  433.  
  434. ; Install the interrupt handler.
  435.  
  436.           call    IINST
  437.           
  438. ; Save the old interrupt mask of the 8259 chip and then turn it on.
  439.  
  440.           mov     cx, irq                 ; interrupt level -> cx
  441.           and     cx, 07q                 ; just keep level on 8259
  442.           mov     ax, 1                   ; 1 -> ax
  443.           shl     ax, cl                  ; make interrupt mask
  444.           mov     maskbit, al             ; save mask bit
  445.           mov     dx, imr                 ; mask register address -> dx
  446.           in      al, dx                  ; get old mask
  447.           mov     savemask, al            ; save mask
  448.           mov     bl, maskbit             ; our interrupt bit -> bl
  449.           not     bl                      ; want to unmask it
  450.           and     al, bl                  ; combine with other interrupts
  451.           out     dx, al                  ; unmask our interrupt
  452.           sti                            ; turn interrupts on
  453.           
  454.  
  455. ;  Reset the 3c505 board - this takes about 15-20 seconds.
  456.  
  457.           mov     al, EC_ATTENTION OR EC_FLUSH_DATA; Master reset command -> al
  458.  
  459.           mov     dx, econtrol            ; dx -> control register
  460.           out     dx, al                  ; do reset
  461.           mov     ax, timer_low           ; current timer -> ax
  462.           add     ax, RESDEL              ; + time to wait
  463.  
  464. wlp1:
  465.           cmp     ax, timer_low           ; compare to current time
  466.           ja      wlp1                    ; wait for reset to propagate
  467.  
  468.           mov     al, EC_COMMAND_ENABLE   ; command interrupt enable -> al
  469.           mov     lastcon, al             ; save last command
  470.           out     dx, al                  ; release reset
  471.           mov     ax, timer_low           ; current timer -> ax
  472.           add     ax, RESDEL              ; + time to wait
  473.  
  474. wlp2:
  475.           cmp     ax, timer_low           ; compare to current time
  476.           ja      wlp2                    ; wait for CPU to start reset
  477.           mov     bx, timer_low           ; current timer -> ax
  478.           add     bx, RESTO               ; + time out
  479.  
  480. wlp3:
  481.           call     getstat                     ; get status
  482.  
  483.           and     ax, ES_FLAG1 OR ES_FLAG2     ; just keep flags
  484.           cmp     ax, ES_FLAG1 OR ES_FLAG2     ; both on?
  485.           jne     resdone                      ; no:  reset completed
  486.  
  487.           cmp     bx, timer_low                ; have we waited too long?
  488.           ja      wlp3                         ; no
  489.           jmp     SHORT openfail                     ; yes:  open failed
  490.  
  491. resdone:  
  492.  
  493. ; Set up the receive buffers.
  494.  
  495.           mov     rbufct, 0                ; clear buffer counter
  496.           mov     cr_length, 1600          ; buffer length:  1600
  497.  
  498. irb1:
  499.           mov     ax, rbufct               ; buffer counter -> ax
  500.           mov     cr_offset, ax            ; use buffer number for offset
  501.           inc     ax                       ; count buffer
  502.           mov     rbufct, ax               ; store buffer number
  503.           mov     ax, 10                   ; pcb length -> ax
  504.           mov     si, offset cr            ; si -> request
  505.  
  506.           call    outpcb                   ; pass pcb
  507.  
  508.           mov     ax, rbufct               ; buffer counter -> ax
  509.           cmp     ax, 10                   ; start 10 receives
  510.           jl     irb1                      ; loop if more buffers
  511.           
  512.           ; We use the same character string pointer for both of the
  513.           ; next two calls, so we don't adjust the stack pointer
  514.           ; until we're done.
  515.           
  516.           mov    ax, [bp+a_ethadr+2]
  517.           push   ax
  518.           mov    ax, [bp+a_ethadr]
  519.           push   ax
  520.  
  521. ; Get the hardware ethernet address.
  522.           
  523.           call   far ptr get_eth_addr
  524.           or     ax, ax
  525.           jz     callset
  526.           add    sp,4
  527.           jmp    SHORT openfail
  528. callset:          
  529.  
  530. ;  Set the 3c505 board to use that address
  531.  
  532.           call     far ptr _E5setaddr
  533.           add    sp, 4
  534.           or     ax, ax
  535.           jnz    openfail
  536.  
  537. ; Tell the 3c505 board to start receiving packets.
  538.  
  539.           
  540.           CALL      E5OPEN
  541. ;     ax = 0 E5open OK, ax = -1 then E5open failed
  542.           jmp     SHORT openx                    ; go return
  543.  
  544. openfail:
  545.           mov     ax, -1                   ; -1 -> ax, fail
  546.  
  547. openx:
  548.           pop     di                      ; restore di
  549.           pop     si                      ; restore si
  550.           pop     es                      ; restore es
  551.           pop     ds                      ; restore ds
  552.           pop     bp                      ; restore bp
  553.           ret
  554. ifdef Microsoft
  555. _E5etopen      endp
  556. else
  557. E5ETOPEN    ENDP
  558. endif
  559.  
  560.  
  561.  
  562.           subttl     _E5etDMA:    DMA request level.
  563.           page     +
  564.  
  565. ;******************************************************************
  566. ;  ETDMA
  567. ;     Initialize the DMA request level.
  568. ;
  569. ;  not needed at this time
  570. ;
  571. a_dma      equ     a_ioadr+2     ; DMA request level
  572. ;
  573. ifdef Microsoft
  574. _E5etdma  proc     far
  575. else
  576. E5ETDMA  PROC  FAR
  577. endif
  578.  
  579.           push     bp          ; save bp
  580.           mov     bp,sp          ; bp -> return, parameters
  581.  
  582.           push     ds                     ; save ds
  583. ifdef Microsoft
  584.           mov     ax, seg _c5_droptot           ; ax -> data segment
  585. else
  586.           mov     ax, seg c5_droptot           ; ax -> data segment
  587. endif
  588.           mov     ds, ax
  589.           
  590.           mov     ax, seg bios_data
  591.           mov     ksegbios, ax
  592.  
  593.           mov     ax, [bp+a_dma]          ; DMA level -> ax
  594.           mov     dma, ax                 ; save IO address
  595.  
  596.           xor     ax, ax
  597.  
  598.           pop     ds                      ; restore ds
  599.  
  600.           pop     bp                      ; restore bp
  601.           ret
  602. ifdef Microsoft
  603. _E5etdma     endp
  604. else
  605. E5ETDMA   ENDP
  606. endif
  607.  
  608.  
  609.  
  610.  
  611.           subttl     open:  Open
  612.           page     +
  613. ;  This routine turns tells the 3c505 board to start receiving packets.
  614.  
  615. E5open       proc     near
  616.  
  617.           push     bp                     ; save bp
  618.           mov     bp, sp                  ; bp -> return, parameters
  619.           push     ds                     ; save ds
  620.           push     es                     ; save es
  621.           push     si                     ; save si
  622.           push     di                     ; save di
  623.                                           
  624. ifdef Microsoft
  625.           mov     ax, seg _c5_droptot           ; ax -> data segment
  626. else
  627.           mov     ax, seg c5_droptot           ; ax -> data segment
  628. endif
  629.           mov     ds, ax                  ; ds -> data segment
  630.           mov     es, ksegbios            ; es -> bios data segment
  631.           mov     si, offset cconc        ; si -> configure 82586 request
  632.           mov     ax, 4                   ; request length -> ax
  633.           mov     fconc, 0                ; clear response received flag
  634.           call    outpcb                  ; send the pcb
  635.  
  636.           mov     ax, timer_low           ; current time -> ax
  637.           add     ax, RESTO               ; + wait time
  638. op_1:
  639.           test    fconc, 0ffh             ; answered yet?
  640.           jnz     op_2                    ; yes
  641.  
  642.           cmp     ax, timer_low           ; expired?
  643.           ja      op_1                    ; no
  644.  
  645.           mov     ax, -1                  ; return fail
  646.           jmp     SHORT op_x                    ; go return
  647. op_2:
  648.           mov     ax, 0                   ; 0 -> ax, success
  649.  
  650. op_x:
  651.           pop     di                      ; restore di
  652.           pop     si                      ; restore si
  653.           pop     es                      ; restore es
  654.           pop     ds                      ; restore ds
  655.           pop     bp                      ; restore bp
  656.           ret               ; Just return
  657. E5open          endp
  658.  
  659.  
  660.           subttl     _E5etclose:  Close board
  661.           page     +
  662.  
  663. ;***********************************************************************
  664. ;  ETCLOSE
  665. ;        shut it down, remove the interrupt handler
  666. ;
  667. ;  usage:  etclose();
  668. ;
  669. ;
  670. ifdef Microsoft
  671. _E5ETCLOSE       PROC     FAR
  672. else
  673. E5ETCLOS     PROC      FAR
  674. endif
  675.      CLI
  676. ;
  677. ;
  678. ;  mask out IRQ on interrupt controller
  679. ;
  680.      push ds
  681. ifdef Microsoft
  682.           mov     ax, seg _c5_droptot           ; ax -> data segment
  683. else
  684.           mov     ax, seg c5_droptot           ; ax -> data segment
  685. endif
  686.      mov  ds, ax
  687.      MIN  imr                  ; get current mask
  688.      OR   AL, TURNOFF          ; force that bit on
  689.      OUT  DX, AL               ; send it back to controller
  690.      STI
  691.  
  692.      CALL  DEINST              ; restore old interrupt handler
  693.  
  694.      MOV   BL, savemask        ; get back saved setting of irq
  695.      NOT   BL                  ; flip it
  696.      
  697.      CLI
  698.      MIN   imr
  699.      AND   AL, BL              ; restore setting of that bit
  700.      OUT   DX, AL
  701.      STI     
  702.      
  703.      xor   ax, ax
  704.      pop   ds
  705.      RET
  706. ifdef Microsoft
  707. _E5ETCLOSE       ENDP
  708. else
  709. E5ETCLOS     ENDP
  710. endif
  711.  
  712.  
  713.           subttl     _c5_getaddr:  Get Ethernet address
  714.           page     +
  715.  
  716. ;*******************************************************************
  717. ;  GETADDR
  718. ;     get the Ethernet address off of the board (This gets called 
  719. ;        before E5etopen)
  720. ;
  721. ;   usage:  getaddr(s,address,ioaddr);
  722. ;    char s[6];           will get six bytes from the PROM
  723. ;       int address;    (unused here)
  724. ;       int ioaddr;     mem address and ioaddress to use
  725. ;
  726. ; _E5getaddr
  727. ;    Get Ethernet address
  728. ;
  729. ; Arguments:
  730.  
  731. a_eadr          equ     x          ; Ethernet address (far char *)
  732. ag_ioadr        equ     a_eadr + 6
  733. ifdef Microsoft
  734. _E5getaddr       proc     far
  735. else
  736. E5GETADD    PROC    FAR
  737. endif
  738.  
  739. ret
  740.  
  741. ifdef Microsoft
  742. _E5getaddr       endp
  743. else
  744. E5GETADD    ENDP
  745. endif
  746.  
  747.  
  748. get_eth_addr   proc far
  749. ;
  750. ; This was the old getaddr routine.  But, to advoid changing the Telnet
  751. ; source code i moved it here.  The interrupt handler has to be installed
  752. ; before this routine is used.
  753. ;
  754.           push     bp
  755.           mov     bp, sp                  ; bp -> return, parameters
  756.           push     ds
  757.           push     es
  758.           push     si
  759.           push     di
  760.  
  761. ifdef Microsoft
  762.           mov     ax, seg _c5_droptot           ; ax -> data segment
  763. else
  764.           mov     ax, seg c5_droptot           ; ax -> data segment
  765. endif
  766.           mov     ds, ax                  ; ds -> data segment
  767.           mov     es, ksegbios            ; es -> bios data segment
  768.  
  769.           mov     si, offset cgeth        ; si -> request ethernet address
  770.           mov     ax, 2                   ; request length -> ax
  771.           mov     fgeth, 0                ; clear response received flag
  772.  
  773.           call    outpcb                  ; send the pcb
  774.  
  775.           mov     ax, timer_low           ; current time -> ax
  776.           add     ax, RESTO               ; + wait time
  777. ga_1:
  778.           test    fgeth, 0ffh             ; answered yet?
  779.           jnz     ga_2                    ; yes
  780.  
  781.           cmp     ax, timer_low           ; expired?
  782.           ja      ga_1                    ; no;
  783.  
  784.           mov     ax, -1                  ; return fail
  785.           jmp     SHORT ga_x                    ; go return
  786.  
  787. ga_2:
  788.           cld
  789.           mov     di, [bp+a_eadr]         ; di -> destination offset
  790.           push    es                      ; save es
  791.           mov     es, [bp+a_eadr+2]       ; es -> destination segment
  792.           mov     si, offset rgeth_ad     ; si -> response
  793.           mov     cx, 6                   ; address length -> cx
  794.  
  795.           rep movsb                       ; return address
  796.  
  797.           pop     es
  798.           mov     ax, 0                   ; 0 -> ax, success
  799. ga_x:
  800.           pop     di
  801.           pop     si
  802.           pop     es
  803.           pop     ds
  804.           pop     bp
  805.           ret
  806.  
  807. get_eth_addr   endp
  808.           subttl     _c5_setaddr:  Set Ethernet address
  809.           page     +
  810.  
  811. ;******************************************************************
  812. ;  SETADDR
  813. ;    set the Ethernet address on the board to 6 byte ID code
  814. ;
  815. ;   usage:   setaddr(s,basea,ioa);
  816. ;             char s[6];           ethernet address to use
  817. ;             int basea;           shared memory base address (unused)
  818. ;             int ioa;             io address for board (unused)
  819. ;
  820. ; _c5_setaddr
  821. ; _E5setaddr
  822. ;    Set Ethernet address
  823. ;
  824. ; Arguments:
  825.  
  826. a_eadr          equ     x          ; Ethernet address (far char *)
  827.  
  828. ifdef Microsoft
  829. _E5setaddr       proc     far
  830. else
  831. E5SETADD    PROC    FAR
  832. endif
  833.  
  834.           push     bp
  835.           mov     bp, sp                  ; bp -> return, parameters
  836.           push     ds
  837.           push     es
  838.           push     si
  839.           push     di
  840.  
  841. ifdef Microsoft
  842.           mov     ax, seg _c5_droptot           ; ax -> data segment
  843. else
  844.           mov     ax, seg c5_droptot           ; ax -> data segment
  845. endif
  846.           mov     ds, ax                  ; ds -> data segment
  847.           mov     es, ksegbios            ; es -> bios data segment
  848.           push    es
  849.  
  850.           mov     di, offset cseth_ad     ; si -> command
  851.           mov     ax, seg cseth_ad        ; ax -> command segment
  852.           mov     es, ax                  ; es -> command segment
  853.           push    ds
  854.  
  855.           mov     si, [bp+a_eadr]         ; di -> destination offset
  856.           mov     ds, [bp+a_eadr+2]       ; es -> destination segment
  857.           mov     cx, 6                   ; address length -> cx
  858.  
  859.           rep movsb                       ; return address
  860.  
  861.           pop     ds
  862.           pop     es
  863.  
  864.           mov     si, offset cseth        ; si -> request ethernet address
  865.           mov     ax, 8                   ; request length -> ax
  866.           mov     fseth, 0                ; clear response received flag
  867.  
  868.           call    outpcb                  ; send the pcb
  869.  
  870.           mov     ax, timer_low           ; current time -> ax
  871.           add     ax, RESTO               ; + wait time
  872. sa_1:
  873.           test     fgeth, 0ffh            ; answered yet?
  874.           jnz     sa_2                    ; yes
  875.           
  876.           cmp     ax, timer_low           ; expired?
  877.           ja      sa_1                    ; no
  878.           
  879.           mov     ax, -1                  ; return fail
  880.           jmp     SHORT sa_x                    ; go return
  881. sa_2:
  882.           mov     ax,0                    ; 0 -> ax, success
  883. sa_x:
  884.           pop     di
  885.           pop     si
  886.           pop     es
  887.           pop     ds
  888.           pop     bp
  889.           ret
  890. ifdef Microsoft
  891. _E5setaddr       endp
  892. else
  893. E5SETADD    ENDP
  894. endif
  895.  
  896.           subttl     _c5_get_adapter_info:  Get adapter information
  897.           page     +
  898.           
  899. ; I don't have the information to use this routine
  900. ;
  901. ; _c5_get_adapter_info
  902. ;    Get adapter information
  903. ;
  904. ; Arguments:
  905.  
  906. a_adin    equ     x        ; Adapter information (far struct r_adapter_info *)
  907.  
  908. _c5_get_adapter_info     proc     far
  909.  
  910.           push     bp                     ; save bp
  911.           mov     bp, sp                  ; bp -> return, parameters
  912.           push     ds                     ; save ds
  913.           push     es                     ; save es
  914.           push     si                     ; save si
  915.           push     di                     ; save di
  916.           
  917. ifdef Microsoft
  918.           mov     ax, seg _c5_droptot           ; ax -> data segment
  919. else
  920.           mov     ax, seg c5_droptot           ; ax -> data segment
  921. endif
  922.           mov     ds, ax                  ; ds -> data segment
  923.           mov     es, ksegbios            ; es -> bios data segment
  924.           mov     si, offset cadin        ; si -> request adapter information
  925.           mov     ax, 2                   ; request length -> ax
  926.           mov     fadin, 0                ; clear response received flag
  927.  
  928.           call    outpcb                  ; send the pcb
  929.  
  930.           mov     ax, timer_low           ; current time -> ax
  931.           add     ax, RESTO               ; + wait time
  932. ai_1:     
  933.           test     fadin, 0ffh            ; answered yet?
  934.           jnz     ai_2                    ; yes
  935.  
  936.           cmp     ax, timer_low           ; expired?
  937.           ja      ai_1                    ; no
  938.  
  939.           mov     ax, -1                  ; return fail
  940.           jmp     SHORT ai_x                    ; go return
  941. ai_2:     
  942.           mov     di, [bp+a_adin]         ; di -> destination offset
  943.           push     es                     ; save es
  944.           mov     es, [bp+a_adin+2]       ; es -> destination segment
  945.           mov     si, offset radin        ; si -> response
  946.           mov     cx, 12                  ; address length -> cx
  947.  
  948.           rep movsb                       ; return address
  949.  
  950.           pop     es                      ; restore es
  951.           mov     ax, 0                   ; 0 -> ax, success
  952. ai_x:     
  953.           pop     di                      ; restore di
  954.           pop     si                      ; restore si
  955.           pop     es                      ; restore es
  956.           pop     ds                      ; restore ds
  957.           pop     bp                      ; restore bp
  958.           ret                           ; return
  959. _c5_get_adapter_info     endp
  960.  
  961.  
  962.           subttl     _c5_get_statistics:  Get statistics
  963.           page     +
  964.  
  965. ; I don't have the information to use this routine
  966. ;
  967. ; _c5_get_statistics
  968. ;    Get network statistics
  969. ;
  970. ; Arguments:
  971.  
  972. a_stat          equ     x          ; Statistics (far struct r_statistics *)
  973.  
  974. _c5_get_statistics     proc     far
  975.  
  976.           push     bp                     ; save bp
  977.           mov     bp, sp                  ; bp -> return, parameters
  978.           push     ds                     ; save ds
  979.           push     es                     ; save es
  980.           push     si                     ; save si
  981.           push     di                     ; save di
  982.           
  983. ifdef Microsoft
  984.           mov     ax, seg _c5_droptot           ; ax -> data segment
  985. else
  986.           mov     ax, seg c5_droptot           ; ax -> data segment
  987. endif
  988.           mov     ds, ax                  ; ds -> data segment
  989.           mov     es, ksegbios            ; es -> bios data segment
  990.           mov     si, offset cstat        ; si -> request statistics
  991.           mov     ax, 2                   ; request length -> ax
  992.           mov     fstat, 0                ; clear response received flag
  993.           
  994.           call    outpcb                  ; send the pcb
  995.           
  996.           mov     ax, timer_low           ; current time -> ax
  997.           add     ax, RESTO               ; + wait time
  998. st_1:
  999.           test     fstat, 0ffh            ; answered yet?
  1000.           jnz     st_2                    ; yes
  1001.           
  1002.           cmp     ax, timer_low           ; expired?
  1003.           ja      st_1                    ; no
  1004.           
  1005.           mov     ax, -1                  ; return fail
  1006.           jmp     SHORT st_x                    ; go return
  1007. st_2:
  1008.           mov     di, [bp+a_stat]         ; di -> destination offset
  1009.           push     es                     ; save es
  1010.           mov     es, [bp+a_stat+2]       ; es -> destination segment
  1011.           mov     si, offset rstat        ; si -> response
  1012.           mov     cx, 18                  ; statistics length -> cx
  1013.  
  1014.           rep movsb                       ; return address
  1015.  
  1016.           pop     es                      ; restore es
  1017.           mov     ax, 0                   ; 0 -> ax, success
  1018. st_x:
  1019.           pop     di                      ; restore di
  1020.           pop     si                      ; restore si
  1021.           pop     es                      ; restore es
  1022.           pop     ds                      ; restore ds
  1023.           pop     bp                      ; restore bp
  1024.           ret                           ; return
  1025. _c5_get_statistics     endp
  1026.  
  1027.  
  1028.           subttl     _E5recv:  Receive message
  1029.           page     +
  1030.  
  1031. ;************************************************************************
  1032. ;   Receive
  1033. ;   This is a CPU hook for boards that must be polled before we can
  1034. ;   deliver packets into the receive buffer.  (i.e. no interrupts used)
  1035. ;
  1036. ;   The 3COM 3C505 version uses interrupts, so this routine is a NOP
  1037. ;   for this board.
  1038. ;
  1039. ;    usage:  recv();
  1040. ;
  1041. ifdef Microsoft
  1042. _E5RECV PROC    FAR
  1043. else
  1044. E5RECV    PROC    FAR
  1045. endif
  1046.  
  1047.     RET            ; for compatibility with other drivers
  1048.  
  1049. ifdef Microsoft
  1050. _E5RECV ENDP
  1051. else
  1052. E5RECV    ENDP
  1053. endif
  1054.  
  1055.  
  1056.  
  1057.  
  1058.           subttl     _c5_xmit:  Transmit message
  1059.           page     +
  1060.  
  1061. ;************************************************************************
  1062. ;  XMIT         
  1063. ;     send a packet to Ethernet
  1064. ;     Is not interrupt driven, just call it when you need it.
  1065. ;
  1066. ;  usage:   xmit(packet,count)
  1067. ;        char *packet;
  1068. ;        int count;
  1069. ;
  1070. ;   Takes a packet raw, Ethernet packets start with destination address,
  1071. ;   and puts it out onto the wire.  Count is the length of packet < 2048
  1072. ;
  1073. ;   checks for packets under the Ethernet size limit of 60 and handles them
  1074. ;
  1075. ; _c5_xmit
  1076. ; _E5xmit
  1077. ;    Transmit message
  1078. ;
  1079. ; Arguments:
  1080.  
  1081. a_xaddr          equ     x          ; Pointer to buffer (far char *--must beeven)
  1082. a_xlength     equ     a_xaddr+4     ; Length in bytes (int)
  1083.  
  1084. ifdef Microsoft
  1085. _E5xmit     proc     far
  1086. else
  1087. E5XMIT    PROC    FAR
  1088. endif
  1089.  
  1090.           push     bp
  1091.           mov     bp, sp                  ; bp -> return, parameters
  1092.           push     ds
  1093.           push     es
  1094.           push     si
  1095.           push     di
  1096.  
  1097. ifdef Microsoft
  1098.           mov     ax, seg _c5_droptot           ; ax -> data segment
  1099. else
  1100.           mov     ax, seg c5_droptot           ; ax -> data segment
  1101. endif
  1102.           mov     ds, ax                  ; ds -> data segment
  1103.           mov     es, ksegbios            ; es -> bios data segment
  1104.           mov     ax, [bp+a_xaddr]        ; ax -> buffer offset
  1105.           mov     cx_offset, ax           ; put in request
  1106.           mov     ax, [bp+a_xaddr+2]      ; ax -> buffer segment
  1107.           mov     cx_segment, ax          ; put in request
  1108.  
  1109.           mov     ax, [bp+a_xlength]      ; message length -> ax
  1110.           cmp     ax, 60                  ; is buffer too short?
  1111.           jg      xm_4                    ; no
  1112.  
  1113.           mov     ax, 60                  ; yes:  pad with garbage
  1114. xm_4:
  1115.           inc     ax                      ; round up
  1116.           sar     ax, 1                   ; divide by 2
  1117.           shl     ax, 1                   ; multiply by 2
  1118.           mov     cx_length, ax           ; put in request
  1119.           mov     fxmit, 0                ; clear transmit done flag
  1120.           mov     si, offset cxmit        ; si -> request
  1121.           mov     ax, 8                   ; request length -> ax
  1122.  
  1123.           call    outpcb                  ; send command
  1124.  
  1125.           mov     bx, estatus             ; bx -> status register
  1126.           mov     dx, edata               ; dx -> data register
  1127.           mov     cx, cx_length           ; length -> cx
  1128.           sar     cx, 1                   ; convert to words
  1129.           mov     si, cx_offset           ; offset -> si
  1130.           push     ds
  1131.           mov     ds, cx_segment          ; segment -> ds
  1132. xm_1:
  1133.           lodsw                           ; next word -> ax
  1134.           out     dx, ax                  ; output it
  1135.           xchg    dx, bx                  ; dx -> status register
  1136. xm_2:
  1137.           in      al, dx                  ; get status
  1138.           test    al, ES_DATA_READY       ; ready for next word?
  1139.           jz      xm_2                    ; no
  1140.           
  1141.           xchg    dx, bx                  ; dx -> data register
  1142.           dec     cx                      ; count word
  1143.           jnz     xm_1                    ; loop through buffer
  1144.           
  1145.           pop     ds
  1146. xm_3:
  1147.           test    fxmit, 0ffh             ; has transmit completed?
  1148.           jz      xm_3                    ; no
  1149.           
  1150.           mov     ax, rx_status           ; return status
  1151. xm_x:
  1152.           pop     di
  1153.           pop     si
  1154.           pop     es
  1155.           pop     ds
  1156.           pop     bp
  1157.           ret
  1158. ifdef Microsoft
  1159. _E5xmit     endp
  1160. else
  1161. E5XMIT    ENDP
  1162. endif
  1163.  
  1164.  
  1165.           subttl     _c5_update:  Update receive buffer pointer
  1166.           page     +
  1167.  
  1168.  
  1169. ;*************************************************************************
  1170. ;  ETUPDATE
  1171. ;      update pointers and/or restart receiver when read routine has
  1172. ;      already removed the current packet
  1173. ;
  1174. ;   usage:  etupdate();
  1175. ;
  1176. ; _c5_update
  1177. ; _E5etupdate
  1178. ;    Update receive buffer pointer
  1179. ;
  1180. ;************  needs much more work to use with Lattice C
  1181. ;
  1182. ifdef Microsoft
  1183. _E5etupdate     proc     far
  1184. else
  1185. E5ETUPDA    PROC    FAR
  1186. endif
  1187.           
  1188.           push     bp
  1189.           mov     bp, sp                  ; bp -> return, parameters
  1190.           push     ds
  1191.           push     es
  1192.           push     si
  1193.           push     di
  1194.           push     cx
  1195.           
  1196. ifdef Microsoft
  1197.           mov     ax, seg _c5_droptot           ; ax -> data segment
  1198. else
  1199.           mov     ax, seg c5_droptot         ; ax -> data segment
  1200. endif
  1201.           mov     ds, ax
  1202.           mov     es, ksegbios               ; es -> bios data segment
  1203.           push    es                         ; save es
  1204.           
  1205.           mov     ds, ksegdata          
  1206.           les     di, dword ptr _bufread     ; es/di -> start of message
  1207.           mov     ax, es:[di]                ; message length -> ax
  1208.           pop     es
  1209.           add     di, ax                     ; advance by message length
  1210.           add     di, 2                      ; + 2 for message length
  1211.           cmp     di, _bufend                ; passed end?
  1212.           jb      up_1                       ; no
  1213.           
  1214.           mov     di, _buforg             ; yes:  start over
  1215.           inc     _c5_wrapct              ; count wraparound
  1216. up_1:     
  1217.           mov     _bufread, di         ; store pointer
  1218.           
  1219.           cli                             ; protect bufbig
  1220.           mov     bx, _bufbig          ; amount of buffer in use -> bx
  1221.           sub     bx, ax                  ; - size just released
  1222.           sub     bx, 2                   ; - 2 for message size
  1223.           mov     _bufbig, bx          ; store size left
  1224.           sti                             ; release bufbig
  1225.           
  1226.           cli                             ; protect drop count
  1227.           mov     ax, rdropnew            ; messages dropped recently -> ax
  1228.           mov     rdropnew, 0             ; clear drop count
  1229.           sti                             ; release interrupts
  1230.           
  1231.           inc     ax                      ; + 1 for buffer released
  1232.           mov     ax, newstart            ; = number to start
  1233. up_2:
  1234.           mov     ax, rbufct              ; buffer counter -> ax
  1235.           mov     cr_offset, ax           ; use buffer number for offset
  1236.           inc     ax                      ; count buffer
  1237.           mov     rbufct, ax              ; store buffer number
  1238.           mov     ax, 10                  ; pcb length -> ax
  1239.           mov     si, offset cr           ; si -> request
  1240.           
  1241.           call     outpcb                 ; pass pcb
  1242.           
  1243.           dec     newstart                ; count receive started
  1244.           jg     up_2                     ; loop if more buffers
  1245. up_x:
  1246.           pop     cx
  1247.           pop     di
  1248.           pop     si
  1249.           pop     es
  1250.           pop     ds
  1251.           pop     bp
  1252.           ret
  1253. ifdef Microsoft
  1254. _E5etupdate     endp
  1255. else
  1256. E5ETUPDA    ENDP
  1257. endif
  1258.  
  1259.  
  1260.           subttl     getstat:  Get board status
  1261.           page     +
  1262. ; Get board status, waiting for it to become stable
  1263. ;
  1264. ; Return:
  1265. ;   al = status
  1266.  
  1267. getstat          proc     near
  1268.  
  1269.           push     bx
  1270.           push     dx
  1271.           
  1272.           mov     dx, estatus             ; dx -> status register
  1273. gs_1:
  1274.           in     al, dx                   ; status -> al
  1275.           mov     bl, al                  ; status -> bl
  1276.           in      al, dx                  ; status -> al
  1277.           cmp     al, bl                  ; same both times?
  1278.           jne     gs_1                    ; No:  try again
  1279.           
  1280.           pop     dx
  1281.           pop     bx
  1282.           ret
  1283. getstat          endp
  1284.  
  1285.  
  1286.  
  1287.           subttl     outpcb:  Send PCB to board
  1288.           page     +
  1289. ; Send pcb to board, retry until accepted
  1290. ;
  1291. ; Entry:
  1292. ;   ax = number of bytes in pcb
  1293. ;   si = address of pcb
  1294.  
  1295. outpcb          proc     near
  1296.  
  1297.           mov     pcblen, ax                   ; save pcb length
  1298.           mov     pcbad, si                    ; save pcb address
  1299.  
  1300. ob_1:
  1301.           mov     cx, pcblen                   ; length -> cx
  1302.           mov     si, pcbad                    ; address -> si
  1303.           
  1304.           cli                                      ; Protect last command
  1305.           mov     al, lastcon                      ; last command -> ax
  1306.           and     al, NOT (EC_FLAG1 OR EC_FLAG2)   ; clear flags
  1307.           mov     lastcon, al                      ; save lastcom
  1308.           sti                                      ; enable interrupts
  1309.           
  1310.           mov     dx, econtrol                 ; dx -> control register
  1311.           out     dx, al                       ; send control
  1312.           mov     dx, ecommand                 ; dx -> command register
  1313.           
  1314. ob_2:
  1315.           mov     al, [si]                     ; next command byte -> al
  1316.           out     dx, al                       ; send command byte
  1317.           mov     bx, timer_low                ; current timer -> ax
  1318.           add     bx, CMDBTO                   ; + time out
  1319.           
  1320. wlp4:
  1321.           call     getstat                     ; get status
  1322.           
  1323.           and     al, ES_HOST_COMMAND_EMPTY    ; has command been taken?
  1324.           jne     ob_3                         ; yes:  go on
  1325.           
  1326.           cmp     bx, timer_low                ; have we waited too long?
  1327.           ja     wlp4                          ; no
  1328.           
  1329.           jmp     SHORT cmdretry                     ; go retry command
  1330.           
  1331.           
  1332. ob_3:
  1333.           inc     si                           ; increment source pointer
  1334.           dec     cx                           ; count byte
  1335.           jg     ob_2                          ; loop if more bytes
  1336.           
  1337.           mov     dx, econtrol                 ; dx -> control register
  1338.           
  1339.           cli                                  ; disable interrupts
  1340.           mov     al, lastcon                  ; last control -> al
  1341.           or     al, (EC_FLAG1 OR EC_FLAG2)    ; set end of command
  1342.           mov     lastcon, al                  ; save lastcon
  1343.           out     dx, al                       ; send flag bits
  1344.           
  1345.           mov     dx, ecommand                 ; dx -> command register
  1346.           mov     ax, pcblen                   ; pcb length -> ax
  1347.           out     dx, al                       ; send pcb length
  1348.           sti                                  ; enable interrupts
  1349.           
  1350.           
  1351.           mov     bx, timer_low                ; current time -> bx
  1352.           add     bx, CMDCTO            ; + time out for command to be accepted
  1353. wlp5:
  1354.           call     getstat                     ; get status
  1355.           
  1356.           and     al, (ES_FLAG1 OR ES_FLAG2)   ; just keep status flags
  1357.           cmp     al, 1                        ; accepted?
  1358.           je     cmdaccept                     ; yes
  1359.           
  1360.           cmp     al, 2                        ; rejected?
  1361.           je     cmdretry                      ; yes
  1362.           
  1363.           cmp     bx, timer_low                ; have we waited too long?
  1364.           ja     wlp5                          ; no
  1365.           
  1366. cmdretry:
  1367.           mov     ax, timer_low                ; current time -> ax
  1368.           add     ax, RETRYDELAY               ; + retry delay
  1369. wlp6:
  1370.           cmp     ax, timer_low                ; have we waited long enough?
  1371.           ja     wlp6                          ; no
  1372.           
  1373.           jmp     ob_1                         ; go do retry
  1374.           
  1375. cmdaccept:
  1376.           cli                                    ; protect last control
  1377.           mov     al, lastcon                    ; last control -> al
  1378.           and     al, NOT (EC_FLAG1 OR EC_FLAG2) ; turn off end of command flag
  1379.           mov     lastcon, al                    ; save last control
  1380.           sti                                    ; reenable interrupts
  1381.           
  1382.           mov     dx, econtrol                 ; dx -> control register
  1383.           out     dx, al                       ; pass control byte
  1384.           mov     ax, 0                        ; return 0, success
  1385.           ret
  1386. outpcb          endp
  1387.  
  1388.  
  1389.           subttl     Interrupt routine
  1390.           page     +
  1391.  
  1392. ;*************************************************************************
  1393. ;  Interrupt Handler
  1394. ;  installation and deinstallation
  1395. ;
  1396. ;     the handler takes the receive packet out of the input buffer
  1397. ;
  1398. DEINST     PROC     NEAR
  1399.      push ds
  1400.      
  1401.      MOV  ax, vec                  ; interrupt in table for 3com board
  1402.      MOV  dx, oldioff              ; get old ip from save spot
  1403.      MOV  ds, oldiseg              ; get old cs from save spot
  1404.      mov  ah, 25h
  1405.      int  21h
  1406.  
  1407.      POP  DS
  1408.      RET
  1409. DEINST     ENDP
  1410.  
  1411.  
  1412. ;
  1413. IINST     PROC     NEAR
  1414.  
  1415.      MOV  CS:MYDS, DS              ; store for use by handler
  1416.  
  1417.      PUSH DS
  1418.      push es
  1419.      push bx
  1420.      
  1421.      mov  ax, vec                  ; get the current interupt vector
  1422.      mov  ah, 35h                  ; that we are using.
  1423.      int  21h
  1424.      
  1425.      mov  oldioff, bx              ; save the vector for later
  1426.      mov  oldiseg, es
  1427.      
  1428.      mov  dx, offset IHAND         ; set our interupt vector
  1429.      mov  ax, vec
  1430.      MOV  BX, CS
  1431.      MOV  DS, BX
  1432.      mov  ah, 25h
  1433.      int  21h
  1434.      
  1435.      pop  bx
  1436.      pop  es
  1437.      POP  DS
  1438.  
  1439.      RET
  1440.      
  1441. MYDS  DW 00H                     ; the data segment for this assembly code
  1442. ICNT  DB 00H
  1443.  
  1444. IHAND:                           ; not a public name, only handles ints
  1445.  
  1446.           push     ds
  1447.           push     es
  1448.           push     si
  1449.           push     di
  1450.           push     bp
  1451.           push     ax
  1452.           push     bx
  1453.           push     cx
  1454.           push     dx
  1455.           
  1456.           sti                             ; let other interrupts come in
  1457.           cld                             ; increment
  1458.  
  1459. ifdef Microsoft
  1460.           mov     ax, seg _c5_droptot           ; ax -> data segment
  1461. else
  1462.           mov     ax, seg c5_droptot           ; ax -> data segment
  1463. endif
  1464.           mov     ds, ax                  ; ds -> data segment
  1465.  
  1466.  
  1467. ; Check to see if we have a command in the command register
  1468.  
  1469. icmdc:
  1470.           mov     dx, estatus                   ; dx -> status register
  1471.           in      al, dx                        ; status -> al
  1472.           and     al, ES_ADAPTER_COMMAND_FULL   ; command register full?
  1473.           jnz     icmd0                         ; yes
  1474.           
  1475.           inc     _c5_nocmd              ; count no command
  1476.           jmp     ir_y                   ; no:  no more commands this interrupt
  1477.           
  1478. ; Yes we may have something.  Clear the flags and then check to see if 
  1479. ; we really have something.
  1480.  
  1481. icmd0:
  1482.           mov     bx, timer_low                    ; current time -> bx
  1483.           add     bx, RCMDTO                       ; + time to wait
  1484.           mov     al, lastcon                      ; last control -> ax
  1485.           and     al, NOT (EC_FLAG1 OR EC_FLAG2)   ; clear flags
  1486.           mov     lastcon, al                      ; save last control
  1487.           mov     dx, econtrol                     ; dx -> control register
  1488.           out     dx, al                      ; clear flags in control register
  1489.  
  1490. ;----------------------------------------------------------------------------
  1491. ; This loop stores the command from the 3c505 board into the icmdb buffer.
  1492. ;
  1493.           mov   di, offset icmdb               ; di -> incoming command buffer
  1494. icmd1:    
  1495.           mov   dx, estatus                    ; dx -> status register
  1496.           in    al, dx                         ; status -> al
  1497.           mov   cx, ax                         ; status -> cx
  1498.           test  al, ES_ADAPTER_COMMAND_FULL    ; command register full?
  1499.           jnz   icmd2                          ; yes
  1500.           
  1501.           cmp   bx, timer_low                  ; have we waited too long?
  1502.           ja    icmd1                          ; no
  1503.           
  1504.           inc   _c5_cmdito                     ; count time out
  1505.           jmp   ir_x                           ; yes:  give up
  1506.           
  1507. ;      Yes we REALLY do have a command waiting from the 3c505 board.
  1508. icmd2:
  1509.           mov     dx, ecommand               ; dx -> command register
  1510.           in      al, dx                     ; get command byte
  1511.           and     cl, ES_FLAG1 OR ES_FLAG2   ; just keep flags
  1512.           cmp     cl, ES_FLAG1 OR ES_FLAG2   ; are both on?
  1513.           je      icmd3                      ; yes:  end of command
  1514.           
  1515.           mov     [di], al                   ; save byte
  1516.           inc     di                         ; increment pointer
  1517.           mov     ax, di                     ; current pointer -> ax
  1518.           sub     ax, offset icmdb           ; - start of buffer
  1519.           cmp     ax, CBS                    ; full?
  1520.           jl      icmd1                      ; no
  1521.           
  1522.           mov     si, (offset icmdb) + CBSH  ; si -> middle of buffer
  1523.           mov     di, offset icmdb           ; di -> start of buffer
  1524.           mov     cx, CBSH                   ; size of half buffer -> cx
  1525.           PUSH    ds
  1526.           POP     es
  1527.           rep movsb                          ; move buffer up
  1528.           jmp     icmd1                      ; loop for another byte
  1529.  
  1530. ;-------------------------------------------------------------------------
  1531. ; We've gotten the command from the board.
  1532.           
  1533. icmd3:    
  1534.           push    ds
  1535.           pop     es                      ; es -> segment of command area
  1536.           mov     ah, 0                   ; clear high byte of length
  1537.           mov     cmdlen, ax              ; save command length
  1538.           mov     si, di                  ; si -> command buffer
  1539.           sub     si, cmdlen              ; back up to start of command
  1540.           mov     di, offset icmd         ; di -> command area
  1541.           mov     cx, cmdlen              ; command length -> cx
  1542.           
  1543.           rep movsb                       ; move command
  1544.           
  1545.           mov     al, icmd                ; first byte of command -> al
  1546.           cmp     al, 32h                 ; configure 82586?
  1547.           je     ic_conc                  ; yes
  1548.           
  1549.           cmp     al, 33h                 ; get Ethernet address?
  1550.           je     ic_geth                  ; yes
  1551.           
  1552.           cmp     al, 38h                 ; receive complete?
  1553.           je     ic_rec                   ; yes
  1554.           
  1555.           cmp     al, 39h                 ; transmit complete?
  1556.           je      ic_xmit                 ; yes
  1557.           
  1558.           cmp     al, 3ah                 ; statistics response?
  1559.           je     ic_stat                  ; yes
  1560.           
  1561.           cmp     al, 40h                 ; set Ethernet address complete?
  1562.           jne     ic_j4                   ; no
  1563.           
  1564.           jmp     ic_seth                 ; yes
  1565.           
  1566. ic_j4:    
  1567.           cmp     al, 41h                 ; adapter information response?
  1568.           jne     ic_j5                   ; no
  1569.           
  1570.           jmp     ic_adin                 ; yes
  1571.           
  1572. ic_j5:    
  1573.           jmp     ir_x                    ; other:  just ignore it
  1574.           
  1575. ic_conc:  
  1576.           push    ds
  1577.           pop     es                   ; es -> configure 82586 response segment
  1578.           mov     si, offset icmd      ; si -> command received
  1579.           mov     di, offset rconc     ; di -> configure 82586 response
  1580.           mov     cx, 2                ; response length -> cx
  1581.           
  1582.           rep movsw                    ; move response
  1583.           
  1584.           mov     fconc, 1             ; flag response received
  1585.           jmp     ir_x                 ; go return from interrupt
  1586.           
  1587. ic_geth:  
  1588.           push    ds
  1589.           pop     es                  ; es -> Ethernet address response segment
  1590.           mov     si, offset icmd     ; si -> command received
  1591.           mov     di, offset rgeth    ; di -> Ethernet address response
  1592.           mov     cx, 4               ; response length -> cx
  1593.           
  1594.           rep movsw                   ; move response
  1595.           
  1596.           mov     fgeth, 1            ; flag response received
  1597.           jmp     ir_x                ; go return from interrupt
  1598.           
  1599. ic_xmit:  
  1600.           push    ds
  1601.           pop     es                      ; es -> transmit response segment
  1602.           mov     si, offset icmd         ; si -> command received
  1603.           mov     di, offset rxmit        ; di -> transmit response
  1604.           mov     cx, 5                   ; response length -> cx
  1605.           
  1606.           rep movsw                       ; move response
  1607.           
  1608.           mov     fxmit, 1                ; flag response received
  1609.           jmp     ir_x                    ; go return from interrupt
  1610.           
  1611. ic_stat:  
  1612.           push    ds
  1613.           pop     es                      ; es -> statistics response segment
  1614.           mov     si, offset icmd         ; si -> command received
  1615.           mov     di, offset rstat        ; di -> statistics response
  1616.           mov     cx, 5                   ; response length -> cx
  1617.           
  1618.           rep movsw                       ; move response
  1619.           
  1620.           mov     fstat, 1                ; flag response received
  1621.           jmp     ir_x                    ; go return from interrupt
  1622.           
  1623. ic_rec:   
  1624.           push    ds
  1625.           pop     es                      ; es -> receive response segment
  1626.           mov     si, offset icmd         ; si -> command received
  1627.           mov     di, offset rr           ; di -> receive response
  1628.           mov     cx, 9                   ; response length -> cx
  1629.           
  1630.           rep movsw                       ; move response
  1631.           
  1632.           push    ds
  1633.           mov     ds, ksegdata
  1634.           mov     ax, _buflim             ; buffer size -> ax
  1635.           sub     ax, _bufbig             ; - amount in use
  1636.           pop     ds
  1637.           sub     ax, rr_dmalen              ; - size of new message
  1638.           jl      ir_drop                    ; no room--drop it
  1639.           
  1640.           push    ds
  1641.           mov     ds, ksegdata
  1642.           les     di, dword ptr _bufpt    ; es/di -> buffer position
  1643.           cmp     di, _bufend             ; have we passed restart point
  1644.           jb      icr_2                      ; no     
  1645.           
  1646.           mov     di, _buforg             ; yes:  start over
  1647. icr_2:    
  1648.           pop     ds
  1649.           mov     ax, rr_dmalen               ; message size -> ax
  1650.           inc     ax                          ; + 1 to round up
  1651.           shr     ax, 1                       ; convert to words
  1652.           shl     ax, 1                       ; convert back to characters
  1653.           mov     rr_dmalen, ax               ; use it to update bufbig
  1654.           stosw                      ; store message length at front of message
  1655.           mov     cx, ax                      ; message length -> cx
  1656.           shr     cx, 1                       ; convert to words
  1657.           mov     al, lastcon                 ; last control -> al
  1658.           or      al, EC_TO_HOST OR EC_FLAG1  ; set direction and acknowledge 
  1659.                                                      ; response
  1660.           mov     lastcon, al                 ; save last control
  1661.           mov     dx, econtrol                ; dx -> control register
  1662.           out     dx, al                      ; pass direction
  1663.           
  1664.           mov     dx, estatus              ; dx -> status register
  1665.           mov     bx, edata                ; bx -> data register
  1666. icr_1:    
  1667.           in      al, dx                   ; get status
  1668.           test    al, ES_DATA_READY        ; is data ready?
  1669.           jz      icr_1                    ; no
  1670.           xchg    dx, bx                   ; dx -> data register
  1671.           in      ax, dx                   ; data word -> ax
  1672.           stosw                            ; store word in buffer
  1673.           xchg    dx, bx                   ; dx -> status register
  1674.           dec     cx                       ; count word
  1675.           jnz     icr_1                    ; loop if more words
  1676.           
  1677.           mov     al, lastcon                      ; last control -> al
  1678.           and     al, NOT (EC_TO_HOST OR EC_FLAG1) ; change direction to output
  1679.           mov     lastcon, al                      ; save last control
  1680.           mov     dx, econtrol                     ; dx -> control register
  1681.           out     dx, al                  ; send control
  1682.           
  1683.           mov     ax, rr_dmalen           ; data length-> ax
  1684.           push    ds
  1685.           mov     ds, ksegdata
  1686.           mov     _bufpt, di              ; store pointer
  1687.           add     ax, _bufbig             ; + bytes in buffer 
  1688.           add     ax, 2                   ; + 2 for size
  1689.           mov     _bufbig, ax             ; save buffer in use
  1690.           pop     ds
  1691.           jmp     SHORT ir_x                    ; go return from interrupt
  1692. ir_drop:
  1693.           inc     _c5_droptot             ; count dropped message
  1694.           inc     rdropnew                ; count so another read gets started
  1695.           
  1696. ; eat the message
  1697.           mov     ax, rr_dmalen             ; message size -> ax
  1698.           inc     ax                        ; + 1 to round up
  1699.           shr     ax, 1                     ; convert to words
  1700.           shl     ax, 1                     ; convert back to characters
  1701.           mov     rr_dmalen, ax             ; use it to update bufbig
  1702.           stosw                             ; store message length at front 
  1703.                                                        ; of message
  1704.           mov     cx, ax                    ; message length -> cx
  1705.           shr     cx, 1                     ; convert to words
  1706.           mov     al, lastcon               ; last control -> al
  1707.           or     al, EC_TO_HOST OR EC_FLAG1 ; set direction and acknowledge 
  1708.                                                     ; response
  1709.           mov     lastcon, al               ; save last control
  1710.           mov     dx, econtrol              ; dx -> control register
  1711.           out     dx, al                    ; pass direction
  1712.           
  1713.           mov     dx, estatus               ; dx -> status register
  1714.           mov     bx, edata                 ; bx -> data register
  1715. icr_3:    
  1716.           in      al, dx                  ; get status
  1717.           test    al, ES_DATA_READY       ; is data ready?
  1718.           jz      icr_3                   ; no
  1719.           
  1720.           xchg    dx, bx                  ; dx -> data register
  1721.           in      ax, dx                  ; data word -> ax
  1722.           xchg    dx, bx                  ; dx -> status register
  1723.           dec     cx                      ; count word
  1724.           jnz     icr_3                   ; loop if more words
  1725.           
  1726.           mov     al, lastcon                      ; last control -> al
  1727.           and     al, NOT (EC_TO_HOST OR EC_FLAG1) ; change direction to output
  1728.           mov     lastcon, al                      ; save last control
  1729.           mov     dx, econtrol                     ; dx -> control register
  1730.           out     dx, al                           ; send control
  1731.           jmp     SHORT ir_x                             ; go return from interrupt
  1732.           
  1733. ic_seth:
  1734.           push    ds
  1735.           pop     es             ; es ->  set Ethernet address response segment
  1736.           mov     si, offset icmd         ; si -> command received
  1737.           mov     di, offset rseth        ; di -> set Ethernet address response
  1738.           mov     cx, 2                   ; response length -> cx
  1739.           
  1740.           rep movsw                       ; move response
  1741.           
  1742.           mov     fseth, 1                ; flag response received
  1743.           jmp     SHORT ir_x                    ; go return from interrupt
  1744.  
  1745. ic_adin:
  1746.           push    ds
  1747.           pop     es               ; es -> adapter information response segment
  1748.           mov     si, offset icmd    ; si -> command received
  1749.           mov     di, offset radin   ; di -> adapter information response
  1750.           mov     cx, 5              ; response length -> cx
  1751.           
  1752.           rep movsw                       ; move response
  1753.           
  1754.           mov     fadin, 1                ; flag response received
  1755.           jmp     SHORT ir_x                    ; go return from interrupt
  1756.           
  1757. ir_x:
  1758.           jmp     icmdc                   ; look for another interrupt
  1759.           
  1760. ir_y:
  1761.           mov     ax, eoi2                ; EOI command for 8259 2 -> ax
  1762.           jz     ir_1                     ; branch if none
  1763.           
  1764.           mov     dx, IOCWR2              ; dx -> 8259 2 command register
  1765.           out     dx, al                  ; do end of interrupt 2
  1766. ir_1:
  1767.           mov     ax, eoi1                ; EOI command for 8259 1 -> ax
  1768.           mov     dx, IOCWR1              ; dx -> 8259 1 command register
  1769.           out     dx, al                  ; do end of interrupt 1
  1770.           
  1771.           pop     dx
  1772.           pop     cx
  1773.           pop     bx
  1774.           pop     ax
  1775.           pop     bp
  1776.           pop     di
  1777.           pop     si
  1778.           pop     es
  1779.           pop     ds
  1780.           iret      
  1781. IINST     endp
  1782.  
  1783.  
  1784.  
  1785. NET505_text     ends
  1786.           end
  1787.  
  1788.  
  1789.