Annotation of sys/dev/pci/if_re_pci.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_re_pci.c,v 1.19 2006/11/28 20:04:02 brad Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Peter Valchev <pvalchev@openbsd.org>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: /*
! 20: * PCI front-end for the Realtek 8169
! 21: */
! 22:
! 23: #include <sys/param.h>
! 24: #include <sys/endian.h>
! 25: #include <sys/systm.h>
! 26: #include <sys/sockio.h>
! 27: #include <sys/mbuf.h>
! 28: #include <sys/malloc.h>
! 29: #include <sys/kernel.h>
! 30: #include <sys/device.h>
! 31: #include <sys/timeout.h>
! 32: #include <sys/socket.h>
! 33:
! 34: #include <net/if.h>
! 35: #include <net/if_dl.h>
! 36: #include <net/if_media.h>
! 37:
! 38: #ifdef INET
! 39: #include <netinet/in.h>
! 40: #include <netinet/in_systm.h>
! 41: #include <netinet/in_var.h>
! 42: #include <netinet/ip.h>
! 43: #include <netinet/if_ether.h>
! 44: #endif
! 45:
! 46: #include <dev/mii/mii.h>
! 47: #include <dev/mii/miivar.h>
! 48:
! 49: #include <dev/pci/pcireg.h>
! 50: #include <dev/pci/pcivar.h>
! 51: #include <dev/pci/pcidevs.h>
! 52:
! 53: #include <dev/ic/rtl81x9reg.h>
! 54: #include <dev/ic/revar.h>
! 55:
! 56: struct re_pci_softc {
! 57: /* General */
! 58: struct rl_softc sc_rl;
! 59:
! 60: /* PCI-specific data */
! 61: void *sc_ih;
! 62: pci_chipset_tag_t sc_pc;
! 63: pcitag_t sc_pcitag;
! 64: };
! 65:
! 66: const struct pci_matchid re_pci_devices[] = {
! 67: { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8101E },
! 68: { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8168 },
! 69: { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169 },
! 70: { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169SC },
! 71: { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_CGLAPCIGT },
! 72: { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE528T },
! 73: { PCI_VENDOR_USR2, PCI_PRODUCT_USR2_USR997902 },
! 74: { PCI_VENDOR_TTTECH, PCI_PRODUCT_TTTECH_MC322 }
! 75: };
! 76:
! 77: #define RE_LINKSYS_EG1032_SUBID 0x00241737
! 78:
! 79: int re_pci_probe(struct device *, void *, void *);
! 80: void re_pci_attach(struct device *, struct device *, void *);
! 81:
! 82: /*
! 83: * PCI autoconfig definitions
! 84: */
! 85: struct cfattach re_pci_ca = {
! 86: sizeof(struct re_pci_softc),
! 87: re_pci_probe,
! 88: re_pci_attach
! 89: };
! 90:
! 91: /*
! 92: * Probe for a Realtek 8169/8110 chip. Check the PCI vendor and device
! 93: * IDs against our list and return a device name if we find a match.
! 94: */
! 95: int
! 96: re_pci_probe(struct device *parent, void *match, void *aux)
! 97: {
! 98: struct pci_attach_args *pa = aux;
! 99: pci_chipset_tag_t pc = pa->pa_pc;
! 100: pcireg_t subid;
! 101:
! 102: subid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
! 103:
! 104: /* C+ mode 8139's */
! 105: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK &&
! 106: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RT8139 &&
! 107: PCI_REVISION(pa->pa_class) == 0x20)
! 108: return (1);
! 109:
! 110: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_LINKSYS &&
! 111: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LINKSYS_EG1032 &&
! 112: subid == RE_LINKSYS_EG1032_SUBID)
! 113: return (1);
! 114:
! 115: return (pci_matchbyid((struct pci_attach_args *)aux, re_pci_devices,
! 116: sizeof(re_pci_devices)/sizeof(re_pci_devices[0])));
! 117: }
! 118:
! 119: /*
! 120: * PCI-specific attach routine
! 121: */
! 122: void
! 123: re_pci_attach(struct device *parent, struct device *self, void *aux)
! 124: {
! 125: struct re_pci_softc *psc = (struct re_pci_softc *)self;
! 126: struct rl_softc *sc = &psc->sc_rl;
! 127: struct pci_attach_args *pa = aux;
! 128: pci_chipset_tag_t pc = pa->pa_pc;
! 129: pci_intr_handle_t ih;
! 130: const char *intrstr = NULL;
! 131: bus_size_t iosize;
! 132: pcireg_t command;
! 133:
! 134: /*
! 135: * Handle power management nonsense.
! 136: */
! 137:
! 138: command = pci_conf_read(pc, pa->pa_tag, RL_PCI_CAPID) & 0x000000FF;
! 139:
! 140: if (command == 0x01) {
! 141: u_int32_t iobase, membase, irq;
! 142:
! 143: /* Save important PCI config data. */
! 144: iobase = pci_conf_read(pc, pa->pa_tag, RL_PCI_LOIO);
! 145: membase = pci_conf_read(pc, pa->pa_tag, RL_PCI_LOMEM);
! 146: irq = pci_conf_read(pc, pa->pa_tag, RL_PCI_INTLINE);
! 147:
! 148: #if 0
! 149: /* Reset the power state. */
! 150: printf(": chip is in D%d power mode "
! 151: "-- setting to D0", command & RL_PSTATE_MASK);
! 152: #endif
! 153: command &= 0xFFFFFFFC;
! 154:
! 155: /* Restore PCI config data. */
! 156: pci_conf_write(pc, pa->pa_tag, RL_PCI_LOIO, iobase);
! 157: pci_conf_write(pc, pa->pa_tag, RL_PCI_LOMEM, membase);
! 158: pci_conf_write(pc, pa->pa_tag, RL_PCI_INTLINE, irq);
! 159: }
! 160:
! 161: /*
! 162: * Map control/status registers.
! 163: */
! 164: if (pci_mapreg_map(pa, RL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
! 165: &sc->rl_btag, &sc->rl_bhandle, NULL, &iosize, 0)) {
! 166: if (pci_mapreg_map(pa, RL_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
! 167: &sc->rl_btag, &sc->rl_bhandle, NULL, &iosize, 0)) {
! 168: printf(": can't map mem or i/o space\n");
! 169: return;
! 170: }
! 171: }
! 172:
! 173: /* Allocate interrupt */
! 174: if (pci_intr_map(pa, &ih)) {
! 175: printf(": couldn't map interrupt\n");
! 176: return;
! 177: }
! 178: intrstr = pci_intr_string(pc, ih);
! 179: psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, re_intr, sc,
! 180: sc->sc_dev.dv_xname);
! 181: if (psc->sc_ih == NULL) {
! 182: printf(": couldn't establish interrupt");
! 183: if (intrstr != NULL)
! 184: printf(" at %s", intrstr);
! 185: return;
! 186: }
! 187:
! 188: sc->sc_dmat = pa->pa_dmat;
! 189: sc->sc_flags |= RL_ENABLED;
! 190:
! 191: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK) {
! 192: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RT8139)
! 193: sc->rl_type = RL_8139CPLUS;
! 194: else
! 195: sc->rl_type = RL_8169;
! 196: } else if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TTTECH &&
! 197: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TTTECH_MC322)
! 198: sc->rl_type = RL_8139CPLUS;
! 199: else
! 200: sc->rl_type = RL_8169;
! 201:
! 202: /* Call bus-independent attach routine */
! 203: re_attach(sc, intrstr);
! 204: }
CVSweb