⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
字号:
/* * 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. */voidlinux_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. */voidfree_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 8static voidcalibrate_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}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -