1/* $NetBSD: apecs_pci.c,v 1.28 2021/06/25 03:45:59 thorpej Exp $ */
2
3/*
4 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5 * All rights reserved.
6 *
7 * Author: Chris G. Demetriou
8 *
9 * Permission to use, copy, modify and distribute this software and
10 * its documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
14 *
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 *
19 * Carnegie Mellon requests users of this software to return to
20 *
21 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22 *  School of Computer Science
23 *  Carnegie Mellon University
24 *  Pittsburgh PA 15213-3890
25 *
26 * any improvements or extensions that they make and grant Carnegie the
27 * rights to redistribute these changes.
28 */
29
30#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
31
32__KERNEL_RCSID(0, "$NetBSD: apecs_pci.c,v 1.28 2021/06/25 03:45:59 thorpej Exp $");
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/device.h>
38
39#include <dev/pci/pcireg.h>
40#include <dev/pci/pcivar.h>
41#include <alpha/pci/apecsreg.h>
42#include <alpha/pci/apecsvar.h>
43
44static pcireg_t	apecs_conf_read(void *, pcitag_t, int);
45static void	apecs_conf_write(void *, pcitag_t, int, pcireg_t);
46
47void
48apecs_pci_init(pci_chipset_tag_t pc, void *v)
49{
50
51	pc->pc_conf_v = v;
52	pc->pc_conf_read = apecs_conf_read;
53	pc->pc_conf_write = apecs_conf_write;
54}
55
56static pcireg_t
57apecs_conf_read(void *cpv, pcitag_t tag, int offset)
58{
59	struct apecs_config *acp = cpv;
60	pcireg_t *datap, data;
61	int s, secondary, ba;
62	int32_t old_haxr2;					/* XXX */
63
64	if ((unsigned int)offset >= PCI_CONF_SIZE)
65		return (pcireg_t) -1;
66
67	s = 0;					/* XXX gcc -Wuninitialized */
68	old_haxr2 = 0;				/* XXX gcc -Wuninitialized */
69
70	/* secondary if bus # != 0 */
71	pci_decompose_tag(&acp->ac_pc, tag, &secondary, 0, 0);
72	if (secondary) {
73		s = splhigh();
74		old_haxr2 = REGVAL(EPIC_HAXR2);
75		alpha_mb();
76		REGVAL(EPIC_HAXR2) = old_haxr2 | 0x1;
77		alpha_mb();
78	}
79
80	datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(APECS_PCI_CONF |
81	    tag << 5UL |					/* XXX */
82	    (offset & ~0x03) << 5 |				/* XXX */
83	    0 << 5 |						/* XXX */
84	    0x3 << 3);						/* XXX */
85	data = (pcireg_t)-1;
86	if (!(ba = badaddr(datap, sizeof *datap)))
87		data = *datap;
88
89	if (secondary) {
90		alpha_mb();
91		REGVAL(EPIC_HAXR2) = old_haxr2;
92		alpha_mb();
93		splx(s);
94	}
95
96#if 0
97	printf("apecs_conf_read: tag 0x%lx, reg 0x%lx -> %x @ %p%s\n", tag, reg,
98	    data, datap, ba ? " (badaddr)" : "");
99#endif
100
101	return data;
102}
103
104static void
105apecs_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data)
106{
107	struct apecs_config *acp = cpv;
108	pcireg_t *datap;
109	int s, secondary;
110	int32_t old_haxr2;					/* XXX */
111
112	if ((unsigned int)offset >= PCI_CONF_SIZE)
113		return;
114
115	s = 0;					/* XXX gcc -Wuninitialized */
116	old_haxr2 = 0;				/* XXX gcc -Wuninitialized */
117
118	/* secondary if bus # != 0 */
119	pci_decompose_tag(&acp->ac_pc, tag, &secondary, 0, 0);
120	if (secondary) {
121		s = splhigh();
122		old_haxr2 = REGVAL(EPIC_HAXR2);
123		alpha_mb();
124		REGVAL(EPIC_HAXR2) = old_haxr2 | 0x1;
125		alpha_mb();
126	}
127
128	datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(APECS_PCI_CONF |
129	    tag << 5UL |					/* XXX */
130	    (offset & ~0x03) << 5 |				/* XXX */
131	    0 << 5 |						/* XXX */
132	    0x3 << 3);						/* XXX */
133
134	alpha_mb();
135	*datap = data;
136	alpha_mb();
137	alpha_mb();
138
139	if (secondary) {
140		alpha_mb();
141		REGVAL(EPIC_HAXR2) = old_haxr2;
142		alpha_mb();
143		splx(s);
144	}
145
146#if 0
147	printf("apecs_conf_write: tag 0x%lx, reg 0x%lx -> 0x%x @ %p\n", tag,
148	    reg, data, datap);
149#endif
150}
151