Path: blob/master/kern/arch/sys161/dev/lamebus_machdep.c
2127 views
/*1* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 20092* The President and Fellows of Harvard College.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. Neither the name of the University nor the names of its contributors13* may be used to endorse or promote products derived from this software14* without specific prior written permission.15*16* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829#include <types.h>30#include <kern/unistd.h>31#include <lib.h>32#include <mips/trapframe.h>33#include <cpu.h>34#include <spl.h>35#include <clock.h>36#include <thread.h>37#include <current.h>38#include <synch.h>39#include <mainbus.h>40#include <sys161/bus.h>41#include <lamebus/lamebus.h>42#include "autoconf.h"4344/*45* CPU frequency used by the on-chip timer.46*47* Note that we really ought to measure the CPU frequency against the48* real-time clock instead of compiling it in like this.49*/50#define CPU_FREQUENCY 25000000 /* 25 MHz */5152/*53* Access to the on-chip timer.54*55* The c0_count register increments on every cycle; when the value56* matches the c0_compare register, the timer interrupt line is57* asserted. Writing to c0_compare again clears the interrupt.58*/59static60void61mips_timer_set(uint32_t count)62{63/*64* $11 == c0_compare; we can't use the symbolic name inside65* the asm string.66*/67__asm volatile(68".set push;" /* save assembler mode */69".set mips32;" /* allow MIPS32 registers */70"mtc0 %0, $11;" /* do it */71".set pop" /* restore assembler mode */72:: "r" (count));73}7475/*76* LAMEbus data for the system. (We have only one LAMEbus per system.)77* This does not need to be locked, because it's constant once78* initialized, and initialized before we start other threads or CPUs.79*/80static struct lamebus_softc *lamebus;8182void83mainbus_bootstrap(void)84{85/* Interrupts should be off (and have been off since startup) */86KASSERT(curthread->t_curspl > 0);8788/* Initialize the system LAMEbus data */89lamebus = lamebus_init();9091/* Probe CPUs (should these be done as device attachments instead?) */92lamebus_find_cpus(lamebus);9394/*95* Print the device name for the main bus.96*/97kprintf("lamebus0 (system main bus)\n");9899/*100* Now we can take interrupts without croaking, so turn them on.101* Some device probes might require being able to get interrupts.102*/103104spl0();105106/*107* Now probe all the devices attached to the bus.108* (This amounts to all devices.)109*/110autoconf_lamebus(lamebus, 0);111112/*113* Configure the MIPS on-chip timer to interrupt HZ times a second.114*/115mips_timer_set(CPU_FREQUENCY / HZ);116}117118/*119* Start all secondary CPUs.120*/121void122mainbus_start_cpus(void)123{124lamebus_start_cpus(lamebus);125}126127/*128* Function to generate the memory address (in the uncached segment)129* for the specified offset into the specified slot's region of the130* LAMEbus.131*/132void *133lamebus_map_area(struct lamebus_softc *bus, int slot, uint32_t offset)134{135uint32_t address;136137(void)bus; // not needed138139KASSERT(slot >= 0 && slot < LB_NSLOTS);140141address = LB_BASEADDR + slot*LB_SLOT_SIZE + offset;142return (void *)address;143}144145/*146* Read a 32-bit register from a LAMEbus device.147*/148uint32_t149lamebus_read_register(struct lamebus_softc *bus, int slot, uint32_t offset)150{151uint32_t *ptr = lamebus_map_area(bus, slot, offset);152153return *ptr;154}155156/*157* Write a 32-bit register of a LAMEbus device.158*/159void160lamebus_write_register(struct lamebus_softc *bus, int slot,161uint32_t offset, uint32_t val)162{163uint32_t *ptr = lamebus_map_area(bus, slot, offset);164165*ptr = val;166}167168169/*170* Power off the system.171*/172void173mainbus_poweroff(void)174{175/*176*177* Note that lamebus_write_register() doesn't actually access178* the bus argument, so this will still work if we get here179* before the bus is initialized.180*/181lamebus_poweroff(lamebus);182}183184/*185* Reboot the system.186*/187void188mainbus_reboot(void)189{190/*191* The MIPS doesn't appear to have any on-chip reset.192* LAMEbus doesn't have a reset control, so we just193* power off instead of rebooting. This would not be194* so great in a real system, but it's fine for what195* we're doing.196*/197kprintf("Cannot reboot - powering off instead, sorry.\n");198mainbus_poweroff();199}200201/*202* Halt the system.203* On some systems, this would return to the boot monitor. But we don't204* have one.205*/206void207mainbus_halt(void)208{209cpu_halt();210}211212/*213* Called to reset the system from panic().214*215* By the time we get here, the system may well be sufficiently hosed216* as to panic recursively if we do much of anything. So just power off.217* (We'd reboot, but System/161 doesn't do that.)218*/219void220mainbus_panic(void)221{222mainbus_poweroff();223}224225/*226* Function to get the size of installed physical RAM from the LAMEbus227* controller.228*/229uint32_t230mainbus_ramsize(void)231{232return lamebus_ramsize();233}234235/*236* Send IPI.237*/238void239mainbus_send_ipi(struct cpu *target)240{241lamebus_assert_ipi(lamebus, target);242}243244/*245* Interrupt dispatcher.246*/247248/* Wiring of LAMEbus interrupts to bits in the cause register */249#define LAMEBUS_IRQ_BIT 0x00000400 /* all system bus slots */250#define LAMEBUS_IPI_BIT 0x00000800 /* inter-processor interrupt */251#define MIPS_TIMER_BIT 0x00008000 /* on-chip timer */252253void254mainbus_interrupt(struct trapframe *tf)255{256uint32_t cause;257258/* interrupts should be off */259KASSERT(curthread->t_curspl > 0);260261cause = tf->tf_cause;262if (cause & LAMEBUS_IRQ_BIT) {263lamebus_interrupt(lamebus);264}265else if (cause & LAMEBUS_IPI_BIT) {266interprocessor_interrupt();267lamebus_clear_ipi(lamebus, curcpu);268}269else if (cause & MIPS_TIMER_BIT) {270/* Reset the timer (this clears the interrupt) */271mips_timer_set(CPU_FREQUENCY / HZ);272/* and call hardclock */273hardclock();274}275else {276panic("Unknown interrupt; cause register is %08x\n", cause);277}278}279280281