1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
7 * Reserved.  This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License').  You may not use this file
10 * except in compliance with the License.  Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Mach Operating System
26 * Copyright (c) 1990 Carnegie-Mellon University
27 * Copyright (c) 1989 Carnegie-Mellon University
28 * Copyright (c) 1988 Carnegie-Mellon University
29 * Copyright (c) 1987 Carnegie-Mellon University
30 * All rights reserved.  The CMU software License Agreement specifies
31 * the terms and conditions for use and redistribution.
32 */
33
34/*
35 * Copyright (c) 1980 Regents of the University of California.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms are permitted
39 * provided that the above copyright notice and this paragraph are
40 * duplicated in all such forms and that any documentation,
41 * advertising materials, and other materials related to such
42 * distribution and use acknowledge that the software was developed
43 * by the University of California, Berkeley.  The name of the
44 * University may not be used to endorse or promote products derived
45 * from this software without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
48 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
49 */
50#ifndef lint
51static char sccsid[] __attribute__((used)) = "@(#)mkglue.c	5.6 (Berkeley) 6/18/88";
52#endif /* not lint */
53
54/*
55 * Make the bus adaptor interrupt glue files.
56 */
57#include <stdio.h>
58#include <string.h>
59#include "config.h"
60#include "parser.h"
61#include <ctype.h>
62
63void dump_mb_handler(FILE *fp, struct idlst *vec, int number);
64void dump_ubavec(FILE *fp, char *vector, int number);
65void dump_std(FILE *fp, FILE *gp);
66void dump_intname(FILE *fp, char *vector, int number);
67void dump_ctrs(FILE *fp);
68void glue(FILE *fp, void (*dump_handler)(FILE *, struct idlst *, int));
69
70/*
71 * Create the UNIBUS interrupt vector glue file.
72 */
73void
74ubglue(void)
75{
76	register FILE *fp, *gp;
77	register struct device *dp, *mp;
78
79	fp = fopen(path("ubglue.s"), "w");
80	if (fp == 0) {
81		perror(path("ubglue.s"));
82		exit(1);
83	}
84	gp = fopen(path("ubvec.s"), "w");
85	if (gp == 0) {
86		perror(path("ubvec.s"));
87		exit(1);
88	}
89	for (dp = dtab; dp != 0; dp = dp->d_next) {
90		mp = dp->d_conn;
91		if (mp != 0 && mp != (struct device *)-1 &&
92		    !eq(mp->d_name, "mba")) {
93			struct idlst *id, *id2;
94
95			for (id = dp->d_vec; id; id = id->id_next) {
96				for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
97					if (id2 == id) {
98						dump_ubavec(fp, id->id,
99						    dp->d_unit);
100						break;
101					}
102					if (!strcmp(id->id, id2->id))
103						break;
104				}
105			}
106		}
107	}
108	dump_std(fp, gp);
109	for (dp = dtab; dp != 0; dp = dp->d_next) {
110		mp = dp->d_conn;
111		if (mp != 0 && mp != (struct device *)-1 &&
112		    !eq(mp->d_name, "mba")) {
113			struct idlst *id, *id2;
114
115			for (id = dp->d_vec; id; id = id->id_next) {
116				for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
117					if (id2 == id) {
118						dump_intname(fp, id->id,
119							dp->d_unit);
120						break;
121					}
122					if (!strcmp(id->id, id2->id))
123						break;
124				}
125			}
126		}
127	}
128	dump_ctrs(fp);
129	(void) fclose(fp);
130	(void) fclose(gp);
131}
132
133static int cntcnt = 0;		/* number of interrupt counters allocated */
134
135/*
136 * Print a UNIBUS interrupt vector.
137 */
138void
139dump_ubavec(FILE *fp, char *vector, int number)
140{
141	char nbuf[80];
142	register char *v = nbuf;
143
144	switch (machine) {
145
146	case MACHINE_VAX:
147		(void) sprintf(v, "%s%d", vector, number);
148		fprintf(fp, "\t.globl\t_X%s\n\t.align\t2\n_X%s:\n",
149		    v, v);
150		fprintf(fp,"\tTIM_PUSHR(0)\n");
151		fprintf(fp, "\tincl\t_fltintrcnt+(4*%d)\n", cntcnt++);
152		if (strncmp(vector, "dzx", 3) == 0)
153			fprintf(fp, "\tmovl\t$%d,r0\n\tjmp\tdzdma\n\n", number);
154		else {
155			if (strncmp(vector, "uur", 3) == 0) {
156				fprintf(fp, "#ifdef UUDMA\n");
157				fprintf(fp, "\tmovl\t$%d,r0\n\tjsb\tuudma\n",
158					    number);
159				fprintf(fp, "#endif\n");
160			}
161			fprintf(fp, "\tpushl\t$%d\n", number);
162			fprintf(fp, "\tcalls\t$1,_%s\n",vector);
163			fprintf(fp, "\tCOUNT(V_INTR)\n");
164			fprintf(fp, "\tTSREI_POPR\n");
165		}
166		break;
167
168	case MACHINE_MIPSY:
169	case MACHINE_MIPS:
170		/*
171		 * Actually, we should never get here!
172		 * Main does not even call ubglue.
173		 */
174		if (strncmp(vector, "dzx", 3) == 0)
175			fprintf(fp, "\tDZINTR(%s,%d)\n", vector, number);
176		else
177			fprintf(fp, "\tDEVINTR(%s,%d)\n", vector, number);
178		break;
179	}
180
181}
182
183static	const char *vaxinames[] = {
184	"clock", "cnr", "cnx", "tur", "tux",
185	"mba0", "mba1", "mba2", "mba3",
186	"uba0", "uba1", "uba2", "uba3"
187};
188static	struct stdintrs {
189	const char	**si_names;	/* list of standard interrupt names */
190	int	si_n;		/* number of such names */
191} stdintrs[] = {
192	{ vaxinames, sizeof (vaxinames) / sizeof (vaxinames[0]) },
193};
194/*
195 * Start the interrupt name table with the names
196 * of the standard vectors not directly associated
197 * with a bus.  Also, dump the defines needed to
198 * reference the associated counters into a separate
199 * file which is prepended to locore.s.
200 */
201void
202dump_std(FILE *fp, FILE *gp)
203{
204	register struct stdintrs *si = &stdintrs[machine-1];
205	register const char **cpp;
206	register int i;
207
208	fprintf(fp, "\n\t.globl\t_intrnames\n");
209	fprintf(fp, "\n\t.globl\t_eintrnames\n");
210	fprintf(fp, "\t.data\n");
211	fprintf(fp, "_intrnames:\n");
212	cpp = si->si_names;
213	for (i = 0; i < si->si_n; i++) {
214		const char *cp;
215		char *tp;
216		char buf[80];
217
218		cp = *cpp;
219		if (cp[0] == 'i' && cp[1] == 'n' && cp[2] == 't') {
220			cp += 3;
221			if (*cp == 'r')
222				cp++;
223		}
224		for (tp = buf; *cp; cp++)
225			if (islower(*cp))
226				*tp++ = toupper(*cp);
227			else
228				*tp++ = *cp;
229		*tp = '\0';
230		fprintf(gp, "#define\tI_%s\t%lu\n", buf, i*sizeof (long));
231		fprintf(fp, "\t.asciz\t\"%s\"\n", *cpp);
232		cpp++;
233	}
234}
235
236void
237dump_intname(FILE *fp, char *vector, int number)
238{
239	register char *cp = vector;
240
241	fprintf(fp, "\t.asciz\t\"");
242	/*
243	 * Skip any "int" or "intr" in the name.
244	 */
245	while (*cp)
246		if (cp[0] == 'i' && cp[1] == 'n' &&  cp[2] == 't') {
247			cp += 3;
248			if (*cp == 'r')
249				cp++;
250		} else {
251			putc(*cp, fp);
252			cp++;
253		}
254	fprintf(fp, "%d\"\n", number);
255}
256
257/*
258 * Reserve space for the interrupt counters.
259 */
260void
261dump_ctrs(FILE *fp)
262{
263	struct stdintrs *si = &stdintrs[machine-1];
264
265	fprintf(fp, "_eintrnames:\n");
266	fprintf(fp, "\n\t.globl\t_intrcnt\n");
267	fprintf(fp, "\n\t.globl\t_eintrcnt\n");
268	fprintf(fp, "\t.align 2\n");
269	fprintf(fp, "_intrcnt:\n");
270	fprintf(fp, "\t.space\t4 * %d\n", si->si_n);
271	fprintf(fp, "_fltintrcnt:\n");
272	fprintf(fp, "\t.space\t4 * %d\n", cntcnt);
273	fprintf(fp, "_eintrcnt:\n\n");
274	fprintf(fp, "\t.text\n");
275}
276
277/*
278 * Routines for making Sun mb interrupt file mbglue.s
279 */
280
281/*
282 * print an interrupt handler for mainbus
283 */
284void
285dump_mb_handler(FILE *fp, struct idlst *vec, int number)
286{
287	fprintf(fp, "\tVECINTR(_X%s%d, _%s, _V%s%d)\n",
288		vec->id, number, vec->id, vec->id, number);
289}
290
291void
292mbglue(void)
293{
294	register FILE *fp;
295	const char *name = "mbglue.s";
296
297	fp = fopen(path(name), "w");
298	if (fp == 0) {
299		perror(path(name));
300		exit(1);
301	}
302	fprintf(fp, "#include <machine/asm_linkage.h>\n\n");
303	glue(fp, dump_mb_handler);
304	(void) fclose(fp);
305}
306
307void
308glue(FILE *fp, void (*dump_handler)(FILE *, struct idlst *, int))
309{
310	register struct device *dp, *mp;
311
312	for (dp = dtab; dp != 0; dp = dp->d_next) {
313		mp = dp->d_conn;
314		if (mp != 0 && mp != (struct device *)-1 &&
315		    !eq(mp->d_name, "mba")) {
316			struct idlst *vd, *vd2;
317
318			for (vd = dp->d_vec; vd; vd = vd->id_next) {
319				for (vd2 = dp->d_vec; vd2; vd2 = vd2->id_next) {
320					if (vd2 == vd) {
321						(void)(*dump_handler)
322							(fp, vd, dp->d_unit);
323						break;
324					}
325					if (!strcmp(vd->id, vd2->id))
326						break;
327				}
328			}
329		}
330	}
331}
332