Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;; I8255x (Intel eepro 100) driver for KolibriOS                   ;;
7
;;                                                                 ;;
8
;;    Written by hidnplayr@kolibrios.org                           ;;
9
;;                                                                 ;;
10
;;    v0.0 - march 2009                                            ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;; current status (september 2009) - INCOMPLETE                    ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18
 
19
format MS COFF
20
 
21
	API_VERSION		equ 0x01000100
22
 
23
	DEBUG			equ 1
24
	__DEBUG__		equ 1
25
	__DEBUG_LEVEL__ 	equ 1
26
 
27
include 'proc32.inc'
28
include 'imports.inc'
29
include 'fdo.inc'
30
 
31
OS_BASE 	equ 0;
32
new_app_base	equ 0x60400000
33
PROC_BASE	equ OS_BASE+0x0080000
34
 
35
public START
36
public service_proc
37
public version
38
 
39
struc IOCTL {
40
      .handle		dd ?
41
      .io_code		dd ?
42
      .input		dd ?
43
      .inp_size 	dd ?
44
      .output		dd ?
45
      .out_size 	dd ?
46
}
47
 
48
virtual at 0
49
  IOCTL IOCTL
50
end virtual
51
 
52
struc ETH_DEVICE {
53
; pointers to procedures
54
      .unload		dd ?
55
      .reset		dd ?
56
      .transmit 	dd ?
57
      .set_MAC		dd ?
58
      .get_MAC		dd ?
59
      .set_mode 	dd ?
60
      .get_mode 	dd ?
61
; status
62
      .bytes_tx 	dd ?
63
      .bytes_rx 	dd ?
64
      .packets_tx	dd ?
65
      .packets_rx	dd ?
66
      .mode		dd ?  ; This dword contains cable status (10mbit/100mbit, full/half duplex, auto negotiation or not,..)
67
      .name		dd ?
68
; device specific
69
      .io_addr		dd ?
70
      .pci_bus		db ?
71
      .pci_dev		db ?
72
      .irq_line 	db ?
73
      .status		dw ? ;
74
      .command		dw ? ;
75
      .link		dd ? ;
76
      .rx_buf_addr	dd ? ;
77
      .count		dw ? ;
78
      .size		dw ? ;
79
      .packet		dd ? ;
80
      .eeprom_data	rd 16
81
 
82
	.txfd:
83
	.txfd_status		 dw  ?
84
	.txfd_command		 dw  ?
85
	.txfd_link		 dd  ?
86
	.txfd_tx_desc_addr	 dd  ?
87
	.txfd_count		 dd  ?
88
	.txfd_tx_buf_addr0	 dd  ?
89
	.txfd_tx_buf_size0	 dd  ?
90
	.txfd_tx_buf_addr1	 dd  ?
91
	.txfd_tx_buf_size1	 dd  ?
92
 
93
      .size_:
94
 
95
}
96
 
97
virtual at 0
98
  device ETH_DEVICE
99
end virtual
100
 
101
 
102
lstats:
103
tx_good_frames: 	dd 0
104
tx_coll16_errs: 	dd 0
105
tx_late_colls:		dd 0
106
tx_underruns:		dd 0
107
tx_lost_carrier:	dd 0
108
tx_deferred:		dd 0
109
tx_one_colls:		dd 0
110
tx_multi_colls: 	dd 0
111
tx_total_colls: 	dd 0
112
 
113
rx_good_frames: 	dd 0
114
rx_crc_errs:		dd 0
115
rx_align_errs:		dd 0
116
rx_resource_errs:	dd 0
117
rx_overrun_errs:	dd 0
118
rx_colls_errs:		dd 0
119
rx_runt_errs:		dd 0
120
 
121
done_marker:		dd 0
122
 
123
 
124
confcmd:
125
	.status:	 dw  0
126
	.command:	 dw  0
127
	.link:		 dd  0
128
 
129
confcmd_data:		db  22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
130
			db  0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
131
			db  0x80, 0x3f, 0x05
132
 
133
 
134
	MAX_I8255x		equ 16	 ; Max number of devices this driver may handle
135
 
136
 
137
; PCI Bus defines
138
 
139
	PCI_HEADER_TYPE 		equ	0x0e  ;8 bit
140
	PCI_BASE_ADDRESS_0		equ	0x10  ;32 bit
141
	PCI_BASE_ADDRESS_5		equ	0x24  ;32 bits
142
	PCI_BASE_ADDRESS_SPACE_IO	equ	0x01
143
	PCI_VENDOR_ID			equ	0x00  ;16 bit
144
	PCI_BASE_ADDRESS_IO_MASK	equ	0xFFFFFFFC
145
 
146
 
