apecs.c revision 1.1 1 /* $NetBSD: apecs.c,v 1.1 1995/06/28 01:25:18 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1994, 1995 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 (at) 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/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
34 #include <sys/device.h>
35 #include <vm/vm.h>
36
37 #include <machine/autoconf.h>
38 #include <machine/pio.h>
39 #include <machine/rpb.h>
40
41 #include <dev/isa/isareg.h>
42 #include <dev/isa/isavar.h>
43 #include <alpha/isa/isa_dma.h>
44
45 #include <dev/pci/pcireg.h>
46 #include <dev/pci/pcivar.h>
47 #include <alpha/pci/pci_chipset.h>
48 #include <alpha/pci/apecsreg.h>
49
50 int apecsmatch __P((struct device *, void *, void *));
51 void apecsattach __P((struct device *, struct device *, void *));
52
53 struct cfdriver apecscd = {
54 NULL, "apecs", apecsmatch, apecsattach, DV_DULL, sizeof(struct device)
55 };
56
57 static int apecsprint __P((void *, char *pnp));
58
59 #ifdef DEC_2100_A50
60 extern void pci_2100_a50_pickintr __P((void));
61 #endif
62
63 #define REGVAL(r) (*(int32_t *)phystok0seg(r))
64
65 static int nsgmapent = 1024;
66 static vm_offset_t sgmap_pci_base = 0x800000;
67 /*static */struct sgmapent *sgmap;
68 static char /* * */ sgbitmap[1024 / NBBY];
69
70 int
71 apecsmatch(parent, match, aux)
72 struct device *parent;
73 void *match, *aux;
74 {
75 struct cfdata *cf = match;
76 struct confargs *pa = aux;
77
78 /* XXX */
79
80 return (1);
81 }
82
83 void
84 apecsattach(parent, self, aux)
85 struct device *parent, *self;
86 void *aux;
87 {
88 struct confargs *ca = aux;
89 struct confargs nca;
90 int pass2_comanche, widemem, pass2_epic;
91
92 pass2_comanche = (REGVAL(COMANCHE_ED) & COMANCHE_ED_PASS2) != 0;
93 widemem = (REGVAL(COMANCHE_GCR) & COMANCHE_GCR_WIDEMEM) != 0;
94 pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
95
96 sgmap = (struct sgmapent *)malloc(1024 * sizeof(struct sgmapent),
97 M_DEVBUF, M_WAITOK);
98
99 printf(": DECchip %s Core Logic chipset\n",
100 widemem ? "21072" : "21071");
101 printf("%s: DC21071-CA pass %d, %d-bit memory bus\n",
102 self->dv_xname, pass2_comanche ? 2 : 1, widemem ? 128 : 64);
103 printf("%s: DC21071-DA pass %d\n", self->dv_xname, pass2_epic ? 2 : 1);
104 /* XXX print bcache size */
105
106 if (!pass2_epic)
107 printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n");
108
109 /* set up the chipset's functions */
110 isadma_fcns = &apecs_isadma_fcns;
111 isa_pio_fcns = &apecs_pio_fcns;
112 if (!pass2_epic)
113 pci_cs_fcns = &apecs_p1e_cs_fcns;
114 else
115 pci_cs_fcns = &apecs_p2e_cs_fcns;
116
117 switch (hwrpb->rpb_type) {
118 #if defined(DEC_2100_A50)
119 case ST_DEC_2100_A50:
120 pci_2100_a50_pickintr();
121 break;
122 #endif
123 default:
124 panic("apecsattach: shouldn't be here, really...");
125 }
126
127 /* attach the PCI bus that hangs off of it... */
128 nca.ca_name = "pci";
129 nca.ca_slot = 0;
130 nca.ca_offset = 0;
131 nca.ca_bus = NULL;
132 if (!config_found(self, &nca, apecsprint))
133 panic("apecsattach: couldn't attach PCI bus");
134 }
135
136 static int
137 apecsprint(aux, pnp)
138 void *aux;
139 char *pnp;
140 {
141 register struct confargs *ca = aux;
142
143 if (pnp)
144 printf("%s at %s", ca->ca_name, pnp);
145 return (UNCONF);
146 }
147
148 vm_offset_t /* XXX? */
149 apecs_sgmap_alloc(va, npg, nocross, waitok)
150 caddr_t va;
151 int npg;
152 vm_size_t nocross;
153 int waitok;
154 {
155 int s;
156 int base, i, stride;
157
158 #ifdef DIAGNOSTIC
159 /* Quick sanity checks. */
160 if ((vm_offset_t)va & PGOFSET)
161 panic("apecs_sgmap_alloc: va not page aligned");
162 if ((nocross & (nocross - 1)) != 0 || nocross == 0)
163 panic("apecs_sgmap_alloc: bogus alignment 0x%lx", nocross);
164 if (npg <= 0)
165 panic("apecs_sgmap_alloc: not allocating anything");
166 if (npg > nsgmapent)
167 panic("apecs_sgmap_alloc: insane allocation");
168 if (ptoa(npg) > nocross)
169 panic("apecs_sgmap_alloc: must cross boundary");
170 #endif
171
172 stride = atop(nocross);
173 #ifdef DIAGNOSTIC
174 if (stride > nsgmapent)
175 panic("apecs_sgmap_alloc: cheesy implementation loses");
176 #endif
177
178 top:
179 s = splhigh();
180 for (base = 0; base < nsgmapent; base += stride) {
181 for (i = base; i < base + npg; i++)
182 if (isset(sgbitmap, i))
183 goto nextstride;
184 break;
185 nextstride:
186 }
187 if (base < nsgmapent) /* found a free chunk, claim it */
188 for (i = base; i < base + npg; i++)
189 setbit(sgbitmap, i);
190 splx(s);
191
192 if (base >= nsgmapent) { /* didn't find a free chunk */
193 if (!waitok)
194 return 0;
195 tsleep(&sgmap, PRIBIO+1, "sgmap", 0);
196 goto top;
197 }
198
199 for (i = base; i < base + npg; i++) {
200 #ifdef DIAGNOSTIC
201 if ((sgmap[i].val & SGMAPENT_EVAL) != 0)
202 panic("apecs_sgmap_alloc: unallocated entry valid");
203 #endif
204 sgmap[i].val = SGMAP_MAKEENTRY(atop(vtophys(va)));
205 va += PAGE_SIZE;
206 }
207
208 /* Invalidate old cached entries. */
209 REGVAL(EPIC_TBIA) = 1;
210
211 /* Return the PCI address. */
212 return (ptoa(base) + sgmap_pci_base);
213 }
214
215 void
216 apecs_sgmap_dealloc(pa, npg)
217 vm_offset_t pa;
218 int npg;
219 {
220 int i, pfn;
221
222 #ifdef DIAGNOSTIC
223 /* Quick sanity checks. */
224 if (pa & PGOFSET)
225 panic("apecs_sgmap_dealloc: pa not page aligned");
226 if (npg <= 0)
227 panic("apecs_sgmap_dealloc: not deallocating anything");
228 if (npg > nsgmapent)
229 panic("apecs_sgmap_dealloc: insane deallocation");
230 #endif
231
232 pfn = atop(pa - sgmap_pci_base);
233 #ifdef DIAGNOSTIC
234 /* Bounds check the deallocation range. Paranoid about wraparound. */
235 if (pfn < 0 || pfn >= nsgmapent || (pfn + npg) >= nsgmapent)
236 panic("apecs_sgmap_dealloc: pa out of range (%s)",
237 pfn < 0 ? "too low" : "too high");
238 #endif
239
240 for (i = 0; i < npg; i++) {
241 #ifdef DIAGNOSTIC
242 /* Make sure it's actually allocated. */
243 if (isclr(sgbitmap, i + pfn))
244 panic("apecs_sgmap_dealloc: multiple frees: entry %d",
245 i + pfn);
246 #endif
247
248 /* Clear the entries and the allocation map bits. */
249 clrbit(sgbitmap, i + pfn);
250 sgmap[i + pfn].val &= ~SGMAPENT_EVAL;
251 }
252
253 /* Invalidate old cached entries. */
254 REGVAL(EPIC_TBIA) = 1;
255
256 /* Wake up anybody waiting for map entries. */
257 wakeup(&sgmap);
258 }
259