2 Copyright © 1995-2006, 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
), MEMF_PUBLIC
);
105 D(bug("fdsk_device: in libopen func. Allocation of unit memory okay. Setting up unit and calling CreateNewProc ...\n"));
108 unit
->fdskbase
= fdskbase
;
109 unit
->unitnum
= unitnum
;
110 unit
->msg
.mn_ReplyPort
= &fdskbase
->port
;
111 unit
->msg
.mn_Length
= sizeof(struct unit
);
112 unit
->port
.mp_Node
.ln_Type
= NT_MSGPORT
;
113 unit
->port
.mp_Flags
= PA_IGNORE
;
114 unit
->port
.mp_SigTask
= CreateNewProc((struct TagItem
*)tags
);
116 D(bug("fdsk_device: in libopen func. CreateNewProc called. Proc = %x\n", unit
->port
.mp_SigTask
));
118 if(unit
->port
.mp_SigTask
!= NULL
)
120 NEWLIST((struct List
*)&unit
->port
.mp_MsgList
);
122 /* setup replyport to point to active task */
123 fdskbase
->port
.mp_SigTask
= FindTask(NULL
);
124 SetSignal(0, SIGF_SINGLE
);
126 D(bug("fdsk_device: in libopen func. Sending startup msg\n"));
127 PutMsg(&((struct Process
*)unit
->port
.mp_SigTask
)->pr_MsgPort
, &unit
->msg
);
129 D(bug("fdsk_device: in libopen func. Waiting for replymsg\n"));
130 WaitPort(&fdskbase
->port
);
131 (void)GetMsg(&fdskbase
->port
);
132 D(bug("fdsk_device: in libopen func. Received replymsg\n"));
136 AddTail((struct List
*)&fdskbase
->units
, &unit
->msg
.mn_Node
);
137 iotd
->iotd_Req
.io_Unit
= (struct Unit
*)unit
;
139 iotd
->iotd_Req
.io_Error
= 0;
140 ReleaseSemaphore(&fdskbase
->sigsem
);
143 iotd
->iotd_Req
.io_Error
= TDERR_NotSpecified
;
145 iotd
->iotd_Req
.io_Error
= TDERR_NoMem
;
146 FreeMem(unit
, sizeof(struct unit
));
148 iotd
->iotd_Req
.io_Error
= TDERR_NoMem
;
150 ReleaseSemaphore(&fdskbase
->sigsem
);
155 /****************************************************************************************/
157 static int GM_UNIQUENAME(Close
)
159 LIBBASETYPEPTR fdskbase
,
165 ObtainSemaphore(&fdskbase
->sigsem
);
166 unit
= (struct unit
*)iotd
->iotd_Req
.io_Unit
;
167 if(!--unit
->usecount
)
169 Remove(&unit
->msg
.mn_Node
);
170 fdskbase
->port
.mp_SigTask
= FindTask(NULL
);
171 SetSignal(0, SIGF_SINGLE
);
172 PutMsg(&unit
->port
, &unit
->msg
);
173 WaitPort(&fdskbase
->port
);
174 (void)GetMsg(&fdskbase
->port
);
175 FreeMem(unit
, sizeof(struct unit
));
177 ReleaseSemaphore(&fdskbase
->sigsem
);
182 /****************************************************************************************/
184 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
185 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
186 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
188 /****************************************************************************************/
190 AROS_LH1(void, beginio
,
191 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
192 struct fdskbase
*, fdskbase
, 5, Fdsk
)
196 switch(iotd
->iotd_Req
.io_Command
)
201 /* Ignore but don't fail */
202 iotd
->iotd_Req
.io_Error
= 0;
211 /* Forward to unit thread */
212 PutMsg(&((struct unit
*)iotd
->iotd_Req
.io_Unit
)->port
,
213 &iotd
->iotd_Req
.io_Message
);
215 iotd
->iotd_Req
.io_Flags
&= ~IOF_QUICK
;
220 iotd
->iotd_Req
.io_Error
= IOERR_NOCMD
;
223 } /* switch(iotd->iotd_Req.io_Command) */
225 /* WaitIO will look into this */
226 iotd
->iotd_Req
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
229 if(!(iotd
->iotd_Req
.io_Flags
&IOF_QUICK
))
230 ReplyMsg(&iotd
->iotd_Req
.io_Message
);
235 /****************************************************************************************/
237 AROS_LH1(LONG
, abortio
,
238 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
239 struct fdskbase
*, fdskbase
, 6, Fdsk
)
246 /****************************************************************************************/
248 #define fdskbase unit->fdskbase
250 /****************************************************************************************/
252 static LONG
error(LONG error
)
256 case ERROR_SEEK_ERROR
:
257 return TDERR_SeekError
;
259 case ERROR_DISK_WRITE_PROTECTED
:
260 case ERROR_WRITE_PROTECTED
:
261 return TDERR_WriteProt
;
264 return TDERR_DiskChanged
;
267 return TDERR_NotSpecified
;
271 /****************************************************************************************/
273 static LONG
read(struct unit
*unit
, struct IOExtTD
*iotd
)
278 D(bug("fdsk_device/read: offset = %d size = %d\n", iotd
->iotd_Req
.io_Offset
, iotd
->iotd_Req
.io_Length
));
281 if(iotd
->iotd_SecLabel
)
283 D(bug("fdsk_device/read: iotd->iotd_SecLabel is != NULL -> returning IOERR_NOCMD\n"));
288 if(Seek(unit
->file
, iotd
->iotd_Req
.io_Offset
, OFFSET_BEGINNING
) == -1)
290 D(bug("fdsk_device/read: Seek to offset %d failed. Returning TDERR_SeekError\n", iotd
->iotd_Req
.io_Offset
));
291 return TDERR_SeekError
;
294 buf
= iotd
->iotd_Req
.io_Data
;
295 size
= iotd
->iotd_Req
.io_Length
;
296 iotd
->iotd_Req
.io_Actual
= size
;
300 subsize
= Read(unit
->file
, buf
, size
);
303 iotd
->iotd_Req
.io_Actual
-= size
;
304 D(bug("fdsk_device/read: Read() returned 0. Returning IOERR_BADLENGTH\n"));
305 return IOERR_BADLENGTH
;
309 iotd
->iotd_Req
.io_Actual
-= size
;
310 D(bug("fdsk_device/read: Read() returned -1. Returning error number %d\n", error(IoErr())));
311 return error(IoErr());
318 buf
= iotd
->iotd_Req
.io_Data
;
319 D(bug("fdsk_device/read: returning 0. First 4 buffer bytes = [%c%c%c%c]\n", buf
[0], buf
[1], buf
[2], buf
[3]));
325 /****************************************************************************************/
327 static LONG
write(struct unit
*unit
, struct IOExtTD
*iotd
)
332 if(iotd
->iotd_SecLabel
)
335 if(Seek(unit
->file
, iotd
->iotd_Req
.io_Offset
, OFFSET_BEGINNING
) == -1)
336 return TDERR_SeekError
;
338 buf
= iotd
->iotd_Req
.io_Data
;
339 size
= iotd
->iotd_Req
.io_Length
;
340 iotd
->iotd_Req
.io_Actual
= size
;
344 subsize
= Write(unit
->file
, buf
, size
);
347 iotd
->iotd_Req
.io_Actual
-= size
;
348 return error(IoErr());
357 /****************************************************************************************/
358 void getgeometry(struct unit
*unit
, struct DriveGeometry
*dg
) {
359 struct FileInfoBlock fib
;
361 Examine(unit
->file
, &fib
);
362 dg
->dg_SectorSize
= 512;
364 dg
->dg_TrackSectors
= 63;
365 dg
->dg_TotalSectors
= fib
.fib_Size
/ dg
->dg_SectorSize
;
366 /* in case of links or block devices with emul_handler we get the wrong size */
367 if (dg
->dg_TotalSectors
== 0)
368 dg
->dg_TotalSectors
= dg
->dg_Heads
*dg
->dg_TrackSectors
*5004;
369 dg
->dg_Cylinders
= dg
->dg_TotalSectors
/ (dg
->dg_Heads
* dg
->dg_TrackSectors
);
370 dg
->dg_CylSectors
= dg
->dg_Heads
* dg
->dg_TrackSectors
;
371 dg
->dg_BufMemType
= MEMF_PUBLIC
;
372 dg
->dg_DeviceType
= DG_DIRECT_ACCESS
;
375 /****************************************************************************************/
377 AROS_UFH2(void, putchr
,
378 AROS_UFHA(UBYTE
, chr
, D0
),
379 AROS_UFHA(STRPTR
*, p
, A3
)
387 /****************************************************************************************/
389 AROS_UFH3(LONG
, unitentry
,
390 AROS_UFHA(STRPTR
, argstr
, A0
),
391 AROS_UFHA(ULONG
, arglen
, D0
),
392 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
396 UBYTE buf
[10 + sizeof(LONG
) * 8 * 301 / 1000 + 1];
400 struct IOExtTD
*iotd
;
404 D(bug("fdsk_device/unitentry: just started\n"));
406 me
= (struct Process
*)FindTask(NULL
);
408 WaitPort(&me
->pr_MsgPort
);
409 unit
= (struct unit
*)GetMsg(&me
->pr_MsgPort
);
410 unit
->port
.mp_SigBit
= AllocSignal(-1);
411 unit
->port
.mp_Flags
= PA_SIGNAL
;
413 /* disable DOS error requesters. save it the old pointer so we can put it
415 win
= me
->pr_WindowPtr
;
416 me
->pr_WindowPtr
= (APTR
) -1;
418 (void)RawDoFmt("FDSK:Unit%ld", &unit
->unitnum
, (VOID_FUNC
)putchr
, &ptr
);
420 D(bug("fdsk_device/unitentry: Trying to open \"%s\" ...\n", buf
));
422 unit
->file
= Open(buf
, MODE_OLDFILE
);
426 #warning FIXME: Next line will produce a segfault -- uninitialized variable iotd
427 iotd->iotd_Req.io_Error = error(IoErr());
429 D(bug("fdsk_device/unitentry: open failed ioerr = %d:-( Replying startup msg.\n", IoErr()));
431 ReplyMsg(&unit
->msg
);
435 /* enable requesters */
436 me
->pr_WindowPtr
= win
;
438 D(bug("fdsk_device/unitentry: open okay :-) Replying startup msg.\n"));
440 ReplyMsg(&unit
->msg
);
442 D(bug("fdsk_device/unitentry: Now entering main loop\n"));
446 while((iotd
= (struct IOExtTD
*)GetMsg(&unit
->port
)) != NULL
)
448 if(&iotd
->iotd_Req
.io_Message
== &unit
->msg
)
450 D(bug("fdsk_device/unitentry: Recevied EXIT message.\n"));
454 ReplyMsg(&unit
->msg
);
458 switch(iotd
->iotd_Req
.io_Command
)
461 D(bug("fdsk_device/unitentry: received CMD_READ.\n"));
462 err
= read(unit
, iotd
);
467 D(bug("fdsk_device/unitentry: received %s\n", (iotd
->iotd_Req
.io_Command
== CMD_WRITE
) ? "CMD_WRITE" : "TD_FORMAT"));
468 err
= write(unit
, iotd
);
473 iotd
->iotd_Req
.io_Actual
= 0;
476 getgeometry(unit
, (struct DriveGeometry
*)iotd
->iotd_Req
.io_Data
);
480 } /* switch(iotd->iotd_Req.io_Command) */
482 iotd
->iotd_Req
.io_Error
= err
;
483 ReplyMsg(&iotd
->iotd_Req
.io_Message
);
485 } /* while((iotd = (struct IOExtTD *)GetMsg(&unit->port)) != NULL) */
487 WaitPort(&unit
->port
);
493 /****************************************************************************************/