summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/nge/nge.h
blob: ca83273109cd293503efc50ee247691338327399 (plain)
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_NGE_H
#define	_SYS_NGE_H

#ifdef __cplusplus
extern "C" {
#endif


#include <sys/types.h>
#include <sys/stream.h>
#include <sys/strsun.h>
#include <sys/strsubr.h>
#include <sys/stat.h>
#include <sys/pci.h>
#include <sys/note.h>
#include <sys/modctl.h>
#include <sys/kstat.h>
#include <sys/ethernet.h>
#include <sys/pattr.h>
#include <sys/errno.h>
#include <sys/dlpi.h>
#include <sys/devops.h>
#include <sys/debug.h>
#include <sys/conf.h>
#include <sys/callb.h>

#include <netinet/ip6.h>

#include <inet/common.h>
#include <inet/ip.h>
#include <netinet/udp.h>
#include <inet/mi.h>
#include <inet/nd.h>

#include <sys/ddi.h>
#include <sys/sunddi.h>

#include <sys/mac_provider.h>
#include <sys/mac_ether.h>

/*
 * Reconfiguring the network devices requires the net_config privilege
 * in Solaris 10+.
 */
extern int secpolicy_net_config(const cred_t *, boolean_t);

#include <sys/netlb.h>
#include <sys/miiregs.h>

#include "nge_chip.h"

#define	PIO_ADDR(ngep, offset)	((void *)((caddr_t)(ngep)->io_regs+(offset)))
/*
 * Copy an ethernet address
 */
#define	ethaddr_copy(src, dst)	bcopy((src), (dst), ETHERADDRL)
#define	ether_eq(a, b) (bcmp((caddr_t)(a), (caddr_t)(b), (ETHERADDRL)) == 0)

#define	BIS(w, b)	(((w) & (b)) ? B_TRUE : B_FALSE)
#define	BIC(w, b)	(((w) & (b)) ? B_FALSE : B_TRUE)
#define	UPORDOWN(x)	((x) ? "up" : "down")

#define	NGE_DRIVER_NAME		"nge"

/*
 * 'Progress' bit flags ...
 */
#define	PROGRESS_CFG		0x0001	/* config space mapped		*/
#define	PROGRESS_REGS		0x0002	/* registers mapped		*/
#define	PROGRESS_BUFS		0x0004	/* registers mapped		*/
#define	PROGRESS_RESCHED	0x0008	/* resched softint registered	*/
#define	PROGRESS_FACTOTUM	0x0010	/* factotum softint registered	*/
#define	PROGRESS_SWINT		0x0020	/* s/w interrupt registered	*/
#define	PROGRESS_INTR		0x0040	/* h/w interrupt registered	*/
					/* and mutexen initialised	*/
#define	PROGRESS_HWINT		0x0080
#define	PROGRESS_PHY		0x0100	/* PHY initialised		*/
#define	PROGRESS_NDD		0x0200	/* NDD parameters set up	*/
#define	PROGRESS_KSTATS		0x0400	/* kstats created		*/
#define	PROGRESS_READY		0x0800	/* ready for work		*/

#define	NGE_HW_ERR		0x00
#define	NGE_HW_LINK		0x01
#define	NGE_HW_BM		0x02
#define	NGE_HW_RCHAN		0x03
#define	NGE_HW_TCHAN		0x04
#define	NGE_HW_ROM		0x05
#define	NGE_SW_PROBLEM_ID	0x06


/*
 * NOTES:
 *
 * #defines:
 *
 *	NGE_PCI_CONFIG_RNUMBER and NGE_PCI_OPREGS_RNUMBER are the
 *	register-set numbers to use for the config space registers
 *	and the operating registers respectively.  On an OBP-based
 *	machine, regset 0 refers to CONFIG space, and regset 1 will
 *	be the operating registers in MEMORY space.  If an expansion
 *	ROM is fitted, it may appear as a further register set.
 *
 *	NGE_DMA_MODE defines the mode (STREAMING/CONSISTENT) used
 *	for the data buffers.  The descriptors are always set up
 *	in CONSISTENT mode.
 *
 *	NGE_HEADROOM defines how much space we'll leave in allocated
 *	mblks before the first valid data byte.  This should be chosen
 *	to be 2 modulo 4, so that once the ethernet header (14 bytes)
 *	has been stripped off, the packet data will be 4-byte aligned.
 *	The remaining space can be used by upstream modules to prepend
 *	any headers required.
 */


#define	NGE_PCI_OPREGS_RNUMBER	1
#define	NGE_DMA_MODE		DDI_DMA_STREAMING
#define	NGE_HEADROOM		6
#define	ETHER_HEAD_LEN		14
#ifndef	VTAG_SIZE
#define	VTAG_SIZE		4
#endif

#define	NGE_CYCLIC_PERIOD	(1000000000)

#define	NGE_DEFAULT_MTU		1500
#define	NGE_DEFAULT_SDU		1518
#define	NGE_MTU_2500		2500
#define	NGE_MTU_4500		4500
#define	NGE_MAX_MTU		9000
#define	NGE_MAX_SDU		9018

#define	NGE_DESC_MIN		0x200

#define	NGE_STD_BUFSZ		1792
#define	NGE_JB2500_BUFSZ	(3*1024)
#define	NGE_JB4500_BUFSZ	(5*1024)
#define	NGE_JB9000_BUFSZ	(9*1024)

#define	NGE_SEND_SLOTS_DESC_1024	1024
#define	NGE_SEND_SLOTS_DESC_3072	3072
#define	NGE_SEND_JB2500_SLOTS_DESC	3072
#define	NGE_SEND_JB4500_SLOTS_DESC	2048
#define	NGE_SEND_JB9000_SLOTS_DESC	1024
#define	NGE_SEND_LOWMEM_SLOTS_DESC	1024
#define	NGE_SEND_SLOTS_BUF		3072

#define	NGE_RECV_SLOTS_DESC_1024	1024
#define	NGE_RECV_SLOTS_DESC_3072	3072
#define	NGE_RECV_JB2500_SLOTS_DESC	3072
#define	NGE_RECV_JB4500_SLOTS_DESC	2048
#define	NGE_RECV_JB9000_SLOTS_DESC	1024
#define	NGE_RECV_LOWMEM_SLOTS_DESC	1024
#define	NGE_RECV_SLOTS_BUF		6144

#define	NGE_SPLIT_32		32
#define	NGE_SPLIT_96		96
#define	NGE_SPLIT_256		256

#define	NGE_RX_COPY_SIZE	512
#define	NGE_TX_COPY_SIZE	512
#define	NGE_MAP_FRAGS		3
#define	NGE_MAX_COOKIES		3
#define	NGE_MAX_DMA_HDR		(4*1024)

/* Used by interrupt moderation */
#define	NGE_TFINT_DEFAULT	32
#define	NGE_POLL_TUNE		80000
#define	NGE_POLL_ENTER		10000
#define	NGE_POLL_MAX		1280000
#define	NGE_POLL_QUIET_TIME	100
#define	NGE_POLL_BUSY_TIME	2

/*
 * NGE-specific ioctls ...
 */
#define	NGE_IOC			((((('N' << 8) + 'G') << 8) + 'E') << 8)

/*
 * PHY register read/write ioctls, used by cable test software
 */
#define	NGE_MII_READ		(NGE_IOC|1)
#define	NGE_MII_WRITE		(NGE_IOC|2)

/*
 * SEEPROM read/write ioctls, for use by SEEPROM upgrade utility
 *
 * Note: SEEPROMs can only be accessed as 32-bit words, so <see_addr>
 * must be a multiple of 4.  Not all systems have a SEEPROM fitted!
 */
#define	NGE_SEE_READ		(NGE_IOC|3)
#define	NGE_SEE_WRITE		(NGE_IOC|4)


/*
 * These diagnostic IOCTLS are enabled only in DEBUG drivers
 */
#define	NGE_DIAG		(NGE_IOC|5)	/* currently a no-op	*/
#define	NGE_PEEK		(NGE_IOC|6)
#define	NGE_POKE		(NGE_IOC|7)
#define	NGE_PHY_RESET		(NGE_IOC|8)
#define	NGE_SOFT_RESET		(NGE_IOC|9)
#define	NGE_HARD_RESET		(NGE_IOC|10)


enum NGE_HW_OP {
	NGE_CLEAR = 0,
	NGE_SET
};

/*
 * Required state according to GLD
 */
enum nge_mac_state {
	NGE_MAC_UNKNOWN,
	NGE_MAC_RESET,
	NGE_MAC_STOPPED,
	NGE_MAC_STARTED,
	NGE_MAC_UNATTACH
};
enum loop_type {
	NGE_LOOP_NONE = 0,
	NGE_LOOP_EXTERNAL_100,
	NGE_LOOP_EXTERNAL_10,
	NGE_LOOP_INTERNAL_PHY,
};

/*
 * (Internal) return values from send_msg subroutines
 */
enum send_status {
	SEND_COPY_FAIL = -1,		/* => GLD_NORESOURCES	*/
	SEND_MAP_FAIL,			/* => GLD_NORESOURCES	*/
	SEND_COPY_SUCESS,		/* OK, msg queued	*/
	SEND_MAP_SUCCESS		/* OK, free msg		*/
};

/*
 * (Internal) return values from ioctl subroutines
 */
enum ioc_reply {
	IOC_INVAL = -1,			/* bad, NAK with EINVAL	*/
	IOC_DONE,			/* OK, reply sent	*/
	IOC_ACK,			/* OK, just send ACK	*/
	IOC_REPLY,			/* OK, just send reply	*/
	IOC_RESTART_ACK,		/* OK, restart & ACK	*/
	IOC_RESTART_REPLY		/* OK, restart & reply	*/
};

enum nge_pp_type {
	NGE_PP_SPACE_CFG = 0,
	NGE_PP_SPACE_REG,
	NGE_PP_SPACE_NIC,
	NGE_PP_SPACE_MII,
	NGE_PP_SPACE_NGE,
	NGE_PP_SPACE_TXDESC,
	NGE_PP_SPACE_TXBUFF,
	NGE_PP_SPACE_RXDESC,
	NGE_PP_SPACE_RXBUFF,
	NGE_PP_SPACE_STATISTICS,
	NGE_PP_SPACE_SEEPROM,
	NGE_PP_SPACE_FLASH
};

/*
 * Flag to kstat type
 */
enum nge_kstat_type {
	NGE_KSTAT_RAW = 0,
	NGE_KSTAT_STATS,
	NGE_KSTAT_CHIPID,
	NGE_KSTAT_DEBUG,
	NGE_KSTAT_COUNT
};


/*
 * Actual state of the nvidia's chip
 */
enum nge_chip_state {
	NGE_CHIP_FAULT = -2,		/* fault, need reset	*/
	NGE_CHIP_ERROR,			/* error, want reset	*/
	NGE_CHIP_INITIAL,		/* Initial state only	*/
	NGE_CHIP_RESET,			/* reset, need init	*/
	NGE_CHIP_STOPPED,		/* Tx/Rx stopped	*/
	NGE_CHIP_RUNNING		/* with interrupts	*/
};

enum nge_eeprom_size {
	EEPROM_1K = 0,
	EEPROM_2K,
	EEPROM_4K,
	EEPROM_8K,
	EEPROM_16K,
	EEPROM_32K,
	EEPROM_64K
};

enum nge_eeprom_access_wid {
	ACCESS_8BIT = 0,
	ACCESS_16BIT
};

/*
 * MDIO operation
 */
enum nge_mdio_operation {
	NGE_MDIO_READ = 0,
	NGE_MDIO_WRITE
};

/*
 * Speed selection
 */
enum nge_speed {
	UNKOWN_SPEED = 0,
	NGE_10M,
	NGE_100M,
	NGE_1000M
};

/*
 * Duplex selection
 */
enum nge_duplex {
	UNKOWN_DUPLEX = 0,
	NGE_HD,
	NGE_FD
};

typedef struct {
	ether_addr_t		addr;		/* in canonical form	*/
	uint8_t			spare;
	uint8_t			set;		/* nonzero => valid	*/
} nge_mac_addr_t;

struct nge;


#define	CHIP_FLAG_COPPER	0x40

/*
 * Collection of physical-layer functions to:
 *	(re)initialise the physical layer
 *	update it to match software settings
 *	check for link status change
 */
typedef struct {
	boolean_t	(*phys_restart)(struct nge *);
	void		(*phys_update)(struct nge *);
	boolean_t	(*phys_check)(struct nge *);
} phys_ops_t;

struct nge_see_rw {
	uint32_t	see_addr;	/* Byte offset within SEEPROM	*/
	uint32_t	see_data;	/* Data read/data to write	*/
};

typedef struct {
	uint64_t	pp_acc_size;	/* in bytes: 1,2,4,8	*/
	uint64_t	pp_acc_space;	/* See #defines below	*/
	uint64_t	pp_acc_offset;
	uint64_t	pp_acc_data;	/* output for peek	*/
					/* input for poke	*/
} nge_peekpoke_t;

typedef uintptr_t 	nge_regno_t;	/* register # (offset)	*/

typedef struct _mul_list {
	struct _mul_list *next;
	uint32_t ref_cnt;
	ether_addr_t mul_addr;
}mul_item, *pmul_item;

/*
 * Describes one chunk of allocated DMA-able memory
 *
 * In some cases, this is a single chunk as allocated from the system;
 * but we also use this structure to represent slices carved off such
 * a chunk.  Even when we don't really need all the information, we
 * use this structure as a convenient way of correlating the various
 * ways of looking at a piece of memory (kernel VA, IO space DVMA,
 * handle+offset, etc).
 */
typedef struct dma_area
{

	caddr_t			private;	/* pointer to nge */
	frtn_t			rx_recycle;	/* recycle function */
	mblk_t			*mp;
	ddi_acc_handle_t	acc_hdl;	/* handle for memory	*/
	void			*mem_va;	/* CPU VA of memory	*/
	uint32_t		nslots;		/* number of slots	*/
	uint32_t		size;		/* size per slot	*/
	size_t			alength;	/* allocated size	*/
						/* >= product of above	*/
	ddi_dma_handle_t	dma_hdl;	/* DMA handle		*/
	offset_t		offset;		/* relative to handle	*/
	ddi_dma_cookie_t	cookie;		/* associated cookie	*/
	uint32_t		ncookies;
	uint32_t		signature;	/* buffer signature	*/
						/* for deciding to free */
						/* or to reuse buffers	*/
	boolean_t		rx_delivered;	/* hold by upper layer	*/
	struct dma_area		*next;
} dma_area_t;

#define	HOST_OWN	0x00000000
#define	CONTROLER_OWN	0x00000001
#define	NGE_END_PACKET	0x00000002


typedef struct nge_dmah_node
{
	struct nge_dmah_node	*next;
	ddi_dma_handle_t	hndl;
} nge_dmah_node_t;

typedef struct nge_dmah_list
{
	nge_dmah_node_t	*head;
	nge_dmah_node_t	*tail;
} nge_dmah_list_t;

/*
 * Software version of the Recv Descriptor
 * There's one of these for each recv buffer (up to 512 per ring)
 */
typedef struct sw_rx_sbd {

	dma_area_t		desc;		/* (const) related h/w	*/
						/* descriptor area	*/
	dma_area_t		*bufp;		/* (const) related	*/
						/* buffer area		*/
	uint8_t			flags;
} sw_rx_sbd_t;

/*
 * Software version of the send Buffer Descriptor
 * There's one of these for each send buffer (up to 512 per ring)
 */
typedef struct sw_tx_sbd {

	dma_area_t		desc;		/* (const) related h/w	*/
						/* descriptor area	*/
	dma_area_t		pbuf;		/* (const) related	*/
						/* buffer area		*/
	void			(*tx_recycle)(struct sw_tx_sbd *);
	uint32_t		flags;
	mblk_t			*mp;		/* related mblk, if any	*/
	nge_dmah_list_t		mp_hndl;
	uint32_t		frags;
	uint32_t		ncookies;	/* dma cookie number */

} sw_tx_sbd_t;

/*
 * Software Receive Buffer (Producer) Ring Control Block
 * There's one of these for each receiver producer ring (up to 3),
 * but each holds buffers of a different size.
 */
typedef struct buff_ring {

	uint64_t		nslots;		/* descriptor area	*/
	struct nge		*ngep;		/* (const) containing	*/
						/* driver soft state	*/
						/* initialise same	*/
	uint64_t		rx_hold;
	sw_rx_sbd_t		*sw_rbds; 	/* software descriptors	*/
	sw_rx_sbd_t		*free_rbds;	/* free ring */
	dma_area_t		*free_list;	/* available buffer queue */
	dma_area_t		*recycle_list;	/* recycling buffer queue */
	kmutex_t		recycle_lock[1];
	uint32_t		buf_sign;	/* buffer ring signature */
						/* for deciding to free  */
						/* or to reuse buffers   */
	boolean_t		rx_bcopy;
} buff_ring_t;

/*
 * Software Receive (Return) Ring Control Block
 * There's one of these for each receiver return ring (up to 16).
 */
typedef struct recv_ring {
	/*
	 * The elements flagged (const) in the comments below are
	 * set up once during initialiation and thereafter unchanged.
	 */
	dma_area_t		desc;		/* (const) related h/w	*/
						/* descriptor area	*/
	struct nge		*ngep;		/* (const) containing	*/
						/* driver soft state	*/
	uint16_t		prod_index;	/* (const) ptr to h/w	*/
						/* "producer index"	*/
	mac_resource_handle_t	handle;
} recv_ring_t;



/*
 * Software Send Ring Control Block
 * There's one of these for each of (up to) 1 send rings
 */
typedef struct send_ring {
	/*
	 * The elements flagged (const) in the comments below are
	 * set up once during initialiation and thereafter unchanged.
	 */
	dma_area_t		desc;		/* (const) related h/w	*/
						/* descriptor area	*/
	dma_area_t		buf[NGE_SEND_SLOTS_BUF];
						/* buffer area(s)	*/
	struct nge		*ngep;		/* (const) containing	*/
						/* driver soft state	*/

	uint32_t		tx_hwmark;
	uint32_t		tx_lwmark;

	/*
	 * The tx_lock must be held when updating
	 * the s/w producer index
	 * (tx_next)
	 */
	kmutex_t		tx_lock[1];	/* serialize h/w update	*/
	uint32_t		tx_next;	/* next slot to use	*/
	uint32_t		tx_flow;

	/*
	 * These counters/indexes are manipulated in the transmit
	 * path using atomics rather than mutexes for speed
	 */
	uint32_t		tx_free;	/* # of slots available	*/

	/*
	 * index (tc_next).
	 */
	kmutex_t		tc_lock[1];
	uint32_t		tc_next;	/* next slot to recycle	*/
						/* ("consumer index")	*/

	sw_tx_sbd_t		*sw_sbds; 	/* software descriptors	*/

	kmutex_t		dmah_lock;
	nge_dmah_list_t		dmah_free;
	nge_dmah_node_t		dmahndl[NGE_MAX_DMA_HDR];

} send_ring_t;


typedef struct {
	uint32_t		businfo;	/* from private reg	*/
	uint16_t		command;	/* saved during attach	*/

	uint16_t		vendor;		/* vendor-id		*/
	uint16_t		device;		/* device-id		*/
	uint16_t		subven;		/* subsystem-vendor-id	*/
	uint16_t		subdev;		/* subsystem-id		*/
	uint8_t			class_code;
	uint8_t			revision;	/* revision-id		*/
	uint8_t			clsize;		/* cache-line-size	*/
	uint8_t			latency;	/* latency-timer	*/
	uint8_t			flags;

	uint16_t		phy_type;	/* Fiber module type 	*/
	uint64_t		hw_mac_addr;	/* from chip register	*/
	nge_mac_addr_t		vendor_addr;	/* transform of same	*/
} chip_info_t;


typedef struct {
	offset_t	index;
	char		*name;
} nge_ksindex_t;

typedef struct {
	uint64_t tso_err_mss;
	uint64_t tso_dis;
	uint64_t tso_err_nosum;
	uint64_t tso_err_hov;
	uint64_t tso_err_huf;
	uint64_t tso_err_l2;
	uint64_t tso_err_ip;
	uint64_t tso_err_l4;
	uint64_t tso_err_tcp;
	uint64_t hsum_err_ip;
	uint64_t hsum_err_l4;
}fe_statistics_t;

/*
 * statistics parameters to tune the driver
 */
typedef struct {
	uint64_t		intr_count;
	uint64_t		intr_lval;
	uint64_t		recv_realloc;
	uint64_t		poll_time;
	uint64_t		recy_free;
	uint64_t		recv_count;
	uint64_t		xmit_count;
	uint64_t		obytes;
	uint64_t		rbytes;
	uint64_t		mp_alloc_err;
	uint64_t		dma_alloc_err;
	uint64_t		kmem_alloc_err;
	uint64_t		load_context;
	uint64_t		ip_hwsum_err;
	uint64_t		tcp_hwsum_err;
	uint64_t		rx_nobuffer;
	uint64_t		rx_err;
	uint64_t		tx_stop_err;
	uint64_t		tx_stall;
	uint64_t		tx_rsrv_fail;
	uint64_t		tx_resched;
	fe_statistics_t	fe_err;
}nge_sw_statistics_t;

typedef struct {
	nge_hw_statistics_t	hw_statistics;
	nge_sw_statistics_t	sw_statistics;
}nge_statistics_t;

struct nge_desc_attr	{

	size_t	rxd_size;
	size_t	txd_size;

	ddi_dma_attr_t	*dma_attr;
	ddi_dma_attr_t	*tx_dma_attr;

	void (*rxd_fill)(void *, const ddi_dma_cookie_t *, size_t);
	uint32_t (*rxd_check)(const void *, size_t *);

	void (*txd_fill)(void *, const ddi_dma_cookie_t *, size_t,
			uint32_t, boolean_t, boolean_t);

	uint32_t (*txd_check)(const void *);
};

typedef struct nge_desc_attr nge_desc_attr_t;

/*
 * Structure used to hold the device-specific config parameters.
 * The setting of such parameters may not consistent with the
 * hardware feature of the device. It's used for software purpose.
 */
typedef struct nge_dev_spec_param {
	boolean_t	msi;		/* specifies msi support */
	boolean_t	msi_x;		/* specifies msi_x support */
	boolean_t	vlan;		/* specifies vlan support */
	boolean_t	advanced_pm;	/* advanced power management support */
	boolean_t	mac_addr_order; /* mac address order */
	boolean_t	tx_pause_frame;	/* specifies tx pause frame support */
	boolean_t	rx_pause_frame;	/* specifies rx pause frame support */
	boolean_t	jumbo;		/* jumbo frame support */
	boolean_t	tx_rx_64byte;	/* set the max tx/rx prd fetch size */
	boolean_t	rx_hw_checksum;	/* specifies tx hw checksum feature */
	uint32_t	tx_hw_checksum;	/* specifies rx hw checksum feature */
	uint32_t	desc_type;	/* specifies descriptor type */
	uint32_t	rx_desc_num;	/* specifies rx descriptor number */
	uint32_t	tx_desc_num;	/* specifies tx descriptor number */
	uint32_t	nge_split;	/* specifies the split number */
} nge_dev_spec_param_t;

typedef struct nge {
	/*
	 * These fields are set by attach() and unchanged thereafter ...
	 */
	dev_info_t		*devinfo;	/* device instance	*/
	mac_handle_t		mh;		/* mac module handle    */
	chip_info_t		chipinfo;
	ddi_acc_handle_t	cfg_handle;	/* DDI I/O handle	*/
	ddi_acc_handle_t	io_handle;	/* DDI I/O handle	*/
	void			*io_regs;	/* mapped registers	*/

	ddi_periodic_t		periodic_id;	/* periodical callback	*/
	uint32_t		factotum_flag;
	ddi_softint_handle_t	factotum_hdl;	/* factotum callback	*/
	ddi_softint_handle_t	resched_hdl;	/* reschedule callback	*/
	uint_t			soft_pri;

	ddi_intr_handle_t 	*htable;	/* for array of interrupts */
	int			intr_type;	/* type of interrupt */
	int			intr_actual_cnt; /* alloc intrs count */
	int			intr_req_cnt;	/* request intrs count */
	uint_t			intr_pri;	/* interrupt priority	*/
	int			intr_cap;	/* interrupt capabilities */

	uint32_t		progress;	/* attach tracking	*/
	uint32_t		debug;		/* flag to debug function */

	char			ifname[8];	/* "nge0" ... "nge999" */


	enum nge_mac_state	nge_mac_state;	/* definitions above	*/
	enum nge_chip_state	nge_chip_state; /* definitions above	*/
	boolean_t		promisc;
	boolean_t		record_promisc;
	boolean_t		suspended;

	int			resched_needed;
	uint32_t		default_mtu;
	uint32_t		max_sdu;
	uint32_t		buf_size;
	uint32_t		rx_desc;
	uint32_t		tx_desc;
	uint32_t		rx_buf;
	uint32_t		nge_split;
	uint32_t		watchdog;
	uint32_t		lowmem_mode;


	/*
	 * Runtime read-write data starts here ...
	 * 1 Receive Rings
	 * 1 Send Rings
	 *
	 * Note: they're not necessarily all used.
	 */
	struct buff_ring	buff[1];
	struct recv_ring	recv[1];
	struct send_ring	send[1];


	kmutex_t		genlock[1];
	krwlock_t		rwlock[1];
	kmutex_t		softlock[1];
	uint32_t		intr_masks;
	boolean_t		poll;
	boolean_t		ch_intr_mode;
	boolean_t		intr_moderation;
	uint32_t		recv_count;
	uint32_t		quiet_time;
	uint32_t		busy_time;
	uint64_t		tpkts_last;
	uint32_t		tfint_threshold;
	uint32_t		sw_intr_intv;
	nge_mac_addr_t		cur_uni_addr;
	uint32_t		rx_datahwm;
	uint32_t		rx_prdlwm;
	uint32_t		rx_prdhwm;
	uint32_t		rx_def;
	uint32_t		desc_mode;

	mul_item		*pcur_mulist;
	nge_mac_addr_t		cur_mul_addr;
	nge_mac_addr_t		cur_mul_mask;

	nge_desc_attr_t		desc_attr;

	/*
	 * Link state data (protected by genlock)
	 */
	int32_t			link_state;	/* See GLD #defines	*/
	uint32_t		stall_cknum;	/* Stall check number */

	uint32_t		phy_xmii_addr;
	uint32_t		phy_id;
	uint32_t		phy_mode;
	const phys_ops_t	*physops;
	uint16_t		phy_gen_status;

	uint32_t		param_loop_mode;

	kstat_t			*nge_kstats[NGE_KSTAT_COUNT];
	nge_statistics_t	statistics;

	nge_dev_spec_param_t	dev_spec_param;

	uint32_t		param_en_pause:1,
				param_en_asym_pause:1,
				param_en_1000hdx:1,
				param_en_1000fdx:1,
				param_en_100fdx:1,
				param_en_100hdx:1,
				param_en_10fdx:1,
				param_en_10hdx:1,
				param_adv_autoneg:1,
				param_adv_pause:1,
				param_adv_asym_pause:1,
				param_adv_1000fdx:1,
				param_adv_1000hdx:1,
				param_adv_100fdx:1,
				param_adv_100hdx:1,
				param_adv_10fdx:1,
				param_adv_10hdx:1,
				param_lp_autoneg:1,
				param_lp_pause:1,
				param_lp_asym_pause:1,
				param_lp_1000fdx:1,
				param_lp_1000hdx:1,
				param_lp_100fdx:1,
				param_lp_100hdx:1,
				param_lp_10fdx:1,
				param_lp_10hdx:1,
				param_link_up:1,
				param_link_autoneg:1,
				param_link_rx_pause:1,
				param_link_tx_pause:1,
				param_pad_to_32:2;
	uint64_t		param_link_speed;
	link_duplex_t		param_link_duplex;
	int			param_txbcopy_threshold;
	int			param_rxbcopy_threshold;
	int			param_recv_max_packet;
	int			param_poll_quiet_time;
	int			param_poll_busy_time;
	int			param_rx_intr_hwater;
	int			param_rx_intr_lwater;
} nge_t;

extern const nge_ksindex_t nge_statistics[];

/*
 * Sync a DMA area described by a dma_area_t
 */
#define	DMA_SYNC(area, flag)	((void) ddi_dma_sync((area).dma_hdl,	\
				    (area).offset, (area).alength, (flag)))

