if_dc_pci.c revision 1.8
1/* $OpenBSD: if_dc_pci.c,v 1.8 2000/10/27 18:13:44 aaron Exp $ */ 2 3/* 4 * Copyright (c) 1997, 1998, 1999 5 * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Bill Paul. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 * THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * $FreeBSD: src/sys/pci/if_dc.c,v 1.5 2000/01/12 22:24:05 wpaul Exp $ 35 */ 36 37#include "bpfilter.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/mbuf.h> 42#include <sys/protosw.h> 43#include <sys/socket.h> 44#include <sys/ioctl.h> 45#include <sys/errno.h> 46#include <sys/malloc.h> 47#include <sys/kernel.h> 48#include <sys/device.h> 49 50#include <net/if.h> 51#include <net/if_dl.h> 52#include <net/if_types.h> 53 54#ifdef INET 55#include <netinet/in.h> 56#include <netinet/in_systm.h> 57#include <netinet/in_var.h> 58#include <netinet/ip.h> 59#include <netinet/if_ether.h> 60#endif 61 62#include <net/if_media.h> 63 64#if NBPFILTER > 0 65#include <net/bpf.h> 66#endif 67 68#include <vm/vm.h> /* for vtophys */ 69#include <vm/pmap.h> /* for vtophys */ 70 71#include <dev/mii/mii.h> 72#include <dev/mii/miivar.h> 73 74#include <dev/pci/pcireg.h> 75#include <dev/pci/pcivar.h> 76#include <dev/pci/pcidevs.h> 77 78#define DC_USEIOSPACE 79 80#include <dev/ic/dcreg.h> 81 82/* 83 * Various supported device vendors/types and their names. 84 */ 85struct dc_type dc_devs[] = { 86 { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142 }, 87 { PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9100 }, 88 { PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9102 }, 89 { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AL981 }, 90 { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN983 }, 91 { PCI_VENDOR_ASIX, PCI_PRODUCT_ASIX_AX88140A }, 92 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713 }, 93 { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98715 }, 94 { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_98713 }, 95 { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNIC }, 96 { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_PNICII }, 97 { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN1217 }, 98 { 0, 0 } 99}; 100 101int dc_pci_probe __P((struct device *, void *, void *)); 102void dc_pci_attach __P((struct device *, struct device *, void *)); 103void dc_pci_acpi __P((struct device *, void *)); 104 105/* 106 * Probe for a 21143 or clone chip. Check the PCI vendor and device 107 * IDs against our list and return a device name if we find a match. 108 */ 109int 110dc_pci_probe(parent, match, aux) 111 struct device *parent; 112 void *match, *aux; 113{ 114 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 115 struct dc_type *t; 116 117 for (t = dc_devs; t->dc_vid != 0; t++) { 118 if ((PCI_VENDOR(pa->pa_id) == t->dc_vid) && 119 (PCI_PRODUCT(pa->pa_id) == t->dc_did)) 120 return (1); 121 } 122 return (0); 123} 124 125void dc_pci_acpi(self, aux) 126 struct device *self; 127 void *aux; 128{ 129 struct dc_softc *sc = (struct dc_softc *)self; 130 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 131 pci_chipset_tag_t pc = pa->pa_pc; 132 u_int32_t r, cptr; 133 int unit; 134 135 unit = sc->dc_unit; 136 137 /* Find the location of the capabilities block */ 138 cptr = pci_conf_read(pc, pa->pa_tag, DC_PCI_CCAP) & 0xFF; 139 140 r = pci_conf_read(pc, pa->pa_tag, cptr) & 0xFF; 141 if (r == 0x01) { 142 143 r = pci_conf_read(pc, pa->pa_tag, cptr + 4); 144 if (r & DC_PSTATE_D3) { 145 u_int32_t iobase, membase, irq; 146 147 /* Save important PCI config data. */ 148 iobase = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFBIO); 149 membase = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFBMA); 150 irq = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFIT); 151 152 /* Reset the power state. */ 153 printf("dc%d: chip is in D%d power mode " 154 "-- setting to D0\n", unit, r & DC_PSTATE_D3); 155 r &= 0xFFFFFFFC; 156 pci_conf_write(pc, pa->pa_tag, cptr + 4, r); 157 158 /* Restore PCI config data. */ 159 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFBIO, iobase); 160 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFBMA, membase); 161 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFIT, irq); 162 } 163 } 164 return; 165} 166 167/* 168 * Attach the interface. Allocate softc structures, do ifmedia 169 * setup and ethernet/BPF attach. 170 */ 171void dc_pci_attach(parent, self, aux) 172 struct device *parent, *self; 173 void *aux; 174{ 175 int s; 176 const char *intrstr = NULL; 177 u_int32_t command; 178 struct dc_softc *sc = (struct dc_softc *)self; 179 struct pci_attach_args *pa = aux; 180 pci_chipset_tag_t pc = pa->pa_pc; 181 pci_intr_handle_t ih; 182 bus_addr_t iobase; 183 bus_size_t iosize; 184 u_int32_t revision; 185 int found = 0; 186 187 s = splimp(); 188 sc->dc_unit = sc->sc_dev.dv_unit; 189 190 /* 191 * Handle power management nonsense. 192 */ 193 dc_pci_acpi(self, aux); 194 195 /* 196 * Map control/status registers. 197 */ 198 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 199 command |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 200 PCI_COMMAND_MASTER_ENABLE; 201 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); 202 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 203 204 sc->dc_csid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 205 206#ifdef DC_USEIOSPACE 207 if (!(command & PCI_COMMAND_IO_ENABLE)) { 208 printf(": failed to enable I/O ports\n"); 209 goto fail; 210 } 211 if (pci_io_find(pc, pa->pa_tag, DC_PCI_CFBIO, &iobase, &iosize)) { 212 printf(": can't find I/O space\n"); 213 goto fail; 214 } 215 if (bus_space_map(pa->pa_iot, iobase, iosize, 0, &sc->dc_bhandle)) { 216 printf(": can't map I/O space\n"); 217 goto fail; 218 } 219 sc->dc_btag = pa->pa_iot; 220#else 221 if (!(command & PCI_COMMAND_MEM_ENABLE)) { 222 printf(": failed to enable memory mapping\n"); 223 goto fail; 224 } 225 if (pci_mem_find(pc, pa->pa_tag, DC_PCI_CFBMA, &iobase, &iosize, NULL)){ 226 printf(": can't find mem space\n"); 227 goto fail; 228 } 229 if (bus_space_map(pa->pa_memt, iobase, iosize, 0, &sc->dc_bhandle)) { 230 printf(": can't map mem space\n"); 231 goto fail; 232 } 233 sc->dc_btag = pa->pa_memt; 234#endif 235 236 /* Allocate interrupt */ 237 if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline, 238 &ih)) { 239 printf(": couldn't map interrupt\n"); 240 goto fail; 241 } 242 intrstr = pci_intr_string(pc, ih); 243 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, dc_intr, sc, 244 self->dv_xname); 245 if (sc->sc_ih == NULL) { 246 printf(": couldn't establish interrupt"); 247 if (intrstr != NULL) 248 printf(" at %s", intrstr); 249 printf("\n"); 250 goto fail; 251 } 252 printf(": %s", intrstr); 253 254 /* Need this info to decide on a chip type. */ 255 sc->dc_revision = revision = PCI_REVISION(pa->pa_class); 256 257 switch (PCI_VENDOR(pa->pa_id)) { 258 case PCI_VENDOR_DEC: 259 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DEC_21142) { 260 found = 1; 261 sc->dc_type = DC_TYPE_21143; 262 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 263 sc->dc_flags |= DC_REDUCED_MII_POLL; 264 } 265 break; 266 case PCI_VENDOR_DAVICOM: 267 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9100 || 268 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9102) { 269 found = 1; 270 sc->dc_type = DC_TYPE_DM9102; 271 sc->dc_flags |= DC_TX_COALESCE|DC_TX_INTR_ALWAYS; 272 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_TX_STORENFWD; 273 sc->dc_pmode = DC_PMODE_MII; 274 } 275 break; 276 case PCI_VENDOR_ADMTEK: 277 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AL981) { 278 found = 1; 279 sc->dc_type = DC_TYPE_AL981; 280 sc->dc_flags |= DC_TX_USE_TX_INTR; 281 sc->dc_flags |= DC_TX_ADMTEK_WAR; 282 sc->dc_pmode = DC_PMODE_MII; 283 } 284 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADMTEK_AN983) { 285 found = 1; 286 sc->dc_type = DC_TYPE_AN983; 287 sc->dc_flags |= DC_TX_USE_TX_INTR; 288 sc->dc_flags |= DC_TX_ADMTEK_WAR; 289 sc->dc_pmode = DC_PMODE_MII; 290 } 291 break; 292 case PCI_VENDOR_MACRONIX: 293 case PCI_VENDOR_ACCTON: 294 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98713) { 295 found = 1; 296 if (revision < DC_REVISION_98713A) { 297 sc->dc_type = DC_TYPE_98713; 298 } 299 if (revision >= DC_REVISION_98713A) { 300 sc->dc_type = DC_TYPE_98713A; 301 sc->dc_flags |= DC_21143_NWAY; 302 } 303 sc->dc_flags |= DC_REDUCED_MII_POLL; 304 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 305 } 306 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MACRONIX_MX98715 || 307 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ACCTON_EN1217) { 308 found = 1; 309 if (revision >= DC_REVISION_98715AEC_C && 310 revision < DC_REVISION_98725) 311 sc->dc_flags |= DC_128BIT_HASH; 312 sc->dc_type = DC_TYPE_987x5; 313 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 314 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; 315 } 316 break; 317 case PCI_VENDOR_COMPEX: 318 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_COMPEX_98713) { 319 found = 1; 320 if (revision < DC_REVISION_98713A) { 321 sc->dc_type = DC_TYPE_98713; 322 sc->dc_flags |= DC_REDUCED_MII_POLL; 323 } 324 if (revision >= DC_REVISION_98713A) 325 sc->dc_type = DC_TYPE_98713A; 326 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 327 } 328 break; 329 case PCI_VENDOR_LITEON: 330 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNICII) { 331 found = 1; 332 sc->dc_type = DC_TYPE_PNICII; 333 sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 334 sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; 335 sc->dc_flags |= DC_128BIT_HASH; 336 } 337 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LITEON_PNIC) { 338 found = 1; 339 sc->dc_type = DC_TYPE_PNIC; 340 sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS; 341 sc->dc_flags |= DC_PNIC_RX_BUG_WAR; 342 sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, 343 M_NOWAIT); 344 if (revision < DC_REVISION_82C169) 345 sc->dc_pmode = DC_PMODE_SYM; 346 } 347 break; 348 case PCI_VENDOR_ASIX: 349 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASIX_AX88140A) { 350 found = 1; 351 sc->dc_type = DC_TYPE_ASIX; 352 sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_INTR_FIRSTFRAG; 353 sc->dc_flags |= DC_REDUCED_MII_POLL; 354 sc->dc_pmode = DC_PMODE_MII; 355 } 356 break; 357 } 358 if (found == 0) { 359 /* This shouldn't happen if probe has done it's job... */ 360 printf(": unknown device: %x:%x\n", 361 PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)); 362 goto fail; 363 } 364 365 /* Save the cache line size. */ 366 if (DC_IS_DAVICOM(sc)) 367 sc->dc_cachesize = 0; 368 else 369 sc->dc_cachesize = pci_conf_read(pc, pa->pa_tag, 370 DC_PCI_CFLT) & 0xFF; 371 372 /* Reset the adapter. */ 373 dc_reset(sc); 374 375 /* Take 21143 out of snooze mode */ 376 if (DC_IS_INTEL(sc)) { 377 command = pci_conf_read(pc, pa->pa_tag, DC_PCI_CFDD); 378 command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); 379 pci_conf_write(pc, pa->pa_tag, DC_PCI_CFDD, command); 380 } 381 382 /* 383 * If we discover later (in dc_attach_common()) that we have an 384 * MII with no PHY, we need to have the 21143 drive the LEDs. 385 * Except there are some systems like the NEC VersaPro NoteBook PC 386 * which have no LEDs, and twiddling these bits has adverse effects 387 * on them. (I.e. you suddenly can't get a link.) 388 * 389 * If mii_attach() returns an error, we leave the DC_TULIP_LEDS 390 * bit set, else we clear it. Since our dc(4) driver is split into 391 * bus-dependent and bus-independent parts, we must do set this bit 392 * here while we are able to do PCI configuration reads. 393 */ 394 if (DC_IS_INTEL(sc)) { 395 if (pci_conf_read(pc, pa->pa_tag, DC_PCI_CSID) != 0x80281033) 396 sc->dc_flags |= DC_TULIP_LEDS; 397 } 398 399 /* 400 * Try to learn something about the supported media. 401 * We know that ASIX and ADMtek and Davicom devices 402 * will *always* be using MII media, so that's a no-brainer. 403 * The tricky ones are the Macronix/PNIC II and the 404 * Intel 21143. 405 */ 406 if (DC_IS_INTEL(sc)) { 407 u_int32_t media, cwuc; 408 cwuc = pci_conf_read(pc, pa->pa_tag, DC_PCI_CWUC); 409 cwuc |= DC_CWUC_FORCE_WUL; 410 pci_conf_write(pc, pa->pa_tag, DC_PCI_CWUC, cwuc); 411 DELAY(10000); 412 media = pci_conf_read(pc, pa->pa_tag, DC_PCI_CWUC); 413 cwuc &= ~DC_CWUC_FORCE_WUL; 414 pci_conf_write(pc, pa->pa_tag, DC_PCI_CWUC, cwuc); 415 DELAY(10000); 416 if (media & DC_CWUC_MII_ABILITY) 417 sc->dc_pmode = DC_PMODE_MII; 418 if (media & DC_CWUC_SYM_ABILITY) { 419 sc->dc_pmode = DC_PMODE_SYM; 420 sc->dc_flags |= DC_21143_NWAY; 421 } 422 /* 423 * If none of the bits are set, then this NIC 424 * isn't meant to support 'wake up LAN' mode. 425 * This is usually only the case on multiport 426 * cards, and these cards almost always have 427 * MII transceivers. 428 */ 429 if (media == 0) 430 sc->dc_pmode = DC_PMODE_MII; 431 } else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) { 432 if (sc->dc_type == DC_TYPE_98713) 433 sc->dc_pmode = DC_PMODE_MII; 434 else 435 sc->dc_pmode = DC_PMODE_SYM; 436 } else if (!sc->dc_pmode) 437 sc->dc_pmode = DC_PMODE_MII; 438 439 dc_attach_common(sc); 440 441fail: 442 splx(s); 443} 444 445struct cfattach dc_pci_ca = { 446 sizeof(struct dc_softc), dc_pci_probe, dc_pci_attach 447}; 448