Annotation of Gnu-Mach/linux/dev/init/main.c, revision 1.1.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.