Subversion Repositories Kolibri OS

Rev

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

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