1139749Simp/*- 265832Snyan * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 365832Snyan * 465832Snyan * This software may be used, modified, copied, distributed, and sold, in 565832Snyan * both source and binary form provided that the above copyright, these 665832Snyan * terms and the following disclaimer are retained. The name of the author 765832Snyan * and/or the contributor may not be used to endorse or promote products 865832Snyan * derived from this software without specific prior written permission. 965832Snyan * 1065832Snyan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND 1165832Snyan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1265832Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1365832Snyan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE 1465832Snyan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1565832Snyan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1665832Snyan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION. 1765832Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1865832Snyan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1965832Snyan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2065832Snyan * SUCH DAMAGE. 2165832Snyan * 2265832Snyan */ 2365832Snyan 24119418Sobrien#include <sys/cdefs.h> 25119418Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/dev/fe/if_fe_pccard.c 199798 2009-11-25 13:31:17Z rwatson $"); 26119418Sobrien 2765832Snyan#include <sys/param.h> 2865832Snyan#include <sys/kernel.h> 2965832Snyan#include <sys/socket.h> 3067158Sphk#include <sys/systm.h> 3165832Snyan#include <sys/module.h> 3265832Snyan 3365832Snyan#include <sys/bus.h> 3465832Snyan#include <machine/bus.h> 35140543Simp#include <sys/rman.h> 3665832Snyan 3765832Snyan#include <net/ethernet.h> 3865832Snyan#include <net/if.h> 3965832Snyan#include <net/if_mib.h> 4065832Snyan#include <net/if_media.h> 4165832Snyan 4265832Snyan#include <netinet/in.h> 4365832Snyan#include <netinet/if_ether.h> 4465832Snyan 45142135Simp#include <dev/fe/mb86960.h> 4665832Snyan#include <dev/fe/if_fereg.h> 4765832Snyan#include <dev/fe/if_fevar.h> 4865832Snyan 4965832Snyan#include <dev/pccard/pccardvar.h> 50140528Simp#include <dev/pccard/pccard_cis.h> 51129764Simp 52129764Simp#include "card_if.h" 53129740Simp#include "pccarddevs.h" 5465832Snyan 5565832Snyan/* 56150458Simp * PC Card (PCMCIA) specific code. 5765832Snyan */ 5865832Snyanstatic int fe_pccard_probe(device_t); 5965832Snyanstatic int fe_pccard_attach(device_t); 6065832Snyanstatic int fe_pccard_detach(device_t); 6165832Snyan 6282778Sshibastatic const struct fe_pccard_product { 63189728Simp struct pccard_product mpp_product; 64140041Simp int mpp_flags; 65189843Simp int mpp_cfe; 66140543Simp#define MPP_MBH10302 1 67151638Simp#define MPP_ANYFUNC 2 68189843Simp#define MPP_SKIP_TO_CFE 4 6982778Sshiba} fe_pccard_products[] = { 70140041Simp /* These need to be first */ 71147580Simp { PCMCIA_CARD(FUJITSU2, FMV_J181), MPP_MBH10302 }, 72147580Simp { PCMCIA_CARD(FUJITSU2, FMV_J182), 0 }, 73147580Simp { PCMCIA_CARD(FUJITSU2, FMV_J182A), 0 }, 74147580Simp { PCMCIA_CARD(FUJITSU2, ITCFJ182A), 0 }, 75140041Simp /* These need to be second */ 76190427Simp { PCMCIA_CARD(TDK, LAK_CD011), 0 }, 77189728Simp { PCMCIA_CARD(TDK, LAK_CD021BX), 0 }, 78189728Simp { PCMCIA_CARD(TDK, LAK_CF010), 0 }, 7982778Sshiba#if 0 /* XXX 86960-based? */ 80189728Simp { PCMCIA_CARD(TDK, LAK_DFL9610), 0 }, 8182778Sshiba#endif 82189843Simp { PCMCIA_CARD(CONTEC, CNETPC), MPP_SKIP_TO_CFE, 2 }, 83147580Simp { PCMCIA_CARD(FUJITSU, LA501), 0 }, 84147580Simp { PCMCIA_CARD(FUJITSU, LA10S), 0 }, 85147580Simp { PCMCIA_CARD(FUJITSU, NE200T), MPP_MBH10302 },/* Sold by Eagle */ 86189843Simp { PCMCIA_CARD(HITACHI, HT_4840), MPP_MBH10302 | MPP_SKIP_TO_CFE, 10 }, 87147580Simp { PCMCIA_CARD(RATOC, REX_R280), 0 }, 88151638Simp { PCMCIA_CARD(XIRCOM, CE), MPP_ANYFUNC }, 89189728Simp { { NULL } } 9082778Sshiba}; 9182778Sshiba 9282778Sshibastatic int 93150396Simpfe_pccard_probe(device_t dev) 9482778Sshiba{ 95140528Simp int error; 96140528Simp uint32_t fcn = PCCARD_FUNCTION_UNSPEC; 97189728Simp const struct fe_pccard_product *pp; 98189681Simp int i; 9982778Sshiba 100189728Simp if ((pp = (const struct fe_pccard_product *)pccard_product_lookup(dev, 101189728Simp (const struct pccard_product *)fe_pccard_products, 102189728Simp sizeof(fe_pccard_products[0]), NULL)) != NULL) { 103151638Simp if (pp->mpp_product.pp_name != NULL) 104151638Simp device_set_desc(dev, pp->mpp_product.pp_name); 105151638Simp if (pp->mpp_flags & MPP_ANYFUNC) 106151638Simp return (0); 107151638Simp /* Make sure we're a network function */ 108151638Simp error = pccard_get_function(dev, &fcn); 109151638Simp if (error != 0) 110151638Simp return (error); 111151638Simp if (fcn != PCCARD_FUNCTION_NETWORK) 112151638Simp return (ENXIO); 113189843Simp if (pp->mpp_flags & MPP_SKIP_TO_CFE) { 114189843Simp for (i = pp->mpp_cfe; i < 32; i++) { 115189681Simp if (pccard_select_cfe(dev, i) == 0) 116189681Simp goto good; 117189681Simp } 118189681Simp device_printf(dev, 119189843Simp "Failed to map CFE %d or higher\n", pp->mpp_cfe); 120189681Simp return ENXIO; 121189681Simp } 122189681Simp good:; 123152621Simp return (0); 124189728Simp } 125189728Simp return (ENXIO); 12682778Sshiba} 12782778Sshiba 12865832Snyanstatic device_method_t fe_pccard_methods[] = { 129189728Simp /* Device interface */ 130189728Simp DEVMETHOD(device_probe, fe_pccard_probe), 131189728Simp DEVMETHOD(device_attach, fe_pccard_attach), 132189728Simp DEVMETHOD(device_detach, fe_pccard_detach), 13365832Snyan 13465832Snyan { 0, 0 } 13565832Snyan}; 13665832Snyan 13765832Snyanstatic driver_t fe_pccard_driver = { 13865832Snyan "fe", 13965832Snyan fe_pccard_methods, 14065832Snyan sizeof (struct fe_softc) 14165832Snyan}; 14265832Snyan 14365832SnyanDRIVER_MODULE(fe, pccard, fe_pccard_driver, fe_devclass, 0, 0); 144189681SimpMODULE_DEPEND(fe, pccard, 1, 1, 1); 14565832Snyan 146140543Simpstatic int fe_probe_mbh(device_t, const struct fe_pccard_product *); 147140543Simpstatic int fe_probe_tdk(device_t, const struct fe_pccard_product *); 148189728Simp 14965832Snyanstatic int 150150396Simpfe_pccard_attach(device_t dev) 15165832Snyan{ 15265832Snyan struct fe_softc *sc; 153189728Simp const struct fe_pccard_product *pp; 15465832Snyan int error; 15565832Snyan 15665832Snyan /* Prepare for the device probe process. */ 15765832Snyan sc = device_get_softc(dev); 15865832Snyan sc->sc_unit = device_get_unit(dev); 15965832Snyan 160189728Simp pp = (const struct fe_pccard_product *) pccard_product_lookup(dev, 161140543Simp (const struct pccard_product *)fe_pccard_products, 162189728Simp sizeof(fe_pccard_products[0]), NULL); 163140543Simp if (pp == NULL) 164140543Simp return (ENXIO); 16565832Snyan 166140543Simp if (pp->mpp_flags & MPP_MBH10302) 167140543Simp error = fe_probe_mbh(dev, pp); 168140543Simp else 169140543Simp error = fe_probe_tdk(dev, pp); 170150396Simp if (error != 0) { 171150396Simp fe_release_resource(dev); 172150396Simp return (error); 173150396Simp } 174150396Simp error = fe_alloc_irq(dev, 0); 175150396Simp if (error != 0) { 176150396Simp fe_release_resource(dev); 177150396Simp return (error); 178150396Simp } 179150396Simp return (fe_attach(dev)); 18065832Snyan} 18165832Snyan 18265832Snyan/* 18365832Snyan * feunload - unload the driver and clear the table. 18465832Snyan */ 18565832Snyanstatic int 18665832Snyanfe_pccard_detach(device_t dev) 18765832Snyan{ 18865832Snyan struct fe_softc *sc = device_get_softc(dev); 189147256Sbrooks struct ifnet *ifp = sc->ifp; 19065832Snyan 191179493Sjhb FE_LOCK(sc); 19265832Snyan fe_stop(sc); 193179493Sjhb FE_UNLOCK(sc); 194179493Sjhb callout_drain(&sc->timer); 195106937Ssam ether_ifdetach(ifp); 196150306Simp bus_teardown_intr(dev, sc->irq_res, sc->irq_handle); 197147256Sbrooks if_free(ifp); 19865832Snyan fe_release_resource(dev); 199179493Sjhb mtx_destroy(&sc->lock); 20065832Snyan 20165832Snyan return 0; 20265832Snyan} 20365832Snyan 20465832Snyan 20565832Snyan/* 20665832Snyan * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface. 20765832Snyan * Note that this is for 10302 only; MBH10304 is handled by fe_probe_tdk(). 20865832Snyan */ 20965832Snyanstatic void 21065832Snyanfe_init_mbh(struct fe_softc *sc) 21165832Snyan{ 21265832Snyan /* Minimal initialization of 86960. */ 21365832Snyan DELAY(200); 21465832Snyan fe_outb(sc, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); 21565832Snyan DELAY(200); 21665832Snyan 21765832Snyan /* Disable all interrupts. */ 21865832Snyan fe_outb(sc, FE_DLCR2, 0); 21965832Snyan fe_outb(sc, FE_DLCR3, 0); 22065832Snyan 22165832Snyan /* Enable master interrupt flag. */ 22265832Snyan fe_outb(sc, FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE); 22365832Snyan} 22465832Snyan 22565832Snyanstatic int 226140543Simpfe_probe_mbh(device_t dev, const struct fe_pccard_product *pp) 22765832Snyan{ 22865832Snyan struct fe_softc *sc = device_get_softc(dev); 22965832Snyan 23065832Snyan static struct fe_simple_probe_struct probe_table [] = { 23165832Snyan { FE_DLCR2, 0x58, 0x00 }, 23265832Snyan { FE_DLCR4, 0x08, 0x00 }, 23365832Snyan { FE_DLCR6, 0xFF, 0xB6 }, 23465832Snyan { 0 } 23565832Snyan }; 23665832Snyan 23765832Snyan /* MBH10302 occupies 32 I/O addresses. */ 23865832Snyan if (fe_alloc_port(dev, 32)) 23965832Snyan return ENXIO; 24065832Snyan 24165832Snyan /* Fill the softc struct with default values. */ 24265832Snyan fe_softc_defaults(sc); 24365832Snyan 24465832Snyan /* 24565832Snyan * See if MBH10302 is on its address. 24665832Snyan * I'm not sure the following probe code works. FIXME. 24765832Snyan */ 24865832Snyan if (!fe_simple_probe(sc, probe_table)) 24965832Snyan return ENXIO; 25065832Snyan 25165832Snyan /* Get our station address from EEPROM. */ 252147256Sbrooks fe_inblk(sc, FE_MBH10, sc->enaddr, ETHER_ADDR_LEN); 25365832Snyan 25465832Snyan /* Make sure we got a valid station address. */ 255147256Sbrooks if (!fe_valid_Ether_p(sc->enaddr, 0)) 25665832Snyan return ENXIO; 25765832Snyan 25865832Snyan /* Determine the card type. */ 25965832Snyan sc->type = FE_TYPE_MBH; 26065832Snyan sc->typestr = "MBH10302 (PCMCIA)"; 26165832Snyan 26265832Snyan /* We seems to need our own IDENT bits... FIXME. */ 26365832Snyan sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE; 26465832Snyan 26565832Snyan /* Setup hooks. We need a special initialization procedure. */ 26665832Snyan sc->init = fe_init_mbh; 26765832Snyan 26865832Snyan return 0; 26965832Snyan} 27065832Snyan 271151638Simpstatic int 272189728Simpfe_pccard_xircom_mac(const struct pccard_tuple *tuple, void *argp) 273151638Simp{ 274151638Simp uint8_t *enaddr = argp; 275151638Simp int i; 276151638Simp 277151638Simp#if 1 278151638Simp /* 279151638Simp * We fail to map the CIS twice, for reasons unknown. We 280151638Simp * may fix this in the future by loading the CIS with a sane 281151638Simp * CIS from userland. 282151638Simp */ 283151638Simp static uint8_t defaultmac[ETHER_ADDR_LEN] = { 284151638Simp 0x00, 0x80, 0xc7, 0xed, 0x16, 0x7b}; 285151638Simp 286151638Simp /* Copy the MAC ADDR and return success */ 287151638Simp for (i = 0; i < ETHER_ADDR_LEN; i++) 288151638Simp enaddr[i] = defaultmac[i]; 289151638Simp#else 290151638Simp /* FUNCE is not after FUNCID, so we gotta go find it */ 291151638Simp if (tuple->code != 0x22) 292151638Simp return (0); 293151638Simp 294151638Simp /* Make sure this is a sane node */ 295151638Simp if (tuple->length < ETHER_ADDR_LEN + 3) 296151638Simp return (0); 297151638Simp 298151638Simp /* Copy the MAC ADDR and return success */ 299151638Simp for (i = 0; i < ETHER_ADDR_LEN; i++) 300151638Simp enaddr[i] = pccard_tuple_read_1(tuple, i + 3); 301151638Simp#endif 302151638Simp return (1); 303151638Simp} 304151638Simp 30565832Snyan/* 30665832Snyan * Probe and initialization for TDK/CONTEC PCMCIA Ethernet interface. 30765832Snyan * by MASUI Kenji <masui@cs.titech.ac.jp> 30865832Snyan * 309199798Srwatson * (Contec uses TDK Ethernet chip -- hosokawa) 31065832Snyan * 31165832Snyan * This version of fe_probe_tdk has been rewrote to handle 312150458Simp * *generic* PC Card implementation of Fujitsu MB8696x family. The 31365832Snyan * name _tdk is just for a historical reason. :-) 31465832Snyan */ 31565832Snyanstatic int 316140543Simpfe_probe_tdk (device_t dev, const struct fe_pccard_product *pp) 31765832Snyan{ 31865832Snyan struct fe_softc *sc = device_get_softc(dev); 31965832Snyan 320189728Simp static struct fe_simple_probe_struct probe_table [] = { 321189728Simp { FE_DLCR2, 0x10, 0x00 }, 322189728Simp { FE_DLCR4, 0x08, 0x00 }, 323189728Simp/* { FE_DLCR5, 0x80, 0x00 }, Does not work well. */ 324189728Simp { 0 } 325189728Simp }; 32665832Snyan 327151638Simp 328189728Simp /* C-NET(PC)C occupies 16 I/O addresses. */ 32965832Snyan if (fe_alloc_port(dev, 16)) 33065832Snyan return ENXIO; 33165832Snyan 33265832Snyan /* Fill the softc struct with default values. */ 33365832Snyan fe_softc_defaults(sc); 33465832Snyan 335189728Simp /* 336189728Simp * See if C-NET(PC)C is on its address. 337189728Simp */ 338189728Simp if (!fe_simple_probe(sc, probe_table)) 339142136Simp return ENXIO; 34065832Snyan 341189728Simp /* Determine the card type. */ 34265832Snyan sc->type = FE_TYPE_TDK; 343189728Simp sc->typestr = "Generic MB8696x/78Q837x Ethernet (PCMCIA)"; 34465832Snyan 345147256Sbrooks pccard_get_ether(dev, sc->enaddr); 346140543Simp 347189728Simp /* Make sure we got a valid station address. */ 348189728Simp if (!fe_valid_Ether_p(sc->enaddr, 0)) { 349189728Simp pccard_cis_scan(dev, fe_pccard_xircom_mac, sc->enaddr); 350151638Simp } 351151638Simp 352189728Simp /* Make sure we got a valid station address. */ 353189728Simp if (!fe_valid_Ether_p(sc->enaddr, 0)) 354142136Simp return ENXIO; 35565832Snyan 356189728Simp return 0; 35765832Snyan} 358