Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 May 1998 14:40:31 +0200 (CEST)
From:      hans@artcom.de
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/6686: -stable does not support large IDE drives
Message-ID:  <m0yblh1-00023bC@mail.artcom.de>

next in thread | raw e-mail | index | archive | help

>Number:         6686
>Category:       kern
>Synopsis:       -stable does not support large IDE drives
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue May 19 05:40:01 PDT 1998
>Last-Modified:
>Originator:     Hans Huebner
>Organization:
Art+Com GmbH
>Release:        FreeBSD 2.2.6-RELEASE i386
>Environment:

2.2.6-RELEASE

>Description:

Large IDE drives are not supported by 2.2.6-RELEASE.  Drives larger
than 8 GB can be utilized only up to 8 GB.

>How-To-Repeat:

Install a large IDE drive in a 2.2.6-RELEASE system.

>Fix:
	
Apply the following patch.  It has been tested by several people.  No
negative effects have been reported.  This is a partial port of -current's
wd driver, only the LBA-relevant code has been merged.  Note that, to use
this, flags need to be specified in the kernel configuration or userconfig
to switch a drive into LBA mode.  The following configuration line works
for me (and our Quantum BigFoot 12G connected to the first IDE port):

controller      wdc0    at isa? port "IO_WD1" bio irq 14 flags 0xb0ffb0ff vector wdintr

Thanks to Soeren Schmidt for helping with the flags.


*** sys/i386/isa/wdreg.h	Wed Jan 14 09:10:49 1998
--- /lion/FreeBSD-stable/sys/i386/isa/wdreg.h	Wed Apr 15 15:28:59 1998
***************
*** 122,127 ****
--- 122,129 ----
  #define WDCC_READ_MULTI	0xC4	/* read multiple */
  #define WDCC_WRITE_MULTI	0xC5	/* write multiple */
  #define WDCC_SET_MULTI 0xC6		/* set multiple count */
+ #define WDCC_READ_DMA	0xC8		/* read using DMA */
+ #define WDCC_WRITE_DMA	0xCA		/* write using DMA */
  
  
  #define	WDCC_EXTDCMD	0xE0		/* send extended command */
