Annotation of Gnu-Mach/i386/dos/i16/i16_vcpi.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: #include <mach/boolean.h>
        !            25: #include <mach/vm_param.h>
        !            26: #include <mach/machine/code16.h>
        !            27: #include <mach/machine/vm_types.h>
        !            28: #include <mach/machine/paging.h>
        !            29: #include <mach/machine/eflags.h>
        !            30: #include <mach/machine/proc_reg.h>
        !            31: #include <mach/machine/far_ptr.h>
        !            32: #include <mach/machine/vcpi.h>
        !            33: #include <mach/machine/asm.h>
        !            34: 
        !            35: #include "config.h"
        !            36: #include "i16.h"
        !            37: #include "i16_dos.h"
        !            38: #include "cpu.h"
        !            39: #include "real.h"
        !            40: #include "debug.h"
        !            41: #include "vm_param.h"
        !            42: 
        !            43: #ifdef ENABLE_VCPI
        !            44: 
        !            45: static boolean_t ems_page_allocated;
        !            46: static unsigned short ems_handle;
        !            47: 
        !            48: static vm_offset_t vcpi_pdir, vcpi_ptable0;
        !            49: 
        !            50: struct far_pointer_32 vcpi_pmode_entry = {0, VCPI_CS};
        !            51: struct vcpi_switch_data vcpi_switch_data;
        !            52: 
        !            53: static struct pseudo_descriptor gdt_pdesc, idt_pdesc;
        !            54: 
        !            55: static boolean_t pic_reprogrammed;
        !            56: 
        !            57: /* Save area for the DOS interrupt vectors
        !            58:    that used to be in the place we relocated the master PIC to.  */
        !            59: static struct far_pointer_16 master_save_vecs[8];
        !            60: 
        !            61: 
        !            62: #ifdef ENABLE_PAGING
        !            63: #define VCPI_PAGING_INIT(pdir_pa, first_unmapped_pa) vcpi_paging_init(pdir_pa, first_unmapped_pa)
        !            64: #else
        !            65: #define VCPI_PAGING_INIT(pdir_pa, first_unmapped_pa) ((void)0)
        !            66: #endif
        !            67: 
        !            68: #ifdef ENABLE_KERNEL_LDT
        !            69: #define KERNEL_LDT_INIT() (vcpi_switch_data.ldt_sel = KERNEL_LDT)
        !            70: #else
        !            71: #define KERNEL_LDT_INIT() ((void)0)
        !            72: #endif
        !            73: 
        !            74: 
        !            75: CODE16
        !            76: 
        !            77: static void i16_vcpi_switch_to_pmode()
        !            78: {
        !            79:        extern vm_offset_t boot_image_pa;
        !            80: 
        !            81:        i16_cli();
        !            82: 
        !            83:        i16_assert(i16_get_ds() == i16_get_cs());
        !            84:        i16_assert(i16_get_es() == i16_get_cs());
        !            85:        i16_assert(i16_get_ss() == i16_get_cs());
        !            86: 
        !            87:        /* Make sure the TSS isn't marked busy.  */
        !            88:        cpu[0].tables.gdt[KERNEL_TSS_IDX].access &= ~ACC_TSS_BUSY;
        !            89: 
        !            90:        /* Ask the VCPI server to switch to protected mode.  */
        !            91:        asm volatile("
        !            92:                movl    %%esp,%%edx
        !            93:                int     $0x67
        !            94:        "SEXT(pmode_return)":
        !            95:                movl    %%edx,%%esp
        !            96:                movw    %2,%%dx
        !            97:                movw    %%dx,%%ss
        !            98:                movw    %%dx,%%ds
        !            99:                movw    %%dx,%%es
        !           100:                xorw    %%dx,%%dx
        !           101:                movw    %%dx,%%fs
        !           102:                movw    %%dx,%%gs
        !           103:        " :
        !           104:          : "a" ((unsigned short)0xde0c),
        !           105:            "S" (boot_image_pa + (vm_offset_t)&vcpi_switch_data),
        !           106:            "i" (KERNEL_DS)
        !           107:          : "eax", "edx", "esi");
        !           108: 
        !           109:        /* Make sure the direction flag is still clear.  */
        !           110:        i16_cld();
        !           111: }
        !           112: 
        !           113: static void i16_vcpi_switch_to_real_mode()
        !           114: {
        !           115:        i16_cli();
        !           116: 
        !           117:        /* As requested by VCPI spec... */
        !           118:        i16_clts();
        !           119: 
        !           120:        /* Perform the switch.  */
        !           121:        asm volatile("
        !           122:                movl    %%esp,%%edx
        !           123:                pushl   %1
        !           124:                pushl   %1
        !           125:                pushl   %1
        !           126:                pushl   %1
        !           127:                pushl   %1
        !           128:                pushl   %%edx
        !           129:                pushl   $0
        !           130:                pushl   %1
        !           131:                pushl   $1f
        !           132:                movw    %2,%%ds
        !           133:                lcall   %%ss:"SEXT(vcpi_pmode_entry)"
        !           134:        1:
        !           135:        " :
        !           136:          : "a" ((unsigned short)0xde0c),
        !           137:            "r" ((unsigned)real_cs),
        !           138:            "r" ((unsigned short)LINEAR_DS)
        !           139:          : "eax", "edx");
        !           140: 
        !           141:        i16_assert(!(i16_get_eflags() & EFL_IF));
        !           142:        i16_assert(i16_get_ds() == i16_get_cs());
        !           143:        i16_assert(i16_get_es() == i16_get_cs());
        !           144:        i16_assert(i16_get_ss() == i16_get_cs());
        !           145: 
        !           146:        /* Make sure the direction flag is still clear.  */
        !           147:        i16_cld();
        !           148: }
        !           149: 
        !           150: CODE32
        !           151: 
        !           152: static void vcpi_real_int(int intnum, struct real_call_data *rcd)
        !           153: {
        !           154:        do_16bit(
        !           155:                unsigned int eflags;
        !           156: 
        !           157:                i16_vcpi_switch_to_real_mode();
        !           158:                i16_real_int(intnum, rcd);
        !           159:                i16_vcpi_switch_to_pmode();
        !           160:        );
        !           161: }
        !           162: 
        !           163: static void vcpi_exit(int rc)
        !           164: {
        !           165:        do_16bit(
        !           166:                i16_vcpi_switch_to_real_mode();
        !           167:                i16_exit(rc);
        !           168:                while (1);
        !           169:        );
        !           170: }
        !           171: 
        !           172: CODE16
        !           173: 
        !           174: static inline void
        !           175: i16_vcpi_set_int_vecs(unsigned short master, unsigned short slave)
        !           176: {
        !           177:        unsigned short rc;
        !           178: 
        !           179:        i16_assert(!(get_eflags() & EFL_IF));
        !           180:        asm volatile("int $0x67"
        !           181:                : "=a" (rc)
        !           182:                : "a" ((unsigned short)0xde0b),
        !           183:                  "b" ((unsigned short)master),
        !           184:                  "c" ((unsigned short)slave));
        !           185:        i16_assert((rc & 0xff00) == 0);
        !           186:        i16_assert(!(get_eflags() & EFL_IF));
        !           187: }
        !           188: 
        !           189: /* Find a (hopefully) empty set of interrupt vectors
        !           190:    to use for the master hardware interrupts.
        !           191:    We assume that eight interrupt vectors in a row
        !           192:    that all have the same value are unused.
        !           193:    If VCPI servers weren't so brain-damaged
        !           194:    and took care of this during interrupt reflection
        !           195:    (like we do when running in raw mode),
        !           196:    this kludgery wouldn't be needed...  */
        !           197: static int i16_find_free_vec_range()
        !           198: {
        !           199:        /* i will track the first vector in a range;
        !           200:           j will track the last.  */
        !           201:        int i, j;
        !           202:        struct far_pointer_16 iv, jv;
        !           203: 
        !           204:        j = 0xff;
        !           205:        i16_dos_get_int_vec(j, &jv);
        !           206: 
        !           207:        for (i = j-1; ; i--)
        !           208:        {
        !           209:                if (i == 0x50)
        !           210:                {
        !           211:                        /* No completely free sets found.
        !           212:                           Stop here and just use 0x50-0x57.  */
        !           213:                        break;
        !           214:                }
        !           215: 
        !           216:                i16_dos_get_int_vec(i, &iv);
        !           217:                if ((iv.ofs != jv.ofs) || (iv.seg != jv.seg))
        !           218:                {
        !           219:                        /* Vector contents changed.  */
        !           220:                        j = i;
        !           221:                        jv = iv;
        !           222:                        continue;
        !           223:                }
        !           224: 
        !           225:                if ((j-i+1 >= 8) && ((i & 7) == 0))
        !           226:                {
        !           227:                        /* Found a free range.  */
        !           228:                        break;
        !           229:                }
        !           230:        }
        !           231: 
        !           232:        return i;
        !           233: }
        !           234: 
        !           235: void i16_vcpi_check()
        !           236: {
        !           237:        extern vm_offset_t dos_mem_phys_free_mem;
        !           238:        extern vm_offset_t dos_mem_phys_free_size;
        !           239:        extern void pmode_return();
        !           240:        extern vm_offset_t boot_image_pa;
        !           241:        extern void (*i16_switch_to_real_mode)();
        !           242:        extern void (*i16_switch_to_pmode)();
        !           243: 
        !           244:        unsigned short rc;
        !           245:        unsigned short first_free_pte;
        !           246:        unsigned short vcpi_ver;
        !           247: 
        !           248:        i16_assert(boot_image_pa == kvtophys(0));
        !           249: 
        !           250:        /* Check for presence of EMM driver.  */
        !           251:        {
        !           252:                int dev_info, out_status;
        !           253:                int fh;
        !           254: 
        !           255:                fh = i16_dos_open("EMMXXXX0", 0);
        !           256:                if (fh < 0)
        !           257:                        return;
        !           258:                dev_info = i16_dos_get_device_info(fh);
        !           259:                out_status = i16_dos_get_output_status(fh);
        !           260:                i16_dos_close(fh);
        !           261:                if ((dev_info < 0) || !(dev_info & 0x80)
        !           262:                    || (out_status != 0xff))
        !           263:                        return;
        !           264:        }
        !           265: 
        !           266:        /* Allocate an EMS page to force the EMM to be turned on.
        !           267:           If it fails, keep going anyway -
        !           268:           it may simply mean all the EMS pages are allocated.  */
        !           269:        asm volatile("int $0x67"
        !           270:                        : "=a" (rc),
        !           271:                          "=d" (ems_handle)
        !           272:                        : "a" ((unsigned short)0x4300),
        !           273:                          "b" ((unsigned short)1));
        !           274:        if (!(rc & 0xff00))
        !           275:                ems_page_allocated = TRUE;
        !           276: 
        !           277:        /* Check for VCPI.  */
        !           278:        asm volatile("int $0x67" : "=a" (rc), "=b" (vcpi_ver) : "a" ((unsigned short)0xde00));
        !           279:        if (rc & 0xff00)
        !           280:                return;
        !           281:        i16_assert(vcpi_ver >= 0x0100);
        !           282: 
        !           283:        /* OK, it's there - we're now committed to using VCPI.  */
        !           284:        i16_switch_to_real_mode = i16_vcpi_switch_to_real_mode;
        !           285:        i16_switch_to_pmode = i16_vcpi_switch_to_pmode;
        !           286:        real_int = vcpi_real_int;
        !           287:        real_exit = vcpi_exit;
        !           288: 
        !           289:        do_debug(i16_puts("VCPI detected"));
        !           290: 
        !           291:        /* Allocate a page directory and page table from low DOS memory.  */
        !           292:        {
        !           293:                vm_offset_t new_dos_mem;
        !           294: 
        !           295:                new_dos_mem = ((dos_mem_phys_free_mem + PAGE_MASK) & ~PAGE_MASK)
        !           296:                                + PAGE_SIZE*2;
        !           297:                if ((!dos_mem_phys_free_mem)
        !           298:                    || (new_dos_mem - dos_mem_phys_free_mem
        !           299:                        > dos_mem_phys_free_size))
        !           300:                        i16_die("not enough low DOS memory available");
        !           301:                dos_mem_phys_free_size -= new_dos_mem - dos_mem_phys_free_mem;
        !           302:                dos_mem_phys_free_mem = new_dos_mem;
        !           303:                vcpi_pdir = new_dos_mem - PAGE_SIZE*2;
        !           304:                vcpi_ptable0 = vcpi_pdir + PAGE_SIZE;
        !           305:        }
        !           306: 
        !           307:        /* Initialize them.  */
        !           308:        {
        !           309:                int i;
        !           310:                pt_entry_t pde0 = vcpi_ptable0
        !           311:                        | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_USER;
        !           312: 
        !           313:                set_fs(vcpi_pdir >> 4);
        !           314:                asm volatile("movl %0,%%fs:(0)" : : "r" (pde0));
        !           315:                for (i = 1; i < NPDES + NPTES; i++)
        !           316:                        asm volatile("movl $0,%%fs:(,%0,4)" : : "r" (i));
        !           317:        }
        !           318: 
        !           319:        /* Initialize the protected-mode interface.  */
        !           320:        asm volatile("
        !           321:                pushw   %%es
        !           322:                movw    %4,%%es
        !           323:                int     $0x67
        !           324:                popw    %%es
        !           325:        "
        !           326:                : "=a" (rc),
        !           327:                  "=b" (vcpi_pmode_entry.ofs),
        !           328:                  "=D" (first_free_pte)
        !           329:                : "a" ((unsigned short)0xde01),
        !           330:                  "r" ((unsigned short)(vcpi_ptable0 >> 4)),
        !           331:                  "D" (0),
        !           332:                  "S" (&cpu[0].tables.gdt[VCPI_CS_IDX]));
        !           333:        i16_assert((rc & 0xff00) == 0);
        !           334:        i16_assert(get_ds() == get_cs());
        !           335:        i16_assert(get_es() == get_cs());
        !           336: 
        !           337: #ifdef DEBUG
        !           338:        /* Sanity check: make sure the server did what it was supposed to do.  */
        !           339: 
        !           340:        i16_assert((cpu[0].tables.gdt[VCPI_CS_IDX].access & ACC_P|ACC_CODE) == ACC_P|ACC_CODE);
        !           341:        if (cpu[0].tables.gdt[VCPI_CS_IDX].granularity & SZ_G)
        !           342:                i16_assert(vcpi_pmode_entry.ofs <
        !           343:                           (((vm_offset_t)cpu[0].tables.gdt[VCPI_CS_IDX].limit_high << 28)
        !           344:                            | ((vm_offset_t)cpu[0].tables.gdt[VCPI_CS_IDX].limit_low << 12)
        !           345:                            | (vm_offset_t)0xfff));
        !           346:        else
        !           347:                i16_assert(vcpi_pmode_entry.ofs <
        !           348:                           (((vm_offset_t)cpu[0].tables.gdt[VCPI_CS_IDX].limit_high << 16)
        !           349:                            | (vm_offset_t)cpu[0].tables.gdt[VCPI_CS_IDX].limit_low));
        !           350: 
        !           351:        i16_assert(first_free_pte/sizeof(pt_entry_t) >= 1*1024*1024/PAGE_SIZE);
        !           352:        i16_assert(first_free_pte/sizeof(pt_entry_t) <= 4*1024*1024/PAGE_SIZE);
        !           353: 
        !           354:        {
        !           355:                int i;
        !           356: 
        !           357:                for (i = 0; i < 1*1024*1024/PAGE_SIZE; i++)
        !           358:                {
        !           359:                        pt_entry_t entry;
        !           360: 
        !           361:                        set_ds(vcpi_ptable0 >> 4);
        !           362:                        entry = ((pt_entry_t*)0)[i];
        !           363:                        set_ds(get_cs());
        !           364:                        i16_assert(entry & INTEL_PTE_VALID);
        !           365:                        if (i < 0xf0000/PAGE_SIZE)
        !           366:                                i16_assert(entry & INTEL_PTE_WRITE);
        !           367:                        i16_assert(entry & INTEL_PTE_USER);
        !           368:                        i16_assert(!(entry & INTEL_PTE_AVAIL));
        !           369:                }
        !           370:        }
        !           371: #endif /* DEBUG */
        !           372: 
        !           373:        /* Find the VCPI server's hardware interrupt vector mappings.  */
        !           374:        asm volatile("int $0x67"
        !           375:                : "=a" (rc),
        !           376:                  "=b" (irq_master_base),
        !           377:                  "=c" (irq_slave_base)
        !           378:                : "a" ((unsigned short)0xde0a));
        !           379:        i16_assert((rc & 0xff00) == 0);
        !           380:        irq_master_base &= 0xffff;
        !           381:        irq_slave_base &= 0xffff;
        !           382:        i16_assert((irq_master_base & 7) == 0);
        !           383:        i16_assert((irq_master_base == 0x08) || (irq_master_base >= 0x20));
        !           384:        i16_assert((irq_slave_base & 7) == 0);
        !           385:        i16_assert(irq_slave_base >= 0x20);
        !           386: 
        !           387:        /* If they're the usual DOS values, change them.  */
        !           388:        if (irq_master_base == 0x08)
        !           389:        {
        !           390:                pic_reprogrammed = TRUE;
        !           391: 
        !           392:                i16_cli();
        !           393: 
        !           394:                irq_master_base = i16_find_free_vec_range();
        !           395: 
        !           396:                /* Save the old vectors in that range
        !           397:                   and set them to a copy of vectors 8-15.  */
        !           398:                {
        !           399:                        int i;
        !           400: 
        !           401:                        for (i = 0; i < 8; i++)
        !           402:                        {
        !           403:                                struct far_pointer_16 hw_vec;
        !           404: 
        !           405:                                i16_dos_get_int_vec(irq_master_base+i,
        !           406:                                                    &master_save_vecs[i]);
        !           407:                                i16_dos_get_int_vec(0x08+i, &hw_vec);
        !           408:                                i16_dos_set_int_vec(irq_master_base+i, &hw_vec);
        !           409:                        }
        !           410:                }
        !           411: 
        !           412:                /* Reprogram the PIC.  */
        !           413:                i16_pic_set_master(irq_master_base);
        !           414: 
        !           415:                /* Inform the VCPI server.  */
        !           416:                i16_vcpi_set_int_vecs(irq_master_base, irq_slave_base);
        !           417:        }
        !           418: 
        !           419:        /* Initialize the switch-to-pmode data structure.  */
        !           420:        vcpi_switch_data.phys_pdir = vcpi_pdir;
        !           421:        vcpi_switch_data.lin_gdt = boot_image_pa+(vm_offset_t)&gdt_pdesc.limit;
        !           422:        vcpi_switch_data.lin_idt = boot_image_pa+(vm_offset_t)&idt_pdesc.limit;
        !           423:        vcpi_switch_data.tss_sel = KERNEL_TSS;
        !           424:        vcpi_switch_data.entry_eip = (unsigned short)(vm_offset_t)&pmode_return;
        !           425:        vcpi_switch_data.entry_cs = KERNEL_16_CS;
        !           426: 
        !           427:        /* Initialize the GDT and IDT pseudo-descriptors.  */
        !           428:        gdt_pdesc.limit = sizeof(cpu[0].tables.gdt)-1;
        !           429:        gdt_pdesc.linear_base = boot_image_pa + (vm_offset_t)&cpu[0].tables.gdt;
        !           430:        idt_pdesc.limit = sizeof(cpu[0].tables.idt)-1;
        !           431:        idt_pdesc.linear_base = boot_image_pa + (vm_offset_t)&cpu[0].tables.idt;
        !           432: 
        !           433:        /* Set the GDT to temporary settings
        !           434:           just for getting into pmode the first time.  */
        !           435:        i16_gdt_init_temp();
        !           436: 
        !           437:        /* VCPI insists on loading a TSS immediately on entering pmode,
        !           438:           so initialize the KERNEL_TSS descriptor in the GDT.  */
        !           439:        i16_fill_gdt_descriptor(&cpu[0], KERNEL_TSS,
        !           440:                                boot_image_pa + (vm_offset_t)&cpu[0].tables.tss,
        !           441:                                sizeof(cpu[0].tables.tss)-1,
        !           442:                                ACC_PL_K|ACC_TSS, 0);
        !           443:        cpu[0].tables.tss.io_bit_map_offset = sizeof(cpu[0].tables.tss);
        !           444: 
        !           445: #if 0
        !           446:        /* Dump the various VCPI data structures, for debugging.  */
        !           447:        {
        !           448:                int i;
        !           449: 
        !           450:                i16_puts("Switch data");
        !           451:                i16_writehexl(switch_data.phys_pdir); i16_putchar(' ');
        !           452:                i16_writehexl(switch_data.lin_gdt); i16_putchar(' ');
        !           453:                i16_writehexl(switch_data.lin_idt); i16_putchar(' ');
        !           454:                i16_writehexw(switch_data.ldt_sel); i16_putchar(' ');
        !           455:                i16_writehexw(switch_data.tss_sel); i16_putchar(' ');
        !           456:                i16_writehexl(switch_data.entry_eip); i16_putchar(' ');
        !           457:                i16_writehexw(switch_data.entry_cs); i16_puts("");
        !           458: 
        !           459:                i16_puts("GDT pdesc");
        !           460:                i16_writehexw(gdt_pdesc.limit); i16_putchar(' ');
        !           461:                i16_writehexl(gdt_pdesc.linear_base); i16_puts("");
        !           462: 
        !           463:                i16_puts("IDT pdesc");
        !           464:                i16_writehexw(idt_pdesc.limit); i16_putchar(' ');
        !           465:                i16_writehexl(idt_pdesc.linear_base); i16_puts("");
        !           466: 
        !           467:                i16_puts("GDT");
        !           468:                for (i = 0; i < GDTSZ; i++)
        !           469:                {
        !           470:                        i16_writehexw(i*8); i16_putchar(' ');
        !           471:                        i16_writehexll(*((long long*)&cpu[0].tables.gdt[i]));
        !           472:                        i16_puts("");
        !           473:                }
        !           474:        }
        !           475: #endif
        !           476: 
        !           477:        /* Switch into pmode briefly to initialize the CPU tables and such.  */
        !           478:        i16_vcpi_switch_to_pmode();
        !           479:        i16_do_32bit(
        !           480: 
        !           481:                /* Note that right now we can only access the first 1MB of memory,
        !           482:                   because paging is enabled and that's the only memory region that's been mapped.
        !           483:                   The rest of physical memory won't be mapped until VCPI_PAGING_INIT,
        !           484:                   but VCPI_PAGING_INIT requires allocating memory for page tables,
        !           485:                   and we can't call phys_mem_collect() to provide memory to the allocator
        !           486:                   until all physical memory can be read and written.
        !           487:                   To get out of this catch-22,
        !           488:                   we call dos_mem_collect() beforehand here
        !           489:                   to make low DOS memory available for allocation by VCPI_PAGING_INIT.
        !           490:                   The call to phys_mem_collect() later will cause dos_mem_collect
        !           491:                   to be called a second time, but it'll just do nothing then.  */
        !           492:                dos_mem_collect();
        !           493: 
        !           494:                /* Initialize the basic CPU tables.  */
        !           495:                cpu_init(&cpu[0]);
        !           496: 
        !           497:                /* Initialize the paging system.  */
        !           498:                VCPI_PAGING_INIT(vcpi_pdir, (vm_offset_t)first_free_pte / 4 * PAGE_SIZE);
        !           499: 
        !           500:                /* Now that we can access all physical memory,
        !           501:                   collect the remaining memory regions we discovered while in 16-bit mode
        !           502:                   and add them to our free memory list.  */
        !           503:                phys_mem_collect();
        !           504: 
        !           505:                /* Initialize the hardware interrupt vectors in the IDT.  */
        !           506:                idt_irq_init();
        !           507: 
        !           508:                /* Now that we have an initialized LDT descriptor, start using it.  */
        !           509:                KERNEL_LDT_INIT();
        !           510: 
        !           511:                /* Switch to real mode and back again once more,
        !           512:                   to make sure everything's loaded properly.  */
        !           513:                do_16bit(
        !           514:                        i16_vcpi_switch_to_real_mode();
        !           515:                        i16_vcpi_switch_to_pmode();
        !           516:                );
        !           517: 
        !           518:                vcpi_start();
        !           519:        );
        !           520: }
        !           521: 
        !           522: /* Shouldn't be necessary, but just in case the end of the above function,
        !           523:    containing the .code16, gets "optimized away"...  */
        !           524: CODE16
        !           525: 
        !           526: void i16_vcpi_shutdown()
        !           527: {
        !           528:        if (pic_reprogrammed)
        !           529:        {
        !           530:                pic_reprogrammed = FALSE;
        !           531: 
        !           532:                i16_cli();
        !           533: 
        !           534:                i16_assert(irq_master_base >= 0x20);
        !           535: 
        !           536:                /* Reprogram the PIC.  */
        !           537:                i16_pic_set_master(0x08);
        !           538: 
        !           539:                /* Inform the VCPI server.  */
        !           540:                i16_vcpi_set_int_vecs(0x08, irq_slave_base);
        !           541: 
        !           542:                /* Restore the old interrupt vectors.  */
        !           543:                {
        !           544:                        int i;
        !           545: 
        !           546:                        for (i = 0; i < 8; i++)
        !           547:                        {
        !           548:                                i16_dos_set_int_vec(irq_master_base+i,
        !           549:                                                    &master_save_vecs[i]);
        !           550:                        }
        !           551:                }
        !           552: 
        !           553:                i16_sti();
        !           554:        }
        !           555: 
        !           556:        if (ems_page_allocated)
        !           557:        {
        !           558:                ems_page_allocated = 0;
        !           559:                asm volatile("int $0x67" : : "a" (0x4500), "d" (ems_handle));
        !           560:        }
        !           561: }
        !           562: 
        !           563: #endif ENABLE_VCPI
        !           564: 

unix.superglobalmegacorp.com

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