Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1472 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
1519 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
1472 hidnplayr 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
1519 hidnplayr 6
;;  3Com network driver for KolibriOS                           ;;
7
;;                                                              ;;
8
;;  Ported to KolibriOS net-branch by hidnplayr (28/05/10)      ;;
9
;;                                                              ;;
10
;;  Thanks to: scrap metal recyclers, whom provide me with      ;;
11
;;                         loads of hardware                    ;;
12
;;             diamond: who makes me understand KolibriOS       ;;
13
;;                                                              ;;
1472 hidnplayr 14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
;;                                                                         ;;
18
;;  3C59X.INC                                                              ;;
19
;;                                                                         ;;
20
;;  Ethernet driver for Menuet OS                                          ;;
21
;;                                                                         ;;
22
;;  Driver for 3Com fast etherlink 3c59x and                               ;;
23
;;         etherlink XL 3c900 and 3c905 cards                              ;;
24
;;  References:                                                            ;;
25
;;    www.3Com.com - data sheets                                           ;;
26
;;    DP83840A.pdf - ethernet physical layer                               ;;
27
;;    3c59x.c - linux driver                                               ;;
28
;;    ethernet driver template by Mike Hibbett                             ;;
29
;;                                                                         ;;
30
;;  Credits                                                                ;;
31
;;   Mike Hibbett,                                                         ;;
32
;;         who kindly supplied me with a 3Com905C-TX-M card                ;;
33
;;                                                                         ;;
34
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35
;;
36
;; Copyright (c) 2004, Endre Kozma 
37
;; All rights reserved.
38
;;
39
;; Redistribution  and  use  in  source  and  binary  forms, with or without
40
;; modification, are permitted provided  that  the following  conditions are
41
;; met:
42
;;
43
;; 1. Redistributions of source code must retain the above  copyright notice,
44
;;    this list of conditions and the following disclaimer.
45
;;
46
;; 2. Redistributions  in  binary form  must  reproduce  the above copyright
47
;;    notice, this  list of conditions  and the  following disclaimer in the
48
;;    documentation and/or other  materials  provided with  the distribution.
49
;;
50
;; 3. The name of the author may not be used to  endorse or promote products
51
;;    derived from this software without  specific prior  written permission.
52
;;
53
;; THIS SOFTWARE IS  PROVIDED  BY  THE  AUTHOR  ``AS IS'' AND ANY EXPRESS OR
54
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55
;; OF  MERCHANTABILITY AND FITNESS  FOR A PARTICULAR  PURPOSE ARE DISCLAIMED.
56
;; IN  NO  EVENT  SHALL  THE  AUTHOR  BE  LIABLE  FOR  ANY  DIRECT, INDIRECT,
57
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR  CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58
;; NOT LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59
;; DATA, OR  PROFITS; OR  BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON ANY
60
;; THEORY OF  LIABILITY, WHETHER IN  CONTRACT,  STRICT  LIABILITY,  OR  TORT
61
;; (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT OF THE USE OF
62
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63
;;
64
;;  History
65
;;  =======
66
;;  $Log: 3C59X.INC,v $
67
;;  Revision 1.3  2004/07/11 12:21:12  kozma
68
;;  Support of vortex chips (3c59x) added.
69
;;  Support of 3c920 and 3c982 added.
70
;;  Corrections.
71
;;
72
;;  Revision 1.2  2004/06/12 19:40:20  kozma
73
;;  Function e3c59x_set_available_media added in order to set
74
;;  the default media in case auto detection finds no valid link.
75
;;  Incorrect mii check removed (3c900 Cyclone works now).
76
;;  Cleanups.
77
;;
78
;;  Revision 1.1  2004/06/12 18:27:15  kozma
79
;;  Initial revision
80
;;
81
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
82
 
83
format MS COFF
84
 
85
	API_VERSION		equ 0x01000100
1519 hidnplayr 86
	DRIVER_VERSION		equ 5
1472 hidnplayr 87
 
1519 hidnplayr 88
	MAX_DEVICES		equ 16
89
	FORCE_FD		equ 0  ; forcing full duplex mode makes sense at some cards and link types
90
	PROMISCIOUS		equ 0  ; enables promiscous mode
91
 
1472 hidnplayr 92
	DEBUG			equ 1
93
	__DEBUG__		equ 1
94
	__DEBUG_LEVEL__ 	equ 1
95
 
96
include 'proc32.inc'
97
include 'imports.inc'
98
include 'fdo.inc'
99
include 'netdrv.inc'
100
 
101
public START
102
public service_proc
103
public version
104
 
105
struc DPD {	; Download Packet Descriptor
106
 
1519 hidnplayr 107
	.next_ptr	  dd ?
108
	.frame_start_hdr  dd ?
109
	.frag_addr	  dd ?	  ; for packet data
110
	.frag_len	  dd ?	  ; for packet data
111
	.realaddr	  dd ?
112
	.size		  = 32
1472 hidnplayr 113
}
114
 
115
virtual at 0
116
  dpd DPD
117
end virtual
118
 
119
 
120
struc UPD {	; Upload Packet Descriptor
121
 
1519 hidnplayr 122
	.next_ptr	dd ?
123
	.pkt_status	dd ?
124
	.frag_addr	dd ?
125
	.frag_len	dd ?	; for packet data
126
	.realaddr	dd ?
127
	.size		= 32
1472 hidnplayr 128
 
129
}
130
 
131
virtual at 0
132
  upd UPD
133
end virtual
134
 
135
; Ethernet frame symbols
136
	ETH_ALEN		equ 6
137
	ETH_HLEN		equ (2*ETH_ALEN+2)
138
	ETH_ZLEN		equ 60 ; 60 + 4bytes auto payload for
139
					      ; mininmum 64bytes frame length
140
; Registers
141
	REG_POWER_MGMT_CTRL	equ 0x7c
142
	REG_UP_LIST_PTR 	equ 0x38
143
	REG_UP_PKT_STATUS	equ 0x30
144
	REG_TX_FREE_THRESH	equ 0x2f
145
	REG_DN_LIST_PTR 	equ 0x24
146
	REG_DMA_CTRL		equ 0x20
147
	REG_TX_STATUS		equ 0x1b
148
	REG_RX_STATUS		equ 0x18
149
	REG_TX_DATA		equ 0x10
1519 hidnplayr 150
 
1472 hidnplayr 151
; Common window registers
152
	REG_INT_STATUS		equ 0xe
153
	REG_COMMAND		equ 0xe
1519 hidnplayr 154
 
1472 hidnplayr 155
; Register window 7
156
	REG_MASTER_STATUS	equ 0xc
157
	REG_POWER_MGMT_EVENT	equ 0xc
158
	REG_MASTER_LEN		equ 0x6
159
	REG_VLAN_ETHER_TYPE	equ 0x4
160
	REG_VLAN_MASK		equ 0x0
161
	REG_MASTER_ADDRESS	equ 0x0
1519 hidnplayr 162
 
1472 hidnplayr 163
; Register window 6
164
	REG_BYTES_XMITTED_OK	equ 0xc
165
	REG_BYTES_RCVD_OK	equ 0xa
166
	REG_UPPER_FRAMES_OK	equ 0x9
167
	REG_FRAMES_DEFERRED	equ 0x8
168
	REG_FRAMES_RCVD_OK	equ 0x7
169
	REG_FRAMES_XMITTED_OK	equ 0x6
170
	REG_RX_OVERRUNS 	equ 0x5
171
	REG_LATE_COLLISIONS	equ 0x4
172
	REG_SINGLE_COLLISIONS	equ 0x3
173
	REG_MULTIPLE_COLLISIONS equ 0x2
174
	REG_SQE_ERRORS		equ 0x1
175
	REG_CARRIER_LOST	equ 0x0
1519 hidnplayr 176
 
1472 hidnplayr 177
; Register window 5
178
	REG_INDICATION_ENABLE	equ 0xc
179
	REG_INTERRUPT_ENABLE	equ 0xa
180
	REG_TX_RECLAIM_THRESH	equ 0x9
181
	REG_RX_FILTER		equ 0x8
182
	REG_RX_EARLY_THRESH	equ 0x6
183
	REG_TX_START_THRESH	equ 0x0
1519 hidnplayr 184
 
1472 hidnplayr 185
; Register window 4
186
	REG_UPPER_BYTES_OK	equ 0xe
187
	REG_BAD_SSD		equ 0xc
188
	REG_MEDIA_STATUS	equ 0xa
189
	REG_PHYSICAL_MGMT	equ 0x8
190
	REG_NETWORK_DIAGNOSTIC	equ 0x6
191
	REG_FIFO_DIAGNOSTIC	equ 0x4
192
	REG_VCO_DIAGNOSTIC	equ 0x2 ; may not supported
1519 hidnplayr 193
 
1472 hidnplayr 194
; Bits in register window 4
195
	BIT_AUTOSELECT		equ 24
1519 hidnplayr 196
 
1472 hidnplayr 197
; Register window 3
198
	REG_TX_FREE		equ 0xc
199
	REG_RX_FREE		equ 0xa
200
	REG_MEDIA_OPTIONS	equ 0x8
201
	REG_MAC_CONTROL 	equ 0x6
202
	REG_MAX_PKT_SIZE	equ 0x4
203
	REG_INTERNAL_CONFIG	equ 0x0
1519 hidnplayr 204
 
1472 hidnplayr 205
; Register window 2
206
	REG_RESET_OPTIONS	equ 0xc
207
	REG_STATION_MASK_HI	equ 0xa
208
	REG_STATION_MASK_MID	equ 0x8
209
	REG_STATION_MASK_LO	equ 0x6
210
	REG_STATION_ADDRESS_HI	equ 0x4
211
	REG_STATION_ADDRESS_MID equ 0x2
212
	REG_STATION_ADDRESS_LO	equ 0x0
1519 hidnplayr 213
 
1472 hidnplayr 214
; Register window 1
215
	REG_TRIGGER_BITS	equ 0xc
216
	REG_SOS_BITS		equ 0xa
217
	REG_WAKE_ON_TIMER	equ 0x8
218
	REG_SMB_RXBYTES 	equ 0x7
219
	REG_SMB_DIAG		equ 0x5
220
	REG_SMB_ARB		equ 0x4
221
	REG_SMB_STATUS		equ 0x2
222
	REG_SMB_ADDRESS 	equ 0x1
223
	REG_SMB_FIFO_DATA	equ 0x0
1519 hidnplayr 224
 
1472 hidnplayr 225
; Register window 0
226
	REG_EEPROM_DATA 	equ 0xc
227
	REG_EEPROM_COMMAND	equ 0xa
228
	REG_BIOS_ROM_DATA	equ 0x8
229
	REG_BIOS_ROM_ADDR	equ 0x4
1519 hidnplayr 230
 
1472 hidnplayr 231
; Physical management bits
232
	BIT_MGMT_DIR		equ 2 ; drive with the data written in mgmtData
233
	BIT_MGMT_DATA		equ 1 ; MII management data bit
234
	BIT_MGMT_CLK		equ 0 ; MII management clock
1519 hidnplayr 235
 
1472 hidnplayr 236
; MII commands
237
	MII_CMD_MASK		equ (1111b shl 10)
238
	MII_CMD_READ		equ (0110b shl 10)
239
	MII_CMD_WRITE		equ (0101b shl 10)
1519 hidnplayr 240
 
1472 hidnplayr 241
; MII registers
242
	REG_MII_BMCR		equ 0 ; basic mode control register
243
	REG_MII_BMSR		equ 1 ; basic mode status register
244
	REG_MII_ANAR		equ 4 ; auto negotiation advertisement register
245
	REG_MII_ANLPAR		equ 5 ; auto negotiation link partner ability register
246
	REG_MII_ANER		equ 6 ; auto negotiation expansion register
1519 hidnplayr 247
 
1472 hidnplayr 248
; MII bits
249
	BIT_MII_AUTONEG_COMPLETE     equ 5 ; auto-negotiation complete
250
	BIT_MII_PREAMBLE_SUPPRESSION equ 6
1519 hidnplayr 251
 
1472 hidnplayr 252
; eeprom bits and commands
253
	EEPROM_CMD_READ 	equ 0x80
254
	EEPROM_BIT_BUSY 	equ 15
1519 hidnplayr 255
 
1472 hidnplayr 256
; eeprom registers
257
	EEPROM_REG_OEM_NODE_ADDR equ 0xa
258
	EEPROM_REG_CAPABILITIES  equ 0x10
1519 hidnplayr 259
 
1472 hidnplayr 260
; Commands for command register
261
	SELECT_REGISTER_WINDOW	equ (1 shl 11)
262
 
263
	IS_VORTEX		equ 0x1
264
	IS_BOOMERANG		equ 0x2
265
	IS_CYCLONE		equ 0x4
266
	IS_TORNADO		equ 0x8
267
	EEPROM_8BIT		equ 0x10
268
	HAS_PWR_CTRL		equ 0x20
269
	HAS_MII 		equ 0x40
270
	HAS_NWAY		equ 0x80
271
	HAS_CB_FNS		equ 0x100
272
	INVERT_MII_PWR		equ 0x200
273
	INVERT_LED_PWR		equ 0x400
274
	MAX_COLLISION_RESET	equ 0x800
275
	EEPROM_OFFSET		equ 0x1000
276
	HAS_HWCKSM		equ 0x2000
277
	EXTRA_PREAMBLE		equ 0x4000
278
 
279
; Status
280
	IntLatch		equ 0x0001
281
	HostError		equ 0x0002
282
	TxComplete		equ 0x0004
283
	TxAvailable		equ 0x0008
284
	RxComplete		equ 0x0010
285
	RxEarly 		equ 0x0020
286
	IntReq			equ 0x0040
287
	StatsFull		equ 0x0080
1519 hidnplayr 288
	DMADone 		equ 0x0100
289
	DownComplete		equ 0x0200
290
	UpComplete		equ 0x0400
1472 hidnplayr 291
	DMAInProgress		equ 0x0800 ; 1 shl 11  (DMA controller is still busy)
292
	CmdInProgress		equ 0x1000 ; 1 shl 12  (EL3_CMD is still busy)
293
 
1519 hidnplayr 294
	S_5_INTS		equ HostError + RxEarly + UpComplete + DownComplete ;+ TxComplete + RxComplete  + TxAvailable
1472 hidnplayr 295
 
296
; Commands
297
	TotalReset		equ 0 shl 11
298
	SelectWindow		equ 1 shl 11
299
	StartCoax		equ 2 shl 11
300
	RxDisable		equ 3 shl 11
301
	RxEnable		equ 4 shl 11
302
	RxReset 		equ 5 shl 11
303
	UpStall 		equ 6 shl 11
304
	UpUnstall		equ (6 shl 11)+1
305
	DownStall		equ (6 shl 11)+2
306
	DownUnstall		equ (6 shl 11)+3
307
	RxDiscard		equ 8 shl 11
308
	TxEnable		equ 9 shl 11
309
	TxDisable		equ 10 shl 11
310
	TxReset 		equ 11 shl 11
311
	FakeIntr		equ 12 shl 11
312
	AckIntr 		equ 13 shl 11
313
	SetIntrEnb		equ 14 shl 11
314
	SetStatusEnb		equ 15 shl 11
315
	SetRxFilter		equ 16 shl 11
316
	SetRxThreshold		equ 17 shl 11
317
	SetTxThreshold		equ 18 shl 11
318
	SetTxStart		equ 19 shl 11
319
	StartDMAUp		equ 20 shl 11
320
	StartDMADown		equ (20 shl 11)+1
321
	StatsEnable		equ 21 shl 11
322
	StatsDisable		equ 22 shl 11
323
	StopCoax		equ 23 shl 11
1519 hidnplayr 324
	SetFilterBit		equ 25 shl 11
1472 hidnplayr 325
 
326
; Rx mode bits
327
	RxStation		equ 1
328
	RxMulticast		equ 2
329
	RxBroadcast		equ 4
330
	RxProm			equ 8
331
 
332
; RX/TX buffers sizes
333
	MAX_ETH_PKT_SIZE	equ 1536   ; max packet size
334
	NUM_RX_DESC		equ 4	   ; a power of 2 number
335
	NUM_TX_DESC		equ 4	   ; a power of 2 number
336
	MAX_ETH_FRAME_SIZE	equ 1520	; size of ethernet frame + bytes alignment
337
 
1519 hidnplayr 338
virtual at ebx
1472 hidnplayr 339
 
1519 hidnplayr 340
	device:
1472 hidnplayr 341
 
1519 hidnplayr 342
	ETH_DEVICE
1472 hidnplayr 343
 
1519 hidnplayr 344
	.dpd_buffer	  rd (dpd.size*NUM_TX_DESC)/4
345
	.upd_buffer	  rd (upd.size*NUM_RX_DESC)/4
346
	.curr_upd	  dd ?
347
	.prev_dpd	  dd ?
1472 hidnplayr 348
 
1519 hidnplayr 349
	.io_addr	  dd ?
350
	.pci_bus	  db ?
351
	.pci_dev	  db ?
352
	.irq_line	  db ?
353
 
354
	.prev_tx_frame		  dd ?
355
	.ver_id 		  db ?
356
	.full_bus_master	  db ?
357
	.has_hwcksm		  db ?
358
	.preamble		  db ?
359
	.dn_list_ptr_cleared	  db ?
360
 
361
	.size = $ - device
362
 
363
end virtual
364
 
1472 hidnplayr 365
section '.flat' code readable align 16
366
 
367
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
368
;;                        ;;
369
;; proc START             ;;
370
;;                        ;;
371
;; (standard driver proc) ;;
372
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
373
 
374
align 4
375
proc START stdcall, state:dword
376
 
377
	cmp [state], 1
378
	jne .exit
379
 
380
  .entry:
381
 
382
	DEBUGF 1,"Loading 3com network driver\n"
383
	stdcall RegService, my_service, service_proc
384
	ret
385
 
386
  .fail:
387
  .exit:
388
	xor eax, eax
389
	ret
390
 
391
endp
392
 
393
 
394
 
395
 
396
 
397
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
398
;;                        ;;
399
;; proc SERVICE_PROC      ;;
400
;;                        ;;
401
;; (standard driver proc) ;;
402
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
403
 
404
align 4
405
proc service_proc stdcall, ioctl:dword
406
 
407
	mov	edx, [ioctl]
408
	mov	eax, [IOCTL.io_code]
409
 
410
;------------------------------------------------------
411
 
412
	cmp	eax, 0 ;SRV_GETVERSION
413
	jne	@F
414
 
415
	cmp	[IOCTL.out_size], 4
416
	jl	.fail
417
	mov	eax, [IOCTL.output]
418
	mov	[eax], dword API_VERSION
419
 
420
	xor	eax, eax
421
	ret
422
 
423
;------------------------------------------------------
424
  @@:
425
	cmp	eax, 1 ;SRV_HOOK
426
	jne	.fail
427
 
428
	cmp	[IOCTL.inp_size], 3		  ; Data input must be at least 3 bytes
429
	jl	.fail
430
 
431
	mov	eax, [IOCTL.input]
432
	cmp	byte [eax], 1				; 1 means device number and bus number (pci) are given
433
	jne	.fail					; other types of this hardware dont exist
434
 
435
; check if the device is already listed
436
 
437
	mov	ecx, [VORTEX_DEVICES]
438
	test	ecx, ecx
439
	jz	.maybeboomerang
440
 
441
	mov	esi, VORTEX_LIST
442
	mov	eax, [IOCTL.input]			; get the pci bus and device numbers
443
	mov	ax , [eax+1]				;
444
  .nextdevice:
445
	mov	ebx, [esi]
446
	cmp	ax , word [device.pci_bus]		; compare with pci and device num in device list (notice the usage of word instead of byte)
447
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
448
	add	esi, 4
449
	loop	.nextdevice
450
 
451
 
452
  .maybeboomerang:
453
	mov	ecx, [BOOMERANG_DEVICES]
454
	test	ecx, ecx
455
	jz	.firstdevice
456
 
457
	mov	esi, BOOMERANG_LIST
458
	mov	eax, [IOCTL.input]			; get the pci bus and device numbers
459
	mov	ax , [eax+1]				;
460
  .nextdevice2:
461
	mov	ebx, [esi]
462
	cmp	ax , word [device.pci_bus]		; compare with pci and device num in device list (notice the usage of word instead of byte)
463
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
464
	add	esi, 4
465
	loop	.nextdevice2
466
 
467
 
468
; This device doesnt have its own eth_device structure yet, lets create one
469
  .firstdevice:
470
	mov	ecx, [BOOMERANG_DEVICES]
471
	add	ecx, [VORTEX_DEVICES]
472
	cmp	ecx, MAX_DEVICES			; First check if the driver can handle one more card
473
	jge	.fail
474
 
1521 hidnplayr 475
	allocate_and_clear ebx, device.size, .fail	; Allocate the buffer for device structure
1472 hidnplayr 476
 
477
; Fill in the direct call addresses into the struct
478
 
479
	mov	[device.reset], reset
480
	mov	[device.transmit], null_op
481
	mov	[device.get_MAC], read_mac
482
	mov	[device.set_MAC], write_mac
483
	mov	[device.unload], null_op
484
	mov	[device.name], my_service
485
 
486
; save the pci bus and device numbers
487
 
488
	mov	eax, [IOCTL.input]
489
	mov	cl , [eax+1]
490
	mov	[device.pci_bus], cl
491
	mov	cl , [eax+2]
492
	mov	[device.pci_dev], cl
493
 
494
; Now, it's time to find the base io addres of the PCI device
495
	find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
496
 
497
; We've found the io address, find IRQ now
1492 hidnplayr 498
	find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
1472 hidnplayr 499
 
500
	DEBUGF	1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
501
	[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
502
 
503
; Ok, the eth_device structure is ready, let's probe the device
504
	call	probe							; this function will output in eax
505
	test	eax, eax
506
	jnz	.err							; If an error occured, exit
507
 
508
 
509
	movzx	ecx, [device.ver_id]
510
	test	word [hw_versions+2+ecx*4], IS_VORTEX
511
	jz	.not_vortex
512
 
1521 hidnplayr 513
	mov	eax, [VORTEX_DEVICES]					; Add the device structure to our device list
1472 hidnplayr 514
	mov	[VORTEX_LIST+4*eax], ebx				; (IRQ handler uses this list to find device)
1521 hidnplayr 515
	inc	[VORTEX_DEVICES]					;
1472 hidnplayr 516
 
517
  .register:
1514 hidnplayr 518
	mov	[device.type], NET_TYPE_ETH
519
	call	NetRegDev
1472 hidnplayr 520
 
521
	cmp	eax, -1
522
	je	.destroy
523
 
1521 hidnplayr 524
	call	start_device
1472 hidnplayr 525
	ret
526
 
527
  .not_vortex:
528
	mov	eax, [BOOMERANG_DEVICES]					  ; Add the device structure to our device list
529
	mov	[BOOMERANG_LIST+4*eax], ebx				   ; (IRQ handler uses this list to find device)
530
	inc	[BOOMERANG_DEVICES]
531
 
1521 hidnplayr 532
	jmp	.register
1472 hidnplayr 533
 
534
; If the device was already loaded, find the device number and return it in eax
535
 
536
  .find_devicenum:
537
	DEBUGF	1,"Trying to find device number of already registered device\n"
1514 hidnplayr 538
	call	NetPtrToNum						; This kernel procedure converts a pointer to device struct in ebx
1472 hidnplayr 539
									; into a device number in edi
540
	mov	eax, edi						; Application wants it in eax instead
541
	DEBUGF	1,"Kernel says: %u\n", eax
542
	ret
543
 
544
; If an error occured, remove all allocated data and exit (returning -1 in eax)
545
 
546
  .destroy:
547
	; todo: reset device into virgin state
548
 
549
  .err:
550
	stdcall KernelFree, ebx
551
 
552
 
553
  .fail:
554
	or	eax, -1
555
	ret
556
 
557
;------------------------------------------------------
558
endp
559
 
560
 
561
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
562
;;                                                                        ;;
563
;;        Actual Hardware dependent code starts here                      ;;
564
;;                                                                        ;;
565
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
566
 
567
 
568
 
569
 
570
 
571
;***************************************************************************
572
;   Function
573
;      probe
574
;   Description
575
;      Searches for an ethernet card, enables it and clears the rx buffer
576
;   Destroyed registers
577
;      eax, ebx, ecx, edx, edi, esi
578
;
579
;***************************************************************************
580
 
581
align 4
1519 hidnplayr 582
probe:
1472 hidnplayr 583
 
584
	DEBUGF	1,"Probing 3com card\n"
585
 
586
	make_bus_master [device.pci_bus], [device.pci_dev]
587
 
588
; wake up the card
589
	call	wake_up
590
 
591
	movzx	ecx, [device.pci_bus]
592
	movzx	edx, [device.pci_dev]
593
	stdcall PciRead32, ecx ,edx ,0				      ; get device/vendor id
594
 
595
	DEBUGF	1,"Vendor id: 0x%x\n", ax
596
 
597
	cmp	ax , 0x10B7
598
	jne	.notfound
599
	shr	eax, 16
600
 
601
	DEBUGF	1,"Vendor ok!, device id: 0x%x\n", ax
602
 
603
; get chip version
604
	mov	ecx, HW_VERSIONS_SIZE/4-1
1521 hidnplayr 605
  .loop:
1472 hidnplayr 606
	cmp	ax , [hw_versions+ecx*4]
607
	jz	.found
608
	loop	.loop
609
	DEBUGF	1,"ecx: %u\n", ecx
1521 hidnplayr 610
  .notfound:
1472 hidnplayr 611
	DEBUGF	1,"Device id not found in list!\n"
612
	or	eax, -1
613
	ret
1521 hidnplayr 614
  .found:
1472 hidnplayr 615
	mov	esi, [hw_str+ecx*4]
616
	DEBUGF	1,"Hardware type: %s\n", esi
617
	mov	[device.name], esi
618
 
619
	mov	[device.ver_id], cl
620
	test	word [hw_versions+2+ecx*4], HAS_HWCKSM
621
	setnz	[device.has_hwcksm]
622
; set pci latency for vortex cards
623
	test	word [hw_versions+2+ecx*4], IS_VORTEX
624
	jz	.not_vortex
625
 
626
	mov	eax, 11111000b ; 248 = max latency
627
	movzx	ecx, [device.pci_bus]
628
	movzx	edx, [device.pci_dev]
629
	stdcall PciWrite32, ecx, edx, PCI_REG_LATENCY, eax
630
 
1521 hidnplayr 631
  .not_vortex:
1472 hidnplayr 632
; set RX/TX functions
633
	mov	ax, EEPROM_REG_CAPABILITIES
634
	call	read_eeprom
635
	test	al, 100000b ; full bus master?
636
	setnz	[device.full_bus_master]
637
	jnz	.boomerang_func
638
	mov	[device.transmit], vortex_transmit
639
	DEBUGF	1,"Device is a vortex type\n"
1519 hidnplayr 640
	DEBUGF	1,"I'm sorry but vortex code hasnt been tested yet\n"
641
	DEBUGF	1,"Please contact me on hidnplayr@kolibrios.org\n"
642
	DEBUGF	1,"If you can help me finish it!\n"
643
	or	eax, -1
644
	ret
1472 hidnplayr 645
	jmp	@f
1521 hidnplayr 646
  .boomerang_func: ; full bus master, so use boomerang functions
1472 hidnplayr 647
	mov	[device.transmit], boomerang_transmit
648
	DEBUGF	1,"Device is a boomerang type\n"
1521 hidnplayr 649
       @@:
1472 hidnplayr 650
	call	read_mac_eeprom
651
 
652
	test	byte [device.full_bus_master], 0xff
653
	jz	.set_preamble
654
; switch to register window 2
655
	set_io	0
656
	set_io	REG_COMMAND
657
	mov	ax, SELECT_REGISTER_WINDOW+2
658
	out	dx, ax
659
; activate xcvr by setting some magic bits
660
	set_io	REG_RESET_OPTIONS
661
	in	ax, dx
662
	and	ax, not 0x4010
663
	movzx	ecx, [device.ver_id]
664
	test	word [ecx*4+hw_versions+2], INVERT_LED_PWR
665
	jz	@f
666
	or	al, 0x10
1521 hidnplayr 667
       @@:
1472 hidnplayr 668
	test	word [ecx*4+hw_versions+2], INVERT_MII_PWR
669
	jz	@f
670
	or	ah, 0x40
1521 hidnplayr 671
       @@:
1472 hidnplayr 672
	out	dx, ax
1521 hidnplayr 673
  .set_preamble:
1472 hidnplayr 674
; use preamble as default
675
	mov	byte [device.preamble], 1 ; enable preamble
676
 
677
	call	global_reset
678
 
679
;--------------------------
680
; RESET
681
 
682
align 4
683
reset:
684
 
685
	movzx	eax, [device.irq_line]
686
	DEBUGF	1,"Attaching int handler to irq %x\n",eax:1
687
 
688
	movzx	ecx, [device.ver_id]
689
	test	word [hw_versions+2+ecx*4], IS_VORTEX
690
	jz	.not_vortex
691
 
692
	mov	esi, int_vortex
693
	jmp	.reg_int
694
 
695
.not_vortex:
696
	mov	esi, int_boomerang
697
 
698
.reg_int:
699
	stdcall AttachIntHandler, eax, esi, dword 0
700
	test	eax, eax
701
	jnz	@f
702
	DEBUGF	1,"\nCould not attach int handler!\n"
703
;        or      eax, -1
704
;        ret
705
  @@:
706
 
707
	set_io	0
708
	set_io	REG_COMMAND
709
	mov	ax, SELECT_REGISTER_WINDOW + 0
710
	out	dx, ax
711
 
712
	mov	ax, StopCoax
713
	out	dx, ax			      ; stop transceiver
714
 
715
	mov	ax, SELECT_REGISTER_WINDOW + 4
716
	out	dx, ax			      ; disable UTP
717
 
718
	set_io	REG_MEDIA_STATUS
719
	mov	ax, 0x0
720
 
721
	set_io	REG_COMMAND
722
	mov	ax, SELECT_REGISTER_WINDOW + 0
723
	out	dx, ax
724
 
725
	set_io	REG_FIFO_DIAGNOSTIC
726
	mov	ax, 0
727
	out	dx, ax			      ; disable card
728
 
729
	mov	ax, 1
730
	out	dx, ax			      ; enable card
731
 
732
	call	write_mac
733
 
734
 
1521 hidnplayr 735
;<<<<<<<<<<<<<<
736
 
1472 hidnplayr 737
	set_io	REG_COMMAND
738
	mov	ax, SELECT_REGISTER_WINDOW + 1
739
	out	dx, ax
740
 
741
	mov	ecx, 32
742
	set_io	0x0b
743
  .loop:
744
	in	al, dx
745
	loop	.loop
746
 
747
; Get rid of stary ints
748
	set_io	REG_COMMAND
749
	mov	ax, AckIntr + 0xff
750
	out	dx, ax
751
 
752
	mov	ax, SetStatusEnb + S_5_INTS
753
	out	dx, ax
754
 
755
	mov	ax, SetIntrEnb + S_5_INTS
756
	out	dx, ax
757
 
758
	call	set_rx_mode
759
	call	set_active_port
760
 
1521 hidnplayr 761
;>>>>>>>>>>
762
 
763
	call	create_rx_ring
764
	call	rx_reset
765
	call	tx_reset
766
 
767
;>>>>>>>>>>>>>>>>>>
768
 
1472 hidnplayr 769
	set_io	0
770
	set_io	REG_COMMAND
771
	mov	ax, RxEnable
772
	out	dx, ax
773
 
774
	mov	ax, TxEnable
775
	out	dx, ax
776
 
777
	set_io	REG_COMMAND
778
	mov	ax, SetRxThreshold + 208
779
	out	dx, ax
780
 
781
	mov	ax, SetTxThreshold + 60 ;16 ; recommended by the manual :)
782
	out	dx, ax
783
 
784
	mov	ax, SELECT_REGISTER_WINDOW + 1
785
	out	dx, ax
786
 
787
	xor	eax, eax
1481 hidnplayr 788
; clear packet/byte counters
1472 hidnplayr 789
 
1481 hidnplayr 790
	lea	edi, [device.bytes_tx]
791
	mov	ecx, 6
792
	rep	stosd
793
 
1519 hidnplayr 794
; Set the mtu, kernel will be able to send now
795
	mov	[device.mtu], 1514
796
 
1472 hidnplayr 797
	ret
798
 
799
 
800
 
801
 
802
 
803
align 4
1521 hidnplayr 804
start_device:
805
	DEBUGF	1,"Starting the device\n"
1472 hidnplayr 806
 
807
	set_io	0
808
	set_io	REG_COMMAND
809
	mov	ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :)
