summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/if_axe.c82
-rw-r--r--sys/dev/usb/if_axereg.h64
2 files changed, 123 insertions, 23 deletions
diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c
index 86a9158f0e1..ea500e604c4 100644
--- a/sys/dev/usb/if_axe.c
+++ b/sys/dev/usb/if_axe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_axe.c,v 1.29 2005/08/01 05:36:48 brad Exp $ */
+/* $OpenBSD: if_axe.c,v 1.30 2005/08/10 23:07:33 jsg Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000-2003
@@ -154,6 +154,7 @@ Static const struct axe_type axe_devs[] = {
{ { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UF200}, 0 },
{ { USB_VENDOR_ACERCM, USB_PRODUCT_ACERCM_EP1427X2}, 0 },
{ { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172}, 0 },
+ { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178}, AX178 },
{ { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC210T}, 0 },
{ { USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_SNAPPORT}, 0 },
{ { USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB2AR}, 0},
@@ -261,6 +262,8 @@ axe_miibus_readreg(device_ptr_t dev, int phy, int reg)
* PHYs attached to the chip, so only read from those.
*/
+ DPRINTF(("axe_miibus_readreg: phy 0x%x reg 0x%x\n", phy, reg));
+
if (sc->axe_phyaddrs[0] != AXE_NOPHY && phy != sc->axe_phyaddrs[0])
return (0);
@@ -324,6 +327,11 @@ axe_miibus_statchg(device_ptr_t dev)
val = AXE_MEDIA_FULL_DUPLEX;
else
val = 0;
+
+ if (sc->axe_flags & AX178)
+ val |= (AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC |
+ AXE_178_MEDIA_ENCK);
+
DPRINTF(("axe_miibus_statchg: val=0x%x\n", val));
err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
if (err) {
@@ -450,11 +458,12 @@ USB_ATTACH(axe)
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
struct mii_data *mii;
+ u_int16_t eeprom;
u_char eaddr[ETHER_ADDR_LEN];
char *devinfop;
char *devname = USBDEVNAME(sc->axe_dev);
struct ifnet *ifp;
- int i, s;
+ int i, s, gpio0 = 0, phymode = 0;
devinfop = usbd_devinfo_alloc(dev, 0);
USB_ATTACH_SETUP;
@@ -468,6 +477,8 @@ USB_ATTACH(axe)
USB_ATTACH_ERROR_RETURN;
}
+ sc->axe_flags = axe_lookup(uaa->vendor, uaa->product)->axe_flags;
+
usb_init_task(&sc->axe_tick_task, axe_tick_task, sc);
lockinit(&sc->axe_mii_lock, PZERO, "axemii", 0, LK_CANRECURSE);
usb_init_task(&sc->axe_stop_task, (void (*)(void *))axe_stop, sc);
@@ -509,10 +520,56 @@ USB_ATTACH(axe)
s = splnet();
+ if (sc->axe_flags & AX178) {
+ axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL);
+ /* XXX magic */
+ axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom);
+ axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL);
+
+ DPRINTF((" EEPROM is 0x%x\n", eeprom));
+
+ /* if EEPROM is invalid we have to use to GPIO0 */
+ if (eeprom == 0xffff) {
+ phymode = 0;
+ gpio0 = 1;
+ } else {
+ phymode = eeprom & 7;
+ if (eeprom & 0x80)
+ gpio0 = 0;
+ }
+
+ DPRINTF(("use gpio0: %d, phymode %d\n", gpio0, phymode));
+
+ /* GPIO voodoo required to turn on PHY */
+ if (gpio0)
+ printf("gpio0 path not done! PHY not enabled\n");
+ else {
+ axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x008c, NULL);
+ if (phymode != 1) {
+ axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
+ axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x001c, NULL);
+ axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
+ } else {
+ axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x0004, NULL);
+ axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x000c, NULL);
+ }
+ }
+
+ axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0, NULL);
+ /* soft reset */
+ axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
+ AXE_178_RESET_PRL | AXE_178_RESET_MAGIC, NULL);
+ delay(500);
+ axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
+ }
+
/*
* Get station address.
*/
- axe_cmd(sc, AXE_CMD_READ_NODEID, 0, 0, &eaddr);
+ if (sc->axe_flags & AX178)
+ axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, &eaddr);
+ else
+ axe_cmd(sc, AXE_172_CMD_READ_NODEID, 0, 0, &eaddr);
/*
* Load IPG values and PHY indexes.
@@ -520,6 +577,9 @@ USB_ATTACH(axe)
axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, (void *)&sc->axe_ipgs);
axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs);
+ DPRINTF((" phyaddrs[0]: %x phyaddrs[1]: %x\n",
+ sc->axe_phyaddrs[0], sc->axe_phyaddrs[1]));
+
/*
* Work around broken adapters that appear to lie about
* their PHY addresses.
@@ -1115,12 +1175,20 @@ axe_init(void *xsc)
}
/* Set transmitter IPG values */
- axe_cmd(sc, AXE_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
- axe_cmd(sc, AXE_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
- axe_cmd(sc, AXE_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
+ if (sc->axe_flags & AX178)
+ axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, 0,
+ (sc->axe_ipgs[0] << 2) | (sc->axe_ipgs[1] << 1) |
+ (sc->axe_ipgs[2]), NULL);
+ else {
+ axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
+ axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
+ axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
+ }
/* Enable receiver, set RX mode */
- rxmode = AXE_RXCMD_UNICAST|AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
+ rxmode = AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
+ if (!(sc->axe_flags & AX178))
+ rxmode |= AXE_172_RXCMD_UNICAST;
/* If we want promiscuous mode, set the allframes bit. */
if (ifp->if_flags & IFF_PROMISC)
diff --git a/sys/dev/usb/if_axereg.h b/sys/dev/usb/if_axereg.h
index d25dca46810..cc895679e3f 100644
--- a/sys/dev/usb/if_axereg.h
+++ b/sys/dev/usb/if_axereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_axereg.h,v 1.4 2004/11/11 12:47:14 dlg Exp $ */
+/* $OpenBSD: if_axereg.h,v 1.5 2005/08/10 23:07:33 jsg Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000-2003
@@ -55,9 +55,11 @@
#define AXE_CMD_LEN(x) (((x) & 0xF000) >> 12)
#define AXE_CMD_CMD(x) ((x) & 0x00FF)
-#define AXE_CMD_READ_RXTX_SRAM 0x2002
-#define AXE_CMD_WRITE_RX_SRAM 0x0103
-#define AXE_CMD_WRITE_TX_SRAM 0x0104
+#define AXE_172_CMD_READ_RXTX_SRAM 0x2002
+#define AXE_182_CMD_READ_RXTX_SRAM 0x8002
+#define AXE_172_CMD_WRITE_RX_SRAM 0x0103
+#define AXE_172_CMD_WRITE_TX_SRAM 0x0104
+#define AXE_182_CMD_WRITE_RXTX_SRAM 0x8103
#define AXE_CMD_MII_OPMODE_SW 0x0106
#define AXE_CMD_MII_READ_REG 0x2007
#define AXE_CMD_MII_WRITE_REG 0x2108
@@ -70,28 +72,56 @@
#define AXE_CMD_RXCTL_READ 0x200F
#define AXE_CMD_RXCTL_WRITE 0x0110
#define AXE_CMD_READ_IPG012 0x3011
-#define AXE_CMD_WRITE_IPG0 0x0112
-#define AXE_CMD_WRITE_IPG1 0x0113
-#define AXE_CMD_WRITE_IPG2 0x0114
+#define AXE_172_CMD_WRITE_IPG0 0x0112
+#define AXE_172_CMD_WRITE_IPG1 0x0113
+#define AXE_172_CMD_WRITE_IPG2 0x0114
+#define AXE_178_CMD_WRITE_IPG012 0x0112
#define AXE_CMD_READ_MCAST 0x8015
#define AXE_CMD_WRITE_MCAST 0x8116
-#define AXE_CMD_READ_NODEID 0x6017
-#define AXE_CMD_WRITE_NODEID 0x6118
+#define AXE_172_CMD_READ_NODEID 0x6017
+#define AXE_172_CMD_WRITE_NODEID 0x6118
+#define AXE_178_CMD_READ_NODEID 0x6013
+#define AXE_178_CMD_WRITE_NODEID 0x6014
#define AXE_CMD_READ_PHYID 0x2019
-#define AXE_CMD_READ_MEDIA 0x101A
+#define AXE_172_CMD_READ_MEDIA 0x101A
+#define AXE_178_CMD_READ_MEDIA 0x201A
#define AXE_CMD_WRITE_MEDIA 0x011B
#define AXE_CMD_READ_MONITOR_MODE 0x101C
#define AXE_CMD_WRITE_MONITOR_MODE 0x011D
#define AXE_CMD_READ_GPIO 0x101E
#define AXE_CMD_WRITE_GPIO 0x011F
-
-#define AXE_MEDIA_FULL_DUPLEX 0x02
-#define AXE_MEDIA_TX_ABORT_ALLOW 0x04
-#define AXE_MEDIA_FLOW_CONTROL_EN 0x10
+#define AXE_CMD_SW_RESET_REG 0x0120
+#define AXE_CMD_SW_PHY_STATUS 0x0021
+#define AXE_CMD_SW_PHY_SELECT 0x0122
+
+#define AXE_178_RESET_RR 0x01
+#define AXE_178_RESET_RT 0x02
+#define AXE_178_RESET_PRTE 0x04
+#define AXE_178_RESET_PRL 0x08
+#define AXE_178_RESET_BZ 0x10
+/* AX88178 documentation says to always write this bit... */
+#define AXE_178_RESET_MAGIC 0x40
+
+#define AXE_178_MEDIA_GMII 0x0001
+#define AXE_MEDIA_FULL_DUPLEX 0x0002
+#define AXE_172_MEDIA_TX_ABORT_ALLOW 0x0004
+/* AX88178 documentation says to always write 1 to reserved bit... */
+#define AXE_178_MEDIA_MAGIC 0x0004
+#define AXE_178_MEDIA_ENCK 0x0008
+#define AXE_172_MEDIA_FLOW_CONTROL_EN 0x0010
+#define AXE_178_MEDIA_RXFLOW_CONTROL_EN 0x0010
+#define AXE_178_MEDIA_TXFLOW_CONTROL_EN 0x0020
+#define AXE_178_MEDIA_JUMBO_EN 0x0040
+#define AXE_178_MEDIA_LTPF_ONLY 0x0080
+#define AXE_178_MEDIA_RX_EN 0x0100
+#define AXE_178_MEDIA_PORT_SPEED 0x0200
+#define AXE_178_MEDIA_SBP 0x0800
+#define AXE_178_MEDIA_SUPERMAC 0x1000
#define AXE_RXCMD_PROMISC 0x0001
#define AXE_RXCMD_ALLMULTI 0x0002
-#define AXE_RXCMD_UNICAST 0x0004
+#define AXE_172_RXCMD_UNICAST 0x0004
+#define AXE_178_RXCMD_KEEP_INVALID_CRC 0x0004
#define AXE_RXCMD_BROADCAST 0x0008
#define AXE_RXCMD_MULTICAST 0x0010
#define AXE_RXCMD_ENABLE 0x0080
@@ -125,7 +155,7 @@
struct axe_type {
struct usb_devno axe_dev;
u_int16_t axe_flags;
-/* XXX No flags so far */
+#define AX178 0x0001 /* AX88178 */
};
struct axe_softc;
@@ -168,6 +198,8 @@ struct axe_softc {
u_int16_t axe_vendor;
u_int16_t axe_product;
+ u_int16_t axe_flags;
+
int axe_ed[AXE_ENDPT_MAX];
usbd_pipe_handle axe_ep[AXE_ENDPT_MAX];
int axe_unit;