/*
 * Find the (kernel virtual) address of block of memory
 * described by a dma_area_t
 */
#define	DMA_VPTR(area)		((area).mem_va)

/*
 * Zero a block of memory described by a dma_area_t
 */
#define	DMA_ZERO(area)		bzero(DMA_VPTR(area), (area).alength)

/*
 * Next/Prev value of a cyclic index
 */
#define	NEXT(index, limit)	((index) + 1 < (limit) ? (index) + 1 : 0)
#define	PREV(index, limit)	(0 == (index) ? (limit - 1) : (index) - 1)

#define	NEXT_INDEX(ndx, num, lim)\
	(((ndx) + (num) < (lim)) ? ((ndx) + (num)) : ((ndx) + (num) - (lim)))


/*
 * Property lookups
 */
#define	NGE_PROP_EXISTS(d, n)	ddi_prop_exists(DDI_DEV_T_ANY, (d),	\
					DDI_PROP_DONTPASS, (n))
#define	NGE_PROP_GET_INT(d, n)	ddi_prop_get_int(DDI_DEV_T_ANY, (d),	\
					DDI_PROP_DONTPASS, (n), -1)


/*
 * Debugging ...
 */
#ifdef	DEBUG
#define	NGE_DEBUGGING		1
#else
#define	NGE_DEBUGGING		0
#endif	/* DEBUG */

