xref: /openbsd/sys/arch/alpha/alpha/prom.c (revision 67a77ffe)
1 /* $OpenBSD: prom.c,v 1.17 2023/02/06 11:16:22 miod Exp $ */
2 /* $NetBSD: prom.c,v 1.39 2000/03/06 21:36:05 thorpej Exp $ */
3 
4 /*
5  * Copyright (c) 1992, 1994, 1995, 1996 Carnegie Mellon University
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie Mellon
26  * the rights to redistribute these changes.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <uvm/uvm_extern.h>
32 #include <sys/proc.h>
33 #include <sys/user.h>
34 #include <sys/mutex.h>
35 
36 #include <machine/cpu.h>
37 #include <machine/rpb.h>
38 #define	ENABLEPROM
39 #include <machine/prom.h>
40 
41 #include <dev/cons.h>
42 
43 /* XXX this is to fake out the console routines, while booting. */
44 struct consdev promcons = { NULL, NULL, promcngetc, promcnputc,
45 			    nullcnpollc, NULL, makedev(23,0), 1 };
46 
47 struct rpb	*hwrpb;
48 int		alpha_console;
49 
50 extern struct prom_vec prom_dispatch_v;
51 
52 struct mutex prom_lock = MUTEX_INITIALIZER(IPL_HIGH);
53 
54 void	prom_enter(void);
55 void	prom_leave(void);
56 
57 void
init_prom_interface(struct rpb * rpb)58 init_prom_interface(struct rpb *rpb)
59 {
60 	struct crb *c;
61 
62 	c = (struct crb *)((char *)rpb + rpb->rpb_crb_off);
63 
64 	prom_dispatch_v.routine_arg = c->crb_v_dispatch;
65 	prom_dispatch_v.routine = c->crb_v_dispatch->entry_va;
66 }
67 
68 void
init_bootstrap_console()69 init_bootstrap_console()
70 {
71 	char buf[4];
72 
73 	init_prom_interface(hwrpb);
74 
75 	prom_getenv(PROM_E_TTY_DEV, buf, 4);
76 	alpha_console = buf[0] - '0';
77 
78 	/* XXX fake out the console routines, for now */
79 	cn_tab = &promcons;
80 }
81 
82 void
prom_enter(void)83 prom_enter(void)
84 {
85 	mtx_enter(&prom_lock);
86 }
87 
88 void
prom_leave(void)89 prom_leave(void)
90 {
91 	mtx_leave(&prom_lock);
92 }
93 
94 /*
95  * promcnputc:
96  *
97  * Remap char before passing off to prom.
98  *
99  * Prom only takes 32 bit addresses. Copy char somewhere prom can
100  * find it. This routine will stop working after pmap_rid_of_console
101  * is called in alpha_init. This is due to the hard coded address
102  * of the console area.
103  */
104 void
promcnputc(dev_t dev,int c)105 promcnputc(dev_t dev, int c)
106 {
107 	prom_return_t ret;
108 	unsigned char *to = (unsigned char *)0x20000000;
109 
110 	prom_enter();	/* lock and map prom */
111 	*to = c;
112 
113 	do {
114 		ret.bits = prom_putstr(alpha_console, to, 1);
115 	} while ((ret.u.retval & 1) == 0);
116 
117 	prom_leave();		/* unmap prom and unlock */
118 }
119 
120 /*
121  * promcngetc:
122  *
123  * Wait for the prom to get a real char and pass it back.
124  */
125 int
promcngetc(dev_t dev)126 promcngetc(dev_t dev)
127 {
128 	prom_return_t ret;
129 
130 	for (;;) {
131 		prom_enter();
132 		ret.bits = prom_getc(alpha_console);
133 		prom_leave();
134 		if (ret.u.status == 0 || ret.u.status == 1)
135 			return (ret.u.retval);
136 	}
137 }
138 
139 int
prom_getenv(int id,char * buf,int len)140 prom_getenv(int id, char *buf, int len)
141 {
142 	unsigned char *to = (unsigned char *)0x20000000;
143 	prom_return_t ret;
144 
145 	prom_enter();
146 	ret.bits = prom_getenv_disp(id, to, len);
147 	bcopy(to, buf, len);
148 	prom_leave();
149 
150 	if (ret.u.status & 0x4)
151 		ret.u.retval = 0;
152 	buf[ret.u.retval] = '\0';
153 
154 	return (ret.bits);
155 }
156 
157 void
prom_halt(int halt)158 prom_halt(int halt)
159 {
160 	struct pcs *p;
161 
162 	/*
163 	 * Turn off interrupts, for sanity.
164 	 */
165 	(void) splhigh();
166 
167 	/*
168 	 * Set "boot request" part of the CPU state depending on what
169 	 * we want to happen when we halt.
170 	 */
171 	p = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
172 	p->pcs_flags &= ~(PCS_RC | PCS_HALT_REQ);
173 	if (halt)
174 		p->pcs_flags |= PCS_HALT_STAY_HALTED;
175 	else
176 		p->pcs_flags |= PCS_HALT_WARM_BOOT;
177 
178 	/*
179 	 * Halt the machine.
180 	 */
181 	alpha_pal_halt();
182 }
183 
184 u_int64_t
hwrpb_checksum()185 hwrpb_checksum()
186 {
187 	u_int64_t *p, sum;
188 	int i;
189 
190 	for (i = 0, p = (u_int64_t *)hwrpb, sum = 0;
191 	    i < (offsetof(struct rpb, rpb_checksum) / sizeof (u_int64_t));
192 	    i++, p++)
193 		sum += *p;
194 
195 	return (sum);
196 }
197 
198 void
hwrpb_primary_init()199 hwrpb_primary_init()
200 {
201 	struct pcs *p;
202 
203 	p = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
204 
205 	/* Initialize the primary's HWPCB and the Virtual Page Table Base. */
206 	bcopy(&proc0.p_addr->u_pcb.pcb_hw, p->pcs_hwpcb,
207 	    sizeof proc0.p_addr->u_pcb.pcb_hw);
208 	hwrpb->rpb_vptb = VPTBASE;
209 
210 	hwrpb->rpb_checksum = hwrpb_checksum();
211 }
212 
213 void
hwrpb_restart_setup()214 hwrpb_restart_setup()
215 {
216 	struct pcs *p;
217 
218 	/* Clear bootstrap-in-progress flag since we're done bootstrapping */
219 	p = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
220 	p->pcs_flags &= ~PCS_BIP;
221 
222 	/* when 'c'ontinuing from console halt, do a dump */
223 	hwrpb->rpb_rest_term = (u_int64_t)&XentRestart;
224 	hwrpb->rpb_rest_term_val = 0x1;
225 
226 	hwrpb->rpb_checksum = hwrpb_checksum();
227 
228 	p->pcs_flags |= (PCS_RC | PCS_CV);
229 }
230 
231 u_int64_t
console_restart(struct trapframe * framep)232 console_restart(struct trapframe *framep)
233 {
234 	struct pcs *p;
235 
236 	/* Clear restart-capable flag, since we can no longer restart. */
237 	p = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
238 	p->pcs_flags &= ~PCS_RC;
239 
240 	/* Fill in the missing frame slots */
241 
242 	framep->tf_regs[FRAME_PS] = p->pcs_halt_ps;
243 	framep->tf_regs[FRAME_PC] = p->pcs_halt_pc;
244 	framep->tf_regs[FRAME_T11] = p->pcs_halt_r25;
245 	framep->tf_regs[FRAME_RA] = p->pcs_halt_r26;
246 	framep->tf_regs[FRAME_T12] = p->pcs_halt_r27;
247 
248 	panic("user requested console halt");
249 
250 	return (1);
251 }
252