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>
index | next in thread | raw e-mail
>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
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?m0yblh1-00023bC>
