]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Directory hardfile fake device driver now can be opened and supports minimal command...
authorToni Wilen <twilen@winuae.net>
Thu, 8 Mar 2018 16:22:42 +0000 (18:22 +0200)
committerToni Wilen <twilen@winuae.net>
Thu, 8 Mar 2018 16:22:42 +0000 (18:22 +0200)
filesys.cpp
hardfile.cpp
scsi.cpp

index f2d0dd1604cae1f045c7329a17cb52b802d5cf4d..6e63263188fef884aac1b504f28e1c584f60cb50 100644 (file)
@@ -593,6 +593,61 @@ void uci_set_defaults (struct uaedev_config_info *uci, bool rdb)
        uci->device_emu_unit = -1;
 }
 
+static void get_usedblocks(struct fs_usage *fsu, bool fs, int *pblocksize, uae_s64 *pnumblocks, uae_s64 *pinuse)
+{
+       uae_s64 numblocks = 0, inuse;
+       int blocksize = *pblocksize;
+
+       if (fs && currprefs.filesys_limit) {
+               if (fsu->total > (uae_s64)currprefs.filesys_limit * 1024) {
+                       uae_s64 oldtotal = fsu->total;
+                       fsu->total = currprefs.filesys_limit * 1024;
+                       fsu->avail = ((fsu->avail / 1024) * (fsu->total / 1024)) / (oldtotal / 1024);
+                       fsu->avail *= 1024;
+               }
+       }
+       while (blocksize < 32768 || numblocks == 0) {
+               numblocks = fsu->total / blocksize;
+               if (numblocks <= 10)
+                       numblocks = 10;
+               if (numblocks <= 0x7fffffff)
+                       break;
+               blocksize *= 2;
+       }
+       inuse = (numblocks * blocksize - fsu->avail) / blocksize;
+       if (inuse > numblocks)
+               inuse = numblocks;
+       if (pnumblocks)
+               *pnumblocks = numblocks;
+       if (pinuse)
+               *pinuse = inuse;
+       if (pblocksize)
+               *pblocksize = blocksize;
+}
+
+static bool get_blocks(const TCHAR *rootdir, int unit, int flags, int *pblocksize, uae_s64 *pnumblocks, uae_s64 *pinuse)
+{
+       struct fs_usage fsu;
+       int ret;
+       bool fs = false;
+       int blocksize;
+
+       blocksize = 512;
+       if (flags & MYVOLUMEINFO_ARCHIVE) {
+               ret = zfile_fs_usage_archive(rootdir, 0, &fsu);
+               fs = true;
+       } else {
+               ret = get_fs_usage(rootdir, 0, &fsu);
+               fs = true;
+       }
+       if (ret)
+               return false;
+       get_usedblocks(&fsu, fs, &blocksize, pnumblocks, pinuse);
+       if (pblocksize)
+               *pblocksize = blocksize;
+       return ret == 0;
+}
+
 static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci)
 {
        UnitInfo *ui;
@@ -668,6 +723,8 @@ static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci)
                c.readonly = true;
        } else if (c.volname[0]) {
                int flags = 0;
+               uae_s64 numblocks;
+
                emptydrive = 1;
                if (c.rootdir[0]) {
                        if (set_filesys_volume (c.rootdir, &flags, &c.readonly, &emptydrive, &ui->zarchive) < 0)
@@ -675,6 +732,25 @@ static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci)
                }
                ui->volname = filesys_createvolname (c.volname, c.rootdir, ui->zarchive, _T("harddrive"));
                ui->volflags = flags;
