Subversion Repositories Kolibri OS

Rev

Rev 2434 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2465 Serge 3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
593 mikedld 8
$Revision: 2465 $
9
 
10
 
261 hidnplayr 11
;; Copyright (c) 2004, Endre Kozma 
12
;; All rights reserved.
13
;;
14
;; Redistribution  and  use  in  source  and  binary  forms, with or without
15
;; modification, are permitted provided  that  the following  conditions are
16
;; met:
17
;;
18
;; 1. Redistributions of source code must retain the above  copyright notice,
19
;;    this list of conditions and the following disclaimer.
20
;;
21
;; 2. Redistributions  in  binary form  must  reproduce  the above copyright
22
;;    notice, this  list of conditions  and the  following disclaimer in the
23
;;    documentation and/or other  materials  provided with  the distribution.
24
;;
25
;; 3. The name of the author may not be used to  endorse or promote products
26
;;    derived from this software without  specific prior  written permission.
27
;;
28
;; THIS SOFTWARE IS  PROVIDED  BY  THE  AUTHOR  ``AS IS'' AND ANY EXPRESS OR
29
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30
;; OF  MERCHANTABILITY AND FITNESS  FOR A PARTICULAR  PURPOSE ARE DISCLAIMED.
31
;; IN  NO  EVENT  SHALL  THE  AUTHOR  BE  LIABLE  FOR  ANY  DIRECT, INDIRECT,
32
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR  CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33
;; NOT LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34
;; DATA, OR  PROFITS; OR  BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON ANY
35
;; THEORY OF  LIABILITY, WHETHER IN  CONTRACT,  STRICT  LIABILITY,  OR  TORT
36
;; (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT OF THE USE OF
37
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
 
39
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40
;;                                                                         ;;
41
;;  3C59X.INC                                                              ;;
42
;;                                                                         ;;
43
;;  Ethernet driver for Menuet OS                                          ;;
44
;;                                                                         ;;
45
;;  Driver for 3Com fast etherlink 3c59x and                               ;;
46
;;         etherlink XL 3c900 and 3c905 cards                              ;;
47
;;  References:                                                            ;;
48
;;    www.3Com.com - data sheets                                           ;;
49
;;    DP83840A.pdf - ethernet physical layer                               ;;
50
;;    3c59x.c - linux driver                                               ;;
51
;;    ethernet driver template by Mike Hibbett                             ;;
52
;;                                                                         ;;
53
;;  Credits                                                                ;;
54
;;   Mike Hibbett,                                                         ;;
55
;;         who kindly supplied me with a 3Com905C-TX-M card                ;;
56
;;                                                                         ;;
57
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
58
;;  History
59
;;  =======
60
;;  $Log: 3C59X.INC,v $
61
;;  Revision 1.3  2004/07/11 12:21:12  kozma
62
;;  Support of vortex chips (3c59x) added.
63
;;  Support of 3c920 and 3c982 added.
64
;;  Corrections.
65
;;
66
;;  Revision 1.2  2004/06/12 19:40:20  kozma
67
;;  Function e3c59x_set_available_media added in order to set
68
;;  the default media in case auto detection finds no valid link.
69
;;  Incorrect mii check removed (3c900 Cyclone works now).
70
;;  Cleanups.
71
;;
72
;;  Revision 1.1  2004/06/12 18:27:15  kozma
73
;;  Initial revision
74
;;
75
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
76
 
77
; comment the next line out if you don't want debug info printed
78
; on the debug board. This option adds a lot of bytes to the driver
79
; so it's worth to comment it out.
80
;        E3C59X_DEBUG    equ 1
81
 
82
; forcing full duplex mode makes sense at some cards and link types
2434 Serge 83
        E3C59X_FORCE_FD equ 1
261 hidnplayr 84
 
85
macro virt_to_dma reg
86
{
2434 Serge 87
        sub     reg, OS_BASE
261 hidnplayr 88
}
89
 
90
macro dma_to_virt reg
91
{
2434 Serge 92
        add     reg, OS_BASE
261 hidnplayr 93
}
94
 
95
macro zero_to_virt reg
96
{
1280 hidnplayr 97
 
261 hidnplayr 98
}
99
 
100
macro virt_to_zero reg
101
{
1280 hidnplayr 102
 
261 hidnplayr 103
}
104
 
105
macro zero_to_dma reg
106
{
2434 Serge 107
        sub     reg, OS_BASE
261 hidnplayr 108
}
109
 
110
macro dma_to_zero reg
111
{
2434 Serge 112
        add     reg, OS_BASE
261 hidnplayr 113
}
114
 
115
macro strtbl name, [string]
116
{
117
common
2434 Serge 118
        label name dword
261 hidnplayr 119
forward
2434 Serge 120
        local label
121
        dd label
261 hidnplayr 122
forward
2434 Serge 123
        label db string, 0
261 hidnplayr 124
}
125
 
126
; Ethernet frame symbols
2434 Serge 127
        ETH_ALEN                       equ 6
128
        ETH_HLEN                       equ (2*ETH_ALEN+2)
129
        ETH_ZLEN                       equ 60 ; 60 + 4bytes auto payload for
130
                                              ; mininmum 64bytes frame length
261 hidnplayr 131
; PCI programming
2434 Serge 132
        PCI_REG_COMMAND                equ 0x4 ; command register
133
        PCI_REG_STATUS                 equ 0x6 ; status register
134
        PCI_REG_LATENCY                equ 0xd ; latency timer register
135
        PCI_REG_CAP_PTR                equ 0x34 ; capabilities pointer
136
        PCI_REG_CAPABILITY_ID          equ 0x0 ; capapility ID in pm register block
137
        PCI_REG_PM_STATUS              equ 0x4 ; power management status register
138
        PCI_REG_PM_CTRL                equ 0x4 ; power management control register
139
        PCI_BIT_PIO                    equ 0 ; bit0: io space control
140
        PCI_BIT_MMIO                   equ 1 ; bit1: memory space control
141
        PCI_BIT_MASTER                 equ 2 ; bit2: device acts as a PCI master
261 hidnplayr 142
; Registers
2434 Serge 143
        E3C59X_REG_POWER_MGMT_CTRL     equ 0x7c
144
        E3C59X_REG_UP_LIST_PTR         equ 0x38
145
        E3C59X_REG_UP_PKT_STATUS       equ 0x30
146
        E3C59X_REG_TX_FREE_THRESH      equ 0x2f
147
        E3C59X_REG_DN_LIST_PTR         equ 0x24
148
        E3C59X_REG_DMA_CTRL            equ 0x20
149
        E3C59X_REG_TX_STATUS           equ 0x1b
150
        E3C59X_REG_RX_STATUS           equ 0x18
151
        E3C59X_REG_TX_DATA             equ 0x10
261 hidnplayr 152
; Common window registers
2434 Serge 153
        E3C59X_REG_INT_STATUS          equ 0xe
154
        E3C59X_REG_COMMAND             equ 0xe
261 hidnplayr 155
; Register window 7
2434 Serge 156
        E3C59X_REG_MASTER_STATUS       equ 0xc
157
        E3C59X_REG_POWER_MGMT_EVENT    equ 0xc
158
        E3C59X_REG_MASTER_LEN          equ 0x6
159
        E3C59X_REG_VLAN_ETHER_TYPE     equ 0x4
160
        E3C59X_REG_VLAN_MASK           equ 0x0
161
        E3C59X_REG_MASTER_ADDRESS      equ 0x0
261 hidnplayr 162
; Register window 6
2434 Serge 163
        E3C59X_REG_BYTES_XMITTED_OK    equ 0xc
164
        E3C59X_REG_BYTES_RCVD_OK       equ 0xa
165
        E3C59X_REG_UPPER_FRAMES_OK     equ 0x9
166
        E3C59X_REG_FRAMES_DEFERRED     equ 0x8
167
        E3C59X_REG_FRAMES_RCVD_OK      equ 0x7
168
        E3C59X_REG_FRAMES_XMITTED_OK   equ 0x6
169
        E3C59X_REG_RX_OVERRUNS         equ 0x5
170
        E3C59X_REG_LATE_COLLISIONS     equ 0x4
171
        E3C59X_REG_SINGLE_COLLISIONS   equ 0x3
172
        E3C59X_REG_MULTIPLE_COLLISIONS equ 0x2
173
        E3C59X_REG_SQE_ERRORS          equ 0x1
174
        E3C59X_REG_CARRIER_LOST        equ 0x0
261 hidnplayr 175
; Register window 5
2434 Serge 176
        E3C59X_REG_INDICATION_ENABLE   equ 0xc
177
        E3C59X_REG_INTERRUPT_ENABLE    equ 0xa
178
        E3C59X_REG_TX_RECLAIM_THRESH   equ 0x9
179
        E3C59X_REG_RX_FILTER           equ 0x8
180
        E3C59X_REG_RX_EARLY_THRESH     equ 0x6
181
        E3C59X_REG_TX_START_THRESH     equ 0x0
261 hidnplayr 182
; Register window 4
2434 Serge 183
        E3C59X_REG_UPPER_BYTES_OK      equ 0xe
184
        E3C59X_REG_BAD_SSD             equ 0xc
185
        E3C59X_REG_MEDIA_STATUS        equ 0xa
186
        E3C59X_REG_PHYSICAL_MGMT       equ 0x8
187
        E3C59X_REG_NETWORK_DIAGNOSTIC  equ 0x6
188
        E3C59X_REG_FIFO_DIAGNOSTIC     equ 0x4
189
        E3C59X_REG_VCO_DIAGNOSTIC      equ 0x2 ; may not supported
261 hidnplayr 190
; Bits in register window 4
2434 Serge 191
        E3C59X_BIT_AUTOSELECT          equ 24
261 hidnplayr 192
; Register window 3
2434 Serge 193
        E3C59X_REG_TX_FREE             equ 0xc
194
        E3C59X_REG_RX_FREE             equ 0xa
195
        E3C59X_REG_MEDIA_OPTIONS       equ 0x8
196
        E3C59X_REG_MAC_CONTROL         equ 0x6
197
        E3C59X_REG_MAX_PKT_SIZE        equ 0x4
198
        E3C59X_REG_INTERNAL_CONFIG     equ 0x0
261 hidnplayr 199
; Register window 2
2434 Serge 200
        E3C59X_REG_RESET_OPTIONS       equ 0xc
201
        E3C59X_REG_STATION_MASK_HI     equ 0xa
202
        E3C59X_REG_STATION_MASK_MID    equ 0x8
203
        E3C59X_REG_STATION_MASK_LO     equ 0x6
204
        E3C59X_REG_STATION_ADDRESS_HI  equ 0x4
205
        E3C59X_REG_STATION_ADDRESS_MID equ 0x2
206
        E3C59X_REG_STATION_ADDRESS_LO  equ 0x0
261 hidnplayr 207
; Register window 1
2434 Serge 208
        E3C59X_REG_TRIGGER_BITS        equ 0xc
209
        E3C59X_REG_SOS_BITS            equ 0xa
210
        E3C59X_REG_WAKE_ON_TIMER       equ 0x8
211
        E3C59X_REG_SMB_RXBYTES         equ 0x7
212
        E3C59X_REG_SMB_DIAG            equ 0x5
213
        E3C59X_REG_SMB_ARB             equ 0x4
214
        E3C59X_REG_SMB_STATUS          equ 0x2
215
        E3C59X_REG_SMB_ADDRESS         equ 0x1
216
        E3C59X_REG_SMB_FIFO_DATA       equ 0x0
261 hidnplayr 217
; Register window 0
2434 Serge 218
        E3C59X_REG_EEPROM_DATA         equ 0xc
219
        E3C59X_REG_EEPROM_COMMAND      equ 0xa
220
        E3C59X_REG_BIOS_ROM_DATA       equ 0x8
221
        E3C59X_REG_BIOS_ROM_ADDR       equ 0x4
261 hidnplayr 222
; Physical management bits
2434 Serge 223
        E3C59X_BIT_MGMT_DIR            equ 2 ; drive with the data written in mgmtData
224
        E3C59X_BIT_MGMT_DATA           equ 1 ; MII management data bit
225
        E3C59X_BIT_MGMT_CLK            equ 0 ; MII management clock
261 hidnplayr 226
; MII commands
2434 Serge 227
        E3C59X_MII_CMD_MASK            equ (1111b shl 10)
228
        E3C59X_MII_CMD_READ            equ (0110b shl 10)
229
        E3C59X_MII_CMD_WRITE           equ (0101b shl 10)
261 hidnplayr 230
; MII registers
2434 Serge 231
        E3C59X_REG_MII_BMCR            equ 0 ; basic mode control register
232
        E3C59X_REG_MII_BMSR            equ 1 ; basic mode status register
233
        E3C59X_REG_MII_ANAR            equ 4 ; auto negotiation advertisement register
234
        E3C59X_REG_MII_ANLPAR          equ 5 ; auto negotiation link partner ability register
235
        E3C59X_REG_MII_ANER            equ 6 ; auto negotiation expansion register
261 hidnplayr 236
; MII bits
2434 Serge 237
        E3C59X_BIT_MII_AUTONEG_COMPLETE     equ 5 ; auto-negotiation complete
238
        E3C59X_BIT_MII_PREAMBLE_SUPPRESSION equ 6
261 hidnplayr 239
; eeprom bits and commands
2434 Serge 240
        E3C59X_EEPROM_CMD_READ         equ 0x80
241
        E3C59X_EEPROM_BIT_BUSY         equ 15
261 hidnplayr 242
; eeprom registers
2434 Serge 243
        E3C59X_EEPROM_REG_OEM_NODE_ADDR equ 0xa
244
        E3C59X_EEPROM_REG_CAPABILITIES  equ 0x10
261 hidnplayr 245
; Commands for command register
2434 Serge 246
        E3C59X_SELECT_REGISTER_WINDOW  equ (1 shl 11)
261 hidnplayr 247
 
2434 Serge 248
        IS_VORTEX                      equ 0x1
249
        IS_BOOMERANG                   equ 0x2
250
        IS_CYCLONE                     equ 0x4
251
        IS_TORNADO                     equ 0x8
252
        EEPROM_8BIT                    equ 0x10
253
        HAS_PWR_CTRL                   equ 0x20
254
        HAS_MII                        equ 0x40
255
        HAS_NWAY                       equ 0x80
256
        HAS_CB_FNS                     equ 0x100
257
        INVERT_MII_PWR                 equ 0x200
258
        INVERT_LED_PWR                 equ 0x400
259
        MAX_COLLISION_RESET            equ 0x800
260
        EEPROM_OFFSET                  equ 0x1000
261
        HAS_HWCKSM                     equ 0x2000
262
        EXTRA_PREAMBLE                 equ 0x4000
261 hidnplayr 263
 
264
iglobal
2434 Serge 265
        align 4
261 hidnplayr 266
e3c59x_hw_versions:
2434 Serge 267
        dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps
268
        dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex
269
        dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex
270
        dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx
271
        dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4
272
        dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII
273
        dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT
274
        dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo
275
        dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO
276
        dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo
277
        dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC
278
        dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL
279
        dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx
280
        dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4
281
        dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx
282
        dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC
283
        dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx
284
        dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado
285
        dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone
286
        dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone
287
        dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane
288
        dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane
289
        dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS \
290
        or      INVERT_MII_PWR or HAS_HWCKSM                  ; 3c556 Laptop Tornado
291
        dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS \
292
        or      INVERT_MII_PWR or HAS_HWCKSM                  ; 3c556B Laptop Hurricane
293
        dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus
294
        dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus
295
        dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT \
296
        or      INVERT_LED_PWR or HAS_HWCKSM                  ; 3CCFE575BT Cyclone CardBus
297
        dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
298
        or      MAX_COLLISION_RESET or HAS_HWCKSM                  ; 3CCFE575CT Tornado CardBus
299
        dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
300
        or      INVERT_LED_PWR or HAS_HWCKSM                  ; 3CCFE656 Cyclone CardBus
301
        dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
302
        or      INVERT_LED_PWR or HAS_HWCKSM                  ; 3CCFEM656B Cyclone+Winmodem CardBus
303
        dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
304
        or      MAX_COLLISION_RESET or HAS_HWCKSM                  ; 3CXFEM656C Tornado+Winmodem CardBus
305
        dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado
306
        dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado
307
        dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A
308
        dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B
309
        dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4
310
        dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado
261 hidnplayr 311
E3C59X_HW_VERSIONS_SIZE= $-e3c59x_hw_versions
312
endg
313
 
314
; RX/TX buffers sizes
2434 Serge 315
        E3C59X_MAX_ETH_PKT_SIZE      equ 1536 ; max packet size
316
        E3C59X_NUM_RX_DESC           equ 4 ; a power of 2 number
317
        E3C59X_NUM_TX_DESC           equ 4 ; a power of 2 number
318
        E3C59X_RX_BUFFER_SIZE        equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_RX_DESC)
