Subversion Repositories Kolibri OS

Rev

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

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