SMCIOC_READ_ELEMENT_DEVIDS

This IOCTL command issues the SCSI Read Element Status command with the device ID (DVCID) bit set and returns the element descriptors for the data transfer elements. The element_address field specifies the starting address of the first data transfer element. The number_elements field specifies the number of elements to return. The application must allocate a return buffer large enough for the number_elements specified in the input structure.

The input data structure is
  struct read_element_devids
  {
     ushort element_address;               /* starting element address */
     ushort number_elements;               /* number of elements */
     struct element_devid *drive_devid;    /* data transfer element pages */
  };
The output data structure is
  struct element_devid
  {
     ushort address;              /* element address */
     uint   :4,                   /* reserved */
            access:1,             /* robot access allowed */
            except:1,             /* abnormal element state */
            :1,                   /* reserved */
            full:1;               /* element contains medium */
     uchar  resvd1;               /* reserved */
     uchar  asc;                  /* additional sense code */
     uchar  ascq;                 /* additional sense code qualifier */
     uint   notbus:1,             /* element not on same bus as robot */
            :1,                   /* reserved */
            idvalid:1,            /* element address valid */
            luvalid:1,            /* logical unit valid */
            :1,                   /* reserved */
            lun:3;                /* logical unit number */
     uchar  scsi;                 /* scsi bus address */
     uchar  resvd2;               /* reserved */
     uint   svalid:1,             /* element address valid */
            invert:1,             /* medium inverted */
            :6;                   /* reserved */
     ushort source;               /* source storage element address */
     uint   :4,                   /* reserved */
            code_set:4;           /* code set X'2' is all ASCII identifier */
     uint   :4,                   /* reserved */
            ident_type:4;         /* identifier type */
     uchar  resvd3;               /* reserved */
     uchar  ident_len;            /* identifier length */
     uchar  identifier[36];       /* device identification */
  };
An example of the SMCIOC_READ_ELEMENT_DEVIDS command is
  #include <sys/Atape.h>

 int smcioc_read_element_devids()
  {
  int i;
  struct element_devid *elem_devid, *elemp;
  struct read_element_devids devids;
  struct element_info element_info;

  if (ioctl(fd, SMCIOC_ELEMENT_INFO, &element_info))
    return errno;

  if (element_info.drives)
    {
    elem_devid = malloc(element_info.drives * sizeof(struct element_devid));
    if (elem_devid == NULL)
      {
      errno = ENOMEM;
      return errno;
      }
     bzero((caddr_t)elem_devid,element_info.drives * sizeof(struct element_devid));
     devids.drive_devid = elem_devid;
     devids.element_address = element_info.drive_addr;
     devids.number_elements = element_info.drives;

     printf("Reading element device ids...\n");

     if (ioctl (fd, SMCIOC_READ_ELEMENT_DEVIDS, &devids))
       {
       free(elem_devid);
       return errno;
       }

     elemp = elem_devid;
     for (i = 0; i < element_info.drives; i++, elemp++)
      {
      printf("\nDrive Address %d\n",elemp->address);
      if (elemp->except)
        printf("  Drive State .................... Abnormal\n");
      else
        printf("  Drive State .................... Normal\n");
      if (elemp->asc == 0x81 && elemp->ascq ==0x00)
        printf("  ASC/ASCQ ....................... %02X%02X (Drive Present)\n",
           elemp->asc,elemp->ascq);
      else if (elemp->asc == 0x82 && elemp->ascq ==0x00)
        printf("  ASC/ASCQ ....................... %02X%02X (Drive Not Present)\n",
           elemp->asc,elemp->ascq);
      else
        printf("  ASC/ASCQ ....................... %02X%02X\n",
           elemp->asc,elemp->ascq);
      if (elemp->full)
        printf("  Media Present .................. Yes\n");
      else
        printf("  Media Present .................. No\n");
      if (elemp->access)
        printf("  Robot Access Allowed ........... Yes\n");
      else
        printf("  Robot Access Allowed ........... No\n");
      if (elemp->svalid)
      printf("  Source Element Address ......... %d\n",elemp->source);
      else
        printf("  Source Element Address Valid ... No\n");
      if (elemp->invert)
        printf("  Media Inverted ................. Yes\n");
      else
        printf("  Media Inverted ................. No\n");
      if (elemp->notbus)
        printf("  Same Bus as Medium Changer ..... No\n");
      else
        printf("  Same Bus as Medium Changer ..... Yes\n");
      if (elemp->idvalid)
        printf("  SCSI Bus Address ............... %d\n",elemp->scsi);
      else
        printf("  SCSI Bus Address Valid ......... No\n");
      if (elemp->luvalid)
        printf("  Logical Unit Number ............ %d\n",elemp->lun);
      else
        printf("  Logical Unit Number Valid ...... No\n");
      printf("  Device ID ...................... %0.36s\n", elemp->identifier);
      }
     }
    else
     {
     printf("\nNo drives found in element information\n");
     }

  free(elem_devid);
  return errno;
  }