810
	out	dx, ax
811
 
812
	call	check_tx_status
813
 
814
	set_io	0
815
	set_io	REG_COMMAND
816
; switch to register window 4
817
	mov	ax, SELECT_REGISTER_WINDOW+4
818
	out	dx, ax
819
 
820
; wait for linkDetect
821
	set_io	REG_MEDIA_STATUS
822
	mov	ecx, 20 ; wait for max 2s
1521 hidnplayr 823
  .link_detect_loop:
824
	mov	esi, 100
825
	call	Sleep ; 100 ms
1472 hidnplayr 826
	in	ax, dx
827
	test	ah, 1000b ; linkDetect
828
	jnz	@f
829
	loop	.link_detect_loop
1521 hidnplayr 830
	DEBUGF	1,"Link detect timed-out!\n"
831
       @@:
1472 hidnplayr 832
 
833
; print link type
834
	xor	eax, eax
835
	bsr	ax, word [device.mode]
836
	jz	@f
837
	sub	ax, 4
1521 hidnplayr 838
       @@:
839
 
1472 hidnplayr 840
	mov	esi, [link_str+eax*4]
1521 hidnplayr 841
	DEBUGF	1,"Established Link type: %s\n", esi
1472 hidnplayr 842
 
1521 hidnplayr 843
; enable interrupts
1472 hidnplayr 844
 