***************
*** 130,149 ****
  
  #define	WDFEA_RCACHE	0xAA		/* read cache enable */
  #define WDFEA_WCACHE	0x02		/* write cache enable */
  
  #define	WD_STEP		0		/* winchester- default 35us step */
  
  #define	WDSD_IBM	0xa0		/* forced to 512 byte sector, ecc */
  
  #ifdef KERNEL
  /*
   * read parameters command returns this:
   */
  struct wdparams {
  	/* drive info */
  	short	wdp_config;		/* general configuration bits */
  	u_short	wdp_cylinders;		/* number of cylinders */
! 	short	wdp_reserved;
  	u_short	wdp_heads;		/* number of heads */
  	short	wdp_unfbytespertrk;	/* number of unformatted bytes/track */
  	short	wdp_unfbytes;		/* number of unformatted bytes/sector */
--- 132,157 ----
  
  #define	WDFEA_RCACHE	0xAA		/* read cache enable */
  #define WDFEA_WCACHE	0x02		/* write cache enable */
+ #define WDFEA_SETXFER	0x03		/* set transfer mode */
  
  #define	WD_STEP		0		/* winchester- default 35us step */
  
  #define	WDSD_IBM	0xa0		/* forced to 512 byte sector, ecc */
+ #define	WDSD_LBA	0x40		/* use Logical Block Adressing */
  
  #ifdef KERNEL
  /*
   * read parameters command returns this:
   */
  struct wdparams {
+ 	/*
+ 	 * XXX partly based on DRAFT X3T13/1153D rev 14.  
+ 	 * by the time you read this it will have changed.
+ 	 */
  	/* drive info */
  	short	wdp_config;		/* general configuration bits */
  	u_short	wdp_cylinders;		/* number of cylinders */
! 	short	wdp_reserved2;
  	u_short	wdp_heads;		/* number of heads */
  	short	wdp_unfbytespertrk;	/* number of unformatted bytes/track */
  	short	wdp_unfbytes;		/* number of unformatted bytes/sector */
***************
*** 159,166 ****
  	short	wdp_necc;		/* ecc bytes appended */
  	char	wdp_rev[8];		/* firmware revision */
  	char	wdp_model[40];		/* model name */
! 	short	wdp_nsecperint;		/* sectors per interrupt */
  	short	wdp_usedmovsd;		/* can use double word read/write? */
  };
  
  /*
--- 167,224 ----
  	short	wdp_necc;		/* ecc bytes appended */
  	char	wdp_rev[8];		/* firmware revision */
  	char	wdp_model[40];		/* model name */
! 	char	wdp_nsecperint;		/* sectors per interrupt */
! 	char	wdp_vendorunique1;
  	short	wdp_usedmovsd;		/* can use double word read/write? */
+ 	char	wdp_vendorunique2;
+ 	char	wdp_capability;		/* various capability bits */
+ 	short	wdp_cap_validate;	/* validation for above */
+ 	char	wdp_vendorunique3;
+ 	char	wdp_opiomode;		/* PIO modes 0-2 */
+ 	char	wdp_vendorunique4;
+ 	char	wdp_odmamode;		/* old DMA modes, not in ATA-3 */
+ 	short	wdp_atavalid;		/* validation for newer fields */
+ 	short	wdp_currcyls;
+ 	short	wdp_currheads;
+ 	short	wdp_currsectors;
+ 	short	wdp_currsize0;
+ 	short	wdp_currsize1;
+ 	char	wdp_currmultsect;
+ 	char	wdp_multsectvalid;
+ 	int	wdp_lbasize;
+ 	short	wdp_dmasword;		/* obsolete in ATA-3 */
+ 	short	wdp_dmamword;		/* multiword DMA modes */
+ 	short	wdp_eidepiomodes;	/* advanced PIO modes */
+ 	short	wdp_eidedmamin;		/* fastest possible DMA timing */
+ 	short	wdp_eidedmanorm;	/* recommended DMA timing */
+ 	short	wdp_eidepioblind;	/* fastest possible blind PIO */
+ 	short	wdp_eidepioacked;	/* fastest possible IORDY PIO */
+ 	short	wdp_reserved69;
+ 	short	wdp_reserved70;
+ 	short	wdp_reserved71;
+ 	short	wdp_reserved72;
+ 	short	wdp_reserved73;
+ 	short	wdp_reserved74;
+ 	short	wdp_queuelen;
+ 	short	wdp_reserved76;
+ 	short	wdp_reserved77;
+ 	short	wdp_reserved78;
+ 	short	wdp_reserved79;
+ 	short	wdp_versmaj;
+ 	short	wdp_versmin;
+ 	short	wdp_featsupp1;
+ 	short	wdp_featsupp2;
+ 	short	wdp_featsupp3;
+ 	short	wdp_featenab1;
+ 	short	wdp_featenab2;
+ 	short	wdp_featenab3;
+ 	short	wdp_udmamode;		/* UltraDMA modes */
+ 	short	wdp_erasetime;
+ 	short	wdp_enherasetime;
+ 	short	wdp_apmlevel;
+ 	short	wdp_reserved92[34];
+ 	short	wdp_rmvcap;
+ 	short	wdp_securelevel;
  };
  
  /*
*** sys/i386/isa/wd.c	Fri Jan 16 23:28:44 1998
--- /lion/FreeBSD-stable/sys/i386/isa/wd.c	Wed Apr 15 15:27:52 1998
***************
*** 116,121 ****
--- 116,123 ----
  				/* can't handle that in all cases */
  #define WDOPT_32BIT	0x8000
  #define WDOPT_SLEEPHACK	0x4000
+ #define WDOPT_DMA	0x2000
+ #define WDOPT_LBA	0x1000
  #define WDOPT_FORCEHD(x)	(((x)&0x0f00)>>8)
  #define WDOPT_MULTIMASK	0x00ff
  
***************
*** 179,184 ****
--- 181,191 ----
  #define	DKFL_32BIT	0x00100	/* use 32-bit i/o mode */
  #define	DKFL_MULTI	0x00200	/* use multi-i/o mode */
  #define	DKFL_BADSCAN	0x00400	/* report all errors */
+ #define DKFL_USEDMA	0x00800	/* use DMA for data transfers */
+ #define DKFL_DMA	0x01000 /* using DMA on this transfer-- DKFL_SINGLE
+ 				 * overrides this
+ 				 */
+ #define DKFL_LBA	0x02000	/* use LBA for data transfers */
  	struct wdparams dk_params; /* ESDI/IDE drive/controller parameters */
  	int	dk_dkunit;	/* disk stats unit number */
  	int	dk_multi;	/* multi transfers */
***************
*** 449,454 ****
--- 456,465 ----
  				dvp->id_unit, unit, lunit,
  				sizeof du->dk_params.wdp_model,
  				du->dk_params.wdp_model);
