apecs.c revision 1.2 1 1.2 cgd /* $NetBSD: apecs.c,v 1.2 1995/08/03 00:44:57 cgd Exp $ */
2 1.1 cgd
3 1.1 cgd /*
4 1.1 cgd * Copyright (c) 1994, 1995 Carnegie-Mellon University.
5 1.1 cgd * All rights reserved.
6 1.1 cgd *
7 1.1 cgd * Author: Chris G. Demetriou
8 1.1 cgd *
9 1.1 cgd * Permission to use, copy, modify and distribute this software and
10 1.1 cgd * its documentation is hereby granted, provided that both the copyright
11 1.1 cgd * notice and this permission notice appear in all copies of the
12 1.1 cgd * software, derivative works or modified versions, and any portions
13 1.1 cgd * thereof, and that both notices appear in supporting documentation.
14 1.1 cgd *
15 1.1 cgd * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 1.1 cgd * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 1.1 cgd * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 1.1 cgd *
19 1.1 cgd * Carnegie Mellon requests users of this software to return to
20 1.1 cgd *
21 1.1 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
22 1.1 cgd * School of Computer Science
23 1.1 cgd * Carnegie Mellon University
24 1.1 cgd * Pittsburgh PA 15213-3890
25 1.1 cgd *
26 1.1 cgd * any improvements or extensions that they make and grant Carnegie the
27 1.1 cgd * rights to redistribute these changes.
28 1.1 cgd */
29 1.1 cgd
30 1.1 cgd #include <sys/param.h>
31 1.1 cgd #include <sys/systm.h>
32 1.1 cgd #include <sys/kernel.h>
33 1.1 cgd #include <sys/malloc.h>
34 1.1 cgd #include <sys/device.h>
35 1.1 cgd #include <vm/vm.h>
36 1.1 cgd
37 1.1 cgd #include <machine/autoconf.h>
38 1.1 cgd #include <machine/pio.h>
39 1.1 cgd #include <machine/rpb.h>
40 1.1 cgd
41 1.1 cgd #include <dev/isa/isareg.h>
42 1.1 cgd #include <dev/isa/isavar.h>
43 1.1 cgd #include <alpha/isa/isa_dma.h>
44 1.1 cgd
45 1.1 cgd #include <dev/pci/pcireg.h>
46 1.1 cgd #include <dev/pci/pcivar.h>
47 1.1 cgd #include <alpha/pci/pci_chipset.h>
48 1.1 cgd #include <alpha/pci/apecsreg.h>
49 1.1 cgd
50 1.1 cgd int apecsmatch __P((struct device *, void *, void *));
51 1.1 cgd void apecsattach __P((struct device *, struct device *, void *));
52 1.1 cgd
53 1.1 cgd struct cfdriver apecscd = {
54 1.1 cgd NULL, "apecs", apecsmatch, apecsattach, DV_DULL, sizeof(struct device)
55 1.1 cgd };
56 1.1 cgd
57 1.1 cgd static int apecsprint __P((void *, char *pnp));
58 1.1 cgd
59 1.1 cgd #ifdef DEC_2100_A50
60 1.1 cgd extern void pci_2100_a50_pickintr __P((void));
61 1.1 cgd #endif
62 1.1 cgd
63 1.1 cgd #define REGVAL(r) (*(int32_t *)phystok0seg(r))
64 1.1 cgd
65 1.1 cgd static int nsgmapent = 1024;
66 1.1 cgd static vm_offset_t sgmap_pci_base = 0x800000;
67 1.1 cgd /*static */struct sgmapent *sgmap;
68 1.1 cgd static char /* * */ sgbitmap[1024 / NBBY];
69 1.1 cgd
70 1.1 cgd int
71 1.1 cgd apecsmatch(parent, match, aux)
72 1.1 cgd struct device *parent;
73 1.1 cgd void *match, *aux;
74 1.1 cgd {
75 1.1 cgd struct cfdata *cf = match;
76 1.1 cgd struct confargs *pa = aux;
77 1.1 cgd
78 1.1 cgd /* XXX */
79 1.1 cgd
80 1.1 cgd return (1);
81 1.1 cgd }
82 1.1 cgd
83 1.2 cgd /*
84 1.2 cgd * Set up the chipset's function pointers.
85 1.2 cgd */
86 1.2 cgd void
87 1.2 cgd apecs_init()
88 1.2 cgd {
89 1.2 cgd int pass2_epic;
90 1.2 cgd
91 1.2 cgd pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
92 1.2 cgd
93 1.2 cgd isadma_fcns = &apecs_isadma_fcns;
94 1.2 cgd isa_pio_fcns = &apecs_pio_fcns;
95 1.2 cgd if (!pass2_epic)
96 1.2 cgd pci_cs_fcns = &apecs_p1e_cs_fcns;
97 1.2 cgd else
98 1.2 cgd pci_cs_fcns = &apecs_p2e_cs_fcns;
99 1.2 cgd }
100 1.2 cgd
101 1.1 cgd void
102 1.1 cgd apecsattach(parent, self, aux)
103 1.1 cgd struct device *parent, *self;
104 1.1 cgd void *aux;
105 1.1 cgd {
106 1.1 cgd struct confargs *ca = aux;
107 1.1 cgd struct confargs nca;
108 1.1 cgd int pass2_comanche, widemem, pass2_epic;
109 1.1 cgd
110 1.1 cgd pass2_comanche = (REGVAL(COMANCHE_ED) & COMANCHE_ED_PASS2) != 0;
111 1.1 cgd widemem = (REGVAL(COMANCHE_GCR) & COMANCHE_GCR_WIDEMEM) != 0;
112 1.1 cgd pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
113 1.1 cgd
114 1.1 cgd sgmap = (struct sgmapent *)malloc(1024 * sizeof(struct sgmapent),
115 1.1 cgd M_DEVBUF, M_WAITOK);
116 1.1 cgd
117 1.1 cgd printf(": DECchip %s Core Logic chipset\n",
118 1.1 cgd widemem ? "21072" : "21071");
119 1.1 cgd printf("%s: DC21071-CA pass %d, %d-bit memory bus\n",
120 1.1 cgd self->dv_xname, pass2_comanche ? 2 : 1, widemem ? 128 : 64);
121 1.1 cgd printf("%s: DC21071-DA pass %d\n", self->dv_xname, pass2_epic ? 2 : 1);
122 1.1 cgd /* XXX print bcache size */
123 1.1 cgd
124 1.1 cgd if (!pass2_epic)
125 1.1 cgd printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n");
126 1.1 cgd
127 1.1 cgd /* set up the chipset's functions */
128 1.2 cgd apecs_init();
129 1.1 cgd
130 1.1 cgd switch (hwrpb->rpb_type) {
131 1.1 cgd #if defined(DEC_2100_A50)
132 1.1 cgd case ST_DEC_2100_A50:
133 1.1 cgd pci_2100_a50_pickintr();
134 1.1 cgd break;
135 1.1 cgd #endif
136 1.1 cgd default:
137 1.1 cgd panic("apecsattach: shouldn't be here, really...");
138 1.1 cgd }
139 1.1 cgd
140 1.1 cgd /* attach the PCI bus that hangs off of it... */
141 1.1 cgd nca.ca_name = "pci";
142 1.1 cgd nca.ca_slot = 0;
143 1.1 cgd nca.ca_offset = 0;
144 1.1 cgd nca.ca_bus = NULL;
145 1.1 cgd if (!config_found(self, &nca, apecsprint))
146 1.1 cgd panic("apecsattach: couldn't attach PCI bus");
147 1.1 cgd }
148 1.1 cgd
149 1.1 cgd static int
150 1.1 cgd apecsprint(aux, pnp)
151 1.1 cgd void *aux;
152 1.1 cgd char *pnp;
153 1.1 cgd {
154 1.1 cgd register struct confargs *ca = aux;
155 1.1 cgd
156 1.1 cgd if (pnp)
157 1.1 cgd printf("%s at %s", ca->ca_name, pnp);
158 1.1 cgd return (UNCONF);
159 1.1 cgd }
160 1.1 cgd
161 1.1 cgd vm_offset_t /* XXX? */
162 1.1 cgd apecs_sgmap_alloc(va, npg, nocross, waitok)
163 1.1 cgd caddr_t va;
164 1.1 cgd int npg;
165 1.1 cgd vm_size_t nocross;
166 1.1 cgd int waitok;
167 1.1 cgd {
168 1.1 cgd int s;
169 1.1 cgd int base, i, stride;
170 1.1 cgd
171 1.1 cgd #ifdef DIAGNOSTIC
172 1.1 cgd /* Quick sanity checks. */
173 1.1 cgd if ((vm_offset_t)va & PGOFSET)
174 1.1 cgd panic("apecs_sgmap_alloc: va not page aligned");
175 1.1 cgd if ((nocross & (nocross - 1)) != 0 || nocross == 0)
176 1.1 cgd panic("apecs_sgmap_alloc: bogus alignment 0x%lx", nocross);
177 1.1 cgd if (npg <= 0)
178 1.1 cgd panic("apecs_sgmap_alloc: not allocating anything");
179 1.1 cgd if (npg > nsgmapent)
180 1.1 cgd panic("apecs_sgmap_alloc: insane allocation");
181 1.1 cgd if (ptoa(npg) > nocross)
182 1.1 cgd panic("apecs_sgmap_alloc: must cross boundary");
183 1.1 cgd #endif
184 1.1 cgd
185 1.1 cgd stride = atop(nocross);
186 1.1 cgd #ifdef DIAGNOSTIC
187 1.1 cgd if (stride > nsgmapent)
188 1.1 cgd panic("apecs_sgmap_alloc: cheesy implementation loses");
189 1.1 cgd #endif
190 1.1 cgd
191 1.1 cgd top:
192 1.1 cgd s = splhigh();
193 1.1 cgd for (base = 0; base < nsgmapent; base += stride) {
194 1.1 cgd for (i = base; i < base + npg; i++)
195 1.1 cgd if (isset(sgbitmap, i))
196 1.1 cgd goto nextstride;
197 1.1 cgd break;
198 1.1 cgd nextstride:
199 1.1 cgd }
200 1.1 cgd if (base < nsgmapent) /* found a free chunk, claim it */
201 1.1 cgd for (i = base; i < base + npg; i++)
202 1.1 cgd setbit(sgbitmap, i);
203 1.1 cgd splx(s);
204 1.1 cgd
205 1.1 cgd if (base >= nsgmapent) { /* didn't find a free chunk */
206 1.1 cgd if (!waitok)
207 1.1 cgd return 0;
208 1.1 cgd tsleep(&sgmap, PRIBIO+1, "sgmap", 0);
209 1.1 cgd goto top;
210 1.1 cgd }
211 1.1 cgd
212 1.1 cgd for (i = base; i < base + npg; i++) {
213 1.1 cgd #ifdef DIAGNOSTIC
214 1.1 cgd if ((sgmap[i].val & SGMAPENT_EVAL) != 0)
215 1.1 cgd panic("apecs_sgmap_alloc: unallocated entry valid");
216 1.1 cgd #endif
217 1.1 cgd sgmap[i].val = SGMAP_MAKEENTRY(atop(vtophys(va)));
218 1.1 cgd va += PAGE_SIZE;
219 1.1 cgd }
220 1.1 cgd
221 1.1 cgd /* Invalidate old cached entries. */
222 1.1 cgd REGVAL(EPIC_TBIA) = 1;
223 1.1 cgd
224 1.1 cgd /* Return the PCI address. */
225 1.1 cgd return (ptoa(base) + sgmap_pci_base);
226 1.1 cgd }
227 1.1 cgd
228 1.1 cgd void
229 1.1 cgd apecs_sgmap_dealloc(pa, npg)
230 1.1 cgd vm_offset_t pa;
231 1.1 cgd int npg;
232 1.1 cgd {
233 1.1 cgd int i, pfn;
234 1.1 cgd
235 1.1 cgd #ifdef DIAGNOSTIC
236 1.1 cgd /* Quick sanity checks. */
237 1.1 cgd if (pa & PGOFSET)
238 1.1 cgd panic("apecs_sgmap_dealloc: pa not page aligned");
239 1.1 cgd if (npg <= 0)
240 1.1 cgd panic("apecs_sgmap_dealloc: not deallocating anything");
241 1.1 cgd if (npg > nsgmapent)
242 1.1 cgd panic("apecs_sgmap_dealloc: insane deallocation");
243 1.1 cgd #endif
244 1.1 cgd
245 1.1 cgd pfn = atop(pa - sgmap_pci_base);
246 1.1 cgd #ifdef DIAGNOSTIC
247 1.1 cgd /* Bounds check the deallocation range. Paranoid about wraparound. */
248 1.1 cgd if (pfn < 0 || pfn >= nsgmapent || (pfn + npg) >= nsgmapent)
249 1.1 cgd panic("apecs_sgmap_dealloc: pa out of range (%s)",
250 1.1 cgd pfn < 0 ? "too low" : "too high");
251 1.1 cgd #endif
252 1.1 cgd
253 1.1 cgd for (i = 0; i < npg; i++) {
254 1.1 cgd #ifdef DIAGNOSTIC
255 1.1 cgd /* Make sure it's actually allocated. */
256 1.1 cgd if (isclr(sgbitmap, i + pfn))
257 1.1 cgd panic("apecs_sgmap_dealloc: multiple frees: entry %d",
258 1.1 cgd i + pfn);
259 1.1 cgd #endif
260 1.1 cgd
261 1.1 cgd /* Clear the entries and the allocation map bits. */
262 1.1 cgd clrbit(sgbitmap, i + pfn);
263 1.1 cgd sgmap[i + pfn].val &= ~SGMAPENT_EVAL;
264 1.1 cgd }
265 1.1 cgd
266 1.1 cgd /* Invalidate old cached entries. */
267 1.1 cgd REGVAL(EPIC_TBIA) = 1;
268 1.1 cgd
269 1.1 cgd /* Wake up anybody waiting for map entries. */
270 1.1 cgd wakeup(&sgmap);
271 1.1 cgd }
272