845
	set_io	REG_COMMAND
846
	mov	ax, SELECT_REGISTER_WINDOW + 1
847
	out	dx, ax
848
 
849
	mov	ax, AckIntr + 0xff
850
	out	dx, ax
851
 
852
	mov	ax, SetStatusEnb + S_5_INTS
853
	out	dx, ax
854
 
855
	mov	ax, SetIntrEnb + S_5_INTS
856
	out	dx, ax
857
 
858
	ret
859
 
860
 
861
 
862
 
863
 
864
 
865
 
866
align 4
867
set_rx_mode:
868
 
1521 hidnplayr 869
	DEBUGF	1,"Setting RX mode\n"
870
 
1472 hidnplayr 871
	set_io	0
872
	set_io	REG_COMMAND
873
 
1521 hidnplayr 874
if	defined PROMISCIOUS
1472 hidnplayr 875
	mov	ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm
1521 hidnplayr 876
else if  defined ALLMULTI
1472 hidnplayr 877
	mov	ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast
1521 hidnplayr 878
else
1472 hidnplayr 879
	mov	ax, SetRxFilter + RxStation + RxBroadcast
1521 hidnplayr 880
end if
1472 hidnplayr 881
	out	dx, ax
882
 
883
	ret
884
 
885
 
886
 
887
 
888
 
889
;***************************************************************************
890
;   Function
891
;      global_reset
892
;   Description
893
;      resets the device
894
;   Parameters:
895
;      ebp - io_addr
896
;   Return value:
897
;   Destroyed registers
898
;      ax, ecx, edx, esi
899
;
900
;***************************************************************************1
901
 
902
align 4
903
global_reset:
904
 
1521 hidnplayr 905
	DEBUGF 1,"Global reset..\n"
1472 hidnplayr 906
 
907
; GlobalReset
908
	set_io	0
909
	set_io	REG_COMMAND
910
	xor	eax, eax
911
;       or      al, 0x14
912
	out	dx, ax
913
; wait for GlobalReset to complete
914
	mov	ecx, 64000
1521 hidnplayr 915
  .loop:
1472 hidnplayr 916
	in	ax , dx
917
	test	ah , 10000b ; check CmdInProgress
918
	loopz	.loop
1521 hidnplayr 919
 
920
	DEBUGF 1,"Waiting for nic to boot..\n"
1472 hidnplayr 921
; wait for 2 seconds for NIC to boot
1521 hidnplayr 922
	mov	esi, 2000
923
	call	Sleep ; 2 seconds
1472 hidnplayr 924
 
925
	DEBUGF 1,"Ok!\n"
926
 
927
	ret
928
 
929
 
930
 
931
;***************************************************************************
932
;   Function
933
;      tx_reset
934
;   Description
935
;      resets and enables transmitter engine
936
;
937
;***************************************************************************
938
 
939
align 4
940
tx_reset:
941
	DEBUGF 1,"tx reset\n"
942
 
943
; TxReset
944
	set_io	0
945
	set_io	REG_COMMAND
946
	mov	ax, TxReset
947
	out	dx, ax
948
; Wait for TxReset to complete
949
	mov	ecx, 200000
950
.tx_reset_loop:
951
	in	ax, dx
952
	test	ah, 10000b ; check CmdInProgress
953
	jz	.tx_set_prev
954
	dec	ecx
955
	jnz	.tx_reset_loop
956
.tx_set_prev:
957
; init last_dpd
1519 hidnplayr 958
	lea	eax, [device.dpd_buffer + (NUM_TX_DESC-1)*dpd.size]
1472 hidnplayr 959
	mov	[device.prev_dpd], eax
960
 
961
.tx_enable:
962
	ret
963
 
964
 
965
 
966
;***************************************************************************
967
;   Function
968
;      rx_reset
969
;   Description
970
;      resets and enables receiver engine
971
;
972
;***************************************************************************
973
 
974
align 4
975
rx_reset:
976
 
977
	DEBUGF 1,"rx reset\n"
978
 
979
	set_io	0
980
	set_io	REG_COMMAND
981
	mov	ax, RxReset or 0x4
982
	out	dx, ax
1519 hidnplayr 983
 
1472 hidnplayr 984
; wait for RxReset to complete
985
	mov	ecx, 200000
1519 hidnplayr 986
  .loop:
1472 hidnplayr 987
	in	ax, dx
988
	test	ah, 10000b ; check CmdInProgress
1521 hidnplayr 989
	jz	.done
1472 hidnplayr 990
	dec	ecx
1519 hidnplayr 991
	jnz	.loop
1521 hidnplayr 992
  .done:
1519 hidnplayr 993
 
1521 hidnplayr 994
	lea	eax, [device.upd_buffer]
995
	mov	[device.curr_upd], eax
996
	GetRealAddr
997
	set_io	0
998
	set_io	REG_UP_LIST_PTR
999
	out	dx, eax
1000
 
1001
  .rx_enable:
1002
	ret
1003
 
1004
 
1005
align 4
1006
create_rx_ring:
1472 hidnplayr 1007
; create upd ring
1519 hidnplayr 1008
	lea	eax, [device.upd_buffer]
1009
	GetRealAddr
1010
	mov	edi, eax						; real addr of first descr
1472 hidnplayr 1011
 
1519 hidnplayr 1012
	lea	esi, [device.upd_buffer]				; ptr to first descr
1013
	lea	edx, [device.upd_buffer + (NUM_RX_DESC-1)*upd.size]	; ptr to last descr
1472 hidnplayr 1014
 
1519 hidnplayr 1015
	mov	ecx, NUM_RX_DESC
1472 hidnplayr 1016
 
1519 hidnplayr 1017
  .upd_loop:
1018
	mov	[edx + upd.next_ptr], edi
1472 hidnplayr 1019
 
1519 hidnplayr 1020
	push	ecx edx
1021
	stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
1022
	pop	edx ecx
1023
	mov	[esi + upd.realaddr], eax
1024
	call	GetPgAddr
1025
	mov	[esi + upd.frag_addr], eax
1026
	and	[esi + upd.pkt_status], 0
