xref: /illumos-gate/usr/src/uts/common/sys/fs/pc_fs.h (revision 0e42dee6)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0e42dee6Sartem  * Common Development and Distribution License (the "License").
6*0e42dee6Sartem  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*0e42dee6Sartem  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #ifndef	_SYS_FS_PC_FS_H
277c478bd9Sstevel@tonic-gate #define	_SYS_FS_PC_FS_H
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <sys/thread.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
347c478bd9Sstevel@tonic-gate extern "C" {
357c478bd9Sstevel@tonic-gate #endif
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate typedef	uint16_t	pc_cluster16_t;
387c478bd9Sstevel@tonic-gate typedef	uint32_t	pc_cluster32_t;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate  * PC (MSDOS) compatible virtual file system.
427c478bd9Sstevel@tonic-gate  *
437c478bd9Sstevel@tonic-gate  * A main goal of the implementation was to maintain statelessness
447c478bd9Sstevel@tonic-gate  * except while files are open. Thus mounting and unmounting merely
457c478bd9Sstevel@tonic-gate  * declared the file system name. The user may change disks at almost
467c478bd9Sstevel@tonic-gate  * any time without concern (just like the PC). It is assumed that when
477c478bd9Sstevel@tonic-gate  * files are open for writing the disk access light will be on, as a
487c478bd9Sstevel@tonic-gate  * warning not to change disks. The implementation must, however, detect
497c478bd9Sstevel@tonic-gate  * disk change and recover gracefully. It does this by comparing the
507c478bd9Sstevel@tonic-gate  * in core entry for a directory to the on disk entry whenever a directory
517c478bd9Sstevel@tonic-gate  * is searched. If a discrepancy is found active directories become root and
527c478bd9Sstevel@tonic-gate  * active files are marked invalid.
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * There are only two type of nodes on the PC file system; files and
557c478bd9Sstevel@tonic-gate  * directories. These are represented by two separate vnode op vectors,
567c478bd9Sstevel@tonic-gate  * and they are kept in two separate tables. Files are known by the
577c478bd9Sstevel@tonic-gate  * disk block number and block (cluster) offset of the files directory
587c478bd9Sstevel@tonic-gate  * entry. Directories are known by the starting cluster number.
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * The file system is locked for during each user operation. This is
617c478bd9Sstevel@tonic-gate  * done to simplify disk verification error conditions.
627c478bd9Sstevel@tonic-gate  *
637c478bd9Sstevel@tonic-gate  * Notes on FAT32 support
647c478bd9Sstevel@tonic-gate  * ----------------------
657c478bd9Sstevel@tonic-gate  * The basic difference between FAT32 and FAT16 is that cluster numbers are now
667c478bd9Sstevel@tonic-gate  * 32-bit instead of 16-bit. The FAT is thus an array of 32-bit cluster numbers,
677c478bd9Sstevel@tonic-gate  * and because of this the cluster size can be much smaller on a large disk
687c478bd9Sstevel@tonic-gate  * (4k, say, on a 1 Gig drive instead of 16k). Unfortunately, the FAT is not
697c478bd9Sstevel@tonic-gate  * the only place cluster numbers are stored - the starting cluster is stored
707c478bd9Sstevel@tonic-gate  * in the directory entry for a file, and of course it's only 16-bit. Luckily,
717c478bd9Sstevel@tonic-gate  * there's a 16-bit OS/2 Extended Attribute field that is now used to store the
727c478bd9Sstevel@tonic-gate  * upper 16-bits of the starting cluster number.
737c478bd9Sstevel@tonic-gate  *
747c478bd9Sstevel@tonic-gate  * Most of the FAT32 changes to pcfs are under 'if it's FAT32' to minimize the
757c478bd9Sstevel@tonic-gate  * effect on non-FAT32 filesystems (and still share the code), except for the
767c478bd9Sstevel@tonic-gate  * starting cluster changes. It seemed easier to make common functions to
777c478bd9Sstevel@tonic-gate  * handle that.
787c478bd9Sstevel@tonic-gate  *
797c478bd9Sstevel@tonic-gate  * Other changes:
807c478bd9Sstevel@tonic-gate  *
817c478bd9Sstevel@tonic-gate  *     1. FAT32 partitions are indicated by partition types 0xB and 0xC.
827c478bd9Sstevel@tonic-gate  *     2. The boot sector is now 2 sectors, to make room for FAT32 extensions.
837c478bd9Sstevel@tonic-gate  *     3. The root directory is no longer stored in a fixed location. Its'
847c478bd9Sstevel@tonic-gate  *        starting cluster is stored in the extended boot sector.
857c478bd9Sstevel@tonic-gate  *     4. "Summary information" is now stored and we need to (at least) maintain
867c478bd9Sstevel@tonic-gate  *        the number of free clusters or scandisk will be upset. Though the
877c478bd9Sstevel@tonic-gate  *        sector this info is in is pointed to by the extensions in the boot
887c478bd9Sstevel@tonic-gate  *        sector, the magic offset of this information is just that so
897c478bd9Sstevel@tonic-gate  *        far - magic. 0x1e0.
907c478bd9Sstevel@tonic-gate  *     5. FAT32 can use the alternate FAT. But we don't.
917c478bd9Sstevel@tonic-gate  *
927c478bd9Sstevel@tonic-gate  * FAT32 also exposed a latent bug: we bread() each copy of the FAT in one
937c478bd9Sstevel@tonic-gate  * big chunk.  This is not good on a large FAT32 drive, such as a 1 Gig
947c478bd9Sstevel@tonic-gate  * Jaz drive that has 4k clusters, since the FAT becomes 1 Meg in size and
957c478bd9Sstevel@tonic-gate  * bread blocks forever. So now we read the FAT in chunks.
967c478bd9Sstevel@tonic-gate  */
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * pre-FAT32 boot sector.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate struct bootsec {
1027c478bd9Sstevel@tonic-gate 	uchar_t	instr[3];
1037c478bd9Sstevel@tonic-gate 	uchar_t	version[8];
1047c478bd9Sstevel@tonic-gate 	uchar_t	bps[2];			/* bytes per sector */
1057c478bd9Sstevel@tonic-gate 	uchar_t	spcl;			/* sectors per allocation unit */
1067c478bd9Sstevel@tonic-gate 	uchar_t	res_sec[2];		/* reserved sectors, starting at 0 */
1077c478bd9Sstevel@tonic-gate 	uchar_t	nfat;			/* number of FATs */
1087c478bd9Sstevel@tonic-gate 	uchar_t	rdirents[2];		/* number of root directory entries */
1097c478bd9Sstevel@tonic-gate 	uchar_t	numsect[2];		/* old total sectors in logical image */
1107c478bd9Sstevel@tonic-gate 	uchar_t	mediadesriptor;		/* media descriptor byte */
111*0e42dee6Sartem 	ushort_t fatsec;		/* number of sectors per FAT */
1127c478bd9Sstevel@tonic-gate 	ushort_t spt;			/* sectors per track */
1137c478bd9Sstevel@tonic-gate 	ushort_t nhead;			/* number of heads */
114*0e42dee6Sartem 	uint_t	hiddensec;		/* number of hidden sectors */
1157c478bd9Sstevel@tonic-gate 	uint_t	totalsec;		/* total sectors in logical image */
1167c478bd9Sstevel@tonic-gate };
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * FAT32 volumes have a bigger boot sector. They include the normal
1207c478bd9Sstevel@tonic-gate  * boot sector.
1217c478bd9Sstevel@tonic-gate  */
1227c478bd9Sstevel@tonic-gate struct fat32_bootsec {
1237c478bd9Sstevel@tonic-gate 	struct bootsec	f_bs;
1247c478bd9Sstevel@tonic-gate 	uint32_t	f_fatlength;	/* size of FAT */
1257c478bd9Sstevel@tonic-gate 	uint16_t	f_flags;
1267c478bd9Sstevel@tonic-gate 	uint8_t		f_major;	/* major filesystem version #? */
1277c478bd9Sstevel@tonic-gate 	uint8_t		f_minor;	/* minor filesystem version #? */
1287c478bd9Sstevel@tonic-gate 	uint32_t	f_rootcluster;	/* first cluster in root directory */
1297c478bd9Sstevel@tonic-gate 	uint16_t	f_infosector;	/* where summary info is */
1307c478bd9Sstevel@tonic-gate 	uint16_t	f_backupboot;	/* backup boot sector */
1317c478bd9Sstevel@tonic-gate 	uint16_t	f_reserved2[6];
1327c478bd9Sstevel@tonic-gate };
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate #define	FAT32_FS_SIGN	0x61417272
1357c478bd9Sstevel@tonic-gate #define	FAT32_BOOT_FSINFO_OFF	0x1e0
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate  * summary information for fat32 volumes. We need to maintain fs_free_clusters
1397c478bd9Sstevel@tonic-gate  * or Microsoft Scandisk will be upset.
1407c478bd9Sstevel@tonic-gate  */
1417c478bd9Sstevel@tonic-gate struct fat32_boot_fsinfo {
1427c478bd9Sstevel@tonic-gate 	uint32_t	fs_reserved1;
1437c478bd9Sstevel@tonic-gate 	uint32_t	fs_signature;	/* 0x61417272 */
1447c478bd9Sstevel@tonic-gate 	uint32_t	fs_free_clusters;  /* # free clusters. -1 if unknown */
1457c478bd9Sstevel@tonic-gate 	uint32_t	fs_next_cluster;   /* unused by pcfs */
1467c478bd9Sstevel@tonic-gate 	uint32_t	fs_reserved2[4];
1477c478bd9Sstevel@tonic-gate };
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate #define	FSINFO_UNKNOWN	(-1)
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate struct pcfs {
1527c478bd9Sstevel@tonic-gate 	struct vfs *pcfs_vfs;		/* vfs for this fs */
1537c478bd9Sstevel@tonic-gate 	int pcfs_flags;			/* flags */
1547c478bd9Sstevel@tonic-gate 	int pcfs_ldrv;			/* logical DOS drive number */
1557c478bd9Sstevel@tonic-gate 	dev_t pcfs_xdev;		/* actual device that is mounted */
1567c478bd9Sstevel@tonic-gate 	struct vnode *pcfs_devvp;	/*   and a vnode for it */
1577c478bd9Sstevel@tonic-gate 	int pcfs_secsize;		/* sector size in bytes */
1587c478bd9Sstevel@tonic-gate 	int pcfs_spcl;			/* sectors per cluster */
1597c478bd9Sstevel@tonic-gate 	int pcfs_spt;			/* sectors per track */
1607c478bd9Sstevel@tonic-gate 	int pcfs_sdshift;		/* shift to convert sector into */
1617c478bd9Sstevel@tonic-gate 					/* DEV_BSIZE "sectors"; assume */
1627c478bd9Sstevel@tonic-gate 					/* pcfs_secsize is 2**n times of */
1637c478bd9Sstevel@tonic-gate 					/* DEV_BSIZE */
1647c478bd9Sstevel@tonic-gate 	int pcfs_fatsec;		/* number of sec per FAT */
1657c478bd9Sstevel@tonic-gate 	int pcfs_numfat;		/* number of FAT copies */
1667c478bd9Sstevel@tonic-gate 	int pcfs_rdirsec;		/* number of sec in root dir */
1677c478bd9Sstevel@tonic-gate 	daddr_t pcfs_dosstart;		/* start blkno of DOS partition */
1687c478bd9Sstevel@tonic-gate 	daddr_t pcfs_fatstart;		/* start blkno of first FAT */
1697c478bd9Sstevel@tonic-gate 	daddr_t pcfs_rdirstart;		/* start blkno of root dir */
1707c478bd9Sstevel@tonic-gate 	daddr_t pcfs_datastart;		/* start blkno of data area */
1717c478bd9Sstevel@tonic-gate 	int pcfs_clsize;		/* cluster size in bytes */
1727c478bd9Sstevel@tonic-gate 	int pcfs_ncluster;		/* number of clusters in fs */
1737c478bd9Sstevel@tonic-gate 	int pcfs_entps;			/* number of dir entry per sector */
1747c478bd9Sstevel@tonic-gate 	int pcfs_nrefs;			/* number of active pcnodes */
1757c478bd9Sstevel@tonic-gate 	int pcfs_frefs;			/* number of active file pcnodes */
1767c478bd9Sstevel@tonic-gate 	int pcfs_nxfrecls;		/* next free cluster */
1777c478bd9Sstevel@tonic-gate 	uchar_t *pcfs_fatp;		/* ptr to FAT data */
1787c478bd9Sstevel@tonic-gate 	uchar_t *pcfs_fat_changemap;	/* map of changed fat data */
1797c478bd9Sstevel@tonic-gate 	int pcfs_fatsize;		/* size of FAT data */
1807c478bd9Sstevel@tonic-gate 	int pcfs_fat_changemapsize;	/* size of FAT changemap */
1817c478bd9Sstevel@tonic-gate 	time_t pcfs_fattime;		/* time FAT becomes invalid */
1827c478bd9Sstevel@tonic-gate 	time_t pcfs_verifytime;		/* time to reverify disk */
1837c478bd9Sstevel@tonic-gate 	kmutex_t	pcfs_lock;		/* per filesystem lock */
1847c478bd9Sstevel@tonic-gate 	kthread_id_t pcfs_owner;		/* id of thread locking pcfs */
1857c478bd9Sstevel@tonic-gate 	int pcfs_count;			/* # of pcfs locks for pcfs_owner */
1867c478bd9Sstevel@tonic-gate 	struct fat32_boot_fsinfo fsinfo_native; /* native fsinfo for fat32 */
1877c478bd9Sstevel@tonic-gate 	uint32_t	f32fsinfo_sector; /* where to read/write fsinfo */
1887c478bd9Sstevel@tonic-gate 	struct pcfs *pcfs_nxt;		/* linked list of all mounts */
1897c478bd9Sstevel@tonic-gate 	int pcfs_fatjustread;		/* Used to flag a freshly found FAT */
1907c478bd9Sstevel@tonic-gate };
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate  * flags
1947c478bd9Sstevel@tonic-gate  */
1957c478bd9Sstevel@tonic-gate #define	PCFS_FATMOD	0x01		/* FAT has been modified */
1967c478bd9Sstevel@tonic-gate #define	PCFS_LOCKED	0x02		/* fs is locked */
1977c478bd9Sstevel@tonic-gate #define	PCFS_WANTED	0x04		/* locked fs is wanted */
1987c478bd9Sstevel@tonic-gate #define	PCFS_FAT16	0x400		/* 16 bit FAT */
1997c478bd9Sstevel@tonic-gate #define	PCFS_NOCHK	0x800		/* don't resync fat on error */
2007c478bd9Sstevel@tonic-gate #define	PCFS_BOOTPART	0x1000		/* boot partition type */
2017c478bd9Sstevel@tonic-gate #define	PCFS_HIDDEN	0x2000		/* show hidden files */
2027c478bd9Sstevel@tonic-gate #define	PCFS_PCMCIA_NO_CIS 0x4000	/* PCMCIA psuedo floppy */
2037c478bd9Sstevel@tonic-gate #define	PCFS_FOLDCASE	0x8000		/* fold all names from media to */
2047c478bd9Sstevel@tonic-gate 					/* lowercase */
2057c478bd9Sstevel@tonic-gate #define	PCFS_FAT32	0x10000		/* 32 bit FAT */
2067c478bd9Sstevel@tonic-gate #define	PCFS_IRRECOV	0x20000		/* FS was messed with during write */
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate /* for compatibility */
2097c478bd9Sstevel@tonic-gate struct old_pcfs_args {
2107c478bd9Sstevel@tonic-gate 	int	secondswest;	/* seconds west of Greenwich */
2117c478bd9Sstevel@tonic-gate 	int	dsttime;    	/* type of dst correction */
2127c478bd9Sstevel@tonic-gate };
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate struct pcfs_args {
2157c478bd9Sstevel@tonic-gate 	int	secondswest;	/* seconds west of Greenwich */
2167c478bd9Sstevel@tonic-gate 	int	dsttime;    	/* type of dst correction */
2177c478bd9Sstevel@tonic-gate 	int	flags;
2187c478bd9Sstevel@tonic-gate };
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate  * flags for the pcfs_args 'flags' field.
2227c478bd9Sstevel@tonic-gate  *
22343893bfeSmm  * Note that these two macros are obsolete - do not use them.
2247c478bd9Sstevel@tonic-gate  */
2257c478bd9Sstevel@tonic-gate #define	PCFS_MNT_HIDDEN		0x01	/* show hidden files */
2267c478bd9Sstevel@tonic-gate #define	PCFS_MNT_FOLDCASE	0x02	/* fold all names from media to */
2277c478bd9Sstevel@tonic-gate 					/* lowercase */
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate /*
2307c478bd9Sstevel@tonic-gate  * pcfs mount options.
2317c478bd9Sstevel@tonic-gate  */
2327c478bd9Sstevel@tonic-gate #define	MNTOPT_PCFS_HIDDEN	"hidden"
2337c478bd9Sstevel@tonic-gate #define	MNTOPT_PCFS_NOHIDDEN	"nohidden"
2347c478bd9Sstevel@tonic-gate #define	MNTOPT_PCFS_FOLDCASE	"foldcase"
2357c478bd9Sstevel@tonic-gate #define	MNTOPT_PCFS_NOFOLDCASE	"nofoldcase"
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate  * Disk timeout value in sec.
2397c478bd9Sstevel@tonic-gate  * This is used to time out the in core FAT and to re-verify the disk.
2407c478bd9Sstevel@tonic-gate  * This should be less than the time it takes to change floppys
2417c478bd9Sstevel@tonic-gate  */
2427c478bd9Sstevel@tonic-gate #define	PCFS_DISKTIMEOUT	2
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate #define	VFSTOPCFS(VFSP)		((struct pcfs *)((VFSP)->vfs_data))
2457c478bd9Sstevel@tonic-gate #define	PCFSTOVFS(FSP)		((FSP)->pcfs_vfs)
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate /*
2487c478bd9Sstevel@tonic-gate  * special cluster numbers in FAT
2497c478bd9Sstevel@tonic-gate  */
2507c478bd9Sstevel@tonic-gate #define	PCF_FREECLUSTER		0x00	/* cluster is available */
2517c478bd9Sstevel@tonic-gate #define	PCF_ERRORCLUSTER	0x01	/* error occurred allocating cluster */
2527c478bd9Sstevel@tonic-gate #define	PCF_12BCLUSTER		0xFF0	/* 12-bit version of reserved cluster */
2537c478bd9Sstevel@tonic-gate #define	PCF_RESCLUSTER		0xFFF0	/* 16-bit version of reserved cluster */
2547c478bd9Sstevel@tonic-gate #define	PCF_RESCLUSTER32	0xFFFFFF0 /* 32-bit version */
2557c478bd9Sstevel@tonic-gate #define	PCF_BADCLUSTER		0xFFF7	/* bad cluster, do not use */
2567c478bd9Sstevel@tonic-gate #define	PCF_BADCLUSTER32	0xFFFFFF7 /* 32-bit version */
2577c478bd9Sstevel@tonic-gate #define	PCF_LASTCLUSTER		0xFFF8	/* >= means last cluster in file */
2587c478bd9Sstevel@tonic-gate #define	PCF_LASTCLUSTER32	0xFFFFFF8 /* 32-bit version */
2597c478bd9Sstevel@tonic-gate #define	PCF_LASTCLUSTERMARK	0xFFFF	/* value used to mark last cluster */
2607c478bd9Sstevel@tonic-gate #define	PCF_LASTCLUSTERMARK32	0xFFFFFFF /* 32-bit version */
2617c478bd9Sstevel@tonic-gate #define	PCF_FIRSTCLUSTER	2	/* first valid cluster number */
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate /*
2647c478bd9Sstevel@tonic-gate  * file system constants
2657c478bd9Sstevel@tonic-gate  */
2667c478bd9Sstevel@tonic-gate #define	PC_MAXFATSEC	256		/* maximum number of sectors in FAT */
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate /*
2697c478bd9Sstevel@tonic-gate  * file system parameter macros
2707c478bd9Sstevel@tonic-gate  */
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate #define	IS_FAT32(PCFS) \
2737c478bd9Sstevel@tonic-gate 	(((PCFS)->pcfs_flags & PCFS_FAT32) == PCFS_FAT32)
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate #define	IS_FAT16(PCFS) \
2767c478bd9Sstevel@tonic-gate 	(((PCFS)->pcfs_flags & PCFS_FAT16) == PCFS_FAT16)
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate #define	IS_FAT12(PCFS) \
2797c478bd9Sstevel@tonic-gate 	(((PCFS)->pcfs_flags & (PCFS_FAT16 | PCFS_FAT32)) == 0)
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate #define	pc_clear_fatchanges(PCFS) \
2827c478bd9Sstevel@tonic-gate 	bzero((PCFS)->pcfs_fat_changemap, (PCFS)->pcfs_fat_changemapsize)
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate #define	pc_blksize(PCFS, PCP, OFF)	/* file system block size */ \
2857c478bd9Sstevel@tonic-gate 	(((PCTOV(PCP)->v_flag & VROOT) && !IS_FAT32(PCFS)) ? \
2867c478bd9Sstevel@tonic-gate 	    ((OFF) >= \
2877c478bd9Sstevel@tonic-gate 	    ((PCFS)->pcfs_rdirsec & \
2887c478bd9Sstevel@tonic-gate 	    ~((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize)? \
2897c478bd9Sstevel@tonic-gate 	    ((PCFS)->pcfs_rdirsec & \
2907c478bd9Sstevel@tonic-gate 	    ((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize): \
2917c478bd9Sstevel@tonic-gate 	    (PCFS)->pcfs_clsize): \
2927c478bd9Sstevel@tonic-gate 	    (PCFS)->pcfs_clsize)
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate #define	pc_blkoff(PCFS, OFF)		/* offset within block */ \
2957c478bd9Sstevel@tonic-gate 	((int)((OFF) & ((PCFS)->pcfs_clsize - 1)))
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate #define	pc_lblkno(PCFS, OFF)		/* logical block (cluster) no */ \
2987c478bd9Sstevel@tonic-gate 	((daddr_t)((OFF) / (PCFS)->pcfs_clsize))
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate #define	pc_dbtocl(PCFS, DB)		/* disk blks to clusters */ \
3017c478bd9Sstevel@tonic-gate 	((int)((DB) / (PCFS)->pcfs_spcl))
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate #define	pc_cltodb(PCFS, CL)		/* clusters to disk blks */ \
3047c478bd9Sstevel@tonic-gate 	((daddr_t)((CL) * (PCFS)->pcfs_spcl))
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate #define	pc_cldaddr(PCFS, CL)	/* DEV_BSIZE "sector" addr for cluster */ \
3077c478bd9Sstevel@tonic-gate 	(((daddr_t)((PCFS)->pcfs_datastart + \
3087c478bd9Sstevel@tonic-gate 	    ((CL) - PCF_FIRSTCLUSTER) * (PCFS)->pcfs_spcl)) << \
3097c478bd9Sstevel@tonic-gate 	    (PCFS)->pcfs_sdshift)
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate #define	pc_daddrcl(PCFS, DADDR)		/* cluster for disk address */ \
3127c478bd9Sstevel@tonic-gate 	((int)(((((DADDR) >> (PCFS)->pcfs_sdshift) - (PCFS)->pcfs_datastart) / \
3137c478bd9Sstevel@tonic-gate 	(PCFS)->pcfs_spcl) + 2))
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate #define	pc_dbdaddr(PCFS, DB)	/* sector to DEV_BSIZE "sector" addr */ \
3167c478bd9Sstevel@tonic-gate 	((DB) << (PCFS)->pcfs_sdshift)
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate #define	pc_daddrdb(PCFS, DADDR)	/* DEV_BSIZE "sector" addr to sector addr */ \
3197c478bd9Sstevel@tonic-gate 	((DADDR) >> (PCFS)->pcfs_sdshift)
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate #define	pc_validcl(PCFS, CL)		/* check that cluster no is legit */ \
3227c478bd9Sstevel@tonic-gate 	((int)(CL) >= PCF_FIRSTCLUSTER && \
3237c478bd9Sstevel@tonic-gate 	    (int)(CL) <= (PCFS)->pcfs_ncluster)
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate  * external routines.
3277c478bd9Sstevel@tonic-gate  */
3287c478bd9Sstevel@tonic-gate extern int pc_lockfs(struct pcfs *, int, int); /* lock fs and get fat */
3297c478bd9Sstevel@tonic-gate extern void pc_unlockfs(struct pcfs *);	/* ulock the fs */
3307c478bd9Sstevel@tonic-gate extern int pc_getfat(struct pcfs *);	/* get fat from disk */
3317c478bd9Sstevel@tonic-gate extern void pc_invalfat(struct pcfs *);	/* invalidate incore fat */
3327c478bd9Sstevel@tonic-gate extern int pc_syncfat(struct pcfs *);	/* sync fat to disk */
3337c478bd9Sstevel@tonic-gate extern int pc_freeclusters(struct pcfs *);	/* num free clusters in fs */
3347c478bd9Sstevel@tonic-gate extern pc_cluster32_t pc_alloccluster(struct pcfs *, int);
3357c478bd9Sstevel@tonic-gate extern void pc_setcluster(struct pcfs *, pc_cluster32_t, pc_cluster32_t);
3367c478bd9Sstevel@tonic-gate extern void pc_mark_fat_updated(struct pcfs *fsp, pc_cluster32_t cn);
3377c478bd9Sstevel@tonic-gate extern int pc_fat_is_changed(struct pcfs *fsp, pc_cluster32_t bn);
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate /*
3407c478bd9Sstevel@tonic-gate  * debugging
3417c478bd9Sstevel@tonic-gate  */
3427c478bd9Sstevel@tonic-gate extern int pcfsdebuglevel;
3437c478bd9Sstevel@tonic-gate #define	PC_DPRINTF0(level, A) \
3447c478bd9Sstevel@tonic-gate 	if (pcfsdebuglevel >= level) \
3457c478bd9Sstevel@tonic-gate 	    cmn_err(CE_CONT, (A))
3467c478bd9Sstevel@tonic-gate #define	PC_DPRINTF1(level, A, B) \
3477c478bd9Sstevel@tonic-gate 	if (pcfsdebuglevel >= level) \
3487c478bd9Sstevel@tonic-gate 	    cmn_err(CE_CONT, (A), (B))
3497c478bd9Sstevel@tonic-gate #define	PC_DPRINTF2(level, A, B, C) \
3507c478bd9Sstevel@tonic-gate 	if (pcfsdebuglevel >= level) \
3517c478bd9Sstevel@tonic-gate 	    cmn_err(CE_CONT, (A), (B), (C))
3527c478bd9Sstevel@tonic-gate #define	PC_DPRINTF3(level, A, B, C, D) \
3537c478bd9Sstevel@tonic-gate 	if (pcfsdebuglevel >= level) \
3547c478bd9Sstevel@tonic-gate 	    cmn_err(CE_CONT, (A), (B), (C), (D))
3557c478bd9Sstevel@tonic-gate #define	PC_DPRINTF4(level, A, B, C, D, E) \
3567c478bd9Sstevel@tonic-gate 	if (pcfsdebuglevel >= level) \
3577c478bd9Sstevel@tonic-gate 	    cmn_err(CE_CONT, (A), (B), (C), (D), (E))
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate #endif
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate #endif	/* _SYS_FS_PC_FS_H */
364