1 /* $NetBSD: s3c2800_pci.c,v 1.12 2007/03/04 05:59:38 christos Exp $ */
4 * Copyright (c) 2002 Fujitsu Component Limited
5 * Copyright (c) 2002 Genetec Corporation
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of The Fujitsu Component Limited nor the name of
17 * Genetec corporation may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
21 * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
25 * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * derived from evbarm/ifpga/ifpga_pci.c
38 * Copyright (c) 2001 ARM Ltd
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the company may not be used to endorse or promote
50 * products derived from this software without specific prior written
53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
54 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
55 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
57 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
58 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
59 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * Copyright (c) 1997,1998 Mark Brinicombe.
66 * Copyright (c) 1997,1998 Causality Limited
67 * All rights reserved.
69 * Redistribution and use in source and binary forms, with or without
70 * modification, are permitted provided that the following conditions
72 * 1. Redistributions of source code must retain the above copyright
73 * notice, this list of conditions and the following disclaimer.
74 * 2. Redistributions in binary form must reproduce the above copyright
75 * notice, this list of conditions and the following disclaimer in the
76 * documentation and/or other materials provided with the distribution.
77 * 3. All advertising materials mentioning features or use of this software
78 * must display the following acknowledgement:
79 * This product includes software developed by Mark Brinicombe
80 * for the NetBSD Project.
81 * 4. The name of the company nor the name of the author may be used to
82 * endorse or promote products derived from this software without specific
83 * prior written permission.
85 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
86 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
87 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
88 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
89 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
90 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
91 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
92 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
93 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
94 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
99 * PCI configuration support for Samsung s3c2800.
102 #include <sys/cdefs.h>
103 __KERNEL_RCSID(0, "$NetBSD: s3c2800_pci.c,v 1.12 2007/03/04 05:59:38 christos Exp $");
105 #include <sys/param.h>
106 #include <sys/systm.h>
107 #include <sys/kernel.h>
108 #include <sys/device.h>
109 #include <sys/extent.h>
110 #include <sys/malloc.h>
112 #include <uvm/uvm_extern.h>
114 #include <machine/bus.h>
116 #include <arm/s3c2xx0/s3c2800reg.h>
117 #include <arm/s3c2xx0/s3c2800var.h>
119 #include <dev/pci/pcireg.h>
120 #include <dev/pci/pciconf.h>
127 * also useful for configuration type 0 address
129 #define BUSNO_SHIFT 16
130 #define BUSNO_MASK (0xff<<BUSNO_SHIFT)
131 #define DEVNO_SHIFT 11
132 #define DEVNO_MASK (0x1f<<DEVNO_SHIFT)
133 #define tag_to_devno(tag) (((tag)&DEVNO_MASK)>>DEVNO_SHIFT)
134 #define FUNNO_SHIFT 8
135 #define FUNNO_MASK (0x07<<FUNNO_SHIFT)
137 #define BUS0_DEV_MIN 1
138 #define BUS0_DEV_MAX 21
140 void s3c2800_pci_attach_hook(struct device
*, struct device
*,
141 struct pcibus_attach_args
*);
142 int s3c2800_pci_bus_maxdevs(void *, int);
143 pcitag_t
s3c2800_pci_make_tag(void *, int, int, int);
144 void s3c2800_pci_decompose_tag(void *, pcitag_t
, int *, int *, int *);
145 pcireg_t
s3c2800_pci_conf_read(void *, pcitag_t
, int);
146 void s3c2800_pci_conf_write(void *, pcitag_t
, int, pcireg_t
);
147 int s3c2800_pci_intr_map(struct pci_attach_args
*, pci_intr_handle_t
*);
148 const char *s3c2800_pci_intr_string(void *, pci_intr_handle_t
);
149 const struct evcnt
*s3c2800_pci_intr_evcnt(void *, pci_intr_handle_t
);
150 void *s3c2800_pci_intr_establish(void *, pci_intr_handle_t
, int,
151 int (*) (void *), void *);
152 void s3c2800_pci_intr_disestablish(void *, void *);
154 #define PCI_CONF_LOCK(s) (s) = disable_interrupts(I32_bit)
155 #define PCI_CONF_UNLOCK(s) restore_interrupts((s))
157 struct sspci_irq_handler
{
158 int (*func
) (void *);
161 SLIST_ENTRY(sspci_irq_handler
) link
;
165 struct device sc_dev
;
167 bus_space_tag_t sc_iot
;
168 bus_space_handle_t sc_reg_ioh
;
169 bus_space_handle_t sc_conf0_ioh
; /* config type0 space */
170 bus_space_handle_t sc_conf1_ioh
; /* config type1 space */
172 uint32_t sc_pciinten
; /* copy of PCIINTEN register */
174 /* list of interrupt handlers. SLIST is not good for removing
175 * element from it, but intr_disestablish is rarely called */
176 SLIST_HEAD(, sspci_irq_handler
) sc_irq_handlers
;
178 void *sc_softinterrupt
;
181 static int sspci_match(struct device
*, struct cfdata
*, void *aux
);
182 static void sspci_attach(struct device
*, struct device
*, void *);
184 static int sspci_bs_map(void *, bus_addr_t
, bus_size_t
, int,
185 bus_space_handle_t
*);
186 static int sspci_init_controller(struct sspci_softc
*);
187 static int sspci_intr(void *);
188 static void sspci_softintr(void *);
190 /* attach structures */
191 CFATTACH_DECL(sspci
, sizeof(struct sspci_softc
), sspci_match
, sspci_attach
,
195 struct arm32_pci_chipset sspci_chipset
= {
197 s3c2800_pci_attach_hook
,
198 s3c2800_pci_bus_maxdevs
,
199 s3c2800_pci_make_tag
,
200 s3c2800_pci_decompose_tag
,
201 s3c2800_pci_conf_read
,
202 s3c2800_pci_conf_write
,
204 s3c2800_pci_intr_map
,
205 s3c2800_pci_intr_string
,
206 s3c2800_pci_intr_evcnt
,
207 s3c2800_pci_intr_establish
,
208 s3c2800_pci_intr_disestablish
213 * bus space tag for PCI IO/Memory access space.
214 * filled in by sspci_attach()
216 struct bus_space sspci_io_tag
, sspci_mem_tag
;
219 sspci_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
225 sspci_attach(struct device
*parent
, struct device
*self
, void *aux
)
227 struct sspci_softc
*sc
= (struct sspci_softc
*) self
;
228 struct s3c2xx0_attach_args
*aa
= aux
;
230 bus_dma_tag_t pci_dma_tag
;
231 const char *error_on
; /* for panic message */
232 #if defined(PCI_NETBSD_CONFIGURE)
233 struct extent
*ioext
, *memext
;
234 struct pcibus_attach_args pci_pba
;
237 #define FAIL(which) do { \
238 error_on=(which); goto abort; }while(/*CONSTCOND*/0)
240 iot
= sc
->sc_iot
= aa
->sa_iot
;
241 if (bus_space_map(iot
, S3C2800_PCICTL_BASE
,
242 S3C2800_PCICTL_SIZE
, 0, &sc
->sc_reg_ioh
))
243 FAIL("control regs");
245 if (bus_space_map(iot
, S3C2800_PCI_CONF0_BASE
,
246 S3C2800_PCI_CONF0_SIZE
, 0, &sc
->sc_conf0_ioh
))
247 FAIL("config type 0 area");
250 if (bus_space_map(iot
, S3C2800_PCI_CONF1_BASE
,
251 S3C2800_PCI_CONF1_SIZE
, 0, &sc
->sc_conf1_ioh
))
252 FAIL("config type 1 area");
256 SLIST_INIT(&sc
->sc_irq_handlers
);
257 if (!s3c2800_intr_establish(S3C2800_INT_PCI
, IPL_AUDIO
, IST_LEVEL
,
259 FAIL("intr_establish");
261 sc
->sc_softinterrupt
= softint_establish(SOFTINT_SERIAL
,
263 if (sc
->sc_softinterrupt
== NULL
)
264 FAIL("softint_establish");
266 #if defined(PCI_NETBSD_CONFIGURE)
267 if (sspci_init_controller(sc
)) {
268 printf("%s: failed to initialize controller\n", self
->dv_xname
);
274 PCIINT_INA
| PCIINT_SER
| PCIINT_TPE
| PCIINT_MPE
|
275 PCIINT_MFE
| PCIINT_PRA
| PCIINT_PRD
;
277 bus_space_write_4(iot
, sc
->sc_reg_ioh
, PCICTL_PCIINTEN
,
281 pcireg_t id_reg
, class_reg
;
284 id_reg
= bus_space_read_4(iot
, sc
->sc_reg_ioh
,
286 class_reg
= bus_space_read_4(iot
,
287 sc
->sc_reg_ioh
, PCI_CLASS_REG
);
289 pci_devinfo(id_reg
, class_reg
, 1, buf
, sizeof(buf
));
290 printf("%s: %s\n", self
->dv_xname
, buf
);
293 #if defined(PCI_NETBSD_CONFIGURE)
294 ioext
= extent_create("pciio", 0x100, S3C2800_PCI_IOSPACE_SIZE
- 0x100,
295 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
297 memext
= extent_create("pcimem", 0, S3C2800_PCI_MEMSPACE_SIZE
,
298 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
300 sspci_chipset
.pc_conf_v
= (void *) sc
;
301 sspci_chipset
.pc_intr_v
= (void *) sc
;
303 pci_configure_bus(&sspci_chipset
, ioext
, memext
, NULL
, 0,
306 extent_destroy(memext
);
307 extent_destroy(ioext
);
308 #endif /* PCI_NETBSD_CONFIGURE */
310 /* initialize bus space tag */
312 sspci_io_tag
.bs_cookie
= (void *) S3C2800_PCI_IOSPACE_BASE
;
313 sspci_io_tag
.bs_map
= sspci_bs_map
;
314 sspci_mem_tag
= *iot
;
315 sspci_mem_tag
.bs_cookie
= (void *) S3C2800_PCI_MEMSPACE_BASE
;
316 sspci_mem_tag
.bs_map
= sspci_bs_map
;
319 /* Platform provides PCI DMA tag */
320 pci_dma_tag
= s3c2800_pci_dma_init();
322 pci_pba
.pba_pc
= &sspci_chipset
;
323 pci_pba
.pba_iot
= &sspci_io_tag
;
324 pci_pba
.pba_memt
= &sspci_mem_tag
;
325 pci_pba
.pba_dmat
= pci_dma_tag
;
326 pci_pba
.pba_dmat64
= NULL
;
327 pci_pba
.pba_flags
= PCI_FLAGS_IO_ENABLED
| PCI_FLAGS_MEM_ENABLED
;
329 pci_pba
.pba_bridgetag
= NULL
;
331 config_found_ia(self
, "pcibus", &pci_pba
, pcibusprint
);
337 panic("%s: map failed (%s)",
338 self
->dv_xname
, error_on
);
343 sspci_bs_map(void *t
, bus_addr_t bpa
, bus_size_t size
, int flag
,
344 bus_space_handle_t
* bshp
)
346 bus_addr_t startpa
, endpa
;
350 printf("sspci_bs_map: t=%p, addr=%lx, size=%lx, flag=%d\n",
354 /* Round the allocation to page boundries */
355 startpa
= trunc_page(bpa
);
356 endpa
= round_page(bpa
+ size
);
359 va
= uvm_km_alloc(kernel_map
, endpa
- startpa
, 0,
360 UVM_KMF_VAONLY
| UVM_KMF_NOWAIT
);
364 /* Store the bus space handle */
365 *bshp
= va
+ (bpa
& PGOFSET
);
367 /* Now map the pages */
368 /* The cookie is the physical base address for PCI I/O or memory area */
369 while (startpa
< endpa
) {
370 /* XXX pmap_kenter_pa maps pages cacheable -- not what we
372 pmap_enter(pmap_kernel(), va
, (bus_addr_t
) t
+ startpa
,
373 VM_PROT_READ
| VM_PROT_WRITE
, 0);
375 startpa
+= PAGE_SIZE
;
377 pmap_update(pmap_kernel());
385 pci_conf_interrupt(pci_chipset_tag_t pc
, int bus
, int dev
, int func
,
386 int swiz
, int *iline
)
389 printf("pci_conf_interrupt(pc(%lx), bus(%d), dev(%d), func(%d), swiz(%d), *iline(%p)\n", (unsigned long) pc
, bus
, dev
, func
, swiz
, iline
);
394 panic("pci_conf_interrupt: bus=%d: not yet implemented", bus
);
399 s3c2800_pci_attach_hook(struct device
* parent
, struct device
* self
,
400 struct pcibus_attach_args
* pba
)
405 printf("s3c2800_pci_attach_hook()\n");
410 s3c2800_pci_bus_maxdevs(void *v
, int busno
)
414 printf("s3c2800_pci_bus_maxdevs(v=%p, busno=%d)\n", v
, busno
);
419 s3c2800_pci_make_tag(void *v
, int bus
, int device
, int function
)
422 return ((bus
<< BUSNO_SHIFT
) | (device
<< DEVNO_SHIFT
) |
423 (function
<< FUNNO_SHIFT
));
427 s3c2800_pci_decompose_tag(void *v
, pcitag_t tag
, int *bp
, int *dp
, int *fp
)
430 *bp
= (tag
>> BUSNO_SHIFT
) & 0xff;
432 *dp
= (tag
>> DEVNO_SHIFT
) & 0x1f;
434 *fp
= (tag
>> FUNNO_SHIFT
) & 0x7;
438 make_pci_conf_va(struct sspci_softc
* sc
, pcitag_t tag
, int offset
)
440 if ((tag
& BUSNO_MASK
) == 0) {
441 /* configuration type 0 */
442 int devno
= tag_to_devno(tag
);
444 if (devno
< BUS0_DEV_MIN
|| BUS0_DEV_MAX
< devno
)
447 return (vaddr_t
) bus_space_vaddr(sc
->sc_iot
, sc
->sc_conf0_ioh
) +
448 (tag
& (DEVNO_MASK
| FUNNO_MASK
)) + offset
;
451 return (vaddr_t
) - 1; /* cause fault */
457 s3c2800_pci_conf_read(void *v
, pcitag_t tag
, int offset
)
459 struct sspci_softc
*sc
= v
;
460 vaddr_t va
= make_pci_conf_va(sc
, tag
, offset
);
465 printf("s3c2800_pci_conf_read: base=%lx tag=%lx offset=%x\n",
466 sc
->sc_conf0_ioh
, tag
, offset
);
473 if (badaddr_read((void *) va
, sizeof(rv
), &rv
)) {
475 printf("conf_read: %lx bad address\n", va
);
485 s3c2800_pci_conf_write(void *v
, pcitag_t tag
, int offset
, pcireg_t val
)
487 struct sspci_softc
*sc
= v
;
488 vaddr_t va
= make_pci_conf_va(sc
, tag
, offset
);
492 printf("s3c2800_pci_conf_write: tag=%lx offset=%x -> va=%lx\n", tag
, offset
, va
);
497 *(pcireg_t
*) va
= val
;
503 s3c2800_pci_intr_establish(void *pcv
, pci_intr_handle_t ih
, int level
,
504 int (*func
) (void *), void *arg
)
506 struct sspci_softc
*sc
= pcv
;
507 struct sspci_irq_handler
*handler
;
511 printf("s3c2800_pci_intr_establish(pcv=%p, ih=0x%lx, level=%d, "
512 "func=%p, arg=%p)\n", pcv
, ih
, level
, func
, arg
);
515 handler
= malloc(sizeof *handler
, M_DEVBUF
, cold
? M_NOWAIT
: M_WAITOK
);
517 panic("sspci_intr_establish: can't malloc handler info");
519 handler
->func
= func
;
521 handler
->level
= level
;
524 SLIST_INSERT_HEAD(&sc
->sc_irq_handlers
, handler
, link
);
531 s3c2800_pci_intr_disestablish(void *pcv
, void *cookie
)
533 struct sspci_softc
*sc
= pcv
;
534 struct sspci_irq_handler
*ih
= cookie
;
538 printf("s3c2800_pci_intr_disestablish(pcv=%p, cookie=%p)\n",
543 SLIST_REMOVE(&sc
->sc_irq_handlers
, ih
, sspci_irq_handler
, link
);
548 s3c2800_pci_intr_map(struct pci_attach_args
* pa
, pci_intr_handle_t
* ihp
)
551 int pin
= pa
->pa_intrpin
;
552 void *pcv
= pa
->pa_pc
;
553 pcitag_t intrtag
= pa
->pa_intrtag
;
554 int bus
, device
, function
;
556 s3c2800_pci_decompose_tag(pcv
, intrtag
, &bus
, &device
, &function
);
557 printf("s3c2800_pci_intr_map: pcv=%p, tag=%08lx pin=%d dev=%d\n",
558 pcv
, intrtag
, pin
, device
);
562 /* S3C2800 has only one interrupt line for PCI */
568 s3c2800_pci_intr_string(void *pcv
, pci_intr_handle_t ih
)
570 /* We have only one interrupt source from PCI */
575 s3c2800_pci_intr_evcnt(void *pcv
, pci_intr_handle_t ih
)
578 /* XXX for now, no evcnt parent reported */
582 * Initialize PCI controller
585 sspci_init_controller(struct sspci_softc
* sc
)
587 bus_space_tag_t iot
= sc
->sc_iot
;
588 bus_space_handle_t ioh
= sc
->sc_reg_ioh
;
590 /* disable PCI command */
591 bus_space_write_4(iot
, ioh
, PCI_COMMAND_STATUS_REG
,
594 /* latency=0x10, cacheline=8 */
595 bus_space_write_4(iot
, ioh
, PCI_BHLC_REG
,
596 PCI_BHLC_CODE(0, 0, 0, 0x10, 8));
598 bus_space_write_4(iot
, ioh
, PCI_INTERRUPT_REG
,
599 PCI_INTERRUPT_CODE(0, 0, 0, 0));
604 bus_space_write_4(iot
, ioh
, PCI_MAPREG_START
,
605 PCI_MAPREG_MEM_TYPE_32BIT
| 0x80000000);
606 /* Cover all DBANKs with BAR0 */
607 bus_space_write_4(iot
, ioh
, PCICTL_PCIBAM0
, 0xf8000000);
608 bus_space_write_4(iot
, ioh
, PCICTL_PCIBATPA0
, S3C2800_DBANK0_START
);
610 bus_space_write_4(iot
, ioh
, PCI_MAPREG_START
,
611 PCI_MAPREG_MEM_TYPE_32BIT
| 0xf0000000);
612 bus_space_write_4(iot
, ioh
, PCI_MAPREG_START
+ 4,
613 PCI_MAPREG_MEM_TYPE_32BIT
| 0x80000000);
615 bus_space_write_4(iot
, ioh
, PCICTL_PCIBAM0
, 0xffff0000);
616 bus_space_write_4(iot
, ioh
, PCICTL_PCIBATPA0
, 0xffff0000);
617 bus_space_write_4(iot
, ioh
, PCICTL_PCIBAM1
, 0xf1000000);
618 bus_space_write_4(iot
, ioh
, PCICTL_PCIBATPA1
, S3C2800_DBANK0_START
);
621 bus_space_write_4(iot
, ioh
, PCI_COMMAND_STATUS_REG
,
622 PCI_STATUS_PARITY_DETECT
|
623 PCI_STATUS_SPECIAL_ERROR
|
624 PCI_STATUS_MASTER_ABORT
|
625 PCI_STATUS_MASTER_TARGET_ABORT
|
626 PCI_STATUS_TARGET_TARGET_ABORT
|
627 PCI_STATUS_DEVSEL_MEDIUM
|
628 PCI_STATUS_PARITY_ERROR
|
629 PCI_STATUS_BACKTOBACK_SUPPORT
|
630 PCI_STATUS_CAPLIST_SUPPORT
|
631 PCI_COMMAND_MASTER_ENABLE
|
632 PCI_COMMAND_MEM_ENABLE
|
633 PCI_COMMAND_IO_ENABLE
);
635 bus_space_write_4(iot
, ioh
, PCICTL_PCICON
,
636 PCICON_ARB
| PCICON_HST
);
638 bus_space_write_4(iot
, ioh
, PCICTL_PCISET
, 0);
639 /* clear all interrupts */
640 bus_space_write_4(iot
, ioh
, PCICTL_PCIINTST
, 0xffffffff);
641 bus_space_write_4(iot
, ioh
, PCICTL_PCIINTEN
, 0);
643 bus_space_write_4(iot
, ioh
, PCICTL_PCICON
,
644 PCICON_RDY
| PCICON_CFD
| PCICON_ATS
|
645 PCICON_ARB
| PCICON_HST
);
653 for (i
= 0; i
<= 0x40; i
+= sizeof(pcireg_t
)) {
654 reg
= bus_space_read_4(iot
, ioh
, i
);
655 printf("%03x: %08x\n", i
, reg
);
657 for (i
= 0x100; i
<= 0x154; i
+= sizeof(pcireg_t
)) {
658 reg
= bus_space_read_4(iot
, ioh
, i
);
659 printf("%03x: %08x\n", i
, reg
);
667 static const char *pci_abnormal_error_name
[] = {
668 "PCI reset deasserted",
669 "PCI reset asserted",
670 "PCI master detected fatal error",
671 "PCI master detected parity error",
672 "PCI target detected parity error",
673 "PCI SERR# asserted",
677 sspci_intr(void *arg
)
679 struct sspci_softc
*sc
= arg
;
681 bus_space_tag_t iot
= sc
->sc_iot
;
682 bus_space_handle_t ioh
= sc
->sc_reg_ioh
;
683 uint32_t interrupts
, errors
;
685 interrupts
= bus_space_read_4(iot
, ioh
, PCICTL_PCIINTST
);
687 if (interrupts
& PCIINT_INA
) {
689 softint_schedule(sc
->sc_softinterrupt
);
691 /* mask INTA itnerrupt until softinterrupt is handled */
692 sc
->sc_pciinten
&= ~PCIINT_INA
;
693 bus_space_write_4(iot
, ioh
, PCICTL_PCIINTEN
,
696 /* acknowledge INTA interrupt */
697 bus_space_write_4(iot
, ioh
, PCICTL_PCIINTST
, PCIINT_INA
);
701 interrupts
&= ~PCIINT_INA
;
704 errors
= interrupts
& (PCIINT_SER
| PCIINT_TPE
| PCIINT_MPE
|
705 PCIINT_MFE
| PCIINT_PRA
| PCIINT_PRD
);
709 for (i
= 0; errors
; ++i
) {
710 if ((errors
& (1 << i
)) == 0)
713 printf("%s: %s\n", sc
->sc_dev
.dv_xname
,
714 pci_abnormal_error_name
[i
> 4 ? 5 : i
]);
718 /* acknowledge interrupts */
719 bus_space_write_4(iot
, ioh
, PCICTL_PCIINTST
, interrupts
);
725 sspci_softintr(void *arg
)
727 struct sspci_softc
*sc
= arg
;
728 struct sspci_irq_handler
*ih
;
732 SLIST_FOREACH(ih
, &(sc
->sc_irq_handlers
), link
) {
733 s
= _splraise(ih
->level
);
738 /* unmask INTA interrupt */
740 sc
->sc_pciinten
|= PCIINT_INA
;
741 bus_space_write_4(sc
->sc_iot
, sc
->sc_reg_ioh
, PCICTL_PCIINTEN
,