147
 
148
;/***********************************************************************/
149
;/*                       I82557 related defines                        */
150
;/***********************************************************************/
151
 
152
; Serial EEPROM section.
153
;   A "bit" grungy, but we work our way through bit-by-bit :->.
154
;  EEPROM_Ctrl bits.
155
EE_SHIFT_CLK   equ   0x01    ; EEPROM shift clock.
156
EE_CS	       equ   0x02    ; EEPROM chip select.
157
EE_DATA_WRITE  equ   0x04    ; EEPROM chip data in.
158
EE_DATA_READ   equ   0x08    ; EEPROM chip data out.
159
EE_WRITE_0     equ   0x4802
160
EE_WRITE_1     equ   0x4806
161
EE_ENB	       equ   0x4802
162
 
163
 
164
; The EEPROM commands include the alway-set leading bit.
165
EE_READ_CMD    equ   6
166
 
167
; The SCB accepts the following controls for the Tx and Rx units:
168
CU_START       equ   0x0010
169
CU_RESUME      equ   0x0020
170
CU_STATSADDR   equ   0x0040
171
CU_SHOWSTATS   equ   0x0050   ; Dump statistics counters.
172
CU_CMD_BASE    equ   0x0060   ; Base address to add to add CU commands.
173
CU_DUMPSTATS   equ   0x0070   ; Dump then reset stats counters.
174
 
175
RX_START       equ   0x0001
176
RX_RESUME      equ   0x0002
177
RX_ABORT       equ   0x0004
178
RX_ADDR_LOAD   equ   0x0006
179
RX_RESUMENR    equ   0x0007
180
INT_MASK       equ   0x0100
181
DRVR_INT       equ   0x0200   ; Driver generated interrupt.
182
 
183
 
184
 
185
 
186
 
187
 
188
section '.flat' code readable align 16
189
 
190
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
191
;;                        ;;
192
;; proc START             ;;
193
;;                        ;;
194
;; (standard driver proc) ;;
195
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
196
 
197
proc START stdcall, state:dword
198
 
199
	cmp [state], 1
200
	jne .exit
201
 
202
  .entry:
203
 
204
	DEBUGF 1,"Loading I8255x driver\n"
205
	stdcall RegService, my_service, service_proc
206
	ret
207
 
208
  .fail:
209
  .exit:
210
	xor eax, eax
211
	ret
212
 
213
endp
214
 
215
 
216
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
217
;;                        ;;
218
;; proc SERVICE_PROC      ;;
219
;;                        ;;
220
;; (standard driver proc) ;;
221
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
222
 
223
align 4
224
proc service_proc stdcall, ioctl:dword
225
 
226
	mov	edx, [ioctl]
227
	mov	eax, [ebx+IOCTL.io_code]
228
 
229
;------------------------------------------------------
230
 
231
	cmp	eax, 0 ;SRV_GETVERSION
232
	jne	@F
233
 
234
	cmp	[edx+IOCTL.out_size], 4
235
	jl	.fail
236
	mov	eax, [edx+IOCTL.output]
237
	mov	[eax], dword API_VERSION
238
 
239
	xor	eax, eax
240
	ret
241
 
242
;------------------------------------------------------
243
  @@:
244
	cmp	eax, 1 ;SRV_HOOK
245
	jne	.fail
246
 
247
	mov	eax, [esp]
248
	DEBUGF 1,"esp=%x [esp]=%x\n",esp,eax
249
 
250
	cmp	[edx + IOCTL.inp_size], 3		; Data input must be at least 3 bytes
251
	jl	.fail
252
 
253
	mov	eax, [edx + IOCTL.input]
254
	cmp	byte [eax], 1				; 1 means device number and bus number (pci) are given
255
	jne	.fail					; other types arent supported for this card yet
256
 
257
; check if the device is already listed
258
 
259
	mov	esi, I8255x_LIST
260
	mov	ecx, [I8255x_DEV]
261
	test	ecx, ecx
262
	jz	.firstdevice
263
	mov	eax, [edx+IOCTL.input]			; get the pci bus and device numbers
264
	mov	bx , [eax+1]				;
265
  .nextdevice:
266
	DEBUGF 1,"1"
267
	lodsd
268
	cmp	bx , word [eax + device.pci_bus]	; compare with pci and device num in RTL8139 list (notice the usage of word instead of byte)
269
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
270
 
271
	loop	.nextdevice
272
 
273
; This device doesnt have its own eth_device structure yet, lets create one
274
  .firstdevice:
275
	cmp	[I8255x_DEV], MAX_I8255x		; First check if the driver can handle one more card
276
	jge	.fail
277
 
278
	push	edx
