xref: /netbsd-src/sys/arch/alpha/alpha/dec_kn20aa.c (revision 296121ed992a66fda2c79e843285616269b1d6d1)
1 /* $NetBSD: dec_kn20aa.c,v 1.68 2024/03/31 19:06:31 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  * Additional Copyright (c) 1997 by Matthew Jacob for NASA/Ames Research Center
31  */
32 
33 #include "opt_kgdb.h"
34 
35 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
36 
37 __KERNEL_RCSID(0, "$NetBSD: dec_kn20aa.c,v 1.68 2024/03/31 19:06:31 thorpej Exp $");
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42 #include <sys/lwp.h>
43 #include <sys/termios.h>
44 
45 #include <sys/conf.h>
46 #include <dev/cons.h>
47 
48 #include <machine/rpb.h>
49 #include <machine/autoconf.h>
50 #include <machine/cpuconf.h>
51 #include <sys/bus.h>
52 #include <machine/alpha.h>
53 #include <machine/logout.h>
54 
55 #include <dev/ic/comreg.h>
56 #include <dev/ic/comvar.h>
57 
58 #include <dev/isa/isareg.h>
59 #include <dev/isa/isavar.h>
60 #include <dev/ic/i8042reg.h>
61 #include <dev/ic/pckbcvar.h>
62 #include <dev/pci/pcireg.h>
63 #include <dev/pci/pcivar.h>
64 
65 #include <alpha/pci/ciareg.h>
66 #include <alpha/pci/ciavar.h>
67 
68 #include <dev/scsipi/scsi_all.h>
69 #include <dev/scsipi/scsipi_all.h>
70 #include <dev/scsipi/scsiconf.h>
71 
72 #include "pckbd.h"
73 
74 #ifndef CONSPEED
75 #define CONSPEED TTYDEF_SPEED
76 #endif
77 static int comcnrate = CONSPEED;
78 
79 void dec_kn20aa_init(void);
80 static void dec_kn20aa_cons_init(void);
81 static void dec_kn20aa_device_register(device_t, void *);
82 
83 static void dec_kn20aa_mcheck_handler
84 (unsigned long, struct trapframe *, unsigned long, unsigned long);
85 
86 static void dec_kn20aa_mcheck(unsigned long, unsigned long,
87 				     unsigned long, struct trapframe *);
88 
89 #ifdef KGDB
90 #include <machine/db_machdep.h>
91 
92 static const char *kgdb_devlist[] = {
93 	"com",
94 	NULL,
95 };
96 #endif /* KGDB */
97 
98 const struct alpha_variation_table dec_kn20aa_variations[] = {
99 	{ 0, "AlphaStation 500 or 600 (KN20AA)" },
100 	{ 0, NULL },
101 };
102 
103 void
dec_kn20aa_init(void)104 dec_kn20aa_init(void)
105 {
106 	uint64_t variation;
107 
108 	platform.family = "AlphaStation 500 or 600 (KN20AA)";
109 
110 	if ((platform.model = alpha_dsr_sysname()) == NULL) {
111 		variation = hwrpb->rpb_variation & SV_ST_MASK;
112 		if ((platform.model = alpha_variation_name(variation,
113 		    dec_kn20aa_variations)) == NULL)
114 			platform.model = alpha_unknown_sysname();
115 	}
116 
117 	platform.iobus = "cia";
118 	platform.cons_init = dec_kn20aa_cons_init;
119 	platform.device_register = dec_kn20aa_device_register;
120 	platform.mcheck_handler = dec_kn20aa_mcheck_handler;
121 }
122 
123 static void
dec_kn20aa_cons_init(void)124 dec_kn20aa_cons_init(void)
125 {
126 	struct ctb *ctb;
127 	struct cia_config *ccp;
128 	extern struct cia_config cia_configuration;
129 
130 	ccp = &cia_configuration;
131 	cia_init(ccp);
132 
133 	ctb = (struct ctb *)(((char *)hwrpb) + hwrpb->rpb_ctb_off);
134 
135 	switch (ctb->ctb_term_type) {
136 	case CTB_PRINTERPORT:
137 		/* serial console ... */
138 		/* XXX */
139 		{
140 			/*
141 			 * Delay to allow PROM putchars to complete.
142 			 * FIFO depth * character time,
143 			 * character time = (1000000 / (defaultrate / 10))
144 			 */
145 			DELAY(160000000 / comcnrate);
146 
147 			if(comcnattach(&ccp->cc_iot, 0x3f8, comcnrate,
148 			    COM_FREQ, COM_TYPE_NORMAL,
149 			    (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8))
150 				panic("can't init serial console");
151 
152 			break;
153 		}
154 
155 	case CTB_GRAPHICS:
156 #if NPCKBD > 0
157 		/* display console ... */
158 		/* XXX */
159 		(void) pckbc_cnattach(&ccp->cc_iot, IO_KBD, KBCMDP,
160 		    PCKBC_KBD_SLOT, 0);
161 
162 		if (CTB_TURBOSLOT_TYPE(ctb->ctb_turboslot) ==
163 		    CTB_TURBOSLOT_TYPE_ISA)
164 			isa_display_console(&ccp->cc_iot, &ccp->cc_memt);
165 		else
166 			pci_display_console(&ccp->cc_iot, &ccp->cc_memt,
167 			    &ccp->cc_pc, CTB_TURBOSLOT_BUS(ctb->ctb_turboslot),
168 			    CTB_TURBOSLOT_SLOT(ctb->ctb_turboslot), 0);
169 #else
170 		panic("not configured to use display && keyboard console");
171 #endif
172 		break;
173 
174 	default:
175 		printf("ctb->ctb_term_type = 0x%lx\n", ctb->ctb_term_type);
176 		printf("ctb->ctb_turboslot = 0x%lx\n", ctb->ctb_turboslot);
177 
178 		panic("consinit: unknown console type %ld",
179 		    ctb->ctb_term_type);
180 	}
181 #ifdef KGDB
182 	/* Attach the KGDB device. */
183 	alpha_kgdb_init(kgdb_devlist, &ccp->cc_iot);
184 #endif /* KGDB */
185 }
186 
187 static void
dec_kn20aa_device_register(device_t dev,void * aux)188 dec_kn20aa_device_register(device_t dev, void *aux)
189 {
190 	static int found, initted, diskboot, netboot;
191 	static device_t pcidev, ctrlrdev;
192 	struct bootdev_data *b = bootdev_data;
193 	device_t parent = device_parent(dev);
194 
195 	if (b == NULL || found)
196 		return;
197 
198 	if (!initted) {
199 		diskboot = (strcasecmp(b->protocol, "SCSI") == 0);
200 		netboot = (strcasecmp(b->protocol, "BOOTP") == 0) ||
201 		    (strcasecmp(b->protocol, "MOP") == 0);
202 #if 0
203 		printf("diskboot = %d, netboot = %d\n", diskboot, netboot);
204 #endif
205 		initted =1;
206 	}
207 
208 	if (pcidev == NULL) {
209 		if (!device_is_a(dev, "pci"))
210 			return;
211 		else {
212 			struct pcibus_attach_args *pba = aux;
213 
214 			if ((b->slot / 1000) != pba->pba_bus)
215 				return;
216 
217 			pcidev = dev;
218 #if 0
219 			printf("\npcidev = %s\n", device_xname(dev));
220 #endif
221 			return;
222 		}
223 	}
224 
225 	if (ctrlrdev == NULL) {
226 		if (parent != pcidev)
227 			return;
228 		else {
229 			struct pci_attach_args *pa = aux;
230 			int slot;
231 
232 			slot = pa->pa_bus * 1000 + pa->pa_function * 100 +
233 			    pa->pa_device;
234 			if (b->slot != slot)
235 				return;
236 
237 			if (netboot) {
238 				booted_device = dev;
239 #if 0
240 				printf("\nbooted_device = %s\n", device_xname(dev));
241 #endif
242 				found = 1;
243 			} else {
244 				ctrlrdev = dev;
245 #if 0
246 				printf("\nctrlrdev = %s\n", device_xname(dev));
247 #endif
248 			}
249 			return;
250 		}
251 	}
252 
253 	if (!diskboot)
254 		return;
255 
256 	if (device_is_a(dev, "sd") ||
257 	    device_is_a(dev, "st") ||
258 	    device_is_a(dev, "cd")) {
259 		struct scsipibus_attach_args *sa = aux;
260 		struct scsipi_periph *periph = sa->sa_periph;
261 		int unit;
262 
263 		if (device_parent(parent) != ctrlrdev)
264 			return;
265 
266 		unit = periph->periph_target * 100 + periph->periph_lun;
267 		if (b->unit != unit)
268 			return;
269 		if (b->channel != periph->periph_channel->chan_channel)
270 			return;
271 
272 		/* we've found it! */
273 		booted_device = dev;
274 #if 0
275 		printf("\nbooted_device = %s\n", device_xname(dev));
276 #endif
277 		found = 1;
278 	}
279 }
280 
281 static void
dec_kn20aa_mcheck(unsigned long mces,unsigned long type,unsigned long logout,struct trapframe * framep)282 dec_kn20aa_mcheck(unsigned long mces, unsigned long type, unsigned long logout, struct trapframe *framep)
283 {
284 	struct mchkinfo *mcp;
285 	mc_hdr_ev5 *hdr;
286 	mc_uc_ev5 *mptr;
287 
288 	/*
289 	 * If we expected a machine check, just go handle it in common code.
290 	 */
291 	mcp = &curcpu()->ci_mcinfo;
292 	if (mcp->mc_expected) {
293 		machine_check(mces, framep, type, logout);
294 		return;
295 	}
296 
297 	hdr = (mc_hdr_ev5 *) logout;
298 	mptr = (mc_uc_ev5 *) (logout + sizeof (*hdr));
299 
300 	/*
301 	 * Now we can finally print some stuff...
302 	 */
303 	ev5_logout_print(hdr, mptr);
304 
305 	machine_check(mces, framep, type, logout);
306 }
307 
308 static void
dec_kn20aa_mcheck_handler(unsigned long mces,struct trapframe * framep,unsigned long vector,unsigned long param)309 dec_kn20aa_mcheck_handler(unsigned long mces, struct trapframe *framep, unsigned long vector, unsigned long param)
310 {
311 
312 	switch (vector) {
313 	case ALPHA_SYS_MCHECK:
314 	case ALPHA_PROC_MCHECK:
315 		dec_kn20aa_mcheck(mces, vector, param, framep);
316 		break;
317 	default:
318 		printf("KN20AA_MCHECK: unknown check vector 0x%lx\n", vector);
319 		machine_check(mces, framep, vector, param);
320 		break;
321 	}
322 }
323