On Tue, Dec 29, 2015 at 12:43:43AM +0100, Mark Kettenis wrote:
> I have an old Maxtor 7Y250M0 SATA drive that didn't quite work when
> attached to an Intel AHCI controller.  The drive was properly
> detected, but any attempt to read from the drive failed.  It worked
> fine if I switched the SATA controller into IDE mode in the BIOS, so
> the drive was fine.  Turns out our atascsi layer didn't set the
> transfer mode like our old wdc/pciide code does.  Fixing this
> omission makes the drive work.
> 
> It doesn't really make all that much sense doing this for a SATA drive
> since they don't really support different DMA modes.  But there is a
> PATA variant of the same drive, so I suppose somebody left an obselete
> check in the firmware code.
> 
> The diff below only checks for Ultra DMA modes.  All SATA drives
> should support those.  If we ever want to support ancient PATA drives
> over atascsi, some additional code will be needed.
> 
> ok?
> 
> 
> Index: atascsi.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ata/atascsi.c,v
> retrieving revision 1.125
> diff -u -p -r1.125 atascsi.c
> --- atascsi.c 28 Aug 2015 00:03:53 -0000      1.125
> +++ atascsi.c 28 Dec 2015 23:23:14 -0000
> @@ -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)
> @@ -363,6 +365,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

Catching up on holiday email, not sure if this already went in, but there
is a typo (drives not drivers) in the previous line.

-ml

> +      * 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) &&
> Index: atascsi.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/ata/atascsi.h,v
> retrieving revision 1.49
> diff -u -p -r1.49 atascsi.h
> --- atascsi.h 15 May 2015 10:54:26 -0000      1.49
> +++ atascsi.h 28 Dec 2015 23:23:14 -0000
> @@ -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 */
> 

Reply via email to