|
|
1.1 root 1: /*
2: dblspace_interface.c
3:
4: DMSDOS CVF-FAT module: high-level interface functions.
5:
6: ******************************************************************************
7: DMSDOS (compressed MSDOS filesystem support) for Linux
8: written 1995-1998 by Frank Gockel and Pavel Pisa
9:
10: (C) Copyright 1995-1998 by Frank Gockel
11: (C) Copyright 1996-1998 by Pavel Pisa
12:
13: Some code of dmsdos has been copied from the msdos filesystem
14: so there are the following additional copyrights:
15:
16: (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
17: (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
18: (C) Copyright 1992-1995 by Linus Torvalds
19:
20: DMSDOS was inspired by the THS filesystem (a simple doublespace
21: DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.
22:
23: The DMSDOS code is distributed under the Gnu General Public Licence.
24: See file COPYING for details.
25: ******************************************************************************
26:
27: */
28:
29: #ifdef __KERNEL__
30: # include <linux/fs.h>
31: # include <linux/blkdev.h>
32: # include <linux/msdos_fs.h>
33: # include <linux/msdos_fs_sb.h>
34: # include <linux/fat_cvf.h>
35: # include <linux/string.h>
36: # include <linux/malloc.h>
37: # include <asm/semaphore.h>
38: # include <linux/module.h>
39: #endif
40:
41: #include"dmsdos.h"
42:
43: #ifdef __DMSDOS_LIB__
44: /* some interface hacks */
45: # include"lib_interface.h"
46: # include<string.h>
47: # include<malloc.h>
48: # define MAJOR(x) 0
49: # define MINOR(x) 0
1.1.1.2 ! root 50: extern long int blk_size[1][1];
1.1 root 51: #endif
52:
53: extern Acache mdfat[];
54: extern Acache dfat[];
55: extern Acache bitfat[];
56:
57: unsigned long loglevel=DEFAULT_LOGLEVEL;
58: unsigned long dmsdos_speedup=DEFAULT_SPEEDUP;
59:
60: /* evaluate numbers from options */
61: char* read_number(char*p, unsigned long* n, int*error)
62: { *n=0;
63: *error=-1;
64: if(*p=='b'||*p=='B'||*p=='%')
65: { /*binary*/
66: ++p;
67: while(*p=='0'||*p=='1')
68: { (*n)*=2;
69: if(*p=='1')++(*n);
70: ++p;
71: *error=0;
72: }
73: }
74: else if(*p=='0'&&(*(p+1)=='x'||*(p+1)=='X'))
75: { /*hexadecimal*/
76: p+=2;
77: while((*p>='0'&&*p<='9')||(*p>='a'&&*p<='f')||(*p>='A'&&*p<='F'))
78: { (*n)*=16;
79: (*n)+=((*p<='9')?(*p):(*p)-'a'+10)&0xf;
80: ++p;
81: *error=0;
82: }
83: }
84: else if(*p=='0'||*p=='O'||*p=='o')
85: { /*octal*/
86: ++p;
87: while(*p>='0'&&*p<='8')
88: { (*n)*=8;
89: (*n)+=(*p)-'0';
90: ++p;
91: *error=0;
92: }
93: }
94: else
95: { /*decimal*/
96: while(*p>='0'&&*p<='9')
97: { (*n)*=10;
98: (*n)+=(*p)-'0';
99: ++p;
100: *error=0;
101: }
102: }
103: LOG_REST("DMSDOS: read_number: n=%lu=0x%lx error=%d\n",*n,*n,*error);
104: return p;
105: }
106:
107: /* evaluates a single option (needn't be '\0' terminated) */
108: int evaluate_option(char*option,Dblsb*dblsb,int*repair)
109: { int ret=0;
110:
111: LOG_REST("DMSDOS: evaluate option: %s\n",option);
112: if(strncmp(option,"comp=",5)==0||strncmp(option,"comp:",5)==0)
113: { if(strncmp(option+5,"no",2)==0)dblsb->s_comp=UNCOMPRESSED;
114: /*else if(strncmp(option+5,"ro",2)==0)*comp=READ_ONLY;*/
115: else if(strncmp(option+5,"ds00",4)==0)dblsb->s_comp=DS_0_0;
116: else if(strncmp(option+5,"ds01",4)==0)dblsb->s_comp=DS_0_1;
117: else if(strncmp(option+5,"ds02",4)==0)dblsb->s_comp=DS_0_2;
118: else if(strncmp(option+5,"jm00",4)==0)dblsb->s_comp=JM_0_0;
119: else if(strncmp(option+5,"jm01",4)==0)dblsb->s_comp=JM_0_1;
120: else if(strncmp(option+5,"sq00",4)==0)dblsb->s_comp=SQ_0_0;
121: else if(strncmp(option+5,"sd3",3)==0)dblsb->s_comp=SD_3;
122: else if(strncmp(option+5,"sd4",3)==0)dblsb->s_comp=SD_4;
123: else if(strncmp(option+5,"guess",5)==0)dblsb->s_comp=GUESS;
124: else ret=-1;
125: }
126: else if(strncmp(option,"cf=",3)==0||strncmp(option,"cf:",3)==0)
127: { if(option[3]=='1'&&option[4]>='0'&&option[4]<='2')
128: dblsb->s_cfaktor=option[4]-'0'+9;
129: else if(option[3]>='1'&&option[3]<='9')
130: dblsb->s_cfaktor=option[3]-'0'-1;
131: else ret=-1;
132: }
133: else if(strncmp(option,"loglevel=",9)==0||strncmp(option,"loglevel:",9)==0)
134: { /* must be decimal or hexadecimal (0x preceeded) number */
135: read_number(option+9,&loglevel,&ret);
136: if(ret>=0)
137: LOG_REST("DMSDOS: evaluate_option: loglevel set to 0x%lx.\n",loglevel);
138: }
139: else if(strncmp(option,"speedup=",8)==0||strncmp(option,"speedup:",8)==0)
140: { /* must be decimal or hexadecimal (0x preceeded) number */
141: read_number(option+8,&dmsdos_speedup,&ret);
142: if(ret>=0)
143: LOG_REST("DMSDOS: evaluate_option: speedup set to 0x%lx.\n",dmsdos_speedup);
144: }
145: else if(strncmp(option,"bitfaterrs=",11)==0||strncmp(option,"bitfaterrs:",11)==0)
146: { if(strncmp(option+11,"repair",6)==0)*repair=1;
147: else if(strncmp(option+11,"ignore",6)==0)*repair=2;
148: else if(strncmp(option+11,"setro",5)==0)*repair=0;
149: else if(strncmp(option+11,"nocheck",7)==0)*repair=-1;
150: else ret=-1;
151: }
152: else
153: { printk(KERN_ERR "DMSDOS: unknown option %s, rejected\n",option);
154: ret=-1;
155: }
156: return ret;
157: }
158:
159: int parse_dmsdos_options(char*options,Dblsb*dblsb,int*repair)
160: { if(options==NULL)return 0;
161:
162: while(*options)
163: { if(evaluate_option(options,dblsb,repair)<0)return -1;
164: while(*options!='\0'&&*options!='.'&&*options!='+')++options;
165: while(*options=='.'||*options=='+')++options;
166: }
167: return 0;
168: }
169:
170: int ilog2(int arg)
171: { /* integer log2 */
172: int i=0;
173:
174: if(arg<=0)return -1;
175:
176: while(arg>>=1)++i;
177: return i;
178: }
179:
180: #ifndef __DMSDOS_LIB__
181: void do_spc_init(void)
182: { /* first call of DMSDOS filesystem, initialising variables */
183: int i;
184:
185: printk(KERN_NOTICE "DMSDOS CVF-FAT extension version %d.%d.%d" DMSDOS_VLT
186: " compiled " __DATE__ " " __TIME__ " with options:"
187: #ifndef DBL_WRITEACCESS
188: " read-only"
189: #else
190: " read-write"
191: #endif
192: #ifdef USE_XMALLOC
193: ", xmalloc"
194: #else
195: #ifdef USE_VMALLOC
196: ", vmalloc"
197: #else
198: ", kmalloc"
199: #endif
200: #endif
201: #ifdef DMSDOS_USE_READPAGE
202: ", readpage"
203: #endif
204: #ifdef USE_READA_LIST
205: ", reada list"
206: #endif
207: #ifdef INTERNAL_DAEMON
208: ", internal daemon"
209: #endif
210: #ifdef DMSDOS_CONFIG_DBLSP_DRVSP
211: ", doublespace/drivespace(<3)"
212: #endif
213: #ifdef DMSDOS_CONFIG_DRVSP3
214: ", drivespace 3"
215: #endif
216: #ifdef DMSDOS_CONFIG_STAC3
217: ", stacker 3"
218: #endif
219: #ifdef DMSDOS_CONFIG_STAC4
220: ", stacker 4"
221: #endif
222: "\n",
223: DMSDOS_MAJOR,DMSDOS_MINOR,DMSDOS_ACT_REL);
224:
225: /* init cluster cache */
226: ccache_init();
227:
228: /* no this is done by mount ... and removed by unmount
229: otherwise the module cannot be unloaded again if the
230: internal daemon is running
231: init_daemon();
232: */
233:
234: #ifdef USE_READA_LIST
235: init_reada_list();
236: #endif
237:
238: for(i=0;i<MDFATCACHESIZE;++i)
239: { mdfat[i].a_time=0;
240: mdfat[i].a_acc=0;
241: mdfat[i].a_buffer=NULL;
242: }
243: for(i=0;i<DFATCACHESIZE;++i)
244: { dfat[i].a_time=0;
245: dfat[i].a_acc=0;
246: dfat[i].a_buffer=NULL;
247: }
248: for(i=0;i<BITFATCACHESIZE;++i)
249: { bitfat[i].a_time=0;
250: bitfat[i].a_acc=0;
251: bitfat[i].a_buffer=NULL;
252: }
253: }
254:
255: void do_spc_exit(void)
256: {
257: force_exit_daemon();
258: }
259: #endif
260:
261: #ifdef DMSDOS_CONFIG_DBL
262: int detect_dblspace(struct super_block*sb)
263: { struct buffer_head*bh;
264:
265: MOD_INC_USE_COUNT;
1.1.1.2 ! root 266: bh=raw_bread(sb,0);
1.1 root 267: if(bh==NULL)
268: { printk(KERN_ERR "DMSDOS: unable to read super block\n");
269: MOD_DEC_USE_COUNT;
270: return 0;
271: }
272: if(strncmp(bh->b_data+3,"MSDBL6.0",8)==0
273: ||strncmp(bh->b_data+3,"MSDSP6.0",8)==0)
274: { raw_brelse(sb,bh);
275: MOD_DEC_USE_COUNT;
276: return 1;
277: }
278: raw_brelse(sb,bh);
279: MOD_DEC_USE_COUNT;
280: return 0;
281: }
282:
1.1.1.2 ! root 283: /* setup fresh dblsb structure */
! 284: Dblsb* malloc_dblsb(void)
! 285: { Dblsb*dblsb;
! 286:
! 287: dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL);
! 288: if(dblsb==NULL)return NULL;
! 289: dblsb->mdfat_alloc_semp=NULL;
! 290:
! 291: return dblsb;
! 292: }
! 293:
! 294: /* ensure all memory is released */
! 295: void free_dblsb(Dblsb*dblsb)
! 296: { if(dblsb==NULL)return;
! 297: if(dblsb->mdfat_alloc_semp)
! 298: { kfree(dblsb->mdfat_alloc_semp);
! 299: dblsb->mdfat_alloc_semp=NULL;
! 300: }
! 301: kfree(dblsb);
! 302: }
! 303:
1.1 root 304: int mount_dblspace(struct super_block*sb,char*options)
305: { struct buffer_head*bh;
306: struct buffer_head*bh2;
307: int i,mdfatb,fatb;
308: unsigned int version_flag;
309: unsigned char * pp;
310: Dblsb* dblsb;
311: int repair=0;
312: int mdrc,m_sector=0;
313:
314: MOD_INC_USE_COUNT;
315: LOG_REST("DMSDOS: dblspace/drvspace module mounting...\n");
1.1.1.2 ! root 316:
! 317: dblsb=malloc_dblsb();
1.1 root 318: if(dblsb==NULL)
319: { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n");
320: MOD_DEC_USE_COUNT;
321: return -1;
322: }
323: MSDOS_SB(sb)->private_data=dblsb;
324:
325: #ifdef __KERNEL__
326: { struct semaphore* sem;
327:
328: sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL);
329: if(sem==NULL)
330: { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n");
1.1.1.2 ! root 331: free_dblsb(dblsb);
! 332: MSDOS_SB(sb)->private_data=NULL;
1.1 root 333: MOD_DEC_USE_COUNT;
334: return -1;
335: }
1.1.1.2 ! root 336: init_MUTEX(sem);
1.1 root 337: dblsb->mdfat_alloc_semp=sem;
338: }
339: #endif
1.1.1.2 ! root 340:
1.1 root 341: dblsb->s_comp=GUESS;
342: dblsb->s_cfaktor=DEFAULT_CF;
343:
344: if(parse_dmsdos_options(options,dblsb,&repair))
345: {
1.1.1.2 ! root 346: free_dblsb(dblsb);
! 347: MSDOS_SB(sb)->private_data=NULL;
! 348: MOD_DEC_USE_COUNT;
! 349: return -1;
! 350: }
! 351:
! 352: dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2;
! 353:
! 354: bh=raw_bread(sb,0);
! 355: if(bh==NULL)
! 356: { printk(KERN_ERR "DMSDOS: unable to read super block\n");
! 357: free_dblsb(dblsb);
! 358: MSDOS_SB(sb)->private_data=NULL;
! 359: MOD_DEC_USE_COUNT;
! 360: return -1;
! 361: }
! 362: if(strncmp(bh->b_data+3,"MSDBL6.0",8)&&strncmp(bh->b_data+3,"MSDSP6.0",8))
! 363: { printk(KERN_ERR "DMSDOS: MSDBL/MSDSP signature not found, CVF skipped\n");
1.1 root 364: raw_brelse(sb,bh);
1.1.1.2 ! root 365: free_dblsb(dblsb);
! 366: MSDOS_SB(sb)->private_data=NULL;
1.1 root 367: MOD_DEC_USE_COUNT;
368: return -1;
369: }
370:
371: if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY;
372: printk(KERN_INFO "DMSDOS: mounting CVF on device 0x%x %s...\n",
373: sb->s_dev,
374: dblsb->s_comp==READ_ONLY?"read-only":"read-write");
375:
376: /* dblspace correction was relocated. Pavel */
377: dblsb->s_dataend-=1;
378:
379: pp=&(bh->b_data[45]);
380: dblsb->s_dcluster=CHS(pp);
381: if(dblsb->s_dcluster&0x8000)dblsb->s_dcluster|=0xffff0000;
382: pp=&(bh->b_data[36]);
383: dblsb->s_mdfatstart=CHS(pp)+1;
384: pp=&(bh->b_data[17]);
385: dblsb->s_rootdirentries=CHS(pp);
386: dblsb->s_sectperclust=((unsigned long)(bh->b_data[13]));
387: dblsb->s_spc_bits=ilog2(dblsb->s_sectperclust);
388: pp=&(bh->b_data[39]);i=CHS(pp);/*i=res0*/
389: dblsb->s_bootblock=i;
390: pp=&(bh->b_data[14]);
391: dblsb->s_fatstart=i+CHS(pp);
392: pp=&(bh->b_data[41]);
393: dblsb->s_rootdir=i+CHS(pp);
394: pp=&(bh->b_data[43]);
395: dblsb->s_datastart=i+CHS(pp)+2;
396: dblsb->s_2nd_fat_offset=0; /* dblsp doesn't have a second fat */
397: dblsb->s_cvf_version=DBLSP;
398: version_flag=bh->b_data[51];
399: if(version_flag==2)dblsb->s_cvf_version=DRVSP;
400: if(version_flag==3||dblsb->s_sectperclust>16)dblsb->s_cvf_version=DRVSP3;
401: if(version_flag>3)printk(KERN_WARNING "DMSDOS: strange version flag %d, assuming 0.\n",
402: version_flag);
403:
404: #ifndef DMSDOS_CONFIG_DBLSP_DRVSP
405: if(dblsb->s_cvf_version<=DRVSP)
406: { printk(KERN_ERR "DMSDOS: support for doublespace/drivespace(<3) not compiled in.\n");
407: raw_brelse(sb,bh);
1.1.1.2 ! root 408: free_dblsb(dblsb);
! 409: MSDOS_SB(sb)->private_data=NULL;
1.1 root 410: MOD_DEC_USE_COUNT;
411: return -1;
412: }
413: #endif
414: #ifndef DMSDOS_CONFIG_DRVSP3
415: if(dblsb->s_cvf_version==DRVSP3)
416: { printk(KERN_ERR "DMSDOS: support for drivespace 3 not compiled in.\n");
417: raw_brelse(sb,bh);
1.1.1.2 ! root 418: free_dblsb(dblsb);
! 419: MSDOS_SB(sb)->private_data=NULL;
1.1 root 420: MOD_DEC_USE_COUNT;
421: return -1;
422: }
423: #endif
424:
425: bh2=raw_bread(sb,dblsb->s_bootblock);
426: if(bh2==NULL)
427: { printk(KERN_ERR "DMSDOS: unable to read emulated boot block\n");
428: raw_brelse(sb,bh);
1.1.1.2 ! root 429: free_dblsb(dblsb);
! 430: MSDOS_SB(sb)->private_data=NULL;
1.1 root 431: MOD_DEC_USE_COUNT;
432: return -1;
433: }
434: pp=&(bh2->b_data[57]);
435: if(CHL(pp)==0x20203631)dblsb->s_16bitfat=1;
436: else if(CHL(pp)==0x20203231)dblsb->s_16bitfat=0;
437: else if(CHL(pp)==0x20203233)
438: { printk(KERN_ERR "DMSDOS: CVF has FAT32 signature, not mounted. Please report this.\n");
439: raw_brelse(sb,bh2);
440: raw_brelse(sb,bh);
1.1.1.2 ! root 441: free_dblsb(dblsb);
! 442: MSDOS_SB(sb)->private_data=NULL;
1.1 root 443: MOD_DEC_USE_COUNT;
444: return -1;
445: }
446: else
447: { pp=&(bh->b_data[62]);
448: dblsb->s_16bitfat=(CHS(pp)>32) ? 1 : 0;
449: printk(KERN_WARNING "DMSDOS: FAT bit size not recognized, guessed %d bit\n",
450: CHS(pp)>32 ? 16 : 12 );
451: }
452: raw_brelse(sb,bh2);
453:
454: /* try to verify correct end of CVF */
455: mdrc=0;
456: for(i=-1;i<=1;++i)
457: { bh2=raw_bread(sb,dblsb->s_dataend+i);
458: if(bh2==NULL)
459: { LOG_REST("DMSDOS: MDR test breaks at i=%d\n",i);
460: break;
461: }
462: if(strcmp(bh2->b_data,"MDR")==0)
463: { ++mdrc;
464: m_sector=dblsb->s_dataend+i;
465: LOG_REST("DMSDOS: MDR signature found at sector %d\n",m_sector);
466: }
467: raw_brelse(sb,bh2);
468: }
469: if(mdrc!=1)
470: printk(KERN_WARNING "DMSDOS: could not find MDR signature or found more than one, mdrc=%d (ignored)\n",
471: mdrc);
472: else
473: { if(dblsb->s_dataend!=m_sector-1)
474: { LOG_REST("DMSDOS: dataend corrected due to MDR signature old=%d new=%d\n",
475: dblsb->s_dataend,m_sector-1);
476: dblsb->s_dataend=m_sector-1;
477: }
478: }
479:
480: dblsb->s_full=0;
481:
482: /* calculate maximum cluster nr (fixes lost cluster messages) */
483: mdfatb=(dblsb->s_bootblock-dblsb->s_mdfatstart);
484: mdfatb*=((dblsb->s_sectperclust>16)?102:128);
485: mdfatb-=dblsb->s_dcluster;
486: fatb=512*(dblsb->s_rootdir-dblsb->s_fatstart);
487: if(dblsb->s_16bitfat)fatb/=2; else fatb=(2*fatb)/3;
488: dblsb->s_max_cluster=((mdfatb<fatb)?mdfatb:fatb)-1;
489: if(dblsb->s_16bitfat)
490: { if(dblsb->s_max_cluster>0xFFF6)dblsb->s_max_cluster=0xFFF6;
491: }
492: else
493: { if(dblsb->s_max_cluster>0xFF6)dblsb->s_max_cluster=0xFF6;
494: }
495:
496: /* adapt max_cluster according to dos' limits */
497: dblsb->s_max_cluster2=dblsb->s_max_cluster;
498: pp=&(bh->b_data[32]);
499: i=CHL(pp);
500: pp=&(bh->b_data[22]);
501: i-=CHS(pp);
502: pp=&(bh->b_data[14]);
503: i-=CHS(pp);
504: i-=dblsb->s_rootdirentries>>4;
505: /*i=(i>>4)+1;*/
506: i=(i/dblsb->s_sectperclust)+1;
507: if(i<=dblsb->s_max_cluster)
508: { dblsb->s_max_cluster=i;
509: }
510: else
511: { printk(KERN_WARNING "DMSDOS: dos max_cluster=%d too large, cutting to %d.\n",
512: i,dblsb->s_max_cluster);
513: }
514:
515: LOG_REST("DMSDOS: dcluster=%d\n",dblsb->s_dcluster);
516: LOG_REST("DMSDOS: mdfatstart=%d\n",dblsb->s_mdfatstart);
517: LOG_REST("DMSDOS: rootdirentries=%d\n",dblsb->s_rootdirentries);
518: LOG_REST("DMSDOS: sectperclust=%d\n",dblsb->s_sectperclust);
519: LOG_REST("DMSDOS: fatstart=%d\n",dblsb->s_fatstart);
520: LOG_REST("DMSDOS: rootdir=%d\n",dblsb->s_rootdir);
521: LOG_REST("DMSDOS: %d bit FAT\n",dblsb->s_16bitfat ? 16 : 12);
522:
523: dblsb->s_lastnear=0;
524: dblsb->s_lastbig=0;
525: dblsb->s_free_sectors=-1; /* -1 means unknown */
526:
527: /* error test (counts sectors) */
528: if(repair!=-1) /* repair==-1 means do not even check */
529: {
530: i=simple_check(sb,repair&1);
531: if(i==-1||i==-2)
532: { printk(KERN_WARNING "DMSDOS: CVF has serious errors or compatibility problems, setting to read-only.\n");
533: dblsb->s_comp=READ_ONLY;
534: }
535: if(i==-3)
536: { if(repair&2)
537: { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, ignored.\n");
538: }
539: else
540: { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, setting to read-only.\n");
541: dblsb->s_comp=READ_ONLY;
542: }
543: }
544: }
545:
546: /* if still unknown then count now */
547: if(dblsb->s_free_sectors<0)check_free_sectors(sb);
548:
549: /* print doublespace version */
550: if(dblsb->s_cvf_version==DBLSP&&dblsb->s_sectperclust==16)
551: { printk(KERN_INFO "DMSDOS: CVF is in doublespace format (version 1).\n");
552: }
553: else if(dblsb->s_cvf_version==DRVSP&&dblsb->s_sectperclust==16)
554: { printk(KERN_INFO "DMSDOS: CVF is in drivespace format (version 2).\n");
555: }
556: else if(dblsb->s_cvf_version==DRVSP3&&dblsb->s_sectperclust==64)
557: { printk(KERN_INFO "DMSDOS: CVF is in drivespace 3 format.\n");
558: }
559: else
560: { printk(KERN_INFO "DMSDOS: CVF is in unknown (new?) format, please report.\n");
561: printk(KERN_INFO "DMSDOS: version_flag=%d sectperclust=%d\n",version_flag,
562: dblsb->s_sectperclust);
563: printk(KERN_NOTICE "DMSDOS: CVF set to read-only.\n");
564: dblsb->s_comp=READ_ONLY;
565: }
566:
567: raw_brelse(sb,bh);
568:
569: /* set some msdos fs important stuff */
570: MSDOS_SB(sb)->dir_start=FAKED_ROOT_DIR_OFFSET;
571: MSDOS_SB(sb)->dir_entries=dblsb->s_rootdirentries;
572: MSDOS_SB(sb)->data_start=FAKED_DATA_START_OFFSET; /*begin of virtual cluster 2*/
573: MSDOS_SB(sb)->clusters=dblsb->s_max_cluster;
574: if(MSDOS_SB(sb)->fat_bits!=dblsb->s_16bitfat?16:12)
575: { LOG_REST("DMSDOS: fat bit size mismatch in fat driver, trying to correct\n");
576: MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12;
577: }
578: MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust;
1.1.1.2 ! root 579: #ifdef HAS_SB_CLUSTER_BITS
! 580: for(MSDOS_SB(sb)->cluster_bits=0;
! 581: (1<<MSDOS_SB(sb)->cluster_bits)<MSDOS_SB(sb)->cluster_size;)
! 582: MSDOS_SB(sb)->cluster_bits++;
! 583: MSDOS_SB(sb)->cluster_bits+=SECTOR_BITS;
! 584: #endif
1.1 root 585:
586: /* these *must* always match */
587: if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY;
588:
589: /* we allow using the daemon - calling this more than once doesn't matter */
590: init_daemon();
591:
592: return 0;
593: }
594: #endif
595:
596: int unmount_dblspace(struct super_block*sb)
597: { int j;
598: Dblsb*dblsb=MSDOS_SB(sb)->private_data;
599:
600: LOG_REST("DMSDOS: CVF on device 0x%x unmounted.\n",sb->s_dev);
601:
602: /* discard/write cached clusters */
603: free_ccache_dev(sb);
604: /* the same for the daemon if it is running */
605: clear_list_dev(sb);
606:
607: #ifdef DMSDOS_CONFIG_STAC
608: /* mark stacker bitfat as up to date and unmounted */
609: if(dblsb->s_cvf_version>=STAC3)
610: stac_bitfat_state(sb,1);
611: #endif
612:
613: /* kill buffers used by unmounted cvf */
614: for(j=0;j<MDFATCACHESIZE;++j)
615: { if(mdfat[j].a_buffer!=NULL)
616: { if(mdfat[j].a_sb->s_dev==sb->s_dev)
617: { raw_brelse(sb,mdfat[j].a_buffer);
618: mdfat[j].a_buffer=NULL;
619: }
620: mdfat[j].a_time=0;
621: mdfat[j].a_acc=0;
622: }
623: }
624: for(j=0;j<DFATCACHESIZE;++j)
625: { if(dfat[j].a_buffer!=NULL)
626: { if(dfat[j].a_sb->s_dev==sb->s_dev)
627: { raw_brelse(sb,dfat[j].a_buffer);
628: dfat[j].a_buffer=NULL;
629: }
630: dfat[j].a_time=0;
631: dfat[j].a_acc=0;
632: }
633: }
634: for(j=0;j<BITFATCACHESIZE;++j)
635: { if(bitfat[j].a_buffer!=NULL)
636: { if(bitfat[j].a_sb->s_dev==sb->s_dev)
637: { raw_brelse(sb,bitfat[j].a_buffer);
638: bitfat[j].a_buffer=NULL;
639: }
640: bitfat[j].a_time=0;
641: bitfat[j].a_acc=0;
642: }
643: }
644:
645: #ifdef __KERNEL__
646: #ifdef USE_READA_LIST
647: /* throw away all stacked reada entries for this dev */
648: kill_reada_list_dev(sb->s_dev);
649: #endif
650: /* this is unused in the library */
1.1.1.2 ! root 651: /* looks like we don't need this here... */
! 652: /*kfree(dblsb->mdfat_alloc_semp);*/
! 653: /*dblsb->mdfat_alloc_semp=NULL;*/
1.1 root 654: #endif
1.1.1.2 ! root 655: /*kfree(MSDOS_SB(sb)->private_data);*/
! 656: free_dblsb(dblsb);
1.1 root 657: MSDOS_SB(sb)->private_data=NULL;
658: /*MSDOS_SB(sb)->cvf_format=NULL;*/ /*this causes a segfault in
659: dec_cvf_format_use_count_by_version*/
660: exit_daemon();
661: MOD_DEC_USE_COUNT;
662: return 0;
663: }
664:
665: #ifdef DMSDOS_CONFIG_STAC
666: int detect_stacker(struct super_block*sb)
667: { struct buffer_head*bh;
668:
669: MOD_INC_USE_COUNT;
670: bh=raw_bread(sb,0);
671: if(bh==NULL)
672: { printk(KERN_ERR "DMSDOS: unable to read super block\n");
673: MOD_DEC_USE_COUNT;
674: return 0;
675: }
676: if(strncmp(bh->b_data,"STACKER",7)==0)
677: { raw_brelse(sb,bh);
678: MOD_DEC_USE_COUNT;
679: return 1;
680: }
681: raw_brelse(sb,bh);
682: MOD_DEC_USE_COUNT;
683: return 0;
684: }
685:
686: int mount_stacker(struct super_block*sb,char*options)
687: {
688: struct buffer_head*bh;
689: struct buffer_head*bh2;
690: int i;
691: unsigned char * pp, *p;
692: unsigned char buf[512];
693: unsigned char b,c;
694: int SectSize, ClustSects, ClustSize, ReservSects, FATCnt;
695: int RootDirEnt, TotalSects, FATSize, HidenSects, FirstRootSect;
696: int FirstDataSect, FirstDataSect2, FAT12, FirstFATSect;
697: int StacVersion;
698: /* parameters of virtual DOS drive */
699: int BB_FirstDataSect, BB_ClustCnt, BB_SectSize, BB_TotalSects;
700: Dblsb*dblsb;
701: int repair=0;
702:
703: MOD_INC_USE_COUNT;
704: LOG_REST("DMSDOS: stacker 3/4 module mounting...\n");
705:
1.1.1.2 ! root 706: dblsb=malloc_dblsb();
! 707: if(dblsb==NULL)
! 708: { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n");
! 709: MOD_DEC_USE_COUNT;
! 710: return -1;
! 711: }
! 712: MSDOS_SB(sb)->private_data=dblsb;
! 713:
! 714: #ifdef __KERNEL__
! 715: { struct semaphore* sem;
! 716:
! 717: sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL);
! 718: if(sem==NULL)
! 719: { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n");
! 720: free_dblsb(dblsb);
! 721: MSDOS_SB(sb)->private_data=NULL;
! 722: MOD_DEC_USE_COUNT;
! 723: return -1;
! 724: }
! 725: init_MUTEX(sem);
! 726: dblsb->mdfat_alloc_semp=sem;
! 727: }
! 728: #endif
! 729:
! 730: dblsb->s_comp=GUESS;
! 731: dblsb->s_cfaktor=DEFAULT_CF;
! 732:
! 733: if(parse_dmsdos_options(options,dblsb,&repair))
! 734: {
! 735: free_dblsb(dblsb);
! 736: MSDOS_SB(sb)->private_data=NULL;
! 737: MOD_DEC_USE_COUNT;
! 738: return -1;
! 739: }
! 740:
! 741: dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2;
! 742:
1.1 root 743: LOG_REST("DMSDOS: reading super block...\n");
744: bh=raw_bread(sb,0);
745: if(bh==NULL)
746: { printk(KERN_ERR "DMSDOS: unable to read super block of CVF\n");
1.1.1.2 ! root 747: free_dblsb(dblsb);
! 748: MSDOS_SB(sb)->private_data=NULL;
1.1 root 749: MOD_DEC_USE_COUNT;
750: return -1;
751: }
752: LOG_REST("DMSDOS: super block read finished\n");
753: pp=&(bh->b_data[0]);
754: if(strncmp(pp,"STACKER",7)!=0)
755: { printk(KERN_ERR "DMSDOS: STACKER signature not found\n");
756: raw_brelse(sb,bh);
1.1.1.2 ! root 757: free_dblsb(dblsb);
! 758: MSDOS_SB(sb)->private_data=NULL;
1.1 root 759: MOD_DEC_USE_COUNT;
760: return -1;
761: }
762:
763: /* copy block (must not directly modify kernel buffer!!!) */
764: memcpy(buf,bh->b_data,SECTOR_SIZE);
765: /* decode super block */
766: for(i=0x30,p=buf+0x50,b=buf[0x4c];i--;p++)
767: { b=0xc4-b;
768: b=b<0x80?b*2:b*2+1;
769: b^=c=*p;
770: *p=b;b=c;
771: }
772: if(buf[0x4e]!=0xa||buf[0x4f]!=0x1a)
773: { printk(KERN_ERR "DMSDOS: Stacker 0x1A0A signature not found\n");
774: raw_brelse(sb,bh);
1.1.1.2 ! root 775: free_dblsb(dblsb);
! 776: MSDOS_SB(sb)->private_data=NULL;
1.1 root 777: MOD_DEC_USE_COUNT;
778: return -1;
779: }
780:
781: if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY;
782: printk(KERN_NOTICE "DMSDOS: mounting CVF on device 0x%x %s...\n",
783: sb->s_dev,
784: dblsb->s_comp==READ_ONLY?"read-only":"read-write");
785:
786: /* extract important info */
787: pp=&(buf[0x6C]);
788: TotalSects=CHL(pp);
789: pp=&(buf[0x70]);
790: dblsb->s_bootblock=CHS(pp);
791: pp=&(buf[0x74]);
792: dblsb->s_mdfatstart=CHS(pp); /* here it's AMAP start !!! */
793: pp=&(buf[0x76]);
794: FirstFATSect=dblsb->s_fatstart=CHS(pp);
795: pp=&(buf[0x7a]);
796: FirstDataSect2=dblsb->s_datastart=CHS(pp);
797: pp=&(buf[0x60]);
798: StacVersion=CHS(pp);
799: if(StacVersion>=410)dblsb->s_cvf_version=STAC4;
800: else dblsb->s_cvf_version=STAC3;
801: /* if(buf[0x64]==9)dblsb->s_cvf_version=STAC4;
802: else dblsb->s_cvf_version=STAC3; */
803:
804: #ifndef DMSDOS_CONFIG_STAC3
805: if(dblsb->s_cvf_version==STAC3)
806: { printk(KERN_ERR "DMSDOS: support for stacker 3 not compiled in.\n");
807: raw_brelse(sb,bh);
1.1.1.2 ! root 808: free_dblsb(dblsb);
! 809: MSDOS_SB(sb)->private_data=NULL;
1.1 root 810: MOD_DEC_USE_COUNT;
811: return -1;
812: }
813: #endif
814: #ifndef DMSDOS_CONFIG_STAC4
815: if(dblsb->s_cvf_version==STAC4)
816: { printk(KERN_ERR "DMSDOS: support for stacker 4 not compiled in.\n");
817: raw_brelse(sb,bh);
1.1.1.2 ! root 818: free_dblsb(dblsb);
! 819: MSDOS_SB(sb)->private_data=NULL;
1.1 root 820: MOD_DEC_USE_COUNT;
821: return -1;
822: }
823: #endif
824:
825: /* now we need the boot block */
826: bh2=raw_bread(sb,dblsb->s_bootblock);
827: if(bh2==NULL)
828: { printk(KERN_ERR "DMSDOS: unable to read emulated boot block of CVF\n");
829: raw_brelse(sb,bh);
1.1.1.2 ! root 830: free_dblsb(dblsb);
! 831: MSDOS_SB(sb)->private_data=NULL;
1.1 root 832: MOD_DEC_USE_COUNT;
833: return -1;
834: }
835: /* read values */
836: dblsb->s_sectperclust=bh2->b_data[0xd];
837: dblsb->s_spc_bits=ilog2(dblsb->s_sectperclust);
838: pp=&(bh2->b_data[0x11]);
839: dblsb->s_rootdirentries=CHS(pp);
840:
841: pp=&(buf[0x62]); SectSize=CHS(pp);
842: pp=&(bh2->b_data[0xB]); BB_SectSize=CHS(pp);
843: if(SectSize!=SECTOR_SIZE||BB_SectSize!=SECTOR_SIZE)
844: printk(KERN_WARNING "DMSDOS: Stacker sector size not 512 bytes, hmm...\n");
845: ClustSects=bh2->b_data[0xD];
846: ClustSize=ClustSects*SectSize;
847: pp=&(bh2->b_data[0xE]); ReservSects=CHS(pp);
848: FATCnt=bh2->b_data[0x10];
849: pp=&(bh2->b_data[0x11]); RootDirEnt=CHS(pp);
850: pp=&(bh2->b_data[0x13]); BB_TotalSects=CHS(pp);
851: if(!BB_TotalSects)
852: { pp=&(bh2->b_data[0x20]); BB_TotalSects=CHL(pp);};
853: pp=&(bh2->b_data[0x16]); FATSize=CHS(pp);
854: pp=&(bh2->b_data[0x1B]); HidenSects=CHS(pp);
855: if(BB_SectSize!=SectSize)printk(KERN_WARNING "DMSDOS: Inconsistent sector length\n");
856: FirstRootSect=FirstFATSect+3*FATCnt*FATSize;
857:
858: dblsb->s_2nd_fat_offset=3*(FATCnt-1)*FATSize;
859:
860: /* Number of sectors in root directory */
861: FirstDataSect=((long)RootDirEnt*0x20+SectSize-1)/SectSize;
862: /* Emulated data start sector for DOS */
863: BB_FirstDataSect=FirstDataSect+FATCnt*FATSize+ReservSects;
864: /* ??? +HidenSects; */
865: /* Real data start sector */
866: FirstDataSect+=FirstRootSect;
867: /* Counting BB_ClustCnt from emulated boot block */
868: BB_ClustCnt=(BB_TotalSects-BB_FirstDataSect)/ClustSects;
869: if(BB_ClustCnt>=0xFED)FAT12=0; else FAT12=1;
870: if(BB_ClustCnt<2||BB_ClustCnt>0xfff7)
871: { printk(KERN_ERR "DMSDOS: BB_ClustCnt=0x%x impossible (FAT32?)\n",BB_ClustCnt);
872: raw_brelse(sb,bh2);
873: raw_brelse(sb,bh);
1.1.1.2 ! root 874: free_dblsb(dblsb);
! 875: MSDOS_SB(sb)->private_data=NULL;
1.1 root 876: MOD_DEC_USE_COUNT;
877: return -1;
878: }
879: if(FirstDataSect2!=FirstDataSect)
880: { printk(KERN_WARNING "DMSDOS: Inconsistent first data sector number. Mounting READ ONLY.\n");
881: printk(KERN_WARNING "In header found %u but computed %u\n",(unsigned)FirstDataSect2,(unsigned)FirstDataSect);
882: dblsb->s_comp=READ_ONLY;
883: }
884:
885: LOG_REST("DMSDOS: Stac version %u start of FAT %u, root %u, data %u; FATSize %u; FATCnt %u; clusts %u; sects %u\n",
886: (unsigned)StacVersion,(unsigned)FirstFATSect,(unsigned)FirstRootSect,
887: (unsigned)FirstDataSect,(unsigned)FATSize,(unsigned)FATCnt,
888: (unsigned)BB_ClustCnt,(unsigned)BB_TotalSects);
889:
890: /* try dos standard method to detect fat bit size - does not work */
891: /* pp=&(bh2->b_data[57]); */
892: /* if(CHL(pp)==0x20203631)dblsb->s_16bitfat=1; */
893: /* else if(CHL(pp)==0x20203231)dblsb->s_16bitfat=0; else */
894:
895: /* used only stacker method for fat entry size now */
896: dblsb->s_16bitfat=FAT12? 0: 1;
897: LOG_REST("DMSDOS: FAT bit size of CVF is %d bit\n",
898: (FAT12) ? 12 : 16 );
899:
900: /* check if clusters fits in FAT */
901: if(BB_ClustCnt+2>(FAT12?(SECTOR_SIZE*FATSize*2)/3:(SECTOR_SIZE*FATSize)/2))
902: { printk(KERN_WARNING "DMSDOS: FAT size does not match cluster count. Mounting READ ONLY.\n");
903: dblsb->s_comp=READ_ONLY;
904: }
905:
906: /* check size of physical media against stacvol parameters */
907: if((TotalSects<=0)||(TotalSects-1)>dblsb->s_dataend)
908: { printk(KERN_WARNING "DMSDOS: CVF is shorter about %d sectors. Mounting READ ONLY.\n",
909: (int)TotalSects-1-dblsb->s_dataend);
910: dblsb->s_comp=READ_ONLY;
911: }
912: else if((TotalSects-1)<dblsb->s_dataend)
913: { printk(KERN_INFO "DMSDOS: CVF end padding %d sectors.\n",
914: (int)dblsb->s_dataend-TotalSects+1);
915: dblsb->s_dataend=TotalSects-1;
916: }
917:
918: raw_brelse(sb,bh2);
919: dblsb->s_full=0;
920: raw_brelse(sb,bh);
921:
922: dblsb->s_rootdir=FirstRootSect;
923: dblsb->s_max_cluster=dblsb->s_max_cluster2=BB_ClustCnt+1;
924:
925: LOG_REST("DMSDOS: mdfatstart=%d\n",dblsb->s_mdfatstart);
926: LOG_REST("DMSDOS: rootdirentries=%d\n",dblsb->s_rootdirentries);
927: LOG_REST("DMSDOS: sectperclust=%d\n",dblsb->s_sectperclust);
928: LOG_REST("DMSDOS: fatstart=%d\n",dblsb->s_fatstart);
929: LOG_REST("DMSDOS: rootdir=%d\n",dblsb->s_rootdir);
930: LOG_REST("DMSDOS: %d bit FAT\n",dblsb->s_16bitfat ? 16 : 12);
931:
932: /* allocation informations */
933: dblsb->s_lastnear=0;
934: dblsb->s_lastbig=0;
935: dblsb->s_free_sectors=-1; /* -1 means unknown */
936:
937: /* set some msdos fs important stuff */
938: MSDOS_SB(sb)->dir_start=FAKED_ROOT_DIR_OFFSET;
939: MSDOS_SB(sb)->dir_entries=dblsb->s_rootdirentries;
940: MSDOS_SB(sb)->data_start=FAKED_DATA_START_OFFSET; /*begin of virtual cluster 2*/
941: MSDOS_SB(sb)->clusters=BB_ClustCnt;
942: if(MSDOS_SB(sb)->fat_bits!=dblsb->s_16bitfat?16:12)
943: { LOG_REST("DMSDOS: fat bit size mismatch in fat driver, trying to correct\n");
944: MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12;
945: }
946: MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust;
1.1.1.2 ! root 947: #ifdef HAS_SB_CLUSTER_BITS
! 948: for(MSDOS_SB(sb)->cluster_bits=0;
! 949: (1<<MSDOS_SB(sb)->cluster_bits)<MSDOS_SB(sb)->cluster_size;)
! 950: MSDOS_SB(sb)->cluster_bits++;
! 951: MSDOS_SB(sb)->cluster_bits+=SECTOR_BITS;
! 952: #endif
1.1 root 953:
954: /* error test */
955: if(repair!=-1) /* repair==-1 means do not even check */
956: {
957: i=simple_check(sb,repair&1);
958: if(i==-1||i==-2)
959: { printk(KERN_WARNING "DMSDOS: CVF has serious errors or compatibility problems, setting to read-only.\n");
960: dblsb->s_comp=READ_ONLY;
961: }
962: if(i==-3)
963: { if(repair&2)
964: { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, ignored.\n");
965: }
966: else
967: { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, setting to read-only.\n");
968: dblsb->s_comp=READ_ONLY;
969: }
970: }
971: }
972:
973: /* print stacker version */
974: if(dblsb->s_cvf_version==STAC3)
975: { printk(KERN_NOTICE "DMSDOS: CVF is in stacker 3 format.\n");
976: }
977: else if(dblsb->s_cvf_version==STAC4)
978: { printk(KERN_NOTICE "DMSDOS: CVF is in stacker 4 format.\n");
979: }
980:
981: /* if still unknown then count now */
982: if(dblsb->s_free_sectors<0)check_free_sectors(sb);
983:
984: /* these *must* always match */
985: if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY;
986:
987: /* mark stacker bitfat as mounted and changing */
988: /* if not regulary unmounted, it must be repaired before */
989: /* next write access */
990: if((sb->s_flags&MS_RDONLY)==0)stac_bitfat_state(sb,2);
991:
992: /* we allow using the daemon - calling this more than once doesn't matter */
993: init_daemon();
994:
995: return 0;
996: }
997: #endif
998:
999: #ifdef DMSDOS_USE_READPAGE
1000: #define READPAGE dblspace_readpage
1001: #define MMAP NULL
1002: #define RMFLAG CVF_USE_READPAGE
1003: #else
1004: #define READPAGE NULL
1005: #define MMAP dblspace_mmap
1006: #define RMFLAG 0
1007: #endif
1008:
1009: #ifndef __DMSDOS_LIB__
1010: #ifdef DMSDOS_CONFIG_DBL
1011: struct cvf_format dblspace_format = {
1012: 0x0001, /* version id */
1013: "dblspace", /* version text */
1014: RMFLAG, /* flags */
1015: detect_dblspace, /* detect */
1016: mount_dblspace, /* mount */
1017: unmount_dblspace, /* unmount */
1018: dblspace_bread, /* bread */
1019: dblspace_getblk, /* getblk */
1020: dblspace_brelse, /* brelse */
1021: dblspace_mark_buffer_dirty, /* mark_buffer_dirty */
1022: dblspace_set_uptodate, /* set_uptodate */
1023: dblspace_is_uptodate, /* is_uptodate */
1024: dblspace_ll_rw_block, /* ll_rw_block */
1025: dblspace_fat_access, /* fat_access */
1026: NULL, /* statfs */
1027: dblspace_bmap, /* bmap */
1.1.1.2 ! root 1028: #ifndef __FOR_KERNEL_2_3_10
1.1 root 1029: dblspace_smap, /* smap */
1.1.1.2 ! root 1030: #endif
1.1 root 1031: dblspace_file_read, /* file_read */
1032: dblspace_file_write, /* file_write */
1033: MMAP, /* mmap */
1034: READPAGE, /* readpage */
1035: NULL, /* writepage */
1036: dmsdos_ioctl_dir, /* dir ioctl */
1037: dblspace_zero_new_cluster /* zero_new_cluster */
1038: };
1039: #endif
1040:
1041: #ifdef DMSDOS_CONFIG_STAC
1042: struct cvf_format stacker_format = {
1043: 0x0002, /* version id */ /**** only ****/
1044: "stacker", /* version text */ /**** these ****/
1045: RMFLAG, /* flags */
1046: detect_stacker, /* detect */ /**** four ****/
1047: mount_stacker, /* mount */ /**** differ :) ****/
1048: unmount_dblspace, /* unmount */
1049: dblspace_bread, /* bread */
1050: dblspace_getblk, /* getblk */
1051: dblspace_brelse, /* brelse */
1052: dblspace_mark_buffer_dirty, /* mark_buffer_dirty */
1053: dblspace_set_uptodate, /* set_uptodate */
1054: dblspace_is_uptodate, /* is_uptodate */
1055: dblspace_ll_rw_block, /* ll_rw_block */
1056: dblspace_fat_access, /* fat_access */
1057: NULL, /* statfs */
1058: dblspace_bmap, /* bmap */
1.1.1.2 ! root 1059: #ifndef __FOR_KERNEL_2_3_10
1.1 root 1060: dblspace_smap, /* smap */
1.1.1.2 ! root 1061: #endif
1.1 root 1062: dblspace_file_read, /* file_read */
1063: dblspace_file_write, /* file_write */
1064: MMAP, /* mmap */
1065: READPAGE, /* readpage */
1066: NULL, /* writepage */
1067: dmsdos_ioctl_dir, /* dir ioctl */
1068: dblspace_zero_new_cluster /* zero_new_cluster */
1069: };
1070: #endif
1071:
1.1.1.2 ! root 1072: int init_dmsdos(void)
1.1 root 1073: { int i;
1074:
1075: do_spc_init();
1076: #ifdef DMSDOS_CONFIG_DBL
1077: i=register_cvf_format(&dblspace_format);
1078: if(i<0)
1.1.1.2 ! root 1079: { printk(KERN_ERR "register_cvf_format failed, dmsdos not loaded successfully\n");
1.1 root 1080: do_spc_exit();
1081: return i;
1082: }
1083: #endif
1084: #ifdef DMSDOS_CONFIG_STAC
1085: i=register_cvf_format(&stacker_format);
1086: if(i<0)
1.1.1.2 ! root 1087: { printk(KERN_ERR "register_cvf_format failed, dmsdos not loaded successfully\n");
1.1 root 1088: do_spc_exit();
1089: #ifdef DMSDOS_CONFIG_DBL
1090: unregister_cvf_format(&dblspace_format);
1091: #endif
1092: return i;
1093: }
1094: #endif
1095: LOG_REST("CVF format(s) successfully registered\n");
1096:
1097: return 0;
1098: }
1099:
1.1.1.2 ! root 1100: #ifdef MODULE
! 1101: int init_module(void)
! 1102: { return init_dmsdos();
! 1103: }
! 1104:
1.1 root 1105: void cleanup_module(void)
1106: { do_spc_exit();
1107: #ifdef DMSDOS_CONFIG_DBL
1108: unregister_cvf_format(&dblspace_format);
1109: #endif
1110: #ifdef DMSDOS_CONFIG_STAC
1111: unregister_cvf_format(&stacker_format);
1112: #endif
1113: }
1.1.1.2 ! root 1114: #endif /* MODULE */
1.1 root 1115: #endif /* ifndef __DMSDOS_LIB__ */
1116:
1117: char seq[]="000000";
1118:
1119: #ifdef __DMSDOS_LIB__
1120: /* we don't need locking in the library */
1121: void lock_prseq(void) {}
1122: void unlock_prseq(void) {}
1123: #else
1.1.1.2 ! root 1124: DECLARE_MUTEX(prseq_sem); /* Must be initialized to green light */
1.1 root 1125: void lock_prseq(void) {down(&prseq_sem);}
1126: void unlock_prseq(void) {up(&prseq_sem);}
1127: #endif
1128:
1129: int log_prseq(void)
1130: { int i;
1131:
1132: lock_prseq();
1133:
1134: i=5;
1135: while(i>=0)
1136: { ++seq[i];
1137: if(seq[i]<='9')break;
1138: seq[i]='0';
1139: --i;
1140: }
1141:
1142: printk(seq);
1143:
1144: unlock_prseq();
1145:
1146: return 1;
1147: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.