root/kern/arch/sys161/dev/lamebus_machdep.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mips_timer_set
  2. mainbus_bootstrap
  3. mainbus_start_cpus
  4. lamebus_map_area
  5. lamebus_read_register
  6. lamebus_write_register
  7. mainbus_poweroff
  8. mainbus_reboot
  9. mainbus_halt
  10. mainbus_panic
  11. mainbus_ramsize
  12. mainbus_send_ipi
  13. mainbus_interrupt

   1 /*
   2  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
   3  *      The President and Fellows of Harvard College.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the University nor the names of its contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 #include <types.h>
  31 #include <kern/unistd.h>
  32 #include <lib.h>
  33 #include <mips/trapframe.h>
  34 #include <cpu.h>
  35 #include <spl.h>
  36 #include <clock.h>
  37 #include <thread.h>
  38 #include <current.h>
  39 #include <synch.h>
  40 #include <mainbus.h>
  41 #include <sys161/bus.h>
  42 #include <lamebus/lamebus.h>
  43 #include "autoconf.h"
  44 
  45 /*
  46  * CPU frequency used by the on-chip timer.
  47  *
  48  * Note that we really ought to measure the CPU frequency against the
  49  * real-time clock instead of compiling it in like this.
  50  */
  51 #define CPU_FREQUENCY 25000000 /* 25 MHz */
  52 
  53 /*
  54  * Access to the on-chip timer.
  55  *
  56  * The c0_count register increments on every cycle; when the value
  57  * matches the c0_compare register, the timer interrupt line is
  58  * asserted. Writing to c0_compare again clears the interrupt.
  59  */
  60 static
  61 void
  62 mips_timer_set(uint32_t count)
  63 {
  64         /*
  65          * $11 == c0_compare; we can't use the symbolic name inside
  66          * the asm string.
  67          */
  68         __asm volatile(
  69                 ".set push;"            /* save assembler mode */
  70                 ".set mips32;"          /* allow MIPS32 registers */
  71                 "mtc0 %0, $11;"         /* do it */
  72                 ".set pop"              /* restore assembler mode */
  73                 :: "r" (count));
  74 }
  75 
  76 /*
  77  * LAMEbus data for the system. (We have only one LAMEbus per system.)
  78  * This does not need to be locked, because it's constant once
  79  * initialized, and initialized before we start other threads or CPUs.
  80  */
  81 static struct lamebus_softc *lamebus;
  82 
  83 void
  84 mainbus_bootstrap(void)
  85 {
  86         /* Interrupts should be off (and have been off since startup) */
  87         KASSERT(curthread->t_curspl > 0);
  88 
  89         /* Initialize the system LAMEbus data */
  90         lamebus = lamebus_init();
  91 
  92         /* Probe CPUs (should these be done as device attachments instead?) */
  93         lamebus_find_cpus(lamebus);
  94 
  95         /*
  96          * Print the device name for the main bus.
  97          */
  98         kprintf("lamebus0 (system main bus)\n");
  99 
 100         /*
 101          * Now we can take interrupts without croaking, so turn them on.
 102          * Some device probes might require being able to get interrupts.
 103          */
 104 
 105         spl0();
 106 
 107         /*
 108          * Now probe all the devices attached to the bus.
 109          * (This amounts to all devices.)
 110          */
 111         autoconf_lamebus(lamebus, 0);
 112 
 113         /*
 114          * Configure the MIPS on-chip timer to interrupt HZ times a second.
 115          */
 116         mips_timer_set(CPU_FREQUENCY / HZ);
 117 }
 118 
 119 /*
 120  * Start all secondary CPUs.
 121  */
 122 void
 123 mainbus_start_cpus(void)
 124 {
 125         lamebus_start_cpus(lamebus);
 126 }
 127 
 128 /*
 129  * Function to generate the memory address (in the uncached segment)
 130  * for the specified offset into the specified slot's region of the
 131  * LAMEbus.
 132  */
 133 void *
 134 lamebus_map_area(struct lamebus_softc *bus, int slot, uint32_t offset)
 135 {
 136         uint32_t address;
 137 
 138         (void)bus;   // not needed
 139 
 140         KASSERT(slot >= 0 && slot < LB_NSLOTS);
 141 
 142         address = LB_BASEADDR + slot*LB_SLOT_SIZE + offset;
 143         return (void *)address;
 144 }
 145 
 146 /*
 147  * Read a 32-bit register from a LAMEbus device.
 148  */
 149 uint32_t
 150 lamebus_read_register(struct lamebus_softc *bus, int slot, uint32_t offset)
 151 {
 152         uint32_t *ptr = lamebus_map_area(bus, slot, offset);
 153 
 154         return *ptr;
 155 }
 156 
 157 /*
 158  * Write a 32-bit register of a LAMEbus device.
 159  */
 160 void
 161 lamebus_write_register(struct lamebus_softc *bus, int slot,
 162                        uint32_t offset, uint32_t val)
 163 {
 164         uint32_t *ptr = lamebus_map_area(bus, slot, offset);
 165 
 166         *ptr = val;
 167 }
 168 
 169 
 170 /*
 171  * Power off the system.
 172  */
 173 void
 174 mainbus_poweroff(void)
 175 {
 176         /*
 177          *
 178          * Note that lamebus_write_register() doesn't actually access
 179          * the bus argument, so this will still work if we get here
 180          * before the bus is initialized.
 181          */
 182         lamebus_poweroff(lamebus);
 183 }
 184 
 185 /*
 186  * Reboot the system.
 187  */
 188 void
 189 mainbus_reboot(void)
 190 {
 191         /*
 192          * The MIPS doesn't appear to have any on-chip reset.
 193          * LAMEbus doesn't have a reset control, so we just
 194          * power off instead of rebooting. This would not be
 195          * so great in a real system, but it's fine for what
 196          * we're doing.
 197          */
 198         kprintf("Cannot reboot - powering off instead, sorry.\n");
 199         mainbus_poweroff();
 200 }
 201 
 202 /*
 203  * Halt the system.
 204  * On some systems, this would return to the boot monitor. But we don't
 205  * have one.
 206  */
 207 void
 208 mainbus_halt(void)
 209 {
 210         cpu_halt();
 211 }
 212 
 213 /*
 214  * Called to reset the system from panic().
 215  *
 216  * By the time we get here, the system may well be sufficiently hosed
 217  * as to panic recursively if we do much of anything. So just power off.
 218  * (We'd reboot, but System/161 doesn't do that.)
 219  */
 220 void
 221 mainbus_panic(void)
 222 {
 223         mainbus_poweroff();
 224 }
 225 
 226 /*
 227  * Function to get the size of installed physical RAM from the LAMEbus
 228  * controller.
 229  */
 230 uint32_t
 231 mainbus_ramsize(void)
 232 {
 233         return lamebus_ramsize();
 234 }
 235 
 236 /*
 237  * Send IPI.
 238  */
 239 void
 240 mainbus_send_ipi(struct cpu *target)
 241 {
 242         lamebus_assert_ipi(lamebus, target);
 243 }
 244 
 245 /*
 246  * Interrupt dispatcher.
 247  */
 248 
 249 /* Wiring of LAMEbus interrupts to bits in the cause register */
 250 #define LAMEBUS_IRQ_BIT  0x00000400     /* all system bus slots */
 251 #define LAMEBUS_IPI_BIT  0x00000800     /* inter-processor interrupt */
 252 #define MIPS_TIMER_BIT   0x00008000     /* on-chip timer */
 253 
 254 void
 255 mainbus_interrupt(struct trapframe *tf)
 256 {
 257         uint32_t cause;
 258 
 259         /* interrupts should be off */
 260         KASSERT(curthread->t_curspl > 0);
 261 
 262         cause = tf->tf_cause;
 263         if (cause & LAMEBUS_IRQ_BIT) {
 264                 lamebus_interrupt(lamebus);
 265         }
 266         else if (cause & LAMEBUS_IPI_BIT) {
 267                 interprocessor_interrupt();
 268                 lamebus_clear_ipi(lamebus, curcpu);
 269         }
 270         else if (cause & MIPS_TIMER_BIT) {
 271                 /* Reset the timer (this clears the interrupt) */
 272                 mips_timer_set(CPU_FREQUENCY / HZ);
 273                 /* and call hardclock */
 274                 hardclock();
 275         }
 276         else {
 277                 panic("Unknown interrupt; cause register is %08x\n", cause);
 278         }
 279 }

/* [<][>][^][v][top][bottom][index][help] */