Re: fujitsu scsi m2513 mo 2048 sector size

Oliver Schaertel (orschaer@cip.informatik.uni-erlangen.de)
Sat, 26 Apr 1997 17:14:50 +0000


This is a multi-part message in MIME format.

--------------B210502028B3D614C31872
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Jacek Zapala wrote:
>
> Is there any patch for linux 2.0.xx for supporting 2048 sector size on
> SCSI (for the device from subject) ?
>
> Jacek Zapala
Hi
Look at http://wwwcip.informatik.uni-erlangen.de/user/orschaer/mo
I also attached the patch!

Oliver

--------------B210502028B3D614C31872
Content-Type: text/plain; charset=us-ascii; name="fujitsu2513a.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="fujitsu2513a.diff"

diff -ru linux2.0.30.unpatched/drivers/block/genhd.c linux2.0.30.mopatched/drivers/block/genhd.c
--- linux2.0.30.unpatched/drivers/block/genhd.c Wed Aug 21 06:18:07 1996
+++ linux2.0.30.mopatched/drivers/block/genhd.c Mon Apr 14 22:17:12 1997
@@ -24,9 +24,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/string.h>
-#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
-#endif

#include <asm/system.h>

@@ -105,7 +103,60 @@
SYS_IND(p) == LINUX_EXTENDED_PARTITION);
}

+static int sec_fac(kdev_t dev)
+{
+ return (hardsect_size[MAJOR(dev)][MINOR(dev)]/512);
+}
+
+static unsigned int get_ptable_blocksize(kdev_t dev)
+{
+ int ret = 1024;
+
+ /*
+ * See whether the low-level driver has given us a minumum blocksize.
+ * If so, check to see whether it is larger than the default of 1024.
+ */
+ if (!blksize_size[MAJOR(dev)])
+ {
+ return ret;
+ }
+
+ /*
+ * Check for certain special power of two sizes that we allow.
+ * With anything larger than 1024, we must force the blocksize up to
+ * the natural blocksize for the device so that we don't have to try
+ * and read partial sectors. Anything smaller should be just fine.
+ */
+ switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
+ {
+ case 2048:
+ ret = 2048;
+ break;
+ case 4096:
+ ret = 4096;
+ break;
+ case 8192:
+ ret = 8192;
+ break;
+ case 1024:
+ case 512:
+ case 256:
+ case 0:
+ /*
+ * These are all OK.
+ */
+ break;
+ default:
+ panic("Strange blocksize for partition table\n");
+ }
+
+ return ret;
+
+}
+
+
#ifdef CONFIG_MSDOS_PARTITION
+
/*
* Create devices for each logical partition in an extended partition.
* The logical partitions form a linked list, with each entry being
@@ -124,7 +175,7 @@
unsigned long first_sector, first_size, this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
int i;
-
+ int sf=sec_fac(dev);
first_sector = hd->part[MINOR(dev)].start_sect;
first_size = hd->part[MINOR(dev)].nr_sects;
this_sector = first_sector;
@@ -132,7 +183,7 @@
while (1) {
if ((current_minor & mask) == 0)
return;
- if (!(bh = bread(dev,0,1024)))
+ if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
return;
/*
* This block is from a device that we're about to stomp on.
@@ -165,14 +216,14 @@

/* Check the 3rd and 4th entries -
these sometimes contain random garbage */
- if (i >= 2
+ if (i >= 2
&& START_SECT(p) + NR_SECTS(p) > this_size
&& (this_sector + START_SECT(p) < first_sector ||
this_sector + START_SECT(p) + NR_SECTS(p) >
first_sector + first_size))
continue;

- add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
+ add_partition(hd, current_minor, this_sector+START_SECT(p) *sf , NR_SECTS(p) *sf );
current_minor++;
if ((current_minor & mask) == 0)
goto done;
@@ -194,9 +245,9 @@
if (i == 4)
goto done; /* nothing left to do */

- hd->part[current_minor].nr_sects = NR_SECTS(p);
- hd->part[current_minor].start_sect = first_sector + START_SECT(p);
- this_sector = first_sector + START_SECT(p);
+ hd->part[current_minor].nr_sects = NR_SECTS(p)*sf ;
+ hd->part[current_minor].start_sect = first_sector + START_SECT(p) *sf;
+ this_sector = first_sector + START_SECT(p)*sf;
dev = MKDEV(hd->major, current_minor);
brelse(bh);
}
@@ -216,7 +267,7 @@
struct bsd_partition *p;
int mask = (1 << hd->minor_shift) - 1;