319
        E3C59X_TX_BUFFER_SIZE        equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_TX_DESC)
261 hidnplayr 320
; Download Packet Descriptor
2434 Serge 321
        E3C59X_DPD_DN_NEXT_PTR       equ 0
322
        E3C59X_DPD_FRAME_START_HDR   equ 4
323
        E3C59X_DPD_DN_FRAG_ADDR      equ 8 ; for packet data
324
        E3C59X_DPD_DN_FRAG_LEN       equ 12 ; for packet data
325
        E3C59X_DPD_SIZE              equ 16 ; a power of 2 number
261 hidnplayr 326
; Upload Packet Descriptor
2434 Serge 327
        E3C59X_UPD_UP_NEXT_PTR       equ 0
328
        E3C59X_UPD_PKT_STATUS        equ 4
329
        E3C59X_UPD_UP_FRAG_ADDR      equ 8 ; for packet data
330
        E3C59X_UPD_UP_FRAG_LEN       equ 12 ; for packet data
331
        E3C59X_UPD_SIZE              equ 16
261 hidnplayr 332
 
333
; RX/TX buffers
334
if defined E3C59X_LINUX
2434 Serge 335
        E3C59X_MAX_ETH_FRAME_SIZE = 160 ; size of ethernet frame + bytes alignment
336
        e3c59x_rx_buff = 0
261 hidnplayr 337
else
2434 Serge 338
        E3C59X_MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment
339
        e3c59x_rx_buff = eth_data_start
261 hidnplayr 340
end if
341
 
2434 Serge 342
        e3c59x_tx_buff = e3c59x_rx_buff+E3C59X_RX_BUFFER_SIZE
343
        e3c59x_dpd_buff = e3c59x_tx_buff+E3C59X_TX_BUFFER_SIZE
344
        e3c59x_upd_buff = e3c59x_dpd_buff+(E3C59X_DPD_SIZE*E3C59X_NUM_TX_DESC)
261 hidnplayr 345
 
346
uglobal
2434 Serge 347
e3c59x_curr_upd:
348
                 dd 0
349
e3c59x_prev_dpd:
350
                 dd 0
351
e3c59x_prev_tx_frame:
352
                      dd 0
353
e3c59x_transmit_function:
354
                          dd 0
355
e3c59x_receive_function:
356
                         dd 0
261 hidnplayr 357
endg
358
 
359
iglobal
2434 Serge 360
e3c59x_ver_id:
361
               db 17
261 hidnplayr 362
endg
1280 hidnplayr 363
 
261 hidnplayr 364
uglobal
2434 Serge 365
e3c59x_full_bus_master:
366
                        db 0
367
e3c59x_has_hwcksm:
368
                    db 0
369
e3c59x_preamble:
370
                 db 0
371
e3c59x_dn_list_ptr_cleared:
372
                            db 0
373
e3c59x_self_directed_packet:
374
                             rb 6
261 hidnplayr 375
endg
376
 
377
if defined E3C59X_DEBUG
2434 Serge 378
e3c59x_hw_type_str:
379
                    db "Detected hardware type  : ", 0
380
e3c59x_device_str:
381
                   db  "Device ID               : 0x"
382
e3c59x_device_id_str:
383
                      db "ffff", 13, 10, 0
384
e3c59x_vendor_str:
385
                   db  "Vendor ID               : 0x"
386
e3c59x_vendor_id_str:
387
                      db "ffff", 13, 10, 0
388
e3c59x_io_info_str:
389
                    db "IO address              : 0x"
390
e3c59x_io_addr_str:
391
                    db "ffff", 13, 10, 0
392
e3c59x_mac_info_str:
393
                     db "MAC address             : "
394
e3c59x_mac_addr_str:
395
                     db "ff:ff:ff:ff:ff:ff", 13, 10, 0
396
e3c59x_boomerang_str:
397
                      db " (boomerang)", 13, 10, 0
398
e3c59x_vortex_str:
399
                   db " (vortex)", 13, 10, 0
400
e3c59x_link_type_str:
401
                      db "Established link type   : ", 0
402
e3c59x_new_line_str:
403
                     db 13, 10, 0
404
e3c59x_link_type:
405
                  dd 0
261 hidnplayr 406
 
2434 Serge 407
e3c59x_charset:
408
                db '0123456789abcdef'
261 hidnplayr 409
 
410
strtbl e3c59x_link_str, \
2434 Serge 411
        "No valid link type detected", \
412
        "10BASE-T half duplex", \
413
        "10BASE-T full-duplex", \
414
        "100BASE-TX half duplex", \
415
        "100BASE-TX full duplex", \
416
        "100BASE-T4", \
417
        "100BASE-FX", \
418
        "10Mbps AUI", \
419
        "10Mbps COAX (BNC)", \
420
        "miiDevice - not supported"
261 hidnplayr 421
 
422
strtbl e3c59x_hw_str, \
2434 Serge 423
        "3c590 Vortex 10Mbps", \
424
        "3c592 EISA 10Mbps Demon/Vortex", \
425
        "3c597 EISA Fast Demon/Vortex", \
426
        "3c595 Vortex 100baseTx", \
427
        "3c595 Vortex 100baseT4", \
428
        "3c595 Vortex 100base-MII", \
429
        "3c900 Boomerang 10baseT", \
430
        "3c900 Boomerang 10Mbps Combo", \
431
        "3c900 Cyclone 10Mbps TPO", \
432
        "3c900 Cyclone 10Mbps Combo", \
433
        "3c900 Cyclone 10Mbps TPC", \
434
        "3c900B-FL Cyclone 10base-FL", \
435
        "3c905 Boomerang 100baseTx", \
436
        "3c905 Boomerang 100baseT4", \
437
        "3c905B Cyclone 100baseTx", \
438
        "3c905B Cyclone 10/100/BNC", \
439
        "3c905B-FX Cyclone 100baseFx", \
440
        "3c905C Tornado", \
441
        "3c980 Cyclone", \
442
        "3c982 Dual Port Server Cyclone", \
443
        "3cSOHO100-TX Hurricane", \
444
        "3c555 Laptop Hurricane", \
445
        "3c556 Laptop Tornado", \
446
        "3c556B Laptop Hurricane", \
447
        "3c575 [Megahertz] 10/100 LAN CardBus", \
448
        "3c575 Boomerang CardBus", \
449
        "3CCFE575BT Cyclone CardBus", \
450
        "3CCFE575CT Tornado CardBus", \
451
        "3CCFE656 Cyclone CardBus", \
452
        "3CCFEM656B Cyclone+Winmodem CardBus", \
453
        "3CXFEM656C Tornado+Winmodem CardBus", \
454
        "3c450 HomePNA Tornado", \
455
        "3c920 Tornado", \
456
        "3c982 Hydra Dual Port A", \
457
        "3c982 Hydra Dual Port B", \
458
        "3c905B-T4", \
459
        "3c920B-EMB-WNM Tornado"
261 hidnplayr 460
 
461
end if ; defined E3C59X_DEBUG
462
 
463
;***************************************************************************
464
;   Function
465
;      e3c59x_debug
466
;   Description
467
;      prints debug info to the debug board
468
;   Parameters
469
;      ebp - io_addr
470
;   Return value
471
;   Destroyed registers
472
;      eax, ebx, ecx, edx, edi, esi
473
;
474
;***************************************************************************
475
if defined E3C59X_DEBUG
2434 Serge 476
        align 4
261 hidnplayr 477
e3c59x_debug:
2434 Serge 478
        pushad
261 hidnplayr 479
; print device type
2434 Serge 480
        mov     esi, e3c59x_hw_type_str
481
        call    sys_msg_board_str
482
        movzx   ecx, byte [e3c59x_ver_id]
483
        mov     esi, [e3c59x_hw_str+ecx*4]
484
        call    sys_msg_board_str
485
        mov     esi, e3c59x_boomerang_str
486
        cmp     dword [e3c59x_transmit_function], e3c59x_boomerang_transmit
487
        jz      .boomerang
488
        mov     esi, e3c59x_vortex_str
261 hidnplayr 489
.boomerang:
2434 Serge 490
        call    sys_msg_board_str
261 hidnplayr 491
; print device/vendor
2434 Serge 492
        mov     ax, [pci_data+2]
493
        mov     cl, 2
494
        mov     ebx, e3c59x_device_id_str
495
        call    e3c59x_print_hex
496
        mov     esi, e3c59x_device_str
497
        call    sys_msg_board_str
498
        mov     ax, [pci_data]
499
        mov     cl, 2
500
        mov     ebx, e3c59x_vendor_id_str
501
        call    e3c59x_print_hex
502
        mov     esi, e3c59x_vendor_str
503
        call    sys_msg_board_str
261 hidnplayr 504
; print io address
2434 Serge 505
        mov     ax, [io_addr]
506
        mov     ebx, e3c59x_io_addr_str
507
        mov     cl, 2
508
        call    e3c59x_print_hex
509
        mov     esi, e3c59x_io_info_str
510
        call    sys_msg_board_str
261 hidnplayr 511
; print MAC address
2434 Serge 512
        mov     ebx, e3c59x_mac_addr_str
513
        xor     ecx, ecx
261 hidnplayr 514
.mac_loop:
2434 Serge 515
        push    ecx
516
        mov     al, [node_addr+ecx]
517
        mov     cl, 1
518
        call    e3c59x_print_hex
519
        inc     ebx
520
        pop     ecx
521
        inc     cl
522
        cmp     cl, 6
523
        jne     .mac_loop
524
        mov     esi, e3c59x_mac_info_str
525
        call    sys_msg_board_str
261 hidnplayr 526
; print link type
2434 Serge 527
        mov     esi, e3c59x_link_type_str
