Subversion Repositories Kolibri OS

Rev

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

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