Subversion Repositories Kolibri OS

Rev

Rev 1472 | Go to most recent revision | Details | Compare with Previous | 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
1481 hidnplayr 830
; clear packet/byte counters
1472 hidnplayr 831
 
1481 hidnplayr 832
	lea	edi, [device.bytes_tx]
833
	mov	ecx, 6
834
	rep	stosd
835
 
1472 hidnplayr 836
	ret
837
 
838
 
839
 
840
 
841
 
842
align 4
843
start:
844
 
845
	set_io	0
846
	set_io	REG_COMMAND
847
	mov	ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :)
848
	out	dx, ax
849
 
850
	call	check_tx_status
851
 
852
	set_io	0
853
	set_io	REG_COMMAND
854
; switch to register window 4
855
	mov	ax, SELECT_REGISTER_WINDOW+4
856
	out	dx, ax
857
 
858
; wait for linkDetect
859
	set_io	REG_MEDIA_STATUS
860
	mov	ecx, 20 ; wait for max 2s
861
.link_detect_loop:
862
	mov	esi, 10
863
	stdcall Sleep ; 100 ms
864
	in	ax, dx
865
	test	ah, 1000b ; linkDetect
866
	jnz	@f
867
	loop	.link_detect_loop
868
@@:
869
 
870
; print link type
871
	xor	eax, eax
872
	bsr	ax, word [device.mode]
873
	jz	@f
874
	sub	ax, 4
875
@@:
876
	mov	esi, [link_str+eax*4]
877
	DEBUGF 1,"Established Link type: %s\n", esi
878
 
879
 
880
	set_io	0
881
	set_io	REG_COMMAND
882
	mov	ax, SELECT_REGISTER_WINDOW + 1
883
	out	dx, ax
884
 
885
	mov	ax, AckIntr + 0xff
886
	out	dx, ax
887
 
888
	mov	ax, SetStatusEnb + S_5_INTS
889
	out	dx, ax
890
 
891
	mov	ax, SetIntrEnb + S_5_INTS
892
	out	dx, ax
893
 
894
	set_io	0
895
	set_io	REG_COMMAND
896
	mov	ax, SELECT_REGISTER_WINDOW + 1
897
 
898
 
899
	ret
900
 
901
 
902
 
903
 
904
 
905
 
906
 
907
align 4
908
set_rx_mode:
909
 
910
	set_io	0
911
	set_io	REG_COMMAND
912
 
913
	if	defined PROMISCIOUS
914
	mov	ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm
915
	else if  defined ALLMULTI
916
	mov	ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast
917
	else
918
	mov	ax, SetRxFilter + RxStation + RxBroadcast
919
	end if
920
 
921
	out	dx, ax
922
 
923
	ret
924
 
925
 
926
 
927
 
928
 
929
;***************************************************************************
930
;   Function
931
;      global_reset
932
;   Description
933
;      resets the device
934
;   Parameters:
935
;      ebp - io_addr
936
;   Return value:
937
;   Destroyed registers
938
;      ax, ecx, edx, esi
939
;
940
;***************************************************************************1
941
 
942
align 4
943
global_reset:
944
 
945
	DEBUGF 1,"Global reset: "
946
 
947
; GlobalReset
948
	set_io	0
949
	set_io	REG_COMMAND
950
	xor	eax, eax
951
;       or      al, 0x14
952
	out	dx, ax
953
; wait for GlobalReset to complete
954
	mov	ecx, 64000
955
.loop:
956
	in	ax , dx
957
	test	ah , 10000b ; check CmdInProgress
958
;        jz      .finish
959
	loopz	.loop
960
;.finish:
961
;        DEBUGF 1,"Waiting for nic to boot..\n"
962
; wait for 2 seconds for NIC to boot
963
	mov	esi, 200
964
	stdcall Sleep ; 2 seconds
965
 
966
	DEBUGF 1,"Ok!\n"
967
 
968
	ret
969
 
970
 
971
 
972
;***************************************************************************
973
;   Function
974
;      tx_reset
975
;   Description
976
;      resets and enables transmitter engine
977
;
978
;***************************************************************************
979
 
980
align 4
981
tx_reset:
982
	DEBUGF 1,"tx reset\n"
983
 
984
; TxReset
985
	set_io	0
986
	set_io	REG_COMMAND
987
	mov	ax, TxReset
988
	out	dx, ax
989
; Wait for TxReset to complete
990
	mov	ecx, 200000
991
.tx_reset_loop:
992
	in	ax, dx
993
	test	ah, 10000b ; check CmdInProgress
994
	jz	.tx_set_prev
995
	dec	ecx
996
	jnz	.tx_reset_loop
997
.tx_set_prev:
998
; init last_dpd
999
	mov	eax, [device.dpd_buffer]
1000
	add	eax, (NUM_TX_DESC-1)*dpd.size
1001
	mov	[device.prev_dpd], eax
1002
 
1003
	mov	eax, [device.tx_buffer]
1004
	add	eax, (NUM_TX_DESC-1)*MAX_ETH_FRAME_SIZE
1005
	mov	[device.prev_tx_frame], eax
1006
.tx_enable:
1007
	ret
1008
 
1009
 
1010
 
1011
;***************************************************************************
1012
;   Function
1013
;      rx_reset
1014
;   Description
1015
;      resets and enables receiver engine
1016
;
1017
;***************************************************************************
1018
 
1019
align 4
1020
rx_reset:
1021
 
1022
	DEBUGF 1,"rx reset\n"
1023
 
1024
	set_io	0
1025
	set_io	REG_COMMAND
1026
	mov	ax, RxReset or 0x4
1027
	out	dx, ax
1028
; wait for RxReset to complete
1029
	mov	ecx, 200000
1030
.rx_reset_loop:
1031
	in	ax, dx
1032
	test	ah, 10000b ; check CmdInProgress
1033
	dec	ecx
1034
	jnz	.rx_reset_loop
1035
; create upd ring
1036
 
1037
	mov	eax, [device.upd_buffer]
1038
	mov	[device.curr_upd], eax
1039
	call	GetPgAddr
1040
	mov	esi, eax
1041
 
1042
	mov	eax, [device.rx_buffer]
1043
	call	GetPgAddr
1044
	mov	edi, eax
1045
 
1046
	mov	edx, [device.upd_buffer]
1047
	add	edx, (NUM_RX_DESC-1)*upd.size
1048
 
1049
	mov	eax, [device.upd_buffer]
1050
 
1051
	push	ebx
1052
	mov	ebx, [device.rx_buffer]
1053
 
1054
	mov	ecx, NUM_RX_DESC
1055
.upd_loop:
1056
	mov	[edx + upd.next_ptr], esi				; edx = upd buff
1057
 
1058
	and	[eax + upd.pkt_status], 0				; eax = next upd buff
1059
	mov	[eax + upd.frag_addr], edi
