Deleted Added
full compact
if_sn.c (199414) if_sn.c (199559)
1/*-
2 * Copyright (c) 1996 Gardner Buchanan <gbuchanan@shl.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1996 Gardner Buchanan <gbuchanan@shl.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/dev/sn/if_sn.c 199414 2009-11-17 18:22:14Z jhb $");
33__FBSDID("$FreeBSD: head/sys/dev/sn/if_sn.c 199559 2009-11-19 22:06:40Z jhb $");
34
35/*
36 * This is a driver for SMC's 9000 series of Ethernet adapters.
37 *
38 * This FreeBSD driver is derived from the smc9194 Linux driver by
39 * Erik Stahlman and is Copyright (C) 1996 by Erik Stahlman.
40 * This driver also shamelessly borrows from the FreeBSD ep driver
41 * which is Copyright (C) 1994 Herb Peyerl <hpeyerl@novatel.ca>

--- 35 unchanged lines hidden (view full) ---

77/*
78 * Multicast support by Kei TANAKA <kei@pal.xerox.com>
79 * Special thanks to itojun@itojun.org
80 */
81
82#include <sys/param.h>
83#include <sys/systm.h>
84#include <sys/errno.h>
34
35/*
36 * This is a driver for SMC's 9000 series of Ethernet adapters.
37 *
38 * This FreeBSD driver is derived from the smc9194 Linux driver by
39 * Erik Stahlman and is Copyright (C) 1996 by Erik Stahlman.
40 * This driver also shamelessly borrows from the FreeBSD ep driver
41 * which is Copyright (C) 1994 Herb Peyerl <hpeyerl@novatel.ca>

--- 35 unchanged lines hidden (view full) ---

77/*
78 * Multicast support by Kei TANAKA <kei@pal.xerox.com>
79 * Special thanks to itojun@itojun.org
80 */
81
82#include <sys/param.h>
83#include <sys/systm.h>
84#include <sys/errno.h>
85#include <sys/kernel.h>
85#include <sys/sockio.h>
86#include <sys/mbuf.h>
87#include <sys/socket.h>
88#include <sys/syslog.h>
89
90#include <sys/module.h>
91#include <sys/bus.h>
92

--- 23 unchanged lines hidden (view full) ---

116
117/* Exported variables */
118devclass_t sn_devclass;
119
120static int snioctl(struct ifnet * ifp, u_long, caddr_t);
121
122static void snresume(struct ifnet *);
123
86#include <sys/sockio.h>
87#include <sys/mbuf.h>
88#include <sys/socket.h>
89#include <sys/syslog.h>
90
91#include <sys/module.h>
92#include <sys/bus.h>
93

--- 23 unchanged lines hidden (view full) ---

117
118/* Exported variables */
119devclass_t sn_devclass;
120
121static int snioctl(struct ifnet * ifp, u_long, caddr_t);
122
123static void snresume(struct ifnet *);
124
125static void snintr_locked(struct sn_softc *);
124static void sninit_locked(void *);
125static void snstart_locked(struct ifnet *);
126
127static void sninit(void *);
128static void snread(struct ifnet *);
129static void snstart(struct ifnet *);
130static void snstop(struct sn_softc *);
126static void sninit_locked(void *);
127static void snstart_locked(struct ifnet *);
128
129static void sninit(void *);
130static void snread(struct ifnet *);
131static void snstart(struct ifnet *);
132static void snstop(struct sn_softc *);
131static void snwatchdog(struct ifnet *);
133static void snwatchdog(void *);
132
133static void sn_setmcast(struct sn_softc *);
134static int sn_getmcf(struct ifnet *ifp, u_char *mcf);
135
136/* I (GB) have been unlucky getting the hardware padding
137 * to work properly.
138 */
139#define SW_PAD

--- 25 unchanged lines hidden (view full) ---