1027
	mov	[esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
1472 hidnplayr 1028
 
1519 hidnplayr 1029
	DEBUGF	1,"UPD: lin=%x phys=%x len=%x next ptr=%x\n", [esi+upd.realaddr]:8, [esi+upd.frag_addr]:8, [esi+upd.frag_len]:8, edi
1030
	DEBUGF	1,"UPD: cur=%x prev=%x\n", esi, edx
1472 hidnplayr 1031
 
1519 hidnplayr 1032
	mov	edx, esi
1472 hidnplayr 1033
	add	esi, upd.size
1519 hidnplayr 1034
	add	edi, upd.size
1472 hidnplayr 1035
	dec	ecx
1036
	jnz	.upd_loop
1037
 
1038
	ret
1039
 
1040
 
1041
 
1042
;---------------------------------------------------------------------------
1043
;   Function
1044
;      try_link_detect
1045
;   Description
1046
;      try_link_detect checks if link exists
1047
;   Parameters
1048
;      ebx = device structure
1049
;   Return value
1050
;      al - 0 ; no link detected
1051
;      al - 1 ; link detected
1052
;   Destroyed registers
1053
;      eax, ebx, ecx, edx, edi, esi
1054
;
1055
;---------------------------------------------------------------------------
1056
 
1057
align 4
1058
try_link_detect:
1059
 
1521 hidnplayr 1060
	DEBUGF	1,"trying to detect link\n"
1472 hidnplayr 1061
 
1062
; create self-directed packet
1521 hidnplayr 1063
	stdcall KernelAlloc, 20 ; create a buffer for the self-directed packet
1064
	test	eax, eax
1065
	jz	.fail
1066
 
1067
	pushd	20		; Packet parameters for device.transmit
1068
	push	eax		;
1069
 
1070
	mov	edi, eax
1071
 
1472 hidnplayr 1072
	lea	esi, [device.mac]
1073
	movsw
1074
	movsd
1075
	sub	esi, 6
1076
	movsw
1077
	movsd
1078
	mov	ax , 0x0608
1079
	stosw
1080
 
1081
; download self-directed packet
1082
	call	[device.transmit]
1083
 
1084
; switch to register window 4
1085
	set_io	0
1086
	set_io	REG_COMMAND
1087
	mov	ax, SELECT_REGISTER_WINDOW+4
1088
	out	dx, ax
1089
 
1090
; See if we have received the packet by now..
1091
	cmp	[device.packets_rx], 0
1092
	jnz	.link_detected
1093
 
1094
; switch to register window 4
1095
	set_io	REG_COMMAND
1096
	mov	ax, SELECT_REGISTER_WINDOW+4
1097
	out	dx, ax
1098
 
1099
; read linkbeatdetect
1100
	set_io	REG_MEDIA_STATUS
1101
	in	ax, dx
1102
	test	ah, 1000b ; test linkBeatDetect
1103
	jnz	.link_detected
1104
	xor	al, al
1105
	jmp	.finish
1106
 
1521 hidnplayr 1107
  .link_detected:
1108
	DEBUGF	1,"link detected!\n"
1472 hidnplayr 1109
	setb	al
1110
 
1521 hidnplayr 1111
  .finish:
1472 hidnplayr 1112
	test	al, al
1113
	jz	@f
1114
	or	byte [device.mode+1], 100b
1521 hidnplayr 1115
       @@:
1472 hidnplayr 1116
	ret
1117
 
1521 hidnplayr 1118
  .fail:
1119
	ret
1472 hidnplayr 1120
 
1121
 
1521 hidnplayr 1122
 
1472 hidnplayr 1123
;***************************************************************************
1124
;   Function
1125
;      try_phy
1126
;   Description
1127
;      try_phy checks the auto-negotiation function
1128
;      in the PHY at PHY index. It can also be extended to
1129
;      include link detection for non-IEEE 802.3u
1521 hidnplayr 1130
;      auto-negotiation devices, for instance the BCM5000.              ; TODO: BCM5000
1472 hidnplayr 1131
;   Parameters
1132
;       ah - PHY index
1133
;       ebx - device stucture
1134
;   Return value
1135
;      al - 0 link is auto-negotiated
1136
;      al - 1 no link is auto-negotiated
1137
;   Destroyed registers
1138
;       eax, ebx, ecx, edx, esi
1139
;
1140
;***************************************************************************
1141
 
1142
align 4
1143
try_phy:
1144
 
1521 hidnplayr 1145
	DEBUGF 1,"PHY=%u\n", ah
1146
	DEBUGF 1,"Detecting if device is auto-negotiation capable\n"
1472 hidnplayr 1147
 
1148
	mov	al, REG_MII_BMCR
1149
	push	eax
1150
	call	mdio_read	; returns with window #4
1151
	or	ah , 0x80	; software reset
1152
	mov	esi, eax
1153
	mov	eax, dword [esp]
1154
	call	mdio_write	; returns with window #4
1155
 
1156
; wait for reset to complete
1521 hidnplayr 1157
	mov	esi, 2000
1472 hidnplayr 1158
	stdcall Sleep	   ; 2s
1159
	mov	eax, [esp]
1160
	call	mdio_read	; returns with window #4
1161
	test	ah , 0x80
1521 hidnplayr 1162
	jnz	.fail1
1472 hidnplayr 1163
	mov	eax, [esp]
1164
 
1165
; wait for a while after reset
1521 hidnplayr 1166
	mov	esi, 20
1472 hidnplayr 1167
	stdcall Sleep	   ; 20ms
1168
	mov	eax, [esp]
1169
	mov	al , REG_MII_BMSR
1521 hidnplayr 1170
	call	mdio_read	 ; returns with window #4
1472 hidnplayr 1171
	test	al , 1		 ; extended capability supported?
1521 hidnplayr 1172
	jz	.fail2
1472 hidnplayr 1173
 
1174
; auto-neg capable?
1175
	test	al , 1000b
1521 hidnplayr 1176
	jz	.fail2		 ; not auto-negotiation capable
1472 hidnplayr 1177
 
1521 hidnplayr 1178
	DEBUGF	1,"Device is auto-negotiation capable\n"
1179
 
1472 hidnplayr 1180
; auto-neg complete?
1181
	test	al , 100000b
1182
	jnz	.auto_neg_ok
1183
 
1521 hidnplayr 1184
	DEBUGF	1,"Restarting auto-negotiation\n"
1185
 
1472 hidnplayr 1186
; restart auto-negotiation
1187
	mov	eax, [esp]
1188
	mov	al , REG_MII_ANAR
1189
	push	eax
1190
	call	mdio_read	; returns with window #4
1191
	or	ax , 1111b shl 5; advertise only 10base-T and 100base-TX
1192
	mov	esi, eax
1193
	pop	eax
1194
	call	mdio_write	; returns with window #4
1195
	mov	eax, [esp]
1196
	call	mdio_read	; returns with window #4
1197
	mov	esi, eax
1198
	or	bh , 10010b	; restart auto-negotiation
1199
	mov	eax, [esp]
1200
	call	mdio_write	; returns with window #4
1521 hidnplayr 1201
	mov	esi, 4000
1472 hidnplayr 1202
	stdcall Sleep  ; 4 seconds
1203
	mov	eax, [esp]
1204
	mov	al , REG_MII_BMSR
1205
	call	mdio_read ; returns with window #4
1206
	test	al , 100000b ; auto-neg complete?
1207
	jnz	.auto_neg_ok
1521 hidnplayr 1208
	jmp	.fail3
1209
  .auto_neg_ok:
1472 hidnplayr 1210
 
1521 hidnplayr 1211
	DEBUGF	1,"Auto-negotiation complete\n"
1212
 
1472 hidnplayr 1213
; compare advertisement and link partner ability registers
1214
	mov	eax, [esp]
1215
	mov	al , REG_MII_ANAR
1216
	call	mdio_read	; returns with window #4
1217
	xchg	eax, [esp]
1218
	mov	al , REG_MII_ANLPAR
1219
	call	mdio_read	; returns with window #4
1220
	pop	esi
1221
	and	eax, esi
1222
	and	eax, 1111100000b
1223
	push	eax
1224
 
1225
	mov	word[device.mode+2], ax
1226
 
1227
; switch to register window 3
1228
	set_io	0
1229
	set_io	REG_COMMAND
1230
	mov	ax , SELECT_REGISTER_WINDOW+3
1231
	out	dx , ax
1232
 
1233
; set full-duplex mode
1234
	set_io	REG_MAC_CONTROL
1235
	in	ax , dx
1236
	and	ax , not 0x120	; clear full duplex and flow control
1237
	pop	esi
1238
	test	esi, 1010b shl 5; check for full-duplex
1239
	jz	.half_duplex
1240
	or	ax , 0x120	; set full duplex and flow control
1521 hidnplayr 1241
  .half_duplex:
1242
	DEBUGF 1,"Using half-duplex\n"
1472 hidnplayr 1243
	out	dx , ax
1244
	mov	al , 1
1245
	ret
1246
 
1521 hidnplayr 1247
 
1248
  .fail1:
1249
	DEBUGF	1,"reset failed!\n"
1472 hidnplayr 1250
	pop	eax
1251
	xor	al, al
1252
	ret
1253
 
1521 hidnplayr 1254
  .fail2:
1255
	DEBUGF	1,"This device is not auto-negotiation capable!\n"
1256
	pop	eax
1257
	xor	al, al
1258
	ret
1472 hidnplayr 1259
 
1521 hidnplayr 1260
  .fail3:
1261
	DEBUGF	1,"auto-negotiation reset failed!\n"
1262
	pop	eax
1263
	xor	al, al
1264
	ret
1472 hidnplayr 1265
 
1521 hidnplayr 1266
 
1267
 
1472 hidnplayr 1268
;***************************************************************************
1269
;   Function
1270
;      try_mii
1271
;   Description
1272
;      try_MII checks the on-chip auto-negotiation logic
1273
;      or an off-chip MII PHY, depending upon what is set in
1274
;      xcvrSelect by the caller.
1275
;      It exits when it finds the first device with a good link.
1276
;   Parameters
1277
;      ebp - io_addr
1278
;   Return value
1279
;      al - 0
1280
;      al - 1
1281
;   Destroyed registers
1282
;      eax, ebx, ecx, edx, esi
1283
;
1284
;***************************************************************************
1285
 
1286
align 4
1287
try_mii:
1288
 
1521 hidnplayr 1289
	DEBUGF	1,"trying to find MII PHY\n"
1472 hidnplayr 1290
 
1291
; switch to register window 3
1292
	set_io	0
1293
	set_io	REG_COMMAND
1294
	mov	ax, SELECT_REGISTER_WINDOW+3
1295
	out	dx, ax
1296
	set_io	REG_INTERNAL_CONFIG
1297
	in	eax, dx
1298
	and	eax, (1111b shl 20)
1299
	cmp	eax, (1000b shl 20) ; is auto-negotiation set?
1300
	jne	.mii_device
1521 hidnplayr 1301
 
1302
	DEBUGF	1,"auto-negotiation is set\n"
1472 hidnplayr 1303
; switch to register window 4
1304
	set_io	REG_COMMAND
1305
	mov	ax , SELECT_REGISTER_WINDOW+4
1306
	out	dx , ax
1521 hidnplayr 1307
 
1472 hidnplayr 1308
; PHY==24 is the on-chip auto-negotiation logic
1309
; it supports only 10base-T and 100base-TX
1310
	mov	ah , 24
1311
	call	try_phy
1312
	test	al , al
1313
	jz	.fail_finish
1521 hidnplayr 1314
 
1472 hidnplayr 1315
	mov	cl , 24
1316
	jmp	.check_preamble
1521 hidnplayr 1317
 
1318
  .mii_device:
1472 hidnplayr 1319
	cmp	eax, (0110b shl 20)
1320
	jne	.fail_finish
1521 hidnplayr 1321
 
1472 hidnplayr 1322
	set_io	0
1323
	set_io	REG_COMMAND
1324
	mov	ax , SELECT_REGISTER_WINDOW+4
1325
	out	dx , ax
1521 hidnplayr 1326
 
1472 hidnplayr 1327
	set_io	REG_PHYSICAL_MGMT
1328
	in	ax , dx
1329
	and	al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA)
1330
	cmp	al , (1 shl BIT_MGMT_DATA)
1331
	je	.search_for_phy
1521 hidnplayr 1332
 
1472 hidnplayr 1333
	xor	al , al
1334
	ret
1521 hidnplayr 1335
 
1336
  .search_for_phy:
1472 hidnplayr 1337
; search for PHY
1338
	mov	cx , 31
1521 hidnplayr 1339
  .search_phy_loop:
1340
	DEBUGF	1,"Searching the PHY\n"
1472 hidnplayr 1341
	cmp	cx , 24
1342
	je	.next_phy
1343
	mov	ah , cl ; ah = phy
1344
	mov	al , REG_MII_BMCR ; al = Basic Mode Status Register
1345
	push	cx
1346
	call	mdio_read
1347
	pop	cx
1348
	test	ax , ax
1349
	jz	.next_phy
1350
	cmp	ax , 0xffff
1351
	je	.next_phy
1352
	mov	ah , cl ; ah = phy
1353
	push	cx
1354
	call	try_phy
1355
	pop	cx
1356
	test	al , al
1357
	jnz	.check_preamble
1521 hidnplayr 1358
  .next_phy:
1472 hidnplayr 1359
	loopw	.search_phy_loop
1521 hidnplayr 1360
 
1361
  .fail_finish:
1472 hidnplayr 1362
	xor	al, al
1363
	ret
1521 hidnplayr 1364
 
1472 hidnplayr 1365
; epilog
1521 hidnplayr 1366
  .check_preamble:
1367
	DEBUGF	1,"Using PHY: %u\nChecking PreAmble\n", cl
1472 hidnplayr 1368
	push	eax ; eax contains the return value of try_phy
1369
; check hard coded preamble forcing
1370
	movzx	eax, [device.ver_id]
1371
	test	word [eax*4+hw_versions+2], EXTRA_PREAMBLE
1372
	setnz	[device.preamble] ; force preamble
1373
	jnz	.finish
1521 hidnplayr 1374
 
1472 hidnplayr 1375
; check mii for preamble suppression
1376
	mov	ah, cl
1377
	mov	al, REG_MII_BMSR
1378
	call	mdio_read
1379
	test	al, 1000000b ; preamble suppression?
1380
	setz	[device.preamble] ; no
1521 hidnplayr 1381
 
1382
  .finish:
1472 hidnplayr 1383
	pop	eax
1384
	ret
1385
 
1386
 
1387
 
1388
;***************************************************************************
1389
;   Function
1390
;      test_packet
1391
;   Description
1392
;      try_loopback try a loopback packet for 10BASE2 or AUI port
1393
;   Parameters
1394
;      ebx = device structure
1395
;
1396
;***************************************************************************
1397
 
1398
align 4
1399
test_packet:
1400
 
1401
	DEBUGF 1,"sending test packet\n"
1402
 
1403
; switch to register window 3
1404
	set_io	0
1405
	set_io	REG_COMMAND
1406
	mov	ax, SELECT_REGISTER_WINDOW+3
1407
	out	dx, ax
1408
 
1409
; set fullDuplexEnable in MacControl register
1410
	set_io	REG_MAC_CONTROL
1411
	in	ax, dx
1412
	or	ax, 0x120
1413
	out	dx, ax
1414
 
1415
; switch to register window 5
1416
	set_io	REG_COMMAND
1417
	mov	ax, SELECT_REGISTER_WINDOW+5
1418
	out	dx, ax
1419
 
1420
; set RxFilter to enable individual address matches
1421
	mov	ax, (10000b shl 11)
1422
	set_io	REG_RX_FILTER
1423
	in	al, dx
1424
	or	al, 1
1425
	set_io	REG_COMMAND
1426
	out	dx, ax
1427
 
1428
; issue RxEnable and TxEnable
1429
	call	rx_reset
1430
	call	tx_reset
1431
 
1521 hidnplayr 1432
; create self-directed packet
1433
	stdcall KernelAlloc, 20 ; create a buffer for the self-directed packet
1434
	test	eax, eax
1435
	jz	.fail
1436
 
1437
	pushd	20		; Packet parameters for device.transmit
1438
	push	eax		;
1439
 
1440
	mov	edi, eax
1472 hidnplayr 1441
	lea	esi, [device.mac]
1442
	movsw
1443
	movsd
1444
	sub	esi, 6
1445
	movsw
1446
	movsd
1447
	mov	ax , 0x0608
1448
	stosw
1449
 
1521 hidnplayr 1450
; download self-directed packet
1472 hidnplayr 1451
	call	[device.transmit]
1452
 
1453
; wait for 2s
1521 hidnplayr 1454
	mov	esi, 2000
