2 * Copyright (c) 2018-2021 Niklas Ekström
5 #include <exec/types.h>
6 #include <exec/ports.h>
7 #include <exec/nodes.h>
8 #include <exec/libraries.h>
10 #include <devices/timer.h>
12 #include <libraries/dos.h>
13 #include <libraries/dosextens.h>
14 #include <libraries/filehandler.h>
16 #include <proto/exec.h>
17 #include <proto/dos.h>
22 #include "../../a314device/a314.h"
23 #include "../../a314device/proto_a314.h"
27 #define MKBADDRU(x) (((ULONG)x) >> 2)
29 #define ID_314_DISK (('3' << 24) | ('1' << 16) | ('4' << 8))
31 #define REQ_RES_BUF_SIZE 256
32 #define BUFFER_SIZE 4096
34 // Not defined if using NDK13
35 #ifndef ACTION_EXAMINE_FH
36 #define ACTION_EXAMINE_FH 1034
39 #ifndef ACTION_SAME_LOCK
40 #define ACTION_SAME_LOCK 40
43 // Grab a reserved action type which seems to be unused
44 #define ACTION_UNSUPPORTED 65535
46 struct ExecBase *SysBase;
47 struct DosLibrary *DOSBase;
50 struct DeviceList *my_volume;
51 char default_volume_name[] = "\006PiDisk";
53 char device_name[32]; // "\004PI0:"
55 struct MsgPort *timer_mp;
56 struct timerequest *tr;
58 struct MsgPort *a314_mp;
59 struct A314_IORequest *a314_ior;
61 struct Library *A314Base;
65 // These are allocated in A314 memory.
66 char *request_buffer = NULL;
67 char *data_buffer = NULL;
69 void MyNewList(struct List *l)
71 l->lh_Head = (struct Node *)&(l->lh_Tail);
73 l->lh_TailPred = (struct Node *)&(l->lh_Head);
76 struct MsgPort *MyCreatePort(char *name, long pri)
78 int sigbit = AllocSignal(-1);
82 struct MsgPort *port = (struct MsgPort *)AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC | MEMF_CLEAR);
89 port->mp_Node.ln_Name = name;
90 port->mp_Node.ln_Pri = pri;
91 port->mp_Node.ln_Type = NT_MSGPORT;
92 port->mp_Flags = PA_SIGNAL;
93 port->mp_SigBit = sigbit;
94 port->mp_SigTask = FindTask(NULL);
99 MyNewList(&(port->mp_MsgList));
104 struct IORequest *MyCreateExtIO(struct MsgPort *ioReplyPort, ULONG size)
109 struct IORequest *ioReq = (struct IORequest *)AllocMem(size, MEMF_PUBLIC | MEMF_CLEAR);
113 ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
114 ioReq->io_Message.mn_Length = size;
115 ioReq->io_Message.mn_ReplyPort = ioReplyPort;
127 void dbg(const char* fmt, ...)
131 struct FileHandle *dbg_log;
132 struct MsgPort *dbg_replyport;
133 struct StandardPacket *dbg_sp;
138 dbg_log = (struct FileHandle *)BADDR(Open("CON:200/0/440/256/a314fs", MODE_NEWFILE));
139 dbg_replyport = MyCreatePort(NULL, 0);
140 dbg_sp = (struct StandardPacket *)AllocMem(sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
145 dbg_sp->sp_Msg.mn_Node.ln_Name = (char *)&(dbg_sp->sp_Pkt);
146 dbg_sp->sp_Pkt.dp_Link = &(dbg_sp->sp_Msg);
147 dbg_sp->sp_Pkt.dp_Port = dbg_replyport;
148 dbg_sp->sp_Pkt.dp_Type = ACTION_WRITE;
149 dbg_sp->sp_Pkt.dp_Arg1 = (long)dbg_log->fh_Arg1;
150 dbg_sp->sp_Pkt.dp_Arg2 = (long)dbg_buf;
151 dbg_sp->sp_Pkt.dp_Arg3 = (long)l - 1;
153 PutMsg((struct MsgPort *)dbg_log->fh_Type, (struct Message *)dbg_sp);
154 WaitPort(dbg_replyport);
155 GetMsg(dbg_replyport);
158 void dbg(const char* fmt, ...)
175 UBYTE x = va_arg(args, UBYTE);
177 for (int i = 0; i < 2; i++)
179 int ni = (x >> ((1 - i) * 4)) & 0xf;
180 *q++ = (ni >= 10) ? ('a' + (ni - 10)) : ('0' + ni);
185 UWORD x = va_arg(args, UWORD);
187 for (int i = 0; i < 4; i++)
189 int ni = (x >> ((3 - i) * 4)) & 0xf;
190 *q++ = (ni >= 10) ? ('a' + (ni - 10)) : ('0' + ni);
195 ULONG x = va_arg(args, ULONG);
197 for (int i = 0; i < 8; i++)
199 int ni = (x >> ((7 - i) * 4)) & 0xf;
200 *q++ = (ni >= 10) ? ('a' + (ni - 10)) : ('0' + ni);
205 unsigned char *s = (unsigned char *)va_arg(args, ULONG);
207 for (int i = 0; i < l; i++)
212 unsigned char *s = (unsigned char *)va_arg(args, ULONG);
227 dbg_out(q - dbg_buf);
231 char *DosAllocMem(int len)
233 long *p = (long *)AllocMem(len + 4, MEMF_PUBLIC | MEMF_CLEAR);
238 void DosFreeMem(char *p)
240 long *lp = (long *)p;
242 FreeMem((char *)lp, len);
245 void reply_packet(struct DosPacket *dp)
247 struct MsgPort *reply_port = dp->dp_Port;
249 PutMsg(reply_port, dp->dp_Link);
252 // Routines for talking to the A314 driver.
253 LONG a314_cmd_wait(UWORD command, char *buffer, int length)
255 a314_ior->a314_Request.io_Command = command;
256 a314_ior->a314_Request.io_Error = 0;
257 a314_ior->a314_Socket = socket;
258 a314_ior->a314_Buffer = buffer;
259 a314_ior->a314_Length = length;
260 return DoIO((struct IORequest *)a314_ior);
263 LONG a314_connect(char *name)
268 return a314_cmd_wait(A314_CONNECT, name, strlen(name));
271 LONG a314_read(char *buf, int length)
273 return a314_cmd_wait(A314_READ, buf, length);
276 LONG a314_write(char *buf, int length)
278 return a314_cmd_wait(A314_WRITE, buf, length);
283 return a314_cmd_wait(A314_EOS, NULL, 0);
288 return a314_cmd_wait(A314_RESET, NULL, 0);
291 void create_and_add_volume()
293 my_volume = (struct DeviceList *)DosAllocMem(sizeof(struct DeviceList));
294 my_volume->dl_Name = MKBADDRU(default_volume_name);
295 my_volume->dl_Type = DLT_VOLUME;
296 my_volume->dl_Task = mp;
297 my_volume->dl_DiskType = ID_314_DISK;
298 DateStamp(&my_volume->dl_VolumeDate);
300 struct RootNode *root = (struct RootNode *)DOSBase->dl_Root;
301 struct DosInfo *info = (struct DosInfo *)BADDR(root->rn_Info);
304 my_volume->dl_Next = info->di_DevInfo;
305 info->di_DevInfo = MKBADDRU(my_volume);
309 void startup_fs_handler(struct DosPacket *dp)
311 unsigned char *name = (unsigned char *)BADDR(dp->dp_Arg1);
312 struct FileSysStartupMsg *fssm = (struct FileSysStartupMsg *)BADDR(dp->dp_Arg2);
313 struct DeviceNode *node = (struct DeviceNode *)BADDR(dp->dp_Arg3);
315 memcpy(device_name, name, *name + 1);
316 device_name[*name + 1] = 0;
320 dp->dp_Res1 = DOSTRUE;
326 dbg("ACTION_STARTUP\n");
327 dbg(" device_name = $S\n", (ULONG)device_name);
328 dbg(" fssm = $l\n", (ULONG)fssm);
329 dbg(" node = $l\n", (ULONG)node);
331 timer_mp = MyCreatePort(NULL, 0);
332 tr = (struct timerequest *)MyCreateExtIO(timer_mp, sizeof(struct timerequest));
333 if (OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *)tr, 0) != 0)
335 // If this happens, there's nothing we can do.
336 // For now, assume this does not happen.
337 dbg("Fatal error: unable to open timer.device\n");
341 a314_mp = MyCreatePort(NULL, 0);
342 a314_ior = (struct A314_IORequest *)MyCreateExtIO(a314_mp, sizeof(struct A314_IORequest));
343 if (OpenDevice(A314_NAME, 0, (struct IORequest *)a314_ior, 0) != 0)
345 // If this fails, there's nothing we can do.
346 // For now, assume this does not happen.
347 dbg("Fatal error: unable to open a314.device\n");
351 A314Base = &(a314_ior->a314_Request.io_Device->dd_Library);
353 if (a314_connect("a314fs") != A314_CONNECT_OK)
355 dbg("Fatal error: unable to connect to a314fs on rasp\n");
356 // This COULD happen.
357 // If it DOES happen, we just wait for a bit and try again.
359 // TODO: Have to use timer.device to set a timer for ~2 seconds and then try connecting again.
363 request_buffer = AllocMem(REQ_RES_BUF_SIZE, MEMF_FAST);
364 data_buffer = AllocMem(BUFFER_SIZE, MEMF_FAST);
366 // We can assume that we arrive here, and have a stream to the Pi side, to where we can transfer data.
367 create_and_add_volume();
369 dbg("Startup successful\n");
371 // If we end up having problems with the connections, treat the disc as ejected, and try inserting it again in two seconds.
372 // TODO: This is not currently handled.
375 void wait_for_response()
377 for (unsigned long i = 0; 1; i++)
381 dbg("--Got response after $l sleeps\n", i);
385 tr->tr_node.io_Command = TR_ADDREQUEST;
386 tr->tr_node.io_Message.mn_ReplyPort = timer_mp;
387 tr->tr_time.tv_secs = 0;
388 tr->tr_time.tv_micro = 1000;
389 DoIO((struct IORequest *)tr);
393 void write_req_and_wait_for_res(int len)
395 ULONG buf[2] = {TranslateAddressA314(request_buffer), len};
396 a314_write((char *)&buf[0], 8);
397 //wait_for_response();
398 a314_read((char *)&buf[0], 8);
401 struct FileLock *create_and_add_file_lock(long key, long mode)
403 struct FileLock *lock = (struct FileLock *)DosAllocMem(sizeof(struct FileLock));
406 lock->fl_Access = mode;
408 lock->fl_Volume = MKBADDRU(my_volume);
411 lock->fl_Link = my_volume->dl_Lock;
412 my_volume->dl_Lock = MKBADDRU(lock);
418 void action_locate_object(struct DosPacket *dp)
420 struct FileLock *parent = (struct FileLock *)BADDR(dp->dp_Arg1);
421 unsigned char *name = (unsigned char *)BADDR(dp->dp_Arg2);
422 long mode = dp->dp_Arg3;
424 dbg("ACTION_LOCATE_OBJECT\n");
425 dbg(" parent lock = $l\n", parent);
426 dbg(" name = $S\n", name);
427 dbg(" mode = $s\n", mode == SHARED_LOCK ? "SHARED_LOCK" : "EXCLUSIVE_LOCK");
429 struct LocateObjectRequest *req = (struct LocateObjectRequest *)request_buffer;
430 req->has_response = 0;
431 req->type = dp->dp_Type;
432 req->key = parent == NULL ? 0 : parent->fl_Key;
436 memcpy(req->name, name, nlen + 1);
438 write_req_and_wait_for_res(sizeof(struct LocateObjectRequest) + nlen);
440 struct LocateObjectResponse *res = (struct LocateObjectResponse *)request_buffer;
443 dbg(" Failed, error code $l\n", (LONG)res->error_code);
444 dp->dp_Res1 = DOSFALSE;
445 dp->dp_Res2 = res->error_code;
449 struct FileLock *lock = create_and_add_file_lock(res->key, mode);
451 dbg(" Returning lock $l\n", lock);
452 dp->dp_Res1 = MKBADDRU(lock);
459 void action_free_lock(struct DosPacket *dp)
461 ULONG arg1 = dp->dp_Arg1;
462 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg1);
464 dbg("ACTION_FREE_LOCK\n");
465 dbg(" lock = $l\n", lock);
469 struct FreeLockRequest *req = (struct FreeLockRequest *)request_buffer;
470 req->has_response = 0;
471 req->type = dp->dp_Type;
472 req->key = lock->fl_Key;
474 write_req_and_wait_for_res(sizeof(struct FreeLockRequest));
476 // Ignore the response. Must succeed.
477 //struct FreeLockResponse *res = (struct FreeLockResponse *)request_buffer;
480 if (my_volume->dl_Lock == arg1)
481 my_volume->dl_Lock = lock->fl_Link;
484 struct FileLock *prev = (struct FileLock *)BADDR(my_volume->dl_Lock);
485 while (prev->fl_Link != arg1)
486 prev = (struct FileLock *)BADDR(prev->fl_Link);
487 prev->fl_Link = lock->fl_Link;
490 DosFreeMem((char *)lock);
493 dp->dp_Res1 = DOSTRUE;
498 void action_copy_dir(struct DosPacket *dp)
500 struct FileLock *parent = (struct FileLock *)BADDR(dp->dp_Arg1);
502 dbg("ACTION_COPY_DIR\n");
503 dbg(" lock to duplicate = $l\n", parent);
512 struct CopyDirRequest *req = (struct CopyDirRequest *)request_buffer;
513 req->has_response = 0;
514 req->type = dp->dp_Type;
515 req->key = parent->fl_Key;
517 write_req_and_wait_for_res(sizeof(struct CopyDirRequest));
519 struct CopyDirResponse *res = (struct CopyDirResponse *)request_buffer;
522 dbg(" Failed, error code $l\n", (LONG)res->error_code);
523 dp->dp_Res1 = DOSFALSE;
524 dp->dp_Res2 = res->error_code;
528 struct FileLock *lock = create_and_add_file_lock(res->key, parent->fl_Access);
530 dbg(" Returning lock $l\n", lock);
531 dp->dp_Res1 = MKBADDRU(lock);
539 void action_parent(struct DosPacket *dp)
541 struct FileLock *prev_lock = (struct FileLock *)BADDR(dp->dp_Arg1);
543 dbg("ACTION_PARENT\n");
544 dbg(" lock = $l\n", prev_lock);
546 if (prev_lock == NULL)
548 dp->dp_Res1 = DOSFALSE;
549 dp->dp_Res2 = ERROR_INVALID_LOCK;
553 struct ParentRequest *req = (struct ParentRequest *)request_buffer;
554 req->has_response = 0;
555 req->type = dp->dp_Type;
556 req->key = prev_lock->fl_Key;
558 write_req_and_wait_for_res(sizeof(struct ParentRequest));
560 struct ParentResponse *res = (struct ParentResponse *)request_buffer;
563 dbg(" Failed, error code $l\n", (LONG)res->error_code);
564 dp->dp_Res1 = DOSFALSE;
565 dp->dp_Res2 = res->error_code;
567 else if (res->key == 0)
574 struct FileLock *lock = create_and_add_file_lock(res->key, SHARED_LOCK);
576 dbg(" Returning lock $l\n", lock);
577 dp->dp_Res1 = MKBADDRU(lock);
585 void action_examine_object(struct DosPacket *dp)
587 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg1);
588 struct FileInfoBlock *fib = (struct FileInfoBlock *)BADDR(dp->dp_Arg2);
590 dbg("ACTION_EXAMINE_OBJECT\n");
591 dbg(" lock = $l\n", lock);
592 dbg(" fib = $l\n", fib);
594 struct ExamineObjectRequest *req = (struct ExamineObjectRequest *)request_buffer;
595 req->has_response = 0;
596 req->type = dp->dp_Type;
597 req->key = lock == NULL ? 0 : lock->fl_Key;
599 write_req_and_wait_for_res(sizeof(struct ExamineObjectRequest));
601 struct ExamineObjectResponse *res = (struct ExamineObjectResponse *)request_buffer;
604 dbg(" Failed, error code $l\n", (LONG)res->error_code);
605 dp->dp_Res1 = DOSFALSE;
606 dp->dp_Res2 = res->error_code;
610 int nlen = (unsigned char)(res->data[0]);
611 memcpy(fib->fib_FileName, res->data, nlen + 1);
612 fib->fib_FileName[nlen + 1] = 0;
614 int clen = (unsigned char)(res->data[nlen + 1]);
615 memcpy(fib->fib_Comment, &(res->data[nlen + 1]), clen + 1);
616 fib->fib_Comment[clen + 1] = 0;
618 fib->fib_DiskKey = res->disk_key;
619 fib->fib_DirEntryType = res->entry_type;
620 fib->fib_EntryType = res->entry_type;
621 fib->fib_Protection = res->protection;
622 fib->fib_Size = res->size;
623 fib->fib_NumBlocks = (res->size + 511) >> 9;
624 fib->fib_Date.ds_Days = res->date[0];
625 fib->fib_Date.ds_Minute = res->date[1];
626 fib->fib_Date.ds_Tick = res->date[2];
628 dp->dp_Res1 = DOSTRUE;
635 void action_examine_next(struct DosPacket *dp)
637 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg1);
638 struct FileInfoBlock *fib = (struct FileInfoBlock *)BADDR(dp->dp_Arg2);
640 dbg("ACTION_EXAMINE_NEXT\n");
641 dbg(" lock = $l\n", lock);
642 dbg(" fib = $l\n", fib);
644 struct ExamineNextRequest *req = (struct ExamineNextRequest *)request_buffer;
645 req->has_response = 0;
646 req->type = dp->dp_Type;
647 req->key = lock == NULL ? 0 : lock->fl_Key;
648 req->disk_key = fib->fib_DiskKey;
650 write_req_and_wait_for_res(sizeof(struct ExamineNextRequest));
652 struct ExamineNextResponse *res = (struct ExamineNextResponse *)request_buffer;
655 dbg(" Failed, error code $l\n", (LONG)res->error_code);
656 dp->dp_Res1 = DOSFALSE;
657 dp->dp_Res2 = res->error_code;
661 int nlen = (unsigned char)(res->data[0]);
662 memcpy(fib->fib_FileName, res->data, nlen + 1);
663 fib->fib_FileName[nlen + 1] = 0;
665 int clen = (unsigned char)(res->data[nlen + 1]);
666 memcpy(fib->fib_Comment, &(res->data[nlen + 1]), clen + 1);
667 fib->fib_Comment[clen + 1] = 0;
669 fib->fib_DiskKey = res->disk_key;
670 fib->fib_DirEntryType = res->entry_type;
671 fib->fib_EntryType = res->entry_type;
672 fib->fib_Protection = res->protection;
673 fib->fib_Size = res->size;
674 fib->fib_NumBlocks = (res->size + 511) >> 9;
675 fib->fib_Date.ds_Days = res->date[0];
676 fib->fib_Date.ds_Minute = res->date[1];
677 fib->fib_Date.ds_Tick = res->date[2];
679 dp->dp_Res1 = DOSTRUE;
686 void action_examine_fh(struct DosPacket *dp)
688 ULONG arg1 = dp->dp_Arg1;
689 struct FileInfoBlock *fib = (struct FileInfoBlock *)BADDR(dp->dp_Arg2);
691 dbg("ACTION_EXAMINE_FH\n");
692 dbg(" arg1 = $l\n", arg1);
693 dbg(" fib = $l\n", fib);
695 struct ExamineFhRequest *req = (struct ExamineFhRequest *)request_buffer;
696 req->has_response = 0;
697 req->type = dp->dp_Type;
700 write_req_and_wait_for_res(sizeof(struct ExamineFhRequest));
702 struct ExamineFhResponse *res = (struct ExamineFhResponse *)request_buffer;
705 dbg(" Failed, error code $l\n", (LONG)res->error_code);
706 dp->dp_Res1 = DOSFALSE;
707 dp->dp_Res2 = res->error_code;
711 int nlen = (unsigned char)(res->data[0]);
712 memcpy(fib->fib_FileName, res->data, nlen + 1);
713 fib->fib_FileName[nlen + 1] = 0;
715 int clen = (unsigned char)(res->data[nlen + 1]);
716 memcpy(fib->fib_Comment, &(res->data[nlen + 1]), clen + 1);
717 fib->fib_Comment[clen + 1] = 0;
719 fib->fib_DiskKey = res->disk_key;
720 fib->fib_DirEntryType = res->entry_type;
721 fib->fib_EntryType = res->entry_type;
722 fib->fib_Protection = res->protection;
723 fib->fib_Size = res->size;
724 fib->fib_NumBlocks = (res->size + 511) >> 9;
725 fib->fib_Date.ds_Days = res->date[0];
726 fib->fib_Date.ds_Minute = res->date[1];
727 fib->fib_Date.ds_Tick = res->date[2];
729 dp->dp_Res1 = DOSTRUE;
736 void action_findxxx(struct DosPacket *dp)
738 struct FileHandle *fh = (struct FileHandle *)BADDR(dp->dp_Arg1);
739 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg2);
740 unsigned char *name = (unsigned char *)BADDR(dp->dp_Arg3);
742 if (dp->dp_Type == ACTION_FINDUPDATE)
743 dbg("ACTION_FINDUPDATE\n");
744 else if (dp->dp_Type == ACTION_FINDINPUT)
745 dbg("ACTION_FINDINPUT\n");
746 else if (dp->dp_Type == ACTION_FINDOUTPUT)
747 dbg("ACTION_FINDOUTPUT\n");
749 dbg(" file handle = $l\n", fh);
750 dbg(" lock = $l\n", lock);
751 dbg(" name = $S\n", name);
753 struct FindXxxRequest *req = (struct FindXxxRequest *)request_buffer;
754 req->has_response = 0;
755 req->type = dp->dp_Type;
756 req->key = lock == NULL ? 0 : lock->fl_Key;
759 memcpy(req->name, name, nlen + 1);
761 write_req_and_wait_for_res(sizeof(struct FindXxxRequest) + nlen);
763 struct FindXxxResponse *res = (struct FindXxxResponse *)request_buffer;
766 dbg(" Failed, error code $l\n", (LONG)res->error_code);
767 dp->dp_Res1 = DOSFALSE;
768 dp->dp_Res2 = res->error_code;
772 fh->fh_Arg1 = res->arg1;
774 fh->fh_Port = DOSFALSE; // Not an interactive file.
776 dp->dp_Res1 = DOSTRUE;
783 void action_read(struct DosPacket *dp)
785 ULONG arg1 = dp->dp_Arg1;
786 UBYTE *dst = (UBYTE *)dp->dp_Arg2;
787 int length = dp->dp_Arg3;
789 dbg("ACTION_READ\n");
790 dbg(" arg1 = $l\n", arg1);
791 dbg(" length = $l\n", length);
796 dp->dp_Res2 = ERROR_INVALID_LOCK; // This is not the correct error.
804 int to_read = length;
805 if (to_read > BUFFER_SIZE)
806 to_read = BUFFER_SIZE;
808 struct ReadRequest *req = (struct ReadRequest *)request_buffer;
809 req->has_response = 0;
810 req->type = dp->dp_Type;
812 req->address = TranslateAddressA314(data_buffer);
813 req->length = to_read;
815 write_req_and_wait_for_res(sizeof(struct ReadRequest));
817 struct ReadResponse *res = (struct ReadResponse *)request_buffer;
820 dbg(" Failed, error code $l\n", (LONG)res->error_code);
822 dp->dp_Res2 = res->error_code;
829 memcpy(dst, data_buffer, res->actual);
831 total_read += res->actual;
832 length -= res->actual;
835 if (res->actual < to_read)
839 dp->dp_Res1 = total_read;
844 void action_write(struct DosPacket *dp)
846 ULONG arg1 = dp->dp_Arg1;
847 UBYTE *src = (UBYTE *)dp->dp_Arg2;
848 int length = dp->dp_Arg3;
850 dbg("ACTION_WRITE\n");
851 dbg(" arg1 = $l\n", arg1);
852 dbg(" length = $l\n", length);
854 int total_written = 0;
857 int to_write = length;
858 if (to_write > BUFFER_SIZE)
859 to_write = BUFFER_SIZE;
861 memcpy(data_buffer, src, to_write);
863 struct WriteRequest *req = (struct WriteRequest *)request_buffer;
864 req->has_response = 0;
865 req->type = dp->dp_Type;
867 req->address = TranslateAddressA314(data_buffer);
868 req->length = to_write;
870 write_req_and_wait_for_res(sizeof(struct WriteRequest));
872 struct WriteResponse *res = (struct WriteResponse *)request_buffer;
875 dbg(" Failed, error code $l\n", (LONG)res->error_code);
876 dp->dp_Res1 = total_written;
877 dp->dp_Res2 = res->error_code;
885 total_written += res->actual;
886 length -= res->actual;
889 if (res->actual < to_write)
893 dp->dp_Res1 = total_written;
898 void action_seek(struct DosPacket *dp)
900 ULONG arg1 = dp->dp_Arg1;
901 LONG new_pos = dp->dp_Arg2;
902 LONG mode = dp->dp_Arg3;
904 dbg("ACTION_SEEK\n");
905 dbg(" arg1 = $l\n", arg1);
906 dbg(" new_pos = $l\n", new_pos);
907 dbg(" mode = $l\n", mode);
909 struct SeekRequest *req = (struct SeekRequest *)request_buffer;
910 req->has_response = 0;
911 req->type = dp->dp_Type;
913 req->new_pos = new_pos;
916 write_req_and_wait_for_res(sizeof(struct SeekRequest));
918 struct SeekResponse *res = (struct SeekResponse *)request_buffer;
921 dbg(" Failed, error code $l\n", (LONG)res->error_code);
923 dp->dp_Res2 = res->error_code;
927 dp->dp_Res1 = res->old_pos;
934 void action_end(struct DosPacket *dp)
936 ULONG arg1 = dp->dp_Arg1;
939 dbg(" arg1 = $l\n", arg1);
941 struct EndRequest *req = (struct EndRequest *)request_buffer;
942 req->has_response = 0;
943 req->type = dp->dp_Type;
946 write_req_and_wait_for_res(sizeof(struct EndRequest));
948 //struct EndResponse *res = (struct EndResponse *)request_buffer;
950 dp->dp_Res1 = DOSTRUE;
955 void action_delete_object(struct DosPacket *dp)
957 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg1);
958 unsigned char *name = (unsigned char *)BADDR(dp->dp_Arg2);
960 dbg("ACTION_DELETE_OBJECT\n");
961 dbg(" lock = $l\n", lock);
962 dbg(" name = $S\n", name);
964 struct DeleteObjectRequest *req = (struct DeleteObjectRequest *)request_buffer;
965 req->has_response = 0;
966 req->type = dp->dp_Type;
967 req->key = lock == NULL ? 0 : lock->fl_Key;
970 memcpy(req->name, name, nlen + 1);
972 write_req_and_wait_for_res(sizeof(struct DeleteObjectRequest) + nlen);
974 struct DeleteObjectResponse *res = (struct DeleteObjectResponse *)request_buffer;
977 dbg(" Failed, error code $l\n", (LONG)res->error_code);
978 dp->dp_Res1 = DOSFALSE;
979 dp->dp_Res2 = res->error_code;
983 dp->dp_Res1 = DOSTRUE;
990 void action_rename_object(struct DosPacket *dp)
992 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg1);
993 unsigned char *name = (unsigned char *)BADDR(dp->dp_Arg2);
994 struct FileLock *target_dir = (struct FileLock *)BADDR(dp->dp_Arg3);
995 unsigned char *new_name = (unsigned char *)BADDR(dp->dp_Arg4);
997 dbg("ACTION_RENAME_OBJECT\n");
998 dbg(" lock = $l\n", lock);
999 dbg(" name = $S\n", name);
1000 dbg(" target directory = $l\n", lock);
1001 dbg(" new name = $S\n", new_name);
1003 struct RenameObjectRequest *req = (struct RenameObjectRequest *)request_buffer;
1004 req->has_response = 0;
1005 req->type = dp->dp_Type;
1006 req->key = lock == NULL ? 0 : lock->fl_Key;
1007 req->target_dir = target_dir == NULL ? 0 : target_dir->fl_Key;
1010 int nnlen = *new_name;
1012 req->name_len = nlen;
1013 req->new_name_len = nnlen;
1015 unsigned char *p = &(req->new_name_len) + 1;
1016 memcpy(p, name + 1, nlen);
1018 memcpy(p, new_name + 1, nnlen);
1020 write_req_and_wait_for_res(sizeof(struct RenameObjectRequest) + nlen + nnlen);
1022 struct RenameObjectResponse *res = (struct RenameObjectResponse *)request_buffer;
1025 dbg(" Failed, error code $l\n", (LONG)res->error_code);
1026 dp->dp_Res1 = DOSFALSE;
1027 dp->dp_Res2 = res->error_code;
1031 dp->dp_Res1 = DOSTRUE;
1038 void action_create_dir(struct DosPacket *dp)
1040 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg1);
1041 unsigned char *name = (unsigned char *)BADDR(dp->dp_Arg2);
1043 dbg("ACTION_CREATE_DIR\n");
1044 dbg(" lock = $l\n", lock);
1045 dbg(" name = $S\n", name);
1047 struct CreateDirRequest *req = (struct CreateDirRequest *)request_buffer;
1048 req->has_response = 0;
1049 req->type = dp->dp_Type;
1050 req->key = lock == NULL ? 0 : lock->fl_Key;
1053 memcpy(req->name, name, nlen + 1);
1055 write_req_and_wait_for_res(sizeof(struct CreateDirRequest) + nlen);
1057 struct CreateDirResponse *res = (struct CreateDirResponse *)request_buffer;
1060 dbg(" Failed, error code $l\n", (LONG)res->error_code);
1061 dp->dp_Res1 = DOSFALSE;
1062 dp->dp_Res2 = res->error_code;
1066 struct FileLock *lock = create_and_add_file_lock(res->key, SHARED_LOCK);
1068 dbg(" Returning lock $l\n", lock);
1069 dp->dp_Res1 = MKBADDRU(lock);
1076 void action_set_protect(struct DosPacket *dp)
1078 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg2);
1079 unsigned char *name = (unsigned char *)BADDR(dp->dp_Arg3);
1080 long mask = dp->dp_Arg4;
1082 dbg("ACTION_SET_PROTECT\n");
1083 dbg(" lock = $l\n", lock);
1084 dbg(" name = $S\n", name);
1085 dbg(" mask = $l\n", mask);
1087 struct SetProtectRequest *req = (struct SetProtectRequest *)request_buffer;
1088 req->has_response = 0;
1089 req->type = dp->dp_Type;
1090 req->key = lock == NULL ? 0 : lock->fl_Key;
1094 memcpy(req->name, name, nlen + 1);
1096 write_req_and_wait_for_res(sizeof(struct SetProtectRequest) + nlen);
1098 struct SetProtectResponse *res = (struct SetProtectResponse *)request_buffer;
1101 dbg(" Failed, error code $l\n", (LONG)res->error_code);
1102 dp->dp_Res1 = DOSFALSE;
1103 dp->dp_Res2 = res->error_code;
1107 dp->dp_Res1 = DOSTRUE;
1114 void action_set_comment(struct DosPacket *dp)
1116 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg2);
1117 unsigned char *name = (unsigned char *)BADDR(dp->dp_Arg3);
1118 unsigned char *comment = (unsigned char *)BADDR(dp->dp_Arg4);
1120 dbg("ACTION_SET_COMMENT\n");
1121 dbg(" lock = $l\n", lock);
1122 dbg(" name = $S\n", name);
1123 dbg(" comment = $S\n", comment);
1125 struct SetCommentRequest *req = (struct SetCommentRequest *)request_buffer;
1126 req->has_response = 0;
1127 req->type = dp->dp_Type;
1128 req->key = lock == NULL ? 0 : lock->fl_Key;
1131 int clen = *comment;
1133 req->name_len = nlen;
1134 req->comment_len = clen;
1136 unsigned char *p = &(req->comment_len) + 1;
1137 memcpy(p, name + 1, nlen);
1139 memcpy(p, comment + 1, clen);
1141 write_req_and_wait_for_res(sizeof(struct SetCommentRequest) + nlen + clen);
1143 struct SetCommentResponse *res = (struct SetCommentResponse *)request_buffer;
1146 dbg(" Failed, error code $l\n", (LONG)res->error_code);
1147 dp->dp_Res1 = DOSFALSE;
1148 dp->dp_Res2 = res->error_code;
1152 dp->dp_Res1 = DOSTRUE;
1159 void action_same_lock(struct DosPacket *dp)
1161 struct FileLock *lock1 = (struct FileLock *)BADDR(dp->dp_Arg1);
1162 struct FileLock *lock2 = (struct FileLock *)BADDR(dp->dp_Arg2);
1164 dbg("ACTION_SAME_LOCK\n");
1165 dbg(" locks to compare = $l $l\n", lock1, lock2);
1167 struct SameLockRequest *req = (struct SameLockRequest *)request_buffer;
1168 req->has_response = 0;
1169 req->type = dp->dp_Type;
1170 req->key1 = lock1->fl_Key;
1171 req->key2 = lock2->fl_Key;
1173 write_req_and_wait_for_res(sizeof(struct SameLockRequest));
1175 struct SameLockResponse *res = (struct SameLockResponse *)request_buffer;
1176 dp->dp_Res1 = res->success ? DOSTRUE : DOSFALSE;
1177 dp->dp_Res2 = res->error_code;
1182 void fill_info_data(struct InfoData *id)
1184 memset(id, 0, sizeof(struct InfoData));
1185 id->id_DiskState = ID_VALIDATED;
1186 id->id_NumBlocks = 512 * 1024;
1187 id->id_NumBlocksUsed = 10;
1188 id->id_BytesPerBlock = 512;
1189 id->id_DiskType = my_volume->dl_DiskType;
1190 id->id_VolumeNode = MKBADDRU(my_volume);
1191 id->id_InUse = DOSTRUE;
1194 void action_info(struct DosPacket *dp)
1196 struct FileLock *lock = (struct FileLock *)BADDR(dp->dp_Arg1);
1197 struct InfoData *id = (struct InfoData *)BADDR(dp->dp_Arg2);
1199 dbg("ACTION_INFO\n");
1200 dbg(" lock = $l\n", lock);
1204 dp->dp_Res1 = DOSTRUE;
1209 void action_disk_info(struct DosPacket *dp)
1211 struct InfoData *id = (struct InfoData *)BADDR(dp->dp_Arg1);
1213 dbg("ACTION_DISK_INFO\n");
1217 dp->dp_Res1 = DOSTRUE;
1222 void action_unsupported(struct DosPacket *dp)
1224 dbg("ACTION_UNSUPPORTED\n");
1225 dbg(" Unsupported action: $l\n", (ULONG)dp->dp_Type);
1227 struct UnsupportedRequest *req = (struct UnsupportedRequest *)request_buffer;
1228 req->has_response = 0;
1229 req->type = ACTION_UNSUPPORTED;
1230 req->dp_Type = dp->dp_Type;
1232 write_req_and_wait_for_res(sizeof(struct UnsupportedRequest));
1234 struct UnsupportedResponse *res = (struct UnsupportedResponse *)request_buffer;
1235 dp->dp_Res1 = res->success ? DOSTRUE : DOSFALSE;
1236 dp->dp_Res2 = res->error_code;
1240 void start(__reg("a0") struct DosPacket *startup_packet)
1242 SysBase = *(struct ExecBase **)4;
1243 DOSBase = (struct DosLibrary *)OpenLibrary(DOSNAME, 0);
1245 mp = MyCreatePort(NULL, 0);
1247 startup_fs_handler(startup_packet);
1252 struct StandardPacket *sp = (struct StandardPacket *)GetMsg(mp);
1253 struct DosPacket *dp = (struct DosPacket *)(sp->sp_Msg.mn_Node.ln_Name);
1255 switch (dp->dp_Type)
1257 case ACTION_LOCATE_OBJECT: action_locate_object(dp); break;
1258 case ACTION_FREE_LOCK: action_free_lock(dp); break;
1259 case ACTION_COPY_DIR: action_copy_dir(dp); break;
1260 case ACTION_PARENT: action_parent(dp); break;
1261 case ACTION_EXAMINE_OBJECT: action_examine_object(dp); break;
1262 case ACTION_EXAMINE_NEXT: action_examine_next(dp); break;
1263 case ACTION_EXAMINE_FH: action_examine_fh(dp); break;
1265 case ACTION_FINDUPDATE: action_findxxx(dp); break;
1266 case ACTION_FINDINPUT: action_findxxx(dp); break;
1267 case ACTION_FINDOUTPUT: action_findxxx(dp); break;
1268 case ACTION_READ: action_read(dp); break;
1269 case ACTION_WRITE: action_write(dp); break;
1270 case ACTION_SEEK: action_seek(dp); break;
1271 case ACTION_END: action_end(dp); break;
1272 //case ACTION_TRUNCATE: action_truncate(dp); break;
1274 case ACTION_DELETE_OBJECT: action_delete_object(dp); break;
1275 case ACTION_RENAME_OBJECT: action_rename_object(dp); break;
1276 case ACTION_CREATE_DIR: action_create_dir(dp); break;
1278 case ACTION_SET_PROTECT: action_set_protect(dp); break;
1279 case ACTION_SET_COMMENT: action_set_comment(dp); break;
1280 //case ACTION_SET_DATE: action_set_date(dp); break;
1282 case ACTION_SAME_LOCK: action_same_lock(dp); break;
1283 case ACTION_DISK_INFO: action_disk_info(dp); break;
1284 case ACTION_INFO: action_info(dp); break;
1287 case ACTION_CURRENT_VOLUME: action_current_volume(dp); break;
1288 case ACTION_RENAME_DISK: action_rename_disk(dp); break;
1290 case ACTION_DIE: //action_die(dp); break;
1291 case ACTION_MORE_CACHE: //action_more_cache(dp); break;
1292 case ACTION_FLUSH: //action_flush(dp); break;
1293 case ACTION_INHIBIT: //action_inhibit(dp); break;
1294 case ACTION_WRITE_PROTECT: //action_write_protect(dp); break;
1297 default: action_unsupported(dp); break;
1301 dbg("Shutting down\n");
1303 // More cleaning up is necessary if the handler is to exit.
1304 CloseLibrary((struct Library *)DOSBase);