528
        call    sys_msg_board_str
529
        xor     eax, eax
530
        bsr     ax, word [e3c59x_link_type]
531
        jz      @f
532
        sub     ax, 4
261 hidnplayr 533
@@:
2434 Serge 534
        mov     esi, [e3c59x_link_str+eax*4]
535
        call    sys_msg_board_str
536
        mov     esi, e3c59x_new_line_str
537
        call    sys_msg_board_str
538
        popad
539
        ret
261 hidnplayr 540
 
541
;***************************************************************************
542
;   Function
543
;      e3c59x_print_hex
544
;   Description
545
;      prints a hexadecimal value
546
;   Parameters
547
;      eax - value to be printed out
548
;      ebx - where to print
549
;       cl - value size (1, 2, 4)
550
;   Return value
551
;      ebx - end address after the print
552
;   Destroyed registers
553
;      eax, ebx
554
;
555
;***************************************************************************
2434 Serge 556
        align 4
261 hidnplayr 557
e3c59x_print_hex:
2434 Serge 558
        cmp     cl, 1
559
        je      .print_byte
560
        cmp     cl, 2
561
        jz      .print_word
261 hidnplayr 562
.print_dword:
2434 Serge 563
        push    eax
564
        bswap   eax
565
        xchg    ah, al
566
        call    .print_word
567
        pop     eax
261 hidnplayr 568
.print_word:
2434 Serge 569
        push    eax
570
        xchg    ah, al
571
        call    .print_byte
572
        pop     eax
261 hidnplayr 573
.print_byte:
2434 Serge 574
        movzx   eax, al
575
        push    eax
576
        and     al, 0xf0
577
        shr     al, 4
578
        mov     al, byte [eax+e3c59x_charset]
579
        mov     [ebx], al
580
        inc     ebx
581
        pop     eax
582
        and     al, 0x0f
583
        mov     al, byte [eax+e3c59x_charset]
584
        mov     [ebx], al
585
        inc     ebx
586
        ret
261 hidnplayr 587
end if ; defined E3C59X_DEBUG
588
 
589
;***************************************************************************
590
;   Function
591
;      e3c59x_try_link_detect
592
;   Description
593
;      e3c59x_try_link_detect checks if link exists
594
;   Parameters
595
;      ebp - io_addr
596
;   Return value
597
;      al - 0 ; no link detected
598
;      al - 1 ; link detected
599
;   Destroyed registers
600
;      eax, ebx, ecx, edx, edi, esi
601
;
602
;***************************************************************************
2434 Serge 603
        align 4
261 hidnplayr 604
e3c59x_try_link_detect:
605
; download self-directed packet
2434 Serge 606
        mov     edi, node_addr
607
        mov     bx, 0x0608 ; packet type
608
        mov     esi, e3c59x_self_directed_packet
609
        mov     ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes
610
        call    dword [e3c59x_transmit_function]
261 hidnplayr 611
; switch to register window 5
2434 Serge 612
        lea     edx, [ebp+E3C59X_REG_COMMAND]
613
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+5
614
        out     dx, ax
261 hidnplayr 615
; program RxFilter for promiscuous operation
2434 Serge 616
        mov     ax, (10000b shl 11)
617
        lea     edx, [ebp+E3C59X_REG_RX_FILTER]
618
        in      al, dx
619
        or      al, 1111b
620
        lea     edx, [ebp+E3C59X_REG_COMMAND]
621
        out     dx, ax
261 hidnplayr 622
; switch to register window 4
2434 Serge 623
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
624
        out     dx, ax
261 hidnplayr 625
; check loop
2434 Serge 626
        xor     ebx, ebx
627
        mov     ecx, 0xffff ; 65535 tries
261 hidnplayr 628
.loop:
2434 Serge 629
        push    ecx ebx
630
        call    dword [e3c59x_receive_function]
631
        pop     ebx ecx
632
        test    al, al
633
        jnz     .finish
261 hidnplayr 634
.no_packet_received:
635
; switch to register window 4
2434 Serge 636
        lea     edx, [ebp+E3C59X_REG_COMMAND]
637
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
638
        out     dx, ax
261 hidnplayr 639
; read linkbeatdetect
2434 Serge 640
        lea     edx, [ebp+E3C59X_REG_MEDIA_STATUS]
641
        in      ax, dx
642
        test    ah, 1000b ; test linkBeatDetect
643
        jnz     .link_detected
644
        xor     al, al
645
        jmp     .finish
261 hidnplayr 646
.link_detected:
647
; test carrierSense
2434 Serge 648
        test    al, 100000b
649
        jz      .no_carrier_sense
650
        inc     ebx
261 hidnplayr 651
.no_carrier_sense:
2434 Serge 652
        dec     ecx
653
        jns     .loop
261 hidnplayr 654
; assume the link is good if 0 < ebx < 25 %
2434 Serge 655
        test    ebx, ebx
656
        setnz   al
657
        jz      .finish
658
        cmp     ebx, 16384 ; 25%
659
        setb    al
261 hidnplayr 660
.finish:
661
if defined E3C59X_DEBUG
2434 Serge 662
        test    al, al
663
        jz      @f
664
        or      byte [e3c59x_link_type+1], 100b
261 hidnplayr 665
@@:
666
end if ; defined E3C59X_DEBUG
2434 Serge 667
        ret
261 hidnplayr 668
 
669
;***************************************************************************
670
;   Function
671
;      e3c59x_try_phy
672
;   Description
673
;      e3c59x_try_phy checks the auto-negotiation function
674
;      in the PHY at PHY index. It can also be extended to
675
;      include link detection for non-IEEE 802.3u
676
;      auto-negotiation devices, for instance the BCM5000.
677
;   Parameters
678
;       ah - PHY index
679
;      ebp - io_addr
680
;   Return value
681
;      al - 0 link is auto-negotiated
682
;      al - 1 no link is auto-negotiated
683
;   Destroyed registers
684
;       eax, ebx, ecx, edx, esi
685
;
686
;***************************************************************************
2434 Serge 687
        align 4
261 hidnplayr 688
e3c59x_try_phy:
2434 Serge 689
        mov     al, E3C59X_REG_MII_BMCR
690
        push    eax
691
        call    e3c59x_mdio_read ; returns with window #4
692
        or      ah, 0x80 ; software reset
693
        mov     ebx, eax
694
        pop     eax
695
        push    eax
696
        call    e3c59x_mdio_write ; returns with window #4
261 hidnplayr 697
; wait for reset to complete
2434 Serge 698
        mov     esi, 2000 ; 2000ms = 2s
699
        call    delay_ms
700
        pop     eax
701
        push    eax
702
        call    e3c59x_mdio_read ; returns with window #4
703
        test    ah, 0x80
704
        jnz     .fail_finish
705
        pop     eax
706
        push    eax
261 hidnplayr 707
; wait for a while after reset
2434 Serge 708
        mov     esi, 20 ; 20ms
709
        call    delay_ms
710
        pop     eax
711
        push    eax
712
        mov     al, E3C59X_REG_MII_BMSR
713
        call    e3c59x_mdio_read ; returns with window #4
714
        test    al, 1 ; extended capability supported?
715
        jz      .no_ext_cap
261 hidnplayr 716
; auto-neg capable?
2434 Serge 717
        test    al, 1000b
718
        jz      .fail_finish ; not auto-negotiation capable
261 hidnplayr 719
; auto-neg complete?
2434 Serge 720
        test    al, 100000b
721
        jnz     .auto_neg_ok
261 hidnplayr 722
; restart auto-negotiation
2434 Serge 723
        pop     eax
724
        push    eax
725
        mov     al, E3C59X_REG_MII_ANAR
726
        push    eax
727
        call    e3c59x_mdio_read ; returns with window #4
728
        or      ax, (1111b shl 5) ; advertise only 10base-T and 100base-TX
729
        mov     ebx, eax
730
        pop     eax
731
        call    e3c59x_mdio_write ; returns with window #4
732
        pop     eax
733
        push    eax
734
        call    e3c59x_mdio_read ; returns with window #4
735
        mov     ebx, eax
736
        or      bh, 10010b ; restart auto-negotiation
737
        pop     eax
738
        push    eax
739
        call    e3c59x_mdio_write ; returns with window #4
740
        mov     esi, 4000 ; 4000ms = 4 seconds
741
        call    delay_ms
742
        pop     eax
743
        push    eax
744
        mov     al, E3C59X_REG_MII_BMSR
745
        call    e3c59x_mdio_read ; returns with window #4
746
        test    al, 100000b ; auto-neg complete?
747
        jnz     .auto_neg_ok
748
        jmp     .fail_finish
261 hidnplayr 749
.auto_neg_ok:
750
; compare advertisement and link partner ability registers
2434 Serge 751
        pop     eax
752
        push    eax
753
        mov     al, E3C59X_REG_MII_ANAR
754
        call    e3c59x_mdio_read ; returns with window #4
755
        xchg    eax, [esp]
756
        mov     al, E3C59X_REG_MII_ANLPAR
757
        call    e3c59x_mdio_read ; returns with window #4
758
        pop     ebx
759
        and     eax, ebx
760
        and     eax, 1111100000b
761
        push    eax
261 hidnplayr 762
if defined E3C59X_DEBUG
2434 Serge 763
        mov     word [e3c59x_link_type], ax
261 hidnplayr 764
end if ; defined E3C59X_DEBUG
765
; switch to register window 3
2434 Serge 766
        lea     edx, [ebp+E3C59X_REG_COMMAND]
767
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
768
        out     dx, ax
261 hidnplayr 769
; set full-duplex mode
2434 Serge 770
        lea     edx, [ebp+E3C59X_REG_MAC_CONTROL]
771
        in      ax, dx
772
        and     ax, not 0x120 ; clear full duplex and flow control
773
        pop     ebx
774
        test    ebx, (1010b shl 5) ; check for full-duplex
775
        jz      .half_duplex
776
        or      ax, 0x120 ; set full duplex and flow control
261 hidnplayr 777
.half_duplex:
2434 Serge 778
        out     dx, ax
779
        mov     al, 1
780
        ret
261 hidnplayr 781
.no_ext_cap:
782
; not yet implemented BCM5000
783
.fail_finish:
2434 Serge 784
        pop     eax
785
        xor     al, al
786
        ret
261 hidnplayr 787
 
788
;***************************************************************************
789
;   Function
790
;      e3c59x_try_mii
791
;   Description
792
;      e3c59x_try_MII checks the on-chip auto-negotiation logic
793
;      or an off-chip MII PHY, depending upon what is set in
794
;      xcvrSelect by the caller.
795
;      It exits when it finds the first device with a good link.
796
;   Parameters
797
;      ebp - io_addr
798
;   Return value
799
;      al - 0
800
;      al - 1
801
;   Destroyed registers
802
;      eax, ebx, ecx, edx, esi
803
;
804
;***************************************************************************
2434 Serge 805
        align 4
261 hidnplayr 806
e3c59x_try_mii:
807
; switch to register window 3
2434 Serge 808
        lea     edx, [ebp+E3C59X_REG_COMMAND]
809
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
810
        out     dx, ax
811
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
812
        in      eax, dx
813
        and     eax, (1111b shl 20)
814
        cmp     eax, (1000b shl 20) ; is auto-negotiation set?
815
        jne     .mii_device
261 hidnplayr 816
; auto-negotiation is set
817
; switch to register window 4
2434 Serge 818
        lea     edx, [ebp+E3C59X_REG_COMMAND]
819
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
820
        out     dx, ax
261 hidnplayr 821
; PHY==24 is the on-chip auto-negotiation logic
822
; it supports only 10base-T and 100base-TX
2434 Serge 823
        mov     ah, 24
824
        call    e3c59x_try_phy
825
        test    al, al
826
        jz      .fail_finish
827
        mov     cl, 24
828
        jmp     .check_preamble
261 hidnplayr 829
.mii_device:
2434 Serge 830
        cmp     eax, (0110b shl 20)
831
        jne     .fail_finish
832
        lea     edx, [ebp+E3C59X_REG_COMMAND]
833
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
834
        out     dx, ax
835
        lea     edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
836
        in      ax, dx
837
        and     al, (1 shl E3C59X_BIT_MGMT_DIR) or (1 shl E3C59X_BIT_MGMT_DATA)
838
        cmp     al, (1 shl E3C59X_BIT_MGMT_DATA)
839
        je      .serch_for_phy
840
        xor     al, al
841
        ret
261 hidnplayr 842
.serch_for_phy:
843
; search for PHY
2434 Serge 844
        mov     cl, 31
261 hidnplayr 845
.search_phy_loop:
2434 Serge 846
        cmp     cl, 24
847
        je      .next_phy
848
        mov     ah, cl ; ah = phy
849
        mov     al, E3C59X_REG_MII_BMCR ; al = Basic Mode Status Register
850
        push    ecx
851
        call    e3c59x_mdio_read
852
        pop     ecx
853
        test    ax, ax
854
        jz      .next_phy
855
        cmp     ax, 0xffff
856
        je      .next_phy
857
        mov     ah, cl ; ah = phy
858
        push    ecx
859
        call    e3c59x_try_phy
860
        pop     ecx
861
        test    al, al
862
        jnz     .check_preamble
261 hidnplayr 863
.next_phy:
2434 Serge 864
        dec     cl
