pci_hades.c revision 1.14.18.1 1 1.14.18.1 christos /* $NetBSD: pci_hades.c,v 1.14.18.1 2019/06/10 22:05:58 christos Exp $ */
2 1.1 leo
3 1.1 leo /*
4 1.1 leo * Copyright (c) 1996 Leo Weppelman. All rights reserved.
5 1.1 leo * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
6 1.1 leo * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
7 1.1 leo *
8 1.1 leo * Redistribution and use in source and binary forms, with or without
9 1.1 leo * modification, are permitted provided that the following conditions
10 1.1 leo * are met:
11 1.1 leo * 1. Redistributions of source code must retain the above copyright
12 1.1 leo * notice, this list of conditions and the following disclaimer.
13 1.1 leo * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 leo * notice, this list of conditions and the following disclaimer in the
15 1.1 leo * documentation and/or other materials provided with the distribution.
16 1.1 leo * 3. All advertising materials mentioning features or use of this software
17 1.1 leo * must display the following acknowledgement:
18 1.1 leo * This product includes software developed by Charles M. Hannum.
19 1.1 leo * 4. The name of the author may not be used to endorse or promote products
20 1.1 leo * derived from this software without specific prior written permission.
21 1.1 leo *
22 1.1 leo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.1 leo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.1 leo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.1 leo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.1 leo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 1.1 leo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 1.1 leo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 1.1 leo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 1.1 leo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 1.1 leo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.1 leo */
33 1.5 lukem
34 1.5 lukem #include <sys/cdefs.h>
35 1.14.18.1 christos __KERNEL_RCSID(0, "$NetBSD: pci_hades.c,v 1.14.18.1 2019/06/10 22:05:58 christos Exp $");
36 1.1 leo
37 1.1 leo #include <sys/types.h>
38 1.1 leo #include <sys/param.h>
39 1.1 leo #include <sys/systm.h>
40 1.1 leo #include <sys/device.h>
41 1.1 leo
42 1.4 thorpej #include <uvm/uvm_extern.h>
43 1.4 thorpej
44 1.12 dyoung #include <sys/bus.h>
45 1.1 leo
46 1.1 leo #include <dev/pci/pcivar.h>
47 1.1 leo #include <dev/pci/pcireg.h>
48 1.1 leo
49 1.1 leo #include <machine/cpu.h>
50 1.1 leo #include <machine/iomap.h>
51 1.1 leo #include <machine/mfp.h>
52 1.7 dsl #include <sys/bswap.h>
53 1.1 leo
54 1.1 leo #include <atari/atari/device.h>
55 1.1 leo #include <atari/pci/pci_vga.h>
56 1.2 leo #include <atari/dev/grf_etreg.h>
57 1.1 leo
58 1.1 leo int
59 1.10 dsl pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
60 1.1 leo {
61 1.14.18.1 christos
62 1.14.18.1 christos return 4;
63 1.1 leo }
64 1.1 leo
65 1.9 dsl static int pci_config_offset(pcitag_t);
66 1.1 leo
67 1.1 leo /*
68 1.4 thorpej * Atari_init.c maps the config areas PAGE_SIZE bytes apart....
69 1.1 leo */
70 1.14.18.1 christos static int
71 1.14.18.1 christos pci_config_offset(pcitag_t tag)
72 1.1 leo {
73 1.14.18.1 christos int device;
74 1.1 leo
75 1.1 leo device = (tag >> 11) & 0x1f;
76 1.14.18.1 christos
77 1.14.18.1 christos return device * PAGE_SIZE;
78 1.1 leo }
79 1.1 leo
80 1.1 leo pcireg_t
81 1.10 dsl pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
82 1.1 leo {
83 1.14.18.1 christos uint32_t data;
84 1.1 leo
85 1.14.18.1 christos if ((uint32_t)reg >= PCI_CONF_SIZE)
86 1.14.18.1 christos return 0xffffffff;
87 1.14 msaitoh
88 1.14.18.1 christos data = *(uint32_t *)(pci_conf_addr + pci_config_offset(tag) + reg);
89 1.14.18.1 christos return bswap32(data);
90 1.1 leo }
91 1.1 leo
92 1.1 leo void
93 1.10 dsl pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
94 1.1 leo {
95 1.14 msaitoh
96 1.14.18.1 christos if ((uint32_t)reg >= PCI_CONF_SIZE)
97 1.14 msaitoh return;
98 1.14 msaitoh
99 1.14.18.1 christos *((uint32_t *)(pci_conf_addr + pci_config_offset(tag) + reg))
100 1.14.18.1 christos = bswap32(data);
101 1.1 leo }
102 1.1 leo
103 1.1 leo /*
104 1.1 leo * The interrupt stuff is rather ugly. On the Hades, all interrupt lines
105 1.1 leo * for a slot are wired together and connected to IO 0,1,2 or 5 (slots:
106 1.1 leo * (0-3) on the TT-MFP. The Pci-config code initializes the irq. number
107 1.1 leo * to the slot position.
108 1.1 leo */
109 1.1 leo static pci_intr_info_t iinfo[4] = { { -1 }, { -1 }, { -1 }, { -1 } };
110 1.1 leo
111 1.14.18.1 christos static int iifun(int, int);
112 1.1 leo
113 1.1 leo static int
114 1.10 dsl iifun(int slot, int sr)
115 1.1 leo {
116 1.1 leo pci_intr_info_t *iinfo_p;
117 1.14.18.1 christos int s;
118 1.1 leo
119 1.1 leo iinfo_p = &iinfo[slot];
120 1.1 leo
121 1.1 leo /*
122 1.1 leo * Disable the interrupts
123 1.1 leo */
124 1.1 leo MFP2->mf_imrb &= ~iinfo_p->imask;
125 1.1 leo
126 1.1 leo if ((sr & PSL_IPL) >= (iinfo_p->ipl & PSL_IPL)) {
127 1.1 leo /*
128 1.1 leo * We're running at a too high priority now.
129 1.1 leo */
130 1.1 leo add_sicallback((si_farg)iifun, (void*)slot, 0);
131 1.14.18.1 christos } else {
132 1.1 leo s = splx(iinfo_p->ipl);
133 1.14.18.1 christos (void)(iinfo_p->ifunc)(iinfo_p->iarg);
134 1.1 leo splx(s);
135 1.1 leo
136 1.1 leo /*
137 1.1 leo * Re-enable interrupts after handling
138 1.1 leo */
139 1.1 leo MFP2->mf_imrb |= iinfo_p->imask;
140 1.1 leo }
141 1.1 leo return 1;
142 1.1 leo }
143 1.1 leo
144 1.8 ad int
145 1.8 ad pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih,
146 1.14.18.1 christos int attr, uint64_t data)
147 1.8 ad {
148 1.8 ad
149 1.8 ad switch (attr) {
150 1.8 ad case PCI_INTR_MPSAFE:
151 1.8 ad return 0;
152 1.8 ad default:
153 1.8 ad return ENODEV;
154 1.8 ad }
155 1.8 ad }
156 1.8 ad
157 1.1 leo void *
158 1.14.18.1 christos pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
159 1.14.18.1 christos int (*ih_fun)(void *), void *ih_arg)
160 1.1 leo {
161 1.1 leo pci_intr_info_t *iinfo_p;
162 1.1 leo struct intrhand *ihand;
163 1.14.18.1 christos int slot;
164 1.1 leo
165 1.1 leo slot = ih;
166 1.1 leo iinfo_p = &iinfo[slot];
167 1.1 leo
168 1.1 leo if (iinfo_p->ipl > 0)
169 1.14.18.1 christos panic("pci_intr_establish: interrupt was already established");
170 1.1 leo
171 1.1 leo ihand = intr_establish((slot == 3) ? 23 : 16 + slot, USER_VEC, 0,
172 1.14.18.1 christos (hw_ifun_t)iifun, (void *)slot);
173 1.1 leo if (ihand != NULL) {
174 1.1 leo iinfo_p->ipl = level;
175 1.1 leo iinfo_p->imask = (slot == 3) ? 0x80 : (0x01 << slot);
176 1.1 leo iinfo_p->ifunc = ih_fun;
177 1.1 leo iinfo_p->iarg = ih_arg;
178 1.1 leo iinfo_p->ihand = ihand;
179 1.1 leo
180 1.1 leo /*
181 1.1 leo * Enable (unmask) the interrupt
182 1.1 leo */
183 1.1 leo MFP2->mf_imrb |= iinfo_p->imask;
184 1.1 leo MFP2->mf_ierb |= iinfo_p->imask;
185 1.14.18.1 christos return iinfo_p;
186 1.1 leo }
187 1.1 leo return NULL;
188 1.1 leo }
189 1.1 leo
190 1.1 leo void
191 1.10 dsl pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
192 1.1 leo {
193 1.1 leo pci_intr_info_t *iinfo_p = (pci_intr_info_t *)cookie;
194 1.1 leo
195 1.1 leo if (iinfo->ipl < 0)
196 1.14.18.1 christos panic("pci_intr_disestablish: interrupt was not established");
197 1.1 leo
198 1.1 leo MFP2->mf_imrb &= ~iinfo->imask;
199 1.1 leo MFP2->mf_ierb &= ~iinfo->imask;
200 1.14.18.1 christos (void)intr_disestablish(iinfo_p->ihand);
201 1.1 leo iinfo_p->ipl = -1;
202 1.2 leo }
203 1.2 leo
204 1.2 leo /*
205 1.2 leo * XXX: Why are we repeating this everywhere! (Leo)
206 1.2 leo */
207 1.2 leo #define PCI_LINMEMBASE 0x0e000000
208 1.2 leo
209 1.14.18.1 christos static const uint8_t crt_tab[] = {
210 1.2 leo 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
211 1.2 leo 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
212 1.2 leo 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
213 1.2 leo 0xff };
214 1.2 leo
215 1.14.18.1 christos static const uint8_t seq_tab[] = {
216 1.14.18.1 christos 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00
217 1.14.18.1 christos };
218 1.14.18.1 christos
219 1.14.18.1 christos static const uint8_t attr_tab[] = {
220 1.14.18.1 christos 0x0c, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00
221 1.14.18.1 christos };
222 1.14.18.1 christos
223 1.14.18.1 christos static const uint8_t gdc_tab[] = {
224 1.14.18.1 christos 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff
225 1.14.18.1 christos };
226 1.2 leo
227 1.2 leo void
228 1.14.18.1 christos ati_vga_init(pci_chipset_tag_t pc, pcitag_t tag, int id, volatile uint8_t *ba,
229 1.14.18.1 christos uint8_t *fb)
230 1.2 leo {
231 1.14.18.1 christos uint32_t csr;
232 1.14.18.1 christos int i;
233 1.2 leo
234 1.2 leo /* Turn on the card */
235 1.2 leo pci_conf_write(pc, tag, PCI_MAPREG_START, PCI_LINMEMBASE);
236 1.2 leo csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
237 1.2 leo csr |= (PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE);
238 1.2 leo csr |= PCI_COMMAND_MASTER_ENABLE;
239 1.2 leo pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
240 1.2 leo
241 1.2 leo /*
242 1.2 leo * Make sure we're allowed to write all crt-registers and reload them.
243 1.2 leo */
244 1.2 leo WCrt(ba, CRT_ID_END_VER_RETR, (RCrt(ba, CRT_ID_END_VER_RETR) & 0x7f));
245 1.2 leo
246 1.2 leo for (i = 0; i < 0x18; i++)
247 1.2 leo WCrt(ba, i, crt_tab[i]);
248 1.2 leo for (i = 0; i < 8; i++)
249 1.2 leo WSeq(ba, i, seq_tab[i]);
250 1.2 leo for (i = 0; i < 9; i++)
251 1.2 leo WGfx(ba, i, gdc_tab[i]);
252 1.2 leo for (i = 0x10; i < 0x18; i++)
253 1.2 leo WAttr(ba, i, attr_tab[i - 0x10]);
254 1.2 leo WAttr(ba, 0x20, 0);
255 1.1 leo }
256