| @@ -1,1078 +1,1078 @@ | | | @@ -1,1078 +1,1078 @@ |
1 | /* $NetBSD: if_mec.c,v 1.50 2014/08/10 16:44:34 tls Exp $ */ | | 1 | /* $NetBSD: if_mec.c,v 1.51 2015/04/13 21:22:34 riastradh Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2004, 2008 Izumi Tsutsui. All rights reserved. | | 4 | * Copyright (c) 2004, 2008 Izumi Tsutsui. All rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ | | 25 | */ |
26 | | | 26 | |
27 | /* | | 27 | /* |
28 | * Copyright (c) 2003 Christopher SEKIYA | | 28 | * Copyright (c) 2003 Christopher SEKIYA |
29 | * All rights reserved. | | 29 | * All rights reserved. |
30 | * | | 30 | * |
31 | * Redistribution and use in source and binary forms, with or without | | 31 | * Redistribution and use in source and binary forms, with or without |
32 | * modification, are permitted provided that the following conditions | | 32 | * modification, are permitted provided that the following conditions |
33 | * are met: | | 33 | * are met: |
34 | * 1. Redistributions of source code must retain the above copyright | | 34 | * 1. Redistributions of source code must retain the above copyright |
35 | * notice, this list of conditions and the following disclaimer. | | 35 | * notice, this list of conditions and the following disclaimer. |
36 | * 2. Redistributions in binary form must reproduce the above copyright | | 36 | * 2. Redistributions in binary form must reproduce the above copyright |
37 | * notice, this list of conditions and the following disclaimer in the | | 37 | * notice, this list of conditions and the following disclaimer in the |
38 | * documentation and/or other materials provided with the distribution. | | 38 | * documentation and/or other materials provided with the distribution. |
39 | * 3. All advertising materials mentioning features or use of this software | | 39 | * 3. All advertising materials mentioning features or use of this software |
40 | * must display the following acknowledgement: | | 40 | * must display the following acknowledgement: |
41 | * This product includes software developed for the | | 41 | * This product includes software developed for the |
42 | * NetBSD Project. See http://www.NetBSD.org/ for | | 42 | * NetBSD Project. See http://www.NetBSD.org/ for |
43 | * information about NetBSD. | | 43 | * information about NetBSD. |
44 | * 4. The name of the author may not be used to endorse or promote products | | 44 | * 4. The name of the author may not be used to endorse or promote products |
45 | * derived from this software without specific prior written permission. | | 45 | * derived from this software without specific prior written permission. |
46 | * | | 46 | * |
47 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 47 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
48 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 48 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
49 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 49 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
50 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 50 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
52 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 52 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
53 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 53 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
54 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 54 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
55 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 55 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
56 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 56 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
57 | */ | | 57 | */ |
58 | | | 58 | |
59 | /* | | 59 | /* |
60 | * MACE MAC-110 Ethernet driver | | 60 | * MACE MAC-110 Ethernet driver |
61 | */ | | 61 | */ |
62 | | | 62 | |
63 | #include <sys/cdefs.h> | | 63 | #include <sys/cdefs.h> |
64 | __KERNEL_RCSID(0, "$NetBSD: if_mec.c,v 1.50 2014/08/10 16:44:34 tls Exp $"); | | 64 | __KERNEL_RCSID(0, "$NetBSD: if_mec.c,v 1.51 2015/04/13 21:22:34 riastradh Exp $"); |
65 | | | 65 | |
66 | #include "opt_ddb.h" | | 66 | #include "opt_ddb.h" |
67 | | | 67 | |
68 | #include <sys/param.h> | | 68 | #include <sys/param.h> |
69 | #include <sys/systm.h> | | 69 | #include <sys/systm.h> |
70 | #include <sys/device.h> | | 70 | #include <sys/device.h> |
71 | #include <sys/callout.h> | | 71 | #include <sys/callout.h> |
72 | #include <sys/mbuf.h> | | 72 | #include <sys/mbuf.h> |
73 | #include <sys/malloc.h> | | 73 | #include <sys/malloc.h> |
74 | #include <sys/kernel.h> | | 74 | #include <sys/kernel.h> |
75 | #include <sys/socket.h> | | 75 | #include <sys/socket.h> |
76 | #include <sys/ioctl.h> | | 76 | #include <sys/ioctl.h> |
77 | #include <sys/errno.h> | | 77 | #include <sys/errno.h> |
78 | | | 78 | |
79 | #include <sys/rnd.h> | | 79 | #include <sys/rndsource.h> |
80 | | | 80 | |
81 | #include <net/if.h> | | 81 | #include <net/if.h> |
82 | #include <net/if_dl.h> | | 82 | #include <net/if_dl.h> |
83 | #include <net/if_media.h> | | 83 | #include <net/if_media.h> |
84 | #include <net/if_ether.h> | | 84 | #include <net/if_ether.h> |
85 | | | 85 | |
86 | #include <netinet/in.h> | | 86 | #include <netinet/in.h> |
87 | #include <netinet/in_systm.h> | | 87 | #include <netinet/in_systm.h> |
88 | #include <netinet/ip.h> | | 88 | #include <netinet/ip.h> |
89 | #include <netinet/tcp.h> | | 89 | #include <netinet/tcp.h> |
90 | #include <netinet/udp.h> | | 90 | #include <netinet/udp.h> |
91 | | | 91 | |
92 | #include <net/bpf.h> | | 92 | #include <net/bpf.h> |
93 | | | 93 | |
94 | #include <sys/bus.h> | | 94 | #include <sys/bus.h> |
95 | #include <machine/intr.h> | | 95 | #include <machine/intr.h> |
96 | #include <machine/machtype.h> | | 96 | #include <machine/machtype.h> |
97 | | | 97 | |
98 | #include <dev/mii/mii.h> | | 98 | #include <dev/mii/mii.h> |
99 | #include <dev/mii/miivar.h> | | 99 | #include <dev/mii/miivar.h> |
100 | | | 100 | |
101 | #include <sgimips/mace/macevar.h> | | 101 | #include <sgimips/mace/macevar.h> |
102 | #include <sgimips/mace/if_mecreg.h> | | 102 | #include <sgimips/mace/if_mecreg.h> |
103 | | | 103 | |
104 | #include <dev/arcbios/arcbios.h> | | 104 | #include <dev/arcbios/arcbios.h> |
105 | #include <dev/arcbios/arcbiosvar.h> | | 105 | #include <dev/arcbios/arcbiosvar.h> |
106 | | | 106 | |
107 | /* #define MEC_DEBUG */ | | 107 | /* #define MEC_DEBUG */ |
108 | | | 108 | |
109 | #ifdef MEC_DEBUG | | 109 | #ifdef MEC_DEBUG |
110 | #define MEC_DEBUG_RESET 0x01 | | 110 | #define MEC_DEBUG_RESET 0x01 |
111 | #define MEC_DEBUG_START 0x02 | | 111 | #define MEC_DEBUG_START 0x02 |
112 | #define MEC_DEBUG_STOP 0x04 | | 112 | #define MEC_DEBUG_STOP 0x04 |
113 | #define MEC_DEBUG_INTR 0x08 | | 113 | #define MEC_DEBUG_INTR 0x08 |
114 | #define MEC_DEBUG_RXINTR 0x10 | | 114 | #define MEC_DEBUG_RXINTR 0x10 |
115 | #define MEC_DEBUG_TXINTR 0x20 | | 115 | #define MEC_DEBUG_TXINTR 0x20 |
116 | #define MEC_DEBUG_TXSEGS 0x40 | | 116 | #define MEC_DEBUG_TXSEGS 0x40 |
117 | uint32_t mec_debug = 0; | | 117 | uint32_t mec_debug = 0; |
118 | #define DPRINTF(x, y) if (mec_debug & (x)) printf y | | 118 | #define DPRINTF(x, y) if (mec_debug & (x)) printf y |
119 | #else | | 119 | #else |
120 | #define DPRINTF(x, y) /* nothing */ | | 120 | #define DPRINTF(x, y) /* nothing */ |
121 | #endif | | 121 | #endif |
122 | | | 122 | |
123 | /* #define MEC_EVENT_COUNTERS */ | | 123 | /* #define MEC_EVENT_COUNTERS */ |
124 | | | 124 | |
125 | #ifdef MEC_EVENT_COUNTERS | | 125 | #ifdef MEC_EVENT_COUNTERS |
126 | #define MEC_EVCNT_INCR(ev) (ev)->ev_count++ | | 126 | #define MEC_EVCNT_INCR(ev) (ev)->ev_count++ |
127 | #else | | 127 | #else |
128 | #define MEC_EVCNT_INCR(ev) do {} while (/* CONSTCOND */ 0) | | 128 | #define MEC_EVCNT_INCR(ev) do {} while (/* CONSTCOND */ 0) |
129 | #endif | | 129 | #endif |
130 | | | 130 | |
131 | /* | | 131 | /* |
132 | * Transmit descriptor list size | | 132 | * Transmit descriptor list size |
133 | */ | | 133 | */ |
134 | #define MEC_NTXDESC 64 | | 134 | #define MEC_NTXDESC 64 |
135 | #define MEC_NTXDESC_MASK (MEC_NTXDESC - 1) | | 135 | #define MEC_NTXDESC_MASK (MEC_NTXDESC - 1) |
136 | #define MEC_NEXTTX(x) (((x) + 1) & MEC_NTXDESC_MASK) | | 136 | #define MEC_NEXTTX(x) (((x) + 1) & MEC_NTXDESC_MASK) |
137 | #define MEC_NTXDESC_RSVD 4 | | 137 | #define MEC_NTXDESC_RSVD 4 |
138 | #define MEC_NTXDESC_INTR 8 | | 138 | #define MEC_NTXDESC_INTR 8 |
139 | | | 139 | |
140 | /* | | 140 | /* |
141 | * software state for TX | | 141 | * software state for TX |
142 | */ | | 142 | */ |
143 | struct mec_txsoft { | | 143 | struct mec_txsoft { |
144 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ | | 144 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ |
145 | bus_dmamap_t txs_dmamap; /* our DMA map */ | | 145 | bus_dmamap_t txs_dmamap; /* our DMA map */ |
146 | uint32_t txs_flags; | | 146 | uint32_t txs_flags; |
147 | #define MEC_TXS_BUFLEN_MASK 0x0000007f /* data len in txd_buf */ | | 147 | #define MEC_TXS_BUFLEN_MASK 0x0000007f /* data len in txd_buf */ |
148 | #define MEC_TXS_TXDPTR 0x00000080 /* concat txd_ptr is used */ | | 148 | #define MEC_TXS_TXDPTR 0x00000080 /* concat txd_ptr is used */ |
149 | }; | | 149 | }; |
150 | | | 150 | |
151 | /* | | 151 | /* |
152 | * Transmit buffer descriptor | | 152 | * Transmit buffer descriptor |
153 | */ | | 153 | */ |
154 | #define MEC_TXDESCSIZE 128 | | 154 | #define MEC_TXDESCSIZE 128 |
155 | #define MEC_NTXPTR 3 | | 155 | #define MEC_NTXPTR 3 |
156 | #define MEC_TXD_BUFOFFSET sizeof(uint64_t) | | 156 | #define MEC_TXD_BUFOFFSET sizeof(uint64_t) |
157 | #define MEC_TXD_BUFOFFSET1 \ | | 157 | #define MEC_TXD_BUFOFFSET1 \ |
158 | (sizeof(uint64_t) + sizeof(uint64_t) * MEC_NTXPTR) | | 158 | (sizeof(uint64_t) + sizeof(uint64_t) * MEC_NTXPTR) |
159 | #define MEC_TXD_BUFSIZE (MEC_TXDESCSIZE - MEC_TXD_BUFOFFSET) | | 159 | #define MEC_TXD_BUFSIZE (MEC_TXDESCSIZE - MEC_TXD_BUFOFFSET) |
160 | #define MEC_TXD_BUFSIZE1 (MEC_TXDESCSIZE - MEC_TXD_BUFOFFSET1) | | 160 | #define MEC_TXD_BUFSIZE1 (MEC_TXDESCSIZE - MEC_TXD_BUFOFFSET1) |
161 | #define MEC_TXD_BUFSTART(len) (MEC_TXD_BUFSIZE - (len)) | | 161 | #define MEC_TXD_BUFSTART(len) (MEC_TXD_BUFSIZE - (len)) |
162 | #define MEC_TXD_ALIGN 8 | | 162 | #define MEC_TXD_ALIGN 8 |
163 | #define MEC_TXD_ALIGNMASK (MEC_TXD_ALIGN - 1) | | 163 | #define MEC_TXD_ALIGNMASK (MEC_TXD_ALIGN - 1) |
164 | #define MEC_TXD_ROUNDUP(addr) \ | | 164 | #define MEC_TXD_ROUNDUP(addr) \ |
165 | (((addr) + MEC_TXD_ALIGNMASK) & ~(uint64_t)MEC_TXD_ALIGNMASK) | | 165 | (((addr) + MEC_TXD_ALIGNMASK) & ~(uint64_t)MEC_TXD_ALIGNMASK) |
166 | #define MEC_NTXSEG 16 | | 166 | #define MEC_NTXSEG 16 |
167 | | | 167 | |
168 | struct mec_txdesc { | | 168 | struct mec_txdesc { |
169 | volatile uint64_t txd_cmd; | | 169 | volatile uint64_t txd_cmd; |
170 | #define MEC_TXCMD_DATALEN 0x000000000000ffff /* data length */ | | 170 | #define MEC_TXCMD_DATALEN 0x000000000000ffff /* data length */ |
171 | #define MEC_TXCMD_BUFSTART 0x00000000007f0000 /* start byte offset */ | | 171 | #define MEC_TXCMD_BUFSTART 0x00000000007f0000 /* start byte offset */ |
172 | #define TXCMD_BUFSTART(x) ((x) << 16) | | 172 | #define TXCMD_BUFSTART(x) ((x) << 16) |
173 | #define MEC_TXCMD_TERMDMA 0x0000000000800000 /* stop DMA on abort */ | | 173 | #define MEC_TXCMD_TERMDMA 0x0000000000800000 /* stop DMA on abort */ |
174 | #define MEC_TXCMD_TXINT 0x0000000001000000 /* INT after TX done */ | | 174 | #define MEC_TXCMD_TXINT 0x0000000001000000 /* INT after TX done */ |
175 | #define MEC_TXCMD_PTR1 0x0000000002000000 /* valid 1st txd_ptr */ | | 175 | #define MEC_TXCMD_PTR1 0x0000000002000000 /* valid 1st txd_ptr */ |
176 | #define MEC_TXCMD_PTR2 0x0000000004000000 /* valid 2nd txd_ptr */ | | 176 | #define MEC_TXCMD_PTR2 0x0000000004000000 /* valid 2nd txd_ptr */ |
177 | #define MEC_TXCMD_PTR3 0x0000000008000000 /* valid 3rd txd_ptr */ | | 177 | #define MEC_TXCMD_PTR3 0x0000000008000000 /* valid 3rd txd_ptr */ |
178 | #define MEC_TXCMD_UNUSED 0xfffffffff0000000ULL /* should be zero */ | | 178 | #define MEC_TXCMD_UNUSED 0xfffffffff0000000ULL /* should be zero */ |
179 | | | 179 | |
180 | #define txd_stat txd_cmd | | 180 | #define txd_stat txd_cmd |
181 | #define MEC_TXSTAT_LEN 0x000000000000ffff /* TX length */ | | 181 | #define MEC_TXSTAT_LEN 0x000000000000ffff /* TX length */ |
182 | #define MEC_TXSTAT_COLCNT 0x00000000000f0000 /* collision count */ | | 182 | #define MEC_TXSTAT_COLCNT 0x00000000000f0000 /* collision count */ |
183 | #define MEC_TXSTAT_COLCNT_SHIFT 16 | | 183 | #define MEC_TXSTAT_COLCNT_SHIFT 16 |
184 | #define MEC_TXSTAT_LATE_COL 0x0000000000100000 /* late collision */ | | 184 | #define MEC_TXSTAT_LATE_COL 0x0000000000100000 /* late collision */ |
185 | #define MEC_TXSTAT_CRCERROR 0x0000000000200000 /* */ | | 185 | #define MEC_TXSTAT_CRCERROR 0x0000000000200000 /* */ |
186 | #define MEC_TXSTAT_DEFERRED 0x0000000000400000 /* */ | | 186 | #define MEC_TXSTAT_DEFERRED 0x0000000000400000 /* */ |
187 | #define MEC_TXSTAT_SUCCESS 0x0000000000800000 /* TX complete */ | | 187 | #define MEC_TXSTAT_SUCCESS 0x0000000000800000 /* TX complete */ |
188 | #define MEC_TXSTAT_TOOBIG 0x0000000001000000 /* */ | | 188 | #define MEC_TXSTAT_TOOBIG 0x0000000001000000 /* */ |
189 | #define MEC_TXSTAT_UNDERRUN 0x0000000002000000 /* */ | | 189 | #define MEC_TXSTAT_UNDERRUN 0x0000000002000000 /* */ |
190 | #define MEC_TXSTAT_COLLISIONS 0x0000000004000000 /* */ | | 190 | #define MEC_TXSTAT_COLLISIONS 0x0000000004000000 /* */ |
191 | #define MEC_TXSTAT_EXDEFERRAL 0x0000000008000000 /* */ | | 191 | #define MEC_TXSTAT_EXDEFERRAL 0x0000000008000000 /* */ |
192 | #define MEC_TXSTAT_COLLIDED 0x0000000010000000 /* */ | | 192 | #define MEC_TXSTAT_COLLIDED 0x0000000010000000 /* */ |
193 | #define MEC_TXSTAT_UNUSED 0x7fffffffe0000000ULL /* should be zero */ | | 193 | #define MEC_TXSTAT_UNUSED 0x7fffffffe0000000ULL /* should be zero */ |
194 | #define MEC_TXSTAT_SENT 0x8000000000000000ULL /* packet sent */ | | 194 | #define MEC_TXSTAT_SENT 0x8000000000000000ULL /* packet sent */ |
195 | | | 195 | |
196 | union { | | 196 | union { |
197 | uint64_t txptr[MEC_NTXPTR]; | | 197 | uint64_t txptr[MEC_NTXPTR]; |
198 | #define MEC_TXPTR_UNUSED2 0x0000000000000007 /* should be zero */ | | 198 | #define MEC_TXPTR_UNUSED2 0x0000000000000007 /* should be zero */ |
199 | #define MEC_TXPTR_DMAADDR 0x00000000fffffff8 /* TX DMA address */ | | 199 | #define MEC_TXPTR_DMAADDR 0x00000000fffffff8 /* TX DMA address */ |
200 | #define MEC_TXPTR_LEN 0x0000ffff00000000ULL /* buffer length */ | | 200 | #define MEC_TXPTR_LEN 0x0000ffff00000000ULL /* buffer length */ |
201 | #define TXPTR_LEN(x) ((uint64_t)(x) << 32) | | 201 | #define TXPTR_LEN(x) ((uint64_t)(x) << 32) |
202 | #define MEC_TXPTR_UNUSED1 0xffff000000000000ULL /* should be zero */ | | 202 | #define MEC_TXPTR_UNUSED1 0xffff000000000000ULL /* should be zero */ |
203 | | | 203 | |
204 | uint8_t txbuf[MEC_TXD_BUFSIZE]; | | 204 | uint8_t txbuf[MEC_TXD_BUFSIZE]; |
205 | } txd_data; | | 205 | } txd_data; |
206 | #define txd_ptr txd_data.txptr | | 206 | #define txd_ptr txd_data.txptr |
207 | #define txd_buf txd_data.txbuf | | 207 | #define txd_buf txd_data.txbuf |
208 | }; | | 208 | }; |
209 | | | 209 | |
210 | /* | | 210 | /* |
211 | * Receive buffer size | | 211 | * Receive buffer size |
212 | */ | | 212 | */ |
213 | #define MEC_NRXDESC 16 | | 213 | #define MEC_NRXDESC 16 |
214 | #define MEC_NRXDESC_MASK (MEC_NRXDESC - 1) | | 214 | #define MEC_NRXDESC_MASK (MEC_NRXDESC - 1) |
215 | #define MEC_NEXTRX(x) (((x) + 1) & MEC_NRXDESC_MASK) | | 215 | #define MEC_NEXTRX(x) (((x) + 1) & MEC_NRXDESC_MASK) |
216 | | | 216 | |
217 | /* | | 217 | /* |
218 | * Receive buffer description | | 218 | * Receive buffer description |
219 | */ | | 219 | */ |
220 | #define MEC_RXDESCSIZE 4096 /* umm, should be 4kbyte aligned */ | | 220 | #define MEC_RXDESCSIZE 4096 /* umm, should be 4kbyte aligned */ |
221 | #define MEC_RXD_NRXPAD 3 | | 221 | #define MEC_RXD_NRXPAD 3 |
222 | #define MEC_RXD_DMAOFFSET (1 + MEC_RXD_NRXPAD) | | 222 | #define MEC_RXD_DMAOFFSET (1 + MEC_RXD_NRXPAD) |
223 | #define MEC_RXD_BUFOFFSET (MEC_RXD_DMAOFFSET * sizeof(uint64_t)) | | 223 | #define MEC_RXD_BUFOFFSET (MEC_RXD_DMAOFFSET * sizeof(uint64_t)) |
224 | #define MEC_RXD_BUFSIZE (MEC_RXDESCSIZE - MEC_RXD_BUFOFFSET) | | 224 | #define MEC_RXD_BUFSIZE (MEC_RXDESCSIZE - MEC_RXD_BUFOFFSET) |
225 | | | 225 | |
226 | struct mec_rxdesc { | | 226 | struct mec_rxdesc { |
227 | volatile uint64_t rxd_stat; | | 227 | volatile uint64_t rxd_stat; |
228 | #define MEC_RXSTAT_LEN 0x000000000000ffff /* data length */ | | 228 | #define MEC_RXSTAT_LEN 0x000000000000ffff /* data length */ |
229 | #define MEC_RXSTAT_VIOLATION 0x0000000000010000 /* code violation (?) */ | | 229 | #define MEC_RXSTAT_VIOLATION 0x0000000000010000 /* code violation (?) */ |
230 | #define MEC_RXSTAT_UNUSED2 0x0000000000020000 /* unknown (?) */ | | 230 | #define MEC_RXSTAT_UNUSED2 0x0000000000020000 /* unknown (?) */ |
231 | #define MEC_RXSTAT_CRCERROR 0x0000000000040000 /* CRC error */ | | 231 | #define MEC_RXSTAT_CRCERROR 0x0000000000040000 /* CRC error */ |
232 | #define MEC_RXSTAT_MULTICAST 0x0000000000080000 /* multicast packet */ | | 232 | #define MEC_RXSTAT_MULTICAST 0x0000000000080000 /* multicast packet */ |
233 | #define MEC_RXSTAT_BROADCAST 0x0000000000100000 /* broadcast packet */ | | 233 | #define MEC_RXSTAT_BROADCAST 0x0000000000100000 /* broadcast packet */ |
234 | #define MEC_RXSTAT_INVALID 0x0000000000200000 /* invalid preamble */ | | 234 | #define MEC_RXSTAT_INVALID 0x0000000000200000 /* invalid preamble */ |
235 | #define MEC_RXSTAT_LONGEVENT 0x0000000000400000 /* long packet */ | | 235 | #define MEC_RXSTAT_LONGEVENT 0x0000000000400000 /* long packet */ |
236 | #define MEC_RXSTAT_BADPACKET 0x0000000000800000 /* bad packet */ | | 236 | #define MEC_RXSTAT_BADPACKET 0x0000000000800000 /* bad packet */ |
237 | #define MEC_RXSTAT_CAREVENT 0x0000000001000000 /* carrier event */ | | 237 | #define MEC_RXSTAT_CAREVENT 0x0000000001000000 /* carrier event */ |
238 | #define MEC_RXSTAT_MATCHMCAST 0x0000000002000000 /* match multicast */ | | 238 | #define MEC_RXSTAT_MATCHMCAST 0x0000000002000000 /* match multicast */ |
239 | #define MEC_RXSTAT_MATCHMAC 0x0000000004000000 /* match MAC */ | | 239 | #define MEC_RXSTAT_MATCHMAC 0x0000000004000000 /* match MAC */ |
240 | #define MEC_RXSTAT_SEQNUM 0x00000000f8000000 /* sequence number */ | | 240 | #define MEC_RXSTAT_SEQNUM 0x00000000f8000000 /* sequence number */ |
241 | #define MEC_RXSTAT_CKSUM 0x0000ffff00000000ULL /* IP checksum */ | | 241 | #define MEC_RXSTAT_CKSUM 0x0000ffff00000000ULL /* IP checksum */ |
242 | #define RXSTAT_CKSUM(x) (((uint64_t)(x) & MEC_RXSTAT_CKSUM) >> 32) | | 242 | #define RXSTAT_CKSUM(x) (((uint64_t)(x) & MEC_RXSTAT_CKSUM) >> 32) |
243 | #define MEC_RXSTAT_UNUSED1 0x7fff000000000000ULL /* should be zero */ | | 243 | #define MEC_RXSTAT_UNUSED1 0x7fff000000000000ULL /* should be zero */ |
244 | #define MEC_RXSTAT_RECEIVED 0x8000000000000000ULL /* set to 1 on RX */ | | 244 | #define MEC_RXSTAT_RECEIVED 0x8000000000000000ULL /* set to 1 on RX */ |
245 | uint64_t rxd_pad1[MEC_RXD_NRXPAD]; | | 245 | uint64_t rxd_pad1[MEC_RXD_NRXPAD]; |
246 | uint8_t rxd_buf[MEC_RXD_BUFSIZE]; | | 246 | uint8_t rxd_buf[MEC_RXD_BUFSIZE]; |
247 | }; | | 247 | }; |
248 | | | 248 | |
249 | /* | | 249 | /* |
250 | * control structures for DMA ops | | 250 | * control structures for DMA ops |
251 | */ | | 251 | */ |
252 | struct mec_control_data { | | 252 | struct mec_control_data { |
253 | /* | | 253 | /* |
254 | * TX descriptors and buffers | | 254 | * TX descriptors and buffers |
255 | */ | | 255 | */ |
256 | struct mec_txdesc mcd_txdesc[MEC_NTXDESC]; | | 256 | struct mec_txdesc mcd_txdesc[MEC_NTXDESC]; |
257 | | | 257 | |
258 | /* | | 258 | /* |
259 | * RX descriptors and buffers | | 259 | * RX descriptors and buffers |
260 | */ | | 260 | */ |
261 | struct mec_rxdesc mcd_rxdesc[MEC_NRXDESC]; | | 261 | struct mec_rxdesc mcd_rxdesc[MEC_NRXDESC]; |
262 | }; | | 262 | }; |
263 | | | 263 | |
264 | /* | | 264 | /* |
265 | * It _seems_ there are some restrictions on descriptor address: | | 265 | * It _seems_ there are some restrictions on descriptor address: |
266 | * | | 266 | * |
267 | * - Base address of txdescs should be 8kbyte aligned | | 267 | * - Base address of txdescs should be 8kbyte aligned |
268 | * - Each txdesc should be 128byte aligned | | 268 | * - Each txdesc should be 128byte aligned |
269 | * - Each rxdesc should be 4kbyte aligned | | 269 | * - Each rxdesc should be 4kbyte aligned |
270 | * | | 270 | * |
271 | * So we should specify 8k align to allocalte txdescs. | | 271 | * So we should specify 8k align to allocalte txdescs. |
272 | * In this case, sizeof(struct mec_txdesc) * MEC_NTXDESC is 8192 | | 272 | * In this case, sizeof(struct mec_txdesc) * MEC_NTXDESC is 8192 |
273 | * so rxdescs are also allocated at 4kbyte aligned. | | 273 | * so rxdescs are also allocated at 4kbyte aligned. |
274 | */ | | 274 | */ |
275 | #define MEC_CONTROL_DATA_ALIGN (8 * 1024) | | 275 | #define MEC_CONTROL_DATA_ALIGN (8 * 1024) |
276 | | | 276 | |
277 | #define MEC_CDOFF(x) offsetof(struct mec_control_data, x) | | 277 | #define MEC_CDOFF(x) offsetof(struct mec_control_data, x) |
278 | #define MEC_CDTXOFF(x) MEC_CDOFF(mcd_txdesc[(x)]) | | 278 | #define MEC_CDTXOFF(x) MEC_CDOFF(mcd_txdesc[(x)]) |
279 | #define MEC_CDRXOFF(x) MEC_CDOFF(mcd_rxdesc[(x)]) | | 279 | #define MEC_CDRXOFF(x) MEC_CDOFF(mcd_rxdesc[(x)]) |
280 | | | 280 | |
281 | /* | | 281 | /* |
282 | * software state per device | | 282 | * software state per device |
283 | */ | | 283 | */ |
284 | struct mec_softc { | | 284 | struct mec_softc { |
285 | device_t sc_dev; /* generic device structures */ | | 285 | device_t sc_dev; /* generic device structures */ |
286 | | | 286 | |
287 | bus_space_tag_t sc_st; /* bus_space tag */ | | 287 | bus_space_tag_t sc_st; /* bus_space tag */ |
288 | bus_space_handle_t sc_sh; /* bus_space handle */ | | 288 | bus_space_handle_t sc_sh; /* bus_space handle */ |
289 | bus_dma_tag_t sc_dmat; /* bus_dma tag */ | | 289 | bus_dma_tag_t sc_dmat; /* bus_dma tag */ |
290 | | | 290 | |
291 | struct ethercom sc_ethercom; /* Ethernet common part */ | | 291 | struct ethercom sc_ethercom; /* Ethernet common part */ |
292 | | | 292 | |
293 | struct mii_data sc_mii; /* MII/media information */ | | 293 | struct mii_data sc_mii; /* MII/media information */ |
294 | int sc_phyaddr; /* MII address */ | | 294 | int sc_phyaddr; /* MII address */ |
295 | struct callout sc_tick_ch; /* tick callout */ | | 295 | struct callout sc_tick_ch; /* tick callout */ |
296 | | | 296 | |
297 | uint8_t sc_enaddr[ETHER_ADDR_LEN]; /* MAC address */ | | 297 | uint8_t sc_enaddr[ETHER_ADDR_LEN]; /* MAC address */ |
298 | | | 298 | |
299 | bus_dmamap_t sc_cddmamap; /* bus_dma map for control data */ | | 299 | bus_dmamap_t sc_cddmamap; /* bus_dma map for control data */ |
300 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr | | 300 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr |
301 | | | 301 | |
302 | /* pointer to allocated control data */ | | 302 | /* pointer to allocated control data */ |
303 | struct mec_control_data *sc_control_data; | | 303 | struct mec_control_data *sc_control_data; |
304 | #define sc_txdesc sc_control_data->mcd_txdesc | | 304 | #define sc_txdesc sc_control_data->mcd_txdesc |
305 | #define sc_rxdesc sc_control_data->mcd_rxdesc | | 305 | #define sc_rxdesc sc_control_data->mcd_rxdesc |
306 | | | 306 | |
307 | /* software state for TX descs */ | | 307 | /* software state for TX descs */ |
308 | struct mec_txsoft sc_txsoft[MEC_NTXDESC]; | | 308 | struct mec_txsoft sc_txsoft[MEC_NTXDESC]; |
309 | | | 309 | |
310 | int sc_txpending; /* number of TX requests pending */ | | 310 | int sc_txpending; /* number of TX requests pending */ |
311 | int sc_txdirty; /* first dirty TX descriptor */ | | 311 | int sc_txdirty; /* first dirty TX descriptor */ |
312 | int sc_txlast; /* last used TX descriptor */ | | 312 | int sc_txlast; /* last used TX descriptor */ |
313 | | | 313 | |
314 | int sc_rxptr; /* next ready RX buffer */ | | 314 | int sc_rxptr; /* next ready RX buffer */ |
315 | | | 315 | |
316 | krndsource_t sc_rnd_source; /* random source */ | | 316 | krndsource_t sc_rnd_source; /* random source */ |
317 | #ifdef MEC_EVENT_COUNTERS | | 317 | #ifdef MEC_EVENT_COUNTERS |
318 | struct evcnt sc_ev_txpkts; /* TX packets queued total */ | | 318 | struct evcnt sc_ev_txpkts; /* TX packets queued total */ |
319 | struct evcnt sc_ev_txdpad; /* TX packets padded in txdesc buf */ | | 319 | struct evcnt sc_ev_txdpad; /* TX packets padded in txdesc buf */ |
320 | struct evcnt sc_ev_txdbuf; /* TX packets copied to txdesc buf */ | | 320 | struct evcnt sc_ev_txdbuf; /* TX packets copied to txdesc buf */ |
321 | struct evcnt sc_ev_txptr1; /* TX packets using concat ptr1 */ | | 321 | struct evcnt sc_ev_txptr1; /* TX packets using concat ptr1 */ |
322 | struct evcnt sc_ev_txptr1a; /* TX packets w/ptr1 ~160bytes */ | | 322 | struct evcnt sc_ev_txptr1a; /* TX packets w/ptr1 ~160bytes */ |
323 | struct evcnt sc_ev_txptr1b; /* TX packets w/ptr1 ~256bytes */ | | 323 | struct evcnt sc_ev_txptr1b; /* TX packets w/ptr1 ~256bytes */ |
324 | struct evcnt sc_ev_txptr1c; /* TX packets w/ptr1 ~512bytes */ | | 324 | struct evcnt sc_ev_txptr1c; /* TX packets w/ptr1 ~512bytes */ |
325 | struct evcnt sc_ev_txptr1d; /* TX packets w/ptr1 ~1024bytes */ | | 325 | struct evcnt sc_ev_txptr1d; /* TX packets w/ptr1 ~1024bytes */ |
326 | struct evcnt sc_ev_txptr1e; /* TX packets w/ptr1 >1024bytes */ | | 326 | struct evcnt sc_ev_txptr1e; /* TX packets w/ptr1 >1024bytes */ |
327 | struct evcnt sc_ev_txptr2; /* TX packets using concat ptr1,2 */ | | 327 | struct evcnt sc_ev_txptr2; /* TX packets using concat ptr1,2 */ |
328 | struct evcnt sc_ev_txptr2a; /* TX packets w/ptr2 ~160bytes */ | | 328 | struct evcnt sc_ev_txptr2a; /* TX packets w/ptr2 ~160bytes */ |
329 | struct evcnt sc_ev_txptr2b; /* TX packets w/ptr2 ~256bytes */ | | 329 | struct evcnt sc_ev_txptr2b; /* TX packets w/ptr2 ~256bytes */ |
330 | struct evcnt sc_ev_txptr2c; /* TX packets w/ptr2 ~512bytes */ | | 330 | struct evcnt sc_ev_txptr2c; /* TX packets w/ptr2 ~512bytes */ |
331 | struct evcnt sc_ev_txptr2d; /* TX packets w/ptr2 ~1024bytes */ | | 331 | struct evcnt sc_ev_txptr2d; /* TX packets w/ptr2 ~1024bytes */ |
332 | struct evcnt sc_ev_txptr2e; /* TX packets w/ptr2 >1024bytes */ | | 332 | struct evcnt sc_ev_txptr2e; /* TX packets w/ptr2 >1024bytes */ |
333 | struct evcnt sc_ev_txptr3; /* TX packets using concat ptr1,2,3 */ | | 333 | struct evcnt sc_ev_txptr3; /* TX packets using concat ptr1,2,3 */ |
334 | struct evcnt sc_ev_txptr3a; /* TX packets w/ptr3 ~160bytes */ | | 334 | struct evcnt sc_ev_txptr3a; /* TX packets w/ptr3 ~160bytes */ |
335 | struct evcnt sc_ev_txptr3b; /* TX packets w/ptr3 ~256bytes */ | | 335 | struct evcnt sc_ev_txptr3b; /* TX packets w/ptr3 ~256bytes */ |
336 | struct evcnt sc_ev_txptr3c; /* TX packets w/ptr3 ~512bytes */ | | 336 | struct evcnt sc_ev_txptr3c; /* TX packets w/ptr3 ~512bytes */ |
337 | struct evcnt sc_ev_txptr3d; /* TX packets w/ptr3 ~1024bytes */ | | 337 | struct evcnt sc_ev_txptr3d; /* TX packets w/ptr3 ~1024bytes */ |
338 | struct evcnt sc_ev_txptr3e; /* TX packets w/ptr3 >1024bytes */ | | 338 | struct evcnt sc_ev_txptr3e; /* TX packets w/ptr3 >1024bytes */ |
339 | struct evcnt sc_ev_txmbuf; /* TX packets copied to new mbufs */ | | 339 | struct evcnt sc_ev_txmbuf; /* TX packets copied to new mbufs */ |
340 | struct evcnt sc_ev_txmbufa; /* TX packets w/mbuf ~160bytes */ | | 340 | struct evcnt sc_ev_txmbufa; /* TX packets w/mbuf ~160bytes */ |
341 | struct evcnt sc_ev_txmbufb; /* TX packets w/mbuf ~256bytes */ | | 341 | struct evcnt sc_ev_txmbufb; /* TX packets w/mbuf ~256bytes */ |
342 | struct evcnt sc_ev_txmbufc; /* TX packets w/mbuf ~512bytes */ | | 342 | struct evcnt sc_ev_txmbufc; /* TX packets w/mbuf ~512bytes */ |
343 | struct evcnt sc_ev_txmbufd; /* TX packets w/mbuf ~1024bytes */ | | 343 | struct evcnt sc_ev_txmbufd; /* TX packets w/mbuf ~1024bytes */ |
344 | struct evcnt sc_ev_txmbufe; /* TX packets w/mbuf >1024bytes */ | | 344 | struct evcnt sc_ev_txmbufe; /* TX packets w/mbuf >1024bytes */ |
345 | struct evcnt sc_ev_txptrs; /* TX packets using ptrs total */ | | 345 | struct evcnt sc_ev_txptrs; /* TX packets using ptrs total */ |
346 | struct evcnt sc_ev_txptrc0; /* TX packets w/ptrs no hdr chain */ | | 346 | struct evcnt sc_ev_txptrc0; /* TX packets w/ptrs no hdr chain */ |
347 | struct evcnt sc_ev_txptrc1; /* TX packets w/ptrs 1 hdr chain */ | | 347 | struct evcnt sc_ev_txptrc1; /* TX packets w/ptrs 1 hdr chain */ |
348 | struct evcnt sc_ev_txptrc2; /* TX packets w/ptrs 2 hdr chains */ | | 348 | struct evcnt sc_ev_txptrc2; /* TX packets w/ptrs 2 hdr chains */ |
349 | struct evcnt sc_ev_txptrc3; /* TX packets w/ptrs 3 hdr chains */ | | 349 | struct evcnt sc_ev_txptrc3; /* TX packets w/ptrs 3 hdr chains */ |
350 | struct evcnt sc_ev_txptrc4; /* TX packets w/ptrs 4 hdr chains */ | | 350 | struct evcnt sc_ev_txptrc4; /* TX packets w/ptrs 4 hdr chains */ |
351 | struct evcnt sc_ev_txptrc5; /* TX packets w/ptrs 5 hdr chains */ | | 351 | struct evcnt sc_ev_txptrc5; /* TX packets w/ptrs 5 hdr chains */ |
352 | struct evcnt sc_ev_txptrc6; /* TX packets w/ptrs >5 hdr chains */ | | 352 | struct evcnt sc_ev_txptrc6; /* TX packets w/ptrs >5 hdr chains */ |
353 | struct evcnt sc_ev_txptrh0; /* TX packets w/ptrs ~8bytes hdr */ | | 353 | struct evcnt sc_ev_txptrh0; /* TX packets w/ptrs ~8bytes hdr */ |
354 | struct evcnt sc_ev_txptrh1; /* TX packets w/ptrs ~16bytes hdr */ | | 354 | struct evcnt sc_ev_txptrh1; /* TX packets w/ptrs ~16bytes hdr */ |
355 | struct evcnt sc_ev_txptrh2; /* TX packets w/ptrs ~32bytes hdr */ | | 355 | struct evcnt sc_ev_txptrh2; /* TX packets w/ptrs ~32bytes hdr */ |
356 | struct evcnt sc_ev_txptrh3; /* TX packets w/ptrs ~64bytes hdr */ | | 356 | struct evcnt sc_ev_txptrh3; /* TX packets w/ptrs ~64bytes hdr */ |
357 | struct evcnt sc_ev_txptrh4; /* TX packets w/ptrs ~80bytes hdr */ | | 357 | struct evcnt sc_ev_txptrh4; /* TX packets w/ptrs ~80bytes hdr */ |
358 | struct evcnt sc_ev_txptrh5; /* TX packets w/ptrs ~96bytes hdr */ | | 358 | struct evcnt sc_ev_txptrh5; /* TX packets w/ptrs ~96bytes hdr */ |
359 | struct evcnt sc_ev_txdstall; /* TX stalled due to no txdesc */ | | 359 | struct evcnt sc_ev_txdstall; /* TX stalled due to no txdesc */ |
360 | struct evcnt sc_ev_txempty; /* TX empty interrupts */ | | 360 | struct evcnt sc_ev_txempty; /* TX empty interrupts */ |
361 | struct evcnt sc_ev_txsent; /* TX sent interrupts */ | | 361 | struct evcnt sc_ev_txsent; /* TX sent interrupts */ |
362 | #endif | | 362 | #endif |
363 | }; | | 363 | }; |
364 | | | 364 | |
365 | #define MEC_CDTXADDR(sc, x) ((sc)->sc_cddma + MEC_CDTXOFF(x)) | | 365 | #define MEC_CDTXADDR(sc, x) ((sc)->sc_cddma + MEC_CDTXOFF(x)) |
366 | #define MEC_CDRXADDR(sc, x) ((sc)->sc_cddma + MEC_CDRXOFF(x)) | | 366 | #define MEC_CDRXADDR(sc, x) ((sc)->sc_cddma + MEC_CDRXOFF(x)) |
367 | | | 367 | |
368 | #define MEC_TXDESCSYNC(sc, x, ops) \ | | 368 | #define MEC_TXDESCSYNC(sc, x, ops) \ |
369 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 369 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
370 | MEC_CDTXOFF(x), MEC_TXDESCSIZE, (ops)) | | 370 | MEC_CDTXOFF(x), MEC_TXDESCSIZE, (ops)) |
371 | #define MEC_TXCMDSYNC(sc, x, ops) \ | | 371 | #define MEC_TXCMDSYNC(sc, x, ops) \ |
372 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 372 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
373 | MEC_CDTXOFF(x), sizeof(uint64_t), (ops)) | | 373 | MEC_CDTXOFF(x), sizeof(uint64_t), (ops)) |
374 | | | 374 | |
375 | #define MEC_RXSTATSYNC(sc, x, ops) \ | | 375 | #define MEC_RXSTATSYNC(sc, x, ops) \ |
376 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 376 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
377 | MEC_CDRXOFF(x), sizeof(uint64_t), (ops)) | | 377 | MEC_CDRXOFF(x), sizeof(uint64_t), (ops)) |
378 | #define MEC_RXBUFSYNC(sc, x, len, ops) \ | | 378 | #define MEC_RXBUFSYNC(sc, x, len, ops) \ |
379 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 379 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
380 | MEC_CDRXOFF(x) + MEC_RXD_BUFOFFSET, \ | | 380 | MEC_CDRXOFF(x) + MEC_RXD_BUFOFFSET, \ |
381 | MEC_ETHER_ALIGN + (len), (ops)) | | 381 | MEC_ETHER_ALIGN + (len), (ops)) |
382 | | | 382 | |
383 | /* XXX these values should be moved to <net/if_ether.h> ? */ | | 383 | /* XXX these values should be moved to <net/if_ether.h> ? */ |
384 | #define ETHER_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN) | | 384 | #define ETHER_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN) |
385 | #define MEC_ETHER_ALIGN 2 | | 385 | #define MEC_ETHER_ALIGN 2 |
386 | | | 386 | |
387 | static int mec_match(device_t, cfdata_t, void *); | | 387 | static int mec_match(device_t, cfdata_t, void *); |
388 | static void mec_attach(device_t, device_t, void *); | | 388 | static void mec_attach(device_t, device_t, void *); |
389 | | | 389 | |
390 | static int mec_mii_readreg(device_t, int, int); | | 390 | static int mec_mii_readreg(device_t, int, int); |
391 | static void mec_mii_writereg(device_t, int, int, int); | | 391 | static void mec_mii_writereg(device_t, int, int, int); |
392 | static int mec_mii_wait(struct mec_softc *); | | 392 | static int mec_mii_wait(struct mec_softc *); |
393 | static void mec_statchg(struct ifnet *); | | 393 | static void mec_statchg(struct ifnet *); |
394 | | | 394 | |
395 | static int mec_init(struct ifnet * ifp); | | 395 | static int mec_init(struct ifnet * ifp); |
396 | static void mec_start(struct ifnet *); | | 396 | static void mec_start(struct ifnet *); |
397 | static void mec_watchdog(struct ifnet *); | | 397 | static void mec_watchdog(struct ifnet *); |
398 | static void mec_tick(void *); | | 398 | static void mec_tick(void *); |
399 | static int mec_ioctl(struct ifnet *, u_long, void *); | | 399 | static int mec_ioctl(struct ifnet *, u_long, void *); |
400 | static void mec_reset(struct mec_softc *); | | 400 | static void mec_reset(struct mec_softc *); |
401 | static void mec_setfilter(struct mec_softc *); | | 401 | static void mec_setfilter(struct mec_softc *); |
402 | static int mec_intr(void *arg); | | 402 | static int mec_intr(void *arg); |
403 | static void mec_stop(struct ifnet *, int); | | 403 | static void mec_stop(struct ifnet *, int); |
404 | static void mec_rxintr(struct mec_softc *); | | 404 | static void mec_rxintr(struct mec_softc *); |
405 | static void mec_rxcsum(struct mec_softc *, struct mbuf *, uint16_t, | | 405 | static void mec_rxcsum(struct mec_softc *, struct mbuf *, uint16_t, |
406 | uint32_t); | | 406 | uint32_t); |
407 | static void mec_txintr(struct mec_softc *, uint32_t); | | 407 | static void mec_txintr(struct mec_softc *, uint32_t); |
408 | static bool mec_shutdown(device_t, int); | | 408 | static bool mec_shutdown(device_t, int); |
409 | | | 409 | |
410 | CFATTACH_DECL_NEW(mec, sizeof(struct mec_softc), | | 410 | CFATTACH_DECL_NEW(mec, sizeof(struct mec_softc), |
411 | mec_match, mec_attach, NULL, NULL); | | 411 | mec_match, mec_attach, NULL, NULL); |
412 | | | 412 | |
413 | static int mec_matched = 0; | | 413 | static int mec_matched = 0; |
414 | | | 414 | |
415 | static int | | 415 | static int |
416 | mec_match(device_t parent, cfdata_t cf, void *aux) | | 416 | mec_match(device_t parent, cfdata_t cf, void *aux) |
417 | { | | 417 | { |
418 | | | 418 | |
419 | /* allow only one device */ | | 419 | /* allow only one device */ |
420 | if (mec_matched) | | 420 | if (mec_matched) |
421 | return 0; | | 421 | return 0; |
422 | | | 422 | |
423 | mec_matched = 1; | | 423 | mec_matched = 1; |
424 | return 1; | | 424 | return 1; |
425 | } | | 425 | } |
426 | | | 426 | |
427 | static void | | 427 | static void |
428 | mec_attach(device_t parent, device_t self, void *aux) | | 428 | mec_attach(device_t parent, device_t self, void *aux) |
429 | { | | 429 | { |
430 | struct mec_softc *sc = device_private(self); | | 430 | struct mec_softc *sc = device_private(self); |
431 | struct mace_attach_args *maa = aux; | | 431 | struct mace_attach_args *maa = aux; |
432 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 432 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
433 | uint64_t address, command; | | 433 | uint64_t address, command; |
434 | const char *macaddr; | | 434 | const char *macaddr; |
435 | struct mii_softc *child; | | 435 | struct mii_softc *child; |
436 | bus_dma_segment_t seg; | | 436 | bus_dma_segment_t seg; |
437 | int i, err, rseg; | | 437 | int i, err, rseg; |
438 | bool mac_is_fake; | | 438 | bool mac_is_fake; |
439 | | | 439 | |
440 | sc->sc_dev = self; | | 440 | sc->sc_dev = self; |
441 | sc->sc_st = maa->maa_st; | | 441 | sc->sc_st = maa->maa_st; |
442 | if (bus_space_subregion(sc->sc_st, maa->maa_sh, | | 442 | if (bus_space_subregion(sc->sc_st, maa->maa_sh, |
443 | maa->maa_offset, 0, &sc->sc_sh) != 0) { | | 443 | maa->maa_offset, 0, &sc->sc_sh) != 0) { |
444 | aprint_error(": can't map i/o space\n"); | | 444 | aprint_error(": can't map i/o space\n"); |
445 | return; | | 445 | return; |
446 | } | | 446 | } |
447 | | | 447 | |
448 | /* set up DMA structures */ | | 448 | /* set up DMA structures */ |
449 | sc->sc_dmat = maa->maa_dmat; | | 449 | sc->sc_dmat = maa->maa_dmat; |
450 | | | 450 | |
451 | /* | | 451 | /* |
452 | * Allocate the control data structures, and create and load the | | 452 | * Allocate the control data structures, and create and load the |
453 | * DMA map for it. | | 453 | * DMA map for it. |
454 | */ | | 454 | */ |
455 | if ((err = bus_dmamem_alloc(sc->sc_dmat, | | 455 | if ((err = bus_dmamem_alloc(sc->sc_dmat, |
456 | sizeof(struct mec_control_data), MEC_CONTROL_DATA_ALIGN, 0, | | 456 | sizeof(struct mec_control_data), MEC_CONTROL_DATA_ALIGN, 0, |
457 | &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { | | 457 | &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { |
458 | aprint_error(": unable to allocate control data, error = %d\n", | | 458 | aprint_error(": unable to allocate control data, error = %d\n", |
459 | err); | | 459 | err); |
460 | goto fail_0; | | 460 | goto fail_0; |
461 | } | | 461 | } |
462 | /* | | 462 | /* |
463 | * XXX needs re-think... | | 463 | * XXX needs re-think... |
464 | * control data structures contain whole RX data buffer, so | | 464 | * control data structures contain whole RX data buffer, so |
465 | * BUS_DMA_COHERENT (which disables cache) may cause some performance | | 465 | * BUS_DMA_COHERENT (which disables cache) may cause some performance |
466 | * issue on copying data from the RX buffer to mbuf on normal memory, | | 466 | * issue on copying data from the RX buffer to mbuf on normal memory, |
467 | * though we have to make sure all bus_dmamap_sync(9) ops are called | | 467 | * though we have to make sure all bus_dmamap_sync(9) ops are called |
468 | * properly in that case. | | 468 | * properly in that case. |
469 | */ | | 469 | */ |
470 | if ((err = bus_dmamem_map(sc->sc_dmat, &seg, rseg, | | 470 | if ((err = bus_dmamem_map(sc->sc_dmat, &seg, rseg, |
471 | sizeof(struct mec_control_data), | | 471 | sizeof(struct mec_control_data), |
472 | (void **)&sc->sc_control_data, /*BUS_DMA_COHERENT*/ 0)) != 0) { | | 472 | (void **)&sc->sc_control_data, /*BUS_DMA_COHERENT*/ 0)) != 0) { |
473 | aprint_error(": unable to map control data, error = %d\n", err); | | 473 | aprint_error(": unable to map control data, error = %d\n", err); |
474 | goto fail_1; | | 474 | goto fail_1; |
475 | } | | 475 | } |
476 | memset(sc->sc_control_data, 0, sizeof(struct mec_control_data)); | | 476 | memset(sc->sc_control_data, 0, sizeof(struct mec_control_data)); |
477 | | | 477 | |
478 | if ((err = bus_dmamap_create(sc->sc_dmat, | | 478 | if ((err = bus_dmamap_create(sc->sc_dmat, |
479 | sizeof(struct mec_control_data), 1, | | 479 | sizeof(struct mec_control_data), 1, |
480 | sizeof(struct mec_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { | | 480 | sizeof(struct mec_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { |
481 | aprint_error(": unable to create control data DMA map," | | 481 | aprint_error(": unable to create control data DMA map," |
482 | " error = %d\n", err); | | 482 | " error = %d\n", err); |
483 | goto fail_2; | | 483 | goto fail_2; |
484 | } | | 484 | } |
485 | if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, | | 485 | if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, |
486 | sc->sc_control_data, sizeof(struct mec_control_data), NULL, | | 486 | sc->sc_control_data, sizeof(struct mec_control_data), NULL, |
487 | BUS_DMA_NOWAIT)) != 0) { | | 487 | BUS_DMA_NOWAIT)) != 0) { |
488 | aprint_error(": unable to load control data DMA map," | | 488 | aprint_error(": unable to load control data DMA map," |
489 | " error = %d\n", err); | | 489 | " error = %d\n", err); |
490 | goto fail_3; | | 490 | goto fail_3; |
491 | } | | 491 | } |
492 | | | 492 | |
493 | /* create TX buffer DMA maps */ | | 493 | /* create TX buffer DMA maps */ |
494 | for (i = 0; i < MEC_NTXDESC; i++) { | | 494 | for (i = 0; i < MEC_NTXDESC; i++) { |
495 | if ((err = bus_dmamap_create(sc->sc_dmat, | | 495 | if ((err = bus_dmamap_create(sc->sc_dmat, |
496 | MCLBYTES, MEC_NTXSEG, MCLBYTES, PAGE_SIZE, 0, | | 496 | MCLBYTES, MEC_NTXSEG, MCLBYTES, PAGE_SIZE, 0, |
497 | &sc->sc_txsoft[i].txs_dmamap)) != 0) { | | 497 | &sc->sc_txsoft[i].txs_dmamap)) != 0) { |
498 | aprint_error(": unable to create tx DMA map %d," | | 498 | aprint_error(": unable to create tx DMA map %d," |
499 | " error = %d\n", i, err); | | 499 | " error = %d\n", i, err); |
500 | goto fail_4; | | 500 | goto fail_4; |
501 | } | | 501 | } |
502 | } | | 502 | } |
503 | | | 503 | |
504 | callout_init(&sc->sc_tick_ch, 0); | | 504 | callout_init(&sc->sc_tick_ch, 0); |
505 | | | 505 | |
506 | /* get Ethernet address from ARCBIOS */ | | 506 | /* get Ethernet address from ARCBIOS */ |
507 | if ((macaddr = arcbios_GetEnvironmentVariable("eaddr")) == NULL) { | | 507 | if ((macaddr = arcbios_GetEnvironmentVariable("eaddr")) == NULL) { |
508 | aprint_error(": unable to get MAC address!\n"); | | 508 | aprint_error(": unable to get MAC address!\n"); |
509 | goto fail_4; | | 509 | goto fail_4; |
510 | } | | 510 | } |
511 | /* | | 511 | /* |
512 | * On some machines the DS2502 chip storing the serial number/ | | 512 | * On some machines the DS2502 chip storing the serial number/ |
513 | * mac address is on the pci riser board - if this board is | | 513 | * mac address is on the pci riser board - if this board is |
514 | * missing, ARCBIOS will not know a good ethernet address (but | | 514 | * missing, ARCBIOS will not know a good ethernet address (but |
515 | * otherwise the machine will work fine). | | 515 | * otherwise the machine will work fine). |
516 | */ | | 516 | */ |
517 | mac_is_fake = false; | | 517 | mac_is_fake = false; |
518 | if (strcmp(macaddr, "ff:ff:ff:ff:ff:ff") == 0) { | | 518 | if (strcmp(macaddr, "ff:ff:ff:ff:ff:ff") == 0) { |
519 | uint32_t ui = 0; | | 519 | uint32_t ui = 0; |
520 | const char * netaddr = | | 520 | const char * netaddr = |
521 | arcbios_GetEnvironmentVariable("netaddr"); | | 521 | arcbios_GetEnvironmentVariable("netaddr"); |
522 | | | 522 | |
523 | /* | | 523 | /* |
524 | * Create a MAC address by abusing the "netaddr" env var | | 524 | * Create a MAC address by abusing the "netaddr" env var |
525 | */ | | 525 | */ |
526 | sc->sc_enaddr[0] = 0xf2; | | 526 | sc->sc_enaddr[0] = 0xf2; |
527 | sc->sc_enaddr[1] = 0x0b; | | 527 | sc->sc_enaddr[1] = 0x0b; |
528 | sc->sc_enaddr[2] = 0xa4; | | 528 | sc->sc_enaddr[2] = 0xa4; |
529 | if (netaddr) { | | 529 | if (netaddr) { |
530 | mac_is_fake = true; | | 530 | mac_is_fake = true; |
531 | while (*netaddr) { | | 531 | while (*netaddr) { |
532 | int v = 0; | | 532 | int v = 0; |
533 | while (*netaddr && *netaddr != '.') { | | 533 | while (*netaddr && *netaddr != '.') { |
534 | if (*netaddr >= '0' && *netaddr <= '9') | | 534 | if (*netaddr >= '0' && *netaddr <= '9') |
535 | v = v*10 + (*netaddr - '0'); | | 535 | v = v*10 + (*netaddr - '0'); |
536 | netaddr++; | | 536 | netaddr++; |
537 | } | | 537 | } |
538 | ui <<= 8; | | 538 | ui <<= 8; |
539 | ui |= v; | | 539 | ui |= v; |
540 | if (*netaddr == '.') | | 540 | if (*netaddr == '.') |
541 | netaddr++; | | 541 | netaddr++; |
542 | } | | 542 | } |
543 | } | | 543 | } |
544 | memcpy(sc->sc_enaddr+3, ((uint8_t *)&ui)+1, 3); | | 544 | memcpy(sc->sc_enaddr+3, ((uint8_t *)&ui)+1, 3); |
545 | } | | 545 | } |
546 | if (!mac_is_fake) | | 546 | if (!mac_is_fake) |
547 | ether_aton_r(sc->sc_enaddr, sizeof(sc->sc_enaddr), macaddr); | | 547 | ether_aton_r(sc->sc_enaddr, sizeof(sc->sc_enaddr), macaddr); |
548 | | | 548 | |
549 | /* set the Ethernet address */ | | 549 | /* set the Ethernet address */ |
550 | address = 0; | | 550 | address = 0; |
551 | for (i = 0; i < ETHER_ADDR_LEN; i++) { | | 551 | for (i = 0; i < ETHER_ADDR_LEN; i++) { |
552 | address = address << 8; | | 552 | address = address << 8; |
553 | address |= sc->sc_enaddr[i]; | | 553 | address |= sc->sc_enaddr[i]; |
554 | } | | 554 | } |
555 | bus_space_write_8(sc->sc_st, sc->sc_sh, MEC_STATION, address); | | 555 | bus_space_write_8(sc->sc_st, sc->sc_sh, MEC_STATION, address); |
556 | | | 556 | |
557 | /* reset device */ | | 557 | /* reset device */ |
558 | mec_reset(sc); | | 558 | mec_reset(sc); |
559 | | | 559 | |
560 | command = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_MAC_CONTROL); | | 560 | command = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_MAC_CONTROL); |
561 | | | 561 | |
562 | aprint_normal(": MAC-110 Ethernet, rev %u\n", | | 562 | aprint_normal(": MAC-110 Ethernet, rev %u\n", |
563 | (u_int)((command & MEC_MAC_REVISION) >> MEC_MAC_REVISION_SHIFT)); | | 563 | (u_int)((command & MEC_MAC_REVISION) >> MEC_MAC_REVISION_SHIFT)); |
564 | | | 564 | |
565 | if (mac_is_fake) | | 565 | if (mac_is_fake) |
566 | aprint_normal_dev(self, | | 566 | aprint_normal_dev(self, |
567 | "could not get ethernet address from firmware" | | 567 | "could not get ethernet address from firmware" |
568 | " - generated one from the \"netaddr\" environment" | | 568 | " - generated one from the \"netaddr\" environment" |
569 | " variable\n"); | | 569 | " variable\n"); |
570 | aprint_normal_dev(self, "Ethernet address %s\n", | | 570 | aprint_normal_dev(self, "Ethernet address %s\n", |
571 | ether_sprintf(sc->sc_enaddr)); | | 571 | ether_sprintf(sc->sc_enaddr)); |
572 | | | 572 | |
573 | /* Done, now attach everything */ | | 573 | /* Done, now attach everything */ |
574 | | | 574 | |
575 | sc->sc_mii.mii_ifp = ifp; | | 575 | sc->sc_mii.mii_ifp = ifp; |
576 | sc->sc_mii.mii_readreg = mec_mii_readreg; | | 576 | sc->sc_mii.mii_readreg = mec_mii_readreg; |
577 | sc->sc_mii.mii_writereg = mec_mii_writereg; | | 577 | sc->sc_mii.mii_writereg = mec_mii_writereg; |
578 | sc->sc_mii.mii_statchg = mec_statchg; | | 578 | sc->sc_mii.mii_statchg = mec_statchg; |
579 | | | 579 | |
580 | /* Set up PHY properties */ | | 580 | /* Set up PHY properties */ |
581 | sc->sc_ethercom.ec_mii = &sc->sc_mii; | | 581 | sc->sc_ethercom.ec_mii = &sc->sc_mii; |
582 | ifmedia_init(&sc->sc_mii.mii_media, 0, ether_mediachange, | | 582 | ifmedia_init(&sc->sc_mii.mii_media, 0, ether_mediachange, |
583 | ether_mediastatus); | | 583 | ether_mediastatus); |
584 | mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, | | 584 | mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, |
585 | MII_OFFSET_ANY, 0); | | 585 | MII_OFFSET_ANY, 0); |
586 | | | 586 | |
587 | child = LIST_FIRST(&sc->sc_mii.mii_phys); | | 587 | child = LIST_FIRST(&sc->sc_mii.mii_phys); |
588 | if (child == NULL) { | | 588 | if (child == NULL) { |
589 | /* No PHY attached */ | | 589 | /* No PHY attached */ |
590 | ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, | | 590 | ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, |
591 | 0, NULL); | | 591 | 0, NULL); |
592 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL); | | 592 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL); |
593 | } else { | | 593 | } else { |
594 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); | | 594 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); |
595 | sc->sc_phyaddr = child->mii_phy; | | 595 | sc->sc_phyaddr = child->mii_phy; |
596 | } | | 596 | } |
597 | | | 597 | |
598 | strcpy(ifp->if_xname, device_xname(self)); | | 598 | strcpy(ifp->if_xname, device_xname(self)); |
599 | ifp->if_softc = sc; | | 599 | ifp->if_softc = sc; |
600 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | | 600 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; |
601 | ifp->if_ioctl = mec_ioctl; | | 601 | ifp->if_ioctl = mec_ioctl; |
602 | ifp->if_start = mec_start; | | 602 | ifp->if_start = mec_start; |
603 | ifp->if_watchdog = mec_watchdog; | | 603 | ifp->if_watchdog = mec_watchdog; |
604 | ifp->if_init = mec_init; | | 604 | ifp->if_init = mec_init; |
605 | ifp->if_stop = mec_stop; | | 605 | ifp->if_stop = mec_stop; |
606 | ifp->if_mtu = ETHERMTU; | | 606 | ifp->if_mtu = ETHERMTU; |
607 | IFQ_SET_READY(&ifp->if_snd); | | 607 | IFQ_SET_READY(&ifp->if_snd); |
608 | | | 608 | |
609 | /* mec has dumb RX cksum support */ | | 609 | /* mec has dumb RX cksum support */ |
610 | ifp->if_capabilities = IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx; | | 610 | ifp->if_capabilities = IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx; |
611 | | | 611 | |
612 | /* We can support 802.1Q VLAN-sized frames. */ | | 612 | /* We can support 802.1Q VLAN-sized frames. */ |
613 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; | | 613 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; |
614 | | | 614 | |
615 | /* attach the interface */ | | 615 | /* attach the interface */ |
616 | if_attach(ifp); | | 616 | if_attach(ifp); |
617 | ether_ifattach(ifp, sc->sc_enaddr); | | 617 | ether_ifattach(ifp, sc->sc_enaddr); |
618 | | | 618 | |
619 | /* establish interrupt */ | | 619 | /* establish interrupt */ |
620 | cpu_intr_establish(maa->maa_intr, maa->maa_intrmask, mec_intr, sc); | | 620 | cpu_intr_establish(maa->maa_intr, maa->maa_intrmask, mec_intr, sc); |
621 | | | 621 | |
622 | rnd_attach_source(&sc->sc_rnd_source, device_xname(self), | | 622 | rnd_attach_source(&sc->sc_rnd_source, device_xname(self), |
623 | RND_TYPE_NET, RND_FLAG_DEFAULT); | | 623 | RND_TYPE_NET, RND_FLAG_DEFAULT); |
624 | | | 624 | |
625 | #ifdef MEC_EVENT_COUNTERS | | 625 | #ifdef MEC_EVENT_COUNTERS |
626 | evcnt_attach_dynamic(&sc->sc_ev_txpkts , EVCNT_TYPE_MISC, | | 626 | evcnt_attach_dynamic(&sc->sc_ev_txpkts , EVCNT_TYPE_MISC, |
627 | NULL, device_xname(self), "TX pkts queued total"); | | 627 | NULL, device_xname(self), "TX pkts queued total"); |
628 | evcnt_attach_dynamic(&sc->sc_ev_txdpad , EVCNT_TYPE_MISC, | | 628 | evcnt_attach_dynamic(&sc->sc_ev_txdpad , EVCNT_TYPE_MISC, |
629 | NULL, device_xname(self), "TX pkts padded in txdesc buf"); | | 629 | NULL, device_xname(self), "TX pkts padded in txdesc buf"); |
630 | evcnt_attach_dynamic(&sc->sc_ev_txdbuf , EVCNT_TYPE_MISC, | | 630 | evcnt_attach_dynamic(&sc->sc_ev_txdbuf , EVCNT_TYPE_MISC, |
631 | NULL, device_xname(self), "TX pkts copied to txdesc buf"); | | 631 | NULL, device_xname(self), "TX pkts copied to txdesc buf"); |
632 | evcnt_attach_dynamic(&sc->sc_ev_txptr1 , EVCNT_TYPE_MISC, | | 632 | evcnt_attach_dynamic(&sc->sc_ev_txptr1 , EVCNT_TYPE_MISC, |
633 | NULL, device_xname(self), "TX pkts using concat ptr1"); | | 633 | NULL, device_xname(self), "TX pkts using concat ptr1"); |
634 | evcnt_attach_dynamic(&sc->sc_ev_txptr1a , EVCNT_TYPE_MISC, | | 634 | evcnt_attach_dynamic(&sc->sc_ev_txptr1a , EVCNT_TYPE_MISC, |
635 | NULL, device_xname(self), "TX pkts w/ptr1 ~160bytes"); | | 635 | NULL, device_xname(self), "TX pkts w/ptr1 ~160bytes"); |
636 | evcnt_attach_dynamic(&sc->sc_ev_txptr1b , EVCNT_TYPE_MISC, | | 636 | evcnt_attach_dynamic(&sc->sc_ev_txptr1b , EVCNT_TYPE_MISC, |
637 | NULL, device_xname(self), "TX pkts w/ptr1 ~256bytes"); | | 637 | NULL, device_xname(self), "TX pkts w/ptr1 ~256bytes"); |
638 | evcnt_attach_dynamic(&sc->sc_ev_txptr1c , EVCNT_TYPE_MISC, | | 638 | evcnt_attach_dynamic(&sc->sc_ev_txptr1c , EVCNT_TYPE_MISC, |
639 | NULL, device_xname(self), "TX pkts w/ptr1 ~512bytes"); | | 639 | NULL, device_xname(self), "TX pkts w/ptr1 ~512bytes"); |
640 | evcnt_attach_dynamic(&sc->sc_ev_txptr1d , EVCNT_TYPE_MISC, | | 640 | evcnt_attach_dynamic(&sc->sc_ev_txptr1d , EVCNT_TYPE_MISC, |
641 | NULL, device_xname(self), "TX pkts w/ptr1 ~1024bytes"); | | 641 | NULL, device_xname(self), "TX pkts w/ptr1 ~1024bytes"); |
642 | evcnt_attach_dynamic(&sc->sc_ev_txptr1e , EVCNT_TYPE_MISC, | | 642 | evcnt_attach_dynamic(&sc->sc_ev_txptr1e , EVCNT_TYPE_MISC, |
643 | NULL, device_xname(self), "TX pkts w/ptr1 >1024bytes"); | | 643 | NULL, device_xname(self), "TX pkts w/ptr1 >1024bytes"); |
644 | evcnt_attach_dynamic(&sc->sc_ev_txptr2 , EVCNT_TYPE_MISC, | | 644 | evcnt_attach_dynamic(&sc->sc_ev_txptr2 , EVCNT_TYPE_MISC, |
645 | NULL, device_xname(self), "TX pkts using concat ptr1,2"); | | 645 | NULL, device_xname(self), "TX pkts using concat ptr1,2"); |
646 | evcnt_attach_dynamic(&sc->sc_ev_txptr2a , EVCNT_TYPE_MISC, | | 646 | evcnt_attach_dynamic(&sc->sc_ev_txptr2a , EVCNT_TYPE_MISC, |
647 | NULL, device_xname(self), "TX pkts w/ptr2 ~160bytes"); | | 647 | NULL, device_xname(self), "TX pkts w/ptr2 ~160bytes"); |
648 | evcnt_attach_dynamic(&sc->sc_ev_txptr2b , EVCNT_TYPE_MISC, | | 648 | evcnt_attach_dynamic(&sc->sc_ev_txptr2b , EVCNT_TYPE_MISC, |
649 | NULL, device_xname(self), "TX pkts w/ptr2 ~256bytes"); | | 649 | NULL, device_xname(self), "TX pkts w/ptr2 ~256bytes"); |
650 | evcnt_attach_dynamic(&sc->sc_ev_txptr2c , EVCNT_TYPE_MISC, | | 650 | evcnt_attach_dynamic(&sc->sc_ev_txptr2c , EVCNT_TYPE_MISC, |
651 | NULL, device_xname(self), "TX pkts w/ptr2 ~512bytes"); | | 651 | NULL, device_xname(self), "TX pkts w/ptr2 ~512bytes"); |
652 | evcnt_attach_dynamic(&sc->sc_ev_txptr2d , EVCNT_TYPE_MISC, | | 652 | evcnt_attach_dynamic(&sc->sc_ev_txptr2d , EVCNT_TYPE_MISC, |
653 | NULL, device_xname(self), "TX pkts w/ptr2 ~1024bytes"); | | 653 | NULL, device_xname(self), "TX pkts w/ptr2 ~1024bytes"); |
654 | evcnt_attach_dynamic(&sc->sc_ev_txptr2e , EVCNT_TYPE_MISC, | | 654 | evcnt_attach_dynamic(&sc->sc_ev_txptr2e , EVCNT_TYPE_MISC, |
655 | NULL, device_xname(self), "TX pkts w/ptr2 >1024bytes"); | | 655 | NULL, device_xname(self), "TX pkts w/ptr2 >1024bytes"); |
656 | evcnt_attach_dynamic(&sc->sc_ev_txptr3 , EVCNT_TYPE_MISC, | | 656 | evcnt_attach_dynamic(&sc->sc_ev_txptr3 , EVCNT_TYPE_MISC, |
657 | NULL, device_xname(self), "TX pkts using concat ptr1,2,3"); | | 657 | NULL, device_xname(self), "TX pkts using concat ptr1,2,3"); |
658 | evcnt_attach_dynamic(&sc->sc_ev_txptr3a , EVCNT_TYPE_MISC, | | 658 | evcnt_attach_dynamic(&sc->sc_ev_txptr3a , EVCNT_TYPE_MISC, |
659 | NULL, device_xname(self), "TX pkts w/ptr3 ~160bytes"); | | 659 | NULL, device_xname(self), "TX pkts w/ptr3 ~160bytes"); |
660 | evcnt_attach_dynamic(&sc->sc_ev_txptr3b , EVCNT_TYPE_MISC, | | 660 | evcnt_attach_dynamic(&sc->sc_ev_txptr3b , EVCNT_TYPE_MISC, |
661 | NULL, device_xname(self), "TX pkts w/ptr3 ~256bytes"); | | 661 | NULL, device_xname(self), "TX pkts w/ptr3 ~256bytes"); |
662 | evcnt_attach_dynamic(&sc->sc_ev_txptr3c , EVCNT_TYPE_MISC, | | 662 | evcnt_attach_dynamic(&sc->sc_ev_txptr3c , EVCNT_TYPE_MISC, |
663 | NULL, device_xname(self), "TX pkts w/ptr3 ~512bytes"); | | 663 | NULL, device_xname(self), "TX pkts w/ptr3 ~512bytes"); |
664 | evcnt_attach_dynamic(&sc->sc_ev_txptr3d , EVCNT_TYPE_MISC, | | 664 | evcnt_attach_dynamic(&sc->sc_ev_txptr3d , EVCNT_TYPE_MISC, |
665 | NULL, device_xname(self), "TX pkts w/ptr3 ~1024bytes"); | | 665 | NULL, device_xname(self), "TX pkts w/ptr3 ~1024bytes"); |
666 | evcnt_attach_dynamic(&sc->sc_ev_txptr3e , EVCNT_TYPE_MISC, | | 666 | evcnt_attach_dynamic(&sc->sc_ev_txptr3e , EVCNT_TYPE_MISC, |
667 | NULL, device_xname(self), "TX pkts w/ptr3 >1024bytes"); | | 667 | NULL, device_xname(self), "TX pkts w/ptr3 >1024bytes"); |
668 | evcnt_attach_dynamic(&sc->sc_ev_txmbuf , EVCNT_TYPE_MISC, | | 668 | evcnt_attach_dynamic(&sc->sc_ev_txmbuf , EVCNT_TYPE_MISC, |
669 | NULL, device_xname(self), "TX pkts copied to new mbufs"); | | 669 | NULL, device_xname(self), "TX pkts copied to new mbufs"); |
670 | evcnt_attach_dynamic(&sc->sc_ev_txmbufa , EVCNT_TYPE_MISC, | | 670 | evcnt_attach_dynamic(&sc->sc_ev_txmbufa , EVCNT_TYPE_MISC, |
671 | NULL, device_xname(self), "TX pkts w/mbuf ~160bytes"); | | 671 | NULL, device_xname(self), "TX pkts w/mbuf ~160bytes"); |
672 | evcnt_attach_dynamic(&sc->sc_ev_txmbufb , EVCNT_TYPE_MISC, | | 672 | evcnt_attach_dynamic(&sc->sc_ev_txmbufb , EVCNT_TYPE_MISC, |
673 | NULL, device_xname(self), "TX pkts w/mbuf ~256bytes"); | | 673 | NULL, device_xname(self), "TX pkts w/mbuf ~256bytes"); |
674 | evcnt_attach_dynamic(&sc->sc_ev_txmbufc , EVCNT_TYPE_MISC, | | 674 | evcnt_attach_dynamic(&sc->sc_ev_txmbufc , EVCNT_TYPE_MISC, |
675 | NULL, device_xname(self), "TX pkts w/mbuf ~512bytes"); | | 675 | NULL, device_xname(self), "TX pkts w/mbuf ~512bytes"); |
676 | evcnt_attach_dynamic(&sc->sc_ev_txmbufd , EVCNT_TYPE_MISC, | | 676 | evcnt_attach_dynamic(&sc->sc_ev_txmbufd , EVCNT_TYPE_MISC, |
677 | NULL, device_xname(self), "TX pkts w/mbuf ~1024bytes"); | | 677 | NULL, device_xname(self), "TX pkts w/mbuf ~1024bytes"); |
678 | evcnt_attach_dynamic(&sc->sc_ev_txmbufe , EVCNT_TYPE_MISC, | | 678 | evcnt_attach_dynamic(&sc->sc_ev_txmbufe , EVCNT_TYPE_MISC, |
679 | NULL, device_xname(self), "TX pkts w/mbuf >1024bytes"); | | 679 | NULL, device_xname(self), "TX pkts w/mbuf >1024bytes"); |
680 | evcnt_attach_dynamic(&sc->sc_ev_txptrs , EVCNT_TYPE_MISC, | | 680 | evcnt_attach_dynamic(&sc->sc_ev_txptrs , EVCNT_TYPE_MISC, |
681 | NULL, device_xname(self), "TX pkts using ptrs total"); | | 681 | NULL, device_xname(self), "TX pkts using ptrs total"); |
682 | evcnt_attach_dynamic(&sc->sc_ev_txptrc0 , EVCNT_TYPE_MISC, | | 682 | evcnt_attach_dynamic(&sc->sc_ev_txptrc0 , EVCNT_TYPE_MISC, |
683 | NULL, device_xname(self), "TX pkts w/ptrs no hdr chain"); | | 683 | NULL, device_xname(self), "TX pkts w/ptrs no hdr chain"); |
684 | evcnt_attach_dynamic(&sc->sc_ev_txptrc1 , EVCNT_TYPE_MISC, | | 684 | evcnt_attach_dynamic(&sc->sc_ev_txptrc1 , EVCNT_TYPE_MISC, |
685 | NULL, device_xname(self), "TX pkts w/ptrs 1 hdr chain"); | | 685 | NULL, device_xname(self), "TX pkts w/ptrs 1 hdr chain"); |
686 | evcnt_attach_dynamic(&sc->sc_ev_txptrc2 , EVCNT_TYPE_MISC, | | 686 | evcnt_attach_dynamic(&sc->sc_ev_txptrc2 , EVCNT_TYPE_MISC, |
687 | NULL, device_xname(self), "TX pkts w/ptrs 2 hdr chains"); | | 687 | NULL, device_xname(self), "TX pkts w/ptrs 2 hdr chains"); |
688 | evcnt_attach_dynamic(&sc->sc_ev_txptrc3 , EVCNT_TYPE_MISC, | | 688 | evcnt_attach_dynamic(&sc->sc_ev_txptrc3 , EVCNT_TYPE_MISC, |
689 | NULL, device_xname(self), "TX pkts w/ptrs 3 hdr chains"); | | 689 | NULL, device_xname(self), "TX pkts w/ptrs 3 hdr chains"); |
690 | evcnt_attach_dynamic(&sc->sc_ev_txptrc4 , EVCNT_TYPE_MISC, | | 690 | evcnt_attach_dynamic(&sc->sc_ev_txptrc4 , EVCNT_TYPE_MISC, |
691 | NULL, device_xname(self), "TX pkts w/ptrs 4 hdr chains"); | | 691 | NULL, device_xname(self), "TX pkts w/ptrs 4 hdr chains"); |
692 | evcnt_attach_dynamic(&sc->sc_ev_txptrc5 , EVCNT_TYPE_MISC, | | 692 | evcnt_attach_dynamic(&sc->sc_ev_txptrc5 , EVCNT_TYPE_MISC, |
693 | NULL, device_xname(self), "TX pkts w/ptrs 5 hdr chains"); | | 693 | NULL, device_xname(self), "TX pkts w/ptrs 5 hdr chains"); |
694 | evcnt_attach_dynamic(&sc->sc_ev_txptrc6 , EVCNT_TYPE_MISC, | | 694 | evcnt_attach_dynamic(&sc->sc_ev_txptrc6 , EVCNT_TYPE_MISC, |
695 | NULL, device_xname(self), "TX pkts w/ptrs >5 hdr chains"); | | 695 | NULL, device_xname(self), "TX pkts w/ptrs >5 hdr chains"); |
696 | evcnt_attach_dynamic(&sc->sc_ev_txptrh0 , EVCNT_TYPE_MISC, | | 696 | evcnt_attach_dynamic(&sc->sc_ev_txptrh0 , EVCNT_TYPE_MISC, |
697 | NULL, device_xname(self), "TX pkts w/ptrs ~8bytes hdr"); | | 697 | NULL, device_xname(self), "TX pkts w/ptrs ~8bytes hdr"); |
698 | evcnt_attach_dynamic(&sc->sc_ev_txptrh1 , EVCNT_TYPE_MISC, | | 698 | evcnt_attach_dynamic(&sc->sc_ev_txptrh1 , EVCNT_TYPE_MISC, |
699 | NULL, device_xname(self), "TX pkts w/ptrs ~16bytes hdr"); | | 699 | NULL, device_xname(self), "TX pkts w/ptrs ~16bytes hdr"); |
700 | evcnt_attach_dynamic(&sc->sc_ev_txptrh2 , EVCNT_TYPE_MISC, | | 700 | evcnt_attach_dynamic(&sc->sc_ev_txptrh2 , EVCNT_TYPE_MISC, |
701 | NULL, device_xname(self), "TX pkts w/ptrs ~32bytes hdr"); | | 701 | NULL, device_xname(self), "TX pkts w/ptrs ~32bytes hdr"); |
702 | evcnt_attach_dynamic(&sc->sc_ev_txptrh3 , EVCNT_TYPE_MISC, | | 702 | evcnt_attach_dynamic(&sc->sc_ev_txptrh3 , EVCNT_TYPE_MISC, |
703 | NULL, device_xname(self), "TX pkts w/ptrs ~64bytes hdr"); | | 703 | NULL, device_xname(self), "TX pkts w/ptrs ~64bytes hdr"); |
704 | evcnt_attach_dynamic(&sc->sc_ev_txptrh4 , EVCNT_TYPE_MISC, | | 704 | evcnt_attach_dynamic(&sc->sc_ev_txptrh4 , EVCNT_TYPE_MISC, |
705 | NULL, device_xname(self), "TX pkts w/ptrs ~80bytes hdr"); | | 705 | NULL, device_xname(self), "TX pkts w/ptrs ~80bytes hdr"); |
706 | evcnt_attach_dynamic(&sc->sc_ev_txptrh5 , EVCNT_TYPE_MISC, | | 706 | evcnt_attach_dynamic(&sc->sc_ev_txptrh5 , EVCNT_TYPE_MISC, |
707 | NULL, device_xname(self), "TX pkts w/ptrs ~96bytes hdr"); | | 707 | NULL, device_xname(self), "TX pkts w/ptrs ~96bytes hdr"); |
708 | evcnt_attach_dynamic(&sc->sc_ev_txdstall , EVCNT_TYPE_MISC, | | 708 | evcnt_attach_dynamic(&sc->sc_ev_txdstall , EVCNT_TYPE_MISC, |
709 | NULL, device_xname(self), "TX stalled due to no txdesc"); | | 709 | NULL, device_xname(self), "TX stalled due to no txdesc"); |
710 | evcnt_attach_dynamic(&sc->sc_ev_txempty , EVCNT_TYPE_MISC, | | 710 | evcnt_attach_dynamic(&sc->sc_ev_txempty , EVCNT_TYPE_MISC, |
711 | NULL, device_xname(self), "TX empty interrupts"); | | 711 | NULL, device_xname(self), "TX empty interrupts"); |
712 | evcnt_attach_dynamic(&sc->sc_ev_txsent , EVCNT_TYPE_MISC, | | 712 | evcnt_attach_dynamic(&sc->sc_ev_txsent , EVCNT_TYPE_MISC, |
713 | NULL, device_xname(self), "TX sent interrupts"); | | 713 | NULL, device_xname(self), "TX sent interrupts"); |
714 | #endif | | 714 | #endif |
715 | | | 715 | |
716 | /* set shutdown hook to reset interface on powerdown */ | | 716 | /* set shutdown hook to reset interface on powerdown */ |
717 | if (pmf_device_register1(self, NULL, NULL, mec_shutdown)) | | 717 | if (pmf_device_register1(self, NULL, NULL, mec_shutdown)) |
718 | pmf_class_network_register(self, ifp); | | 718 | pmf_class_network_register(self, ifp); |
719 | else | | 719 | else |
720 | aprint_error_dev(self, "couldn't establish power handler\n"); | | 720 | aprint_error_dev(self, "couldn't establish power handler\n"); |
721 | | | 721 | |
722 | return; | | 722 | return; |
723 | | | 723 | |
724 | /* | | 724 | /* |
725 | * Free any resources we've allocated during the failed attach | | 725 | * Free any resources we've allocated during the failed attach |
726 | * attempt. Do this in reverse order and fall though. | | 726 | * attempt. Do this in reverse order and fall though. |
727 | */ | | 727 | */ |
728 | fail_4: | | 728 | fail_4: |
729 | for (i = 0; i < MEC_NTXDESC; i++) { | | 729 | for (i = 0; i < MEC_NTXDESC; i++) { |
730 | if (sc->sc_txsoft[i].txs_dmamap != NULL) | | 730 | if (sc->sc_txsoft[i].txs_dmamap != NULL) |
731 | bus_dmamap_destroy(sc->sc_dmat, | | 731 | bus_dmamap_destroy(sc->sc_dmat, |
732 | sc->sc_txsoft[i].txs_dmamap); | | 732 | sc->sc_txsoft[i].txs_dmamap); |
733 | } | | 733 | } |
734 | bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); | | 734 | bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); |
735 | fail_3: | | 735 | fail_3: |
736 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); | | 736 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); |
737 | fail_2: | | 737 | fail_2: |
738 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, | | 738 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, |
739 | sizeof(struct mec_control_data)); | | 739 | sizeof(struct mec_control_data)); |
740 | fail_1: | | 740 | fail_1: |
741 | bus_dmamem_free(sc->sc_dmat, &seg, rseg); | | 741 | bus_dmamem_free(sc->sc_dmat, &seg, rseg); |
742 | fail_0: | | 742 | fail_0: |
743 | return; | | 743 | return; |
744 | } | | 744 | } |
745 | | | 745 | |
746 | static int | | 746 | static int |
747 | mec_mii_readreg(device_t self, int phy, int reg) | | 747 | mec_mii_readreg(device_t self, int phy, int reg) |
748 | { | | 748 | { |
749 | struct mec_softc *sc = device_private(self); | | 749 | struct mec_softc *sc = device_private(self); |
750 | bus_space_tag_t st = sc->sc_st; | | 750 | bus_space_tag_t st = sc->sc_st; |
751 | bus_space_handle_t sh = sc->sc_sh; | | 751 | bus_space_handle_t sh = sc->sc_sh; |
752 | uint64_t val; | | 752 | uint64_t val; |
753 | int i; | | 753 | int i; |
754 | | | 754 | |
755 | if (mec_mii_wait(sc) != 0) | | 755 | if (mec_mii_wait(sc) != 0) |
756 | return 0; | | 756 | return 0; |
757 | | | 757 | |
758 | bus_space_write_8(st, sh, MEC_PHY_ADDRESS, | | 758 | bus_space_write_8(st, sh, MEC_PHY_ADDRESS, |
759 | (phy << MEC_PHY_ADDR_DEVSHIFT) | (reg & MEC_PHY_ADDR_REGISTER)); | | 759 | (phy << MEC_PHY_ADDR_DEVSHIFT) | (reg & MEC_PHY_ADDR_REGISTER)); |
760 | delay(25); | | 760 | delay(25); |
761 | bus_space_write_8(st, sh, MEC_PHY_READ_INITIATE, 1); | | 761 | bus_space_write_8(st, sh, MEC_PHY_READ_INITIATE, 1); |
762 | delay(25); | | 762 | delay(25); |
763 | mec_mii_wait(sc); | | 763 | mec_mii_wait(sc); |
764 | | | 764 | |
765 | for (i = 0; i < 20; i++) { | | 765 | for (i = 0; i < 20; i++) { |
766 | delay(30); | | 766 | delay(30); |
767 | | | 767 | |
768 | val = bus_space_read_8(st, sh, MEC_PHY_DATA); | | 768 | val = bus_space_read_8(st, sh, MEC_PHY_DATA); |
769 | | | 769 | |
770 | if ((val & MEC_PHY_DATA_BUSY) == 0) | | 770 | if ((val & MEC_PHY_DATA_BUSY) == 0) |
771 | return val & MEC_PHY_DATA_VALUE; | | 771 | return val & MEC_PHY_DATA_VALUE; |
772 | } | | 772 | } |
773 | return 0; | | 773 | return 0; |
774 | } | | 774 | } |
775 | | | 775 | |
776 | static void | | 776 | static void |
777 | mec_mii_writereg(device_t self, int phy, int reg, int val) | | 777 | mec_mii_writereg(device_t self, int phy, int reg, int val) |
778 | { | | 778 | { |
779 | struct mec_softc *sc = device_private(self); | | 779 | struct mec_softc *sc = device_private(self); |
780 | bus_space_tag_t st = sc->sc_st; | | 780 | bus_space_tag_t st = sc->sc_st; |
781 | bus_space_handle_t sh = sc->sc_sh; | | 781 | bus_space_handle_t sh = sc->sc_sh; |
782 | | | 782 | |
783 | if (mec_mii_wait(sc) != 0) { | | 783 | if (mec_mii_wait(sc) != 0) { |
784 | printf("timed out writing %x: %x\n", reg, val); | | 784 | printf("timed out writing %x: %x\n", reg, val); |
785 | return; | | 785 | return; |
786 | } | | 786 | } |
787 | | | 787 | |
788 | bus_space_write_8(st, sh, MEC_PHY_ADDRESS, | | 788 | bus_space_write_8(st, sh, MEC_PHY_ADDRESS, |
789 | (phy << MEC_PHY_ADDR_DEVSHIFT) | (reg & MEC_PHY_ADDR_REGISTER)); | | 789 | (phy << MEC_PHY_ADDR_DEVSHIFT) | (reg & MEC_PHY_ADDR_REGISTER)); |
790 | | | 790 | |
791 | delay(60); | | 791 | delay(60); |
792 | | | 792 | |
793 | bus_space_write_8(st, sh, MEC_PHY_DATA, val & MEC_PHY_DATA_VALUE); | | 793 | bus_space_write_8(st, sh, MEC_PHY_DATA, val & MEC_PHY_DATA_VALUE); |
794 | | | 794 | |
795 | delay(60); | | 795 | delay(60); |
796 | | | 796 | |
797 | mec_mii_wait(sc); | | 797 | mec_mii_wait(sc); |
798 | } | | 798 | } |
799 | | | 799 | |
800 | static int | | 800 | static int |
801 | mec_mii_wait(struct mec_softc *sc) | | 801 | mec_mii_wait(struct mec_softc *sc) |
802 | { | | 802 | { |
803 | uint32_t busy; | | 803 | uint32_t busy; |
804 | int i, s; | | 804 | int i, s; |
805 | | | 805 | |
806 | for (i = 0; i < 100; i++) { | | 806 | for (i = 0; i < 100; i++) { |
807 | delay(30); | | 807 | delay(30); |
808 | | | 808 | |
809 | s = splhigh(); | | 809 | s = splhigh(); |
810 | busy = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_PHY_DATA); | | 810 | busy = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_PHY_DATA); |
811 | splx(s); | | 811 | splx(s); |
812 | | | 812 | |
813 | if ((busy & MEC_PHY_DATA_BUSY) == 0) | | 813 | if ((busy & MEC_PHY_DATA_BUSY) == 0) |
814 | return 0; | | 814 | return 0; |
815 | #if 0 | | 815 | #if 0 |
816 | if (busy == 0xffff) /* XXX ? */ | | 816 | if (busy == 0xffff) /* XXX ? */ |
817 | return 0; | | 817 | return 0; |
818 | #endif | | 818 | #endif |
819 | } | | 819 | } |
820 | | | 820 | |
821 | printf("%s: MII timed out\n", device_xname(sc->sc_dev)); | | 821 | printf("%s: MII timed out\n", device_xname(sc->sc_dev)); |
822 | return 1; | | 822 | return 1; |
823 | } | | 823 | } |
824 | | | 824 | |
825 | static void | | 825 | static void |
826 | mec_statchg(struct ifnet *ifp) | | 826 | mec_statchg(struct ifnet *ifp) |
827 | { | | 827 | { |
828 | struct mec_softc *sc = ifp->if_softc; | | 828 | struct mec_softc *sc = ifp->if_softc; |
829 | bus_space_tag_t st = sc->sc_st; | | 829 | bus_space_tag_t st = sc->sc_st; |
830 | bus_space_handle_t sh = sc->sc_sh; | | 830 | bus_space_handle_t sh = sc->sc_sh; |
831 | uint32_t control; | | 831 | uint32_t control; |
832 | | | 832 | |
833 | control = bus_space_read_8(st, sh, MEC_MAC_CONTROL); | | 833 | control = bus_space_read_8(st, sh, MEC_MAC_CONTROL); |
834 | control &= ~(MEC_MAC_IPGT | MEC_MAC_IPGR1 | MEC_MAC_IPGR2 | | | 834 | control &= ~(MEC_MAC_IPGT | MEC_MAC_IPGR1 | MEC_MAC_IPGR2 | |
835 | MEC_MAC_FULL_DUPLEX | MEC_MAC_SPEED_SELECT); | | 835 | MEC_MAC_FULL_DUPLEX | MEC_MAC_SPEED_SELECT); |
836 | | | 836 | |
837 | /* must also set IPG here for duplex stuff ... */ | | 837 | /* must also set IPG here for duplex stuff ... */ |
838 | if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0) { | | 838 | if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0) { |
839 | control |= MEC_MAC_FULL_DUPLEX; | | 839 | control |= MEC_MAC_FULL_DUPLEX; |
840 | } else { | | 840 | } else { |
841 | /* set IPG */ | | 841 | /* set IPG */ |
842 | control |= MEC_MAC_IPG_DEFAULT; | | 842 | control |= MEC_MAC_IPG_DEFAULT; |
843 | } | | 843 | } |
844 | | | 844 | |
845 | bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); | | 845 | bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); |
846 | } | | 846 | } |
847 | | | 847 | |
848 | static int | | 848 | static int |
849 | mec_init(struct ifnet *ifp) | | 849 | mec_init(struct ifnet *ifp) |
850 | { | | 850 | { |
851 | struct mec_softc *sc = ifp->if_softc; | | 851 | struct mec_softc *sc = ifp->if_softc; |
852 | bus_space_tag_t st = sc->sc_st; | | 852 | bus_space_tag_t st = sc->sc_st; |
853 | bus_space_handle_t sh = sc->sc_sh; | | 853 | bus_space_handle_t sh = sc->sc_sh; |
854 | struct mec_rxdesc *rxd; | | 854 | struct mec_rxdesc *rxd; |
855 | int i, rc; | | 855 | int i, rc; |
856 | | | 856 | |
857 | /* cancel any pending I/O */ | | 857 | /* cancel any pending I/O */ |
858 | mec_stop(ifp, 0); | | 858 | mec_stop(ifp, 0); |
859 | | | 859 | |
860 | /* reset device */ | | 860 | /* reset device */ |
861 | mec_reset(sc); | | 861 | mec_reset(sc); |
862 | | | 862 | |
863 | /* setup filter for multicast or promisc mode */ | | 863 | /* setup filter for multicast or promisc mode */ |
864 | mec_setfilter(sc); | | 864 | mec_setfilter(sc); |
865 | | | 865 | |
866 | /* set the TX ring pointer to the base address */ | | 866 | /* set the TX ring pointer to the base address */ |
867 | bus_space_write_8(st, sh, MEC_TX_RING_BASE, MEC_CDTXADDR(sc, 0)); | | 867 | bus_space_write_8(st, sh, MEC_TX_RING_BASE, MEC_CDTXADDR(sc, 0)); |
868 | | | 868 | |
869 | sc->sc_txpending = 0; | | 869 | sc->sc_txpending = 0; |
870 | sc->sc_txdirty = 0; | | 870 | sc->sc_txdirty = 0; |
871 | sc->sc_txlast = MEC_NTXDESC - 1; | | 871 | sc->sc_txlast = MEC_NTXDESC - 1; |
872 | | | 872 | |
873 | /* put RX buffers into FIFO */ | | 873 | /* put RX buffers into FIFO */ |
874 | for (i = 0; i < MEC_NRXDESC; i++) { | | 874 | for (i = 0; i < MEC_NRXDESC; i++) { |
875 | rxd = &sc->sc_rxdesc[i]; | | 875 | rxd = &sc->sc_rxdesc[i]; |
876 | rxd->rxd_stat = 0; | | 876 | rxd->rxd_stat = 0; |
877 | MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); | | 877 | MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); |
878 | MEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD); | | 878 | MEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD); |
879 | bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, MEC_CDRXADDR(sc, i)); | | 879 | bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, MEC_CDRXADDR(sc, i)); |
880 | } | | 880 | } |
881 | sc->sc_rxptr = 0; | | 881 | sc->sc_rxptr = 0; |
882 | | | 882 | |
883 | #if 0 /* XXX no info */ | | 883 | #if 0 /* XXX no info */ |
884 | bus_space_write_8(st, sh, MEC_TIMER, 0); | | 884 | bus_space_write_8(st, sh, MEC_TIMER, 0); |
885 | #endif | | 885 | #endif |
886 | | | 886 | |
887 | /* | | 887 | /* |
888 | * MEC_DMA_TX_INT_ENABLE will be set later otherwise it causes | | 888 | * MEC_DMA_TX_INT_ENABLE will be set later otherwise it causes |
889 | * spurious interrupts when TX buffers are empty | | 889 | * spurious interrupts when TX buffers are empty |
890 | */ | | 890 | */ |
891 | bus_space_write_8(st, sh, MEC_DMA_CONTROL, | | 891 | bus_space_write_8(st, sh, MEC_DMA_CONTROL, |
892 | (MEC_RXD_DMAOFFSET << MEC_DMA_RX_DMA_OFFSET_SHIFT) | | | 892 | (MEC_RXD_DMAOFFSET << MEC_DMA_RX_DMA_OFFSET_SHIFT) | |
893 | (MEC_NRXDESC << MEC_DMA_RX_INT_THRESH_SHIFT) | | | 893 | (MEC_NRXDESC << MEC_DMA_RX_INT_THRESH_SHIFT) | |
894 | MEC_DMA_TX_DMA_ENABLE | /* MEC_DMA_TX_INT_ENABLE | */ | | 894 | MEC_DMA_TX_DMA_ENABLE | /* MEC_DMA_TX_INT_ENABLE | */ |
895 | MEC_DMA_RX_DMA_ENABLE | MEC_DMA_RX_INT_ENABLE); | | 895 | MEC_DMA_RX_DMA_ENABLE | MEC_DMA_RX_INT_ENABLE); |
896 | | | 896 | |
897 | callout_reset(&sc->sc_tick_ch, hz, mec_tick, sc); | | 897 | callout_reset(&sc->sc_tick_ch, hz, mec_tick, sc); |
898 | | | 898 | |
899 | if ((rc = ether_mediachange(ifp)) != 0) | | 899 | if ((rc = ether_mediachange(ifp)) != 0) |
900 | return rc; | | 900 | return rc; |
901 | | | 901 | |
902 | ifp->if_flags |= IFF_RUNNING; | | 902 | ifp->if_flags |= IFF_RUNNING; |
903 | ifp->if_flags &= ~IFF_OACTIVE; | | 903 | ifp->if_flags &= ~IFF_OACTIVE; |
904 | mec_start(ifp); | | 904 | mec_start(ifp); |
905 | | | 905 | |
906 | return 0; | | 906 | return 0; |
907 | } | | 907 | } |
908 | | | 908 | |
909 | static void | | 909 | static void |
910 | mec_reset(struct mec_softc *sc) | | 910 | mec_reset(struct mec_softc *sc) |
911 | { | | 911 | { |
912 | bus_space_tag_t st = sc->sc_st; | | 912 | bus_space_tag_t st = sc->sc_st; |
913 | bus_space_handle_t sh = sc->sc_sh; | | 913 | bus_space_handle_t sh = sc->sc_sh; |
914 | uint64_t control; | | 914 | uint64_t control; |
915 | | | 915 | |
916 | /* stop DMA first */ | | 916 | /* stop DMA first */ |
917 | bus_space_write_8(st, sh, MEC_DMA_CONTROL, 0); | | 917 | bus_space_write_8(st, sh, MEC_DMA_CONTROL, 0); |
918 | | | 918 | |
919 | /* reset chip */ | | 919 | /* reset chip */ |
920 | bus_space_write_8(st, sh, MEC_MAC_CONTROL, MEC_MAC_CORE_RESET); | | 920 | bus_space_write_8(st, sh, MEC_MAC_CONTROL, MEC_MAC_CORE_RESET); |
921 | delay(1000); | | 921 | delay(1000); |
922 | bus_space_write_8(st, sh, MEC_MAC_CONTROL, 0); | | 922 | bus_space_write_8(st, sh, MEC_MAC_CONTROL, 0); |
923 | delay(1000); | | 923 | delay(1000); |
924 | | | 924 | |
925 | /* Default to 100/half and let auto-negotiation work its magic */ | | 925 | /* Default to 100/half and let auto-negotiation work its magic */ |
926 | control = MEC_MAC_SPEED_SELECT | MEC_MAC_FILTER_MATCHMULTI | | | 926 | control = MEC_MAC_SPEED_SELECT | MEC_MAC_FILTER_MATCHMULTI | |
927 | MEC_MAC_IPG_DEFAULT; | | 927 | MEC_MAC_IPG_DEFAULT; |
928 | | | 928 | |
929 | bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); | | 929 | bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); |
930 | /* stop DMA again for sanity */ | | 930 | /* stop DMA again for sanity */ |
931 | bus_space_write_8(st, sh, MEC_DMA_CONTROL, 0); | | 931 | bus_space_write_8(st, sh, MEC_DMA_CONTROL, 0); |
932 | | | 932 | |
933 | DPRINTF(MEC_DEBUG_RESET, ("mec: control now %llx\n", | | 933 | DPRINTF(MEC_DEBUG_RESET, ("mec: control now %llx\n", |
934 | bus_space_read_8(st, sh, MEC_MAC_CONTROL))); | | 934 | bus_space_read_8(st, sh, MEC_MAC_CONTROL))); |
935 | } | | 935 | } |
936 | | | 936 | |
937 | static void | | 937 | static void |
938 | mec_start(struct ifnet *ifp) | | 938 | mec_start(struct ifnet *ifp) |
939 | { | | 939 | { |
940 | struct mec_softc *sc = ifp->if_softc; | | 940 | struct mec_softc *sc = ifp->if_softc; |
941 | struct mbuf *m0, *m; | | 941 | struct mbuf *m0, *m; |
942 | struct mec_txdesc *txd; | | 942 | struct mec_txdesc *txd; |
943 | struct mec_txsoft *txs; | | 943 | struct mec_txsoft *txs; |
944 | bus_dmamap_t dmamap; | | 944 | bus_dmamap_t dmamap; |
945 | bus_space_tag_t st = sc->sc_st; | | 945 | bus_space_tag_t st = sc->sc_st; |
946 | bus_space_handle_t sh = sc->sc_sh; | | 946 | bus_space_handle_t sh = sc->sc_sh; |
947 | int error, firsttx, nexttx, opending; | | 947 | int error, firsttx, nexttx, opending; |
948 | int len, bufoff, buflen, nsegs, align, resid, pseg, nptr, slen, i; | | 948 | int len, bufoff, buflen, nsegs, align, resid, pseg, nptr, slen, i; |
949 | uint32_t txdcmd; | | 949 | uint32_t txdcmd; |
950 | | | 950 | |
951 | if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) | | 951 | if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) |
952 | return; | | 952 | return; |
953 | | | 953 | |
954 | /* | | 954 | /* |
955 | * Remember the previous txpending and the first transmit descriptor. | | 955 | * Remember the previous txpending and the first transmit descriptor. |
956 | */ | | 956 | */ |
957 | opending = sc->sc_txpending; | | 957 | opending = sc->sc_txpending; |
958 | firsttx = MEC_NEXTTX(sc->sc_txlast); | | 958 | firsttx = MEC_NEXTTX(sc->sc_txlast); |
959 | | | 959 | |
960 | DPRINTF(MEC_DEBUG_START, | | 960 | DPRINTF(MEC_DEBUG_START, |
961 | ("%s: opending = %d, firsttx = %d\n", __func__, opending, firsttx)); | | 961 | ("%s: opending = %d, firsttx = %d\n", __func__, opending, firsttx)); |
962 | | | 962 | |
963 | while (sc->sc_txpending < MEC_NTXDESC - 1) { | | 963 | while (sc->sc_txpending < MEC_NTXDESC - 1) { |
964 | /* Grab a packet off the queue. */ | | 964 | /* Grab a packet off the queue. */ |
965 | IFQ_POLL(&ifp->if_snd, m0); | | 965 | IFQ_POLL(&ifp->if_snd, m0); |
966 | if (m0 == NULL) | | 966 | if (m0 == NULL) |
967 | break; | | 967 | break; |
968 | m = NULL; | | 968 | m = NULL; |
969 | | | 969 | |
970 | /* | | 970 | /* |
971 | * Get the next available transmit descriptor. | | 971 | * Get the next available transmit descriptor. |
972 | */ | | 972 | */ |
973 | nexttx = MEC_NEXTTX(sc->sc_txlast); | | 973 | nexttx = MEC_NEXTTX(sc->sc_txlast); |
974 | txd = &sc->sc_txdesc[nexttx]; | | 974 | txd = &sc->sc_txdesc[nexttx]; |
975 | txs = &sc->sc_txsoft[nexttx]; | | 975 | txs = &sc->sc_txsoft[nexttx]; |
976 | dmamap = txs->txs_dmamap; | | 976 | dmamap = txs->txs_dmamap; |
977 | txs->txs_flags = 0; | | 977 | txs->txs_flags = 0; |
978 | | | 978 | |
979 | buflen = 0; | | 979 | buflen = 0; |
980 | bufoff = 0; | | 980 | bufoff = 0; |
981 | resid = 0; | | 981 | resid = 0; |
982 | nptr = 0; /* XXX gcc */ | | 982 | nptr = 0; /* XXX gcc */ |
983 | pseg = 0; /* XXX gcc */ | | 983 | pseg = 0; /* XXX gcc */ |
984 | | | 984 | |
985 | len = m0->m_pkthdr.len; | | 985 | len = m0->m_pkthdr.len; |
986 | | | 986 | |
987 | DPRINTF(MEC_DEBUG_START, | | 987 | DPRINTF(MEC_DEBUG_START, |
988 | ("%s: len = %d, nexttx = %d, txpending = %d\n", | | 988 | ("%s: len = %d, nexttx = %d, txpending = %d\n", |
989 | __func__, len, nexttx, sc->sc_txpending)); | | 989 | __func__, len, nexttx, sc->sc_txpending)); |
990 | | | 990 | |
991 | if (len <= MEC_TXD_BUFSIZE) { | | 991 | if (len <= MEC_TXD_BUFSIZE) { |
992 | /* | | 992 | /* |
993 | * If a TX packet will fit into small txdesc buffer, | | 993 | * If a TX packet will fit into small txdesc buffer, |
994 | * just copy it into there. Maybe it's faster than | | 994 | * just copy it into there. Maybe it's faster than |
995 | * checking alignment and calling bus_dma(9) etc. | | 995 | * checking alignment and calling bus_dma(9) etc. |
996 | */ | | 996 | */ |
997 | DPRINTF(MEC_DEBUG_START, ("%s: short packet\n", | | 997 | DPRINTF(MEC_DEBUG_START, ("%s: short packet\n", |
998 | __func__)); | | 998 | __func__)); |
999 | IFQ_DEQUEUE(&ifp->if_snd, m0); | | 999 | IFQ_DEQUEUE(&ifp->if_snd, m0); |
1000 | | | 1000 | |
1001 | /* | | 1001 | /* |
1002 | * I don't know if MEC chip does auto padding, | | 1002 | * I don't know if MEC chip does auto padding, |
1003 | * but do it manually for safety. | | 1003 | * but do it manually for safety. |
1004 | */ | | 1004 | */ |
1005 | if (len < ETHER_PAD_LEN) { | | 1005 | if (len < ETHER_PAD_LEN) { |
1006 | MEC_EVCNT_INCR(&sc->sc_ev_txdpad); | | 1006 | MEC_EVCNT_INCR(&sc->sc_ev_txdpad); |
1007 | bufoff = MEC_TXD_BUFSTART(ETHER_PAD_LEN); | | 1007 | bufoff = MEC_TXD_BUFSTART(ETHER_PAD_LEN); |
1008 | m_copydata(m0, 0, len, txd->txd_buf + bufoff); | | 1008 | m_copydata(m0, 0, len, txd->txd_buf + bufoff); |
1009 | memset(txd->txd_buf + bufoff + len, 0, | | 1009 | memset(txd->txd_buf + bufoff + len, 0, |
1010 | ETHER_PAD_LEN - len); | | 1010 | ETHER_PAD_LEN - len); |
1011 | len = buflen = ETHER_PAD_LEN; | | 1011 | len = buflen = ETHER_PAD_LEN; |
1012 | } else { | | 1012 | } else { |
1013 | MEC_EVCNT_INCR(&sc->sc_ev_txdbuf); | | 1013 | MEC_EVCNT_INCR(&sc->sc_ev_txdbuf); |
1014 | bufoff = MEC_TXD_BUFSTART(len); | | 1014 | bufoff = MEC_TXD_BUFSTART(len); |
1015 | m_copydata(m0, 0, len, txd->txd_buf + bufoff); | | 1015 | m_copydata(m0, 0, len, txd->txd_buf + bufoff); |
1016 | buflen = len; | | 1016 | buflen = len; |
1017 | } | | 1017 | } |
1018 | } else { | | 1018 | } else { |
1019 | /* | | 1019 | /* |
1020 | * If the packet won't fit the static buffer in txdesc, | | 1020 | * If the packet won't fit the static buffer in txdesc, |
1021 | * we have to use the concatenate pointers to handle it. | | 1021 | * we have to use the concatenate pointers to handle it. |
1022 | */ | | 1022 | */ |
1023 | DPRINTF(MEC_DEBUG_START, ("%s: long packet\n", | | 1023 | DPRINTF(MEC_DEBUG_START, ("%s: long packet\n", |
1024 | __func__)); | | 1024 | __func__)); |
1025 | txs->txs_flags = MEC_TXS_TXDPTR; | | 1025 | txs->txs_flags = MEC_TXS_TXDPTR; |
1026 | | | 1026 | |
1027 | /* | | 1027 | /* |
1028 | * Call bus_dmamap_load_mbuf(9) first to see | | 1028 | * Call bus_dmamap_load_mbuf(9) first to see |
1029 | * how many chains the TX mbuf has. | | 1029 | * how many chains the TX mbuf has. |
1030 | */ | | 1030 | */ |
1031 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, | | 1031 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, |
1032 | BUS_DMA_WRITE | BUS_DMA_NOWAIT); | | 1032 | BUS_DMA_WRITE | BUS_DMA_NOWAIT); |
1033 | if (error == 0) { | | 1033 | if (error == 0) { |
1034 | /* | | 1034 | /* |
1035 | * Check chains which might contain headers. | | 1035 | * Check chains which might contain headers. |
1036 | * They might be so much fragmented and | | 1036 | * They might be so much fragmented and |
1037 | * it's better to copy them into txdesc buffer | | 1037 | * it's better to copy them into txdesc buffer |
1038 | * since they would be small enough. | | 1038 | * since they would be small enough. |
1039 | */ | | 1039 | */ |
1040 | nsegs = dmamap->dm_nsegs; | | 1040 | nsegs = dmamap->dm_nsegs; |
1041 | for (pseg = 0; pseg < nsegs; pseg++) { | | 1041 | for (pseg = 0; pseg < nsegs; pseg++) { |
1042 | slen = dmamap->dm_segs[pseg].ds_len; | | 1042 | slen = dmamap->dm_segs[pseg].ds_len; |
1043 | if (buflen + slen > | | 1043 | if (buflen + slen > |
1044 | MEC_TXD_BUFSIZE1 - MEC_TXD_ALIGN) | | 1044 | MEC_TXD_BUFSIZE1 - MEC_TXD_ALIGN) |
1045 | break; | | 1045 | break; |
1046 | buflen += slen; | | 1046 | buflen += slen; |
1047 | } | | 1047 | } |
1048 | /* | | 1048 | /* |
1049 | * Check if the rest chains can be fit into | | 1049 | * Check if the rest chains can be fit into |
1050 | * the concatinate pointers. | | 1050 | * the concatinate pointers. |
1051 | */ | | 1051 | */ |
1052 | align = dmamap->dm_segs[pseg].ds_addr & | | 1052 | align = dmamap->dm_segs[pseg].ds_addr & |
1053 | MEC_TXD_ALIGNMASK; | | 1053 | MEC_TXD_ALIGNMASK; |
1054 | if (align > 0) { | | 1054 | if (align > 0) { |
1055 | /* | | 1055 | /* |
1056 | * If the first chain isn't uint64_t | | 1056 | * If the first chain isn't uint64_t |
1057 | * aligned, append the unaligned part | | 1057 | * aligned, append the unaligned part |
1058 | * into txdesc buffer too. | | 1058 | * into txdesc buffer too. |
1059 | */ | | 1059 | */ |
1060 | resid = MEC_TXD_ALIGN - align; | | 1060 | resid = MEC_TXD_ALIGN - align; |
1061 | buflen += resid; | | 1061 | buflen += resid; |
1062 | for (; pseg < nsegs; pseg++) { | | 1062 | for (; pseg < nsegs; pseg++) { |
1063 | slen = | | 1063 | slen = |
1064 | dmamap->dm_segs[pseg].ds_len; | | 1064 | dmamap->dm_segs[pseg].ds_len; |
1065 | if (slen > resid) | | 1065 | if (slen > resid) |
1066 | break; | | 1066 | break; |
1067 | resid -= slen; | | 1067 | resid -= slen; |
1068 | } | | 1068 | } |
1069 | } else if (pseg == 0) { | | 1069 | } else if (pseg == 0) { |
1070 | /* | | 1070 | /* |
1071 | * In this case, the first chain is | | 1071 | * In this case, the first chain is |
1072 | * uint64_t aligned but it's too long | | 1072 | * uint64_t aligned but it's too long |
1073 | * to put into txdesc buf. | | 1073 | * to put into txdesc buf. |
1074 | * We have to put some data into | | 1074 | * We have to put some data into |
1075 | * txdesc buf even in this case, | | 1075 | * txdesc buf even in this case, |
1076 | * so put MEC_TXD_ALIGN bytes there. | | 1076 | * so put MEC_TXD_ALIGN bytes there. |
1077 | */ | | 1077 | */ |
1078 | buflen = resid = MEC_TXD_ALIGN; | | 1078 | buflen = resid = MEC_TXD_ALIGN; |