| @@ -1,768 +1,765 @@ | | | @@ -1,768 +1,765 @@ |
1 | /* $NetBSD: mb8795.c,v 1.65 2019/05/29 10:07:29 msaitoh Exp $ */ | | 1 | /* $NetBSD: mb8795.c,v 1.66 2020/01/29 05:31:10 thorpej Exp $ */ |
2 | /* | | 2 | /* |
3 | * Copyright (c) 1998 Darrin B. Jewell | | 3 | * Copyright (c) 1998 Darrin B. Jewell |
4 | * All rights reserved. | | 4 | * 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 | #include <sys/cdefs.h> | | 27 | #include <sys/cdefs.h> |
28 | __KERNEL_RCSID(0, "$NetBSD: mb8795.c,v 1.65 2019/05/29 10:07:29 msaitoh Exp $"); | | 28 | __KERNEL_RCSID(0, "$NetBSD: mb8795.c,v 1.66 2020/01/29 05:31:10 thorpej Exp $"); |
29 | | | 29 | |
30 | #include "opt_inet.h" | | 30 | #include "opt_inet.h" |
31 | | | 31 | |
32 | #include <sys/param.h> | | 32 | #include <sys/param.h> |
33 | #include <sys/systm.h> | | 33 | #include <sys/systm.h> |
34 | #include <sys/mbuf.h> | | 34 | #include <sys/mbuf.h> |
35 | #include <sys/syslog.h> | | 35 | #include <sys/syslog.h> |
36 | #include <sys/socket.h> | | 36 | #include <sys/socket.h> |
37 | #include <sys/device.h> | | 37 | #include <sys/device.h> |
38 | #include <sys/malloc.h> | | 38 | #include <sys/malloc.h> |
39 | #include <sys/ioctl.h> | | 39 | #include <sys/ioctl.h> |
40 | #include <sys/errno.h> | | 40 | #include <sys/errno.h> |
41 | #include <sys/rndsource.h> | | 41 | #include <sys/rndsource.h> |
42 | | | 42 | |
43 | #include <net/if.h> | | 43 | #include <net/if.h> |
44 | #include <net/if_dl.h> | | 44 | #include <net/if_dl.h> |
45 | #include <net/if_ether.h> | | 45 | #include <net/if_ether.h> |
46 | #include <net/if_media.h> | | 46 | #include <net/if_media.h> |
47 | #include <net/bpf.h> | | 47 | #include <net/bpf.h> |
48 | | | 48 | |
49 | #ifdef INET | | 49 | #ifdef INET |
50 | #include <netinet/in.h> | | 50 | #include <netinet/in.h> |
51 | #include <netinet/if_inarp.h> | | 51 | #include <netinet/if_inarp.h> |
52 | #include <netinet/in_systm.h> | | 52 | #include <netinet/in_systm.h> |
53 | #include <netinet/in_var.h> | | 53 | #include <netinet/in_var.h> |
54 | #include <netinet/ip.h> | | 54 | #include <netinet/ip.h> |
55 | #endif | | 55 | #endif |
56 | | | 56 | |
57 | #include <machine/cpu.h> | | 57 | #include <machine/cpu.h> |
58 | #include <machine/bus.h> | | 58 | #include <machine/bus.h> |
59 | #include <machine/intr.h> | | 59 | #include <machine/intr.h> |
60 | | | 60 | |
61 | /* @@@ this is here for the REALIGN_DMABUF hack below */ | | 61 | /* @@@ this is here for the REALIGN_DMABUF hack below */ |
62 | #include "nextdmareg.h" | | 62 | #include "nextdmareg.h" |
63 | #include "nextdmavar.h" | | 63 | #include "nextdmavar.h" |
64 | | | 64 | |
65 | #include "mb8795reg.h" | | 65 | #include "mb8795reg.h" |
66 | #include "mb8795var.h" | | 66 | #include "mb8795var.h" |
67 | | | 67 | |
68 | #include "bmapreg.h" | | 68 | #include "bmapreg.h" |
69 | | | 69 | |
70 | #ifdef DEBUG | | 70 | #ifdef DEBUG |
71 | #define MB8795_DEBUG | | 71 | #define MB8795_DEBUG |
72 | #endif | | 72 | #endif |
73 | | | 73 | |
74 | #define PRINTF(x) printf x; | | 74 | #define PRINTF(x) printf x; |
75 | #ifdef MB8795_DEBUG | | 75 | #ifdef MB8795_DEBUG |
76 | int mb8795_debug = 0; | | 76 | int mb8795_debug = 0; |
77 | #define DPRINTF(x) if (mb8795_debug) printf x; | | 77 | #define DPRINTF(x) if (mb8795_debug) printf x; |
78 | #else | | 78 | #else |
79 | #define DPRINTF(x) | | 79 | #define DPRINTF(x) |
80 | #endif | | 80 | #endif |
81 | | | 81 | |
82 | extern int turbo; | | 82 | extern int turbo; |
83 | | | 83 | |
84 | /* | | 84 | /* |
85 | * Support for | | 85 | * Support for |
86 | * Fujitsu Ethernet Data Link Controller (MB8795) | | 86 | * Fujitsu Ethernet Data Link Controller (MB8795) |
87 | * and the Fujitsu Manchester Encoder/Decoder (MB502). | | 87 | * and the Fujitsu Manchester Encoder/Decoder (MB502). |
88 | */ | | 88 | */ |
89 | | | 89 | |
90 | void mb8795_shutdown(void *); | | 90 | void mb8795_shutdown(void *); |
91 | | | 91 | |
92 | bus_dmamap_t mb8795_txdma_restart(bus_dmamap_t, void *); | | 92 | bus_dmamap_t mb8795_txdma_restart(bus_dmamap_t, void *); |
93 | void mb8795_start_dma(struct mb8795_softc *); | | 93 | void mb8795_start_dma(struct mb8795_softc *); |
94 | | | 94 | |
95 | int mb8795_mediachange(struct ifnet *); | | 95 | int mb8795_mediachange(struct ifnet *); |
96 | void mb8795_mediastatus(struct ifnet *, struct ifmediareq *); | | 96 | void mb8795_mediastatus(struct ifnet *, struct ifmediareq *); |
97 | | | 97 | |
98 | void | | 98 | void |
99 | mb8795_config(struct mb8795_softc *sc, int *media, int nmedia, int defmedia) | | 99 | mb8795_config(struct mb8795_softc *sc, int *media, int nmedia, int defmedia) |
100 | { | | 100 | { |
101 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 101 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
102 | | | 102 | |
103 | DPRINTF(("%s: mb8795_config()\n", device_xname(sc->sc_dev))); | | 103 | DPRINTF(("%s: mb8795_config()\n", device_xname(sc->sc_dev))); |
104 | | | 104 | |
105 | /* Initialize ifnet structure. */ | | 105 | /* Initialize ifnet structure. */ |
106 | memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); | | 106 | memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); |
107 | ifp->if_softc = sc; | | 107 | ifp->if_softc = sc; |
108 | ifp->if_start = mb8795_start; | | 108 | ifp->if_start = mb8795_start; |
109 | ifp->if_ioctl = mb8795_ioctl; | | 109 | ifp->if_ioctl = mb8795_ioctl; |
110 | ifp->if_watchdog = mb8795_watchdog; | | 110 | ifp->if_watchdog = mb8795_watchdog; |
111 | ifp->if_flags = IFF_BROADCAST; | | 111 | ifp->if_flags = IFF_BROADCAST; |
112 | | | 112 | |
113 | /* Initialize media goo. */ | | 113 | /* Initialize media goo. */ |
114 | sc->sc_ethercom.ec_ifmedia = &sc->sc_media; | | 114 | sc->sc_ethercom.ec_ifmedia = &sc->sc_media; |
115 | ifmedia_init(&sc->sc_media, 0, mb8795_mediachange, mb8795_mediastatus); | | 115 | ifmedia_init(&sc->sc_media, 0, mb8795_mediachange, mb8795_mediastatus); |
116 | if (media != NULL) { | | 116 | if (media != NULL) { |
117 | int i; | | 117 | int i; |
118 | for (i = 0; i < nmedia; i++) | | 118 | for (i = 0; i < nmedia; i++) |
119 | ifmedia_add(&sc->sc_media, media[i], 0, NULL); | | 119 | ifmedia_add(&sc->sc_media, media[i], 0, NULL); |
120 | ifmedia_set(&sc->sc_media, defmedia); | | 120 | ifmedia_set(&sc->sc_media, defmedia); |
121 | } else { | | 121 | } else { |
122 | ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); | | 122 | ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); |
123 | ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); | | 123 | ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); |
124 | } | | 124 | } |
125 | | | 125 | |
126 | /* Attach the interface. */ | | 126 | /* Attach the interface. */ |
127 | if_attach(ifp); | | 127 | if_attach(ifp); |
128 | ether_ifattach(ifp, sc->sc_enaddr); | | 128 | ether_ifattach(ifp, sc->sc_enaddr); |
129 | | | 129 | |
130 | sc->sc_sh = shutdownhook_establish(mb8795_shutdown, sc); | | 130 | sc->sc_sh = shutdownhook_establish(mb8795_shutdown, sc); |
131 | if (sc->sc_sh == NULL) | | 131 | if (sc->sc_sh == NULL) |
132 | panic("mb8795_config: can't establish shutdownhook"); | | 132 | panic("mb8795_config: can't establish shutdownhook"); |
133 | | | 133 | |
134 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | | 134 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), |
135 | RND_TYPE_NET, RND_FLAG_DEFAULT); | | 135 | RND_TYPE_NET, RND_FLAG_DEFAULT); |
136 | | | 136 | |
137 | DPRINTF(("%s: leaving mb8795_config()\n", device_xname(sc->sc_dev))); | | 137 | DPRINTF(("%s: leaving mb8795_config()\n", device_xname(sc->sc_dev))); |
138 | } | | 138 | } |
139 | | | 139 | |
140 | /* | | 140 | /* |
141 | * Media change callback. | | 141 | * Media change callback. |
142 | */ | | 142 | */ |
143 | int | | 143 | int |
144 | mb8795_mediachange(struct ifnet *ifp) | | 144 | mb8795_mediachange(struct ifnet *ifp) |
145 | { | | 145 | { |
146 | struct mb8795_softc *sc = ifp->if_softc; | | 146 | struct mb8795_softc *sc = ifp->if_softc; |
147 | int data; | | 147 | int data; |
148 | | | 148 | |
149 | if (turbo) | | 149 | if (turbo) |
150 | return 0; | | 150 | return 0; |
151 | | | 151 | |
152 | switch IFM_SUBTYPE(sc->sc_media.ifm_media) { | | 152 | switch IFM_SUBTYPE(sc->sc_media.ifm_media) { |
153 | case IFM_AUTO: | | 153 | case IFM_AUTO: |
154 | if ((bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, | | 154 | if ((bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, |
155 | BMAP_DATA) & BMAP_DATA_UTPENABLED_MASK) || | | 155 | BMAP_DATA) & BMAP_DATA_UTPENABLED_MASK) || |
156 | !(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, | | 156 | !(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, |
157 | BMAP_DATA) & BMAP_DATA_UTPCARRIER_MASK)) { | | 157 | BMAP_DATA) & BMAP_DATA_UTPCARRIER_MASK)) { |
158 | data = BMAP_DATA_UTPENABLE; | | 158 | data = BMAP_DATA_UTPENABLE; |
159 | sc->sc_media.ifm_cur->ifm_data = IFM_ETHER | IFM_10_T; | | 159 | sc->sc_media.ifm_cur->ifm_data = IFM_ETHER | IFM_10_T; |
160 | } else { | | 160 | } else { |
161 | data = BMAP_DATA_BNCENABLE; | | 161 | data = BMAP_DATA_BNCENABLE; |
162 | sc->sc_media.ifm_cur->ifm_data = IFM_ETHER | IFM_10_2; | | 162 | sc->sc_media.ifm_cur->ifm_data = IFM_ETHER | IFM_10_2; |
163 | } | | 163 | } |
164 | break; | | 164 | break; |
165 | case IFM_10_T: | | 165 | case IFM_10_T: |
166 | data = BMAP_DATA_UTPENABLE; | | 166 | data = BMAP_DATA_UTPENABLE; |
167 | break; | | 167 | break; |
168 | case IFM_10_2: | | 168 | case IFM_10_2: |
169 | data = BMAP_DATA_BNCENABLE; | | 169 | data = BMAP_DATA_BNCENABLE; |
170 | break; | | 170 | break; |
171 | default: | | 171 | default: |
172 | return 1; | | 172 | return 1; |
173 | break; | | 173 | break; |
174 | } | | 174 | } |
175 | | | 175 | |
176 | bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, | | 176 | bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, |
177 | BMAP_DDIR, BMAP_DDIR_UTPENABLE_MASK); | | 177 | BMAP_DDIR, BMAP_DDIR_UTPENABLE_MASK); |
178 | bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, | | 178 | bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, |
179 | BMAP_DATA, data); | | 179 | BMAP_DATA, data); |
180 | | | 180 | |
181 | return 0; | | 181 | return 0; |
182 | } | | 182 | } |
183 | | | 183 | |
184 | /* | | 184 | /* |
185 | * Media status callback. | | 185 | * Media status callback. |
186 | */ | | 186 | */ |
187 | void | | 187 | void |
188 | mb8795_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) | | 188 | mb8795_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) |
189 | { | | 189 | { |
190 | struct mb8795_softc *sc = ifp->if_softc; | | 190 | struct mb8795_softc *sc = ifp->if_softc; |
191 | | | 191 | |
192 | if (turbo) | | 192 | if (turbo) |
193 | return; | | 193 | return; |
194 | | | 194 | |
195 | if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_AUTO) | | 195 | if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_AUTO) |
196 | ifmr->ifm_active = sc->sc_media.ifm_cur->ifm_data; | | 196 | ifmr->ifm_active = sc->sc_media.ifm_cur->ifm_data; |
197 | | | 197 | |
198 | if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_10_T) { | | 198 | if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_10_T) { |
199 | ifmr->ifm_status = IFM_AVALID; | | 199 | ifmr->ifm_status = IFM_AVALID; |
200 | if (!(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, | | 200 | if (!(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, |
201 | BMAP_DATA) & BMAP_DATA_UTPCARRIER_MASK)) | | 201 | BMAP_DATA) & BMAP_DATA_UTPCARRIER_MASK)) |
202 | ifmr->ifm_status |= IFM_ACTIVE; | | 202 | ifmr->ifm_status |= IFM_ACTIVE; |
203 | } else | | 203 | } else |
204 | ifmr->ifm_status &= ~IFM_AVALID; /* don't know for 10_2 */ | | 204 | ifmr->ifm_status &= ~IFM_AVALID; /* don't know for 10_2 */ |
205 | | | 205 | |
206 | return; | | 206 | return; |
207 | } | | 207 | } |
208 | | | 208 | |
209 | /****************************************************************/ | | 209 | /****************************************************************/ |
210 | #ifdef MB8795_DEBUG | | 210 | #ifdef MB8795_DEBUG |
211 | #define XCHR(x) hexdigits[(x) & 0xf] | | 211 | #define XCHR(x) hexdigits[(x) & 0xf] |
212 | static void | | 212 | static void |
213 | mb8795_hex_dump(unsigned char *pkt, size_t len) | | 213 | mb8795_hex_dump(unsigned char *pkt, size_t len) |
214 | { | | 214 | { |
215 | size_t i, j; | | 215 | size_t i, j; |
216 | | | 216 | |
217 | printf("00000000 "); | | 217 | printf("00000000 "); |
218 | for (i=0; i<len; i++) { | | 218 | for (i=0; i<len; i++) { |
219 | printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i])); | | 219 | printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i])); |
220 | if ((i+1) % 16 == 8) { | | 220 | if ((i+1) % 16 == 8) { |
221 | printf(" "); | | 221 | printf(" "); |
222 | } | | 222 | } |
223 | if ((i+1) % 16 == 0) { | | 223 | if ((i+1) % 16 == 0) { |
224 | printf(" %c", '|'); | | 224 | printf(" %c", '|'); |
225 | for (j=0; j<16; j++) { | | 225 | for (j=0; j<16; j++) { |
226 | printf("%c", | | 226 | printf("%c", |
227 | (pkt[i-15+j] >= 32 && pkt[i-15+j] < 127) | | 227 | (pkt[i-15+j] >= 32 && pkt[i-15+j] < 127) |
228 | ? pkt[i-15+j] : '.'); | | 228 | ? pkt[i-15+j] : '.'); |
229 | } | | 229 | } |
230 | printf("%c\n%c%c%c%c%c%c%c%c ", '|', | | 230 | printf("%c\n%c%c%c%c%c%c%c%c ", '|', |
231 | XCHR((i+1)>>28), XCHR((i+1)>>24), XCHR((i+1)>>20), | | 231 | XCHR((i+1)>>28), XCHR((i+1)>>24), XCHR((i+1)>>20), |
232 | XCHR((i+1)>>16), XCHR((i+1)>>12), XCHR((i+1)>>8), | | 232 | XCHR((i+1)>>16), XCHR((i+1)>>12), XCHR((i+1)>>8), |
233 | XCHR((i+1)>>4), XCHR(i+1)); | | 233 | XCHR((i+1)>>4), XCHR(i+1)); |
234 | } | | 234 | } |
235 | } | | 235 | } |
236 | printf("\n"); | | 236 | printf("\n"); |
237 | } | | 237 | } |
238 | #undef XCHR | | 238 | #undef XCHR |
239 | #endif | | 239 | #endif |
240 | | | 240 | |
241 | /* | | 241 | /* |
242 | * Controller receive interrupt. | | 242 | * Controller receive interrupt. |
243 | */ | | 243 | */ |
244 | void | | 244 | void |
245 | mb8795_rint(struct mb8795_softc *sc) | | 245 | mb8795_rint(struct mb8795_softc *sc) |
246 | { | | 246 | { |
247 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 247 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
248 | int error = 0; | | 248 | int error = 0; |
249 | u_char rxstat; | | 249 | u_char rxstat; |
250 | u_char rxmask; | | 250 | u_char rxmask; |
251 | | | 251 | |
252 | rxstat = MB_READ_REG(sc, MB8795_RXSTAT); | | 252 | rxstat = MB_READ_REG(sc, MB8795_RXSTAT); |
253 | rxmask = MB_READ_REG(sc, MB8795_RXMASK); | | 253 | rxmask = MB_READ_REG(sc, MB8795_RXMASK); |
254 | __USE(rxmask); | | 254 | __USE(rxmask); |
255 | | | 255 | |
256 | MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR); | | 256 | MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR); |
257 | | | 257 | |
258 | if (rxstat & MB8795_RXSTAT_RESET) { | | 258 | if (rxstat & MB8795_RXSTAT_RESET) { |
259 | DPRINTF(("%s: rx reset packet\n", device_xname(sc->sc_dev))); | | 259 | DPRINTF(("%s: rx reset packet\n", device_xname(sc->sc_dev))); |
260 | error++; | | 260 | error++; |
261 | } | | 261 | } |
262 | if (rxstat & MB8795_RXSTAT_SHORT) { | | 262 | if (rxstat & MB8795_RXSTAT_SHORT) { |
263 | DPRINTF(("%s: rx short packet\n", device_xname(sc->sc_dev))); | | 263 | DPRINTF(("%s: rx short packet\n", device_xname(sc->sc_dev))); |
264 | error++; | | 264 | error++; |
265 | } | | 265 | } |
266 | if (rxstat & MB8795_RXSTAT_ALIGNERR) { | | 266 | if (rxstat & MB8795_RXSTAT_ALIGNERR) { |
267 | DPRINTF(("%s: rx alignment error\n",device_xname(sc->sc_dev))); | | 267 | DPRINTF(("%s: rx alignment error\n",device_xname(sc->sc_dev))); |
268 | #if 0 | | 268 | #if 0 |
269 | error++; | | 269 | error++; |
270 | #endif | | 270 | #endif |
271 | } | | 271 | } |
272 | if (rxstat & MB8795_RXSTAT_CRCERR) { | | 272 | if (rxstat & MB8795_RXSTAT_CRCERR) { |
273 | DPRINTF(("%s: rx CRC error\n", device_xname(sc->sc_dev))); | | 273 | DPRINTF(("%s: rx CRC error\n", device_xname(sc->sc_dev))); |
274 | #if 0 | | 274 | #if 0 |
275 | error++; | | 275 | error++; |
276 | #endif | | 276 | #endif |
277 | } | | 277 | } |
278 | if (rxstat & MB8795_RXSTAT_OVERFLOW) { | | 278 | if (rxstat & MB8795_RXSTAT_OVERFLOW) { |
279 | DPRINTF(("%s: rx overflow error\n", device_xname(sc->sc_dev))); | | 279 | DPRINTF(("%s: rx overflow error\n", device_xname(sc->sc_dev))); |
280 | #if 0 | | 280 | #if 0 |
281 | error++; | | 281 | error++; |
282 | #endif | | 282 | #endif |
283 | } | | 283 | } |
284 | | | 284 | |
285 | if (error) { | | 285 | if (error) { |
286 | ifp->if_ierrors++; | | 286 | if_statinc(ifp, if_ierrors); |
287 | /* @@@ handle more gracefully, free memory, etc. */ | | 287 | /* @@@ handle more gracefully, free memory, etc. */ |
288 | } | | 288 | } |
289 | | | 289 | |
290 | if (rxstat & MB8795_RXSTAT_OK) { | | 290 | if (rxstat & MB8795_RXSTAT_OK) { |
291 | struct mbuf *m; | | 291 | struct mbuf *m; |
292 | int s; | | 292 | int s; |
293 | s = spldma(); | | 293 | s = spldma(); |
294 | | | 294 | |
295 | while ((m = MBDMA_RX_MBUF (sc))) { | | 295 | while ((m = MBDMA_RX_MBUF (sc))) { |
296 | /* CRC is included with the packet; trim it. */ | | 296 | /* CRC is included with the packet; trim it. */ |
297 | m->m_pkthdr.len = m->m_len = m->m_len - ETHER_CRC_LEN; | | 297 | m->m_pkthdr.len = m->m_len = m->m_len - ETHER_CRC_LEN; |
298 | m_set_rcvif(m, ifp); | | 298 | m_set_rcvif(m, ifp); |
299 | | | 299 | |
300 | /* Find receive length, keep crc */ | | 300 | /* Find receive length, keep crc */ |
301 | /* enable DMA interrupts while we process the packet */ | | 301 | /* enable DMA interrupts while we process the packet */ |
302 | splx(s); | | 302 | splx(s); |
303 | | | 303 | |
304 | #if defined(MB8795_DEBUG) | | 304 | #if defined(MB8795_DEBUG) |
305 | /* Peek at the packet */ | | 305 | /* Peek at the packet */ |
306 | DPRINTF(("%s: received packet, at VA %p-%p,len %d\n", | | 306 | DPRINTF(("%s: received packet, at VA %p-%p,len %d\n", |
307 | device_xname(sc->sc_dev), mtod(m,u_char *), | | 307 | device_xname(sc->sc_dev), mtod(m,u_char *), |
308 | mtod(m,u_char *) + m->m_len, m->m_len)); | | 308 | mtod(m,u_char *) + m->m_len, m->m_len)); |
309 | if (mb8795_debug > 3) { | | 309 | if (mb8795_debug > 3) { |
310 | mb8795_hex_dump(mtod(m,u_char *), | | 310 | mb8795_hex_dump(mtod(m,u_char *), |
311 | m->m_pkthdr.len); | | 311 | m->m_pkthdr.len); |
312 | } else if (mb8795_debug > 2) { | | 312 | } else if (mb8795_debug > 2) { |
313 | mb8795_hex_dump(mtod(m,u_char *), | | 313 | mb8795_hex_dump(mtod(m,u_char *), |
314 | m->m_pkthdr.len < 255 | | 314 | m->m_pkthdr.len < 255 |
315 | ? m->m_pkthdr.len : 128); | | 315 | ? m->m_pkthdr.len : 128); |
316 | } | | 316 | } |
317 | #endif | | 317 | #endif |
318 | | | 318 | |
319 | /* Pass the packet up. */ | | 319 | /* Pass the packet up. */ |
320 | if_percpuq_enqueue(ifp->if_percpuq, m); | | 320 | if_percpuq_enqueue(ifp->if_percpuq, m); |
321 | | | 321 | |
322 | s = spldma(); | | 322 | s = spldma(); |
323 | } | | 323 | } |
324 | | | 324 | |
325 | splx(s); | | 325 | splx(s); |
326 | | | 326 | |
327 | } | | 327 | } |
328 | | | 328 | |
329 | #ifdef MB8795_DEBUG | | 329 | #ifdef MB8795_DEBUG |
330 | if (mb8795_debug) { | | 330 | if (mb8795_debug) { |
331 | char sbuf[256]; | | 331 | char sbuf[256]; |
332 | | | 332 | |
333 | snprintb(sbuf, sizeof(sbuf), MB8795_RXSTAT_BITS, rxstat); | | 333 | snprintb(sbuf, sizeof(sbuf), MB8795_RXSTAT_BITS, rxstat); |
334 | printf("%s: rx interrupt, rxstat = %s\n", | | 334 | printf("%s: rx interrupt, rxstat = %s\n", |
335 | device_xname(sc->sc_dev), sbuf); | | 335 | device_xname(sc->sc_dev), sbuf); |
336 | | | 336 | |
337 | snprintb(sbuf, sizeof(sbuf), MB8795_RXSTAT_BITS, | | 337 | snprintb(sbuf, sizeof(sbuf), MB8795_RXSTAT_BITS, |
338 | MB_READ_REG(sc, MB8795_RXSTAT)); | | 338 | MB_READ_REG(sc, MB8795_RXSTAT)); |
339 | | | 339 | |
340 | printf("rxstat = %s\n", sbuf); | | 340 | printf("rxstat = %s\n", sbuf); |
341 | | | 341 | |
342 | snprintb(sbuf, sizeof(sbuf), MB8795_RXMASK_BITS, | | 342 | snprintb(sbuf, sizeof(sbuf), MB8795_RXMASK_BITS, |
343 | MB_READ_REG(sc, MB8795_RXMASK)); | | 343 | MB_READ_REG(sc, MB8795_RXMASK)); |
344 | printf("rxmask = %s\n", sbuf); | | 344 | printf("rxmask = %s\n", sbuf); |
345 | | | 345 | |
346 | snprintb(sbuf, sizeof(sbuf), MB8795_RXMODE_BITS, | | 346 | snprintb(sbuf, sizeof(sbuf), MB8795_RXMODE_BITS, |
347 | MB_READ_REG(sc, MB8795_RXMODE)); | | 347 | MB_READ_REG(sc, MB8795_RXMODE)); |
348 | printf("rxmode = %s\n", sbuf); | | 348 | printf("rxmode = %s\n", sbuf); |
349 | } | | 349 | } |
350 | #endif | | 350 | #endif |
351 | | | 351 | |
352 | return; | | 352 | return; |
353 | } | | 353 | } |
354 | | | 354 | |
355 | /* | | 355 | /* |
356 | * Controller transmit interrupt. | | 356 | * Controller transmit interrupt. |
357 | */ | | 357 | */ |
358 | void | | 358 | void |
359 | mb8795_tint(struct mb8795_softc *sc) | | 359 | mb8795_tint(struct mb8795_softc *sc) |
360 | { | | 360 | { |
361 | u_char txstat; | | 361 | u_char txstat; |
362 | u_char txmask; | | 362 | u_char txmask; |
363 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 363 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
364 | | | 364 | |
365 | panic ("tint"); | | 365 | panic ("tint"); |
366 | txstat = MB_READ_REG(sc, MB8795_TXSTAT); | | 366 | txstat = MB_READ_REG(sc, MB8795_TXSTAT); |
367 | txmask = MB_READ_REG(sc, MB8795_TXMASK); | | 367 | txmask = MB_READ_REG(sc, MB8795_TXMASK); |
368 | __USE(txmask); | | 368 | __USE(txmask); |
369 | | | 369 | |
370 | if ((txstat & MB8795_TXSTAT_READY) || | | 370 | if ((txstat & MB8795_TXSTAT_READY) || |
371 | (txstat & MB8795_TXSTAT_TXRECV)) { | | 371 | (txstat & MB8795_TXSTAT_TXRECV)) { |
372 | /* printf("X"); */ | | 372 | /* printf("X"); */ |
373 | MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); | | 373 | MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); |
374 | /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_READYIE); */ | | 374 | /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_READYIE); */ |
375 | /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_TXRXIE); */ | | 375 | /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_TXRXIE); */ |
376 | MB_WRITE_REG(sc, MB8795_TXMASK, 0); | | 376 | MB_WRITE_REG(sc, MB8795_TXMASK, 0); |
377 | if ((ifp->if_flags & IFF_RUNNING) | | 377 | if ((ifp->if_flags & IFF_RUNNING) |
378 | && !IF_IS_EMPTY(&sc->sc_tx_snd)) { | | 378 | && !IF_IS_EMPTY(&sc->sc_tx_snd)) { |
379 | void mb8795_start_dma(struct mb8795_softc *); /* XXX */ | | 379 | void mb8795_start_dma(struct mb8795_softc *); /* XXX */ |
380 | /* printf ("Z"); */ | | 380 | /* printf ("Z"); */ |
381 | mb8795_start_dma(sc); | | 381 | mb8795_start_dma(sc); |
382 | } | | 382 | } |
383 | return; | | 383 | return; |
384 | } | | 384 | } |
385 | | | 385 | |
386 | if (txstat & MB8795_TXSTAT_SHORTED) { | | 386 | if (txstat & MB8795_TXSTAT_SHORTED) { |
387 | printf("%s: tx cable shorted\n", device_xname(sc->sc_dev)); | | 387 | printf("%s: tx cable shorted\n", device_xname(sc->sc_dev)); |
388 | ifp->if_oerrors++; | | 388 | if_statinc(ifp, if_oerrors); |
389 | } | | 389 | } |
390 | if (txstat & MB8795_TXSTAT_UNDERFLOW) { | | 390 | if (txstat & MB8795_TXSTAT_UNDERFLOW) { |
391 | printf("%s: tx underflow\n", device_xname(sc->sc_dev)); | | 391 | printf("%s: tx underflow\n", device_xname(sc->sc_dev)); |
392 | ifp->if_oerrors++; | | 392 | if_statinc(ifp, if_oerrors); |
393 | } | | 393 | } |
394 | if (txstat & MB8795_TXSTAT_COLLERR) { | | 394 | if (txstat & MB8795_TXSTAT_COLLERR) { |
395 | DPRINTF(("%s: tx collision\n", device_xname(sc->sc_dev))); | | 395 | DPRINTF(("%s: tx collision\n", device_xname(sc->sc_dev))); |
396 | ifp->if_collisions++; | | 396 | if_statinc(ifp, if_collisions); |
397 | } | | 397 | } |
398 | if (txstat & MB8795_TXSTAT_COLLERR16) { | | 398 | if (txstat & MB8795_TXSTAT_COLLERR16) { |
399 | printf("%s: tx 16th collision\n", device_xname(sc->sc_dev)); | | 399 | printf("%s: tx 16th collision\n", device_xname(sc->sc_dev)); |
400 | ifp->if_oerrors++; | | 400 | if_statinc(ifp, if_oerrors); |
401 | ifp->if_collisions += 16; | | 401 | if_statadd(ifp, if_collisions, 16); |
402 | } | | 402 | } |
403 | | | 403 | |
404 | #if 0 | | 404 | #if 0 |
405 | if (txstat & MB8795_TXSTAT_READY) { | | 405 | if (txstat & MB8795_TXSTAT_READY) { |
406 | char sbuf[256]; | | 406 | char sbuf[256]; |
407 | | | 407 | |
408 | snprintb(sbuf, sizeof(sbuf), MB8795_TXSTAT_BITS, txstat); | | 408 | snprintb(sbuf, sizeof(sbuf), MB8795_TXSTAT_BITS, txstat); |
409 | panic("%s: unexpected tx interrupt %s", | | 409 | panic("%s: unexpected tx interrupt %s", |
410 | device_xname(sc->sc_dev), sbuf); | | 410 | device_xname(sc->sc_dev), sbuf); |
411 | | | 411 | |
412 | /* turn interrupt off */ | | 412 | /* turn interrupt off */ |
413 | MB_WRITE_REG(sc, MB8795_TXMASK, | | 413 | MB_WRITE_REG(sc, MB8795_TXMASK, |
414 | txmask & ~MB8795_TXMASK_READYIE); | | 414 | txmask & ~MB8795_TXMASK_READYIE); |
415 | } | | 415 | } |
416 | #endif | | 416 | #endif |
417 | | | 417 | |
418 | return; | | 418 | return; |
419 | } | | 419 | } |
420 | | | 420 | |
421 | /****************************************************************/ | | 421 | /****************************************************************/ |
422 | | | 422 | |
423 | void | | 423 | void |
424 | mb8795_reset(struct mb8795_softc *sc) | | 424 | mb8795_reset(struct mb8795_softc *sc) |
425 | { | | 425 | { |
426 | int s; | | 426 | int s; |
427 | int i; | | 427 | int i; |
428 | | | 428 | |
429 | s = splnet(); | | 429 | s = splnet(); |
430 | | | 430 | |
431 | DPRINTF (("%s: mb8795_reset()\n", device_xname(sc->sc_dev))); | | 431 | DPRINTF (("%s: mb8795_reset()\n", device_xname(sc->sc_dev))); |
432 | | | 432 | |
433 | sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); | | 433 | sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); |
434 | sc->sc_ethercom.ec_if.if_timer = 0; | | 434 | sc->sc_ethercom.ec_if.if_timer = 0; |
435 | | | 435 | |
436 | MBDMA_RESET(sc); | | 436 | MBDMA_RESET(sc); |
437 | | | 437 | |
438 | MB_WRITE_REG(sc, MB8795_RESET, MB8795_RESET_MODE); | | 438 | MB_WRITE_REG(sc, MB8795_RESET, MB8795_RESET_MODE); |
439 | | | 439 | |
440 | mb8795_mediachange(&sc->sc_ethercom.ec_if); | | 440 | mb8795_mediachange(&sc->sc_ethercom.ec_if); |
441 | | | 441 | |
442 | #if 0 /* This interrupt was sometimes failing to ack correctly | | 442 | #if 0 /* This interrupt was sometimes failing to ack correctly |
443 | * causing a loop @@@ | | 443 | * causing a loop @@@ |
444 | */ | | 444 | */ |
445 | MB_WRITE_REG(sc, MB8795_TXMASK, | | 445 | MB_WRITE_REG(sc, MB8795_TXMASK, |
446 | MB8795_TXMASK_UNDERFLOWIE | MB8795_TXMASK_COLLIE | | 446 | MB8795_TXMASK_UNDERFLOWIE | MB8795_TXMASK_COLLIE |
447 | | MB8795_TXMASK_COLL16IE | MB8795_TXMASK_PARERRIE); | | 447 | | MB8795_TXMASK_COLL16IE | MB8795_TXMASK_PARERRIE); |
448 | #else | | 448 | #else |
449 | MB_WRITE_REG(sc, MB8795_TXMASK, 0); | | 449 | MB_WRITE_REG(sc, MB8795_TXMASK, 0); |
450 | #endif | | 450 | #endif |
451 | MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); | | 451 | MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); |
452 | | | 452 | |
453 | #if 0 | | 453 | #if 0 |
454 | MB_WRITE_REG(sc, MB8795_RXMASK, | | 454 | MB_WRITE_REG(sc, MB8795_RXMASK, |
455 | MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | MB8795_RXMASK_SHORTIE | | 455 | MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | MB8795_RXMASK_SHORTIE |
456 | | MB8795_RXMASK_ALIGNERRIE | MB8795_RXMASK_CRCERRIE | | 456 | | MB8795_RXMASK_ALIGNERRIE | MB8795_RXMASK_CRCERRIE |
457 | | MB8795_RXMASK_OVERFLOWIE); | | 457 | | MB8795_RXMASK_OVERFLOWIE); |
458 | #else | | 458 | #else |
459 | MB_WRITE_REG(sc, MB8795_RXMASK, | | 459 | MB_WRITE_REG(sc, MB8795_RXMASK, |
460 | MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | | 460 | MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE |
461 | | MB8795_RXMASK_SHORTIE); | | 461 | | MB8795_RXMASK_SHORTIE); |
462 | #endif | | 462 | #endif |
463 | | | 463 | |
464 | MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR); | | 464 | MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR); |
465 | | | 465 | |
466 | for (i=0;i<sizeof(sc->sc_enaddr);i++) | | 466 | for (i=0;i<sizeof(sc->sc_enaddr);i++) |
467 | MB_WRITE_REG(sc, MB8795_ENADDR+i, sc->sc_enaddr[i]); | | 467 | MB_WRITE_REG(sc, MB8795_ENADDR+i, sc->sc_enaddr[i]); |
468 | | | 468 | |
469 | DPRINTF(("%s: initializing ethernet %02x:%02x:%02x:%02x:%02x:%02x, " | | 469 | DPRINTF(("%s: initializing ethernet %02x:%02x:%02x:%02x:%02x:%02x, " |
470 | "size=%d\n", device_xname(sc->sc_dev), | | 470 | "size=%d\n", device_xname(sc->sc_dev), |
471 | sc->sc_enaddr[0],sc->sc_enaddr[1],sc->sc_enaddr[2], | | 471 | sc->sc_enaddr[0],sc->sc_enaddr[1],sc->sc_enaddr[2], |
472 | sc->sc_enaddr[3],sc->sc_enaddr[4],sc->sc_enaddr[5], | | 472 | sc->sc_enaddr[3],sc->sc_enaddr[4],sc->sc_enaddr[5], |
473 | sizeof(sc->sc_enaddr))); | | 473 | sizeof(sc->sc_enaddr))); |
474 | | | 474 | |
475 | MB_WRITE_REG(sc, MB8795_RESET, 0); | | 475 | MB_WRITE_REG(sc, MB8795_RESET, 0); |
476 | | | 476 | |
477 | splx(s); | | 477 | splx(s); |
478 | } | | 478 | } |
479 | | | 479 | |
480 | void | | 480 | void |
481 | mb8795_watchdog(struct ifnet *ifp) | | 481 | mb8795_watchdog(struct ifnet *ifp) |
482 | { | | 482 | { |
483 | struct mb8795_softc *sc = ifp->if_softc; | | 483 | struct mb8795_softc *sc = ifp->if_softc; |
484 | | | 484 | |
485 | log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); | | 485 | log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); |
486 | ++ifp->if_oerrors; | | 486 | if_statinc(ifp, if_oerrors); |
487 | | | | |
488 | DPRINTF(("%s: %lld input errors, %lld input packets\n", | | | |
489 | device_xname(sc->sc_dev), ifp->if_ierrors, ifp->if_ipackets)); | | | |
490 | | | 487 | |
491 | ifp->if_flags &= ~IFF_RUNNING; | | 488 | ifp->if_flags &= ~IFF_RUNNING; |
492 | mb8795_init(sc); | | 489 | mb8795_init(sc); |
493 | } | | 490 | } |
494 | | | 491 | |
495 | /* | | 492 | /* |
496 | * Initialization of interface; set up initialization block | | 493 | * Initialization of interface; set up initialization block |
497 | * and transmit/receive descriptor rings. | | 494 | * and transmit/receive descriptor rings. |
498 | */ | | 495 | */ |
499 | void | | 496 | void |
500 | mb8795_init(struct mb8795_softc *sc) | | 497 | mb8795_init(struct mb8795_softc *sc) |
501 | { | | 498 | { |
502 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 499 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
503 | int s; | | 500 | int s; |
504 | | | 501 | |
505 | DPRINTF (("%s: mb8795_init()\n", device_xname(sc->sc_dev))); | | 502 | DPRINTF (("%s: mb8795_init()\n", device_xname(sc->sc_dev))); |
506 | | | 503 | |
507 | if (ifp->if_flags & IFF_UP) { | | 504 | if (ifp->if_flags & IFF_UP) { |
508 | int rxmode; | | 505 | int rxmode; |
509 | | | 506 | |
510 | s = spldma(); | | 507 | s = spldma(); |
511 | if ((ifp->if_flags & IFF_RUNNING) == 0) | | 508 | if ((ifp->if_flags & IFF_RUNNING) == 0) |
512 | mb8795_reset(sc); | | 509 | mb8795_reset(sc); |
513 | | | 510 | |
514 | if (ifp->if_flags & IFF_PROMISC) | | 511 | if (ifp->if_flags & IFF_PROMISC) |
515 | rxmode = MB8795_RXMODE_PROMISCUOUS; | | 512 | rxmode = MB8795_RXMODE_PROMISCUOUS; |
516 | else | | 513 | else |
517 | rxmode = MB8795_RXMODE_NORMAL; | | 514 | rxmode = MB8795_RXMODE_NORMAL; |
518 | /* XXX add support for multicast */ | | 515 | /* XXX add support for multicast */ |
519 | if (turbo) | | 516 | if (turbo) |
520 | rxmode |= MB8795_RXMODE_TEST; | | 517 | rxmode |= MB8795_RXMODE_TEST; |
521 | | | 518 | |
522 | /* switching mode probably borken now with turbo */ | | 519 | /* switching mode probably borken now with turbo */ |
523 | MB_WRITE_REG(sc, MB8795_TXMODE, | | 520 | MB_WRITE_REG(sc, MB8795_TXMODE, |
524 | turbo ? MB8795_TXMODE_TURBO1 : MB8795_TXMODE_LB_DISABLE); | | 521 | turbo ? MB8795_TXMODE_TURBO1 : MB8795_TXMODE_LB_DISABLE); |
525 | MB_WRITE_REG(sc, MB8795_RXMODE, rxmode); | | 522 | MB_WRITE_REG(sc, MB8795_RXMODE, rxmode); |
526 | | | 523 | |
527 | if ((ifp->if_flags & IFF_RUNNING) == 0) { | | 524 | if ((ifp->if_flags & IFF_RUNNING) == 0) { |
528 | MBDMA_RX_SETUP(sc); | | 525 | MBDMA_RX_SETUP(sc); |
529 | MBDMA_TX_SETUP(sc); | | 526 | MBDMA_TX_SETUP(sc); |
530 | | | 527 | |
531 | ifp->if_flags |= IFF_RUNNING; | | 528 | ifp->if_flags |= IFF_RUNNING; |
532 | ifp->if_flags &= ~IFF_OACTIVE; | | 529 | ifp->if_flags &= ~IFF_OACTIVE; |
533 | ifp->if_timer = 0; | | 530 | ifp->if_timer = 0; |
534 | | | 531 | |
535 | MBDMA_RX_GO(sc); | | 532 | MBDMA_RX_GO(sc); |
536 | } | | 533 | } |
537 | splx(s); | | 534 | splx(s); |
538 | #if 0 | | 535 | #if 0 |
539 | s = spldma(); | | 536 | s = spldma(); |
540 | if (! IF_IS_EMPTY(&sc->sc_tx_snd)) | | 537 | if (! IF_IS_EMPTY(&sc->sc_tx_snd)) |
541 | mb8795_start_dma(ifp); | | 538 | mb8795_start_dma(ifp); |
542 | splx(s); | | 539 | splx(s); |
543 | #endif | | 540 | #endif |
544 | } else | | 541 | } else |
545 | mb8795_reset(sc); | | 542 | mb8795_reset(sc); |
546 | } | | 543 | } |
547 | | | 544 | |
548 | void | | 545 | void |
549 | mb8795_shutdown(void *arg) | | 546 | mb8795_shutdown(void *arg) |
550 | { | | 547 | { |
551 | struct mb8795_softc *sc = (struct mb8795_softc *)arg; | | 548 | struct mb8795_softc *sc = (struct mb8795_softc *)arg; |
552 | | | 549 | |
553 | DPRINTF(("%s: mb8795_shutdown()\n", device_xname(sc->sc_dev))); | | 550 | DPRINTF(("%s: mb8795_shutdown()\n", device_xname(sc->sc_dev))); |
554 | | | 551 | |
555 | mb8795_reset(sc); | | 552 | mb8795_reset(sc); |
556 | } | | 553 | } |
557 | | | 554 | |
558 | /****************************************************************/ | | 555 | /****************************************************************/ |
559 | int | | 556 | int |
560 | mb8795_ioctl(struct ifnet *ifp, u_long cmd, void *data) | | 557 | mb8795_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
561 | { | | 558 | { |
562 | struct mb8795_softc *sc = ifp->if_softc; | | 559 | struct mb8795_softc *sc = ifp->if_softc; |
563 | struct ifaddr *ifa = (struct ifaddr *)data; | | 560 | struct ifaddr *ifa = (struct ifaddr *)data; |
564 | int s, error = 0; | | 561 | int s, error = 0; |
565 | | | 562 | |
566 | s = splnet(); | | 563 | s = splnet(); |
567 | | | 564 | |
568 | DPRINTF(("%s: mb8795_ioctl()\n", device_xname(sc->sc_dev))); | | 565 | DPRINTF(("%s: mb8795_ioctl()\n", device_xname(sc->sc_dev))); |
569 | | | 566 | |
570 | switch (cmd) { | | 567 | switch (cmd) { |
571 | | | 568 | |
572 | case SIOCINITIFADDR: | | 569 | case SIOCINITIFADDR: |
573 | DPRINTF(("%s: mb8795_ioctl() SIOCINITIFADDR\n", | | 570 | DPRINTF(("%s: mb8795_ioctl() SIOCINITIFADDR\n", |
574 | device_xname(sc->sc_dev))); | | 571 | device_xname(sc->sc_dev))); |
575 | ifp->if_flags |= IFF_UP; | | 572 | ifp->if_flags |= IFF_UP; |
576 | | | 573 | |
577 | mb8795_init(sc); | | 574 | mb8795_init(sc); |
578 | switch (ifa->ifa_addr->sa_family) { | | 575 | switch (ifa->ifa_addr->sa_family) { |
579 | #ifdef INET | | 576 | #ifdef INET |
580 | case AF_INET: | | 577 | case AF_INET: |
581 | arp_ifinit(ifp, ifa); | | 578 | arp_ifinit(ifp, ifa); |
582 | break; | | 579 | break; |
583 | #endif | | 580 | #endif |
584 | default: | | 581 | default: |
585 | break; | | 582 | break; |
586 | } | | 583 | } |
587 | break; | | 584 | break; |
588 | | | 585 | |
589 | | | 586 | |
590 | case SIOCSIFFLAGS: | | 587 | case SIOCSIFFLAGS: |
591 | DPRINTF(("%s: mb8795_ioctl() SIOCSIFFLAGS\n", | | 588 | DPRINTF(("%s: mb8795_ioctl() SIOCSIFFLAGS\n", |
592 | device_xname(sc->sc_dev))); | | 589 | device_xname(sc->sc_dev))); |
593 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) | | 590 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) |
594 | break; | | 591 | break; |
595 | switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { | | 592 | switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { |
596 | case IFF_RUNNING: | | 593 | case IFF_RUNNING: |
597 | /* | | 594 | /* |
598 | * If interface is marked down and it is running, then | | 595 | * If interface is marked down and it is running, then |
599 | * stop it. | | 596 | * stop it. |
600 | */ | | 597 | */ |
601 | #if 0 | | 598 | #if 0 |
602 | ifp->if_flags &= ~IFF_RUNNING; | | 599 | ifp->if_flags &= ~IFF_RUNNING; |
603 | #endif | | 600 | #endif |
604 | mb8795_reset(sc); | | 601 | mb8795_reset(sc); |
605 | break; | | 602 | break; |
606 | case IFF_UP: | | 603 | case IFF_UP: |
607 | /* | | 604 | /* |
608 | * If interface is marked up and it is stopped, then | | 605 | * If interface is marked up and it is stopped, then |
609 | * start it. | | 606 | * start it. |
610 | */ | | 607 | */ |
611 | mb8795_init(sc); | | 608 | mb8795_init(sc); |
612 | break; | | 609 | break; |
613 | default: | | 610 | default: |
614 | /* | | 611 | /* |
615 | * Reset the interface to pick up changes in any other | | 612 | * Reset the interface to pick up changes in any other |
616 | * flags that affect hardware registers. | | 613 | * flags that affect hardware registers. |
617 | */ | | 614 | */ |
618 | mb8795_init(sc); | | 615 | mb8795_init(sc); |
619 | break; | | 616 | break; |
620 | } | | 617 | } |
621 | #ifdef MB8795_DEBUG | | 618 | #ifdef MB8795_DEBUG |
622 | if (ifp->if_flags & IFF_DEBUG) | | 619 | if (ifp->if_flags & IFF_DEBUG) |
623 | sc->sc_debug = 1; | | 620 | sc->sc_debug = 1; |
624 | else | | 621 | else |
625 | sc->sc_debug = 0; | | 622 | sc->sc_debug = 0; |
626 | #endif | | 623 | #endif |
627 | break; | | 624 | break; |
628 | | | 625 | |
629 | case SIOCADDMULTI: | | 626 | case SIOCADDMULTI: |
630 | case SIOCDELMULTI: | | 627 | case SIOCDELMULTI: |
631 | DPRINTF(("%s: mb8795_ioctl() SIOCADDMULTI\n", | | 628 | DPRINTF(("%s: mb8795_ioctl() SIOCADDMULTI\n", |
632 | device_xname(sc->sc_dev))); | | 629 | device_xname(sc->sc_dev))); |
633 | if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { | | 630 | if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { |
634 | /* | | 631 | /* |
635 | * Multicast list has changed; set the hardware filter | | 632 | * Multicast list has changed; set the hardware filter |
636 | * accordingly. | | 633 | * accordingly. |
637 | */ | | 634 | */ |
638 | if (ifp->if_flags & IFF_RUNNING) | | 635 | if (ifp->if_flags & IFF_RUNNING) |
639 | mb8795_init(sc); | | 636 | mb8795_init(sc); |
640 | error = 0; | | 637 | error = 0; |
641 | } | | 638 | } |
642 | break; | | 639 | break; |
643 | | | 640 | |
644 | default: | | 641 | default: |
645 | error = ether_ioctl(ifp, cmd, data); | | 642 | error = ether_ioctl(ifp, cmd, data); |
646 | break; | | 643 | break; |
647 | } | | 644 | } |
648 | | | 645 | |
649 | splx(s); | | 646 | splx(s); |
650 | | | 647 | |
651 | #if 0 | | 648 | #if 0 |
652 | DPRINTF(("DEBUG: mb8795_ioctl(0x%lx) returning %d\n", cmd, error)); | | 649 | DPRINTF(("DEBUG: mb8795_ioctl(0x%lx) returning %d\n", cmd, error)); |
653 | #endif | | 650 | #endif |
654 | | | 651 | |
655 | return error; | | 652 | return error; |
656 | } | | 653 | } |
657 | | | 654 | |
658 | /* | | 655 | /* |
659 | * Setup output on interface. | | 656 | * Setup output on interface. |
660 | * Get another datagram to send off of the interface queue, and map it to the | | 657 | * Get another datagram to send off of the interface queue, and map it to the |
661 | * interface before starting the output. | | 658 | * interface before starting the output. |
662 | * Called only at splnet or interrupt level. | | 659 | * Called only at splnet or interrupt level. |
663 | */ | | 660 | */ |
664 | void | | 661 | void |
665 | mb8795_start(struct ifnet *ifp) | | 662 | mb8795_start(struct ifnet *ifp) |
666 | { | | 663 | { |
667 | struct mb8795_softc *sc = ifp->if_softc; | | 664 | struct mb8795_softc *sc = ifp->if_softc; |
668 | struct mbuf *m; | | 665 | struct mbuf *m; |
669 | int s; | | 666 | int s; |
670 | | | 667 | |
671 | DPRINTF(("%s: mb8795_start()\n", device_xname(sc->sc_dev))); | | 668 | DPRINTF(("%s: mb8795_start()\n", device_xname(sc->sc_dev))); |
672 | | | 669 | |
673 | #ifdef DIAGNOSTIC | | 670 | #ifdef DIAGNOSTIC |
674 | IFQ_POLL(&ifp->if_snd, m); | | 671 | IFQ_POLL(&ifp->if_snd, m); |
675 | if (m == 0) | | 672 | if (m == 0) |
676 | panic("%s: No packet to start", device_xname(sc->sc_dev)); | | 673 | panic("%s: No packet to start", device_xname(sc->sc_dev)); |
677 | #endif | | 674 | #endif |
678 | | | 675 | |
679 | while (1) { | | 676 | while (1) { |
680 | if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) | | 677 | if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) |
681 | != IFF_RUNNING) | | 678 | != IFF_RUNNING) |
682 | return; | | 679 | return; |
683 | | | 680 | |
684 | #if 0 | | 681 | #if 0 |
685 | return; /* @@@ Turn off xmit for debugging */ | | 682 | return; /* @@@ Turn off xmit for debugging */ |
686 | #endif | | 683 | #endif |
687 | | | 684 | |
688 | ifp->if_flags |= IFF_OACTIVE; | | 685 | ifp->if_flags |= IFF_OACTIVE; |
689 | | | 686 | |
690 | IFQ_DEQUEUE(&ifp->if_snd, m); | | 687 | IFQ_DEQUEUE(&ifp->if_snd, m); |
691 | if (m == 0) { | | 688 | if (m == 0) { |
692 | ifp->if_flags &= ~IFF_OACTIVE; | | 689 | ifp->if_flags &= ~IFF_OACTIVE; |
693 | return; | | 690 | return; |
694 | } | | 691 | } |
695 | | | 692 | |
696 | /* Pass packet to bpf if there is a listener. */ | | 693 | /* Pass packet to bpf if there is a listener. */ |
697 | bpf_mtap(ifp, m, BPF_D_OUT); | | 694 | bpf_mtap(ifp, m, BPF_D_OUT); |
698 | | | 695 | |
699 | s = spldma(); | | 696 | s = spldma(); |
700 | IF_ENQUEUE(&sc->sc_tx_snd, m); | | 697 | IF_ENQUEUE(&sc->sc_tx_snd, m); |
701 | if (!MBDMA_TX_ISACTIVE(sc)) | | 698 | if (!MBDMA_TX_ISACTIVE(sc)) |
702 | mb8795_start_dma(sc); | | 699 | mb8795_start_dma(sc); |
703 | splx(s); | | 700 | splx(s); |
704 | | | 701 | |
705 | ifp->if_flags &= ~IFF_OACTIVE; | | 702 | ifp->if_flags &= ~IFF_OACTIVE; |
706 | } | | 703 | } |
707 | } | | 704 | } |
708 | | | 705 | |
709 | void | | 706 | void |
710 | mb8795_start_dma(struct mb8795_softc *sc) | | 707 | mb8795_start_dma(struct mb8795_softc *sc) |
711 | { | | 708 | { |
712 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 709 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
713 | struct mbuf *m; | | 710 | struct mbuf *m; |
714 | u_char txmask; | | 711 | u_char txmask; |
715 | | | 712 | |
716 | DPRINTF(("%s: mb8795_start_dma()\n", device_xname(sc->sc_dev))); | | 713 | DPRINTF(("%s: mb8795_start_dma()\n", device_xname(sc->sc_dev))); |
717 | | | 714 | |
718 | #if (defined(DIAGNOSTIC)) | | 715 | #if (defined(DIAGNOSTIC)) |
719 | { | | 716 | { |
720 | u_char txstat; | | 717 | u_char txstat; |
721 | txstat = MB_READ_REG(sc, MB8795_TXSTAT); | | 718 | txstat = MB_READ_REG(sc, MB8795_TXSTAT); |
722 | if (!turbo && !(txstat & MB8795_TXSTAT_READY)) { | | 719 | if (!turbo && !(txstat & MB8795_TXSTAT_READY)) { |
723 | /* | | 720 | /* |
724 | * @@@ I used to panic here, but then it paniced once. | | 721 | * @@@ I used to panic here, but then it paniced once. |
725 | * Let's see if I can just reset instead. | | 722 | * Let's see if I can just reset instead. |
726 | * [ dbj 980706.1900 ] | | 723 | * [ dbj 980706.1900 ] |
727 | */ | | 724 | */ |
728 | printf("%s: transmitter not ready\n", | | 725 | printf("%s: transmitter not ready\n", |
729 | device_xname(sc->sc_dev)); | | 726 | device_xname(sc->sc_dev)); |
730 | ifp->if_flags &= ~IFF_RUNNING; | | 727 | ifp->if_flags &= ~IFF_RUNNING; |
731 | mb8795_init(sc); | | 728 | mb8795_init(sc); |
732 | return; | | 729 | return; |
733 | } | | 730 | } |
734 | } | | 731 | } |
735 | #endif | | 732 | #endif |
736 | | | 733 | |
737 | #if 0 | | 734 | #if 0 |
738 | return; /* @@@ Turn off xmit for debugging */ | | 735 | return; /* @@@ Turn off xmit for debugging */ |
739 | #endif | | 736 | #endif |
740 | | | 737 | |
741 | IF_DEQUEUE(&sc->sc_tx_snd, m); | | 738 | IF_DEQUEUE(&sc->sc_tx_snd, m); |
742 | if (m == 0) { | | 739 | if (m == 0) { |
743 | #ifdef DIAGNOSTIC | | 740 | #ifdef DIAGNOSTIC |
744 | panic("%s: No packet to start_dma", device_xname(sc->sc_dev)); | | 741 | panic("%s: No packet to start_dma", device_xname(sc->sc_dev)); |
745 | #endif | | 742 | #endif |
746 | return; | | 743 | return; |
747 | } | | 744 | } |
748 | | | 745 | |
749 | MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); | | 746 | MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); |
750 | txmask = MB_READ_REG(sc, MB8795_TXMASK); | | 747 | txmask = MB_READ_REG(sc, MB8795_TXMASK); |
751 | __USE(txmask); | | 748 | __USE(txmask); |
752 | /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_READYIE); */ | | 749 | /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_READYIE); */ |
753 | /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_TXRXIE); */ | | 750 | /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_TXRXIE); */ |
754 | | | 751 | |
755 | ifp->if_timer = 5; | | 752 | ifp->if_timer = 5; |
756 | | | 753 | |
757 | if (MBDMA_TX_MBUF(sc, m)) | | 754 | if (MBDMA_TX_MBUF(sc, m)) |
758 | return; | | 755 | return; |
759 | | | 756 | |
760 | MBDMA_TX_GO(sc); | | 757 | MBDMA_TX_GO(sc); |
761 | if (turbo) | | 758 | if (turbo) |
762 | MB_WRITE_REG(sc, MB8795_TXMODE, | | 759 | MB_WRITE_REG(sc, MB8795_TXMODE, |
763 | MB8795_TXMODE_TURBO1 | MB8795_TXMODE_TURBOSTART); | | 760 | MB8795_TXMODE_TURBO1 | MB8795_TXMODE_TURBOSTART); |
764 | | | 761 | |
765 | ifp->if_opackets++; | | 762 | if_statinc(ifp, if_opackets); |
766 | } | | 763 | } |
767 | | | 764 | |
768 | /****************************************************************/ | | 765 | /****************************************************************/ |