summaryrefslogtreecommitdiff
path: root/linux/dev/init
diff options
context:
space:
mode:
Diffstat (limited to 'linux/dev/init')
-rw-r--r--linux/dev/init/main.c391
-rw-r--r--linux/dev/init/version.c32
2 files changed, 423 insertions, 0 deletions
diff --git a/linux/dev/init/main.c b/linux/dev/init/main.c
new file mode 100644
index 0000000..0c14353
--- /dev/null
+++ b/linux/dev/init/main.c
@@ -0,0 +1,391 @@
+/*
+ * Linux initialization.
+ *
+ * Copyright (C) 1996 The University of Utah and the Computer Systems
+ * Laboratory at the University of Utah (CSL)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Shantanu Goel, University of Utah CSL
+ */
+
+/*
+ * linux/init/main.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <sys/types.h>
+
+#include <mach/vm_param.h>
+#include <mach/vm_prot.h>
+#include <mach/machine.h>
+
+#include <vm/vm_page.h>
+#include <kern/kalloc.h>
+
+#include <machine/spl.h>
+#include <machine/pmap.h>
+#include <machine/vm_param.h>
+
+#define MACH_INCLUDE
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <device-drivers.h>
+
+/*
+ * Timing loop count.
+ */
+unsigned long loops_per_sec = 1;
+
+/*
+ * End of physical memory.
+ */
+unsigned long high_memory;
+
+/*
+ * Flag to indicate auto-configuration is in progress.
+ */
+int linux_auto_config = 1;
+
+/*
+ * Hard drive parameters obtained from the BIOS.
+ */
+struct drive_info_struct
+{
+ char dummy[32];
+} drive_info;
+
+/*
+ * Forward declarations.
+ */
+static void calibrate_delay (void);
+
+extern int hz;
+extern vm_offset_t phys_last_addr;
+
+extern void *alloc_contig_mem (unsigned, unsigned, unsigned, vm_page_t *);
+extern void free_contig_mem (vm_page_t);
+extern void init_IRQ (void);
+extern void restore_IRQ (void);
+extern void startrtclock (void);
+extern void linux_version_init (void);
+extern void linux_kmem_init (void);
+extern unsigned long pci_init (unsigned long, unsigned long);
+extern void linux_net_emulation_init (void);
+extern void device_setup (void);
+extern void linux_printk (char *,...);
+extern int linux_timer_intr (void);
+extern spl_t spl0 (void);
+extern spl_t splhigh (void);
+extern void form_pic_mask (void);
+extern int linux_bad_intr (int);
+extern int prtnull ();
+extern int intnull ();
+extern void linux_sched_init (void);
+
+
+/*
+ * Amount of contiguous memory to allocate for initialization.
+ */
+#define CONTIG_ALLOC (512 * 1024)
+
+/*
+ * Initialize Linux drivers.
+ */
+void
+linux_init (void)
+{
+ int addr;
+ unsigned memory_start, memory_end;
+ vm_page_t pages;
+
+ /*
+ * Initialize memory size.
+ */
+ high_memory = phys_last_addr;
+ init_IRQ ();
+ linux_sched_init ();
+
+ /*
+ * Set loop count.
+ */
+ calibrate_delay ();
+
+ /*
+ * Initialize drive info.
+ */
+ addr = *((unsigned *) phystokv (0x104));
+ memcpy (&drive_info,
+ (void *) ((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
+ addr = *((unsigned *) phystokv (0x118));
+ memcpy ((char *) &drive_info + 16,
+ (void *) ((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
+
+ /*
+ * Initialize Linux memory allocator.
+ */
+ linux_kmem_init ();
+
+ /*
+ * Allocate contiguous memory below 16 MB.
+ */
+ memory_start = (unsigned long) alloc_contig_mem (CONTIG_ALLOC,
+ 16 * 1024 * 1024,
+ 0, &pages);
+ if (memory_start == 0)
+ panic ("linux_init: alloc_contig_mem failed");
+ memory_end = memory_start + CONTIG_ALLOC;
+
+ /*
+ * Initialize PCI bus.
+ */
+ memory_start = pci_init (memory_start, memory_end);
+
+ if (memory_start > memory_end)
+ panic ("linux_init: ran out memory");
+
+ /*
+ * Free unused memory.
+ */
+ while (pages && pages->phys_addr < round_page (memory_start))
+ pages = (vm_page_t) pages->pageq.next;
+ if (pages)
+ free_contig_mem (pages);
+
+ /*
+ * Initialize devices.
+ */
+#ifdef CONFIG_INET
+ linux_net_emulation_init ();
+#endif
+ cli ();
+ device_setup ();
+
+ restore_IRQ ();
+ linux_auto_config = 0;
+}
+
+#ifndef NBPW
+#define NBPW 32
+#endif
+
+/*
+ * Allocate contiguous memory with the given constraints.
+ * This routine is horribly inefficient but it is presently
+ * only used during initialization so it's not that bad.
+ */
+void *
+alloc_contig_mem (unsigned size, unsigned limit,
+ unsigned mask, vm_page_t * pages)
+{
+ int i, j, bits_len;
+ unsigned *bits, len;
+ void *m;
+ vm_page_t p, page_list, tail, prev;
+ vm_offset_t addr, max_addr;
+
+ if (size == 0)
+ return (NULL);
+ size = round_page (size);
+ if ((size >> PAGE_SHIFT) > vm_page_free_count)
+ return (NULL);
+
+ /* Allocate bit array. */
+ max_addr = phys_last_addr;
+ if (max_addr > limit)
+ max_addr = limit;
+ bits_len = ((((max_addr >> PAGE_SHIFT) + NBPW - 1) / NBPW)
+ * sizeof (unsigned));
+ bits = (unsigned *) kalloc (bits_len);
+ if (!bits)
+ return (NULL);
+ memset (bits, 0, bits_len);
+
+ /*
+ * Walk the page free list and set a bit for every usable page.
+ */
+ simple_lock (&vm_page_queue_free_lock);
+ p = vm_page_queue_free;
+ while (p)
+ {
+ if (p->phys_addr < limit)
+ (bits[(p->phys_addr >> PAGE_SHIFT) / NBPW]
+ |= 1 << ((p->phys_addr >> PAGE_SHIFT) % NBPW));
+ p = (vm_page_t) p->pageq.next;
+ }
+
+ /*
+ * Scan bit array for contiguous pages.
+ */
+ len = 0;
+ m = NULL;
+ for (i = 0; len < size && i < bits_len / sizeof (unsigned); i++)
+ for (j = 0; len < size && j < NBPW; j++)
+ if (!(bits[i] & (1 << j)))
+ {
+ len = 0;
+ m = NULL;
+ }
+ else
+ {
+ if (len == 0)
+ {
+ addr = ((vm_offset_t) (i * NBPW + j)
+ << PAGE_SHIFT);
+ if ((addr & mask) == 0)
+ {
+ len += PAGE_SIZE;
+ m = (void *) addr;
+ }
+ }
+ else
+ len += PAGE_SIZE;
+ }
+
+ if (len != size)
+ {
+ simple_unlock (&vm_page_queue_free_lock);
+ kfree ((vm_offset_t) bits, bits_len);
+ return (NULL);
+ }
+
+ /*
+ * Remove pages from free list
+ * and construct list to return to caller.
+ */
+ page_list = NULL;
+ for (len = 0; len < size; len += PAGE_SIZE, addr += PAGE_SIZE)
+ {
+ prev = NULL;
+ for (p = vm_page_queue_free; p; p = (vm_page_t) p->pageq.next)
+ {
+ if (p->phys_addr == addr)
+ break;
+ prev = p;
+ }
+ if (!p)
+ panic ("alloc_contig_mem: page not on free list");
+ if (prev)
+ prev->pageq.next = p->pageq.next;
+ else
+ vm_page_queue_free = (vm_page_t) p->pageq.next;
+ p->free = FALSE;
+ p->pageq.next = NULL;
+ if (!page_list)
+ page_list = tail = p;
+ else
+ {
+ tail->pageq.next = (queue_entry_t) p;
+ tail = p;
+ }
+ vm_page_free_count--;
+ }
+
+ simple_unlock (&vm_page_queue_free_lock);
+ kfree ((vm_offset_t) bits, bits_len);
+ if (pages)
+ *pages = page_list;
+ return (m);
+}
+
+/*
+ * Free memory allocated by alloc_contig_mem.
+ */
+void
+free_contig_mem (vm_page_t pages)
+{
+ int i;
+ vm_page_t p;
+
+ for (p = pages, i = 0; p->pageq.next; p = (vm_page_t) p->pageq.next, i++)
+ p->free = TRUE;
+ p->free = TRUE;
+ simple_lock (&vm_page_queue_free_lock);
+ vm_page_free_count += i + 1;
+ p->pageq.next = (queue_entry_t) vm_page_queue_free;
+ vm_page_queue_free = pages;
+ simple_unlock (&vm_page_queue_free_lock);
+}
+
+/* This is the number of bits of precision for the loops_per_second. Each
+ * bit takes on average 1.5/HZ seconds. This (like the original) is a little
+ * better than 1%
+ */
+#define LPS_PREC 8
+
+static void
+calibrate_delay (void)
+{
+ int ticks;
+ int loopbit;
+ int lps_precision = LPS_PREC;
+
+ loops_per_sec = (1 << 12);
+
+#ifndef MACH
+ printk ("Calibrating delay loop.. ");
+#endif
+ while (loops_per_sec <<= 1)
+ {
+ /* wait for "start of" clock tick */
+ ticks = jiffies;
+ while (ticks == jiffies)
+ /* nothing */ ;
+ /* Go .. */
+ ticks = jiffies;
+ __delay (loops_per_sec);
+ ticks = jiffies - ticks;
+ if (ticks)
+ break;
+ }
+
+ /* Do a binary approximation to get loops_per_second set to equal one clock
+ * (up to lps_precision bits)
+ */
+ loops_per_sec >>= 1;
+ loopbit = loops_per_sec;
+ while (lps_precision-- && (loopbit >>= 1))
+ {
+ loops_per_sec |= loopbit;
+ ticks = jiffies;
+ while (ticks == jiffies);
+ ticks = jiffies;
+ __delay (loops_per_sec);
+ if (jiffies != ticks) /* longer than 1 tick */
+ loops_per_sec &= ~loopbit;
+ }
+
+ /* finally, adjust loops per second in terms of seconds instead of clocks */
+ loops_per_sec *= HZ;
+ /* Round the value and print it */
+#ifndef MACH
+ printk ("ok - %lu.%02lu BogoMIPS\n",
+ (loops_per_sec + 2500) / 500000,
+ ((loops_per_sec + 2500) / 5000) % 100);
+#endif
+
+#if defined(__SMP__) && defined(__i386__)
+ smp_loops_per_tick = loops_per_sec / 400;
+#endif
+}
diff --git a/linux/dev/init/version.c b/linux/dev/init/version.c
new file mode 100644
index 0000000..1989483
--- /dev/null
+++ b/linux/dev/init/version.c
@@ -0,0 +1,32 @@
+/*
+ * linux/version.c
+ *
+ * Copyright (C) 1992 Theodore Ts'o
+ *
+ * May be freely distributed as part of Linux.
+ */
+
+#define MACH_INCLUDE
+#include <linux/config.h>
+#include <linux/utsname.h>
+#include <linux/version.h>
+#include <linux/compile.h>
+
+/* make the "checkconfig" script happy: we really need to include config.h */
+#ifdef CONFIG_BOGUS
+#endif
+
+#define version(a) Version_ ## a
+#define version_string(a) version(a)
+
+int version_string (LINUX_VERSION_CODE) = 0;
+
+struct new_utsname system_utsname =
+{
+ UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION,
+ UTS_MACHINE, UTS_DOMAINNAME
+};
+
+const char *linux_banner =
+"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";