pegasus: Replace with the upstream FreeBSD version.
Fixes #19745. Change-Id: Ie540beecbf9f0a998f016f015357a38d1fa95bfd Reviewed-on: https://review.haiku-os.org/c/haiku/+/9599 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
83be3b3da0
commit
d5a5f22579
@@ -327,6 +327,7 @@ SYSTEM_ADD_ONS_DRIVERS_NET = [ FFilterByBuildFeatures
|
||||
marvell_yukon
|
||||
nforce
|
||||
pcnet
|
||||
pegasus
|
||||
rtl8125
|
||||
rtl8139
|
||||
rtl81xx
|
||||
@@ -339,7 +340,6 @@ SYSTEM_ADD_ONS_DRIVERS_NET = [ FFilterByBuildFeatures
|
||||
}@ # x86,x86_64,riscv64
|
||||
|
||||
etherpci
|
||||
pegasus
|
||||
usb_davicom
|
||||
usb_rndis
|
||||
wb840
|
||||
|
||||
@@ -2,7 +2,6 @@ SubDir HAIKU_TOP src add-ons kernel drivers network ether ;
|
||||
|
||||
# Haiku-native drivers
|
||||
HaikuSubInclude etherpci ;
|
||||
HaikuSubInclude pegasus ;
|
||||
HaikuSubInclude virtio ;
|
||||
HaikuSubInclude usb_davicom ;
|
||||
HaikuSubInclude usb_ecm ;
|
||||
@@ -26,6 +25,7 @@ HaikuSubInclude jmicron2x0 ;
|
||||
HaikuSubInclude marvell_yukon ;
|
||||
HaikuSubInclude nforce ;
|
||||
HaikuSubInclude pcnet ;
|
||||
HaikuSubInclude pegasus ;
|
||||
HaikuSubInclude rdc ;
|
||||
HaikuSubInclude rtl8139 ;
|
||||
HaikuSubInclude rtl81xx ;
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers network ether pegasus ;
|
||||
|
||||
SubDirSysHdrs $(HAIKU_TOP) headers os drivers ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ]
|
||||
: true ;
|
||||
UsePrivateHeaders net system ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
# For ether_driver.h
|
||||
UsePrivateHeaders net ;
|
||||
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ] ;
|
||||
|
||||
UseHeaders [ FDirName $(SUBDIR) ] : true ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev usb net ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev mii ] ;
|
||||
|
||||
KernelAddon pegasus :
|
||||
driver.c
|
||||
devlist.c
|
||||
glue.c
|
||||
if_aue.c
|
||||
acphy.c
|
||||
:
|
||||
freebsd_usb.a
|
||||
freebsd_mii.a
|
||||
libfreebsd_network.a
|
||||
;
|
||||
|
||||
ObjectHdrs [ FGristFiles driver$(SUFOBJ) if_aue$(SUFOBJ) ]
|
||||
ObjectHdrs [ FGristFiles if_aue$(SUFOBJ) ]
|
||||
: [ FDirName $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) libs compat freebsd_network ] ;
|
||||
Includes [ FGristFiles driver.c if_aue.c ] : <src!libs!compat!freebsd_network>usbdevs.h ;
|
||||
Includes [ FGristFiles if_aue.c ] : <src!libs!compat!freebsd_network>usbdevs.h ;
|
||||
|
||||
ObjectHdrs [ FGristFiles acphy$(SUFOBJ) ]
|
||||
: [ FDirName $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) libs compat freebsd_network ] ;
|
||||
Includes [ FGristFiles acphy.c ] : <src!libs!compat!freebsd_network>miidevs.h ;
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``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 FOUNDATION OR CONTRIBUTORS
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 Manuel Bouyer. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
* Driver for Altima AC101 10/100 PHY
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
#include "miidevs.h"
|
||||
|
||||
#include <dev/mii/acphyreg.h>
|
||||
|
||||
#include "miibus_if.h"
|
||||
|
||||
static int acphy_probe(device_t);
|
||||
static int acphy_attach(device_t);
|
||||
|
||||
static device_method_t acphy_methods[] = {
|
||||
/* device interface */
|
||||
DEVMETHOD(device_probe, acphy_probe),
|
||||
DEVMETHOD(device_attach, acphy_attach),
|
||||
DEVMETHOD(device_detach, mii_phy_detach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t acphy_driver = {
|
||||
"acphy",
|
||||
acphy_methods,
|
||||
sizeof(struct mii_softc)
|
||||
};
|
||||
|
||||
DRIVER_MODULE(acphy, miibus, acphy_driver, 0, 0);
|
||||
|
||||
static int acphy_service(struct mii_softc *, struct mii_data *, int);
|
||||
static void acphy_reset(struct mii_softc *);
|
||||
static void acphy_status(struct mii_softc *);
|
||||
|
||||
static const struct mii_phydesc acphys[] = {
|
||||
MII_PHY_DESC(ALTIMA, AC101),
|
||||
MII_PHY_DESC(ALTIMA, AC101L),
|
||||
/* XXX This is reported to work, but it's not from any data sheet. */
|
||||
MII_PHY_DESC(ALTIMA, ACXXX),
|
||||
MII_PHY_END
|
||||
};
|
||||
|
||||
static const struct mii_phy_funcs acphy_funcs = {
|
||||
acphy_service,
|
||||
acphy_status,
|
||||
acphy_reset
|
||||
};
|
||||
|
||||
static int
|
||||
acphy_probe(device_t dev)
|
||||
{
|
||||
|
||||
return (mii_phy_dev_probe(dev, acphys, BUS_PROBE_DEFAULT));
|
||||
}
|
||||
|
||||
static int
|
||||
acphy_attach(device_t dev)
|
||||
{
|
||||
struct mii_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &acphy_funcs, 0);
|
||||
|
||||
PHY_RESET(sc);
|
||||
|
||||
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask;
|
||||
device_printf(dev, " ");
|
||||
|
||||
#define ADD(m) ifmedia_add(&sc->mii_pdata->mii_media, (m), 0, NULL)
|
||||
if ((PHY_READ(sc, MII_ACPHY_MCTL) & AC_MCTL_FX_SEL) != 0) {
|
||||
sc->mii_flags |= MIIF_HAVEFIBER;
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, sc->mii_inst));
|
||||
printf("100baseFX, ");
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst));
|
||||
printf("100baseFX-FDX, ");
|
||||
}
|
||||
#undef ADD
|
||||
|
||||
mii_phy_add_media(sc);
|
||||
printf("\n");
|
||||
|
||||
MIIBUS_MEDIAINIT(sc->mii_dev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
acphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
|
||||
{
|
||||
int reg;
|
||||
|
||||
switch (cmd) {
|
||||
case MII_POLLSTAT:
|
||||
break;
|
||||
|
||||
case MII_MEDIACHG:
|
||||
/* Wake & deisolate up if necessary */
|
||||
reg = PHY_READ(sc, MII_BMCR);
|
||||
if (reg & (BMCR_ISO | BMCR_PDOWN))
|
||||
PHY_WRITE(sc, MII_BMCR, reg & ~(BMCR_ISO | BMCR_PDOWN));
|
||||
|
||||
mii_phy_setmedia(sc);
|
||||
break;
|
||||
|
||||
case MII_TICK:
|
||||
/*
|
||||
* This PHY's autonegotiation doesn't need to be kicked.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update the media status. */
|
||||
PHY_STATUS(sc);
|
||||
|
||||
/* Callback if something changed. */
|
||||
mii_phy_update(sc, cmd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
acphy_status(struct mii_softc *sc)
|
||||
{
|
||||
struct mii_data *mii = sc->mii_pdata;
|
||||
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
|
||||
int bmsr, bmcr, diag;
|
||||
|
||||
mii->mii_media_status = IFM_AVALID;
|
||||
mii->mii_media_active = IFM_ETHER;
|
||||
|
||||
bmsr = PHY_READ(sc, MII_BMSR) |
|
||||
PHY_READ(sc, MII_BMSR);
|
||||
if (bmsr & BMSR_LINK)
|
||||
mii->mii_media_status |= IFM_ACTIVE;
|
||||
|
||||
bmcr = PHY_READ(sc, MII_BMCR);
|
||||
if (bmcr & BMCR_ISO) {
|
||||
mii->mii_media_active |= IFM_NONE;
|
||||
mii->mii_media_status = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (bmcr & BMCR_LOOP)
|
||||
mii->mii_media_active |= IFM_LOOP;
|
||||
|
||||
if (bmcr & BMCR_AUTOEN) {
|
||||
if ((bmsr & BMSR_ACOMP) == 0) {
|
||||
/* Erg, still trying, I guess... */
|
||||
mii->mii_media_active |= IFM_NONE;
|
||||
return;
|
||||
}
|
||||
diag = PHY_READ(sc, MII_ACPHY_DIAG);
|
||||
if (diag & AC_DIAG_SPEED)
|
||||
mii->mii_media_active |= IFM_100_TX;
|
||||
else
|
||||
mii->mii_media_active |= IFM_10_T;
|
||||
|
||||
if (diag & AC_DIAG_DUPLEX)
|
||||
mii->mii_media_active |=
|
||||
IFM_FDX | mii_phy_flowstatus(sc);
|
||||
else
|
||||
mii->mii_media_active |= IFM_HDX;
|
||||
} else
|
||||
mii->mii_media_active = ife->ifm_media;
|
||||
}
|
||||
|
||||
static void
|
||||
acphy_reset(struct mii_softc *sc)
|
||||
{
|
||||
|
||||
mii_phy_reset(sc);
|
||||
PHY_WRITE(sc, MII_ACPHY_INT, 0);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2001 Semen Ustimenko ([email protected])
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_MII_ACPHYREG_H_
|
||||
#define _DEV_MII_ACPHYREG_H_
|
||||
|
||||
/*
|
||||
* Register definitions for the Altima Communications AC101
|
||||
*/
|
||||
|
||||
#define MII_ACPHY_POL 0x10 /* Polarity int level */
|
||||
|
||||
/* High byte is interrupt mask register */
|
||||
#define MII_ACPHY_INT 0x11 /* Interrupt control/status */
|
||||
#define AC_INT_ACOMP 0x0001 /* Autoneg complete */
|
||||
#define AC_INT_REM_FLT 0x0002 /* Remote fault */
|
||||
#define AC_INT_LINK_DOWN 0x0004 /* Link not OK */
|
||||
#define AC_INT_LP_ACK 0x0008 /* FLP ack recved */
|
||||
#define AC_INT_PD_FLT 0x0010 /* Parallel detect fault */
|
||||
#define AC_INT_PAGE_RECV 0x0020 /* New page recved */
|
||||
#define AC_INT_RX_ER 0x0040 /* RX_ER transitions high */
|
||||
#define AC_INT_JAB 0x0080 /* Jabber detected */
|
||||
|
||||
#define MII_ACPHY_DIAG 0x12 /* Diagnostic */
|
||||
#define AC_DIAG_RX_LOCK 0x0100
|
||||
#define AC_DIAG_RX_PASS 0x0200
|
||||
#define AC_DIAG_SPEED 0x0400 /* Aneg speed result */
|
||||
#define AC_DIAG_DUPLEX 0x0800 /* Aneg duplex result */
|
||||
|
||||
#define MII_ACPHY_PWRLOOP 0x13 /* Power/Loopback */
|
||||
#define MII_ACPHY_CBLMEAS 0x14 /* Cable meas. */
|
||||
|
||||
#define MII_ACPHY_MCTL 0x15 /* Mode control */
|
||||
#define AC_MCTL_FX_SEL 0x0001 /* FX mode */
|
||||
#define AC_MCTL_BYP_PCS 0x0002 /* Bypass PCS */
|
||||
#define AC_MCTL_SCRMBL 0x0004 /* Data scrambling */
|
||||
#define AC_MCTL_REM_LOOP 0x0008 /* Remote loopback */
|
||||
#define AC_MCTL_DIS_WDT 0x0010 /* Disable watchdog timer */
|
||||
#define AC_MCTL_DIS_REC 0x0020 /* Disable recv error counter */
|
||||
#define AC_MCTL_REC_FULL 0x0040 /* Recv error counter full */
|
||||
#define AC_MCTL_FRC_FEF 0x0080 /* Force Far End Fault Insert. */
|
||||
#define AC_MCTL_DIS_FEF 0x0100 /* Disable FEF Insertion */
|
||||
#define AC_MCTL_LED_SEL 0x0200 /* Compat LED config */
|
||||
#define AC_MCTL_ALED_SEL 0x0400 /* ActLED RX&TX - RX only */
|
||||
#define AC_MCTL_10BT_SEL 0x0800 /* Enable 7-wire interface */
|
||||
#define AC_MCTL_DIS_JAB 0x1000 /* Disable jabber */
|
||||
#define AC_MCTL_FRC_LINK 0x2000 /* Force TX link up */
|
||||
#define AC_MCTL_DIS_NLP 0x4000 /* Disable NLP check */
|
||||
|
||||
#define MII_ACPHY_REC 0x18 /* Recv error counter */
|
||||
|
||||
#endif /* _DEV_MII_ACPHYREG_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,220 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-4-Clause
|
||||
*
|
||||
* Copyright (c) 1997, 1998, 1999
|
||||
* Bill Paul <[email protected]>. 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 Bill Paul.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``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 Bill Paul OR THE VOICES IN HIS HEAD
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Register definitions for ADMtek Pegasus AN986 USB to Ethernet
|
||||
* chip. The Pegasus uses a total of four USB endpoints: the control
|
||||
* endpoint (0), a bulk read endpoint for receiving packets (1),
|
||||
* a bulk write endpoint for sending packets (2) and an interrupt
|
||||
* endpoint for passing RX and TX status (3). Endpoint 0 is used
|
||||
* to read and write the ethernet module's registers. All registers
|
||||
* are 8 bits wide.
|
||||
*
|
||||
* Packet transfer is done in 64 byte chunks. The last chunk in a
|
||||
* transfer is denoted by having a length less that 64 bytes. For
|
||||
* the RX case, the data includes an optional RX status word.
|
||||
*/
|
||||
|
||||
#define AUE_UR_READREG 0xF0
|
||||
#define AUE_UR_WRITEREG 0xF1
|
||||
|
||||
#define AUE_CONFIG_INDEX 0 /* config number 1 */
|
||||
#define AUE_IFACE_IDX 0
|
||||
|
||||
/*
|
||||
* Note that while the ADMtek technically has four endpoints, the control
|
||||
* endpoint (endpoint 0) is regarded as special by the USB code and drivers
|
||||
* don't have direct access to it (we access it using usbd_do_request()
|
||||
* when reading/writing registers. Consequently, our endpoint indexes
|
||||
* don't match those in the ADMtek Pegasus manual: we consider the RX data
|
||||
* endpoint to be index 0 and work up from there.
|
||||
*/
|
||||
enum {
|
||||
AUE_BULK_DT_WR,
|
||||
AUE_BULK_DT_RD,
|
||||
AUE_INTR_DT_RD,
|
||||
AUE_N_TRANSFER,
|
||||
};
|
||||
|
||||
#define AUE_INTR_PKTLEN 0x8
|
||||
|
||||
#define AUE_CTL0 0x00
|
||||
#define AUE_CTL1 0x01
|
||||
#define AUE_CTL2 0x02
|
||||
#define AUE_MAR0 0x08
|
||||
#define AUE_MAR1 0x09
|
||||
#define AUE_MAR2 0x0A
|
||||
#define AUE_MAR3 0x0B
|
||||
#define AUE_MAR4 0x0C
|
||||
#define AUE_MAR5 0x0D
|
||||
#define AUE_MAR6 0x0E
|
||||
#define AUE_MAR7 0x0F
|
||||
#define AUE_MAR AUE_MAR0
|
||||
#define AUE_PAR0 0x10
|
||||
#define AUE_PAR1 0x11
|
||||
#define AUE_PAR2 0x12
|
||||
#define AUE_PAR3 0x13
|
||||
#define AUE_PAR4 0x14
|
||||
#define AUE_PAR5 0x15
|
||||
#define AUE_PAR AUE_PAR0
|
||||
#define AUE_PAUSE0 0x18
|
||||
#define AUE_PAUSE1 0x19
|
||||
#define AUE_PAUSE AUE_PAUSE0
|
||||
#define AUE_RX_FLOWCTL_CNT 0x1A
|
||||
#define AUE_RX_FLOWCTL_FIFO 0x1B
|
||||
#define AUE_REG_1D 0x1D
|
||||
#define AUE_EE_REG 0x20
|
||||
#define AUE_EE_DATA0 0x21
|
||||
#define AUE_EE_DATA1 0x22
|
||||
#define AUE_EE_DATA AUE_EE_DATA0
|
||||
#define AUE_EE_CTL 0x23
|
||||
#define AUE_PHY_ADDR 0x25
|
||||
#define AUE_PHY_DATA0 0x26
|
||||
#define AUE_PHY_DATA1 0x27
|
||||
#define AUE_PHY_DATA AUE_PHY_DATA0
|
||||
#define AUE_PHY_CTL 0x28
|
||||
#define AUE_USB_STS 0x2A
|
||||
#define AUE_TXSTAT0 0x2B
|
||||
#define AUE_TXSTAT1 0x2C
|
||||
#define AUE_TXSTAT AUE_TXSTAT0
|
||||
#define AUE_RXSTAT 0x2D
|
||||
#define AUE_PKTLOST0 0x2E
|
||||
#define AUE_PKTLOST1 0x2F
|
||||
#define AUE_PKTLOST AUE_PKTLOST0
|
||||
|
||||
#define AUE_REG_7B 0x7B
|
||||
#define AUE_GPIO0 0x7E
|
||||
#define AUE_GPIO1 0x7F
|
||||
#define AUE_REG_81 0x81
|
||||
|
||||
#define AUE_CTL0_INCLUDE_RXCRC 0x01
|
||||
#define AUE_CTL0_ALLMULTI 0x02
|
||||
#define AUE_CTL0_STOP_BACKOFF 0x04
|
||||
#define AUE_CTL0_RXSTAT_APPEND 0x08
|
||||
#define AUE_CTL0_WAKEON_ENB 0x10
|
||||
#define AUE_CTL0_RXPAUSE_ENB 0x20
|
||||
#define AUE_CTL0_RX_ENB 0x40
|
||||
#define AUE_CTL0_TX_ENB 0x80
|
||||
|
||||
#define AUE_CTL1_HOMELAN 0x04
|
||||
#define AUE_CTL1_RESETMAC 0x08
|
||||
#define AUE_CTL1_SPEEDSEL 0x10 /* 0 = 10mbps, 1 = 100mbps */
|
||||
#define AUE_CTL1_DUPLEX 0x20 /* 0 = half, 1 = full */
|
||||
#define AUE_CTL1_DELAYHOME 0x40
|
||||
|
||||
#define AUE_CTL2_EP3_CLR 0x01 /* reading EP3 clrs status regs */
|
||||
#define AUE_CTL2_RX_BADFRAMES 0x02
|
||||
#define AUE_CTL2_RX_PROMISC 0x04
|
||||
#define AUE_CTL2_LOOPBACK 0x08
|
||||
#define AUE_CTL2_EEPROMWR_ENB 0x10
|
||||
#define AUE_CTL2_EEPROM_LOAD 0x20
|
||||
|
||||
#define AUE_EECTL_WRITE 0x01
|
||||
#define AUE_EECTL_READ 0x02
|
||||
#define AUE_EECTL_DONE 0x04
|
||||
|
||||
#define AUE_PHYCTL_PHYREG 0x1F
|
||||
#define AUE_PHYCTL_WRITE 0x20
|
||||
#define AUE_PHYCTL_READ 0x40
|
||||
#define AUE_PHYCTL_DONE 0x80
|
||||
|
||||
#define AUE_USBSTS_SUSPEND 0x01
|
||||
#define AUE_USBSTS_RESUME 0x02
|
||||
|
||||
#define AUE_TXSTAT0_JABTIMO 0x04
|
||||
#define AUE_TXSTAT0_CARLOSS 0x08
|
||||
#define AUE_TXSTAT0_NOCARRIER 0x10
|
||||
#define AUE_TXSTAT0_LATECOLL 0x20
|
||||
#define AUE_TXSTAT0_EXCESSCOLL 0x40
|
||||
#define AUE_TXSTAT0_UNDERRUN 0x80
|
||||
|
||||
#define AUE_TXSTAT1_PKTCNT 0x0F
|
||||
#define AUE_TXSTAT1_FIFO_EMPTY 0x40
|
||||
#define AUE_TXSTAT1_FIFO_FULL 0x80
|
||||
|
||||
#define AUE_RXSTAT_OVERRUN 0x01
|
||||
#define AUE_RXSTAT_PAUSE 0x02
|
||||
|
||||
#define AUE_GPIO_IN0 0x01
|
||||
#define AUE_GPIO_OUT0 0x02
|
||||
#define AUE_GPIO_SEL0 0x04
|
||||
#define AUE_GPIO_IN1 0x08
|
||||
#define AUE_GPIO_OUT1 0x10
|
||||
#define AUE_GPIO_SEL1 0x20
|
||||
|
||||
#define AUE_TIMEOUT 100 /* 10*ms */
|
||||
#define AUE_MIN_FRAMELEN 60
|
||||
|
||||
#define AUE_RXSTAT_MCAST 0x01
|
||||
#define AUE_RXSTAT_GIANT 0x02
|
||||
#define AUE_RXSTAT_RUNT 0x04
|
||||
#define AUE_RXSTAT_CRCERR 0x08
|
||||
#define AUE_RXSTAT_DRIBBLE 0x10
|
||||
#define AUE_RXSTAT_MASK 0x1E
|
||||
|
||||
#define GET_MII(sc) uether_getmii(&(sc)->sc_ue)
|
||||
|
||||
struct aue_intrpkt {
|
||||
uint8_t aue_txstat0;
|
||||
uint8_t aue_txstat1;
|
||||
uint8_t aue_rxstat;
|
||||
uint8_t aue_rxlostpkt0;
|
||||
uint8_t aue_rxlostpkt1;
|
||||
uint8_t aue_wakeupstat;
|
||||
uint8_t aue_rsvd;
|
||||
} __packed;
|
||||
|
||||
struct aue_rxpkt {
|
||||
uint16_t aue_pktlen;
|
||||
uint8_t aue_rxstat;
|
||||
uint8_t pad;
|
||||
} __packed;
|
||||
|
||||
struct aue_softc {
|
||||
struct usb_ether sc_ue;
|
||||
struct mtx sc_mtx;
|
||||
struct usb_xfer *sc_xfer[AUE_N_TRANSFER];
|
||||
|
||||
int sc_flags;
|
||||
#define AUE_FLAG_LSYS 0x0001 /* use Linksys reset */
|
||||
#define AUE_FLAG_PNA 0x0002 /* has Home PNA */
|
||||
#define AUE_FLAG_PII 0x0004 /* Pegasus II chip */
|
||||
#define AUE_FLAG_LINK 0x0008 /* wait for link to come up */
|
||||
#define AUE_FLAG_VER_2 0x0200 /* chip is version 2 */
|
||||
#define AUE_FLAG_DUAL_PHY 0x0400 /* chip has two transcivers */
|
||||
};
|
||||
|
||||
#define AUE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
|
||||
#define AUE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
|
||||
#define AUE_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t)
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jérôme Duval
|
||||
*
|
||||
* Some portions of code are copyrighted by
|
||||
* USB Joystick driver for BeOS R5
|
||||
* Copyright 2000 (C) ITO, Takayuki. All rights reserved
|
||||
*/
|
||||
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
sem_id gDeviceListLock = -1;
|
||||
bool gDeviceListChanged = true; /* added or removed */
|
||||
/* dynamically generated */
|
||||
char **gDeviceNames = NULL;
|
||||
|
||||
|
||||
static pegasus_dev *sDeviceList = NULL;
|
||||
static int sDeviceCount = 0;
|
||||
|
||||
|
||||
void
|
||||
add_device_info(pegasus_dev *device)
|
||||
{
|
||||
ASSERT(device != NULL);
|
||||
|
||||
acquire_sem(gDeviceListLock);
|
||||
device->next = sDeviceList;
|
||||
sDeviceList = device;
|
||||
sDeviceCount++;
|
||||
gDeviceListChanged = true;
|
||||
release_sem(gDeviceListLock);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
remove_device_info(pegasus_dev *device)
|
||||
{
|
||||
ASSERT(device != NULL);
|
||||
|
||||
acquire_sem(gDeviceListLock);
|
||||
|
||||
if (sDeviceList == device) {
|
||||
sDeviceList = device->next;
|
||||
--sDeviceCount;
|
||||
gDeviceListChanged = true;
|
||||
} else {
|
||||
pegasus_dev *previous;
|
||||
for (previous = sDeviceList; previous != NULL; previous = previous->next) {
|
||||
if (previous->next == device) {
|
||||
previous->next = device->next;
|
||||
--sDeviceCount;
|
||||
gDeviceListChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(previous != NULL);
|
||||
}
|
||||
release_sem(gDeviceListLock);
|
||||
}
|
||||
|
||||
|
||||
pegasus_dev *
|
||||
search_device_info(const char* name)
|
||||
{
|
||||
pegasus_dev *device;
|
||||
|
||||
acquire_sem(gDeviceListLock);
|
||||
for (device = sDeviceList; device != NULL; device = device->next) {
|
||||
if (strcmp(device->name, name) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
release_sem(gDeviceListLock);
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - device names
|
||||
|
||||
|
||||
void
|
||||
alloc_device_names(void)
|
||||
{
|
||||
ASSERT(gDeviceNames == NULL);
|
||||
gDeviceNames = malloc(sizeof(char *) * (sDeviceCount + 1));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
free_device_names(void)
|
||||
{
|
||||
if (gDeviceNames != NULL) {
|
||||
int i;
|
||||
for (i = 0; gDeviceNames [i] != NULL; i++) {
|
||||
free(gDeviceNames[i]);
|
||||
}
|
||||
|
||||
free(gDeviceNames);
|
||||
gDeviceNames = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rebuild_device_names(void)
|
||||
{
|
||||
int i;
|
||||
pegasus_dev *device;
|
||||
|
||||
ASSERT(gDeviceNames != NULL);
|
||||
acquire_sem(gDeviceListLock);
|
||||
for (i = 0, device = sDeviceList; device != NULL; device = device->next) {
|
||||
gDeviceNames[i++] = strdup(device->name);
|
||||
DPRINTF_INFO(MY_ID "publishing %s\n", device->name);
|
||||
}
|
||||
gDeviceNames[i] = NULL;
|
||||
release_sem(gDeviceListLock);
|
||||
}
|
||||
|
||||
@@ -1,837 +0,0 @@
|
||||
/*
|
||||
* Pegasus BeOS Driver
|
||||
*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jérôme Duval
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "driver.h"
|
||||
#include "usbdevs.h"
|
||||
|
||||
typedef struct driver_cookie {
|
||||
struct driver_cookie *next;
|
||||
pegasus_dev *device;
|
||||
} driver_cookie;
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
static status_t pegasus_device_added(const usb_device dev, void **cookie);
|
||||
static status_t pegasus_device_removed(void *cookie);
|
||||
|
||||
static int sDeviceNumber = 0;
|
||||
static const char *kBaseName = "net/pegasus/";
|
||||
|
||||
static const char *kDriverName = DRIVER_NAME;
|
||||
|
||||
usb_module_info *usb;
|
||||
|
||||
|
||||
usb_support_descriptor supported_devices[] = {
|
||||
{ 0, 0, 0, USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460B},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX1},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX2},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UFE1000},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX4},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX5},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX6},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX7},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX8},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX9},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX10},
|
||||
{ 0, 0, 0, USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_DSB650TX_PNA},
|
||||
{ 0, 0, 0, USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_USB320_EC},
|
||||
{ 0, 0, 0, USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SS1001},
|
||||
{ 0, 0, 0, USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUS},
|
||||
{ 0, 0, 0, USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII},
|
||||
{ 0, 0, 0, USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_2},
|
||||
{ 0, 0, 0, USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_3},
|
||||
{ 0, 0, 0, USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2LAN},
|
||||
{ 0, 0, 0, USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB100},
|
||||
{ 0, 0, 0, USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBLP100},
|
||||
{ 0, 0, 0, USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBEL100},
|
||||
{ 0, 0, 0, USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBE100},
|
||||
{ 0, 0, 0, USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TX},
|
||||
{ 0, 0, 0, USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXS},
|
||||
{ 0, 0, 0, USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX4},
|
||||
{ 0, 0, 0, USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX1},
|
||||
{ 0, 0, 0, USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX},
|
||||
{ 0, 0, 0, USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX_PNA},
|
||||
{ 0, 0, 0, USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX3},
|
||||
{ 0, 0, 0, USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX2},
|
||||
{ 0, 0, 0, USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650},
|
||||
{ 0, 0, 0, USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX0},
|
||||
{ 0, 0, 0, USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX1},
|
||||
{ 0, 0, 0, USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX2},
|
||||
{ 0, 0, 0, USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX3},
|
||||
{ 0, 0, 0, USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBLTX},
|
||||
{ 0, 0, 0, USB_VENDOR_ELSA, USB_PRODUCT_ELSA_USB2ETHERNET},
|
||||
{ 0, 0, 0, USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_UF100},
|
||||
{ 0, 0, 0, USB_VENDOR_HP, USB_PRODUCT_HP_HN210E},
|
||||
{ 0, 0, 0, USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETTX},
|
||||
{ 0, 0, 0, USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETTXS},
|
||||
{ 0, 0, 0, USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_KNU101TX},
|
||||
{ 0, 0, 0, USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TX1},
|
||||
{ 0, 0, 0, USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10T},
|
||||
{ 0, 0, 0, USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100TX},
|
||||
{ 0, 0, 0, USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100H1},
|
||||
{ 0, 0, 0, USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TA},
|
||||
{ 0, 0, 0, USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TX2},
|
||||
{ 0, 0, 0, USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_MN110},
|
||||
{ 0, 0, 0, USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX1},
|
||||
{ 0, 0, 0, USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX5},
|
||||
{ 0, 0, 0, USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUA2TX5},
|
||||
{ 0, 0, 0, USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA101},
|
||||
{ 0, 0, 0, USB_VENDOR_SIEMENS, USB_PRODUCT_SIEMENS_SPEEDSTREAM},
|
||||
{ 0, 0, 0, USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTNIC},
|
||||
{ 0, 0, 0, USB_VENDOR_SMC, USB_PRODUCT_SMC_2202USB},
|
||||
{ 0, 0, 0, USB_VENDOR_SMC, USB_PRODUCT_SMC_2206USB},
|
||||
{ 0, 0, 0, USB_VENDOR_SOHOWARE, USB_PRODUCT_SOHOWARE_NUB100},
|
||||
};
|
||||
|
||||
|
||||
static const struct aue_type aue_devs[] = {
|
||||
{{ USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460B}, PII },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX1}, PNA|PII },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX2}, PII },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UFE1000}, LSYS },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX4}, PNA },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX5}, PNA },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX6}, PII },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX7}, PII },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX8}, PII },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX9}, PNA },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX10}, 0 },
|
||||
{{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_DSB650TX_PNA}, 0 },
|
||||
{{ USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_USB320_EC}, 0 },
|
||||
{{ USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SS1001}, PII },
|
||||
{{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUS}, PNA },
|
||||
{{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII}, PII },
|
||||
{{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_2}, PII },
|
||||
{{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_3}, PII },
|
||||
{{ USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2LAN}, PII },
|
||||
{{ USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB100}, 0 },
|
||||
{{ USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBLP100}, PNA },
|
||||
{{ USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBEL100}, 0 },
|
||||
{{ USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBE100}, PII },
|
||||
{{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TX}, 0 },
|
||||
{{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXS},PII },
|
||||
{{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX4}, LSYS|PII },
|
||||
{{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX1}, LSYS },
|
||||
{{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX}, LSYS },
|
||||
{{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX_PNA}, PNA },
|
||||
{{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX3}, LSYS|PII },
|
||||
{{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX2}, LSYS|PII },
|
||||
{{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650}, LSYS },
|
||||
{{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX0}, 0 },
|
||||
{{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX1}, LSYS },
|
||||
{{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX2}, 0 },
|
||||
{{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX3}, LSYS },
|
||||
{{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBLTX}, PII },
|
||||
{{ USB_VENDOR_ELSA, USB_PRODUCT_ELSA_USB2ETHERNET}, 0 },
|
||||
{{ USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_UF100}, PII },
|
||||
{{ USB_VENDOR_HP, USB_PRODUCT_HP_HN210E}, PII },
|
||||
{{ USB_VENDOR_IODATA, 0x092a /* USB_PRODUCT_IODATA_ETXUS2 */}, PII },
|
||||
{{ USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETTX}, 0 },
|
||||
{{ USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETTXS}, PII },
|
||||
{{ USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_KNU101TX}, 0 },
|
||||
{{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TX1}, LSYS|PII },
|
||||
{{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10T}, LSYS },
|
||||
{{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100TX}, LSYS },
|
||||
{{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100H1}, LSYS|PNA },
|
||||
{{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TA}, LSYS },
|
||||
{{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TX2}, LSYS|PII },
|
||||
{{ USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_MN110}, PII },
|
||||
{{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX1}, 0 },
|
||||
{{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX5}, 0 },
|
||||
{{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUA2TX5}, PII },
|
||||
{{ USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA101}, PII },
|
||||
{{ USB_VENDOR_SIEMENS, USB_PRODUCT_SIEMENS_SPEEDSTREAM}, PII },
|
||||
{{ USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTNIC},PII },
|
||||
{{ USB_VENDOR_SMC, USB_PRODUCT_SMC_2202USB}, 0 },
|
||||
{{ USB_VENDOR_SMC, USB_PRODUCT_SMC_2206USB}, PII },
|
||||
{{ USB_VENDOR_SOHOWARE, USB_PRODUCT_SOHOWARE_NUB100}, 0 },
|
||||
};
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_checkdeviceinfo(pegasus_dev *dev)
|
||||
{
|
||||
if (!dev || dev->cookieMagic != PEGASUS_COOKIE_MAGIC)
|
||||
return EINVAL;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
pegasus_dev *
|
||||
create_device(const usb_device dev, const usb_interface_info *ii, uint16 ifno)
|
||||
{
|
||||
pegasus_dev *device = NULL;
|
||||
sem_id sem;
|
||||
|
||||
ASSERT(usb != NULL && dev != 0);
|
||||
|
||||
device = malloc(sizeof(pegasus_dev));
|
||||
if (device == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(device, 0, sizeof(pegasus_dev));
|
||||
|
||||
device->sem_lock = sem = create_sem(1, DRIVER_NAME "_lock");
|
||||
if (sem < B_OK) {
|
||||
DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32 "\n", sem);
|
||||
free(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
device->rx_sem = sem = create_sem(1, DRIVER_NAME"_receive");
|
||||
if (sem < B_OK) {
|
||||
DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32 "\n", sem);
|
||||
delete_sem(device->sem_lock);
|
||||
free(device);
|
||||
return NULL;
|
||||
}
|
||||
set_sem_owner(device->rx_sem, B_SYSTEM_TEAM);
|
||||
|
||||
device->rx_sem_cb = sem = create_sem(0, DRIVER_NAME"_receive_cb");
|
||||
if (sem < B_OK) {
|
||||
DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32 "\n", sem);
|
||||
delete_sem(device->rx_sem);
|
||||
delete_sem(device->sem_lock);
|
||||
free(device);
|
||||
return NULL;
|
||||
}
|
||||
set_sem_owner(device->rx_sem_cb, B_SYSTEM_TEAM);
|
||||
|
||||
device->tx_sem = sem = create_sem(1, DRIVER_NAME"_transmit");
|
||||
if (sem < B_OK) {
|
||||
delete_sem(device->sem_lock);
|
||||
delete_sem(device->rx_sem);
|
||||
delete_sem(device->rx_sem_cb);
|
||||
free(device);
|
||||
return NULL;
|
||||
}
|
||||
set_sem_owner(device->tx_sem, B_SYSTEM_TEAM);
|
||||
|
||||
device->tx_sem_cb = sem = create_sem(0, DRIVER_NAME"_transmit_cb");
|
||||
if (sem < B_OK) {
|
||||
delete_sem(device->sem_lock);
|
||||
delete_sem(device->rx_sem);
|
||||
delete_sem(device->rx_sem_cb);
|
||||
delete_sem(device->tx_sem);
|
||||
free(device);
|
||||
return NULL;
|
||||
}
|
||||
set_sem_owner(device->tx_sem_cb, B_SYSTEM_TEAM);
|
||||
|
||||
device->number = sDeviceNumber++;
|
||||
device->cookieMagic = PEGASUS_COOKIE_MAGIC;
|
||||
sprintf(device->name, "%s%d", kBaseName, device->number);
|
||||
device->dev = dev;
|
||||
device->ifno = ifno;
|
||||
device->open = 0;
|
||||
device->open_fds = NULL;
|
||||
device->aue_dying = false;
|
||||
device->flags = 0;
|
||||
device->maxframesize = 1514; // XXX is MAXIMUM_ETHERNET_FRAME_SIZE = 1518 too much?
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
remove_device(pegasus_dev *device)
|
||||
{
|
||||
ASSERT(device != NULL);
|
||||
|
||||
delete_sem(device->rx_sem);
|
||||
delete_sem(device->tx_sem);
|
||||
delete_sem(device->rx_sem_cb);
|
||||
delete_sem(device->tx_sem_cb);
|
||||
|
||||
delete_sem(device->sem_lock);
|
||||
|
||||
free(device);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\fn:
|
||||
*/
|
||||
static status_t
|
||||
setup_endpoints(const usb_interface_info *uii, pegasus_dev *dev)
|
||||
{
|
||||
ssize_t epts[3] = { -1, -1, -1 };
|
||||
size_t ep = 0;
|
||||
for(; ep < uii->endpoint_count; ep++){
|
||||
usb_endpoint_descriptor *ed = uii->endpoint[ep].descr;
|
||||
DPRINTF_INFO("try endpoint:%ld %x %x %lx\n", ep, ed->attributes,
|
||||
ed->endpoint_address, uii->endpoint[ep].handle);
|
||||
if ((ed->attributes & USB_ENDPOINT_ATTR_MASK) == USB_ENDPOINT_ATTR_BULK) {
|
||||
if ((ed->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
|
||||
== USB_ENDPOINT_ADDR_DIR_IN) {
|
||||
epts[0] = ep;
|
||||
} else
|
||||
epts[1] = ep;
|
||||
} else if ((ed->attributes & USB_ENDPOINT_ATTR_MASK)
|
||||
== USB_ENDPOINT_ATTR_INTERRUPT) {
|
||||
epts[2] = ep;
|
||||
}
|
||||
}
|
||||
|
||||
dev->pipe_in = uii->endpoint[epts[0]].handle;
|
||||
dev->pipe_out = uii->endpoint[epts[1]].handle;
|
||||
dev->pipe_intr = uii->endpoint[epts[2]].handle;
|
||||
DPRINTF_INFO("endpoint:%lx %lx %lx\n", dev->pipe_in, dev->pipe_out, dev->pipe_intr);
|
||||
|
||||
return ((epts[0] > -1) && (epts[1] > -1) && (epts[2] > -1)) ? B_OK : B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pegasus_rx_callback(void *cookie, status_t status, void *data, size_t actual_len)
|
||||
{
|
||||
pegasus_dev *dev = (pegasus_dev *)cookie;
|
||||
|
||||
DPRINTF_INFO("pegasus_rx_callback() %ld %ld\n", status, actual_len);
|
||||
if (status == B_CANCELED) {
|
||||
/* cancelled: device is unplugged */
|
||||
DPRINTF_ERR("pegasus_rx_callback() cancelled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(cookie != NULL);
|
||||
dev->rx_actual_length = actual_len;
|
||||
dev->rx_status = status; /* B_USB_STATUS_* */
|
||||
release_sem(dev->rx_sem_cb);
|
||||
DPRINTF_INFO("pegasus_rx_callback release sem %ld\n", dev->rx_sem_cb);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pegasus_tx_callback(void *cookie, status_t status, void *data, size_t actual_len)
|
||||
{
|
||||
pegasus_dev *dev = (pegasus_dev *)cookie;
|
||||
|
||||
DPRINTF_INFO("pegasus_tx_callback() %ld %ld\n", status, actual_len);
|
||||
if (status == B_CANCELED) {
|
||||
/* cancelled: device is unplugged */
|
||||
DPRINTF_ERR("pegasus_tx_callback() cancelled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(cookie != NULL);
|
||||
dev->tx_actual_length = actual_len;
|
||||
dev->tx_status = status; /* B_USB_STATUS_* */
|
||||
release_sem(dev->tx_sem_cb);
|
||||
DPRINTF_INFO("pegasus_tx_callback release sem %ld\n", dev->tx_sem_cb);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - device hooks
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_device_added(const usb_device dev, void **cookie)
|
||||
{
|
||||
pegasus_dev *device;
|
||||
const usb_device_descriptor *dev_desc;
|
||||
const usb_configuration_info *conf;
|
||||
const usb_interface_info *intf;
|
||||
status_t status;
|
||||
uint16 ifno;
|
||||
unsigned int i;
|
||||
|
||||
ASSERT(dev != 0 && cookie != NULL);
|
||||
DPRINTF_INFO("device_added()\n");
|
||||
|
||||
dev_desc = usb->get_device_descriptor(dev);
|
||||
|
||||
DPRINTF_INFO("vendor ID 0x%04X, product ID 0x%04X\n", dev_desc->vendor_id,
|
||||
dev_desc->product_id);
|
||||
|
||||
if ((conf = usb->get_nth_configuration(dev, DEFAULT_CONFIGURATION))
|
||||
== NULL) {
|
||||
DPRINTF_ERR("cannot get default configuration\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
ifno = AUE_IFACE_IDX;
|
||||
intf = conf->interface [ifno].active;
|
||||
|
||||
/* configuration */
|
||||
|
||||
if ((status = usb->set_configuration(dev, conf)) != B_OK) {
|
||||
DPRINTF_ERR("set_configuration() failed %s\n", strerror(status));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if ((device = create_device(dev, intf, ifno)) == NULL) {
|
||||
DPRINTF_ERR("create_device() failed\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
device->aue_vendor = dev_desc->vendor_id;
|
||||
device->aue_product = dev_desc->product_id;
|
||||
|
||||
for (i=0; i < sizeof(aue_devs) / sizeof(struct aue_type); i++)
|
||||
if (aue_devs[i].aue_dev.vendor == dev_desc->vendor_id
|
||||
&& aue_devs[i].aue_dev.product == dev_desc->product_id) {
|
||||
device->aue_flags = aue_devs[i].aue_flags;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find endpoints. */
|
||||
setup_endpoints(intf, device);
|
||||
|
||||
aue_attach(device);
|
||||
|
||||
DPRINTF_INFO("MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
device->macaddr[0], device->macaddr[1], device->macaddr[2],
|
||||
device->macaddr[3], device->macaddr[4], device->macaddr[5]);
|
||||
|
||||
aue_init(device);
|
||||
|
||||
/* create a port */
|
||||
add_device_info(device);
|
||||
|
||||
*cookie = device;
|
||||
DPRINTF_INFO("added %s\n", device->name);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_device_removed(void *cookie)
|
||||
{
|
||||
pegasus_dev *device = cookie;
|
||||
|
||||
ASSERT(cookie != NULL);
|
||||
|
||||
DPRINTF_INFO("device_removed(%s)\n", device->name);
|
||||
|
||||
aue_uninit(device);
|
||||
|
||||
usb->cancel_queued_transfers(device->pipe_in);
|
||||
usb->cancel_queued_transfers(device->pipe_out);
|
||||
usb->cancel_queued_transfers(device->pipe_intr);
|
||||
remove_device_info(device);
|
||||
|
||||
if (device->open == 0) {
|
||||
remove_device(device);
|
||||
} else {
|
||||
DPRINTF_INFO("%s still open\n", device->name);
|
||||
AUE_LOCK(device);
|
||||
device->aue_dying = true;
|
||||
AUE_UNLOCK(device);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_device_open(const char *name, uint32 flags,
|
||||
driver_cookie **out_cookie)
|
||||
{
|
||||
driver_cookie *cookie;
|
||||
pegasus_dev *device;
|
||||
status_t err;
|
||||
|
||||
ASSERT(name != NULL);
|
||||
ASSERT(out_cookie != NULL);
|
||||
DPRINTF_INFO("open(%s)\n", name);
|
||||
|
||||
if ((device = search_device_info(name)) == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
if ((cookie = malloc(sizeof(driver_cookie))) == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if ((err = acquire_sem(device->sem_lock)) != B_OK) {
|
||||
free(cookie);
|
||||
return err;
|
||||
}
|
||||
device->nonblocking = (flags & O_NONBLOCK) != 0;
|
||||
|
||||
cookie->device = device;
|
||||
cookie->next = device->open_fds;
|
||||
device->open_fds = cookie;
|
||||
device->open++;
|
||||
release_sem(device->sem_lock);
|
||||
|
||||
*out_cookie = cookie;
|
||||
DPRINTF_INFO("device %s open (%d)\n", name, device->open);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_device_read(driver_cookie *cookie, off_t position, void *buffer, size_t *_length)
|
||||
{
|
||||
pegasus_dev *dev;
|
||||
status_t status;
|
||||
int32 blockFlag;
|
||||
size_t size;
|
||||
|
||||
DPRINTF_INFO("device %p read\n", cookie);
|
||||
|
||||
if (pegasus_checkdeviceinfo(dev = cookie->device) != B_OK) {
|
||||
DPRINTF_ERR("EINVAL\n");
|
||||
#ifndef __HAIKU__
|
||||
*_length = 0;
|
||||
// net_server work-around; it obviously doesn't care about error conditions
|
||||
// For Haiku, this can be removed
|
||||
#endif
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
if (dev->aue_dying)
|
||||
return B_DEVICE_NOT_FOUND; /* already unplugged */
|
||||
|
||||
blockFlag = dev->nonblocking ? B_TIMEOUT : 0;
|
||||
|
||||
// block until receive is available (if blocking is allowed)
|
||||
if ((status = acquire_sem_etc(dev->rx_sem, 1, B_CAN_INTERRUPT | blockFlag, 0)) != B_NO_ERROR) {
|
||||
DPRINTF_ERR("cannot acquire read sem: %" B_PRIx32 ", %s\n", status, strerror(status));
|
||||
#ifndef __HAIKU__
|
||||
*_length = 0;
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
// queue new request
|
||||
status = usb->queue_bulk(dev->pipe_in, dev->rx_buffer, MAX_FRAME_SIZE, &pegasus_rx_callback, dev);
|
||||
|
||||
if (status != B_OK) {
|
||||
DPRINTF_ERR("queue_bulk:failed:%08" B_PRIx32 "\n", status);
|
||||
goto rx_done;
|
||||
}
|
||||
|
||||
// block until data is available (if blocking is allowed)
|
||||
if ((status = acquire_sem_etc(dev->rx_sem_cb, 1, B_CAN_INTERRUPT | blockFlag, 0)) != B_NO_ERROR) {
|
||||
DPRINTF_ERR("cannot acquire read sem: %" B_PRIx32 ", %s\n", status, strerror(status));
|
||||
#ifndef __HAIKU__
|
||||
*_length = 0;
|
||||
#endif
|
||||
goto rx_done;
|
||||
}
|
||||
|
||||
if (dev->rx_status != B_OK) {
|
||||
status = usb->clear_feature(dev->pipe_in, USB_FEATURE_ENDPOINT_HALT);
|
||||
if (status != B_OK)
|
||||
DPRINTF_ERR("clear_feature() error %s\n", strerror(status));
|
||||
goto rx_done;
|
||||
}
|
||||
|
||||
// copy buffer
|
||||
size = dev->rx_actual_length;
|
||||
if (size > MAX_FRAME_SIZE || (size - 2) > *_length) {
|
||||
DPRINTF_ERR("ERROR read: bad frame size %ld\n", size);
|
||||
size = *_length;
|
||||
} else if (size < *_length)
|
||||
*_length = size - 2;
|
||||
|
||||
memcpy(buffer, dev->rx_buffer, size);
|
||||
|
||||
DPRINTF_INFO("read done %ld\n", *_length);
|
||||
|
||||
rx_done:
|
||||
release_sem(dev->rx_sem);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_device_write(driver_cookie *cookie, off_t position, const void *buffer, size_t *_length)
|
||||
{
|
||||
pegasus_dev *dev;
|
||||
status_t status;
|
||||
uint16 frameSize;
|
||||
|
||||
DPRINTF_INFO("device %p write %ld\n", cookie, *_length);
|
||||
|
||||
if (pegasus_checkdeviceinfo(dev = cookie->device) != B_OK) {
|
||||
DPRINTF_ERR("EINVAL\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (dev->aue_dying)
|
||||
return B_DEVICE_NOT_FOUND; /* already unplugged */
|
||||
|
||||
// block until a free tx descriptor is available
|
||||
if ((status = acquire_sem_etc(dev->tx_sem, 1, B_TIMEOUT, ETHER_TRANSMIT_TIMEOUT)) < B_NO_ERROR) {
|
||||
DPRINTF_ERR("write: acquiring sem failed: %" B_PRIx32 ", %s\n", status, strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
if (*_length > MAX_FRAME_SIZE)
|
||||
*_length = MAX_FRAME_SIZE;
|
||||
|
||||
frameSize = *_length;
|
||||
|
||||
/* Copy data to tx buffer */
|
||||
memcpy(dev->tx_buffer+2, buffer, frameSize);
|
||||
|
||||
/*
|
||||
* The ADMtek documentation says that the packet length is
|
||||
* supposed to be specified in the first two bytes of the
|
||||
* transfer, however it actually seems to ignore this info
|
||||
* and base the frame size on the bulk transfer length.
|
||||
*/
|
||||
dev->tx_buffer[0] = (uint8)frameSize;
|
||||
dev->tx_buffer[1] = (uint8)(frameSize >> 8);
|
||||
|
||||
// queue new request, bulk length is one more if size is a multiple of 64
|
||||
status = usb->queue_bulk(dev->pipe_out, dev->tx_buffer, ((frameSize + 2) & 0x3f) ? frameSize + 2 : frameSize + 3,
|
||||
&pegasus_tx_callback, dev);
|
||||
|
||||
if (status != B_OK){
|
||||
DPRINTF_ERR("queue_bulk:failed:%08" B_PRIx32 "\n", status);
|
||||
goto tx_done;
|
||||
}
|
||||
|
||||
// block until data is sent (if blocking is allowed)
|
||||
if ((status = acquire_sem_etc(dev->tx_sem_cb, 1, B_CAN_INTERRUPT, 0)) != B_NO_ERROR) {
|
||||
DPRINTF_ERR("cannot acquire write done sem: %" B_PRIx32 ", %s\n", status, strerror(status));
|
||||
#ifndef __HAIKU__
|
||||
*_length = 0;
|
||||
#endif
|
||||
goto tx_done;
|
||||
}
|
||||
|
||||
if (dev->tx_status != B_OK) {
|
||||
status = usb->clear_feature(dev->pipe_out, USB_FEATURE_ENDPOINT_HALT);
|
||||
if (status != B_OK)
|
||||
DPRINTF_ERR("clear_feature() error %s\n", strerror(status));
|
||||
goto tx_done;
|
||||
}
|
||||
|
||||
*_length = frameSize;
|
||||
|
||||
tx_done:
|
||||
release_sem(dev->tx_sem);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_device_control(driver_cookie *cookie, uint32 op,
|
||||
void *arg, size_t len)
|
||||
{
|
||||
status_t err = B_ERROR;
|
||||
pegasus_dev *device;
|
||||
|
||||
ASSERT(cookie != NULL);
|
||||
device = cookie->device;
|
||||
ASSERT(device != NULL);
|
||||
DPRINTF_INFO("ioctl(0x%x)\n", (int)op);
|
||||
|
||||
if (device->aue_dying)
|
||||
return B_DEVICE_NOT_FOUND; /* already unplugged */
|
||||
|
||||
switch (op) {
|
||||
case ETHER_INIT:
|
||||
DPRINTF_INFO("control() ETHER_INIT\n");
|
||||
return B_OK;
|
||||
|
||||
case ETHER_GETADDR:
|
||||
DPRINTF_INFO("control() ETHER_GETADDR\n");
|
||||
memcpy(arg, &device->macaddr, sizeof(device->macaddr));
|
||||
return B_OK;
|
||||
|
||||
case ETHER_NONBLOCK:
|
||||
if (*(int32 *)arg) {
|
||||
DPRINTF_INFO("non blocking mode on\n");
|
||||
device->nonblocking = true;
|
||||
} else {
|
||||
DPRINTF_INFO("non blocking mode off\n");
|
||||
device->nonblocking = false;
|
||||
}
|
||||
return B_OK;
|
||||
|
||||
case ETHER_ADDMULTI:
|
||||
DPRINTF_INFO("control() ETHER_ADDMULTI\n");
|
||||
break;
|
||||
|
||||
case ETHER_REMMULTI:
|
||||
DPRINTF_INFO("control() ETHER_REMMULTI\n");
|
||||
return B_OK;
|
||||
|
||||
case ETHER_SETPROMISC:
|
||||
if (*(int32 *)arg) {
|
||||
DPRINTF_INFO("control() ETHER_SETPROMISC on\n");
|
||||
} else {
|
||||
DPRINTF_INFO("control() ETHER_SETPROMISC off\n");
|
||||
}
|
||||
return B_OK;
|
||||
|
||||
case ETHER_GETFRAMESIZE:
|
||||
DPRINTF_INFO("control() ETHER_GETFRAMESIZE, framesize = %ld (MTU = %ld)\n", device->maxframesize, device->maxframesize - ENET_HEADER_SIZE);
|
||||
*(uint32*)arg = device->maxframesize;
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
DPRINTF_INFO("control() Invalid command\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_device_close(driver_cookie *cookie)
|
||||
{
|
||||
pegasus_dev *device;
|
||||
|
||||
ASSERT(cookie != NULL && cookie->device != NULL);
|
||||
device = cookie->device;
|
||||
DPRINTF_INFO("close(%s)\n", device->name);
|
||||
|
||||
/* detach the cookie from list */
|
||||
|
||||
acquire_sem(device->sem_lock);
|
||||
if (device->open_fds == cookie)
|
||||
device->open_fds = cookie->next;
|
||||
else {
|
||||
driver_cookie *p;
|
||||
for (p = device->open_fds; p != NULL; p = p->next) {
|
||||
if (p->next == cookie) {
|
||||
p->next = cookie->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
--device->open;
|
||||
release_sem(device->sem_lock);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pegasus_device_free(driver_cookie *cookie)
|
||||
{
|
||||
pegasus_dev *device;
|
||||
|
||||
ASSERT(cookie != NULL && cookie->device != NULL);
|
||||
device = cookie->device;
|
||||
DPRINTF_INFO("free(%s)\n", device->name);
|
||||
|
||||
free(cookie);
|
||||
if (device->open > 0)
|
||||
DPRINTF_INFO("%d opens left\n", device->open);
|
||||
else if (device->aue_dying) {
|
||||
DPRINTF_INFO("removed %s\n", device->name);
|
||||
remove_device(device);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Driver Hooks ---------------------------------------------------------
|
||||
**
|
||||
** These functions provide the glue used by DevFS to load/unload
|
||||
** the driver and also handle registering with the USB bus manager
|
||||
** to receive device added and removed events
|
||||
*/
|
||||
|
||||
static usb_notify_hooks notify_hooks =
|
||||
{
|
||||
&pegasus_device_added,
|
||||
&pegasus_device_removed
|
||||
};
|
||||
|
||||
|
||||
status_t
|
||||
init_hardware(void)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
init_driver(void)
|
||||
{
|
||||
DPRINTF_INFO("init_driver(), built %s %s\n", __DATE__, __TIME__);
|
||||
|
||||
#if DEBUG_DRIVER
|
||||
if (load_driver_symbols(drivername) == B_OK) {
|
||||
DPRINTF_INFO("loaded symbols\n");
|
||||
} else {
|
||||
DPRINTF_INFO("no symbols for you!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (get_module(B_USB_MODULE_NAME, (module_info**) &usb) != B_OK) {
|
||||
DPRINTF_INFO("cannot get module \"%s\"\n", B_USB_MODULE_NAME);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if ((gDeviceListLock = create_sem(1, "dev_list_lock")) < 0) {
|
||||
put_module(B_USB_MODULE_NAME);
|
||||
return gDeviceListLock;
|
||||
}
|
||||
|
||||
usb->register_driver(kDriverName, supported_devices,
|
||||
sizeof(supported_devices)/sizeof(usb_support_descriptor), NULL);
|
||||
usb->install_notify(kDriverName, ¬ify_hooks);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_driver(void)
|
||||
{
|
||||
DPRINTF_INFO("uninit_driver()\n");
|
||||
|
||||
usb->uninstall_notify(kDriverName);
|
||||
delete_sem(gDeviceListLock);
|
||||
put_module(B_USB_MODULE_NAME);
|
||||
free_device_names();
|
||||
}
|
||||
|
||||
|
||||
const char**
|
||||
publish_devices(void)
|
||||
{
|
||||
if (gDeviceListChanged) {
|
||||
free_device_names();
|
||||
alloc_device_names();
|
||||
if (gDeviceNames != NULL)
|
||||
rebuild_device_names();
|
||||
gDeviceListChanged = false;
|
||||
}
|
||||
ASSERT(gDeviceNames != NULL);
|
||||
return (const char **) gDeviceNames;
|
||||
}
|
||||
|
||||
|
||||
device_hooks*
|
||||
find_device(const char* name)
|
||||
{
|
||||
static device_hooks hooks = {
|
||||
(device_open_hook)pegasus_device_open,
|
||||
(device_close_hook)pegasus_device_close,
|
||||
(device_free_hook)pegasus_device_free,
|
||||
(device_control_hook)pegasus_device_control,
|
||||
(device_read_hook)pegasus_device_read,
|
||||
(device_write_hook)pegasus_device_write,
|
||||
NULL
|
||||
};
|
||||
|
||||
if (search_device_info(name) != NULL)
|
||||
return &hooks;
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Pegasus BeOS Driver
|
||||
*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jérôme Duval
|
||||
*/
|
||||
#ifndef _DEV_PEGASUS_H_
|
||||
#define _DEV_PEGASUS_H_
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <OS.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <USB3.h>
|
||||
|
||||
#include "ether_driver.h"
|
||||
|
||||
#include "ByteOrder.h"
|
||||
|
||||
// compat
|
||||
#define u_uint8_t uint8
|
||||
#define u_uint16_t uint16
|
||||
#define u_int8_t int8
|
||||
#define u_int16_t int16
|
||||
#define DELAY snooze
|
||||
|
||||
#include "if_auereg.h"
|
||||
|
||||
#define VERSION "Version 0, Copyright (c) 2006 Jérôme Duval, compiled on " ## __DATE__ ## " " ## __TIME__
|
||||
#define DRIVER_NAME "pegasus"
|
||||
|
||||
#define MY_ID "\033[34m" DRIVER_NAME ":\033[m "
|
||||
#define MY_ERR "\033[31merror:\033[m "
|
||||
#define MY_WARN "\033[31mwarning:\033[m "
|
||||
|
||||
//#define DEBUG 1
|
||||
#if DEBUG
|
||||
#define DPRINTF_INFO(x...) dprintf(MY_ID x)
|
||||
#define DPRINTF_ERR(x...) dprintf(MY_ID x)
|
||||
#else
|
||||
#define DPRINTF_INFO(x...)
|
||||
#define DPRINTF_ERR(x...) dprintf(MY_ID x)
|
||||
#endif
|
||||
|
||||
#define ASSERT(x) \
|
||||
((x) ? 0 : dprintf (MY_ID "assertion failed at " __FILE__ ", line %d\n", __LINE__))
|
||||
|
||||
#define NUM_CARDS 3
|
||||
#define DEVNAME 32
|
||||
|
||||
#define DEFAULT_CONFIGURATION 0
|
||||
|
||||
#define ENET_HEADER_SIZE 14
|
||||
#define ETHER_ADDRESS_LENGTH 6
|
||||
#define MAX_FRAME_SIZE 1536
|
||||
#define ETHER_TRANSMIT_TIMEOUT ((bigtime_t)5000000)
|
||||
/* five seconds */
|
||||
|
||||
/*
|
||||
* Various supported device vendors/products.
|
||||
*/
|
||||
struct aue_type {
|
||||
struct usb_devno {
|
||||
uint16 vendor;
|
||||
uint16 product;
|
||||
} aue_dev;
|
||||
uint16 aue_flags;
|
||||
#define LSYS 0x0001 /* use Linksys reset */
|
||||
#define PNA 0x0002 /* has Home PNA */
|
||||
#define PII 0x0004 /* Pegasus II chip */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
typedef struct _pegasus_dev {
|
||||
/* list structure */
|
||||
struct _pegasus_dev *next;
|
||||
|
||||
uint32 cookieMagic;
|
||||
|
||||
/* maintain device */
|
||||
sem_id sem_lock;
|
||||
|
||||
char name[DEVNAME]; /* used for resources */
|
||||
int type;
|
||||
usb_device dev;
|
||||
uint16 aue_vendor;
|
||||
uint16 aue_product;
|
||||
|
||||
uint16 ifno;
|
||||
|
||||
int open;
|
||||
struct driver_cookie *open_fds;
|
||||
volatile bool aue_dying;
|
||||
int number;
|
||||
uint flags;
|
||||
|
||||
int aue_unit;
|
||||
uint16 aue_flags;
|
||||
|
||||
volatile bool nonblocking;
|
||||
|
||||
uint32 maxframesize; // 14 bytes header + MTU
|
||||
uint8 macaddr[6];
|
||||
|
||||
usb_pipe pipe_in; /**/
|
||||
usb_pipe pipe_out; /**/
|
||||
usb_pipe pipe_intr; /**/
|
||||
|
||||
uint16 phy;
|
||||
bool link;
|
||||
|
||||
// receive data
|
||||
|
||||
sem_id rx_sem;
|
||||
sem_id rx_sem_cb;
|
||||
char rx_buffer[MAX_FRAME_SIZE];
|
||||
status_t rx_status;
|
||||
size_t rx_actual_length;
|
||||
|
||||
// transmit data
|
||||
|
||||
sem_id tx_sem;
|
||||
sem_id tx_sem_cb;
|
||||
char tx_buffer[MAX_FRAME_SIZE];
|
||||
status_t tx_status;
|
||||
size_t tx_actual_length;
|
||||
|
||||
} pegasus_dev;
|
||||
|
||||
#define PEGASUS_COOKIE_MAGIC 'pega'
|
||||
|
||||
|
||||
/* driver.c */
|
||||
|
||||
extern usb_module_info *usb;
|
||||
|
||||
pegasus_dev *create_device(const usb_device dev, const usb_interface_info *ii, uint16 ifno);
|
||||
void remove_device(pegasus_dev *device);
|
||||
|
||||
/* devlist.c */
|
||||
|
||||
extern sem_id gDeviceListLock;
|
||||
extern bool gDeviceListChanged;
|
||||
|
||||
void add_device_info(pegasus_dev *device);
|
||||
void remove_device_info(pegasus_dev *device);
|
||||
pegasus_dev *search_device_info(const char *name);
|
||||
|
||||
extern char **gDeviceNames;
|
||||
|
||||
void alloc_device_names(void);
|
||||
void free_device_names(void);
|
||||
void rebuild_device_names(void);
|
||||
|
||||
/* if_aue.c */
|
||||
void aue_attach(pegasus_dev *sc);
|
||||
void aue_init(pegasus_dev *sc);
|
||||
void aue_uninit(pegasus_dev *sc);
|
||||
|
||||
#endif /* _DEV_PEGASUS_H_ */
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2025, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/bus.h>
|
||||
|
||||
|
||||
extern driver_t* DRIVER_MODULE_NAME(aue, uhub);
|
||||
|
||||
HAIKU_FBSD_DRIVERS_GLUE(pegasus)
|
||||
HAIKU_DRIVER_REQUIREMENTS(0);
|
||||
HAIKU_FBSD_MII_DRIVER(acphy);
|
||||
NO_HAIKU_CHECK_DISABLE_INTERRUPTS();
|
||||
NO_HAIKU_REENABLE_INTERRUPTS();
|
||||
|
||||
|
||||
void
|
||||
__haiku_init_hardware()
|
||||
{
|
||||
driver_t *usb_drivers[] = {
|
||||
DRIVER_MODULE_NAME(aue, uhub),
|
||||
NULL
|
||||
};
|
||||
_fbsd_init_hardware_uhub(usb_drivers);
|
||||
}
|
||||
@@ -1,458 +0,0 @@
|
||||
/*
|
||||
* Pegasus BeOS Driver
|
||||
*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jérôme Duval
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 1999, 2000
|
||||
* Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``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 Bill Paul OR THE VOICES IN HIS HEAD
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "driver.h"
|
||||
#include "usbdevs.h"
|
||||
|
||||
extern usb_module_info *usb;
|
||||
|
||||
#define AUE_SETBIT(sc, reg, x) \
|
||||
aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) | (x))
|
||||
|
||||
#define AUE_CLRBIT(sc, reg, x) \
|
||||
aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) & ~(x))
|
||||
|
||||
static int
|
||||
aue_csr_read_1(pegasus_dev *sc, int reg)
|
||||
{
|
||||
status_t err;
|
||||
uint8 val = 0;
|
||||
size_t length;
|
||||
|
||||
if (sc->aue_dying)
|
||||
return (0);
|
||||
|
||||
AUE_LOCK(sc);
|
||||
|
||||
err = usb->send_request(sc->dev, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN,
|
||||
AUE_UR_READREG, 0, reg, 1, &val, &length);
|
||||
AUE_UNLOCK(sc);
|
||||
|
||||
if (err) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
static int
|
||||
aue_csr_read_2(pegasus_dev *sc, int reg)
|
||||
{
|
||||
status_t err;
|
||||
uint16 val = 0;
|
||||
size_t length;
|
||||
|
||||
if (sc->aue_dying)
|
||||
return (0);
|
||||
|
||||
AUE_LOCK(sc);
|
||||
|
||||
err = usb->send_request(sc->dev, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN,
|
||||
AUE_UR_READREG, 0, reg, 2, &val, &length);
|
||||
|
||||
AUE_UNLOCK(sc);
|
||||
|
||||
if (err) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
static int
|
||||
aue_csr_write_1(pegasus_dev *sc, int reg, int val)
|
||||
{
|
||||
status_t err;
|
||||
size_t length = 1;
|
||||
|
||||
if (sc->aue_dying)
|
||||
return (0);
|
||||
|
||||
AUE_LOCK(sc);
|
||||
|
||||
err = usb->send_request(sc->dev, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
|
||||
AUE_UR_WRITEREG, val, reg, 1, &val, &length);
|
||||
|
||||
AUE_UNLOCK(sc);
|
||||
|
||||
if (err) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aue_csr_write_2(pegasus_dev *sc, int reg, int val)
|
||||
{
|
||||
status_t err;
|
||||
size_t length = 2;
|
||||
|
||||
if (sc->aue_dying)
|
||||
return (0);
|
||||
|
||||
AUE_LOCK(sc);
|
||||
|
||||
err = usb->send_request(sc->dev, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
|
||||
AUE_UR_WRITEREG, val, reg, 2, &val, &length);
|
||||
|
||||
AUE_UNLOCK(sc);
|
||||
|
||||
if (err) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a word of data stored in the EEPROM at address 'addr.'
|
||||
*/
|
||||
static void
|
||||
aue_eeprom_getword(pegasus_dev *sc, int addr, u_int16_t *dest)
|
||||
{
|
||||
int i;
|
||||
u_int16_t word = 0;
|
||||
|
||||
aue_csr_write_1(sc, AUE_EE_REG, addr);
|
||||
aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ);
|
||||
|
||||
for (i = 0; i < AUE_TIMEOUT; i++) {
|
||||
if (aue_csr_read_1(sc, AUE_EE_CTL) & AUE_EECTL_DONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == AUE_TIMEOUT) {
|
||||
dprintf("aue%d: EEPROM read timed out\n",
|
||||
sc->aue_unit);
|
||||
}
|
||||
|
||||
word = aue_csr_read_2(sc, AUE_EE_DATA);
|
||||
*dest = word;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read a sequence of words from the EEPROM.
|
||||
*/
|
||||
static void
|
||||
aue_read_eeprom(pegasus_dev *sc, caddr_t dest, int off, int cnt, int swap)
|
||||
{
|
||||
int i;
|
||||
u_int16_t word = 0, *ptr;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
aue_eeprom_getword(sc, off + i, &word);
|
||||
ptr = (u_int16_t *)(dest + (i * 2));
|
||||
if (swap)
|
||||
*ptr = B_BENDIAN_TO_HOST_INT16(word);
|
||||
else
|
||||
*ptr = word;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
aue_miibus_readreg(pegasus_dev *sc, int phy, int reg)
|
||||
{
|
||||
int i;
|
||||
u_int16_t val = 0;
|
||||
|
||||
/*
|
||||
* The Am79C901 HomePNA PHY actually contains
|
||||
* two transceivers: a 1Mbps HomePNA PHY and a
|
||||
* 10Mbps full/half duplex ethernet PHY with
|
||||
* NWAY autoneg. However in the ADMtek adapter,
|
||||
* only the 1Mbps PHY is actually connected to
|
||||
* anything, so we ignore the 10Mbps one. It
|
||||
* happens to be configured for MII address 3,
|
||||
* so we filter that out.
|
||||
*/
|
||||
if (sc->aue_vendor == USB_VENDOR_ADMTEK &&
|
||||
sc->aue_product == USB_PRODUCT_ADMTEK_PEGASUS) {
|
||||
if (phy == 3)
|
||||
return (0);
|
||||
#ifdef notdef
|
||||
if (phy != 1)
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
aue_csr_write_1(sc, AUE_PHY_ADDR, phy);
|
||||
aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_READ);
|
||||
|
||||
for (i = 0; i < AUE_TIMEOUT; i++) {
|
||||
if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == AUE_TIMEOUT) {
|
||||
dprintf("aue%d: MII read timed out\n", sc->aue_unit);
|
||||
}
|
||||
|
||||
val = aue_csr_read_2(sc, AUE_PHY_DATA);
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
aue_miibus_writereg(pegasus_dev *sc, int phy, int reg, int data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (phy == 3)
|
||||
return (0);
|
||||
|
||||
aue_csr_write_2(sc, AUE_PHY_DATA, data);
|
||||
aue_csr_write_1(sc, AUE_PHY_ADDR, phy);
|
||||
aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_WRITE);
|
||||
|
||||
for (i = 0; i < AUE_TIMEOUT; i++) {
|
||||
if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == AUE_TIMEOUT) {
|
||||
dprintf("aue%d: MII read timed out\n",
|
||||
sc->aue_unit);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static uint16
|
||||
aue_miibus_read(pegasus_dev *dev, uint16 reg)
|
||||
{
|
||||
return aue_miibus_readreg(dev, dev->phy, reg);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aue_miibus_write(pegasus_dev *dev, uint16 reg, uint16 value)
|
||||
{
|
||||
aue_miibus_writereg(dev, dev->phy, reg, value);
|
||||
}
|
||||
|
||||
|
||||
static uint16
|
||||
aue_miibus_status_from_phy(pegasus_dev *dev, uint16 phy)
|
||||
{
|
||||
uint16 status;
|
||||
int i = 0;
|
||||
|
||||
// the status must be retrieved two times, because the first
|
||||
// one may not work on some PHYs (notably ICS 1893)
|
||||
while (i++ < 2)
|
||||
status = aue_miibus_readreg(dev, phy, MII_STATUS);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static uint16
|
||||
aue_miibus_status(pegasus_dev *dev)
|
||||
{
|
||||
return aue_miibus_status_from_phy(dev, dev->phy);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
aue_init_phy(pegasus_dev *dev)
|
||||
{
|
||||
uint16 phy, status;
|
||||
int i;
|
||||
|
||||
dev->phy = 255;
|
||||
|
||||
// search for total of 32 possible MII PHY addresses
|
||||
for (phy = 0; phy < 32; phy++) {
|
||||
uint16 status;
|
||||
|
||||
status = aue_miibus_status_from_phy(dev, phy);
|
||||
if (status == 0xffff || status == 0x0000)
|
||||
// this MII is not accessable
|
||||
continue;
|
||||
|
||||
dev->phy = phy;
|
||||
}
|
||||
|
||||
if (dev->phy == 255) {
|
||||
DPRINTF_ERR("No MII PHY transceiver found!\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
DPRINTF_INFO("aue_init_phy MII PHY found at %d\n", dev->phy);
|
||||
|
||||
status = aue_miibus_read(dev, MII_CONTROL);
|
||||
status &= ~MII_CONTROL_ISOLATE;
|
||||
|
||||
aue_miibus_write(dev, MII_CONTROL, status);
|
||||
|
||||
aue_miibus_write(dev, MII_CONTROL, MII_CONTROL_RESET);
|
||||
for (i = 0; i < 100; i++) {
|
||||
if ((aue_miibus_read(dev, MII_STATUS) & MII_CONTROL_RESET) == 0)
|
||||
break;
|
||||
DELAY(1000);
|
||||
}
|
||||
|
||||
dev->link = aue_miibus_status(dev) & MII_STATUS_LINK;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aue_reset_pegasus_II(pegasus_dev *sc)
|
||||
{
|
||||
/* Magic constants taken from Linux driver. */
|
||||
aue_csr_write_1(sc, AUE_REG_1D, 0);
|
||||
aue_csr_write_1(sc, AUE_REG_7B, 2);
|
||||
#if 0
|
||||
if ((sc->aue_flags & HAS_HOME_PNA) && mii_mode)
|
||||
aue_csr_write_1(sc, AUE_REG_81, 6);
|
||||
else
|
||||
#endif
|
||||
aue_csr_write_1(sc, AUE_REG_81, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
aue_reset(pegasus_dev *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_RESETMAC);
|
||||
|
||||
for (i = 0; i < AUE_TIMEOUT; i++) {
|
||||
if (!(aue_csr_read_1(sc, AUE_CTL1) & AUE_CTL1_RESETMAC))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == AUE_TIMEOUT)
|
||||
dprintf("aue%d: reset failed\n", sc->aue_unit);
|
||||
|
||||
/*
|
||||
* The PHY(s) attached to the Pegasus chip may be held
|
||||
* in reset until we flip on the GPIO outputs. Make sure
|
||||
* to set the GPIO pins high so that the PHY(s) will
|
||||
* be enabled.
|
||||
*
|
||||
* Note: We force all of the GPIO pins low first, *then*
|
||||
* enable the ones we want.
|
||||
*/
|
||||
aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0);
|
||||
aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0|AUE_GPIO_SEL1);
|
||||
|
||||
if (sc->aue_flags & LSYS) {
|
||||
/* Grrr. LinkSys has to be different from everyone else. */
|
||||
aue_csr_write_1(sc, AUE_GPIO0,
|
||||
AUE_GPIO_SEL0 | AUE_GPIO_SEL1);
|
||||
aue_csr_write_1(sc, AUE_GPIO0,
|
||||
AUE_GPIO_SEL0 | AUE_GPIO_SEL1 | AUE_GPIO_OUT0);
|
||||
}
|
||||
|
||||
if (sc->aue_flags & PII)
|
||||
aue_reset_pegasus_II(sc);
|
||||
|
||||
/* Wait a little while for the chip to get its brains in order. */
|
||||
DELAY(10000);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Attach
|
||||
*/
|
||||
void
|
||||
aue_attach(pegasus_dev *sc)
|
||||
{
|
||||
u_char eaddr[ETHER_ADDRESS_LENGTH];
|
||||
|
||||
AUE_LOCK(sc);
|
||||
|
||||
/* Reset the adapter. */
|
||||
aue_reset(sc);
|
||||
|
||||
/*
|
||||
* Get station address from the EEPROM.
|
||||
*/
|
||||
aue_read_eeprom(sc, (caddr_t)&eaddr, 0, 3, 0);
|
||||
|
||||
memcpy(sc->macaddr, eaddr, ETHER_ADDRESS_LENGTH);
|
||||
|
||||
if (aue_init_phy(sc) != B_OK)
|
||||
goto done;
|
||||
|
||||
sc->aue_dying = 0;
|
||||
|
||||
done:
|
||||
AUE_UNLOCK(sc);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
aue_init(pegasus_dev *sc)
|
||||
{
|
||||
|
||||
/* Enable RX and TX */
|
||||
aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB);
|
||||
AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB);
|
||||
AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_EP3_CLR);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
aue_uninit(pegasus_dev *sc)
|
||||
{
|
||||
aue_csr_write_1(sc, AUE_CTL0, 0);
|
||||
aue_csr_write_1(sc, AUE_CTL1, 0);
|
||||
aue_reset(sc);
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
/*
|
||||
* Pegasus BeOS Driver
|
||||
*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jérôme Duval
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 1999
|
||||
* Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``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 Bill Paul OR THE VOICES IN HIS HEAD
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: /repoman/r/ncvs/src/sys/dev/usb/if_auereg.h,v 1.22 2005/06/10 16:49:15 brooks Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Register definitions for ADMtek Pegasus AN986 USB to Ethernet
|
||||
* chip. The Pegasus uses a total of four USB endpoints: the control
|
||||
* endpoint (0), a bulk read endpoint for receiving packets (1),
|
||||
* a bulk write endpoint for sending packets (2) and an interrupt
|
||||
* endpoint for passing RX and TX status (3). Endpoint 0 is used
|
||||
* to read and write the ethernet module's registers. All registers
|
||||
* are 8 bits wide.
|
||||
*
|
||||
* Packet transfer is done in 64 byte chunks. The last chunk in a
|
||||
* transfer is denoted by having a length less that 64 bytes. For
|
||||
* the RX case, the data includes an optional RX status word.
|
||||
*/
|
||||
|
||||
#define AUE_UR_READREG 0xF0
|
||||
#define AUE_UR_WRITEREG 0xF1
|
||||
|
||||
#define AUE_CONFIG_NO 1
|
||||
#define AUE_IFACE_IDX 0
|
||||
|
||||
/*
|
||||
* Note that while the ADMtek technically has four
|
||||
* endpoints, the control endpoint (endpoint 0) is
|
||||
* regarded as special by the USB code and drivers
|
||||
* don't have direct access to it. (We access it
|
||||
* using usbd_do_request() when reading/writing
|
||||
* registers.) Consequently, our endpoint indexes
|
||||
* don't match those in the ADMtek Pegasus manual:
|
||||
* we consider the RX data endpoint to be index 0
|
||||
* and work up from there.
|
||||
*/
|
||||
#define AUE_ENDPT_RX 0x0
|
||||
#define AUE_ENDPT_TX 0x1
|
||||
#define AUE_ENDPT_INTR 0x2
|
||||
#define AUE_ENDPT_MAX 0x3
|
||||
|
||||
#define AUE_INTR_PKTLEN 0x8
|
||||
|
||||
#define AUE_CTL0 0x00
|
||||
#define AUE_CTL1 0x01
|
||||
#define AUE_CTL2 0x02
|
||||
#define AUE_MAR0 0x08
|
||||
#define AUE_MAR1 0x09
|
||||
#define AUE_MAR2 0x0A
|
||||
#define AUE_MAR3 0x0B
|
||||
#define AUE_MAR4 0x0C
|
||||
#define AUE_MAR5 0x0D
|
||||
#define AUE_MAR6 0x0E
|
||||
#define AUE_MAR7 0x0F
|
||||
#define AUE_MAR AUE_MAR0
|
||||
#define AUE_PAR0 0x10
|
||||
#define AUE_PAR1 0x11
|
||||
#define AUE_PAR2 0x12
|
||||
#define AUE_PAR3 0x13
|
||||
#define AUE_PAR4 0x14
|
||||
#define AUE_PAR5 0x15
|
||||
#define AUE_PAR AUE_PAR0
|
||||
#define AUE_PAUSE0 0x18
|
||||
#define AUE_PAUSE1 0x19
|
||||
#define AUE_PAUSE AUE_PAUSE0
|
||||
#define AUE_RX_FLOWCTL_CNT 0x1A
|
||||
#define AUE_RX_FLOWCTL_FIFO 0x1B
|
||||
#define AUE_REG_1D 0x1D
|
||||
#define AUE_EE_REG 0x20
|
||||
#define AUE_EE_DATA0 0x21
|
||||
#define AUE_EE_DATA1 0x22
|
||||
#define AUE_EE_DATA AUE_EE_DATA0
|
||||
#define AUE_EE_CTL 0x23
|
||||
#define AUE_PHY_ADDR 0x25
|
||||
#define AUE_PHY_DATA0 0x26
|
||||
#define AUE_PHY_DATA1 0x27
|
||||
#define AUE_PHY_DATA AUE_PHY_DATA0
|
||||
#define AUE_PHY_CTL 0x28
|
||||
#define AUE_USB_STS 0x2A
|
||||
#define AUE_TXSTAT0 0x2B
|
||||
#define AUE_TXSTAT1 0x2C
|
||||
#define AUE_TXSTAT AUE_TXSTAT0
|
||||
#define AUE_RXSTAT 0x2D
|
||||
#define AUE_PKTLOST0 0x2E
|
||||
#define AUE_PKTLOST1 0x2F
|
||||
#define AUE_PKTLOST AUE_PKTLOST0
|
||||
|
||||
#define AUE_REG_7B 0x7B
|
||||
#define AUE_GPIO0 0x7E
|
||||
#define AUE_GPIO1 0x7F
|
||||
#define AUE_REG_81 0x81
|
||||
|
||||
#define AUE_CTL0_INCLUDE_RXCRC 0x01
|
||||
#define AUE_CTL0_ALLMULTI 0x02
|
||||
#define AUE_CTL0_STOP_BACKOFF 0x04
|
||||
#define AUE_CTL0_RXSTAT_APPEND 0x08
|
||||
#define AUE_CTL0_WAKEON_ENB 0x10
|
||||
#define AUE_CTL0_RXPAUSE_ENB 0x20
|
||||
#define AUE_CTL0_RX_ENB 0x40
|
||||
#define AUE_CTL0_TX_ENB 0x80
|
||||
|
||||
#define AUE_CTL1_HOMELAN 0x04
|
||||
#define AUE_CTL1_RESETMAC 0x08
|
||||
#define AUE_CTL1_SPEEDSEL 0x10 /* 0 = 10mbps, 1 = 100mbps */
|
||||
#define AUE_CTL1_DUPLEX 0x20 /* 0 = half, 1 = full */
|
||||
#define AUE_CTL1_DELAYHOME 0x40
|
||||
|
||||
#define AUE_CTL2_EP3_CLR 0x01 /* reading EP3 clrs status regs */
|
||||
#define AUE_CTL2_RX_BADFRAMES 0x02
|
||||
#define AUE_CTL2_RX_PROMISC 0x04
|
||||
#define AUE_CTL2_LOOPBACK 0x08
|
||||
#define AUE_CTL2_EEPROMWR_ENB 0x10
|
||||
#define AUE_CTL2_EEPROM_LOAD 0x20
|
||||
|
||||
#define AUE_EECTL_WRITE 0x01
|
||||
#define AUE_EECTL_READ 0x02
|
||||
#define AUE_EECTL_DONE 0x04
|
||||
|
||||
#define AUE_PHYCTL_PHYREG 0x1F
|
||||
#define AUE_PHYCTL_WRITE 0x20
|
||||
#define AUE_PHYCTL_READ 0x40
|
||||
#define AUE_PHYCTL_DONE 0x80
|
||||
|
||||
#define AUE_USBSTS_SUSPEND 0x01
|
||||
#define AUE_USBSTS_RESUME 0x02
|
||||
|
||||
#define AUE_TXSTAT0_JABTIMO 0x04
|
||||
#define AUE_TXSTAT0_CARLOSS 0x08
|
||||
#define AUE_TXSTAT0_NOCARRIER 0x10
|
||||
#define AUE_TXSTAT0_LATECOLL 0x20
|
||||
#define AUE_TXSTAT0_EXCESSCOLL 0x40
|
||||
#define AUE_TXSTAT0_UNDERRUN 0x80
|
||||
|
||||
#define AUE_TXSTAT1_PKTCNT 0x0F
|
||||
#define AUE_TXSTAT1_FIFO_EMPTY 0x40
|
||||
#define AUE_TXSTAT1_FIFO_FULL 0x80
|
||||
|
||||
#define AUE_RXSTAT_OVERRUN 0x01
|
||||
#define AUE_RXSTAT_PAUSE 0x02
|
||||
|
||||
#define AUE_GPIO_IN0 0x01
|
||||
#define AUE_GPIO_OUT0 0x02
|
||||
#define AUE_GPIO_SEL0 0x04
|
||||
#define AUE_GPIO_IN1 0x08
|
||||
#define AUE_GPIO_OUT1 0x10
|
||||
#define AUE_GPIO_SEL1 0x20
|
||||
|
||||
struct aue_intrpkt {
|
||||
u_int8_t aue_txstat0;
|
||||
u_int8_t aue_txstat1;
|
||||
u_int8_t aue_rxstat;
|
||||
u_int8_t aue_rxlostpkt0;
|
||||
u_int8_t aue_rxlostpkt1;
|
||||
u_int8_t aue_wakeupstat;
|
||||
u_int8_t aue_rsvd;
|
||||
};
|
||||
|
||||
struct aue_rxpkt {
|
||||
u_int16_t aue_pktlen;
|
||||
u_int8_t aue_rxstat;
|
||||
};
|
||||
|
||||
#define AUE_RXSTAT_MCAST 0x01
|
||||
#define AUE_RXSTAT_GIANT 0x02
|
||||
#define AUE_RXSTAT_RUNT 0x04
|
||||
#define AUE_RXSTAT_CRCERR 0x08
|
||||
#define AUE_RXSTAT_DRIBBLE 0x10
|
||||
#define AUE_RXSTAT_MASK 0x1E
|
||||
|
||||
#define AUE_INC(x, y) (x) = (x + 1) % y
|
||||
|
||||
#if 0
|
||||
#define AUE_LOCK(_sc) mtx_lock(&(_sc)->aue_mtx)
|
||||
#define AUE_UNLOCK(_sc) mtx_unlock(&(_sc)->aue_mtx)
|
||||
#else
|
||||
#define AUE_LOCK(_sc)
|
||||
#define AUE_UNLOCK(_sc)
|
||||
#endif
|
||||
|
||||
#define AUE_TIMEOUT 1000
|
||||
#define AUE_MIN_FRAMELEN 60
|
||||
#define AUE_TX_TIMEOUT 10000 /* ms */
|
||||
#define AUE_INTR_INTERVAL 100 /* ms */
|
||||
#define AUE_BUFSZ 1536
|
||||
#define ETHER_ALIGN 2
|
||||
|
||||
|
||||
/***************************** Media Independent Interface *****************************/
|
||||
|
||||
|
||||
enum MII_address {
|
||||
// standard registers
|
||||
MII_CONTROL = 0x00,
|
||||
MII_STATUS = 0x01,
|
||||
MII_PHY_ID0 = 0x02,
|
||||
MII_PHY_ID1 = 0x03,
|
||||
MII_AUTONEG_ADV = 0x04,
|
||||
MII_AUTONEG_LINK_PARTNER = 0x05,
|
||||
MII_AUTONEG_EXT = 0x06,
|
||||
};
|
||||
|
||||
enum MII_control {
|
||||
MII_CONTROL_RESET = 0x8000,
|
||||
MII_CONTROL_RESET_AUTONEG = 0x0200,
|
||||
MII_CONTROL_AUTO = 0x1000,
|
||||
MII_CONTROL_FULL_DUPLEX = 0x0100,
|
||||
MII_CONTROL_ISOLATE = 0x0400
|
||||
};
|
||||
|
||||
enum SiS900_MII_commands {
|
||||
MII_CMD_READ = 0x6000,
|
||||
MII_CMD_WRITE = 0x5002,
|
||||
|
||||
MII_PHY_SHIFT = 7,
|
||||
MII_REG_SHIFT = 2,
|
||||
};
|
||||
|
||||
enum MII_status_bits {
|
||||
MII_STATUS_EXT = 0x0001,
|
||||
MII_STATUS_JAB = 0x0002,
|
||||
MII_STATUS_LINK = 0x0004,
|
||||
MII_STATUS_CAN_AUTO = 0x0008,
|
||||
MII_STATUS_FAULT = 0x0010,
|
||||
MII_STATUS_AUTO_DONE = 0x0020,
|
||||
MII_STATUS_CAN_T = 0x0800,
|
||||
MII_STATUS_CAN_T_FDX = 0x1000,
|
||||
MII_STATUS_CAN_TX = 0x2000,
|
||||
MII_STATUS_CAN_TX_FDX = 0x4000,
|
||||
MII_STATUS_CAN_T4 = 0x8000
|
||||
};
|
||||
|
||||
|
||||
enum MII_link_status {
|
||||
MII_LINK_FAIL = 0x4000,
|
||||
MII_LINK_100_MBIT = 0x0080,
|
||||
MII_LINK_FULL_DUPLEX = 0x0040
|
||||
};
|
||||
Reference in New Issue
Block a user