// Perform read/write/verify using new-style "int13ext" accesses. static void noinline extended_access(struct bregs *regs, struct drive_s *drive_gf, u16 command) { struct disk_op_s dop; struct int13ext_s *param_far = (struct int13ext_s*)(regs->si+0); // Get lba and check. dop.lba = GET_FARVAR(regs->ds, param_far->lba); dop.command = command; dop.drive_gf = drive_gf; if (dop.lba >= GET_GLOBALFLAT(drive_gf->sectors)) { warn_invalid(regs); disk_ret(regs, DISK_RET_EPARAM); return; } dop.buf_fl = SEGOFF_TO_FLATPTR(GET_FARVAR(regs->ds, param_far->data)); dop.count = GET_FARVAR(regs->ds, param_far->count); if (! dop.count) { // Nothing to do. disk_ret(regs, DISK_RET_SUCCESS); return; } int status = send_disk_op(&dop); SET_FARVAR(regs->ds, param_far->count, dop.count); disk_ret(regs, status); }
static int bochsvga_save_state(u16 seg, u16 *info) { u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE); SET_FARVAR(seg, *info, en); info++; if (!(en & VBE_DISPI_ENABLED)) return 0; int i; for (i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) if (i != VBE_DISPI_INDEX_ENABLE) { u16 v = dispi_read(i); SET_FARVAR(seg, *info, v); info++; } return 0; }
// BBS - Get Version and Installation Check static u16 handle_pnp60(u16 *args) { u16 version_ptr = args[1]; u16 version_seg = args[2]; SET_FARVAR(version_seg, *(u16*)(version_ptr+0), 0x0101); return 0; }
static void vbe_104f00(struct bregs *regs) { u16 seg = regs->es; struct vbe_info *info = (void*)(regs->di+0); if (GET_FARVAR(seg, info->signature) == VBE2_SIGNATURE) { dprintf(4, "Get VBE Controller: VBE2 Signature found\n"); } else if (GET_FARVAR(seg, info->signature) == VESA_SIGNATURE) { dprintf(4, "Get VBE Controller: VESA Signature found\n"); } else { dprintf(4, "Get VBE Controller: Invalid Signature\n"); } memset_far(seg, info, 0, sizeof(*info)); SET_FARVAR(seg, info->signature, VESA_SIGNATURE); SET_FARVAR(seg, info->version, 0x0300); SET_FARVAR(seg, info->oem_string, SEGOFF(get_global_seg(), (u32)VBE_OEM_STRING)); SET_FARVAR(seg, info->capabilities, GET_GLOBAL(VBE_capabilities)); /* We generate our mode list in the reserved field of the info block */ u16 *destmode = (void*)info->reserved; SET_FARVAR(seg, info->video_mode, SEGOFF(seg, (u32)destmode)); /* Total memory (in 64k blocks) */ SET_FARVAR(seg, info->total_memory , GET_GLOBAL(VBE_total_memory) / (64*1024)); SET_FARVAR(seg, info->oem_vendor_string, SEGOFF(get_global_seg(), (u32)VBE_VENDOR_STRING)); SET_FARVAR(seg, info->oem_product_string, SEGOFF(get_global_seg(), (u32)VBE_PRODUCT_STRING)); SET_FARVAR(seg, info->oem_revision_string, SEGOFF(get_global_seg(), (u32)VBE_REVISION_STRING)); /* Fill list of modes */ u16 *last = (void*)&info->reserved[sizeof(info->reserved)]; vgahw_list_modes(seg, destmode, last - 1); regs->ax = 0x004f; }
static u8 enqueue_key(u8 scan_code, u8 ascii_code) { 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, *(u8*)(temp_tail+0), ascii_code); SET_FARVAR(SEG_BDA, *(u8*)(temp_tail+1), scan_code); SET_BDA(kbd_buf_tail, buffer_tail); return 1; }
// Execute a "disk_op_s" request after jumping to the extra stack. static int __send_disk_op(struct disk_op_s *op_far, u16 op_seg) { struct disk_op_s dop; memcpy_far(GET_SEG(SS), &dop, op_seg, op_far, sizeof(dop)); int status = process_op(&dop); // Update count with total sectors transferred. SET_FARVAR(op_seg, op_far->count, dop.count); return status; }
void bochsvga_list_modes(u16 seg, u16 *dest, u16 *last) { struct bochsvga_mode *m = bochsvga_modes; if (GET_GLOBAL(dispi_found)) { for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)] && dest<last; m++) { u16 mode = GET_GLOBAL(m->mode); if (mode == 0xffff) continue; SET_FARVAR(seg, *dest, mode); dest++; } } stdvga_list_modes(seg, dest, last); }
static void gfx_planar(struct gfx_op *op) { if (!CONFIG_VGA_STDVGA_PORTS) return; void *dest_far = (void*)(op->y * op->linelength + op->x / 8); int plane; switch (op->op) { default: case GO_READ8: memset(op->pixels, 0, sizeof(op->pixels)); for (plane = 0; plane < 4; plane++) { stdvga_planar4_plane(plane); u8 data = GET_FARVAR(SEG_GRAPH, *(u8*)dest_far); int pixel; for (pixel=0; pixel<8; pixel++) op->pixels[pixel] |= ((data>>(7-pixel)) & 1) << plane; } break; case GO_WRITE8: for (plane = 0; plane<4; plane++) { stdvga_planar4_plane(plane); u8 data = 0; int pixel; for (pixel=0; pixel<8; pixel++) data |= ((op->pixels[pixel]>>plane) & 1) << (7-pixel); SET_FARVAR(SEG_GRAPH, *(u8*)dest_far, data); } break; case GO_MEMSET: for (plane = 0; plane < 4; plane++) { stdvga_planar4_plane(plane); u8 data = (op->pixels[0] & (1<<plane)) ? 0xff : 0x00; memset_stride(SEG_GRAPH, dest_far, data , op->xlen / 8, op->linelength, op->ylen); } break; case GO_MEMMOVE: ; void *src_far = (void*)(op->srcy * op->linelength + op->x / 8); for (plane = 0; plane < 4; plane++) { stdvga_planar4_plane(plane); memmove_stride(SEG_GRAPH, dest_far, src_far , op->xlen / 8, op->linelength, op->ylen); } break; } stdvga_planar4_plane(-1); }
static void vbe_104f01(struct bregs *regs) { u16 seg = regs->es; struct vbe_mode_info *info = (void*)(regs->di+0); u16 mode = regs->cx; dprintf(1, "VBE mode info request: %x\n", mode); struct vgamode_s *vmode_g = vgahw_find_mode(mode & ~MF_VBEFLAGS); if (! vmode_g) { dprintf(1, "VBE mode %x not found\n", mode); regs->ax = 0x014f; return; } memset_far(seg, info, 0, sizeof(*info)); // Basic information about video controller. u32 win_granularity = GET_GLOBAL(VBE_win_granularity); SET_FARVAR(seg, info->winA_attributes, (win_granularity ? VBE_WINDOW_ATTRIBUTE_RELOCATABLE : 0) | VBE_WINDOW_ATTRIBUTE_READABLE | VBE_WINDOW_ATTRIBUTE_WRITEABLE); SET_FARVAR(seg, info->winB_attributes, 0); SET_FARVAR(seg, info->win_granularity, win_granularity); SET_FARVAR(seg, info->win_size, 64); /* Bank size 64K */ SET_FARVAR(seg, info->winA_seg, GET_GLOBAL(vmode_g->sstart)); SET_FARVAR(seg, info->winB_seg, 0x0); extern void entry_104f05(void); SET_FARVAR(seg, info->win_func_ptr , SEGOFF(get_global_seg(), (u32)entry_104f05)); // Basic information about mode. int width = GET_GLOBAL(vmode_g->width); int height = GET_GLOBAL(vmode_g->height); int linesize = DIV_ROUND_UP(width * vga_bpp(vmode_g), 8); SET_FARVAR(seg, info->bytes_per_scanline, linesize); SET_FARVAR(seg, info->xres, width); SET_FARVAR(seg, info->yres, height); SET_FARVAR(seg, info->xcharsize, GET_GLOBAL(vmode_g->cwidth)); SET_FARVAR(seg, info->ycharsize, GET_GLOBAL(vmode_g->cheight)); int depth = GET_GLOBAL(vmode_g->depth); SET_FARVAR(seg, info->bits_per_pixel, depth); u8 memmodel = GET_GLOBAL(vmode_g->memmodel); SET_FARVAR(seg, info->mem_model, memmodel); SET_FARVAR(seg, info->reserved0, 1); // Mode specific info. u16 mode_attr = VBE_MODE_ATTRIBUTE_SUPPORTED | VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | VBE_MODE_ATTRIBUTE_COLOR_MODE | VBE_MODE_ATTRIBUTE_GRAPHICS_MODE | VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE; u32 framebuffer = 0; int planes = 1, banks = 1; u32 pages = GET_GLOBAL(VBE_total_memory) / ALIGN(height * linesize, 64*1024); switch (memmodel) { case MM_TEXT: mode_attr &= ~VBE_MODE_ATTRIBUTE_GRAPHICS_MODE; mode_attr |= VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT; if (GET_GLOBAL(vmode_g->sstart) == SEG_MTEXT) mode_attr &= ~VBE_MODE_ATTRIBUTE_COLOR_MODE; pages = 1; break; case MM_CGA: pages = 1; banks = 2; SET_FARVAR(seg, info->bank_size, 8); break; case MM_PLANAR: planes = 4; pages /= 4; break; default: framebuffer = GET_GLOBAL(VBE_framebuffer); if (framebuffer) mode_attr |= VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE; break; } SET_FARVAR(seg, info->mode_attributes, mode_attr); SET_FARVAR(seg, info->planes, planes); SET_FARVAR(seg, info->pages, pages - 1); SET_FARVAR(seg, info->banks, banks); // Pixel color breakdown u8 r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos; switch (depth) { case 15: r_size = 5; r_pos = 10; g_size = 5; g_pos = 5; b_size = 5; b_pos = 0; a_size = 1; a_pos = 15; break; case 16: r_size = 5; r_pos = 11; g_size = 6; g_pos = 5; b_size = 5; b_pos = 0; a_size = 0; a_pos = 0; break; case 24: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8; b_size = 8; b_pos = 0; a_size = 0; a_pos = 0; break; case 32: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8; b_size = 8; b_pos = 0; a_size = 8; a_pos = 24; SET_FARVAR(seg, info->directcolor_info, VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE); break; default: r_size = 0; r_pos = 0; g_size = 0; g_pos = 0; b_size = 0; b_pos = 0; a_size = 0; a_pos = 0; break; } SET_FARVAR(seg, info->red_size, r_size); SET_FARVAR(seg, info->red_pos, r_pos); SET_FARVAR(seg, info->green_size, g_size); SET_FARVAR(seg, info->green_pos, g_pos); SET_FARVAR(seg, info->blue_size, b_size); SET_FARVAR(seg, info->blue_pos, b_pos); SET_FARVAR(seg, info->alpha_size, a_size); SET_FARVAR(seg, info->alpha_pos, a_pos); // Linear framebuffer info. if (framebuffer) { SET_FARVAR(seg, info->phys_base, framebuffer); SET_FARVAR(seg, info->reserved1, 0); SET_FARVAR(seg, info->reserved2, 0); SET_FARVAR(seg, info->linear_bytes_per_scanline, linesize); SET_FARVAR(seg, info->linear_pages, 0); SET_FARVAR(seg, info->linear_red_size, r_size); SET_FARVAR(seg, info->linear_red_pos, r_pos); SET_FARVAR(seg, info->linear_green_size, g_size); SET_FARVAR(seg, info->linear_green_pos, g_pos); SET_FARVAR(seg, info->linear_blue_size, b_size); SET_FARVAR(seg, info->linear_blue_pos, b_pos); SET_FARVAR(seg, info->linear_alpha_size, a_size); SET_FARVAR(seg, info->linear_alpha_pos, a_pos); } regs->ax = 0x004f; }
// IBM/MS get drive parameters static void noinline disk_1348(struct bregs *regs, struct drive_s *drive_gf) { u16 seg = regs->ds; struct int13dpt_s *param_far = (struct int13dpt_s*)(regs->si+0); u16 size = GET_FARVAR(seg, param_far->size); u16 t13 = size == 74; // Buffer is too small if (size < 26) { disk_ret(regs, DISK_RET_EPARAM); return; } // EDD 1.x u8 type = GET_GLOBALFLAT(drive_gf->type); u16 npc = GET_GLOBALFLAT(drive_gf->pchs.cylinder); u16 nph = GET_GLOBALFLAT(drive_gf->pchs.head); u16 nps = GET_GLOBALFLAT(drive_gf->pchs.sector); u64 lba = GET_GLOBALFLAT(drive_gf->sectors); u16 blksize = GET_GLOBALFLAT(drive_gf->blksize); dprintf(DEBUG_HDL_13, "disk_1348 size=%d t=%d chs=%d,%d,%d lba=%d bs=%d\n" , size, type, npc, nph, nps, (u32)lba, blksize); SET_FARVAR(seg, param_far->size, 26); if (type == DTYPE_ATA_ATAPI) { // 0x74 = removable, media change, lockable, max values SET_FARVAR(seg, param_far->infos, 0x74); SET_FARVAR(seg, param_far->cylinders, 0xffffffff); SET_FARVAR(seg, param_far->heads, 0xffffffff); SET_FARVAR(seg, param_far->spt, 0xffffffff); SET_FARVAR(seg, param_far->sector_count, (u64)-1); } else { if (lba > (u64)nps*nph*0x3fff) { SET_FARVAR(seg, param_far->infos, 0x00); // geometry is invalid SET_FARVAR(seg, param_far->cylinders, 0x3fff); } else { SET_FARVAR(seg, param_far->infos, 0x02); // geometry is valid SET_FARVAR(seg, param_far->cylinders, (u32)npc); } SET_FARVAR(seg, param_far->heads, (u32)nph); SET_FARVAR(seg, param_far->spt, (u32)nps); SET_FARVAR(seg, param_far->sector_count, lba); } SET_FARVAR(seg, param_far->blksize, blksize); if (size < 30 || (type != DTYPE_ATA && type != DTYPE_ATA_ATAPI && type != DTYPE_VIRTIO_BLK && type != DTYPE_VIRTIO_SCSI)) { disk_ret(regs, DISK_RET_SUCCESS); return; } // EDD 2.x int bdf; u16 iobase1 = 0; u64 device_path = 0; u8 channel = 0; SET_FARVAR(seg, param_far->size, 30); if (type == DTYPE_ATA || type == DTYPE_ATA_ATAPI) { SET_FARVAR(seg, param_far->dpte, SEGOFF(SEG_LOW, (u32)&DefaultDPTE)); // Fill in dpte struct atadrive_s *adrive_gf = container_of( drive_gf, struct atadrive_s, drive); struct ata_channel_s *chan_gf = GET_GLOBALFLAT(adrive_gf->chan_gf); u8 slave = GET_GLOBALFLAT(adrive_gf->slave); u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2); u8 irq = GET_GLOBALFLAT(chan_gf->irq); iobase1 = GET_GLOBALFLAT(chan_gf->iobase1); bdf = GET_GLOBALFLAT(chan_gf->pci_bdf); device_path = slave; channel = GET_GLOBALFLAT(chan_gf->chanid); u16 options = 0; if (type == DTYPE_ATA) { u8 translation = GET_GLOBALFLAT(drive_gf->translation); if (translation != TRANSLATION_NONE) { options |= 1<<3; // CHS translation if (translation == TRANSLATION_LBA) options |= 1<<9; if (translation == TRANSLATION_RECHS) options |= 3<<9; } } else { // ATAPI options |= 1<<5; // removable device options |= 1<<6; // atapi device } options |= 1<<4; // lba translation if (CONFIG_ATA_PIO32) options |= 1<<7; SET_LOW(DefaultDPTE.iobase1, iobase1); SET_LOW(DefaultDPTE.iobase2, iobase2 + ATA_CB_DC); SET_LOW(DefaultDPTE.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | ATA_CB_DH_LBA)); SET_LOW(DefaultDPTE.unused, 0xcb); SET_LOW(DefaultDPTE.irq, irq); SET_LOW(DefaultDPTE.blkcount, 1); SET_LOW(DefaultDPTE.dma, 0); SET_LOW(DefaultDPTE.pio, 0); SET_LOW(DefaultDPTE.options, options); SET_LOW(DefaultDPTE.reserved, 0); SET_LOW(DefaultDPTE.revision, 0x11); u8 sum = checksum_far(SEG_LOW, &DefaultDPTE, 15); SET_LOW(DefaultDPTE.checksum, -sum); } else {