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