/*
 * Bit flags in the 'debug' word ...
 */
#define	NGE_DBG_STOP		0x00000001	/* early debug_enter()	*/
#define	NGE_DBG_TRACE		0x00000002	/* general flow tracing	*/

#define	NGE_DBG_MII		0x00000010	/* low-level MII access	*/
#define	NGE_DBG_CHIP		0x00000020	/* low(ish)-level code	*/

#define	NGE_DBG_RECV		0x00000100	/* receive-side code	*/
#define	NGE_DBG_SEND		0x00000200	/* packet-send code	*/

#define	NGE_DBG_INIT		0x00100000	/* initialisation	*/
#define	NGE_DBG_NEMO		0x00200000	/* MAC layer entry points */
#define	NGE_DBG_STATS		0x00400000	/* statistics		*/

#define	NGE_DBG_BADIOC		0x01000000	/* unknown ioctls	*/

#define	NGE_DBG_NDD		0x10000000	/* NDD operations	*/



/*
 * 'Do-if-debugging' macro.  The parameter <command> should be one or more
 * C statements (but without the *final* semicolon), which will either be
 * compiled inline or completely ignored, depending on the NGE_DEBUGGING
 * compile-time flag.
 *
 * You should get a compile-time error (at least on a DEBUG build) if
 * your statement isn't actually a statement, rather than unexpected
 * run-time behaviour caused by unintended matching of if-then-elses etc.
 *
 * Note that the NGE_DDB() macro itself can only be used as a statement,
 * not an expression, and should always be followed by a semicolon.
 */
