ad7dd57ce1b35e54a6b8aeca75ba1731a4c4a6ff
[dragonfly.git] / sys / platform / pc32 / isa / ic / i82586.h
1 /*-
2  * Copyright (c) 1992, University of Vermont and State Agricultural College.
3  * Copyright (c) 1992, Garrett A. Wollman.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by the University of
17  *      Vermont and State Agricultural College and Garrett A. Wollman.
18  * 4. Neither the name of the University nor the name of the author
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR AUTHOR BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $FreeBSD: src/sys/i386/isa/ic/i82586.h,v 1.9 1999/08/28 00:45:14 peter Exp $
35  * $DragonFly: src/sys/platform/pc32/isa/ic/i82586.h,v 1.2 2003/06/17 04:28:37 dillon Exp $
36  */
37
38 /*
39  * Intel 82586 Ethernet chip
40  * Register, bit, and structure definitions.
41  *
42  * Written by GAW with reference to the Clarkson Packet Driver code for this
43  * chip written by Russ Nelson and others.
44  */
45
46 struct ie_en_addr {
47         u_char data[6];
48 };
49
50 /*
51  * This is the master configuration block.  It tells the hardware where all
52  * the rest of the stuff is.
53  */
54 struct ie_sys_conf_ptr {
55         u_short mbz;                    /* must be zero */
56         u_char ie_bus_use;              /* true if 8-bit only */
57         u_char mbz2[5];                 /* must be zero */
58         caddr_t ie_iscp_ptr;            /* 24-bit physaddr of ISCP */
59 };
60
61 /*
62  * Note that this is wired in hardware; the SCP is always located here, no
63  * matter what.
64  */
65 #define IE_SCP_ADDR 0xfffff4
66
67 /*
68  * The tells the hardware where all the rest of the stuff is, too.
69  * FIXME: some of these should be re-commented after we figure out their
70  * REAL function.
71  */
72 struct ie_int_sys_conf_ptr {
73         u_char ie_busy;                 /* zeroed after init */
74         u_char mbz;
75         u_short ie_scb_offset;          /* 16-bit physaddr of next struct */
76         caddr_t ie_base;                /* 24-bit physaddr for all 16-bit vars */
77 };
78
79 /*
80  * This FINALLY tells the hardware what to do and where to put it.
81  */
82 struct ie_sys_ctl_block {
83         u_short ie_status;              /* status word */
84         u_short ie_command;             /* command word */
85         u_short ie_command_list;        /* 16-pointer to command block list */
86         u_short ie_recv_list;           /* 16-pointer to receive frame list */
87         u_short ie_err_crc;             /* CRC errors */
88         u_short ie_err_align;           /* Alignment errors */
89         u_short ie_err_resource;        /* Resource errors */
90         u_short ie_err_overrun;         /* Overrun errors */
91 };
92
93 /* Command values */
94 #define IE_RU_COMMAND   0x0070  /* mask for RU command */
95 #define IE_RU_NOP       0       /* for completeness */
96 #define IE_RU_START     0x0010  /* start receive unit command */
97 #define IE_RU_ENABLE    0x0020  /* enable receiver command */
98 #define IE_RU_DISABLE   0x0030  /* disable receiver command */
99 #define IE_RU_ABORT     0x0040  /* abort current receive operation */
100
101 #define IE_CU_COMMAND   0x0700  /* mask for CU command */
102 #define IE_CU_NOP       0       /* included for completeness */
103 #define IE_CU_START     0x0100  /* do-command command */
104 #define IE_CU_RESUME    0x0200  /* resume a suspended cmd list */
105 #define IE_CU_STOP      0x0300  /* SUSPEND was already taken */
106 #define IE_CU_ABORT     0x0400  /* abort current command */
107
108 #define IE_ACK_COMMAND  0xf000  /* mask for ACK command */
109 #define IE_ACK_CX       0x8000  /* ack IE_ST_DONE */
110 #define IE_ACK_FR       0x4000  /* ack IE_ST_RECV */
111 #define IE_ACK_CNA      0x2000  /* ack IE_ST_ALLDONE */
112 #define IE_ACK_RNR      0x1000  /* ack IE_ST_RNR */
113
114 #define IE_ACTION_COMMAND(x) (((x) & IE_CU_COMMAND) == IE_CU_START)
115                                 /* is this command an action command? */
116
117 /* Status values */
118 #define IE_ST_WHENCE    0xf000  /* mask for cause of interrupt */
119 #define IE_ST_DONE      0x8000  /* command with I bit completed */
120 #define IE_ST_RECV      0x4000  /* frame received */
121 #define IE_ST_ALLDONE   0x2000  /* all commands completed */
122 #define IE_ST_RNR       0x1000  /* receive not ready */
123
124 #define IE_CU_STATUS    0x700   /* mask for command unit status */
125 #define IE_CU_ACTIVE    0x200   /* command unit is active */
126 #define IE_CU_SUSPEND   0x100   /* command unit is suspended */
127
128 #define IE_RU_STATUS    0x70    /* mask for receiver unit status */
129 #define IE_RU_SUSPEND   0x10    /* receiver is suspended */
130 #define IE_RU_NOSPACE   0x20    /* receiver has no resources */
131 #define IE_RU_READY     0x40    /* reveiver is ready */
132
133 /*
134  * This is filled in partially by the chip, partially by us.
135  */
136 struct ie_recv_frame_desc {
137         u_short ie_fd_status;           /* status for this frame */
138         u_short ie_fd_last;             /* end of frame list flag */
139         u_short ie_fd_next;             /* 16-pointer to next RFD */
140         u_short ie_fd_buf_desc;         /* 16-pointer to list of buffer desc's */
141         struct ie_en_addr dest;         /* destination ether */
142         struct ie_en_addr src;          /* source ether */
143         u_short ie_length;              /* 802 length/Ether type */
144         u_short mbz;                    /* must be zero */
145 };
146
147 #define IE_FD_LAST      0x8000  /* last rfd in list */
148 #define IE_FD_SUSP      0x4000  /* suspend RU after receipt */
149
150 #define IE_FD_COMPLETE  0x8000  /* frame is complete */
151 #define IE_FD_BUSY      0x4000  /* frame is busy */
152 #define IE_FD_OK        0x2000  /* frame is bad */
153 #define IE_FD_RNR       0x0200  /* receiver out of resources here */
154
155 /*
156  * linked list of buffers...
157  */
158 struct ie_recv_buf_desc {
159         u_short ie_rbd_actual;          /* status for this buffer */
160         u_short ie_rbd_next;            /* 16-pointer to next RBD */
161         caddr_t ie_rbd_buffer;          /* 24-pointer to buffer for this RBD */
162         u_short ie_rbd_length;          /* length of the buffer */
163         u_short mbz;                    /* must be zero */
164 };
165
166 #define IE_RBD_LAST     0x8000  /* last buffer */
167 #define IE_RBD_USED     0x4000  /* this buffer has data */
168 /*
169  * All commands share this in common.
170  */
171 struct ie_cmd_common {
172         u_short ie_cmd_status;          /* status of this command */
173         u_short ie_cmd_cmd;             /* command word */
174         u_short ie_cmd_link;            /* link to next command */
175 };
176
177 #define IE_STAT_COMPL   0x8000  /* command is completed */
178 #define IE_STAT_BUSY    0x4000  /* command is running now */
179 #define IE_STAT_OK      0x2000  /* command completed successfully */
180
181 #define IE_CMD_NOP      0x0000  /* NOP */
182 #define IE_CMD_IASETUP  0x0001  /* initial address setup */
183 #define IE_CMD_CONFIG   0x0002  /* configure command */
184 #define IE_CMD_MCAST    0x0003  /* multicast setup command */
185 #define IE_CMD_XMIT     0x0004  /* transmit command */
186 #define IE_CMD_TDR      0x0005  /* time-domain reflectometer command */
187 #define IE_CMD_DUMP     0x0006  /* dump command */
188 #define IE_CMD_DIAGNOSE 0x0007  /* diagnostics command */
189
190 #define IE_CMD_LAST     0x8000  /* this is the last command in the list */
191 #define IE_CMD_SUSPEND  0x4000  /* suspend CU after this command */
192 #define IE_CMD_INTR     0x2000  /* post an interrupt after completion */
193
194 /*
195  * This is the command to transmit a frame.
196  */
197 struct ie_xmit_cmd {
198         struct ie_cmd_common com;       /* common part */
199 #define ie_xmit_status com.ie_cmd_status
200
201         u_short ie_xmit_desc;           /* 16-pointer to buffer descriptor */
202         struct ie_en_addr ie_xmit_addr; /* destination address */
203
204         u_short ie_xmit_length;         /* 802.3 length/Ether type field */
205 };
206
207 #define IE_XS_MAXCOLL   0x000f  /* number of collisions during transmit */
208 #define IE_XS_EXCMAX    0x0020  /* exceeded maximum number of collisions */
209 #define IE_XS_SQE       0x0040  /* SQE positive */
210 #define IE_XS_DEFERRED  0x0080  /* transmission deferred */
211 #define IE_XS_UNDERRUN  0x0100  /* DMA underrun */
212 #define IE_XS_LOSTCTS   0x0200  /* Lost CTS */
213 #define IE_XS_NOCARRIER 0x0400  /* No Carrier */
214 #define IE_XS_LATECOLL  0x0800  /* Late collision */
215
216 /*
217  * This is a buffer descriptor for a frame to be transmitted.
218  */
219
220 struct ie_xmit_buf {
221         u_short ie_xmit_flags;          /* see below */
222         u_short ie_xmit_next;           /* 16-pointer to next desc. */
223         caddr_t ie_xmit_buf;            /* 24-pointer to the actual buffer */
224 };
225
226 #define IE_XMIT_LAST 0x8000     /* this TBD is the last one */
227 /* The rest of the `flags' word is actually the length. */
228
229 /*
230  * Multicast setup command.
231  */
232
233 #define MAXMCAST 50             /* must fit in transmit buffer */
234
235 struct ie_mcast_cmd {
236         struct ie_cmd_common com;       /* common part */
237 #define ie_mcast_status com.ie_cmd_status
238
239         u_short ie_mcast_bytes; /* size (in bytes) of multicast addresses */
240         struct ie_en_addr ie_mcast_addrs[MAXMCAST + 1]; /* space for them */
241 };
242
243 /*
244  * Time Domain Reflectometer command.
245  */
246
247 struct ie_tdr_cmd {
248         struct ie_cmd_common com;       /* common part */
249 #define ie_tdr_status com.ie_cmd_status
250
251         u_short ie_tdr_time;            /* error bits and time */
252 };
253
254 #define IE_TDR_SUCCESS  0x8000  /* TDR succeeded without error */
255 #define IE_TDR_XCVR     0x4000  /* detected a transceiver problem */
256 #define IE_TDR_OPEN     0x2000  /* detected an open */
257 #define IE_TDR_SHORT    0x1000  /* TDR detected a short */
258 #define IE_TDR_TIME     0x07ff  /* mask for reflection time */
259
260 /*
261  * Initial Address Setup command
262  */
263 struct ie_iasetup_cmd {
264         struct ie_cmd_common com;
265 #define ie_iasetup_status com.ie_cmd_status
266
267         struct ie_en_addr ie_address;
268 };
269
270 /*
271  * Configuration command
272  */
273 struct ie_config_cmd {
274         struct ie_cmd_common com;       /* common part */
275 #define ie_config_status com.ie_cmd_status
276
277         u_char ie_config_count;         /* byte count (0x0c) */
278         u_char ie_fifo;                 /* fifo (8) */
279         u_char ie_save_bad;             /* save bad frames (0x40) */
280         u_char ie_addr_len;             /* address length (0x2e) (AL-LOC == 1) */
281         u_char ie_priority;             /* priority and backoff (0x0) */
282         u_char ie_ifs;                  /* inter-frame spacing (0x60) */
283         u_char ie_slot_low;             /* slot time, LSB (0x0) */
284         u_char ie_slot_high;            /* slot time, MSN, and retries (0xf2) */
285         u_char ie_promisc;              /* 1 if promiscuous, else 0 */
286         u_char ie_crs_cdt;              /* CSMA/CD parameters (0x0) */
287         u_char ie_min_len;              /* min frame length (0x40) */
288         u_char ie_junk;                 /* stuff for 82596 (0xff) */
289 };
290
291 /*
292  * Here are a few useful functions.  We could have done these as macros,
293  * but since we have the inline facility, it makes sense to use that
294  * instead.
295  */
296 static __inline void
297 ie_setup_config(volatile struct ie_config_cmd *cmd,
298                 int promiscuous, int manchester) {
299         cmd->ie_config_count = 0x0c;
300         cmd->ie_fifo = 8;
301         cmd->ie_save_bad = 0x40;
302         cmd->ie_addr_len = 0x2e;
303         cmd->ie_priority = 0;
304         cmd->ie_ifs = 0x60;
305         cmd->ie_slot_low = 0;
306         cmd->ie_slot_high = 0xf2;
307         cmd->ie_promisc = !!promiscuous | manchester << 2;
308         cmd->ie_crs_cdt = 0;
309         cmd->ie_min_len = 64;
310         cmd->ie_junk = 0xff;
311 }
312
313 static __inline void *
314 Align(void *ptr) {
315         uintptr_t l = (uintptr_t)ptr;
316         l = (l + 3) & ~3L;
317         return (void *)l;
318 }
319
320 static __inline volatile void *
321 Alignvol(volatile void *ptr) {
322         uintptr_t l = (uintptr_t)ptr;
323         l = (l + 3) & ~3L;
324         return (volatile void *)l;
325 }
326
327 static __inline void
328 ie_ack(volatile struct ie_sys_ctl_block *scb,
329                                   u_int mask, int unit,
330                                   void (*ca)(int)) {
331         scb->ie_command = scb->ie_status & mask;
332         (*ca)(unit);
333 }