- if (!(bh = bread(dev,0,1024)))
+ if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
return;
bh->b_state = 0;
l = (struct bsd_disklabel *) (bh->b_data+512);
@@ -248,12 +299,13 @@
struct partition *p;
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
+ int sf=sec_fac(dev);
#ifdef CONFIG_BLK_DEV_IDE
int tested_for_xlate = 0;

read_mbr:
#endif
- if (!(bh = bread(dev,0,1024))) {
+ if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
printk(" unable to read partition table\n");
return -1;
}
@@ -343,10 +395,11 @@
#endif /* CONFIG_BLK_DEV_IDE */

current_minor += 4; /* first "extra" minor (for extended partitions) */
+
for (i=1 ; i<=4 ; minor++,i++,p++) {
if (!NR_SECTS(p))
continue;
- add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
+ add_partition(hd, minor, first_sector+START_SECT(p)*sf , NR_SECTS(p)*sf );
if (is_extended_partition(p)) {
printk(" <");
/*
@@ -371,6 +424,7 @@
printk(" >");
}
#endif
+
}
/*
* Check for old-style Disk Manager partition table
@@ -434,7 +488,7 @@
struct d_partition * partition;
#define DISKLABELMAGIC (0x82564557UL)

- if (!(bh = bread(dev,0,1024))) {
+ if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
printk("unable to read partition table\n");
return -1;
}
@@ -509,7 +563,7 @@
| (((__u32)(x) & 0xFF000000) >> 24) \
: (__u32)(x))

- if(!(bh = bread(dev, 0, 1024))) {
+ if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
printk("Dev %s: unable to read partition table\n",
kdevname(dev));
return -1;
diff -ru linux2.0.30.unpatched/drivers/block/hd.c linux2.0.30.mopatched/drivers/block/hd.c
--- linux2.0.30.unpatched/drivers/block/hd.c Fri Mar 1 05:50:39 1996
+++ linux2.0.30.mopatched/drivers/block/hd.c Mon Apr 14 22:15:44 1997
@@ -801,6 +801,8 @@
(short *) &loc->cylinders);
put_user(hd[MINOR(inode->i_rdev)].start_sect,
(long *) &loc->start);
+ put_user(hardsect_size[MAJOR(dev)][MINOR(dev)],
+ (long *) &loc->sector_size);
return 0;
case BLKRASET:
if(!suser()) return -EACCES;
diff -ru linux2.0.30.unpatched/drivers/block/ide.c linux2.0.30.mopatched/drivers/block/ide.c
--- linux2.0.30.unpatched/drivers/block/ide.c Tue Nov 19 14:21:06 1996
+++ linux2.0.30.mopatched/drivers/block/ide.c Mon Apr 14 22:18:55 1997
@@ -2037,6 +2037,8 @@
put_user(drive->bios_cyl, (unsigned short *) &loc->cylinders);
put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,
(unsigned long *) &loc->start);
+ put_user(hardsect_size[MAJOR(inode->i_rdev)][MINOR(inode->i_rdev)],
+ (long *) &loc->sector_size);
return 0;
}
case BLKFLSBUF:
diff -ru linux2.0.30.unpatched/drivers/block/md.c linux2.0.30.mopatched/drivers/block/md.c
--- linux2.0.30.unpatched/drivers/block/md.c Sat Jun 29 21:04:00 1996
+++ linux2.0.30.mopatched/drivers/block/md.c Mon Apr 14 22:15:44 1997
@@ -336,6 +336,8 @@
put_user (md_hd_struct[minor].nr_sects/8, (short *) &loc->cylinders);
put_user (md_hd_struct[MINOR(inode->i_rdev)].start_sect,
(long *) &loc->start);
+ put_user(hardsect_size[MAJOR(dev)][MINOR(dev)],
+ (long *) &loc->sector_size);
break;

RO_IOCTLS(inode->i_rdev,arg);
diff -ru linux2.0.30.unpatched/drivers/block/xd.c linux2.0.30.mopatched/drivers/block/xd.c
--- linux2.0.30.unpatched/drivers/block/xd.c Sun Sep 8 16:50:20 1996
+++ linux2.0.30.mopatched/drivers/block/xd.c Mon Apr 14 22:27:33 1997
@@ -260,6 +260,8 @@
put_user(xd_info[dev].sectors, &geometry->sectors);
put_user(xd_info[dev].cylinders, &geometry->cylinders);
put_user(xd[MINOR(inode->i_rdev)].start_sect,&geometry->start);
+ put_user(hardsect_size[MAJOR(dev)][MINOR(dev)],
+ (long *) &geometry->sector_size);

return (0);
}
diff -ru linux2.0.30.unpatched/drivers/scsi/sd.c linux2.0.30.mopatched/drivers/scsi/sd.c
--- linux2.0.30.unpatched/drivers/scsi/sd.c Mon Apr 14 22:10:47 1997
+++ linux2.0.30.mopatched/drivers/scsi/sd.c Mon Apr 14 22:15:45 1997
@@ -59,7 +59,7 @@
*/

#define SD_TIMEOUT (15 * HZ)
-#define SD_MOD_TIMEOUT (15 * HZ)
+#define SD_MOD_TIMEOUT (75 * HZ)

#define CLUSTERABLE_DEVICE(SC) (SC->host->use_clustering && \
SC->device->type != TYPE_MOD)
@@ -249,6 +249,11 @@
error_sector <<= 1;
if (block_sectors < 2) block_sectors = 2;
}
+ else if (sector_size == 2048)
+ {
+ error_sector <<= 2;
+ if (block_sectors < 4) block_sectors = 4;
+ }
else if (sector_size == 256)
error_sector >>= 1;
error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
@@ -629,6 +634,13 @@
goto repeat;
}

