Subversion Repositories Kolibri OS

Rev

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

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