1060
	mov	[eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
1061
	mov	[eax + upd.realaddr], ebx
1062
 
1063
	add	edi, MAX_ETH_FRAME_SIZE
1064
	add	ebx, MAX_ETH_FRAME_SIZE
1065
	add	esi, upd.size
1066
	mov	edx, eax
1067
	add	eax, upd.size
1068
 
1069
	dec	ecx
1070
	jnz	.upd_loop
1071
 
1072
	pop	ebx
1073
 
1074
	mov	eax, [device.upd_buffer]
1075
	call	GetPgAddr
1076
	set_io	0
1077
	set_io	REG_UP_LIST_PTR
1078
	out	dx, eax
1079
 
1080
.rx_enable:
1081
	ret
1082
 
1083
 
1084
 
1085
 
1086
;---------------------------------------------------------------------------
1087
;   Function
1088
;      try_link_detect
1089
;   Description
1090
;      try_link_detect checks if link exists
1091
;   Parameters
1092
;      ebx = device structure
1093
;   Return value
1094
;      al - 0 ; no link detected
1095
;      al - 1 ; link detected
1096
;   Destroyed registers
1097
;      eax, ebx, ecx, edx, edi, esi
1098
;
1099
;---------------------------------------------------------------------------
1100
 
1101
align 4
1102
try_link_detect:
1103
 
1104
	DEBUGF 1,"trying to detect link\n"
1105
 
1106
; create self-directed packet
1107
	lea	esi, [device.mac]
1108
	lea	edi, [device.self_directed_packet]
1109
	movsw
1110
	movsd
1111
	sub	esi, 6
1112
	movsw
1113
	movsd
1114
	mov	ax , 0x0608
1115
	stosw
1116
 
1117
; download self-directed packet
1118
	push	20
1119
	lea	eax, [device.self_directed_packet]
1120
	push	eax
1121
	call	[device.transmit]
1122
 
1123
; switch to register window 4
1124
	set_io	0
1125
	set_io	REG_COMMAND
1126
	mov	ax, SELECT_REGISTER_WINDOW+4
1127
	out	dx, ax
1128
 
1129
; See if we have received the packet by now..
1130
	cmp	[device.packets_rx], 0
1131
	jnz	.link_detected
1132
 
1133
; switch to register window 4
1134
	set_io	REG_COMMAND
1135
	mov	ax, SELECT_REGISTER_WINDOW+4
1136
	out	dx, ax
1137
 
1138
; read linkbeatdetect
1139
	set_io	REG_MEDIA_STATUS
1140
	in	ax, dx
1141
	test	ah, 1000b ; test linkBeatDetect
1142
	jnz	.link_detected
1143
	xor	al, al
1144
	jmp	.finish
1145
 
1146
.link_detected:
1147
	setb	al
1148
 
1149
.finish:
1150
	test	al, al
1151
	jz	@f
1152
	or	byte [device.mode+1], 100b
1153
@@:
1154
	ret
1155
 
1156
 
1157
 
1158
;***************************************************************************
1159
;   Function
1160
;      try_phy
1161
;   Description
1162
;      try_phy checks the auto-negotiation function
1163
;      in the PHY at PHY index. It can also be extended to
1164
;      include link detection for non-IEEE 802.3u
1165
;      auto-negotiation devices, for instance the BCM5000.
1166
;   Parameters
1167
;       ah - PHY index
1168
;       ebx - device stucture
1169
;   Return value
1170
;      al - 0 link is auto-negotiated
1171
;      al - 1 no link is auto-negotiated
1172
;   Destroyed registers
1173
;       eax, ebx, ecx, edx, esi
1174
;
1175
;***************************************************************************
1176
 
1177
align 4
1178
try_phy:
1179
 
1180
	DEBUGF 1,"trying phy\n"
1181
 
1182
	mov	al, REG_MII_BMCR
1183
	push	eax
1184
	call	mdio_read	; returns with window #4
1185
	or	ah , 0x80	; software reset
1186
	mov	esi, eax
1187
	mov	eax, dword [esp]
1188
	call	mdio_write	; returns with window #4
1189
 
1190
; wait for reset to complete
1191
	mov	esi, 200
1192
	stdcall Sleep	   ; 2s
1193
	mov	eax, [esp]
1194
	call	mdio_read	; returns with window #4
1195
	test	ah , 0x80
1196
	jnz	.fail_finish
1197
	mov	eax, [esp]
1198
 
1199
; wait for a while after reset
1200
	mov	esi, 2
1201
	stdcall Sleep	   ; 20ms
1202
	mov	eax, [esp]
1203
	mov	al , REG_MII_BMSR
1204
	call	mdio_read	; returns with window #4
1205
	test	al , 1		 ; extended capability supported?
1206
	jz	.no_ext_cap
1207
 
1208
; auto-neg capable?
1209
	test	al , 1000b
1210
	jz	.fail_finish	; not auto-negotiation capable
1211
 
1212
; auto-neg complete?
1213
	test	al , 100000b
1214
	jnz	.auto_neg_ok
1215
 
1216
; restart auto-negotiation
1217
	mov	eax, [esp]
1218
	mov	al , REG_MII_ANAR
1219
	push	eax
1220
	call	mdio_read	; returns with window #4
1221
	or	ax , 1111b shl 5; advertise only 10base-T and 100base-TX
1222
	mov	esi, eax
1223
	pop	eax
1224
	call	mdio_write	; returns with window #4
1225
	mov	eax, [esp]
1226
	call	mdio_read	; returns with window #4
1227
	mov	esi, eax
1228
	or	bh , 10010b	; restart auto-negotiation
1229
	mov	eax, [esp]
1230
	call	mdio_write	; returns with window #4
1231
	mov	esi, 400
1232
	stdcall Sleep  ; 4 seconds
1233
	mov	eax, [esp]
1234
	mov	al , REG_MII_BMSR
1235
	call	mdio_read ; returns with window #4
1236
	test	al , 100000b ; auto-neg complete?
1237
	jnz	.auto_neg_ok
1238
	jmp	.fail_finish
1239
.auto_neg_ok:
1240
 
1241
; compare advertisement and link partner ability registers
1242
	mov	eax, [esp]
1243
	mov	al , REG_MII_ANAR
1244
	call	mdio_read	; returns with window #4
1245
	xchg	eax, [esp]
1246
	mov	al , REG_MII_ANLPAR
1247
	call	mdio_read	; returns with window #4
1248
	pop	esi
1249
	and	eax, esi
1250
	and	eax, 1111100000b
1251
	push	eax
1252
 
1253
	mov	word[device.mode+2], ax
1254
 
1255
; switch to register window 3
1256
	set_io	0
1257
	set_io	REG_COMMAND
1258
	mov	ax , SELECT_REGISTER_WINDOW+3
1259
	out	dx , ax
1260
 
1261
; set full-duplex mode
1262
	set_io	REG_MAC_CONTROL
1263
	in	ax , dx
1264
	and	ax , not 0x120	; clear full duplex and flow control
1265
	pop	esi
1266
	test	esi, 1010b shl 5; check for full-duplex
1267
	jz	.half_duplex
1268
	or	ax , 0x120	; set full duplex and flow control
1269
.half_duplex:
1270
	out	dx , ax
1271
	mov	al , 1
1272
	ret
1273
.no_ext_cap:
1274
 
1275
; not yet implemented BCM5000
1276
.fail_finish:
1277
	pop	eax
1278
	xor	al, al
1279
	ret
1280
 
1281
 
1282
 
1283
;***************************************************************************
1284
;   Function
1285
;      try_mii
1286
;   Description
1287
;      try_MII checks the on-chip auto-negotiation logic
1288
;      or an off-chip MII PHY, depending upon what is set in
1289
;      xcvrSelect by the caller.
1290
;      It exits when it finds the first device with a good link.
1291
;   Parameters
1292
;      ebp - io_addr
1293
;   Return value
1294
;      al - 0
1295
;      al - 1
1296
;   Destroyed registers
1297
;      eax, ebx, ecx, edx, esi
1298
;
1299
;***************************************************************************
1300
 
1301
align 4
1302
try_mii:
1303
 
1304
	DEBUGF 1,"trying mii\n"
1305
 
1306
; switch to register window 3
1307
	set_io	0
1308
	set_io	REG_COMMAND
1309
	mov	ax, SELECT_REGISTER_WINDOW+3
1310
	out	dx, ax
1311
	set_io	REG_INTERNAL_CONFIG
1312
	in	eax, dx
1313
	and	eax, (1111b shl 20)
1314
	cmp	eax, (1000b shl 20) ; is auto-negotiation set?
1315
	jne	.mii_device
1316
; auto-negotiation is set
1317
; switch to register window 4
1318
	set_io	REG_COMMAND
1319
	mov	ax , SELECT_REGISTER_WINDOW+4
1320
	out	dx , ax
1321
; PHY==24 is the on-chip auto-negotiation logic
1322
; it supports only 10base-T and 100base-TX
1323
	mov	ah , 24
1324
	call	try_phy
1325
	test	al , al
1326
	jz	.fail_finish
1327
	mov	cl , 24
1328
	jmp	.check_preamble
1329
.mii_device:
1330
	cmp	eax, (0110b shl 20)
1331
	jne	.fail_finish
1332
	set_io	0
1333
	set_io	REG_COMMAND
1334
	mov	ax , SELECT_REGISTER_WINDOW+4
1335
	out	dx , ax
1336
	set_io	REG_PHYSICAL_MGMT
1337
	in	ax , dx
1338
	and	al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA)
1339
	cmp	al , (1 shl BIT_MGMT_DATA)
1340
	je	.search_for_phy
1341
	xor	al , al
1342
	ret
1343
.search_for_phy:
1344
; search for PHY
1345
	mov	cx , 31
1346
.search_phy_loop:
1347
	cmp	cx , 24
1348
	je	.next_phy
1349
	mov	ah , cl ; ah = phy
1350
	mov	al , REG_MII_BMCR ; al = Basic Mode Status Register
1351
	push	cx
1352
	call	mdio_read
1353
	pop	cx
1354
	test	ax , ax
1355
	jz	.next_phy
1356
	cmp	ax , 0xffff
1357
	je	.next_phy
1358
	mov	ah , cl ; ah = phy
1359
	push	cx
1360
	call	try_phy
1361
	pop	cx
1362
	test	al , al
1363
	jnz	.check_preamble
1364
.next_phy:
1365
	loopw	.search_phy_loop
1366
.fail_finish:
1367
	xor	al, al
1368
	ret
1369
; epilog
1370
.check_preamble:
1371
	push	eax ; eax contains the return value of try_phy
1372
; check hard coded preamble forcing
1373
	movzx	eax, [device.ver_id]
1374
	test	word [eax*4+hw_versions+2], EXTRA_PREAMBLE
1375
	setnz	[device.preamble] ; force preamble
1376
	jnz	.finish
1377
; check mii for preamble suppression
1378
	mov	ah, cl
1379
	mov	al, REG_MII_BMSR
1380
	call	mdio_read
1381
	test	al, 1000000b ; preamble suppression?
1382
	setz	[device.preamble] ; no
1383
.finish:
1384
	pop	eax
1385
	ret
1386
 
1387
 
1388
 
1389
;***************************************************************************
1390
;   Function
1391
;      test_packet
1392
;   Description
1393
;      try_loopback try a loopback packet for 10BASE2 or AUI port
1394
;   Parameters
1395
;      ebx = device structure
1396
;
1397
;***************************************************************************
1398
 
1399
align 4
1400
test_packet:
1401
 
1402
	DEBUGF 1,"sending test packet\n"
