summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2005-10-12 20:00:26 +0000
committersos <sos@FreeBSD.org>2005-10-12 20:00:26 +0000
commite52c6023e63fb6a76b24587c9f4b384326a7c4e9 (patch)
tree26be3138a55d4fe1bd79beca46297c27d45bb6b0 /sys/dev/ata
parentd6130a47038460d2093bdc0fcdadd546393cc823 (diff)
downloadFreeBSD-src-e52c6023e63fb6a76b24587c9f4b384326a7c4e9.zip
FreeBSD-src-e52c6023e63fb6a76b24587c9f4b384326a7c4e9.tar.gz
Add support for the ATI IXP[234]00 series chipsets.
HW donated by: sentex
Diffstat (limited to 'sys/dev/ata')
-rw-r--r--sys/dev/ata/ata-chipset.c113
-rw-r--r--sys/dev/ata/ata-pci.c4
-rw-r--r--sys/dev/ata/ata-pci.h9
-rw-r--r--sys/dev/ata/ata-raid.c1
4 files changed, 126 insertions, 1 deletions
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index a5af06e..e800f2d 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -77,6 +77,8 @@ static int ata_ali_sata_allocate(device_t dev);
static void ata_ali_reset(device_t dev);
static void ata_ali_setmode(device_t dev, int mode);
static int ata_amd_chipinit(device_t dev);
+static int ata_ati_chipinit(device_t dev);
+static void ata_ati_setmode(device_t dev, int mode);
static int ata_cyrix_chipinit(device_t dev);
static void ata_cyrix_setmode(device_t dev, int mode);
static int ata_cypress_chipinit(device_t dev);
@@ -1111,6 +1113,115 @@ ata_amd_chipinit(device_t dev)
/*
+ * ATI chipset support functions
+ */
+int
+ata_ati_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_ATI_IXP200, 0x00, 0, 0, ATA_UDMA5, "ATI IXP200" },
+ { ATA_ATI_IXP300, 0x00, 0, 0, ATA_UDMA6, "ATI IXP300" },
+ { ATA_ATI_IXP400, 0x00, 0, 0, ATA_UDMA6, "ATI IXP400" },
+ { ATA_ATI_IXP300_S1, 0x00, SIIMEMIO, 0, ATA_SA150, "ATI IXP300" },
+ { ATA_ATI_IXP400_S1, 0x00, SIIMEMIO, 0, ATA_SA150, "ATI IXP400" },
+ { ATA_ATI_IXP400_S2, 0x00, SIIMEMIO, 0, ATA_SA150, "ATI IXP400" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+
+ /* the ATI SATA controller is actually a SiI 3112 controller*/
+ if (ctlr->chip->cfg1 & SIIMEMIO)
+ ctlr->chipinit = ata_sii_chipinit;
+ else
+ ctlr->chipinit = ata_ati_chipinit;
+ return 0;
+}
+
+static int
+ata_ati_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_setup_interrupt(dev))
+ return ENXIO;
+
+ ctlr->setmode = ata_ati_setmode;
+ return 0;
+}
+
+static void
+ata_ati_setmode(device_t dev, int mode)
+{
+ device_t gparent = GRANDPARENT(dev);
+ struct ata_pci_controller *ctlr = device_get_softc(gparent);
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ struct ata_device *atadev = device_get_softc(dev);
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+ int offset = (devno ^ 0x01) << 3;
+ int error;
+ u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
+ u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 };
+
+ mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
+
+ mode = ata_check_80pin(dev, mode);
+
+ error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
+
+ if (bootverbose)
+ device_printf(dev, "%ssetting %s on %s chip\n",
+ (error) ? "FAILURE " : "",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ if (mode >= ATA_UDMA0) {
+ pci_write_config(gparent, 0x56,
+ (pci_read_config(gparent, 0x56, 2) &
+ ~(0xf << (devno << 2))) |
+ ((mode & ATA_MODE_MASK) << (devno << 2)), 2);
+ pci_write_config(gparent, 0x54,
+ pci_read_config(gparent, 0x54, 1) |
+ (0x01 << devno), 1);
+ pci_write_config(gparent, 0x44,
+ (pci_read_config(gparent, 0x44, 4) &
+ ~(0xff << offset)) |
+ (dmatimings[2] << offset), 4);
+ }
+ else if (mode >= ATA_WDMA0) {
+ pci_write_config(gparent, 0x54,
+ pci_read_config(gparent, 0x54, 1) &
+ ~(0x01 << devno), 1);
+ pci_write_config(gparent, 0x44,
+ (pci_read_config(gparent, 0x44, 4) &
+ ~(0xff << offset)) |
+ (dmatimings[mode & ATA_MODE_MASK] << offset), 4);
+ }
+ else
+ pci_write_config(gparent, 0x54,
+ pci_read_config(gparent, 0x54, 1) &
+ ~(0x01 << devno), 1);
+
+ pci_write_config(gparent, 0x4a,
+ (pci_read_config(gparent, 0x4a, 2) &
+ ~(0xf << (devno << 2))) |
+ (((mode - ATA_PIO0) & ATA_MODE_MASK) << (devno<<2)),2);
+ pci_write_config(gparent, 0x40,
+ (pci_read_config(gparent, 0x40, 4) &
+ ~(0xff << offset)) |
+ (piotimings[ata_mode2idx(mode)] << offset), 4);
+ atadev->mode = mode;
+ }
+}
+
+/*
* Cyrix chipset support functions
*/
int
@@ -3260,7 +3371,7 @@ ata_serverworks_setmode(device_t dev, int mode)
pci_write_config(gparent, 0x44,
(pci_read_config(gparent, 0x44, 4) &
~(0xff << offset)) |
- (dmatimings[mode & ATA_MODE_MASK] << offset),4);
+ (dmatimings[mode & ATA_MODE_MASK] << offset), 4);
}
else
pci_write_config(gparent, 0x54,
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index 0222ef5..43a0a0a 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -90,6 +90,10 @@ ata_pci_probe(device_t dev)
if (!ata_amd_ident(dev))
return 0;
break;
+ case ATA_ATI_ID:
+ if (!ata_ati_ident(dev))
+ return 0;
+ break;
case ATA_CYRIX_ID:
if (!ata_cyrix_ident(dev))
return 0;
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index 99a1fb1..b09afcb 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -97,6 +97,14 @@ struct ata_connect_task {
#define ATA_ALI_5288 0x528810b9
#define ATA_ALI_5289 0x528910b9
+#define ATA_ATI_ID 0x1002
+#define ATA_ATI_IXP200 0x43491002
+#define ATA_ATI_IXP300 0x43691002
+#define ATA_ATI_IXP400 0x43761002
+#define ATA_ATI_IXP300_S1 0x436e1002
+#define ATA_ATI_IXP400_S1 0x43791002
+#define ATA_ATI_IXP400_S2 0x437a1002
+
#define ATA_CENATEK_ID 0x16ca
#define ATA_CENATEK_ROCKET 0x000116ca
@@ -373,6 +381,7 @@ int ata_generic_ident(device_t);
int ata_acard_ident(device_t);
int ata_ali_ident(device_t);
int ata_amd_ident(device_t);
+int ata_ati_ident(device_t);
int ata_cyrix_ident(device_t);
int ata_cypress_ident(device_t);
int ata_highpoint_ident(device_t);
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
index f0b9eb8..ce08bd8 100644
--- a/sys/dev/ata/ata-raid.c
+++ b/sys/dev/ata/ata-raid.c
@@ -1225,6 +1225,7 @@ ata_raid_read_metadata(device_t subdisk)
return 0;
break;
+ case ATA_ATI_ID:
case ATA_SILICON_IMAGE_ID:
if (ata_raid_sii_read_meta(subdisk, ata_raid_arrays))
return 0;
OpenPOWER on IntegriCloud