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