/* 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(); FILESYS * minix_init(k) struct kerinfo *k; { 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 S.N.Henson\r\n"); #ifdef MFS_PLEV CCONWS("Patch Level " str(MFS_PLEV) "\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'); shadmap |= p2; } } } *((unsigned long *)0x4c2) = vdrvs | shadmap; if(shadmap) /* Any shadows installed ? */ { /* Set new system vectors */ old_rwabs = *((lfptr *) 0x476); old_getbpb = *((lfptr *) 0x472); old_mediach = *((lfptr *) 0x47e); *((lfptr *) 0x476) = kludge_rwabs; *((lfptr *) 0x472) = kludge_getbpb; *((lfptr *) 0x47e) = kludge_mediach; } 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(cache_mode==TURBO) { BASEPAGE *b; b = (BASEPAGE *)p_exec(5, 0L, "", 0L); /* create a basepage */ (void)m_shrink(0,b, 512l); /* Basepage + stack */ b->p_tbase = (char *)update; /* text start = func to start */ b->p_hitpa = ((char *)b) + 512; 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; { setstack(bp+512); /* 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(;;) { Talarm(sync_time); Pause(); } } 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]) { mfspath[0]='A'+i; Dcntl(MFS_SYNC,mfspath,0); return; } } } /* 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; super_info *psblk; if(!( *(long *)0x4c2 & (1l<<drv))) { 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; (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_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_MAGIC) { 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; } else { 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 acess large partition %c:",drv+'A'); Kfree(psblk); super_ptr[drv]=DFS; return -1; } 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; /* 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; }