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 --- |