ATA/CHS problem (path + new information)

From: Roman Kurakin <rik_at_cronyx.ru>
Date: Sun, 11 Apr 2004 23:00:15 +0400
Hi,

You can find history of my previous postings below.

I didn't moved far since that time, because lack of time. But any way
I have some new information and one patch I want to share. This patch
didn't solve any of my problems.

Soren, please review it. This time it is comlete. I hope this
patch would allow to track down similar problems I have.

I remind you that now I have two problems. First one that FreeBSD uses
wrong assumption about which device should be CHS and which LBA:

if (!ad_version(atadev->param->version_major) ||
!(atadev->param->atavalid & ATA_FLAG_54_58) || !lbasize)
atadev->flags |= ATA_D_USE_CHS;

True ATA device may not have ATA_FLAG_54_58 valid bit, and also due
to last ATA standard this bit is obsoleted.

I also want to know why ata driver doesn't check LBA support from word 49?
May be this one check could solve my problems and didn't breake code for
non-ATA devices.

Second one, that only 20G part of my hard disk works with CHS. This is other
side of the same problem. Device should work in CHS mode. And it works
witch ICH5 controller. But with ICH2 it doesn't with out hack.

I've checked standard again and I sew command 91h (Initialize drive 
parameters).
YES, this command solved my problem witch CHS. But. But the life is no 
so easy :-)
This command fails itself with abort code. But as I said I can access 
sectors that was
previously NOT FOUND after it.
(ata_controlcmd (atadev,0x91, 0, 0xfUL << 24, 63); I've put it just 
after Identify driver
command in ata_getparam function)

Any comments and suggestions very very appreciated. And please do not 
suggest how
to fix this problem only for me. I already know a few variant that can't 
be commited.
I realy want to crush this bug.


rik

Roman Kurakin wrote:

> Hi,
>
> (Was "HDD question" on hackers_at_, posted also here cause this is also 
> CURRENT problem)
>
> History:
>
>> I have some problems with my HDD (ST380021A). The problem was 
>
>> checked on 5.2, 5.2.1, and some
>
>> 5.Current (cvsuped about week or two).
>>
>> At first I got this problem while system installation. I get trap 
>
>> and message from ata after I start a commit:
>
>> FAILURE READ_DMA status=51 <READY, DSC, ERROR> error=10 
>
>> <NID_NOT_FOUND> LBA=245529601
>
>>
>> I started to hack sysinstall and finally came to simple program 
>
>> that could lead
>
>> to the same message from ata:
>>
>> fd = open ("/dev/ata0", O_RDWR);
>> read_block (fd, (daddr_t)41929650, 512); // this one could be changed 
>
>> // to pair calls lseek and read,
>
>> // so this is not libdisk problem
>
>>
>> I checked the same code with /dev/ata1 which is twice as little, but 
>
>> I didn't get any messages.
>> I don't have any ideas where my read call goes, which drivers to look 
>
>> to catch this bug.
>
>>
>> So I need a help from some gurus in this area.
>
>
> What I've found since that time:
>
> This is not an LBA request. ATA driver thinks that I have 80G CHS 
> device, cause it's ATA_FLAG_54_58
> is zero. (This decision is incorrect, we shouldn't relay on this 
> flag). I've checked another seagate 80G drive in
> CHS mode(by driver hacking), and problematic one with LBA mode. I get 
> the same behavior on both with CHS.
> And both work fine in LBA mode. It also should be mentioned that I get 
> this problem on machine with
> ICH2 controller, and it seems that I don't have such problem on other 
> machine with ICH5.
>
> PS. If you have any ideas, or if you have any materials (standards for 
> example) about ATA/ATAPI and you
> can share them with me, please let me know. I am not ata developer, so 
> this is a bit difficalt for me to
> dig this problem.
>
> rik



diff -ubr ata-orig/ata-disk.c ata/ata-disk.c
--- ata-orig/ata-disk.c	Wed Mar 10 20:05:56 2004
+++ ata/ata-disk.c	Sun Apr 11 12:26:02 2004
_at__at_ -388,13 +388,14 _at__at_
 					(adp->heads * adp->sectors)),
 		   adp->heads, adp->sectors, DEV_BSIZE);
 
-	ata_prtdev(adp->device, "%d secs/int, %d depth queue, %s%s\n", 
+	ata_prtdev(adp->device, "%d secs/int, %d depth queue, %s%s%s\n", 
 		   adp->max_iosize / DEV_BSIZE, adp->num_tags + 1,
 		   (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
-		   ata_mode2str(adp->device->mode));
+		   ata_mode2str(adp->device->mode),
+		   (adp->device->flags & ATA_D_USE_CHS) ? "(CHS mode)": "");
     }
     else
