Subject: port-amiga/9729: Can't use media with sector size greater than 512 bytes
To: None <netbsd-bugs@netbsd.org>
From: John Darrow <John.P.Darrow@wheaton.edu>
List: netbsd-bugs
Date: 04/05/2000 14:58:19
Date: Wed, 26 May 1999 22:59:45 +0200
From: TetiSoft@apg.lahn.de (=?ISO-8859-1?Q?Detlef_W=FCrkner?=)
To: gnats-bugs@gnats.netbsd.org
Subject: Can't use media with sector size greater than 512 bytes


>Number:         9729
>Category:       port-amiga
>Synopsis:       media with sector size > 512 don't work.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-amiga-maintainer
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Mar 31 00:16:43 PST 2000
>Closed-Date:    
>Last-Modified:  
>Originator:     Detlef Wuerkner
>Release:        Sat May  8 21:10:58 UTC 1999
>Organization:
>Environment:
	Amiga 4000, CyberStorm MkII/060/SCSI, 640MB MO-drive, NetBSD1.4/amiga
System: NetBSD mobile 1.4 NetBSD 1.4 (GENERIC) #50: Sun May 9 17:10:33 MEST 1999 is@jocelyn:/usr/obj/kernel/GENERIC amiga




>Description:
	Partitions on media with physical sektor size greater than
	the normal 512 bytes can't be found by NetBSD 1.4/amiga
	(error message "partition block with bad id" at boot time).
	Some other changes are suggested for successfull usage of a file
	system on such media.
>How-To-Repeat:
	Of course you need media with physical sector size greater than
	512 bytes, for example 3,5" 640MB MO-media (2048 bytes/sector).
	Partition it on an amiga with the latest HDToolBox (40.4) and
	boot NetBSD (from another drive). The error message
	"sdx: partition block with bad id" appears while booting,
	and "disklabel sdx" doesn't show the partitions.
>Fix:
	The reason for the problem is the fact that NetBSD counts blocks
	in DEV_BSIZE units (always 512?), but AmigaOS counts blocks in
	physical units.


	In /usr/src/sys/dev/scsipi/sd.c, routine sdstart() adjusts the
	block numbers, it changes from DEV_BSIZE units to physical units:
	blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
	As long as media with sector sizes of 512 bytes are used, this
	doesn't matter (divide by 1), but for successfull usage of media
	with greater sector sizes (e.g. 640MB MO-media with
	2048 bytes/sector) we must multiply block numbers with
	(lp->d_secsize / DEV_BSIZE) to keep "unchanged" physical block
	numbers.


	Several other problem reports dealt with the adjustment from
	physical to DEV_BSIZE units in sd.c, especially the PR's
	number 495, 3460, 3790, 3791 and 3792, all years old. Since
	nothing changed until now, I suggest the following changes to
	/usr/src/sys/arch/amiga/amiga/disksubr.c, the disksubr.c-
	routines of other architectures may need similar changes.
	If in future sd.c is changed, disksubr.c only needs a change
	of a #define-line.


	In /usr/src/sys/arch/amiga/amiga/disksubr.c, before reading the
	RDSK- and PART-blocks the block number has to be multiplied with
	(physical block size / DEV_BSIZE).


	Since the block numbers now may be greater by powers of two,
	and bounds_check_with_label() is called from sd.c before
	adjusting the block number, bounds_check_with_label() must be
	adopted. The current version did a check for the B_RAW flag,
	that relied on a patch of sd.c suggested in problem report 495
	but not included in the source tree. The bounds_check_with_label()
	functions of some other architectures also contain this
	currently unnecessary check for B_RAW.


	Also, the block size of AmigaDOS-partitions must be changed from
	constant 512 to max(512, lp->d_secsize) to force reading of at
	least the physical block size and for e.g. correct checksumming
	routines in adosfs. A problem report which enables adosfs to
	handle AmigaDOS-partitions with sector size > 512 will follow.


	OK, and here's the diff:


*** bffsc:src/sys/arch/amiga/amiga/disksubr.c.orig	Wed Apr 28 22:44:34 1999
--- bffsc:src/sys/arch/amiga/amiga/disksubr.c	Wed May 26 21:56:51 1999
***************
*** 42,49 ****
--- 42,61 ----
  #include <sys/disk.h>
  #include <amiga/amiga/adosglue.h>

  
  /*
+  * In /usr/src/sys/dev/scsipi/sd.c, routine sdstart() adjusts the
+  * block numbers, it changes from DEV_BSIZE units to physical units:
+  * blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
+  * As long as media with sector sizes of 512 bytes are used, this
+  * doesn't matter (divide by 1), but for successfull usage of media with
+  * greater sector sizes (e.g. 640MB MO-media with 2048 bytes/sector)
+  * we must multiply block numbers with (lp->d_secsize / DEV_BSIZE)
+  * to keep "unchanged" physical block numbers.
+  */
+ #define SD_C_ADJUSTS_NR
+ 
+ /*
   * bitmap id's
   */
  #define RDBLOCK_BID	1
  #define PARTBLOCK_BID	2
