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#undef MACHINE
61#include "parser.h"
62#include <ctype.h>
63
64void dump_mb_handler(FILE *fp, struct idlst *vec, int number);
65void dump_ubavec(FILE *fp, char *vector, int number);
66void dump_std(FILE *fp, FILE *gp);
67void dump_intname(FILE *fp, char *vector, int number);
68void dump_ctrs(FILE *fp);
69void glue(FILE *fp, void (*dump_handler)(FILE *, struct idlst *, int));
70
71/*
72 * Create the UNIBUS interrupt vector glue file.
73 */
74void
75ubglue(void)
76{
77	register FILE *fp, *gp;
78	register struct device *dp, *mp;
79
80	fp = fopen(path("ubglue.s"), "w");
81	if (fp == 0) {
82		perror(path("ubglue.s"));
83		exit(1);
84	}
85	gp = fopen(path("ubvec.s"), "w");
86	if (gp == 0) {
87		perror(path("ubvec.s"));
88		exit(1);
89	}
90	for (dp = dtab; dp != 0; dp = dp->d_next) {
91		mp = dp->d_conn;
92		if (mp != 0 && mp != (struct device *)-1 &&
93		    !eq(mp->d_name, "mba")) {
94			struct idlst *id, *id2;
95
96			for (id = dp->d_vec; id; id = id->id_next) {
97				for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
98					if (id2 == id) {
99						dump_ubavec(fp, id->id,
100						    dp->d_unit);
101						break;
102					}
103					if (!strcmp(id->id, id2->id))
104						break;
105				}
106			}
107		}
108	}
109	dump_std(fp, gp);
110	for (dp = dtab; dp != 0; dp = dp->d_next) {
111		mp = dp->d_conn;
112		if (mp != 0 && mp != (struct device *)-1 &&
113		    !eq(mp->d_name, "mba")) {
114			struct idlst *id, *id2;
115
116			for (id = dp->d_vec; id; id = id->id_next) {
117				for (id2 = dp->d_vec; id2; id2 = id2->id_next) {
118					if (id2 == id) {
119						dump_intname(fp, id->id,
120							dp->d_unit);
121						break;
122					}
123					if (!strcmp(id->id, id2->id))
124						break;
125				}
126			}
127		}
128	}
129	dump_ctrs(fp);
130	(void) fclose(fp);
131	(void) fclose(gp);
132}
133
134static int cntcnt = 0;		/* number of interrupt counters allocated */
135
136/*
137 * Print a UNIBUS interrupt vector.
138 */
139void
140dump_ubavec(FILE *fp, char *vector, int number)
141{
142	char nbuf[80];
143	register char *v = nbuf;
144
145	switch (machine) {
146
147	case MACHINE_VAX:
148		(void) sprintf(v, "%s%d", vector, number);
149		fprintf(fp, "\t.globl\t_X%s\n\t.align\t2\n_X%s:\n",
150		    v, v);
151		fprintf(fp,"\tTIM_PUSHR(0)\n");
152		fprintf(fp, "\tincl\t_fltintrcnt+(4*%d)\n", cntcnt++);
153		if (strncmp(vector, "dzx", 3) == 0)
154			fprintf(fp, "\tmovl\t$%d,r0\n\tjmp\tdzdma\n\n", number);
155		else {
156			if (strncmp(vector, "uur", 3) == 0) {
157				fprintf(fp, "#ifdef UUDMA\n");
158				fprintf(fp, "\tmovl\t$%d,r0\n\tjsb\tuudma\n",
159					    number);
160				fprintf(fp, "#endif\n");
161			}
162			fprintf(fp, "\tpushl\t$%d\n", number);
163			fprintf(fp, "\tcalls\t$1,_%s\n",vector);
164			fprintf(fp, "\tCOUNT(V_INTR)\n");
165			fprintf(fp, "\tTSREI_POPR\n");
166		}
167		break;
168
169	case MACHINE_MIPSY:
170	case MACHINE_MIPS:
171		/*
172		 * Actually, we should never get here!
173		 * Main does not even call ubglue.
174		 */
175		if (strncmp(vector, "dzx", 3) == 0)
176			fprintf(fp, "\tDZINTR(%s,%d)\n", vector, number);
177		else
178			fprintf(fp, "\tDEVINTR(%s,%d)\n", vector, number);
179		break;
180	}
181
182}
183
184static	const char *vaxinames[] = {
185	"clock", "cnr", "cnx", "tur", "tux",
186	"mba0", "mba1", "mba2", "mba3",
187	"uba0", "uba1", "uba2", "uba3"
188};
189static	struct stdintrs {
190	const char	**si_names;	/* list of standard interrupt names */
191	int	si_n;		/* number of such names */
192} stdintrs[] = {
193	{ vaxinames, sizeof (vaxinames) / sizeof (vaxinames[0]) },
194};
195/*
196 * Start the interrupt name table with the names
197 * of the standard vectors not directly associated
198 * with a bus.  Also, dump the defines needed to
199 * reference the associated counters into a separate
200 * file which is prepended to locore.s.
201 */
202void
203dump_std(FILE *fp, FILE *gp)
204{
205	register struct stdintrs *si = &stdintrs[machine-1];
206	register const char **cpp;
207	register int i;
208
209	fprintf(fp, "\n\t.globl\t_intrnames\n");
210	fprintf(fp, "\n\t.globl\t_eintrnames\n");
211	fprintf(fp, "\t.data\n");
212	fprintf(fp, "_intrnames:\n");
213	cpp = si->si_names;
214	for (i = 0; i < si->si_n; i++) {
215		const char *cp;
216		char *tp;
217		char buf[80];
218
219		cp = *cpp;
220		if (cp[0] == 'i' && cp[1] == 'n' && cp[2] == 't') {
221			cp += 3;
222			if (*cp == 'r')
223				cp++;
224		}
225		for (tp = buf; *cp; cp++)
226			if (islower(*cp))
227				*tp++ = toupper(*cp);
228			else
229				*tp++ = *cp;
230		*tp = '\0';
231		fprintf(gp, "#define\tI_%s\t%lu\n", buf, i*sizeof (long));
232		fprintf(fp, "\t.asciz\t\"%s\"\n", *cpp);
233		cpp++;
234	}
235}
236
237void
238dump_intname(FILE *fp, char *vector, int number)
239{
240	register char *cp = vector;
241
242	fprintf(fp, "\t.asciz\t\"");
243	/*
244	 * Skip any "int" or "intr" in the name.
245	 */
246	while (*cp)
247		if (cp[0] == 'i' && cp[1] == 'n' &&  cp[2] == 't') {
248			cp += 3;
249			if (*cp == 'r')
250				cp++;
251		} else {
252			putc(*cp, fp);
253			cp++;
254		}
255	fprintf(fp, "%d\"\n", number);
256}
257
258/*
259 * Reserve space for the interrupt counters.
260 */
261void
262dump_ctrs(FILE *fp)
263{
264	struct stdintrs *si = &stdintrs[machine-1];
265
266	fprintf(fp, "_eintrnames:\n");
267	fprintf(fp, "\n\t.globl\t_intrcnt\n");
268	fprintf(fp, "\n\t.globl\t_eintrcnt\n");
269	fprintf(fp, "\t.align 2\n");
270	fprintf(fp, "_intrcnt:\n");
271	fprintf(fp, "\t.space\t4 * %d\n", si->si_n);
272	fprintf(fp, "_fltintrcnt:\n");
273	fprintf(fp, "\t.space\t4 * %d\n", cntcnt);
274	fprintf(fp, "_eintrcnt:\n\n");
275	fprintf(fp, "\t.text\n");
276}
277
278/*
279 * Routines for making Sun mb interrupt file mbglue.s
280 */
281
282/*
283 * print an interrupt handler for mainbus
284 */
285void
286dump_mb_handler(FILE *fp, struct idlst *vec, int number)
287{
288	fprintf(fp, "\tVECINTR(_X%s%d, _%s, _V%s%d)\n",
289		vec->id, number, vec->id, vec->id, number);
290}
291
292void
293mbglue(void)
294{
295	register FILE *fp;
296	const char *name = "mbglue.s";
297
298	fp = fopen(path(name), "w");
299	if (fp == 0) {
300		perror(path(name));
301		exit(1);
302	}
303	fprintf(fp, "#include <machine/asm_linkage.h>\n\n");
304	glue(fp, dump_mb_handler);
305	(void) fclose(fp);
306}
307
308void
309glue(FILE *fp, void (*dump_handler)(FILE *, struct idlst *, int))
310{
311	register struct device *dp, *mp;
312
313	for (dp = dtab; dp != 0; dp = dp->d_next) {
314		mp = dp->d_conn;
315		if (mp != 0 && mp != (struct device *)-1 &&
316		    !eq(mp->d_name, "mba")) {
317			struct idlst *vd, *vd2;
318
319			for (vd = dp->d_vec; vd; vd = vd->id_next) {
320				for (vd2 = dp->d_vec; vd2; vd2 = vd2->id_next) {
321					if (vd2 == vd) {
322						(void)(*dump_handler)
323							(fp, vd, dp->d_unit);
324						break;
325					}
326					if (!strcmp(vd->id, vd2->id))
327						break;
328				}
329			}
330		}
331	}
332}
333