279
	stdcall KernelAlloc, device.size		; Allocate the buffer for eth_device structure
280
	pop	edx
281
	test	eax, eax
282
	jz	.fail
283
	mov	ebx, eax				; ebx is always used as a pointer to the structure (in driver, but also in kernel code)
284
 
285
; Fill in the direct call addresses into the struct
286
 
287
	mov	dword [ebx+device.reset], reset
288
	mov	dword [ebx+device.transmit], transmit
289
;        mov     dword [ebx+device.get_MAC], read_mac
290
;        mov     dword [ebx+device.set_MAC], write_mac
291
	mov	dword [ebx+device.unload], unload
292
	mov	dword [ebx+device.name], devicename
293
 
294
; save the pci bus and device numbers
295
 
296
	mov	eax, [edx+IOCTL.input]
297
	mov	cl , [eax+1]
298
	mov	[ebx+device.pci_bus], cl
299
	mov	cl , [eax+2]
300
	mov	[ebx+device.pci_dev], cl
301
 
302
; Now, it's time to find the base io addres of the PCI device
303
; TODO: implement check if bus and dev exist on this machine
304
 
305
	mov	edx, PCI_BASE_ADDRESS_0
306
  .reg_check:
307
	movzx	eax, byte [ebx+device.pci_bus]
308
	movzx	ecx, byte [ebx+device.pci_dev]
309
 
310
	push	edx ecx
311
	stdcall PciRead16, eax ,ecx ,edx
312
	pop	ecx edx
313
 
314
	mov	[ebx+device.io_addr], eax
315
	and	eax, PCI_BASE_ADDRESS_IO_MASK
316
	test	eax, eax
317
	jz	.inc_reg
318
	mov	eax, [ebx+device.io_addr]
319
	and	eax, PCI_BASE_ADDRESS_SPACE_IO
320
	test	eax, eax
321
	jz	.inc_reg
322
 
323
	mov	eax, [ebx+device.io_addr]
324
	and	eax, PCI_BASE_ADDRESS_IO_MASK
325
	mov	[ebx+device.io_addr], eax
326
	jmp	.got_io
327
 
328
  .inc_reg:
329
	add	edx, 4
330
	cmp	edx, PCI_BASE_ADDRESS_5
331
	jbe	.reg_check
332
 
333
  .got_io:
334
 
335
; We've found the io address, find IRQ now
336
 
337
	movzx	eax, byte [ebx+device.pci_bus]
338
	movzx	ecx, byte [ebx+device.pci_dev]
339
	push	ebx
340
	stdcall PciRead8, eax ,ecx ,0x3c				; 0x3c is the offset where irq can be found
341
	pop	ebx
342
	mov	byte [ebx+device.irq_line], al
343
 
344
	DEBUGF	1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
345
	[ebx+device.pci_dev]:1,[ebx+device.pci_bus]:1,[ebx+device.irq_line]:1,[ebx+device.io_addr]:4
346
 
347
; Allocate the Receive buffer
348
 
349
	stdcall KernelAlloc, dword (RX_BUFFER_SIZE+MAX_ETH_FRAME_SIZE)
350
	test	eax, eax
351
	jz	.err
352
	mov	[ebx+device.rx_buffer], eax				; Save the address to it into the device struct
353
 
354
; Now, Clear the allocated buffer
355
 
356
	cld
357
	mov	edi, eax
358
	mov	ecx, (RX_BUFFER_SIZE)/4 				; divide by 4 because we are going to use DWORD
359
	xor	eax, eax
360
	rep	stosd
361
 
362
; Allocate the Transmit Buffer
363
 
364
	stdcall KernelAlloc, dword (TX_BUFFER_SIZE)
365
	test	eax, eax
366
	jz	.err
367
	mov	[ebx+device.tx_buffer], eax
368
 
369
; This one needs to be cleared too..
370
 
371
	mov	edi, eax
372
	mov	ecx, (TX_BUFFER_SIZE)/4
373
	xor	eax, eax
374
	rep	stosd
375
 
376
; Ok, the eth_device structure is ready, let's probe the device
377
 
378
	call	probe							; this function will output in eax
379
	test	eax, eax
380
	jnz	.err							; If an error occured, exit
381
 
382
	mov	eax, [I8255x_DEV]					; Add the device structure to our device list
383
	mov	[I8255x_LIST+4*eax], ebx				; (IRQ handler uses this list to find device)
384
	inc	[I8255x_DEV]						;
385
 
386
	jmp	EthRegDev						; Register the device to kernel (ebx points to device struct)
387
									; Notice the jump instead of call, it is the same as
388
									;
389
									; call EthRegDev
390
									; ret
391
									;