#if NGE_DEBUGGING
#define	NGE_DDB(command)	do {					\
					{ command; }			\
					_NOTE(CONSTANTCONDITION)	\
				} while (0)
#else 	/* NGE_DEBUGGING */
#define	NGE_DDB(command)
/*
 * Old way of debugging.  This is a poor way, as it leeaves empty
 * statements that cause lint to croak.
 * #define	NGE_DDB(command)	do {				\
 * 					{ _NOTE(EMPTY); }		\
 * 					_NOTE(CONSTANTCONDITION)	\
 * 				} while (0)
 */
#endif	/* NGE_DEBUGGING */

/*
 * 'Internal' macros used to construct the TRACE/DEBUG macros below.
 * These provide the primitive conditional-call capability required.
 * Note: the parameter <args> is a parenthesised list of the actual
 * printf-style arguments to be passed to the debug function ...
 */
#define	NGE_XDB(b, w, f, args)	NGE_DDB(if ((b) & (w)) f args)
#define	NGE_GDB(b, args)	NGE_XDB(b, nge_debug, (*nge_gdb()), args)
#define	NGE_LDB(b, args)	NGE_XDB(b, ngep->debug, \
				    (*nge_db(ngep)), args)
#define	NGE_CDB(f, args)	NGE_XDB(NGE_DBG, ngep->debug, f, args)

