if_xe_pccard.c revision 128070
1139749Simp/* 2136467Ssimokawa * Copyright (c) 2002 Takeshi Shibagaki 3121468Ssimokawa * All rights reserved. 4121468Ssimokawa * 5121468Ssimokawa * Redistribution and use in source and binary forms, with or without 6121468Ssimokawa * modification, are permitted provided that the following conditions 7121468Ssimokawa * are met: 8121468Ssimokawa * 1. Redistributions of source code must retain the above copyright 9121468Ssimokawa * notice, this list of conditions and the following disclaimer. 10121468Ssimokawa * 2. Redistributions in binary form must reproduce the above copyright 11121468Ssimokawa * notice, this list of conditions and the following disclaimer in the 12121468Ssimokawa * documentation and/or other materials provided with the distribution. 13121468Ssimokawa * 14121468Ssimokawa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND 15121468Ssimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16121468Ssimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17121468Ssimokawa * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18121468Ssimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19121468Ssimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20121468Ssimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21121468Ssimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22121468Ssimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23121468Ssimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24121468Ssimokawa * SUCH DAMAGE. 25121468Ssimokawa */ 26121468Ssimokawa 27121468Ssimokawa#include <sys/cdefs.h> 28121468Ssimokawa__FBSDID("$FreeBSD: head/sys/dev/xe/if_xe_pccard.c 128070 2004-04-09 17:34:54Z rsm $"); 29121468Ssimokawa 30121468Ssimokawa/* xe pccard interface driver */ 31121468Ssimokawa 32121468Ssimokawa#include <sys/param.h> 33121468Ssimokawa#include <sys/systm.h> 34121468Ssimokawa#include <sys/kernel.h> 35121468Ssimokawa#include <sys/socket.h> 36121468Ssimokawa 37121468Ssimokawa#include <sys/module.h> 38136781Ssimokawa#include <sys/bus.h> 39121468Ssimokawa 40121468Ssimokawa#include <machine/bus.h> 41121468Ssimokawa#include <machine/resource.h> 42121468Ssimokawa#include <sys/rman.h> 43121468Ssimokawa 44121468Ssimokawa#include <net/ethernet.h> 45121468Ssimokawa#include <net/if.h> 46121468Ssimokawa#include <net/if_arp.h> 47121468Ssimokawa#include <net/if_media.h> 48121468Ssimokawa#include <net/if_mib.h> 49121468Ssimokawa 50121468Ssimokawa 51121468Ssimokawa#include <dev/xe/if_xereg.h> 52121468Ssimokawa#include <dev/xe/if_xevar.h> 53121468Ssimokawa 54121468Ssimokawa#include <dev/pccard/pccardvar.h> 55121468Ssimokawa#include <dev/pccard/pccarddevs.h> 56121468Ssimokawa#include <dev/pccard/pccard_cis.h> 57121468Ssimokawa#include "card_if.h" 58121468Ssimokawa 59121468Ssimokawa/* 60121468Ssimokawa * Debug logging levels - set with hw.xe.debug sysctl 61121468Ssimokawa * 0 = None 62121468Ssimokawa * 1 = More hardware details, probe/attach progress 63121468Ssimokawa * 2 = Most function calls, ioctls and media selection progress 64121468Ssimokawa * 3 = Everything - interrupts, packets in/out and multicast address setup 65121468Ssimokawa */ 66121468Ssimokawa#define XE_DEBUG 67121468Ssimokawa#ifdef XE_DEBUG 68170420Ssimokawa 69170420Ssimokawaextern int xe_debug; 70121468Ssimokawa 71121468Ssimokawa#define DEVPRINTF(level, arg) if (xe_debug >= (level)) device_printf arg 72121468Ssimokawa#define DPRINTF(level, arg) if (xe_debug >= (level)) printf arg 73121468Ssimokawa#else 74121468Ssimokawa#define DEVPRINTF(level, arg) 75121468Ssimokawa#define DPRINTF(level, arg) 76121468Ssimokawa#endif 77121468Ssimokawa 78121468Ssimokawa 79136781Ssimokawa#define XE_CARD_TYPE_FLAGS_NO 0x0 80121468Ssimokawa#define XE_CARD_TYPE_FLAGS_CE2 0x1 81121468Ssimokawa#define XE_CARD_TYPE_FLAGS_MOHAWK 0x2 82121468Ssimokawa#define XE_CARD_TYPE_FLAGS_DINGO 0x4 83121468Ssimokawa#define XE_PROD_ETHER_MASK 0x0100 84121468Ssimokawa#define XE_PROD_MODEM_MASK 0x1000 85121468Ssimokawa 86121468Ssimokawa#define XE_BOGUS_MAC_OFFSET 0x90 87121468Ssimokawa 88121468Ssimokawa/* MAC vendor prefix used by most Xircom cards is 00:80:c7 */ 89121468Ssimokawa#define XE_MAC_ADDR_0 0x00 90121468Ssimokawa#define XE_MAC_ADDR_1 0x80 91121468Ssimokawa#define XE_MAC_ADDR_2 0xc7 92121468Ssimokawa 93170420Ssimokawa/* Some (all?) REM56 cards have vendor prefix 00:10:a4 */ 94121468Ssimokawa#define XE_REM56_MAC_ADDR_0 0x00 95136781Ssimokawa#define XE_REM56_MAC_ADDR_1 0x10 96136467Ssimokawa#define XE_REM56_MAC_ADDR_2 0xa4 97136467Ssimokawa 98136467Ssimokawa 99136467Ssimokawastruct xe_pccard_product { 100136467Ssimokawa struct pccard_product product; 101181905Sed u_int16_t prodext; 102125862Ssimokawa u_int16_t flags; 103136467Ssimokawa}; 104136467Ssimokawa 105136467Ssimokawastatic const struct xe_pccard_product xe_pccard_products[] = { 106136467Ssimokawa { PCMCIA_CARD_D(ACCTON, EN2226, 0), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 107136467Ssimokawa { PCMCIA_CARD_D(COMPAQ2, CPQ_10_100, 0), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 108136467Ssimokawa { PCMCIA_CARD_D(INTEL, EEPRO100, 0), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 109121468Ssimokawa { PCMCIA_CARD_D(XIRCOM, CE, 0), 0x41, XE_CARD_TYPE_FLAGS_NO }, 110 { PCMCIA_CARD_D(XIRCOM, CE2, 0), 0x41, XE_CARD_TYPE_FLAGS_CE2 }, 111 { PCMCIA_CARD_D(XIRCOM, CE2, 0), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 112 { PCMCIA_CARD_D(XIRCOM, CE2_2, 0), 0x41, XE_CARD_TYPE_FLAGS_CE2 }, 113 { PCMCIA_CARD_D(XIRCOM, CE2_2, 0), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 114 { PCMCIA_CARD_D(XIRCOM, CE3, 0), 0x43, XE_CARD_TYPE_FLAGS_MOHAWK }, 115 { PCMCIA_CARD_D(XIRCOM, CEM, 0), 0x41, XE_CARD_TYPE_FLAGS_NO }, 116 { PCMCIA_CARD_D(XIRCOM, CEM2, 0), 0x42, XE_CARD_TYPE_FLAGS_CE2 }, 117 { PCMCIA_CARD_D(XIRCOM, CEM28, 0), 0x43, XE_CARD_TYPE_FLAGS_CE2 }, 118 { PCMCIA_CARD_D(XIRCOM, CEM33, 0), 0x44, XE_CARD_TYPE_FLAGS_CE2 }, 119 { PCMCIA_CARD_D(XIRCOM, CEM33_2, 0), 0x44, XE_CARD_TYPE_FLAGS_CE2 }, 120 { PCMCIA_CARD_D(XIRCOM, CEM56, 0), 0x45, XE_CARD_TYPE_FLAGS_DINGO }, 121 { PCMCIA_CARD_D(XIRCOM, CEM56_2, 0), 0x46, XE_CARD_TYPE_FLAGS_DINGO }, 122 { PCMCIA_CARD_D(XIRCOM, REM56, 0), 0x46, XE_CARD_TYPE_FLAGS_DINGO }, 123 { PCMCIA_CARD_D(XIRCOM, REM10, 0), 0x47, XE_CARD_TYPE_FLAGS_DINGO }, 124 { PCMCIA_CARD_D(XIRCOM, XEM5600, 0), 0x56, XE_CARD_TYPE_FLAGS_DINGO }, 125 { { NULL }, 0, 0 } 126}; 127 128 129/* 130 * Fixing for CEM2, CEM3 and CEM56/REM56 cards. These need some magic to 131 * enable the Ethernet function, which isn't mentioned anywhere in the CIS. 132 * Despite the register names, most of this isn't Dingo-specific. 133 */ 134static int 135xe_cemfix(device_t dev) 136{ 137 struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev); 138 bus_space_tag_t bst; 139 bus_space_handle_t bsh; 140 struct resource *r; 141 int rid; 142 int ioport; 143 144 DEVPRINTF(2, (dev, "cemfix\n")); 145 146 DEVPRINTF(1, (dev, "CEM I/O port 0x%0lx, size 0x%0lx\n", 147 bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid), 148 bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid))); 149 150 rid = 0; 151 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, 152 ~0, 4 << 10, RF_ACTIVE); 153 if (!r) { 154 device_printf(dev, "cemfix: Can't map in attribute memory\n"); 155 return (-1); 156 } 157 158 bsh = rman_get_bushandle(r); 159 bst = rman_get_bustag(r); 160 161 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid, 162 PCCARD_A_MEM_ATTR); 163 164 bus_space_write_1(bst, bsh, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL | 165 DINGO_ECOR_INT_ENABLE | 166 DINGO_ECOR_IOB_ENABLE | 167 DINGO_ECOR_ETH_ENABLE); 168 ioport = bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid); 169 bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff); 170 bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff); 171 172 if (sc->dingo) { 173 bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT); 174 bus_space_write_1(bst, bsh, DINGO_DCOR1, DINGO_DCOR1_INT_LEVEL | 175 DINGO_DCOR1_EEDIO); 176 bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00); 177 bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00); 178 bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00); 179 } 180 181 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 182 183 /* success! */ 184 return (0); 185} 186 187/* 188 * Fixing for CE2-class cards with bogus CIS entry for MAC address. This 189 * should be in a type 0x22 tuple, but some cards seem to use 0x89. 190 * This function looks for a sensible MAC address tuple starting at the given 191 * offset in attribute memory, ignoring the tuple type field. 192 */ 193static int 194xe_macfix(device_t dev, int offset) 195{ 196 struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev); 197 bus_space_tag_t bst; 198 bus_space_handle_t bsh; 199 struct resource *r; 200 int rid, i; 201 u_int8_t cisdata[9]; 202 u_int8_t required[6] = { 0x08, PCCARD_TPLFE_TYPE_LAN_NID, ETHER_ADDR_LEN, 203 XE_MAC_ADDR_0, XE_MAC_ADDR_1, XE_MAC_ADDR_2 }; 204 205 DEVPRINTF(2, (dev, "macfix\n")); 206 207 rid = 0; 208 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, 209 ~0, 4 << 10, RF_ACTIVE); 210 if (!r) { 211 device_printf(dev, "macfix: Can't map in attribute memory\n"); 212 return (-1); 213 } 214 215 bsh = rman_get_bushandle(r); 216 bst = rman_get_bustag(r); 217 218 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid, 219 PCCARD_A_MEM_ATTR); 220 221 /* 222 * Looking for (relative to offset): 223 * 224 * 0x00 0x?? Tuple type (ignored) 225 * 0x02 0x08 Tuple length (must be 8) 226 * 0x04 0x04 Address type? (must be 4) 227 * 0x06 0x06 Address length (must be 6) 228 * 0x08 0x00 Manufacturer ID, byte 1 229 * 0x0a 0x80 Manufacturer ID, byte 2 230 * 0x0c 0xc7 Manufacturer ID, byte 3 231 * 0x0e 0x?? Card ID, byte 1 232 * 0x10 0x?? Card ID, byte 2 233 * 0x12 0x?? Card ID, byte 3 234 */ 235 for (i = 0; i < 9; i++) { 236 cisdata[i] = bus_space_read_1(bst, bsh, offset + (2 * i) + 2); 237 if (i < 6 && required[i] != cisdata[i]) { 238 device_printf(dev, "macfix: Can't find valid MAC address\n"); 239 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 240 return (-1); 241 } 242 } 243 244 for (i = 0; i < ETHER_ADDR_LEN; i++) { 245 sc->arpcom.ac_enaddr[i] = cisdata[i + 3]; 246 } 247 248 bus_release_resource(dev, SYS_RES_MEMORY, rid, r); 249 250 /* success! */ 251 return (0); 252} 253 254/* 255 * PCMCIA probe routine. 256 * Identify the device. Called from the bus driver when the card is 257 * inserted or otherwise powers up. 258 */ 259static int 260xe_pccard_probe(device_t dev) 261{ 262 struct xe_softc *scp = (struct xe_softc *) device_get_softc(dev); 263 u_int32_t vendor,product; 264 u_int16_t prodext; 265 const char* vendor_str = NULL; 266 const char* product_str = NULL; 267 const char* cis4_str = NULL; 268 const char *cis3_str=NULL; 269 const struct xe_pccard_product *xpp; 270 271 DEVPRINTF(2, (dev, "pccard_probe\n")); 272 273 pccard_get_vendor(dev, &vendor); 274 pccard_get_product(dev, &product); 275 pccard_get_prodext(dev, &prodext); 276 pccard_get_vendor_str(dev, &vendor_str); 277 pccard_get_product_str(dev, &product_str); 278 pccard_get_cis3_str(dev, &cis3_str); 279 pccard_get_cis4_str(dev, &cis4_str); 280 281 DEVPRINTF(1, (dev, "vendor = 0x%04x\n", vendor)); 282 DEVPRINTF(1, (dev, "product = 0x%04x\n", product)); 283 DEVPRINTF(1, (dev, "prodext = 0x%02x\n", prodext)); 284 DEVPRINTF(1, (dev, "vendor_str = %s\n", vendor_str)); 285 DEVPRINTF(1, (dev, "product_str = %s\n", product_str)); 286 DEVPRINTF(1, (dev, "cis3_str = %s\n", cis3_str)); 287 DEVPRINTF(1, (dev, "cis4_str = %s\n", cis4_str)); 288 289 290 /* 291 * Possibly already did this search in xe_pccard_match(), 292 * but we need to do it here anyway to figure out which 293 * card we have. 294 */ 295 for (xpp = xe_pccard_products; xpp->product.pp_vendor != 0; xpp++) { 296 if (vendor == xpp->product.pp_vendor && 297 product == xpp->product.pp_product && 298 prodext == xpp->prodext) 299 break; 300 } 301 302 /* Found a match? */ 303 if (xpp->product.pp_vendor == 0) 304 return (ENODEV); 305 306 307 /* Set card name for logging later */ 308 if (xpp->product.pp_name != NULL) 309 device_set_desc(dev, xpp->product.pp_name); 310 311 /* Reject known but unsupported cards */ 312 if (xpp->flags & XE_CARD_TYPE_FLAGS_NO) { 313 device_printf(dev, "Sorry, your %s %s card is not supported :(\n", 314 vendor_str, product_str); 315 return (ENODEV); 316 } 317 318 /* Set various card ID fields in softc */ 319 scp->vendor = vendor_str; 320 scp->card_type = product_str; 321 if (xpp->flags & XE_CARD_TYPE_FLAGS_CE2) 322 scp->ce2 = 1; 323 if (xpp->flags & XE_CARD_TYPE_FLAGS_MOHAWK) 324 scp->mohawk = 1; 325 if (xpp->flags & XE_CARD_TYPE_FLAGS_DINGO) { 326 scp->dingo = 1; 327 scp->mohawk = 1; 328 } 329 if (xpp->product.pp_product & XE_PROD_MODEM_MASK) 330 scp->modem = 1; 331 332 /* Get MAC address */ 333 pccard_get_ether(dev, scp->arpcom.ac_enaddr); 334 335 /* Deal with bogus MAC address */ 336 if (xpp->product.pp_vendor == PCMCIA_VENDOR_XIRCOM 337 && scp->ce2 338 && (scp->arpcom.ac_enaddr[0] != XE_MAC_ADDR_0 339 || scp->arpcom.ac_enaddr[1] != XE_MAC_ADDR_1 340 || scp->arpcom.ac_enaddr[2] != XE_MAC_ADDR_2) 341 && xe_macfix(dev, XE_BOGUS_MAC_OFFSET) < 0) { 342 device_printf(dev, 343 "Unable to find MAC address for your %s card\n", 344 scp->card_type); 345 return (ENODEV); 346 } 347 348 /* Success */ 349 return (0); 350} 351 352/* 353 * Attach a device. 354 */ 355static int 356xe_pccard_attach(device_t dev) 357{ 358 struct xe_softc *scp = device_get_softc(dev); 359 int err; 360 361 DEVPRINTF(2, (dev, "pccard_attach\n")); 362 363 if ((err = xe_activate(dev)) != 0) 364 return (err); 365 366 /* Hack RealPorts into submission */ 367 if (scp->modem && xe_cemfix(dev) < 0) { 368 device_printf(dev, "Unable to fix your %s %s combo card\n", 369 scp->vendor, scp->card_type); 370 xe_deactivate(dev); 371 return (ENODEV); 372 } 373 if ((err = xe_attach(dev))) { 374 device_printf(dev, "xe_attach() failed! (%d)\n", err); 375 return (err); 376 } 377 return (0); 378} 379 380/* 381 * The device entry is being removed, probably because someone ejected the 382 * card. The interface should have been brought down manually before calling 383 * this function; if not you may well lose packets. In any case, I shut down 384 * the card and the interface, and hope for the best. 385 */ 386static int 387xe_pccard_detach(device_t dev) 388{ 389 struct xe_softc *sc = device_get_softc(dev); 390 391 DEVPRINTF(2, (dev, "pccard_detach\n")); 392 393 sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; 394 ether_ifdetach(&sc->arpcom.ac_if); 395 xe_deactivate(dev); 396 return (0); 397} 398 399static int 400xe_pccard_product_match(device_t dev, const struct pccard_product* ent, int vpfmatch) 401{ 402 const struct xe_pccard_product* xpp; 403 u_int16_t prodext; 404 405 DEVPRINTF(2, (dev, "pccard_product_match\n")); 406 407 xpp = (const struct xe_pccard_product*)ent; 408 pccard_get_prodext(dev, &prodext); 409 410 if (xpp->prodext != prodext) 411 vpfmatch--; 412 413 return (vpfmatch); 414} 415 416static int 417xe_pccard_match(device_t dev) 418{ 419 const struct pccard_product *pp; 420 421 DEVPRINTF(2, (dev, "pccard_match\n")); 422 423 pp = (const struct pccard_product*)xe_pccard_products; 424 425 if ((pp = pccard_product_lookup(dev, pp, 426 sizeof(xe_pccard_products[0]), xe_pccard_product_match)) != NULL) 427 return (0); 428 429 return (EIO); 430} 431 432static device_method_t xe_pccard_methods[] = { 433 /* Device interface */ 434 DEVMETHOD(device_probe, pccard_compat_probe), 435 DEVMETHOD(device_attach, pccard_compat_attach), 436 DEVMETHOD(device_detach, xe_pccard_detach), 437 438 /* Card interface */ 439 DEVMETHOD(card_compat_match, xe_pccard_match), 440 DEVMETHOD(card_compat_probe, xe_pccard_probe), 441 DEVMETHOD(card_compat_attach, xe_pccard_attach), 442 443 { 0, 0 } 444}; 445 446static driver_t xe_pccard_driver = { 447 "xe", 448 xe_pccard_methods, 449 sizeof(struct xe_softc), 450}; 451 452devclass_t xe_devclass; 453 454DRIVER_MODULE(xe, pccard, xe_pccard_driver, xe_devclass, 0, 0); 455