mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 01:38:57 +00:00
Make cm(4) driver MPSAFE.
This commit is contained in:
parent
affcaf7871
commit
5349526518
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=159529
@ -48,10 +48,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_arc.h>
|
||||
|
||||
#include <dev/cm/smc90cx6reg.h>
|
||||
#include <dev/cm/smc90cx6var.h>
|
||||
|
||||
static int cm_isa_probe (device_t);
|
||||
@ -62,20 +65,35 @@ cm_isa_probe(dev)
|
||||
device_t dev;
|
||||
{
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
int error;
|
||||
int rid;
|
||||
|
||||
bzero(sc, sizeof(struct cm_softc));
|
||||
rid = 0;
|
||||
sc->port_res = bus_alloc_resource(
|
||||
dev, SYS_RES_IOPORT, &rid, 0ul, ~0ul, CM_IO_PORTS, RF_ACTIVE);
|
||||
if (sc->port_res == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
error = cm_probe(dev);
|
||||
if (error == 0)
|
||||
goto end;
|
||||
if (GETREG(CMSTAT) == 0xff) {
|
||||
cm_release_resources(dev);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
end:
|
||||
if (error == 0)
|
||||
error = cm_alloc_irq(dev, 0);
|
||||
rid = 0;
|
||||
sc->mem_res = bus_alloc_resource(
|
||||
dev, SYS_RES_MEMORY, &rid, 0ul, ~0ul, CM_MEM_SIZE, RF_ACTIVE);
|
||||
if (sc->mem_res == NULL) {
|
||||
cm_release_resources(dev);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
cm_release_resources(dev);
|
||||
return (error);
|
||||
rid = 0;
|
||||
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
|
||||
if (sc->irq_res == NULL) {
|
||||
cm_release_resources(dev);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -85,18 +103,25 @@ cm_isa_attach(dev)
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
cm_alloc_port(dev, sc->port_rid, sc->port_used);
|
||||
cm_alloc_memory(dev, sc->mem_rid, sc->mem_used);
|
||||
cm_alloc_irq(dev, sc->irq_rid);
|
||||
/* init mtx and setup interrupt */
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(dev),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
|
||||
cmintr, sc, &sc->irq_handle);
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
|
||||
cmintr, sc, &sc->irq_handle);
|
||||
if (error) {
|
||||
cm_release_resources(dev);
|
||||
return (error);
|
||||
}
|
||||
/* attach */
|
||||
error = cm_attach(dev);
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
return cm_attach(dev);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
cm_release_resources(dev);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -104,19 +129,23 @@ cm_isa_detach(device_t dev)
|
||||
{
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int s;
|
||||
|
||||
cm_stop(sc);
|
||||
/* stop and detach */
|
||||
CM_LOCK(sc);
|
||||
cm_stop_locked(sc);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
||||
CM_UNLOCK(sc);
|
||||
|
||||
s = splimp();
|
||||
callout_drain(&sc->sc_recon_ch);
|
||||
arc_ifdetach(ifp);
|
||||
splx(s);
|
||||
|
||||
/* teardown interrupt, destroy mtx and release resources */
|
||||
bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
if_free(ifp);
|
||||
cm_release_resources(dev);
|
||||
|
||||
bus_generic_detach(dev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -62,10 +62,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#if __FreeBSD_version < 500000
|
||||
#include <machine/clock.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
@ -87,25 +83,6 @@ MODULE_DEPEND(if_cm, arcnet, 1, 1, 1);
|
||||
/* for watchdog timer. This should be more than enough. */
|
||||
#define ARCTIMEOUT (5*IFNET_SLOWHZ)
|
||||
|
||||
/* short notation */
|
||||
|
||||
#define GETREG(off) \
|
||||
bus_space_read_1(rman_get_bustag((sc)->port_res), \
|
||||
rman_get_bushandle((sc)->port_res), \
|
||||
(off))
|
||||
#define PUTREG(off, value) \
|
||||
bus_space_write_1(rman_get_bustag((sc)->port_res), \
|
||||
rman_get_bushandle((sc)->port_res), \
|
||||
(off), (value))
|
||||
#define GETMEM(off) \
|
||||
bus_space_read_1(rman_get_bustag((sc)->mem_res), \
|
||||
rman_get_bushandle((sc)->mem_res), \
|
||||
(off))
|
||||
#define PUTMEM(off, value) \
|
||||
bus_space_write_1(rman_get_bustag((sc)->mem_res), \
|
||||
rman_get_bushandle((sc)->mem_res), \
|
||||
(off), (value))
|
||||
|
||||
devclass_t cm_devclass;
|
||||
|
||||
/*
|
||||
@ -134,7 +111,7 @@ devclass_t cm_devclass;
|
||||
* case 2: set IFF_DRV_OACTIVE to stop arc_output from filling us.
|
||||
* case 1: start tx
|
||||
*
|
||||
* tint clears IFF_OCATIVE, decrements and checks tx_fillcount
|
||||
* tint clears IFF_OACTIVE, decrements and checks tx_fillcount
|
||||
* case 1: start tx on tx_act ^ 1, softcall cm_start
|
||||
* case 0: softcall cm_start
|
||||
*
|
||||
@ -142,103 +119,15 @@ devclass_t cm_devclass;
|
||||
*/
|
||||
|
||||
void cm_init(void *);
|
||||
void cm_reset(struct cm_softc *);
|
||||
static void cm_init_locked(struct cm_softc *);
|
||||
static void cm_reset_locked(struct cm_softc *);
|
||||
void cm_start(struct ifnet *);
|
||||
void cm_start_locked(struct ifnet *);
|
||||
int cm_ioctl(struct ifnet *, unsigned long, caddr_t);
|
||||
void cm_watchdog(struct ifnet *);
|
||||
void cm_srint(void *vsc);
|
||||
static void cm_tint(struct cm_softc *, int);
|
||||
void cm_reconwatch(void *);
|
||||
|
||||
int
|
||||
cm_probe(dev)
|
||||
device_t dev;
|
||||
{
|
||||
int error;
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
|
||||
error = cm_alloc_port(dev, 0, CM_IO_PORTS);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (GETREG(CMSTAT) == 0xff)
|
||||
return ENXIO;
|
||||
|
||||
error = cm_alloc_memory(dev, 0, 0x800);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a port resource with the given resource id.
|
||||
*/
|
||||
int
|
||||
cm_alloc_port(dev, rid, size)
|
||||
device_t dev;
|
||||
int rid;
|
||||
int size;
|
||||
{
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
struct resource *res;
|
||||
|
||||
res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||
0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (res) {
|
||||
sc->port_rid = rid;
|
||||
sc->port_res = res;
|
||||
sc->port_used = size;
|
||||
return (0);
|
||||
} else {
|
||||
return (ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a memory resource with the given resource id.
|
||||
*/
|
||||
int
|
||||
cm_alloc_memory(dev, rid, size)
|
||||
device_t dev;
|
||||
int rid;
|
||||
int size;
|
||||
{
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
struct resource *res;
|
||||
|
||||
res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
|
||||
0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (res) {
|
||||
sc->mem_rid = rid;
|
||||
sc->mem_res = res;
|
||||
sc->mem_used = size;
|
||||
return (0);
|
||||
} else {
|
||||
return (ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an irq resource with the given resource id.
|
||||
*/
|
||||
int
|
||||
cm_alloc_irq(dev, rid)
|
||||
device_t dev;
|
||||
int rid;
|
||||
{
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
struct resource *res;
|
||||
|
||||
res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
|
||||
if (res) {
|
||||
sc->irq_rid = rid;
|
||||
sc->irq_res = res;
|
||||
return (0);
|
||||
} else {
|
||||
return (ENOENT);
|
||||
}
|
||||
}
|
||||
void cm_srint_locked(void *vsc);
|
||||
static void cm_tint_locked(struct cm_softc *, int);
|
||||
void cm_reconwatch_locked(void *);
|
||||
|
||||
/*
|
||||
* Release all resources
|
||||
@ -249,26 +138,26 @@ cm_release_resources(dev)
|
||||
{
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (sc->port_res) {
|
||||
if (sc->port_res != NULL) {
|
||||
bus_deactivate_resource(dev, SYS_RES_IOPORT,
|
||||
sc->port_rid, sc->port_res);
|
||||
0, sc->port_res);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||
sc->port_rid, sc->port_res);
|
||||
sc->port_res = 0;
|
||||
0, sc->port_res);
|
||||
sc->port_res = NULL;
|
||||
}
|
||||
if (sc->mem_res) {
|
||||
if (sc->mem_res != NULL) {
|
||||
bus_deactivate_resource(dev, SYS_RES_MEMORY,
|
||||
sc->mem_rid, sc->mem_res);
|
||||
0, sc->mem_res);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
sc->mem_rid, sc->mem_res);
|
||||
sc->mem_res = 0;
|
||||
0, sc->mem_res);
|
||||
sc->mem_res = NULL;
|
||||
}
|
||||
if (sc->irq_res) {
|
||||
if (sc->irq_res != NULL) {
|
||||
bus_deactivate_resource(dev, SYS_RES_IRQ,
|
||||
sc->irq_rid, sc->irq_res);
|
||||
0, sc->irq_res);
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->irq_rid, sc->irq_res);
|
||||
sc->irq_res = 0;
|
||||
0, sc->irq_res);
|
||||
sc->irq_res = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,29 +167,22 @@ cm_attach(dev)
|
||||
{
|
||||
struct cm_softc *sc = device_get_softc(dev);
|
||||
struct ifnet *ifp;
|
||||
int s;
|
||||
u_int8_t linkaddress;
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_ARCNET);
|
||||
if (ifp == NULL) {
|
||||
if (ifp == NULL)
|
||||
return (ENOSPC);
|
||||
}
|
||||
|
||||
s = splhigh();
|
||||
|
||||
/*
|
||||
* read the arcnet address from the board
|
||||
*/
|
||||
|
||||
GETREG(CMRESET);
|
||||
do {
|
||||
DELAY(200);
|
||||
} while (!(GETREG(CMSTAT) & CM_POR));
|
||||
|
||||
linkaddress = GETMEM(CMMACOFF);
|
||||
|
||||
/* clear the int mask... */
|
||||
|
||||
sc->sc_intmask = 0;
|
||||
PUTREG(CMSTAT, 0);
|
||||
|
||||
@ -308,13 +190,10 @@ cm_attach(dev)
|
||||
PUTREG(CMCMD, CM_CLR(CLR_POR|CLR_RECONFIG));
|
||||
sc->sc_recontime = sc->sc_reconcount = 0;
|
||||
|
||||
/* and reenable kernel int level */
|
||||
splx(s);
|
||||
|
||||
/*
|
||||
* set interface to stopped condition (reset)
|
||||
*/
|
||||
cm_stop(sc);
|
||||
cm_stop_locked(sc);
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
|
||||
@ -326,7 +205,7 @@ cm_attach(dev)
|
||||
/* XXX IFQ_SET_READY(&ifp->if_snd); */
|
||||
ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
|
||||
ifp->if_timer = 0;
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NEEDSGIANT;
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
|
||||
|
||||
arc_ifattach(ifp, linkaddress);
|
||||
|
||||
@ -336,11 +215,7 @@ cm_attach(dev)
|
||||
(void (*)(void *))cm_start, ifp);
|
||||
#endif
|
||||
|
||||
#if __FreeBSD_version < 500000
|
||||
callout_init(&sc->sc_recon_ch);
|
||||
#else
|
||||
callout_init(&sc->sc_recon_ch, 0);
|
||||
#endif
|
||||
callout_init_mtx(&sc->sc_recon_ch, &sc->sc_mtx, 0);
|
||||
|
||||
if_printf(ifp, "link addr 0x%02x (%d)\n", linkaddress, linkaddress);
|
||||
return 0;
|
||||
@ -355,28 +230,30 @@ cm_init(xsc)
|
||||
void *xsc;
|
||||
{
|
||||
struct cm_softc *sc = (struct cm_softc *)xsc;
|
||||
struct ifnet *ifp;
|
||||
int s;
|
||||
|
||||
ifp = sc->sc_ifp;
|
||||
CM_LOCK(sc);
|
||||
cm_init_locked(sc);
|
||||
CM_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
cm_init_locked(struct cm_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
s = splimp();
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
cm_reset(sc);
|
||||
cm_start(ifp);
|
||||
splx(s);
|
||||
cm_reset_locked(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the interface...
|
||||
*
|
||||
* this assumes that it is called inside a critical section...
|
||||
*
|
||||
* Assumes that it is called with sc_mtx held
|
||||
*/
|
||||
void
|
||||
cm_reset(sc)
|
||||
cm_reset_locked(sc)
|
||||
struct cm_softc *sc;
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
@ -444,14 +321,14 @@ cm_reset(sc)
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
cm_start(ifp);
|
||||
cm_start_locked(ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take interface offline
|
||||
*/
|
||||
void
|
||||
cm_stop(sc)
|
||||
cm_stop_locked(sc)
|
||||
struct cm_softc *sc;
|
||||
{
|
||||
/* Stop the interrupts */
|
||||
@ -464,24 +341,32 @@ cm_stop(sc)
|
||||
sc->sc_ifp->if_timer = 0;
|
||||
}
|
||||
|
||||
void
|
||||
cm_start(struct ifnet *ifp)
|
||||
{
|
||||
struct cm_softc *sc = ifp->if_softc;
|
||||
|
||||
CM_LOCK(sc);
|
||||
cm_start_locked(ifp);
|
||||
CM_UNLOCK(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start output on interface. Get another datagram to send
|
||||
* off the interface queue, and copy it to the
|
||||
* interface becore starting the output
|
||||
*
|
||||
* this assumes that it is called inside a critical section...
|
||||
* XXX hm... does it still?
|
||||
*
|
||||
* Assumes that sc_mtx is held
|
||||
*/
|
||||
void
|
||||
cm_start(ifp)
|
||||
cm_start_locked(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct cm_softc *sc = ifp->if_softc;
|
||||
struct mbuf *m,*mp;
|
||||
struct mbuf *m, *mp;
|
||||
|
||||
int cm_ram_ptr;
|
||||
int len, tlen, offset, s, buffer;
|
||||
int len, tlen, offset, buffer;
|
||||
#ifdef CMTIMINGS
|
||||
u_long copystart, lencopy, perbyte;
|
||||
#endif
|
||||
@ -493,18 +378,12 @@ cm_start(ifp)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
s = splimp();
|
||||
|
||||
if (sc->sc_tx_fillcount >= 2) {
|
||||
splx(s);
|
||||
if (sc->sc_tx_fillcount >= 2)
|
||||
return;
|
||||
}
|
||||
|
||||
m = arc_frag_next(ifp);
|
||||
buffer = sc->sc_tx_act ^ 1;
|
||||
|
||||
splx(s);
|
||||
|
||||
if (m == 0)
|
||||
return;
|
||||
|
||||
@ -569,9 +448,6 @@ cm_start(ifp)
|
||||
sc->sc_broadcast[buffer] = (m->m_flags & M_BCAST) != 0;
|
||||
sc->sc_retransmits[buffer] = (m->m_flags & M_BCAST) ? 1 : 5;
|
||||
|
||||
/* actually transmit the packet */
|
||||
s = splimp();
|
||||
|
||||
if (++sc->sc_tx_fillcount > 1) {
|
||||
/*
|
||||
* We are filled up to the rim. No more bufs for the moment,
|
||||
@ -596,7 +472,6 @@ cm_start(ifp)
|
||||
|
||||
ifp->if_timer = ARCTIMEOUT;
|
||||
}
|
||||
splx(s);
|
||||
m_freem(m);
|
||||
|
||||
/*
|
||||
@ -605,20 +480,30 @@ cm_start(ifp)
|
||||
* the hardware retries till shutdown.
|
||||
* This is integrated now in the code above.
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CMSOFTCOPY
|
||||
void
|
||||
cm_srint(void *vsc)
|
||||
{
|
||||
struct cm_softc *sc = (struct cm_softc *)vsc;
|
||||
|
||||
CM_LOCK(sc);
|
||||
cm_srint_locked(vsc);
|
||||
CM_UNLOCK(sc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Arcnet interface receiver soft interrupt:
|
||||
* get the stuff out of any filled buffer we find.
|
||||
*/
|
||||
void
|
||||
cm_srint(vsc)
|
||||
cm_srint_locked(vsc)
|
||||
void *vsc;
|
||||
{
|
||||
struct cm_softc *sc = (struct cm_softc *)vsc;
|
||||
int buffer, len, offset, s, type;
|
||||
int buffer, len, offset, type;
|
||||
int cm_ram_ptr;
|
||||
struct mbuf *m;
|
||||
struct arc_header *ah;
|
||||
@ -626,9 +511,7 @@ cm_srint(vsc)
|
||||
|
||||
ifp = sc->sc_ifp;
|
||||
|
||||
s = splimp();
|
||||
buffer = sc->sc_rx_act ^ 1;
|
||||
splx(s);
|
||||
|
||||
/* Allocate header mbuf */
|
||||
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
||||
@ -695,7 +578,9 @@ cm_srint(vsc)
|
||||
rman_get_bustag(sc->mem_res), rman_get_bushandle(sc->mem_res),
|
||||
cm_ram_ptr + offset, mtod(m, u_char *) + 2, len);
|
||||
|
||||
CM_UNLOCK(sc);
|
||||
arc_input(ifp, m);
|
||||
CM_LOCK(sc);
|
||||
|
||||
m = NULL;
|
||||
ifp->if_ipackets++;
|
||||
@ -707,8 +592,6 @@ cleanup:
|
||||
|
||||
/* mark buffer as invalid by source id 0 */
|
||||
PUTMEM(buffer << 9, 0);
|
||||
s = splimp();
|
||||
|
||||
if (--sc->sc_rx_fillcount == 2 - 1) {
|
||||
|
||||
/* was off, restart it on buffer just emptied */
|
||||
@ -723,11 +606,10 @@ cleanup:
|
||||
if_printf(ifp, "srint: restarted rx on buf %d\n", buffer);
|
||||
#endif
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
__inline static void
|
||||
cm_tint(sc, isr)
|
||||
cm_tint_locked(sc, isr)
|
||||
struct cm_softc *sc;
|
||||
int isr;
|
||||
{
|
||||
@ -807,7 +689,7 @@ cm_tint(sc, isr)
|
||||
softintr_schedule(sc->sc_txcookie);
|
||||
#else
|
||||
/* call it directly */
|
||||
cm_start(ifp);
|
||||
cm_start_locked(ifp);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -825,10 +707,15 @@ cmintr(arg)
|
||||
int buffer;
|
||||
u_long newsec;
|
||||
|
||||
CM_LOCK(sc);
|
||||
|
||||
isr = GETREG(CMSTAT);
|
||||
maskedisr = isr & sc->sc_intmask;
|
||||
if (!maskedisr)
|
||||
if (!maskedisr || (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
CM_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
#if defined(CM_DEBUG) && (CM_DEBUG > 1)
|
||||
@ -881,7 +768,7 @@ cmintr(arg)
|
||||
}
|
||||
sc->sc_recontime = newsec;
|
||||
callout_reset(&sc->sc_recon_ch, 15 * hz,
|
||||
cm_reconwatch, (void *)sc);
|
||||
cm_reconwatch_locked, (void *)sc);
|
||||
}
|
||||
|
||||
if (maskedisr & CM_RI) {
|
||||
@ -936,12 +823,12 @@ cmintr(arg)
|
||||
softintr_schedule(sc->sc_rxcookie);
|
||||
#else
|
||||
/* this one does the copy here */
|
||||
cm_srint(sc);
|
||||
cm_srint_locked(sc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (maskedisr & CM_TA) {
|
||||
cm_tint(sc, isr);
|
||||
cm_tint_locked(sc, isr);
|
||||
}
|
||||
isr = GETREG(CMSTAT);
|
||||
maskedisr = isr & sc->sc_intmask;
|
||||
@ -950,10 +837,11 @@ cmintr(arg)
|
||||
if_printf(ifp, "intr (exit): status 0x%02x, intmask 0x%02x\n",
|
||||
isr, sc->sc_intmask);
|
||||
#endif
|
||||
CM_UNLOCK(sc);
|
||||
}
|
||||
|
||||
void
|
||||
cm_reconwatch(arg)
|
||||
cm_reconwatch_locked(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct cm_softc *sc = arg;
|
||||
@ -981,13 +869,12 @@ cm_ioctl(ifp, command, data)
|
||||
struct cm_softc *sc;
|
||||
struct ifaddr *ifa;
|
||||
struct ifreq *ifr;
|
||||
int s, error;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
sc = ifp->if_softc;
|
||||
ifa = (struct ifaddr *)data;
|
||||
ifr = (struct ifreq *)data;
|
||||
s = splimp();
|
||||
|
||||
#if defined(CM_DEBUG) && (CM_DEBUG > 2)
|
||||
if_printf(ifp, "ioctl() called, cmd = 0x%lx\n", command);
|
||||
@ -1003,13 +890,14 @@ cm_ioctl(ifp, command, data)
|
||||
break;
|
||||
|
||||
case SIOCSIFFLAGS:
|
||||
CM_LOCK(sc);
|
||||
if ((ifp->if_flags & IFF_UP) == 0 &&
|
||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
|
||||
/*
|
||||
* If interface is marked down and it is running,
|
||||
* then stop it.
|
||||
*/
|
||||
cm_stop(sc);
|
||||
cm_stop_locked(sc);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
||||
} else if ((ifp->if_flags & IFF_UP) != 0 &&
|
||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
@ -1017,8 +905,9 @@ cm_ioctl(ifp, command, data)
|
||||
* If interface is marked up and it is stopped, then
|
||||
* start it.
|
||||
*/
|
||||
cm_init(sc);
|
||||
cm_init_locked(sc);
|
||||
}
|
||||
CM_UNLOCK(sc);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1026,7 +915,6 @@ cm_ioctl(ifp, command, data)
|
||||
break;
|
||||
}
|
||||
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1040,16 +928,14 @@ cm_ioctl(ifp, command, data)
|
||||
* Only thing we do is disable transmitter. We'll get a transmit timeout,
|
||||
* and the int handler will have to decide not to retransmit (in case
|
||||
* retransmission is implemented).
|
||||
*
|
||||
* This one assumes being called inside splimp()
|
||||
*/
|
||||
|
||||
void
|
||||
cm_watchdog(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct cm_softc *sc = ifp->if_softc;
|
||||
|
||||
CM_LOCK(sc);
|
||||
PUTREG(CMCMD, CM_TXDIS);
|
||||
return;
|
||||
CM_UNLOCK(sc);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define _SMC90CXVAR_H_
|
||||
|
||||
#define CM_IO_PORTS 16
|
||||
#define CM_MEM_SIZE 0x800
|
||||
|
||||
/* register offsets */
|
||||
|
||||
|
@ -57,14 +57,13 @@
|
||||
|
||||
struct cm_softc {
|
||||
struct ifnet *sc_ifp; /* Common arcnet structures */
|
||||
struct mtx sc_mtx; /* sc mutex */
|
||||
|
||||
int port_rid; /* resource id for port range */
|
||||
struct resource *port_res; /* resource for port range */
|
||||
int port_used; /* ports used */
|
||||
|
||||
int mem_rid; /* resource id for memory range */
|
||||
struct resource *mem_res; /* resource for memory range */
|
||||
int mem_used; /* memory used */
|
||||
|
||||
int irq_rid; /* resource id for irq */
|
||||
struct resource *irq_res; /* resource for irq */
|
||||
@ -89,15 +88,30 @@ struct cm_softc {
|
||||
|
||||
int cm_attach(device_t dev);
|
||||
void cmintr(void *);
|
||||
|
||||
int cm_probe(device_t dev);
|
||||
void cm_stop(struct cm_softc *sc);
|
||||
|
||||
int cm_alloc_port(device_t dev, int rid, int size);
|
||||
int cm_alloc_memory(device_t dev, int rid, int size);
|
||||
int cm_alloc_irq(device_t dev, int rid);
|
||||
void cm_stop_locked(struct cm_softc *sc);
|
||||
void cm_release_resources(device_t dev);
|
||||
|
||||
extern devclass_t cm_devclass;
|
||||
|
||||
#define CM_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
|
||||
#define CM_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
|
||||
|
||||
/* short notation */
|
||||
#define GETREG(off) \
|
||||
bus_space_read_1(rman_get_bustag((sc)->port_res), \
|
||||
rman_get_bushandle((sc)->port_res), \
|
||||
(off))
|
||||
#define PUTREG(off, value) \
|
||||
bus_space_write_1(rman_get_bustag((sc)->port_res), \
|
||||
rman_get_bushandle((sc)->port_res), \
|
||||
(off), (value))
|
||||
#define GETMEM(off) \
|
||||
bus_space_read_1(rman_get_bustag((sc)->mem_res), \
|
||||
rman_get_bushandle((sc)->mem_res), \
|
||||
(off))
|
||||
#define PUTMEM(off, value) \
|
||||
bus_space_write_1(rman_get_bustag((sc)->mem_res), \
|
||||
rman_get_bushandle((sc)->mem_res), \
|
||||
(off), (value))
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user