/*
 * Conditional-print macros.
 *
 * Define NGE_DBG to be the relevant member of the set of NGE_DBG_* values
 * above before using the NGE_GDEBUG() or NGE_DEBUG() macros.  The 'G'
 * versions look at the Global debug flag word (nge_debug); the non-G
 * versions look in the per-instance data (ngep->debug) and so require a
 * variable called 'ngep' to be in scope (and initialised!) before use.
 *
 * You could redefine NGE_TRC too if you really need two different
 * flavours of debugging output in the same area of code, but I don't
 * really recommend it.
 *
 * Note: the parameter <args> is a parenthesised list of the actual
 * arguments to be passed to the debug function, usually a printf-style
 * format string and corresponding values to be formatted.
 */

#define	NGE_TRC	NGE_DBG_TRACE

#define	NGE_GTRACE(args)	NGE_GDB(NGE_TRC, args)
#define	NGE_GDEBUG(args)	NGE_GDB(NGE_DBG, args)
#define	NGE_TRACE(args)		NGE_LDB(NGE_TRC, args)
#define	NGE_DEBUG(args)		NGE_LDB(NGE_DBG, args)

/*
 * Debug-only action macros
 */


#define	NGE_REPORT(args)	NGE_DDB(nge_log args)

boolean_t nge_atomic_decrease(uint64_t *count_p, uint64_t n);
void nge_atomic_increase(uint64_t *count_p, uint64_t n);