+               TCHAR *vs = au(UAEFS_VERSION);
+               TCHAR *vsp = vs + _tcslen(vs) - 1;
+               while (vsp != vs) {
+                       if (*vsp == ' ') {
+                               *vsp++ = 0;
+                               break;
+                       }
+                       vsp--;
+               }
+               _tcscpy(ui->hf.vendor_id, _T("UAE"));
+               _tcscpy(ui->hf.product_id, vs);
+               _tcscpy(ui->hf.product_rev, vsp);
+               xfree(vs);
+               ui->hf.ci.unit_feature_level = HD_LEVEL_SCSI_2;
+               if (get_blocks(c.rootdir, nr, flags, &ui->hf.ci.blocksize, &numblocks, NULL))
+                       ui->hf.ci.max_lba = numblocks > 0xffffffff ? 0xffffffff : numblocks;
+               else
+                       ui->hf.ci.max_lba = 0x00ffffff;
+
        } else {
                ui->unit_type = UNIT_FILESYSTEM;
                ui->hf.unitnum = nr;
@@ -1053,7 +1129,7 @@ struct hardfiledata *get_hardfile_data_controller(int nr)
 {
        UnitInfo *uip = mountinfo.ui;
        for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
-               if (uip[i].open == 0 || is_virtual(i))
+               if (uip[i].open == 0)
                        continue;
                if (uip[i].hf.ci.controller_unit == nr)
                        return &uip[i].hf;
@@ -3301,26 +3377,8 @@ static void      do_info(TrapContext *ctx, Unit *unit, dpacket *packet, uaecptr info,
                put_long_host(buf + 24, -1); /* ID_NO_DISK_PRESENT */
                put_long_host(buf + 28, 0);
        } else {
-               if (fs && currprefs.filesys_limit) {
-                       if (fsu.total > (uae_s64)currprefs.filesys_limit * 1024) {
-                               uae_s64 oldtotal = fsu.total;
-                               fsu.total = currprefs.filesys_limit * 1024;
-                               fsu.avail = ((fsu.avail / 1024) * (fsu.total / 1024)) / (oldtotal / 1024);
-                               fsu.avail *= 1024;
-                       }
-               }
-               uae_s64 numblocks = 0;
-               while (blocksize < 32768 || numblocks == 0) {
-                       numblocks = fsu.total / blocksize;
-                       if (numblocks <= 10)
-                               numblocks = 10;
-                       if (numblocks <= 0x7fffffff)
-                               break;
-                       blocksize *= 2;
-               }
-               uae_s64 inuse = (numblocks * blocksize - fsu.avail) / blocksize;
-               if (inuse > numblocks)
-                       inuse = numblocks;
+               uae_s64 numblocks, inuse;
+               get_usedblocks(&fsu, fs, &blocksize, &numblocks, &inuse);
                //write_log(_T("total %lld avail %lld Blocks %lld Inuse %lld blocksize %d\n"), fsu.total, fsu.avail, numblocks, inuse, blocksize);
                put_long_host(buf + 12, (uae_u32)numblocks); /* numblocks */
                put_long_host(buf + 16, (uae_u32)inuse); /* inuse */
@@ -8964,7 +9022,7 @@ void filesys_install (void)
        ROM_filesys_resname = ds_ansi ("UAEfs.resource");
        ROM_filesys_resid = ds_ansi (UAEFS_VERSION);
 
-       fsdevname = ds_ansi ("uae.device"); /* does not really exist */
+       fsdevname = ROM_hardfile_resname;
        fshandlername = ds_bstr_ansi ("uaefs");
 
        cdfs_devname = ds_ansi ("uaescsi.device");
index 19826079f7d38b22ef610cbc69e76431884871ba..947c6aaf298f3f2f85149caaeb268b856b242c39 100644 (file)
@@ -80,6 +80,7 @@ struct hardfileprivdata {
        int changenum;
        uaecptr changeint;
        struct scsi_data *sd;
+       bool directorydrive;
 };
 
 #define HFD_CHD_OTHER 5
@@ -2440,18 +2441,35 @@ static uae_u32 REGPARAM2 hardfile_open (TrapContext *ctx)
        if (unit >= 0 && unit < MAX_FILESYSTEM_UNITS) {
                struct hardfileprivdata *hfpd = &hardfpd[unit];
                struct hardfiledata *hfd = get_hardfile_data_controller(unit);
-               if (hfd && (hfd->handle_valid || hfd->drive_empty) && start_thread (ctx, unit)) {
-                       trap_put_word(ctx, hfpd->base + 32, trap_get_word(ctx, hfpd->base + 32) + 1);
-                       trap_put_long(ctx, ioreq + 24, unit); /* io_Unit */
-                       trap_put_byte(ctx, ioreq + 31, 0); /* io_Error */
-                       trap_put_byte(ctx, ioreq + 8, 7); /* ln_type = NT_REPLYMSG */
-                       if (!hfpd->sd)
-                               hfpd->sd = scsi_alloc_generic(hfd, UAEDEV_HDF);
-                       hf_log (_T("hardfile_open, unit %d (%d), OK\n"), unit, trap_get_dreg (ctx, 0));
-                       return 0;
+               if (hfd) {
+                       if (is_hardfile(hfd->ci.controller_type_unit) == FILESYS_VIRTUAL) {
+                               if (start_thread(ctx, unit)) {
+                                       hfpd->directorydrive = true;
+                                       trap_put_word(ctx, hfpd->base + 32, trap_get_word(ctx, hfpd->base + 32) + 1);
+                                       trap_put_long(ctx, ioreq + 24, unit); /* io_Unit */
+                                       trap_put_byte(ctx, ioreq + 31, 0); /* io_Error */
+                                       trap_put_byte(ctx, ioreq + 8, 7); /* ln_type = NT_REPLYMSG */
+                                       if (!hfpd->sd)
+                                               hfpd->sd = scsi_alloc_generic(hfd, UAEDEV_DIR);
+                                       hf_log(_T("virtual hardfile_open, unit %d (%d), OK\n"), unit, trap_get_dreg(ctx, 0));
+                                       return 0;
+                               }
+                       } else {
+                               if ((hfd->handle_valid || hfd->drive_empty) && start_thread(ctx, unit)) {
+                                       hfpd->directorydrive = false;
+                                       trap_put_word(ctx, hfpd->base + 32, trap_get_word(ctx, hfpd->base + 32) + 1);
+                                       trap_put_long(ctx, ioreq + 24, unit); /* io_Unit */
+                                       trap_put_byte(ctx, ioreq + 31, 0); /* io_Error */
+                                       trap_put_byte(ctx, ioreq + 8, 7); /* ln_type = NT_REPLYMSG */
+                                       if (!hfpd->sd)
+                                               hfpd->sd = scsi_alloc_generic(hfd, UAEDEV_HDF);
+                                       hf_log(_T("hardfile_open, unit %d (%d), OK\n"), unit, trap_get_dreg(ctx, 0));
+                                       return 0;
+                               }
+                       }
                }
        }
-       if (unit < 1000 || is_hardfile (unit) == FILESYS_VIRTUAL || is_hardfile (unit) == FILESYS_CD)
+       if (unit < 1000)
                err = 50; /* HFERR_NoBoard */
        hf_log (_T("hardfile_open, unit %d (%d), ERR=%d\n"), unit, trap_get_dreg(ctx, 0), err);
        trap_put_long(ctx, ioreq + 20, (uae_u32)err);
@@ -2514,6 +2532,11 @@ static bool isbadblock(struct hardfiledata *hfd, uae_u64 offset, uae_u64 len)
        return false;
 }
 
+static bool vdisk(struct hardfileprivdata *hfdp)
+{
+       return hfdp->directorydrive;
+}
+
 static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struct hardfileprivdata *hfpd, uae_u8 *iobuf, uaecptr request)
 {
        uae_u32 dataptr, offset, actual = 0, cmd;
@@ -2541,14 +2564,24 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
                        unaligned (cmd, offset, len, hfd->ci.blocksize);
                        goto bad_len;
                }
-               if (len + offset > hfd->virtsize) {
-                       outofbounds (cmd, offset, len, hfd->virtsize);
-                       goto bad_len;
-               }
-               if (isbadblock(hfd, offset, len)) {
-                       goto bad_block;
+               if (vdisk(hfpd)) {
+                       for (int i = 0; i < len; i++) {
+                               put_byte(dataptr + i, 0);
+                       }
+                       if (offset == 0) {
+                               put_long(dataptr, 0x444f5301);
+                       }
+                       actual = len;
+               } else {
+                       if (len + offset > hfd->virtsize) {
+                               outofbounds(cmd, offset, len, hfd->virtsize);
+                               goto bad_len;
+                       }
+                       if (isbadblock(hfd, offset, len)) {
+                               goto bad_block;
+                       }
+                       actual = (uae_u32)cmd_read(ctx, hfd, dataptr, offset, len);
                }
-               actual = (uae_u32)cmd_read(ctx, hfd, dataptr, offset, len);
                break;
 
 #if HDF_SUPPORT_TD64
@@ -2560,6 +2593,8 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
 #if defined(HDF_SUPPORT_NSD) || defined(HDF_SUPPORT_TD64)
                if (nodisk (hfd))
                        goto no_disk;
+               if (vdisk(hfpd))
+                       goto v_disk;
                offset64 = get_long_host(iobuf + 44) | ((uae_u64)get_long_host(iobuf + 32) << 32);
                len = get_long_host(iobuf + 36); /* io_Length */
                if (offset64 & bmask) {
@@ -2585,6 +2620,8 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
        case CMD_FORMAT: /* Format */
                if (nodisk (hfd))
                        goto no_disk;
+               if (vdisk(hfpd))
+                       goto v_disk;
                if (is_writeprotected(hfd)) {
                        error = 28; /* write protect */
                } else {
@@ -2620,6 +2657,8 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
 #if defined(HDF_SUPPORT_NSD) || defined(HDF_SUPPORT_TD64)
                if (nodisk (hfd))
                        goto no_disk;
+               if (vdisk(hfpd))
+                       goto v_disk;
                if (is_writeprotected(hfd)) {
                        error = 28; /* write protect */
                } else {
@@ -2647,6 +2686,8 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
 
 #if HDF_SUPPORT_NSD
        case NSCMD_DEVICEQUERY:
+               if (vdisk(hfpd))
+                       goto v_disk;
                trap_put_long(ctx, dataptr + 0, 0);
                trap_put_long(ctx, dataptr + 4, 16); /* size */
                trap_put_word(ctx, dataptr + 8, NSDEVTYPE_TRACKDISK);
@@ -2657,8 +2698,14 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
 #endif
 
        case CMD_GETDRIVETYPE:
+               if (vdisk(hfpd))
+                       goto v_disk;
+#if HDF_SUPPORT_NSD
                actual = DRIVE_NEWSTYLE;
                break;
+#else
+               goto no_cmd;
+#endif
 
        case CMD_GETNUMTRACKS:
                {
@@ -2704,9 +2751,20 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
        case CMD_CLEAR:
        case CMD_MOTOR:
        case CMD_SEEK:
+               break;
+
+#if HDF_SUPPORT_TD64
        case TD_SEEK64:
+               if (vdisk(hfpd))
+                       goto v_disk;
+               break;
+#endif
+#ifdef HDF_SUPPORT_NSD
        case NSCMD_TD_SEEK64:
+               if (vdisk(hfpd))
+                       goto v_disk;
                break;
+#endif
 
        case CMD_REMOVE:
                hfpd->changeint = get_long (request + 40);
@@ -2717,17 +2775,23 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
                break;
 
        case CMD_ADDCHANGEINT:
+               if (vdisk(hfpd))
+                       goto v_disk;
                error = add_async_request (hfpd, iobuf, request, ASYNC_REQUEST_CHANGEINT, get_long_host(iobuf + 40));
                if (!error)
                        async = 1;
                break;
        case CMD_REMCHANGEINT:
+               if (vdisk(hfpd))
+                       goto v_disk;
                release_async_request (hfpd, request);
                break;
 
 #if HDF_SUPPORT_DS
        case HD_SCSICMD: /* SCSI */
-               if (HDF_SUPPORT_DS_PARTITION || enable_ds_partition_hdf || (!hfd->ci.sectors && !hfd->ci.surfaces && !hfd->ci.reserved)) {
+               if (vdisk(hfpd)) {
+                       error = handle_scsi(ctx, iobuf, request, hfd, hfpd->sd);
+               } else if (HDF_SUPPORT_DS_PARTITION || enable_ds_partition_hdf || (!hfd->ci.sectors && !hfd->ci.surfaces && !hfd->ci.reserved)) {
                        error = handle_scsi(ctx, iobuf, request, hfd, hfpd->sd);
                } else { /* we don't want users trashing their "partition" hardfiles with hdtoolbox */
                        error = IOERR_NOCMD;
@@ -2737,6 +2801,8 @@ static uae_u32 hardfile_do_io (TrapContext *ctx, struct hardfiledata *hfd, struc
 #endif
 
        case CD_EJECT:
+               if (vdisk(hfpd))
+                       goto v_disk;
                if (hfd->ci.sectors && hfd->ci.surfaces) {
                        int len = get_long_host(iobuf + 36);
                        if (len) {
@@ -2764,11 +2830,15 @@ bad_command:
 bad_len:
                error = IOERR_BADLENGTH;
                break;
+v_disk:
+               error = IOERR_BadDriveType;
+               break;
 no_disk:
                error = 29; /* no disk */
                break;
 
        default:
+no_cmd:
                /* Command not understood. */
                error = IOERR_NOCMD;
                break;
index 0ec871221bf5d4d8d559d3bb72ce4e6f91164dbb..b13d6ea84a26c7c35e3ff1a41a4d34fc95173132 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
 
 extern int log_scsiemu;
 
-static const int outcmd[] = { 0x04, 0x0a, 0x0c, 0x11, 0x2a, 0xaa, 0x15, 0x55, 0x0f, -1 };
-static const int incmd[] = { 0x01, 0x03, 0x08, 0x0e, 0x12, 0x1a, 0x5a, 0x25, 0x28, 0x34, 0x37, 0x42, 0x43, 0xa8, 0x51, 0x52, 0xb9, 0xbd, 0xd8, 0xd9, 0xbe, -1 };
-static const int nonecmd[] = { 0x00, 0x05, 0x06, 0x07, 0x09, 0x0b, 0x10, 0x16, 0x17, 0x19, 0x1b, 0x1d, 0x1e, 0x2b, 0x35, 0x45, 0x47, 0x48, 0x49, 0x4b, 0x4e, 0xa5, 0xa9, 0xba, 0xbc, 0xe0, 0xe3, 0xe4, -1 };
-static const int scsicmdsizes[] = { 6, 10, 10, 12, 16, 12, 10, 6 };
+static const uae_s16 outcmd[] = { 0x04, 0x0a, 0x0c, 0x11, 0x2a, 0xaa, 0x15, 0x55, 0x0f, -1 };
+static const uae_s16 incmd[] = { 0x01, 0x03, 0x08, 0x0e, 0x12, 0x1a, 0x5a, 0x25, 0x28, 0x34, 0x37, 0x42, 0x43, 0xa8, 0x51, 0x52, 0xb9, 0xbd, 0xd8, 0xd9, 0xbe, -1 };
+static const uae_s16 nonecmd[] = { 0x00, 0x05, 0x06, 0x07, 0x09, 0x0b, 0x10, 0x16, 0x17, 0x19, 0x1b, 0x1d, 0x1e, 0x2b, 0x35, 0x45, 0x47, 0x48, 0x49, 0x4b, 0x4e, 0xa5, 0xa9, 0xba, 0xbc, 0xe0, 0xe3, 0xe4, -1 };
+static const uae_s16 dirscsi[] = { 0x00, 0x01, 0x03, 0x0e, 0x0f, 0x12, 0x1a, 0x1b, 0x25, 0x35, 0x5a, -1 };
+static const uae_s16 scsicmdsizes[] = { 6, 10, 10, 12, 16, 12, 10, 6 };
 
 static void scsi_illegal_command(struct scsi_data *sd)
 {
@@ -385,6 +386,7 @@ void scsi_emulate_cmd(struct scsi_data *sd)
                sd->device_type, sd->nativescsiunit);
 #endif
        if (sd->device_type == UAEDEV_CD && sd->cd_emu_unit >= 0) {
+
                uae_u32 ua = 0;
                ua = scsi_cd_emulate(sd->cd_emu_unit, NULL, 0, 0, 0, 0, 0, 0, 0, sd->atapi);
                if (ua)
@@ -398,7 +400,9 @@ void scsi_emulate_cmd(struct scsi_data *sd)
                                copyreply(sd);
                        }
                }
+
        } else if (sd->device_type == UAEDEV_HDF && sd->nativescsiunit < 0) {
+
                uae_u32 ua = 0;
                ua = scsi_hd_emulate(sd->hfd, sd->hdhfd, NULL, 0, 0, 0, 0, 0, 0, 0);
                if (ua)
@@ -413,7 +417,9 @@ void scsi_emulate_cmd(struct scsi_data *sd)
                                copyreply(sd);
                        }
                }
+
        } else if (sd->device_type == UAEDEV_TAPE && sd->nativescsiunit < 0) {
+
                uae_u32 ua = 0;
                ua = scsi_tape_emulate(sd->tape, NULL, 0, 0, 0, 0, 0, 0, 0);
                if (ua)
@@ -428,6 +434,40 @@ void scsi_emulate_cmd(struct scsi_data *sd)
                                copyreply(sd);
                        }
                }
+
+       } else if (sd->device_type == UAEDEV_DIR) {
+
+               uae_u32 ua = 0;
+               ua = scsi_hd_emulate(sd->hfd, sd->hdhfd, NULL, 0, 0, 0, 0, 0, 0, 0);
+               if (ua)
+                       sd->unit_attention = ua;
+               if (handle_ca(sd)) {
+                       bool allowed = false;
+                       for (int i = 0; dirscsi[i] >= 0; i++) {
+                               if (dirscsi[i] == sd->cmd[0]) {
+                                       allowed = true;
+                                       break;
+                               }
+                       }
+                       if (allowed) {
+                               if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
+                                       scsi_hd_emulate(sd->hfd, sd->hdhfd, sd->cmd, 0, 0, 0, 0, 0, sd->sense, &sd->sense_len);
+                                       copysense(sd);
+                               } else {
+                                       sd->status = scsi_hd_emulate(sd->hfd, sd->hdhfd,
+                                               sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
+                                       copyreply(sd);
+                               }
+                       } else {
+                               sd->sense[0] = 0x70;
+                               sd->sense[2] = 5; /* Illegal Request */
+                               sd->sense[12] = 0x20; /* Invalid/unsupported command code */
+                               sd->sense_len = 18;
+                               sd->status = 2;
+                               copyreply(sd);
+                       }
+               }
+
        } else if (sd->nativescsiunit >= 0) {
                struct amigascsi as;