2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
6 /****************************************************************************************/
8 #include <devices/trackdisk.h>
9 #include <exec/resident.h>
10 #include <exec/errors.h>
11 #include <exec/memory.h>
12 #include <proto/exec.h>
13 #include <dos/dosextens.h>
14 #include <dos/dostags.h>
15 #include <proto/dos.h>
16 #include <aros/asmcall.h>
17 #include <aros/libcall.h>
18 #include <aros/symbolsets.h>
19 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
20 #include "fdsk_device_gcc.h"
24 #include <aros/debug.h>
26 #include LC_LIBDEFS_FILE
28 /****************************************************************************************/
30 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR fdskbase
)
32 D(bug("fdsk_device: in libinit func\n"));
34 InitSemaphore(&fdskbase
->sigsem
);
35 NEWLIST((struct List
*)&fdskbase
->units
);
36 fdskbase
->port
.mp_Node
.ln_Type
= NT_MSGPORT
;
37 fdskbase
->port
.mp_Flags
= PA_SIGNAL
;
38 fdskbase
->port
.mp_SigBit
= SIGB_SINGLE
;
39 NEWLIST((struct List
*)&fdskbase
->port
.mp_MsgList
);
41 D(bug("fdsk_device: in libinit func. Returning %x (success) :-)\n", fdskbase
));
45 /****************************************************************************************/
47 AROS_UFP3(LONG
, unitentry
,
48 AROS_UFPA(STRPTR
, argstr
, A0
),
49 AROS_UFPA(ULONG
, arglen
, D0
),
50 AROS_UFPA(struct ExecBase
*, SysBase
, A6
));
52 /****************************************************************************************/
54 static int GM_UNIQUENAME(Open
)
56 LIBBASETYPEPTR fdskbase
,
62 static const struct TagItem tags
[] =
64 { NP_Name
, (IPTR
)"File Disk Unit Process"},
68 { NP_CurrentDir
, 0 },
72 { NP_Entry
, (IPTR
)unitentry
},
77 D(bug("fdsk_device: in libopen func.\n"));
79 D(bug("fdsk_device: in libopen func. Looking if unit is already open\n"));
81 ObtainSemaphore(&fdskbase
->sigsem
);
83 for(unit
= (struct unit
*)fdskbase
->units
.mlh_Head
;
84 unit
->msg
.mn_Node
.ln_Succ
!= NULL
;
85 unit
= (struct unit
*)unit
->msg
.mn_Node
.ln_Succ
)
86 if(unit
->unitnum
== unitnum
)
89 ReleaseSemaphore(&fdskbase
->sigsem
);
91 iotd
->iotd_Req
.io_Unit
= (struct Unit
*)unit
;
92 iotd
->iotd_Req
.io_Error
= 0;
93 iotd
->iotd_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
95 D(bug("fdsk_device: in libopen func. Yep. Unit is already open\n"));
100 D(bug("fdsk_device: in libopen func. No, it is not. So creating new unit ...\n"));
102 unit
= (struct unit
*)AllocMem(sizeof(struct unit
),
103 MEMF_PUBLIC
| MEMF_CLEAR
);
106 D(bug("fdsk_device: in libopen func. Allocation of unit memory okay. Setting up unit and calling CreateNewProc ...\n"));
109 unit
->fdskbase
= fdskbase
;
110 unit
->unitnum
= unitnum
;
111 unit
->msg
.mn_ReplyPort
= &fdskbase
->port
;
112 unit
->msg
.mn_Length
= sizeof(struct unit
);
113 unit
->port
.mp_Node
.ln_Type
= NT_MSGPORT
;
114 unit
->port
.mp_Flags
= PA_IGNORE
;
115 unit
->port
.mp_SigTask
= CreateNewProc((struct TagItem
*)tags
);
116 NEWLIST((struct List
*)&unit
->changeints
);
118 D(bug("fdsk_device: in libopen func. CreateNewProc called. Proc = %x\n", unit
->port
.mp_SigTask
));
120 if(unit
->port
.mp_SigTask
!= NULL
)
122 NEWLIST((struct List
*)&unit
->port
.mp_MsgList
);
124 /* setup replyport to point to active task */
125 fdskbase
->port
.mp_SigTask
= FindTask(NULL
);
126 SetSignal(0, SIGF_SINGLE
);
128 D(bug("fdsk_device: in libopen func. Sending startup msg\n"));
129 PutMsg(&((struct Process
*)unit
->port
.mp_SigTask
)->pr_MsgPort
, &unit
->msg
);
131 D(bug("fdsk_device: in libopen func. Waiting for replymsg\n"));
132 WaitPort(&fdskbase
->port
);
133 (void)GetMsg(&fdskbase
->port
);
134 D(bug("fdsk_device: in libopen func. Received replymsg\n"));
138 AddTail((struct List
*)&fdskbase
->units
, &unit
->msg
.mn_Node
);
139 iotd
->iotd_Req
.io_Unit
= (struct Unit
*)unit
;
141 iotd
->iotd_Req
.io_Error
= 0;
142 ReleaseSemaphore(&fdskbase
->sigsem
);
145 iotd
->iotd_Req
.io_Error
= TDERR_NotSpecified
;
147 iotd
->iotd_Req
.io_Error
= TDERR_NoMem
;
148 FreeMem(unit
, sizeof(struct unit
));
150 iotd
->iotd_Req
.io_Error
= TDERR_NoMem
;
152 ReleaseSemaphore(&fdskbase
->sigsem
);
157 /****************************************************************************************/
159 static int GM_UNIQUENAME(Close
)
161 LIBBASETYPEPTR fdskbase
,
167 ObtainSemaphore(&fdskbase
->sigsem
);
168 unit
= (struct unit
*)iotd
->iotd_Req
.io_Unit
;
169 if(!--unit
->usecount
)
171 Remove(&unit
->msg
.mn_Node
);
172 fdskbase
->port
.mp_SigTask
= FindTask(NULL
);
173 SetSignal(0, SIGF_SINGLE
);
174 PutMsg(&unit
->port
, &unit
->msg
);
175 WaitPort(&fdskbase
->port
);
176 (void)GetMsg(&fdskbase
->port
);
177 FreeMem(unit
, sizeof(struct unit
));
179 ReleaseSemaphore(&fdskbase
->sigsem
);
184 /****************************************************************************************/
186 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
187 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
188 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
190 /****************************************************************************************/
192 AROS_LH1(void, beginio
,
193 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
194 struct fdskbase
*, fdskbase
, 5, Fdsk
)
198 switch(iotd
->iotd_Req
.io_Command
)
203 /* Ignore but don't fail */
204 iotd
->iotd_Req
.io_Error
= 0;
212 case TD_ADDCHANGEINT
:
213 case TD_REMCHANGEINT
:
217 /* Forward to unit thread */
218 PutMsg(&((struct unit
*)iotd
->iotd_Req
.io_Unit
)->port
,
219 &iotd
->iotd_Req
.io_Message
);
221 iotd
->iotd_Req
.io_Flags
&= ~IOF_QUICK
;
226 iotd
->iotd_Req
.io_Error
= IOERR_NOCMD
;
229 } /* switch(iotd->iotd_Req.io_Command) */
231 /* WaitIO will look into this */
232 iotd
->iotd_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
235 if(!(iotd
->iotd_Req
.io_Flags
&IOF_QUICK
))
236 ReplyMsg(&iotd
->iotd_Req
.io_Message
);
241 /****************************************************************************************/
243 AROS_LH1(LONG
, abortio
,
244 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
245 struct fdskbase
*, fdskbase
, 6, Fdsk
)
252 /****************************************************************************************/
254 #define fdskbase unit->fdskbase
256 /****************************************************************************************/
258 static LONG
error(LONG error
)
262 case ERROR_SEEK_ERROR
:
263 return TDERR_SeekError
;
265 case ERROR_DISK_WRITE_PROTECTED
:
266 case ERROR_WRITE_PROTECTED
:
267 return TDERR_WriteProt
;
270 return TDERR_DiskChanged
;
273 return TDERR_NotSpecified
;
277 /****************************************************************************************/
279 static LONG
read(struct unit
*unit
, struct IOExtTD
*iotd
)
284 D(bug("fdsk_device/read: offset = %d size = %d\n", iotd
->iotd_Req
.io_Offset
, iotd
->iotd_Req
.io_Length
));
287 if(iotd
->iotd_SecLabel
)
289 D(bug("fdsk_device/read: iotd->iotd_SecLabel is != NULL -> returning IOERR_NOCMD\n"));
294 if(Seek(unit
->file
, iotd
->iotd_Req
.io_Offset
, OFFSET_BEGINNING
) == -1)
296 D(bug("fdsk_device/read: Seek to offset %d failed. Returning TDERR_SeekError\n", iotd
->iotd_Req
.io_Offset
));
297 return TDERR_SeekError
;
300 buf
= iotd
->iotd_Req
.io_Data
;
301 size
= iotd
->iotd_Req
.io_Length
;
302 iotd
->iotd_Req
.io_Actual
= size
;
306 subsize
= Read(unit
->file
, buf
, size
);
309 iotd
->iotd_Req
.io_Actual
-= size
;
310 D(bug("fdsk_device/read: Read() returned 0. Returning IOERR_BADLENGTH\n"));
311 return IOERR_BADLENGTH
;
315 iotd
->iotd_Req
.io_Actual
-= size
;
316 D(bug("fdsk_device/read: Read() returned -1. Returning error number %d\n", error(IoErr())));
317 return error(IoErr());
324 buf
= iotd
->iotd_Req
.io_Data
;
325 D(bug("fdsk_device/read: returning 0. First 4 buffer bytes = [%c%c%c%c]\n", buf
[0], buf
[1], buf
[2], buf
[3]));
331 /****************************************************************************************/
333 static LONG
write(struct unit
*unit
, struct IOExtTD
*iotd
)
339 return TDERR_WriteProt
;
341 if(iotd
->iotd_SecLabel
)
344 if(Seek(unit
->file
, iotd
->iotd_Req
.io_Offset
, OFFSET_BEGINNING
) == -1)
345 return TDERR_SeekError
;
347 buf
= iotd
->iotd_Req
.io_Data
;
348 size
= iotd
->iotd_Req
.io_Length
;
349 iotd
->iotd_Req
.io_Actual
= size
;
353 subsize
= Write(unit
->file
, buf
, size
);
356 iotd
->iotd_Req
.io_Actual
-= size
;
357 return error(IoErr());
366 /**************************************************************************/
368 static void addchangeint(struct unit
*unit
, struct IOExtTD
*iotd
) {
370 AddTail((struct List
*)&unit
->changeints
, (struct Node
*)iotd
);
374 /**************************************************************************/
376 static void remchangeint(struct unit
*unit
, struct IOExtTD
*iotd
) {
378 Remove((struct Node
*)iotd
);
382 /**************************************************************************/
384 void getgeometry(struct unit
*unit
, struct DriveGeometry
*dg
) {
385 struct FileInfoBlock fib
;
387 ExamineFH(unit
->file
, &fib
);
388 dg
->dg_SectorSize
= 512;
390 dg
->dg_TrackSectors
= 63;
391 dg
->dg_TotalSectors
= fib
.fib_Size
/ dg
->dg_SectorSize
;
392 /* in case of links or block devices with emul_handler we get the wrong size */
393 if (dg
->dg_TotalSectors
== 0)
394 dg
->dg_TotalSectors
= dg
->dg_Heads
*dg
->dg_TrackSectors
*5004;
395 dg
->dg_Cylinders
= dg
->dg_TotalSectors
/ (dg
->dg_Heads
* dg
->dg_TrackSectors
);
396 dg
->dg_CylSectors
= dg
->dg_Heads
* dg
->dg_TrackSectors
;
397 dg
->dg_BufMemType
= MEMF_PUBLIC
;
398 dg
->dg_DeviceType
= DG_DIRECT_ACCESS
;
399 dg
->dg_Flags
= DGF_REMOVABLE
;
402 /**************************************************************************/
404 void eject(struct unit
*unit
, BOOL eject
) {
405 struct IOExtTD
*iotd
;
406 struct FileInfoBlock fib
;
411 unit
->file
= (BPTR
)NULL
;
415 unit
->file
= Open(unit
->filename
, MODE_OLDFILE
);
416 if (unit
->file
== (BPTR
) NULL
)
418 ExamineFH(unit
->file
, &fib
);
419 unit
->writable
= !(fib
.fib_Protection
& FIBF_WRITE
);
424 ForeachNode(&unit
->changeints
, iotd
)
426 Cause((struct Interrupt
*)iotd
->iotd_Req
.io_Data
);
430 /**************************************************************************/
432 AROS_UFH2(void, putchr
,
433 AROS_UFHA(UBYTE
, chr
, D0
),
434 AROS_UFHA(STRPTR
*, p
, A3
)
442 /****************************************************************************************/
444 AROS_UFH3(LONG
, unitentry
,
445 AROS_UFHA(STRPTR
, argstr
, A0
),
446 AROS_UFHA(ULONG
, arglen
, D0
),
447 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
451 UBYTE buf
[10 + sizeof(LONG
) * 8 * 301 / 1000 + 1];
455 struct IOExtTD
*iotd
;
458 struct FileInfoBlock fib
;
460 D(bug("fdsk_device/unitentry: just started\n"));
462 me
= (struct Process
*)FindTask(NULL
);
464 WaitPort(&me
->pr_MsgPort
);
465 unit
= (struct unit
*)GetMsg(&me
->pr_MsgPort
);
466 unit
->port
.mp_SigBit
= AllocSignal(-1);
467 unit
->port
.mp_Flags
= PA_SIGNAL
;
469 /* disable DOS error requesters. save the old pointer so we can put it
471 win
= me
->pr_WindowPtr
;
472 me
->pr_WindowPtr
= (APTR
) -1;
474 (void)RawDoFmt("FDSK:Unit%ld", &unit
->unitnum
, (VOID_FUNC
)putchr
, &ptr
);
476 D(bug("fdsk_device/unitentry: Trying to open \"%s\" ...\n", buf
));
478 unit
->filename
= buf
;
479 unit
->file
= Open(buf
, MODE_OLDFILE
);
483 #warning FIXME: Next line will produce a segfault -- uninitialized variable iotd
484 iotd->iotd_Req.io_Error = error(IoErr());
486 D(bug("fdsk_device/unitentry: open failed ioerr = %d:-( Replying startup msg.\n", IoErr()));
488 ReplyMsg(&unit
->msg
);
492 ExamineFH(unit
->file
, &fib
);
493 unit
->writable
= !(fib
.fib_Protection
& FIBF_WRITE
);
495 /* enable requesters */
496 me
->pr_WindowPtr
= win
;
498 D(bug("fdsk_device/unitentry: open okay :-) Replying startup msg.\n"));
500 ReplyMsg(&unit
->msg
);
502 D(bug("fdsk_device/unitentry: Now entering main loop\n"));
506 while((iotd
= (struct IOExtTD
*)GetMsg(&unit
->port
)) != NULL
)
508 if(&iotd
->iotd_Req
.io_Message
== &unit
->msg
)
510 D(bug("fdsk_device/unitentry: Received EXIT message.\n"));
514 ReplyMsg(&unit
->msg
);
518 switch(iotd
->iotd_Req
.io_Command
)
521 D(bug("fdsk_device/unitentry: received CMD_READ.\n"));
522 err
= read(unit
, iotd
);
527 D(bug("fdsk_device/unitentry: received %s\n", (iotd
->iotd_Req
.io_Command
== CMD_WRITE
) ? "CMD_WRITE" : "TD_FORMAT"));
528 err
= write(unit
, iotd
);
532 iotd
->iotd_Req
.io_Actual
= unit
->changecount
;
536 iotd
->iotd_Req
.io_Actual
= unit
->file
== (BPTR
)NULL
;
538 case TD_ADDCHANGEINT
:
539 addchangeint(unit
, iotd
);
542 case TD_REMCHANGEINT
:
543 remchangeint(unit
, iotd
);
547 getgeometry(unit
, (struct DriveGeometry
*)iotd
->iotd_Req
.io_Data
);
551 eject(unit
, iotd
->iotd_Req
.io_Length
);
555 iotd
->iotd_Req
.io_Actual
= !unit
->writable
;
559 } /* switch(iotd->iotd_Req.io_Command) */
561 iotd
->iotd_Req
.io_Error
= err
;
562 ReplyMsg(&iotd
->iotd_Req
.io_Message
);
564 } /* while((iotd = (struct IOExtTD *)GetMsg(&unit->port)) != NULL) */
566 WaitPort(&unit
->port
);
572 /****************************************************************************************/