-	ata_prtdev(adp->device,"%lluMB <%.40s> [%lld/%d/%d] at ata%d-%s %s%s\n",
+	ata_prtdev(adp->device,"%lluMB <%.40s> [%lld/%d/%d] at ata%d-%s %s%s%s\n",
 		   (unsigned long long)(adp->total_secs /
 					((1024L * 1024L) / DEV_BSIZE)),
 		   adp->device->param->model,
_at__at_ -404,7 +405,8 _at__at_
 		   device_get_unit(adp->device->channel->dev),
 		   (adp->device->unit == ATA_MASTER) ? "master" : "slave",
 		   (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
-		   ata_mode2str(adp->device->mode));
+		   ata_mode2str(adp->device->mode),
+		   (adp->device->flags & ATA_D_USE_CHS) ? " (CHS mode)": "");
 }
 
 static int
diff -ubr ata-orig/ata-queue.c ata/ata-queue.c
--- ata-orig/ata-queue.c	Tue Mar 23 20:39:22 2004
+++ ata/ata-queue.c	Sun Apr 11 19:00:05 2004
_at__at_ -47,6 +47,7 _at__at_
 /* prototypes */
 static void ata_completed(void *, int);
 static void ata_timeout(struct ata_request *);
+static void ata_print_lba (u_int64_t lba, int non_lba_mode);
 static char *ata_skey2str(u_int8_t);
 
 void
_at__at_ -278,7 +279,8 _at__at_
 		       "WARNING - %s soft error (ECC corrected)",
 		       ata_cmd2str(request));
 	    if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
-		printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
+	        ata_print_lba (request->u.ata.lba,
+			       request->device->flags & ATA_D_USE_CHS);
 	    printf("\n");
 	}
 
_at__at_ -289,7 +291,8 _at__at_
 			   "WARNING - %s UDMA ICRC error (retrying request)",
 			   ata_cmd2str(request));
 		if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
-		    printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
+	            ata_print_lba (request->u.ata.lba,
+			           request->device->flags & ATA_D_USE_CHS);
 		printf("\n");
 		request->flags |= (ATA_R_IMMEDIATE | ATA_R_REQUEUE);
 		ata_queue_request(request);
_at__at_ -316,7 +319,8 _at__at_
 		    (request->dmastat & ATA_BMSTAT_ERROR))
 		    printf(" dma=0x%02x", request->dmastat);
 		if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
-		    printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
+	            ata_print_lba (request->u.ata.lba,
+			           request->device->flags & ATA_D_USE_CHS);
 		printf("\n");
 	    }
 
_at__at_ -420,7 +424,8 _at__at_
 		       "WARNING - %s interrupt was seen but timeout fired",
 		       ata_cmd2str(request));
 	    if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
-		printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
+	        ata_print_lba (request->u.ata.lba,
+			       request->device->flags & ATA_D_USE_CHS);
 	    printf("\n");
 
 	    /* re-arm timeout */
_at__at_ -435,7 +440,8 _at__at_
 		       "WARNING - %s interrupt was seen but taskqueue stalled",
 		       ata_cmd2str(request));
 	    if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
-		printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
+	        ata_print_lba (request->u.ata.lba,
+			       request->device->flags & ATA_D_USE_CHS);
 	    printf("\n");
 	    ata_completed(request, 0);
 	}
_at__at_ -449,7 +455,8 _at__at_
 		   ata_cmd2str(request), request->retries,
 		   request->retries == 1 ? "y" : "ies");
 	if (!(request->flags & (ATA_R_ATAPI | ATA_R_CONTROL)))
-	    printf(" LBA=%llu", (unsigned long long)request->u.ata.lba);
+	    ata_print_lba (request->u.ata.lba,
+			   request->device->flags & ATA_D_USE_CHS);
 	printf("\n");
     }
 
_at__at_ -618,5 +625,18 _at__at_
     case 0x0e: return ("MISCOMPARE");
     case 0x0f: return ("RESERVED");
     default: return("UNKNOWN");
+    }
+}
+
+static void
+ata_print_lba (u_int64_t lba, int non_lba_mode)
+{
+    if (!non_lba_mode) {
+	printf(" LBA=%llu", (unsigned long long)lba);
+    } else {
+	printf(" CHS=%u/%u/%u",
+	       (unsigned int)((lba >> 8) & 0xffff),
+	       (unsigned int)((lba >> 24) & 0xf),
+	       (unsigned int)(lba & 0xff));
     }
 }
Received on Sun Apr 11 2004 - 09:55:29 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:50 UTC