prism2.device: Compiler delint
[AROS.git] / workbench / devs / fdsk_device.c
blobf86c6d6f55e70de1dc4a3038cb6f715fedf552b5
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
4 */
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"
23 #endif
25 #define DEBUG 0
26 #include <aros/debug.h>
28 #include LC_LIBDEFS_FILE
30 #define NEWSTYLE_DEVICE 1
32 #if NEWSTYLE_DEVICE
33 static const UWORD SupportedCommands[] =
35 CMD_UPDATE,
36 CMD_CLEAR,
37 TD_MOTOR,
38 CMD_READ,
39 CMD_WRITE,
40 TD_FORMAT,
41 TD_CHANGENUM,
42 TD_CHANGESTATE,
43 TD_ADDCHANGEINT,
44 TD_REMCHANGEINT,
45 TD_GETGEOMETRY,
46 TD_EJECT,
47 TD_PROTSTATUS,
48 ETD_READ,
49 ETD_WRITE,
50 ETD_UPDATE,
51 ETD_CLEAR,
52 ETD_MOTOR,
53 ETD_FORMAT,
54 TD_GETDRIVETYPE,
55 NSCMD_DEVICEQUERY,
58 #endif
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));
74 return TRUE;
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,
89 struct IOExtTD *iotd,
90 ULONG unitnum,
91 ULONG flags
94 static const struct TagItem tags[] =
96 { NP_Name , (IPTR)"File Disk Unit Process"},
97 { NP_Input , 0 },
98 { NP_Output , 0 },
99 { NP_Error , 0 },
100 { NP_CurrentDir , 0 },
101 { NP_Priority , 0 },
102 { NP_HomeDir , 0 },
103 { NP_CopyVars , 0 },
104 { NP_Entry , (IPTR)unitentry },
105 { TAG_END , 0 }
107 struct unit *unit;
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)
120 unit->usecount++;
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));
129 return TRUE;
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);
136 if(unit != NULL)
138 D(bug("[FDSK%02ld] in libopen func. Allocation of unit memory okay. Setting up unit and calling CreateNewProc ...\n", unitnum));
140 unit->usecount = 1;
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 if(unit->file)
170 AddTail((struct List *)&fdskbase->units, &unit->msg.mn_Node);
171 iotd->iotd_Req.io_Unit = (struct Unit *)unit;
172 /* Set returncode */
173 iotd->iotd_Req.io_Error = 0;
174 ReleaseSemaphore(&fdskbase->sigsem);
175 return TRUE;
176 }else
177 iotd->iotd_Req.io_Error = TDERR_NotSpecified;
178 }else
179 iotd->iotd_Req.io_Error = TDERR_NoMem;
180 FreeMem(unit, sizeof(struct unit));
181 }else
182 iotd->iotd_Req.io_Error = TDERR_NoMem;
184 ReleaseSemaphore(&fdskbase->sigsem);
186 return FALSE;
189 /****************************************************************************************/
191 static int GM_UNIQUENAME(Close)
193 LIBBASETYPEPTR fdskbase,
194 struct IOExtTD *iotd
197 struct unit *unit;
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);
213 return TRUE;
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)
228 AROS_LIBFUNC_INIT
230 switch(iotd->iotd_Req.io_Command)
232 #if NEWSTYLE_DEVICE
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;
239 else
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;
254 break;
255 case TD_GETDRIVETYPE:
256 iotd->iotd_Req.io_Actual = DRIVE_NEWSTYLE;
257 break;
258 #endif
259 case ETD_UPDATE:
260 case ETD_CLEAR:
261 case ETD_MOTOR:
262 case CMD_UPDATE:
263 case CMD_CLEAR:
264 case TD_MOTOR:
265 /* Ignore but don't fail */
266 iotd->iotd_Req.io_Error = 0;
267 break;
269 case ETD_READ:
270 case ETD_WRITE:
271 case ETD_FORMAT:
272 case CMD_READ:
273 case CMD_WRITE:
274 case TD_FORMAT:
275 case TD_CHANGENUM:
276 case TD_CHANGESTATE:
277 case TD_ADDCHANGEINT:
278 case TD_REMCHANGEINT:
279 case TD_GETGEOMETRY:
280 case TD_EJECT:
281 case TD_PROTSTATUS:
282 /* Forward to unit thread */
283 PutMsg(&((struct unit *)iotd->iotd_Req.io_Unit)->port,
284 &iotd->iotd_Req.io_Message);
285 /* Not done quick */
286 iotd->iotd_Req.io_Flags &= ~IOF_QUICK;
287 return;
289 default:
290 /* Not supported */
291 iotd->iotd_Req.io_Error = IOERR_NOCMD;
292 break;
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;
299 /* Finish message */
300 if(!(iotd->iotd_Req.io_Flags&IOF_QUICK))
301 ReplyMsg(&iotd->iotd_Req.io_Message);
303 AROS_LIBFUNC_EXIT
306 /****************************************************************************************/
308 AROS_LH1(LONG, abortio,
309 AROS_LHA(struct IOExtTD *, iotd, A1),
310 struct fdskbase *, fdskbase, 6, Fdsk)
312 AROS_LIBFUNC_INIT
313 return IOERR_NOCMD;
314 AROS_LIBFUNC_EXIT
317 /****************************************************************************************/
319 #define fdskbase unit->fdskbase
321 /****************************************************************************************/
323 static LONG error(LONG error)
325 switch(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;
334 case ERROR_NO_DISK:
335 return TDERR_DiskChanged;
337 default:
338 return TDERR_NotSpecified;
342 /****************************************************************************************/
344 static LONG read(struct unit *unit, struct IOExtTD *iotd)
346 STRPTR buf;
347 LONG size, subsize;
349 D(bug("[FDSK%02ld] read32: offset = %08x size = %08x\n", unit->unitnum, iotd->iotd_Req.io_Offset, iotd->iotd_Req.io_Length));
351 #if 0
352 if(iotd->iotd_SecLabel)
354 D(bug("[FDSK%02ld] read32: iotd->iotd_SecLabel is != NULL -> returning IOERR_NOCMD\n", unit->unitnum));
355 return IOERR_NOCMD;
357 #endif
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;
369 while(size)
371 subsize = Read(unit->file, buf, size);
372 if(!subsize)
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;
378 if(subsize == -1)
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());
384 buf += subsize;
385 size -= subsize;
388 #if DEBUG
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]));
391 #endif
393 return 0;
396 /****************************************************************************************/
398 static LONG write(struct unit *unit, struct IOExtTD *iotd)
400 STRPTR buf;
401 LONG size, subsize;
403 D(bug("[FDSK%02ld] write32: offset = %08x size = %08x\n", unit->unitnum, iotd->iotd_Req.io_Offset, iotd->iotd_Req.io_Length));
405 if(!unit->writable)
406 return TDERR_WriteProt;
407 #if 0
408 if(iotd->iotd_SecLabel)
409 return IOERR_NOCMD;
410 #endif
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;
418 while(size)
420 subsize = Write(unit->file, buf, size);
421 if(subsize == -1)
423 iotd->iotd_Req.io_Actual -= size;
424 return error(IoErr());
426 buf += subsize;
427 size -= subsize;
430 return 0;
433 /**************************************************************************/
435 static void addchangeint(struct unit *unit, struct IOExtTD *iotd) {
436 Forbid();
437 AddTail((struct List *)&unit->changeints, (struct Node *)iotd);
438 Permit();
441 /**************************************************************************/
443 static void remchangeint(struct unit *unit, struct IOExtTD *iotd) {
444 Forbid();
445 Remove((struct Node *)iotd);
446 Permit();
449 /**************************************************************************/
451 void getgeometry(struct unit *unit, struct DriveGeometry *dg) {
452 struct FileInfoBlock fib;
454 ExamineFH(unit->file, &fib);
455 dg->dg_SectorSize = 512;
456 dg->dg_Heads = 16;
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;
475 if (eject)
477 Close(unit->file);
478 unit->file = (BPTR)NULL;
480 else
482 unit->file = Open(unit->filename, MODE_OLDFILE);
483 if (unit->file == BNULL)
484 return;
485 ExamineFH(unit->file, &fib);
486 unit->writable = !(fib.fib_Protection & FIBF_WRITE);
489 unit->changecount++;
491 ForeachNode(&unit->changeints, iotd)
493 Cause((struct Interrupt *)iotd->iotd_Req.io_Data);
495 return;
498 /**************************************************************************/
500 AROS_UFH2(void, putchr,
501 AROS_UFHA(UBYTE, chr, D0),
502 AROS_UFHA(STRPTR *, p, A3)
505 AROS_USERFUNC_INIT
506 *(*p)++ = chr;
507 AROS_USERFUNC_EXIT
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))
517 AROS_USERFUNC_INIT
519 UBYTE buf[10 + sizeof(LONG) * 8 * 301 / 1000 + 1];
520 STRPTR ptr = buf;
521 struct Process *me;
522 LONG err = 0L;
523 struct IOExtTD *iotd;
524 struct unit *unit;
525 APTR win;
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
536 * back later */
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);
546 if(!unit->file)
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);
555 return 0;
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));
570 for(;;)
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));
578 Close(unit->file);
579 Forbid();
580 ReplyMsg(&unit->msg);
581 return 0;
583 switch(iotd->iotd_Req.io_Command)
585 case ETD_READ:
586 case CMD_READ:
587 D(bug("[FDSK%02ld] received CMD_READ.\n", unit->unitnum));
588 err = read(unit, iotd);
589 break;
590 case ETD_WRITE:
591 case CMD_WRITE:
592 case TD_FORMAT:
593 case ETD_FORMAT:
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);
598 break;
599 case TD_CHANGENUM:
600 err = 0;
601 iotd->iotd_Req.io_Actual = unit->changecount;
602 break;
603 case TD_CHANGESTATE:
604 err = 0;
605 iotd->iotd_Req.io_Actual = unit->file == (BPTR)NULL;
606 break;
607 case TD_ADDCHANGEINT:
608 addchangeint(unit, iotd);
609 err = 0;
610 break;
611 case TD_REMCHANGEINT:
612 remchangeint(unit, iotd);
613 err = 0;
614 break;
615 case TD_GETGEOMETRY:
616 getgeometry(unit, (struct DriveGeometry *)iotd->iotd_Req.io_Data);
617 err = 0;
618 break;
619 case TD_EJECT:
620 eject(unit, iotd->iotd_Req.io_Length);
621 err = 0;
622 break;
623 case TD_PROTSTATUS:
624 iotd->iotd_Req.io_Actual = !unit->writable;
625 err = 0;
626 break;
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);
633 } /* for(;;) */
634 AROS_USERFUNC_EXIT
637 /****************************************************************************************/