Subversion Repositories Kolibri OS

Rev

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