392
									; Also notice that the value EthRegDev returned in eax, will be returned to
393
									; the caller application
394
 
395
; If the device was already loaded, find the device number and return it in eax
396
 
397
  .find_devicenum:
398
	DEBUGF	1,"Trying to find device number of already registered device\n"
399
	mov	ebx, eax
400
	call	EthStruc2Dev						; This kernel procedure converts a pointer to device struct in ebx
401
									; into a device number in edi
402
	mov	eax, edi						; Application wants it in eax instead
403
	DEBUGF	1,"Kernel says: %u\n", eax
404
	ret
405
 
406
; If an error occured, remove all allocated data and exit (returning -1 in eax)
407
 
408
  .err:
409
	stdcall KernelFree, dword [ebx+device.rx_buffer]
410
	stdcall KernelFree, dword [ebx+device.tx_buffer]
411
	stdcall KernelFree, ebx
412
 
413
  .fail:
414
	or	eax, -1
415
	ret
416
 
417
;------------------------------------------------------
418
endp
419
 
420
 
421
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
422
;;                                                                        ;;
423
;;        Actual Hardware dependent code starts here                      ;;
424
;;                                                                        ;;
425
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
426
 
427
 
428
unload:
429
	; TODO: (in this particular order)
430
	;
431
	; - Stop the device
432
	; - Detach int handler
433
	; - Remove device from local list (RTL8139_LIST)
434
	; - call unregister function in kernel
435
	; - Remove all allocated structures and buffers the card used
436
 
437
	or	eax,-1
438
 
439
ret
440
 
441
;***************************************************************************
442
;   Function
443
;      I8255x_probe
444
;   Description
445
;      Searches for an ethernet card, enables it and clears the rx buffer
446
;      If a card was found, it enables the ethernet -> TCPIP link
447
;
448
;***************************************************************************
449
 
450
probe:
451
 
452
	DEBUGF 1," Probing i8255x device: "
453
 
454
; enable the device
455
 
456
	movzx	eax, byte [ebx+device.pci_bus]
457
	movzx	ecx, byte [ebx+device.pci_dev]
458
	stdcall PciRead16, eax ,ecx ,PCI_REG_CMD
459
 
460
	mov	cx , ax
461
	or	cx , 0x05
462
	movzx	eax, byte [ebx+device.pci_bus]
463
	movzx	edx, byte [ebx+device.pci_dev]
464
	stdcall PciWrite16, eax ,edx ,PCI_REG_CMD, ecx
465
 
466
; do something else TODO
467
 
468
	mov	ebx, 0x6000000
469
	mov	ecx, 27
470
	call	do_eeprom_cmd
471
	and	eax, 0xffe0000
472
	cmp	eax, 0xffe0000
473
	je	bige
474
 
475
	mov	ebx, 0x1800000
476
	mov	ecx, 0x40
477
	jmp	doread
478
 
479
bige:
480
	mov	ebx, 0x6000000
481
	mov	ecx, 0x100
482
 
483
doread:
484
 
485
	; do-eeprom-cmd will destroy all registers
486
	; we have eesize in ecx
487
	; read_cmd in ebx
488
 
489
	; Ignore full eeprom - just load the mac address
490
	mov	ecx, 0
491
 
492
drlp:
493
 
494
 
495
	push	ecx	 ; save count
496
	push	ebx
497
	mov	eax, ecx
498
	shl	eax, 16
499
	or	ebx, eax
500
	mov	ecx, 27
501
	call	do_eeprom_cmd
502
 
503
	pop	ebx
504
	pop	ecx
505
 
506
	mov	edx, ecx
507
	shl	edx, 2
508
	mov	esi, eeprom_data
509
	add	esi, edx
510
	mov	[esi], eax
511
 
512
	inc	ecx
513
	cmp	ecx, 16
514
	jne	drlp
515
 
516
	; OK, we have the MAC address.
517
 
518
;***************************************************************************
519
;   Function
520
;      I8255x_reset
521
;   Description
522
;      Place the chip (ie, the ethernet card) into a virgin state
523
;      No inputs
524
;      All registers destroyed
525
;
526
;***************************************************************************
527
 
528
reset:
529
 
530
	; Now reset the card
531
 
532
	mov	edx, [ebx+device.io_addr]
533
	add	dx, 8	      ; SCBPort
534
	xor	eax, eax      ; The reset cmd == 0
535
	out	dx, eax
536
 
537
	mov	esi, 10
538
	call	delay_ms      ; Give the card time to warm up.
539
 
540
	mov	eax, lstats
541
	mov	edx, [ebx+device.io_addr]
542
	add	edx, 4		  ; SCBPointer
543
	out	dx, eax
