#include "opt_amigaccgrf.h"
#include "opt_p5ppc68kboard.h"
#include "opt_devreload.h"
#include "opt_m68k_arch.h"
#include "z3rambd.h"
#include "ser.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: amiga_init.c,v 1.141 2026/05/30 10:10:11 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/tty.h>
#include <sys/buf.h>
#include <sys/msgbuf.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/reboot.h>
#include <sys/exec.h>
#include <dev/mm.h>
#include <uvm/uvm_extern.h>
#include <machine/pte.h>
#include <machine/cpu.h>
#include <machine/vectors.h>
#include <amiga/amiga/cc.h>
#include <amiga/amiga/cia.h>
#include <amiga/amiga/custom.h>
#include <amiga/amiga/cfdev.h>
#include <amiga/amiga/drcustom.h>
#include <amiga/amiga/gayle.h>
#include <amiga/amiga/memlist.h>
#include <amiga/dev/zbusvar.h>
#include <amiga/dev/z3rambdvar.h>
#define RELOC(v, t) *((t*)((u_int)&(v) + loadbase))
extern u_int lowram;
extern u_int Umap;
extern u_long boot_partition;
extern vaddr_t m68k_uptbase;
#ifdef P5PPC68KBOARD
extern int p5ppc;
#endif
extern char *esym;
#ifdef GRF_AGA
extern u_long aga_enable;
#endif
#if NSER > 0
extern int serconsole;
#endif
extern u_long noncontig_enable;
vaddr_t INTREQRaddr;
vaddr_t INTREQWaddr;
volatile unsigned short *amiga_intena_read, *amiga_intena_write;
vaddr_t CHIPMEMADDR;
vaddr_t chipmem_start;
vaddr_t chipmem_end;
vaddr_t z2mem_start;
static vaddr_t z2mem_end;
int use_z2_mem = 1;
u_long boot_fphystart, boot_fphysize, boot_cphysize;
static u_int start_c_fphystart;
static u_int start_c_pstart;
static u_long boot_flags;
struct boot_memlist *memlist;
struct cfdev *cfdev;
int ncfdev;
u_long scsi_nosync;
int shift_nosync;
void start_c(int, u_int, u_int, u_int, char *, u_int, u_long, u_long, u_int);
void rollcolor(int);
#ifdef DEVRELOAD
static int kernel_image_magic_size(void);
static void kernel_image_magic_copy(u_char *);
int kernel_reload_write(struct uio *);
extern void kernel_reload(char *, u_long, u_long, u_long, u_long,
u_long, u_long, u_long, u_long, u_long, u_long);
#endif
extern void etext(void);
void *start_c_finish(void);
void *
chipmem_steal(long amount)
{
vaddr_t p = chipmem_end - amount;
if (p & 1)
p = p - 1;
chipmem_end = p;
if(chipmem_start > chipmem_end)
panic("not enough chip memory");
return((void *)p);
}
void *
alloc_z2mem(long amount)
{
if (use_z2_mem && z2mem_end && (z2mem_end - amount) >= z2mem_start) {
z2mem_end -= amount;
return ((void *)z2mem_end);
}
return (alloc_chipmem(amount));
}
int kernel_copyback = 1;
__attribute__ ((no_instrument_function))
void
start_c(int id, u_int fphystart, u_int fphysize, u_int cphysize,
char *esym_addr, u_int flags, u_long inh_sync, u_long boot_part,
u_int loadbase)
{
extern char end[];
struct cfdev *cd;
paddr_t pstart, pend;
vaddr_t vstart, vend;
psize_t avail;
paddr_t ptpa;
psize_t ptsize;
u_int ptextra, kstsize;
paddr_t Sysptmap_pa;
register st_entry_t sg_proto, *sg;
#if defined(M68040) || defined(M68060)
register st_entry_t *esg;
#endif
register pt_entry_t pg_proto, *pg, *epg;
vaddr_t end_loaded;
u_int ncd;
#if defined(M68040) || defined(M68060)
u_int i, nl1desc, nl2desc;
#endif
vaddr_t kva;
struct boot_memlist *ml;
#ifdef DEBUG_KERNEL_START
volatile u_int8_t *altaiscolpt = (u_int8_t *)0x200003c8;
volatile u_int8_t *altaiscol = (u_int8_t *)0x200003c9;
#endif
#ifdef DEBUG_KERNEL_START
if ((id>>24)==0x7D) {
*altaiscolpt = 0;
*altaiscol = 40;
*altaiscol = 0;
*altaiscol = 0;
} else
((volatile struct Custom *)0xdff000)->color[0] = 0xa00;
#endif
#ifdef LIMITMEM
if (fphysize > LIMITMEM*1024*1024)
fphysize = LIMITMEM*1024*1024;
#endif
RELOC(boot_fphystart, u_long) = fphystart;
RELOC(boot_fphysize, u_long) = fphysize;
RELOC(boot_cphysize, u_long) = cphysize;
RELOC(machineid, int) = id;
RELOC(chipmem_end, vaddr_t) = cphysize;
RELOC(esym, char *) = esym_addr;
RELOC(boot_flags, u_long) = flags;
RELOC(boot_partition, u_long) = boot_part;
#ifdef GRF_AGA
if (flags & 1)
RELOC(aga_enable, u_long) |= 1;
#endif
if (flags & (3 << 1))
RELOC(noncontig_enable, u_long) = (flags >> 1) & 3;
#if NSER > 0
if (flags & (1 << 3))
RELOC(serconsole, int) = 0;
#endif
RELOC(scsi_nosync, u_long) = inh_sync;
if (esym_addr == NULL)
end_loaded = (vaddr_t)&end;
else
end_loaded = (vaddr_t)esym_addr;
RELOC(ncfdev, int) = *(int *)(&RELOC(*(u_int *)end_loaded, u_int));
RELOC(cfdev, struct cfdev *) = (struct cfdev *) ((int)end_loaded + 4);
end_loaded += 4 + RELOC(ncfdev, int) * sizeof(struct cfdev);
RELOC(memlist, struct boot_memlist *) =
(struct boot_memlist *)end_loaded;
ml = &RELOC(*(struct boot_memlist *)end_loaded, struct boot_memlist);
end_loaded = (vaddr_t)&((RELOC(memlist, struct boot_memlist *))->
m_seg[ml->m_nseg]);
if (ml->m_nseg > 0 && ml->m_nseg < 16 && RELOC(use_z2_mem, int)) {
struct boot_memseg *sp, *esp;
sp = ml->m_seg;
esp = sp + ml->m_nseg;
for (; sp < esp; sp++) {
if ((sp->ms_attrib & (MEMF_FAST | MEMF_24BITDMA))
!= (MEMF_FAST|MEMF_24BITDMA))
continue;
if (sp->ms_start == fphystart)
continue;
RELOC(z2mem_end, paddr_t) =
sp->ms_start + sp->ms_size;
RELOC(z2mem_start, paddr_t) =
RELOC(z2mem_end, paddr_t) - MAXPHYS *
RELOC(use_z2_mem, int) * 7;
RELOC(NZTWOMEMPG, u_int) =
(RELOC(z2mem_end, paddr_t) -
RELOC(z2mem_start, paddr_t)) / PAGE_SIZE;
if ((RELOC(z2mem_end, paddr_t) -
RELOC(z2mem_start, paddr_t)) > sp->ms_size) {
RELOC(NZTWOMEMPG, u_int) = sp->ms_size /
PAGE_SIZE;
RELOC(z2mem_start, paddr_t) =
RELOC(z2mem_end, paddr_t) - sp->ms_size;
}
break;
}
}
for (RELOC(ZBUSAVAIL, u_int) = 0, cd =
&RELOC(*RELOC(cfdev, struct cfdev *),struct cfdev),
ncd = RELOC(ncfdev, int); ncd > 0; ncd--, cd++) {
int bd_type = cd->rom.type & (ERT_TYPEMASK | ERTF_MEMLIST);
if (cd->rom.manid == 8512 &&
(cd->rom.prodid == 100 || cd->rom.prodid == 110))
RELOC(ZBUSAVAIL, u_int) += m68k_round_page(0x1400000);
#if NZ3RAMBD > 0
if (z3rambd_match_id(cd->rom.manid, cd->rom.prodid) > 0)
{
} else
#endif
if (bd_type != ERT_ZORROIII &&
(bd_type != ERT_ZORROII || isztwopa(cd->addr)))
continue;
if (bd_type == ERT_ZORROIII &&
!(cd->rom.flags & ERFF_EXTENDED) &&
(cd->rom.flags & ERT_Z3_SSMASK) == 0)
cd->size = 0x10000 <<
((cd->rom.type - 1) & ERT_MEMMASK);
RELOC(ZBUSAVAIL, u_int) += m68k_round_page(cd->size);
}
vend = fphysize;
avail = vend;
vstart = end_loaded;
vstart = m68k_round_page(vstart);
pstart = (paddr_t)vstart + fphystart;
pend = vend + fphystart;
avail -= vstart;
RELOC(lwp0uarea, vaddr_t) = vstart;
pstart += USPACE;
vstart += USPACE;
avail -= USPACE;
#if defined(M68040) || defined(M68060)
if (RELOC(mmutype, int) == MMU_68040)
kstsize = MAXKL2SIZE / (NPTEPG/SG4_LEV2SIZE);
else
#endif
kstsize = 1;
RELOC(Sysseg_pa, u_int) = pstart;
RELOC(Sysseg, u_int) = vstart;
vstart += PAGE_SIZE * kstsize;
pstart += PAGE_SIZE * kstsize;
avail -= PAGE_SIZE * kstsize;
RELOC(Sysptmap, u_int) = vstart;
Sysptmap_pa = pstart;
vstart += PAGE_SIZE;
pstart += PAGE_SIZE;
avail -= PAGE_SIZE;
ptpa = pstart;
#ifdef DRACO
if ((id>>24)==0x7D) {
ptextra = NDRCCPG
+ RELOC(NZTWOMEMPG, u_int)
+ btoc(RELOC(ZBUSAVAIL, u_int));
} else
#endif
ptextra = NCHIPMEMPG + NCIAPG + NZTWOROMPG + RELOC(NZTWOMEMPG, u_int) +
btoc(RELOC(ZBUSAVAIL, u_int)) + NPCMCIAPG;
ptsize = (RELOC(Sysptsize, u_int) +
howmany(ptextra, NPTEPG)) << PGSHIFT;
vstart += ptsize;
pstart += ptsize;
avail -= ptsize;
RELOC(Sysmap, u_int *) = (u_int *)SYSMAP_VA;
#if defined(M68040) || defined(M68060)
if (RELOC(mmutype, int) == MMU_68040) {
sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
esg = &sg[kstsize * NPTEPG];
while (sg < esg)
*sg++ = SG_NV;
nl2desc = (ptsize >> PGSHIFT) * (NPTEPG / SG4_LEV3SIZE);
sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
sg = &sg[SG4_LEV1SIZE];
esg = &sg[nl2desc];
sg_proto = ptpa | SG_U | SG_RW | SG_V;
while (sg < esg) {
*sg++ = sg_proto;
sg_proto += (SG4_LEV3SIZE * sizeof (st_entry_t));
}
nl1desc = howmany(nl2desc, SG4_LEV2SIZE);
sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
esg = &sg[nl1desc];
sg_proto = (paddr_t)&sg[SG4_LEV1SIZE] | SG_U | SG_RW | SG_V;
while (sg < esg) {
*sg++ = sg_proto;
sg_proto += (SG4_LEV2SIZE * sizeof(st_entry_t));
}
sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
sg = &sg[SG4_LEV1SIZE - 1];
*sg = sg_proto;
i = SG4_LEV1SIZE + (nl1desc * SG4_LEV2SIZE);
sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
sg = &sg[i + SG4_LEV2SIZE - (NPTEPG / SG4_LEV3SIZE)];
esg = &sg[NPTEPG / SG4_LEV3SIZE];
sg_proto = Sysptmap_pa | SG_U | SG_RW | SG_V;
while (sg < esg) {
*sg++ = sg_proto;
sg_proto += (SG4_LEV3SIZE * sizeof (st_entry_t));
}
RELOC(protostfree, u_int) =
(~0 << (1 + nl1desc + 1)) ;
pg = (pt_entry_t *)Sysptmap_pa;
epg = &pg[ptsize >> PGSHIFT];
pg_proto = ptpa | PG_RW | PG_CI | PG_V;
while (pg < epg) {
*pg++ = pg_proto;
pg_proto += PAGE_SIZE;
}
epg = (pt_entry_t *)(Sysptmap_pa + PAGE_SIZE - sizeof(st_entry_t));
while (pg < epg)
*pg++ = SG_NV;
pg = (pt_entry_t *)Sysptmap_pa;
pg = &pg[SYSMAP_VA >> SEGSHIFT];
*pg = Sysptmap_pa | PG_RW | PG_CI | PG_V;
} else
#endif
{
sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
pg = (pt_entry_t *)Sysptmap_pa;
epg = &pg[ptsize >> PGSHIFT];
sg_proto = ptpa | SG_RW | SG_V;
pg_proto = ptpa | PG_RW | PG_CI | PG_V;
while (pg < epg) {
*sg++ = sg_proto;
*pg++ = pg_proto;
sg_proto += PAGE_SIZE;
pg_proto += PAGE_SIZE;
}
epg = (pt_entry_t *)Sysptmap_pa;
epg = &epg[TIA_SIZE];
while (pg < epg) {
*sg++ = SG_NV;
*pg++ = PG_NV;
}
sg = (st_entry_t *)RELOC(Sysseg_pa, u_int);
sg = &sg[SYSMAP_VA >> SEGSHIFT];
pg = (pt_entry_t *)Sysptmap_pa;
pg = &pg[SYSMAP_VA >> SEGSHIFT];
*sg = Sysptmap_pa | SG_RW | SG_V;
*pg = Sysptmap_pa | PG_RW | PG_CI | PG_V;
}
pg_proto = fphystart | PG_RO | PG_V;
pg = (pt_entry_t *)ptpa;
*pg++ = PG_NV;
pg_proto += PAGE_SIZE;
for (kva = PAGE_SIZE; kva < (vaddr_t)etext;
kva += PAGE_SIZE, pg_proto += PAGE_SIZE)
*pg++ = pg_proto;
pg_proto = (pg_proto & PG_FRAME) | PG_RW | PG_V;
#if defined(M68040) || defined(M68060)
if (RELOC(mmutype, int) == MMU_68040) {
if (RELOC(kernel_copyback, int))
pg_proto |= PG_CCB;
for (; kva < RELOC(Sysseg, u_int);
kva += PAGE_SIZE, pg_proto += PAGE_SIZE)
*pg++ = pg_proto;
pg_proto = (pg_proto & ~PG_CCB) | PG_CI;
for (; kva < vstart; kva += PAGE_SIZE, pg_proto += PAGE_SIZE)
*pg++ = pg_proto;
pg_proto = (pg_proto & ~PG_CI);
if (RELOC(kernel_copyback, int))
pg_proto |= PG_CCB;
}
#endif
for (; kva < vstart; kva += PAGE_SIZE, pg_proto += PAGE_SIZE)
*pg++ = pg_proto;
while (pg < (pt_entry_t *) (ptpa + ptsize))
*pg++ = PG_NV;
pg = &((u_int *)ptpa)[vstart >> PGSHIFT];
#ifdef DRACO
if ((id >> 24) == 0x7D) {
RELOC(DRCCADDR, u_int) = vstart;
RELOC(CIAADDR, vaddr_t) =
RELOC(DRCCADDR, u_int) + DRCIAPG * PAGE_SIZE;
if (RELOC(z2mem_end, vaddr_t) == 0)
RELOC(ZBUSADDR, vaddr_t) =
RELOC(DRCCADDR, u_int) + NDRCCPG * PAGE_SIZE;
pg_proto = DRCCBASE | PG_RW | PG_CI | PG_V;
while (pg_proto < DRZ2BASE) {
*pg++ = pg_proto;
pg_proto += DRCCSTRIDE;
vstart += PAGE_SIZE;
}
*pg++ = DRSCSIBASE | PG_RW | PG_CI | PG_V;
vstart += PAGE_SIZE;
#ifdef DEBUG_KERNEL_START
*pg++ = 0x20000000 | PG_RW | PG_CI | PG_V;
vstart += PAGE_SIZE;
#endif
} else
#endif
{
RELOC(CHIPMEMADDR, vaddr_t) = vstart;
pg_proto = CHIPMEMBASE | PG_RW | PG_CI | PG_V;
while (pg_proto < CHIPMEMTOP) {
*pg++ = pg_proto;
pg_proto += PAGE_SIZE;
vstart += PAGE_SIZE;
}
}
if (RELOC(z2mem_end, paddr_t)) {
RELOC(ZTWOMEMADDR, vaddr_t) = vstart;
RELOC(ZBUSADDR, vaddr_t) = RELOC(ZTWOMEMADDR, vaddr_t) +
RELOC(NZTWOMEMPG, u_int) * PAGE_SIZE;
pg_proto = RELOC(z2mem_start, paddr_t) |
PG_RW | PG_V;
while (pg_proto < RELOC(z2mem_end, paddr_t)) {
*pg++ = pg_proto;
pg_proto += PAGE_SIZE;
vstart += PAGE_SIZE;
}
}
#ifdef DRACO
if ((id >> 24) != 0x7D)
#endif
{
RELOC(CIAADDR, vaddr_t) = vstart;
pg_proto = CIABASE | PG_RW | PG_CI | PG_V;
while (pg_proto < CIATOP) {
*pg++ = pg_proto;
pg_proto += PAGE_SIZE;
vstart += PAGE_SIZE;
}
RELOC(ZTWOROMADDR, vaddr_t) = vstart;
pg_proto = ZTWOROMBASE | PG_RW | PG_CI | PG_V;
while (pg_proto < ZTWOROMTOP) {
*pg++ = pg_proto;
pg_proto += PAGE_SIZE;
vstart += PAGE_SIZE;
}
RELOC(ZBUSADDR, vaddr_t) = vstart;
RELOC(CIAADDR, vaddr_t) += PAGE_SIZE/2;
RELOC(CUSTOMADDR, vaddr_t) =
RELOC(ZTWOROMADDR, vaddr_t) - ZTWOROMBASE + CUSTOMBASE;
}
vstart += RELOC(ZBUSAVAIL, u_int);
RELOC(maxmem, u_int) = pend >> PGSHIFT;
RELOC(lowram, u_int) = fphystart;
RELOC(physmem, psize_t) = fphysize >> PGSHIFT;
RELOC(virtual_avail, u_int) = vstart;
RELOC(m68k_uptbase, vaddr_t) =
roundup(vstart + 0x10000000, 0x10000000);
#if defined(M68020) || defined(M68030)
RELOC(protorp[1], u_int) = RELOC(Sysseg_pa, u_int);
#endif
RELOC(start_c_fphystart, u_int) = fphystart;
RELOC(start_c_pstart, u_int) = pstart;
if (loadbase == 0) {
register paddr_t *lp, *le, *fp;
lp = (paddr_t *)0;
le = (paddr_t *)end_loaded;
fp = (paddr_t *)fphystart;
while (lp < le)
*fp++ = *lp++;
}
#ifdef DEBUG_KERNEL_START
if ((id>>24)==0x7D) {
*altaiscolpt = 0;
*altaiscol = 40;
*altaiscol = 40;
*altaiscol = 0;
} else
((volatile struct Custom *)0xdff000)->color[0] = 0xAA0;
#endif
#if defined(M68040) || defined(M68060)
if (RELOC(mmutype, int) == MMU_68040) {
if (id & AMIGA_68060) {
__asm volatile ( ".word 0x4e7a,0x0002;"
"orl #0x400000,%%d0;"
".word 0x4e7b,0x0002" : : : "d0");
}
__asm volatile ("movel %0,%%a0; .word 0x4e7b,0x8807"
: : "a" (RELOC(Sysseg_pa, u_int)) : "a0");
#ifdef DEBUG_KERNEL_START
if ((id>>24)==0x7D) {
*altaiscolpt = 0;
*altaiscol = 40;
*altaiscol = 33;
*altaiscol = 0;
} else
((volatile struct Custom *)0xdff000)->color[0] = 0xA70;
#endif
return;
}
#endif
#if defined(M68020) || defined(M68030)
__asm volatile ("pmove %0@,%%srp":: "a" (&RELOC(protorp, u_int)));
#endif
}
void *
start_c_finish(void)
{
#ifdef P5PPC68KBOARD
struct cfdev *cdp, *ecdp;
#endif
#ifdef DEBUG_KERNEL_START
#ifdef DRACO
if ((id >> 24) == 0x7D) {
int i;
altaiscolpt = (volatile u_int8_t *)(DRCCADDR+PAGE_SIZE*9+0x3c8);
altaiscol = altaiscolpt + 1;
for (i=0; i<140000; i++) {
*altaiscolpt = 0;
*altaiscol = 0;
*altaiscol = 40;
*altaiscol = 0;
}
} else
#endif
((volatile struct Custom *)CUSTOMADDR)->color[0] = 0x0a0;
#endif
#ifdef DRACO
extern char DraCoIntr[], DraCoLev1intr[], DraCoLev2intr[];
u_char dracorev;
dracorev = is_draco();
if (dracorev) {
if (dracorev >= 4) {
vectab[24+1] = DraCoLev1intr;
vectab[24+2] = DraCoIntr;
} else {
vectab[24+1] = DraCoIntr;
vectab[24+2] = DraCoLev2intr;
}
vectab[24+3] = DraCoIntr;
vectab[24+4] = DraCoIntr;
vectab[24+5] = DraCoIntr;
vectab[24+6] = DraCoIntr;
}
#endif
pmap_bootstrap(start_c_pstart, start_c_fphystart);
void *ksp = pmap_bootstrap2();
extern paddr_t msgbufpa;
for (int i = 0; i < btoc(round_page(MSGBUFSIZE)); i++) {
pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
msgbufpa + i * PAGE_SIZE,
VM_PROT_READ|VM_PROT_WRITE, 0);
}
initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE));
CIAAbase = CIAADDR + 0x1001;
CIABbase = CIAADDR;
CUSTOMbase = CUSTOMADDR;
#ifdef DRACO
if (is_draco()) {
draco_intena = (volatile u_int8_t *)DRCCADDR+1;
draco_intpen = draco_intena + PAGE_SIZE;
draco_intfrc = draco_intpen + PAGE_SIZE;
draco_misc = draco_intfrc + PAGE_SIZE;
draco_ioct = (struct drioct *)(DRCCADDR + DRIOCTLPG*PAGE_SIZE);
} else
#endif
{
INTREQRaddr = (vaddr_t)&custom.intreqr;
INTREQWaddr = (vaddr_t)&custom.intreq;
}
chipmem_start += CHIPMEMADDR;
chipmem_end += CHIPMEMADDR;
if (z2mem_end) {
z2mem_end = ZTWOMEMADDR + NZTWOMEMPG * PAGE_SIZE;
z2mem_start = ZTWOMEMADDR;
}
#ifdef DRACO
if (is_draco()) {
*draco_intena = 0;
*draco_intpen = 0;
*draco_intfrc = 0;
ciaa.icr = 0x7f;
ciab.icr = 0x7f;
draco_ioct->io_control &=
~(DRCNTRL_KBDINTENA|DRCNTRL_FDCINTENA);
draco_ioct->io_status2 &=
~(DRSTAT2_PARIRQENA|DRSTAT2_TMRINTENA);
*(volatile u_int8_t *)(DRCCADDR + 1 +
DRSUPIOPG*PAGE_SIZE + 4*(0x3F8 + 1)) = 0;
*(volatile u_int8_t *)(DRCCADDR + 1 +
DRSUPIOPG*PAGE_SIZE + 4*(0x2F8 + 1)) = 0;
draco_ioct->io_control |= DRCNTRL_WDOGDIS;
*draco_misc &= ~1;
} else
#endif
{
custom.intena = 0x7fff;
custom.intena = INTF_SETCLR | INTF_INTEN;
custom.intreq = 0x7fff;
ciaa.icr = 0x7f;
ciab.icr = 0x7f;
amiga_intena_read = &custom.intenar;
amiga_intena_write = &custom.intena;
}
if (is_a3000()) {
volatile unsigned char *a3000_magic_reset;
a3000_magic_reset = (volatile unsigned char *)ztwomap(0xde0002);
*a3000_magic_reset |= 0x80;
}
#ifdef P5PPC68KBOARD
for (cdp = cfdev, ecdp = &cfdev[ncfdev]; cdp < ecdp; cdp++) {
if (cdp->rom.manid == 8512 &&
(cdp->rom.prodid == 100 || cdp->rom.prodid == 110)) {
p5ppc = 1;
break;
}
}
#endif
if (machineid & AMIGA_68060)
delay_divisor = delay_divisor_est60(80);
else if (machineid & AMIGA_68040)
delay_divisor = delay_divisor_est40(40);
else if (machineid & AMIGA_68030)
delay_divisor = delay_divisor_est(50);
else
delay_divisor = delay_divisor_est(33);
return ksp;
}
void
rollcolor(int color)
{
int s, i;
s = splhigh();
for (i = 0; i < 400000; i++)
((volatile struct Custom *)CUSTOMbase)->color[0] = color;
splx(s);
}
#ifdef DEVRELOAD
static struct exec kernel_exec;
static u_char *kernel_image;
static u_long kernel_text_size, kernel_load_ofs;
static u_long kernel_load_phase;
static u_long kernel_load_endseg;
static u_long kernel_symbol_size, kernel_symbol_esym;
static int
kernel_image_magic_size(void)
{
int sz;
sz = 8 + ncfdev * sizeof(struct cfdev)
+ memlist->m_nseg * sizeof(struct boot_memseg);
return(sz);
}
static void
kernel_image_magic_copy(u_char *dest)
{
*((int*)dest) = ncfdev;
dest += 4;
memcpy(dest, cfdev, ncfdev * sizeof(struct cfdev)
+ memlist->m_nseg * sizeof(struct boot_memseg) + 4);
}
#undef AOUT_LDPGSZ
#define AOUT_LDPGSZ 8192
int
kernel_reload_write(struct uio *uio)
{
extern int eclockfreq;
struct iovec *iov;
int error, c;
iov = uio->uio_iov;
if (kernel_image == 0) {
if (iov->iov_len < sizeof(kernel_exec))
return ENOEXEC;
if ((error = uiomove((void *)&kernel_exec, sizeof(kernel_exec),
uio)) != 0)
return(error);
printf("loading kernel %ld+%ld+%ld+%ld\n", kernel_exec.a_text,
kernel_exec.a_data, kernel_exec.a_bss,
esym == NULL ? 0 : kernel_exec.a_syms);
kernel_text_size = (kernel_exec.a_text
+ AOUT_LDPGSZ - 1) & (-AOUT_LDPGSZ);
if (esym != NULL) {
kernel_symbol_size = kernel_exec.a_syms;
kernel_symbol_size += 16 * (kernel_symbol_size / 12);
}
if ((kernel_text_size + kernel_exec.a_data +
kernel_exec.a_bss + kernel_symbol_size +
kernel_image_magic_size()) > boot_cphysize)
return (EFBIG);
kernel_image = malloc(kernel_text_size + kernel_exec.a_data
+ kernel_exec.a_bss
+ kernel_symbol_size
+ kernel_image_magic_size(),
M_TEMP, M_WAITOK);
kernel_load_ofs = 0;
kernel_load_phase = 0;
kernel_load_endseg = kernel_exec.a_text;
return(0);
}
c = uimin(iov->iov_len, kernel_load_endseg - kernel_load_ofs);
c = uimin(c, MAXPHYS);
if ((error = uiomove(kernel_image + kernel_load_ofs, (int)c, uio)) != 0)
return(error);
kernel_load_ofs += c;
if (kernel_load_ofs != kernel_load_endseg)
return(0);
switch (kernel_load_phase) {
case 0:
kernel_load_ofs = kernel_text_size;
kernel_load_endseg = kernel_load_ofs + kernel_exec.a_data;
kernel_load_phase = 1;
break;
case 1:
for(c = 0; c < kernel_exec.a_bss; c++)
kernel_image[kernel_load_ofs + c] = 0;
kernel_load_ofs += kernel_exec.a_bss;
if (esym) {
kernel_load_endseg = kernel_load_ofs
+ kernel_exec.a_syms + 8;
*((u_long *)(kernel_image + kernel_load_ofs)) =
kernel_exec.a_syms;
kernel_load_ofs += 4;
kernel_load_phase = 3;
break;
}
case 2:
kernel_image_magic_copy(kernel_image + kernel_load_ofs);
kernel_reload(kernel_image,
kernel_load_ofs + kernel_image_magic_size(),
kernel_exec.a_entry, boot_fphystart, boot_fphysize,
boot_cphysize, kernel_symbol_esym, eclockfreq,
boot_flags, scsi_nosync, boot_partition);
free(kernel_image, M_TEMP);
kernel_image = NULL;
return (ENODEV);
case 3:
c = *((u_long *)(kernel_image + kernel_load_ofs - 4));
if (c > 16 * (kernel_exec.a_syms / 12))
c = 16 * (kernel_exec.a_syms / 12);
kernel_load_endseg += c - 4;
kernel_symbol_esym = kernel_load_endseg;
#ifdef notyet
kernel_image_copy = kernel_image;
kernel_image = malloc(kernel_load_ofs + c
+ kernel_image_magic_size(), M_TEMP, M_WAITOK);
if (kernel_image == NULL)
panic("kernel_reload failed second malloc");
for (c = 0; c < kernel_load_ofs; c += MAXPHYS)
memcpy(kernel_image + c, kernel_image_copy + c,
(kernel_load_ofs - c) > MAXPHYS ? MAXPHYS :
kernel_load_ofs - c);
#endif
kernel_load_phase = 2;
}
return(0);
}
#endif
int
mm_md_readwrite(dev_t dev, struct uio *uio)
{
switch (minor(dev)) {
#ifdef DEVRELOAD
case DEV_RELOAD:
if (uio->uio_rw == UIO_READ)
return 0;
return kernel_reload_write(uio);
#endif
default:
return ENXIO;
}
}