865
        jns     .search_phy_loop
261 hidnplayr 866
.fail_finish:
2434 Serge 867
        xor     al, al
868
        ret
261 hidnplayr 869
; epilog
870
.check_preamble:
2434 Serge 871
        push    eax ; eax contains the return value of e3c59x_try_phy
261 hidnplayr 872
; check hard coded preamble forcing
2434 Serge 873
        movzx   eax, byte [e3c59x_ver_id]
874
        test    word [eax*4+e3c59x_hw_versions+2], EXTRA_PREAMBLE
875
        setnz   [e3c59x_preamble] ; force preamble
876
        jnz     .finish
261 hidnplayr 877
; check mii for preamble suppression
2434 Serge 878
        mov     ah, cl
879
        mov     al, E3C59X_REG_MII_BMSR
880
        call    e3c59x_mdio_read
881
        test    al, 1000000b ; preamble suppression?
882
        setz    [e3c59x_preamble] ; no
261 hidnplayr 883
.finish:
2434 Serge 884
        pop     eax
885
        ret
261 hidnplayr 886
 
887
;***************************************************************************
888
;   Function
889
;      e3c59x_test_packet
890
;   Description
891
;      e3c59x_try_loopback try a loopback packet for 10BASE2 or AUI port
892
;   Parameters
893
;      ebp - io_addr
894
;   Return value
895
;      al - 0
896
;      al - 1
897
;   Destroyed registers
898
;      eax, ebx, ecx, edx, edi, esi
899
;
900
;***************************************************************************
2434 Serge 901
        align 4
261 hidnplayr 902
e3c59x_test_packet:
903
; switch to register window 3
2434 Serge 904
        lea     edx, [ebp+E3C59X_REG_COMMAND]
905
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
906
        out     dx, ax
261 hidnplayr 907
; set fullDuplexEnable in MacControl register
2434 Serge 908
        lea     edx, [ebp+E3C59X_REG_MAC_CONTROL]
909
        in      ax, dx
910
        or      ax, 0x120
911
        out     dx, ax
261 hidnplayr 912
; switch to register window 5
2434 Serge 913
        lea     edx, [ebp+E3C59X_REG_COMMAND]
914
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+5
915
        out     dx, ax
261 hidnplayr 916
; set RxFilter to enable individual address matches
2434 Serge 917
        mov     ax, (10000b shl 11)
918
        lea     edx, [ebp+E3C59X_REG_RX_FILTER]
919
        in      al, dx
920
        or      al, 1
921
        lea     edx, [ebp+E3C59X_REG_COMMAND]
922
        out     dx, ax
261 hidnplayr 923
; issue RxEnable and TxEnable
2434 Serge 924
        call    e3c59x_rx_reset
925
        call    e3c59x_tx_reset
261 hidnplayr 926
; download a self-directed test packet
2434 Serge 927
        mov     edi, node_addr
928
        mov     bx, 0x0608 ; packet type
929
        mov     esi, e3c59x_self_directed_packet
930
        mov     ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes
931
        call    dword [e3c59x_transmit_function]
261 hidnplayr 932
; wait for 2s
2434 Serge 933
        mov     esi, 2000 ; 2000ms = 2s
934
        call    delay_ms
261 hidnplayr 935
; check if self-directed packet is received
2434 Serge 936
        call    dword [e3c59x_receive_function]
937
        test    al, al
938
        jnz     .finish
261 hidnplayr 939
; switch to register window 3
2434 Serge 940
        lea     edx, [ebp+E3C59X_REG_COMMAND]
941
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
942
        out     dx, ax
261 hidnplayr 943
; clear fullDuplexEnable in MacControl register
2434 Serge 944
        lea     edx, [ebp+E3C59X_REG_MAC_CONTROL]
945
        in      ax, dx
946
        and     ax, not 0x120
947
        out     dx, ax
948
        xor     al, al
261 hidnplayr 949
.finish:
2434 Serge 950
        ret
261 hidnplayr 951
 
952
;***************************************************************************
953
;   Function
954
;      e3c59x_try_loopback
955
;   Description
956
;      tries a loopback packet for 10BASE2 or AUI port
957
;   Parameters
958
;      al -  0: 10Mbps AUI connector
959
;            1: 10BASE-2
960
;      ebp - io_addr
961
;   Return value
962
;      al - 0
963
;      al - 1
964
;   Destroyed registers
965
;      eax, ebx, ecx, edx, edi, esi
966
;
967
;***************************************************************************
2434 Serge 968
        align 4
261 hidnplayr 969
e3c59x_try_loopback:
2434 Serge 970
        push    eax
261 hidnplayr 971
; switch to register window 3
2434 Serge 972
        lea     edx, [ebp+E3C59X_REG_COMMAND]
973
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
974
        out     dx, ax
975
        pop     eax
976
        push    eax
261 hidnplayr 977
if defined E3C59X_DEBUG
2434 Serge 978
        mov     bl, al
979
        inc     bl
980
        shl     bl, 3
981
        or      byte [e3c59x_link_type+1], bl
261 hidnplayr 982
end if ; defined E3C59X_DEBUG
2434 Serge 983
        test    al, al ; aui or coax?
984
        jz      .complete_loopback
261 hidnplayr 985
; enable 100BASE-2 DC-DC converter
2434 Serge 986
        mov     ax, (10b shl 11) ; EnableDcConverter
987
        out     dx, ax
261 hidnplayr 988
.complete_loopback:
2434 Serge 989
        mov     cl, 2 ; give a port 3 chances to complete a loopback
261 hidnplayr 990
.next_try:
2434 Serge 991
        push    ecx
992
        call    e3c59x_test_packet
993
        pop     ecx
994
        test    al, al
995
        jnz     .finish
996
        dec     cl
997
        jns     .next_try
261 hidnplayr 998
.finish:
2434 Serge 999
        xchg    eax, [esp]
1000
        test    al, al
1001
        jz      .aui_finish
261 hidnplayr 1002
; issue DisableDcConverter command
2434 Serge 1003
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1004
        mov     ax, (10111b shl 11)
1005
        out     dx, ax
261 hidnplayr 1006
.aui_finish:
2434 Serge 1007
        pop     eax ; al contains the result of operation
261 hidnplayr 1008
if defined E3C59X_DEBUG
2434 Serge 1009
        test    al, al
1010
        jnz     @f
1011
        and     byte [e3c59x_link_type+1], not 11000b
261 hidnplayr 1012
@@:
1013
end if ; defined E3C59X_DEBUG
2434 Serge 1014
        ret
261 hidnplayr 1015
 
1016
;***************************************************************************
1017
;   Function
1018
;      e3c59x_set_available_media
1019
;   Description
1020
;      sets the first available media
1021
;   Parameters
1022
;      ebp - io_addr
1023
;   Return value
1024
;      al - 0
1025
;      al - 1
1026
;   Destroyed registers
1027
;      eax, edx
1028
;
1029
;***************************************************************************
2434 Serge 1030
        align 4
261 hidnplayr 1031
e3c59x_set_available_media:
1032
; switch to register window 3
2434 Serge 1033
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1034
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
1035
        out     dx, ax
1036
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
1037
        in      eax, dx
1038
        push    eax
1039
        lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
1040
        in      ax, dx
1041
        test    al, 10b
1042
        jz      @f
261 hidnplayr 1043
; baseTXAvailable
2434 Serge 1044
        pop     eax
1045
        and     eax, not (1111b shl 20)
1046
        or      eax, (100b shl 20)
261 hidnplayr 1047
if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD
2434 Serge 1048
        mov     word [e3c59x_link_type], (1 shl 8)
261 hidnplayr 1049
else if defined E3C59X_DEBUG
2434 Serge 1050
        mov     word [e3c59x_link_type], (1 shl 7)
261 hidnplayr 1051
end if
2434 Serge 1052
        jmp     .set_media
261 hidnplayr 1053
@@:
2434 Serge 1054
        test    al, 100b
1055
        jz      @f
261 hidnplayr 1056
; baseFXAvailable
2434 Serge 1057
        pop     eax
1058
        and     eax, not (1111b shl 20)
1059
        or      eax, (101b shl 20)
261 hidnplayr 1060
if defined E3C59X_DEBUG
2434 Serge 1061
        mov     word [e3c59x_link_type], (1 shl 10)
261 hidnplayr 1062
end if
2434 Serge 1063
        jmp     .set_media
261 hidnplayr 1064
@@:
2434 Serge 1065
        test    al, 1000000b
1066
        jz      @f
261 hidnplayr 1067
; miiDevice
2434 Serge 1068
        pop     eax
1069
        and     eax, not (1111b shl 20)
1070
        or      eax, (0110b shl 20)
261 hidnplayr 1071
if defined E3C59X_DEBUG
2434 Serge 1072
        mov     word [e3c59x_link_type], (1 shl 13)
261 hidnplayr 1073
end if
2434 Serge 1074
        jmp     .set_media
261 hidnplayr 1075
@@:
2434 Serge 1076
        test    al, 1000b
1077
        jz      @f
261 hidnplayr 1078
.set_default:
1079
; 10bTAvailable
2434 Serge 1080
        pop     eax
1081
        and     eax, not (1111b shl 20)
261 hidnplayr 1082
if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD
2434 Serge 1083
        mov     word [e3c59x_link_type], (1 shl 6)
261 hidnplayr 1084
else if defined E3C59X_DEBUG
2434 Serge 1085
        mov     word [e3c59x_link_type], (1 shl 5)
261 hidnplayr 1086
end if ; E3C59X_FORCE_FD
2434 Serge 1087
        jmp     .set_media
261 hidnplayr 1088
@@:
2434 Serge 1089
        test    al, 10000b
1090
        jz      @f
261 hidnplayr 1091
; coaxAvailable
2434 Serge 1092
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1093
        mov     ax, (10b shl 11) ; EnableDcConverter
1094
        out     dx, ax
1095
        pop     eax
1096
        and     eax, not (1111b shl 20)
1097
        or      eax, (11b shl 20)
261 hidnplayr 1098
if defined E3C59X_DEBUG
2434 Serge 1099
        mov     word [e3c59x_link_type], (1 shl 12)
261 hidnplayr 1100
end if ; defined E3C59X_DEBUG
2434 Serge 1101
        jmp     .set_media
261 hidnplayr 1102
@@:
2434 Serge 1103
        test    al, 10000b
1104
        jz      .set_default
261 hidnplayr 1105
; auiAvailable
2434 Serge 1106
        pop     eax
1107
        and     eax, not (1111b shl 20)
1108
        or      eax, (1 shl 20)
261 hidnplayr 1109
if defined E3C59X_DEBUG
2434 Serge 1110
        mov     word [e3c59x_link_type], (1 shl 11)
261 hidnplayr 1111
end if ; defined E3C59X_DEBUG
1112
.set_media:
2434 Serge 1113
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
1114
        out     dx, eax
261 hidnplayr 1115
if defined E3C59X_FORCE_FD
1116
; set fullDuplexEnable in MacControl register
2434 Serge 1117
        lea     edx, [ebp+E3C59X_REG_MAC_CONTROL]
1118
        in      ax, dx
1119
        or      ax, 0x120
1120
        out     dx, ax
261 hidnplayr 1121
end if ; E3C59X_FORCE_FD
2434 Serge 1122
        mov     al, 1
1123
        ret
261 hidnplayr 1124
 
1125
;***************************************************************************
1126
;   Function
1127
;      e3c59x_set_active_port
1128
;   Description
1129
;      It selects the media port (transceiver) to be used
1130
;   Parameters:
1131
;      ebp - io_addr
1132
;   Return value:
1133
;   Destroyed registers
1134
;      eax, ebx, ecx, edx, edi, esi
1135
;
1136
;***************************************************************************
2434 Serge 1137
        align 4
261 hidnplayr 1138
e3c59x_set_active_port:
1139
; switch to register window 3
2434 Serge 1140
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1141
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
1142
        out     dx, ax
1143
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
1144
        in      eax, dx
1145
        test    eax, (1 shl 24) ; check if autoselect enable
1146
        jz      .set_first_available_media
261 hidnplayr 1147
; check 100BASE-TX and 10BASE-T
2434 Serge 1148
        lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
1149
        in      ax, dx
1150
        test    al, 1010b ; check whether 100BASE-TX or 10BASE-T available
1151
        jz      .mii_device ; they are not available
261 hidnplayr 1152
; set auto-negotiation
2434 Serge 1153
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
1154
        in      eax, dx
1155
        and     eax, not (1111b shl 20)
1156
        or      eax, (1000b shl 20)
1157
        out     dx, eax
1158
        call    e3c59x_try_mii
1159
        test    al, al
1160
        jz      .mii_device
1161
        ret
261 hidnplayr 1162
.mii_device:
1163
; switch to register window 3
2434 Serge 1164
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1165
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
1166
        out     dx, ax
261 hidnplayr 1167
; check for off-chip mii device
2434 Serge 1168
        lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
1169
        in      ax, dx
1170
        test    al, 1000000b ; check miiDevice
1171
        jz      .base_fx
1172
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
1173
        in      eax, dx
1174
        and     eax, not (1111b shl 20)
1175
        or      eax, (0110b shl 20) ; set MIIDevice
1176
        out     dx, eax
1177
        call    e3c59x_try_mii
1178
        test    al, al
