From 7ebce0231b0752baa2e2d594802a57bcaf344842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Schmidt?= Date: Wed, 12 Oct 2005 20:00:26 +0000 Subject: [PATCH] Add support for the ATI IXP[234]00 series chipsets. HW donated by: sentex --- sys/dev/ata/ata-chipset.c | 113 +++++++++++++++++++++++++++++++++++++- sys/dev/ata/ata-pci.c | 4 ++ sys/dev/ata/ata-pci.h | 9 +++ sys/dev/ata/ata-raid.c | 1 + 4 files changed, 126 insertions(+), 1 deletion(-) diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index a5af06ed1ba..e800f2d062c 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); @@ -1110,6 +1112,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 */ @@ -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 0222ef518e5..43a0a0a3f29 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 99a1fb10483..b09afcbcd89 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 f0b9eb829d9..ce08bd8747e 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;