544
 
545
	mov	eax, 0x0140	    ; INT_MASK | CU_STATSADDR
546
	mov	edx, [ebx+device.io_addr]
547
	add	edx, 2		  ; SCBCmd
548
	out	dx, ax
549
 
550
	call	wait_for_cmd_done
551
 
552
	mov	eax, 0
553
	mov	edx, [ebx+device.io_addr]
554
	add	edx, 4		  ; SCBPointer
555
	out	dx, eax
556
 
557
	mov	eax, 0x0106	    ; INT_MASK | RX_ADDR_LOAD
558
	mov	edx, [ebx+device.io_addr]
559
	add	edx, 2		  ; SCBCmd
560
	out	dx, ax
561
 
562
	call	wait_for_cmd_done
563
   ; build rxrd structure
564
	mov	ax, 0x0001
565
	mov	[ebx+device.status], ax
566
	mov	ax, 0x0000
567
	mov	[rxfd_command], ax
568
 
569
	mov	eax, rxfd_status
570
	sub	eax, OS_BASE
571
	mov	[ebx+device.link], eax
572
 
573
	mov	eax, Ether_buffer
574
	sub	eax, OS_BASE
575
	mov	[ebx+device.rx_buf_addr], eax
576
 
577
	mov	ax, 0
578
	mov	[ebx+device.count], ax
579
 
580
	mov	ax, 1528
581
	mov	[ebx+device.size], ax
582
 
583
	mov	edx, [ebx+device.io_addr]
584
	add	edx, 4		 ; SCBPointer
585
 
586
	mov	eax, rxfd_status
587
	sub	eax, OS_BASE
588
	out	dx, eax
589
 
590
	mov	edx, [ebx+device.io_addr]
591
	add	edx, 2		 ; SCBCmd
592
 
593
	mov	ax, 0x0101	   ; INT_MASK | RX_START
594
	out	dx, ax
595
 
596
	call	wait_for_cmd_done
597
 
598
   ; start the receiver
599
 
600
	mov	ax, 0
601
	mov	[ebx+device.status], ax
602
 
603
	mov	ax, 0xc000
604
	mov	[ebx+device.command], ax
605
 
606
	mov	edx, [ebx+device.io_addr]
607
	add	edx, 4		 ; SCBPointer
608
 
609
	mov	eax, rxfd_status
610
	sub	eax, OS_BASE
611
	out	dx, eax
612
 
613
	mov	edx, [ebx+device.io_addr]
614
	add	edx, 2		 ; SCBCmd
615
 
616
	mov	ax, 0x0101	   ; INT_MASK | RX_START
617
	out	dx, ax
618
 
619
   ; Init TX Stuff
620
 
621
	mov	edx, [ebx+device.io_addr]
622
	add	edx, 4		 ; SCBPointer
623
 
624
	mov	eax, 0
625
	out	dx, eax
626
 
627
	mov	edx, [ebx+device.io_addr]
628
	add	edx, 2		 ; SCBCmd
629
 
630
	mov	ax, 0x0160	   ; INT_MASK | CU_CMD_BASE
631
	out	dx, ax
632
 
633
	call	wait_for_cmd_done
634
 
635
   ; Set TX Base address
636
 
637
   ; First, set up confcmd values
638
 
639
	mov	ax, 2
640
	mov	[confcmd_command], ax
641
	mov	eax, txfd
642
	sub	eax, OS_BASE
643
	mov	[confcmd_link], eax
644
 
645
	mov	ax, 1
646
	mov	[txfd_command], ax	   ; CmdIASetup
647
 
648
	mov	ax, 0
649
	mov	[txfd_status], ax
650
 
651
	mov	eax, confcmd
652
	sub	eax, OS_BASE
653
	mov	[txfd_link], eax
654
 
655
 
656
 
657
   ; ETH_ALEN is 6 bytes
658
 
659
	mov	esi, eeprom_data
660
	mov	edi, node_addr
661
	mov	ecx, 3
662
 
663
drp000:
664
 
665
	mov	eax, [esi]
666
	mov	[edi], al
667
	shr	eax, 8
668
	inc	edi
669
	mov	[edi], al
670
	inc	edi
671
	add	esi, 4
672
	loop	drp000
673
 
674
   ; Hard code your MAC address into node_addr at this point,
675
   ; If you cannot read the MAC address from the eeprom in the previous step.
676
   ; You also have to write the mac address into txfd_tx_desc_addr, rather
677
   ; than taking data from eeprom_data
678
 
679
	mov	esi, eeprom_data
680
	mov	edi, txfd_tx_desc_addr
681
	mov	ecx, 3
682
 
683
drp001:
684
 