1403
 
1404
; switch to register window 3
1405
	set_io	0
1406
	set_io	REG_COMMAND
1407
	mov	ax, SELECT_REGISTER_WINDOW+3
1408
	out	dx, ax
1409
 
1410
; set fullDuplexEnable in MacControl register
1411
	set_io	REG_MAC_CONTROL
1412
	in	ax, dx
1413
	or	ax, 0x120
1414
	out	dx, ax
1415
 
1416
; switch to register window 5
1417
	set_io	REG_COMMAND
1418
	mov	ax, SELECT_REGISTER_WINDOW+5
1419
	out	dx, ax
1420
 
1421
; set RxFilter to enable individual address matches
1422
	mov	ax, (10000b shl 11)
1423
	set_io	REG_RX_FILTER
1424
	in	al, dx
1425
	or	al, 1
1426
	set_io	REG_COMMAND
1427
	out	dx, ax
1428
 
1429
; issue RxEnable and TxEnable
1430
	call	rx_reset
1431
	call	tx_reset
1432
 
1433
; download a self-directed test packet
1434
	lea	esi, [device.mac]
1435
	lea	edi, [device.self_directed_packet]
1436
	movsw
1437
	movsd
1438
	sub	esi, 6
1439
	movsw
1440
	movsd
1441
	mov	ax , 0x0608
1442
	stosw
1443
 
1444
	push	20
1445
	lea	eax, [device.self_directed_packet]
1446
	push	eax
1447
	call	[device.transmit]
1448
 
1449
; wait for 2s
1450
	mov	esi, 200
1451
	stdcall Sleep	 ; 2s
1452
 
1453
; check if self-directed packet is received
1454
	mov	eax, [device.packets_rx]
1455
	test	eax, eax
1456
	jnz	.finish
1457
 
1458
; switch to register window 3
1459
	set_io	0
1460
	set_io	REG_COMMAND
1461
	mov	ax, SELECT_REGISTER_WINDOW+3
1462
	out	dx, ax
1463
 
1464
; clear fullDuplexEnable in MacControl register
1465
	set_io	REG_MAC_CONTROL
1466
	in	ax , dx
1467
	and	ax , not 0x120
1468
	out	dx , ax
1469
	xor	eax, eax
1470
 
1471
.finish:
1472
	ret
1473
 
1474
 
1475
 
1476
;***************************************************************************
1477
;   Function
1478
;      try_loopback
1479
;   Description
1480
;      tries a loopback packet for 10BASE2 or AUI port
1481
;   Parameters
1482
;      al -  0: 10Mbps AUI connector
1483
;            1: 10BASE-2
1484
;      ebp - io_addr
1485
;   Return value
1486
;      al - 0
1487
;      al - 1
1488
;   Destroyed registers
1489
;      eax, ebx, ecx, edx, edi, esi
1490
;
1491
;***************************************************************************
1492
 
1493
align 4
1494
try_loopback:
1495
 
1496
	DEBUGF 1,"trying loopback\n"
1497
 
1498
	push	eax
1499
; switch to register window 3
1500
	set_io	0
1501
	set_io	REG_COMMAND
1502
	mov	ax, SELECT_REGISTER_WINDOW+3
1503
	out	dx, ax
1504
	mov	eax, [esp]
1505
 
1506
	mov	cl, al
1507
	inc	cl
1508
	shl	cl, 3
1509
	or	byte [device.mode+1], cl
1510
 
1511
	test	al, al ; aui or coax?
1512
	jz	.complete_loopback
1513
; enable 100BASE-2 DC-DC converter
1514
	mov	ax, (10b shl 11) ; EnableDcConverter
1515
	out	dx, ax
1516
.complete_loopback:
1517
	mov	cx, 2 ; give a port 3 chances to complete a loopback
1518
.next_try:
1519
	push	ecx
1520
	call	test_packet
1521
	pop	ecx
1522
	test	eax, eax
1523
	loopzw	.next_try
1524
.finish:
1525
	xchg	eax, [esp]
1526
	test	al, al
1527
	jz	.aui_finish
1528
; issue DisableDcConverter command
1529
	set_io	0
1530
	set_io	REG_COMMAND
1531
	mov	ax, (10111b shl 11)
1532
	out	dx, ax
1533
.aui_finish:
1534
	pop	eax ; al contains the result of operation
1535
 
1536
	test	al, al
1537
	jnz	@f
1538
	and	byte [device.mode+1], not 11000b
1539
@@:
1540
 
1541
	ret
1542
 
1543
 
1544
;***************************************************************************
1545
;   Function
1546
;      set_active_port
1547
;   Description
1548
;      It selects the media port (transceiver) to be used
1549
;   Return value:
1550
;   Destroyed registers
1551
;      eax, ebx, ecx, edx, edi, esi
1552
;
1553
;***************************************************************************
1554
 
1555
align 4
1556
set_active_port:
1557
 
1558
	DEBUGF 1,"Setting active port: "
1559
 
1560
; switch to register window 3
1561
	set_io	0
1562
	set_io	REG_COMMAND
1563
	mov	ax, SELECT_REGISTER_WINDOW+3
1564
	out	dx, ax
1565
	set_io	REG_INTERNAL_CONFIG
1566
	in	eax, dx
1567
	test	eax, (1 shl 24) ; check if autoselect enable
1568
	jz	.set_first_available_media
1569
 
1570
; check 100BASE-TX and 10BASE-T
1571
	set_io	REG_MEDIA_OPTIONS
1572
	in	ax, dx
1573
	test	al, 1010b	; check whether 100BASE-TX or 10BASE-T available
1574
	jz	.mii_device	; they are not available
1575
 
1576
; set auto-negotiation
1577
	set_io	REG_INTERNAL_CONFIG
1578
	in	eax, dx
1579
	and	eax, not (1111b shl 20)
1580
	or	eax, (1000b shl 20)
1581
	out	dx, eax
1582
	call	try_mii
1583
	test	al, al
1584
	jz	.mii_device
1585
	DEBUGF 1,"Using auto negotiation\n"
1586
	ret
1587
.mii_device:
1588
 
1589
; switch to register window 3
1590
	set_io	0
1591
	set_io	REG_COMMAND
1592
	mov	ax, SELECT_REGISTER_WINDOW+3
1593
	out	dx, ax
1594
 
1595
; check for off-chip mii device
1596
	set_io	REG_MEDIA_OPTIONS
1597
	in	ax, dx
1598
	test	al, 1000000b ; check miiDevice
1599
	jz	.base_fx
1600
	set_io	REG_INTERNAL_CONFIG
1601
	in	eax, dx
1602
	and	eax, not (1111b shl 20)
1603
	or	eax, (0110b shl 20) ; set MIIDevice
1604
	out	dx, eax
1605
	call	try_mii
1606
	test	al, al
1607
	jz	.base_fx
1608
	DEBUGF 1,"Using off-chip mii device\n"
1609
	ret
1610
.base_fx:
1611
 
1612
; switch to register window 3
1613
	set_io	0
1614
	set_io	REG_COMMAND
1615
	mov	ax, SELECT_REGISTER_WINDOW+3
1616
	out	dx, ax
1617
; check for 100BASE-FX
1618
	set_io	REG_MEDIA_OPTIONS
1619
	in	ax, dx ; read media option register
1620
	test	al, 100b ; check 100BASE-FX
1621
	jz	.aui_enable
1622
	set_io	REG_INTERNAL_CONFIG
1623
	in	eax, dx
1624
	and	eax, not (1111b shl 20)
1625
	or	eax, (0101b shl 20) ; set 100base-FX
1626
	out	dx, eax
1627
	call	try_link_detect
1628
	test	al, al
1629
	jz	.aui_enable
1630
	DEBUGF 1,"Using 100Base-FX\n"
1631
	ret
1632
.aui_enable:
1633
 
1634
; switch to register window 3
1635
	set_io	0
1636
	set_io	REG_COMMAND
1637
	mov	ax, SELECT_REGISTER_WINDOW+3
1638
	out	dx, ax
1639
; check for 10Mbps AUI connector
1640
	set_io	REG_MEDIA_OPTIONS
1641
	in	ax, dx ; read media option register
1642
	test	al, 100000b ; check 10Mbps AUI connector
1643
	jz	.coax_available
1644
	set_io	REG_INTERNAL_CONFIG
1645
	in	eax, dx
1646
	and	eax, not (1111b shl 20)
1647
	or	eax, (0001b shl 20) ; set 10Mbps AUI connector
1648
	out	dx, eax
1649
	xor	al, al ; try 10Mbps AUI connector
1650
	call	try_loopback
1651
	test	al, al
1652
	jz	.coax_available
1653
	DEBUGF 1,"Using 10Mbps aui\n"
1654
	ret
1655
.coax_available:
1656
 
1657
; switch to register window 3
1658
	set_io	0
1659
	set_io	REG_COMMAND
1660
	mov	ax, SELECT_REGISTER_WINDOW+3
1661
	out	dx, ax
1662
; check for coaxial 10BASE-2 port
1663
	set_io	REG_MEDIA_OPTIONS
1664
	in	ax, dx ; read media option register
1665
	test	al, 10000b ; check 10BASE-2