1455
	call	Sleep
1472 hidnplayr 1456
 
1457
; check if self-directed packet is received
1458
	mov	eax, [device.packets_rx]
1459
	test	eax, eax
1460
	jnz	.finish
1461
 
1462
; switch to register window 3
1463
	set_io	0
1464
	set_io	REG_COMMAND
1465
	mov	ax, SELECT_REGISTER_WINDOW+3
1466
	out	dx, ax
1467
 
1468
; clear fullDuplexEnable in MacControl register
1469
	set_io	REG_MAC_CONTROL
1470
	in	ax , dx
1471
	and	ax , not 0x120
1472
	out	dx , ax
1521 hidnplayr 1473
  .fail:
1472 hidnplayr 1474
	xor	eax, eax
1475
 
1521 hidnplayr 1476
  .finish:
1472 hidnplayr 1477
	ret
1478
 
1479
 
1480
 
1481
;***************************************************************************
1482
;   Function
1483
;      try_loopback
1484
;   Description
1485
;      tries a loopback packet for 10BASE2 or AUI port
1486
;   Parameters
1487
;      al -  0: 10Mbps AUI connector
1488
;            1: 10BASE-2
1489
;      ebp - io_addr
1490
;   Return value
1491
;      al - 0
1492
;      al - 1
1493
;   Destroyed registers
1494
;      eax, ebx, ecx, edx, edi, esi
1495
;
1496
;***************************************************************************
1497
 
1498
align 4
1499
try_loopback:
1500
 
1501
	DEBUGF 1,"trying loopback\n"
1502
 
1503
	push	eax
1504
; switch to register window 3
1505
	set_io	0
1506
	set_io	REG_COMMAND
1507
	mov	ax, SELECT_REGISTER_WINDOW+3
1508
	out	dx, ax
1509
	mov	eax, [esp]
1510
 
1511
	mov	cl, al
1512
	inc	cl
1513
	shl	cl, 3
1514
	or	byte [device.mode+1], cl
1515
 
1516
	test	al, al ; aui or coax?
1517
	jz	.complete_loopback
1518
; enable 100BASE-2 DC-DC converter
1519
	mov	ax, (10b shl 11) ; EnableDcConverter
1520
	out	dx, ax
1521 hidnplayr 1521
  .complete_loopback:
1522
 
1472 hidnplayr 1523
	mov	cx, 2 ; give a port 3 chances to complete a loopback
1521 hidnplayr 1524
  .next_try:
1472 hidnplayr 1525
	push	ecx
1526
	call	test_packet
1527
	pop	ecx
1528
	test	eax, eax
1529
	loopzw	.next_try
1521 hidnplayr 1530
 
1531
  .finish:
1472 hidnplayr 1532
	xchg	eax, [esp]
1533
	test	al, al
1534
	jz	.aui_finish
1521 hidnplayr 1535
 
1472 hidnplayr 1536
; issue DisableDcConverter command
1537
	set_io	0
1538
	set_io	REG_COMMAND
1539
	mov	ax, (10111b shl 11)
1540
	out	dx, ax
1521 hidnplayr 1541
  .aui_finish:
1472 hidnplayr 1542
	pop	eax ; al contains the result of operation
1543
 
1544
	test	al, al
1545
	jnz	@f
1546
	and	byte [device.mode+1], not 11000b
1521 hidnplayr 1547
       @@:
1472 hidnplayr 1548
 
1549
	ret
1550
 
1551
 
1552
;***************************************************************************
1553
;   Function
1554
;      set_active_port
1555
;   Description
1556
;      It selects the media port (transceiver) to be used
1557
;   Return value:
1558
;   Destroyed registers
1559
;      eax, ebx, ecx, edx, edi, esi
1560
;
1561
;***************************************************************************
1562
 
1563
align 4
1564
set_active_port:
1565
 
1521 hidnplayr 1566
	DEBUGF 1,"Trying to find the active port\n"
1472 hidnplayr 1567
 
1568
; switch to register window 3
1569
	set_io	0
1570
	set_io	REG_COMMAND
1521 hidnplayr 1571
	mov	ax, SELECT_REGISTER_WINDOW + 3
1472 hidnplayr 1572
	out	dx, ax
1521 hidnplayr 1573
 
1472 hidnplayr 1574
	set_io	REG_INTERNAL_CONFIG
1575
	in	eax, dx
1576
	test	eax, (1 shl 24) ; check if autoselect enable
1577
	jz	.set_first_available_media
1578
 
1579
; check 100BASE-TX and 10BASE-T
1580
	set_io	REG_MEDIA_OPTIONS
1581
	in	ax, dx
1582
	test	al, 1010b	; check whether 100BASE-TX or 10BASE-T available
1583
	jz	.mii_device	; they are not available
1584
 
1585
; set auto-negotiation
1586
	set_io	REG_INTERNAL_CONFIG
1587
	in	eax, dx
1588
	and	eax, not (1111b shl 20)
1589
	or	eax, (1000b shl 20)
1590
	out	dx, eax
1591
	call	try_mii
1592
	test	al, al
1593
	jz	.mii_device
1594
	DEBUGF 1,"Using auto negotiation\n"
1595
	ret
1596
 
1521 hidnplayr 1597
  .mii_device:
1472 hidnplayr 1598
; switch to register window 3
1599
	set_io	0
1600
; check for off-chip mii device
1601
	set_io	REG_MEDIA_OPTIONS
1602
	in	ax, dx
1603
	test	al, 1000000b ; check miiDevice
1604
	jz	.base_fx
1605
	set_io	REG_INTERNAL_CONFIG
1606
	in	eax, dx
1607
	and	eax, not (1111b shl 20)
1608
	or	eax, (0110b shl 20) ; set MIIDevice
1609
	out	dx, eax
1610
	call	try_mii
1611
	test	al, al
1612
	jz	.base_fx
1613
	DEBUGF 1,"Using off-chip mii device\n"
1614
	ret
1615
 
1521 hidnplayr 1616
  .base_fx:
1472 hidnplayr 1617
; switch to register window 3
1618
	set_io	0
1619
; check for 100BASE-FX
1620
	set_io	REG_MEDIA_OPTIONS
1621
	in	ax, dx ; read media option register
1622
	test	al, 100b ; check 100BASE-FX
1623
	jz	.aui_enable
1624
	set_io	REG_INTERNAL_CONFIG
1625
	in	eax, dx
1626
	and	eax, not (1111b shl 20)
1627
	or	eax, (0101b shl 20) ; set 100base-FX
1628
	out	dx, eax
1629
	call	try_link_detect
1630
	test	al, al
1631
	jz	.aui_enable
1632
	DEBUGF 1,"Using 100Base-FX\n"
1633
	ret
1634
 
1521 hidnplayr 1635
  .aui_enable:
1472 hidnplayr 1636
; switch to register window 3
1637
	set_io	0
1638
; check for 10Mbps AUI connector
1639
	set_io	REG_MEDIA_OPTIONS
1640
	in	ax, dx ; read media option register
1641
	test	al, 100000b ; check 10Mbps AUI connector
1642
	jz	.coax_available
1643
	set_io	REG_INTERNAL_CONFIG
1644
	in	eax, dx
1645
	and	eax, not (1111b shl 20)
1646
	or	eax, (0001b shl 20) ; set 10Mbps AUI connector
1647
	out	dx, eax
1648
	xor	al, al ; try 10Mbps AUI connector
1649
	call	try_loopback
1650
	test	al, al
1651
	jz	.coax_available
1652
	DEBUGF 1,"Using 10Mbps aui\n"
1653
	ret
1654
 
1521 hidnplayr 1655
  .coax_available:
1472 hidnplayr 1656
; switch to register window 3
1657
	set_io	0
1658
; check for coaxial 10BASE-2 port
1659
	set_io	REG_MEDIA_OPTIONS
1660
	in	ax, dx ; read media option register
1661
	test	al, 10000b ; check 10BASE-2
1662
	jz	.set_first_available_media
1521 hidnplayr 1663
 
1472 hidnplayr 1664
	set_io	REG_INTERNAL_CONFIG
1665
	in	eax, dx
1666
	and	eax, not (1111b shl 20)
1667
	or	eax, (0011b shl 20) ; set 10BASE-2
1668
	out	dx, eax
1669
	mov	al, 1
1670
	call	try_loopback
1671
	test	al, al
1672
	jz	.set_first_available_media
1673
	DEBUGF 1,"Using 10BASE-2 port\n"
1674
	ret
1675
 
1521 hidnplayr 1676
  .set_first_available_media:
1677
	DEBUGF	1,"Using the first available media\n"
1472 hidnplayr 1678
 
1679
;***************************************************************************
1680
;   Function
1681
;      set_available_media
1682
;   Description
1683
;      sets the first available media
1684
;   Parameters
1521 hidnplayr 1685
;      ebx - ptr to device struct
1472 hidnplayr 1686
;   Return value
1687
;      al - 0
1688
;      al - 1
1689
;   Destroyed registers
1690
;      eax, edx
1691
;
1692
;***************************************************************************
1693
 
1694
align 4
1695
set_available_media:
1696
 
1521 hidnplayr 1697
	DEBUGF	1,"Setting the available media\n"
1472 hidnplayr 1698
; switch to register window 3
1699
	set_io	0
1700
	set_io	REG_COMMAND
1701
	mov	ax, SELECT_REGISTER_WINDOW+3
1702
	out	dx, ax
1521 hidnplayr 1703
 
1704
	set_io	REG_MEDIA_OPTIONS
1705
	in	ax, dx
1706
	DEBUGF	1,"available media:%x\n", al
1707
	mov	cl, al
1708
 
1472 hidnplayr 1709
	set_io	REG_INTERNAL_CONFIG
1710
	in	eax, dx
1521 hidnplayr 1711
	and	eax, not (1111b shl 20) ; these bits hold the 'transceiver select' value
1712
 
1713
	test	cl, 10b 	; baseTXAvailable
1472 hidnplayr 1714
	jz	@f
1521 hidnplayr 1715
 
1716
	DEBUGF	1,"base TX is available\n"
1472 hidnplayr 1717
	or	eax, (100b shl 20)
1718
if defined FORCE_FD
1719
	mov	word [device.mode], (1 shl 8)
1720
else
1721
	mov	word [device.mode], (1 shl 7)
1722
end if
1723
	jmp	.set_media
1521 hidnplayr 1724
       @@:
1725
 
1726
	test	cl, 100b	; baseFXAvailable
1472 hidnplayr 1727
	jz	@f
1521 hidnplayr 1728
 
1729
	DEBUGF	1,"base FX is available\n"
1472 hidnplayr 1730
	or	eax, (101b shl 20)
1731
	mov	word [device.mode], (1 shl 10)
1521 hidnplayr 1732
	jmp	.set_media
1733
       @@:
1472 hidnplayr 1734
 
1521 hidnplayr 1735
	test	cl, 1000000b	; miiDevice
1472 hidnplayr 1736
	jz	@f
1521 hidnplayr 1737
 
1738
	DEBUGF	1,"mii-device is available\n"
1472 hidnplayr 1739
	or	eax, (0110b shl 20)
1740
	mov	word [device.mode], (1 shl 13)
1521 hidnplayr 1741
	jmp	.set_media
1742
       @@:
1472 hidnplayr 1743
 
1521 hidnplayr 1744
	test	cl, 1000b	; 10bTAvailable
1472 hidnplayr 1745
	jz	@f
1521 hidnplayr 1746
 
1747
	DEBUGF	1,"10base-T is available\n"
1748
  .set_default:
1472 hidnplayr 1749
if FORCE_FD
1750
	mov	word [device.mode], (1 shl 6)
1751
else
1752
	mov	word [device.mode], (1 shl 5)
1521 hidnplayr 1753
end if
1472 hidnplayr 1754
	jmp	.set_media
1521 hidnplayr 1755
       @@:
1756
 
1757
	test	cl, 10000b	; coaxAvailable
1472 hidnplayr 1758
	jz	@f
1521 hidnplayr 1759
 
1760
	DEBUGF	1,"coax is available\n"
1761
	push	eax
1472 hidnplayr 1762
	set_io	REG_COMMAND
1763
	mov	ax, (10b shl 11) ; EnableDcConverter
1764
	out	dx, ax
1765
	pop	eax
1521 hidnplayr 1766
 
1472 hidnplayr 1767
	or	eax, (11b shl 20)
1768
	mov	word [device.mode], (1 shl 12)
1521 hidnplayr 1769
	jmp	.set_media
1770
       @@:
1472 hidnplayr 1771
 
1521 hidnplayr 1772
	test	cl, 10000b	; auiAvailable
1472 hidnplayr 1773
	jz	.set_default
1521 hidnplayr 1774
 
1775
	DEBUGF	1,"AUI is available\n"
1472 hidnplayr 1776
	or	eax, (1 shl 20)
1777
	mov	word [device.mode], (1 shl 11)
1778
 
1521 hidnplayr 1779
  .set_media:
1780
	set_io	0
1472 hidnplayr 1781
	set_io	REG_INTERNAL_CONFIG
1782
	out	dx, eax
1521 hidnplayr 1783
 
1472 hidnplayr 1784
if FORCE_FD
1521 hidnplayr 1785
	DEBUGF	1,"Forcing full duplex\n"
1472 hidnplayr 1786
	set_io	REG_MAC_CONTROL
1787
	in	ax, dx
1788
	or	ax, 0x120
1789
	out	dx, ax
1521 hidnplayr 1790
end if
1791
 
1472 hidnplayr 1792
	mov	al, 1
1793
	ret
1794
 
1795
 
1796
 
1797
;***************************************************************************
1798
;   Function
1799
;      wake_up
1800
;   Description
1801
;      set the power state to D0
1802
;
1803
;***************************************************************************
1804
 
1805
align 4
1806
wake_up:
1807
 
1808
	DEBUGF 1,"Waking up NIC: "
1809
 
1810
; wake up - we directly do it by programming PCI
1811
; check if the device is power management capable
1812
	movzx	ecx, [device.pci_bus]
1813
	movzx	edx, [device.pci_dev]
1814
	stdcall PciRead32, ecx, edx, PCI_REG_STATUS
1815
 
1816
	test	al, 10000b	; is there "new capabilities" linked list?
1817
	jz	.device_awake
