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