Annotation of Gnu-Mach/i386/pc/i16/i16_raw.c, revision 1.1.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.