Removed some unnecessary null-pointer checks.
[AROS.git] / rom / filesys / afs / os_aros_support.c
blob3100ee5f3803b14712d60dd92a1ec17f30993cee
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #ifndef DEBUG
7 #define DEBUG 0
8 #endif
10 #include <exec/types.h>
11 #include <devices/input.h>
12 #include <devices/newstyle.h>
13 #include <devices/trackdisk.h>
14 #include <exec/errors.h>
15 #include <exec/io.h>
16 #include <hardware/custom.h>
17 #include <hardware/intbits.h>
18 #include <intuition/intuition.h>
20 #include "os.h"
21 #include "afsblocks.h"
22 #include "error.h"
23 #include "extstrings.h"
24 #include "volumes.h"
25 #include "baseredef.h"
28 * The deadlock bug caused by calling LockDosList() when adding avolume node
29 * has now been fixed, but a deadlock still occurs when trying to mount an
30 * AFS disk image with fdsk.device if the image file is on an AFS volume.
31 * This is because of there only being one filesystem process that is shared
32 * between all AFS devices.
35 // pushes an IECLASS event in the input stream.
36 static void SendEvent(struct AFSBase *afsbase, LONG event) {
37 struct IOStdReq *InputRequest;
38 struct MsgPort *InputPort;
39 struct InputEvent *ie;
40 if ((InputPort = (struct MsgPort*)CreateMsgPort())) {
42 if ((InputRequest = (struct IOStdReq*)CreateIORequest(InputPort, sizeof(struct IOStdReq)))) {
44 if (!OpenDevice("input.device", 0, (struct IORequest*)InputRequest, 0)) {
46 if ((ie = AllocVec(sizeof(struct InputEvent), MEMF_PUBLIC|MEMF_CLEAR))) {
47 ie->ie_Class = event;
48 InputRequest->io_Command = IND_WRITEEVENT;
49 InputRequest->io_Data = ie;
50 InputRequest->io_Length = sizeof(struct InputEvent);
52 DoIO((struct IORequest*)InputRequest);
54 FreeVec(ie);
56 CloseDevice((struct IORequest*)InputRequest);
58 DeleteIORequest ((APTR)InputRequest);
60 DeleteMsgPort (InputPort);
64 /************************** DOS ******************************************/
65 /*******************************************
66 Name : initDeviceList
67 Descr.: initializes a devicelist structure
68 Input : devicelist - devicelist structure to initialize
69 rootblock - cacheblock of the rootblock
70 Output: DOSTRUE for success; DOSFALSE otherwise
71 ********************************************/
72 LONG initDeviceList
74 struct AFSBase *afsbase,
75 struct Volume *volume,
76 struct BlockCache *rootblock
79 STRPTR name;
80 BSTR newname;
81 UBYTE i;
83 name=(char *)rootblock->buffer+(BLK_DISKNAME_START(volume)*4);
84 volume->devicelist.dl_Next = 0;
85 volume->devicelist.dl_Type = DLT_VOLUME;
86 volume->devicelist.dl_Lock = 0;
87 volume->devicelist.dl_VolumeDate.ds_Days =
88 AROS_BE2LONG(rootblock->buffer[BLK_ROOT_DAYS(volume)]);
89 volume->devicelist.dl_VolumeDate.ds_Minute =
90 AROS_BE2LONG(rootblock->buffer[BLK_ROOT_MINS(volume)]);
91 volume->devicelist.dl_VolumeDate.ds_Tick =
92 AROS_BE2LONG(rootblock->buffer[BLK_ROOT_TICKS(volume)]);
93 volume->devicelist.dl_LockList = 0;
94 volume->devicelist.dl_DiskType = volume->dostype;
95 if (volume->devicelist.dl_Name != BNULL)
97 newname = volume->devicelist.dl_Name;
99 else
101 newname = MKBADDR(AllocVec(32,MEMF_CLEAR | MEMF_PUBLIC));
102 if (newname == BNULL)
103 return DOSFALSE;
105 for (i=0; i<name[0]; i++)
106 AROS_BSTR_putchar(newname, i, name[i+1]);
107 AROS_BSTR_setstrlen(newname, name[0]);
108 volume->devicelist.dl_Name = newname;
109 return DOSTRUE;
112 /*******************************************
113 Name : attemptAddDosVolume
114 Descr.: adds a new volume to dos
115 Input : volume - volume to add
116 Output: DOSTRUE for success; DOSFALSE otherwise
117 ********************************************/
118 LONG attemptAddDosVolume(struct AFSBase *afsbase, struct Volume *volume) {
119 struct DosList *doslist;
120 struct DosList *dl=NULL;
121 char string[32];
122 BSTR bname;
123 UBYTE i;
125 if (volume->volumenode) {
126 D(bug("[afs 0x%08lX] VolumeNode is already present!\n", volume));
127 return DOSTRUE;
129 bname = volume->devicelist.dl_Name;
130 for (i=0; i<AROS_BSTR_strlen(bname); i++)
131 string[i] = AROS_BSTR_getchar(bname,i);
132 string[AROS_BSTR_strlen(bname)] = 0;
133 D(bug("[afs 0x%08lX] Processing inserted volume %s\n", volume, string));
134 /* is the volume already in the list? */
135 doslist = AttemptLockDosList(LDF_WRITE | LDF_VOLUMES);
136 if (doslist != NULL)
138 dl = FindDosEntry(doslist,string,LDF_VOLUMES);
139 UnLockDosList(LDF_WRITE | LDF_VOLUMES);
141 else
142 return TRUE;
144 /* if not create a new doslist */
145 if (dl == NULL)
147 D(bug("[afs 0x%08lX] Creating new VolumeNode\n", volume));
148 doslist = MakeDosEntry(string,DLT_VOLUME);
149 if (doslist == NULL)
150 return DOSFALSE;
151 doslist->dol_Task = &((struct Process *)FindTask(NULL))->pr_MsgPort;
152 doslist->dol_misc.dol_volume.dol_VolumeDate.ds_Days =
153 volume->devicelist.dl_VolumeDate.ds_Days;
154 doslist->dol_misc.dol_volume.dol_VolumeDate.ds_Minute =
155 volume->devicelist.dl_VolumeDate.ds_Minute;
156 doslist->dol_misc.dol_volume.dol_VolumeDate.ds_Tick =
157 volume->devicelist.dl_VolumeDate.ds_Tick;
158 AddDosEntry(doslist);
159 /* if we re-use "volume" clear locklist */
160 volume->locklist = NULL;
161 dl = doslist;
163 volume->volumenode = dl;
164 SendEvent(afsbase, IECLASS_DISKINSERTED);
165 return DOSTRUE;
168 /*******************************************
169 Name : remDosVolume
170 Descr.: removes a volume added by addDosVolume
171 or if there are some locks active
172 set dol_LockList
173 Input : volume - volume to remove
174 Output: -
175 ********************************************/
176 void remDosVolume(struct AFSBase *afsbase, struct Volume *volume) {
177 struct DosList *dl;
179 dl = volume->volumenode;
180 if (dl) {
181 if (volume->locklist != NULL)
183 D(bug("[afs 0x%08lX] VolumeNode in use, keeping as offline\n", volume));
184 dl->dol_misc.dol_volume.dol_LockList = MKBADDR(volume->locklist);
186 else
188 D(bug("[afs 0x%08lX] Removing VolumeNode\n", volume));
189 remDosNode(afsbase, dl);
191 volume->volumenode = NULL;
195 /*******************************************
196 Name : remDosNode
197 Descr.: removes a DOS volume node
198 Input : dl - volume to remove
199 Output: -
200 ********************************************/
201 void remDosNode(struct AFSBase *afsbase, struct DosList *dl)
203 RemDosEntry(dl);
204 FreeDosEntry(dl);
205 SendEvent(afsbase, IECLASS_DISKREMOVED);
208 LONG osMediumInit
209 (struct AFSBase *afsbase, struct Volume *volume, struct BlockCache *block)
211 if (!initDeviceList(afsbase, volume, block))
212 return ERROR_NO_FREE_STORE;
213 if (!attemptAddDosVolume(afsbase, volume))
215 showError(afsbase, ERR_DOSENTRY);
216 remDosVolume(afsbase, volume);
217 return ERROR_UNKNOWN;
219 return 0;
222 void osMediumFree(struct AFSBase *afsbase, struct Volume *volume, LONG all) {
223 remDosVolume(afsbase, volume);
224 if (all)
225 FreeVec(BADDR(volume->devicelist.dl_Name));
228 /************************** I/O ******************************************/
229 struct IOExtTD *openDevice
231 struct AFSBase *afsbase,
232 struct MsgPort *mp,
233 STRPTR device,
234 ULONG unit,
235 ULONG flags
238 struct IOExtTD *ioreq;
240 ioreq = (struct IOExtTD *)CreateIORequest(mp, sizeof(struct IOExtTD));
241 if (ioreq != NULL)
243 if (OpenDevice(device, unit, (struct IORequest *)ioreq, flags) == 0)
245 return ioreq;
247 else
248 showError(afsbase, ERR_DEVICE, device);
249 DeleteIORequest((struct IORequest *)ioreq);
251 return NULL;
254 void closeDevice(struct AFSBase *afsbase, struct IOExtTD *ioreq) {
255 if (ioreq->iotd_Req.io_Device != NULL)
256 CloseDevice((struct IORequest *)&ioreq->iotd_Req);
257 DeleteIORequest((APTR)ioreq);
260 LONG getGeometry
261 (struct AFSBase *afsbase, struct IOHandle *ioh, struct DriveGeometry *dg)
263 ioh->ioreq->iotd_Req.io_Command = TD_GETGEOMETRY;
264 ioh->ioreq->iotd_Req.io_Data = dg;
265 ioh->ioreq->iotd_Req.io_Length = sizeof(struct DriveGeometry);
266 return DoIO((struct IORequest *)&ioh->ioreq->iotd_Req);
269 AROS_INTP(changeIntCode);
271 LONG addChangeInt(struct AFSBase *afsbase, struct IOHandle *ioh) {
273 ioh->mc_int.is_Code = (VOID_FUNC)changeIntCode;
274 ioh->mc_int.is_Data = ioh;
275 ioh->iochangeint->iotd_Req.io_Command = TD_ADDCHANGEINT;
276 ioh->iochangeint->iotd_Req.io_Flags = 0;
277 ioh->iochangeint->iotd_Req.io_Length = sizeof(struct Interrupt);
278 ioh->iochangeint->iotd_Req.io_Data = &ioh->mc_int;
279 ioh->iochangeint->iotd_Req.io_Error = 0;
280 SendIO((struct IORequest *)&ioh->iochangeint->iotd_Req);
281 return ioh->iochangeint->iotd_Req.io_Error;
284 void remChangeInt(struct AFSBase *afsbase, struct IOHandle *ioh) {
286 if (
287 (ioh->iochangeint != NULL) &&
288 (ioh->iochangeint->iotd_Req.io_Error == 0)
291 ioh->iochangeint->iotd_Req.io_Command = TD_REMCHANGEINT;
292 DoIO((struct IORequest *)&ioh->iochangeint->iotd_Req);
296 void checkAddChangeInt(struct AFSBase *afsbase, struct IOHandle *ioh) {
297 struct DriveGeometry dg;
299 if (!getGeometry(afsbase, ioh, &dg))
301 if (dg.dg_Flags & DGF_REMOVABLE)
303 ioh->iochangeint = openDevice
304 (afsbase, ioh->mp, ioh->blockdevice, ioh->unit, ioh->flags);
305 if (ioh->iochangeint != NULL)
307 addChangeInt(afsbase, ioh);
310 ioh->sectorsize = dg.dg_SectorSize;
314 UBYTE diskPresent(struct AFSBase *afsbase, struct IOHandle *ioh) {
316 ioh->ioreq->iotd_Req.io_Command = TD_CHANGESTATE;
317 DoIO((struct IORequest *)&ioh->ioreq->iotd_Req);
318 return ioh->ioreq->iotd_Req.io_Actual == 0;
321 BOOL diskWritable(struct AFSBase *afsbase, struct IOHandle *ioh)
323 ioh->ioreq->iotd_Req.io_Command = TD_PROTSTATUS;
324 DoIO((struct IORequest *)&ioh->ioreq->iotd_Req);
325 return ioh->ioreq->iotd_Req.io_Actual == 0;
328 ULONG sectorSize(struct AFSBase *afsbase, struct IOHandle *ioh)
330 return ioh->sectorsize;
333 struct IOHandle *openBlockDevice(struct AFSBase *afsbase, struct IOHandle *ioh)
336 ioh->mp = CreateMsgPort();
337 if (ioh->mp != NULL)
339 ioh->ioreq = openDevice(afsbase, ioh->mp, ioh->blockdevice, ioh->unit, ioh->flags);
340 if (ioh->ioreq != NULL)
342 ioh->cmdread = CMD_READ;
343 ioh->cmdwrite = CMD_WRITE;
344 ioh->cmdseek = TD_SEEK;
345 ioh->cmdformat = TD_FORMAT;
346 ioh->afsbase = afsbase;
347 if (diskPresent(afsbase, ioh))
348 ioh->ioflags |= IOHF_DISK_IN;
349 checkAddChangeInt(afsbase, ioh);
350 return ioh;
352 DeleteMsgPort(ioh->mp);
354 return NULL;
357 void closeBlockDevice(struct AFSBase *afsbase, struct IOHandle *ioh) {
359 remChangeInt(afsbase, ioh);
360 if (ioh->iochangeint != NULL)
361 closeDevice(afsbase, ioh->iochangeint);
362 if (ioh->ioreq != NULL)
363 closeDevice(afsbase, ioh->ioreq);
364 if (ioh->mp != NULL)
365 DeleteMsgPort(ioh->mp);
368 void motorOff(struct AFSBase *afsbase, struct IOHandle *ioh) {
370 ioh->ioreq->iotd_Req.io_Command = TD_MOTOR;
371 ioh->ioreq->iotd_Req.io_Length = 0;
372 DoIO((struct IORequest *)&ioh->ioreq->iotd_Req);
375 void checkDeviceFlags(struct AFSBase *afsbase) {
376 struct Volume *volume;
377 struct IOHandle *ioh;
379 volume = (struct Volume *)afsbase->device_list.lh_Head;
380 while (volume->ln.ln_Succ != NULL)
382 ioh = &volume->ioh;
383 if ((ioh->ioflags & IOHF_MEDIA_CHANGE) && (!volume->inhibitcounter))
385 D(bug("[afs 0x%08lX] Media change signalled\n", volume));
386 if (diskPresent(afsbase, ioh))
388 if (!volume->inhibitcounter)
390 D(bug("[afs 0x%08lX] Media inserted\n", volume));
391 newMedium(afsbase, volume);
393 ioh->ioflags |= IOHF_DISK_IN;
395 else
397 if (!volume->inhibitcounter)
399 flush(afsbase, volume);
400 remDosVolume(afsbase, volume);
402 ioh->ioflags &= ~IOHF_DISK_IN;
404 ioh->ioflags &= ~IOHF_MEDIA_CHANGE;
406 volume = (struct Volume *)volume->ln.ln_Succ;
410 void check64BitSupport(struct AFSBase *afsbase, struct Volume *volume) {
411 struct NSDeviceQueryResult nsdq;
412 UWORD *cmdcheck;
414 if (
416 (volume->startblock+(volume->countblocks))* /* last block */
417 (volume->SizeBlock*4/512) /* 1 portion (block) equals 512 (bytes) */
418 )>8388608)
420 nsdq.SizeAvailable = 0;
421 nsdq.DevQueryFormat = 0;
422 volume->ioh.ioreq->iotd_Req.io_Command = NSCMD_DEVICEQUERY;
423 volume->ioh.ioreq->iotd_Req.io_Data = &nsdq;
424 volume->ioh.ioreq->iotd_Req.io_Length = sizeof(struct NSDeviceQueryResult);
425 if (DoIO((struct IORequest *)volume->ioh.ioreq) == IOERR_NOCMD)
427 D(bug("[afs] initVolume-NSD: device doesn't understand NSD-Query\n"));
429 else
431 if (
432 (volume->ioh.ioreq->iotd_Req.io_Actual > sizeof(struct NSDeviceQueryResult)) ||
433 (volume->ioh.ioreq->iotd_Req.io_Actual == 0) ||
434 (volume->ioh.ioreq->iotd_Req.io_Actual != nsdq.SizeAvailable)
437 D(bug("[afs] initVolume-NSD: WARNING wrong io_Actual using NSD\n"));
439 else
441 D(bug("[afs] initVolume-NSD: using NSD commands\n"));
442 if (nsdq.DeviceType != NSDEVTYPE_TRACKDISK)
443 D(bug("[afs] initVolume-NSD: WARNING no trackdisk type\n"));
444 for (cmdcheck=nsdq.SupportedCommands; *cmdcheck; cmdcheck++)
446 if (*cmdcheck == NSCMD_TD_READ64)
447 volume->ioh.cmdread = NSCMD_TD_READ64;
448 if (*cmdcheck == NSCMD_TD_WRITE64);
449 volume->ioh.cmdwrite = NSCMD_TD_WRITE64;
450 if (*cmdcheck == NSCMD_TD_SEEK64)
451 volume->ioh.cmdseek = NSCMD_TD_SEEK64;
452 if (*cmdcheck == NSCMD_TD_FORMAT64)
453 volume->ioh.cmdformat = NSCMD_TD_FORMAT64;
455 if (
456 (volume->ioh.cmdread != NSCMD_TD_READ64) ||
457 (volume->ioh.cmdwrite != NSCMD_TD_WRITE64)
459 D(bug("[afs] initVolume-NSD: WARNING no READ64/WRITE64\n"));
463 else
465 D(bug("[afs] initVolume-NSD: no need for NSD\n"));
469 /*******************************************
470 Name : flush
471 Descr.: flush buffers and update disk (sync)
472 Input : volume - volume to flush
473 Output: DOSTRUE
474 ********************************************/
475 BOOL flush(struct AFSBase *afsbase, struct Volume *volume) {
477 flushCache(afsbase, volume);
478 volume->ioh.ioreq->iotd_Req.io_Command = CMD_UPDATE;
479 DoIO((struct IORequest *)&volume->ioh.ioreq->iotd_Req);
480 clearCache(afsbase, volume->blockcache);
481 return DOSTRUE;
484 static ULONG readwriteDisk
486 struct AFSBase *afsbase,
487 struct Volume *volume,
488 ULONG start,
489 ULONG count,
490 APTR mem,
491 ULONG cmd
494 LONG retval;
495 struct IOHandle *ioh = &volume->ioh;
496 UQUAD offset;
498 if (start + count <= volume->countblocks)
500 ioh->ioreq->iotd_Req.io_Command = cmd;
501 ioh->ioreq->iotd_Req.io_Length = count*BLOCK_SIZE(volume);
502 ioh->ioreq->iotd_Req.io_Data = mem;
504 offset = (UQUAD)volume->startblock * volume->sectorsize
505 + (UQUAD)start * BLOCK_SIZE(volume);
507 ioh->ioreq->iotd_Req.io_Offset = 0xFFFFFFFF & offset;
508 ioh->ioreq->iotd_Req.io_Actual = offset>>32;
509 retval = DoIO((struct IORequest *)&ioh->ioreq->iotd_Req);
510 ioh->flags |= IOHF_MOTOR_OFF;
512 else
514 showText(afsbase, "Attempted to read/write block outside range!\n\n"
515 "range: %lu-%lu, start: %lu, count: %lu",
516 volume->startblock, volume->lastblock,
517 volume->startblock + start * volume->blocksectors,
518 count * volume->blocksectors);
519 retval = 1;
521 return retval;
524 LONG readDisk(struct AFSBase *afsbase, struct Volume *volume, ULONG start, ULONG count, APTR data) {
525 LONG result = 0;
526 BOOL retry = TRUE;
528 while (retry)
530 DB2(bug("[afs] readDisk: reading blocks %lu to %lu\n", start, start+count-1));
531 result = readwriteDisk(afsbase, volume, start, count, data, volume->ioh.cmdread);
532 if (result == 0)
533 retry = FALSE;
534 else
535 retry = showRetriableError(afsbase, "Read error %ld on block %lu", result, start) == 1;
538 return result;
541 LONG writeDisk(struct AFSBase *afsbase, struct Volume *volume, ULONG start, ULONG count, APTR data) {
542 LONG result = 0;
543 BOOL retry = TRUE;
545 while (retry)
547 DB2(bug("[afs] writeDisk: writing blocks %lu to %lu\n", start, start+count-1));
548 result = readwriteDisk(afsbase, volume, start, count, data, volume->ioh.cmdwrite);
549 if (result == 0)
550 retry = FALSE;
551 else
552 retry = showRetriableError(afsbase, "Write error %ld on block %lu", result, start) == 1;
555 return result;
558 #undef SysBase
560 AROS_INTH1(changeIntCode, struct IOHandle *, ioh)
562 AROS_INTFUNC_INIT
564 ioh->ioflags |= IOHF_MEDIA_CHANGE;
565 Signal(ioh->afsbase->port.mp_SigTask, 1<<ioh->afsbase->port.mp_SigBit);
567 return FALSE;
569 AROS_INTFUNC_EXIT