3 * Revision 11.34 1999/09/11 17:05:14 Michiel
6 * Revision 11.33 1999/05/14 11:31:34 Michiel
7 * Long filename support implemented; bugfixes
9 * Revision 11.32 1999/03/23 05:57:39 Michiel
10 * Autoupgrade bug involving MODE_SUPERDELDIR fixed
12 * Revision 11.31 1999/03/09 10:32:19 Michiel
13 * 00136: 1024 byte sector support
15 * Revision 11.30 1999/02/22 16:25:30 Michiel
16 * Changes for increasing deldir capacity
18 * Revision 11.29 1998/09/27 11:26:37 Michiel
19 * Dynamic rootblock allocation in GetCurrentRoot
20 * New ErrorMsg function that replaces macro
22 * Revision 11.28 1998/05/30 18:40:14 Michiel
23 * Title of error requesters was wrong
25 * Revision 11.27 1998/05/27 21:00:08 Michiel
26 * MODE_DATESTAMP is automatically turned on
28 * Revision 11.26 1998/05/22 22:59:58 Michiel
31 * Revision 11.25 1997/03/03 22:04:04 Michiel
34 * Revision 11.24 1996/03/29 17:00:11 Michiel
35 * bugfix: rootblock was freed with FreeVec instead of with FreeBufmem
37 * Revision 11.23 1996/01/30 12:50:39 Michiel
38 * Diskinsertsequence didn't used old instead of just read rootblock
39 * --- working tree overlap ---
41 * Revision 11.22 1996/01/03 10:04:35 Michiel
44 * Revision 11.21 1995/11/15 16:00:05 Michiel
45 * Rootblock extension detection, loading and automatic creation
47 * Revision 11.20 1995/11/07 15:07:18 Michiel
48 * Adapted to new datacache (16.2)
49 * FreeUnusedResources() checks if volume
51 * Revision 11.19 1995/09/01 11:18:05 Michiel
52 * CheckCurrentVolumeBack added
53 * NormalErrorMsg changed. Extra argument that specifies the
54 * number of targets added.
56 * Revision 11.18 1995/08/21 04:23:11 Michiel
57 * Create deldir if it isn't there
59 * Revision 11.17 1995/08/04 04:23:01 Michiel
60 * use of MODE_SIZEFIELD added
62 * Revision 11.16 1995/07/21 06:58:07 Michiel
63 * DELDIR adaptions: MakeVolumeData, FreeVolumeResources
65 * Revision 11.15 1995/07/11 17:29:31 Michiel
66 * ErrorMsg () calls use messages.c variables now.
68 * Revision 11.14 1995/07/11 09:23:36 Michiel
71 * Revision 11.13 1995/07/07 14:38:47 Michiel
74 * Revision 11.12 1995/07/07 10:14:12 Michiel
75 * changed CheckVolume()
77 * Revision 11.11 1995/06/19 09:43:19 Michiel
78 * softprotect of on diskchange
80 * Revision 11.10 1995/06/16 09:59:37 Michiel
81 * using Allec & FreeBufMem
83 * Revision 11.9 1995/06/15 18:56:53 Michiel
86 * Revision 11.8 1995/05/20 12:12:12 Michiel
87 * Updated messages to reflect Ami-FileLock
91 * Revision 11.7 1995/03/30 18:55:39 Michiel
92 * Initialization of notifylist added to MakeVolumeData()
94 * Revision 11.6 1995/02/15 16:43:39 Michiel
96 * Using new headers (struct.h & blocks.h)
98 * Revision 11.5 1995/01/29 07:34:57 Michiel
99 * Raw res read/write and LOCK update
101 * Revision 11.4 1995/01/24 09:54:14 Michiel
102 * Cache hashing added
104 * Revision 11.3 1995/01/18 04:29:34 Michiel
105 * Bugfixes. Now ready for beta release.
107 * Revision 11.2 1995/01/15 05:26:44 Michiel
108 * fixed FreeVolumeResources bug
109 * inhibited trackdisk specific parts
111 * Revision 11.1 1995/01/08 16:24:01 Michiel
112 * Compiled (new MODE_BIG version)
114 * Revision 10.4 1994/11/15 17:52:30 Michiel
117 * Revision 10.3 1994/10/29 08:55:42 Michiel
118 * changed process references to msgport references
120 * Revision 10.2 1994/10/27 11:38:17 Michiel
121 * Killed old Update() routines, that now reside in new_Update()
122 * MakeBlockDirty() now unconditionally sets g->dirty
124 * Revision 10.1 1994/10/24 11:16:28 Michiel
129 //#define DEBUGMODE 1
130 #define __USE_SYSBASE
132 #include <exec/types.h>
133 #include <exec/memory.h>
134 #include <exec/devices.h>
136 #include <exec/interrupts.h>
137 #include <devices/input.h>
138 #include <devices/timer.h>
139 #include <dos/filehandler.h>
140 #include <intuition/intuition.h>
141 #include <proto/intuition.h>
142 #include <clib/alib_protos.h>
155 #include "directory_protos.h"
156 #include "volume_protos.h"
157 #include "disk_protos.h"
158 #include "allocation_protos.h"
159 #include "anodes_protos.h"
160 #include "update_protos.h"
161 #include "lru_protos.h"
162 #include "ass_protos.h"
163 #include "init_protos.h"
164 #include "format_protos.h"
166 static VOID
CreateInputEvent(BOOL inserted
, globaldata
*g
);
168 /**********************************************************************/
170 /**********************************************************************/
174 static UBYTE debugbuf
[120];
175 #define DebugOn debug++
176 #define DebugOff debug=(debug?debug-1:0)
177 #define DebugMsg(msg) if(debug) {NormalErrorMsg(msg, NULL); debug=0;}
178 #define DebugMsgNum(msg, num) sprintf(debugbuf, "%s 0x%08lx.", msg, num); \
179 if(debug) {NormalErrorMsg(debugbuf, NULL); debug=0;}
180 #define DebugMsgName(msg, name) sprintf(debugbuf, "%s >%s<.", msg, name); \
181 if(debug) {NormalErrorMsg(debugbuf, NULL); debug=0;}
186 #define DebugMsgNum(msg,num)
187 #define DebugMsgName(msg, name)
191 /**********************************************************************/
195 /**********************************************************************/
199 ** I Update diskchangenumber
200 ** :nochange->exit (tenzij FORCE = TRUE)
202 ** II New state = volume present?
203 ** :get id of new disk (read rootblock)
204 ** New disk = current disk?
207 ** III Old state = volume present?
208 ** :diskremoved-sequence
210 ** IV New state = volume present ?
211 ** :diskinserted-sequence
213 ** II-III-IV ordering is essential because diskremove-sequence has to be done before
214 ** diskinsert-sequence and diskremove-sequence can only be executed if newvolume <>
217 ** DiskRemove-sequence
219 ** I Clear globaldata->currentvolume (prevent infinite recursive loop)
221 ** II Changed blocks in cache ?
222 ** :request old volume (causes recursive call)
226 ** III Locks/files open on volume?
227 ** yes: link locks in doslist
228 ** clear volume task field
229 ** no: remove volume from doslist
230 ** free all volume resources
232 ** DiskInsert-sequence
234 ** I Search new disk in volumelist
235 ** found: take over volume and locklist
236 ** ~found: make new volumestructure
237 ** link volume in doslist
239 ** II Update globaldata->currentvolume
241 ** use FORCE to force a new volume even if the changecount is equal
243 static BOOL
SameDisk(struct rootblock
*, struct rootblock
*);
244 static BOOL
SameDiskDL(struct rootblock
*, struct DeviceList
*);
245 static void TakeOverLocks(struct FileLock
*, globaldata
*);
247 void NewVolume (BOOL FORCE
, globaldata
*g
)
249 BOOL oldstate
, newstate
, changed
;
250 struct rootblock
*rootblock
;
252 /* check if something changed */
253 changed
= UpdateChangeCount (g
);
254 if (!FORCE
&& !changed
)
260 /* newstate <=> there is a PFS disk present */
261 oldstate
= g
->currentvolume
? TRUE
: FALSE
;
262 newstate
= GetCurrentRoot (&rootblock
, g
);
264 /* undo error enforced softprotect */
265 if ((g
->softprotect
== 1) && g
->protectkey
== ~0)
266 g
->softprotect
= g
->protectkey
= 0;
268 if (oldstate
&& !newstate
)
269 DiskRemoveSequence (g
);
273 if (oldstate
&& SameDisk (rootblock
, g
->currentvolume
->rootblk
))
275 FreeBufmem (rootblock
, g
); /* @XLVII */
280 DiskRemoveSequence (g
);
281 DiskInsertSequence (rootblock
, g
);
286 g
->currentvolume
= NULL
; /* @XL */
295 ** globaldata->currentvolume not necessarily present
297 ** the old currentvolume is updated en als 'removed' currentvolume == 0
298 ** return waarde = currentdisk back in drive?
299 ** used by NewVolume and ACTION_INHIBIT
301 void DiskRemoveSequence(globaldata
*g
)
303 struct volumedata
*oldvolume
= g
->currentvolume
;
305 ENTER("DiskRemoveSequence");
308 ** will ask for old volume if there are unsaved changes
309 ** causes recursive NewVolume call. That's why 'currentvolume'
310 ** has to be cleared first; UpdateDisk won't be called for the
313 if(oldvolume
&& g
->dirty
)
315 RequestCurrentVolumeBack(g
);
321 g
->currentvolume
= NULL
;
324 /* -II- link locks in doslist
325 ** lockentries: link to doslist...
326 ** fileentries: link them too...
328 Forbid(); /* LockDosList(LDF_VOLUMES|LDF_READ); */
329 if(!IsMinListEmpty(&oldvolume
->fileentries
))
331 DB(Trace(1, "DiskRemoveSequence", "there are locks\n"));
332 oldvolume
->devlist
->dl_LockList
= MKBADDR(&(((listentry_t
*)(HeadOf(&oldvolume
->fileentries
)))->lock
));
333 oldvolume
->devlist
->dl_Task
= NULL
;
334 FreeUnusedResources(oldvolume
, g
);
338 DB(Trace(1, "DiskRemoveSequence", "removing doslist\n"));
339 RemDosEntry((struct DosList
*)oldvolume
->devlist
);
340 FreeDosEntry((struct DosList
*)oldvolume
->devlist
);
341 MinRemove(oldvolume
);
342 FreeVolumeResources(oldvolume
, g
);
344 Permit(); /* UnLockDosList(LDF_VOLUMES|LDF_READ); */
349 g
->request
->iotd_Req
.io_Command
= CMD_CLEAR
;
354 CreateInputEvent(FALSE
, g
);
357 g
->tdmode
= ACCESS_UNDETECTED
;
360 EXIT("DiskRemoveSequence");
364 void DiskInsertSequence(struct rootblock
*rootblock
, globaldata
*g
)
366 struct DosList
*doslist
;
368 struct DeviceList
*devlist
;
369 BOOL found
= FALSE
, added
= FALSE
;
370 UBYTE diskname
[DNSIZE
]; // or should it be a DSTR??
373 ENTER("DiskInsertSequence");
375 /* -I- Search new disk in volumelist */
377 BCPLtoCString(diskname
, rootblock
->diskname
);
378 // doslist = LockDosList(LDF_VOLUMES|LDF_READ);
380 di
= BADDR(((struct RootNode
*)DOSBase
->dl_Root
)->rn_Info
);
381 doslist
= BADDR(di
->di_DevInfo
);
383 for (doslist
= BADDR(di
->di_DevInfo
);doslist
;doslist
= BADDR(doslist
->dol_Next
))
385 if (doslist
->dol_Type
== DLT_VOLUME
&& SameDiskDL(rootblock
, (struct DeviceList
*)doslist
))
394 // doslist = NextDosEntry(doslist, LDF_VOLUMES);
396 // if(doslist && (doslist = FindDosEntry(doslist, diskname, LDF_VOLUMES)))
397 // found = SameDiskDL(rootblock, (struct DeviceList *)doslist);
404 DB(Trace(1, "DiskInsertSequence", "found\n"));
406 devlist
= (struct DeviceList
*)doslist
;
407 locklist
= (SIPTR
)BADDR(devlist
->dl_LockList
);
410 ** use LOCKTOFILEENTRY(lock)->volume to get volumepointer
416 /* get volumepointer @XLXV */
417 fe
= LOCKTOFILEENTRY(locklist
);
418 if(fe
->le
.type
.flags
.type
== ETF_VOLUME
)
419 g
->currentvolume
= fe
->le
.info
.volume
.volume
;
421 g
->currentvolume
= fe
->le
.volume
;
423 /* update rootblock */
424 if (g
->rootblock
) FreeBufmem (g
->rootblock
, g
);
426 g
->currentvolume
->rootblk
= rootblock
;
428 /* take over filelocks
429 ** lockentries: takeover, change taskfield
430 ** fileentries: don't change taskfield
432 TakeOverLocks((struct FileLock
*)locklist
, g
);
433 devlist
= (struct DeviceList
*)doslist
;
434 devlist
->dl_LockList
= BNULL
;
435 devlist
->dl_Task
= g
->msgport
;
440 RemDosEntry(doslist
); // @@ freeing rootblk etc?
441 FreeDosEntry(doslist
);
442 found
= FALSE
; // an empty doslistentry is useless to us
445 // UnLockDosList(LDF_VOLUMES|LDF_READ);
450 DB(Trace(1, "DiskInsertSequence", "not found %s\n", diskname
));
452 /* make new doslist entry (MOET eerst (zie blz67 schrift) */
453 devlist
= (struct DeviceList
*)MakeDosEntry(diskname
, DLT_VOLUME
);
456 /* devlist invullen. Diskname NIET @XLIX */
457 devlist
->dl_Task
= g
->msgport
;
458 devlist
->dl_VolumeDate
.ds_Days
= rootblock
->creationday
;
459 devlist
->dl_VolumeDate
.ds_Minute
= rootblock
->creationminute
;
460 devlist
->dl_VolumeDate
.ds_Tick
= rootblock
->creationtick
;
461 devlist
->dl_LockList
= BNULL
; // no locks open yet
462 devlist
->dl_DiskType
= rootblock
->disktype
;
463 added
= AddDosEntry((struct DosList
*)devlist
);
466 /* make new volumestructure for inserted volume */
467 g
->currentvolume
= MakeVolumeData(rootblock
, g
);
468 MinAddHead(&g
->volumes
, g
->currentvolume
);
469 g
->currentvolume
->devlist
= (struct DeviceList
*)devlist
;
471 /* check if things worked out */
472 if(!devlist
|| !added
) // duplicate disks or out of memory
474 ErrorMsg (AFS_ERROR_DOSLIST_ADD
, NULL
, g
);
476 FreeDosEntry((struct DosList
*)devlist
);
477 FreeVolumeResources(g
->currentvolume
, g
);
478 g
->currentvolume
= NULL
;
481 CreateInputEvent(TRUE
, g
);
484 /* Reconfigure modules to new volume */
485 InitModules (g
->currentvolume
, FALSE
, g
);
487 /* create rootblockextension if its not there yet */
488 if (!g
->currentvolume
->rblkextension
&&
489 g
->diskstate
!= ID_WRITE_PROTECTED
)
491 MakeRBlkExtension (g
);
496 if (rootblock
->deldir
)
498 struct cdeldirblock
*ddblk
;
501 /* kill current deldir */
502 ddblk
= (struct cdeldirblock
*)AllocLRU(g
);
505 if (RawRead ((UBYTE
*)&ddblk
->blk
, RESCLUSTER
, rootblock
->deldir
, g
) == 0)
507 if (ddblk
->blk
.id
== DELDIRID
)
510 nr
= ddblk
->blk
.entries
[i
].anodenr
;
512 FreeAnodesInChain(nr
, g
);
515 FreeLRU ((struct cachedblock
*)ddblk
);
518 /* create new deldir */
520 ResToBeFreed(rootblock
->deldir
, g
);
521 rootblock
->deldir
= 0;
522 rootblock
->options
|= MODE_SUPERDELDIR
;
526 /* update datestamp and enable */
527 rootblock
->options
|= MODE_DATESTAMP
;
528 rootblock
->datestamp
++;
531 EXIT("DiskInsertSequence");
534 /* check if rootblocks are of the same disk */
535 static BOOL
SameDisk(struct rootblock
*disk1
, struct rootblock
*disk2
)
539 result
= disk1
->creationday
== disk2
->creationday
&&
540 disk1
->creationminute
== disk2
->creationminute
&&
541 disk1
->creationtick
== disk2
->creationtick
&&
542 ddstricmp(disk1
->diskname
, disk2
->diskname
);
547 /* checks is devicelist belongs to rootblock */
548 static BOOL
SameDiskDL(struct rootblock
*disk1
, struct DeviceList
*disk2
)
552 result
= ddstricmp(disk1
->diskname
, BADDR(disk2
->dl_Name
)) &&
553 disk1
->creationday
== disk2
->dl_VolumeDate
.ds_Days
&&
554 disk1
->creationminute
== disk2
->dl_VolumeDate
.ds_Minute
&&
555 disk1
->creationtick
== disk2
->dl_VolumeDate
.ds_Tick
;
560 /* make and fill in volume structure
564 struct volumedata
*MakeVolumeData (struct rootblock
*rootblock
, globaldata
*g
)
566 struct volumedata
*volume
;
567 struct MinList
*list
;
569 ENTER("MakeVolumeData");
571 volume
= AllocMemPR (sizeof(struct volumedata
), g
);
573 volume
->rootblk
= rootblock
;
574 volume
->rootblockchangeflag
= FALSE
;
576 /* lijsten initieren */
577 for (list
= &volume
->fileentries
; list
<= &volume
->notifylist
; list
++)
578 NewList((struct List
*)list
);
580 /* andere gegevens invullen */
581 volume
->numsofterrors
= 0;
582 volume
->diskstate
= ID_VALIDATED
;
584 /* these could be put in rootblock @@ see also HD version */
585 volume
->numblocks
= g
->geom
->dg_TotalSectors
;
586 volume
->bytesperblock
= g
->geom
->dg_SectorSize
;
587 volume
->rescluster
= rootblock
->reserved_blksize
/ volume
->bytesperblock
;
589 /* load rootblock extension (if it is present) */
590 if (rootblock
->extension
&& (rootblock
->options
& MODE_EXTENSION
))
592 struct crootblockextension
*rext
;
594 rext
= AllocBufmemR (sizeof(struct cachedblock
) + rootblock
->reserved_blksize
, g
);
595 memset (rext
, 0, sizeof(struct cachedblock
) + rootblock
->reserved_blksize
);
596 if (RawRead ((UBYTE
*)&rext
->blk
, volume
->rescluster
, rootblock
->extension
, g
) != 0)
598 ErrorMsg (AFS_ERROR_READ_EXTENSION
, NULL
, g
);
599 FreeBufmem (rext
, g
);
600 rootblock
->options
^= MODE_EXTENSION
;
604 if (rext
->blk
.id
== EXTENSIONID
)
606 volume
->rblkextension
= rext
;
607 rext
->volume
= volume
;
608 rext
->blocknr
= rootblock
->extension
;
612 ErrorMsg (AFS_ERROR_EXTENSION_INVALID
, NULL
, g
);
613 FreeBufmem (rext
, g
);
614 rootblock
->options
^= MODE_EXTENSION
;
620 volume
->rblkextension
= NULL
;
623 EXIT("MakeVolumeData");
627 /* fill in my process at the task fields of the locks */
628 static void TakeOverLocks (struct FileLock
*locklist
, globaldata
*g
)
632 locklist
->fl_Task
= g
->msgport
;
633 locklist
= (struct FileLock
*)BADDR(locklist
->fl_Link
);
637 /* free all resources (memory) taken by volume accept doslist
638 ** it is assumed all this data can be discarded (not checked here!)
639 ** it is also assumed this volume is no part of any volumelist
641 void FreeVolumeResources(struct volumedata
*volume
, globaldata
*g
)
643 ENTER("Free volume resources");
647 FreeUnusedResources (volume
, g
);
649 if (volume
->rblkextension
)
650 FreeBufmem (volume
->rblkextension
, g
);
653 // if (g->deldirenabled)
654 // FreeBufmem (volume->deldir, g);
656 FreeBufmem (volume
->rootblk
, g
);
657 FreeMemP (volume
, g
);
660 EXIT("FreeVolumeResources");
663 void FreeUnusedResources(struct volumedata
*volume
, globaldata
*g
)
665 struct MinList
*list
;
666 struct MinNode
*node
, *next
;
668 ENTER("FreeUnusedResources");
670 /* check if volume passed */
674 /* start with anblks!, fileentries are to be kept! */
675 for (list
= volume
->anblks
; list
<=&volume
->bmindexblks
; list
++)
677 node
= (struct MinNode
*)HeadOf(list
);
678 while ((next
= node
->mln_Succ
))
680 FlushBlock((struct cachedblock
*)node
, g
);
681 FreeLRU((struct cachedblock
*)node
);
690 ** generate a `disk inserted/removed' event, in order to get Workbench to
691 ** rescan the DosList and update the list of volume icons.
693 ** function supplied by Nicola Salmoria
695 static VOID
CreateInputEvent(BOOL inserted
, globaldata
*g
)
697 struct MsgPort
*port
;
699 port
= CreateMsgPort();
705 io
= CreateStdIO(port
);
707 io
= CreateIORequest(port
, sizeof(*io
));
711 if (!OpenDevice("input.device",0,(struct IORequest
*)io
,0))
713 struct InputEvent ie
;
715 memset(&ie
,0,sizeof(struct InputEvent
));
716 ie
.ie_Class
= inserted
? IECLASS_DISKINSERTED
: IECLASS_DISKREMOVED
;
717 io
->io_Command
= IND_WRITEEVENT
;
719 io
->io_Length
= sizeof(struct InputEvent
);
720 DoIO((struct IORequest
*)io
);
722 CloseDevice((struct IORequest
*)io
);
737 /**********************************************************************/
738 /* OTHER VOLUMEROUTINES */
739 /* OTHER VOLUMEROUTINES */
740 /* OTHER VOLUMEROUTINES */
741 /**********************************************************************/
743 /* Update the changecount
744 ** returns TRUE if changecount changed
746 BOOL
UpdateChangeCount(globaldata
*g
)
748 struct IOExtTD
*request
= g
->request
;
754 ENTER("UpdateChangeCount");
755 request
->iotd_Req
.io_Command
= TD_CHANGENUM
;
756 if(DoIO((struct IORequest
*)request
) == 0)
757 changecount
= request
->iotd_Req
.io_Actual
;
761 result
= (changecount
!= g
->changecount
);
762 g
->changecount
= changecount
;
767 return 0; /* no change */
771 /* checks if disk is changed. If so calls NewVolume()
772 ** NB: new volume might be NOVOLUME or NOTAFDSDISK
774 void UpdateCurrentDisk(globaldata
*g
)
779 /* CheckVolume checks if a volume (ve lock) is (still) present.
780 ** If volume==NULL (no disk present) then FALSE is returned (@XLII).
781 ** result: requested volume present/not present TRUE/FALSE
783 BOOL
CheckVolume(struct volumedata
*volume
, BOOL write
, SIPTR
*error
, globaldata
*g
)
785 if(!volume
|| !g
->currentvolume
)
790 case ID_UNREADABLE_DISK
:
791 case ID_NOT_REALLY_DOS
:
792 *error
= ERROR_NOT_A_DOS_DISK
;
795 case ID_NO_DISK_PRESENT
:
796 if(!volume
&& !g
->currentvolume
)
798 *error
= ERROR_NO_DISK
;
803 *error
= ERROR_DEVICE_NOT_MOUNTED
;
807 else if(g
->currentvolume
== volume
)
811 case ID_WRITE_PROTECTED
:
814 *error
= ERROR_DISK_WRITE_PROTECTED
;
821 *error
= ERROR_DISK_NOT_VALIDATED
;
826 if(write
&& g
->softprotect
)
828 *error
= ERROR_DISK_WRITE_PROTECTED
;
838 *error
= ERROR_DEVICE_NOT_MOUNTED
;
844 /**********************************************************************/
848 /**********************************************************************/
851 * ErrorMsg wrapper function
853 LONG
ErrorMsg(CONST_STRPTR msg
, APTR arg
, globaldata
*g
)
856 char charbuffer
[256], *b
;
858 b
= stpcpy(charbuffer
, "Device ");
859 strncpy(b
, &g
->mountname
[1], g
->mountname
[0]);
860 b
+= g
->mountname
[0];
861 b
= stpcpy(b
, ":\n");
864 rv
= (g
->ErrorMsg
)(charbuffer
,arg
,1,g
);
865 if (!g
->softprotect
) {
869 if (g
->currentvolume
)
870 g
->currentvolume
->numsofterrors
++;
875 /* All possible ErrorMsg routines
877 ** Displays easyrequest with error message
878 ** Intuition library has to be opened
880 static const CONST_STRPTR gadgets
[] =
885 LONG
_NormalErrorMsg(CONST_STRPTR melding
, APTR arg
, ULONG notargets
, globaldata
*g
)
887 struct EasyStruct req
;
890 * Make sure we don't hold the performance semaphore while displaying
891 * a requester. Note that unlock_device_unit is safe to call multiple
892 * times, and even when not holding a lock. Unlock also is safe to call
893 * before init has been called.
895 unlock_device_unit(g
);
897 req
.es_StructSize
= sizeof(req
);
899 req
.es_Title
= "PFS-III Error Requester";
900 req
.es_TextFormat
= (STRPTR
)melding
;
901 req
.es_GadgetFormat
= (STRPTR
)gadgets
[notargets
-1];
902 return EasyRequestArgs(NULL
, &req
, NULL
, arg
);
906 /* Don't show up a error requester. Used by GetCurrentRoot */
907 static LONG
NoErrorMsg(CONST_STRPTR melding
, APTR arg
, ULONG dummy
, globaldata
*g
)
912 /***********************************************************************/
916 /***********************************************************************/
918 /* Load the rootblock of the volume that is currently in the drive.
919 * Returns FLASE if no disk or no PFS disk and TRU if it is a PFS disk.
920 * Sets disktype in globaldata->disktype
921 * Should NOT change globaldata->currentvolume
923 * Allocates space in 'rootblock' which is freed if an error occurs.
927 static void UpdateDosEnvec(globaldata
*g
);
930 BOOL
GetCurrentRoot(struct rootblock
**rootblock
, globaldata
*g
)
934 struct IOExtTD
*request
= g
->request
;
937 ENTER("GetCurrentRoot");
942 UpdateChangeCount(g
);
945 ** ESSENTIAL for diskspare.device
946 ** if not present problems with interleaving FFS disks
951 g
->request
->iotd_Req
.io_Command
= CMD_CLEAR
;
956 /* Get volumepresentstate */
957 request
->iotd_Req
.io_Command
= TD_CHANGESTATE
;
958 if (DoIO((struct IORequest
*)request
) == 0)
960 /* changestate <=> there is a disk present */
961 changestate
= !request
->iotd_Req
.io_Actual
;
964 if ((g
->disktype
== ID_NOT_REALLY_DOS
) || (g
->disktype
== ID_UNREADABLE_DISK
))
965 CreateInputEvent(FALSE
, g
);
966 g
->disktype
= ID_NO_DISK_PRESENT
;
972 /* get drive geometry table (V4.3) */
975 /* Get diskprotection @XLI */
976 request
->iotd_Req
.io_Command
= TD_PROTSTATUS
;
977 if (DoIO((struct IORequest
*)request
) == 0)
979 if (request
->iotd_Req
.io_Actual
)
980 g
->diskstate
= ID_WRITE_PROTECTED
;
982 g
->diskstate
= ID_VALIDATED
;
986 g
->diskstate
= ID_VALIDATED
;
987 DB(Trace(1, "GetCurrentRoot", "TD_PROTSTATUS failed\n"));
990 /* check if disk is PFS disk */
991 *rootblock
= AllocBufmemR (BLOCKSIZE
, g
);
992 g
->ErrorMsg
= NoErrorMsg
; // prevent readerrormsg
995 /* detect best access mode, td32, td64, nsd or directscsi */
996 if (g
->tdmode
== ACCESS_UNDETECTED
) {
997 if (!detectaccessmode((UBYTE
*)*rootblock
, g
))
1002 error
= RawRead((UBYTE
*)*rootblock
, 1, BOOTBLOCK1
, g
);
1003 g
->ErrorMsg
= _NormalErrorMsg
;
1007 if ((*rootblock
)->disktype
== ID_PFS_DISK
|| (*rootblock
)->disktype
== ID_PFS2_DISK
)
1009 g
->disktype
= ID_PFS_DISK
;
1010 error
= RawRead((UBYTE
*)*rootblock
, 1, ROOTBLOCK
, g
);
1013 /* check size and read all rootblock blocks */
1014 // 17.10: with 1024 byte blocks rblsize can be 1!
1015 rblsize
= (*rootblock
)->rblkcluster
;
1016 if (rblsize
< 1 || rblsize
> 512)
1019 if (!InitLRU(g
, (*rootblock
)->reserved_blksize
))
1022 FreeBufmem(*rootblock
, g
);
1023 *rootblock
= AllocBufmemR (rblsize
<< BLOCKSHIFT
, g
);
1024 error
= RawRead((UBYTE
*)*rootblock
, rblsize
, ROOTBLOCK
, g
);
1028 if (((*rootblock
)->options
& MODE_SIZEFIELD
) &&
1029 (g
->geom
->dg_TotalSectors
!= (*rootblock
)->disksize
))
1038 g
->disktype
= ID_NOT_REALLY_DOS
;
1039 CreateInputEvent(TRUE
, g
);
1040 FreeBufmem (*rootblock
, g
);
1044 else if (error
== TDERR_DiskChanged
)
1046 if ((g
->disktype
== ID_NOT_REALLY_DOS
) || (g
->disktype
== ID_UNREADABLE_DISK
))
1047 CreateInputEvent(FALSE
, g
);
1048 g
->disktype
= ID_NO_DISK_PRESENT
;
1049 FreeBufmem (*rootblock
, g
);
1055 if (g
->diskstate
!= ID_WRITE_PROTECTED
)
1056 g
->diskstate
= ID_VALIDATING
;
1058 g
->disktype
= ID_UNREADABLE_DISK
;
1059 CreateInputEvent(TRUE
, g
);
1060 FreeBufmem (*rootblock
, g
);
1067 /* Get drivegeometry from diskdevice.
1068 ** If TD_GETGEOMETRY fails the DOSENVEC values are taken
1069 ** Dosenvec is taken into consideration
1071 void GetDriveGeometry(globaldata
*g
)
1073 IPTR
*env
= (IPTR
*)g
->dosenvec
;
1074 struct DriveGeometry
*geom
= g
->geom
;
1078 struct IOExtTD
*request
= g
->request
;
1082 request
->iotd_Req
.io_Data
= geom
;
1083 request
->iotd_Req
.io_Command
= TD_GETGEOMETRY
;
1084 request
->iotd_Req
.io_Length
= sizeof(struct DriveGeometry
);
1085 if(!(error
= DoIO((struct IORequest
*)request
)))
1090 if(error
|| !g
->trackdisk
)
1092 geom
->dg_SectorSize
= env
[DE_SIZEBLOCK
] << 2;
1093 geom
->dg_Cylinders
= env
[DE_UPPERCYL
] - env
[DE_LOWCYL
] + 1;
1094 geom
->dg_CylSectors
= env
[DE_NUMHEADS
] * env
[DE_BLKSPERTRACK
];
1095 geom
->dg_TotalSectors
= g
->geom
->dg_Cylinders
*
1096 g
->geom
->dg_CylSectors
;
1097 geom
->dg_Heads
= env
[DE_NUMHEADS
];
1098 geom
->dg_TrackSectors
= env
[DE_BLKSPERTRACK
];
1099 geom
->dg_BufMemType
= env
[DE_MEMBUFTYPE
];
1100 geom
->dg_DeviceType
= DG_UNKNOWN
;
1104 g
->firstblock
= g
->dosenvec
->de_LowCyl
* geom
->dg_CylSectors
;
1105 g
->lastblock
= (g
->dosenvec
->de_HighCyl
+ 1) * geom
->dg_CylSectors
- 1;
1106 #if LIMIT_MAXTRANSFER
1107 /* A600/A1200/A4000 ROM scsi.device ATA spec max transfer bug workaround */
1108 g
->maxtransfer
= min(g
->dosenvec
->de_MaxTransfer
, LIMIT_MAXTRANSFER
);
1110 g
->maxtransfer
= g
->dosenvec
->de_MaxTransfer
;
1112 DB(Trace(1,"GetDriveGeometry","firstblk %ld lastblk %ld\n",g
->firstblock
,g
->lastblock
));
1118 ** Adapt dosenvec to the current drivegeometry
1119 ** DO NOT call this function if you use partitions (ONLY called by GetDriveGeometry)
1121 static void UpdateDosEnvec(globaldata
*g
)
1124 struct DriveGeometry
*geom
;
1127 // LockDosList(LDF_DEVICES|LDF_READ);
1131 env
= (ULONG
*)g
->dosenvec
;
1132 size
= env
[DE_TABLESIZE
];
1134 if(size
> DE_SIZEBLOCK
)
1135 env
[DE_SIZEBLOCK
] = geom
->dg_SectorSize
>> 2;
1137 if(size
> DE_NUMHEADS
)
1138 env
[DE_NUMHEADS
] = geom
->dg_Heads
;
1140 if(size
> DE_BLKSPERTRACK
)
1141 env
[DE_BLKSPERTRACK
] = geom
->dg_TrackSectors
;
1143 if(size
> DE_LOWCYL
)
1146 if(size
> DE_UPPERCYL
)
1147 env
[DE_UPPERCYL
] = geom
->dg_Cylinders
- 1;
1149 // UnLockDosList(LDF_DEVICES|LDF_READ);
1155 /* Get the currentvolume back in the drive
1157 void RequestCurrentVolumeBack(globaldata
*g
)
1159 UBYTE volumename
[DNSIZE
];
1161 struct rootblock
*rootblock
;
1162 struct volumedata
*volume
= g
->currentvolume
;
1164 ENTER("GetCurrentVolumeBack");
1166 BCPLtoCString(volumename
, volume
->rootblk
->diskname
);
1170 ready
= GetCurrentRoot(&rootblock
, g
) && SameDisk(volume
->rootblk
, rootblock
);
1172 ErrorReport(ABORT_BUSY
, REPORT_VOLUME
, (IPTR
)MKBADDR(volume
->devlist
), NULL
);
1176 FreeBufmem (rootblock
, g
);
1179 BOOL
CheckCurrentVolumeBack (globaldata
*g
)
1182 struct rootblock
*rootblock
;
1183 struct volumedata
*volume
= g
->currentvolume
;
1185 ready
= GetCurrentRoot(&rootblock
, g
) && SameDisk(volume
->rootblk
, rootblock
);
1187 FreeBufmem (rootblock
, g
);