1/* $NetBSD: smc90cx6.c,v 1.38 2001/07/07 15:57:53 thorpej Exp $ */ 2 3#include <sys/cdefs.h>
| 1/* $NetBSD: smc90cx6.c,v 1.38 2001/07/07 15:57:53 thorpej Exp $ */ 2 3#include <sys/cdefs.h>
|
4__FBSDID("$FreeBSD: head/sys/dev/cm/smc90cx6.c 147256 2005-06-10 16:49:24Z brooks $");
| 4__FBSDID("$FreeBSD: head/sys/dev/cm/smc90cx6.c 148887 2005-08-09 10:20:02Z rwatson $");
|
5 6/*- 7 * Copyright (c) 1994, 1995, 1998 The NetBSD Foundation, Inc. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Ignatios Souvatzis. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the NetBSD 24 * Foundation, Inc. and its contributors. 25 * 4. Neither the name of The NetBSD Foundation nor the names of its 26 * contributors may be used to endorse or promote products derived 27 * from this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 * POSSIBILITY OF SUCH DAMAGE. 40 */ 41 42/* 43 * Chip core driver for the SMC90c26 / SMC90c56 (and SMC90c66 in '56 44 * compatibility mode) boards 45 */ 46 47/* #define CMSOFTCOPY */ 48#define CMRETRANSMIT /**/ 49/* #define CM_DEBUG */ 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/sockio.h> 54#include <sys/mbuf.h> 55#include <sys/module.h> 56#include <sys/kernel.h> 57#include <sys/socket.h> 58#include <sys/syslog.h> 59#include <sys/bus.h> 60 61#include <machine/bus.h> 62#include <sys/rman.h> 63#include <machine/resource.h> 64 65#if __FreeBSD_version < 500000 66#include <machine/clock.h> 67#endif 68 69#include <net/if.h> 70#include <net/if_dl.h> 71#include <net/if_types.h> 72#include <net/if_arc.h> 73 74#include <dev/cm/smc90cx6reg.h> 75#include <dev/cm/smc90cx6var.h> 76 77MODULE_DEPEND(if_cm, arcnet, 1, 1, 1); 78 79/* these should be elsewhere */ 80 81#define ARC_MIN_LEN 1 82#define ARC_MIN_FORBID_LEN 254 83#define ARC_MAX_FORBID_LEN 256 84#define ARC_MAX_LEN 508 85#define ARC_ADDR_LEN 1 86 87/* for watchdog timer. This should be more than enough. */ 88#define ARCTIMEOUT (5*IFNET_SLOWHZ) 89 90/* short notation */ 91 92#define GETREG(off) \ 93 bus_space_read_1(rman_get_bustag((sc)->port_res), \ 94 rman_get_bushandle((sc)->port_res), \ 95 (off)) 96#define PUTREG(off, value) \ 97 bus_space_write_1(rman_get_bustag((sc)->port_res), \ 98 rman_get_bushandle((sc)->port_res), \ 99 (off), (value)) 100#define GETMEM(off) \ 101 bus_space_read_1(rman_get_bustag((sc)->mem_res), \ 102 rman_get_bushandle((sc)->mem_res), \ 103 (off)) 104#define PUTMEM(off, value) \ 105 bus_space_write_1(rman_get_bustag((sc)->mem_res), \ 106 rman_get_bushandle((sc)->mem_res), \ 107 (off), (value)) 108 109devclass_t cm_devclass; 110 111/* 112 * This currently uses 2 bufs for tx, 2 for rx 113 * 114 * New rx protocol: 115 * 116 * rx has a fillcount variable. If fillcount > (NRXBUF-1), 117 * rx can be switched off from rx hard int. 118 * Else rx is restarted on the other receiver. 119 * rx soft int counts down. if it is == (NRXBUF-1), it restarts 120 * the receiver. 121 * To ensure packet ordering (we need that for 1201 later), we have a counter 122 * which is incremented modulo 256 on each receive and a per buffer 123 * variable, which is set to the counter on filling. The soft int can 124 * compare both values to determine the older packet. 125 * 126 * Transmit direction: 127 * 128 * cm_start checks tx_fillcount 129 * case 2: return 130 * 131 * else fill tx_act ^ 1 && inc tx_fillcount 132 * 133 * check tx_fillcount again.
| 5 6/*- 7 * Copyright (c) 1994, 1995, 1998 The NetBSD Foundation, Inc. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Ignatios Souvatzis. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the NetBSD 24 * Foundation, Inc. and its contributors. 25 * 4. Neither the name of The NetBSD Foundation nor the names of its 26 * contributors may be used to endorse or promote products derived 27 * from this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 * POSSIBILITY OF SUCH DAMAGE. 40 */ 41 42/* 43 * Chip core driver for the SMC90c26 / SMC90c56 (and SMC90c66 in '56 44 * compatibility mode) boards 45 */ 46 47/* #define CMSOFTCOPY */ 48#define CMRETRANSMIT /**/ 49/* #define CM_DEBUG */ 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/sockio.h> 54#include <sys/mbuf.h> 55#include <sys/module.h> 56#include <sys/kernel.h> 57#include <sys/socket.h> 58#include <sys/syslog.h> 59#include <sys/bus.h> 60 61#include <machine/bus.h> 62#include <sys/rman.h> 63#include <machine/resource.h> 64 65#if __FreeBSD_version < 500000 66#include <machine/clock.h> 67#endif 68 69#include <net/if.h> 70#include <net/if_dl.h> 71#include <net/if_types.h> 72#include <net/if_arc.h> 73 74#include <dev/cm/smc90cx6reg.h> 75#include <dev/cm/smc90cx6var.h> 76 77MODULE_DEPEND(if_cm, arcnet, 1, 1, 1); 78 79/* these should be elsewhere */ 80 81#define ARC_MIN_LEN 1 82#define ARC_MIN_FORBID_LEN 254 83#define ARC_MAX_FORBID_LEN 256 84#define ARC_MAX_LEN 508 85#define ARC_ADDR_LEN 1 86 87/* for watchdog timer. This should be more than enough. */ 88#define ARCTIMEOUT (5*IFNET_SLOWHZ) 89 90/* short notation */ 91 92#define GETREG(off) \ 93 bus_space_read_1(rman_get_bustag((sc)->port_res), \ 94 rman_get_bushandle((sc)->port_res), \ 95 (off)) 96#define PUTREG(off, value) \ 97 bus_space_write_1(rman_get_bustag((sc)->port_res), \ 98 rman_get_bushandle((sc)->port_res), \ 99 (off), (value)) 100#define GETMEM(off) \ 101 bus_space_read_1(rman_get_bustag((sc)->mem_res), \ 102 rman_get_bushandle((sc)->mem_res), \ 103 (off)) 104#define PUTMEM(off, value) \ 105 bus_space_write_1(rman_get_bustag((sc)->mem_res), \ 106 rman_get_bushandle((sc)->mem_res), \ 107 (off), (value)) 108 109devclass_t cm_devclass; 110 111/* 112 * This currently uses 2 bufs for tx, 2 for rx 113 * 114 * New rx protocol: 115 * 116 * rx has a fillcount variable. If fillcount > (NRXBUF-1), 117 * rx can be switched off from rx hard int. 118 * Else rx is restarted on the other receiver. 119 * rx soft int counts down. if it is == (NRXBUF-1), it restarts 120 * the receiver. 121 * To ensure packet ordering (we need that for 1201 later), we have a counter 122 * which is incremented modulo 256 on each receive and a per buffer 123 * variable, which is set to the counter on filling. The soft int can 124 * compare both values to determine the older packet. 125 * 126 * Transmit direction: 127 * 128 * cm_start checks tx_fillcount 129 * case 2: return 130 * 131 * else fill tx_act ^ 1 && inc tx_fillcount 132 * 133 * check tx_fillcount again.
|
134 * case 2: set IFF_OACTIVE to stop arc_output from filling us.
| 134 * case 2: set IFF_DRV_OACTIVE to stop arc_output from filling us.
|
135 * case 1: start tx 136 * 137 * tint clears IFF_OCATIVE, decrements and checks tx_fillcount 138 * case 1: start tx on tx_act ^ 1, softcall cm_start 139 * case 0: softcall cm_start 140 * 141 * #define fill(i) get mbuf && copy mbuf to chip(i) 142 */ 143 144void cm_init(void *); 145void cm_reset(struct cm_softc *); 146void cm_start(struct ifnet *); 147int cm_ioctl(struct ifnet *, unsigned long, caddr_t); 148void cm_watchdog(struct ifnet *); 149void cm_srint(void *vsc); 150static void cm_tint(struct cm_softc *, int); 151void cm_reconwatch(void *); 152 153int 154cm_probe(dev) 155 device_t dev; 156{ 157 int error; 158 struct cm_softc *sc = device_get_softc(dev); 159 160 error = cm_alloc_port(dev, 0, CM_IO_PORTS); 161 if (error) 162 return error; 163 164 if (GETREG(CMSTAT) == 0xff) 165 return ENXIO; 166 167 error = cm_alloc_memory(dev, 0, 0x800); 168 if (error) 169 return error; 170 171 return 0; 172} 173 174/* 175 * Allocate a port resource with the given resource id. 176 */ 177int 178cm_alloc_port(dev, rid, size) 179 device_t dev; 180 int rid; 181 int size; 182{ 183 struct cm_softc *sc = device_get_softc(dev); 184 struct resource *res; 185 186 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 187 0ul, ~0ul, size, RF_ACTIVE); 188 if (res) { 189 sc->port_rid = rid; 190 sc->port_res = res; 191 sc->port_used = size; 192 return (0); 193 } else { 194 return (ENOENT); 195 } 196} 197 198/* 199 * Allocate a memory resource with the given resource id. 200 */ 201int 202cm_alloc_memory(dev, rid, size) 203 device_t dev; 204 int rid; 205 int size; 206{ 207 struct cm_softc *sc = device_get_softc(dev); 208 struct resource *res; 209 210 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 211 0ul, ~0ul, size, RF_ACTIVE); 212 if (res) { 213 sc->mem_rid = rid; 214 sc->mem_res = res; 215 sc->mem_used = size; 216 return (0); 217 } else { 218 return (ENOENT); 219 } 220} 221 222/* 223 * Allocate an irq resource with the given resource id. 224 */ 225int 226cm_alloc_irq(dev, rid) 227 device_t dev; 228 int rid; 229{ 230 struct cm_softc *sc = device_get_softc(dev); 231 struct resource *res; 232 233 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 234 if (res) { 235 sc->irq_rid = rid; 236 sc->irq_res = res; 237 return (0); 238 } else { 239 return (ENOENT); 240 } 241} 242 243/* 244 * Release all resources 245 */ 246void 247cm_release_resources(dev) 248 device_t dev; 249{ 250 struct cm_softc *sc = device_get_softc(dev); 251 252 if (sc->port_res) { 253 bus_deactivate_resource(dev, SYS_RES_IOPORT, 254 sc->port_rid, sc->port_res); 255 bus_release_resource(dev, SYS_RES_IOPORT, 256 sc->port_rid, sc->port_res); 257 sc->port_res = 0; 258 } 259 if (sc->mem_res) { 260 bus_deactivate_resource(dev, SYS_RES_MEMORY, 261 sc->mem_rid, sc->mem_res); 262 bus_release_resource(dev, SYS_RES_MEMORY, 263 sc->mem_rid, sc->mem_res); 264 sc->mem_res = 0; 265 } 266 if (sc->irq_res) { 267 bus_deactivate_resource(dev, SYS_RES_IRQ, 268 sc->irq_rid, sc->irq_res); 269 bus_release_resource(dev, SYS_RES_IRQ, 270 sc->irq_rid, sc->irq_res); 271 sc->irq_res = 0; 272 } 273} 274 275int 276cm_attach(dev) 277 device_t dev; 278{ 279 struct cm_softc *sc = device_get_softc(dev); 280 struct ifnet *ifp; 281 int s; 282 u_int8_t linkaddress; 283 284 ifp = sc->sc_ifp = if_alloc(IFT_ARCNET); 285 if (ifp == NULL) { 286 return (ENOSPC); 287 } 288 289 s = splhigh(); 290 291 /* 292 * read the arcnet address from the board 293 */ 294 295 GETREG(CMRESET); 296 do { 297 DELAY(200); 298 } while (!(GETREG(CMSTAT) & CM_POR)); 299 300 linkaddress = GETMEM(CMMACOFF); 301 302 /* clear the int mask... */ 303 304 sc->sc_intmask = 0; 305 PUTREG(CMSTAT, 0); 306 307 PUTREG(CMCMD, CM_CONF(CONF_LONG)); 308 PUTREG(CMCMD, CM_CLR(CLR_POR|CLR_RECONFIG)); 309 sc->sc_recontime = sc->sc_reconcount = 0; 310 311 /* and reenable kernel int level */ 312 splx(s); 313 314 /* 315 * set interface to stopped condition (reset) 316 */ 317 cm_stop(sc); 318 319 ifp->if_softc = sc; 320 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 321 ifp->if_output = arc_output; 322 ifp->if_start = cm_start; 323 ifp->if_ioctl = cm_ioctl; 324 ifp->if_watchdog = cm_watchdog; 325 ifp->if_init = cm_init; 326 /* XXX IFQ_SET_READY(&ifp->if_snd); */ 327 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 328 ifp->if_timer = 0; 329 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NEEDSGIANT; 330 331 arc_ifattach(ifp, linkaddress); 332 333#ifdef CMSOFTCOPY 334 sc->sc_rxcookie = softintr_establish(IPL_SOFTNET, cm_srint, sc); 335 sc->sc_txcookie = softintr_establish(IPL_SOFTNET, 336 (void (*)(void *))cm_start, ifp); 337#endif 338 339#if __FreeBSD_version < 500000 340 callout_init(&sc->sc_recon_ch); 341#else 342 callout_init(&sc->sc_recon_ch, 0); 343#endif 344 345 if_printf(ifp, "link addr 0x%02x (%d)\n", linkaddress, linkaddress); 346 return 0; 347} 348 349/* 350 * Initialize device 351 * 352 */ 353void 354cm_init(xsc) 355 void *xsc; 356{ 357 struct cm_softc *sc = (struct cm_softc *)xsc; 358 struct ifnet *ifp; 359 int s; 360 361 ifp = sc->sc_ifp; 362
| 135 * case 1: start tx 136 * 137 * tint clears IFF_OCATIVE, decrements and checks tx_fillcount 138 * case 1: start tx on tx_act ^ 1, softcall cm_start 139 * case 0: softcall cm_start 140 * 141 * #define fill(i) get mbuf && copy mbuf to chip(i) 142 */ 143 144void cm_init(void *); 145void cm_reset(struct cm_softc *); 146void cm_start(struct ifnet *); 147int cm_ioctl(struct ifnet *, unsigned long, caddr_t); 148void cm_watchdog(struct ifnet *); 149void cm_srint(void *vsc); 150static void cm_tint(struct cm_softc *, int); 151void cm_reconwatch(void *); 152 153int 154cm_probe(dev) 155 device_t dev; 156{ 157 int error; 158 struct cm_softc *sc = device_get_softc(dev); 159 160 error = cm_alloc_port(dev, 0, CM_IO_PORTS); 161 if (error) 162 return error; 163 164 if (GETREG(CMSTAT) == 0xff) 165 return ENXIO; 166 167 error = cm_alloc_memory(dev, 0, 0x800); 168 if (error) 169 return error; 170 171 return 0; 172} 173 174/* 175 * Allocate a port resource with the given resource id. 176 */ 177int 178cm_alloc_port(dev, rid, size) 179 device_t dev; 180 int rid; 181 int size; 182{ 183 struct cm_softc *sc = device_get_softc(dev); 184 struct resource *res; 185 186 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 187 0ul, ~0ul, size, RF_ACTIVE); 188 if (res) { 189 sc->port_rid = rid; 190 sc->port_res = res; 191 sc->port_used = size; 192 return (0); 193 } else { 194 return (ENOENT); 195 } 196} 197 198/* 199 * Allocate a memory resource with the given resource id. 200 */ 201int 202cm_alloc_memory(dev, rid, size) 203 device_t dev; 204 int rid; 205 int size; 206{ 207 struct cm_softc *sc = device_get_softc(dev); 208 struct resource *res; 209 210 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 211 0ul, ~0ul, size, RF_ACTIVE); 212 if (res) { 213 sc->mem_rid = rid; 214 sc->mem_res = res; 215 sc->mem_used = size; 216 return (0); 217 } else { 218 return (ENOENT); 219 } 220} 221 222/* 223 * Allocate an irq resource with the given resource id. 224 */ 225int 226cm_alloc_irq(dev, rid) 227 device_t dev; 228 int rid; 229{ 230 struct cm_softc *sc = device_get_softc(dev); 231 struct resource *res; 232 233 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 234 if (res) { 235 sc->irq_rid = rid; 236 sc->irq_res = res; 237 return (0); 238 } else { 239 return (ENOENT); 240 } 241} 242 243/* 244 * Release all resources 245 */ 246void 247cm_release_resources(dev) 248 device_t dev; 249{ 250 struct cm_softc *sc = device_get_softc(dev); 251 252 if (sc->port_res) { 253 bus_deactivate_resource(dev, SYS_RES_IOPORT, 254 sc->port_rid, sc->port_res); 255 bus_release_resource(dev, SYS_RES_IOPORT, 256 sc->port_rid, sc->port_res); 257 sc->port_res = 0; 258 } 259 if (sc->mem_res) { 260 bus_deactivate_resource(dev, SYS_RES_MEMORY, 261 sc->mem_rid, sc->mem_res); 262 bus_release_resource(dev, SYS_RES_MEMORY, 263 sc->mem_rid, sc->mem_res); 264 sc->mem_res = 0; 265 } 266 if (sc->irq_res) { 267 bus_deactivate_resource(dev, SYS_RES_IRQ, 268 sc->irq_rid, sc->irq_res); 269 bus_release_resource(dev, SYS_RES_IRQ, 270 sc->irq_rid, sc->irq_res); 271 sc->irq_res = 0; 272 } 273} 274 275int 276cm_attach(dev) 277 device_t dev; 278{ 279 struct cm_softc *sc = device_get_softc(dev); 280 struct ifnet *ifp; 281 int s; 282 u_int8_t linkaddress; 283 284 ifp = sc->sc_ifp = if_alloc(IFT_ARCNET); 285 if (ifp == NULL) { 286 return (ENOSPC); 287 } 288 289 s = splhigh(); 290 291 /* 292 * read the arcnet address from the board 293 */ 294 295 GETREG(CMRESET); 296 do { 297 DELAY(200); 298 } while (!(GETREG(CMSTAT) & CM_POR)); 299 300 linkaddress = GETMEM(CMMACOFF); 301 302 /* clear the int mask... */ 303 304 sc->sc_intmask = 0; 305 PUTREG(CMSTAT, 0); 306 307 PUTREG(CMCMD, CM_CONF(CONF_LONG)); 308 PUTREG(CMCMD, CM_CLR(CLR_POR|CLR_RECONFIG)); 309 sc->sc_recontime = sc->sc_reconcount = 0; 310 311 /* and reenable kernel int level */ 312 splx(s); 313 314 /* 315 * set interface to stopped condition (reset) 316 */ 317 cm_stop(sc); 318 319 ifp->if_softc = sc; 320 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 321 ifp->if_output = arc_output; 322 ifp->if_start = cm_start; 323 ifp->if_ioctl = cm_ioctl; 324 ifp->if_watchdog = cm_watchdog; 325 ifp->if_init = cm_init; 326 /* XXX IFQ_SET_READY(&ifp->if_snd); */ 327 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 328 ifp->if_timer = 0; 329 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NEEDSGIANT; 330 331 arc_ifattach(ifp, linkaddress); 332 333#ifdef CMSOFTCOPY 334 sc->sc_rxcookie = softintr_establish(IPL_SOFTNET, cm_srint, sc); 335 sc->sc_txcookie = softintr_establish(IPL_SOFTNET, 336 (void (*)(void *))cm_start, ifp); 337#endif 338 339#if __FreeBSD_version < 500000 340 callout_init(&sc->sc_recon_ch); 341#else 342 callout_init(&sc->sc_recon_ch, 0); 343#endif 344 345 if_printf(ifp, "link addr 0x%02x (%d)\n", linkaddress, linkaddress); 346 return 0; 347} 348 349/* 350 * Initialize device 351 * 352 */ 353void 354cm_init(xsc) 355 void *xsc; 356{ 357 struct cm_softc *sc = (struct cm_softc *)xsc; 358 struct ifnet *ifp; 359 int s; 360 361 ifp = sc->sc_ifp; 362
|
363 if ((ifp->if_flags & IFF_RUNNING) == 0) {
| 363 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
364 s = splimp();
| 364 s = splimp();
|
365 ifp->if_flags |= IFF_RUNNING;
| 365 ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
366 cm_reset(sc); 367 cm_start(ifp); 368 splx(s); 369 } 370} 371 372/* 373 * Reset the interface... 374 * 375 * this assumes that it is called inside a critical section... 376 * 377 */ 378void 379cm_reset(sc) 380 struct cm_softc *sc; 381{ 382 struct ifnet *ifp; 383 int linkaddress; 384 385 ifp = sc->sc_ifp; 386 387#ifdef CM_DEBUG 388 if_printf(ifp, "reset\n"); 389#endif 390 /* stop and restart hardware */ 391 392 GETREG(CMRESET); 393 do { 394 DELAY(200); 395 } while (!(GETREG(CMSTAT) & CM_POR)); 396 397 linkaddress = GETMEM(CMMACOFF); 398 399#if defined(CM_DEBUG) && (CM_DEBUG > 2) 400 if_printf(ifp, "reset: card reset, link addr = 0x%02x (%d)\n", 401 linkaddress, linkaddress); 402#endif 403 404 /* tell the routing level about the (possibly changed) link address */ 405 arc_storelladdr(ifp, linkaddress); 406 arc_frag_init(ifp); 407 408 /* POR is NMI, but we need it below: */ 409 sc->sc_intmask = CM_RECON|CM_POR; 410 PUTREG(CMSTAT, sc->sc_intmask); 411 PUTREG(CMCMD, CM_CONF(CONF_LONG)); 412 413#ifdef CM_DEBUG 414 if_printf(ifp, "reset: chip configured, status=0x%02x\n", 415 GETREG(CMSTAT)); 416#endif 417 PUTREG(CMCMD, CM_CLR(CLR_POR|CLR_RECONFIG)); 418 419#ifdef CM_DEBUG 420 if_printf(ifp, "reset: bits cleared, status=0x%02x\n", 421 GETREG(CMSTAT)); 422#endif 423 424 sc->sc_reconcount_excessive = ARC_EXCESSIVE_RECONS; 425 426 /* start receiver */ 427 428 sc->sc_intmask |= CM_RI; 429 sc->sc_rx_fillcount = 0; 430 sc->sc_rx_act = 2; 431 432 PUTREG(CMCMD, CM_RXBC(2)); 433 PUTREG(CMSTAT, sc->sc_intmask); 434 435#ifdef CM_DEBUG 436 if_printf(ifp, "reset: started receiver, status=0x%02x\n", 437 GETREG(CMSTAT)); 438#endif 439 440 /* and init transmitter status */ 441 sc->sc_tx_act = 0; 442 sc->sc_tx_fillcount = 0; 443
| 366 cm_reset(sc); 367 cm_start(ifp); 368 splx(s); 369 } 370} 371 372/* 373 * Reset the interface... 374 * 375 * this assumes that it is called inside a critical section... 376 * 377 */ 378void 379cm_reset(sc) 380 struct cm_softc *sc; 381{ 382 struct ifnet *ifp; 383 int linkaddress; 384 385 ifp = sc->sc_ifp; 386 387#ifdef CM_DEBUG 388 if_printf(ifp, "reset\n"); 389#endif 390 /* stop and restart hardware */ 391 392 GETREG(CMRESET); 393 do { 394 DELAY(200); 395 } while (!(GETREG(CMSTAT) & CM_POR)); 396 397 linkaddress = GETMEM(CMMACOFF); 398 399#if defined(CM_DEBUG) && (CM_DEBUG > 2) 400 if_printf(ifp, "reset: card reset, link addr = 0x%02x (%d)\n", 401 linkaddress, linkaddress); 402#endif 403 404 /* tell the routing level about the (possibly changed) link address */ 405 arc_storelladdr(ifp, linkaddress); 406 arc_frag_init(ifp); 407 408 /* POR is NMI, but we need it below: */ 409 sc->sc_intmask = CM_RECON|CM_POR; 410 PUTREG(CMSTAT, sc->sc_intmask); 411 PUTREG(CMCMD, CM_CONF(CONF_LONG)); 412 413#ifdef CM_DEBUG 414 if_printf(ifp, "reset: chip configured, status=0x%02x\n", 415 GETREG(CMSTAT)); 416#endif 417 PUTREG(CMCMD, CM_CLR(CLR_POR|CLR_RECONFIG)); 418 419#ifdef CM_DEBUG 420 if_printf(ifp, "reset: bits cleared, status=0x%02x\n", 421 GETREG(CMSTAT)); 422#endif 423 424 sc->sc_reconcount_excessive = ARC_EXCESSIVE_RECONS; 425 426 /* start receiver */ 427 428 sc->sc_intmask |= CM_RI; 429 sc->sc_rx_fillcount = 0; 430 sc->sc_rx_act = 2; 431 432 PUTREG(CMCMD, CM_RXBC(2)); 433 PUTREG(CMSTAT, sc->sc_intmask); 434 435#ifdef CM_DEBUG 436 if_printf(ifp, "reset: started receiver, status=0x%02x\n", 437 GETREG(CMSTAT)); 438#endif 439 440 /* and init transmitter status */ 441 sc->sc_tx_act = 0; 442 sc->sc_tx_fillcount = 0; 443
|
444 ifp->if_flags |= IFF_RUNNING; 445 ifp->if_flags &= ~IFF_OACTIVE;
| 444 ifp->if_drv_flags |= IFF_DRV_RUNNING; 445 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
446 447 cm_start(ifp); 448} 449 450/* 451 * Take interface offline 452 */ 453void 454cm_stop(sc) 455 struct cm_softc *sc; 456{ 457 /* Stop the interrupts */ 458 PUTREG(CMSTAT, 0); 459 460 /* Stop the interface */ 461 GETREG(CMRESET); 462 463 /* Stop watchdog timer */ 464 sc->sc_ifp->if_timer = 0; 465} 466 467/* 468 * Start output on interface. Get another datagram to send 469 * off the interface queue, and copy it to the 470 * interface becore starting the output 471 * 472 * this assumes that it is called inside a critical section... 473 * XXX hm... does it still? 474 * 475 */ 476void 477cm_start(ifp) 478 struct ifnet *ifp; 479{ 480 struct cm_softc *sc = ifp->if_softc; 481 struct mbuf *m,*mp; 482 483 int cm_ram_ptr; 484 int len, tlen, offset, s, buffer; 485#ifdef CMTIMINGS 486 u_long copystart, lencopy, perbyte; 487#endif 488 489#if defined(CM_DEBUG) && (CM_DEBUG > 3) 490 if_printf(ifp, "start(%p)\n", ifp); 491#endif 492
| 446 447 cm_start(ifp); 448} 449 450/* 451 * Take interface offline 452 */ 453void 454cm_stop(sc) 455 struct cm_softc *sc; 456{ 457 /* Stop the interrupts */ 458 PUTREG(CMSTAT, 0); 459 460 /* Stop the interface */ 461 GETREG(CMRESET); 462 463 /* Stop watchdog timer */ 464 sc->sc_ifp->if_timer = 0; 465} 466 467/* 468 * Start output on interface. Get another datagram to send 469 * off the interface queue, and copy it to the 470 * interface becore starting the output 471 * 472 * this assumes that it is called inside a critical section... 473 * XXX hm... does it still? 474 * 475 */ 476void 477cm_start(ifp) 478 struct ifnet *ifp; 479{ 480 struct cm_softc *sc = ifp->if_softc; 481 struct mbuf *m,*mp; 482 483 int cm_ram_ptr; 484 int len, tlen, offset, s, buffer; 485#ifdef CMTIMINGS 486 u_long copystart, lencopy, perbyte; 487#endif 488 489#if defined(CM_DEBUG) && (CM_DEBUG > 3) 490 if_printf(ifp, "start(%p)\n", ifp); 491#endif 492
|
493 if ((ifp->if_flags & IFF_RUNNING) == 0)
| 493 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
494 return; 495 496 s = splimp(); 497 498 if (sc->sc_tx_fillcount >= 2) { 499 splx(s); 500 return; 501 } 502 503 m = arc_frag_next(ifp); 504 buffer = sc->sc_tx_act ^ 1; 505 506 splx(s); 507 508 if (m == 0) 509 return; 510 511#ifdef CM_DEBUG 512 if (m->m_len < ARC_HDRLEN) 513 m = m_pullup(m, ARC_HDRLEN);/* gcc does structure padding */ 514 if_printf(ifp, "start: filling %d from %d to %d type %d\n", 515 buffer, mtod(m, u_char *)[0], 516 mtod(m, u_char *)[1], mtod(m, u_char *)[2]); 517#else 518 if (m->m_len < 2) 519 m = m_pullup(m, 2); 520#endif 521 cm_ram_ptr = buffer * 512; 522 523 if (m == 0) 524 return; 525 526 /* write the addresses to RAM and throw them away */ 527 528 /* 529 * Hardware does this: Yet Another Microsecond Saved. 530 * (btw, timing code says usually 2 microseconds) 531 * PUTMEM(cm_ram_ptr + 0, mtod(m, u_char *)[0]); 532 */ 533 534 PUTMEM(cm_ram_ptr + 1, mtod(m, u_char *)[1]); 535 m_adj(m, 2); 536 537 /* get total length left at this point */ 538 tlen = m->m_pkthdr.len; 539 if (tlen < ARC_MIN_FORBID_LEN) { 540 offset = 256 - tlen; 541 PUTMEM(cm_ram_ptr + 2, offset); 542 } else { 543 PUTMEM(cm_ram_ptr + 2, 0); 544 if (tlen <= ARC_MAX_FORBID_LEN) 545 offset = 255; /* !!! */ 546 else { 547 if (tlen > ARC_MAX_LEN) 548 tlen = ARC_MAX_LEN; 549 offset = 512 - tlen; 550 } 551 PUTMEM(cm_ram_ptr + 3, offset); 552 553 } 554 cm_ram_ptr += offset; 555 556 /* lets loop through the mbuf chain */ 557 558 for (mp = m; mp; mp = mp->m_next) { 559 if ((len = mp->m_len)) { /* YAMS */ 560 bus_space_write_region_1( 561 rman_get_bustag(sc->mem_res), 562 rman_get_bushandle(sc->mem_res), 563 cm_ram_ptr, mtod(mp, caddr_t), len); 564 565 cm_ram_ptr += len; 566 } 567 } 568 569 sc->sc_broadcast[buffer] = (m->m_flags & M_BCAST) != 0; 570 sc->sc_retransmits[buffer] = (m->m_flags & M_BCAST) ? 1 : 5; 571 572 /* actually transmit the packet */ 573 s = splimp(); 574 575 if (++sc->sc_tx_fillcount > 1) { 576 /* 577 * We are filled up to the rim. No more bufs for the moment, 578 * please. 579 */
| 494 return; 495 496 s = splimp(); 497 498 if (sc->sc_tx_fillcount >= 2) { 499 splx(s); 500 return; 501 } 502 503 m = arc_frag_next(ifp); 504 buffer = sc->sc_tx_act ^ 1; 505 506 splx(s); 507 508 if (m == 0) 509 return; 510 511#ifdef CM_DEBUG 512 if (m->m_len < ARC_HDRLEN) 513 m = m_pullup(m, ARC_HDRLEN);/* gcc does structure padding */ 514 if_printf(ifp, "start: filling %d from %d to %d type %d\n", 515 buffer, mtod(m, u_char *)[0], 516 mtod(m, u_char *)[1], mtod(m, u_char *)[2]); 517#else 518 if (m->m_len < 2) 519 m = m_pullup(m, 2); 520#endif 521 cm_ram_ptr = buffer * 512; 522 523 if (m == 0) 524 return; 525 526 /* write the addresses to RAM and throw them away */ 527 528 /* 529 * Hardware does this: Yet Another Microsecond Saved. 530 * (btw, timing code says usually 2 microseconds) 531 * PUTMEM(cm_ram_ptr + 0, mtod(m, u_char *)[0]); 532 */ 533 534 PUTMEM(cm_ram_ptr + 1, mtod(m, u_char *)[1]); 535 m_adj(m, 2); 536 537 /* get total length left at this point */ 538 tlen = m->m_pkthdr.len; 539 if (tlen < ARC_MIN_FORBID_LEN) { 540 offset = 256 - tlen; 541 PUTMEM(cm_ram_ptr + 2, offset); 542 } else { 543 PUTMEM(cm_ram_ptr + 2, 0); 544 if (tlen <= ARC_MAX_FORBID_LEN) 545 offset = 255; /* !!! */ 546 else { 547 if (tlen > ARC_MAX_LEN) 548 tlen = ARC_MAX_LEN; 549 offset = 512 - tlen; 550 } 551 PUTMEM(cm_ram_ptr + 3, offset); 552 553 } 554 cm_ram_ptr += offset; 555 556 /* lets loop through the mbuf chain */ 557 558 for (mp = m; mp; mp = mp->m_next) { 559 if ((len = mp->m_len)) { /* YAMS */ 560 bus_space_write_region_1( 561 rman_get_bustag(sc->mem_res), 562 rman_get_bushandle(sc->mem_res), 563 cm_ram_ptr, mtod(mp, caddr_t), len); 564 565 cm_ram_ptr += len; 566 } 567 } 568 569 sc->sc_broadcast[buffer] = (m->m_flags & M_BCAST) != 0; 570 sc->sc_retransmits[buffer] = (m->m_flags & M_BCAST) ? 1 : 5; 571 572 /* actually transmit the packet */ 573 s = splimp(); 574 575 if (++sc->sc_tx_fillcount > 1) { 576 /* 577 * We are filled up to the rim. No more bufs for the moment, 578 * please. 579 */
|
580 ifp->if_flags |= IFF_OACTIVE;
| 580 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
581 } else { 582#ifdef CM_DEBUG 583 if_printf(ifp, "start: starting transmitter on buffer %d\n", 584 buffer); 585#endif 586 /* Transmitter was off, start it */ 587 sc->sc_tx_act = buffer; 588 589 /* 590 * We still can accept another buf, so don't:
| 581 } else { 582#ifdef CM_DEBUG 583 if_printf(ifp, "start: starting transmitter on buffer %d\n", 584 buffer); 585#endif 586 /* Transmitter was off, start it */ 587 sc->sc_tx_act = buffer; 588 589 /* 590 * We still can accept another buf, so don't:
|
591 * ifp->if_flags |= IFF_OACTIVE;
| 591 * ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
592 */ 593 sc->sc_intmask |= CM_TA; 594 PUTREG(CMCMD, CM_TX(buffer)); 595 PUTREG(CMSTAT, sc->sc_intmask); 596 597 ifp->if_timer = ARCTIMEOUT; 598 } 599 splx(s); 600 m_freem(m); 601 602 /* 603 * After 10 times reading the docs, I realized 604 * that in the case the receiver NAKs the buffer request, 605 * the hardware retries till shutdown. 606 * This is integrated now in the code above. 607 */ 608 609 return; 610} 611 612/* 613 * Arcnet interface receiver soft interrupt: 614 * get the stuff out of any filled buffer we find. 615 */ 616void 617cm_srint(vsc) 618 void *vsc; 619{ 620 struct cm_softc *sc = (struct cm_softc *)vsc; 621 int buffer, len, offset, s, type; 622 int cm_ram_ptr; 623 struct mbuf *m; 624 struct arc_header *ah; 625 struct ifnet *ifp; 626 627 ifp = sc->sc_ifp; 628 629 s = splimp(); 630 buffer = sc->sc_rx_act ^ 1; 631 splx(s); 632 633 /* Allocate header mbuf */ 634 MGETHDR(m, M_DONTWAIT, MT_DATA); 635 636 if (m == 0) { 637 /* 638 * in case s.th. goes wrong with mem, drop it 639 * to make sure the receiver can be started again 640 * count it as input error (we dont have any other 641 * detectable) 642 */ 643 ifp->if_ierrors++; 644 goto cleanup; 645 } 646 647 m->m_pkthdr.rcvif = ifp; 648 649 /* 650 * Align so that IP packet will be longword aligned. Here we 651 * assume that m_data of new packet is longword aligned. 652 * When implementing PHDS, we might have to change it to 2, 653 * (2*sizeof(ulong) - CM_HDRNEWLEN)), packet type dependent. 654 */ 655 656 cm_ram_ptr = buffer * 512; 657 offset = GETMEM(cm_ram_ptr + 2); 658 if (offset) 659 len = 256 - offset; 660 else { 661 offset = GETMEM(cm_ram_ptr + 3); 662 len = 512 - offset; 663 } 664 665 /* 666 * first +2 bytes for align fixup below 667 * second +2 bytes are for src/dst addresses 668 */ 669 if ((len + 2 + 2) > MHLEN) { 670 /* attach an mbuf cluster */ 671 MCLGET(m, M_DONTWAIT); 672 673 /* Insist on getting a cluster */ 674 if ((m->m_flags & M_EXT) == 0) { 675 ifp->if_ierrors++; 676 goto cleanup; 677 } 678 } 679 680 if (m == 0) { 681 ifp->if_ierrors++; 682 goto cleanup; 683 } 684 685 type = GETMEM(cm_ram_ptr + offset); 686 m->m_data += 1 + arc_isphds(type); 687 /* mbuf filled with ARCnet addresses */ 688 m->m_pkthdr.len = m->m_len = len + 2; 689 690 ah = mtod(m, struct arc_header *); 691 ah->arc_shost = GETMEM(cm_ram_ptr + 0); 692 ah->arc_dhost = GETMEM(cm_ram_ptr + 1); 693 694 bus_space_read_region_1( 695 rman_get_bustag(sc->mem_res), rman_get_bushandle(sc->mem_res), 696 cm_ram_ptr + offset, mtod(m, u_char *) + 2, len); 697 698 arc_input(ifp, m); 699 700 m = NULL; 701 ifp->if_ipackets++; 702 703cleanup: 704 705 if (m != NULL) 706 m_freem(m); 707 708 /* mark buffer as invalid by source id 0 */ 709 PUTMEM(buffer << 9, 0); 710 s = splimp(); 711 712 if (--sc->sc_rx_fillcount == 2 - 1) { 713 714 /* was off, restart it on buffer just emptied */ 715 sc->sc_rx_act = buffer; 716 sc->sc_intmask |= CM_RI; 717 718 /* this also clears the RI flag interupt: */ 719 PUTREG(CMCMD, CM_RXBC(buffer)); 720 PUTREG(CMSTAT, sc->sc_intmask); 721 722#ifdef CM_DEBUG 723 if_printf(ifp, "srint: restarted rx on buf %d\n", buffer); 724#endif 725 } 726 splx(s); 727} 728 729__inline static void 730cm_tint(sc, isr) 731 struct cm_softc *sc; 732 int isr; 733{ 734 struct ifnet *ifp; 735 736 int buffer; 737#ifdef CMTIMINGS 738 int clknow; 739#endif 740 741 ifp = sc->sc_ifp; 742 buffer = sc->sc_tx_act; 743 744 /* 745 * retransmit code: 746 * Normal situtations first for fast path: 747 * If acknowledgement received ok or broadcast, we're ok. 748 * else if 749 */ 750 751 if (isr & CM_TMA || sc->sc_broadcast[buffer]) 752 ifp->if_opackets++; 753#ifdef CMRETRANSMIT 754 else if (ifp->if_flags & IFF_LINK2 && ifp->if_timer > 0 755 && --sc->sc_retransmits[buffer] > 0) { 756 /* retransmit same buffer */ 757 PUTREG(CMCMD, CM_TX(buffer)); 758 return; 759 } 760#endif 761 else 762 ifp->if_oerrors++; 763 764 765 /* We know we can accept another buffer at this point. */
| 592 */ 593 sc->sc_intmask |= CM_TA; 594 PUTREG(CMCMD, CM_TX(buffer)); 595 PUTREG(CMSTAT, sc->sc_intmask); 596 597 ifp->if_timer = ARCTIMEOUT; 598 } 599 splx(s); 600 m_freem(m); 601 602 /* 603 * After 10 times reading the docs, I realized 604 * that in the case the receiver NAKs the buffer request, 605 * the hardware retries till shutdown. 606 * This is integrated now in the code above. 607 */ 608 609 return; 610} 611 612/* 613 * Arcnet interface receiver soft interrupt: 614 * get the stuff out of any filled buffer we find. 615 */ 616void 617cm_srint(vsc) 618 void *vsc; 619{ 620 struct cm_softc *sc = (struct cm_softc *)vsc; 621 int buffer, len, offset, s, type; 622 int cm_ram_ptr; 623 struct mbuf *m; 624 struct arc_header *ah; 625 struct ifnet *ifp; 626 627 ifp = sc->sc_ifp; 628 629 s = splimp(); 630 buffer = sc->sc_rx_act ^ 1; 631 splx(s); 632 633 /* Allocate header mbuf */ 634 MGETHDR(m, M_DONTWAIT, MT_DATA); 635 636 if (m == 0) { 637 /* 638 * in case s.th. goes wrong with mem, drop it 639 * to make sure the receiver can be started again 640 * count it as input error (we dont have any other 641 * detectable) 642 */ 643 ifp->if_ierrors++; 644 goto cleanup; 645 } 646 647 m->m_pkthdr.rcvif = ifp; 648 649 /* 650 * Align so that IP packet will be longword aligned. Here we 651 * assume that m_data of new packet is longword aligned. 652 * When implementing PHDS, we might have to change it to 2, 653 * (2*sizeof(ulong) - CM_HDRNEWLEN)), packet type dependent. 654 */ 655 656 cm_ram_ptr = buffer * 512; 657 offset = GETMEM(cm_ram_ptr + 2); 658 if (offset) 659 len = 256 - offset; 660 else { 661 offset = GETMEM(cm_ram_ptr + 3); 662 len = 512 - offset; 663 } 664 665 /* 666 * first +2 bytes for align fixup below 667 * second +2 bytes are for src/dst addresses 668 */ 669 if ((len + 2 + 2) > MHLEN) { 670 /* attach an mbuf cluster */ 671 MCLGET(m, M_DONTWAIT); 672 673 /* Insist on getting a cluster */ 674 if ((m->m_flags & M_EXT) == 0) { 675 ifp->if_ierrors++; 676 goto cleanup; 677 } 678 } 679 680 if (m == 0) { 681 ifp->if_ierrors++; 682 goto cleanup; 683 } 684 685 type = GETMEM(cm_ram_ptr + offset); 686 m->m_data += 1 + arc_isphds(type); 687 /* mbuf filled with ARCnet addresses */ 688 m->m_pkthdr.len = m->m_len = len + 2; 689 690 ah = mtod(m, struct arc_header *); 691 ah->arc_shost = GETMEM(cm_ram_ptr + 0); 692 ah->arc_dhost = GETMEM(cm_ram_ptr + 1); 693 694 bus_space_read_region_1( 695 rman_get_bustag(sc->mem_res), rman_get_bushandle(sc->mem_res), 696 cm_ram_ptr + offset, mtod(m, u_char *) + 2, len); 697 698 arc_input(ifp, m); 699 700 m = NULL; 701 ifp->if_ipackets++; 702 703cleanup: 704 705 if (m != NULL) 706 m_freem(m); 707 708 /* mark buffer as invalid by source id 0 */ 709 PUTMEM(buffer << 9, 0); 710 s = splimp(); 711 712 if (--sc->sc_rx_fillcount == 2 - 1) { 713 714 /* was off, restart it on buffer just emptied */ 715 sc->sc_rx_act = buffer; 716 sc->sc_intmask |= CM_RI; 717 718 /* this also clears the RI flag interupt: */ 719 PUTREG(CMCMD, CM_RXBC(buffer)); 720 PUTREG(CMSTAT, sc->sc_intmask); 721 722#ifdef CM_DEBUG 723 if_printf(ifp, "srint: restarted rx on buf %d\n", buffer); 724#endif 725 } 726 splx(s); 727} 728 729__inline static void 730cm_tint(sc, isr) 731 struct cm_softc *sc; 732 int isr; 733{ 734 struct ifnet *ifp; 735 736 int buffer; 737#ifdef CMTIMINGS 738 int clknow; 739#endif 740 741 ifp = sc->sc_ifp; 742 buffer = sc->sc_tx_act; 743 744 /* 745 * retransmit code: 746 * Normal situtations first for fast path: 747 * If acknowledgement received ok or broadcast, we're ok. 748 * else if 749 */ 750 751 if (isr & CM_TMA || sc->sc_broadcast[buffer]) 752 ifp->if_opackets++; 753#ifdef CMRETRANSMIT 754 else if (ifp->if_flags & IFF_LINK2 && ifp->if_timer > 0 755 && --sc->sc_retransmits[buffer] > 0) { 756 /* retransmit same buffer */ 757 PUTREG(CMCMD, CM_TX(buffer)); 758 return; 759 } 760#endif 761 else 762 ifp->if_oerrors++; 763 764 765 /* We know we can accept another buffer at this point. */
|
766 ifp->if_flags &= ~IFF_OACTIVE;
| 766 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
767 768 if (--sc->sc_tx_fillcount > 0) { 769 770 /* 771 * start tx on other buffer. 772 * This also clears the int flag 773 */ 774 buffer ^= 1; 775 sc->sc_tx_act = buffer; 776 777 /* 778 * already given: 779 * sc->sc_intmask |= CM_TA; 780 * PUTREG(CMSTAT, sc->sc_intmask); 781 */ 782 PUTREG(CMCMD, CM_TX(buffer)); 783 /* init watchdog timer */ 784 ifp->if_timer = ARCTIMEOUT; 785 786#if defined(CM_DEBUG) && (CM_DEBUG > 1) 787 if_printf(ifp, 788 "tint: starting tx on buffer %d, status 0x%02x\n", 789 buffer, GETREG(CMSTAT)); 790#endif 791 } else { 792 /* have to disable TX interrupt */ 793 sc->sc_intmask &= ~CM_TA; 794 PUTREG(CMSTAT, sc->sc_intmask); 795 /* ... and watchdog timer */ 796 ifp->if_timer = 0; 797 798#ifdef CM_DEBUG 799 if_printf(ifp, "tint: no more buffers to send, status 0x%02x\n", 800 GETREG(CMSTAT)); 801#endif 802 } 803 804 /* XXXX TODO */ 805#ifdef CMSOFTCOPY 806 /* schedule soft int to fill a new buffer for us */ 807 softintr_schedule(sc->sc_txcookie); 808#else 809 /* call it directly */ 810 cm_start(ifp); 811#endif 812} 813 814/* 815 * Our interrupt routine 816 */ 817void 818cmintr(arg) 819 void *arg; 820{ 821 struct cm_softc *sc = arg; 822 struct ifnet *ifp = sc->sc_ifp; 823 824 u_char isr, maskedisr; 825 int buffer; 826 u_long newsec; 827 828 isr = GETREG(CMSTAT); 829 maskedisr = isr & sc->sc_intmask; 830 if (!maskedisr) 831 return; 832 do { 833 834#if defined(CM_DEBUG) && (CM_DEBUG > 1) 835 if_printf(ifp, "intr: status 0x%02x, intmask 0x%02x\n", 836 isr, sc->sc_intmask); 837#endif 838 839 if (maskedisr & CM_POR) { 840 /* 841 * XXX We should never see this. Don't bother to store 842 * the address. 843 * sc->sc_ifp->if_l2com->ac_anaddr = GETMEM(CMMACOFF); 844 */ 845 PUTREG(CMCMD, CM_CLR(CLR_POR)); 846 log(LOG_WARNING, 847 "%s: intr: got spurious power on reset int\n", 848 ifp->if_xname); 849 } 850 851 if (maskedisr & CM_RECON) { 852 /* 853 * we dont need to: 854 * PUTREG(CMCMD, CM_CONF(CONF_LONG)); 855 */ 856 PUTREG(CMCMD, CM_CLR(CLR_RECONFIG)); 857 ifp->if_collisions++; 858 859 /* 860 * If less than 2 seconds per reconfig: 861 * If ARC_EXCESSIVE_RECONFIGS 862 * since last burst, complain and set treshold for 863 * warnings to ARC_EXCESSIVE_RECONS_REWARN. 864 * 865 * This allows for, e.g., new stations on the cable, or 866 * cable switching as long as it is over after 867 * (normally) 16 seconds. 868 * 869 * XXX TODO: check timeout bits in status word and 870 * double time if necessary. 871 */ 872 873 callout_stop(&sc->sc_recon_ch); 874 newsec = time_second; 875 if ((newsec - sc->sc_recontime <= 2) && 876 (++sc->sc_reconcount == ARC_EXCESSIVE_RECONS)) { 877 log(LOG_WARNING, 878 "%s: excessive token losses, " 879 "cable problem?\n", 880 ifp->if_xname); 881 } 882 sc->sc_recontime = newsec; 883 callout_reset(&sc->sc_recon_ch, 15 * hz, 884 cm_reconwatch, (void *)sc); 885 } 886 887 if (maskedisr & CM_RI) { 888#if defined(CM_DEBUG) && (CM_DEBUG > 1) 889 if_printf(ifp, "intr: hard rint, act %d\n", 890 sc->sc_rx_act); 891#endif 892 893 buffer = sc->sc_rx_act; 894 /* look if buffer is marked invalid: */ 895 if (GETMEM(buffer * 512) == 0) { 896 /* 897 * invalid marked buffer (or illegally 898 * configured sender) 899 */ 900 log(LOG_WARNING, 901 "%s: spurious RX interupt or sender 0 " 902 " (ignored)\n", ifp->if_xname); 903 /* 904 * restart receiver on same buffer. 905 * XXX maybe better reset interface? 906 */ 907 PUTREG(CMCMD, CM_RXBC(buffer)); 908 } else { 909 if (++sc->sc_rx_fillcount > 1) { 910 sc->sc_intmask &= ~CM_RI; 911 PUTREG(CMSTAT, sc->sc_intmask); 912 } else { 913 buffer ^= 1; 914 sc->sc_rx_act = buffer; 915 916 /* 917 * Start receiver on other receive 918 * buffer. This also clears the RI 919 * interupt flag. 920 */ 921 PUTREG(CMCMD, CM_RXBC(buffer)); 922 /* in RX intr, so mask is ok for RX */ 923 924#ifdef CM_DEBUG 925 if_printf(ifp, "strt rx for buf %d, " 926 "stat 0x%02x\n", 927 sc->sc_rx_act, GETREG(CMSTAT)); 928#endif 929 } 930 931#ifdef CMSOFTCOPY 932 /* 933 * this one starts a soft int to copy out 934 * of the hw 935 */ 936 softintr_schedule(sc->sc_rxcookie); 937#else 938 /* this one does the copy here */ 939 cm_srint(sc); 940#endif 941 } 942 } 943 if (maskedisr & CM_TA) { 944 cm_tint(sc, isr); 945 } 946 isr = GETREG(CMSTAT); 947 maskedisr = isr & sc->sc_intmask; 948 } while (maskedisr); 949#if defined(CM_DEBUG) && (CM_DEBUG > 1) 950 if_printf(ifp, "intr (exit): status 0x%02x, intmask 0x%02x\n", 951 isr, sc->sc_intmask); 952#endif 953} 954 955void 956cm_reconwatch(arg) 957 void *arg; 958{ 959 struct cm_softc *sc = arg; 960 struct ifnet *ifp = sc->sc_ifp; 961 962 if (sc->sc_reconcount >= ARC_EXCESSIVE_RECONS) { 963 sc->sc_reconcount = 0; 964 log(LOG_WARNING, "%s: token valid again.\n", 965 ifp->if_xname); 966 } 967 sc->sc_reconcount = 0; 968} 969 970 971/* 972 * Process an ioctl request. 973 * This code needs some work - it looks pretty ugly. 974 */ 975int 976cm_ioctl(ifp, command, data) 977 struct ifnet *ifp; 978 u_long command; 979 caddr_t data; 980{ 981 struct cm_softc *sc; 982 struct ifaddr *ifa; 983 struct ifreq *ifr; 984 int s, error; 985 986 error = 0; 987 sc = ifp->if_softc; 988 ifa = (struct ifaddr *)data; 989 ifr = (struct ifreq *)data; 990 s = splimp(); 991 992#if defined(CM_DEBUG) && (CM_DEBUG > 2) 993 if_printf(ifp, "ioctl() called, cmd = 0x%lx\n", command); 994#endif 995 996 switch (command) { 997 case SIOCSIFADDR: 998 case SIOCGIFADDR: 999 case SIOCADDMULTI: 1000 case SIOCDELMULTI: 1001 case SIOCSIFMTU: 1002 error = arc_ioctl(ifp, command, data); 1003 break; 1004 1005 case SIOCSIFFLAGS: 1006 if ((ifp->if_flags & IFF_UP) == 0 &&
| 767 768 if (--sc->sc_tx_fillcount > 0) { 769 770 /* 771 * start tx on other buffer. 772 * This also clears the int flag 773 */ 774 buffer ^= 1; 775 sc->sc_tx_act = buffer; 776 777 /* 778 * already given: 779 * sc->sc_intmask |= CM_TA; 780 * PUTREG(CMSTAT, sc->sc_intmask); 781 */ 782 PUTREG(CMCMD, CM_TX(buffer)); 783 /* init watchdog timer */ 784 ifp->if_timer = ARCTIMEOUT; 785 786#if defined(CM_DEBUG) && (CM_DEBUG > 1) 787 if_printf(ifp, 788 "tint: starting tx on buffer %d, status 0x%02x\n", 789 buffer, GETREG(CMSTAT)); 790#endif 791 } else { 792 /* have to disable TX interrupt */ 793 sc->sc_intmask &= ~CM_TA; 794 PUTREG(CMSTAT, sc->sc_intmask); 795 /* ... and watchdog timer */ 796 ifp->if_timer = 0; 797 798#ifdef CM_DEBUG 799 if_printf(ifp, "tint: no more buffers to send, status 0x%02x\n", 800 GETREG(CMSTAT)); 801#endif 802 } 803 804 /* XXXX TODO */ 805#ifdef CMSOFTCOPY 806 /* schedule soft int to fill a new buffer for us */ 807 softintr_schedule(sc->sc_txcookie); 808#else 809 /* call it directly */ 810 cm_start(ifp); 811#endif 812} 813 814/* 815 * Our interrupt routine 816 */ 817void 818cmintr(arg) 819 void *arg; 820{ 821 struct cm_softc *sc = arg; 822 struct ifnet *ifp = sc->sc_ifp; 823 824 u_char isr, maskedisr; 825 int buffer; 826 u_long newsec; 827 828 isr = GETREG(CMSTAT); 829 maskedisr = isr & sc->sc_intmask; 830 if (!maskedisr) 831 return; 832 do { 833 834#if defined(CM_DEBUG) && (CM_DEBUG > 1) 835 if_printf(ifp, "intr: status 0x%02x, intmask 0x%02x\n", 836 isr, sc->sc_intmask); 837#endif 838 839 if (maskedisr & CM_POR) { 840 /* 841 * XXX We should never see this. Don't bother to store 842 * the address. 843 * sc->sc_ifp->if_l2com->ac_anaddr = GETMEM(CMMACOFF); 844 */ 845 PUTREG(CMCMD, CM_CLR(CLR_POR)); 846 log(LOG_WARNING, 847 "%s: intr: got spurious power on reset int\n", 848 ifp->if_xname); 849 } 850 851 if (maskedisr & CM_RECON) { 852 /* 853 * we dont need to: 854 * PUTREG(CMCMD, CM_CONF(CONF_LONG)); 855 */ 856 PUTREG(CMCMD, CM_CLR(CLR_RECONFIG)); 857 ifp->if_collisions++; 858 859 /* 860 * If less than 2 seconds per reconfig: 861 * If ARC_EXCESSIVE_RECONFIGS 862 * since last burst, complain and set treshold for 863 * warnings to ARC_EXCESSIVE_RECONS_REWARN. 864 * 865 * This allows for, e.g., new stations on the cable, or 866 * cable switching as long as it is over after 867 * (normally) 16 seconds. 868 * 869 * XXX TODO: check timeout bits in status word and 870 * double time if necessary. 871 */ 872 873 callout_stop(&sc->sc_recon_ch); 874 newsec = time_second; 875 if ((newsec - sc->sc_recontime <= 2) && 876 (++sc->sc_reconcount == ARC_EXCESSIVE_RECONS)) { 877 log(LOG_WARNING, 878 "%s: excessive token losses, " 879 "cable problem?\n", 880 ifp->if_xname); 881 } 882 sc->sc_recontime = newsec; 883 callout_reset(&sc->sc_recon_ch, 15 * hz, 884 cm_reconwatch, (void *)sc); 885 } 886 887 if (maskedisr & CM_RI) { 888#if defined(CM_DEBUG) && (CM_DEBUG > 1) 889 if_printf(ifp, "intr: hard rint, act %d\n", 890 sc->sc_rx_act); 891#endif 892 893 buffer = sc->sc_rx_act; 894 /* look if buffer is marked invalid: */ 895 if (GETMEM(buffer * 512) == 0) { 896 /* 897 * invalid marked buffer (or illegally 898 * configured sender) 899 */ 900 log(LOG_WARNING, 901 "%s: spurious RX interupt or sender 0 " 902 " (ignored)\n", ifp->if_xname); 903 /* 904 * restart receiver on same buffer. 905 * XXX maybe better reset interface? 906 */ 907 PUTREG(CMCMD, CM_RXBC(buffer)); 908 } else { 909 if (++sc->sc_rx_fillcount > 1) { 910 sc->sc_intmask &= ~CM_RI; 911 PUTREG(CMSTAT, sc->sc_intmask); 912 } else { 913 buffer ^= 1; 914 sc->sc_rx_act = buffer; 915 916 /* 917 * Start receiver on other receive 918 * buffer. This also clears the RI 919 * interupt flag. 920 */ 921 PUTREG(CMCMD, CM_RXBC(buffer)); 922 /* in RX intr, so mask is ok for RX */ 923 924#ifdef CM_DEBUG 925 if_printf(ifp, "strt rx for buf %d, " 926 "stat 0x%02x\n", 927 sc->sc_rx_act, GETREG(CMSTAT)); 928#endif 929 } 930 931#ifdef CMSOFTCOPY 932 /* 933 * this one starts a soft int to copy out 934 * of the hw 935 */ 936 softintr_schedule(sc->sc_rxcookie); 937#else 938 /* this one does the copy here */ 939 cm_srint(sc); 940#endif 941 } 942 } 943 if (maskedisr & CM_TA) { 944 cm_tint(sc, isr); 945 } 946 isr = GETREG(CMSTAT); 947 maskedisr = isr & sc->sc_intmask; 948 } while (maskedisr); 949#if defined(CM_DEBUG) && (CM_DEBUG > 1) 950 if_printf(ifp, "intr (exit): status 0x%02x, intmask 0x%02x\n", 951 isr, sc->sc_intmask); 952#endif 953} 954 955void 956cm_reconwatch(arg) 957 void *arg; 958{ 959 struct cm_softc *sc = arg; 960 struct ifnet *ifp = sc->sc_ifp; 961 962 if (sc->sc_reconcount >= ARC_EXCESSIVE_RECONS) { 963 sc->sc_reconcount = 0; 964 log(LOG_WARNING, "%s: token valid again.\n", 965 ifp->if_xname); 966 } 967 sc->sc_reconcount = 0; 968} 969 970 971/* 972 * Process an ioctl request. 973 * This code needs some work - it looks pretty ugly. 974 */ 975int 976cm_ioctl(ifp, command, data) 977 struct ifnet *ifp; 978 u_long command; 979 caddr_t data; 980{ 981 struct cm_softc *sc; 982 struct ifaddr *ifa; 983 struct ifreq *ifr; 984 int s, error; 985 986 error = 0; 987 sc = ifp->if_softc; 988 ifa = (struct ifaddr *)data; 989 ifr = (struct ifreq *)data; 990 s = splimp(); 991 992#if defined(CM_DEBUG) && (CM_DEBUG > 2) 993 if_printf(ifp, "ioctl() called, cmd = 0x%lx\n", command); 994#endif 995 996 switch (command) { 997 case SIOCSIFADDR: 998 case SIOCGIFADDR: 999 case SIOCADDMULTI: 1000 case SIOCDELMULTI: 1001 case SIOCSIFMTU: 1002 error = arc_ioctl(ifp, command, data); 1003 break; 1004 1005 case SIOCSIFFLAGS: 1006 if ((ifp->if_flags & IFF_UP) == 0 &&
|
1007 (ifp->if_flags & IFF_RUNNING) != 0) {
| 1007 (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
|
1008 /* 1009 * If interface is marked down and it is running, 1010 * then stop it. 1011 */ 1012 cm_stop(sc);
| 1008 /* 1009 * If interface is marked down and it is running, 1010 * then stop it. 1011 */ 1012 cm_stop(sc);
|
1013 ifp->if_flags &= ~IFF_RUNNING;
| 1013 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
1014 } else if ((ifp->if_flags & IFF_UP) != 0 &&
| 1014 } else if ((ifp->if_flags & IFF_UP) != 0 &&
|
1015 (ifp->if_flags & IFF_RUNNING) == 0) {
| 1015 (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
1016 /* 1017 * If interface is marked up and it is stopped, then 1018 * start it. 1019 */ 1020 cm_init(sc); 1021 } 1022 break; 1023 1024 default: 1025 error = EINVAL; 1026 break; 1027 } 1028 1029 splx(s); 1030 return (error); 1031} 1032 1033/* 1034 * watchdog routine for transmitter. 1035 * 1036 * We need this, because else a receiver whose hardware is alive, but whose 1037 * software has not enabled the Receiver, would make our hardware wait forever 1038 * Discovered this after 20 times reading the docs. 1039 * 1040 * Only thing we do is disable transmitter. We'll get a transmit timeout, 1041 * and the int handler will have to decide not to retransmit (in case 1042 * retransmission is implemented). 1043 * 1044 * This one assumes being called inside splimp() 1045 */ 1046 1047void 1048cm_watchdog(ifp) 1049 struct ifnet *ifp; 1050{ 1051 struct cm_softc *sc = ifp->if_softc; 1052 1053 PUTREG(CMCMD, CM_TXDIS); 1054 return; 1055}
| 1016 /* 1017 * If interface is marked up and it is stopped, then 1018 * start it. 1019 */ 1020 cm_init(sc); 1021 } 1022 break; 1023 1024 default: 1025 error = EINVAL; 1026 break; 1027 } 1028 1029 splx(s); 1030 return (error); 1031} 1032 1033/* 1034 * watchdog routine for transmitter. 1035 * 1036 * We need this, because else a receiver whose hardware is alive, but whose 1037 * software has not enabled the Receiver, would make our hardware wait forever 1038 * Discovered this after 20 times reading the docs. 1039 * 1040 * Only thing we do is disable transmitter. We'll get a transmit timeout, 1041 * and the int handler will have to decide not to retransmit (in case 1042 * retransmission is implemented). 1043 * 1044 * This one assumes being called inside splimp() 1045 */ 1046 1047void 1048cm_watchdog(ifp) 1049 struct ifnet *ifp; 1050{ 1051 struct cm_softc *sc = ifp->if_softc; 1052 1053 PUTREG(CMCMD, CM_TXDIS); 1054 return; 1055}
|