if_ed_pccard.c revision 86396
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 86396 2001-11-15 08:15:44Z 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(SYNERGY21, S21810, 0), 125 -1, { 0x00, 0x48, 0x54} }, 126 { PCMCIA_CARD(AMBICOM, AMB8002T, 0), 127 -1, { 0x00, 0x10, 0x7a } }, 128 { PCMCIA_CARD(PREMAX, PE200, 0), 129 0x07f0, { 0x00, 0x20, 0xe0 } }, 130 { PCMCIA_CARD(DIGITAL, DEPCMXX, 0), 131 0x0ff0, { 0x00, 0x00, 0xe8 } }, 132 { PCMCIA_CARD(PLANET, SMARTCOM2000, 0), 133 0xff0, { 0x00, 0x00, 0xe8 } }, 134 { PCMCIA_CARD(DLINK, DE660, 0), 135 -1, { 0x00, 0x80, 0xc8 } }, 136 { PCMCIA_CARD(DLINK, DE660PLUS, 0), 137 -1, { 0x00, 0x80, 0x08 } }, 138 { PCMCIA_CARD(RPTI, EP400, 0), 139 -1, { 0x00, 0x40, 0x95 } }, 140 { PCMCIA_CARD(RPTI, EP401, 0), 141 -1, { 0x00, 0x40, 0x95 } }, 142 { PCMCIA_CARD(ACCTON, EN2212, 0), 143 0x0ff0, { 0x00, 0x00, 0xe8 } }, 144 { PCMCIA_CARD(SVEC, COMBOCARD, 0), 145 -1, { 0x00, 0xe0, 0x98 } }, 146 { PCMCIA_CARD(SVEC, LANCARD, 0), 147 0x7f0, { 0x00, 0xc0, 0x6c } }, 148 { PCMCIA_CARD(EPSON, EEN10B, 0), 149 0xff0, { 0x00, 0x00, 0x48 } }, 150 { PCMCIA_CARD(CNET, NE2000, 0), 151 -1, { 0x00, 0x80, 0xad } }, 152 { PCMCIA_CARD(ZONET, ZEN, 0), 153 -1, { 0x00, 0x80, 0xad } }, 154 155 /* 156 * You have to add new entries which contains 157 * PCMCIA_VENDOR_INVALID and/or PCMCIA_PRODUCT_INVALID 158 * in front of this comment. 159 * 160 * There are cards which use a generic vendor and product id but needs 161 * a different handling depending on the cis_info, so ne2000_match 162 * needs a table where the exceptions comes first and then the normal 163 * product and vendor entries. 164 */ 165 { PCMCIA_CARD(IBM, INFOMOVER, 0), 166 0x0ff0, { 0x08, 0x00, 0x5a } }, 167 { PCMCIA_CARD(IBM, INFOMOVER, 0), 168 0x0ff0, { 0x00, 0x04, 0xac } }, 169 { PCMCIA_CARD(IBM, INFOMOVER, 0), 170 0x0ff0, { 0x00, 0x06, 0x29 } }, 171 { PCMCIA_CARD(KINGSTON, KNE2, 0), 172 -1, { 0, 0, 0 }, 0 }, /* XXX */ 173 { PCMCIA_CARD(LINKSYS, ECARD_1, 0), 174 -1, { 0x00, 0x80, 0xc8 } }, 175 { PCMCIA_CARD(PLANEX, FNW3600T, 0), 176 -1, { 0x00, 0x90, 0xcc }, NE2000DVF_DL10019 }, 177 { PCMCIA_CARD(SVEC, PN650TX, 0), 178 -1, { 0x00, 0xe0, 0x98 }, NE2000DVF_DL10019 }, 179 180 /* 181 * This entry should be here so that above two cards doesn't 182 * match with this. FNW-3700T won't match above entries due to 183 * MAC address check. 184 */ 185 { PCMCIA_CARD(LINKSYS, COMBO_ECARD, 0), 186 -1, { 0x00, 0x90, 0xcc }, NE2000DVF_AX88190 }, 187 { PCMCIA_CARD(LINKSYS, ETHERFAST, 0), 188 -1, { 0x00, 0x80, 0xc8 }, NE2000DVF_DL10019 }, 189 { PCMCIA_CARD(LINKSYS, ETHERFAST, 0), 190 -1, { 0x00, 0x90, 0xfe }, NE2000DVF_DL10019 }, 191 { PCMCIA_CARD2(LINKSYS, ETHERFAST, DLINK_DE650, 0), 192 -1, { 0x00, 0xe0, 0x98 }, NE2000DVF_DL10019 }, 193 { PCMCIA_CARD2(LINKSYS, ETHERFAST, MELCO_LPC2_TX, 0), 194 -1, { 0x00, 0x40, 0x26 }, NE2000DVF_DL10019 }, 195 { PCMCIA_CARD(LINKSYS, COMBO_ECARD, 0), 196 -1, { 0x00, 0x80, 0xc8 } }, 197 { PCMCIA_CARD(LINKSYS, TRUST_COMBO_ECARD, 0), 198 0x0120, { 0x20, 0x04, 0x49 } }, 199 200 /* 201 * Although the comments above say to put VENDOR/PRODUCT 202 * INVALID IDs above this list, we need to keep this one below 203 * the ECARD_1, or else both will match the same more-generic 204 * entry rather than the more specific one above with proper 205 * vendor and product IDs. 206 */ 207 { PCMCIA_CARD(LINKSYS, ECARD_2, 0), 208 -1, { 0x00, 0x80, 0xc8 } }, 209 210 /* 211 * D-Link DE-650 has many minor versions: 212 * 213 * CIS information Manufacturer Product Note 214 * 1 "D-Link, DE-650" INVALID INVALID white card 215 * 2 "D-Link, DE-650, Ver 01.00" INVALID INVALID became bare metal 216 * 3 "D-Link, DE-650, Ver 01.00" 0x149 0x265 minor changed look 217 * 4 "D-Link, DE-650, Ver 01.00" 0x149 0x265 collision LED added 218 * 219 * While the 1st and the 2nd types should use the "D-Link DE-650" 220 * entry, the 3rd and the 4th types should use the "Linksys 221 * EtherCard" entry. Therefore, this enty must be below the 222 * LINKSYS_ECARD_1. --itohy 223 */ 224 { PCMCIA_CARD(DLINK, DE650, 0), 225 0x0040, { 0x00, 0x80, 0xc8 } }, 226 227 /* 228 * IO-DATA PCLA/TE and later version of PCLA/T has valid 229 * vendor/product ID and it is possible to read MAC address 230 * using standard I/O ports. It also read from CIS offset 0x01c0. 231 * On the other hand, earlier version of PCLA/T doesn't have valid 232 * vendor/product ID and MAC address must be read from CIS offset 233 * 0x0ff0 (i.e., usual ne2000 way to read it doesn't work). 234 * And CIS information of earlier and later version of PCLA/T are 235 * same except fourth element. So, for now, we place the entry for 236 * PCLA/TE (and later version of PCLA/T) followed by entry 237 * for the earlier version of PCLA/T (or, modify to match all CIS 238 * information and have three or more individual entries). 239 */ 240 { PCMCIA_CARD(IODATA, PCLATE, 0), 241 -1, { 0x00, 0xa0, 0xb0 } }, 242 243 /* 244 * This entry should be placed after above PCLA-TE entry. 245 * See above comments for detail. 246 */ 247 { PCMCIA_CARD(IODATA, PCLAT, 0), 248 0x0ff0, { 0x00, 0xa0, 0xb0 } }, 249 { PCMCIA_CARD(DAYNA, COMMUNICARD_E_1, 0), 250 0x0110, { 0x00, 0x80, 0x19 } }, 251 { PCMCIA_CARD(DAYNA, COMMUNICARD_E_2, 0), 252 -1, { 0x00, 0x80, 0x19 } }, 253 { PCMCIA_CARD(COREGA, ETHER_PCC_TD, 0), 254 -1, { 0x00, 0x00, 0xf4 } }, 255 { PCMCIA_CARD(COREGA, ETHER_PCC_T, 0), 256 -1, { 0x00, 0x00, 0xf4 } }, 257 { PCMCIA_CARD(COREGA, ETHER_II_PCC_T, 0), 258 -1, { 0x00, 0x00, 0xf4 } }, 259 { PCMCIA_CARD(COREGA, FAST_ETHER_PCC_TX, 0), 260 -1, { 0x00, 0x00, 0xf4 }, NE2000DVF_DL10019 }, 261 { PCMCIA_CARD(COREGA, FETHER_PCC_TXD, 0), 262 -1, { 0x00, 0x90, 0x99 } }, 263 { PCMCIA_CARD(COREGA, FETHER_PCC_TXF, 0), 264 -1, { 0x00, 0x90, 0x99 }, NE2000DVF_DL10019 }, 265 { PCMCIA_CARD(COMPEX, LINKPORT_ENET_B, 0), 266 0x01c0, { 0x00, 0xa0, 0x0c } }, 267 { PCMCIA_CARD(SMC, EZCARD, 0), 268 0x01c0, { 0x00, 0xe0, 0x29 } }, 269 { PCMCIA_CARD(SOCKET, EA_ETHER, 0), 270 -1, { 0x00, 0xc0, 0x1b } }, 271 { PCMCIA_CARD(SOCKET, LP_ETHER_CF, 0), 272 -1, { 0x00, 0xc0, 0x1b } }, 273 { PCMCIA_CARD(SOCKET, LP_ETHER, 0), 274 -1, { 0x00, 0xc0, 0x1b } }, 275 { PCMCIA_CARD(KINGSTON, KNE2, 0), 276 -1, { 0x00, 0xc0, 0xf0 } }, 277 { PCMCIA_CARD(XIRCOM, CFE_10, 0), 278 -1, { 0x00, 0x10, 0xa4 } }, 279 { PCMCIA_CARD(MELCO, LPC3_TX, 0), 280 -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 }, 281 { PCMCIA_CARD(BILLIONTON, LNT10TN, 0), 282 -1, { 0x00, 0x00, 0x00 } }, 283 { PCMCIA_CARD(NDC, ND5100_E, 0), 284 -1, { 0x00, 0x80, 0xc6 } }, 285 { PCMCIA_CARD(TELECOMDEVICE, TCD_HPC100, 0), 286 -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 }, 287 { PCMCIA_CARD(MACNICA, ME1_JEIDA, 0), 288 0x00b8, { 0x08, 0x00, 0x42 } }, 289 { PCMCIA_CARD(ALLIEDTELESIS, LA_PCM, 0), 290 0x0ff0, { 0x00, 0x00, 0xf4 } }, 291#if 0 292 /* the rest of these are stolen from the linux pcnet pcmcia device 293 driver. Since I don't know the manfid or cis info strings for 294 any of them, they're not compiled in until I do. */ 295 { "APEX MultiCard", 296 0x0000, 0x0000, NULL, NULL, 0, 297 0x03f4, { 0x00, 0x20, 0xe5 } }, 298 { "ASANTE FriendlyNet", 299 0x0000, 0x0000, NULL, NULL, 0, 300 0x4910, { 0x00, 0x00, 0x94 } }, 301 { "Danpex EN-6200P2", 302 0x0000, 0x0000, NULL, NULL, 0, 303 0x0110, { 0x00, 0x40, 0xc7 } }, 304 { "DataTrek NetCard", 305 0x0000, 0x0000, NULL, NULL, 0, 306 0x0ff0, { 0x00, 0x20, 0xe8 } }, 307 { "Dayna CommuniCard E", 308 0x0000, 0x0000, NULL, NULL, 0, 309 0x0110, { 0x00, 0x80, 0x19 } }, 310 { "EP-210 Ethernet", 311 0x0000, 0x0000, NULL, NULL, 0, 312 0x0110, { 0x00, 0x40, 0x33 } }, 313 { "ELECOM Laneed LD-CDWA", 314 0x0000, 0x0000, NULL, NULL, 0, 315 0x00b8, { 0x08, 0x00, 0x42 } }, 316 { "Grey Cell GCS2220", 317 0x0000, 0x0000, NULL, NULL, 0, 318 0x0000, { 0x00, 0x47, 0x43 } }, 319 { "Hypertec Ethernet", 320 0x0000, 0x0000, NULL, NULL, 0, 321 0x01c0, { 0x00, 0x40, 0x4c } }, 322 { "IBM CCAE", 323 0x0000, 0x0000, NULL, NULL, 0, 324 0x0ff0, { 0x08, 0x00, 0x5a } }, 325 { "IBM CCAE", 326 0x0000, 0x0000, NULL, NULL, 0, 327 0x0ff0, { 0x00, 0x04, 0xac } }, 328 { "IBM CCAE", 329 0x0000, 0x0000, NULL, NULL, 0, 330 0x0ff0, { 0x00, 0x06, 0x29 } }, 331 { "IBM FME", 332 0x0000, 0x0000, NULL, NULL, 0, 333 0x0374, { 0x00, 0x04, 0xac } }, 334 { "IBM FME", 335 0x0000, 0x0000, NULL, NULL, 0, 336 0x0374, { 0x08, 0x00, 0x5a } }, 337 { "Katron PE-520", 338 0x0000, 0x0000, NULL, NULL, 0, 339 0x0110, { 0x00, 0x40, 0xf6 } }, 340 { "Kingston KNE-PCM/x", 341 0x0000, 0x0000, NULL, NULL, 0, 342 0x0ff0, { 0x00, 0xc0, 0xf0 } }, 343 { "Kingston KNE-PCM/x", 344 0x0000, 0x0000, NULL, NULL, 0, 345 0x0ff0, { 0xe2, 0x0c, 0x0f } }, 346 { "Longshine LCS-8534", 347 0x0000, 0x0000, NULL, NULL, 0, 348 0x0000, { 0x08, 0x00, 0x00 } }, 349 { "Maxtech PCN2000", 350 0x0000, 0x0000, NULL, NULL, 0, 351 0x5000, { 0x00, 0x00, 0xe8 } }, 352 { "NDC Instant-Link", 353 0x0000, 0x0000, NULL, NULL, 0, 354 0x003a, { 0x00, 0x80, 0xc6 } }, 355 { "NE2000 Compatible", 356 0x0000, 0x0000, NULL, NULL, 0, 357 0x0ff0, { 0x00, 0xa0, 0x0c } }, 358 { "Network General Sniffer", 359 0x0000, 0x0000, NULL, NULL, 0, 360 0x0ff0, { 0x00, 0x00, 0x65 } }, 361 { "Panasonic VEL211", 362 0x0000, 0x0000, NULL, NULL, 0, 363 0x0ff0, { 0x00, 0x80, 0x45 } }, 364 { "SCM Ethernet", 365 0x0000, 0x0000, NULL, NULL, 0, 366 0x0ff0, { 0x00, 0x20, 0xcb } }, 367 { "Volktek NPL-402CT", 368 0x0000, 0x0000, NULL, NULL, 0, 369 0x0060, { 0x00, 0x40, 0x05 } }, 370#endif 371 { { NULL } } 372 373}; 374 375static int 376ed_pccard_match(device_t dev) 377{ 378 const struct pccard_product *pp; 379 380 if ((pp = pccard_product_lookup(dev, 381 (const struct pccard_product *) ed_pccard_products, 382 sizeof(ed_pccard_products[0]), NULL)) != NULL) { 383 device_set_desc(dev, pp->pp_name); 384 return 0; 385 } 386 return EIO; 387} 388 389/* 390 * Probe framework for pccards. Replicates the standard framework, 391 * minus the pccard driver registration and ignores the ether address 392 * supplied (from the CIS), relying on the probe to find it instead. 393 */ 394static int 395ed_pccard_probe(device_t dev) 396{ 397 int error; 398 int flags = device_get_flags(dev); 399 400 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_AX88190) { 401 error = ed_pccard_ax88190(dev); 402 goto end2; 403 } 404 405 error = ed_probe_Novell(dev, 0, flags); 406 if (error == 0) 407 goto end; 408 ed_release_resources(dev); 409 410 error = ed_probe_WD80x3(dev, 0, flags); 411 if (error == 0) 412 goto end; 413 ed_release_resources(dev); 414 goto end2; 415 416end: 417 if (ED_FLAGS_GETTYPE(flags) & ED_FLAGS_LINKSYS) 418 ed_pccard_Linksys(dev); 419end2: 420 if (error == 0) 421 error = ed_alloc_irq(dev, 0, 0); 422 423 ed_release_resources(dev); 424 return (error); 425} 426 427static int 428ed_pccard_attach(device_t dev) 429{ 430 int error; 431 int flags = device_get_flags(dev); 432 int i; 433 struct ed_softc *sc = device_get_softc(dev); 434 u_char sum; 435 u_char ether_addr[ETHER_ADDR_LEN]; 436 437 if (sc->port_used > 0) 438 ed_alloc_port(dev, sc->port_rid, sc->port_used); 439 if (sc->mem_used) 440 ed_alloc_memory(dev, sc->mem_rid, sc->mem_used); 441 ed_alloc_irq(dev, sc->irq_rid, 0); 442 443 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, 444 edintr, sc, &sc->irq_handle); 445 if (error) { 446 printf("setup intr failed %d \n", error); 447 ed_release_resources(dev); 448 return (error); 449 } 450 451 if (sc->vendor != ED_VENDOR_LINKSYS) { 452 pccard_get_ether(dev, ether_addr); 453 for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) 454 sum |= ether_addr[i]; 455 if (sum) 456 bcopy(ether_addr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 457 } 458 459 error = ed_attach(sc, device_get_unit(dev), flags); 460#ifndef ED_NO_MIIBUS 461 if (error == 0 && sc->vendor == ED_VENDOR_LINKSYS) { 462 /* Probe for an MII bus, but ignore errors. */ 463 ed_pccard_dlink_mii_reset(sc); 464 sc->mii_readbits = ed_pccard_dlink_mii_readbits; 465 sc->mii_writebits = ed_pccard_dlink_mii_writebits; 466 mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd, 467 ed_ifmedia_sts); 468 } 469#endif 470 471 return (error); 472} 473 474static void 475ax88190_geteprom(struct ed_softc *sc) 476{ 477 int prom[16],i; 478 u_char tmp; 479 struct { 480 unsigned char offset, value; 481 } pg_seq[] = { 482 {ED_P0_CR, ED_CR_RD2|ED_CR_STP},/* Select Page0 */ 483 {ED_P0_DCR, 0x01}, 484 {ED_P0_RBCR0, 0x00}, /* Clear the count regs. */ 485 {ED_P0_RBCR1, 0x00}, 486 {ED_P0_IMR, 0x00}, /* Mask completion irq. */ 487 {ED_P0_ISR, 0xff}, 488 {ED_P0_RCR, ED_RCR_MON | ED_RCR_INTT}, /* Set To Monitor */ 489 {ED_P0_TCR, ED_TCR_LB0}, /* loopback mode. */ 490 {ED_P0_RBCR0, 32}, 491 {ED_P0_RBCR1, 0x00}, 492 {ED_P0_RSAR0, 0x00}, 493 {ED_P0_RSAR1, 0x04}, 494 {ED_P0_CR ,ED_CR_RD0 | ED_CR_STA}, 495 }; 496 497 /* Reset Card */ 498 tmp = ed_asic_inb(sc, ED_NOVELL_RESET); 499 ed_asic_outb(sc, ED_NOVELL_RESET, tmp); 500 DELAY(5000); 501 ed_asic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 502 DELAY(5000); 503 504 /* Card Settings */ 505 for (i = 0; i < sizeof(pg_seq) / sizeof(pg_seq[0]); i++) 506 ed_nic_outb(sc, pg_seq[i].offset, pg_seq[i].value); 507 508 /* Get Data */ 509 for (i = 0; i < 16; i++) 510 prom[i] = ed_asic_inb(sc, 0); 511 sc->arpcom.ac_enaddr[0] = prom[0] & 0xff; 512 sc->arpcom.ac_enaddr[1] = prom[0] >> 8; 513 sc->arpcom.ac_enaddr[2] = prom[1] & 0xff; 514 sc->arpcom.ac_enaddr[3] = prom[1] >> 8; 515 sc->arpcom.ac_enaddr[4] = prom[2] & 0xff; 516 sc->arpcom.ac_enaddr[5] = prom[2] >> 8; 517} 518 519static int 520ed_pccard_memwrite(device_t dev, off_t offset, u_char byte) 521{ 522 int cis_rid; 523 struct resource *cis; 524 525 cis_rid = 0; 526 cis = bus_alloc_resource(dev, SYS_RES_MEMORY, &cis_rid, 0, ~0, 527 4 << 10, RF_ACTIVE | RF_SHAREABLE); 528 if (cis == NULL) 529 return (ENXIO); 530 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, 531 cis_rid, PCCARD_A_MEM_ATTR); 532 533 bus_space_write_1(rman_get_bustag(cis), rman_get_bushandle(cis), 534 offset, byte); 535 536 bus_deactivate_resource(dev, SYS_RES_MEMORY, cis_rid, cis); 537 bus_release_resource(dev, SYS_RES_MEMORY, cis_rid, cis); 538 539 return (0); 540} 541 542/* 543 * Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100 544 * and compatible cards (DL10019C Ethernet controller). 545 * 546 * Note: The PAO patches try to use more memory for the card, but that 547 * seems to fail for my card. A future optimization would add this back 548 * conditionally. 549 */ 550static int 551ed_pccard_Linksys(device_t dev) 552{ 553 struct ed_softc *sc = device_get_softc(dev); 554 u_char sum; 555 int i; 556 557 /* 558 * Linksys registers(offset from ASIC base) 559 * 560 * 0x04-0x09 : Physical Address Register 0-5 (PAR0-PAR5) 561 * 0x0A : Card ID Register (CIR) 562 * 0x0B : Check Sum Register (SR) 563 */ 564 for (sum = 0, i = 0x04; i < 0x0c; i++) 565 sum += ed_asic_inb(sc, i); 566 if (sum != 0xff) 567 return (0); /* invalid DL10019C */ 568 for (i = 0; i < ETHER_ADDR_LEN; i++) { 569 sc->arpcom.ac_enaddr[i] = ed_asic_inb(sc, 0x04 + i); 570 } 571 572 ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); 573 sc->isa16bit = 1; 574 sc->vendor = ED_VENDOR_LINKSYS; 575 sc->type = ED_TYPE_NE2000; 576 sc->type_str = "Linksys"; 577 578 return (1); 579} 580 581/* 582 * Special setup for AX88190 583 */ 584static int 585ed_pccard_ax88190(device_t dev) 586{ 587 int error; 588 int flags = device_get_flags(dev); 589 int iobase; 590 struct ed_softc *sc = device_get_softc(dev); 591 592 /* Allocate the port resource during setup. */ 593 error = ed_alloc_port(dev, 0, ED_NOVELL_IO_PORTS); 594 if (error) 595 return (error); 596 597 sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 598 sc->nic_offset = ED_NOVELL_NIC_OFFSET; 599 sc->chip_type = ED_CHIP_TYPE_AX88190; 600 601 /* 602 * Set Attribute Memory IOBASE Register 603 */ 604 iobase = rman_get_start(sc->port_res); 605 ed_pccard_memwrite(dev, ED_AX88190_IOBASE0, iobase & 0xff); 606 ed_pccard_memwrite(dev, ED_AX88190_IOBASE1, (iobase >> 8) & 0xff); 607 ax88190_geteprom(sc); 608 ed_release_resources(dev); 609 error = ed_probe_Novell(dev, 0, flags); 610 return (error); 611} 612 613#ifndef ED_NO_MIIBUS 614/* MII bit-twiddling routines for cards using Dlink chipset */ 615#define DLINK_MIISET(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \ 616 ed_asic_inb(sc, ED_DLINK_MIIBUS) | (x)) 617#define DLINK_MIICLR(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \ 618 ed_asic_inb(sc, ED_DLINK_MIIBUS) & ~(x)) 619 620static void 621ed_pccard_dlink_mii_reset(sc) 622 struct ed_softc *sc; 623{ 624 ed_asic_outb(sc, ED_DLINK_MIIBUS, 0); 625 DELAY(10); 626 DLINK_MIISET(sc, ED_DLINK_MII_RESET2); 627 DELAY(10); 628 DLINK_MIISET(sc, ED_DLINK_MII_RESET1); 629 DELAY(10); 630 DLINK_MIICLR(sc, ED_DLINK_MII_RESET1); 631 DELAY(10); 632 DLINK_MIICLR(sc, ED_DLINK_MII_RESET2); 633 DELAY(10); 634} 635 636static void 637ed_pccard_dlink_mii_writebits(sc, val, nbits) 638 struct ed_softc *sc; 639 u_int val; 640 int nbits; 641{ 642 int i; 643 644 DLINK_MIISET(sc, ED_DLINK_MII_DIROUT); 645 646 for (i = nbits - 1; i >= 0; i--) { 647 if ((val >> i) & 1) 648 DLINK_MIISET(sc, ED_DLINK_MII_DATAOUT); 649 else 650 DLINK_MIICLR(sc, ED_DLINK_MII_DATAOUT); 651 DELAY(10); 652 DLINK_MIISET(sc, ED_DLINK_MII_CLK); 653 DELAY(10); 654 DLINK_MIICLR(sc, ED_DLINK_MII_CLK); 655 DELAY(10); 656 } 657} 658 659static u_int 660ed_pccard_dlink_mii_readbits(sc, nbits) 661 struct ed_softc *sc; 662 int nbits; 663{ 664 int i; 665 u_int val = 0; 666 667 DLINK_MIICLR(sc, ED_DLINK_MII_DIROUT); 668 669 for (i = nbits - 1; i >= 0; i--) { 670 DLINK_MIISET(sc, ED_DLINK_MII_CLK); 671 DELAY(10); 672 val <<= 1; 673 if (ed_asic_inb(sc, ED_DLINK_MIIBUS) & ED_DLINK_MII_DATATIN) 674 val++; 675 DLINK_MIICLR(sc, ED_DLINK_MII_CLK); 676 DELAY(10); 677 } 678 679 return val; 680} 681#endif 682 683static device_method_t ed_pccard_methods[] = { 684 /* Device interface */ 685 DEVMETHOD(device_probe, pccard_compat_probe), 686 DEVMETHOD(device_attach, pccard_compat_attach), 687 DEVMETHOD(device_detach, ed_pccard_detach), 688 689#ifndef ED_NO_MIIBUS 690 /* Bus interface */ 691 DEVMETHOD(bus_child_detached, ed_child_detached), 692 693 /* MII interface */ 694 DEVMETHOD(miibus_readreg, ed_miibus_readreg), 695 DEVMETHOD(miibus_writereg, ed_miibus_writereg), 696#endif 697 698 /* Card interface */ 699 DEVMETHOD(card_compat_match, ed_pccard_match), 700 DEVMETHOD(card_compat_probe, ed_pccard_probe), 701 DEVMETHOD(card_compat_attach, ed_pccard_attach), 702 { 0, 0 } 703}; 704 705static driver_t ed_pccard_driver = { 706 "ed", 707 ed_pccard_methods, 708 sizeof(struct ed_softc) 709}; 710 711DRIVER_MODULE(if_ed, pccard, ed_pccard_driver, ed_devclass, 0, 0); 712#ifndef ED_NO_MIIBUS 713DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0); 714#endif 715