smc91cxx.c revision 1.25 1 /* $NetBSD: smc91cxx.c,v 1.25 2000/05/29 17:37:14 jhawk Exp $ */
2
3 /*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1996 Gardner Buchanan <gbuchanan (at) shl.com>
42 * All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by Gardner Buchanan.
55 * 4. The name of Gardner Buchanan may not be used to endorse or promote
56 * products derived from this software without specific prior written
57 * permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 *
70 * from FreeBSD Id: if_sn.c,v 1.4 1996/03/18 15:47:16 gardner Exp
71 */
72
73 /*
74 * Core driver for the SMC 91Cxx family of Ethernet chips.
75 *
76 * Memory allocation interrupt logic is drived from an SMC 91C90 driver
77 * written for NetBSD/amiga by Michael Hitch.
78 */
79
80 #include "opt_inet.h"
81 #include "opt_ccitt.h"
82 #include "opt_llc.h"
83 #include "opt_ns.h"
84 #include "bpfilter.h"
85 #include "rnd.h"
86
87 #include <sys/param.h>
88 #include <sys/systm.h>
89 #include <sys/mbuf.h>
90 #include <sys/syslog.h>
91 #include <sys/socket.h>
92 #include <sys/device.h>
93 #include <sys/malloc.h>
94 #include <sys/ioctl.h>
95 #include <sys/errno.h>
96 #if NRND > 0
97 #include <sys/rnd.h>
98 #endif
99
100 #include <machine/bus.h>
101 #include <machine/intr.h>
102
103 #include <net/if.h>
104 #include <net/if_dl.h>
105 #include <net/if_ether.h>
106 #include <net/if_media.h>
107
108 #ifdef INET
109 #include <netinet/in.h>
110 #include <netinet/if_inarp.h>
111 #include <netinet/in_systm.h>
112 #include <netinet/in_var.h>
113 #include <netinet/ip.h>
114 #endif
115
116 #ifdef NS
117 #include <netns/ns.h>
118 #include <netns/ns_if.h>
119 #endif
120
121 #if defined(CCITT) && defined(LLC)
122 #include <sys/socketvar.h>
123 #include <netccitt/x25.h>
124 #include <netccitt/pk.h>
125 #include <netccitt/pk_var.h>
126 #include <netccitt/pk_extern.h>
127 #endif
128
129 #if NBPFILTER > 0
130 #include <net/bpf.h>
131 #include <net/bpfdesc.h>
132 #endif
133
134 #include <dev/ic/smc91cxxreg.h>
135 #include <dev/ic/smc91cxxvar.h>
136
137 /* XXX Hardware padding doesn't work yet(?) */
138 #define SMC91CXX_SW_PAD
139
140 const char *smc91cxx_idstrs[] = {
141 NULL, /* 0 */
142 NULL, /* 1 */
143 NULL, /* 2 */
144 "SMC91C90/91C92", /* 3 */
145 "SMC91C94", /* 4 */
146 "SMC91C95", /* 5 */
147 NULL, /* 6 */
148 "SMC91C100", /* 7 */
149 NULL, /* 8 */
150 NULL, /* 9 */
151 NULL, /* 10 */
152 NULL, /* 11 */
153 NULL, /* 12 */
154 NULL, /* 13 */
155 NULL, /* 14 */
156 NULL, /* 15 */
157 };
158
159 /* Supported media types. */
160 const int smc91cxx_media[] = {
161 IFM_ETHER|IFM_10_T,
162 IFM_ETHER|IFM_10_5,
163 };
164 #define NSMC91CxxMEDIA (sizeof(smc91cxx_media) / sizeof(smc91cxx_media[0]))
165
166 int smc91cxx_mediachange __P((struct ifnet *));
167 void smc91cxx_mediastatus __P((struct ifnet *, struct ifmediareq *));
168
169 int smc91cxx_set_media __P((struct smc91cxx_softc *, int));
170
171 void smc91cxx_init __P((struct smc91cxx_softc *));
172 void smc91cxx_read __P((struct smc91cxx_softc *));
173 void smc91cxx_reset __P((struct smc91cxx_softc *));
174 void smc91cxx_start __P((struct ifnet *));
175 void smc91cxx_resume __P((struct smc91cxx_softc *));
176 void smc91cxx_stop __P((struct smc91cxx_softc *));
177 void smc91cxx_watchdog __P((struct ifnet *));
178 int smc91cxx_ioctl __P((struct ifnet *, u_long, caddr_t));
179
180 static __inline int ether_cmp __P((void *, void *));
181 static __inline int
182 ether_cmp(va, vb)
183 void *va, *vb;
184 {
185 u_int8_t *a = va;
186 u_int8_t *b = vb;
187
188 return ((a[5] != b[5]) || (a[4] != b[4]) || (a[3] != b[3]) ||
189 (a[2] != b[2]) || (a[1] != b[1]) || (a[0] != b[0]));
190 }
191
192 void
193 smc91cxx_attach(sc, myea)
194 struct smc91cxx_softc *sc;
195 u_int8_t *myea;
196 {
197 struct ifnet *ifp = &sc->sc_ec.ec_if;
198 bus_space_tag_t bst = sc->sc_bst;
199 bus_space_handle_t bsh = sc->sc_bsh;
200 const char *idstr;
201 u_int16_t tmp;
202 u_int8_t enaddr[ETHER_ADDR_LEN];
203 int i, aui;
204
205 /* Make sure the chip is stopped. */
206 smc91cxx_stop(sc);
207
208 SMC_SELECT_BANK(sc, 3);
209 tmp = bus_space_read_2(bst, bsh, REVISION_REG_W);
210 /* check magic number */
211 if ((tmp & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
212 idstr = NULL;
213 printf("%s: invalid BSR 0x%04x\n", sc->sc_dev.dv_xname, tmp);
214 } else
215 idstr = smc91cxx_idstrs[RR_ID(tmp)];
216 printf("%s: ", sc->sc_dev.dv_xname);
217 if (idstr != NULL)
218 printf("%s, ", idstr);
219 else
220 printf("unknown chip id %d, ", RR_ID(tmp));
221 printf("revision %d\n", RR_REV(tmp));
222
223 /* Read the station address from the chip. */
224 SMC_SELECT_BANK(sc, 1);
225 if (myea == NULL) {
226 myea = enaddr;
227 for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
228 tmp = bus_space_read_2(bst, bsh, IAR_ADDR0_REG_W + i);
229 myea[i + 1] = (tmp >> 8) & 0xff;
230 myea[i] = tmp & 0xff;
231 }
232 }
233 printf("%s: MAC address %s, ", sc->sc_dev.dv_xname,
234 ether_sprintf(myea));
235
236 /* ..and default media. */
237 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
238 printf("default media %s\n", (aui = (tmp & CR_AUI_SELECT)) ?
239 "AUI" : "UTP");
240
241 /* Initialize the ifnet structure. */
242 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
243 ifp->if_softc = sc;
244 ifp->if_start = smc91cxx_start;
245 ifp->if_ioctl = smc91cxx_ioctl;
246 ifp->if_watchdog = smc91cxx_watchdog;
247 ifp->if_flags =
248 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
249
250 /* Attach the interface. */
251 if_attach(ifp);
252 ether_ifattach(ifp, myea);
253
254 /* Initialize the media structures. */
255 ifmedia_init(&sc->sc_media, 0, smc91cxx_mediachange,
256 smc91cxx_mediastatus);
257 for (i = 0; i < NSMC91CxxMEDIA; i++)
258 ifmedia_add(&sc->sc_media, smc91cxx_media[i], 0, NULL);
259 ifmedia_set(&sc->sc_media, IFM_ETHER | (aui ? IFM_10_5 : IFM_10_T));
260
261 #if NBPFILTER > 0
262 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
263 #endif
264
265 #if NRND > 0
266 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
267 RND_TYPE_NET, 0);
268 #endif
269
270 /* The attach is successful. */
271 sc->sc_flags |= SMC_FLAGS_ATTACHED;
272 }
273
274 /*
275 * Change media according to request.
276 */
277 int
278 smc91cxx_mediachange(ifp)
279 struct ifnet *ifp;
280 {
281 struct smc91cxx_softc *sc = ifp->if_softc;
282
283 return (smc91cxx_set_media(sc, sc->sc_media.ifm_media));
284 }
285
286 int
287 smc91cxx_set_media(sc, media)
288 struct smc91cxx_softc *sc;
289 int media;
290 {
291 bus_space_tag_t bst = sc->sc_bst;
292 bus_space_handle_t bsh = sc->sc_bsh;
293 u_int16_t tmp;
294
295 /*
296 * If the interface is not currently powered on, just return.
297 * When it is enabled later, smc91cxx_init() will properly set
298 * up the media for us.
299 */
300 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0)
301 return (0);
302
303 if (IFM_TYPE(media) != IFM_ETHER)
304 return (EINVAL);
305
306 switch (IFM_SUBTYPE(media)) {
307 case IFM_10_T:
308 case IFM_10_5:
309 SMC_SELECT_BANK(sc, 1);
310 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
311 if (IFM_SUBTYPE(media) == IFM_10_5)
312 tmp |= CR_AUI_SELECT;
313 else
314 tmp &= ~CR_AUI_SELECT;
315 bus_space_write_2(bst, bsh, CONFIG_REG_W, tmp);
316 delay(20000); /* XXX is this needed? */
317 break;
318
319 default:
320 return (EINVAL);
321 }
322
323 return (0);
324 }
325
326 /*
327 * Notify the world which media we're using.
328 */
329 void
330 smc91cxx_mediastatus(ifp, ifmr)
331 struct ifnet *ifp;
332 struct ifmediareq *ifmr;
333 {
334 struct smc91cxx_softc *sc = ifp->if_softc;
335 bus_space_tag_t bst = sc->sc_bst;
336 bus_space_handle_t bsh = sc->sc_bsh;
337 u_int16_t tmp;
338
339 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0) {
340 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
341 ifmr->ifm_status = 0;
342 return;
343 }
344
345 SMC_SELECT_BANK(sc, 1);
346 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
347 ifmr->ifm_active =
348 IFM_ETHER | ((tmp & CR_AUI_SELECT) ? IFM_10_5 : IFM_10_T);
349 }
350
351 /*
352 * Reset and initialize the chip.
353 */
354 void
355 smc91cxx_init(sc)
356 struct smc91cxx_softc *sc;
357 {
358 struct ifnet *ifp = &sc->sc_ec.ec_if;
359 bus_space_tag_t bst = sc->sc_bst;
360 bus_space_handle_t bsh = sc->sc_bsh;
361 u_int16_t tmp;
362 u_int8_t *enaddr;
363 int s, i;
364
365 s = splnet();
366
367 /*
368 * This resets the registersmostly to defaults, but doesn't
369 * affect the EEPROM. After the reset cycle, we pause briefly
370 * for the chip to recover.
371 *
372 * XXX how long are we really supposed to delay? --thorpej
373 */
374 SMC_SELECT_BANK(sc, 0);
375 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET);
376 delay(100);
377 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
378 delay(200);
379
380 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
381
382 /* Set the Ethernet address. */
383 SMC_SELECT_BANK(sc, 1);
384 enaddr = (u_int8_t *)LLADDR(ifp->if_sadl);
385 for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
386 tmp = enaddr[i + 1] << 8 | enaddr[i];
387 bus_space_write_2(bst, bsh, IAR_ADDR0_REG_W + i, tmp);
388 }
389
390 /*
391 * Set the control register to automatically release successfully
392 * transmitted packets (making the best use of our limited memory)
393 * and enable the EPH interrupt on certain TX errors.
394 */
395 bus_space_write_2(bst, bsh, CONTROL_REG_W, (CTR_AUTO_RELEASE |
396 CTR_TE_ENABLE | CTR_CR_ENABLE | CTR_LE_ENABLE));
397
398 /*
399 * Reset the MMU and wait for it to be un-busy.
400 */
401 SMC_SELECT_BANK(sc, 2);
402 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET);
403 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
404 /* XXX bound this loop! */ ;
405
406 /*
407 * Disable all interrupts.
408 */
409 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
410
411 /*
412 * Set current media.
413 */
414 smc91cxx_set_media(sc, sc->sc_media.ifm_cur->ifm_media);
415
416 /*
417 * Set the receive filter. We want receive enable and auto
418 * strip of CRC from received packet. If we are in promisc. mode,
419 * then set that bit as well.
420 *
421 * XXX Initialize multicast filter. For now, we just accept
422 * XXX all multicast.
423 */
424 SMC_SELECT_BANK(sc, 0);
425
426 tmp = RCR_ENABLE | RCR_STRIP_CRC | RCR_ALMUL;
427 if (ifp->if_flags & IFF_PROMISC)
428 tmp |= RCR_PROMISC;
429
430 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, tmp);
431
432 /*
433 * Set transmitter control to "enabled".
434 */
435 tmp = TCR_ENABLE;
436
437 #ifndef SMC91CXX_SW_PAD
438 /*
439 * Enable hardware padding of transmitted packets.
440 * XXX doesn't work?
441 */
442 tmp |= TCR_PAD_ENABLE;
443 #endif
444
445 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, tmp);
446
447 /*
448 * Now, enable interrupts.
449 */
450 SMC_SELECT_BANK(sc, 2);
451
452 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
453 IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
454
455 /* Interface is now running, with no output active. */
456 ifp->if_flags |= IFF_RUNNING;
457 ifp->if_flags &= ~IFF_OACTIVE;
458
459 /*
460 * Attempt to start any pending transmission.
461 */
462 smc91cxx_start(ifp);
463
464 splx(s);
465 }
466
467 /*
468 * Start output on an interface.
469 * Must be called at splnet or interrupt level.
470 */
471 void
472 smc91cxx_start(ifp)
473 struct ifnet *ifp;
474 {
475 struct smc91cxx_softc *sc = ifp->if_softc;
476 bus_space_tag_t bst = sc->sc_bst;
477 bus_space_handle_t bsh = sc->sc_bsh;
478 u_int len;
479 struct mbuf *m, *top;
480 u_int16_t length, npages;
481 u_int8_t packetno;
482 int timo, pad;
483
484 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
485 return;
486
487 again:
488 /*
489 * Peek at the next packet.
490 */
491 if ((m = ifp->if_snd.ifq_head) == NULL)
492 return;
493
494 /*
495 * Compute the frame length and set pad to give an overall even
496 * number of bytes. Below, we assume that the packet length
497 * is even.
498 */
499 for (len = 0, top = m; m != NULL; m = m->m_next)
500 len += m->m_len;
501 pad = (len & 1);
502
503 /*
504 * We drop packets that are too large. Perhaps we should
505 * truncate them instead?
506 */
507 if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
508 printf("%s: large packet discarded\n", sc->sc_dev.dv_xname);
509 ifp->if_oerrors++;
510 IF_DEQUEUE(&ifp->if_snd, m);
511 m_freem(m);
512 goto readcheck;
513 }
514
515 #ifdef SMC91CXX_SW_PAD
516 /*
517 * Not using hardware padding; pad to ETHER_MIN_LEN.
518 */
519 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN))
520 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
521 #endif
522
523 length = pad + len;
524
525 /*
526 * The MMU has a 256 byte page size. The MMU expects us to
527 * ask for "npages - 1". We include space for the status word,
528 * byte count, and control bytes in the allocation request.
529 */
530 npages = (length + 6) >> 8;
531
532 /*
533 * Now allocate the memory.
534 */
535 SMC_SELECT_BANK(sc, 2);
536 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages);
537
538 timo = MEMORY_WAIT_TIME;
539 do {
540 if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
541 break;
542 delay(1);
543 } while (--timo);
544
545 packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
546
547 if (packetno & ARR_FAILED || timo == 0) {
548 /*
549 * No transmit memory is available. Record the number
550 * of requestd pages and enable the allocation completion
551 * interrupt. Set up the watchdog timer in case we miss
552 * the interrupt. Mark the interface as active so that
553 * no one else attempts to transmit while we're allocating
554 * memory.
555 */
556 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
557 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT);
558
559 ifp->if_timer = 5;
560 ifp->if_flags |= IFF_OACTIVE;
561
562 return;
563 }
564
565 /*
566 * We have a packet number - set the data window.
567 */
568 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
569
570 /*
571 * Point to the beginning of the packet.
572 */
573 bus_space_write_2(bst, bsh, POINTER_REG_W, PTR_AUTOINC /* | 0x0000 */);
574
575 /*
576 * Send the packet length (+6 for stats, length, and control bytes)
577 * and the status word (set to zeros).
578 */
579 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
580 bus_space_write_1(bst, bsh, DATA_REG_B, (length + 6) & 0xff);
581 bus_space_write_1(bst, bsh, DATA_REG_B, ((length + 6) >> 8) & 0xff);
582
583 /*
584 * Get the packet from the kernel. This will include the Ethernet
585 * frame header, MAC address, etc.
586 */
587 IF_DEQUEUE(&ifp->if_snd, m);
588
589 /*
590 * Push the packet out to the card.
591 */
592 for (top = m; m != NULL; m = m->m_next) {
593 /* Words... */
594 bus_space_write_multi_2(bst, bsh, DATA_REG_W,
595 mtod(m, u_int16_t *), m->m_len >> 1);
596
597 /* ...and the remaining byte, if any. */
598 if (m->m_len & 1)
599 bus_space_write_1(bst, bsh, DATA_REG_B,
600 *(u_int8_t *)(mtod(m, u_int8_t *) + (m->m_len - 1)));
601 }
602
603 #ifdef SMC91CXX_SW_PAD
604 /*
605 * Push out padding.
606 */
607 while (pad > 1) {
608 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
609 pad -= 2;
610 }
611 if (pad)
612 bus_space_write_1(bst, bsh, DATA_REG_B, 0);
613 #endif
614
615 /*
616 * Push out control byte and unused packet byte. The control byte
617 * is 0, meaning the packet is even lengthed and no special
618 * CRC handling is necessary.
619 */
620 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
621
622 /*
623 * Enable transmit interrupts and let the chip go. Set a watchdog
624 * in case we miss the interrupt.
625 */
626 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
627 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) |
628 IM_TX_INT | IM_TX_EMPTY_INT);
629
630 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE);
631
632 ifp->if_timer = 5;
633
634 #if NBPFILTER > 0
635 /* Hand off a copy to the bpf. */
636 if (ifp->if_bpf)
637 bpf_mtap(ifp->if_bpf, top);
638 #endif
639
640 ifp->if_opackets++;
641 m_freem(top);
642
643 readcheck:
644 /*
645 * Check for incoming pcakets. We don't want to overflow the small
646 * RX FIFO. If nothing has arrived, attempt to queue another
647 * transmit packet.
648 */
649 if (bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & FIFO_REMPTY)
650 goto again;
651 }
652
653 /*
654 * Interrupt service routine.
655 */
656 int
657 smc91cxx_intr(arg)
658 void *arg;
659 {
660 struct smc91cxx_softc *sc = arg;
661 struct ifnet *ifp = &sc->sc_ec.ec_if;
662 bus_space_tag_t bst = sc->sc_bst;
663 bus_space_handle_t bsh = sc->sc_bsh;
664 u_int8_t mask, interrupts, status;
665 u_int16_t packetno, tx_status, card_stats;
666
667 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0 ||
668 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
669 return (0);
670
671 SMC_SELECT_BANK(sc, 2);
672
673 /*
674 * Obtain the current interrupt mask.
675 */
676 mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
677
678 /*
679 * Get the set of interrupt which occurred and eliminate any
680 * which are not enabled.
681 */
682 interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
683 status = interrupts & mask;
684
685 /* Ours? */
686 if (status == 0)
687 return (0);
688
689 /*
690 * It's ours; disable all interrupts while we process them.
691 */
692 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
693
694 /*
695 * Receive overrun interrupts.
696 */
697 if (status & IM_RX_OVRN_INT) {
698 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT);
699 ifp->if_ierrors++;
700 }
701
702 /*
703 * Receive interrupts.
704 */
705 if (status & IM_RCV_INT) {
706 #if 1 /* DIAGNOSTIC */
707 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
708 if (packetno & FIFO_REMPTY)
709 printf("%s: receive interrupt on empty fifo\n",
710 sc->sc_dev.dv_xname);
711 else
712 #endif
713 smc91cxx_read(sc);
714 }
715
716 /*
717 * Memory allocation interrupts.
718 */
719 if (status & IM_ALLOC_INT) {
720 /* Disable this interrupt. */
721 mask &= ~IM_ALLOC_INT;
722
723 /*
724 * Release the just-allocated memory. We will reallocate
725 * it through the normal start logic.
726 */
727 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
728 /* XXX bound this loop! */ ;
729 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
730
731 ifp->if_flags &= ~IFF_OACTIVE;
732 ifp->if_timer = 0;
733 }
734
735 /*
736 * Transmit complete interrupt. Handle transmission error messages.
737 * This will only be called on error condition because of AUTO RELEASE
738 * mode.
739 */
740 if (status & IM_TX_INT) {
741 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT);
742
743 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) &
744 FIFO_TX_MASK;
745
746 /*
747 * Select this as the packet to read from.
748 */
749 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
750
751 /*
752 * Position the pointer to the beginning of the packet.
753 */
754 bus_space_write_2(bst, bsh, POINTER_REG_W,
755 PTR_AUTOINC | PTR_READ /* | 0x0000 */);
756
757 /*
758 * Fetch the TX status word. This will be a copy of
759 * the EPH_STATUS_REG_W at the time of the transmission
760 * failure.
761 */
762 tx_status = bus_space_read_2(bst, bsh, DATA_REG_W);
763
764 if (tx_status & EPHSR_TX_SUC)
765 printf("%s: successful packet caused TX interrupt?!\n",
766 sc->sc_dev.dv_xname);
767 else
768 ifp->if_oerrors++;
769
770 if (tx_status & EPHSR_LATCOL)
771 ifp->if_collisions++;
772
773 /*
774 * Some of these errors disable the transmitter; reenable it.
775 */
776 SMC_SELECT_BANK(sc, 0);
777 #ifdef SMC91CXX_SW_PAD
778 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, TCR_ENABLE);
779 #else
780 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W,
781 TCR_ENABLE | TCR_PAD_ENABLE);
782 #endif
783
784 /*
785 * Kill the failed packet and wait for the MMU to unbusy.
786 */
787 SMC_SELECT_BANK(sc, 2);
788 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
789 /* XXX bound this loop! */ ;
790 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
791
792 ifp->if_timer = 0;
793 }
794
795 /*
796 * Transmit underrun interrupts. We use this opportunity to
797 * update transmit statistics from the card.
798 */
799 if (status & IM_TX_EMPTY_INT) {
800 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
801
802 /* Disable this interrupt. */
803 mask &= ~IM_TX_EMPTY_INT;
804
805 SMC_SELECT_BANK(sc, 0);
806 card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W);
807
808 /* Single collisions. */
809 ifp->if_collisions += card_stats & ECR_COLN_MASK;
810
811 /* Multiple collisions. */
812 ifp->if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4;
813
814 SMC_SELECT_BANK(sc, 2);
815
816 ifp->if_timer = 0;
817 }
818
819 /*
820 * Other errors. Reset the interface.
821 */
822 if (status & IM_EPH_INT) {
823 smc91cxx_stop(sc);
824 smc91cxx_init(sc);
825 }
826
827 /*
828 * Attempt to queue more packets for transmission.
829 */
830 smc91cxx_start(ifp);
831
832 /*
833 * Reenable the interrupts we wish to receive now that processing
834 * is complete.
835 */
836 mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
837 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
838
839 #if NRND > 0
840 if (status)
841 rnd_add_uint32(&sc->rnd_source, status);
842 #endif
843
844 return (1);
845 }
846
847 /*
848 * Read a packet from the card and pass it up to the kernel.
849 * NOTE! WE EXPECT TO BE IN REGISTER WINDOW 2!
850 */
851 void
852 smc91cxx_read(sc)
853 struct smc91cxx_softc *sc;
854 {
855 struct ifnet *ifp = &sc->sc_ec.ec_if;
856 bus_space_tag_t bst = sc->sc_bst;
857 bus_space_handle_t bsh = sc->sc_bsh;
858 struct ether_header *eh;
859 struct mbuf *m;
860 u_int16_t status, packetno, packetlen;
861 u_int8_t *data;
862
863 again:
864 /*
865 * Set data pointer to the beginning of the packet. Since
866 * PTR_RCV is set, the packet number will be found automatically
867 * in FIFO_PORTS_REG_W, FIFO_RX_MASK.
868 */
869 bus_space_write_2(bst, bsh, POINTER_REG_W,
870 PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */);
871
872 /*
873 * First two words are status and packet length.
874 */
875 status = bus_space_read_2(bst, bsh, DATA_REG_W);
876 packetlen = bus_space_read_2(bst, bsh, DATA_REG_W);
877
878 /*
879 * The packet length includes 3 extra words: status, length,
880 * and an extra word that includes the control byte.
881 */
882 packetlen -= 6;
883
884 /*
885 * Account for receive errors and discard.
886 */
887 if (status & RS_ERRORS) {
888 ifp->if_ierrors++;
889 goto out;
890 }
891
892 /*
893 * Adjust for odd-length packet.
894 */
895 if (status & RS_ODDFRAME)
896 packetlen++;
897
898 /*
899 * Allocate a header mbuf.
900 */
901 MGETHDR(m, M_DONTWAIT, MT_DATA);
902 if (m == NULL)
903 goto out;
904
905 m->m_pkthdr.rcvif = ifp;
906 m->m_pkthdr.len = m->m_len = packetlen;
907
908 /*
909 * Always put the packet in a cluster.
910 * XXX should chain small mbufs if less than threshold.
911 */
912 MCLGET(m, M_DONTWAIT);
913 if ((m->m_flags & M_EXT) == 0) {
914 m_freem(m);
915 ifp->if_ierrors++;
916 printf("%s: can't allocate cluster for incoming packet\n",
917 sc->sc_dev.dv_xname);
918 goto out;
919 }
920
921 /*
922 * Pull the packet off the interface.
923 */
924 eh = mtod(m, struct ether_header *);
925 data = mtod(m, u_int8_t *);
926 bus_space_read_multi_2(bst, bsh, DATA_REG_W, (u_int16_t *)data,
927 packetlen >> 1);
928 if (packetlen & 1) {
929 data += packetlen & ~1;
930 *data = bus_space_read_1(bst, bsh, DATA_REG_B);
931 }
932
933 ifp->if_ipackets++;
934
935 /*
936 * Make sure to behave as IFF_SIMPLEX in all cases.
937 * This is to cope with SMC91C92 (Megahertz XJ10BT), which
938 * loops back packets to itself on promiscuous mode.
939 * (should be ensured by chipset configuration)
940 */
941 if ((ifp->if_flags & IFF_PROMISC) != 0) {
942 /*
943 * Drop packet looped back from myself.
944 */
945 if (ether_cmp(eh->ether_shost, LLADDR(ifp->if_sadl)) == 0) {
946 m_freem(m);
947 goto out;
948 }
949 }
950
951 #if NBPFILTER > 0
952 /*
953 * Hand the packet off to bpf listeners.
954 */
955 if (ifp->if_bpf)
956 bpf_mtap(ifp->if_bpf, m);
957 #endif
958
959 /*
960 * If this is unicast and not for me, drop it.
961 */
962 if ((eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
963 ether_cmp(eh->ether_dhost, LLADDR(ifp->if_sadl)) != 0) {
964 m_freem(m);
965 goto out;
966 }
967
968 m->m_pkthdr.len = m->m_len = packetlen;
969 (*ifp->if_input)(ifp, m);
970
971 out:
972 /*
973 * Tell the card to free the memory occupied by this packet.
974 */
975 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
976 /* XXX bound this loop! */ ;
977 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RELEASE);
978
979 /*
980 * Check for another packet.
981 */
982 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
983 if (packetno & FIFO_REMPTY)
984 return;
985 goto again;
986 }
987
988 /*
989 * Process an ioctl request.
990 */
991 int
992 smc91cxx_ioctl(ifp, cmd, data)
993 struct ifnet *ifp;
994 u_long cmd;
995 caddr_t data;
996 {
997 struct smc91cxx_softc *sc = ifp->if_softc;
998 struct ifaddr *ifa = (struct ifaddr *)data;
999 struct ifreq *ifr = (struct ifreq *)data;
1000 int s, error = 0;
1001
1002 s = splnet();
1003
1004 switch (cmd) {
1005 case SIOCSIFADDR:
1006 if ((error = smc91cxx_enable(sc)) != 0)
1007 break;
1008 ifp->if_flags |= IFF_UP;
1009 switch (ifa->ifa_addr->sa_family) {
1010 #ifdef INET
1011 case AF_INET:
1012 smc91cxx_init(sc);
1013 arp_ifinit(ifp, ifa);
1014 break;
1015 #endif
1016 #ifdef NS
1017 case AF_NS:
1018 {
1019 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1020
1021 if (ns_nullhost(*ina))
1022 ina->x_host =
1023 *(union ns_host *)LLADDR(ifp->if_sadl);
1024 else {
1025 bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
1026 ETHER_ADDR_LEN);
1027 }
1028
1029 /*
1030 * Set new address. Reset, because the receiver
1031 * has to be stopped before we can set the new
1032 * MAC address.
1033 */
1034 smc91cxx_reset(sc);
1035 break;
1036 }
1037 #endif
1038 default:
1039 smc91cxx_init(sc);
1040 break;
1041 }
1042 break;
1043
1044 #if defined(CCITT) && defined(LLC)
1045 case SIOCSIFCONF_X25:
1046 if ((error = smc91cxx_enable(sc)) != 0)
1047 break;
1048 ifp->if_flags |= IFF_UP;
1049 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
1050 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
1051 if (error == 0)
1052 smc91cxx_init(sc);
1053 break;
1054 #endif
1055
1056 case SIOCSIFFLAGS:
1057 if ((ifp->if_flags & IFF_UP) == 0 &&
1058 (ifp->if_flags & IFF_RUNNING) != 0) {
1059 /*
1060 * If interface is marked down and it is running,
1061 * stop it.
1062 */
1063 smc91cxx_stop(sc);
1064 ifp->if_flags &= ~IFF_RUNNING;
1065 smc91cxx_disable(sc);
1066 } else if ((ifp->if_flags & IFF_UP) != 0 &&
1067 (ifp->if_flags & IFF_RUNNING) == 0) {
1068 /*
1069 * If interface is marked up and it is stopped,
1070 * start it.
1071 */
1072 if ((error = smc91cxx_enable(sc)) != 0)
1073 break;
1074 smc91cxx_init(sc);
1075 } else if ((ifp->if_flags & IFF_UP) != 0) {
1076 /*
1077 * Reset the interface to pick up changes in any
1078 * other flags that affect hardware registers.
1079 */
1080 smc91cxx_reset(sc);
1081 }
1082 break;
1083
1084 case SIOCADDMULTI:
1085 case SIOCDELMULTI:
1086 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0) {
1087 error = EIO;
1088 break;
1089 }
1090
1091 error = (cmd == SIOCADDMULTI) ?
1092 ether_addmulti(ifr, &sc->sc_ec) :
1093 ether_delmulti(ifr, &sc->sc_ec);
1094 if (error == ENETRESET) {
1095 /*
1096 * Multicast list has changed; set the hardware
1097 * filter accordingly.
1098 */
1099 smc91cxx_reset(sc);
1100 error = 0;
1101 }
1102 break;
1103
1104 case SIOCGIFMEDIA:
1105 case SIOCSIFMEDIA:
1106 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1107 break;
1108
1109 default:
1110 error = EINVAL;
1111 break;
1112 }
1113
1114 splx(s);
1115 return (error);
1116 }
1117
1118 /*
1119 * Reset the interface.
1120 */
1121 void
1122 smc91cxx_reset(sc)
1123 struct smc91cxx_softc *sc;
1124 {
1125 int s;
1126
1127 s = splnet();
1128 smc91cxx_stop(sc);
1129 smc91cxx_init(sc);
1130 splx(s);
1131 }
1132
1133 /*
1134 * Watchdog timer.
1135 */
1136 void
1137 smc91cxx_watchdog(ifp)
1138 struct ifnet *ifp;
1139 {
1140 struct smc91cxx_softc *sc = ifp->if_softc;
1141
1142 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1143 ifp->if_oerrors++;
1144 smc91cxx_reset(sc);
1145 }
1146
1147 /*
1148 * Stop output on the interface.
1149 */
1150 void
1151 smc91cxx_stop(sc)
1152 struct smc91cxx_softc *sc;
1153 {
1154 bus_space_tag_t bst = sc->sc_bst;
1155 bus_space_handle_t bsh = sc->sc_bsh;
1156
1157 /*
1158 * Clear interrupt mask; disable all interrupts.
1159 */
1160 SMC_SELECT_BANK(sc, 2);
1161 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
1162
1163 /*
1164 * Disable transmitter and receiver.
1165 */
1166 SMC_SELECT_BANK(sc, 0);
1167 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
1168 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
1169
1170 /*
1171 * Cancel watchdog timer.
1172 */
1173 sc->sc_ec.ec_if.if_timer = 0;
1174 }
1175
1176 /*
1177 * Enable power on the interface.
1178 */
1179 int
1180 smc91cxx_enable(sc)
1181 struct smc91cxx_softc *sc;
1182 {
1183
1184 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0 && sc->sc_enable != NULL) {
1185 if ((*sc->sc_enable)(sc) != 0) {
1186 printf("%s: device enable failed\n",
1187 sc->sc_dev.dv_xname);
1188 return (EIO);
1189 }
1190 }
1191
1192 sc->sc_flags |= SMC_FLAGS_ENABLED;
1193 return (0);
1194 }
1195
1196 /*
1197 * Disable power on the interface.
1198 */
1199 void
1200 smc91cxx_disable(sc)
1201 struct smc91cxx_softc *sc;
1202 {
1203
1204 if ((sc->sc_flags & SMC_FLAGS_ENABLED) != 0 && sc->sc_disable != NULL) {
1205 (*sc->sc_disable)(sc);
1206 sc->sc_flags &= ~SMC_FLAGS_ENABLED;
1207 }
1208 }
1209
1210 int
1211 smc91cxx_activate(self, act)
1212 struct device *self;
1213 enum devact act;
1214 {
1215 struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
1216 int rv = 0, s;
1217
1218 s = splnet();
1219 switch (act) {
1220 case DVACT_ACTIVATE:
1221 rv = EOPNOTSUPP;
1222 break;
1223
1224 case DVACT_DEACTIVATE:
1225 if_deactivate(&sc->sc_ec.ec_if);
1226 break;
1227 }
1228 splx(s);
1229 return (rv);
1230 }
1231
1232 int
1233 smc91cxx_detach(self, flags)
1234 struct device *self;
1235 int flags;
1236 {
1237 struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
1238 struct ifnet *ifp = &sc->sc_ec.ec_if;
1239
1240 /* Succeed now if there's no work to do. */
1241 if ((sc->sc_flags & SMC_FLAGS_ATTACHED) == 0)
1242 return (0);
1243
1244
1245 /* smc91cxx_disable() checks SMC_FLAGS_ENABLED */
1246 smc91cxx_disable(sc);
1247
1248 /* smc91cxx_attach() never fails */
1249
1250 /* Delete all media. */
1251 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
1252
1253 #if NRND > 0
1254 rnd_detach_source(&sc->rnd_source);
1255 #endif
1256 #if NBPFILTER > 0
1257 bpfdetach(ifp);
1258 #endif
1259 ether_ifdetach(ifp);
1260 if_detach(ifp);
1261
1262 return (0);
1263 }
1264