Annotation of sys/dev/pci/if_xl_pci.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_xl_pci.c,v 1.22 2006/08/10 20:10:19 brad Exp $ */
2:
3: /*
4: * Copyright (c) 1997, 1998, 1999
5: * Bill Paul <wpaul@ctr.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: if_xl.c,v 1.72 2000/01/09 21:12:59 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/proc.h> /* only for declaration of wakeup() used by vm.h */
49: #include <sys/device.h>
50:
51: #include <net/if.h>
52: #include <net/if_dl.h>
53: #include <net/if_types.h>
54: #include <net/if_media.h>
55:
56: #ifdef INET
57: #include <netinet/in.h>
58: #include <netinet/in_systm.h>
59: #include <netinet/in_var.h>
60: #include <netinet/ip.h>
61: #include <netinet/if_ether.h>
62: #endif
63:
64: #include <dev/mii/mii.h>
65: #include <dev/mii/miivar.h>
66: #include <dev/pci/pcireg.h>
67: #include <dev/pci/pcivar.h>
68: #include <dev/pci/pcidevs.h>
69:
70: #if NBPFILTER > 0
71: #include <net/bpf.h>
72: #endif
73:
74: /*
75: * The following #define causes the code to use PIO to access the
76: * chip's registers instead of memory mapped mode. The reason PIO mode
77: * is on by default is that the Etherlink XL manual seems to indicate
78: * that only the newer revision chips (3c905B) support both PIO and
79: * memory mapped access. Since we want to be compatible with the older
80: * bus master chips, we use PIO here. If you comment this out, the
81: * driver will use memory mapped I/O, which may be faster but which
82: * might not work on some devices.
83: */
84: #define XL_USEIOSPACE
85:
86: #define XL_PCI_FUNCMEM 0x0018
87: #define XL_PCI_INTR 0x0004
88: #define XL_PCI_INTRACK 0x8000
89:
90: #include <dev/ic/xlreg.h>
91:
92: int xl_pci_match(struct device *, void *, void *);
93: void xl_pci_attach(struct device *, struct device *, void *);
94: void xl_pci_intr_ack(struct xl_softc *);
95:
96: struct cfattach xl_pci_ca = {
97: sizeof(struct xl_softc), xl_pci_match, xl_pci_attach,
98: };
99:
100: const struct pci_matchid xl_pci_devices[] = {
101: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CSOHO100TX },
102: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900TPO },
103: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900COMBO },
104: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900B },
105: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BCOMBO },
106: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BTPC },
107: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BFL },
108: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905TX },
109: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905T4 },
110: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BTX },
111: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BT4 },
112: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BCOMBO },
113: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BFX },
114: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C980TX },
115: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C980CTX },
116: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905CTX },
117: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C450 },
118: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C555 },
119: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C556 },
120: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C556B },
121: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C9201 },
122: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C920BEMBW },
123: };
124:
125: int
126: xl_pci_match(struct device *parent, void *match, void *aux)
127: {
128: return (pci_matchbyid((struct pci_attach_args *)aux, xl_pci_devices,
129: sizeof(xl_pci_devices)/sizeof(xl_pci_devices[0])));
130: }
131:
132: void
133: xl_pci_attach(struct device *parent, struct device *self, void *aux)
134: {
135: struct xl_softc *sc = (struct xl_softc *)self;
136: struct pci_attach_args *pa = aux;
137: pci_chipset_tag_t pc = pa->pa_pc;
138: pci_intr_handle_t ih;
139: const char *intrstr = NULL;
140: bus_size_t iosize, funsize;
141: u_int32_t command;
142:
143: sc->sc_dmat = pa->pa_dmat;
144:
145: sc->xl_flags = 0;
146:
147: /* set required flags */
148: switch (PCI_PRODUCT(pa->pa_id)) {
149: case TC_DEVICEID_HURRICANE_555:
150: sc->xl_flags |= XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM;
151: break;
152: case TC_DEVICEID_HURRICANE_556:
153: sc->xl_flags |= XL_FLAG_FUNCREG | XL_FLAG_PHYOK |
154: XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_WEIRDRESET;
155: sc->xl_flags |= XL_FLAG_INVERT_LED_PWR|XL_FLAG_INVERT_MII_PWR;
156: sc->xl_flags |= XL_FLAG_8BITROM;
157: break;
158: case TC_DEVICEID_HURRICANE_556B:
159: sc->xl_flags |= XL_FLAG_FUNCREG | XL_FLAG_PHYOK |
160: XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_WEIRDRESET;
161: sc->xl_flags |= XL_FLAG_INVERT_LED_PWR|XL_FLAG_INVERT_MII_PWR;
162: break;
163: case PCI_PRODUCT_3COM_3C9201:
164: case PCI_PRODUCT_3COM_3C920BEMBW:
165: sc->xl_flags |= XL_FLAG_PHYOK;
166: break;
167: case TC_DEVICEID_BOOMERANG_10_100BT:
168: sc->xl_flags |= XL_FLAG_NO_MMIO;
169: break;
170: default:
171: break;
172: }
173:
174: /*
175: * If this is a 3c905B, we have to check one extra thing.
176: * The 905B supports power management and may be placed in
177: * a low-power mode (D3 mode), typically by certain operating
178: * systems which shall not be named. The PCI BIOS is supposed
179: * to reset the NIC and bring it out of low-power mode, but
180: * some do not. Consequently, we have to see if this chip
181: * supports power management, and if so, make sure it's not
182: * in low-power mode. If power management is available, the
183: * capid byte will be 0x01.
184: *
185: * I _think_ that what actually happens is that the chip
186: * loses its PCI configuration during the transition from
187: * D3 back to D0; this means that it should be possible for
188: * us to save the PCI iobase, membase and IRQ, put the chip
189: * back in the D0 state, then restore the PCI config ourselves.
190: */
191: command = pci_conf_read(pc, pa->pa_tag, XL_PCI_CAPID) & 0xff;
192: if (command == 0x01) {
193:
194: command = pci_conf_read(pc, pa->pa_tag,
195: XL_PCI_PWRMGMTCTRL);
196: if (command & XL_PSTATE_MASK) {
197: u_int32_t io, mem, irq;
198:
199: /* Save PCI config */
200: io = pci_conf_read(pc, pa->pa_tag, XL_PCI_LOIO);
201: mem = pci_conf_read(pc, pa->pa_tag, XL_PCI_LOMEM);
202: irq = pci_conf_read(pc, pa->pa_tag, XL_PCI_INTLINE);
203:
204: /* Reset the power state. */
205: printf("%s: chip is in D%d power mode "
206: "-- setting to D0\n",
207: sc->sc_dev.dv_xname, command & XL_PSTATE_MASK);
208: command &= 0xFFFFFFFC;
209: pci_conf_write(pc, pa->pa_tag,
210: XL_PCI_PWRMGMTCTRL, command);
211:
212: pci_conf_write(pc, pa->pa_tag, XL_PCI_LOIO, io);
213: pci_conf_write(pc, pa->pa_tag, XL_PCI_LOMEM, mem);
214: pci_conf_write(pc, pa->pa_tag, XL_PCI_INTLINE, irq);
215: }
216: }
217:
218: /*
219: * Map control/status registers.
220: */
221: #ifdef XL_USEIOSPACE
222: if (pci_mapreg_map(pa, XL_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
223: &sc->xl_btag, &sc->xl_bhandle, NULL, &iosize, 0)) {
224: printf(": can't map i/o space\n");
225: return;
226: }
227: #else
228: if (pci_mapreg_map(pa, XL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
229: &sc->xl_btag, &sc->xl_bhandle, NULL, &iosize, 0)) {
230: printf(": can't map i/o space\n");
231: return;
232: }
233: #endif
234:
235: if (sc->xl_flags & XL_FLAG_FUNCREG) {
236: if (pci_mapreg_map(pa, XL_PCI_FUNCMEM, PCI_MAPREG_TYPE_MEM, 0,
237: &sc->xl_funct, &sc->xl_funch, NULL, &funsize, 0)) {
238: printf(": can't map i/o space\n");
239: bus_space_unmap(sc->xl_btag, sc->xl_bhandle, iosize);
240: return;
241: }
242: sc->intr_ack = xl_pci_intr_ack;
243: }
244:
245: /*
246: * Allocate our interrupt.
247: */
248: if (pci_intr_map(pa, &ih)) {
249: printf(": couldn't map interrupt\n");
250: bus_space_unmap(sc->xl_btag, sc->xl_bhandle, iosize);
251: if (sc->xl_flags & XL_FLAG_FUNCREG)
252: bus_space_unmap(sc->xl_funct, sc->xl_funch, funsize);
253: return;
254: }
255:
256: intrstr = pci_intr_string(pc, ih);
257: sc->xl_intrhand = pci_intr_establish(pc, ih, IPL_NET, xl_intr, sc,
258: self->dv_xname);
259: if (sc->xl_intrhand == NULL) {
260: printf(": couldn't establish interrupt");
261: if (intrstr != NULL)
262: printf(" at %s", intrstr);
263: bus_space_unmap(sc->xl_btag, sc->xl_bhandle, iosize);
264: if (sc->xl_flags & XL_FLAG_FUNCREG)
265: bus_space_unmap(sc->xl_funct, sc->xl_funch, funsize);
266: return;
267: }
268: printf(": %s", intrstr);
269:
270: xl_attach(sc);
271: }
272:
273:
274: void
275: xl_pci_intr_ack(struct xl_softc *sc)
276: {
277: bus_space_write_4(sc->xl_funct, sc->xl_funch, XL_PCI_INTR,
278: XL_PCI_INTRACK);
279: }
CVSweb