if_ed_pccard.c revision 100531
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 100531 2002-07-22 21:28:46Z 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, FAST_ETHER_PCC_TX, 0), 267 -1, { 0x00, 0x00, 0xf4 }, NE2000DVF_DL10019 }, 268 { PCMCIA_CARD(COREGA, FETHER_PCC_TXD, 0), 269 -1, { 0x00, 0x90, 0x99 } }, 270 { PCMCIA_CARD(COREGA, FETHER_PCC_TXF, 0), 271 -1, { 0x00, 0x90, 0x99 }, NE2000DVF_DL10019 }, 272 { PCMCIA_CARD(COMPEX, LINKPORT_ENET_B, 0), 273 0x01c0, { 0x00, 0xa0, 0x0c } }, 274 { PCMCIA_CARD(SMC, EZCARD, 0), 275 0x01c0, { 0x00, 0xe0, 0x29 } }, 276 { PCMCIA_CARD(SOCKET, EA_ETHER, 0), 277 -1, { 0x00, 0xc0, 0x1b } }, 278 { PCMCIA_CARD(SOCKET, LP_ETHER_CF, 0), 279 -1, { 0x00, 0xc0, 0x1b } }, 280 { PCMCIA_CARD(SOCKET, LP_ETHER, 0), 281 -1, { 0x00, 0xc0, 0x1b } }, 282 { PCMCIA_CARD(KINGSTON, KNE2, 0), 283 -1, { 0x00, 0xc0, 0xf0 } }, 284 { PCMCIA_CARD(XIRCOM, CFE_10, 0), 285 -1, { 0x00, 0x10, 0xa4 } }, 286 { PCMCIA_CARD(MELCO, LPC3_TX, 0), 287 -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 }, 288 { PCMCIA_CARD(BILLIONTON, LNT10TN, 0), 289 -1, { 0x00, 0x00, 0x00 } }, 290 { PCMCIA_CARD(NDC, ND5100_E, 0), 291 -1, { 0x00, 0x80, 0xc6 } }, 292 { PCMCIA_CARD(TELECOMDEVICE, TCD_HPC100, 0), 293 -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 }, 294 { PCMCIA_CARD(MACNICA, ME1_JEIDA, 0), 295 0x00b8, { 0x08, 0x00, 0x42 } }, 296 { PCMCIA_CARD(ALLIEDTELESIS, LA_PCM, 0), 297 0x0ff0, { 0x00, 0x00, 0xf4 } }, 298 { PCMCIA_CARD(NETGEAR, FA410TXC, 0), 299 -1, { 0x00, 0x48, 0x54 } }, 300 { PCMCIA_CARD(NETGEAR, FA411, 0), 301 -1, { 0x00, 0x40, 0xf4 }, NE2000DVF_AX88190}, 302 303#if 0 304 /* the rest of these are stolen from the linux pcnet pcmcia device 305 driver. Since I don't know the manfid or cis info strings for 306 any of them, they're not compiled in until I do. */ 307 { "APEX MultiCard", 308 0x0000, 0x0000, NULL, NULL, 0, 309 0x03f4, { 0x00, 0x20, 0xe5 } }, 310 { "ASANTE FriendlyNet", 311 0x0000, 0x0000, NULL, NULL, 0, 312 0x4910, { 0x00, 0x00, 0x94 } }, 313 { "Danpex EN-6200P2", 314 0x0000, 0x0000, NULL, NULL, 0, 315 0x0110, { 0x00, 0x40, 0xc7 } }, 316 { "DataTrek NetCard", 317 0x0000, 0x0000, NULL, NULL, 0, 318 0x0ff0, { 0x00, 0x20, 0xe8 } }, 319 { "Dayna CommuniCard E", 320 0x0000, 0x0000, NULL, NULL, 0, 321 0x0110, { 0x00, 0x80, 0x19 } }, 322 { "EP-210 Ethernet", 323 0x0000, 0x0000, NULL, NULL, 0, 324 0x0110, { 0x00, 0x40, 0x33 } }, 325 { "ELECOM Laneed LD-CDWA", 326 0x0000, 0x0000, NULL, NULL, 0, 327 0x00b8, { 0x08, 0x00, 0x42 } }, 328 { "Grey Cell GCS2220", 329 0x0000, 0x0000, NULL, NULL, 0, 330 0x0000, { 0x00, 0x47, 0x43 } }, 331 { "Hypertec Ethernet", 332 0x0000, 0x0000, NULL, NULL, 0, 333 0x01c0, { 0x00, 0x40, 0x4c } }, 334 { "IBM CCAE", 335 0x0000, 0x0000, NULL, NULL, 0, 336 0x0ff0, { 0x08, 0x00, 0x5a } }, 337 { "IBM CCAE", 338 0x0000, 0x0000, NULL, NULL, 0, 339 0x0ff0, { 0x00, 0x04, 0xac } }, 340 { "IBM CCAE", 341 0x0000, 0x0000, NULL, NULL, 0, 342 0x0ff0, { 0x00, 0x06, 0x29 } }, 343 { "IBM FME", 344 0x0000, 0x0000, NULL, NULL, 0, 345 0x0374, { 0x00, 0x04, 0xac } }, 346 { "IBM FME", 347 0x0000, 0x0000, NULL, NULL, 0, 348 0x0374, { 0x08, 0x00, 0x5a } }, 349 { "Katron PE-520", 350 0x0000, 0x0000, NULL, NULL, 0, 351 0x0110, { 0x00, 0x40, 0xf6 } }, 352 { "Kingston KNE-PCM/x", 353 0x0000, 0x0000, NULL, NULL, 0, 354 0x0ff0, { 0x00, 0xc0, 0xf0 } }, 355 { "Kingston KNE-PCM/x", 356 0x0000, 0x0000, NULL, NULL, 0, 357 0x0ff0, { 0xe2, 0x0c, 0x0f } }, 358 { "Longshine LCS-8534", 359 0x0000, 0x0000, NULL, NULL, 0, 360 0x0000, { 0x08, 0x00, 0x00 } }, 361 { "Maxtech PCN2000", 362 0x0000, 0x0000, NULL, NULL, 0, 363 0x5000, { 0x00, 0x00, 0xe8 } }, 364 { "NDC Instant-Link", 365 0x0000, 0x0000, NULL, NULL, 0, 366 0x003a, { 0x00, 0x80, 0xc6 } }, 367 { "NE2000 Compatible", 368 0x0000, 0x0000, NULL, NULL, 0, 369 0x0ff0, { 0x00, 0xa0, 0x0c } }, 370 { "Network General Sniffer", 371 0x0000, 0x0000, NULL, NULL, 0, 372 0x0ff0, { 0x00, 0x00, 0x65 } }, 373 { "Panasonic VEL211", 374 0x0000, 0x0000, NULL, NULL, 0, 375 0x0ff0, { 0x00, 0x80, 0x45 } }, 376 { "SCM Ethernet", 377 0x0000, 0x0000, NULL, NULL, 0, 378 0x0ff0, { 0x00, 0x20, 0xcb } }, 379 { "Volktek NPL-402CT", 380 0x0000, 0x0000, NULL, NULL, 0, 381 0x0060, { 0x00, 0x40, 0x05 } }, 382#endif 383 { { NULL } } 384 385}; 386 387static int 388ed_pccard_match(device_t dev) 389{ 390 const struct ed_product *pp; 391 392 if ((pp = (const struct ed_product *) pccard_product_lookup(dev, 393 (const struct pccard_product *) ed_pccard_products, 394 sizeof(ed_pccard_products[0]), NULL)) != NULL) { 395 device_set_desc(dev, pp->prod.pp_name); 396 if (pp->flags & NE2000DVF_DL10019) 397 device_set_flags(dev, ED_FLAGS_LINKSYS); 398 else if (pp->flags & NE2000DVF_AX88190) 399 device_set_flags(dev, ED_FLAGS_AX88190); 400 return (0); 401 } 402 return (EIO); 403} 404 405/* 406 * Probe framework for pccards. Replicates the standard framework, 407 * minus the pccard driver registration and ignores the ether address 408 * supplied (from the CIS), relying on the probe to find it instead. 409 */ 410static int 411ed_pccard_probe(device_t dev) 412{ 413 int error; 414 int flags = device_get_flags(dev); 415 416 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_AX88190) { 417 error = ed_pccard_ax88190(dev); 418 goto end2; 419 } 420 421 error = ed_probe_Novell(dev, 0, flags); 422 if (error == 0) 423 goto end; 424 ed_release_resources(dev); 425 426 error = ed_probe_WD80x3(dev, 0, flags); 427 if (error == 0) 428 goto end; 429 ed_release_resources(dev); 430 goto end2; 431 432end: 433 if (ED_FLAGS_GETTYPE(flags) & ED_FLAGS_LINKSYS) 434 ed_pccard_Linksys(dev); 435end2: 436 if (error == 0) 437 error = ed_alloc_irq(dev, 0, 0); 438 439 ed_release_resources(dev); 440 return (error); 441} 442 443static int 444ed_pccard_attach(device_t dev) 445{ 446 int error; 447 int flags = device_get_flags(dev); 448 int i; 449 struct ed_softc *sc = device_get_softc(dev); 450 u_char sum; 451 u_char ether_addr[ETHER_ADDR_LEN]; 452 453 if (sc->port_used > 0) 454 ed_alloc_port(dev, sc->port_rid, sc->port_used); 455 if (sc->mem_used) 456 ed_alloc_memory(dev, sc->mem_rid, sc->mem_used); 457 ed_alloc_irq(dev, sc->irq_rid, 0); 458 459 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, 460 edintr, sc, &sc->irq_handle); 461 if (error) { 462 printf("setup intr failed %d \n", error); 463 ed_release_resources(dev); 464 return (error); 465 } 466 467 if (sc->vendor != ED_VENDOR_LINKSYS) { 468 pccard_get_ether(dev, ether_addr); 469 for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) 470 sum |= ether_addr[i]; 471 if (sum) 472 bcopy(ether_addr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 473 } 474 475 error = ed_attach(sc, device_get_unit(dev), flags); 476#ifndef ED_NO_MIIBUS 477 if (error == 0 && sc->vendor == ED_VENDOR_LINKSYS) { 478 /* Probe for an MII bus, but ignore errors. */ 479 ed_pccard_dlink_mii_reset(sc); 480 sc->mii_readbits = ed_pccard_dlink_mii_readbits; 481 sc->mii_writebits = ed_pccard_dlink_mii_writebits; 482 mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd, 483 ed_ifmedia_sts); 484 } 485#endif 486 487 return (error); 488} 489 490static void 491ax88190_geteprom(struct ed_softc *sc) 492{ 493 int prom[16],i; 494 u_char tmp; 495 struct { 496 unsigned char offset, value; 497 } pg_seq[] = { 498 {ED_P0_CR, ED_CR_RD2|ED_CR_STP},/* Select Page0 */ 499 {ED_P0_DCR, 0x01}, 500 {ED_P0_RBCR0, 0x00}, /* Clear the count regs. */ 501 {ED_P0_RBCR1, 0x00}, 502 {ED_P0_IMR, 0x00}, /* Mask completion irq. */ 503 {ED_P0_ISR, 0xff}, 504 {ED_P0_RCR, ED_RCR_MON | ED_RCR_INTT}, /* Set To Monitor */ 505 {ED_P0_TCR, ED_TCR_LB0}, /* loopback mode. */ 506 {ED_P0_RBCR0, 32}, 507 {ED_P0_RBCR1, 0x00}, 508 {ED_P0_RSAR0, 0x00}, 509 {ED_P0_RSAR1, 0x04}, 510 {ED_P0_CR ,ED_CR_RD0 | ED_CR_STA}, 511 }; 512 513 /* Reset Card */ 514 tmp = ed_asic_inb(sc, ED_NOVELL_RESET); 515 ed_asic_outb(sc, ED_NOVELL_RESET, tmp); 516 DELAY(5000); 517 ed_asic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 518 DELAY(5000); 519 520 /* Card Settings */ 521 for (i = 0; i < sizeof(pg_seq) / sizeof(pg_seq[0]); i++) 522 ed_nic_outb(sc, pg_seq[i].offset, pg_seq[i].value); 523 524 /* Get Data */ 525 for (i = 0; i < 16; i++) 526 prom[i] = ed_asic_inb(sc, 0); 527 sc->arpcom.ac_enaddr[0] = prom[0] & 0xff; 528 sc->arpcom.ac_enaddr[1] = prom[0] >> 8; 529 sc->arpcom.ac_enaddr[2] = prom[1] & 0xff; 530 sc->arpcom.ac_enaddr[3] = prom[1] >> 8; 531 sc->arpcom.ac_enaddr[4] = prom[2] & 0xff; 532 sc->arpcom.ac_enaddr[5] = prom[2] >> 8; 533} 534 535static int 536ed_pccard_memwrite(device_t dev, off_t offset, u_char byte) 537{ 538 int cis_rid; 539 struct resource *cis; 540 541 cis_rid = 0; 542 cis = bus_alloc_resource(dev, SYS_RES_MEMORY, &cis_rid, 0, ~0, 543 4 << 10, RF_ACTIVE | RF_SHAREABLE); 544 if (cis == NULL) 545 return (ENXIO); 546 CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, 547 cis_rid, PCCARD_A_MEM_ATTR); 548 549 bus_space_write_1(rman_get_bustag(cis), rman_get_bushandle(cis), 550 offset, byte); 551 552 bus_deactivate_resource(dev, SYS_RES_MEMORY, cis_rid, cis); 553 bus_release_resource(dev, SYS_RES_MEMORY, cis_rid, cis); 554 555 return (0); 556} 557 558/* 559 * Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100 560 * and compatible cards (DL10019C Ethernet controller). 561 * 562 * Note: The PAO patches try to use more memory for the card, but that 563 * seems to fail for my card. A future optimization would add this back 564 * conditionally. 565 */ 566static int 567ed_pccard_Linksys(device_t dev) 568{ 569 struct ed_softc *sc = device_get_softc(dev); 570 u_char sum; 571 int i; 572 573 /* 574 * Linksys registers(offset from ASIC base) 575 * 576 * 0x04-0x09 : Physical Address Register 0-5 (PAR0-PAR5) 577 * 0x0A : Card ID Register (CIR) 578 * 0x0B : Check Sum Register (SR) 579 */ 580 for (sum = 0, i = 0x04; i < 0x0c; i++) 581 sum += ed_asic_inb(sc, i); 582 if (sum != 0xff) 583 return (0); /* invalid DL10019C */ 584 for (i = 0; i < ETHER_ADDR_LEN; i++) { 585 sc->arpcom.ac_enaddr[i] = ed_asic_inb(sc, 0x04 + i); 586 } 587 588 ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); 589 sc->isa16bit = 1; 590 sc->vendor = ED_VENDOR_LINKSYS; 591 sc->type = ED_TYPE_NE2000; 592 sc->type_str = "Linksys"; 593 594 return (1); 595} 596 597/* 598 * Special setup for AX88190 599 */ 600static int 601ed_pccard_ax88190(device_t dev) 602{ 603 int error; 604 int flags = device_get_flags(dev); 605 int iobase; 606 struct ed_softc *sc = device_get_softc(dev); 607 608 /* Allocate the port resource during setup. */ 609 error = ed_alloc_port(dev, 0, ED_NOVELL_IO_PORTS); 610 if (error) 611 return (error); 612 613 sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 614 sc->nic_offset = ED_NOVELL_NIC_OFFSET; 615 sc->chip_type = ED_CHIP_TYPE_AX88190; 616 617 /* 618 * Set Attribute Memory IOBASE Register 619 */ 620 iobase = rman_get_start(sc->port_res); 621 ed_pccard_memwrite(dev, ED_AX88190_IOBASE0, iobase & 0xff); 622 ed_pccard_memwrite(dev, ED_AX88190_IOBASE1, (iobase >> 8) & 0xff); 623 ax88190_geteprom(sc); 624 ed_release_resources(dev); 625 error = ed_probe_Novell(dev, 0, flags); 626 if (error == 0) { 627 sc->vendor = ED_VENDOR_PCCARD; 628 sc->type = ED_TYPE_NE2000; 629 sc->type_str = "AX88190"; 630 } 631 return (error); 632} 633 634#ifndef ED_NO_MIIBUS 635/* MII bit-twiddling routines for cards using Dlink chipset */ 636#define DLINK_MIISET(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \ 637 ed_asic_inb(sc, ED_DLINK_MIIBUS) | (x)) 638#define DLINK_MIICLR(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \ 639 ed_asic_inb(sc, ED_DLINK_MIIBUS) & ~(x)) 640 641static void 642ed_pccard_dlink_mii_reset(sc) 643 struct ed_softc *sc; 644{ 645 ed_asic_outb(sc, ED_DLINK_MIIBUS, 0); 646 DELAY(10); 647 DLINK_MIISET(sc, ED_DLINK_MII_RESET2); 648 DELAY(10); 649 DLINK_MIISET(sc, ED_DLINK_MII_RESET1); 650 DELAY(10); 651 DLINK_MIICLR(sc, ED_DLINK_MII_RESET1); 652 DELAY(10); 653 DLINK_MIICLR(sc, ED_DLINK_MII_RESET2); 654 DELAY(10); 655} 656 657static void 658ed_pccard_dlink_mii_writebits(sc, val, nbits) 659 struct ed_softc *sc; 660 u_int val; 661 int nbits; 662{ 663 int i; 664 665 DLINK_MIISET(sc, ED_DLINK_MII_DIROUT); 666 667 for (i = nbits - 1; i >= 0; i--) { 668 if ((val >> i) & 1) 669 DLINK_MIISET(sc, ED_DLINK_MII_DATAOUT); 670 else 671 DLINK_MIICLR(sc, ED_DLINK_MII_DATAOUT); 672 DELAY(10); 673 DLINK_MIISET(sc, ED_DLINK_MII_CLK); 674 DELAY(10); 675 DLINK_MIICLR(sc, ED_DLINK_MII_CLK); 676 DELAY(10); 677 } 678} 679 680static u_int 681ed_pccard_dlink_mii_readbits(sc, nbits) 682 struct ed_softc *sc; 683 int nbits; 684{ 685 int i; 686 u_int val = 0; 687 688 DLINK_MIICLR(sc, ED_DLINK_MII_DIROUT); 689 690 for (i = nbits - 1; i >= 0; i--) { 691 DLINK_MIISET(sc, ED_DLINK_MII_CLK); 692 DELAY(10); 693 val <<= 1; 694 if (ed_asic_inb(sc, ED_DLINK_MIIBUS) & ED_DLINK_MII_DATATIN) 695 val++; 696 DLINK_MIICLR(sc, ED_DLINK_MII_CLK); 697 DELAY(10); 698 } 699 700 return val; 701} 702#endif 703 704static device_method_t ed_pccard_methods[] = { 705 /* Device interface */ 706 DEVMETHOD(device_probe, pccard_compat_probe), 707 DEVMETHOD(device_attach, pccard_compat_attach), 708 DEVMETHOD(device_detach, ed_pccard_detach), 709 710#ifndef ED_NO_MIIBUS 711 /* Bus interface */ 712 DEVMETHOD(bus_child_detached, ed_child_detached), 713 714 /* MII interface */ 715 DEVMETHOD(miibus_readreg, ed_miibus_readreg), 716 DEVMETHOD(miibus_writereg, ed_miibus_writereg), 717#endif 718 719 /* Card interface */ 720 DEVMETHOD(card_compat_match, ed_pccard_match), 721 DEVMETHOD(card_compat_probe, ed_pccard_probe), 722 DEVMETHOD(card_compat_attach, ed_pccard_attach), 723 { 0, 0 } 724}; 725 726static driver_t ed_pccard_driver = { 727 "ed", 728 ed_pccard_methods, 729 sizeof(struct ed_softc) 730}; 731 732DRIVER_MODULE(if_ed, pccard, ed_pccard_driver, ed_devclass, 0, 0); 733#ifndef ED_NO_MIIBUS 734DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0); 735#endif 736