int nge_alloc_dma_mem(nge_t *ngep, size_t memsize,
    ddi_device_acc_attr_t *attr_p, uint_t dma_flags, dma_area_t *dma_p);
void nge_free_dma_mem(dma_area_t *dma_p);
int nge_restart(nge_t *ngep);
void nge_wake_factotum(nge_t *ngep);

uint8_t nge_reg_get8(nge_t *ngep, nge_regno_t regno);
void nge_reg_put8(nge_t *ngep, nge_regno_t regno, uint8_t data);
uint16_t nge_reg_get16(nge_t *ngep, nge_regno_t regno);
void nge_reg_put16(nge_t *ngep, nge_regno_t regno, uint16_t data);
uint32_t nge_reg_get32(nge_t *ngep, nge_regno_t regno);
void nge_reg_put32(nge_t *ngep, nge_regno_t regno, uint32_t data);
uint_t nge_chip_factotum(caddr_t args1, caddr_t args2);
void nge_chip_cfg_init(nge_t *ngep, chip_info_t *infop, boolean_t reset);
void nge_init_dev_spec_param(nge_t *ngep);
int nge_chip_stop(nge_t *ngep, boolean_t fault);
void nge_restore_mac_addr(nge_t *ngep);
int nge_chip_reset(nge_t *ngep);
int nge_chip_start(nge_t *ngep);
void nge_chip_sync(nge_t *ngep);

