--- qemu/roms/seabios/src/cdrom.c 2018/04/24 17:36:47 1.1 +++ qemu/roms/seabios/src/cdrom.c 2018/04/24 18:27:19 1.1.1.3 @@ -10,17 +10,22 @@ #include "bregs.h" // struct bregs #include "biosvar.h" // GET_EBDA #include "ata.h" // ATA_CMD_REQUEST_SENSE +#include "blockcmd.h" // CDB_CMD_REQUEST_SENSE /**************************************************************** * CD emulation ****************************************************************/ +struct drive_s *cdemu_drive_gf VAR16VISIBLE; +u8 *cdemu_buf_fl VAR16VISIBLE; + static int cdemu_read(struct disk_op_s *op) { u16 ebda_seg = get_ebda_seg(); - struct drive_s *drive_g = GET_EBDA2(ebda_seg, cdemu.emulated_drive); + struct drive_s *drive_g; + drive_g = GLOBALFLAT2GLOBAL(GET_EBDA2(ebda_seg, cdemu.emulated_drive_gf)); struct disk_op_s dop; dop.drive_g = drive_g; dop.command = op->command; @@ -28,12 +33,12 @@ cdemu_read(struct disk_op_s *op) int count = op->count; op->count = 0; - u8 *cdbuf_far = (void*)offsetof(struct extended_bios_data_area_s, cdemu_buf); + u8 *cdbuf_fl = GET_GLOBAL(cdemu_buf_fl); if (op->lba & 3) { // Partial read of first block. dop.count = 1; - dop.buf_fl = MAKE_FLATPTR(ebda_seg, cdbuf_far); + dop.buf_fl = cdbuf_fl; int ret = process_op(&dop); if (ret) return ret; @@ -41,10 +46,7 @@ cdemu_read(struct disk_op_s *op) if (thiscount > count) thiscount = count; count -= thiscount; - memcpy_far(FLATPTR_TO_SEG(op->buf_fl) - , (void*)FLATPTR_TO_OFFSET(op->buf_fl) - , ebda_seg, cdbuf_far + (op->lba & 3) * 512 - , thiscount * 512); + memcpy_fl(op->buf_fl, cdbuf_fl + (op->lba & 3) * 512, thiscount * 512); op->buf_fl += thiscount * 512; op->count += thiscount; dop.lba++; @@ -67,14 +69,12 @@ cdemu_read(struct disk_op_s *op) if (count) { // Partial read on last block. dop.count = 1; - dop.buf_fl = MAKE_FLATPTR(ebda_seg, cdbuf_far); + dop.buf_fl = cdbuf_fl; int ret = process_op(&dop); if (ret) return ret; u8 thiscount = count; - memcpy_far(FLATPTR_TO_SEG(op->buf_fl) - , (void*)FLATPTR_TO_OFFSET(op->buf_fl) - , ebda_seg, cdbuf_far, thiscount * 512); + memcpy_fl(op->buf_fl, cdbuf_fl, thiscount * 512); op->count += thiscount; } @@ -104,20 +104,27 @@ process_cdemu_op(struct disk_op_s *op) } } -struct drive_s *cdemu_drive VAR16VISIBLE; - void -cdemu_setup() +cdemu_setup(void) { if (!CONFIG_CDROM_EMU) return; + cdemu_drive_gf = NULL; + cdemu_buf_fl = NULL; + if (!Drives.cdcount) + return; - struct drive_s *drive_g = allocDrive(); - if (!drive_g) { - cdemu_drive = NULL; + struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g)); + u8 *buf = malloc_low(CDROM_SECTOR_SIZE); + if (!drive_g || !buf) { + warn_noalloc(); + free(drive_g); + free(buf); return; } - cdemu_drive = ADJUST_GLOBAL_PTR(drive_g); + cdemu_drive_gf = drive_g; + cdemu_buf_fl = buf; + memset(drive_g, 0, sizeof(*drive_g)); drive_g->type = DTYPE_CDEMU; drive_g->blksize = DISK_SECTOR_SIZE; drive_g->sectors = (u64)-1; @@ -151,8 +158,10 @@ cdemu_134b(struct bregs *regs) SET_INT13ET(regs, media, GET_EBDA2(ebda_seg, cdemu.media)); SET_INT13ET(regs, emulated_drive , GET_EBDA2(ebda_seg, cdemu.emulated_extdrive)); - struct drive_s *drive_g = GET_EBDA2(ebda_seg, cdemu.emulated_drive); - u8 cntl_id = GET_GLOBAL(drive_g->cntl_id); + struct drive_s *drive_gf = GET_EBDA2(ebda_seg, cdemu.emulated_drive_gf); + u8 cntl_id = 0; + if (drive_gf) + cntl_id = GET_GLOBALFLAT(drive_gf->cntl_id); SET_INT13ET(regs, controller_index, cntl_id / 2); SET_INT13ET(regs, device_spec, cntl_id % 2); SET_INT13ET(regs, ilba, GET_EBDA2(ebda_seg, cdemu.ilba)); @@ -167,6 +176,8 @@ cdemu_134b(struct bregs *regs) if (regs->al == 0x00) { // FIXME ElTorito Various. Should be handled accordingly to spec SET_EBDA2(ebda_seg, cdemu.active, 0x00); // bye bye + + // XXX - update floppy/hd count. } disk_ret(regs, DISK_RET_SUCCESS); @@ -177,80 +188,41 @@ cdemu_134b(struct bregs *regs) * CD booting ****************************************************************/ -// Request SENSE -static int -atapi_get_sense(struct drive_s *drive_g, u8 *asc, u8 *ascq) -{ - u8 atacmd[12], buffer[18]; - memset(atacmd, 0, sizeof(atacmd)); - atacmd[0] = ATA_CMD_REQUEST_SENSE; - atacmd[4] = sizeof(buffer); - int ret = ata_cmd_packet(drive_g, atacmd, sizeof(atacmd), sizeof(buffer) - , MAKE_FLATPTR(GET_SEG(SS), buffer)); - if (ret) - return ret; - - *asc = buffer[12]; - *ascq = buffer[13]; - - return 0; -} - -// Request capacity -static int -atapi_read_capacity(struct drive_s *drive_g, u32 *blksize, u32 *sectors) -{ - u8 packet[12], buf[8]; - memset(packet, 0, sizeof(packet)); - packet[0] = 0x25; /* READ CAPACITY */ - int ret = ata_cmd_packet(drive_g, packet, sizeof(packet), sizeof(buf) - , MAKE_FLATPTR(GET_SEG(SS), buf)); - if (ret) - return ret; - - *blksize = (((u32)buf[4] << 24) | ((u32)buf[5] << 16) - | ((u32)buf[6] << 8) | ((u32)buf[7] << 0)); - *sectors = (((u32)buf[0] << 24) | ((u32)buf[1] << 16) - | ((u32)buf[2] << 8) | ((u32)buf[3] << 0)); - - return 0; -} - static int -atapi_is_ready(struct drive_s *drive_g) +atapi_is_ready(struct disk_op_s *op) { - dprintf(6, "atapi_is_ready (drive=%p)\n", drive_g); + dprintf(6, "atapi_is_ready (drive=%p)\n", op->drive_g); /* Retry READ CAPACITY for 5 seconds unless MEDIUM NOT PRESENT is * reported by the device. If the device reports "IN PROGRESS", * 30 seconds is added. */ - u32 blksize, sectors; + struct cdbres_read_capacity info; int in_progress = 0; u64 end = calc_future_tsc(5000); for (;;) { - if (check_time(end)) { + if (check_tsc(end)) { dprintf(1, "read capacity failed\n"); return -1; } - int ret = atapi_read_capacity(drive_g, &blksize, §ors); + int ret = cdb_read_capacity(op, &info); if (!ret) // Success break; - u8 asc, ascq; - ret = atapi_get_sense(drive_g, &asc, &ascq); + struct cdbres_request_sense sense; + ret = cdb_get_sense(op, &sense); if (ret) // Error - retry. continue; // Sense succeeded. - if (asc == 0x3a) { /* MEDIUM NOT PRESENT */ + if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */ dprintf(1, "Device reports MEDIUM NOT PRESENT\n"); return -1; } - if (asc == 0x04 && ascq == 0x01 && !in_progress) { + if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) { /* IN PROGRESS OF BECOMING READY */ printf("Waiting for device to detect medium... "); /* Allow 30 seconds more */ @@ -259,7 +231,8 @@ atapi_is_ready(struct drive_s *drive_g) } } - if (blksize != GET_GLOBAL(drive_g->blksize)) { + u32 blksize = ntohl(info.blksize), sectors = ntohl(info.sectors); + if (blksize != GET_GLOBAL(op->drive_g->blksize)) { printf("Unsupported sector size %u\n", blksize); return -1; } @@ -272,23 +245,22 @@ atapi_is_ready(struct drive_s *drive_g) int cdrom_boot(int cdid) { - struct drive_s *drive_g = getDrive(EXTTYPE_CD, cdid); - if (!drive_g) + struct disk_op_s dop; + memset(&dop, 0, sizeof(dop)); + dop.drive_g = getDrive(EXTTYPE_CD, cdid); + if (!dop.drive_g) return 1; - int ret = atapi_is_ready(drive_g); + int ret = atapi_is_ready(&dop); if (ret) dprintf(1, "atapi_is_ready returned %d\n", ret); // Read the Boot Record Volume Descriptor u8 buffer[2048]; - struct disk_op_s dop; - memset(&dop, 0, sizeof(dop)); - dop.drive_g = drive_g; dop.lba = 0x11; dop.count = 1; dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer); - ret = cdrom_read(&dop); + ret = cdb_read(&dop); if (ret) return 3; @@ -303,7 +275,8 @@ cdrom_boot(int cdid) // And we read the Boot Catalog dop.lba = lba; - ret = cdrom_read(&dop); + dop.count = 1; + ret = cdb_read(&dop); if (ret) return 7; @@ -325,7 +298,7 @@ cdrom_boot(int cdid) u8 media = buffer[0x21]; SET_EBDA2(ebda_seg, cdemu.media, media); - SET_EBDA2(ebda_seg, cdemu.emulated_drive, ADJUST_GLOBAL_PTR(drive_g)); + SET_EBDA2(ebda_seg, cdemu.emulated_drive_gf, dop.drive_g); u16 boot_segment = *(u16*)&buffer[0x22]; if (!boot_segment) @@ -343,7 +316,7 @@ cdrom_boot(int cdid) dop.lba = lba; dop.count = DIV_ROUND_UP(nbsectors, 4); dop.buf_fl = MAKE_FLATPTR(boot_segment, 0); - ret = cdrom_read(&dop); + ret = cdb_read(&dop); if (ret) return 12; @@ -354,7 +327,7 @@ cdrom_boot(int cdid) } // Emulation of a floppy/harddisk requested - if (! CONFIG_CDROM_EMU || !cdemu_drive) + if (! CONFIG_CDROM_EMU || !cdemu_drive_gf) return 13; // Set emulated drive id and increase bios installed hardware @@ -362,6 +335,7 @@ cdrom_boot(int cdid) if (media < 4) { // Floppy emulation SET_EBDA2(ebda_seg, cdemu.emulated_extdrive, 0x00); + // XXX - get and set actual floppy count. SETBITS_BDA(equipment_list_flags, 0x41); switch (media) {