1818
 
1819
; search for power management register
1820
	stdcall PciRead16, ecx, edx, PCI_REG_CAP_PTR
1821
	cmp	al, 0x3f
1822
	jbe	.device_awake
1823
 
1824
; traverse the list
1825
	movzx	esi, al
1521 hidnplayr 1826
  .pm_loop:
1472 hidnplayr 1827
	stdcall PciRead32, ecx, edx, esi
1828
 
1829
	cmp	al , 1
1830
	je	.set_pm_state
1831
 
1832
	movzx	esi, ah
1833
 
1834
	test	ah , ah
1835
	jnz	.pm_loop
1836
	jmp	.device_awake
1837
 
1838
; waku up the device if necessary
1521 hidnplayr 1839
  .set_pm_state:
1472 hidnplayr 1840
 
1841
	add	esi, PCI_REG_PM_CTRL
1842
	stdcall PciRead32, ecx, edx, esi
1843
	test	al, 3
1844
	jz	.device_awake
1845
	and	al, not 11b ; set state to D0
1846
	stdcall PciWrite32, ecx, edx, esi, eax
1847
 
1521 hidnplayr 1848
  .device_awake:
1472 hidnplayr 1849
	DEBUGF 1,"Device is awake\n"
1850
 
1851
	ret
1852
 
1853
 
1854
 
1855
 
1856
;***************************************************************************
1857
;   Function
1858
;      write_eeprom
1859
;   Description
1860
;      reads eeprom
1861
;      Note : the caller must switch to the register window 0
1862
;             before calling this function
1863
;   Parameters:
1864
;      ax - register to be read (only the first 63 words can be read)
1865
;      cx - value to be read into the register
1866
;   Return value:
1867
;      ax - word read
1868
;   Destroyed registers
1869
;      ax, ebx, edx
1870
;
1871
;***************************************************************************
1872
;       align 4
1873
;write_eeprom:
1874
;       mov     edx, [io_addr]
1875
;       add     edx, REG_EEPROM_COMMAND
1876
;       cmp     ah, 11b
1877
;       ja      .finish ; address may have a value of maximal 1023
1878
;       shl     ax, 2
1879
;       shr     al, 2
1880
;       push    eax
1881
;; wait for busy
1882
;       mov     ebx, 0xffff
1883
;@@:
1884
;       in      ax, dx
1885
;       test    ah, 0x80
1886
;       jz      .write_enable
1887
;       dec     ebx
1888
;       jns     @r
1889
;; write enable
1890
;.write_enable:
1891
;       xor     eax, eax
1892
;       mov     eax, (11b shl 4)
1893
;       out     dx, ax
1894
;; wait for busy
1895
;       mov     ebx, 0xffff
1896
;@@:
1897
;       in      ax, dx
1898
;       test    ah, 0x80
1899
;       jz      .erase_loop
1900
;       dec     ebx
1901
;       jns     @r
1902
;.erase_loop:
1903
;       pop     eax
1904
;       push    eax
1905
;       or      ax, (11b shl 6) ; erase register
1906
;       out     dx, ax
1907
;       mov     ebx, 0xffff
1908
;@@:
1909
;       in      ax, dx
1910
;       test    ah, 0x80
1911
;       jz      .write_reg
1912
;       dec     ebx
1913
;       jns     @r
1914
;.write_reg:
1915
;       add     edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND
1916
;       mov     eax, ecx
1917
;       out     dx, ax
1918
;; write enable
1919
;       add     edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA
1920
;       xor     eax, eax
1921
;       mov     eax, (11b shl 4)
1922
;       out     dx, ax
1923
; wait for busy
1924
;       mov     ebx, 0xffff
1925
;@@:
1926
;       in      ax, dx
1927
;       test    ah, 0x80
1928
;       jz      .issue_write_reg
1929
;       dec     ebx
1930
;       jns     @r
1931
;.issue_write_reg:
1932
;       pop     eax
1933
;       or      ax, 01b shl 6
1934
;       out     dx, ax
1935
;.finish:
1936
;       ret
1521 hidnplayr 1937
 
1938
 
1472 hidnplayr 1939
;***************************************************************************
1940
;   Function
1941
;      read_eeprom
1942
;   Description
1943
;      reads eeprom
1944
;   Parameters:
1945
;       ax - register to be read (only the first 63 words can be read)
1946
;      ebx = driver structure
1947
;   Return value:
1948
;      ax - word read
1949
;   Destroyed registers
1521 hidnplayr 1950
;      ax, ebx, edx
1472 hidnplayr 1951
;
1952
;***************************************************************************
1953
 
1954
align 4
1955
read_eeprom:
1956
 
1521 hidnplayr 1957
	DEBUGF 1,"Reading from eeprom.. "
1472 hidnplayr 1958
 
1959
	push	eax
1960
; switch to register window 0
1961
	set_io	0
1962
	set_io	REG_COMMAND
1963
	mov	ax, SELECT_REGISTER_WINDOW+0
1964
	out	dx, ax
1965
	pop	eax
1966
	and	ax, 111111b ; take only the first 6 bits into account
1967
	movzx	esi, [device.ver_id]
1968
 
1969
	test	word [esi*4+hw_versions+2], EEPROM_8BIT
1970
	jz	@f
1971
	add	ax, 0x230 ; hardware constant
1972
	jmp	.read
1973
@@:
1974
 
1975
	add	ax, EEPROM_CMD_READ
1976
	test	word [esi*4+hw_versions+2], EEPROM_OFFSET
1977
	jz	.read
1978
	add	ax, 0x30
1979
.read:
1980
 
1981
	set_io	REG_EEPROM_COMMAND
1982
	out	dx, ax
1983
	mov	ecx, 0xffff ; duration of about 162 us ;-)
1984
.wait_for_reading:
1985
	in	ax, dx
1986
	test	ah, 0x80 ; check bit eepromBusy
1987
	jz	.read_data
1988
	loop	.wait_for_reading
1989
.read_data:
1990
	set_io	REG_EEPROM_DATA
1991
	in	ax, dx
1992
 
1993
	DEBUGF 1,"ok!\n"
1994
 
1995
	ret
1996
 
1997
;***************************************************************************
1998
;   Function
1999
;      mdio_sync
2000
;   Description
2001
;      initial synchronization
2002
;   Parameters
2003
;      ebp - io_addr
2004
;   Return value
2005
;   Destroyed registers
2006
;      ax, edx, cl
2007
;
2008
;***************************************************************************
2009
 
2010
align 4
2011
mdio_sync:
2012
 
2013
	DEBUGF 1,"syncing mdio\n"
2014
 
2015
; switch to register window 4
2016
	set_io	0
2017
	set_io	REG_COMMAND
2018
	mov	ax, SELECT_REGISTER_WINDOW+4
2019
	out	dx, ax
2020
	cmp	[device.preamble], 0
2021
	je	.no_preamble
2022
; send 32 logic ones
2023
	set_io	REG_PHYSICAL_MGMT
2024
	mov	ecx, 31
1521 hidnplayr 2025
  .loop:
1472 hidnplayr 2026
	mov	ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR)
2027
	out	dx, ax
2028
	in	ax, dx ; delay
2029
	mov	ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK)
2030
	out	dx, ax
2031
	in	ax, dx ; delay
2032
	loop	.loop
1521 hidnplayr 2033
  .no_preamble:
1472 hidnplayr 2034
 
2035
	ret
2036
 
2037
;***************************************************************************
2038
;   Function
2039
;      mdio_read
2040
;   Description
2041
;      read MII register
2042
;      see page 16 in D83840A.pdf
2043
;   Parameters
2044
;       ah - PHY addr
2045
;       al - register addr
2046
;      ebx = device structure
2047
;   Return value
2048
;      ax - register read
2049
;
2050
;***************************************************************************
2051
 
2052
align 4
2053
mdio_read:
2054
 
1521 hidnplayr 2055
	DEBUGF 1,"Reading MII registers\n"
1472 hidnplayr 2056
 
2057
	push	eax
2058
	call	mdio_sync ; returns with window #4
2059
	pop	eax
2060
	set_io	0
2061
	set_io	REG_PHYSICAL_MGMT
2062
	shl	al, 3
2063
	shr	ax, 3
2064
	and	ax, not MII_CMD_MASK
2065
	or	ax, MII_CMD_READ
2066
 
2067
	mov	esi, eax
2068
	mov	ecx, 13
1521 hidnplayr 2069
  .cmd_loop:
1472 hidnplayr 2070
	mov	ax, (1 shl BIT_MGMT_DIR) ; write mii
2071
	bt	esi, ecx
2072
	jnc	.zero_bit
2073
	or	al, (1 shl BIT_MGMT_DATA)
2074
 
1521 hidnplayr 2075
  .zero_bit:
1472 hidnplayr 2076
	out	dx, ax
2077
	push	ax
2078
	in	ax, dx ; delay
2079
	pop	ax
2080
	or	al, (1 shl BIT_MGMT_CLK) ; write
2081
	out	dx, ax
2082
	in	ax, dx ; delay
2083
	loop	.cmd_loop
2084
 
2085
; read data (18 bits with the two transition bits)
2086
	mov	ecx, 17
2087
	xor	esi, esi
1521 hidnplayr 2088
  .read_loop:
1472 hidnplayr 2089
	shl	esi, 1
2090
	xor	eax, eax ; read comand
2091
	out	dx, ax
2092
	in	ax, dx ; delay
2093
	in	ax, dx
2094
	test	al, (1 shl BIT_MGMT_DATA)
2095
	jz	.dont_set
2096
	inc	esi
1521 hidnplayr 2097
  .dont_set:
1472 hidnplayr 2098
	mov	ax, (1 shl BIT_MGMT_CLK)
2099
	out	dx, ax
2100
	in	ax, dx ; delay
2101
	loop	.read_loop
2102
	mov	eax, esi
2103
 
2104
	ret
2105
 
2106
 
2107
 
2108
;***************************************************************************
2109
;   Function
2110
;      mdio_write
2111
;   Description
2112
;      write MII register
2113
;      see page 16 in D83840A.pdf
2114
;   Parameters
2115
;       ah - PHY addr
2116
;       al - register addr
2117
;       si - word to be written
2118
;   Return value
2119
;      ax - register read
2120
;
2121
;***************************************************************************
2122
 
2123
align 4
2124
mdio_write:
2125
 
2126
	DEBUGF 1,"Writing MII registers\n"
2127
 
2128
	push	eax
2129
	call	mdio_sync
2130
	pop	eax
2131
	set_io	0
2132
	set_io	REG_PHYSICAL_MGMT
2133
	shl	al, 3
2134
	shr	ax, 3
2135
	and	ax, not MII_CMD_MASK
2136
	or	ax, MII_CMD_WRITE
2137
	shl	eax, 2
2138
	or	eax, 10b ; transition bits
2139
	shl	eax, 16
2140
	mov	ax, si
2141
	mov	esi, eax
2142
	mov	ecx, 31
1521 hidnplayr 2143
 
2144
  .cmd_loop:
1472 hidnplayr 2145
	mov	ax, (1 shl BIT_MGMT_DIR) ; write mii
2146
	bt	esi, ecx
1521 hidnplayr 2147
	jnc	@f
1472 hidnplayr 2148
	or	al, (1 shl BIT_MGMT_DATA)
1521 hidnplayr 2149
       @@:
1472 hidnplayr 2150
	out	dx, ax
2151
	push	eax
2152
	in	ax, dx ; delay
2153
	pop	eax
2154
	or	al, (1 shl BIT_MGMT_CLK) ; write
2155
	out	dx, ax
2156
	in	ax, dx ; delay
2157
	loop	.cmd_loop
2158
 
2159
	ret
2160
 
2161
 
2162
;***************************************************************************
2163
;   Function
2164
;      check_tx_status
2165
;   Description
2166
;      Checks TxStatus queue.
2167
;   Return value
2168
;      al - 0 no error was found
1545 hidnplayr 2169
;      al - 1 error was found TxReset was needed
1472 hidnplayr 2170
;   Destroyed registers
2171
;      eax, ecx, edx, ebp
2172
;
2173
;***************************************************************************
2174
 
2175
align 4
2176
check_tx_status:
2177
 
2178
	DEBUGF 1,"Checking TX status\n"
2179
 
2180
; clear TxStatus queue
2181
	set_io	0
2182
	set_io	REG_TX_STATUS
2183
	mov	ecx, 31 ; max number of queue entries
1521 hidnplayr 2184
 
2185
  .tx_status_loop:
1472 hidnplayr 2186
	in	al, dx
2187
	test	al, al
2188
	jz	.finish ; no error
2189
	test	al, 0x3f
1545 hidnplayr 2190
	jnz	.error
1521 hidnplayr 2191
  .no_error_found:
1472 hidnplayr 2192
; clear current TxStatus entry which advances the next one
2193
	xor	al, al
2194
	out	dx, al
2195
	loop	.tx_status_loop
2196
 
1521 hidnplayr 2197
  .finish:
2198
 
1472 hidnplayr 2199
	ret
2200
 
1545 hidnplayr 2201
  .error:
2202
	call	tx_reset
2203
	ret
1472 hidnplayr 2204
 
2205
 
1545 hidnplayr 2206
 
1472 hidnplayr 2207
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2208
;;                                         ;;
2209
;; Transmit (vortex)                       ;;
2210
;;                                         ;;
2211
;; In: buffer pointer in [esp+4]           ;;
2212
;;     size of buffer in [esp+8]           ;;
2213
;;     pointer to device structure in ebx  ;;
2214
;;                                         ;;
2215
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2216
 
2217
align 4
2218
vortex_transmit:
2219
 
2220
	DEBUGF 1,"Sending packet (vortex)\n"
2221
 
2222
	cmp	dword [esp+8], MAX_ETH_FRAME_SIZE
2223
	ja	.finish ; packet is too long
2224
 
2225
	call	check_tx_status
2226
 
2227
; switch to register window 7
2228
	set_io	0
2229
	set_io	REG_COMMAND
2230
	mov	ax, SELECT_REGISTER_WINDOW+7
2231
	out	dx, ax
2232
; check for master operation in progress
2233
	set_io	REG_MASTER_STATUS
2234
	in	ax, dx
2235
	test	ah, 0x80
2236
	jnz	.finish ; no DMA for sending