+ 			if (du->dk_flags & DKFL_LBA)
+ 				printf(", LBA");
+ 			if (du->dk_flags & DKFL_USEDMA)
+ 				printf(", DMA");
  			if (du->dk_flags & DKFL_32BIT)
  				printf(", 32-bit");
  			if (du->dk_multi > 1)
***************
*** 798,807 ****
  		u_int	count;
  		long	cylin, head, sector;
  
! 		cylin = blknum / secpercyl;
! 		head = (blknum % secpercyl) / secpertrk;
! 		sector = blknum % secpertrk;
! 
  		if (wdtab[ctrlr].b_errcnt && (bp->b_flags & B_READ) == 0)
  			du->dk_bc += DEV_BSIZE;
  		count = howmany( du->dk_bc, DEV_BSIZE);
--- 809,828 ----
  		u_int	count;
  		long	cylin, head, sector;
  
! 		if (du->dk_flags & DKFL_LBA) {
! 			sector = (blknum >> 0) & 0xff; 
! 			cylin = (blknum >> 8) & 0xffff;
! 			head = ((blknum >> 24) & 0xf) | WDSD_LBA; 
! 		}
! 		else {
! 			cylin = blknum / secpercyl;
! 			head = (blknum % secpercyl) / secpertrk;
! 			sector = blknum % secpertrk;
! 		}
! 		/* 
! 		 * XXX this looks like an attempt to skip bad sectors
! 		 * on write.
! 		 */
  		if (wdtab[ctrlr].b_errcnt && (bp->b_flags & B_READ) == 0)
  			du->dk_bc += DEV_BSIZE;
  		count = howmany( du->dk_bc, DEV_BSIZE);
***************
*** 1411,1420 ****
  		outb(wdc + wd_cyl_lo, cylinder);
  		outb(wdc + wd_cyl_hi, cylinder >> 8);
  		outb(wdc + wd_sdh, WDSD_IBM | (du->dk_unit << 4) | head);
! 		outb(wdc + wd_sector, sector + 1);
  		outb(wdc + wd_seccnt, count);
  	}
! 	if (wdwait(du, command == WDCC_DIAGNOSE || command == WDCC_IDC
  		       ? 0 : WDCS_READY, TIMEOUT) < 0)
  		return (1);
  	outb(wdc + wd_command, command);
--- 1432,1444 ----
  		outb(wdc + wd_cyl_lo, cylinder);
  		outb(wdc + wd_cyl_hi, cylinder >> 8);
  		outb(wdc + wd_sdh, WDSD_IBM | (du->dk_unit << 4) | head);
! 		if (head & WDSD_LBA)
! 			outb(wdc + wd_sector, sector);
! 		else
! 			outb(wdc + wd_sector, sector + 1);
  		outb(wdc + wd_seccnt, count);
  	}
! 	if (wdwait(du, (command == WDCC_DIAGNOSE || command == WDCC_IDC)
  		       ? 0 : WDCS_READY, TIMEOUT) < 0)
  		return (1);
  	outb(wdc + wd_command, command);
***************
*** 1458,1493 ****
  	       du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks,
  	       du->dk_dd.d_nsectors);
  #endif
! 	if (du->dk_dd.d_ntracks == 0 || du->dk_dd.d_ntracks > 16) {
! 		struct wdparams *wp;
! 
! 		printf("wd%d: can't handle %lu heads from partition table ",
! 		       du->dk_lunit, du->dk_dd.d_ntracks);
! 		/* obtain parameters */
! 		wp = &du->dk_params;
! 		if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) {
! 			printf("(controller value %u restored)\n",
! 				wp->wdp_heads);
! 			du->dk_dd.d_ntracks = wp->wdp_heads;
  		}
! 		else {
! 			printf("(truncating to 16)\n");
! 			du->dk_dd.d_ntracks = 16;
  		}
! 	}
! 
! 	if (du->dk_dd.d_nsectors == 0 || du->dk_dd.d_nsectors > 255) {
! 		printf("wd%d: cannot handle %lu sectors (max 255)\n",
! 		       du->dk_lunit, du->dk_dd.d_nsectors);
! 		error = 1;
! 	}
! 	if (error) {
  #ifdef CMD640 
! 		wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES;
  #else
! 		wdtab[du->dk_ctrlr].b_errcnt += RETRIES;
  #endif
! 		return (1);
  	}
  	if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0,
  		      du->dk_dd.d_nsectors, WDCC_IDC) != 0
