Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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