NetBSD-Bugs archive

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

Re: kern/39511: ataraid(4): Intel MatrixRAID support



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

From: Juan RP <xtraeme%gmail.com@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: 
Subject: Re: kern/39511: ataraid(4): Intel MatrixRAID support
Date: Wed, 10 Sep 2008 17:14:17 +0200

 Here's the patch:
 
 Index: share/man/man4/ataraid.4
 ===================================================================
 RCS file: /cvsroot/src/share/man/man4/ataraid.4,v
 retrieving revision 1.10
 diff -b -u -p -r1.10 ataraid.4
 --- share/man/man4/ataraid.4   5 Sep 2008 13:38:58 -0000       1.10
 +++ share/man/man4/ataraid.4   10 Sep 2008 15:11:41 -0000
 @@ -27,7 +27,7 @@
  .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  .\" POSSIBILITY OF SUCH DAMAGE.
  .\"
 -.Dd September 5, 2008
 +.Dd September 10, 2008
  .Dt ATARAID 4
  .Os
  .Sh NAME
 @@ -35,6 +35,7 @@
  .Nd software BIOS RAID
  .Sh SYNOPSIS
  .Cd "pseudo-device ataraid"
 +.Cd "ld* at ataraid? vendtype ? unit ?"
  .Sh DESCRIPTION
  The
  .Nm
 @@ -50,6 +51,8 @@ The driver currently supports RAID forma
  .It
  Adaptec HostRAID (found in Intel 6300ESB)
  .It
 +Intel MatrixRAID
 +.It
  JMicron RAID
  .It
  nVidia MediaShield
 @@ -83,3 +86,7 @@ state, and it does not do the right thin
  .Pp
  At least part of the reason for this is that the publically-available
  information on these formats is quite limited.
 +.Pp
 +The support with Intel MatrixRAID controller is incomplete, and only
 +the first volume found will be used. This will be fixed in future
 +revisions of this driver.
 Index: sys/dev/ata/ata_raid.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ata/ata_raid.c,v
 retrieving revision 1.31
 diff -b -u -p -r1.31 ata_raid.c
 --- sys/dev/ata/ata_raid.c     5 Sep 2008 12:37:13 -0000       1.31
 +++ sys/dev/ata/ata_raid.c     10 Sep 2008 15:11:41 -0000
 @@ -116,7 +116,8 @@ ata_raid_type_name(u_int type)
                "Adaptec",
                "VIA V-RAID",
                "nVidia",
 -              "JMicron"
 +              "JMicron",
 +              "Intel MatrixRAID"
        };
  
        if (type < __arraycount(ata_raid_type_names))
 @@ -250,6 +251,8 @@ ata_raid_check_component(device_t self)
                return;
        if (ata_raid_read_config_jmicron(sc) == 0)
                return;
 +      if (ata_raid_read_config_intel(sc) == 0)
 +              return;
  }
  
  struct ataraid_array_info *
 Index: sys/dev/ata/ata_raid_intel.c
 ===================================================================
 RCS file: sys/dev/ata/ata_raid_intel.c
 diff -N sys/dev/ata/ata_raid_intel.c
 --- /dev/null  1 Jan 1970 00:00:00 -0000
 +++ sys/dev/ata/ata_raid_intel.c       10 Sep 2008 15:11:41 -0000
 @@ -0,0 +1,281 @@
 +/*    $NetBSD$        */
 +
 +/*-
 + * Copyright (c) 2000-2008 S_ren Schmidt <sos%FreeBSD.org@localhost>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer,
 + *    without modification, immediately at the beginning of the file.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +/*
 + * Support for parsing Intel MatrixRAID controller configuration blocks.
 + *
 + * Adapted to NetBSD by Juan Romero Pardines (xtraeme%gmail.org@localhost).
 + */
 +
 +#include <sys/cdefs.h>
 +__KERNEL_RCSID(0, "$NetBSD: ata_raid_jmicron.c,v 1.1 2008/09/05 12:37:13 tron 
Exp $");
 +
 +#include <sys/param.h>
 +#include <sys/buf.h>
 +#include <sys/bufq.h>
 +#include <sys/conf.h>
 +#include <sys/device.h>
 +#include <sys/disk.h>
 +#include <sys/disklabel.h>
 +#include <sys/fcntl.h>
 +#include <sys/malloc.h>
 +#include <sys/vnode.h>
 +#include <sys/kauth.h>
 +
 +#include <miscfs/specfs/specdev.h>
 +
 +#include <dev/ata/atareg.h>
 +#include <dev/ata/atavar.h>
 +#include <dev/ata/wdvar.h>
 +
 +#include <dev/ata/ata_raidreg.h>
 +#include <dev/ata/ata_raidvar.h>
 +
 +#ifdef ATA_RAID_DEBUG
 +#define       DPRINTF(x)      printf x
 +#else
 +#define       DPRINTF(x)      /* nothing */
 +#endif
 +
 +#ifdef ATA_RAID_DEBUG
 +static const char *
 +ata_raid_intel_type(int type)
 +{
 +      static char buffer[16];
 +
 +      switch (type) {
 +      case INTEL_T_RAID0:
 +              return "RAID0";
 +      case INTEL_T_RAID1:
 +              return "RAID1";
 +      case INTEL_T_RAID5:
 +              return "RAID5";
 +      default:
 +              sprintf(buffer, "UNKNOWN 0x%02x", type);
 +              return buffer;
 +      }
 +}
 +
 +static void
 +ata_raid_intel_print_info(struct intel_raid_conf *info)
 +{
 +      struct intel_raid_mapping *map;
 +      int i, j;
 + 
 +      printf("********* ATA Intel MatrixRAID Metadata *********\n");
 +      printf("intel_id                <%.24s>\n", info->intel_id);
 +      printf("version                 <%.6s>\n", info->version);
 +      printf("checksum                0x%08x\n", info->checksum);
 +      printf("config_size             0x%08x\n", info->config_size);
 +      printf("config_id               0x%08x\n", info->config_id);
 +      printf("generation              0x%08x\n", info->generation);
 +      printf("total_disks             %u\n", info->total_disks);
 +      printf("total_volumes           %u\n", info->total_volumes);
 +      printf("DISK#   serial  disk    sectors disk_id flags\n");
 +      for (i = 0; i < info->total_disks; i++) {
 +              printf("    %d <%16.s> %u 0x%08x 0x%08x\n",
 +                  i, info->disk[i].serial, info->disk[i].sectors,
 +                  info->disk[i].id, info->disk[i].flags);
 +      }
 +
 +      map = (struct intel_raid_mapping *)&info->disk[info->total_disks];
 +      for (j = 0; j < info->total_volumes; j++) {
 +              printf("name            %.16s\n", map->name);
 +              printf("total_sectors   %ju\n", map->total_sectors);
 +              printf("state           %u\n", map->state);
 +              printf("reserved        %u\n", map->reserved);
 +              printf("offset          %u\n", map->offset);
 +              printf("disk_sectors    %u\n", map->disk_sectors);
 +              printf("stripe_count    %u\n", map->stripe_count);
 +              printf("stripe_sectors  %u\n", map->stripe_sectors);
 +              printf("status          %u\n", map->status);
 +              printf("type            %s\n", ata_raid_intel_type(map->type));
 +              printf("total_disks     %u\n", map->total_disks);
 +              printf("magic[0]        0x%02x\n", map->magic[0]);
 +              printf("magic[1]        0x%02x\n", map->magic[1]);
 +              printf("magic[2]        0x%02x\n", map->magic[2]);
 +              for (i = 0; i < map->total_disks; i++)
 +                      printf("    disk %d at disk_idx 0x%08x\n",
 +                          i, map->disk_idx[i]);
 +
 +              map = (struct intel_raid_mapping *)
 +                  &map->disk_idx[map->total_disks];
 +      }
 +      printf("=================================================\n");
 +}
 +#endif
 +
 +int
 +ata_raid_read_config_intel(struct wd_softc *sc)
 +{
 +      struct intel_raid_conf *info;
 +      struct intel_raid_mapping *map;
 +      struct ataraid_array_info *aai;
 +      struct ataraid_disk_info *adi;
 +      struct vnode *vp;
 +      uint32_t checksum, *ptr;
 +      static int curdrive;
 +      int bmajor, count, error = 0;
 +      char *tmp;
 +      dev_t dev;
 +
 +      info = malloc(1536, M_DEVBUF, M_WAITOK|M_ZERO);
 +
 +      bmajor = devsw_name2blk(device_xname(sc->sc_dev), NULL, 0);
 +
 +      /* Get a vnode for the raw partition of this disk. */
 +      dev = MAKEDISKDEV(bmajor, device_unit(sc->sc_dev), RAW_PART);
 +      error = bdevvp(dev, &vp);
 +      if (error)
 +              goto out;
 +
 +      error = VOP_OPEN(vp, FREAD, NOCRED);
 +      if (error) {
 +              vput(vp);
 +              goto out;
 +      }
 +
 +      error = ata_raid_config_block_rw(vp, INTEL_LBA(sc), info,
 +          1024, B_READ);
 +      VOP_CLOSE(vp, FREAD, NOCRED);
 +      vput(vp);
 +      if (error) {
 +              DPRINTF(("%s: error %d reading Intel MatrixRAID config block\n",
 +                  device_xname(sc->sc_dev), error));
 +              goto out;
 +      }
 +
 +      tmp = (char *)info;
 +      (void)memcpy(tmp + 1024, tmp, 512);
 +      (void)memcpy(tmp, tmp + 512, 1024);
 +      (void)memset(tmp + 1024, 0, 512);
 +
 +      /* Check if this is a Intel RAID struct */
 +      if (strncmp(info->intel_id, INTEL_MAGIC, strlen(INTEL_MAGIC))) {
 +              DPRINTF(("%s: Intel MatrixRAID signature check failed\n",
 +                  device_xname(sc->sc_dev)));
 +              error = ESRCH;
 +              goto out;
 +      }
 +
 +      /* calculate checksum and compare for valid */
 +      for (checksum = 0, ptr = (uint32_t *)info, count = 0;
 +           count < (info->config_size / sizeof(uint32_t)); count++)
 +              checksum += *ptr++;
 +
 +      checksum -= info->checksum;
 +      if (checksum != info->checksum) {
 +              DPRINTF(("%s: Intel MatrixRAID checksum failed 0x%x != 0x%x\n",
 +                  device_xname(sc->sc_dev), checksum, info->checksum));
 +              error = ESRCH;
 +              goto out;
 +      }
 +
 +#ifdef ATA_RAID_DEBUG
 +      ata_raid_intel_print_info(info);
 +#endif
 +
 +      /* This one points to the first volume */
 +      map = (struct intel_raid_mapping *)&info->disk[info->total_disks];
 +
 +      /*
 +       * Lookup or allocate a new array info structure for this array.
 +       *
 +       * TODO:
 +       * We only look at the first volume. Need to solve a few issues before
 +       * multiple volumes are working correctly.
 +       */
 +      aai = ata_raid_get_array_info(ATA_RAID_TYPE_INTEL, 0); 
 +
 +      /* Fill in array info */
 +      aai->aai_generation = info->generation;
 +      aai->aai_status = AAI_S_READY;
 +
 +      switch (map->type) {
 +      case INTEL_T_RAID0:
 +              aai->aai_level = AAI_L_RAID0;
 +              aai->aai_width = info->total_disks;
 +              break;
 +      case INTEL_T_RAID1:
 +              aai->aai_level = AAI_L_RAID1;
 +              aai->aai_width = 1;
 +              break;
 +      default:
 +              DPRINTF(("%s: unknown Intel MatrixRAID type 0x%02x\n",
 +                  sc->sc_dev->dv_xname, map->type));
 +              error = EINVAL;
 +              goto out;
 +      }
 +
 +      switch (map->state) {
 +      case INTEL_S_DEGRADED:
 +              aai->aai_status |= AAI_S_DEGRADED;
 +              break;
 +      case INTEL_S_DISABLED:
 +      case INTEL_S_FAILURE:
 +              aai->aai_status &= ~AAI_S_READY;
 +              break;
 +      }
 +
 +      aai->aai_type = ATA_RAID_TYPE_INTEL;
 +      aai->aai_capacity = map->total_sectors;
 +      aai->aai_interleave = map->stripe_sectors;
 +      aai->aai_ndisks = map->total_disks;
 +      aai->aai_heads = 255;
 +      aai->aai_sectors = 63;
 +      aai->aai_cylinders =
 +          aai->aai_capacity / (aai->aai_heads * aai->aai_sectors);
 +      aai->aai_offset = map->offset;
 +      aai->aai_reserved = 3;
 +
 +      /* Fill in disk info */
 +      adi = &aai->aai_disks[curdrive];
 +      adi->adi_status = 0;
 +
 +      if (info->disk[curdrive].flags & INTEL_F_ONLINE)
 +              adi->adi_status |= ADI_S_ONLINE;
 +      if (info->disk[curdrive].flags & INTEL_F_ASSIGNED)
 +              adi->adi_status |= ADI_S_ASSIGNED;
 +      if (info->disk[curdrive].flags & INTEL_F_SPARE) {
 +              adi->adi_status &= ~ADI_S_ONLINE;
 +              adi->adi_status |= ADI_S_SPARE;
 +      }
 +      if (info->disk[curdrive].flags & INTEL_F_DOWN)
 +              adi->adi_status &= ~ADI_S_ONLINE;
 +
 +      if (adi->adi_status) {
 +              adi->adi_dev = sc->sc_dev;
 +              adi->adi_sectors = info->disk[curdrive].sectors;
 +              adi->adi_compsize = adi->adi_sectors - aai->aai_reserved;
 +              curdrive++;
 +      }
 +
 + out:
 +      free(info, M_DEVBUF);
 +      return error;
 +}
 Index: sys/dev/ata/ata_raidreg.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ata/ata_raidreg.h,v
 retrieving revision 1.7
 diff -b -u -p -r1.7 ata_raidreg.h
 --- sys/dev/ata/ata_raidreg.h  5 Sep 2008 12:37:13 -0000       1.7
 +++ sys/dev/ata/ata_raidreg.h  10 Sep 2008 15:11:42 -0000
 @@ -293,4 +293,67 @@ struct jmicron_raid_conf {
        uint8_t         filler_5[384];
  };
  
 +/* Intel MatrixRAID metadata */
 +#define INTEL_LBA(wd)         ((wd)->sc_capacity - 3)
 +
 +struct intel_raid_conf {
 +      uint8_t         intel_id[24];
 +#define INTEL_MAGIC           "Intel Raid ISM Cfg Sig. "
 +
 +      uint8_t         version[6];
 +#define INTEL_VERSION_1100    "1.1.00"
 +#define INTEL_VERSION_1201    "1.2.01"
 +#define INTEL_VERSION_1202    "1.2.02"
 +
 +      uint8_t         dummy_0[2];
 +      uint32_t        checksum;
 +      uint32_t        config_size;
 +      uint32_t        config_id;
 +      uint32_t        generation;
 +      uint32_t        dummy_1[2];
 +      uint8_t         total_disks;
 +      uint8_t         total_volumes;
 +      uint8_t         dummy_2[2];
 +      uint32_t        filler_0[39];
 +      struct {
 +              uint8_t         serial[16];
 +              uint32_t        sectors;
 +              uint32_t        id;
 +              uint32_t        flags;
 +#define INTEL_F_SPARE                 0x01
 +#define INTEL_F_ASSIGNED              0x02
 +#define INTEL_F_DOWN                  0x04
 +#define INTEL_F_ONLINE                        0x08
 +              uint32_t        filler[5];
 +      } __packed disk[1];
 +      uint32_t        filler_1[62];
 +} __packed;
 +
 +struct intel_raid_mapping {
 +      uint8_t         name[16];
 +      uint64_t        total_sectors __packed;
 +      uint32_t        state;
 +      uint32_t        reserved;
 +      uint32_t        filler_0[20];
 +      uint32_t        offset;
 +      uint32_t        disk_sectors;
 +      uint32_t        stripe_count;
 +      uint16_t        stripe_sectors;
 +      uint8_t         status;
 +#define INTEL_S_READY         0x00
 +#define INTEL_S_DISABLED      0x01
 +#define INTEL_S_DEGRADED      0x02
 +#define INTEL_S_FAILURE               0x03
 +
 +      uint8_t         type;
 +#define INTEL_T_RAID0         0x00
 +#define INTEL_T_RAID1         0x01
 +#define INTEL_T_RAID5         0x05
 +
 +      uint8_t         total_disks;
 +      uint8_t         magic[3];
 +      uint32_t        filler_1[7];
 +      uint32_t        disk_idx[1];
 +} __packed;
 +
  #endif /* _DEV_PCI_PCIIDE_PROMISE_RAID_H_ */
 Index: sys/dev/ata/ata_raidvar.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ata/ata_raidvar.h,v
 retrieving revision 1.7
 diff -b -u -p -r1.7 ata_raidvar.h
 --- sys/dev/ata/ata_raidvar.h  5 Sep 2008 12:37:13 -0000       1.7
 +++ sys/dev/ata/ata_raidvar.h  10 Sep 2008 15:11:42 -0000
 @@ -53,7 +53,8 @@
  #define       ATA_RAID_TYPE_VIA       2
  #define       ATA_RAID_TYPE_NVIDIA    3
  #define ATA_RAID_TYPE_JMICRON 4
 -#define       ATA_RAID_TYPE_MAX       4
 +#define       ATA_RAID_TYPE_INTEL     5
 +#define       ATA_RAID_TYPE_MAX       5
  
  /*
   * Max # of disks supported by a single array.  This is limited by
 @@ -138,4 +139,7 @@ int        ata_raid_read_config_nvidia(struct w
  /* JMicron RAID support */
  int   ata_raid_read_config_jmicron(struct wd_softc *);
  
 +/* Intel MatrixRAID support */
 +int   ata_raid_read_config_intel(struct wd_softc *);
 +
  #endif /* _DEV_ATA_ATA_RAIDVAR_H_ */
 Index: sys/dev/ata/files.ata
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ata/files.ata,v
 retrieving revision 1.18
 diff -b -u -p -r1.18 files.ata
 --- sys/dev/ata/files.ata      5 Sep 2008 12:37:13 -0000       1.18
 +++ sys/dev/ata/files.ata      10 Sep 2008 15:11:42 -0000
 @@ -23,6 +23,7 @@ file dev/ata/ata_raid_adaptec.c      ataraid
  file  dev/ata/ata_raid_nvidia.c       ataraid
  file  dev/ata/ata_raid_via.c          ataraid
  file  dev/ata/ata_raid_jmicron.c      ataraid
 +file  dev/ata/ata_raid_intel.c        ataraid
  
  attach        ld at ataraid with ld_ataraid
  file  dev/ata/ld_ataraid.c            ld_ataraid
 


Home | Main Index | Thread Index | Old Index