Annotation of Gnu-Mach/i386/i386at/gpl/linux/linux_init.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: 
                     38: #include <i386/ipl.h>
                     39: #include <i386/pic.h>
                     40: #include <i386/pit.h>
                     41: #include <i386/machspl.h>
                     42: #include <i386/pmap.h>
                     43: #include <i386/vm_param.h>
                     44: 
                     45: #include <i386at/gpl/linux/linux_emul.h>
                     46: 
                     47: #define MACH_INCLUDE
                     48: #include <linux/sched.h>
                     49: #include <linux/mm.h>
                     50: #include <linux/interrupt.h>
                     51: #include <linux/delay.h>
                     52: #include <linux/ioport.h>
                     53: #include <linux/string.h>
                     54: 
                     55: #include <asm/system.h>
                     56: 
                     57: #include <i386/device-drivers.h>
                     58: 
                     59: /*
                     60:  * Set if the machine has an EISA bus.
                     61:  */
                     62: int EISA_bus = 0;
                     63: 
                     64: /*
                     65:  * Timing loop count.
                     66:  */
                     67: unsigned long loops_per_sec = 1;
                     68: 
                     69: /*
                     70:  * End of physical memory.
                     71:  */
                     72: unsigned long high_memory;
                     73: 
                     74: /*
                     75:  * Flag to indicate auto-configuration is in progress.
                     76:  */
                     77: int linux_auto_config = 1;
                     78: 
                     79: /*
                     80:  * Hard drive parameters obtained from the BIOS.
                     81:  */
                     82: struct drive_info_struct {
                     83:        char dummy[32];
                     84: } drive_info;
                     85: 
                     86: /*
                     87:  * Forward declarations.
                     88:  */
                     89: static void calibrate_delay(void);
                     90: 
                     91: extern int hz;
                     92: extern vm_offset_t phys_last_addr;
                     93: 
                     94: extern void timer_bh(void *);
                     95: extern void tqueue_bh(void *);
                     96: extern void startrtclock(void);
                     97: extern void linux_version_init(void);
                     98: extern void linux_kmem_init(void);
                     99: extern unsigned long pci_init(unsigned long, unsigned long);
                    100: extern void linux_net_emulation_init (void);
                    101: extern void device_setup(void);
                    102: extern void linux_printk(char *, ...);
                    103: extern int linux_timer_intr();
                    104: 
                    105: /*
                    106:  * Amount of contiguous memory to allocate for initialization.
                    107:  */
                    108: #define CONTIG_ALLOC (512 * 1024)
                    109: 
                    110: /*
                    111:  * Initialize Linux drivers.
                    112:  */
                    113: void
                    114: linux_init()
                    115: {
                    116:        char *p;
                    117:        int i, addr;
                    118:        int (*old_clock_handler)(), old_clock_pri;
                    119:        unsigned memory_start, memory_end;
                    120:        vm_page_t pages;
                    121: 
                    122:        /*
                    123:         * Initialize memory size.
                    124:         */
                    125:        high_memory = phys_last_addr;
                    126: 
                    127:        /*
                    128:         * Ensure interrupts are disabled.
                    129:         */
                    130:        (void) splhigh();
                    131: 
                    132:        /*
                    133:         * Program counter 0 of 8253 to interrupt hz times per second.
                    134:         */
                    135:        outb(PITCTL_PORT, PIT_C0|PIT_SQUAREMODE|PIT_READMODE);
                    136:        outb(PITCTR0_PORT, CLKNUM / hz);
                    137:        outb(PITCTR0_PORT, (CLKNUM / hz) >> 8);
                    138: 
                    139:        /*
                    140:         * Install our clock interrupt handler.
                    141:         */
                    142:        old_clock_handler = ivect[0];
                    143:        old_clock_pri = intpri[0];
                    144:        ivect[0] = linux_timer_intr;
                    145:        intpri[0] = SPLHI;
                    146:        form_pic_mask();
                    147: 
                    148:        /*
                    149:         * Enable interrupts.
                    150:         */
                    151:        (void) spl0();
                    152: 
                    153:        /*
                    154:         * Set Linux version.
                    155:         */
                    156:        linux_version_init();
                    157: 
                    158:        /*
                    159:         * Check if the machine has an EISA bus.
                    160:         */
                    161:        p = (char *)0x0FFFD9;
                    162:        if (*p++ == 'E' && *p++ == 'I' && *p++ == 'S' && *p == 'A')
                    163:                EISA_bus = 1;
                    164: 
                    165:        /*
                    166:         * Permanently allocate standard device ports.
                    167:         */
                    168:        request_region(0x00, 0x20, "dma1");
                    169:        request_region(0x40, 0x20, "timer");
                    170:        request_region(0x70, 0x10, "rtc");
                    171:        request_region(0x80, 0x20, "dma page reg");
                    172:        request_region(0xc0, 0x20, "dma2");
                    173:        request_region(0xf0, 0x02, "fpu");
                    174:        request_region(0xf8, 0x08, "fpu");
                    175: 
                    176:        /*
                    177:         * Install software interrupt handlers.
                    178:         */
                    179:        bh_base[TIMER_BH].routine = timer_bh;
                    180:        bh_base[TIMER_BH].data = 0;
                    181:        enable_bh(TIMER_BH);
                    182:        bh_base[TQUEUE_BH].routine = tqueue_bh;
                    183:        bh_base[TQUEUE_BH].data = 0;
                    184:        enable_bh(TQUEUE_BH);
                    185: 
                    186:        /*
                    187:         * Set loop count.
                    188:         */
                    189:        calibrate_delay();
                    190: 
                    191:        /*
                    192:         * Initialize drive info.
                    193:         */
                    194:        addr = *((unsigned *)phystokv(0x104));
                    195:        memcpy (&drive_info,
                    196:                (void *)((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
                    197:        addr = *((unsigned *)phystokv(0x118));
                    198:        memcpy ((char *)&drive_info + 16,
                    199:                (void *)((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
                    200: 
                    201:        /*
                    202:         * Initialize Linux memory allocator.
                    203:         */
                    204:        linux_kmem_init();
                    205: 
                    206:        /*
                    207:         * Allocate contiguous memory below 16 MB.
                    208:         */
                    209:        memory_start = (unsigned long)alloc_contig_mem(CONTIG_ALLOC,
                    210:                                                       16 * 1024 * 1024,
                    211:                                                       0, &pages);
                    212:        if (memory_start == 0)
                    213:                panic("linux_init: alloc_contig_mem failed");
                    214:        memory_end = memory_start + CONTIG_ALLOC;
                    215: 
                    216:        /*
                    217:         * Initialize PCI bus.
                    218:         */
                    219:        memory_start = pci_init(memory_start, memory_end);
                    220: 
                    221:        if (memory_start > memory_end)
                    222:                panic("linux_init: ran out memory");
                    223: 
                    224:        /*
                    225:         * Free unused memory.
                    226:         */
                    227:        while (pages && pages->phys_addr < round_page(memory_start))
                    228:                pages = (vm_page_t)pages->pageq.next;
                    229:        if (pages)
                    230:                free_contig_mem(pages);
                    231: 
                    232:        /*
                    233:         * Initialize devices.
                    234:         */
                    235: #ifdef CONFIG_INET
                    236:        linux_net_emulation_init();
                    237: #endif
                    238:        cli();
                    239:        device_setup();
                    240: 
                    241:        /*
                    242:         * Disable interrupts.
                    243:         */
                    244:        (void) splhigh();
                    245: 
                    246:        /*
                    247:         * Restore clock interrupt handler.
                    248:         */
                    249:        ivect[0] = old_clock_handler;
                    250:        intpri[0] = old_clock_pri;
                    251:        form_pic_mask();
                    252: 
                    253:        linux_auto_config = 0;
                    254: }
                    255: 
                    256: #ifndef NBPW
                    257: #define NBPW 32
                    258: #endif
                    259: 
                    260: /*
                    261:  * Allocate contiguous memory with the given constraints.
                    262:  * This routine is horribly inefficient but it is presently
                    263:  * only used during initialization so it's not that bad.
                    264:  */
                    265: void *
                    266: alloc_contig_mem(unsigned size, unsigned limit,
                    267:                 unsigned mask, vm_page_t *pages)
                    268: {
                    269:        int i, j, bits_len;
                    270:        unsigned *bits, len;
                    271:        void *m;
                    272:        vm_page_t p, page_list, tail, prev;
                    273:        vm_offset_t addr, max_addr;
                    274: 
                    275:        if (size == 0)
                    276:                return (NULL);
                    277:        size = round_page(size);
                    278:        if ((size >> PAGE_SHIFT) > vm_page_free_count)
                    279:                return (NULL);
                    280: 
                    281:        /* Allocate bit array.  */
                    282:        max_addr = phys_last_addr;
                    283:        if (max_addr > limit)
                    284:                max_addr = limit;
                    285:        bits_len = ((((max_addr >> PAGE_SHIFT) + NBPW - 1) / NBPW)
                    286:                    * sizeof(unsigned));
                    287:        bits = (unsigned *)kalloc(bits_len);
                    288:        if (!bits)
                    289:                return (NULL);
                    290:        memset (bits, 0, bits_len);
                    291: 
                    292:        /*
                    293:         * Walk the page free list and set a bit for every usable page.
                    294:         */
                    295:        simple_lock(&vm_page_queue_free_lock);
                    296:        p = vm_page_queue_free;
                    297:        while (p) {
                    298:                if (p->phys_addr < limit)
                    299:                        (bits[(p->phys_addr >> PAGE_SHIFT) / NBPW]
                    300:                         |= 1 << ((p->phys_addr >> PAGE_SHIFT) % NBPW));
                    301:                p = (vm_page_t)p->pageq.next;
                    302:        }
                    303: 
                    304:        /*
                    305:         * Scan bit array for contiguous pages.
                    306:         */
                    307:        len = 0;
                    308:        m = NULL;
                    309:        for (i = 0; len < size && i < bits_len / sizeof (unsigned); i++)
                    310:                for (j = 0; len < size && j < NBPW; j++)
                    311:                        if (!(bits[i] & (1 << j))) {
                    312:                                len = 0;
                    313:                                m = NULL;
                    314:                        } else {
                    315:                                if (len == 0) {
                    316:                                        addr = ((vm_offset_t)(i * NBPW + j)
                    317:                                                << PAGE_SHIFT);
                    318:                                        if ((addr & mask) == 0) {
                    319:                                                len += PAGE_SIZE;
                    320:                                                m = (void *) addr;
                    321:                                        }
                    322:                                } else
                    323:                                        len += PAGE_SIZE;
                    324:                        }
                    325: 
                    326:        if (len != size) {
                    327:                simple_unlock(&vm_page_queue_free_lock);
                    328:                kfree ((vm_offset_t)bits, bits_len);
                    329:                return (NULL);
                    330:        }
                    331: 
                    332:        /*
                    333:         * Remove pages from free list
                    334:         * and construct list to return to caller.
                    335:         */
                    336:        page_list = NULL;
                    337:        for (len = 0; len < size; len += PAGE_SIZE, addr += PAGE_SIZE) {
                    338:                prev = NULL;
                    339:                for (p = vm_page_queue_free; p; p = (vm_page_t)p->pageq.next) {
                    340:                        if (p->phys_addr == addr)
                    341:                                break;
                    342:                        prev = p;
                    343:                }
                    344:                if (!p)
                    345:                        panic("alloc_contig_mem: page not on free list");
                    346:                if (prev)
                    347:                        prev->pageq.next = p->pageq.next;
                    348:                else
                    349:                        vm_page_queue_free = (vm_page_t)p->pageq.next;
                    350:                p->free = FALSE;
                    351:                p->pageq.next = NULL;
                    352:                if (!page_list)
                    353:                        page_list = tail = p;
                    354:                else {
                    355:                        tail->pageq.next = (queue_entry_t)p;
                    356:                        tail = p;
                    357:                }
                    358:                vm_page_free_count--;
                    359:        }
                    360: 
                    361:        simple_unlock(&vm_page_queue_free_lock);
                    362:        kfree((vm_offset_t)bits, bits_len);
                    363:        if (pages)
                    364:                *pages = page_list;
                    365:        return (m);
                    366: }
                    367: 
                    368: /*
                    369:  * Free memory allocated by alloc_contig_mem.
                    370:  */
                    371: void
                    372: free_contig_mem(vm_page_t pages)
                    373: {
                    374:   int i;
                    375:   vm_page_t p;
                    376: 
                    377:   for (p = pages, i = 0; p->pageq.next; p = (vm_page_t)p->pageq.next, i++)
                    378:     p->free = TRUE;
                    379:   p->free = TRUE;
                    380:   simple_lock(&vm_page_queue_free_lock);
                    381:   vm_page_free_count += i + 1;
                    382:   p->pageq.next = (queue_entry_t)vm_page_queue_free;
                    383:   vm_page_queue_free = pages;
                    384:   simple_unlock(&vm_page_queue_free_lock);
                    385: }
                    386: 
                    387: /*
                    388:  * Calibrate delay loop.
                    389:  * Lifted straight from Linux.
                    390:  */
                    391: static void
                    392: calibrate_delay()
                    393: {
                    394:        int ticks;
                    395: 
                    396:        /*      printk("Calibrating delay loop.. "); */
                    397:        while (loops_per_sec <<= 1) {
                    398:                /* Wait for "start of" clock tick.  */
                    399:                ticks = jiffies;
                    400:                while (ticks == jiffies)
                    401:                        /* nothing */;
                    402:                /* Go .. */
                    403:                ticks = jiffies;
                    404:                __delay(loops_per_sec);
                    405:                ticks = jiffies - ticks;
                    406:                if (ticks >= hz) {
                    407:                        loops_per_sec = muldiv(loops_per_sec,
                    408:                                                     hz, ticks);
                    409:                        /*printk("ok - %lu.%02lu BogoMips\n",
                    410:                               loops_per_sec / 500000,
                    411:                               (loops_per_sec / 5000) % 100);*/
                    412:                        return;
                    413:                }
                    414:        }
                    415: /*     printk("failed\n");*/
                    416: }

unix.superglobalmegacorp.com

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