From owner-freebsd-current@FreeBSD.ORG Wed Dec 19 23:06:26 2007 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1C96616A418 for ; Wed, 19 Dec 2007 23:06:26 +0000 (UTC) (envelope-from bofh@terranova.net) Received: from tog.net (tog.net [216.89.226.5]) by mx1.freebsd.org (Postfix) with ESMTP id B7C7613C46B for ; Wed, 19 Dec 2007 23:06:25 +0000 (UTC) (envelope-from bofh@terranova.net) Received: from [216.89.228.170] (host-216-89-228-170.wireless.terranova.net [216.89.228.170]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by tog.net (Postfix) with ESMTP id C29AB29B5FA for ; Wed, 19 Dec 2007 18:06:24 -0500 (EST) Message-ID: <4769A3F0.709@terranova.net> Date: Wed, 19 Dec 2007 18:06:24 -0500 From: Travis Mikalson Organization: TerraNovaNet Internet Services User-Agent: Thunderbird 1.5.0.13 (Windows/20070809) MIME-Version: 1.0 To: freebsd-current@freebsd.org Content-Type: multipart/mixed; boundary="------------090903010000020605060607" Subject: ServerWorks/Broadcom HT1000 chipset errata saga X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 19 Dec 2007 23:06:26 -0000 This is a multi-part message in MIME format. --------------090903010000020605060607 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit As far as I can tell, Søren has the HT1000 problems worked out, or at least worked around. (If the chipset doesn't do that correctly, stop doing that...) If you want to see the specifics, check out his commits to HEAD on December 13th, 2007 in src/sys/dev/ata or look at the attached patch which includes same. RELENG_6 disclaimer: I haven't tried RELENG_6 with his fixes yet, and RELENG_6 seemed to have even stranger issues with HT1000 than RELENG_7 did. In theory, though, this stuff should apply cleanly to RELENG_6. This does need testing on RELENG_6 still. I took Søren's Dec 13th commits and made a little patchset out of it that applies to RELENG_7 and it has been working great for me using my HT1000 motherboard's on-board SATA controller. This set of fixes should also have the similar problem with the Marvell chipset SATA controllers fixed, though I haven't been able to confirm that yet myself. See attached patch, *please* test for RELENG_7 and report back here so re@ can feel a lot more warm and fuzzy about including this in RELENG_7 before 7.0-RELEASE occurs. It would be fantastic if 7.0-RELEASE worked right out of the box for people using HT1000-based motherboards. Thanks, -T -- TerraNovaNet Internet Services - Key Largo, FL Voice: (305)453-4011 x101 Fax: (305)451-5991 http://www.terranova.net/ ---------------------------------------------- Life's not fair, but the root password helps. --------------090903010000020605060607 Content-Type: text/plain; name="sata-patch1" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sata-patch1" --- src/sys/dev/ata/ata-all.h 2007/11/21 21:15:00 1.124.2.1 +++ src/sys/dev/ata/ata-all.h 2007/12/13 11:47:36 1.126 @@ -464,6 +464,8 @@ struct ata_lowlevel { int (*begin_transaction)(struct ata_request *request); int (*end_transaction)(struct ata_request *request); int (*command)(struct ata_request *request); + void (*tf_read)(struct ata_request *request); + void (*tf_write)(struct ata_request *request); }; /* structure holding resources for an ATA channel */ --- src/sys/dev/ata/ata-chipset.c 2007/12/07 13:14:31 1.210 +++ src/sys/dev/ata/ata-chipset.c 2007/12/13 11:47:36 1.211 @@ -99,7 +99,7 @@ static void ata_intel_new_setmode(device static void ata_intel_sata_setmode(device_t dev, int mode); static int ata_intel_31244_allocate(device_t dev); static int ata_intel_31244_status(device_t dev); -static int ata_intel_31244_command(struct ata_request *request); +static void ata_intel_31244_tf_write(struct ata_request *request); static void ata_intel_31244_reset(device_t dev); static int ata_ite_chipinit(device_t dev); static void ata_ite_setmode(device_t dev, int mode); @@ -152,6 +152,8 @@ static void ata_promise_queue_hpkt(struc static void ata_promise_next_hpkt(struct ata_pci_controller *ctlr); static int ata_serverworks_chipinit(device_t dev); static int ata_serverworks_allocate(device_t dev); +static void ata_serverworks_tf_read(struct ata_request *request); +static void ata_serverworks_tf_write(struct ata_request *request); static void ata_serverworks_setmode(device_t dev, int mode); static int ata_sii_chipinit(device_t dev); static int ata_cmd_allocate(device_t dev); @@ -2093,7 +2095,7 @@ ata_intel_31244_allocate(device_t dev) ch->flags |= ATA_NO_SLAVE; ata_pci_hw(dev); ch->hw.status = ata_intel_31244_status; - ch->hw.command = ata_intel_31244_command; + ch->hw.tf_write = ata_intel_31244_tf_write; /* enable PHY state change interrupt */ ATA_OUTL(ctlr->r_res2, 0x4, @@ -2111,32 +2113,55 @@ ata_intel_31244_status(device_t dev) return ata_pci_status(dev); } -static int -ata_intel_31244_command(struct ata_request *request) +static void +ata_intel_31244_tf_write(struct ata_request *request) { struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); struct ata_device *atadev = device_get_softc(request->dev); - u_int64_t lba; - - if (!(atadev->flags & ATA_D_48BIT_ACTIVE)) - return (ata_generic_command(request)); - - lba = request->u.ata.lba; - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit); - /* enable interrupt */ - ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT); - ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); - ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); - ATA_IDX_OUTW(ch, ATA_SECTOR, ((lba >> 16) & 0xff00) | (lba & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((lba >> 24) & 0xff00) | - ((lba >> 8) & 0x00ff)); - ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((lba >> 32) & 0xff00) | - ((lba >> 16) & 0x00ff)); - /* issue command to controller */ - ATA_IDX_OUTB(ch, ATA_COMMAND, request->u.ata.command); - - return 0; + if (atadev->flags & ATA_D_48BIT_ACTIVE) { + ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); + ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); + ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) | + (request->u.ata.lba & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) | + ((request->u.ata.lba >> 8) & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | + ((request->u.ata.lba >> 16) & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit); + } + else { + ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); + ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); + if (atadev->flags & ATA_D_USE_CHS) { + int heads, sectors; + + if (atadev->param.atavalid & ATA_FLAG_54_58) { + heads = atadev->param.current_heads; + sectors = atadev->param.current_sectors; + } + else { + heads = atadev->param.heads; + sectors = atadev->param.sectors; + } + ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, + (request->u.ata.lba / (sectors * heads))); + ATA_IDX_OUTB(ch, ATA_CYL_MSB, + (request->u.ata.lba / (sectors * heads)) >> 8); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit | + (((request->u.ata.lba% (sectors * heads)) / + sectors) & 0xf)); + } + else { + ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); + ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); + ATA_IDX_OUTB(ch, ATA_DRIVE, + ATA_D_IBM | ATA_D_LBA | atadev->unit | + ((request->u.ata.lba >> 24) & 0x0f)); + } + } } static void @@ -2849,8 +2874,12 @@ ata_marvell_edma_dmainit(device_t dev) /* note start and stop are not used here */ ch->dma->setprd = ata_marvell_edma_dmasetprd; + /* if 64bit support present adjust max address used */ if (ATA_INL(ctlr->r_res1, 0x00d00) & 0x00000004) ch->dma->max_address = BUS_SPACE_MAXADDR; + + /* chip does not reliably do 64K DMA transfers */ + ch->dma->max_iosize = 126 * DEV_BSIZE; } } @@ -4248,10 +4277,97 @@ ata_serverworks_allocate(device_t dev) ch->flags |= ATA_NO_SLAVE; ata_pci_hw(dev); + ch->hw.tf_read = ata_serverworks_tf_read; + ch->hw.tf_write = ata_serverworks_tf_write; + + /* chip does not reliably do 64K DMA transfers */ + if (ch->dma) + ch->dma->max_iosize = 126 * DEV_BSIZE; + return 0; } static void +ata_serverworks_tf_read(struct ata_request *request) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); + struct ata_device *atadev = device_get_softc(request->dev); + + if (atadev->flags & ATA_D_48BIT_ACTIVE) { + u_int16_t temp; + + request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT); + temp = ATA_IDX_INW(ch, ATA_SECTOR); + request->u.ata.lba = (u_int64_t)(temp & 0x00ff) | + ((u_int64_t)(temp & 0xff00) << 24); + temp = ATA_IDX_INW(ch, ATA_CYL_LSB); + request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 8) | + ((u_int64_t)(temp & 0xff00) << 32); + temp = ATA_IDX_INW(ch, ATA_CYL_MSB); + request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 16) | + ((u_int64_t)(temp & 0xff00) << 40); + } + else { + request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT) & 0x00ff; + request->u.ata.lba = (ATA_IDX_INW(ch, ATA_SECTOR) & 0x00ff) | + ((ATA_IDX_INW(ch, ATA_CYL_LSB) & 0x00ff) << 8) | + ((ATA_IDX_INW(ch, ATA_CYL_MSB) & 0x00ff) << 16) | + ((ATA_IDX_INW(ch, ATA_DRIVE) & 0xf) << 24); + } +} + +static void +ata_serverworks_tf_write(struct ata_request *request) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); + struct ata_device *atadev = device_get_softc(request->dev); + + if (atadev->flags & ATA_D_48BIT_ACTIVE) { + ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); + ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); + ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) | + (request->u.ata.lba & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) | + ((request->u.ata.lba >> 8) & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | + ((request->u.ata.lba >> 16) & 0x00ff)); + ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit); + } + else { + ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); + ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); + if (atadev->flags & ATA_D_USE_CHS) { + int heads, sectors; + + if (atadev->param.atavalid & ATA_FLAG_54_58) { + heads = atadev->param.current_heads; + sectors = atadev->param.current_sectors; + } + else { + heads = atadev->param.heads; + sectors = atadev->param.sectors; + } + ATA_IDX_OUTW(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1); + ATA_IDX_OUTW(ch, ATA_CYL_LSB, + (request->u.ata.lba / (sectors * heads))); + ATA_IDX_OUTW(ch, ATA_CYL_MSB, + (request->u.ata.lba / (sectors * heads)) >> 8); + ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit | + (((request->u.ata.lba% (sectors * heads)) / + sectors) & 0xf)); + } + else { + ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba); + ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); + ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); + ATA_IDX_OUTW(ch, ATA_DRIVE, + ATA_D_IBM | ATA_D_LBA | atadev->unit | + ((request->u.ata.lba >> 24) & 0x0f)); + } + } +} + +static void ata_serverworks_setmode(device_t dev, int mode) { device_t gparent = GRANDPARENT(dev); @@ -4562,7 +4678,7 @@ ata_sii_allocate(device_t dev) if ((ctlr->chip->cfg2 & SIIBUG) && ch->dma) { /* work around errata in early chips */ - ch->dma->boundary = 16 * DEV_BSIZE; + ch->dma->boundary = 8192; ch->dma->segsize = 15 * DEV_BSIZE; } --- src/sys/dev/ata/ata-dma.c 2007/11/20 04:52:19 1.149 +++ src/sys/dev/ata/ata-dma.c 2007/12/13 11:47:36 1.150 @@ -75,7 +75,7 @@ ata_dmainit(device_t dev) ch->dma->load = ata_dmaload; ch->dma->unload = ata_dmaunload; ch->dma->alignment = 2; - ch->dma->boundary = 128 * DEV_BSIZE; + ch->dma->boundary = 65536; ch->dma->segsize = 128 * DEV_BSIZE; ch->dma->max_iosize = 128 * DEV_BSIZE; ch->dma->max_address = BUS_SPACE_MAXADDR_32BIT; --- src/sys/dev/ata/ata-lowlevel.c 2007/04/06 16:18:59 1.79 +++ src/sys/dev/ata/ata-lowlevel.c 2007/12/13 11:47:36 1.80 @@ -50,6 +50,8 @@ static int ata_generic_status(device_t d static int ata_wait(struct ata_channel *ch, struct ata_device *, u_int8_t); static void ata_pio_read(struct ata_request *, int); static void ata_pio_write(struct ata_request *, int); +static void ata_tf_read(struct ata_request *); +static void ata_tf_write(struct ata_request *); /* * low level ATA functions @@ -63,6 +65,8 @@ ata_generic_hw(device_t dev) ch->hw.end_transaction = ata_end_transaction; ch->hw.status = ata_generic_status; ch->hw.command = ata_generic_command; + ch->hw.tf_read = ata_tf_read; + ch->hw.tf_write = ata_tf_write; } /* must be called with ATA channel locked and state_mtx held */ @@ -244,28 +248,7 @@ ata_end_transaction(struct ata_request * /* on control commands read back registers to the request struct */ if (request->flags & ATA_R_CONTROL) { - if (atadev->flags & ATA_D_48BIT_ACTIVE) { - ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT | ATA_A_HOB); - request->u.ata.count = (ATA_IDX_INB(ch, ATA_COUNT) << 8); - request->u.ata.lba = - ((u_int64_t)(ATA_IDX_INB(ch, ATA_SECTOR)) << 24) | - ((u_int64_t)(ATA_IDX_INB(ch, ATA_CYL_LSB)) << 32) | - ((u_int64_t)(ATA_IDX_INB(ch, ATA_CYL_MSB)) << 40); - - ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT); - request->u.ata.count |= ATA_IDX_INB(ch, ATA_COUNT); - request->u.ata.lba |= - (ATA_IDX_INB(ch, ATA_SECTOR) | - (ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) | - (ATA_IDX_INB(ch, ATA_CYL_MSB) << 16)); - } - else { - request->u.ata.count = ATA_IDX_INB(ch, ATA_COUNT); - request->u.ata.lba = ATA_IDX_INB(ch, ATA_SECTOR) | - (ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) | - (ATA_IDX_INB(ch, ATA_CYL_MSB) << 16) | - ((ATA_IDX_INB(ch, ATA_DRIVE) & 0xf) << 24); - } + ch->hw.tf_read(request); } /* if we got an error we are done with the HW */ @@ -734,57 +717,96 @@ ata_generic_command(struct ata_request * ATA_PROTO_ATAPI_12 ? 6 : 8); } else { - if (atadev->flags & ATA_D_48BIT_ACTIVE) { - ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8); - ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); - ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count >> 8); - ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); - ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba >> 24); - ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); - ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 32); - ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); - ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 40); - ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit); - } - else { - ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); - ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); - if (atadev->flags & ATA_D_USE_CHS) { - int heads, sectors; + ch->hw.tf_write(request); + + /* issue command to controller */ + ATA_IDX_OUTB(ch, ATA_COMMAND, request->u.ata.command); + } + return 0; +} + +static void +ata_tf_read(struct ata_request *request) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); + struct ata_device *atadev = device_get_softc(request->dev); + + if (atadev->flags & ATA_D_48BIT_ACTIVE) { + ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT | ATA_A_HOB); + request->u.ata.count = (ATA_IDX_INB(ch, ATA_COUNT) << 8); + request->u.ata.lba = + ((u_int64_t)(ATA_IDX_INB(ch, ATA_SECTOR)) << 24) | + ((u_int64_t)(ATA_IDX_INB(ch, ATA_CYL_LSB)) << 32) | + ((u_int64_t)(ATA_IDX_INB(ch, ATA_CYL_MSB)) << 40); + + ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT); + request->u.ata.count |= ATA_IDX_INB(ch, ATA_COUNT); + request->u.ata.lba |= + (ATA_IDX_INB(ch, ATA_SECTOR) | + (ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) | + (ATA_IDX_INB(ch, ATA_CYL_MSB) << 16)); + } + else { + request->u.ata.count = ATA_IDX_INB(ch, ATA_COUNT); + request->u.ata.lba = ATA_IDX_INB(ch, ATA_SECTOR) | + (ATA_IDX_INB(ch, ATA_CYL_LSB) << 8) | + (ATA_IDX_INB(ch, ATA_CYL_MSB) << 16) | + ((ATA_IDX_INB(ch, ATA_DRIVE) & 0xf) << 24); + } +} + +static void +ata_tf_write(struct ata_request *request) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(request->dev)); + struct ata_device *atadev = device_get_softc(request->dev); + + if (atadev->flags & ATA_D_48BIT_ACTIVE) { + ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature >> 8); + ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); + ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count >> 8); + ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); + ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba >> 24); + ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 32); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); + ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 40); + ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit); + } + else { + ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); + ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); + if (atadev->flags & ATA_D_USE_CHS) { + int heads, sectors; - if (atadev->param.atavalid & ATA_FLAG_54_58) { - heads = atadev->param.current_heads; - sectors = atadev->param.current_sectors; - } - else { - heads = atadev->param.heads; - sectors = atadev->param.sectors; - } - ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1); - ATA_IDX_OUTB(ch, ATA_CYL_LSB, - (request->u.ata.lba / (sectors * heads))); - ATA_IDX_OUTB(ch, ATA_CYL_MSB, - (request->u.ata.lba / (sectors * heads)) >> 8); - ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit | - (((request->u.ata.lba% (sectors * heads)) / - sectors) & 0xf)); + if (atadev->param.atavalid & ATA_FLAG_54_58) { + heads = atadev->param.current_heads; + sectors = atadev->param.current_sectors; } else { - ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); - ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); - ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); - ATA_IDX_OUTB(ch, ATA_DRIVE, - ATA_D_IBM | ATA_D_LBA | atadev->unit | - ((request->u.ata.lba >> 24) & 0x0f)); + heads = atadev->param.heads; + sectors = atadev->param.sectors; } - } - /* issue command to controller */ - ATA_IDX_OUTB(ch, ATA_COMMAND, request->u.ata.command); + ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, + (request->u.ata.lba / (sectors * heads))); + ATA_IDX_OUTB(ch, ATA_CYL_MSB, + (request->u.ata.lba / (sectors * heads)) >> 8); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit | + (((request->u.ata.lba% (sectors * heads)) / + sectors) & 0xf)); + } + else { + ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); + ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); + ATA_IDX_OUTB(ch, ATA_DRIVE, + ATA_D_IBM | ATA_D_LBA | atadev->unit | + ((request->u.ata.lba >> 24) & 0x0f)); + } } - - return 0; } static void --------------090903010000020605060607--