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

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>
1.1.1.2 ! root       42: #include <machine/model_dep.h>
1.1       root       43: 
                     44: #define MACH_INCLUDE
                     45: #include <linux/sched.h>
                     46: #include <linux/mm.h>
                     47: #include <linux/interrupt.h>
                     48: #include <linux/delay.h>
                     49: #include <linux/ioport.h>
                     50: #include <linux/string.h>
1.1.1.2 ! root       51: #include <linux/pci.h>
        !            52: #include <linux/dev/glue/glue.h>
1.1       root       53: 
                     54: #include <asm/system.h>
                     55: #include <asm/io.h>
                     56: 
                     57: /*
                     58:  * Timing loop count.
                     59:  */
                     60: unsigned long loops_per_sec = 1;
                     61: 
1.1.1.2 ! root       62: #if defined(__SMP__) && defined(__i386__)
        !            63: unsigned long smp_loops_per_tick = 1000000;
        !            64: #endif
        !            65: 
1.1       root       66: /*
                     67:  * End of physical memory.
                     68:  */
                     69: unsigned long high_memory;
                     70: 
                     71: /*
                     72:  * Flag to indicate auto-configuration is in progress.
                     73:  */
                     74: int linux_auto_config = 1;
                     75: 
                     76: /*
                     77:  * Hard drive parameters obtained from the BIOS.
                     78:  */
                     79: struct drive_info_struct
                     80: {
                     81:   char dummy[32];
                     82: } drive_info;
                     83: 
                     84: /*
                     85:  * Forward declarations.
                     86:  */
                     87: static void calibrate_delay (void);
                     88: 
                     89: /*
                     90:  * Amount of contiguous memory to allocate for initialization.
                     91:  */
                     92: #define CONTIG_ALLOC (512 * 1024)
                     93: 
                     94: /*
                     95:  * Initialize Linux drivers.
                     96:  */
                     97: void
                     98: linux_init (void)
                     99: {
                    100:   int addr;
                    101:   unsigned memory_start, memory_end;
                    102:   vm_page_t pages;
                    103: 
                    104:   /*
                    105:    * Initialize memory size.
                    106:    */
                    107:   high_memory = phys_last_addr;
                    108:   init_IRQ ();
                    109:   linux_sched_init ();
                    110: 
                    111:   /*
                    112:    * Set loop count.
                    113:    */
                    114:   calibrate_delay ();
                    115: 
                    116:   /*
                    117:    * Initialize drive info.
                    118:    */
                    119:   addr = *((unsigned *) phystokv (0x104));
                    120:   memcpy (&drive_info,
                    121:          (void *) ((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
                    122:   addr = *((unsigned *) phystokv (0x118));
                    123:   memcpy ((char *) &drive_info + 16,
                    124:          (void *) ((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
                    125: 
                    126:   /*
                    127:    * Initialize Linux memory allocator.
                    128:    */
                    129:   linux_kmem_init ();
                    130: 
                    131:   /*
                    132:    * Allocate contiguous memory below 16 MB.
                    133:    */
                    134:   memory_start = (unsigned long) alloc_contig_mem (CONTIG_ALLOC,
                    135:                                                   16 * 1024 * 1024,
                    136:                                                   0, &pages);
                    137:   if (memory_start == 0)
                    138:     panic ("linux_init: alloc_contig_mem failed");
                    139:   memory_end = memory_start + CONTIG_ALLOC;
                    140: 
                    141:   /*
                    142:    * Initialize PCI bus.
                    143:    */
                    144:   memory_start = pci_init (memory_start, memory_end);
                    145: 
                    146:   if (memory_start > memory_end)
                    147:     panic ("linux_init: ran out memory");
                    148: 
                    149:   /*
                    150:    * Free unused memory.
                    151:    */
1.1.1.2 ! root      152:   while (pages && phystokv(pages->phys_addr) < round_page (memory_start))
1.1       root      153:     pages = (vm_page_t) pages->pageq.next;
                    154:   if (pages)
                    155:     free_contig_mem (pages);
                    156: 
                    157:   /*
                    158:    * Initialize devices.
                    159:    */
                    160: #ifdef CONFIG_INET
                    161:   linux_net_emulation_init ();
                    162: #endif
1.1.1.2 ! root      163: 
1.1       root      164:   cli ();
                    165:   device_setup ();
                    166: 
1.1.1.2 ! root      167: #ifdef CONFIG_PCMCIA
        !           168:   /* 
        !           169:    * Initialize pcmcia.
        !           170:    */
        !           171:   pcmcia_init ();
        !           172: #endif
        !           173: 
1.1       root      174:   restore_IRQ ();
1.1.1.2 ! root      175: 
1.1       root      176:   linux_auto_config = 0;
                    177: }
                    178: 
                    179: #ifndef NBPW
                    180: #define NBPW 32
                    181: #endif
                    182: 
                    183: /*
                    184:  * Allocate contiguous memory with the given constraints.
                    185:  * This routine is horribly inefficient but it is presently
                    186:  * only used during initialization so it's not that bad.
                    187:  */
                    188: void *
                    189: alloc_contig_mem (unsigned size, unsigned limit,
                    190:                  unsigned mask, vm_page_t * pages)
                    191: {
                    192:   int i, j, bits_len;
                    193:   unsigned *bits, len;
                    194:   void *m;
                    195:   vm_page_t p, page_list, tail, prev;
                    196:   vm_offset_t addr, max_addr;
                    197: 
                    198:   if (size == 0)
                    199:     return (NULL);
                    200:   size = round_page (size);
                    201:   if ((size >> PAGE_SHIFT) > vm_page_free_count)
                    202:     return (NULL);
                    203: 
                    204:   /* Allocate bit array.  */
                    205:   max_addr = phys_last_addr;
                    206:   if (max_addr > limit)
                    207:     max_addr = limit;
                    208:   bits_len = ((((max_addr >> PAGE_SHIFT) + NBPW - 1) / NBPW)
                    209:              * sizeof (unsigned));
                    210:   bits = (unsigned *) kalloc (bits_len);
                    211:   if (!bits)
                    212:     return (NULL);
                    213:   memset (bits, 0, bits_len);
                    214: 
                    215:   /*
                    216:    * Walk the page free list and set a bit for every usable page.
                    217:    */
                    218:   simple_lock (&vm_page_queue_free_lock);
                    219:   p = vm_page_queue_free;
                    220:   while (p)
                    221:     {
                    222:       if (p->phys_addr < limit)
                    223:        (bits[(p->phys_addr >> PAGE_SHIFT) / NBPW]
                    224:         |= 1 << ((p->phys_addr >> PAGE_SHIFT) % NBPW));
                    225:       p = (vm_page_t) p->pageq.next;
                    226:     }
                    227: 
                    228:   /*
                    229:    * Scan bit array for contiguous pages.
                    230:    */
                    231:   len = 0;
                    232:   m = NULL;
                    233:   for (i = 0; len < size && i < bits_len / sizeof (unsigned); i++)
                    234:     for (j = 0; len < size && j < NBPW; j++)
                    235:       if (!(bits[i] & (1 << j)))
                    236:        {
                    237:          len = 0;
                    238:          m = NULL;
                    239:        }
                    240:       else
                    241:        {
                    242:          if (len == 0)
                    243:            {
                    244:              addr = ((vm_offset_t) (i * NBPW + j)
                    245:                      << PAGE_SHIFT);
                    246:              if ((addr & mask) == 0)
                    247:                {
                    248:                  len += PAGE_SIZE;
                    249:                  m = (void *) addr;
                    250:                }
                    251:            }
                    252:          else
                    253:            len += PAGE_SIZE;
                    254:        }
                    255: 
                    256:   if (len != size)
                    257:     {
                    258:       simple_unlock (&vm_page_queue_free_lock);
                    259:       kfree ((vm_offset_t) bits, bits_len);
                    260:       return (NULL);
                    261:     }
                    262: 
                    263:   /*
                    264:    * Remove pages from free list
                    265:    * and construct list to return to caller.
                    266:    */
                    267:   page_list = NULL;
                    268:   for (len = 0; len < size; len += PAGE_SIZE, addr += PAGE_SIZE)
                    269:     {
                    270:       prev = NULL;
                    271:       for (p = vm_page_queue_free; p; p = (vm_page_t) p->pageq.next)
                    272:        {
                    273:          if (p->phys_addr == addr)
                    274:            break;
                    275:          prev = p;
                    276:        }
                    277:       if (!p)
                    278:        panic ("alloc_contig_mem: page not on free list");
                    279:       if (prev)
                    280:        prev->pageq.next = p->pageq.next;
                    281:       else
                    282:        vm_page_queue_free = (vm_page_t) p->pageq.next;
                    283:       p->free = FALSE;
                    284:       p->pageq.next = NULL;
                    285:       if (!page_list)
                    286:        page_list = tail = p;
                    287:       else
                    288:        {
                    289:          tail->pageq.next = (queue_entry_t) p;
                    290:          tail = p;
                    291:        }
                    292:       vm_page_free_count--;
                    293:     }
                    294: 
                    295:   simple_unlock (&vm_page_queue_free_lock);
                    296:   kfree ((vm_offset_t) bits, bits_len);
                    297:   if (pages)
                    298:     *pages = page_list;
1.1.1.2 ! root      299:   return phystokv(m);
1.1       root      300: }
                    301: 
                    302: /*
                    303:  * Free memory allocated by alloc_contig_mem.
                    304:  */
                    305: void
                    306: free_contig_mem (vm_page_t pages)
                    307: {
                    308:   int i;
                    309:   vm_page_t p;
                    310: 
                    311:   for (p = pages, i = 0; p->pageq.next; p = (vm_page_t) p->pageq.next, i++)
                    312:     p->free = TRUE;
                    313:   p->free = TRUE;
                    314:   simple_lock (&vm_page_queue_free_lock);
                    315:   vm_page_free_count += i + 1;
                    316:   p->pageq.next = (queue_entry_t) vm_page_queue_free;
                    317:   vm_page_queue_free = pages;
                    318:   simple_unlock (&vm_page_queue_free_lock);
                    319: }
                    320: 
                    321: /* This is the number of bits of precision for the loops_per_second.  Each
                    322:  * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
                    323:  * better than 1%
                    324:  */
                    325: #define LPS_PREC 8
                    326: 
                    327: static void
                    328: calibrate_delay (void)
                    329: {
                    330:   int ticks;
                    331:   int loopbit;
                    332:   int lps_precision = LPS_PREC;
                    333: 
                    334:   loops_per_sec = (1 << 12);
                    335: 
                    336: #ifndef MACH
                    337:   printk ("Calibrating delay loop.. ");
                    338: #endif
                    339:   while (loops_per_sec <<= 1)
                    340:     {
                    341:       /* wait for "start of" clock tick */
                    342:       ticks = jiffies;
                    343:       while (ticks == jiffies)
                    344:        /* nothing */ ;
                    345:       /* Go .. */
                    346:       ticks = jiffies;
                    347:       __delay (loops_per_sec);
                    348:       ticks = jiffies - ticks;
                    349:       if (ticks)
                    350:        break;
                    351:     }
                    352: 
                    353:   /* Do a binary approximation to get loops_per_second set to equal one clock
                    354:    * (up to lps_precision bits)
                    355:    */
                    356:   loops_per_sec >>= 1;
                    357:   loopbit = loops_per_sec;
                    358:   while (lps_precision-- && (loopbit >>= 1))
                    359:     {
                    360:       loops_per_sec |= loopbit;
                    361:       ticks = jiffies;
                    362:       while (ticks == jiffies);
                    363:       ticks = jiffies;
                    364:       __delay (loops_per_sec);
                    365:       if (jiffies != ticks)    /* longer than 1 tick */
                    366:        loops_per_sec &= ~loopbit;
                    367:     }
                    368: 
                    369:   /* finally, adjust loops per second in terms of seconds instead of clocks */
                    370:   loops_per_sec *= HZ;
                    371:   /* Round the value and print it */
                    372: #ifndef MACH
                    373:   printk ("ok - %lu.%02lu BogoMIPS\n",
                    374:          (loops_per_sec + 2500) / 500000,
                    375:          ((loops_per_sec + 2500) / 5000) % 100);
                    376: #endif
                    377: 
                    378: #if defined(__SMP__) && defined(__i386__)
                    379:   smp_loops_per_tick = loops_per_sec / 400;
                    380: #endif
                    381: }

unix.superglobalmegacorp.com

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