1666
	jz	.set_first_available_media
1667
	set_io	REG_INTERNAL_CONFIG
1668
	in	eax, dx
1669
	and	eax, not (1111b shl 20)
1670
	or	eax, (0011b shl 20) ; set 10BASE-2
1671
	out	dx, eax
1672
	mov	al, 1
1673
	call	try_loopback
1674
	test	al, al
1675
	jz	.set_first_available_media
1676
	DEBUGF 1,"Using 10BASE-2 port\n"
1677
	ret
1678
.set_first_available_media:
1679
 
1680
 
1681
;***************************************************************************
1682
;   Function
1683
;      set_available_media
1684
;   Description
1685
;      sets the first available media
1686
;   Parameters
1687
;      ebp - io_addr
1688
;   Return value
1689
;      al - 0
1690
;      al - 1
1691
;   Destroyed registers
1692
;      eax, edx
1693
;
1694
;***************************************************************************
1695
 
1696
align 4
1697
set_available_media:
1698
 
1699
	DEBUGF 1,"Using the first available media\n"
1700
 
1701
; switch to register window 3
1702
	set_io	0
1703
	set_io	REG_COMMAND
1704
	mov	ax, SELECT_REGISTER_WINDOW+3
1705
	out	dx, ax
1706
	set_io	REG_INTERNAL_CONFIG
1707
	in	eax, dx
1708
	push	eax
1709
	set_io	REG_MEDIA_OPTIONS
1710
	in	ax, dx
1711
	test	al, 10b
1712
	jz	@f
1713
; baseTXAvailable
1714
	pop	eax
1715
	and	eax, not (1111b shl 20)
1716
	or	eax, (100b shl 20)
1717
if defined FORCE_FD
1718
	mov	word [device.mode], (1 shl 8)
1719
else
1720
	mov	word [device.mode], (1 shl 7)
1721
end if
1722
	jmp	.set_media
1723
@@:
1724
	test	al, 100b
1725
	jz	@f
1726
; baseFXAvailable
1727
	pop	eax
1728
	and	eax, not (1111b shl 20)
1729
	or	eax, (101b shl 20)
1730
 
1731
	mov	word [device.mode], (1 shl 10)
1732
 
1733
	jmp	.set_media
1734
@@:
1735
	test	al, 1000000b
1736
	jz	@f
1737
; miiDevice
1738
	pop	eax
1739
	and	eax, not (1111b shl 20)
1740
	or	eax, (0110b shl 20)
1741
 
1742
	mov	word [device.mode], (1 shl 13)
1743
 
1744
	jmp	.set_media
1745
@@:
1746
	test	al, 1000b
1747
	jz	@f
1748
.set_default:
1749
; 10bTAvailable
1750
	pop	eax
1751
	and	eax, not (1111b shl 20)
1752
if FORCE_FD
1753
	mov	word [device.mode], (1 shl 6)
1754
else
1755
	mov	word [device.mode], (1 shl 5)
1756
end if ; FORCE_FD
1757
	jmp	.set_media
1758
@@:
1759
	test	al, 10000b
1760
	jz	@f
1761
; coaxAvailable
1762
	set_io	REG_COMMAND
1763
	mov	ax, (10b shl 11) ; EnableDcConverter
1764
	out	dx, ax
1765
	pop	eax
1766
	and	eax, not (1111b shl 20)
1767
	or	eax, (11b shl 20)
1768
 
1769
	mov	word [device.mode], (1 shl 12)
1770
 
1771
	jmp	.set_media
1772
@@:
1773
	test	al, 10000b
1774
	jz	.set_default
1775
; auiAvailable
1776
	pop	eax
1777
	and	eax, not (1111b shl 20)
1778
	or	eax, (1 shl 20)
1779
 
1780
	mov	word [device.mode], (1 shl 11)
1781
 
1782
.set_media:
1783
	set_io	REG_INTERNAL_CONFIG
1784
	out	dx, eax
1785
if FORCE_FD
1786
; set fullDuplexEnable in MacControl register
1787
	set_io	REG_MAC_CONTROL
1788
	in	ax, dx
1789
	or	ax, 0x120
1790
	out	dx, ax
1791
end if ; FORCE_FD
1792
	mov	al, 1
1793
 
1794
	ret
1795
 
1796
 
1797
 
1798
;***************************************************************************
1799
;   Function
1800
;      wake_up
1801
;   Description
1802
;      set the power state to D0
1803
;
1804
;***************************************************************************
1805
 
1806
align 4
1807
wake_up:
1808
 
1809
	DEBUGF 1,"Waking up NIC: "
1810
 
1811
; wake up - we directly do it by programming PCI
1812
; check if the device is power management capable
1813
	movzx	ecx, [device.pci_bus]
1814
	movzx	edx, [device.pci_dev]
1815
	stdcall PciRead32, ecx, edx, PCI_REG_STATUS
1816
 
1817
	test	al, 10000b	; is there "new capabilities" linked list?
1818
	jz	.device_awake
1819
 
1820
	DEBUGF 1,"1 "
1821
 
1822
; search for power management register
1823
	stdcall PciRead16, ecx, edx, PCI_REG_CAP_PTR
1824
	cmp	al, 0x3f
1825
	jbe	.device_awake
1826
 
1827
	DEBUGF 1,"2 "
1828
 
1829
; traverse the list
1830
	movzx	esi, al
1831
.pm_loop:
1832
	stdcall PciRead32, ecx, edx, esi
1833
 
1834
	cmp	al , 1
1835
	je	.set_pm_state
1836
 
1837
	movzx	esi, ah
1838
 
1839
	test	ah , ah
1840
	jnz	.pm_loop
1841
	jmp	.device_awake
1842
 
1843
; waku up the device if necessary
1844
.set_pm_state:
1845
 
1846
	DEBUGF 1,"3 "
1847
 
1848
	add	esi, PCI_REG_PM_CTRL
1849
	stdcall PciRead32, ecx, edx, esi
1850
	test	al, 3
1851
	jz	.device_awake
1852
	and	al, not 11b ; set state to D0
1853
	stdcall PciWrite32, ecx, edx, esi, eax
1854
.device_awake:
1855
 
1856
	DEBUGF 1,"Device is awake\n"
1857
 
1858
	ret
1859
 
1860
 
1861
 
1862
 
1863
;***************************************************************************
1864
;   Function
1865
;      write_eeprom
1866
;   Description
1867
;      reads eeprom
1868
;      Note : the caller must switch to the register window 0
1869
;             before calling this function
1870
;   Parameters:
1871
;      ax - register to be read (only the first 63 words can be read)
1872
;      cx - value to be read into the register
1873
;   Return value:
1874
;      ax - word read
1875
;   Destroyed registers
1876
;      ax, ebx, edx
1877
;
1878
;***************************************************************************
1879
;       align 4
1880
;write_eeprom:
1881
;       mov     edx, [io_addr]
1882
;       add     edx, REG_EEPROM_COMMAND
1883
;       cmp     ah, 11b
1884
;       ja      .finish ; address may have a value of maximal 1023
1885
;       shl     ax, 2
1886
;       shr     al, 2
1887
;       push    eax
1888
;; wait for busy
1889
;       mov     ebx, 0xffff
1890
;@@:
1891
;       in      ax, dx
1892
;       test    ah, 0x80
1893
;       jz      .write_enable
1894
;       dec     ebx
1895
;       jns     @r
1896
;; write enable
1897
;.write_enable:
1898
;       xor     eax, eax
1899
;       mov     eax, (11b shl 4)
1900
;       out     dx, ax
1901
;; wait for busy
1902
;       mov     ebx, 0xffff
1903
;@@:
1904
;       in      ax, dx
1905
;       test    ah, 0x80
1906
;       jz      .erase_loop
1907
;       dec     ebx
1908
;       jns     @r
1909
;.erase_loop:
1910
;       pop     eax
1911
;       push    eax
1912
;       or      ax, (11b shl 6) ; erase register
1913
;       out     dx, ax
1914
;       mov     ebx, 0xffff
1915
;@@:
1916
;       in      ax, dx
1917
;       test    ah, 0x80
1918
;       jz      .write_reg
1919
;       dec     ebx
1920
;       jns     @r
1921
;.write_reg:
1922
;       add     edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND
1923
;       mov     eax, ecx
1924
;       out     dx, ax
1925
;; write enable
1926
;       add     edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA
1927
;       xor     eax, eax
1928
;       mov     eax, (11b shl 4)
1929
;       out     dx, ax
1930
; wait for busy
1931
;       mov     ebx, 0xffff
1932
;@@:
1933
;       in      ax, dx
1934
;       test    ah, 0x80
1935
;       jz      .issue_write_reg
1936
;       dec     ebx
1937
;       jns     @r
1938
;.issue_write_reg:
1939
;       pop     eax
1940
;       or      ax, 01b shl 6
1941
;       out     dx, ax
1942
;.finish:
1943
;       ret
1944
;***************************************************************************
1945
;   Function
1946
;      read_eeprom
1947
;   Description
1948
;      reads eeprom
1949
;   Parameters:
1950
;       ax - register to be read (only the first 63 words can be read)
1951
;      ebx = driver structure
1952
;   Return value:
1953
;      ax - word read
1954
;   Destroyed registers
1955
;      ax, ebx, edx, ebp
1956
;
1957
;***************************************************************************
1958
 
