2012-07-22 18:32:49 +04:00
|
|
|
/* $NetBSD: if_xi.c,v 1.73 2012/07/22 14:33:05 matt Exp $ */
|
2000-06-06 03:14:22 +04:00
|
|
|
/* OpenBSD: if_xe.c,v 1.9 1999/09/16 11:28:42 niklas Exp */
|
|
|
|
|
2000-10-02 03:32:39 +04:00
|
|
|
/*
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
* Copyright (c) 2004 Charles M. Hannum. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by Charles M. Hannum.
|
|
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
2000-10-02 03:32:39 +04:00
|
|
|
*/
|
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1999 Niklas Hallqvist, Brandon Creighton, Job de Haas
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by Niklas Hallqvist,
|
|
|
|
* Brandon Creighton and Job de Haas.
|
|
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A driver for Xircom CreditCard PCMCIA Ethernet adapters.
|
|
|
|
*/
|
|
|
|
|
2001-11-13 10:24:43 +03:00
|
|
|
#include <sys/cdefs.h>
|
2012-07-22 18:32:49 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: if_xi.c,v 1.73 2012/07/22 14:33:05 matt Exp $");
|
2001-11-13 10:24:43 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
#include "opt_inet.h"
|
2003-06-23 15:00:59 +04:00
|
|
|
#include "opt_ipx.h"
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/device.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/socket.h>
|
2004-08-12 22:23:50 +04:00
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/proc.h>
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_dl.h>
|
|
|
|
#include <net/if_media.h>
|
|
|
|
#include <net/if_types.h>
|
|
|
|
#include <net/if_ether.h>
|
|
|
|
|
|
|
|
#ifdef INET
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/in_var.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <netinet/if_inarp.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef IPX
|
|
|
|
#include <netipx/ipx.h>
|
|
|
|
#include <netipx/ipx_if.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#include <net/bpf.h>
|
|
|
|
#include <net/bpfdesc.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Maximum number of bytes to read per interrupt. Linux recommends
|
|
|
|
* somewhere between 2000-22000.
|
|
|
|
* XXX This is currently a hard maximum.
|
|
|
|
*/
|
|
|
|
#define MAX_BYTES_INTR 12000
|
|
|
|
|
|
|
|
#include <dev/mii/mii.h>
|
|
|
|
#include <dev/mii/miivar.h>
|
|
|
|
|
|
|
|
#include <dev/pcmcia/pcmciareg.h>
|
|
|
|
#include <dev/pcmcia/pcmciavar.h>
|
|
|
|
#include <dev/pcmcia/pcmciadevs.h>
|
|
|
|
|
|
|
|
#include <dev/pcmcia/if_xireg.h>
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
#include <dev/pcmcia/if_xivar.h>
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
#ifdef __GNUC__
|
2005-12-24 23:27:29 +03:00
|
|
|
#define INLINE inline
|
2000-06-06 03:14:22 +04:00
|
|
|
#else
|
|
|
|
#define INLINE
|
|
|
|
#endif /* __GNUC__ */
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
#define XIDEBUG
|
2004-08-08 09:56:50 +04:00
|
|
|
#define XIDEBUG_VALUE 0
|
2004-08-07 00:38:09 +04:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
#ifdef XIDEBUG
|
|
|
|
#define DPRINTF(cat, x) if (xidebug & (cat)) printf x
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
#define XID_CONFIG 0x01
|
|
|
|
#define XID_MII 0x02
|
|
|
|
#define XID_INTR 0x04
|
|
|
|
#define XID_FIFO 0x08
|
|
|
|
#define XID_MCAST 0x10
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
#ifdef XIDEBUG_VALUE
|
|
|
|
int xidebug = XIDEBUG_VALUE;
|
|
|
|
#else
|
|
|
|
int xidebug = 0;
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
#define DPRINTF(cat, x) (void)0
|
|
|
|
#endif
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
#define STATIC
|
|
|
|
|
2005-02-04 05:10:35 +03:00
|
|
|
STATIC int xi_enable(struct xi_softc *);
|
|
|
|
STATIC void xi_disable(struct xi_softc *);
|
|
|
|
STATIC void xi_cycle_power(struct xi_softc *);
|
2007-03-04 08:59:00 +03:00
|
|
|
STATIC int xi_ether_ioctl(struct ifnet *, u_long cmd, void *);
|
2005-02-04 05:10:35 +03:00
|
|
|
STATIC void xi_full_reset(struct xi_softc *);
|
|
|
|
STATIC void xi_init(struct xi_softc *);
|
2007-03-04 08:59:00 +03:00
|
|
|
STATIC int xi_ioctl(struct ifnet *, u_long, void *);
|
2009-05-12 18:38:26 +04:00
|
|
|
STATIC int xi_mdi_read(device_t, int, int);
|
|
|
|
STATIC void xi_mdi_write(device_t, int, int, int);
|
2005-02-04 05:10:35 +03:00
|
|
|
STATIC int xi_mediachange(struct ifnet *);
|
|
|
|
STATIC u_int16_t xi_get(struct xi_softc *);
|
|
|
|
STATIC void xi_reset(struct xi_softc *);
|
|
|
|
STATIC void xi_set_address(struct xi_softc *);
|
|
|
|
STATIC void xi_start(struct ifnet *);
|
2012-07-22 18:32:49 +04:00
|
|
|
STATIC void xi_statchg(struct ifnet *);
|
2005-02-04 05:10:35 +03:00
|
|
|
STATIC void xi_stop(struct xi_softc *);
|
|
|
|
STATIC void xi_watchdog(struct ifnet *);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_attach(struct xi_softc *sc, u_int8_t *myea)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
#if 0
|
2000-06-06 03:14:22 +04:00
|
|
|
/*
|
2001-07-01 05:57:29 +04:00
|
|
|
* Configuration as advised by DINGO documentation.
|
2000-06-06 03:14:22 +04:00
|
|
|
* Dingo has some extra configuration registers in the CCR space.
|
|
|
|
*/
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_chipset >= XI_CHIPSET_DINGO) {
|
2000-06-06 03:14:22 +04:00
|
|
|
struct pcmcia_mem_handle pcmh;
|
|
|
|
int ccr_window;
|
2003-02-27 10:50:57 +03:00
|
|
|
bus_size_t ccr_offset;
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2001-07-01 05:57:29 +04:00
|
|
|
/* get access to the DINGO CCR space */
|
2000-06-06 03:14:22 +04:00
|
|
|
if (pcmcia_mem_alloc(psc->sc_pf, PCMCIA_CCR_SIZE_DINGO,
|
|
|
|
&pcmh)) {
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi: bad mem alloc\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
if (pcmcia_mem_map(psc->sc_pf, PCMCIA_MEM_ATTR,
|
|
|
|
psc->sc_pf->ccr_base, PCMCIA_CCR_SIZE_DINGO,
|
|
|
|
&pcmh, &ccr_offset, &ccr_window)) {
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi: bad mem map\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
pcmcia_mem_free(psc->sc_pf, &pcmh);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2001-07-01 05:57:29 +04:00
|
|
|
/* enable the second function - usually modem */
|
2000-06-06 03:14:22 +04:00
|
|
|
bus_space_write_1(pcmh.memt, pcmh.memh,
|
|
|
|
ccr_offset + PCMCIA_CCR_DCOR0, PCMCIA_CCR_DCOR0_SFINT);
|
|
|
|
bus_space_write_1(pcmh.memt, pcmh.memh,
|
|
|
|
ccr_offset + PCMCIA_CCR_DCOR1,
|
|
|
|
PCMCIA_CCR_DCOR1_FORCE_LEVIREQ | PCMCIA_CCR_DCOR1_D6);
|
|
|
|
bus_space_write_1(pcmh.memt, pcmh.memh,
|
|
|
|
ccr_offset + PCMCIA_CCR_DCOR2, 0);
|
|
|
|
bus_space_write_1(pcmh.memt, pcmh.memh,
|
|
|
|
ccr_offset + PCMCIA_CCR_DCOR3, 0);
|
|
|
|
bus_space_write_1(pcmh.memt, pcmh.memh,
|
|
|
|
ccr_offset + PCMCIA_CCR_DCOR4, 0);
|
|
|
|
|
|
|
|
/* We don't need them anymore and can free them (I think). */
|
|
|
|
pcmcia_mem_unmap(psc->sc_pf, ccr_window);
|
|
|
|
pcmcia_mem_free(psc->sc_pf, &pcmh);
|
|
|
|
}
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
#endif
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
/* Reset and initialize the card. */
|
|
|
|
xi_full_reset(sc);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2009-12-07 02:05:39 +03:00
|
|
|
printf("%s: MAC address %s\n", device_xname(sc->sc_dev), ether_sprintf(myea));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
ifp = &sc->sc_ethercom.ec_if;
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
/* Initialize the ifnet structure. */
|
2009-12-07 02:05:39 +03:00
|
|
|
strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
|
2000-06-06 03:14:22 +04:00
|
|
|
ifp->if_softc = sc;
|
|
|
|
ifp->if_start = xi_start;
|
|
|
|
ifp->if_ioctl = xi_ioctl;
|
|
|
|
ifp->if_watchdog = xi_watchdog;
|
|
|
|
ifp->if_flags =
|
|
|
|
IFF_BROADCAST | IFF_NOTRAILERS | IFF_SIMPLEX | IFF_MULTICAST;
|
2000-12-14 09:27:23 +03:00
|
|
|
IFQ_SET_READY(&ifp->if_snd);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
/* 802.1q capability */
|
|
|
|
sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
|
|
|
|
|
|
|
|
/* Attach the interface. */
|
|
|
|
if_attach(ifp);
|
|
|
|
ether_ifattach(ifp, myea);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize our media structures and probe the MII.
|
|
|
|
*/
|
|
|
|
sc->sc_mii.mii_ifp = ifp;
|
|
|
|
sc->sc_mii.mii_readreg = xi_mdi_read;
|
|
|
|
sc->sc_mii.mii_writereg = xi_mdi_write;
|
|
|
|
sc->sc_mii.mii_statchg = xi_statchg;
|
Make many ethernet drivers share the common code for MII media
handling, ether_mediastatus() and ether_mediachange(). Check for
a non-ENXIO error return from mii_mediachg(). (ENXIO indicates
that a PHY is suspended.)
This patch shrinks the source code size by 979 lines. There was
a 5100-byte savings on the NetBSD/i386 kernel configuration, ALL.
I have made a few miscellaneous changes, too:
gem(4): use LIST_EMPTY(), LIST_FOREACH().
mtd(4): handle media ioctls, for a change!
axe(4): do not track link status in sc->axe_link any longer
nfe(4), aue(4), axe(4), udav(4), url(4): do not reset all PHYs
on a change of media
Except for the change to mtd(4), no functional changes are intended.
XXX This patch affects more architectures than I can feasibly
XXX compile and run. I have compiled macppc, sparc64, i386. I
XXX have run the patches on i386 boxen with bnx(4) and sip(4).
XXX Compiling and running on evbmips (MERAKI, ADM5120) is in
XXX progress.
2008-01-20 01:10:14 +03:00
|
|
|
sc->sc_ethercom.ec_mii = &sc->sc_mii;
|
2000-06-06 03:14:22 +04:00
|
|
|
ifmedia_init(&sc->sc_mii.mii_media, 0, xi_mediachange,
|
Make many ethernet drivers share the common code for MII media
handling, ether_mediastatus() and ether_mediachange(). Check for
a non-ENXIO error return from mii_mediachg(). (ENXIO indicates
that a PHY is suspended.)
This patch shrinks the source code size by 979 lines. There was
a 5100-byte savings on the NetBSD/i386 kernel configuration, ALL.
I have made a few miscellaneous changes, too:
gem(4): use LIST_EMPTY(), LIST_FOREACH().
mtd(4): handle media ioctls, for a change!
axe(4): do not track link status in sc->axe_link any longer
nfe(4), aue(4), axe(4), udav(4), url(4): do not reset all PHYs
on a change of media
Except for the change to mtd(4), no functional changes are intended.
XXX This patch affects more architectures than I can feasibly
XXX compile and run. I have compiled macppc, sparc64, i386. I
XXX have run the patches on i386 boxen with bnx(4) and sip(4).
XXX Compiling and running on evbmips (MERAKI, ADM5120) is in
XXX progress.
2008-01-20 01:10:14 +03:00
|
|
|
ether_mediastatus);
|
2000-06-06 03:14:22 +04:00
|
|
|
DPRINTF(XID_MII | XID_CONFIG,
|
2009-12-07 02:05:39 +03:00
|
|
|
("xi: bmsr %x\n", xi_mdi_read(sc->sc_dev, 0, 1)));
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
|
2009-12-07 02:05:39 +03:00
|
|
|
mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
|
2000-06-06 03:14:22 +04:00
|
|
|
MII_OFFSET_ANY, 0);
|
|
|
|
if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL)
|
|
|
|
ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO, 0,
|
|
|
|
NULL);
|
|
|
|
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
|
|
|
|
|
2012-02-02 23:42:57 +04:00
|
|
|
rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
|
|
|
|
RND_TYPE_NET, 0);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2009-05-12 18:38:26 +04:00
|
|
|
xi_detach(device_t self, int flags)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
2009-11-13 04:14:35 +03:00
|
|
|
struct xi_softc *sc = device_private(self);
|
2000-06-06 03:14:22 +04:00
|
|
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_detach()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2004-08-08 11:25:20 +04:00
|
|
|
xi_disable(sc);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
rnd_detach_source(&sc->sc_rnd_source);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
|
|
|
|
ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
|
|
|
|
ether_ifdetach(ifp);
|
|
|
|
if_detach(ifp);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-07-25 01:50:10 +04:00
|
|
|
int
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_intr(void *arg)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
struct xi_softc *sc = arg;
|
|
|
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
|
2004-08-09 09:11:33 +04:00
|
|
|
u_int8_t esr, rsr, isr, rx_status;
|
2003-10-29 02:26:28 +03:00
|
|
|
u_int16_t tx_status, recvcount = 0, tempint;
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_intr()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2009-12-07 02:05:39 +03:00
|
|
|
if (sc->sc_enabled == 0 || !device_is_active(sc->sc_dev))
|
2000-06-06 03:14:22 +04:00
|
|
|
return (0);
|
|
|
|
|
|
|
|
ifp->if_timer = 0; /* turn watchdog timer off */
|
|
|
|
|
2004-08-09 09:11:33 +04:00
|
|
|
PAGE(sc, 0);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_chipset >= XI_CHIPSET_MOHAWK) {
|
2000-06-06 03:14:22 +04:00
|
|
|
/* Disable interrupt (Linux does it). */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(sc->sc_bst, sc->sc_bsh, CR, 0);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
2004-08-12 23:42:03 +04:00
|
|
|
esr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, ESR);
|
|
|
|
isr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, ISR0);
|
|
|
|
rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, RSR);
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
/* Check to see if card has been ejected. */
|
|
|
|
if (isr == 0xff) {
|
|
|
|
#ifdef DIAGNOSTIC
|
2009-12-07 02:05:39 +03:00
|
|
|
printf("%s: interrupt for dead card\n",
|
|
|
|
device_xname(sc->sc_dev));
|
2000-06-06 03:14:22 +04:00
|
|
|
#endif
|
|
|
|
goto end;
|
|
|
|
}
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
DPRINTF(XID_INTR, ("xi: isr=%02x\n", isr));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
PAGE(sc, 0x40);
|
2000-06-06 03:14:22 +04:00
|
|
|
rx_status =
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_read_1(sc->sc_bst, sc->sc_bsh, RXST0);
|
|
|
|
bus_space_write_1(sc->sc_bst, sc->sc_bsh, RXST0, ~rx_status & 0xff);
|
2000-06-06 03:14:22 +04:00
|
|
|
tx_status =
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_read_1(sc->sc_bst, sc->sc_bsh, TXST0);
|
2002-09-22 14:13:32 +04:00
|
|
|
tx_status |=
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_read_1(sc->sc_bst, sc->sc_bsh, TXST1) << 8;
|
|
|
|
bus_space_write_1(sc->sc_bst, sc->sc_bsh, TXST0, 0);
|
|
|
|
bus_space_write_1(sc->sc_bst, sc->sc_bsh, TXST1, 0);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
DPRINTF(XID_INTR, ("xi: rx_status=%02x tx_status=%04x\n", rx_status,
|
|
|
|
tx_status));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
PAGE(sc, 0);
|
|
|
|
while (esr & FULL_PKT_RCV) {
|
|
|
|
if (!(rsr & RSR_RX_OK))
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Compare bytes read this interrupt to hard maximum. */
|
|
|
|
if (recvcount > MAX_BYTES_INTR) {
|
|
|
|
DPRINTF(XID_INTR,
|
2000-06-09 12:22:13 +04:00
|
|
|
("xi: too many bytes this interrupt\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
ifp->if_iqdrops++;
|
|
|
|
/* Drop packet. */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_2(sc->sc_bst, sc->sc_bsh, DO0,
|
|
|
|
DO_SKIP_RX_PKT);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
tempint = xi_get(sc); /* XXX doesn't check the error! */
|
|
|
|
recvcount += tempint;
|
|
|
|
ifp->if_ibytes += tempint;
|
2004-08-12 23:42:03 +04:00
|
|
|
esr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, ESR);
|
|
|
|
rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, RSR);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
/* Packet too long? */
|
|
|
|
if (rsr & RSR_TOO_LONG) {
|
|
|
|
ifp->if_ierrors++;
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_INTR, ("xi: packet too long\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* CRC error? */
|
|
|
|
if (rsr & RSR_CRCERR) {
|
|
|
|
ifp->if_ierrors++;
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_INTR, ("xi: CRC error detected\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Alignment error? */
|
|
|
|
if (rsr & RSR_ALIGNERR) {
|
|
|
|
ifp->if_ierrors++;
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_INTR, ("xi: alignment error detected\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for rx overrun. */
|
|
|
|
if (rx_status & RX_OVERRUN) {
|
2002-09-22 14:13:32 +04:00
|
|
|
ifp->if_ierrors++;
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(sc->sc_bst, sc->sc_bsh, CR, CLR_RX_OVERRUN);
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_INTR, ("xi: overrun cleared\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
/* Try to start more packets transmitting. */
|
2000-12-14 09:27:23 +03:00
|
|
|
if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
|
2000-06-06 03:14:22 +04:00
|
|
|
xi_start(ifp);
|
|
|
|
|
|
|
|
/* Detected excessive collisions? */
|
|
|
|
if ((tx_status & EXCESSIVE_COLL) && ifp->if_opackets > 0) {
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_INTR, ("xi: excessive collisions\n"));
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(sc->sc_bst, sc->sc_bsh, CR, RESTART_TX);
|
2000-06-06 03:14:22 +04:00
|
|
|
ifp->if_oerrors++;
|
|
|
|
}
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
if ((tx_status & TX_ABORT) && ifp->if_opackets > 0)
|
|
|
|
ifp->if_oerrors++;
|
|
|
|
|
2003-10-29 02:26:28 +03:00
|
|
|
/* have handled the interrupt */
|
2005-02-27 03:26:58 +03:00
|
|
|
rnd_add_uint32(&sc->sc_rnd_source, tx_status);
|
2003-10-29 02:26:28 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
end:
|
|
|
|
/* Reenable interrupts. */
|
2004-08-09 09:11:33 +04:00
|
|
|
PAGE(sc, 0);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(sc->sc_bst, sc->sc_bsh, CR, ENABLE_INT);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pull a packet from the card into an mbuf chain.
|
|
|
|
*/
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC u_int16_t
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_get(struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
|
|
|
|
struct mbuf *top, **mp, *m;
|
|
|
|
u_int16_t pktlen, len, recvcount = 0;
|
|
|
|
u_int8_t *data;
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_get()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
PAGE(sc, 0);
|
|
|
|
pktlen =
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_read_2(sc->sc_bst, sc->sc_bsh, RBC0) & RBC_COUNT_MASK;
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
DPRINTF(XID_CONFIG, ("xi_get: pktlen=%d\n", pktlen));
|
|
|
|
|
|
|
|
if (pktlen == 0) {
|
|
|
|
/*
|
|
|
|
* XXX At least one CE2 sets RBC0 == 0 occasionally, and only
|
|
|
|
* when MPE is set. It is not known why.
|
|
|
|
*/
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX should this be incremented now ? */
|
|
|
|
recvcount += pktlen;
|
|
|
|
|
|
|
|
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
2006-04-14 21:46:29 +04:00
|
|
|
if (m == NULL)
|
2000-06-06 03:14:22 +04:00
|
|
|
return (recvcount);
|
|
|
|
m->m_pkthdr.rcvif = ifp;
|
|
|
|
m->m_pkthdr.len = pktlen;
|
|
|
|
len = MHLEN;
|
2006-04-14 21:46:29 +04:00
|
|
|
top = NULL;
|
2000-06-06 03:14:22 +04:00
|
|
|
mp = ⊤
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
while (pktlen > 0) {
|
|
|
|
if (top) {
|
|
|
|
MGET(m, M_DONTWAIT, MT_DATA);
|
2006-04-14 21:46:29 +04:00
|
|
|
if (m == NULL) {
|
2000-06-06 03:14:22 +04:00
|
|
|
m_freem(top);
|
|
|
|
return (recvcount);
|
|
|
|
}
|
|
|
|
len = MLEN;
|
|
|
|
}
|
|
|
|
if (pktlen >= MINCLSIZE) {
|
|
|
|
MCLGET(m, M_DONTWAIT);
|
|
|
|
if (!(m->m_flags & M_EXT)) {
|
|
|
|
m_freem(m);
|
|
|
|
m_freem(top);
|
|
|
|
return (recvcount);
|
|
|
|
}
|
|
|
|
len = MCLBYTES;
|
|
|
|
}
|
2006-04-14 21:46:29 +04:00
|
|
|
if (top == NULL) {
|
2007-03-04 08:59:00 +03:00
|
|
|
char *newdata = (char *)ALIGN(m->m_data +
|
2000-06-06 03:14:22 +04:00
|
|
|
sizeof(struct ether_header)) -
|
|
|
|
sizeof(struct ether_header);
|
|
|
|
len -= newdata - m->m_data;
|
|
|
|
m->m_data = newdata;
|
|
|
|
}
|
|
|
|
len = min(pktlen, len);
|
|
|
|
data = mtod(m, u_int8_t *);
|
|
|
|
if (len > 1) {
|
|
|
|
len &= ~1;
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_read_multi_2(sc->sc_bst, sc->sc_bsh, EDP,
|
|
|
|
(u_int16_t *)data, len>>1);
|
2000-06-06 03:14:22 +04:00
|
|
|
} else
|
2004-08-12 23:42:03 +04:00
|
|
|
*data = bus_space_read_1(sc->sc_bst, sc->sc_bsh, EDP);
|
2000-06-06 03:14:22 +04:00
|
|
|
m->m_len = len;
|
|
|
|
pktlen -= len;
|
|
|
|
*mp = m;
|
|
|
|
mp = &m->m_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip Rx packet. */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_2(sc->sc_bst, sc->sc_bsh, DO0, DO_SKIP_RX_PKT);
|
2005-01-30 22:30:16 +03:00
|
|
|
|
2006-04-14 21:46:29 +04:00
|
|
|
if (top == NULL)
|
|
|
|
return recvcount;
|
|
|
|
|
2005-01-30 22:30:16 +03:00
|
|
|
/* Trim the CRC off the end of the packet. */
|
|
|
|
m_adj(top, -ETHER_CRC_LEN);
|
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
ifp->if_ipackets++;
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2010-04-05 11:19:28 +04:00
|
|
|
bpf_mtap(ifp, top);
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
(*ifp->if_input)(ifp, top);
|
|
|
|
return (recvcount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Serial management for the MII.
|
|
|
|
* The DELAY's below stem from the fact that the maximum frequency
|
|
|
|
* acceptable on the MDC pin is 2.5 MHz and fast processors can easily
|
|
|
|
* go much faster than that.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Let the MII serial management be idle for one period. */
|
2005-02-04 05:10:35 +03:00
|
|
|
static INLINE void xi_mdi_idle(struct xi_softc *);
|
2000-06-06 03:14:22 +04:00
|
|
|
static INLINE void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_mdi_idle(struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
|
|
|
|
|
|
|
/* Drive MDC low... */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP2, MDC_LOW);
|
2000-06-06 03:14:22 +04:00
|
|
|
DELAY(1);
|
|
|
|
|
|
|
|
/* and high again. */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP2, MDC_HIGH);
|
2000-06-06 03:14:22 +04:00
|
|
|
DELAY(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pulse out one bit of data. */
|
2005-02-04 05:10:35 +03:00
|
|
|
static INLINE void xi_mdi_pulse(struct xi_softc *, int);
|
2000-06-06 03:14:22 +04:00
|
|
|
static INLINE void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_mdi_pulse(struct xi_softc *sc, int data)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
|
|
|
u_int8_t bit = data ? MDIO_HIGH : MDIO_LOW;
|
|
|
|
|
|
|
|
/* First latch the data bit MDIO with clock bit MDC low...*/
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP2, bit | MDC_LOW);
|
2000-06-06 03:14:22 +04:00
|
|
|
DELAY(1);
|
|
|
|
|
|
|
|
/* then raise the clock again, preserving the data bit. */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP2, bit | MDC_HIGH);
|
2000-06-06 03:14:22 +04:00
|
|
|
DELAY(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Probe one bit of data. */
|
2005-02-04 05:10:35 +03:00
|
|
|
static INLINE int xi_mdi_probe(struct xi_softc *sc);
|
2000-06-06 03:14:22 +04:00
|
|
|
static INLINE int
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_mdi_probe(struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
|
|
|
u_int8_t x;
|
|
|
|
|
|
|
|
/* Pull clock bit MDCK low... */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP2, MDC_LOW);
|
2000-06-06 03:14:22 +04:00
|
|
|
DELAY(1);
|
|
|
|
|
|
|
|
/* Read data and drive clock high again. */
|
2004-08-12 23:42:03 +04:00
|
|
|
x = bus_space_read_1(bst, bsh, GP2);
|
|
|
|
bus_space_write_1(bst, bsh, GP2, MDC_HIGH);
|
2000-06-06 03:14:22 +04:00
|
|
|
DELAY(1);
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
return (x & MDIO);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Pulse out a sequence of data bits. */
|
2005-02-04 05:10:35 +03:00
|
|
|
static INLINE void xi_mdi_pulse_bits(struct xi_softc *, u_int32_t, int);
|
2000-06-06 03:14:22 +04:00
|
|
|
static INLINE void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_mdi_pulse_bits(struct xi_softc *sc, u_int32_t data, int len)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
u_int32_t mask;
|
|
|
|
|
|
|
|
for (mask = 1 << (len - 1); mask; mask >>= 1)
|
|
|
|
xi_mdi_pulse(sc, data & mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read a PHY register. */
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC int
|
2009-05-12 18:38:26 +04:00
|
|
|
xi_mdi_read(device_t self, int phy, int reg)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
2009-11-13 04:14:35 +03:00
|
|
|
struct xi_softc *sc = device_private(self);
|
2000-06-06 03:14:22 +04:00
|
|
|
int i;
|
|
|
|
u_int32_t mask;
|
|
|
|
u_int32_t data = 0;
|
|
|
|
|
|
|
|
PAGE(sc, 2);
|
|
|
|
for (i = 0; i < 32; i++) /* Synchronize. */
|
|
|
|
xi_mdi_pulse(sc, 1);
|
|
|
|
xi_mdi_pulse_bits(sc, 0x06, 4); /* Start + Read opcode */
|
|
|
|
xi_mdi_pulse_bits(sc, phy, 5); /* PHY address */
|
|
|
|
xi_mdi_pulse_bits(sc, reg, 5); /* PHY register */
|
|
|
|
xi_mdi_idle(sc); /* Turn around. */
|
|
|
|
xi_mdi_probe(sc); /* Drop initial zero bit. */
|
|
|
|
|
|
|
|
for (mask = 1 << 15; mask; mask >>= 1) {
|
|
|
|
if (xi_mdi_probe(sc))
|
|
|
|
data |= mask;
|
|
|
|
}
|
|
|
|
xi_mdi_idle(sc);
|
|
|
|
|
|
|
|
DPRINTF(XID_MII,
|
|
|
|
("xi_mdi_read: phy %d reg %d -> %x\n", phy, reg, data));
|
|
|
|
|
|
|
|
return (data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write a PHY register. */
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-05-12 18:38:26 +04:00
|
|
|
xi_mdi_write(device_t self, int phy, int reg, int value)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
2009-11-13 04:14:35 +03:00
|
|
|
struct xi_softc *sc = device_private(self);
|
2000-06-06 03:14:22 +04:00
|
|
|
int i;
|
|
|
|
|
|
|
|
PAGE(sc, 2);
|
|
|
|
for (i = 0; i < 32; i++) /* Synchronize. */
|
|
|
|
xi_mdi_pulse(sc, 1);
|
|
|
|
xi_mdi_pulse_bits(sc, 0x05, 4); /* Start + Write opcode */
|
|
|
|
xi_mdi_pulse_bits(sc, phy, 5); /* PHY address */
|
|
|
|
xi_mdi_pulse_bits(sc, reg, 5); /* PHY register */
|
|
|
|
xi_mdi_pulse_bits(sc, 0x02, 2); /* Turn around. */
|
|
|
|
xi_mdi_pulse_bits(sc, value, 16); /* Write the data */
|
|
|
|
xi_mdi_idle(sc); /* Idle away. */
|
|
|
|
|
|
|
|
DPRINTF(XID_MII,
|
|
|
|
("xi_mdi_write: phy %d reg %d val %x\n", phy, reg, value));
|
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2012-07-22 18:32:49 +04:00
|
|
|
xi_statchg(struct ifnet *ifp)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
/* XXX Update ifp->if_baudrate */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change media according to request.
|
|
|
|
*/
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC int
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_mediachange(struct ifnet *ifp)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
2004-08-08 11:25:20 +04:00
|
|
|
int s;
|
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_mediachange()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2004-08-08 11:25:20 +04:00
|
|
|
if (ifp->if_flags & IFF_UP) {
|
|
|
|
s = splnet();
|
2000-06-06 03:14:22 +04:00
|
|
|
xi_init(ifp->if_softc);
|
2004-08-08 11:25:20 +04:00
|
|
|
splx(s);
|
|
|
|
}
|
2000-06-06 03:14:22 +04:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_reset(struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
int s;
|
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_reset()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
s = splnet();
|
|
|
|
xi_stop(sc);
|
|
|
|
xi_init(sc);
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_watchdog(struct ifnet *ifp)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
struct xi_softc *sc = ifp->if_softc;
|
|
|
|
|
2009-12-07 02:05:39 +03:00
|
|
|
printf("%s: device timeout\n", device_xname(sc->sc_dev));
|
2000-06-06 03:14:22 +04:00
|
|
|
++ifp->if_oerrors;
|
|
|
|
|
|
|
|
xi_reset(sc);
|
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_stop(register struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_stop()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2004-08-09 08:47:40 +04:00
|
|
|
PAGE(sc, 0x40);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, CMD0, DISABLE_RX);
|
2004-08-09 08:47:40 +04:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
/* Disable interrupts. */
|
|
|
|
PAGE(sc, 0);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, CR, 0);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
PAGE(sc, 1);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, IMR0, 0);
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
/* Cancel watchdog timer. */
|
|
|
|
sc->sc_ethercom.ec_if.if_timer = 0;
|
|
|
|
}
|
|
|
|
|
2004-08-08 11:25:20 +04:00
|
|
|
STATIC int
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_enable(struct xi_softc *sc)
|
2004-08-08 11:25:20 +04:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (!sc->sc_enabled) {
|
|
|
|
error = (*sc->sc_enable)(sc);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
sc->sc_enabled = 1;
|
|
|
|
xi_full_reset(sc);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_disable(struct xi_softc *sc)
|
2004-08-08 11:25:20 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
if (sc->sc_enabled) {
|
|
|
|
sc->sc_enabled = 0;
|
|
|
|
(*sc->sc_disable)(sc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_init(struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_init()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
/* Setup the ethernet interrupt mask. */
|
|
|
|
PAGE(sc, 1);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, IMR0,
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
ISR_TX_OFLOW | ISR_PKT_TX | ISR_MAC_INT | /* ISR_RX_EARLY | */
|
|
|
|
ISR_RX_FULL | ISR_RX_PKT_REJ | ISR_FORCED_INT);
|
|
|
|
if (sc->sc_chipset < XI_CHIPSET_DINGO) {
|
|
|
|
/* XXX What is this? Not for Dingo at least. */
|
|
|
|
/* Unmask TX underrun detection */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, IMR1, 1);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Enable interrupts. */
|
|
|
|
PAGE(sc, 0);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, CR, ENABLE_INT);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
|
2004-08-09 08:47:40 +04:00
|
|
|
xi_set_address(sc);
|
|
|
|
|
|
|
|
PAGE(sc, 0x40);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, CMD0, ENABLE_RX | ONLINE);
|
2004-08-09 08:47:40 +04:00
|
|
|
|
|
|
|
PAGE(sc, 0);
|
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
/* Set current media. */
|
|
|
|
mii_mediachg(&sc->sc_mii);
|
|
|
|
|
|
|
|
ifp->if_flags |= IFF_RUNNING;
|
|
|
|
ifp->if_flags &= ~IFF_OACTIVE;
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
|
2004-08-08 11:25:20 +04:00
|
|
|
xi_start(ifp);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Start outputting on the interface.
|
|
|
|
* Always called as splnet().
|
|
|
|
*/
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_start(struct ifnet *ifp)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
struct xi_softc *sc = ifp->if_softc;
|
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
|
|
|
unsigned int s, len, pad = 0;
|
|
|
|
struct mbuf *m0, *m;
|
|
|
|
u_int16_t space;
|
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_start()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/* Don't transmit if interface is busy or not running. */
|
|
|
|
if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) {
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi: interface busy or not running\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Peek at the next packet. */
|
2000-12-14 09:27:23 +03:00
|
|
|
IFQ_POLL(&ifp->if_snd, m0);
|
2000-06-06 03:14:22 +04:00
|
|
|
if (m0 == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* We need to use m->m_pkthdr.len, so require the header. */
|
|
|
|
if (!(m0->m_flags & M_PKTHDR))
|
|
|
|
panic("xi_start: no header mbuf");
|
|
|
|
|
|
|
|
len = m0->m_pkthdr.len;
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
#if 1
|
2000-06-06 03:14:22 +04:00
|
|
|
/* Pad to ETHER_MIN_LEN - ETHER_CRC_LEN. */
|
|
|
|
if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
|
|
|
|
pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
#else
|
|
|
|
pad = 0;
|
|
|
|
#endif
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
PAGE(sc, 0);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_2(bst, bsh, TRS, (u_int16_t)len + pad + 2);
|
|
|
|
space = bus_space_read_2(bst, bsh, TSO) & 0x7fff;
|
2000-06-06 03:14:22 +04:00
|
|
|
if (len + pad + 2 > space) {
|
|
|
|
DPRINTF(XID_FIFO,
|
2000-06-09 12:22:13 +04:00
|
|
|
("xi: not enough space in output FIFO (%d > %d)\n",
|
|
|
|
len + pad + 2, space));
|
2000-06-06 03:14:22 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-12-14 09:27:23 +03:00
|
|
|
IFQ_DEQUEUE(&ifp->if_snd, m0);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2010-04-05 11:19:28 +04:00
|
|
|
bpf_mtap(ifp, m0);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the output at splhigh() so that an interrupt from another device
|
|
|
|
* won't cause a FIFO underrun.
|
|
|
|
*/
|
|
|
|
s = splhigh();
|
|
|
|
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_2(bst, bsh, EDP, (u_int16_t)len + pad);
|
2000-06-06 03:14:22 +04:00
|
|
|
for (m = m0; m; ) {
|
|
|
|
if (m->m_len > 1)
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_multi_2(bst, bsh, EDP,
|
2002-05-05 07:19:26 +04:00
|
|
|
mtod(m, u_int16_t *), m->m_len>>1);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (m->m_len & 1) {
|
|
|
|
DPRINTF(XID_CONFIG, ("xi: XXX odd!\n"));
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, EDP,
|
2000-06-06 03:14:22 +04:00
|
|
|
*(mtod(m, u_int8_t *) + m->m_len - 1));
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
}
|
2000-06-06 03:14:22 +04:00
|
|
|
MFREE(m, m0);
|
|
|
|
m = m0;
|
|
|
|
}
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi: len=%d pad=%d total=%d\n", len, pad, len+pad+4));
|
|
|
|
if (sc->sc_chipset >= XI_CHIPSET_MOHAWK)
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, CR, TX_PKT | ENABLE_INT);
|
2000-06-06 03:14:22 +04:00
|
|
|
else {
|
|
|
|
for (; pad > 1; pad -= 2)
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_2(bst, bsh, EDP, 0);
|
2000-06-06 03:14:22 +04:00
|
|
|
if (pad == 1)
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, EDP, 0);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
splx(s);
|
|
|
|
|
|
|
|
ifp->if_timer = 5;
|
|
|
|
++ifp->if_opackets;
|
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC int
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_ether_ioctl(struct ifnet *ifp, u_long cmd, void *data)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
struct ifaddr *ifa = (struct ifaddr *)data;
|
|
|
|
struct xi_softc *sc = ifp->if_softc;
|
2004-08-08 11:25:20 +04:00
|
|
|
int error;
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_ether_ioctl()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
switch (cmd) {
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
case SIOCINITIFADDR:
|
2004-08-08 11:25:20 +04:00
|
|
|
if ((error = xi_enable(sc)) != 0)
|
|
|
|
break;
|
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
ifp->if_flags |= IFF_UP;
|
|
|
|
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
xi_init(sc);
|
2000-06-06 03:14:22 +04:00
|
|
|
switch (ifa->ifa_addr->sa_family) {
|
|
|
|
#ifdef INET
|
|
|
|
case AF_INET:
|
|
|
|
arp_ifinit(ifp, ifa);
|
|
|
|
break;
|
|
|
|
#endif /* INET */
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC int
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
xi_ioctl(struct ifnet *ifp, u_long cmd, void *data)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
struct xi_softc *sc = ifp->if_softc;
|
2000-06-06 03:14:22 +04:00
|
|
|
int s, error = 0;
|
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_ioctl()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2001-01-14 20:37:41 +03:00
|
|
|
s = splnet();
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
switch (cmd) {
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
case SIOCINITIFADDR:
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
error = xi_ether_ioctl(ifp, cmd, data);
|
2000-06-06 03:14:22 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SIOCSIFFLAGS:
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
if ((error = ifioctl_common(ifp, cmd, data)) != 0)
|
|
|
|
break;
|
|
|
|
/* XXX re-use ether_ioctl() */
|
|
|
|
switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
|
|
|
|
case IFF_RUNNING:
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
/*
|
|
|
|
* If interface is marked down and it is running,
|
|
|
|
* stop it.
|
|
|
|
*/
|
|
|
|
xi_stop(sc);
|
|
|
|
ifp->if_flags &= ~IFF_RUNNING;
|
2004-08-08 11:25:20 +04:00
|
|
|
xi_disable(sc);
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
break;
|
|
|
|
case IFF_UP:
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
/*
|
|
|
|
* If interface is marked up and it is stopped,
|
|
|
|
* start it.
|
|
|
|
*/
|
2004-08-08 11:25:20 +04:00
|
|
|
if ((error = xi_enable(sc)) != 0)
|
|
|
|
break;
|
2000-06-06 03:14:22 +04:00
|
|
|
xi_init(sc);
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
break;
|
|
|
|
case IFF_UP|IFF_RUNNING:
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
/*
|
|
|
|
* Reset the interface to pick up changes in any
|
|
|
|
* other flags that affect hardware registers.
|
|
|
|
*/
|
2004-08-08 11:25:20 +04:00
|
|
|
xi_set_address(sc);
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
break;
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIOCADDMULTI:
|
|
|
|
case SIOCDELMULTI:
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_enabled == 0) {
|
|
|
|
error = EIO;
|
|
|
|
break;
|
|
|
|
}
|
Make many ethernet drivers share the common code for MII media
handling, ether_mediastatus() and ether_mediachange(). Check for
a non-ENXIO error return from mii_mediachg(). (ENXIO indicates
that a PHY is suspended.)
This patch shrinks the source code size by 979 lines. There was
a 5100-byte savings on the NetBSD/i386 kernel configuration, ALL.
I have made a few miscellaneous changes, too:
gem(4): use LIST_EMPTY(), LIST_FOREACH().
mtd(4): handle media ioctls, for a change!
axe(4): do not track link status in sc->axe_link any longer
nfe(4), aue(4), axe(4), udav(4), url(4): do not reset all PHYs
on a change of media
Except for the change to mtd(4), no functional changes are intended.
XXX This patch affects more architectures than I can feasibly
XXX compile and run. I have compiled macppc, sparc64, i386. I
XXX have run the patches on i386 boxen with bnx(4) and sip(4).
XXX Compiling and running on evbmips (MERAKI, ADM5120) is in
XXX progress.
2008-01-20 01:10:14 +03:00
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case SIOCSIFMEDIA:
|
|
|
|
case SIOCGIFMEDIA:
|
2007-09-01 11:32:22 +04:00
|
|
|
if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
|
2000-06-06 03:14:22 +04:00
|
|
|
/*
|
|
|
|
* Multicast list has changed; set the hardware
|
|
|
|
* filter accordingly.
|
|
|
|
*/
|
2004-10-30 22:08:34 +04:00
|
|
|
if (ifp->if_flags & IFF_RUNNING)
|
|
|
|
xi_set_address(sc);
|
2000-06-06 03:14:22 +04:00
|
|
|
error = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
error = ether_ioctl(ifp, cmd, data);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
break;
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
|
2000-06-06 03:14:22 +04:00
|
|
|
splx(s);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_set_address(struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
|
|
|
struct ethercom *ether = &sc->sc_ethercom;
|
|
|
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
|
2001-07-01 05:57:29 +04:00
|
|
|
struct ether_multistep step;
|
|
|
|
struct ether_multi *enm;
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
int page, num;
|
2001-07-01 05:57:29 +04:00
|
|
|
int i;
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
u_int8_t x;
|
2007-08-30 02:33:42 +04:00
|
|
|
const u_int8_t *enaddr;
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
u_int8_t indaddr[64];
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_set_address()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2007-08-30 02:33:42 +04:00
|
|
|
enaddr = (const u_int8_t *)CLLADDR(ifp->if_sadl);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_chipset >= XI_CHIPSET_MOHAWK)
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
indaddr[i] = enaddr[5 - i];
|
|
|
|
else
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
indaddr[i] = enaddr[i];
|
|
|
|
num = 1;
|
|
|
|
|
|
|
|
if (ether->ec_multicnt > 9) {
|
|
|
|
ifp->if_flags |= IFF_ALLMULTI;
|
|
|
|
goto done;
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
2001-07-01 05:57:29 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
ETHER_FIRST_MULTI(step, ether, enm);
|
|
|
|
for (; enm; num++) {
|
|
|
|
if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
|
|
|
|
sizeof(enm->enm_addrlo)) != 0) {
|
|
|
|
/*
|
|
|
|
* The multicast address is really a range;
|
|
|
|
* it's easier just to accept all multicasts.
|
|
|
|
* XXX should we be setting IFF_ALLMULTI here?
|
|
|
|
*/
|
|
|
|
ifp->if_flags |= IFF_ALLMULTI;
|
|
|
|
goto done;
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_chipset >= XI_CHIPSET_MOHAWK)
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
indaddr[num * 6 + i] = enm->enm_addrlo[5 - i];
|
|
|
|
else
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
indaddr[num * 6 + i] = enm->enm_addrlo[i];
|
|
|
|
ETHER_NEXT_MULTI(step, enm);
|
|
|
|
}
|
|
|
|
ifp->if_flags &= ~IFF_ALLMULTI;
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
done:
|
|
|
|
if (num < 10)
|
|
|
|
memset(&indaddr[num * 6], 0xff, 6 * (10 - num));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
for (page = 0; page < 8; page++) {
|
|
|
|
#ifdef XIDEBUG
|
|
|
|
if (xidebug & XID_MCAST) {
|
2004-08-09 17:30:16 +04:00
|
|
|
printf("page %d before:", page);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
printf(" %02x", indaddr[page * 8 + i]);
|
2001-07-01 05:57:29 +04:00
|
|
|
printf("\n");
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
2001-07-01 05:57:29 +04:00
|
|
|
#endif
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
|
|
|
|
PAGE(sc, 0x50 + page);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_region_1(bst, bsh, IA, &indaddr[page * 8],
|
|
|
|
page == 7 ? 4 : 8);
|
2004-08-09 17:30:16 +04:00
|
|
|
/*
|
|
|
|
* XXX
|
|
|
|
* Without this delay, the address registers on my CE2 get
|
|
|
|
* trashed the first and I have to cycle it. I have no idea
|
|
|
|
* why. - mycroft, 2004/08/09
|
|
|
|
*/
|
|
|
|
DELAY(50);
|
|
|
|
|
|
|
|
#ifdef XIDEBUG
|
|
|
|
if (xidebug & XID_MCAST) {
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_read_region_1(bst, bsh, IA,
|
2004-08-09 17:30:16 +04:00
|
|
|
&indaddr[page * 8], page == 7 ? 4 : 8);
|
|
|
|
printf("page %d after: ", page);
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
printf(" %02x", indaddr[page * 8 + i]);
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
#endif
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
|
|
|
|
PAGE(sc, 0x42);
|
|
|
|
x = SWC1_IND_ADDR;
|
|
|
|
if (ifp->if_flags & IFF_PROMISC)
|
|
|
|
x |= SWC1_PROMISC;
|
2004-08-09 08:47:40 +04:00
|
|
|
if (ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC))
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
x |= SWC1_MCAST_PROM;
|
|
|
|
if (!LIST_FIRST(&sc->sc_mii.mii_phys))
|
|
|
|
x |= SWC1_AUTO_MEDIA;
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(sc->sc_bst, sc->sc_bsh, SWC1, x);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_cycle_power(struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_cycle_power()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
PAGE(sc, 4);
|
|
|
|
DELAY(1);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP1, 0);
|
2004-08-12 22:23:50 +04:00
|
|
|
tsleep(&xi_cycle_power, PWAIT, "xipwr1", hz * 40 / 1000);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_chipset >= XI_CHIPSET_MOHAWK)
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP1, POWER_UP);
|
2000-06-06 03:14:22 +04:00
|
|
|
else
|
|
|
|
/* XXX What is bit 2 (aka AIC)? */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP1, POWER_UP | 4);
|
2004-08-12 22:23:50 +04:00
|
|
|
tsleep(&xi_cycle_power, PWAIT, "xipwr2", hz * 20 / 1000);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
STATIC void
|
2009-03-14 18:35:58 +03:00
|
|
|
xi_full_reset(struct xi_softc *sc)
|
2000-06-06 03:14:22 +04:00
|
|
|
{
|
|
|
|
bus_space_tag_t bst = sc->sc_bst;
|
|
|
|
bus_space_handle_t bsh = sc->sc_bsh;
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
u_int8_t x;
|
2000-06-06 03:14:22 +04:00
|
|
|
|
2000-06-09 12:22:13 +04:00
|
|
|
DPRINTF(XID_CONFIG, ("xi_full_reset()\n"));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/* Do an as extensive reset as possible on all functions. */
|
|
|
|
xi_cycle_power(sc);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, CR, SOFT_RESET);
|
2004-08-12 22:23:50 +04:00
|
|
|
tsleep(&xi_full_reset, PWAIT, "xirst1", hz * 20 / 1000);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, CR, 0);
|
2004-08-12 22:23:50 +04:00
|
|
|
tsleep(&xi_full_reset, PWAIT, "xirst2", hz * 20 / 1000);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
PAGE(sc, 4);
|
|
|
|
if (sc->sc_chipset >= XI_CHIPSET_MOHAWK) {
|
2000-06-06 03:14:22 +04:00
|
|
|
/*
|
|
|
|
* Drive GP1 low to power up ML6692 and GP2 high to power up
|
2003-02-22 08:06:36 +03:00
|
|
|
* the 10MHz chip. XXX What chip is that? The phy?
|
2000-06-06 03:14:22 +04:00
|
|
|
*/
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP0, GP1_OUT | GP2_OUT | GP2_WR);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
2004-08-12 22:23:50 +04:00
|
|
|
tsleep(&xi_full_reset, PWAIT, "xirst3", hz * 500 / 1000);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/* Get revision information. XXX Symbolic constants. */
|
2004-08-12 23:42:03 +04:00
|
|
|
sc->sc_rev = bus_space_read_1(bst, bsh, BV) &
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
((sc->sc_chipset >= XI_CHIPSET_MOHAWK) ? 0x70 : 0x30) >> 4;
|
|
|
|
DPRINTF(XID_CONFIG, ("xi: rev=%02x\n", sc->sc_rev));
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/* Media selection. XXX Maybe manual overriding too? */
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_chipset < XI_CHIPSET_MOHAWK) {
|
2000-06-06 03:14:22 +04:00
|
|
|
/*
|
|
|
|
* XXX I have no idea what this really does, it is from the
|
|
|
|
* Linux driver.
|
|
|
|
*/
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, GP0, GP1_OUT);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
2004-08-12 22:23:50 +04:00
|
|
|
tsleep(&xi_full_reset, PWAIT, "xirst4", hz * 40 / 1000);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable source insertion.
|
|
|
|
* XXX Dingo does not have this bit, but Linux does it unconditionally.
|
|
|
|
*/
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_chipset < XI_CHIPSET_DINGO) {
|
2000-06-06 03:14:22 +04:00
|
|
|
PAGE(sc, 0x42);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, SWC0, 0x20);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the local memory dividing line. */
|
|
|
|
if (sc->sc_rev != 1) {
|
|
|
|
PAGE(sc, 2);
|
|
|
|
/* XXX Symbolic constant preferrable. */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_2(bst, bsh, RBS0, 0x2000);
|
2000-06-06 03:14:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Apparently the receive byte pointer can be bad after a reset, so
|
|
|
|
* we hardwire it correctly.
|
|
|
|
*/
|
|
|
|
PAGE(sc, 0);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_2(bst, bsh, DO0, DO_CHG_OFFSET);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/* Setup ethernet MAC registers. XXX Symbolic constants. */
|
|
|
|
PAGE(sc, 0x40);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, RX0MSK,
|
2000-06-06 03:14:22 +04:00
|
|
|
PKT_TOO_LONG | CRC_ERR | RX_OVERRUN | RX_ABORT | RX_OK);
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, TX0MSK,
|
2000-06-06 03:14:22 +04:00
|
|
|
CARRIER_LOST | EXCESSIVE_COLL | TX_UNDERRUN | LATE_COLLISION |
|
|
|
|
SQE | TX_ABORT | TX_OK);
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
if (sc->sc_chipset < XI_CHIPSET_DINGO)
|
2000-06-06 03:14:22 +04:00
|
|
|
/* XXX From Linux, dunno what 0xb0 means. */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, TX1MSK, 0xb0);
|
|
|
|
bus_space_write_1(bst, bsh, RXST0, 0);
|
|
|
|
bus_space_write_1(bst, bsh, TXST0, 0);
|
|
|
|
bus_space_write_1(bst, bsh, TXST1, 0);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
PAGE(sc, 2);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
Split "xi" into a "xirc" frontend (similar to mhzc; it attaches two child
devices) and a "xi" backend.
My CE2 and CEM2 cards are now probed correctly. However, there are still
some problems with one model of the CE2, and the CEM2 doesn't seem to get
any modem interrupts.
While I'm at it, fix several bugs:
* The tuple scan for the MAC address was broken in multiple ways.
* xi_intr() did not deal well with a shared interrupt.
* We were setting the wrong page number to look at the receive status. (How
did this work???)
* Remove the xi_full_reset() from xi_reset(). Move the parts of
xi_full_reset() needed to undo the effect of xi_stop() into xi_init(). This
allows a stop/init pair to DTRT, and much quicker, as used by various
ioctl()s.
* Set the TRS register before reading the TSO register, as the Linux driver
does. While I'm at it, fix the name.
* Fix numerous problems with xi_set_address(). "Where do I begin?" There's a
chance that multicast works now, but I haven't tested it.
* Explicitly clear the MSR register, and also force SELECT_MII to 0 if we
didn't find any PHYs.
* Clean up some cruft that appears to be bogus.
Probably needs more work, but it's a start.
2004-08-08 09:56:08 +04:00
|
|
|
/* Enable MII function if available. */
|
|
|
|
x = 0;
|
|
|
|
if (LIST_FIRST(&sc->sc_mii.mii_phys))
|
|
|
|
x |= SELECT_MII;
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, MSR, x);
|
2004-08-12 22:23:50 +04:00
|
|
|
tsleep(&xi_full_reset, PWAIT, "xirst5", hz * 20 / 1000);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/* Configure the LED registers. */
|
|
|
|
/* XXX This is not good for 10base2. */
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, LED,
|
2004-08-08 10:37:17 +04:00
|
|
|
(LED_TX_ACT << LED1_SHIFT) | (LED_10MB_LINK << LED0_SHIFT));
|
|
|
|
if (sc->sc_chipset >= XI_CHIPSET_DINGO)
|
2004-08-12 23:42:03 +04:00
|
|
|
bus_space_write_1(bst, bsh, LED3, LED_100MB_LINK << LED3_SHIFT);
|
2000-06-06 03:14:22 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Linux driver says this:
|
|
|
|
* We should switch back to page 0 to avoid a bug in revision 0
|
|
|
|
* where regs with offset below 8 can't be read after an access
|
|
|
|
* to the MAC registers.
|
|
|
|
*/
|
|
|
|
PAGE(sc, 0);
|
|
|
|
}
|