diff options
author | 2015-12-29 09:44:46 +0000 | |
---|---|---|
committer | 2015-12-29 09:44:46 +0000 | |
commit | 1d84b43843563672061fae076a97e99ab6eabc24 (patch) | |
tree | b5aa58a1421947907b7de5c612479701cf7a79e6 /sys/dev/ata/atascsi.c | |
parent | Remove NULL-checks before free(). (diff) | |
download | wireguard-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.c | 22 |
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)) { |