if_ed_pccard.c revision 104857
1/* 2 * Copyright (c) 1995, David Greenman 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: head/sys/dev/ed/if_ed_pccard.c 104857 2002-10-11 07:03:09Z imp $ 28 */ 29 30#include "opt_ed.h" 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/socket.h> 35#include <sys/kernel.h> 36#include <sys/conf.h> 37#include <sys/uio.h> 38 39#include <sys/module.h> 40#include <sys/bus.h> 41#include <machine/bus.h> 42#include <sys/rman.h> 43#include <machine/resource.h> 44 45#include <net/ethernet.h> 46#include <net/if.h> 47#include <net/if_arp.h> 48#include <net/if_mib.h> 49#include <net/if_media.h> 50 51#include <dev/ed/if_edreg.h> 52#include <dev/ed/if_edvar.h> 53#include <dev/pccard/pccardvar.h> 54#include <dev/pccard/pccarddevs.h> 55#ifndef ED_NO_MIIBUS 56#include <dev/mii/mii.h> 57#include <dev/mii/miivar.h> 58#endif 59 60#include "card_if.h" 61#ifndef ED_NO_MIIBUS 62/* "device miibus" required. See GENERIC if you get errors here. */ 63#include "miibus_if.h" 64 65MODULE_DEPEND(ed, miibus, 1, 1, 1); 66#endif 67 68/* 69 * PC-Card (PCMCIA) specific code. 70 */ 71static int ed_pccard_match(device_t); 72static int ed_pccard_probe(device_t); 73static int ed_pccard_attach(device_t); 74static int ed_pccard_detach(device_t); 75 76static int ed_pccard_Linksys(device_t dev); 77static int ed_pccard_ax88190(device_t dev); 78 79static void ax88190_geteprom(struct ed_softc *); 80static int ed_pccard_memwrite(device_t dev, off_t offset, u_char byte); 81#ifndef ED_NO_MIIBUS 82static void ed_pccard_dlink_mii_reset(struct ed_softc *sc); 83static u_int ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits); 84static void ed_pccard_dlink_mii_writebits(struct ed_softc *sc, u_int val, 85 int nbits); 86#endif 87 88/* 89 * ed_pccard_detach - unload the driver and clear the table. 90 * XXX TODO: 91 * This is usually called when the card is ejected, but 92 * can be caused by a modunload of a controller driver. 93 * The idea is to reset the driver's view of the device 94 * and ensure that any driver entry points such as 95 * read and write do not hang. 96 */ 97static int 98ed_pccard_detach(device_t dev) 99{ 100 struct ed_softc *sc = device_get_softc(dev); 101 struct ifnet *ifp = &sc->arpcom.ac_if; 102 103 if (sc->gone) { 104 device_printf(dev, "already unloaded\n"); 105 return (0); 106 } 107 ed_stop(sc); 108 ifp->if_flags &= ~IFF_RUNNING; 109 ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); 110 sc->gone = 1; 111 bus_teardown_intr(dev, sc->irq_res, sc->irq_handle); 112 ed_release_resources(dev); 113 return (0); 114} 115 116static const struct ed_product { 117 struct pccard_product prod; 118 int enet_maddr; 119 unsigned char enet_vendor[3]; 120 int flags; 121#define NE2000DVF_DL10019 0x0001 /* chip is D-Link DL10019 */ 122#define NE2000DVF_AX88190 0x0002 /* chip is ASIX AX88190 */ 123} ed_pccard_products[] = { 124 { PCMCIA_CARD(EDIMAX, EP4000A, 0), 125 -1, { 0x00, 0xa0, 0x0c } }, 126 { PCMCIA_CARD(SYNERGY21, S21810, 0), 127 -1, { 0x00, 0x48, 0x54} }, 128 { PCMCIA_CARD(AMBICOM, AMB8002T, 0), 129 -1, { 0x00, 0x10, 0x7a } }, 130 { PCMCIA_CARD(PREMAX, PE200, 0), 131 0x07f0, { 0x00, 0x20, 0xe0 } }, 132 { PCMCIA_CARD(DIGITAL, DEPCMXX, 0), 133 0x0ff0, { 0x00, 0x00, 0xe8 } }, 134 { PCMCIA_CARD(PLANET, SMARTCOM2000, 0), 135 0xff0, { 0x00, 0x00, 0xe8 } }, 136 { PCMCIA_CARD(DLINK, DE660, 0), 137 -1, { 0x00, 0x80, 0xc8 } }, 138 { PCMCIA_CARD(DLINK, DE660PLUS, 0), 139 -1, { 0x00, 0x80, 0x08 } }, 140 { PCMCIA_CARD(RPTI, EP400, 0), 141 -1, { 0x00, 0x40, 0x95 } }, 142 { PCMCIA_CARD(RPTI, EP401, 0), 143 -1, { 0x00, 0x40, 0x95 } }, 144 { PCMCIA_CARD(ACCTON, EN2212, 0), 145 0x0ff0, { 0x00, 0x00, 0xe8 } }, 146 { PCMCIA_CARD(SVEC, COMBOCARD, 0), 147 -1, { 0x00, 0xe0, 0x98 } }, 148 { PCMCIA_CARD(SVEC, LANCARD, 0), 149 0x7f0, { 0x00, 0xc0, 0x6c } }, 150 { PCMCIA_CARD(EPSON, EEN10B, 0), 151 0xff0, { 0x00, 0x00, 0x48 } }, 152 { PCMCIA_CARD(CNET, NE2000, 0), 153 -1, { 0x00, 0x80, 0xad } }, 154 { PCMCIA_CARD(ZONET, ZEN, 0), 155 -1, { 0x00, 0x80, 0xad } }, 156 157 /* 158 * You have to add new entries which contains 159 * PCMCIA_VENDOR_INVALID and/or PCMCIA_PRODUCT_INVALID 160 * in front of this comment. 161 */ 162 { PCMCIA_CARD(LANTECH, FASTNETTX, 0), 163 -1, { 0x00, 0x04, 0x1c}, NE2000DVF_AX88190 }, 164 { PCMCIA_CARD(IBM, INFOMOVER, 0), 165 0x0ff0, { 0x08, 0x00, 0x5a } }, 166 { PCMCIA_CARD(IBM, INFOMOVER, 0), 167 0x0ff0, { 0x00, 0x04, 0xac } }, 168 { PCMCIA_CARD(IBM, INFOMOVER, 0), 169 0x0ff0, { 0x00, 0x06, 0x29 } }, 170 { PCMCIA_CARD(KINGSTON, KNE2, 0), 171 -1, { 0, 0, 0 }, 0 }, /* XXX */ 172 { PCMCIA_CARD(LINKSYS, ECARD_1, 0), 173 -1, { 0x00, 0x80, 0xc8 } }, 174 { PCMCIA_CARD(LINKSYS, PCM100, 0), 175 -1, { 0x00, 0x04, 0x5a } }, 176#ifdef BOGUS 177 /* 178 * The next three should be detected as linksys, but might fail 179 * the mac sanity check. 180 */ 181 { PCMCIA_CARD(PLANEX, FNW3600T, 0), 182 -1, { 0x00, 0x90, 0xcc }, NE2000DVF_DL10019 }, 183 { PCMCIA_CARD(PLANEX, FNW3700T, 0), 184 -1, { 0x00, 0x90, 0xcc }, NE2000DVF_DL10019 }, 185 { PCMCIA_CARD(SVEC, PN650TX, 0), 186 -1, { 0x00, 0xe0, 0x98 }, NE2000DVF_DL10019 }, 187#endif 188 189 /* 190 * This entry should be here so that above two cards doesn't 191 * match with this. FNW-3700T won't match above entries due to 192 * MAC address check. 193 */ 194 { PCMCIA_CARD(LINKSYS, COMBO_ECARD, 0), 195 -1, { 0x00, 0x90, 0xcc }, NE2000DVF_DL10019 }, 196 { PCMCIA_CARD(LINKSYS, ETHERFAST, 0), 197 -1, { 0x00, 0x80, 0xc8 }, NE2000DVF_DL10019 }, 198 { PCMCIA_CARD(LINKSYS, ETHERFAST, 0), 199 -1, { 0x00, 0x90, 0xfe }, NE2000DVF_DL10019 }, 200 { PCMCIA_CARD2(LINKSYS, ETHERFAST, DLINK_DE650, 0), 201 -1, { 0x00, 0xe0, 0x98 }, NE2000DVF_DL10019 }, 202 { PCMCIA_CARD2(LINKSYS, ETHERFAST, MELCO_LPC2_TX, 0), 203 -1, { 0x00, 0x40, 0x26 }, NE2000DVF_DL10019 }, 204 { PCMCIA_CARD(LINKSYS, TRUST_COMBO_ECARD, 0), 205 0x0120, { 0x20, 0x04, 0x49 } }, 206 207 /* 208 * Although the comments above say to put VENDOR/PRODUCT 209 * INVALID IDs above this list, we need to keep this one below 210 * the ECARD_1, or else both will match the same more-generic 211 * entry rather than the more specific one above with proper 212 * vendor and product IDs. 213 */ 214 { PCMCIA_CARD(LINKSYS, ECARD_2, 0), 215 -1, { 0x00, 0x80, 0xc8 } }, 216 217 /* 218 * D-Link DE-650 has many minor versions: 219 * 220 * CIS information Manufacturer Product Note 221 * 1 "D-Link, DE-650" INVALID INVALID white card 222 * 2 "D-Link, DE-650, Ver 01.00" INVALID INVALID became bare metal 223 * 3 "D-Link, DE-650, Ver 01.00" 0x149 0x265 minor changed look 224 * 4 "D-Link, DE-650, Ver 01.00" 0x149 0x265 collision LED added 225 * 226 * While the 1st and the 2nd types should use the "D-Link DE-650" 227 * entry, the 3rd and the 4th types should use the "Linksys 228 * EtherCard" entry. Therefore, this enty must be below the 229 * LINKSYS_ECARD_1. --itohy 230 */ 231 { PCMCIA_CARD(DLINK, DE650, 0), 232 0x0040, { 0x00, 0x80, 0xc8 } }, 233 234 /* 235 * IO-DATA PCLA/TE and later version of PCLA/T has valid 236 * vendor/product ID and it is possible to read MAC address 237 * using standard I/O ports. It also read from CIS offset 0x01c0. 238 * On the other hand, earlier version of PCLA/T doesn't have valid 239 * vendor/product ID and MAC address must be read from CIS offset 240 * 0x0ff0 (i.e., usual ne2000 way to read it doesn't work). 241 * And CIS information of earlier and later version of PCLA/T are 242 * same except fourth element. So, for now, we place the entry for 243 * PCLA/TE (and later version of PCLA/T) followed by entry 244 * for the earlier version of PCLA/T (or, modify to match all CIS 245 * information and have three or more individual entries). 246 */ 247 { PCMCIA_CARD(IODATA, PCLATE, 0), 248 -1, { 0x00, 0xa0, 0xb0 } }, 249 250 /* 251 * This entry should be placed after above PCLA-TE entry. 252 * See above comments for detail. 253 */ 254 { PCMCIA_CARD(IODATA, PCLAT, 0), 255 0x0ff0, { 0x00, 0xa0, 0xb0 } }, 256 { PCMCIA_CARD(DAYNA, COMMUNICARD_E_1, 0), 257 0x0110, { 0x00, 0x80, 0x19 } }, 258 { PCMCIA_CARD(DAYNA, COMMUNICARD_E_2, 0), 259 -1, { 0x00, 0x80, 0x19 } }, 260 { PCMCIA_CARD(COREGA, ETHER_PCC_TD, 0), 261 -1, { 0x00, 0x00, 0xf4 } }, 262 { PCMCIA_CARD(COREGA, ETHER_PCC_T, 0), 263 -1, { 0x00, 0x00, 0xf4 } }, 264 { PCMCIA_CARD(COREGA, ETHER_II_PCC_T, 0), 265 -1, { 0x00, 0x00, 0xf4 } }, 266 { PCMCIA_CARD(COREGA, ETHER_II_PCC_TD, 0), 267 -1, { 0x00, 0x00, 0xf4 } }, 268 { PCMCIA_CARD(COREGA, FAST_ETHER_PCC_TX, 0), 269 -1, { 0x00, 0x00, 0xf4 }, NE2000DVF_DL10019 }, 270 { PCMCIA_CARD(COREGA, FETHER_PCC_TXD, 0), 271 -1, { 0x00, 0x90, 0x99 } }, 272 { PCMCIA_CARD(COREGA, FETHER_PCC_TXF, 0), 273 -1, { 0x00, 0x90, 0x99 }, NE2000DVF_DL10019 }, 274 { PCMCIA_CARD(COMPEX, LINKPORT_ENET_B, 0), 275 0x01c0, { 0x00, 0xa0, 0x0c } }, 276 { PCMCIA_CARD(DYNALINK, L10C, 0), 277 0x01c0, { 0x00, 0x00, 0x00 } }, 278 { PCMCIA_CARD(SMC, EZCARD, 0), 279 0x01c0, { 0x00, 0xe0, 0x29 } }, 280 { PCMCIA_CARD(SOCKET, EA_ETHER, 0), 281 -1, { 0x00, 0xc0, 0x1b } }, 282 { PCMCIA_CARD(SOCKET, LP_ETHER_CF, 0), 283 -1, { 0x00, 0xc0, 0x1b } }, 284 { PCMCIA_CARD(SOCKET, LP_ETHER, 0), 285 -1, { 0x00, 0xc0, 0x1b } }, 286 { PCMCIA_CARD(KINGSTON, KNE2, 0), 287 -1, { 0x00, 0xc0, 0xf0 } }, 288 { PCMCIA_CARD(XIRCOM, CFE_10, 0), 289 -1, { 0x00, 0x10, 0xa4 } }, 290 { PCMCIA_CARD(MELCO, LPC3_TX, 0), 291 -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 }, 292 { PCMCIA_CARD(BUFFALO, LPC3_CLT, 0), 293 -1, { 0x00, 0x07, 0x40 } }, 294 { PCMCIA_CARD(BILLIONTON, LNT10TN, 0), 295 -1, { 0x00, 0x00, 0x00 } }, 296 { PCMCIA_CARD(NDC, ND5100_E, 0), 297 -1, { 0x00, 0x80, 0xc6 } }, 298 { PCMCIA_CARD(TELECOMDEVICE, TCD_HPC100, 0), 299 -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 }, 300 { PCMCIA_CARD(MACNICA, ME1_JEIDA, 0), 301 0x00b8, { 0x08, 0x00, 0x42 } }, 302 { PCMCIA_CARD(ALLIEDTELESIS, LA_PCM, 0), 303 0x0ff0, { 0x00, 0x00, 0xf4 } }, 304 { PCMCIA_CARD(DLINK, DFE670TXD, 0), 305 -1, { 0x00, 0x50, 0xba}, NE2000DVF_DL10019}, 306 { PCMCIA_CARD(NETGEAR, FA410TXC, 0), 307 -1, { 0x00, 0x48, 0x54 }, NE2000DVF_DL10019}, 308 { PCMCIA_CARD(NETGEAR, FA411, 0), 309 -1, { 0x00, 0x40, 0xf4 }, NE2000DVF_AX88190}, 310 311#if 0 312 /* the rest of these are stolen from the linux pcnet pcmcia device 313 driver. Since I don't know the manfid or cis info strings for 314 any of them, they're not compiled in until I do. */ 315 { "APEX MultiCard", 316 0x0000, 0x0000, NULL, NULL, 0, 317 0x03f4, { 0x00, 0x20, 0xe5 } }, 318 { "ASANTE FriendlyNet", 319 0x0000, 0x0000, NULL, NULL, 0, 320 0x4910, { 0x00, 0x00, 0x94 } }, 321 { "Danpex EN-6200P2", 322 0x0000, 0x0000, NULL, NULL, 0, 323 0x0110, { 0x00, 0x40, 0xc7 } }, 324 { "DataTrek NetCard", 325 0x0000, 0x0000, NULL, NULL, 0, 326 0x0ff0, { 0x00, 0x20, 0xe8 } }, 327 { "Dayna CommuniCard E", 328 0x0000, 0x0000, NULL, NULL, 0, 329 0x0110, { 0x00, 0x80, 0x19 } }, 330 { "EP-210 Ethernet", 331 0x0000, 0x0000, NULL, NULL, 0, 332 0x0110, { 0x00, 0x40, 0x33 } }, 333 { "ELECOM Laneed LD-CDWA", 334 0x0000, 0x0000, NULL, NULL, 0, 335 0x00b8, { 0x08, 0x00, 0x42 } }, 336 { "Grey Cell GCS2220", 337 0x0000, 0x0000, NULL, NULL, 0, 338 0x0000, { 0x00, 0x47, 0x43 } }, 339 { "Hypertec Ethernet", 340 0x0000, 0x0000, NULL, NULL, 0, 341 0x01c0, { 0x00, 0x40, 0x4c } }, 342 { "IBM CCAE", 343 0x0000, 0x0000, NULL, NULL, 0, 344 0x0ff0, { 0x08, 0x00, 0x5a } }, 345 { "IBM CCAE", 346 0x0000, 0x0000, NULL, NULL, 0, 347 0x0ff0, { 0x00, 0x04, 0xac } }, 348 { "IBM CCAE", 349 0x0000, 0x0000, NULL, NULL, 0, 350 0x0ff0, { 0x00, 0x06, 0x29 } }, 351 { "IBM FME", 352 0x0000, 0x0000, NULL, NULL, 0, 353 0x0374, { 0x00, 0x04, 0xac } }, 354 { "IBM FME", 355 0x0000, 0x0000, NULL, NULL, 0, 356 0x0374, { 0x08, 0x00, 0x5a } }, 357 { "Katron PE-520", 358 0x0000, 0x0000, NULL, NULL, 0, 359 0x0110, { 0x00, 0x40, 0xf6 } }, 360 { "Kingston KNE-PCM/x", 361 0x0000, 0x0000, NULL, NULL, 0, 362 0x0ff0, { 0x00, 0xc0, 0xf0 } }, 363 { "Kingston KNE-PCM/x", 364 0x0000, 0x0000, NULL, NULL, 0, 365 0x0ff0, { 0xe2, 0x0c, 0x0f } }, 366 { "Longshine LCS-8534", 367 0x0000, 0x0000, NULL, NULL, 0, 368 0x0000, { 0x08, 0x00, 0x00 } }, 369 { "Maxtech PCN2000", 370 0x0000, 0x0000, NULL, NULL, 0, 371 0x5000, { 0x00, 0x00, 0xe8 } }, 372 { "NDC Instant-Link", 373 0x0000, 0x0000, NULL, NULL, 0, 374 0x003a, { 0x00, 0x80, 0xc6 } }, 375 { "NE2000 Compatible", 376 0x0000, 0x0000, NULL, NULL, 0, 377 0x0ff0, { 0x00, 0xa0, 0x0c } }, 378 { "Network General Sniffer", 379 0x0000, 0x0000, NULL, NULL, 0, 380 0x0ff0, { 0x00, 0x00, 0x65 } }, 381 { "Panasonic VEL211", 382 0x0000, 0x0000, NULL, NULL, 0, 383 0x0ff0, { 0x00, 0x80, 0x45 } }, 384 { "SCM Ethernet", 385 0x0000, 0x0000, NULL, NULL, 0, 386 0x0ff0, { 0x00, 0x20, 0xcb } }, 387 { "Volktek NPL-402CT", 388 0x0000, 0x0000, NULL, NULL, 0, 389 0x0060, { 0x00, 0x40, 0x05 } }, 390#endif 391 { { NULL } } 392 393}; 394 395static int 396ed_pccard_match(device_t dev) 397{ 398 const struct ed_product *pp; 399 400 if ((pp = (const struct ed_product *) pccard_product_lookup(dev, 401 (const struct pccard_product *) ed_pccard_products, 402 sizeof(ed_pccard_products[0]), NULL)) != NULL) { 403 device_set_desc(dev, pp->prod.pp_name); 404 if (pp->flags & NE2000DVF_DL10019) 405 device_set_flags(dev, ED_FLAGS_LINKSYS); 406 else if (pp->flags & NE2000DVF_AX88190) 407 device_set_flags(dev, ED_FLAGS_AX88190); 408 return (0); 409 } 410 return (EIO); 411} 412 413/* 414 * Probe framework for pccards. Replicates the standard framework, 415 * minus the pccard driver registration and ignores the ether address 416 * supplied (from the CIS), relying on the probe to find it instead. 417 */ 418static int 419ed_pccard_probe(device_t dev) 420{ 421 int error; 422 int flags = device_get_flags(dev); 423 424 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_AX88190) { 425 error = ed_pccard_ax88190(dev); 426 goto end2; 427 } 428 429 error = ed_probe_Novell(dev, 0, flags); 430 if (error == 0) 431 goto end; 432 ed_release_resources(dev); 433 434 error = ed_probe_WD80x3(dev, 0, flags); 435 if (error == 0) 436 goto end; 437 ed_release_resources(dev); 438 goto end2; 439 440end: 441 if (ED_FLAGS_GETTYPE(flags) & ED_FLAGS_LINKSYS) 442 ed_pccard_Linksys(dev); 443end2: 444 if (error == 0) 445 error = ed_alloc_irq(dev, 0, 0); 446 447 ed_release_resources(dev); 448 return (error); 449} 450 451static int 452ed_pccard_attach(device_t dev) 453{ 454 int error; 455 int flags = device_get_flags(dev); 456 int i; 457 struct ed_softc *sc = device_get_softc(dev); 458 u_char sum; 459 u_char ether_addr[ETHER_ADDR_LEN]; 460 461 if (sc->port_used > 0) 462 ed_alloc_port(dev, sc->port_rid, sc->port_used); 463 if (sc->mem_used) 464 ed_alloc_memory(dev, sc->mem_rid, sc->mem_used); 465 ed_alloc_irq(dev, sc->irq_rid, 0); 466 467 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, 468 edintr, sc, &sc->irq_handle); 469 if (error) { 470 printf("setup intr failed %d \n", error); 471 ed_release_resources(dev); 472 return (error); 473 } 474 475 if (sc->vendor != ED_VENDOR_LINKSYS) { 476 pccard_get_ether(dev, ether_addr); 477 for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) 478 sum |= ether_addr[i]; 479 if (sum) 480 bcopy(ether_addr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 481 } 482 483 error = ed_attach(sc, device_get_unit(dev), flags); 484#ifndef ED_NO_MIIBUS 485 if (error == 0 && sc->vendor == ED_VENDOR_LINKSYS) { 486 /* Probe for an MII bus, but ignore errors. */ 487 ed_pccard_dlink_mii_reset(sc); 488 sc->mii_readbits = ed_pccard_dlink_mii_readbits; 489 sc->mii_writebits = ed_pccard_dlink_mii_writebits; 490 mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd, 491 ed_ifmedia_sts); 492 } 493#endif 494 495 return (error); 496} 497 498static void 499ax88190_geteprom(struct ed_softc *sc) 500{ 501 int prom[16],i; 502 u_char tmp; 503 struct { 504 unsigned char offset, value; 505 } pg_seq[] = { 506 {ED_P0_CR, ED_CR_RD2|ED_CR_STP},/* Select Page0 */ 507 {ED_P0_DCR, 0x01}, 508 {ED_P0_RBCR0, 0x00}, /* Clear the count regs. */ 509 {ED_P0_RBCR1, 0x00}, 510 {ED_P0_IMR, 0x00}, /* Mask completion irq. */ 511 {ED_P0_ISR, 0xff}, 512 {ED_P0_RCR, ED_RCR_MON | ED_RCR_INTT}, /* Set To Monitor */ 513 {ED_P0_TCR, ED_TCR_LB0}, /* loopback mode. */ 514 {ED_P0_RBCR0, 32}, 515 {ED_P0_RBCR1, 0x00}, 516 {ED_P0_RSAR0, 0x00}, 517 {ED_P0_RSAR1, 0x04}, 518 {ED_P0_CR ,ED_CR_RD0 | ED_CR_STA}, 519 }; 520 521 /* Reset Card */ 522 tmp = ed_asic_inb(sc, ED_NOVELL_RESET); 523 ed_asic_outb(sc, ED_NOVELL_RESET, tmp); 524 DELAY(5000); 525 ed_asic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 526 DELAY(5000); 527 528 /* Card Settings */ 529 for (i = 0; i < sizeof(pg_seq) / sizeof(pg_seq[0]); i++) 530 ed_nic_outb(sc, pg_seq[i].offset, pg_seq[i].value); 531 532 /* Get Data */ 533 for (i = 0; i < 16; i++) 534 prom[i] = ed_asic_inb(sc, 0); 535 sc->arpcom.ac_enaddr[0] = prom[0] & 0xff; 536 sc->arpcom.ac_enaddr[1] = prom[0] >> 8; 537 sc->arpcom.ac_enaddr[2] = prom[1] & 0xff; 538 sc->arpcom.ac_enaddr[3] = prom[1] >> 8; 539 sc->arpcom.ac_enaddr[4] = prom[2] & 0xff; 540 sc->arpcom.ac_enaddr[5] = prom[2] >> 8; 541} 542 543static int 544ed_pccard_memwrite(device_t dev, off_t offset, u_char byte) 545{ 546 int cis_rid; 547 struct resource *cis; 548 549 cis_rid = 0; 550 cis = bus_alloc_resource(dev, SYS_RES_MEMORY, &cis_rid, 0, ~0, 551 4 << 10, RF_ACTIVE | RF_SHAREABLE); 552 if (cis == NULL) 553 return (ENXIO); 554 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, 555 cis_rid, PCCARD_A_MEM_ATTR); 556 557 bus_space_write_1(rman_get_bustag(cis), rman_get_bushandle(cis), 558 offset, byte); 559 560 bus_deactivate_resource(dev, SYS_RES_MEMORY, cis_rid, cis); 561 bus_release_resource(dev, SYS_RES_MEMORY, cis_rid, cis); 562 563 return (0); 564} 565 566/* 567 * Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100 568 * and compatible cards (DL10019C Ethernet controller). 569 * 570 * Note: The PAO patches try to use more memory for the card, but that 571 * seems to fail for my card. A future optimization would add this back 572 * conditionally. 573 */ 574static int 575ed_pccard_Linksys(device_t dev) 576{ 577 struct ed_softc *sc = device_get_softc(dev); 578 u_char sum; 579 int i; 580 581 /* 582 * Linksys registers(offset from ASIC base) 583 * 584 * 0x04-0x09 : Physical Address Register 0-5 (PAR0-PAR5) 585 * 0x0A : Card ID Register (CIR) 586 * 0x0B : Check Sum Register (SR) 587 */ 588 for (sum = 0, i = 0x04; i < 0x0c; i++) 589 sum += ed_asic_inb(sc, i); 590 if (sum != 0xff) 591 return (0); /* invalid DL10019C */ 592 for (i = 0; i < ETHER_ADDR_LEN; i++) { 593 sc->arpcom.ac_enaddr[i] = ed_asic_inb(sc, 0x04 + i); 594 } 595 596 ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); 597 sc->isa16bit = 1; 598 sc->vendor = ED_VENDOR_LINKSYS; 599 sc->type = ED_TYPE_NE2000; 600 sc->type_str = "Linksys"; 601 602 return (1); 603} 604 605/* 606 * Special setup for AX88190 607 */ 608static int 609ed_pccard_ax88190(device_t dev) 610{ 611 int error; 612 int flags = device_get_flags(dev); 613 int iobase; 614 struct ed_softc *sc = device_get_softc(dev); 615 616 /* Allocate the port resource during setup. */ 617 error = ed_alloc_port(dev, 0, ED_NOVELL_IO_PORTS); 618 if (error) 619 return (error); 620 621 sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 622 sc->nic_offset = ED_NOVELL_NIC_OFFSET; 623 sc->chip_type = ED_CHIP_TYPE_AX88190; 624 625 /* 626 * Set Attribute Memory IOBASE Register 627 */ 628 iobase = rman_get_start(sc->port_res); 629 ed_pccard_memwrite(dev, ED_AX88190_IOBASE0, iobase & 0xff); 630 ed_pccard_memwrite(dev, ED_AX88190_IOBASE1, (iobase >> 8) & 0xff); 631 ax88190_geteprom(sc); 632 ed_release_resources(dev); 633 error = ed_probe_Novell(dev, 0, flags); 634 if (error == 0) { 635 sc->vendor = ED_VENDOR_PCCARD; 636 sc->type = ED_TYPE_NE2000; 637 sc->type_str = "AX88190"; 638 } 639 return (error); 640} 641 642#ifndef ED_NO_MIIBUS 643/* MII bit-twiddling routines for cards using Dlink chipset */ 644#define DLINK_MIISET(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \ 645 ed_asic_inb(sc, ED_DLINK_MIIBUS) | (x)) 646#define DLINK_MIICLR(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \ 647 ed_asic_inb(sc, ED_DLINK_MIIBUS) & ~(x)) 648 649static void 650ed_pccard_dlink_mii_reset(sc) 651 struct ed_softc *sc; 652{ 653 ed_asic_outb(sc, ED_DLINK_MIIBUS, 0); 654 DELAY(10); 655 DLINK_MIISET(sc, ED_DLINK_MII_RESET2); 656 DELAY(10); 657 DLINK_MIISET(sc, ED_DLINK_MII_RESET1); 658 DELAY(10); 659 DLINK_MIICLR(sc, ED_DLINK_MII_RESET1); 660 DELAY(10); 661 DLINK_MIICLR(sc, ED_DLINK_MII_RESET2); 662 DELAY(10); 663} 664 665static void 666ed_pccard_dlink_mii_writebits(sc, val, nbits) 667 struct ed_softc *sc; 668 u_int val; 669 int nbits; 670{ 671 int i; 672 673 DLINK_MIISET(sc, ED_DLINK_MII_DIROUT); 674 675 for (i = nbits - 1; i >= 0; i--) { 676 if ((val >> i) & 1) 677 DLINK_MIISET(sc, ED_DLINK_MII_DATAOUT); 678 else 679 DLINK_MIICLR(sc, ED_DLINK_MII_DATAOUT); 680 DELAY(10); 681 DLINK_MIISET(sc, ED_DLINK_MII_CLK); 682 DELAY(10); 683 DLINK_MIICLR(sc, ED_DLINK_MII_CLK); 684 DELAY(10); 685 } 686} 687 688static u_int 689ed_pccard_dlink_mii_readbits(sc, nbits) 690 struct ed_softc *sc; 691 int nbits; 692{ 693 int i; 694 u_int val = 0; 695 696 DLINK_MIICLR(sc, ED_DLINK_MII_DIROUT); 697 698 for (i = nbits - 1; i >= 0; i--) { 699 DLINK_MIISET(sc, ED_DLINK_MII_CLK); 700 DELAY(10); 701 val <<= 1; 702 if (ed_asic_inb(sc, ED_DLINK_MIIBUS) & ED_DLINK_MII_DATATIN) 703 val++; 704 DLINK_MIICLR(sc, ED_DLINK_MII_CLK); 705 DELAY(10); 706 } 707 708 return val; 709} 710#endif 711 712static device_method_t ed_pccard_methods[] = { 713 /* Device interface */ 714 DEVMETHOD(device_probe, pccard_compat_probe), 715 DEVMETHOD(device_attach, pccard_compat_attach), 716 DEVMETHOD(device_detach, ed_pccard_detach), 717 718#ifndef ED_NO_MIIBUS 719 /* Bus interface */ 720 DEVMETHOD(bus_child_detached, ed_child_detached), 721 722 /* MII interface */ 723 DEVMETHOD(miibus_readreg, ed_miibus_readreg), 724 DEVMETHOD(miibus_writereg, ed_miibus_writereg), 725#endif 726 727 /* Card interface */ 728 DEVMETHOD(card_compat_match, ed_pccard_match), 729 DEVMETHOD(card_compat_probe, ed_pccard_probe), 730 DEVMETHOD(card_compat_attach, ed_pccard_attach), 731 { 0, 0 } 732}; 733 734static driver_t ed_pccard_driver = { 735 "ed", 736 ed_pccard_methods, 737 sizeof(struct ed_softc) 738}; 739 740DRIVER_MODULE(if_ed, pccard, ed_pccard_driver, ed_devclass, 0, 0); 741#ifndef ED_NO_MIIBUS 742DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0); 743#endif 744