Subversion Repositories Kolibri OS

Rev

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