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