if_xe_pccard.c revision 140521
1132718Skan/*- 290075Sobrien * Copyright (c) 2002 Takeshi Shibagaki 390075Sobrien * All rights reserved. 490075Sobrien * 590075Sobrien * Redistribution and use in source and binary forms, with or without 690075Sobrien * modification, are permitted provided that the following conditions 790075Sobrien * are met: 890075Sobrien * 1. Redistributions of source code must retain the above copyright 990075Sobrien * notice, this list of conditions and the following disclaimer. 1090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1190075Sobrien * notice, this list of conditions and the following disclaimer in the 1290075Sobrien * documentation and/or other materials provided with the distribution. 1390075Sobrien * 1490075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND 1590075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1690075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1790075Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1890075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1990075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2090075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2190075Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2290075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2390075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2490075Sobrien * SUCH DAMAGE. 2590075Sobrien */ 2690075Sobrien 2790075Sobrien#include <sys/cdefs.h> 2890075Sobrien__FBSDID("$FreeBSD: head/sys/dev/xe/if_xe_pccard.c 140521 2005-01-20 19:32:37Z imp $"); 2990075Sobrien 3090075Sobrien/* xe pccard interface driver */ 3190075Sobrien 3290075Sobrien#include <sys/param.h> 3390075Sobrien#include <sys/bus.h> 3490075Sobrien#include <sys/kernel.h> 3590075Sobrien#include <sys/module.h> 3690075Sobrien#include <sys/socket.h> 37132718Skan#include <sys/systm.h> 38132718Skan 3990075Sobrien#include <machine/bus.h> 4090075Sobrien#include <machine/resource.h> 4190075Sobrien#include <sys/rman.h> 4290075Sobrien 4390075Sobrien#include <net/ethernet.h> 4490075Sobrien#include <net/if.h> 4590075Sobrien#include <net/if_arp.h> 4690075Sobrien#include <net/if_media.h> 4790075Sobrien#include <net/if_mib.h> 4890075Sobrien 4990075Sobrien 5090075Sobrien#include <dev/xe/if_xereg.h> 5190075Sobrien#include <dev/xe/if_xevar.h> 5290075Sobrien 5390075Sobrien#include <dev/pccard/pccardvar.h> 5490075Sobrien#include <dev/pccard/pccard_cis.h> 5590075Sobrien 5690075Sobrien#include "card_if.h" 5790075Sobrien#include "pccarddevs.h" 5890075Sobrien 5990075Sobrien/* 6090075Sobrien * Debug logging levels - set with hw.xe.debug sysctl 6190075Sobrien * 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(ACCTON, EN2226, 0), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 107 { PCMCIA_CARD_D(COMPAQ2, CPQ_10_100, 0), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 108 { PCMCIA_CARD_D(INTEL, EEPRO100, 0), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 109 { PCMCIA_CARD_D(INTEL, PRO100LAN56, 0), 0x46, XE_CARD_TYPE_FLAGS_DINGO }, 110 { PCMCIA_CARD_D(XIRCOM, CE, 0), 0x41, XE_CARD_TYPE_FLAGS_NO }, 111 { PCMCIA_CARD_D(XIRCOM, CE2, 0), 0x41, XE_CARD_TYPE_FLAGS_CE2 }, 112 { PCMCIA_CARD_D(XIRCOM, CE2, 0), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 113 { PCMCIA_CARD_D(XIRCOM, CE2_2, 0), 0x41, XE_CARD_TYPE_FLAGS_CE2 }, 114 { PCMCIA_CARD_D(XIRCOM, CE2_2, 0), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 115 { PCMCIA_CARD_D(XIRCOM, CE3, 0), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 116 { PCMCIA_CARD_D(XIRCOM, CEM, 0), 0x41, XE_CARD_TYPE_FLAGS_NO }, 117 { PCMCIA_CARD_D(XIRCOM, CEM2, 0), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 118 { PCMCIA_CARD_D(XIRCOM, CEM28, 0), 0x43, XE_CARD_TYPE_FLAGS_CE2 }, 119 { PCMCIA_CARD_D(XIRCOM, CEM33, 0), 0x44, XE_CARD_TYPE_FLAGS_CE2 }, 120 { PCMCIA_CARD_D(XIRCOM, CEM33_2, 0), 0x44, XE_CARD_TYPE_FLAGS_CE2 }, 121 { PCMCIA_CARD_D(XIRCOM, CEM56, 0), 0x45, XE_CARD_TYPE_FLAGS_DINGO }, 122 { PCMCIA_CARD_D(XIRCOM, CEM56_2, 0), 0x46, XE_CARD_TYPE_FLAGS_DINGO }, 123 { PCMCIA_CARD_D(XIRCOM, REM56, 0), 0x46, XE_CARD_TYPE_FLAGS_DINGO }, 124 { PCMCIA_CARD_D(XIRCOM, REM10, 0), 0x47, XE_CARD_TYPE_FLAGS_DINGO }, 125 { PCMCIA_CARD_D(XIRCOM, XEM5600, 0), 0x56, XE_CARD_TYPE_FLAGS_DINGO }, 126 { { NULL }, 0, 0 } 127}; 128 129 130/* 131 * Fixing for CEM2, CEM3 and CEM56/REM56 cards. These need some magic to 132 * enable the Ethernet function, which isn't mentioned anywhere in the CIS. 133 * Despite the register names, most of this isn't Dingo-specific. 134 */ 135static int 136xe_cemfix(device_t dev) 137{ 138 struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev); 139 bus_space_tag_t bst; 140 bus_space_handle_t bsh; 141 struct resource *r; 142 int rid; 143 int ioport; 144 145 DEVPRINTF(2, (dev, "cemfix\n")); 146 147 DEVPRINTF(1, (dev, "CEM I/O port 0x%0lx, size 0x%0lx\n", 148 bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid), 149 bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid))); 150 151 rid = 0; 152 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, 153 ~0, 4 << 10, RF_ACTIVE); 154 if (!r) { 155 device_printf(dev, "cemfix: Can't map in attribute memory\n"); 156 return (-1); 157 } 158 159 bsh = rman_get_bushandle(r); 160 bst = rman_get_bustag(r); 161 162 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid, 163 PCCARD_A_MEM_ATTR); 164 165 bus_space_write_1(bst, bsh, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL | 166 DINGO_ECOR_INT_ENABLE | 167 DINGO_ECOR_IOB_ENABLE | 168 DINGO_ECOR_ETH_ENABLE); 169 ioport = bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid); 170 bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff); 171 bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff); 172 173 if (sc->dingo) { 174 bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT); 175 bus_space_write_1(bst, bsh, DINGO_DCOR1, DINGO_DCOR1_INT_LEVEL | 176 DINGO_DCOR1_EEDIO); 177 bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00); 178 bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00); 179 bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00); 180 } 181 182 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 183 184 /* success! */ 185 return (0); 186} 187 188/* 189 * Fixing for CE2-class cards with bogus CIS entry for MAC address. This 190 * should be in a type 0x22 tuple, but some cards seem to use 0x89. 191 * This function looks for a sensible MAC address tuple starting at the given 192 * offset in attribute memory, ignoring the tuple type field. 193 */ 194static int 195xe_macfix(device_t dev, int offset) 196{ 197 struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev); 198 bus_space_tag_t bst; 199 bus_space_handle_t bsh; 200 struct resource *r; 201 int rid, i; 202 uint8_t cisdata[9]; 203 uint8_t required[6] = { 0x08, PCCARD_TPLFE_TYPE_LAN_NID, ETHER_ADDR_LEN, 204 XE_MAC_ADDR_0, XE_MAC_ADDR_1, XE_MAC_ADDR_2 }; 205 206 DEVPRINTF(2, (dev, "macfix\n")); 207 208 rid = 0; 209 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, 210 ~0, 4 << 10, RF_ACTIVE); 211 if (!r) { 212 device_printf(dev, "macfix: Can't map in attribute memory\n"); 213 return (-1); 214 } 215 216 bsh = rman_get_bushandle(r); 217 bst = rman_get_bustag(r); 218 219 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid, 220 PCCARD_A_MEM_ATTR); 221 222 /* 223 * Looking for (relative to offset): 224 * 225 * 0x00 0x?? Tuple type (ignored) 226 * 0x02 0x08 Tuple length (must be 8) 227 * 0x04 0x04 Address type? (must be 4) 228 * 0x06 0x06 Address length (must be 6) 229 * 0x08 0x00 Manufacturer ID, byte 1 230 * 0x0a 0x80 Manufacturer ID, byte 2 231 * 0x0c 0xc7 Manufacturer ID, byte 3 232 * 0x0e 0x?? Card ID, byte 1 233 * 0x10 0x?? Card ID, byte 2 234 * 0x12 0x?? Card ID, byte 3 235 */ 236 for (i = 0; i < 9; i++) { 237 cisdata[i] = bus_space_read_1(bst, bsh, offset + (2 * i) + 2); 238 if (i < 6 && required[i] != cisdata[i]) { 239 device_printf(dev, "macfix: Can't find valid MAC address\n"); 240 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 241 return (-1); 242 } 243 } 244 245 for (i = 0; i < ETHER_ADDR_LEN; i++) { 246 sc->arpcom.ac_enaddr[i] = cisdata[i + 3]; 247 } 248 249 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 250 251 /* success! */ 252 return (0); 253} 254 255/* 256 * PCMCIA probe 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_probe(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 272 DEVPRINTF(2, (dev, "pccard_probe\n")); 273 274 pccard_get_vendor(dev, &vendor); 275 pccard_get_product(dev, &product); 276 pccard_get_prodext(dev, &prodext); 277 pccard_get_vendor_str(dev, &vendor_str); 278 pccard_get_product_str(dev, &product_str); 279 pccard_get_cis3_str(dev, &cis3_str); 280 pccard_get_cis4_str(dev, &cis4_str); 281 282 DEVPRINTF(1, (dev, "vendor = 0x%04x\n", vendor)); 283 DEVPRINTF(1, (dev, "product = 0x%04x\n", product)); 284 DEVPRINTF(1, (dev, "prodext = 0x%02x\n", prodext)); 285 DEVPRINTF(1, (dev, "vendor_str = %s\n", vendor_str)); 286 DEVPRINTF(1, (dev, "product_str = %s\n", product_str)); 287 DEVPRINTF(1, (dev, "cis3_str = %s\n", cis3_str)); 288 DEVPRINTF(1, (dev, "cis4_str = %s\n", cis4_str)); 289 290 291 /* 292 * Possibly already did this search in xe_pccard_match(), 293 * but we need to do it here anyway to figure out which 294 * card we have. 295 */ 296 for (xpp = xe_pccard_products; xpp->product.pp_vendor != 0; xpp++) { 297 if (vendor == xpp->product.pp_vendor && 298 product == xpp->product.pp_product && 299 prodext == xpp->prodext) 300 break; 301 } 302 303 /* Found a match? */ 304 if (xpp->product.pp_vendor == 0) 305 return (ENODEV); 306 307 308 /* Set card name for logging later */ 309 if (xpp->product.pp_name != NULL) 310 device_set_desc(dev, xpp->product.pp_name); 311 312 /* Reject known but unsupported cards */ 313 if (xpp->flags & XE_CARD_TYPE_FLAGS_NO) { 314 device_printf(dev, "Sorry, your %s %s card is not supported :(\n", 315 vendor_str, product_str); 316 return (ENODEV); 317 } 318 319 /* Set various card ID fields in softc */ 320 scp->vendor = vendor_str; 321 scp->card_type = product_str; 322 if (xpp->flags & XE_CARD_TYPE_FLAGS_CE2) 323 scp->ce2 = 1; 324 if (xpp->flags & XE_CARD_TYPE_FLAGS_MOHAWK) 325 scp->mohawk = 1; 326 if (xpp->flags & XE_CARD_TYPE_FLAGS_DINGO) { 327 scp->dingo = 1; 328 scp->mohawk = 1; 329 } 330 if (xpp->product.pp_product & XE_PROD_MODEM_MASK) 331 scp->modem = 1; 332 333 /* Get MAC address */ 334 pccard_get_ether(dev, scp->arpcom.ac_enaddr); 335 336 /* Deal with bogus MAC address */ 337 if (xpp->product.pp_vendor == PCMCIA_VENDOR_XIRCOM 338 && scp->ce2 339 && (scp->arpcom.ac_enaddr[0] != XE_MAC_ADDR_0 340 || scp->arpcom.ac_enaddr[1] != XE_MAC_ADDR_1 341 || scp->arpcom.ac_enaddr[2] != XE_MAC_ADDR_2) 342 && xe_macfix(dev, XE_BOGUS_MAC_OFFSET) < 0) { 343 device_printf(dev, 344 "Unable to find MAC address for your %s card\n", 345 scp->card_type); 346 return (ENODEV); 347 } 348 349 /* Success */ 350 return (0); 351} 352 353/* 354 * Attach a device. 355 */ 356static int 357xe_pccard_attach(device_t dev) 358{ 359 struct xe_softc *scp = device_get_softc(dev); 360 int err; 361 362 DEVPRINTF(2, (dev, "pccard_attach\n")); 363 364 if ((err = xe_activate(dev)) != 0) 365 return (err); 366 367 /* Hack RealPorts into submission */ 368 if (scp->modem && xe_cemfix(dev) < 0) { 369 device_printf(dev, "Unable to fix your %s %s combo card\n", 370 scp->vendor, scp->card_type); 371 xe_deactivate(dev); 372 return (ENODEV); 373 } 374 if ((err = xe_attach(dev))) { 375 device_printf(dev, "xe_attach() failed! (%d)\n", err); 376 return (err); 377 } 378 return (0); 379} 380 381/* 382 * The device entry is being removed, probably because someone ejected the 383 * card. The interface should have been brought down manually before calling 384 * this function; if not you may well lose packets. In any case, I shut down 385 * the card and the interface, and hope for the best. 386 */ 387static int 388xe_pccard_detach(device_t dev) 389{ 390 struct xe_softc *sc = device_get_softc(dev); 391 392 DEVPRINTF(2, (dev, "pccard_detach\n")); 393 394 sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; 395 ether_ifdetach(&sc->arpcom.ac_if); 396 xe_deactivate(dev); 397 return (0); 398} 399 400static int 401xe_pccard_product_match(device_t dev, const struct pccard_product* ent, int vpfmatch) 402{ 403 const struct xe_pccard_product* xpp; 404 uint16_t prodext; 405 406 DEVPRINTF(2, (dev, "pccard_product_match\n")); 407 408 xpp = (const struct xe_pccard_product*)ent; 409 pccard_get_prodext(dev, &prodext); 410 411 if (xpp->prodext != prodext) 412 vpfmatch = 0; 413 else 414 vpfmatch++; 415 416 return (vpfmatch); 417} 418 419static int 420xe_pccard_match(device_t dev) 421{ 422 int error = 0; 423 uint32_t fcn = PCCARD_FUNCTION_UNSPEC; 424 const struct pccard_product *pp; 425 426 DEVPRINTF(2, (dev, "pccard_match\n")); 427 428 /* Make sure we're a network function */ 429 error = pccard_get_function(dev, &fcn); 430 if (error != 0) 431 return (error); 432 if (fcn != PCCARD_FUNCTION_NETWORK) 433 return (ENXIO); 434 435 /* If we match something in the table, it is our device. */ 436 pp = (const struct pccard_product *)xe_pccard_products; 437 if ((pp = pccard_product_lookup(dev, pp, 438 sizeof(xe_pccard_products[0]), xe_pccard_product_match)) != NULL) 439 return (0); 440 441 return (EIO); 442} 443 444static device_method_t xe_pccard_methods[] = { 445 /* Device interface */ 446 DEVMETHOD(device_probe, pccard_compat_probe), 447 DEVMETHOD(device_attach, pccard_compat_attach), 448 DEVMETHOD(device_detach, xe_pccard_detach), 449 450 /* Card interface */ 451 DEVMETHOD(card_compat_match, xe_pccard_match), 452 DEVMETHOD(card_compat_probe, xe_pccard_probe), 453 DEVMETHOD(card_compat_attach, xe_pccard_attach), 454 455 { 0, 0 } 456}; 457 458static driver_t xe_pccard_driver = { 459 "xe", 460 xe_pccard_methods, 461 sizeof(struct xe_softc), 462}; 463 464devclass_t xe_devclass; 465 466DRIVER_MODULE(xe, pccard, xe_pccard_driver, xe_devclass, 0, 0); 467