#include <sys/param.h>
#include <sys/systm.h>
#include <uvm/uvm_extern.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/mutex.h>
#include <machine/cpu.h>
#include <machine/rpb.h>
#define ENABLEPROM
#include <machine/prom.h>
#include <dev/cons.h>
struct consdev promcons = { NULL, NULL, promcngetc, promcnputc,
nullcnpollc, NULL, makedev(23,0), 1 };
struct rpb *hwrpb;
int alpha_console;
extern struct prom_vec prom_dispatch_v;
struct mutex prom_lock = MUTEX_INITIALIZER(IPL_HIGH);
void prom_enter(void);
void prom_leave(void);
void
init_prom_interface(struct rpb *rpb)
{
struct crb *c;
c = (struct crb *)((char *)rpb + rpb->rpb_crb_off);
prom_dispatch_v.routine_arg = c->crb_v_dispatch;
prom_dispatch_v.routine = c->crb_v_dispatch->entry_va;
}
void
init_bootstrap_console(void)
{
char buf[4];
init_prom_interface(hwrpb);
prom_getenv(PROM_E_TTY_DEV, buf, 4);
alpha_console = buf[0] - '0';
cn_tab = &promcons;
}
void
prom_enter(void)
{
mtx_enter(&prom_lock);
}
void
prom_leave(void)
{
mtx_leave(&prom_lock);
}
void
promcnputc(dev_t dev, int c)
{
prom_return_t ret;
unsigned char *to = (unsigned char *)0x20000000;
prom_enter();
*to = c;
do {
ret.bits = prom_putstr(alpha_console, to, 1);
} while ((ret.u.retval & 1) == 0);
prom_leave();
}
int
promcngetc(dev_t dev)
{
prom_return_t ret;
for (;;) {
prom_enter();
ret.bits = prom_getc(alpha_console);
prom_leave();
if (ret.u.status == 0 || ret.u.status == 1)
return (ret.u.retval);
}
}
int
prom_getenv(int id, char *buf, int len)
{
unsigned char *to = (unsigned char *)0x20000000;
prom_return_t ret;
prom_enter();
ret.bits = prom_getenv_disp(id, to, len);
bcopy(to, buf, len);
prom_leave();
if (ret.u.status & 0x4)
ret.u.retval = 0;
buf[ret.u.retval] = '\0';
return (ret.bits);
}
void
prom_halt(int halt)
{
struct pcs *p;
(void) splhigh();
p = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
p->pcs_flags &= ~(PCS_RC | PCS_HALT_REQ);
if (halt)
p->pcs_flags |= PCS_HALT_STAY_HALTED;
else
p->pcs_flags |= PCS_HALT_WARM_BOOT;
alpha_pal_halt();
}
u_int64_t
hwrpb_checksum(void)
{
u_int64_t *p, sum;
int i;
for (i = 0, p = (u_int64_t *)hwrpb, sum = 0;
i < (offsetof(struct rpb, rpb_checksum) / sizeof (u_int64_t));
i++, p++)
sum += *p;
return (sum);
}
void
hwrpb_primary_init(void)
{
struct pcs *p;
p = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
bcopy(&proc0.p_addr->u_pcb.pcb_hw, p->pcs_hwpcb,
sizeof proc0.p_addr->u_pcb.pcb_hw);
hwrpb->rpb_vptb = VPTBASE;
hwrpb->rpb_checksum = hwrpb_checksum();
}
void
hwrpb_restart_setup(void)
{
struct pcs *p;
p = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
p->pcs_flags &= ~PCS_BIP;
hwrpb->rpb_rest_term = (u_int64_t)&XentRestart;
hwrpb->rpb_rest_term_val = 0x1;
hwrpb->rpb_checksum = hwrpb_checksum();
p->pcs_flags |= (PCS_RC | PCS_CV);
}
u_int64_t
console_restart(struct trapframe *framep)
{
struct pcs *p;
p = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
p->pcs_flags &= ~PCS_RC;
framep->tf_regs[FRAME_PS] = p->pcs_halt_ps;
framep->tf_regs[FRAME_PC] = p->pcs_halt_pc;
framep->tf_regs[FRAME_T11] = p->pcs_halt_r25;
framep->tf_regs[FRAME_RA] = p->pcs_halt_r26;
framep->tf_regs[FRAME_T12] = p->pcs_halt_r27;
panic("user requested console halt");
return (1);
}