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