2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
6 /****************************************************************************************/
8 #include <devices/trackdisk.h>
9 #include <devices/newstyle.h>
10 #include <exec/resident.h>
11 #include <exec/errors.h>
12 #include <exec/memory.h>
13 #include <exec/initializers.h>
14 #include <proto/exec.h>
15 #include <dos/dosextens.h>
16 #include <dos/dostags.h>
17 #include <proto/dos.h>
18 #include <aros/asmcall.h>
19 #include <aros/libcall.h>
20 #include <aros/symbolsets.h>
21 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
22 #include "fdsk_device_gcc.h"
26 #include <aros/debug.h>
28 #include LC_LIBDEFS_FILE
30 #define NEWSTYLE_DEVICE 1
33 static const UWORD SupportedCommands
[] =
60 /****************************************************************************************/
62 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR fdskbase
)
64 D(bug("[FDSK ] in libinit func\n"));
66 InitSemaphore(&fdskbase
->sigsem
);
67 NEWLIST((struct List
*)&fdskbase
->units
);
68 fdskbase
->port
.mp_Node
.ln_Type
= NT_MSGPORT
;
69 fdskbase
->port
.mp_Flags
= PA_SIGNAL
;
70 fdskbase
->port
.mp_SigBit
= SIGB_SINGLE
;
71 NEWLIST((struct List
*)&fdskbase
->port
.mp_MsgList
);
73 D(bug("[FDSK ] in libinit func. Returning %x (success) :-)\n", fdskbase
));
77 /****************************************************************************************/
79 AROS_UFP3(LONG
, unitentry
,
80 AROS_UFPA(STRPTR
, argstr
, A0
),
81 AROS_UFPA(ULONG
, arglen
, D0
),
82 AROS_UFPA(struct ExecBase
*, SysBase
, A6
));
84 /****************************************************************************************/
86 static int GM_UNIQUENAME(Open
)
88 LIBBASETYPEPTR fdskbase
,
94 static const struct TagItem tags
[] =
96 { NP_Name
, (IPTR
)"File Disk Unit Process"},
100 { NP_CurrentDir
, 0 },
104 { NP_Entry
, (IPTR
)unitentry
},
109 D(bug("[FDSK%02ld] in libopen func.\n", unitnum
));
111 D(bug("[FDSK%02ld] in libopen func. Looking if unit%ld is already open\n", unitnum
, unitnum
));
113 ObtainSemaphore(&fdskbase
->sigsem
);
115 for(unit
= (struct unit
*)fdskbase
->units
.mlh_Head
;
116 unit
->msg
.mn_Node
.ln_Succ
!= NULL
;
117 unit
= (struct unit
*)unit
->msg
.mn_Node
.ln_Succ
)
118 if(unit
->unitnum
== unitnum
)
121 ReleaseSemaphore(&fdskbase
->sigsem
);
123 iotd
->iotd_Req
.io_Unit
= (struct Unit
*)unit
;
124 iotd
->iotd_Req
.io_Error
= 0;
125 iotd
->iotd_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
127 D(bug("[FDSK%02ld] in libopen func. Yep. Unit is already open\n", unitnum
));
132 D(bug("[FDSK%02ld] in libopen func. No, it is not. So creating new unit ...\n", unitnum
));
134 unit
= (struct unit
*)AllocMem(sizeof(struct unit
),
135 MEMF_PUBLIC
| MEMF_CLEAR
);
138 D(bug("[FDSK%02ld] in libopen func. Allocation of unit memory okay. Setting up unit and calling CreateNewProc ...\n", unitnum
));
141 unit
->fdskbase
= fdskbase
;
142 unit
->unitnum
= unitnum
;
143 unit
->msg
.mn_ReplyPort
= &fdskbase
->port
;
144 unit
->msg
.mn_Length
= sizeof(struct unit
);
145 unit
->port
.mp_Node
.ln_Type
= NT_MSGPORT
;
146 unit
->port
.mp_Flags
= PA_IGNORE
;
147 unit
->port
.mp_SigTask
= CreateNewProc((struct TagItem
*)tags
);
148 NEWLIST((struct List
*)&unit
->changeints
);
150 D(bug("[FDSK%02ld] in libopen func. CreateNewProc called. Proc = %x\n", unitnum
, unit
->port
.mp_SigTask
));
152 if(unit
->port
.mp_SigTask
!= NULL
)
154 NEWLIST((struct List
*)&unit
->port
.mp_MsgList
);
156 /* setup replyport to point to active task */
157 fdskbase
->port
.mp_SigTask
= FindTask(NULL
);
158 SetSignal(0, SIGF_SINGLE
);
160 D(bug("[FDSK%02ld] in libopen func. Sending startup msg\n", unitnum
));
161 PutMsg(&((struct Process
*)unit
->port
.mp_SigTask
)->pr_MsgPort
, &unit
->msg
);
163 D(bug("[FDSK%02ld] in libopen func. Waiting for replymsg\n", unitnum
));
164 WaitPort(&fdskbase
->port
);
165 (void)GetMsg(&fdskbase
->port
);
166 D(bug("[FDSK%02ld] in libopen func. Received replymsg\n", unitnum
));
170 AddTail((struct List
*)&fdskbase
->units
, &unit
->msg
.mn_Node
);
171 iotd
->iotd_Req
.io_Unit
= (struct Unit
*)unit
;
173 iotd
->iotd_Req
.io_Error
= 0;
174 ReleaseSemaphore(&fdskbase
->sigsem
);
177 iotd
->iotd_Req
.io_Error
= TDERR_NotSpecified
;
179 iotd
->iotd_Req
.io_Error
= TDERR_NoMem
;
180 FreeMem(unit
, sizeof(struct unit
));
182 iotd
->iotd_Req
.io_Error
= TDERR_NoMem
;
184 ReleaseSemaphore(&fdskbase
->sigsem
);
189 /****************************************************************************************/
191 static int GM_UNIQUENAME(Close
)
193 LIBBASETYPEPTR fdskbase
,
199 ObtainSemaphore(&fdskbase
->sigsem
);
200 unit
= (struct unit
*)iotd
->iotd_Req
.io_Unit
;
201 if(!--unit
->usecount
)
203 Remove(&unit
->msg
.mn_Node
);
204 fdskbase
->port
.mp_SigTask
= FindTask(NULL
);
205 SetSignal(0, SIGF_SINGLE
);
206 PutMsg(&unit
->port
, &unit
->msg
);
207 WaitPort(&fdskbase
->port
);
208 (void)GetMsg(&fdskbase
->port
);
209 FreeMem(unit
, sizeof(struct unit
));
211 ReleaseSemaphore(&fdskbase
->sigsem
);
216 /****************************************************************************************/
218 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
219 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
220 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
222 /****************************************************************************************/
224 AROS_LH1(void, beginio
,
225 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
226 struct fdskbase
*, fdskbase
, 5, Fdsk
)
230 switch(iotd
->iotd_Req
.io_Command
)
233 case NSCMD_DEVICEQUERY
:
234 D(bug("[FDSK ] NSCMD_DEVICEQUERY\n"));
235 if(iotd
->iotd_Req
.io_Length
< ((LONG
)OFFSET(NSDeviceQueryResult
, SupportedCommands
)) + sizeof(UWORD
*))
237 iotd
->iotd_Req
.io_Error
= IOERR_BADLENGTH
;
241 struct NSDeviceQueryResult
*d
;
243 d
= (struct NSDeviceQueryResult
*)iotd
->iotd_Req
.io_Data
;
245 d
->DevQueryFormat
= 0;
246 d
->SizeAvailable
= sizeof(struct NSDeviceQueryResult
);
247 d
->DeviceType
= NSDEVTYPE_TRACKDISK
;
248 d
->DeviceSubType
= 0;
249 d
->SupportedCommands
= (UWORD
*)SupportedCommands
;
251 iotd
->iotd_Req
.io_Actual
= sizeof(struct NSDeviceQueryResult
);
252 iotd
->iotd_Req
.io_Error
= 0;
255 case TD_GETDRIVETYPE
:
256 iotd
->iotd_Req
.io_Actual
= DRIVE_NEWSTYLE
;
265 /* Ignore but don't fail */
266 iotd
->iotd_Req
.io_Error
= 0;
277 case TD_ADDCHANGEINT
:
278 case TD_REMCHANGEINT
:
282 /* Forward to unit thread */
283 PutMsg(&((struct unit
*)iotd
->iotd_Req
.io_Unit
)->port
,
284 &iotd
->iotd_Req
.io_Message
);
286 iotd
->iotd_Req
.io_Flags
&= ~IOF_QUICK
;
291 iotd
->iotd_Req
.io_Error
= IOERR_NOCMD
;
294 } /* switch(iotd->iotd_Req.io_Command) */
296 /* WaitIO will look into this */
297 iotd
->iotd_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
300 if(!(iotd
->iotd_Req
.io_Flags
&IOF_QUICK
))
301 ReplyMsg(&iotd
->iotd_Req
.io_Message
);
306 /****************************************************************************************/
308 AROS_LH1(LONG
, abortio
,
309 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
310 struct fdskbase
*, fdskbase
, 6, Fdsk
)
317 /****************************************************************************************/
319 #define fdskbase unit->fdskbase
321 /****************************************************************************************/
323 static LONG
error(LONG error
)
327 case ERROR_SEEK_ERROR
:
328 return TDERR_SeekError
;
330 case ERROR_DISK_WRITE_PROTECTED
:
331 case ERROR_WRITE_PROTECTED
:
332 return TDERR_WriteProt
;
335 return TDERR_DiskChanged
;
338 return TDERR_NotSpecified
;
342 /****************************************************************************************/
344 static LONG
read(struct unit
*unit
, struct IOExtTD
*iotd
)
349 D(bug("[FDSK%02ld] read32: offset = %08x size = %08x\n", unit
->unitnum
, iotd
->iotd_Req
.io_Offset
, iotd
->iotd_Req
.io_Length
));
352 if(iotd
->iotd_SecLabel
)
354 D(bug("[FDSK%02ld] read32: iotd->iotd_SecLabel is != NULL -> returning IOERR_NOCMD\n", unit
->unitnum
));
359 if(Seek(unit
->file
, iotd
->iotd_Req
.io_Offset
, OFFSET_BEGINNING
) == -1)
361 D(bug("[FDSK%02ld] read32: Seek to offset %d failed. Returning TDERR_SeekError\n", unit
->unitnum
, iotd
->iotd_Req
.io_Offset
));
362 return TDERR_SeekError
;
365 buf
= iotd
->iotd_Req
.io_Data
;
366 size
= iotd
->iotd_Req
.io_Length
;
367 iotd
->iotd_Req
.io_Actual
= size
;
371 subsize
= Read(unit
->file
, buf
, size
);
374 iotd
->iotd_Req
.io_Actual
-= size
;
375 D(bug("[FDSK%02ld] read32: Read() returned 0. Returning IOERR_BADLENGTH\n", unit
->unitnum
));
376 return IOERR_BADLENGTH
;
380 iotd
->iotd_Req
.io_Actual
-= size
;
381 D(bug("[FDSK%02ld] read32: Read() returned -1. Returning error number %d\n", unit
->unitnum
, error(IoErr())));
382 return error(IoErr());
389 buf
= iotd
->iotd_Req
.io_Data
;
390 D(bug("[FDSK%02ld] read32: returning 0. First 4 buffer bytes = [%c%c%c%c]\n", unit
->unitnum
, buf
[0], buf
[1], buf
[2], buf
[3]));
396 /****************************************************************************************/
398 static LONG
write(struct unit
*unit
, struct IOExtTD
*iotd
)
403 D(bug("[FDSK%02ld] write32: offset = %08x size = %08x\n", unit
->unitnum
, iotd
->iotd_Req
.io_Offset
, iotd
->iotd_Req
.io_Length
));
406 return TDERR_WriteProt
;
408 if(iotd
->iotd_SecLabel
)
411 if(Seek(unit
->file
, iotd
->iotd_Req
.io_Offset
, OFFSET_BEGINNING
) == -1)
412 return TDERR_SeekError
;
414 buf
= iotd
->iotd_Req
.io_Data
;
415 size
= iotd
->iotd_Req
.io_Length
;
416 iotd
->iotd_Req
.io_Actual
= size
;
420 subsize
= Write(unit
->file
, buf
, size
);
423 iotd
->iotd_Req
.io_Actual
-= size
;
424 return error(IoErr());
433 /**************************************************************************/
435 static void addchangeint(struct unit
*unit
, struct IOExtTD
*iotd
) {
437 AddTail((struct List
*)&unit
->changeints
, (struct Node
*)iotd
);
441 /**************************************************************************/
443 static void remchangeint(struct unit
*unit
, struct IOExtTD
*iotd
) {
445 Remove((struct Node
*)iotd
);
449 /**************************************************************************/
451 void getgeometry(struct unit
*unit
, struct DriveGeometry
*dg
) {
452 struct FileInfoBlock fib
;
454 ExamineFH(unit
->file
, &fib
);
455 dg
->dg_SectorSize
= 512;
457 dg
->dg_TrackSectors
= 63;
458 dg
->dg_TotalSectors
= fib
.fib_Size
/ dg
->dg_SectorSize
;
459 /* in case of links or block devices with emul_handler we get the wrong size */
460 if (dg
->dg_TotalSectors
== 0)
461 dg
->dg_TotalSectors
= dg
->dg_Heads
*dg
->dg_TrackSectors
*5004;
462 dg
->dg_Cylinders
= dg
->dg_TotalSectors
/ (dg
->dg_Heads
* dg
->dg_TrackSectors
);
463 dg
->dg_CylSectors
= dg
->dg_Heads
* dg
->dg_TrackSectors
;
464 dg
->dg_BufMemType
= MEMF_PUBLIC
;
465 dg
->dg_DeviceType
= DG_DIRECT_ACCESS
;
466 dg
->dg_Flags
= DGF_REMOVABLE
;
469 /**************************************************************************/
471 void eject(struct unit
*unit
, BOOL eject
) {
472 struct IOExtTD
*iotd
;
473 struct FileInfoBlock fib
;
478 unit
->file
= (BPTR
)NULL
;
482 unit
->file
= Open(unit
->filename
, MODE_OLDFILE
);
483 if (unit
->file
== BNULL
)
485 ExamineFH(unit
->file
, &fib
);
486 unit
->writable
= !(fib
.fib_Protection
& FIBF_WRITE
);
491 ForeachNode(&unit
->changeints
, iotd
)
493 Cause((struct Interrupt
*)iotd
->iotd_Req
.io_Data
);
498 /**************************************************************************/
500 AROS_UFH2(void, putchr
,
501 AROS_UFHA(UBYTE
, chr
, D0
),
502 AROS_UFHA(STRPTR
*, p
, A3
)
510 /****************************************************************************************/
512 AROS_UFH3(LONG
, unitentry
,
513 AROS_UFHA(STRPTR
, argstr
, A0
),
514 AROS_UFHA(ULONG
, arglen
, D0
),
515 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
519 UBYTE buf
[10 + sizeof(LONG
) * 8 * 301 / 1000 + 1];
523 struct IOExtTD
*iotd
;
526 struct FileInfoBlock fib
;
528 me
= (struct Process
*)FindTask(NULL
);
530 WaitPort(&me
->pr_MsgPort
);
531 unit
= (struct unit
*)GetMsg(&me
->pr_MsgPort
);
532 unit
->port
.mp_SigBit
= AllocSignal(-1);
533 unit
->port
.mp_Flags
= PA_SIGNAL
;
535 /* disable DOS error requesters. save the old pointer so we can put it
537 win
= me
->pr_WindowPtr
;
538 me
->pr_WindowPtr
= (APTR
) -1;
540 (void)RawDoFmt("FDSK:Unit%ld", &unit
->unitnum
, (VOID_FUNC
)putchr
, &ptr
);
542 D(bug("[FDSK%02ld] Trying to open \"%s\" ...\n", unit
->unitnum
, buf
));
544 unit
->filename
= buf
;
545 unit
->file
= Open(buf
, MODE_OLDFILE
);
549 #warning FIXME: Next line will produce a segfault -- uninitialized variable iotd
550 iotd->iotd_Req.io_Error = error(IoErr());
552 D(bug("[FDSK%02ld] open failed ioerr = %d :-( Replying startup msg!\n", unit
->unitnum
, IoErr()));
554 ReplyMsg(&unit
->msg
);
558 ExamineFH(unit
->file
, &fib
);
559 unit
->writable
= !(fib
.fib_Protection
& FIBF_WRITE
);
561 /* enable requesters */
562 me
->pr_WindowPtr
= win
;
564 D(bug("[FDSK%02ld] open okay :-) Replying startup msg.\n", unit
->unitnum
));
566 ReplyMsg(&unit
->msg
);
568 D(bug("[FDSK%02ld] now entering main loop.\n", unit
->unitnum
));
572 while((iotd
= (struct IOExtTD
*)GetMsg(&unit
->port
)) != NULL
)
574 if(&iotd
->iotd_Req
.io_Message
== &unit
->msg
)
576 D(bug("[FDSK%02ld] received EXIT message.\n", unit
->unitnum
));
580 ReplyMsg(&unit
->msg
);
583 switch(iotd
->iotd_Req
.io_Command
)
587 D(bug("[FDSK%02ld] received CMD_READ.\n", unit
->unitnum
));
588 err
= read(unit
, iotd
);
594 D(bug("[FDSK%02ld] received %s\n", unit
->unitnum
, (
595 (iotd
->iotd_Req
.io_Command
== ETD_WRITE
) ||
596 (iotd
->iotd_Req
.io_Command
== CMD_WRITE
)) ? "CMD_WRITE" : "TD_FORMAT"));
597 err
= write(unit
, iotd
);
601 iotd
->iotd_Req
.io_Actual
= unit
->changecount
;
605 iotd
->iotd_Req
.io_Actual
= unit
->file
== (BPTR
)NULL
;
607 case TD_ADDCHANGEINT
:
608 addchangeint(unit
, iotd
);
611 case TD_REMCHANGEINT
:
612 remchangeint(unit
, iotd
);
616 getgeometry(unit
, (struct DriveGeometry
*)iotd
->iotd_Req
.io_Data
);
620 eject(unit
, iotd
->iotd_Req
.io_Length
);
624 iotd
->iotd_Req
.io_Actual
= !unit
->writable
;
628 } /* switch(iotd->iotd_Req.io_Command) */
629 iotd
->iotd_Req
.io_Error
= err
;
630 ReplyMsg(&iotd
->iotd_Req
.io_Message
);
631 } /* while((iotd = (struct IOExtTD *)GetMsg(&unit->port)) != NULL) */
632 WaitPort(&unit
->port
);
637 /****************************************************************************************/