ServerWorks/Broadcom HT1000 chipset errata saga
Xin LI
delphij at delphij.net
Mon Jan 7 14:28:13 PST 2008
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Travis Mikalson wrote:
> Nick Pope wrote:
>> I csup'ed to latest RELENG_7_0 (RC1) and built the GENERIC kernel.
>> I'm assuming Soren's patch has made it into RC1 because, without
>> commenting out the rr232x driver, the kernel mis-detects my Supermicro
>> PCI-X SATA controller (MV88SX6081 chipset) as an rr232x.
>
> No, Søren's HT1000/Marvell fixing stuff is still in HEAD only according
> to cvsweb. Did not make it to RELENG_7 or RELENG_7_0 yet.
>
> I think your problem is unrelated to this patchset.
>
> It wasn't making any sense that any of this code that was touched would
> have any effect on detection of your Marvell device anyway...
Here is a patch that brings the HT1000 changeset back to RELENG_7 and
RELENG_7_0. Newer change by phk@ seems to be harmless, but it does not
have effect for HT1000 either.
Cheers,
- --
Xin LI <delphij at delphij.net> http://www.delphij.net/
FreeBSD - The Power to Serve!
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4 (FreeBSD)
iD8DBQFHgqdoi+vbBBjt66ARAj/8AKCn6Ar4gxVbEvKPXVmLVnwEV6QWJgCgpRef
TJhBZGIJqvuvkZoifOkTcXs=
=2gRs
-----END PGP SIGNATURE-----
-------------- next part --------------
Index: ata-all.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-all.h,v
retrieving revision 1.124.2.1
diff -u -p -r1.124.2.1 ata-all.h
--- ata-all.h 21 Nov 2007 21:15:00 -0000 1.124.2.1
+++ ata-all.h 7 Jan 2008 22:17:41 -0000
@@ -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 */
Index: ata-chipset.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-chipset.c,v
retrieving revision 1.202.2.5
diff -u -p -r1.202.2.5 ata-chipset.c
--- ata-chipset.c 9 Dec 2007 19:26:56 -0000 1.202.2.5
+++ ata-chipset.c 7 Jan 2008 22:17:56 -0000
@@ -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;
}
Index: ata-dma.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-dma.c,v
retrieving revision 1.147.2.1
diff -u -p -r1.147.2.1 ata-dma.c
--- ata-dma.c 21 Nov 2007 21:15:00 -0000 1.147.2.1
+++ ata-dma.c 7 Jan 2008 22:18:10 -0000
@@ -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;
Index: ata-lowlevel.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-lowlevel.c,v
retrieving revision 1.79
diff -u -p -r1.79 ata-lowlevel.c
--- ata-lowlevel.c 6 Apr 2007 16:18:59 -0000 1.79
+++ ata-lowlevel.c 7 Jan 2008 22:18:25 -0000
@@ -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
More information about the freebsd-current
mailing list