if_ed_pccard.c revision 199380
1168404Spjd/*- 2168404Spjd * Copyright (c) 2005, M. Warner Losh 3168404Spjd * Copyright (c) 1995, David Greenman 4168404Spjd * All rights reserved. 5168404Spjd * 6168404Spjd * Redistribution and use in source and binary forms, with or without 7168404Spjd * modification, are permitted provided that the following conditions 8168404Spjd * are met: 9168404Spjd * 1. Redistributions of source code must retain the above copyright 10168404Spjd * notice unmodified, this list of conditions, and the following 11168404Spjd * disclaimer. 12168404Spjd * 2. Redistributions in binary form must reproduce the above copyright 13168404Spjd * notice, this list of conditions and the following disclaimer in the 14168404Spjd * documentation and/or other materials provided with the distribution. 15168404Spjd * 16168404Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19168404Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20168404Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21168404Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22185029Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26168404Spjd * SUCH DAMAGE. 27168404Spjd * 28168404Spjd * $FreeBSD: head/sys/dev/ed/if_ed_pccard.c 199380 2009-11-17 14:23:09Z jhb $ 29168404Spjd */ 30168404Spjd 31168404Spjd/* 32168404Spjd * Notes for adding media support. Each chipset is somewhat different 33168404Spjd * from the others. Linux has a table of OIDs that it uses to see what 34168404Spjd * supports the misc register of the NS83903. But a sampling of datasheets 35168404Spjd * I could dig up on cards I own paints a different picture. 36168404Spjd * 37185029Spjd * Chipset specific details: 38185029Spjd * NS 83903/902A paired 39185029Spjd * ccr base 0x1020 40168404Spjd * id register at 0x1000: 7-3 = 0, 2-0 = 1. 41185029Spjd * (maybe this test is too week) 42168404Spjd * misc register at 0x018: 43168404Spjd * 6 WAIT_TOUTENABLE enable watchdog timeout 44185029Spjd * 3 AUI/TPI 1 AUX, 0 TPI 45185029Spjd * 2 loopback 46185029Spjd * 1 gdlink (tpi mode only) 1 tp good, 0 tp bad 47185029Spjd * 0 0-no mam, 1 mam connected 48185029Spjd * 49185029Spjd * NS83926 appears to be a NS pcmcia glue chip used on the IBM Ethernet II 50185029Spjd * and the NEC PC9801N-J12 ccr base 0x2000! 51185029Spjd * 52185029Spjd * winbond 289c926 53185029Spjd * ccr base 0xfd0 54185029Spjd * cfb (am 0xff2): 55185029Spjd * 0-1 PHY01 00 TPI, 01 10B2, 10 10B5, 11 TPI (reduced squ) 56185029Spjd * 2 LNKEN 0 - enable link and auto switch, 1 disable 57185029Spjd * 3 LNKSTS TPI + LNKEN=0 + link good == 1, else 0 58185029Spjd * sr (am 0xff4) 59185029Spjd * 88 00 88 00 88 00, etc 60185029Spjd * 61185029Spjd * TMI tc3299a (cr PHY01 == 0) 62185029Spjd * ccr base 0x3f8 63185029Spjd * cra (io 0xa) 64185029Spjd * crb (io 0xb) 65185029Spjd * 0-1 PHY01 00 auto, 01 res, 10 10B5, 11 TPI 66185029Spjd * 2 GDLINK 1 disable checking of link 67185029Spjd * 6 LINK 0 bad link, 1 good link 68185029Spjd * 69185029Spjd * EN5017A, EN5020 no data, but very popular 70185029Spjd * Other chips? 71185029Spjd * NetBSD supports RTL8019, but none have surfaced that I can see 72185029Spjd */ 73185029Spjd 74185029Spjd#include <sys/param.h> 75185029Spjd#include <sys/systm.h> 76185029Spjd#include <sys/socket.h> 77185029Spjd#include <sys/kernel.h> 78185029Spjd#include <sys/conf.h> 79185029Spjd#include <sys/uio.h> 80185029Spjd 81185029Spjd#include <sys/module.h> 82185029Spjd#include <sys/bus.h> 83185029Spjd#include <machine/bus.h> 84185029Spjd#include <sys/rman.h> 85185029Spjd#include <machine/resource.h> 86185029Spjd 87185029Spjd#include <net/ethernet.h> 88185029Spjd#include <net/if.h> 89185029Spjd#include <net/if_arp.h> 90185029Spjd#include <net/if_mib.h> 91185029Spjd#include <net/if_media.h> 92185029Spjd 93185029Spjd#include <dev/ed/if_edreg.h> 94185029Spjd#include <dev/ed/if_edvar.h> 95185029Spjd#include <dev/ed/ax88x90reg.h> 96185029Spjd#include <dev/ed/dl100xxreg.h> 97185029Spjd#include <dev/ed/tc5299jreg.h> 98185029Spjd#include <dev/pccard/pccardvar.h> 99185029Spjd#include <dev/pccard/pccardreg.h> 100185029Spjd#include <dev/pccard/pccard_cis.h> 101185029Spjd#include <dev/mii/mii.h> 102185029Spjd#include <dev/mii/miivar.h> 103185029Spjd 104185029Spjd#include "card_if.h" 105185029Spjd/* "device miibus" required. See GENERIC if you get errors here. */ 106185029Spjd#include "miibus_if.h" 107185029Spjd#include "pccarddevs.h" 108185029Spjd 109185029Spjd/* 110185029Spjd * NE-2000 based PC Cards have a number of ways to get the MAC address. 111185029Spjd * Some cards encode this as a FUNCE. Others have this in the ROMs the 112185029Spjd * same way that ISA cards do. Some have it encoded in the attribute 113185029Spjd * memory somewhere that isn't in the CIS. Some new chipsets have it 114185029Spjd * in special registers in the ASIC part of the chip. 115185029Spjd * 116185029Spjd * For those cards that have the MAC adress stored in attribute memory 117185029Spjd * outside of a FUNCE entry in the CIS, nearly all of them have it at 118185029Spjd * a fixed offset (0xff0). We use that offset as a source of last 119185029Spjd * resource if other offsets have failed. This is the address of the 120185029Spjd * National Semiconductor DP83903A, which is the only chip's datasheet 121185029Spjd * I've found. 122185029Spjd */ 123185029Spjd#define ED_DEFAULT_MAC_OFFSET 0xff0 124185029Spjd 125185029Spjdstatic const struct ed_product { 126185029Spjd struct pccard_product prod; 127185029Spjd int flags; 128185029Spjd#define NE2000DVF_DL100XX 0x0001 /* chip is D-Link DL10019/22 */ 129185029Spjd#define NE2000DVF_AX88X90 0x0002 /* chip is ASIX AX88[17]90 */ 130185029Spjd#define NE2000DVF_TC5299J 0x0004 /* chip is Tamarack TC5299J */ 131185029Spjd#define NE2000DVF_TOSHIBA 0x0008 /* Toshiba DP83902A */ 132185029Spjd#define NE2000DVF_ENADDR 0x0100 /* Get MAC from attr mem */ 133185029Spjd#define NE2000DVF_ANYFUNC 0x0200 /* Allow any function type */ 134185029Spjd#define NE2000DVF_MODEM 0x0400 /* Has a modem/serial */ 135185029Spjd int enoff; 136168404Spjd} ed_pccard_products[] = { 137168404Spjd { PCMCIA_CARD(ACCTON, EN2212), 0}, 138168404Spjd { PCMCIA_CARD(ACCTON, EN2216), 0}, 139168404Spjd { PCMCIA_CARD(ALLIEDTELESIS, LA_PCM), 0}, 140168404Spjd { PCMCIA_CARD(AMBICOM, AMB8002), 0}, 141168404Spjd { PCMCIA_CARD(AMBICOM, AMB8002T), 0}, 142185029Spjd { PCMCIA_CARD(AMBICOM, AMB8010), 0}, 143168404Spjd { PCMCIA_CARD(AMBICOM, AMB8010_ALT), 0}, 144168404Spjd { PCMCIA_CARD(AMBICOM, AMB8610), 0}, 145168404Spjd { PCMCIA_CARD(BILLIONTON, CFLT10N), 0}, 146168404Spjd { PCMCIA_CARD(BILLIONTON, LNA100B), NE2000DVF_AX88X90}, 147168404Spjd { PCMCIA_CARD(BILLIONTON, LNT10TB), 0}, 148168404Spjd { PCMCIA_CARD(BILLIONTON, LNT10TN), 0}, 149168404Spjd { PCMCIA_CARD(BROMAX, AXNET), NE2000DVF_AX88X90}, 150168404Spjd { PCMCIA_CARD(BROMAX, IPORT), 0}, 151168404Spjd { PCMCIA_CARD(BROMAX, IPORT2), 0}, 152168404Spjd { PCMCIA_CARD(BUFFALO, LPC2_CLT), 0}, 153168404Spjd { PCMCIA_CARD(BUFFALO, LPC3_CLT), 0}, 154168404Spjd { PCMCIA_CARD(BUFFALO, LPC3_CLX), NE2000DVF_AX88X90}, 155168404Spjd { PCMCIA_CARD(BUFFALO, LPC4_TX), NE2000DVF_AX88X90}, 156168404Spjd { PCMCIA_CARD(BUFFALO, LPC4_CLX), NE2000DVF_AX88X90}, 157168404Spjd { PCMCIA_CARD(BUFFALO, LPC_CF_CLT), 0}, 158168404Spjd { PCMCIA_CARD(CNET, NE2000), 0}, 159168404Spjd { PCMCIA_CARD(COMPEX, AX88190), NE2000DVF_AX88X90}, 160168404Spjd { PCMCIA_CARD(COMPEX, LANMODEM), 0}, 161168404Spjd { PCMCIA_CARD(COMPEX, LINKPORT_ENET_B), 0}, 162168404Spjd { PCMCIA_CARD(COREGA, ETHER_II_PCC_T), 0}, 163168404Spjd { PCMCIA_CARD(COREGA, ETHER_II_PCC_TD), 0}, 164168404Spjd { PCMCIA_CARD(COREGA, ETHER_PCC_T), 0}, 165168404Spjd { PCMCIA_CARD(COREGA, ETHER_PCC_TD), 0}, 166168404Spjd { PCMCIA_CARD(COREGA, FAST_ETHER_PCC_TX), NE2000DVF_DL100XX}, 167168404Spjd { PCMCIA_CARD(COREGA, FETHER_PCC_TXD), NE2000DVF_AX88X90}, 168168404Spjd { PCMCIA_CARD(COREGA, FETHER_PCC_TXF), NE2000DVF_DL100XX}, 169168404Spjd { PCMCIA_CARD(COREGA, FETHER_II_PCC_TXD), NE2000DVF_AX88X90}, 170168404Spjd { PCMCIA_CARD(COREGA, LAPCCTXD), 0}, 171168404Spjd { PCMCIA_CARD(DAYNA, COMMUNICARD_E_1), 0}, 172168404Spjd { PCMCIA_CARD(DAYNA, COMMUNICARD_E_2), 0}, 173168404Spjd { PCMCIA_CARD(DLINK, DE650), NE2000DVF_ANYFUNC }, 174168404Spjd { PCMCIA_CARD(DLINK, DE660), 0 }, 175168404Spjd { PCMCIA_CARD(DLINK, DE660PLUS), 0}, 176168404Spjd { PCMCIA_CARD(DYNALINK, L10C), 0}, 177168404Spjd { PCMCIA_CARD(EDIMAX, EP4000A), 0}, 178168404Spjd { PCMCIA_CARD(EPSON, EEN10B), 0}, 179168404Spjd { PCMCIA_CARD(EXP, THINLANCOMBO), 0}, 180168404Spjd { PCMCIA_CARD(GLOBALVILLAGE, LANMODEM), 0}, 181168404Spjd { PCMCIA_CARD(GREY_CELL, TDK3000), 0}, 182168404Spjd { PCMCIA_CARD(GREY_CELL, DMF650TX), 183168404Spjd NE2000DVF_ANYFUNC | NE2000DVF_DL100XX | NE2000DVF_MODEM}, 184197150Spjd { PCMCIA_CARD(GVC, NIC_2000P), 0}, 185168404Spjd { PCMCIA_CARD(IBM, HOME_AND_AWAY), 0}, 186168404Spjd { PCMCIA_CARD(IBM, INFOMOVER), 0}, 187168404Spjd { PCMCIA_CARD(IODATA3, PCLAT), 0}, 188197150Spjd { PCMCIA_CARD(KINGSTON, CIO10T), 0}, 189168404Spjd { PCMCIA_CARD(KINGSTON, KNE2), 0}, 190168404Spjd { PCMCIA_CARD(LANTECH, FASTNETTX), NE2000DVF_AX88X90}, 191168404Spjd /* Same ID for many different cards, including generic NE2000 */ 192168404Spjd { PCMCIA_CARD(LINKSYS, COMBO_ECARD), 193168404Spjd NE2000DVF_DL100XX | NE2000DVF_AX88X90}, 194168404Spjd { PCMCIA_CARD(LINKSYS, ECARD_1), 0}, 195168404Spjd { PCMCIA_CARD(LINKSYS, ECARD_2), 0}, 196168404Spjd { PCMCIA_CARD(LINKSYS, ETHERFAST), NE2000DVF_DL100XX}, 197168404Spjd { PCMCIA_CARD(LINKSYS, TRUST_COMBO_ECARD), 0}, 198197150Spjd { PCMCIA_CARD(MACNICA, ME1_JEIDA), 0}, 199197150Spjd { PCMCIA_CARD(MAGICRAM, ETHER), 0}, 200197150Spjd { PCMCIA_CARD(MELCO, LPC3_CLX), NE2000DVF_AX88X90}, 201197150Spjd { PCMCIA_CARD(MELCO, LPC3_TX), NE2000DVF_AX88X90}, 202197150Spjd { PCMCIA_CARD(MELCO2, LPC2_T), 0}, 203197150Spjd { PCMCIA_CARD(MELCO2, LPC2_TX), 0}, 204168404Spjd { PCMCIA_CARD(MITSUBISHI, B8895), NE2000DVF_ANYFUNC}, /* NG */ 205168404Spjd { PCMCIA_CARD(MICRORESEARCH, MR10TPC), 0}, 206168404Spjd { PCMCIA_CARD(NDC, ND5100_E), 0}, 207185029Spjd { PCMCIA_CARD(NETGEAR, FA410TXC), NE2000DVF_DL100XX}, 208168404Spjd /* Same ID as DLINK DFE-670TXD. 670 has DL10022, fa411 has ax88790 */ 209168404Spjd { PCMCIA_CARD(NETGEAR, FA411), NE2000DVF_AX88X90 | NE2000DVF_DL100XX}, 210168404Spjd { PCMCIA_CARD(NEXTCOM, NEXTHAWK), 0}, 211168404Spjd { PCMCIA_CARD(NEWMEDIA, LANSURFER), NE2000DVF_ANYFUNC}, 212185029Spjd { PCMCIA_CARD(NEWMEDIA, LIVEWIRE), 0}, 213168404Spjd { PCMCIA_CARD(OEM2, 100BASE), NE2000DVF_AX88X90}, 214185029Spjd { PCMCIA_CARD(OEM2, ETHERNET), 0}, 215185029Spjd { PCMCIA_CARD(OEM2, FAST_ETHERNET), NE2000DVF_AX88X90}, 216168404Spjd { PCMCIA_CARD(OEM2, NE2000), 0}, 217185029Spjd { PCMCIA_CARD(PLANET, SMARTCOM2000), 0 }, 218168404Spjd { PCMCIA_CARD(PREMAX, PE200), 0}, 219168404Spjd { PCMCIA_CARD(PSION, LANGLOBAL), 220185029Spjd NE2000DVF_ANYFUNC | NE2000DVF_AX88X90 | NE2000DVF_MODEM}, 221168404Spjd { PCMCIA_CARD(RACORE, ETHERNET), 0}, 222168404Spjd { PCMCIA_CARD(RACORE, FASTENET), NE2000DVF_AX88X90}, 223185029Spjd { PCMCIA_CARD(RACORE, 8041TX), NE2000DVF_AX88X90 | NE2000DVF_TC5299J}, 224168404Spjd { PCMCIA_CARD(RELIA, COMBO), 0}, 225168404Spjd { PCMCIA_CARD(RIOS, PCCARD3), 0}, 226168404Spjd { PCMCIA_CARD(RPTI, EP400), 0}, 227185029Spjd { PCMCIA_CARD(RPTI, EP401), 0}, 228185029Spjd { PCMCIA_CARD(SMC, EZCARD), 0}, 229168404Spjd { PCMCIA_CARD(SOCKET, EA_ETHER), 0}, 230168404Spjd { PCMCIA_CARD(SOCKET, ES_1000), 0}, 231185029Spjd { PCMCIA_CARD(SOCKET, LP_ETHER), 0}, 232185029Spjd { PCMCIA_CARD(SOCKET, LP_ETHER_CF), 0}, 233185029Spjd { PCMCIA_CARD(SOCKET, LP_ETH_10_100_CF), NE2000DVF_DL100XX}, 234185029Spjd { PCMCIA_CARD(SVEC, COMBOCARD), 0}, 235168404Spjd { PCMCIA_CARD(SVEC, LANCARD), 0}, 236168404Spjd { PCMCIA_CARD(TAMARACK, ETHERNET), 0}, 237168404Spjd { PCMCIA_CARD(TDK, CFE_10), 0}, 238168404Spjd { PCMCIA_CARD(TDK, LAK_CD031), 0}, 239168404Spjd { PCMCIA_CARD(TDK, DFL5610WS), 0}, 240168404Spjd { PCMCIA_CARD(TELECOMDEVICE, LM5LT), 0 }, 241168404Spjd { PCMCIA_CARD(TELECOMDEVICE, TCD_HPC100), NE2000DVF_AX88X90}, 242168404Spjd { PCMCIA_CARD(TJ, PTJ_LAN_T), 0 }, 243168404Spjd { PCMCIA_CARD(TOSHIBA2, LANCT00A), NE2000DVF_ANYFUNC | NE2000DVF_TOSHIBA}, 244168404Spjd { PCMCIA_CARD(ZONET, ZEN), 0}, 245168404Spjd { { NULL } } 246168404Spjd}; 247168404Spjd 248168404Spjd/* 249168404Spjd * PC Card (PCMCIA) specific code. 250168404Spjd */ 251168404Spjdstatic int ed_pccard_probe(device_t); 252168404Spjdstatic int ed_pccard_attach(device_t); 253168404Spjdstatic void ed_pccard_tick(struct ed_softc *); 254168404Spjd 255168404Spjdstatic int ed_pccard_dl100xx(device_t dev, const struct ed_product *); 256168404Spjdstatic void ed_pccard_dl100xx_mii_reset(struct ed_softc *sc); 257168404Spjdstatic u_int ed_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits); 258168404Spjdstatic void ed_pccard_dl100xx_mii_writebits(struct ed_softc *sc, u_int val, 259168404Spjd int nbits); 260168404Spjd 261168404Spjdstatic int ed_pccard_ax88x90(device_t dev, const struct ed_product *); 262168404Spjdstatic u_int ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits); 263168404Spjdstatic void ed_pccard_ax88x90_mii_writebits(struct ed_softc *sc, u_int val, 264168404Spjd int nbits); 265168404Spjd 266168404Spjdstatic int ed_miibus_readreg(device_t dev, int phy, int reg); 267168404Spjdstatic int ed_ifmedia_upd(struct ifnet *); 268168404Spjdstatic void ed_ifmedia_sts(struct ifnet *, struct ifmediareq *); 269168404Spjd 270168404Spjdstatic int ed_pccard_tc5299j(device_t dev, const struct ed_product *); 271168404Spjdstatic u_int ed_pccard_tc5299j_mii_readbits(struct ed_softc *sc, int nbits); 272168404Spjdstatic void ed_pccard_tc5299j_mii_writebits(struct ed_softc *sc, u_int val, 273168404Spjd int nbits); 274168404Spjd 275168404Spjdstatic void 276168404Spjded_pccard_print_entry(const struct ed_product *pp) 277168404Spjd{ 278168404Spjd int i; 279168404Spjd 280168404Spjd printf("Product entry: "); 281168404Spjd if (pp->prod.pp_name) 282168404Spjd printf("name='%s',", pp->prod.pp_name); 283168404Spjd printf("vendor=%#x,product=%#x", pp->prod.pp_vendor, 284168404Spjd pp->prod.pp_product); 285168404Spjd for (i = 0; i < 4; i++) 286168404Spjd if (pp->prod.pp_cis[i]) 287168404Spjd printf(",CIS%d='%s'", i, pp->prod.pp_cis[i]); 288168404Spjd printf("\n"); 289168404Spjd} 290168404Spjd 291168404Spjdstatic int 292168404Spjded_pccard_probe(device_t dev) 293168404Spjd{ 294168404Spjd const struct ed_product *pp, *pp2; 295168404Spjd int error, first = 1; 296168404Spjd uint32_t fcn = PCCARD_FUNCTION_UNSPEC; 297168404Spjd 298168404Spjd /* Make sure we're a network function */ 299168404Spjd error = pccard_get_function(dev, &fcn); 300168404Spjd if (error != 0) 301185029Spjd return (error); 302168404Spjd 303168404Spjd if ((pp = (const struct ed_product *) pccard_product_lookup(dev, 304168404Spjd (const struct pccard_product *) ed_pccard_products, 305168404Spjd sizeof(ed_pccard_products[0]), NULL)) != NULL) { 306168404Spjd if (pp->prod.pp_name != NULL) 307168404Spjd device_set_desc(dev, pp->prod.pp_name); 308168404Spjd /* 309168404Spjd * Some devices don't ID themselves as network, but 310168404Spjd * that's OK if the flags say so. 311168404Spjd */ 312168404Spjd if (!(pp->flags & NE2000DVF_ANYFUNC) && 313168404Spjd fcn != PCCARD_FUNCTION_NETWORK) 314168404Spjd return (ENXIO); 315168404Spjd /* 316168404Spjd * Some devices match multiple entries. Report that 317172443Spjd * as a warning to help cull the table 318172443Spjd */ 319168404Spjd pp2 = pp; 320168404Spjd while ((pp2 = (const struct ed_product *)pccard_product_lookup( 321168404Spjd dev, (const struct pccard_product *)(pp2 + 1), 322168404Spjd sizeof(ed_pccard_products[0]), NULL)) != NULL) { 323168404Spjd if (first) { 324168404Spjd device_printf(dev, 325168404Spjd "Warning: card matches multiple entries. Report to imp@freebsd.org\n"); 326168404Spjd ed_pccard_print_entry(pp); 327185029Spjd first = 0; 328168404Spjd } 329168404Spjd ed_pccard_print_entry(pp2); 330168404Spjd } 331168404Spjd 332168404Spjd return (0); 333168404Spjd } 334168404Spjd return (ENXIO); 335168404Spjd} 336185029Spjd 337185029Spjdstatic int 338185029Spjded_pccard_rom_mac(device_t dev, uint8_t *enaddr) 339185029Spjd{ 340197150Spjd struct ed_softc *sc = device_get_softc(dev); 341197150Spjd uint8_t romdata[32], sum; 342197150Spjd int i; 343197150Spjd 344197172Spjd /* 345197150Spjd * Read in the rom data at location 0. Since there are no 346197150Spjd * NE-1000 based PC Card devices, we'll assume we're 16-bit. 347185029Spjd * 348168404Spjd * In researching what format this takes, I've found that the 349168404Spjd * following appears to be true for multiple cards based on 350168404Spjd * observation as well as datasheet digging. 351168404Spjd * 352185029Spjd * Data is stored in some ROM and is copied out 8 bits at a time 353168404Spjd * into 16-bit wide locations. This means that the odd locations 354168404Spjd * of the ROM are not used (and can be either 0 or ff). 355168404Spjd * 356168404Spjd * The contents appears to be as follows: 357168404Spjd * PROM RAM 358168404Spjd * Offset Offset What 359168404Spjd * 0 0 ENETADDR 0 360168404Spjd * 1 2 ENETADDR 1 361168404Spjd * 2 4 ENETADDR 2 362168404Spjd * 3 6 ENETADDR 3 363168404Spjd * 4 8 ENETADDR 4 364168404Spjd * 5 10 ENETADDR 5 365168404Spjd * 6-13 12-26 Reserved (varies by manufacturer) 366168404Spjd * 14 28 0x57 367168404Spjd * 15 30 0x57 368168404Spjd * 369168404Spjd * Some manufacturers have another image of enetaddr from 370168404Spjd * PROM offset 0x10 to 0x15 with 0x42 in 0x1e and 0x1f, but 371168404Spjd * this doesn't appear to be universally documented in the 372168404Spjd * datasheets. Some manufactuers have a card type, card config 373168404Spjd * checksums, etc encoded into PROM offset 6-13, but deciphering it 374168404Spjd * requires more knowledge about the exact underlying chipset than 375168404Spjd * we possess (and maybe can possess). 376168404Spjd */ 377168404Spjd ed_pio_readmem(sc, 0, romdata, 32); 378168404Spjd if (bootverbose) 379185029Spjd device_printf(dev, "ROM DATA: %32D\n", romdata, " "); 380168404Spjd if (romdata[28] != 0x57 || romdata[30] != 0x57) 381168404Spjd return (0); 382168404Spjd for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) 383168404Spjd sum |= romdata[i * 2]; 384168404Spjd if (sum == 0) 385168404Spjd return (0); 386168404Spjd for (i = 0; i < ETHER_ADDR_LEN; i++) 387168404Spjd enaddr[i] = romdata[i * 2]; 388168404Spjd return (1); 389168404Spjd} 390168404Spjd 391168404Spjdstatic int 392168404Spjded_pccard_add_modem(device_t dev) 393168404Spjd{ 394168404Spjd device_printf(dev, "Need to write this code\n"); 395168404Spjd return 0; 396168404Spjd} 397168404Spjd 398168404Spjdstatic int 399168404Spjded_pccard_kick_phy(struct ed_softc *sc) 400168404Spjd{ 401168404Spjd struct mii_softc *miisc; 402168404Spjd struct mii_data *mii; 403168404Spjd 404168404Spjd /* 405168404Spjd * Many of the PHYs that wind up on PC Cards are weird in 406168404Spjd * this way. Generally, we don't need to worry so much about 407168404Spjd * the Isolation protocol since there's only one PHY in 408168404Spjd * these designs, so this workaround is reasonable. 409168404Spjd */ 410168404Spjd mii = device_get_softc(sc->miibus); 411168404Spjd LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 412168404Spjd miisc->mii_flags |= MIIF_FORCEANEG; 413168404Spjd mii_phy_reset(miisc); 414168404Spjd } 415168404Spjd return (mii_mediachg(mii)); 416168404Spjd} 417168404Spjd 418168404Spjdstatic int 419168404Spjded_pccard_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command) 420168404Spjd{ 421168404Spjd struct mii_data *mii; 422168404Spjd 423168404Spjd if (sc->miibus == NULL) 424168404Spjd return (EINVAL); 425168404Spjd mii = device_get_softc(sc->miibus); 426168404Spjd return (ifmedia_ioctl(sc->ifp, ifr, &mii->mii_media, command)); 427168404Spjd} 428168404Spjd 429168404Spjd 430168404Spjdstatic void 431185029Spjded_pccard_mediachg(struct ed_softc *sc) 432168404Spjd{ 433168404Spjd struct mii_data *mii; 434168404Spjd 435168404Spjd if (sc->miibus == NULL) 436168404Spjd return; 437168404Spjd mii = device_get_softc(sc->miibus); 438185029Spjd mii_mediachg(mii); 439168404Spjd} 440168404Spjd 441168404Spjdstatic int 442168404Spjded_pccard_attach(device_t dev) 443168404Spjd{ 444168404Spjd u_char sum; 445168404Spjd u_char enaddr[ETHER_ADDR_LEN]; 446168404Spjd const struct ed_product *pp; 447168404Spjd int error, i, flags, port_rid, modem_rid; 448168404Spjd struct ed_softc *sc = device_get_softc(dev); 449168404Spjd u_long size; 450168404Spjd static uint16_t *intr_vals[] = {NULL, NULL}; 451168404Spjd 452168404Spjd sc->dev = dev; 453168404Spjd if ((pp = (const struct ed_product *) pccard_product_lookup(dev, 454168404Spjd (const struct pccard_product *) ed_pccard_products, 455168404Spjd sizeof(ed_pccard_products[0]), NULL)) == NULL) { 456168404Spjd printf("Can't find\n"); 457185029Spjd return (ENXIO); 458185029Spjd } 459168404Spjd modem_rid = port_rid = -1; 460168404Spjd if (pp->flags & NE2000DVF_MODEM) { 461168404Spjd for (i = 0; i < 4; i++) { 462185029Spjd size = bus_get_resource_count(dev, SYS_RES_IOPORT, i); 463168404Spjd if (size == ED_NOVELL_IO_PORTS) 464168404Spjd port_rid = i; 465168404Spjd else if (size == 8) 466168404Spjd modem_rid = i; 467168404Spjd } 468168404Spjd if (port_rid == -1) { 469168404Spjd device_printf(dev, "Cannot locate my ports!\n"); 470168404Spjd return (ENXIO); 471168404Spjd } 472168404Spjd } else { 473185029Spjd port_rid = 0; 474185029Spjd } 475185029Spjd /* Allocate the port resource during setup. */ 476185029Spjd error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS); 477168404Spjd if (error) { 478168404Spjd printf("alloc_port failed\n"); 479168404Spjd return (error); 480185029Spjd } 481168404Spjd if (rman_get_size(sc->port_res) == ED_NOVELL_IO_PORTS / 2) { 482168404Spjd port_rid++; 483168404Spjd sc->port_res2 = bus_alloc_resource(dev, SYS_RES_IOPORT, 484168404Spjd &port_rid, 0ul, ~0ul, 1, RF_ACTIVE); 485168404Spjd if (sc->port_res2 == NULL || 486168404Spjd rman_get_size(sc->port_res2) != ED_NOVELL_IO_PORTS / 2) { 487168404Spjd error = ENXIO; 488185029Spjd goto bad; 489168404Spjd } 490168404Spjd } 491168404Spjd error = ed_alloc_irq(dev, 0, 0); 492168404Spjd if (error) 493185029Spjd goto bad; 494185029Spjd 495185029Spjd /* 496185029Spjd * Determine which chipset we are. Almost all the PC Card chipsets 497185029Spjd * have the Novel ASIC and NIC offsets. There's 2 known cards that 498185029Spjd * follow the WD80x3 conventions, which are handled as a special case. 499168404Spjd */ 500168404Spjd sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 501185029Spjd sc->nic_offset = ED_NOVELL_NIC_OFFSET; 502185029Spjd error = ENXIO; 503168404Spjd flags = device_get_flags(dev); 504168404Spjd if (error != 0) 505168404Spjd error = ed_pccard_dl100xx(dev, pp); 506185029Spjd if (error != 0) 507168404Spjd error = ed_pccard_ax88x90(dev, pp); 508168404Spjd if (error != 0) 509168404Spjd error = ed_pccard_tc5299j(dev, pp); 510168404Spjd if (error != 0) { 511168404Spjd error = ed_probe_Novell_generic(dev, flags); 512168404Spjd printf("Novell probe generic %d\n", error); 513168404Spjd } 514168404Spjd if (error != 0 && (pp->flags & NE2000DVF_TOSHIBA)) { 515168404Spjd flags |= ED_FLAGS_TOSH_ETHER; 516168404Spjd flags |= ED_FLAGS_PCCARD; 517168404Spjd sc->asic_offset = ED_WD_ASIC_OFFSET; 518168404Spjd sc->nic_offset = ED_WD_NIC_OFFSET; 519168404Spjd error = ed_probe_WD80x3_generic(dev, flags, intr_vals); 520168404Spjd } 521168404Spjd if (error) 522168404Spjd goto bad; 523168404Spjd 524168404Spjd /* 525185029Spjd * There are several ways to get the MAC address for the card. 526168404Spjd * Some of the above probe routines can fill in the enaddr. If 527168404Spjd * not, we run through a number of 'well known' locations: 528168404Spjd * (1) From the PC Card FUNCE 529168404Spjd * (2) From offset 0 in the shared memory 530168404Spjd * (3) From a hinted offset in attribute memory 531168404Spjd * (4) From 0xff0 in attribute memory 532168404Spjd * If we can't get a non-zero MAC address from this list, we fail. 533185029Spjd */ 534185029Spjd for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) 535185029Spjd sum |= sc->enaddr[i]; 536185029Spjd if (sum == 0) { 537185029Spjd pccard_get_ether(dev, enaddr); 538185029Spjd if (bootverbose) 539185029Spjd device_printf(dev, "CIS MAC %6D\n", enaddr, ":"); 540185029Spjd for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) 541185029Spjd sum |= enaddr[i]; 542168404Spjd if (sum == 0 && ed_pccard_rom_mac(dev, enaddr)) { 543168404Spjd if (bootverbose) 544168404Spjd device_printf(dev, "ROM mac %6D\n", enaddr, 545168404Spjd ":"); 546168404Spjd sum++; 547185029Spjd } 548168404Spjd if (sum == 0 && pp->flags & NE2000DVF_ENADDR) { 549168404Spjd for (i = 0; i < ETHER_ADDR_LEN; i++) { 550168404Spjd pccard_attr_read_1(dev, pp->enoff + i * 2, 551168404Spjd enaddr + i); 552168404Spjd sum |= enaddr[i]; 553168404Spjd } 554168404Spjd if (bootverbose) 555185029Spjd device_printf(dev, "Hint %x MAC %6D\n", 556185029Spjd pp->enoff, enaddr, ":"); 557185029Spjd } 558185029Spjd if (sum == 0) { 559185029Spjd for (i = 0; i < ETHER_ADDR_LEN; i++) { 560185029Spjd pccard_attr_read_1(dev, ED_DEFAULT_MAC_OFFSET + 561185029Spjd i * 2, enaddr + i); 562168404Spjd sum |= enaddr[i]; 563168404Spjd } 564185029Spjd if (bootverbose) 565168404Spjd device_printf(dev, "Fallback MAC %6D\n", 566168404Spjd enaddr, ":"); 567168404Spjd } 568168404Spjd if (sum == 0) { 569168404Spjd device_printf(dev, "Cannot extract MAC address.\n"); 570168404Spjd ed_release_resources(dev); 571168404Spjd return (ENXIO); 572168404Spjd } 573168404Spjd bcopy(enaddr, sc->enaddr, ETHER_ADDR_LEN); 574168404Spjd } 575168404Spjd 576168404Spjd error = ed_attach(dev); 577168404Spjd if (error) 578168404Spjd goto bad; 579168404Spjd if (sc->chip_type == ED_CHIP_TYPE_DL10019 || 580168404Spjd sc->chip_type == ED_CHIP_TYPE_DL10022) { 581168404Spjd /* Probe for an MII bus, but ignore errors. */ 582168404Spjd ed_pccard_dl100xx_mii_reset(sc); 583168404Spjd (void)mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd, 584168404Spjd ed_ifmedia_sts); 585168404Spjd } else if (sc->chip_type == ED_CHIP_TYPE_AX88190 || 586168404Spjd sc->chip_type == ED_CHIP_TYPE_AX88790) { 587168404Spjd if ((error = mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd, 588168404Spjd ed_ifmedia_sts)) != 0) { 589168404Spjd device_printf(dev, "Missing mii %d!\n", error); 590168404Spjd goto bad; 591168404Spjd } 592168404Spjd 593168404Spjd } else if (sc->chip_type == ED_CHIP_TYPE_TC5299J) { 594168404Spjd if ((error = mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd, 595168404Spjd ed_ifmedia_sts)) != 0) { 596168404Spjd device_printf(dev, "Missing mii!\n"); 597168404Spjd goto bad; 598168404Spjd } 599168404Spjd 600168404Spjd } 601168404Spjd if (sc->miibus != NULL) { 602185029Spjd sc->sc_tick = ed_pccard_tick; 603168404Spjd sc->sc_mediachg = ed_pccard_mediachg; 604168404Spjd sc->sc_media_ioctl = ed_pccard_media_ioctl; 605168404Spjd ed_pccard_kick_phy(sc); 606168404Spjd } else { 607168404Spjd ed_gen_ifmedia_init(sc); 608168404Spjd } 609168404Spjd if (modem_rid != -1) 610168404Spjd ed_pccard_add_modem(dev); 611168404Spjd 612168404Spjd error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, 613168404Spjd NULL, edintr, sc, &sc->irq_handle); 614168404Spjd if (error) { 615185029Spjd device_printf(dev, "setup intr failed %d \n", error); 616185029Spjd goto bad; 617168404Spjd } 618185029Spjd 619185029Spjd return (0); 620185029Spjdbad: 621185029Spjd ed_detach(dev); 622185029Spjd return (error); 623185029Spjd} 624168404Spjd 625185029Spjd/* 626185029Spjd * Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100 627185029Spjd * and compatible cards (DL10019C Ethernet controller). 628185029Spjd */ 629185029Spjdstatic int 630185029Spjded_pccard_dl100xx(device_t dev, const struct ed_product *pp) 631185029Spjd{ 632185029Spjd struct ed_softc *sc = device_get_softc(dev); 633185029Spjd u_char sum; 634185029Spjd uint8_t id; 635185029Spjd u_int memsize; 636185029Spjd int i, error; 637185029Spjd 638185029Spjd if (!(pp->flags & NE2000DVF_DL100XX)) 639185029Spjd return (ENXIO); 640185029Spjd if (bootverbose) 641185029Spjd device_printf(dev, "Trying DL100xx probing\n"); 642185029Spjd error = ed_probe_Novell_generic(dev, device_get_flags(dev)); 643185029Spjd if (bootverbose && error) 644185029Spjd device_printf(dev, "Novell generic probe failed: %d\n", error); 645185029Spjd if (error != 0) 646185029Spjd return (error); 647185029Spjd 648185029Spjd /* 649185029Spjd * Linksys registers(offset from ASIC base) 650185029Spjd * 651185029Spjd * 0x04-0x09 : Physical Address Register 0-5 (PAR0-PAR5) 652185029Spjd * 0x0A : Card ID Register (CIR) 653185029Spjd * 0x0B : Check Sum Register (SR) 654185029Spjd */ 655185029Spjd for (sum = 0, i = 0x04; i < 0x0c; i++) 656185029Spjd sum += ed_asic_inb(sc, i); 657185029Spjd if (sum != 0xff) { 658185029Spjd if (bootverbose) 659168404Spjd device_printf(dev, "Bad checksum %#x\n", sum); 660168404Spjd return (ENXIO); /* invalid DL10019C */ 661168404Spjd } 662168404Spjd if (bootverbose) 663185029Spjd device_printf(dev, "CIR is %d\n", ed_asic_inb(sc, 0xa)); 664185029Spjd for (i = 0; i < ETHER_ADDR_LEN; i++) 665185029Spjd sc->enaddr[i] = ed_asic_inb(sc, 0x04 + i); 666185029Spjd ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); 667185029Spjd id = ed_asic_inb(sc, 0xf); 668185029Spjd sc->isa16bit = 1; 669185029Spjd /* 670185029Spjd * Hard code values based on the datasheet. We're NE-2000 compatible 671185029Spjd * NIC with 24kb of packet memory starting at 24k offset. These 672185029Spjd * cards also work with 16k at 16k, but don't work with 24k at 16k 673168404Spjd * or 32k at 16k. 674168404Spjd */ 675168404Spjd sc->type = ED_TYPE_NE2000; 676185029Spjd sc->mem_start = 24 * 1024; 677168404Spjd memsize = sc->mem_size = 24 * 1024; 678185029Spjd sc->mem_end = sc->mem_start + memsize; 679168404Spjd sc->tx_page_start = memsize / ED_PAGE_SIZE; 680168404Spjd sc->txb_cnt = 3; 681185029Spjd sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE; 682185029Spjd sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE; 683185029Spjd 684185029Spjd sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; 685185029Spjd 686185029Spjd ed_nic_outb(sc, ED_P0_PSTART, sc->mem_start / ED_PAGE_SIZE); 687168404Spjd ed_nic_outb(sc, ED_P0_PSTOP, sc->mem_end / ED_PAGE_SIZE); 688185029Spjd sc->vendor = ED_VENDOR_NOVELL; 689185029Spjd sc->chip_type = (id & 0x90) == 0x90 ? 690168404Spjd ED_CHIP_TYPE_DL10022 : ED_CHIP_TYPE_DL10019; 691185029Spjd sc->type_str = ((id & 0x90) == 0x90) ? "DL10022" : "DL10019"; 692168404Spjd sc->mii_readbits = ed_pccard_dl100xx_mii_readbits; 693168404Spjd sc->mii_writebits = ed_pccard_dl100xx_mii_writebits; 694168404Spjd return (0); 695185029Spjd} 696168404Spjd 697185029Spjd/* MII bit-twiddling routines for cards using Dlink chipset */ 698168404Spjd#define DL100XX_MIISET(sc, x) ed_asic_outb(sc, ED_DL100XX_MIIBUS, \ 699185029Spjd ed_asic_inb(sc, ED_DL100XX_MIIBUS) | (x)) 700168404Spjd#define DL100XX_MIICLR(sc, x) ed_asic_outb(sc, ED_DL100XX_MIIBUS, \ 701185029Spjd ed_asic_inb(sc, ED_DL100XX_MIIBUS) & ~(x)) 702185029Spjd 703185029Spjdstatic void 704185029Spjded_pccard_dl100xx_mii_reset(struct ed_softc *sc) 705185029Spjd{ 706185029Spjd if (sc->chip_type != ED_CHIP_TYPE_DL10022) 707185029Spjd return; 708168404Spjd 709168404Spjd ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL10022_MII_RESET2); 710185029Spjd DELAY(10); 711168404Spjd ed_asic_outb(sc, ED_DL100XX_MIIBUS, 712168404Spjd ED_DL10022_MII_RESET2 | ED_DL10022_MII_RESET1); 713168404Spjd DELAY(10); 714168404Spjd ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL10022_MII_RESET2); 715168404Spjd DELAY(10); 716168404Spjd ed_asic_outb(sc, ED_DL100XX_MIIBUS, 717168404Spjd ED_DL10022_MII_RESET2 | ED_DL10022_MII_RESET1); 718168404Spjd DELAY(10); 719168404Spjd ed_asic_outb(sc, ED_DL100XX_MIIBUS, 0); 720168404Spjd} 721168404Spjd 722185029Spjdstatic void 723168404Spjded_pccard_dl100xx_mii_writebits(struct ed_softc *sc, u_int val, int nbits) 724185029Spjd{ 725168404Spjd int i; 726168404Spjd 727185029Spjd DL100XX_MIISET(sc, ED_DL100XX_MII_DIROUT); 728185029Spjd for (i = nbits - 1; i >= 0; i--) { 729185029Spjd if ((val >> i) & 1) 730185029Spjd DL100XX_MIISET(sc, ED_DL100XX_MII_DATAOUT); 731185029Spjd else 732168404Spjd DL100XX_MIICLR(sc, ED_DL100XX_MII_DATAOUT); 733185029Spjd DL100XX_MIISET(sc, ED_DL100XX_MII_CLK); 734168404Spjd DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK); 735185029Spjd } 736168404Spjd} 737168404Spjd 738168404Spjdstatic u_int 739168404Spjded_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits) 740168404Spjd{ 741168404Spjd int i; 742168404Spjd u_int val = 0; 743168404Spjd 744168404Spjd DL100XX_MIICLR(sc, ED_DL100XX_MII_DIROUT); 745185029Spjd for (i = nbits - 1; i >= 0; i--) { 746168404Spjd DL100XX_MIISET(sc, ED_DL100XX_MII_CLK); 747168404Spjd val <<= 1; 748168404Spjd if (ed_asic_inb(sc, ED_DL100XX_MIIBUS) & ED_DL100XX_MII_DATAIN) 749168404Spjd val++; 750168404Spjd DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK); 751185029Spjd } 752168404Spjd return val; 753168404Spjd} 754185029Spjd 755168404Spjdstatic void 756168404Spjded_pccard_ax88x90_reset(struct ed_softc *sc) 757168404Spjd{ 758185029Spjd int i; 759185029Spjd 760168404Spjd /* Reset Card */ 761168404Spjd ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0); 762168404Spjd ed_asic_outb(sc, ED_NOVELL_RESET, ed_asic_inb(sc, ED_NOVELL_RESET)); 763168404Spjd 764168404Spjd /* Wait for the RST bit to assert, but cap it at 10ms */ 765185029Spjd for (i = 10000; !(ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST) && i > 0; 766168404Spjd i--) 767168404Spjd continue; 768168404Spjd ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RST); /* ACK INTR */ 769185029Spjd if (i == 0) 770168404Spjd device_printf(sc->dev, "Reset didn't finish\n"); 771168404Spjd} 772168404Spjd 773168404Spjd/* 774168404Spjd * Probe and vendor-specific initialization routine for ax88x90 boards 775168404Spjd */ 776168404Spjdstatic int 777168404Spjded_probe_ax88x90_generic(device_t dev, int flags) 778168404Spjd{ 779185029Spjd struct ed_softc *sc = device_get_softc(dev); 780168404Spjd u_int memsize; 781168404Spjd static char test_pattern[32] = "THIS is A memory TEST pattern"; 782168404Spjd char test_buffer[32]; 783168404Spjd 784168404Spjd ed_pccard_ax88x90_reset(sc); 785197150Spjd DELAY(10*1000); 786168404Spjd 787168404Spjd /* Make sure that we really have an 8390 based board */ 788168404Spjd if (!ed_probe_generic8390(sc)) 789168404Spjd return (ENXIO); 790168404Spjd 791168404Spjd sc->vendor = ED_VENDOR_NOVELL; 792168404Spjd sc->mem_shared = 0; 793168404Spjd sc->cr_proto = ED_CR_RD2; 794168404Spjd 795168404Spjd /* 796168404Spjd * This prevents packets from being stored in the NIC memory when the 797168404Spjd * readmem routine turns on the start bit in the CR. We write some 798168404Spjd * bytes in word mode and verify we can read them back. If we can't 799168404Spjd * then we don't have an AX88x90 chip here. 800168404Spjd */ 801168404Spjd sc->isa16bit = 1; 802168404Spjd ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON); 803168404Spjd ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); 804168404Spjd ed_pio_writemem(sc, test_pattern, 16384, sizeof(test_pattern)); 805185029Spjd ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern)); 806168404Spjd if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) != 0) 807185029Spjd return (ENXIO); 808168404Spjd 809168404Spjd /* 810185029Spjd * Hard code values based on the datasheet. We're NE-2000 compatible 811185029Spjd * NIC with 16kb of packet memory starting at 16k offset. 812185029Spjd */ 813185029Spjd sc->type = ED_TYPE_NE2000; 814185029Spjd memsize = sc->mem_size = 16*1024; 815168404Spjd sc->mem_start = 16 * 1024; 816185029Spjd if (ed_asic_inb(sc, ED_AX88X90_TEST) != 0) 817185029Spjd sc->chip_type = ED_CHIP_TYPE_AX88790; 818168404Spjd else { 819168404Spjd sc->chip_type = ED_CHIP_TYPE_AX88190; 820168404Spjd /* 821168404Spjd * The AX88190 (not A) has external 64k SRAM. Probe for this 822185029Spjd * here. Most of the cards I have either use the AX88190A 823185029Spjd * part, or have only 32k SRAM for some reason, so I don't 824185029Spjd * know if this works or not. 825185029Spjd */ 826168404Spjd ed_pio_writemem(sc, test_pattern, 32768, sizeof(test_pattern)); 827185029Spjd ed_pio_readmem(sc, 32768, test_buffer, sizeof(test_pattern)); 828168404Spjd if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) { 829168404Spjd sc->mem_start = 2*1024; 830168404Spjd memsize = sc->mem_size = 62 * 1024; 831185029Spjd } 832168404Spjd } 833168404Spjd sc->mem_end = sc->mem_start + memsize; 834185029Spjd sc->tx_page_start = memsize / ED_PAGE_SIZE; 835185029Spjd if (sc->mem_size > 16 * 1024) 836185029Spjd sc->txb_cnt = 3; 837185029Spjd else 838168404Spjd sc->txb_cnt = 2; 839168404Spjd sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE; 840168404Spjd sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE; 841168404Spjd 842168404Spjd sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; 843168404Spjd 844168404Spjd ed_nic_outb(sc, ED_P0_PSTART, sc->mem_start / ED_PAGE_SIZE); 845168404Spjd ed_nic_outb(sc, ED_P0_PSTOP, sc->mem_end / ED_PAGE_SIZE); 846168404Spjd 847168404Spjd /* Get the mac before we go -- It's just at 0x400 in "SRAM" */ 848185029Spjd ed_pio_readmem(sc, 0x400, sc->enaddr, ETHER_ADDR_LEN); 849168404Spjd 850168404Spjd /* clear any pending interrupts that might have occurred above */ 851185029Spjd ed_nic_outb(sc, ED_P0_ISR, 0xff); 852168404Spjd sc->sc_write_mbufs = ed_pio_write_mbufs; 853168404Spjd return (0); 854185029Spjd} 855185029Spjd 856185029Spjdstatic int 857185029Spjded_pccard_ax88x90_check_mii(device_t dev, struct ed_softc *sc) 858185029Spjd{ 859168404Spjd int i, id; 860185029Spjd 861185029Spjd /* 862168404Spjd * All AX88x90 devices have MII and a PHY, so we use this to weed out 863168404Spjd * chips that would otherwise make it through the tests we have after 864168404Spjd * this point. 865168404Spjd */ 866185029Spjd for (i = 0; i < 32; i++) { 867185029Spjd id = ed_miibus_readreg(dev, i, MII_BMSR); 868185029Spjd if (id != 0 && id != 0xffff) 869185029Spjd break; 870185029Spjd } 871168404Spjd /* 872185029Spjd * Found one, we're good. 873168404Spjd */ 874168404Spjd if (i != 32) 875168404Spjd return (0); 876168404Spjd /* 877168404Spjd * Didn't find anything, so try to power up and try again. The PHY 878185029Spjd * may be not responding because we're in power down mode. 879168404Spjd */ 880168404Spjd if (sc->chip_type == ED_CHIP_TYPE_AX88190) 881185029Spjd return (ENXIO); 882185029Spjd pccard_ccr_write_1(dev, PCCARD_CCR_STATUS, PCCARD_CCR_STATUS_PWRDWN); 883185029Spjd for (i = 0; i < 32; i++) { 884185029Spjd id = ed_miibus_readreg(dev, i, MII_BMSR); 885168404Spjd if (id != 0 && id != 0xffff) 886168404Spjd break; 887168404Spjd } 888168404Spjd /* 889168404Spjd * Still no joy? We're AFU, punt. 890168404Spjd */ 891185029Spjd if (i == 32) 892185029Spjd return (ENXIO); 893185029Spjd return (0); 894185029Spjd 895185029Spjd} 896185029Spjd 897185029Spjd/* 898168404Spjd * Special setup for AX88[17]90 899168404Spjd */ 900168404Spjdstatic int 901185029Spjded_pccard_ax88x90(device_t dev, const struct ed_product *pp) 902168404Spjd{ 903185029Spjd int error; 904168404Spjd int iobase; 905168404Spjd struct ed_softc *sc = device_get_softc(dev); 906185029Spjd 907185029Spjd if (!(pp->flags & NE2000DVF_AX88X90)) 908185029Spjd return (ENXIO); 909185029Spjd 910185029Spjd if (bootverbose) 911168404Spjd device_printf(dev, "Checking AX88x90\n"); 912185029Spjd 913168404Spjd /* 914185029Spjd * Set the IOBASE Register. The AX88x90 cards are potentially 915168404Spjd * multifunction cards, and thus requires a slight workaround. 916168404Spjd * We write the address the card is at, on the off chance that this 917168404Spjd * card is not MFC. 918168404Spjd * XXX I'm not sure that this is still needed... 919168404Spjd */ 920168404Spjd iobase = rman_get_start(sc->port_res); 921168404Spjd pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE0, iobase & 0xff); 922168404Spjd pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE1, (iobase >> 8) & 0xff); 923168404Spjd 924185029Spjd sc->mii_readbits = ed_pccard_ax88x90_mii_readbits; 925168404Spjd sc->mii_writebits = ed_pccard_ax88x90_mii_writebits; 926168404Spjd error = ed_probe_ax88x90_generic(dev, device_get_flags(dev)); 927168404Spjd if (error) { 928168404Spjd if (bootverbose) 929168404Spjd device_printf(dev, "probe ax88x90 failed %d\n", 930168404Spjd error); 931168404Spjd goto fail; 932168404Spjd } 933168404Spjd error = ed_pccard_ax88x90_check_mii(dev, sc); 934168404Spjd if (error) 935168404Spjd goto fail; 936168404Spjd sc->vendor = ED_VENDOR_NOVELL; 937168404Spjd sc->type = ED_TYPE_NE2000; 938168404Spjd if (sc->chip_type == ED_CHIP_TYPE_AX88190) 939168404Spjd sc->type_str = "AX88190"; 940168404Spjd else 941168404Spjd sc->type_str = "AX88790"; 942168404Spjd return (0); 943168404Spjdfail:; 944168404Spjd sc->mii_readbits = 0; 945168404Spjd sc->mii_writebits = 0; 946168404Spjd return (error); 947168404Spjd} 948168404Spjd 949168404Spjdstatic void 950168404Spjded_pccard_ax88x90_mii_writebits(struct ed_softc *sc, u_int val, int nbits) 951168404Spjd{ 952168404Spjd int i, data; 953168404Spjd 954168404Spjd for (i = nbits - 1; i >= 0; i--) { 955168404Spjd data = (val >> i) & 1 ? ED_AX88X90_MII_DATAOUT : 0; 956168404Spjd ed_asic_outb(sc, ED_AX88X90_MIIBUS, data); 957168404Spjd ed_asic_outb(sc, ED_AX88X90_MIIBUS, data | ED_AX88X90_MII_CLK); 958168404Spjd } 959168404Spjd} 960168404Spjd 961168404Spjdstatic u_int 962168404Spjded_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits) 963168404Spjd{ 964168404Spjd int i; 965168404Spjd u_int val = 0; 966168404Spjd uint8_t mdio; 967168404Spjd 968168404Spjd mdio = ED_AX88X90_MII_DIRIN; 969168404Spjd for (i = nbits - 1; i >= 0; i--) { 970168404Spjd ed_asic_outb(sc, ED_AX88X90_MIIBUS, mdio); 971168404Spjd val <<= 1; 972168404Spjd if (ed_asic_inb(sc, ED_AX88X90_MIIBUS) & ED_AX88X90_MII_DATAIN) 973168404Spjd val++; 974168404Spjd ed_asic_outb(sc, ED_AX88X90_MIIBUS, mdio | ED_AX88X90_MII_CLK); 975168404Spjd } 976168404Spjd return val; 977168404Spjd} 978168404Spjd 979168404Spjd/* 980168404Spjd * Special setup for TC5299J 981168404Spjd */ 982168404Spjdstatic int 983168404Spjded_pccard_tc5299j(device_t dev, const struct ed_product *pp) 984168404Spjd{ 985168404Spjd int error, i, id; 986168404Spjd char *ts; 987168404Spjd struct ed_softc *sc = device_get_softc(dev); 988168404Spjd 989168404Spjd if (!(pp->flags & NE2000DVF_TC5299J)) 990168404Spjd return (ENXIO); 991168404Spjd 992168404Spjd if (bootverbose) 993168404Spjd device_printf(dev, "Checking Tc5299j\n"); 994168404Spjd 995168404Spjd error = ed_probe_Novell_generic(dev, device_get_flags(dev)); 996168404Spjd if (bootverbose) 997168404Spjd device_printf(dev, "probe novel returns %d\n", error); 998168404Spjd if (error != 0) 999168404Spjd return (error); 1000168404Spjd 1001168404Spjd /* 1002168404Spjd * Check to see if we have a MII PHY ID at any address. All TC5299J 1003168404Spjd * devices have MII and a PHY, so we use this to weed out chips that 1004168404Spjd * would otherwise make it through the tests we have after this point. 1005185029Spjd */ 1006168404Spjd sc->mii_readbits = ed_pccard_tc5299j_mii_readbits; 1007168404Spjd sc->mii_writebits = ed_pccard_tc5299j_mii_writebits; 1008168404Spjd for (i = 0; i < 32; i++) { 1009168404Spjd id = ed_miibus_readreg(dev, i, MII_PHYIDR1); 1010168404Spjd if (id != 0 && id != 0xffff) 1011168404Spjd break; 1012168404Spjd } 1013168404Spjd if (i == 32) { 1014168404Spjd sc->mii_readbits = 0; 1015168404Spjd sc->mii_writebits = 0; 1016168404Spjd return (ENXIO); 1017168404Spjd } 1018168404Spjd ts = "TC5299J"; 1019168404Spjd if (ed_pccard_rom_mac(dev, sc->enaddr) == 0) { 1020168404Spjd sc->mii_readbits = 0; 1021168404Spjd sc->mii_writebits = 0; 1022168404Spjd return (ENXIO); 1023168404Spjd } 1024168404Spjd sc->vendor = ED_VENDOR_NOVELL; 1025185029Spjd sc->type = ED_TYPE_NE2000; 1026185029Spjd sc->chip_type = ED_CHIP_TYPE_TC5299J; 1027185029Spjd sc->type_str = ts; 1028185029Spjd return (0); 1029185029Spjd} 1030185029Spjd 1031168404Spjdstatic void 1032168404Spjded_pccard_tc5299j_mii_writebits(struct ed_softc *sc, u_int val, int nbits) 1033168404Spjd{ 1034168404Spjd int i; 1035168404Spjd uint8_t cr, data; 1036168404Spjd 1037168404Spjd /* Select page 3 */ 1038168404Spjd cr = ed_nic_inb(sc, ED_P0_CR); 1039168404Spjd ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3); 1040168404Spjd 1041168404Spjd for (i = nbits - 1; i >= 0; i--) { 1042168404Spjd data = (val >> i) & 1 ? ED_TC5299J_MII_DATAOUT : 0; 1043168404Spjd ed_nic_outb(sc, ED_TC5299J_MIIBUS, data); 1044168404Spjd ed_nic_outb(sc, ED_TC5299J_MIIBUS, data | ED_TC5299J_MII_CLK); 1045168404Spjd } 1046168404Spjd ed_nic_outb(sc, ED_TC5299J_MIIBUS, 0); 1047168404Spjd 1048168404Spjd /* Restore prior page */ 1049168404Spjd ed_nic_outb(sc, ED_P0_CR, cr); 1050168404Spjd} 1051168404Spjd 1052168404Spjdstatic u_int 1053168404Spjded_pccard_tc5299j_mii_readbits(struct ed_softc *sc, int nbits) 1054168404Spjd{ 1055168404Spjd int i; 1056168404Spjd u_int val = 0; 1057168404Spjd uint8_t cr; 1058168404Spjd 1059168404Spjd /* Select page 3 */ 1060168404Spjd cr = ed_nic_inb(sc, ED_P0_CR); 1061168404Spjd ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3); 1062168404Spjd 1063168404Spjd ed_asic_outb(sc, ED_TC5299J_MIIBUS, ED_TC5299J_MII_DIROUT); 1064168404Spjd for (i = nbits - 1; i >= 0; i--) { 1065168404Spjd ed_nic_outb(sc, ED_TC5299J_MIIBUS, 1066185029Spjd ED_TC5299J_MII_CLK | ED_TC5299J_MII_DIROUT); 1067168404Spjd val <<= 1; 1068168404Spjd if (ed_nic_inb(sc, ED_TC5299J_MIIBUS) & ED_TC5299J_MII_DATAIN) 1069168404Spjd val++; 1070168404Spjd ed_nic_outb(sc, ED_TC5299J_MIIBUS, ED_TC5299J_MII_DIROUT); 1071168404Spjd } 1072168404Spjd 1073168404Spjd /* Restore prior page */ 1074168404Spjd ed_nic_outb(sc, ED_P0_CR, cr); 1075168404Spjd return val; 1076168404Spjd} 1077168404Spjd 1078168404Spjd/* 1079168404Spjd * MII bus support routines. 1080168404Spjd */ 1081168404Spjdstatic int 1082209962Smmed_miibus_readreg(device_t dev, int phy, int reg) 1083209962Smm{ 1084209962Smm struct ed_softc *sc; 1085209962Smm int failed, val; 1086209962Smm 1087209962Smm sc = device_get_softc(dev); 1088209962Smm /* 1089209962Smm * The AX88790 has an interesting quirk. It has an internal phy that 1090209962Smm * needs a special bit set to access, but can also have additional 1091209962Smm * external PHYs set for things like HomeNET media. When accessing 1092209962Smm * the internal PHY, a bit has to be set, when accessing the external 1093209962Smm * PHYs, it must be clear. See Errata 1, page 51, in the AX88790 1094209962Smm * datasheet for more details. 1095209962Smm * 1096209962Smm * Also, PHYs above 16 appear to be phantoms on some cards, but not 1097209962Smm * others. Registers read for this are often the same as prior values 1098209962Smm * read. Filter all register requests to 17-31. 1099209962Smm * 1100209962Smm * I can't explain it, since I don't have the DL100xx data sheets, but 1101209962Smm * the DL100xx chips do 13-bits before the 'ACK' but, but the AX88x90 1102209962Smm * chips have 14. The linux pcnet and axnet drivers confirm this. 1103209962Smm */ 1104209962Smm if (sc->chip_type == ED_CHIP_TYPE_AX88790) { 1105209962Smm if (phy > 0x10) 1106209962Smm return (0); 1107209962Smm if (phy == 0x10) 1108209962Smm ed_asic_outb(sc, ED_AX88X90_GPIO, 1109209962Smm ED_AX88X90_GPIO_INT_PHY); 1110209962Smm else 1111209962Smm ed_asic_outb(sc, ED_AX88X90_GPIO, 0); 1112209962Smm } 1113209962Smm 1114209962Smm (*sc->mii_writebits)(sc, 0xffffffff, 32); 1115209962Smm (*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS); 1116209962Smm (*sc->mii_writebits)(sc, ED_MII_READOP, ED_MII_OP_BITS); 1117209962Smm (*sc->mii_writebits)(sc, phy, ED_MII_PHY_BITS); 1118209962Smm (*sc->mii_writebits)(sc, reg, ED_MII_REG_BITS); 1119209962Smm if (sc->chip_type == ED_CHIP_TYPE_AX88790 || 1120209962Smm sc->chip_type == ED_CHIP_TYPE_AX88190) 1121209962Smm (*sc->mii_readbits)(sc, ED_MII_ACK_BITS); 1122209962Smm failed = (*sc->mii_readbits)(sc, ED_MII_ACK_BITS); 1123209962Smm val = (*sc->mii_readbits)(sc, ED_MII_DATA_BITS); 1124209962Smm (*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS); 1125209962Smm/* printf("Reading phy %d reg %#x returning %#x (valid %d)\n", phy, reg, val, !failed); */ 1126209962Smm return (failed ? 0 : val); 1127209962Smm} 1128209962Smm 1129209962Smmstatic int 1130209962Smmed_miibus_writereg(device_t dev, int phy, int reg, int data) 1131209962Smm{ 1132209962Smm struct ed_softc *sc; 1133209962Smm 1134209962Smm/* printf("Writing phy %d reg %#x data %#x\n", phy, reg, data); */ 1135209962Smm sc = device_get_softc(dev); 1136209962Smm /* See ed_miibus_readreg for details */ 1137209962Smm if (sc->chip_type == ED_CHIP_TYPE_AX88790) { 1138209962Smm if (phy > 0x10) 1139209962Smm return (0); 1140209962Smm if (phy == 0x10) 1141209962Smm ed_asic_outb(sc, ED_AX88X90_GPIO, 1142209962Smm ED_AX88X90_GPIO_INT_PHY); 1143209962Smm else 1144209962Smm ed_asic_outb(sc, ED_AX88X90_GPIO, 0); 1145209962Smm } 1146209962Smm (*sc->mii_writebits)(sc, 0xffffffff, 32); 1147209962Smm (*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS); 1148209962Smm (*sc->mii_writebits)(sc, ED_MII_WRITEOP, ED_MII_OP_BITS); 1149209962Smm (*sc->mii_writebits)(sc, phy, ED_MII_PHY_BITS); 1150209962Smm (*sc->mii_writebits)(sc, reg, ED_MII_REG_BITS); 1151209962Smm (*sc->mii_writebits)(sc, ED_MII_TURNAROUND, ED_MII_TURNAROUND_BITS); 1152209962Smm (*sc->mii_writebits)(sc, data, ED_MII_DATA_BITS); 1153209962Smm (*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS); 1154209962Smm return (0); 1155209962Smm} 1156209962Smm 1157209962Smmstatic int 1158ed_ifmedia_upd(struct ifnet *ifp) 1159{ 1160 struct ed_softc *sc; 1161 int error; 1162 1163 sc = ifp->if_softc; 1164 if (sc->miibus == NULL) 1165 return (ENXIO); 1166 ED_LOCK(sc); 1167 error = ed_pccard_kick_phy(sc); 1168 ED_UNLOCK(sc); 1169 return (error); 1170} 1171 1172static void 1173ed_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1174{ 1175 struct ed_softc *sc; 1176 struct mii_data *mii; 1177 1178 sc = ifp->if_softc; 1179 if (sc->miibus == NULL) 1180 return; 1181 1182 mii = device_get_softc(sc->miibus); 1183 mii_pollstat(mii); 1184 ifmr->ifm_active = mii->mii_media_active; 1185 ifmr->ifm_status = mii->mii_media_status; 1186} 1187 1188static void 1189ed_child_detached(device_t dev, device_t child) 1190{ 1191 struct ed_softc *sc; 1192 1193 sc = device_get_softc(dev); 1194 if (child == sc->miibus) 1195 sc->miibus = NULL; 1196} 1197 1198static void 1199ed_pccard_tick(struct ed_softc *sc) 1200{ 1201 struct mii_data *mii; 1202 int media = 0; 1203 1204 ED_ASSERT_LOCKED(sc); 1205 if (sc->miibus != NULL) { 1206 mii = device_get_softc(sc->miibus); 1207 media = mii->mii_media_status; 1208 mii_tick(mii); 1209 if (mii->mii_media_status & IFM_ACTIVE && 1210 media != mii->mii_media_status) { 1211 if (sc->chip_type == ED_CHIP_TYPE_DL10022) { 1212 ed_asic_outb(sc, ED_DL10022_DIAG, 1213 (mii->mii_media_active & IFM_FDX) ? 1214 ED_DL10022_COLLISON_DIS : 0); 1215#ifdef notyet 1216 } else if (sc->chip_type == ED_CHIP_TYPE_DL10019) { 1217 write_asic(sc, ED_DL10019_MAGIC, 1218 (mii->mii_media_active & IFM_FDX) ? 1219 DL19FDUPLX : 0); 1220#endif 1221 } 1222 } 1223 1224 } 1225} 1226 1227static device_method_t ed_pccard_methods[] = { 1228 /* Device interface */ 1229 DEVMETHOD(device_probe, ed_pccard_probe), 1230 DEVMETHOD(device_attach, ed_pccard_attach), 1231 DEVMETHOD(device_detach, ed_detach), 1232 1233 /* Bus interface */ 1234 DEVMETHOD(bus_child_detached, ed_child_detached), 1235 1236 /* MII interface */ 1237 DEVMETHOD(miibus_readreg, ed_miibus_readreg), 1238 DEVMETHOD(miibus_writereg, ed_miibus_writereg), 1239 1240 { 0, 0 } 1241}; 1242 1243static driver_t ed_pccard_driver = { 1244 "ed", 1245 ed_pccard_methods, 1246 sizeof(struct ed_softc) 1247}; 1248 1249DRIVER_MODULE(ed, pccard, ed_pccard_driver, ed_devclass, 0, 0); 1250DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0); 1251MODULE_DEPEND(ed, miibus, 1, 1, 1); 1252MODULE_DEPEND(ed, ether, 1, 1, 1); 1253