if_xe_pccard.c revision 148031
169935Sdannyboy/*- 248734Siwasaki * Copyright (c) 2002 Takeshi Shibagaki 350472Speter * All rights reserved. 448734Siwasaki * 548734Siwasaki * Redistribution and use in source and binary forms, with or without 648734Siwasaki * modification, are permitted provided that the following conditions 748734Siwasaki * are met: 848734Siwasaki * 1. Redistributions of source code must retain the above copyright 948734Siwasaki * notice, this list of conditions and the following disclaimer. 1048734Siwasaki * 2. Redistributions in binary form must reproduce the above copyright 1148734Siwasaki * notice, this list of conditions and the following disclaimer in the 1248734Siwasaki * documentation and/or other materials provided with the distribution. 1348734Siwasaki * 1448734Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND 1548734Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1648734Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1748734Siwasaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1848734Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1948734Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2048734Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2148734Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2248734Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2348734Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2448734Siwasaki * SUCH DAMAGE. 2548734Siwasaki */ 2648734Siwasaki 2748734Siwasaki#include <sys/cdefs.h> 2848734Siwasaki__FBSDID("$FreeBSD: head/sys/dev/xe/if_xe_pccard.c 148031 2005-07-15 06:46:04Z imp $"); 2948734Siwasaki 3048734Siwasaki/* xe pccard interface driver */ 3148734Siwasaki 3248734Siwasaki#include <sys/param.h> 3348734Siwasaki#include <sys/bus.h> 3448734Siwasaki#include <sys/kernel.h> 3548734Siwasaki#include <sys/module.h> 3648734Siwasaki#include <sys/socket.h> 3781159Snsayer#include <sys/systm.h> 3881159Snsayer 3981159Snsayer#include <machine/bus.h> 4081159Snsayer#include <machine/resource.h> 4181159Snsayer#include <sys/rman.h> 4281159Snsayer 4381159Snsayer#include <net/ethernet.h> 4481159Snsayer#include <net/if.h> 4581159Snsayer#include <net/if_arp.h> 4681159Snsayer#include <net/if_media.h> 4781159Snsayer#include <net/if_mib.h> 4881159Snsayer 4969935Sdannyboy 50#include <dev/xe/if_xereg.h> 51#include <dev/xe/if_xevar.h> 52 53#include <dev/pccard/pccardvar.h> 54#include <dev/pccard/pccard_cis.h> 55 56#include "card_if.h" 57#include "pccarddevs.h" 58 59/* 60 * Debug logging levels - set with hw.xe.debug sysctl 61 * 0 = None 62 * 1 = More hardware details, probe/attach progress 63 * 2 = Most function calls, ioctls and media selection progress 64 * 3 = Everything - interrupts, packets in/out and multicast address setup 65 */ 66#define XE_DEBUG 67#ifdef XE_DEBUG 68 69extern int xe_debug; 70 71#define DEVPRINTF(level, arg) if (xe_debug >= (level)) device_printf arg 72#define DPRINTF(level, arg) if (xe_debug >= (level)) printf arg 73#else 74#define DEVPRINTF(level, arg) 75#define DPRINTF(level, arg) 76#endif 77 78 79#define XE_CARD_TYPE_FLAGS_NO 0x0 80#define XE_CARD_TYPE_FLAGS_CE2 0x1 81#define XE_CARD_TYPE_FLAGS_MOHAWK 0x2 82#define XE_CARD_TYPE_FLAGS_DINGO 0x4 83#define XE_PROD_ETHER_MASK 0x0100 84#define XE_PROD_MODEM_MASK 0x1000 85 86#define XE_BOGUS_MAC_OFFSET 0x90 87 88/* MAC vendor prefix used by most Xircom cards is 00:80:c7 */ 89#define XE_MAC_ADDR_0 0x00 90#define XE_MAC_ADDR_1 0x80 91#define XE_MAC_ADDR_2 0xc7 92 93/* Some (all?) REM56 cards have vendor prefix 00:10:a4 */ 94#define XE_REM56_MAC_ADDR_0 0x00 95#define XE_REM56_MAC_ADDR_1 0x10 96#define XE_REM56_MAC_ADDR_2 0xa4 97 98 99struct xe_pccard_product { 100 struct pccard_product product; 101 uint16_t prodext; 102 uint16_t flags; 103}; 104 105static const struct xe_pccard_product xe_pccard_products[] = { 106 { PCMCIA_CARD_D(COMPAQ, CPQ550), 0x43, XE_CARD_TYPE_FLAGS_CE2 }, 107 { PCMCIA_CARD_D(COMPAQ2, CPQ_10_100), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 108 { PCMCIA_CARD_D(INTEL, EEPRO100), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 109 { PCMCIA_CARD_D(INTEL, PRO100LAN56), 0x46, XE_CARD_TYPE_FLAGS_DINGO }, 110 { PCMCIA_CARD_D(RACORE, ACCTON_EN2226),0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 111 { PCMCIA_CARD_D(XIRCOM, CE), 0x41, XE_CARD_TYPE_FLAGS_NO }, 112 { PCMCIA_CARD_D(XIRCOM, CE2), 0x41, XE_CARD_TYPE_FLAGS_CE2 }, 113 { PCMCIA_CARD_D(XIRCOM, CE2), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 114 { PCMCIA_CARD_D(XIRCOM, CE2_2), 0x41, XE_CARD_TYPE_FLAGS_CE2 }, 115 { PCMCIA_CARD_D(XIRCOM, CE2_2), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 116 { PCMCIA_CARD_D(XIRCOM, CE3), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 117 { PCMCIA_CARD_D(XIRCOM, CEM), 0x41, XE_CARD_TYPE_FLAGS_NO }, 118 { PCMCIA_CARD_D(XIRCOM, CEM2), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 119 { PCMCIA_CARD_D(XIRCOM, CEM28), 0x43, XE_CARD_TYPE_FLAGS_CE2 }, 120 { PCMCIA_CARD_D(XIRCOM, CEM33), 0x44, XE_CARD_TYPE_FLAGS_CE2 }, 121 { PCMCIA_CARD_D(XIRCOM, CEM33_2), 0x44, XE_CARD_TYPE_FLAGS_CE2 }, 122 { PCMCIA_CARD_D(XIRCOM, CEM56), 0x45, XE_CARD_TYPE_FLAGS_DINGO }, 123 { PCMCIA_CARD_D(XIRCOM, CEM56_2), 0x46, XE_CARD_TYPE_FLAGS_DINGO }, 124 { PCMCIA_CARD_D(XIRCOM, REM56), 0x46, XE_CARD_TYPE_FLAGS_DINGO }, 125 { PCMCIA_CARD_D(XIRCOM, REM10), 0x47, XE_CARD_TYPE_FLAGS_DINGO }, 126 { PCMCIA_CARD_D(XIRCOM, XEM5600), 0x56, XE_CARD_TYPE_FLAGS_DINGO }, 127 { { NULL }, 0, 0 } 128}; 129 130 131/* 132 * Fixing for CEM2, CEM3 and CEM56/REM56 cards. These need some magic to 133 * enable the Ethernet function, which isn't mentioned anywhere in the CIS. 134 * Despite the register names, most of this isn't Dingo-specific. 135 */ 136static int 137xe_cemfix(device_t dev) 138{ 139 struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev); 140 bus_space_tag_t bst; 141 bus_space_handle_t bsh; 142 struct resource *r; 143 int rid; 144 int ioport; 145 146 DEVPRINTF(2, (dev, "cemfix\n")); 147 148 DEVPRINTF(1, (dev, "CEM I/O port 0x%0lx, size 0x%0lx\n", 149 bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid), 150 bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid))); 151 152 rid = 0; 153 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, 154 ~0, 4 << 10, RF_ACTIVE); 155 if (!r) { 156 device_printf(dev, "cemfix: Can't map in attribute memory\n"); 157 return (-1); 158 } 159 160 bsh = rman_get_bushandle(r); 161 bst = rman_get_bustag(r); 162 163 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid, 164 PCCARD_A_MEM_ATTR); 165 166 bus_space_write_1(bst, bsh, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL | 167 DINGO_ECOR_INT_ENABLE | 168 DINGO_ECOR_IOB_ENABLE | 169 DINGO_ECOR_ETH_ENABLE); 170 ioport = bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid); 171 bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff); 172 bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff); 173 174 if (sc->dingo) { 175 bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT); 176 bus_space_write_1(bst, bsh, DINGO_DCOR1, DINGO_DCOR1_INT_LEVEL | 177 DINGO_DCOR1_EEDIO); 178 bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00); 179 bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00); 180 bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00); 181 } 182 183 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 184 185 /* success! */ 186 return (0); 187} 188 189static int 190xe_pccard_product_match(device_t dev, const struct pccard_product* ent, int vpfmatch) 191{ 192 const struct xe_pccard_product* xpp; 193 uint16_t prodext; 194 195 if (vpfmatch == 0) 196 return (0); 197 198 xpp = (const struct xe_pccard_product*)ent; 199 pccard_get_prodext(dev, &prodext); 200 if (xpp->prodext != prodext) 201 vpfmatch = 0; 202 else 203 vpfmatch++; 204 return (vpfmatch); 205} 206 207static const struct xe_pccard_product * 208xe_pccard_get_product(device_t dev) 209{ 210 return ((const struct xe_pccard_product *) pccard_product_lookup(dev, 211 (const struct pccard_product *)xe_pccard_products, 212 sizeof(xe_pccard_products[0]), xe_pccard_product_match)); 213} 214 215/* 216 * Fixing for CE2-class cards with bogus CIS entry for MAC address. 217 */ 218static int 219xe_pccard_mac(const struct pccard_tuple *tuple, void *argp) 220{ 221 uint8_t *enaddr = argp, test; 222 int i; 223 224 /* Code 0x89 is Xircom special cis node contianing the MAC */ 225 if (tuple->code != 0x89) 226 return (0); 227 228 /* Make sure this is a sane node */ 229 if (tuple->length != ETHER_ADDR_LEN + 2) 230 return (0); 231 test = pccard_tuple_read_1(tuple, 0); 232 if (test != PCCARD_TPLFE_TYPE_LAN_NID) 233 return (0); 234 test = pccard_tuple_read_1(tuple, 1); 235 if (test != ETHER_ADDR_LEN) 236 return (0); 237 238 /* Copy the MAC ADDR and return success */ 239 for (i = 0; i < ETHER_ADDR_LEN; i++) 240 enaddr[i] = pccard_tuple_read_1(tuple, i + 2); 241 return (1); 242} 243 244static int 245xe_bad_mac(uint8_t *enaddr) 246{ 247 int i; 248 uint8_t sum; 249 250 for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) 251 sum |= enaddr[i]; 252 return (sum == 0); 253} 254 255/* 256 * PCMCIA attach routine. 257 * Identify the device. Called from the bus driver when the card is 258 * inserted or otherwise powers up. 259 */ 260static int 261xe_pccard_attach(device_t dev) 262{ 263 struct xe_softc *scp = (struct xe_softc *) device_get_softc(dev); 264 uint32_t vendor,product; 265 uint16_t prodext; 266 const char* vendor_str = NULL; 267 const char* product_str = NULL; 268 const char* cis4_str = NULL; 269 const char *cis3_str=NULL; 270 const struct xe_pccard_product *xpp; 271 int err; 272 device_t pdev; 273 274 DEVPRINTF(2, (dev, "pccard_attach\n")); 275 276 pccard_get_vendor(dev, &vendor); 277 pccard_get_product(dev, &product); 278 pccard_get_prodext(dev, &prodext); 279 pccard_get_vendor_str(dev, &vendor_str); 280 pccard_get_product_str(dev, &product_str); 281 pccard_get_cis3_str(dev, &cis3_str); 282 pccard_get_cis4_str(dev, &cis4_str); 283 284 DEVPRINTF(1, (dev, "vendor = 0x%04x\n", vendor)); 285 DEVPRINTF(1, (dev, "product = 0x%04x\n", product)); 286 DEVPRINTF(1, (dev, "prodext = 0x%02x\n", prodext)); 287 DEVPRINTF(1, (dev, "vendor_str = %s\n", vendor_str)); 288 DEVPRINTF(1, (dev, "product_str = %s\n", product_str)); 289 DEVPRINTF(1, (dev, "cis3_str = %s\n", cis3_str)); 290 DEVPRINTF(1, (dev, "cis4_str = %s\n", cis4_str)); 291 292 pdev = device_get_parent(dev); 293 xpp = xe_pccard_get_product(dev); 294 if (xpp == NULL) 295 return (ENXIO); 296 297 /* Set various card ID fields in softc */ 298 scp->vendor = vendor_str; 299 scp->card_type = product_str; 300 if (xpp->flags & XE_CARD_TYPE_FLAGS_CE2) 301 scp->ce2 = 1; 302 if (xpp->flags & XE_CARD_TYPE_FLAGS_MOHAWK) 303 scp->mohawk = 1; 304 if (xpp->flags & XE_CARD_TYPE_FLAGS_DINGO) { 305 scp->dingo = 1; 306 scp->mohawk = 1; 307 } 308 if (xpp->product.pp_product & XE_PROD_MODEM_MASK) 309 scp->modem = 1; 310 311 /* Get MAC address */ 312 pccard_get_ether(dev, scp->enaddr); 313 314 /* Deal with bogus MAC address */ 315 if (xe_bad_mac(scp->enaddr) 316 && !CARD_CIS_SCAN(pdev, xe_pccard_mac, scp->enaddr)) { 317 device_printf(dev, 318 "Unable to find MAC address for your %s card\n", 319 device_get_desc(dev)); 320 return (ENXIO); 321 } 322 323 if ((err = xe_activate(dev)) != 0) 324 return (err); 325 326 /* Hack RealPorts into submission */ 327 if (scp->modem && xe_cemfix(dev) < 0) { 328 device_printf(dev, "Unable to fix your %s combo card\n", 329 device_get_desc(dev)); 330 xe_deactivate(dev); 331 return (ENXIO); 332 } 333 if ((err = xe_attach(dev))) { 334 device_printf(dev, "xe_attach() failed! (%d)\n", err); 335 return (err); 336 } 337 return (0); 338} 339 340/* 341 * The device entry is being removed, probably because someone ejected the 342 * card. The interface should have been brought down manually before calling 343 * this function; if not you may well lose packets. In any case, I shut down 344 * the card and the interface, and hope for the best. 345 */ 346static int 347xe_pccard_detach(device_t dev) 348{ 349 struct xe_softc *sc = device_get_softc(dev); 350 351 DEVPRINTF(2, (dev, "pccard_detach\n")); 352 353 sc->ifp->if_flags &= ~IFF_RUNNING; 354 ether_ifdetach(sc->ifp); 355 if_free(sc->ifp); 356 xe_deactivate(dev); 357 return (0); 358} 359 360static int 361xe_pccard_probe(device_t dev) 362{ 363 const struct xe_pccard_product *xpp; 364 365 DEVPRINTF(2, (dev, "pccard_probe\n")); 366 367 /* 368 * Xircom cards aren't proper MFC cards, so we have to take all 369 * cards that match, not just ones that are network. 370 */ 371 372 /* If we match something in the table, it is our device. */ 373 if ((xpp = xe_pccard_get_product(dev)) == NULL) 374 return (ENXIO); 375 376 /* Set card name for logging later */ 377 if (xpp->product.pp_name != NULL) 378 device_set_desc(dev, xpp->product.pp_name); 379 380 /* Reject known but unsupported cards */ 381 if (xpp->flags & XE_CARD_TYPE_FLAGS_NO) { 382 device_printf(dev, "Sorry, your %s card is not supported :(\n", 383 device_get_desc(dev)); 384 return (ENXIO); 385 } 386 387 return (0); 388} 389 390static device_method_t xe_pccard_methods[] = { 391 /* Device interface */ 392 DEVMETHOD(device_probe, xe_pccard_probe), 393 DEVMETHOD(device_attach, xe_pccard_attach), 394 DEVMETHOD(device_detach, xe_pccard_detach), 395 396 { 0, 0 } 397}; 398 399static driver_t xe_pccard_driver = { 400 "xe", 401 xe_pccard_methods, 402 sizeof(struct xe_softc), 403}; 404 405devclass_t xe_devclass; 406 407DRIVER_MODULE(xe, pccard, xe_pccard_driver, xe_devclass, 0, 0); 408