lkml.org 
[lkml]   [1999]   [Jun]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectPATCH 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");
\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.638 / U:0.140 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site