Messages in this thread Patch in this message | | | Date | Tue, 22 Jun 1999 03:38:53 +0000 | From | Farrell Woods <> | Subject | PATCH drivers/scsi/scsi.c fs/fat/inode.c fs/fat/misc.c |
| |
Hi,
I've patched a 2.2.10 kernel to support my Panasonic DVD-RAM drive with a FAT32 filesystem. The patches for scsi.c are basically from http://www.bitwizard.nl/dvd which I've changed slightly to fix a conflict with 2.2.10. Rogier Wolff of BitWizard was gracious enough to give me permission to post a modified version of his scsi.c patch to this list.
The changes to the fat support are as follows:
fs/fat/inode.c:
o The Format UDF! utility supplied with the Panasonic drive will lay down a UDF, FAT16, or FAT32 filesystem. When asked to do FAT32 it puts down both a partition that spans the entire DVD-RAM disc as well as a filesystem. However it does not use the "fsinfo" structure that appears to be expected when a FAT32 filesystem is encountered. Instead the "fsinfo" sector offset is 0xffff. The change to inode.c will cause it to not read the fsinfo structure in this case.
o Having fixed that, I had to modify misc.c to stop complaining when it tries to update the on-disc fsinfo structure, only to discover that the fsinfo signature at sector offset 0xffff doesn't look right.
The doc's for the Panasonic drive advise using the Format UDF! utility for laying down a filesystem on the DVD-RAM drive. These mods appear to work when following that advice. I've not attempted to use FAT16 since FAT16 will use just 2GB of a possible 2.4GB of the drive.
I attempted to use win95 itself to put a filesystem on the DVD-RAM, after using "fdisk" on Linux to create a partition that spanned the entire platter. Curiously, windows decided to ignore the offset for the first partition as given in the partition table (sector offset 3F; byte offset 0x1f800 from the start of the disc given a 2048 byte sector.) Instead, windows started the partition at byte offset 0x10000. What's even more interesting is that Windows seems perfectly happy with this...
Format UDF places the FAT32 partition at byte offset 0x1f800, exactly where it should be. (Q: anyone know why/how windows is happy with 0x10000 and ignores the partition info?)
One footnote: early on I bumped into the error message generated by this bit of code in fs/fat/inode.c:
if (MSDOS_SB(sb)->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) { printk("fat_read_super: Bad fsinfo_offset\n"); fat_brelse(sb, bh); goto out_invalid; }
This appears to me to work only by chance. s_blocksize is arbitrarily set to 1024 above for disks who's native block size is <= 1024 bytes. Since most fixed disks these days are 512 bytes/sector this makes the above predicate work: fsinfo_offset usually ends up being 0x3e0 (offset of 1 sector x 512 bytes/sector + 0x1e0), which is less than 0x400.
But it seems like this predicate will break for disks with physical sector sizes of 1024 or 2048 bytes. For instance, if the fsinfo sector offset is 1 sector and a sector is 1024 bytes, the byte offset ends up being 0x5e0 which is of course greater than a s_blocksize value of 0x400. The predicate fails even though the data are valid.
My changes for the DVD_RAM support sidestep this problem since the sector offset for the fsinfo structure if 0xffff, and I don't attempt to read the on-disk structure in that case.
If you have a DVD-RAM or even an MO disk with a sector size >512 bytes, please give this patch a shot. I tune into the digest of this list; I can also be reached via e-mail.
Enjoy!
-- FarrellThis file patches linux-2.2.10 to support a few DVD-RAM (in particular, the Panasonic LF-D101) drives with FAT32 filesystems.
ftw@no.more.spam.mediaone.net --- linux/drivers/scsi/scsi.c.orig Sun Jun 20 08:07:50 1999 +++ linux/drivers/scsi/scsi.c Sun Jun 20 08:12:04 1999 @@ -110,6 +110,9 @@ #define BLIST_NOTQ 0x20 #define BLIST_SPARSELUN 0x40 #define BLIST_MAX5LUN 0x80 +#define BLIST_ISROM 0x100 +#define BLIST_GHOST 0x200 +#define BLIST_ISDISK 0x400 /* * Data declarations. @@ -285,10 +288,14 @@ {"CANON","IPUBJD","*", BLIST_SPARSELUN}, {"nCipher","Fastness Crypto","*", BLIST_FORCELUN}, {"NEC","PD-1 ODX654P","*", BLIST_FORCELUN | BLIST_SINGLELUN}, -{"MATSHITA","PD","*", BLIST_FORCELUN | BLIST_SINGLELUN}, +{"MATSHITA","PD-1","*", BLIST_FORCELUN | BLIST_SINGLELUN}, {"YAMAHA","CDR100","1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ {"YAMAHA","CDR102","1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ {"iomega","jaz 1GB","J.86", BLIST_NOTQ | BLIST_NOLUN}, +{"CREATIVE","DVD-RAM RAM","*", BLIST_GHOST}, +{"MATSHITA","PD-2 LF-D100","*", BLIST_GHOST}, +{"YAMAHA","CRW4416S","*", BLIST_GHOST}, +{"TOSHIBA","CDROM","*", BLIST_ISROM}, /* * Must be at end of list... */ @@ -635,6 +642,8 @@ struct Scsi_Device_Template *sdtpnt; Scsi_Device * SDtail, *SDpnt=*SDpnt2; int bflags, type=-1; + static int ghost_channel=-1, ghost_dev=-1; + int org_lun = lun; SDpnt->host = shpnt; SDpnt->id = dev; @@ -642,6 +651,12 @@ SDpnt->channel = channel; SDpnt->online = TRUE; + if ((channel == ghost_channel) && (dev == ghost_dev) && (lun == 1)) { + SDpnt->lun = 0; + } else { + ghost_channel = ghost_dev = -1; + } + /* Some low level driver could use device->type (DB) */ SDpnt->type = -1; @@ -734,15 +749,37 @@ } /* - * It would seem some TOSHIBA CDROM gets things wrong + * Get any flags for this device. + */ + bflags = get_device_flags (scsi_result); + + /* The Toshiba ROM was "gender-changed" here as an inline hack. + This is now much more generic. + This is a mess: What we really want is to leave the scsi_result + alone, and just change the SDpnt structure. And the SDpnt is what + we want print_inquiry to print. -- REW */ - if (!strncmp (scsi_result + 8, "TOSHIBA", 7) && - !strncmp (scsi_result + 16, "CD-ROM", 6) && - scsi_result[0] == TYPE_DISK) { + if (bflags & BLIST_ISDISK) { + scsi_result[0] = TYPE_DISK; + scsi_result[1] |= 0x80; /* removable */ + } + + if (bflags & BLIST_ISROM) { scsi_result[0] = TYPE_ROM; scsi_result[1] |= 0x80; /* removable */ } + if (bflags & BLIST_GHOST) { + if ((ghost_channel == channel) && (ghost_dev == dev) && (org_lun == 1)) { + lun=1; + } else { + ghost_channel = channel; + ghost_dev = dev; + scsi_result[0] = TYPE_MOD; + scsi_result[1] |= 0x80; /* removable */ + } + } + memcpy (SDpnt->vendor, scsi_result + 8, 8); memcpy (SDpnt->model, scsi_result + 16, 16); memcpy (SDpnt->rev, scsi_result + 32, 4); @@ -805,10 +842,6 @@ */ SDpnt->disconnect = 0; - /* - * Get any flags for this device. - */ - bflags = get_device_flags (scsi_result); /* * Set the tagged_queue flag for SCSI-II devices that purport to support @@ -933,6 +966,15 @@ */ if (bflags & BLIST_FORCELUN) { *max_dev_lun = 8; + return 1; + } + + /* + * If this device is Ghosted, scan upto two luns. (It physically only + * has one). -- REW + */ + if (bflags & BLIST_GHOST) { + *max_dev_lun = 2; return 1; } --- linux/fs/fat/inode.c.orig Mon Jun 21 07:53:08 1999 +++ linux/fs/fat/inode.c Sun Jun 20 14:36:32 1999 @@ -7,6 +7,9 @@ * Fixes: * * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0 + * + * Farrell Woods: If fsinfo offset is 0xffff then assume no fsinfo + * structure is present and go on... */ #include <linux/version.h> @@ -366,6 +369,11 @@ MSDOS_SB(sb)->fat_length= CF_LE_W(b->fat32_length)*sector_mult; MSDOS_SB(sb)->root_cluster = CF_LE_L(b->root_cluster); + /* FTW - FAT32, but no fsinfo structure */ + if (b->info_sector == 0xffff) { + MSDOS_SB(sb)->free_clusters = -1; /* Don't know yet */ + MSDOS_SB(sb)->fsinfo_offset = 0xffffffff; + } else { /* MC - if info_sector is 0, don't multiply by 0 */ if(CF_LE_W(b->info_sector) == 0) { MSDOS_SB(sb)->fsinfo_offset = @@ -377,6 +385,7 @@ } if (MSDOS_SB(sb)->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) { printk("fat_read_super: Bad fsinfo_offset\n"); + printk("0x%x, 0x%x, 0x%x\n", MSDOS_SB(sb)->fsinfo_offset, sizeof(struct fat_boot_fsinfo), sb->s_blocksize); fat_brelse(sb, bh); goto out_invalid; } @@ -388,6 +397,7 @@ CF_LE_L(fsinfo->signature)); } else { MSDOS_SB(sb)->free_clusters = CF_LE_L(fsinfo->free_clusters); + } } } else { fat32 = 0; --- linux/fs/fat/misc.c.orig Mon Jun 21 07:53:21 1999 +++ linux/fs/fat/misc.c Sun Jun 20 16:48:27 1999 @@ -2,6 +2,9 @@ * linux/fs/fat/misc.c * * Written 1992,1993 by Werner Almesberger + * + * Farrell Woods - If FAT32 and fsinfo offset is 0xffff then + * assume the fsinfo structure isn't there. */ #include <linux/fs.h> @@ -120,6 +123,8 @@ /* The fat32 boot fs info is at offset 0x3e0 by observation */ offset = MSDOS_SB(sb)->fsinfo_offset; + if (offset == 0xffffffff) /* FTW - there is no fsinfo structure */ + return; bh = fat_bread(sb, (offset >> SECTOR_BITS)); if (bh == NULL) { printk("FAT bread failed in fat_clusters_flush\n"); | |