Subversion Repositories Kolibri OS

Rev

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