2237
; program frame address to be sent
2238
	set_io	REG_MASTER_ADDRESS
2239
	mov	eax, [esp+4]
2240
	call	GetPgAddr
2241
	out	dx, eax
2242
; program frame length
2243
	set_io	REG_MASTER_LEN
2244
	mov	eax, [esp+8]
2245
;;;        and     eax, not 3
2246
	out	dx, ax
2247
; start DMA Down
2248
	set_io	REG_COMMAND
2249
	mov	ax, (10100b shl 11) + 1 ; StartDMADown
2250
	out	dx, ax
2251
.finish:
1519 hidnplayr 2252
	call	KernelFree
2253
	add	esp, 4
1472 hidnplayr 2254
	ret
2255
 
2256
 
2257
 
2258
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2259
;;                                         ;;
2260
;; Transmit (boomerang)                    ;;
2261
;;                                         ;;
2262
;; In: buffer pointer in [esp+4]           ;;
2263
;;     size of buffer in [esp+8]           ;;
2264
;;     pointer to device structure in ebx  ;;
2265
;;                                         ;;
2266
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2267
 
2268
align 4
2269
boomerang_transmit:
2270
 
1519 hidnplayr 2271
	DEBUGF	1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
2272
	mov	eax, [esp+4]
2273
	DEBUGF	1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
2274
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
2275
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
2276
	[eax+13]:2,[eax+12]:2
1472 hidnplayr 2277
 
2278
	cmp	dword [esp+8], MAX_ETH_FRAME_SIZE
1519 hidnplayr 2279
	jg	.fail
1472 hidnplayr 2280
 
2281
	call	check_tx_status
1519 hidnplayr 2282
 
1472 hidnplayr 2283
; calculate descriptor address
1519 hidnplayr 2284
	mov	esi, [device.prev_dpd]
2285
	DEBUGF	1,"Previous DPD: %x\n", esi
2286
	add	esi, dpd.size
2287
	lea	ecx, [device.dpd_buffer + (NUM_TX_DESC)*dpd.size]
2288
	cmp	esi, ecx
2289
	jl	@f
2290
	lea	esi, [device.dpd_buffer]	; Wrap if needed
2291
       @@:
2292
	DEBUGF	1,"Found a free DPD: %x\n", esi
1472 hidnplayr 2293
 
2294
; check DnListPtr
2295
	set_io	0
2296
	set_io	REG_DN_LIST_PTR
2297
	in	eax, dx
2298
; mark if Dn_List_Ptr is cleared
2299
	test	eax, eax
2300
	setz	[device.dn_list_ptr_cleared]
1519 hidnplayr 2301
 
1472 hidnplayr 2302
; finish if no more free descriptor is available - FIXME!
1519 hidnplayr 2303
;        cmp     eax, esi
2304
;        jz      .finish
1472 hidnplayr 2305
 
1481 hidnplayr 2306
; update statistics
2307
	inc	[device.packets_tx]
1519 hidnplayr 2308
	mov	ecx, [esp+8]		; buffer size
1481 hidnplayr 2309
	add	dword [device.bytes_tx], ecx
2310
	adc	dword [device.bytes_tx + 4], 0
2311
 
1472 hidnplayr 2312
; program DPD
1519 hidnplayr 2313
	and	[esi+dpd.next_ptr], 0
2314
	mov	eax, [esp+4]		; Tx buffer address
2315
	mov	[esi+dpd.realaddr], eax
1472 hidnplayr 2316
	call	GetPgAddr
1519 hidnplayr 2317
	mov	[esi+dpd.frag_addr], eax
2318
	mov	ecx, [esp+8]		; packet size
2319
	or	ecx, 0x80000000 	; last fragment
2320
	mov	[esi+dpd.frag_len], ecx
1472 hidnplayr 2321
 
1519 hidnplayr 2322
	mov	ecx, [esp+8]		; packet size
2323
;        or      ecx, 0x8000             ; transmission complete notification
1472 hidnplayr 2324
 
1519 hidnplayr 2325
	or	ecx, 1 shl 31
1472 hidnplayr 2326
 
2327
;        test    byte [device.has_hwcksm], 0xff
2328
;        jz      @f
1519 hidnplayr 2329
;        or      ecx, (1 shl 26)         ; set AddTcpChecksum
1472 hidnplayr 2330
;@@:
1519 hidnplayr 2331
	mov	[esi+dpd.frame_start_hdr], ecx
1472 hidnplayr 2332
 
1519 hidnplayr 2333
	DEBUGF	1,"DPD: lin=%x phys=%x len=%x start hdr=%x\n", [esi+dpd.realaddr]:8, [esi+dpd.frag_addr]:8, [esi+dpd.frag_len]:8, [esi+dpd.frame_start_hdr]:8
1472 hidnplayr 2334
 
1519 hidnplayr 2335
; calculate physical address of dpd
2336
	mov	eax, esi
2337
	GetRealAddr
1472 hidnplayr 2338
	cmp	[device.dn_list_ptr_cleared], 0
2339
	jz	.add_to_list
2340
 
2341
; write Dn_List_Ptr
1519 hidnplayr 2342
	DEBUGF	1,"DPD phys addr=%x\n", eax
1472 hidnplayr 2343
	set_io	0
2344
	set_io	REG_DN_LIST_PTR
2345
	out	dx, eax
1519 hidnplayr 2346
	jmp	.finish
1472 hidnplayr 2347
 
1519 hidnplayr 2348
  .add_to_list:
1472 hidnplayr 2349
	DEBUGF	1,"Adding To list\n"
1519 hidnplayr 2350
	push	eax
1472 hidnplayr 2351
; DnStall
2352
	set_io	0
2353
	set_io	REG_COMMAND
2354
	mov	ax, ((110b shl 11)+2)
2355
	out	dx, ax
2356
 
2357
; wait for DnStall to complete
2358
	DEBUGF	1,"Waiting for DnStall\n"
2359
	mov	ecx, 6000
1519 hidnplayr 2360
  .wait_for_stall:
1472 hidnplayr 2361
	in	ax, dx			; read REG_INT_STATUS
2362
	test	ah, 10000b
2363
	jz	.dnstall_ok
2364
	dec	ecx
2365
	jnz	.wait_for_stall
2366
 
1519 hidnplayr 2367
  .dnstall_ok:
1472 hidnplayr 2368
	DEBUGF	1,"DnStall ok!\n"
2369
	mov	ecx, [device.prev_dpd]
2370
	mov	[ecx+dpd.next_ptr], eax
2371
 
2372
	set_io	0
2373
	set_io	REG_DN_LIST_PTR
2374
	in	eax, dx
2375
	test	eax, eax
1519 hidnplayr 2376
	pop	eax
1472 hidnplayr 2377
	jnz	.dnunstall
1519 hidnplayr 2378
 
1472 hidnplayr 2379
; if Dn_List_Ptr has been cleared fill it up
2380
	DEBUGF	1,"DnList Ptr has been cleared\n"
2381
	out	dx, eax
2382
 
1519 hidnplayr 2383
  .dnunstall:
1472 hidnplayr 2384
; DnUnStall
2385
	set_io	0
2386
	set_io	REG_COMMAND
2387
	mov	ax, ((110b shl 11)+3)
2388
	out	dx, ax
2389
 
1519 hidnplayr 2390
  .finish:
2391
	mov	[device.prev_dpd], esi
1472 hidnplayr 2392
	xor	eax, eax
1519 hidnplayr 2393
	ret	8
1472 hidnplayr 2394
 
1519 hidnplayr 2395
  .fail:
2396
	stdcall KernelFree, [esp+4]
2397
	ret	8
1472 hidnplayr 2398
 
1519 hidnplayr 2399
 
1472 hidnplayr 2400
;---------------------------------
2401
; Write MAC
2402
 
2403
align 4
1521 hidnplayr 2404
write_mac:
1472 hidnplayr 2405
 
2406
	DEBUGF 1,"Writing mac\n"
2407
 
2408
	set_io	0
2409
	set_io	REG_COMMAND
2410
 
2411
; switch to register window 2
2412
	mov	ax, SELECT_REGISTER_WINDOW+2
2413
	out	dx, ax
2414
 
2415
; write MAC addres back into the station address registers
2416
	set_io	REG_STATION_ADDRESS_LO
2417
	lea	esi, [device.mac]
2418
	outsw
2419
	inc	dx
2420
	inc	dx
2421
	outsw
2422
	inc	dx
2423
	inc	dx
2424
	outsw
2425
 
1521 hidnplayr 2426
 
1472 hidnplayr 2427
;----------------------------
2428
; Read MAC
2429
 
2430
align 4
1521 hidnplayr 2431
read_mac:
1472 hidnplayr 2432
 
2433
	set_io	0
2434
	set_io	REG_COMMAND
2435
 
2436
; switch to register window 2
2437
	mov	ax, SELECT_REGISTER_WINDOW+2
2438
	out	dx, ax
2439
 
2440
; write MAC addres back into the station address registers
2441
	set_io	REG_STATION_ADDRESS_LO
2442
	lea	edi, [device.mac]
2443
	insw
2444
	inc	dx
2445
	inc	dx
2446
	insw
2447
	inc	dx
2448
	inc	dx
2449
	insw
2450
 
2451
	DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
2452
 
2453
	ret
2454
 
2455
 
2456
;------------------------------------
2457
; Read MAC from eeprom
2458
 
2459
align 4
2460
read_mac_eeprom:	; Tested - ok
2461
 
2462
	DEBUGF 1,"Reading mac from eeprom\n"
2463
 
2464
; read MAC from eeprom
2465
	mov	ecx, 3
1521 hidnplayr 2466
  .mac_loop:
1472 hidnplayr 2467
	lea	ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1]
2468
	push	ecx
2469
	call	read_eeprom
2470
	pop	ecx
2471
	xchg	ah, al ; htons
2472
	mov	word [device.mac+ecx*2-2], ax
2473
	loop	.mac_loop
2474
 
2475
	DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
2476
 
2477
	ret
2478
 
2479
 
2480
 
2481
 
2482
 
2483
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2484
;;                          ;;
2485
;; Vortex Interrupt handler ;;
2486
;;                          ;;
2487
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2488
 
2489
align 4
2490
int_vortex:
2491
 
2492
	DEBUGF	1,"vortex IRQ %x ",eax:2
2493
 
2494
; find pointer of device wich made IRQ occur
2495
 
2496
	mov	esi, VORTEX_LIST
2497
	mov	ecx, [VORTEX_DEVICES]
2498
	test	ecx, ecx
2499
	jz	.fail
2500
  .nextdevice:
2501
	mov	ebx, dword [esi]
2502
 
2503
 
2504
	set_io	0
2505
	set_io	REG_INT_STATUS
2506
	in	ax, dx
2507
;;        and     ax, INT_MASK
2508
	jnz	.got_it
2509
 
2510
 
2511
	add	esi, 4
2512
 
2513
	test	ax , ax
2514
	jnz	.got_it
2515
	loop	.nextdevice
2516
 
2517
  .fail:
2518
 
2519
	ret
2520
 
2521
.got_it:
2522
 
2523
	DEBUGF	1,"Device: %x Status: %x ",ebx,eax:4
2524
 
2525
	test	ax, RxComplete
2526
	jz	.noRX
2527
 
2528
	set_io	0
2529
  .rx_status_loop:
2530
; examine RxStatus
2531
	set_io	REG_RX_STATUS
2532
	in	ax, dx
2533
	test	ax, ax
2534
	jz	.finish
2535
 
2536
	test	ah, 0x80 ; rxIncomplete
2537
	jnz	.finish
2538
 
2539
	test	ah, 0x40
2540
	jz	.check_length
2541
 
2542
; discard the top frame received advancing the next one
2543
	set_io	REG_COMMAND
2544
	mov	ax, (01000b shl 11)
2545
	out	dx, ax
2546
	jmp	.rx_status_loop
2547
 
2548
  .check_length:
2549
	and	eax, 0x1fff
2550
	cmp	eax, MAX_ETH_PKT_SIZE
2551
	ja	.discard_frame ; frame is too long discard it
2552
 
2553
  .check_dma:
2554
	mov	ecx, eax
2555
; switch to register window 7
2556
	set_io	0
2557
	set_io	REG_COMMAND
2558
	mov	ax, SELECT_REGISTER_WINDOW+7
2559
	out	dx, ax
2560
; check for master operation in progress
2561
	set_io	REG_MASTER_STATUS
2562
	in	ax, dx
2563
 
2564
	test	ah, 0x80
2565
	jnz	.finish
2566
 
2567
  .read_frame:
2568
; program buffer address to read in
1519 hidnplayr 2569
	push	ecx
2570
	stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
2571
	pop	ecx
1472 hidnplayr 2572
	test	eax, eax
2573
	jz	.finish
2574
 
2575
	push	.discard_frame
2576
	push	ecx
2577
	push	eax
2578
;        zero_to_dma eax
2579
	set_io	REG_MASTER_ADDRESS
2580
	out	dx, eax
2581
 
2582
; program frame length
2583
	set_io	REG_MASTER_LEN
2584
	mov	ax, 1560
2585
	out	dx, ax
2586
 
2587
; start DMA Up
2588
	set_io	REG_COMMAND
2589
	mov	ax, (10100b shl 11) ; StartDMAUp
2590
	out	dx, ax
2591
 
2592
; check for master operation in progress
2593
	set_io	REG_MASTER_STATUS   ; TODO: use timeout and reset after timeout expired
2594
  .dma_loop:
2595
	in	ax, dx
2596
	test	ah, 0x80
2597
	jnz	.dma_loop
2598
 
2599
; registrate the received packet to kernel
2600
	jmp	EthReceiver
2601
 
2602
; discard the top frame received
2603
  .discard_frame:
2604
	set_io	0
2605
	set_io	REG_COMMAND
2606
	mov	ax, (01000b shl 11)
2607
	out	dx, ax
2608
 
2609
  .finish:
2610
 
2611
 
2612
.noRX:
2613
 
2614
	test	ax, DMADone
2615
	jz	.noDMA
2616
 
2617
	push	ax
2618
 
2619
	set_io	0
2620
	set_io	12
2621
	in	ax, dx
2622
	test	ax, 0x1000
2623
	jz	.nodmaclear
2624
 
2625
	mov	ax, 0x1000
