--- qemu/roms/seabios/src/cdrom.c 2018/04/24 17:51:53 1.1.1.2 +++ qemu/roms/seabios/src/cdrom.c 2018/04/24 19:43:31 1.1.1.6 @@ -10,17 +10,21 @@ #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; + 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 +32,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(bounce_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 +45,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 +68,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 +103,24 @@ process_cdemu_op(struct disk_op_s *op) } } -struct drive_s *cdemu_drive VAR16VISIBLE; - void cdemu_setup(void) { if (!CONFIG_CDROM_EMU) return; + if (!CDCount) + return; + if (bounce_buf_init() < 0) + return; - struct drive_s *drive_g = allocDrive(); + struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g)); if (!drive_g) { - cdemu_drive = NULL; + warn_noalloc(); + free(drive_g); return; } - cdemu_drive = ADJUST_GLOBAL_PTR(drive_g); + cdemu_drive_gf = drive_g; + 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 +154,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 +172,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,118 +184,26 @@ 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) -{ - dprintf(6, "atapi_is_ready (drive=%p)\n", 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; - int in_progress = 0; - u64 end = calc_future_tsc(5000); - for (;;) { - if (check_time(end)) { - dprintf(1, "read capacity failed\n"); - return -1; - } - - int ret = atapi_read_capacity(drive_g, &blksize, §ors); - if (!ret) - // Success - break; - - u8 asc, ascq; - ret = atapi_get_sense(drive_g, &asc, &ascq); - if (ret) - // Error - retry. - continue; - - // Sense succeeded. - if (asc == 0x3a) { /* MEDIUM NOT PRESENT */ - dprintf(1, "Device reports MEDIUM NOT PRESENT\n"); - return -1; - } - - if (asc == 0x04 && ascq == 0x01 && !in_progress) { - /* IN PROGRESS OF BECOMING READY */ - printf("Waiting for device to detect medium... "); - /* Allow 30 seconds more */ - end = calc_future_tsc(30000); - in_progress = 1; - } - } - - if (blksize != GET_GLOBAL(drive_g->blksize)) { - printf("Unsupported sector size %u\n", blksize); - return -1; - } - - dprintf(6, "sectors=%u\n", sectors); - printf("%dMB medium detected\n", sectors>>(20-11)); - return 0; -} - int -cdrom_boot(int cdid) +cdrom_boot(struct drive_s *drive_g) { - struct drive_s *drive_g = getDrive(EXTTYPE_CD, cdid); - if (!drive_g) + 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 = atapi_is_ready(drive_g); + int ret = scsi_is_ready(&dop); if (ret) - dprintf(1, "atapi_is_ready returned %d\n", ret); + dprintf(1, "scsi_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 +218,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 +241,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 +259,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 +270,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 +278,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) {