-
Notifications
You must be signed in to change notification settings - Fork 1
/
gei82543End.c
6171 lines (4707 loc) · 186 KB
/
gei82543End.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* gei82543End.c - Intel PRO/1000 F/T/XF/XT/MT/MF network adapter END driver */
/* Copyright 1984-2002 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01p,15feb03,jln remove an unnessary cacheInvalidate for RX buffers (spr 86318)
01o,19dec02,jln fix polling mode misalignment (spr 85241)
add PHY's BSP hookup for 82543-copper-based adapter(spr 84779)
01n,05nov02,jln used cacheable memory for RX data buffer (spr 83679)
merge wpaul's RFC2233 poll mode support (spr 84019)
01m,23may02,jln support 82545/82546 fiber-based adapter(spr 78084)
clean interrupts only when packets can be processed
01l,02may02,jln support 82540/82545/82546 based adapters spr # 76739;
stop device only after device has been started spr # 76511
change input argument from vector to unit in SYS_INT_ENABLE
and SYS_INT_DISABLE macros
01k,22apr02,rcs changed gei82543MemAllFree() to use free for
pDrvCtrl->pTxDesCtlBase SPR# 76130
01j,22apr02,rcs removed taskDelay() from gei82543EndPollSend() SPR# 76102
01i,14jan02,dat Removing warnings from Diab compiler
01h,08nov01,jln coding workaround for TBI compatibility HW bug (spr# 71363),
but disable it by default for testing issues.
01g,01sep01,jln clean up documentation
01f,10aug01,jln add support for 82544-based adapters spr# 69774; remove
copying method for transmitting; add support for jumbo
frames spr# 67477
01e,03may01,jln fix memory leak in gei82543EndStop (spr# 67116);
added read operation before exit ISR to flush write buffer
for PCI bridge; polish TX/RX handling
01d,01may01,jln change MACRO(s) GEI_READ_REG, GEI_READ_DESC_WORD, and
GEI_READ_DESC_LONG for coding convention
01c,19apr01,jln clean up for spr#65326
01b,01apr01,jln clean up after code review (partial spr#65326).
01a,08jan01,jln created based on templateEnd.c and fei82557End.c END scheme
*/
/*
DESCRIPTION
The gei82543End driver supports Intel PRO1000 T/F/XF/XT/MT/MF adaptors
These adaptors use Intel 82543GC, 82544GC/EI, or 82540/82545/82546EB Gigabit
Ethernet controllers.The 8254x are highly integrated, high-performance LAN
controllers for 1000/100/10Mb/s transfer rates. They provide 32/64 bit 33/66Mhz
interfaces to the PCI bus with 32/64 bit addressing and are fully compliant
with PCI bus specification version 2.2. The 82544, 82545 and 82546 also
provide PCI-X interface.
The 8254x controllers implement all IEEE 802.3 receive and transmit
MAC functions. They provide a Ten-Bit Interface (TBI) as specified in the IEEE
802.3z standard for 1000Mb/s full-duplex operation with 1.25 GHz Ethernet
transceivers (SERDES), as well as a GMII interface as specified in
IEEE 802.3ab for 10/100/1000 BASE-T transceivers, and also an MII interface as
specified in IEEE 802.3u for 10/100 BASE-T transceivers.
The 8254x controllers offer auto-negotiation capability for TBI and GMII/MII
modes and also support IEEE 802.3x compliant flow control. Although these
devices also support other advanced features such as receive and transmit
IP/TCP/UDP checksum offloading, jumbo frames, and provide flash support up
to 512KB and EEPROM support, this driver does NOT support these features.
The 8254x establishes a shared memory communication system with the
CPU, which is divided into two parts: the control/status registers and the
receive/transmit descriptors/buffers. The control/status registers
are on the 8254x chips and are only accessible with PCI or PCI-X
memory cycles, whereas the other structures reside on the host. The buffer
size can be programmed between 256 bytes to 16k bytes. This driver uses the
receive buffer size of 2048 bytes for an MTU of 1500.
The Intel PRO/1000 F/XF/MF adapters only implement the TBI mode of the
8254x controller with built-in SERDESs in the adaptors.
The Intel PRO/1000 T adapters based on 82543GC implement the GMII mode with
a Gigabit Ethernet Transceiver (PHY) of MARVELL's Alaska 88E1000/88E1000S.
However, the PRO/1000 XT/MT adapters based on 82540/82544/82545/82546 use
the built-in PHY in controllers.
The driver on the current release supports both GMII mode for Intel
PRO1000T/XT/MT adapers and TBI mode for Intel PRO1000 F/XF/MF adapters. However,
it requires the target-specific initialization code (sys543BoardInit ())
to distinguish these kinds of adapters by PCI device IDs.
EXTERNAL INTERFACE
The driver provides the standard external interface, gei82543EndLoad(), which
takes a string of colon separated parameters. The parameter string is parsed
using strtok_r() and each parameter in converted from a string representation
to a binary.
The format of the parameter string is:
"<memBase>:<memSize>:<nRxDes>:<nTxDes>:<flags>:<offset>:<mtu>"
TARGET-SPECIFIC PARAMETERS
.IP <memBase>
This parameter is passed to the driver via gei82543EndLoad().
The 8254x is a DMA-type device and typically shares access to some region of
memory with the CPU. This driver is designed for systems that directly share
memory between the CPU and the 8254x.
This parameter can be used to specify an explicit memory region for use
by the 8254x chip. This should be done on targets that restrict the 8254x
to a particular memory region. The constant `NONE' can be used to indicate
that there are such memory, in which case the driver will allocate cache safe
memory for its use using cacheDmaAlloc().
.IP <memSize>
The memory size parameter specifies the size of the pre-allocated memory
region. The driver checks the size of the provided memory region is adequate
with respect to the given number of transmit Descriptor and Receive
Descriptor.
.IP <nRxDes>
This parameter specifies the number of transmit descriptors to be
allocated. If this number is 0, a default value of 24 will be used.
.IP <nTxDes>
This parameter specifies the number of receive descriptors to be
allocated. If this parameter is 0, a default of 24 is used.
.IP <flags>
This parameter is provided for user to customize this device driver for their
application.
GEI_END_SET_TIMER (0x01): a timer will be started to constantly free back the
loaned transmit mBlks.
GEI_END_SET_RX_PRIORITY (0x02): packet transfer (receive) from device to host
memory will have higher priority than the packet transfer (transmit) from host
memory to device in the PCI bus. For end-station application, it is suggested
to set this priority in favor of receive operation to avoid receive overrun.
However, for routing applications, it is not necessary to use this priority.
This option is only for 82543-based adapters.
GEI_END_FREE_RESOURCE_DELAY (0x04): when transmitting larger packets, the
driver will hold mblks(s) from the network stack and return them after the
driver has completed transmitting the packet, and either the timer has expired
or there are no more available descriptors. If this option is not used, the
driver will free mblk(s) when ever the packet transmission is done. This option
will place greater demands on the network pool and should only be used in
systems which have sufficient memory to allocate a large network pool. It is
not advised for the memory-limited target systems.
GEI_END_TBI_COMPATIBILITY (0x200): if this driver enables the workaround for
TBI compatibility HW bugs (#define INCLUDE_TBI_COMPATIBLE), user can set
this bit to enable a software workaround for the well-known TBI compatibility
HW bug in the Intel PRO1000 T adapter. This bug is only occured in the
copper-and-82543-based adapter, and the link partner has advertised only
1000Base-T capability.
GEI_END_USER_MEM_FOR_DESC_ONLY (0x400): User can provide memory for this driver
through the shMemBase and shMemSize in the load string. By default, this memory
is used for TX/RX descriptors and RX buffer. However, if this flag is set, that
memory will be only used for TX/RX descriptors, and the driver will malloc
other memory for RX buffers and maintain cache coherency for RX buffers. It is
user's resonsibility to maintain the cache coherence for memory they provided.
.IP <offset>
This parameter is provided for the architectures which need DWORD (4 byte)
alignment of the IP header. In that case, the value of OFFSET should be two,
otherwise, the default value is zero.
.LP
EXTERNAL SUPPORT REQUIREMENTS
This driver requires one external support function:
.CS
STATUS sys82543BoardInit (int unit, ADAPTOR_INFO *pBoard)
.CE
This routine performs some target-specific initialization such as EEPROM
validation and obtaining ETHERNET address and initialization control words
(ICWs) from EEPROM. The routine also initializes the adaptor-specific data
structure. Some target-specific functions used later in driver operation
are hooked up to that structure. It's strongly recommended that users provide
a delay function with higher timing resolution. This delay function will be
used in the PHY's read/write operations if GMII is used. The driver will use
taskDelay() by default if user can NOT provide any delay function, and
this will probably result in very slow PHY initialization process. The user
should also specify the PHY's type of MII or GMII. This routine returns OK,
or ERROR if it fails.
.LP
SYSTEM RESOURCE USAGE
The driver uses cacheDmaMalloc() to allocate memory to share with the 8254xGC.
The size of this area is affected by the configuration parameters specified
in the gei82543EndLoad() call.
Either the shared memory region must be non-cacheable, or else the hardware
must implement bus snooping. The driver cannot maintain cache coherency for
the device because fields within the command structures are asynchronously
modified by both the driver and the device, and these fields may share the
same cache line.
SYSTEM TUNING HINTS
Significant performance gains may be had by tuning the system and network stack.
This may be especially necessary for achiving gigabit transfer rates.
Increasing the network stack's pools are strongly recommended. This driver
borrows mblks from the network stack to accerlate packet transmitting.
Theoretically, the number borrowed clusters could be the same as the number of
the device's transmit descriptors. However, if the network stack has fewer
available clusters than available transmit descriptors then this will result
in reduced throughput. Therefore, increasing the network stack's number of
clusters relative to the number of transmit descriptors will increase bandwidth.
Of course this technique will eventually reach a point of diminishing return.
There are actually several sizes of clusters available in the network pool.
Increasing any or all of these cluster sizes will result in some increase in
performance. However, increasing the 2048-byte cluster size will likely have
the greatest impact since this size will hold an entire MTU and header.
Increasing the number of receive descriptors and clusters may also have
positive impact.
Increasing the buffer size of sockets can also be beneficial. This can
significantly improve performance for a target system under higher transfer
rates. However, it should be noted that large amounts of unread buffers idling
in sockets reduces the resources available to the rest of the stack. This can,
in fact, have a negative impact on bandwidth. One method to reduce this effect
is to carefully adjust application tasks' priorities and possibly increase
number of receive clusters.
Callback functions defined in the sysGei82543End.c can be used to dynamically
and/or statically change the internal timer registers such as ITR, RADV, and
RDTR to reduce RX interrupt rate.
INTERNAL
This library contains two conditional compilation switchs: DRV_DEBUG and
INCLUDE_GEI82543_DEBUG_ROUTINE. If defined, debug routines will be included.
And output message can be selected by gei82543GCDebug variable.
SEE ALSO: muxLib, endLib
.I "RS-82543GC GIGABIT ETHERNET CONTROLLER NETWORKING DEVELOPER'S MANUAL"
*/
/* includes */
#include "vxWorks.h"
#include "stdlib.h"
#include "cacheLib.h"
#include "intLib.h"
#include "end.h" /* common END structures. */
#include "endLib.h"
#include "lstLib.h" /* needed to maintain protocol list. */
#include "wdLib.h"
#include "iv.h"
#include "semLib.h"
#include "logLib.h"
#include "netLib.h"
#include "stdio.h"
#include "sysLib.h"
#include "errno.h"
#include "errnoLib.h"
#include "memLib.h"
#include "iosLib.h"
#undef ETHER_MAP_IP_MULTICAST
#include "etherMultiLib.h" /* multicast stuff. */
#include "sys/times.h"
#include "net/mbuf.h"
#include "net/unixLib.h"
#include "net/protosw.h"
#include "net/systm.h"
#include "net/if_subr.h"
#include "net/route.h"
#include "sys/socket.h"
#include "sys/ioctl.h"
#ifdef WR_IPV6
#include "adv_net.h"
#endif /* WR_IPV6 */
#include "drv/end/gei82543End.h"
#define INCLUDE_RFC_1213
/* IMPORT */
IMPORT STATUS sys82543BoardInit (int, ADAPTOR_INFO *);
IMPORT int endMultiLstCnt (END_OBJ* pEnd);
/* defines */
#undef INCLUDE_TBI_COMPATIBLE
/* all 8254x chip registers are 32 bit long*/
#if (_BYTE_ORDER == _BIG_ENDIAN)
#define GEI_READ_REG(offset,result) \
do { \
UINT32 temp; \
temp = ((*(volatile UINT32 *)(pDrvCtrl->devRegBase + (offset)))); \
result = LONGSWAP(temp); /* swap the data */ \
} while (0)
#define GEI_WRITE_REG(offset, value) \
((*(volatile UINT32 *)(pDrvCtrl->devRegBase + (offset))) = \
(UINT32) LONGSWAP(value))
#define GEI_WRITE_DESC_WORD(pDesc, offset, value) \
(*(UINT16 *)((UINT32)pDesc + offset) = \
(MSB(value) | LSB(value)<<8) & 0xffff)
#define GEI_WRITE_DESC_LONG(pDesc, offset, value) \
(*(UINT32 *)((UINT32)pDesc + offset) = \
(UINT32) LONGSWAP(value))
#define GEI_READ_DESC_WORD(pDesc, offset, result) \
do { \
UINT16 temp; \
temp = *(UINT16 *)((UINT32)pDesc + offset); \
result = (MSB(temp) | (LSB(temp) << 8)) & 0xffff; \
} while (0)
#define GEI_READ_DESC_LONG(pDesc, offset, result) \
do { \
UINT32 temp; \
temp = *(UINT32 *)((UINT32)pDesc + offset); \
result = LONGSWAP(temp); /* swap the data */ \
} while (0)
#else /* (_BYTE_ORDER == _BIG_ENDIAN) */
#define GEI_READ_REG(offset, result) \
result = (*(volatile UINT32 *)(pDrvCtrl->devRegBase + (offset)))
#define GEI_WRITE_REG(offset, value) \
((*(volatile UINT32 *)(pDrvCtrl->devRegBase + (offset))) = \
(UINT32)(value))
#define GEI_WRITE_DESC_WORD(pDesc, offset, value) \
(*(UINT16 *)((UINT32)pDesc + offset) = (UINT16)(value & 0xffff))
#define GEI_WRITE_DESC_LONG(pDesc, offset, value) \
(*(UINT32 *)((UINT32)pDesc + offset) = (UINT32)value)
#define GEI_READ_DESC_WORD(pDesc, offset, result) \
result = ((UINT16)(*(UINT16 *)((UINT32)pDesc + offset)) & 0xffff)
#define GEI_READ_DESC_LONG(pDesc, offset, result) \
result = ((UINT32)( *(UINT32 *)((UINT32)pDesc + offset)))
#endif /* (_BYTE_ORDER == _BIG_ENDIAN) */
#define GEI_WRITE_DESC_BYTE(pDesc, offset, value) \
(*(UINT8 *)((UINT32)pDesc + offset) = (UINT8) (value & 0xff))
#define GEI_READ_DESC_BYTE(pDesc, offset) \
((UINT8)( *(UINT8 *)((UINT32)pDesc + offset)) & 0xff)
#define GEI_GET_RX_DESC_ADDR(offset) \
(pDrvCtrl->pRxDescBase + ((offset) * RXDESC_SIZE))
#define GEI_GET_TX_DESC_ADDR(offset) \
(pDrvCtrl->pTxDescBase + ((offset) * TXDESC_SIZE))
#define GEI_GET_TX_DESC_CTL_ADDR(offset) \
(pDrvCtrl->pTxDesCtlBase + (offset));
#define GEI_GET_TX_DESC_TAIL_UPDATE(tmp, num) \
(tmp) = (pDrvCtrl->txDescTail + (num)) % (pDrvCtrl->txDescNum)
#define GEI_GET_RX_DESC_TAIL_UPDATE(tmp, num) \
(tmp) = (pDrvCtrl->rxDescTail + (num)) % (pDrvCtrl->rxDescNum)
#define ROUND_UP_MULTIPLE(x, y) \
( ( ( x + ( y - 1 ) ) / y ) * y )
/* bus/CPU address translation macros */
#define GEI_VIRT_TO_BUS(virtAddr) \
(GEI_PHYS_TO_BUS (((UINT32) GEI_VIRT_TO_PHYS (virtAddr))))
#define GEI_PHYS_TO_VIRT(physAddr) \
END_CACHE_PHYS_TO_VIRT ((char *)(physAddr))
#define GEI_VIRT_TO_PHYS(virtAddr) \
END_CACHE_VIRT_TO_PHYS ((char *)(virtAddr))
#define GEI_PHYS_TO_BUS(physAddr) \
PHYS_TO_BUS_ADDR (pDrvCtrl->unit, (physAddr))
#define GEI_BUS_TO_PHYS(busAddr) \
BUS_TO_PHYS_ADDR (pDrvCtrl->unit, (busAddr))
/* cache macros */
#define END_USR_CACHE_FLUSH(address, len) \
CACHE_DRV_FLUSH (&cacheUserFuncs, (address), (len))
#define END_DRV_CACHE_INVALIDATE(address, len) \
CACHE_DRV_INVALIDATE (pDrvCtrl->pCacheFuncs, (address), (len))
#define END_CACHE_PHYS_TO_VIRT(address) \
CACHE_DRV_PHYS_TO_VIRT (&cacheDmaFuncs, (address))
#define END_CACHE_VIRT_TO_PHYS(address) \
CACHE_DRV_VIRT_TO_PHYS (&cacheDmaFuncs, (address))
/* misc. */
#define GEI_DESC_ALIGN_BYTE (128)
/*
* Default macro definitions for BSP interface.
* These macros can be redefined in a wrapper file, to generate
* a new module with an optimized interface.
*/
/* macro to connect interrupt handler to vector */
#ifndef SYS_INT_CONNECT
#define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) \
{ \
*pResult = OK; \
if (pDrvCtrl->adaptor.intConnect) \
*pResult = (pDrvCtrl->adaptor.intConnect) ((VOIDFUNCPTR *) \
INUM_TO_IVEC (pDrvCtrl->adaptor.vector), \
rtn, (int)arg); \
}
#endif
/* macro to disconnect interrupt handler from vector */
#ifndef SYS_INT_DISCONNECT
#define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) \
{ \
*pResult = OK; \
if (pDrvCtrl->adaptor.intDisConnect) \
*pResult = (pDrvCtrl->adaptor.intDisConnect) ((VOIDFUNCPTR *) \
INUM_TO_IVEC (pDrvCtrl->adaptor.vector), \
rtn, (int)arg); \
}
#endif
/* macro to enable the appropriate interrupt level */
#ifndef SYS_INT_ENABLE
#define SYS_INT_ENABLE(pDrvCtrl) \
{ \
pDrvCtrl->adaptor.intEnable(pDrvCtrl->unit); \
}
#endif
#ifndef SYS_INT_DISABLE
#define SYS_INT_DISABLE(pDrvCtrl) \
{ \
pDrvCtrl->adaptor.intDisable(pDrvCtrl->unit); \
}
#endif
/*
* a shortcut for getting the hardware address
* from the MIB II stuff.
*/
#ifdef INCLUDE_RFC_1213
#define END_HADDR(pEnd) \
((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
#define END_HADDR_LEN(pEnd) \
((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
#else /* !INCLUDE_RFC_1213 */
#define END_HADDR(pEnd) \
((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.phyAddress)
#define END_HADDR_LEN(pEnd) \
((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.addrLength)
#endif /* INCLUDE_RFC_1213 */
/* device structure */
typedef struct end_device
{
END_OBJ end; /* the class we inherit from. */
int unit; /* unit number */
UINT32 flags; /* flags for device configuration */
UINT32 usrFlags; /* flags for user customization */
CACHE_FUNCS * pCacheFuncs; /* cache function pointers */
CL_POOL_ID pClPoolId; /* cluster pool ID */
ADAPTOR_INFO adaptor; /* adaptor information */
UINT32 devRegBase; /* virtual base address for registers */
P_TX_DESCTL pTxDesCtlBase; /* pointer to the TX management array base */
char *pTxDescBase; /* pointer to the TX descriptor base */
char *pRxDescBase; /* pointer to the RX descriptor base */
char * pRxBufBase; /* pointer to the RX buffer base */
volatile int txDescTail; /* index to the TX tail */
volatile int rxDescTail; /* index to the RX tail */
int txDescNum; /* num of TX descriptors */
int rxDescNum; /* num of RX descriptors */
UINT32 rxBufSize; /* RX buffer size */
UINT32 txReqDescNum; /* request number for TX descriptor */
int mtu; /* maximum transfer unit */
volatile int rxtxHandling; /* indicator for RX handling */
volatile BOOL txStall; /* indicator for transmit stall */
volatile BOOL txDescResChk; /* indicator for checking TX descriptor */
char * pRxBufMem; /* allocated Rx Buffer memory pointer*/
UINT32 rxPktSz; /* MRU + offset */
UINT32 clSz; /* cluster size for RX buffer */
int txIntDelay; /* delay time for TX interrupt */
int rxIntDelay; /* delay time for RX interrupt */
int maxRxNumPerInt; /* maximum RX packets processed per Int */
BOOL dmaPriority; /* indicator for TX/RX DMA prefer */
UINT32 timerInterval; /* interval for timer interrupt */
BOOL timerCheckTxStall; /* indicator for txStall checking */
UINT32 multiCastFilterType; /* indicator of multicast table type */
int flowCtrl; /* flow control setting */
STATUS linkInitStatus; /* the status of first link */
volatile UINT32 linkStatus; /* indicator for link status */
BOOL linkMethod; /* indicator for link approaches */
WDOG_ID timerId; /* timer ID */
UINT32 txConfigureWord; /* copy of TX configuration word register */
UINT32 devCtrlRegVal; /* control register value */
UINT32 speed; /* device speed */
UINT32 duplex; /* device duplex mode */
UINT32 offset; /* offset for IP header */
UINT32 cableType; /* cable type (Fiber or Copper) */
BOOL memAllocFlag; /* indicator that the shared memory */
/* allocated by driver */
char * pMemBase; /* memory base for TX/RX area */
int memSize; /* total memory size for RX/TX area */
char * pMclkArea; /* address of Mclk */
char * pTxPollBufAdr; /* address for TX buffer in polling mode */
PHY_INFO * pPhyInfo; /* pointer to phyInfo structure */
UINT32 phyInitFlags; /* Initial PHY flags for phyInfo */
volatile UINT32 txDescLastCheck; /* index of the last checked TX desc */
volatile UINT32 txDescFreeNum; /* available/usable TX desc number */
char ** pRxBufVirtAddr; /* pointer to Rx Buf Virtual Adr array */
BOOL txResoFreeQuick; /* flag to free loaned mBlk quickly */
volatile BOOL attach; /* indicator for drive attach */
volatile BOOL devStartFlag; /* indicator for device start */
UINT32 rxtxHandlerNum; /* num of rxtx handler calling */
UINT32 rxIntCount; /* receive interrupt count */
UINT32 txIntCount; /* transmit interrupt count */
UINT32 rxORunIntCount; /* num of RX overrun interrupt count */
UINT32 rxPacketNum; /* statistic RX packet number */
UINT32 rxPacketDrvErr ; /* num of RX packet drop due to no resc */
#ifdef INCLUDE_TBI_COMPATIBLE
BOOL tbiCompatibility; /* TBI compatibility for HW bug */
#endif
STA_REG staRegs; /* statistic register structure */
#ifndef INCLUDE_RFC_1213
END_IFDRVCONF endStatsConf;
END_IFCOUNTERS endStatsCounters;
#endif /* INCLUDE_RFC_1213 */
} END_DEVICE;
/* DEBUG MACROS */
#undef GEI82543_NO_LOCAL
#if 1
#undef DRV_DEBUG
#undef INCLUDE_GEI82543_DEBUG_ROUTINE
#else
#define DEBUG
#define DRV_DEBUG
#define INCLUDE_GEI82543_DEBUG_ROUTINE
#endif
#ifdef DEBUG
#define LOGMSG(x,a,b,c,d,e,f) \
if (/*endDebug*/1) \
{ \
logMsg (x,a,b,c,d,e,f); \
}
#else
#define LOGMSG(x,a,b,c,d,e,f)
#endif /* DEBUG */
#ifdef GEI82543_NO_LOCAL
#undef LOCAL
#define LOCAL
#endif
/*#define DRV_DEBUG*/
#ifdef DRV_DEBUG
#define DRV_DEBUG_OFF 0x0000
#define DRV_DEBUG_RX 0x0001
#define DRV_DEBUG_TX 0x0002
#define DRV_DEBUG_INT 0x0004
#define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
#define DRV_DEBUG_POLL_RX 0x0008
#define DRV_DEBUG_POLL_TX 0x0010
#define DRV_DEBUG_LOAD 0x0020
#define DRV_DEBUG_IOCTL 0x0040
#define DRV_DEBUG_TIMER 0x20000
int gei82543GCDebug = 0xffffffff; /*wangfq*/
#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
if (gei82543GCDebug & FLG) \
logMsg(X0, X1, X2, X3, X4, X5, X6);
#define DRV_PRINT(FLG,X) \
if (gei82543GCDebug & FLG) printf X;
#else /* DRV_DEBUG */
#define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
#define DRV_PRINT(DBG_SW,X)
#endif /* DRV_DEBUG */
#ifdef INCLUDE_GEI82543_DEBUG_ROUTINE
LOCAL void gei82543LedOff (int);
LOCAL void gei82543LedOn (int);
LOCAL void gei82543StatusShow (int);
LOCAL UINT32 gei82543RegGet (int,UINT32);
LOCAL void gei82543RegSet (int,UINT32, UINT32);
#ifdef INCLUDE_TBI_COMPATIBLE
LOCAL void gei82543TbiCompWr (int, int);
#endif /* INCLUDE_TBI_COMPATIBLE */
#endif /* INCLUDE_GEI82543_DEBUG_ROUTINE */
/* forward functions */
LOCAL void gei82543EndTimerHandler (END_DEVICE *);
LOCAL void gei82543MemAllFree (END_DEVICE *);
LOCAL STATUS gei82543linkStatusCheck (END_DEVICE *);
LOCAL void gei82543TxRxEnable (END_DEVICE *);
LOCAL void gei82543TxRxDisable (END_DEVICE *);
LOCAL void gei82543Delay (END_DEVICE *, UINT32);
LOCAL void gei82543RxSetup (END_DEVICE *);
LOCAL void gei82543TxSetup (END_DEVICE *);
LOCAL STATUS gei82543HwInit (END_DEVICE *);
LOCAL void gei82543RxDesUpdate (END_DEVICE *,char *);
LOCAL void gei82543DuplexGet (END_DEVICE *);
LOCAL void gei82543SpeedGet (END_DEVICE *);
LOCAL void gei82543HwStatusDump (END_DEVICE *);
LOCAL STATUS gei82543linkInit (END_DEVICE *);
LOCAL STATUS gei82543linkTBISetup (END_DEVICE *,BOOL);
LOCAL STATUS gei82543TBIlinkForce (END_DEVICE *,BOOL, BOOL);
LOCAL STATUS gei82543TBIHwAutoNegotiate (END_DEVICE *,BOOL, BOOL);
LOCAL void gei82543EtherRxAdrSet (END_DEVICE *,UINT8 adr[],int);
LOCAL void gei82543AllRxAdrClean (END_DEVICE *);
LOCAL void gei82543McastAdrClean (END_DEVICE *);
LOCAL void gei82543AllMtaAdrClean (END_DEVICE *);
LOCAL void gei82543AllVlanClean (END_DEVICE *);
LOCAL UINT32 gei82543DisableChipInt (END_DEVICE *);
LOCAL void gei82543EnableChipInt (END_DEVICE *);
LOCAL void gei82543Reset (END_DEVICE *);
LOCAL void gei82543TxMblkFree (END_DEVICE *,int);
LOCAL void gei82543TxMblkWaitClean (END_DEVICE *);
LOCAL STATUS gei82543EndMCastAdd (END_DEVICE *,char*);
LOCAL STATUS gei82543EndMCastDel (END_DEVICE *,char*);
LOCAL STATUS gei82543EndMCastGet (END_DEVICE *,MULTI_TABLE*);
LOCAL void gei82543EndInt (END_DEVICE *);
LOCAL void gei82543RxTxIntHandle (END_DEVICE *);
LOCAL STATUS gei82543Recv (END_DEVICE *,char *, UINT8);
LOCAL void gei82543EndConfigure (END_DEVICE *);
LOCAL void gei82543FlowCtrlRegsSet (END_DEVICE *);
LOCAL STATUS gei82543PhyWrite (END_DEVICE *,UINT8,UINT8,UINT16);
LOCAL STATUS gei82543PhyRead (END_DEVICE *,UINT8,UINT8,
UINT16 *);
LOCAL STATUS gei82544PhyWrite (END_DEVICE *,UINT8,UINT8,UINT16);
LOCAL STATUS gei82544PhyRead (END_DEVICE *,UINT8,UINT8,
UINT16 *);
LOCAL void gei82543LoanTransmit (END_DEVICE *,M_BLK_ID);
LOCAL void gei82543TxResoFree (END_DEVICE *);
LOCAL int gei82543TxDesCleanGet (END_DEVICE *,int);
LOCAL UINT32 gei82543TxStallCheck (END_DEVICE *);
LOCAL void gei82543GMIIphyConfig (END_DEVICE *);
LOCAL void gei82543GMIIphyReConfig (END_DEVICE *);
LOCAL STATUS gei82543linkGMIISetup (END_DEVICE *);
LOCAL STATUS gei82543linkGMIIPreInit (END_DEVICE *);
#ifndef INCLUDE_RFC_1213
LOCAL STATUS gei82543EndStatsDump (END_DEVICE *);
#endif /* INCLUDE_RFC_1213 */
/* END specific interfaces. */
/* This is the only externally visible interface. */
END_OBJ* gei82543EndLoad (char* initString);
LOCAL STATUS gei82543EndStart (END_DEVICE* pDrvCtrl);
LOCAL STATUS gei82543EndStop (END_DEVICE* pDrvCtrl);
LOCAL int gei82543EndIoctl (END_DEVICE* pDrvCtrl, int cmd,
caddr_t data);
LOCAL STATUS gei82543EndUnload (END_DEVICE* pDrvCtrl);
LOCAL STATUS gei82543EndSend (END_DEVICE* pDrvCtrl,
M_BLK_ID pBuf);
LOCAL STATUS gei82543EndMCastAdd (END_DEVICE* pDrvCtrl,
char* pAddress);
LOCAL STATUS gei82543EndMCastDel (END_DEVICE* pDrvCtrl,
char* pAddress);
LOCAL STATUS gei82543EndMCastGet (END_DEVICE* pDrvCtrl,
MULTI_TABLE* pTable);
LOCAL STATUS gei82543EndPollStart (END_DEVICE* pDrvCtrl);
LOCAL STATUS gei82543EndPollStop (END_DEVICE* pDrvCtrl);
LOCAL STATUS gei82543EndPollSend (END_DEVICE* pDrvCtrl,
M_BLK_ID pBuf);
LOCAL STATUS gei82543EndPollRcv (END_DEVICE* pDrvCtrl,
M_BLK_ID pBuf);
LOCAL void gei82543AddrFilterSet (END_DEVICE* pDrvCtrl);
LOCAL STATUS gei82543EndParse (END_DEVICE*, char *);
LOCAL STATUS gei82543EndMemInit (END_DEVICE*);
/*
* Declare our function table. This is LOCAL across all driver
* instances.
*/
LOCAL NET_FUNCS gei82543EndFuncTable =
{
(FUNCPTR) gei82543EndStart, /* Function to start the device. */
(FUNCPTR) gei82543EndStop, /* Function to stop the device. */
(FUNCPTR) gei82543EndUnload, /* Unloading function for the driver. */
(FUNCPTR) gei82543EndIoctl, /* Ioctl function for the driver. */
(FUNCPTR) gei82543EndSend, /* Send function for the driver. */
(FUNCPTR) gei82543EndMCastAdd, /* Multicast add function for the */
/* driver. */
(FUNCPTR) gei82543EndMCastDel, /* Multicast delete function for */
/* the driver. */
(FUNCPTR) gei82543EndMCastGet, /* Multicast retrieve function for */
/* the driver. */
(FUNCPTR) gei82543EndPollSend, /* Polling send function */
(FUNCPTR) gei82543EndPollRcv, /* Polling receive function */
endEtherAddressForm, /* put address info into a NET_BUFFER */
endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
endEtherPacketAddrGet /* Get packet addresses. */
};
/*************************************************************************
*
* gei82543EndLoad - initialize the driver and device
*
* This routine initializes the driver and the device to the operational state.
* All of the device specific parameters are passed in the initString.
*
* The string contains the target specific parameters like this:
* "unitnum:shmem_addr:shmem_size:rxDescNum:txDescNum:usrFlags:offset:mtu"
*
* RETURNS: an END object pointer, NULL if error, or zero
*/
END_OBJ* gei82543EndLoad
(
char *initString /* String to be parsed by the driver. */
)
{
END_DEVICE *pDrvCtrl = NULL; /* pointer to device structure */
/*printf("in gei82543EndLoad\n");*/
DRV_LOG (DRV_DEBUG_LOAD, "Loading gei82543End Driver...\n",
1, 2, 3, 4, 5, 6);
/* sanity check */
if (initString == NULL)
return NULL;
if (initString[0] == 0)
{
bcopy ((char *) DEVICE_NAME, (void *)initString, DEVICE_NAME_LENGTH);
return 0;
}
/* allocate the device structure */
pDrvCtrl = (END_DEVICE *)calloc (sizeof (END_DEVICE), 1);
if (pDrvCtrl == NULL)
goto errorExit;
/* clean up driver structure */
memset((void *)pDrvCtrl, 0, sizeof (END_DEVICE));
/* parse the init string, filling in the device structure */
if (gei82543EndParse (pDrvCtrl, initString) == ERROR)
goto errorExit;
/* zero adaptor structure */
memset ((void *)&pDrvCtrl->adaptor, 0, sizeof(ADAPTOR_INFO));
/* call BSP routine to get PCI information*/
if (sys82543BoardInit (pDrvCtrl->unit, &pDrvCtrl->adaptor) != OK)
{
DRV_LOG (DRV_DEBUG_LOAD, "Error in getting board info\n",
1, 2, 3, 4, 5, 6);
goto errorExit;
}
/* set up the base register */
pDrvCtrl->devRegBase = (UINT32)(pDrvCtrl->adaptor.regBaseLow);
/* set up device structure based on user's flags */
if (pDrvCtrl->usrFlags & GEI_END_JUMBO_FRAME_SUPPORT)
{
if (pDrvCtrl->mtu <= 0)
pDrvCtrl->mtu = GEI_DEFAULT_JUMBO_MTU_SIZE;
pDrvCtrl->mtu = (pDrvCtrl->mtu <= ETHERMTU)? ETHERMTU :
((pDrvCtrl->mtu > GEI_MAX_JUMBO_MTU_SIZE)?
GEI_MAX_JUMBO_MTU_SIZE : pDrvCtrl->mtu);
}
else /* normal frame */
pDrvCtrl->mtu = ETHERMTU;
/* increase transmit storage in FIFO for jumbo frames */
if (pDrvCtrl->mtu > ETHERMTU)
{
GEI_WRITE_REG(INTEL_82543GC_PBA, 0x20); /* 24KB for TX buffer */
}
/* perform memory allocation for descriptors */
if (gei82543EndMemInit (pDrvCtrl) == ERROR)
goto errorExit;
/* set up device structure based on user's flags */
if (pDrvCtrl->usrFlags & GEI_END_SET_TIMER)
{
pDrvCtrl->timerId = wdCreate ();
if (pDrvCtrl->timerId == NULL)
DRV_LOG (DRV_DEBUG_LOAD, ("create timer fails\n"),
1, 2, 3, 4, 5, 6);
}
if (pDrvCtrl->usrFlags & GEI_END_SET_RX_PRIORITY)
pDrvCtrl->dmaPriority = DMA_RX_PRIORITY;
else
pDrvCtrl->dmaPriority = DMA_FAIR_RX_TX;
if (pDrvCtrl->usrFlags & GEI_END_FREE_RESOURCE_DELAY)
{
pDrvCtrl->txIntDelay = TXINT_DELAY_MORE;
pDrvCtrl->txResoFreeQuick = FALSE;
}
else
{
pDrvCtrl->txIntDelay = TXINT_DELAY_LESS;
pDrvCtrl->txResoFreeQuick = TRUE;
}
#ifdef INCLUDE_TBI_COMPATIBLE
pDrvCtrl->tbiCompatibility = FALSE;
#endif /* INCLUDE_TBI_COMPATIBLE */
/* stop/reset the chip before configuration */
gei82543Reset (pDrvCtrl);
/* disable all chip interrupt */
gei82543DisableChipInt (pDrvCtrl);
/* turn off system interrupts */
SYS_INT_DISABLE(pDrvCtrl);
/* set the default value for device */
pDrvCtrl->rxIntDelay = DEFAULT_RXINT_DELAY;
pDrvCtrl->maxRxNumPerInt = DEFAULT_RXRES_PROCESS_FACTOR *
pDrvCtrl->rxDescNum;
pDrvCtrl->timerInterval = DEFAULT_TIMER_INTERVAL;
pDrvCtrl->flowCtrl = DEFAULT_FLOW_CONTRL;
pDrvCtrl->duplex = DEFAULT_DUPLEX_MODE;
/* Misc. setting */
pDrvCtrl->flags = 0;
pDrvCtrl->linkStatus = LINK_STATUS_UNKNOWN;
pDrvCtrl->linkMethod = GEI82543_HW_AUTO;
pDrvCtrl->txConfigureWord = (TXCW_ANE_BIT | TXCW_FD_BIT);
pDrvCtrl->multiCastFilterType = DEFAULT_MULTI_FILTER_TYPE;
pDrvCtrl->attach = FALSE;
pDrvCtrl->devStartFlag = FALSE;
/* initialize the END and MIB2 parts of the structure */
/*
* The M2 element must come from m2Lib.h
* This setting is for a DIX type ethernet device.
*/
#ifdef INCLUDE_RFC_1213
if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, DEVICE_NAME,
pDrvCtrl->unit, &gei82543EndFuncTable,
"gei82543End Driver.") == ERROR ||
END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
&pDrvCtrl->adaptor.enetAddr[0], 6, pDrvCtrl->mtu,
END_SPEED) == ERROR )
goto errorExit;
#else /* !INCLUDE_RFC_1213 */
bzero ((char *)&pDrvCtrl->endStatsCounters, sizeof(END_IFCOUNTERS));
pDrvCtrl->endStatsConf.ifPollInterval = sysClkRateGet();
pDrvCtrl->endStatsConf.ifEndObj = &pDrvCtrl->end;
pDrvCtrl->endStatsConf.ifWatchdog = NULL;
pDrvCtrl->endStatsConf.ifValidCounters = (END_IFINUCASTPKTS_VALID |
END_IFINMULTICASTPKTS_VALID | END_IFINBROADCASTPKTS_VALID |
END_IFINOCTETS_VALID | END_IFOUTOCTETS_VALID | END_IFOUTUCASTPKTS_VALID |
END_IFOUTMULTICASTPKTS_VALID | END_IFOUTBROADCASTPKTS_VALID);
if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, DEVICE_NAME,
pDrvCtrl->unit, &gei82543EndFuncTable,
"gei82543End Driver.") == ERROR)
goto errorExit;
/* New RFC 2233 mib2 interface */
/* Initialize MIB-II entries (for RFC 2233 ifXTable) */
pDrvCtrl->end.pMib2Tbl = m2IfAlloc(M2_ifType_ethernet_csmacd,
(UINT8*) &pDrvCtrl->adaptor.enetAddr[0], 6,
pDrvCtrl->mtu, 1000000000,
"gei", pDrvCtrl->unit);
if (pDrvCtrl->end.pMib2Tbl == NULL)
{
DRV_LOG (DRV_DEBUG_LOAD, ("%s%d - MIB-II initializations failed\n"),
"gei", pDrvCtrl->unit, 3, 4, 5, 6);
goto errorExit;
}
/*
* Set the RFC2233 flag bit in the END object flags field and
* install the counter update routines.
*/
m2IfPktCountRtnInstall(pDrvCtrl->end.pMib2Tbl, m2If8023PacketCount);
/*
* Make a copy of the data in mib2Tbl struct as well. We do this
* mainly for backward compatibility issues. There might be some
* code that might be referencing the END pointer and might
* possibly do lookups on the mib2Tbl, which will cause all sorts
* of problems.
*/
bcopy ((char *)&pDrvCtrl->end.pMib2Tbl->m2Data.mibIfTbl,
(char *)&pDrvCtrl->end.mib2Tbl, sizeof (M2_INTERFACETBL));
END_OBJ_READY (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS |
IFF_BROADCAST | IFF_MULTICAST | END_MIB_2233));
#endif /* INCLUDE_RFC_1213 */
/* disable RX/TX operations now, will be re-enable in Start function */
gei82543TxRxDisable (pDrvCtrl);
pDrvCtrl->attach = TRUE;
DRV_LOG (DRV_DEBUG_LOAD, ("loading gei82543End...OK\n"),1,2,3,4,5,6);
/* printf("loading gei82543End...OK\n"); */
return (&pDrvCtrl->end);
errorExit:
/* free all allocated memory */
gei82543MemAllFree (pDrvCtrl);
if (pDrvCtrl != NULL)
free ((char *)pDrvCtrl);
DRV_LOG (DRV_DEBUG_LOAD, ("Loading gei82543End...Error\n"),
1, 2, 3, 4, 5, 6);
return NULL;
}
/*************************************************************************
*
* gei82534EndParse - parse the init string
*
* Parse the input string. Fill in values in the driver control structure.
*
* RETURNS: OK or ERROR for invalid arguments.
*/
LOCAL STATUS gei82543EndParse
(
END_DEVICE * pDrvCtrl, /* device pointer */
char * initString /* information string */
)
{
char * tok;
char * pHolder = NULL;
/*printf("in gei82543EndParse\n");*/
DRV_LOG (DRV_DEBUG_LOAD, ("gei82543EndParse...\n"), 1, 2, 3, 4, 5, 6);
/* parse the initString */
tok = strtok_r (initString, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->unit = atoi (tok);
/* address of shared memory */