--- uae/src/filesys.c 2018/04/24 17:02:12 1.1.1.13 +++ uae/src/filesys.c 2018/04/24 17:22:13 1.1.1.23 @@ -27,7 +27,6 @@ #include "sysconfig.h" #include "sysdeps.h" -#include "config.h" #include "threaddep/thread.h" #include "options.h" #include "uae.h" @@ -36,15 +35,20 @@ #include "events.h" #include "newcpu.h" #include "filesys.h" +#include "traps.h" #include "autoconf.h" -#include "compiler.h" #include "fsusage.h" #include "native2amiga.h" #include "scsidev.h" #include "fsdb.h" -/* #define TRACING_ENABLED */ -#ifdef TRACING_ENABLED +/* Count the number of FS packets waiting to be serviced, for the benefit + * of the idle on STOP code. */ +int active_fs_packets; +uae_sem_t packet_counter_sem; + +#define TRACING_ENABLED 0 +#if TRACING_ENABLED #define TRACE(x) do { write_log x; } while(0) #define DUMPLOCK(u,x) dumplock(u,x) #else @@ -112,6 +116,8 @@ static uae_u32 fsdevname, filesys_config #define FS_STARTUP 0 #define FS_GO_DOWN 1 +#define DEVNAMES_PER_HDF 32 + typedef struct { char *devname; /* device name, e.g. UAE0: */ uaecptr devname_amiga; @@ -119,8 +125,9 @@ typedef struct { char *volname; /* volume name, e.g. CDROM, WORK, etc. */ char *rootdir; /* root unix directory */ int readonly; /* disallow write access? */ + int bootpri; int devno; - + struct hardfiledata hf; /* Threading stuff */ @@ -130,6 +137,15 @@ typedef struct { /* Reset handling */ uae_sem_t reset_sync_sem; int reset_state; + + /* RDB stuff */ + uaecptr rdb_devname_amiga[DEVNAMES_PER_HDF]; + int rdb_lowcyl; + int rdb_highcyl; + int rdb_cylblocks; + uae_u8 *rdb_filesysstore; + int rdb_filesyssize; + char *filesysdir; } UnitInfo; #define MAX_UNITS 20 @@ -146,9 +162,20 @@ int nr_units (struct uaedev_mount_info * return mountinfo->num_units; } -int is_hardfile (struct uaedev_mount_info *mountinfo, int unit_no) +int hardfile_fs_type (struct uaedev_mount_info *mountinfo, int unit_no) { - return mountinfo->ui[unit_no].volname == 0; + if (mountinfo->ui[unit_no].volname) + return FILESYS_VIRTUAL; + + if (mountinfo->ui[unit_no].hf.secspertrack == 0) { +#if 0 + if (mountinfo->ui[unit_no].hf.flags & 1) + return FILESYS_HARDDRIVE; +#endif + return FILESYS_HARDFILE_RDB; + } + + return FILESYS_HARDFILE; } static void close_filesys_unit (UnitInfo *uip) @@ -176,16 +203,17 @@ static void close_filesys_unit (UnitInfo } char *get_filesys_unit (struct uaedev_mount_info *mountinfo, int nr, - char **volname, char **rootdir, int *readonly, - int *secspertrack, int *surfaces, int *reserved, - int *cylinders, int *size, int *blocksize) + char **devname, char **volname, char **rootdir, + int *readonly, int *secspertrack, int *surfaces, int *reserved, + int *cylinders, int *size, int *blocksize, int *bootpri) { UnitInfo *uip = mountinfo->ui + nr; if (nr >= mountinfo->num_units) return "No slot allocated for this unit"; - + *volname = uip->volname ? my_strdup (uip->volname) : 0; + *devname = uip->devname ? my_strdup (uip->devname) : 0; *rootdir = uip->rootdir ? my_strdup (uip->rootdir) : 0; *readonly = uip->readonly; *secspertrack = uip->hf.secspertrack; @@ -194,13 +222,14 @@ char *get_filesys_unit (struct uaedev_mo *size = uip->hf.size; *cylinders = uip->hf.nrcyls; *blocksize = uip->hf.blocksize; + *bootpri = uip->bootpri; return 0; } static char *set_filesys_unit_1 (struct uaedev_mount_info *mountinfo, int nr, - char *volname, char *rootdir, int readonly, - int secspertrack, int surfaces, int reserved, - int blocksize) + const char *devname, const char *volname, const char *rootdir, + int readonly, int secspertrack, int surfaces, int reserved, + int blocksize, int bootpri) { UnitInfo *ui = mountinfo->ui + nr; @@ -227,10 +256,11 @@ static char *set_filesys_unit_1 (struct if (ui->hf.fd == 0) return "Hardfile not found"; - if (secspertrack < 1 || secspertrack > 32767 - || surfaces < 1 || surfaces > 1023 - || reserved < 0 || reserved > 1023 - || (blocksize & (blocksize - 1)) != 0) + if ((secspertrack || surfaces || reserved) + && (secspertrack < 1 || secspertrack > 32767 + || surfaces < 1 || surfaces > 1023 + || reserved < 0 || reserved > 1023 + || (blocksize & (blocksize - 1)) != 0)) { return "Bad hardfile geometry"; } @@ -239,25 +269,35 @@ static char *set_filesys_unit_1 (struct ui->hf.secspertrack = secspertrack; ui->hf.surfaces = surfaces; ui->hf.reservedblocks = reserved; - ui->hf.nrcyls = (ui->hf.size / blocksize) / (secspertrack * surfaces); + ui->hf.nrcyls = (secspertrack * surfaces + ? (ui->hf.size / blocksize) / (secspertrack * surfaces) + : 0); ui->hf.blocksize = blocksize; } ui->self = 0; ui->reset_state = FS_STARTUP; ui->rootdir = my_strdup (rootdir); + if (devname != 0 && strlen (devname) != 0) + ui->devname = my_strdup (devname); ui->readonly = readonly; + if (bootpri < -128) + bootpri = -128; + if (bootpri > 127) + bootpri = 127; + ui->bootpri = bootpri; return 0; } char *set_filesys_unit (struct uaedev_mount_info *mountinfo, int nr, - char *volname, char *rootdir, int readonly, - int secspertrack, int surfaces, int reserved, - int blocksize) + const char *devname, const char *volname, const char *rootdir, + int readonly, int secspertrack, int surfaces, int reserved, + int blocksize, int bootpri) { UnitInfo ui = mountinfo->ui[nr]; - char *result = set_filesys_unit_1 (mountinfo, nr, volname, rootdir, readonly, - secspertrack, surfaces, reserved, blocksize); + char *result = set_filesys_unit_1 (mountinfo, nr, devname, volname, rootdir, + readonly, secspertrack, surfaces, reserved, + blocksize, bootpri); if (result) mountinfo->ui[nr] = ui; else @@ -267,9 +307,9 @@ char *set_filesys_unit (struct uaedev_mo } char *add_filesys_unit (struct uaedev_mount_info *mountinfo, - char *volname, char *rootdir, int readonly, - int secspertrack, int surfaces, int reserved, - int blocksize) + const char *devname, const char *volname, const char *rootdir, + int readonly, int secspertrack, int surfaces, int reserved, + int blocksize, int bootpri) { char *retval; int nr = mountinfo->num_units; @@ -279,8 +319,9 @@ char *add_filesys_unit (struct uaedev_mo return "Maximum number of file systems mounted"; mountinfo->num_units++; - retval = set_filesys_unit_1 (mountinfo, nr, volname, rootdir, readonly, - secspertrack, surfaces, reserved, blocksize); + retval = set_filesys_unit_1 (mountinfo, nr, devname, volname, rootdir, readonly, + secspertrack, surfaces, reserved, blocksize, + bootpri); if (retval) mountinfo->num_units--; return retval; @@ -348,13 +389,22 @@ void write_filesys_config (struct uaedev for (i = 0; i < mountinfo->num_units; i++) { char *str; str = cfgfile_subst_path (default_path, unexpanded, uip[i].rootdir); - if (uip[i].volname != 0) { + if (hardfile_fs_type (mountinfo, i) == FILESYS_VIRTUAL) { + fprintf (f, "filesystem2=%s,%s:%s:%s,%d\n", uip[i].readonly ? "ro" : "rw", + "", uip[i].volname, str, uip[i].bootpri); fprintf (f, "filesystem=%s,%s:%s\n", uip[i].readonly ? "ro" : "rw", uip[i].volname, str); } else { + fprintf (f, "hardfile2=%s,%s:%s,%d,%d,%d,%d,%d,%s,%s\n", + uip[i].readonly ? "ro" : "rw", + "", str, + uip[i].hf.secspertrack, + uip[i].hf.surfaces, uip[i].hf.reservedblocks, + uip[i].hf.blocksize, uip[i].bootpri, "", "uae"); fprintf (f, "hardfile=%s,%d,%d,%d,%d,%s\n", uip[i].readonly ? "ro" : "rw", uip[i].hf.secspertrack, - uip[i].hf.surfaces, uip[i].hf.reservedblocks, 512, str); + uip[i].hf.surfaces, uip[i].hf.reservedblocks, + uip[i].hf.blocksize, str); } free (str); } @@ -416,7 +466,7 @@ struct hardfiledata *get_hardfile_data ( #define dp_Arg4 32 /* result codes */ -#define DOS_TRUE ((unsigned long)-1L) +#define DOS_TRUE (0xffffffffUL) #define DOS_FALSE (0L) /* Passed as type to Lock() */ @@ -475,8 +525,10 @@ struct hardfiledata *get_hardfile_data ( typedef struct { uae_u32 uniq; + /* The directory we're going through. */ a_inode *aino; - DIR* dir; + /* The file we're going to look up next. */ + a_inode *curr_file; } ExamineKey; typedef struct key { @@ -517,8 +569,9 @@ typedef struct _unit { volatile unsigned int cmds_acked; /* ExKeys */ - ExamineKey examine_keys[EXKEYS]; + ExamineKey examine_keys[EXKEYS]; int next_exkey; + unsigned long total_locked_ainos; /* Keys */ struct key *keys; @@ -547,11 +600,11 @@ static char *bstr1 (uaecptr addr) { static char buf[256]; int i; - int n = get_byte(addr); + int n = get_byte (addr); addr++; for (i = 0; i < n; i++, addr++) - buf[i] = get_byte(addr); + buf[i] = get_byte (addr); buf[i] = 0; return buf; } @@ -559,11 +612,11 @@ static char *bstr1 (uaecptr addr) static char *bstr (Unit *unit, uaecptr addr) { int i; - int n = get_byte(addr); + int n = get_byte (addr); addr++; for (i = 0; i < n; i++, addr++) - unit->tmpbuf3[i] = get_byte(addr); + unit->tmpbuf3[i] = get_byte (addr); unit->tmpbuf3[i] = 0; return unit->tmpbuf3; } @@ -576,7 +629,7 @@ static char *bstr_cut (Unit *unit, uaecp addr++; for (i = 0; i < n; i++, addr++) { - uae_u8 c = get_byte(addr); + uae_u8 c = get_byte (addr); unit->tmpbuf3[i] = c; if (c == '/' || (c == ':' && colon_seen++ == 0)) p = unit->tmpbuf3 + i + 1; @@ -598,7 +651,7 @@ find_unit (uaecptr port) return u; } - + static void prepare_for_open (char *name) { #if 0 @@ -650,34 +703,55 @@ static void recycle_aino (Unit *unit, a_ /* Still in use */ return; - if (unit->aino_cache_size > 500) { + TRACE (("Recycling; cache size %d, total_locked %d\n", + unit->aino_cache_size, unit->total_locked_ainos)); + if (unit->aino_cache_size > 500 + unit->total_locked_ainos) { /* Reap a few. */ int i = 0; while (i < 50) { - a_inode **aip; - aip = &unit->rootnode.prev->parent->child; - for (;;) { - a_inode *aino = *aip; - if (aino == 0) - break; - - if (aino->next == 0) - aip = &aino->sibling; - else { - if (aino->shlock > 0 || aino->elock) - write_log ("panic: freeing locked a_inode!\n"); - - de_recycle_aino (unit, aino); - dispose_aino (unit, aip, aino); - i++; + a_inode *parent = unit->rootnode.prev->parent; + a_inode **aip, *old_prev; + aip = &parent->child; + + if (! parent->locked_children) { + for (;;) { + a_inode *aino = *aip; + if (aino == 0) + break; + + /* Not recyclable if next == 0 (i.e., not chained into + recyclable list), or if parent directory is being + ExNext()ed. */ + if (aino->next == 0) { + aip = &aino->sibling; + } else { + if (aino->shlock > 0 || aino->elock) + write_log ("panic: freeing locked a_inode!\n"); + + de_recycle_aino (unit, aino); + dispose_aino (unit, aip, aino); + i++; + } } } + /* In the previous loop, we went through all children of one + parent. Re-arrange the recycled list so that we'll find a + different parent the next time around. */ + old_prev = unit->rootnode.prev; + do { + unit->rootnode.next->prev = unit->rootnode.prev; + unit->rootnode.prev->next = unit->rootnode.next; + unit->rootnode.next = unit->rootnode.prev; + unit->rootnode.prev = unit->rootnode.prev->prev; + unit->rootnode.prev->next = unit->rootnode.next->prev = &unit->rootnode; + } while (unit->rootnode.prev != old_prev + && unit->rootnode.prev->parent == parent); } #if 0 { char buffer[40]; sprintf (buffer, "%d ainos reaped.\n", i); - write_log (buffer); + TRACE ((buffer)); } #endif } @@ -698,7 +772,7 @@ static void update_child_names (Unit *un char *name_start; char *new_name; char dirsep[2] = { FSDB_DIR_SEPARATOR, '\0' }; - + a->parent = parent; name_start = strrchr (a->nname, FSDB_DIR_SEPARATOR); if (name_start == 0) { @@ -727,13 +801,31 @@ static void move_aino_children (Unit *un static void delete_aino (Unit *unit, a_inode *aino) { a_inode **aip; - int hash; TRACE(("deleting aino %x\n", aino->uniq)); aino->dirty = 1; aino->deleted = 1; de_recycle_aino (unit, aino); + + /* If any ExKeys are currently pointing at us, advance them. */ + if (aino->parent->exnext_count > 0) { + int i; + TRACE(("entering exkey validation\n")); + for (i = 0; i < EXKEYS; i++) { + ExamineKey *k = unit->examine_keys + i; + if (k->uniq == 0) + continue; + if (k->aino == aino->parent) { + TRACE(("Same parent found for %d\n", i)); + if (k->curr_file == aino) { + k->curr_file = aino->sibling; + TRACE(("Advancing curr_file\n")); + } + } + } + } + aip = &aino->parent->child; while (*aip != aino && *aip != 0) aip = &(*aip)->sibling; @@ -767,9 +859,14 @@ static a_inode *lookup_sub (a_inode *dir } cp = &c->sibling; } - *cp = c->sibling; - c->sibling = dir->child; - dir->child = c; + if (! dir->locked_children) { + /* Move to the front to speed up repeated lookups. Don't do this if + an ExNext is going on in this directory, or we'll terminally + confuse it. */ + *cp = c->sibling; + c->sibling = dir->child; + dir->child = c; + } return retval; } @@ -818,7 +915,7 @@ static char *get_nname (Unit *unit, a_in char *p = 0; *modified_rel = 0; - + /* If we have a mapping of some other aname to "rel", we must pretend * it does not exist. * This can happen for example if an Amiga program creates a @@ -851,7 +948,7 @@ static char *create_nname (Unit *unit, a char *p; /* We are trying to create a file called REL. */ - + /* If the name is used otherwise in the directory (or globally), we * need a new unique nname. */ if (fsdb_name_invalid (rel) || fsdb_used_as_nname (base, rel)) { @@ -898,6 +995,14 @@ static void init_child_aino (Unit *unit, aino->dirty = 0; aino->deleted = 0; + /* For directories - this one isn't being ExNext()ed yet. */ + aino->locked_children = 0; + aino->exnext_count = 0; + /* But the parent might be. */ + if (base->exnext_count) { + unit->total_locked_ainos++; + base->locked_children++; + } /* Update tree structure */ aino->parent = base; aino->child = 0; @@ -936,7 +1041,7 @@ static a_inode *new_child_aino (Unit *un init_child_aino (unit, base, aino); recycle_aino (unit, aino); - TRACE(("created aino %x, lookup\n", aino->uniq)); + TRACE(("created aino %x, lookup, amigaos_mode %d\n", aino->uniq, aino->amigaos_mode)); return aino; } @@ -1081,7 +1186,7 @@ static a_inode *get_aino (Unit *unit, a_ return curr; } -static uae_u32 startup_handler (void) +static uae_u32 startup_handler (TrapContext *dummy) { /* Just got the startup packet. It's in A4. DosBase is in A2, * our allocated volume structure is in D6, A5 is a pointer to @@ -1133,6 +1238,7 @@ static uae_u32 startup_handler (void) unit->ui.volname = my_strdup (uinfo->volname); /* might free later for rename */ unit->ui.rootdir = uinfo->rootdir; unit->ui.readonly = uinfo->readonly; + unit->ui.bootpri = uinfo->bootpri; unit->ui.unit_pipe = uinfo->unit_pipe; unit->ui.back_pipe = uinfo->back_pipe; unit->cmds_complete = 0; @@ -1140,9 +1246,10 @@ static uae_u32 startup_handler (void) unit->cmds_acked = 0; for (i = 0; i < EXKEYS; i++) { unit->examine_keys[i].aino = 0; - unit->examine_keys[i].dir = 0; + unit->examine_keys[i].curr_file = 0; unit->examine_keys[i].uniq = 0; } + unit->total_locked_ainos = 0; unit->next_exkey = 1; unit->keys = 0; unit->a_uniq = unit->key_uniq = 0; @@ -1213,7 +1320,7 @@ static void do_info (Unit *unit, dpacket packet, uaecptr info) { struct fs_usage fsu; - + if (get_fs_usage (unit->ui.rootdir, 0, &fsu) != 0) { PUT_PCK_RES1 (packet, DOS_FALSE); PUT_PCK_RES2 (packet, dos_errno ()); @@ -1512,12 +1619,16 @@ put_time (long days, long mins, long tic return t; } -static void free_exkey (ExamineKey *ek) +static void free_exkey (Unit *unit, ExamineKey *ek) { + if (--ek->aino->exnext_count == 0) { + TRACE (("Freeing ExKey and reducing total_locked from %d by %d\n", + unit->total_locked_ainos, ek->aino->locked_children)); + unit->total_locked_ainos -= ek->aino->locked_children; + ek->aino->locked_children = 0; + } ek->aino = 0; ek->uniq = 0; - if (ek->dir) - closedir (ek->dir); } static ExamineKey *lookup_exkey (Unit *unit, uae_u32 uniq) @@ -1539,7 +1650,7 @@ static ExamineKey *lookup_exkey (Unit *u static ExamineKey *new_exkey (Unit *unit, a_inode *aino) { uae_u32 uniq; - uae_u32 oldest = 0xFFFFFFFF; + uae_u32 oldest = 0xFFFFFFFE; ExamineKey *ek, *oldest_ek = 0; int i; @@ -1559,23 +1670,44 @@ static ExamineKey *new_exkey (Unit *unit } /* This message should usually be harmless. */ write_log ("Houston, we have a problem.\n"); - free_exkey (oldest_ek); + free_exkey (unit, oldest_ek); ek = oldest_ek; found: uniq = unit->next_exkey; - if (uniq == 0xFFFFFFFF) { + if (uniq >= 0xFFFFFFFE) { /* Things will probably go wrong, but most likely the Amiga will crash * before this happens because of something else. */ uniq = 1; } unit->next_exkey = uniq+1; ek->aino = aino; - ek->dir = 0; + ek->curr_file = 0; ek->uniq = uniq; return ek; } +static void move_exkeys (Unit *unit, a_inode *from, a_inode *to) +{ + int i; + unsigned long tmp = 0; + for (i = 0; i < EXKEYS; i++) { + ExamineKey *k = unit->examine_keys + i; + if (k->uniq == 0) + continue; + if (k->aino == from) { + k->aino = to; + tmp++; + } + } + if (tmp != from->exnext_count) + write_log ("filesys.c: Bug in ExNext bookkeeping. BAD.\n"); + to->exnext_count = from->exnext_count; + to->locked_children = from->locked_children; + from->exnext_count = 0; + from->locked_children = 0; +} + static void get_fileinfo (Unit *unit, dpacket packet, uaecptr info, a_inode *aino) { @@ -1624,7 +1756,10 @@ get_fileinfo (Unit *unit, dpacket packet else { TRACE(("comment=\"%s\"\n", aino->comment)); i = 144; - n = strlen (x = aino->comment); + x = aino->comment; + if (! x) + x = ""; + n = strlen (x); if (n > 78) n = 78; put_byte (info + i, n); i++; @@ -1636,47 +1771,6 @@ get_fileinfo (Unit *unit, dpacket packet PUT_PCK_RES1 (packet, DOS_TRUE); } -static void do_examine (Unit *unit, dpacket packet, ExamineKey *ek, uaecptr info) -{ - struct dirent de_space; - struct dirent* de; - a_inode *aino; - uae_u32 err; - - if (!ek->dir) { - ek->dir = opendir (ek->aino->nname); - } - if (!ek->dir) { - free_exkey (ek); - PUT_PCK_RES1 (packet, DOS_FALSE); - PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES); - return; - } - - do { - de = my_readdir (ek->dir, &de_space); - } while (de && fsdb_name_invalid (de->d_name)); - - if (!de) { - TRACE(("no more entries\n")); - free_exkey (ek); - PUT_PCK_RES1 (packet, DOS_FALSE); - PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES); - return; - } - - TRACE(("entry=\"%s\"\n", de->d_name)); - aino = lookup_child_aino_for_exnext (unit, ek->aino, de->d_name, &err); - if (err != 0) { - write_log ("Severe problem in ExNext.\n"); - free_exkey (ek); - PUT_PCK_RES1 (packet, DOS_FALSE); - PUT_PCK_RES2 (packet, err); - return; - } - get_fileinfo (unit, packet, info, aino); -} - static void action_examine_object (Unit *unit, dpacket packet) { uaecptr lock = GET_PCK_ARG1 (packet) << 2; @@ -1698,6 +1792,61 @@ static void action_examine_object (Unit put_long (info, 0); } +/* Read a directory's contents, create a_inodes for each file, and + mark them as locked in memory so that recycle_aino will not reap + them. + We do this to avoid problems with the host OS: we don't want to + leave the directory open on the host side until all ExNext()s have + finished - they may never finish! */ + +static void populate_directory (Unit *unit, a_inode *base) +{ + DIR *d = opendir (base->nname); + a_inode *aino; + + for (aino = base->child; aino; aino = aino->sibling) { + base->locked_children++; + unit->total_locked_ainos++; + } + TRACE(("Populating directory, child %p, locked_children %d\n", + base->child, base->locked_children)); + for (;;) { + struct dirent de_space; + struct dirent *de; + uae_u32 err; + + /* Find next file that belongs to the Amiga fs (skipping things + like "..", "." etc. */ + do { + de = my_readdir (d, &de_space); + } while (de && fsdb_name_invalid (de->d_name)); + if (! de) + break; + /* This calls init_child_aino, which will notice that the parent is + being ExNext()ed, and it will increment the locked counts. */ + aino = lookup_child_aino_for_exnext (unit, base, de->d_name, &err); + } + closedir (d); +} + +static void do_examine (Unit *unit, dpacket packet, ExamineKey *ek, uaecptr info) +{ + if (ek->curr_file == 0) + goto no_more_entries; + + get_fileinfo (unit, packet, info, ek->curr_file); + ek->curr_file = ek->curr_file->sibling; + TRACE (("curr_file set to %p %s\n", ek->curr_file, + ek->curr_file ? ek->curr_file->aname : "NULL")); + return; + + no_more_entries: + TRACE(("no more entries\n")); + free_exkey (unit, ek); + PUT_PCK_RES1 (packet, DOS_FALSE); + PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES); +} + static void action_examine_next (Unit *unit, dpacket packet) { uaecptr lock = GET_PCK_ARG1 (packet) << 2; @@ -1717,21 +1866,34 @@ static void action_examine_next (Unit *u uniq = get_long (info); if (uniq == 0) { write_log ("ExNext called for a file! (Houston?)\n"); - PUT_PCK_RES1 (packet, DOS_FALSE); - PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES); - return; - } else if (uniq == 0xFFFFFFFF) { - ek = new_exkey(unit, aino); - } else + goto no_more_entries; + } else if (uniq == 0xFFFFFFFE) + goto no_more_entries; + else if (uniq == 0xFFFFFFFF) { + TRACE(("Creating new ExKey\n")); + ek = new_exkey (unit, aino); + if (ek) { + if (aino->exnext_count++ == 0) + populate_directory (unit, aino); + } + ek->curr_file = aino->child; + TRACE(("Initial curr_file: %p %s\n", ek->curr_file, + ek->curr_file ? ek->curr_file->aname : "NULL")); + } else { + TRACE(("Looking up ExKey\n")); ek = lookup_exkey (unit, get_long (info)); + } if (ek == 0) { write_log ("Couldn't find a matching ExKey. Prepare for trouble.\n"); - PUT_PCK_RES1 (packet, DOS_FALSE); - PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES); - return; + goto no_more_entries; } put_long (info, ek->uniq); do_examine (unit, packet, ek, info); + return; + + no_more_entries: + PUT_PCK_RES1 (packet, DOS_FALSE); + PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES); } static void do_find (Unit *unit, dpacket packet, int mode, int create, int fallback) @@ -1871,9 +2033,9 @@ action_fh_from_lock (Unit *unit, dpacket mode = aino->amigaos_mode; /* Use same mode for opened filehandle as existing Lock() */ prepare_for_open (aino->nname); - - openmode = (((mode & A_FIBF_READ) == 0 ? O_WRONLY - : (mode & A_FIBF_WRITE) == 0 ? O_RDONLY + TRACE ((" mode is %d\n", mode)); + openmode = (((mode & A_FIBF_READ) ? O_WRONLY + : (mode & A_FIBF_WRITE) ? O_RDONLY : O_RDWR)); /* the files on CD really can have the write-bit set. */ @@ -2009,7 +2171,7 @@ action_read (Unit *unit, dpacket packet) int i; PUT_PCK_RES1 (packet, actual); for (i = 0; i < actual; i++) - put_byte(addr + i, buf[i]); + put_byte (addr + i, buf[i]); k->file_pos += actual; } free (buf); @@ -2048,7 +2210,7 @@ action_write (Unit *unit, dpacket packet } for (i = 0; i < size; i++) - buf[i] = get_byte(addr + i); + buf[i] = get_byte (addr + i); PUT_PCK_RES1 (packet, write(k->fd, buf, size)); if (GET_PCK_RES1 (packet) != size) @@ -2081,6 +2243,22 @@ action_seek (Unit *unit, dpacket packet) TRACE(("ACTION_SEEK(%s,%d,%d)\n", k->aino->nname, pos, mode)); old = lseek (k->fd, 0, SEEK_CUR); + { + uae_s32 temppos; + long filesize = lseek (k->fd, 0, SEEK_END); + lseek (k->fd, old, SEEK_SET); + + if (whence == SEEK_CUR) temppos = old + pos; + if (whence == SEEK_SET) temppos = pos; + if (whence == SEEK_END) temppos = filesize + pos; + if (filesize < temppos) { + res = -1; + PUT_PCK_RES1 (packet,res); + PUT_PCK_RES2 (packet, ERROR_SEEK_ERROR); + return; + } + } + res = lseek (k->fd, pos, whence); if (-1 == res) { @@ -2190,7 +2368,7 @@ action_change_mode (Unit *unit, dpacket /* will be CHANGE_FH or CHANGE_LOCK value */ long type = GET_PCK_ARG1 (packet); /* either a file-handle or lock */ - uaecptr object = GET_PCK_ARG2 (packet) << 2; + uaecptr object = GET_PCK_ARG2 (packet) << 2; /* will be EXCLUSIVE_LOCK/SHARED_LOCK if CHANGE_LOCK, * or MODE_OLDFILE/MODE_NEWFILE/MODE_READWRITE if CHANGE_FH */ long mode = GET_PCK_ARG3 (packet); @@ -2569,6 +2747,8 @@ action_rename_object (Unit *unit, dpacke a2->comment = a1->comment; a1->comment = 0; a2->amigaos_mode = a1->amigaos_mode; + a2->uniq = a1->uniq; + move_exkeys (unit, a1, a2); move_aino_children (unit, a1, a2); delete_aino (unit, a1); PUT_PCK_RES1 (packet, DOS_TRUE); @@ -2627,7 +2807,7 @@ action_flush (Unit *unit, dpacket packet * know whether AmigaOS takes care of that, but this does. */ static uae_sem_t singlethread_int_sem; -static uae_u32 exter_int_helper (void) +static uae_u32 exter_int_helper (TrapContext *dummy) { UnitInfo *uip = current_mountinfo->ui; uaecptr port; @@ -2834,6 +3014,11 @@ static void *filesys_thread (void *unit_ /* The message is sent by our interrupt handler, so make sure an interrupt * happens. */ uae_int_requested = 1; + + uae_sem_wait (&packet_counter_sem); + active_fs_packets--; + uae_sem_post (&packet_counter_sem); + /* Send back the locks. */ if (get_long (ui->self->locklist) != 0) write_comm_pipe_int (ui->back_pipe, (int)(get_long (ui->self->locklist)), 0); @@ -2844,7 +3029,7 @@ static void *filesys_thread (void *unit_ #endif /* Talk about spaghetti code... */ -static uae_u32 filesys_handler (void) +static uae_u32 filesys_handler (TrapContext *dummy) { Unit *unit = find_unit (m68k_areg (regs, 5)); uaecptr packet_addr = m68k_dreg (regs, 3); @@ -2877,6 +3062,10 @@ static uae_u32 filesys_handler (void) put_long (m68k_areg (regs, 3), get_long (get_long (morelocks))); put_long (get_long (morelocks), 0); + uae_sem_wait (&packet_counter_sem); + active_fs_packets++; + uae_sem_post (&packet_counter_sem); + /* The packet wasn't processed yet. */ do_put_mem_long ((uae_u32 *)(msg + 4), 0); write_comm_pipe_pvoid (unit->ui.unit_pipe, (void *)pck, 0); @@ -2908,21 +3097,12 @@ static void reset_uaedevices (void) current_cdrom = 0; } -static int get_new_device (char **devname, uaecptr *devname_amiga, int cdrom) +static void init_filesys_diagentry (void) { - int result; - char buffer[80]; - - if (cdrom) { - sprintf (buffer, "CD%d", current_cdrom); - result = current_cdrom++; - } else { - sprintf (buffer, "DH%d", current_deviceno); - result = current_deviceno++; - } - - *devname_amiga = ds (*devname = my_strdup (buffer)); - return result; + do_put_mem_long ((uae_u32 *)(filesysory + 0x2100), EXPANSION_explibname); + do_put_mem_long ((uae_u32 *)(filesysory + 0x2104), filesys_configdev); + do_put_mem_long ((uae_u32 *)(filesysory + 0x2108), EXPANSION_doslibname); + do_put_mem_long ((uae_u32 *)(filesysory + 0x210c), current_mountinfo->num_units); } void filesys_start_threads (void) @@ -2933,14 +3113,14 @@ void filesys_start_threads (void) current_mountinfo = dup_mountinfo (currprefs.mountinfo); reset_uaedevices (); - + uip = current_mountinfo->ui; for (i = 0; i < current_mountinfo->num_units; i++) { - uip[i].unit_pipe = 0; - uip[i].devno = get_new_device (&uip[i].devname, &uip[i].devname_amiga, 0); + UnitInfo *ui = &uip[i]; + ui->unit_pipe = 0; #ifdef UAE_FILESYS_THREADS - if (! is_hardfile (current_mountinfo, i)) { + if (hardfile_fs_type (current_mountinfo, i) == FILESYS_VIRTUAL) { uip[i].unit_pipe = (smp_comm_pipe *)xmalloc (sizeof (smp_comm_pipe)); uip[i].back_pipe = (smp_comm_pipe *)xmalloc (sizeof (smp_comm_pipe)); init_comm_pipe (uip[i].unit_pipe, 50, 3); @@ -2971,6 +3151,16 @@ void filesys_reset (void) current_mountinfo = 0; } +static void free_all_ainos (Unit *u, a_inode *parent) +{ + a_inode *a; + while (a = parent->child) { + free_all_ainos (u, a); + dispose_aino (u, &parent->child, a); + } +} + + void filesys_prepare_reset (void) { UnitInfo *uip = current_mountinfo->ui; @@ -2992,18 +3182,14 @@ void filesys_prepare_reset (void) #endif u = units; while (u != 0) { - while (u->rootnode.next != &u->rootnode) { - a_inode *b; - a_inode *a = u->rootnode.next; - u->rootnode.next = a->next; - de_recycle_aino (u, a); - dispose_aino (u, &b, a); - } + free_all_ainos (u, &u->rootnode); + u->rootnode.next = u->rootnode.prev = &u->rootnode; + u->aino_cache_size = 0; u = u->next; } } -static uae_u32 filesys_diagentry (void) +static uae_u32 filesys_diagentry (TrapContext *dummy) { uaecptr resaddr = m68k_areg (regs, 2) + 0x10; uaecptr start = resaddr; @@ -3012,11 +3198,7 @@ static uae_u32 filesys_diagentry (void) TRACE (("filesystem: diagentry called\n")); filesys_configdev = m68k_areg (regs, 3); - - do_put_mem_long ((uae_u32 *)(filesysory + 0x2100), EXPANSION_explibname); - do_put_mem_long ((uae_u32 *)(filesysory + 0x2104), filesys_configdev); - do_put_mem_long ((uae_u32 *)(filesysory + 0x2108), EXPANSION_doslibname); - do_put_mem_long ((uae_u32 *)(filesysory + 0x210c), current_mountinfo->num_units); + init_filesys_diagentry (); uae_sem_init (&singlethread_int_sem, 0, 1); if (ROM_hardfile_resid != 0) { @@ -3033,7 +3215,7 @@ static uae_u32 filesys_diagentry (void) } resaddr += 0x1A; tmp = resaddr; - + /* The good thing about this function is that it always gets called * when we boot. So we could put all sorts of stuff that wants to be done * here. @@ -3060,40 +3242,424 @@ static uae_u32 filesys_diagentry (void) tmp++; } } - put_word (resaddr, 0x7001); /* moveq.l #1,d0 */ - put_word (resaddr + 2, RTS); + /* call setup_exter */ + put_word (resaddr + 0, 0x2079); + put_long (resaddr + 2, RTAREA_BASE + 28 + 4); /* move.l RTAREA_BASE+32,a0 */ + put_word (resaddr + 6, 0xd1fc); + put_long (resaddr + 8, RTAREA_BASE + 8 + 4); /* add.l #RTAREA_BASE+12,a0 */ + put_word (resaddr + 12, 0x4e90); /* jsr (a0) */ + put_word (resaddr + 14, 0x7001); /* moveq.l #1,d0 */ + put_word (resaddr + 16, RTS); m68k_areg (regs, 0) = residents; return 1; } +/* don't forget filesys.asm! */ +#define PP_MAXSIZE 4 * 96 +#define PP_FSSIZE 400 +#define PP_FSPTR 404 +#define PP_FSRES 408 +#define PP_EXPLIB 412 +#define PP_FSHDSTART 416 + +static uae_u32 REGPARAM2 filesys_dev_bootfilesys (TrapContext *dummy) +{ + uaecptr devicenode = m68k_areg (regs, 3); + uaecptr parmpacket = m68k_areg (regs, 1); + uaecptr fsres = get_long (parmpacket + PP_FSRES); + uaecptr fsnode; + uae_u32 dostype, dostype2; + int no = m68k_dreg (regs, 6); + int unit_no = no & 65535; + int type = hardfile_fs_type (current_mountinfo, unit_no); + + if (type == FILESYS_VIRTUAL) + return 0; + dostype = get_long (parmpacket + 80); + fsnode = get_long (fsres + 18); + while (get_long (fsnode)) { + dostype2 = get_long (fsnode + 14); + if (dostype2 == dostype) { + if (get_long (fsnode + 22) & (1 << 7)) { + put_long (devicenode + 32, get_long (fsnode + 54)); /* dn_SegList */ + put_long (devicenode + 36, -1); /* dn_GlobalVec */ + } + return 1; + } + fsnode = get_long (fsnode); + } + return 0; +} + /* Remember a pointer AmigaOS gave us so we can later use it to identify * which unit a given startup message belongs to. */ -static uae_u32 filesys_dev_remember (void) +static uae_u32 filesys_dev_remember (TrapContext *dummy) { - int unit_no = m68k_dreg (regs, 6); + int no = m68k_dreg (regs, 6); + int unit_no = no & 65535; + int sub_no = no >> 16; + UnitInfo *uip = ¤t_mountinfo->ui[unit_no]; uaecptr devicenode = m68k_areg (regs, 3); + uaecptr parmpacket = m68k_areg (regs, 1); - current_mountinfo->ui[unit_no].startup = get_long (devicenode + 28); + /* copy filesystem loaded from RDB */ + if (get_long (parmpacket + PP_FSPTR)) { + int i; + for (i = 0; i < uip->rdb_filesyssize; i++) + put_byte (get_long (parmpacket + PP_FSPTR) + i, uip->rdb_filesysstore[i]); + free (uip->rdb_filesysstore); + uip->rdb_filesysstore = 0; + uip->rdb_filesyssize = 0; + } + if ((uae_s32)m68k_dreg (regs, 3) >= 0) + uip->startup = get_long (devicenode + 28); return devicenode; } +static int legalrdbblock (UnitInfo *uip, int block) +{ + if (block <= 0) + return 0; + if (block >= uip->hf.size / uip->hf.blocksize) + return 0; + return 1; +} + +static int rl (uae_u8 *p) +{ + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); +} + +static int rdb_checksum (char *id, uae_u8 *p, int block) +{ + uae_u32 sum = 0; + int i, blocksize; + + if (memcmp (id, p, 4)) + return 0; + blocksize = rl (p + 4); + if (blocksize < 1 || blocksize * 4 > FILESYS_MAX_BLOCKSIZE) + return 0; + for (i = 0; i < blocksize; i++) + sum += rl (p + i * 4); + sum = -sum; + if (sum) { + write_log ("RDB: block %d ('%s') checksum error\n", block, id); + return 0; + } + return 1; +} + +static void dump_partinfo (char *name, int num, uaecptr pp, int partblock) +{ + uae_u32 dostype = get_long (pp + 80); + write_log ("RDB: '%s' dostype=%08.8X. PartBlock=%d\n", name, dostype, partblock); + write_log ("BlockSize: %d, Surfaces: %d, SectorsPerBlock %d\n", + get_long (pp + 20) * 4, get_long (pp + 28), get_long (pp + 32)); + write_log ("SectorsPerTrack: %d, Reserved: %d, LowCyl %d, HighCyl %d\n", + get_long (pp + 36), get_long (pp + 40), get_long (pp + 52), get_long (pp + 56)); + write_log ("Buffers: %d, BufMemType: %08.8x, MaxTransfer: %08.8x, BootPri: %d\n", + get_long (pp + 60), get_long (pp + 64), get_long (pp + 68), get_long (pp + 76)); +} + +static char *device_dupfix (uaecptr expbase, char *devname) +{ + uaecptr bnode, dnode, name; + int len, i, modified; + char dname[256], newname[256]; + + strcpy (newname, devname); + modified = 1; + while (modified) { + modified = 0; + bnode = get_long (expbase + 74); /* expansion.library bootnode list */ + while (get_long (bnode)) { + dnode = get_long (bnode + 16); /* device node */ + name = get_long (dnode + 40) << 2; /* device name BSTR */ + len = get_byte (name); + for (i = 0; i < len; i++) + dname[i] = get_byte (name + 1 + i); + dname[len] = 0; + for (;;) { + if (strcasecmp (newname, dname) == 0) { + if (strlen (newname) > 2 && newname[strlen (newname) - 2] == '_') { + newname[strlen (newname) - 1]++; + } else { + strcat (newname, "_0"); + } + modified = 1; + } else { + break; + } + } + bnode = get_long (bnode); + } + } + return my_strdup (newname); +} + +#define rdbmnt write_log ("Mounting uaehf.device %d (%d) (size=%llu):\n", unit_no, partnum, hfd->size); + +static int rdb_mount (UnitInfo *uip, int unit_no, int partnum, uaecptr parmpacket) +{ + int lastblock = 63, blocksize, readblocksize, badblock, driveinitblock; + uae_u8 bufrdb[FILESYS_MAX_BLOCKSIZE], *buf = 0; + uae_u8 *fsmem = 0; + int rdblock, partblock, fileblock, lsegblock, i; + uae_u32 flags; + struct hardfiledata *hfd = &uip->hf; + uae_u32 dostype; + uaecptr fsres, fsnode; + int err = 0; + int oldversion, oldrevision; + int newversion, newrevision; + + if (hfd->blocksize == 0) { + rdbmnt + write_log ("failed, blocksize == 0\n"); + return -1; + } + if (lastblock * hfd->blocksize > hfd->size) { + rdbmnt + write_log ("failed, too small (%d*%d > %I64u)\n", lastblock, hfd->blocksize, hfd->size); + return -2; + } + for (rdblock = 0; rdblock < lastblock; rdblock++) { + hdf_read (hfd, bufrdb, rdblock * hfd->blocksize, hfd->blocksize); + if (rdb_checksum ("RDSK", bufrdb, rdblock)) + break; + hdf_read (hfd, bufrdb, rdblock * hfd->blocksize, hfd->blocksize); + if (!memcmp ("RDSK", bufrdb, 4)) { + bufrdb[0xdc] = 0; + bufrdb[0xdd] = 0; + bufrdb[0xde] = 0; + bufrdb[0xdf] = 0; +#if 0 + if (rdb_checksum ("RDSK", bufrdb, rdblock)) { + write_log ("Windows 95/98/ME trashed RDB detected, fixing..\n"); + hdf_write (hfd, bufrdb, rdblock * hfd->blocksize, hfd->blocksize); + break; + } +#endif + } + } + if (rdblock == lastblock) { + rdbmnt + write_log ("failed, no RDB detected\n"); + return -2; + } + blocksize = rl (bufrdb + 16); + readblocksize = blocksize > hfd->blocksize ? blocksize : hfd->blocksize; + badblock = rl (bufrdb + 24); + if (badblock != -1) { + rdbmnt + write_log ("RDB: badblock list is not yet supported. Contact the author.\n"); + return -2; + } + driveinitblock = rl (bufrdb + 36); + if (driveinitblock != -1) { + rdbmnt + write_log ("RDB: driveinit is not yet supported. Contact the author.\n"); + return -2; + } + hfd->cylinders = rl (bufrdb + 64); + hfd->sectors = rl (bufrdb + 68); + hfd->heads = rl (bufrdb + 72); + fileblock = rl (bufrdb + 32); + + if (partnum == 0) { + write_log ("RDB: RDSK detected at %d, FSHD=%d, C=%d S=%d H=%d\n", + rdblock, fileblock, hfd->cylinders, hfd->sectors, hfd->heads); + } + + buf = (uae_u8*)xmalloc (readblocksize); + for (i = 0; i <= partnum; i++) { + if (i == 0) + partblock = rl (bufrdb + 28); + else + partblock = rl (buf + 4 * 4); + if (!legalrdbblock (uip, partblock)) { + err = -2; + goto error; + } + memset (buf, 0, readblocksize); + hdf_read (hfd, buf, partblock * hfd->blocksize, readblocksize); + if (!rdb_checksum ("PART", buf, partblock)) { + err = -2; + goto error; + } + } + + rdbmnt + flags = rl (buf + 20); + if (flags & 2) { /* do not mount */ + err = -1; + write_log ("RDB: Automount disabled, not mounting\n"); + goto error; + } + + if (!(flags & 1)) /* not bootable */ + m68k_dreg (regs, 7) = 0; + + buf[37 + buf[36]] = 0; /* zero terminate BSTR */ + uip->rdb_devname_amiga[partnum] + = ds (device_dupfix (get_long (parmpacket + PP_EXPLIB), buf + 37)); + put_long (parmpacket, uip->rdb_devname_amiga[partnum]); /* name */ + put_long (parmpacket + 4, ROM_hardfile_resname); + put_long (parmpacket + 8, uip->devno); + put_long (parmpacket + 12, 0); /* Device flags */ + for (i = 0; i < PP_MAXSIZE; i++) + put_byte (parmpacket + 16 + i, buf[128 + i]); + dump_partinfo (buf + 37, uip->devno, parmpacket, partblock); + dostype = get_long (parmpacket + 80); + + if (dostype == 0) { + write_log ("RDB: mount failed, dostype=0\n"); + err = -1; + goto error; + } + + if (hfd->cylinders * hfd->sectors * hfd->heads * blocksize > hfd->size) + write_log ("RDB: WARNING: end of partition > size of disk!\n"); + + err = 2; + + /* load custom filesystems if needed */ + if (fileblock == -1 || !legalrdbblock (uip, fileblock)) + goto error; + + fsres = get_long (parmpacket + PP_FSRES); + if (!fsres) { + write_log ("RDB: FileSystem.resource not found, this shouldn't happen!\n"); + goto error; + } + fsnode = get_long (fsres + 18); + while (get_long (fsnode)) { + if (get_long (fsnode + 14) == dostype) + break; + fsnode = get_long (fsnode); + } + oldversion = oldrevision = -1; + if (get_long (fsnode)) { + oldversion = get_word (fsnode + 18); + oldrevision = get_word (fsnode + 20); + } else { + fsnode = 0; + } + + for (;;) { + if (fileblock == -1) { + if (!fsnode) + write_log ("RDB: required FS %08.8X not in FileSystem.resource or in RDB\n", dostype); + goto error; + } + if (!legalrdbblock (uip, fileblock)) { + write_log ("RDB: corrupt FSHD pointer %d\n", fileblock); + goto error; + } + memset (buf, 0, readblocksize); + hdf_read (hfd, buf, fileblock * hfd->blocksize, readblocksize); + if (!rdb_checksum ("FSHD", buf, fileblock)) { + write_log ("RDB: checksum error in FSHD block %d\n", fileblock); + goto error; + } + fileblock = rl (buf + 16); + if ((dostype >> 8) == (rl (buf + 32) >> 8)) + break; + } + newversion = (buf[36] << 8) | buf[37]; + newrevision = (buf[38] << 8) | buf[39]; + + write_log ("RDB: RDB filesystem %08.8X version %d.%d\n", dostype, newversion, newrevision); + if (fsnode) { + write_log ("RDB: %08.8X in FileSystem.resouce version %d.%d\n", dostype, oldversion, oldrevision); + } + if (newversion * 65536 + newrevision <= oldversion * 65536 + oldrevision && oldversion >= 0) { + write_log ("RDB: FS in FileSystem.resource is newer or same, ignoring RDB filesystem\n"); + goto error; + } + + for (i = 0; i < 140; i++) + put_byte (parmpacket + PP_FSHDSTART + i, buf[32 + i]); + put_long (parmpacket + PP_FSHDSTART, dostype); + /* we found required FSHD block */ + fsmem = (uae_u8*)xmalloc (262144); + lsegblock = rl (buf + 72); + i = 0; + for (;;) { + int pb = lsegblock; + if (!legalrdbblock (uip, lsegblock)) + goto error; + memset (buf, 0, readblocksize); + hdf_read (hfd, buf, lsegblock * hfd->blocksize, readblocksize); + if (!rdb_checksum ("LSEG", buf, lsegblock)) + goto error; + lsegblock = rl (buf + 16); + if (lsegblock == pb) + goto error; + memcpy (fsmem + i * (blocksize - 20), buf + 20, blocksize - 20); + i++; + if (lsegblock == -1) + break; + } + write_log ("RDB: Filesystem loaded, %d bytes\n", i * (blocksize - 20)); + put_long (parmpacket + PP_FSSIZE, i * (blocksize - 20)); /* RDB filesystem size hack */ + uip->rdb_filesysstore = fsmem; + uip->rdb_filesyssize = i * (blocksize - 20); + free (buf); + return 2; +error: + free (buf); + free (fsmem); + return err; +} + +static void get_new_device (int type, uaecptr parmpacket, char **devname, + uaecptr *devname_amiga, int unit_no) +{ + char buffer[80]; + + sprintf (buffer, "DH%d", unit_no); + + if (*devname == NULL) + *devname = device_dupfix (get_long (parmpacket + PP_EXPLIB), buffer); + *devname_amiga = ds (*devname); + if (type == FILESYS_VIRTUAL) + write_log ("FS: mounted virtual unit %s\n", buffer); + else + write_log ("FS: mounted HDF unit %s\n", buffer); +} + /* Fill in per-unit fields of a parampacket */ -static uae_u32 filesys_dev_storeinfo (void) +static uae_u32 filesys_dev_storeinfo (TrapContext *dummy) { UnitInfo *uip = current_mountinfo->ui; - int unit_no = m68k_dreg (regs, 6); + int no = m68k_dreg (regs, 6); + int unit_no = no & 65535; + int sub_no = no >> 16; + int type = hardfile_fs_type (current_mountinfo, unit_no); uaecptr parmpacket = m68k_areg (regs, 0); - put_long (parmpacket, current_mountinfo->ui[unit_no].devname_amiga); - put_long (parmpacket + 4, is_hardfile (current_mountinfo, unit_no) ? ROM_hardfile_resname : fsdevname); + if (type == FILESYS_HARDFILE_RDB || type == FILESYS_HARDDRIVE) { + /* RDB hardfile */ + uip[unit_no].devno = unit_no; + return rdb_mount (&uip[unit_no], unit_no, sub_no, parmpacket); + } + /* No subunits for normal filesystems and hardfiles. */ + if (sub_no) + return -2; + get_new_device (type, parmpacket, &uip[unit_no].devname, &uip[unit_no].devname_amiga, unit_no); + uip[unit_no].devno = unit_no; + put_long (parmpacket, uip[unit_no].devname_amiga); + put_long (parmpacket + 4, type != FILESYS_VIRTUAL ? ROM_hardfile_resname : fsdevname); put_long (parmpacket + 8, uip[unit_no].devno); put_long (parmpacket + 12, 0); /* Device flags */ put_long (parmpacket + 16, 16); /* Env. size */ put_long (parmpacket + 20, uip[unit_no].hf.blocksize >> 2); /* longwords per block */ put_long (parmpacket + 24, 0); /* unused */ put_long (parmpacket + 28, uip[unit_no].hf.surfaces); /* heads */ - put_long (parmpacket + 32, 0); /* unused */ + put_long (parmpacket + 32, 1); /* sectors per block */ put_long (parmpacket + 36, uip[unit_no].hf.secspertrack); /* sectors per track */ put_long (parmpacket + 40, uip[unit_no].hf.reservedblocks); /* reserved blocks */ put_long (parmpacket + 44, 0); /* unused */ @@ -3104,11 +3670,11 @@ static uae_u32 filesys_dev_storeinfo (vo put_long (parmpacket + 64, 0); /* Buffer mem type */ put_long (parmpacket + 68, 0x7FFFFFFF); /* largest transfer */ put_long (parmpacket + 72, ~1); /* addMask (?) */ - put_long (parmpacket + 76, (uae_u32)-1); /* bootPri */ + put_long (parmpacket + 76, uip[unit_no].bootpri); /* bootPri */ put_long (parmpacket + 80, 0x444f5300); /* DOS\0 */ put_long (parmpacket + 84, 0); /* pad */ - return is_hardfile (current_mountinfo, unit_no); + return type; } void filesys_install (void) @@ -3118,38 +3684,45 @@ void filesys_install (void) TRACE (("Installing filesystem\n")); - ROM_filesys_resname = ds("UAEunixfs.resource"); - ROM_filesys_resid = ds("UAE unixfs 0.4"); + ROM_filesys_resname = ds ("UAEunixfs.resource"); + ROM_filesys_resid = ds ("UAE unixfs 0.4"); fsdevname = ds ("uae.device"); /* does not really exist */ ROM_filesys_diagentry = here(); calltrap (deftrap(filesys_diagentry)); - dw(0x4ED0); /* JMP (a0) - jump to code that inits Residents */ + dw (0x4ED0); /* JMP (a0) - jump to code that inits Residents */ loop = here (); + + org (RTAREA_BASE + 0xFF18); + calltrap (deftrap (filesys_dev_bootfilesys)); + dw (RTS); + /* Special trap for the assembly make_dev routine */ - org (0xF0FF20); + org (RTAREA_BASE + 0xFF20); calltrap (deftrap (filesys_dev_remember)); dw (RTS); - org (0xF0FF28); + org (RTAREA_BASE + 0xFF28); calltrap (deftrap (filesys_dev_storeinfo)); dw (RTS); - org (0xF0FF30); + org (RTAREA_BASE + 0xFF30); calltrap (deftrap (filesys_handler)); dw (RTS); - org (0xF0FF40); + org (RTAREA_BASE + 0xFF40); calltrap (deftrap (startup_handler)); dw (RTS); - org (0xF0FF50); + org (RTAREA_BASE + 0xFF50); calltrap (deftrap (exter_int_helper)); dw (RTS); org (loop); + + uae_sem_init (&packet_counter_sem, 0, 0); } void filesys_install_code (void) @@ -3157,114 +3730,9 @@ void filesys_install_code (void) align(4); /* The last offset comes from the code itself, look for it near the top. */ - EXPANSION_bootcode = here () + 8 + 0x14; + EXPANSION_bootcode = here () + 8 + 0x1c + 4; /* Ouch. Make sure this is _always_ a multiple of two bytes. */ - filesys_initcode = here() + 8 + 0x28; - db(0x00); db(0x00); db(0x00); db(0x10); db(0x00); db(0x00); db(0x00); db(0x00); - db(0x60); db(0x00); db(0x01); db(0xd4); db(0x00); db(0x00); db(0x01); db(0x3e); - db(0x00); db(0x00); db(0x00); db(0x28); db(0x00); db(0x00); db(0x00); db(0xbc); - db(0x00); db(0x00); db(0x00); db(0x14); db(0x43); db(0xfa); db(0x03); db(0x11); - db(0x4e); db(0xae); db(0xff); db(0xa0); db(0x20); db(0x40); db(0x20); db(0x28); - db(0x00); db(0x16); db(0x20); db(0x40); db(0x4e); db(0x90); db(0x4e); db(0x75); - db(0x48); db(0xe7); db(0xff); db(0xfe); db(0x2c); db(0x78); db(0x00); db(0x04); - db(0x2a); db(0x79); db(0x00); db(0xf0); db(0xff); db(0xfc); db(0x43); db(0xfa); - db(0x02); db(0xfb); db(0x70); db(0x24); db(0x7a); db(0x00); db(0x4e); db(0xae); - db(0xfd); db(0xd8); db(0x4a); db(0x80); db(0x66); db(0x0c); db(0x43); db(0xfa); - db(0x02); db(0xeb); db(0x70); db(0x00); db(0x7a); db(0x01); db(0x4e); db(0xae); - db(0xfd); db(0xd8); db(0x28); db(0x40); db(0x70); db(0x58); db(0x72); db(0x01); - db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x26); db(0x40); db(0x7e); db(0x54); - db(0x27); db(0xb5); db(0x78); db(0x00); db(0x78); db(0x00); db(0x59); db(0x87); - db(0x64); db(0xf6); db(0x7c); db(0x00); db(0xbc); db(0xad); db(0x01); db(0x0c); - db(0x64); db(0x14); db(0x20); db(0x4b); db(0x48); db(0xe7); db(0x02); db(0x10); - db(0x7e); db(0x01); db(0x61); db(0x00); db(0x00); db(0xc2); db(0x4c); db(0xdf); - db(0x08); db(0x40); db(0x52); db(0x86); db(0x60); db(0xe6); db(0x2c); db(0x78); - db(0x00); db(0x04); db(0x22); db(0x4c); db(0x4e); db(0xae); db(0xfe); db(0x62); - db(0x61); db(0x00); db(0x00); db(0x7c); db(0x2c); db(0x78); db(0x00); db(0x04); - db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x80); db(0x72); db(0x03); - db(0x74); db(0xf6); db(0x20); db(0x7c); db(0x00); db(0x20); db(0x00); db(0x00); - db(0x90); db(0x88); db(0x65); db(0x0a); db(0x67); db(0x08); db(0x78); db(0x00); - db(0x22); db(0x44); db(0x4e); db(0xae); db(0xfd); db(0x96); db(0x4c); db(0xdf); - db(0x7f); db(0xff); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x00); db(0x20); - db(0x70); db(0x00); db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x50); - db(0x4a); db(0x80); db(0x67); db(0x3c); db(0x2c); db(0x78); db(0x00); db(0x04); - db(0x70); db(0x02); db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x50); - db(0x0c); db(0x80); db(0x00); db(0x00); db(0x00); db(0x01); db(0x6d); db(0x1e); - db(0x6e); db(0x06); db(0x4e); db(0xae); db(0xfe); db(0x92); db(0x60); db(0xe8); - db(0x0c); db(0x80); db(0x00); db(0x00); db(0x00); db(0x02); db(0x6e); db(0x08); - db(0x20); db(0x01); db(0x4e); db(0xae); db(0xfe); db(0xbc); db(0x60); db(0xd8); - db(0x4e); db(0xae); db(0xfe); db(0x86); db(0x60); db(0xd2); db(0x70); db(0x04); - db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x50); db(0x70); db(0x01); - db(0x4c); db(0xdf); db(0x04); db(0x00); db(0x4e); db(0x75); db(0x2c); db(0x78); - db(0x00); db(0x04); db(0x70); db(0x1a); db(0x22); db(0x3c); db(0x00); db(0x01); - db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x22); db(0x40); - db(0x41); db(0xfa); db(0x01); db(0xf6); db(0x23); db(0x48); db(0x00); db(0x0a); - db(0x41); db(0xfa); db(0xff); db(0x92); db(0x23); db(0x48); db(0x00); db(0x0e); - db(0x41); db(0xfa); db(0xff); db(0x8a); db(0x23); db(0x48); db(0x00); db(0x12); - db(0x70); db(0x0d); db(0x4e); db(0xee); db(0xff); db(0x58); db(0x2a); db(0x79); - db(0x00); db(0xf0); db(0xff); db(0xfc); db(0x4e); db(0xb9); db(0x00); db(0xf0); - db(0xff); db(0x28); db(0x26); db(0x00); db(0xc0); db(0x85); db(0x66); db(0x00); - db(0xff); db(0x6a); db(0x2c); db(0x4c); db(0x4e); db(0xae); db(0xff); db(0x70); - db(0x26); db(0x40); db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x20); - db(0x70); db(0x00); db(0x27); db(0x40); db(0x00); db(0x08); db(0x27); db(0x40); - db(0x00); db(0x10); db(0x27); db(0x40); db(0x00); db(0x20); db(0x4a); db(0x83); - db(0x66); db(0x1c); db(0x27); db(0x7c); db(0x00); db(0x00); db(0x0f); db(0xa0); - db(0x00); db(0x14); db(0x43); db(0xfa); db(0xfe); db(0x80); db(0x20); db(0x09); - db(0xe4); db(0x88); db(0x27); db(0x40); db(0x00); db(0x20); db(0x27); db(0x7c); - db(0xff); db(0xff); db(0xff); db(0xff); db(0x00); db(0x24); db(0x4a); db(0x87); - db(0x67); db(0x36); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x70); db(0x14); - db(0x72); db(0x00); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x22); db(0x40); - db(0x70); db(0x00); db(0x22); db(0x80); db(0x23); db(0x40); db(0x00); db(0x04); - db(0x33); db(0x40); db(0x00); db(0x0e); db(0x30); db(0x3c); db(0x10); db(0xff); - db(0x90); db(0x06); db(0x33); db(0x40); db(0x00); db(0x08); db(0x23); db(0x6d); - db(0x01); db(0x04); db(0x00); db(0x0a); db(0x23); db(0x4b); db(0x00); db(0x10); - db(0x41); db(0xec); db(0x00); db(0x4a); db(0x4e); db(0xee); db(0xfe); db(0xf2); - db(0x20); db(0x4b); db(0x72); db(0x00); db(0x22); db(0x41); db(0x70); db(0xff); - db(0x2c); db(0x4c); db(0x4e); db(0xee); db(0xff); db(0x6a); db(0x2c); db(0x78); - db(0x00); db(0x04); db(0x70); db(0x00); db(0x22); db(0x40); db(0x4e); db(0xae); - db(0xfe); db(0xda); db(0x20); db(0x40); db(0x4b); db(0xe8); db(0x00); db(0x5c); - db(0x43); db(0xfa); db(0x01); db(0x3d); db(0x70); db(0x00); db(0x4e); db(0xae); - db(0xfd); db(0xd8); db(0x24); db(0x40); db(0x20); db(0x3c); db(0x00); db(0x00); - db(0x00); db(0x9d); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01); - db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x26); db(0x40); db(0x7c); db(0x00); - db(0x26); db(0x86); db(0x27); db(0x46); db(0x00); db(0x04); db(0x27); db(0x46); - db(0x00); db(0x08); db(0x7a); db(0x00); db(0x20); db(0x4d); db(0x4e); db(0xae); - db(0xfe); db(0x80); db(0x20); db(0x4d); db(0x4e); db(0xae); db(0xfe); db(0x8c); - db(0x28); db(0x40); db(0x26); db(0x2c); db(0x00); db(0x0a); db(0x70); db(0x00); - db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x40); db(0x60); db(0x76); - db(0x20); db(0x4d); db(0x4e); db(0xae); db(0xfe); db(0x80); db(0x20); db(0x4d); - db(0x4e); db(0xae); db(0xfe); db(0x8c); db(0x28); db(0x40); db(0x26); db(0x2c); - db(0x00); db(0x0a); db(0x66); db(0x38); db(0x70); db(0x01); db(0x4e); db(0xb9); - db(0x00); db(0xf0); db(0xff); db(0x50); db(0x45); db(0xeb); db(0x00); db(0x04); - db(0x20); db(0x52); db(0x20); db(0x08); db(0x67); db(0xda); db(0x22); db(0x50); - db(0x20); db(0x40); db(0x20); db(0x28); db(0x00); db(0x04); db(0x6a); db(0x16); - db(0x48); db(0xe7); db(0x00); db(0xc0); db(0x28); db(0x68); db(0x00); db(0x0a); - db(0x61); db(0x42); db(0x53); db(0x85); db(0x4c); db(0xdf); db(0x03); db(0x00); - db(0x24); db(0x89); db(0x20); db(0x49); db(0x60); db(0xdc); db(0x24); db(0x48); - db(0x20); db(0x49); db(0x60); db(0xd6); db(0x0c); db(0x85); db(0x00); db(0x00); - db(0x00); db(0x14); db(0x65); db(0x00); db(0x00); db(0x0a); db(0x70); db(0x01); - db(0x29); db(0x40); db(0x00); db(0x04); db(0x60); db(0x0e); db(0x61); db(0x2a); - db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x30); db(0x4a); db(0x80); - db(0x67); db(0x0c); db(0x52); db(0x85); db(0x28); db(0xab); db(0x00); db(0x04); - db(0x27); db(0x4c); db(0x00); db(0x04); db(0x60); db(0x8a); db(0x28); db(0x43); - db(0x61); db(0x02); db(0x60); db(0x84); db(0x22); db(0x54); db(0x20); db(0x6c); - db(0x00); db(0x04); db(0x29); db(0x4d); db(0x00); db(0x04); db(0x4e); db(0xee); - db(0xfe); db(0x92); db(0x2f); db(0x05); db(0x7a); db(0xfc); db(0x24); db(0x53); - db(0x2e); db(0x0a); db(0x22); db(0x0a); db(0x67); db(0x00); db(0x00); db(0x0c); - db(0x52); db(0x85); db(0x67); db(0x1e); db(0x22); db(0x4a); db(0x24); db(0x52); - db(0x60); db(0xf0); db(0x52); db(0x85); db(0x67); db(0x3c); db(0x24); db(0x47); - db(0x70); db(0x18); db(0x72); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); - db(0x52); db(0x46); db(0x24); db(0x40); db(0x24); db(0x87); db(0x2e); db(0x0a); - db(0x60); db(0xe8); db(0x20); db(0x12); db(0x67); db(0x24); db(0x20); db(0x40); - db(0x20); db(0x10); db(0x67); db(0x1e); db(0x20); db(0x40); db(0x20); db(0x10); - db(0x67); db(0x18); db(0x70); db(0x00); db(0x22); db(0x80); db(0x22); db(0x4a); - db(0x24); db(0x51); db(0x70); db(0x18); db(0x4e); db(0xae); db(0xff); db(0x2e); - db(0x06); db(0x86); db(0x00); db(0x01); db(0x00); db(0x00); db(0x20); db(0x0a); - db(0x66); db(0xec); db(0x26); db(0x87); db(0x2a); db(0x1f); db(0x4e); db(0x75); - db(0x55); db(0x41); db(0x45); db(0x20); db(0x66); db(0x69); db(0x6c); db(0x65); - db(0x73); db(0x79); db(0x73); db(0x74); db(0x65); db(0x6d); db(0x00); db(0x64); - db(0x6f); db(0x73); db(0x2e); db(0x6c); db(0x69); db(0x62); db(0x72); db(0x61); - db(0x72); db(0x79); db(0x00); db(0x65); db(0x78); db(0x70); db(0x61); db(0x6e); - db(0x73); db(0x69); db(0x6f); db(0x6e); db(0x2e); db(0x6c); db(0x69); db(0x62); - db(0x72); db(0x61); db(0x72); db(0x79); db(0x00); db(0x00); db(0x00); db(0x00); - db(0x00); db(0x00); db(0x03); db(0xf2); + filesys_initcode = here() + 8 + 0x30 + 4; + + #include "filesys_bootrom.c" }