1179
        jz      .base_fx
1180
        ret
261 hidnplayr 1181
.base_fx:
1182
; switch to register window 3
2434 Serge 1183
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1184
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
1185
        out     dx, ax
261 hidnplayr 1186
; check for 100BASE-FX
2434 Serge 1187
        lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
1188
        in      ax, dx ; read media option register
1189
        test    al, 100b ; check 100BASE-FX
1190
        jz      .aui_enable
1191
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
1192
        in      eax, dx
1193
        and     eax, not (1111b shl 20)
1194
        or      eax, (0101b shl 20) ; set 100base-FX
1195
        out     dx, eax
1196
        call    e3c59x_try_link_detect
1197
        test    al, al
1198
        jz      .aui_enable
1199
        ret
261 hidnplayr 1200
.aui_enable:
1201
; switch to register window 3
2434 Serge 1202
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1203
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
1204
        out     dx, ax
261 hidnplayr 1205
; check for 10Mbps AUI connector
2434 Serge 1206
        lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
1207
        in      ax, dx ; read media option register
1208
        test    al, 100000b ; check 10Mbps AUI connector
1209
        jz      .coax_available
1210
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
1211
        in      eax, dx
1212
        and     eax, not (1111b shl 20)
1213
        or      eax, (0001b shl 20) ; set 10Mbps AUI connector
1214
        out     dx, eax
1215
        xor     al, al ; try 10Mbps AUI connector
1216
        call    e3c59x_try_loopback
1217
        test    al, al
1218
        jz      .coax_available
1219
        ret
261 hidnplayr 1220
.coax_available:
1221
; switch to register window 3
2434 Serge 1222
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1223
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+3
1224
        out     dx, ax
261 hidnplayr 1225
; check for coaxial 10BASE-2 port
2434 Serge 1226
        lea     edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
1227
        in      ax, dx ; read media option register
1228
        test    al, 10000b ; check 10BASE-2
1229
        jz      .set_first_available_media
1230
        lea     edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
1231
        in      eax, dx
1232
        and     eax, not (1111b shl 20)
1233
        or      eax, (0011b shl 20) ; set 10BASE-2
1234
        out     dx, eax
1235
        mov     al, 1
1236
        call    e3c59x_try_loopback
1237
        test    al, al
1238
        jz      .set_first_available_media
1239
        ret
261 hidnplayr 1240
.set_first_available_media:
2434 Serge 1241
        jmp     e3c59x_set_available_media
261 hidnplayr 1242
 
1243
;***************************************************************************
1244
;   Function
1245
;      e3c59x_wake_up
1246
;   Description
1247
;      set the power state to D0
1248
;   Destroyed registers
1249
;      eax, ebx, ecx, edx, edi, esi
1250
;
1251
;***************************************************************************
2434 Serge 1252
        align 4
261 hidnplayr 1253
e3c59x_wake_up:
1254
; wake up - we directly do it by programming PCI
1255
; check if the device is power management capable
2434 Serge 1256
        mov     al, 2
1257
        mov     ah, [pci_bus]
1258
        mov     bl, PCI_REG_STATUS
1259
        mov     bh, [pci_dev]
1260
        push    eax ebx
1261
        call    pci_read_reg
1262
        test    al, 10000b ; is there "new capabilities" linked list?
1263
        pop     ebx eax
1264
        jz      .device_awake
261 hidnplayr 1265
; search for power management register
2434 Serge 1266
        mov     al, 1
1267
        mov     bl, PCI_REG_CAP_PTR
1268
        push    eax ebx
1269
        call    pci_read_reg
1270
        mov     cl, al
1271
        cmp     cl, 0x3f
1272
        pop     ebx eax
1273
        jbe     .device_awake
261 hidnplayr 1274
; traverse the list
2434 Serge 1275
        mov     al, 2
261 hidnplayr 1276
.pm_loop:
2434 Serge 1277
        mov     bl, cl
1278
        push    eax ebx
1279
        call    pci_read_reg
1280
        cmp     al, 1
1281
        je      .set_pm_state
1282
        test    ah, ah
1283
        mov     cl, ah
1284
        pop     ebx eax
1285
        jnz     .pm_loop
1286
        jmp     .device_awake
261 hidnplayr 1287
; waku up the device if necessary
1288
.set_pm_state:
2434 Serge 1289
        pop     ebx eax
1290
        add     bl, PCI_REG_PM_CTRL
1291
        push    eax ebx
1292
        call    pci_read_reg
1293
        mov     cx, ax
1294
        test    cl, 3
1295
        pop     ebx eax
1296
        jz      .device_awake
1297
        and     cl, not 11b ; set state to D0
1298
        call    pci_write_reg
261 hidnplayr 1299
.device_awake:
2434 Serge 1300
        ret
261 hidnplayr 1301
 
1302
;***************************************************************************
1303
;   Function
1304
;      e3c59x_probe
1305
;   Description
1306
;      Searches for an ethernet card, enables it and clears the rx buffer
1307
;      If a card was found, it enables the ethernet -> TCPIP link
1308
;   Destroyed registers
1309
;      eax, ebx, ecx, edx, edi, esi
1310
;
1311
;***************************************************************************
2434 Serge 1312
        align 4
261 hidnplayr 1313
e3c59x_probe:
2434 Serge 1314
        movzx   ebp, word [io_addr]
1315
        mov     al, 2
1316
        mov     ah, [pci_bus]
1317
        mov     bh, [pci_dev]
1318
        mov     bl, PCI_REG_COMMAND
1319
        push    ebp eax ebx
1320
        call    pci_read_reg
1321
        mov     cx, ax
1322
        or      cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO)
1323
        and     cl, not (1 shl PCI_BIT_MMIO)
1324
        pop     ebx eax
1325
        call    pci_write_reg
261 hidnplayr 1326
; wake up the card
2434 Serge 1327
        call    e3c59x_wake_up
1328
        pop     ebp
261 hidnplayr 1329
; get chip version
2434 Serge 1330
        mov     ax, [pci_data+2]
1331
        mov     ecx, E3C59X_HW_VERSIONS_SIZE/4-1
261 hidnplayr 1332
.chip_ver_loop:
2434 Serge 1333
        cmp     ax, [e3c59x_hw_versions+ecx*4]
1334
        jz      .chip_ver_found
1335
        dec     ecx
1336
        jns     .chip_ver_loop
1337
        xor     ecx, ecx
261 hidnplayr 1338
.chip_ver_found:
2434 Serge 1339
        mov     [e3c59x_ver_id], cl
1340
        test    word [e3c59x_hw_versions+2+ecx*4], HAS_HWCKSM
1341
        setnz   [e3c59x_has_hwcksm]
261 hidnplayr 1342
; set pci latency for vortex cards
2434 Serge 1343
        test    word [e3c59x_hw_versions+2+ecx*4], IS_VORTEX
1344
        jz      .not_vortex
1345
        mov     cx, 11111000b ; 248 = max latency
1346
        mov     al, 1
1347
        mov     ah, [pci_bus]
1348
        mov     bl, PCI_REG_LATENCY
1349
        mov     bh, [pci_dev]
1350
        call    pci_write_reg
261 hidnplayr 1351
.not_vortex:
1352
; set RX/TX functions
2434 Serge 1353
        mov     ax, E3C59X_EEPROM_REG_CAPABILITIES
1354
        call    e3c59x_read_eeprom
1355
        test    al, 100000b ; full bus master?
1356
        setnz   [e3c59x_full_bus_master]
1357
        jnz     .boomerang_func
1358
        mov     dword [e3c59x_transmit_function], e3c59x_vortex_transmit
1359
        mov     dword [e3c59x_receive_function], e3c59x_vortex_poll
1360
        jmp     @f
261 hidnplayr 1361
.boomerang_func: ; full bus master, so use boomerang functions
2434 Serge 1362
        mov     dword [e3c59x_transmit_function], e3c59x_boomerang_transmit
1363
        mov     dword [e3c59x_receive_function], e3c59x_boomerang_poll
261 hidnplayr 1364
@@:
1365
; read MAC from eeprom
2434 Serge 1366
        mov     ecx, 2
261 hidnplayr 1367
.mac_loop:
2434 Serge 1368
        lea     ax, [E3C59X_EEPROM_REG_OEM_NODE_ADDR+ecx]
1369
        call    e3c59x_read_eeprom
1370
        xchg    ah, al ; htons
1371
        mov     [node_addr+ecx*2], ax
1372
        dec     ecx
1373
        jns     .mac_loop
1374
        test    byte [e3c59x_full_bus_master], 0xff
1375
        jz      .set_preamble
261 hidnplayr 1376
; switch to register window 2
2434 Serge 1377
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1378
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+2
1379
        out     dx, ax
261 hidnplayr 1380
; activate xcvr by setting some magic bits
2434 Serge 1381
        lea     edx, [ebp+E3C59X_REG_RESET_OPTIONS]
1382
        in      ax, dx
1383
        and     ax, not 0x4010
1384
        movzx   ebx, byte [e3c59x_ver_id]
1385
        test    word [ebx*4+e3c59x_hw_versions+2], INVERT_LED_PWR
1386
        jz      @f
1387
        or      al, 0x10
261 hidnplayr 1388
@@:
2434 Serge 1389
        test    word [ebx*4+e3c59x_hw_versions+2], INVERT_MII_PWR
1390
        jz      @f
1391
        or      ah, 0x40
261 hidnplayr 1392
@@:
2434 Serge 1393
        out     dx, ax
261 hidnplayr 1394
.set_preamble:
1395
; use preamble as default
2434 Serge 1396
        mov     byte [e3c59x_preamble], 1 ; enable preamble
261 hidnplayr 1397
 
1398
;***************************************************************************
1399
;   Function
1400
;      e3c59x_reset
1401
;   Description
1402
;      Place the chip (ie, the ethernet card) into a virgin state
1403
;   Destroyed registers
1404
;      eax, ebx, ecx, edx, edi, esi
1405
;
1406
;***************************************************************************
1407
e3c59x_reset:
1408
; issue global reset
2434 Serge 1409
        call    e3c59x_global_reset
261 hidnplayr 1410
; disable interrupts
2434 Serge 1411
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1412
        mov     ax, (1110b shl 11)
1413
        out     dx, ax
261 hidnplayr 1414
; enable Statistics
2434 Serge 1415
        mov     ax, (10101b shl 11)
1416
        out     dx, ax
261 hidnplayr 1417
; set indication
2434 Serge 1418
        mov     ax, (1111b shl 11) or 0x6c6
1419
        out     dx, ax
261 hidnplayr 1420
; acknowledge (clear) every interrupt indicator
2434 Serge 1421
        mov     ax, (1101b shl 11) or 0x661
1422
        out     dx, ax
261 hidnplayr 1423
; switch to register window 2
2434 Serge 1424
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+2
1425
        out     dx, ax
261 hidnplayr 1426
; write MAC addres back into the station address registers
2434 Serge 1427
        lea     edx, [ebp+E3C59X_REG_STATION_ADDRESS_LO]
1428
        mov     esi, node_addr
1429
        cld
1430
        outsw
1431
        add     edx, 2
1432
        outsw
1433
        add     edx, 2
1434
        outsw
1435
        add     edx, 2
261 hidnplayr 1436
; clear station mask
2434 Serge 1437
        xor     eax, eax
1438
        out     dx, ax
1439
        add     edx, 2
1440
        out     dx, ax
1441
        add     edx, 2
1442
        out     dx, ax
261 hidnplayr 1443
; switch to register window 6
2434 Serge 1444
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1445
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+6
1446
        out     dx, ax
261 hidnplayr 1447
; clear all statistics by reading
2434 Serge 1448
        lea     edx, [ebp+E3C59X_REG_CARRIER_LOST]
1449
        mov     cl, 9
261 hidnplayr 1450
.stat_clearing_loop:
2434 Serge 1451
        in      al, dx
1452
        inc     edx
1453
        dec     cl
1454
        jns     .stat_clearing_loop
1455
        in      ax, dx
1456
        add     dx, 2
1457
        in      ax, dx
261 hidnplayr 1458
; switch to register window 4
2434 Serge 1459
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1460
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
1461
        out     dx, ax
261 hidnplayr 1462
; clear BadSSD
2434 Serge 1463
        lea     edx, [ebp+E3C59X_REG_BAD_SSD]
1464
        in      al, dx
261 hidnplayr 1465
; clear extra statistics bit in NetworkDiagnostic
2434 Serge 1466
        lea     edx, [ebp+E3C59X_REG_NETWORK_DIAGNOSTIC]
1467
        in      ax, dx
1468
        or      ax, 0x0040
1469
        out     dx, ax
261 hidnplayr 1470
; SetRxEarlyThreshold
2434 Serge 1471
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1472
        mov     ax, (10001b shl 11)+(E3C59X_MAX_ETH_PKT_SIZE shr 2)
1473
        out     dx, ax
1474
        test    byte [e3c59x_full_bus_master], 0xff
1475
        jz      .skip_boomerang_setting
261 hidnplayr 1476
; set upRxEarlyEnable
2434 Serge 1477
        lea     edx, [ebp+E3C59X_REG_DMA_CTRL]
1478
        in      eax, dx
1479
        or      eax, 0x20
1480
        out     dx, eax