+ if (rscsi_disks[dev].sector_size == 2048)
+ if((block & 3) || (SCpnt->request.nr_sectors & 3)) {
+ printk("sd.c:Bad block number requested");
+ SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+ goto repeat;
+ }
+
switch (SCpnt->request.cmd)
{
case WRITE :
@@ -895,6 +907,13 @@

cmd[1] = (SCpnt->lun << 5) & 0xe0;

+ if (rscsi_disks[dev].sector_size == 2048){
+ if(block & 3) panic("sd.c:Bad block number requested");
+ if(this_count & 3) panic("sd.c:Bad block number requested");
+ block = block >> 2;
+ this_count = this_count >> 2;
+ }
+
if (rscsi_disks[dev].sector_size == 1024){
if(block & 1) panic("sd.c:Bad block number requested");
if(this_count & 1) panic("sd.c:Bad block number requested");
@@ -1196,6 +1215,7 @@

if (rscsi_disks[i].sector_size != 512 &&
rscsi_disks[i].sector_size != 1024 &&
+ rscsi_disks[i].sector_size != 2048 &&
rscsi_disks[i].sector_size != 256)
{
printk ("sd%c : unsupported sector size %d.\n",
@@ -1210,6 +1230,22 @@
return i;
}
}
+
+ if( rscsi_disks[i].sector_size == 2048 )
+ {
+ int m;
+
+ /*
+ * We must fix the sd_blocksizes and sd_hardsizes
+ * to allow us to read the partition tables.
+ * The disk reading code does not allow for reading
+ * of partial sectors.
+ */
+ for (m=i<<4; m<((i+1)<<4); m++)
+ {
+ sd_blocksizes[m] = 2048;
+ }
+ }
{
/*
* The msdos fs needs to know the hardware sector size
@@ -1233,6 +1269,8 @@
i+'a', hard_sector, rscsi_disks[i].capacity,
mb, sz_quot, sz_rem);
}
+ if(rscsi_disks[i].sector_size == 2048)
+ rscsi_disks[i].capacity <<= 2; /* Change into 512 byte sectors */
if(rscsi_disks[i].sector_size == 1024)
rscsi_disks[i].capacity <<= 1; /* Change into 512 byte sectors */
if(rscsi_disks[i].sector_size == 256)
@@ -1336,10 +1374,12 @@
sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
sizeof(int), GFP_ATOMIC);

- for(i=0;i<(sd_template.dev_max << 4);i++){
- sd_blocksizes[i] = 1024;
- sd_hardsizes[i] = 512;
- }
+ for(i=0;i<(sd_template.dev_max << 4);i++)
+ {
+ sd_blocksizes[i] = 1024;
+ sd_hardsizes[i] = 512;
+ }
+
blksize_size[MAJOR_NR] = sd_blocksizes;
hardsect_size[MAJOR_NR] = sd_hardsizes;
sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) *
@@ -1472,9 +1512,15 @@
gdev->part[minor].nr_sects = 0;
/*
* Reset the blocksize for everything so that we can read
- * the partition table.
+ * the partition table. Technically we will determine the
+ * correct block size when we revalidate, but we do this just
+ * to make sure that everything remains consistent.
*/
blksize_size[MAJOR_NR][minor] = 1024;
+ if( rscsi_disks[target].sector_size == 2048 )
+ blksize_size[MAJOR_NR][minor] = 2048;
+ else
+ blksize_size[MAJOR_NR][minor] = 1024;
}