165
166 ifp = sc->ifp = if_alloc(IFT_ETHER);
167 if (ifp == NULL) {
168 device_printf(dev, "can not if_alloc()\n");
169 return (ENOSPC);
170 }
171
172 SN_LOCK_INIT(sc);
134
135static void sn_setmcast(struct sn_softc *);
136static int sn_getmcf(struct ifnet *ifp, u_char *mcf);
137
138/* I (GB) have been unlucky getting the hardware padding
139 * to work properly.
140 */
141#define SW_PAD

--- 25 unchanged lines hidden (view full) ---

167
168 ifp = sc->ifp = if_alloc(IFT_ETHER);
169 if (ifp == NULL) {
170 device_printf(dev, "can not if_alloc()\n");
171 return (ENOSPC);
172 }
173
174 SN_LOCK_INIT(sc);
175 callout_init_mtx(&sc->watchdog, &sc->sc_mtx, 0);
173 snstop(sc);
174 sc->pages_wanted = -1;
175
176 if (bootverbose || 1) {
177 SMC_SELECT_BANK(sc, 3);
178 rev = (CSR_READ_2(sc, REVISION_REG_W) >> 4) & 0xf;
179 if (chip_ids[rev])
180 device_printf(dev, " %s ", chip_ids[rev]);

--- 16 unchanged lines hidden (view full) ---

197 p[i] = address & 0xFF;
198 }
199 ifp->if_softc = sc;
200 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
201 ifp->if_mtu = ETHERMTU;
202 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
203 ifp->if_start = snstart;
204 ifp->if_ioctl = snioctl;
176 snstop(sc);
177 sc->pages_wanted = -1;
178
179 if (bootverbose || 1) {
180 SMC_SELECT_BANK(sc, 3);
181 rev = (CSR_READ_2(sc, REVISION_REG_W) >> 4) & 0xf;
182 if (chip_ids[rev])
183 device_printf(dev, " %s ", chip_ids[rev]);

--- 16 unchanged lines hidden (view full) ---

200 p[i] = address & 0xFF;
201 }
202 ifp->if_softc = sc;
203 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
204 ifp->if_mtu = ETHERMTU;
205 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
206 ifp->if_start = snstart;
207 ifp->if_ioctl = snioctl;
205 ifp->if_watchdog = snwatchdog;
206 ifp->if_init = sninit;
207 ifp->if_baudrate = 10000000;
208 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
209 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
210 IFQ_SET_READY(&ifp->if_snd);
208 ifp->if_init = sninit;
209 ifp->if_baudrate = 10000000;
210 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
211 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
212 IFQ_SET_READY(&ifp->if_snd);
211 ifp->if_timer = 0;
212
213 ether_ifattach(ifp, eaddr);
214
215 /*
216 * Activate the interrupt so we can get card interrupts. This
217 * needs to be done last so that we don't have/hold the lock
218 * during startup to avoid LORs in the network layer.
219 */

--- 8 unchanged lines hidden (view full) ---

228
229
230int
231sn_detach(device_t dev)
232{
233 struct sn_softc *sc = device_get_softc(dev);
234 struct ifnet *ifp = sc->ifp;
235
213
214 ether_ifattach(ifp, eaddr);
215
216 /*
217 * Activate the interrupt so we can get card interrupts. This
218 * needs to be done last so that we don't have/hold the lock
219 * during startup to avoid LORs in the network layer.
220 */

--- 8 unchanged lines hidden (view full) ---

229
230
231int
232sn_detach(device_t dev)
233{
234 struct sn_softc *sc = device_get_softc(dev);
235 struct ifnet *ifp = sc->ifp;
236
236 snstop(sc);
237 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
238 ether_ifdetach(ifp);
237 ether_ifdetach(ifp);
238 SN_LOCK(sc);
239 snstop(sc);
240 SN_UNLOCK(sc);
241 callout_drain(&sc->watchdog);
239 sn_deactivate(dev);
240 if_free(ifp);
241 SN_LOCK_DESTROY(sc);
242 return 0;
243}
244
245static void
246sninit(void *xsc)

--- 90 unchanged lines hidden (view full) ---

337 sc->pages_wanted = -1;
338
339
340 /*
341 * Mark the interface running but not active.
342 */
343 ifp->if_drv_flags |= IFF_DRV_RUNNING;
344 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
242 sn_deactivate(dev);
243 if_free(ifp);
244 SN_LOCK_DESTROY(sc);
245 return 0;
246}
247
248static void
249sninit(void *xsc)

