Annotation of sys/dev/pci/if_re_pci.c, Revision 1.1.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