Annotation of Gnu-Mach/i386/pc/i16/i16_raw.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Copyright (c) 1995-1994 The University of Utah and
        !             3:  * the Computer Systems Laboratory at the University of Utah (CSL).
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Permission to use, copy, modify and distribute this software is hereby
        !             7:  * granted provided that (1) source code retains these copyright, permission,
        !             8:  * and disclaimer notices, and (2) redistributions including binaries
        !             9:  * reproduce the notices in supporting documentation, and (3) all advertising
        !            10:  * materials mentioning features or use of this software display the following
        !            11:  * acknowledgement: ``This product includes software developed by the
        !            12:  * Computer Systems Laboratory at the University of Utah.''
        !            13:  *
        !            14:  * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
        !            15:  * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
        !            16:  * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            17:  *
        !            18:  * CSL requests users of this software to return to [email protected] any
        !            19:  * improvements that they make and grant CSL redistribution rights.
        !            20:  *
        !            21:  *      Author: Bryan Ford, University of Utah CSL
        !            22:  */
        !            23: /*
        !            24:        This file rovides a default implementation
        !            25:        of real/pmode switching code.
        !            26:        Assumes that, as far as it's concerned,
        !            27:        low linear address always map to physical addresses.
        !            28:        (The low linear mappings can be changed,
        !            29:        but must be changed back before switching back to real mode.)
        !            30: 
        !            31:        Provides:
        !            32:                i16_raw_switch_to_pmode()
        !            33:                i16_raw_switch_to_real_mode()
        !            34: 
        !            35:                i16_raw_start()
        !            36:                        Called in real mode.
        !            37:                        Initializes the pmode switching system,
        !            38:                        switches to pmode for the first time,
        !            39:                        and calls the 32-bit function raw_start().
        !            40: 
        !            41:        Depends on:
        !            42: 
        !            43:                paging.h:
        !            44:                        raw_paging_enable()
        !            45:                        raw_paging_disable()
        !            46:                        raw_paging_init()
        !            47: 
        !            48:                a20.h:
        !            49:                        i16_enable_a20()
        !            50:                        i16_disable_a20()
        !            51: 
        !            52:                real.h:
        !            53:                        real_cs
        !            54: */
        !            55: 
        !            56: #include <mach/boolean.h>
        !            57: #include <mach/machine/code16.h>
        !            58: #include <mach/machine/vm_param.h>
        !            59: #include <mach/machine/proc_reg.h>
        !            60: #include <mach/machine/pio.h>
        !            61: #include <mach/machine/seg.h>
        !            62: #include <mach/machine/eflags.h>
        !            63: #include <mach/machine/pmode.h>
        !            64: 
        !            65: #include "config.h"
        !            66: #include "cpu.h"
        !            67: #include "i16.h"
        !            68: #include "vm_param.h"
        !            69: #include "pic.h"
        !            70: #include "debug.h"
        !            71: #include "i16_a20.h"
        !            72: #include "i16_switch.h"
        !            73: 
        !            74: int irq_master_base, irq_slave_base;
        !            75: 
        !            76: /* Set to true when everything is initialized properly.  */
        !            77: static boolean_t inited;
        !            78: 
        !            79: /* Saved value of eflags register for real mode.  */
        !            80: static unsigned real_eflags;
        !            81: 
        !            82: 
        !            83: 
        !            84: #ifdef ENABLE_PAGING
        !            85: #define RAW_PAGING_ENABLE() raw_paging_enable()
        !            86: #define RAW_PAGING_DISABLE() raw_paging_disable()
        !            87: #define RAW_PAGING_INIT() raw_paging_init()
        !            88: #else
        !            89: #define RAW_PAGING_ENABLE() ((void)0)
        !            90: #define RAW_PAGING_DISABLE() ((void)0)
        !            91: #define RAW_PAGING_INIT() ((void)0)
        !            92: #endif
        !            93: 
        !            94: 
        !            95: CODE16
        !            96: 
        !            97: void i16_raw_switch_to_pmode()
        !            98: {
        !            99:        /* No interrupts from now on please.  */
        !           100:        i16_cli();
        !           101: 
        !           102:        /* Save the eflags register for switching back later.  */
        !           103:        real_eflags = get_eflags();
        !           104: 
        !           105:        /* Enable the A20 address line.  */
        !           106:        i16_enable_a20();
        !           107: 
        !           108:        /* Load the GDT.
        !           109:           Note that we have to do this each time we enter pmode,
        !           110:           not just the first,
        !           111:           because other real-mode programs may have switched to pmode
        !           112:           and back again in the meantime, trashing the GDT pointer.  */
        !           113:        {
        !           114:                struct pseudo_descriptor pdesc;
        !           115: 
        !           116:                pdesc.limit = sizeof(cpu[0].tables.gdt)-1;
        !           117:                pdesc.linear_base = boot_image_pa
        !           118:                                    + (vm_offset_t)&cpu[0].tables.gdt;
        !           119:                i16_set_gdt(&pdesc);
        !           120:        }
        !           121: 
        !           122:        /* Switch into protected mode.  */
        !           123:        i16_enter_pmode(KERNEL_16_CS);
        !           124: 
        !           125:        /* Reload all the segment registers from the new GDT.  */
        !           126:        set_ds(KERNEL_DS);
        !           127:        set_es(KERNEL_DS);
        !           128:        set_fs(0);
        !           129:        set_gs(0);
        !           130:        set_ss(KERNEL_DS);
        !           131: 
        !           132:        i16_do_32bit(
        !           133: 
        !           134:                if (inited)
        !           135:                {
        !           136:                        /* Turn paging on if necessary.  */
        !           137:                        RAW_PAGING_ENABLE();
        !           138: 
        !           139:                        /* Load the CPU tables into the processor.  */
        !           140:                        cpu_tables_load(&cpu[0]);
        !           141: 
        !           142:                        /* Program the PIC so the interrupt vectors won't
        !           143:                           conflict with the processor exception vectors.  */
        !           144:                        pic_init(PICM_VECTBASE, PICS_VECTBASE);
        !           145:                }
        !           146: 
        !           147:                /* Make sure our flags register is appropriate.  */
        !           148:                set_eflags((get_eflags()
        !           149:                           & ~(EFL_IF | EFL_DF | EFL_NT))
        !           150:                           | EFL_IOPL_USER);
        !           151:        );
        !           152: }
        !           153: 
        !           154: void i16_raw_switch_to_real_mode()
        !           155: {
        !           156:        /* Make sure interrupts are disabled.  */
        !           157:        cli();
        !           158: 
        !           159:        /* Avoid sending DOS bogus coprocessor exceptions.
        !           160:           XXX should we save/restore all of CR0?  */
        !           161:        i16_clts();
        !           162: 
        !           163:        i16_do_32bit(
        !           164:                /* Turn paging off if necessary.  */
        !           165:                RAW_PAGING_DISABLE();
        !           166: 
        !           167:                /* Reprogram the PIC back to the settings DOS expects.  */
        !           168:                pic_init(0x08, 0x70);
        !           169:        );
        !           170: 
        !           171:        /* Make sure all the segment registers are 16-bit.
        !           172:           The code segment definitely is already,
        !           173:           because we're running 16-bit code.  */
        !           174:        set_ds(KERNEL_16_DS);
        !           175:        set_es(KERNEL_16_DS);
        !           176:        set_fs(KERNEL_16_DS);
        !           177:        set_gs(KERNEL_16_DS);
        !           178:        set_ss(KERNEL_16_DS);
        !           179: 
        !           180:        /* Switch back to real mode.  */
        !           181:        i16_leave_pmode(real_cs);
        !           182: 
        !           183:        /* Load the real-mode segment registers.  */
        !           184:        set_ds(real_cs);
        !           185:        set_es(real_cs);
        !           186:        set_fs(real_cs);
        !           187:        set_gs(real_cs);
        !           188:        set_ss(real_cs);
        !           189: 
        !           190:        /* Load the real-mode IDT.  */
        !           191:        {
        !           192:                struct pseudo_descriptor pdesc;
        !           193: 
        !           194:                pdesc.limit = 0xffff;
        !           195:                pdesc.linear_base = 0;
        !           196:                i16_set_idt(&pdesc);
        !           197:        }
        !           198: 
        !           199:        /* Disable the A20 address line.  */
        !           200:        i16_disable_a20();
        !           201: 
        !           202:        /* Restore the eflags register to its original real-mode state.
        !           203:           Note that this will leave interrupts disabled
        !           204:           since it was saved after the cli() above.  */
        !           205:        set_eflags(real_eflags);
        !           206: }
        !           207: 
        !           208: void i16_raw_start()
        !           209: {
        !           210:        /* Make sure we're not already in protected mode.  */
        !           211:        if (i16_get_msw() & CR0_PE)
        !           212:                i16_die("The processor is in an unknown "
        !           213:                        "protected mode environment.");
        !           214: 
        !           215:        do_debug(i16_puts("Real mode detected"));
        !           216: 
        !           217:        /* Minimally initialize the GDT.  */
        !           218:        i16_gdt_init_temp();
        !           219: 
        !           220:        /* Switch to protected mode for the first time.
        !           221:           This won't load all the processor tables and everything yet,
        !           222:           since they're not fully initialized.  */
        !           223:        i16_raw_switch_to_pmode();
        !           224: 
        !           225:        /* We can now hop in and out of 32-bit mode at will.  */
        !           226:        i16_do_32bit(
        !           227: 
        !           228:                /* Now that we can access all physical memory,
        !           229:                   collect the memory regions we discovered while in 16-bit mode
        !           230:                   and add them to our free memory list.
        !           231:                   We can't do this before now because the free list nodes
        !           232:                   are stored in the free memory itself,
        !           233:                   which is probably out of reach of our 16-bit segments.  */
        !           234:                phys_mem_collect();
        !           235: 
        !           236:                /* Initialize paging if necessary.
        !           237:                   Do it before initializing the other processor tables
        !           238:                   because they might have to be located
        !           239:                   somewhere in high linear memory.  */
        !           240:                RAW_PAGING_INIT();
        !           241: 
        !           242:                /* Initialize the processor tables.  */
        !           243:                cpu_init(&cpu[0]);
        !           244: 
        !           245:                /* Initialize the hardware interrupt vectors in the IDT.  */
        !           246:                irq_master_base = PICM_VECTBASE;
        !           247:                irq_slave_base = PICS_VECTBASE;
        !           248:                idt_irq_init();
        !           249: 
        !           250:                inited = TRUE;
        !           251: 
        !           252:                /* Switch to real mode and back again once more,
        !           253:                   to make sure everything's loaded properly.  */
        !           254:                do_16bit(
        !           255:                        i16_raw_switch_to_real_mode();
        !           256:                        i16_raw_switch_to_pmode();
        !           257:                );
        !           258: 
        !           259:                raw_start();
        !           260:        );
        !           261: }
        !           262: 
        !           263: void (*i16_switch_to_real_mode)() = i16_raw_switch_to_real_mode;
        !           264: void (*i16_switch_to_pmode)() = i16_raw_switch_to_pmode;
        !           265: 

unix.superglobalmegacorp.com

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