smc91cxx.c revision 1.13 1 /* $NetBSD: smc91cxx.c,v 1.13 1998/11/18 18:34:52 thorpej 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 /* XXX Should be in a common header file. */
181 #define ETHER_MAX_LEN 1518
182 #define ETHER_MIN_LEN 64
183 #define ETHER_CRC_LEN 4
184
185 static __inline int ether_cmp __P((void *, void *));
186 static __inline int
187 ether_cmp(va, vb)
188 void *va, *vb;
189 {
190 u_int8_t *a = va;
191 u_int8_t *b = vb;
192
193 return ((a[5] != b[5]) || (a[4] != b[4]) || (a[3] != b[3]) ||
194 (a[2] != b[2]) || (a[1] != b[1]) || (a[0] != b[0]));
195 }
196
197 void
198 smc91cxx_attach(sc, myea)
199 struct smc91cxx_softc *sc;
200 u_int8_t *myea;
201 {
202 struct ifnet *ifp = &sc->sc_ec.ec_if;
203 bus_space_tag_t bst = sc->sc_bst;
204 bus_space_handle_t bsh = sc->sc_bsh;
205 const char *idstr;
206 u_int16_t tmp;
207 u_int8_t enaddr[ETHER_ADDR_LEN];
208 int i, aui;
209
210 /* Make sure the chip is stopped. */
211 smc91cxx_stop(sc);
212
213 SMC_SELECT_BANK(sc, 3);
214 tmp = bus_space_read_2(bst, bsh, REVISION_REG_W);
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, RND_TYPE_NET);
267 #endif
268 }
269
270 /*
271 * Change media according to request.
272 */
273 int
274 smc91cxx_mediachange(ifp)
275 struct ifnet *ifp;
276 {
277 struct smc91cxx_softc *sc = ifp->if_softc;
278
279 return (smc91cxx_set_media(sc, sc->sc_media.ifm_media));
280 }
281
282 int
283 smc91cxx_set_media(sc, media)
284 struct smc91cxx_softc *sc;
285 int media;
286 {
287 bus_space_tag_t bst = sc->sc_bst;
288 bus_space_handle_t bsh = sc->sc_bsh;
289 u_int16_t tmp;
290
291 /*
292 * If the interface is not currently powered on, just return.
293 * When it is enabled later, smc91cxx_init() will properly set
294 * up the media for us.
295 */
296 if (sc->sc_enabled == 0)
297 return (0);
298
299 if (IFM_TYPE(media) != IFM_ETHER)
300 return (EINVAL);
301
302 switch (IFM_SUBTYPE(media)) {
303 case IFM_10_T:
304 case IFM_10_5:
305 SMC_SELECT_BANK(sc, 1);
306 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
307 if (IFM_SUBTYPE(media) == IFM_10_5)
308 tmp |= CR_AUI_SELECT;
309 else
310 tmp &= ~CR_AUI_SELECT;
311 bus_space_write_2(bst, bsh, CONFIG_REG_W, tmp);
312 delay(20000); /* XXX is this needed? */
313 break;
314
315 default:
316 return (EINVAL);
317 }
318
319 return (0);
320 }
321
322 /*
323 * Notify the world which media we're using.
324 */
325 void
326 smc91cxx_mediastatus(ifp, ifmr)
327 struct ifnet *ifp;
328 struct ifmediareq *ifmr;
329 {
330 struct smc91cxx_softc *sc = ifp->if_softc;
331 bus_space_tag_t bst = sc->sc_bst;
332 bus_space_handle_t bsh = sc->sc_bsh;
333 u_int16_t tmp;
334
335 if (sc->sc_enabled == 0) {
336 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
337 ifmr->ifm_status = 0;
338 return;
339 }
340
341 SMC_SELECT_BANK(sc, 1);
342 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
343 ifmr->ifm_active =
344 IFM_ETHER | ((tmp & CR_AUI_SELECT) ? IFM_10_5 : IFM_10_T);
345 }
346
347 /*
348 * Reset and initialize the chip.
349 */
350 void
351 smc91cxx_init(sc)
352 struct smc91cxx_softc *sc;
353 {
354 struct ifnet *ifp = &sc->sc_ec.ec_if;
355 bus_space_tag_t bst = sc->sc_bst;
356 bus_space_handle_t bsh = sc->sc_bsh;
357 u_int16_t tmp;
358 u_int8_t *enaddr;
359 int s, i;
360
361 s = splnet();
362
363 /*
364 * This resets the registersmostly to defaults, but doesn't
365 * affect the EEPROM. After the reset cycle, we pause briefly
366 * for the chip to recover.
367 *
368 * XXX how long are we really supposed to delay? --thorpej
369 */
370 SMC_SELECT_BANK(sc, 0);
371 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET);
372 delay(100);
373 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
374 delay(200);
375
376 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
377
378 /* Set the Ethernet address. */
379 SMC_SELECT_BANK(sc, 1);
380 enaddr = (u_int8_t *)LLADDR(ifp->if_sadl);
381 for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
382 tmp = enaddr[i + 1] << 8 | enaddr[i];
383 bus_space_write_2(bst, bsh, IAR_ADDR0_REG_W + i, tmp);
384 }
385
386 /*
387 * Set the control register to automatically release successfully
388 * transmitted packets (making the best use of our limited memory)
389 * and enable the EPH interrupt on certain TX errors.
390 */
391 bus_space_write_2(bst, bsh, CONTROL_REG_W, (CTR_AUTO_RELEASE |
392 CTR_TE_ENABLE | CTR_CR_ENABLE | CTR_LE_ENABLE));
393
394 /*
395 * Reset the MMU and wait for it to be un-busy.
396 */
397 SMC_SELECT_BANK(sc, 2);
398 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET);
399 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
400 /* XXX bound this loop! */ ;
401
402 /*
403 * Disable all interrupts.
404 */
405 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
406
407 /*
408 * Set current media.
409 */
410 smc91cxx_set_media(sc, sc->sc_media.ifm_cur->ifm_media);
411
412 /*
413 * Set the receive filter. We want receive enable and auto
414 * strip of CRC from received packet. If we are in promisc. mode,
415 * then set that bit as well.
416 *
417 * XXX Initialize multicast filter. For now, we just accept
418 * XXX all multicast.
419 */
420 SMC_SELECT_BANK(sc, 0);
421
422 tmp = RCR_ENABLE | RCR_STRIP_CRC | RCR_ALMUL;
423 if (ifp->if_flags & IFF_PROMISC)
424 tmp |= RCR_PROMISC;
425
426 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, tmp);
427
428 /*
429 * Set transmitter control to "enabled".
430 */
431 tmp = TCR_ENABLE;
432
433 #ifndef SMC91CXX_SW_PAD
434 /*
435 * Enable hardware padding of transmitted packets.
436 * XXX doesn't work?
437 */
438 tmp |= TCR_PAD_ENABLE;
439 #endif
440
441 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, tmp);
442
443 /*
444 * Now, enable interrupts.
445 */
446 SMC_SELECT_BANK(sc, 2);
447
448 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
449 IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
450
451 /* Interface is now running, with no output active. */
452 ifp->if_flags |= IFF_RUNNING;
453 ifp->if_flags &= ~IFF_OACTIVE;
454
455 /*
456 * Attempt to start any pending transmission.
457 */
458 smc91cxx_start(ifp);
459
460 splx(s);
461 }
462
463 /*
464 * Start output on an interface.
465 * Must be called at splnet or interrupt level.
466 */
467 void
468 smc91cxx_start(ifp)
469 struct ifnet *ifp;
470 {
471 struct smc91cxx_softc *sc = ifp->if_softc;
472 bus_space_tag_t bst = sc->sc_bst;
473 bus_space_handle_t bsh = sc->sc_bsh;
474 u_int len;
475 struct mbuf *m, *top;
476 u_int16_t length, npages;
477 u_int8_t packetno;
478 int timo, pad;
479
480 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
481 return;
482
483 again:
484 /*
485 * Peek at the next packet.
486 */
487 if ((m = ifp->if_snd.ifq_head) == NULL)
488 return;
489
490 /*
491 * Compute the frame length and set pad to give an overall even
492 * number of bytes. Below, we assume that the packet length
493 * is even.
494 */
495 for (len = 0, top = m; m != NULL; m = m->m_next)
496 len += m->m_len;
497 pad = (len & 1);
498
499 /*
500 * We drop packets that are too large. Perhaps we should
501 * truncate them instead?
502 */
503 if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
504 printf("%s: large packet discarded\n", sc->sc_dev.dv_xname);
505 ifp->if_oerrors++;
506 IF_DEQUEUE(&ifp->if_snd, m);
507 m_freem(m);
508 goto readcheck;
509 }
510
511 #ifdef SMC91CXX_SW_PAD
512 /*
513 * Not using hardware padding; pad to ETHER_MIN_LEN.
514 */
515 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN))
516 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
517 #endif
518
519 length = pad + len;
520
521 /*
522 * The MMU has a 256 byte page size. The MMU expects us to
523 * ask for "npages - 1". We include space for the status word,
524 * byte count, and control bytes in the allocation request.
525 */
526 npages = (length + 6) >> 8;
527
528 /*
529 * Now allocate the memory.
530 */
531 SMC_SELECT_BANK(sc, 2);
532 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages);
533
534 timo = MEMORY_WAIT_TIME;
535 do {
536 if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
537 break;
538 delay(1);
539 } while (--timo);
540
541 packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
542
543 if (packetno & ARR_FAILED || timo == 0) {
544 /*
545 * No transmit memory is available. Record the number
546 * of requestd pages and enable the allocation completion
547 * interrupt. Set up the watchdog timer in case we miss
548 * the interrupt. Mark the interface as active so that
549 * no one else attempts to transmit while we're allocating
550 * memory.
551 */
552 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
553 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT);
554
555 ifp->if_timer = 5;
556 ifp->if_flags |= IFF_OACTIVE;
557
558 return;
559 }
560
561 /*
562 * We have a packet number - set the data window.
563 */
564 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
565
566 /*
567 * Point to the beginning of the packet.
568 */
569 bus_space_write_2(bst, bsh, POINTER_REG_W, PTR_AUTOINC /* | 0x0000 */);
570
571 /*
572 * Send the packet length (+6 for stats, length, and control bytes)
573 * and the status word (set to zeros).
574 */
575 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
576 bus_space_write_1(bst, bsh, DATA_REG_B, (length + 6) & 0xff);
577 bus_space_write_1(bst, bsh, DATA_REG_B, ((length + 6) >> 8) & 0xff);
578
579 /*
580 * Get the packet from the kernel. This will include the Ethernet
581 * frame header, MAC address, etc.
582 */
583 IF_DEQUEUE(&ifp->if_snd, m);
584
585 /*
586 * Push the packet out to the card.
587 */
588 for (top = m; m != NULL; m = m->m_next) {
589 /* Words... */
590 bus_space_write_multi_2(bst, bsh, DATA_REG_W,
591 mtod(m, u_int16_t *), m->m_len >> 1);
592
593 /* ...and the remaining byte, if any. */
594 if (m->m_len & 1)
595 bus_space_write_1(bst, bsh, DATA_REG_B,
596 *(u_int8_t *)(mtod(m, u_int8_t *) + (m->m_len - 1)));
597 }
598
599 #ifdef SMC91CXX_SW_PAD
600 /*
601 * Push out padding.
602 */
603 while (pad > 1) {
604 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
605 pad -= 2;
606 }
607 if (pad)
608 bus_space_write_1(bst, bsh, DATA_REG_B, 0);
609 #endif
610
611 /*
612 * Push out control byte and unused packet byte. The control byte
613 * is 0, meaning the packet is even lengthed and no special
614 * CRC handling is necessary.
615 */
616 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
617
618 /*
619 * Enable transmit interrupts and let the chip go. Set a watchdog
620 * in case we miss the interrupt.
621 */
622 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
623 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) |
624 IM_TX_INT | IM_TX_EMPTY_INT);
625
626 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE);
627
628 ifp->if_timer = 5;
629
630 #if NBPFILTER > 0
631 /* Hand off a copy to the bpf. */
632 if (ifp->if_bpf)
633 bpf_mtap(ifp->if_bpf, top);
634 #endif
635
636 ifp->if_opackets++;
637 m_freem(top);
638
639 readcheck:
640 /*
641 * Check for incoming pcakets. We don't want to overflow the small
642 * RX FIFO. If nothing has arrived, attempt to queue another
643 * transmit packet.
644 */
645 if (bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & FIFO_REMPTY)
646 goto again;
647 }
648
649 /*
650 * Interrupt service routine.
651 */
652 int
653 smc91cxx_intr(arg)
654 void *arg;
655 {
656 struct smc91cxx_softc *sc = arg;
657 struct ifnet *ifp = &sc->sc_ec.ec_if;
658 bus_space_tag_t bst = sc->sc_bst;
659 bus_space_handle_t bsh = sc->sc_bsh;
660 u_int8_t mask, interrupts, status;
661 u_int16_t packetno, tx_status, card_stats;
662
663 if (sc->sc_enabled == 0)
664 return (0);
665
666 SMC_SELECT_BANK(sc, 2);
667
668 /*
669 * Obtain the current interrupt mask.
670 */
671 mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
672
673 /*
674 * Get the set of interrupt which occurred and eliminate any
675 * which are not enabled.
676 */
677 interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
678 status = interrupts & mask;
679
680 /* Ours? */
681 if (status == 0)
682 return (0);
683
684 /*
685 * It's ours; disable all interrupts while we process them.
686 */
687 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
688
689 /*
690 * Receive overrun interrupts.
691 */
692 if (status & IM_RX_OVRN_INT) {
693 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT);
694 ifp->if_ierrors++;
695 }
696
697 /*
698 * Receive interrupts.
699 */
700 if (status & IM_RCV_INT) {
701 #if 1 /* DIAGNOSTIC */
702 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
703 if (packetno & FIFO_REMPTY)
704 printf("%s: receive interrupt on empty fifo\n",
705 sc->sc_dev.dv_xname);
706 else
707 #endif
708 smc91cxx_read(sc);
709 }
710
711 /*
712 * Memory allocation interrupts.
713 */
714 if (status & IM_ALLOC_INT) {
715 /* Disable this interrupt. */
716 mask &= ~IM_ALLOC_INT;
717
718 /*
719 * Release the just-allocated memory. We will reallocate
720 * it through the normal start logic.
721 */
722 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
723 /* XXX bound this loop! */ ;
724 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
725
726 ifp->if_flags &= ~IFF_OACTIVE;
727 ifp->if_timer = 0;
728 }
729
730 /*
731 * Transmit complete interrupt. Handle transmission error messages.
732 * This will only be called on error condition because of AUTO RELEASE
733 * mode.
734 */
735 if (status & IM_TX_INT) {
736 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT);
737
738 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) &
739 FIFO_TX_MASK;
740
741 /*
742 * Select this as the packet to read from.
743 */
744 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
745
746 /*
747 * Position the pointer to the beginning of the packet.
748 */
749 bus_space_write_2(bst, bsh, POINTER_REG_W,
750 PTR_AUTOINC | PTR_READ /* | 0x0000 */);
751
752 /*
753 * Fetch the TX status word. This will be a copy of
754 * the EPH_STATUS_REG_W at the time of the transmission
755 * failure.
756 */
757 tx_status = bus_space_read_2(bst, bsh, DATA_REG_W);
758
759 if (tx_status & EPHSR_TX_SUC)
760 printf("%s: successful packet caused TX interrupt?!\n",
761 sc->sc_dev.dv_xname);
762 else
763 ifp->if_oerrors++;
764
765 if (tx_status & EPHSR_LATCOL)
766 ifp->if_collisions++;
767
768 /*
769 * Some of these errors disable the transmitter; reenable it.
770 */
771 SMC_SELECT_BANK(sc, 0);
772 #ifdef SMC91CXX_SW_PAD
773 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, TCR_ENABLE);
774 #else
775 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W,
776 TCR_ENABLE | TCR_PAD_ENABLE);
777 #endif
778
779 /*
780 * Kill the failed packet and wait for the MMU to unbusy.
781 */
782 SMC_SELECT_BANK(sc, 2);
783 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
784 /* XXX bound this loop! */ ;
785 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
786
787 ifp->if_timer = 0;
788 }
789
790 /*
791 * Transmit underrun interrupts. We use this opportunity to
792 * update transmit statistics from the card.
793 */
794 if (status & IM_TX_EMPTY_INT) {
795 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
796
797 /* Disable this interrupt. */
798 mask &= ~IM_TX_EMPTY_INT;
799
800 SMC_SELECT_BANK(sc, 0);
801 card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W);
802
803 /* Single collisions. */
804 ifp->if_collisions += card_stats & ECR_COLN_MASK;
805
806 /* Multiple collisions. */
807 ifp->if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4;
808
809 SMC_SELECT_BANK(sc, 2);
810
811 ifp->if_timer = 0;
812 }
813
814 /*
815 * Other errors. Reset the interface.
816 */
817 if (status & IM_EPH_INT) {
818 smc91cxx_stop(sc);
819 smc91cxx_init(sc);
820 }
821
822 /*
823 * Attempt to queue more packets for transmission.
824 */
825 smc91cxx_start(ifp);
826
827 /*
828 * Reenable the interrupts we wish to receive now that processing
829 * is complete.
830 */
831 mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
832 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
833
834 #if NRND > 0
835 if (status)
836 rnd_add_uint32(&sc->rnd_source, status);
837 #endif
838
839 return (1);
840 }
841
842 /*
843 * Read a packet from the card and pass it up to the kernel.
844 * NOTE! WE EXPECT TO BE IN REGISTER WINDOW 2!
845 */
846 void
847 smc91cxx_read(sc)
848 struct smc91cxx_softc *sc;
849 {
850 struct ifnet *ifp = &sc->sc_ec.ec_if;
851 bus_space_tag_t bst = sc->sc_bst;
852 bus_space_handle_t bsh = sc->sc_bsh;
853 struct ether_header *eh;
854 struct mbuf *m;
855 u_int16_t status, packetno, packetlen;
856 u_int8_t *data;
857
858 again:
859 /*
860 * Set data pointer to the beginning of the packet. Since
861 * PTR_RCV is set, the packet number will be found automatically
862 * in FIFO_PORTS_REG_W, FIFO_RX_MASK.
863 */
864 bus_space_write_2(bst, bsh, POINTER_REG_W,
865 PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */);
866
867 /*
868 * First two words are status and packet length.
869 */
870 status = bus_space_read_2(bst, bsh, DATA_REG_W);
871 packetlen = bus_space_read_2(bst, bsh, DATA_REG_W);
872
873 /*
874 * The packet length includes 3 extra words: status, length,
875 * and an extra word that includes the control byte.
876 */
877 packetlen -= 6;
878
879 /*
880 * Account for receive errors and discard.
881 */
882 if (status & RS_ERRORS) {
883 ifp->if_ierrors++;
884 goto out;
885 }
886
887 /*
888 * Adjust for odd-length packet.
889 */
890 if (status & RS_ODDFRAME)
891 packetlen++;
892
893 /*
894 * Allocate a header mbuf.
895 */
896 MGETHDR(m, M_DONTWAIT, MT_DATA);
897 if (m == NULL)
898 goto out;
899
900 m->m_pkthdr.rcvif = ifp;
901 m->m_pkthdr.len = m->m_len = packetlen;
902
903 /*
904 * Always put the packet in a cluster.
905 * XXX should chain small mbufs if less than threshold.
906 */
907 MCLGET(m, M_DONTWAIT);
908 if ((m->m_flags & M_EXT) == 0) {
909 m_freem(m);
910 ifp->if_ierrors++;
911 printf("%s: can't allocate cluster for incoming packet\n",
912 sc->sc_dev.dv_xname);
913 goto out;
914 }
915
916 /*
917 * Pull the packet off the interface.
918 */
919 eh = mtod(m, struct ether_header *);
920 data = mtod(m, u_int8_t *);
921 bus_space_read_multi_2(bst, bsh, DATA_REG_W, (u_int16_t *)data,
922 packetlen >> 1);
923 if (packetlen & 1) {
924 data += packetlen & ~1;
925 *data = bus_space_read_1(bst, bsh, DATA_REG_B);
926 }
927
928 ifp->if_ipackets++;
929
930 #if NBPFILTER > 0
931 /*
932 * Hand the packet off to bpf listeners. If there's a bpf listener,
933 * we need to check if the packet is ours.
934 */
935 if (ifp->if_bpf) {
936 bpf_mtap(ifp->if_bpf, m);
937
938 if ((ifp->if_flags & IFF_PROMISC) &&
939 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
940 ether_cmp(eh->ether_dhost, LLADDR(ifp->if_sadl))) {
941 m_freem(m);
942 goto out;
943 }
944 }
945 #endif
946
947 /*
948 * Strip the ethernet header.
949 */
950 m->m_pkthdr.len = m->m_len = packetlen - sizeof(struct ether_header);
951 m->m_data += sizeof(struct ether_header);
952
953 ether_input(ifp, eh, m);
954
955 out:
956 /*
957 * Tell the card to free the memory occupied by this packet.
958 */
959 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
960 /* XXX bound this loop! */ ;
961 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RELEASE);
962
963 /*
964 * Check for another packet.
965 */
966 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
967 if (packetno & FIFO_REMPTY)
968 return;
969 goto again;
970 }
971
972 /*
973 * Process an ioctl request.
974 */
975 int
976 smc91cxx_ioctl(ifp, cmd, data)
977 struct ifnet *ifp;
978 u_long cmd;
979 caddr_t data;
980 {
981 struct smc91cxx_softc *sc = ifp->if_softc;
982 struct ifaddr *ifa = (struct ifaddr *)data;
983 struct ifreq *ifr = (struct ifreq *)data;
984 int s, error = 0;
985
986 s = splnet();
987
988 switch (cmd) {
989 case SIOCSIFADDR:
990 if ((error = smc91cxx_enable(sc)) != 0)
991 break;
992 ifp->if_flags |= IFF_UP;
993 switch (ifa->ifa_addr->sa_family) {
994 #ifdef INET
995 case AF_INET:
996 smc91cxx_init(sc);
997 arp_ifinit(ifp, ifa);
998 break;
999 #endif
1000 #ifdef NS
1001 case AF_NS:
1002 {
1003 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1004
1005 if (ns_nullhost(*ina))
1006 ina->x_host =
1007 *(union ns_host *)LLADDR(ifp->if_sadl);
1008 else {
1009 bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
1010 ETHER_ADDR_LEN);
1011 }
1012
1013 /*
1014 * Set new address. Reset, because the receiver
1015 * has to be stopped before we can set the new
1016 * MAC address.
1017 */
1018 smc91cxx_reset(sc);
1019 break;
1020 }
1021 #endif
1022 default:
1023 smc91cxx_init(sc);
1024 break;
1025 }
1026 break;
1027
1028 #if defined(CCITT) && defined(LLC)
1029 case SIOCSIFCONF_X25:
1030 if ((error = smc91cxx_enable(sc)) != 0)
1031 break;
1032 ifp->if_flags |= IFF_UP;
1033 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
1034 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
1035 if (error == 0)
1036 smc91cxx_init(sc);
1037 break;
1038 #endif
1039
1040 case SIOCSIFFLAGS:
1041 if ((ifp->if_flags & IFF_UP) == 0 &&
1042 (ifp->if_flags & IFF_RUNNING) != 0) {
1043 /*
1044 * If interface is marked down and it is running,
1045 * stop it.
1046 */
1047 smc91cxx_stop(sc);
1048 ifp->if_flags &= ~IFF_RUNNING;
1049 smc91cxx_disable(sc);
1050 } else if ((ifp->if_flags & IFF_UP) != 0 &&
1051 (ifp->if_flags & IFF_RUNNING) == 0) {
1052 /*
1053 * If interface is marked up and it is stopped,
1054 * start it.
1055 */
1056 if ((error = smc91cxx_enable(sc)) != 0)
1057 break;
1058 smc91cxx_init(sc);
1059 } else if (sc->sc_enabled) {
1060 /*
1061 * Reset the interface to pick up changes in any
1062 * other flags that affect hardware registers.
1063 */
1064 smc91cxx_reset(sc);
1065 }
1066 break;
1067
1068 case SIOCADDMULTI:
1069 case SIOCDELMULTI:
1070 if (sc->sc_enabled == 0) {
1071 error = EIO;
1072 break;
1073 }
1074
1075 error = (cmd == SIOCADDMULTI) ?
1076 ether_addmulti(ifr, &sc->sc_ec) :
1077 ether_delmulti(ifr, &sc->sc_ec);
1078 if (error == ENETRESET) {
1079 /*
1080 * Multicast list has changed; set the hardware
1081 * filter accordingly.
1082 */
1083 smc91cxx_reset(sc);
1084 error = 0;
1085 }
1086 break;
1087
1088 case SIOCGIFMEDIA:
1089 case SIOCSIFMEDIA:
1090 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1091 break;
1092
1093 default:
1094 error = EINVAL;
1095 break;
1096 }
1097
1098 splx(s);
1099 return (error);
1100 }
1101
1102 /*
1103 * Reset the interface.
1104 */
1105 void
1106 smc91cxx_reset(sc)
1107 struct smc91cxx_softc *sc;
1108 {
1109 int s;
1110
1111 s = splnet();
1112 smc91cxx_stop(sc);
1113 smc91cxx_init(sc);
1114 splx(s);
1115 }
1116
1117 /*
1118 * Watchdog timer.
1119 */
1120 void
1121 smc91cxx_watchdog(ifp)
1122 struct ifnet *ifp;
1123 {
1124 struct smc91cxx_softc *sc = ifp->if_softc;
1125
1126 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1127 ifp->if_oerrors++;
1128 smc91cxx_reset(sc);
1129 }
1130
1131 /*
1132 * Stop output on the interface.
1133 */
1134 void
1135 smc91cxx_stop(sc)
1136 struct smc91cxx_softc *sc;
1137 {
1138 bus_space_tag_t bst = sc->sc_bst;
1139 bus_space_handle_t bsh = sc->sc_bsh;
1140
1141 /*
1142 * Clear interrupt mask; disable all interrupts.
1143 */
1144 SMC_SELECT_BANK(sc, 2);
1145 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
1146
1147 /*
1148 * Disable transmitter and receiver.
1149 */
1150 SMC_SELECT_BANK(sc, 0);
1151 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
1152 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
1153
1154 /*
1155 * Cancel watchdog timer.
1156 */
1157 sc->sc_ec.ec_if.if_timer = 0;
1158 }
1159
1160 /*
1161 * Enable power on the interface.
1162 */
1163 int
1164 smc91cxx_enable(sc)
1165 struct smc91cxx_softc *sc;
1166 {
1167
1168 if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
1169 if ((*sc->sc_enable)(sc) != 0) {
1170 printf("%s: device enable failed\n",
1171 sc->sc_dev.dv_xname);
1172 return (EIO);
1173 }
1174 }
1175
1176 sc->sc_enabled = 1;
1177 return (0);
1178 }
1179
1180 /*
1181 * Disable power on the interface.
1182 */
1183 void
1184 smc91cxx_disable(sc)
1185 struct smc91cxx_softc *sc;
1186 {
1187
1188 if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
1189 (*sc->sc_disable)(sc);
1190 sc->sc_enabled = 0;
1191 }
1192 }
1193
1194 int
1195 smc91cxx_activate(self, act)
1196 struct device *self;
1197 enum devact act;
1198 {
1199 struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
1200 int rv = 0, s;
1201
1202 s = splnet();
1203 switch (act) {
1204 case DVACT_ACTIVATE:
1205 rv = EOPNOTSUPP;
1206 break;
1207
1208 case DVACT_DEACTIVATE:
1209 #ifdef notyet
1210 /* First, kill off the interface. */
1211 if_detach(sc->sc_ec.ec_if);
1212 #endif
1213
1214 /* Now disable the interface. */
1215 smc91cxx_disable(sc);
1216 break;
1217 }
1218 splx(s);
1219 return (rv);
1220 }
1221