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.
*/
|