summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2007-12-07 13:14:31 +0000
committersos <sos@FreeBSD.org>2007-12-07 13:14:31 +0000
commit9bc486376bf7bd1de04b93b8ed2688cf3b4dfc11 (patch)
tree22ef244df17780ed62692bd45a7d8ccfd5bb5bac /sys
parent0845b2053ba8c7d8dfc58162fb571300edcc73cc (diff)
downloadFreeBSD-src-9bc486376bf7bd1de04b93b8ed2688cf3b4dfc11.zip
FreeBSD-src-9bc486376bf7bd1de04b93b8ed2688cf3b4dfc11.tar.gz
Fix speed report on Intel SATA chips in compat mode.
Fix broken detect of JMicron 368.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ata/ata-chipset.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index f784946..d0a95e7 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -96,6 +96,7 @@ static int ata_intel_allocate(device_t dev);
static void ata_intel_reset(device_t dev);
static void ata_intel_old_setmode(device_t dev, int mode);
static void ata_intel_new_setmode(device_t dev, int mode);
+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);
@@ -1859,8 +1860,15 @@ ata_intel_chipinit(device_t dev)
(pci_read_config(dev, 0x90, 1) & 0xc0) &&
(ata_ahci_chipinit(dev) != ENXIO))
return 0;
-
- ctlr->setmode = ata_sata_setmode;
+
+ /* if BAR(5) is IO it should point to SATA interface registers */
+ ctlr->r_type2 = SYS_RES_IOPORT;
+ ctlr->r_rid2 = PCIR_BAR(5);
+ if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
+ &ctlr->r_rid2, RF_ACTIVE)))
+ ctlr->setmode = ata_intel_sata_setmode;
+ else
+ ctlr->setmode = ata_sata_setmode;
/* enable PCI interrupt */
pci_write_config(dev, PCIR_COMMAND,
@@ -1872,12 +1880,21 @@ ata_intel_chipinit(device_t dev)
static int
ata_intel_allocate(device_t dev)
{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
/* setup the usual register normal pci style */
if (ata_pci_allocate(dev))
return ENXIO;
+ /* if r_res2 is valid it points to SATA interface registers */
+ if (ctlr->r_res2) {
+ ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
+ ch->r_io[ATA_IDX_ADDR].offset = 0x00;
+ ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2;
+ ch->r_io[ATA_IDX_DATA].offset = 0x04;
+ }
+
ch->flags |= ATA_ALWAYS_DMASTAT;
return 0;
}
@@ -2004,6 +2021,38 @@ ata_intel_new_setmode(device_t dev, int mode)
atadev->mode = mode;
}
+static void
+ata_intel_sata_setmode(device_t dev, int mode)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+
+ if (atadev->param.satacapabilities != 0x0000 &&
+ atadev->param.satacapabilities != 0xffff) {
+
+ struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+ int devno = (ch->unit << 1) + ATA_DEV(atadev->unit);
+
+ /* on some drives we need to set the transfer mode */
+ ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
+ ata_limit_mode(dev, mode, ATA_UDMA6));
+
+ /* set ATA_SSTATUS register offset */
+ ATA_IDX_OUTL(ch, ATA_IDX_ADDR, devno * 0x100);
+
+ /* query SATA STATUS for the speed */
+ if ((ATA_IDX_INL(ch, ATA_IDX_DATA) & ATA_SS_CONWELL_MASK) ==
+ ATA_SS_CONWELL_GEN2)
+ atadev->mode = ATA_SA300;
+ else
+ atadev->mode = ATA_SA150;
+ }
+ else {
+ mode = ata_limit_mode(dev, mode, ATA_UDMA5);
+ if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
+ atadev->mode = mode;
+ }
+}
+
static int
ata_intel_31244_allocate(device_t dev)
{
@@ -2260,7 +2309,7 @@ ata_jmicron_chipinit(device_t dev)
pci_write_config(dev, 0x40, 0x80c0a131, 4);
pci_write_config(dev, 0x80, 0x01200000, 4);
- if ((error = ata_ahci_chipinit(dev)))
+ if (ctlr->chip->cfg1 && (error = ata_ahci_chipinit(dev)))
return error;
ctlr->allocate = ata_jmicron_allocate;
OpenPOWER on IntegriCloud