Fixes to pciusb as found and proposed by Georg Steger (thanks!).
[cake.git] / workbench / devs / fdsk_device.c
blob6c4348dd269cbfcad48b8a4f4b335aa7f150ef06
1 /*
2 Copyright © 1995-2006, 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), MEMF_PUBLIC);
103 if(unit != NULL)
105 D(bug("fdsk_device: in libopen func. Allocation of unit memory okay. Setting up unit and calling CreateNewProc ...\n"));
107 unit->usecount = 1;
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"));
134 if(unit->file)
136 AddTail((struct List *)&fdskbase->units, &unit->msg.mn_Node);
137 iotd->iotd_Req.io_Unit = (struct Unit *)unit;
138 /* Set returncode */
139 iotd->iotd_Req.io_Error = 0;
140 ReleaseSemaphore(&fdskbase->sigsem);
141 return TRUE;
142 }else
143 iotd->iotd_Req.io_Error = TDERR_NotSpecified;
144 }else
145 iotd->iotd_Req.io_Error = TDERR_NoMem;
146 FreeMem(unit, sizeof(struct unit));
147 }else
148 iotd->iotd_Req.io_Error = TDERR_NoMem;
150 ReleaseSemaphore(&fdskbase->sigsem);
152 return FALSE;
155 /****************************************************************************************/
157 static int GM_UNIQUENAME(Close)
159 LIBBASETYPEPTR fdskbase,
160 struct IOExtTD *iotd
163 struct unit *unit;
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);
179 return TRUE;
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)
194 AROS_LIBFUNC_INIT
196 switch(iotd->iotd_Req.io_Command)
198 case CMD_UPDATE:
199 case CMD_CLEAR:
200 case TD_MOTOR:
201 /* Ignore but don't fail */
202 iotd->iotd_Req.io_Error = 0;
203 break;
205 case CMD_READ:
206 case CMD_WRITE:
207 case TD_FORMAT:
208 case TD_CHANGENUM:
209 case TD_CHANGESTATE:
210 case TD_GETGEOMETRY:
211 /* Forward to unit thread */
212 PutMsg(&((struct unit *)iotd->iotd_Req.io_Unit)->port,
213 &iotd->iotd_Req.io_Message);
214 /* Not done quick */
215 iotd->iotd_Req.io_Flags &= ~IOF_QUICK;
216 return;
218 default:
219 /* Not supported */
220 iotd->iotd_Req.io_Error = IOERR_NOCMD;
221 break;
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;
228 /* Finish message */
229 if(!(iotd->iotd_Req.io_Flags&IOF_QUICK))
230 ReplyMsg(&iotd->iotd_Req.io_Message);
232 AROS_LIBFUNC_EXIT
235 /****************************************************************************************/
237 AROS_LH1(LONG, abortio,
238 AROS_LHA(struct IOExtTD *, iotd, A1),
239 struct fdskbase *, fdskbase, 6, Fdsk)
241 AROS_LIBFUNC_INIT
242 return IOERR_NOCMD;
243 AROS_LIBFUNC_EXIT
246 /****************************************************************************************/
248 #define fdskbase unit->fdskbase
250 /****************************************************************************************/
252 static LONG error(LONG error)
254 switch(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;
263 case ERROR_NO_DISK:
264 return TDERR_DiskChanged;
266 default:
267 return TDERR_NotSpecified;
271 /****************************************************************************************/
273 static LONG read(struct unit *unit, struct IOExtTD *iotd)
275 STRPTR buf;
276 LONG size, subsize;
278 D(bug("fdsk_device/read: offset = %d size = %d\n", iotd->iotd_Req.io_Offset, iotd->iotd_Req.io_Length));
280 #if 0
281 if(iotd->iotd_SecLabel)
283 D(bug("fdsk_device/read: iotd->iotd_SecLabel is != NULL -> returning IOERR_NOCMD\n"));
284 return IOERR_NOCMD;
286 #endif
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;
298 while(size)
300 subsize = Read(unit->file, buf, size);
301 if(!subsize)
303 iotd->iotd_Req.io_Actual -= size;
304 D(bug("fdsk_device/read: Read() returned 0. Returning IOERR_BADLENGTH\n"));
305 return IOERR_BADLENGTH;
307 if(subsize == -1)
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());
313 buf += subsize;
314 size -= subsize;
317 #if DEBUG
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]));
320 #endif
322 return 0;
325 /****************************************************************************************/
327 static LONG write(struct unit *unit, struct IOExtTD *iotd)
329 STRPTR buf;
330 LONG size, subsize;
331 #if 0
332 if(iotd->iotd_SecLabel)
333 return IOERR_NOCMD;
334 #endif
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;
342 while(size)
344 subsize = Write(unit->file, buf, size);
345 if(subsize == -1)
347 iotd->iotd_Req.io_Actual -= size;
348 return error(IoErr());
350 buf += subsize;
351 size -= subsize;
354 return 0;
357 /****************************************************************************************/
358 void getgeometry(struct unit *unit, struct DriveGeometry *dg) {
359 struct FileInfoBlock fib;
361 Examine(unit->file, &fib);
362 dg->dg_SectorSize = 512;
363 dg->dg_Heads = 16;
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;
373 dg->dg_Flags = 0;
375 /****************************************************************************************/
377 AROS_UFH2(void, putchr,
378 AROS_UFHA(UBYTE, chr, D0),
379 AROS_UFHA(STRPTR *, p, A3)
382 AROS_USERFUNC_INIT
383 *(*p)++ = chr;
384 AROS_USERFUNC_EXIT
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))
394 AROS_USERFUNC_INIT
396 UBYTE buf[10 + sizeof(LONG) * 8 * 301 / 1000 + 1];
397 STRPTR ptr = buf;
398 struct Process *me;
399 LONG err = 0L;
400 struct IOExtTD *iotd;
401 struct unit *unit;
402 APTR win;
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
414 * back later */
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);
423 if(!unit->file)
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);
432 return 0;
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"));
444 for(;;)
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"));
452 Close(unit->file);
453 Forbid();
454 ReplyMsg(&unit->msg);
455 return 0;
458 switch(iotd->iotd_Req.io_Command)
460 case CMD_READ:
461 D(bug("fdsk_device/unitentry: received CMD_READ.\n"));
462 err = read(unit, iotd);
463 break;
465 case CMD_WRITE:
466 case TD_FORMAT:
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);
469 break;
470 case TD_CHANGENUM:
471 case TD_CHANGESTATE:
472 err = 0;
473 iotd->iotd_Req.io_Actual = 0;
474 break;
475 case TD_GETGEOMETRY:
476 getgeometry(unit, (struct DriveGeometry *)iotd->iotd_Req.io_Data);
477 err = 0;
478 break;
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);
489 } /* for(;;) */
490 AROS_USERFUNC_EXIT
493 /****************************************************************************************/