NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/42122: larger than 2TB drives can't be properly found at boot



The following reply was made to PR kern/42122; it has been noted by GNATS.

From: David Holland <dholland-bugs%netbsd.org@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: kern/42122: larger than 2TB drives can't be properly found at
        boot
Date: Thu, 28 Jan 2010 05:18:08 +0000

 (wasn't sent to gnats-bugs)
 
    ------
 
 From: Michael van Elst <mlelstv%serpens.de@localhost>
 To: gnats%netbsd.org@localhost
 Subject: Re: kern/42122: larger than 2TB drives can't be properly found at
        boot
 Date: Mon, 25 Jan 2010 13:54:06 +0100
 
 
 The Array should return -1 with read_capacity_10 to signal
 that read_capacity_16 is required. Apparently this is not
 implemented right. A workaround is to try the read_capacity_16
 first and retry with read_capacity_10 if the command wasn't
 accepted (Invalid Command).
 
 Does this patch help?
 
 Index: sd.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/scsipi/sd.c,v
 retrieving revision 1.290
 diff -u -r1.290 sd.c
 --- sd.c       21 Oct 2009 21:12:05 -0000      1.290
 +++ sd.c       25 Jan 2010 11:26:14 -0000
 @@ -1679,9 +1679,7 @@
                struct scsipi_read_capacity_16_data data16;
        } *datap;
        uint64_t rv;
 -
 -      memset(&cmd, 0, sizeof(cmd));
 -      cmd.cmd.opcode = READ_CAPACITY_10;
 +      int error;
  
        /*
         * Don't allocate data buffer on stack;
 @@ -1693,43 +1691,44 @@
        if (datap == NULL)
                return 0;
  
 -      /*
 -       * If the command works, interpret the result as a 4 byte
 -       * number of blocks
 -       */
        rv = 0;
 -      memset(datap, 0, sizeof(datap->data));
 -      if (scsipi_command(periph, (void *)&cmd.cmd, sizeof(cmd.cmd),
 -          (void *)datap, sizeof(datap->data), SCSIPIRETRIES, 20000, NULL,
 -          flags | XS_CTL_DATA_IN | XS_CTL_SILENT) != 0)
 -              goto out;
 -
 -      if (_4btol(datap->data.addr) != 0xffffffff) {
 -              *blksize = _4btol(datap->data.length);
 -              rv = _4btol(datap->data.addr) + 1;
 -              goto out;
 -      }
  
        /*
 -       * Device is larger than can be reflected by READ CAPACITY (10).
 -       * Try READ CAPACITY (16).
 +       * Try READ CAPACITY (16) first, some disks don't return
 +       * a correct overflow with READ CAPACITY (10).
         */
 -
        memset(&cmd, 0, sizeof(cmd));
        cmd.cmd16.opcode = READ_CAPACITY_16;
        cmd.cmd16.byte2 = SRC16_SERVICE_ACTION;
        _lto4b(sizeof(datap->data16), cmd.cmd16.len);
  
        memset(datap, 0, sizeof(datap->data16));
 -      if (scsipi_command(periph, (void *)&cmd.cmd16, sizeof(cmd.cmd16),
 +      error = scsipi_command(periph, (void *)&cmd.cmd16, sizeof(cmd.cmd16),
            (void *)datap, sizeof(datap->data16), SCSIPIRETRIES, 20000, NULL,
 -          flags | XS_CTL_DATA_IN | XS_CTL_SILENT) != 0)
 -              goto out;
 +          flags | XS_CTL_DATA_IN | XS_CTL_SILENT);
  
 -      *blksize = _4btol(datap->data16.length);
 -      rv = _8btol(datap->data16.addr) + 1;
 +      if (error == 0) {
 +              *blksize = _4btol(datap->data16.length);
 +              rv = _8btol(datap->data16.addr) + 1;
 +      } else if (error == EINVAL) {
 +              /*
 +               * Fall back to READ CAPACITY (10)
 +               */
 +              memset(&cmd, 0, sizeof(cmd));
 +              cmd.cmd.opcode = READ_CAPACITY_10;
 +
 +              memset(datap, 0, sizeof(datap->data));
 +              error = scsipi_command(periph, (void *)&cmd.cmd, 
sizeof(cmd.cmd),
 +                  (void *)datap, sizeof(datap->data), SCSIPIRETRIES, 20000, 
NULL,
 +                  flags | XS_CTL_DATA_IN | XS_CTL_SILENT);
 +              if (error == 0) {
 +                      if (_4btol(datap->data.addr) != 0xffffffff) {
 +                              *blksize = _4btol(datap->data.length);
 +                              rv = _4btol(datap->data.addr) + 1;
 +                      }
 +              }
 +      }
  
 - out:
        free(datap, M_TEMP);
        return rv;
  }
 
 -- 
                                 Michael van Elst
 Internet: mlelstv%serpens.de@localhost
                                 "A potential Snark may lurk in every tree."
 


Home | Main Index | Thread Index | Old Index