if_fe_pccard.c revision 67158
1220137Strasz/* 2220137Strasz * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 3220137Strasz * 4220137Strasz * This software may be used, modified, copied, distributed, and sold, in 5220137Strasz * both source and binary form provided that the above copyright, these 6220137Strasz * terms and the following disclaimer are retained. The name of the author 7220137Strasz * and/or the contributor may not be used to endorse or promote products 8220137Strasz * derived from this software without specific prior written permission. 9220137Strasz * 10220137Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND 11220137Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12220137Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 13220137Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE 14220137Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 15220137Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 16220137Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION. 17220137Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 18220137Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 19220137Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 20220137Strasz * SUCH DAMAGE. 21220137Strasz * 22220137Strasz * $FreeBSD: head/sys/dev/fe/if_fe_pccard.c 67158 2000-10-15 09:51:49Z phk $ 23220137Strasz */ 24220137Strasz 25220137Strasz#include "opt_fe.h" 26220137Strasz#include "opt_inet.h" 27220137Strasz#include "opt_ipx.h" 28220137Strasz 29220137Strasz#include <sys/param.h> 30220137Strasz#include <sys/kernel.h> 31220137Strasz#include <sys/socket.h> 32220137Strasz#include <sys/systm.h> 33220137Strasz#include <sys/module.h> 34220137Strasz#include <machine/clock.h> 35220137Strasz 36242139Strasz#include <sys/bus.h> 37220137Strasz#include <machine/bus.h> 38220137Strasz#include <machine/resource.h> 39228430Savg 40220137Strasz#include <net/ethernet.h> 41220137Strasz#include <net/if.h> 42220137Strasz#include <net/if_mib.h> 43220137Strasz#include <net/if_media.h> 44220137Strasz 45220137Strasz#include <netinet/in.h> 46220137Strasz#include <netinet/if_ether.h> 47220137Strasz 48220137Strasz#include <i386/isa/ic/mb86960.h> 49220137Strasz#include <dev/fe/if_fereg.h> 50220137Strasz#include <dev/fe/if_fevar.h> 51220137Strasz 52220137Strasz#include <dev/pccard/pccardvar.h> 53220137Strasz#include <pccard/cardinfo.h> 54242139Strasz 55220137Strasz/* 56242139Strasz * PC-Card (PCMCIA) specific code. 57220137Strasz */ 58220137Straszstatic int fe_pccard_probe(device_t); 59220137Straszstatic int fe_pccard_attach(device_t); 60242139Straszstatic int fe_pccard_detach(device_t); 61220137Strasz 62220137Straszstatic device_method_t fe_pccard_methods[] = { 63220137Strasz /* Device interface */ 64220137Strasz DEVMETHOD(device_probe, fe_pccard_probe), 65220137Strasz DEVMETHOD(device_attach, fe_pccard_attach), 66220137Strasz DEVMETHOD(device_detach, fe_pccard_detach), 67220137Strasz 68220137Strasz { 0, 0 } 69220137Strasz}; 70242139Strasz 71242139Straszstatic driver_t fe_pccard_driver = { 72242139Strasz "fe", 73242139Strasz fe_pccard_methods, 74242139Strasz sizeof (struct fe_softc) 75242139Strasz}; 76242139Strasz 77242139StraszDRIVER_MODULE(fe, pccard, fe_pccard_driver, fe_devclass, 0, 0); 78242139Strasz 79242139Strasz 80242139Straszstatic int fe_probe_mbh(device_t); 81242139Straszstatic int fe_probe_tdk(device_t); 82242139Strasz 83242139Strasz/* 84242139Strasz * Initialize the device - called from Slot manager. 85242139Strasz */ 86242139Straszstatic int 87220137Straszfe_pccard_probe(device_t dev) 88220137Strasz{ 89220137Strasz struct fe_softc *sc; 90220137Strasz int error; 91220137Strasz 92220137Strasz /* Prepare for the device probe process. */ 93220137Strasz sc = device_get_softc(dev); 94220137Strasz sc->sc_unit = device_get_unit(dev); 95220137Strasz 96220137Strasz pccard_get_ether(dev, sc->sc_enaddr); 97220137Strasz 98220137Strasz /* Probe for supported cards. */ 99220137Strasz if ((error = fe_probe_mbh(dev)) == 0) 100220137Strasz goto end; 101220137Strasz fe_release_resource(dev); 102220137Strasz 103220137Strasz if ((error = fe_probe_tdk(dev)) == 0) 104220137Strasz goto end; 105220137Strasz fe_release_resource(dev); 106220137Strasz 107220137Straszend: 108220137Strasz if (error == 0) 109220137Strasz error = fe_alloc_irq(dev, 0); 110220137Strasz 111220137Strasz fe_release_resource(dev); 112220137Strasz return (error); 113220137Strasz} 114220137Strasz 115220137Straszstatic int 116220137Straszfe_pccard_attach(device_t dev) 117220137Strasz{ 118220137Strasz struct fe_softc *sc = device_get_softc(dev); 119220137Strasz 120220137Strasz if (sc->port_used) 121220137Strasz fe_alloc_port(dev, sc->port_used); 122220137Strasz fe_alloc_irq(dev, 0); 123220137Strasz 124220137Strasz return fe_attach(dev); 125220137Strasz} 126224036Strasz 127220137Strasz/* 128220137Strasz * feunload - unload the driver and clear the table. 129220137Strasz * XXX TODO: 130220137Strasz * This is usually called when the card is ejected, but 131220137Strasz * can be caused by a modunload of a controller driver. 132220137Strasz * The idea is to reset the driver's view of the device 133220137Strasz * and ensure that any driver entry points such as 134220137Strasz * read and write do not hang. 135220137Strasz */ 136220137Straszstatic int 137220137Straszfe_pccard_detach(device_t dev) 138220137Strasz{ 139220137Strasz struct fe_softc *sc = device_get_softc(dev); 140220137Strasz struct ifnet *ifp = &sc->arpcom.ac_if; 141220137Strasz 142220137Strasz fe_stop(sc); 143220137Strasz ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); 144220137Strasz bus_teardown_intr(dev, sc->irq_res, sc->irq_handle); 145220137Strasz fe_release_resource(dev); 146220137Strasz 147220137Strasz return 0; 148220137Strasz} 149220137Strasz 150220137Strasz 151220137Strasz/* 152220137Strasz * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface. 153220137Strasz * Note that this is for 10302 only; MBH10304 is handled by fe_probe_tdk(). 154220137Strasz */ 155220137Straszstatic void 156220137Straszfe_init_mbh(struct fe_softc *sc) 157220137Strasz{ 158220137Strasz /* Minimal initialization of 86960. */ 159220137Strasz DELAY(200); 160220137Strasz fe_outb(sc, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); 161220137Strasz DELAY(200); 162220137Strasz 163220137Strasz /* Disable all interrupts. */ 164242139Strasz fe_outb(sc, FE_DLCR2, 0); 165242139Strasz fe_outb(sc, FE_DLCR3, 0); 166242139Strasz 167220137Strasz /* Enable master interrupt flag. */ 168242139Strasz fe_outb(sc, FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE); 169242139Strasz} 170242139Strasz 171242139Straszstatic int 172242139Straszfe_probe_mbh(device_t dev) 173242139Strasz{ 174242139Strasz struct fe_softc *sc = device_get_softc(dev); 175242139Strasz 176242139Strasz static struct fe_simple_probe_struct probe_table [] = { 177242139Strasz { FE_DLCR2, 0x58, 0x00 }, 178242139Strasz { FE_DLCR4, 0x08, 0x00 }, 179242139Strasz { FE_DLCR6, 0xFF, 0xB6 }, 180242139Strasz { 0 } 181242139Strasz }; 182242139Strasz 183242139Strasz /* MBH10302 occupies 32 I/O addresses. */ 184242139Strasz if (fe_alloc_port(dev, 32)) 185242139Strasz return ENXIO; 186242139Strasz 187242139Strasz /* Ethernet MAC address should *NOT* have been given by pccardd, 188242139Strasz if this is a true MBH10302; i.e., Ethernet address must be 189242139Strasz "all-zero" upon entry. */ 190242139Strasz if (sc->sc_enaddr[0] || sc->sc_enaddr[1] || sc->sc_enaddr[2] || 191242139Strasz sc->sc_enaddr[3] || sc->sc_enaddr[4] || sc->sc_enaddr[5]) 192242139Strasz return ENXIO; 193242139Strasz 194242139Strasz /* Fill the softc struct with default values. */ 195242139Strasz fe_softc_defaults(sc); 196242139Strasz 197242139Strasz /* 198242139Strasz * See if MBH10302 is on its address. 199242139Strasz * I'm not sure the following probe code works. FIXME. 200242139Strasz */ 201242139Strasz if (!fe_simple_probe(sc, probe_table)) 202242139Strasz return ENXIO; 203242139Strasz 204242139Strasz /* Get our station address from EEPROM. */ 205242139Strasz fe_inblk(sc, FE_MBH10, sc->sc_enaddr, ETHER_ADDR_LEN); 206242139Strasz 207242139Strasz /* Make sure we got a valid station address. */ 208242139Strasz if (!valid_Ether_p(sc->sc_enaddr, 0)) 209242139Strasz return ENXIO; 210242139Strasz 211242139Strasz /* Determine the card type. */ 212242139Strasz sc->type = FE_TYPE_MBH; 213242139Strasz sc->typestr = "MBH10302 (PCMCIA)"; 214242139Strasz 215242139Strasz /* We seems to need our own IDENT bits... FIXME. */ 216242139Strasz sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE; 217242139Strasz 218242139Strasz /* Setup hooks. We need a special initialization procedure. */ 219242139Strasz sc->init = fe_init_mbh; 220242139Strasz 221242139Strasz return 0; 222242139Strasz} 223242139Strasz 224242139Strasz/* 225242139Strasz * Probe and initialization for TDK/CONTEC PCMCIA Ethernet interface. 226242139Strasz * by MASUI Kenji <masui@cs.titech.ac.jp> 227242139Strasz * 228242139Strasz * (Contec uses TDK Ethenet chip -- hosokawa) 229242139Strasz * 230242139Strasz * This version of fe_probe_tdk has been rewrote to handle 231242139Strasz * *generic* PC card implementation of Fujitsu MB8696x family. The 232242139Strasz * name _tdk is just for a historical reason. :-) 233242139Strasz */ 234242139Straszstatic int 235242139Straszfe_probe_tdk (device_t dev) 236242139Strasz{ 237242139Strasz struct fe_softc *sc = device_get_softc(dev); 238242139Strasz 239242139Strasz static struct fe_simple_probe_struct probe_table [] = { 240242139Strasz { FE_DLCR2, 0x50, 0x00 }, 241242139Strasz { FE_DLCR4, 0x08, 0x00 }, 242242139Strasz /* { FE_DLCR5, 0x80, 0x00 }, Does not work well. */ 243242139Strasz { 0 } 244242139Strasz }; 245242139Strasz 246242139Strasz /* C-NET(PC)C occupies 16 I/O addresses. */ 247242139Strasz if (fe_alloc_port(dev, 16)) 248242139Strasz return ENXIO; 249242139Strasz 250242139Strasz /* Fill the softc struct with default values. */ 251242139Strasz fe_softc_defaults(sc); 252242139Strasz 253242139Strasz /* 254242139Strasz * See if C-NET(PC)C is on its address. 255242139Strasz */ 256242139Strasz if (!fe_simple_probe(sc, probe_table)) 257242139Strasz return ENXIO; 258242139Strasz 259242139Strasz /* Determine the card type. */ 260242139Strasz sc->type = FE_TYPE_TDK; 261242139Strasz sc->typestr = "Generic MB8696x/78Q837x Ethernet (PCMCIA)"; 262242139Strasz 263242139Strasz /* Make sure we got a valid station address. */ 264242139Strasz if (!valid_Ether_p(sc->sc_enaddr, 0)) 265242139Strasz return ENXIO; 266242139Strasz 267242139Strasz return 0; 268242139Strasz} 269242139Strasz