home *** CD-ROM | disk | FTP | other *** search
- /* Minixfs version 0.60 , Copyright S.N. Henson 1991,1992,1993
- * see the file 'copying' for more info.
- */
-
- /* Define all global variables */
- #define EXTERN /**/
-
- #include "minixfs.h"
- #include "proto.h"
- #include "global.h"
- #include "xhdi.h"
- #include "pun.h"
- #include <basepage.h>
- #include <mintbind.h>
- #include <signal.h>
-
- /* This rubbish ensures that str(XXX) gets expanded then stringifyed */
- #define str(x) _stringify(x)
- #define _stringify(x) #x
-
- /* Initialisation routine called first by the kernel */
-
- extern FILESYS minix_filesys;
-
- typedef long (*lfptr)();
-
- lfptr old_rwabs,old_getbpb,old_mediach;
-
- unsigned long shadmap;
-
- extern long kludge_rwabs(),kludge_getbpb(),kludge_mediach(),setstack();
-
- long _stksize=1024l; /* Update stacksize */
-
- FILESYS *
- minix_init(k)
- struct kerinfo *k;
- {
- extern int init_icd();
- unsigned long p2,vdrvs;
- int i;
-
- kernel = k;
- CCONWS("Minix file system driver for MiNT. Version "
- str(MFS_MAJOR) "." str(MFS_MINOR) "\r\n"
- "Copyright 1991,1992,1993,1994 S.N.Henson\r\n");
- #ifdef MFS_PLEV
- CCONWS("Patch Level " str(MFS_PLEV) "\r\n");
- #endif
- #ifdef PRE_RELEASE
- CCONWS("Pre-Release Test Version\r\n");
- #endif
- CCONWS("Please read the file COPYING for conditions of use.\r\n");
-
- if( (k->maj_version > 0) || (k->min_version >= 94) ) lockok=1;
- else CCONWS("File Locking not Installed , Use MiNT 0.94 or newer\r\n");
-
- if( (k->maj_version==0) && (k->min_version < 97) ) no_length=1;
-
- /* Allocate Cache */
- if(init_cache()) return NULL;
-
- /* See if there are any shadow drives */
-
- vdrvs=*((unsigned long *)0x4c2);
-
- for(i=0,p2=1;i<NUM_DRIVES;i++,p2<<=1)
- {
- if(ppart[i].start !=-1 )
- {
- if(vdrvs & p2)
- ALERT("Minixfs: shadow drive %c: not installed: drive"
- " already exists!",i+'A');
- else
- {
- ALERT("Shadow Drive %c Installed",i+'A');
- ALERT("Start %ld Finish %ld Device %d",
- ppart[i].start,ppart[i].finish,ppart[i].shadow);
- shadmap |= p2;
- }
- }
- }
-
- *((unsigned long *)0x4c2) = vdrvs | shadmap;
-
- /* Initialise icd kludge */
- init_icd();
-
- if(shadmap) /* Any shadows installed ? */
- {
- /* Set new system vectors */
-
- old_mediach = *((lfptr *) 0x47e);
- old_rwabs = *((lfptr *) 0x476);
- old_getbpb = *((lfptr *) 0x472);
-
- *((lfptr *) 0x47e) = kludge_mediach;
- *((lfptr *) 0x476) = kludge_rwabs;
- *((lfptr *) 0x472) = kludge_getbpb;
- }
-
- switch(cache_mode)
- {
- case ROBUST:
- CCONWS("Robust mode\r\n");
- break;
-
- case NORMAL:
- CCONWS("Normal mode\r\n");
- break;
-
- case TURBO:
- CCONWS("TURBO mode\r\n");
- break;
- }
-
- /* If we are in Turbo mode then run a backround updater.
- * This is a variant of the code used in 'thread.c' in mintlib
- * If we have Addroottimeout, use that.
- */
-
- if(cache_mode==TURBO)
- {
- BASEPAGE *b;
-
- if(Addroottimeout) Addroottimeout(sync_time*1000l,t_sync,0);
- else
- {
- b = (BASEPAGE *)p_exec(5, 0L, "", 0L); /* create a basepage */
-
- (void)m_shrink(0,b, 256 + _stksize); /* Basepage + stack */
-
- b->p_tbase = (char *)update; /* text start = func to start */
- b->p_hitpa = ((char *)b) + 256 + _stksize;
-
- update_pid = (short) p_exec(104, "update", b, 0L);
-
- /* run in backround */
- }
- }
-
- return &minix_filesys;
- }
-
- /* Note: update is a user level process and must act accordingly i.e. use
- * the syscalls not the dos/bios tables.
- */
-
- int update(bp)
- long bp;
- {
- #if 1
- #define _base ((BASEPAGE *)(&init_addr)-1)
- extern long init_addr;
- ((BASEPAGE *)bp)->p_tbase = _base->p_tbase;
- ((BASEPAGE *)bp)->p_tlen = _base->p_tlen;
- ((BASEPAGE *)bp)->p_dbase = _base->p_dbase;
- ((BASEPAGE *)bp)->p_dlen = _base->p_dlen;
- ((BASEPAGE *)bp)->p_bbase = _base->p_bbase;
- ((BASEPAGE *)bp)->p_blen = _base->p_blen;
- #endif
-
- setstack(bp+256+_stksize);
-
- /* Trap most signals */
-
- Psignal(SIGALRM,do_sync);
- Psignal(SIGTERM,do_sync);
- Psignal(SIGQUIT,do_sync);
- Psignal(SIGHUP,do_sync);
- Psignal(SIGTSTP,do_sync);
- Psignal(SIGINT,do_sync);
-
- for(;;)
- {
- int tsync;
- tsync=sync_time;
- while(tsync > 32 )
- {
- (void) Fselect(32000,0l,0l,0l);
- tsync-=32;
- }
- if(tsync > 0) (void) Fselect(tsync*1000l,0l,0l,0l);
- do_sync(0);
- }
- }
-
- char mfspath[]="A:";
-
- void do_sync(signum)
- long signum;
- {
- int i;
- if(update_suspend) return;
- for(i=0;i<NUM_DRIVES;i++)
- {
- if(super_ptr[i] && super_ptr[i]!=DFS)
- {
- mfspath[0]='A'+i;
- Dcntl(MFS_SYNC,mfspath,0);
- return;
- }
- }
- }
-
- /* Much cleaner method using addroottimeout(), this is now at kernel
- * level and so can call l_sync() safely, it also schedules the next
- * sync()
- */
-
- void t_sync()
- {
- TRACE("Minixfs: doing t_sync()");
- if(!update_suspend) l_sync();
- Addroottimeout(1000l*sync_time,t_sync,0);
- }
-
- /* Sanity checker, checks a filesystem is minix and then sets up all internal
- * structures accordingly, e.g. superblock and directory increment. Returns
- * '1' if the filesystem is minix, 0 otherwise. Uses get_hddinf to try all
- * possible means to access the drive.
- */
-
- int
- minix_sanity(drv)
- int drv;
- {
- int i;
- d_inode rip;
- struct hdinfo *dsk;
- char is_phys;
- long err;
- unsigned long drv_mask;
- super_info *psblk;
-
- drv_mask = 1l<<drv;
-
- if(!( *((unsigned long *)0x4c2) & drv_mask ))
- {
- DEBUG("Invalid drive %c:",drv+'A');
- return 0;
- }
-
- dsk=&disk[drv];
- psblk=Kmalloc(sizeof(super_info));
- if(!psblk)
- {
- ALERT("Minixfs: No memory for super_info structure");
- return 0;
- }
-
- psblk->dev=drv;
-
- if(ppart[drv].start!=-1) /* Is this a physical partition ? */
- {
- struct phys_part *pp;
- pp=&ppart[drv];
- dsk->start=pp->start;
- dsk->size=pp->finish-dsk->start+1;
- dsk->scsiz=pp->scsiz;
- dsk->major = pp->shadow;
- dsk->drive = drv;
- (void)GETBPB(drv); /* Satisfy disk changes */
- dsk->rwmode = RW_PHYS;
- if(dsk->start > 0xfff0)
- {
- if(no_plrecno(dsk->major))
- {
- ALERT("Cannot access physical parition %c:",drv+'A');
- Kfree(psblk);
- return 0;
- }
- dsk->rwmode |= RW_LRECNO;
- }
- is_phys=1;
- }
- else
- {
- is_phys=0;
- if( (err=get_hddinf(drv,dsk,0)) )
- {
- DEBUG("Cannot access partition %c: %s.",drv+'A',hdd_err[err]);
- Kfree(psblk);
- return 0;
- }
- }
-
- super_ptr[drv]=psblk;
-
- crwabs(2,&temp,1,SUPER_BLOCK,drv);
-
- psblk->sblk=*((super_block *)&temp);
-
- if(( (psblk->sblk.s_magic==SUPER_MAGIC) ||
- (psblk->sblk.s_magic==SUPER_V2) ||
- (psblk->sblk.s_magic==SUPER_V1_30) )
- && psblk->sblk.s_ninodes) {
- if(psblk->sblk.s_log_zsize) {
- DEBUG("Cannot read Drive %c Zone-size > Block-size",drv+'A');
- super_ptr[drv]=DFS;
- Kfree(psblk);
- return -1;
- }
- if(psblk->sblk.s_magic==SUPER_V2)
- {
- TRACE("Drive %c V2 filesystem",drv+'A');
- psblk->version=1;
- psblk->ipb=INODES_PER_BLOCK2;
- psblk->zpind=NR_INDIRECTS2;
- psblk->dzpi=NR_DZONE_NUM2;
- psblk->ndbl=NR_DBL2;
-
- /* Check if lrecno needed/supported */
-
- if(set_lrecno(dsk,psblk->sblk.s_zones))
- {
- ALERT("No way to access large partition %c:",drv+'A');
- Kfree(psblk);
- super_ptr[drv]=DFS;
- return -1;
- }
- }
- else
- {
- TRACE("Drive %c V1 filesyetem",drv+'A');
- psblk->version=0;
- psblk->ipb=INODES_PER_BLOCK;
- psblk->zpind=NR_INDIRECTS;
- psblk->sblk.s_zones=psblk->sblk.s_nzones;
- psblk->dzpi=NR_DZONE_NUM;
- psblk->ndbl=NR_DBL;
- }
-
- psblk->ioff = psblk->sblk.s_imap_blks + psblk->sblk.s_zmap_blks
- + 2 ;
- read_inode(ROOT_INODE,&rip,drv);
- if(IS_DIR(rip)) {
- void *p;
- int dot=-1,dotdot=-1;
- p=Kmalloc((unsigned) (BLOCK_SIZE*(psblk->sblk.s_imap_blks+
- psblk->sblk.s_zmap_blks)));
- if(!p) {
- DEBUG("No room for bitmaps");
- Kfree(psblk);
- super_ptr[drv]=DFS;
- return -1;
- }
- psblk->ibitmap=p;
- psblk->zbitmap=p+BLOCK_SIZE*psblk->sblk.s_imap_blks;
- crwabs(2,p,psblk->sblk.s_imap_blks+psblk->sblk.s_zmap_blks
- ,2,drv);
- psblk->idirty=0;
- psblk->zdirty=0;
- psblk->zlast=0;
- psblk->ilast=0;
-
- /* Clear all mount flags */
-
- psblk->mnt_first=0;
- psblk->mnt_next=0;
- psblk->mnt_inode=0;
- psblk->mnt_flags=0;
- psblk->mnt_dev=0;
-
- /* Final step , read in the root directory zone 1 and check the '.' and '..'
- * spacing , The spacing between the '.' and '..' will be used as an indicator
- * of the directory entry size. If in doubt assume a normal minix filesystem.
- */
-
- read_zone(rip.i_zone[0],&temp,drv,&syscache);
-
- for(i=0;i<min(NR_DIR_ENTRIES,rip.i_size/DIR_ENTRY_SIZE);i++)
- {
- if(temp.bdir[i].d_inum)
- {
- if(!strcmp(temp.bdir[i].d_name,"."))
- {
- if(dot==-1) dot=i;
- else
- {
- ALERT ("Drive %c multiple \".\" in root dir!!", drv + 'A');
- dot=-1;
- i=NR_DIR_ENTRIES;
- }
- }
-
- if(!strcmp(temp.bdir[i].d_name,".."))
- {
- if(dotdot==-1) dotdot=i;
- else
- {
- ALERT ("Drive %c multiple \"..\" in root directory", drv + 'A');
- dotdot=-1;
- i=NR_DIR_ENTRIES;
- }
- }
- }
- }
-
- if( (dotdot==-1) || (dot==-1) )
- {
- ALERT("Drive %c no . or .. in root directory",drv+'A');
- Kfree(psblk->ibitmap);
- Kfree(psblk);
- super_ptr[drv]=DFS;
- return -1;
- }
- else psblk->increment=dotdot-dot;
-
- if( (psblk->increment < 1) || NPOW2(psblk->increment))
- {
- ALERT("Drive %c weird . .. positions",drv+'A');
- Kfree(psblk->ibitmap);
- Kfree(psblk);
- super_ptr[drv]=DFS;
- return -1;
- }
-
- if(psblk->increment > MAX_INCREMENT)
- {
- ALERT("Drive %c Increment %d",drv+'A',psblk->increment);
- ALERT("This minix.xfs binary can only handle %d",MAX_INCREMENT);
- ALERT("Recompile with a higher MAX_INCREMENT");
- Kfree(psblk->ibitmap);
- Kfree(psblk);
- super_ptr[drv]=DFS;
- return -1;
- }
-
- return 1;
-
- }
- else {
- ALERT("root inode on drive %c is not a directory??",
- drv+'A');
- Kfree(psblk->ibitmap);
- Kfree(psblk);
- super_ptr[drv]=DFS;
- return -1;
- }
- }
-
- Kfree(psblk);
-
- if(is_phys)
- {
- ALERT("Physical partition %c: not minix!!",drv+'A');
- super_ptr[drv]=DFS;
- return -1;
- }
-
- super_ptr[drv]=0;
- return 0;
- }
-