smc91cxx.c revision 1.2 1 /* $NetBSD: smc91cxx.c,v 1.2 1997/09/02 00:10:55 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 REGENTS OR CONTRIBUTORS BE
31 * 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 "bpfilter.h"
81
82 #include <sys/param.h>
83 #include <sys/systm.h>
84 #include <sys/mbuf.h>
85 #include <sys/syslog.h>
86 #include <sys/socket.h>
87 #include <sys/device.h>
88 #include <sys/malloc.h>
89 #include <sys/ioctl.h>
90 #include <sys/errno.h>
91
92 #include <machine/bus.h>
93 #include <machine/intr.h>
94
95 #include <net/if.h>
96 #include <net/if_dl.h>
97 #include <net/if_ether.h>
98 #include <net/if_media.h>
99
100 #ifdef INET
101 #include <netinet/in.h>
102 #include <netinet/if_inarp.h>
103 #include <netinet/in_systm.h>
104 #include <netinet/in_var.h>
105 #include <netinet/ip.h>
106 #endif
107
108 #ifdef NS
109 #include <netns/ns.h>
110 #include <netns/ns_if.h>
111 #endif
112
113 #if defined(CCITT) && defined(LLC)
114 #include <sys/socketvar.h>
115 #include <netccitt/x25.h>
116 #include <netccitt/pk.h>
117 #include <netccitt/pk_var.h>
118 #include <netccitt/pk_extern.h>
119 #endif
120
121 #if NBPFILTER > 0
122 #include <net/bpf.h>
123 #include <net/bpfdesc.h>
124 #endif
125
126 #include <dev/ic/smc91cxxreg.h>
127 #include <dev/ic/smc91cxxvar.h>
128
129 /* XXX Hardware padding doesn't work yet(?) */
130 #define SMC91CXX_SW_PAD
131
132 struct cfdriver sm_cd = {
133 NULL, "sm", DV_IFNET
134 };
135
136 const char *smc91cxx_idstrs[] = {
137 NULL, /* 0 */
138 NULL, /* 1 */
139 NULL, /* 2 */
140 "SMC91C90/91C92", /* 3 */
141 "SMC91C94", /* 4 */
142 "SMC91C95", /* 5 */
143 NULL, /* 6 */
144 "SMC91C100", /* 7 */
145 NULL, /* 8 */
146 NULL, /* 9 */
147 NULL, /* 10 */
148 NULL, /* 11 */
149 NULL, /* 12 */
150 NULL, /* 13 */
151 NULL, /* 14 */
152 NULL, /* 15 */
153 };
154
155 /* Supported media types. */
156 const int smc91cxx_media[] = {
157 IFM_ETHER|IFM_10_T,
158 IFM_ETHER|IFM_10_5,
159 };
160 #define NSMC91CxxMEDIA (sizeof(smc91cxx_media) / sizeof(smc91cxx_media[0]))
161
162 int smc91cxx_mediachange __P((struct ifnet *));
163 void smc91cxx_mediastatus __P((struct ifnet *, struct ifmediareq *));
164
165 int smc91cxx_set_media __P((struct smc91cxx_softc *, int));
166
167 void smc91cxx_init __P((struct smc91cxx_softc *));
168 void smc91cxx_read __P((struct smc91cxx_softc *));
169 void smc91cxx_reset __P((struct smc91cxx_softc *));
170 void smc91cxx_start __P((struct ifnet *));
171 void smc91cxx_resume __P((struct smc91cxx_softc *));
172 void smc91cxx_stop __P((struct smc91cxx_softc *));
173 void smc91cxx_watchdog __P((struct ifnet *));
174 int smc91cxx_ioctl __P((struct ifnet *, u_long, caddr_t));
175
176 /* XXX Should be in a common header file. */
177 #define ETHER_MAX_LEN 1518
178 #define ETHER_MIN_LEN 64
179 #define ETHER_CRC_LEN 4
180
181 static __inline int ether_cmp __P((void *, void *));
182 static __inline int
183 ether_cmp(va, vb)
184 void *va, *vb;
185 {
186 u_int8_t *a = va;
187 u_int8_t *b = vb;
188
189 return ((a[5] != b[5]) || (a[4] != b[4]) || (a[3] != b[3]) ||
190 (a[2] != b[2]) || (a[1] != b[1]) || (a[0] != b[0]));
191 }
192
193 void
194 smc91cxx_attach(sc, myea)
195 struct smc91cxx_softc *sc;
196 u_int8_t *myea;
197 {
198 struct ifnet *ifp = &sc->sc_ec.ec_if;
199 bus_space_tag_t bst = sc->sc_bst;
200 bus_space_handle_t bsh = sc->sc_bsh;
201 const char *idstr;
202 u_int16_t tmp;
203 u_int8_t enaddr[ETHER_ADDR_LEN];
204 int i, aui;
205
206 /* Make sure the chip is stopped. */
207 smc91cxx_stop(sc);
208
209 SMC_SELECT_BANK(sc, 3);
210 tmp = bus_space_read_2(bst, bsh, REVISION_REG_W);
211 idstr = smc91cxx_idstrs[RR_ID(tmp)];
212 printf("%s: ", sc->sc_dev.dv_xname);
213 if (idstr != NULL)
214 printf("%s, ", idstr);
215 else
216 printf("unknown chip id %d, ", RR_ID(tmp));
217 printf("revision %d\n", RR_REV(tmp));
218
219 /* Read the station address from the chip. */
220 SMC_SELECT_BANK(sc, 1);
221 if (myea == NULL) {
222 myea = enaddr;
223 for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
224 tmp = bus_space_read_2(bst, bsh, IAR_ADDR0_REG_W + i);
225 myea[i + 1] = (tmp >> 8) & 0xff;
226 myea[i] = tmp & 0xff;
227 }
228 }
229 printf("%s: MAC address %s, ", sc->sc_dev.dv_xname,
230 ether_sprintf(myea));
231
232 /* ..and default media. */
233 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
234 printf("default media %s\n", (aui = (tmp & CR_AUI_SELECT)) ?
235 "AUI" : "UTP");
236
237 /* Initialize the ifnet structure. */
238 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
239 ifp->if_softc = sc;
240 ifp->if_start = smc91cxx_start;
241 ifp->if_ioctl = smc91cxx_ioctl;
242 ifp->if_watchdog = smc91cxx_watchdog;
243 ifp->if_flags =
244 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
245
246 /* Attach the interface. */
247 if_attach(ifp);
248 ether_ifattach(ifp, myea);
249
250 /* Initialize the media structures. */
251 ifmedia_init(&sc->sc_media, 0, smc91cxx_mediachange,
252 smc91cxx_mediastatus);
253 for (i = 0; i < NSMC91CxxMEDIA; i++)
254 ifmedia_add(&sc->sc_media, smc91cxx_media[i], 0, NULL);
255 ifmedia_set(&sc->sc_media, IFM_ETHER | (aui ? IFM_10_5 : IFM_10_T));
256
257 #if NBPFILTER > 0
258 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
259 #endif
260 }
261
262 /*
263 * Change media according to request.
264 */
265 int
266 smc91cxx_mediachange(ifp)
267 struct ifnet *ifp;
268 {
269 struct smc91cxx_softc *sc = ifp->if_softc;
270
271 return (smc91cxx_set_media(sc, sc->sc_media.ifm_media));
272 }
273
274 int
275 smc91cxx_set_media(sc, media)
276 struct smc91cxx_softc *sc;
277 int media;
278 {
279 bus_space_tag_t bst = sc->sc_bst;
280 bus_space_handle_t bsh = sc->sc_bsh;
281 u_int16_t tmp;
282
283 if (IFM_TYPE(media) != IFM_ETHER)
284 return (EINVAL);
285
286 switch (IFM_SUBTYPE(media)) {
287 case IFM_10_T:
288 case IFM_10_5:
289 SMC_SELECT_BANK(sc, 1);
290 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
291 if (IFM_SUBTYPE(media) == IFM_10_5)
292 tmp |= CR_AUI_SELECT;
293 else
294 tmp &= ~CR_AUI_SELECT;
295 bus_space_write_2(bst, bsh, CONFIG_REG_W, tmp);
296 delay(20000); /* XXX is this needed? */
297 break;
298
299 default:
300 return (EINVAL);
301 }
302
303 return (0);
304 }
305
306 /*
307 * Notify the world which media we're using.
308 */
309 void
310 smc91cxx_mediastatus(ifp, ifmr)
311 struct ifnet *ifp;
312 struct ifmediareq *ifmr;
313 {
314 struct smc91cxx_softc *sc = ifp->if_softc;
315 bus_space_tag_t bst = sc->sc_bst;
316 bus_space_handle_t bsh = sc->sc_bsh;
317 u_int16_t tmp;
318
319 SMC_SELECT_BANK(sc, 1);
320 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
321 ifmr->ifm_active =
322 IFM_ETHER | ((tmp & CR_AUI_SELECT) ? IFM_10_5 : IFM_10_T);
323 }
324
325 /*
326 * Reset and initialize the chip.
327 */
328 void
329 smc91cxx_init(sc)
330 struct smc91cxx_softc *sc;
331 {
332 struct ifnet *ifp = &sc->sc_ec.ec_if;
333 bus_space_tag_t bst = sc->sc_bst;
334 bus_space_handle_t bsh = sc->sc_bsh;
335 u_int16_t tmp;
336 u_int8_t *enaddr;
337 int s, i;
338
339 s = splimp();
340
341 /*
342 * This resets the registersmostly to defaults, but doesn't
343 * affect the EEPROM. After the reset cycle, we pause briefly
344 * for the chip to recover.
345 *
346 * XXX how long are we really supposed to delay? --thorpej
347 */
348 SMC_SELECT_BANK(sc, 0);
349 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET);
350 delay(100);
351 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
352 delay(200);
353
354 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
355
356 /* Set the Ethernet address. */
357 SMC_SELECT_BANK(sc, 1);
358 enaddr = (u_int8_t *)LLADDR(ifp->if_sadl);
359 for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
360 tmp = enaddr[i + 1] << 8 | enaddr[i];
361 bus_space_write_2(bst, bsh, IAR_ADDR0_REG_W + i, tmp);
362 }
363
364 /*
365 * Set the control register to automatically release successfully
366 * transmitted packets (making the best use of our limited memory)
367 * and enable the EPH interrupt on certain TX errors.
368 */
369 bus_space_write_2(bst, bsh, CONTROL_REG_W, (CTR_AUTO_RELEASE |
370 CTR_TE_ENABLE | CTR_CR_ENABLE | CTR_LE_ENABLE));
371
372 /*
373 * Reset the MMU and wait for it to be un-busy.
374 */
375 SMC_SELECT_BANK(sc, 2);
376 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET);
377 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
378 /* XXX bound this loop! */ ;
379
380 /*
381 * Disable all interrupts.
382 */
383 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
384
385 /*
386 * Set current media.
387 */
388 smc91cxx_set_media(sc, sc->sc_media.ifm_cur->ifm_media);
389
390 /*
391 * Set the receive filter. We want receive enable and auto
392 * strip of CRC from received packet. If we are in promisc. mode,
393 * then set that bit as well.
394 *
395 * XXX Initialize multicast filter. For now, we just accept
396 * XXX all multicast.
397 */
398 SMC_SELECT_BANK(sc, 0);
399
400 tmp = RCR_ENABLE | RCR_STRIP_CRC | RCR_ALMUL;
401 if (ifp->if_flags & IFF_PROMISC)
402 tmp |= RCR_PROMISC;
403
404 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, tmp);
405
406 /*
407 * Set transmitter control to "enabled".
408 */
409 tmp = TCR_ENABLE;
410
411 #ifndef SMC91CXX_SW_PAD
412 /*
413 * Enable hardware padding of transmitted packets.
414 * XXX doesn't work?
415 */
416 tmp |= TCR_PAD_ENABLE;
417 #endif
418
419 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, tmp);
420
421 /*
422 * Now, enable interrupts.
423 */
424 SMC_SELECT_BANK(sc, 2);
425
426 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
427 IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
428
429 /* Interface is now running, with no output active. */
430 ifp->if_flags |= IFF_RUNNING;
431 ifp->if_flags &= ~IFF_OACTIVE;
432
433 /*
434 * Attempt to start any pending transmission.
435 */
436 smc91cxx_start(ifp);
437
438 splx(s);
439 }
440
441 /*
442 * Start output on an interface.
443 * Must be called at splimp or interrupt level.
444 */
445 void
446 smc91cxx_start(ifp)
447 struct ifnet *ifp;
448 {
449 struct smc91cxx_softc *sc = ifp->if_softc;
450 bus_space_tag_t bst = sc->sc_bst;
451 bus_space_handle_t bsh = sc->sc_bsh;
452 u_int len;
453 struct mbuf *m, *top;
454 u_int16_t length, npages;
455 u_int8_t packetno;
456 int timo, pad;
457
458 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
459 return;
460
461 again:
462 /*
463 * Peek at the next packet.
464 */
465 if ((m = ifp->if_snd.ifq_head) == NULL)
466 return;
467
468 /*
469 * Compute the frame length and set pad to give an overall even
470 * number of bytes. Below, we assume that the packet length
471 * is even.
472 */
473 for (len = 0, top = m; m != NULL; m = m->m_next)
474 len += m->m_len;
475 pad = (len & 1);
476
477 /*
478 * We drop packets that are too large. Perhaps we should
479 * truncate them instead?
480 */
481 if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
482 printf("%s: large packet discarded\n", sc->sc_dev.dv_xname);
483 ifp->if_oerrors++;
484 IF_DEQUEUE(&ifp->if_snd, m);
485 m_freem(m);
486 goto readcheck;
487 }
488
489 #ifdef SMC91CXX_SW_PAD
490 /*
491 * Not using hardware padding; pad to ETHER_MIN_LEN.
492 */
493 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN))
494 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
495 #endif
496
497 length = pad + len;
498
499 /*
500 * The MMU has a 256 byte page size. The MMU expects us to
501 * ask for "npages - 1". We include space for the status word,
502 * byte count, and control bytes in the allocation request.
503 */
504 npages = (length + 6) >> 8;
505
506 /*
507 * Now allocate the memory.
508 */
509 SMC_SELECT_BANK(sc, 2);
510 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages);
511
512 timo = MEMORY_WAIT_TIME;
513 do {
514 if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
515 break;
516 delay(1);
517 } while (--timo);
518
519 packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
520
521 if (packetno & ARR_FAILED || timo == 0) {
522 /*
523 * No transmit memory is available. Record the number
524 * of requestd pages and enable the allocation completion
525 * interrupt. Set up the watchdog timer in case we miss
526 * the interrupt. Mark the interface as active so that
527 * no one else attempts to transmit while we're allocating
528 * memory.
529 */
530 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
531 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT);
532
533 ifp->if_timer = 5;
534 ifp->if_flags |= IFF_OACTIVE;
535
536 return;
537 }
538
539 /*
540 * We have a packet number - set the data window.
541 */
542 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
543
544 /*
545 * Point to the beginning of the packet.
546 */
547 bus_space_write_2(bst, bsh, POINTER_REG_W, PTR_AUTOINC /* | 0x0000 */);
548
549 /*
550 * Send the packet length (+6 for stats, length, and control bytes)
551 * and the status word (set to zeros).
552 */
553 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
554 bus_space_write_1(bst, bsh, DATA_REG_B, (length + 6) & 0xff);
555 bus_space_write_1(bst, bsh, DATA_REG_B, ((length + 6) >> 8) & 0xff);
556
557 /*
558 * Get the packet from the kernel. This will include the Ethernet
559 * frame header, MAC address, etc.
560 */
561 IF_DEQUEUE(&ifp->if_snd, m);
562
563 /*
564 * Push the packet out to the card.
565 */
566 for (top = m; m != NULL; m = m->m_next) {
567 /* Words... */
568 bus_space_write_multi_2(bst, bsh, DATA_REG_W,
569 mtod(m, u_int16_t *), m->m_len >> 1);
570
571 /* ...and the remaining byte, if any. */
572 if (m->m_len & 1)
573 bus_space_write_1(bst, bsh, DATA_REG_B,
574 *(u_int8_t *)(mtod(m, u_int8_t *) + (m->m_len - 1)));
575 }
576
577 #ifdef SMC91CXX_SW_PAD
578 /*
579 * Push out padding.
580 */
581 while (pad > 1) {
582 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
583 pad -= 2;
584 }
585 if (pad)
586 bus_space_write_1(bst, bsh, DATA_REG_B, 0);
587 #endif
588
589 /*
590 * Push out control byte and unused packet byte. The control byte
591 * is 0, meaning the packet is even lengthed and no special
592 * CRC handling is necessary.
593 */
594 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
595
596 /*
597 * Enable transmit interrupts and let the chip go. Set a watchdog
598 * in case we miss the interrupt.
599 */
600 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
601 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) |
602 IM_TX_INT | IM_TX_EMPTY_INT);
603
604 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE);
605
606 ifp->if_timer = 5;
607
608 #if NBPFILTER > 0
609 /* Hand off a copy to the bpf. */
610 if (ifp->if_bpf)
611 bpf_mtap(ifp->if_bpf, top);
612 #endif
613
614 ifp->if_opackets++;
615 m_freem(top);
616
617 readcheck:
618 /*
619 * Check for incoming pcakets. We don't want to overflow the small
620 * RX FIFO. If nothing has arrived, attempt to queue another
621 * transmit packet.
622 */
623 if (bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & FIFO_REMPTY)
624 goto again;
625 }
626
627 /*
628 * Interrupt service routine.
629 */
630 int
631 smc91cxx_intr(arg)
632 void *arg;
633 {
634 struct smc91cxx_softc *sc = arg;
635 struct ifnet *ifp = &sc->sc_ec.ec_if;
636 bus_space_tag_t bst = sc->sc_bst;
637 bus_space_handle_t bsh = sc->sc_bsh;
638 u_int8_t mask, interrupts, status;
639 u_int16_t packetno, tx_status, card_stats;
640
641 SMC_SELECT_BANK(sc, 2);
642
643 /*
644 * Obtain the current interrupt mask.
645 */
646 mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
647
648 /*
649 * Get the set of interrupt which occurred and eliminate any
650 * which are not enabled.
651 */
652 interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
653 status = interrupts & mask;
654
655 /* Ours? */
656 if (status == 0)
657 return (0);
658
659 /*
660 * It's ours; disable all interrupts while we process them.
661 */
662 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
663
664 /*
665 * Receive overrun interrupts.
666 */
667 if (status & IM_RX_OVRN_INT) {
668 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT);
669 ifp->if_ierrors++;
670 }
671
672 /*
673 * Receive interrupts.
674 */
675 if (status & IM_RCV_INT) {
676 #if 1 /* DIAGNOSTIC */
677 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
678 if (packetno & FIFO_REMPTY)
679 printf("%s: receive interrupt on empty fifo\n",
680 sc->sc_dev.dv_xname);
681 else
682 #endif
683 smc91cxx_read(sc);
684 }
685
686 /*
687 * Memory allocation interrupts.
688 */
689 if (status & IM_ALLOC_INT) {
690 /* Disable this interrupt. */
691 mask &= ~IM_ALLOC_INT;
692
693 /*
694 * Release the just-allocated memory. We will reallocate
695 * it through the normal start logic.
696 */
697 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
698 /* XXX bound this loop! */ ;
699 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
700
701 ifp->if_flags &= ~IFF_OACTIVE;
702 ifp->if_timer = 0;
703 }
704
705 /*
706 * Transmit complete interrupt. Handle transmission error messages.
707 * This will only be called on error condition because of AUTO RELEASE
708 * mode.
709 */
710 if (status & IM_TX_INT) {
711 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT);
712
713 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) &
714 FIFO_TX_MASK;
715
716 /*
717 * Select this as the packet to read from.
718 */
719 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
720
721 /*
722 * Position the pointer to the beginning of the packet.
723 */
724 bus_space_write_2(bst, bsh, POINTER_REG_W,
725 PTR_AUTOINC | PTR_READ /* | 0x0000 */);
726
727 /*
728 * Fetch the TX status word. This will be a copy of
729 * the EPH_STATUS_REG_W at the time of the transmission
730 * failure.
731 */
732 tx_status = bus_space_read_2(bst, bsh, DATA_REG_W);
733
734 if (tx_status & EPHSR_TX_SUC)
735 printf("%s: successful packet caused TX interrupt?!\n",
736 sc->sc_dev.dv_xname);
737 else
738 ifp->if_oerrors++;
739
740 if (tx_status & EPHSR_LATCOL)
741 ifp->if_collisions++;
742
743 /*
744 * Some of these errors disable the transmitter; reenable it.
745 */
746 SMC_SELECT_BANK(sc, 0);
747 #ifdef SMC91CXX_SW_PAD
748 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, TCR_ENABLE);
749 #else
750 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W,
751 TCR_ENABLE | TCR_PAD_ENABLE);
752 #endif
753
754 /*
755 * Kill the failed packet and wait for the MMU to unbusy.
756 */
757 SMC_SELECT_BANK(sc, 2);
758 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
759 /* XXX bound this loop! */ ;
760 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
761
762 ifp->if_timer = 0;
763 }
764
765 /*
766 * Transmit underrun interrupts. We use this opportunity to
767 * update transmit statistics from the card.
768 */
769 if (status & IM_TX_EMPTY_INT) {
770 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
771
772 /* Disable this interrupt. */
773 mask &= ~IM_TX_EMPTY_INT;
774
775 SMC_SELECT_BANK(sc, 0);
776 card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W);
777
778 /* Single collisions. */
779 ifp->if_collisions += card_stats & ECR_COLN_MASK;
780
781 /* Multiple collisions. */
782 ifp->if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4;
783
784 SMC_SELECT_BANK(sc, 2);
785
786 ifp->if_timer = 0;
787 }
788
789 /*
790 * Other errors. Reset the interface.
791 */
792 if (status & IM_EPH_INT) {
793 smc91cxx_stop(sc);
794 smc91cxx_init(sc);
795 }
796
797 /*
798 * Attempt to queue more packets for transmission.
799 */
800 smc91cxx_start(ifp);
801
802 /*
803 * Reenable the interrupts we wish to receive now that processing
804 * is complete.
805 */
806 mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
807 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
808
809 return (1);
810 }
811
812 /*
813 * Read a packet from the card and pass it up to the kernel.
814 * NOTE! WE EXPECT TO BE IN REGISTER WINDOW 2!
815 */
816 void
817 smc91cxx_read(sc)
818 struct smc91cxx_softc *sc;
819 {
820 struct ifnet *ifp = &sc->sc_ec.ec_if;
821 bus_space_tag_t bst = sc->sc_bst;
822 bus_space_handle_t bsh = sc->sc_bsh;
823 struct ether_header *eh;
824 struct mbuf *m;
825 u_int16_t status, packetno, packetlen;
826 u_int8_t *data;
827
828 again:
829 /*
830 * Set data pointer to the beginning of the packet. Since
831 * PTR_RCV is set, the packet number will be found automatically
832 * in FIFO_PORTS_REG_W, FIFO_RX_MASK.
833 */
834 bus_space_write_2(bst, bsh, POINTER_REG_W,
835 PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */);
836
837 /*
838 * First two words are status and packet length.
839 */
840 status = bus_space_read_2(bst, bsh, DATA_REG_W);
841 packetlen = bus_space_read_2(bst, bsh, DATA_REG_W);
842
843 /*
844 * The packet length includes 3 extra words: status, length,
845 * and an extra word that includes the control byte.
846 */
847 packetlen -= 6;
848
849 /*
850 * Account for receive errors and discard.
851 */
852 if (status & RS_ERRORS) {
853 ifp->if_ierrors++;
854 goto out;
855 }
856
857 /*
858 * Adjust for odd-length packet.
859 */
860 if (status & RS_ODDFRAME)
861 packetlen++;
862
863 /*
864 * Allocate a header mbuf.
865 */
866 MGETHDR(m, M_DONTWAIT, MT_DATA);
867 if (m == NULL)
868 goto out;
869
870 m->m_pkthdr.rcvif = ifp;
871 m->m_pkthdr.len = m->m_len = packetlen;
872
873 /*
874 * Always put the packet in a cluster.
875 * XXX should chain small mbufs if less than threshold.
876 */
877 MCLGET(m, M_DONTWAIT);
878 if ((m->m_flags & M_EXT) == 0) {
879 m_freem(m);
880 ifp->if_ierrors++;
881 printf("%s: can't allocate cluster for incoming packet\n",
882 sc->sc_dev.dv_xname);
883 goto out;
884 }
885
886 /*
887 * Pull the packet off the interface.
888 */
889 eh = mtod(m, struct ether_header *);
890 data = mtod(m, u_int8_t *);
891 bus_space_read_multi_2(bst, bsh, DATA_REG_W, (u_int16_t *)data,
892 packetlen >> 1);
893 if (packetlen & 1) {
894 data += packetlen & ~1;
895 *data = bus_space_read_1(bst, bsh, DATA_REG_B);
896 }
897
898 ifp->if_ipackets++;
899
900 #if NBPFILTER > 0
901 /*
902 * Hand the packet off to bpf listeners. If there's a bpf listener,
903 * we need to check if the packet is ours.
904 */
905 if (ifp->if_bpf) {
906 bpf_mtap(ifp->if_bpf, m);
907
908 if ((ifp->if_flags & IFF_PROMISC) &&
909 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
910 ether_cmp(eh->ether_dhost, LLADDR(ifp->if_sadl))) {
911 m_freem(m);
912 goto out;
913 }
914 }
915 #endif
916
917 /*
918 * Strip the ethernet header.
919 */
920 m->m_pkthdr.len = m->m_len = packetlen - sizeof(struct ether_header);
921 m->m_data += sizeof(struct ether_header);
922
923 ether_input(ifp, eh, m);
924
925 out:
926 /*
927 * Tell the card to free the memory occupied by this packet.
928 */
929 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
930 /* XXX bound this loop! */ ;
931 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RELEASE);
932
933 /*
934 * Check for another packet.
935 */
936 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
937 if (packetno & FIFO_REMPTY)
938 return;
939 goto again;
940 }
941
942 /*
943 * Process an ioctl request.
944 */
945 int
946 smc91cxx_ioctl(ifp, cmd, data)
947 struct ifnet *ifp;
948 u_long cmd;
949 caddr_t data;
950 {
951 struct smc91cxx_softc *sc = ifp->if_softc;
952 struct ifaddr *ifa = (struct ifaddr *)data;
953 struct ifreq *ifr = (struct ifreq *)data;
954 int s, error = 0;
955
956 s = splimp();
957
958 switch (cmd) {
959 case SIOCSIFADDR:
960 ifp->if_flags |= IFF_UP;
961 switch (ifa->ifa_addr->sa_family) {
962 #ifdef INET
963 case AF_INET:
964 smc91cxx_init(sc);
965 arp_ifinit(ifp, ifa);
966 break;
967 #endif
968 #ifdef NS
969 case AF_NS:
970 {
971 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
972
973 if (ns_nullhost(*ina))
974 ina->x_host =
975 *(union ns_host *)LLADDR(ifp->if_sadl);
976 else {
977 bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
978 ETHER_ADDR_LEN);
979 }
980
981 /*
982 * Set new address. Reset, because the receiver
983 * has to be stopped before we can set the new
984 * MAC address.
985 */
986 smc91cxx_reset(sc);
987 break;
988 }
989 #endif
990 default:
991 smc91cxx_init(sc);
992 break;
993 }
994 break;
995
996 #if defined(CCITT) && defined(LLC)
997 case SIOCSIFCONF_X25:
998 ifp->if_flags |= IFF_UP;
999 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
1000 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
1001 if (error == 0)
1002 smc91cxx_init(sc);
1003 break;
1004 #endif
1005
1006 case SIOCSIFFLAGS:
1007 if ((ifp->if_flags & IFF_UP) == 0 &&
1008 (ifp->if_flags & IFF_RUNNING) != 0) {
1009 /*
1010 * If interface is marked down and it is running,
1011 * stop it.
1012 */
1013 smc91cxx_stop(sc);
1014 ifp->if_flags &= ~IFF_RUNNING;
1015 } else if ((ifp->if_flags & IFF_UP) != 0 &&
1016 (ifp->if_flags & IFF_RUNNING) == 0) {
1017 /*
1018 * If interface is marked up and it is stopped,
1019 * start it.
1020 */
1021 smc91cxx_init(sc);
1022 } else {
1023 /*
1024 * Reset the interface to pick up changes in any
1025 * other flags that affect hardware registers.
1026 */
1027 smc91cxx_reset(sc);
1028 }
1029 break;
1030
1031 case SIOCADDMULTI:
1032 case SIOCDELMULTI:
1033 error = (cmd == SIOCADDMULTI) ?
1034 ether_addmulti(ifr, &sc->sc_ec) :
1035 ether_delmulti(ifr, &sc->sc_ec);
1036 if (error == ENETRESET) {
1037 /*
1038 * Multicast list has changed; set the hardware
1039 * filter accordingly.
1040 */
1041 smc91cxx_reset(sc);
1042 error = 0;
1043 }
1044 break;
1045
1046 case SIOCGIFMEDIA:
1047 case SIOCSIFMEDIA:
1048 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1049 break;
1050
1051 default:
1052 error = EINVAL;
1053 break;
1054 }
1055
1056 splx(s);
1057 return (error);
1058 }
1059
1060 /*
1061 * Reset the interface.
1062 */
1063 void
1064 smc91cxx_reset(sc)
1065 struct smc91cxx_softc *sc;
1066 {
1067 int s;
1068
1069 s = splimp();
1070 smc91cxx_stop(sc);
1071 smc91cxx_init(sc);
1072 splx(s);
1073 }
1074
1075 /*
1076 * Watchdog timer.
1077 */
1078 void
1079 smc91cxx_watchdog(ifp)
1080 struct ifnet *ifp;
1081 {
1082 struct smc91cxx_softc *sc = ifp->if_softc;
1083
1084 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1085 ifp->if_oerrors++;
1086 smc91cxx_reset(sc);
1087 }
1088
1089 /*
1090 * Stop output on the interface.
1091 */
1092 void
1093 smc91cxx_stop(sc)
1094 struct smc91cxx_softc *sc;
1095 {
1096 bus_space_tag_t bst = sc->sc_bst;
1097 bus_space_handle_t bsh = sc->sc_bsh;
1098
1099 /*
1100 * Clear interrupt mask; disable all interrupts.
1101 */
1102 SMC_SELECT_BANK(sc, 2);
1103 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
1104
1105 /*
1106 * Disable transmitter and receiver.
1107 */
1108 SMC_SELECT_BANK(sc, 0);
1109 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
1110 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
1111
1112 /*
1113 * Cancel watchdog timer.
1114 */
1115 sc->sc_ec.ec_if.if_timer = 0;
1116 }
1117