***************
*** 152,159 ****
--- 164,174 ----
  		bp->b_blkno = nextb;
  		bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
  		bp->b_bcount = lp->d_secsize;
  		bp->b_flags = B_BUSY | B_READ;
+ #ifdef SD_C_ADJUSTS_NR
+ 		bp->b_blkno *= (lp->d_secsize / DEV_BSIZE);
+ #endif
  		strat(bp);

  
  		if (biowait(bp)) {
  			msg = "rdb scan I/O error";
***************
*** 243,250 ****
--- 258,268 ----
  		bp->b_blkno = nextb;
  		bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
  		bp->b_bcount = lp->d_secsize;
  		bp->b_flags = B_BUSY | B_READ;
+ #ifdef SD_C_ADJUSTS_NR
+ 		bp->b_blkno *= (lp->d_secsize / DEV_BSIZE);
+ #endif
  		strat(bp);

  		
  		if (biowait(bp)) {
  			msg = "partition scan I/O error";
***************
*** 368,385 ****
  			/*
  			 * Save reserved blocks at begin in cpg and
  			 *  adjust size by reserved blocks at end
  			 */
! 			pp->p_fsize = 512;
  			pp->p_frag = pbp->e.secperblk;
  			pp->p_cpg = pbp->e.resvblocks;
  			pp->p_size -= pbp->e.prefac;
  		} else if (pbp->e.tabsize > 22 && ISFSARCH_NETBSD(adt)) {
  			pp->p_fsize = pbp->e.fsize;
  			pp->p_frag = pbp->e.frag;
  			pp->p_cpg = pbp->e.cpg;
  		} else {
! 			pp->p_fsize = 1024;
  			pp->p_frag = 8;
  			pp->p_cpg = 0;
  		}

  
--- 386,415 ----
  			/*
  			 * Save reserved blocks at begin in cpg and
  			 *  adjust size by reserved blocks at end
  			 */
! 
! 			/*
! 			 * file system block size must be at least
! 			 * physical block size and at least 512
! 			 */
! 			pp->p_fsize = max(512, lp->d_secsize);
! 
  			pp->p_frag = pbp->e.secperblk;
  			pp->p_cpg = pbp->e.resvblocks;
  			pp->p_size -= pbp->e.prefac;
  		} else if (pbp->e.tabsize > 22 && ISFSARCH_NETBSD(adt)) {
  			pp->p_fsize = pbp->e.fsize;
  			pp->p_frag = pbp->e.frag;
  			pp->p_cpg = pbp->e.cpg;
  		} else {
! 
! 			/*
! 			 * file system block size must be at least
! 			 * physical block size and at least 1024
! 			 */
! 			pp->p_fsize = max(1024, lp->d_secsize);
! 
  			pp->p_frag = 8;
  			pp->p_cpg = 0;
  		}

  
***************
*** 483,498 ****
  	struct partition *pp;
  	long maxsz, sz;

  
  	pp = &lp->d_partitions[DISKPART(bp->b_dev)];
! 	if (bp->b_flags & B_RAW) {
! 		maxsz = pp->p_size * (lp->d_secsize / DEV_BSIZE);
! 		sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
! 	} else {
! 		maxsz = pp->p_size;
! 		sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
! 	}
! 
  	if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
  		if (bp->b_blkno == maxsz) {
  			/* 
  			 * trying to get one block beyond return EOF.
--- 513,531 ----
  	struct partition *pp;
  	long maxsz, sz;

  
  	pp = &lp->d_partitions[DISKPART(bp->b_dev)];
! 	/*
! 	 * This routine is called before sd.c adjusts block numbers
! 	 * and must take this into account
! 	 */
! #ifdef SD_C_ADJUSTS_NR
! 	maxsz = pp->p_size * (lp->d_secsize / DEV_BSIZE);
! 	sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
! #else
! 	maxsz = pp->p_size;
! 	sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
! #endif
  	if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
  		if (bp->b_blkno == maxsz) {
  			/* 
  			 * trying to get one block beyond return EOF.


Ciao, Detlef
-- 
_ // TetiSoft@apg.lahn.de
\X/  Detlef Wuerkner, Giessen, Germany


>Release-Note:
>Audit-Trail:
>Unformatted: