Annotation of Gnu-Mach/linux/dev/init/main.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Linux initialization.
        !             3:  *
        !             4:  * Copyright (C) 1996 The University of Utah and the Computer Systems
        !             5:  * Laboratory at the University of Utah (CSL)
        !             6:  *
        !             7:  * This program is free software; you can redistribute it and/or modify
        !             8:  * it under the terms of the GNU General Public License as published by
        !             9:  * the Free Software Foundation; either version 2, or (at your option)
        !            10:  * any later version.
        !            11:  *
        !            12:  * This program is distributed in the hope that it will be useful,
        !            13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15:  * GNU General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU General Public License
        !            18:  * along with this program; if not, write to the Free Software
        !            19:  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
        !            20:  *
        !            21:  *      Author: Shantanu Goel, University of Utah CSL
        !            22:  */
        !            23: 
        !            24: /*
        !            25:  *  linux/init/main.c
        !            26:  *
        !            27:  *  Copyright (C) 1991, 1992  Linus Torvalds
        !            28:  */
        !            29: 
        !            30: #include <sys/types.h>
        !            31: 
        !            32: #include <mach/vm_param.h>
        !            33: #include <mach/vm_prot.h>
        !            34: #include <mach/machine.h>
        !            35: 
        !            36: #include <vm/vm_page.h>
        !            37: #include <kern/kalloc.h>
        !            38: 
        !            39: #include <machine/spl.h>
        !            40: #include <machine/pmap.h>
        !            41: #include <machine/vm_param.h>
        !            42: 
        !            43: #define MACH_INCLUDE
        !            44: #include <linux/sched.h>
        !            45: #include <linux/mm.h>
        !            46: #include <linux/interrupt.h>
        !            47: #include <linux/delay.h>
        !            48: #include <linux/ioport.h>
        !            49: #include <linux/string.h>
        !            50: 
        !            51: #include <asm/system.h>
        !            52: #include <asm/io.h>
        !            53: 
        !            54: #include <device-drivers.h>
        !            55: 
        !            56: /*
        !            57:  * Timing loop count.
        !            58:  */
        !            59: unsigned long loops_per_sec = 1;
        !            60: 
        !            61: /*
        !            62:  * End of physical memory.
        !            63:  */
        !            64: unsigned long high_memory;
        !            65: 
        !            66: /*
        !            67:  * Flag to indicate auto-configuration is in progress.
        !            68:  */
        !            69: int linux_auto_config = 1;
        !            70: 
        !            71: /*
        !            72:  * Hard drive parameters obtained from the BIOS.
        !            73:  */
        !            74: struct drive_info_struct
        !            75: {
        !            76:   char dummy[32];
        !            77: } drive_info;
        !            78: 
        !            79: /*
        !            80:  * Forward declarations.
        !            81:  */
        !            82: static void calibrate_delay (void);
        !            83: 
        !            84: extern int hz;
        !            85: extern vm_offset_t phys_last_addr;
        !            86: 
        !            87: extern void *alloc_contig_mem (unsigned, unsigned, unsigned, vm_page_t *);
        !            88: extern void free_contig_mem (vm_page_t);
        !            89: extern void init_IRQ (void);
        !            90: extern void restore_IRQ (void);
        !            91: extern void startrtclock (void);
        !            92: extern void linux_version_init (void);
        !            93: extern void linux_kmem_init (void);
        !            94: extern unsigned long pci_init (unsigned long, unsigned long);
        !            95: extern void linux_net_emulation_init (void);
        !            96: extern void device_setup (void);
        !            97: extern void linux_printk (char *,...);
        !            98: extern int linux_timer_intr (void);
        !            99: extern spl_t spl0 (void);
        !           100: extern spl_t splhigh (void);
        !           101: extern void form_pic_mask (void);
        !           102: extern int linux_bad_intr (int);
        !           103: extern int prtnull ();
        !           104: extern int intnull ();
        !           105: extern void linux_sched_init (void);
        !           106: 
        !           107: 
        !           108: /*
        !           109:  * Amount of contiguous memory to allocate for initialization.
        !           110:  */
        !           111: #define CONTIG_ALLOC (512 * 1024)
        !           112: 
        !           113: /*
        !           114:  * Initialize Linux drivers.
        !           115:  */
        !           116: void
        !           117: linux_init (void)
        !           118: {
        !           119:   int addr;
        !           120:   unsigned memory_start, memory_end;
        !           121:   vm_page_t pages;
        !           122: 
        !           123:   /*
        !           124:    * Initialize memory size.
        !           125:    */
        !           126:   high_memory = phys_last_addr;
        !           127:   init_IRQ ();
        !           128:   linux_sched_init ();
        !           129: 
        !           130:   /*
        !           131:    * Set loop count.
        !           132:    */
        !           133:   calibrate_delay ();
        !           134: 
        !           135:   /*
        !           136:    * Initialize drive info.
        !           137:    */
        !           138:   addr = *((unsigned *) phystokv (0x104));
        !           139:   memcpy (&drive_info,
        !           140:          (void *) ((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
        !           141:   addr = *((unsigned *) phystokv (0x118));
        !           142:   memcpy ((char *) &drive_info + 16,
        !           143:          (void *) ((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
        !           144: 
        !           145:   /*
        !           146:    * Initialize Linux memory allocator.
        !           147:    */
        !           148:   linux_kmem_init ();
        !           149: 
        !           150:   /*
        !           151:    * Allocate contiguous memory below 16 MB.
        !           152:    */
        !           153:   memory_start = (unsigned long) alloc_contig_mem (CONTIG_ALLOC,
        !           154:                                                   16 * 1024 * 1024,
        !           155:                                                   0, &pages);
        !           156:   if (memory_start == 0)
        !           157:     panic ("linux_init: alloc_contig_mem failed");
        !           158:   memory_end = memory_start + CONTIG_ALLOC;
        !           159: 
        !           160:   /*
        !           161:    * Initialize PCI bus.
        !           162:    */
        !           163:   memory_start = pci_init (memory_start, memory_end);
        !           164: 
        !           165:   if (memory_start > memory_end)
        !           166:     panic ("linux_init: ran out memory");
        !           167: 
        !           168:   /*
        !           169:    * Free unused memory.
        !           170:    */
        !           171:   while (pages && pages->phys_addr < round_page (memory_start))
        !           172:     pages = (vm_page_t) pages->pageq.next;
        !           173:   if (pages)
        !           174:     free_contig_mem (pages);
        !           175: 
        !           176:   /*
        !           177:    * Initialize devices.
        !           178:    */
        !           179: #ifdef CONFIG_INET
        !           180:   linux_net_emulation_init ();
        !           181: #endif
        !           182:   cli ();
        !           183:   device_setup ();
        !           184: 
        !           185:   restore_IRQ ();
        !           186:   linux_auto_config = 0;
        !           187: }
        !           188: 
        !           189: #ifndef NBPW
        !           190: #define NBPW 32
        !           191: #endif
        !           192: 
        !           193: /*
        !           194:  * Allocate contiguous memory with the given constraints.
        !           195:  * This routine is horribly inefficient but it is presently
        !           196:  * only used during initialization so it's not that bad.
        !           197:  */
        !           198: void *
        !           199: alloc_contig_mem (unsigned size, unsigned limit,
        !           200:                  unsigned mask, vm_page_t * pages)
        !           201: {
        !           202:   int i, j, bits_len;
        !           203:   unsigned *bits, len;
        !           204:   void *m;
        !           205:   vm_page_t p, page_list, tail, prev;
        !           206:   vm_offset_t addr, max_addr;
        !           207: 
        !           208:   if (size == 0)
        !           209:     return (NULL);
        !           210:   size = round_page (size);
        !           211:   if ((size >> PAGE_SHIFT) > vm_page_free_count)
        !           212:     return (NULL);
        !           213: 
        !           214:   /* Allocate bit array.  */
        !           215:   max_addr = phys_last_addr;
        !           216:   if (max_addr > limit)
        !           217:     max_addr = limit;
        !           218:   bits_len = ((((max_addr >> PAGE_SHIFT) + NBPW - 1) / NBPW)
        !           219:              * sizeof (unsigned));
        !           220:   bits = (unsigned *) kalloc (bits_len);
        !           221:   if (!bits)
        !           222:     return (NULL);
        !           223:   memset (bits, 0, bits_len);
        !           224: 
        !           225:   /*
        !           226:    * Walk the page free list and set a bit for every usable page.
        !           227:    */
        !           228:   simple_lock (&vm_page_queue_free_lock);
        !           229:   p = vm_page_queue_free;
        !           230:   while (p)
        !           231:     {
        !           232:       if (p->phys_addr < limit)
        !           233:        (bits[(p->phys_addr >> PAGE_SHIFT) / NBPW]
        !           234:         |= 1 << ((p->phys_addr >> PAGE_SHIFT) % NBPW));
        !           235:       p = (vm_page_t) p->pageq.next;
        !           236:     }
        !           237: 
        !           238:   /*
        !           239:    * Scan bit array for contiguous pages.
        !           240:    */
        !           241:   len = 0;
        !           242:   m = NULL;
        !           243:   for (i = 0; len < size && i < bits_len / sizeof (unsigned); i++)
        !           244:     for (j = 0; len < size && j < NBPW; j++)
        !           245:       if (!(bits[i] & (1 << j)))
        !           246:        {
        !           247:          len = 0;
        !           248:          m = NULL;
        !           249:        }
        !           250:       else
        !           251:        {
        !           252:          if (len == 0)
        !           253:            {
        !           254:              addr = ((vm_offset_t) (i * NBPW + j)
        !           255:                      << PAGE_SHIFT);
        !           256:              if ((addr & mask) == 0)
        !           257:                {
        !           258:                  len += PAGE_SIZE;
        !           259:                  m = (void *) addr;
        !           260:                }
        !           261:            }
        !           262:          else
        !           263:            len += PAGE_SIZE;
        !           264:        }
        !           265: 
        !           266:   if (len != size)
        !           267:     {
        !           268:       simple_unlock (&vm_page_queue_free_lock);
        !           269:       kfree ((vm_offset_t) bits, bits_len);
        !           270:       return (NULL);
        !           271:     }
        !           272: 
        !           273:   /*
        !           274:    * Remove pages from free list
        !           275:    * and construct list to return to caller.
        !           276:    */
        !           277:   page_list = NULL;
        !           278:   for (len = 0; len < size; len += PAGE_SIZE, addr += PAGE_SIZE)
        !           279:     {
        !           280:       prev = NULL;
        !           281:       for (p = vm_page_queue_free; p; p = (vm_page_t) p->pageq.next)
        !           282:        {
        !           283:          if (p->phys_addr == addr)
        !           284:            break;
        !           285:          prev = p;
        !           286:        }
        !           287:       if (!p)
        !           288:        panic ("alloc_contig_mem: page not on free list");
        !           289:       if (prev)
        !           290:        prev->pageq.next = p->pageq.next;
        !           291:       else
        !           292:        vm_page_queue_free = (vm_page_t) p->pageq.next;
        !           293:       p->free = FALSE;
        !           294:       p->pageq.next = NULL;
        !           295:       if (!page_list)
        !           296:        page_list = tail = p;
        !           297:       else
        !           298:        {
        !           299:          tail->pageq.next = (queue_entry_t) p;
        !           300:          tail = p;
        !           301:        }
        !           302:       vm_page_free_count--;
        !           303:     }
        !           304: 
        !           305:   simple_unlock (&vm_page_queue_free_lock);
        !           306:   kfree ((vm_offset_t) bits, bits_len);
        !           307:   if (pages)
        !           308:     *pages = page_list;
        !           309:   return (m);
        !           310: }
        !           311: 
        !           312: /*
        !           313:  * Free memory allocated by alloc_contig_mem.
        !           314:  */
        !           315: void
        !           316: free_contig_mem (vm_page_t pages)
        !           317: {
        !           318:   int i;
        !           319:   vm_page_t p;
        !           320: 
        !           321:   for (p = pages, i = 0; p->pageq.next; p = (vm_page_t) p->pageq.next, i++)
        !           322:     p->free = TRUE;
        !           323:   p->free = TRUE;
        !           324:   simple_lock (&vm_page_queue_free_lock);
        !           325:   vm_page_free_count += i + 1;
        !           326:   p->pageq.next = (queue_entry_t) vm_page_queue_free;
        !           327:   vm_page_queue_free = pages;
        !           328:   simple_unlock (&vm_page_queue_free_lock);
        !           329: }
        !           330: 
        !           331: /* This is the number of bits of precision for the loops_per_second.  Each
        !           332:  * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
        !           333:  * better than 1%
        !           334:  */
        !           335: #define LPS_PREC 8
        !           336: 
        !           337: static void
        !           338: calibrate_delay (void)
        !           339: {
        !           340:   int ticks;
        !           341:   int loopbit;
        !           342:   int lps_precision = LPS_PREC;
        !           343: 
        !           344:   loops_per_sec = (1 << 12);
        !           345: 
        !           346: #ifndef MACH
        !           347:   printk ("Calibrating delay loop.. ");
        !           348: #endif
        !           349:   while (loops_per_sec <<= 1)
        !           350:     {
        !           351:       /* wait for "start of" clock tick */
        !           352:       ticks = jiffies;
        !           353:       while (ticks == jiffies)
        !           354:        /* nothing */ ;
        !           355:       /* Go .. */
        !           356:       ticks = jiffies;
        !           357:       __delay (loops_per_sec);
        !           358:       ticks = jiffies - ticks;
        !           359:       if (ticks)
        !           360:        break;
        !           361:     }
        !           362: 
        !           363:   /* Do a binary approximation to get loops_per_second set to equal one clock
        !           364:    * (up to lps_precision bits)
        !           365:    */
        !           366:   loops_per_sec >>= 1;
        !           367:   loopbit = loops_per_sec;
        !           368:   while (lps_precision-- && (loopbit >>= 1))
        !           369:     {
        !           370:       loops_per_sec |= loopbit;
        !           371:       ticks = jiffies;
        !           372:       while (ticks == jiffies);
        !           373:       ticks = jiffies;
        !           374:       __delay (loops_per_sec);
        !           375:       if (jiffies != ticks)    /* longer than 1 tick */
        !           376:        loops_per_sec &= ~loopbit;
        !           377:     }
        !           378: 
        !           379:   /* finally, adjust loops per second in terms of seconds instead of clocks */
        !           380:   loops_per_sec *= HZ;
        !           381:   /* Round the value and print it */
        !           382: #ifndef MACH
        !           383:   printk ("ok - %lu.%02lu BogoMIPS\n",
        !           384:          (loops_per_sec + 2500) / 500000,
        !           385:          ((loops_per_sec + 2500) / 5000) % 100);
        !           386: #endif
        !           387: 
        !           388: #if defined(__SMP__) && defined(__i386__)
        !           389:   smp_loops_per_tick = loops_per_sec / 400;
        !           390: #endif
        !           391: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.