1959
align 4
1960
read_eeprom:
1961
 
1962
	DEBUGF 1,"Reading from eeprom:\n"
1963
 
1964
	push	eax
1965
; switch to register window 0
1966
	set_io	0
1967
	set_io	REG_COMMAND
1968
	mov	ax, SELECT_REGISTER_WINDOW+0
1969
	out	dx, ax
1970
	pop	eax
1971
	and	ax, 111111b ; take only the first 6 bits into account
1972
	movzx	esi, [device.ver_id]
1973
 
1974
	test	word [esi*4+hw_versions+2], EEPROM_8BIT
1975
	jz	@f
1976
	add	ax, 0x230 ; hardware constant
1977
	jmp	.read
1978
@@:
1979
 
1980
	add	ax, EEPROM_CMD_READ
1981
	test	word [esi*4+hw_versions+2], EEPROM_OFFSET
1982
	jz	.read
1983
	add	ax, 0x30
1984
.read:
1985
 
1986
	set_io	REG_EEPROM_COMMAND
1987
	out	dx, ax
1988
	mov	ecx, 0xffff ; duration of about 162 us ;-)
1989
.wait_for_reading:
1990
	in	ax, dx
1991
	test	ah, 0x80 ; check bit eepromBusy
1992
	jz	.read_data
1993
	loop	.wait_for_reading
1994
.read_data:
1995
	set_io	REG_EEPROM_DATA
1996
	in	ax, dx
1997
 
1998
	DEBUGF 1,"ok!\n"
1999
 
2000
	ret
2001
 
2002
;***************************************************************************
2003
;   Function
2004
;      mdio_sync
2005
;   Description
2006
;      initial synchronization
2007
;   Parameters
2008
;      ebp - io_addr
2009
;   Return value
2010
;   Destroyed registers
2011
;      ax, edx, cl
2012
;
2013
;***************************************************************************
2014
 
2015
align 4
2016
mdio_sync:
2017
 
2018
	DEBUGF 1,"syncing mdio\n"
2019
 
2020
; switch to register window 4
2021
	set_io	0
2022
	set_io	REG_COMMAND
2023
	mov	ax, SELECT_REGISTER_WINDOW+4
2024
	out	dx, ax
2025
	cmp	[device.preamble], 0
2026
	je	.no_preamble
2027
; send 32 logic ones
2028
	set_io	REG_PHYSICAL_MGMT
2029
	mov	ecx, 31
2030
.loop:
2031
	mov	ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR)
2032
	out	dx, ax
2033
	in	ax, dx ; delay
2034
	mov	ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK)
2035
	out	dx, ax
2036
	in	ax, dx ; delay
2037
	loop	.loop
2038
.no_preamble:
2039
 
2040
	ret
2041
 
2042
;***************************************************************************
2043
;   Function
2044
;      mdio_read
2045
;   Description
2046
;      read MII register
2047
;      see page 16 in D83840A.pdf
2048
;   Parameters
2049
;       ah - PHY addr
2050
;       al - register addr
2051
;      ebx = device structure
2052
;   Return value
2053
;      ax - register read
2054
;
2055
;***************************************************************************
2056
 
2057
align 4
2058
mdio_read:
2059
 
2060
	DEBUGF 1,"reading MII registers\n"
2061
 
2062
	push	eax
2063
	call	mdio_sync ; returns with window #4
2064
	pop	eax
2065
	set_io	0
2066
	set_io	REG_PHYSICAL_MGMT
2067
	shl	al, 3
2068
	shr	ax, 3
2069
	and	ax, not MII_CMD_MASK
2070
	or	ax, MII_CMD_READ
2071
 
2072
	mov	esi, eax
2073
	mov	ecx, 13
2074
.cmd_loop:
2075
	mov	ax, (1 shl BIT_MGMT_DIR) ; write mii
2076
	bt	esi, ecx
2077
	jnc	.zero_bit
2078
	or	al, (1 shl BIT_MGMT_DATA)
2079
 
2080
.zero_bit:
2081
	out	dx, ax
2082
	push	ax
2083
	in	ax, dx ; delay
2084
	pop	ax
2085
	or	al, (1 shl BIT_MGMT_CLK) ; write
2086
	out	dx, ax
2087
	in	ax, dx ; delay
2088
	loop	.cmd_loop
2089
 
2090
; read data (18 bits with the two transition bits)
2091
	mov	ecx, 17
2092
	xor	esi, esi
2093
.read_loop:
2094
	shl	esi, 1
2095
	xor	eax, eax ; read comand
2096
	out	dx, ax
2097
	in	ax, dx ; delay
2098
	in	ax, dx
2099
	test	al, (1 shl BIT_MGMT_DATA)
2100
	jz	.dont_set
2101
	inc	esi
2102
.dont_set:
2103
	mov	ax, (1 shl BIT_MGMT_CLK)
2104
	out	dx, ax
2105
	in	ax, dx ; delay
2106
	loop	.read_loop
2107
	mov	eax, esi
2108
 
2109
	ret
2110
 
2111
 
2112
 
2113
;***************************************************************************
2114
;   Function
2115
;      mdio_write
2116
;   Description
2117
;      write MII register
2118
;      see page 16 in D83840A.pdf
2119
;   Parameters
2120
;       ah - PHY addr
2121
;       al - register addr
2122
;       si - word to be written
2123
;   Return value
2124
;      ax - register read
2125
;
2126
;***************************************************************************
2127
 
2128
align 4
2129
mdio_write:
2130
 
2131
	DEBUGF 1,"Writing MII registers\n"
2132
 
2133
	push	eax
2134
	call	mdio_sync
2135
	pop	eax
2136
	set_io	0
2137
	set_io	REG_PHYSICAL_MGMT
2138
	shl	al, 3
2139
	shr	ax, 3
2140
	and	ax, not MII_CMD_MASK
2141
	or	ax, MII_CMD_WRITE
2142
	shl	eax, 2
2143
	or	eax, 10b ; transition bits
2144
	shl	eax, 16
2145
	mov	ax, si
2146
	mov	esi, eax
2147
	mov	ecx, 31
2148
.cmd_loop:
2149
	mov	ax, (1 shl BIT_MGMT_DIR) ; write mii
2150
	bt	esi, ecx
2151
	jnc	.zero_bit
2152
	or	al, (1 shl BIT_MGMT_DATA)
2153
.zero_bit:
2154
	out	dx, ax
2155
	push	eax
2156
	in	ax, dx ; delay
2157
	pop	eax
2158
	or	al, (1 shl BIT_MGMT_CLK) ; write
2159
	out	dx, ax
2160
	in	ax, dx ; delay
2161
	loop	.cmd_loop
2162
 
2163
	ret
2164
 
2165
 
2166
;***************************************************************************
2167
;   Function
2168
;      check_tx_status
2169
;   Description
2170
;      Checks TxStatus queue.
2171
;   Return value
2172
;      al - 0 no error was found
2173
;      al - 1 error was found TxReset is needed
2174
;   Destroyed registers
2175
;      eax, ecx, edx, ebp
2176
;
2177
;***************************************************************************
2178
 
2179
align 4
2180
check_tx_status:
2181
 
2182
	DEBUGF 1,"Checking TX status\n"
2183
 
2184
; clear TxStatus queue
2185
	set_io	0
2186
	set_io	REG_TX_STATUS
2187
	mov	ecx, 31 ; max number of queue entries
2188
.tx_status_loop:
2189
	in	al, dx
2190
	test	al, al
2191
	jz	.finish ; no error
2192
	test	al, 0x3f
2193
	jnz	.finish ; error
2194
.no_error_found:
2195
; clear current TxStatus entry which advances the next one
2196
	xor	al, al
2197
	out	dx, al
2198
	loop	.tx_status_loop
2199
.finish:
2200
 
2201
	ret
2202
 
2203
 
2204
 
2205
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2206
;;                                         ;;
2207
;; Transmit (vortex)                       ;;
2208
;;                                         ;;
2209
;; In: buffer pointer in [esp+4]           ;;
2210
;;     size of buffer in [esp+8]           ;;
2211
;;     pointer to device structure in ebx  ;;
2212
;;                                         ;;
2213
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2214
 
2215
align 4
2216
vortex_transmit:
2217
 
2218
	DEBUGF 1,"Sending packet (vortex)\n"
2219
 
2220
	cmp	dword [esp+8], MAX_ETH_FRAME_SIZE
2221
	ja	.finish ; packet is too long
2222
 
2223
	call	check_tx_status
2224
	test	al, al
2225
	jnz	tx_reset
2226
 
2227
; switch to register window 7
2228
	set_io	0
2229
	set_io	REG_COMMAND
2230
	mov	ax, SELECT_REGISTER_WINDOW+7
2231
	out	dx, ax
2232
; check for master operation in progress
2233
	set_io	REG_MASTER_STATUS
2234
	in	ax, dx
2235
	test	ah, 0x80
2236
	jnz	.finish ; no DMA for sending
2237
; program frame address to be sent
2238
	set_io	REG_MASTER_ADDRESS
2239
	mov	eax, [esp+4]
