// get extended keyboard status static void handle_1612(struct bregs *regs) { yield(); regs->ax = ((GET_BDA(kbd_flag0) & ~((KF1_RCTRL|KF1_RALT) << 8)) | ((GET_BDA(kbd_flag1) & (KF1_RCTRL|KF1_RALT)) << 8)); //BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX); }
// get extended keyboard status static void handle_1612(struct bregs *regs) { regs->al = GET_BDA(kbd_flag0); regs->ah = ((GET_BDA(kbd_flag1) & ~(KF2_RCTRL|KF2_RALT)) | (GET_BDA(kbd_flag2) & (KF2_RCTRL|KF2_RALT))); //BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX); }
static void dequeue_key(struct bregs *regs, int incr, int extended) { yield(); u16 buffer_head; u16 buffer_tail; for (;;) { buffer_head = GET_BDA(kbd_buf_head); buffer_tail = GET_BDA(kbd_buf_tail); if (buffer_head != buffer_tail) break; if (!incr) { regs->flags |= F_ZF; return; } yield_toirq(); } u16 keycode = GET_FARVAR(SEG_BDA, *(u16*)(buffer_head+0)); u8 ascii = keycode & 0xff; if (!extended) { // Translate extended keys if (ascii == 0xe0 && keycode & 0xff00) keycode &= 0xff00; else if (keycode == 0xe00d || keycode == 0xe00a) // Extended enter key keycode = 0x1c00 | ascii; else if (keycode == 0xe02f) // Extended '/' key keycode = 0x352f; // Technically, if the ascii value is 0xf0 or if the // 'scancode' is greater than 0x84 then the key should be // discarded. However, there seems no harm in passing on the // extended values in these cases. } if (ascii == 0xf0 && keycode & 0xff00) keycode &= 0xff00; regs->ax = keycode; if (!incr) { regs->flags &= ~F_ZF; return; } u16 buffer_start = GET_BDA(kbd_buf_start_offset); u16 buffer_end = GET_BDA(kbd_buf_end_offset); buffer_head += 2; if (buffer_head >= buffer_end) buffer_head = buffer_start; SET_BDA(kbd_buf_head, buffer_head); }
// read disk status static void disk_1301(struct bregs *regs, struct drive_s *drive_g) { u8 v; if (regs->dl < EXTSTART_HD) // Floppy v = GET_BDA(floppy_last_status); else v = GET_BDA(disk_last_status); regs->ah = v; set_cf(regs, v); // XXX - clear disk_last_status? }
void VISIBLE16 vbe_104f05(struct bregs *regs) { if (regs->bh > 1 || regs->bl > 1) goto fail; if (GET_BDA(vbe_mode) & MF_LINEARFB) { regs->ah = VBE_RETURN_STATUS_INVALID; return; } struct vgamode_s *vmode_g = get_current_mode(); if (! vmode_g) goto fail; if (regs->bh) { int ret = vgahw_get_window(vmode_g, regs->bl); if (ret < 0) goto fail; regs->dx = ret; regs->ax = 0x004f; return; } int ret = vgahw_set_window(vmode_g, regs->bl, regs->dx); if (ret) goto fail; regs->ax = 0x004f; return; fail: regs->ax = 0x014f; }
static void vbe_104f03(struct bregs *regs) { regs->bx = GET_BDA(vbe_mode); dprintf(1, "VBE current mode=%x\n", regs->bx); regs->ax = 0x004f; }
static u8 enqueue_key(u16 keycode) { u16 buffer_start = GET_BDA(kbd_buf_start_offset); u16 buffer_end = GET_BDA(kbd_buf_end_offset); u16 buffer_head = GET_BDA(kbd_buf_head); u16 buffer_tail = GET_BDA(kbd_buf_tail); u16 temp_tail = buffer_tail; buffer_tail += 2; if (buffer_tail >= buffer_end) buffer_tail = buffer_start; if (buffer_tail == buffer_head) return 0; SET_FARVAR(SEG_BDA, *(u16*)(temp_tail+0), keycode); SET_BDA(kbd_buf_tail, buffer_tail); return 1; }
// read disk drive parameters static void noinline disk_1308(struct bregs *regs, struct drive_s *drive_g) { u16 ebda_seg = get_ebda_seg(); // Get logical geometry from table u16 nlc, nlh, nlspt; fillLCHS(drive_g, &nlc, &nlh, &nlspt); nlc--; nlh--; u8 count; if (regs->dl < EXTSTART_HD) { // Floppy count = GET_GLOBAL(FloppyCount); if (CONFIG_CDROM_EMU && drive_g == GLOBALFLAT2GLOBAL(GET_GLOBAL(cdemu_drive_gf))) regs->bx = GET_EBDA2(ebda_seg, cdemu.media) * 2; else regs->bx = GET_GLOBAL(drive_g->floppy_type); // set es & di to point to 11 byte diskette param table in ROM regs->es = SEG_BIOS; regs->di = (u32)&diskette_param_table2; } else if (regs->dl < EXTSTART_CD) { // Hard drive count = GET_BDA(hdcount); nlc--; // last sector reserved } else { // Not supported on CDROM disk_ret(regs, DISK_RET_EPARAM); return; } if (CONFIG_CDROM_EMU && GET_EBDA2(ebda_seg, cdemu.active)) { u8 emudrive = GET_EBDA2(ebda_seg, cdemu.emulated_extdrive); if (((emudrive ^ regs->dl) & 0x80) == 0) // Note extra drive due to emulation. count++; if (regs->dl < EXTSTART_HD && count > 2) // Max of two floppy drives. count = 2; } regs->al = 0; regs->ch = nlc & 0xff; regs->cl = ((nlc >> 2) & 0xc0) | (nlspt & 0x3f); regs->dh = nlh; disk_ret(regs, DISK_RET_SUCCESS); regs->dl = count; }
static void dequeue_key(struct bregs *regs, int incr, int extended) { yield(); u16 buffer_head; u16 buffer_tail; for (;;) { buffer_head = GET_BDA(kbd_buf_head); buffer_tail = GET_BDA(kbd_buf_tail); if (buffer_head != buffer_tail) break; if (!incr) { regs->flags |= F_ZF; return; } yield_toirq(); } u8 ascii_code = GET_FARVAR(SEG_BDA, *(u8*)(buffer_head+0)); u8 scan_code = GET_FARVAR(SEG_BDA, *(u8*)(buffer_head+1)); if ((ascii_code == 0xF0 && scan_code != 0) || (ascii_code == 0xE0 && !extended)) ascii_code = 0; regs->ax = (scan_code << 8) | ascii_code; if (!incr) { regs->flags &= ~F_ZF; return; } u16 buffer_start = GET_BDA(kbd_buf_start_offset); u16 buffer_end = GET_BDA(kbd_buf_end_offset); buffer_head += 2; if (buffer_head >= buffer_end) buffer_head = buffer_start; SET_BDA(kbd_buf_head, buffer_head); }
static void vbe_104f10(struct bregs *regs) { switch (regs->bl) { case 0x00: regs->bx = 0x0f30; break; case 0x01: SET_BDA(vbe_flag, regs->bh); break; case 0x02: regs->bh = GET_BDA(vbe_flag); break; default: regs->ax = 0x014f; return; } regs->ax = 0x004f; }
int cdrom_boot(struct drive_s *drive_g) { ASSERT32FLAT(); struct disk_op_s dop; int cdid = getDriveId(EXTTYPE_CD, drive_g); memset(&dop, 0, sizeof(dop)); dop.drive_g = drive_g; if (!dop.drive_g || cdid < 0) return 1; int ret = scsi_is_ready(&dop); if (ret) dprintf(1, "scsi_is_ready returned %d\n", ret); // Read the Boot Record Volume Descriptor u8 buffer[CDROM_SECTOR_SIZE]; dop.lba = 0x11; dop.count = 1; dop.buf_fl = buffer; ret = cdb_read(&dop); if (ret) return 3; // Validity checks if (buffer[0]) return 4; if (strcmp((char*)&buffer[1], "CD001\001EL TORITO SPECIFICATION") != 0) return 5; // ok, now we calculate the Boot catalog address u32 lba = *(u32*)&buffer[0x47]; // And we read the Boot Catalog dop.lba = lba; dop.count = 1; ret = cdb_read(&dop); if (ret) return 7; // Validation entry if (buffer[0x00] != 0x01) return 8; // Header if (buffer[0x01] != 0x00) return 9; // Platform if (buffer[0x1E] != 0x55) return 10; // key 1 if (buffer[0x1F] != 0xAA) return 10; // key 2 // Initial/Default Entry if (buffer[0x20] != 0x88) return 11; // Bootable u8 media = buffer[0x21]; CDEmu.media = media; CDEmu.emulated_drive_gf = dop.drive_g; u16 boot_segment = *(u16*)&buffer[0x22]; if (!boot_segment) boot_segment = 0x07C0; CDEmu.load_segment = boot_segment; CDEmu.buffer_segment = 0x0000; u16 nbsectors = *(u16*)&buffer[0x26]; CDEmu.sector_count = nbsectors; lba = *(u32*)&buffer[0x28]; CDEmu.ilba = lba; // And we read the image in memory dop.lba = lba; dop.count = DIV_ROUND_UP(nbsectors, 4); dop.buf_fl = MAKE_FLATPTR(boot_segment, 0); ret = cdb_read(&dop); if (ret) return 12; if (media == 0) { // No emulation requested - return success. CDEmu.emulated_extdrive = EXTSTART_CD + cdid; return 0; } // Emulation of a floppy/harddisk requested if (! CONFIG_CDROM_EMU || !cdemu_drive_gf) return 13; // Set emulated drive id and increase bios installed hardware // number of devices if (media < 4) { // Floppy emulation CDEmu.emulated_extdrive = 0x00; // XXX - get and set actual floppy count. set_equipment_flags(0x41, 0x41); switch (media) { case 0x01: // 1.2M floppy CDEmu.lchs.spt = 15; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; case 0x02: // 1.44M floppy CDEmu.lchs.spt = 18; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; case 0x03: // 2.88M floppy CDEmu.lchs.spt = 36; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; } } else { // Harddrive emulation CDEmu.emulated_extdrive = 0x80; SET_BDA(hdcount, GET_BDA(hdcount) + 1); // Peak at partition table to get chs. struct mbr_s *mbr = (void*)0; u8 sptcyl = GET_FARVAR(boot_segment, mbr->partitions[0].last.sptcyl); u8 cyllow = GET_FARVAR(boot_segment, mbr->partitions[0].last.cyllow); u8 heads = GET_FARVAR(boot_segment, mbr->partitions[0].last.heads); CDEmu.lchs.spt = sptcyl & 0x3f; CDEmu.lchs.cylinders = ((sptcyl<<2)&0x300) + cyllow + 1; CDEmu.lchs.heads = heads + 1; } // everything is ok, so from now on, the emulation is active CDEmu.active = 0x01; dprintf(6, "cdemu media=%d\n", media); return 0; }
// get shift flag status static void handle_1602(struct bregs *regs) { yield(); regs->al = GET_BDA(kbd_flag0); }
handle_16a2(struct bregs *regs) { // don't change AH : function int16 ah=0x20-0x22 NOT supported } static void handle_16XX(struct bregs *regs) { warn_unimplemented(regs); } static void noinline set_leds(void) { u8 shift_flags = (GET_BDA(kbd_flag0) >> 4) & 0x07; u8 kbd_led = GET_BDA(kbd_led); u8 led_flags = kbd_led & 0x07; if (shift_flags == led_flags) return; int ret = kbd_command(ATKBD_CMD_SETLEDS, &shift_flags); if (ret) // Error return; kbd_led = (kbd_led & ~0x07) | shift_flags; SET_BDA(kbd_led, kbd_led); } // INT 16h Keyboard Service Entry Point void VISIBLE16 handle_16(struct bregs *regs)