#ifdef MAYBE_REINIT
diff -ru linux2.0.30.unpatched/drivers/scsi/sd_ioctl.c linux2.0.30.mopatched/drivers/scsi/sd_ioctl.c
--- linux2.0.30.unpatched/drivers/scsi/sd_ioctl.c Thu May 2 04:48:54 1996
+++ linux2.0.30.mopatched/drivers/scsi/sd_ioctl.c Mon Apr 14 22:15:45 1997
@@ -55,6 +55,7 @@
put_user(diskinfo[1], &loc->sectors);
put_user(diskinfo[2], &loc->cylinders);
put_user(sd[MINOR(inode->i_rdev)].start_sect, &loc->start);
+ put_user(hardsect_size[MAJOR(dev)][MINOR(dev)], &loc->sector_size);
return 0;
case BLKGETSIZE: /* Return device size */
if (!arg) return -EINVAL;
diff -ru linux2.0.30.unpatched/drivers/scsi/sr.c linux2.0.30.mopatched/drivers/scsi/sr.c
--- linux2.0.30.unpatched/drivers/scsi/sr.c Mon Apr 14 22:10:47 1997
+++ linux2.0.30.mopatched/drivers/scsi/sr.c Mon Apr 14 22:15:45 1997
@@ -54,9 +54,10 @@
sr_finish, sr_attach, sr_detach};

Scsi_CD * scsi_CDs = NULL;
-static int * sr_sizes;
+static int * sr_sizes = NULL;

-static int * sr_blocksizes;
+static int * sr_blocksizes = NULL;
+static int * sr_hardsizes = NULL; /* Hardware sector size */

static int sr_open(struct inode *, struct file *);
void get_sectorsize(int);
@@ -123,24 +124,37 @@
inode.i_rdev = full_dev; /* This is all we really need here */
retval = sr_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0);

- if(retval){ /* Unable to test, unit probably not ready. This usually
+ if(retval)
+ {
+ /* Unable to test, unit probably not ready. This usually
* means there is no disc in the drive. Mark as changed,
* and we will figure it out later once the drive is
* available again. */

- scsi_CDs[target].device->changed = 1;
- return 1; /* This will force a flush, if called from
- * check_disk_change */
- };
+ scsi_CDs[target].device->changed = 1;
+ return 1; /* This will force a flush, if called from
+ * check_disk_change */
+ }

retval = scsi_CDs[target].device->changed;
- if(!flag) {
- scsi_CDs[target].device->changed = 0;
- /* If the disk changed, the capacity will now be different,
- * so we force a re-read of this information */
- if (retval) scsi_CDs[target].needs_sector_size = 1;
- };
- return retval;
+ if(!flag)
+ {
+ scsi_CDs[target].device->changed = 0;
+ /*
+ * If the disk changed, the capacity will now be different,
+ * so we force a re-read of this information
+ * Force 2048 for the sector size so that filesystems won't
+ * be trying to use something that is too small if the disc
+ * has changed.
+ */
+ if (retval)
+ {
+ scsi_CDs[target].needs_sector_size = 1;
+ scsi_CDs[target].sector_size =
+ sr_hardsizes[target] = 2048;
+ }
+ }
+ return retval;
}

/*
@@ -1120,6 +1134,12 @@
scsi_CDs[i].capacity = 0;
scsi_CDs[i].needs_sector_size = 1;
}
+
+ /*
+ * Add this so that we have the ability to correctly gauge
+ * what the device is capable of.
+ */
+ sr_hardsizes[i] = scsi_CDs[i].sector_size;
scsi_CDs[i].needs_sector_size = 0;
sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
};
@@ -1153,8 +1173,16 @@

sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max *
sizeof(int), GFP_ATOMIC);
+ sr_hardsizes = (int *) scsi_init_malloc(sr_template.dev_max *
+ sizeof(int), GFP_ATOMIC);
+
+ /*
+ * These are good guesses for the time being.
+ */
for(i=0;i<sr_template.dev_max;i++) sr_blocksizes[i] = 2048;
+ for(i=0;i<sr_template.dev_max;i++) sr_hardsizes[i] = 2048;
blksize_size[MAJOR_NR] = sr_blocksizes;
+ hardsect_size[MAJOR_NR] = sr_hardsizes;
return 0;
}

@@ -1247,7 +1275,13 @@
* sizeof(Scsi_CD));

scsi_init_free((char *) sr_sizes, sr_template.dev_max * sizeof(int));
+ sr_sizes = NULL;
+
scsi_init_free((char *) sr_blocksizes, sr_template.dev_max * sizeof(int));
+ sr_blocksizes = NULL;
+
+ scsi_init_free((char *) sr_hardsizes, s