261 hidnplayr 1481
; TxFreeThreshold
2434 Serge 1482
        lea     edx, [ebp+E3C59X_REG_TX_FREE_THRESH]
1483
        mov     al, (E3C59X_MAX_ETH_PKT_SIZE / 256)
1484
        out     dx, al
261 hidnplayr 1485
; program DnListPtr
2434 Serge 1486
        lea     edx, [ebp+E3C59X_REG_DN_LIST_PTR]
1487
        xor     eax, eax
1488
        out     dx, eax
261 hidnplayr 1489
.skip_boomerang_setting:
1490
; initialization
2434 Serge 1491
        call    e3c59x_rx_reset
1492
        call    e3c59x_tx_reset
1493
        call    e3c59x_set_active_port
1494
        call    e3c59x_rx_reset
1495
        call    e3c59x_tx_reset
261 hidnplayr 1496
; switch to register window 5
2434 Serge 1497
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1498
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+5
1499
        out     dx, ax
261 hidnplayr 1500
; program RxFilter for promiscuous operation
2434 Serge 1501
        mov     ax, (10000b shl 11)
1502
        lea     edx, [ebp+E3C59X_REG_RX_FILTER]
1503
        in      al, dx
1504
        or      al, 1111b
1505
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1506
        out     dx, ax
261 hidnplayr 1507
; switch to register window 4
2434 Serge 1508
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
1509
        out     dx, ax
261 hidnplayr 1510
; wait for linkDetect
2434 Serge 1511
        lea     edx, [ebp+E3C59X_REG_MEDIA_STATUS]
1512
        mov     cl, 20 ; wait for max 2s
1513
        mov     esi, 100 ; 100ms
261 hidnplayr 1514
.link_detect_loop:
2434 Serge 1515
        call    delay_ms
1516
        in      ax, dx
1517
        test    ah, 1000b ; linkDetect
1518
        jnz     @f
1519
        dec     cl
1520
        jnz     .link_detect_loop
261 hidnplayr 1521
@@:
1522
; Indicate that we have successfully reset the card
2434 Serge 1523
        mov     eax, [pci_data]
1524
        mov     [eth_status], eax
261 hidnplayr 1525
if defined E3C59X_DEBUG
2434 Serge 1526
        call    e3c59x_debug
261 hidnplayr 1527
end if ; defined E3C59X_DEBUG
2434 Serge 1528
        ret
261 hidnplayr 1529
 
1530
;***************************************************************************
1531
;   Function
1532
;      e3c59x_global_reset
1533
;   Description
1534
;      resets the device
1535
;   Parameters:
1536
;      ebp - io_addr
1537
;   Return value:
1538
;   Destroyed registers
1539
;      ax, ecx, edx, esi
1540
;
1541
;***************************************************************************
2434 Serge 1542
        align 4
261 hidnplayr 1543
e3c59x_global_reset:
1544
; GlobalReset
2434 Serge 1545
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1546
        xor     eax, eax
261 hidnplayr 1547
;       or      al, 0x14
2434 Serge 1548
        out     dx, ax
261 hidnplayr 1549
; wait for GlobalReset to complete
2434 Serge 1550
        mov     ecx, 64000
261 hidnplayr 1551
.global_reset_loop:
2434 Serge 1552
        in      ax, dx
1553
        test    ah, 10000b ; check CmdInProgress
1554
        jz      .finish
1555
        dec     ecx
1556
        jnz     .global_reset_loop
261 hidnplayr 1557
.finish:
1558
; wait for 2 seconds for NIC to boot
2434 Serge 1559
        mov     esi, 2000 ; 2000ms = 2s
1560
        push    ebp
1561
        call    delay_ms
1562
        pop     ebp
1563
        ret
261 hidnplayr 1564
 
1565
;***************************************************************************
1566
;   Function
1567
;      e3c59x_tx_reset
1568
;   Description
1569
;      resets and enables transmitter engine
1570
;   Parameters:
1571
;      ebp - io_addr
1572
;   Return value:
1573
;   Destroyed registers
1574
;      ax, ecx, edx
1575
;
1576
;***************************************************************************
2434 Serge 1577
        align 4
261 hidnplayr 1578
e3c59x_tx_reset:
1579
; TxReset
2434 Serge 1580
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1581
        mov     ax, (01011b shl 11)
1582
        out     dx, ax
1280 hidnplayr 1583
; Wait for TxReset to complete
2434 Serge 1584
        mov     ecx, 200000
261 hidnplayr 1585
.tx_reset_loop:
2434 Serge 1586
        in      ax, dx
1587
        test    ah, 10000b ; check CmdInProgress
1588
        jz      .tx_set_prev
1589
        dec     ecx
1590
        jns     .tx_reset_loop
1280 hidnplayr 1591
.tx_set_prev:
2434 Serge 1592
        test    byte [e3c59x_full_bus_master], 0xff
1593
        jz      .tx_enable
261 hidnplayr 1594
; init last_dpd
2434 Serge 1595
        mov     dword [e3c59x_prev_dpd], e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE
1596
        mov     dword [e3c59x_prev_tx_frame], e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE
261 hidnplayr 1597
.tx_enable:
2434 Serge 1598
        mov     ax, (01001b shl 11) ; TxEnable
1599
        out     dx, ax
1600
        ret
261 hidnplayr 1601
 
1602
;***************************************************************************
1603
;   Function
1604
;      e3c59x_rx_reset
1605
;   Description
1606
;      resets and enables receiver engine
1607
;   Parameters:
1608
;      ebp - io_addr
1609
;   Return value:
1610
;   Destroyed registers
1611
;      eax, ebx, ecx, edx, edi, esi
1612
;
1613
;***************************************************************************
2434 Serge 1614
        align 4
261 hidnplayr 1615
e3c59x_rx_reset:
2434 Serge 1616
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1617
        mov     ax, (0101b shl 11) or 0x4 ; RxReset
1618
        out     dx, ax
261 hidnplayr 1619
; wait for RxReset to complete
2434 Serge 1620
        mov     ecx, 200000
261 hidnplayr 1621
.rx_reset_loop:
2434 Serge 1622
        in      ax, dx
1623
        test    ah, 10000b ; check CmdInProgress
1624
        jz      .setup_upd
1625
        dec     ecx
1626
        jns     .rx_reset_loop
261 hidnplayr 1627
.setup_upd:
1628
; check if full bus mastering
2434 Serge 1629
        test    byte [e3c59x_full_bus_master], 0xff
1630
        jz      .rx_enable
261 hidnplayr 1631
; create upd ring
2434 Serge 1632
        mov     eax, e3c59x_upd_buff
1633
        zero_to_virt eax
1634
        mov     [e3c59x_curr_upd], eax
1635
        mov     esi, eax
1636
        virt_to_dma esi
1637
        mov     edi, e3c59x_rx_buff
1638
        zero_to_dma edi
1639
        mov     ebx, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE
1640
        zero_to_virt ebx
1641
        mov     cl, E3C59X_NUM_RX_DESC-1
261 hidnplayr 1642
.upd_loop:
2434 Serge 1643
        mov     [ebx+E3C59X_UPD_UP_NEXT_PTR], esi
1644
        and     dword [eax+E3C59X_UPD_PKT_STATUS], 0
1645
        mov     [eax+E3C59X_UPD_UP_FRAG_ADDR], edi
1646
        mov     dword [eax+E3C59X_UPD_UP_FRAG_LEN], E3C59X_MAX_ETH_FRAME_SIZE or (1 shl 31)
1647
        add     edi, E3C59X_MAX_ETH_FRAME_SIZE
1648
        add     esi, E3C59X_UPD_SIZE
1649
        mov     ebx, eax
1650
        add     eax, E3C59X_UPD_SIZE
1651
        dec     cl
1652
        jns     .upd_loop
1653
        mov     eax, e3c59x_upd_buff
1654
        zero_to_dma eax
1655
        lea     edx, [ebp+E3C59X_REG_UP_LIST_PTR]
1656
        out     dx, eax ; write E3C59X_REG_UP_LIST_PTR
1657
        lea     edx, [ebp+E3C59X_REG_COMMAND]
261 hidnplayr 1658
.rx_enable:
2434 Serge 1659
        mov     ax, (00100b shl 11) ; RxEnable
1660
        out     dx, ax
1661
        ret
261 hidnplayr 1662
 
1663
;***************************************************************************
1664
;   Function
1665
;      e3c59x_write_eeprom
1666
;   Description
1667
;      reads eeprom
1668
;      Note : the caller must switch to the register window 0
1669
;             before calling this function
1670
;   Parameters:
1671
;      ax - register to be read (only the first 63 words can be read)
1672
;      cx - value to be read into the register
1673
;   Return value:
1674
;      ax - word read
1675
;   Destroyed registers
1676
;      ax, ebx, edx
1677
;
1678
;***************************************************************************
1679
;       align 4
1680
;e3c59x_write_eeprom:
1681
;       mov     edx, [io_addr]
1682
;       add     edx, E3C59X_REG_EEPROM_COMMAND
1683
;       cmp     ah, 11b
1684
;       ja      .finish ; address may have a value of maximal 1023
1685
;       shl     ax, 2
1686
;       shr     al, 2
1687
;       push    eax
1688
;; wait for busy
1689
;       mov     ebx, 0xffff
1690
;@@:
1691
;       in      ax, dx
1692
;       test    ah, 0x80
1693
;       jz      .write_enable
1694
;       dec     ebx
1695
;       jns     @r
1696
;; write enable
1697
;.write_enable:
1698
;       xor     eax, eax
1699
;       mov     eax, (11b shl 4)
1700
;       out     dx, ax
1701
;; wait for busy
1702
;       mov     ebx, 0xffff
1703
;@@:
1704
;       in      ax, dx
1705
;       test    ah, 0x80
1706
;       jz      .erase_loop
1707
;       dec     ebx
1708
;       jns     @r
1709
;.erase_loop:
1710
;       pop     eax
1711
;       push    eax
1712
;       or      ax, (11b shl 6) ; erase register
1713
;       out     dx, ax
1714
;       mov     ebx, 0xffff
1715
;@@:
1716
;       in      ax, dx
1717
;       test    ah, 0x80
1718
;       jz      .write_reg
1719
;       dec     ebx
1720
;       jns     @r
1721
;.write_reg:
1722
;       add     edx, E3C59X_REG_EEPROM_DATA-E3C59X_REG_EEPROM_COMMAND
1723
;       mov     eax, ecx
1724
;       out     dx, ax
1725
;; write enable
1726
;       add     edx, E3C59X_REG_EEPROM_COMMAND-E3C59X_REG_EEPROM_DATA
1727
;       xor     eax, eax
1728
;       mov     eax, (11b shl 4)
1729
;       out     dx, ax
1730
; wait for busy
1731
;       mov     ebx, 0xffff
1732
;@@:
1733
;       in      ax, dx
1734
;       test    ah, 0x80
1735
;       jz      .issue_write_reg
1736
;       dec     ebx
1737
;       jns     @r
1738
;.issue_write_reg:
1739
;       pop     eax
1740
;       or      ax, 01b shl 6
1741
;       out     dx, ax
1742
;.finish:
1743
;       ret
1744
;***************************************************************************
1745
;   Function
1746
;      e3c59x_read_eeprom
1747
;   Description
1748
;      reads eeprom
1749
;   Parameters:
1750
;       ax - register to be read (only the first 63 words can be read)
1751
;      ebp - io_addr
1752
;   Return value:
1753
;      ax - word read
1754
;   Destroyed registers
1755
;      ax, ebx, edx, ebp
1756
;
1757
;***************************************************************************
2434 Serge 1758
        align 4
261 hidnplayr 1759
e3c59x_read_eeprom:
2434 Serge 1760
        push    eax
261 hidnplayr 1761
; switch to register window 0
2434 Serge 1762
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1763
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+0
1764
        out     dx, ax
1765
        pop     eax
1766
        and     ax, 111111b ; take only the first 6 bits into account
1767
        movzx   ebx, byte [e3c59x_ver_id]
1768
        test    word [ebx*4+e3c59x_hw_versions+2], EEPROM_8BIT
1769
        jz      @f
1770
        add     ax, 0x230 ; hardware constant
1771
        jmp     .read
261 hidnplayr 1772
@@:
2434 Serge 1773
        add     ax, E3C59X_EEPROM_CMD_READ
1774
        test    word [ebx*4+e3c59x_hw_versions+2], EEPROM_OFFSET
1775
        jz      .read
1776
        add     ax, 0x30
261 hidnplayr 1777
.read:
2434 Serge 1778
        lea     edx, [ebp+E3C59X_REG_EEPROM_COMMAND]
1779
        out     dx, ax
1780
        mov     ebx, 0xffff ; duration of about 162 us ;-)
261 hidnplayr 1781
.wait_for_reading:
2434 Serge 1782
        in      ax, dx
1783
        test    ah, 0x80 ; check bit eepromBusy
1784
        jz      .read_data
1785
        dec     ebx
1786
        jns     .wait_for_reading
261 hidnplayr 1787
.read_data:
2434 Serge 1788
        lea     edx, [ebp+E3C59X_REG_EEPROM_DATA]
1789
        in      ax, dx
1790
        ret
261 hidnplayr 1791
 
