From owner-freebsd-bugs Tue May 19 05:44:36 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id FAA03538 for freebsd-bugs-outgoing; Tue, 19 May 1998 05:44:36 -0700 (PDT) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id FAA03523 for ; Tue, 19 May 1998 05:44:30 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.8/8.8.5) id FAA27939; Tue, 19 May 1998 05:40:01 -0700 (PDT) Received: from mail.artcom.de ([192.76.129.2]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id FAA02783 for ; Tue, 19 May 1998 05:40:35 -0700 (PDT) (envelope-from hans@artcom.de) Received: by mail.artcom.de id m0yblh1-00023bC; Tue, 19 May 1998 14:40:31 +0200 (CEST) Message-Id: Date: Tue, 19 May 1998 14:40:31 +0200 (CEST) From: hans@artcom.de To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.2 Subject: kern/6686: -stable does not support large IDE drives Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >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