From 74f7c840cad3e1dff186088b4fb148193beea69c Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Tue, 29 Dec 2015 09:44:47 +0000 Subject: 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@) --- sys/dev/ata/atascsi.c | 22 +++++++++++++++++++++- sys/dev/ata/atascsi.h | 5 ++++- 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'sys/dev/ata') 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 @@ -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 @@ -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 */ -- cgit v1.2.3