diff --git a/Software/a314fs/a314fs.c b/Software/a314fs/a314fs.c index 77fb396..ecfc5a7 100644 --- a/Software/a314fs/a314fs.c +++ b/Software/a314fs/a314fs.c @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -70,6 +71,19 @@ BOOL request_buffer_in_a314_memory; // These are allocated in A314 memory. ULONG request_buffer_address; ULONG data_buffer_address; +ULONG data_buffer_size; + +void DeletePort(struct MsgPort *port) +{ + if (port) + { + if (port->mp_Node.ln_Name) + RemPort(port); + if (port->mp_SigBit < 32) + FreeSignal(port->mp_SigBit); + FreeMem(port, sizeof(struct MsgPort)); + } +} void MyNewList(struct List *l) { @@ -375,7 +389,8 @@ void startup_fs_handler(struct DosPacket *dp) request_buffer_address = AllocMemA314(REQ_RES_BUF_SIZE); } - data_buffer_address = AllocMemA314(BUFFER_SIZE); + data_buffer_size = BUFFER_SIZE; + data_buffer_address = AllocMemA314(data_buffer_size); // Så vi kan anta att vi kommer hit, och då har vi en ström till rasp-sidan, där vi kan skicka data. create_and_add_volume(); @@ -1284,6 +1299,72 @@ void action_is_filesystem(struct DosPacket *dp) reply_packet(dp); } +void action_die(struct DosPacket *dp) +{ + dbg("ACTION_DIE\n"); + + struct DieRequest *req = (struct DieRequest *)request_buffer; + req->has_response = 0; + req->type = ACTION_DIE; + + write_req_and_wait_for_res(sizeof(struct DieRequest)); + + // Clean up resources here + if (A314Base) + CloseLibrary(A314Base); + if (a314_ior) + CloseDevice((struct IORequest *)a314_ior); + if (a314_mp) + DeletePort(a314_mp); + if (timer_mp) + DeletePort(timer_mp); + if (mp) + DeletePort(mp); + if (request_buffer) + FreeMem(request_buffer, REQ_RES_BUF_SIZE); + if (data_buffer_address) + FreeMemA314(data_buffer_address, data_buffer_size); + + dp->dp_Res1 = DOSTRUE; + dp->dp_Res2 = 0; + reply_packet(dp); +} + +void action_inhibit(struct DosPacket *dp) +{ + LONG inhibit = dp->dp_Arg1; + dbg("ACTION_INHIBIT\n"); + dbg(" inhibit = $l\n", inhibit); + + struct InhibitRequest *req = (struct InhibitRequest *)request_buffer; + req->has_response = 0; + req->type = ACTION_INHIBIT; + req->inhibit = inhibit; + + write_req_and_wait_for_res(sizeof(struct InhibitRequest)); + + struct InhibitResponse *res = (struct InhibitResponse *)request_buffer; + dp->dp_Res1 = res->success ? DOSTRUE : DOSFALSE; + dp->dp_Res2 = res->error_code; + reply_packet(dp); +} + +void action_flush(struct DosPacket *dp) +{ + dbg("ACTION_FLUSH\n"); + + struct FlushRequest *req = (struct FlushRequest *)request_buffer; + req->has_response = 0; + req->type = ACTION_FLUSH; + + write_req_and_wait_for_res(sizeof(struct FlushRequest)); + + struct FlushResponse *res = (struct FlushResponse *)request_buffer; + dp->dp_Res1 = res->success ? DOSTRUE : DOSFALSE; + dp->dp_Res2 = res->error_code; + reply_packet(dp); +} + void action_unsupported(struct DosPacket *dp) { dbg("ACTION_UNSUPPORTED\n"); @@ -1350,14 +1431,15 @@ void start(__reg("a0") struct DosPacket *startup_packet) case ACTION_IS_FILESYSTEM: action_is_filesystem(dp); break; + case ACTION_DIE: action_die(dp); break; + case ACTION_INHIBIT: action_inhibit(dp); break; + case ACTION_FLUSH: action_flush(dp); break; + /* case ACTION_CURRENT_VOLUME: action_current_volume(dp); break; case ACTION_RENAME_DISK: action_rename_disk(dp); break; - case ACTION_DIE: //action_die(dp); break; - case ACTION_MORE_CACHE: //action_more_cache(dp); break; - case ACTION_FLUSH: //action_flush(dp); break; - case ACTION_INHIBIT: //action_inhibit(dp); break; + case ACTION_MORE_CACHE: //action_more_cache(dp); break; case ACTION_WRITE_PROTECT: //action_write_protect(dp); break; */ diff --git a/Software/a314fs/a314fs.py b/Software/a314fs/a314fs.py index 67f612d..f53ccb7 100644 --- a/Software/a314fs/a314fs.py +++ b/Software/a314fs/a314fs.py @@ -710,11 +710,55 @@ def process_info(key): block_size = INFO_BLOCK_SIZE return struct.pack('>HHIII', 1, 0, total_blocks, used_blocks, block_size) +# Add a global variable to track mount state +is_mounted = True + +def process_die(): + logger.debug('ACTION_DIE') + global is_mounted + is_mounted = False + # Close all open file handles + for fp in list(open_file_handles.keys()): + process_end(fp) + # Clear all locks + locks.clear() + return struct.pack('>HH', 1, 0) + +def process_inhibit(inhibit): + logger.debug('ACTION_INHIBIT, inhibit: %s', inhibit) + global is_mounted + if inhibit: + # Inhibit the volume (prepare for unmount) + is_mounted = False + else: + # Uninhibit the volume (remount) + is_mounted = True + return struct.pack('>HH', 1, 0) + +def process_flush(): + logger.debug('ACTION_FLUSH') + os.sync() + return struct.pack('>HH', 1, 0) + def process_request(req): #logger.debug('len(req): %s, req: %s', len(req), list(req)) - + + global is_mounted + (rtype,) = struct.unpack('>H', req[:2]) + if rtype == ACTION_DIE: + return process_die() + elif rtype == ACTION_INHIBIT: + (inhibit,) = struct.unpack('>I', req[2:6]) + return process_inhibit(inhibit) + elif rtype == ACTION_FLUSH: + return process_flush() + + # For all other actions, check if the volume is mounted + if not is_mounted: + return struct.pack('>HH', 0, ERROR_DEVICE_NOT_MOUNTED) + if rtype == ACTION_LOCATE_OBJECT: key, mode, nlen = struct.unpack('>IHB', req[2:9]) name = req[9:9+nlen].decode('latin-1') @@ -825,6 +869,7 @@ def process_request(req): send_reset(current_stream_id) current_stream_id = stream_id send_connect_response(stream_id, 0) + is_mounted = True # Reset the mount state on a new connection else: send_connect_response(stream_id, 3) elif ptype == MSG_DATA: @@ -838,7 +883,9 @@ def process_request(req): logger.debug('Got EOS, stream closed') send_eos(stream_id) current_stream_id = None + is_mounted = False # Reset the mount state on stream close elif ptype == MSG_RESET: if stream_id == current_stream_id: logger.debug('Got RESET, stream closed') current_stream_id = None + is_mounted = False # Reset the mount state on stream close diff --git a/Software/a314fs/messages.h b/Software/a314fs/messages.h index 33ea578..a218ed1 100644 --- a/Software/a314fs/messages.h +++ b/Software/a314fs/messages.h @@ -348,4 +348,35 @@ struct UnsupportedResponse short error_code; }; +struct DieRequest { + UBYTE has_response; + UBYTE type; +}; + +struct DieResponse { + UBYTE success; + ULONG error_code; +}; + +struct InhibitRequest { + UBYTE has_response; + UBYTE type; + LONG inhibit; +}; + +struct InhibitResponse { + UBYTE success; + ULONG error_code; +}; + +struct FlushRequest { + UBYTE has_response; + UBYTE type; +}; + +struct FlushResponse { + UBYTE success; + ULONG error_code; +}; + #pragma pack(pop)