[comp.sys.hp] scsi_info.c

ianhogg@cs.umn.edu (Ian J. Hogg) (02/12/91)

Here it is, the wonderful scsi_info program that creates disktab entries for you
It has only been tested on Imprimis disk drives.  I don't know how well it works
for other vendors' drives.  I believe that it core dumped when tryin to get info
from whatever HP's first 300 MB scsi drive was.  Anyways use it to your hearts
content, and I hope it helps others as much as it did me.  

If anyone has mods or enhancements let me send me mail.  If someone else wants
to be a sort of official keeper of this program, let me know.  I would but since
I switched jobs I don't have access to any HP's.

======================       cut here =========================================

/*****************************************************************************
This program was written by Matt Endres, Imprimis Technology.

usage:	scsi_info special name mbytes

where:
	special is the raw device file for the scsi device for which the
			information is to be displayed

	name 	is a name to be used for the disktab entry

	mbytes	is the number of MBytes to be used as swap space on the device

Example:
		To create a disktab entry for a SABRE V disk drive whose device file
		is located in the device directory /dev/rdsk/1s0 with 50 Mbytes of
		swap, the command line is:

			scsi_info /dev/rdsk/1s0 SABRE_V 50
****************************************************************************/

#include <sys/types.h>
#include <sys/scsi.h>
#include <sys/ioctl.h>
#include <fcntl.h>
struct inquiry i_data;
struct capacity c_data;
char scsi_vendor[9];
char scsi_product[17];
int num_cylinders;
int num_heads;
int num_usable_sectors;
int alt_sect,tracks_zone,sectors_track;
int swap;
int scsi_dev;
char *entry_name;
unsigned char geometry_data[100];
unsigned char dad_form_data[100];
char *scsi_device_name;


main(argc,argv)
int argc;
char *argv[];
{
  	  
  if (argc < 4)
  {
    printf("Usage: scsi_info special disktab_name swap_size\n");
    exit(1);
  }
  scsi_device_name=argv[1];
  scsi_dev=open(scsi_device_name,O_RDONLY);
  if (scsi_dev == -1)
  {
    printf("Unable to open %s\n",argv[1]);
    exit(1);
  }
  sscanf(argv[3],"%d",&swap);
  entry_name=argv[2];
  print_ids();
  print_geometry();
  print_disktab_entry();
  close(scsi_dev);
}

/********************************************************************
print_ids
	This procedure will issue an inquiry command to the opened scsi
	device (raw device must be used) and print out the returned
	information.  This information is not needed for the disktab
	file.
********************************************************************/
print_ids()
{
  int x;

  ioctl(scsi_dev,SIOC_INQUIRY,&i_data);
  for(x=0;x<8;x++) scsi_vendor[x]=i_data.vendor_id[x];
  scsi_vendor[8]='\0';
  for(x=0;x<16;x++) scsi_product[x]=i_data.product_id[x];
  scsi_product[16]='\0';
  printf("\nInformation for device %s\n",scsi_device_name);
  printf("\nVendor                     = %s\n",scsi_vendor);
  printf("Product type               = %s\n",scsi_product);
}

/*****************************************************************
print_geometry:
	This procedure will issue a mode sense geometry command, a mode
	sense format command, and a capacity command to the scsi device.
	The returned data will be printed out, this data will be used to
	computer the disktab entry.
*******************************************************************/
print_geometry()
{
  int offset;

  ioctl(scsi_dev,SIOC_MODE_SENSE_GEOMETRY,geometry_data);
  ioctl(scsi_dev,SIOC_MODE_SENSE_FORMAT,dad_form_data);
  ioctl(scsi_dev,SIOC_CAPACITY,&c_data);
  for(offset=0;geometry_data[offset] != 0x84;offset++);
  num_cylinders=(geometry_data[offset + 2]<<12)+(geometry_data[offset + 3]<<8)+geometry_data[offset + 4];
  num_heads=geometry_data[offset + 5];
  alt_sect=(dad_form_data[16]<<8) + dad_form_data[17];
  tracks_zone=(dad_form_data[14]<<8) + dad_form_data[15];
  sectors_track=(dad_form_data[22]<<8) + dad_form_data[23];
  num_usable_sectors=(sectors_track -(1 / (tracks_zone * alt_sect)))/(1024 / c_data.blksz);
  printf("Number of total blocks     = %d\n",c_data.lba);
  printf("Block Size                 = %d\n",c_data.blksz);
  printf("Number of Cylinders        = %d\n",num_cylinders);
  printf("Number of Heads            = %d\n",num_heads);
  printf("Number of 1K Sectors/Track = %d\n",num_usable_sectors);
}

/********************************************************************
print_disktab_entry:
	This procedure will calculate the disktab entry and print it.
	The entry is calculated in the following manner:

		The number of cylinders is equal to the total number of cylinders
		minus the number of cylinders used for swap space.

		The number of usable sectors is the number of 1 Kbyte sectors
		per track.  This may cause some sectors to be unused if the
		number of sectors times the block size is not divisible by 1024.

		The s0 entry in the disktab file is the number of usable
		sectors times the number of tracks (heads) times the number
		of cylinders which are not used for swap space.

		The numbers printed out may not be the same as listed in the
		disk drive manuals because scsi devices reserve some sectors
		and some cylinders for alternates because of flaws on the disk.
*********************************************************************/
print_disktab_entry()
{
  long file_cylinders;
  double swap_space,file_space;
	
  if ((swap * 1024) > (c_data.lba / (1024 / c_data.blksz)))
  {
    printf("\n\nSwap size requested is larger than total disk size\n");
    printf("Unable to create disktab endtry\n");
    exit(2);
  }
  file_cylinders=num_cylinders-((swap * 1024)/(num_heads*num_usable_sectors)+1);
  if (swap==0)
    swap_space=0;
  else
    swap_space=((num_cylinders - file_cylinders) * num_heads * num_usable_sectors);
  file_space=(file_cylinders * num_heads * num_usable_sectors);
  file_space=file_space / 1024;
  swap_space=swap_space / 1024;
  printf("\nFile System Parameters:\n");
  printf("    %1.3f Mbyte(s) swap\n",swap_space);
  printf("    %1.3f Mbyte(s) usable file space\n",file_space);
  printf("\n\n\n/etc/disktab entry\n");
  printf("\n%s:\\\n",entry_name);
  printf("    :%d Mbyte(s) Swap:ns#%d:nt#%d:nc#%d:\\\n",swap,
	 num_usable_sectors,num_heads,file_cylinders);
  printf("    :s0#%d:b0#8192:f0#1024:\\\n",num_usable_sectors *
	 num_heads * file_cylinders);
  printf("    :se#%d:rm#3600:\n",c_data.blksz);
}
-- 
===============================================================================
Ian Hogg						ianhogg@cs.umn.edu
                                                        (612) 225-1401