Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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