summaryrefslogtreecommitdiff
path: root/sys/dev/ata
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-12-29 09:44:47 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-12-29 09:44:47 +0000
commit74f7c840cad3e1dff186088b4fb148193beea69c (patch)
tree20afce67e29420583e7c235ff9b263c73448657e /sys/dev/ata
parent50e79a803f68420b63aa1c234d9fbb559b516596 (diff)
Set UltraDMA transfer mode. Some (early?) SATA drives, such as the Maxtor
7Y250M0, refuse to do DMA unless the transfer mode has been set. This causes reads (and presumably writes) to time out. Unlike the wdc code, this only sets the UltraDMA transfer mode. If we ever want to support ancient PATA drivers through the atascsi layer, we probably need to set the PIO and/or MWDMA transfer modes as well. ok jmatthew@, dlg@)
Diffstat (limited to 'sys/dev/ata')
-rw-r--r--sys/dev/ata/atascsi.c22
-rw-r--r--sys/dev/ata/atascsi.h5
2 files changed, 25 insertions, 2 deletions
diff --git a/sys/dev/ata/atascsi.c b/sys/dev/ata/atascsi.c
index bb825a90420..c4c67ffd3f3 100644
--- a/sys/dev/ata/atascsi.c
+++ b/sys/dev/ata/atascsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atascsi.c,v 1.125 2015/08/28 00:03:53 deraadt Exp $ */
+/* $OpenBSD: atascsi.c,v 1.126 2015/12/29 09:44:46 kettenis Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -266,6 +266,8 @@ atascsi_probe(struct scsi_link *link)
int port, type, qdepth;
int rv;
u_int16_t cmdset;
+ u_int16_t validinfo, ultradma;
+ int i, xfermode = -1;
port = link->target;
if (port >= as->as_link.adapter_buswidth)
@@ -364,6 +366,24 @@ atascsi_probe(struct scsi_link *link)
if (type != ATA_PORT_T_DISK)
return (0);
+ /*
+ * Early SATA drivers (as well as PATA drives) need to have
+ * their transfer mode set properly, otherwise commands that
+ * use DMA will time out.
+ */
+ validinfo = letoh16(ap->ap_identify.validinfo);
+ if (ISSET(validinfo, ATA_ID_VALIDINFO_ULTRADMA)) {
+ ultradma = letoh16(ap->ap_identify.ultradma);
+ for (i = 7; i >= 0; i--) {
+ if (ultradma & (1 << i)) {
+ xfermode = ATA_SF_XFERMODE_UDMA | i;
+ break;
+ }
+ }
+ }
+ if (xfermode != -1)
+ (void)atascsi_port_set_features(ap, ATA_SF_XFERMODE, xfermode);
+
if (as->as_capability & ASAA_CAP_NCQ &&
ISSET(letoh16(ap->ap_identify.satacap), ATA_SATACAP_NCQ) &&
(link->lun == 0 || as->as_capability & ASAA_CAP_PMP_NCQ)) {
diff --git a/sys/dev/ata/atascsi.h b/sys/dev/ata/atascsi.h
index ce15b954dc2..93e3021c8fd 100644
--- a/sys/dev/ata/atascsi.h
+++ b/sys/dev/ata/atascsi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: atascsi.h,v 1.49 2015/05/15 10:54:26 dlg Exp $ */
+/* $OpenBSD: atascsi.h,v 1.50 2015/12/29 09:44:46 kettenis Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -53,6 +53,8 @@ struct scsi_link;
* ATA SET FEATURES subcommands
*/
#define ATA_SF_WRITECACHE_EN 0x02
+#define ATA_SF_XFERMODE 0x03
+#define ATA_SF_XFERMODE_UDMA 0x40
#define ATA_SF_LOOKAHEAD_EN 0xaa
struct ata_identify {
@@ -77,6 +79,7 @@ struct ata_identify {
u_int16_t piomode; /* 51 */
u_int16_t dmamode; /* 52 */
u_int16_t validinfo; /* 53 */
+#define ATA_ID_VALIDINFO_ULTRADMA 0x0004
u_int16_t curcyls; /* 54 */
u_int16_t curheads; /* 55 */
u_int16_t cursectrk; /* 56 */