2240
	call	GetPgAddr
2241
	out	dx, eax
2242
; program frame length
2243
	set_io	REG_MASTER_LEN
2244
	mov	eax, [esp+8]
2245
;;;        and     eax, not 3
2246
	out	dx, ax
2247
; start DMA Down
2248
	set_io	REG_COMMAND
2249
	mov	ax, (10100b shl 11) + 1 ; StartDMADown
2250
	out	dx, ax
2251
.finish:
2252
	ret
2253
 
2254
 
2255
 
2256
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2257
;;                                         ;;
2258
;; Transmit (boomerang)                    ;;
2259
;;                                         ;;
2260
;; In: buffer pointer in [esp+4]           ;;
2261
;;     size of buffer in [esp+8]           ;;
2262
;;     pointer to device structure in ebx  ;;
2263
;;                                         ;;
2264
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2265
 
2266
align 4
2267
boomerang_transmit:
2268
 
2269
	DEBUGF	1,"Sending packet (boomerang)\n"
2270
 
2271
	cmp	dword [esp+8], MAX_ETH_FRAME_SIZE
2272
	ja	.finish ; packet is too long
2273
 
2274
	call	check_tx_status
2275
	test	al, al
2276
	jnz	tx_reset
2277
 
2278
; calculate descriptor address
2279
	mov	eax, [device.prev_dpd]
2280
	DEBUGF	1,"Previous DPD: %x\n", eax
2281
	add	eax, dpd.size
2282
	mov	ecx, [device.dpd_buffer]
2283
	add	ecx, NUM_TX_DESC*dpd.size
2284
	cmp	eax, ecx
2285
	cmovae	eax, [device.dpd_buffer]	; Wrap if needed
2286
 
2287
	DEBUGF	1,"Found a free DPD: %x\n", eax
2288
	push	eax
2289
; check DnListPtr
2290
	set_io	0
2291
	set_io	REG_DN_LIST_PTR
2292
	in	eax, dx
2293
; mark if Dn_List_Ptr is cleared
2294
	test	eax, eax
2295
	setz	[device.dn_list_ptr_cleared]
2296
; finish if no more free descriptor is available - FIXME!
2297
	cmp	eax, [esp]
2298
	pop	eax
2299
	jz	.finish
2300
 
2301
 
2302
	push	eax		;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2303
; calculate tx_buffer address
2304
	mov	edi, [device.prev_tx_frame]
2305
	DEBUGF	1,"Previous TX frame:: %x\n", edi
2306
	add	edi, MAX_ETH_FRAME_SIZE
2307
 
2308
	mov	ecx, [device.tx_buffer]
2309
	add	ecx, NUM_TX_DESC*MAX_ETH_FRAME_SIZE
2310
	cmp	edi, ecx
2311
	cmovae	edi, [device.tx_buffer] 	; Wrap if needed
2312
 
2313
	DEBUGF	1,"Found place in TX buffer: %x\n", edi
2314
	push	edi		;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2315
 
1481 hidnplayr 2316
; update statistics
2317
	inc	[device.packets_tx]
2318
 
2319
	mov	ecx, [esp+8+8]
2320
	add	dword [device.bytes_tx], ecx
2321
	adc	dword [device.bytes_tx + 4], 0
2322
 
1472 hidnplayr 2323
; copy packet data
2324
	mov	esi, [esp+4+8]
2325
	DEBUGF	1,"Copying %u bytes from %x to %x\n", ecx, esi, edi
2326
	shr	cx , 1
2327
	jnc	.nb
2328
	movsb
2329
  .nb:
2330
	shr	cx , 1
2331
	jnc	.nw
2332
	movsw
2333
  .nw:
2334
	rep	movsd
2335
 
2336
; program DPD
2337
	mov	eax, [esp]		; Tx buffer address
2338
	call	GetPgAddr
2339
	mov	edi, [esp]
2340
	and	edi, 4096 - 1
2341
	or	edi, eax
2342
 
2343
	mov	eax, [esp+4]		; descriptor
2344
	DEBUGF	1,"Frag addr is: %x\n", edi
2345
	and	[eax+dpd.next_ptr], 0
2346
	mov	[eax+dpd.frag_addr], edi
2347
 
2348
	mov	ecx, [esp+8+8]		; packet size
2349
	or	ecx, 0x80000000 	; last fragment
2350
	DEBUGF	1,"Frag size + flag is: %x\n", ecx
2351
	mov	[eax+dpd.frag_len], ecx
2352
 
2353
	mov	ecx, [esp+8+8]		; packet size
2354
	or	ecx, 0x8000		; transmission complete notification
2355
;        test    byte [device.has_hwcksm], 0xff
2356
;        jz      @f
2357
;        or      ecx, (1 shl 26) ; set AddTcpChecksum
2358
;@@:
2359
	DEBUGF	1,"Frag start_hdr + flag is: %x\n", ecx
2360
	mov	[eax+dpd.frame_start_hdr], ecx
2361
 
2362
 
2363
; calculate physical address
2364
	mov	edi, eax
2365
	call	GetPgAddr
2366
	and	edi, 4096 - 1
2367
	or	eax, edi
2368
	cmp	[device.dn_list_ptr_cleared], 0
2369
	jz	.add_to_list
2370
 
2371
	DEBUGF	1,"DN list ptr: %x\n", eax
2372
; write Dn_List_Ptr
2373
	set_io	0
2374
	set_io	REG_DN_LIST_PTR
2375
	out	dx, eax
2376
	jmp	.finish_pop
2377
.add_to_list:
2378
 
2379
	DEBUGF	1,"Adding To list\n"
2380
 
2381
; DnStall
2382
	set_io	0
2383
	set_io	REG_COMMAND
2384
	mov	ax, ((110b shl 11)+2)
2385
	out	dx, ax
2386
 
2387
; wait for DnStall to complete
2388
 
2389
	DEBUGF	1,"Waiting for DnStall\n"
2390
	mov	ecx, 6000
2391
.wait_for_stall:
2392
	in	ax, dx			; read REG_INT_STATUS
2393
	test	ah, 10000b
2394
	jz	.dnstall_ok
2395
	dec	ecx
2396
	jnz	.wait_for_stall
2397
 
2398
.dnstall_ok:
2399
	DEBUGF	1,"DnStall ok!\n"
2400
	mov	eax, [esp]		; prev_tx_frame
2401
	mov	ecx, [device.prev_dpd]
2402
	mov	[ecx+dpd.next_ptr], eax
2403
 
2404
	set_io	0
2405
	set_io	REG_DN_LIST_PTR
2406
	in	eax, dx
2407
 
2408
	test	eax, eax
2409
	jnz	.dnunstall
2410
; if Dn_List_Ptr has been cleared fill it up
2411
	DEBUGF	1,"DnList Ptr has been cleared\n"
2412
	mov	eax, [esp]
2413
	out	dx, eax
2414
 
2415
.dnunstall:
2416
; DnUnStall
2417
	set_io	0
2418
	set_io	REG_COMMAND
2419
	mov	ax, ((110b shl 11)+3)
2420
	out	dx, ax
2421
 
2422
.finish_pop:
2423
	pop	[device.prev_tx_frame]
2424
	pop	[device.prev_dpd]
2425
 
2426
.finish:
2427
	xor	eax, eax
2428
	ret
2429
 
2430
 
2431
;---------------------------------
2432
; Write MAC
2433
 
2434
 
2435
align 4
2436
write_mac:   ; Tested - ok
2437
 
2438
	DEBUGF 1,"Writing mac\n"
2439
 
2440
	set_io	0
2441
	set_io	REG_COMMAND
2442
 
2443
; switch to register window 2
2444
	mov	ax, SELECT_REGISTER_WINDOW+2
2445
	out	dx, ax
2446
 
2447
; write MAC addres back into the station address registers
2448
	set_io	REG_STATION_ADDRESS_LO
2449
	lea	esi, [device.mac]
2450
	outsw
2451
	inc	dx
2452
	inc	dx
2453
	outsw
2454
	inc	dx
2455
	inc	dx
2456
	outsw
2457
 
2458
;----------------------------
2459
; Read MAC
2460
 
2461
 
2462
align 4
2463
read_mac:    ; Tested - ok
2464
 
2465
 
2466
 
2467
	set_io	0
2468
	set_io	REG_COMMAND
2469
 
2470
; switch to register window 2
2471
	mov	ax, SELECT_REGISTER_WINDOW+2
2472
	out	dx, ax
2473
 
2474
; write MAC addres back into the station address registers
2475
	set_io	REG_STATION_ADDRESS_LO
2476
	lea	edi, [device.mac]
2477
	insw
2478
	inc	dx
2479
	inc	dx
2480
	insw
2481
	inc	dx
2482
	inc	dx
2483
	insw
2484
 
2485
	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
2486
 
2487
	ret
2488
 
2489
 
2490
;------------------------------------
2491
; Read MAC from eeprom
2492
 
2493
 
2494
align 4
2495
read_mac_eeprom:	; Tested - ok
2496
 
2497
	DEBUGF 1,"Reading mac from eeprom\n"
2498
 
2499
; read MAC from eeprom
2500
	mov	ecx, 3
2501
.mac_loop:
2502
	lea	ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1]
