pci_hades.c revision 1.1.4.1 1 1.1.4.1 thorpej /* $NetBSD: pci_hades.c,v 1.1.4.1 2002/01/10 19:40:04 thorpej 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.1 leo
34 1.1 leo #include <sys/types.h>
35 1.1 leo #include <sys/param.h>
36 1.1 leo #include <sys/systm.h>
37 1.1 leo #include <sys/device.h>
38 1.1 leo
39 1.1 leo #include <machine/bus.h>
40 1.1 leo
41 1.1 leo #include <dev/pci/pcivar.h>
42 1.1 leo #include <dev/pci/pcireg.h>
43 1.1 leo
44 1.1 leo #include <machine/cpu.h>
45 1.1 leo #include <machine/iomap.h>
46 1.1 leo #include <machine/mfp.h>
47 1.1 leo #include <machine/bswap.h>
48 1.1 leo
49 1.1 leo #include <atari/atari/device.h>
50 1.1 leo #include <atari/pci/pci_vga.h>
51 1.1.4.1 thorpej #include <atari/dev/grf_etreg.h>
52 1.1 leo
53 1.1 leo int
54 1.1 leo pci_bus_maxdevs(pc, busno)
55 1.1 leo pci_chipset_tag_t pc;
56 1.1 leo int busno;
57 1.1 leo {
58 1.1 leo return (4);
59 1.1 leo }
60 1.1 leo
61 1.1 leo static int pci_config_offset __P((pcitag_t));
62 1.1 leo
63 1.1 leo /*
64 1.1 leo * Atari_init.c maps the config areas NBPG bytes apart....
65 1.1 leo */
66 1.1 leo static int pci_config_offset(tag)
67 1.1 leo pcitag_t tag;
68 1.1 leo {
69 1.1 leo int device;
70 1.1 leo
71 1.1 leo device = (tag >> 11) & 0x1f;
72 1.1 leo return(device * NBPG);
73 1.1 leo }
74 1.1 leo
75 1.1 leo pcireg_t
76 1.1 leo pci_conf_read(pc, tag, reg)
77 1.1 leo pci_chipset_tag_t pc;
78 1.1 leo pcitag_t tag;
79 1.1 leo int reg;
80 1.1 leo {
81 1.1 leo u_long data;
82 1.1 leo
83 1.1 leo data = *(u_long *)(pci_conf_addr + pci_config_offset(tag) + reg);
84 1.1 leo return (bswap32(data));
85 1.1 leo }
86 1.1 leo
87 1.1 leo void
88 1.1 leo pci_conf_write(pc, tag, reg, data)
89 1.1 leo pci_chipset_tag_t pc;
90 1.1 leo pcitag_t tag;
91 1.1 leo int reg;
92 1.1 leo pcireg_t data;
93 1.1 leo {
94 1.1 leo *((u_long *)(pci_conf_addr + pci_config_offset(tag) + reg))
95 1.1 leo = bswap32(data);
96 1.1 leo }
97 1.1 leo
98 1.1 leo /*
99 1.1 leo * The interrupt stuff is rather ugly. On the Hades, all interrupt lines
100 1.1 leo * for a slot are wired together and connected to IO 0,1,2 or 5 (slots:
101 1.1 leo * (0-3) on the TT-MFP. The Pci-config code initializes the irq. number
102 1.1 leo * to the slot position.
103 1.1 leo */
104 1.1 leo static pci_intr_info_t iinfo[4] = { { -1 }, { -1 }, { -1 }, { -1 } };
105 1.1 leo
106 1.1 leo static int iifun __P((int, int));
107 1.1 leo
108 1.1 leo static int
109 1.1 leo iifun(slot, sr)
110 1.1 leo int slot;
111 1.1 leo int sr;
112 1.1 leo {
113 1.1 leo pci_intr_info_t *iinfo_p;
114 1.1 leo int s;
115 1.1 leo
116 1.1 leo iinfo_p = &iinfo[slot];
117 1.1 leo
118 1.1 leo /*
119 1.1 leo * Disable the interrupts
120 1.1 leo */
121 1.1 leo MFP2->mf_imrb &= ~iinfo_p->imask;
122 1.1 leo
123 1.1 leo if ((sr & PSL_IPL) >= (iinfo_p->ipl & PSL_IPL)) {
124 1.1 leo /*
125 1.1 leo * We're running at a too high priority now.
126 1.1 leo */
127 1.1 leo add_sicallback((si_farg)iifun, (void*)slot, 0);
128 1.1 leo }
129 1.1 leo else {
130 1.1 leo s = splx(iinfo_p->ipl);
131 1.1 leo (void) (iinfo_p->ifunc)(iinfo_p->iarg);
132 1.1 leo splx(s);
133 1.1 leo
134 1.1 leo /*
135 1.1 leo * Re-enable interrupts after handling
136 1.1 leo */
137 1.1 leo MFP2->mf_imrb |= iinfo_p->imask;
138 1.1 leo }
139 1.1 leo return 1;
140 1.1 leo }
141 1.1 leo
142 1.1 leo void *
143 1.1 leo pci_intr_establish(pc, ih, level, ih_fun, ih_arg)
144 1.1 leo pci_chipset_tag_t pc;
145 1.1 leo pci_intr_handle_t ih;
146 1.1 leo int level;
147 1.1 leo int (*ih_fun) __P((void *));
148 1.1 leo void *ih_arg;
149 1.1 leo {
150 1.1 leo pci_intr_info_t *iinfo_p;
151 1.1 leo struct intrhand *ihand;
152 1.1 leo int slot;
153 1.1 leo
154 1.1 leo slot = ih;
155 1.1 leo iinfo_p = &iinfo[slot];
156 1.1 leo
157 1.1 leo if (iinfo_p->ipl > 0)
158 1.1 leo panic("pci_intr_establish: interrupt was already established\n");
159 1.1 leo
160 1.1 leo ihand = intr_establish((slot == 3) ? 23 : 16 + slot, USER_VEC, 0,
161 1.1 leo (hw_ifun_t)iifun, (void *)slot);
162 1.1 leo if (ihand != NULL) {
163 1.1 leo iinfo_p->ipl = level;
164 1.1 leo iinfo_p->imask = (slot == 3) ? 0x80 : (0x01 << slot);
165 1.1 leo iinfo_p->ifunc = ih_fun;
166 1.1 leo iinfo_p->iarg = ih_arg;
167 1.1 leo iinfo_p->ihand = ihand;
168 1.1 leo
169 1.1 leo /*
170 1.1 leo * Enable (unmask) the interrupt
171 1.1 leo */
172 1.1 leo MFP2->mf_imrb |= iinfo_p->imask;
173 1.1 leo MFP2->mf_ierb |= iinfo_p->imask;
174 1.1 leo return(iinfo_p);
175 1.1 leo }
176 1.1 leo return NULL;
177 1.1 leo }
178 1.1 leo
179 1.1 leo void
180 1.1 leo pci_intr_disestablish(pc, cookie)
181 1.1 leo pci_chipset_tag_t pc;
182 1.1 leo void *cookie;
183 1.1 leo {
184 1.1 leo pci_intr_info_t *iinfo_p = (pci_intr_info_t *)cookie;
185 1.1 leo
186 1.1 leo if (iinfo->ipl < 0)
187 1.1 leo panic("pci_intr_disestablish: interrupt was not established\n");
188 1.1 leo
189 1.1 leo MFP2->mf_imrb &= ~iinfo->imask;
190 1.1 leo MFP2->mf_ierb &= ~iinfo->imask;
191 1.1 leo (void) intr_disestablish(iinfo_p->ihand);
192 1.1 leo iinfo_p->ipl = -1;
193 1.1.4.1 thorpej }
194 1.1.4.1 thorpej
195 1.1.4.1 thorpej /*
196 1.1.4.1 thorpej * XXX: Why are we repeating this everywhere! (Leo)
197 1.1.4.1 thorpej */
198 1.1.4.1 thorpej #define PCI_LINMEMBASE 0x0e000000
199 1.1.4.1 thorpej
200 1.1.4.1 thorpej static u_char crt_tab[] = {
201 1.1.4.1 thorpej 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
202 1.1.4.1 thorpej 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
203 1.1.4.1 thorpej 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
204 1.1.4.1 thorpej 0xff };
205 1.1.4.1 thorpej
206 1.1.4.1 thorpej static u_char seq_tab[] = {
207 1.1.4.1 thorpej 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00 };
208 1.1.4.1 thorpej
209 1.1.4.1 thorpej static u_char attr_tab[] = {
210 1.1.4.1 thorpej 0x0c, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00 };
211 1.1.4.1 thorpej
212 1.1.4.1 thorpej static u_char gdc_tab[] = {
213 1.1.4.1 thorpej 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff };
214 1.1.4.1 thorpej
215 1.1.4.1 thorpej void
216 1.1.4.1 thorpej ati_vga_init(pc, tag, id, ba, fb)
217 1.1.4.1 thorpej pci_chipset_tag_t pc;
218 1.1.4.1 thorpej pcitag_t tag;
219 1.1.4.1 thorpej int id;
220 1.1.4.1 thorpej volatile u_char *ba;
221 1.1.4.1 thorpej u_char *fb;
222 1.1.4.1 thorpej {
223 1.1.4.1 thorpej int i, csr;
224 1.1.4.1 thorpej
225 1.1.4.1 thorpej /* Turn on the card */
226 1.1.4.1 thorpej pci_conf_write(pc, tag, PCI_MAPREG_START, PCI_LINMEMBASE);
227 1.1.4.1 thorpej csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
228 1.1.4.1 thorpej csr |= (PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE);
229 1.1.4.1 thorpej csr |= PCI_COMMAND_MASTER_ENABLE;
230 1.1.4.1 thorpej pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
231 1.1.4.1 thorpej
232 1.1.4.1 thorpej /*
233 1.1.4.1 thorpej * Make sure we're allowed to write all crt-registers and reload them.
234 1.1.4.1 thorpej */
235 1.1.4.1 thorpej WCrt(ba, CRT_ID_END_VER_RETR, (RCrt(ba, CRT_ID_END_VER_RETR) & 0x7f));
236 1.1.4.1 thorpej
237 1.1.4.1 thorpej for (i = 0; i < 0x18; i++)
238 1.1.4.1 thorpej WCrt(ba, i, crt_tab[i]);
239 1.1.4.1 thorpej for (i = 0; i < 8; i++)
240 1.1.4.1 thorpej WSeq(ba, i, seq_tab[i]);
241 1.1.4.1 thorpej for (i = 0; i < 9; i++)
242 1.1.4.1 thorpej WGfx(ba, i, gdc_tab[i]);
243 1.1.4.1 thorpej for (i = 0x10; i < 0x18; i++)
244 1.1.4.1 thorpej WAttr(ba, i, attr_tab[i - 0x10]);
245 1.1.4.1 thorpej WAttr(ba, 0x20, 0);
246 1.1 leo }
247