Пример #1
0
struct vgamode_s *bochsvga_find_mode(int mode)
{
    struct bochsvga_mode *m = bochsvga_modes;
    if (GET_GLOBAL(dispi_found))
        for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)]; m++)
            if (GET_GLOBAL(m->mode) == mode)
                return &m->info;
    return stdvga_find_mode(mode);
}
Пример #2
0
static u8
get_translation(struct drive_s *drive_g)
{
    u8 type = GET_GLOBAL(drive_g->type);
    if (! CONFIG_COREBOOT && type == DTYPE_ATA) {
        // Emulators pass in the translation info via nvram.
        u8 ataid = GET_GLOBAL(drive_g->cntl_id);
        u8 channel = ataid / 2;
        u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
        translation >>= 2 * (ataid % 4);
        translation &= 0x03;
        return translation;
    }
Пример #3
0
static void
via_155f18(struct bregs *regs)
{
    int fbsize = GET_GLOBAL(ViaFBsize), ramspeed = GET_GLOBAL(ViaRamSpeed);
    if (fbsize < 0 || ramspeed < 0) {
        set_code_invalid(regs, RET_EUNSUPPORTED);
        return;
    }
    regs->eax = 0x5f;
    regs->ebx = 0x500 | (ramspeed << 4) | fbsize;
    regs->ecx = 0x060;
    set_success(regs);
}
Пример #4
0
// Reset a drive
static void
ata_reset(struct atadrive_s *adrive_g)
{
    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
    u8 slave = GET_GLOBAL(adrive_g->slave);
    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);

    dprintf(6, "ata_reset drive=%p\n", &adrive_g->drive);
    // Pulse SRST
    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC);
    udelay(5);
    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
    msleep(2);

    // wait for device to become not busy.
    int status = await_not_bsy(iobase1);
    if (status < 0)
        goto done;
    if (slave) {
        // Change device.
        u64 end = calc_future_tsc(IDE_TIMEOUT);
        for (;;) {
            outb(ATA_CB_DH_DEV1, iobase1 + ATA_CB_DH);
            status = ndelay_await_not_bsy(iobase1);
            if (status < 0)
                goto done;
            if (inb(iobase1 + ATA_CB_DH) == ATA_CB_DH_DEV1)
                break;
            // Change drive request failed to take effect - retry.
            if (check_tsc(end)) {
                warn_timeout();
                goto done;
            }
        }
    } else {
        // QEMU doesn't reset dh on reset, so set it explicitly.
        outb(ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH);
    }

    // On a user-reset request, wait for RDY if it is an ATA device.
    u8 type=GET_GLOBAL(adrive_g->drive.type);
    if (type == DTYPE_ATA)
        status = await_rdy(iobase1);

done:
    // Enable interrupts
    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);

    dprintf(6, "ata_reset exit status=%x\n", status);
}
Пример #5
0
// 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;
}
Пример #6
0
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);
}
Пример #7
0
static void
vbe_104f06(struct bregs *regs)
{
    if (regs->bl > 0x02)
        goto fail;
    struct vgamode_s *vmode_g = get_current_mode();
    if (! vmode_g)
        goto fail;
    int bpp = vga_bpp(vmode_g);

    if (regs->bl == 0x00) {
        int ret = vgahw_set_linelength(vmode_g, DIV_ROUND_UP(regs->cx * bpp, 8));
        if (ret)
            goto fail;
    } else if (regs->bl == 0x02) {
        int ret = vgahw_set_linelength(vmode_g, regs->cx);
        if (ret)
            goto fail;
    }
    int linelength = vgahw_get_linelength(vmode_g);
    if (linelength < 0)
        goto fail;

    regs->bx = linelength;
    regs->cx = (linelength * 8) / bpp;
    regs->dx = GET_GLOBAL(VBE_total_memory) / linelength;
    regs->ax = 0x004f;
    return;
fail:
    regs->ax = 0x014f;
}
Пример #8
0
// Send an ata command that does not transfer any further data.
int
ata_cmd_nondata(struct atadrive_s *adrive_g, struct ata_pio_command *cmd)
{
    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);

    // Disable interrupts
    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);

    int ret = send_cmd(adrive_g, cmd);
    if (ret)
        goto fail;
    ret = ndelay_await_not_bsy(iobase1);
    if (ret < 0)
        goto fail;

    if (ret & ATA_CB_STAT_ERR) {
        dprintf(6, "nondata cmd : read error (status=%02x err=%02x)\n"
                , ret, inb(iobase1 + ATA_CB_ERR));
        ret = -4;
        goto fail;
    }
    if (ret & ATA_CB_STAT_DRQ) {
        dprintf(6, "nondata cmd : DRQ set (status %02x)\n", ret);
        ret = -5;
        goto fail;
    }

