summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/atascsi.c
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2015-12-29 09:44:46 +0000
committerkettenis <kettenis@openbsd.org>2015-12-29 09:44:46 +0000
commit1d84b43843563672061fae076a97e99ab6eabc24 (patch)
treeb5aa58a1421947907b7de5c612479701cf7a79e6 /sys/dev/ata/atascsi.c
parentRemove NULL-checks before free(). (diff)
downloadwireguard-openbsd-1d84b43843563672061fae076a97e99ab6eabc24.tar.xz
wireguard-openbsd-1d84b43843563672061fae076a97e99ab6eabc24.zip
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/atascsi.c')
-rw-r--r--sys/dev/ata/atascsi.c22
1 files changed, 21 insertions, 1 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)) {