Subversion Repositories Kolibri OS

Rev

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

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