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/11.0/sys/dev/fe/if_fe_pccard.c 292079 2015-12-11 05:27:56Z imp $"); 26119418Sobrien 2765832Snyan#include <sys/param.h> 2865832Snyan#include <sys/kernel.h> 2965832Snyan#include <sys/socket.h> 3067158Sphk#include <sys/systm.h> 31257176Sglebius#include <sys/lock.h> 3265832Snyan#include <sys/module.h> 33257176Sglebius#include <sys/mutex.h> 3465832Snyan 3565832Snyan#include <sys/bus.h> 3665832Snyan#include <machine/bus.h> 37140543Simp#include <sys/rman.h> 3865832Snyan 3965832Snyan#include <net/ethernet.h> 4065832Snyan#include <net/if.h> 41257176Sglebius#include <net/if_var.h> 4265832Snyan#include <net/if_mib.h> 4365832Snyan#include <net/if_media.h> 4465832Snyan 4565832Snyan#include <netinet/in.h> 4665832Snyan#include <netinet/if_ether.h> 4765832Snyan 48142135Simp#include <dev/fe/mb86960.h> 4965832Snyan#include <dev/fe/if_fereg.h> 5065832Snyan#include <dev/fe/if_fevar.h> 5165832Snyan 5265832Snyan#include <dev/pccard/pccardvar.h> 53140528Simp#include <dev/pccard/pccard_cis.h> 54129764Simp 55129764Simp#include "card_if.h" 56129740Simp#include "pccarddevs.h" 5765832Snyan 5865832Snyan/* 59150458Simp * PC Card (PCMCIA) specific code. 6065832Snyan */ 6165832Snyanstatic int fe_pccard_probe(device_t); 6265832Snyanstatic int fe_pccard_attach(device_t); 6365832Snyanstatic int fe_pccard_detach(device_t); 6465832Snyan 6582778Sshibastatic const struct fe_pccard_product { 66189728Simp struct pccard_product mpp_product; 67140041Simp int mpp_flags; 68189843Simp int mpp_cfe; 69140543Simp#define MPP_MBH10302 1 70151638Simp#define MPP_ANYFUNC 2 71189843Simp#define MPP_SKIP_TO_CFE 4 7282778Sshiba} fe_pccard_products[] = { 73140041Simp /* These need to be first */ 74147580Simp { PCMCIA_CARD(FUJITSU2, FMV_J181), MPP_MBH10302 }, 75147580Simp { PCMCIA_CARD(FUJITSU2, FMV_J182), 0 }, 76147580Simp { PCMCIA_CARD(FUJITSU2, FMV_J182A), 0 }, 77147580Simp { PCMCIA_CARD(FUJITSU2, ITCFJ182A), 0 }, 78140041Simp /* These need to be second */ 79190427Simp { PCMCIA_CARD(TDK, LAK_CD011), 0 }, 80189728Simp { PCMCIA_CARD(TDK, LAK_CD021BX), 0 }, 81189728Simp { PCMCIA_CARD(TDK, LAK_CF010), 0 }, 8282778Sshiba#if 0 /* XXX 86960-based? */ 83189728Simp { PCMCIA_CARD(TDK, LAK_DFL9610), 0 }, 8482778Sshiba#endif 85189843Simp { PCMCIA_CARD(CONTEC, CNETPC), MPP_SKIP_TO_CFE, 2 }, 86147580Simp { PCMCIA_CARD(FUJITSU, LA501), 0 }, 87147580Simp { PCMCIA_CARD(FUJITSU, LA10S), 0 }, 88147580Simp { PCMCIA_CARD(FUJITSU, NE200T), MPP_MBH10302 },/* Sold by Eagle */ 89189843Simp { PCMCIA_CARD(HITACHI, HT_4840), MPP_MBH10302 | MPP_SKIP_TO_CFE, 10 }, 90147580Simp { PCMCIA_CARD(RATOC, REX_R280), 0 }, 91151638Simp { PCMCIA_CARD(XIRCOM, CE), MPP_ANYFUNC }, 92189728Simp { { NULL } } 9382778Sshiba}; 9482778Sshiba 9582778Sshibastatic int 96150396Simpfe_pccard_probe(device_t dev) 9782778Sshiba{ 98140528Simp int error; 99140528Simp uint32_t fcn = PCCARD_FUNCTION_UNSPEC; 100189728Simp const struct fe_pccard_product *pp; 101189681Simp int i; 10282778Sshiba 103189728Simp if ((pp = (const struct fe_pccard_product *)pccard_product_lookup(dev, 104189728Simp (const struct pccard_product *)fe_pccard_products, 105189728Simp sizeof(fe_pccard_products[0]), NULL)) != NULL) { 106151638Simp if (pp->mpp_product.pp_name != NULL) 107151638Simp device_set_desc(dev, pp->mpp_product.pp_name); 108151638Simp if (pp->mpp_flags & MPP_ANYFUNC) 109151638Simp return (0); 110151638Simp /* Make sure we're a network function */ 111151638Simp error = pccard_get_function(dev, &fcn); 112151638Simp if (error != 0) 113151638Simp return (error); 114151638Simp if (fcn != PCCARD_FUNCTION_NETWORK) 115151638Simp return (ENXIO); 116189843Simp if (pp->mpp_flags & MPP_SKIP_TO_CFE) { 117189843Simp for (i = pp->mpp_cfe; i < 32; i++) { 118189681Simp if (pccard_select_cfe(dev, i) == 0) 119189681Simp goto good; 120189681Simp } 121189681Simp device_printf(dev, 122189843Simp "Failed to map CFE %d or higher\n", pp->mpp_cfe); 123189681Simp return ENXIO; 124189681Simp } 125189681Simp good:; 126152621Simp return (0); 127189728Simp } 128189728Simp return (ENXIO); 12982778Sshiba} 13082778Sshiba 13165832Snyanstatic device_method_t fe_pccard_methods[] = { 132189728Simp /* Device interface */ 133189728Simp DEVMETHOD(device_probe, fe_pccard_probe), 134189728Simp DEVMETHOD(device_attach, fe_pccard_attach), 135189728Simp DEVMETHOD(device_detach, fe_pccard_detach), 13665832Snyan 13765832Snyan { 0, 0 } 13865832Snyan}; 13965832Snyan 14065832Snyanstatic driver_t fe_pccard_driver = { 14165832Snyan "fe", 14265832Snyan fe_pccard_methods, 14365832Snyan sizeof (struct fe_softc) 14465832Snyan}; 14565832Snyan 14665832SnyanDRIVER_MODULE(fe, pccard, fe_pccard_driver, fe_devclass, 0, 0); 147189681SimpMODULE_DEPEND(fe, pccard, 1, 1, 1); 148292079SimpPCCARD_PNP_INFO(fe_pccard_products); 14965832Snyan 150140543Simpstatic int fe_probe_mbh(device_t, const struct fe_pccard_product *); 151140543Simpstatic int fe_probe_tdk(device_t, const struct fe_pccard_product *); 152189728Simp 15365832Snyanstatic int 154150396Simpfe_pccard_attach(device_t dev) 15565832Snyan{ 15665832Snyan struct fe_softc *sc; 157189728Simp const struct fe_pccard_product *pp; 15865832Snyan int error; 15965832Snyan 16065832Snyan /* Prepare for the device probe process. */ 16165832Snyan sc = device_get_softc(dev); 16265832Snyan sc->sc_unit = device_get_unit(dev); 16365832Snyan 164189728Simp pp = (const struct fe_pccard_product *) pccard_product_lookup(dev, 165140543Simp (const struct pccard_product *)fe_pccard_products, 166189728Simp sizeof(fe_pccard_products[0]), NULL); 167140543Simp if (pp == NULL) 168140543Simp return (ENXIO); 16965832Snyan 170140543Simp if (pp->mpp_flags & MPP_MBH10302) 171140543Simp error = fe_probe_mbh(dev, pp); 172140543Simp else 173140543Simp error = fe_probe_tdk(dev, pp); 174150396Simp if (error != 0) { 175150396Simp fe_release_resource(dev); 176150396Simp return (error); 177150396Simp } 178150396Simp error = fe_alloc_irq(dev, 0); 179150396Simp if (error != 0) { 180150396Simp fe_release_resource(dev); 181150396Simp return (error); 182150396Simp } 183150396Simp return (fe_attach(dev)); 18465832Snyan} 18565832Snyan 18665832Snyan/* 18765832Snyan * feunload - unload the driver and clear the table. 18865832Snyan */ 18965832Snyanstatic int 19065832Snyanfe_pccard_detach(device_t dev) 19165832Snyan{ 19265832Snyan struct fe_softc *sc = device_get_softc(dev); 193147256Sbrooks struct ifnet *ifp = sc->ifp; 19465832Snyan 195179493Sjhb FE_LOCK(sc); 19665832Snyan fe_stop(sc); 197179493Sjhb FE_UNLOCK(sc); 198179493Sjhb callout_drain(&sc->timer); 199106937Ssam ether_ifdetach(ifp); 200150306Simp bus_teardown_intr(dev, sc->irq_res, sc->irq_handle); 201147256Sbrooks if_free(ifp); 20265832Snyan fe_release_resource(dev); 203179493Sjhb mtx_destroy(&sc->lock); 20465832Snyan 20565832Snyan return 0; 20665832Snyan} 20765832Snyan 20865832Snyan 20965832Snyan/* 21065832Snyan * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface. 21165832Snyan * Note that this is for 10302 only; MBH10304 is handled by fe_probe_tdk(). 21265832Snyan */ 21365832Snyanstatic void 21465832Snyanfe_init_mbh(struct fe_softc *sc) 21565832Snyan{ 21665832Snyan /* Minimal initialization of 86960. */ 21765832Snyan DELAY(200); 21865832Snyan fe_outb(sc, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); 21965832Snyan DELAY(200); 22065832Snyan 22165832Snyan /* Disable all interrupts. */ 22265832Snyan fe_outb(sc, FE_DLCR2, 0); 22365832Snyan fe_outb(sc, FE_DLCR3, 0); 22465832Snyan 22565832Snyan /* Enable master interrupt flag. */ 22665832Snyan fe_outb(sc, FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE); 22765832Snyan} 22865832Snyan 22965832Snyanstatic int 230140543Simpfe_probe_mbh(device_t dev, const struct fe_pccard_product *pp) 23165832Snyan{ 23265832Snyan struct fe_softc *sc = device_get_softc(dev); 23365832Snyan 23465832Snyan static struct fe_simple_probe_struct probe_table [] = { 23565832Snyan { FE_DLCR2, 0x58, 0x00 }, 23665832Snyan { FE_DLCR4, 0x08, 0x00 }, 23765832Snyan { FE_DLCR6, 0xFF, 0xB6 }, 23865832Snyan { 0 } 23965832Snyan }; 24065832Snyan 24165832Snyan /* MBH10302 occupies 32 I/O addresses. */ 24265832Snyan if (fe_alloc_port(dev, 32)) 24365832Snyan return ENXIO; 24465832Snyan 24565832Snyan /* Fill the softc struct with default values. */ 24665832Snyan fe_softc_defaults(sc); 24765832Snyan 24865832Snyan /* 24965832Snyan * See if MBH10302 is on its address. 25065832Snyan * I'm not sure the following probe code works. FIXME. 25165832Snyan */ 25265832Snyan if (!fe_simple_probe(sc, probe_table)) 25365832Snyan return ENXIO; 25465832Snyan 25565832Snyan /* Get our station address from EEPROM. */ 256147256Sbrooks fe_inblk(sc, FE_MBH10, sc->enaddr, ETHER_ADDR_LEN); 25765832Snyan 25865832Snyan /* Make sure we got a valid station address. */ 259147256Sbrooks if (!fe_valid_Ether_p(sc->enaddr, 0)) 26065832Snyan return ENXIO; 26165832Snyan 26265832Snyan /* Determine the card type. */ 26365832Snyan sc->type = FE_TYPE_MBH; 26465832Snyan sc->typestr = "MBH10302 (PCMCIA)"; 26565832Snyan 26665832Snyan /* We seems to need our own IDENT bits... FIXME. */ 26765832Snyan sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE; 26865832Snyan 26965832Snyan /* Setup hooks. We need a special initialization procedure. */ 27065832Snyan sc->init = fe_init_mbh; 27165832Snyan 27265832Snyan return 0; 27365832Snyan} 27465832Snyan 275151638Simpstatic int 276189728Simpfe_pccard_xircom_mac(const struct pccard_tuple *tuple, void *argp) 277151638Simp{ 278151638Simp uint8_t *enaddr = argp; 279151638Simp int i; 280151638Simp 281151638Simp#if 1 282151638Simp /* 283151638Simp * We fail to map the CIS twice, for reasons unknown. We 284151638Simp * may fix this in the future by loading the CIS with a sane 285151638Simp * CIS from userland. 286151638Simp */ 287151638Simp static uint8_t defaultmac[ETHER_ADDR_LEN] = { 288151638Simp 0x00, 0x80, 0xc7, 0xed, 0x16, 0x7b}; 289151638Simp 290151638Simp /* Copy the MAC ADDR and return success */ 291151638Simp for (i = 0; i < ETHER_ADDR_LEN; i++) 292151638Simp enaddr[i] = defaultmac[i]; 293151638Simp#else 294151638Simp /* FUNCE is not after FUNCID, so we gotta go find it */ 295151638Simp if (tuple->code != 0x22) 296151638Simp return (0); 297151638Simp 298151638Simp /* Make sure this is a sane node */ 299151638Simp if (tuple->length < ETHER_ADDR_LEN + 3) 300151638Simp return (0); 301151638Simp 302151638Simp /* Copy the MAC ADDR and return success */ 303151638Simp for (i = 0; i < ETHER_ADDR_LEN; i++) 304151638Simp enaddr[i] = pccard_tuple_read_1(tuple, i + 3); 305151638Simp#endif 306151638Simp return (1); 307151638Simp} 308151638Simp 30965832Snyan/* 31065832Snyan * Probe and initialization for TDK/CONTEC PCMCIA Ethernet interface. 31165832Snyan * by MASUI Kenji <masui@cs.titech.ac.jp> 31265832Snyan * 313199798Srwatson * (Contec uses TDK Ethernet chip -- hosokawa) 31465832Snyan * 31565832Snyan * This version of fe_probe_tdk has been rewrote to handle 316150458Simp * *generic* PC Card implementation of Fujitsu MB8696x family. The 31765832Snyan * name _tdk is just for a historical reason. :-) 31865832Snyan */ 31965832Snyanstatic int 320140543Simpfe_probe_tdk (device_t dev, const struct fe_pccard_product *pp) 32165832Snyan{ 32265832Snyan struct fe_softc *sc = device_get_softc(dev); 32365832Snyan 324189728Simp static struct fe_simple_probe_struct probe_table [] = { 325189728Simp { FE_DLCR2, 0x10, 0x00 }, 326189728Simp { FE_DLCR4, 0x08, 0x00 }, 327189728Simp/* { FE_DLCR5, 0x80, 0x00 }, Does not work well. */ 328189728Simp { 0 } 329189728Simp }; 33065832Snyan 331151638Simp 332189728Simp /* C-NET(PC)C occupies 16 I/O addresses. */ 33365832Snyan if (fe_alloc_port(dev, 16)) 33465832Snyan return ENXIO; 33565832Snyan 33665832Snyan /* Fill the softc struct with default values. */ 33765832Snyan fe_softc_defaults(sc); 33865832Snyan 339189728Simp /* 340189728Simp * See if C-NET(PC)C is on its address. 341189728Simp */ 342189728Simp if (!fe_simple_probe(sc, probe_table)) 343142136Simp return ENXIO; 34465832Snyan 345189728Simp /* Determine the card type. */ 34665832Snyan sc->type = FE_TYPE_TDK; 347189728Simp sc->typestr = "Generic MB8696x/78Q837x Ethernet (PCMCIA)"; 34865832Snyan 349147256Sbrooks pccard_get_ether(dev, sc->enaddr); 350140543Simp 351189728Simp /* Make sure we got a valid station address. */ 352189728Simp if (!fe_valid_Ether_p(sc->enaddr, 0)) { 353189728Simp pccard_cis_scan(dev, fe_pccard_xircom_mac, sc->enaddr); 354151638Simp } 355151638Simp 356189728Simp /* Make sure we got a valid station address. */ 357189728Simp if (!fe_valid_Ether_p(sc->enaddr, 0)) 358142136Simp return ENXIO; 35965832Snyan 360189728Simp return 0; 36165832Snyan} 362