fail:
    // Enable interrupts
    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);

    return ret;
}
Пример #9
0
static void
vbe_104f08(struct bregs *regs)
{
    struct vgamode_s *vmode_g = get_current_mode();
    if (! vmode_g)
        goto fail;
    u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
    if (memmodel == MM_DIRECT || memmodel == MM_YUV) {
        regs->ax = 0x034f;
        return;
    }
    if (regs->bl > 1)
        goto fail;
    if (regs->bl == 0) {
        int ret = vgahw_set_dacformat(vmode_g, regs->bh);
        if (ret < 0)
            goto fail;
    }
    int ret = vgahw_get_dacformat(vmode_g);
    if (ret < 0)
        goto fail;
    regs->bh = ret;
    regs->ax = 0x004f;
    return;
fail:
    regs->ax = 0x014f;
}
Пример #10
0
// Test if USB keyboard is active.
inline int
usb_kbd_active(void)
{
    if (! CONFIG_USB_KEYBOARD)
        return 0;
    return GET_GLOBAL(keyboard_pipe) != NULL;
}
Пример #11
0
// Test if USB mouse is active.
inline int
usb_mouse_active(void)
{
    if (! CONFIG_USB_MOUSE)
        return 0;
    return GET_GLOBAL(mouse_pipe) != NULL;
}
Пример #12
0
struct drive_s *
getDrive(u8 exttype, u8 extdriveoffset)
{
    if (extdriveoffset >= ARRAY_SIZE(IDMap[0]))
        return NULL;
    return GET_GLOBAL(IDMap[exttype][extdriveoffset]);
}
Пример #13
0
// Perform read/write/verify using new-style "int13ext" accesses.
static void noinline
extended_access(struct bregs *regs, struct drive_s *drive_g, u16 command)
{
    struct disk_op_s dop;
    // Get lba and check.
    dop.lba = GET_INT13EXT(regs, lba);
    dop.command = command;
    dop.drive_g = drive_g;
    if (dop.lba >= GET_GLOBAL(drive_g->sectors)) {
        warn_invalid(regs);
        disk_ret(regs, DISK_RET_EPARAM);
        return;
    }

    dop.buf_fl = SEGOFF_TO_FLATPTR(GET_INT13EXT(regs, data));
    dop.count = GET_INT13EXT(regs, count);
    if (! dop.count) {
        // Nothing to do.
        disk_ret(regs, DISK_RET_SUCCESS);
        return;
    }

    int status = send_disk_op(&dop);

    SET_INT13EXT(regs, count, dop.count);

    disk_ret(regs, status);
}
Пример #14
0
static void
intel_155f40(struct bregs *regs)
{
    regs->ax = 0x005f;
    regs->cl = GET_GLOBAL(IntelDisplayId);
    set_success(regs);
}
Пример #15
0
// Route command to low-level handler.
static int
cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
{
    u8 type = GET_GLOBAL(op->drive_g->type);
    switch (type) {
    case DTYPE_ATA_ATAPI:
        return atapi_cmd_data(op, cdbcmd, blocksize);
    case DTYPE_USB:
        return usb_cmd_data(op, cdbcmd, blocksize);
    case DTYPE_UAS:
        return uas_cmd_data(op, cdbcmd, blocksize);
    case DTYPE_AHCI_ATAPI:
        return ahci_cmd_data(op, cdbcmd, blocksize);
    case DTYPE_VIRTIO_SCSI:
        return virtio_scsi_cmd_data(op, cdbcmd, blocksize);
    case DTYPE_LSI_SCSI:
        return lsi_scsi_cmd_data(op, cdbcmd, blocksize);
    case DTYPE_ESP_SCSI:
        return esp_scsi_cmd_data(op, cdbcmd, blocksize);
    case DTYPE_MEGASAS:
        return megasas_cmd_data(op, cdbcmd, blocksize);
    default:
        op->count = 0;
        return DISK_RET_EPARAM;
    }
}
Пример #16
0
// INT 13h Fixed Disk Services Entry Point
void VISIBLE16
handle_13(struct bregs *regs)
{
    debug_enter(regs, DEBUG_HDL_13);
    u8 extdrive = regs->dl;

    if (CONFIG_CDROM_EMU) {
        if (regs->ah == 0x4b) {
            cdemu_134b(regs);
            return;
        }
        u16 ebda_seg = get_ebda_seg();
        if (GET_EBDA2(ebda_seg, cdemu.active)) {
            u8 emudrive = GET_EBDA2(ebda_seg, cdemu.emulated_extdrive);
            if (extdrive == emudrive) {
                // Access to an emulated drive.
                struct drive_s *cdemu = GET_GLOBAL(cdemu_drive);
                if (regs->ah > 0x16) {
                    // Only old-style commands supported.
                    disk_13XX(regs, cdemu);
                    return;
                }
                disk_13(regs, cdemu);
                return;
            }
            if (extdrive < EXTSTART_CD && ((emudrive ^ extdrive) & 0x80) == 0)
                // Adjust id to make room for emulated drive.
                extdrive--;
        }
    }
    handle_legacy_disk(regs, extdrive);
}
Пример #17
0
static int
ramdisk_copy(struct disk_op_s *op, int iswrite)
{
    u32 offset = GET_GLOBAL(op->drive_g->cntl_id);
    offset += (u32)op->lba * DISK_SECTOR_SIZE;
    u64 opd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)op->buf_fl);
    u64 ramd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE(offset);

    u64 gdt[6];
    if (iswrite) {
        gdt[2] = opd;
        gdt[3] = ramd;
    } else {
        gdt[2] = ramd;
        gdt[3] = opd;
    }

    // Call int 1587 to copy data.
    struct bregs br;
    memset(&br, 0, sizeof(br));
    br.flags = F_CF|F_IF;
    br.ah = 0x87;
    br.es = GET_SEG(SS);
    br.si = (u32)gdt;
    br.cx = op->count * DISK_SECTOR_SIZE / 2;
    call16_int(0x15, &br);

    if (br.flags & F_CF)
        return DISK_RET_EBADTRACK;
    return DISK_RET_SUCCESS;
}
Пример #18
0
static int
cdemu_read(struct disk_op_s *op)
{
    struct drive_s *drive_g;
    drive_g = GLOBALFLAT2GLOBAL(GET_LOW(CDEmu.emulated_drive_gf));
    struct disk_op_s dop;
    dop.drive_g = drive_g;
    dop.command = op->command;
    dop.lba = GET_LOW(CDEmu.ilba) + op->lba / 4;

    int count = op->count;
    op->count = 0;
    u8 *cdbuf_fl = GET_GLOBAL(bounce_buf_fl);

    if (op->lba & 3) {
        // Partial read of first block.
        dop.count = 1;
        dop.buf_fl = cdbuf_fl;
        int ret = process_op(&dop);
        if (ret)
            return ret;
        u8 thiscount = 4 - (op->lba & 3);
        if (thiscount > count)
            thiscount = count;
        count -= thiscount;
        memcpy_fl(op->buf_fl, cdbuf_fl + (op->lba & 3) * 512, thiscount * 512);
        op->buf_fl += thiscount * 512;
        op->count += thiscount;
        dop.lba++;
    }

    if (count > 3) {
        // Read n number of regular blocks.
        dop.count = count / 4;
        dop.buf_fl = op->buf_fl;
        int ret = process_op(&dop);
        op->count += dop.count * 4;
        if (ret)
            return ret;
        u8 thiscount = count & ~3;
        count &= 3;
        op->buf_fl += thiscount * 512;
        dop.lba += thiscount / 4;
    }

    if (count) {
        // Partial read on last block.
        dop.count = 1;
        dop.buf_fl = cdbuf_fl;
        int ret = process_op(&dop);
        if (ret)
            return ret;
        u8 thiscount = count;
        memcpy_fl(op->buf_fl, cdbuf_fl, thiscount * 512);
        op->count += thiscount;
    }

    return DISK_RET_SUCCESS;
}
Пример #19
0
static void
smi_157f02(struct bregs *regs)
{
    /* Boot Display Device Override */
    regs->ax = 0x007f;
    regs->bl = GET_GLOBAL(SmiBootDisplay);
    set_success(regs);
}
Пример #20
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;
}
Пример #21
0
// Handle a USB key press/release event.
static void
procscankey(u8 key, u8 key_release, u8 mods)
{
    if (key >= ARRAY_SIZE(KeyToScanCode))
        return;
    u16 scancode = GET_GLOBAL(KeyToScanCode[key]);
    if (scancode)
        prockeys(scancode, key_release, mods);
}
Пример #22
0
static void
fillLCHS(struct drive_s *drive_g, u16 *nlc, u16 *nlh, u16 *nlspt)
{
    if (CONFIG_CDROM_EMU && drive_g == GET_GLOBAL(cdemu_drive)) {
        // Emulated drive - get info from ebda.  (It's not possible to
        // populate the geometry directly in the driveid because the
        // geometry is only known after the bios segment is made
        // read-only).
        u16 ebda_seg = get_ebda_seg();
        *nlc = GET_EBDA2(ebda_seg, cdemu.lchs.cylinders);
        *nlh = GET_EBDA2(ebda_seg, cdemu.lchs.heads);
        *nlspt = GET_EBDA2(ebda_seg, cdemu.lchs.spt);
        return;
    }
    *nlc = GET_GLOBAL(drive_g->lchs.cylinders);
    *nlh = GET_GLOBAL(drive_g->lchs.heads);
    *nlspt = GET_GLOBAL(drive_g->lchs.spt);
}
Пример #23
0
// Write sectors.
int
cdb_write(struct disk_op_s *op)
{
    struct cdb_rwdata_10 cmd;
    memset(&cmd, 0, sizeof(cmd));
    cmd.command = CDB_CMD_WRITE_10;
    cmd.lba = cpu_to_be32(op->lba);
    cmd.count = cpu_to_be16(op->count);
    return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
}
Пример #24
0
static u8
bochsvga_dispi_enabled(void)
{
    if (!GET_GLOBAL(dispi_found))
        return 0;
    u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE);
    if (!(en & VBE_DISPI_ENABLED))
        return 0;
    return 1;
}
Пример #25
0
// installation check
static void
handle_1ab101(struct bregs *regs)
{
    regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
    regs->bx = 0x0210; // PCI version 2.10
    regs->cl = GET_GLOBAL(MaxPCIBus);
    regs->edx = 0x20494350; // "PCI "
    regs->edi = (u32)entry_pcibios32 + BUILD_BIOS_ADDR;
    set_code_success(regs);
}
Пример #26
0
struct drive_s *
getDrive(u8 exttype, u8 extdriveoffset)
{
    if (extdriveoffset >= ARRAY_SIZE(IDMap[0]))
        return NULL;
    struct drive_s *drive_gf = GET_GLOBAL(IDMap[exttype][extdriveoffset]);
    if (!drive_gf)
        return NULL;
    return GLOBALFLAT2GLOBAL(drive_gf);
}
Пример #27
0
// Read sectors.
int
cdb_read(struct disk_op_s *op)
{
    struct cdb_rwdata_10 cmd;
    memset(&cmd, 0, sizeof(cmd));
    cmd.command = CDB_CMD_READ_10;
    cmd.lba = htonl(op->lba);
    cmd.count = htons(op->count);
    return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
}
Пример #28
0
struct vgamode_s *
find_vga_entry(u8 mode)
{
    int i;
    for (i = 0; i < ARRAY_SIZE(vga_modes); i++) {
        struct vgamode_s *vmode_g = &vga_modes[i];
        if (GET_GLOBAL(vmode_g->svgamode) == mode)
            return vmode_g;
    }
    return NULL;
}
Пример #29
0
// Output a string that is in the CS segment.
static void
puts_cs(struct putcinfo *action, const char *s)
{
    char *vs = (char*)s;
    for (;; vs++) {
        char c = GET_GLOBAL(*vs);
        if (!c)
            break;
        putc(action, c);
    }
}
Пример #30
0
// Check for drive RDY for 16bit interface command.
static int
isready(struct atadrive_s *adrive_g)
{
    // Read the status from controller
    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
    u8 status = inb(iobase1 + ATA_CB_STAT);
    if ((status & (ATA_CB_STAT_BSY|ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY)
        return DISK_RET_SUCCESS;
    return DISK_RET_ENOTREADY;
}