summaryrefslogtreecommitdiff
path: root/sys/dev/usb/if_axe.c
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2005-08-10 23:07:34 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2005-08-10 23:07:34 +0000
commitc86a5fad9b241f52414ca939344b39e6db088174 (patch)
tree4c21f8629de1d26442d4ef68aab0e6bab7899975 /sys/dev/usb/if_axe.c
parent8c3c3e548c40fd2582c0524443d999b99f19173d (diff)
Some of the bits that will be required for AX88178.
PHY doesn't attach possibly due to not twiddling GPIO pins correctly, rx and tx pipes being swapped not dealt with yet.
Diffstat (limited to 'sys/dev/usb/if_axe.c')
-rw-r--r--sys/dev/usb/if_axe.c82
1 files changed, 75 insertions, 7 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)