#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: shark_machdep.c,v 1.47 2021/08/17 22:00:31 andvar Exp $");
#include "opt_ddb.h"
#include "opt_modular.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/reboot.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/buf.h>
#include <sys/exec.h>
#include <sys/ksyms.h>
#include <sys/device.h>
#include <sys/cpu.h>
#include <sys/intr.h>
#include <uvm/uvm_extern.h>
#include <dev/cons.h>
#include <dev/ofw/openfirm.h>
#include <dev/isa/isavar.h>
#include <dev/ofisa/ofisavar.h>
#include <machine/db_machdep.h>
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>
#include <arm/fiq.h>
#include <arm/locore.h>
#include <arm/undefined.h>
#include <arm/arm32/machdep.h>
#include <machine/bootconfig.h>
#include <machine/pio.h>
#include <machine/ofw.h>
#include <machine/isa_machdep.h>
#include <shark/shark/sequoia.h>
#include "isadma.h"
#include "vlpci.h"
#include "wd.h"
#include "cd.h"
#include "sd.h"
#if NWD > 0 || NSD > 0 || NCD > 0
#include <dev/ata/atavar.h>
#endif
#if NSD > 0 || NCD > 0
#include <dev/scsipi/scsi_all.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsipiconf.h>
#endif
#include "ksyms.h"
extern pv_addr_t irqstack;
extern pv_addr_t undstack;
extern pv_addr_t abtstack;
extern void data_abort_handler(trapframe_t *frame);
extern void prefetch_abort_handler(trapframe_t *frame);
extern void undefinedinstruction_bounce(trapframe_t *frame);
extern void consinit(void);
int ofbus_match(device_t, cfdata_t, void *);
void ofbus_attach(device_t, device_t, void *);
paddr_t isa_io_physaddr, isa_mem_physaddr;
BootConfig bootconfig;
char *boot_args = NULL;
char *boot_file = NULL;
extern char *booted_kernel;
#ifndef PMAP_STATIC_L1S
int max_processes = 64;
#endif
int ofw_handleticks = 0;
extern unsigned int sa1_cache_clean_addr;
extern unsigned int sa1_cache_clean_size;
#if NVLPCI > 0
extern vaddr_t vlpci_mem_vaddr;
#endif
CFATTACH_DECL_NEW(ofbus_root, 0,
ofbus_match, ofbus_attach, NULL, NULL);
extern void cpu_reboot(int, char *);
extern void ofrootfound(void);
static void process_kernel_args(void);
void ofw_device_register(device_t, void *);
#define KERNEL_TEXT_BASE (KERNEL_BASE + 0x00000000)
void
cpu_reboot(int howto, char *bootstr)
{
ofw_boot(howto, bootstr);
OF_boot("not reached -- stupid compiler");
}
struct fiqhandler shark_fiqhandler;
struct fiqregs shark_fiqregs;
vaddr_t
initarm(void *arg)
{
ofw_handle_t ofw_handle = arg;
paddr_t pclean;
vaddr_t isa_io_virtaddr, isa_mem_virtaddr;
paddr_t isadmaphysbufs;
extern char shark_fiq[], shark_fiq_end[];
(void)disable_interrupts(I32_bit | F32_bit);
set_cpufuncs();
boothowto = 0;
ofw_init(ofw_handle);
ofw_configisa(&isa_io_physaddr, &isa_mem_physaddr);
isa_mem_virtaddr = ofw_map(isa_mem_physaddr, L1_S_SIZE, 0);
isa_io_virtaddr = ofw_map(isa_io_physaddr, L1_S_SIZE, 0);
#if NVLPCI > 0
vlpci_mem_vaddr = ofw_map(0x02000000, 0x00100000, 0);
#endif
isa_init(isa_io_virtaddr, isa_mem_virtaddr);
consinit();
ofw_getbootinfo(&boot_file, &boot_args);
process_kernel_args();
ofw_configisadma(&isadmaphysbufs);
#if (NISADMA > 0)
isa_dma_init();
#endif
if ((pclean = ofw_getcleaninfo()) != -1) {
sa1_cache_clean_addr = ofw_map(pclean, 0x4000 * 2,
L2_B | L2_C);
sa1_cache_clean_size = 0x4000;
}
ofw_configmem();
set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + PAGE_SIZE);
set_stackptr(PSR_UND32_MODE, undstack.pv_va + PAGE_SIZE);
set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + PAGE_SIZE);
arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL & ~ARM_VEC_RESET);
data_abort_handler_address = (u_int)data_abort_handler;
prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
undefined_handler_address =
(u_int)undefinedinstruction_bounce;
undefined_init();
shark_fiqhandler.fh_func = shark_fiq;
shark_fiqhandler.fh_size = shark_fiq_end - shark_fiq;
shark_fiqhandler.fh_flags = 0;
shark_fiqhandler.fh_regs = &shark_fiqregs;
shark_fiqregs.fr_r8 = isa_io_virtaddr;
shark_fiqregs.fr_r9 = 0;
shark_fiqregs.fr_r10 = 0;
shark_fiqregs.fr_r11 = 0;
shark_fiqregs.fr_r12 = 0;
shark_fiqregs.fr_r13 = 0;
if (fiq_claim(&shark_fiqhandler))
panic("Cannot claim FIQ vector.");
#ifdef DDB
db_machine_init();
if (boothowto & RB_KDB)
Debugger();
#endif
return kernelstack.pv_va + USPACE_SVC_STACK_TOP;
}
static void
process_kernel_args(void)
{
#ifdef RB_QUIET
int value;
#endif
#if defined(RB_QUIET) && defined(BOOT_QUIETLY)
boothowto |= RB_QUIET;
#endif
parse_mi_bootargs(boot_args);
#ifdef RB_QUIET
if (get_bootconf_option(args, "noquiet", BOOTOPT_TYPE_BOOLEAN, &value)) {
if (!value)
boothowto |= RB_QUIET;
else
boothowto &= ~RB_QUIET;
}
if (get_bootconf_option(args, "quiet", BOOTOPT_TYPE_BOOLEAN, &value)) {
if (value)
boothowto |= RB_QUIET;
else
boothowto &= ~RB_QUIET;
}
#endif
}
void
ofrootfound(void)
{
int node;
struct ofbus_attach_args aa;
if (!(node = OF_peer(0)))
panic("No OFW root");
aa.oba_busname = "ofw";
aa.oba_phandle = node;
if (!config_rootfound("ofbus", &aa))
panic("ofw root ofbus not configured");
}
void
ofw_device_register(device_t dev, void *aux)
{
static device_t parent;
#if NSD > 0 || NCD > 0
static device_t scsipidev;
#endif
static char *boot_component;
struct ofbus_attach_args *oba;
char name[64];
int i;
if (boot_component == NULL) {
char *cp;
boot_component = boot_file;
if (boot_component == NULL)
return;
cp = strrchr(boot_component, ':');
if (cp != NULL) {
int cplen;
*cp++ = '\0';
if (cp[0] == '\\')
cp++;
booted_kernel = cp;
cplen = strlen(cp);
if (cplen > 5 && !strcmp(&cp[cplen-5], ".aout")) {
cp[cplen-5] = '\0';
}
}
}
if (booted_device != NULL
|| boot_component == NULL
|| boot_component[0] == '\0')
return;
if (device_is_a(dev, "ofbus") || device_is_a(dev, "ofisa")) {
oba = aux;
} else if (parent == NULL) {
return;
} else if (parent == device_parent(dev)
&& device_is_a(parent, "ofisa")) {
struct ofisa_attach_args *aa = aux;
oba = &aa->oba;
#if NWD > 0 || NSD > 0 || NCD > 0
} else if (device_parent(device_parent(dev)) != NULL
&& parent == device_parent(device_parent(dev))
&& device_is_a(parent, "wdc")) {
#if NSD > 0 || NCD > 0
if (device_is_a(dev, "atapibus")) {
scsipidev = dev;
return;
}
#endif
#if NWD > 0
if (device_is_a(dev, "wd")) {
struct ata_device *adev = aux;
char *cp = strchr(boot_component, '@');
if (cp != NULL
&& adev->adev_drv_data->drive == strtoul(cp+1, NULL, 16)
&& adev->adev_channel == 0) {
booted_device = dev;
return;
}
}
return;
#endif
#if NSD > 0 || NCD > 0
} else if (scsipidev == device_parent(dev)
&& (device_is_a(dev, "sd") || device_is_a(dev, "cd"))) {
struct scsipibus_attach_args *sa = aux;
char *cp = strchr(boot_component, '@');
if (cp != NULL
&& sa->sa_periph->periph_channel->chan_bustype->bustype_type == SCSIPI_BUSTYPE_ATAPI
&& sa->sa_periph->periph_channel->chan_channel == 0
&& sa->sa_periph->periph_target == strtoul(cp+1, NULL, 16)) {
booted_device = dev;
}
return;
#endif
#endif
} else {
return;
}
(void) of_packagename(oba->oba_phandle, name, sizeof name);
i = strlen(name);
if (!strncmp(name, &boot_component[1], i)
&& (boot_component[i+1] == '/' || boot_component[i+1] == '\0')) {
boot_component += i + 1;
if (boot_component[0] == '/') {
parent = dev;
} else {
booted_device = dev;
}
}
}