uint_t nge_chip_intr(caddr_t arg1, caddr_t arg2);
enum ioc_reply nge_chip_ioctl(nge_t *ngep, mblk_t *mp, struct iocblk *iocp);

void nge_phys_init(nge_t *ngep);
boolean_t nge_phy_reset(nge_t *ngep);
uint16_t nge_mii_get16(nge_t *ngep, nge_regno_t regno);
void nge_mii_put16(nge_t *ngep, nge_regno_t regno, uint16_t data);

void nge_recv_recycle(caddr_t arg);
void nge_receive(nge_t *ngep);

uint_t nge_reschedule(caddr_t args1, caddr_t args2);
mblk_t *nge_m_tx(void *arg, mblk_t *mp);

void nge_tx_recycle(nge_t *ngep, boolean_t is_intr);
void nge_tx_recycle_all(nge_t *ngep);

int nge_nd_init(nge_t *ngep);
void nge_nd_cleanup(nge_t *ngep);


void nge_init_kstats(nge_t *ngep, int instance);
void nge_fini_kstats(nge_t *ngep);
int nge_m_stat(void *arg, uint_t stat, uint64_t *val);

uint32_t nge_atomic_shl32(uint32_t *sp, uint_t count);

void nge_log(nge_t *ngep, const char *fmt, ...);
void nge_problem(nge_t *ngep, const char *fmt, ...);
void nge_error(nge_t *ngep, const char *fmt, ...);
void
nge_report(nge_t *ngep, uint8_t error_id);

void (*nge_db(nge_t *ngep))(const char *fmt, ...);
void (*nge_gdb(void))(const char *fmt, ...);
extern	uint32_t nge_debug;

/*
 * DESC MODE 2
 */

extern void nge_sum_rxd_fill(void *, const ddi_dma_cookie_t *, size_t);
extern uint32_t nge_sum_rxd_check(const void *, size_t *);

extern void nge_sum_txd_fill(void *, const ddi_dma_cookie_t *,
				size_t, uint32_t, boolean_t, boolean_t);
extern uint32_t nge_sum_txd_check(const void *);

/*
 * DESC MODE 3
 */

extern void nge_hot_rxd_fill(void *, const ddi_dma_cookie_t *, size_t);
extern uint32_t nge_hot_rxd_check(const void *, size_t *);

extern void nge_hot_txd_fill(void *, const ddi_dma_cookie_t *,
				size_t, uint32_t, boolean_t, boolean_t);
extern uint32_t nge_hot_txd_check(const void *);

#ifdef __cplusplus
}
#endif

#endif	/* _SYS_NGE_H */