Annotation of Gnu-Mach/i386/dos/i16/i16_vcpi.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: #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.