dec_6600.c revision 1.39
1/* $NetBSD: dec_6600.c,v 1.39 2025/03/09 01:06:41 thorpej Exp $ */
2
3/*
4 * Copyright (c) 1995, 1996, 1997 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@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/cdefs.h>			/* RCS ID & Copyright macro defns */
31
32__KERNEL_RCSID(0, "$NetBSD: dec_6600.c,v 1.39 2025/03/09 01:06:41 thorpej Exp $");
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/device.h>
37#include <sys/lwp.h>
38
39#include <machine/rpb.h>
40#include <machine/autoconf.h>
41#include <machine/cpuconf.h>
42#include <machine/alpha.h>
43#include <machine/logout.h>
44
45#include <dev/pci/pcivar.h>
46
47#include <alpha/pci/tsreg.h>
48#include <alpha/pci/tsvar.h>
49
50#define	DR_VERBOSE(f) while (0)
51
52void dec_6600_init(void);
53static void dec_6600_cons_init(void);
54static void dec_6600_device_register(device_t, void *);
55static void dec_6600_mcheck(unsigned long, struct ev6_logout_area *);
56static void dec_6600_mcheck_sys(unsigned int, struct ev6_logout_area *);
57static void dec_6600_mcheck_handler(unsigned long, struct trapframe *,
58				    unsigned long, unsigned long);
59
60static const struct alpha_variation_table dec_6600_variations[] = {
61	{ SV_ST_DP264, "AlphaPC DP264" },
62	{ SV_ST_CLIPPER, "AlphaServer ES40 (\"Clipper\")" },
63	{ SV_ST_GOLDRUSH, "AlphaServer DS20 (\"GoldRush\")" },
64	{ SV_ST_WEBBRICK, "AlphaServer DS10 (\"WebBrick\")" },
65	{ SV_ST_SHARK, "AlphaServer DS20L (\"Shark\")" },
66	{ 0, NULL },
67};
68
69static const struct alpha_variation_table dec_titan_variations[] = {
70	{ 0, NULL },
71};
72
73void
74dec_6600_init(void)
75{
76	uint64_t variation;
77
78	platform.family = (hwrpb->rpb_type == ST_DEC_TITAN) ? "Titan"
79							    : "6600";
80
81	if ((platform.model = alpha_dsr_sysname()) == NULL) {
82		const struct alpha_variation_table *vartab =
83		    (hwrpb->rpb_type == ST_DEC_TITAN) ? dec_titan_variations
84						      : dec_6600_variations;
85		variation = hwrpb->rpb_variation & SV_ST_MASK;
86		if ((platform.model = alpha_variation_name(variation,
87							   vartab)) == NULL) {
88			platform.model = alpha_unknown_sysname();
89		}
90	}
91
92	platform.iobus = "tsc";
93	platform.cons_init = dec_6600_cons_init;
94	platform.device_register = dec_6600_device_register;
95	platform.mcheck_handler = dec_6600_mcheck_handler;
96
97	/* enable Cchip and Pchip error interrupts */
98	STQP(TS_C_DIM0) = 0xe000000000000000;
99	STQP(TS_C_DIM1) = 0xe000000000000000;
100}
101
102static void
103dec_6600_cons_init(void)
104{
105	struct ctb *ctb;
106	uint64_t ctbslot;
107	struct tsp_config *tsp;
108	bus_space_tag_t isa_iot, isa_memt;
109
110	ctb = (struct ctb *)(((char *)hwrpb) + hwrpb->rpb_ctb_off);
111	ctbslot = ctb->ctb_turboslot;
112
113	/* Console hose defaults to hose 0. */
114	tsp_console_hose = 0;
115
116	tsp = tsp_init(tsp_console_hose);
117
118	isa_iot = &tsp->pc_iot;
119	isa_memt = &tsp->pc_memt;
120
121	switch (ctb->ctb_term_type) {
122	case CTB_PRINTERPORT:
123		/* serial console ... */
124		assert(CTB_TURBOSLOT_HOSE(ctbslot) == 0);
125		break;
126
127	case CTB_GRAPHICS:
128		/* PCI display might be on a different hose. */
129		if (CTB_TURBOSLOT_TYPE(ctbslot) != CTB_TURBOSLOT_TYPE_ISA) {
130			tsp_console_hose = CTB_TURBOSLOT_HOSE(ctbslot);
131			tsp = tsp_init(tsp_console_hose);
132		}
133		break;
134
135	default:
136		/* Let pci_consinit() handle it. */
137		break;
138	}
139
140	pci_consinit(&tsp->pc_pc, &tsp->pc_iot, &tsp->pc_memt,
141	    isa_iot, isa_memt);
142}
143
144static void
145dec_6600_device_register(device_t dev, void *aux)
146{
147	static device_t primarydev;
148	struct bootdev_data *b = bootdev_data;
149	device_t parent = device_parent(dev);
150
151	/*
152	 * First section: Deal with system-specific quirks.
153	 */
154
155	if ((hwrpb->rpb_variation & SV_ST_MASK) == SV_ST_WEBBRICK) {
156		/*
157		 * DMA on the on-board ALI IDE controller is not
158		 * working correctly; disable it for now to let
159		 * the systems at least hobble along.
160		 *
161		 * N.B. There's only one Pchip on a DS10, do there
162		 * is not need to determine which hose we have here.
163		 *
164		 * XXX This is meant to be temporary until we can find
165		 * XXX and fix the issue with bus-master DMA.
166		 */
167		if (device_is_a(parent, "pci") && device_is_a(dev, "aceride")) {
168			struct pci_attach_args *pa = aux;
169
170			if (pa->pa_bus == 0 && pa->pa_device == 13 &&
171			    pa->pa_function == 0) {
172				prop_dictionary_set_bool(device_properties(dev),
173				    "pciide-disable-dma", true);
174			}
175		}
176	}
177
178	/*
179	 * Second section: Boot device detection.
180	 */
181
182	if (booted_device != NULL || b == NULL) {
183		return;
184	}
185
186	if (primarydev == NULL) {
187		if (device_is_a(dev, "tsp")) {
188			struct tsp_attach_args *tsp = aux;
189
190			if (b->bus == tsp->tsp_slot) {
191				primarydev = dev;
192				DR_VERBOSE(printf("\nprimarydev = %s\n",
193				    device_xname(dev)));
194			}
195		}
196		return;
197	}
198
199	pci_find_bootdev(primarydev, dev, aux);
200}
201
202static void
203dec_6600_mcheck(unsigned long vector, struct ev6_logout_area *la)
204{
205	const char *t = "Unknown", *c = "";
206
207	if (vector == ALPHA_SYS_ERROR || vector == ALPHA_PROC_ERROR)
208		c = " Correctable";
209
210	switch (vector) {
211	case ALPHA_SYS_ERROR:
212	case ALPHA_SYS_MCHECK:
213		t = "System";
214		break;
215
216	case ALPHA_PROC_ERROR:
217	case ALPHA_PROC_MCHECK:
218		t = "Processor";
219		break;
220
221	case ALPHA_ENV_MCHECK:
222		t = "Environmental";
223		break;
224	}
225
226	printf("\n%s%s Machine Check (%lx): "
227	       "Rev 0x%x, Code 0x%x, Flags 0x%x\n\n",
228	       t, c, vector, la->mchk_rev, la->mchk_code, la->la.la_flags);
229}
230
231static void
232dec_6600_mcheck_sys(unsigned int indent, struct ev6_logout_area *la)
233{
234	struct ev6_logout_sys *ls =
235		(struct ev6_logout_sys *)ALPHA_LOGOUT_SYSTEM_AREA(&la->la);
236
237#define FMT	"%-30s = 0x%016lx\n"
238
239	IPRINTF(indent, FMT, "Software Error Summary Flags", ls->flags);
240
241	IPRINTF(indent, FMT, "CPU Device Interrupt Requests", ls->dir);
242	tsc_print_dir(indent + 1, ls->dir);
243
244	IPRINTF(indent, FMT, "Cchip Miscellaneous Register", ls->misc);
245	tsc_print_misc(indent + 1, ls->misc);
246
247	IPRINTF(indent, FMT, "Pchip 0 Error Register", ls->p0_error);
248	if (ls->flags & 0x5)
249		tsp_print_error(indent + 1, ls->p0_error);
250
251	IPRINTF(indent, FMT, "Pchip 1 Error Register", ls->p1_error);
252	if (ls->flags & 0x6)
253		tsp_print_error(indent + 1, ls->p1_error);
254}
255
256static void
257dec_6600_mcheck_handler(unsigned long mces, struct trapframe *framep,
258			unsigned long vector, unsigned long param)
259{
260	struct mchkinfo *mcp;
261	struct ev6_logout_area *la = (struct ev6_logout_area *)param;
262
263	/*
264	 * If we expected a machine check, just go handle it in common code.
265	 */
266	mcp = &curcpu()->ci_mcinfo;
267	if (mcp->mc_expected)
268		machine_check(mces, framep, vector, param);
269
270	dec_6600_mcheck(vector, la);
271
272	switch (vector) {
273	case ALPHA_SYS_ERROR:
274	case ALPHA_SYS_MCHECK:
275		dec_6600_mcheck_sys(1, la);
276		break;
277
278	}
279
280	machine_check(mces, framep, vector, param);
281}
282