AHCI: Prevent sign extension of partial address
authorFergus Simpson <afergs@google.com>
Thu, 20 Oct 2016 19:00:55 +0000 (12:00 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 20 Oct 2016 19:18:06 +0000 (15:18 -0400)
Drive reads were not working past the 1 TiB mark because the resulting
address was negative. This was determined to be an issue with an
unsigned char getting sign extended when bit shifted into an int64_t.
It is now cast to a uint32_t after the shift to prevent sign extension.
The container was also changed from int64_t to uint64_t.

Change-Id: I590b0da4fd0c02b0e2542a0b65bde510bba89525
Signed-off-by: Fergus Simpson <afergs@google.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/sdiahci.c

index 172b854..811fc05 100644 (file)
@@ -1943,7 +1943,7 @@ static int iario(struct sdreq *r)
 {
        ERRSTACK(2);
        int i, n, count, try, max, flag, task;
-       int64_t lba;
+       uint64_t lba;
        char *name;
        unsigned char *cmd, *data;
        void *port;
@@ -1978,7 +1978,9 @@ static int iario(struct sdreq *r)
                return SDcheck;
        }
 
-       lba = cmd[2] << 24 | cmd[3] << 16 | cmd[4] << 8 | cmd[5];
+       // TODO: make cmd bigger to support drives with >= 2 TiB capacity,
+       // with 32 bits and 512 B blocks only 2^(9+32) = 2 TiB addressable
+       lba = (uint32_t)(cmd[2] << 24) | cmd[3] << 16 | cmd[4] << 8 | cmd[5];
        count = cmd[7] << 8 | cmd[8];
        if (r->data == NULL)
                return SDok;