685
	mov	eax, [esi]
686
	mov	[edi], al
687
	shr	eax, 8
688
	inc	edi
689
	mov	[edi], al
690
	inc	edi
691
	add	esi, 4
692
	loop	drp001
693
 
694
	mov	esi, eeprom_data + (6 * 4)
695
	mov	eax, [esi]
696
	shr	eax, 8
697
	and	eax, 0x3f
698
	cmp	eax, 4		  ; DP83840
699
	je	drp002
700
	cmp	eax, 10 	   ; DP83840A
701
	je	drp002
702
	jmp	drp003
703
 
704
drp002:
705
 
706
	mov	ebx, [esi]
707
	and	ebx, 0x1f
708
	push	ebx
709
	mov	ecx, 23
710
	call	mdio_read
711
	pop	ebx
712
	or	eax, 0x0422
713
	mov	ecx, 23
714
	mov	edx, eax
715
	call	mdio_write
716
 
717
drp003:
718
 
719
	mov	ax, 0x4002	   ; Cmdsuspend | CmdConfigure
720
	mov	[confcmd_command], ax
721
	mov	ax, 0
722
	mov	[confcmd_status], ax
723
	mov	eax, txfd
724
	mov	[confcmd_link], eax
725
	mov	ebx, confcmd_data
726
	mov	al, 0x88	 ; fifo of 8 each
727
	mov	[ebx + 1], al
728
	mov	al, 0
729
	mov	[ebx + 4], al
730
	mov	al, 0x80
731
	mov	[ebx + 5], al
732
	mov	al, 0x48
733
	mov	[ebx + 15], al
734
	mov	al, 0x80
735
	mov	[ebx + 19], al
736
	mov	al, 0x05
737
	mov	[ebx + 21], al
738
 
739
	mov	eax, txfd
740
	sub	eax, OS_BASE
741
	mov	edx, [ebx+device.io_addr]
742
	add	edx, 4		  ; SCBPointer
743
	out	dx, eax
744
 
745
	mov	eax, 0x0110	    ; INT_MASK | CU_START
746
	mov	edx, [ebx+device.io_addr]
747
	add	edx, 2		  ; SCBCmd
748
	out	dx, ax
749
 
750
	call	wait_for_cmd_done
751
 
752
jmp skip
753
 
754
   ; wait for thing to start
755
drp004:
756
 
757
	mov	ax, [txfd_status]
758
	test	ax, ax
759
	jz	drp004
760
 
761
skip:
762
   ; Indicate that we have successfully reset the card
763
 
764
	xor	eax, eax
765
 
766
	ret
767
 
768
 
769
;***************************************************************************
770
;   Function
771
;      I8255x_transmit
772
;
773
;   Description
774
;       Transmits a packet of data via the ethernet card
775
;          Pointer to 48 bit destination address in edi
776
;         Type of packet in bx
777
;         size of packet in ecx
778
;         pointer to packet data in esi
779
;
780
;***************************************************************************
781
 
782
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
783
;;                                         ;;
784
;; Transmit                                ;;
785
;;                                         ;;
786
;; In: buffer pointer in [esp]             ;;
787
;;     size of buffer in [esp+4]           ;;
788
;;     pointer to device structure in ebx  ;;
789
;;                                         ;;
790
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
791
 
792
align 4
793
transmit:
794
 
795
	DEBUGF	1,"Transmitting packet, buffer:%x, size:%u\n",[esp],[esp+4]
796
	mov	eax, [esp]
797
	DEBUGF	1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
798
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
799
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
800
	[eax+13]:2,[eax+12]:2
801
 
802
	cmp	dword [esp+4], MAX_ETH_FRAME_SIZE
803
	jg	.finish 			; packet is too long
804
	cmp	dword [esp+4], 60
805
	jl	.finish 			; packet is too short
806
 
807
;        mov     [hdr_type], bx
808
 
809
;        mov     eax, [edi]
810
;        mov     [hdr_dst_addr], eax
811
;        mov     ax, [edi+4]
812
;        mov     [hdr_dst_addr+4], ax
813
 
814
;        mov     eax, [node_addr]
815
;        mov     [hdr_src_addr], eax
816
;        mov     ax, [node_addr+4]
817
;        mov     [hdr_src_addr+4], ax
818
 
819
	mov	edx, [ebx+device.io_addr]
820
	in	ax, dx
821
	and	ax, 0xfc00
822
	out	dx, ax
823
 
824
	mov	[ebx+device.txfd_status], 0
825
	mov	[ebx+device.txfd_command], 0x400C		  ; Cmdsuspend | CmdTx | CmdTxFlex
826
	lea	eax, [ebx+device.txfd]
