diff --git a/src/devices/cdrom/cdrom.c b/src/devices/cdrom/cdrom.c index 7aaf775..9920379 100644 --- a/src/devices/cdrom/cdrom.c +++ b/src/devices/cdrom/cdrom.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.c 1.0.16 2018/10/05 + * Version: @(#)cdrom.c 1.0.17 2018/10/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1832,6 +1832,15 @@ cdrom_command(cdrom_t *dev, uint8_t *cdb) should forget about the not ready, and report unit attention straight away. */ cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); max_len = cdb[4]; + + if (!max_len) { + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20LL * CDROM_TIME; + cdrom_set_callback(dev); + break; + } + cdrom_buf_alloc(dev, 256); cdrom_set_buf_len(dev, BufLen, &max_len); cdrom_request_sense(dev, cdbufferb, max_len); diff --git a/src/devices/disk/hdd.h b/src/devices/disk/hdd.h index a02235e..0ca1852 100644 --- a/src/devices/disk/hdd.h +++ b/src/devices/disk/hdd.h @@ -57,8 +57,7 @@ enum { #define HDD_BUS_MAX (HDD_BUS_USB) /* USB exclusive */ -typedef struct vhd_footer_t -{ +typedef struct { uint8_t cookie[8]; uint32_t features; uint32_t version; diff --git a/src/devices/disk/hdd_image.c b/src/devices/disk/hdd_image.c index 5be88a5..82a82e2 100644 --- a/src/devices/disk/hdd_image.c +++ b/src/devices/disk/hdd_image.c @@ -14,7 +14,7 @@ * merged with hdd.c, since that is the scope of hdd.c. The * actual format handlers can then be in hdd_format.c etc. * - * Version: @(#)hdd_image.c 1.0.7 2018/10/01 + * Version: @(#)hdd_image.c 1.0.8 2018/10/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -95,10 +95,6 @@ int hdd_image_do_log = ENABLE_HDD_LOG; hdd_image_t hdd_images[HDD_NUM]; -static char empty_sector[512]; -static char *empty_sector_1mb; - - void hdd_image_log(int level, const char *fmt, ...) { @@ -480,33 +476,37 @@ hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size) static int -prepare_new_hard_disk(uint8_t id, uint64_t full_size) +prepare_new_hard_disk(hdd_image_t *img, uint64_t full_size) { - uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file); + uint64_t target_size; + uint8_t *bufp; + uint32_t r, t; + uint32_t i, k; - uint32_t size; - uint32_t t, i; + /* Make sure we start writing at the beginning. */ + target_size = (full_size + img->base) - ftello64(img->file); +#if 0 + fseeko64(img->file, 0ULL, SEEK_SET); +#endif - t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */ - size = (uint32_t) (target_size & 0xfffff); /* 1 MB mask. */ + k = (1 << 20); /* 1048576 bytes, 1MB */ + t = (uint32_t) (target_size / k); /* number of full 1MB blocks */ + r = (uint32_t) (target_size & (k - 1)); /* remainder, if any */ - empty_sector_1mb = (char *)mem_alloc(1048576); - memset(empty_sector_1mb, 0, 1048576); + bufp = (uint8_t *)mem_alloc(k); + memset(bufp, 0x00, k); - /* First, write all the 1 MB blocks. */ - if (t > 0) { - for (i = 0; i < t; i++) - fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file); - } + /* First, write all the 1MB blocks (if any.) */ + for (i = 0; i < t; i++) + fwrite((uint8_t *)bufp, 1, k, img->file); /* Then, write the remainder. */ - fwrite(empty_sector_1mb, 1, size, hdd_images[id].file); + fwrite((uint8_t *)bufp, 1, r, img->file); - free(empty_sector_1mb); + free(bufp); - hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - - hdd_images[id].loaded = 1; + img->last_sector = (uint32_t) (full_size >> 9) - 1; + img->loaded = 1; return 1; } @@ -525,6 +525,7 @@ hdd_image_init(void) int hdd_image_load(int id) { + hdd_image_t *img = &hdd_images[id]; uint32_t sector_size = 512; uint32_t zero = 0; uint64_t signature = 0xD778A82044445459ll; @@ -536,29 +537,29 @@ hdd_image_load(int id) int is_hdx[2] = { 0, 0 }; int is_vhd[2] = { 0, 0 }; vhd_footer_t *vft = NULL; + uint8_t *empty; - memset(empty_sector, 0, sizeof(empty_sector)); + img->base = 0; - hdd_images[id].base = 0; is_vhd[0] = image_is_vhd(fn, 0); is_vhd[1] = image_is_vhd(fn, 1); - if (hdd_images[id].loaded) { - if (hdd_images[id].file) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; + if (img->loaded) { + if (img->file) { + (void)fclose(img->file); + img->file = NULL; } - hdd_images[id].loaded = 0; + img->loaded = 0; } is_hdx[0] = image_is_hdx(fn, 0); is_hdx[1] = image_is_hdx(fn, 1); - hdd_images[id].pos = 0; + img->pos = 0; /* Try to open existing hard disk image */ - hdd_images[id].file = plat_fopen(fn, L"rb+"); - if (hdd_images[id].file == NULL) { + img->file = plat_fopen(fn, L"rb+"); + if (img->file == NULL) { /* Failed to open existing hard disk image */ if (errno == ENOENT) { /* Failed because it does not exist, @@ -569,8 +570,8 @@ hdd_image_load(int id) return 0; } - hdd_images[id].file = plat_fopen(fn, L"wb+"); - if (hdd_images[id].file == NULL) { + img->file = plat_fopen(fn, L"wb+"); + if (img->file == NULL) { DEBUG("Unable to open image\n"); memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; @@ -579,48 +580,47 @@ hdd_image_load(int id) full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; - hdd_images[id].base = 0x1000; - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file); - fwrite(&full_size, 1, 4, hdd_images[id].file); - fwrite(§or_size, 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); + img->base = 0x1000; + fwrite(&zero, 1, 4, img->file); + fwrite(&zero, 1, 4, img->file); + fwrite(&(img->base), 1, 4, img->file); + fwrite(&full_size, 1, 4, img->file); + fwrite(§or_size, 1, 4, img->file); + fwrite(&(hdd[id].spt), 1, 4, img->file); + fwrite(&(hdd[id].hpc), 1, 4, img->file); + fwrite(&(hdd[id].tracks), 1, 4, img->file); for (c = 0; c < 0x3f8; c++) - fwrite(&zero, 1, 4, hdd_images[id].file); - hdd_images[id].type = 1; + fwrite(&zero, 1, 4, img->file); + img->type = 1; } else if (is_hdx[0]) { full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; - hdd_images[id].base = 0x28; - fwrite(&signature, 1, 8, hdd_images[id].file); - fwrite(&full_size, 1, 8, hdd_images[id].file); - fwrite(§or_size, 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - hdd_images[id].type = 2; + img->base = 0x28; + fwrite(&signature, 1, 8, img->file); + fwrite(&full_size, 1, 8, img->file); + fwrite(§or_size, 1, 4, img->file); + fwrite(&(hdd[id].spt), 1, 4, img->file); + fwrite(&(hdd[id].hpc), 1, 4, img->file); + fwrite(&(hdd[id].tracks), 1, 4, img->file); + fwrite(&zero, 1, 4, img->file); + fwrite(&zero, 1, 4, img->file); + img->type = 2; } else if (is_vhd[1]) { - empty_sector_1mb = (char *)mem_alloc(512); - memset(empty_sector_1mb, 0, 512); - fseeko64(hdd_images[id].file, -512, SEEK_END); - fread(empty_sector_1mb, 1, 512, hdd_images[id].file); + empty = (uint8_t *)mem_alloc(512); + memset(empty, 0x00, 512); + fseeko64(img->file, -512, SEEK_END); + fread(empty, 1, 512, img->file); new_vhd_footer(&vft); - vhd_footer_from_bytes(vft, (uint8_t *) empty_sector_1mb); + vhd_footer_from_bytes(vft, empty); if (vft->type != 2) { /* VHD is not fixed size */ DEBUG("VHD: Image is not fixed size\n"); free(vft); vft = NULL; - free(empty_sector_1mb); - empty_sector_1mb = NULL; - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; + free(empty); + fclose(img->file); + img->file = NULL; memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } @@ -630,45 +630,43 @@ hdd_image_load(int id) hdd[id].spt = vft->geom.spt; free(vft); vft = NULL; - free(empty_sector_1mb); - empty_sector_1mb = NULL; - hdd_images[id].type = 3; + free(empty); + img->type = 3; /* If we're here, this means there is a valid VHD footer in the image, which means that by definition, all valid sectors are there. */ - hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - hdd_images[id].loaded = 1; + img->last_sector = (uint32_t) (full_size >> 9) - 1; + img->loaded = 1; return 1; } else - hdd_images[id].type = 0; - hdd_images[id].last_sector = 0; + img->type = 0; + img->last_sector = 0; } s = full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; - ret = prepare_new_hard_disk(id, full_size); + ret = prepare_new_hard_disk(img, full_size); if (is_vhd[0]) { /* VHD image. */ /* Generate new footer. */ - empty_sector_1mb = (char *)mem_alloc(512); + empty = (uint8_t *)mem_alloc(512); + memset(empty, 0x00, 512); new_vhd_footer(&vft); vft->orig_size = vft->curr_size = full_size; - vft->geom.cyl = tracks; - vft->geom.heads = hpc; - vft->geom.spt = spt; + vft->geom.cyl = hdd[id].tracks; + vft->geom.heads = hdd[id].hpc; + vft->geom.spt = hdd[id].spt; generate_vhd_checksum(vft); - memset(empty_sector_1mb, 0, 512); - vhd_footer_to_bytes((uint8_t *) empty_sector_1mb, vft); - fwrite(empty_sector_1mb, 1, 512, hdd_images[id].file); + vhd_footer_to_bytes(empty, vft); + fseeko64(img->file, 0, SEEK_END); + fwrite(empty, 1, 512, img->file); free(vft); - vft = NULL; - free(empty_sector_1mb); - empty_sector_1mb = NULL; - hdd_images[id].type = 3; + free(empty); + img->type = 3; } return ret; } else { @@ -679,114 +677,143 @@ hdd_image_load(int id) } } else { if (image_is_hdi(fn)) { - fseeko64(hdd_images[id].file, 0x8, SEEK_SET); - fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0xC, SEEK_SET); + fseeko64(img->file, 0x8, SEEK_SET); + fread(&(img->base), 1, 4, img->file); + fseeko64(img->file, 0xC, SEEK_SET); full_size = 0LL; - fread(&full_size, 1, 4, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0x10, SEEK_SET); - fread(§or_size, 1, 4, hdd_images[id].file); + fread(&full_size, 1, 4, img->file); + fseeko64(img->file, 0x10, SEEK_SET); + fread(§or_size, 1, 4, img->file); if (sector_size != 512) { /* Sector size is not 512 */ DEBUG("HDI: Sector size is not 512\n"); - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; + fclose(img->file); + img->file = NULL; memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - fread(&spt, 1, 4, hdd_images[id].file); - fread(&hpc, 1, 4, hdd_images[id].file); - fread(&tracks, 1, 4, hdd_images[id].file); + fread(&spt, 1, 4, img->file); + fread(&hpc, 1, 4, img->file); + fread(&tracks, 1, 4, img->file); hdd[id].spt = spt; hdd[id].hpc = hpc; hdd[id].tracks = tracks; - hdd_images[id].type = 1; + img->type = 1; } else if (is_hdx[1]) { - hdd_images[id].base = 0x28; - fseeko64(hdd_images[id].file, 8, SEEK_SET); - fread(&full_size, 1, 8, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0x10, SEEK_SET); + img->base = 0x28; + fseeko64(img->file, 8, SEEK_SET); + fread(&full_size, 1, 8, img->file); + fseeko64(img->file, 0x10, SEEK_SET); fread(§or_size, 1, 4, hdd_images[id].file); if (sector_size != 512) { /* Sector size is not 512 */ DEBUG("HDX: Sector size is not 512\n"); - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; + fclose(img->file); + img->file = NULL; memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - fread(&spt, 1, 4, hdd_images[id].file); - fread(&hpc, 1, 4, hdd_images[id].file); - fread(&tracks, 1, 4, hdd_images[id].file); + fread(&spt, 1, 4, img->file); + fread(&hpc, 1, 4, img->file); + fread(&tracks, 1, 4, img->file); hdd[id].spt = spt; hdd[id].hpc = hpc; hdd[id].tracks = tracks; - fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); - fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); - hdd_images[id].type = 2; + fread(&(hdd[id].at_spt), 1, 4, img->file); + fread(&(hdd[id].at_hpc), 1, 4, img->file); + img->type = 2; } else { full_size = ((uint64_t) hdd[id].spt) * ((uint64_t) hdd[id].hpc) * ((uint64_t) hdd[id].tracks) << 9LL; - hdd_images[id].type = 0; + img->type = 0; } } - fseeko64(hdd_images[id].file, 0, SEEK_END); - s = ftello64(hdd_images[id].file); - if (s < (full_size + hdd_images[id].base)) - return prepare_new_hard_disk(id, full_size); - else { - hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - hdd_images[id].loaded = 1; - return 1; + fseeko64(img->file, 0, SEEK_END); + s = ftello64(img->file); + if (s < (full_size + img->base)) { + ret = prepare_new_hard_disk(img, full_size); + } else { + img->last_sector = (uint32_t) (full_size >> 9) - 1; + img->loaded = 1; + ret = 1; } + + if (is_vhd[0]) { + fseeko64(img->file, 0, SEEK_END); + s = ftello64(img->file); + if (s == (full_size + img->base)) { + /* VHD image: generate new footer. */ + empty = (uint8_t *)mem_alloc(512); + memset(empty, 0x00, 512); + new_vhd_footer(&vft); + vft->orig_size = vft->curr_size = full_size; + vft->geom.cyl = hdd[id].tracks; + vft->geom.heads = hdd[id].hpc; + vft->geom.spt = hdd[id].spt; + generate_vhd_checksum(vft); + vhd_footer_to_bytes(empty, vft); + fwrite((uint8_t *)empty, 1, 512, img->file); + free(vft); + free(empty); + img->type = 3; + } + } + + return ret; } void hdd_image_seek(uint8_t id, uint32_t sector) { - off64_t addr = sector; - addr = (uint64_t)sector << 9LL; + hdd_image_t *img = &hdd_images[id]; + off64_t addr = (off64_t)sector << 9LL; - hdd_images[id].pos = sector; + img->pos = sector; - fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET); + fseeko64(img->file, addr + img->base, SEEK_SET); } void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { - hdd_images[id].pos = sector; + hdd_image_t *img = &hdd_images[id]; - fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); - fread(buffer, 1, count << 9, hdd_images[id].file); + img->pos = sector; + + fseeko64(img->file, ((uint64_t)sector << 9LL) + img->base, SEEK_SET); + fread(buffer, 1, count << 9, img->file); } uint32_t hdd_sectors(uint8_t id) { - fseeko64(hdd_images[id].file, 0, SEEK_END); - return (uint32_t) ((ftello64(hdd_images[id].file) - hdd_images[id].base) >> 9); + hdd_image_t *img = &hdd_images[id]; + + fseeko64(img->file, 0, SEEK_END); + + return (uint32_t) ((ftello64(img->file) - img->base) >> 9); } int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { + hdd_image_t *img = &hdd_images[id]; uint32_t transfer_sectors = count; uint32_t sectors = hdd_sectors(id); if ((sectors - sector) < transfer_sectors) transfer_sectors = sectors - sector; - hdd_images[id].pos = sector; + img->pos = sector; - fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); - fread(buffer, 1, transfer_sectors << 9, hdd_images[id].file); + fseeko64(img->file, ((uint64_t)sector << 9LL) + img->base, SEEK_SET); + fread(buffer, 1, transfer_sectors << 9, img->file); if (count != transfer_sectors) return 1; @@ -798,29 +825,33 @@ hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { - hdd_images[id].pos = sector; + hdd_image_t *img = &hdd_images[id]; - fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); - fwrite(buffer, count << 9, 1, hdd_images[id].file); + img->pos = sector; + + fseeko64(img->file, ((uint64_t)sector << 9LL) + img->base, SEEK_SET); + fwrite(buffer, count << 9, 1, img->file); } int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { + hdd_image_t *img = &hdd_images[id]; uint32_t transfer_sectors = count; uint32_t sectors = hdd_sectors(id); if ((sectors - sector) < transfer_sectors) transfer_sectors = sectors - sector; - hdd_images[id].pos = sector; + img->pos = sector; - fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); - fwrite(buffer, transfer_sectors << 9, 1, hdd_images[id].file); + fseeko64(img->file, ((uint64_t)sector << 9LL) + img->base, SEEK_SET); + fwrite(buffer, transfer_sectors << 9, 1, img->file); if (count != transfer_sectors) return 1; + return 0; } @@ -828,32 +859,41 @@ hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) { + hdd_image_t *img = &hdd_images[id]; + uint8_t empty[512]; uint32_t i = 0; - hdd_images[id].pos = sector; + memset(empty, 0x00, sizeof(empty)); + + img->pos = sector; + + fseeko64(img->file, ((uint64_t)sector << 9LL) + img->base, SEEK_SET); - fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); for (i = 0; i < count; i++) - fwrite(empty_sector, 512, 1, hdd_images[id].file); + fwrite(empty, 512, 1, img->file); } int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count) { - uint32_t i = 0; - + hdd_image_t *img = &hdd_images[id]; + uint8_t empty[512]; uint32_t transfer_sectors = count; uint32_t sectors = hdd_sectors(id); + uint32_t i = 0; if ((sectors - sector) < transfer_sectors) transfer_sectors = sectors - sector; - hdd_images[id].pos = sector; + memset(empty, 0x00, sizeof(empty)); + + img->pos = sector; + + fseeko64(img->file, ((uint64_t)sector << 9LL) + img->base, SEEK_SET); - fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); for (i = 0; i < transfer_sectors; i++) - fwrite(empty_sector, 1, 512, hdd_images[id].file); + fwrite(empty, 1, 512, img->file); if (count != transfer_sectors) return 1; @@ -886,12 +926,16 @@ hdd_image_get_type(uint8_t id) void hdd_image_specify(uint8_t id, int hpc, int spt) { - if (hdd_images[id].type == 2) { + hdd_image_t *img = &hdd_images[id]; + + if (img->type == 2) { hdd[id].at_hpc = hpc; hdd[id].at_spt = spt; - fseeko64(hdd_images[id].file, 0x20, SEEK_SET); - fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); + + fseeko64(img->file, 0x20, SEEK_SET); + + fwrite(&(hdd[id].at_spt), 1, 4, img->file); + fwrite(&(hdd[id].at_hpc), 1, 4, img->file); } } @@ -899,18 +943,20 @@ hdd_image_specify(uint8_t id, int hpc, int spt) void hdd_image_unload(uint8_t id, int fn_preserve) { + hdd_image_t *img = &hdd_images[id]; + if (wcslen(hdd[id].fn) == 0) return; - if (hdd_images[id].loaded) { - if (hdd_images[id].file != NULL) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; + if (img->loaded) { + if (img->file != NULL) { + (void)fclose(img->file); + img->file = NULL; } - hdd_images[id].loaded = 0; + img->loaded = 0; } - hdd_images[id].last_sector = -1; + img->last_sector = -1; memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn)); if (fn_preserve) @@ -922,15 +968,17 @@ hdd_image_unload(uint8_t id, int fn_preserve) void hdd_image_close(uint8_t id) { + hdd_image_t *img = &hdd_images[id]; + DEBUG("hdd_image_close(%i)\n", id); - if (!hdd_images[id].loaded) - return; + if (! img->loaded) return; - if (hdd_images[id].file != NULL) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; + if (img->file != NULL) { + (void)fclose(img->file); + img->file = NULL; } - memset(&hdd_images[id], 0, sizeof(hdd_image_t)); - hdd_images[id].loaded = 0; + + memset(img, 0x00, sizeof(hdd_image_t)); + img->loaded = 0; /* redundant --FvK */ } diff --git a/src/devices/disk/zip.c b/src/devices/disk/zip.c index 0c45da3..61f64e6 100644 --- a/src/devices/disk/zip.c +++ b/src/devices/disk/zip.c @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.c 1.0.15 2018/10/05 + * Version: @(#)zip.c 1.0.16 2018/10/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1684,6 +1684,15 @@ zip_command(zip_t *dev, uint8_t *cdb) should forget about the not ready, and report unit attention straight away. */ zip_set_phase(dev, SCSI_PHASE_DATA_IN); max_len = cdb[4]; + + if (!max_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = ZIP_PHASE_COMPLETE; + dev->callback = 20LL * ZIP_TIME; + zip_set_callback(dev); + break; + } + zip_buf_alloc(dev, 256); zip_set_buf_len(dev, BufLen, &max_len); len = (cdb[1] & 1) ? 8 : 18; diff --git a/src/devices/input/mouse_bus.c b/src/devices/input/mouse_bus.c index 9279957..1af7a3a 100644 --- a/src/devices/input/mouse_bus.c +++ b/src/devices/input/mouse_bus.c @@ -51,7 +51,7 @@ * Microsoft Windows NT 3.1 * Microsoft Windows 98 SE * - * Version: @(#)mouse_bus.c 1.1.0 2018/10/05 + * Version: @(#)mouse_bus.c 1.1.1 2018/10/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -256,6 +256,7 @@ static void lt_write(uint16_t port, uint8_t val, void *priv) { mouse_t *dev = (mouse_t *)priv; + uint8_t bit; DBGLOG(2, "MOUSE: write(%04x, %02x)\n", port, val); @@ -295,6 +296,8 @@ lt_write(uint16_t port, uint8_t val, void *priv) * explains the value: * * D7 = Mode set flag (1 = active) + * This indicates the mode of operation of D7: + * 1 = Mode set, 0 = Bit set/reset * D6,D5 = Mode selection (port A) * 00 = Mode 0 = Basic I/O * 01 = Mode 1 = Strobed I/O @@ -311,17 +314,25 @@ lt_write(uint16_t port, uint8_t val, void *priv) * port, B is an output port, C is split with upper 4 bits * being an output port and lower 4 bits an input port, and * enable the sucker. Courtesy Intel 8255 databook. Lars + * + * 1001 1011 9B 1111 Default state + * 1001 0001 91 1001 Driver-initialized state + * The only difference is - port C upper and port B go from + * input to output. */ dev->conf = val; if (val & DEVICE_ACTIVE) { + /* Mode set/reset - enable this */ + dev->conf = val; dev->flags |= (FLAG_ENABLED | FLAG_TIMER_INT); dev->ctrl = 0x0F & ~IRQ_MASK; - dev->timer = ((int64_t) dev->period) * TIMER_USEC; - dev->timer_enabled = 1LL; } else { - dev->flags &= ~(FLAG_ENABLED | FLAG_TIMER_INT); - dev->timer = 0LL; - dev->timer_enabled = 0LL; + /* Single-bit set/reset */ + bit = 1 << ((val >> 1) & 0x07); /* Bits 3-1 specify the target bit */ + if (val & 1) + dev->ctrl |= bit; /* Set */ + else + dev->ctrl &= ~bit; /* Reset */ } break; } @@ -671,31 +682,39 @@ bm_init(const device_t *info) dev->bn = device_get_config_int("buttons"); mouse_set_buttons(dev->bn); - dev->timer_enabled = 0; - dev->timer = 0LL; + dev->timer_enabled = 0; + dev->timer = 0LL; - dev->delayed_dx = 0; - dev->delayed_dy = 0; - dev->buttons = 0; - dev->buttons_last = 0; - dev->curr_x = 0; - dev->curr_y = 0; - dev->curr_b = 0; + dev->delayed_dx = 0; + dev->delayed_dy = 0; + dev->buttons = 0; + dev->buttons_last = 0; + dev->curr_x = 0; + dev->curr_y = 0; + dev->curr_b = 0; - dev->sig = 0; /* the signature port value */ - dev->cmd = 0; /* command byte */ - dev->toggle = 0; /* signature byte / IRQ bit toggle */ + dev->sig = 0; /* the signature port value */ + dev->cmd = 0; /* command byte */ + dev->toggle = 0; /* signature byte / IRQ bit toggle */ if (dev->flags & FLAG_INPORT) { - dev->ctrl = 0; /* the control port value */ - dev->flags |= FLAG_ENABLED; - dev->period = 0.0; + dev->ctrl = 0; /* the control port value */ + dev->flags |= FLAG_ENABLED; + dev->period = 0.0; + + dev->timer = 0LL; + dev->timer_enabled = 0LL; io_sethandler(dev->base, 4, ms_read,NULL,NULL, ms_write,NULL,NULL, dev); } else { - dev->ctrl = 0x0f; /* the control port value */ - dev->conf = 0x0e; /* the config port value */ - dev->period = 1000000.0 / ((double) device_get_config_int("hz")); + dev->ctrl = 0x0f; /* the control port value */ + dev->conf = 0x9b; /* the config port value - 0x9b is the + default state of the 8255: all ports + are set to input */ + dev->period = 1000000.0 / ((double) device_get_config_int("hz")); + + dev->timer = ((int64_t) dev->period) * TIMER_USEC; + dev->timer_enabled = 1LL; io_sethandler(dev->base, 4, lt_read,NULL,NULL, lt_write,NULL,NULL, dev); diff --git a/src/devices/network/net_3com.h b/src/devices/network/net_3com.h index 8312c59..f06b849 100644 --- a/src/devices/network/net_3com.h +++ b/src/devices/network/net_3com.h @@ -8,7 +8,7 @@ * * Definitions for the 3Com series of ethernet controllers. * - * Version: @(#)net_3com.h 1.0.1 2018/09/07 + * Version: @(#)net_3com.h 1.0.2 2018/10/12 * * Author: Fred N. van Kempen, * diff --git a/src/devices/ports/game.c b/src/devices/ports/game.c index 200fda9..dee5b2e 100644 --- a/src/devices/ports/game.c +++ b/src/devices/ports/game.c @@ -8,7 +8,7 @@ * * Implementation of a generic Game Port. * - * Version: @(#)game.c 1.0.15 2018/09/22 + * Version: @(#)game.c 1.0.16 2018/10/12 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -80,7 +80,7 @@ void game_log(int level, const char *fmt, ...) { #ifdef ENABLE_GAME_LOG - va_list ap; + va_list ap; if (game_do_log >= level) { va_start(ap, fmt); diff --git a/src/devices/scsi/scsi_disk.c b/src/devices/scsi/scsi_disk.c index 9de9afc..5402549 100644 --- a/src/devices/scsi/scsi_disk.c +++ b/src/devices/scsi/scsi_disk.c @@ -8,7 +8,7 @@ * * Emulation of SCSI fixed disks. * - * Version: @(#)scsi_disk.c 1.0.12 2018/10/05 + * Version: @(#)scsi_disk.c 1.0.13 2018/10/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -738,6 +738,14 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE should forget about the not ready, and report unit attention straight away. */ len = cdb[4]; + + if (!len) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; + break; + } + scsi_disk_set_buf_len(dev, BufLen, &len); if (*BufLen < cdb[4]) diff --git a/src/devices/scsi/scsi_ncr5380.c b/src/devices/scsi/scsi_ncr5380.c index d60fc61..671628d 100644 --- a/src/devices/scsi/scsi_ncr5380.c +++ b/src/devices/scsi/scsi_ncr5380.c @@ -11,7 +11,7 @@ * * NOTE: This code now only supports targets at LUN=0 !! * - * Version: @(#)scsi_ncr5380.c 1.0.9 2018/10/07 + * Version: @(#)scsi_ncr5380.c 1.0.10 2018/10/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -143,39 +143,34 @@ typedef struct { typedef struct { const char *name; + uint32_t rom_addr; uint16_t base; int8_t irq; int8_t type; - rom_t bios_rom; - mem_map_t mapping; - uint8_t block_count; - int block_count_loaded; - uint8_t status_ctrl; - uint8_t buffer[128]; + int8_t dma_enabled; + int8_t ncr_busy; + + int block_count_loaded; int buffer_pos; int buffer_host_pos; - uint8_t int_ram[0x40]; - uint8_t ext_ram[0x600]; - - ncr_t ncr; - int ncr_busy; - - int is_non_data_mode; - - int dma_enabled; - int64_t timer_period; int64_t timer_enabled; - - int64_t media_period, - temp_period; double period; + + ncr_t ncr; + + rom_t bios_rom; + mem_map_t mapping; + + uint8_t buffer[128], + int_ram[0x40], + ext_ram[0x600]; } ncr5380_t; @@ -195,8 +190,7 @@ typedef struct { ncr->cur_bus = (ncr->cur_bus & ~(SCSI_PHASE_MESSAGE_IN)) | \ (state & (SCSI_PHASE_MESSAGE_IN)) - -static void ncr_callback(void *priv); +static const int cmd_len[8] = {6, 10, 10, 6, 16, 12, 6, 6}; static int @@ -212,24 +206,6 @@ get_dev_id(uint8_t data) } -/* get the length of a SCSI command based on its command byte type */ -static int -get_cmd_len(int cbyte) -{ - int len = 12; - int group; - - group = (cbyte >> 5) & 7; - - if (group == 0) - len = 6; - if (group == 1 || group == 2) - len = 10; - - return(len); -} - - static void ncr_reset(ncr_t *ncr) { @@ -271,16 +247,14 @@ get_bus_host(ncr_t *ncr) DEBUG("Busy phase\n"); bus_host |= BUS_BSY; } - if (ncr->icr & ICR_ATN) { + if (ncr->icr & ICR_ATN) bus_host |= BUS_ATN; - } if (ncr->icr & ICR_ACK) { DEBUG("ACK phase\n"); bus_host |= BUS_ACK; } - if (ncr->mode & MODE_ARBITRATE) { + if (ncr->mode & MODE_ARBITRATE) bus_host |= BUS_ARB; - } return(bus_host | BUS_SETDATA(ncr->output_data)); } @@ -292,11 +266,11 @@ ncr_wait_process(ncr5380_t *ncr_dev) ncr_t *ncr = &ncr_dev->ncr; scsi_device_t *dev; - /*Wait processes to handle bus requests*/ + /* Wait processes to handle bus requests. */ DEBUG("Clear REQ=%d\n", ncr->clear_req); if (ncr->clear_req) { ncr->clear_req--; - if (!ncr->clear_req) { + if (! ncr->clear_req) { DEBUG("Prelude to command data\n"); SET_BUS_STATE(ncr, ncr->new_phase); ncr->cur_bus |= BUS_REQ; @@ -305,8 +279,7 @@ ncr_wait_process(ncr5380_t *ncr_dev) if (ncr->wait_data) { ncr->wait_data--; - - if (!ncr->wait_data) { + if (! ncr->wait_data) { dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; SET_BUS_STATE(ncr, ncr->new_phase); @@ -329,8 +302,6 @@ ncr_wait_process(ncr5380_t *ncr_dev) DEBUG("Bus Idle phase\n"); ncr->state = STATE_IDLE; ncr->cur_bus &= ~BUS_BSY; - ncr_dev->media_period = 0LL; - ncr_dev->temp_period = 0LL; } else { ncr->state = STATE_DATAOUT; DEBUG("Data Out bus phase\n"); @@ -341,15 +312,448 @@ ncr_wait_process(ncr5380_t *ncr_dev) if (ncr->wait_complete) { ncr->wait_complete--; - if (!ncr->wait_complete) { + if (! ncr->wait_complete) ncr->cur_bus |= BUS_REQ; - } } ncr->bus_host = ncr->cur_bus; } +static void +ncr_callback(void *priv) +{ + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr_t *ncr = &ncr_dev->ncr; + scsi_device_t *dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + int c = 0; + int64_t p; + uint8_t temp, data; + + DEBUG("NCR: DMA mode=%d\n", ncr->dma_mode); + + ncr_dev->timer_enabled = 0; + + if (((ncr->state == STATE_DATAIN) || (ncr->state == STATE_DATAOUT)) && (ncr->dma_mode != DMA_IDLE)) + ncr_dev->timer_period = (int64_t) ncr_dev->period; + else + ncr_dev->timer_period += 10LL * TIMER_USEC; + + if (ncr->dma_mode == DMA_IDLE) { + ncr->bus_host = get_bus_host(ncr); + + /*Start the SCSI command layer, which will also make the timings*/ + if (ncr->bus_host & BUS_ARB) { + DEBUG("NCR: arbitration\n"); + ncr->state = STATE_IDLE; + } + + if (ncr->state == STATE_IDLE) { + ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; + if ((ncr->bus_host & BUS_SEL) && !(ncr->bus_host & BUS_BSY)) { + DEBUG("NCR: selection phase\n"); + uint8_t sel_data = BUS_GETDATA(ncr->bus_host); + + ncr->target_id = get_dev_id(sel_data); + + DEBUG("NCR: select - target ID = %i\n", ncr->target_id); + + /*Once the device has been found and selected, mark it as busy*/ + if ((ncr->target_id != -1) && + scsi_device_present(ncr->target_id, ncr->target_lun)) { + ncr->cur_bus |= BUS_BSY; + DEBUG("DEBUG: device found at ID %i\n", ncr->target_id); + DEBUG("NCR: current Bus BSY=%02x\n", ncr->cur_bus); + ncr->state = STATE_COMMAND; + ncr->cur_bus = BUS_BSY | BUS_REQ; + DEBUG("NCR: CurBus BSY|REQ=%02x\n", ncr->cur_bus); + ncr->command_pos = 0; + SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); + picint(1 << ncr_dev->irq); + } else { + ncr->state = STATE_IDLE; + ncr->cur_bus = 0; + } + } + } else if (ncr->state == STATE_COMMAND) { + /*Command phase, make sure the ICR ACK bit is set to keep on, + because the device must be acknowledged by ICR*/ + DEBUG("NCR: ICR for Command=%02x\n", ncr->bus_host & BUS_ACK); + if ((ncr->bus_host & BUS_ACK) && (ncr->command_pos < cmd_len[(ncr->command[0] >> 5) & 7])) { + /*Write command byte to the output data register*/ + ncr->command[ncr->command_pos++] = BUS_GETDATA(ncr->bus_host); + + ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; + ncr->clear_req = 3; + DEBUG("NCR: current bus for command request=%02x\n", ncr->cur_bus & BUS_REQ); + ncr->cur_bus &= ~BUS_REQ; + + DEBUG("NCR: command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(ncr->bus_host)); + + if (ncr->command_pos == cmd_len[(ncr->command[0] >> 5) & 7]) { + /*Reset data position to default*/ + ncr->data_pos = 0; + + dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + + DEBUG("NCR: SCSI command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->Status); + + dev->BufferLength = -1; + + /*Now, execute the given SCSI command*/ + scsi_device_command_phase0(ncr->target_id, ncr->target_lun, ncr->command); + + DEBUG("NCR: SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->BufferLength, dev->Phase); + + if (dev->Status != SCSI_STATUS_OK) { + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + return; + } + + /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ + if (dev->BufferLength && (dev->Phase == SCSI_PHASE_DATA_IN || dev->Phase == SCSI_PHASE_DATA_OUT)) { + dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength); + + p = scsi_device_get_callback(ncr->target_id, ncr->target_lun); + if (p <= 0LL) + ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) MIN(64, dev->BufferLength)); + else + ncr_dev->period = (p / ((double) dev->BufferLength)) * ((double) MIN(64, dev->BufferLength)); + } + + if (dev->Phase == SCSI_PHASE_DATA_OUT) { + /* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */ + DEBUG("NCR: next state is data out\n"); + ncr->new_phase = SCSI_PHASE_DATA_OUT; + ncr->wait_data = 4; + ncr->clear_req = 4; + } else { + /* Other command - execute immediately. */ + ncr->new_phase = dev->Phase; + + if (ncr->new_phase == SCSI_PHASE_DATA_IN) + scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + + ncr->wait_data = 4; + } + } + } + } else if (ncr->state == STATE_DATAIN) { + dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + DEBUG("NCR: Data In ACK=%02x\n", ncr->bus_host & BUS_ACK); + if (ncr->bus_host & BUS_ACK) { + if (ncr->data_pos >= dev->BufferLength) { + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_DATA_IN; + } + } + } else if (ncr->state == STATE_DATAOUT) { + dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + + DEBUG("NCR: Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK); + if (ncr->bus_host & BUS_ACK) { + dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + + if (ncr->data_pos >= dev->BufferLength) { + scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + DEBUG("NCR: CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + ncr->cur_bus |= BUS_REQ; + DEBUG("NCR: CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + } + } + } else if (ncr->state == STATE_STATUS) { + if (ncr->bus_host & BUS_ACK) { + /*All transfers done, wait until next transfer*/ + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_MESSAGE_IN; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } + } else if (ncr->state == STATE_MESSAGEIN) { + if (ncr->bus_host & BUS_ACK) { + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = BUS_IDLE; + ncr->wait_data = 4; + } + } + ncr->bus_in = ncr->bus_host; + } + + if (ncr_dev->type < 3) { + if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { + if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + DEBUG("NCR: DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); + return; + } + + DEBUG("NCR: status for reading=%02x\n", ncr_dev->status_ctrl); + + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) return; + + if (!ncr_dev->block_count_loaded) return; + + while (c < 64) { + /* Data ready. */ + ncr_wait_process(ncr_dev); + temp = BUS_GETDATA(ncr->bus_host); + ncr->bus_host = get_bus_host(ncr); + + if (ncr->data_pos >= dev->BufferLength) { + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_DATA_IN; + } + + ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; + DEBUG("NCR: buffer pos for reading=%d\n", ncr_dev->buffer_pos); + + c++; + + if (ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; + + DEBUG("NCR: remaining blocks to be read=%d\n", ncr_dev->block_count); + + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + DEBUG("DEBUG: IO End of read transfer\n"); + + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + DEBUG("NCR: NCR read irq\n"); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + } else if (ncr->dma_mode == DMA_SEND) { + if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { + DEBUG("NCR: DMA_SEND with DMA direction set wrong\n"); + return; + } + + DEBUG("NCR: status for writing=%02x\n", ncr_dev->status_ctrl); + + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { + DEBUG("NCR: buffer ready\n"); + return; + } + + if (!ncr_dev->block_count_loaded) return; + + while (c < 64) { + /* Data ready. */ + data = ncr_dev->buffer[ncr_dev->buffer_pos]; + ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; + ncr->bus_host |= BUS_SETDATA(data); + + dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + + if (ncr->data_pos >= dev->BufferLength) { + scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + DEBUG("NCR: CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + ncr->cur_bus |= BUS_REQ; + DEBUG("NCR: CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + } + + c++; + + if (++ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->ncr_busy = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; + DEBUG("NCR: remaining blocks to be written=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + DEBUG("NCR: IO End of write transfer\n"); + + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + DEBUG("NCR: write irq\n"); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + } + } else { + if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { + if (!(ncr_dev->block_count_loaded)) + return; + + while (c < 64) { + /* Data ready. */ + ncr_wait_process(ncr_dev); + temp = BUS_GETDATA(ncr->bus_host); + ncr->bus_host = get_bus_host(ncr); + + if (ncr->data_pos >= dev->BufferLength) { + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_DATA_IN; + } + + ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; + DEBUG("NCR: buffer pos for reading=%d\n", ncr_dev->buffer_pos); + + c++; + + if (ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; + DEBUG("NCR: remaining blocks to be read=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + DEBUG("NCR: IO End of read transfer\n"); + + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + DEBUG("NCR: read irq\n"); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + } else if (ncr->dma_mode == DMA_SEND) { + if (!ncr_dev->block_count_loaded) + return; + + while (c < 64) { + /* Data ready. */ + data = ncr_dev->buffer[ncr_dev->buffer_pos]; + ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; + ncr->bus_host |= BUS_SETDATA(data); + + dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + + if (ncr->data_pos >= dev->BufferLength) { + scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + DEBUG("NCR: CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + ncr->cur_bus |= BUS_REQ; + DEBUG("DEBUG: CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + } + + c++; + + if (++ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; + DEBUG("NCR: remaining blocks to be written=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + DEBUG("NCR: IO End of write transfer\n"); + + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + DEBUG("NCR: write irq\n"); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + } + } + + ncr_wait_process(ncr_dev); + if (!(ncr->bus_host & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + DEBUG("NCR: updating DMA\n"); + ncr->mode &= ~MODE_DMA; + ncr->dma_mode = DMA_IDLE; + } +} + + static void ncr_write(uint16_t port, uint8_t val, void *priv) { @@ -877,445 +1281,6 @@ scsiat_out(uint16_t port, uint8_t val, void *priv) } -static void -ncr_callback(void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; - int64_t p; - int c = 0; - - DEBUG("DMA mode=%d\n", ncr->dma_mode); - - ncr_dev->timer_enabled = 0; - if (((ncr->state == STATE_DATAIN) || (ncr->state == STATE_DATAOUT)) && (ncr->dma_mode != DMA_IDLE)) - ncr_dev->timer_period = (int64_t)ncr_dev->period; - else - ncr_dev->timer_period += 10LL * TIMER_USEC; - - if (ncr->dma_mode == DMA_IDLE) { - ncr->bus_host = get_bus_host(ncr); - - /*Start the SCSI command layer, which will also make the timings*/ - if (ncr->bus_host & BUS_ARB) { - DEBUG("Arbitration\n"); - ncr->state = STATE_IDLE; - } - - if (ncr->state == STATE_IDLE) { - ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; - if ((ncr->bus_host & BUS_SEL) && !(ncr->bus_host & BUS_BSY)) { - DEBUG("Selection phase\n"); - uint8_t sel_data = BUS_GETDATA(ncr->bus_host); - - ncr->target_id = get_dev_id(sel_data); - - DEBUG("Select - target ID = %i\n", ncr->target_id); - - /*Once the device has been found and selected, mark it as busy*/ - if ((ncr->target_id != -1) && - scsi_device_present(ncr->target_id, ncr->target_lun)) { - ncr->cur_bus |= BUS_BSY; - DEBUG("Device found at ID %i\n", ncr->target_id); - DEBUG("Current Bus BSY=%02x\n", ncr->cur_bus); - ncr->state = STATE_COMMAND; - ncr->cur_bus = BUS_BSY | BUS_REQ; - DEBUG("CurBus BSY|REQ=%02x\n", ncr->cur_bus); - ncr->command_pos = 0; - SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); - picint(1 << ncr_dev->irq); - } else { - ncr->state = STATE_IDLE; - ncr->cur_bus = 0; - } - } - } else if (ncr->state == STATE_COMMAND) { - /*Command phase, make sure the ICR ACK bit is set to keep on, - because the device must be acknowledged by ICR*/ - DEBUG("NCR ICR for Command=%02x\n", ncr->bus_host & BUS_ACK); - if (ncr->bus_host & BUS_ACK) { - if (ncr->command_pos < get_cmd_len(ncr->command[0])) { - /*Write command byte to the output data register*/ - ncr->command[ncr->command_pos++] = BUS_GETDATA(ncr->bus_host); - - ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; - ncr->clear_req = 3; - DEBUG("NCR: current bus for command request=%02x\n", ncr->cur_bus & BUS_REQ); - ncr->cur_bus &= ~BUS_REQ; - - DEBUG("NCR: Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(ncr->bus_host)); - if (get_cmd_len(ncr->command[0]) == ncr->command_pos) { - /*Reset data position to default*/ - ncr->data_pos = 0; - - dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; - - DEBUG("NCR: SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->Status); - - dev->BufferLength = -1; - - /*Now, execute the given SCSI command*/ - scsi_device_command_phase0(ncr->target_id, ncr->target_lun, ncr->command); - DEBUG("NCR: SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->BufferLength, dev->Phase); - - if (dev->Status != SCSI_STATUS_OK) - ncr_dev->is_non_data_mode = 1; - if (ncr_dev->is_non_data_mode) { - ncr_dev->is_non_data_mode = 0; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - return; - } - /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ - if (dev->BufferLength && (dev->Phase == SCSI_PHASE_DATA_IN || dev->Phase == SCSI_PHASE_DATA_OUT)) { - dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength); - p = scsi_device_get_callback(ncr->target_id, ncr->target_lun); - if (p <= 0LL) { - ncr_dev->temp_period = (int64_t)(dev->BufferLength); - ncr_dev->media_period = 0; - ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) MIN(64, ncr_dev->temp_period)); - } else { - ncr_dev->media_period += p; - ncr_dev->temp_period = dev->BufferLength; - ncr_dev->period = (p / ((double) ncr_dev->temp_period)) * ((double) MIN(64, ncr_dev->temp_period)); - } - } - if (dev->Phase == SCSI_PHASE_DATA_OUT) { - /* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */ - DEBUG("NCR: Next state is data out\n"); - ncr->new_phase = SCSI_PHASE_DATA_OUT; - ncr->wait_data = 4; - ncr->clear_req = 4; - } else { - /* Other command - execute immediately. */ - ncr->new_phase = dev->Phase; - if (ncr->new_phase == SCSI_PHASE_DATA_IN) - scsi_device_command_phase1(ncr->target_id, ncr->target_lun); - ncr->wait_data = 4; - } - } - } - } - } else if (ncr->state == STATE_DATAIN) { - dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; - DEBUG("Data In ACK=%02x\n", ncr->bus_host & BUS_ACK); - if (ncr->bus_host & BUS_ACK) { - if (ncr->data_pos >= dev->BufferLength) { - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - } - } else if (ncr->state == STATE_DATAOUT) { - dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; - - DEBUG("Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK); - if (ncr->bus_host & BUS_ACK) { - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id, ncr->target_lun); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - DEBUG("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - DEBUG("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - } - } else if (ncr->state == STATE_STATUS) { - if (ncr->bus_host & BUS_ACK) { - /*All transfers done, wait until next transfer*/ - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_MESSAGE_IN; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } - } else if (ncr->state == STATE_MESSAGEIN) { - if (ncr->bus_host & BUS_ACK) { - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = BUS_IDLE; - ncr->wait_data = 4; - } - } - } - - if (ncr_dev->type < 3) { - if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { - if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - DEBUG("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); - return; - } - - DEBUG("Status for reading=%02x\n", ncr_dev->status_ctrl); - - if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) return; - - if (!ncr_dev->block_count_loaded) return; - - while (c < 64) { - /* Data ready. */ - uint8_t temp; - - ncr_wait_process(ncr_dev); - temp = BUS_GETDATA(ncr->bus_host); - ncr->bus_host = get_bus_host(ncr); - - if (ncr->data_pos >= dev->BufferLength) { - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - DEBUG("Buffer pos for reading=%d\n", ncr_dev->buffer_pos); - - c++; - - if (ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - DEBUG("Remaining blocks to be read=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - DEBUG("IO End of read transfer\n"); - - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) { - DEBUG("NCR read irq\n"); - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } else if (ncr->dma_mode == DMA_SEND) { - if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { - DEBUG("DMA_SEND with DMA direction set wrong\n"); - return; - } - - DEBUG("Status for writing=%02x\n", ncr_dev->status_ctrl); - - if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { - DEBUG("Buffer ready\n"); - return; - } - - if (!ncr_dev->block_count_loaded) return; - - while (c < 64) { - /* Data ready. */ - uint8_t data; - - data = ncr_dev->buffer[ncr_dev->buffer_pos]; - ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; - ncr->bus_host |= BUS_SETDATA(data); - - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id, ncr->target_lun); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - DEBUG("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - DEBUG("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - - c++; - - if (++ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->ncr_busy = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - DEBUG("Remaining blocks to be written=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - DEBUG("IO End of write transfer\n"); - - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) { - DEBUG("NCR write irq\n"); - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } - } else { - if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { - if (!(ncr_dev->block_count_loaded)) - return; - - while (c < 64) { - /* Data ready. */ - uint8_t temp; - - ncr_wait_process(ncr_dev); - temp = BUS_GETDATA(ncr->bus_host); - ncr->bus_host = get_bus_host(ncr); - - if (ncr->data_pos >= dev->BufferLength) { - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - DEBUG("Buffer pos for reading=%d\n", ncr_dev->buffer_pos); - - c++; - - if (ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - DEBUG("Remaining blocks to be read=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - DEBUG("IO End of read transfer\n"); - - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) { - DEBUG("NCR read irq\n"); - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } else if (ncr->dma_mode == DMA_SEND) { - if (!ncr_dev->block_count_loaded) return; - while (c < 64) { - /* Data ready. */ - uint8_t data; - - data = ncr_dev->buffer[ncr_dev->buffer_pos]; - ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; - ncr->bus_host |= BUS_SETDATA(data); - - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id, ncr->target_lun); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - DEBUG("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - DEBUG("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - - c++; - - if (++ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - DEBUG("Remaining blocks to be written=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - DEBUG("IO End of write transfer\n"); - - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) { - DEBUG("NCR write irq\n"); - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } - } - - ncr_wait_process(ncr_dev); - - if (!(ncr->bus_host & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { - DEBUG("Updating DMA\n"); - ncr->mode &= ~MODE_DMA; - ncr->dma_mode = DMA_IDLE; - } -} - - static void * ncr_init(const device_t *info) { diff --git a/src/devices/video/vid_oak_oti.c b/src/devices/video/vid_oak_oti.c index c125c73..93b9cf3 100644 --- a/src/devices/video/vid_oak_oti.c +++ b/src/devices/video/vid_oak_oti.c @@ -8,7 +8,7 @@ * * Oak OTI037C/67/077 emulation. * - * Version: @(#)vid_oak_oti.c 1.0.13 2018/10/08 + * Version: @(#)vid_oak_oti.c 1.0.14 2018/10/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -421,7 +421,7 @@ oti_init(const device_t *info) case OTI_067_AMA932J: /* Onboard OTI067; ROM set up by machine. */ dev->chip_id = OTI_067; - dev->vram_size = 512; + dev->vram_size = device_get_config_int("memory");; dev->dipswitch_val |= 0x20; /* @@ -527,6 +527,26 @@ static const device_config_t oti067_config[] = { } }; +static const device_config_t oti067_onboard_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 256, + { + { + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + static const device_config_t oti077_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 1024, @@ -586,7 +606,7 @@ const device_t oti067_onboard_device = { speed_changed, force_redraw, &oti_timing, - NULL + oti067_onboard_config }; const device_t oti077_device = { diff --git a/src/machines/m_at_headland.c b/src/machines/m_at_headland.c index 932fab2..16f419b 100644 --- a/src/machines/m_at_headland.c +++ b/src/machines/m_at_headland.c @@ -10,7 +10,7 @@ * * FIXME: fix the mem_map_t stuff in mem_read_b() et al! * - * Version: @(#)m_at_headland.c 1.0.7 2018/10/07 + * Version: @(#)m_at_headland.c 1.0.8 2018/10/08 * * Authors: Fred N. van Kempen, * Original by GreatPsycho for PCem. @@ -53,6 +53,7 @@ #include "../devices/input/keyboard.h" #include "../devices/floppy/fdd.h" #include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" #include "../devices/video/video.h" #include "machine.h" @@ -653,13 +654,16 @@ headland_common_init(int ht386) } +/* Arche Technologies AMA-932J-25 (Headland HT18 386SX-25.) */ void machine_at_ama932j_init(const machine_t *model, void *arg) { romdef_t *roms = (romdef_t *)arg; headland_t *dev; - machine_at_common_ide_init(model, arg); + machine_at_common_init(model, arg); + + device_add(&ide_isa_device); dev = headland_common_init(1); @@ -679,8 +683,7 @@ machine_at_tg286m_init(const machine_t *model, void *arg) { machine_at_common_init(model, arg); - headland_common_init(0); + device_add(&ide_isa_device); - if (video_card == VID_INTERNAL) - device_add(&et4000k_tg286_isa_device); + headland_common_init(0); } diff --git a/src/machines/machine_table.c b/src/machines/machine_table.c index d7760fd..ee91992 100644 --- a/src/machines/machine_table.c +++ b/src/machines/machine_table.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine_table.c 1.0.28 2018/10/06 + * Version: @(#)machine_table.c 1.0.29 2018/10/08 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -99,7 +99,7 @@ const machine_t machines[] = { { "[286 ISA] Samsung SPC-4200P", "samsung_spc4200p", L"samsung/spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 128, machine_at_scat_init, NULL, NULL }, { "[286 ISA] Samsung SPC-4216P", "samsung_spc4216p", L"samsung/spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 128, machine_at_scat_spc4216p_init, NULL, NULL }, { "[286 ISA] Toshiba T3100e", "toshiba_t3100e", L"toshiba/t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 64, machine_at_t3100e_init, NULL, NULL }, - { "[286 ISA] Trigem 286M", "tg286m", L"trigem/tg286m", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 512, 8192, 128, 128, machine_at_tg286m_init, &et4000k_tg286_isa_device,NULL }, + { "[286 ISA] Trigem 286M", "tg286m", L"trigem/tg286m", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 128, machine_at_tg286m_init, NULL, NULL }, { "[286 MCA] IBM PS/2 model 50", "ibm_ps2_m50", L"ibm/ps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 10, 1, 64, machine_ps2_model_50_init, NULL, NULL }, @@ -111,7 +111,7 @@ const machine_t machines[] = { { "[386SX ISA] IBM PS/1 m.2121+ISA", "ibm_ps1_2121_isa", L"ibm/ps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 64, machine_ps1_m2121_init, &m_ps1_device, NULL }, { "[386SX ISA] KMX-C-02", "kmxc02", L"unknown/kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 128, machine_at_scatsx_init, NULL, NULL }, - { "[386SX ISA] AMA-932J", "ama932j", L"unknown/ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 128, machine_at_ama932j_init, &oti067_onboard_device, NULL }, + { "[386SX ISA] Arche AMA-932J", "arche_ama932j", L"arche/ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 128, machine_at_ama932j_init, &oti067_onboard_device, NULL }, { "[386SX MCA] IBM PS/2 model 55SX", "ibm_ps2_m55sx", L"ibm/ps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 8, 1, 64, machine_ps2_model_55sx_init, NULL, NULL },