1792
;***************************************************************************
1793
;   Function
1794
;      e3c59x_mdio_sync
1795
;   Description
1796
;      initial synchronization
1797
;   Parameters
1798
;      ebp - io_addr
1799
;   Return value
1800
;   Destroyed registers
1801
;      ax, edx, cl
1802
;
1803
;***************************************************************************
2434 Serge 1804
        align 4
261 hidnplayr 1805
e3c59x_mdio_sync:
1806
; switch to register window 4
2434 Serge 1807
        lea     edx, [ebp+E3C59X_REG_COMMAND]
1808
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+4
1809
        out     dx, ax
1810
        cmp     byte [e3c59x_preamble], 0
1811
        je      .no_preamble
261 hidnplayr 1812
; send 32 logic ones
2434 Serge 1813
        lea     edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
1814
        mov     cl, 31
261 hidnplayr 1815
.loop:
2434 Serge 1816
        mov     ax, (1 shl E3C59X_BIT_MGMT_DATA) or (1 shl E3C59X_BIT_MGMT_DIR)
1817
        out     dx, ax
1818
        in      ax, dx ; delay
1819
        mov     ax, (1 shl E3C59X_BIT_MGMT_DATA) \
1820
                or (1 shl E3C59X_BIT_MGMT_DIR) \
1821
                or (1 shl E3C59X_BIT_MGMT_CLK)
1822
        out     dx, ax
1823
        in      ax, dx ; delay
1824
        dec     cl
1825
        jns     .loop
261 hidnplayr 1826
.no_preamble:
2434 Serge 1827
        ret
261 hidnplayr 1828
 
1829
;***************************************************************************
1830
;   Function
1831
;      e3c59x_mdio_read
1832
;   Description
1833
;      read MII register
1834
;      see page 16 in D83840A.pdf
1835
;   Parameters
1836
;       ah - PHY addr
1837
;       al - register addr
1838
;      ebp - io_addr
1839
;   Return value
1840
;      ax - register read
1841
;   Destroyed registers
1842
;      eax, ebx, cx, edx
1843
;
1844
;***************************************************************************
2434 Serge 1845
        align 4
261 hidnplayr 1846
e3c59x_mdio_read:
2434 Serge 1847
        push    eax
1848
        call    e3c59x_mdio_sync ; returns with window #4
1849
        pop     eax
1850
        lea     edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
1851
        shl     al, 3
1852
        shr     ax, 3
1853
        and     ax, not E3C59X_MII_CMD_MASK
1854
        or      ax, E3C59X_MII_CMD_READ
1855
        mov     ebx, eax
1856
        xor     ecx, ecx
1857
        mov     cl, 13
261 hidnplayr 1858
.cmd_loop:
2434 Serge 1859
        mov     ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii
1860
        bt      ebx, ecx
1861
        jnc     .zero_bit
1862
        or      al, (1 shl E3C59X_BIT_MGMT_DATA)
261 hidnplayr 1863
.zero_bit:
2434 Serge 1864
        out     dx, ax
1865
        push    eax
1866
        in      ax, dx ; delay
1867
        pop     eax
1868
        or      al, (1 shl E3C59X_BIT_MGMT_CLK) ; write
1869
        out     dx, ax
1870
        in      ax, dx ; delay
1871
        dec     cl
1872
        jns     .cmd_loop
261 hidnplayr 1873
; read data (18 bits with the two transition bits)
2434 Serge 1874
        mov     cl, 17
1875
        xor     ebx, ebx
261 hidnplayr 1876
.read_loop:
2434 Serge 1877
        shl     ebx, 1
1878
        xor     eax, eax ; read comand
1879
        out     dx, ax
1880
        in      ax, dx ; delay
1881
        in      ax, dx
1882
        test    al, (1 shl E3C59X_BIT_MGMT_DATA)
1883
        jz      .dont_set
1884
        inc     ebx
261 hidnplayr 1885
.dont_set:
2434 Serge 1886
        mov     ax, (1 shl E3C59X_BIT_MGMT_CLK)
1887
        out     dx, ax
1888
        in      ax, dx ; delay
1889
        dec     cl
1890
        jns     .read_loop
1891
        mov     eax, ebx
1892
        ret
261 hidnplayr 1893
 
1894
;***************************************************************************
1895
;   Function
1896
;      e3c59x_mdio_write
1897
;   Description
1898
;      write MII register
1899
;      see page 16 in D83840A.pdf
1900
;   Parameters
1901
;       ah - PHY addr
1902
;       al - register addr
1903
;       bx - word to be written
1904
;      ebp - io_addr
1905
;   Return value
1906
;      ax - register read
1907
;   Destroyed registers
1908
;      eax, ebx, cx, edx
1909
;
1910
;***************************************************************************
2434 Serge 1911
        align 4
261 hidnplayr 1912
e3c59x_mdio_write:
2434 Serge 1913
        push    eax
1914
        call    e3c59x_mdio_sync
1915
        pop     eax
1916
        lea     edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
1917
        shl     al, 3
1918
        shr     ax, 3
1919
        and     ax, not E3C59X_MII_CMD_MASK
1920
        or      ax, E3C59X_MII_CMD_WRITE
1921
        shl     eax, 2
1922
        or      eax, 10b ; transition bits
1923
        shl     eax, 16
1924
        mov     ax, bx
1925
        mov     ebx, eax
1926
        mov     ecx, 31
261 hidnplayr 1927
.cmd_loop:
2434 Serge 1928
        mov     ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii
1929
        bt      ebx, ecx
1930
        jnc     .zero_bit
1931
        or      al, (1 shl E3C59X_BIT_MGMT_DATA)
261 hidnplayr 1932
.zero_bit:
2434 Serge 1933
        out     dx, ax
1934
        push    eax
1935
        in      ax, dx ; delay
1936
        pop     eax
1937
        or      al, (1 shl E3C59X_BIT_MGMT_CLK) ; write
1938
        out     dx, ax
1939
        in      ax, dx ; delay
1940
        dec     ecx
1941
        jns     .cmd_loop
1942
        ret
261 hidnplayr 1943
 
1944
;***************************************************************************
1945
;   Function
1946
;      e3c59x_transmit
1947
;   Description
1948
;      Transmits a packet of data via the ethernet card
1949
;         edi - Pointer to 48 bit destination address
1950
;          bx - Type of packet
1951
;         ecx - size of packet
1952
;         esi - pointer to packet data
1953
;         ebp - io_addr
1954
;   Destroyed registers
1955
;      eax, ecx, edx, ebp
1956
;
1957
;***************************************************************************
2434 Serge 1958
        align 4
261 hidnplayr 1959
e3c59x_transmit:
2434 Serge 1960
        jmp     dword [e3c59x_transmit_function]
261 hidnplayr 1961
 
1962
;***************************************************************************
1963
;   Function
1964
;      e3c59x_check_tx_status
1965
;   Description
1966
;      Checks TxStatus queue.
1967
;   Return value
1968
;      al - 0 no error was found
1969
;      al - 1 error was found TxReset is needed
1970
;   Destroyed registers
1971
;      eax, ecx, edx, ebp
1972
;
1973
;***************************************************************************
1974
e3c59x_check_tx_status:
2434 Serge 1975
        movzx   ebp, word [io_addr] ; to be implemented in ETHERNET.INC
261 hidnplayr 1976
; clear TxStatus queue
2434 Serge 1977
        lea     edx, [ebp+E3C59X_REG_TX_STATUS]
1978
        mov     cl, 31 ; max number of queue entries
261 hidnplayr 1979
.tx_status_loop:
2434 Serge 1980
        in      al, dx
1981
        test    al, al
1982
        jz      .finish ; no error
1983
        test    al, 0x3f
1984
        jnz     .finish ; error
261 hidnplayr 1985
.no_error_found:
1986
; clear current TxStatus entry which advances the next one
2434 Serge 1987
        xor     al, al
1988
        out     dx, al
1989
        dec     cl
1990
        jns     .tx_status_loop
261 hidnplayr 1991
.finish:
2434 Serge 1992
        ret
261 hidnplayr 1993
 
1994
;***************************************************************************
1995
;   Function
1996
;      e3c59x_vortex_transmit
1997
;   Description
1998
;      Transmits a packet of data via the ethernet card
1999
;         edi - Pointer to 48 bit destination address
2000
;          bx - Type of packet
2001
;         ecx - size of packet
2002
;         esi - pointer to packet data
2003
;         ebp - io_addr
2004
;   Destroyed registers
2005
;      eax, edx, ecx, edi, esi, ebp
2006
;
2007
;***************************************************************************
2434 Serge 2008
        align 4
261 hidnplayr 2009
e3c59x_vortex_transmit:
2434 Serge 2010
        push    ecx
2011
        call    e3c59x_check_tx_status
2012
        pop     ecx
2013
        test    al, al
2014
        jz      .no_error_found
2015
        jmp     e3c59x_tx_reset
261 hidnplayr 2016
.no_error_found:
2017
; switch to register window 7
2434 Serge 2018
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2019
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+7
2020
        out     dx, ax
261 hidnplayr 2021
; check for master operation in progress
2434 Serge 2022
        lea     edx, [ebp+E3C59X_REG_MASTER_STATUS]
2023
        in      ax, dx
2024
        test    ah, 0x80
2025
        jnz     .finish ; no DMA for sending
261 hidnplayr 2026
; dword boundary correction
2434 Serge 2027
        cmp     ecx, E3C59X_MAX_ETH_FRAME_SIZE
2028
        ja      .finish ; packet is too long
261 hidnplayr 2029
; write Frame Start Header
2434 Serge 2030
        mov     eax, ecx
261 hidnplayr 2031
; add header length and extend the complete length to dword boundary
2434 Serge 2032
        add     eax, ETH_HLEN+3
2033
        and     eax, not 3
2034
        lea     edx, [ebp+E3C59X_REG_TX_DATA]
2035
        out     dx, eax
261 hidnplayr 2036
; prepare the complete frame
2434 Serge 2037
        push    esi
2038
        mov     esi, edi
2039
        mov     edi, e3c59x_tx_buff
2040
        zero_to_virt edi
2041
        cld
261 hidnplayr 2042
; copy destination address
2434 Serge 2043
        movsd
2044
        movsw
261 hidnplayr 2045
; copy source address
2434 Serge 2046
        mov     esi, node_addr
2047
        movsd
2048
        movsw
261 hidnplayr 2049
; copy packet type
2434 Serge 2050
        mov     [edi], bx
2051
        add     edi, 2
261 hidnplayr 2052
; copy packet data
2434 Serge 2053
        pop     esi
2054
        push    ecx
2055
        shr     ecx, 2
2056
        rep movsd
2057
        pop     ecx
2058
        and     ecx, 3
2059
        rep movsb
2060
        mov     ecx, eax
261 hidnplayr 2061
; program frame address to be sent
2434 Serge 2062
        lea     edx, [ebp+E3C59X_REG_MASTER_ADDRESS]
2063
        mov     eax, e3c59x_tx_buff
2064
        zero_to_dma eax
2065
        out     dx, eax
261 hidnplayr 2066
; program frame length
2434 Serge 2067
        lea     edx, [ebp+E3C59X_REG_MASTER_LEN]
2068
        mov     eax, ecx
2069
        out     dx, ax
261 hidnplayr 2070
; start DMA Down
2434 Serge 2071
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2072
        mov     ax, (10100b shl 11) + 1 ; StartDMADown
2073
        out     dx, ax
261 hidnplayr 2074
.finish:
2434 Serge 2075
        ret
261 hidnplayr 2076
 
2077
;***************************************************************************
2078
;   Function
2079
;      e3c59x_boomerang_transmit
2080
;   Description
2081
;      Transmits a packet of data via the ethernet card
2082
;         edi - Pointer to 48 bit destination address
2083
;          bx - Type of packet
2084
;         ecx - size of packet
2085
;         esi - pointer to packet data
2086
;         ebp - io_addr
2087
;   Destroyed registers
2088
;      eax, ebx, ecx, edx, esi, edi, ebp
2089
;
2090
;***************************************************************************
2434 Serge 2091
        align 4
261 hidnplayr 2092
e3c59x_boomerang_transmit:
2434 Serge 2093
        push    ecx
2094
        call    e3c59x_check_tx_status
2095
        pop     ecx
2096
        test    al, al
2097
        jz      .no_error_found
2098
        jmp     e3c59x_tx_reset
261 hidnplayr 2099
.no_error_found:
2434 Serge 2100
        cmp     ecx, E3C59X_MAX_ETH_FRAME_SIZE
2101
        ja      .finish ; packet is too long
261 hidnplayr 2102
; calculate descriptor address
2434 Serge 2103
        mov     eax, [e3c59x_prev_dpd]
2104
        cmp     eax, e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE
2105
        jb      @f
261 hidnplayr 2106
; wrap around
2434 Serge 2107
        mov     eax, e3c59x_dpd_buff-E3C59X_DPD_SIZE
261 hidnplayr 2108
@@:
2434 Serge 2109
        add     eax, E3C59X_DPD_SIZE
2110
        zero_to_virt eax
2111
        push    eax
261 hidnplayr 2112
; check DnListPtr
2434 Serge 2113
        lea     edx, [ebp+E3C59X_REG_DN_LIST_PTR]
2114
        in      eax, dx
261 hidnplayr 2115
; mark if Dn_List_Ptr is cleared
2434 Serge 2116
        test    eax, eax