827
	mov	[txfd_link], eax
828
	mov	[txfd_count], 0x02208000
829
	mov	eax, txfd_tx_buf_addr0
830
	call	GetPgAddr
831
	mov	[txfd_tx_desc_addr], eax
832
	mov	eax, hdr
833
	call	GetPgAddr
834
	mov	[txfd_tx_buf_addr0], eax
835
	mov	eax, 14   ; sizeof hdr
836
	mov	[txfd_tx_buf_size0], eax
837
 
838
	; Copy the buffer address and size in
839
;        mov     eax, esi
840
;        sub     eax, OS_BASE
841
;        mov     [txfd_tx_buf_addr1], eax
842
;        mov     eax, ecx
843
;        mov     [txfd_tx_buf_size1], eax
844
 
845
	mov	eax, ebx
846
	call	GetPgAddr
847
	add	eax, device.txfd
848
	mov	edx, [ebx+device.io_addr]
849
	add	edx, 4		  ; SCBPointer
850
	out	dx, eax
851
 
852
	mov	ax, 0x0110	   ; INT_MASK | CU_START
853
	mov	edx, [ebx+device.io_addr]
854
	add	edx, 2		  ; SCBCmd
855
	out	dx, ax
856
 
857
	call	wait_for_cmd_done
858
 
859
	mov	edx, [ebx+device.io_addr]
860
	in	ax, dx
861
 
862
I8t_001:
863
 
864
	mov	ax, [ebx+device.txfd_status]
865
	cmp	ax, 0
866
	je	I8t_001
867
 
868
	mov	edx, [ebx+device.io_addr]
869
	in	ax, dx
870
 
871
  .finish:
872
 
873
	ret
874
 
875
 
876
 
877
;***************************************************************************
878
; Function
879
;    I8255x_poll
880
;
881
; Description
882
;    Polls the ethernet card for a received packet
883
;    Received data, if any, ends up in Ether_buffer
884
;
885
;***************************************************************************
886
I8255x_poll:
887
 
888
	mov	ax, 0	   ; assume no data
889
	mov	[eth_rx_data_len], ax
890
 
891
	mov	ax, [rxfd_status]
892
	cmp	ax, 0
893
	je	i8p_exit
894
 
895
	mov	ax, 0
896
	mov	[rxfd_status], ax
897
 
898
	mov	ax, 0xc000
899
	mov	[rxfd_command], ax
900
 
901
	mov	edx, [io_addr]
902
	add	edx, 4		 ; SCBPointer
903
 
904
	mov	eax, rxfd_status
905
	sub	eax, OS_BASE
906
	out	dx, eax
907
 
908
	mov	edx, [ebx+device.io_addr]
909
	add	edx, 2		 ; SCBCmd
910
 
911
	mov	ax, 0x0101	   ; INT_MASK | RX_START
912
	out	dx, ax
913
 
914
	call	wait_for_cmd_done
915
 
916
	mov	esi, rxfd_packet
917
	mov	edi, Ether_buffer
918
	mov	ecx, 1518
919
	cld
920
	rep	movsb
921
 
922
	mov	ax, [rxfd_count]
923
	and	ax, 0x3fff
924
	mov	[eth_rx_data_len], ax
925
 
926
i8p_exit:
927
   ret
928
 
929
 
930
 
931
 
932
;***************************************************************************
933
;   Function
934
;      wait_for_cmd_done
935
;
936
;   Description
937
;       waits for the hardware to complete a command
938
;       port address in edx
939
;
940
;       al destroyed
941
;***************************************************************************
942
 
943
wait_for_cmd_done:
944
 
945
;        mov     edx, [ebx + device.io_addr]
946
 
947
  .loop:
948
	in	al , dx
949
	test	al , al
950
	jnz	.loop
951
 
952
	ret
953
 
954
 
955
 
956
;***************************************************************************
957
;   Function
958
;      mdio_read
959
;
960
;   Description
961
;       This probably reads a register in the "physical media interface chip"
962
;         Phy_id in ebx   NOW EAX
963
;         location in ecx
964
;
965
;       Data returned in eax
966
;
967
;***************************************************************************
968
 
969
mdio_read:
970
 
971
	mov	edx, [ebx + device.io_addr]
972
	add	edx, 16 	; SCBCtrlMDI
973
 
974
;        mov     eax, 0x08000000
975
;        shl     ecx, 16
976
;        or      eax, ecx
977
;        shl     ebx, 21
978
;        or      eax, ebx
979
				   ;
980
	shl	ecx, 16 	   ;
981
	shl	eax, 21 	   ;
982
	or	eax, ecx	   ;
983
	or	eax, 0x08000000    ;