--- 90 unchanged lines hidden (view full) ---

340 sc->pages_wanted = -1;
341
342
343 /*
344 * Mark the interface running but not active.
345 */
346 ifp->if_drv_flags |= IFF_DRV_RUNNING;
347 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
348 callout_reset(&sc->watchdog, hz, snwatchdog, sc);
345
346 /*
347 * Attempt to push out any waiting packets.
348 */
349 snstart_locked(ifp);
350}
351
352static void

--- 105 unchanged lines hidden (view full) ---

458 * watchdog in case we miss the interrupt. We mark the
459 * interface active since there is no point in attempting an
460 * snstart() until after the memory is available.
461 */
462 mask = CSR_READ_1(sc, INTR_MASK_REG_B) | IM_ALLOC_INT;
463 CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
464 sc->intr_mask = mask;
465
349
350 /*
351 * Attempt to push out any waiting packets.
352 */
353 snstart_locked(ifp);
354}
355
356static void

--- 105 unchanged lines hidden (view full) ---

462 * watchdog in case we miss the interrupt. We mark the
463 * interface active since there is no point in attempting an
464 * snstart() until after the memory is available.
465 */
466 mask = CSR_READ_1(sc, INTR_MASK_REG_B) | IM_ALLOC_INT;
467 CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
468 sc->intr_mask = mask;
469
466 ifp->if_timer = 1;
470 sc->timer = 1;
467 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
468 sc->pages_wanted = numPages;
469 return;
470 }
471 /*
472 * The memory allocation completed. Check the results.
473 */
474 packet_no = CSR_READ_1(sc, ALLOC_RESULT_REG_B);

--- 68 unchanged lines hidden (view full) ---

543 */
544 mask = CSR_READ_1(sc, INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT);
545 CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
546 sc->intr_mask = mask;
547
548 CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_ENQUEUE);
549
550 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
471 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
472 sc->pages_wanted = numPages;
473 return;
474 }
475 /*
476 * The memory allocation completed. Check the results.
477 */
478 packet_no = CSR_READ_1(sc, ALLOC_RESULT_REG_B);

--- 68 unchanged lines hidden (view full) ---

547 */
548 mask = CSR_READ_1(sc, INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT);
549 CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
550 sc->intr_mask = mask;
551
552 CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_ENQUEUE);
553
554 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
551 ifp->if_timer = 1;
555 sc->timer = 1;
552
553 BPF_MTAP(ifp, top);
554
555 ifp->if_opackets++;
556 m_freem(top);
557
558
559readcheck:

--- 92 unchanged lines hidden (view full) ---