2117
        setz    [e3c59x_dn_list_ptr_cleared]
261 hidnplayr 2118
; finish if no more free descriptor is available - FIXME!
2434 Serge 2119
        cmp     eax, [esp]
2120
        pop     eax
2121
        jz      .finish
2122
        push    eax esi
2123
        mov     esi, edi
261 hidnplayr 2124
; calculate tx_buffer address
2434 Serge 2125
        mov     edi, [e3c59x_prev_tx_frame]
2126
        cmp     edi, e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE
2127
        jb      @f
261 hidnplayr 2128
; wrap around
2434 Serge 2129
        mov     edi, e3c59x_tx_buff-E3C59X_MAX_ETH_FRAME_SIZE
261 hidnplayr 2130
@@:
2434 Serge 2131
        add     edi, E3C59X_MAX_ETH_FRAME_SIZE
2132
        zero_to_virt edi
2133
        mov     eax, edi
2134
        cld
261 hidnplayr 2135
; copy destination address
2434 Serge 2136
        movsd
2137
        movsw
261 hidnplayr 2138
; copy source address
2434 Serge 2139
        mov     esi, node_addr
2140
        movsd
2141
        movsw
261 hidnplayr 2142
; copy packet type
2434 Serge 2143
        mov     [edi], bx
2144
        add     edi, 2
261 hidnplayr 2145
; copy packet data
2434 Serge 2146
        pop     esi
2147
        push    ecx
2148
        shr     ecx, 2
2149
        rep movsd
2150
        pop     ecx
2151
        push    ecx
2152
        and     ecx, 3
2153
        rep movsb
261 hidnplayr 2154
; padding, do we really need it?
2434 Serge 2155
        pop     ecx
2156
        add     ecx, ETH_HLEN
2157
        cmp     ecx, ETH_ZLEN
2158
        jae     @f
2159
        mov     ecx, ETH_ZLEN
261 hidnplayr 2160
@@:
2161
; calculate
2434 Serge 2162
        mov     ebx, ecx
2163
        ;test   byte [e3c59x_has_hwcksm], 0xff
2164
        ;jz     @f
2165
        ;or      ebx, (1 shl 26) ; set AddTcpChecksum
1288 tsdima 2166
;@@:
2434 Serge 2167
        or      ebx, 0x8000 ; transmission complete notification
2168
        or      ecx, 0x80000000 ; last fragment
261 hidnplayr 2169
; program DPD
2434 Serge 2170
        mov     edi, eax
2171
        pop     eax
2172
        and     dword [eax+E3C59X_DPD_DN_NEXT_PTR], 0
2173
        mov     dword [eax+E3C59X_DPD_FRAME_START_HDR], ebx
2174
        virt_to_dma edi
2175
        mov     dword [eax+E3C59X_DPD_DN_FRAG_ADDR], edi
2176
        mov     [eax+E3C59X_DPD_DN_FRAG_LEN], ecx
261 hidnplayr 2177
; calculate physical address
2434 Serge 2178
        virt_to_dma eax
2179
        push    eax
2180
        cmp     byte [e3c59x_dn_list_ptr_cleared], 0
2181
        jz      .add_to_list
261 hidnplayr 2182
; write Dn_List_Ptr
2434 Serge 2183
        out     dx, eax
2184
        jmp     .finish
261 hidnplayr 2185
.add_to_list:
2186
; DnStall
2434 Serge 2187
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2188
        mov     ax, ((110b shl 11)+2)
2189
        out     dx, ax
261 hidnplayr 2190
; wait for DnStall to complete
2434 Serge 2191
        mov     ecx, 6000
261 hidnplayr 2192
.wait_for_stall:
2434 Serge 2193
        in      ax, dx ; read E3C59X_REG_INT_STATUS
2194
        test    ah, 10000b
2195
        jz      .dnstall_ok
2196
        dec     ecx
2197
        jnz     .wait_for_stall
261 hidnplayr 2198
.dnstall_ok:
2434 Serge 2199
        pop     eax
2200
        push    eax
2201
        mov     ebx, [e3c59x_prev_dpd]
2202
        zero_to_virt ebx
2203
        mov     [ebx], eax
2204
        lea     edx, [ebp+E3C59X_REG_DN_LIST_PTR]
2205
        in      eax, dx
2206
        test    eax, eax
2207
        jnz     .dnunstall
261 hidnplayr 2208
; if Dn_List_Ptr has been cleared fill it up
2434 Serge 2209
        pop     eax
2210
        push    eax
2211
        out     dx, eax
261 hidnplayr 2212
.dnunstall:
2213
; DnUnStall
2434 Serge 2214
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2215
        mov     ax, ((110b shl 11)+3)
2216
        out     dx, ax
261 hidnplayr 2217
.finish:
2434 Serge 2218
        pop     eax
2219
        dma_to_zero eax
2220
        mov     [e3c59x_prev_dpd], eax
2221
        dma_to_zero edi
2222
        mov     [e3c59x_prev_tx_frame], edi
2223
        ret
261 hidnplayr 2224
 
2225
;***************************************************************************
2226
; Function
2227
;    e3c59x_poll
2228
; Description
2229
;    Polls the ethernet card for a received packet
2230
;    Received data, if any, ends up in Ether_buffer
2231
; Destroyed registers
2232
;    eax, ebx, edx, ecx, edi, esi, ebp
2233
;
2234
;***************************************************************************
2434 Serge 2235
        align 4
261 hidnplayr 2236
e3c59x_poll:
2434 Serge 2237
        jmp     dword [e3c59x_receive_function]
261 hidnplayr 2238
 
2239
;***************************************************************************
2240
; Function
2241
;    e3c59x_vortex_poll
2242
; Description
2243
;    Polls the ethernet card for a received packet
2244
;    Received data, if any, ends up in Ether_buffer
2245
; Parameters
2246
;    ebp - io_addr
2247
; Return value
2248
;    al - 0 ; no packet received
2249
;    al - 1 ; packet received
2250
; Destroyed registers
2251
;    eax, ebx, edx, ecx, edi, esi, ebp
2252
;
2253
;***************************************************************************
2434 Serge 2254
        align 4
261 hidnplayr 2255
e3c59x_vortex_poll:
2434 Serge 2256
        and     word [eth_rx_data_len], 0 ; assume no packet received
2257
        movzx   ebp, word [io_addr] ; to be implemented in ETHERNET.INC
261 hidnplayr 2258
.rx_status_loop:
2259
; examine RxStatus
2434 Serge 2260
        lea     edx, [ebp+E3C59X_REG_RX_STATUS]
2261
        in      ax, dx
2262
        test    ax, ax
2263
        jz      .finish
2264
        test    ah, 0x80 ; rxIncomplete
2265
        jz      .check_error
2266
        jmp     .finish
261 hidnplayr 2267
.check_error:
2434 Serge 2268
        test    ah, 0x40
2269
        jz      .check_length
261 hidnplayr 2270
; discard the top frame received advancing the next one
2434 Serge 2271
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2272
        mov     ax, (01000b shl 11)
2273
        out     dx, ax
2274
        jmp     .rx_status_loop
261 hidnplayr 2275
.check_length:
2434 Serge 2276
        and     eax, 0x1fff
2277
        cmp     eax, E3C59X_MAX_ETH_PKT_SIZE
2278
        ja      .discard_frame ; frame is too long discard it
261 hidnplayr 2279
.check_dma:
2434 Serge 2280
        push    eax
261 hidnplayr 2281
; switch to register window 7
2434 Serge 2282
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2283
        mov     ax, E3C59X_SELECT_REGISTER_WINDOW+7
2284
        out     dx, ax
261 hidnplayr 2285
; check for master operation in progress
2434 Serge 2286
        lea     edx, [ebp+E3C59X_REG_MASTER_STATUS]
2287
        in      ax, dx
2288
        test    ah, 0x80
2289
        jz      .read_frame ; no DMA for receiving
2290
        pop     eax
2291
        jmp     .finish
261 hidnplayr 2292
.read_frame:
2293
; program buffer address to read in
2434 Serge 2294
        lea     edx, [ebp+E3C59X_REG_MASTER_ADDRESS]
261 hidnplayr 2295
if defined E3C59X_LINUX
2434 Serge 2296
        mov     eax, e3c59x_rx_buff
2297
        zero_to_dma eax
261 hidnplayr 2298
else
2434 Serge 2299
        mov     eax, Ether_buffer
261 hidnplayr 2300
end if
2434 Serge 2301
        out     dx, eax
261 hidnplayr 2302
; program frame length
2434 Serge 2303
        lea     edx, [ebp+E3C59X_REG_MASTER_LEN]
2304
        mov     ax, 1560
2305
        out     dx, ax
261 hidnplayr 2306
; start DMA Up
2434 Serge 2307
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2308
        mov     ax, (10100b shl 11) ; StartDMAUp
2309
        out     dx, ax
261 hidnplayr 2310
; check for master operation in progress
2311
.dma_loop:
2434 Serge 2312
        lea     edx, [ebp+E3C59X_REG_MASTER_STATUS]
2313
        in      ax, dx
2314
        test    ah, 0x80
2315
        jnz     .dma_loop
261 hidnplayr 2316
; registrate the received packet length
2434 Serge 2317
        pop     eax
2318
        mov     word [eth_rx_data_len], ax
261 hidnplayr 2319
; discard the top frame received
2320
.discard_frame:
2434 Serge 2321
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2322
        mov     ax, (01000b shl 11)
2323
        out     dx, ax
261 hidnplayr 2324
.finish:
2325
; set return value
2434 Serge 2326
        cmp     word [eth_rx_data_len], 0
2327
        setne   al
2328
        ret
261 hidnplayr 2329
 
2330
;***************************************************************************
2331
; Function
2332
;    e3c59x_boomerang_poll
2333
; Description
2334
;    Polls the ethernet card for a received packet
2335
;    Received data, if any, ends up in Ether_buffer
2336
; Parameters
2337
;    ebp - io_addr
2338
; Return value
2339
;    al - 0 ; no packet received
2340
;    al - 1 ; packet received
2341
; Destroyed registers
2342
;    eax, edx, ecx, edi, esi, ebp
2343
;
2344
;***************************************************************************
2434 Serge 2345
        align 4
261 hidnplayr 2346
e3c59x_boomerang_poll:
2434 Serge 2347
        and     word [eth_rx_data_len], 0 ; assume no packet received
2348
        movzx   ebp, word [io_addr] ; to be implemented in ETHERNET.INC
261 hidnplayr 2349
; check if packet is uploaded
2434 Serge 2350
        mov     eax, [e3c59x_curr_upd]
2351
        test    byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x80 ; upPktComplete
2352
        jnz     .check_error
2353
        jmp     .finish
261 hidnplayr 2354
; packet is uploaded check for any error
2355
.check_error:
2434 Serge 2356
        test    byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x40 ; upError
2357
        jz      .copy_packet_length
2358
        and     dword [eax+E3C59X_UPD_PKT_STATUS], 0
2359
        jmp     .finish
261 hidnplayr 2360
.copy_packet_length:
2434 Serge 2361
        mov     ecx, [eax+E3C59X_UPD_PKT_STATUS]
2362
        and     ecx, 0x1fff
2363
        cmp     ecx, E3C59X_MAX_ETH_PKT_SIZE
2364
        jbe     .copy_packet
2365
        and     dword [eax+E3C59X_UPD_PKT_STATUS], 0
2366
        jmp     .finish
261 hidnplayr 2367
.copy_packet:
2434 Serge 2368
        push    ecx
2369
        mov     word [eth_rx_data_len], cx
2370
        mov     esi, [eax+E3C59X_UPD_UP_FRAG_ADDR]
2371
        dma_to_virt esi
2372
        mov     edi, Ether_buffer
2373
        shr     ecx, 2 ; first copy dword-wise
2374
        cld
2375
        rep movsd     ; copy the dwords
2376
        pop     ecx
2377
        and     ecx, 3
2378
        rep movsb     ; copy the rest bytes
2379
        mov     eax, [e3c59x_curr_upd]
2380
        and     dword [eax+E3C59X_UPD_PKT_STATUS], 0
2381
        virt_to_zero eax
2382
        cmp     eax, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE
2383
        jb      .no_wrap
261 hidnplayr 2384
; wrap around
2434 Serge 2385
        mov     eax, e3c59x_upd_buff-E3C59X_UPD_SIZE
261 hidnplayr 2386
.no_wrap:
2434 Serge 2387
        add     eax, E3C59X_UPD_SIZE
2388
        zero_to_virt eax
2389
        mov     [e3c59x_curr_upd], eax
261 hidnplayr 2390
.finish:
2391
; check if the NIC is in the upStall state
2434 Serge 2392
        lea     edx, [ebp+E3C59X_REG_UP_PKT_STATUS]
2393
        in      eax, dx
2394
        test    ah, 0x20 ; UpStalled
2395
        jz      .noUpUnStall
261 hidnplayr 2396
; issue upUnStall command
2434 Serge 2397
        lea     edx, [ebp+E3C59X_REG_COMMAND]
2398
        mov     ax, ((110b shl 11)+1) ; upUnStall
2399
        out     dx, ax
261 hidnplayr 2400
.noUpUnStall:
2401
; set return value
2434 Serge 2402
        cmp     word [eth_rx_data_len], 0
2403
        setnz   al
2404
        ret