1 1.53 thorpej /* $NetBSD: if_qn.c,v 1.53 2022/09/17 19:23:24 thorpej Exp $ */ 2 1.1 chopps 3 1.1 chopps /* 4 1.1 chopps * Copyright (c) 1995 Mika Kortelainen 5 1.1 chopps * All rights reserved. 6 1.1 chopps * 7 1.1 chopps * Redistribution and use in source and binary forms, with or without 8 1.1 chopps * modification, are permitted provided that the following conditions 9 1.1 chopps * are met: 10 1.1 chopps * 1. Redistributions of source code must retain the above copyright 11 1.1 chopps * notice, this list of conditions and the following disclaimer. 12 1.1 chopps * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 chopps * notice, this list of conditions and the following disclaimer in the 14 1.1 chopps * documentation and/or other materials provided with the distribution. 15 1.1 chopps * 3. All advertising materials mentioning features or use of this software 16 1.1 chopps * must display the following acknowledgement: 17 1.1 chopps * This product includes software developed by Mika Kortelainen 18 1.1 chopps * 4. The name of the author may not be used to endorse or promote products 19 1.1 chopps * derived from this software without specific prior written permission 20 1.1 chopps * 21 1.1 chopps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 1.1 chopps * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 1.1 chopps * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 1.1 chopps * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 1.1 chopps * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 1.1 chopps * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 1.1 chopps * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 1.1 chopps * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 1.1 chopps * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 1.1 chopps * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 1.1 chopps * 32 1.1 chopps * Thanks for Aspecs Oy (Finland) for the data book for the NIC used 33 1.1 chopps * in this card and also many thanks for the Resource Management Force 34 1.1 chopps * (QuickNet card manufacturer) and especially Daniel Koch for providing 35 1.1 chopps * me with the necessary 'inside' information to write the driver. 36 1.1 chopps * 37 1.1 chopps * This is partly based on other code: 38 1.2 jtc * - if_ed.c: basic function structure for Ethernet driver and now also 39 1.2 jtc * qn_put() is done similarly, i.e. no extra packet buffers. 40 1.1 chopps * 41 1.1 chopps * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 42 1.1 chopps * adapters. 43 1.1 chopps * 44 1.1 chopps * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 45 1.1 chopps * 46 1.1 chopps * Copyright (C) 1993, David Greenman. This software may be used, 47 1.1 chopps * modified, copied, distributed, and sold, in both source and binary 48 1.1 chopps * form provided that the above copyright and these terms are retained. 49 1.1 chopps * Under no circumstances is the author responsible for the proper 50 1.1 chopps * functioning of this software, nor does the author assume any 51 1.1 chopps * responsibility for damages incurred with its use. 52 1.1 chopps * 53 1.1 chopps * - if_es.c: used as an example of -current driver 54 1.1 chopps * 55 1.1 chopps * Copyright (c) 1995 Michael L. Hitch 56 1.1 chopps * All rights reserved. 57 1.1 chopps * 58 1.2 jtc * - if_fe.c: some ideas for error handling for qn_rint() which might 59 1.2 jtc * have fixed those random lock ups, too. 60 1.2 jtc * 61 1.2 jtc * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 62 1.2 jtc * 63 1.1 chopps * 64 1.1 chopps * TODO: 65 1.1 chopps * - add multicast support 66 1.1 chopps */ 67 1.22 aymeric 68 1.22 aymeric #include <sys/cdefs.h> 69 1.53 thorpej __KERNEL_RCSID(0, "$NetBSD: if_qn.c,v 1.53 2022/09/17 19:23:24 thorpej Exp $"); 70 1.1 chopps 71 1.1 chopps #include "qn.h" 72 1.1 chopps #if NQN > 0 73 1.1 chopps 74 1.1 chopps #define QN_DEBUG 75 1.2 jtc #define QN_DEBUG1_no /* hides some old tests */ 76 1.7 is #define QN_CHECKS_no /* adds some checks (not needed in normal situations) */ 77 1.1 chopps 78 1.1 chopps 79 1.1 chopps /* 80 1.2 jtc * Fujitsu MB86950 Ethernet Controller (as used in the QuickNet QN2000 81 1.2 jtc * Ethernet card) 82 1.1 chopps */ 83 1.15 jonathan 84 1.15 jonathan #include "opt_inet.h" 85 1.16 jonathan #include "opt_ns.h" 86 1.1 chopps 87 1.1 chopps #include <sys/param.h> 88 1.1 chopps #include <sys/systm.h> 89 1.1 chopps #include <sys/mbuf.h> 90 1.1 chopps #include <sys/buf.h> 91 1.1 chopps #include <sys/device.h> 92 1.1 chopps #include <sys/protosw.h> 93 1.1 chopps #include <sys/socket.h> 94 1.1 chopps #include <sys/syslog.h> 95 1.1 chopps #include <sys/ioctl.h> 96 1.1 chopps #include <sys/errno.h> 97 1.1 chopps 98 1.1 chopps #include <net/if.h> 99 1.12 is #include <net/if_dl.h> 100 1.11 is #include <net/if_ether.h> 101 1.45 msaitoh #include <net/bpf.h> 102 1.1 chopps 103 1.1 chopps #ifdef INET 104 1.1 chopps #include <netinet/in.h> 105 1.1 chopps #include <netinet/in_systm.h> 106 1.1 chopps #include <netinet/in_var.h> 107 1.1 chopps #include <netinet/ip.h> 108 1.11 is #include <netinet/if_inarp.h> 109 1.1 chopps #endif 110 1.1 chopps 111 1.1 chopps #include <machine/cpu.h> 112 1.1 chopps #include <amiga/amiga/device.h> 113 1.1 chopps #include <amiga/amiga/isr.h> 114 1.1 chopps #include <amiga/dev/zbusvar.h> 115 1.1 chopps #include <amiga/dev/if_qnreg.h> 116 1.1 chopps 117 1.1 chopps 118 1.2 jtc #define NIC_R_MASK (R_INT_PKT_RDY | R_INT_ALG_ERR |\ 119 1.2 jtc R_INT_CRC_ERR | R_INT_OVR_FLO) 120 1.2 jtc #define MAX_PACKETS 30 /* max number of packets read per interrupt */ 121 1.1 chopps 122 1.1 chopps /* 123 1.1 chopps * Ethernet software status per interface 124 1.1 chopps * 125 1.1 chopps * Each interface is referenced by a network interface structure, 126 1.1 chopps * qn_if, which the routing code uses to locate the interface. 127 1.1 chopps * This structure contains the output queue for the interface, its address, ... 128 1.1 chopps */ 129 1.1 chopps struct qn_softc { 130 1.39 chs device_t sc_dev; 131 1.1 chopps struct isr sc_isr; 132 1.11 is struct ethercom sc_ethercom; /* Common ethernet structures */ 133 1.1 chopps u_char volatile *sc_base; 134 1.1 chopps u_char volatile *sc_nic_base; 135 1.1 chopps u_short volatile *nic_fifo; 136 1.1 chopps u_short volatile *nic_r_status; 137 1.1 chopps u_short volatile *nic_t_status; 138 1.1 chopps u_short volatile *nic_r_mask; 139 1.1 chopps u_short volatile *nic_t_mask; 140 1.1 chopps u_short volatile *nic_r_mode; 141 1.1 chopps u_short volatile *nic_t_mode; 142 1.1 chopps u_short volatile *nic_reset; 143 1.1 chopps u_short volatile *nic_len; 144 1.52 thorpej bool transmit_pending; 145 1.51 thorpej }; 146 1.1 chopps 147 1.39 chs int qnmatch(device_t, cfdata_t, void *); 148 1.39 chs void qnattach(device_t, device_t, void *); 149 1.21 aymeric int qnintr(void *); 150 1.26 christos int qnioctl(struct ifnet *, u_long, void *); 151 1.21 aymeric void qnstart(struct ifnet *); 152 1.21 aymeric void qnwatchdog(struct ifnet *); 153 1.21 aymeric void qnreset(struct qn_softc *); 154 1.21 aymeric void qninit(struct qn_softc *); 155 1.21 aymeric void qnstop(struct qn_softc *); 156 1.21 aymeric static u_short qn_put(u_short volatile *, struct mbuf *); 157 1.21 aymeric static void qn_rint(struct qn_softc *, u_short); 158 1.21 aymeric static void qn_flush(struct qn_softc *); 159 1.21 aymeric static void inline word_copy_from_card(u_short volatile *, u_short *, u_short); 160 1.21 aymeric static void inline word_copy_to_card(u_short *, u_short volatile *, 161 1.21 aymeric register u_short); 162 1.21 aymeric static void qn_get_packet(struct qn_softc *, u_short); 163 1.2 jtc #ifdef QN_DEBUG1 164 1.21 aymeric static void qn_dump(struct qn_softc *); 165 1.2 jtc #endif 166 1.1 chopps 167 1.39 chs CFATTACH_DECL_NEW(qn, sizeof(struct qn_softc), 168 1.24 thorpej qnmatch, qnattach, NULL, NULL); 169 1.2 jtc 170 1.1 chopps int 171 1.39 chs qnmatch(device_t parent, cfdata_t cf, void *aux) 172 1.1 chopps { 173 1.1 chopps struct zbus_args *zap; 174 1.1 chopps 175 1.1 chopps zap = (struct zbus_args *)aux; 176 1.1 chopps 177 1.1 chopps /* RMF QuickNet QN2000 EtherNet card */ 178 1.1 chopps if (zap->manid == 2011 && zap->prodid == 2) 179 1.1 chopps return (1); 180 1.1 chopps 181 1.1 chopps return (0); 182 1.1 chopps } 183 1.1 chopps 184 1.1 chopps /* 185 1.1 chopps * Interface exists: make available by filling in network interface 186 1.1 chopps * record. System will initialize the interface when it is ready 187 1.1 chopps * to accept packets. 188 1.1 chopps */ 189 1.1 chopps void 190 1.39 chs qnattach(device_t parent, device_t self, void *aux) 191 1.1 chopps { 192 1.1 chopps struct zbus_args *zap; 193 1.39 chs struct qn_softc *sc = device_private(self); 194 1.11 is struct ifnet *ifp = &sc->sc_ethercom.ec_if; 195 1.11 is u_int8_t myaddr[ETHER_ADDR_LEN]; 196 1.1 chopps 197 1.48 msaitoh sc->sc_dev = self; 198 1.1 chopps zap = (struct zbus_args *)aux; 199 1.1 chopps 200 1.1 chopps sc->sc_base = zap->va; 201 1.1 chopps sc->sc_nic_base = sc->sc_base + QUICKNET_NIC_BASE; 202 1.1 chopps sc->nic_fifo = (u_short volatile *)(sc->sc_nic_base + NIC_BMPR0); 203 1.1 chopps sc->nic_len = (u_short volatile *)(sc->sc_nic_base + NIC_BMPR2); 204 1.1 chopps sc->nic_t_status = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR0); 205 1.1 chopps sc->nic_r_status = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR2); 206 1.1 chopps sc->nic_t_mask = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR1); 207 1.1 chopps sc->nic_r_mask = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR3); 208 1.1 chopps sc->nic_t_mode = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR4); 209 1.1 chopps sc->nic_r_mode = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR5); 210 1.1 chopps sc->nic_reset = (u_short volatile *)(sc->sc_nic_base + NIC_DLCR6); 211 1.52 thorpej sc->transmit_pending = false; 212 1.1 chopps 213 1.1 chopps /* 214 1.1 chopps * The ethernet address of the board (1st three bytes are the vendor 215 1.1 chopps * address, the rest is the serial number of the board). 216 1.1 chopps */ 217 1.11 is myaddr[0] = 0x5c; 218 1.11 is myaddr[1] = 0x5c; 219 1.11 is myaddr[2] = 0x00; 220 1.11 is myaddr[3] = (zap->serno >> 16) & 0xff; 221 1.11 is myaddr[4] = (zap->serno >> 8) & 0xff; 222 1.11 is myaddr[5] = zap->serno & 0xff; 223 1.1 chopps 224 1.1 chopps /* set interface to stopped condition (reset) */ 225 1.1 chopps qnstop(sc); 226 1.1 chopps 227 1.39 chs memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 228 1.6 thorpej ifp->if_softc = sc; 229 1.1 chopps ifp->if_ioctl = qnioctl; 230 1.1 chopps ifp->if_watchdog = qnwatchdog; 231 1.1 chopps ifp->if_start = qnstart; 232 1.1 chopps /* XXX IFF_MULTICAST */ 233 1.47 msaitoh ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 234 1.1 chopps ifp->if_mtu = ETHERMTU; 235 1.1 chopps 236 1.1 chopps /* Attach the interface. */ 237 1.1 chopps if_attach(ifp); 238 1.44 nonaka if_deferred_start_init(ifp, NULL); 239 1.11 is ether_ifattach(ifp, myaddr); 240 1.1 chopps 241 1.1 chopps #ifdef QN_DEBUG 242 1.11 is printf(": hardware address %s\n", ether_sprintf(myaddr)); 243 1.1 chopps #endif 244 1.1 chopps 245 1.1 chopps sc->sc_isr.isr_intr = qnintr; 246 1.1 chopps sc->sc_isr.isr_arg = sc; 247 1.1 chopps sc->sc_isr.isr_ipl = 2; 248 1.1 chopps add_isr(&sc->sc_isr); 249 1.1 chopps } 250 1.1 chopps 251 1.1 chopps /* 252 1.1 chopps * Initialize device 253 1.1 chopps * 254 1.1 chopps */ 255 1.1 chopps void 256 1.21 aymeric qninit(struct qn_softc *sc) 257 1.1 chopps { 258 1.11 is struct ifnet *ifp = &sc->sc_ethercom.ec_if; 259 1.1 chopps u_short i; 260 1.14 veego static int retry = 0; 261 1.1 chopps 262 1.2 jtc *sc->nic_r_mask = NIC_R_MASK; 263 1.2 jtc *sc->nic_t_mode = NO_LOOPBACK; 264 1.1 chopps 265 1.11 is if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC) { 266 1.1 chopps *sc->nic_r_mode = PROMISCUOUS_MODE; 267 1.1 chopps log(LOG_INFO, "qn: Promiscuous mode (not tested)\n"); 268 1.1 chopps } else 269 1.1 chopps *sc->nic_r_mode = NORMAL_MODE; 270 1.1 chopps 271 1.1 chopps /* Set physical ethernet address. */ 272 1.1 chopps for (i = 0; i < ETHER_ADDR_LEN; i++) 273 1.2 jtc *((u_short volatile *)(sc->sc_nic_base+ 274 1.2 jtc QNET_HARDWARE_ADDRESS+2*i)) = 275 1.28 dyoung ((((u_short)CLLADDR(ifp->if_sadl)[i]) << 8) | 276 1.28 dyoung CLLADDR(ifp->if_sadl)[i]); 277 1.1 chopps 278 1.1 chopps ifp->if_flags |= IFF_RUNNING; 279 1.52 thorpej sc->transmit_pending = false; 280 1.1 chopps 281 1.1 chopps qn_flush(sc); 282 1.1 chopps 283 1.2 jtc /* QuickNet magic. Done ONLY once, otherwise a lockup occurs. */ 284 1.2 jtc if (retry == 0) { 285 1.2 jtc *((u_short volatile *)(sc->sc_nic_base + QNET_MAGIC)) = 0; 286 1.2 jtc retry = 1; 287 1.2 jtc } 288 1.2 jtc 289 1.1 chopps /* Enable data link controller. */ 290 1.1 chopps *sc->nic_reset = ENABLE_DLC; 291 1.1 chopps 292 1.1 chopps /* Attempt to start output, if any. */ 293 1.44 nonaka if_schedule_deferred_start(ifp); 294 1.1 chopps } 295 1.1 chopps 296 1.1 chopps /* 297 1.1 chopps * Device timeout/watchdog routine. Entered if the device neglects to 298 1.1 chopps * generate an interrupt after a transmit has been started on it. 299 1.1 chopps */ 300 1.1 chopps void 301 1.21 aymeric qnwatchdog(struct ifnet *ifp) 302 1.1 chopps { 303 1.6 thorpej struct qn_softc *sc = ifp->if_softc; 304 1.1 chopps 305 1.2 jtc log(LOG_INFO, "qn: device timeout (watchdog)\n"); 306 1.49 thorpej if_statinc(ifp, if_oerrors); 307 1.1 chopps 308 1.1 chopps qnreset(sc); 309 1.1 chopps } 310 1.1 chopps 311 1.1 chopps /* 312 1.2 jtc * Flush card's buffer RAM. 313 1.1 chopps */ 314 1.1 chopps static void 315 1.21 aymeric qn_flush(struct qn_softc *sc) 316 1.1 chopps { 317 1.2 jtc #if 1 318 1.1 chopps /* Read data until bus read error (i.e. buffer empty). */ 319 1.2 jtc while (!(*sc->nic_r_status & R_BUS_RD_ERR)) 320 1.1 chopps (void)(*sc->nic_fifo); 321 1.2 jtc #else 322 1.2 jtc /* Read data twice to clear some internal pipelines. */ 323 1.2 jtc (void)(*sc->nic_fifo); 324 1.2 jtc (void)(*sc->nic_fifo); 325 1.1 chopps #endif 326 1.1 chopps 327 1.1 chopps /* Clear bus read error. */ 328 1.1 chopps *sc->nic_r_status = R_BUS_RD_ERR; 329 1.1 chopps } 330 1.1 chopps 331 1.1 chopps /* 332 1.2 jtc * Reset the interface. 333 1.1 chopps * 334 1.1 chopps */ 335 1.1 chopps void 336 1.21 aymeric qnreset(struct qn_softc *sc) 337 1.1 chopps { 338 1.1 chopps int s; 339 1.1 chopps 340 1.3 mycroft s = splnet(); 341 1.1 chopps qnstop(sc); 342 1.1 chopps qninit(sc); 343 1.1 chopps splx(s); 344 1.1 chopps } 345 1.1 chopps 346 1.1 chopps /* 347 1.2 jtc * Take interface offline. 348 1.1 chopps */ 349 1.1 chopps void 350 1.21 aymeric qnstop(struct qn_softc *sc) 351 1.1 chopps { 352 1.1 chopps 353 1.1 chopps /* Stop the interface. */ 354 1.2 jtc *sc->nic_reset = DISABLE_DLC; 355 1.2 jtc delay(200); 356 1.2 jtc *sc->nic_t_status = CLEAR_T_ERR; 357 1.2 jtc *sc->nic_t_mask = CLEAR_T_MASK; 358 1.2 jtc *sc->nic_r_status = CLEAR_R_ERR; 359 1.2 jtc *sc->nic_r_mask = CLEAR_R_MASK; 360 1.2 jtc 361 1.2 jtc /* Turn DMA off */ 362 1.2 jtc *((u_short volatile *)(sc->sc_nic_base + NIC_BMPR4)) = 0; 363 1.1 chopps 364 1.2 jtc /* Accept no packets. */ 365 1.2 jtc *sc->nic_r_mode = 0; 366 1.2 jtc *sc->nic_t_mode = 0; 367 1.1 chopps 368 1.1 chopps qn_flush(sc); 369 1.1 chopps } 370 1.1 chopps 371 1.1 chopps /* 372 1.1 chopps * Start output on interface. Get another datagram to send 373 1.1 chopps * off the interface queue, and copy it to the 374 1.1 chopps * interface before starting the output. 375 1.1 chopps * 376 1.1 chopps * This assumes that it is called inside a critical section... 377 1.1 chopps * 378 1.1 chopps */ 379 1.1 chopps void 380 1.21 aymeric qnstart(struct ifnet *ifp) 381 1.1 chopps { 382 1.6 thorpej struct qn_softc *sc = ifp->if_softc; 383 1.1 chopps struct mbuf *m; 384 1.1 chopps u_short len; 385 1.2 jtc int timout = 60000; 386 1.2 jtc 387 1.1 chopps 388 1.53 thorpej if ((ifp->if_flags & IFF_RUNNING) == 0) 389 1.53 thorpej return; 390 1.53 thorpej 391 1.53 thorpej if (sc->transmit_pending) 392 1.1 chopps return; 393 1.1 chopps 394 1.11 is IF_DEQUEUE(&ifp->if_snd, m); 395 1.1 chopps if (m == 0) 396 1.1 chopps return; 397 1.1 chopps 398 1.1 chopps /* 399 1.1 chopps * If bpf is listening on this interface, let it 400 1.1 chopps * see the packet before we commit it to the wire 401 1.1 chopps * 402 1.1 chopps * (can't give the copy in QuickNet card RAM to bpf, because 403 1.1 chopps * that RAM is not visible to the host but is read from FIFO) 404 1.1 chopps */ 405 1.46 msaitoh bpf_mtap(ifp, m, BPF_D_OUT); 406 1.1 chopps len = qn_put(sc->nic_fifo, m); 407 1.2 jtc m_freem(m); 408 1.1 chopps 409 1.1 chopps /* 410 1.2 jtc * Really transmit the packet. 411 1.1 chopps */ 412 1.1 chopps 413 1.2 jtc /* Set packet length (byte-swapped). */ 414 1.1 chopps len = ((len >> 8) & 0x0007) | TRANSMIT_START | ((len & 0x00ff) << 8); 415 1.1 chopps *sc->nic_len = len; 416 1.1 chopps 417 1.2 jtc /* Wait for the packet to really leave. */ 418 1.2 jtc while (!(*sc->nic_t_status & T_TMT_OK) && --timout) { 419 1.2 jtc if ((timout % 10000) == 0) 420 1.50 msaitoh log(LOG_INFO, "qn: timeout...\n"); 421 1.2 jtc } 422 1.2 jtc 423 1.1 chopps if (timout == 0) 424 1.1 chopps /* Maybe we should try to recover from this one? */ 425 1.2 jtc /* But now, let's just fall thru and hope the best... */ 426 1.50 msaitoh log(LOG_INFO, "qn: transmit timeout (fatal?)\n"); 427 1.1 chopps 428 1.52 thorpej sc->transmit_pending = true; 429 1.1 chopps *sc->nic_t_mask = INT_TMT_OK | INT_SIXTEEN_COL; 430 1.1 chopps 431 1.1 chopps ifp->if_timer = 2; 432 1.1 chopps } 433 1.1 chopps 434 1.1 chopps /* 435 1.1 chopps * Memory copy, copies word at a time 436 1.1 chopps */ 437 1.1 chopps static void inline 438 1.21 aymeric word_copy_from_card(u_short volatile *card, u_short *b, u_short len) 439 1.1 chopps { 440 1.1 chopps register u_short l = len/2; 441 1.1 chopps 442 1.1 chopps while (l--) 443 1.1 chopps *b++ = *card; 444 1.1 chopps } 445 1.1 chopps 446 1.1 chopps static void inline 447 1.21 aymeric word_copy_to_card(u_short *a, u_short volatile *card, register u_short len) 448 1.1 chopps { 449 1.7 is /*register u_short l = len/2;*/ 450 1.1 chopps 451 1.7 is while (len--) 452 1.1 chopps *card = *a++; 453 1.1 chopps } 454 1.1 chopps 455 1.1 chopps /* 456 1.1 chopps * Copy packet from mbuf to the board memory 457 1.1 chopps * 458 1.1 chopps */ 459 1.1 chopps static u_short 460 1.21 aymeric qn_put(u_short volatile *addr, struct mbuf *m) 461 1.1 chopps { 462 1.7 is u_short *data; 463 1.7 is u_char savebyte[2]; 464 1.7 is int len, len1, wantbyte; 465 1.2 jtc u_short totlen; 466 1.2 jtc 467 1.2 jtc totlen = wantbyte = 0; 468 1.2 jtc 469 1.2 jtc for (; m != NULL; m = m->m_next) { 470 1.5 veego data = mtod(m, u_short *); 471 1.2 jtc len = m->m_len; 472 1.2 jtc if (len > 0) { 473 1.7 is totlen += len; 474 1.7 is 475 1.2 jtc /* Finish the last word. */ 476 1.2 jtc if (wantbyte) { 477 1.7 is savebyte[1] = *((u_char *)data); 478 1.2 jtc *addr = *((u_short *)savebyte); 479 1.25 skrll data = (u_short *)((u_char *)data + 1); 480 1.2 jtc len--; 481 1.2 jtc wantbyte = 0; 482 1.2 jtc } 483 1.2 jtc /* Output contiguous words. */ 484 1.2 jtc if (len > 1) { 485 1.7 is len1 = len/2; 486 1.7 is word_copy_to_card(data, addr, len1); 487 1.7 is data += len1; 488 1.2 jtc len &= 1; 489 1.2 jtc } 490 1.2 jtc /* Save last byte, if necessary. */ 491 1.2 jtc if (len == 1) { 492 1.7 is savebyte[0] = *((u_char *)data); 493 1.2 jtc wantbyte = 1; 494 1.2 jtc } 495 1.2 jtc } 496 1.2 jtc } 497 1.1 chopps 498 1.2 jtc if (wantbyte) { 499 1.2 jtc savebyte[1] = 0; 500 1.2 jtc *addr = *((u_short *)savebyte); 501 1.2 jtc } 502 1.1 chopps 503 1.17 thorpej if(totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) { 504 1.2 jtc /* 505 1.2 jtc * Fill the rest of the packet with zeros. 506 1.2 jtc * N.B.: This is required! Otherwise MB86950 fails. 507 1.2 jtc */ 508 1.17 thorpej for(len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN); 509 1.17 thorpej len += 2) 510 1.2 jtc *addr = (u_short)0x0000; 511 1.17 thorpej totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN); 512 1.1 chopps } 513 1.1 chopps 514 1.2 jtc return (totlen); 515 1.1 chopps } 516 1.1 chopps 517 1.1 chopps /* 518 1.2 jtc * Copy packet from board RAM. 519 1.1 chopps * 520 1.1 chopps * Trailers not supported. 521 1.1 chopps * 522 1.1 chopps */ 523 1.1 chopps static void 524 1.21 aymeric qn_get_packet(struct qn_softc *sc, u_short len) 525 1.1 chopps { 526 1.1 chopps register u_short volatile *nic_fifo_ptr = sc->nic_fifo; 527 1.12 is struct ifnet *ifp = &sc->sc_ethercom.ec_if; 528 1.2 jtc struct mbuf *m, *dst, *head = NULL; 529 1.1 chopps register u_short len1; 530 1.1 chopps u_short amount; 531 1.1 chopps 532 1.1 chopps /* Allocate header mbuf. */ 533 1.1 chopps MGETHDR(m, M_DONTWAIT, MT_DATA); 534 1.2 jtc if (m == NULL) 535 1.1 chopps goto bad; 536 1.1 chopps 537 1.2 jtc /* 538 1.2 jtc * Round len to even value. 539 1.2 jtc */ 540 1.2 jtc if (len & 1) 541 1.2 jtc len++; 542 1.2 jtc 543 1.42 ozaki m_set_rcvif(m, &sc->sc_ethercom.ec_if); 544 1.1 chopps m->m_pkthdr.len = len; 545 1.1 chopps m->m_len = 0; 546 1.1 chopps head = m; 547 1.1 chopps 548 1.1 chopps word_copy_from_card(nic_fifo_ptr, 549 1.1 chopps mtod(head, u_short *), 550 1.1 chopps sizeof(struct ether_header)); 551 1.1 chopps 552 1.1 chopps head->m_len += sizeof(struct ether_header); 553 1.1 chopps len -= sizeof(struct ether_header); 554 1.1 chopps 555 1.1 chopps while (len > 0) { 556 1.1 chopps len1 = len; 557 1.1 chopps 558 1.1 chopps amount = M_TRAILINGSPACE(m); 559 1.1 chopps if (amount == 0) { 560 1.2 jtc /* Allocate another mbuf. */ 561 1.1 chopps dst = m; 562 1.1 chopps MGET(m, M_DONTWAIT, MT_DATA); 563 1.2 jtc if (m == NULL) 564 1.1 chopps goto bad; 565 1.1 chopps 566 1.1 chopps if (len1 >= MINCLSIZE) 567 1.1 chopps MCLGET(m, M_DONTWAIT); 568 1.1 chopps 569 1.1 chopps m->m_len = 0; 570 1.1 chopps dst->m_next = m; 571 1.1 chopps 572 1.1 chopps amount = M_TRAILINGSPACE(m); 573 1.1 chopps } 574 1.1 chopps 575 1.2 jtc if (amount < len1) 576 1.1 chopps len1 = amount; 577 1.2 jtc 578 1.1 chopps word_copy_from_card(nic_fifo_ptr, 579 1.27 he (u_short *)(mtod(m, char *) + m->m_len), 580 1.2 jtc len1); 581 1.1 chopps m->m_len += len1; 582 1.1 chopps len -= len1; 583 1.1 chopps } 584 1.1 chopps 585 1.41 ozaki if_percpuq_enqueue(ifp->if_percpuq, head); 586 1.1 chopps return; 587 1.1 chopps 588 1.1 chopps bad: 589 1.2 jtc if (head) { 590 1.1 chopps m_freem(head); 591 1.2 jtc log(LOG_INFO, "qn_get_packet: mbuf alloc failed\n"); 592 1.2 jtc } 593 1.1 chopps } 594 1.1 chopps 595 1.1 chopps /* 596 1.1 chopps * Ethernet interface receiver interrupt. 597 1.1 chopps */ 598 1.1 chopps static void 599 1.21 aymeric qn_rint(struct qn_softc *sc, u_short rstat) 600 1.1 chopps { 601 1.1 chopps int i; 602 1.1 chopps u_short len, status; 603 1.1 chopps 604 1.2 jtc /* Clear the status register. */ 605 1.2 jtc *sc->nic_r_status = CLEAR_R_ERR; 606 1.2 jtc 607 1.1 chopps /* 608 1.2 jtc * Was there some error? 609 1.2 jtc * Some of them are senseless because they are masked off. 610 1.2 jtc * XXX 611 1.1 chopps */ 612 1.7 is if (rstat & R_INT_OVR_FLO) { 613 1.1 chopps #ifdef QN_DEBUG 614 1.2 jtc log(LOG_INFO, "Overflow\n"); 615 1.1 chopps #endif 616 1.49 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 617 1.2 jtc } 618 1.7 is if (rstat & R_INT_CRC_ERR) { 619 1.1 chopps #ifdef QN_DEBUG 620 1.2 jtc log(LOG_INFO, "CRC Error\n"); 621 1.1 chopps #endif 622 1.49 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 623 1.2 jtc } 624 1.7 is if (rstat & R_INT_ALG_ERR) { 625 1.1 chopps #ifdef QN_DEBUG 626 1.2 jtc log(LOG_INFO, "Alignment error\n"); 627 1.1 chopps #endif 628 1.49 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 629 1.2 jtc } 630 1.7 is if (rstat & R_INT_SRT_PKT) { 631 1.2 jtc /* Short packet (these may occur and are 632 1.2 jtc * no reason to worry about - or maybe 633 1.2 jtc * they are?). 634 1.2 jtc */ 635 1.1 chopps #ifdef QN_DEBUG 636 1.2 jtc log(LOG_INFO, "Short packet\n"); 637 1.1 chopps #endif 638 1.49 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 639 1.2 jtc } 640 1.2 jtc if (rstat & 0x4040) { 641 1.1 chopps #ifdef QN_DEBUG 642 1.2 jtc log(LOG_INFO, "Bus read error\n"); 643 1.1 chopps #endif 644 1.49 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 645 1.2 jtc qnreset(sc); 646 1.2 jtc } 647 1.1 chopps 648 1.2 jtc /* 649 1.2 jtc * Read at most MAX_PACKETS packets per interrupt 650 1.2 jtc */ 651 1.2 jtc for (i = 0; i < MAX_PACKETS; i++) { 652 1.2 jtc if (*sc->nic_r_mode & RM_BUF_EMP) 653 1.2 jtc /* Buffer empty. */ 654 1.2 jtc break; 655 1.1 chopps 656 1.2 jtc /* 657 1.2 jtc * Read the first word: upper byte contains useful 658 1.2 jtc * information. 659 1.2 jtc */ 660 1.2 jtc status = *sc->nic_fifo; 661 1.2 jtc if ((status & 0x7000) != 0x2000) { 662 1.2 jtc log(LOG_INFO, "qn: ERROR: status=%04x\n", status); 663 1.2 jtc continue; 664 1.2 jtc } 665 1.2 jtc 666 1.2 jtc /* 667 1.2 jtc * Read packet length (byte-swapped). 668 1.2 jtc * CRC is stripped off by the NIC. 669 1.2 jtc */ 670 1.2 jtc len = *sc->nic_fifo; 671 1.2 jtc len = ((len << 8) & 0xff00) | ((len >> 8) & 0x00ff); 672 1.1 chopps 673 1.7 is #ifdef QN_CHECKS 674 1.17 thorpej if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN) || 675 1.17 thorpej len < ETHER_HDR_LEN) { 676 1.2 jtc log(LOG_WARNING, 677 1.2 jtc "%s: received a %s packet? (%u bytes)\n", 678 1.39 chs device_xname(sc->sc_dev), 679 1.17 thorpej len < ETHER_HDR_LEN ? "partial" : "big", len); 680 1.49 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 681 1.2 jtc continue; 682 1.1 chopps } 683 1.2 jtc #endif 684 1.7 is #ifdef QN_CHECKS 685 1.17 thorpej if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) 686 1.2 jtc log(LOG_WARNING, 687 1.2 jtc "%s: received a short packet? (%u bytes)\n", 688 1.39 chs device_xname(sc->sc_dev), len); 689 1.21 aymeric #endif 690 1.2 jtc 691 1.2 jtc /* Read the packet. */ 692 1.2 jtc qn_get_packet(sc, len); 693 1.1 chopps } 694 1.1 chopps 695 1.2 jtc #ifdef QN_DEBUG 696 1.2 jtc /* This print just to see whether MAX_PACKETS is large enough. */ 697 1.2 jtc if (i == MAX_PACKETS) 698 1.2 jtc log(LOG_INFO, "used all the %d loops\n", MAX_PACKETS); 699 1.2 jtc #endif 700 1.1 chopps } 701 1.1 chopps 702 1.1 chopps /* 703 1.1 chopps * Our interrupt routine 704 1.1 chopps */ 705 1.1 chopps int 706 1.21 aymeric qnintr(void *arg) 707 1.1 chopps { 708 1.5 veego struct qn_softc *sc = arg; 709 1.2 jtc u_short tint, rint, tintmask; 710 1.2 jtc char return_tintmask = 0; 711 1.1 chopps 712 1.1 chopps /* 713 1.1 chopps * If the driver has not been initialized, just return immediately. 714 1.1 chopps * This also happens if there is no QuickNet board present. 715 1.1 chopps */ 716 1.1 chopps if (sc->sc_base == NULL) 717 1.1 chopps return (0); 718 1.1 chopps 719 1.1 chopps /* Get interrupt statuses and masks. */ 720 1.2 jtc rint = (*sc->nic_r_status) & NIC_R_MASK; 721 1.1 chopps tintmask = *sc->nic_t_mask; 722 1.2 jtc tint = (*sc->nic_t_status) & tintmask; 723 1.2 jtc if (tint == 0 && rint == 0) 724 1.1 chopps return (0); 725 1.1 chopps 726 1.2 jtc /* Disable interrupts so that we won't miss anything. */ 727 1.1 chopps *sc->nic_r_mask = CLEAR_R_MASK; 728 1.2 jtc *sc->nic_t_mask = CLEAR_T_MASK; 729 1.1 chopps 730 1.1 chopps /* 731 1.1 chopps * Handle transmitter interrupts. Some of them are not asked for 732 1.1 chopps * but do happen, anyway. 733 1.1 chopps */ 734 1.2 jtc 735 1.2 jtc if (tint != 0) { 736 1.2 jtc /* Clear transmit interrupt status. */ 737 1.1 chopps *sc->nic_t_status = CLEAR_T_ERR; 738 1.2 jtc 739 1.1 chopps if (sc->transmit_pending && (tint & T_TMT_OK)) { 740 1.52 thorpej sc->transmit_pending = false; 741 1.1 chopps /* 742 1.1 chopps * Update total number of successfully 743 1.1 chopps * transmitted packets. 744 1.1 chopps */ 745 1.49 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_opackets); 746 1.1 chopps } 747 1.1 chopps 748 1.1 chopps if (tint & T_SIXTEEN_COL) { 749 1.1 chopps /* 750 1.1 chopps * 16 collision (i.e., packet lost). 751 1.1 chopps */ 752 1.1 chopps log(LOG_INFO, "qn: 16 collision - packet lost\n"); 753 1.2 jtc #ifdef QN_DEBUG1 754 1.2 jtc qn_dump(sc); 755 1.2 jtc #endif 756 1.49 thorpej if_statadd2(&sc->sc_ethercom.ec_if, 757 1.49 thorpej if_oerrors, 1, if_collisions, 16); 758 1.52 thorpej sc->transmit_pending = false; 759 1.1 chopps } 760 1.1 chopps 761 1.1 chopps if (sc->transmit_pending) { 762 1.1 chopps log(LOG_INFO, "qn:still pending...\n"); 763 1.2 jtc 764 1.2 jtc /* Must return transmission interrupt mask. */ 765 1.2 jtc return_tintmask = 1; 766 1.1 chopps } else { 767 1.1 chopps /* Clear watchdog timer. */ 768 1.11 is sc->sc_ethercom.ec_if.if_timer = 0; 769 1.1 chopps } 770 1.2 jtc } else 771 1.2 jtc return_tintmask = 1; 772 1.1 chopps 773 1.1 chopps /* 774 1.1 chopps * Handle receiver interrupts. 775 1.1 chopps */ 776 1.2 jtc if (rint != 0) 777 1.2 jtc qn_rint(sc, rint); 778 1.1 chopps 779 1.53 thorpej if (!sc->transmit_pending) 780 1.44 nonaka if_schedule_deferred_start(&sc->sc_ethercom.ec_if); 781 1.2 jtc else if (return_tintmask == 1) 782 1.2 jtc *sc->nic_t_mask = tintmask; 783 1.2 jtc 784 1.2 jtc /* Set receive interrupt mask back. */ 785 1.2 jtc *sc->nic_r_mask = NIC_R_MASK; 786 1.1 chopps 787 1.1 chopps return (1); 788 1.1 chopps } 789 1.1 chopps 790 1.1 chopps /* 791 1.1 chopps * Process an ioctl request. This code needs some work - it looks pretty ugly. 792 1.1 chopps * I somehow think that this is quite a common excuse... ;-) 793 1.1 chopps */ 794 1.1 chopps int 795 1.30 he qnioctl(register struct ifnet *ifp, u_long cmd, void *data) 796 1.1 chopps { 797 1.6 thorpej struct qn_softc *sc = ifp->if_softc; 798 1.1 chopps register struct ifaddr *ifa = (struct ifaddr *)data; 799 1.1 chopps #if 0 800 1.1 chopps struct ifreg *ifr = (struct ifreg *)data; 801 1.1 chopps #endif 802 1.1 chopps int s, error = 0; 803 1.1 chopps 804 1.3 mycroft s = splnet(); 805 1.1 chopps 806 1.30 he switch (cmd) { 807 1.1 chopps 808 1.32 dyoung case SIOCINITIFADDR: 809 1.1 chopps ifp->if_flags |= IFF_UP; 810 1.1 chopps 811 1.1 chopps switch (ifa->ifa_addr->sa_family) { 812 1.1 chopps #ifdef INET 813 1.1 chopps case AF_INET: 814 1.2 jtc qnstop(sc); 815 1.1 chopps qninit(sc); 816 1.11 is arp_ifinit(ifp, ifa); 817 1.1 chopps break; 818 1.1 chopps #endif 819 1.1 chopps default: 820 1.1 chopps log(LOG_INFO, "qn:sa_family:default (not tested)\n"); 821 1.2 jtc qnstop(sc); 822 1.1 chopps qninit(sc); 823 1.1 chopps break; 824 1.1 chopps } 825 1.1 chopps break; 826 1.1 chopps 827 1.1 chopps case SIOCSIFFLAGS: 828 1.32 dyoung if ((error = ifioctl_common(ifp, cmd, data)) != 0) 829 1.32 dyoung break; 830 1.32 dyoung /* XXX see the comment in ed_ioctl() about code re-use */ 831 1.1 chopps if ((ifp->if_flags & IFF_UP) == 0 && 832 1.1 chopps (ifp->if_flags & IFF_RUNNING) != 0) { 833 1.1 chopps /* 834 1.1 chopps * If interface is marked down and it is running, then 835 1.1 chopps * stop it. 836 1.1 chopps */ 837 1.2 jtc #ifdef QN_DEBUG1 838 1.2 jtc qn_dump(sc); 839 1.2 jtc #endif 840 1.1 chopps qnstop(sc); 841 1.1 chopps ifp->if_flags &= ~IFF_RUNNING; 842 1.1 chopps } else if ((ifp->if_flags & IFF_UP) != 0 && 843 1.2 jtc (ifp->if_flags & IFF_RUNNING) == 0) { 844 1.1 chopps /* 845 1.1 chopps * If interface is marked up and it is stopped, then 846 1.1 chopps * start it. 847 1.1 chopps */ 848 1.1 chopps qninit(sc); 849 1.2 jtc } else { 850 1.1 chopps /* 851 1.1 chopps * Something else... we won't do anything so we won't 852 1.1 chopps * break anything (hope so). 853 1.1 chopps */ 854 1.2 jtc #ifdef QN_DEBUG1 855 1.2 jtc log(LOG_INFO, "Else branch...\n"); 856 1.2 jtc #endif 857 1.1 chopps } 858 1.1 chopps break; 859 1.1 chopps 860 1.1 chopps case SIOCADDMULTI: 861 1.1 chopps case SIOCDELMULTI: 862 1.1 chopps log(LOG_INFO, "qnioctl: multicast not done yet\n"); 863 1.1 chopps #if 0 864 1.29 dyoung if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 865 1.1 chopps /* 866 1.1 chopps * Multicast list has changed; set the hardware filter 867 1.1 chopps * accordingly. 868 1.1 chopps */ 869 1.1 chopps log(LOG_INFO, "qnioctl: multicast not done yet\n"); 870 1.1 chopps error = 0; 871 1.1 chopps } 872 1.1 chopps #else 873 1.1 chopps error = EINVAL; 874 1.1 chopps #endif 875 1.1 chopps break; 876 1.1 chopps 877 1.1 chopps default: 878 1.32 dyoung error = ether_ioctl(ifp, cmd, data); 879 1.1 chopps } 880 1.1 chopps 881 1.2 jtc splx(s); 882 1.1 chopps return (error); 883 1.1 chopps } 884 1.2 jtc 885 1.2 jtc /* 886 1.2 jtc * Dump some register information. 887 1.2 jtc */ 888 1.2 jtc #ifdef QN_DEBUG1 889 1.2 jtc static void 890 1.21 aymeric qn_dump(struct qn_softc *sc) 891 1.2 jtc { 892 1.2 jtc 893 1.2 jtc log(LOG_INFO, "t_status : %04x\n", *sc->nic_t_status); 894 1.2 jtc log(LOG_INFO, "t_mask : %04x\n", *sc->nic_t_mask); 895 1.2 jtc log(LOG_INFO, "t_mode : %04x\n", *sc->nic_t_mode); 896 1.2 jtc log(LOG_INFO, "r_status : %04x\n", *sc->nic_r_status); 897 1.2 jtc log(LOG_INFO, "r_mask : %04x\n", *sc->nic_r_mask); 898 1.2 jtc log(LOG_INFO, "r_mode : %04x\n", *sc->nic_r_mode); 899 1.52 thorpej log(LOG_INFO, "pending : %s\n", sc->transmit_pending ? "T" : "F"); 900 1.11 is log(LOG_INFO, "if_flags : %04x\n", sc->sc_ethercom.ec_if.if_flags); 901 1.2 jtc } 902 1.2 jtc #endif 903 1.1 chopps 904 1.1 chopps #endif /* NQN > 0 */ 905