aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/i82586.h
blob: 5f65b250646fef1301c3ba5abd8a93d2c871ee18 (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
/*
 * Intel 82586 IEEE 802.3 Ethernet LAN Coprocessor.
 *
 * See:
 *	Intel Microcommunications 1991
 *	p1-1 to p1-37
 *	Intel order No. 231658
 *	ISBN 1-55512-119-5
 *
 *     Unfortunately, the above chapter mentions neither
 * the System Configuration Pointer (SCP) nor the
 * Intermediate System Configuration Pointer (ISCP),
 * so we probably need to look elsewhere for the
 * whole story -- some recommend the "Intel LAN
 * Components manual" but I have neither a copy
 * nor a full reference.  But "elsewhere" may be
 * in the same publication...
 *     The description of a later device, the
 * "82596CA High-Performance 32-Bit Local Area Network
 * Coprocessor", (ibid. p1-38 to p1-109) does mention
 * the SCP and ISCP and also has an i82586 compatibility
 * mode.  Even more useful is "AP-235 An 82586 Data Link
 * Driver" (ibid. p1-337 to p1-417).
 */

#define	I82586_MEMZ	(64 * 1024)

#define	I82586_SCP_ADDR	(I82586_MEMZ - sizeof(scp_t))

#define	ADDR_LEN	6
#define	I82586NULL	0xFFFF

#define	toff(t,p,f) 	(unsigned short)((void *)(&((t *)((void *)0 + (p)))->f) - (void *)0)

/*
 * System Configuration Pointer (SCP).
 */
typedef struct scp_t	scp_t;
struct scp_t
{
	unsigned short	scp_sysbus;	/* 82586 bus width:	*/
#define		SCP_SY_16BBUS	(0x0 << 0)	/* 16 bits */
#define		SCP_SY_8BBUS	(0x1 << 0)	/*  8 bits. */
	unsigned short	scp_junk[2];	/* Unused */
	unsigned short	scp_iscpl;	/* lower 16 bits of ISCP_ADDR */
	unsigned short	scp_iscph;	/* upper 16 bits of ISCP_ADDR */
};

/*
 * Intermediate System Configuration Pointer (ISCP).
 */
typedef struct iscp_t	iscp_t;
struct iscp_t
{
	unsigned short	iscp_busy;	/* set by CPU before first CA,	*/
					/* cleared by 82586 after read.	*/
	unsigned short	iscp_offset;	/* offset of SCB		*/
	unsigned short	iscp_basel;	/* base of SCB			*/
	unsigned short	iscp_baseh;	/*  "				*/
};

/*
 * System Control Block (SCB).
 *	The 82586 writes its status to scb_status and then
 *	raises an interrupt to alert the CPU.
 *	The CPU writes a command to scb_command and
 *	then issues a Channel Attention (CA) to alert the 82586.
 */
typedef struct scb_t	scb_t;
struct scb_t
{
	unsigned short	scb_status;	/* Status of 82586		*/
#define		SCB_ST_INT	(0xF << 12)	/* Some of:		*/
#define		SCB_ST_CX	(0x1 << 15)	/* Cmd completed	*/
#define		SCB_ST_FR	(0x1 << 14)	/* Frame received	*/
#define		SCB_ST_CNA	(0x1 << 13)	/* Cmd unit not active	*/
#define		SCB_ST_RNR	(0x1 << 12)	/* Rcv unit not ready	*/
#define		SCB_ST_JUNK0	(0x1 << 11)	/* 0			*/
#define		SCB_ST_CUS	(0x7 <<  8)	/* Cmd unit status	*/
#define			SCB_ST_CUS_IDLE	(0 << 8)	/* Idle		*/
#define			SCB_ST_CUS_SUSP	(1 << 8)	/* Suspended	*/
#define			SCB_ST_CUS_ACTV	(2 << 8)	/* Active	*/
#define		SCB_ST_JUNK1	(0x1 <<  7)	/* 0			*/
#define		SCB_ST_RUS	(0x7 <<  4)	/* Rcv unit status	*/
#define			SCB_ST_RUS_IDLE	(0 << 4)	/* Idle		*/
#define			SCB_ST_RUS_SUSP	(1 << 4)	/* Suspended	*/
#define			SCB_ST_RUS_NRES	(2 << 4)	/* No resources	*/
#define			SCB_ST_RUS_RDY	(4 << 4)	/* Ready	*/
	unsigned short	scb_command;	/* Next command			*/
#define		SCB_CMD_ACK_CX	(0x1 << 15)	/* Ack cmd completion	*/
#define		SCB_CMD_ACK_FR	(0x1 << 14)	/* Ack frame received	*/
#define		SCB_CMD_ACK_CNA	(0x1 << 13)	/* Ack CU not active	*/
#define		SCB_CMD_ACK_RNR	(0x1 << 12)	/* Ack RU not ready	*/
#define		SCB_CMD_JUNKX	(0x1 << 11)	/* Unused		*/
#define		SCB_CMD_CUC	(0x7 <<  8)	/* Command Unit command	*/
#define			SCB_CMD_CUC_NOP	(0 << 8)	/* Nop		*/
#define			SCB_CMD_CUC_GO	(1 << 8)	/* Start cbl_offset */
#define			SCB_CMD_CUC_RES	(2 << 8)	/* Resume execution */
#define			SCB_CMD_CUC_SUS	(3 << 8)	/* Suspend   "	*/
#define			SCB_CMD_CUC_ABT	(4 << 8)	/* Abort     "	*/
#define		SCB_CMD_RESET	(0x1 <<  7)	/* Reset chip (hardware) */
#define		SCB_CMD_RUC	(0x7 <<  4)	/* Receive Unit command	*/
#define			SCB_CMD_RUC_NOP	(0 << 4)	/* Nop		*/
#define			SCB_CMD_RUC_GO	(1 << 4)	/* Start rfa_offset */
#define			SCB_CMD_RUC_RES	(2 << 4)	/* Resume reception */
#define			SCB_CMD_RUC_SUS	(3 << 4)	/* Suspend   "	*/
#define			SCB_CMD_RUC_ABT	(4 << 4)	/* Abort     "	*/
	unsigned short	scb_cbl_offset;	/* Offset of first command unit	*/
					/* Action Command		*/
	unsigned short	scb_rfa_offset;	/* Offset of first Receive	*/
					/* Frame Descriptor in the	*/
					/* Receive Frame Area		*/
	unsigned short	scb_crcerrs;	/* Properly aligned frames	*/
					/* received with a CRC error	*/
	unsigned short	scb_alnerrs;	/* Misaligned frames received	*/
					/* with a CRC error		*/
	unsigned short	scb_rscerrs;	/* Frames lost due to no space	*/
	unsigned short	scb_ovrnerrs;	/* Frames lost due to slow bus	*/
};

#define	scboff(p,f) 	toff(scb_t, p, f)

/*
 * The eight Action Commands.
 */
typedef enum acmd_e	acmd_e;
enum acmd_e
{
	acmd_nop	= 0,	/* Do nothing				*/
	acmd_ia_setup	= 1,	/* Load an (ethernet) address into the	*/
				/* 82586				*/
	acmd_configure	= 2,	/* Update the 82586 operating parameters */
	acmd_mc_setup	= 3,	/* Load a list of (ethernet) multicast	*/
				/* addresses into the 82586		*/
	acmd_transmit	= 4,	/* Transmit a frame			*/
	acmd_tdr	= 5,	/* Perform a Time Domain Reflectometer	*/
				/* test on the serial link		*/
	acmd_dump	= 6,	/* Copy 82586 registers to memory	*/
	acmd_diagnose	= 7,	/* Run an internal self test		*/
};

/*
 * Generic Action Command header.
 */
typedef struct ach_t	ach_t;
struct ach_t
{
	unsigned short	ac_status;		/* Command status:	*/
#define		AC_SFLD_C	(0x1 << 15)	/* Command completed	*/
#define		AC_SFLD_B	(0x1 << 14)	/* Busy executing	*/
#define		AC_SFLD_OK	(0x1 << 13)	/* Completed error free	*/
#define		AC_SFLD_A	(0x1 << 12)	/* Command aborted	*/
#define		AC_SFLD_FAIL	(0x1 << 11)	/* Selftest failed	*/
#define		AC_SFLD_S10	(0x1 << 10)	/* No carrier sense	*/
						/* during transmission	*/
#define		AC_SFLD_S9	(0x1 <<  9)	/* Tx unsuccessful:	*/
						/* (stopped) lost CTS	*/
#define		AC_SFLD_S8	(0x1 <<  8)	/* Tx unsuccessful:	*/
						/* (stopped) slow DMA	*/
#define		AC_SFLD_S7	(0x1 <<  7)	/* Tx deferred:		*/
						/* other link traffic	*/
#define		AC_SFLD_S6	(0x1 <<  6)	/* Heart Beat: collision */
						/* detect after last tx	*/
#define		AC_SFLD_S5	(0x1 <<  5)	/* Tx stopped:		*/
						/* excessive collisions	*/
#define		AC_SFLD_MAXCOL	(0xF <<  0)	/* Collision count  	*/
	unsigned short	ac_command;		/* Command specifier:	*/
#define		AC_CFLD_EL	(0x1 << 15)	/* End of command list	*/
#define		AC_CFLD_S	(0x1 << 14)	/* Suspend on completion */
#define		AC_CFLD_I	(0x1 << 13)	/* Interrupt on completion */
#define		AC_CFLD_CMD	(0x7 <<  0)	/* acmd_e		*/
	unsigned short	ac_link;		/* Next Action Command	*/
};

#define	acoff(p,f) 	toff(ach_t, p, f)

/*
 * The Nop Action Command.
 */
typedef struct ac_nop_t	ac_nop_t;
struct ac_nop_t
{
	ach_t	nop_h;
};

/*
 * The IA-Setup Action Command.
 */
typedef struct ac_ias_t	ac_ias_t;
struct ac_ias_t
{
	ach_t		ias_h;
	unsigned char	ias_addr[ADDR_LEN]; /* The (ethernet) address	*/
};

/*
 * The Configure Action Command.
 */
typedef struct ac_cfg_t	ac_cfg_t;
struct ac_cfg_t
{
	ach_t		cfg_h;
	unsigned char	cfg_byte_cnt;	/* Size foll data: 4-12	*/
#define	AC_CFG_BYTE_CNT(v)	(((v) & 0xF) << 0)
	unsigned char	cfg_fifolim;	/* FIFO threshold	*/
#define	AC_CFG_FIFOLIM(v)	(((v) & 0xF) << 0)
	unsigned char	cfg_byte8;
#define	AC_CFG_SAV_BF(v) 	(((v) & 0x1) << 7)	/* Save rxd bad frames	*/
#define	AC_CFG_SRDY(v) 		(((v) & 0x1) << 6)	/* SRDY/ARDY pin means	*/
							/* external sync.	*/
	unsigned char	cfg_byte9;
#define	AC_CFG_ELPBCK(v)	(((v) & 0x1) << 7)	/* External loopback	*/
#define	AC_CFG_ILPBCK(v)	(((v) & 0x1) << 6)	/* Internal loopback	*/
#define	AC_CFG_PRELEN(v)	(((v) & 0x3) << 4)	/* Preamble length	*/
#define		AC_CFG_PLEN_2		0		/*  2 bytes	*/
#define		AC_CFG_PLEN_4		1		/*  4 bytes	*/
#define		AC_CFG_PLEN_8		2		/*  8 bytes	*/
#define		AC_CFG_PLEN_16		3		/* 16 bytes	*/
#define	AC_CFG_ALOC(v)		(((v) & 0x1) << 3)	/* Addr/len data is	*/
							/* explicit in buffers	*/
#define	AC_CFG_ADDRLEN(v)	(((v) & 0x7) << 0)	/* Bytes per address	*/
	unsigned char	cfg_byte10;
#define	AC_CFG_BOFMET(v)	(((v) & 0x1) << 7)	/* Use alternate expo.	*/
							/* backoff method	*/
#define	AC_CFG_ACR(v)		(((v) & 0x7) << 4)	/* Accelerated cont. res. */
#define	AC_CFG_LINPRIO(v)	(((v) & 0x7) << 0)	/* Linear priority	*/
	unsigned char	cfg_ifs;	/* Interframe spacing		*/
	unsigned char	cfg_slotl;	/* Slot time (low byte)		*/
	unsigned char	cfg_byte13;
#define	AC_CFG_RETRYNUM(v)	(((v) & 0xF) << 4)	/* Max. collision retry	*/
#define	AC_CFG_SLTTMHI(v)	(((v) & 0x7) << 0)	/* Slot time (high bits) */
	unsigned char	cfg_byte14;
#define	AC_CFG_FLGPAD(v)	(((v) & 0x1) << 7)	/* Pad with HDLC flags	*/
#define	AC_CFG_BTSTF(v)		(((v) & 0x1) << 6)	/* Do HDLC bitstuffing	*/
#define	AC_CFG_CRC16(v)		(((v) & 0x1) << 5)	/* 16 bit CCITT CRC	*/
#define	AC_CFG_NCRC(v)		(((v) & 0x1) << 4)	/* Insert no CRC	*/
#define	AC_CFG_TNCRS(v)		(((v) & 0x1) << 3)	/* Tx even if no carrier */
#define	AC_CFG_MANCH(v)		(((v) & 0x1) << 2)	/* Manchester coding	*/
#define	AC_CFG_BCDIS(v)		(((v) & 0x1) << 1)	/* Disable broadcast	*/
#define	AC_CFG_PRM(v)		(((v) & 0x1) << 0)	/* Promiscuous mode	*/
	unsigned char	cfg_byte15;
#define	AC_CFG_ICDS(v)		(((v) & 0x1) << 7)	/* Internal collision	*/
							/* detect source	*/
#define	AC_CFG_CDTF(v)		(((v) & 0x7) << 4)	/* Collision detect	*/
							/* filter in bit times	*/
#define	AC_CFG_ICSS(v)		(((v) & 0x1) << 3)	/* Internal carrier	*/
							/* sense source		*/
#define	AC_CFG_CSTF(v)		(((v) & 0x7) << 0)	/* Carrier sense	*/
							/* filter in bit times	*/
	unsigned short	cfg_min_frm_len;
#define	AC_CFG_MNFRM(v)		(((v) & 0xFF) << 0)	/* Min. bytes/frame (<= 255) */
};

/*
 * The MC-Setup Action Command.
 */
typedef struct ac_mcs_t	ac_mcs_t;
struct ac_mcs_t
{
	ach_t		mcs_h;
	unsigned short	mcs_cnt;	/* No. of bytes of MC addresses	*/
#if 0
	unsigned char	mcs_data[ADDR_LEN]; /* The first MC address ..	*/
	...
#endif
};

#define I82586_MAX_MULTICAST_ADDRESSES	128	/* Hardware hashed filter */

/*
 * The Transmit Action Command.
 */
typedef struct ac_tx_t	ac_tx_t;
struct ac_tx_t
{
	ach_t		tx_h;
	unsigned short	tx_tbd_offset;	/* Address of list of buffers.	*/
#if	0
Linux packets are passed down with the destination MAC address
and length/type field already prepended to the data,
so we do not need to insert it.  Consistent with this
we must also set the AC_CFG_ALOC(..) flag during the
ac_cfg_t action command.
	unsigned char	tx_addr[ADDR_LEN]; /* The frame dest. address	*/
	unsigned short	tx_length;	/* The frame length		*/
#endif	/* 0 */
};

/*
 * The Time Domain Reflectometer Action Command.
 */
typedef struct ac_tdr_t	ac_tdr_t;
struct ac_tdr_t
{
	ach_t		tdr_h;
	unsigned short	tdr_result;	/* Result.	*/
#define		AC_TDR_LNK_OK	(0x1 << 15)	/* No link problem	*/
#define		AC_TDR_XCVR_PRB	(0x1 << 14)	/* Txcvr cable problem	*/
#define		AC_TDR_ET_OPN	(0x1 << 13)	/* Open on the link	*/
#define		AC_TDR_ET_SRT	(0x1 << 12)	/* Short on the link	*/
#define		AC_TDR_TIME	(0x7FF << 0)	/* Distance to problem	*/
						/* site	in transmit	*/
						/* clock cycles		*/
};

/*
 * The Dump Action Command.
 */
typedef struct ac_dmp_t	ac_dmp_t;
struct ac_dmp_t
{
	ach_t		dmp_h;
	unsigned short	dmp_offset;	/* Result.	*/
};

/*
 * Size of the result of the dump command.
 */
#define	DUMPBYTES	170

/*
 * The Diagnose Action Command.
 */
typedef struct ac_dgn_t	ac_dgn_t;
struct ac_dgn_t
{
	ach_t		dgn_h;
};

/*
 * Transmit Buffer Descriptor (TBD).
 */
typedef struct tbd_t	tbd_t;
struct tbd_t
{
	unsigned short	tbd_status;		/* Written by the CPU	*/
#define		TBD_STATUS_EOF	(0x1 << 15)	/* This TBD is the	*/
						/* last for this frame	*/
#define		TBD_STATUS_ACNT	(0x3FFF << 0)	/* Actual count of data	*/
						/* bytes in this buffer	*/
	unsigned short	tbd_next_bd_offset;	/* Next in list		*/
	unsigned short	tbd_bufl;		/* Buffer address (low)	*/
	unsigned short	tbd_bufh;		/*    "	     "	(high)	*/
};

/*
 * Receive Buffer Descriptor (RBD).
 */
typedef struct rbd_t	rbd_t;
struct rbd_t
{
	unsigned short	rbd_status;		/* Written by the 82586	*/
#define		RBD_STATUS_EOF	(0x1 << 15)	/* This RBD is the	*/
						/* last for this frame	*/
#define		RBD_STATUS_F	(0x1 << 14)	/* ACNT field is valid	*/
#define		RBD_STATUS_ACNT	(0x3FFF << 0)	/* Actual no. of data	*/
						/* bytes in this buffer	*/
	unsigned short	rbd_next_rbd_offset;	/* Next rbd in list	*/
	unsigned short	rbd_bufl;		/* Data pointer (low)	*/
	unsigned short	rbd_bufh;		/*  "	   "    (high)	*/
	unsigned short	rbd_el_size;		/* EL+Data buf. size	*/
#define		RBD_EL	(0x1 << 15)		/* This BD is the	*/
						/* last in the list	*/
#define		RBD_SIZE (0x3FFF << 0)		/* No. of bytes the	*/
						/* buffer can hold	*/
};

#define	rbdoff(p,f) 	toff(rbd_t, p, f)

/*
 * Frame Descriptor (FD).
 */
typedef struct fd_t	fd_t;
struct fd_t
{
	unsigned short	fd_status;		/* Written by the 82586	*/
#define		FD_STATUS_C	(0x1 << 15)	/* Completed storing frame */
#define		FD_STATUS_B	(0x1 << 14)	/* FD was consumed by RU */
#define		FD_STATUS_OK	(0x1 << 13)	/* Frame rxd successfully */
#define		FD_STATUS_S11	(0x1 << 11)	/* CRC error		*/
#define		FD_STATUS_S10	(0x1 << 10)	/* Alignment error	*/
#define		FD_STATUS_S9	(0x1 <<  9)	/* Ran out of resources	*/
#define		FD_STATUS_S8	(0x1 <<  8)	/* Rx DMA overrun	*/
#define		FD_STATUS_S7	(0x1 <<  7)	/* Frame too short	*/
#define		FD_STATUS_S6	(0x1 <<  6)	/* No EOF flag		*/
	unsigned short	fd_command;		/* Command		*/
#define		FD_COMMAND_EL	(0x1 << 15)	/* Last FD in list	*/
#define		FD_COMMAND_S	(0x1 << 14)	/* Suspend RU after rx	*/
	unsigned short	fd_link_offset;		/* Next FD		*/
	unsigned short	fd_rbd_offset;		/* First RBD (data)	*/
						/* Prepared by CPU,	*/
						/* updated by 82586	*/
#if	0
I think the rest is unused since we
have set AC_CFG_ALOC(..).  However, just
in case, we leave the space.
#endif	/* 0 */
	unsigned char	fd_dest[ADDR_LEN];	/* Destination address	*/
						/* Written by 82586	*/
	unsigned char	fd_src[ADDR_LEN];	/* Source address	*/
						/* Written by 82586	*/
	unsigned short	fd_length;		/* Frame length or type	*/
						/* Written by 82586	*/
};

#define	fdoff(p,f) 	toff(fd_t, p, f)

/*
 * This software may only be used and distributed
 * according to the terms of the GNU General Public License.
 *
 * For more details, see wavelan.c.
 */