1 /* $NetBSD: igsfb_pci.c,v 1.19 2009/05/06 10:34:32 cegger Exp $ */
4 * Copyright (c) 2002, 2003 Valeriy E. Ushakov
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * Integraphics Systems IGA 168x and CyberPro series.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: igsfb_pci.c,v 1.19 2009/05/06 10:34:32 cegger Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
43 #ifdef __sparc__ /* XXX: this doesn't belong here */
44 #include <machine/autoconf.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pcireg.h>
51 #include <dev/pci/pcidevs.h>
53 #include <dev/wscons/wsdisplayvar.h>
54 #include <dev/wscons/wsconsio.h>
55 #include <dev/rasops/rasops.h>
56 #include <dev/wscons/wsdisplay_vconsvar.h>
58 #include <dev/ic/igsfbreg.h>
59 #include <dev/ic/igsfbvar.h>
60 #include <dev/pci/igsfb_pcivar.h>
63 static int igsfb_pci_match_by_id(pcireg_t
);
64 static int igsfb_pci_map_regs(struct igsfb_devconfig
*,
65 bus_space_tag_t
, bus_space_tag_t
,
67 pcitag_t
, pci_product_id_t
);
68 static int igsfb_pci_is_console(pci_chipset_tag_t
, pcitag_t
);
70 static int igsfb_pci_console
= 0;
71 static pcitag_t igsfb_pci_constag
;
75 static int igsfb_pci_match(device_t
, cfdata_t
, void *);
76 static void igsfb_pci_attach(device_t
, device_t
, void *);
78 CFATTACH_DECL(igsfb_pci
, sizeof(struct igsfb_softc
),
79 igsfb_pci_match
, igsfb_pci_attach
, NULL
, NULL
);
83 igsfb_pci_match_by_id(pcireg_t id
)
86 if (PCI_VENDOR(id
) != PCI_VENDOR_INTEGRAPHICS
)
89 switch (PCI_PRODUCT(id
)) {
90 case PCI_PRODUCT_INTEGRAPHICS_IGA1682
: /* FALLTHROUGH */
91 case PCI_PRODUCT_INTEGRAPHICS_CYBERPRO2000
: /* FALLTHROUGH */
92 case PCI_PRODUCT_INTEGRAPHICS_CYBERPRO2010
:
101 igsfb_pci_cnattach(bus_space_tag_t iot
, bus_space_tag_t memt
,
102 pci_chipset_tag_t pc
,
103 int bus
, int device
, int function
)
105 struct igsfb_devconfig
*dc
;
110 tag
= pci_make_tag(pc
, bus
, device
, function
);
111 id
= pci_conf_read(pc
, tag
, PCI_ID_REG
);
113 if (igsfb_pci_match_by_id(id
) == 0)
116 dc
= &igsfb_console_dc
;
117 if (igsfb_pci_map_regs(dc
, iot
, memt
, pc
, tag
, PCI_PRODUCT(id
)) != 0)
120 ret
= igsfb_enable(dc
->dc_iot
, dc
->dc_iobase
, dc
->dc_ioflags
);
124 ret
= igsfb_cnattach_subr(dc
);
128 igsfb_pci_console
= 1;
129 igsfb_pci_constag
= tag
;
136 igsfb_pci_is_console(pci_chipset_tag_t pc
, pcitag_t tag
)
139 return igsfb_pci_console
&&
140 !memcmp(&tag
, &igsfb_pci_constag
, sizeof tag
);
145 igsfb_pci_match(device_t parent
, cfdata_t match
, void *aux
)
147 struct pci_attach_args
*pa
= aux
;
149 return igsfb_pci_match_by_id(pa
->pa_id
);
154 igsfb_pci_attach(device_t parent
, device_t self
, void *aux
)
156 struct igsfb_softc
*sc
= device_private(self
);
157 struct pci_attach_args
*pa
= aux
;
161 pci_devinfo(pa
->pa_id
, pa
->pa_class
, 0, devinfo
, sizeof(devinfo
));
162 printf(": %s (rev. 0x%02x)\n", devinfo
, PCI_REVISION(pa
->pa_class
));
165 #if defined(__sparc__) && !defined(KRUPS_FORCE_SERIAL_CONSOLE)
166 /* XXX: this doesn't belong here */
167 if (PCITAG_NODE(pa
->pa_tag
) == prom_instance_to_package(prom_stdout()))
171 pci_decompose_tag(pa
->pa_pc
, pa
->pa_tag
, &b
, &d
, &f
);
172 igsfb_pci_cnattach(pa
->pa_iot
, pa
->pa_memt
, pa
->pa_pc
, b
,d
,f
);
177 if (igsfb_pci_is_console(pa
->pa_pc
, pa
->pa_tag
)) {
178 sc
->sc_dc
= &igsfb_console_dc
;
181 sc
->sc_dc
= malloc(sizeof(struct igsfb_devconfig
),
182 M_DEVBUF
, M_NOWAIT
| M_ZERO
);
183 if (sc
->sc_dc
== NULL
)
184 panic("unable to allocate igsfb_devconfig");
185 if (igsfb_pci_map_regs(sc
->sc_dc
,
186 pa
->pa_iot
, pa
->pa_memt
, pa
->pa_pc
,
187 pa
->pa_tag
, PCI_PRODUCT(pa
->pa_id
)) != 0)
189 printf("unable to map device registers\n");
190 free(sc
->sc_dc
, M_DEVBUF
);
195 igsfb_enable(sc
->sc_dc
->dc_iot
, sc
->sc_dc
->dc_iobase
,
196 sc
->sc_dc
->dc_ioflags
);
199 igsfb_attach_subr(sc
, isconsole
);
204 * Init memory and i/o bus space tags. Map device registers.
205 * Use memory space mapped i/o space access for i/o registers
206 * for CyberPro cards.
209 igsfb_pci_map_regs(struct igsfb_devconfig
*dc
,
210 bus_space_tag_t iot
, bus_space_tag_t memt
,
211 pci_chipset_tag_t pc
, pcitag_t tag
,
218 * Configure memory space first since for CyberPro we use
219 * memory-mapped i/o access. Note that we are NOT mapping any
220 * of it yet. (XXX: search for memory BAR?)
222 #define IGS_MEM_MAPREG (PCI_MAPREG_START + 0)
225 if (pci_mapreg_info(pc
, tag
,
226 IGS_MEM_MAPREG
, PCI_MAPREG_TYPE_MEM
,
227 &dc
->dc_memaddr
, &dc
->dc_memsz
, &dc
->dc_memflags
) != 0)
229 printf("unable to configure memory space\n");
234 * Configure I/O space. On CyberPro use MMIO. IGS 168x doesn't
235 * have a BAR for its i/o space, so we have to hardcode it.
237 if (id
>= PCI_PRODUCT_INTEGRAPHICS_CYBERPRO2000
) {
238 dc
->dc_iot
= dc
->dc_memt
;
239 dc
->dc_iobase
= dc
->dc_memaddr
| IGS_MEM_MMIO_SELECT
;
240 dc
->dc_ioflags
= dc
->dc_memflags
;
248 * Map I/O registers. This is done in bus glue, not in common
249 * code because on e.g. ISA bus we'd need to access registers
250 * to obtain/program linear memory location.
252 if (bus_space_map(dc
->dc_iot
,
253 dc
->dc_iobase
+ IGS_REG_BASE
, IGS_REG_SIZE
,
257 printf("unable to map I/O registers\n");