summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2007-04-06 16:18:59 +0000
committersos <sos@FreeBSD.org>2007-04-06 16:18:59 +0000
commitad1c8d45dd9e00e35ba116b6533afa81d61ba468 (patch)
tree201e448cb2148165a217198cea1f94fee5c60221
parent6bf6173310e7cae2c2f38a95c34f0158596cb441 (diff)
downloadFreeBSD-src-ad1c8d45dd9e00e35ba116b6533afa81d61ba468.zip
FreeBSD-src-ad1c8d45dd9e00e35ba116b6533afa81d61ba468.tar.gz
Add support for 64bit addressing to AHCI and Marvell controllers.
Munged into ATA shape and Marvell specifics my yours truely. Submitted by: jhb
-rw-r--r--sys/dev/ata/ata-all.h1
-rw-r--r--sys/dev/ata/ata-chipset.c29
-rw-r--r--sys/dev/ata/ata-dma.c10
-rw-r--r--sys/dev/ata/ata-lowlevel.c1
-rw-r--r--sys/dev/ata/ata_if.m2
5 files changed, 28 insertions, 15 deletions
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 2b410a0..31da23b 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -445,6 +445,7 @@ struct ata_dma {
#define ATA_DMA_READ 0x01 /* transaction is a read */
#define ATA_DMA_LOADED 0x02 /* DMA tables etc loaded */
#define ATA_DMA_ACTIVE 0x04 /* DMA transfer in progress */
+#define ATA_DMA_64BIT 0x10 /* supports 64bit addressing */
void (*alloc)(device_t dev);
void (*free)(device_t dev);
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index be7451b..38ba71b 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -503,6 +503,7 @@ ata_ahci_allocate(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
+ u_int64_t work;
int offset = ch->unit << 7;
/* set the SATA resources */
@@ -521,13 +522,13 @@ ata_ahci_allocate(device_t dev)
ch->hw.command = NULL; /* not used here */
/* setup work areas */
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset,
- ch->dma->work_bus + ATA_AHCI_CL_OFFSET);
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, 0x00000000);
+ work = ch->dma->work_bus + ATA_AHCI_CL_OFFSET;
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32);
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset,
- ch->dma->work_bus + ATA_AHCI_FB_OFFSET);
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, 0x00000000);
+ work = ch->dma->work_bus + ATA_AHCI_FB_OFFSET;
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32);
/* enable wanted port interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset,
@@ -766,6 +767,7 @@ ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
static void
ata_ahci_dmainit(device_t dev)
{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
ata_dmainit(dev);
@@ -773,6 +775,8 @@ ata_ahci_dmainit(device_t dev)
/* note start and stop are not used here */
ch->dma->setprd = ata_ahci_dmasetprd;
ch->dma->max_iosize = 8192 * DEV_BSIZE;
+ if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_64BIT)
+ ch->dma->flags |= ATA_DMA_64BIT;
}
}
@@ -2417,7 +2421,7 @@ ata_marvell_edma_allocate(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- bus_addr_t work = ch->dma->work_bus;
+ u_int64_t work = ch->dma->work_bus;
int i;
/* clear work area */
@@ -2470,7 +2474,7 @@ ata_marvell_edma_allocate(device_t dev)
ATA_OUTL(ctlr->r_res1, 0x02000 + ATA_MV_EDMA_BASE(ch), (1<<11) | (1<<13));
/* request queue base high */
- ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), (work >> 16) >> 16);
+ ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), work >> 32);
/* request queue in ptr */
ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff);
@@ -2480,7 +2484,7 @@ ata_marvell_edma_allocate(device_t dev)
/* response queue base high */
work += 1024;
- ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), (work >> 16) >> 16);
+ ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), work >> 32);
/* response queue in ptr */
ATA_OUTL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch), 0x0);
@@ -2568,7 +2572,7 @@ ata_marvell_edma_begin_transaction(struct ata_request *request)
/* fill in this request */
quadp[0] = (long)ch->dma->sg_bus & 0xffffffff;
- quadp[1] = (ch->dma->sg_bus & 0xffffffff00000000ull) >> 32;
+ quadp[1] = (u_int64_t)ch->dma->sg_bus >> 32;
wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (tag<<1);
i = 10;
@@ -2721,12 +2725,17 @@ ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs,
static void
ata_marvell_edma_dmainit(device_t dev)
{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
ata_dmainit(dev);
if (ch->dma) {
/* note start and stop are not used here */
ch->dma->setprd = ata_marvell_edma_dmasetprd;
+
+device_printf(dev, "HW qword=%08x\n", ATA_INL(ctlr->r_res1, 0x00d00));
+ if (ATA_INL(ctlr->r_res1, 0x00d00) & 0x00000004)
+ ch->dma->flags |= ATA_DMA_64BIT;
}
}
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index 0c1ecaf..fbe23f0 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -95,22 +95,24 @@ ata_dmaalloc(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
struct ata_dc_cb_args ccba;
+ int maxaddr = (ch->dma->flags & ATA_DMA_64BIT ?
+ BUS_SPACE_MAXADDR : BUS_SPACE_MAXADDR_32BIT);
if (bus_dma_tag_create(bus_get_dma_tag(dev), ch->dma->alignment, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
+ maxaddr, BUS_SPACE_MAXADDR,
NULL, NULL, ch->dma->max_iosize,
ATA_DMA_ENTRIES, ch->dma->segsize,
0, NULL, NULL, &ch->dma->dmatag))
goto error;
if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, PAGE_SIZE,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
+ maxaddr, BUS_SPACE_MAXADDR,
NULL, NULL, MAXTABSZ, 1, MAXTABSZ,
0, NULL, NULL, &ch->dma->sg_tag))
goto error;
if (bus_dma_tag_create(ch->dma->dmatag,ch->dma->alignment,ch->dma->boundary,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
+ maxaddr, BUS_SPACE_MAXADDR,
NULL, NULL, ch->dma->max_iosize,
ATA_DMA_ENTRIES, ch->dma->segsize,
0, NULL, NULL, &ch->dma->data_tag))
@@ -131,7 +133,7 @@ ata_dmaalloc(device_t dev)
goto error;
if (bus_dma_tag_create(ch->dma->dmatag, PAGE_SIZE, 64 * 1024,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
+ maxaddr, BUS_SPACE_MAXADDR,
NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ,
0, NULL, NULL, &ch->dma->work_tag))
goto error;
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index 4150865..07e7184 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -102,6 +102,7 @@ ata_begin_transaction(struct ata_request *request)
/* device reset doesn't interrupt */
if (request->u.ata.command == ATA_DEVICE_RESET) {
+
int timeout = 1000000;
do {
DELAY(10);
diff --git a/sys/dev/ata/ata_if.m b/sys/dev/ata/ata_if.m
index 19d6987..2621fef 100644
--- a/sys/dev/ata/ata_if.m
+++ b/sys/dev/ata/ata_if.m
@@ -1,4 +1,4 @@
-# Copyright (c) 2004 - 2006 Søren Schmidt <sos@FreeBSD.org>
+# Copyright (c) 2004 - 2007 Søren Schmidt <sos@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
OpenPOWER on IntegriCloud