Fix IRQ name
[AROS.git] / workbench / devs / fdsk_device.c
blob81a9c07f7c57bcb75842e9d14ef54c01f26c6ffb
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
4 */
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"
21 #endif
23 #define DEBUG 0
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));
42 return TRUE;
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,
57 struct IOExtTD *iotd,
58 ULONG unitnum,
59 ULONG flags
62 static const struct TagItem tags[] =
64 { NP_Name , (IPTR)"File Disk Unit Process"},
65 { NP_Input , 0 },
66 { NP_Output , 0 },
67 { NP_Error , 0 },
68 { NP_CurrentDir , 0 },
69 { NP_Priority , 0 },
70 { NP_HomeDir , 0 },
71 { NP_CopyVars , 0 },
72 { NP_Entry , (IPTR)unitentry },
73 { TAG_END , 0 }
75 struct unit *unit;
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)
88 unit->usecount++;
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"));
97 return TRUE;
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);
104 if(unit != NULL)
106 D(bug("fdsk_device: in libopen func. Allocation of unit memory okay. Setting up unit and calling CreateNewProc ...\n"));
108 unit->usecount = 1;
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"));
136 if(unit->file)
138 AddTail((struct List *)&fdskbase->units, &unit->msg.mn_Node);
139 iotd->iotd_Req.io_Unit = (struct Unit *)unit;
140 /* Set returncode */
141 iotd->iotd_Req.io_Error = 0;
142 ReleaseSemaphore(&fdskbase->sigsem);
143 return TRUE;
144 }else
145 iotd->iotd_Req.io_Error = TDERR_NotSpecified;
146 }else
147 iotd->iotd_Req.io_Error = TDERR_NoMem;
148 FreeMem(unit, sizeof(struct unit));
149 }else
150 iotd->iotd_Req.io_Error = TDERR_NoMem;
152 ReleaseSemaphore(&fdskbase->sigsem);
154 return FALSE;
157 /****************************************************************************************/
159 static int GM_UNIQUENAME(Close)
161 LIBBASETYPEPTR fdskbase,
162 struct IOExtTD *iotd
165 struct unit *unit;
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);
181 return TRUE;
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)
196 AROS_LIBFUNC_INIT
198 switch(iotd->iotd_Req.io_Command)
200 case CMD_UPDATE:
201 case CMD_CLEAR:
202 case TD_MOTOR:
203 /* Ignore but don't fail */
204 iotd->iotd_Req.io_Error = 0;
205 break;
207 case CMD_READ:
208 case CMD_WRITE:
209 case TD_FORMAT:
210 case TD_CHANGENUM:
211 case TD_CHANGESTATE:
212 case TD_ADDCHANGEINT:
213 case TD_REMCHANGEINT:
214 case TD_GETGEOMETRY:
215 case TD_EJECT:
216 case TD_PROTSTATUS:
217 /* Forward to unit thread */
218 PutMsg(&((struct unit *)iotd->iotd_Req.io_Unit)->port,
219 &iotd->iotd_Req.io_Message);
220 /* Not done quick */
221 iotd->iotd_Req.io_Flags &= ~IOF_QUICK;
222 return;
224 default:
225 /* Not supported */
226 iotd->iotd_Req.io_Error = IOERR_NOCMD;
227 break;
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;
234 /* Finish message */
235 if(!(iotd->iotd_Req.io_Flags&IOF_QUICK))
236 ReplyMsg(&iotd->iotd_Req.io_Message);
238 AROS_LIBFUNC_EXIT
241 /****************************************************************************************/
243 AROS_LH1(LONG, abortio,
244 AROS_LHA(struct IOExtTD *, iotd, A1),
245 struct fdskbase *, fdskbase, 6, Fdsk)
247 AROS_LIBFUNC_INIT
248 return IOERR_NOCMD;
249 AROS_LIBFUNC_EXIT
252 /****************************************************************************************/
254 #define fdskbase unit->fdskbase
256 /****************************************************************************************/
258 static LONG error(LONG error)
260 switch(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;
269 case ERROR_NO_DISK:
270 return TDERR_DiskChanged;
272 default:
273 return TDERR_NotSpecified;
277 /****************************************************************************************/
279 static LONG read(struct unit *unit, struct IOExtTD *iotd)
281 STRPTR buf;
282 LONG size, subsize;
284 D(bug("fdsk_device/read: offset = %d size = %d\n", iotd->iotd_Req.io_Offset, iotd->iotd_Req.io_Length));
286 #if 0
287 if(iotd->iotd_SecLabel)
289 D(bug("fdsk_device/read: iotd->iotd_SecLabel is != NULL -> returning IOERR_NOCMD\n"));
290 return IOERR_NOCMD;
292 #endif
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;
304 while(size)
306 subsize = Read(unit->file, buf, size);
307 if(!subsize)
309 iotd->iotd_Req.io_Actual -= size;
310 D(bug("fdsk_device/read: Read() returned 0. Returning IOERR_BADLENGTH\n"));
311 return IOERR_BADLENGTH;
313 if(subsize == -1)
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());
319 buf += subsize;
320 size -= subsize;
323 #if DEBUG
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]));
326 #endif
328 return 0;
331 /****************************************************************************************/
333 static LONG write(struct unit *unit, struct IOExtTD *iotd)
335 STRPTR buf;
336 LONG size, subsize;
338 if(!unit->writable)
339 return TDERR_WriteProt;
340 #if 0
341 if(iotd->iotd_SecLabel)
342 return IOERR_NOCMD;
343 #endif
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;
351 while(size)
353 subsize = Write(unit->file, buf, size);
354 if(subsize == -1)
356 iotd->iotd_Req.io_Actual -= size;
357 return error(IoErr());
359 buf += subsize;
360 size -= subsize;
363 return 0;
366 /**************************************************************************/
368 static void addchangeint(struct unit *unit, struct IOExtTD *iotd) {
369 Forbid();
370 AddTail((struct List *)&unit->changeints, (struct Node *)iotd);
371 Permit();
374 /**************************************************************************/
376 static void remchangeint(struct unit *unit, struct IOExtTD *iotd) {
377 Forbid();
378 Remove((struct Node *)iotd);
379 Permit();
382 /**************************************************************************/
384 void getgeometry(struct unit *unit, struct DriveGeometry *dg) {
385 struct FileInfoBlock fib;
387 ExamineFH(unit->file, &fib);
388 dg->dg_SectorSize = 512;
389 dg->dg_Heads = 16;
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;
408 if (eject)
410 Close(unit->file);
411 unit->file = (BPTR)NULL;
413 else
415 unit->file = Open(unit->filename, MODE_OLDFILE);
416 if (unit->file == (BPTR) NULL)
417 return;
418 ExamineFH(unit->file, &fib);
419 unit->writable = !(fib.fib_Protection & FIBF_WRITE);
422 unit->changecount++;
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)
437 AROS_USERFUNC_INIT
438 *(*p)++ = chr;
439 AROS_USERFUNC_EXIT
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))
449 AROS_USERFUNC_INIT
451 UBYTE buf[10 + sizeof(LONG) * 8 * 301 / 1000 + 1];
452 STRPTR ptr = buf;
453 struct Process *me;
454 LONG err = 0L;
455 struct IOExtTD *iotd;
456 struct unit *unit;
457 APTR win;
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
470 * back later */
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);
480 if(!unit->file)
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);
489 return 0;
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"));
504 for(;;)
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"));
512 Close(unit->file);
513 Forbid();
514 ReplyMsg(&unit->msg);
515 return 0;
518 switch(iotd->iotd_Req.io_Command)
520 case CMD_READ:
521 D(bug("fdsk_device/unitentry: received CMD_READ.\n"));
522 err = read(unit, iotd);
523 break;
525 case CMD_WRITE:
526 case TD_FORMAT:
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);
529 break;
530 case TD_CHANGENUM:
531 err = 0;
532 iotd->iotd_Req.io_Actual = unit->changecount;
533 break;
534 case TD_CHANGESTATE:
535 err = 0;
536 iotd->iotd_Req.io_Actual = unit->file == (BPTR)NULL;
537 break;
538 case TD_ADDCHANGEINT:
539 addchangeint(unit, iotd);
540 err = 0;
541 break;
542 case TD_REMCHANGEINT:
543 remchangeint(unit, iotd);
544 err = 0;
545 break;
546 case TD_GETGEOMETRY:
547 getgeometry(unit, (struct DriveGeometry *)iotd->iotd_Req.io_Data);
548 err = 0;
549 break;
550 case TD_EJECT:
551 eject(unit, iotd->iotd_Req.io_Length);
552 err = 0;
553 break;
554 case TD_PROTSTATUS:
555 iotd->iotd_Req.io_Actual = !unit->writable;
556 err = 0;
557 break;
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);
568 } /* for(;;) */
569 AROS_USERFUNC_EXIT
572 /****************************************************************************************/