2626
	out	dx, ax
2627
 
2628
  .nodmaclear:
2629
 
2630
	pop	ax
2631
 
2632
	DEBUGF	1, "DMA Done!\n", cx
2633
 
2634
 
2635
 
2636
.noDMA:
2637
 
2638
 
2639
 
2640
.ACK:
2641
	set_io	0
2642
	set_io	REG_COMMAND
2643
	mov	ax, AckIntr + IntReq + IntLatch
2644
	out	dx, ax
2645
 
2646
	ret
2647
 
2648
 
2649
 
2650
 
2651
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2652
;;                             ;;
2653
;; Boomerang Interrupt handler ;;
2654
;;                             ;;
2655
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2656
 
2657
align 4
2658
int_boomerang:
2659
 
1519 hidnplayr 2660
	DEBUGF	1,"\nIRQ %x Boomerang\n",eax:2
1472 hidnplayr 2661
 
2662
; find pointer of device wich made IRQ occur
2663
 
2664
	mov	esi, BOOMERANG_LIST
2665
	mov	ecx, [BOOMERANG_DEVICES]
2666
 
2667
	test	ecx, ecx
2668
	jz	.fail
2669
  .nextdevice:
2670
	mov	ebx, dword[esi]
2671
 
2672
	set_io	0
2673
	set_io	REG_INT_STATUS
2674
	in	ax, dx
2675
	test	ax, IntLatch
2676
	jnz	.got_it
2677
 
2678
	add	esi, 4
2679
 
2680
	test	ax , ax
2681
	jnz	.got_it
2682
	dec	ecx
2683
	jnz	.nextdevice
2684
 
2685
  .fail:
2686
	DEBUGF	1,"Failed!\n"
2687
	ret
2688
 
2689
.got_it:
2690
 
2691
	DEBUGF	1,"Device: %x Status: %x ", ebx, eax
2692
	push	ax
2693
; disable all INTS
2694
 
2695
	set_io	REG_COMMAND
2696
	mov	ax, SetIntrEnb
2697
	out	dx, ax
2698
 
2699
;--------------------------------------------------------------------------
2700
	test	word[esp], UpComplete
2701
	jz	.noRX
2702
 
2703
	push	ebx
2704
 
2705
  .receive:
2706
	DEBUGF	1,"UpComplete\n"
2707
 
2708
; check if packet is uploaded
1519 hidnplayr 2709
	mov	esi, [device.curr_upd]
2710
	test	byte [esi+upd.pkt_status+1], 0x80 ; upPktComplete
1472 hidnplayr 2711
	jz	.finish
1519 hidnplayr 2712
	DEBUGF	1, "Current upd: %x\n", esi
1472 hidnplayr 2713
; packet is uploaded check for any error
2714
  .check_error:
1519 hidnplayr 2715
	test	byte [esi+upd.pkt_status+1], 0x40 ; upError
1472 hidnplayr 2716
	jz	.copy_packet_length
2717
	DEBUGF	1,"Error in packet\n"
1519 hidnplayr 2718
	and	[esi+upd.pkt_status], 0 	  ; mark packet as read
1472 hidnplayr 2719
	jmp	.finish
2720
  .copy_packet_length:
1519 hidnplayr 2721
	mov	ecx, [esi+upd.pkt_status]
1472 hidnplayr 2722
	and	ecx, 0x1fff
2723
 
1519 hidnplayr 2724
;        cmp     ecx, MAX_ETH_PKT_SIZE
2725
;        jbe     .copy_packet
2726
;        and     [esi+upd.pkt_status], 0
2727
;        jmp     .finish
2728
;  .copy_packet:
1472 hidnplayr 2729
 
1519 hidnplayr 2730
	DEBUGF	1, "Received %u bytes in buffer %x\n", ecx, [esi+upd.realaddr]:8
1472 hidnplayr 2731
 
2732
	push	dword .loop ;.finish
1519 hidnplayr 2733
	push	ecx
2734
	push	[esi+upd.realaddr]
1472 hidnplayr 2735
 
1481 hidnplayr 2736
; update statistics
2737
	inc	[device.packets_rx]
2738
	add	dword [device.bytes_rx], ecx
2739
	adc	dword [device.bytes_rx + 4], 0
2740
 
1519 hidnplayr 2741
; update UPD (Alloc new buffer for next packet)
2742
	stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
2743
	mov	[esi + upd.realaddr], eax
2744
	GetRealAddr
2745
	mov	[esi + upd.frag_addr], eax
2746
	and	[esi + upd.pkt_status], 0
2747
	mov	[esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
1472 hidnplayr 2748
 
1519 hidnplayr 2749
; Update UPD pointer
2750
	add	esi, upd.size
2751
	lea	ecx, [device.upd_buffer+(NUM_RX_DESC)*upd.size]
2752
	cmp	esi, ecx
2753
	jl	@f
2754
	lea	esi, [device.upd_buffer]
2755
       @@:
2756
	mov	[device.curr_upd], esi
2757
	DEBUGF	1, "Next upd: %x\n", esi
1472 hidnplayr 2758
 
2759
	jmp	EthReceiver
1519 hidnplayr 2760
  .loop:
1472 hidnplayr 2761
 
2762
	mov	ebx, [esp]
2763
	jmp	.receive
2764
 
2765
  .finish:
2766
	pop	ebx
2767
 
2768
; check if the NIC is in the upStall state
2769
	set_io	0
2770
	set_io	REG_UP_PKT_STATUS
2771
	in	eax, dx
2772
	test	ah, 0x20	     ; UpStalled
2773
	jz	.noUpUnStall
1519 hidnplayr 2774
 
2775
	DEBUGF	1, "upUnStalling\n"
1472 hidnplayr 2776
; issue upUnStall command
2777
	set_io	REG_COMMAND
2778
	mov	ax, ((11b shl 12)+1) ; upUnStall
2779
	out	dx, ax
1519 hidnplayr 2780
 
2781
	;;;; FIXME: make upunstall work
2782
 
1472 hidnplayr 2783
  .noUpUnStall:
1519 hidnplayr 2784
.noRX:
2785
	test	word[esp], DownComplete
2786
	jz	.noTX
2787
	DEBUGF	1, "Downcomplete!\n"
1472 hidnplayr 2788
 
1519 hidnplayr 2789
	mov	ecx, NUM_TX_DESC
2790
	lea	esi, [device.dpd_buffer]
2791
  .txloop:
2792
	test	[esi+dpd.frame_start_hdr], 1 shl 31
2793
	jz	.maybenext
2794
 
2795
	and	[esi+dpd.frame_start_hdr], 0
2796
	push	ecx
2797
	stdcall KernelFree, [esi+dpd.realaddr]
2798
	pop	ecx
2799
 
2800
  .maybenext:
2801
	add	esi, dpd.size
2802
	dec	ecx
2803
	jnz	.txloop
2804
 
2805
.noTX:
1472 hidnplayr 2806
	pop	ax
2807
 
2808
	set_io	0
2809
	set_io	REG_COMMAND
2810
	or	ax, AckIntr
2811
	out	dx, ax
2812
 
2813
	set_io	REG_INT_STATUS
2814
	in	ax, dx
2815
	test	ax, S_5_INTS
2816
	jnz	.got_it
2817
 
2818
;re-enable ints
2819
	set_io	REG_COMMAND
2820
	mov	ax, SetIntrEnb + S_5_INTS
2821
	out	dx, ax
2822
 
2823
	ret
2824
 
2825
 
2826
 
2827
 
2828
; End of code
2829
align 4 					; Place all initialised data here
2830
 
2831
macro strtbl name, [string]
2832
{
2833
common
2834
	label name dword
2835
forward
2836
	local label
2837
	dd label
2838
forward
2839
	label db string, 0
2840
}
2841
 
2842
VORTEX_DEVICES	     dd 0
2843
BOOMERANG_DEVICES    dd 0
1519 hidnplayr 2844
version 	     dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1472 hidnplayr 2845
my_service	     db '3C59X',0		     ; max 16 chars include zero
2846
 
2847
 
2848
strtbl link_str, \
2849
	"No valid link type detected", \
2850
	"10BASE-T half duplex", \
2851
	"10BASE-T full-duplex", \
2852
	"100BASE-TX half duplex", \
2853
	"100BASE-TX full duplex", \
2854
	"100BASE-T4", \
2855
	"100BASE-FX", \
2856
	"10Mbps AUI", \
2857
	"10Mbps COAX (BNC)", \
2858
	"miiDevice - not supported"
2859
 
2860
strtbl hw_str, \
2861
	"3c590 Vortex 10Mbps", \
2862
	"3c592 EISA 10Mbps Demon/Vortex", \
2863
	"3c597 EISA Fast Demon/Vortex", \
2864
	"3c595 Vortex 100baseTx", \
2865
	"3c595 Vortex 100baseT4", \
2866
	"3c595 Vortex 100base-MII", \
2867
	"3c900 Boomerang 10baseT", \
2868
	"3c900 Boomerang 10Mbps Combo", \
2869
	"3c900 Cyclone 10Mbps TPO", \
2870
	"3c900 Cyclone 10Mbps Combo", \
2871
	"3c900 Cyclone 10Mbps TPC", \
2872
	"3c900B-FL Cyclone 10base-FL", \
2873
	"3c905 Boomerang 100baseTx", \
2874
	"3c905 Boomerang 100baseT4", \
2875
	"3c905B Cyclone 100baseTx", \
2876
	"3c905B Cyclone 10/100/BNC", \
2877
	"3c905B-FX Cyclone 100baseFx", \
2878
	"3c905C Tornado", \
2879
	"3c980 Cyclone", \
2880
	"3c982 Dual Port Server Cyclone", \
2881
	"3cSOHO100-TX Hurricane", \
2882
	"3c555 Laptop Hurricane", \
2883
	"3c556 Laptop Tornado", \
2884
	"3c556B Laptop Hurricane", \
2885
	"3c575 [Megahertz] 10/100 LAN CardBus", \
2886
	"3c575 Boomerang CardBus", \
2887
	"3CCFE575BT Cyclone CardBus", \
2888
	"3CCFE575CT Tornado CardBus", \
2889
	"3CCFE656 Cyclone CardBus", \
2890
	"3CCFEM656B Cyclone+Winmodem CardBus", \
2891
	"3CXFEM656C Tornado+Winmodem CardBus", \
2892
	"3c450 HomePNA Tornado", \
2893
	"3c920 Tornado", \
2894
	"3c982 Hydra Dual Port A", \
2895
	"3c982 Hydra Dual Port B", \
2896
	"3c905B-T4", \
2897
	"3c920B-EMB-WNM Tornado"
2898
 
2899
 
2900
 
2901
align 4
2902
hw_versions:
2903
dw 0x5900, IS_VORTEX
2904
; 3c590 Vortex 10Mbps
2905
dw 0x5920, IS_VORTEX
2906
; 3c592 EISA 10Mbps Demon/Vortex
2907
dw 0x5970, IS_VORTEX
2908
; 3c597 EISA Fast Demon/Vortex
2909
dw 0x5950, IS_VORTEX
2910
; 3c595 Vortex 100baseTx
2911
dw 0x5951, IS_VORTEX
2912
; 3c595 Vortex 100baseT4
2913
dw 0x5952, IS_VORTEX
2914
; 3c595 Vortex 100base-MII
2915
dw 0x9000, IS_BOOMERANG
2916
; 3c900 Boomerang 10baseT
2917
dw 0x9001, IS_BOOMERANG
2918
; 3c900 Boomerang 10Mbps Combo
2919
dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
2920
; 3c900 Cyclone 10Mbps TPO
2921
dw 0x9005, IS_CYCLONE or HAS_HWCKSM
2922
; 3c900 Cyclone 10Mbps Combo
2923
dw 0x9006, IS_CYCLONE or HAS_HWCKSM
2924
; 3c900 Cyclone 10Mbps TPC
2925
dw 0x900A, IS_CYCLONE or HAS_HWCKSM
2926
; 3c900B-FL Cyclone 10base-FL
2927
dw 0x9050, IS_BOOMERANG or HAS_MII
2928
; 3c905 Boomerang 100baseTx
2929
dw 0x9051, IS_BOOMERANG or HAS_MII
2930
; 3c905 Boomerang 100baseT4
2931
dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE
2932
; 3c905B Cyclone 100baseTx
2933
dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
2934
; 3c905B Cyclone 10/100/BNC
2935
dw 0x905A, IS_CYCLONE or HAS_HWCKSM
2936
; 3c905B-FX Cyclone 100baseFx
2937
dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
2938
; 3c905C Tornado
2939
dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
2940
; 3c980 Cyclone
2941
dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
2942
; 3c982 Dual Port Server Cyclone
2943
dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
2944
; 3cSOHO100-TX Hurricane
2945
dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM
2946
; 3c555 Laptop Hurricane
2947
dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM
2948
; 3c556 Laptop Tornado
2949
dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM
2950
; 3c556B Laptop Hurricane
2951
dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT
2952
; 3c575 [Megahertz] 10/100 LAN CardBus
2953
dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT
2954
; 3c575 Boomerang CardBus
2955
dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM
2956
; 3CCFE575BT Cyclone CardBus
2957
dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM
2958
; 3CCFE575CT Tornado CardBus
2959
dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM
2960
; 3CCFE656 Cyclone CardBus
2961
dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM
2962
; 3CCFEM656B Cyclone+Winmodem CardBus
2963
dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM
2964
; 3CXFEM656C Tornado+Winmodem CardBus
2965
dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
2966
; 3c450 HomePNA Tornado
2967
dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
2968
; 3c920 Tornado
2969
dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY
2970
; 3c982 Hydra Dual Port A
2971
dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY
2972
; 3c982 Hydra Dual Port B
2973
dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE
2974
; 3c905B-T4
2975
dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
2976
; 3c920B-EMB-WNM Tornado
2977
HW_VERSIONS_SIZE = $ - hw_versions
2978
 
2979
include_debug_strings				; All data wich FDO uses will be included here
2980
 
2981
section '.data' data readable writable align 16 ; place all uninitialized data place here
2982
 
2983
VORTEX_LIST    rd MAX_DEVICES			; This list contains all pointers to device structures the driver is handling
2984
BOOMERANG_LIST rd MAX_DEVICES
2985
 
2986
 
2987
 
2988