2503
	push	ecx
2504
	call	read_eeprom
2505
	pop	ecx
2506
	xchg	ah, al ; htons
2507
	mov	word [device.mac+ecx*2-2], ax
2508
 
2509
	loop	.mac_loop
2510
 
2511
	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
2512
 
2513
	ret
2514
 
2515
 
2516
 
2517
 
2518
 
2519
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2520
;;                          ;;
2521
;; Vortex Interrupt handler ;;
2522
;;                          ;;
2523
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2524
 
2525
align 4
2526
int_vortex:
2527
 
2528
	DEBUGF	1,"vortex IRQ %x ",eax:2
2529
 
2530
; find pointer of device wich made IRQ occur
2531
 
2532
	mov	esi, VORTEX_LIST
2533
	mov	ecx, [VORTEX_DEVICES]
2534
	test	ecx, ecx
2535
	jz	.fail
2536
  .nextdevice:
2537
	mov	ebx, dword [esi]
2538
 
2539
 
2540
	set_io	0
2541
	set_io	REG_INT_STATUS
2542
	in	ax, dx
2543
;;        and     ax, INT_MASK
2544
	jnz	.got_it
2545
 
2546
 
2547
	add	esi, 4
2548
 
2549
	test	ax , ax
2550
	jnz	.got_it
2551
	loop	.nextdevice
2552
 
2553
  .fail:
2554
 
2555
	ret
2556
 
2557
.got_it:
2558
 
2559
	DEBUGF	1,"Device: %x Status: %x ",ebx,eax:4
2560
 
2561
	test	ax, RxComplete
2562
	jz	.noRX
2563
 
2564
	set_io	0
2565
  .rx_status_loop:
2566
; examine RxStatus
2567
	set_io	REG_RX_STATUS
2568
	in	ax, dx
2569
	test	ax, ax
2570
	jz	.finish
2571
 
2572
	test	ah, 0x80 ; rxIncomplete
2573
	jnz	.finish
2574
 
2575
	test	ah, 0x40
2576
	jz	.check_length
2577
 
2578
; discard the top frame received advancing the next one
2579
	set_io	REG_COMMAND
2580
	mov	ax, (01000b shl 11)
2581
	out	dx, ax
2582
	jmp	.rx_status_loop
2583
 
2584
  .check_length:
2585
	and	eax, 0x1fff
2586
	cmp	eax, MAX_ETH_PKT_SIZE
2587
	ja	.discard_frame ; frame is too long discard it
2588
 
2589
  .check_dma:
2590
	mov	ecx, eax
2591
; switch to register window 7
2592
	set_io	0
2593
	set_io	REG_COMMAND
2594
	mov	ax, SELECT_REGISTER_WINDOW+7
2595
	out	dx, ax
2596
; check for master operation in progress
2597
	set_io	REG_MASTER_STATUS
2598
	in	ax, dx
2599
 
2600
	test	ah, 0x80
2601
	jnz	.finish
2602
 
2603
  .read_frame:
2604
; program buffer address to read in
2605
	stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
2606
	test	eax, eax
2607
	jz	.finish
2608
 
2609
	push	.discard_frame
2610
	push	ecx
2611
	push	eax
2612
;        zero_to_dma eax
2613
	set_io	REG_MASTER_ADDRESS
2614
	out	dx, eax
2615
 
2616
; program frame length
2617
	set_io	REG_MASTER_LEN
2618
	mov	ax, 1560
2619
	out	dx, ax
2620
 
2621
; start DMA Up
2622
	set_io	REG_COMMAND
2623
	mov	ax, (10100b shl 11) ; StartDMAUp
2624
	out	dx, ax
2625
 
2626
; check for master operation in progress
2627
	set_io	REG_MASTER_STATUS   ; TODO: use timeout and reset after timeout expired
2628
  .dma_loop:
2629
	xor	esi, esi
2630
	stdcall Sleep
2631
	in	ax, dx
2632
	test	ah, 0x80
2633
	jnz	.dma_loop
2634
 
2635
; registrate the received packet to kernel
2636
	jmp	EthReceiver
2637
 
2638
; discard the top frame received
2639
  .discard_frame:
2640
	set_io	0
2641
	set_io	REG_COMMAND
2642
	mov	ax, (01000b shl 11)
2643
	out	dx, ax
2644
 
2645
  .finish:
2646
 
2647
 
2648
.noRX:
2649
 
2650
	test	ax, DMADone
2651
	jz	.noDMA
2652
 
2653
	push	ax
2654
 
2655
	set_io	0
2656
	set_io	12
2657
	in	ax, dx
2658
	test	ax, 0x1000
2659
	jz	.nodmaclear
2660
 
2661
	mov	ax, 0x1000
2662
	out	dx, ax
2663
 
2664
  .nodmaclear:
2665
 
2666
	pop	ax
2667
 
2668
	DEBUGF	1, "DMA Done!\n", cx
2669
 
2670
 
2671
 
2672
.noDMA:
2673
 
2674
 
2675
 
2676
.ACK:
2677
	set_io	0
2678
	set_io	REG_COMMAND
2679
	mov	ax, AckIntr + IntReq + IntLatch
2680
	out	dx, ax
2681
 
2682
	ret
2683
 
2684
 
2685
 
2686
 
2687
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2688
;;                             ;;
2689
;; Boomerang Interrupt handler ;;
2690
;;                             ;;
2691
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2692
 
2693
align 4
2694
int_boomerang:
2695
 
2696
;        DEBUGF  1,"\nIRQ %x Boomerang\n",eax:2
2697
 
2698
; find pointer of device wich made IRQ occur
2699
 
2700
	mov	esi, BOOMERANG_LIST
2701
	mov	ecx, [BOOMERANG_DEVICES]
2702
 
2703
;        DEBUGF  1,"Devices: %u\n", ecx
2704
	test	ecx, ecx
2705
	jz	.fail
2706
  .nextdevice:
2707
	mov	ebx, dword[esi]
2708
 
2709
	set_io	0
2710
	set_io	REG_INT_STATUS
2711
	in	ax, dx
2712
	test	ax, IntLatch
2713
	jnz	.got_it
2714
 
2715
	add	esi, 4
2716
 
2717
	test	ax , ax
2718
	jnz	.got_it
2719
	dec	ecx
2720
	jnz	.nextdevice
2721
 
2722
  .fail:
2723
	DEBUGF	1,"Failed!\n"
2724
	ret
2725
 
2726
.got_it:
2727
 
2728
	DEBUGF	1,"Device: %x Status: %x ", ebx, eax
2729
 
2730
	push	ax
2731
; disable all INTS
2732
 
2733
	set_io	REG_COMMAND
2734
	mov	ax, SetIntrEnb
2735
	out	dx, ax
2736
 
2737
;; acknowledge all int sources
2738
;
2739
;        mov     ax, word [esp]
2740
;        and     ax, 0xff
2741
;        or      ax, AckIntr
2742
;        out     dx, ax
2743
 
2744
;--------------------------------------------------------------------------
2745
	test	word[esp], UpComplete
2746
	jz	.noRX
2747
 
2748
	push	ebx
2749
 
2750
  .receive:
2751
	DEBUGF	1,"UpComplete\n"
2752
 
2753
; check if packet is uploaded
2754
	mov	eax, [device.curr_upd]
2755
	test	byte [eax+upd.pkt_status+1], 0x80 ; upPktComplete
2756
	jz	.finish
2757
; packet is uploaded check for any error
2758
  .check_error:
2759
	test	byte [eax+upd.pkt_status+1], 0x40 ; upError
2760
	jz	.copy_packet_length
2761
	DEBUGF	1,"Error in packet\n"
2762
	and	[eax+upd.pkt_status], 0 	  ; mark packet as read
2763
	jmp	.finish
2764
  .copy_packet_length:
2765
	mov	ecx, [eax+upd.pkt_status]
2766
	and	ecx, 0x1fff
2767
	cmp	ecx, MAX_ETH_PKT_SIZE
2768
	jbe	.copy_packet
2769
	and	[eax+upd.pkt_status], 0
2770
	jmp	.finish
2771
 
2772
  .copy_packet:
2773
	DEBUGF	1, " data hw addr:%x\n", [eax+upd.frag_addr]
2774
 
2775
	mov	esi, [eax+upd.realaddr]
2776
 
2777
	push	esi ecx
2778
	stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
2779
	pop	ecx esi
2780
	test	eax, eax
2781
	jz	.finish
2782
 
2783
	push	dword .loop ;.finish
2784
	push	ecx eax
2785
	mov	edi, eax
2786
 
2787
	DEBUGF	1, " copying %u bytes from %x to %x\n", ecx, esi, edi
2788
 
1481 hidnplayr 2789
; update statistics
2790
	inc	[device.packets_rx]
2791
 
2792
	add	dword [device.bytes_rx], ecx
2793
	adc	dword [device.bytes_rx + 4], 0
2794
 
1472 hidnplayr 2795
; copy packet data
2796
	shr	cx , 1
2797
	jnc	.nb
2798
	movsb
2799
  .nb:
2800
	shr	cx , 1
2801
	jnc	.nw
2802
	movsw
2803
  .nw:
2804
	rep	movsd
2805
 