652
653 /*
654 * The memory allocation completed. Check the results. If it failed,
655 * we simply set a watchdog timer and hope for the best.
656 */
657 packet_no = CSR_READ_1(sc, ALLOC_RESULT_REG_B);
658 if (packet_no & ARR_FAILED) {
659 if_printf(ifp, "Memory allocation failed. Weird.\n");
556
557 BPF_MTAP(ifp, top);
558
559 ifp->if_opackets++;
560 m_freem(top);
561
562
563readcheck:

--- 92 unchanged lines hidden (view full) ---

656
657 /*
658 * The memory allocation completed. Check the results. If it failed,
659 * we simply set a watchdog timer and hope for the best.
660 */
661 packet_no = CSR_READ_1(sc, ALLOC_RESULT_REG_B);
662 if (packet_no & ARR_FAILED) {
663 if_printf(ifp, "Memory allocation failed. Weird.\n");
660 ifp->if_timer = 1;
664 sc->timer = 1;
661 goto try_start;
662 }
663 /*
664 * We have a packet number, so tell the card to use it.
665 */
666 CSR_WRITE_1(sc, PACKET_NUM_REG_B, packet_no);
667
668 /*

--- 81 unchanged lines hidden (view full) ---

750 m_freem(top);
751
752try_start:
753
754 /*
755 * Now pass control to snstart() to queue any additional packets
756 */
757 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
665 goto try_start;
666 }
667 /*
668 * We have a packet number, so tell the card to use it.
669 */
670 CSR_WRITE_1(sc, PACKET_NUM_REG_B, packet_no);
671
672 /*

--- 81 unchanged lines hidden (view full) ---

754 m_freem(top);
755
756try_start:
757
758 /*
759 * Now pass control to snstart() to queue any additional packets
760 */
761 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
758 snstart(ifp);
762 snstart_locked(ifp);
759
760 /*
761 * We've sent something, so we're active. Set a watchdog in case the
762 * TX_EMPTY interrupt is lost.
763 */
764 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
763
764 /*
765 * We've sent something, so we're active. Set a watchdog in case the
766 * TX_EMPTY interrupt is lost.
767 */
768 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
765 ifp->if_timer = 1;
769 sc->timer = 1;
766
767 return;
768}
769
770
771 return;
772}
773
770
771void
772sn_intr(void *arg)
773{
774void
775sn_intr(void *arg)
776{
774 int status, interrupts;
775 struct sn_softc *sc = (struct sn_softc *) arg;
777 struct sn_softc *sc = (struct sn_softc *) arg;
778
779 SN_LOCK(sc);
780 snintr_locked(sc);
781 SN_UNLOCK(sc);
782}
783
784static void
785snintr_locked(struct sn_softc *sc)
786{
787 int status, interrupts;
776 struct ifnet *ifp = sc->ifp;
777
778 /*
779 * Chip state registers
780 */
781 uint8_t mask;
782 uint8_t packet_no;
783 uint16_t tx_status;
784 uint16_t card_stats;
785
788 struct ifnet *ifp = sc->ifp;
789
790 /*
791 * Chip state registers
792 */
793 uint8_t mask;
794 uint8_t packet_no;
795 uint16_t tx_status;
796 uint16_t card_stats;
797
786 SN_LOCK(sc);
787
788 /*
789 * Clear the watchdog.
790 */
798 /*
799 * Clear the watchdog.
800 */
791 ifp->if_timer = 0;
801 sc->timer = 0;
792
793 SMC_SELECT_BANK(sc, 2);
794
795 /*
796 * Obtain the current interrupt mask and clear the hardware mask
797 * while servicing interrupts.
798 */
799 mask = CSR_READ_1(sc, INTR_MASK_REG_B);

--- 176 unchanged lines hidden (view full) ---

976 * during this interrupt. Note that the hardware mask, which was set
977 * to 0x00 at the start of this service routine, may have been
978 * updated by one or more of the interrupt handers and we must let
979 * those new interrupts stay enabled here.
980 */
981 mask |= CSR_READ_1(sc, INTR_MASK_REG_B);
982 CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
983 sc->intr_mask = mask;
802
803 SMC_SELECT_BANK(sc, 2);
804
805 /*
806 * Obtain the current interrupt mask and clear the hardware mask
807 * while servicing interrupts.
808 */
809 mask = CSR_READ_1(sc, INTR_MASK_REG_B);

--- 176 unchanged lines hidden (view full) ---

986 * during this interrupt. Note that the hardware mask, which was set
987 * to 0x00 at the start of this service routine, may have been
988 * updated by one or more of the interrupt handers and we must let
989 * those new interrupts stay enabled here.
990 */
991 mask |= CSR_READ_1(sc, INTR_MASK_REG_B);
992 CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
993 sc->intr_mask = mask;
984 SN_UNLOCK(sc);
985}
986
987static void
988snread(struct ifnet *ifp)
989{
990 struct sn_softc *sc = ifp->if_softc;
991 struct ether_header *eh;
992 struct mbuf *m;

--- 138 unchanged lines hidden (view full) ---

1131 struct sn_softc *sc = ifp->if_softc;
1132 int error = 0;
1133
1134 switch (cmd) {
1135 case SIOCSIFFLAGS:
1136 SN_LOCK(sc);
1137 if ((ifp->if_flags & IFF_UP) == 0 &&
1138 ifp->if_drv_flags & IFF_DRV_RUNNING) {
994}
995
996static void
997snread(struct ifnet *ifp)
998{
999 struct sn_softc *sc = ifp->if_softc;
1000 struct ether_header *eh;
1001 struct mbuf *m;

--- 138 unchanged lines hidden (view full) ---

1140 struct sn_softc *sc = ifp->if_softc;
1141 int error = 0;
1142
1143 switch (cmd) {
1144 case SIOCSIFFLAGS:
1145 SN_LOCK(sc);
1146 if ((ifp->if_flags & IFF_UP) == 0 &&
1147 ifp->if_drv_flags & IFF_DRV_RUNNING) {
1139 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1140 snstop(sc);
1141 } else {
1142 /* reinitialize card on any parameter change */
1143 sninit_locked(sc);
1144 }
1145 SN_UNLOCK(sc);
1146 break;
1147

--- 8 unchanged lines hidden (view full) ---

1156 default:
1157 error = ether_ioctl(ifp, cmd, data);
1158 break;
1159 }
1160 return (error);
1161}
1162
1163static void
1148 snstop(sc);
1149 } else {
1150 /* reinitialize card on any parameter change */
1151 sninit_locked(sc);
1152 }
1153 SN_UNLOCK(sc);
1154 break;
1155

--- 8 unchanged lines hidden (view full) ---

1164 default:
1165 error = ether_ioctl(ifp, cmd, data);
1166 break;
1167 }
1168 return (error);
1169}
1170
1171static void
1164snwatchdog(struct ifnet *ifp)
1172snwatchdog(void *arg)
1165{
1173{
1166 sn_intr(ifp->if_softc);
1174 struct sn_softc *sc;
1175
1176 sc = arg;
1177 SN_ASSERT_LOCKED(sc);
1178 callout_reset(&sc->watchdog, hz, snwatchdog, sc);
1179 if (sc->timer == 0 || --sc->timer > 0)
1180 return;
1181 snintr_locked(sc);
1167}
1168
1169
1170/* 1. zero the interrupt mask
1171 * 2. clear the enable receive flag
1172 * 3. clear the enable xmit flags
1173 */
1174static void

--- 13 unchanged lines hidden (view full) ---

1188 */
1189 SMC_SELECT_BANK(sc, 0);
1190 CSR_WRITE_2(sc, RECV_CONTROL_REG_W, 0x0000);
1191 CSR_WRITE_2(sc, TXMIT_CONTROL_REG_W, 0x0000);
1192
1193 /*
1194 * Cancel watchdog.
1195 */
1182}
1183
1184
1185/* 1. zero the interrupt mask
1186 * 2. clear the enable receive flag
1187 * 3. clear the enable xmit flags
1188 */
1189static void

--- 13 unchanged lines hidden (view full) ---

1203 */
1204 SMC_SELECT_BANK(sc, 0);
1205 CSR_WRITE_2(sc, RECV_CONTROL_REG_W, 0x0000);
1206 CSR_WRITE_2(sc, TXMIT_CONTROL_REG_W, 0x0000);
1207
1208 /*
1209 * Cancel watchdog.
1210 */
1196 ifp->if_timer = 0;
1211 sc->timer = 0;
1212 callout_stop(&sc->watchdog);
1213 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1197}
1198
1199
1200int
1201sn_activate(device_t dev)
1202{
1203 struct sn_softc *sc = device_get_softc(dev);
1204

--- 219 unchanged lines hidden ---
1214}
1215
1216
1217int
1218sn_activate(device_t dev)
1219{
1220 struct sn_softc *sc = device_get_softc(dev);
1221

--- 219 unchanged lines hidden ---