#define VERSION "V2.2 05-Nov-97"

/* mtinfo.c 
**
** Determine SCSI tape driver information on Solaris 2.4 system
**
** based on original posting by
**	tl@hrz-serv7.hrz.uni-kassel.de (Thomas Landgraf HRZ)
**
** extended by Alan McRae, Metadigm Ltd <alan@metadigm.co.uk>
**
** fixed by Sun to work under Solaris 2.4
** ST_NOPARITY removed for Solaris 2.5 APM
**
** include sys/scsi/scsi_types.h for Solaris 2.6 - APM 05-Nov 97
**
** Usage: mtinfo /dev/rmt/0
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>
#include <sys/mkdev.h>
#include <sys/ddi.h>

/* just to get it to compile */
#define kcondvar_t char
#include <sys/scsi/scsi_types.h>
#include <sys/scsi/targets/stdef.h>

typedef struct flaginfo
	{
	char *name;
	int bits;
	} FLAGINFO;

FLAGINFO fi[] =
	{
	{"ST_VARIABLE",ST_VARIABLE},
	{"ST_REEL",ST_REEL},
	{"ST_BSF",ST_BSF},
	{"ST_BSR",ST_BSR},
	{"ST_LONG_ERASE",ST_LONG_ERASE},
	{"ST_AUTODEN_OVERRIDE",ST_AUTODEN_OVERRIDE},
	{"ST_NOBUF",ST_NOBUF},
#ifdef solaris24
	{"ST_NOPARITY",ST_NOPARITY},
#endif
	{"ST_KNOWS_EOD",ST_KNOWS_EOD},
	{"ST_QIC",ST_QIC},
	{"ST_UNLOADABLE",ST_UNLOADABLE},
	{"ST_SOFT_ERROR_REPORTING",ST_SOFT_ERROR_REPORTING},
	{"ST_LONG_TIMEOUTS",ST_LONG_TIMEOUTS},
	{"ST_DYNAMIC",ST_DYNAMIC},
	{"ST_BUFFERED_WRITES",ST_BUFFERED_WRITES},
	{"ST_NO_RECSIZE_LIMIT",ST_NO_RECSIZE_LIMIT},
	{"ST_MODE_SEL_COMP",ST_MODE_SEL_COMP},
	{"ST_NO_RESERVE_RELEASE",ST_NO_RESERVE_RELEASE},
	{"ST_READ_IGNORE_ILI",ST_READ_IGNORE_ILI},
	{"ST_READ_IGNORE_EOFS",ST_READ_IGNORE_EOFS},
	{"ST_SHORT_FILEMARKS",ST_SHORT_FILEMARKS}
	};
#define NFI (sizeof(fi)/sizeof(FLAGINFO))

/* just to get it to compile */
#define XTS_BITS 0
struct mt_tape_info ti[] = MT_TAPE_INFO;

char devchar[] = { 0,'l','m','h','c','u'};
char name[64],devname[64];

main(argc,argv)
int argc;
char *argv[];
{
  int fd;
  struct mtget mtg;
  struct mtdrivetype mdt;
  struct mtdrivetype_request mdt_req;
  struct stat s;
  int i,nmin,nmaj,nden,density;

  printf("mtinfo %s\n",VERSION);
  
  if (argc != 2)
	{
	fprintf(stderr,"Usage: %s <device>\n",argv[0]);
	fprintf(stderr,"e.g.   %s /dev/rmt/0\n",argv[0]);
	exit(7);
	}

  strcpy(devname,argv[1]);
  fd=open(devname,O_RDONLY);
 
 if(fd<0) 
    { 
      fprintf(stderr,"Cannot open %s\n",devname); 
      perror("open device");
      exit(-1);
    }
  if (ioctl(fd, MTIOCGET, &mtg) != 0) {
    fprintf(stderr,"Cannot extract tape %s status\n", devname);
    exit(-1); }
  printf("Type                : 0x%x",mtg.mt_type);
  for (i=0;;i++)
	{
	if (ti[i].t_type == 0) break;
	if (mtg.mt_type == ti[i].t_type)
		{
		printf("\t %s",ti[i].t_name);
		break;
		}
	}
  printf("\n");
  printf("Status              : %d\n",mtg.mt_dsreg);
  printf("Error               : %d\n",mtg.mt_erreg);
  printf("Residual Count      : %ld\n",mtg.mt_resid);
  printf("FileNo curr. Pos.   : %ld\n",mtg.mt_fileno);
  printf("BlokNo curr. Pos.   : %ld\n",mtg.mt_blkno);
  printf("Flags               : 0x%x\n",mtg.mt_flags);
  printf("Opt. Blocking Factor: %d\n",mtg.mt_bf);
  mdt_req.size = sizeof(struct mtdrivetype);
  mdt_req.mtdtp = & mdt;
  if (ioctl(fd, MTIOCGETDRIVETYPE, &mdt_req) != 0) {
	fprintf(stderr,"Cannot extract tape %s info\n", devname);
	exit(-1); }
  
  printf("Name               :%s\n",mdt.name);
  printf("VID                :%s\n",mdt.vid);
  printf("Type               :0x%x\n",mdt.type);
  printf("BlockSize          :%u\n",mdt.bsize);
  printf("Options            :0x%x\n",mdt.options);
  for (i=0; i<NFI; i++)
	{
	if (fi[i].bits & mdt.options)
		printf("\t%16s\t(0x%x)\n",fi[i].name,fi[i].bits);
	}
  printf("Max read Retries   :%u\n",mdt.max_rretries);
  printf("Max. write Retries :%u\n",mdt.max_wretries);
  printf("Densities          :0x%2.2x,0x%2.2x,0x%2.2x,0x%2.2x\n",mdt.densities[0],mdt.densities[1],
	 mdt.densities[2],mdt.densities[3]);
  density =  (mdt.default_density >> 3) & 3;
  printf("Default density    :%u (%d)\n",mdt.default_density, density);
  printf("Speeds             :%u,%u,%u,%u\n",mdt.speeds[0],mdt.speeds[1],
	 mdt.speeds[2],mdt.speeds[3]);
  
  close(fd);

  printf("\n/kernel/drv/st.conf entry:\n\n");
  printf("tape-config-list =\n");
  printf("\t\"%s\",\"%s\",\"tape-data\";\n",
	mdt.vid,
	mdt.name
	);
  printf("\ttape-data = %d,0x%x,%d,0x%x,%d,0x%2.2x,0x%2.2x,0x%2.2x,0x%2.2x,%d;\n",
	1,
	mdt.type,
	mdt.bsize,
	mdt.options,
	MT_NDENSITIES,
	mdt.densities[0],
	mdt.densities[1],
	mdt.densities[2],
	mdt.densities[3],
	density
	);

  printf("\n");
  printf("Density bytes used by device entry:\n\n");
  for (i=0; i<6; i++)
	{
	sprintf(name,"%s%c",devname,devchar[i]);
	stat(name,&s);
	nmaj = major(s.st_rdev);
	nmin = minor(s.st_rdev);
	nden = (nmin & MT_DENSITY_MASK) >> 3;
	printf("%-12s major=%3d minor=%3d density=%1d density byte=0x%2.2x\n",name,nmaj,nmin,nden,mdt.densities[nden]);
	}

}
