コード例 #1
0
ファイル: parallel.c プロジェクト: apaka/vbox
void BIOSCALL int17_function(pusha_regs_t regs, uint16_t es, uint16_t ds, volatile iret_addr_t iret_addr)
{
    uint16_t    addr,timeout;
    uint8_t     val8;

    int_enable();
    
    addr = read_word(0x0040, (regs.u.r16.dx << 1) + 8);
    if ((regs.u.r8.ah < 3) && (regs.u.r16.dx < 3) && (addr > 0)) {
        timeout = read_byte(0x0040, 0x0078 + regs.u.r16.dx) << 8;
        if (regs.u.r8.ah == 0) {
            outb(addr, regs.u.r8.al);
            val8 = inb(addr+2);
            outb(addr+2, val8 | 0x01); // send strobe
            outb(addr+2, val8 & ~0x01);
            while (((inb(addr+1) & 0x40) == 0x40) && (timeout)) {
                timeout--;
            }
        }
        if (regs.u.r8.ah == 1) {
            val8 = inb(addr+2);
            outb(addr+2, val8 & ~0x04); // send init
            outb(addr+2, val8 | 0x04);
        }
        val8 = inb(addr+1);
        regs.u.r8.ah = (val8 ^ 0x48);
        if (!timeout) regs.u.r8.ah |= 0x01;
        ClearCF(iret_addr.flags);
    } else {
        SetCF(iret_addr.flags); // Unsupported
    }
}
コード例 #2
0
void BIOSCALL int1a_function(pusha_regs_t regs, uint16_t ds, uint16_t es, iret_addr_t iret_addr)
{
    uint8_t     val8;

    BX_DEBUG_INT1A("int1a: AX=%04x BX=%04x CX=%04x DX=%04x DS=%04x\n",
                   regs.u.r16.ax, regs.u.r16.bx, regs.u.r16.cx, regs.u.r16.dx, ds);
    int_enable();

    switch (regs.u.r8.ah) {
    case 0: // get current clock count
        int_disable();
        regs.u.r16.cx = BiosData->ticks_high;
        regs.u.r16.dx = BiosData->ticks_low;
        regs.u.r8.al  = BiosData->midnight_flag;
        BiosData->midnight_flag = 0; // reset flag
        int_enable();
        // AH already 0
        ClearCF(iret_addr.flags); // OK
        break;

    case 1: // Set Current Clock Count
        int_disable();
        BiosData->ticks_high = regs.u.r16.cx;
        BiosData->ticks_low  = regs.u.r16.dx;
        BiosData->midnight_flag = 0; // reset flag
        int_enable();
        regs.u.r8.ah = 0;
        ClearCF(iret_addr.flags); // OK
        break;

    case 2: // Read CMOS Time
        if (rtc_updating()) {
            SetCF(iret_addr.flags);
            break;
        }

        regs.u.r8.dh = inb_cmos(0x00); // Seconds
        regs.u.r8.cl = inb_cmos(0x02); // Minutes
        regs.u.r8.ch = inb_cmos(0x04); // Hours
        regs.u.r8.dl = inb_cmos(0x0b) & 0x01; // Stat Reg B
        regs.u.r8.ah = 0;
        regs.u.r8.al = regs.u.r8.ch;
        ClearCF(iret_addr.flags); // OK
        break;

    case 3: // Set CMOS Time
        // Using a debugger, I notice the following masking/setting
        // of bits in Status Register B, by setting Reg B to
        // a few values and getting its value after INT 1A was called.
        //
        //        try#1       try#2       try#3
        // before 1111 1101   0111 1101   0000 0000
        // after  0110 0010   0110 0010   0000 0010
        //
        // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
        // My assumption: RegB = ((RegB & 01100000b) | 00000010b)
        if (rtc_updating()) {
            init_rtc();
            // fall through as if an update were not in progress
        }
        outb_cmos(0x00, regs.u.r8.dh); // Seconds
        outb_cmos(0x02, regs.u.r8.cl); // Minutes
        outb_cmos(0x04, regs.u.r8.ch); // Hours
        // Set Daylight Savings time enabled bit to requested value
        val8 = (inb_cmos(0x0b) & 0x60) | 0x02 | (regs.u.r8.dl & 0x01);
        // (reg B already selected)
        outb_cmos(0x0b, val8);
        regs.u.r8.ah = 0;
        regs.u.r8.al = val8; // val last written to Reg B
        ClearCF(iret_addr.flags); // OK
        break;

    case 4: // Read CMOS Date
        regs.u.r8.ah = 0;
        if (rtc_updating()) {
            SetCF(iret_addr.flags);
            break;
        }
        regs.u.r8.cl = inb_cmos(0x09); // Year
        regs.u.r8.dh = inb_cmos(0x08); // Month
        regs.u.r8.dl = inb_cmos(0x07); // Day of Month
        regs.u.r8.ch = inb_cmos(0x32); // Century
        regs.u.r8.al = regs.u.r8.ch;
        ClearCF(iret_addr.flags); // OK
        break;

    case 5: // Set CMOS Date
        // Using a debugger, I notice the following masking/setting
        // of bits in Status Register B, by setting Reg B to
        // a few values and getting its value after INT 1A was called.
        //
        //        try#1       try#2       try#3       try#4
        // before 1111 1101   0111 1101   0000 0010   0000 0000
        // after  0110 1101   0111 1101   0000 0010   0000 0000
        //
        // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
        // My assumption: RegB = (RegB & 01111111b)
        if (rtc_updating()) {
            init_rtc();
            SetCF(iret_addr.flags);
            break;
        }
        outb_cmos(0x09, regs.u.r8.cl); // Year
        outb_cmos(0x08, regs.u.r8.dh); // Month
        outb_cmos(0x07, regs.u.r8.dl); // Day of Month
        outb_cmos(0x32, regs.u.r8.ch); // Century
        val8 = inb_cmos(0x0b) & 0x7f; // clear halt-clock bit
        outb_cmos(0x0b, val8);
        regs.u.r8.ah = 0;
        regs.u.r8.al = val8; // AL = val last written to Reg B
        ClearCF(iret_addr.flags); // OK
        break;

    case 6: // Set Alarm Time in CMOS
        // Using a debugger, I notice the following masking/setting
        // of bits in Status Register B, by setting Reg B to
        // a few values and getting its value after INT 1A was called.
        //
        //        try#1       try#2       try#3
        // before 1101 1111   0101 1111   0000 0000
        // after  0110 1111   0111 1111   0010 0000
        //
        // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
        // My assumption: RegB = ((RegB & 01111111b) | 00100000b)
        val8 = inb_cmos(0x0b); // Get Status Reg B
        regs.u.r16.ax = 0;
        if (val8 & 0x20) {
            // Alarm interrupt enabled already
            SetCF(iret_addr.flags); // Error: alarm in use
            break;
        }
        if (rtc_updating()) {
            init_rtc();
            // fall through as if an update were not in progress
        }
        outb_cmos(0x01, regs.u.r8.dh); // Seconds alarm
        outb_cmos(0x03, regs.u.r8.cl); // Minutes alarm
        outb_cmos(0x05, regs.u.r8.ch); // Hours alarm
        outb(0xa1, inb(0xa1) & 0xfe); // enable IRQ 8
        // enable Status Reg B alarm bit, clear halt clock bit
        outb_cmos(0x0b, (val8 & 0x7f) | 0x20);
        ClearCF(iret_addr.flags); // OK
        break;

    case 7: // Turn off Alarm
        // Using a debugger, I notice the following masking/setting
        // of bits in Status Register B, by setting Reg B to
        // a few values and getting its value after INT 1A was called.
        //
        //        try#1       try#2       try#3       try#4
        // before 1111 1101   0111 1101   0010 0000   0010 0010
        // after  0100 0101   0101 0101   0000 0000   0000 0010
        //
        // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
        // My assumption: RegB = (RegB & 01010111b)
        val8 = inb_cmos(0x0b); // Get Status Reg B
        // clear clock-halt bit, disable alarm bit
        outb_cmos(0x0b, val8 & 0x57); // disable alarm bit
        regs.u.r8.ah = 0;
        regs.u.r8.al = val8; // val last written to Reg B
        ClearCF(iret_addr.flags); // OK
        break;

    default:
        BX_DEBUG_INT1A("int1a: AX=%04x unsupported\n", regs.u.r16.ax);
        SetCF(iret_addr.flags); // Unsupported
    }
}