2 Copyright © 1995-2013, 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
));
168 AddTail((struct List
*)&fdskbase
->units
, &unit
->msg
.mn_Node
);
169 iotd
->iotd_Req
.io_Unit
= (struct Unit
*)unit
;
171 iotd
->iotd_Req
.io_Error
= 0;
172 ReleaseSemaphore(&fdskbase
->sigsem
);
175 iotd
->iotd_Req
.io_Error
= TDERR_NoMem
;
176 FreeMem(unit
, sizeof(struct unit
));
178 iotd
->iotd_Req
.io_Error
= TDERR_NoMem
;
180 ReleaseSemaphore(&fdskbase
->sigsem
);
185 /****************************************************************************************/
187 static int GM_UNIQUENAME(Close
)
189 LIBBASETYPEPTR fdskbase
,
195 ObtainSemaphore(&fdskbase
->sigsem
);
196 unit
= (struct unit
*)iotd
->iotd_Req
.io_Unit
;
197 if(!--unit
->usecount
)
199 Remove(&unit
->msg
.mn_Node
);
200 fdskbase
->port
.mp_SigTask
= FindTask(NULL
);
201 SetSignal(0, SIGF_SINGLE
);
202 PutMsg(&unit
->port
, &unit
->msg
);
203 WaitPort(&fdskbase
->port
);
204 (void)GetMsg(&fdskbase
->port
);
205 FreeMem(unit
, sizeof(struct unit
));
207 ReleaseSemaphore(&fdskbase
->sigsem
);
212 /****************************************************************************************/
214 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
215 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
216 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
218 /****************************************************************************************/
220 AROS_LH1(void, beginio
,
221 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
222 struct fdskbase
*, fdskbase
, 5, Fdsk
)
226 struct unit
*unit
= (struct unit
*)iotd
->iotd_Req
.io_Unit
;
227 switch(iotd
->iotd_Req
.io_Command
)
230 case NSCMD_DEVICEQUERY
:
231 D(bug("[FDSK ] NSCMD_DEVICEQUERY\n"));
232 if(iotd
->iotd_Req
.io_Length
< ((LONG
)OFFSET(NSDeviceQueryResult
, SupportedCommands
)) + sizeof(UWORD
*))
234 iotd
->iotd_Req
.io_Error
= IOERR_BADLENGTH
;
238 struct NSDeviceQueryResult
*d
;
240 d
= (struct NSDeviceQueryResult
*)iotd
->iotd_Req
.io_Data
;
242 d
->DevQueryFormat
= 0;
243 d
->SizeAvailable
= sizeof(struct NSDeviceQueryResult
);
244 d
->DeviceType
= NSDEVTYPE_TRACKDISK
;
245 d
->DeviceSubType
= 0;
246 d
->SupportedCommands
= (UWORD
*)SupportedCommands
;
248 iotd
->iotd_Req
.io_Actual
= sizeof(struct NSDeviceQueryResult
);
249 iotd
->iotd_Req
.io_Error
= 0;
252 case TD_GETDRIVETYPE
:
253 iotd
->iotd_Req
.io_Actual
= DRIVE_NEWSTYLE
;
262 /* Ignore but don't fail */
263 iotd
->iotd_Req
.io_Error
= 0;
273 if (unit
->file
== BNULL
)
275 iotd
->iotd_Req
.io_Error
= TDERR_DiskChanged
;
280 case TD_ADDCHANGEINT
:
281 case TD_REMCHANGEINT
:
284 /* Forward to unit thread */
285 PutMsg(&unit
->port
, &iotd
->iotd_Req
.io_Message
);
287 iotd
->iotd_Req
.io_Flags
&= ~IOF_QUICK
;
292 iotd
->iotd_Req
.io_Error
= IOERR_NOCMD
;
295 } /* switch(iotd->iotd_Req.io_Command) */
297 /* WaitIO will look into this */
298 iotd
->iotd_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
301 if(!(iotd
->iotd_Req
.io_Flags
&IOF_QUICK
))
302 ReplyMsg(&iotd
->iotd_Req
.io_Message
);
307 /****************************************************************************************/
309 AROS_LH1(LONG
, abortio
,
310 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
311 struct fdskbase
*, fdskbase
, 6, Fdsk
)
318 /****************************************************************************************/
320 #define fdskbase unit->fdskbase
322 /****************************************************************************************/
324 static LONG
error(LONG error
)
328 case ERROR_SEEK_ERROR
:
329 return TDERR_SeekError
;
331 case ERROR_DISK_WRITE_PROTECTED
:
332 case ERROR_WRITE_PROTECTED
:
333 return TDERR_WriteProt
;
336 return TDERR_DiskChanged
;
339 return TDERR_NotSpecified
;
343 /****************************************************************************************/
345 static LONG
read(struct unit
*unit
, struct IOExtTD
*iotd
)
350 D(bug("[FDSK%02ld] read32: offset = %08x size = %08x\n", unit
->unitnum
, iotd
->iotd_Req
.io_Offset
, iotd
->iotd_Req
.io_Length
));
353 if(iotd
->iotd_SecLabel
)
355 D(bug("[FDSK%02ld] read32: iotd->iotd_SecLabel is != NULL -> returning IOERR_NOCMD\n", unit
->unitnum
));
360 if(Seek(unit
->file
, iotd
->iotd_Req
.io_Offset
, OFFSET_BEGINNING
) == -1)
362 D(bug("[FDSK%02ld] read32: Seek to offset %d failed. Returning TDERR_SeekError\n", unit
->unitnum
, iotd
->iotd_Req
.io_Offset
));
363 return TDERR_SeekError
;
366 buf
= iotd
->iotd_Req
.io_Data
;
367 size
= iotd
->iotd_Req
.io_Length
;
368 iotd
->iotd_Req
.io_Actual
= size
;
372 subsize
= Read(unit
->file
, buf
, size
);
375 iotd
->iotd_Req
.io_Actual
-= size
;
376 D(bug("[FDSK%02ld] read32: Read() returned 0. Returning IOERR_BADLENGTH\n", unit
->unitnum
));
377 return IOERR_BADLENGTH
;
381 iotd
->iotd_Req
.io_Actual
-= size
;
382 D(bug("[FDSK%02ld] read32: Read() returned -1. Returning error number %d\n", unit
->unitnum
, error(IoErr())));
383 return error(IoErr());
390 buf
= iotd
->iotd_Req
.io_Data
;
391 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]));
397 /****************************************************************************************/
399 static LONG
write(struct unit
*unit
, struct IOExtTD
*iotd
)
404 D(bug("[FDSK%02ld] write32: offset = %08x size = %08x\n", unit
->unitnum
, iotd
->iotd_Req
.io_Offset
, iotd
->iotd_Req
.io_Length
));
407 return TDERR_WriteProt
;
409 if(iotd
->iotd_SecLabel
)
412 if(Seek(unit
->file
, iotd
->iotd_Req
.io_Offset
, OFFSET_BEGINNING
) == -1)
413 return TDERR_SeekError
;
415 buf
= iotd
->iotd_Req
.io_Data
;
416 size
= iotd
->iotd_Req
.io_Length
;
417 iotd
->iotd_Req
.io_Actual
= size
;
421 subsize
= Write(unit
->file
, buf
, size
);
424 iotd
->iotd_Req
.io_Actual
-= size
;
425 return error(IoErr());
434 /**************************************************************************/
436 static void addchangeint(struct unit
*unit
, struct IOExtTD
*iotd
) {
438 AddTail((struct List
*)&unit
->changeints
, (struct Node
*)iotd
);
442 /**************************************************************************/
444 static void remchangeint(struct unit
*unit
, struct IOExtTD
*iotd
) {
446 Remove((struct Node
*)iotd
);
450 /**************************************************************************/
452 void getgeometry(struct unit
*unit
, struct DriveGeometry
*dg
) {
453 struct FileInfoBlock fib
;
455 ExamineFH(unit
->file
, &fib
);
456 dg
->dg_SectorSize
= 512;
458 dg
->dg_TrackSectors
= 63;
459 dg
->dg_TotalSectors
= fib
.fib_Size
/ dg
->dg_SectorSize
;
460 /* in case of links or block devices with emul_handler we get the wrong size */
461 if (dg
->dg_TotalSectors
== 0)
462 dg
->dg_TotalSectors
= dg
->dg_Heads
*dg
->dg_TrackSectors
*5004;
463 dg
->dg_Cylinders
= dg
->dg_TotalSectors
/ (dg
->dg_Heads
* dg
->dg_TrackSectors
);
464 dg
->dg_CylSectors
= dg
->dg_Heads
* dg
->dg_TrackSectors
;
465 dg
->dg_BufMemType
= MEMF_PUBLIC
;
466 dg
->dg_DeviceType
= DG_DIRECT_ACCESS
;
467 dg
->dg_Flags
= DGF_REMOVABLE
;
470 /**************************************************************************/
472 void eject(struct unit
*unit
, BOOL eject
) {
473 struct IOExtTD
*iotd
;
474 struct FileInfoBlock fib
;
476 if((eject
&& unit
->file
!= BNULL
) || (!eject
&& unit
->file
== BNULL
))
481 unit
->file
= (BPTR
)NULL
;
485 unit
->file
= Open(unit
->filename
, MODE_OLDFILE
);
486 if (unit
->file
== BNULL
)
488 ExamineFH(unit
->file
, &fib
);
489 unit
->writable
= !(fib
.fib_Protection
& FIBF_WRITE
);
494 ForeachNode(&unit
->changeints
, iotd
)
496 Cause((struct Interrupt
*)iotd
->iotd_Req
.io_Data
);
503 /**************************************************************************/
505 AROS_UFH2(void, putchr
,
506 AROS_UFHA(UBYTE
, chr
, D0
),
507 AROS_UFHA(STRPTR
*, p
, A3
)
515 /****************************************************************************************/
517 AROS_UFH3(LONG
, unitentry
,
518 AROS_UFHA(STRPTR
, argstr
, A0
),
519 AROS_UFHA(ULONG
, arglen
, D0
),
520 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
524 UBYTE buf
[10 + sizeof(LONG
) * 8 * 301 / 1000 + 1];
528 struct IOExtTD
*iotd
;
531 struct FileInfoBlock fib
;
533 me
= (struct Process
*)FindTask(NULL
);
535 WaitPort(&me
->pr_MsgPort
);
536 unit
= (struct unit
*)GetMsg(&me
->pr_MsgPort
);
537 unit
->port
.mp_SigBit
= AllocSignal(-1);
538 unit
->port
.mp_Flags
= PA_SIGNAL
;
540 /* disable DOS error requesters. save the old pointer so we can put it
542 win
= me
->pr_WindowPtr
;
543 me
->pr_WindowPtr
= (APTR
) -1;
545 (void)RawDoFmt("FDSK:Unit%ld", &unit
->unitnum
, (VOID_FUNC
)putchr
, &ptr
);
547 D(bug("[FDSK%02ld] Trying to open \"%s\" ...\n", unit
->unitnum
, buf
));
549 unit
->filename
= buf
;
550 unit
->file
= Open(buf
, MODE_OLDFILE
);
552 if(unit
->file
!= BNULL
)
554 ExamineFH(unit
->file
, &fib
);
555 unit
->writable
= !(fib
.fib_Protection
& FIBF_WRITE
);
558 /* enable requesters */
559 me
->pr_WindowPtr
= win
;
561 D(bug("[FDSK%02ld] open okay :-) Replying startup msg.\n", unit
->unitnum
));
563 ReplyMsg(&unit
->msg
);
565 D(bug("[FDSK%02ld] now entering main loop.\n", unit
->unitnum
));
569 while((iotd
= (struct IOExtTD
*)GetMsg(&unit
->port
)) != NULL
)
571 if(&iotd
->iotd_Req
.io_Message
== &unit
->msg
)
573 D(bug("[FDSK%02ld] received EXIT message.\n", unit
->unitnum
));
577 ReplyMsg(&unit
->msg
);
580 switch(iotd
->iotd_Req
.io_Command
)
584 D(bug("[FDSK%02ld] received CMD_READ.\n", unit
->unitnum
));
585 err
= read(unit
, iotd
);
591 D(bug("[FDSK%02ld] received %s\n", unit
->unitnum
, (
592 (iotd
->iotd_Req
.io_Command
== ETD_WRITE
) ||
593 (iotd
->iotd_Req
.io_Command
== CMD_WRITE
)) ? "CMD_WRITE" : "TD_FORMAT"));
594 err
= write(unit
, iotd
);
598 iotd
->iotd_Req
.io_Actual
= unit
->changecount
;
602 iotd
->iotd_Req
.io_Actual
= unit
->file
== (BPTR
)NULL
;
604 case TD_ADDCHANGEINT
:
605 addchangeint(unit
, iotd
);
608 case TD_REMCHANGEINT
:
609 remchangeint(unit
, iotd
);
613 getgeometry(unit
, (struct DriveGeometry
*)iotd
->iotd_Req
.io_Data
);
617 eject(unit
, iotd
->iotd_Req
.io_Length
);
621 iotd
->iotd_Req
.io_Actual
= !unit
->writable
;
625 } /* switch(iotd->iotd_Req.io_Command) */
626 iotd
->iotd_Req
.io_Error
= err
;
627 ReplyMsg(&iotd
->iotd_Req
.io_Message
);
628 } /* while((iotd = (struct IOExtTD *)GetMsg(&unit->port)) != NULL) */
629 WaitPort(&unit
->port
);
634 /****************************************************************************************/