984
	out	dx , eax	   ;
985
				   ;
986
mrlp:
987
	call	delay_us
988
	in	eax, dx
989
	mov	ecx, eax
990
	and	ecx, 0x10000000
991
	jz	mrlp
992
 
993
	and	eax, 0xffff
994
	ret
995
 
996
 
997
 
998
;***************************************************************************
999
;   Function
1000
;      mdio_write
1001
;
1002
;   Description
1003
;       This probably writes a register in the "physical media interface chip"
1004
;         Phy_id in ebx   NOW EAX
1005
;         location in ecx
1006
;         data in edx
1007
;       Data returned in eax
1008
;
1009
;***************************************************************************
1010
 
1011
mdio_write:
1012
 
1013
;        mov     eax, 0x04000000
1014
;        shl     ecx, 16
1015
;        or      eax, ecx
1016
;        shl     ebx, 21
1017
;        or      eax, ebx
1018
;        or      eax, edx
1019
 
1020
	shl	ecx, 16 	  ;
1021
	shl	ebx, 21 	  ;
1022
	or	eax, ecx	  ;
1023
	or	eax, edx	  ;
1024
	or	eax, 0x04000000   ;
1025
 
1026
	mov	edx, [ebx + device.io_addr]
1027
	add	edx, 16 	; SCBCtrlMDI
1028
	out	dx, eax
1029
 
1030
mwlp:
1031
	call	delay_us
1032
	in	eax, dx
1033
	mov	ecx, eax
1034
	and	ecx, 0x10000000
1035
	jz	mwlp
1036
 
1037
	and	eax, 0xffff
1038
	ret
1039
 
1040
 
1041
;***************************************************************************
1042
;   Function
1043
;      do_eeprom_cmd
1044
;
1045
;   Description
1046
;       writes a cmd to the ethernet cards eeprom, by bit bashing
1047
;       cmd in ebx        NOW EAX
1048
;       cmd length in ecx
1049
;       return in eax
1050
;***************************************************************************
1051
 
1052
do_eeprom_cmd:
1053
 
1054
	push	eax
1055
	mov	edx, [ebx + device.io_addr]
1056
	add	dx, 14		  ; the value SCBeeprom
1057
 
1058
	mov	ax, EE_ENB
1059
	out	dx, ax
1060
	call	delay_us
1061
 
1062
	mov	ax, 0x4803	  ; EE_ENB | EE_SHIFT_CLK
1063
	out	dx, ax
1064
	call	delay_us
1065
 
1066
	 ; dx holds ee_addr
1067
	 ; ecx holds count
1068
	 ; eax holds cmd
1069
	xor	edi, edi	  ; this will be the receive data
1070
 
1071
dec_001:
1072
 
1073
	mov	esi, 1
1074
 
1075
	dec	ecx
1076
	shl	esi, cl
1077
	inc	ecx
1078
	and	esi, [esp]
1079
	mov	eax, EE_WRITE_0   ; I am assuming this doesnt affect the flags..
1080
	cmp	esi, 0
1081
	jz	dec_002
1082
	mov	eax, EE_WRITE_1
1083
 
1084
dec_002:
1085
 
1086
	out	dx, ax
1087
	call	delay_us
1088
 
1089
	or	ax, EE_SHIFT_CLK
1090
	out	dx, ax
1091
	call	delay_us
1092
 
1093
	shl	edi,1
1094
 
1095
	in	ax, dx
1096
	and	ax, EE_DATA_READ
1097
	cmp	ax,0
1098
	jz	dec_003
1099
	inc	edi
1100
 
1101
dec_003:
1102
 
1103
	loop	dec_001
1104
 
1105
	mov	ax, EE_ENB
1106
	out	dx, ax
1107
	call	delay_us
1108
 
1109
	mov	ax, 0x4800
1110
	out	dx, ax
1111
	call	delay_us
1112
 
1113
	add	esp, 4
1114
	mov	eax, edi
1115
 
1116
	ret
1117
 
1118
 
1119
 
1120
 
1121
 
1122
; End of code
1123
 
1124
align 4 					; Place all initialised data here
1125
 
1126
I8255x_DEV    dd 0
1127
version       dd (5 shl 16) or (API_VERSION and 0xFFFF)
1128
my_service    db 'I8255x',0			; max 16 chars include zero
1129
devicename    db 'Intel Etherexpress pro/100',0
1130
 
1131
 
1132
 
1133
include_debug_strings				; All data wich FDO uses will be included here
1134
 
1135
section '.data' data readable writable align 16 ; place all uninitialized data place here
1136
 
1137
I8255x_LIST rd I8255x			  ; This list contains all pointers to device structures the driver is handling
1138