diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2015-12-29 09:44:47 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2015-12-29 09:44:47 +0000 |
commit | 74f7c840cad3e1dff186088b4fb148193beea69c (patch) | |
tree | 20afce67e29420583e7c235ff9b263c73448657e /sys/dev/ata | |
parent | 50e79a803f68420b63aa1c234d9fbb559b516596 (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.c | 22 | ||||
-rw-r--r-- | sys/dev/ata/atascsi.h | 5 |
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 */ |