1 /* $NetBSD: pci_gio.c,v 1.4 2006/12/29 00:04:20 rumble Exp $ */
4 * Copyright (c) 2006 Stephen M. Rumble
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. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: pci_gio.c,v 1.4 2006/12/29 00:04:20 rumble Exp $");
31 * Glue for PCI devices that are connected to the GIO bus by various little
34 * We presently support the following boards:
35 * o Phobos G100/G130/G160 (if_tlp, lxtphy)
36 * o Set Engineering GFE (if_tl, nsphy)
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
46 #include <sys/extent.h>
48 #include <machine/bus.h>
49 #include <machine/machtype.h>
51 #include <sgimips/gio/giovar.h>
52 #include <sgimips/gio/gioreg.h>
53 #include <sgimips/gio/giodevs.h>
55 #include <sgimips/dev/imcvar.h>
57 #include <mips/cache.h>
59 #include <dev/pci/pcivar.h>
60 #include <dev/pci/pcireg.h>
61 #include <dev/pci/pcidevs.h>
62 #include <dev/pci/pciconf.h>
65 #define DPRINTF(_x) if (giopci_debug) printf _x
69 struct sgimips_pci_chipset sc_pc
;
73 bus_space_tag_t sc_iot
;
74 bus_space_handle_t sc_ioh
;
77 static int giopci_match(struct device
*, struct cfdata
*, void *);
78 static void giopci_attach(struct device
*, struct device
*, void *);
79 static int giopci_bus_maxdevs(pci_chipset_tag_t
, int);
80 static pcireg_t
giopci_conf_read(pci_chipset_tag_t
, pcitag_t
, int);
81 static void giopci_conf_write(pci_chipset_tag_t
, pcitag_t
, int, pcireg_t
);
82 static int giopci_conf_hook(pci_chipset_tag_t
, int, int, int, pcireg_t
);
83 static int giopci_intr_map(struct pci_attach_args
*, pci_intr_handle_t
*);
85 giopci_intr_string(pci_chipset_tag_t
, pci_intr_handle_t
);
86 static void *giopci_intr_establish(int, int, int (*)(void *), void *);
87 static void giopci_intr_disestablish(void *);
89 #define PHOBOS_PCI_OFFSET 0x00100000
90 #define PHOBOS_PCI_LENGTH 128 /* ~arbitrary */
91 #define PHOBOS_TULIP_START 0x00101000
92 #define PHOBOS_TULIP_END 0x001fffff
94 #define SETENG_MAGIC_OFFSET 0x00020000
95 #define SETENG_MAGIC_VALUE 0x00001000
96 #define SETENG_PCI_OFFSET 0x00080000
97 #define SETENG_PCI_LENGTH 128 /* ~arbitrary */
98 #define SETENG_TLAN_START 0x00100000
99 #define SETENG_TLAN_END 0x001fffff
101 CFATTACH_DECL(giopci
, sizeof(struct giopci_softc
),
102 giopci_match
, giopci_attach
, NULL
, NULL
);
105 giopci_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
107 struct gio_attach_args
*ga
= aux
;
111 * I think that these cards are all GIO32-bis or GIO64. Thus
112 * they work in either Indigo2/Challenge M or
113 * Indy/Challenge S/Indigo R4k, according to form factor. However,
114 * there are some exceptions (e.g. my Indigo R4k won't power
115 * on with the Set Engineering card installed).
117 if (mach_type
!= MACH_SGI_IP20
&& mach_type
!= MACH_SGI_IP22
)
120 gprid
= GIO_PRODUCT_PRODUCTID(ga
->ga_product
);
121 if (gprid
== PHOBOS_G100
|| gprid
== PHOBOS_G130
||
122 gprid
== PHOBOS_G160
|| gprid
== SETENG_GFE
)
129 giopci_attach(struct device
*parent
, struct device
*self
, void *aux
)
131 struct giopci_softc
*sc
= (void *)self
;
132 pci_chipset_tag_t pc
= &sc
->sc_pc
;
133 struct gio_attach_args
*ga
= aux
;
134 uint32_t pci_off
, pci_len
, arb
;
135 struct pcibus_attach_args pba
;
136 u_long m_start
, m_end
;
137 #ifdef PCI_NETBSD_CONFIGURE
138 extern int pci_conf_debug
;
140 pci_conf_debug
= giopci_debug
;
143 sc
->sc_iot
= ga
->ga_iot
;
144 sc
->sc_slot
= ga
->ga_slot
;
145 sc
->sc_gprid
= GIO_PRODUCT_PRODUCTID(ga
->ga_product
);
147 if (mach_type
== MACH_SGI_IP22
&&
148 mach_subtype
== MACH_SGI_IP22_FULLHOUSE
)
149 arb
= GIO_ARB_RT
| GIO_ARB_MST
| GIO_ARB_PIPE
;
151 arb
= GIO_ARB_RT
| GIO_ARB_MST
;
153 if (gio_arb_config(ga
->ga_slot
, arb
)) {
154 printf(": failed to configure GIO bus arbiter\n");
159 imc_disable_sysad_parity();
162 switch (sc
->sc_gprid
) {
166 pci_off
= PHOBOS_PCI_OFFSET
;
167 pci_len
= PHOBOS_PCI_LENGTH
;
168 m_start
= MIPS_KSEG1_TO_PHYS(ga
->ga_addr
+ PHOBOS_TULIP_START
);
169 m_end
= MIPS_KSEG1_TO_PHYS(ga
->ga_addr
+ PHOBOS_TULIP_END
);
174 * NB: The SetEng board does not allow the ThunderLAN's DMA
175 * engine to properly transfer segments that span page
176 * boundaries. See sgimips/autoconf.c where we catch a
177 * tl(4) device attachment and create an appropriate
178 * proplib entry to enable the workaround.
180 pci_off
= SETENG_PCI_OFFSET
;
181 pci_len
= SETENG_PCI_LENGTH
;
182 m_start
= MIPS_KSEG1_TO_PHYS(ga
->ga_addr
+ SETENG_TLAN_START
);
183 m_end
= MIPS_KSEG1_TO_PHYS(ga
->ga_addr
+ SETENG_TLAN_END
);
184 bus_space_write_4(ga
->ga_iot
, ga
->ga_ioh
,
185 SETENG_MAGIC_OFFSET
, SETENG_MAGIC_VALUE
);
189 panic("giopci_attach: unsupported GIO product id 0x%02x",
193 if (bus_space_subregion(ga
->ga_iot
, ga
->ga_ioh
, pci_off
, pci_len
,
195 printf("%s: unable to map PCI registers\n",sc
->sc_dev
.dv_xname
);
198 sc
->sc_pci_len
= pci_len
;
200 pc
->pc_bus_maxdevs
= giopci_bus_maxdevs
;
201 pc
->pc_conf_read
= giopci_conf_read
;
202 pc
->pc_conf_write
= giopci_conf_write
;
203 pc
->pc_conf_hook
= giopci_conf_hook
;
204 pc
->pc_intr_map
= giopci_intr_map
;
205 pc
->pc_intr_string
= giopci_intr_string
;
206 pc
->intr_establish
= giopci_intr_establish
;
207 pc
->intr_disestablish
= giopci_intr_disestablish
;
208 pc
->iot
= ga
->ga_iot
;
209 pc
->ioh
= ga
->ga_ioh
;
212 printf(": %s\n", gio_product_string(sc
->sc_gprid
));
214 #ifdef PCI_NETBSD_CONFIGURE
215 pc
->pc_memext
= extent_create("giopcimem", m_start
, m_end
,
216 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
217 pci_configure_bus(pc
, NULL
, pc
->pc_memext
, NULL
, 0, mips_dcache_align
);
220 memset(&pba
, 0, sizeof(pba
));
221 pba
.pba_memt
= SGIMIPS_BUS_SPACE_MEM
;
222 pba
.pba_dmat
= ga
->ga_dmat
;
224 pba
.pba_flags
= PCI_FLAGS_MEM_ENABLED
;
225 /* NB: do not set PCI_FLAGS_{MRL,MRM,MWI}_OKAY -- true ?! */
227 config_found_ia(self
, "pcibus", &pba
, pcibusprint
);
231 giopci_bus_maxdevs(pci_chipset_tag_t pc
, int busno
)
238 giopci_conf_read(pci_chipset_tag_t pc
, pcitag_t tag
, int reg
)
240 struct giopci_softc
*sc
= pc
->cookie
;
244 pci_decompose_tag(pc
, tag
, &bus
, &dev
, &func
);
245 if (bus
!= 0 || dev
!= 0 || func
!= 0)
248 /* XXX - should just use bus_space_peek */
249 if (reg
>= sc
->sc_pci_len
) {
250 DPRINTF(("giopci_conf_read: reg 0x%x out of bounds\n", reg
));
254 DPRINTF(("giopci_conf_read: reg 0x%x = 0x", reg
));
255 data
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, reg
);
256 DPRINTF(("%08x\n", data
));
262 giopci_conf_write(pci_chipset_tag_t pc
, pcitag_t tag
, int reg
, pcireg_t data
)
264 struct giopci_softc
*sc
= pc
->cookie
;
267 pci_decompose_tag(pc
, tag
, &bus
, &dev
, &func
);
268 if (bus
!= 0 || dev
!= 0 || func
!= 0)
271 /* XXX - should just use bus_space_poke */
272 if (reg
>= sc
->sc_pci_len
) {
273 DPRINTF(("giopci_conf_write: reg 0x%x out of bounds "
274 "(val = 0x%08x)\n", reg
, data
));
278 DPRINTF(("giopci_conf_write: reg 0x%x = 0x%08x\n", reg
, data
));
279 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, reg
, data
);
283 giopci_conf_hook(pci_chipset_tag_t pc
, int bus
, int device
, int function
,
287 /* All devices use memory accesses only. */
288 return (PCI_CONF_MAP_MEM
| PCI_CONF_ENABLE_MEM
| PCI_CONF_ENABLE_BM
);
292 giopci_intr_map(struct pci_attach_args
*pa
, pci_intr_handle_t
*ihp
)
294 struct giopci_softc
*sc
= pa
->pa_pc
->cookie
;
302 giopci_intr_string(pci_chipset_tag_t pc
, pci_intr_handle_t ih
)
306 snprintf(str
, sizeof(str
), "slot %s",
307 (ih
== GIO_SLOT_EXP0
) ? "EXP0" :
308 (ih
== GIO_SLOT_EXP1
) ? "EXP1" : "GFX");
313 giopci_intr_establish(int slot
, int level
, int (*func
)(void *), void *arg
)
316 return (gio_intr_establish(slot
, level
, func
, arg
));
320 giopci_intr_disestablish(void *cookie
)
323 panic("giopci_intr_disestablish: impossible.");