Annotation of Gnu-Mach/i386/i386at/gpl/linux/linux_init.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: 
        !            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.