2806
	mov	eax, [device.curr_upd]
2807
	DEBUGF	1, "current upd: %x\n", eax
2808
	and	[eax + upd.pkt_status], 0	; clear the ring buffer entry for reuse
2809
	mov	[eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) ;;;
2810
	add	eax, upd.size
2811
 
2812
	mov	ecx, [device.upd_buffer]
2813
	add	ecx, (NUM_RX_DESC)*upd.size
2814
 
2815
	cmp	eax, ecx
2816
	cmovae	eax, [device.upd_buffer]
2817
	mov	[device.curr_upd], eax
2818
	DEBUGF	1, "next upd: %x\n", eax
2819
 
2820
	jmp	EthReceiver
2821
 
2822
  .loop:
2823
	mov	ebx, [esp]
2824
	jmp	.receive
2825
 
2826
  .finish:
2827
	pop	ebx
2828
 
2829
; check if the NIC is in the upStall state
2830
	set_io	0
2831
	set_io	REG_UP_PKT_STATUS
2832
	in	eax, dx
2833
	test	ah, 0x20	     ; UpStalled
2834
	jz	.noUpUnStall
2835
; issue upUnStall command
2836
	set_io	REG_COMMAND
2837
	mov	ax, ((11b shl 12)+1) ; upUnStall
2838
	out	dx, ax
2839
	DEBUGF	1, "upUnStalling\n"
2840
  .noUpUnStall:
2841
 
2842
.noRX:
2843
	pop	ax
2844
 
2845
	set_io	0
2846
	set_io	REG_COMMAND
2847
	or	ax, AckIntr
2848
	out	dx, ax
2849
 
2850
    ;    set_io  REG_COMMAND
2851
    ;    mov     ax, AckIntr + IntLatch
2852
    ;    out     dx, ax
2853
 
2854
 
2855
	set_io	REG_INT_STATUS
2856
	in	ax, dx
2857
	test	ax, S_5_INTS
2858
	jnz	.got_it
2859
 
2860
;re-enable ints
2861
	set_io	REG_COMMAND
2862
	mov	ax, SetIntrEnb + S_5_INTS
2863
	out	dx, ax
2864
 
2865
 
2866
	ret
2867
 
2868
 
2869
 
2870
 
2871
; End of code
2872
 
2873
align 4 					; Place all initialised data here
2874
 
2875
 
2876
 
2877
macro strtbl name, [string]
2878
{
2879
common
2880
	label name dword
2881
forward
2882
	local label
2883
	dd label
2884
forward
2885
	label db string, 0
2886
}
2887
 
2888
VORTEX_DEVICES	     dd 0
2889
BOOMERANG_DEVICES    dd 0
2890
version 	     dd (5 shl 16) or (API_VERSION and 0xFFFF)
2891
my_service	     db '3C59X',0		     ; max 16 chars include zero
2892
 
2893
 
2894
strtbl link_str, \
2895
	"No valid link type detected", \
2896
	"10BASE-T half duplex", \
2897
	"10BASE-T full-duplex", \
2898
	"100BASE-TX half duplex", \
2899
	"100BASE-TX full duplex", \
2900
	"100BASE-T4", \
2901
	"100BASE-FX", \
2902
	"10Mbps AUI", \
2903
	"10Mbps COAX (BNC)", \
2904
	"miiDevice - not supported"
2905
 
2906
strtbl hw_str, \
2907
	"3c590 Vortex 10Mbps", \
2908
	"3c592 EISA 10Mbps Demon/Vortex", \
2909
	"3c597 EISA Fast Demon/Vortex", \
2910
	"3c595 Vortex 100baseTx", \
2911
	"3c595 Vortex 100baseT4", \
2912
	"3c595 Vortex 100base-MII", \
2913
	"3c900 Boomerang 10baseT", \
2914
	"3c900 Boomerang 10Mbps Combo", \
2915
	"3c900 Cyclone 10Mbps TPO", \
2916
	"3c900 Cyclone 10Mbps Combo", \
2917
	"3c900 Cyclone 10Mbps TPC", \
2918
	"3c900B-FL Cyclone 10base-FL", \
2919
	"3c905 Boomerang 100baseTx", \
2920
	"3c905 Boomerang 100baseT4", \
2921
	"3c905B Cyclone 100baseTx", \
2922
	"3c905B Cyclone 10/100/BNC", \
2923
	"3c905B-FX Cyclone 100baseFx", \
2924
	"3c905C Tornado", \
2925
	"3c980 Cyclone", \
2926
	"3c982 Dual Port Server Cyclone", \
2927
	"3cSOHO100-TX Hurricane", \
2928
	"3c555 Laptop Hurricane", \
2929
	"3c556 Laptop Tornado", \
2930
	"3c556B Laptop Hurricane", \
2931
	"3c575 [Megahertz] 10/100 LAN CardBus", \
2932
	"3c575 Boomerang CardBus", \
2933
	"3CCFE575BT Cyclone CardBus", \
2934
	"3CCFE575CT Tornado CardBus", \
2935
	"3CCFE656 Cyclone CardBus", \
2936
	"3CCFEM656B Cyclone+Winmodem CardBus", \
2937
	"3CXFEM656C Tornado+Winmodem CardBus", \
2938
	"3c450 HomePNA Tornado", \
2939
	"3c920 Tornado", \
2940
	"3c982 Hydra Dual Port A", \
2941
	"3c982 Hydra Dual Port B", \
2942
	"3c905B-T4", \
2943
	"3c920B-EMB-WNM Tornado"
2944
 
2945
 
2946
 
2947
align 4
2948
hw_versions:
2949
dw 0x5900, IS_VORTEX
2950
; 3c590 Vortex 10Mbps
2951
dw 0x5920, IS_VORTEX
2952
; 3c592 EISA 10Mbps Demon/Vortex
2953
dw 0x5970, IS_VORTEX
2954
; 3c597 EISA Fast Demon/Vortex
2955
dw 0x5950, IS_VORTEX
2956
; 3c595 Vortex 100baseTx
2957
dw 0x5951, IS_VORTEX
2958
; 3c595 Vortex 100baseT4
2959
dw 0x5952, IS_VORTEX
2960
; 3c595 Vortex 100base-MII
2961
dw 0x9000, IS_BOOMERANG
2962
; 3c900 Boomerang 10baseT
2963
dw 0x9001, IS_BOOMERANG
2964
; 3c900 Boomerang 10Mbps Combo
2965
dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
2966
; 3c900 Cyclone 10Mbps TPO
2967
dw 0x9005, IS_CYCLONE or HAS_HWCKSM
2968
; 3c900 Cyclone 10Mbps Combo
2969
dw 0x9006, IS_CYCLONE or HAS_HWCKSM
2970
; 3c900 Cyclone 10Mbps TPC
2971
dw 0x900A, IS_CYCLONE or HAS_HWCKSM
2972
; 3c900B-FL Cyclone 10base-FL
2973
dw 0x9050, IS_BOOMERANG or HAS_MII
2974
; 3c905 Boomerang 100baseTx
2975
dw 0x9051, IS_BOOMERANG or HAS_MII
2976
; 3c905 Boomerang 100baseT4
2977
dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE
2978
; 3c905B Cyclone 100baseTx
2979
dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
2980
; 3c905B Cyclone 10/100/BNC
2981
dw 0x905A, IS_CYCLONE or HAS_HWCKSM
2982
; 3c905B-FX Cyclone 100baseFx
2983
dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
2984
; 3c905C Tornado
2985
dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
2986
; 3c980 Cyclone
2987
dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
2988
; 3c982 Dual Port Server Cyclone
2989
dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM
2990
; 3cSOHO100-TX Hurricane
2991
dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM
2992
; 3c555 Laptop Hurricane
2993
dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM
2994
; 3c556 Laptop Tornado
2995
dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM
2996
; 3c556B Laptop Hurricane
2997
dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT
2998
; 3c575 [Megahertz] 10/100 LAN CardBus
2999
dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT
3000
; 3c575 Boomerang CardBus
3001
dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM
3002
; 3CCFE575BT Cyclone CardBus
3003
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
3004
; 3CCFE575CT Tornado CardBus
3005
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
3006
; 3CCFE656 Cyclone CardBus
3007
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
3008
; 3CCFEM656B Cyclone+Winmodem CardBus
3009
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
3010
; 3CXFEM656C Tornado+Winmodem CardBus
3011
dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
3012
; 3c450 HomePNA Tornado
3013
dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
3014
; 3c920 Tornado
3015
dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY
3016
; 3c982 Hydra Dual Port A
3017
dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY
3018
; 3c982 Hydra Dual Port B
3019
dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE
3020
; 3c905B-T4
3021
dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
3022
; 3c920B-EMB-WNM Tornado
3023
HW_VERSIONS_SIZE = $ - hw_versions
3024
 
3025
 
3026
include_debug_strings				; All data wich FDO uses will be included here
3027
 
3028
section '.data' data readable writable align 16 ; place all uninitialized data place here
3029
 
3030
VORTEX_LIST    rd MAX_DEVICES			; This list contains all pointers to device structures the driver is handling
3031
BOOMERANG_LIST rd MAX_DEVICES
3032
 
3033
 
3034
 
3035