--- 1482,1519 ----
  	       du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks,
  	       du->dk_dd.d_nsectors);
  #endif
! 	if (!(du->dk_flags & DKFL_LBA)) {
! 		if (du->dk_dd.d_ntracks == 0 || du->dk_dd.d_ntracks > 16) {
! 			struct wdparams *wp;
! 	
! 			printf("wd%d: can't handle %lu heads from partition table ",
! 		       	du->dk_lunit, du->dk_dd.d_ntracks);
! 			/* obtain parameters */
! 			wp = &du->dk_params;
! 			if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) {
! 				printf("(controller value %u restored)\n",
! 					wp->wdp_heads);
! 				du->dk_dd.d_ntracks = wp->wdp_heads;
! 			}
! 			else {
! 				printf("(truncating to 16)\n");
! 				du->dk_dd.d_ntracks = 16;
! 			}
  		}
! 	
! 		if (du->dk_dd.d_nsectors == 0 || du->dk_dd.d_nsectors > 255) {
! 			printf("wd%d: cannot handle %lu sectors (max 255)\n",
! 		       	du->dk_lunit, du->dk_dd.d_nsectors);
! 			error = 1;
  		}
! 		if (error) {
  #ifdef CMD640 
! 		  wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES;
  #else
! 		  wdtab[du->dk_ctrlr].b_errcnt += RETRIES;
  #endif
! 		  return (1);
! 		}
  	}
  	if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0,
  		      du->dk_dd.d_nsectors, WDCC_IDC) != 0
***************
*** 1694,1704 ****
  
  	/* update disklabel given drive information */
  	du->dk_dd.d_secsize = DEV_BSIZE;
! 	du->dk_dd.d_ncylinders = wp->wdp_cylinders;	/* +- 1 */
! 	du->dk_dd.d_ntracks = wp->wdp_heads;
! 	du->dk_dd.d_nsectors = wp->wdp_sectors;
! 	du->dk_dd.d_secpercyl = du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
! 	du->dk_dd.d_secperunit = du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
  	if (WDOPT_FORCEHD(du->cfg_flags)) {
  		du->dk_dd.d_ntracks = WDOPT_FORCEHD(du->cfg_flags);
  		du->dk_dd.d_secpercyl = 
--- 1720,1759 ----
  
  	/* update disklabel given drive information */
  	du->dk_dd.d_secsize = DEV_BSIZE;
! 	if ((du->cfg_flags & WDOPT_LBA) && wp->wdp_lbasize) {
! 		du->dk_dd.d_nsectors = 63;
! 		if (wp->wdp_lbasize < 16*63*1024) {		/* <=528.4 MB */
! 			du->dk_dd.d_ntracks = 16;
! 		}
! 		else if (wp->wdp_lbasize < 32*63*1024) {	/* <=1.057 GB */
! 			du->dk_dd.d_ntracks = 32;
! 		}
! 		else if (wp->wdp_lbasize < 64*63*1024) {	/* <=2.114 GB */
! 			du->dk_dd.d_ntracks = 64;
! 		}
! 		else if (wp->wdp_lbasize < 128*63*1024) {	/* <=4.228 GB */
! 			du->dk_dd.d_ntracks = 128;
! 		}
! 		else if (wp->wdp_lbasize < 128*63*1024) {	/* <=8.422 GB */
! 			du->dk_dd.d_ntracks = 255;
! 		}
! 		else {						/* >8.422 GB */
! 			du->dk_dd.d_ntracks = 255;		/* XXX */
! 		}
! 		du->dk_dd.d_secpercyl= du->dk_dd.d_ntracks*du->dk_dd.d_nsectors;
! 		du->dk_dd.d_ncylinders = wp->wdp_lbasize/du->dk_dd.d_secpercyl;
! 		du->dk_dd.d_secperunit = wp->wdp_lbasize;
! 		du->dk_flags |= DKFL_LBA;
! 	}
! 	else {
! 		du->dk_dd.d_ncylinders = wp->wdp_cylinders;	/* +- 1 */
! 		du->dk_dd.d_ntracks = wp->wdp_heads;
! 		du->dk_dd.d_nsectors = wp->wdp_sectors;
! 		du->dk_dd.d_secpercyl = 
! 			du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
! 		du->dk_dd.d_secperunit = 
! 			du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
! 	}
  	if (WDOPT_FORCEHD(du->cfg_flags)) {
  		du->dk_dd.d_ntracks = WDOPT_FORCEHD(du->cfg_flags);
  		du->dk_dd.d_secpercyl = 
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?m0yblh1-00023bC>